@sanity/codegen 5.9.0-watch-mode.2 → 5.9.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,1358 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return JSON.parse(content);
|
|
11
|
-
}
|
|
12
|
-
// src/typescript/findQueriesInPath.ts
|
|
13
|
-
import fs2 from "node:fs/promises";
|
|
14
|
-
import createDebug3 from "debug";
|
|
15
|
-
import glob from "globby";
|
|
16
|
-
// src/getBabelConfig.ts
|
|
17
|
-
import { existsSync } from "node:fs";
|
|
18
|
-
import { dirname, join, resolve } from "node:path";
|
|
19
|
-
import { fileURLToPath } from "node:url";
|
|
20
|
-
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
21
|
-
function findBabelConfig(path3) {
|
|
22
|
-
const configPath = join(path3, "babel.config.json");
|
|
23
|
-
if (existsSync(configPath)) {
|
|
24
|
-
return configPath;
|
|
25
|
-
}
|
|
26
|
-
const parent = resolve(join(path3, ".."));
|
|
27
|
-
if (parent && parent !== path3) {
|
|
28
|
-
return findBabelConfig(parent);
|
|
29
|
-
}
|
|
30
|
-
throw new Error("Could not find `babel.config.json` in @sanity/codegen");
|
|
31
|
-
}
|
|
32
|
-
function getBabelConfig(path3) {
|
|
33
|
-
const configPath = findBabelConfig(path3 || __dirname);
|
|
34
|
-
return {
|
|
35
|
-
extends: configPath
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
// src/typescript/findQueriesInSource.ts
|
|
39
|
-
import { createRequire } from "node:module";
|
|
40
|
-
import { traverse as traverse2 } from "@babel/core";
|
|
41
|
-
import * as babelTypes2 from "@babel/types";
|
|
42
|
-
// src/typescript/expressionResolvers.ts
|
|
43
|
-
import fs from "node:fs";
|
|
44
|
-
import path from "node:path";
|
|
45
|
-
import { traverse } from "@babel/core";
|
|
46
|
-
import { Scope } from "@babel/traverse";
|
|
47
|
-
import * as babelTypes from "@babel/types";
|
|
48
|
-
import createDebug from "debug";
|
|
49
|
-
// src/utils/formatPath.ts
|
|
50
|
-
function formatPath(path3) {
|
|
51
|
-
return path3.replaceAll("\\", "/");
|
|
52
|
-
}
|
|
53
|
-
// src/typescript/parseSource.ts
|
|
54
|
-
import { parse } from "@babel/core";
|
|
55
|
-
function parseSourceFile(_source, _filename, babelOptions) {
|
|
56
|
-
let source = _source;
|
|
57
|
-
let filename = _filename;
|
|
58
|
-
if (filename.endsWith(".astro")) {
|
|
59
|
-
filename += ".ts";
|
|
60
|
-
source = parseAstro(source);
|
|
61
|
-
} else if (filename.endsWith(".vue")) {
|
|
62
|
-
filename += ".ts";
|
|
63
|
-
source = parseVue(source);
|
|
64
|
-
} else if (filename.endsWith(".svelte")) {
|
|
65
|
-
filename += ".ts";
|
|
66
|
-
source = parseSvelte(source);
|
|
67
|
-
}
|
|
68
|
-
const result = parse(source, {
|
|
69
|
-
...babelOptions,
|
|
70
|
-
filename
|
|
71
|
-
});
|
|
72
|
-
if (!result) {
|
|
73
|
-
throw new Error(`Failed to parse ${filename}`);
|
|
74
|
-
}
|
|
75
|
-
return result;
|
|
76
|
-
}
|
|
77
|
-
function parseAstro(source) {
|
|
78
|
-
const codeFences = source.match(/---\r?\n([\s\S]*?)\r?\n---/g);
|
|
79
|
-
if (!codeFences) {
|
|
80
|
-
return "";
|
|
81
|
-
}
|
|
82
|
-
return codeFences.map((codeFence)=>{
|
|
83
|
-
return codeFence.split(/\r?\n/).slice(1, -1).join("\n");
|
|
84
|
-
}).join("\n");
|
|
85
|
-
}
|
|
86
|
-
function parseVue(source) {
|
|
87
|
-
const scriptRegex = /<script(?:\s+generic=["'][^"']*["'])?[^>]*>([\s\S]*?)<\/script>/g;
|
|
88
|
-
const matches = matchAllPolyfill(source, scriptRegex);
|
|
89
|
-
if (matches.length === 0) {
|
|
90
|
-
return "";
|
|
91
|
-
}
|
|
92
|
-
return matches.map((match)=>match[1]).join("\n");
|
|
93
|
-
}
|
|
94
|
-
function parseSvelte(source) {
|
|
95
|
-
const scriptRegex = /<script[^>]*>([\s\S]*?)<\/script>/g;
|
|
96
|
-
const matches = matchAllPolyfill(source, scriptRegex);
|
|
97
|
-
if (matches.length === 0) {
|
|
98
|
-
return "";
|
|
99
|
-
}
|
|
100
|
-
return matches.map((match)=>match[1]).join("\n");
|
|
101
|
-
}
|
|
102
|
-
function matchAllPolyfill(str, regex) {
|
|
103
|
-
if (!regex.global) {
|
|
104
|
-
throw new Error("matchAll polyfill requires a global regex (with /g flag)");
|
|
105
|
-
}
|
|
106
|
-
const matches = [];
|
|
107
|
-
let match;
|
|
108
|
-
while((match = regex.exec(str)) !== null){
|
|
109
|
-
matches.push(match);
|
|
110
|
-
}
|
|
111
|
-
return matches;
|
|
112
|
-
}
|
|
113
|
-
// src/typescript/expressionResolvers.ts
|
|
114
|
-
var debug = createDebug("sanity:codegen:findQueries:debug");
|
|
115
|
-
var TAGGED_TEMPLATE_ALLOW_LIST = /* @__PURE__ */ new Set([
|
|
116
|
-
"groq"
|
|
117
|
-
]);
|
|
118
|
-
var FUNCTION_WRAPPER_ALLOW_LIST = /* @__PURE__ */ new Set([
|
|
119
|
-
"defineQuery"
|
|
120
|
-
]);
|
|
121
|
-
function resolveExpression({ babelConfig, file, filename, fnArguments = [], node, params = [], resolver, scope }) {
|
|
122
|
-
debug(`Resolving node ${node.type} in ${filename}:${node.loc?.start.line}:${node.loc?.start.column}`);
|
|
123
|
-
if (babelTypes.isTaggedTemplateExpression(node) && babelTypes.isIdentifier(node.tag) && TAGGED_TEMPLATE_ALLOW_LIST.has(node.tag.name)) {
|
|
124
|
-
return resolveExpression({
|
|
125
|
-
babelConfig,
|
|
126
|
-
file,
|
|
127
|
-
filename,
|
|
128
|
-
fnArguments,
|
|
129
|
-
node: node.quasi,
|
|
130
|
-
params,
|
|
131
|
-
resolver,
|
|
132
|
-
scope
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
if (babelTypes.isTemplateLiteral(node)) {
|
|
136
|
-
const resolvedExpressions = node.expressions.map((expression)=>resolveExpression({
|
|
137
|
-
babelConfig,
|
|
138
|
-
file,
|
|
139
|
-
filename,
|
|
140
|
-
fnArguments,
|
|
141
|
-
node: expression,
|
|
142
|
-
params,
|
|
143
|
-
resolver,
|
|
144
|
-
scope
|
|
145
|
-
}));
|
|
146
|
-
return node.quasis.map((quasi, idx)=>{
|
|
147
|
-
return (quasi.value.cooked || "") + (resolvedExpressions[idx] || "");
|
|
148
|
-
}).join("");
|
|
149
|
-
}
|
|
150
|
-
if (babelTypes.isLiteral(node)) {
|
|
151
|
-
if (node.type === "NullLiteral" || node.type === "RegExpLiteral") {
|
|
152
|
-
throw new Error(`Unsupported literal type: ${node.type}`);
|
|
153
|
-
}
|
|
154
|
-
return node.value.toString();
|
|
155
|
-
}
|
|
156
|
-
if (babelTypes.isIdentifier(node)) {
|
|
157
|
-
return resolveIdentifier({
|
|
158
|
-
babelConfig,
|
|
159
|
-
file,
|
|
160
|
-
filename,
|
|
161
|
-
fnArguments,
|
|
162
|
-
node,
|
|
163
|
-
params,
|
|
164
|
-
resolver,
|
|
165
|
-
scope
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
if (babelTypes.isVariableDeclarator(node)) {
|
|
169
|
-
const init = node.init ?? (babelTypes.isAssignmentPattern(node.id) && node.id.right);
|
|
170
|
-
if (!init) {
|
|
171
|
-
throw new Error(`Unsupported variable declarator`);
|
|
172
|
-
}
|
|
173
|
-
return resolveExpression({
|
|
174
|
-
babelConfig,
|
|
175
|
-
file,
|
|
176
|
-
filename,
|
|
177
|
-
fnArguments,
|
|
178
|
-
node: init,
|
|
179
|
-
resolver,
|
|
180
|
-
scope
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
if (babelTypes.isCallExpression(node) && babelTypes.isIdentifier(node.callee) && FUNCTION_WRAPPER_ALLOW_LIST.has(node.callee.name)) {
|
|
184
|
-
return resolveExpression({
|
|
185
|
-
babelConfig,
|
|
186
|
-
file,
|
|
187
|
-
filename,
|
|
188
|
-
node: node.arguments[0],
|
|
189
|
-
params,
|
|
190
|
-
resolver,
|
|
191
|
-
scope
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
if (babelTypes.isCallExpression(node)) {
|
|
195
|
-
return resolveCallExpression({
|
|
196
|
-
babelConfig,
|
|
197
|
-
file,
|
|
198
|
-
filename,
|
|
199
|
-
fnArguments,
|
|
200
|
-
node,
|
|
201
|
-
params,
|
|
202
|
-
resolver,
|
|
203
|
-
scope
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
if (babelTypes.isArrowFunctionExpression(node) || babelTypes.isFunctionDeclaration(node) || babelTypes.isFunctionExpression(node)) {
|
|
207
|
-
const newScope = new Scope(scope.path, scope);
|
|
208
|
-
for (const [i, param] of params.entries()){
|
|
209
|
-
newScope.push({
|
|
210
|
-
id: param,
|
|
211
|
-
init: fnArguments[i]
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
return resolveExpression({
|
|
215
|
-
babelConfig,
|
|
216
|
-
file,
|
|
217
|
-
filename,
|
|
218
|
-
fnArguments,
|
|
219
|
-
node: node.body,
|
|
220
|
-
params: node.params,
|
|
221
|
-
resolver,
|
|
222
|
-
scope: newScope
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
if (babelTypes.isNewExpression(node)) {
|
|
226
|
-
return resolveExpression({
|
|
227
|
-
babelConfig,
|
|
228
|
-
file,
|
|
229
|
-
filename,
|
|
230
|
-
node: node.callee,
|
|
231
|
-
resolver,
|
|
232
|
-
scope
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
if (babelTypes.isImportDefaultSpecifier(node) || babelTypes.isImportSpecifier(node)) {
|
|
236
|
-
return resolveImportSpecifier({
|
|
237
|
-
babelConfig,
|
|
238
|
-
file,
|
|
239
|
-
filename,
|
|
240
|
-
fnArguments,
|
|
241
|
-
node,
|
|
242
|
-
resolver,
|
|
243
|
-
scope
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
if (babelTypes.isAssignmentPattern(node)) {
|
|
247
|
-
return resolveExpression({
|
|
248
|
-
babelConfig,
|
|
249
|
-
file,
|
|
250
|
-
filename,
|
|
251
|
-
fnArguments,
|
|
252
|
-
node: node.right,
|
|
253
|
-
params,
|
|
254
|
-
resolver,
|
|
255
|
-
scope
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
if (babelTypes.isTSAsExpression(node)) {
|
|
259
|
-
return resolveExpression({
|
|
260
|
-
babelConfig,
|
|
261
|
-
file,
|
|
262
|
-
filename,
|
|
263
|
-
fnArguments,
|
|
264
|
-
node: node.expression,
|
|
265
|
-
params,
|
|
266
|
-
resolver,
|
|
267
|
-
scope
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
throw new Error(`Unsupported expression type: ${node.type} in ${filename}:${node.loc?.start.line}:${node.loc?.start.column}`);
|
|
271
|
-
}
|
|
272
|
-
function resolveIdentifier({ babelConfig, file, filename, fnArguments, node, params, resolver, scope }) {
|
|
273
|
-
const paramIndex = params.findIndex((param)=>babelTypes.isIdentifier(param) && node.name === param.name || babelTypes.isAssignmentPattern(param) && babelTypes.isIdentifier(param.left) && node.name === param.left.name);
|
|
274
|
-
let argument = fnArguments[paramIndex];
|
|
275
|
-
if (!argument && paramIndex !== -1 && babelTypes.isAssignmentPattern(params[paramIndex])) {
|
|
276
|
-
argument = params[paramIndex].right;
|
|
277
|
-
}
|
|
278
|
-
if (argument && babelTypes.isLiteral(argument)) {
|
|
279
|
-
return resolveExpression({
|
|
280
|
-
babelConfig,
|
|
281
|
-
file,
|
|
282
|
-
filename,
|
|
283
|
-
fnArguments,
|
|
284
|
-
node: argument,
|
|
285
|
-
params,
|
|
286
|
-
resolver,
|
|
287
|
-
scope
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
const binding = scope.getBinding(node.name);
|
|
291
|
-
if (binding) {
|
|
292
|
-
if (babelTypes.isIdentifier(binding.path.node)) {
|
|
293
|
-
const isSame = binding.path.node.name === node.name;
|
|
294
|
-
if (isSame) {
|
|
295
|
-
throw new Error(`Could not resolve same identifier "${node.name}" in "${filename}:${node.loc?.start.line}:${node.loc?.start.column}"`);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
return resolveExpression({
|
|
299
|
-
babelConfig,
|
|
300
|
-
file,
|
|
301
|
-
filename,
|
|
302
|
-
fnArguments,
|
|
303
|
-
node: binding.path.node,
|
|
304
|
-
params,
|
|
305
|
-
resolver,
|
|
306
|
-
scope
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
throw new Error(`Could not find binding for node "${node.name}" in ${filename}:${node.loc?.start.line}:${node.loc?.start.column}`);
|
|
310
|
-
}
|
|
311
|
-
function resolveCallExpression({ babelConfig, file, filename, node, params, resolver, scope }) {
|
|
312
|
-
const { callee } = node;
|
|
313
|
-
return resolveExpression({
|
|
314
|
-
babelConfig,
|
|
315
|
-
file,
|
|
316
|
-
filename,
|
|
317
|
-
fnArguments: node.arguments,
|
|
318
|
-
node: callee,
|
|
319
|
-
params,
|
|
320
|
-
resolver,
|
|
321
|
-
scope
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
function resolveImportSpecifier({ babelConfig, file, filename, fnArguments, node, resolver }) {
|
|
325
|
-
let importDeclaration2;
|
|
326
|
-
traverse(file, {
|
|
327
|
-
ImportDeclaration (n) {
|
|
328
|
-
if (!babelTypes.isImportDeclaration(n.node)) {
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
|
-
for (const specifier of n.node.specifiers){
|
|
332
|
-
if (babelTypes.isImportDefaultSpecifier(specifier) && specifier.local.loc?.identifierName === node.local.name) {
|
|
333
|
-
importDeclaration2 = n.node;
|
|
334
|
-
break;
|
|
335
|
-
}
|
|
336
|
-
if (specifier.local.name === node.local.name) {
|
|
337
|
-
importDeclaration2 = n.node;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
if (!importDeclaration2) {
|
|
343
|
-
throw new Error(`Could not find import declaration for ${node.local.name}`);
|
|
344
|
-
}
|
|
345
|
-
const importName = node.local.name;
|
|
346
|
-
const importFileName = importDeclaration2.source.value;
|
|
347
|
-
const importPath = importFileName.startsWith("./") || importFileName.startsWith("../") ? path.resolve(path.dirname(filename), importFileName) : importFileName;
|
|
348
|
-
const resolvedFile = resolver(formatPath(importPath));
|
|
349
|
-
const source = fs.readFileSync(resolvedFile);
|
|
350
|
-
const tree = parseSourceFile(source.toString(), resolvedFile, babelConfig);
|
|
351
|
-
let newScope;
|
|
352
|
-
traverse(tree, {
|
|
353
|
-
Program (p) {
|
|
354
|
-
newScope = p.scope;
|
|
355
|
-
}
|
|
356
|
-
});
|
|
357
|
-
if (!newScope) {
|
|
358
|
-
throw new Error(`Could not find scope for ${filename}`);
|
|
359
|
-
}
|
|
360
|
-
const binding = newScope.getBinding(importName);
|
|
361
|
-
if (binding) {
|
|
362
|
-
return resolveExpression({
|
|
363
|
-
babelConfig,
|
|
364
|
-
file: tree,
|
|
365
|
-
filename: resolvedFile,
|
|
366
|
-
fnArguments,
|
|
367
|
-
node: binding.path.node,
|
|
368
|
-
resolver,
|
|
369
|
-
scope: newScope
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
|
-
let namedExport;
|
|
373
|
-
let newImportName;
|
|
374
|
-
traverse(tree, {
|
|
375
|
-
ExportDeclaration (p) {
|
|
376
|
-
if (p.node.type === "ExportNamedDeclaration") {
|
|
377
|
-
for (const specifier of p.node.specifiers){
|
|
378
|
-
if (specifier.type === "ExportSpecifier" && specifier.exported.type === "Identifier" && specifier.exported.name === importName) {
|
|
379
|
-
namedExport = p.node;
|
|
380
|
-
newImportName = specifier.exported.name;
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
});
|
|
386
|
-
if (namedExport && newImportName) {
|
|
387
|
-
return resolveExportSpecifier({
|
|
388
|
-
babelConfig,
|
|
389
|
-
filename: resolvedFile,
|
|
390
|
-
fnArguments,
|
|
391
|
-
importName: newImportName,
|
|
392
|
-
node: namedExport,
|
|
393
|
-
resolver
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
|
-
let result;
|
|
397
|
-
traverse(tree, {
|
|
398
|
-
ExportDeclaration (p) {
|
|
399
|
-
if (p.node.type === "ExportAllDeclaration") {
|
|
400
|
-
try {
|
|
401
|
-
result = resolveExportSpecifier({
|
|
402
|
-
babelConfig,
|
|
403
|
-
filename: resolvedFile,
|
|
404
|
-
fnArguments,
|
|
405
|
-
importName,
|
|
406
|
-
node: p.node,
|
|
407
|
-
resolver
|
|
408
|
-
});
|
|
409
|
-
} catch (e) {
|
|
410
|
-
if (e.cause !== `noBinding:${importName}`) throw e;
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
});
|
|
415
|
-
if (result) return result;
|
|
416
|
-
throw new Error(`Could not find binding for import "${importName}" in ${importFileName}`);
|
|
417
|
-
}
|
|
418
|
-
function resolveExportSpecifier({ babelConfig, filename, fnArguments, importName, node, resolver }) {
|
|
419
|
-
if (!node.source) {
|
|
420
|
-
throw new Error(`Could not find source for export "${importName}" in ${filename}`);
|
|
421
|
-
}
|
|
422
|
-
const importFileName = node.source.value;
|
|
423
|
-
const importPath = path.resolve(path.dirname(filename), importFileName);
|
|
424
|
-
const resolvedFile = resolver(formatPath(importPath));
|
|
425
|
-
const source = fs.readFileSync(resolvedFile);
|
|
426
|
-
const tree = parseSourceFile(source.toString(), resolvedFile, babelConfig);
|
|
427
|
-
let newScope;
|
|
428
|
-
traverse(tree, {
|
|
429
|
-
Program (p) {
|
|
430
|
-
newScope = p.scope;
|
|
431
|
-
}
|
|
432
|
-
});
|
|
433
|
-
if (!newScope) {
|
|
434
|
-
throw new Error(`Could not find scope for ${filename}`);
|
|
435
|
-
}
|
|
436
|
-
const binding = newScope.getBinding(importName);
|
|
437
|
-
if (binding) {
|
|
438
|
-
return resolveExpression({
|
|
439
|
-
babelConfig,
|
|
440
|
-
file: tree,
|
|
441
|
-
filename: resolvedFile,
|
|
442
|
-
fnArguments,
|
|
443
|
-
node: binding.path.node,
|
|
444
|
-
resolver,
|
|
445
|
-
scope: newScope
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
|
-
throw new Error(`Could not find binding for export "${importName}" in ${importFileName}`, {
|
|
449
|
-
cause: `noBinding:${importName}`
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
// src/typescript/types.ts
|
|
453
|
-
var isRecord = (value)=>(typeof value === "object" || typeof value === "function") && !!value;
|
|
454
|
-
var QueryExtractionError = class extends Error {
|
|
455
|
-
filename;
|
|
456
|
-
variable;
|
|
457
|
-
constructor({ cause, filename, variable }){
|
|
458
|
-
super(`Error while extracting query ${variable ? `from variable '${variable.id.name}' ` : ""}in ${filename}: ${isRecord(cause) && typeof cause.message === "string" ? cause.message : "Unknown error"}`);
|
|
459
|
-
this.name = "QueryExtractionError";
|
|
460
|
-
this.cause = cause;
|
|
461
|
-
this.variable = variable;
|
|
462
|
-
this.filename = filename;
|
|
463
|
-
}
|
|
464
|
-
};
|
|
465
|
-
var QueryEvaluationError = class extends Error {
|
|
466
|
-
filename;
|
|
467
|
-
variable;
|
|
468
|
-
constructor({ cause, filename, variable }){
|
|
469
|
-
super(`Error while evaluating query ${variable ? `from variable '${variable.id.name}' ` : ""}in ${filename}: ${isRecord(cause) && typeof cause.message === "string" ? cause.message : "Unknown error"}`);
|
|
470
|
-
this.name = "QueryEvaluationError";
|
|
471
|
-
this.cause = cause;
|
|
472
|
-
this.variable = variable;
|
|
473
|
-
this.filename = filename;
|
|
474
|
-
}
|
|
475
|
-
};
|
|
476
|
-
// src/typescript/findQueriesInSource.ts
|
|
477
|
-
var require2 = createRequire(import.meta.url);
|
|
478
|
-
var groqTagName = "groq";
|
|
479
|
-
var defineQueryFunctionName = "defineQuery";
|
|
480
|
-
var groqModuleName = "groq";
|
|
481
|
-
var nextSanityModuleName = "next-sanity";
|
|
482
|
-
var sveltekitModuleName = "@sanity/sveltekit";
|
|
483
|
-
var ignoreValue = "@sanity-typegen-ignore";
|
|
484
|
-
function findQueriesInSource(source, filename, babelConfig = getBabelConfig(), resolver = require2.resolve) {
|
|
485
|
-
const queries = [];
|
|
486
|
-
const errors = [];
|
|
487
|
-
const file = parseSourceFile(source, filename, babelConfig);
|
|
488
|
-
traverse2(file, {
|
|
489
|
-
// Look for variable declarations, e.g. `const myQuery = groq`... and extract the query.
|
|
490
|
-
// The variable name is used as the name of the query result type
|
|
491
|
-
VariableDeclarator (path3) {
|
|
492
|
-
const { node, scope } = path3;
|
|
493
|
-
const init = node.init;
|
|
494
|
-
const isGroqTemplateTag = babelTypes2.isTaggedTemplateExpression(init) && babelTypes2.isIdentifier(init.tag) && init.tag.name === groqTagName;
|
|
495
|
-
const isDefineQueryCall = babelTypes2.isCallExpression(init) && (isImportFrom(groqModuleName, defineQueryFunctionName, scope, init.callee) || isImportFrom(nextSanityModuleName, defineQueryFunctionName, scope, init.callee) || isImportFrom(sveltekitModuleName, defineQueryFunctionName, scope, init.callee));
|
|
496
|
-
if (babelTypes2.isIdentifier(node.id) && (isGroqTemplateTag || isDefineQueryCall)) {
|
|
497
|
-
if (declarationLeadingCommentContains(path3, ignoreValue)) {
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
const { end, id, start } = node;
|
|
501
|
-
const variable = {
|
|
502
|
-
id,
|
|
503
|
-
...start && {
|
|
504
|
-
start
|
|
505
|
-
},
|
|
506
|
-
...end && {
|
|
507
|
-
end
|
|
508
|
-
}
|
|
509
|
-
};
|
|
510
|
-
try {
|
|
511
|
-
const query = resolveExpression({
|
|
512
|
-
babelConfig,
|
|
513
|
-
file,
|
|
514
|
-
filename,
|
|
515
|
-
node: init,
|
|
516
|
-
resolver,
|
|
517
|
-
scope
|
|
518
|
-
});
|
|
519
|
-
queries.push({
|
|
520
|
-
filename,
|
|
521
|
-
query,
|
|
522
|
-
variable
|
|
523
|
-
});
|
|
524
|
-
} catch (cause) {
|
|
525
|
-
errors.push(new QueryExtractionError({
|
|
526
|
-
cause,
|
|
527
|
-
filename,
|
|
528
|
-
variable
|
|
529
|
-
}));
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
});
|
|
534
|
-
return {
|
|
535
|
-
errors,
|
|
536
|
-
filename,
|
|
537
|
-
queries
|
|
538
|
-
};
|
|
539
|
-
}
|
|
540
|
-
function declarationLeadingCommentContains(path3, comment) {
|
|
541
|
-
const variableDeclaration2 = path3.find((node)=>node.isVariableDeclaration());
|
|
542
|
-
if (!variableDeclaration2) return false;
|
|
543
|
-
if (variableDeclaration2.node.leadingComments?.find((commentItem)=>commentItem.value.trim() === comment)) {
|
|
544
|
-
return true;
|
|
545
|
-
}
|
|
546
|
-
if (variableDeclaration2.parent.leadingComments?.find((commentItem)=>commentItem.value.trim() === comment)) {
|
|
547
|
-
return true;
|
|
548
|
-
}
|
|
549
|
-
return false;
|
|
550
|
-
}
|
|
551
|
-
function isImportFrom(moduleName, importName, scope, node) {
|
|
552
|
-
if (babelTypes2.isIdentifier(node)) {
|
|
553
|
-
const binding = scope.getBinding(node.name);
|
|
554
|
-
if (!binding) {
|
|
555
|
-
return false;
|
|
556
|
-
}
|
|
557
|
-
const { path: path3 } = binding;
|
|
558
|
-
if (babelTypes2.isImportSpecifier(path3.node)) {
|
|
559
|
-
return path3.node.importKind === "value" && path3.parentPath && babelTypes2.isImportDeclaration(path3.parentPath.node) && path3.parentPath.node.source.value === moduleName && babelTypes2.isIdentifier(path3.node.imported) && path3.node.imported.name === importName;
|
|
560
|
-
}
|
|
561
|
-
if (babelTypes2.isVariableDeclarator(path3.node)) {
|
|
562
|
-
const { init } = path3.node;
|
|
563
|
-
return babelTypes2.isCallExpression(init) && babelTypes2.isIdentifier(init.callee) && init.callee.name === "require" && babelTypes2.isStringLiteral(init.arguments[0]) && init.arguments[0].value === moduleName;
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
if (babelTypes2.isMemberExpression(node)) {
|
|
567
|
-
const { object, property } = node;
|
|
568
|
-
if (!babelTypes2.isIdentifier(object)) {
|
|
569
|
-
return false;
|
|
570
|
-
}
|
|
571
|
-
const binding = scope.getBinding(object.name);
|
|
572
|
-
if (!binding) {
|
|
573
|
-
return false;
|
|
574
|
-
}
|
|
575
|
-
const { path: path3 } = binding;
|
|
576
|
-
return babelTypes2.isIdentifier(object) && babelTypes2.isIdentifier(property) && property.name === importName && babelTypes2.isImportNamespaceSpecifier(path3.node) && path3.parentPath && babelTypes2.isImportDeclaration(path3.parentPath.node) && path3.parentPath.node.source.value === moduleName;
|
|
577
|
-
}
|
|
578
|
-
return false;
|
|
579
|
-
}
|
|
580
|
-
// src/typescript/helpers.ts
|
|
581
|
-
import path2 from "node:path";
|
|
582
|
-
import { CodeGenerator } from "@babel/generator";
|
|
583
|
-
import * as t2 from "@babel/types";
|
|
584
|
-
// src/typescript/constants.ts
|
|
585
|
-
import * as t from "@babel/types";
|
|
586
|
-
var INTERNAL_REFERENCE_SYMBOL = t.identifier("internalGroqTypeReferenceTo");
|
|
587
|
-
var ALL_SANITY_SCHEMA_TYPES = t.identifier("AllSanitySchemaTypes");
|
|
588
|
-
var SANITY_QUERIES = t.identifier("SanityQueries");
|
|
589
|
-
var ARRAY_OF = t.identifier("ArrayOf");
|
|
590
|
-
var RESERVED_IDENTIFIERS = /* @__PURE__ */ new Set();
|
|
591
|
-
RESERVED_IDENTIFIERS.add(SANITY_QUERIES.name);
|
|
592
|
-
RESERVED_IDENTIFIERS.add(ALL_SANITY_SCHEMA_TYPES.name);
|
|
593
|
-
RESERVED_IDENTIFIERS.add(INTERNAL_REFERENCE_SYMBOL.name);
|
|
594
|
-
RESERVED_IDENTIFIERS.add(ARRAY_OF.name);
|
|
595
|
-
// src/typescript/helpers.ts
|
|
596
|
-
function normalizePrintablePath(root, filename) {
|
|
597
|
-
const resolved = path2.resolve(root, filename);
|
|
598
|
-
return formatPath(path2.relative(root, resolved));
|
|
599
|
-
}
|
|
600
|
-
function normalizeGlobPattern(pattern) {
|
|
601
|
-
if (Array.isArray(pattern)) {
|
|
602
|
-
return pattern.map((p)=>formatPath(p));
|
|
603
|
-
}
|
|
604
|
-
return formatPath(pattern);
|
|
605
|
-
}
|
|
606
|
-
function sanitizeIdentifier(input) {
|
|
607
|
-
return `${input.replace(/^\d/, "_").replaceAll(/[^$\w]+(.)/g, (_, char)=>char.toUpperCase())}`;
|
|
608
|
-
}
|
|
609
|
-
function isIdentifierName(input) {
|
|
610
|
-
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(input);
|
|
611
|
-
}
|
|
612
|
-
function normalizeIdentifier(input) {
|
|
613
|
-
const sanitized = sanitizeIdentifier(input);
|
|
614
|
-
return `${sanitized.charAt(0).toUpperCase()}${sanitized.slice(1)}`;
|
|
615
|
-
}
|
|
616
|
-
function getUniqueIdentifierForName(name, currentIdentifiers) {
|
|
617
|
-
const desiredName = normalizeIdentifier(name);
|
|
618
|
-
let resultingName = desiredName;
|
|
619
|
-
let index = 2;
|
|
620
|
-
while(currentIdentifiers.has(resultingName) || RESERVED_IDENTIFIERS.has(resultingName)){
|
|
621
|
-
resultingName = `${desiredName}_${index}`;
|
|
622
|
-
index++;
|
|
623
|
-
}
|
|
624
|
-
return t2.identifier(resultingName);
|
|
625
|
-
}
|
|
626
|
-
function computeOnce(fn) {
|
|
627
|
-
const ref = {
|
|
628
|
-
computed: false,
|
|
629
|
-
current: void 0
|
|
630
|
-
};
|
|
631
|
-
return function() {
|
|
632
|
-
if (ref.computed) return ref.current;
|
|
633
|
-
ref.current = fn();
|
|
634
|
-
ref.computed = true;
|
|
635
|
-
return ref.current;
|
|
636
|
-
};
|
|
637
|
-
}
|
|
638
|
-
function weakMapMemo(fn) {
|
|
639
|
-
const cache = /* @__PURE__ */ new WeakMap();
|
|
640
|
-
const wrapped = function(arg) {
|
|
641
|
-
if (cache.has(arg)) return cache.get(arg);
|
|
642
|
-
const result = fn(arg);
|
|
643
|
-
cache.set(arg, result);
|
|
644
|
-
return result;
|
|
645
|
-
};
|
|
646
|
-
return wrapped;
|
|
647
|
-
}
|
|
648
|
-
function generateCode(node) {
|
|
649
|
-
return `${new CodeGenerator(node).generate().code.trim()}
|
|
650
|
-
|
|
651
|
-
`;
|
|
652
|
-
}
|
|
653
|
-
function getFilterArrayUnionType(typeNode, predicate) {
|
|
654
|
-
if (typeNode.of.type !== "union") {
|
|
655
|
-
return typeNode;
|
|
656
|
-
}
|
|
657
|
-
return {
|
|
658
|
-
...typeNode,
|
|
659
|
-
of: {
|
|
660
|
-
...typeNode.of,
|
|
661
|
-
of: typeNode.of.of.filter((unionTypeNode)=>predicate(unionTypeNode))
|
|
662
|
-
}
|
|
663
|
-
};
|
|
664
|
-
}
|
|
665
|
-
// src/typescript/moduleResolver.ts
|
|
666
|
-
import { createRequire as createRequire2 } from "node:module";
|
|
667
|
-
import createDebug2 from "debug";
|
|
668
|
-
import { createMatchPath, loadConfig as loadTSConfig } from "tsconfig-paths";
|
|
669
|
-
var require3 = createRequire2(import.meta.url);
|
|
670
|
-
var debug2 = createDebug2("sanity:codegen:moduleResolver");
|
|
671
|
-
function getResolver(cwd) {
|
|
672
|
-
const tsConfig = loadTSConfig(cwd);
|
|
673
|
-
if (tsConfig.resultType === "failed") {
|
|
674
|
-
debug2("Could not load tsconfig, using default resolver: %s", tsConfig.message);
|
|
675
|
-
return require3.resolve;
|
|
676
|
-
}
|
|
677
|
-
const matchPath = createMatchPath(tsConfig.absoluteBaseUrl, tsConfig.paths, tsConfig.mainFields, tsConfig.addMatchAll);
|
|
678
|
-
const resolve2 = function(request, options) {
|
|
679
|
-
const found = matchPath(request);
|
|
680
|
-
if (found !== void 0) {
|
|
681
|
-
return require3.resolve(found, options);
|
|
682
|
-
}
|
|
683
|
-
return require3.resolve(request, options);
|
|
684
|
-
};
|
|
685
|
-
resolve2.paths = (request)=>{
|
|
686
|
-
return require3.resolve.paths(request);
|
|
687
|
-
};
|
|
688
|
-
return resolve2;
|
|
689
|
-
}
|
|
690
|
-
// src/typescript/findQueriesInPath.ts
|
|
691
|
-
var debug3 = createDebug3("sanity:codegen:findQueries:debug");
|
|
692
|
-
function findQueriesInPath({ babelOptions = getBabelConfig(), path: path3, resolver = getResolver() }) {
|
|
693
|
-
const queryNames = /* @__PURE__ */ new Set();
|
|
694
|
-
debug3(`Globing ${path3}`);
|
|
695
|
-
const normalizedPath = normalizeGlobPattern(path3);
|
|
696
|
-
const files = glob.sync(normalizedPath, {
|
|
697
|
-
absolute: false,
|
|
698
|
-
ignore: [
|
|
699
|
-
"**/node_modules/**"
|
|
700
|
-
],
|
|
701
|
-
// we never want to look in node_modules
|
|
702
|
-
onlyFiles: true
|
|
703
|
-
}).toSorted();
|
|
704
|
-
async function* getQueries() {
|
|
705
|
-
for (const filename of files){
|
|
706
|
-
if (typeof filename !== "string") {
|
|
707
|
-
continue;
|
|
708
|
-
}
|
|
709
|
-
debug3(`Found file "${filename}"`);
|
|
710
|
-
try {
|
|
711
|
-
const source = await fs2.readFile(filename, "utf8");
|
|
712
|
-
const pluckedModuleResult = findQueriesInSource(source, filename, babelOptions, resolver);
|
|
713
|
-
for (const { variable } of pluckedModuleResult.queries){
|
|
714
|
-
if (queryNames.has(variable.id.name)) {
|
|
715
|
-
throw new Error(`Duplicate query name found: "${variable.id.name}". Query names must be unique across all files.`);
|
|
716
|
-
}
|
|
717
|
-
queryNames.add(variable.id.name);
|
|
718
|
-
}
|
|
719
|
-
yield pluckedModuleResult;
|
|
720
|
-
} catch (cause) {
|
|
721
|
-
debug3(`Error in file "${filename}"`, cause);
|
|
722
|
-
yield {
|
|
723
|
-
errors: [
|
|
724
|
-
new QueryExtractionError({
|
|
725
|
-
cause,
|
|
726
|
-
filename
|
|
727
|
-
})
|
|
728
|
-
],
|
|
729
|
-
filename,
|
|
730
|
-
queries: []
|
|
731
|
-
};
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
return {
|
|
736
|
-
files,
|
|
737
|
-
queries: getQueries()
|
|
738
|
-
};
|
|
739
|
-
}
|
|
740
|
-
// src/typescript/registerBabel.ts
|
|
741
|
-
import register from "@babel/register";
|
|
742
|
-
function registerBabel(babelOptions) {
|
|
743
|
-
const options = babelOptions || getBabelConfig();
|
|
744
|
-
register({
|
|
745
|
-
...options,
|
|
746
|
-
extensions: [
|
|
747
|
-
".ts",
|
|
748
|
-
".tsx",
|
|
749
|
-
".js",
|
|
750
|
-
".jsx",
|
|
751
|
-
".mjs",
|
|
752
|
-
".cjs"
|
|
753
|
-
]
|
|
754
|
-
});
|
|
755
|
-
}
|
|
756
|
-
// src/typescript/typeGenerator.ts
|
|
757
|
-
import process from "node:process";
|
|
758
|
-
import * as t4 from "@babel/types";
|
|
759
|
-
import { createSelector } from "reselect";
|
|
760
|
-
// src/casing.ts
|
|
761
|
-
function resultSuffix(variableName) {
|
|
762
|
-
if (!variableName) return "result";
|
|
763
|
-
const isUpperSnake = /^[A-Z0-9_]+$/.test(variableName);
|
|
764
|
-
const isSnake = /^[a-z0-9_]+$/.test(variableName) && variableName.includes("_");
|
|
765
|
-
const isCamel = /^[a-z][A-Za-z0-9]*$/.test(variableName);
|
|
766
|
-
if (isCamel) {
|
|
767
|
-
return `${variableName}Result`;
|
|
768
|
-
}
|
|
769
|
-
if (isUpperSnake) {
|
|
770
|
-
return `${variableName}_RESULT`;
|
|
771
|
-
}
|
|
772
|
-
if (isSnake) {
|
|
773
|
-
return `${variableName}_result`;
|
|
774
|
-
}
|
|
775
|
-
const cleaned = variableName.replaceAll(/[^A-Za-z0-9]/g, "");
|
|
776
|
-
return `${cleaned}Result`;
|
|
777
|
-
}
|
|
778
|
-
// src/typescript/schemaTypeGenerator.ts
|
|
779
|
-
import * as t3 from "@babel/types";
|
|
780
|
-
import { typeEvaluate } from "groq-js";
|
|
781
|
-
// src/safeParseQuery.ts
|
|
782
|
-
import { parse as parse2 } from "groq-js";
|
|
783
|
-
function safeParseQuery(query) {
|
|
784
|
-
const params = {};
|
|
785
|
-
for (const param of extractSliceParams(query)){
|
|
786
|
-
params[param] = 0;
|
|
787
|
-
}
|
|
788
|
-
return parse2(query, {
|
|
789
|
-
params
|
|
790
|
-
});
|
|
791
|
-
}
|
|
792
|
-
function* extractSliceParams(query) {
|
|
793
|
-
const sliceRegex = /\[(\$(\w+)|\d)\.\.\.?(\$(\w+)|\d)\]/g;
|
|
794
|
-
const matches = query.matchAll(sliceRegex);
|
|
795
|
-
if (!matches) {
|
|
796
|
-
return;
|
|
797
|
-
}
|
|
798
|
-
for (const match of matches){
|
|
799
|
-
const start = match[1] === `$${match[2]}` ? match[2] : null;
|
|
800
|
-
if (start !== null) {
|
|
801
|
-
yield start;
|
|
802
|
-
}
|
|
803
|
-
const end = match[3] === `$${match[4]}` ? match[4] : null;
|
|
804
|
-
if (end !== null) {
|
|
805
|
-
yield end;
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
// src/typescript/schemaTypeGenerator.ts
|
|
810
|
-
var SchemaTypeGenerator = class {
|
|
811
|
-
schema;
|
|
812
|
-
evaluateQuery = weakMapMemo(// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
813
|
-
({ query })=>{
|
|
814
|
-
const ast = safeParseQuery(query);
|
|
815
|
-
const typeNode = typeEvaluate(ast, this.schema);
|
|
816
|
-
const tsType = this.generateTsType(typeNode);
|
|
817
|
-
const stats = walkAndCountQueryTypeNodeStats(typeNode);
|
|
818
|
-
return {
|
|
819
|
-
stats,
|
|
820
|
-
tsType
|
|
821
|
-
};
|
|
822
|
-
});
|
|
823
|
-
identifiers = /* @__PURE__ */ new Map();
|
|
824
|
-
tsTypes = /* @__PURE__ */ new Map();
|
|
825
|
-
constructor(schema){
|
|
826
|
-
this.schema = schema;
|
|
827
|
-
const uniqueTypeNames = /* @__PURE__ */ new Set();
|
|
828
|
-
for (const type of schema){
|
|
829
|
-
if (uniqueTypeNames.has(type.name)) {
|
|
830
|
-
throw new Error(`Duplicate type name "${type.name}" in schema. Type names must be unique within the same schema.`);
|
|
831
|
-
}
|
|
832
|
-
uniqueTypeNames.add(type.name);
|
|
833
|
-
}
|
|
834
|
-
for (const type of schema){
|
|
835
|
-
const currentIdentifierNames = new Set([
|
|
836
|
-
...this.identifiers.values()
|
|
837
|
-
].map((id)=>id.name));
|
|
838
|
-
const uniqueIdentifier = getUniqueIdentifierForName(type.name, currentIdentifierNames);
|
|
839
|
-
this.identifiers.set(type.name, uniqueIdentifier);
|
|
840
|
-
}
|
|
841
|
-
for (const type of schema){
|
|
842
|
-
this.tsTypes.set(type.name, this.generateTsType(type));
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
getType(typeName) {
|
|
846
|
-
const tsType = this.tsTypes.get(typeName);
|
|
847
|
-
const id = this.identifiers.get(typeName);
|
|
848
|
-
if (tsType && id) return {
|
|
849
|
-
id,
|
|
850
|
-
tsType
|
|
851
|
-
};
|
|
852
|
-
return void 0;
|
|
853
|
-
}
|
|
854
|
-
hasType(typeName) {
|
|
855
|
-
return this.tsTypes.has(typeName);
|
|
856
|
-
}
|
|
857
|
-
*[Symbol.iterator]() {
|
|
858
|
-
for (const { name } of this.schema){
|
|
859
|
-
yield {
|
|
860
|
-
name,
|
|
861
|
-
...this.getType(name)
|
|
862
|
-
};
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
typeNames() {
|
|
866
|
-
return this.schema.map((schemaType)=>schemaType.name);
|
|
867
|
-
}
|
|
868
|
-
/**
|
|
869
|
-
* Helper function used to generate TS types for arrays of inline types, or arrays of inline types
|
|
870
|
-
* wrapped in the ArrayOf wrapper that adds _key prop
|
|
871
|
-
*/ generateArrayOfTsType(typeNode) {
|
|
872
|
-
const typeNodes = this.generateTsType(typeNode.of);
|
|
873
|
-
return t3.tsTypeReference(ARRAY_OF, t3.tsTypeParameterInstantiation([
|
|
874
|
-
typeNodes
|
|
875
|
-
]));
|
|
876
|
-
}
|
|
877
|
-
// Helper function used to generate TS types for array type nodes.
|
|
878
|
-
generateArrayTsType(typeNode) {
|
|
879
|
-
if (typeNode.of.type === "inline") {
|
|
880
|
-
return this.generateArrayOfTsType(typeNode);
|
|
881
|
-
}
|
|
882
|
-
if (typeNode.of.type !== "union") {
|
|
883
|
-
const typeNodes = this.generateTsType(typeNode.of);
|
|
884
|
-
return t3.tsTypeReference(t3.identifier("Array"), t3.tsTypeParameterInstantiation([
|
|
885
|
-
typeNodes
|
|
886
|
-
]));
|
|
887
|
-
}
|
|
888
|
-
if (typeNode.of.of.every((unionTypeNode)=>unionTypeNode.type !== "inline")) {
|
|
889
|
-
const typeNodes = this.generateTsType(typeNode.of);
|
|
890
|
-
return t3.tsTypeReference(t3.identifier("Array"), t3.tsTypeParameterInstantiation([
|
|
891
|
-
typeNodes
|
|
892
|
-
]));
|
|
893
|
-
}
|
|
894
|
-
if (typeNode.of.of.every((unionMember)=>unionMember.type === "inline")) {
|
|
895
|
-
return this.generateArrayOfTsType(typeNode);
|
|
896
|
-
}
|
|
897
|
-
const arrayOfNonInline = getFilterArrayUnionType(typeNode, (member)=>member.type !== "inline");
|
|
898
|
-
const arrayOfInline = getFilterArrayUnionType(typeNode, (member)=>member.type === "inline");
|
|
899
|
-
return t3.tsUnionType([
|
|
900
|
-
this.generateArrayTsType(arrayOfNonInline),
|
|
901
|
-
this.generateArrayTsType(arrayOfInline)
|
|
902
|
-
]);
|
|
903
|
-
}
|
|
904
|
-
// Helper function used to generate TS types for document type nodes.
|
|
905
|
-
generateDocumentTsType(document) {
|
|
906
|
-
const props = Object.entries(document.attributes).map(([key, node])=>this.generateTsObjectProperty(key, node));
|
|
907
|
-
return t3.tsTypeLiteral(props);
|
|
908
|
-
}
|
|
909
|
-
generateInlineTsType(typeNode) {
|
|
910
|
-
const id = this.identifiers.get(typeNode.name);
|
|
911
|
-
if (!id) {
|
|
912
|
-
return t3.addComment(t3.tsUnknownKeyword(), "trailing", ` Unable to locate the referenced type "${typeNode.name}" in schema`, true);
|
|
913
|
-
}
|
|
914
|
-
return t3.tsTypeReference(id);
|
|
915
|
-
}
|
|
916
|
-
// Helper function used to generate TS types for object type nodes.
|
|
917
|
-
generateObjectTsType(typeNode) {
|
|
918
|
-
const props = [];
|
|
919
|
-
for (const [key, attribute] of Object.entries(typeNode.attributes)){
|
|
920
|
-
props.push(this.generateTsObjectProperty(key, attribute));
|
|
921
|
-
}
|
|
922
|
-
const rest = typeNode.rest;
|
|
923
|
-
if (rest) {
|
|
924
|
-
switch(rest.type){
|
|
925
|
-
case "inline":
|
|
926
|
-
{
|
|
927
|
-
const resolved = this.generateInlineTsType(rest);
|
|
928
|
-
if (t3.isTSUnknownKeyword(resolved)) return resolved;
|
|
929
|
-
return t3.tsIntersectionType([
|
|
930
|
-
t3.tsTypeLiteral(props),
|
|
931
|
-
resolved
|
|
932
|
-
]);
|
|
933
|
-
}
|
|
934
|
-
case "object":
|
|
935
|
-
{
|
|
936
|
-
for (const [key, attribute] of Object.entries(rest.attributes)){
|
|
937
|
-
props.push(this.generateTsObjectProperty(key, attribute));
|
|
938
|
-
}
|
|
939
|
-
break;
|
|
940
|
-
}
|
|
941
|
-
case "unknown":
|
|
942
|
-
{
|
|
943
|
-
return t3.tsUnknownKeyword();
|
|
944
|
-
}
|
|
945
|
-
default:
|
|
946
|
-
{
|
|
947
|
-
throw new Error(`Type "${rest.type}" not found in schema`);
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
if (typeNode.dereferencesTo) {
|
|
952
|
-
const derefType = Object.assign(t3.tsPropertySignature(INTERNAL_REFERENCE_SYMBOL, t3.tsTypeAnnotation(t3.tsLiteralType(t3.stringLiteral(typeNode.dereferencesTo)))), {
|
|
953
|
-
computed: true,
|
|
954
|
-
optional: true
|
|
955
|
-
});
|
|
956
|
-
props.push(derefType);
|
|
957
|
-
}
|
|
958
|
-
return t3.tsTypeLiteral(props);
|
|
959
|
-
}
|
|
960
|
-
// Helper function used to generate TS types for object properties.
|
|
961
|
-
generateTsObjectProperty(key, attribute) {
|
|
962
|
-
const type = this.generateTsType(attribute.value);
|
|
963
|
-
const keyNode = isIdentifierName(key) ? t3.identifier(key) : t3.stringLiteral(key);
|
|
964
|
-
const propertySignature = t3.tsPropertySignature(keyNode, t3.tsTypeAnnotation(type));
|
|
965
|
-
propertySignature.optional = attribute.optional;
|
|
966
|
-
return propertySignature;
|
|
967
|
-
}
|
|
968
|
-
generateTsType(typeNode) {
|
|
969
|
-
switch(typeNode.type){
|
|
970
|
-
case "array":
|
|
971
|
-
{
|
|
972
|
-
return this.generateArrayTsType(typeNode);
|
|
973
|
-
}
|
|
974
|
-
case "boolean":
|
|
975
|
-
{
|
|
976
|
-
if (typeNode.value !== void 0) {
|
|
977
|
-
return t3.tsLiteralType(t3.booleanLiteral(typeNode.value));
|
|
978
|
-
}
|
|
979
|
-
return t3.tsBooleanKeyword();
|
|
980
|
-
}
|
|
981
|
-
case "document":
|
|
982
|
-
{
|
|
983
|
-
return this.generateDocumentTsType(typeNode);
|
|
984
|
-
}
|
|
985
|
-
case "inline":
|
|
986
|
-
{
|
|
987
|
-
return this.generateInlineTsType(typeNode);
|
|
988
|
-
}
|
|
989
|
-
case "null":
|
|
990
|
-
{
|
|
991
|
-
return t3.tsNullKeyword();
|
|
992
|
-
}
|
|
993
|
-
case "number":
|
|
994
|
-
{
|
|
995
|
-
if (typeNode.value !== void 0) {
|
|
996
|
-
return t3.tsLiteralType(t3.numericLiteral(typeNode.value));
|
|
997
|
-
}
|
|
998
|
-
return t3.tsNumberKeyword();
|
|
999
|
-
}
|
|
1000
|
-
case "object":
|
|
1001
|
-
{
|
|
1002
|
-
return this.generateObjectTsType(typeNode);
|
|
1003
|
-
}
|
|
1004
|
-
case "string":
|
|
1005
|
-
{
|
|
1006
|
-
if (typeNode.value !== void 0) {
|
|
1007
|
-
return t3.tsLiteralType(t3.stringLiteral(typeNode.value));
|
|
1008
|
-
}
|
|
1009
|
-
return t3.tsStringKeyword();
|
|
1010
|
-
}
|
|
1011
|
-
case "type":
|
|
1012
|
-
{
|
|
1013
|
-
return this.generateTsType(typeNode.value);
|
|
1014
|
-
}
|
|
1015
|
-
case "union":
|
|
1016
|
-
{
|
|
1017
|
-
return this.generateUnionTsType(typeNode);
|
|
1018
|
-
}
|
|
1019
|
-
case "unknown":
|
|
1020
|
-
{
|
|
1021
|
-
return t3.tsUnknownKeyword();
|
|
1022
|
-
}
|
|
1023
|
-
default:
|
|
1024
|
-
{
|
|
1025
|
-
throw new Error(`Encountered unsupported node type "${typeNode.type}" while generating schema types`);
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
}
|
|
1029
|
-
// Helper function used to generate TS types for union type nodes.
|
|
1030
|
-
generateUnionTsType(typeNode) {
|
|
1031
|
-
if (typeNode.of.length === 0) return t3.tsNeverKeyword();
|
|
1032
|
-
if (typeNode.of.length === 1) return this.generateTsType(typeNode.of[0]);
|
|
1033
|
-
return t3.tsUnionType(typeNode.of.map((node)=>this.generateTsType(node)));
|
|
1034
|
-
}
|
|
1035
|
-
};
|
|
1036
|
-
function walkAndCountQueryTypeNodeStats(typeNode) {
|
|
1037
|
-
switch(typeNode.type){
|
|
1038
|
-
case "array":
|
|
1039
|
-
{
|
|
1040
|
-
const acc = walkAndCountQueryTypeNodeStats(typeNode.of);
|
|
1041
|
-
acc.allTypes += 1;
|
|
1042
|
-
return acc;
|
|
1043
|
-
}
|
|
1044
|
-
case "object":
|
|
1045
|
-
{
|
|
1046
|
-
if (typeNode.rest && typeNode.rest.type === "unknown") {
|
|
1047
|
-
return {
|
|
1048
|
-
allTypes: 2,
|
|
1049
|
-
emptyUnions: 0,
|
|
1050
|
-
unknownTypes: 1
|
|
1051
|
-
};
|
|
1052
|
-
}
|
|
1053
|
-
const restStats = typeNode.rest ? walkAndCountQueryTypeNodeStats(typeNode.rest) : {
|
|
1054
|
-
allTypes: 0,
|
|
1055
|
-
emptyUnions: 0,
|
|
1056
|
-
unknownTypes: 0
|
|
1057
|
-
};
|
|
1058
|
-
restStats.allTypes += 1;
|
|
1059
|
-
const attrs = Object.values(typeNode.attributes);
|
|
1060
|
-
let acc = restStats;
|
|
1061
|
-
for (const attribute of attrs){
|
|
1062
|
-
const { allTypes, emptyUnions, unknownTypes } = walkAndCountQueryTypeNodeStats(attribute.value);
|
|
1063
|
-
acc = {
|
|
1064
|
-
allTypes: acc.allTypes + allTypes,
|
|
1065
|
-
emptyUnions: acc.emptyUnions + emptyUnions,
|
|
1066
|
-
unknownTypes: acc.unknownTypes + unknownTypes
|
|
1067
|
-
};
|
|
1068
|
-
}
|
|
1069
|
-
return acc;
|
|
1070
|
-
}
|
|
1071
|
-
case "union":
|
|
1072
|
-
{
|
|
1073
|
-
if (typeNode.of.length === 0) {
|
|
1074
|
-
return {
|
|
1075
|
-
allTypes: 1,
|
|
1076
|
-
emptyUnions: 1,
|
|
1077
|
-
unknownTypes: 0
|
|
1078
|
-
};
|
|
1079
|
-
}
|
|
1080
|
-
let acc = {
|
|
1081
|
-
allTypes: 1,
|
|
1082
|
-
emptyUnions: 0,
|
|
1083
|
-
unknownTypes: 0
|
|
1084
|
-
};
|
|
1085
|
-
for (const type of typeNode.of){
|
|
1086
|
-
const { allTypes, emptyUnions, unknownTypes } = walkAndCountQueryTypeNodeStats(type);
|
|
1087
|
-
acc = {
|
|
1088
|
-
allTypes: acc.allTypes + allTypes,
|
|
1089
|
-
emptyUnions: acc.emptyUnions + emptyUnions,
|
|
1090
|
-
unknownTypes: acc.unknownTypes + unknownTypes
|
|
1091
|
-
};
|
|
1092
|
-
}
|
|
1093
|
-
return acc;
|
|
1094
|
-
}
|
|
1095
|
-
case "unknown":
|
|
1096
|
-
{
|
|
1097
|
-
return {
|
|
1098
|
-
allTypes: 1,
|
|
1099
|
-
emptyUnions: 0,
|
|
1100
|
-
unknownTypes: 1
|
|
1101
|
-
};
|
|
1102
|
-
}
|
|
1103
|
-
default:
|
|
1104
|
-
{
|
|
1105
|
-
return {
|
|
1106
|
-
allTypes: 1,
|
|
1107
|
-
emptyUnions: 0,
|
|
1108
|
-
unknownTypes: 0
|
|
1109
|
-
};
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
// src/typescript/typeGenerator.ts
|
|
1114
|
-
var TypeGenerator = class _TypeGenerator {
|
|
1115
|
-
getSchemaTypeGenerator = createSelector([
|
|
1116
|
-
(options)=>options.schema
|
|
1117
|
-
], (schema)=>new SchemaTypeGenerator(schema));
|
|
1118
|
-
getSchemaTypeDeclarations = createSelector([
|
|
1119
|
-
(options)=>options.root,
|
|
1120
|
-
(options)=>options.schemaPath,
|
|
1121
|
-
this.getSchemaTypeGenerator
|
|
1122
|
-
], (root = process.cwd(), schemaPath, schema)=>[
|
|
1123
|
-
...schema
|
|
1124
|
-
].map(({ id, name, tsType }, index)=>{
|
|
1125
|
-
const typeAlias = t4.tsTypeAliasDeclaration(id, null, tsType);
|
|
1126
|
-
let ast = t4.exportNamedDeclaration(typeAlias);
|
|
1127
|
-
if (index === 0 && schemaPath) {
|
|
1128
|
-
ast = t4.addComments(ast, "leading", [
|
|
1129
|
-
{
|
|
1130
|
-
type: "CommentLine",
|
|
1131
|
-
value: ` Source: ${normalizePrintablePath(root, schemaPath)}`
|
|
1132
|
-
}
|
|
1133
|
-
]);
|
|
1134
|
-
}
|
|
1135
|
-
const code = generateCode(ast);
|
|
1136
|
-
return {
|
|
1137
|
-
ast,
|
|
1138
|
-
code,
|
|
1139
|
-
id,
|
|
1140
|
-
name,
|
|
1141
|
-
tsType
|
|
1142
|
-
};
|
|
1143
|
-
}));
|
|
1144
|
-
getAllSanitySchemaTypesDeclaration = createSelector([
|
|
1145
|
-
this.getSchemaTypeDeclarations
|
|
1146
|
-
], (schemaTypes)=>{
|
|
1147
|
-
const ast = t4.exportNamedDeclaration(t4.tsTypeAliasDeclaration(ALL_SANITY_SCHEMA_TYPES, null, schemaTypes.length > 0 ? t4.tsUnionType(schemaTypes.map(({ id })=>t4.tsTypeReference(id))) : t4.tsNeverKeyword()));
|
|
1148
|
-
const code = generateCode(ast);
|
|
1149
|
-
return {
|
|
1150
|
-
ast,
|
|
1151
|
-
code,
|
|
1152
|
-
id: ALL_SANITY_SCHEMA_TYPES
|
|
1153
|
-
};
|
|
1154
|
-
});
|
|
1155
|
-
getArrayOfDeclaration = computeOnce(()=>{
|
|
1156
|
-
const typeParam = t4.tsTypeParameter(null, null, "T");
|
|
1157
|
-
const intersectionType = t4.tsIntersectionType([
|
|
1158
|
-
t4.tsTypeReference(t4.identifier("T")),
|
|
1159
|
-
t4.tsTypeLiteral([
|
|
1160
|
-
t4.tsPropertySignature(t4.identifier("_key"), t4.tsTypeAnnotation(t4.tsStringKeyword()))
|
|
1161
|
-
])
|
|
1162
|
-
]);
|
|
1163
|
-
const arrayType = t4.tsTypeReference(t4.identifier("Array"), t4.tsTypeParameterInstantiation([
|
|
1164
|
-
intersectionType
|
|
1165
|
-
]));
|
|
1166
|
-
const ast = t4.tsTypeAliasDeclaration(ARRAY_OF, t4.tsTypeParameterDeclaration([
|
|
1167
|
-
typeParam
|
|
1168
|
-
]), arrayType);
|
|
1169
|
-
const code = generateCode(ast);
|
|
1170
|
-
return {
|
|
1171
|
-
ast,
|
|
1172
|
-
code,
|
|
1173
|
-
id: ARRAY_OF
|
|
1174
|
-
};
|
|
1175
|
-
});
|
|
1176
|
-
getInternalReferenceSymbolDeclaration = computeOnce(()=>{
|
|
1177
|
-
const typeOperator = t4.tsTypeOperator(t4.tsSymbolKeyword(), "unique");
|
|
1178
|
-
const id = INTERNAL_REFERENCE_SYMBOL;
|
|
1179
|
-
id.typeAnnotation = t4.tsTypeAnnotation(typeOperator);
|
|
1180
|
-
const declaration = t4.variableDeclaration("const", [
|
|
1181
|
-
t4.variableDeclarator(id)
|
|
1182
|
-
]);
|
|
1183
|
-
declaration.declare = true;
|
|
1184
|
-
const ast = t4.exportNamedDeclaration(declaration);
|
|
1185
|
-
const code = generateCode(ast);
|
|
1186
|
-
return {
|
|
1187
|
-
ast,
|
|
1188
|
-
code,
|
|
1189
|
-
id
|
|
1190
|
-
};
|
|
1191
|
-
});
|
|
1192
|
-
static async getEvaluatedModules({ queries: extractedModules, reporter: report, root = process.cwd(), schemaTypeDeclarations, schemaTypeGenerator }) {
|
|
1193
|
-
if (!extractedModules) {
|
|
1194
|
-
report?.stream.evaluatedModules.end();
|
|
1195
|
-
return [];
|
|
1196
|
-
}
|
|
1197
|
-
const currentIdentifiers = new Set(schemaTypeDeclarations.map(({ id })=>id.name));
|
|
1198
|
-
const evaluatedModuleResults = [];
|
|
1199
|
-
for await (const { filename, ...extractedModule } of extractedModules){
|
|
1200
|
-
const queries = [];
|
|
1201
|
-
const errors = [
|
|
1202
|
-
...extractedModule.errors
|
|
1203
|
-
];
|
|
1204
|
-
for (const extractedQuery of extractedModule.queries){
|
|
1205
|
-
const { variable } = extractedQuery;
|
|
1206
|
-
try {
|
|
1207
|
-
const { stats, tsType } = schemaTypeGenerator.evaluateQuery(extractedQuery);
|
|
1208
|
-
const id = getUniqueIdentifierForName(resultSuffix(variable.id.name), currentIdentifiers);
|
|
1209
|
-
const typeAlias = t4.tsTypeAliasDeclaration(id, null, tsType);
|
|
1210
|
-
const trimmedQuery = extractedQuery.query.replaceAll(/(\r\n|\n|\r)/gm, "").trim();
|
|
1211
|
-
const ast = t4.addComments(t4.exportNamedDeclaration(typeAlias), "leading", [
|
|
1212
|
-
{
|
|
1213
|
-
type: "CommentLine",
|
|
1214
|
-
value: ` Source: ${normalizePrintablePath(root, filename)}`
|
|
1215
|
-
},
|
|
1216
|
-
{
|
|
1217
|
-
type: "CommentLine",
|
|
1218
|
-
value: ` Variable: ${variable.id.name}`
|
|
1219
|
-
},
|
|
1220
|
-
{
|
|
1221
|
-
type: "CommentLine",
|
|
1222
|
-
value: ` Query: ${trimmedQuery}`
|
|
1223
|
-
}
|
|
1224
|
-
]);
|
|
1225
|
-
const evaluatedQueryResult = {
|
|
1226
|
-
ast,
|
|
1227
|
-
code: generateCode(ast),
|
|
1228
|
-
id,
|
|
1229
|
-
stats,
|
|
1230
|
-
tsType,
|
|
1231
|
-
...extractedQuery
|
|
1232
|
-
};
|
|
1233
|
-
currentIdentifiers.add(id.name);
|
|
1234
|
-
queries.push(evaluatedQueryResult);
|
|
1235
|
-
} catch (cause) {
|
|
1236
|
-
errors.push(new QueryEvaluationError({
|
|
1237
|
-
cause,
|
|
1238
|
-
filename,
|
|
1239
|
-
variable
|
|
1240
|
-
}));
|
|
1241
|
-
}
|
|
1242
|
-
}
|
|
1243
|
-
const evaluatedModule = {
|
|
1244
|
-
errors,
|
|
1245
|
-
filename,
|
|
1246
|
-
queries
|
|
1247
|
-
};
|
|
1248
|
-
report?.stream.evaluatedModules.emit(evaluatedModule);
|
|
1249
|
-
evaluatedModuleResults.push(evaluatedModule);
|
|
1250
|
-
}
|
|
1251
|
-
report?.stream.evaluatedModules.end();
|
|
1252
|
-
return evaluatedModuleResults;
|
|
1253
|
-
}
|
|
1254
|
-
static async getQueryMapDeclaration({ evaluatedModules, overloadClientMethods = true }) {
|
|
1255
|
-
if (!overloadClientMethods) return {
|
|
1256
|
-
ast: t4.program([]),
|
|
1257
|
-
code: ""
|
|
1258
|
-
};
|
|
1259
|
-
const queries = evaluatedModules.flatMap((module)=>module.queries);
|
|
1260
|
-
if (queries.length === 0) return {
|
|
1261
|
-
ast: t4.program([]),
|
|
1262
|
-
code: ""
|
|
1263
|
-
};
|
|
1264
|
-
const typesByQuerystring = {};
|
|
1265
|
-
for (const { id, query } of queries){
|
|
1266
|
-
typesByQuerystring[query] ??= [];
|
|
1267
|
-
typesByQuerystring[query].push(id.name);
|
|
1268
|
-
}
|
|
1269
|
-
const queryReturnInterface = t4.tsInterfaceDeclaration(SANITY_QUERIES, null, [], t4.tsInterfaceBody(Object.entries(typesByQuerystring).map(([query, types])=>{
|
|
1270
|
-
return t4.tsPropertySignature(t4.stringLiteral(query), t4.tsTypeAnnotation(types.length > 0 ? t4.tsUnionType(types.map((type)=>t4.tsTypeReference(t4.identifier(type)))) : t4.tsNeverKeyword()));
|
|
1271
|
-
})));
|
|
1272
|
-
const declareModule2 = t4.declareModule(t4.stringLiteral("@sanity/client"), t4.blockStatement([
|
|
1273
|
-
queryReturnInterface
|
|
1274
|
-
]));
|
|
1275
|
-
const clientImport = t4.addComments(t4.importDeclaration([], t4.stringLiteral("@sanity/client")), "leading", [
|
|
1276
|
-
{
|
|
1277
|
-
type: "CommentLine",
|
|
1278
|
-
value: " Query TypeMap"
|
|
1279
|
-
}
|
|
1280
|
-
]);
|
|
1281
|
-
const ast = t4.program([
|
|
1282
|
-
clientImport,
|
|
1283
|
-
declareModule2
|
|
1284
|
-
]);
|
|
1285
|
-
const code = generateCode(ast);
|
|
1286
|
-
return {
|
|
1287
|
-
ast,
|
|
1288
|
-
code
|
|
1289
|
-
};
|
|
1290
|
-
}
|
|
1291
|
-
async generateTypes(options) {
|
|
1292
|
-
const { reporter: report } = options;
|
|
1293
|
-
const internalReferenceSymbol = this.getInternalReferenceSymbolDeclaration();
|
|
1294
|
-
const arrayOfDeclaration = this.getArrayOfDeclaration();
|
|
1295
|
-
const schemaTypeDeclarations = this.getSchemaTypeDeclarations(options);
|
|
1296
|
-
const allSanitySchemaTypesDeclaration = this.getAllSanitySchemaTypesDeclaration(options);
|
|
1297
|
-
report?.event.generatedSchemaTypes({
|
|
1298
|
-
allSanitySchemaTypesDeclaration,
|
|
1299
|
-
internalReferenceSymbol,
|
|
1300
|
-
schemaTypeDeclarations
|
|
1301
|
-
});
|
|
1302
|
-
const program2 = t4.program([]);
|
|
1303
|
-
let code = "";
|
|
1304
|
-
for (const declaration of schemaTypeDeclarations){
|
|
1305
|
-
program2.body.push(declaration.ast);
|
|
1306
|
-
code += declaration.code;
|
|
1307
|
-
}
|
|
1308
|
-
program2.body.push(allSanitySchemaTypesDeclaration.ast);
|
|
1309
|
-
code += allSanitySchemaTypesDeclaration.code;
|
|
1310
|
-
program2.body.push(internalReferenceSymbol.ast);
|
|
1311
|
-
code += internalReferenceSymbol.code;
|
|
1312
|
-
program2.body.push(arrayOfDeclaration.ast);
|
|
1313
|
-
code += arrayOfDeclaration.code;
|
|
1314
|
-
const evaluatedModules = await _TypeGenerator.getEvaluatedModules({
|
|
1315
|
-
...options,
|
|
1316
|
-
schemaTypeDeclarations,
|
|
1317
|
-
schemaTypeGenerator: this.getSchemaTypeGenerator(options)
|
|
1318
|
-
});
|
|
1319
|
-
for (const { queries } of evaluatedModules){
|
|
1320
|
-
for (const query of queries){
|
|
1321
|
-
program2.body.push(query.ast);
|
|
1322
|
-
code += query.code;
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1325
|
-
const queryMapDeclaration = await _TypeGenerator.getQueryMapDeclaration({
|
|
1326
|
-
...options,
|
|
1327
|
-
evaluatedModules
|
|
1328
|
-
});
|
|
1329
|
-
program2.body.push(...queryMapDeclaration.ast.body);
|
|
1330
|
-
code += queryMapDeclaration.code;
|
|
1331
|
-
report?.event.generatedQueryTypes({
|
|
1332
|
-
queryMapDeclaration
|
|
1333
|
-
});
|
|
1334
|
-
return {
|
|
1335
|
-
ast: program2,
|
|
1336
|
-
code
|
|
1337
|
-
};
|
|
1338
|
-
}
|
|
1339
|
-
};
|
|
1340
|
-
// src/actions/typegenGenerate.worker.ts
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
2
|
+
import { isAbsolute, join } from 'node:path';
|
|
3
|
+
import { isMainThread, parentPort, workerData } from 'node:worker_threads';
|
|
4
|
+
import { WorkerChannelReporter } from '@sanity/worker-channels';
|
|
5
|
+
import { readSchema } from '../readSchema.js';
|
|
6
|
+
import { findQueriesInPath } from '../typescript/findQueriesInPath.js';
|
|
7
|
+
import { getResolver } from '../typescript/moduleResolver.js';
|
|
8
|
+
import { registerBabel } from '../typescript/registerBabel.js';
|
|
9
|
+
import { TypeGenerator } from '../typescript/typeGenerator.js';
|
|
1341
10
|
if (isMainThread || !parentPort) {
|
|
1342
|
-
throw new Error(
|
|
11
|
+
throw new Error('This module must be run as a worker thread');
|
|
1343
12
|
}
|
|
1344
13
|
registerBabel();
|
|
1345
14
|
async function main({ overloadClientMethods, schemaPath, searchPath, workDir }) {
|
|
1346
15
|
const report = WorkerChannelReporter.from(parentPort);
|
|
1347
|
-
const fullPath = isAbsolute(schemaPath) ? schemaPath :
|
|
16
|
+
const fullPath = isAbsolute(schemaPath) ? schemaPath : join(workDir, schemaPath);
|
|
1348
17
|
try {
|
|
1349
18
|
const schemaStats = await stat(fullPath);
|
|
1350
19
|
if (!schemaStats.isFile()) {
|
|
1351
20
|
throw new Error(`Schema path is not a file: ${schemaPath}`);
|
|
1352
21
|
}
|
|
1353
22
|
} catch (err) {
|
|
1354
|
-
if (err instanceof Error &&
|
|
1355
|
-
|
|
23
|
+
if (err instanceof Error && 'code' in err && err.code === 'ENOENT') {
|
|
24
|
+
// If the user has not provided a specific schema path (eg we're using the default), give some help
|
|
25
|
+
const hint = schemaPath === './schema.json' ? ` - did you run "sanity schema extract"?` : '';
|
|
1356
26
|
throw new Error(`Schema file not found: ${fullPath}${hint}`, {
|
|
1357
27
|
cause: err
|
|
1358
28
|
});
|