@sanity/cli 8.15.0 → 8.16.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.
@@ -0,0 +1,40 @@
1
+ import { convertToDefinition } from '@sanity/schema-descriptor-utils';
2
+ import { createSchemaFromManifestTypes, extractSchema } from '@sanity/schema/_internal';
3
+ import { getDatasetSchemaBinding, getSchemaDescriptor } from '../../services/schemas.js';
4
+ import { getResourceKey } from './parseTypegenResources.js';
5
+ /**
6
+ * Fetches the schema bound to a resource's dataset and extracts it for typegen.
7
+ *
8
+ * Throws when the dataset has no binding, naming the resource so the user can set a local
9
+ * `schema` for it instead.
10
+ */ export async function fetchResourceSchema(resource) {
11
+ const key = getResourceKey(resource);
12
+ // The binding's own `types` are hydrated for display and do not compile, so only its
13
+ // descriptor ID is used.
14
+ const binding = await getDatasetSchemaBinding(resource.projectId, resource.dataset);
15
+ if (!binding) {
16
+ throw new Error(`No schema is bound to dataset "${key}", or the dataset does not exist. Check its projectId and dataset, or set "schema" for this resource to a file extracted with "sanity schema extract".`);
17
+ }
18
+ const { schemaVersion } = binding._meta;
19
+ const descriptor = await getSchemaDescriptor(schemaVersion);
20
+ return {
21
+ schema: extractDescriptorSchema(descriptor, {
22
+ enforceRequiredFields: resource.enforceRequiredFields ?? false
23
+ }),
24
+ schemaVersion
25
+ };
26
+ }
27
+ /**
28
+ * Compiles a schema descriptor and extracts it.
29
+ *
30
+ * Uses the `manifest` format because it keeps validation, which `enforceRequiredFields` reads.
31
+ * The `createSchema` format drops validation, so every field would come out optional.
32
+ * `createSchemaFromManifestTypes` compiles on the built-in types, which descriptors omit.
33
+ */ export function extractDescriptorSchema(descriptor, options) {
34
+ const definition = convertToDefinition(descriptor, {
35
+ format: 'manifest'
36
+ });
37
+ return extractSchema(createSchemaFromManifestTypes(definition), options);
38
+ }
39
+
40
+ //# sourceMappingURL=fetchResourceSchema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/typegen/fetchResourceSchema.ts"],"sourcesContent":["import {type TypeGenResource} from '@sanity/cli-core/types'\nimport {type RunTypegenOptions} from '@sanity/codegen'\nimport {convertToDefinition, type SchemaSummary} from '@sanity/schema-descriptor-utils'\nimport {createSchemaFromManifestTypes, extractSchema} from '@sanity/schema/_internal'\n\nimport {getDatasetSchemaBinding, getSchemaDescriptor} from '../../services/schemas.js'\nimport {getResourceKey} from './parseTypegenResources.js'\n\n/** A schema in the format `sanity schema extract` writes. */\nexport type ExtractedSchema = NonNullable<RunTypegenOptions['extractedSchema']>\n\n/**\n * The schema bound to a resource's dataset.\n */\nexport interface FetchedResourceSchema {\n schema: ExtractedSchema\n /** The Lexicon descriptor ID the dataset's binding points at. */\n schemaVersion: string\n}\n\n/**\n * Fetches the schema bound to a resource's dataset and extracts it for typegen.\n *\n * Throws when the dataset has no binding, naming the resource so the user can set a local\n * `schema` for it instead.\n */\nexport async function fetchResourceSchema(\n resource: Pick<TypeGenResource, 'dataset' | 'enforceRequiredFields' | 'projectId'>,\n): Promise<FetchedResourceSchema> {\n const key = getResourceKey(resource)\n\n // The binding's own `types` are hydrated for display and do not compile, so only its\n // descriptor ID is used.\n const binding = await getDatasetSchemaBinding(resource.projectId, resource.dataset)\n if (!binding) {\n throw new Error(\n `No schema is bound to dataset \"${key}\", or the dataset does not exist. Check its projectId and dataset, or set \"schema\" for this resource to a file extracted with \"sanity schema extract\".`,\n )\n }\n\n const {schemaVersion} = binding._meta\n const descriptor = await getSchemaDescriptor(schemaVersion)\n\n return {\n schema: extractDescriptorSchema(descriptor, {\n enforceRequiredFields: resource.enforceRequiredFields ?? false,\n }),\n schemaVersion,\n }\n}\n\n/**\n * Compiles a schema descriptor and extracts it.\n *\n * Uses the `manifest` format because it keeps validation, which `enforceRequiredFields` reads.\n * The `createSchema` format drops validation, so every field would come out optional.\n * `createSchemaFromManifestTypes` compiles on the built-in types, which descriptors omit.\n */\nexport function extractDescriptorSchema(\n descriptor: SchemaSummary,\n options: {enforceRequiredFields: boolean},\n): ExtractedSchema {\n const definition = convertToDefinition(descriptor, {format: 'manifest'})\n return extractSchema(createSchemaFromManifestTypes(definition), options)\n}\n"],"names":["convertToDefinition","createSchemaFromManifestTypes","extractSchema","getDatasetSchemaBinding","getSchemaDescriptor","getResourceKey","fetchResourceSchema","resource","key","binding","projectId","dataset","Error","schemaVersion","_meta","descriptor","schema","extractDescriptorSchema","enforceRequiredFields","options","definition","format"],"mappings":"AAEA,SAAQA,mBAAmB,QAA2B,kCAAiC;AACvF,SAAQC,6BAA6B,EAAEC,aAAa,QAAO,2BAA0B;AAErF,SAAQC,uBAAuB,EAAEC,mBAAmB,QAAO,4BAA2B;AACtF,SAAQC,cAAc,QAAO,6BAA4B;AAczD;;;;;CAKC,GACD,OAAO,eAAeC,oBACpBC,QAAkF;IAElF,MAAMC,MAAMH,eAAeE;IAE3B,qFAAqF;IACrF,yBAAyB;IACzB,MAAME,UAAU,MAAMN,wBAAwBI,SAASG,SAAS,EAAEH,SAASI,OAAO;IAClF,IAAI,CAACF,SAAS;QACZ,MAAM,IAAIG,MACR,CAAC,+BAA+B,EAAEJ,IAAI,sJAAsJ,CAAC;IAEjM;IAEA,MAAM,EAACK,aAAa,EAAC,GAAGJ,QAAQK,KAAK;IACrC,MAAMC,aAAa,MAAMX,oBAAoBS;IAE7C,OAAO;QACLG,QAAQC,wBAAwBF,YAAY;YAC1CG,uBAAuBX,SAASW,qBAAqB,IAAI;QAC3D;QACAL;IACF;AACF;AAEA;;;;;;CAMC,GACD,OAAO,SAASI,wBACdF,UAAyB,EACzBI,OAAyC;IAEzC,MAAMC,aAAapB,oBAAoBe,YAAY;QAACM,QAAQ;IAAU;IACtE,OAAOnB,cAAcD,8BAA8BmB,aAAaD;AAClE"}
@@ -0,0 +1,115 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { isAbsolute, join } from 'node:path';
3
+ import { runTypegenGenerate } from '@sanity/codegen';
4
+ import { fetchResourceSchema } from './fetchResourceSchema.js';
5
+ import { getResourceKey } from './parseTypegenResources.js';
6
+ /**
7
+ * Locates the schema for every resource before anything is generated.
8
+ *
9
+ * A resource with a `schema` path uses that file, which must exist and parse. One without
10
+ * fetches the schema bound to its dataset. Doing this first means a missing binding or a
11
+ * missing or malformed file fails the run before any output is written.
12
+ */ export async function resolveResourceSchemas(options) {
13
+ const { onResolved, onResolving, resources, workDir } = options;
14
+ const resolved = [];
15
+ for (const resource of resources){
16
+ const key = getResourceKey(resource);
17
+ onResolving?.(resource, key);
18
+ let entry;
19
+ if (resource.schema === undefined) {
20
+ try {
21
+ entry = {
22
+ key,
23
+ resource,
24
+ ...await fetchResourceSchema(resource)
25
+ };
26
+ } catch (error) {
27
+ const message = error instanceof Error ? error.message : String(error);
28
+ throw new Error(`Failed to get the schema for "${key}": ${message}`, {
29
+ cause: error
30
+ });
31
+ }
32
+ } else {
33
+ const schemaPath = isAbsolute(resource.schema) ? resource.schema : join(workDir, resource.schema);
34
+ await assertExtractedSchemaFile(schemaPath, {
35
+ key,
36
+ schema: resource.schema
37
+ });
38
+ // Codegen reads the file again, so the generated output names it as its source, as it
39
+ // does without resources.
40
+ entry = {
41
+ key,
42
+ resource,
43
+ schemaPath: resource.schema
44
+ };
45
+ }
46
+ resolved.push(entry);
47
+ onResolved?.(entry);
48
+ }
49
+ return resolved;
50
+ }
51
+ /**
52
+ * Generates one output file per resource, registering its types under the resource key.
53
+ */ export async function generateResourceTypes(options) {
54
+ const { config, onProgress, resolved, workDir } = options;
55
+ const results = [];
56
+ for (const entry of resolved){
57
+ const { dataset, generates, path, projectId } = entry.resource;
58
+ let result;
59
+ try {
60
+ result = await runTypegenGenerate({
61
+ config: {
62
+ ...config,
63
+ generates,
64
+ path: path ?? config.path,
65
+ schema: 'schemaPath' in entry ? entry.schemaPath : config.schema
66
+ },
67
+ extractedSchema: 'schema' in entry ? entry.schema : undefined,
68
+ onProgress: onProgress?.(entry),
69
+ resource: {
70
+ dataset,
71
+ projectId
72
+ },
73
+ workDir
74
+ });
75
+ } catch (error) {
76
+ // Codegen writes a resource's file once its generation succeeds, so the files of this
77
+ // resource and the ones after it are unchanged. Files of earlier resources are not
78
+ // rolled back.
79
+ const message = error instanceof Error ? error.message : String(error);
80
+ const written = results.map(({ key })=>`"${key}"`).join(', ');
81
+ throw new Error(`Failed to generate types for "${entry.key}": ${message}` + (written ? `\nTypes for ${written} were updated. The other output files are unchanged.` : ''), {
82
+ cause: error
83
+ });
84
+ }
85
+ results.push({
86
+ key: entry.key,
87
+ result
88
+ });
89
+ }
90
+ return results;
91
+ }
92
+ /**
93
+ * Checks that a local schema file exists and holds an extracted schema, which is a JSON array.
94
+ */ async function assertExtractedSchemaFile(schemaPath, { key, schema }) {
95
+ let content;
96
+ try {
97
+ content = await readFile(schemaPath, 'utf8');
98
+ } catch {
99
+ throw new Error(`Schema file not found for "${key}": ${schema}. Run "sanity schema extract" to create it.`);
100
+ }
101
+ let parsed;
102
+ try {
103
+ parsed = JSON.parse(content);
104
+ } catch (error) {
105
+ const message = error instanceof Error ? error.message : String(error);
106
+ throw new Error(`Schema file for "${key}" is not valid JSON: ${schema}. ${message}`, {
107
+ cause: error
108
+ });
109
+ }
110
+ if (!Array.isArray(parsed)) {
111
+ throw new TypeError(`Schema file for "${key}" is not an extracted schema: ${schema}. Run "sanity schema extract" to recreate it.`);
112
+ }
113
+ }
114
+
115
+ //# sourceMappingURL=generateResourceTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/typegen/generateResourceTypes.ts"],"sourcesContent":["import {readFile} from 'node:fs/promises'\nimport {isAbsolute, join} from 'node:path'\n\nimport {type TypeGenResource} from '@sanity/cli-core/types'\nimport {\n type GenerationResult,\n runTypegenGenerate,\n type TypeGenConfig,\n type TypegenProgressEvent,\n} from '@sanity/codegen'\n\nimport {type ExtractedSchema, fetchResourceSchema} from './fetchResourceSchema.js'\nimport {getResourceKey} from './parseTypegenResources.js'\n\n/**\n * A resource whose schema has been located, ready to generate.\n */\nexport type ResolvedResource =\n | {key: string; resource: TypeGenResource; schema: ExtractedSchema; schemaVersion: string}\n | {key: string; resource: TypeGenResource; schemaPath: string}\n\n/**\n * Locates the schema for every resource before anything is generated.\n *\n * A resource with a `schema` path uses that file, which must exist and parse. One without\n * fetches the schema bound to its dataset. Doing this first means a missing binding or a\n * missing or malformed file fails the run before any output is written.\n */\nexport async function resolveResourceSchemas(options: {\n /** Called once a resource's schema is located. */\n onResolved?: (resolved: ResolvedResource) => void\n /** Called before a resource's schema is located. */\n onResolving?: (resource: TypeGenResource, key: string) => void\n resources: TypeGenResource[]\n workDir: string\n}): Promise<ResolvedResource[]> {\n const {onResolved, onResolving, resources, workDir} = options\n const resolved: ResolvedResource[] = []\n\n for (const resource of resources) {\n const key = getResourceKey(resource)\n onResolving?.(resource, key)\n let entry: ResolvedResource\n\n if (resource.schema === undefined) {\n try {\n entry = {key, resource, ...(await fetchResourceSchema(resource))}\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new Error(`Failed to get the schema for \"${key}\": ${message}`, {cause: error})\n }\n } else {\n const schemaPath = isAbsolute(resource.schema)\n ? resource.schema\n : join(workDir, resource.schema)\n await assertExtractedSchemaFile(schemaPath, {key, schema: resource.schema})\n // Codegen reads the file again, so the generated output names it as its source, as it\n // does without resources.\n entry = {key, resource, schemaPath: resource.schema}\n }\n\n resolved.push(entry)\n onResolved?.(entry)\n }\n\n return resolved\n}\n\n/**\n * Generates one output file per resource, registering its types under the resource key.\n */\nexport async function generateResourceTypes(options: {\n /** Settings shared by every resource. */\n config: TypeGenConfig\n /** Returns the progress handler for one resource's generation. */\n onProgress?: (resolved: ResolvedResource) => ((event: TypegenProgressEvent) => void) | undefined\n resolved: ResolvedResource[]\n workDir: string\n}): Promise<{key: string; result: GenerationResult}[]> {\n const {config, onProgress, resolved, workDir} = options\n const results: {key: string; result: GenerationResult}[] = []\n\n for (const entry of resolved) {\n const {dataset, generates, path, projectId} = entry.resource\n let result: GenerationResult\n try {\n result = await runTypegenGenerate({\n config: {\n ...config,\n generates,\n path: path ?? config.path,\n schema: 'schemaPath' in entry ? entry.schemaPath : config.schema,\n },\n extractedSchema: 'schema' in entry ? entry.schema : undefined,\n onProgress: onProgress?.(entry),\n resource: {dataset, projectId},\n workDir,\n })\n } catch (error) {\n // Codegen writes a resource's file once its generation succeeds, so the files of this\n // resource and the ones after it are unchanged. Files of earlier resources are not\n // rolled back.\n const message = error instanceof Error ? error.message : String(error)\n const written = results.map(({key}) => `\"${key}\"`).join(', ')\n throw new Error(\n `Failed to generate types for \"${entry.key}\": ${message}` +\n (written\n ? `\\nTypes for ${written} were updated. The other output files are unchanged.`\n : ''),\n {cause: error},\n )\n }\n results.push({key: entry.key, result})\n }\n\n return results\n}\n\n/**\n * Checks that a local schema file exists and holds an extracted schema, which is a JSON array.\n */\nasync function assertExtractedSchemaFile(\n schemaPath: string,\n {key, schema}: {key: string; schema: string},\n): Promise<void> {\n let content: string\n try {\n content = await readFile(schemaPath, 'utf8')\n } catch {\n throw new Error(\n `Schema file not found for \"${key}\": ${schema}. Run \"sanity schema extract\" to create it.`,\n )\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(content)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new Error(`Schema file for \"${key}\" is not valid JSON: ${schema}. ${message}`, {\n cause: error,\n })\n }\n\n if (!Array.isArray(parsed)) {\n throw new TypeError(\n `Schema file for \"${key}\" is not an extracted schema: ${schema}. Run \"sanity schema extract\" to recreate it.`,\n )\n }\n}\n"],"names":["readFile","isAbsolute","join","runTypegenGenerate","fetchResourceSchema","getResourceKey","resolveResourceSchemas","options","onResolved","onResolving","resources","workDir","resolved","resource","key","entry","schema","undefined","error","message","Error","String","cause","schemaPath","assertExtractedSchemaFile","push","generateResourceTypes","config","onProgress","results","dataset","generates","path","projectId","result","extractedSchema","written","map","content","parsed","JSON","parse","Array","isArray","TypeError"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,mBAAkB;AACzC,SAAQC,UAAU,EAAEC,IAAI,QAAO,YAAW;AAG1C,SAEEC,kBAAkB,QAGb,kBAAiB;AAExB,SAA8BC,mBAAmB,QAAO,2BAA0B;AAClF,SAAQC,cAAc,QAAO,6BAA4B;AASzD;;;;;;CAMC,GACD,OAAO,eAAeC,uBAAuBC,OAO5C;IACC,MAAM,EAACC,UAAU,EAAEC,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAC,GAAGJ;IACtD,MAAMK,WAA+B,EAAE;IAEvC,KAAK,MAAMC,YAAYH,UAAW;QAChC,MAAMI,MAAMT,eAAeQ;QAC3BJ,cAAcI,UAAUC;QACxB,IAAIC;QAEJ,IAAIF,SAASG,MAAM,KAAKC,WAAW;YACjC,IAAI;gBACFF,QAAQ;oBAACD;oBAAKD;oBAAU,GAAI,MAAMT,oBAAoBS,SAAS;gBAAC;YAClE,EAAE,OAAOK,OAAO;gBACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;gBAChE,MAAM,IAAIE,MAAM,CAAC,8BAA8B,EAAEN,IAAI,GAAG,EAAEK,SAAS,EAAE;oBAACG,OAAOJ;gBAAK;YACpF;QACF,OAAO;YACL,MAAMK,aAAatB,WAAWY,SAASG,MAAM,IACzCH,SAASG,MAAM,GACfd,KAAKS,SAASE,SAASG,MAAM;YACjC,MAAMQ,0BAA0BD,YAAY;gBAACT;gBAAKE,QAAQH,SAASG,MAAM;YAAA;YACzE,sFAAsF;YACtF,0BAA0B;YAC1BD,QAAQ;gBAACD;gBAAKD;gBAAUU,YAAYV,SAASG,MAAM;YAAA;QACrD;QAEAJ,SAASa,IAAI,CAACV;QACdP,aAAaO;IACf;IAEA,OAAOH;AACT;AAEA;;CAEC,GACD,OAAO,eAAec,sBAAsBnB,OAO3C;IACC,MAAM,EAACoB,MAAM,EAAEC,UAAU,EAAEhB,QAAQ,EAAED,OAAO,EAAC,GAAGJ;IAChD,MAAMsB,UAAqD,EAAE;IAE7D,KAAK,MAAMd,SAASH,SAAU;QAC5B,MAAM,EAACkB,OAAO,EAAEC,SAAS,EAAEC,IAAI,EAAEC,SAAS,EAAC,GAAGlB,MAAMF,QAAQ;QAC5D,IAAIqB;QACJ,IAAI;YACFA,SAAS,MAAM/B,mBAAmB;gBAChCwB,QAAQ;oBACN,GAAGA,MAAM;oBACTI;oBACAC,MAAMA,QAAQL,OAAOK,IAAI;oBACzBhB,QAAQ,gBAAgBD,QAAQA,MAAMQ,UAAU,GAAGI,OAAOX,MAAM;gBAClE;gBACAmB,iBAAiB,YAAYpB,QAAQA,MAAMC,MAAM,GAAGC;gBACpDW,YAAYA,aAAab;gBACzBF,UAAU;oBAACiB;oBAASG;gBAAS;gBAC7BtB;YACF;QACF,EAAE,OAAOO,OAAO;YACd,sFAAsF;YACtF,mFAAmF;YACnF,eAAe;YACf,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;YAChE,MAAMkB,UAAUP,QAAQQ,GAAG,CAAC,CAAC,EAACvB,GAAG,EAAC,GAAK,CAAC,CAAC,EAAEA,IAAI,CAAC,CAAC,EAAEZ,IAAI,CAAC;YACxD,MAAM,IAAIkB,MACR,CAAC,8BAA8B,EAAEL,MAAMD,GAAG,CAAC,GAAG,EAAEK,SAAS,GACtDiB,CAAAA,UACG,CAAC,YAAY,EAAEA,QAAQ,oDAAoD,CAAC,GAC5E,EAAC,GACP;gBAACd,OAAOJ;YAAK;QAEjB;QACAW,QAAQJ,IAAI,CAAC;YAACX,KAAKC,MAAMD,GAAG;YAAEoB;QAAM;IACtC;IAEA,OAAOL;AACT;AAEA;;CAEC,GACD,eAAeL,0BACbD,UAAkB,EAClB,EAACT,GAAG,EAAEE,MAAM,EAAgC;IAE5C,IAAIsB;IACJ,IAAI;QACFA,UAAU,MAAMtC,SAASuB,YAAY;IACvC,EAAE,OAAM;QACN,MAAM,IAAIH,MACR,CAAC,2BAA2B,EAAEN,IAAI,GAAG,EAAEE,OAAO,2CAA2C,CAAC;IAE9F;IAEA,IAAIuB;IACJ,IAAI;QACFA,SAASC,KAAKC,KAAK,CAACH;IACtB,EAAE,OAAOpB,OAAO;QACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;QAChE,MAAM,IAAIE,MAAM,CAAC,iBAAiB,EAAEN,IAAI,qBAAqB,EAAEE,OAAO,EAAE,EAAEG,SAAS,EAAE;YACnFG,OAAOJ;QACT;IACF;IAEA,IAAI,CAACwB,MAAMC,OAAO,CAACJ,SAAS;QAC1B,MAAM,IAAIK,UACR,CAAC,iBAAiB,EAAE9B,IAAI,8BAA8B,EAAEE,OAAO,6CAA6C,CAAC;IAEjH;AACF"}
@@ -0,0 +1,92 @@
1
+ import { resolve } from 'node:path';
2
+ import { array, boolean, getDotPath, isValiError, minLength, nonEmpty, optional, parse, pipe, strictObject, string, union } from 'valibot';
3
+ import { parseTypegenConfig } from './parseTypegenConfig.js';
4
+ const requiredString = pipe(string(), nonEmpty('Must not be empty'));
5
+ const resourcesDefinition = pipe(array(// Strict, so a misspelled `schema` fails instead of silently fetching the remote schema.
6
+ strictObject({
7
+ dataset: requiredString,
8
+ enforceRequiredFields: optional(boolean()),
9
+ generates: requiredString,
10
+ path: optional(union([
11
+ string(),
12
+ array(string())
13
+ ])),
14
+ projectId: requiredString,
15
+ schema: optional(requiredString)
16
+ })), minLength(1, 'List at least one resource, or remove `resources`'));
17
+ /**
18
+ * The key a resource's types are registered under, matching the SDK runtime.
19
+ */ export function getResourceKey(resource) {
20
+ return `${resource.projectId}.${resource.dataset}`;
21
+ }
22
+ /**
23
+ * Validates `typegen.resources` and resolves the settings shared by every resource.
24
+ *
25
+ * Returns `undefined` when `resources` is not set, so callers keep the single-schema flow.
26
+ * `overloadClientMethods` defaults to `false` here: with more than one resource the flat query
27
+ * map conflicts across files, and App SDK apps under pnpm cannot resolve `@sanity/client` for it.
28
+ *
29
+ * @param workDir - The project root that `generates` paths are relative to.
30
+ */ export function parseTypegenResources(typegen, workDir) {
31
+ if (typegen?.resources === undefined) return undefined;
32
+ let resources;
33
+ try {
34
+ resources = parse(resourcesDefinition, typegen.resources);
35
+ } catch (error) {
36
+ if (isValiError(error)) {
37
+ const issues = error.issues.map((issue)=>{
38
+ const path = getDotPath(issue);
39
+ return ` resources${path ? `.${path}` : ''}: ${issue.message}`;
40
+ });
41
+ throw new TypeError(`Error in typegen config\n${issues.join('\n')}`, {
42
+ cause: error
43
+ });
44
+ }
45
+ throw error;
46
+ }
47
+ const keys = new Set();
48
+ const outputs = new Map();
49
+ for (const resource of resources){
50
+ const key = getResourceKey(resource);
51
+ if (keys.has(key)) {
52
+ throw new TypeError(`Error in typegen config\n resources: "${key}" is listed more than once. Its types are registered under that key, so it can only have one entry.`);
53
+ }
54
+ keys.add(key);
55
+ // Case-insensitive, because two names that differ only in case are the same file on the
56
+ // default macOS and Windows file systems.
57
+ const output = resolve(workDir, resource.generates).toLowerCase();
58
+ const existing = outputs.get(output);
59
+ if (existing) {
60
+ throw new TypeError(`Error in typegen config\n resources: "${existing}" and "${key}" both generate "${resource.generates}". Each resource needs its own output file.`);
61
+ }
62
+ outputs.set(output, key);
63
+ }
64
+ const config = parseTypegenConfig({
65
+ ...typegen,
66
+ overloadClientMethods: typegen.overloadClientMethods ?? false
67
+ });
68
+ const warnings = [];
69
+ if (config.overloadClientMethods && resources.length > 1) {
70
+ warnings.push('typegen.overloadClientMethods is enabled with more than one resource. Every generated file adds to the same global query map, so a query whose result differs between datasets fails to compile with TS2717.');
71
+ }
72
+ for (const field of [
73
+ 'schema',
74
+ 'generates'
75
+ ]){
76
+ if (typegen[field] !== undefined) {
77
+ warnings.push(`typegen.${field} is not used when typegen.resources is set. Each resource sets its own.`);
78
+ }
79
+ }
80
+ for (const resource of resources){
81
+ if (resource.enforceRequiredFields !== undefined && resource.schema !== undefined) {
82
+ warnings.push(`typegen.resources: enforceRequiredFields has no effect for "${getResourceKey(resource)}", which uses a local schema file. Pass --enforce-required-fields to "sanity schema extract" instead.`);
83
+ }
84
+ }
85
+ return {
86
+ config,
87
+ resources,
88
+ warnings
89
+ };
90
+ }
91
+
92
+ //# sourceMappingURL=parseTypegenResources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/typegen/parseTypegenResources.ts"],"sourcesContent":["import {resolve} from 'node:path'\n\nimport {type CliConfig} from '@sanity/cli-core'\nimport {type TypeGenResource} from '@sanity/cli-core/types'\nimport {type TypeGenConfig} from '@sanity/codegen'\nimport {\n array,\n boolean,\n getDotPath,\n isValiError,\n minLength,\n nonEmpty,\n optional,\n parse,\n pipe,\n strictObject,\n string,\n union,\n} from 'valibot'\n\nimport {parseTypegenConfig} from './parseTypegenConfig.js'\n\nconst requiredString = pipe(string(), nonEmpty('Must not be empty'))\n\nconst resourcesDefinition = pipe(\n array(\n // Strict, so a misspelled `schema` fails instead of silently fetching the remote schema.\n strictObject({\n dataset: requiredString,\n enforceRequiredFields: optional(boolean()),\n generates: requiredString,\n path: optional(union([string(), array(string())])),\n projectId: requiredString,\n schema: optional(requiredString),\n }),\n ),\n minLength(1, 'List at least one resource, or remove `resources`'),\n)\n\n/**\n * Typegen settings for generating types per resource.\n */\nexport interface TypegenResourcesConfig {\n /** Settings shared by every resource. `schema` and `generates` are unused. */\n config: TypeGenConfig\n resources: TypeGenResource[]\n /** Valid configuration that is likely to produce types that do not compile. */\n warnings: string[]\n}\n\n/**\n * The key a resource's types are registered under, matching the SDK runtime.\n */\nexport function getResourceKey(resource: Pick<TypeGenResource, 'dataset' | 'projectId'>): string {\n return `${resource.projectId}.${resource.dataset}`\n}\n\n/**\n * Validates `typegen.resources` and resolves the settings shared by every resource.\n *\n * Returns `undefined` when `resources` is not set, so callers keep the single-schema flow.\n * `overloadClientMethods` defaults to `false` here: with more than one resource the flat query\n * map conflicts across files, and App SDK apps under pnpm cannot resolve `@sanity/client` for it.\n *\n * @param workDir - The project root that `generates` paths are relative to.\n */\nexport function parseTypegenResources(\n typegen: CliConfig['typegen'],\n workDir: string,\n): TypegenResourcesConfig | undefined {\n if (typegen?.resources === undefined) return undefined\n\n let resources: TypeGenResource[]\n try {\n resources = parse(resourcesDefinition, typegen.resources)\n } catch (error) {\n if (isValiError(error)) {\n const issues = error.issues.map((issue) => {\n const path = getDotPath(issue)\n return ` resources${path ? `.${path}` : ''}: ${issue.message}`\n })\n throw new TypeError(`Error in typegen config\\n${issues.join('\\n')}`, {cause: error})\n }\n throw error\n }\n\n const keys = new Set<string>()\n const outputs = new Map<string, string>()\n for (const resource of resources) {\n const key = getResourceKey(resource)\n if (keys.has(key)) {\n throw new TypeError(\n `Error in typegen config\\n resources: \"${key}\" is listed more than once. Its types are registered under that key, so it can only have one entry.`,\n )\n }\n keys.add(key)\n\n // Case-insensitive, because two names that differ only in case are the same file on the\n // default macOS and Windows file systems.\n const output = resolve(workDir, resource.generates).toLowerCase()\n const existing = outputs.get(output)\n if (existing) {\n throw new TypeError(\n `Error in typegen config\\n resources: \"${existing}\" and \"${key}\" both generate \"${resource.generates}\". Each resource needs its own output file.`,\n )\n }\n outputs.set(output, key)\n }\n\n const config = parseTypegenConfig({\n ...typegen,\n overloadClientMethods: typegen.overloadClientMethods ?? false,\n })\n\n const warnings: string[] = []\n if (config.overloadClientMethods && resources.length > 1) {\n warnings.push(\n 'typegen.overloadClientMethods is enabled with more than one resource. Every generated file adds to the same global query map, so a query whose result differs between datasets fails to compile with TS2717.',\n )\n }\n for (const field of ['schema', 'generates'] as const) {\n if (typegen[field] !== undefined) {\n warnings.push(\n `typegen.${field} is not used when typegen.resources is set. Each resource sets its own.`,\n )\n }\n }\n for (const resource of resources) {\n if (resource.enforceRequiredFields !== undefined && resource.schema !== undefined) {\n warnings.push(\n `typegen.resources: enforceRequiredFields has no effect for \"${getResourceKey(resource)}\", which uses a local schema file. Pass --enforce-required-fields to \"sanity schema extract\" instead.`,\n )\n }\n }\n\n return {config, resources, warnings}\n}\n"],"names":["resolve","array","boolean","getDotPath","isValiError","minLength","nonEmpty","optional","parse","pipe","strictObject","string","union","parseTypegenConfig","requiredString","resourcesDefinition","dataset","enforceRequiredFields","generates","path","projectId","schema","getResourceKey","resource","parseTypegenResources","typegen","workDir","resources","undefined","error","issues","map","issue","message","TypeError","join","cause","keys","Set","outputs","Map","key","has","add","output","toLowerCase","existing","get","set","config","overloadClientMethods","warnings","length","push","field"],"mappings":"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"}
@@ -7,7 +7,10 @@ import { spinner } from '@sanity/cli-core/ux';
7
7
  import { readConfig, runTypegenGenerate, runTypegenWatcher, TypegenWatchModeTrace, TypesGeneratedTrace } from '@sanity/codegen';
8
8
  import omit from 'lodash-es/omit.js';
9
9
  import once from 'lodash-es/once.js';
10
+ import { formatPath } from '../../actions/typegen/formatPath.js';
11
+ import { generateResourceTypes, resolveResourceSchemas } from '../../actions/typegen/generateResourceTypes.js';
10
12
  import { parseTypegenConfig } from '../../actions/typegen/parseTypegenConfig.js';
13
+ import { parseTypegenResources } from '../../actions/typegen/parseTypegenResources.js';
11
14
  import { createTypegenProgressRenderer } from '../../actions/typegen/renderTypegenProgress.js';
12
15
  const description = `Sanity TypeGen
13
16
 
@@ -26,7 +29,8 @@ This command can utilize configuration settings defined in a \`sanity-typegen.js
26
29
  The 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.
27
30
 
28
31
  ${styleText('bold', 'Note:')}
29
- - 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.`.trim();
32
+ - 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.
33
+ - To generate types for several datasets, list them in \`typegen.resources\` in \`sanity.cli.ts\` (beta). Each resource uses its own \`schema\` file, or the schema bound to its dataset when \`schema\` is omitted.`.trim();
30
34
  export class TypegenGenerateCommand extends SanityCommand {
31
35
  static description = description;
32
36
  static examples = [
@@ -87,9 +91,11 @@ export class TypegenGenerateCommand extends SanityCommand {
87
91
 
88
92
  The config from the Sanity CLI config is used.
89
93
  `));
94
+ const resources = parseTypegenResources(config.typegen, workDir);
90
95
  return {
91
- config: parseTypegenConfig(config.typegen || {}),
96
+ config: resources?.config ?? parseTypegenConfig(config.typegen || {}),
92
97
  path: rootDir.path,
98
+ resources,
93
99
  type: 'cli',
94
100
  workDir
95
101
  };
@@ -105,10 +111,12 @@ export class TypegenGenerateCommand extends SanityCommand {
105
111
  workDir
106
112
  };
107
113
  }
114
+ const resources = parseTypegenResources(config.typegen, workDir);
108
115
  spin.succeed(`Config loaded from sanity.cli.ts`);
109
116
  return {
110
- config: parseTypegenConfig(config.typegen || {}),
117
+ config: resources?.config ?? parseTypegenConfig(config.typegen || {}),
111
118
  path: rootDir.path,
119
+ resources,
112
120
  type: 'cli',
113
121
  workDir
114
122
  };
@@ -127,8 +135,47 @@ export class TypegenGenerateCommand extends SanityCommand {
127
135
  const trace = this.telemetry.trace(TypesGeneratedTrace);
128
136
  let spin;
129
137
  try {
130
- const { config: typegenConfig, type: typegenConfigMethod, workDir } = await this.getConfig();
138
+ const { config: typegenConfig, resources, type: typegenConfigMethod, workDir } = await this.getConfig();
131
139
  trace.start();
140
+ if (resources) {
141
+ for (const warning of resources.warnings){
142
+ this.output.warn(warning);
143
+ }
144
+ const resourceSpin = spinner({});
145
+ spin = resourceSpin;
146
+ const resolved = await resolveResourceSchemas({
147
+ onResolved: (entry)=>{
148
+ resourceSpin.succeed('schemaPath' in entry ? `Using ${formatPath(entry.schemaPath)} for ${entry.key}` : `Fetched the schema bound to ${entry.key} (${entry.schemaVersion})`);
149
+ },
150
+ onResolving: (resource, key)=>{
151
+ resourceSpin.start(resource.schema === undefined ? `Fetching the schema bound to ${key}…` : `Checking the schema file for ${key}…`);
152
+ },
153
+ resources: resources.resources,
154
+ workDir
155
+ });
156
+ const results = await generateResourceTypes({
157
+ config: typegenConfig,
158
+ onProgress: (entry)=>{
159
+ resourceSpin.start(`Generating types for ${entry.key}…`);
160
+ return createTypegenProgressRenderer(resourceSpin, {
161
+ formatGeneratedCode: typegenConfig.formatGeneratedCode,
162
+ generates: entry.resource.generates,
163
+ schema: 'schemaPath' in entry ? entry.schemaPath : entry.key
164
+ });
165
+ },
166
+ resolved,
167
+ workDir
168
+ });
169
+ for (const { result } of results){
170
+ trace.log({
171
+ configMethod: typegenConfigMethod,
172
+ configOverloadClientMethods: typegenConfig.overloadClientMethods,
173
+ ...omit(result, 'code', 'duration')
174
+ });
175
+ }
176
+ trace.complete();
177
+ return;
178
+ }
132
179
  spin = spinner({}).start('Loading schema…');
133
180
  const result = await runTypegenGenerate({
134
181
  config: typegenConfig,
@@ -160,7 +207,12 @@ export class TypegenGenerateCommand extends SanityCommand {
160
207
  const trace = this.telemetry.trace(TypegenWatchModeTrace);
161
208
  let spin;
162
209
  try {
163
- const { config: typegenConfig, workDir } = await this.getConfig();
210
+ const { config: typegenConfig, resources, workDir } = await this.getConfig();
211
+ if (resources) {
212
+ this.error('Watch mode does not support typegen.resources yet. Run "sanity typegen generate" without --watch.', {
213
+ exit: exitCodes.USAGE_ERROR
214
+ });
215
+ }
164
216
  trace.start();
165
217
  let resolve = ()=>{};
166
218
  const promise = new Promise((res)=>{
@@ -213,6 +265,8 @@ export class TypegenGenerateCommand extends SanityCommand {
213
265
  spin.fail();
214
266
  }
215
267
  trace.error(error instanceof Error ? error : new Error(String(error)));
268
+ // Errors already reported with `this.error()` keep their own exit code.
269
+ if (error instanceof CLIError) throw error;
216
270
  this.error(`${error instanceof Error ? error.message : 'Unknown error'}`, {
217
271
  exit: exitCodes.RUNTIME_ERROR
218
272
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/typegen/generate.ts"],"sourcesContent":["import {stat} from 'node:fs/promises'\nimport {styleText} from 'node:util'\n\nimport {Flags} from '@oclif/core'\nimport {CLIError} from '@oclif/core/errors'\nimport {exitCodes, SanityCommand} from '@sanity/cli-core'\nimport {spinner, type SpinnerInstance} from '@sanity/cli-core/ux'\nimport {\n readConfig,\n runTypegenGenerate,\n runTypegenWatcher,\n type TypeGenConfig,\n TypegenWatchModeTrace,\n TypesGeneratedTrace,\n} from '@sanity/codegen'\nimport omit from 'lodash-es/omit.js'\nimport once from 'lodash-es/once.js'\n\nimport {parseTypegenConfig} from '../../actions/typegen/parseTypegenConfig.js'\nimport {createTypegenProgressRenderer} from '../../actions/typegen/renderTypegenProgress.js'\n\nconst description = `Sanity TypeGen\n\n${styleText('bold', 'Configuration:')}\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\n${styleText('bold', 'Note:')}\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.`.trim()\n\nexport class TypegenGenerateCommand extends SanityCommand<typeof TypegenGenerateCommand> {\n static override description = description\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: `Generate TypeScript type definitions from a Sanity Studio schema extracted using the \\`sanity schema extract\\` command.`,\n },\n ]\n\n static override flags = {\n 'config-path': Flags.string({\n description:\n '[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.',\n }),\n watch: Flags.boolean({\n default: false,\n description: '[Default: false] Run the typegen in watch mode',\n }),\n }\n\n static override hiddenAliases: string[] = ['typegen:generate']\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(TypegenGenerateCommand)\n\n if (flags.watch) {\n await this.runWatcher()\n return\n }\n\n await this.runSingle()\n }\n\n private async getConfig(): Promise<{\n config: TypeGenConfig\n path?: string\n type: 'cli' | 'legacy'\n workDir: string\n }> {\n const spin = spinner({}).start('Loading config…')\n\n try {\n const {flags} = await this.parse(TypegenGenerateCommand)\n const rootDir = await this.getProjectRoot()\n const config = await this.getCliConfig()\n\n const configPath = flags['config-path']\n const workDir = rootDir.directory\n\n const legacyConfigPath = configPath || 'sanity-typegen.json'\n let hasLegacyConfig = false\n\n try {\n const file = await stat(legacyConfigPath)\n hasLegacyConfig = file.isFile()\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ENOENT' && configPath) {\n spin.fail()\n this.error(`Typegen config file not found: ${configPath}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (err instanceof Error && 'code' in err && err.code !== 'ENOENT') {\n spin.fail()\n this.error(`Error when checking if typegen config file exists: ${legacyConfigPath}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n if (config?.typegen && hasLegacyConfig) {\n spin.warn(\n styleText(\n 'yellow',\n `You've specified typegen in your Sanity CLI config, but also have a typegen config.\n\n The config from the Sanity CLI config is used.\n `,\n ),\n )\n\n return {\n config: parseTypegenConfig(config.typegen || {}),\n path: rootDir.path,\n type: 'cli',\n workDir,\n }\n }\n\n if (hasLegacyConfig) {\n spin.warn(\n styleText(\n 'yellow',\n `The separate typegen config has been deprecated. Use \\`typegen\\` in the sanity CLI config instead.\n\n See: https://www.sanity.io/docs/help/configuring-typegen-in-sanity-cli-config`,\n ),\n )\n return {\n config: await readConfig(legacyConfigPath),\n path: legacyConfigPath,\n type: 'legacy',\n workDir,\n }\n }\n\n spin.succeed(`Config loaded from sanity.cli.ts`)\n\n return {\n config: parseTypegenConfig(config.typegen || {}),\n path: rootDir.path,\n type: 'cli',\n workDir,\n }\n } catch (err) {\n // The config-file checks above already reported a user-facing error via\n // `this.error()` (an oclif CLIError). Re-throw those as-is instead of\n // wrapping them a second time and failing the spinner twice.\n if (err instanceof CLIError) throw err\n spin.fail()\n this.error(`An error occurred during config loading: ${err}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async runSingle(): Promise<void> {\n const trace = this.telemetry.trace(TypesGeneratedTrace)\n let spin: SpinnerInstance | undefined\n\n try {\n const {config: typegenConfig, type: typegenConfigMethod, workDir} = await this.getConfig()\n trace.start()\n\n spin = spinner({}).start('Loading schema…')\n const result = await runTypegenGenerate({\n config: typegenConfig,\n onProgress: createTypegenProgressRenderer(spin, {\n formatGeneratedCode: typegenConfig.formatGeneratedCode,\n generates: typegenConfig.generates,\n schema: typegenConfig.schema,\n }),\n workDir,\n })\n\n const traceStats = omit(result, 'code', 'duration')\n\n trace.log({\n configMethod: typegenConfigMethod,\n configOverloadClientMethods: typegenConfig.overloadClientMethods,\n ...traceStats,\n })\n trace.complete()\n } catch (error) {\n if (spin?.isSpinning) {\n spin.fail()\n }\n trace.error(error instanceof Error ? error : new Error(String(error)))\n this.error(`${error instanceof Error ? error.message : 'Unknown error'}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async runWatcher(): Promise<void> {\n const trace = this.telemetry.trace(TypegenWatchModeTrace)\n let spin: SpinnerInstance | undefined\n\n try {\n const {config: typegenConfig, workDir} = await this.getConfig()\n trace.start()\n\n let resolve: () => void = () => {}\n const promise = new Promise<void>((res) => {\n resolve = res\n })\n\n const watchSpin = spinner({}).start('Loading schema…')\n spin = watchSpin\n const rendererContext = {\n formatGeneratedCode: typegenConfig.formatGeneratedCode,\n generates: typegenConfig.generates,\n schema: typegenConfig.schema,\n }\n let renderProgress = createTypegenProgressRenderer(watchSpin, rendererContext)\n\n const typegenWatcher = runTypegenWatcher({\n config: typegenConfig,\n onProgress: (event) => {\n // 'schemaLoaded' is the first event of every generation cycle; the\n // renderer accumulates per-run state, so start each cycle fresh.\n if (event.type === 'schemaLoaded') {\n renderProgress = createTypegenProgressRenderer(watchSpin, rendererContext)\n }\n renderProgress(event)\n },\n workDir,\n })\n\n const stop = once(async () => {\n process.off('SIGINT', stop)\n process.off('SIGTERM', stop)\n\n if (watchSpin.isSpinning) {\n watchSpin.stop()\n }\n\n trace.log({\n step: 'stopped',\n ...typegenWatcher.getStats(),\n })\n trace.complete()\n\n try {\n await typegenWatcher.stop()\n } catch {\n // We're shutting down; a failure to close the watcher shouldn't hang\n // the process or surface as an unhandled rejection.\n }\n resolve()\n })\n\n process.on('SIGINT', stop)\n process.on('SIGTERM', stop)\n\n await promise\n } catch (error) {\n if (spin?.isSpinning) {\n spin.fail()\n }\n trace.error(error instanceof Error ? error : new Error(String(error)))\n this.error(`${error instanceof Error ? error.message : 'Unknown error'}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n}\n"],"names":["stat","styleText","Flags","CLIError","exitCodes","SanityCommand","spinner","readConfig","runTypegenGenerate","runTypegenWatcher","TypegenWatchModeTrace","TypesGeneratedTrace","omit","once","parseTypegenConfig","createTypegenProgressRenderer","description","trim","TypegenGenerateCommand","examples","command","flags","string","watch","boolean","default","hiddenAliases","run","parse","runWatcher","runSingle","getConfig","spin","start","rootDir","getProjectRoot","config","getCliConfig","configPath","workDir","directory","legacyConfigPath","hasLegacyConfig","file","isFile","err","Error","code","fail","error","exit","RUNTIME_ERROR","typegen","warn","path","type","succeed","trace","telemetry","typegenConfig","typegenConfigMethod","result","onProgress","formatGeneratedCode","generates","schema","traceStats","log","configMethod","configOverloadClientMethods","overloadClientMethods","complete","isSpinning","String","message","resolve","promise","Promise","res","watchSpin","rendererContext","renderProgress","typegenWatcher","event","stop","process","off","step","getStats","on"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/typegen/generate.ts"],"sourcesContent":["import {stat} from 'node:fs/promises'\nimport {styleText} from 'node:util'\n\nimport {Flags} from '@oclif/core'\nimport {CLIError} from '@oclif/core/errors'\nimport {exitCodes, SanityCommand} from '@sanity/cli-core'\nimport {spinner, type SpinnerInstance} from '@sanity/cli-core/ux'\nimport {\n readConfig,\n runTypegenGenerate,\n runTypegenWatcher,\n type TypeGenConfig,\n TypegenWatchModeTrace,\n TypesGeneratedTrace,\n} from '@sanity/codegen'\nimport omit from 'lodash-es/omit.js'\nimport once from 'lodash-es/once.js'\n\nimport {formatPath} from '../../actions/typegen/formatPath.js'\nimport {\n generateResourceTypes,\n resolveResourceSchemas,\n} from '../../actions/typegen/generateResourceTypes.js'\nimport {parseTypegenConfig} from '../../actions/typegen/parseTypegenConfig.js'\nimport {\n parseTypegenResources,\n type TypegenResourcesConfig,\n} from '../../actions/typegen/parseTypegenResources.js'\nimport {createTypegenProgressRenderer} from '../../actions/typegen/renderTypegenProgress.js'\n\nconst description = `Sanity TypeGen\n\n${styleText('bold', 'Configuration:')}\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\n${styleText('bold', 'Note:')}\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- To generate types for several datasets, list them in \\`typegen.resources\\` in \\`sanity.cli.ts\\` (beta). Each resource uses its own \\`schema\\` file, or the schema bound to its dataset when \\`schema\\` is omitted.`.trim()\n\nexport class TypegenGenerateCommand extends SanityCommand<typeof TypegenGenerateCommand> {\n static override description = description\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: `Generate TypeScript type definitions from a Sanity Studio schema extracted using the \\`sanity schema extract\\` command.`,\n },\n ]\n\n static override flags = {\n 'config-path': Flags.string({\n description:\n '[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.',\n }),\n watch: Flags.boolean({\n default: false,\n description: '[Default: false] Run the typegen in watch mode',\n }),\n }\n\n static override hiddenAliases: string[] = ['typegen:generate']\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(TypegenGenerateCommand)\n\n if (flags.watch) {\n await this.runWatcher()\n return\n }\n\n await this.runSingle()\n }\n\n private async getConfig(): Promise<{\n config: TypeGenConfig\n path?: string\n resources?: TypegenResourcesConfig\n type: 'cli' | 'legacy'\n workDir: string\n }> {\n const spin = spinner({}).start('Loading config…')\n\n try {\n const {flags} = await this.parse(TypegenGenerateCommand)\n const rootDir = await this.getProjectRoot()\n const config = await this.getCliConfig()\n\n const configPath = flags['config-path']\n const workDir = rootDir.directory\n\n const legacyConfigPath = configPath || 'sanity-typegen.json'\n let hasLegacyConfig = false\n\n try {\n const file = await stat(legacyConfigPath)\n hasLegacyConfig = file.isFile()\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ENOENT' && configPath) {\n spin.fail()\n this.error(`Typegen config file not found: ${configPath}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (err instanceof Error && 'code' in err && err.code !== 'ENOENT') {\n spin.fail()\n this.error(`Error when checking if typegen config file exists: ${legacyConfigPath}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n if (config?.typegen && hasLegacyConfig) {\n spin.warn(\n styleText(\n 'yellow',\n `You've specified typegen in your Sanity CLI config, but also have a typegen config.\n\n The config from the Sanity CLI config is used.\n `,\n ),\n )\n\n const resources = parseTypegenResources(config.typegen, workDir)\n return {\n config: resources?.config ?? parseTypegenConfig(config.typegen || {}),\n path: rootDir.path,\n resources,\n type: 'cli',\n workDir,\n }\n }\n\n if (hasLegacyConfig) {\n spin.warn(\n styleText(\n 'yellow',\n `The separate typegen config has been deprecated. Use \\`typegen\\` in the sanity CLI config instead.\n\n See: https://www.sanity.io/docs/help/configuring-typegen-in-sanity-cli-config`,\n ),\n )\n return {\n config: await readConfig(legacyConfigPath),\n path: legacyConfigPath,\n type: 'legacy',\n workDir,\n }\n }\n\n const resources = parseTypegenResources(config.typegen, workDir)\n spin.succeed(`Config loaded from sanity.cli.ts`)\n\n return {\n config: resources?.config ?? parseTypegenConfig(config.typegen || {}),\n path: rootDir.path,\n resources,\n type: 'cli',\n workDir,\n }\n } catch (err) {\n // The config-file checks above already reported a user-facing error via\n // `this.error()` (an oclif CLIError). Re-throw those as-is instead of\n // wrapping them a second time and failing the spinner twice.\n if (err instanceof CLIError) throw err\n spin.fail()\n this.error(`An error occurred during config loading: ${err}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async runSingle(): Promise<void> {\n const trace = this.telemetry.trace(TypesGeneratedTrace)\n let spin: SpinnerInstance | undefined\n\n try {\n const {\n config: typegenConfig,\n resources,\n type: typegenConfigMethod,\n workDir,\n } = await this.getConfig()\n trace.start()\n\n if (resources) {\n for (const warning of resources.warnings) {\n this.output.warn(warning)\n }\n\n const resourceSpin = spinner({})\n spin = resourceSpin\n const resolved = await resolveResourceSchemas({\n onResolved: (entry) => {\n resourceSpin.succeed(\n 'schemaPath' in entry\n ? `Using ${formatPath(entry.schemaPath)} for ${entry.key}`\n : `Fetched the schema bound to ${entry.key} (${entry.schemaVersion})`,\n )\n },\n onResolving: (resource, key) => {\n resourceSpin.start(\n resource.schema === undefined\n ? `Fetching the schema bound to ${key}…`\n : `Checking the schema file for ${key}…`,\n )\n },\n resources: resources.resources,\n workDir,\n })\n\n const results = await generateResourceTypes({\n config: typegenConfig,\n onProgress: (entry) => {\n resourceSpin.start(`Generating types for ${entry.key}…`)\n return createTypegenProgressRenderer(resourceSpin, {\n formatGeneratedCode: typegenConfig.formatGeneratedCode,\n generates: entry.resource.generates,\n schema: 'schemaPath' in entry ? entry.schemaPath : entry.key,\n })\n },\n resolved,\n workDir,\n })\n\n for (const {result} of results) {\n trace.log({\n configMethod: typegenConfigMethod,\n configOverloadClientMethods: typegenConfig.overloadClientMethods,\n ...omit(result, 'code', 'duration'),\n })\n }\n trace.complete()\n return\n }\n\n spin = spinner({}).start('Loading schema…')\n const result = await runTypegenGenerate({\n config: typegenConfig,\n onProgress: createTypegenProgressRenderer(spin, {\n formatGeneratedCode: typegenConfig.formatGeneratedCode,\n generates: typegenConfig.generates,\n schema: typegenConfig.schema,\n }),\n workDir,\n })\n\n const traceStats = omit(result, 'code', 'duration')\n\n trace.log({\n configMethod: typegenConfigMethod,\n configOverloadClientMethods: typegenConfig.overloadClientMethods,\n ...traceStats,\n })\n trace.complete()\n } catch (error) {\n if (spin?.isSpinning) {\n spin.fail()\n }\n trace.error(error instanceof Error ? error : new Error(String(error)))\n this.error(`${error instanceof Error ? error.message : 'Unknown error'}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async runWatcher(): Promise<void> {\n const trace = this.telemetry.trace(TypegenWatchModeTrace)\n let spin: SpinnerInstance | undefined\n\n try {\n const {config: typegenConfig, resources, workDir} = await this.getConfig()\n if (resources) {\n this.error(\n 'Watch mode does not support typegen.resources yet. Run \"sanity typegen generate\" without --watch.',\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n trace.start()\n\n let resolve: () => void = () => {}\n const promise = new Promise<void>((res) => {\n resolve = res\n })\n\n const watchSpin = spinner({}).start('Loading schema…')\n spin = watchSpin\n const rendererContext = {\n formatGeneratedCode: typegenConfig.formatGeneratedCode,\n generates: typegenConfig.generates,\n schema: typegenConfig.schema,\n }\n let renderProgress = createTypegenProgressRenderer(watchSpin, rendererContext)\n\n const typegenWatcher = runTypegenWatcher({\n config: typegenConfig,\n onProgress: (event) => {\n // 'schemaLoaded' is the first event of every generation cycle; the\n // renderer accumulates per-run state, so start each cycle fresh.\n if (event.type === 'schemaLoaded') {\n renderProgress = createTypegenProgressRenderer(watchSpin, rendererContext)\n }\n renderProgress(event)\n },\n workDir,\n })\n\n const stop = once(async () => {\n process.off('SIGINT', stop)\n process.off('SIGTERM', stop)\n\n if (watchSpin.isSpinning) {\n watchSpin.stop()\n }\n\n trace.log({\n step: 'stopped',\n ...typegenWatcher.getStats(),\n })\n trace.complete()\n\n try {\n await typegenWatcher.stop()\n } catch {\n // We're shutting down; a failure to close the watcher shouldn't hang\n // the process or surface as an unhandled rejection.\n }\n resolve()\n })\n\n process.on('SIGINT', stop)\n process.on('SIGTERM', stop)\n\n await promise\n } catch (error) {\n if (spin?.isSpinning) {\n spin.fail()\n }\n trace.error(error instanceof Error ? error : new Error(String(error)))\n // Errors already reported with `this.error()` keep their own exit code.\n if (error instanceof CLIError) throw error\n this.error(`${error instanceof Error ? error.message : 'Unknown error'}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n}\n"],"names":["stat","styleText","Flags","CLIError","exitCodes","SanityCommand","spinner","readConfig","runTypegenGenerate","runTypegenWatcher","TypegenWatchModeTrace","TypesGeneratedTrace","omit","once","formatPath","generateResourceTypes","resolveResourceSchemas","parseTypegenConfig","parseTypegenResources","createTypegenProgressRenderer","description","trim","TypegenGenerateCommand","examples","command","flags","string","watch","boolean","default","hiddenAliases","run","parse","runWatcher","runSingle","getConfig","spin","start","rootDir","getProjectRoot","config","getCliConfig","configPath","workDir","directory","legacyConfigPath","hasLegacyConfig","file","isFile","err","Error","code","fail","error","exit","RUNTIME_ERROR","typegen","warn","resources","path","type","succeed","trace","telemetry","typegenConfig","typegenConfigMethod","warning","warnings","output","resourceSpin","resolved","onResolved","entry","schemaPath","key","schemaVersion","onResolving","resource","schema","undefined","results","onProgress","formatGeneratedCode","generates","result","log","configMethod","configOverloadClientMethods","overloadClientMethods","complete","traceStats","isSpinning","String","message","USAGE_ERROR","resolve","promise","Promise","res","watchSpin","rendererContext","renderProgress","typegenWatcher","event","stop","process","off","step","getStats","on"],"mappings":"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"}
@@ -33,6 +33,16 @@ import { toForwardSlashes } from '../../util/toForwardSlashes.js';
33
33
  * @internal
34
34
  */ export function sanityTypegenPlugin(options) {
35
35
  const { config: inputConfig, output = console, telemetryLogger, workDir } = options;
36
+ // Generating per resource is not supported here yet. Without this check the plugin would
37
+ // generate from the top-level `schema`, which a resources config does not use.
38
+ if (inputConfig.resources !== undefined) {
39
+ return {
40
+ configResolved () {
41
+ output.log(logSymbols.warning, 'Typegen during "sanity dev" does not support typegen.resources yet. Run "sanity typegen generate" instead.');
42
+ },
43
+ name: 'sanity/typegen'
44
+ };
45
+ }
36
46
  // Apply defaults through the same schema as `sanity typegen generate`,
37
47
  // so watch mode and manual generation produce identical output
38
48
  const config = parseTypegenConfig(inputConfig);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/server/vite/plugin-typegen.ts"],"sourcesContent":["import {existsSync} from 'node:fs'\nimport path from 'node:path'\n\nimport {CLITelemetryStore} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\nimport {\n type GenerationResult,\n runTypegenGenerate,\n type TypeGenConfig,\n TypegenWatchModeTrace,\n TypesGeneratedTrace,\n} from '@sanity/codegen'\nimport debounce from 'lodash-es/debounce.js'\nimport mean from 'lodash-es/mean.js'\nimport once from 'lodash-es/once.js'\nimport picomatch from 'picomatch'\nimport {type Plugin} from 'vite'\n\nimport {parseTypegenConfig} from '../../actions/typegen/parseTypegenConfig.js'\nimport {toForwardSlashes} from '../../util/toForwardSlashes.js'\n\n/** Default debounce delay in milliseconds */\nconst DEFAULT_DEBOUNCE_MS = 1000\n\n/**\n * Delay before initial generation to allow Vite to finish startup\n * and avoid race conditions with module resolution.\n */\nconst INITIAL_GENERATION_DELAY_MS = 1000\n\n/**\n * Options for the Sanity typegen Vite plugin.\n *\n * @internal\n */\ninterface TypegenPluginOptions {\n /**\n * Typegen configuration from sanity.cli.ts.\n * All fields are optional and will use sensible defaults.\n */\n config: Partial<TypeGenConfig>\n\n /**\n * Working directory containing the Sanity configuration.\n * This should be the root of your Sanity Studio project.\n */\n workDir: string\n\n /**\n * Logger for output messages. Must implement `log`, `info`, and `error` methods.\n * @defaultValue `console`\n */\n output?: Pick<Console, 'error' | 'info' | 'log'>\n\n /**\n * Telemetry logger for the Sanity CLI tooling.\n */\n telemetryLogger?: CLITelemetryStore\n}\n\n/**\n * Creates a Vite plugin that automatically generates TypeScript types during development and build.\n *\n * **During development:**\n * The plugin performs an initial generation when the dev server starts, then watches\n * for file changes and re-generates types when relevant files are modified.\n *\n * **During build:**\n * The plugin generates types once at the end of the build process.\n *\n * **Prerequisites:**\n * The schema.json file must exist before typegen can run. Run `sanity schema extract`\n * first to generate the schema file.\n *\n * @param options - Configuration options for the plugin\n * @returns A Vite plugin configured for typegen\n *\n * @internal\n */\nexport function sanityTypegenPlugin(options: TypegenPluginOptions): Plugin {\n const {config: inputConfig, output = console, telemetryLogger, workDir} = options\n\n // Apply defaults through the same schema as `sanity typegen generate`,\n // so watch mode and manual generation produce identical output\n const config: TypeGenConfig = parseTypegenConfig(inputConfig)\n\n // Build query patterns from config\n const queryPatterns = Array.isArray(config.path) ? config.path : [config.path]\n\n // Resolved after Vite config is available\n let resolvedSchemaPath: string\n\n // State for concurrency control\n let isGenerating = false\n let pendingGeneration = false\n\n // Stats for telemetry\n const startTime = Date.now()\n const stats: {failedCount: number; successfulDurations: number[]} = {\n failedCount: 0,\n successfulDurations: [],\n }\n\n /**\n * Runs type generation with concurrency control.\n * If generation is already running, queues one more generation to run after completion.\n * Returns the generation result, or null if generation was skipped or failed.\n */\n async function runGeneration(isBuilding = false): Promise<GenerationResult | null> {\n if (isGenerating) {\n pendingGeneration = true\n return null\n }\n\n isGenerating = true\n pendingGeneration = false\n\n const generationStartTime = Date.now()\n\n try {\n // Validate schema.json exists\n if (!existsSync(resolvedSchemaPath)) {\n output.error(\n `${logSymbols.error} Schema file not found: ${config.schema}\\n` +\n `Run \"sanity schema extract\" first to generate the schema file.`,\n )\n return null\n }\n\n const result = await runTypegenGenerate({\n config,\n workDir,\n })\n\n if (isBuilding) {\n // Add newline for better formatting in build output\n output.log('')\n }\n\n if (result.filesWithErrors > 0) {\n output.log(\n logSymbols.warning,\n `Generated types to ${config.generates} (with errors in ${result.filesWithErrors} file${result.filesWithErrors === 1 ? '' : 's'})`,\n )\n } else {\n output.log(logSymbols.success, `Generated types to ${config.generates}`)\n }\n\n // Track stats for telemetry (all completed generations count as successful)\n stats.successfulDurations.push(Date.now() - generationStartTime)\n\n return result\n } catch (err) {\n output.error(\n `${logSymbols.error} Generation failed: ${err instanceof Error ? err.message : String(err)}`,\n )\n stats.failedCount++\n return null\n } finally {\n isGenerating = false\n\n // If a change came in during generation, run again\n if (pendingGeneration) {\n pendingGeneration = false\n void runGeneration()\n }\n }\n }\n\n const debouncedGenerate = debounce(() => {\n void runGeneration()\n }, DEFAULT_DEBOUNCE_MS)\n\n // Create a matcher function from query patterns\n const isQueryMatch = picomatch(queryPatterns)\n\n return {\n name: 'sanity/typegen',\n\n configResolved() {\n const rootDir = workDir\n\n resolvedSchemaPath = path.isAbsolute(config.schema)\n ? config.schema\n : path.join(rootDir, config.schema)\n },\n\n configureServer(server) {\n const trace = telemetryLogger?.trace(TypegenWatchModeTrace)\n trace?.start()\n trace?.log({step: 'started'})\n\n // Build absolute patterns for query files\n const absoluteQueryPatterns = queryPatterns.map((pattern) =>\n path.isAbsolute(pattern) ? pattern : path.join(workDir, pattern),\n )\n\n // Add query patterns AND schema.json to Vite's watcher\n server.watcher.add([...absoluteQueryPatterns, resolvedSchemaPath])\n\n // Listen for file changes\n const handleChange = (filePath: string) => {\n const relativePath = path.isAbsolute(filePath) ? path.relative(workDir, filePath) : filePath\n // Normalize to forward slashes for cross-platform picomatch compatibility\n const normalizedPath = toForwardSlashes(relativePath)\n\n // Trigger on schema.json change OR matching query file\n if (filePath === resolvedSchemaPath || isQueryMatch(normalizedPath)) {\n debouncedGenerate()\n }\n }\n\n // Prepare function to log \"stopped\" event to trace and complete the trace\n const onClose = once(() => {\n // Cancel any pending debounced extractions\n debouncedGenerate.cancel()\n\n if (trace) {\n trace.log({\n averageGenerationDuration: mean(stats.successfulDurations) || 0,\n generationFailedCount: stats.failedCount,\n generationSuccessfulCount: stats.successfulDurations.length,\n step: 'stopped',\n watcherDuration: Date.now() - startTime,\n })\n trace.complete()\n }\n\n // Clean up process listeners (must always run, not just when trace exists)\n process.off('SIGTERM', onClose)\n process.off('SIGINT', onClose)\n })\n\n server.watcher.on('change', handleChange)\n server.watcher.on('add', handleChange)\n server.watcher.on('unlink', handleChange)\n\n // Call the onClose method when watcher is closed or when process is stopped/killed\n server.watcher.on('close', onClose)\n process.on('SIGTERM', onClose)\n process.on('SIGINT', onClose)\n\n // Run initial generation after server is ready\n const startGeneration = () => {\n setTimeout(() => {\n // Notify about typegen enabled\n output.info(logSymbols.info, 'Typegen enabled. Watching:')\n for (const pattern of queryPatterns) {\n output.info(` - ${pattern}`)\n }\n output.info(` - ${config.schema} (schema)`)\n\n // Perform first generation\n void runGeneration()\n }, INITIAL_GENERATION_DELAY_MS)\n }\n\n if (server.httpServer) {\n server.httpServer.once('listening', startGeneration)\n } else {\n // Middleware mode - no HTTP server, run generation immediately\n startGeneration()\n }\n },\n\n async buildEnd() {\n // Build mode: One-time generation with telemetry tracking\n const result = await runGeneration(true)\n\n // Only log telemetry if generation completed successfully\n if (result && telemetryLogger) {\n const trace = telemetryLogger.trace(TypesGeneratedTrace)\n trace.start()\n trace.log({\n configMethod: 'cli',\n configOverloadClientMethods: config.overloadClientMethods ?? false,\n emptyUnionTypeNodesGenerated: result.emptyUnionTypeNodesGenerated,\n filesWithErrors: result.filesWithErrors,\n outputSize: result.code.length,\n queriesCount: result.queriesCount,\n queryFilesCount: result.queryFilesCount,\n schemaTypesCount: result.schemaTypesCount,\n typeNodesGenerated: result.typeNodesGenerated,\n unknownTypeNodesGenerated: result.unknownTypeNodesGenerated,\n unknownTypeNodesRatio:\n result.typeNodesGenerated > 0\n ? result.unknownTypeNodesGenerated / result.typeNodesGenerated\n : 0,\n })\n trace.complete()\n }\n },\n } satisfies Plugin\n}\n"],"names":["existsSync","path","logSymbols","runTypegenGenerate","TypegenWatchModeTrace","TypesGeneratedTrace","debounce","mean","once","picomatch","parseTypegenConfig","toForwardSlashes","DEFAULT_DEBOUNCE_MS","INITIAL_GENERATION_DELAY_MS","sanityTypegenPlugin","options","config","inputConfig","output","console","telemetryLogger","workDir","queryPatterns","Array","isArray","resolvedSchemaPath","isGenerating","pendingGeneration","startTime","Date","now","stats","failedCount","successfulDurations","runGeneration","isBuilding","generationStartTime","error","schema","result","log","filesWithErrors","warning","generates","success","push","err","Error","message","String","debouncedGenerate","isQueryMatch","name","configResolved","rootDir","isAbsolute","join","configureServer","server","trace","start","step","absoluteQueryPatterns","map","pattern","watcher","add","handleChange","filePath","relativePath","relative","normalizedPath","onClose","cancel","averageGenerationDuration","generationFailedCount","generationSuccessfulCount","length","watcherDuration","complete","process","off","on","startGeneration","setTimeout","info","httpServer","buildEnd","configMethod","configOverloadClientMethods","overloadClientMethods","emptyUnionTypeNodesGenerated","outputSize","code","queriesCount","queryFilesCount","schemaTypesCount","typeNodesGenerated","unknownTypeNodesGenerated","unknownTypeNodesRatio"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/server/vite/plugin-typegen.ts"],"sourcesContent":["import {existsSync} from 'node:fs'\nimport path from 'node:path'\n\nimport {type CliConfig, CLITelemetryStore} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\nimport {\n type GenerationResult,\n runTypegenGenerate,\n type TypeGenConfig,\n TypegenWatchModeTrace,\n TypesGeneratedTrace,\n} from '@sanity/codegen'\nimport debounce from 'lodash-es/debounce.js'\nimport mean from 'lodash-es/mean.js'\nimport once from 'lodash-es/once.js'\nimport picomatch from 'picomatch'\nimport {type Plugin} from 'vite'\n\nimport {parseTypegenConfig} from '../../actions/typegen/parseTypegenConfig.js'\nimport {toForwardSlashes} from '../../util/toForwardSlashes.js'\n\n/** Default debounce delay in milliseconds */\nconst DEFAULT_DEBOUNCE_MS = 1000\n\n/**\n * Delay before initial generation to allow Vite to finish startup\n * and avoid race conditions with module resolution.\n */\nconst INITIAL_GENERATION_DELAY_MS = 1000\n\n/**\n * Options for the Sanity typegen Vite plugin.\n *\n * @internal\n */\ninterface TypegenPluginOptions {\n /**\n * Typegen configuration from sanity.cli.ts.\n * All fields are optional and will use sensible defaults.\n */\n config: Partial<TypeGenConfig> & Pick<NonNullable<CliConfig['typegen']>, 'resources'>\n\n /**\n * Working directory containing the Sanity configuration.\n * This should be the root of your Sanity Studio project.\n */\n workDir: string\n\n /**\n * Logger for output messages. Must implement `log`, `info`, and `error` methods.\n * @defaultValue `console`\n */\n output?: Pick<Console, 'error' | 'info' | 'log'>\n\n /**\n * Telemetry logger for the Sanity CLI tooling.\n */\n telemetryLogger?: CLITelemetryStore\n}\n\n/**\n * Creates a Vite plugin that automatically generates TypeScript types during development and build.\n *\n * **During development:**\n * The plugin performs an initial generation when the dev server starts, then watches\n * for file changes and re-generates types when relevant files are modified.\n *\n * **During build:**\n * The plugin generates types once at the end of the build process.\n *\n * **Prerequisites:**\n * The schema.json file must exist before typegen can run. Run `sanity schema extract`\n * first to generate the schema file.\n *\n * @param options - Configuration options for the plugin\n * @returns A Vite plugin configured for typegen\n *\n * @internal\n */\nexport function sanityTypegenPlugin(options: TypegenPluginOptions): Plugin {\n const {config: inputConfig, output = console, telemetryLogger, workDir} = options\n\n // Generating per resource is not supported here yet. Without this check the plugin would\n // generate from the top-level `schema`, which a resources config does not use.\n if (inputConfig.resources !== undefined) {\n return {\n configResolved() {\n output.log(\n logSymbols.warning,\n 'Typegen during \"sanity dev\" does not support typegen.resources yet. Run \"sanity typegen generate\" instead.',\n )\n },\n name: 'sanity/typegen',\n } satisfies Plugin\n }\n\n // Apply defaults through the same schema as `sanity typegen generate`,\n // so watch mode and manual generation produce identical output\n const config: TypeGenConfig = parseTypegenConfig(inputConfig)\n\n // Build query patterns from config\n const queryPatterns = Array.isArray(config.path) ? config.path : [config.path]\n\n // Resolved after Vite config is available\n let resolvedSchemaPath: string\n\n // State for concurrency control\n let isGenerating = false\n let pendingGeneration = false\n\n // Stats for telemetry\n const startTime = Date.now()\n const stats: {failedCount: number; successfulDurations: number[]} = {\n failedCount: 0,\n successfulDurations: [],\n }\n\n /**\n * Runs type generation with concurrency control.\n * If generation is already running, queues one more generation to run after completion.\n * Returns the generation result, or null if generation was skipped or failed.\n */\n async function runGeneration(isBuilding = false): Promise<GenerationResult | null> {\n if (isGenerating) {\n pendingGeneration = true\n return null\n }\n\n isGenerating = true\n pendingGeneration = false\n\n const generationStartTime = Date.now()\n\n try {\n // Validate schema.json exists\n if (!existsSync(resolvedSchemaPath)) {\n output.error(\n `${logSymbols.error} Schema file not found: ${config.schema}\\n` +\n `Run \"sanity schema extract\" first to generate the schema file.`,\n )\n return null\n }\n\n const result = await runTypegenGenerate({\n config,\n workDir,\n })\n\n if (isBuilding) {\n // Add newline for better formatting in build output\n output.log('')\n }\n\n if (result.filesWithErrors > 0) {\n output.log(\n logSymbols.warning,\n `Generated types to ${config.generates} (with errors in ${result.filesWithErrors} file${result.filesWithErrors === 1 ? '' : 's'})`,\n )\n } else {\n output.log(logSymbols.success, `Generated types to ${config.generates}`)\n }\n\n // Track stats for telemetry (all completed generations count as successful)\n stats.successfulDurations.push(Date.now() - generationStartTime)\n\n return result\n } catch (err) {\n output.error(\n `${logSymbols.error} Generation failed: ${err instanceof Error ? err.message : String(err)}`,\n )\n stats.failedCount++\n return null\n } finally {\n isGenerating = false\n\n // If a change came in during generation, run again\n if (pendingGeneration) {\n pendingGeneration = false\n void runGeneration()\n }\n }\n }\n\n const debouncedGenerate = debounce(() => {\n void runGeneration()\n }, DEFAULT_DEBOUNCE_MS)\n\n // Create a matcher function from query patterns\n const isQueryMatch = picomatch(queryPatterns)\n\n return {\n name: 'sanity/typegen',\n\n configResolved() {\n const rootDir = workDir\n\n resolvedSchemaPath = path.isAbsolute(config.schema)\n ? config.schema\n : path.join(rootDir, config.schema)\n },\n\n configureServer(server) {\n const trace = telemetryLogger?.trace(TypegenWatchModeTrace)\n trace?.start()\n trace?.log({step: 'started'})\n\n // Build absolute patterns for query files\n const absoluteQueryPatterns = queryPatterns.map((pattern) =>\n path.isAbsolute(pattern) ? pattern : path.join(workDir, pattern),\n )\n\n // Add query patterns AND schema.json to Vite's watcher\n server.watcher.add([...absoluteQueryPatterns, resolvedSchemaPath])\n\n // Listen for file changes\n const handleChange = (filePath: string) => {\n const relativePath = path.isAbsolute(filePath) ? path.relative(workDir, filePath) : filePath\n // Normalize to forward slashes for cross-platform picomatch compatibility\n const normalizedPath = toForwardSlashes(relativePath)\n\n // Trigger on schema.json change OR matching query file\n if (filePath === resolvedSchemaPath || isQueryMatch(normalizedPath)) {\n debouncedGenerate()\n }\n }\n\n // Prepare function to log \"stopped\" event to trace and complete the trace\n const onClose = once(() => {\n // Cancel any pending debounced extractions\n debouncedGenerate.cancel()\n\n if (trace) {\n trace.log({\n averageGenerationDuration: mean(stats.successfulDurations) || 0,\n generationFailedCount: stats.failedCount,\n generationSuccessfulCount: stats.successfulDurations.length,\n step: 'stopped',\n watcherDuration: Date.now() - startTime,\n })\n trace.complete()\n }\n\n // Clean up process listeners (must always run, not just when trace exists)\n process.off('SIGTERM', onClose)\n process.off('SIGINT', onClose)\n })\n\n server.watcher.on('change', handleChange)\n server.watcher.on('add', handleChange)\n server.watcher.on('unlink', handleChange)\n\n // Call the onClose method when watcher is closed or when process is stopped/killed\n server.watcher.on('close', onClose)\n process.on('SIGTERM', onClose)\n process.on('SIGINT', onClose)\n\n // Run initial generation after server is ready\n const startGeneration = () => {\n setTimeout(() => {\n // Notify about typegen enabled\n output.info(logSymbols.info, 'Typegen enabled. Watching:')\n for (const pattern of queryPatterns) {\n output.info(` - ${pattern}`)\n }\n output.info(` - ${config.schema} (schema)`)\n\n // Perform first generation\n void runGeneration()\n }, INITIAL_GENERATION_DELAY_MS)\n }\n\n if (server.httpServer) {\n server.httpServer.once('listening', startGeneration)\n } else {\n // Middleware mode - no HTTP server, run generation immediately\n startGeneration()\n }\n },\n\n async buildEnd() {\n // Build mode: One-time generation with telemetry tracking\n const result = await runGeneration(true)\n\n // Only log telemetry if generation completed successfully\n if (result && telemetryLogger) {\n const trace = telemetryLogger.trace(TypesGeneratedTrace)\n trace.start()\n trace.log({\n configMethod: 'cli',\n configOverloadClientMethods: config.overloadClientMethods ?? false,\n emptyUnionTypeNodesGenerated: result.emptyUnionTypeNodesGenerated,\n filesWithErrors: result.filesWithErrors,\n outputSize: result.code.length,\n queriesCount: result.queriesCount,\n queryFilesCount: result.queryFilesCount,\n schemaTypesCount: result.schemaTypesCount,\n typeNodesGenerated: result.typeNodesGenerated,\n unknownTypeNodesGenerated: result.unknownTypeNodesGenerated,\n unknownTypeNodesRatio:\n result.typeNodesGenerated > 0\n ? result.unknownTypeNodesGenerated / result.typeNodesGenerated\n : 0,\n })\n trace.complete()\n }\n },\n } satisfies Plugin\n}\n"],"names":["existsSync","path","logSymbols","runTypegenGenerate","TypegenWatchModeTrace","TypesGeneratedTrace","debounce","mean","once","picomatch","parseTypegenConfig","toForwardSlashes","DEFAULT_DEBOUNCE_MS","INITIAL_GENERATION_DELAY_MS","sanityTypegenPlugin","options","config","inputConfig","output","console","telemetryLogger","workDir","resources","undefined","configResolved","log","warning","name","queryPatterns","Array","isArray","resolvedSchemaPath","isGenerating","pendingGeneration","startTime","Date","now","stats","failedCount","successfulDurations","runGeneration","isBuilding","generationStartTime","error","schema","result","filesWithErrors","generates","success","push","err","Error","message","String","debouncedGenerate","isQueryMatch","rootDir","isAbsolute","join","configureServer","server","trace","start","step","absoluteQueryPatterns","map","pattern","watcher","add","handleChange","filePath","relativePath","relative","normalizedPath","onClose","cancel","averageGenerationDuration","generationFailedCount","generationSuccessfulCount","length","watcherDuration","complete","process","off","on","startGeneration","setTimeout","info","httpServer","buildEnd","configMethod","configOverloadClientMethods","overloadClientMethods","emptyUnionTypeNodesGenerated","outputSize","code","queriesCount","queryFilesCount","schemaTypesCount","typeNodesGenerated","unknownTypeNodesGenerated","unknownTypeNodesRatio"],"mappings":"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"}