@effect/language-service 0.60.0 → 0.62.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/cli.js CHANGED
@@ -21014,14 +21014,14 @@ var foldChunksReader = (s, contFn, f) => {
21014
21014
  };
21015
21015
  var foldLeftChunks = (s, f) => foldChunks(s, constTrue, f);
21016
21016
  var forEach9 = (f) => {
21017
- const process2 = readWithCause({
21017
+ const process3 = readWithCause({
21018
21018
  onInput: (input) => pipe(fromEffect4(forEach8(input, (v) => f(v), {
21019
21019
  discard: true
21020
- })), flatMap12(() => process2)),
21020
+ })), flatMap12(() => process3)),
21021
21021
  onFailure: failCause8,
21022
21022
  onDone: () => void_5
21023
21023
  });
21024
- return new SinkImpl(process2);
21024
+ return new SinkImpl(process3);
21025
21025
  };
21026
21026
  var fromChannel = (channel) => new SinkImpl(channel);
21027
21027
  var fromEffect6 = (effect3) => new SinkImpl(fromEffect4(effect3));
@@ -21279,12 +21279,12 @@ var bufferChunks = /* @__PURE__ */ dual(2, (self, options3) => {
21279
21279
  }
21280
21280
  const queue = toQueue(self, options3);
21281
21281
  return new StreamImpl(unwrapScoped2(map17(queue, (queue2) => {
21282
- const process2 = pipe(fromEffect4(take3(queue2)), flatMap12(match16({
21282
+ const process3 = pipe(fromEffect4(take3(queue2)), flatMap12(match16({
21283
21283
  onEnd: () => void_5,
21284
21284
  onFailure: failCause8,
21285
- onSuccess: (value5) => pipe(write(value5), flatMap12(() => process2))
21285
+ onSuccess: (value5) => pipe(write(value5), flatMap12(() => process3))
21286
21286
  })));
21287
- return process2;
21287
+ return process3;
21288
21288
  })));
21289
21289
  });
21290
21290
  var bufferChunksDropping = /* @__PURE__ */ dual(2, (self, capacity3) => {
@@ -21305,12 +21305,12 @@ var bufferSignal = (scoped6, bufferChannel) => {
21305
21305
  });
21306
21306
  };
21307
21307
  const consumer = (queue) => {
21308
- const process2 = pipe(fromEffect4(take3(queue)), flatMap12(([take6, deferred]) => zipRight4(fromEffect4(succeed6(deferred, void 0)), match16(take6, {
21308
+ const process3 = pipe(fromEffect4(take3(queue)), flatMap12(([take6, deferred]) => zipRight4(fromEffect4(succeed6(deferred, void 0)), match16(take6, {
21309
21309
  onEnd: () => void_5,
21310
21310
  onFailure: failCause8,
21311
- onSuccess: (value5) => pipe(write(value5), flatMap12(() => process2))
21311
+ onSuccess: (value5) => pipe(write(value5), flatMap12(() => process3))
21312
21312
  }))));
21313
- return process2;
21313
+ return process3;
21314
21314
  };
21315
21315
  return unwrapScoped2(pipe(scoped6, flatMap9((queue) => pipe(make38(), tap2((start4) => succeed6(start4, void 0)), flatMap9((start4) => pipe(make25(start4), flatMap9((ref) => pipe(bufferChannel, pipeTo(producer(queue, ref)), runScoped, forkScoped2)), as4(consumer(queue))))))));
21316
21316
  };
@@ -23772,9 +23772,9 @@ var resolve = function resolve2() {
23772
23772
  if (i >= 0) {
23773
23773
  path2 = arguments[i];
23774
23774
  } else {
23775
- const process2 = globalThis.process;
23776
- if (cwd === void 0 && "process" in globalThis && typeof process2 === "object" && process2 !== null && typeof process2.cwd === "function") {
23777
- cwd = process2.cwd();
23775
+ const process3 = globalThis.process;
23776
+ if (cwd === void 0 && "process" in globalThis && typeof process3 === "object" && process3 !== null && typeof process3.cwd === "function") {
23777
+ cwd = process3.cwd();
23778
23778
  }
23779
23779
  path2 = cwd;
23780
23780
  }
@@ -28305,7 +28305,7 @@ var ExitCode = /* @__PURE__ */ nominal();
28305
28305
  var ProcessId = /* @__PURE__ */ nominal();
28306
28306
  var CommandExecutor = /* @__PURE__ */ GenericTag("@effect/platform/CommandExecutor");
28307
28307
  var makeExecutor = (start4) => {
28308
- const stream3 = (command) => unwrapScoped6(map17(start4(command), (process2) => process2.stdout));
28308
+ const stream3 = (command) => unwrapScoped6(map17(start4(command), (process3) => process3.stdout));
28309
28309
  const streamLines2 = (command, encoding) => {
28310
28310
  const decoder2 = new TextDecoder(encoding);
28311
28311
  return splitLines3(mapChunks2(stream3(command), map5((bytes) => decoder2.decode(bytes))));
@@ -28313,11 +28313,11 @@ var makeExecutor = (start4) => {
28313
28313
  return {
28314
28314
  [TypeId24]: TypeId24,
28315
28315
  start: start4,
28316
- exitCode: (command) => scoped2(flatMap9(start4(command), (process2) => process2.exitCode)),
28316
+ exitCode: (command) => scoped2(flatMap9(start4(command), (process3) => process3.exitCode)),
28317
28317
  stream: stream3,
28318
28318
  string: (command, encoding = "utf-8") => {
28319
28319
  const decoder2 = new TextDecoder(encoding);
28320
- return pipe(start4(command), flatMap9((process2) => run4(process2.stdout, collectUint8Array)), map17((bytes) => decoder2.decode(bytes)), scoped2);
28320
+ return pipe(start4(command), flatMap9((process3) => run4(process3.stdout, collectUint8Array)), map17((bytes) => decoder2.decode(bytes)), scoped2);
28321
28321
  },
28322
28322
  lines: (command, encoding = "utf-8") => {
28323
28323
  return pipe(streamLines2(command, encoding), runCollect3, map17(toArray2));
@@ -28662,7 +28662,7 @@ var runCommand = (fileSystem) => (command) => {
28662
28662
  stdout: stdout2
28663
28663
  });
28664
28664
  }),
28665
- typeof command.stdin === "string" ? identity : tap2((process2) => forkDaemon2(run4(command.stdin, process2.stdin)))
28665
+ typeof command.stdin === "string" ? identity : tap2((process3) => forkDaemon2(run4(command.stdin, process3.stdin)))
28666
28666
  );
28667
28667
  }
28668
28668
  case "PipedCommand": {
@@ -28674,7 +28674,7 @@ var runCommand = (fileSystem) => (command) => {
28674
28674
  const tail = flattened2.slice(1);
28675
28675
  const initial = tail.slice(0, tail.length - 1);
28676
28676
  const last5 = tail[tail.length - 1];
28677
- const stream3 = initial.reduce((stdin3, command2) => pipe(stdin2(command2, stdin3), runCommand(fileSystem), map17((process2) => process2.stdout), unwrapScoped6), pipe(runCommand(fileSystem)(head5), map17((process2) => process2.stdout), unwrapScoped6));
28677
+ const stream3 = initial.reduce((stdin3, command2) => pipe(stdin2(command2, stdin3), runCommand(fileSystem), map17((process3) => process3.stdout), unwrapScoped6), pipe(runCommand(fileSystem)(head5), map17((process3) => process3.stdout), unwrapScoped6));
28678
28678
  return pipe(stdin2(last5, stream3), runCommand(fileSystem));
28679
28679
  }
28680
28680
  }
@@ -31627,7 +31627,11 @@ var getEditsForCodegen = fn2("LSP.getEditsForCodegen")(function* (codegens2, sou
31627
31627
  service2(ChangeTracker),
31628
31628
  map34((changeTracker) => {
31629
31629
  changeTracker.deleteRange(sourceFile, range3);
31630
- changeTracker.insertText(sourceFile, range3.pos, `${codegen2.name}:${edit.hash}`);
31630
+ changeTracker.insertText(
31631
+ sourceFile,
31632
+ range3.pos,
31633
+ edit.hash.length > 0 ? `${codegen2.name}:${edit.hash}` : codegen2.name
31634
+ );
31631
31635
  })
31632
31636
  );
31633
31637
  return {
@@ -31673,6 +31677,9 @@ function makeTypeCheckerUtils(ts, typeChecker, tsUtils) {
31673
31677
  function isThisTypeParameter(type2) {
31674
31678
  return !!(type2.flags & ts.TypeFlags.TypeParameter && type2.isThisType);
31675
31679
  }
31680
+ function isMissingIntrinsicType(type2) {
31681
+ return (type2.flags & ts.TypeFlags.Undefined) !== 0 && "debugIntrinsicName" in type2 && type2.debugIntrinsicName === "missing";
31682
+ }
31676
31683
  function getTypeParameterAtPosition(signature, pos) {
31677
31684
  const type2 = typeChecker.getParameterType(signature, pos);
31678
31685
  if (isIndexType(type2) && isThisTypeParameter(type2.type)) {
@@ -31977,6 +31984,7 @@ function makeTypeCheckerUtils(ts, typeChecker, tsUtils) {
31977
31984
  }
31978
31985
  return {
31979
31986
  isUnion: isUnion4,
31987
+ isMissingIntrinsicType,
31980
31988
  getTypeParameterAtPosition,
31981
31989
  getMissingTypeEntriesInTargetType,
31982
31990
  unrollUnionMembers,
@@ -33533,8 +33541,662 @@ var annotate3 = createCodegen({
33533
33541
  })
33534
33542
  });
33535
33543
 
33544
+ // src/utils/StructuralSchemaGen.ts
33545
+ var UnsupportedTypeError = class {
33546
+ constructor(type2, reason) {
33547
+ this.type = type2;
33548
+ this.reason = reason;
33549
+ }
33550
+ _tag = "@effect/language-service/UnsupportedTypeError";
33551
+ toString() {
33552
+ return `Unsupported type: ${this.reason}`;
33553
+ }
33554
+ };
33555
+ var StructuralSchemaGenContext = Tag4("StructuralSchemaGenContext");
33556
+ var makeStructuralSchemaGenContext = fn2("StructuralSchemaGen.makeContext")(
33557
+ function* (sourceFile, schemaIdentifier) {
33558
+ const ts = yield* service2(TypeScriptApi);
33559
+ const program = yield* service2(TypeScriptProgram);
33560
+ const typeChecker = yield* service2(TypeCheckerApi);
33561
+ const typeCheckerUtils = yield* service2(TypeCheckerUtils);
33562
+ const effectSchemaIdentifier = schemaIdentifier || "Schema";
33563
+ return identity({
33564
+ ts,
33565
+ program,
33566
+ typeChecker,
33567
+ typeCheckerUtils,
33568
+ sourceFile,
33569
+ createApiPropertyAccess: (apiName) => ts.factory.createPropertyAccessExpression(
33570
+ ts.factory.createIdentifier(effectSchemaIdentifier),
33571
+ apiName
33572
+ ),
33573
+ createApiCall: (apiName, args3) => ts.factory.createCallExpression(
33574
+ ts.factory.createPropertyAccessExpression(
33575
+ ts.factory.createIdentifier(effectSchemaIdentifier),
33576
+ apiName
33577
+ ),
33578
+ [],
33579
+ args3
33580
+ ),
33581
+ hoistedSchemas: /* @__PURE__ */ new Map(),
33582
+ typeToStatementIndex: /* @__PURE__ */ new Map(),
33583
+ nameToType: /* @__PURE__ */ new Map(),
33584
+ usedGlobalIdentifiers: /* @__PURE__ */ new Map(),
33585
+ schemaStatements: [],
33586
+ rangesToDelete: []
33587
+ });
33588
+ }
33589
+ );
33590
+ var pushHoistedStatement = fn2("StructuralSchemaGen.pushHoistedStatement")(
33591
+ function* (ctx, name, type2, statement, createReference) {
33592
+ ctx.usedGlobalIdentifiers.set(name, (ctx.usedGlobalIdentifiers.get(name) || 0) + 1);
33593
+ ctx.schemaStatements.push(statement);
33594
+ ctx.typeToStatementIndex.set(type2, ctx.schemaStatements.length - 1);
33595
+ ctx.hoistedSchemas.set(type2, createReference);
33596
+ }
33597
+ );
33598
+ var pushHoistedVariableStatement = fn2("StructuralSchemaGen.pushHoistedVariableStatement")(
33599
+ function* (ts, ctx, name, type2, result) {
33600
+ return yield* pushHoistedStatement(
33601
+ ctx,
33602
+ name,
33603
+ type2,
33604
+ ts.factory.createVariableStatement(
33605
+ void 0,
33606
+ ts.factory.createVariableDeclarationList(
33607
+ [ts.factory.createVariableDeclaration(ts.factory.createIdentifier(name), void 0, void 0, result)],
33608
+ ts.NodeFlags.Const
33609
+ )
33610
+ ),
33611
+ () => ts.factory.createIdentifier(name)
33612
+ );
33613
+ }
33614
+ );
33615
+ var createProcessingContext = (maxDepth = 200) => ({
33616
+ depth: 0,
33617
+ maxDepth,
33618
+ hoistName: void 0
33619
+ });
33620
+ var processType = fn2(
33621
+ "StructuralSchemaGen.processType"
33622
+ )(
33623
+ function* (type2, context7) {
33624
+ const processingContext = context7 || createProcessingContext();
33625
+ const { hoistedSchemas, nameToType, ts, typeChecker, usedGlobalIdentifiers } = yield* service2(
33626
+ StructuralSchemaGenContext
33627
+ );
33628
+ if (processingContext.depth >= processingContext.maxDepth) {
33629
+ return yield* fail18(new UnsupportedTypeError(type2, "Maximum depth exceeded"));
33630
+ }
33631
+ let hoistName = fromIterable(nameToType.entries()).find(([_, existingType]) => existingType === type2)?.[0];
33632
+ if (!hoistName && type2 && type2.symbol && type2.symbol.declarations && type2.symbol.declarations.length === 1) {
33633
+ const declaration = type2.symbol.declarations[0];
33634
+ if (ts.isInterfaceDeclaration(declaration)) {
33635
+ hoistName = ts.idText(declaration.name);
33636
+ } else if (declaration.parent && ts.isTypeAliasDeclaration(declaration.parent)) {
33637
+ hoistName = ts.idText(declaration.parent.name);
33638
+ }
33639
+ if (hoistName) {
33640
+ const existingType = nameToType.get(hoistName);
33641
+ const isSame = existingType && typeChecker.isTypeAssignableTo(type2, existingType) && typeChecker.isTypeAssignableTo(existingType, type2);
33642
+ if (!isSame) {
33643
+ const usedCount = usedGlobalIdentifiers.get(hoistName) || 0;
33644
+ hoistName = usedCount > 0 ? hoistName + "_" + usedCount : hoistName;
33645
+ }
33646
+ }
33647
+ }
33648
+ const nestedContext = {
33649
+ ...processingContext,
33650
+ depth: processingContext.depth + 1,
33651
+ hoistName
33652
+ };
33653
+ for (const [hoistedType, hoistedSchema] of hoistedSchemas.entries()) {
33654
+ if (hoistedType === type2 || typeChecker.isTypeAssignableTo(type2, hoistedType) && typeChecker.isTypeAssignableTo(hoistedType, type2)) {
33655
+ return hoistedSchema();
33656
+ }
33657
+ }
33658
+ const [schemaExpr, skipHoisting] = yield* processTypeImpl(type2, nestedContext);
33659
+ if (!skipHoisting && hoistName) {
33660
+ const ctx = yield* service2(StructuralSchemaGenContext);
33661
+ yield* pushHoistedVariableStatement(ts, ctx, hoistName, type2, schemaExpr);
33662
+ return ctx.hoistedSchemas.get(type2)();
33663
+ }
33664
+ return schemaExpr;
33665
+ }
33666
+ );
33667
+ var processTypeImpl = fn2(
33668
+ "StructuralSchemaGen.processTypeImpl"
33669
+ )(
33670
+ function* (type2, context7) {
33671
+ const { createApiCall, createApiPropertyAccess, ts, typeChecker, typeCheckerUtils } = yield* service2(
33672
+ StructuralSchemaGenContext
33673
+ );
33674
+ if (type2.flags & ts.TypeFlags.String) {
33675
+ return [createApiPropertyAccess("String"), true];
33676
+ }
33677
+ if (type2.flags & ts.TypeFlags.Number) {
33678
+ return [createApiPropertyAccess("Number"), true];
33679
+ }
33680
+ if (type2.flags & ts.TypeFlags.Boolean) {
33681
+ return [createApiPropertyAccess("Boolean"), true];
33682
+ }
33683
+ if (type2.flags & ts.TypeFlags.BigInt) {
33684
+ return [createApiPropertyAccess("BigInt"), true];
33685
+ }
33686
+ if (type2.flags & ts.TypeFlags.Void) {
33687
+ return [createApiPropertyAccess("Void"), true];
33688
+ }
33689
+ if (type2.flags & ts.TypeFlags.Undefined) {
33690
+ return [createApiPropertyAccess("Undefined"), true];
33691
+ }
33692
+ if (type2.flags & ts.TypeFlags.Null) {
33693
+ return [createApiPropertyAccess("Null"), true];
33694
+ }
33695
+ if (type2.flags & ts.TypeFlags.Never) {
33696
+ return [createApiPropertyAccess("Never"), true];
33697
+ }
33698
+ if (type2.flags & ts.TypeFlags.Any) {
33699
+ return [createApiPropertyAccess("Any"), true];
33700
+ }
33701
+ if (type2.flags & ts.TypeFlags.Unknown) {
33702
+ return [createApiPropertyAccess("Unknown"), true];
33703
+ }
33704
+ if (type2.flags & ts.TypeFlags.StringLiteral) {
33705
+ const literalType = type2;
33706
+ return [createApiCall("Literal", [ts.factory.createStringLiteral(literalType.value)]), true];
33707
+ }
33708
+ if (type2.flags & ts.TypeFlags.NumberLiteral) {
33709
+ const literalType = type2;
33710
+ return [createApiCall("Literal", [ts.factory.createNumericLiteral(literalType.value)]), true];
33711
+ }
33712
+ if (type2.flags & ts.TypeFlags.BooleanLiteral) {
33713
+ const value5 = type2.intrinsicName === "true";
33714
+ return [createApiCall("Literal", [value5 ? ts.factory.createTrue() : ts.factory.createFalse()]), true];
33715
+ }
33716
+ if (typeCheckerUtils.isUnion(type2)) {
33717
+ return yield* processUnionType(type2.types, context7);
33718
+ }
33719
+ if (type2.flags & ts.TypeFlags.Intersection) {
33720
+ return yield* processIntersectionType(type2, context7);
33721
+ }
33722
+ if (typeChecker.isArrayType(type2)) {
33723
+ return yield* processArrayType(type2, context7);
33724
+ }
33725
+ if (typeChecker.isTupleType(type2)) {
33726
+ return yield* processTupleType(type2, context7);
33727
+ }
33728
+ if (type2.flags & ts.TypeFlags.Object) {
33729
+ const symbol3 = type2.symbol || type2.aliasSymbol;
33730
+ if (symbol3) {
33731
+ const typeName = typeChecker.symbolToString(symbol3);
33732
+ if (typeName === "Date") {
33733
+ return [createApiPropertyAccess("Date"), false];
33734
+ }
33735
+ if (typeName === "ReadonlyArray" || typeName === "Array") {
33736
+ return yield* processArrayType(type2, context7);
33737
+ }
33738
+ }
33739
+ const objectType = type2;
33740
+ return yield* processObjectType(objectType, context7);
33741
+ }
33742
+ return yield* fail18(
33743
+ new UnsupportedTypeError(
33744
+ type2,
33745
+ `Type with flags ${type2.flags} is not supported`
33746
+ )
33747
+ );
33748
+ }
33749
+ );
33750
+ var processUnionType = fn2(
33751
+ "StructuralSchemaGen.processUnionType"
33752
+ )(
33753
+ function* (types, context7) {
33754
+ const { createApiCall, ts } = yield* service2(StructuralSchemaGenContext);
33755
+ const allLiterals = types.every(
33756
+ (t) => t.flags & ts.TypeFlags.StringLiteral || t.flags & ts.TypeFlags.NumberLiteral || t.flags & ts.TypeFlags.BooleanLiteral
33757
+ );
33758
+ if (allLiterals) {
33759
+ const literals = yield* all9(
33760
+ ...types.map((t) => processType(t, context7))
33761
+ );
33762
+ const literalValues = literals.map((expr) => {
33763
+ if (ts.isCallExpression(expr) && expr.arguments.length > 0) {
33764
+ return expr.arguments[0];
33765
+ }
33766
+ return expr;
33767
+ }).filter((arg) => arg !== void 0);
33768
+ return [createApiCall("Literal", literalValues), false];
33769
+ }
33770
+ const members = yield* all9(
33771
+ ...types.map((t) => processType(t, context7))
33772
+ );
33773
+ if (members.length === 1) {
33774
+ return [members[0], false];
33775
+ }
33776
+ return [createApiCall("Union", members), false];
33777
+ }
33778
+ );
33779
+ var processIntersectionType = fn2(
33780
+ "StructuralSchemaGen.processIntersectionType"
33781
+ )(
33782
+ function* (type2, context7) {
33783
+ const { createApiCall, ts } = yield* service2(StructuralSchemaGenContext);
33784
+ const [firstSchema, ...otherSchemas] = yield* all9(
33785
+ ...type2.types.map((t) => processType(t, context7))
33786
+ );
33787
+ if (otherSchemas.length === 0) {
33788
+ return [firstSchema, false];
33789
+ }
33790
+ return [
33791
+ ts.factory.createCallExpression(
33792
+ ts.factory.createPropertyAccessExpression(
33793
+ firstSchema,
33794
+ "pipe"
33795
+ ),
33796
+ [],
33797
+ otherSchemas.map((schema) => createApiCall("extend", [schema]))
33798
+ ),
33799
+ false
33800
+ ];
33801
+ }
33802
+ );
33803
+ var processArrayType = fn2(
33804
+ "StructuralSchemaGen.processArrayType"
33805
+ )(
33806
+ function* (type2, context7) {
33807
+ const { createApiCall, typeChecker } = yield* service2(StructuralSchemaGenContext);
33808
+ const typeArgs = typeChecker.getTypeArguments(type2);
33809
+ if (typeArgs.length === 0) {
33810
+ return yield* fail18(new UnsupportedTypeError(type2, "Array type has no type arguments"));
33811
+ }
33812
+ const elementSchema = yield* processType(typeArgs[0], context7);
33813
+ return [createApiCall("Array", [elementSchema]), false];
33814
+ }
33815
+ );
33816
+ var processTupleType = fn2(
33817
+ "StructuralSchemaGen.processTupleType"
33818
+ )(
33819
+ function* (type2, context7) {
33820
+ const { createApiCall, typeChecker } = yield* service2(StructuralSchemaGenContext);
33821
+ const typeArgs = typeChecker.getTypeArguments(type2);
33822
+ const elementSchemas = yield* all9(
33823
+ ...typeArgs.map((t) => processType(t, context7))
33824
+ );
33825
+ return [createApiCall("Tuple", elementSchemas), false];
33826
+ }
33827
+ );
33828
+ var processObjectType = fn2(
33829
+ "StructuralSchemaGen.processObjectType"
33830
+ )(
33831
+ function* (type2, context7) {
33832
+ const {
33833
+ createApiCall,
33834
+ createApiPropertyAccess,
33835
+ program,
33836
+ ts,
33837
+ typeChecker,
33838
+ typeCheckerUtils
33839
+ } = yield* service2(
33840
+ StructuralSchemaGenContext
33841
+ );
33842
+ let hasRecords = false;
33843
+ const properties = typeChecker.getPropertiesOfType(type2);
33844
+ const propertyAssignments = [];
33845
+ for (const property of properties) {
33846
+ const propertyName = typeChecker.symbolToString(property);
33847
+ const propertyType = typeChecker.getTypeOfSymbol(property);
33848
+ const isOptional = (property.flags & ts.SymbolFlags.Optional) !== 0;
33849
+ let schemaExpr;
33850
+ if (isOptional) {
33851
+ if (program.getCompilerOptions().exactOptionalPropertyTypes) {
33852
+ if (typeCheckerUtils.isUnion(propertyType)) {
33853
+ const typeWithoutMissing = propertyType.types.filter((t) => !typeCheckerUtils.isMissingIntrinsicType(t));
33854
+ const [result, _] = yield* processUnionType(typeWithoutMissing, context7);
33855
+ schemaExpr = createApiCall("optionalWith", [
33856
+ result,
33857
+ ts.factory.createObjectLiteralExpression([
33858
+ ts.factory.createPropertyAssignment("exact", ts.factory.createTrue())
33859
+ ])
33860
+ ]);
33861
+ }
33862
+ } else {
33863
+ schemaExpr = yield* processType(propertyType, context7);
33864
+ schemaExpr = createApiCall("optional", [schemaExpr]);
33865
+ }
33866
+ }
33867
+ if (!schemaExpr) {
33868
+ schemaExpr = yield* processType(propertyType, context7);
33869
+ }
33870
+ const propertyNameNode = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(propertyName) ? ts.factory.createIdentifier(propertyName) : ts.factory.createStringLiteral(propertyName);
33871
+ propertyAssignments.push(
33872
+ ts.factory.createPropertyAssignment(
33873
+ propertyNameNode,
33874
+ schemaExpr
33875
+ )
33876
+ );
33877
+ }
33878
+ const indexInfos = typeChecker.getIndexInfosOfType(type2);
33879
+ const args3 = [
33880
+ ts.factory.createObjectLiteralExpression(propertyAssignments, propertyAssignments.length > 0)
33881
+ ];
33882
+ for (const indexInfo of indexInfos) {
33883
+ hasRecords = true;
33884
+ const keyType = indexInfo.keyType;
33885
+ const valueType = indexInfo.type;
33886
+ const keySchema = yield* processType(keyType, context7);
33887
+ const valueSchema = yield* processType(valueType, context7);
33888
+ args3.push(
33889
+ ts.factory.createObjectLiteralExpression([
33890
+ ts.factory.createPropertyAssignment("key", keySchema),
33891
+ ts.factory.createPropertyAssignment("value", valueSchema)
33892
+ ])
33893
+ );
33894
+ }
33895
+ if (!hasRecords && context7.hoistName) {
33896
+ const ctx = yield* service2(StructuralSchemaGenContext);
33897
+ yield* pushHoistedStatement(
33898
+ ctx,
33899
+ context7.hoistName,
33900
+ type2,
33901
+ ts.factory.createClassDeclaration(
33902
+ void 0,
33903
+ ts.factory.createIdentifier(context7.hoistName),
33904
+ [],
33905
+ [ts.factory.createHeritageClause(
33906
+ ts.SyntaxKind.ExtendsKeyword,
33907
+ [
33908
+ ts.factory.createExpressionWithTypeArguments(
33909
+ ts.factory.createCallExpression(
33910
+ ts.factory.createCallExpression(
33911
+ createApiPropertyAccess("Class"),
33912
+ [ts.factory.createTypeReferenceNode(
33913
+ context7.hoistName
33914
+ )],
33915
+ [ts.factory.createStringLiteral(context7.hoistName)]
33916
+ ),
33917
+ [],
33918
+ args3
33919
+ ),
33920
+ []
33921
+ )
33922
+ ]
33923
+ )],
33924
+ []
33925
+ ),
33926
+ () => ts.factory.createIdentifier(context7.hoistName)
33927
+ );
33928
+ return [ctx.hoistedSchemas.get(type2)(), true];
33929
+ }
33930
+ return [createApiCall("Struct", args3), propertyAssignments.length === 0];
33931
+ }
33932
+ );
33933
+ var findNodeToProcess = fn2("StructuralSchemaGen.findNodeToProcess")(
33934
+ function* (sourceFile, textRange) {
33935
+ const ts = yield* service2(TypeScriptApi);
33936
+ const tsUtils = yield* service2(TypeScriptUtils);
33937
+ const typeChecker = yield* service2(TypeCheckerApi);
33938
+ return pipe(
33939
+ tsUtils.getAncestorNodesInRange(sourceFile, textRange),
33940
+ filter2((node) => ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node)),
33941
+ filter2((node) => tsUtils.isNodeInRange(textRange)(node.name)),
33942
+ filter2((node) => (node.typeParameters || []).length === 0),
33943
+ map4((node) => ({
33944
+ node,
33945
+ identifier: node.name,
33946
+ type: typeChecker.getTypeAtLocation(node.name),
33947
+ isExported: node.modifiers ? (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) !== 0 : false
33948
+ })),
33949
+ filter2(({ type: type2 }) => !!type2),
33950
+ head
33951
+ );
33952
+ }
33953
+ );
33954
+ var process2 = fn2("StructuralSchemaGen.process")(
33955
+ function* (sourceFile, scope4, typeMap, isExported, handleCodegeneratedComments) {
33956
+ const ts = yield* service2(TypeScriptApi);
33957
+ const tsUtils = yield* service2(TypeScriptUtils);
33958
+ const typeChecker = yield* service2(TypeCheckerApi);
33959
+ const typeParser = yield* service2(TypeParser);
33960
+ const schemaIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Schema") || "Schema";
33961
+ const ctx = yield* makeStructuralSchemaGenContext(sourceFile, schemaIdentifier);
33962
+ for (const [name, type2] of typeMap.entries()) {
33963
+ ctx.nameToType.set(name, type2);
33964
+ }
33965
+ if (handleCodegeneratedComments) {
33966
+ for (const declaration of sourceFile.statements) {
33967
+ const nodeText = sourceFile.text.slice(declaration.pos, declaration.end);
33968
+ if (!nodeText.toLowerCase().includes("@effect-schema-codegenerated")) continue;
33969
+ const interleavingRange = ctx.rangesToDelete.find(
33970
+ (range3) => range3.pos < declaration.end && range3.end > declaration.pos
33971
+ );
33972
+ if (interleavingRange) {
33973
+ interleavingRange.pos = Math.min(interleavingRange.pos, declaration.pos);
33974
+ interleavingRange.end = Math.max(interleavingRange.end, declaration.end);
33975
+ } else {
33976
+ ctx.rangesToDelete.push({
33977
+ pos: declaration.pos,
33978
+ end: declaration.end
33979
+ });
33980
+ }
33981
+ }
33982
+ }
33983
+ for (const symbol3 of typeChecker.getSymbolsInScope(scope4, ts.SymbolFlags.Value)) {
33984
+ const name = typeChecker.symbolToString(symbol3);
33985
+ ctx.usedGlobalIdentifiers.set(name, 1);
33986
+ const type2 = typeChecker.getTypeOfSymbolAtLocation(symbol3, sourceFile);
33987
+ if (type2) {
33988
+ const schemaType = yield* pipe(
33989
+ typeParser.effectSchemaType(type2, scope4),
33990
+ orElse14(() => void_8)
33991
+ );
33992
+ if (schemaType) {
33993
+ ctx.hoistedSchemas.set(
33994
+ schemaType.A,
33995
+ () => {
33996
+ const expression = typeChecker.symbolToExpression(
33997
+ symbol3,
33998
+ ts.SymbolFlags.Value,
33999
+ scope4,
34000
+ ts.NodeBuilderFlags.NoTruncation
34001
+ );
34002
+ if (expression) {
34003
+ return expression;
34004
+ }
34005
+ return ts.factory.createIdentifier(name);
34006
+ }
34007
+ );
34008
+ }
34009
+ }
34010
+ }
34011
+ const results = yield* pipe(
34012
+ all9(
34013
+ ...fromIterable(ctx.nameToType.entries()).map(
34014
+ ([name, type2]) => pipe(
34015
+ processType(type2),
34016
+ orElse14(
34017
+ (error4) => succeed17(ts.addSyntheticLeadingComment(
34018
+ ts.factory.createIdentifier(""),
34019
+ ts.SyntaxKind.MultiLineCommentTrivia,
34020
+ " " + String(error4) + " ",
34021
+ true
34022
+ ))
34023
+ ),
34024
+ map34((_) => ({ requestedName: name, type: type2, result: _ }))
34025
+ )
34026
+ )
34027
+ ),
34028
+ provideService7(StructuralSchemaGenContext, ctx)
34029
+ );
34030
+ for (const { requestedName, result, type: type2 } of results) {
34031
+ const statementIndex = ctx.typeToStatementIndex.get(type2);
34032
+ if (statementIndex !== void 0) continue;
34033
+ ctx.schemaStatements.push(ts.factory.createVariableStatement(
34034
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
34035
+ ts.factory.createVariableDeclarationList(
34036
+ [ts.factory.createVariableDeclaration(
34037
+ ts.factory.createIdentifier(requestedName),
34038
+ void 0,
34039
+ void 0,
34040
+ result
34041
+ )],
34042
+ ts.NodeFlags.Const
34043
+ )
34044
+ ));
34045
+ ctx.typeToStatementIndex.set(type2, ctx.schemaStatements.length - 1);
34046
+ }
34047
+ if (isExported) {
34048
+ const statementsToExport = pipe(
34049
+ fromIterable(ctx.nameToType),
34050
+ map4(([_, type2]) => ctx.typeToStatementIndex.get(type2)),
34051
+ filter2((index) => index !== void 0),
34052
+ dedupe
34053
+ );
34054
+ for (let i = 0; i < ctx.schemaStatements.length; i++) {
34055
+ if (!statementsToExport.includes(i)) continue;
34056
+ const statement = ctx.schemaStatements[i];
34057
+ if (ts.isVariableStatement(statement)) {
34058
+ ctx.schemaStatements[i] = ts.factory.updateVariableStatement(
34059
+ statement,
34060
+ ts.factory.createModifiersFromModifierFlags(ts.ModifierFlags.Export),
34061
+ statement.declarationList
34062
+ );
34063
+ } else if (ts.isClassDeclaration(statement)) {
34064
+ ctx.schemaStatements[i] = ts.factory.updateClassDeclaration(
34065
+ statement,
34066
+ ts.factory.createModifiersFromModifierFlags(ts.ModifierFlags.Export),
34067
+ statement.name,
34068
+ statement.typeParameters,
34069
+ statement.heritageClauses,
34070
+ statement.members
34071
+ );
34072
+ }
34073
+ }
34074
+ }
34075
+ if (handleCodegeneratedComments) {
34076
+ for (let i = 0; i < ctx.schemaStatements.length; i++) {
34077
+ const statement = ctx.schemaStatements[i];
34078
+ ctx.schemaStatements[i] = ts.addSyntheticLeadingComment(
34079
+ statement,
34080
+ ts.SyntaxKind.SingleLineCommentTrivia,
34081
+ " @effect-schema-codegenerated: This schema will be re-generated by the effect-schema-codegens command, remove this comment to disable re-generation.",
34082
+ true
34083
+ );
34084
+ }
34085
+ }
34086
+ return ctx;
34087
+ }
34088
+ );
34089
+ var applyAtNode = fn2("StructuralSchemaGen.applyAtNode")(
34090
+ function* (sourceFile, node, identifier2, type2, isExported) {
34091
+ const changeTracker = yield* service2(ChangeTracker);
34092
+ const ts = yield* service2(TypeScriptApi);
34093
+ const ctx = yield* process2(sourceFile, node, /* @__PURE__ */ new Map([[ts.idText(identifier2), type2]]), isExported, false);
34094
+ for (const statement of ctx.schemaStatements) {
34095
+ changeTracker.insertNodeAt(sourceFile, node.pos, statement, { prefix: "\n", suffix: "\n" });
34096
+ }
34097
+ }
34098
+ );
34099
+
34100
+ // src/codegens/typeToSchema.ts
34101
+ var typeToSchema = createCodegen({
34102
+ name: "typeToSchema",
34103
+ apply: fn2("typeToSchema.apply")(function* (sourceFile, textRange) {
34104
+ const ts = yield* service2(TypeScriptApi);
34105
+ const tsUtils = yield* service2(TypeScriptUtils);
34106
+ const typeChecker = yield* service2(TypeCheckerApi);
34107
+ const typeCheckerUtils = yield* service2(TypeCheckerUtils);
34108
+ const typeParser = yield* service2(TypeParser);
34109
+ const program = yield* service2(TypeScriptProgram);
34110
+ const inThisFile = yield* getCodegensForSourceFile([typeToSchema], sourceFile);
34111
+ if (inThisFile.length > 1) {
34112
+ return yield* fail18(
34113
+ new CodegenNotApplicableError("the typeToSchema codegen can be used only once per file")
34114
+ );
34115
+ }
34116
+ const parse6 = (node) => gen3(function* () {
34117
+ if (!ts.isTypeAliasDeclaration(node)) {
34118
+ return yield* fail18(
34119
+ new CodegenNotApplicableError(
34120
+ "this codegen is applicable only to a type alias where each object member is a schema to generate. e.g. `type ToGenerate = { UserSchema: User, TodoSchema: Todo}`"
34121
+ )
34122
+ );
34123
+ }
34124
+ const type2 = typeChecker.getTypeAtLocation(node.name);
34125
+ if (!type2) {
34126
+ return yield* fail18(
34127
+ new CodegenNotApplicableError(
34128
+ "error getting the type to process"
34129
+ )
34130
+ );
34131
+ }
34132
+ const nameToType = /* @__PURE__ */ new Map();
34133
+ const typeProperties = typeChecker.getPropertiesOfType(type2);
34134
+ for (const symProp of typeProperties) {
34135
+ const symName = ts.symbolName(symProp);
34136
+ const propType = typeChecker.getTypeOfSymbolAtLocation(symProp, node);
34137
+ if (propType) nameToType.set(symName, propType);
34138
+ }
34139
+ const hash2 = pipe(
34140
+ fromIterable(nameToType),
34141
+ map4(([name, type3]) => {
34142
+ const typeString = typeChecker.typeToString(
34143
+ type3,
34144
+ node,
34145
+ ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.UseStructuralFallback
34146
+ );
34147
+ return name + ": " + typeString;
34148
+ }),
34149
+ join("\n"),
34150
+ cyrb53
34151
+ );
34152
+ return {
34153
+ hash: hash2,
34154
+ nameToType
34155
+ };
34156
+ });
34157
+ const nodeAndCommentRange = tsUtils.findNodeWithLeadingCommentAtPosition(sourceFile, textRange.pos);
34158
+ if (!nodeAndCommentRange) {
34159
+ return yield* fail18(new CodegenNotApplicableError("no node and comment range affected"));
34160
+ }
34161
+ return yield* pipe(
34162
+ parse6(nodeAndCommentRange.node),
34163
+ map34(
34164
+ (_) => ({
34165
+ hash: _.hash,
34166
+ description: "Generate Schemas from types",
34167
+ apply: pipe(
34168
+ gen3(function* () {
34169
+ const changeTracker = yield* service2(ChangeTracker);
34170
+ const ctx = yield* process2(
34171
+ sourceFile,
34172
+ nodeAndCommentRange.node,
34173
+ _.nameToType,
34174
+ true,
34175
+ true
34176
+ );
34177
+ const pos = sourceFile.end;
34178
+ for (const range3 of ctx.rangesToDelete) {
34179
+ changeTracker.deleteRange(sourceFile, range3);
34180
+ }
34181
+ for (const statement of ctx.schemaStatements) {
34182
+ changeTracker.insertNodeAt(sourceFile, pos, statement, { prefix: "\n", suffix: "\n" });
34183
+ }
34184
+ }),
34185
+ provideService7(TypeScriptApi, ts),
34186
+ provideService7(TypeScriptUtils, tsUtils),
34187
+ provideService7(TypeCheckerApi, typeChecker),
34188
+ provideService7(TypeCheckerUtils, typeCheckerUtils),
34189
+ provideService7(TypeParser, typeParser),
34190
+ provideService7(TypeScriptProgram, program)
34191
+ )
34192
+ })
34193
+ )
34194
+ );
34195
+ })
34196
+ });
34197
+
33536
34198
  // src/codegens.ts
33537
- var codegens = [accessors, annotate3];
34199
+ var codegens = [accessors, annotate3, typeToSchema];
33538
34200
 
33539
34201
  // src/cli/codegen.ts
33540
34202
  var NoFilesToCodegenError = class extends TaggedError("NoFilesToCodegenError") {
@@ -33554,11 +34216,15 @@ var verbose = boolean5("verbose").pipe(
33554
34216
  withDefault3(false),
33555
34217
  withDescription3("Verbose output.")
33556
34218
  );
34219
+ var force = boolean5("force").pipe(
34220
+ withDefault3(false),
34221
+ withDescription3("Force codegen even if no changes are needed.")
34222
+ );
33557
34223
  var BATCH_SIZE = 50;
33558
34224
  var codegen = make58(
33559
34225
  "codegen",
33560
- { file: file4, project: project2, verbose },
33561
- fn("codegen")(function* ({ file: file5, project: project3, verbose: verbose2 }) {
34226
+ { file: file4, project: project2, verbose, force },
34227
+ fn("codegen")(function* ({ file: file5, force: force3, project: project3, verbose: verbose2 }) {
33562
34228
  const path2 = yield* Path2;
33563
34229
  const fs = yield* FileSystem;
33564
34230
  const tsInstance = yield* getTypeScript;
@@ -33622,7 +34288,7 @@ var codegen = make58(
33622
34288
  getEditsForCodegen([codegen2], sourceFile, range3),
33623
34289
  orElse14(() => void_8)
33624
34290
  );
33625
- if (applicable && applicable.hash !== hash2) {
34291
+ if (applicable && (applicable.hash !== hash2 || force3)) {
33626
34292
  const changes2 = tsInstance.textChanges.ChangeTracker.with(
33627
34293
  {
33628
34294
  formatContext,
@@ -36796,7 +37462,7 @@ var moduleNames = choice3("module", [
36796
37462
  repeated4,
36797
37463
  withDescription3("The name of the module to patch.")
36798
37464
  );
36799
- var force = boolean5("force").pipe(
37465
+ var force2 = boolean5("force").pipe(
36800
37466
  withDefault3(false),
36801
37467
  withDescription3("Force patch even if already patched.")
36802
37468
  );
@@ -36998,8 +37664,8 @@ var printRememberPrepareScript = fn("printRememberPrepareScript")(function* () {
36998
37664
  }, ignore2);
36999
37665
  var patch9 = make58(
37000
37666
  "patch",
37001
- { dirPath: dirPath2, moduleNames, force },
37002
- fn("patch")(function* ({ dirPath: dirPath4, force: force2, moduleNames: moduleNames3 }) {
37667
+ { dirPath: dirPath2, moduleNames, force: force2 },
37668
+ fn("patch")(function* ({ dirPath: dirPath4, force: force3, moduleNames: moduleNames3 }) {
37003
37669
  const fs = yield* FileSystem;
37004
37670
  const { version: effectLspVersion } = yield* getPackageJsonData(__dirname);
37005
37671
  yield* logDebug2(`Searching for typescript in ${dirPath4}...`);
@@ -37014,7 +37680,7 @@ var patch9 = make58(
37014
37680
  yield* logDebug2(
37015
37681
  `Checking if ${filePath} is already patched with marker ${getPatchedMarker(effectLspVersion)}...`
37016
37682
  );
37017
- if (!force2 && sourceText.indexOf(getPatchedMarker(effectLspVersion)) !== -1) {
37683
+ if (!force3 && sourceText.indexOf(getPatchedMarker(effectLspVersion)) !== -1) {
37018
37684
  yield* logInfo2(`${filePath} is already patched with version ${effectLspVersion}, skipped.`);
37019
37685
  continue;
37020
37686
  }