@effect/language-service 0.73.0 → 0.74.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect/language-service",
3
- "version": "0.73.0",
3
+ "version": "0.74.0",
4
4
  "description": "A Language-Service Plugin to Refactor and Diagnostic effect-ts projects",
5
5
  "main": "index.cjs",
6
6
  "bin": {
package/transform.js CHANGED
@@ -1967,7 +1967,7 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
1967
1967
  const lineOverrides = {};
1968
1968
  const sectionOverrides = {};
1969
1969
  const skippedRules = [];
1970
- const regex = /@effect-diagnostics(-next-line)?((?:\s[a-zA-Z0-9/]+:(?:off|warning|error|message|suggestion|skip-file))+)?/gm;
1970
+ const regex = /@effect-diagnostics(-next-line)?((?:\s(?:[a-zA-Z0-9/]+|\*):(?:off|warning|error|message|suggestion|skip-file))+)?/gm;
1971
1971
  let match2;
1972
1972
  while ((match2 = regex.exec(sourceFile.text)) !== null) {
1973
1973
  const nextLineCaptureGroup = match2[1];
@@ -2016,8 +2016,10 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
2016
2016
  const codeFixes = [];
2017
2017
  const ruleNameLowered = rule.name.toLowerCase();
2018
2018
  const defaultLevel = pluginOptions.diagnosticSeverity[ruleNameLowered] || rule.severity;
2019
- if (skippedRules.indexOf(ruleNameLowered) > -1) return { diagnostics: diagnostics2, codeFixes };
2020
- if (defaultLevel === "off" && (lineOverrides[ruleNameLowered] || sectionOverrides[ruleNameLowered] || []).length === 0) {
2019
+ if (skippedRules.indexOf(ruleNameLowered) > -1 || skippedRules.indexOf("*") > -1) {
2020
+ return { diagnostics: diagnostics2, codeFixes };
2021
+ }
2022
+ if (defaultLevel === "off" && (lineOverrides[ruleNameLowered] || sectionOverrides[ruleNameLowered] || lineOverrides["*"] || sectionOverrides["*"] || []).length === 0) {
2021
2023
  return { diagnostics: diagnostics2, codeFixes };
2022
2024
  }
2023
2025
  const fixByDisableNextLine = (node) => ({
@@ -2066,14 +2068,22 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
2066
2068
  const unusedLineOverrides = new Set(lineOverrides[ruleNameLowered] || []);
2067
2069
  for (const emitted of applicableDiagnostics.slice(0)) {
2068
2070
  let newLevel = defaultLevel;
2069
- const lineOverride = (lineOverrides[ruleNameLowered] || []).find(
2071
+ const specificLineOverride = (lineOverrides[ruleNameLowered] || []).find(
2072
+ (_) => _.pos < emitted.range.pos && _.end >= emitted.range.end
2073
+ );
2074
+ const wildcardLineOverride = (lineOverrides["*"] || []).find(
2070
2075
  (_) => _.pos < emitted.range.pos && _.end >= emitted.range.end
2071
2076
  );
2077
+ const lineOverride = specificLineOverride && wildcardLineOverride ? specificLineOverride.pos >= wildcardLineOverride.pos ? specificLineOverride : wildcardLineOverride : specificLineOverride || wildcardLineOverride;
2072
2078
  if (lineOverride) {
2073
2079
  newLevel = lineOverride.level;
2074
2080
  unusedLineOverrides.delete(lineOverride);
2075
2081
  } else {
2076
- const sectionOverride = (sectionOverrides[ruleNameLowered] || []).find((_) => _.pos < emitted.range.pos);
2082
+ const specificSectionOverride = (sectionOverrides[ruleNameLowered] || []).find(
2083
+ (_) => _.pos < emitted.range.pos
2084
+ );
2085
+ const wildcardSectionOverride = (sectionOverrides["*"] || []).find((_) => _.pos < emitted.range.pos);
2086
+ const sectionOverride = specificSectionOverride && wildcardSectionOverride ? specificSectionOverride.pos >= wildcardSectionOverride.pos ? specificSectionOverride : wildcardSectionOverride : specificSectionOverride || wildcardSectionOverride;
2077
2087
  if (sectionOverride) newLevel = sectionOverride.level;
2078
2088
  }
2079
2089
  if (!(newLevel in levelToDiagnosticCategory)) continue;
@@ -3394,6 +3404,28 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
3394
3404
  `TypeParser.isNodeReferenceToEffectParseResultModuleApi(${memberName})`,
3395
3405
  (node) => node
3396
3406
  );
3407
+ const isEffectSchemaParserSourceFile = cachedBy(
3408
+ fn("TypeParser.isEffectSchemaParserSourceFile")(function* (sourceFile) {
3409
+ const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
3410
+ if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
3411
+ const parseIssueSymbol = typeChecker.tryGetMemberInModuleExports("Parser", moduleSymbol);
3412
+ if (!parseIssueSymbol) return yield* typeParserIssue("ParseIssue type not found", void 0, sourceFile);
3413
+ const decodeSyncSymbol = typeChecker.tryGetMemberInModuleExports("decodeEffect", moduleSymbol);
3414
+ if (!decodeSyncSymbol) return yield* typeParserIssue("decodeSync not found", void 0, sourceFile);
3415
+ const encodeSyncSymbol = typeChecker.tryGetMemberInModuleExports("encodeEffect", moduleSymbol);
3416
+ if (!encodeSyncSymbol) return yield* typeParserIssue("encodeSync not found", void 0, sourceFile);
3417
+ return sourceFile;
3418
+ }),
3419
+ "TypeParser.isEffectSchemaParserSourceFile",
3420
+ (sourceFile) => sourceFile
3421
+ );
3422
+ const isNodeReferenceToEffectSchemaParserModuleApi = (memberName) => cachedBy(
3423
+ fn("TypeParser.isNodeReferenceToEffectSchemaParserModuleApi")(function* (node) {
3424
+ return yield* isNodeReferenceToExportOfPackageModule(node, "effect", isEffectSchemaParserSourceFile, memberName);
3425
+ }),
3426
+ `TypeParser.isNodeReferenceToEffectSchemaParserModuleApi(${memberName})`,
3427
+ (node) => node
3428
+ );
3397
3429
  const contextTagVarianceStruct = (type, atLocation) => map4(
3398
3430
  all(
3399
3431
  varianceStructInvariantType(type, atLocation, "_Identifier"),
@@ -3401,6 +3433,31 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
3401
3433
  ),
3402
3434
  ([Identifier, Service]) => ({ Identifier, Service })
3403
3435
  );
3436
+ const serviceVarianceStruct = (type, atLocation) => map4(
3437
+ all(
3438
+ varianceStructInvariantType(type, atLocation, "_Identifier"),
3439
+ varianceStructInvariantType(type, atLocation, "_Service")
3440
+ ),
3441
+ ([Identifier, Service]) => ({ Identifier, Service })
3442
+ );
3443
+ const serviceType = cachedBy(
3444
+ fn("TypeParser.serviceType")(function* (type, atLocation) {
3445
+ yield* pipeableType(type, atLocation);
3446
+ const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
3447
+ (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
3448
+ );
3449
+ if (propertiesSymbols.length === 0) {
3450
+ return yield* typeParserIssue("Type has no tag variance struct", type, atLocation);
3451
+ }
3452
+ propertiesSymbols.sort((a, b) => ts.symbolName(b).indexOf("TypeId") - ts.symbolName(a).indexOf("TypeId"));
3453
+ return yield* firstSuccessOf(propertiesSymbols.map((propertySymbol) => {
3454
+ const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
3455
+ return serviceVarianceStruct(propertyType, atLocation);
3456
+ }));
3457
+ }),
3458
+ "TypeParser.serviceType",
3459
+ (type) => type
3460
+ );
3404
3461
  const contextTag = cachedBy(
3405
3462
  fn("TypeParser.contextTag")(function* (type, atLocation) {
3406
3463
  yield* pipeableType(type, atLocation);
@@ -3482,14 +3539,22 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
3482
3539
  );
3483
3540
  const scopeType = cachedBy(
3484
3541
  fn("TypeParser.scopeType")(function* (type, atLocation) {
3485
- yield* pipeableType(type, atLocation);
3486
- const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
3487
- (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
3488
- );
3489
- if (propertiesSymbols.some((s) => ts.symbolName(s).indexOf("ScopeTypeId") !== -1)) {
3490
- return type;
3542
+ if (supportedEffect() === "v4") {
3543
+ const typeIdSymbol = typeChecker.getPropertyOfType(type, "~effect/Scope");
3544
+ if (typeIdSymbol) {
3545
+ return type;
3546
+ }
3547
+ return yield* typeParserIssue("Type is not an effect", type, atLocation);
3548
+ } else {
3549
+ yield* pipeableType(type, atLocation);
3550
+ const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
3551
+ (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
3552
+ );
3553
+ if (propertiesSymbols.some((s) => ts.symbolName(s).indexOf("ScopeTypeId") !== -1)) {
3554
+ return type;
3555
+ }
3556
+ return yield* typeParserIssue("Type has no scope type id", type, atLocation);
3491
3557
  }
3492
- return yield* typeParserIssue("Type has no scope type id", type, atLocation);
3493
3558
  }),
3494
3559
  "TypeParser.scopeType",
3495
3560
  (type) => type
@@ -3971,6 +4036,55 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
3971
4036
  "TypeParser.extendsEffectService",
3972
4037
  (atLocation) => atLocation
3973
4038
  );
4039
+ const extendsServiceMapService = cachedBy(
4040
+ fn("TypeParser.extendsServiceMapService")(function* (atLocation) {
4041
+ if (!atLocation.name) {
4042
+ return yield* typeParserIssue("Class has no name", void 0, atLocation);
4043
+ }
4044
+ const heritageClauses = atLocation.heritageClauses;
4045
+ if (!heritageClauses) {
4046
+ return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
4047
+ }
4048
+ for (const heritageClause of heritageClauses) {
4049
+ for (const typeX of heritageClause.types) {
4050
+ if (ts.isExpressionWithTypeArguments(typeX)) {
4051
+ const wholeCall = typeX.expression;
4052
+ if (ts.isCallExpression(wholeCall)) {
4053
+ const serviceMapServiceCall = wholeCall.expression;
4054
+ if (ts.isCallExpression(serviceMapServiceCall) && serviceMapServiceCall.typeArguments && serviceMapServiceCall.typeArguments.length > 0) {
4055
+ const serviceMapServiceIdentifier = serviceMapServiceCall.expression;
4056
+ const selfTypeNode = serviceMapServiceCall.typeArguments[0];
4057
+ const isServiceMapService = yield* pipe(
4058
+ isNodeReferenceToServiceMapModuleApi("Service")(serviceMapServiceIdentifier),
4059
+ orUndefined
4060
+ );
4061
+ if (isServiceMapService) {
4062
+ const classSym = typeChecker.getSymbolAtLocation(atLocation.name);
4063
+ if (!classSym) return yield* typeParserIssue("Class has no symbol", void 0, atLocation);
4064
+ const type = typeChecker.getTypeOfSymbol(classSym);
4065
+ const parsedServiceType = yield* pipe(
4066
+ serviceType(type, atLocation),
4067
+ orUndefined
4068
+ );
4069
+ if (parsedServiceType) {
4070
+ return {
4071
+ ...parsedServiceType,
4072
+ className: atLocation.name,
4073
+ selfTypeNode,
4074
+ keyStringLiteral: wholeCall.arguments.length > 0 && ts.isStringLiteral(wholeCall.arguments[0]) ? wholeCall.arguments[0] : void 0
4075
+ };
4076
+ }
4077
+ }
4078
+ }
4079
+ }
4080
+ }
4081
+ }
4082
+ }
4083
+ return yield* typeParserIssue("Class does not extend ServiceMap.Service", void 0, atLocation);
4084
+ }),
4085
+ "TypeParser.extendsServiceMapService",
4086
+ (atLocation) => atLocation
4087
+ );
3974
4088
  const isEffectSqlModelTypeSourceFile = cachedBy(
3975
4089
  fn("TypeParser.isEffectSqlModelTypeSourceFile")(function* (sourceFile) {
3976
4090
  const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
@@ -4063,6 +4177,24 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
4063
4177
  `TypeParser.isNodeReferenceToEffectLayerModuleApi(${memberName})`,
4064
4178
  (node) => node
4065
4179
  );
4180
+ const isServiceMapTypeSourceFile = cachedBy(
4181
+ fn("TypeParser.isServiceMapTypeSourceFile")(function* (sourceFile) {
4182
+ const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
4183
+ if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
4184
+ const serviceMapSymbol = typeChecker.tryGetMemberInModuleExports("ServiceMap", moduleSymbol);
4185
+ if (!serviceMapSymbol) return yield* typeParserIssue("ServiceMap not found", void 0, sourceFile);
4186
+ return sourceFile;
4187
+ }),
4188
+ "TypeParser.isServiceMapTypeSourceFile",
4189
+ (sourceFile) => sourceFile
4190
+ );
4191
+ const isNodeReferenceToServiceMapModuleApi = (memberName) => cachedBy(
4192
+ fn("TypeParser.isNodeReferenceToServiceMapModuleApi")(function* (node) {
4193
+ return yield* isNodeReferenceToExportOfPackageModule(node, "effect", isServiceMapTypeSourceFile, memberName);
4194
+ }),
4195
+ `TypeParser.isNodeReferenceToServiceMapModuleApi(${memberName})`,
4196
+ (node) => node
4197
+ );
4066
4198
  const lazyExpression = cachedBy(
4067
4199
  function(node) {
4068
4200
  if (!ts.isArrowFunction(node) && !ts.isFunctionExpression(node)) {
@@ -4393,6 +4525,9 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
4393
4525
  isNodeReferenceToEffectContextModuleApi,
4394
4526
  isNodeReferenceToEffectSqlModelModuleApi,
4395
4527
  isNodeReferenceToEffectLayerModuleApi,
4528
+ isNodeReferenceToEffectSchemaParserModuleApi,
4529
+ isServiceMapTypeSourceFile,
4530
+ isNodeReferenceToServiceMapModuleApi,
4396
4531
  effectType,
4397
4532
  strictEffectType,
4398
4533
  layerType,
@@ -4408,6 +4543,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
4408
4543
  unnecessaryEffectGen: unnecessaryEffectGen2,
4409
4544
  effectSchemaType,
4410
4545
  contextTag,
4546
+ serviceType,
4411
4547
  pipeableType,
4412
4548
  pipeCall,
4413
4549
  singleArgCall,
@@ -4415,6 +4551,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
4415
4551
  promiseLike,
4416
4552
  extendsEffectTag,
4417
4553
  extendsEffectService,
4554
+ extendsServiceMapService,
4418
4555
  extendsContextTag,
4419
4556
  extendsSchemaClass,
4420
4557
  extendsSchemaTaggedClass,
@@ -4892,6 +5029,7 @@ var deterministicKeys = createDiagnostic({
4892
5029
  typeParser.extendsEffectService(node),
4893
5030
  orElse2(() => typeParser.extendsContextTag(node)),
4894
5031
  orElse2(() => typeParser.extendsEffectTag(node)),
5032
+ orElse2(() => typeParser.extendsServiceMapService(node)),
4895
5033
  map4(({ className, keyStringLiteral }) => ({ keyStringLiteral, className, target: "service" }))
4896
5034
  ),
4897
5035
  orElse2(
@@ -6287,6 +6425,9 @@ More info and examples at https://effect.website/docs/requirements-management/la
6287
6425
  if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.name) && ts.idText(node.expression.name) === "GenericTag") {
6288
6426
  const nodeType = typeCheckerUtils.getTypeAtLocation(node);
6289
6427
  if (nodeType) typesToCheck.push([nodeType, node]);
6428
+ } else if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.name) && ts.idText(node.expression.name) === "Service") {
6429
+ const nodeType = typeCheckerUtils.getTypeAtLocation(node);
6430
+ if (nodeType) typesToCheck.push([nodeType, node]);
6290
6431
  } else if (ts.isClassDeclaration(node) && node.name && node.heritageClauses) {
6291
6432
  const classSym = typeChecker.getSymbolAtLocation(node.name);
6292
6433
  if (classSym) {
@@ -6300,6 +6441,7 @@ More info and examples at https://effect.website/docs/requirements-management/la
6300
6441
  for (const [type, reportAt] of typesToCheck) {
6301
6442
  yield* pipe(
6302
6443
  typeParser.contextTag(type, node),
6444
+ orElse2(() => typeParser.serviceType(type, node)),
6303
6445
  flatMap2(
6304
6446
  ({ Service }) => pipe(
6305
6447
  parseLeakedRequirements(Service, node),
@@ -7074,6 +7216,7 @@ var nonObjectEffectServiceType = createDiagnostic({
7074
7216
  const typeChecker = yield* service(TypeCheckerApi);
7075
7217
  const typeCheckerUtils = yield* service(TypeCheckerUtils);
7076
7218
  const typeParser = yield* service(TypeParser);
7219
+ if (typeParser.supportedEffect() === "v4") return;
7077
7220
  function isPrimitiveType(type) {
7078
7221
  return typeCheckerUtils.unrollUnionMembers(type).some(
7079
7222
  (type2) => !!(type2.flags & ts.TypeFlags.String || type2.flags & ts.TypeFlags.Number || type2.flags & ts.TypeFlags.Boolean || type2.flags & ts.TypeFlags.StringLiteral || type2.flags & ts.TypeFlags.NumberLiteral || type2.flags & ts.TypeFlags.BooleanLiteral || type2.flags & ts.TypeFlags.Undefined || type2.flags & ts.TypeFlags.Null)
@@ -7358,6 +7501,7 @@ var parse2 = fn("writeTagClassAccessors.parse")(function* (node) {
7358
7501
  const typeChecker = yield* service(TypeCheckerApi);
7359
7502
  const typeParser = yield* service(TypeParser);
7360
7503
  const typeCheckerUtils = yield* service(TypeCheckerUtils);
7504
+ if (typeParser.supportedEffect() === "v4") return yield* fail("not applicable to Effect v4");
7361
7505
  if (!ts.isClassDeclaration(node)) return yield* fail("not a class declaration");
7362
7506
  const { Service, accessors: accessors2, className, kind } = yield* pipe(
7363
7507
  map4(typeParser.extendsEffectService(node), (_) => ({ kind: "effectService", ..._ })),
@@ -7600,16 +7744,16 @@ var pushHoistedVariableStatement = fn("StructuralSchemaGen.pushHoistedVariableSt
7600
7744
  );
7601
7745
  }
7602
7746
  );
7603
- var createProcessingContext = (maxDepth = 200) => ({
7747
+ var createProcessingContext = (supportedEffect, maxDepth = 200) => ({
7604
7748
  depth: 0,
7605
7749
  maxDepth,
7606
- hoistName: void 0
7750
+ hoistName: void 0,
7751
+ supportedEffect
7607
7752
  });
7608
7753
  var processType = fn(
7609
7754
  "StructuralSchemaGen.processType"
7610
7755
  )(
7611
- function* (type, context) {
7612
- const processingContext = context || createProcessingContext();
7756
+ function* (type, processingContext) {
7613
7757
  const { hoistedSchemas, nameToType, ts, typeChecker, usedGlobalIdentifiers } = yield* service(
7614
7758
  StructuralSchemaGenContext
7615
7759
  );
@@ -7744,7 +7888,7 @@ var processUnionType = fn(
7744
7888
  const allLiterals = types.every(
7745
7889
  (t) => t.flags & ts.TypeFlags.StringLiteral || t.flags & ts.TypeFlags.NumberLiteral || t.flags & ts.TypeFlags.BooleanLiteral
7746
7890
  );
7747
- if (allLiterals) {
7891
+ if (allLiterals && context.supportedEffect !== "v4") {
7748
7892
  const literals = yield* all(
7749
7893
  ...types.map((t) => processType(t, context))
7750
7894
  );
@@ -7754,7 +7898,13 @@ var processUnionType = fn(
7754
7898
  }
7755
7899
  return expr;
7756
7900
  }).filter((arg) => arg !== void 0);
7757
- return [createApiCall("Literal", literalValues), false];
7901
+ return [
7902
+ createApiCall(
7903
+ "Literal",
7904
+ literalValues
7905
+ ),
7906
+ false
7907
+ ];
7758
7908
  }
7759
7909
  const members = yield* all(
7760
7910
  ...types.map((t) => processType(t, context))
@@ -7762,7 +7912,13 @@ var processUnionType = fn(
7762
7912
  if (members.length === 1) {
7763
7913
  return [members[0], false];
7764
7914
  }
7765
- return [createApiCall("Union", members), false];
7915
+ return [
7916
+ createApiCall(
7917
+ "Union",
7918
+ context.supportedEffect === "v4" ? [ts.factory.createArrayLiteralExpression(members)] : members
7919
+ ),
7920
+ false
7921
+ ];
7766
7922
  }
7767
7923
  );
7768
7924
  var processIntersectionType = fn(
@@ -7808,12 +7964,18 @@ var processTupleType = fn(
7808
7964
  "StructuralSchemaGen.processTupleType"
7809
7965
  )(
7810
7966
  function* (type, context) {
7811
- const { createApiCall, typeChecker } = yield* service(StructuralSchemaGenContext);
7967
+ const { createApiCall, ts, typeChecker } = yield* service(StructuralSchemaGenContext);
7812
7968
  const typeArgs = typeChecker.getTypeArguments(type);
7813
7969
  const elementSchemas = yield* all(
7814
7970
  ...typeArgs.map((t) => processType(t, context))
7815
7971
  );
7816
- return [createApiCall("Tuple", elementSchemas), false];
7972
+ return [
7973
+ createApiCall(
7974
+ "Tuple",
7975
+ context.supportedEffect === "v4" ? [ts.factory.createArrayLiteralExpression(elementSchemas)] : elementSchemas
7976
+ ),
7977
+ false
7978
+ ];
7817
7979
  }
7818
7980
  );
7819
7981
  var processObjectType = fn(
@@ -7830,7 +7992,6 @@ var processObjectType = fn(
7830
7992
  } = yield* service(
7831
7993
  StructuralSchemaGenContext
7832
7994
  );
7833
- let hasRecords = false;
7834
7995
  const properties = typeChecker.getPropertiesOfType(type);
7835
7996
  const propertyAssignments = [];
7836
7997
  for (const property of properties) {
@@ -7870,20 +8031,28 @@ var processObjectType = fn(
7870
8031
  const args2 = [
7871
8032
  ts.factory.createObjectLiteralExpression(propertyAssignments, propertyAssignments.length > 0)
7872
8033
  ];
8034
+ const records = [];
7873
8035
  for (const indexInfo of indexInfos) {
7874
- hasRecords = true;
7875
8036
  const keyType = indexInfo.keyType;
7876
8037
  const valueType = indexInfo.type;
7877
8038
  const keySchema = yield* processType(keyType, context);
7878
8039
  const valueSchema = yield* processType(valueType, context);
7879
- args2.push(
7880
- ts.factory.createObjectLiteralExpression([
7881
- ts.factory.createPropertyAssignment("key", keySchema),
7882
- ts.factory.createPropertyAssignment("value", valueSchema)
7883
- ])
7884
- );
8040
+ records.push({ key: keySchema, value: valueSchema });
8041
+ }
8042
+ if (context.supportedEffect === "v4") {
8043
+ if (records.length > 0) {
8044
+ return [
8045
+ createApiCall("StructWithRest", [
8046
+ createApiCall("Struct", args2),
8047
+ ts.factory.createArrayLiteralExpression(
8048
+ records.map(({ key, value }) => createApiCall("Record", [key, value]))
8049
+ )
8050
+ ]),
8051
+ propertyAssignments.length === 0
8052
+ ];
8053
+ }
7885
8054
  }
7886
- if (!hasRecords && context.hoistName) {
8055
+ if (records.length === 0 && context.hoistName) {
7887
8056
  const ctx = yield* service(StructuralSchemaGenContext);
7888
8057
  yield* pushHoistedStatement(
7889
8058
  ctx,
@@ -7918,6 +8087,14 @@ var processObjectType = fn(
7918
8087
  );
7919
8088
  return [ctx.hoistedSchemas.get(type)(), true];
7920
8089
  }
8090
+ for (const { key, value } of records) {
8091
+ args2.push(
8092
+ ts.factory.createObjectLiteralExpression([
8093
+ ts.factory.createPropertyAssignment("key", key),
8094
+ ts.factory.createPropertyAssignment("value", value)
8095
+ ])
8096
+ );
8097
+ }
7921
8098
  return [createApiCall("Struct", args2), propertyAssignments.length === 0];
7922
8099
  }
7923
8100
  );
@@ -8003,7 +8180,7 @@ var process = fn("StructuralSchemaGen.process")(
8003
8180
  all(
8004
8181
  ...fromIterable(ctx.nameToType.entries()).map(
8005
8182
  ([name, type]) => pipe(
8006
- processType(type),
8183
+ processType(type, createProcessingContext(typeParser.supportedEffect())),
8007
8184
  orElse2(
8008
8185
  (error) => succeed(ts.addSyntheticLeadingComment(
8009
8186
  ts.factory.createIdentifier(""),
@@ -8585,6 +8762,7 @@ var runEffectInsideEffect = createDiagnostic({
8585
8762
  const ts = yield* service(TypeScriptApi);
8586
8763
  const typeParser = yield* service(TypeParser);
8587
8764
  const tsUtils = yield* service(TypeScriptUtils);
8765
+ if (typeParser.supportedEffect() === "v4") return;
8588
8766
  const parseEffectMethod = (node, methodName) => pipe(
8589
8767
  typeParser.isNodeReferenceToEffectModuleApi(methodName)(node),
8590
8768
  map4(() => ({ node, methodName }))
@@ -8779,12 +8957,18 @@ var schemaStructWithTag = createDiagnostic({
8779
8957
  });
8780
8958
 
8781
8959
  // src/diagnostics/schemaSyncInEffect.ts
8782
- var syncToEffectMethod = {
8960
+ var syncToEffectMethodV3 = {
8783
8961
  decodeSync: "decode",
8784
8962
  decodeUnknownSync: "decodeUnknown",
8785
8963
  encodeSync: "encode",
8786
8964
  encodeUnknownSync: "encodeUnknown"
8787
8965
  };
8966
+ var syncToEffectMethodV4 = {
8967
+ decodeSync: "decodeEffect",
8968
+ decodeUnknownSync: "decodeUnknownEffect",
8969
+ encodeSync: "encodeEffect",
8970
+ encodeUnknownSync: "encodeUnknownEffect"
8971
+ };
8788
8972
  var schemaSyncInEffect = createDiagnostic({
8789
8973
  name: "schemaSyncInEffect",
8790
8974
  code: 43,
@@ -8793,8 +8977,10 @@ var schemaSyncInEffect = createDiagnostic({
8793
8977
  apply: fn("schemaSyncInEffect.apply")(function* (sourceFile, report) {
8794
8978
  const ts = yield* service(TypeScriptApi);
8795
8979
  const typeParser = yield* service(TypeParser);
8980
+ const syncToEffectMethod = typeParser.supportedEffect() === "v3" ? syncToEffectMethodV3 : syncToEffectMethodV4;
8796
8981
  const parseSchemaSyncMethod = (node, methodName) => pipe(
8797
8982
  typeParser.isNodeReferenceToEffectParseResultModuleApi(methodName)(node),
8983
+ orElse2(() => typeParser.isNodeReferenceToEffectSchemaParserModuleApi(methodName)(node)),
8798
8984
  map4(() => ({ node, methodName }))
8799
8985
  );
8800
8986
  const nodeToVisit = [];
@@ -8824,7 +9010,7 @@ var schemaSyncInEffect = createDiagnostic({
8824
9010
  const effectMethodName = syncToEffectMethod[isSchemaSyncCall.value.methodName];
8825
9011
  report({
8826
9012
  location: node.expression,
8827
- messageText: `Using ${nodeText} inside an Effect generator is not recommended. Use Schema.${effectMethodName} instead to get properly typed ParseError in the error channel.`,
9013
+ messageText: `Using ${nodeText} inside an Effect generator is not recommended. Use Schema.${effectMethodName} instead to get properly typed error channel.`,
8828
9014
  fixes: []
8829
9015
  });
8830
9016
  }
@@ -8840,6 +9026,7 @@ var schemaUnionOfLiterals = createDiagnostic({
8840
9026
  apply: fn("schemaUnionOfLiterals.apply")(function* (sourceFile, report) {
8841
9027
  const ts = yield* service(TypeScriptApi);
8842
9028
  const typeParser = yield* service(TypeParser);
9029
+ if (typeParser.supportedEffect() === "v4") return;
8843
9030
  const nodeToVisit = [];
8844
9031
  const appendNodeToVisit = (node) => {
8845
9032
  nodeToVisit.push(node);