@effect/language-service 0.78.0 → 0.79.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.
@@ -1637,10 +1637,12 @@ var defaults = {
1637
1637
  extendedKeyDetection: false,
1638
1638
  ignoreEffectWarningsInTscExitCode: false,
1639
1639
  ignoreEffectSuggestionsInTscExitCode: true,
1640
+ ignoreEffectErrorsInTscExitCode: false,
1640
1641
  pipeableMinArgCount: 2,
1641
1642
  effectFn: ["span"],
1642
1643
  layerGraphFollowDepth: 0,
1643
- mermaidProvider: "mermaid.live"
1644
+ mermaidProvider: "mermaid.live",
1645
+ skipDisabledOptimization: false
1644
1646
  };
1645
1647
  function parseKeyPatterns(patterns) {
1646
1648
  const result = [];
@@ -1664,6 +1666,7 @@ function parse(config) {
1664
1666
  includeSuggestionsInTsc: isObject(config) && hasProperty(config, "includeSuggestionsInTsc") && isBoolean(config.includeSuggestionsInTsc) ? config.includeSuggestionsInTsc : defaults.includeSuggestionsInTsc,
1665
1667
  ignoreEffectWarningsInTscExitCode: isObject(config) && hasProperty(config, "ignoreEffectWarningsInTscExitCode") && isBoolean(config.ignoreEffectWarningsInTscExitCode) ? config.ignoreEffectWarningsInTscExitCode : defaults.ignoreEffectWarningsInTscExitCode,
1666
1668
  ignoreEffectSuggestionsInTscExitCode: isObject(config) && hasProperty(config, "ignoreEffectSuggestionsInTscExitCode") && isBoolean(config.ignoreEffectSuggestionsInTscExitCode) ? config.ignoreEffectSuggestionsInTscExitCode : defaults.ignoreEffectSuggestionsInTscExitCode,
1669
+ ignoreEffectErrorsInTscExitCode: isObject(config) && hasProperty(config, "ignoreEffectErrorsInTscExitCode") && isBoolean(config.ignoreEffectErrorsInTscExitCode) ? config.ignoreEffectErrorsInTscExitCode : defaults.ignoreEffectErrorsInTscExitCode,
1667
1670
  quickinfo: isObject(config) && hasProperty(config, "quickinfo") && isBoolean(config.quickinfo) ? config.quickinfo : defaults.quickinfo,
1668
1671
  quickinfoEffectParameters: isObject(config) && hasProperty(config, "quickinfoEffectParameters") && isString(config.quickinfoEffectParameters) && ["always", "never", "whentruncated"].includes(config.quickinfoEffectParameters.toLowerCase()) ? config.quickinfoEffectParameters.toLowerCase() : defaults.quickinfoEffectParameters,
1669
1672
  quickinfoMaximumLength: isObject(config) && hasProperty(config, "quickinfoMaximumLength") && isNumber(config.quickinfoMaximumLength) ? config.quickinfoMaximumLength : defaults.quickinfoMaximumLength,
@@ -1684,7 +1687,8 @@ function parse(config) {
1684
1687
  (_) => _.toLowerCase()
1685
1688
  ) : defaults.effectFn,
1686
1689
  layerGraphFollowDepth: isObject(config) && hasProperty(config, "layerGraphFollowDepth") && isNumber(config.layerGraphFollowDepth) ? config.layerGraphFollowDepth : defaults.layerGraphFollowDepth,
1687
- mermaidProvider: isObject(config) && hasProperty(config, "mermaidProvider") && isString(config.mermaidProvider) ? config.mermaidProvider : defaults.mermaidProvider
1690
+ mermaidProvider: isObject(config) && hasProperty(config, "mermaidProvider") && isString(config.mermaidProvider) ? config.mermaidProvider : defaults.mermaidProvider,
1691
+ skipDisabledOptimization: isObject(config) && hasProperty(config, "skipDisabledOptimization") && isBoolean(config.skipDisabledOptimization) ? config.skipDisabledOptimization : defaults.skipDisabledOptimization
1688
1692
  };
1689
1693
  }
1690
1694
 
@@ -2454,7 +2458,7 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
2454
2458
  if (skippedRules.indexOf(ruleNameLowered) > -1 || skippedRules.indexOf("*") > -1) {
2455
2459
  return { diagnostics: diagnostics2, codeFixes };
2456
2460
  }
