Detalhes do pacote

@effect/language-service

Effect-TS169.8kMIT0.23.0

A Language-Service Plugin to Refactor and Diagnostic effect-ts projects

typescript, algebraic-data-types, functional-programming

readme (leia-me)

language-service

This package implements a TypeScript language service plugin that allows additional refactors and diagnostics with your VSCode editor (or any editor that supports TypeScript's LSP).

Installation

  1. npm install @effect/language-service --save-dev in your project
  2. inside your tsconfig.json, you should add the plugin configuration as follows:

    {
    "compilerOptions": {
     "plugins": [
       // ... other LSPs (if any) and as last
       {
         "name": "@effect/language-service"
       }
     ]
    }
    }
  3. Ensure that you have installed TypeScript locally in your project and set your editor to use your workspace TypeScript version.

    • In VSCode you can do this by pressing "F1" and typing "TypeScript: Select TypeScript version". Then select "Use workspace version". If that option does not appear, TypeScript is not installed locally in your node_modules.
    • In JetBrains you may have to disable the Vue language service, and chose the workspace version of TypeScript in the settings from the dropdown.
    • In NVim with nvim-vtsls you should refer to how to enable TypeScript plugins in vstls

And you're done! You'll now be able to use a set of refactor and diagnostics that targets Effect!

Provided functionalities

Quickinfo

  • Show the extended type of the current Effect
  • Hovering yield\* of Effect.gen will show the Effect type parameters
  • Hovering a variable assignment of a type Layer, will show info on how each service got involve
  • Hovering a layer, will attempt to produce a graph

Diagnostics

  • Better error readability when you're missing errors or service types in your Effect definitions
  • Floating Effects that are not yielded or run
  • Wrong usage of yield inside Effect.gen
  • Multiple versions of Effect in your project
  • Warn on leaking requirements in Effect services
  • Unnecessary usages of Effect.gen or pipe()
  • Warn when importing from a barrel file instead of from the module directly

Completions

  • Autocomplete 'Self' in Effect.Service, Context.Tag, Schema.TaggedClass, Schema.TaggedRequest and family
  • Autocomplete Effect.gen with function*(){}
  • Autocomplete Effect.fn with the span name given by the exported member
  • Allow to configure packages to be imported with namespace style import * as Effect from "effect"
  • Effect comment directives

Refactors

  • Transform an async function definition, into an Effect by using Effect.gen.
  • Transform an async function definition, into an Effect by using Effect.gen, and generating a tagged error for each promise call.
  • Transform a function returning an Effect.gen into a Effect.fn
  • Function calls to pipe: Transform a set of function calls to a pipe() call.
  • Pipe to datafirst: Transform a pipe() call into a series of datafirst function calls (where available).
  • Toggle return type signature: With a single refactor, adds or removes type annotations from the definition.
  • Remove unnecessary Effect.gen definitions that contains a single yield statement.
  • Wrap an Effect expression with Effect.gen

Miscellaneous

  • "Go to definition" for RpcClient will resolve to the Rpc definition

Options

Few options can be provided alongside the initialization of the Language Service Plugin.

{
  "compilerOptions": {
    "plugins": [
      {
        "name": "@effect/language-service",
        "diagnostics": true, // controls Effect diagnostics (default: true)
        "diagnosticSeverity": { // allows to change per-rule default severity of the diagnostic in the whole project
          "floatingEffect": "warning" // example for a rule, allowed values are off,error,warning,message,suggestion
        },
        "quickinfo": true, // controls quickinfo over Effect (default: true)
        "completions": true, // controls Effect completions (default: true)
        "goto": true, // controls Effect goto references (default: true)
        "allowedDuplicatedPackages": [], // list of package names that has effect in peer dependencies and are allowed to be duplicated (default: [])
        "barrelImportPackages": [], // package names that should be preferred as imported from the top level barrel file (default: [])
        "namespaceImportPackages": [] // package names that should be preferred as imported with namespace imports e.g. ["effect"] (default: [])
      }
    ]
  }
}

Why diagnostics does not appear at compile time?

TypeScript LSP are loaded only while editing your files. That means that if you run tsc in your project, the plugin won't be loaded and you'll miss out on the Effect diagnostics.

HOWEVER, if you use ts-patch you can enable the transform as well to get the diagnostics also at compile time. Your tsconfig.json should look like this:

{
  "compilerOptions": {
    "plugins": [
      {
        "name": "@effect/language-service",
        "transform": "@effect/language-service/transform" // enables diagnostics at compile time when using ts-patch
      }
    ]
  }
}

To get diagnostics you need to install ts-patch which will make it possible to run tspc.

Running tspc in your project will now also run the plugin and give you the diagnostics at compile time. Effect diagnostics will be shown only after standard TypeScript diagnostics has been satisfied.

$ npx tspc
index.ts:3:1 - error TS3: Effect must be yielded or assigned to a variable.

3 Effect.succeed(1)
  ~~~~~~~~~~~~~~~~~

Found 1 error in index.ts:3

Configuring diagnostics

You can either disable or change the severity of specific diagnostics by using comments in your code.

// @effect-diagnostics effect/floatingEffect:off
Effect.succeed(1); // This will not be reported as a floating effect

// @effect-diagnostics effect/floatingEffect:error
Effect.succeed(1); // This will be reported as a floating effect

or you can set the severity for the entire project in the global plugin configuration

{
  "compilerOptions": {
    "plugins": [
      {
        // ...
        "diagnosticSeverity": { // allows to change per-rule default severity of the diagnostic in the whole project
          "floatingEffect": "warning" // example for a rule, allowed values are off,error,warning,message,suggestion
        },
        // ...
      }
    ]
  }
}

Known gotchas

Svelte VSCode extension and SvelteKit

The Svelte LSP does not properly compose with other LSPs when using SvelteKit. So the Effect LSP should be loaded as last entry to ensure proper composition.

If you did not installed the Svelte LSP into your local project but instead through the Svelte VSCode extension, we recommend instead to install locally and add it as first entry. That way it won't be applied by the VSCode extension.

Your tsconfig should look like this:

{
  "compilerOptions": {
    "plugins": [
      { "name": "typescript-svelte-plugin" },
      { "name": "@effect/language-service" }
    ]
  }
}

changelog (log de mudanças)

@effect/language-service

0.23.0

Minor Changes

0.22.3

Patch Changes

0.22.2

Patch Changes

0.22.1

Patch Changes

0.22.0

Minor Changes

Patch Changes

0.21.8

Patch Changes

0.21.7

Patch Changes

0.21.6

Patch Changes

0.21.5

Patch Changes

0.21.4

Patch Changes

0.21.3

Patch Changes

0.21.2

Patch Changes

0.21.1

Patch Changes

0.21.0

Minor Changes

Patch Changes

0.20.1

Patch Changes

0.20.0

Minor Changes

Patch Changes

0.19.0

Minor Changes

0.18.1

Patch Changes

  • #179 a170bfc Thanks @mattiamanzati! - Handle unnecessary Effect.gen even when yielded expression is not returned

    export const shouldRaiseForSingle = Effect.gen(function* () {
      yield* Effect.succeed(42);
    });
    // ^- this will become Effect.asVoid(Effect.succeed(42))
    
    export const shouldRaiseForSingleReturnVoid = Effect.gen(function* () {
      yield* Effect.void;
    });
    // ^- this will become Effect.void

0.18.0

Minor Changes

Patch Changes

0.17.1

Patch Changes

0.17.0

Minor Changes

0.16.7

Patch Changes

0.16.6

Patch Changes

0.16.5

Patch Changes

0.16.4

Patch Changes

0.16.3

Patch Changes

0.16.2

Patch Changes

0.16.1

Patch Changes

0.16.0

Minor Changes

0.15.1

Patch Changes

0.15.0

Minor Changes

0.14.0

Minor Changes

0.13.0

Minor Changes

Patch Changes

0.12.2

Patch Changes

0.12.1

Patch Changes

0.12.0

Minor Changes

0.11.0

Minor Changes

0.10.2

Patch Changes

0.10.1

Patch Changes

0.10.0

Minor Changes

0.9.2

Patch Changes

  • #109 c325568 Thanks @mattiamanzati! - Add support for completions for Data.TaggedClass and Data.TaggedError

  • #106 63cc227 Thanks @wmaurer! - Fixed a bug where certain refactors were not available when the cursor was position at the start of a node

0.9.1

Patch Changes

0.9.0

Minor Changes

0.8.1

Patch Changes

0.8.0

Minor Changes

Patch Changes

0.7.1

Patch Changes

0.7.0

Minor Changes

  • #88 c3944ce Thanks @wmaurer! - Add refactor remove-unnecessary-effect-gen. This removes unnecessary Effect.gen calls by simplifying generator functions that only wrap a single yield* statement returning an Effect. This refactor replaces the Effect.gen wrapper with the inner Effect directly, making the code more concise and readable.

0.6.2

Patch Changes

0.6.1

Patch Changes

0.6.0

Minor Changes

Patch Changes

0.5.1

Patch Changes

  • #73 3c9c1ba Thanks @mattiamanzati! - Avoid to bail-out type generation when imports are missing, show instead partial signature

0.5.0

Minor Changes

  • #71 8d309ab Thanks @mattiamanzati! - Detect unnecessary usages of Effect.gen

  • #68 79ce0b1 Thanks @mattiamanzati! - Adds support for quickinfo for effect

    They can be disabled by the LSP option "quickinfo": false.

    Once you hover a truncated type, you'll see additional information about the Effect type arguments like Success, Failure and Requirements.

Patch Changes

0.4.0

Minor Changes

Patch Changes

0.3.2

Patch Changes

0.3.1

Patch Changes

0.3.0

Minor Changes

  • #54 19e5a77 Thanks @mattiamanzati! - - Update internal version of effect from 2.x beta to 3.12.5

    • Remove adapter from gen refactors
  • #56 5b2b27c Thanks @mattiamanzati! - Add support for Effect diagnostics

    With this release of the language service plugin, we aim to improve the overall Effect experience by providing additional diagnostics that tries to fix misleading or hard to read TypeScript errors.

    All of the diagnostics provided by the language service are available only in editor-mode, that means that they won't show up when using tsc.

    Diagnostics are enabled by default, but you can opt-out of them by changing the language service configuration and provide diagnostics: false.

    {
      "plugins": [
        {
          "name": "@effect/language-service",
          "diagnostics": false
        }
      ]
    }

    Please report any false positive or missing diagnostic you encounter over the Github repository.

    Missing Errors and Services in Effects

    Additionally to the standard TypeScript error that may be cryptic at first:

    Argument of type 'Effect<number, never, ServiceB | ServiceA | ServiceC>' is not assignable to parameter of type 'Effect<number, never, ServiceB | ServiceA>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
      Type 'ServiceB | ServiceA | ServiceC' is not assignable to type 'ServiceB | ServiceA'.
        Type 'ServiceC' is not assignable to type 'ServiceB | ServiceA'.
          Type 'ServiceC' is not assignable to type 'ServiceA'.
            Types of property 'a' are incompatible.
              Type '3' is not assignable to type '1'.ts(2379)

    you'll now receive an additional error:

    Missing 'ServiceC' in the expected Effect context.

    Floating Effect

    In some situation you may not receive any compile error at all, but that's because you may have forgot to yield your effects inside gen!

    Floating Effects that are not assigned to a variable will be reported into the Effect diagnostics.

    Effect.runPromise(
      Effect.gen(function* () {
        Effect.sync(() => console.log("Hello!"));
        // ^- Effect must be yielded or assigned to a variable.
      })
    );

    Used yield instead of yield*

    Similarly, yield instead of yield* won't result in a type error by itself, but is not the intended usage.

    This yield will be reported in the effect diagnostics.

    Effect.runPromise(
      Effect.gen(function* () {
        yield Effect.sync(() => console.log("Hello!"));
        // ^- When yielding Effects inside Effect.gen, you should use yield* instead of yield.
      })
    );

0.2.0

Minor Changes

0.1.0

Minor Changes

  • #48 9bb0011 Thanks @wmaurer! - Improve Effect imports to work with current effect npm package

  • #48 9bb0011 Thanks @wmaurer! - Modernise build setup. Fix asyncWaitToGen problem for TS5. Refactor asyncWaitToGen to work with current Effect API. Add config option preferredEffectGenAdapterName.

0.0.21

Patch Changes

0.0.20

Patch Changes

0.0.19

Patch Changes

0.0.18

Patch Changes

0.0.17

Patch Changes

0.0.16

Patch Changes

0.0.15

Patch Changes

0.0.14

Patch Changes

0.0.13

Patch Changes

0.0.12

Patch Changes

0.0.11

Patch Changes

0.0.10

Patch Changes

0.0.9

Patch Changes

0.0.8

Patch Changes

0.0.7

Patch Changes

0.0.6

Patch Changes

0.0.5

Patch Changes

0.0.4

Patch Changes

0.0.3

Patch Changes

0.0.2

Patch Changes

0.0.1

Patch Changes

  • #2 8915f80 Thanks @mattiamanzati! - Fixed type annotation removal in both toggle return type and toggle type annotation