@sanity/codegen 5.7.0-next.8 → 5.7.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.
Files changed (59) hide show
  1. package/bin/run.js +31 -0
  2. package/dist/_exports/index.js +11 -0
  3. package/dist/_exports/index.js.map +1 -0
  4. package/dist/actions/generatedFileWarning.js +15 -0
  5. package/dist/actions/generatedFileWarning.js.map +1 -0
  6. package/dist/actions/typegenGenerate.worker.js +54 -0
  7. package/dist/actions/typegenGenerate.worker.js.map +1 -0
  8. package/dist/actions/types.js +3 -0
  9. package/dist/actions/types.js.map +1 -0
  10. package/dist/casing.js +27 -0
  11. package/dist/casing.js.map +1 -0
  12. package/dist/commands/typegen/generate.js +237 -0
  13. package/dist/commands/typegen/generate.js.map +1 -0
  14. package/dist/getBabelConfig.js +37 -0
  15. package/dist/getBabelConfig.js.map +1 -0
  16. package/dist/index.d.ts +459 -0
  17. package/dist/readConfig.js +38 -0
  18. package/dist/readConfig.js.map +1 -0
  19. package/dist/readSchema.js +14 -0
  20. package/dist/readSchema.js.map +1 -0
  21. package/dist/safeParseQuery.js +37 -0
  22. package/dist/safeParseQuery.js.map +1 -0
  23. package/dist/typeUtils.js +37 -0
  24. package/dist/typeUtils.js.map +1 -0
  25. package/dist/typescript/constants.js +12 -0
  26. package/dist/typescript/constants.js.map +1 -0
  27. package/dist/typescript/expressionResolvers.js +356 -0
  28. package/dist/typescript/expressionResolvers.js.map +1 -0
  29. package/dist/typescript/findQueriesInPath.js +69 -0
  30. package/dist/typescript/findQueriesInPath.js.map +1 -0
  31. package/dist/typescript/findQueriesInSource.js +175 -0
  32. package/dist/typescript/findQueriesInSource.js.map +1 -0
  33. package/dist/typescript/helpers.js +86 -0
  34. package/dist/typescript/helpers.js.map +1 -0
  35. package/dist/typescript/moduleResolver.js +33 -0
  36. package/dist/typescript/moduleResolver.js.map +1 -0
  37. package/dist/typescript/parseSource.js +75 -0
  38. package/dist/typescript/parseSource.js.map +1 -0
  39. package/dist/typescript/registerBabel.js +23 -0
  40. package/dist/typescript/registerBabel.js.map +1 -0
  41. package/dist/typescript/schemaTypeGenerator.js +323 -0
  42. package/dist/typescript/schemaTypeGenerator.js.map +1 -0
  43. package/dist/typescript/typeGenerator.js +240 -0
  44. package/dist/typescript/typeGenerator.js.map +1 -0
  45. package/dist/typescript/types.js +31 -0
  46. package/dist/typescript/types.js.map +1 -0
  47. package/dist/utils/count.js +6 -0
  48. package/dist/utils/count.js.map +1 -0
  49. package/dist/utils/formatPath.js +8 -0
  50. package/dist/utils/formatPath.js.map +1 -0
  51. package/dist/utils/getMessage.js +3 -0
  52. package/dist/utils/getMessage.js.map +1 -0
  53. package/dist/utils/percent.js +8 -0
  54. package/dist/utils/percent.js.map +1 -0
  55. package/oclif.manifest.json +39 -0
  56. package/package.json +49 -23
  57. package/lib/index.d.ts +0 -433
  58. package/lib/index.js +0 -1011
  59. package/lib/index.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/typescript/schemaTypeGenerator.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport {\n type ArrayTypeNode,\n type DocumentSchemaType,\n type InlineTypeNode,\n type ObjectAttribute,\n type ObjectTypeNode,\n type SchemaType,\n type TypeDeclarationSchemaType,\n typeEvaluate,\n type TypeNode,\n type UnionTypeNode,\n} from 'groq-js'\n\nimport {safeParseQuery} from '../safeParseQuery.js'\nimport {ARRAY_OF, INTERNAL_REFERENCE_SYMBOL} from './constants.js'\nimport {\n getFilterArrayUnionType,\n getUniqueIdentifierForName,\n isIdentifierName,\n weakMapMemo,\n} from './helpers.js'\nimport {type ExtractedQuery, type TypeEvaluationStats} from './types.js'\n\nexport class SchemaTypeGenerator {\n public readonly schema: SchemaType\n evaluateQuery = weakMapMemo(\n // eslint-disable-next-line unicorn/consistent-function-scoping\n ({query}: Pick<ExtractedQuery, 'query'>): {stats: TypeEvaluationStats; tsType: t.TSType} => {\n const ast = safeParseQuery(query)\n const typeNode = typeEvaluate(ast, this.schema)\n const tsType = this.generateTsType(typeNode)\n const stats = walkAndCountQueryTypeNodeStats(typeNode)\n return {stats, tsType}\n },\n )\n private identifiers = new Map<string, t.Identifier>()\n\n private tsTypes = new Map<string, t.TSType>()\n\n constructor(schema: SchemaType) {\n this.schema = schema\n\n const uniqueTypeNames = new Set<string>()\n for (const type of schema) {\n if (uniqueTypeNames.has(type.name)) {\n throw new Error(\n `Duplicate type name \"${type.name}\" in schema. Type names must be unique within the same schema.`,\n )\n }\n uniqueTypeNames.add(type.name)\n }\n\n for (const type of schema) {\n const currentIdentifierNames = new Set([...this.identifiers.values()].map((id) => id.name))\n const uniqueIdentifier = getUniqueIdentifierForName(type.name, currentIdentifierNames)\n this.identifiers.set(type.name, uniqueIdentifier)\n }\n\n for (const type of schema) {\n this.tsTypes.set(type.name, this.generateTsType(type))\n }\n }\n\n getType(typeName: string): {id: t.Identifier; tsType: t.TSType} | undefined {\n const tsType = this.tsTypes.get(typeName)\n const id = this.identifiers.get(typeName)\n if (tsType && id) return {id, tsType}\n return undefined\n }\n\n hasType(typeName: string): boolean {\n return this.tsTypes.has(typeName)\n }\n\n *[Symbol.iterator]() {\n for (const {name} of this.schema) {\n yield {name, ...this.getType(name)!}\n }\n }\n\n typeNames(): string[] {\n return this.schema.map((schemaType) => schemaType.name)\n }\n\n /**\n * Helper function used to generate TS types for arrays of inline types, or arrays of inline types\n * wrapped in the ArrayOf wrapper that adds _key prop\n */\n private generateArrayOfTsType(typeNode: ArrayTypeNode): t.TSTypeReference {\n const typeNodes = this.generateTsType(typeNode.of)\n return t.tsTypeReference(ARRAY_OF, t.tsTypeParameterInstantiation([typeNodes]))\n }\n\n // Helper function used to generate TS types for array type nodes.\n private generateArrayTsType(typeNode: ArrayTypeNode): t.TSTypeReference | t.TSUnionType {\n // if it's an array of a single inline type, wrap it in ArrayOf\n if (typeNode.of.type === 'inline') {\n return this.generateArrayOfTsType(typeNode)\n }\n\n // if it's not an inline object and not a union, wrap in Array\n if (typeNode.of.type !== 'union') {\n const typeNodes = this.generateTsType(typeNode.of)\n return t.tsTypeReference(t.identifier('Array'), t.tsTypeParameterInstantiation([typeNodes]))\n }\n\n // if it's not a union type or all of the union type members are non-inlines, wrap type in Array\n if (typeNode.of.of.every((unionTypeNode) => unionTypeNode.type !== 'inline')) {\n const typeNodes = this.generateTsType(typeNode.of)\n return t.tsTypeReference(t.identifier('Array'), t.tsTypeParameterInstantiation([typeNodes]))\n }\n\n // all the union types nodes are inline\n if (typeNode.of.of.every((unionMember) => unionMember.type === 'inline')) {\n return this.generateArrayOfTsType(typeNode)\n }\n\n // some of the union types are inlines, while some are not - split and recurse\n const arrayOfNonInline = getFilterArrayUnionType(typeNode, (member) => member.type !== 'inline')\n const arrayOfInline = getFilterArrayUnionType(typeNode, (member) => member.type === 'inline')\n\n return t.tsUnionType([\n this.generateArrayTsType(arrayOfNonInline),\n this.generateArrayTsType(arrayOfInline),\n ])\n }\n\n // Helper function used to generate TS types for document type nodes.\n private generateDocumentTsType(document: DocumentSchemaType): t.TSType {\n const props = Object.entries(document.attributes).map(([key, node]) =>\n this.generateTsObjectProperty(key, node),\n )\n\n return t.tsTypeLiteral(props)\n }\n\n private generateInlineTsType(typeNode: InlineTypeNode): t.TSType {\n const id = this.identifiers.get(typeNode.name)\n if (!id) {\n // Not found in schema, return unknown type\n return t.addComment(\n t.tsUnknownKeyword(),\n 'trailing',\n ` Unable to locate the referenced type \"${typeNode.name}\" in schema`,\n true,\n )\n }\n\n return t.tsTypeReference(id)\n }\n\n // Helper function used to generate TS types for object type nodes.\n private generateObjectTsType(typeNode: ObjectTypeNode): t.TSType {\n const props: t.TSPropertySignature[] = []\n for (const [key, attribute] of Object.entries(typeNode.attributes)) {\n props.push(this.generateTsObjectProperty(key, attribute))\n }\n const rest = typeNode.rest\n\n if (rest) {\n switch (rest.type) {\n case 'inline': {\n const resolved = this.generateInlineTsType(rest)\n // if object rest is unknown, we can't generate a type literal for it\n if (t.isTSUnknownKeyword(resolved)) return resolved\n return t.tsIntersectionType([t.tsTypeLiteral(props), resolved])\n }\n case 'object': {\n for (const [key, attribute] of Object.entries(rest.attributes)) {\n props.push(this.generateTsObjectProperty(key, attribute))\n }\n break\n }\n case 'unknown': {\n return t.tsUnknownKeyword()\n }\n default: {\n // @ts-expect-error This should never happen\n throw new Error(`Type \"${rest.type}\" not found in schema`)\n }\n }\n }\n\n if (typeNode.dereferencesTo) {\n const derefType = Object.assign(\n t.tsPropertySignature(\n INTERNAL_REFERENCE_SYMBOL,\n t.tsTypeAnnotation(t.tsLiteralType(t.stringLiteral(typeNode.dereferencesTo))),\n ),\n {computed: true, optional: true},\n )\n props.push(derefType)\n }\n\n return t.tsTypeLiteral(props)\n }\n\n // Helper function used to generate TS types for object properties.\n private generateTsObjectProperty(key: string, attribute: ObjectAttribute): t.TSPropertySignature {\n const type = this.generateTsType(attribute.value)\n const keyNode = isIdentifierName(key) ? t.identifier(key) : t.stringLiteral(key)\n const propertySignature = t.tsPropertySignature(keyNode, t.tsTypeAnnotation(type))\n propertySignature.optional = attribute.optional\n\n return propertySignature\n }\n\n private generateTsType(\n typeNode: DocumentSchemaType | TypeDeclarationSchemaType | TypeNode,\n ): t.TSType {\n switch (typeNode.type) {\n case 'array': {\n return this.generateArrayTsType(typeNode)\n }\n case 'boolean': {\n if (typeNode.value !== undefined) {\n return t.tsLiteralType(t.booleanLiteral(typeNode.value))\n }\n return t.tsBooleanKeyword()\n }\n case 'document': {\n return this.generateDocumentTsType(typeNode)\n }\n case 'inline': {\n return this.generateInlineTsType(typeNode)\n }\n case 'null': {\n return t.tsNullKeyword()\n }\n case 'number': {\n if (typeNode.value !== undefined) {\n return t.tsLiteralType(t.numericLiteral(typeNode.value))\n }\n return t.tsNumberKeyword()\n }\n case 'object': {\n return this.generateObjectTsType(typeNode)\n }\n case 'string': {\n if (typeNode.value !== undefined) {\n return t.tsLiteralType(t.stringLiteral(typeNode.value))\n }\n return t.tsStringKeyword()\n }\n case 'type': {\n return this.generateTsType(typeNode.value)\n }\n case 'union': {\n return this.generateUnionTsType(typeNode)\n }\n case 'unknown': {\n return t.tsUnknownKeyword()\n }\n\n default: {\n throw new Error(\n `Encountered unsupported node type \"${\n // @ts-expect-error This should never happen\n typeNode.type\n }\" while generating schema types`,\n )\n }\n }\n }\n\n // Helper function used to generate TS types for union type nodes.\n private generateUnionTsType(typeNode: UnionTypeNode): t.TSType {\n if (typeNode.of.length === 0) return t.tsNeverKeyword()\n if (typeNode.of.length === 1) return this.generateTsType(typeNode.of[0]!)\n return t.tsUnionType(typeNode.of.map((node) => this.generateTsType(node)))\n }\n}\n\nexport function walkAndCountQueryTypeNodeStats(typeNode: TypeNode): TypeEvaluationStats {\n switch (typeNode.type) {\n case 'array': {\n const acc = walkAndCountQueryTypeNodeStats(typeNode.of)\n acc.allTypes += 1 // count the array type itself\n return acc\n }\n case 'object': {\n // if the rest is unknown, we count it as one unknown type\n if (typeNode.rest && typeNode.rest.type === 'unknown') {\n return {allTypes: 2, emptyUnions: 0, unknownTypes: 1} // count the object type itself as well\n }\n\n const restStats = typeNode.rest\n ? walkAndCountQueryTypeNodeStats(typeNode.rest)\n : {allTypes: 0, emptyUnions: 0, unknownTypes: 0}\n\n // count the object type itself\n restStats.allTypes += 1\n\n const attrs = Object.values(typeNode.attributes)\n let acc = restStats\n for (const attribute of attrs) {\n const {allTypes, emptyUnions, unknownTypes} = walkAndCountQueryTypeNodeStats(\n attribute.value,\n )\n acc = {\n allTypes: acc.allTypes + allTypes,\n emptyUnions: acc.emptyUnions + emptyUnions,\n unknownTypes: acc.unknownTypes + unknownTypes,\n }\n }\n return acc\n }\n case 'union': {\n if (typeNode.of.length === 0) {\n return {allTypes: 1, emptyUnions: 1, unknownTypes: 0}\n }\n\n let acc = {allTypes: 1, emptyUnions: 0, unknownTypes: 0} // count the union type itself\n for (const type of typeNode.of) {\n const {allTypes, emptyUnions, unknownTypes} = walkAndCountQueryTypeNodeStats(type)\n acc = {\n allTypes: acc.allTypes + allTypes,\n emptyUnions: acc.emptyUnions + emptyUnions,\n unknownTypes: acc.unknownTypes + unknownTypes,\n }\n }\n return acc\n }\n case 'unknown': {\n return {allTypes: 1, emptyUnions: 0, unknownTypes: 1}\n }\n default: {\n return {allTypes: 1, emptyUnions: 0, unknownTypes: 0}\n }\n }\n}\n"],"names":["t","typeEvaluate","safeParseQuery","ARRAY_OF","INTERNAL_REFERENCE_SYMBOL","getFilterArrayUnionType","getUniqueIdentifierForName","isIdentifierName","weakMapMemo","SchemaTypeGenerator","schema","evaluateQuery","query","ast","typeNode","tsType","generateTsType","stats","walkAndCountQueryTypeNodeStats","identifiers","Map","tsTypes","uniqueTypeNames","Set","type","has","name","Error","add","currentIdentifierNames","values","map","id","uniqueIdentifier","set","getType","typeName","get","undefined","hasType","Symbol","iterator","typeNames","schemaType","generateArrayOfTsType","typeNodes","of","tsTypeReference","tsTypeParameterInstantiation","generateArrayTsType","identifier","every","unionTypeNode","unionMember","arrayOfNonInline","member","arrayOfInline","tsUnionType","generateDocumentTsType","document","props","Object","entries","attributes","key","node","generateTsObjectProperty","tsTypeLiteral","generateInlineTsType","addComment","tsUnknownKeyword","generateObjectTsType","attribute","push","rest","resolved","isTSUnknownKeyword","tsIntersectionType","dereferencesTo","derefType","assign","tsPropertySignature","tsTypeAnnotation","tsLiteralType","stringLiteral","computed","optional","value","keyNode","propertySignature","booleanLiteral","tsBooleanKeyword","tsNullKeyword","numericLiteral","tsNumberKeyword","tsStringKeyword","generateUnionTsType","length","tsNeverKeyword","acc","allTypes","emptyUnions","unknownTypes","restStats","attrs"],"mappings":"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"}
@@ -0,0 +1,240 @@
1
+ /* eslint-disable unicorn/consistent-function-scoping */ import process from 'node:process';
2
+ import * as t from '@babel/types';
3
+ import { createSelector } from 'reselect';
4
+ import { resultSuffix } from '../casing.js';
5
+ import { ALL_SANITY_SCHEMA_TYPES, ARRAY_OF, INTERNAL_REFERENCE_SYMBOL, SANITY_QUERIES } from './constants.js';
6
+ import { computeOnce, generateCode, getUniqueIdentifierForName, normalizePrintablePath } from './helpers.js';
7
+ import { SchemaTypeGenerator } from './schemaTypeGenerator.js';
8
+ import { QueryEvaluationError } from './types.js';
9
+ /**
10
+ * A class used to generate TypeScript types from a given schema
11
+ * @beta
12
+ */ export class TypeGenerator {
13
+ getSchemaTypeGenerator = createSelector([
14
+ (options)=>options.schema
15
+ ], (schema)=>new SchemaTypeGenerator(schema));
16
+ getSchemaTypeDeclarations = createSelector([
17
+ (options)=>options.root,
18
+ (options)=>options.schemaPath,
19
+ this.getSchemaTypeGenerator
20
+ ], (root = process.cwd(), schemaPath, schema)=>[
21
+ ...schema
22
+ ].map(({ id, name, tsType }, index)=>{
23
+ const typeAlias = t.tsTypeAliasDeclaration(id, null, tsType);
24
+ let ast = t.exportNamedDeclaration(typeAlias);
25
+ if (index === 0 && schemaPath) {
26
+ ast = t.addComments(ast, 'leading', [
27
+ {
28
+ type: 'CommentLine',
29
+ value: ` Source: ${normalizePrintablePath(root, schemaPath)}`
30
+ }
31
+ ]);
32
+ }
33
+ const code = generateCode(ast);
34
+ return {
35
+ ast,
36
+ code,
37
+ id,
38
+ name,
39
+ tsType
40
+ };
41
+ }));
42
+ getAllSanitySchemaTypesDeclaration = createSelector([
43
+ this.getSchemaTypeDeclarations
44
+ ], (schemaTypes)=>{
45
+ const ast = t.exportNamedDeclaration(t.tsTypeAliasDeclaration(ALL_SANITY_SCHEMA_TYPES, null, schemaTypes.length > 0 ? t.tsUnionType(schemaTypes.map(({ id })=>t.tsTypeReference(id))) : t.tsNeverKeyword()));
46
+ const code = generateCode(ast);
47
+ return {
48
+ ast,
49
+ code,
50
+ id: ALL_SANITY_SCHEMA_TYPES
51
+ };
52
+ });
53
+ getArrayOfDeclaration = computeOnce(()=>{
54
+ // Creates: type ArrayOf<T> = Array<T & { _key: string }>;
55
+ const typeParam = t.tsTypeParameter(null, null, 'T');
56
+ const intersectionType = t.tsIntersectionType([
57
+ t.tsTypeReference(t.identifier('T')),
58
+ t.tsTypeLiteral([
59
+ t.tsPropertySignature(t.identifier('_key'), t.tsTypeAnnotation(t.tsStringKeyword()))
60
+ ])
61
+ ]);
62
+ const arrayType = t.tsTypeReference(t.identifier('Array'), t.tsTypeParameterInstantiation([
63
+ intersectionType
64
+ ]));
65
+ const ast = t.tsTypeAliasDeclaration(ARRAY_OF, t.tsTypeParameterDeclaration([
66
+ typeParam
67
+ ]), arrayType);
68
+ const code = generateCode(ast);
69
+ return {
70
+ ast,
71
+ code,
72
+ id: ARRAY_OF
73
+ };
74
+ });
75
+ getInternalReferenceSymbolDeclaration = computeOnce(()=>{
76
+ const typeOperator = t.tsTypeOperator(t.tsSymbolKeyword(), 'unique');
77
+ const id = INTERNAL_REFERENCE_SYMBOL;
78
+ id.typeAnnotation = t.tsTypeAnnotation(typeOperator);
79
+ const declaration = t.variableDeclaration('const', [
80
+ t.variableDeclarator(id)
81
+ ]);
82
+ declaration.declare = true;
83
+ const ast = t.exportNamedDeclaration(declaration);
84
+ const code = generateCode(ast);
85
+ return {
86
+ ast,
87
+ code,
88
+ id
89
+ };
90
+ });
91
+ static async getEvaluatedModules({ queries: extractedModules, reporter: report, root = process.cwd(), schemaTypeDeclarations, schemaTypeGenerator }) {
92
+ if (!extractedModules) {
93
+ report?.stream.evaluatedModules.end();
94
+ return [];
95
+ }
96
+ const currentIdentifiers = new Set(schemaTypeDeclarations.map(({ id })=>id.name));
97
+ const evaluatedModuleResults = [];
98
+ for await (const { filename, ...extractedModule } of extractedModules){
99
+ const queries = [];
100
+ const errors = [
101
+ ...extractedModule.errors
102
+ ];
103
+ for (const extractedQuery of extractedModule.queries){
104
+ const { variable } = extractedQuery;
105
+ try {
106
+ const { stats, tsType } = schemaTypeGenerator.evaluateQuery(extractedQuery);
107
+ const id = getUniqueIdentifierForName(resultSuffix(variable.id.name), currentIdentifiers);
108
+ const typeAlias = t.tsTypeAliasDeclaration(id, null, tsType);
109
+ const trimmedQuery = extractedQuery.query.replaceAll(/(\r\n|\n|\r)/gm, '').trim();
110
+ const ast = t.addComments(t.exportNamedDeclaration(typeAlias), 'leading', [
111
+ {
112
+ type: 'CommentLine',
113
+ value: ` Source: ${normalizePrintablePath(root, filename)}`
114
+ },
115
+ {
116
+ type: 'CommentLine',
117
+ value: ` Variable: ${variable.id.name}`
118
+ },
119
+ {
120
+ type: 'CommentLine',
121
+ value: ` Query: ${trimmedQuery}`
122
+ }
123
+ ]);
124
+ const evaluatedQueryResult = {
125
+ ast,
126
+ code: generateCode(ast),
127
+ id,
128
+ stats,
129
+ tsType,
130
+ ...extractedQuery
131
+ };
132
+ currentIdentifiers.add(id.name);
133
+ queries.push(evaluatedQueryResult);
134
+ } catch (cause) {
135
+ errors.push(new QueryEvaluationError({
136
+ cause,
137
+ filename,
138
+ variable
139
+ }));
140
+ }
141
+ }
142
+ const evaluatedModule = {
143
+ errors,
144
+ filename,
145
+ queries
146
+ };
147
+ report?.stream.evaluatedModules.emit(evaluatedModule);
148
+ evaluatedModuleResults.push(evaluatedModule);
149
+ }
150
+ report?.stream.evaluatedModules.end();
151
+ return evaluatedModuleResults;
152
+ }
153
+ static async getQueryMapDeclaration({ evaluatedModules, overloadClientMethods = true }) {
154
+ if (!overloadClientMethods) return {
155
+ ast: t.program([]),
156
+ code: ''
157
+ };
158
+ const queries = evaluatedModules.flatMap((module)=>module.queries);
159
+ if (queries.length === 0) return {
160
+ ast: t.program([]),
161
+ code: ''
162
+ };
163
+ const typesByQuerystring = {};
164
+ for (const { id, query } of queries){
165
+ typesByQuerystring[query] ??= [];
166
+ typesByQuerystring[query].push(id.name);
167
+ }
168
+ const queryReturnInterface = t.tsInterfaceDeclaration(SANITY_QUERIES, null, [], t.tsInterfaceBody(Object.entries(typesByQuerystring).map(([query, types])=>{
169
+ return t.tsPropertySignature(t.stringLiteral(query), t.tsTypeAnnotation(types.length > 0 ? t.tsUnionType(types.map((type)=>t.tsTypeReference(t.identifier(type)))) : t.tsNeverKeyword()));
170
+ })));
171
+ const declareModule = t.declareModule(t.stringLiteral('@sanity/client'), t.blockStatement([
172
+ queryReturnInterface
173
+ ]));
174
+ const clientImport = t.addComments(t.importDeclaration([], t.stringLiteral('@sanity/client')), 'leading', [
175
+ {
176
+ type: 'CommentLine',
177
+ value: ' Query TypeMap'
178
+ }
179
+ ]);
180
+ const ast = t.program([
181
+ clientImport,
182
+ declareModule
183
+ ]);
184
+ const code = generateCode(ast);
185
+ return {
186
+ ast,
187
+ code
188
+ };
189
+ }
190
+ async generateTypes(options) {
191
+ const { reporter: report } = options;
192
+ const internalReferenceSymbol = this.getInternalReferenceSymbolDeclaration();
193
+ const arrayOfDeclaration = this.getArrayOfDeclaration();
194
+ const schemaTypeDeclarations = this.getSchemaTypeDeclarations(options);
195
+ const allSanitySchemaTypesDeclaration = this.getAllSanitySchemaTypesDeclaration(options);
196
+ report?.event.generatedSchemaTypes({
197
+ allSanitySchemaTypesDeclaration,
198
+ internalReferenceSymbol,
199
+ schemaTypeDeclarations
200
+ });
201
+ const program = t.program([]);
202
+ let code = '';
203
+ for (const declaration of schemaTypeDeclarations){
204
+ program.body.push(declaration.ast);
205
+ code += declaration.code;
206
+ }
207
+ program.body.push(allSanitySchemaTypesDeclaration.ast);
208
+ code += allSanitySchemaTypesDeclaration.code;
209
+ program.body.push(internalReferenceSymbol.ast);
210
+ code += internalReferenceSymbol.code;
211
+ program.body.push(arrayOfDeclaration.ast);
212
+ code += arrayOfDeclaration.code;
213
+ const evaluatedModules = await TypeGenerator.getEvaluatedModules({
214
+ ...options,
215
+ schemaTypeDeclarations,
216
+ schemaTypeGenerator: this.getSchemaTypeGenerator(options)
217
+ });
218
+ for (const { queries } of evaluatedModules){
219
+ for (const query of queries){
220
+ program.body.push(query.ast);
221
+ code += query.code;
222
+ }
223
+ }
224
+ const queryMapDeclaration = await TypeGenerator.getQueryMapDeclaration({
225
+ ...options,
226
+ evaluatedModules
227
+ });
228
+ program.body.push(...queryMapDeclaration.ast.body);
229
+ code += queryMapDeclaration.code;
230
+ report?.event.generatedQueryTypes({
231
+ queryMapDeclaration
232
+ });
233
+ return {
234
+ ast: program,
235
+ code
236
+ };
237
+ }
238
+ }
239
+
240
+ //# sourceMappingURL=typeGenerator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/typescript/typeGenerator.ts"],"sourcesContent":["/* eslint-disable unicorn/consistent-function-scoping */\nimport process from 'node:process'\n\nimport * as t from '@babel/types'\nimport {type WorkerChannel, type WorkerChannelReporter} from '@sanity/worker-channels'\nimport {type SchemaType} from 'groq-js'\nimport {createSelector} from 'reselect'\n\nimport {resultSuffix} from '../casing.js'\nimport {\n ALL_SANITY_SCHEMA_TYPES,\n ARRAY_OF,\n INTERNAL_REFERENCE_SYMBOL,\n SANITY_QUERIES,\n} from './constants.js'\nimport {\n computeOnce,\n generateCode,\n getUniqueIdentifierForName,\n normalizePrintablePath,\n} from './helpers.js'\nimport {SchemaTypeGenerator} from './schemaTypeGenerator.js'\nimport {\n type EvaluatedModule,\n type EvaluatedQuery,\n type ExtractedModule,\n QueryEvaluationError,\n type QueryExtractionError,\n} from './types.js'\n\nexport type TypegenWorkerChannel = WorkerChannel.Definition<{\n evaluatedModules: WorkerChannel.Stream<EvaluatedModule>\n generatedQueryTypes: WorkerChannel.Event<{\n queryMapDeclaration: {ast: t.Program; code: string}\n }>\n generatedSchemaTypes: WorkerChannel.Event<{\n allSanitySchemaTypesDeclaration: {\n ast: t.ExportNamedDeclaration\n code: string\n id: t.Identifier\n }\n internalReferenceSymbol: {\n ast: t.ExportNamedDeclaration\n code: string\n id: t.Identifier\n }\n schemaTypeDeclarations: {\n ast: t.ExportNamedDeclaration\n code: string\n id: t.Identifier\n name: string\n tsType: t.TSType\n }[]\n }>\n}>\n\nexport interface GenerateTypesOptions {\n schema: SchemaType\n\n overloadClientMethods?: boolean\n queries?: AsyncIterable<ExtractedModule>\n reporter?: WorkerChannelReporter<TypegenWorkerChannel>\n root?: string\n schemaPath?: string\n}\n\ntype GetEvaluatedModulesOptions = GenerateTypesOptions & {\n schemaTypeDeclarations: ReturnType<TypeGenerator['getSchemaTypeDeclarations']>\n schemaTypeGenerator: SchemaTypeGenerator\n}\ntype GetQueryMapDeclarationOptions = GenerateTypesOptions & {\n evaluatedModules: EvaluatedModule[]\n}\n\n/**\n * A class used to generate TypeScript types from a given schema\n * @beta\n */\nexport class TypeGenerator {\n private getSchemaTypeGenerator = createSelector(\n [(options: GenerateTypesOptions) => options.schema],\n\n (schema) => new SchemaTypeGenerator(schema),\n )\n\n private getSchemaTypeDeclarations = createSelector(\n [\n (options: GenerateTypesOptions) => options.root,\n (options: GenerateTypesOptions) => options.schemaPath,\n this.getSchemaTypeGenerator,\n ],\n\n (root = process.cwd(), schemaPath, schema) =>\n [...schema].map(({id, name, tsType}, index) => {\n const typeAlias = t.tsTypeAliasDeclaration(id, null, tsType)\n let ast = t.exportNamedDeclaration(typeAlias)\n\n if (index === 0 && schemaPath) {\n ast = t.addComments(ast, 'leading', [\n {type: 'CommentLine', value: ` Source: ${normalizePrintablePath(root, schemaPath)}`},\n ])\n }\n const code = generateCode(ast)\n return {ast, code, id, name, tsType}\n }),\n )\n\n private getAllSanitySchemaTypesDeclaration = createSelector(\n [this.getSchemaTypeDeclarations],\n (schemaTypes) => {\n const ast = t.exportNamedDeclaration(\n t.tsTypeAliasDeclaration(\n ALL_SANITY_SCHEMA_TYPES,\n null,\n schemaTypes.length > 0\n ? t.tsUnionType(schemaTypes.map(({id}) => t.tsTypeReference(id)))\n : t.tsNeverKeyword(),\n ),\n )\n const code = generateCode(ast)\n\n return {ast, code, id: ALL_SANITY_SCHEMA_TYPES}\n },\n )\n\n private getArrayOfDeclaration = computeOnce(() => {\n // Creates: type ArrayOf<T> = Array<T & { _key: string }>;\n const typeParam = t.tsTypeParameter(null, null, 'T')\n const intersectionType = t.tsIntersectionType([\n t.tsTypeReference(t.identifier('T')),\n t.tsTypeLiteral([\n t.tsPropertySignature(t.identifier('_key'), t.tsTypeAnnotation(t.tsStringKeyword())),\n ]),\n ])\n const arrayType = t.tsTypeReference(\n t.identifier('Array'),\n t.tsTypeParameterInstantiation([intersectionType]),\n )\n\n const ast = t.tsTypeAliasDeclaration(\n ARRAY_OF,\n t.tsTypeParameterDeclaration([typeParam]),\n arrayType,\n )\n const code = generateCode(ast)\n\n return {ast, code, id: ARRAY_OF}\n })\n\n private getInternalReferenceSymbolDeclaration = computeOnce(() => {\n const typeOperator = t.tsTypeOperator(t.tsSymbolKeyword(), 'unique')\n\n const id = INTERNAL_REFERENCE_SYMBOL\n id.typeAnnotation = t.tsTypeAnnotation(typeOperator)\n\n const declaration = t.variableDeclaration('const', [t.variableDeclarator(id)])\n declaration.declare = true\n const ast = t.exportNamedDeclaration(declaration)\n const code = generateCode(ast)\n\n return {ast, code, id}\n })\n\n private static async getEvaluatedModules({\n queries: extractedModules,\n reporter: report,\n root = process.cwd(),\n schemaTypeDeclarations,\n schemaTypeGenerator,\n }: GetEvaluatedModulesOptions) {\n if (!extractedModules) {\n report?.stream.evaluatedModules.end()\n return []\n }\n\n const currentIdentifiers = new Set<string>(schemaTypeDeclarations.map(({id}) => id.name))\n const evaluatedModuleResults: EvaluatedModule[] = []\n\n for await (const {filename, ...extractedModule} of extractedModules) {\n const queries: EvaluatedQuery[] = []\n const errors: (QueryEvaluationError | QueryExtractionError)[] = [...extractedModule.errors]\n\n for (const extractedQuery of extractedModule.queries) {\n const {variable} = extractedQuery\n try {\n const {stats, tsType} = schemaTypeGenerator.evaluateQuery(extractedQuery)\n const id = getUniqueIdentifierForName(resultSuffix(variable.id.name), currentIdentifiers)\n const typeAlias = t.tsTypeAliasDeclaration(id, null, tsType)\n const trimmedQuery = extractedQuery.query.replaceAll(/(\\r\\n|\\n|\\r)/gm, '').trim()\n const ast = t.addComments(t.exportNamedDeclaration(typeAlias), 'leading', [\n {type: 'CommentLine', value: ` Source: ${normalizePrintablePath(root, filename)}`},\n {type: 'CommentLine', value: ` Variable: ${variable.id.name}`},\n {type: 'CommentLine', value: ` Query: ${trimmedQuery}`},\n ])\n\n const evaluatedQueryResult: EvaluatedQuery = {\n ast,\n code: generateCode(ast),\n id,\n stats,\n tsType,\n ...extractedQuery,\n }\n\n currentIdentifiers.add(id.name)\n queries.push(evaluatedQueryResult)\n } catch (cause) {\n errors.push(new QueryEvaluationError({cause, filename, variable}))\n }\n }\n\n const evaluatedModule: EvaluatedModule = {\n errors,\n filename,\n queries,\n }\n report?.stream.evaluatedModules.emit(evaluatedModule)\n evaluatedModuleResults.push(evaluatedModule)\n }\n report?.stream.evaluatedModules.end()\n\n return evaluatedModuleResults\n }\n\n private static async getQueryMapDeclaration({\n evaluatedModules,\n overloadClientMethods = true,\n }: GetQueryMapDeclarationOptions) {\n if (!overloadClientMethods) return {ast: t.program([]), code: ''}\n\n const queries = evaluatedModules.flatMap((module) => module.queries)\n if (queries.length === 0) return {ast: t.program([]), code: ''}\n\n const typesByQuerystring: {[query: string]: string[]} = {}\n for (const {id, query} of queries) {\n typesByQuerystring[query] ??= []\n typesByQuerystring[query].push(id.name)\n }\n\n const queryReturnInterface = t.tsInterfaceDeclaration(\n SANITY_QUERIES,\n null,\n [],\n t.tsInterfaceBody(\n Object.entries(typesByQuerystring).map(([query, types]) => {\n return t.tsPropertySignature(\n t.stringLiteral(query),\n t.tsTypeAnnotation(\n types.length > 0\n ? t.tsUnionType(types.map((type) => t.tsTypeReference(t.identifier(type))))\n : t.tsNeverKeyword(),\n ),\n )\n }),\n ),\n )\n\n const declareModule = t.declareModule(\n t.stringLiteral('@sanity/client'),\n t.blockStatement([queryReturnInterface]),\n )\n\n const clientImport = t.addComments(\n t.importDeclaration([], t.stringLiteral('@sanity/client')),\n 'leading',\n [{type: 'CommentLine', value: ' Query TypeMap'}],\n )\n\n const ast = t.program([clientImport, declareModule])\n const code = generateCode(ast)\n return {ast, code}\n }\n\n async generateTypes(options: GenerateTypesOptions) {\n const {reporter: report} = options\n const internalReferenceSymbol = this.getInternalReferenceSymbolDeclaration()\n const arrayOfDeclaration = this.getArrayOfDeclaration()\n const schemaTypeDeclarations = this.getSchemaTypeDeclarations(options)\n const allSanitySchemaTypesDeclaration = this.getAllSanitySchemaTypesDeclaration(options)\n\n report?.event.generatedSchemaTypes({\n allSanitySchemaTypesDeclaration,\n internalReferenceSymbol,\n schemaTypeDeclarations,\n })\n\n const program = t.program([])\n let code = ''\n\n for (const declaration of schemaTypeDeclarations) {\n program.body.push(declaration.ast)\n code += declaration.code\n }\n\n program.body.push(allSanitySchemaTypesDeclaration.ast)\n code += allSanitySchemaTypesDeclaration.code\n\n program.body.push(internalReferenceSymbol.ast)\n code += internalReferenceSymbol.code\n\n program.body.push(arrayOfDeclaration.ast)\n code += arrayOfDeclaration.code\n\n const evaluatedModules = await TypeGenerator.getEvaluatedModules({\n ...options,\n schemaTypeDeclarations,\n schemaTypeGenerator: this.getSchemaTypeGenerator(options),\n })\n for (const {queries} of evaluatedModules) {\n for (const query of queries) {\n program.body.push(query.ast)\n code += query.code\n }\n }\n\n const queryMapDeclaration = await TypeGenerator.getQueryMapDeclaration({\n ...options,\n evaluatedModules,\n })\n program.body.push(...queryMapDeclaration.ast.body)\n code += queryMapDeclaration.code\n\n report?.event.generatedQueryTypes({queryMapDeclaration})\n\n return {ast: program, code}\n }\n}\n"],"names":["process","t","createSelector","resultSuffix","ALL_SANITY_SCHEMA_TYPES","ARRAY_OF","INTERNAL_REFERENCE_SYMBOL","SANITY_QUERIES","computeOnce","generateCode","getUniqueIdentifierForName","normalizePrintablePath","SchemaTypeGenerator","QueryEvaluationError","TypeGenerator","getSchemaTypeGenerator","options","schema","getSchemaTypeDeclarations","root","schemaPath","cwd","map","id","name","tsType","index","typeAlias","tsTypeAliasDeclaration","ast","exportNamedDeclaration","addComments","type","value","code","getAllSanitySchemaTypesDeclaration","schemaTypes","length","tsUnionType","tsTypeReference","tsNeverKeyword","getArrayOfDeclaration","typeParam","tsTypeParameter","intersectionType","tsIntersectionType","identifier","tsTypeLiteral","tsPropertySignature","tsTypeAnnotation","tsStringKeyword","arrayType","tsTypeParameterInstantiation","tsTypeParameterDeclaration","getInternalReferenceSymbolDeclaration","typeOperator","tsTypeOperator","tsSymbolKeyword","typeAnnotation","declaration","variableDeclaration","variableDeclarator","declare","getEvaluatedModules","queries","extractedModules","reporter","report","schemaTypeDeclarations","schemaTypeGenerator","stream","evaluatedModules","end","currentIdentifiers","Set","evaluatedModuleResults","filename","extractedModule","errors","extractedQuery","variable","stats","evaluateQuery","trimmedQuery","query","replaceAll","trim","evaluatedQueryResult","add","push","cause","evaluatedModule","emit","getQueryMapDeclaration","overloadClientMethods","program","flatMap","module","typesByQuerystring","queryReturnInterface","tsInterfaceDeclaration","tsInterfaceBody","Object","entries","types","stringLiteral","declareModule","blockStatement","clientImport","importDeclaration","generateTypes","internalReferenceSymbol","arrayOfDeclaration","allSanitySchemaTypesDeclaration","event","generatedSchemaTypes","body","queryMapDeclaration","generatedQueryTypes"],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ const isRecord = (value)=>(typeof value === 'object' || typeof value === 'function') && !!value;
2
+ /**
3
+ * An error that occurred during query extraction.
4
+ * @public
5
+ */ export class QueryExtractionError extends Error {
6
+ filename;
7
+ variable;
8
+ constructor({ cause, filename, variable }){
9
+ super(`Error while extracting query ${variable ? `from variable '${variable.id.name}' ` : ''}in ${filename}: ${isRecord(cause) && typeof cause.message === 'string' ? cause.message : 'Unknown error'}`);
10
+ this.name = 'QueryExtractionError';
11
+ this.cause = cause;
12
+ this.variable = variable;
13
+ this.filename = filename;
14
+ }
15
+ }
16
+ /**
17
+ * An error that occurred during query evaluation.
18
+ * @public
19
+ */ export class QueryEvaluationError extends Error {
20
+ filename;
21
+ variable;
22
+ constructor({ cause, filename, variable }){
23
+ super(`Error while evaluating query ${variable ? `from variable '${variable.id.name}' ` : ''}in ${filename}: ${isRecord(cause) && typeof cause.message === 'string' ? cause.message : 'Unknown error'}`);
24
+ this.name = 'QueryEvaluationError';
25
+ this.cause = cause;
26
+ this.variable = variable;
27
+ this.filename = filename;
28
+ }
29
+ }
30
+
31
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/typescript/types.ts"],"sourcesContent":["import type * as t from '@babel/types'\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n (typeof value === 'object' || typeof value === 'function') && !!value\n\n/**\n * Statistics from the query type evaluation process.\n * @public\n */\nexport interface TypeEvaluationStats {\n allTypes: number\n emptyUnions: number\n unknownTypes: number\n}\n\ninterface QueryVariable {\n id: t.Identifier\n\n end?: number\n start?: number\n}\n\n/**\n * A GROQ query extracted from a source file.\n * @public\n */\nexport interface ExtractedQuery {\n filename: string\n query: string\n variable: QueryVariable\n}\n\n/**\n * A module (file) containing extracted GROQ queries.\n * @public\n */\nexport interface ExtractedModule {\n errors: QueryExtractionError[]\n filename: string\n queries: ExtractedQuery[]\n}\n\n/**\n * An `ExtractedQuery` that has been evaluated against a schema, yielding a TypeScript type.\n * @public\n */\nexport interface EvaluatedQuery extends ExtractedQuery {\n ast: t.ExportNamedDeclaration\n code: string\n id: t.Identifier\n stats: TypeEvaluationStats\n tsType: t.TSType\n}\n\n/**\n * A module containing queries that have been evaluated.\n * @public\n */\nexport interface EvaluatedModule {\n errors: (QueryEvaluationError | QueryExtractionError)[]\n filename: string\n queries: EvaluatedQuery[]\n}\n\ninterface QueryExtractionErrorOptions {\n cause: unknown\n filename: string\n\n variable?: QueryVariable\n}\n\n/**\n * An error that occurred during query extraction.\n * @public\n */\nexport class QueryExtractionError extends Error {\n filename: string\n variable?: QueryVariable\n constructor({cause, filename, variable}: QueryExtractionErrorOptions) {\n super(\n `Error while extracting query ${variable ? `from variable '${variable.id.name}' ` : ''}in ${filename}: ${\n isRecord(cause) && typeof cause.message === 'string' ? cause.message : 'Unknown error'\n }`,\n )\n this.name = 'QueryExtractionError'\n this.cause = cause\n this.variable = variable\n this.filename = filename\n }\n}\n\ninterface QueryEvaluationErrorOptions {\n cause: unknown\n filename: string\n\n variable?: QueryVariable\n}\n\n/**\n * An error that occurred during query evaluation.\n * @public\n */\nexport class QueryEvaluationError extends Error {\n filename: string\n variable?: QueryVariable\n constructor({cause, filename, variable}: QueryEvaluationErrorOptions) {\n super(\n `Error while evaluating query ${variable ? `from variable '${variable.id.name}' ` : ''}in ${filename}: ${\n isRecord(cause) && typeof cause.message === 'string' ? cause.message : 'Unknown error'\n }`,\n )\n this.name = 'QueryEvaluationError'\n this.cause = cause\n this.variable = variable\n this.filename = filename\n }\n}\n"],"names":["isRecord","value","QueryExtractionError","Error","filename","variable","cause","id","name","message","QueryEvaluationError"],"mappings":"AAEA,MAAMA,WAAW,CAACC,QAChB,AAAC,CAAA,OAAOA,UAAU,YAAY,OAAOA,UAAU,UAAS,KAAM,CAAC,CAACA;AAoElE;;;CAGC,GACD,OAAO,MAAMC,6BAA6BC;IACxCC,SAAgB;IAChBC,SAAwB;IACxB,YAAY,EAACC,KAAK,EAAEF,QAAQ,EAAEC,QAAQ,EAA8B,CAAE;QACpE,KAAK,CACH,CAAC,6BAA6B,EAAEA,WAAW,CAAC,eAAe,EAAEA,SAASE,EAAE,CAACC,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,GAAG,EAAEJ,SAAS,EAAE,EACrGJ,SAASM,UAAU,OAAOA,MAAMG,OAAO,KAAK,WAAWH,MAAMG,OAAO,GAAG,iBACvE;QAEJ,IAAI,CAACD,IAAI,GAAG;QACZ,IAAI,CAACF,KAAK,GAAGA;QACb,IAAI,CAACD,QAAQ,GAAGA;QAChB,IAAI,CAACD,QAAQ,GAAGA;IAClB;AACF;AASA;;;CAGC,GACD,OAAO,MAAMM,6BAA6BP;IACxCC,SAAgB;IAChBC,SAAwB;IACxB,YAAY,EAACC,KAAK,EAAEF,QAAQ,EAAEC,QAAQ,EAA8B,CAAE;QACpE,KAAK,CACH,CAAC,6BAA6B,EAAEA,WAAW,CAAC,eAAe,EAAEA,SAASE,EAAE,CAACC,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,GAAG,EAAEJ,SAAS,EAAE,EACrGJ,SAASM,UAAU,OAAOA,MAAMG,OAAO,KAAK,WAAWH,MAAMG,OAAO,GAAG,iBACvE;QAEJ,IAAI,CAACD,IAAI,GAAG;QACZ,IAAI,CAACF,KAAK,GAAGA;QACb,IAAI,CAACD,QAAQ,GAAGA;QAChB,IAAI,CAACD,QAAQ,GAAGA;IAClB;AACF"}
@@ -0,0 +1,6 @@
1
+ export const count = (amount, plural = '', singular = plural.slice(0, Math.max(0, plural.length - 1)))=>[
2
+ amount.toLocaleString('en-US'),
3
+ amount === 1 ? singular : plural
4
+ ].filter(Boolean).join(' ');
5
+
6
+ //# sourceMappingURL=count.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/count.ts"],"sourcesContent":["export const count = (\n amount: number,\n plural: string = '',\n singular: string = plural.slice(0, Math.max(0, plural.length - 1)),\n): string =>\n [amount.toLocaleString('en-US'), amount === 1 ? singular : plural].filter(Boolean).join(' ')\n"],"names":["count","amount","plural","singular","slice","Math","max","length","toLocaleString","filter","Boolean","join"],"mappings":"AAAA,OAAO,MAAMA,QAAQ,CACnBC,QACAC,SAAiB,EAAE,EACnBC,WAAmBD,OAAOE,KAAK,CAAC,GAAGC,KAAKC,GAAG,CAAC,GAAGJ,OAAOK,MAAM,GAAG,GAAG,GAElE;QAACN,OAAOO,cAAc,CAAC;QAAUP,WAAW,IAAIE,WAAWD;KAAO,CAACO,MAAM,CAACC,SAASC,IAAI,CAAC,KAAI"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Formats a path so it is the same in Windows and Unix
3
+ * @param path - The path to format
4
+ */ export function formatPath(path) {
5
+ return path.replaceAll('\\', '/');
6
+ }
7
+
8
+ //# sourceMappingURL=formatPath.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/formatPath.ts"],"sourcesContent":["/**\n * Formats a path so it is the same in Windows and Unix\n * @param path - The path to format\n */\nexport function formatPath(path: string): string {\n return path.replaceAll('\\\\', '/')\n}\n"],"names":["formatPath","path","replaceAll"],"mappings":"AAAA;;;CAGC,GACD,OAAO,SAASA,WAAWC,IAAY;IACrC,OAAOA,KAAKC,UAAU,CAAC,MAAM;AAC/B"}
@@ -0,0 +1,3 @@
1
+ export const getMessage = (error)=>typeof error === 'object' && !!error && 'message' in error && typeof error.message === 'string' ? error.message : 'Unknown error';
2
+
3
+ //# sourceMappingURL=getMessage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/getMessage.ts"],"sourcesContent":["export const getMessage = (error: unknown) =>\n typeof error === 'object' && !!error && 'message' in error && typeof error.message === 'string'\n ? error.message\n : 'Unknown error'\n"],"names":["getMessage","error","message"],"mappings":"AAAA,OAAO,MAAMA,aAAa,CAACC,QACzB,OAAOA,UAAU,YAAY,CAAC,CAACA,SAAS,aAAaA,SAAS,OAAOA,MAAMC,OAAO,KAAK,WACnFD,MAAMC,OAAO,GACb,gBAAe"}
@@ -0,0 +1,8 @@
1
+ const formatter = new Intl.NumberFormat('en-US', {
2
+ maximumFractionDigits: 1,
3
+ minimumFractionDigits: 1,
4
+ style: 'percent'
5
+ });
6
+ export const percent = (value)=>formatter.format(Math.min(value, 1));
7
+
8
+ //# sourceMappingURL=percent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/percent.ts"],"sourcesContent":["const formatter = new Intl.NumberFormat('en-US', {\n maximumFractionDigits: 1,\n minimumFractionDigits: 1,\n style: 'percent',\n})\n\nexport const percent = (value: number): string => formatter.format(Math.min(value, 1))\n"],"names":["formatter","Intl","NumberFormat","maximumFractionDigits","minimumFractionDigits","style","percent","value","format","Math","min"],"mappings":"AAAA,MAAMA,YAAY,IAAIC,KAAKC,YAAY,CAAC,SAAS;IAC/CC,uBAAuB;IACvBC,uBAAuB;IACvBC,OAAO;AACT;AAEA,OAAO,MAAMC,UAAU,CAACC,QAA0BP,UAAUQ,MAAM,CAACC,KAAKC,GAAG,CAACH,OAAO,IAAG"}
@@ -0,0 +1,39 @@
1
+ {
2
+ "commands": {
3
+ "typegen:generate": {
4
+ "aliases": [],
5
+ "args": {},
6
+ "description": "Sanity TypeGen (Beta)\nThis command is currently in beta and may undergo significant changes. Feedback is welcome!\n\nConfiguration:\nThis command can utilize configuration settings defined in a `sanity-typegen.json` file. These settings include:\n\n- \"path\": Specifies a glob pattern to locate your TypeScript or JavaScript files.\n Default: \"./src/**/*.{ts,tsx,js,jsx}\"\n\n- \"schema\": Defines the path to your Sanity schema file. This file should be generated using the `sanity schema extract` command.\n Default: \"schema.json\"\n\n- \"generates\": Indicates the path where the generated TypeScript type definitions will be saved.\n Default: \"./sanity.types.ts\"\n\nThe default configuration values listed above are used if not overridden in your `sanity-typegen.json` configuration file. To customize the behavior of the type generation, adjust these properties in the configuration file according to your project's needs.\n\nNote:\n- The `sanity schema extract` command is a prerequisite for extracting your Sanity Studio schema into a `schema.json` file, which is then used by the `sanity typegen generate` command to generate type definitions.\n- While this tool is in beta, we encourage you to experiment with these configurations and provide feedback to help improve its functionality and usability.",
7
+ "examples": [
8
+ {
9
+ "command": "<%= config.bin %> <%= command.id %>",
10
+ "description": "Generate TypeScript type definitions from a Sanity Studio schema extracted using the `sanity schema extract` command."
11
+ }
12
+ ],
13
+ "flags": {
14
+ "config-path": {
15
+ "description": "[Default: sanity-typegen.json] Specifies the path to the typegen configuration file. This file should be a JSON file that contains settings for the type generation process.",
16
+ "name": "config-path",
17
+ "hasDynamicHelp": false,
18
+ "multiple": false,
19
+ "type": "option"
20
+ }
21
+ },
22
+ "hasDynamicHelp": false,
23
+ "hiddenAliases": [],
24
+ "id": "typegen:generate",
25
+ "pluginAlias": "@sanity/codegen",
26
+ "pluginName": "@sanity/codegen",
27
+ "pluginType": "core",
28
+ "strict": true,
29
+ "isESM": true,
30
+ "relativePath": [
31
+ "dist",
32
+ "commands",
33
+ "typegen",
34
+ "generate.js"
35
+ ]
36
+ }
37
+ },
38
+ "version": "5.7.0"
39
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/codegen",
3
- "version": "5.7.0-next.8+18ba86acbc",
3
+ "version": "5.7.0",
4
4
  "description": "Codegen toolkit for Sanity.io",
5
5
  "keywords": [
6
6
  "sanity",
@@ -12,25 +12,32 @@
12
12
  ],
13
13
  "homepage": "https://www.sanity.io/",
14
14
  "bugs": {
15
- "url": "https://github.com/sanity-io/sanity/issues"
15
+ "url": "https://github.com/sanity-io/codegen/issues"
16
16
  },
17
17
  "repository": {
18
18
  "type": "git",
19
- "url": "git+https://github.com/sanity-io/sanity.git",
20
- "directory": "packages/@sanity/codegen"
19
+ "url": "git+https://github.com/sanity-io/codegen.git"
21
20
  },
22
21
  "license": "MIT",
23
22
  "author": "Sanity.io <hello@sanity.io>",
24
23
  "sideEffects": false,
25
24
  "type": "module",
26
25
  "exports": {
27
- ".": "./lib/index.js",
26
+ ".": {
27
+ "source": "./src/_exports/index.ts",
28
+ "default": "./dist/index.js"
29
+ },
28
30
  "./package.json": "./package.json"
29
31
  },
30
- "main": "./lib/index.cjs",
31
- "types": "./lib/index.d.ts",
32
+ "main": "./dist/index.cjs",
33
+ "types": "./dist/index.d.ts",
34
+ "bin": {
35
+ "sanity-typegen": "./bin/run.js"
36
+ },
32
37
  "files": [
33
- "lib",
38
+ "dist",
39
+ "bin",
40
+ "oclif.manifest.json",
34
41
  "babel.config.json"
35
42
  ],
36
43
  "dependencies": {
@@ -42,42 +49,61 @@
42
49
  "@babel/register": "^7.28.6",
43
50
  "@babel/traverse": "^7.28.6",
44
51
  "@babel/types": "^7.28.6",
52
+ "@oclif/core": "^4.8.0",
53
+ "@oclif/plugin-help": "^6.2.36",
54
+ "@sanity/cli-core": "^0.1.0-alpha.8",
45
55
  "@sanity/worker-channels": "^1.1.0",
46
56
  "debug": "^4.4.3",
47
57
  "globby": "^11.1.0",
58
+ "groq": "^5.2.0",
48
59
  "groq-js": "^1.25.0",
49
60
  "json5": "^2.2.3",
61
+ "prettier": "^3.7.4",
50
62
  "reselect": "^5.1.1",
51
63
  "tsconfig-paths": "^4.2.0",
52
- "zod": "^3.25.76",
53
- "groq": "5.7.0-next.8+18ba86acbc"
64
+ "zod": "^3.25.76"
54
65
  },
55
66
  "devDependencies": {
56
- "@sanity/pkg-utils": "^10.3.3",
67
+ "@eslint/compat": "^2.0.1",
68
+ "@microsoft/api-extractor": "^7.55.2",
69
+ "@oclif/test": "^4.1.15",
70
+ "@sanity/cli-test": "^0.0.2-alpha.7",
71
+ "@sanity/eslint-config-cli": "0.0.0-alpha.1",
72
+ "@swc/cli": "^0.7.9",
73
+ "@swc/core": "^1.15.8",
57
74
  "@types/babel__core": "^7.20.5",
58
75
  "@types/babel__generator": "^7.27.0",
59
76
  "@types/babel__register": "^7.17.3",
60
77
  "@types/babel__traverse": "^7.28.0",
61
78
  "@types/debug": "^4.1.12",
62
- "@types/node": "^24.3.0",
63
- "@typescript/native-preview": "7.0.0-dev.20260112.1",
79
+ "@types/node": "^20.19.28",
80
+ "@vitest/coverage-istanbul": "^4.0.17",
81
+ "chokidar": "^5.0.0",
64
82
  "eslint": "^9.39.2",
83
+ "husky": "^9.1.7",
84
+ "lint-staged": "^16.2.7",
85
+ "oclif": "^4.22.65",
86
+ "prettier-plugin-packagejson": "^2.5.20",
65
87
  "rimraf": "^5.0.10",
66
- "vitest": "^4.0.16",
67
- "@repo/eslint-config": "5.7.0-next.8+18ba86acbc",
68
- "@repo/test-config": "5.7.0-next.8+18ba86acbc",
69
- "@repo/tsconfig": "5.7.0-next.8+18ba86acbc",
70
- "@repo/package.config": "5.7.0-next.8+18ba86acbc"
88
+ "tinyglobby": "^0.2.15",
89
+ "typescript": "^5.9.3",
90
+ "vitest": "^4.0.17"
71
91
  },
72
92
  "engines": {
73
93
  "node": ">=20.19 <22 || >=22.12"
74
94
  },
95
+ "publishConfig": {
96
+ "access": "public"
97
+ },
75
98
  "scripts": {
76
- "build": "pkg-utils build --strict --check --clean",
77
- "check:types": "(cd ../../.. && tsgo --project packages/@sanity/codegen/tsconfig.lib.json --erasableSyntaxOnly)",
78
- "clean": "rimraf lib coverage",
79
- "lint": "eslint .",
99
+ "build": "swc --delete-dir-on-start src -d dist --strip-leading-paths --ignore '**/__tests__/**' && pnpm run build:types",
100
+ "postbuild": "oclif manifest",
101
+ "build:api": "api-extractor run --local",
102
+ "build:types": "tsc --project tsconfig.lib.json && pnpm run build:api && rimraf dist/__tmp__",
103
+ "clean": "rimraf dist coverage",
104
+ "lint": "eslint . --fix",
105
+ "pretest": "pnpm build",
80
106
  "test": "vitest",
81
- "watch": "pkg-utils watch"
107
+ "watch": "swc src -d dist --strip-leading-paths --watch"
82
108
  }
83
109
  }