@effect/language-service 0.72.0 → 0.73.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.
package/index.js CHANGED
@@ -3414,6 +3414,13 @@ var option = (fa) => {
3414
3414
  nano[contE] = (_) => _ instanceof NanoDefectException ? fail3(_) : succeed(none2());
3415
3415
  return nano;
3416
3416
  };
3417
+ var orUndefined = (fa) => {
3418
+ const nano = Object.create(MatchProto);
3419
+ nano[args] = fa;
3420
+ nano[contA] = (_) => succeed(_);
3421
+ nano[contE] = (_) => _ instanceof NanoDefectException ? fail3(_) : succeed(void 0);
3422
+ return nano;
3423
+ };
3417
3424
  var ignore = (fa) => {
3418
3425
  const nano = Object.create(MatchProto);
3419
3426
  nano[args] = fa;
@@ -3617,7 +3624,7 @@ function makeTypeScriptUtils(ts) {
3617
3624
  if (!hasProperty(packageJsonScope, "packageDirectory")) return;
3618
3625
  if (!isString(packageJsonScope.packageDirectory)) return;
3619
3626
  const { name } = packageJsonContent;
3620
- const version = hasProperty(packageJsonScope, "version") ? packageJsonScope.version : "";
3627
+ const version = hasProperty(packageJsonContent, "version") ? packageJsonContent.version : "unknown";
3621
3628
  if (!isString(name)) return;
3622
3629
  if (!isString(version)) return;
3623
3630
  const hasEffectInPeerDependencies = hasProperty(packageJsonContent, "peerDependencies") && isObject(packageJsonContent.peerDependencies) && hasProperty(packageJsonContent.peerDependencies, "effect");
@@ -4909,6 +4916,8 @@ function makeTypeCheckerUtils(ts, typeChecker, tsUtils) {
4909
4916
  }
4910
4917
 
4911
4918
  // src/core/TypeParser.ts
4919
+ var checkedPackagesCache = /* @__PURE__ */ new Map();
4920
+ var programResolvedCacheSize = /* @__PURE__ */ new Map();
4912
4921
  var TypeParser = Tag("@effect/language-service/TypeParser");
4913
4922
  var nanoLayer3 = (fa) => gen(function* () {
4914
4923
  const ts = yield* service(TypeScriptApi);
@@ -4929,6 +4938,42 @@ function typeParserIssue(_message, _type, _node) {
4929
4938
  return TypeParserIssue.issue;
4930
4939
  }
4931
4940
  function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
4941
+ function supportedEffect() {
4942
+ for (const fileName of program.getRootFileNames()) {
4943
+ const sourceFile = program.getSourceFile(fileName);
4944
+ if (!sourceFile) continue;
4945
+ const resolvedPackages = getEffectRelatedPackages(sourceFile);
4946
+ const effectPkgs = resolvedPackages["effect"];
4947
+ if (!effectPkgs) continue;
4948
+ for (const version of Object.keys(effectPkgs)) {
4949
+ if (String(version).startsWith("4")) return "v4";
4950
+ if (String(version).startsWith("3")) return "v3";
4951
+ }
4952
+ }
4953
+ return "v3";
4954
+ }
4955
+ function getEffectRelatedPackages(sourceFile) {
4956
+ let resolvedPackages = checkedPackagesCache.get(sourceFile.fileName) || {};
4957
+ const newResolvedModuleSize = hasProperty(program, "resolvedModules") && hasProperty(program.resolvedModules, "size") && isNumber(program.resolvedModules.size) ? program.resolvedModules.size : 0;
4958
+ const oldResolvedSize = programResolvedCacheSize.get(sourceFile.fileName) || -1;
4959
+ if (newResolvedModuleSize !== oldResolvedSize) {
4960
+ const seenPackages = /* @__PURE__ */ new Set();
4961
+ resolvedPackages = {};
4962
+ program.getSourceFiles().map((_) => {
4963
+ const packageInfo = tsUtils.parsePackageContentNameAndVersionFromScope(_);
4964
+ if (!packageInfo) return;
4965
+ const packageNameAndVersion = packageInfo.name + "@" + packageInfo.version;
4966
+ if (seenPackages.has(packageNameAndVersion)) return;
4967
+ seenPackages.add(packageNameAndVersion);
4968
+ if (!(packageInfo.name === "effect" || packageInfo.hasEffectInPeerDependencies)) return;
4969
+ resolvedPackages[packageInfo.name] = resolvedPackages[packageInfo.name] || {};
4970
+ resolvedPackages[packageInfo.name][packageInfo.version] = packageInfo.packageDirectory;
4971
+ });
4972
+ checkedPackagesCache.set(sourceFile.fileName, resolvedPackages);
4973
+ programResolvedCacheSize.set(sourceFile.fileName, newResolvedModuleSize);
4974
+ }
4975
+ return resolvedPackages;
4976
+ }
4932
4977
  const getSourceFilePackageInfo = cachedBy(
4933
4978
  fn("TypeParser.getSourceFilePackageInfo")(function* (sourceFile) {
4934
4979
  return tsUtils.resolveModuleWithPackageInfoFromSourceFile(program, sourceFile);
@@ -5157,19 +5202,28 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5157
5202
  );
5158
5203
  const effectType = cachedBy(
5159
5204
  fn("TypeParser.effectType")(function* (type, atLocation) {
5160
- const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
5161
- (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
5162
- );
5163
- if (propertiesSymbols.length === 0) {
5164
- return yield* typeParserIssue("Type has no effect variance struct", type, atLocation);
5205
+ if (supportedEffect() === "v4") {
5206
+ const typeIdSymbol = typeChecker.getPropertyOfType(type, "~effect/Effect");
5207
+ if (typeIdSymbol) {
5208
+ const typeIdType = typeChecker.getTypeOfSymbolAtLocation(typeIdSymbol, atLocation);
5209
+ return yield* effectVarianceStruct(typeIdType, atLocation);
5210
+ }
5211
+ return yield* typeParserIssue("Type is not an effect", type, atLocation);
5212
+ } else {
5213
+ const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
5214
+ (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
5215
+ );
5216
+ if (propertiesSymbols.length === 0) {
5217
+ return yield* typeParserIssue("Type has no effect variance struct", type, atLocation);
5218
+ }
5219
+ propertiesSymbols.sort(
5220
+ (a, b) => ts.symbolName(b).indexOf("EffectTypeId") - ts.symbolName(a).indexOf("EffectTypeId")
5221
+ );
5222
+ return yield* firstSuccessOf(propertiesSymbols.map((propertySymbol) => {
5223
+ const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
5224
+ return effectVarianceStruct(propertyType, atLocation);
5225
+ }));
5165
5226
  }
5166
- propertiesSymbols.sort(
5167
- (a, b) => ts.symbolName(b).indexOf("EffectTypeId") - ts.symbolName(a).indexOf("EffectTypeId")
5168
- );
5169
- return yield* firstSuccessOf(propertiesSymbols.map((propertySymbol) => {
5170
- const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
5171
- return effectVarianceStruct(propertyType, atLocation);
5172
- }));
5173
5227
  }),
5174
5228
  "TypeParser.effectType",
5175
5229
  (type) => type
@@ -5298,7 +5352,7 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5298
5352
  fn("TypeParser.isEffectDataSourceFile")(function* (sourceFile) {
5299
5353
  const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
5300
5354
  if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
5301
- const taggedEnumSymbol = typeChecker.tryGetMemberInModuleExports("TaggedEnum", moduleSymbol);
5355
+ const taggedEnumSymbol = typeChecker.tryGetMemberInModuleExports("TaggedEnum", moduleSymbol) || typeChecker.tryGetMemberInModuleExports("taggedEnum", moduleSymbol);
5302
5356
  if (!taggedEnumSymbol) return yield* typeParserIssue("TaggedEnum not found", void 0, sourceFile);
5303
5357
  const taggedErrorSymbol = typeChecker.tryGetMemberInModuleExports("TaggedError", moduleSymbol);
5304
5358
  if (!taggedErrorSymbol) return yield* typeParserIssue("TaggedError not found", void 0, sourceFile);
@@ -5489,10 +5543,10 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5489
5543
  }))
5490
5544
  )
5491
5545
  ),
5492
- option
5546
+ orUndefined
5493
5547
  );
5494
- if (isSome2(isEffectGen)) {
5495
- effectGenResult = isEffectGen.value;
5548
+ if (isEffectGen) {
5549
+ effectGenResult = isEffectGen;
5496
5550
  }
5497
5551
  }
5498
5552
  if (scopeNode && effectGenResult) {
@@ -5612,6 +5666,21 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5612
5666
  const effectSchemaType = cachedBy(
5613
5667
  fn("TypeParser.effectSchemaType")(function* (type, atLocation) {
5614
5668
  yield* pipeableType(type, atLocation);
5669
+ const typeId = typeChecker.getPropertyOfType(type, "~effect/Schema/Schema");
5670
+ if (typeId) {
5671
+ const typeKey = typeChecker.getPropertyOfType(type, "Type");
5672
+ const encodedKey = typeChecker.getPropertyOfType(type, "Encoded");
5673
+ if (typeKey && encodedKey) {
5674
+ const typeType = typeChecker.getTypeOfSymbolAtLocation(typeKey, atLocation);
5675
+ const encodedType = typeChecker.getTypeOfSymbolAtLocation(encodedKey, atLocation);
5676
+ return {
5677
+ A: typeType,
5678
+ I: encodedType,
5679
+ R: typeChecker.getNeverType()
5680
+ };
5681
+ }
5682
+ return yield* typeParserIssue("missing Type and Encoded");
5683
+ }
5615
5684
  const ast = typeChecker.getPropertyOfType(type, "ast");
5616
5685
  if (!ast) return yield* typeParserIssue("Has no 'ast' property", type, atLocation);
5617
5686
  const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
@@ -5830,9 +5899,9 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5830
5899
  if (ts.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
5831
5900
  const isEffectSchemaModuleApi = yield* pipe(
5832
5901
  isNodeReferenceToEffectSchemaModuleApi("Class")(schemaCall.expression),
5833
- option
5902
+ orUndefined
5834
5903
  );
5835
- if (isSome2(isEffectSchemaModuleApi)) {
5904
+ if (isEffectSchemaModuleApi) {
5836
5905
  return {
5837
5906
  className: atLocation.name,
5838
5907
  selfTypeNode: schemaCall.typeArguments[0]
@@ -5867,9 +5936,9 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5867
5936
  const selfTypeNode = schemaTaggedClassTCall.typeArguments[0];
5868
5937
  const isEffectSchemaModuleApi = yield* pipe(
5869
5938
  isNodeReferenceToEffectSchemaModuleApi("TaggedClass")(schemaTaggedClassTCall.expression),
5870
- option
5939
+ orUndefined
5871
5940
  );
5872
- if (isSome2(isEffectSchemaModuleApi)) {
5941
+ if (isEffectSchemaModuleApi) {
5873
5942
  return {
5874
5943
  className: atLocation.name,
5875
5944
  selfTypeNode,
@@ -5906,9 +5975,9 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5906
5975
  const selfTypeNode = schemaTaggedErrorTCall.typeArguments[0];
5907
5976
  const isEffectSchemaModuleApi = yield* pipe(
5908
5977
  isNodeReferenceToEffectSchemaModuleApi("TaggedError")(schemaTaggedErrorTCall.expression),
5909
- option
5978
+ orUndefined
5910
5979
  );
5911
- if (isSome2(isEffectSchemaModuleApi)) {
5980
+ if (isEffectSchemaModuleApi) {
5912
5981
  return {
5913
5982
  className: atLocation.name,
5914
5983
  selfTypeNode,
@@ -5928,6 +5997,9 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5928
5997
  );
5929
5998
  const extendsSchemaTaggedRequest = cachedBy(
5930
5999
  fn("TypeParser.extendsSchemaTaggedRequest")(function* (atLocation) {
6000
+ if (supportedEffect() === "v4") {
6001
+ return yield* typeParserIssue("Schema.TaggedClass is not supported in Effect v4", void 0, atLocation);
6002
+ }
5931
6003
  if (!atLocation.name) {
5932
6004
  return yield* typeParserIssue("Class has no name", void 0, atLocation);
5933
6005
  }
@@ -5945,9 +6017,9 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5945
6017
  const selfTypeNode = schemaTaggedRequestTCall.typeArguments[0];
5946
6018
  const isEffectSchemaModuleApi = yield* pipe(
5947
6019
  isNodeReferenceToEffectSchemaModuleApi("TaggedRequest")(schemaTaggedRequestTCall.expression),
5948
- option
6020
+ orUndefined
5949
6021
  );
5950
- if (isSome2(isEffectSchemaModuleApi)) {
6022
+ if (isEffectSchemaModuleApi) {
5951
6023
  return {
5952
6024
  className: atLocation.name,
5953
6025
  selfTypeNode,
@@ -5965,6 +6037,48 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5965
6037
  "TypeParser.extendsSchemaTaggedRequest",
5966
6038
  (atLocation) => atLocation
5967
6039
  );
6040
+ const extendsSchemaRequestClass = cachedBy(
6041
+ fn("TypeParser.extendsSchemaRequestClass")(function* (atLocation) {
6042
+ if (supportedEffect() === "v3") {
6043
+ return yield* typeParserIssue("Schema.RequestClass is not supported in Effect v3", void 0, atLocation);
6044
+ }
6045
+ if (!atLocation.name) {
6046
+ return yield* typeParserIssue("Class has no name", void 0, atLocation);
6047
+ }
6048
+ const heritageClauses = atLocation.heritageClauses;
6049
+ if (!heritageClauses) {
6050
+ return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
6051
+ }
6052
+ for (const heritageClause of heritageClauses) {
6053
+ for (const typeX of heritageClause.types) {
6054
+ if (ts.isExpressionWithTypeArguments(typeX)) {
6055
+ const expression = typeX.expression;
6056
+ if (ts.isCallExpression(expression)) {
6057
+ const schemaTaggedRequestTCall = expression.expression;
6058
+ if (ts.isCallExpression(schemaTaggedRequestTCall) && schemaTaggedRequestTCall.typeArguments && schemaTaggedRequestTCall.typeArguments.length > 0) {
6059
+ const selfTypeNode = schemaTaggedRequestTCall.typeArguments[0];
6060
+ const isEffectSchemaModuleApi = yield* pipe(
6061
+ isNodeReferenceToEffectSchemaModuleApi("RequestClass")(schemaTaggedRequestTCall.expression),
6062
+ orUndefined
6063
+ );
6064
+ if (isEffectSchemaModuleApi) {
6065
+ return {
6066
+ className: atLocation.name,
6067
+ selfTypeNode,
6068
+ tagStringLiteral: void 0,
6069
+ keyStringLiteral: schemaTaggedRequestTCall.arguments.length > 0 && ts.isStringLiteral(schemaTaggedRequestTCall.arguments[0]) ? schemaTaggedRequestTCall.arguments[0] : void 0
6070
+ };
6071
+ }
6072
+ }
6073
+ }
6074
+ }
6075
+ }
6076
+ }
6077
+ return yield* typeParserIssue("Class does not extend Schema.RequestClass", void 0, atLocation);
6078
+ }),
6079
+ "TypeParser.extendsSchemaRequestClass",
6080
+ (atLocation) => atLocation
6081
+ );
5968
6082
  const extendsDataTaggedError = cachedBy(
5969
6083
  fn("TypeParser.extendsDataTaggedError")(function* (atLocation) {
5970
6084
  if (!atLocation.name) {
@@ -5984,13 +6098,13 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
5984
6098
  if (ts.isPropertyAccessExpression(dataIdentifier) && ts.isIdentifier(dataIdentifier.name) && ts.idText(dataIdentifier.name) === "TaggedError") {
5985
6099
  const parsedDataModule = yield* pipe(
5986
6100
  importedDataModule(dataIdentifier.expression),
5987
- option
6101
+ orUndefined
5988
6102
  );
5989
- if (isSome2(parsedDataModule)) {
6103
+ if (parsedDataModule) {
5990
6104
  return {
5991
6105
  className: atLocation.name,
5992
6106
  keyStringLiteral: dataTaggedErrorCall.arguments.length > 0 && ts.isStringLiteral(dataTaggedErrorCall.arguments[0]) ? dataTaggedErrorCall.arguments[0] : void 0,
5993
- Data: parsedDataModule.value
6107
+ Data: parsedDataModule
5994
6108
  };
5995
6109
  }
5996
6110
  }
@@ -6022,13 +6136,13 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6022
6136
  if (ts.isPropertyAccessExpression(dataIdentifier) && ts.isIdentifier(dataIdentifier.name) && ts.idText(dataIdentifier.name) === "TaggedClass") {
6023
6137
  const parsedDataModule = yield* pipe(
6024
6138
  importedDataModule(dataIdentifier.expression),
6025
- option
6139
+ orUndefined
6026
6140
  );
6027
- if (isSome2(parsedDataModule)) {
6141
+ if (parsedDataModule) {
6028
6142
  return {
6029
6143
  className: atLocation.name,
6030
6144
  keyStringLiteral: dataTaggedClassCall.arguments.length > 0 && ts.isStringLiteral(dataTaggedClassCall.arguments[0]) ? dataTaggedClassCall.arguments[0] : void 0,
6031
- Data: parsedDataModule.value
6145
+ Data: parsedDataModule
6032
6146
  };
6033
6147
  }
6034
6148
  }
@@ -6062,9 +6176,9 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6062
6176
  if (ts.isPropertyAccessExpression(contextTagIdentifier) && ts.isIdentifier(contextTagIdentifier.name) && ts.idText(contextTagIdentifier.name) === "Tag") {
6063
6177
  const parsedContextModule = yield* pipe(
6064
6178
  importedContextModule(contextTagIdentifier.expression),
6065
- option
6179
+ orUndefined
6066
6180
  );
6067
- if (isSome2(parsedContextModule)) {
6181
+ if (parsedContextModule) {
6068
6182
  const classSym = typeChecker.getSymbolAtLocation(atLocation.name);
6069
6183
  if (!classSym) return yield* typeParserIssue("Class has no symbol", void 0, atLocation);
6070
6184
  const type = typeChecker.getTypeOfSymbol(classSym);
@@ -6075,7 +6189,7 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6075
6189
  keyStringLiteral: ts.isStringLiteral(contextTagCall.arguments[0]) ? contextTagCall.arguments[0] : void 0,
6076
6190
  args: contextTagCall.arguments,
6077
6191
  Identifier: tagType.Identifier,
6078
- Tag: parsedContextModule.value
6192
+ Tag: parsedContextModule
6079
6193
  };
6080
6194
  }
6081
6195
  }
@@ -6113,9 +6227,9 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6113
6227
  const selfTypeNode = wholeCall.typeArguments[0];
6114
6228
  const isEffectTag = yield* pipe(
6115
6229
  isNodeReferenceToEffectModuleApi("Tag")(effectTagIdentifier),
6116
- option
6230
+ orUndefined
6117
6231
  );
6118
- if (isSome2(isEffectTag)) {
6232
+ if (isEffectTag) {
6119
6233
  return {
6120
6234
  className: atLocation.name,
6121
6235
  selfTypeNode,
@@ -6155,17 +6269,17 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6155
6269
  const selfTypeNode = effectServiceCall.typeArguments[0];
6156
6270
  const isEffectService = yield* pipe(
6157
6271
  isNodeReferenceToEffectModuleApi("Service")(effectServiceIdentifier),
6158
- option
6272
+ orUndefined
6159
6273
  );
6160
- if (isSome2(isEffectService)) {
6274
+ if (isEffectService) {
6161
6275
  const classSym = typeChecker.getSymbolAtLocation(atLocation.name);
6162
6276
  if (!classSym) return yield* typeParserIssue("Class has no symbol", void 0, atLocation);
6163
6277
  const type = typeChecker.getTypeOfSymbol(classSym);
6164
6278
  const parsedContextTag = yield* pipe(
6165
6279
  contextTag(type, atLocation),
6166
- option
6280
+ orUndefined
6167
6281
  );
6168
- if (isSome2(parsedContextTag)) {
6282
+ if (parsedContextTag) {
6169
6283
  let accessors2 = void 0;
6170
6284
  let dependencies = void 0;
6171
6285
  if (wholeCall.arguments.length >= 2) {
@@ -6182,7 +6296,7 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6182
6296
  }
6183
6297
  }
6184
6298
  return {
6185
- ...parsedContextTag.value,
6299
+ ...parsedContextTag,
6186
6300
  className: atLocation.name,
6187
6301
  selfTypeNode,
6188
6302
  args: wholeCall.arguments,
@@ -6252,9 +6366,9 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6252
6366
  if (ts.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
6253
6367
  const isEffectSchemaModuleApi = yield* pipe(
6254
6368
  isNodeReferenceToEffectSqlModelModuleApi("Class")(schemaCall.expression),
6255
- option
6369
+ orUndefined
6256
6370
  );
6257
- if (isSome2(isEffectSchemaModuleApi)) {
6371
+ if (isEffectSchemaModuleApi) {
6258
6372
  return {
6259
6373
  className: atLocation.name,
6260
6374
  selfTypeNode: schemaCall.typeArguments[0]
@@ -6377,19 +6491,18 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6377
6491
  map8((s) => ({ _tag: "call", ...s }))
6378
6492
  )
6379
6493
  ),
6380
- option
6494
+ orUndefined
6381
6495
  );
6382
- if (isSome2(parsed)) {
6383
- const result2 = parsed.value;
6496
+ if (parsed) {
6384
6497
  let transformations;
6385
6498
  let flowNode;
6386
6499
  let childrenToTraverse = [];
6387
- if (result2._tag === "pipe") {
6388
- const signature = typeChecker.getResolvedSignature(result2.node);
6500
+ if (parsed._tag === "pipe") {
6501
+ const signature = typeChecker.getResolvedSignature(parsed.node);
6389
6502
  const typeArguments = signature ? typeChecker.getTypeArgumentsForResolvedSignature(signature) : void 0;
6390
6503
  transformations = [];
6391
- for (let i = 0; i < result2.args.length; i++) {
6392
- const arg = result2.args[i];
6504
+ for (let i = 0; i < parsed.args.length; i++) {
6505
+ const arg = parsed.args[i];
6393
6506
  const outType = typeArguments?.[i + 1];
6394
6507
  if (ts.isCallExpression(arg)) {
6395
6508
  transformations.push({
@@ -6398,7 +6511,7 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6398
6511
  args: Array.from(arg.arguments),
6399
6512
  // e.g., [(x) => x + 1]
6400
6513
  outType,
6401
- kind: result2.kind
6514
+ kind: parsed.kind
6402
6515
  });
6403
6516
  } else {
6404
6517
  transformations.push({
@@ -6406,17 +6519,17 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6406
6519
  // e.g., Effect.asVoid
6407
6520
  args: void 0,
6408
6521
  outType,
6409
- kind: result2.kind
6522
+ kind: parsed.kind
6410
6523
  });
6411
6524
  }
6412
6525
  }
6413
- flowNode = result2.node;
6414
- childrenToTraverse = result2.args;
6526
+ flowNode = parsed.node;
6527
+ childrenToTraverse = parsed.args;
6415
6528
  } else {
6416
6529
  const callSignature = typeChecker.getResolvedSignature(node);
6417
6530
  const outType = callSignature ? typeChecker.getReturnTypeOfSignature(callSignature) : void 0;
6418
6531
  transformations = [{
6419
- callee: result2.callee,
6532
+ callee: parsed.callee,
6420
6533
  args: void 0,
6421
6534
  outType,
6422
6535
  kind: "call"
@@ -6426,20 +6539,20 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6426
6539
  if (parentFlow) {
6427
6540
  parentFlow.transformations.unshift(...transformations);
6428
6541
  parentFlow.subject = {
6429
- node: result2.subject,
6430
- outType: typeCheckerUtils.getTypeAtLocation(result2.subject)
6542
+ node: parsed.subject,
6543
+ outType: typeCheckerUtils.getTypeAtLocation(parsed.subject)
6431
6544
  };
6432
- workQueue.push([result2.subject, parentFlow]);
6545
+ workQueue.push([parsed.subject, parentFlow]);
6433
6546
  } else {
6434
6547
  const newFlow = {
6435
6548
  node: flowNode,
6436
6549
  subject: {
6437
- node: result2.subject,
6438
- outType: typeCheckerUtils.getTypeAtLocation(result2.subject)
6550
+ node: parsed.subject,
6551
+ outType: typeCheckerUtils.getTypeAtLocation(parsed.subject)
6439
6552
  },
6440
6553
  transformations
6441
6554
  };
6442
- workQueue.push([result2.subject, newFlow]);
6555
+ workQueue.push([parsed.subject, newFlow]);
6443
6556
  }
6444
6557
  for (const child of childrenToTraverse) {
6445
6558
  ts.forEachChild(child, (c) => {
@@ -6449,17 +6562,17 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6449
6562
  continue;
6450
6563
  }
6451
6564
  if (includeEffectFn) {
6452
- const effectFnGenParsed = yield* pipe(effectFnGen(node), option);
6453
- const effectFnUntracedGenParsed = isNone2(effectFnGenParsed) ? yield* pipe(effectFnUntracedGen(node), option) : none2();
6454
- const effectFnNonGenParsed = isNone2(effectFnGenParsed) && isNone2(effectFnUntracedGenParsed) ? yield* pipe(effectFn(node), option) : none2();
6455
- const isEffectFnGen = isSome2(effectFnGenParsed);
6456
- const isEffectFnUntracedGen = isSome2(effectFnUntracedGenParsed);
6457
- const isEffectFnNonGen = isSome2(effectFnNonGenParsed);
6458
- const transformationKind = isEffectFnUntracedGen ? "effectFnUntraced" : "effectFn";
6459
- if (isEffectFnGen || isEffectFnUntracedGen) {
6460
- const effectFnParsed = isEffectFnGen ? effectFnGenParsed : effectFnUntracedGenParsed;
6461
- if (isSome2(effectFnParsed) && effectFnParsed.value.pipeArguments.length > 0) {
6462
- const fnResult = effectFnParsed.value;
6565
+ const effectFnKind = yield* pipe(
6566
+ map8(effectFnGen(node), (_) => ({ kind: "effectFnGen", ..._ })),
6567
+ orElse2(
6568
+ () => map8(effectFnUntracedGen(node), (_) => ({ kind: "effectFnUntracedGen", ..._ }))
6569
+ ),
6570
+ orElse2(() => map8(effectFn(node), (_) => ({ kind: "effectFn", ..._ }))),
6571
+ orUndefined
6572
+ );
6573
+ if (effectFnKind && (effectFnKind.kind === "effectFnGen" || effectFnKind.kind === "effectFnUntracedGen")) {
6574
+ if (effectFnKind.pipeArguments.length > 0) {
6575
+ const fnResult = effectFnKind;
6463
6576
  const pipeArgs = fnResult.pipeArguments;
6464
6577
  const transformations = [];
6465
6578
  let subjectType;
@@ -6479,14 +6592,14 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6479
6592
  callee: arg.expression,
6480
6593
  args: Array.from(arg.arguments),
6481
6594
  outType,
6482
- kind: transformationKind
6595
+ kind: effectFnKind.kind === "effectFnUntracedGen" ? "effectFnUntraced" : "effectFn"
6483
6596
  });
6484
6597
  } else {
6485
6598
  transformations.push({
6486
6599
  callee: arg,
6487
6600
  args: void 0,
6488
6601
  outType,
6489
- kind: transformationKind
6602
+ kind: effectFnKind.kind === "effectFnUntracedGen" ? "effectFnUntraced" : "effectFn"
6490
6603
  });
6491
6604
  }
6492
6605
  }
@@ -6508,8 +6621,8 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6508
6621
  continue;
6509
6622
  }
6510
6623
  }
6511
- if (isEffectFnNonGen && isSome2(effectFnNonGenParsed) && effectFnNonGenParsed.value.pipeArguments.length > 0) {
6512
- const fnResult = effectFnNonGenParsed.value;
6624
+ if (effectFnKind && effectFnKind.kind === "effectFn" && effectFnKind.pipeArguments.length > 0) {
6625
+ const fnResult = effectFnKind;
6513
6626
  const pipeArgs = fnResult.pipeArguments;
6514
6627
  const transformations = [];
6515
6628
  let subjectType;
@@ -6655,11 +6768,14 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
6655
6768
  extendsDataTaggedError,
6656
6769
  extendsDataTaggedClass,
6657
6770
  extendsSchemaTaggedRequest,
6771
+ extendsSchemaRequestClass,
6658
6772
  extendsEffectSqlModelClass,
6659
6773
  lazyExpression,
6660
6774
  emptyFunction,
6661
6775
  pipingFlows,
6662
- reconstructPipingFlow
6776
+ reconstructPipingFlow,
6777
+ getEffectRelatedPackages,
6778
+ supportedEffect
6663
6779
  };
6664
6780
  }
6665
6781
 
@@ -6670,6 +6786,7 @@ var contextSelfInClasses = createCompletion({
6670
6786
  const ts = yield* service(TypeScriptApi);
6671
6787
  const tsUtils = yield* service(TypeScriptUtils);
6672
6788
  const typeParser = yield* service(TypeParser);
6789
+ if (typeParser.supportedEffect() === "v4") return [];
6673
6790
  const maybeInfos = tsUtils.parseDataForExtendsClassCompletion(sourceFile, position);
6674
6791
  if (!maybeInfos) return [];
6675
6792
  const { accessedObject, className, replacementSpan } = maybeInfos;
@@ -7969,6 +8086,7 @@ var catchAllToMapError = createDiagnostic({
7969
8086
  apply: fn("catchAllToMapError.apply")(function* (sourceFile, report) {
7970
8087
  const ts = yield* service(TypeScriptApi);
7971
8088
  const typeParser = yield* service(TypeParser);
8089
+ const catchAllName = typeParser.supportedEffect() === "v3" ? "catchAll" : "catch";
7972
8090
  const getFunctionBody = (node) => {
7973
8091
  if (ts.isArrowFunction(node)) {
7974
8092
  return node.body;
@@ -7983,10 +8101,10 @@ var catchAllToMapError = createDiagnostic({
7983
8101
  if (ts.isCallExpression(body)) {
7984
8102
  const isFailCall = yield* pipe(
7985
8103
  typeParser.isNodeReferenceToEffectModuleApi("fail")(body.expression),
7986
- option
8104
+ orUndefined
7987
8105
  );
7988
- if (isSome2(isFailCall) && body.arguments.length >= 1) {
7989
- return some2({ failCall: body, failArg: body.arguments[0] });
8106
+ if (isFailCall && body.arguments.length >= 1) {
8107
+ return { failCall: body, failArg: body.arguments[0] };
7990
8108
  }
7991
8109
  }
7992
8110
  if (ts.isBlock(body)) {
@@ -7996,15 +8114,14 @@ var catchAllToMapError = createDiagnostic({
7996
8114
  if (ts.isReturnStatement(stmt) && stmt.expression && ts.isCallExpression(stmt.expression)) {
7997
8115
  const isFailCall = yield* pipe(
7998
8116
  typeParser.isNodeReferenceToEffectModuleApi("fail")(stmt.expression.expression),
7999
- option
8117
+ orUndefined
8000
8118
  );
8001
- if (isSome2(isFailCall) && stmt.expression.arguments.length >= 1) {
8002
- return some2({ failCall: stmt.expression, failArg: stmt.expression.arguments[0] });
8119
+ if (isFailCall && stmt.expression.arguments.length >= 1) {
8120
+ return { failCall: stmt.expression, failArg: stmt.expression.arguments[0] };
8003
8121
  }
8004
8122
  }
8005
8123
  }
8006
8124
  }
8007
- return none2();
8008
8125
  });
8009
8126
  };
8010
8127
  const flows = yield* typeParser.pipingFlows(true)(sourceFile);
@@ -8014,10 +8131,10 @@ var catchAllToMapError = createDiagnostic({
8014
8131
  continue;
8015
8132
  }
8016
8133
  const isCatchAllCall = yield* pipe(
8017
- typeParser.isNodeReferenceToEffectModuleApi("catchAll")(transformation.callee),
8018
- option
8134
+ typeParser.isNodeReferenceToEffectModuleApi(catchAllName)(transformation.callee),
8135
+ orUndefined
8019
8136
  );
8020
- if (isNone2(isCatchAllCall)) {
8137
+ if (!isCatchAllCall) {
8021
8138
  continue;
8022
8139
  }
8023
8140
  const callback = transformation.args[0];
@@ -8025,11 +8142,11 @@ var catchAllToMapError = createDiagnostic({
8025
8142
  const functionBody = getFunctionBody(callback);
8026
8143
  if (!functionBody) continue;
8027
8144
  const failCallInfo = yield* getEffectFailCallInfo(functionBody);
8028
- if (isNone2(failCallInfo)) continue;
8029
- const { failArg, failCall } = failCallInfo.value;
8145
+ if (!failCallInfo) continue;
8146
+ const { failArg, failCall } = failCallInfo;
8030
8147
  report({
8031
8148
  location: transformation.callee,
8032
- messageText: `You can use Effect.mapError instead of Effect.catchAll + Effect.fail to transform the error type.`,
8149
+ messageText: `You can use Effect.mapError instead of Effect.${catchAllName} + Effect.fail to transform the error type.`,
8033
8150
  fixes: [{
8034
8151
  fixName: "catchAllToMapError_fix",
8035
8152
  description: "Replace with Effect.mapError",
@@ -8060,7 +8177,7 @@ var catchUnfailableEffect = createDiagnostic({
8060
8177
  apply: fn("catchUnfailableEffect.apply")(function* (sourceFile, report) {
8061
8178
  const ts = yield* service(TypeScriptApi);
8062
8179
  const typeParser = yield* service(TypeParser);
8063
- const catchFunctions = ["catchAll", "catch", "catchIf", "catchSome", "catchTag", "catchTags"];
8180
+ const catchFunctions = typeParser.supportedEffect() === "v3" ? ["catchAll", "catch", "catchIf", "catchSome", "catchTag", "catchTags"] : ["catch", "catchIf", "catchTag", "catchTags"];
8064
8181
  const flows = yield* typeParser.pipingFlows(true)(sourceFile);
8065
8182
  for (const flow2 of flows) {
8066
8183
  for (let i = 0; i < flow2.transformations.length; i++) {
@@ -8125,7 +8242,12 @@ var classSelfMismatch = createDiagnostic({
8125
8242
  orElse2(() => typeParser.extendsSchemaClass(node)),
8126
8243
  orElse2(() => typeParser.extendsSchemaTaggedClass(node)),
8127
8244
  orElse2(() => typeParser.extendsSchemaTaggedError(node)),
8128
- orElse2(() => typeParser.extendsSchemaTaggedRequest(node)),
8245
+ orElse2(
8246
+ () => pipe(
8247
+ typeParser.extendsSchemaTaggedRequest(node),
8248
+ orElse2(() => typeParser.extendsSchemaRequestClass(node))
8249
+ )
8250
+ ),
8129
8251
  orElse2(() => typeParser.extendsEffectSqlModelClass(node)),
8130
8252
  orElse2(() => void_)
8131
8253
  );
@@ -8286,39 +8408,18 @@ var deterministicKeys = createDiagnostic({
8286
8408
  });
8287
8409
 
8288
8410
  // src/diagnostics/duplicatePackage.ts
8289
- var checkedPackagesCache = /* @__PURE__ */ new Map();
8290
- var programResolvedCacheSize = /* @__PURE__ */ new Map();
8291
8411
  var duplicatePackage = createDiagnostic({
8292
8412
  name: "duplicatePackage",
8293
8413
  code: 6,
8294
8414
  description: "Detects when multiple versions of the same Effect package are loaded",
8295
8415
  severity: "warning",
8296
8416
  apply: fn("duplicatePackage.apply")(function* (sourceFile, report) {
8297
- const program = yield* service(TypeScriptProgram);
8298
- const tsUtils = yield* service(TypeScriptUtils);
8417
+ const typeParser = yield* service(TypeParser);
8299
8418
  const options = yield* service(LanguageServicePluginOptions);
8300
8419
  if (sourceFile.statements.length < 1) return;
8301
- let resolvedPackages = checkedPackagesCache.get(sourceFile.fileName) || {};
8302
- const newResolvedModuleSize = hasProperty(program, "resolvedModules") && hasProperty(program.resolvedModules, "size") && isNumber(program.resolvedModules.size) ? program.resolvedModules.size : 0;
8303
- const oldResolvedSize = programResolvedCacheSize.get(sourceFile.fileName) || -1;
8304
- if (newResolvedModuleSize !== oldResolvedSize) {
8305
- const seenPackages = /* @__PURE__ */ new Set();
8306
- resolvedPackages = {};
8307
- program.getSourceFiles().map((_) => {
8308
- const packageInfo = tsUtils.parsePackageContentNameAndVersionFromScope(_);
8309
- if (!packageInfo) return;
8310
- const packageNameAndVersion = packageInfo.name + "@" + packageInfo.version;
8311
- if (seenPackages.has(packageNameAndVersion)) return;
8312
- seenPackages.add(packageNameAndVersion);
8313
- if (!(packageInfo.name === "effect" || packageInfo.hasEffectInPeerDependencies)) return;
8314
- if (options.allowedDuplicatedPackages.indexOf(packageInfo.name) > -1) return;
8315
- resolvedPackages[packageInfo.name] = resolvedPackages[packageInfo.name] || {};
8316
- resolvedPackages[packageInfo.name][packageInfo.version] = packageInfo.packageDirectory;
8317
- });
8318
- checkedPackagesCache.set(sourceFile.fileName, resolvedPackages);
8319
- programResolvedCacheSize.set(sourceFile.fileName, newResolvedModuleSize);
8320
- }
8420
+ const resolvedPackages = typeParser.getEffectRelatedPackages(sourceFile);
8321
8421
  for (const packageName of Object.keys(resolvedPackages)) {
8422
+ if (options.allowedDuplicatedPackages.indexOf(packageName) > -1) return;
8322
8423
  if (Object.keys(resolvedPackages[packageName]).length > 1) {
8323
8424
  const versions = Object.keys(resolvedPackages[packageName]);
8324
8425
  report({
@@ -9142,23 +9243,25 @@ var globalErrorInEffectCatch = createDiagnostic({
9142
9243
  if (isEffectWithCatch) {
9143
9244
  const signature = typeChecker.getResolvedSignature(node);
9144
9245
  if (signature) {
9145
- const objectType = typeChecker.getParameterType(signature, 0);
9146
- const catchFunctionSymbol = typeChecker.getPropertyOfType(objectType, "catch");
9147
- if (catchFunctionSymbol) {
9148
- const catchFunctionType = typeChecker.getTypeOfSymbolAtLocation(catchFunctionSymbol, node);
9149
- const signatures = typeChecker.getSignaturesOfType(catchFunctionType, ts.SignatureKind.Call);
9150
- if (signatures.length > 0) {
9151
- const returnType = typeChecker.getReturnTypeOfSignature(signatures[0]);
9152
- if (returnType && typeCheckerUtils.isGlobalErrorType(returnType)) {
9153
- const nodeText = sourceFile.text.substring(
9154
- ts.getTokenPosOfNode(node.expression, sourceFile),
9155
- node.expression.end
9156
- );
9157
- report({
9158
- location: node.expression,
9159
- messageText: `The 'catch' callback in ${nodeText} returns global 'Error', which loses type safety as untagged errors merge together. Consider using a tagged error and optionally wrapping the original in a 'cause' property.`,
9160
- fixes: []
9161
- });
9246
+ const firstParameterType = typeChecker.getParameterType(signature, 0);
9247
+ for (const objectType of typeCheckerUtils.unrollUnionMembers(firstParameterType)) {
9248
+ const catchFunctionSymbol = typeChecker.getPropertyOfType(objectType, "catch");
9249
+ if (catchFunctionSymbol) {
9250
+ const catchFunctionType = typeChecker.getTypeOfSymbolAtLocation(catchFunctionSymbol, node);
9251
+ const signatures = typeChecker.getSignaturesOfType(catchFunctionType, ts.SignatureKind.Call);
9252
+ if (signatures.length > 0) {
9253
+ const returnType = typeChecker.getReturnTypeOfSignature(signatures[0]);
9254
+ if (returnType && typeCheckerUtils.isGlobalErrorType(returnType)) {
9255
+ const nodeText = sourceFile.text.substring(
9256
+ ts.getTokenPosOfNode(node.expression, sourceFile),
9257
+ node.expression.end
9258
+ );
9259
+ report({
9260
+ location: node.expression,
9261
+ messageText: `The 'catch' callback in ${nodeText} returns global 'Error', which loses type safety as untagged errors merge together. Consider using a tagged error and optionally wrapping the original in a 'cause' property.`,
9262
+ fixes: []
9263
+ });
9264
+ }
9162
9265
  }
9163
9266
  }
9164
9267
  }
@@ -9971,22 +10074,23 @@ var missingEffectError = createDiagnostic({
9971
10074
  map8((result) => {
9972
10075
  if (result.missingErrorTypes.length === 0) return;
9973
10076
  const fixes = [];
9974
- if (ts.isExpression(valueNode) && result.expectedErrorType.flags & ts.TypeFlags.Never) {
10077
+ const catchAllErrorsName = typeParser.supportedEffect() === "v3" ? "catchAll" : "catch";
10078
+ if (ts.isExpression(valueNode) && result.expectedErrorType.flags & ts.TypeFlags.Never && catchAllErrorsName) {
9975
10079
  fixes.push({
9976
- fixName: "missingEffectError_catchAll",
9977
- description: "Catch all errors with Effect.catchAll",
10080
+ fixName: `missingEffectError_${catchAllErrorsName}`,
10081
+ description: `Catch all errors with Effect.${catchAllErrorsName}`,
9978
10082
  apply: gen(function* () {
9979
10083
  const changeTracker = yield* service(ChangeTracker);
9980
10084
  changeTracker.insertText(
9981
10085
  sourceFile,
9982
10086
  ts.getTokenPosOfNode(valueNode, sourceFile),
9983
- effectModuleIdentifier + ".catchAll("
10087
+ effectModuleIdentifier + `.${catchAllErrorsName}(`
9984
10088
  );
9985
10089
  changeTracker.insertText(sourceFile, valueNode.end, ", () => ");
9986
10090
  changeTracker.insertNodeAt(
9987
10091
  sourceFile,
9988
10092
  valueNode.end,
9989
- createDieMessage("TODO: catchAll not implemented")
10093
+ createDieMessage(`TODO: ${catchAllErrorsName} not implemented`)
9990
10094
  );
9991
10095
  changeTracker.insertText(sourceFile, valueNode.end, ")");
9992
10096
  })
@@ -10068,6 +10172,7 @@ var missingEffectServiceDependency = createDiagnostic({
10068
10172
  const typeChecker = yield* service(TypeCheckerApi);
10069
10173
  const typeCheckerUtils = yield* service(TypeCheckerUtils);
10070
10174
  const typeParser = yield* service(TypeParser);
10175
+ if (typeParser.supportedEffect() !== "v3") return;
10071
10176
  const nodeToVisit = [];
10072
10177
  const appendNodeToVisit = (node) => {
10073
10178
  nodeToVisit.push(node);
@@ -11254,6 +11359,7 @@ var scopeInLayerEffect = createDiagnostic({
11254
11359
  const typeChecker = yield* service(TypeCheckerApi);
11255
11360
  const typeParser = yield* service(TypeParser);
11256
11361
  const typeCheckerUtils = yield* service(TypeCheckerUtils);
11362
+ if (typeParser.supportedEffect() !== "v3") return;
11257
11363
  const layerModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
11258
11364
  sourceFile,
11259
11365
  "effect",
@@ -11462,6 +11568,17 @@ var tryCatchInEffectGen = createDiagnostic({
11462
11568
  apply: fn("tryCatchInEffectGen.apply")(function* (sourceFile, report) {
11463
11569
  const ts = yield* service(TypeScriptApi);
11464
11570
  const typeParser = yield* service(TypeParser);
11571
+ const alternatives = typeParser.supportedEffect() === "v4" ? [
11572
+ "Effect.try",
11573
+ "Effect.tryPromise",
11574
+ "Effect.catch",
11575
+ "Effect.catchTag"
11576
+ ] : [
11577
+ "Effect.try",
11578
+ "Effect.tryPromise",
11579
+ "Effect.catchAll",
11580
+ "Effect.catchTag"
11581
+ ];
11465
11582
  const nodeToVisit = [];
11466
11583
  const appendNodeToVisit = (node) => {
11467
11584
  nodeToVisit.push(node);
@@ -11487,7 +11604,7 @@ var tryCatchInEffectGen = createDiagnostic({
11487
11604
  map8(() => {
11488
11605
  report({
11489
11606
  location: node,
11490
- messageText: "Avoid using try/catch inside Effect generators. Use Effect's error handling mechanisms instead (e.g., Effect.try, Effect.tryPromise, Effect.catchAll, Effect.catchTag).",
11607
+ messageText: `Avoid using try/catch inside Effect generators. Use Effect's error handling mechanisms instead (e.g. ${alternatives.join(", ")}).`,
11491
11608
  fixes: []
11492
11609
  });
11493
11610
  }),
@@ -11509,6 +11626,7 @@ var unknownInEffectCatch = createDiagnostic({
11509
11626
  const ts = yield* service(TypeScriptApi);
11510
11627
  const typeParser = yield* service(TypeParser);
11511
11628
  const typeChecker = yield* service(TypeCheckerApi);
11629
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
11512
11630
  const nodeToVisit = [];
11513
11631
  const appendNodeToVisit = (node) => {
11514
11632
  nodeToVisit.push(node);
@@ -11529,24 +11647,26 @@ var unknownInEffectCatch = createDiagnostic({
11529
11647
  if (isEffectWithCatch) {
11530
11648
  const signature = typeChecker.getResolvedSignature(node);
11531
11649
  if (signature) {
11532
- const objectType = typeChecker.getParameterType(signature, 0);
11533
- const catchFunctionSymbol = typeChecker.getPropertyOfType(objectType, "catch");
11534
- if (catchFunctionSymbol) {
11535
- const catchFunctionType = typeChecker.getTypeOfSymbolAtLocation(catchFunctionSymbol, node);
11536
- const signatures = typeChecker.getSignaturesOfType(catchFunctionType, ts.SignatureKind.Call);
11537
- if (signatures.length > 0) {
11538
- const returnType = typeChecker.getReturnTypeOfSignature(signatures[0]);
11539
- if (returnType && (returnType.flags & ts.TypeFlags.Unknown || returnType.flags & ts.TypeFlags.Any)) {
11540
- const nodeText = sourceFile.text.substring(
11541
- ts.getTokenPosOfNode(node.expression, sourceFile),
11542
- node.expression.end
11543
- );
11544
- report({
11545
- location: node.expression,
11546
- messageText: `The 'catch' callback in ${nodeText} returns 'unknown'. The catch callback should be used to provide typed errors.
11650
+ const parameterType = typeChecker.getParameterType(signature, 0);
11651
+ for (const objectType of typeCheckerUtils.unrollUnionMembers(parameterType)) {
11652
+ const catchFunctionSymbol = typeChecker.getPropertyOfType(objectType, "catch");
11653
+ if (catchFunctionSymbol) {
11654
+ const catchFunctionType = typeChecker.getTypeOfSymbolAtLocation(catchFunctionSymbol, node);
11655
+ const signatures = typeChecker.getSignaturesOfType(catchFunctionType, ts.SignatureKind.Call);
11656
+ if (signatures.length > 0) {
11657
+ const returnType = typeChecker.getReturnTypeOfSignature(signatures[0]);
11658
+ if (returnType && (returnType.flags & ts.TypeFlags.Unknown || returnType.flags & ts.TypeFlags.Any)) {
11659
+ const nodeText = sourceFile.text.substring(
11660
+ ts.getTokenPosOfNode(node.expression, sourceFile),
11661
+ node.expression.end
11662
+ );
11663
+ report({
11664
+ location: node.expression,
11665
+ messageText: `The 'catch' callback in ${nodeText} returns 'unknown'. The catch callback should be used to provide typed errors.
11547
11666
  Consider wrapping unknown errors into Effect's Data.TaggedError for example, or narrow down the type to the specific error raised.`,
11548
- fixes: []
11549
- });
11667
+ fixes: []
11668
+ });
11669
+ }
11550
11670
  }
11551
11671
  }
11552
11672
  }
@@ -11982,50 +12102,90 @@ var effectSchemaSelfInClasses = createCompletion({
11982
12102
  isSnippet: true
11983
12103
  });
11984
12104
  }
11985
- const hasTaggedErrorCompletion = isFullyQualified || isSome2(
11986
- yield* pipe(
11987
- typeParser.isNodeReferenceToEffectSchemaModuleApi("TaggedError")(accessedObject),
11988
- option
11989
- )
11990
- );
11991
- if (hasTaggedErrorCompletion) {
11992
- completions2.push({
11993
- name: `TaggedError<${name}>`,
11994
- kind: ts.ScriptElementKind.constElement,
11995
- insertText: isFullyQualified ? `${schemaIdentifier}.TaggedError<${name}>()("${errorTagKey}", {${"${0}"}}){}` : `TaggedError<${name}>()("${errorTagKey}", {${"${0}"}}){}`,
11996
- replacementSpan,
11997
- isSnippet: true
11998
- });
12105
+ if (typeParser.supportedEffect() === "v3") {
12106
+ const hasTaggedErrorCompletion = isFullyQualified || isSome2(
12107
+ yield* pipe(
12108
+ typeParser.isNodeReferenceToEffectSchemaModuleApi("TaggedError")(accessedObject),
12109
+ option
12110
+ )
12111
+ );
12112
+ if (hasTaggedErrorCompletion) {
12113
+ completions2.push({
12114
+ name: `TaggedError<${name}>`,
12115
+ kind: ts.ScriptElementKind.constElement,
12116
+ insertText: isFullyQualified ? `${schemaIdentifier}.TaggedError<${name}>()("${errorTagKey}", {${"${0}"}}){}` : `TaggedError<${name}>()("${errorTagKey}", {${"${0}"}}){}`,
12117
+ replacementSpan,
12118
+ isSnippet: true
12119
+ });
12120
+ }
11999
12121
  }
12000
- const hasTaggedClassCompletion = isFullyQualified || isSome2(
12001
- yield* pipe(
12002
- typeParser.isNodeReferenceToEffectSchemaModuleApi("TaggedClass")(accessedObject),
12003
- option
12004
- )
12005
- );
12006
- if (hasTaggedClassCompletion) {
12007
- completions2.push({
12008
- name: `TaggedClass<${name}>`,
12009
- kind: ts.ScriptElementKind.constElement,
12010
- insertText: isFullyQualified ? `${schemaIdentifier}.TaggedClass<${name}>()("${name}", {${"${0}"}}){}` : `TaggedClass<${name}>()("${name}", {${"${0}"}}){}`,
12011
- replacementSpan,
12012
- isSnippet: true
12013
- });
12122
+ if (typeParser.supportedEffect() === "v3") {
12123
+ const hasTaggedClassCompletion = isFullyQualified || isSome2(
12124
+ yield* pipe(
12125
+ typeParser.isNodeReferenceToEffectSchemaModuleApi("TaggedClass")(accessedObject),
12126
+ option
12127
+ )
12128
+ );
12129
+ if (hasTaggedClassCompletion) {
12130
+ completions2.push({
12131
+ name: `TaggedClass<${name}>`,
12132
+ kind: ts.ScriptElementKind.constElement,
12133
+ insertText: isFullyQualified ? `${schemaIdentifier}.TaggedClass<${name}>()("${name}", {${"${0}"}}){}` : `TaggedClass<${name}>()("${name}", {${"${0}"}}){}`,
12134
+ replacementSpan,
12135
+ isSnippet: true
12136
+ });
12137
+ }
12014
12138
  }
12015
- const hasTaggedRequestCompletion = isFullyQualified || isSome2(
12016
- yield* pipe(
12017
- typeParser.isNodeReferenceToEffectSchemaModuleApi("TaggedRequest")(accessedObject),
12018
- option
12019
- )
12020
- );
12021
- if (hasTaggedRequestCompletion) {
12022
- completions2.push({
12023
- name: `TaggedRequest<${name}>`,
12024
- kind: ts.ScriptElementKind.constElement,
12025
- insertText: isFullyQualified ? `${schemaIdentifier}.TaggedRequest<${name}>()("${name}", {${"${0}"}}){}` : `TaggedRequest<${name}>()("${name}", {${"${0}"}}){}`,
12026
- replacementSpan,
12027
- isSnippet: true
12028
- });
12139
+ if (typeParser.supportedEffect() === "v3") {
12140
+ const hasTaggedRequestCompletion = isFullyQualified || isSome2(
12141
+ yield* pipe(
12142
+ typeParser.isNodeReferenceToEffectSchemaModuleApi("TaggedRequest")(accessedObject),
12143
+ option
12144
+ )
12145
+ );
12146
+ if (hasTaggedRequestCompletion) {
12147
+ completions2.push({
12148
+ name: `TaggedRequest<${name}>`,
12149
+ kind: ts.ScriptElementKind.constElement,
12150
+ insertText: isFullyQualified ? `${schemaIdentifier}.TaggedRequest<${name}>()("${name}", {${"${0}"}}){}` : `TaggedRequest<${name}>()("${name}", {${"${0}"}}){}`,
12151
+ replacementSpan,
12152
+ isSnippet: true
12153
+ });
12154
+ }
12155
+ }
12156
+ if (typeParser.supportedEffect() === "v4") {
12157
+ const hasErrorClassCompletion = isFullyQualified || isSome2(
12158
+ yield* pipe(
12159
+ typeParser.isNodeReferenceToEffectSchemaModuleApi("ErrorClass")(accessedObject),
12160
+ option
12161
+ )
12162
+ );
12163
+ if (hasErrorClassCompletion) {
12164
+ completions2.push({
12165
+ name: `ErrorClass<${name}>`,
12166
+ kind: ts.ScriptElementKind.constElement,
12167
+ insertText: isFullyQualified ? `${schemaIdentifier}.ErrorClass<${name}>()({${"${0}"}}){}` : `ErrorClass<${name}>()({${"${0}"}}){}`,
12168
+ replacementSpan,
12169
+ isSnippet: true
12170
+ });
12171
+ }
12172
+ }
12173
+ if (typeParser.supportedEffect() === "v4") {
12174
+ const hasRequestClassCompletion = isFullyQualified || isSome2(
12175
+ yield* pipe(
12176
+ typeParser.isNodeReferenceToEffectSchemaModuleApi("RequestClass")(accessedObject),
12177
+ option
12178
+ )
12179
+ );
12180
+ if (hasRequestClassCompletion) {
12181
+ completions2.push({
12182
+ name: `RequestClass<${name}>`,
12183
+ kind: ts.ScriptElementKind.constElement,
12184
+ insertText: isFullyQualified ? `${schemaIdentifier}.RequestClass<${name}>("${name}")({${"${0}"}}){}` : `RequestClass<${name}>("${name}")({${"${0}"}}){}`,
12185
+ replacementSpan,
12186
+ isSnippet: true
12187
+ });
12188
+ }
12029
12189
  }
12030
12190
  return completions2;
12031
12191
  })
@@ -12050,35 +12210,39 @@ var effectSelfInClasses = createCompletion({
12050
12210
  const name = ts.idText(className);
12051
12211
  const tagKey = (yield* createString(sourceFile, name, "service")) || name;
12052
12212
  const completions2 = [];
12053
- const hasServiceCompletion = isFullyQualified || isSome2(
12054
- yield* pipe(
12055
- typeParser.isNodeReferenceToEffectModuleApi("Service")(accessedObject),
12056
- option
12057
- )
12058
- );
12059
- if (hasServiceCompletion) {
12060
- completions2.push({
12061
- name: `Service<${name}>`,
12062
- kind: ts.ScriptElementKind.constElement,
12063
- insertText: isFullyQualified ? `${effectIdentifier}.Service<${name}>()("${tagKey}", {${"${0}"}}){}` : `Service<${name}>()("${tagKey}", {${"${0}"}}){}`,
12064
- replacementSpan,
12065
- isSnippet: true
12066
- });
12213
+ if (typeParser.supportedEffect() === "v3") {
12214
+ const hasServiceCompletion = isFullyQualified || isSome2(
12215
+ yield* pipe(
12216
+ typeParser.isNodeReferenceToEffectModuleApi("Service")(accessedObject),
12217
+ option
12218
+ )
12219
+ );
12220
+ if (hasServiceCompletion) {
12221
+ completions2.push({
12222
+ name: `Service<${name}>`,
12223
+ kind: ts.ScriptElementKind.constElement,
12224
+ insertText: isFullyQualified ? `${effectIdentifier}.Service<${name}>()("${tagKey}", {${"${0}"}}){}` : `Service<${name}>()("${tagKey}", {${"${0}"}}){}`,
12225
+ replacementSpan,
12226
+ isSnippet: true
12227
+ });
12228
+ }
12067
12229
  }
12068
- const hasTagCompletion = isFullyQualified || isSome2(
12069
- yield* pipe(
12070
- typeParser.isNodeReferenceToEffectModuleApi("Tag")(accessedObject),
12071
- option
12072
- )
12073
- );
12074
- if (hasTagCompletion) {
12075
- completions2.push({
12076
- name: `Tag("${name}")`,
12077
- kind: ts.ScriptElementKind.constElement,
12078
- insertText: isFullyQualified ? `${effectIdentifier}.Tag("${tagKey}")<${name}, {${"${0}"}}>(){}` : `Tag("${tagKey}")<${name}, {${"${0}"}}>(){}`,
12079
- replacementSpan,
12080
- isSnippet: true
12081
- });
12230
+ if (typeParser.supportedEffect() === "v3") {
12231
+ const hasTagCompletion = isFullyQualified || isSome2(
12232
+ yield* pipe(
12233
+ typeParser.isNodeReferenceToEffectModuleApi("Tag")(accessedObject),
12234
+ option
12235
+ )
12236
+ );
12237
+ if (hasTagCompletion) {
12238
+ completions2.push({
12239
+ name: `Tag("${name}")`,
12240
+ kind: ts.ScriptElementKind.constElement,
12241
+ insertText: isFullyQualified ? `${effectIdentifier}.Tag("${tagKey}")<${name}, {${"${0}"}}>(){}` : `Tag("${tagKey}")<${name}, {${"${0}"}}>(){}`,
12242
+ replacementSpan,
12243
+ isSnippet: true
12244
+ });
12245
+ }
12082
12246
  }
12083
12247
  return completions2;
12084
12248
  })
@@ -12091,6 +12255,7 @@ var effectSqlModelSelfInClasses = createCompletion({
12091
12255
  const ts = yield* service(TypeScriptApi);
12092
12256
  const tsUtils = yield* service(TypeScriptUtils);
12093
12257
  const typeParser = yield* service(TypeParser);
12258
+ if (typeParser.supportedEffect() === "v4") return [];
12094
12259
  const maybeInfos = tsUtils.parseDataForExtendsClassCompletion(sourceFile, position);
12095
12260
  if (!maybeInfos) return [];
12096
12261
  const { accessedObject, className, replacementSpan } = maybeInfos;
@@ -12207,6 +12372,8 @@ var rpcMakeClasses = createCompletion({
12207
12372
  apply: fn("rpcMakeClasses")(function* (sourceFile, position) {
12208
12373
  const ts = yield* service(TypeScriptApi);
12209
12374
  const tsUtils = yield* service(TypeScriptUtils);
12375
+ const typeParser = yield* service(TypeParser);
12376
+ if (typeParser.supportedEffect() === "v4") return [];
12210
12377
  const maybeInfos = tsUtils.parseDataForExtendsClassCompletion(sourceFile, position);
12211
12378
  if (!maybeInfos) return [];
12212
12379
  const { accessedObject, className, replacementSpan } = maybeInfos;
@@ -12233,6 +12400,8 @@ var schemaBrand = createCompletion({
12233
12400
  apply: fn("schemaBrand")(function* (sourceFile, position) {
12234
12401
  const ts = yield* service(TypeScriptApi);
12235
12402
  const tsUtils = yield* service(TypeScriptUtils);
12403
+ const typeParser = yield* service(TypeParser);
12404
+ if (typeParser.supportedEffect() === "v4") return [];
12236
12405
  const maybeInfos = tsUtils.parseAccessedExpressionForCompletion(sourceFile, position);
12237
12406
  if (!maybeInfos) return [];
12238
12407
  const { accessedObject } = maybeInfos;
@@ -18500,6 +18669,12 @@ var effectGenToFn = createRefactor({
18500
18669
  const ts = yield* service(TypeScriptApi);
18501
18670
  const tsUtils = yield* service(TypeScriptUtils);
18502
18671
  const typeParser = yield* service(TypeParser);
18672
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
18673
+ const effectIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
18674
+ sourceFile,
18675
+ "effect",
18676
+ "Effect"
18677
+ ) || "Effect";
18503
18678
  const skipReturnBlock = (node) => ts.isBlock(node) && node.statements.length === 1 && ts.isReturnStatement(node.statements[0]) && node.statements[0].expression ? node.statements[0].expression : node;
18504
18679
  const parseFunctionLikeReturnEffectGen = fn("parseFunctionLikeReturnEffect.apply")(function* (node) {
18505
18680
  if ((ts.isArrowFunction(node) || ts.isMethodDeclaration(node) || ts.isFunctionDeclaration(node)) && node.body) {
@@ -18550,6 +18725,45 @@ var effectGenToFn = createRefactor({
18550
18725
  effectModule,
18551
18726
  "fn"
18552
18727
  );
18728
+ let returnType = void 0;
18729
+ if (nodeToReplace.type) {
18730
+ const actualType = typeCheckerUtils.getTypeAtLocation(nodeToReplace.type);
18731
+ if (actualType) {
18732
+ const maybeType = yield* pipe(
18733
+ typeParser.strictEffectType(actualType, nodeToReplace.type),
18734
+ orUndefined
18735
+ );
18736
+ if (maybeType) {
18737
+ const aType = typeCheckerUtils.typeToSimplifiedTypeNode(
18738
+ maybeType.A,
18739
+ nodeToReplace,
18740
+ ts.NodeBuilderFlags.NoTruncation
18741
+ );
18742
+ const eType = typeCheckerUtils.typeToSimplifiedTypeNode(
18743
+ maybeType.E,
18744
+ nodeToReplace,
18745
+ ts.NodeBuilderFlags.NoTruncation
18746
+ );
18747
+ const rType = typeCheckerUtils.typeToSimplifiedTypeNode(
18748
+ maybeType.R,
18749
+ nodeToReplace,
18750
+ ts.NodeBuilderFlags.NoTruncation
18751
+ );
18752
+ if (aType && eType && rType) {
18753
+ returnType = ts.factory.createTypeReferenceNode(
18754
+ ts.factory.createQualifiedName(
18755
+ ts.factory.createQualifiedName(
18756
+ ts.factory.createIdentifier(effectIdentifier),
18757
+ ts.factory.createIdentifier("fn")
18758
+ ),
18759
+ ts.factory.createIdentifier("Return")
18760
+ ),
18761
+ [aType, eType, rType]
18762
+ );
18763
+ }
18764
+ }
18765
+ }
18766
+ }
18553
18767
  const effectFnCallWithGenerator = ts.factory.createCallExpression(
18554
18768
  effectFn,
18555
18769
  void 0,
@@ -18559,7 +18773,7 @@ var effectGenToFn = createRefactor({
18559
18773
  void 0,
18560
18774
  nodeToReplace.typeParameters,
18561
18775
  nodeToReplace.parameters,
18562
- nodeToReplace.type,
18776
+ returnType,
18563
18777
  generatorFunction.body
18564
18778
  )].concat(pipeArgs)
18565
18779
  );