oxlint-plugin-effect 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/README.md +80 -38
  2. package/dist/presets/index.d.ts +3 -9
  3. package/dist/presets/index.js +3 -17
  4. package/dist/presets/recommended.d.ts +18 -0
  5. package/dist/presets/recommended.js +18 -0
  6. package/dist/rules/index.d.ts +5 -61
  7. package/dist/rules/index.js +6 -118
  8. package/dist/rules/no-async-function.js +8 -13
  9. package/dist/rules/no-dynamic-imports.js +89 -60
  10. package/dist/rules/no-globals.js +164 -127
  11. package/dist/rules/no-new-error.js +26 -13
  12. package/dist/rules/no-new-promise.js +22 -21
  13. package/dist/rules/no-node-builtin-import.js +98 -41
  14. package/dist/rules/no-test-lifecycle-hooks.d.ts +6 -0
  15. package/dist/rules/no-test-lifecycle-hooks.js +37 -0
  16. package/dist/rules/no-throw-statement.js +4 -16
  17. package/dist/rules/no-try-catch.js +4 -16
  18. package/package.json +2 -2
  19. package/dist/presets/core.d.ts +0 -50
  20. package/dist/presets/core.js +0 -50
  21. package/dist/presets/effect-native.d.ts +0 -29
  22. package/dist/presets/effect-native.js +0 -29
  23. package/dist/presets/full.d.ts +0 -68
  24. package/dist/presets/full.js +0 -68
  25. package/dist/presets/functional.d.ts +0 -22
  26. package/dist/presets/functional.js +0 -22
  27. package/dist/presets/strict.d.ts +0 -73
  28. package/dist/presets/strict.js +0 -73
  29. package/dist/presets/v3-strict.d.ts +0 -16
  30. package/dist/presets/v3-strict.js +0 -16
  31. package/dist/presets/v3.d.ts +0 -18
  32. package/dist/presets/v3.js +0 -18
  33. package/dist/rules/_effect-context.d.ts +0 -19
  34. package/dist/rules/_effect-context.js +0 -22
  35. package/dist/rules/no-arrow-ladder.d.ts +0 -6
  36. package/dist/rules/no-arrow-ladder.js +0 -61
  37. package/dist/rules/no-catch-all-to-map-error.d.ts +0 -6
  38. package/dist/rules/no-catch-all-to-map-error.js +0 -67
  39. package/dist/rules/no-effect-all-step-sequencing.d.ts +0 -6
  40. package/dist/rules/no-effect-all-step-sequencing.js +0 -63
  41. package/dist/rules/no-effect-as.d.ts +0 -6
  42. package/dist/rules/no-effect-as.js +0 -16
  43. package/dist/rules/no-effect-async.d.ts +0 -6
  44. package/dist/rules/no-effect-async.js +0 -16
  45. package/dist/rules/no-effect-fn-generator.d.ts +0 -6
  46. package/dist/rules/no-effect-fn-generator.js +0 -30
  47. package/dist/rules/no-effect-gen-adapter.d.ts +0 -6
  48. package/dist/rules/no-effect-gen-adapter.js +0 -30
  49. package/dist/rules/no-effect-map-flatten.d.ts +0 -6
  50. package/dist/rules/no-effect-map-flatten.js +0 -53
  51. package/dist/rules/no-effect-map-void.d.ts +0 -6
  52. package/dist/rules/no-effect-map-void.js +0 -40
  53. package/dist/rules/no-effect-never.d.ts +0 -6
  54. package/dist/rules/no-effect-never.js +0 -16
  55. package/dist/rules/no-effect-orElse-ladder.d.ts +0 -6
  56. package/dist/rules/no-effect-orElse-ladder.js +0 -53
  57. package/dist/rules/no-effect-succeed-string.d.ts +0 -6
  58. package/dist/rules/no-effect-succeed-string.js +0 -30
  59. package/dist/rules/no-effect-succeed-variable.d.ts +0 -6
  60. package/dist/rules/no-effect-succeed-variable.js +0 -30
  61. package/dist/rules/no-effect-succeed-void.d.ts +0 -6
  62. package/dist/rules/no-effect-succeed-void.js +0 -33
  63. package/dist/rules/no-effect-sync-console.d.ts +0 -6
  64. package/dist/rules/no-effect-sync-console.js +0 -63
  65. package/dist/rules/no-effect-sync-wrapper.d.ts +0 -6
  66. package/dist/rules/no-effect-sync-wrapper.js +0 -37
  67. package/dist/rules/no-effect-type-alias.d.ts +0 -6
  68. package/dist/rules/no-effect-type-alias.js +0 -52
  69. package/dist/rules/no-effect-wrapper-alias.d.ts +0 -6
  70. package/dist/rules/no-effect-wrapper-alias.js +0 -69
  71. package/dist/rules/no-extends-native-error.d.ts +0 -6
  72. package/dist/rules/no-extends-native-error.js +0 -41
  73. package/dist/rules/no-flatmap-ladder.d.ts +0 -6
  74. package/dist/rules/no-flatmap-ladder.js +0 -48
  75. package/dist/rules/no-fromnullable-coalesce.d.ts +0 -6
  76. package/dist/rules/no-fromnullable-coalesce.js +0 -36
  77. package/dist/rules/no-global-error-in-catch.d.ts +0 -6
  78. package/dist/rules/no-global-error-in-catch.js +0 -75
  79. package/dist/rules/no-global-error-in-failure.d.ts +0 -6
  80. package/dist/rules/no-global-error-in-failure.js +0 -54
  81. package/dist/rules/no-hand-rolled-tagged-union.d.ts +0 -6
  82. package/dist/rules/no-hand-rolled-tagged-union.js +0 -70
  83. package/dist/rules/no-if-statement.d.ts +0 -6
  84. package/dist/rules/no-if-statement.js +0 -18
  85. package/dist/rules/no-iife-wrapper.d.ts +0 -6
  86. package/dist/rules/no-iife-wrapper.js +0 -37
  87. package/dist/rules/no-inline-provide.d.ts +0 -6
  88. package/dist/rules/no-inline-provide.js +0 -31
  89. package/dist/rules/no-instanceof-schema.d.ts +0 -6
  90. package/dist/rules/no-instanceof-schema.js +0 -35
  91. package/dist/rules/no-make-unsafe.d.ts +0 -6
  92. package/dist/rules/no-make-unsafe.js +0 -30
  93. package/dist/rules/no-manual-data-guard.d.ts +0 -6
  94. package/dist/rules/no-manual-data-guard.js +0 -56
  95. package/dist/rules/no-manual-effect-channels.d.ts +0 -6
  96. package/dist/rules/no-manual-effect-channels.js +0 -40
  97. package/dist/rules/no-match-effect-branch.d.ts +0 -6
  98. package/dist/rules/no-match-effect-branch.js +0 -64
  99. package/dist/rules/no-match-void-branch.d.ts +0 -6
  100. package/dist/rules/no-match-void-branch.js +0 -50
  101. package/dist/rules/no-multiple-effect-provide.d.ts +0 -6
  102. package/dist/rules/no-multiple-effect-provide.js +0 -45
  103. package/dist/rules/no-nested-effect-call.d.ts +0 -6
  104. package/dist/rules/no-nested-effect-call.js +0 -97
  105. package/dist/rules/no-nested-effect-gen.d.ts +0 -6
  106. package/dist/rules/no-nested-effect-gen.js +0 -46
  107. package/dist/rules/no-nested-pipe.d.ts +0 -6
  108. package/dist/rules/no-nested-pipe.js +0 -38
  109. package/dist/rules/no-option-as.d.ts +0 -6
  110. package/dist/rules/no-option-as.js +0 -16
  111. package/dist/rules/no-option-boolean-normalization.d.ts +0 -6
  112. package/dist/rules/no-option-boolean-normalization.js +0 -50
  113. package/dist/rules/no-positional-log-error.d.ts +0 -6
  114. package/dist/rules/no-positional-log-error.js +0 -52
  115. package/dist/rules/no-promise-control-flow-in-tests.d.ts +0 -6
  116. package/dist/rules/no-promise-control-flow-in-tests.js +0 -94
  117. package/dist/rules/no-redundant-schema-tag-identifier.d.ts +0 -6
  118. package/dist/rules/no-redundant-schema-tag-identifier.js +0 -46
  119. package/dist/rules/no-return-in-arrow.d.ts +0 -6
  120. package/dist/rules/no-return-in-arrow.js +0 -41
  121. package/dist/rules/no-return-nullish.d.ts +0 -6
  122. package/dist/rules/no-return-nullish.js +0 -47
  123. package/dist/rules/no-run-in-effect-gen.d.ts +0 -6
  124. package/dist/rules/no-run-in-effect-gen.js +0 -48
  125. package/dist/rules/no-runtime-run-fork.d.ts +0 -6
  126. package/dist/rules/no-runtime-run-fork.js +0 -19
  127. package/dist/rules/no-schema-struct-with-tag.d.ts +0 -6
  128. package/dist/rules/no-schema-struct-with-tag.js +0 -48
  129. package/dist/rules/no-schema-struct.d.ts +0 -6
  130. package/dist/rules/no-schema-struct.js +0 -28
  131. package/dist/rules/no-schema-union-of-literals.d.ts +0 -6
  132. package/dist/rules/no-schema-union-of-literals.js +0 -35
  133. package/dist/rules/no-sleep-in-tests.d.ts +0 -6
  134. package/dist/rules/no-sleep-in-tests.js +0 -55
  135. package/dist/rules/no-spread.d.ts +0 -6
  136. package/dist/rules/no-spread.js +0 -26
  137. package/dist/rules/no-string-sentinel-const.d.ts +0 -6
  138. package/dist/rules/no-string-sentinel-const.js +0 -38
  139. package/dist/rules/no-switch-statement.d.ts +0 -6
  140. package/dist/rules/no-switch-statement.js +0 -16
  141. package/dist/rules/no-unnecessary-arrow-block.d.ts +0 -6
  142. package/dist/rules/no-unnecessary-arrow-block.js +0 -34
  143. package/dist/rules/no-unnecessary-effect-gen.d.ts +0 -6
  144. package/dist/rules/no-unnecessary-effect-gen.js +0 -35
  145. package/dist/rules/no-unnecessary-pipe-chain.d.ts +0 -6
  146. package/dist/rules/no-unnecessary-pipe-chain.js +0 -36
  147. package/dist/rules/no-unnecessary-pipe.d.ts +0 -6
  148. package/dist/rules/no-unnecessary-pipe.js +0 -29
@@ -1,48 +0,0 @@
1
- import { isCallOf } from "../vendor/effect-oxlint/AST.js";
2
- import { make } from "../vendor/effect-oxlint/Diagnostic.js";
3
- import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
4
- import { define, meta } from "../vendor/effect-oxlint/Rule.js";
5
- import "../vendor/effect-oxlint/index.js";
6
- import * as Effect from "effect/Effect";
7
- //#region src/rules/no-flatmap-ladder.ts
8
- const isEffectFlatMap = (node) => isCallOf(node, "Effect", "flatMap");
9
- const containsEffectFlatMap = (node) => {
10
- if (node == null || typeof node !== "object") return false;
11
- const n = node;
12
- if (n["type"] === "CallExpression" && "callee" in n && "arguments" in n) {
13
- if (isEffectFlatMap(node)) return true;
14
- }
15
- if ("arguments" in n && Array.isArray(n["arguments"])) {
16
- for (const arg of n["arguments"]) if (containsEffectFlatMap(arg)) return true;
17
- }
18
- if ("body" in n) return containsEffectFlatMap(n["body"]);
19
- return false;
20
- };
21
- const noFlatmapLadder = define({
22
- name: "no-flatmap-ladder",
23
- meta: meta({
24
- type: "suggestion",
25
- description: "Avoid nested Effect.flatMap (flatMap ladder). Build context once with Effect.all and run a single flatMap."
26
- }),
27
- create: function* () {
28
- const ctx = yield* RuleContext;
29
- return { CallExpression: (node) => {
30
- const ce = node;
31
- if (!isEffectFlatMap(ce)) return Effect.void;
32
- if (!("arguments" in ce) || !Array.isArray(ce.arguments)) return Effect.void;
33
- for (const arg of ce.arguments) if (arg != null && typeof arg === "object" && "type" in arg) {
34
- if (arg.type === "CallExpression" && isEffectFlatMap(arg)) return ctx.report(make({
35
- node,
36
- message: "Nested Effect.flatMap detected. Build context with Effect.all, then single flatMap."
37
- }));
38
- if ((arg.type === "ArrowFunctionExpression" || arg.type === "FunctionExpression") && "body" in arg && containsEffectFlatMap(arg.body)) return ctx.report(make({
39
- node,
40
- message: "Nested Effect.flatMap detected. Build context with Effect.all, then single flatMap."
41
- }));
42
- }
43
- return Effect.void;
44
- } };
45
- }
46
- });
47
- //#endregion
48
- export { noFlatmapLadder };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-fromnullable-coalesce.d.ts
4
- declare const noFromNullableCoalesce: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noFromNullableCoalesce };
@@ -1,36 +0,0 @@
1
- import { isCallOf } from "../vendor/effect-oxlint/AST.js";
2
- import { make } from "../vendor/effect-oxlint/Diagnostic.js";
3
- import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
4
- import { define, meta } from "../vendor/effect-oxlint/Rule.js";
5
- import "../vendor/effect-oxlint/index.js";
6
- import * as Effect from "effect/Effect";
7
- //#region src/rules/no-fromnullable-coalesce.ts
8
- const noFromNullableCoalesce = define({
9
- name: "no-fromnullable-coalesce",
10
- meta: meta({
11
- type: "suggestion",
12
- description: "Redundant nullish coalescing in Option.fromNullable. Pass the value directly."
13
- }),
14
- create: function* () {
15
- const ctx = yield* RuleContext;
16
- return { CallExpression: (node) => {
17
- const ce = node;
18
- if (!(isCallOf(ce, "Option", "fromNullable") || isCallOf(ce, "Option", "fromNullishOr"))) return Effect.void;
19
- if ("arguments" in node && Array.isArray(node.arguments) && node.arguments.length >= 1) {
20
- const arg = node.arguments[0];
21
- if (arg != null && typeof arg === "object" && "type" in arg && arg.type === "LogicalExpression" && "operator" in arg && arg.operator === "??") {
22
- if ("right" in arg && arg.right != null && typeof arg.right === "object" && "type" in arg.right) {
23
- const rhs = arg.right;
24
- if (rhs.type === "Literal" && "value" in rhs && rhs.value === null || rhs.type === "Identifier" && "name" in rhs && rhs.name === "undefined") return ctx.report(make({
25
- node,
26
- message: "Redundant ?? null/undefined in Option.fromNullable. Pass the value directly."
27
- }));
28
- }
29
- }
30
- }
31
- return Effect.void;
32
- } };
33
- }
34
- });
35
- //#endregion
36
- export { noFromNullableCoalesce };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-global-error-in-catch.d.ts
4
- declare const noGlobalErrorInCatch: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noGlobalErrorInCatch };
@@ -1,75 +0,0 @@
1
- import { memberNames } from "../vendor/effect-oxlint/AST.js";
2
- import { make } from "../vendor/effect-oxlint/Diagnostic.js";
3
- import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
4
- import { define, meta } from "../vendor/effect-oxlint/Rule.js";
5
- import "../vendor/effect-oxlint/index.js";
6
- import * as Option from "effect/Option";
7
- import * as Effect from "effect/Effect";
8
- //#region src/rules/no-global-error-in-catch.ts
9
- const nativeErrors = new Set([
10
- "Error",
11
- "TypeError",
12
- "RangeError",
13
- "ReferenceError",
14
- "SyntaxError",
15
- "URIError",
16
- "EvalError"
17
- ]);
18
- const catchMethods = new Set([
19
- "catch",
20
- "catchAll",
21
- "catchAllCause",
22
- "catchIf",
23
- "catchCauseIf",
24
- "catchTag",
25
- "catchTags",
26
- "catchDefect"
27
- ]);
28
- const isNativeErrorNew = (node) => {
29
- if (node.type !== "NewExpression") return false;
30
- const callee = node["callee"];
31
- return callee.type === "Identifier" && "name" in callee && nativeErrors.has(callee.name);
32
- };
33
- /**
34
- * Check if a function body returns `new Error(...)`.
35
- */
36
- const bodyReturnsNativeError = (fn) => {
37
- const body = fn["body"];
38
- if (body.type !== "BlockStatement") return isNativeErrorNew(body);
39
- const stmts = body["body"];
40
- if (!Array.isArray(stmts) || stmts.length !== 1) return false;
41
- const stmt = stmts[0];
42
- if (stmt.type !== "ReturnStatement") return false;
43
- const arg = stmt["argument"];
44
- return arg != null && typeof arg === "object" && isNativeErrorNew(arg);
45
- };
46
- const noGlobalErrorInCatch = define({
47
- name: "no-global-error-in-catch",
48
- meta: meta({
49
- type: "suggestion",
50
- description: "Avoid native Error in Effect catch handlers. Use Schema.TaggedErrorClass or Data.TaggedError."
51
- }),
52
- create: function* () {
53
- const ctx = yield* RuleContext;
54
- return { CallExpression: (node) => {
55
- const call = node;
56
- const names = Option.getOrUndefined(memberNames(call.callee));
57
- if (names === void 0) return Effect.void;
58
- const [obj, prop] = names;
59
- if (obj !== "Effect") return Effect.void;
60
- if (!catchMethods.has(prop)) return Effect.void;
61
- const args = call.arguments;
62
- if (args.length === 0) return Effect.void;
63
- const callback = args[args.length - 1];
64
- if (callback === void 0) return Effect.void;
65
- if (callback.type !== "ArrowFunctionExpression" && callback.type !== "FunctionExpression") return Effect.void;
66
- if (bodyReturnsNativeError(callback)) return ctx.report(make({
67
- node: callback,
68
- message: "Avoid native Error in Effect catch handler. Use Schema.TaggedErrorClass or Data.TaggedError."
69
- }));
70
- return Effect.void;
71
- } };
72
- }
73
- });
74
- //#endregion
75
- export { noGlobalErrorInCatch };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-global-error-in-failure.d.ts
4
- declare const noGlobalErrorInFailure: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noGlobalErrorInFailure };
@@ -1,54 +0,0 @@
1
- import { matchCallOf } from "../vendor/effect-oxlint/AST.js";
2
- import { make } from "../vendor/effect-oxlint/Diagnostic.js";
3
- import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
4
- import { define, meta } from "../vendor/effect-oxlint/Rule.js";
5
- import "../vendor/effect-oxlint/index.js";
6
- import * as Option from "effect/Option";
7
- import * as Effect from "effect/Effect";
8
- //#region src/rules/no-global-error-in-failure.ts
9
- const nativeErrors = new Set([
10
- "Error",
11
- "TypeError",
12
- "RangeError",
13
- "ReferenceError",
14
- "SyntaxError",
15
- "URIError",
16
- "EvalError"
17
- ]);
18
- const isNativeErrorNew = (node) => {
19
- if (node.type !== "NewExpression") return false;
20
- const callee = node["callee"];
21
- return callee.type === "Identifier" && "name" in callee && nativeErrors.has(callee.name);
22
- };
23
- const noGlobalErrorInFailure = define({
24
- name: "no-global-error-in-failure",
25
- meta: meta({
26
- type: "suggestion",
27
- description: "Avoid native Error in Effect.fail(). Use Schema.TaggedErrorClass or Data.TaggedError."
28
- }),
29
- create: function* () {
30
- const ctx = yield* RuleContext;
31
- return { CallExpression: (node) => {
32
- const call = node;
33
- if (Option.isNone(matchCallOf(call, "Effect", "fail")) && Option.isNone(matchCallOf(call, "Effect", "failSync")) && Option.isNone(matchCallOf(call, "Effect", "failCause"))) return Effect.void;
34
- const args = call.arguments;
35
- if (args.length === 0) return Effect.void;
36
- const arg = args[args.length - 1];
37
- if (arg === void 0) return Effect.void;
38
- if (isNativeErrorNew(arg)) return ctx.report(make({
39
- node: arg,
40
- message: "Avoid native Error in Effect.fail(). Use Schema.TaggedErrorClass or Data.TaggedError."
41
- }));
42
- if (arg.type === "ArrowFunctionExpression") {
43
- const body = arg["body"];
44
- if (body.type !== "BlockStatement" && isNativeErrorNew(body)) return ctx.report(make({
45
- node: arg,
46
- message: "Avoid native Error in Effect.failSync(). Use Schema.TaggedErrorClass or Data.TaggedError."
47
- }));
48
- }
49
- return Effect.void;
50
- } };
51
- }
52
- });
53
- //#endregion
54
- export { noGlobalErrorInFailure };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-hand-rolled-tagged-union.d.ts
4
- declare const noHandRolledTaggedUnion: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noHandRolledTaggedUnion };
@@ -1,70 +0,0 @@
1
- import { make } from "../vendor/effect-oxlint/Diagnostic.js";
2
- import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
3
- import { define, meta } from "../vendor/effect-oxlint/Rule.js";
4
- import "../vendor/effect-oxlint/index.js";
5
- import * as Effect from "effect/Effect";
6
- //#region src/rules/no-hand-rolled-tagged-union.ts
7
- const isAstNode = (value) => typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
8
- const getNodeField = (node, field) => {
9
- const value = node[field];
10
- return isAstNode(value) ? value : void 0;
11
- };
12
- const getStringField = (node, field) => {
13
- const value = node[field];
14
- return typeof value === "string" ? value : void 0;
15
- };
16
- const getNodeArrayField = (node, field) => {
17
- const value = node[field];
18
- return Array.isArray(value) ? value.filter(isAstNode) : void 0;
19
- };
20
- const getPropertyKeyName = (node) => {
21
- if (node.type === "Identifier" || node.type === "StringLiteral" || node.type === "Literal") return getStringField(node, "name") ?? getStringField(node, "value");
22
- };
23
- const isPascalCaseTag = (value) => {
24
- if (value.length === 0) return false;
25
- const first = value.charAt(0);
26
- return first === first.toUpperCase() && first !== first.toLowerCase();
27
- };
28
- const isReportableTagLiteral = (member) => {
29
- if (member.type !== "TSPropertySignature") return false;
30
- const key = getNodeField(member, "key");
31
- if (key === void 0 || getPropertyKeyName(key) !== "_tag") return false;
32
- const annotation = getNodeField(member, "typeAnnotation");
33
- const inner = annotation === void 0 ? void 0 : getNodeField(annotation, "typeAnnotation");
34
- if (inner?.type !== "TSLiteralType") return false;
35
- const literal = getNodeField(inner, "literal");
36
- if (literal === void 0) return false;
37
- if (literal.type !== "StringLiteral" && literal.type !== "Literal") return false;
38
- const value = getStringField(literal, "value");
39
- return value !== void 0 && isPascalCaseTag(value);
40
- };
41
- const literalHasTag = (node) => {
42
- if (node.type !== "TSTypeLiteral") return false;
43
- const members = getNodeArrayField(node, "members");
44
- return members !== void 0 && members.some(isReportableTagLiteral);
45
- };
46
- const noHandRolledTaggedUnion = define({
47
- name: "no-hand-rolled-tagged-union",
48
- meta: meta({
49
- type: "suggestion",
50
- description: "Use Schema.TaggedUnion, Schema.TaggedStruct, or Schema.TaggedErrorClass instead of inline _tag union literals."
51
- }),
52
- create: function* () {
53
- const ctx = yield* RuleContext;
54
- return { TSUnionType: (node) => {
55
- const types = getNodeArrayField(node, "types");
56
- if (types === void 0 || types.length < 2) return Effect.void;
57
- let tagged = 0;
58
- for (const type of types) {
59
- if (literalHasTag(type)) tagged += 1;
60
- if (tagged >= 2) return ctx.report(make({
61
- node,
62
- message: "Hand-rolled `_tag` discriminated union. Use Schema.TaggedUnion, Schema.TaggedStruct, or Schema.TaggedErrorClass instead."
63
- }));
64
- }
65
- return Effect.void;
66
- } };
67
- }
68
- });
69
- //#endregion
70
- export { noHandRolledTaggedUnion };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-if-statement.d.ts
4
- declare const noIfStatement: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noIfStatement };
@@ -1,18 +0,0 @@
1
- import { banStatement } from "../vendor/effect-oxlint/Rule.js";
2
- import "../vendor/effect-oxlint/index.js";
3
- //#region src/rules/no-if-statement.ts
4
- /**
5
- * Ban `if` statements in Effect codebases.
6
- *
7
- * Use `Option.match`, `Either.match`, `Match.value`, or data combinators.
8
- *
9
- * Source: biome-effect-linting-rules/no-if-statement
10
- *
11
- * Note: Very opinionated — recommended for strict functional presets only.
12
- */
13
- const noIfStatement = banStatement("IfStatement", {
14
- message: "Avoid if statements. Use Option.match, Either.match, Match.value, or Effect.if.",
15
- meta: { type: "suggestion" }
16
- });
17
- //#endregion
18
- export { noIfStatement };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-iife-wrapper.d.ts
4
- declare const noIifeWrapper: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noIifeWrapper };
@@ -1,37 +0,0 @@
1
- import { make } from "../vendor/effect-oxlint/Diagnostic.js";
2
- import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
3
- import { define, meta } from "../vendor/effect-oxlint/Rule.js";
4
- import "../vendor/effect-oxlint/index.js";
5
- import * as Effect from "effect/Effect";
6
- //#region src/rules/no-iife-wrapper.ts
7
- /**
8
- * Ban immediately-invoked function expressions (IIFEs).
9
- *
10
- * Use named const binding + flat pipeline.
11
- *
12
- * Source: biome-effect-linting-rules/no-iife-wrapper
13
- */
14
- const noIifeWrapper = define({
15
- name: "no-iife-wrapper",
16
- meta: meta({
17
- type: "suggestion",
18
- description: "Avoid IIFEs. Use named const bindings + flat pipeline."
19
- }),
20
- create: function* () {
21
- const ctx = yield* RuleContext;
22
- return { CallExpression: (node) => {
23
- if (!("callee" in node)) return Effect.void;
24
- const callee = node.callee;
25
- if (callee == null || typeof callee !== "object" || !("type" in callee)) return Effect.void;
26
- const isWrappedFn = callee.type === "ArrowFunctionExpression" || callee.type === "FunctionExpression";
27
- const isParenWrapped = callee.type === "ParenthesizedExpression" && "expression" in callee && callee.expression != null && typeof callee.expression === "object" && "type" in callee.expression && (callee.expression.type === "ArrowFunctionExpression" || callee.expression.type === "FunctionExpression");
28
- if (isWrappedFn || isParenWrapped) return ctx.report(make({
29
- node,
30
- message: "Avoid IIFEs. Use named const binding + flat pipeline."
31
- }));
32
- return Effect.void;
33
- } };
34
- }
35
- });
36
- //#endregion
37
- export { noIifeWrapper };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-inline-provide.d.ts
4
- declare const noInlineProvide: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noInlineProvide };
@@ -1,31 +0,0 @@
1
- import { isCallOf } from "../vendor/effect-oxlint/AST.js";
2
- import { make } from "../vendor/effect-oxlint/Diagnostic.js";
3
- import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
4
- import { merge } from "../vendor/effect-oxlint/Visitor.js";
5
- import { define, meta } from "../vendor/effect-oxlint/Rule.js";
6
- import "../vendor/effect-oxlint/index.js";
7
- import { makeEffectContextTracker } from "./_effect-context.js";
8
- import * as Effect from "effect/Effect";
9
- import * as Ref from "effect/Ref";
10
- //#region src/rules/no-inline-provide.ts
11
- const noInlineProvide = define({
12
- name: "no-inline-provide",
13
- meta: meta({
14
- type: "suggestion",
15
- description: "Avoid Effect.provide inside Effect.gen/fn. Provide layers at the boundary."
16
- }),
17
- create: function* () {
18
- const ctx = yield* RuleContext;
19
- const [depth, tracker] = yield* makeEffectContextTracker;
20
- return merge(tracker, { CallExpression: (node) => Effect.flatMap(Ref.get(depth), (d) => {
21
- if (d <= 0) return Effect.void;
22
- if (!isCallOf(node, "Effect", "provide")) return Effect.void;
23
- return ctx.report(make({
24
- node,
25
- message: "Avoid Effect.provide inside Effect.gen/fn. Provide layers at the boundary."
26
- }));
27
- }) });
28
- }
29
- });
30
- //#endregion
31
- export { noInlineProvide };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-instanceof-schema.d.ts
4
- declare const noInstanceofSchema: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noInstanceofSchema };
@@ -1,35 +0,0 @@
1
- import { make } from "../vendor/effect-oxlint/Diagnostic.js";
2
- import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
3
- import { define, meta } from "../vendor/effect-oxlint/Rule.js";
4
- import "../vendor/effect-oxlint/index.js";
5
- import * as Effect from "effect/Effect";
6
- //#region src/rules/no-instanceof-schema.ts
7
- /**
8
- * Ban `instanceof` checks against Schema-derived classes.
9
- *
10
- * Use `Schema.is(SchemaType)` instead.
11
- *
12
- * Source: language-service/instanceOfSchema
13
- *
14
- * Note: Without type information, we detect common Effect Schema class names
15
- * used in `instanceof` checks. This is a best-effort heuristic.
16
- */
17
- const noInstanceofSchema = define({
18
- name: "no-instanceof-schema",
19
- meta: meta({
20
- type: "suggestion",
21
- description: "Avoid instanceof with Schema types. Use Schema.is(SchemaType) instead."
22
- }),
23
- create: function* () {
24
- const ctx = yield* RuleContext;
25
- return { BinaryExpression: (node) => {
26
- if ("operator" in node && node.operator === "instanceof") return ctx.report(make({
27
- node,
28
- message: "Avoid instanceof. Add a static `is` field to your class: `static is = Schema.is(this)`, then use `MyClass.is(value)`. For tagged types, use `_tag` checks."
29
- }));
30
- return Effect.void;
31
- } };
32
- }
33
- });
34
- //#endregion
35
- export { noInstanceofSchema };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-make-unsafe.d.ts
4
- declare const noMakeUnsafe: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noMakeUnsafe };
@@ -1,30 +0,0 @@
1
- import { memberNames } from "../vendor/effect-oxlint/AST.js";
2
- import { make } from "../vendor/effect-oxlint/Diagnostic.js";
3
- import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
4
- import { define, meta } from "../vendor/effect-oxlint/Rule.js";
5
- import "../vendor/effect-oxlint/index.js";
6
- import * as Option from "effect/Option";
7
- import * as Effect from "effect/Effect";
8
- //#region src/rules/no-make-unsafe.ts
9
- const noMakeUnsafe = define({
10
- name: "no-make-unsafe",
11
- meta: meta({
12
- type: "problem",
13
- description: "Avoid makeUnsafe constructors. Use safe Effectful or Option-returning construction."
14
- }),
15
- create: function* () {
16
- const ctx = yield* RuleContext;
17
- return { CallExpression: (node) => {
18
- const call = node;
19
- if (call.callee.type !== "MemberExpression") return Effect.void;
20
- if (Option.isNone(memberNames(call.callee))) return Effect.void;
21
- if (Option.getOrUndefined(memberNames(call.callee))?.[1] !== "makeUnsafe") return Effect.void;
22
- return ctx.report(make({
23
- node,
24
- message: "Do not call `.makeUnsafe(...)`. Use safe Effectful/Option-returning construction instead of bypassing validation."
25
- }));
26
- } };
27
- }
28
- });
29
- //#endregion
30
- export { noMakeUnsafe };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-manual-data-guard.d.ts
4
- declare const noManualDataGuard: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noManualDataGuard };
@@ -1,56 +0,0 @@
1
- import { make } from "../vendor/effect-oxlint/Diagnostic.js";
2
- import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
3
- import { define, meta } from "../vendor/effect-oxlint/Rule.js";
4
- import "../vendor/effect-oxlint/index.js";
5
- import * as Effect from "effect/Effect";
6
- //#region src/rules/no-manual-data-guard.ts
7
- const isAstNode = (value) => typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
8
- const functionTypes = new Set([
9
- "ArrowFunctionExpression",
10
- "FunctionDeclaration",
11
- "FunctionExpression"
12
- ]);
13
- const findFunction = (node) => {
14
- let parent = node.parent;
15
- while (isAstNode(parent)) {
16
- if (functionTypes.has(parent.type)) return parent;
17
- parent = parent.parent;
18
- }
19
- };
20
- const containsNodeType = (value, nodeTypes) => {
21
- if (Array.isArray(value)) return value.some((item) => containsNodeType(item, nodeTypes));
22
- if (!isAstNode(value)) return false;
23
- if (nodeTypes.has(value.type)) return true;
24
- return Object.entries(value).some(([key, child]) => key !== "parent" && containsNodeType(child, nodeTypes));
25
- };
26
- const containsInstanceOf = (value) => {
27
- if (Array.isArray(value)) return value.some(containsInstanceOf);
28
- if (!isAstNode(value)) return false;
29
- if (value.type === "BinaryExpression" && value["operator"] === "instanceof") return true;
30
- return Object.entries(value).some(([key, child]) => key !== "parent" && containsInstanceOf(child));
31
- };
32
- const parameterName = (parameter) => {
33
- if (!isAstNode(parameter)) return void 0;
34
- if ((parameter.type === "Identifier" || parameter.type === "BindingIdentifier") && typeof parameter["name"] === "string") return parameter["name"];
35
- };
36
- const noManualDataGuard = define({
37
- name: "no-manual-data-guard",
38
- meta: meta({
39
- type: "suggestion",
40
- description: "Decode unknown data with Schema instead of asserting it with a type predicate."
41
- }),
42
- create: function* () {
43
- const ctx = yield* RuleContext;
44
- return { TSTypePredicate: (node) => {
45
- const fn = findFunction(node);
46
- if (fn === void 0 || containsInstanceOf(fn["body"])) return Effect.void;
47
- const predicateParameter = parameterName(node.parameterName);
48
- return (Array.isArray(fn["params"]) ? fn["params"] : []).some((parameter) => parameterName(parameter) === predicateParameter && containsNodeType(parameter, new Set(["TSUnknownKeyword", "TSAnyKeyword"]))) ? ctx.report(make({
49
- node,
50
- message: "Avoid promoting unknown data with a manual type predicate. Decode it with the canonical Schema first."
51
- })) : Effect.void;
52
- } };
53
- }
54
- });
55
- //#endregion
56
- export { noManualDataGuard };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-manual-effect-channels.d.ts
4
- declare const noManualEffectChannels: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noManualEffectChannels };
@@ -1,40 +0,0 @@
1
- import { make } from "../vendor/effect-oxlint/Diagnostic.js";
2
- import { RuleContext } from "../vendor/effect-oxlint/RuleContext.js";
3
- import { define, meta } from "../vendor/effect-oxlint/Rule.js";
4
- import "../vendor/effect-oxlint/index.js";
5
- import * as Effect from "effect/Effect";
6
- //#region src/rules/no-manual-effect-channels.ts
7
- /**
8
- * Ban manual `Effect.Effect<A, E, R>` type annotations.
9
- *
10
- * Let return types infer from the Effect/Layer you return.
11
- *
12
- * Source: biome-effect-linting-rules/no-manual-effect-channels
13
- */
14
- const noManualEffectChannels = define({
15
- name: "no-manual-effect-channels",
16
- meta: meta({
17
- type: "suggestion",
18
- description: "Avoid manual Effect.Effect<A, E, R> annotations. Let types infer from the returned Effect."
19
- }),
20
- create: function* () {
21
- const ctx = yield* RuleContext;
22
- return { TSTypeReference: (node) => {
23
- if (!("typeName" in node) || node.typeName == null) return Effect.void;
24
- const typeName = node.typeName;
25
- if (typeName["type"] === "TSQualifiedName" && "left" in typeName && "right" in typeName) {
26
- const left = typeName["left"];
27
- const right = typeName["right"];
28
- if (left != null && left["type"] === "Identifier" && (left["name"] === "Effect" || left["name"] === "Layer") && right != null && right["type"] === "Identifier" && (right["name"] === "Effect" || right["name"] === "Layer")) {
29
- if ("typeParameters" in node && node.typeParameters != null && typeof node.typeParameters === "object" && "params" in node.typeParameters && Array.isArray(node.typeParameters["params"]) && node.typeParameters["params"].length > 0) return ctx.report(make({
30
- node,
31
- message: "Avoid manual Effect/Layer channel annotations. Let types infer from the returned value."
32
- }));
33
- }
34
- }
35
- return Effect.void;
36
- } };
37
- }
38
- });
39
- //#endregion
40
- export { noManualEffectChannels };
@@ -1,6 +0,0 @@
1
- import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
-
3
- //#region src/rules/no-match-effect-branch.d.ts
4
- declare const noMatchEffectBranch: _$_oxlint_plugins0.CreateRule;
5
- //#endregion
6
- export { noMatchEffectBranch };