2457
- if (defaultLevel === "off" && (lineOverrides[ruleNameLowered] || sectionOverrides[ruleNameLowered] || lineOverrides["*"] || sectionOverrides["*"] || []).length === 0) {
2461
+ if (!pluginOptions.skipDisabledOptimization && defaultLevel === "off" && (lineOverrides[ruleNameLowered] || sectionOverrides[ruleNameLowered] || lineOverrides["*"] || sectionOverrides["*"] || []).length === 0) {
2458
2462
  return { diagnostics: diagnostics2, codeFixes };
2459
2463
  }
2460
2464
  const fixByDisableNextLine = (node) => ({
@@ -5131,6 +5135,8 @@ var anyUnknownInErrorContext = createDiagnostic({
5131
5135
  code: 28,
5132
5136
  description: "Detects 'any' or 'unknown' types in Effect error or requirements channels",
5133
5137
  severity: "off",
5138
+ fixable: false,
5139
+ supportedEffect: ["v3", "v4"],
5134
5140
  apply: fn("anyUnknownInErrorContext.apply")(function* (sourceFile, report) {
5135
5141
  const ts = yield* service(TypeScriptApi);
5136
5142
  const typeChecker = yield* service(TypeCheckerApi);
@@ -5234,6 +5240,8 @@ var catchAllToMapError = createDiagnostic({
5234
5240
  code: 39,
5235
5241
  description: "Suggests using Effect.mapError instead of Effect.catchAll when the callback only wraps the error with Effect.fail",
5236
5242
  severity: "suggestion",
5243
+ fixable: true,
5244
+ supportedEffect: ["v3", "v4"],
5237
5245
  apply: fn("catchAllToMapError.apply")(function* (sourceFile, report) {
5238
5246
  const ts = yield* service(TypeScriptApi);
5239
5247
  const typeParser = yield* service(TypeParser);
@@ -5331,6 +5339,8 @@ var catchUnfailableEffect = createDiagnostic({
5331
5339
  code: 2,
5332
5340
  description: "Warns when using error handling on Effects that never fail (error type is 'never')",
5333
5341
  severity: "suggestion",
5342
+ fixable: false,
5343
+ supportedEffect: ["v3", "v4"],
5334
5344
  apply: fn("catchUnfailableEffect.apply")(function* (sourceFile, report) {
5335
5345
  const ts = yield* service(TypeScriptApi);
5336
5346
  const typeParser = yield* service(TypeParser);
@@ -5380,6 +5390,8 @@ var classSelfMismatch = createDiagnostic({
5380
5390
  code: 20,
5381
5391
  description: "Ensures Self type parameter matches the class name in Service/Tag/Schema classes",
5382
5392
  severity: "error",
5393
+ fixable: true,
5394
+ supportedEffect: ["v3", "v4"],
5383
5395
  apply: fn("classSelfMismatch.apply")(function* (sourceFile, report) {
5384
5396
  const ts = yield* service(TypeScriptApi);
5385
5397
  const typeParser = yield* service(TypeParser);
@@ -5518,6 +5530,8 @@ var deterministicKeys = createDiagnostic({
5518
5530
  code: 25,
5519
5531
  description: "Enforces deterministic naming for service/tag/error identifiers based on class names",
5520
5532
  severity: "off",
5533
+ fixable: true,
5534
+ supportedEffect: ["v3", "v4"],
5521
5535
  apply: fn("deterministicKeys.apply")(function* (sourceFile, report) {
5522
5536
  const ts = yield* service(TypeScriptApi);
5523
5537
  const typeParser = yield* service(TypeParser);
@@ -5635,6 +5649,8 @@ var duplicatePackage = createDiagnostic({
5635
5649
  code: 6,
5636
5650
  description: "Detects when multiple versions of the same Effect package are loaded",
5637
5651
  severity: "warning",
5652
+ fixable: false,
5653
+ supportedEffect: ["v3", "v4"],
5638
5654
  apply: fn("duplicatePackage.apply")(function* (sourceFile, report) {
5639
5655
  const typeParser = yield* service(TypeParser);
5640
5656
  const options = yield* service(LanguageServicePluginOptions);
@@ -5664,6 +5680,8 @@ var effectFnIife = createDiagnostic({
5664
5680
  code: 46,
5665
5681
  description: "Effect.fn or Effect.fnUntraced is called as an IIFE (Immediately Invoked Function Expression). Use Effect.gen instead.",
5666
5682
  severity: "warning",
5683
+ fixable: true,
5684
+ supportedEffect: ["v3", "v4"],
5667
5685
  apply: fn("effectFnIife.apply")(function* (sourceFile, report) {
5668
5686
  const ts = yield* service(TypeScriptApi);
5669
5687
  const typeParser = yield* service(TypeParser);
@@ -5766,6 +5784,8 @@ var effectFnOpportunity = createDiagnostic({
5766
5784
  code: 41,
5767
5785
  description: "Suggests using Effect.fn for functions that returns an Effect",
5768
5786
  severity: "suggestion",
5787
+ fixable: true,
5788
+ supportedEffect: ["v3", "v4"],
5769
5789
  apply: fn("effectFnOpportunity.apply")(function* (sourceFile, report) {
5770
5790
  const ts = yield* service(TypeScriptApi);
5771
5791
  const typeChecker = yield* service(TypeCheckerApi);
@@ -6358,6 +6378,8 @@ var effectGenUsesAdapter = createDiagnostic({
6358
6378
  code: 23,
6359
6379
  description: "Warns when using the deprecated adapter parameter in Effect.gen",
6360
6380
  severity: "warning",
6381
+ fixable: false,
6382
+ supportedEffect: ["v3", "v4"],
6361
6383
  apply: fn("effectGenUsesAdapter.apply")(function* (sourceFile, report) {
6362
6384
  const ts = yield* service(TypeScriptApi);
6363
6385
  const typeParser = yield* service(TypeParser);
@@ -6396,6 +6418,8 @@ var effectInFailure = createDiagnostic({
6396
6418
  code: 49,
6397
6419
  description: "Warns when an Effect is used inside an Effect failure channel",
6398
6420
  severity: "warning",
6421
+ fixable: false,
6422
+ supportedEffect: ["v3", "v4"],
6399
6423
  apply: fn("effectInFailure.apply")(function* (sourceFile, report) {
6400
6424
  const ts = yield* service(TypeScriptApi);
6401
6425
  const typeChecker = yield* service(TypeCheckerApi);
@@ -6460,6 +6484,8 @@ var effectInVoidSuccess = createDiagnostic({
6460
6484
  code: 14,
6461
6485
  description: "Detects nested Effects in void success channels that may cause unexecuted effects",
6462
6486
  severity: "warning",
6487
+ fixable: false,
6488
+ supportedEffect: ["v3", "v4"],
6463
6489
  apply: fn("effectInVoidSuccess.apply")(function* (sourceFile, report) {
6464
6490
  const ts = yield* service(TypeScriptApi);
6465
6491
  const typeChecker = yield* service(TypeCheckerApi);
@@ -6509,6 +6535,8 @@ var effectMapVoid = createDiagnostic({
6509
6535
  code: 40,
6510
6536
  description: "Suggests using Effect.asVoid instead of Effect.map(() => void 0), Effect.map(() => undefined), or Effect.map(() => {})",
6511
6537
  severity: "suggestion",
6538
+ fixable: true,
6539
+ supportedEffect: ["v3", "v4"],
6512
6540
  apply: fn("effectMapVoid.apply")(function* (sourceFile, report) {
6513
6541
  const ts = yield* service(TypeScriptApi);
6514
6542
  const typeParser = yield* service(TypeParser);
@@ -6573,6 +6601,8 @@ var effectSucceedWithVoid = createDiagnostic({
6573
6601
  code: 47,
6574
6602
  description: "Suggests using Effect.void instead of Effect.succeed(undefined) or Effect.succeed(void 0)",
6575
6603
  severity: "suggestion",
6604
+ fixable: true,
6605
+ supportedEffect: ["v3", "v4"],
6576
6606
  apply: fn("effectSucceedWithVoid.apply")(function* (sourceFile, report) {
6577
6607
  const ts = yield* service(TypeScriptApi);
6578
6608
  const typeParser = yield* service(TypeParser);
@@ -6618,12 +6648,66 @@ var effectSucceedWithVoid = createDiagnostic({
6618
6648
  })
6619
6649
  });
6620
6650
 
6651
+ // src/diagnostics/extendsNativeError.ts
6652
+ var extendsNativeError = createDiagnostic({
6653
+ name: "extendsNativeError",
6654
+ code: 50,
6655
+ description: "Warns when a class directly extends the native Error class",
6656
+ severity: "off",
6657
+ fixable: false,
6658
+ supportedEffect: ["v3", "v4"],
6659
+ apply: fn("extendsNativeError.apply")(function* (sourceFile, report) {
6660
+ const ts = yield* service(TypeScriptApi);
6661
+ const typeChecker = yield* service(TypeCheckerApi);
6662
+ const errorSymbol = typeChecker.resolveName("Error", void 0, ts.SymbolFlags.Type, false);
6663
+ if (!errorSymbol) return;
6664
+ const nodeToVisit = [];
6665
+ const appendNodeToVisit = (node) => {
6666
+ nodeToVisit.push(node);
6667
+ return void 0;
6668
+ };
6669
+ ts.forEachChild(sourceFile, appendNodeToVisit);
6670
+ while (nodeToVisit.length > 0) {
6671
+ const node = nodeToVisit.shift();
6672
+ if (ts.isClassDeclaration(node) && node.heritageClauses) {
6673
+ for (const clause of node.heritageClauses) {
6674
+ if (clause.token === ts.SyntaxKind.ExtendsKeyword && clause.types.length > 0) {
6675
+ const typeExpression = clause.types[0].expression;
6676
+ const exprSymbol = typeChecker.getSymbolAtLocation(typeExpression);
6677
+ const resolvedSymbol = exprSymbol && exprSymbol.flags & ts.SymbolFlags.Alias ? typeChecker.getAliasedSymbol(exprSymbol) : exprSymbol;
6678
+ const isNativeError = resolvedSymbol === errorSymbol || (() => {
6679
+ if (!resolvedSymbol || resolvedSymbol === errorSymbol) return false;
6680
+ const exprType = typeChecker.getTypeAtLocation(typeExpression);
6681
+ const constructSignatures = typeChecker.getSignaturesOfType(exprType, ts.SignatureKind.Construct);
6682
+ if (constructSignatures.length > 0) {
6683
+ const instanceType = typeChecker.getReturnTypeOfSignature(constructSignatures[0]);
6684
+ return instanceType.symbol === errorSymbol;
6685
+ }
6686
+ return false;
6687
+ })();
6688
+ if (isNativeError) {
6689
+ report({
6690
+ location: node.name ?? typeExpression,
6691
+ messageText: "Avoid extending the native 'Error' class directly. Consider using a tagged error (e.g. Data.TaggedError) to maintain type safety in the Effect failure channel.",
6692
+ fixes: []
6693
+ });
6694
+ }
6695
+ }
6696
+ }
6697
+ }
6698
+ ts.forEachChild(node, appendNodeToVisit);
6699
+ }
6700
+ })
6701
+ });
6702
+
6621
6703
  // src/diagnostics/floatingEffect.ts
6622
6704
  var floatingEffect = createDiagnostic({
6623
6705
  name: "floatingEffect",
6624
6706
  code: 3,
6625
6707
  description: "Ensures Effects are yielded or assigned to variables, not left floating",
6626
6708
  severity: "error",
6709
+ fixable: false,
6710
+ supportedEffect: ["v3", "v4"],
6627
6711
  apply: fn("floatingEffect.apply")(function* (sourceFile, report) {
6628
6712
  const ts = yield* service(TypeScriptApi);
6629
6713
  const typeChecker = yield* service(TypeCheckerApi);
@@ -6675,6 +6759,8 @@ var genericEffectServices = createDiagnostic({
6675
6759
  code: 10,
6676
6760
  description: "Prevents services with type parameters that cannot be discriminated at runtime",
6677
6761
  severity: "warning",
6762
+ fixable: false,
6763
+ supportedEffect: ["v3", "v4"],
6678
6764
  apply: fn("genericEffectServices.apply")(function* (sourceFile, report) {
6679
6765
  const ts = yield* service(TypeScriptApi);
6680
6766
  const typeParser = yield* service(TypeParser);
@@ -6722,6 +6808,8 @@ var globalErrorInEffectCatch = createDiagnostic({
6722
6808
  code: 36,
6723
6809
  description: "Warns when catch callbacks return global Error type instead of typed errors",
6724
6810
  severity: "warning",
6811
+ fixable: false,
6812
+ supportedEffect: ["v3", "v4"],
6725
6813
  apply: fn("globalErrorInEffectCatch.apply")(function* (sourceFile, report) {
6726
6814
  const ts = yield* service(TypeScriptApi);
6727
6815
  const typeParser = yield* service(TypeParser);
@@ -6782,6 +6870,8 @@ var globalErrorInEffectFailure = createDiagnostic({
6782
6870
  code: 35,
6783
6871
  description: "Warns when the global Error type is used in an Effect failure channel",
6784
6872
  severity: "warning",
6873
+ fixable: false,
6874
+ supportedEffect: ["v3", "v4"],
6785
6875
  apply: fn("globalErrorInEffectFailure.apply")(function* (sourceFile, report) {
6786
6876
  const ts = yield* service(TypeScriptApi);
6787
6877
  const typeParser = yield* service(TypeParser);
@@ -6835,6 +6925,8 @@ var importFromBarrel = createDiagnostic({
6835
6925
  code: 12,
6836
6926
  description: "Suggests importing from specific module paths instead of barrel exports",
6837
6927
  severity: "off",
6928
+ fixable: true,
6929
+ supportedEffect: ["v3", "v4"],
6838
6930
  apply: fn("importFromBarrel.apply")(function* (sourceFile, report) {
6839
6931
  const languageServicePluginOptions = yield* service(LanguageServicePluginOptions);
6840
6932
  if (languageServicePluginOptions.namespaceImportPackages.length === 0) return;
@@ -6975,6 +7067,8 @@ var instanceOfSchema = createDiagnostic({
6975
7067
  code: 45,
6976
7068
  description: "Suggests using Schema.is instead of instanceof for Effect Schema types",
6977
7069
  severity: "off",
7070
+ fixable: true,
7071
+ supportedEffect: ["v3", "v4"],
6978
7072
  apply: fn("instanceOfSchema.apply")(function* (sourceFile, report) {
6979
7073
  const ts = yield* service(TypeScriptApi);
6980
7074
  const typeParser = yield* service(TypeParser);
@@ -7038,6 +7132,8 @@ var layerMergeAllWithDependencies = createDiagnostic({
7038
7132
  code: 37,
7039
7133
  description: "Detects interdependencies in Layer.mergeAll calls where one layer provides a service that another layer requires",
7040
7134
  severity: "warning",
7135
+ fixable: true,
7136
+ supportedEffect: ["v3", "v4"],
7041
7137
  apply: fn("layerMergeAllWithDependencies.apply")(function* (sourceFile, report) {
7042
7138
  const ts = yield* service(TypeScriptApi);
7043
7139
  const typeChecker = yield* service(TypeCheckerApi);
@@ -7151,6 +7247,8 @@ var leakingRequirements = createDiagnostic({
7151
7247
  code: 8,
7152
7248
  description: "Detects implementation services leaked in service methods",
7153
7249
  severity: "suggestion",
7250
+ fixable: false,
7251
+ supportedEffect: ["v3", "v4"],
7154
7252
  apply: fn("leakingRequirements.apply")(function* (sourceFile, report) {
7155
7253
  const ts = yield* service(TypeScriptApi);
7156
7254
  const typeChecker = yield* service(TypeCheckerApi);
@@ -7305,6 +7403,8 @@ var missedPipeableOpportunity = createDiagnostic({
7305
7403
  code: 26,
7306
7404
  description: "Enforces the use of pipeable style for nested function calls",
7307
7405
  severity: "off",
7406
+ fixable: true,
7407
+ supportedEffect: ["v3", "v4"],
7308
7408
  apply: fn("missedPipeableOpportunity.apply")(function* (sourceFile, report) {
7309
7409
  const ts = yield* service(TypeScriptApi);
7310
7410
  const typeChecker = yield* service(TypeCheckerApi);
@@ -7485,6 +7585,8 @@ var missingEffectContext = createDiagnostic({
7485
7585
  code: 1,
7486
7586
  description: "Reports missing service requirements in Effect context channel",
7487
7587
  severity: "error",
7588
+ fixable: false,
7589
+ supportedEffect: ["v3", "v4"],
7488
7590
  apply: fn("missingEffectContext.apply")(function* (sourceFile, report) {
7489
7591
  const typeChecker = yield* service(TypeCheckerApi);
7490
7592
  const typeParser = yield* service(TypeParser);
@@ -7534,6 +7636,8 @@ var missingEffectError = createDiagnostic({
7534
7636
  code: 1,
7535
7637
  description: "Reports missing error types in Effect error channel",
7536
7638
  severity: "error",
7639
+ fixable: true,
7640
+ supportedEffect: ["v3", "v4"],
7537
7641
  apply: fn("missingEffectError.apply")(function* (sourceFile, report) {
7538
7642
  const ts = yield* service(TypeScriptApi);
7539
7643
  const tsUtils = yield* service(TypeScriptUtils);
@@ -7675,6 +7779,8 @@ var missingEffectServiceDependency = createDiagnostic({
7675
7779
  code: 22,
7676
7780
  description: "Checks that Effect.Service dependencies satisfy all required layer inputs",
7677
7781
  severity: "off",
7782
+ fixable: false,
7783
+ supportedEffect: ["v3"],
7678
7784
  apply: fn("missingEffectServiceDependency.apply")(function* (sourceFile, report) {
7679
7785
  const ts = yield* service(TypeScriptApi);
7680
7786
  const typeChecker = yield* service(TypeCheckerApi);
@@ -7769,6 +7875,8 @@ var missingLayerContext = createDiagnostic({
7769
7875
  code: 38,
7770
7876
  description: "Reports missing service requirements in Layer context channel",
7771
7877
  severity: "error",
7878
+ fixable: false,
7879
+ supportedEffect: ["v3", "v4"],
7772
7880
  apply: fn("missingLayerContext.apply")(function* (sourceFile, report) {
7773
7881
  const typeChecker = yield* service(TypeCheckerApi);
7774
7882
  const typeParser = yield* service(TypeParser);
@@ -7818,6 +7926,8 @@ var missingReturnYieldStar = createDiagnostic({
7818
7926
  code: 7,
7819
7927
  description: "Suggests using 'return yield*' for Effects with never success for better type narrowing",
7820
7928
  severity: "error",
7929
+ fixable: true,
7930
+ supportedEffect: ["v3", "v4"],
7821
7931
  apply: fn("missingReturnYieldStar.apply")(function* (sourceFile, report) {
7822
7932
  const ts = yield* service(TypeScriptApi);
7823
7933
  const typeCheckerUtils = yield* service(TypeCheckerUtils);
@@ -7868,6 +7978,8 @@ var missingStarInYieldEffectGen = createDiagnostic({
7868
7978
  code: 4,
7869
7979
  description: "Enforces using 'yield*' instead of 'yield' when yielding Effects in generators",
7870
7980
  severity: "error",
7981
+ fixable: true,
7982
+ supportedEffect: ["v3", "v4"],
7871
7983
  apply: fn("missingStarInYieldEffectGen.apply")(function* (sourceFile, report) {
7872
7984
  const ts = yield* service(TypeScriptApi);
7873
7985
  const typeParser = yield* service(TypeParser);
@@ -7943,6 +8055,8 @@ var multipleEffectProvide = createDiagnostic({
7943
8055
  code: 18,
7944
8056
  description: "Warns against chaining Effect.provide calls which can cause service lifecycle issues",
7945
8057
  severity: "warning",
8058
+ fixable: true,
8059
+ supportedEffect: ["v3", "v4"],
7946
8060
  apply: fn("multipleEffectProvide.apply")(function* (sourceFile, report) {
7947
8061
  const ts = yield* service(TypeScriptApi);
7948
8062
  const tsUtils = yield* service(TypeScriptUtils);
@@ -8029,12 +8143,85 @@ var multipleEffectProvide = createDiagnostic({
8029
8143
  })
8030
8144
  });
8031
8145
 
8146
+ // src/diagnostics/nodeBuiltinImport.ts
8147
+ var moduleAlternativesV3 = /* @__PURE__ */ new Map([
8148
+ ["fs", { alternative: "FileSystem", module: "fs", package: "@effect/platform" }],
8149
+ ["node:fs", { alternative: "FileSystem", module: "fs", package: "@effect/platform" }],
8150
+ ["fs/promises", { alternative: "FileSystem", module: "fs", package: "@effect/platform" }],
8151
+ ["node:fs/promises", { alternative: "FileSystem", module: "fs", package: "@effect/platform" }],
8152
+ ["path", { alternative: "Path", module: "path", package: "@effect/platform" }],
8153
+ ["node:path", { alternative: "Path", module: "path", package: "@effect/platform" }],
8154
+ ["path/posix", { alternative: "Path", module: "path", package: "@effect/platform" }],
8155
+ ["node:path/posix", { alternative: "Path", module: "path", package: "@effect/platform" }],
8156
+ ["path/win32", { alternative: "Path", module: "path", package: "@effect/platform" }],
8157
+ ["node:path/win32", { alternative: "Path", module: "path", package: "@effect/platform" }],
8158
+ ["child_process", { alternative: "CommandExecutor", module: "child_process", package: "@effect/platform" }],
8159
+ ["node:child_process", { alternative: "CommandExecutor", module: "child_process", package: "@effect/platform" }]
8160
+ ]);
8161
+ var moduleAlternativesV4 = /* @__PURE__ */ new Map([
8162
+ ["fs", { alternative: "FileSystem", module: "fs", package: "effect" }],
8163
+ ["node:fs", { alternative: "FileSystem", module: "fs", package: "effect" }],
8164
+ ["fs/promises", { alternative: "FileSystem", module: "fs", package: "effect" }],
8165
+ ["node:fs/promises", { alternative: "FileSystem", module: "fs", package: "effect" }],
8166
+ ["path", { alternative: "Path", module: "path", package: "effect" }],
8167
+ ["node:path", { alternative: "Path", module: "path", package: "effect" }],
8168
+ ["path/posix", { alternative: "Path", module: "path", package: "effect" }],
8169
+ ["node:path/posix", { alternative: "Path", module: "path", package: "effect" }],
8170
+ ["path/win32", { alternative: "Path", module: "path", package: "effect" }],
8171
+ ["node:path/win32", { alternative: "Path", module: "path", package: "effect" }],
8172
+ ["child_process", { alternative: "ChildProcess", module: "child_process", package: "effect" }],
8173
+ ["node:child_process", { alternative: "ChildProcess", module: "child_process", package: "effect" }]
8174
+ ]);
8175
+ var nodeBuiltinImport = createDiagnostic({
8176
+ name: "nodeBuiltinImport",
8177
+ code: 52,
8178
+ description: "Warns when importing Node.js built-in modules that have Effect-native counterparts",
8179
+ severity: "off",
8180
+ fixable: false,
8181
+ supportedEffect: ["v3", "v4"],
8182
+ apply: fn("nodeBuiltinImport.apply")(function* (sourceFile, report) {
8183
+ const ts = yield* service(TypeScriptApi);
8184
+ const typeParser = yield* service(TypeParser);
8185
+ const moduleAlternatives = typeParser.supportedEffect() === "v3" ? moduleAlternativesV3 : moduleAlternativesV4;
8186
+ for (const statement of sourceFile.statements) {
8187
+ if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {
8188
+ const specifier = statement.moduleSpecifier.text;
8189
+ const match2 = moduleAlternatives.get(specifier);
8190
+ if (match2) {
8191
+ report({
8192
+ location: statement.moduleSpecifier,
8193
+ messageText: `Prefer using ${match2.alternative} from ${match2.package} instead of the Node.js '${match2.module}' module.`,
8194
+ fixes: []
8195
+ });
8196
+ }
8197
+ } else if (ts.isVariableStatement(statement)) {
8198
+ for (const decl of statement.declarationList.declarations) {
8199
+ if (decl.initializer && ts.isCallExpression(decl.initializer) && ts.isIdentifier(decl.initializer.expression) && ts.idText(decl.initializer.expression) === "require" && decl.initializer.arguments.length === 1 && ts.isStringLiteral(decl.initializer.arguments[0])) {
8200
+ const arg = decl.initializer.arguments[0];
8201
+ const specifier = arg.text;
8202
+ const match2 = moduleAlternatives.get(specifier);
8203
+ if (match2) {
8204
+ report({
8205
+ location: arg,
8206
+ messageText: `Prefer using ${match2.alternative} from ${match2.package} instead of the Node.js '${match2.module}' module.`,
8207
+ fixes: []
8208
+ });
8209
+ }
8210
+ }
8211
+ }
8212
+ }
8213
+ }
8214
+ })
8215
+ });
8216
+
8032
8217
  // src/diagnostics/nonObjectEffectServiceType.ts
8033
8218
  var nonObjectEffectServiceType = createDiagnostic({
8034
8219
  name: "nonObjectEffectServiceType",
8035
8220
  code: 24,
8036
8221
  description: "Ensures Effect.Service types are objects, not primitives",
8037
8222
  severity: "error",
8223
+ fixable: false,
8224
+ supportedEffect: ["v3"],
8038
8225
  apply: fn("nonObjectEffectServiceType.apply")(function* (sourceFile, report) {
8039
8226
  const ts = yield* service(TypeScriptApi);
8040
8227
  const typeChecker = yield* service(TypeCheckerApi);
@@ -8817,6 +9004,8 @@ var outdatedApi = createDiagnostic({
8817
9004
  code: 48,
8818
9005
  description: "Detects usage of APIs that have been removed or renamed in Effect v4",
8819
9006
  severity: "warning",
9007
+ fixable: false,
9008
+ supportedEffect: ["v4"],
8820
9009
  apply: fn("outdatedApi.apply")(function* (sourceFile, report) {
8821
9010
  const typeParser = yield* service(TypeParser);
8822
9011
  const ts = yield* service(TypeScriptApi);
@@ -9953,6 +10142,8 @@ var outdatedEffectCodegen = createDiagnostic({
9953
10142
  code: 19,
9954
10143
  description: "Detects when generated code is outdated and needs to be regenerated",
9955
10144
  severity: "warning",
10145
+ fixable: true,
10146
+ supportedEffect: ["v3", "v4"],
9956
10147
  apply: fn("outdatedEffectCodegen.apply")(function* (sourceFile, _report) {
9957
10148
  const codegensWithRanges = yield* getCodegensForSourceFile(codegens, sourceFile);
9958
10149
  for (const { codegen, hash: hash2, range } of codegensWithRanges) {
@@ -9999,6 +10190,8 @@ var overriddenSchemaConstructor = createDiagnostic({
9999
10190
  code: 30,
10000
10191
  description: "Prevents overriding constructors in Schema classes which breaks decoding behavior",
10001
10192
  severity: "error",
10193
+ fixable: true,
10194
+ supportedEffect: ["v3", "v4"],
10002
10195
  apply: fn("overriddenSchemaConstructor.apply")(function* (sourceFile, report) {
10003
10196
  const ts = yield* service(TypeScriptApi);
10004
10197
  const typeParser = yield* service(TypeParser);
@@ -10136,6 +10329,8 @@ var preferSchemaOverJson = createDiagnostic({
10136
10329
  code: 44,
10137
10330
  description: "Suggests using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify which may throw",
10138
10331
  severity: "suggestion",
10332
+ fixable: false,
10333
+ supportedEffect: ["v3", "v4"],
10139
10334
  apply: fn("preferSchemaOverJson.apply")(function* (sourceFile, report) {
10140
10335
  const ts = yield* service(TypeScriptApi);
10141
10336
  const typeParser = yield* service(TypeParser);
@@ -10246,6 +10441,8 @@ var redundantSchemaTagIdentifier = createDiagnostic({
10246
10441
  code: 42,
10247
10442
  description: "Suggests removing redundant identifier argument when it equals the tag value in Schema.TaggedClass/TaggedError/TaggedRequest",
10248
10443
  severity: "suggestion",
10444
+ fixable: true,
10445
+ supportedEffect: ["v3", "v4"],
10249
10446
  apply: fn("redundantSchemaTagIdentifier.apply")(function* (sourceFile, report) {
10250
10447
  const ts = yield* service(TypeScriptApi);
10251
10448
  const typeParser = yield* service(TypeParser);
@@ -10296,6 +10493,8 @@ var returnEffectInGen = createDiagnostic({
10296
10493
  code: 11,
10297
10494
  description: "Warns when returning an Effect in a generator causes nested Effect<Effect<...>>",
10298
10495
  severity: "suggestion",
10496
+ fixable: true,
10497
+ supportedEffect: ["v3", "v4"],
10299
10498
  apply: fn("returnEffectInGen.apply")(function* (sourceFile, report) {
10300
10499
  const ts = yield* service(TypeScriptApi);
10301
10500
  const typeCheckerUtils = yield* service(TypeCheckerUtils);
@@ -10365,6 +10564,8 @@ var runEffectInsideEffect = createDiagnostic({
10365
10564
  code: 32,
10366
10565
  description: "Suggests using Runtime methods instead of Effect.run* inside Effect contexts",
10367
10566
  severity: "suggestion",
10567
+ fixable: true,
10568
+ supportedEffect: ["v3"],
10368
10569
  apply: fn("runEffectInsideEffect.apply")(function* (sourceFile, report) {
10369
10570
  const ts = yield* service(TypeScriptApi);
10370
10571
  const typeParser = yield* service(TypeParser);
@@ -10489,6 +10690,8 @@ var schemaStructWithTag = createDiagnostic({
10489
10690
  code: 34,
10490
10691
  description: "Suggests using Schema.TaggedStruct instead of Schema.Struct with _tag field",
10491
10692
  severity: "suggestion",
10693
+ fixable: true,
10694
+ supportedEffect: ["v3", "v4"],
10492
10695
  apply: fn("schemaStructWithTag.apply")(function* (sourceFile, report) {
10493
10696
  const ts = yield* service(TypeScriptApi);
10494
10697
  const typeParser = yield* service(TypeParser);
@@ -10581,6 +10784,8 @@ var schemaSyncInEffect = createDiagnostic({
10581
10784
  code: 43,
10582
10785
  description: "Suggests using Effect-based Schema methods instead of sync methods inside Effect generators",
10583
10786
  severity: "suggestion",
10787
+ fixable: false,
10788
+ supportedEffect: ["v3", "v4"],
10584
10789
  apply: fn("schemaSyncInEffect.apply")(function* (sourceFile, report) {
10585
10790
  const ts = yield* service(TypeScriptApi);
10586
10791
  const typeParser = yield* service(TypeParser);
@@ -10630,6 +10835,8 @@ var schemaUnionOfLiterals = createDiagnostic({
10630
10835
  code: 33,
10631
10836
  description: "Simplifies Schema.Union of multiple Schema.Literal calls into single Schema.Literal",
10632
10837
  severity: "off",
10838
+ fixable: true,
10839
+ supportedEffect: ["v3"],
10633
10840
  apply: fn("schemaUnionOfLiterals.apply")(function* (sourceFile, report) {
10634
10841
  const ts = yield* service(TypeScriptApi);
10635
10842
  const typeParser = yield* service(TypeParser);
@@ -10705,6 +10912,8 @@ var scopeInLayerEffect = createDiagnostic({
10705
10912
  code: 13,
10706
10913
  description: "Suggests using Layer.scoped instead of Layer.effect when Scope is in requirements",
10707
10914
  severity: "warning",
10915
+ fixable: true,
10916
+ supportedEffect: ["v3"],
10708
10917
  apply: fn("scopeInLayerEffect.apply")(function* (sourceFile, report) {
10709
10918
  const ts = yield* service(TypeScriptApi);
10710
10919
  const tsUtils = yield* service(TypeScriptUtils);
@@ -10794,12 +11003,91 @@ Consider using "scoped" instead to get rid of the scope in the requirements.`,
10794
11003
  })
10795
11004
  });
10796
11005
 
11006
+ // src/diagnostics/serviceNotAsClass.ts
11007
+ var serviceNotAsClass = createDiagnostic({
11008
+ name: "serviceNotAsClass",
11009
+ code: 51,
11010
+ description: "Warns when ServiceMap.Service is used as a variable instead of a class declaration",
11011
+ severity: "off",
11012
+ fixable: true,
11013
+ supportedEffect: ["v4"],
11014
+ apply: fn("serviceNotAsClass.apply")(function* (sourceFile, report) {
11015
+ const ts = yield* service(TypeScriptApi);
11016
+ const typeParser = yield* service(TypeParser);
11017
+ if (typeParser.supportedEffect() === "v3") return;
11018
+ const nodeToVisit = [];
11019
+ const appendNodeToVisit = (node) => {
11020
+ nodeToVisit.push(node);
11021
+ return void 0;
11022
+ };
11023
+ ts.forEachChild(sourceFile, appendNodeToVisit);
11024
+ while (nodeToVisit.length > 0) {
11025
+ const node = nodeToVisit.shift();
11026
+ ts.forEachChild(node, appendNodeToVisit);
11027
+ if (!ts.isVariableDeclaration(node)) continue;
11028
+ if (!node.initializer || !ts.isCallExpression(node.initializer)) continue;
11029
+ const callExpr = node.initializer;
11030
+ if (!callExpr.typeArguments || callExpr.typeArguments.length === 0) continue;
11031
+ const typeArgs = callExpr.typeArguments;
11032
+ const declList = node.parent;
11033
+ if (!ts.isVariableDeclarationList(declList)) continue;
11034
+ if (!(declList.flags & ts.NodeFlags.Const)) continue;
11035
+ const isServiceMapService = yield* pipe(
11036
+ typeParser.isNodeReferenceToServiceMapModuleApi("Service")(callExpr.expression),
11037
+ orUndefined
11038
+ );
11039
+ if (!isServiceMapService) continue;
11040
+ const variableName = ts.isIdentifier(node.name) ? ts.idText(node.name) : sourceFile.text.substring(ts.getTokenPosOfNode(node.name, sourceFile), node.name.end);
11041
+ const variableStatement = declList.parent;
11042
+ const argsText = callExpr.arguments.length > 0 ? callExpr.arguments.map((a) => sourceFile.text.substring(ts.getTokenPosOfNode(a, sourceFile), a.end)).join(", ") : "";
11043
+ const shapeText = typeArgs.length > 0 ? typeArgs.map((t) => sourceFile.text.substring(ts.getTokenPosOfNode(t, sourceFile), t.end)).join(", ") : "Shape";
11044
+ report({
11045
+ location: callExpr,
11046
+ messageText: `ServiceMap.Service should be used in a class declaration instead of as a variable. Use: class ${variableName} extends ServiceMap.Service<${variableName}, ${shapeText}>()("${argsText.replace(/['"]/g, "")}") {}`,
11047
+ fixes: [{
11048
+ fixName: "serviceNotAsClass",
11049
+ description: `Convert to class declaration`,
11050
+ apply: gen(function* () {
11051
+ const changeTracker = yield* service(ChangeTracker);
11052
+ const targetNode = ts.isVariableStatement(variableStatement) ? variableStatement : declList;
11053
+ const innerCall = ts.factory.createCallExpression(
11054
+ callExpr.expression,
11055
+ [ts.factory.createTypeReferenceNode(variableName), ...typeArgs],
11056
+ []
11057
+ );
11058
+ const outerCall = ts.factory.createCallExpression(
11059
+ innerCall,
11060
+ void 0,
11061
+ [...callExpr.arguments]
11062
+ );
11063
+ const heritageClause = ts.factory.createHeritageClause(
11064
+ ts.SyntaxKind.ExtendsKeyword,
11065
+ [ts.factory.createExpressionWithTypeArguments(outerCall, void 0)]
11066
+ );
11067
+ const modifiers = ts.isVariableStatement(variableStatement) ? variableStatement.modifiers : void 0;
11068
+ const classDeclaration = ts.factory.createClassDeclaration(
11069
+ modifiers,
11070
+ ts.isIdentifier(node.name) ? node.name : ts.factory.createIdentifier(variableName),
11071
+ void 0,
11072
+ [heritageClause],
11073
+ []
11074
+ );
11075
+ changeTracker.replaceNode(sourceFile, targetNode, classDeclaration);
11076
+ })
11077
+ }]
11078
+ });
11079
+ }
11080
+ })
11081
+ });
11082
+
10797
11083
  // src/diagnostics/strictBooleanExpressions.ts
10798
11084
  var strictBooleanExpressions = createDiagnostic({
10799
11085
  name: "strictBooleanExpressions",
10800
11086
  code: 17,
10801
11087
  description: "Enforces boolean types in conditional expressions for type safety",
10802
11088
  severity: "off",
11089
+ fixable: false,
11090
+ supportedEffect: ["v3", "v4"],
10803
11091
  apply: fn("strictBooleanExpressions.apply")(function* (sourceFile, report) {
10804
11092
  const ts = yield* service(TypeScriptApi);
10805
11093
  const typeChecker = yield* service(TypeCheckerApi);
@@ -10871,6 +11159,8 @@ var strictEffectProvide = createDiagnostic({
10871
11159
  code: 27,
10872
11160
  description: "Warns when using Effect.provide with layers outside of application entry points",
10873
11161
  severity: "off",
11162
+ fixable: false,
11163
+ supportedEffect: ["v3", "v4"],
10874
11164
  apply: fn("strictEffectProvide.apply")(function* (sourceFile, report) {
10875
11165
  const ts = yield* service(TypeScriptApi);
10876
11166
  const typeCheckerUtils = yield* service(TypeCheckerUtils);
@@ -10922,6 +11212,8 @@ var tryCatchInEffectGen = createDiagnostic({
10922
11212
  code: 15,
10923
11213
  description: "Discourages try/catch in Effect generators in favor of Effect error handling",
10924
11214
  severity: "suggestion",
11215
+ fixable: false,
11216
+ supportedEffect: ["v3", "v4"],
10925
11217
  apply: fn("tryCatchInEffectGen.apply")(function* (sourceFile, report) {
10926
11218
  const ts = yield* service(TypeScriptApi);
10927
11219
  const typeParser = yield* service(TypeParser);
@@ -10979,6 +11271,8 @@ var unknownInEffectCatch = createDiagnostic({
10979
11271
  code: 31,
10980
11272
  description: "Warns when catch callbacks return unknown instead of typed errors",
10981
11273
  severity: "warning",
11274
+ fixable: false,
11275
+ supportedEffect: ["v3", "v4"],
10982
11276
  apply: fn("unknownInEffectCatch.apply")(function* (sourceFile, report) {
10983
11277
  const ts = yield* service(TypeScriptApi);
10984
11278
  const typeParser = yield* service(TypeParser);
@@ -11040,6 +11334,8 @@ var unnecessaryEffectGen = createDiagnostic({
11040
11334
  code: 5,
11041
11335
  description: "Suggests removing Effect.gen when it contains only a single return statement",
11042
11336
  severity: "suggestion",
11337
+ fixable: true,
11338
+ supportedEffect: ["v3", "v4"],
11043
11339
  apply: fn("unnecessaryEffectGen.apply")(function* (sourceFile, report) {
11044
11340
  const ts = yield* service(TypeScriptApi);
11045
11341
  const typeParser = yield* service(TypeParser);
@@ -11084,6 +11380,8 @@ var unnecessaryFailYieldableError = createDiagnostic({
11084
11380
  code: 29,
11085
11381
  description: "Suggests yielding yieldable errors directly instead of wrapping with Effect.fail",
11086
11382
  severity: "suggestion",
11383
+ fixable: true,
11384
+ supportedEffect: ["v3", "v4"],
11087
11385
  apply: fn("unnecessaryFailYieldableError.apply")(function* (sourceFile, report) {
11088
11386
  const ts = yield* service(TypeScriptApi);
11089
11387
  const typeParser = yield* service(TypeParser);
@@ -11143,6 +11441,8 @@ var unnecessaryPipe = createDiagnostic({
11143
11441
  code: 9,
11144
11442
  description: "Removes pipe calls with no arguments",
11145
11443
  severity: "suggestion",
11444
+ fixable: true,
11445
+ supportedEffect: ["v3", "v4"],
11146
11446
  apply: fn("unnecessaryPipe.apply")(function* (sourceFile, report) {
11147
11447
  const ts = yield* service(TypeScriptApi);
11148
11448
  const typeParser = yield* service(TypeParser);
@@ -11189,6 +11489,8 @@ var unnecessaryPipeChain = createDiagnostic({
11189
11489
  code: 16,
11190
11490
  description: "Simplifies chained pipe calls into a single pipe call",
11191
11491
  severity: "suggestion",
11492
+ fixable: true,
11493
+ supportedEffect: ["v3", "v4"],
11192
11494
  apply: fn("unnecessaryPipeChain.apply")(function* (sourceFile, report) {
11193
11495
  const ts = yield* service(TypeScriptApi);
11194
11496
  const typeParser = yield* service(TypeParser);
@@ -11264,6 +11566,8 @@ var unsupportedServiceAccessors = createDiagnostic({
11264
11566
  code: 21,
11265
11567
  description: "Warns about service accessors that need codegen due to generic/complex signatures",
11266
11568
  severity: "warning",
11569
+ fixable: true,
11570
+ supportedEffect: ["v3", "v4"],
11267
11571
  apply: fn("unsupportedServiceAccessors.apply")(function* (sourceFile, report) {
11268
11572
  const ts = yield* service(TypeScriptApi);
11269
11573
  const nodeToVisit = [];
@@ -11366,7 +11670,10 @@ var diagnostics = [
11366
11670
  effectFnOpportunity,
11367
11671
  redundantSchemaTagIdentifier,
11368
11672
  schemaSyncInEffect,
11369
- preferSchemaOverJson
11673
+ preferSchemaOverJson,
11674
+ extendsNativeError,
11675
+ serviceNotAsClass,
11676
+ nodeBuiltinImport
11370
11677
  ];
11371
11678
 
11372
11679
  // src/effect-lsp-patch-utils.ts
@@ -11447,6 +11754,12 @@ function extractDiagnosticsForExitStatus(tsInstance, program, diagnostics2, _mod
11447
11754
  (_) => !(_.source === "effect" && _.category === tsInstance.DiagnosticCategory.Warning)
11448
11755
  );
11449
11756
  }
11757
+ if (parsedOptions.ignoreEffectErrorsInTscExitCode) {
11758
+ newDiagnostics = filter(
11759
+ newDiagnostics,
11760
+ (_) => !(_.source === "effect" && _.category === tsInstance.DiagnosticCategory.Error)
11761
+ );
11762
+ }
11450
11763
  return newDiagnostics;
11451
11764
  }
11452
11765
  // Annotate the CommonJS export names for ESM import in node: