oxlint-plugin-effect 0.1.0 → 0.2.1

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 (256) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +13 -0
  2. package/dist/index.d.ts +4 -0
  3. package/dist/index.js +4 -0
  4. package/dist/plugin.d.ts +5 -0
  5. package/dist/plugin.js +18 -0
  6. package/dist/presets/core.d.ts +43 -0
  7. package/dist/presets/core.js +43 -0
  8. package/dist/presets/effect-native.d.ts +28 -0
  9. package/dist/presets/effect-native.js +28 -0
  10. package/dist/presets/full.d.ts +60 -0
  11. package/dist/presets/full.js +60 -0
  12. package/dist/presets/functional.d.ts +21 -0
  13. package/dist/presets/functional.js +21 -0
  14. package/dist/presets/index.d.ts +13 -0
  15. package/dist/presets/index.js +18 -0
  16. package/dist/presets/strict.d.ts +69 -0
  17. package/dist/presets/strict.js +69 -0
  18. package/dist/presets/v3.d.ts +15 -0
  19. package/dist/presets/v3.js +15 -0
  20. package/dist/rules/_effect-context.d.ts +19 -0
  21. package/dist/rules/_effect-context.js +22 -0
  22. package/dist/rules/index.d.ts +66 -0
  23. package/dist/rules/index.js +124 -0
  24. package/dist/rules/no-arrow-ladder.d.ts +6 -0
  25. package/dist/rules/no-arrow-ladder.js +61 -0
  26. package/dist/rules/no-async-function.d.ts +6 -0
  27. package/dist/rules/no-async-function.js +46 -0
  28. package/dist/rules/no-catch-all-to-map-error.d.ts +6 -0
  29. package/dist/rules/no-catch-all-to-map-error.js +67 -0
  30. package/dist/rules/no-effect-as.d.ts +6 -0
  31. package/dist/rules/no-effect-as.js +16 -0
  32. package/dist/rules/no-effect-async.d.ts +6 -0
  33. package/dist/rules/no-effect-async.js +16 -0
  34. package/dist/rules/no-effect-bind.d.ts +6 -0
  35. package/dist/rules/no-effect-bind.js +16 -0
  36. package/dist/rules/no-effect-do.d.ts +6 -0
  37. package/dist/rules/no-effect-do.js +16 -0
  38. package/dist/rules/no-effect-fn-generator.d.ts +6 -0
  39. package/dist/rules/no-effect-fn-generator.js +30 -0
  40. package/dist/rules/no-effect-gen-adapter.d.ts +6 -0
  41. package/dist/rules/no-effect-gen-adapter.js +30 -0
  42. package/dist/rules/no-effect-map-flatten.d.ts +6 -0
  43. package/dist/rules/no-effect-map-flatten.js +53 -0
  44. package/dist/rules/no-effect-map-void.d.ts +6 -0
  45. package/dist/rules/no-effect-map-void.js +40 -0
  46. package/dist/rules/no-effect-never.d.ts +6 -0
  47. package/dist/rules/no-effect-never.js +16 -0
  48. package/dist/rules/no-effect-orElse-ladder.d.ts +6 -0
  49. package/dist/rules/no-effect-orElse-ladder.js +53 -0
  50. package/dist/rules/no-effect-succeed-string.d.ts +6 -0
  51. package/dist/rules/no-effect-succeed-string.js +30 -0
  52. package/dist/rules/no-effect-succeed-variable.d.ts +6 -0
  53. package/dist/rules/no-effect-succeed-variable.js +30 -0
  54. package/dist/rules/no-effect-succeed-void.d.ts +6 -0
  55. package/dist/rules/no-effect-succeed-void.js +33 -0
  56. package/dist/rules/no-effect-sync-console.d.ts +6 -0
  57. package/dist/rules/no-effect-sync-console.js +63 -0
  58. package/dist/rules/no-effect-sync-wrapper.d.ts +6 -0
  59. package/dist/rules/no-effect-sync-wrapper.js +37 -0
  60. package/dist/rules/no-effect-type-alias.d.ts +6 -0
  61. package/dist/rules/no-effect-type-alias.js +52 -0
  62. package/dist/rules/no-effect-wrapper-alias.d.ts +6 -0
  63. package/dist/rules/no-effect-wrapper-alias.js +69 -0
  64. package/dist/rules/no-extends-native-error.d.ts +6 -0
  65. package/dist/rules/no-extends-native-error.js +41 -0
  66. package/dist/rules/no-flatmap-ladder.d.ts +6 -0
  67. package/dist/rules/no-flatmap-ladder.js +48 -0
  68. package/dist/rules/no-fromnullable-coalesce.d.ts +6 -0
  69. package/dist/rules/no-fromnullable-coalesce.js +36 -0
  70. package/dist/rules/no-global-error-in-catch.d.ts +6 -0
  71. package/dist/rules/no-global-error-in-catch.js +75 -0
  72. package/dist/rules/no-global-error-in-failure.d.ts +6 -0
  73. package/dist/rules/no-global-error-in-failure.js +54 -0
  74. package/dist/rules/no-globals.d.ts +6 -0
  75. package/dist/rules/no-globals.js +164 -0
  76. package/dist/rules/no-if-statement.d.ts +6 -0
  77. package/dist/rules/no-if-statement.js +18 -0
  78. package/dist/rules/no-iife-wrapper.d.ts +6 -0
  79. package/dist/rules/no-iife-wrapper.js +37 -0
  80. package/dist/rules/no-inline-provide.d.ts +6 -0
  81. package/dist/rules/no-inline-provide.js +31 -0
  82. package/dist/rules/no-instanceof-schema.d.ts +6 -0
  83. package/dist/rules/no-instanceof-schema.js +35 -0
  84. package/dist/rules/no-manual-effect-channels.d.ts +6 -0
  85. package/dist/rules/no-manual-effect-channels.js +40 -0
  86. package/dist/rules/no-match-effect-branch.d.ts +6 -0
  87. package/dist/rules/no-match-effect-branch.js +64 -0
  88. package/dist/rules/no-match-void-branch.d.ts +6 -0
  89. package/dist/rules/no-match-void-branch.js +50 -0
  90. package/dist/rules/no-multiple-effect-provide.d.ts +6 -0
  91. package/dist/rules/no-multiple-effect-provide.js +45 -0
  92. package/dist/rules/no-nested-effect-call.d.ts +6 -0
  93. package/dist/rules/no-nested-effect-call.js +97 -0
  94. package/dist/rules/no-nested-effect-gen.d.ts +6 -0
  95. package/dist/rules/no-nested-effect-gen.js +46 -0
  96. package/dist/rules/no-nested-pipe.d.ts +6 -0
  97. package/dist/rules/no-nested-pipe.js +38 -0
  98. package/dist/rules/no-new-error.d.ts +6 -0
  99. package/dist/rules/no-new-error.js +39 -0
  100. package/dist/rules/no-new-promise.d.ts +6 -0
  101. package/dist/rules/no-new-promise.js +38 -0
  102. package/dist/rules/no-node-builtin-import.d.ts +6 -0
  103. package/dist/rules/no-node-builtin-import.js +61 -0
  104. package/dist/rules/no-option-as.d.ts +6 -0
  105. package/dist/rules/no-option-as.js +16 -0
  106. package/dist/rules/no-option-boolean-normalization.d.ts +6 -0
  107. package/dist/rules/no-option-boolean-normalization.js +50 -0
  108. package/dist/rules/no-positional-log-error.d.ts +6 -0
  109. package/dist/rules/no-positional-log-error.js +52 -0
  110. package/dist/rules/no-redundant-schema-tag-identifier.d.ts +6 -0
  111. package/dist/rules/no-redundant-schema-tag-identifier.js +46 -0
  112. package/dist/rules/no-return-in-arrow.d.ts +6 -0
  113. package/dist/rules/no-return-in-arrow.js +41 -0
  114. package/dist/rules/no-return-nullish.d.ts +6 -0
  115. package/dist/rules/no-return-nullish.js +47 -0
  116. package/dist/rules/no-run-in-effect-gen.d.ts +6 -0
  117. package/dist/rules/no-run-in-effect-gen.js +48 -0
  118. package/dist/rules/no-runtime-run-fork.d.ts +6 -0
  119. package/dist/rules/no-runtime-run-fork.js +19 -0
  120. package/dist/rules/no-schema-struct-with-tag.d.ts +6 -0
  121. package/dist/rules/no-schema-struct-with-tag.js +48 -0
  122. package/dist/rules/no-schema-union-of-literals.d.ts +6 -0
  123. package/dist/rules/no-schema-union-of-literals.js +35 -0
  124. package/dist/rules/no-string-sentinel-const.d.ts +6 -0
  125. package/dist/rules/no-string-sentinel-const.js +38 -0
  126. package/dist/rules/no-switch-statement.d.ts +6 -0
  127. package/dist/rules/no-switch-statement.js +16 -0
  128. package/dist/rules/no-ternary.d.ts +6 -0
  129. package/dist/rules/no-ternary.js +30 -0
  130. package/dist/rules/no-throw-statement.d.ts +6 -0
  131. package/dist/rules/no-throw-statement.js +34 -0
  132. package/dist/rules/no-try-catch.d.ts +6 -0
  133. package/dist/rules/no-try-catch.js +34 -0
  134. package/dist/rules/no-unnecessary-arrow-block.d.ts +6 -0
  135. package/dist/rules/no-unnecessary-arrow-block.js +34 -0
  136. package/dist/rules/no-unnecessary-effect-gen.d.ts +6 -0
  137. package/dist/rules/no-unnecessary-effect-gen.js +35 -0
  138. package/dist/rules/no-unnecessary-pipe-chain.d.ts +6 -0
  139. package/dist/rules/no-unnecessary-pipe-chain.js +36 -0
  140. package/dist/rules/no-unnecessary-pipe.d.ts +6 -0
  141. package/dist/rules/no-unnecessary-pipe.js +29 -0
  142. package/dist/vendor/effect-oxlint/AST.d.ts +199 -0
  143. package/dist/vendor/effect-oxlint/AST.js +214 -0
  144. package/dist/vendor/effect-oxlint/Comment.d.ts +55 -0
  145. package/dist/vendor/effect-oxlint/Comment.js +67 -0
  146. package/dist/vendor/effect-oxlint/Diagnostic.d.ts +86 -0
  147. package/dist/vendor/effect-oxlint/Diagnostic.js +115 -0
  148. package/dist/vendor/effect-oxlint/Plugin.d.ts +38 -0
  149. package/dist/vendor/effect-oxlint/Plugin.js +45 -0
  150. package/dist/vendor/effect-oxlint/Rule.d.ts +218 -0
  151. package/dist/vendor/effect-oxlint/Rule.js +309 -0
  152. package/dist/vendor/effect-oxlint/RuleContext.d.ts +77 -0
  153. package/dist/vendor/effect-oxlint/RuleContext.js +74 -0
  154. package/dist/vendor/effect-oxlint/Scope.d.ts +100 -0
  155. package/dist/vendor/effect-oxlint/Scope.js +110 -0
  156. package/dist/vendor/effect-oxlint/SourceCode.d.ts +180 -0
  157. package/dist/vendor/effect-oxlint/SourceCode.js +203 -0
  158. package/dist/vendor/effect-oxlint/Testing.d.ts +510 -0
  159. package/dist/vendor/effect-oxlint/Testing.js +963 -0
  160. package/dist/vendor/effect-oxlint/Token.d.ts +98 -0
  161. package/dist/vendor/effect-oxlint/Token.js +103 -0
  162. package/dist/vendor/effect-oxlint/Visitor.d.ts +166 -0
  163. package/dist/vendor/effect-oxlint/Visitor.js +138 -0
  164. package/dist/vendor/effect-oxlint/index.d.ts +13 -0
  165. package/dist/vendor/effect-oxlint/index.js +12 -0
  166. package/package.json +24 -5
  167. package/.effect-lsp.json +0 -60
  168. package/.oxlintrc.json +0 -33
  169. package/CHANGELOG.md +0 -37
  170. package/scripts/add-rule.ts +0 -87
  171. package/scripts/codegen.ts +0 -108
  172. package/src/index.ts +0 -9
  173. package/src/plugin.ts +0 -16
  174. package/src/presets/core.ts +0 -47
  175. package/src/presets/effect-native.ts +0 -34
  176. package/src/presets/full.ts +0 -70
  177. package/src/presets/functional.ts +0 -18
  178. package/src/presets/index.ts +0 -5
  179. package/src/presets/strict.ts +0 -77
  180. package/src/rules/_effect-context.ts +0 -28
  181. package/src/rules/index.ts +0 -72
  182. package/src/rules/no-arrow-ladder.ts +0 -70
  183. package/src/rules/no-async-function.ts +0 -47
  184. package/src/rules/no-catch-all-to-map-error.ts +0 -89
  185. package/src/rules/no-effect-as.ts +0 -14
  186. package/src/rules/no-effect-async.ts +0 -14
  187. package/src/rules/no-effect-bind.ts +0 -13
  188. package/src/rules/no-effect-do.ts +0 -14
  189. package/src/rules/no-effect-fn-generator.ts +0 -58
  190. package/src/rules/no-effect-gen-adapter.ts +0 -50
  191. package/src/rules/no-effect-map-flatten.ts +0 -82
  192. package/src/rules/no-effect-map-void.ts +0 -80
  193. package/src/rules/no-effect-never.ts +0 -14
  194. package/src/rules/no-effect-orElse-ladder.ts +0 -79
  195. package/src/rules/no-effect-succeed-string.ts +0 -52
  196. package/src/rules/no-effect-succeed-variable.ts +0 -50
  197. package/src/rules/no-effect-succeed-void.ts +0 -63
  198. package/src/rules/no-effect-sync-console.ts +0 -91
  199. package/src/rules/no-effect-sync-wrapper.ts +0 -67
  200. package/src/rules/no-effect-type-alias.ts +0 -71
  201. package/src/rules/no-effect-wrapper-alias.ts +0 -95
  202. package/src/rules/no-extends-native-error.ts +0 -54
  203. package/src/rules/no-flatmap-ladder.ts +0 -77
  204. package/src/rules/no-fromnullable-coalesce.ts +0 -62
  205. package/src/rules/no-global-error-in-catch.ts +0 -104
  206. package/src/rules/no-global-error-in-failure.ts +0 -83
  207. package/src/rules/no-globals.ts +0 -178
  208. package/src/rules/no-if-statement.ts +0 -16
  209. package/src/rules/no-iife-wrapper.ts +0 -51
  210. package/src/rules/no-inline-provide.ts +0 -41
  211. package/src/rules/no-instanceof-schema.ts +0 -42
  212. package/src/rules/no-manual-effect-channels.ts +0 -58
  213. package/src/rules/no-match-effect-branch.ts +0 -82
  214. package/src/rules/no-match-void-branch.ts +0 -72
  215. package/src/rules/no-multiple-effect-provide.ts +0 -75
  216. package/src/rules/no-nested-effect-call.ts +0 -57
  217. package/src/rules/no-nested-effect-gen.ts +0 -43
  218. package/src/rules/no-nested-pipe.ts +0 -73
  219. package/src/rules/no-new-error.ts +0 -53
  220. package/src/rules/no-new-promise.ts +0 -50
  221. package/src/rules/no-node-builtin-import.ts +0 -68
  222. package/src/rules/no-option-as.ts +0 -13
  223. package/src/rules/no-option-boolean-normalization.ts +0 -88
  224. package/src/rules/no-positional-log-error.ts +0 -76
  225. package/src/rules/no-redundant-schema-tag-identifier.ts +0 -62
  226. package/src/rules/no-return-in-arrow.ts +0 -76
  227. package/src/rules/no-return-nullish.ts +0 -80
  228. package/src/rules/no-run-in-effect.ts +0 -18
  229. package/src/rules/no-runtime-run-fork.ts +0 -14
  230. package/src/rules/no-schema-struct-with-tag.ts +0 -64
  231. package/src/rules/no-schema-union-of-literals.ts +0 -48
  232. package/src/rules/no-string-sentinel-const.ts +0 -49
  233. package/src/rules/no-switch-statement.ts +0 -13
  234. package/src/rules/no-ternary.ts +0 -30
  235. package/src/rules/no-throw-statement.ts +0 -39
  236. package/src/rules/no-try-catch.ts +0 -39
  237. package/src/rules/no-unnecessary-arrow-block.ts +0 -51
  238. package/src/rules/no-unnecessary-effect-gen.ts +0 -83
  239. package/src/rules/no-unnecessary-pipe-chain.ts +0 -47
  240. package/src/rules/no-unnecessary-pipe.ts +0 -45
  241. package/src/vendor/effect-oxlint/AST.ts +0 -516
  242. package/src/vendor/effect-oxlint/Comment.ts +0 -86
  243. package/src/vendor/effect-oxlint/Diagnostic.ts +0 -199
  244. package/src/vendor/effect-oxlint/Plugin.ts +0 -71
  245. package/src/vendor/effect-oxlint/Rule.ts +0 -528
  246. package/src/vendor/effect-oxlint/RuleContext.ts +0 -144
  247. package/src/vendor/effect-oxlint/Scope.ts +0 -177
  248. package/src/vendor/effect-oxlint/SourceCode.ts +0 -377
  249. package/src/vendor/effect-oxlint/Testing.ts +0 -1227
  250. package/src/vendor/effect-oxlint/Token.ts +0 -131
  251. package/src/vendor/effect-oxlint/Visitor.ts +0 -287
  252. package/src/vendor/effect-oxlint/index.ts +0 -88
  253. package/tests/ban-rules.test.ts +0 -85
  254. package/tests/context-rules.test.ts +0 -198
  255. package/tests/pattern-rules.test.ts +0 -247
  256. package/tsconfig.json +0 -15
