@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/transform.js CHANGED
@@ -764,6 +764,10 @@ var isEmptyArray = (self) => self.length === 0;
764
764
  var isEmptyReadonlyArray = isEmptyArray;
765
765
  var isNonEmptyReadonlyArray = isNonEmptyArray;
766
766
  var isOutOfBounds = (i, as) => i < 0 || i >= as.length;
767
+ var get = /* @__PURE__ */ dual(2, (self, index) => {
768
+ const i = Math.floor(index);
769
+ return isOutOfBounds(i, self) ? none2() : some2(self[i]);
770
+ });
767
771
  var unsafeGet = /* @__PURE__ */ dual(2, (self, index) => {
768
772
  const i = Math.floor(index);
769
773
  if (isOutOfBounds(i, self)) {
@@ -771,6 +775,7 @@ var unsafeGet = /* @__PURE__ */ dual(2, (self, index) => {
771
775
  }
772
776
  return self[i];
773
777
  });
778
+ var head = /* @__PURE__ */ get(0);
774
779
  var headNonEmpty = /* @__PURE__ */ unsafeGet(0);
775
780
  var tailNonEmpty = (self) => self.slice(1);
776
781
  var reverse = (self) => Array.from(self).reverse();
@@ -834,6 +839,7 @@ var dedupeWith = /* @__PURE__ */ dual(2, (self, isEquivalent) => {
834
839
  return [];
835
840
  });
836
841
  var dedupe = (self) => dedupeWith(self, equivalence());
842
+ var join = /* @__PURE__ */ dual(2, (self, sep) => fromIterable(self).join(sep));
837
843
 
838
844
  // src/core/Nano.ts
839
845
  var NanoTag = class {
@@ -2138,7 +2144,11 @@ var getEditsForCodegen = fn("LSP.getEditsForCodegen")(function* (codegens2, sour
2138
2144
  service(ChangeTracker),
2139
2145
  map4((changeTracker) => {
2140
2146
  changeTracker.deleteRange(sourceFile, range);
2141
- changeTracker.insertText(sourceFile, range.pos, `${codegen.name}:${edit.hash}`);
2147
+ changeTracker.insertText(
2148
+ sourceFile,
2149
+ range.pos,
2150
+ edit.hash.length > 0 ? `${codegen.name}:${edit.hash}` : codegen.name
2151
+ );
2142
2152
  })
2143
2153
  );
2144
2154
  return {
@@ -2184,6 +2194,9 @@ function makeTypeCheckerUtils(ts, typeChecker, tsUtils) {
2184
2194
  function isThisTypeParameter(type) {
2185
2195
  return !!(type.flags & ts.TypeFlags.TypeParameter && type.isThisType);
2186
2196
  }
2197
+ function isMissingIntrinsicType(type) {
2198
+ return (type.flags & ts.TypeFlags.Undefined) !== 0 && "debugIntrinsicName" in type && type.debugIntrinsicName === "missing";
2199
+ }
2187
2200
  function getTypeParameterAtPosition(signature, pos) {
2188
2201
  const type = typeChecker.getParameterType(signature, pos);
2189
2202
  if (isIndexType(type) && isThisTypeParameter(type.type)) {
@@ -2488,6 +2501,7 @@ function makeTypeCheckerUtils(ts, typeChecker, tsUtils) {
2488
2501
  }
2489
2502
  return {
2490
2503
  isUnion,
2504
+ isMissingIntrinsicType,
2491
2505
  getTypeParameterAtPosition,
2492
2506
  getMissingTypeEntriesInTargetType,
2493
2507
  unrollUnionMembers,
@@ -5659,8 +5673,662 @@ var annotate = createCodegen({
5659
5673
  })
5660
5674
  });
5661
5675
 
5676
+ // src/utils/StructuralSchemaGen.ts
5677
+ var UnsupportedTypeError = class {
5678
+ constructor(type, reason) {
5679
+ this.type = type;
5680
+ this.reason = reason;
5681
+ }
5682
+ _tag = "@effect/language-service/UnsupportedTypeError";
5683
+ toString() {
5684
+ return `Unsupported type: ${this.reason}`;
5685
+ }
5686
+ };
5687
+ var StructuralSchemaGenContext = Tag("StructuralSchemaGenContext");
5688
+ var makeStructuralSchemaGenContext = fn("StructuralSchemaGen.makeContext")(
5689
+ function* (sourceFile, schemaIdentifier) {
5690
+ const ts = yield* service(TypeScriptApi);
5691
+ const program = yield* service(TypeScriptProgram);
5692
+ const typeChecker = yield* service(TypeCheckerApi);
5693
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
5694
+ const effectSchemaIdentifier = schemaIdentifier || "Schema";
5695
+ return identity({
5696
+ ts,
5697
+ program,
5698
+ typeChecker,
5699
+ typeCheckerUtils,
5700
+ sourceFile,
5701
+ createApiPropertyAccess: (apiName) => ts.factory.createPropertyAccessExpression(
5702
+ ts.factory.createIdentifier(effectSchemaIdentifier),
5703
+ apiName
5704
+ ),
5705
+ createApiCall: (apiName, args2) => ts.factory.createCallExpression(
5706
+ ts.factory.createPropertyAccessExpression(
5707
+ ts.factory.createIdentifier(effectSchemaIdentifier),
5708
+ apiName
5709
+ ),
5710
+ [],
5711
+ args2
5712
+ ),
5713
+ hoistedSchemas: /* @__PURE__ */ new Map(),
5714
+ typeToStatementIndex: /* @__PURE__ */ new Map(),
5715
+ nameToType: /* @__PURE__ */ new Map(),
5716
+ usedGlobalIdentifiers: /* @__PURE__ */ new Map(),
5717
+ schemaStatements: [],
5718
+ rangesToDelete: []
5719
+ });
5720
+ }
5721
+ );
5722
+ var pushHoistedStatement = fn("StructuralSchemaGen.pushHoistedStatement")(
5723
+ function* (ctx, name, type, statement, createReference) {
5724
+ ctx.usedGlobalIdentifiers.set(name, (ctx.usedGlobalIdentifiers.get(name) || 0) + 1);
5725
+ ctx.schemaStatements.push(statement);
5726
+ ctx.typeToStatementIndex.set(type, ctx.schemaStatements.length - 1);
5727
+ ctx.hoistedSchemas.set(type, createReference);
5728
+ }
5729
+ );
5730
+ var pushHoistedVariableStatement = fn("StructuralSchemaGen.pushHoistedVariableStatement")(
5731
+ function* (ts, ctx, name, type, result) {
5732
+ return yield* pushHoistedStatement(
5733
+ ctx,
5734
+ name,
5735
+ type,
5736
+ ts.factory.createVariableStatement(
5737
+ void 0,
5738
+ ts.factory.createVariableDeclarationList(
5739
+ [ts.factory.createVariableDeclaration(ts.factory.createIdentifier(name), void 0, void 0, result)],
5740
+ ts.NodeFlags.Const
5741
+ )
5742
+ ),
5743
+ () => ts.factory.createIdentifier(name)
5744
+ );
5745
+ }
5746
+ );
5747
+ var createProcessingContext = (maxDepth = 200) => ({
5748
+ depth: 0,
5749
+ maxDepth,
5750
+ hoistName: void 0
5751
+ });
5752
+ var processType = fn(
5753
+ "StructuralSchemaGen.processType"
5754
+ )(
5755
+ function* (type, context) {
5756
+ const processingContext = context || createProcessingContext();
5757
+ const { hoistedSchemas, nameToType, ts, typeChecker, usedGlobalIdentifiers } = yield* service(
5758
+ StructuralSchemaGenContext
5759
+ );
5760
+ if (processingContext.depth >= processingContext.maxDepth) {
5761
+ return yield* fail(new UnsupportedTypeError(type, "Maximum depth exceeded"));
5762
+ }
5763
+ let hoistName = fromIterable(nameToType.entries()).find(([_, existingType]) => existingType === type)?.[0];
5764
+ if (!hoistName && type && type.symbol && type.symbol.declarations && type.symbol.declarations.length === 1) {
5765
+ const declaration = type.symbol.declarations[0];
5766
+ if (ts.isInterfaceDeclaration(declaration)) {
5767
+ hoistName = ts.idText(declaration.name);
5768
+ } else if (declaration.parent && ts.isTypeAliasDeclaration(declaration.parent)) {
5769
+ hoistName = ts.idText(declaration.parent.name);
5770
+ }
5771
+ if (hoistName) {
5772
+ const existingType = nameToType.get(hoistName);
5773
+ const isSame = existingType && typeChecker.isTypeAssignableTo(type, existingType) && typeChecker.isTypeAssignableTo(existingType, type);
5774
+ if (!isSame) {
5775
+ const usedCount = usedGlobalIdentifiers.get(hoistName) || 0;
5776
+ hoistName = usedCount > 0 ? hoistName + "_" + usedCount : hoistName;
5777
+ }
5778
+ }
5779
+ }
5780
+ const nestedContext = {
5781
+ ...processingContext,
5782
+ depth: processingContext.depth + 1,
5783
+ hoistName
5784
+ };
5785
+ for (const [hoistedType, hoistedSchema] of hoistedSchemas.entries()) {
5786
+ if (hoistedType === type || typeChecker.isTypeAssignableTo(type, hoistedType) && typeChecker.isTypeAssignableTo(hoistedType, type)) {
5787
+ return hoistedSchema();
5788
+ }
5789
+ }
5790
+ const [schemaExpr, skipHoisting] = yield* processTypeImpl(type, nestedContext);
5791
+ if (!skipHoisting && hoistName) {
5792
+ const ctx = yield* service(StructuralSchemaGenContext);
5793
+ yield* pushHoistedVariableStatement(ts, ctx, hoistName, type, schemaExpr);
5794
+ return ctx.hoistedSchemas.get(type)();
5795
+ }
5796
+ return schemaExpr;
5797
+ }
5798
+ );
5799
+ var processTypeImpl = fn(
5800
+ "StructuralSchemaGen.processTypeImpl"
5801
+ )(
5802
+ function* (type, context) {
5803
+ const { createApiCall, createApiPropertyAccess, ts, typeChecker, typeCheckerUtils } = yield* service(
5804
+ StructuralSchemaGenContext
5805
+ );
5806
+ if (type.flags & ts.TypeFlags.String) {
5807
+ return [createApiPropertyAccess("String"), true];
5808
+ }
5809
+ if (type.flags & ts.TypeFlags.Number) {
5810
+ return [createApiPropertyAccess("Number"), true];
5811
+ }
5812
+ if (type.flags & ts.TypeFlags.Boolean) {
5813
+ return [createApiPropertyAccess("Boolean"), true];
5814
+ }
5815
+ if (type.flags & ts.TypeFlags.BigInt) {
5816
+ return [createApiPropertyAccess("BigInt"), true];
5817
+ }
5818
+ if (type.flags & ts.TypeFlags.Void) {
5819
+ return [createApiPropertyAccess("Void"), true];
5820
+ }
5821
+ if (type.flags & ts.TypeFlags.Undefined) {
5822
+ return [createApiPropertyAccess("Undefined"), true];
5823
+ }
5824
+ if (type.flags & ts.TypeFlags.Null) {
5825
+ return [createApiPropertyAccess("Null"), true];
5826
+ }
5827
+ if (type.flags & ts.TypeFlags.Never) {
5828
+ return [createApiPropertyAccess("Never"), true];
5829
+ }
5830
+ if (type.flags & ts.TypeFlags.Any) {
5831
+ return [createApiPropertyAccess("Any"), true];
5832
+ }
5833
+ if (type.flags & ts.TypeFlags.Unknown) {
5834
+ return [createApiPropertyAccess("Unknown"), true];
5835
+ }
5836
+ if (type.flags & ts.TypeFlags.StringLiteral) {
5837
+ const literalType = type;
5838
+ return [createApiCall("Literal", [ts.factory.createStringLiteral(literalType.value)]), true];
5839
+ }
5840
+ if (type.flags & ts.TypeFlags.NumberLiteral) {
5841
+ const literalType = type;
5842
+ return [createApiCall("Literal", [ts.factory.createNumericLiteral(literalType.value)]), true];
5843
+ }
5844
+ if (type.flags & ts.TypeFlags.BooleanLiteral) {
5845
+ const value = type.intrinsicName === "true";
5846
+ return [createApiCall("Literal", [value ? ts.factory.createTrue() : ts.factory.createFalse()]), true];
5847
+ }
5848
+ if (typeCheckerUtils.isUnion(type)) {
5849
+ return yield* processUnionType(type.types, context);
5850
+ }
5851
+ if (type.flags & ts.TypeFlags.Intersection) {
5852
+ return yield* processIntersectionType(type, context);
5853
+ }
5854
+ if (typeChecker.isArrayType(type)) {
5855
+ return yield* processArrayType(type, context);
5856
+ }
5857
+ if (typeChecker.isTupleType(type)) {
5858
+ return yield* processTupleType(type, context);
5859
+ }
5860
+ if (type.flags & ts.TypeFlags.Object) {
5861
+ const symbol3 = type.symbol || type.aliasSymbol;
5862
+ if (symbol3) {
5863
+ const typeName = typeChecker.symbolToString(symbol3);
5864
+ if (typeName === "Date") {
5865
+ return [createApiPropertyAccess("Date"), false];
5866
+ }
5867
+ if (typeName === "ReadonlyArray" || typeName === "Array") {
5868
+ return yield* processArrayType(type, context);
5869
+ }
5870
+ }
5871
+ const objectType = type;
5872
+ return yield* processObjectType(objectType, context);
5873
+ }
5874
+ return yield* fail(
5875
+ new UnsupportedTypeError(
5876
+ type,
5877
+ `Type with flags ${type.flags} is not supported`
5878
+ )
5879
+ );
5880
+ }
5881
+ );
5882
+ var processUnionType = fn(
5883
+ "StructuralSchemaGen.processUnionType"
5884
+ )(
5885
+ function* (types, context) {
5886
+ const { createApiCall, ts } = yield* service(StructuralSchemaGenContext);
5887
+ const allLiterals = types.every(
5888
+ (t) => t.flags & ts.TypeFlags.StringLiteral || t.flags & ts.TypeFlags.NumberLiteral || t.flags & ts.TypeFlags.BooleanLiteral
5889
+ );
5890
+ if (allLiterals) {
5891
+ const literals = yield* all(
5892
+ ...types.map((t) => processType(t, context))
5893
+ );
5894
+ const literalValues = literals.map((expr) => {
5895
+ if (ts.isCallExpression(expr) && expr.arguments.length > 0) {
5896
+ return expr.arguments[0];
5897
+ }
5898
+ return expr;
5899
+ }).filter((arg) => arg !== void 0);
5900
+ return [createApiCall("Literal", literalValues), false];
5901
+ }
5902
+ const members = yield* all(
5903
+ ...types.map((t) => processType(t, context))
5904
+ );
5905
+ if (members.length === 1) {
5906
+ return [members[0], false];
5907
+ }
5908
+ return [createApiCall("Union", members), false];
5909
+ }
5910
+ );
5911
+ var processIntersectionType = fn(
5912
+ "StructuralSchemaGen.processIntersectionType"
5913
+ )(
5914
+ function* (type, context) {
5915
+ const { createApiCall, ts } = yield* service(StructuralSchemaGenContext);
5916
+ const [firstSchema, ...otherSchemas] = yield* all(
5917
+ ...type.types.map((t) => processType(t, context))
5918
+ );
5919
+ if (otherSchemas.length === 0) {
5920
+ return [firstSchema, false];
5921
+ }
5922
+ return [
5923
+ ts.factory.createCallExpression(
5924
+ ts.factory.createPropertyAccessExpression(
5925
+ firstSchema,
5926
+ "pipe"
5927
+ ),
5928
+ [],
5929
+ otherSchemas.map((schema) => createApiCall("extend", [schema]))
5930
+ ),
5931
+ false
5932
+ ];
5933
+ }
5934
+ );
5935
+ var processArrayType = fn(
5936
+ "StructuralSchemaGen.processArrayType"
5937
+ )(
5938
+ function* (type, context) {
5939
+ const { createApiCall, typeChecker } = yield* service(StructuralSchemaGenContext);
5940
+ const typeArgs = typeChecker.getTypeArguments(type);
5941
+ if (typeArgs.length === 0) {
5942
+ return yield* fail(new UnsupportedTypeError(type, "Array type has no type arguments"));
5943
+ }
5944
+ const elementSchema = yield* processType(typeArgs[0], context);
5945
+ return [createApiCall("Array", [elementSchema]), false];
5946
+ }
5947
+ );
5948
+ var processTupleType = fn(
5949
+ "StructuralSchemaGen.processTupleType"
5950
+ )(
5951
+ function* (type, context) {
5952
+ const { createApiCall, typeChecker } = yield* service(StructuralSchemaGenContext);
5953
+ const typeArgs = typeChecker.getTypeArguments(type);
5954
+ const elementSchemas = yield* all(
5955
+ ...typeArgs.map((t) => processType(t, context))
5956
+ );
5957
+ return [createApiCall("Tuple", elementSchemas), false];
5958
+ }
5959
+ );
5960
+ var processObjectType = fn(
5961
+ "StructuralSchemaGen.processObjectType"
5962
+ )(
5963
+ function* (type, context) {
5964
+ const {
5965
+ createApiCall,
5966
+ createApiPropertyAccess,
5967
+ program,
5968
+ ts,
5969
+ typeChecker,
5970
+ typeCheckerUtils
5971
+ } = yield* service(
5972
+ StructuralSchemaGenContext
5973
+ );
5974
+ let hasRecords = false;
5975
+ const properties = typeChecker.getPropertiesOfType(type);
5976
+ const propertyAssignments = [];
5977
+ for (const property of properties) {
5978
+ const propertyName = typeChecker.symbolToString(property);
5979
+ const propertyType = typeChecker.getTypeOfSymbol(property);
5980
+ const isOptional = (property.flags & ts.SymbolFlags.Optional) !== 0;
5981
+ let schemaExpr;
5982
+ if (isOptional) {
5983
+ if (program.getCompilerOptions().exactOptionalPropertyTypes) {
5984
+ if (typeCheckerUtils.isUnion(propertyType)) {
5985
+ const typeWithoutMissing = propertyType.types.filter((t) => !typeCheckerUtils.isMissingIntrinsicType(t));
5986
+ const [result, _] = yield* processUnionType(typeWithoutMissing, context);
5987
+ schemaExpr = createApiCall("optionalWith", [
5988
+ result,
5989
+ ts.factory.createObjectLiteralExpression([
5990
+ ts.factory.createPropertyAssignment("exact", ts.factory.createTrue())
5991
+ ])
5992
+ ]);
5993
+ }
5994
+ } else {
5995
+ schemaExpr = yield* processType(propertyType, context);
5996
+ schemaExpr = createApiCall("optional", [schemaExpr]);
5997
+ }
5998
+ }
5999
+ if (!schemaExpr) {
6000
+ schemaExpr = yield* processType(propertyType, context);
6001
+ }
6002
+ const propertyNameNode = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(propertyName) ? ts.factory.createIdentifier(propertyName) : ts.factory.createStringLiteral(propertyName);
6003
+ propertyAssignments.push(
6004
+ ts.factory.createPropertyAssignment(
6005
+ propertyNameNode,
6006
+ schemaExpr
6007
+ )
6008
+ );
6009
+ }
6010
+ const indexInfos = typeChecker.getIndexInfosOfType(type);
6011
+ const args2 = [
6012
+ ts.factory.createObjectLiteralExpression(propertyAssignments, propertyAssignments.length > 0)
6013
+ ];
6014
+ for (const indexInfo of indexInfos) {
6015
+ hasRecords = true;
6016
+ const keyType = indexInfo.keyType;
6017
+ const valueType = indexInfo.type;
6018
+ const keySchema = yield* processType(keyType, context);
6019
+ const valueSchema = yield* processType(valueType, context);
6020
+ args2.push(
6021
+ ts.factory.createObjectLiteralExpression([
6022
+ ts.factory.createPropertyAssignment("key", keySchema),
6023
+ ts.factory.createPropertyAssignment("value", valueSchema)
6024
+ ])
6025
+ );
6026
+ }
6027
+ if (!hasRecords && context.hoistName) {
6028
+ const ctx = yield* service(StructuralSchemaGenContext);
6029
+ yield* pushHoistedStatement(
6030
+ ctx,
6031
+ context.hoistName,
6032
+ type,
6033
+ ts.factory.createClassDeclaration(
6034
+ void 0,
6035
+ ts.factory.createIdentifier(context.hoistName),
6036
+ [],
6037
+ [ts.factory.createHeritageClause(
6038
+ ts.SyntaxKind.ExtendsKeyword,
6039
+ [
6040
+ ts.factory.createExpressionWithTypeArguments(
6041
+ ts.factory.createCallExpression(
6042
+ ts.factory.createCallExpression(
6043
+ createApiPropertyAccess("Class"),
6044
+ [ts.factory.createTypeReferenceNode(
6045
+ context.hoistName
6046
+ )],
6047
+ [ts.factory.createStringLiteral(context.hoistName)]
6048
+ ),
6049
+ [],
6050
+ args2
6051
+ ),
6052
+ []
6053
+ )
6054
+ ]
6055
+ )],
6056
+ []
6057
+ ),
6058
+ () => ts.factory.createIdentifier(context.hoistName)
6059
+ );
6060
+ return [ctx.hoistedSchemas.get(type)(), true];
6061
+ }
6062
+ return [createApiCall("Struct", args2), propertyAssignments.length === 0];
6063
+ }
6064
+ );
6065
+ var findNodeToProcess = fn("StructuralSchemaGen.findNodeToProcess")(
6066
+ function* (sourceFile, textRange) {
6067
+ const ts = yield* service(TypeScriptApi);
6068
+ const tsUtils = yield* service(TypeScriptUtils);
6069
+ const typeChecker = yield* service(TypeCheckerApi);
6070
+ return pipe(
6071
+ tsUtils.getAncestorNodesInRange(sourceFile, textRange),
6072
+ filter((node) => ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node)),
6073
+ filter((node) => tsUtils.isNodeInRange(textRange)(node.name)),
6074
+ filter((node) => (node.typeParameters || []).length === 0),
6075
+ map3((node) => ({
6076
+ node,
6077
+ identifier: node.name,
6078
+ type: typeChecker.getTypeAtLocation(node.name),
6079
+ isExported: node.modifiers ? (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) !== 0 : false
6080
+ })),
6081
+ filter(({ type }) => !!type),
6082
+ head
6083
+ );
6084
+ }
6085
+ );
6086
+ var process = fn("StructuralSchemaGen.process")(
6087
+ function* (sourceFile, scope, typeMap, isExported, handleCodegeneratedComments) {
6088
+ const ts = yield* service(TypeScriptApi);
6089
+ const tsUtils = yield* service(TypeScriptUtils);
6090
+ const typeChecker = yield* service(TypeCheckerApi);
6091
+ const typeParser = yield* service(TypeParser);
6092
+ const schemaIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Schema") || "Schema";
6093
+ const ctx = yield* makeStructuralSchemaGenContext(sourceFile, schemaIdentifier);
6094
+ for (const [name, type] of typeMap.entries()) {
6095
+ ctx.nameToType.set(name, type);
6096
+ }
6097
+ if (handleCodegeneratedComments) {
6098
+ for (const declaration of sourceFile.statements) {
6099
+ const nodeText = sourceFile.text.slice(declaration.pos, declaration.end);
6100
+ if (!nodeText.toLowerCase().includes("@effect-schema-codegenerated")) continue;
6101
+ const interleavingRange = ctx.rangesToDelete.find(
6102
+ (range) => range.pos < declaration.end && range.end > declaration.pos
6103
+ );
6104
+ if (interleavingRange) {
6105
+ interleavingRange.pos = Math.min(interleavingRange.pos, declaration.pos);
6106
+ interleavingRange.end = Math.max(interleavingRange.end, declaration.end);
6107
+ } else {
6108
+ ctx.rangesToDelete.push({
6109
+ pos: declaration.pos,
6110
+ end: declaration.end
6111
+ });
6112
+ }
6113
+ }
6114
+ }
6115
+ for (const symbol3 of typeChecker.getSymbolsInScope(scope, ts.SymbolFlags.Value)) {
6116
+ const name = typeChecker.symbolToString(symbol3);
6117
+ ctx.usedGlobalIdentifiers.set(name, 1);
6118
+ const type = typeChecker.getTypeOfSymbolAtLocation(symbol3, sourceFile);
6119
+ if (type) {
6120
+ const schemaType = yield* pipe(
6121
+ typeParser.effectSchemaType(type, scope),
6122
+ orElse2(() => void_)
6123
+ );
6124
+ if (schemaType) {
6125
+ ctx.hoistedSchemas.set(
6126
+ schemaType.A,
6127
+ () => {
6128
+ const expression = typeChecker.symbolToExpression(
6129
+ symbol3,
6130
+ ts.SymbolFlags.Value,
6131
+ scope,
6132
+ ts.NodeBuilderFlags.NoTruncation
6133
+ );
6134
+ if (expression) {
6135
+ return expression;
6136
+ }
6137
+ return ts.factory.createIdentifier(name);
6138
+ }
6139
+ );
6140
+ }
6141
+ }
6142
+ }
6143
+ const results = yield* pipe(
6144
+ all(
6145
+ ...fromIterable(ctx.nameToType.entries()).map(
6146
+ ([name, type]) => pipe(
6147
+ processType(type),
6148
+ orElse2(
6149
+ (error) => succeed(ts.addSyntheticLeadingComment(
6150
+ ts.factory.createIdentifier(""),
6151
+ ts.SyntaxKind.MultiLineCommentTrivia,
6152
+ " " + String(error) + " ",
6153
+ true
6154
+ ))
6155
+ ),
6156
+ map4((_) => ({ requestedName: name, type, result: _ }))
6157
+ )
6158
+ )
6159
+ ),
6160
+ provideService(StructuralSchemaGenContext, ctx)
6161
+ );
6162
+ for (const { requestedName, result, type } of results) {
6163
+ const statementIndex = ctx.typeToStatementIndex.get(type);
6164
+ if (statementIndex !== void 0) continue;
6165
+ ctx.schemaStatements.push(ts.factory.createVariableStatement(
6166
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
6167
+ ts.factory.createVariableDeclarationList(
6168
+ [ts.factory.createVariableDeclaration(
6169
+ ts.factory.createIdentifier(requestedName),
6170
+ void 0,
6171
+ void 0,
6172
+ result
6173
+ )],
6174
+ ts.NodeFlags.Const
6175
+ )
6176
+ ));
6177
+ ctx.typeToStatementIndex.set(type, ctx.schemaStatements.length - 1);
6178
+ }
6179
+ if (isExported) {
6180
+ const statementsToExport = pipe(
6181
+ fromIterable(ctx.nameToType),
6182
+ map3(([_, type]) => ctx.typeToStatementIndex.get(type)),
6183
+ filter((index) => index !== void 0),
6184
+ dedupe
6185
+ );
6186
+ for (let i = 0; i < ctx.schemaStatements.length; i++) {
6187
+ if (!statementsToExport.includes(i)) continue;
6188
+ const statement = ctx.schemaStatements[i];
6189
+ if (ts.isVariableStatement(statement)) {
6190
+ ctx.schemaStatements[i] = ts.factory.updateVariableStatement(
6191
+ statement,
6192
+ ts.factory.createModifiersFromModifierFlags(ts.ModifierFlags.Export),
6193
+ statement.declarationList
6194
+ );
6195
+ } else if (ts.isClassDeclaration(statement)) {
6196
+ ctx.schemaStatements[i] = ts.factory.updateClassDeclaration(
6197
+ statement,
6198
+ ts.factory.createModifiersFromModifierFlags(ts.ModifierFlags.Export),
6199
+ statement.name,
6200
+ statement.typeParameters,
6201
+ statement.heritageClauses,
6202
+ statement.members
6203
+ );
6204
+ }
6205
+ }
6206
+ }
6207
+ if (handleCodegeneratedComments) {
6208
+ for (let i = 0; i < ctx.schemaStatements.length; i++) {
6209
+ const statement = ctx.schemaStatements[i];
6210
+ ctx.schemaStatements[i] = ts.addSyntheticLeadingComment(
6211
+ statement,
6212
+ ts.SyntaxKind.SingleLineCommentTrivia,
6213
+ " @effect-schema-codegenerated: This schema will be re-generated by the effect-schema-codegens command, remove this comment to disable re-generation.",
6214
+ true
6215
+ );
6216
+ }
6217
+ }
6218
+ return ctx;
6219
+ }
6220
+ );
6221
+ var applyAtNode = fn("StructuralSchemaGen.applyAtNode")(
6222
+ function* (sourceFile, node, identifier, type, isExported) {
6223
+ const changeTracker = yield* service(ChangeTracker);
6224
+ const ts = yield* service(TypeScriptApi);
6225
+ const ctx = yield* process(sourceFile, node, /* @__PURE__ */ new Map([[ts.idText(identifier), type]]), isExported, false);
6226
+ for (const statement of ctx.schemaStatements) {
6227
+ changeTracker.insertNodeAt(sourceFile, node.pos, statement, { prefix: "\n", suffix: "\n" });
6228
+ }
6229
+ }
6230
+ );
6231
+
6232
+ // src/codegens/typeToSchema.ts
6233
+ var typeToSchema = createCodegen({
6234
+ name: "typeToSchema",
6235
+ apply: fn("typeToSchema.apply")(function* (sourceFile, textRange) {
6236
+ const ts = yield* service(TypeScriptApi);
6237
+ const tsUtils = yield* service(TypeScriptUtils);
6238
+ const typeChecker = yield* service(TypeCheckerApi);
6239
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
6240
+ const typeParser = yield* service(TypeParser);
6241
+ const program = yield* service(TypeScriptProgram);
6242
+ const inThisFile = yield* getCodegensForSourceFile([typeToSchema], sourceFile);
6243
+ if (inThisFile.length > 1) {
6244
+ return yield* fail(
6245
+ new CodegenNotApplicableError("the typeToSchema codegen can be used only once per file")
6246
+ );
6247
+ }
6248
+ const parse3 = (node) => gen(function* () {
6249
+ if (!ts.isTypeAliasDeclaration(node)) {
6250
+ return yield* fail(
6251
+ new CodegenNotApplicableError(
6252
+ "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}`"
6253
+ )
6254
+ );
6255
+ }
6256
+ const type = typeChecker.getTypeAtLocation(node.name);
6257
+ if (!type) {
6258
+ return yield* fail(
6259
+ new CodegenNotApplicableError(
6260
+ "error getting the type to process"
6261
+ )
6262
+ );
6263
+ }
6264
+ const nameToType = /* @__PURE__ */ new Map();
6265
+ const typeProperties = typeChecker.getPropertiesOfType(type);
6266
+ for (const symProp of typeProperties) {
6267
+ const symName = ts.symbolName(symProp);
6268
+ const propType = typeChecker.getTypeOfSymbolAtLocation(symProp, node);
6269
+ if (propType) nameToType.set(symName, propType);
6270
+ }
6271
+ const hash2 = pipe(
6272
+ fromIterable(nameToType),
6273
+ map3(([name, type2]) => {
6274
+ const typeString = typeChecker.typeToString(
6275
+ type2,
6276
+ node,
6277
+ ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.UseStructuralFallback
6278
+ );
6279
+ return name + ": " + typeString;
6280
+ }),
6281
+ join("\n"),
6282
+ cyrb53
6283
+ );
6284
+ return {
6285
+ hash: hash2,
6286
+ nameToType
6287
+ };
6288
+ });
6289
+ const nodeAndCommentRange = tsUtils.findNodeWithLeadingCommentAtPosition(sourceFile, textRange.pos);
6290
+ if (!nodeAndCommentRange) {
6291
+ return yield* fail(new CodegenNotApplicableError("no node and comment range affected"));
6292
+ }
6293
+ return yield* pipe(
6294
+ parse3(nodeAndCommentRange.node),
6295
+ map4(
6296
+ (_) => ({
6297
+ hash: _.hash,
6298
+ description: "Generate Schemas from types",
6299
+ apply: pipe(
6300
+ gen(function* () {
6301
+ const changeTracker = yield* service(ChangeTracker);
6302
+ const ctx = yield* process(
6303
+ sourceFile,
6304
+ nodeAndCommentRange.node,
6305
+ _.nameToType,
6306
+ true,
6307
+ true
6308
+ );
6309
+ const pos = sourceFile.end;
6310
+ for (const range of ctx.rangesToDelete) {
6311
+ changeTracker.deleteRange(sourceFile, range);
6312
+ }
6313
+ for (const statement of ctx.schemaStatements) {
6314
+ changeTracker.insertNodeAt(sourceFile, pos, statement, { prefix: "\n", suffix: "\n" });
6315
+ }
6316
+ }),
6317
+ provideService(TypeScriptApi, ts),
6318
+ provideService(TypeScriptUtils, tsUtils),
6319
+ provideService(TypeCheckerApi, typeChecker),
6320
+ provideService(TypeCheckerUtils, typeCheckerUtils),
6321
+ provideService(TypeParser, typeParser),
6322
+ provideService(TypeScriptProgram, program)
6323
+ )
6324
+ })
6325
+ )
6326
+ );
6327
+ })
6328
+ });
6329
+
5662
6330
  // src/codegens.ts
5663
- var codegens = [accessors, annotate];
6331
+ var codegens = [accessors, annotate, typeToSchema];
5664
6332
 
5665
6333
  // src/diagnostics/outdatedEffectCodegen.ts
5666
6334
  var outdatedEffectCodegen = createDiagnostic({