@effect/language-service 0.76.0 → 0.78.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.
@@ -27,7 +27,7 @@ __export(effect_lsp_patch_utils_exports, {
27
27
  });
28
28
  module.exports = __toCommonJS(effect_lsp_patch_utils_exports);
29
29
 
30
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/Pipeable.js
30
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Pipeable.js
31
31
  var pipeArguments = (self, args3) => {
32
32
  switch (args3.length) {
33
33
  case 0:
@@ -60,7 +60,7 @@ var pipeArguments = (self, args3) => {
60
60
  }
61
61
  };
62
62
 
63
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/Function.js
63
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Function.js
64
64
  var dual = function(arity, body) {
65
65
  if (typeof arity === "function") {
66
66
  return function() {
@@ -108,7 +108,7 @@ function pipe(a, ...args3) {
108
108
  return pipeArguments(a, args3);
109
109
  }
110
110
 
111
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/internal/equal.js
111
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/internal/equal.js
112
112
  var getAllObjectKeys = (obj) => {
113
113
  const keys2 = new Set(Reflect.ownKeys(obj));
114
114
  if (obj.constructor === Object) return keys2;
@@ -131,7 +131,7 @@ var getAllObjectKeys = (obj) => {
131
131
  };
132
132
  var byReferenceInstances = /* @__PURE__ */ new WeakSet();
133
133
 
134
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/Predicate.js
134
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Predicate.js
135
135
  function isString(input) {
136
136
  return typeof input === "string";
137
137
  }
@@ -152,7 +152,7 @@ function isObjectKeyword(input) {
152
152
  }
153
153
  var hasProperty = /* @__PURE__ */ dual(2, (self, property) => isObjectKeyword(self) && property in self);
154
154
 
155
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/Hash.js
155
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Hash.js
156
156
  var symbol = "~effect/interfaces/Hash";
157
157
  var hash = (self) => {
158
158
  switch (typeof self) {
@@ -271,7 +271,7 @@ function withVisitedTracking(obj, fn2) {
271
271
  return result;
272
272
  }
273
273
 
274
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/Equal.js
274
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Equal.js
275
275
  var symbol2 = "~effect/interfaces/Equal";
276
276
  function equals() {
277
277
  if (arguments.length === 1) {
@@ -433,7 +433,10 @@ var compareSets = /* @__PURE__ */ makeCompareSet(compareBoth);
433
433
  var isEqual = (u) => hasProperty(u, symbol2);
434
434
  var asEquivalence = () => equals;
435
435
 
436
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/Redactable.js
436
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/internal/array.js
437
+ var isArrayNonEmpty = (self) => self.length > 0;
438
+
439
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Redactable.js
437
440
  var symbolRedactable = /* @__PURE__ */ Symbol.for("~effect/Inspectable/redactable");
438
441
  var isRedactable = (u) => hasProperty(u, symbolRedactable);
439
442
  function redact(u) {
@@ -452,7 +455,7 @@ var emptyServiceMap = {
452
455
  }
453
456
  };
454
457
 
455
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/Formatter.js
458
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Formatter.js
456
459
  function format(input, options) {
457
460
  const space = options?.space ?? 0;
458
461
  const seen = /* @__PURE__ */ new WeakSet();
@@ -531,7 +534,7 @@ function safeToString(input) {
531
534
  }
532
535
  }
533
536
 
534
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/Inspectable.js
537
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Inspectable.js
535
538
  var NodeInspectSymbol = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
536
539
  var toJson = (input) => {
537
540
  try {
@@ -575,7 +578,7 @@ var Class = class {
575
578
  }
576
579
  };
577
580
 
578
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/Utils.js
581
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Utils.js
579
582
  var GenKindTypeId = "~effect/Utils/GenKind";
580
583
  var GenKindImpl = class {
581
584
  value;
@@ -643,7 +646,7 @@ var internalCall = isNotOptimizedAway ? standard[InternalTypeId] : forced[Intern
643
646
  var genConstructor = function* () {
644
647
  }.constructor;
645
648
 
646
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/internal/core.js
649
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/internal/core.js
647
650
  var EffectTypeId = `~effect/Effect`;
648
651
  var ExitTypeId = `~effect/Exit`;
649
652
  var effectVariance = {
@@ -990,7 +993,7 @@ var DoneVoid = {
990
993
  value: void 0
991
994
  };
992
995
 
993
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/internal/option.js
996
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/internal/option.js
994
997
  var TypeId = "~effect/data/Option";
995
998
  var CommonProto = {
996
999
  [TypeId]: {
@@ -1055,7 +1058,7 @@ var some = (value) => {
1055
1058
  return a;
1056
1059
  };
1057
1060
 
1058
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/internal/result.js
1061
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/internal/result.js
1059
1062
  var TypeId2 = "~effect/data/Result";
1060
1063
  var CommonProto2 = {
1061
1064
  [TypeId2]: {
@@ -1126,13 +1129,13 @@ var succeed = (success) => {
1126
1129
  return a;
1127
1130
  };
1128
1131
 
1129
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/Order.js
1132
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Order.js
1130
1133
  function make(compare) {
1131
1134
  return (self, that) => self === that ? 0 : compare(self, that);
1132
1135
  }
1133
1136
  var String2 = /* @__PURE__ */ make((self, that) => self < that ? -1 : 1);
1134
1137
 
1135
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/Option.js
1138
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Option.js
1136
1139
  var none2 = () => none;
1137
1140
  var some2 = some;
1138
1141
  var isNone2 = isNone;
@@ -1142,7 +1145,7 @@ var orElse = /* @__PURE__ */ dual(2, (self, that) => isNone2(self) ? that() : se
1142
1145
  var fromNullishOr = (a) => a == null ? none2() : some2(a);
1143
1146
  var getOrUndefined = /* @__PURE__ */ getOrElse(constUndefined);
1144
1147
 
1145
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/Result.js
1148
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Result.js
1146
1149
  var succeed2 = succeed;
1147
1150
  var fail2 = fail;
1148
1151
  var isFailure2 = isFailure;
@@ -1150,18 +1153,7 @@ var isSuccess2 = isSuccess;
1150
1153
  var map = /* @__PURE__ */ dual(2, (self, f) => isSuccess2(self) ? succeed2(f(self.success)) : fail2(self.failure));
1151
1154
  var getOrElse2 = /* @__PURE__ */ dual(2, (self, onFailure) => isFailure2(self) ? onFailure(self.failure) : self.success);
1152
1155
 
1153
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/Filter.js
1154
- var apply = (filter2, input, ...args3) => {
1155
- const result = filter2(input, ...args3);
1156
- if (result === true) return succeed2(input);
1157
- if (result === false) return fail2(input);
1158
- return result;
1159
- };
1160
-
1161
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/internal/array.js
1162
- var isArrayNonEmpty = (self) => self.length > 0;
1163
-
1164
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/Record.js
1156
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Record.js
1165
1157
  var map2 = /* @__PURE__ */ dual(2, (self, f) => {
1166
1158
  const out = {
1167
1159
  ...self
@@ -1173,7 +1165,7 @@ var map2 = /* @__PURE__ */ dual(2, (self, f) => {
1173
1165
  });
1174
1166
  var keys = (self) => Object.keys(self);
1175
1167
 
1176
- // ../../node_modules/.pnpm/effect@4.0.0-beta.12/node_modules/effect/dist/Array.js
1168
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Array.js
1177
1169
  var Array2 = globalThis.Array;
1178
1170
  var fromIterable = (collection) => Array2.isArray(collection) ? collection : Array2.from(collection);
1179
1171
  var append = /* @__PURE__ */ dual(2, (self, last) => [...self, last]);
@@ -1236,13 +1228,12 @@ var flatMap = /* @__PURE__ */ dual(2, (self, f) => {
1236
1228
  return out;
1237
1229
  });
1238
1230
  var flatten = /* @__PURE__ */ flatMap(identity);
1239
- var filter = /* @__PURE__ */ dual(2, (self, f) => {
1231
+ var filter = /* @__PURE__ */ dual(2, (self, predicate) => {
1240
1232
  const as = fromIterable(self);
1241
1233
  const out = [];
1242
1234
  for (let i = 0; i < as.length; i++) {
1243
- const result = apply(f, as[i], i);
1244
- if (!isFailure2(result)) {
1245
- out.push(result.success);
1235
+ if (predicate(as[i], i)) {
1236
+ out.push(as[i]);
1246
1237
  }
1247
1238
  }
1248
1239
  return out;
@@ -1689,7 +1680,9 @@ function parse(config) {
1689
1680
  keyPatterns: isObject(config) && hasProperty(config, "keyPatterns") && isArray(config.keyPatterns) ? parseKeyPatterns(config.keyPatterns) : defaults.keyPatterns,
1690
1681
  extendedKeyDetection: isObject(config) && hasProperty(config, "extendedKeyDetection") && isBoolean(config.extendedKeyDetection) ? config.extendedKeyDetection : defaults.extendedKeyDetection,
1691
1682
  pipeableMinArgCount: isObject(config) && hasProperty(config, "pipeableMinArgCount") && isNumber(config.pipeableMinArgCount) ? config.pipeableMinArgCount : defaults.pipeableMinArgCount,
1692
- effectFn: isObject(config) && hasProperty(config, "effectFn") && isArray(config.effectFn) && config.effectFn.every(isString) ? config.effectFn.map((_) => _.toLowerCase()) : defaults.effectFn,
1683
+ effectFn: isObject(config) && hasProperty(config, "effectFn") && isArray(config.effectFn) && config.effectFn.every(isString) ? config.effectFn.map(
1684
+ (_) => _.toLowerCase()
1685
+ ) : defaults.effectFn,
1693
1686
  layerGraphFollowDepth: isObject(config) && hasProperty(config, "layerGraphFollowDepth") && isNumber(config.layerGraphFollowDepth) ? config.layerGraphFollowDepth : defaults.layerGraphFollowDepth,
1694
1687
  mermaidProvider: isObject(config) && hasProperty(config, "mermaidProvider") && isString(config.mermaidProvider) ? config.mermaidProvider : defaults.mermaidProvider
1695
1688
  };
@@ -3381,6 +3374,14 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
3381
3374
  const layerType = cachedBy(
3382
3375
  fn("TypeParser.layerType")(function* (type, atLocation) {
3383
3376
  yield* pipeableType(type, atLocation);
3377
+ if (supportedEffect() === "v4") {
3378
+ const typeIdSymbol = typeChecker.getPropertyOfType(type, "~effect/Layer");
3379
+ if (typeIdSymbol) {
3380
+ const typeIdType = typeChecker.getTypeOfSymbolAtLocation(typeIdSymbol, atLocation);
3381
+ return yield* layerVarianceStruct(typeIdType, atLocation);
3382
+ }
3383
+ return yield* typeParserIssue("Type is not a layer", type, atLocation);
3384
+ }
3384
3385
  const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
3385
3386
  (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
3386
3387
  );
@@ -3430,6 +3431,34 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
3430
3431
  "TypeParser.effectSubtype",
3431
3432
  (type) => type
3432
3433
  );
3434
+ const effectYieldableType = cachedBy(
3435
+ fn("TypeParser.effectYieldableType")(function* (type, atLocation) {
3436
+ if (supportedEffect() === "v3") {
3437
+ return yield* effectType(type, atLocation);
3438
+ }
3439
+ return yield* firstSuccessOf([
3440
+ effectType(type, atLocation),
3441
+ gen(function* () {
3442
+ const asEffectSymbol = typeChecker.getPropertyOfType(type, "asEffect");
3443
+ if (!asEffectSymbol) {
3444
+ return yield* typeParserIssue("Type has no 'asEffect' property", type, atLocation);
3445
+ }
3446
+ const asEffectType = typeChecker.getTypeOfSymbolAtLocation(asEffectSymbol, atLocation);
3447
+ const asEffectSignatures = typeChecker.getSignaturesOfType(asEffectType, ts.SignatureKind.Call);
3448
+ if (asEffectSignatures.length === 0) {
3449
+ return yield* typeParserIssue("'asEffect' property is not callable", type, atLocation);
3450
+ }
3451
+ return yield* firstSuccessOf(
3452
+ asEffectSignatures.map(
3453
+ (signature) => effectType(typeChecker.getReturnTypeOfSignature(signature), atLocation)
3454
+ )
3455
+ );
3456
+ })
3457
+ ]);
3458
+ }),
3459
+ "TypeParser.effectYieldableType",
3460
+ (type) => type
3461
+ );
3433
3462
  const isEffectContextSourceFile = cachedBy(
3434
3463
  fn("TypeParser.isEffectContextSourceFile")(function* (sourceFile) {
3435
3464
  const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
@@ -4608,6 +4637,73 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
4608
4637
  "TypeParser.extendsEffectSqlModelClass",
4609
4638
  (atLocation) => atLocation
4610
4639
  );
4640
+ const isEffectSchemaModelTypeSourceFile = cachedBy(
4641
+ fn("TypeParser.isEffectSchemaModelTypeSourceFile")(function* (sourceFile) {
4642
+ const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
4643
+ if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
4644
+ const classSymbol = typeChecker.tryGetMemberInModuleExports("Class", moduleSymbol);
4645
+ if (!classSymbol) return yield* typeParserIssue("Model's Class type not found", void 0, sourceFile);
4646
+ const generatedSymbol = typeChecker.tryGetMemberInModuleExports("Generated", moduleSymbol);
4647
+ if (!generatedSymbol) {
4648
+ return yield* typeParserIssue("Model's Generated type not found", void 0, sourceFile);
4649
+ }
4650
+ const fieldOptionSymbol = typeChecker.tryGetMemberInModuleExports("FieldOption", moduleSymbol);
4651
+ if (!fieldOptionSymbol) {
4652
+ return yield* typeParserIssue("Model's FieldOption type not found", void 0, sourceFile);
4653
+ }
4654
+ return sourceFile;
4655
+ }),
4656
+ "TypeParser.isEffectSchemaModelTypeSourceFile",
4657
+ (sourceFile) => sourceFile
4658
+ );
4659
+ const isNodeReferenceToEffectSchemaModelModuleApi = (memberName) => cachedBy(
4660
+ fn("TypeParser.isNodeReferenceToEffectSchemaModelModuleApi")(function* (node) {
4661
+ return yield* isNodeReferenceToExportOfPackageModule(
4662
+ node,
4663
+ "effect",
4664
+ isEffectSchemaModelTypeSourceFile,
4665
+ memberName
4666
+ );
4667
+ }),
4668
+ `TypeParser.isNodeReferenceToEffectSchemaModelModuleApi(${memberName})`,
4669
+ (node) => node
4670
+ );
4671
+ const extendsEffectSchemaModelClass = cachedBy(
4672
+ fn("TypeParser.extendsEffectSchemaModelClass")(function* (atLocation) {
4673
+ if (!atLocation.name) {
4674
+ return yield* typeParserIssue("Class has no name", void 0, atLocation);
4675
+ }
4676
+ const heritageClauses = atLocation.heritageClauses;
4677
+ if (!heritageClauses) {
4678
+ return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
4679
+ }
4680
+ for (const heritageClause of heritageClauses) {
4681
+ for (const typeX of heritageClause.types) {
4682
+ if (ts.isExpressionWithTypeArguments(typeX)) {
4683
+ const expression = typeX.expression;
4684
+ if (ts.isCallExpression(expression)) {
4685
+ const schemaCall = expression.expression;
4686
+ if (ts.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
4687
+ const isEffectSchemaModelModuleApi = yield* pipe(
4688
+ isNodeReferenceToEffectSchemaModelModuleApi("Class")(schemaCall.expression),
4689
+ orUndefined
4690
+ );
4691
+ if (isEffectSchemaModelModuleApi) {
4692
+ return {
4693
+ className: atLocation.name,
4694
+ selfTypeNode: schemaCall.typeArguments[0]
4695
+ };
4696
+ }
4697
+ }
4698
+ }
4699
+ }
4700
+ }
4701
+ }
4702
+ return yield* typeParserIssue("Class does not extend effect's Model.Class", void 0, atLocation);
4703
+ }),
4704
+ "TypeParser.extendsEffectSchemaModelClass",
4705
+ (atLocation) => atLocation
4706
+ );
4611
4707
  const isEffectLayerTypeSourceFile = cachedBy(
4612
4708
  fn("TypeParser.isEffectLayerTypeSourceFile")(function* (sourceFile) {
4613
4709
  const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
@@ -4980,6 +5076,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
4980
5076
  isNodeReferenceToEffectDataModuleApi,
4981
5077
  isNodeReferenceToEffectContextModuleApi,
4982
5078
  isNodeReferenceToEffectSqlModelModuleApi,
5079
+ isNodeReferenceToEffectSchemaModelModuleApi,
4983
5080
  isNodeReferenceToEffectLayerModuleApi,
4984
5081
  isNodeReferenceToEffectSchemaParserModuleApi,
4985
5082
  isServiceMapTypeSourceFile,
@@ -4989,6 +5086,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
4989
5086
  layerType,
4990
5087
  fiberType,
4991
5088
  effectSubtype,
5089
+ effectYieldableType,
4992
5090
  importedEffectModule,
4993
5091
  effectGen,
4994
5092
  effectFnUntracedGen,
@@ -5017,6 +5115,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5017
5115
  extendsSchemaTaggedRequest,
5018
5116
  extendsSchemaRequestClass,
5019
5117
  extendsEffectSqlModelClass,
5118
+ extendsEffectSchemaModelClass,
5020
5119
  lazyExpression,
5021
5120
  emptyFunction,
5022
5121
  pipingFlows,
@@ -5307,6 +5406,7 @@ var classSelfMismatch = createDiagnostic({
5307
5406
  )
5308
5407
  ),
5309
5408
  orElse2(() => typeParser.extendsEffectSqlModelClass(node)),
5409
+ orElse2(() => typeParser.extendsEffectSchemaModelClass(node)),
5310
5410
  orElse2(() => void_)
5311
5411
  );
5312
5412
  if (result) {
@@ -5699,16 +5799,16 @@ var effectFnOpportunity = createDiagnostic({
5699
5799
  if (ts.isFunctionDeclaration(node) && node.name) {
5700
5800
  return node.name;
5701
5801
  }
5702
- if (node.parent && ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name)) {
5802
+ if (node.parent && ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name) && node.parent.initializer === node) {
5703
5803
  return node.parent.name;
5704
5804
  }
5705
- if (node.parent && ts.isPropertyAssignment(node.parent)) {
5805
+ if (node.parent && ts.isPropertyAssignment(node.parent) && node.parent.initializer === node) {
5706
5806
  const name = node.parent.name;
5707
5807
  if (ts.isIdentifier(name) || ts.isStringLiteral(name)) {
5708
5808
  return name;
5709
5809
  }
5710
5810
  }
5711
- if (node.parent && ts.isPropertyDeclaration(node.parent)) {
5811
+ if (node.parent && ts.isPropertyDeclaration(node.parent) && node.parent.initializer === node) {
5712
5812
  const name = node.parent.name;
5713
5813
  if (ts.isIdentifier(name)) {
5714
5814
  return name;
@@ -5716,6 +5816,190 @@ var effectFnOpportunity = createDiagnostic({
5716
5816
  }
5717
5817
  return void 0;
5718
5818
  };
5819
+ const hasExportModifier = (node) => {
5820
+ if (!ts.canHaveModifiers(node)) return false;
5821
+ const modifiers = ts.getModifiers(node);
5822
+ return modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword) ?? false;
5823
+ };
5824
+ const layerServiceNameFromExpression = (expression) => {
5825
+ if (expression.kind === ts.SyntaxKind.ThisKeyword) {
5826
+ const enclosingClass = ts.findAncestor(
5827
+ expression,
5828
+ (node) => ts.isClassDeclaration(node)
5829
+ );
5830
+ if (enclosingClass?.name) {
5831
+ return ts.idText(enclosingClass.name);
5832
+ }
5833
+ }
5834
+ if (ts.isIdentifier(expression)) return ts.idText(expression);
5835
+ return sourceFile.text.slice(expression.pos, expression.end).trim();
5836
+ };
5837
+ const tryGetLayerApiMethod = (node) => pipe(
5838
+ typeParser.isNodeReferenceToEffectLayerModuleApi("effect")(node),
5839
+ map4(() => "effect"),
5840
+ orElse2(
5841
+ () => pipe(
5842
+ typeParser.isNodeReferenceToEffectLayerModuleApi("succeed")(node),
5843
+ map4(() => "succeed"),
5844
+ orElse2(
5845
+ () => pipe(
5846
+ typeParser.isNodeReferenceToEffectLayerModuleApi("sync")(node),
5847
+ map4(() => "sync"),
5848
+ orElse2(() => succeed3(void 0))
5849
+ )
5850
+ )
5851
+ )
5852
+ )
5853
+ );
5854
+ const verifyLayerMethodAtCall = fn("effectFnOpportunity.verifyLayerMethodAtCall")(
5855
+ function* (callExpression, method, implementationExpression) {
5856
+ const directMethod = yield* tryGetLayerApiMethod(callExpression.expression);
5857
+ if (directMethod === method && callExpression.arguments.length >= 2 && callExpression.arguments[1] === implementationExpression) {
5858
+ return layerServiceNameFromExpression(callExpression.arguments[0]);
5859
+ }
5860
+ if (ts.isCallExpression(callExpression.expression)) {
5861
+ const innerCall = callExpression.expression;
5862
+ const innerMethod = yield* tryGetLayerApiMethod(innerCall.expression);
5863
+ if (innerMethod === method && innerCall.arguments.length >= 1 && callExpression.arguments.length >= 1 && callExpression.arguments[0] === implementationExpression) {
5864
+ return layerServiceNameFromExpression(innerCall.arguments[0]);
5865
+ }
5866
+ }
5867
+ return void 0;
5868
+ }
5869
+ );
5870
+ const tryMatchLayerSucceedInference = fn("effectFnOpportunity.tryMatchLayerSucceedInference")(
5871
+ function* (objectLiteral) {
5872
+ const callExpression = objectLiteral.parent;
5873
+ if (!callExpression || !ts.isCallExpression(callExpression)) return void 0;
5874
+ return yield* verifyLayerMethodAtCall(callExpression, "succeed", objectLiteral);
5875
+ }
5876
+ );
5877
+ const tryMatchLayerSyncInference = fn("effectFnOpportunity.tryMatchLayerSyncInference")(
5878
+ function* (objectLiteral) {
5879
+ const returnStatement = objectLiteral.parent;
5880
+ if (!returnStatement || !ts.isReturnStatement(returnStatement)) return void 0;
5881
+ const functionBody = returnStatement.parent;
5882
+ if (!functionBody || !ts.isBlock(functionBody)) return void 0;
5883
+ const lazyFunction = functionBody.parent;
5884
+ if (!lazyFunction || !ts.isArrowFunction(lazyFunction) && !ts.isFunctionExpression(lazyFunction)) {
5885
+ return void 0;
5886
+ }
5887
+ const callExpression = lazyFunction.parent;
5888
+ if (!callExpression || !ts.isCallExpression(callExpression)) return void 0;
5889
+ return yield* verifyLayerMethodAtCall(callExpression, "sync", lazyFunction);
5890
+ }
5891
+ );
5892
+ const tryMatchLayerEffectInference = fn("effectFnOpportunity.tryMatchLayerEffectInference")(
5893
+ function* (objectLiteral) {
5894
+ const returnStatement = objectLiteral.parent;
5895
+ if (!returnStatement || !ts.isReturnStatement(returnStatement)) return void 0;
5896
+ const generatorBody = returnStatement.parent;
5897
+ if (!generatorBody || !ts.isBlock(generatorBody)) return void 0;
5898
+ const generatorFunction = generatorBody.parent;
5899
+ if (!generatorFunction || !ts.isFunctionExpression(generatorFunction) || !generatorFunction.asteriskToken) {
5900
+ return void 0;
5901
+ }
5902
+ const genCall = generatorFunction.parent;
5903
+ if (!genCall || !ts.isCallExpression(genCall)) return void 0;
5904
+ const parsedEffectGen = yield* option(typeParser.effectGen(genCall));
5905
+ if (parsedEffectGen._tag === "None" || parsedEffectGen.value.generatorFunction !== generatorFunction) {
5906
+ return void 0;
5907
+ }
5908
+ const layerCall = genCall.parent;
5909
+ if (!layerCall || !ts.isCallExpression(layerCall)) return void 0;
5910
+ return yield* verifyLayerMethodAtCall(layerCall, "effect", genCall);
5911
+ }
5912
+ );
5913
+ const tryMatchOfInference = fn("effectFnOpportunity.tryMatchOfInference")(
5914
+ function* (objectLiteral) {
5915
+ const callExpression = objectLiteral.parent;
5916
+ if (!callExpression || !ts.isCallExpression(callExpression)) return void 0;
5917
+ if (callExpression.arguments.length < 1 || callExpression.arguments[0] !== objectLiteral) return void 0;
5918
+ if (!ts.isPropertyAccessExpression(callExpression.expression)) return void 0;
5919
+ if (ts.idText(callExpression.expression.name) !== "of") return void 0;
5920
+ const serviceTagExpression = callExpression.expression.expression;
5921
+ const serviceTagType = typeCheckerUtils.getTypeAtLocation(serviceTagExpression);
5922
+ if (!serviceTagType) return void 0;
5923
+ const isTagLike = yield* pipe(
5924
+ typeParser.contextTag(serviceTagType, serviceTagExpression),
5925
+ orElse2(() => typeParser.serviceType(serviceTagType, serviceTagExpression)),
5926
+ option
5927
+ );
5928
+ if (isTagLike._tag === "None") return void 0;
5929
+ return layerServiceNameFromExpression(serviceTagExpression);
5930
+ }
5931
+ );
5932
+ const tryMatchServiceMapMakeInference = fn("effectFnOpportunity.tryMatchServiceMapMakeInference")(
5933
+ function* (objectLiteral) {
5934
+ const returnStatement = objectLiteral.parent;
5935
+ if (!returnStatement || !ts.isReturnStatement(returnStatement)) return void 0;
5936
+ const generatorBody = returnStatement.parent;
5937
+ if (!generatorBody || !ts.isBlock(generatorBody)) return void 0;
5938
+ const generatorFunction = generatorBody.parent;
5939
+ if (!generatorFunction || !ts.isFunctionExpression(generatorFunction) || !generatorFunction.asteriskToken) {
5940
+ return void 0;
5941
+ }
5942
+ const genCall = generatorFunction.parent;
5943
+ if (!genCall || !ts.isCallExpression(genCall)) return void 0;
5944
+ const parsedEffectGen = yield* option(typeParser.effectGen(genCall));
5945
+ if (parsedEffectGen._tag === "None" || parsedEffectGen.value.generatorFunction !== generatorFunction) {
5946
+ return void 0;
5947
+ }
5948
+ const makeProperty = genCall.parent;
5949
+ if (!makeProperty || !ts.isPropertyAssignment(makeProperty)) return void 0;
5950
+ if (makeProperty.initializer !== genCall) return void 0;
5951
+ if (!ts.isIdentifier(makeProperty.name) || ts.idText(makeProperty.name) !== "make") return void 0;
5952
+ let currentNode = makeProperty.parent;
5953
+ let classDeclaration = void 0;
5954
+ while (currentNode) {
5955
+ if (ts.isClassDeclaration(currentNode)) {
5956
+ classDeclaration = currentNode;
5957
+ break;
5958
+ }
5959
+ currentNode = currentNode.parent;
5960
+ }
5961
+ if (!classDeclaration || !classDeclaration.name) return void 0;
5962
+ const parsedServiceMapService = yield* option(typeParser.extendsServiceMapService(classDeclaration));
5963
+ if (parsedServiceMapService._tag === "None") return void 0;
5964
+ return ts.idText(classDeclaration.name);
5965
+ }
5966
+ );
5967
+ const tryGetLayerInferredTraceName = fn("effectFnOpportunity.tryGetLayerInferredTraceName")(
5968
+ function* (node, suggestedTraceName) {
5969
+ if (!suggestedTraceName) return void 0;
5970
+ if (!(node.parent && ts.isPropertyAssignment(node.parent) && node.parent.initializer === node && node.parent.parent && ts.isObjectLiteralExpression(node.parent.parent))) {
5971
+ return void 0;
5972
+ }
5973
+ const objectLiteral = node.parent.parent;
5974
+ const succeedServiceName = yield* tryMatchLayerSucceedInference(objectLiteral);
5975
+ if (succeedServiceName) return `${succeedServiceName}.${suggestedTraceName}`;
5976
+ const syncServiceName = yield* tryMatchLayerSyncInference(objectLiteral);
5977
+ if (syncServiceName) return `${syncServiceName}.${suggestedTraceName}`;
5978
+ const effectServiceName = yield* tryMatchLayerEffectInference(objectLiteral);
5979
+ if (effectServiceName) return `${effectServiceName}.${suggestedTraceName}`;
5980
+ const ofServiceName = yield* tryMatchOfInference(objectLiteral);
5981
+ if (ofServiceName) return `${ofServiceName}.${suggestedTraceName}`;
5982
+ const serviceMapMakeServiceName = yield* tryMatchServiceMapMakeInference(objectLiteral);
5983
+ return serviceMapMakeServiceName ? `${serviceMapMakeServiceName}.${suggestedTraceName}` : void 0;
5984
+ }
5985
+ );
5986
+ const getInferredTraceName = fn("effectFnOpportunity.getInferredTraceName")(
5987
+ function* (node, suggestedTraceName) {
5988
+ const inferredFromLayer = yield* tryGetLayerInferredTraceName(node, suggestedTraceName);
5989
+ if (inferredFromLayer) return inferredFromLayer;
5990
+ if (ts.isFunctionDeclaration(node) && node.name && hasExportModifier(node)) {
5991
+ return ts.idText(node.name);
5992
+ }
5993
+ if (node.parent && ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name) && node.parent.initializer === node) {
5994
+ const variableDeclarationList = node.parent.parent;
5995
+ const variableStatement = variableDeclarationList?.parent;
5996
+ if (variableDeclarationList && ts.isVariableDeclarationList(variableDeclarationList) && variableStatement && ts.isVariableStatement(variableStatement) && hasExportModifier(variableStatement) && (variableDeclarationList.flags & ts.NodeFlags.Const) !== 0) {
5997
+ return ts.idText(node.parent.name);
5998
+ }
5999
+ }
6000
+ return void 0;
6001
+ }
6002
+ );
5719
6003
  const areParametersReferencedIn = (fnNode, nodes) => {
5720
6004
  if (fnNode.parameters.length === 0 || nodes.length === 0) return false;
5721
6005
  const firstParam = fnNode.parameters[0];
@@ -5800,7 +6084,10 @@ var effectFnOpportunity = createDiagnostic({
5800
6084
  );
5801
6085
  };
5802
6086
  const parseEffectFnOpportunityTargetGen = fn("effectFnOpportunity.parseEffectFnOpportunityTarget")(
5803
- function* (node, returnType, traceName, nameIdentifier) {
6087
+ function* (node, returnType, nameIdentifier) {
6088
+ const suggestedTraceName = nameIdentifier ? ts.isIdentifier(nameIdentifier) ? ts.idText(nameIdentifier) : nameIdentifier.text : void 0;
6089
+ const inferredTraceName = yield* getInferredTraceName(node, suggestedTraceName);
6090
+ const hasStrictLayerInferredName = inferredTraceName !== void 0 && inferredTraceName !== suggestedTraceName;
5804
6091
  if (yield* isInsideEffectFn(node)) {
5805
6092
  return yield* TypeParserIssue.issue;
5806
6093
  }
@@ -5809,11 +6096,11 @@ var effectFnOpportunity = createDiagnostic({
5809
6096
  const opportunity = yield* pipe(
5810
6097
  tryParseGenOpportunity(node),
5811
6098
  orElse2(() => {
5812
- if (ts.isArrowFunction(node) && !ts.isBlock(node.body)) {
6099
+ if (ts.isArrowFunction(node) && !ts.isBlock(node.body) && !hasStrictLayerInferredName) {
5813
6100
  return TypeParserIssue.issue;
5814
6101
  }
5815
6102
  const body = ts.isArrowFunction(node) ? node.body : node.body;
5816
- if (!body || !ts.isBlock(body) || body.statements.length <= 5) {
6103
+ if ((!body || !ts.isBlock(body) || body.statements.length <= 5) && !hasStrictLayerInferredName) {
5817
6104
  return TypeParserIssue.issue;
5818
6105
  }
5819
6106
  return succeed3({
@@ -5828,7 +6115,8 @@ var effectFnOpportunity = createDiagnostic({
5828
6115
  node,
5829
6116
  nameIdentifier,
5830
6117
  effectModuleName: opportunity.effectModuleName,
5831
- inferredTraceName: traceName,
6118
+ inferredTraceName,
6119
+ suggestedTraceName,
5832
6120
  explicitTraceExpression: opportunity.explicitTraceExpression,
5833
6121
  pipeArguments: opportunity.pipeArguments,
5834
6122
  generatorFunction: opportunity.generatorFunction,
@@ -5838,27 +6126,26 @@ var effectFnOpportunity = createDiagnostic({
5838
6126
  );
5839
6127
  const parseEffectFnOpportunityTarget = (node) => {
5840
6128
  if (!ts.isFunctionExpression(node) && !ts.isArrowFunction(node) && !ts.isFunctionDeclaration(node)) {
5841
- return TypeParserIssue.issue;
6129
+ return;
5842
6130
  }
5843
6131
  if ((ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) && node.asteriskToken) {
5844
- return TypeParserIssue.issue;
6132
+ return;
5845
6133
  }
5846
6134
  if (ts.isFunctionExpression(node) && node.name) {
5847
- return TypeParserIssue.issue;
6135
+ return;
5848
6136
  }
5849
6137
  if (node.type) {
5850
- return TypeParserIssue.issue;
6138
+ return;
5851
6139
  }
5852
6140
  const functionType = typeChecker.getTypeAtLocation(node);
5853
- if (!functionType) return TypeParserIssue.issue;
6141
+ if (!functionType) return;
5854
6142
  const callSignatures = typeChecker.getSignaturesOfType(functionType, ts.SignatureKind.Call);
5855
- if (callSignatures.length !== 1) return TypeParserIssue.issue;
6143
+ if (callSignatures.length !== 1) return;
5856
6144
  const signature = callSignatures[0];
5857
6145
  const returnType = typeChecker.getReturnTypeOfSignature(signature);
5858
6146
  const nameIdentifier = getNameIdentifier(node);
5859
- const traceName = nameIdentifier ? ts.isIdentifier(nameIdentifier) ? ts.idText(nameIdentifier) : nameIdentifier.text : void 0;
5860
- if (!traceName) return TypeParserIssue.issue;
5861
- return parseEffectFnOpportunityTargetGen(node, returnType, traceName, nameIdentifier);
6147
+ if (!nameIdentifier) return;
6148
+ return parseEffectFnOpportunityTargetGen(node, returnType, nameIdentifier);
5862
6149
  };
5863
6150
  const getFunctionBodyBlock = (node) => {
5864
6151
  if (ts.isArrowFunction(node)) {
@@ -5932,18 +6219,21 @@ var effectFnOpportunity = createDiagnostic({
5932
6219
  while (nodeToVisit.length > 0) {
5933
6220
  const node = nodeToVisit.shift();
5934
6221
  ts.forEachChild(node, appendNodeToVisit);
5935
- const target = yield* pipe(parseEffectFnOpportunityTarget(node), option);
5936
- if (isNone2(target)) continue;
5937
- if (target.value.hasParamsInPipeArgs) continue;
6222
+ const test = parseEffectFnOpportunityTarget(node);
6223
+ if (!test) continue;
6224
+ const target = yield* orUndefined(test);
6225
+ if (!target) continue;
6226
+ if (target.hasParamsInPipeArgs) continue;
5938
6227
  const {
5939
6228
  effectModuleName,
5940
6229
  explicitTraceExpression,
5941
6230
  inferredTraceName,
5942
6231
  nameIdentifier,
5943
6232
  node: targetNode,
5944
- pipeArguments: pipeArguments2
5945
- } = target.value;
5946
- const innerFunction = target.value.generatorFunction ?? targetNode;
6233
+ pipeArguments: pipeArguments2,
6234
+ suggestedTraceName
6235
+ } = target;
6236
+ const innerFunction = target.generatorFunction ?? targetNode;
5947
6237
  const fixes = [];
5948
6238
  if (pluginOptions.effectFn.includes("span") && explicitTraceExpression) {
5949
6239
  fixes.push({
@@ -5963,7 +6253,7 @@ var effectFnOpportunity = createDiagnostic({
5963
6253
  })
5964
6254
  });
5965
6255
  }
5966
- if (pluginOptions.effectFn.includes("untraced") && target.value.generatorFunction) {
6256
+ if (pluginOptions.effectFn.includes("untraced") && target.generatorFunction) {
5967
6257
  fixes.push({
5968
6258
  fixName: "effectFnOpportunity_toEffectFnUntraced",
5969
6259
  description: "Convert to Effect.fnUntraced",
@@ -5985,22 +6275,41 @@ var effectFnOpportunity = createDiagnostic({
5985
6275
  })
5986
6276
  });
5987
6277
  }
5988
- if (pluginOptions.effectFn.includes("inferred-span") && inferredTraceName && !explicitTraceExpression) {
5989
- fixes.push({
5990
- fixName: "effectFnOpportunity_toEffectFnSpanInferred",
5991
- description: `Convert to Effect.fn("${inferredTraceName}")`,
5992
- apply: gen(function* () {
5993
- const changeTracker = yield* service(ChangeTracker);
5994
- const newNode = createEffectFnNode(
5995
- targetNode,
5996
- innerFunction,
5997
- effectModuleName,
5998
- inferredTraceName,
5999
- pipeArguments2
6000
- );
6001
- changeTracker.replaceNode(sourceFile, targetNode, newNode);
6002
- })
6003
- });
6278
+ if (!explicitTraceExpression) {
6279
+ if (pluginOptions.effectFn.includes("inferred-span") && inferredTraceName) {
6280
+ fixes.push({
6281
+ fixName: "effectFnOpportunity_toEffectFnSpanInferred",
6282
+ description: `Convert to Effect.fn("${inferredTraceName}")`,
6283
+ apply: gen(function* () {
6284
+ const changeTracker = yield* service(ChangeTracker);
6285
+ const newNode = createEffectFnNode(
6286
+ targetNode,
6287
+ innerFunction,
6288
+ effectModuleName,
6289
+ inferredTraceName,
6290
+ pipeArguments2
6291
+ );
6292
+ changeTracker.replaceNode(sourceFile, targetNode, newNode);
6293
+ })
6294
+ });
6295
+ }
6296
+ if (pluginOptions.effectFn.includes("suggested-span") && suggestedTraceName && (!pluginOptions.effectFn.includes("inferred-span") || suggestedTraceName !== inferredTraceName)) {
6297
+ fixes.push({
6298
+ fixName: "effectFnOpportunity_toEffectFnSpanSuggested",
6299
+ description: `Convert to Effect.fn("${suggestedTraceName}")`,
6300
+ apply: gen(function* () {
6301
+ const changeTracker = yield* service(ChangeTracker);
6302
+ const newNode = createEffectFnNode(
6303
+ targetNode,
6304
+ innerFunction,
6305
+ effectModuleName,
6306
+ suggestedTraceName,
6307
+ pipeArguments2
6308
+ );
6309
+ changeTracker.replaceNode(sourceFile, targetNode, newNode);
6310
+ })
6311
+ });
6312
+ }
6004
6313
  }
6005
6314
  if (fixes.length === 0) continue;
6006
6315
  const generateExpectedSignature = () => {
@@ -6013,7 +6322,7 @@ var effectFnOpportunity = createDiagnostic({
6013
6322
  }
6014
6323
  return "_";
6015
6324
  }).join(", ");
6016
- const fnSignature = `function*${typeParamNames}(${paramNames}) { ... }`;
6325
+ const fnSignature = ts.isArrowFunction(innerFunction) ? `${typeParamNames}(${paramNames}) => { ... }` : isGeneratorFunction(innerFunction) ? `function*${typeParamNames}(${paramNames}) { ... }` : `function${typeParamNames}(${paramNames}) { ... }`;
6017
6326
  const pipeArgsForWithSpan = pipeArguments2.slice(0, -1);
6018
6327
  const pipeArgsSuffix = (args3) => args3.length > 0 ? ", ...pipeTransformations" : "";
6019
6328
  switch (firstFix.fixName) {
@@ -6027,6 +6336,8 @@ var effectFnOpportunity = createDiagnostic({
6027
6336
  return `${effectModuleName}.fn(${fnSignature}${pipeArgsSuffix(pipeArguments2)})`;
6028
6337
  case "effectFnOpportunity_toEffectFnSpanInferred":
6029
6338
  return `${effectModuleName}.fn("${inferredTraceName}")(${fnSignature}${pipeArgsSuffix(pipeArguments2)})`;
6339
+ case "effectFnOpportunity_toEffectFnSpanSuggested":
6340
+ return `${effectModuleName}.fn("${suggestedTraceName}")(${fnSignature}${pipeArgsSuffix(pipeArguments2)})`;
6030
6341
  default:
6031
6342
  return `${effectModuleName}.fn(${fnSignature})`;
6032
6343
  }
@@ -6079,6 +6390,70 @@ var effectGenUsesAdapter = createDiagnostic({
6079
6390
  })
6080
6391
  });
6081
6392
 
6393
+ // src/diagnostics/effectInFailure.ts
6394
+ var effectInFailure = createDiagnostic({
6395
+ name: "effectInFailure",
6396
+ code: 49,
6397
+ description: "Warns when an Effect is used inside an Effect failure channel",
6398
+ severity: "warning",
6399
+ apply: fn("effectInFailure.apply")(function* (sourceFile, report) {
6400
+ const ts = yield* service(TypeScriptApi);
6401
+ const typeChecker = yield* service(TypeCheckerApi);
6402
+ const typeParser = yield* service(TypeParser);
6403
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
6404
+ const isStrictEffectType = cachedBy(
6405
+ fn("effectInFailure.isStrictEffectType")(function* (type, atLocation) {
6406
+ yield* typeParser.strictEffectType(type, atLocation);
6407
+ return true;
6408
+ }),
6409
+ "effectInFailure.isStrictEffectType",
6410
+ (type) => type
6411
+ );
6412
+ const visited = /* @__PURE__ */ new WeakSet();
6413
+ const stack = [sourceFile];
6414
+ const shouldSkipBecauseChildMatched = /* @__PURE__ */ new WeakSet();
6415
+ while (stack.length > 0) {
6416
+ const node = stack.pop();
6417
+ if (!visited.has(node)) {
6418
+ visited.add(node);
6419
+ stack.push(node);
6420
+ ts.forEachChild(node, (child) => {
6421
+ stack.push(child);
6422
+ return void 0;
6423
+ });
6424
+ continue;
6425
+ }
6426
+ if (shouldSkipBecauseChildMatched.has(node)) {
6427
+ if (node.parent) shouldSkipBecauseChildMatched.add(node.parent);
6428
+ continue;
6429
+ }
6430
+ const type = typeCheckerUtils.getTypeAtLocation(node);
6431
+ if (!type) continue;
6432
+ const effect = yield* orUndefined(typeParser.strictEffectType(type, node));
6433
+ if (!effect) continue;
6434
+ const failureMembers = typeCheckerUtils.unrollUnionMembers(effect.E);
6435
+ let memberWithEffect = void 0;
6436
+ for (const member of failureMembers) {
6437
+ const isMemberEffect = yield* orUndefined(isStrictEffectType(member, node));
6438
+ if (isMemberEffect) {
6439
+ memberWithEffect = member;
6440
+ break;
6441
+ }
6442
+ }
6443
+ if (!memberWithEffect) continue;
6444
+ const messageText = `The error channel contains an Effect (${typeChecker.typeToString(memberWithEffect)}). Putting Effect computations in the failure channel is not intended; keep only failure types there.`;
6445
+ report({
6446
+ location: node,
6447
+ messageText,
6448
+ fixes: []
6449
+ });
6450
+ if (node.parent) {
6451
+ shouldSkipBecauseChildMatched.add(node.parent);
6452
+ }
6453
+ }
6454
+ })
6455
+ });
6456
+
6082
6457
  // src/diagnostics/effectInVoidSuccess.ts
6083
6458
  var effectInVoidSuccess = createDiagnostic({
6084
6459
  name: "effectInVoidSuccess",
@@ -7447,6 +7822,7 @@ var missingReturnYieldStar = createDiagnostic({
7447
7822
  const ts = yield* service(TypeScriptApi);
7448
7823
  const typeCheckerUtils = yield* service(TypeCheckerUtils);
7449
7824
  const typeParser = yield* service(TypeParser);
7825
+ const tsUtils = yield* service(TypeScriptUtils);
7450
7826
  const nodeToVisit = [];
7451
7827
  const appendNodeToVisit = (node) => {
7452
7828
  nodeToVisit.push(node);
@@ -7456,50 +7832,32 @@ var missingReturnYieldStar = createDiagnostic({
7456
7832
  while (nodeToVisit.length > 0) {
7457
7833
  const node = nodeToVisit.shift();
7458
7834
  ts.forEachChild(node, appendNodeToVisit);
7459
- if (ts.isYieldExpression(node) && node.expression && node.asteriskToken) {
7460
- const type = typeCheckerUtils.getTypeAtLocation(node.expression);
7461
- if (type) {
7462
- const maybeEffect = yield* option(typeParser.effectType(type, node.expression));
7463
- if (isSome2(maybeEffect) && maybeEffect.value.A.flags & ts.TypeFlags.Never) {
7464
- const generatorFunctionOrReturnStatement = ts.findAncestor(
7465
- node,
7466
- (_) => ts.isFunctionExpression(_) || ts.isFunctionDeclaration(_) || ts.isMethodDeclaration(_) || ts.isReturnStatement(_) || ts.isThrowStatement(_)
7467
- );
7468
- if (generatorFunctionOrReturnStatement && !ts.isReturnStatement(generatorFunctionOrReturnStatement) && !ts.isThrowStatement(generatorFunctionOrReturnStatement)) {
7469
- if (generatorFunctionOrReturnStatement && generatorFunctionOrReturnStatement.parent) {
7470
- const effectGenNode = generatorFunctionOrReturnStatement.parent;
7471
- const effectGenLike = yield* pipe(
7472
- typeParser.effectGen(effectGenNode),
7473
- orElse2(() => typeParser.effectFnUntracedGen(effectGenNode)),
7474
- orElse2(() => typeParser.effectFnGen(effectGenNode)),
7475
- option
7476
- );
7477
- if (isSome2(effectGenLike)) {
7478
- const fix = node.expression ? [{
7479
- fixName: "missingReturnYieldStar_fix",
7480
- description: "Add return statement",
7481
- apply: gen(function* () {
7482
- const changeTracker = yield* service(ChangeTracker);
7483
- changeTracker.replaceNode(
7484
- sourceFile,
7485
- node,
7486
- ts.factory.createReturnStatement(
7487
- node
7488
- )
7489
- );
7490
- })
7491
- }] : [];
7492
- report({
7493
- location: node,
7494
- messageText: `It is recommended to use return yield* for Effects that never succeed to signal a definitive exit point for type narrowing and tooling support.`,
7495
- fixes: fix
7496
- });
7497
- }
7498
- }
7499
- }
7500
- }
7501
- }
7502
- }
7835
+ if (!ts.isExpressionStatement(node)) continue;
7836
+ const unwrapped = tsUtils.skipOuterExpressions(node.expression);
7837
+ if (!ts.isYieldExpression(unwrapped) || !unwrapped.expression || !unwrapped.asteriskToken) continue;
7838
+ const type = typeCheckerUtils.getTypeAtLocation(unwrapped.expression);
7839
+ if (!type) continue;
7840
+ const maybeEffect = yield* option(typeParser.effectYieldableType(type, unwrapped.expression));
7841
+ if (!(isSome2(maybeEffect) && maybeEffect.value.A.flags & ts.TypeFlags.Never)) continue;
7842
+ const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(node);
7843
+ if (!effectGen || scopeNode && scopeNode !== effectGen.generatorFunction) continue;
7844
+ const fix = [{
7845
+ fixName: "missingReturnYieldStar_fix",
7846
+ description: "Add return statement",
7847
+ apply: gen(function* () {
7848
+ const changeTracker = yield* service(ChangeTracker);
7849
+ changeTracker.replaceNode(
7850
+ sourceFile,
7851
+ node,
7852
+ ts.factory.createReturnStatement(node.expression)
7853
+ );
7854
+ })
7855
+ }];
7856
+ report({
7857
+ location: unwrapped,
7858
+ messageText: `It is recommended to use return yield* for Effects that never succeed to signal a definitive exit point for type narrowing and tooling support.`,
7859
+ fixes: fix
7860
+ });
7503
7861
  }
7504
7862
  })
7505
7863
  });
@@ -7765,6 +8123,761 @@ var nonObjectEffectServiceType = createDiagnostic({
7765
8123
  })
7766
8124
  });
7767
8125
 
8126
+ // src/diagnostics/outdatedApi.db.ts
8127
+ var asUnchanged = {
8128
+ _tag: "Unchanged"
8129
+ };
8130
+ var asRenamedSameBehaviour = (newName) => ({
8131
+ _tag: "RenamedSameBehaviour",
8132
+ newName
8133
+ });
8134
+ var asRenamedAndNeedsOptions = (newName, optionsInstructions) => ({
8135
+ _tag: "RenamedAndNeedsOptions",
8136
+ newName,
8137
+ optionsInstructions
8138
+ });
8139
+ var asRemoved = (alternativePattern) => ({
8140
+ _tag: "Removed",
8141
+ alternativePattern
8142
+ });
8143
+ var effectModuleMigrationDb = {
8144
+ // Common APIs (in both v3 and v4, unchanged)
8145
+ "acquireRelease": asUnchanged,
8146
+ "acquireUseRelease": asUnchanged,
8147
+ "addFinalizer": asUnchanged,
8148
+ "all": asUnchanged,
8149
+ "andThen": asUnchanged,
8150
+ "annotateCurrentSpan": asUnchanged,
8151
+ "annotateLogs": asUnchanged,
8152
+ "annotateSpans": asUnchanged,
8153
+ "as": asUnchanged,
8154
+ "asSome": asUnchanged,
8155
+ "asVoid": asUnchanged,
8156
+ "cached": asUnchanged,
8157
+ "cachedInvalidateWithTTL": asUnchanged,
8158
+ "cachedWithTTL": asUnchanged,
8159
+ "catch": asUnchanged,
8160
+ "catchIf": asUnchanged,
8161
+ "catchTag": asUnchanged,
8162
+ "catchTags": asUnchanged,
8163
+ "clockWith": asUnchanged,
8164
+ "currentParentSpan": asUnchanged,
8165
+ "currentSpan": asUnchanged,
8166
+ "delay": asUnchanged,
8167
+ "die": asUnchanged,
8168
+ "ensuring": asUnchanged,
8169
+ "eventually": asUnchanged,
8170
+ "exit": asUnchanged,
8171
+ "fail": asUnchanged,
8172
+ "failCause": asUnchanged,
8173
+ "failCauseSync": asUnchanged,
8174
+ "failSync": asUnchanged,
8175
+ "fiberId": asUnchanged,
8176
+ "filter": asUnchanged,
8177
+ "filterMap": asUnchanged,
8178
+ "filterOrElse": asUnchanged,
8179
+ "filterOrFail": asUnchanged,
8180
+ "flatMap": asUnchanged,
8181
+ "flatten": asUnchanged,
8182
+ "flip": asUnchanged,
8183
+ "fn": asUnchanged,
8184
+ "fnUntraced": asUnchanged,
8185
+ "forEach": asUnchanged,
8186
+ "forever": asUnchanged,
8187
+ "forkIn": asUnchanged,
8188
+ "forkScoped": asUnchanged,
8189
+ "gen": asUnchanged,
8190
+ "ignore": asUnchanged,
8191
+ "interrupt": asUnchanged,
8192
+ "interruptible": asUnchanged,
8193
+ "interruptibleMask": asUnchanged,
8194
+ "isEffect": asUnchanged,
8195
+ "isFailure": asUnchanged,
8196
+ "isSuccess": asUnchanged,
8197
+ "linkSpans": asUnchanged,
8198
+ "log": asUnchanged,
8199
+ "logDebug": asUnchanged,
8200
+ "logError": asUnchanged,
8201
+ "logFatal": asUnchanged,
8202
+ "logInfo": asUnchanged,
8203
+ "logTrace": asUnchanged,
8204
+ "logWarning": asUnchanged,
8205
+ "logWithLevel": asUnchanged,
8206
+ "makeLatch": asRemoved(
8207
+ "Use Latch.make instead of Effect.makeLatch."
8208
+ ),
8209
+ "makeSemaphore": asRemoved(
8210
+ "Use Semaphore.make instead of Effect.makeSemaphore."
8211
+ ),
8212
+ "makeSpan": asUnchanged,
8213
+ "makeSpanScoped": asUnchanged,
8214
+ "map": asUnchanged,
8215
+ "mapBoth": asUnchanged,
8216
+ "mapError": asUnchanged,
8217
+ "match": asUnchanged,
8218
+ "matchCause": asUnchanged,
8219
+ "matchCauseEffect": asUnchanged,
8220
+ "matchEffect": asUnchanged,
8221
+ "never": asUnchanged,
8222
+ "onError": asUnchanged,
8223
+ "onExit": asUnchanged,
8224
+ "onInterrupt": asUnchanged,
8225
+ "option": asUnchanged,
8226
+ "orDie": asUnchanged,
8227
+ "orElseSucceed": asUnchanged,
8228
+ "promise": asUnchanged,
8229
+ "provide": asUnchanged,
8230
+ "provideService": asUnchanged,
8231
+ "provideServiceEffect": asUnchanged,
8232
+ "race": asUnchanged,
8233
+ "raceAll": asUnchanged,
8234
+ "raceFirst": asUnchanged,
8235
+ "repeat": asUnchanged,
8236
+ "repeatOrElse": asUnchanged,
8237
+ "replicate": asUnchanged,
8238
+ "replicateEffect": asUnchanged,
8239
+ "request": asUnchanged,
8240
+ "retry": asUnchanged,
8241
+ "retryOrElse": asUnchanged,
8242
+ "runCallback": asUnchanged,
8243
+ "runFork": asUnchanged,
8244
+ "runPromise": asUnchanged,
8245
+ "runPromiseExit": asUnchanged,
8246
+ "runSync": asUnchanged,
8247
+ "runSyncExit": asUnchanged,
8248
+ "sandbox": asUnchanged,
8249
+ "schedule": asUnchanged,
8250
+ "scheduleFrom": asUnchanged,
8251
+ "scope": asUnchanged,
8252
+ "scoped": asUnchanged,
8253
+ "scopedWith": asUnchanged,
8254
+ "serviceOption": asUnchanged,
8255
+ "sleep": asUnchanged,
8256
+ "spanAnnotations": asUnchanged,
8257
+ "spanLinks": asUnchanged,
8258
+ "succeed": asUnchanged,
8259
+ "succeedNone": asUnchanged,
8260
+ "succeedSome": asUnchanged,
8261
+ "suspend": asUnchanged,
8262
+ "sync": asUnchanged,
8263
+ "tap": asUnchanged,
8264
+ "tapDefect": asUnchanged,
8265
+ "tapError": asUnchanged,
8266
+ "tapErrorTag": asUnchanged,
8267
+ "timed": asUnchanged,
8268
+ "timeout": asUnchanged,
8269
+ "timeoutOption": asUnchanged,
8270
+ "tracer": asUnchanged,
8271
+ "try": asUnchanged,
8272
+ "tryPromise": asUnchanged,
8273
+ "uninterruptible": asUnchanged,
8274
+ "uninterruptibleMask": asUnchanged,
8275
+ "updateService": asUnchanged,
8276
+ "useSpan": asUnchanged,
8277
+ "void": asUnchanged,
8278
+ "when": asUnchanged,
8279
+ "whileLoop": asUnchanged,
8280
+ "withConcurrency": asUnchanged,
8281
+ "withExecutionPlan": asUnchanged,
8282
+ "withLogSpan": asUnchanged,
8283
+ "withParentSpan": asUnchanged,
8284
+ "withSpan": asUnchanged,
8285
+ "withSpanScoped": asUnchanged,
8286
+ "withTracer": asUnchanged,
8287
+ "withTracerEnabled": asUnchanged,
8288
+ "withTracerTiming": asUnchanged,
8289
+ "yieldNow": asUnchanged,
8290
+ "zip": asUnchanged,
8291
+ "zipWith": asUnchanged,
8292
+ // Renamed APIs (v3 name → v4 name)
8293
+ "catchAll": asRenamedSameBehaviour("catch"),
8294
+ "catchAllCause": asRenamedSameBehaviour("catchCause"),
8295
+ "catchAllDefect": asRenamedSameBehaviour("catchDefect"),
8296
+ "catchSome": asRemoved(
8297
+ "Use Effect.catchIf instead. Note: the API shape changed from returning Option<Effect> to taking a predicate and handler separately."
8298
+ ),
8299
+ "catchSomeCause": asRemoved(
8300
+ "Use Effect.catchCauseIf instead. Note: the API shape changed from returning Option<Effect> to taking a predicate and handler separately."
8301
+ ),
8302
+ "ensureErrorType": asRenamedSameBehaviour("satisfiesErrorType"),
8303
+ "ensureRequirementsType": asRenamedSameBehaviour("satisfiesServicesType"),
8304
+ "ensureSuccessType": asRenamedSameBehaviour("satisfiesSuccessType"),
8305
+ "fork": asRenamedSameBehaviour("forkChild"),
8306
+ "forkDaemon": asRenamedSameBehaviour("forkDetach"),
8307
+ "scopeWith": asRenamedSameBehaviour("scopedWith"),
8308
+ "serviceOptional": asRenamedSameBehaviour("serviceOption"),
8309
+ "tapErrorCause": asRenamedSameBehaviour("tapCause"),
8310
+ // Removed APIs
8311
+ "annotateLogsScoped": asUnchanged,
8312
+ "awaitAllChildren": asUnchanged,
8313
+ "bind": asUnchanged,
8314
+ "bindTo": asUnchanged,
8315
+ "Do": asUnchanged,
8316
+ "let": asUnchanged,
8317
+ "partition": asUnchanged,
8318
+ "validate": asUnchanged,
8319
+ "catchSomeDefect": asRemoved(
8320
+ "Use Effect.catchDefect or Effect.matchCause to handle specific defects."
8321
+ ),
8322
+ "forkAll": asRemoved(
8323
+ "Fork effects individually with Effect.forEach and Effect.forkChild, or use Effect.all with concurrency options."
8324
+ ),
8325
+ "forkWithErrorHandler": asRemoved(
8326
+ "Fork the effect with Effect.forkChild and observe the fiber result via Fiber.join or Fiber.await."
8327
+ ),
8328
+ "Tag": asRemoved(
8329
+ "Use ServiceMap.Service instead of Effect.Tag."
8330
+ ),
8331
+ "Service": asRemoved(
8332
+ "Use ServiceMap.Service instead of Effect.Service."
8333
+ ),
8334
+ "runtime": asRemoved(
8335
+ "Runtime has been removed in Effect v4. Use Effect.services to grab services and then run using Effect.runPromiseWith."
8336
+ ),
8337
+ "bindAll": asRemoved(
8338
+ "Use Effect.gen instead of Effect.bindAll."
8339
+ ),
8340
+ "EffectTypeId": asRemoved(
8341
+ "EffectTypeId has been removed in Effect v4."
8342
+ ),
8343
+ "acquireReleaseInterruptible": asRemoved(
8344
+ "Use Effect.acquireRelease instead."
8345
+ ),
8346
+ "allSuccesses": asRemoved(
8347
+ "Use Effect.all with the { mode: 'either' } option and filter successes."
8348
+ ),
8349
+ "allWith": asRemoved(
8350
+ "Use Effect.all with options instead."
8351
+ ),
8352
+ "allowInterrupt": asRemoved(
8353
+ "Use Effect.yieldNow instead."
8354
+ ),
8355
+ "ap": asRemoved(
8356
+ "Use Effect.map and Effect.flatMap to apply functions instead."
8357
+ ),
8358
+ "asSomeError": asRemoved(
8359
+ "Use Effect.mapError(Option.some) instead."
8360
+ ),
8361
+ "async": asRenamedAndNeedsOptions("callback", "Note: in v4 the callback receives a Scheduler as 'this' context."),
8362
+ "asyncEffect": asRemoved(
8363
+ "Use Effect.suspend combined with Effect.promise instead."
8364
+ ),
8365
+ "blocked": asRemoved(
8366
+ "The request batching API has been reworked in Effect v4."
8367
+ ),
8368
+ "cacheRequestResult": asRemoved(
8369
+ "The request batching API has been reworked in Effect v4."
8370
+ ),
8371
+ "cachedFunction": asRemoved(
8372
+ "Use Effect.cached or implement caching with a Ref instead."
8373
+ ),
8374
+ "cause": asRemoved(
8375
+ "Use Effect.matchCause or Effect.sandbox to access the cause."
8376
+ ),
8377
+ "checkInterruptible": asRemoved(
8378
+ "Interruption checking has been removed in Effect v4."
8379
+ ),
8380
+ "clock": asRemoved(
8381
+ "Use Effect.clockWith instead."
8382
+ ),
8383
+ "configProviderWith": asRemoved(
8384
+ "ConfigProvider access has been reworked in Effect v4."
8385
+ ),
8386
+ "console": asRemoved(
8387
+ "Use Effect.consoleWith or the Console service directly."
8388
+ ),
8389
+ "consoleWith": asRemoved(
8390
+ "Console access has been reworked in Effect v4."
8391
+ ),
8392
+ "context": asRemoved(
8393
+ "Use Effect.context is removed. Access services directly via yield* or Effect.provideService."
8394
+ ),
8395
+ "contextWith": asRemoved(
8396
+ "Use Effect.map with service access instead."
8397
+ ),
8398
+ "contextWithEffect": asRemoved(
8399
+ "Use Effect.flatMap with service access instead."
8400
+ ),
8401
+ "custom": asRemoved(
8402
+ "Use Effect.suspend or Effect.sync to create custom effects."
8403
+ ),
8404
+ "daemonChildren": asRemoved(
8405
+ "Use Effect.forkDetach to fork detached fibers instead."
8406
+ ),
8407
+ "descriptor": asRemoved(
8408
+ "Fiber descriptor access has been removed in Effect v4."
8409
+ ),
8410
+ "descriptorWith": asRemoved(
8411
+ "Fiber descriptor access has been removed in Effect v4."
8412
+ ),
8413
+ "dieMessage": asRemoved(
8414
+ "Use Effect.die(new Error(message)) instead."
8415
+ ),
8416
+ "dieSync": asRemoved(
8417
+ "Use Effect.die with a lazily evaluated value instead."
8418
+ ),
8419
+ "diffFiberRefs": asRemoved(
8420
+ "FiberRef has been replaced by ServiceMap.Reference in Effect v4."
8421
+ ),
8422
+ "disconnect": asRemoved(
8423
+ "Fiber disconnect has been removed in Effect v4."
8424
+ ),
8425
+ "dropUntil": asRemoved(
8426
+ "Use Array.dropUntil and Effect.forEach instead."
8427
+ ),
8428
+ "dropWhile": asRemoved(
8429
+ "Use Array.dropWhile and Effect.forEach instead."
8430
+ ),
8431
+ "either": asRenamedAndNeedsOptions(
8432
+ "result",
8433
+ "Note: returns Result.Result<A, E> instead of Either<E, A>. Use the Result module to work with the result."
8434
+ ),
8435
+ "ensuringChild": asRemoved(
8436
+ "Use Effect.onExit to manage child fiber cleanup instead."
8437
+ ),
8438
+ "ensuringChildren": asRemoved(
8439
+ "Use Effect.onExit to manage child fiber cleanup instead."
8440
+ ),
8441
+ "every": asRemoved(
8442
+ "Use Effect.forEach with a predicate check instead."
8443
+ ),
8444
+ "exists": asRemoved(
8445
+ "Use Effect.forEach with a predicate check instead."
8446
+ ),
8447
+ "fiberIdWith": asRemoved(
8448
+ "Use Effect.fiberId instead."
8449
+ ),
8450
+ "filterEffectOrElse": asRemoved(
8451
+ "Use Effect.filterOrElse with an effectful predicate instead."
8452
+ ),
8453
+ "filterEffectOrFail": asRemoved(
8454
+ "Use Effect.filterOrFail with an effectful predicate instead."
8455
+ ),
8456
+ "filterOrDie": asRemoved(
8457
+ "Use Effect.filterOrFail and Effect.orDie instead."
8458
+ ),
8459
+ "filterOrDieMessage": asRemoved(
8460
+ "Use Effect.filterOrFail and Effect.orDie instead."
8461
+ ),
8462
+ "finalizersMask": asRemoved(
8463
+ "Finalizer masking has been removed in Effect v4."
8464
+ ),
8465
+ "findFirst": asUnchanged,
8466
+ "firstSuccessOf": asRemoved(
8467
+ "Use Effect.raceAll instead."
8468
+ ),
8469
+ "flipWith": asRemoved(
8470
+ "Use Effect.flip combined with the desired transformation instead."
8471
+ ),
8472
+ "fromFiber": asRemoved(
8473
+ "Use Fiber.join instead."
8474
+ ),
8475
+ "fromFiberEffect": asRemoved(
8476
+ "Use Effect.flatMap with Fiber.join instead."
8477
+ ),
8478
+ "fromNullable": asRemoved(
8479
+ "Use Effect.suspend with null checks instead."
8480
+ ),
8481
+ "functionWithSpan": asRemoved(
8482
+ "Use Effect.withSpan instead."
8483
+ ),
8484
+ "getFiberRefs": asRemoved(
8485
+ "FiberRef has been replaced by ServiceMap.Reference in Effect v4."
8486
+ ),
8487
+ "getRuntimeFlags": asRemoved(
8488
+ "Runtime flags have been removed in Effect v4."
8489
+ ),
8490
+ "head": asRemoved(
8491
+ "Use Array.head and Effect.flatMap instead."
8492
+ ),
8493
+ "if": asRemoved(
8494
+ "Use Effect.when instead of Effect.if."
8495
+ ),
8496
+ "ignoreLogged": asRemoved(
8497
+ "Logging configuration has been reworked in Effect v4."
8498
+ ),
8499
+ "inheritFiberRefs": asRemoved(
8500
+ "FiberRef has been replaced by ServiceMap.Reference in Effect v4."
8501
+ ),
8502
+ "interruptWith": asRemoved(
8503
+ "Use Effect.interrupt instead."
8504
+ ),
8505
+ "intoDeferred": asRemoved(
8506
+ "Use Deferred.complete instead."
8507
+ ),
8508
+ "iterate": asRemoved(
8509
+ "Use Effect.whileLoop or recursion with Effect.suspend instead."
8510
+ ),
8511
+ "labelMetrics": asRemoved(
8512
+ "Metric labeling has been reworked in Effect v4."
8513
+ ),
8514
+ "labelMetricsScoped": asRemoved(
8515
+ "Metric labeling has been reworked in Effect v4."
8516
+ ),
8517
+ "liftPredicate": asRemoved(
8518
+ "Use Effect.filterOrFail instead."
8519
+ ),
8520
+ "linkSpanCurrent": asRemoved(
8521
+ "Use Effect.linkSpans instead."
8522
+ ),
8523
+ "locally": asRemoved(
8524
+ "FiberRef.locally has been removed. Use Effect.provideService with ServiceMap.Reference instead."
8525
+ ),
8526
+ "locallyScoped": asRemoved(
8527
+ "FiberRef.locally has been removed. Use Effect.provideService with ServiceMap.Reference instead."
8528
+ ),
8529
+ "locallyScopedWith": asRemoved(
8530
+ "FiberRef.locally has been removed. Use Effect.provideService with ServiceMap.Reference instead."
8531
+ ),
8532
+ "locallyWith": asRemoved(
8533
+ "FiberRef.locally has been removed. Use Effect.provideService with ServiceMap.Reference instead."
8534
+ ),
8535
+ "logAnnotations": asRemoved(
8536
+ "Use Effect.annotateLogs instead."
8537
+ ),
8538
+ "loop": asRemoved(
8539
+ "Use Effect.whileLoop or recursion with Effect.suspend instead."
8540
+ ),
8541
+ "mapAccum": asRemoved(
8542
+ "Use Effect.gen with a mutable accumulator instead."
8543
+ ),
8544
+ "mapErrorCause": asRemoved(
8545
+ "Use Effect.sandbox and Effect.mapError instead."
8546
+ ),
8547
+ "mapInputContext": asRemoved(
8548
+ "Use Effect.provide with a layer instead."
8549
+ ),
8550
+ "merge": asRemoved(
8551
+ "Use Effect.match or Effect.exit instead."
8552
+ ),
8553
+ "mergeAll": asRemoved(
8554
+ "Use Effect.forEach with a mutable accumulator instead."
8555
+ ),
8556
+ "metricLabels": asRemoved(
8557
+ "Metric labeling has been reworked in Effect v4."
8558
+ ),
8559
+ "negate": asRemoved(
8560
+ "Use Effect.map with boolean negation instead."
8561
+ ),
8562
+ "none": asRemoved(
8563
+ "Use Effect.filterOrFail or Effect.option instead."
8564
+ ),
8565
+ "once": asRemoved(
8566
+ "Use Effect.cached instead."
8567
+ ),
8568
+ "optionFromOptional": asRemoved(
8569
+ "Use Effect.option instead."
8570
+ ),
8571
+ "orDieWith": asRemoved(
8572
+ "Use Effect.orDie or Effect.mapError combined with Effect.orDie instead."
8573
+ ),
8574
+ "orElse": asRemoved(
8575
+ "Use Effect.catch or Effect.matchEffect instead."
8576
+ ),
8577
+ "orElseFail": asRemoved(
8578
+ "Use Effect.mapError instead."
8579
+ ),
8580
+ "parallelErrors": asRemoved(
8581
+ "Use Effect.all with concurrency options instead."
8582
+ ),
8583
+ "parallelFinalizers": asRemoved(
8584
+ "Finalizer ordering configuration has been removed in Effect v4."
8585
+ ),
8586
+ "patchFiberRefs": asRemoved(
8587
+ "FiberRef has been replaced by ServiceMap.Reference in Effect v4."
8588
+ ),
8589
+ "patchRuntimeFlags": asRemoved(
8590
+ "Runtime flags have been removed in Effect v4."
8591
+ ),
8592
+ "raceWith": asRemoved(
8593
+ "Use Effect.race or Effect.raceFirst instead."
8594
+ ),
8595
+ "random": asRemoved(
8596
+ "Use Effect.randomWith instead."
8597
+ ),
8598
+ "randomWith": asRemoved(
8599
+ "Random access has been reworked in Effect v4."
8600
+ ),
8601
+ "reduce": asRemoved(
8602
+ "Use Effect.forEach with a mutable accumulator or Effect.gen instead."
8603
+ ),
8604
+ "reduceEffect": asRemoved(
8605
+ "Use Effect.forEach with a mutable accumulator or Effect.gen instead."
8606
+ ),
8607
+ "reduceRight": asRemoved(
8608
+ "Use Effect.forEach with a mutable accumulator or Effect.gen instead."
8609
+ ),
8610
+ "reduceWhile": asRemoved(
8611
+ "Use Effect.gen with early return instead."
8612
+ ),
8613
+ "repeatN": asRemoved(
8614
+ "Use Effect.repeat with a schedule instead."
8615
+ ),
8616
+ "runRequestBlock": asRemoved(
8617
+ "The request batching API has been reworked in Effect v4."
8618
+ ),
8619
+ "scheduleForked": asRemoved(
8620
+ "Use Effect.schedule combined with Effect.forkChild instead."
8621
+ ),
8622
+ "sequentialFinalizers": asRemoved(
8623
+ "Finalizer ordering configuration has been removed in Effect v4."
8624
+ ),
8625
+ "serviceConstants": asRemoved(
8626
+ "Service helpers have been removed. Use ServiceMap.Service and yield* to access services."
8627
+ ),
8628
+ "serviceFunction": asRemoved(
8629
+ "Service helpers have been removed. Use ServiceMap.Service and yield* to access services."
8630
+ ),
8631
+ "serviceFunctionEffect": asRemoved(
8632
+ "Service helpers have been removed. Use ServiceMap.Service and yield* to access services."
8633
+ ),
8634
+ "serviceFunctions": asRemoved(
8635
+ "Service helpers have been removed. Use ServiceMap.Service and yield* to access services."
8636
+ ),
8637
+ "serviceMembers": asRemoved(
8638
+ "Service helpers have been removed. Use ServiceMap.Service and yield* to access services."
8639
+ ),
8640
+ "setFiberRefs": asRemoved(
8641
+ "FiberRef has been replaced by ServiceMap.Reference in Effect v4."
8642
+ ),
8643
+ "step": asRemoved(
8644
+ "The request batching API has been reworked in Effect v4."
8645
+ ),
8646
+ "summarized": asRemoved(
8647
+ "Use Effect.gen to capture before/after state instead."
8648
+ ),
8649
+ "supervised": asRemoved(
8650
+ "Supervision has been reworked in Effect v4."
8651
+ ),
8652
+ "tagMetrics": asRemoved(
8653
+ "Metric labeling has been reworked in Effect v4."
8654
+ ),
8655
+ "tagMetricsScoped": asRemoved(
8656
+ "Metric labeling has been reworked in Effect v4."
8657
+ ),
8658
+ "takeUntil": asRemoved(
8659
+ "Use Array.takeUntil and Effect.forEach instead."
8660
+ ),
8661
+ "takeWhile": asRemoved(
8662
+ "Use Array.takeWhile and Effect.forEach instead."
8663
+ ),
8664
+ "tapBoth": asRemoved(
8665
+ "Use Effect.tap and Effect.tapError instead."
8666
+ ),
8667
+ "timedWith": asRemoved(
8668
+ "Use Effect.timed instead."
8669
+ ),
8670
+ "timeoutFail": asRemoved(
8671
+ "Use Effect.timeout combined with Effect.catchTag for TimeoutException instead."
8672
+ ),
8673
+ "timeoutFailCause": asRemoved(
8674
+ "Use Effect.timeout combined with Effect.sandbox instead."
8675
+ ),
8676
+ "timeoutTo": asRemoved(
8677
+ "Use Effect.timeoutOption and Effect.map instead."
8678
+ ),
8679
+ "tracerWith": asRemoved(
8680
+ "Use Effect.tracer instead."
8681
+ ),
8682
+ "transplant": asRemoved(
8683
+ "Fiber transplanting has been removed in Effect v4."
8684
+ ),
8685
+ "transposeMapOption": asRemoved(
8686
+ "Use Effect.map with Option operations instead."
8687
+ ),
8688
+ "transposeOption": asRemoved(
8689
+ "Use Effect.option instead."
8690
+ ),
8691
+ "tryMap": asRemoved(
8692
+ "Use Effect.map inside Effect.try instead."
8693
+ ),
8694
+ "tryMapPromise": asRemoved(
8695
+ "Use Effect.tryPromise instead."
8696
+ ),
8697
+ "unless": asRemoved(
8698
+ "Use Effect.when with a negated condition instead."
8699
+ ),
8700
+ "unlessEffect": asRemoved(
8701
+ "Use Effect.when with a negated effectful condition instead."
8702
+ ),
8703
+ "unsafeMakeLatch": asRemoved(
8704
+ "Use Effect.makeLatch instead."
8705
+ ),
8706
+ "unsafeMakeSemaphore": asRemoved(
8707
+ "Use Effect.makeSemaphore instead."
8708
+ ),
8709
+ "unsandbox": asRemoved(
8710
+ "Use Effect.catchCause instead."
8711
+ ),
8712
+ "updateFiberRefs": asRemoved(
8713
+ "FiberRef has been replaced by ServiceMap.Reference in Effect v4."
8714
+ ),
8715
+ "using": asRemoved(
8716
+ "Use Effect.scoped instead."
8717
+ ),
8718
+ "validateAll": asRemoved(
8719
+ "Use Effect.all with { mode: 'validate' } instead."
8720
+ ),
8721
+ "validateFirst": asRemoved(
8722
+ "Use Effect.all with { mode: 'validate' } instead."
8723
+ ),
8724
+ "validateWith": asRemoved(
8725
+ "Use Effect.all with { mode: 'validate' } instead."
8726
+ ),
8727
+ "whenEffect": asRemoved(
8728
+ "Use Effect.when with an effectful condition via Effect.flatMap instead."
8729
+ ),
8730
+ "whenFiberRef": asRemoved(
8731
+ "FiberRef has been replaced by ServiceMap.Reference in Effect v4."
8732
+ ),
8733
+ "whenLogLevel": asRemoved(
8734
+ "Log level checking has been reworked in Effect v4."
8735
+ ),
8736
+ "whenRef": asRemoved(
8737
+ "Use Ref.get and Effect.when instead."
8738
+ ),
8739
+ "withClock": asRemoved(
8740
+ "Clock configuration has been reworked in Effect v4."
8741
+ ),
8742
+ "withClockScoped": asRemoved(
8743
+ "Clock configuration has been reworked in Effect v4."
8744
+ ),
8745
+ "withConfigProvider": asRemoved(
8746
+ "ConfigProvider configuration has been reworked in Effect v4."
8747
+ ),
8748
+ "withConfigProviderScoped": asRemoved(
8749
+ "ConfigProvider configuration has been reworked in Effect v4."
8750
+ ),
8751
+ "withConsole": asRemoved(
8752
+ "Console configuration has been reworked in Effect v4."
8753
+ ),
8754
+ "withConsoleScoped": asRemoved(
8755
+ "Console configuration has been reworked in Effect v4."
8756
+ ),
8757
+ "withEarlyRelease": asRemoved(
8758
+ "Use Effect.scoped with manual resource management instead."
8759
+ ),
8760
+ "withFiberRuntime": asRenamedAndNeedsOptions(
8761
+ "withFiber",
8762
+ "Note: in v4, only the Fiber is provided (not the full FiberRuntime with status). The callback receives (fiber: Fiber<unknown, unknown>) instead of (fiber: FiberRuntime<A, E>, status: FiberStatus)."
8763
+ ),
8764
+ "withMaxOpsBeforeYield": asRemoved(
8765
+ "Use ServiceMap.Reference for MaxOpsBeforeYield configuration instead."
8766
+ ),
8767
+ "withMetric": asRemoved(
8768
+ "Metric configuration has been reworked in Effect v4."
8769
+ ),
8770
+ "withRandom": asRemoved(
8771
+ "Random configuration has been reworked in Effect v4."
8772
+ ),
8773
+ "withRandomFixed": asRemoved(
8774
+ "Random configuration has been reworked in Effect v4."
8775
+ ),
8776
+ "withRandomScoped": asRemoved(
8777
+ "Random configuration has been reworked in Effect v4."
8778
+ ),
8779
+ "withRequestBatching": asRemoved(
8780
+ "Request batching configuration has been reworked in Effect v4."
8781
+ ),
8782
+ "withRequestCache": asRemoved(
8783
+ "Request caching configuration has been reworked in Effect v4."
8784
+ ),
8785
+ "withRequestCaching": asRemoved(
8786
+ "Request caching configuration has been reworked in Effect v4."
8787
+ ),
8788
+ "withRuntimeFlagsPatch": asRemoved(
8789
+ "Runtime flags have been removed in Effect v4."
8790
+ ),
8791
+ "withRuntimeFlagsPatchScoped": asRemoved(
8792
+ "Runtime flags have been removed in Effect v4."
8793
+ ),
8794
+ "withScheduler": asRemoved(
8795
+ "Use ServiceMap.Reference for Scheduler configuration instead."
8796
+ ),
8797
+ "withSchedulingPriority": asRemoved(
8798
+ "Scheduling priority configuration has been removed in Effect v4."
8799
+ ),
8800
+ "withTracerScoped": asRemoved(
8801
+ "Use Effect.withTracer instead."
8802
+ ),
8803
+ "withUnhandledErrorLogLevel": asRemoved(
8804
+ "Use ServiceMap.Reference for UnhandledLogLevel configuration instead."
8805
+ ),
8806
+ "zipLeft": asRemoved(
8807
+ "Use Effect.tap instead of Effect.zipLeft."
8808
+ ),
8809
+ "zipRight": asRemoved(
8810
+ "Use Effect.andThen instead of Effect.zipRight."
8811
+ )
8812
+ };
8813
+
8814
+ // src/diagnostics/outdatedApi.ts
8815
+ var outdatedApi = createDiagnostic({
8816
+ name: "outdatedApi",
8817
+ code: 48,
8818
+ description: "Detects usage of APIs that have been removed or renamed in Effect v4",
8819
+ severity: "warning",
8820
+ apply: fn("outdatedApi.apply")(function* (sourceFile, report) {
8821
+ const typeParser = yield* service(TypeParser);
8822
+ const ts = yield* service(TypeScriptApi);
8823
+ const typeChecker = yield* service(TypeCheckerApi);
8824
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
8825
+ if (typeParser.supportedEffect() === "v3") return;
8826
+ let hasReported = false;
8827
+ function reportMigration(propertyAccess, propertyName, _migration) {
8828
+ hasReported = true;
8829
+ report({
8830
+ location: propertyAccess.name,
8831
+ messageText: `${propertyName} is an Effect v3 API, but the project is using Effect v4.`,
8832
+ fixes: []
8833
+ });
8834
+ }
8835
+ const checkPropertyAccessMigration = (propertyAccess, checkRightNode, migrationDb) => {
8836
+ if (!ts.isPropertyAccessExpression(propertyAccess)) return;
8837
+ const identifier2 = propertyAccess.name;
8838
+ if (!ts.isIdentifier(identifier2)) return;
8839
+ const identifierName = ts.idText(identifier2);
8840
+ const migration = migrationDb[identifierName];
8841
+ if (!migration) return;
8842
+ if (migration._tag === "Unchanged") return;
8843
+ const targetType = typeCheckerUtils.getTypeAtLocation(propertyAccess.expression);
8844
+ if (!targetType) return;
8845
+ const targetPropertySymbol = typeChecker.getPropertyOfType(targetType, identifierName);
8846
+ if (targetPropertySymbol) return;
8847
+ return pipe(
8848
+ checkRightNode(propertyAccess.expression),
8849
+ map4(() => reportMigration(propertyAccess, identifierName, migration)),
8850
+ ignore
8851
+ );
8852
+ };
8853
+ const nodeToVisit = [];
8854
+ const appendNodeToVisit = (node) => {
8855
+ nodeToVisit.push(node);
8856
+ return void 0;
8857
+ };
8858
+ ts.forEachChild(sourceFile, appendNodeToVisit);
8859
+ while (nodeToVisit.length > 0) {
8860
+ const node = nodeToVisit.shift();
8861
+ ts.forEachChild(node, appendNodeToVisit);
8862
+ const checkEffectMigration = checkPropertyAccessMigration(
8863
+ node,
8864
+ typeParser.importedEffectModule,
8865
+ effectModuleMigrationDb
8866
+ );
8867
+ if (checkEffectMigration) {
8868
+ yield* ignore(checkEffectMigration);
8869
+ }
8870
+ }
8871
+ if (hasReported) {
8872
+ report({
8873
+ location: { pos: 0, end: 0 },
8874
+ messageText: "This project targets Effect v4, but is using Effect v3 APIs. To find the correct API to use, clone and consult the github.com/effect-ts/effect-smol repository for the corresponding v4 replacement.",
8875
+ fixes: []
8876
+ });
8877
+ }
8878
+ })
8879
+ });
8880
+
7768
8881
  // src/refactors/writeTagClassAccessors.ts
7769
8882
  var generate = fn("writeTagClassAccessors.generate")(function* (sourceFile, service2, className, atLocation, involvedMembers) {
7770
8883
  const ts = yield* service(TypeScriptApi);
@@ -10204,6 +11317,7 @@ var unsupportedServiceAccessors = createDiagnostic({
10204
11317
 
10205
11318
  // src/diagnostics.ts
10206
11319
  var diagnostics = [
11320
+ outdatedApi,
10207
11321
  anyUnknownInErrorContext,
10208
11322
  instanceOfSchema,
10209
11323
  catchAllToMapError,
@@ -10216,6 +11330,7 @@ var diagnostics = [
10216
11330
  missingEffectServiceDependency,
10217
11331
  missingLayerContext,
10218
11332
  floatingEffect,
11333
+ effectInFailure,
10219
11334
  missingStarInYieldEffectGen,
10220
11335
  unnecessaryEffectGen,
10221
11336
  unnecessaryFailYieldableError,