@@ -0,0 +1,36 @@
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 };
@@ -0,0 +1,6 @@
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 };
@@ -0,0 +1,75 @@
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 };
@@ -0,0 +1,6 @@
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 };
@@ -0,0 +1,54 @@
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 };
@@ -0,0 +1,6 @@
1
+ import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
+
3
+ //#region src/rules/no-globals.d.ts
4
+ declare const noGlobals: _$_oxlint_plugins0.CreateRule;
5
+ //#endregion
6
+ export { noGlobals };
@@ -0,0 +1,164 @@
1
+ import { calleeName, matchMember, 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 { 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 Option from "effect/Option";
9
+ import * as Effect from "effect/Effect";
10
+ import * as Ref from "effect/Ref";
11
+ //#region src/rules/no-globals.ts
12
+ const memberBans = [
13
+ [
14
+ "console",
15
+ [
16
+ "log",
17
+ "warn",
18
+ "error",
19
+ "info",
20
+ "debug",
21
+ "trace"
22
+ ],
23
+ "Avoid console.* inside Effect context. Use Effect.log / Effect.logWarning / Effect.logError."
24
+ ],
25
+ [
26
+ "Date",
27
+ "now",
28
+ "Avoid Date.now() inside Effect context. Use Clock service from 'effect'."
29
+ ],
30
+ [
31
+ "JSON",
32
+ ["parse", "stringify"],
33
+ "Avoid JSON.parse/stringify inside Effect context. Use Schema.fromJsonString."
34
+ ],
35
+ [
36
+ "Math",
37
+ "random",
38
+ "Avoid Math.random() inside Effect context. Use Random service from 'effect'."
39
+ ],
40
+ [
41
+ "crypto",
42
+ ["randomUUID", "getRandomValues"],
43
+ "Avoid crypto.randomUUID() inside Effect context. Use Random service from 'effect'."
44
+ ]
45
+ ];
46
+ const platformObjects = new Set([
47
+ "Bun",
48
+ "process",
49
+ "Deno"
50
+ ]);
51
+ const alternatives = {
52
+ Bun: {
53
+ file: "Use FileSystem from 'effect'",
54
+ write: "Use FileSystem from 'effect'",
55
+ read: "Use FileSystem from 'effect'",
56
+ serve: "Use HttpServer from 'effect/unstable/http'",
57
+ env: "Use Config from 'effect'",
58
+ spawn: "Use Command from 'effect'",
59
+ sleep: "Use Effect.sleep",
60
+ stdin: "Use Terminal from 'effect'",
61
+ stdout: "Use Terminal from 'effect'",
62
+ stderr: "Use Terminal from 'effect'",
63
+ cwd: "Use Path from 'effect'",
64
+ which: "Use Command from 'effect'",
65
+ resolveSync: "Use Path from 'effect'",
66
+ pathToFileURL: "Use Path from 'effect'",
67
+ randomUUID: "Use Random service from 'effect'",
68
+ randomUUIDv7: "Use Random service from 'effect'"
69
+ },
70
+ process: {
71
+ env: "Use Config from 'effect'",
72
+ exit: "Use Effect.fail or Effect.die",
73
+ cwd: "Use Path from 'effect'",
74
+ argv: "Use Args/Command from 'effect/unstable/cli'",
75
+ stdin: "Use Terminal from 'effect'",
76
+ stdout: "Use Terminal from 'effect'",
77
+ stderr: "Use Terminal from 'effect'",
78
+ chdir: "Use Path from 'effect'",
79
+ kill: "Use Command from 'effect'",
80
+ on: "Use Effect.async or Stream.async",
81
+ platform: "Use PlatformInfo from 'effect'",
82
+ arch: "Use PlatformInfo from 'effect'",
83
+ execPath: "Use Command from 'effect'",
84
+ execArgv: "Use Args/Command from 'effect/unstable/cli'"
85
+ },
86
+ Deno: {
87
+ readFile: "Use FileSystem from 'effect'",
88
+ writeFile: "Use FileSystem from 'effect'",
89
+ readTextFile: "Use FileSystem from 'effect'",
90
+ writeTextFile: "Use FileSystem from 'effect'",
91
+ open: "Use FileSystem from 'effect'",
92
+ remove: "Use FileSystem from 'effect'",
93
+ mkdir: "Use FileSystem from 'effect'",
94
+ readDir: "Use FileSystem from 'effect'",
95
+ stat: "Use FileSystem from 'effect'",
96
+ cwd: "Use Path from 'effect'",
97
+ env: "Use Config from 'effect'",
98
+ exit: "Use Effect.fail or Effect.die",
99
+ serve: "Use HttpServer from 'effect/unstable/http'",
100
+ run: "Use Command from 'effect'",
101
+ args: "Use Args/Command from 'effect/unstable/cli'"
102
+ }
103
+ };
104
+ function getHint(obj, prop) {
105
+ const hint = alternatives[obj]?.[prop];
106
+ if (hint) return `. ${hint}`;
107
+ return ". Wrap in a service for testability";
108
+ }
109
+ const callBans = {
110
+ fetch: "Avoid fetch() inside Effect context. Use HttpClient from 'effect/unstable/http'.",
111
+ setTimeout: "Avoid setTimeout inside Effect context. Use Effect.sleep or Schedule.",
112
+ setInterval: "Avoid setInterval inside Effect context. Use Effect.sleep or Schedule."
113
+ };
114
+ const noGlobals = define({
115
+ name: "no-globals",
116
+ meta: meta({
117
+ type: "suggestion",
118
+ description: "Avoid global/platform APIs inside Effect.gen/fn. Use Effect platform services instead."
119
+ }),
120
+ create: function* () {
121
+ const ctx = yield* RuleContext;
122
+ const [depth, tracker] = yield* makeEffectContextTracker;
123
+ return merge(tracker, {
124
+ MemberExpression: (node) => Effect.flatMap(Ref.get(depth), (d) => {
125
+ if (d <= 0) return Effect.void;
126
+ const memberNode = node;
127
+ for (const [obj, props, message] of memberBans) if (Option.isSome(matchMember(memberNode, obj, props))) return ctx.report(make({
128
+ node,
129
+ message
130
+ }));
131
+ const names = Option.getOrUndefined(memberNames(memberNode));
132
+ if (names !== void 0) {
133
+ const [obj, prop] = names;
134
+ if (platformObjects.has(obj)) return ctx.report(make({
135
+ node,
136
+ message: `Avoid ${obj}.${prop} inside Effect context${getHint(obj, prop)}.`
137
+ }));
138
+ }
139
+ return Effect.void;
140
+ }),
141
+ CallExpression: (node) => Effect.flatMap(Ref.get(depth), (d) => {
142
+ if (d <= 0) return Effect.void;
143
+ const name = Option.getOrUndefined(calleeName(node));
144
+ const message = name !== void 0 ? callBans[name] : void 0;
145
+ if (message !== void 0) return ctx.report(make({
146
+ node,
147
+ message
148
+ }));
149
+ return Effect.void;
150
+ }),
151
+ NewExpression: (node) => Effect.flatMap(Ref.get(depth), (d) => {
152
+ if (d <= 0) return Effect.void;
153
+ const callee = node["callee"];
154
+ if (callee.type === "Identifier" && "name" in callee && callee.name === "Date") return ctx.report(make({
155
+ node,
156
+ message: "Avoid new Date() inside Effect context. Use Clock service from 'effect'."
157
+ }));
158
+ return Effect.void;
159
+ })
160
+ });
161
+ }
162
+ });
163
+ //#endregion
164
+ export { noGlobals };
@@ -0,0 +1,6 @@
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 };
@@ -0,0 +1,18 @@
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 };
@@ -0,0 +1,6 @@
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 };
@@ -0,0 +1,37 @@
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 };
@@ -0,0 +1,6 @@
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 };
@@ -0,0 +1,31 @@
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 };
@@ -0,0 +1,6 @@
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 };
@@ -0,0 +1,35 @@
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 };
@@ -0,0 +1,6 @@
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 };
@@ -0,0 +1,40 @@
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 };
@@ -0,0 +1,6 @@
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 };
@@ -0,0 +1,64 @@
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-match-effect-branch.ts
8
+ const sequencingMethods = new Set([
9
+ "flatMap",
10
+ "map",
11
+ "andThen",
12
+ "tap",
13
+ "zipRight",
14
+ "pipe"
15
+ ]);
16
+ const containsEffectSequencing = (node) => {
17
+ if (node == null || typeof node !== "object") return false;
18
+ const n = node;
19
+ if (n["type"] === "CallExpression" && "callee" in n) {
20
+ const callee = n["callee"];
21
+ if (callee != null && callee["type"] === "MemberExpression") {
22
+ const obj = callee["object"];
23
+ const prop = callee["property"];
24
+ if (obj != null && obj["type"] === "Identifier" && obj["name"] === "Effect" && prop != null && prop["type"] === "Identifier" && typeof prop["name"] === "string" && sequencingMethods.has(prop["name"])) return true;
25
+ }
26
+ if ("arguments" in n && Array.isArray(n["arguments"])) {
27
+ for (const arg of n["arguments"]) if (containsEffectSequencing(arg)) return true;
28
+ }
29
+ }
30
+ if ("body" in n) {
31
+ if (Array.isArray(n["body"])) {
32
+ for (const child of n["body"]) if (containsEffectSequencing(child)) return true;
33
+ } else if (containsEffectSequencing(n["body"])) return true;
34
+ }
35
+ if ("argument" in n && containsEffectSequencing(n["argument"])) return true;
36
+ if ("expression" in n && containsEffectSequencing(n["expression"])) return true;
37
+ return false;
38
+ };
39
+ const noMatchEffectBranch = define({
40
+ name: "no-match-effect-branch",
41
+ meta: meta({
42
+ type: "suggestion",
43
+ description: "Avoid Effect sequencing inside Match branches. Select value in Match, run Effect outside."
44
+ }),
45
+ create: function* () {
46
+ const ctx = yield* RuleContext;
47
+ return { CallExpression: (node) => {
48
+ const ce = node;
49
+ const isMatchWhen = isCallOf(ce, "Match", "when");
50
+ const isMatchOrElse = isCallOf(ce, "Match", "orElse");
51
+ if (!isMatchWhen && !isMatchOrElse) return Effect.void;
52
+ if (!("arguments" in node) || !Array.isArray(node.arguments)) return Effect.void;
53
+ const callbackIdx = isMatchWhen ? 1 : 0;
54
+ const callback = node.arguments[callbackIdx];
55
+ if (callback != null && containsEffectSequencing(callback)) return ctx.report(make({
56
+ node,
57
+ message: "Avoid Effect sequencing inside Match branches. Select value in Match, then run one Effect pipeline outside."
58
+ }));
59
+ return Effect.void;
60
+ } };
61
+ }
62
+ });
63
+ //#endregion
64
+ export { noMatchEffectBranch };
@@ -0,0 +1,6 @@
1
+ import * as _$_oxlint_plugins0 from "@oxlint/plugins";
2
+
3
+ //#region src/rules/no-match-void-branch.d.ts
4
+ declare const noMatchVoidBranch: _$_oxlint_plugins0.CreateRule;
5
+ //#endregion
6
+ export { noMatchVoidBranch };