effect-oxlint

raw JSON →
0.2.0 verified Fri May 01 auth: no javascript

Effect-first library for writing oxlint custom lint rules. Current stable version: 0.2.0. Release cadence: irregular, with initial releases in early 2025. Key differentiators: provides typed errors, composable visitors, Option-safe AST matching, and Ref-based state without mutable variables, wrapping @oxlint/plugins in Effect idioms. Requires effect@^4.0.0-beta.57 as a peer dependency. Ideal for Effect ecosystem developers who want to write lint rules with Effect's effectful computation model.

error Cannot find module 'effect-oxlint' or its corresponding type declarations.
cause Missing or incompatible peer dependency 'effect'.
fix
Install effect@^4.0.0-beta.57 alongside effect-oxlint.
error TypeError: (intermediate value) is not iterable
cause Using yield* in a non-generator context or missing Effect.run*.
fix
Ensure create is a generator function and wrap in Effect.runSync or similar.
error Error: Cannot find module 'effect-oxlint/testing'
cause Importing Testing from wrong path; Testing is a subpath export.
fix
import { Testing } from 'effect-oxlint/testing'
breaking In v0.2.0, SourceCode.getText was split into getText() (whole file) and getNodeText(node) (node-specific). Old overload with Option<Node> removed.
fix Use SourceCode.getText() for full file and SourceCode.getNodeText(node) for specific nodes.
breaking Requires effect@^4.0.0-beta.57; incompatible with older effect versions.
fix Update effect to ^4.0.0-beta.57.
deprecated The previous Option<Node> overload of SourceCode.getText is removed; update to split functions.
fix Use getNodeText for node-specific text extraction.
breaking Peer dependency effect must be at least 4.0.0-beta.57; earlier betas fail.
fix npm install effect@^4.0.0-beta.57
npm install effect-oxlint
yarn add effect-oxlint
pnpm add effect-oxlint

Defines a custom oxlint rule using Effect idioms, then assembles it into a plugin.

import * as Effect from 'effect/Effect';
import * as Option from 'effect/Option';
import { AST, Diagnostic, Rule, RuleContext } from 'effect-oxlint';

const noJsonParse = Rule.define({
  name: 'no-json-parse',
  meta: Rule.meta({
    type: 'suggestion',
    description: 'Use Schema for JSON decoding instead of JSON.parse'
  }),
  create: function* () {
    const ctx = yield* RuleContext;
    return {
      MemberExpression: (node) =>
        Option.match(
          AST.matchMember(node, 'JSON', ['parse', 'stringify']),
          {
            onNone: () => Effect.void,
            onSome: (matched) =>
              ctx.report(
                Diagnostic.make({
                  node: matched,
                  message: 'Use Schema for JSON'
                })
              )
          }
        )
    };
  }
});

export default Plugin.define({
  name: 'my-effect-rules',
  rules: {
    'no-json-parse': noJsonParse
  }
});