@sanity/cli 3.88.1-typegen-experimental.0 → 3.88.1

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.
@@ -1,154 +1,43 @@
1
- declare interface QueryProgress {
2
- queriesCount: number
3
- projectionsCount: number
4
- filesCount: number
5
- }
6
-
7
1
  export declare interface TypegenGenerateTypesWorkerData {
8
2
  workDir: string
9
- schemas: {
10
- schemaPath: string
11
- schemaId: string
12
- }[]
3
+ workspaceName?: string
4
+ schemaPath: string
13
5
  searchPath: string | string[]
14
- overloadClientMethods: boolean
15
- augmentGroqModule: boolean
6
+ overloadClientMethods?: boolean
16
7
  }
17
8
 
18
- /** @internal */
19
- export declare type TypegenWorkerChannel = WorkerChannel<{
20
- loadedSchemas: WorkerChannelEvent
21
- generatedSchemaDeclarations: WorkerChannelEvent<{
22
- code: string
23
- schemaStats: {
24
- schemaTypesCount: number
25
- schemaCount: number
9
+ export declare type TypegenGenerateTypesWorkerMessage =
10
+ | {
11
+ type: 'error'
12
+ error: Error
13
+ fatal: boolean
14
+ query?: string
15
+ filename?: string
26
16
  }
27
- }>
28
- fileCount: WorkerChannelEvent<{
29
- fileCount: number
30
- }>
31
- generatedQueryResultDeclaration: WorkerChannelStream<
32
- | {
33
- type: 'progress'
34
- progress: QueryProgress
35
- }
36
- | {
37
- type: 'declaration'
38
- code: string
39
- progress: QueryProgress
40
- }
41
- | {
42
- type: 'error'
43
- message: string
44
- progress: QueryProgress
45
- }
46
- >
47
- generationComplete: WorkerChannelEvent<{
48
- augmentedQueryResultDeclarations: {
49
- code: string
17
+ | {
18
+ type: 'types'
19
+ filename: string
20
+ types: {
21
+ queryName: string
22
+ query: string
23
+ type: string
24
+ unknownTypeNodesGenerated: number
25
+ typeNodesGenerated: number
26
+ emptyUnionTypeNodesGenerated: number
27
+ }[]
50
28
  }
51
- queryStats: {
52
- queriesCount: number
53
- projectionsCount: number
54
- totalScannedFilesCount: number
55
- queryFilesCount: number
56
- projectionFilesCount: number
57
- filesWithErrors: number
58
- errorCount: number
59
- typeNodesGenerated: number
60
- unknownTypeNodesGenerated: number
61
- unknownTypeNodesRatio: number
62
- emptyUnionTypeNodesGenerated: number
29
+ | {
30
+ type: 'schema'
31
+ filename: string
32
+ schema: string
33
+ length: number
34
+ }
35
+ | {
36
+ type: 'typemap'
37
+ typeMap: string
38
+ }
39
+ | {
40
+ type: 'complete'
63
41
  }
64
- }>
65
- }>
66
-
67
- /**
68
- * Represents the definition of a "worker channel" to report progress from the
69
- * worker to the parent. Worker channels can define named events or streams and
70
- * the worker will report events and streams while the parent will await them.
71
- * This allows the control flow of the parent to follow the control flow of the
72
- * worker 1-to-1.
73
- *
74
- * @example
75
- *
76
- * ```ts
77
- * // Define the channel interface (shared between parent and worker)
78
- * type MyWorkerChannel = WorkerChannel<{
79
- * compileStart: WorkerChannelEvent<void>
80
- * compileProgress: WorkerChannelStream<{ file: string; progress: number }>
81
- * compileEnd: WorkerChannelEvent<{ duration: number }>
82
- * }>;
83
- *
84
- * // --- In the worker file (e.g., worker.ts) ---
85
- * import { parentPort } from 'node:worker_threads';
86
- * import { createReporter } from './workerChannels';
87
- *
88
- * const report = createReporter<MyWorkerChannel>(parentPort);
89
- *
90
- * async function runCompilation() {
91
- * report.event.compileStart(); // Signal start
92
- *
93
- * const files = ['a.js', 'b.js', 'c.js'];
94
- * for (const file of files) {
95
- * // Simulate work and report progress
96
- * await new Promise(resolve => setTimeout(resolve, 100));
97
- * report.stream.compileProgress.emit({ file, progress: 100 });
98
- * }
99
- * report.stream.compileProgress.end(); // Signal end of progress stream
100
- *
101
- * report.event.compileEnd({ duration: 300 }); // Signal end with result
102
- * }
103
- *
104
- * runCompilation();
105
- *
106
- * // --- In the parent file (e.g., main.ts) ---
107
- * import { Worker } from 'node:worker_threads';
108
- * import { createReceiver } from './workerChannels';
109
- *
110
- * const worker = new Worker('./worker.js');
111
- * const receiver = createReceiver<MyWorkerChannel>(worker);
112
- *
113
- * async function monitorCompilation() {
114
- * console.log('Waiting for compilation to start...');
115
- * await receiver.event.compileStart();
116
- * console.log('Compilation started.');
117
- *
118
- * console.log('Receiving progress:');
119
- * for await (const progress of receiver.stream.compileProgress()) {
120
- * console.log(` - ${progress.file}: ${progress.progress}%`);
121
- * }
122
- *
123
- * console.log('Waiting for compilation to end...');
124
- * const { duration } = await receiver.event.compileEnd();
125
- * console.log(`Compilation finished in ${duration}ms.`);
126
- *
127
- * await receiver.dispose(); // Clean up listeners and terminate worker
128
- * }
129
- *
130
- * monitorCompilation();
131
- * ```
132
- *
133
- * @internal
134
- */
135
- declare type WorkerChannel<
136
- TWorkerChannel extends Record<
137
- string,
138
- WorkerChannelEvent<unknown> | WorkerChannelStream<unknown>
139
- > = Record<string, WorkerChannelEvent<unknown> | WorkerChannelStream<unknown>>,
140
- > = TWorkerChannel
141
-
142
- /** @internal */
143
- declare type WorkerChannelEvent<TPayload = void> = {
144
- type: 'event'
145
- payload: TPayload
146
- }
147
-
148
- /** @internal */
149
- declare type WorkerChannelStream<TPayload = void> = {
150
- type: 'stream'
151
- payload: TPayload
152
- }
153
42
 
154
43
  export {}
@@ -1,95 +1,124 @@
1
1
  "use strict";
2
- var fs = require("node:fs/promises"), node_worker_threads = require("node:worker_threads"), codegen = require("@sanity/codegen"), workerChannel = require("../_chunks-cjs/workerChannel.js");
3
- const DEFAULT_SCHEMA_PATH = codegen.DEFAULT_CONFIG.schemas[0].schemaPath;
2
+ var node_worker_threads = require("node:worker_threads"), codegen = require("@sanity/codegen"), createDebug = require("debug"), groqJs = require("groq-js");
3
+ function _interopDefaultCompat(e) {
4
+ return e && typeof e == "object" && "default" in e ? e : { default: e };
5
+ }
6
+ var createDebug__default = /* @__PURE__ */ _interopDefaultCompat(createDebug);
7
+ const $info = createDebug__default.default("sanity:codegen:generate:info");
8
+ createDebug__default.default("sanity:codegen:generate:warn");
4
9
  if (node_worker_threads.isMainThread || !node_worker_threads.parentPort)
5
10
  throw new Error("This module must be run as a worker thread");
6
- const report = workerChannel.createReporter(node_worker_threads.parentPort), opts = node_worker_threads.workerData;
11
+ const opts = node_worker_threads.workerData;
12
+ codegen.registerBabel();
7
13
  async function main() {
8
- const schemas = [];
9
- for (const { schemaId, schemaPath } of opts.schemas)
10
- try {
11
- if (!(await fs.stat(schemaPath)).isFile())
12
- throw new Error(
13
- `Failed to load schema "${schemaId}". Schema path is not a file: ${schemaPath}`
14
- );
15
- const schema = await codegen.readSchema(schemaPath);
16
- schemas.push({ schema, schemaId, filename: schemaPath });
17
- } catch (err) {
18
- if (err.code === "ENOENT") {
19
- const hint = schemaPath === DEFAULT_SCHEMA_PATH ? ' - did you run "sanity schema extract"?' : "";
20
- throw new Error(`Schema file not found for schema "${schemaId}": ${schemaPath}${hint}`);
21
- } else
22
- throw err;
23
- }
24
- report.event.loadedSchemas();
25
- const generator = new codegen.TypeGenerator({
26
- schemas,
27
- queriesByFile: codegen.findQueriesInPath({ path: opts.searchPath, resolver: codegen.getResolver() }),
28
- augmentGroqModule: opts.augmentGroqModule,
29
- overloadClientMethods: opts.overloadClientMethods
14
+ const schema = await codegen.readSchema(opts.schemaPath), typeGenerator = new codegen.TypeGenerator(schema), schemaTypes = [typeGenerator.generateSchemaTypes(), codegen.TypeGenerator.generateKnownTypes()].join(`
15
+ `).trim(), resolver = codegen.getResolver();
16
+ node_worker_threads.parentPort?.postMessage({
17
+ type: "schema",
18
+ schema: `${schemaTypes.trim()}
19
+ `,
20
+ filename: "schema.json",
21
+ length: schema.length
30
22
  });
31
- report.event.generatedSchemaDeclarations({
32
- code: [
33
- generator.getKnownTypes().code,
34
- ...generator.getSchemaTypeDeclarations().map((i) => i.code),
35
- generator.getAllSanitySchemaTypesDeclaration().code,
36
- ...generator.getSchemaDeclarations().map((i) => i.code),
37
- generator.getAugmentedSchemasDeclarations().code
38
- ].join(`
39
- `),
40
- schemaStats: {
41
- schemaTypesCount: generator.getSchemaTypeDeclarations().length,
42
- schemaCount: schemas.length
23
+ const queries = codegen.findQueriesInPath({
24
+ path: opts.searchPath,
25
+ resolver
26
+ }), allQueries = [];
27
+ for await (const result of queries) {
28
+ if (result.type === "error") {
29
+ node_worker_threads.parentPort?.postMessage({
30
+ type: "error",
31
+ error: result.error,
32
+ fatal: !1,
33
+ filename: result.filename
34
+ });
35
+ continue;
43
36
  }
44
- });
45
- const allFilenames = /* @__PURE__ */ new Set(), errorFilenames = /* @__PURE__ */ new Set(), queryFilenames = /* @__PURE__ */ new Set(), projectionFilenames = /* @__PURE__ */ new Set();
46
- let errorCount = 0, queriesCount = 0, projectionsCount = 0, typeNodesGenerated = 0, unknownTypeNodesGenerated = 0, emptyUnionTypeNodesGenerated = 0;
47
- const { fileCount } = await generator.getQueryFileCount();
48
- report.event.fileCount({ fileCount });
49
- for await (const { filename, ...result } of generator.getQueryResultDeclarations()) {
50
- allFilenames.add(filename);
51
- const progress = {
52
- queriesCount,
53
- projectionsCount,
54
- filesCount: allFilenames.size
55
- };
56
- switch (result.type) {
57
- case "error": {
58
- errorCount += 1, errorFilenames.add(filename);
59
- const errorMessage = typeof result.error == "object" && result.error !== null && "message" in result.error ? String(result.error.message) : "Unknown Error", message = `Error generating types in "${filename}": ${errorMessage}`;
60
- report.stream.generatedQueryResultDeclaration.emit({ type: "error", message, progress });
61
- continue;
62
- }
63
- case "queries": {
64
- if (!result.queryResultDeclarations.length) {
65
- report.stream.generatedQueryResultDeclaration.emit({ type: "progress", progress });
66
- continue;
67
- }
68
- for (const { code, type, stats } of result.queryResultDeclarations)
69
- queriesCount += type === "query" ? 1 : 0, projectionsCount += type === "projection" ? 1 : 0, typeNodesGenerated += stats.allTypes, unknownTypeNodesGenerated += stats.unknownTypes, emptyUnionTypeNodesGenerated += stats.emptyUnions, type === "projection" ? projectionFilenames.add(filename) : queryFilenames.add(filename), report.stream.generatedQueryResultDeclaration.emit({ type: "declaration", code, progress });
70
- continue;
37
+ $info(`Processing ${result.queries.length} queries in "${result.filename}"...`);
38
+ const fileQueryTypes = [];
39
+ for (const { name: queryName, result: query } of result.queries)
40
+ try {
41
+ const ast = codegen.safeParseQuery(query), queryTypes = groqJs.typeEvaluate(ast, schema), typeName = `${queryName}Result`, type = typeGenerator.generateTypeNodeTypes(typeName, queryTypes), queryTypeStats = walkAndCountQueryTypeNodeStats(queryTypes);
42
+ fileQueryTypes.push({
43
+ queryName,
44
+ query,
45
+ typeName,
46
+ typeNode: queryTypes,
47
+ type: `${type.trim()}
48
+ `,
49
+ unknownTypeNodesGenerated: queryTypeStats.unknownTypes,
50
+ typeNodesGenerated: queryTypeStats.allTypes,
51
+ emptyUnionTypeNodesGenerated: queryTypeStats.emptyUnions
52
+ });
53
+ } catch (err) {
54
+ node_worker_threads.parentPort?.postMessage({
55
+ type: "error",
56
+ error: new Error(
57
+ `Error generating types for query "${queryName}" in "${result.filename}": ${err.message}`,
58
+ { cause: err }
59
+ ),
60
+ fatal: !1,
61
+ query
62
+ });
71
63
  }
72
- default:
73
- continue;
74
- }
64
+ fileQueryTypes.length > 0 && ($info(`Generated types for ${fileQueryTypes.length} queries in "${result.filename}"
65
+ `), node_worker_threads.parentPort?.postMessage({
66
+ type: "types",
67
+ types: fileQueryTypes,
68
+ filename: result.filename
69
+ })), fileQueryTypes.length > 0 && allQueries.push(...fileQueryTypes);
75
70
  }
76
- report.stream.generatedQueryResultDeclaration.end(), report.event.generationComplete({
77
- augmentedQueryResultDeclarations: await generator.getAugmentedQueryResultsDeclarations(),
78
- queryStats: {
79
- errorCount,
80
- queriesCount,
81
- projectionsCount,
82
- typeNodesGenerated,
83
- unknownTypeNodesGenerated,
84
- emptyUnionTypeNodesGenerated,
85
- totalScannedFilesCount: allFilenames.size,
86
- filesWithErrors: errorFilenames.size,
87
- queryFilesCount: queryFilenames.size,
88
- projectionFilesCount: projectionFilenames.size,
89
- unknownTypeNodesRatio: typeNodesGenerated > 0 ? unknownTypeNodesGenerated / typeNodesGenerated : 0
90
- }
71
+ if (opts.overloadClientMethods && allQueries.length > 0) {
72
+ const typeMap = `${typeGenerator.generateQueryMap(allQueries).trim()}
73
+ `;
74
+ node_worker_threads.parentPort?.postMessage({
75
+ type: "typemap",
76
+ typeMap
77
+ });
78
+ }
79
+ node_worker_threads.parentPort?.postMessage({
80
+ type: "complete"
91
81
  });
92
82
  }
93
- codegen.registerBabel();
83
+ function walkAndCountQueryTypeNodeStats(typeNode) {
84
+ switch (typeNode.type) {
85
+ case "unknown":
86
+ return { allTypes: 1, unknownTypes: 1, emptyUnions: 0 };
87
+ case "array": {
88
+ const acc = walkAndCountQueryTypeNodeStats(typeNode.of);
89
+ return acc.allTypes += 1, acc;
90
+ }
91
+ case "object": {
92
+ if (typeNode.rest && typeNode.rest.type === "unknown")
93
+ return { allTypes: 2, unknownTypes: 1, emptyUnions: 0 };
94
+ const restStats = typeNode.rest ? walkAndCountQueryTypeNodeStats(typeNode.rest) : { allTypes: 1, unknownTypes: 0, emptyUnions: 0 };
95
+ return Object.values(typeNode.attributes).reduce((acc, attribute) => {
96
+ const { allTypes, unknownTypes, emptyUnions } = walkAndCountQueryTypeNodeStats(
97
+ attribute.value
98
+ );
99
+ return {
100
+ allTypes: acc.allTypes + allTypes,
101
+ unknownTypes: acc.unknownTypes + unknownTypes,
102
+ emptyUnions: acc.emptyUnions + emptyUnions
103
+ };
104
+ }, restStats);
105
+ }
106
+ case "union":
107
+ return typeNode.of.length === 0 ? { allTypes: 1, unknownTypes: 0, emptyUnions: 1 } : typeNode.of.reduce(
108
+ (acc, type) => {
109
+ const { allTypes, unknownTypes, emptyUnions } = walkAndCountQueryTypeNodeStats(type);
110
+ return {
111
+ allTypes: acc.allTypes + allTypes,
112
+ unknownTypes: acc.unknownTypes + unknownTypes,
113
+ emptyUnions: acc.emptyUnions + emptyUnions
114
+ };
115
+ },
116
+ { allTypes: 1, unknownTypes: 0, emptyUnions: 0 }
117
+ // count the union type itself
118
+ );
119
+ default:
120
+ return { allTypes: 1, unknownTypes: 0, emptyUnions: 0 };
121
+ }
122
+ }
94
123
  main();
95
124
  //# sourceMappingURL=typegenGenerate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"typegenGenerate.js","sources":["../../src/workers/typegenGenerate.ts"],"sourcesContent":["/* eslint-disable max-statements */\nimport {stat} from 'node:fs/promises'\nimport {isMainThread, parentPort, workerData as _workerData} from 'node:worker_threads'\n\nimport {\n DEFAULT_CONFIG,\n findQueriesInPath,\n getResolver,\n readSchema,\n registerBabel,\n TypeGenerator,\n} from '@sanity/codegen'\nimport {type SchemaType} from 'groq-js'\n\nimport {\n createReporter,\n type WorkerChannel,\n type WorkerChannelEvent,\n type WorkerChannelStream,\n} from '../util/workerChannel'\n\nconst DEFAULT_SCHEMA_PATH = DEFAULT_CONFIG.schemas[0].schemaPath\n\nexport interface TypegenGenerateTypesWorkerData {\n workDir: string\n schemas: {schemaPath: string; schemaId: string}[]\n searchPath: string | string[]\n overloadClientMethods: boolean\n augmentGroqModule: boolean\n}\n\ninterface QueryProgress {\n queriesCount: number\n projectionsCount: number\n filesCount: number\n}\n\n/** @internal */\nexport type TypegenWorkerChannel = WorkerChannel<{\n loadedSchemas: WorkerChannelEvent\n generatedSchemaDeclarations: WorkerChannelEvent<{\n code: string\n schemaStats: {\n schemaTypesCount: number\n schemaCount: number\n }\n }>\n fileCount: WorkerChannelEvent<{fileCount: number}>\n generatedQueryResultDeclaration: WorkerChannelStream<\n | {\n type: 'progress'\n progress: QueryProgress\n }\n | {\n type: 'declaration'\n code: string\n progress: QueryProgress\n }\n | {\n type: 'error'\n message: string\n progress: QueryProgress\n }\n >\n generationComplete: WorkerChannelEvent<{\n augmentedQueryResultDeclarations: {code: string}\n queryStats: {\n queriesCount: number\n projectionsCount: number\n totalScannedFilesCount: number\n queryFilesCount: number\n projectionFilesCount: number\n filesWithErrors: number\n errorCount: number\n typeNodesGenerated: number\n unknownTypeNodesGenerated: number\n unknownTypeNodesRatio: number\n emptyUnionTypeNodesGenerated: number\n }\n }>\n}>\n\nif (isMainThread || !parentPort) {\n throw new Error('This module must be run as a worker thread')\n}\n\nconst report = createReporter<TypegenWorkerChannel>(parentPort)\nconst opts = _workerData as TypegenGenerateTypesWorkerData\n\nasync function main() {\n const schemas: {schema: SchemaType; schemaId: string; filename: string}[] = []\n\n for (const {schemaId, schemaPath} of opts.schemas) {\n try {\n const schemaStats = await stat(schemaPath)\n if (!schemaStats.isFile()) {\n throw new Error(\n `Failed to load schema \"${schemaId}\". Schema path is not a file: ${schemaPath}`,\n )\n }\n\n const schema = await readSchema(schemaPath)\n schemas.push({schema, schemaId, filename: schemaPath})\n } catch (err) {\n if (err.code === 'ENOENT') {\n // If the user has not provided a specific schema path (eg we're using the default), give some help\n const hint =\n schemaPath === DEFAULT_SCHEMA_PATH ? ` - did you run \"sanity schema extract\"?` : ''\n throw new Error(`Schema file not found for schema \"${schemaId}\": ${schemaPath}${hint}`)\n } else {\n throw err\n }\n }\n }\n report.event.loadedSchemas()\n\n const generator = new TypeGenerator({\n schemas,\n queriesByFile: findQueriesInPath({path: opts.searchPath, resolver: getResolver()}),\n augmentGroqModule: opts.augmentGroqModule,\n overloadClientMethods: opts.overloadClientMethods,\n })\n\n report.event.generatedSchemaDeclarations({\n code: [\n generator.getKnownTypes().code,\n ...generator.getSchemaTypeDeclarations().map((i) => i.code),\n generator.getAllSanitySchemaTypesDeclaration().code,\n ...generator.getSchemaDeclarations().map((i) => i.code),\n generator.getAugmentedSchemasDeclarations().code,\n ].join('\\n'),\n schemaStats: {\n schemaTypesCount: generator.getSchemaTypeDeclarations().length,\n schemaCount: schemas.length,\n },\n })\n\n const allFilenames = new Set<string>()\n const errorFilenames = new Set<string>()\n const queryFilenames = new Set<string>()\n const projectionFilenames = new Set<string>()\n\n let errorCount = 0\n let queriesCount = 0\n let projectionsCount = 0\n let typeNodesGenerated = 0\n let unknownTypeNodesGenerated = 0\n let emptyUnionTypeNodesGenerated = 0\n\n const {fileCount} = await generator.getQueryFileCount()\n report.event.fileCount({fileCount})\n\n for await (const {filename, ...result} of generator.getQueryResultDeclarations()) {\n allFilenames.add(filename)\n const progress = {\n queriesCount,\n projectionsCount,\n filesCount: allFilenames.size,\n }\n\n switch (result.type) {\n case 'error': {\n errorCount += 1\n errorFilenames.add(filename)\n\n const errorMessage =\n typeof result.error === 'object' && result.error !== null && 'message' in result.error\n ? String(result.error.message)\n : 'Unknown Error'\n\n const message = `Error generating types in \"${filename}\": ${errorMessage}`\n report.stream.generatedQueryResultDeclaration.emit({type: 'error', message, progress})\n continue\n }\n\n case 'queries': {\n if (!result.queryResultDeclarations.length) {\n report.stream.generatedQueryResultDeclaration.emit({type: 'progress', progress})\n continue\n }\n\n for (const {code, type, stats} of result.queryResultDeclarations) {\n queriesCount += type === 'query' ? 1 : 0\n projectionsCount += type === 'projection' ? 1 : 0\n typeNodesGenerated += stats.allTypes\n unknownTypeNodesGenerated += stats.unknownTypes\n emptyUnionTypeNodesGenerated += stats.emptyUnions\n\n if (type === 'projection') {\n projectionFilenames.add(filename)\n } else {\n queryFilenames.add(filename)\n }\n\n report.stream.generatedQueryResultDeclaration.emit({type: 'declaration', code, progress})\n }\n continue\n }\n\n default: {\n continue\n }\n }\n }\n report.stream.generatedQueryResultDeclaration.end()\n\n report.event.generationComplete({\n augmentedQueryResultDeclarations: await generator.getAugmentedQueryResultsDeclarations(),\n queryStats: {\n errorCount,\n queriesCount,\n projectionsCount,\n typeNodesGenerated,\n unknownTypeNodesGenerated,\n emptyUnionTypeNodesGenerated,\n totalScannedFilesCount: allFilenames.size,\n filesWithErrors: errorFilenames.size,\n queryFilesCount: queryFilenames.size,\n projectionFilesCount: projectionFilenames.size,\n unknownTypeNodesRatio:\n typeNodesGenerated > 0 ? unknownTypeNodesGenerated / typeNodesGenerated : 0,\n },\n })\n}\n\nregisterBabel()\nmain()\n"],"names":["DEFAULT_CONFIG","isMainThread","parentPort","createReporter","_workerData","stat","readSchema","TypeGenerator","findQueriesInPath","getResolver","registerBabel"],"mappings":"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"}
1
+ {"version":3,"file":"typegenGenerate.js","sources":["../../src/workers/typegenGenerate.ts"],"sourcesContent":["import {isMainThread, parentPort, workerData as _workerData} from 'node:worker_threads'\n\nimport {\n findQueriesInPath,\n getResolver,\n readSchema,\n registerBabel,\n safeParseQuery,\n TypeGenerator,\n} from '@sanity/codegen'\nimport createDebug from 'debug'\nimport {typeEvaluate, type TypeNode} from 'groq-js'\n\nconst $info = createDebug('sanity:codegen:generate:info')\nconst $warn = createDebug('sanity:codegen:generate:warn')\n\nexport interface TypegenGenerateTypesWorkerData {\n workDir: string\n workspaceName?: string\n schemaPath: string\n searchPath: string | string[]\n overloadClientMethods?: boolean\n}\n\nexport type TypegenGenerateTypesWorkerMessage =\n | {\n type: 'error'\n error: Error\n fatal: boolean\n query?: string\n filename?: string\n }\n | {\n type: 'types'\n filename: string\n types: {\n queryName: string\n query: string\n type: string\n unknownTypeNodesGenerated: number\n typeNodesGenerated: number\n emptyUnionTypeNodesGenerated: number\n }[]\n }\n | {\n type: 'schema'\n filename: string\n schema: string\n length: number\n }\n | {\n type: 'typemap'\n typeMap: string\n }\n | {\n type: 'complete'\n }\n\nif (isMainThread || !parentPort) {\n throw new Error('This module must be run as a worker thread')\n}\n\nconst opts = _workerData as TypegenGenerateTypesWorkerData\n\nregisterBabel()\n\nasync function main() {\n const schema = await readSchema(opts.schemaPath)\n\n const typeGenerator = new TypeGenerator(schema)\n const schemaTypes = [typeGenerator.generateSchemaTypes(), TypeGenerator.generateKnownTypes()]\n .join('\\n')\n .trim()\n const resolver = getResolver()\n\n parentPort?.postMessage({\n type: 'schema',\n schema: `${schemaTypes.trim()}\\n`,\n filename: 'schema.json',\n length: schema.length,\n } satisfies TypegenGenerateTypesWorkerMessage)\n\n const queries = findQueriesInPath({\n path: opts.searchPath,\n resolver,\n })\n\n const allQueries = []\n\n for await (const result of queries) {\n if (result.type === 'error') {\n parentPort?.postMessage({\n type: 'error',\n error: result.error,\n fatal: false,\n filename: result.filename,\n } satisfies TypegenGenerateTypesWorkerMessage)\n continue\n }\n $info(`Processing ${result.queries.length} queries in \"${result.filename}\"...`)\n\n const fileQueryTypes: {\n queryName: string\n query: string\n type: string\n typeName: string\n typeNode: TypeNode\n unknownTypeNodesGenerated: number\n typeNodesGenerated: number\n emptyUnionTypeNodesGenerated: number\n }[] = []\n for (const {name: queryName, result: query} of result.queries) {\n try {\n const ast = safeParseQuery(query)\n const queryTypes = typeEvaluate(ast, schema)\n\n const typeName = `${queryName}Result`\n const type = typeGenerator.generateTypeNodeTypes(typeName, queryTypes)\n\n const queryTypeStats = walkAndCountQueryTypeNodeStats(queryTypes)\n fileQueryTypes.push({\n queryName,\n query,\n typeName,\n typeNode: queryTypes,\n type: `${type.trim()}\\n`,\n unknownTypeNodesGenerated: queryTypeStats.unknownTypes,\n typeNodesGenerated: queryTypeStats.allTypes,\n emptyUnionTypeNodesGenerated: queryTypeStats.emptyUnions,\n })\n } catch (err) {\n parentPort?.postMessage({\n type: 'error',\n error: new Error(\n `Error generating types for query \"${queryName}\" in \"${result.filename}\": ${err.message}`,\n {cause: err},\n ),\n fatal: false,\n query,\n } satisfies TypegenGenerateTypesWorkerMessage)\n }\n }\n\n if (fileQueryTypes.length > 0) {\n $info(`Generated types for ${fileQueryTypes.length} queries in \"${result.filename}\"\\n`)\n parentPort?.postMessage({\n type: 'types',\n types: fileQueryTypes,\n filename: result.filename,\n } satisfies TypegenGenerateTypesWorkerMessage)\n }\n\n if (fileQueryTypes.length > 0) {\n allQueries.push(...fileQueryTypes)\n }\n }\n\n if (opts.overloadClientMethods && allQueries.length > 0) {\n const typeMap = `${typeGenerator.generateQueryMap(allQueries).trim()}\\n`\n parentPort?.postMessage({\n type: 'typemap',\n typeMap,\n } satisfies TypegenGenerateTypesWorkerMessage)\n }\n\n parentPort?.postMessage({\n type: 'complete',\n } satisfies TypegenGenerateTypesWorkerMessage)\n}\n\nfunction walkAndCountQueryTypeNodeStats(typeNode: TypeNode): {\n allTypes: number\n unknownTypes: number\n emptyUnions: number\n} {\n switch (typeNode.type) {\n case 'unknown': {\n return {allTypes: 1, unknownTypes: 1, emptyUnions: 0}\n }\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, unknownTypes: 1, emptyUnions: 0} // count the object type itself as well\n }\n\n const restStats = typeNode.rest\n ? walkAndCountQueryTypeNodeStats(typeNode.rest)\n : {allTypes: 1, unknownTypes: 0, emptyUnions: 0} // count the object type itself\n\n return Object.values(typeNode.attributes).reduce((acc, attribute) => {\n const {allTypes, unknownTypes, emptyUnions} = walkAndCountQueryTypeNodeStats(\n attribute.value,\n )\n return {\n allTypes: acc.allTypes + allTypes,\n unknownTypes: acc.unknownTypes + unknownTypes,\n emptyUnions: acc.emptyUnions + emptyUnions,\n }\n }, restStats)\n }\n case 'union': {\n if (typeNode.of.length === 0) {\n return {allTypes: 1, unknownTypes: 0, emptyUnions: 1}\n }\n\n return typeNode.of.reduce(\n (acc, type) => {\n const {allTypes, unknownTypes, emptyUnions} = walkAndCountQueryTypeNodeStats(type)\n return {\n allTypes: acc.allTypes + allTypes,\n unknownTypes: acc.unknownTypes + unknownTypes,\n emptyUnions: acc.emptyUnions + emptyUnions,\n }\n },\n {allTypes: 1, unknownTypes: 0, emptyUnions: 0}, // count the union type itself\n )\n }\n default: {\n return {allTypes: 1, unknownTypes: 0, emptyUnions: 0}\n }\n }\n}\n\nmain()\n"],"names":["createDebug","isMainThread","parentPort","_workerData","registerBabel","readSchema","TypeGenerator","getResolver","findQueriesInPath","safeParseQuery","typeEvaluate"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/cli",
3
- "version": "3.88.1-typegen-experimental.0",
3
+ "version": "3.88.1",
4
4
  "description": "Sanity CLI tool for managing Sanity installations, managing plugins, schemas and datasets",
5
5
  "keywords": [
6
6
  "sanity",
@@ -46,9 +46,20 @@
46
46
  "src",
47
47
  "templates"
48
48
  ],
49
+ "scripts": {
50
+ "build": "pkg-utils build --strict --check --clean",
51
+ "check:types": "tsc --project tsconfig.lib.json",
52
+ "clean": "rimraf lib",
53
+ "lint": "eslint --cache .",
54
+ "prepublishOnly": "turbo run build",
55
+ "test": "vitest",
56
+ "ts": "node -r esbuild-register",
57
+ "watch": "pkg-utils watch"
58
+ },
49
59
  "dependencies": {
50
60
  "@babel/traverse": "^7.23.5",
51
61
  "@sanity/client": "^7.1.0",
62
+ "@sanity/codegen": "3.88.1",
52
63
  "@sanity/runtime-cli": "^6.1.1",
53
64
  "@sanity/telemetry": "^0.8.0",
54
65
  "@sanity/template-validator": "^2.4.3",
@@ -63,14 +74,16 @@
63
74
  "pkg-dir": "^5.0.0",
64
75
  "prettier": "^3.3.0",
65
76
  "semver": "^7.3.5",
66
- "validate-npm-package-name": "^3.0.0",
67
- "@sanity/codegen": "3.88.1-typegen-experimental.0"
77
+ "validate-npm-package-name": "^3.0.0"
68
78
  },
69
79
  "devDependencies": {
80
+ "@repo/package.config": "3.88.1",
81
+ "@repo/test-config": "3.88.1",
70
82
  "@rexxars/gitconfiglocal": "^3.0.1",
71
83
  "@rollup/plugin-node-resolve": "^15.2.3",
72
84
  "@sanity/eslint-config-studio": "^4.0.0",
73
85
  "@sanity/generate-help-url": "^3.0.0",
86
+ "@sanity/types": "3.88.1",
74
87
  "@types/babel__traverse": "^7.20.5",
75
88
  "@types/configstore": "^5.0.1",
76
89
  "@types/cpx": "^1.5.2",
@@ -117,21 +130,10 @@
117
130
  "vite": "^6.2.4",
118
131
  "vitest": "^3.1.1",
119
132
  "which": "^2.0.2",
120
- "xdg-basedir": "^4.0.0",
121
- "@repo/package.config": "3.88.1",
122
- "@repo/test-config": "3.88.1",
123
- "@sanity/types": "3.88.1"
133
+ "xdg-basedir": "^4.0.0"
124
134
  },
125
135
  "engines": {
126
136
  "node": ">=18"
127
137
  },
128
- "scripts": {
129
- "build": "pkg-utils build --strict --check --clean",
130
- "check:types": "tsc --project tsconfig.lib.json",
131
- "clean": "rimraf lib",
132
- "lint": "eslint --cache .",
133
- "test": "vitest",
134
- "ts": "node -r esbuild-register",
135
- "watch": "pkg-utils watch"
136
- }
137
- }
138
+ "gitHead": "26a4552965274b9d35f92b9d1191eb029cb913e8"
139
+ }
@@ -1,26 +1,20 @@
1
1
  import {defineTrace} from '@sanity/telemetry'
2
2
 
3
- interface TypesGeneratedTraceAttributes {
3
+ interface TypesGeneratedTraceAttrubutes {
4
4
  outputSize: number
5
5
  queriesCount: number
6
- projectionsCount: number
7
6
  schemaTypesCount: number
8
- schemaCount: number
9
- totalScannedFilesCount: number
10
7
  queryFilesCount: number
11
- projectionFilesCount: number
12
8
  filesWithErrors: number
13
- errorCount: number
14
9
  typeNodesGenerated: number
15
10
  unknownTypeNodesGenerated: number
16
11
  unknownTypeNodesRatio: number
17
12
  emptyUnionTypeNodesGenerated: number
18
13
  configOverloadClientMethods: boolean
19
- configAugmentGroqModule: boolean
20
14
  }
21
15
 
22
- export const TypesGeneratedTrace = defineTrace<TypesGeneratedTraceAttributes>({
16
+ export const TypesGeneratedTrace = defineTrace<TypesGeneratedTraceAttrubutes>({
23
17
  name: 'Types Generated',
24
- version: 1,
18
+ version: 0,
25
19
  description: 'Trace emitted when generating TypeScript types for queries',
26
20
  })