sanity 5.2.1-next.2 → 5.3.0-next.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/_chunks-es/extractAction.js +216 -6
- package/lib/_chunks-es/extractAction.js.map +1 -1
- package/lib/_chunks-es/formatSchemaValidation.js +60 -0
- package/lib/_chunks-es/formatSchemaValidation.js.map +1 -0
- package/lib/_chunks-es/package.js +1 -1
- package/lib/_chunks-es/validateAction.js +1 -48
- package/lib/_chunks-es/validateAction.js.map +1 -1
- package/lib/_chunks-es/version.js +1 -1
- package/package.json +13 -13
|
@@ -1,9 +1,189 @@
|
|
|
1
1
|
import { writeFile } from "node:fs/promises";
|
|
2
|
-
import { dirname, join } from "node:path";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
2
|
+
import path, { dirname, join } from "node:path";
|
|
3
|
+
import { pathToFileURL, fileURLToPath } from "node:url";
|
|
4
4
|
import { Worker } from "node:worker_threads";
|
|
5
5
|
import readPkgUp from "read-pkg-up";
|
|
6
|
+
import { resolveConfig, SchemaError } from "sanity";
|
|
7
|
+
import fs from "node:fs";
|
|
8
|
+
import Module, { createRequire, register as register$1 } from "node:module";
|
|
9
|
+
import { firstValueFrom } from "rxjs";
|
|
10
|
+
import { ResizeObserver } from "@juggle/resize-observer";
|
|
11
|
+
import { register } from "esbuild-register/dist/node";
|
|
12
|
+
import jsdomGlobal from "jsdom-global";
|
|
13
|
+
import { addHook } from "pirates";
|
|
14
|
+
import resolveFrom from "resolve-from";
|
|
15
|
+
import { getStudioEnvironmentVariables } from "./cli.js";
|
|
6
16
|
import { defineTrace } from "@sanity/telemetry";
|
|
17
|
+
import { formatSchemaValidation } from "./formatSchemaValidation.js";
|
|
18
|
+
function getProxyHandler() {
|
|
19
|
+
const handler = {
|
|
20
|
+
get: (_target, prop) => prop === "__esModule" ? !0 : prop === "default" ? new Proxy({}, handler) : new Proxy({}, handler),
|
|
21
|
+
apply: () => new Proxy({}, handler)
|
|
22
|
+
};
|
|
23
|
+
return new Proxy({}, handler);
|
|
24
|
+
}
|
|
25
|
+
function setupImportErrorHandler() {
|
|
26
|
+
const ModuleConstructor = Module, originalLoad = ModuleConstructor._load;
|
|
27
|
+
return ModuleConstructor._load = function(request, parent, isMain) {
|
|
28
|
+
try {
|
|
29
|
+
return originalLoad.call(this, request, parent, isMain);
|
|
30
|
+
} catch (error) {
|
|
31
|
+
if (request.startsWith("https://themer.sanity.build/api/"))
|
|
32
|
+
return getProxyHandler();
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
}, {
|
|
36
|
+
cleanup: () => {
|
|
37
|
+
ModuleConstructor._load = originalLoad;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const require$2 = createRequire(import.meta.url);
|
|
42
|
+
register$1("./mock-browser-env-stub-loader.mjs", pathToFileURL(require$2.resolve("sanity/package.json")));
|
|
43
|
+
const jsdomDefaultHtml = `<!doctype html>
|
|
44
|
+
<html>
|
|
45
|
+
<head><meta charset="utf-8"></head>
|
|
46
|
+
<body></body>
|
|
47
|
+
</html>`;
|
|
48
|
+
function mockBrowserEnvironment(basePath) {
|
|
49
|
+
if (global && global.window && "__mockedBySanity" in global.window)
|
|
50
|
+
return () => {
|
|
51
|
+
};
|
|
52
|
+
const importErrorHandler = setupImportErrorHandler(), btoa = global.btoa, domCleanup = jsdomGlobal(jsdomDefaultHtml, {
|
|
53
|
+
url: "http://localhost:3333/"
|
|
54
|
+
});
|
|
55
|
+
typeof btoa == "function" && (global.btoa = btoa);
|
|
56
|
+
const windowCleanup = () => global.window.close(), globalCleanup = provideFakeGlobals(basePath), cleanupFileLoader = addHook((code, filename) => `module.exports = ${JSON.stringify(filename)}`, {
|
|
57
|
+
ignoreNodeModules: !1,
|
|
58
|
+
exts: getFileExtensions()
|
|
59
|
+
}), {
|
|
60
|
+
unregister: unregisterESBuild
|
|
61
|
+
} = register({
|
|
62
|
+
target: "node18",
|
|
63
|
+
supported: {
|
|
64
|
+
"dynamic-import": !0
|
|
65
|
+
},
|
|
66
|
+
format: "cjs",
|
|
67
|
+
extensions: [".js", ".jsx", ".ts", ".tsx", ".mjs"],
|
|
68
|
+
jsx: "automatic",
|
|
69
|
+
define: {
|
|
70
|
+
// define the `process.env` global
|
|
71
|
+
...getStudioEnvironmentVariables({
|
|
72
|
+
prefix: "process.env.",
|
|
73
|
+
jsonEncode: !0
|
|
74
|
+
}),
|
|
75
|
+
// define the `import.meta.env` global
|
|
76
|
+
...getStudioEnvironmentVariables({
|
|
77
|
+
prefix: "import.meta.env.",
|
|
78
|
+
jsonEncode: !0
|
|
79
|
+
}),
|
|
80
|
+
// define the `import.meta.hot` global, so we don't get `"import.meta" is not available with the "cjs" output format and will be empty` warnings
|
|
81
|
+
"import.meta.hot": "false"
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
return function() {
|
|
85
|
+
unregisterESBuild(), cleanupFileLoader(), globalCleanup(), windowCleanup(), domCleanup(), importErrorHandler.cleanup();
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const getFakeGlobals = (basePath) => ({
|
|
89
|
+
__mockedBySanity: !0,
|
|
90
|
+
requestAnimationFrame: setImmediate,
|
|
91
|
+
cancelAnimationFrame: clearImmediate,
|
|
92
|
+
requestIdleCallback: setImmediate,
|
|
93
|
+
cancelIdleCallback: clearImmediate,
|
|
94
|
+
ace: tryGetAceGlobal(basePath),
|
|
95
|
+
InputEvent: global.window?.InputEvent,
|
|
96
|
+
customElements: global.window?.customElements,
|
|
97
|
+
ResizeObserver: global.window?.ResizeObserver || ResizeObserver,
|
|
98
|
+
matchMedia: global.window?.matchMedia || (() => ({
|
|
99
|
+
matches: !1,
|
|
100
|
+
media: "",
|
|
101
|
+
onchange: null
|
|
102
|
+
}))
|
|
103
|
+
}), getFakeDocumentProps = () => ({
|
|
104
|
+
execCommand: function(_commandName, _showDefaultUI, _valueArgument) {
|
|
105
|
+
return !1;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
function provideFakeGlobals(basePath) {
|
|
109
|
+
const globalEnv = global, globalWindow = global.window, globalDocument = global.document || document || {}, fakeGlobals = getFakeGlobals(basePath), fakeDocumentProps = getFakeDocumentProps(), stubbedGlobalKeys = [], stubbedWindowKeys = [], stubbedDocumentKeys = [];
|
|
110
|
+
for (const [rawKey, value] of Object.entries(fakeGlobals)) {
|
|
111
|
+
if (typeof value > "u")
|
|
112
|
+
continue;
|
|
113
|
+
const key = rawKey;
|
|
114
|
+
key in globalEnv || (globalEnv[key] = fakeGlobals[key], stubbedGlobalKeys.push(key)), key in global.window || (globalWindow[key] = fakeGlobals[key], stubbedWindowKeys.push(key));
|
|
115
|
+
}
|
|
116
|
+
for (const [rawKey, value] of Object.entries(fakeDocumentProps)) {
|
|
117
|
+
if (typeof value > "u")
|
|
118
|
+
continue;
|
|
119
|
+
const key = rawKey;
|
|
120
|
+
key in globalDocument || (globalDocument[key] = fakeDocumentProps[key], stubbedDocumentKeys.push(key));
|
|
121
|
+
}
|
|
122
|
+
return () => {
|
|
123
|
+
stubbedGlobalKeys.forEach((key) => {
|
|
124
|
+
delete globalEnv[key];
|
|
125
|
+
}), stubbedWindowKeys.forEach((key) => {
|
|
126
|
+
delete globalWindow[key];
|
|
127
|
+
}), stubbedDocumentKeys.forEach((key) => {
|
|
128
|
+
delete globalDocument[key];
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function tryGetAceGlobal(basePath) {
|
|
133
|
+
const acePath = resolveFrom.silent(basePath, "ace-builds");
|
|
134
|
+
if (acePath)
|
|
135
|
+
try {
|
|
136
|
+
return require$2(acePath);
|
|
137
|
+
} catch {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function getFileExtensions() {
|
|
142
|
+
return [".css", ".eot", ".gif", ".jpeg", ".jpg", ".otf", ".png", ".sass", ".scss", ".svg", ".ttf", ".webp", ".woff", ".woff2"];
|
|
143
|
+
}
|
|
144
|
+
const require$1 = createRequire(import.meta.url), candidates = ["sanity.config.js", "sanity.config.jsx", "sanity.config.ts", "sanity.config.tsx"];
|
|
145
|
+
function getStudioConfig({
|
|
146
|
+
basePath,
|
|
147
|
+
configPath: cfgPath
|
|
148
|
+
}) {
|
|
149
|
+
let cleanup;
|
|
150
|
+
try {
|
|
151
|
+
cleanup = mockBrowserEnvironment(basePath);
|
|
152
|
+
let configPath = cfgPath;
|
|
153
|
+
if (configPath && !fs.existsSync(configPath))
|
|
154
|
+
throw new Error(`Failed to find config at "${cfgPath}"`);
|
|
155
|
+
if (configPath || (configPath = candidates.map((candidate) => path.join(basePath, candidate)).find((candidate) => fs.existsSync(candidate))), !configPath)
|
|
156
|
+
throw new Error(`Failed to resolve sanity.config.(js|ts) for base path "${basePath}"`);
|
|
157
|
+
let config;
|
|
158
|
+
try {
|
|
159
|
+
const mod = require$1(configPath);
|
|
160
|
+
config = mod.__esModule && mod.default ? mod.default : mod;
|
|
161
|
+
} catch (err) {
|
|
162
|
+
throw new Error(`Failed to load configuration file "${configPath}"`, {
|
|
163
|
+
cause: err
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
if (!config) throw new Error("Configuration did not export expected config shape");
|
|
167
|
+
return Array.isArray(config) ? config : [{
|
|
168
|
+
...config,
|
|
169
|
+
name: config.name || "default",
|
|
170
|
+
basePath: config.basePath || "/"
|
|
171
|
+
}];
|
|
172
|
+
} finally {
|
|
173
|
+
cleanup?.();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
async function getStudioWorkspaces(options) {
|
|
177
|
+
let cleanup;
|
|
178
|
+
try {
|
|
179
|
+
cleanup = mockBrowserEnvironment(options.basePath);
|
|
180
|
+
const config = getStudioConfig(options), workspaces = await firstValueFrom(resolveConfig(config));
|
|
181
|
+
if (!workspaces) throw new Error("Failed to resolve configuration");
|
|
182
|
+
return workspaces;
|
|
183
|
+
} finally {
|
|
184
|
+
cleanup?.();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
7
187
|
const SchemaExtractedTrace = defineTrace({
|
|
8
188
|
name: "Schema Extracted",
|
|
9
189
|
version: 0,
|
|
@@ -43,13 +223,43 @@ async function extractAction(args, {
|
|
|
43
223
|
enforceRequiredFields,
|
|
44
224
|
schemaFormat: formatFlag
|
|
45
225
|
});
|
|
46
|
-
const
|
|
47
|
-
spinner.text = `Writing schema to ${
|
|
48
|
-
`), trace.complete(), spinner.succeed(enforceRequiredFields ? `Extracted schema to ${
|
|
226
|
+
const path2 = flags.path || join(process.cwd(), "schema.json");
|
|
227
|
+
spinner.text = `Writing schema to ${path2}`, await writeFile(path2, `${JSON.stringify(schema, null, 2)}
|
|
228
|
+
`), trace.complete(), spinner.succeed(enforceRequiredFields ? `Extracted schema to ${path2} with enforced required fields` : `Extracted schema to ${path2}`);
|
|
49
229
|
} catch (err) {
|
|
50
|
-
|
|
230
|
+
if (trace.error(err), spinner.fail(enforceRequiredFields ? "Failed to extract schema, with enforced required fields" : "Failed to extract schema"), isSchemaError(err))
|
|
231
|
+
try {
|
|
232
|
+
await getStudioWorkspaces({
|
|
233
|
+
basePath: workDir
|
|
234
|
+
});
|
|
235
|
+
} catch (innerErr) {
|
|
236
|
+
const validation = extractValidationFromCoreSchemaError(innerErr);
|
|
237
|
+
throw validation && validation.length > 0 && (output.print(""), output.print(formatSchemaValidation(validation))), err;
|
|
238
|
+
}
|
|
239
|
+
throw err;
|
|
51
240
|
}
|
|
52
241
|
}
|
|
242
|
+
function isValidationProblemGroup(item) {
|
|
243
|
+
if (typeof item != "object" || item === null)
|
|
244
|
+
return !1;
|
|
245
|
+
const group = item;
|
|
246
|
+
return Array.isArray(group.path) && Array.isArray(group.problems);
|
|
247
|
+
}
|
|
248
|
+
function extractValidationFromCoreSchemaError(error) {
|
|
249
|
+
if (!(error instanceof SchemaError))
|
|
250
|
+
return null;
|
|
251
|
+
const schema = error.schema;
|
|
252
|
+
if (!schema || typeof schema != "object")
|
|
253
|
+
return null;
|
|
254
|
+
const validation = schema._validation;
|
|
255
|
+
return !Array.isArray(validation) || !validation.every(isValidationProblemGroup) ? null : validation;
|
|
256
|
+
}
|
|
257
|
+
function isSchemaError(err) {
|
|
258
|
+
if (typeof err != "object" || err === null)
|
|
259
|
+
return !1;
|
|
260
|
+
const errorLike = err, hasSchemaErrorName = errorLike.name === "SchemaError", hasSchemaErrorMessage = errorLike.message === "SchemaError";
|
|
261
|
+
return hasSchemaErrorName || hasSchemaErrorMessage;
|
|
262
|
+
}
|
|
53
263
|
export {
|
|
54
264
|
extractAction as default
|
|
55
265
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractAction.js","sources":["../../src/_internal/cli/actions/schema/extractSchema.telemetry.ts","../../src/_internal/cli/actions/schema/extractAction.ts"],"sourcesContent":["import {defineTrace} from '@sanity/telemetry'\n\ninterface SchemaExtractedTraceAttrubutes {\n schemaAllTypesCount: number\n schemaDocumentTypesCount: number\n schemaTypesCount: number\n\n enforceRequiredFields: boolean\n schemaFormat: string\n}\n\nexport const SchemaExtractedTrace = defineTrace<SchemaExtractedTraceAttrubutes>({\n name: 'Schema Extracted',\n version: 0,\n description: 'Trace emitted when extracting schema',\n})\n","import {writeFile} from 'node:fs/promises'\nimport {dirname, join} from 'node:path'\nimport {fileURLToPath} from 'node:url'\nimport {Worker} from 'node:worker_threads'\n\nimport {type CliCommandArguments, type CliCommandContext} from '@sanity/cli'\nimport readPkgUp from 'read-pkg-up'\n\nimport {\n type ExtractSchemaWorkerData,\n type ExtractSchemaWorkerResult,\n} from '../../threads/extractSchema'\nimport {SchemaExtractedTrace} from './extractSchema.telemetry'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\ninterface ExtractFlags {\n 'workspace'?: string\n 'path'?: string\n 'enforce-required-fields'?: boolean\n 'format'?: 'groq-type-nodes' | string\n}\n\nexport type SchemaValidationFormatter = (result: ExtractSchemaWorkerResult) => string\n\nexport default async function extractAction(\n args: CliCommandArguments<ExtractFlags>,\n {workDir, output, telemetry}: CliCommandContext,\n): Promise<void> {\n const flags = args.extOptions\n const formatFlag = flags.format || 'groq-type-nodes'\n const enforceRequiredFields = flags['enforce-required-fields'] || false\n\n const rootPkgPath = readPkgUp.sync({cwd: __dirname})?.path\n if (!rootPkgPath) {\n throw new Error('Could not find root directory for `sanity` package')\n }\n\n const workerPath = join(\n dirname(rootPkgPath),\n 'lib',\n '_internal',\n 'cli',\n 'threads',\n 'extractSchema.cjs',\n )\n\n const spinner = output\n .spinner({})\n .start(\n enforceRequiredFields\n ? 'Extracting schema, with enforced required fields'\n : 'Extracting schema',\n )\n\n const trace = telemetry.trace(SchemaExtractedTrace)\n trace.start()\n\n const worker = new Worker(workerPath, {\n workerData: {\n workDir,\n workspaceName: flags.workspace,\n enforceRequiredFields,\n format: formatFlag,\n } satisfies ExtractSchemaWorkerData,\n env: process.env,\n })\n\n try {\n const {schema} = await new Promise<ExtractSchemaWorkerResult>((resolve, reject) => {\n worker.addListener('message', resolve)\n worker.addListener('error', reject)\n })\n\n trace.log({\n schemaAllTypesCount: schema.length,\n schemaDocumentTypesCount: schema.filter((type) => type.type === 'document').length,\n schemaTypesCount: schema.filter((type) => type.type === 'type').length,\n enforceRequiredFields,\n schemaFormat: formatFlag,\n })\n\n const path = flags.path || join(process.cwd(), 'schema.json')\n\n spinner.text = `Writing schema to ${path}`\n\n await writeFile(path, `${JSON.stringify(schema, null, 2)}\\n`)\n\n trace.complete()\n\n spinner.succeed(\n enforceRequiredFields\n ? `Extracted schema to ${path} with enforced required fields`\n : `Extracted schema to ${path}`,\n )\n } catch (err) {\n trace.error(err)\n spinner.fail(\n enforceRequiredFields\n ? 'Failed to extract schema, with enforced required fields'\n : 'Failed to extract schema',\n )\n throw err\n }\n}\n"],"names":["SchemaExtractedTrace","defineTrace","name","version","description","__dirname","dirname","fileURLToPath","import","url","extractAction","args","workDir","output","telemetry","flags","extOptions","formatFlag","format","enforceRequiredFields","rootPkgPath","readPkgUp","sync","cwd","path","Error","workerPath","join","spinner","start","trace","worker","Worker","workerData","workspaceName","workspace","env","process","schema","Promise","resolve","reject","addListener","log","schemaAllTypesCount","length","schemaDocumentTypesCount","filter","type","schemaTypesCount","schemaFormat","text","writeFile","JSON","stringify","complete","succeed","err","error","fail"],"mappings":";;;;;;AAWO,MAAMA,uBAAuBC,YAA4C;AAAA,EAC9EC,MAAM;AAAA,EACNC,SAAS;AAAA,EACTC,aAAa;AACf,CAAC,GCDKC,cAAYC,QAAQC,cAAcC,YAAYC,GAAG,CAAC;AAWxD,eAA8BC,cAC5BC,MACA;AAAA,EAACC;AAAAA,EAASC;AAAAA,EAAQC;AAA4B,GAC/B;AACf,QAAMC,QAAQJ,KAAKK,YACbC,aAAaF,MAAMG,UAAU,mBAC7BC,wBAAwBJ,MAAM,yBAAyB,KAAK,IAE5DK,cAAcC,UAAUC,KAAK;AAAA,IAACC,KAAKlB;AAAAA,EAAAA,CAAU,GAAGmB;AACtD,MAAI,CAACJ;AACH,UAAM,IAAIK,MAAM,oDAAoD;AAGtE,QAAMC,aAAaC,KACjBrB,QAAQc,WAAW,GACnB,OACA,aACA,OACA,WACA,mBACF,GAEMQ,UAAUf,OACbe,QAAQ,CAAA,CAAE,EACVC,MACCV,wBACI,qDACA,mBACN,GAEIW,QAAQhB,UAAUgB,MAAM9B,oBAAoB;AAClD8B,QAAMD,MAAAA;AAEN,QAAME,SAAS,IAAIC,OAAON,YAAY;AAAA,IACpCO,YAAY;AAAA,MACVrB;AAAAA,MACAsB,eAAenB,MAAMoB;AAAAA,MACrBhB;AAAAA,MACAD,QAAQD;AAAAA,IAAAA;AAAAA,IAEVmB,KAAKC,QAAQD;AAAAA,EAAAA,CACd;AAED,MAAI;AACF,UAAM;AAAA,MAACE;AAAAA,IAAAA,IAAU,MAAM,IAAIC,QAAmC,CAACC,SAASC,WAAW;AACjFV,aAAOW,YAAY,WAAWF,OAAO,GACrCT,OAAOW,YAAY,SAASD,MAAM;AAAA,IACpC,CAAC;AAEDX,UAAMa,IAAI;AAAA,MACRC,qBAAqBN,OAAOO;AAAAA,MAC5BC,0BAA0BR,OAAOS,OAAQC,UAASA,KAAKA,SAAS,UAAU,EAAEH;AAAAA,MAC5EI,kBAAkBX,OAAOS,OAAQC,UAASA,KAAKA,SAAS,MAAM,EAAEH;AAAAA,MAChE1B;AAAAA,MACA+B,cAAcjC;AAAAA,IAAAA,CACf;AAED,UAAMO,OAAOT,MAAMS,QAAQG,KAAKU,QAAQd,IAAAA,GAAO,aAAa;AAE5DK,YAAQuB,OAAO,qBAAqB3B,IAAI,IAExC,MAAM4B,UAAU5B,MAAM,GAAG6B,KAAKC,UAAUhB,QAAQ,MAAM,CAAC,CAAC;AAAA,CAAI,GAE5DR,MAAMyB,SAAAA,GAEN3B,QAAQ4B,QACNrC,wBACI,uBAAuBK,IAAI,mCAC3B,uBAAuBA,IAAI,EACjC;AAAA,EACF,SAASiC,KAAK;AACZ3B,UAAAA,MAAM4B,MAAMD,GAAG,GACf7B,QAAQ+B,KACNxC,wBACI,4DACA,0BACN,GACMsC;AAAAA,EACR;AACF;"}
|
|
1
|
+
{"version":3,"file":"extractAction.js","sources":["../../src/_internal/cli/util/importErrorHandler.ts","../../src/_internal/cli/util/mockBrowserEnvironment.ts","../../src/_internal/cli/util/getStudioWorkspaces.ts","../../src/_internal/cli/actions/schema/extractSchema.telemetry.ts","../../src/_internal/cli/actions/schema/extractAction.ts"],"sourcesContent":["import Module from 'node:module'\n\nexport interface ImportErrorHandlerResult {\n cleanup: () => void\n}\n\n// Module._load is an internal Node.js API not exposed in types\ninterface ModuleConstructor {\n _load(request: string, parent: Module | undefined, isMain: boolean): any\n}\n\n/**\n * Return safe empty module with Proxy for deep property access. This ensures any property\n * access or function call returns a safe value\n */\nfunction getProxyHandler() {\n const handler: ProxyHandler<object> = {\n get: (_target, prop) => {\n if (prop === '__esModule') return true\n if (prop === 'default') return new Proxy({}, handler)\n return new Proxy({}, handler)\n },\n apply: () => new Proxy({}, handler),\n }\n return new Proxy({}, handler)\n}\n\n/**\n * Sets up a Module._load wrapper to silently ignore imports from https://themer.sanity.build\n * This allows users to use themer URL imports in their config without breaking CLI commands.\n *\n * @returns Handler result with cleanup function\n * @internal\n */\nexport function setupImportErrorHandler(): ImportErrorHandlerResult {\n // Store original Module._load\n const ModuleConstructor = Module as unknown as ModuleConstructor\n const originalLoad = ModuleConstructor._load\n\n // Override Module._load to catch and handle themer.sanity.build imports\n ModuleConstructor._load = function (\n request: string,\n parent: Module | undefined,\n isMain: boolean,\n ) {\n try {\n return originalLoad.call(this, request, parent, isMain)\n } catch (error) {\n // Check if this is a themer.sanity.build URL import\n if (request.startsWith('https://themer.sanity.build/api/')) {\n // Return a safe proxy object that can be used in place of the theme\n return getProxyHandler()\n }\n\n // Re-throw all other errors\n throw error\n }\n }\n\n return {\n cleanup: () => {\n ModuleConstructor._load = originalLoad\n },\n }\n}\n","import {createRequire, register} from 'node:module'\nimport {pathToFileURL} from 'node:url'\n\nimport {ResizeObserver} from '@juggle/resize-observer'\nimport {register as registerESBuild} from 'esbuild-register/dist/node'\nimport jsdomGlobal from 'jsdom-global'\nimport {addHook} from 'pirates'\nimport resolveFrom from 'resolve-from'\n\nimport {getStudioEnvironmentVariables} from '../server/getStudioEnvironmentVariables'\nimport {setupImportErrorHandler} from './importErrorHandler'\n\nconst require = createRequire(import.meta.url)\n\n// Handle require(esm) cases that breaks free from esbuild-register+pirates\nregister(\n './mock-browser-env-stub-loader.mjs',\n pathToFileURL(require.resolve('sanity/package.json')),\n)\n\nconst jsdomDefaultHtml = `<!doctype html>\n<html>\n <head><meta charset=\"utf-8\"></head>\n <body></body>\n</html>`\n\nexport function mockBrowserEnvironment(basePath: string): () => void {\n // Guard against double-registering\n if (global && global.window && '__mockedBySanity' in global.window) {\n return () => {\n /* intentional noop */\n }\n }\n\n // Set up import error handler before esbuild-register to silently ignore themer.sanity.build URLs\n const importErrorHandler = setupImportErrorHandler()\n\n const btoa = global.btoa\n const domCleanup = jsdomGlobal(jsdomDefaultHtml, {url: 'http://localhost:3333/'})\n\n // Don't use jsdom's btoa as it's using the deprecatd `abab` package.\n if (typeof btoa === 'function') global.btoa = btoa\n\n const windowCleanup = () => global.window.close()\n const globalCleanup = provideFakeGlobals(basePath)\n const cleanupFileLoader = addHook(\n (code, filename) => `module.exports = ${JSON.stringify(filename)}`,\n {\n ignoreNodeModules: false,\n exts: getFileExtensions(),\n },\n )\n\n const {unregister: unregisterESBuild} = registerESBuild({\n target: 'node18',\n supported: {'dynamic-import': true},\n format: 'cjs',\n extensions: ['.js', '.jsx', '.ts', '.tsx', '.mjs'],\n jsx: 'automatic',\n define: {\n // define the `process.env` global\n ...getStudioEnvironmentVariables({prefix: 'process.env.', jsonEncode: true}),\n // define the `import.meta.env` global\n ...getStudioEnvironmentVariables({prefix: 'import.meta.env.', jsonEncode: true}),\n // define the `import.meta.hot` global, so we don't get `\"import.meta\" is not available with the \"cjs\" output format and will be empty` warnings\n 'import.meta.hot': 'false',\n },\n })\n\n return function cleanupBrowserEnvironment() {\n unregisterESBuild()\n cleanupFileLoader()\n globalCleanup()\n windowCleanup()\n domCleanup()\n importErrorHandler.cleanup()\n }\n}\n\nconst getFakeGlobals = (basePath: string) => ({\n __mockedBySanity: true,\n requestAnimationFrame: setImmediate,\n cancelAnimationFrame: clearImmediate,\n requestIdleCallback: setImmediate,\n cancelIdleCallback: clearImmediate,\n ace: tryGetAceGlobal(basePath),\n InputEvent: global.window?.InputEvent,\n customElements: global.window?.customElements,\n ResizeObserver: global.window?.ResizeObserver || ResizeObserver,\n matchMedia:\n global.window?.matchMedia ||\n (() => ({\n matches: false,\n media: '',\n onchange: null,\n })),\n})\n\nconst getFakeDocumentProps = () => ({\n execCommand: function execCommand(\n // Provide the right arity for the function, even if unused\n _commandName: string,\n _showDefaultUI: boolean,\n _valueArgument: unknown,\n ) {\n // Return false to indicate \"unsupported\"\n return false\n },\n})\n\nfunction provideFakeGlobals(basePath: string): () => void {\n const globalEnv = global as any as Record<string, unknown>\n const globalWindow = global.window as Record<string, any>\n const globalDocument = (global.document || document || {}) as Record<string, any>\n\n const fakeGlobals = getFakeGlobals(basePath)\n const fakeDocumentProps = getFakeDocumentProps()\n\n const stubbedGlobalKeys: string[] = []\n const stubbedWindowKeys: string[] = []\n const stubbedDocumentKeys: string[] = []\n\n for (const [rawKey, value] of Object.entries(fakeGlobals)) {\n if (typeof value === 'undefined') {\n continue\n }\n\n const key = rawKey as keyof typeof fakeGlobals\n\n if (!(key in globalEnv)) {\n globalEnv[key] = fakeGlobals[key]\n stubbedGlobalKeys.push(key)\n }\n\n if (!(key in global.window)) {\n globalWindow[key] = fakeGlobals[key]\n stubbedWindowKeys.push(key)\n }\n }\n\n for (const [rawKey, value] of Object.entries(fakeDocumentProps)) {\n if (typeof value === 'undefined') {\n continue\n }\n\n const key = rawKey as keyof typeof fakeDocumentProps\n if (!(key in globalDocument)) {\n globalDocument[key] = fakeDocumentProps[key]\n stubbedDocumentKeys.push(key)\n }\n }\n\n return () => {\n stubbedGlobalKeys.forEach((key) => {\n delete globalEnv[key]\n })\n\n stubbedWindowKeys.forEach((key) => {\n delete globalWindow[key]\n })\n\n stubbedDocumentKeys.forEach((key) => {\n delete globalDocument[key]\n })\n }\n}\n\nfunction tryGetAceGlobal(basePath: string) {\n // Work around an issue where using the @sanity/code-input plugin would crash\n // due to `ace` not being defined on the global due to odd bundling stategy.\n const acePath = resolveFrom.silent(basePath, 'ace-builds')\n if (!acePath) {\n return undefined\n }\n\n try {\n // eslint-disable-next-line import/no-dynamic-require\n return require(acePath)\n } catch (err) {\n return undefined\n }\n}\n\nfunction getFileExtensions() {\n return [\n '.css',\n '.eot',\n '.gif',\n '.jpeg',\n '.jpg',\n '.otf',\n '.png',\n '.sass',\n '.scss',\n '.svg',\n '.ttf',\n '.webp',\n '.woff',\n '.woff2',\n ]\n}\n","import fs from 'node:fs'\nimport {createRequire} from 'node:module'\nimport path from 'node:path'\n\nimport {firstValueFrom} from 'rxjs'\nimport {type Config, resolveConfig, type Workspace, type WorkspaceOptions} from 'sanity'\n\nimport {mockBrowserEnvironment} from './mockBrowserEnvironment'\n\nconst require = createRequire(import.meta.url)\n\nconst candidates = [\n 'sanity.config.js',\n 'sanity.config.jsx',\n 'sanity.config.ts',\n 'sanity.config.tsx',\n]\n\ninterface GetStudioWorkspacesOptions {\n configPath?: string\n basePath: string\n}\n\n/**\n * Note: Don't run this on the main thread, use it a forked process\n */\nexport function getStudioConfig({\n basePath,\n configPath: cfgPath,\n}: GetStudioWorkspacesOptions): WorkspaceOptions[] {\n let cleanup\n try {\n cleanup = mockBrowserEnvironment(basePath)\n\n let configPath = cfgPath\n if (configPath && !fs.existsSync(configPath)) {\n throw new Error(`Failed to find config at \"${cfgPath}\"`)\n } else if (!configPath) {\n configPath = candidates\n .map((candidate) => path.join(basePath, candidate))\n .find((candidate) => fs.existsSync(candidate))\n }\n\n if (!configPath) {\n throw new Error(`Failed to resolve sanity.config.(js|ts) for base path \"${basePath}\"`)\n }\n\n let config: Config | undefined\n try {\n // eslint-disable-next-line import/no-dynamic-require\n const mod = require(configPath)\n config = mod.__esModule && mod.default ? mod.default : mod\n } catch (err) {\n throw new Error(`Failed to load configuration file \"${configPath}\"`, {\n cause: err,\n })\n }\n\n if (!config) throw new Error('Configuration did not export expected config shape')\n const normalized = Array.isArray(config)\n ? config\n : [{...config, name: config.name || 'default', basePath: config.basePath || '/'}]\n\n return normalized\n } finally {\n cleanup?.()\n }\n}\n\n/**\n * Note: Don't run this on the main thread, use it a forked process\n */\nexport async function getStudioWorkspaces(\n options: GetStudioWorkspacesOptions,\n): Promise<Workspace[]> {\n let cleanup\n\n try {\n cleanup = mockBrowserEnvironment(options.basePath)\n const config = getStudioConfig(options)\n const workspaces = await firstValueFrom(resolveConfig(config))\n if (!workspaces) throw new Error('Failed to resolve configuration')\n return workspaces\n } finally {\n cleanup?.()\n }\n}\n","import {defineTrace} from '@sanity/telemetry'\n\ninterface SchemaExtractedTraceAttrubutes {\n schemaAllTypesCount: number\n schemaDocumentTypesCount: number\n schemaTypesCount: number\n\n enforceRequiredFields: boolean\n schemaFormat: string\n}\n\nexport const SchemaExtractedTrace = defineTrace<SchemaExtractedTraceAttrubutes>({\n name: 'Schema Extracted',\n version: 0,\n description: 'Trace emitted when extracting schema',\n})\n","import {writeFile} from 'node:fs/promises'\nimport {dirname, join} from 'node:path'\nimport {fileURLToPath} from 'node:url'\nimport {Worker} from 'node:worker_threads'\n\nimport {type CliCommandArguments, type CliCommandContext} from '@sanity/cli'\nimport {type SchemaValidationProblemGroup} from '@sanity/types'\nimport readPkgUp from 'read-pkg-up'\nimport {SchemaError as CoreSchemaError} from 'sanity'\n\nimport {\n type ExtractSchemaWorkerData,\n type ExtractSchemaWorkerResult,\n} from '../../threads/extractSchema'\nimport {getStudioWorkspaces} from '../../util/getStudioWorkspaces'\nimport {SchemaExtractedTrace} from './extractSchema.telemetry'\nimport {formatSchemaValidation} from './formatSchemaValidation'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\ninterface ExtractFlags {\n 'workspace'?: string\n 'path'?: string\n 'enforce-required-fields'?: boolean\n 'format'?: 'groq-type-nodes' | string\n}\n\nexport type SchemaValidationFormatter = (result: ExtractSchemaWorkerResult) => string\n\nexport default async function extractAction(\n args: CliCommandArguments<ExtractFlags>,\n {workDir, output, telemetry}: CliCommandContext,\n): Promise<void> {\n const flags = args.extOptions\n const formatFlag = flags.format || 'groq-type-nodes'\n const enforceRequiredFields = flags['enforce-required-fields'] || false\n\n const rootPkgPath = readPkgUp.sync({cwd: __dirname})?.path\n if (!rootPkgPath) {\n throw new Error('Could not find root directory for `sanity` package')\n }\n\n const workerPath = join(\n dirname(rootPkgPath),\n 'lib',\n '_internal',\n 'cli',\n 'threads',\n 'extractSchema.cjs',\n )\n\n const spinner = output\n .spinner({})\n .start(\n enforceRequiredFields\n ? 'Extracting schema, with enforced required fields'\n : 'Extracting schema',\n )\n\n const trace = telemetry.trace(SchemaExtractedTrace)\n trace.start()\n\n const worker = new Worker(workerPath, {\n workerData: {\n workDir,\n workspaceName: flags.workspace,\n enforceRequiredFields,\n format: formatFlag,\n } satisfies ExtractSchemaWorkerData,\n env: process.env,\n })\n\n try {\n const {schema} = await new Promise<ExtractSchemaWorkerResult>((resolve, reject) => {\n worker.addListener('message', resolve)\n worker.addListener('error', reject)\n })\n\n trace.log({\n schemaAllTypesCount: schema.length,\n schemaDocumentTypesCount: schema.filter((type) => type.type === 'document').length,\n schemaTypesCount: schema.filter((type) => type.type === 'type').length,\n enforceRequiredFields,\n schemaFormat: formatFlag,\n })\n\n const path = flags.path || join(process.cwd(), 'schema.json')\n\n spinner.text = `Writing schema to ${path}`\n\n await writeFile(path, `${JSON.stringify(schema, null, 2)}\\n`)\n\n trace.complete()\n\n spinner.succeed(\n enforceRequiredFields\n ? `Extracted schema to ${path} with enforced required fields`\n : `Extracted schema to ${path}`,\n )\n } catch (err) {\n trace.error(err)\n spinner.fail(\n enforceRequiredFields\n ? 'Failed to extract schema, with enforced required fields'\n : 'Failed to extract schema',\n )\n\n if (isSchemaError(err)) {\n try {\n // Re-resolve config in-process to surface validation details\n await getStudioWorkspaces({basePath: workDir})\n } catch (innerErr) {\n const validation = extractValidationFromCoreSchemaError(innerErr)\n if (validation && validation.length > 0) {\n output.print('')\n output.print(formatSchemaValidation(validation))\n }\n throw err\n }\n }\n throw err\n }\n}\n\n/**\n * Type guard to check if an item conforms to the SchemaValidationProblemGroup shape.\n */\nfunction isValidationProblemGroup(item: unknown): item is SchemaValidationProblemGroup {\n if (typeof item !== 'object' || item === null) {\n return false\n }\n const group = item as Record<string, unknown>\n return Array.isArray(group.path) && Array.isArray(group.problems)\n}\n\n/**\n * Extracts the `_validation` array from a CoreSchemaError's internal schema object.\n *\n * CoreSchemaError stores the compiled schema (which includes validation results) on\n * `error.schema._validation`. This function safely navigates that structure and validates\n * it conforms to the expected `SchemaValidationProblemGroup[]` shape before returning.\n */\nfunction extractValidationFromCoreSchemaError(\n error: unknown,\n): SchemaValidationProblemGroup[] | null {\n if (!(error instanceof CoreSchemaError)) {\n return null\n }\n\n const schema = error.schema as unknown as Record<string, unknown> | null | undefined\n if (!schema || typeof schema !== 'object') {\n return null\n }\n\n const validation = schema._validation\n if (!Array.isArray(validation)) {\n return null\n }\n\n if (!validation.every(isValidationProblemGroup)) {\n return null\n }\n\n return validation\n}\n\n/**\n * Type guard for SchemaError. Checks both `name` and `message` properties because\n * errors from worker threads lose their prototype chain during serialization,\n * and may only preserve the error name in the message string.\n */\nfunction isSchemaError(err: unknown): err is Error & {name: 'SchemaError'} {\n if (typeof err !== 'object' || err === null) {\n return false\n }\n\n const errorLike = err as {name?: unknown; message?: unknown}\n const hasSchemaErrorName = errorLike.name === 'SchemaError'\n const hasSchemaErrorMessage = errorLike.message === 'SchemaError'\n\n return hasSchemaErrorName || hasSchemaErrorMessage\n}\n"],"names":["getProxyHandler","handler","get","_target","prop","Proxy","apply","setupImportErrorHandler","ModuleConstructor","Module","originalLoad","_load","request","parent","isMain","call","error","startsWith","cleanup","require","createRequire","import","url","register","pathToFileURL","resolve","jsdomDefaultHtml","mockBrowserEnvironment","basePath","global","window","importErrorHandler","btoa","domCleanup","jsdomGlobal","windowCleanup","close","globalCleanup","provideFakeGlobals","cleanupFileLoader","addHook","code","filename","JSON","stringify","ignoreNodeModules","exts","getFileExtensions","unregister","unregisterESBuild","registerESBuild","target","supported","format","extensions","jsx","define","getStudioEnvironmentVariables","prefix","jsonEncode","getFakeGlobals","__mockedBySanity","requestAnimationFrame","setImmediate","cancelAnimationFrame","clearImmediate","requestIdleCallback","cancelIdleCallback","ace","tryGetAceGlobal","InputEvent","customElements","ResizeObserver","matchMedia","matches","media","onchange","getFakeDocumentProps","execCommand","_commandName","_showDefaultUI","_valueArgument","globalEnv","globalWindow","globalDocument","document","fakeGlobals","fakeDocumentProps","stubbedGlobalKeys","stubbedWindowKeys","stubbedDocumentKeys","rawKey","value","Object","entries","key","push","forEach","acePath","resolveFrom","silent","candidates","getStudioConfig","configPath","cfgPath","fs","existsSync","Error","map","candidate","path","join","find","config","mod","__esModule","default","err","cause","Array","isArray","name","getStudioWorkspaces","options","workspaces","firstValueFrom","resolveConfig","SchemaExtractedTrace","defineTrace","version","description","__dirname","dirname","fileURLToPath","extractAction","args","workDir","output","telemetry","flags","extOptions","formatFlag","enforceRequiredFields","rootPkgPath","readPkgUp","sync","cwd","workerPath","spinner","start","trace","worker","Worker","workerData","workspaceName","workspace","env","process","schema","Promise","reject","addListener","log","schemaAllTypesCount","length","schemaDocumentTypesCount","filter","type","schemaTypesCount","schemaFormat","text","writeFile","complete","succeed","fail","isSchemaError","innerErr","validation","extractValidationFromCoreSchemaError","print","formatSchemaValidation","isValidationProblemGroup","item","group","problems","CoreSchemaError","_validation","every","errorLike","hasSchemaErrorName","hasSchemaErrorMessage","message"],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { isatty } from "node:tty";
|
|
2
|
+
import { generateHelpUrl } from "./generate-help-url.esm.js";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import logSymbols from "log-symbols";
|
|
5
|
+
const isTty = isatty(1), headers = {
|
|
6
|
+
error: isTty ? chalk.bold(chalk.bgRed(chalk.black(" ERROR "))) : chalk.red("[ERROR]"),
|
|
7
|
+
warning: isTty ? chalk.bold(chalk.bgYellow(chalk.black(" WARN "))) : chalk.yellow("[WARN]")
|
|
8
|
+
}, severityValues = {
|
|
9
|
+
error: 0,
|
|
10
|
+
warning: 1
|
|
11
|
+
};
|
|
12
|
+
function formatPath(pathSegments) {
|
|
13
|
+
const format = ([curr, ...next], mode = "object") => {
|
|
14
|
+
if (!curr) return "";
|
|
15
|
+
if (curr.kind === "property") return format(next, curr.name === "of" ? "array" : "object");
|
|
16
|
+
const name = curr.name ? curr.name : `<anonymous_${curr.type}>`;
|
|
17
|
+
return `${mode === "array" ? `[${name}]` : `.${name}`}${format(next)}`;
|
|
18
|
+
};
|
|
19
|
+
return format(pathSegments.slice(1)).slice(1);
|
|
20
|
+
}
|
|
21
|
+
function getAggregatedSeverity(groupOrGroups) {
|
|
22
|
+
return (Array.isArray(groupOrGroups) ? groupOrGroups : [groupOrGroups]).flatMap((group) => group.problems.map((problem) => problem.severity)).find((severity) => severity === "error") ? "error" : "warning";
|
|
23
|
+
}
|
|
24
|
+
function formatSchemaValidation(validation) {
|
|
25
|
+
let unnamedTopLevelTypeCount = 0;
|
|
26
|
+
return Object.entries(validation.reduce((acc, next) => {
|
|
27
|
+
const [firstSegment] = next.path;
|
|
28
|
+
if (!firstSegment || firstSegment.kind !== "type") return acc;
|
|
29
|
+
const topLevelType = firstSegment.name || `<unnamed_${firstSegment.type}_type_${unnamedTopLevelTypeCount++}>`, problems = acc[topLevelType] ?? [];
|
|
30
|
+
return problems.push(next), acc[topLevelType] = problems, acc;
|
|
31
|
+
}, {})).sort((a, b) => {
|
|
32
|
+
const [aType, aGroups] = a, [bType, bGroups] = b, aValue = severityValues[getAggregatedSeverity(aGroups)], bValue = severityValues[getAggregatedSeverity(bGroups)];
|
|
33
|
+
return aValue === bValue ? aType.localeCompare(bType, "en-US") : aValue - bValue;
|
|
34
|
+
}).map(([topLevelType, groups]) => {
|
|
35
|
+
const formattedTopLevelType = isTty ? chalk.bgWhite(chalk.black(` ${topLevelType} `)) : `[${topLevelType}]`, header = `${headers[getAggregatedSeverity(groups)]} ${formattedTopLevelType}`, body = groups.sort((a, b) => severityValues[getAggregatedSeverity(a)] - severityValues[getAggregatedSeverity(b)]).map((group) => {
|
|
36
|
+
const formattedPath = ` ${chalk.bold(formatPath(group.path) || "(root)")}`, formattedMessages = group.problems.sort((a, b) => severityValues[a.severity] - severityValues[b.severity]).map(({
|
|
37
|
+
severity,
|
|
38
|
+
message,
|
|
39
|
+
helpId
|
|
40
|
+
}) => {
|
|
41
|
+
const help = helpId ? `
|
|
42
|
+
See ${generateHelpUrl(helpId)}` : "";
|
|
43
|
+
return ` ${logSymbols[severity]} ${message}${help}`;
|
|
44
|
+
}).join(`
|
|
45
|
+
`);
|
|
46
|
+
return `${formattedPath}
|
|
47
|
+
${formattedMessages}`;
|
|
48
|
+
}).join(`
|
|
49
|
+
`);
|
|
50
|
+
return `${header}
|
|
51
|
+
${body}`;
|
|
52
|
+
}).join(`
|
|
53
|
+
|
|
54
|
+
`);
|
|
55
|
+
}
|
|
56
|
+
export {
|
|
57
|
+
formatSchemaValidation,
|
|
58
|
+
getAggregatedSeverity
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=formatSchemaValidation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatSchemaValidation.js","sources":["../../src/_internal/cli/actions/schema/formatSchemaValidation.ts"],"sourcesContent":["import {isatty} from 'node:tty'\n\nimport {generateHelpUrl} from '@sanity/generate-help-url'\nimport {type SchemaValidationProblemGroup, type SchemaValidationProblemPath} from '@sanity/types'\nimport chalk from 'chalk'\nimport logSymbols from 'log-symbols'\n\nconst isTty = isatty(1)\n\nconst headers = {\n error: isTty ? chalk.bold(chalk.bgRed(chalk.black(' ERROR '))) : chalk.red('[ERROR]'),\n warning: isTty ? chalk.bold(chalk.bgYellow(chalk.black(' WARN '))) : chalk.yellow('[WARN]'),\n}\n\nconst severityValues = {error: 0, warning: 1}\n\n/**\n * Formats a schema validation path into a human-readable dot/bracket notation string.\n * e.g. `[{kind: 'type', name: 'post'}, {kind: 'property', name: 'of'}, {kind: 'type', name: 'image'}]`\n * becomes `[image]` (array notation because parent property was 'of').\n */\nfunction formatPath(pathSegments: SchemaValidationProblemPath) {\n const format = (\n [curr, ...next]: SchemaValidationProblemPath,\n mode: 'object' | 'array' = 'object',\n ): string => {\n if (!curr) return ''\n // 'property' segments control notation for the next type segment:\n // 'of' property means array items, so use bracket notation; otherwise use dot notation\n if (curr.kind === 'property') return format(next, curr.name === 'of' ? 'array' : 'object')\n\n const name = curr.name ? curr.name : `<anonymous_${curr.type}>`\n return `${mode === 'array' ? `[${name}]` : `.${name}`}${format(next)}`\n }\n\n // Skip the first segment (top-level type) and trim the leading '.' from the result\n return format(pathSegments.slice(1)).slice(1)\n}\n\nexport function getAggregatedSeverity(\n groupOrGroups: SchemaValidationProblemGroup | SchemaValidationProblemGroup[],\n): 'error' | 'warning' {\n const groups = Array.isArray(groupOrGroups) ? groupOrGroups : [groupOrGroups]\n return groups\n .flatMap((group) => group.problems.map((problem) => problem.severity))\n .find((severity) => severity === 'error')\n ? 'error'\n : 'warning'\n}\n\nexport function formatSchemaValidation(validation: SchemaValidationProblemGroup[]): string {\n let unnamedTopLevelTypeCount = 0\n // Group validation problems by their top-level schema type (e.g., 'post', 'author')\n // so errors can be displayed organized by which type they belong to\n const validationByType = Object.entries(\n validation.reduce<Record<string, SchemaValidationProblemGroup[]>>((acc, next) => {\n const [firstSegment] = next.path\n if (!firstSegment) return acc\n if (firstSegment.kind !== 'type') return acc\n\n const topLevelType =\n firstSegment.name || `<unnamed_${firstSegment.type}_type_${unnamedTopLevelTypeCount++}>`\n const problems = acc[topLevelType] ?? []\n\n problems.push(next)\n\n acc[topLevelType] = problems\n return acc\n }, {}),\n )\n\n // Sort types by severity (errors first), then alphabetically within each severity level\n const formatted = validationByType\n .sort((a, b) => {\n const [aType, aGroups] = a\n const [bType, bGroups] = b\n const aValue = severityValues[getAggregatedSeverity(aGroups)]\n const bValue = severityValues[getAggregatedSeverity(bGroups)]\n if (aValue === bValue) return aType.localeCompare(bType, 'en-US')\n return aValue - bValue\n })\n .map(([topLevelType, groups]) => {\n const formattedTopLevelType = isTty\n ? chalk.bgWhite(chalk.black(` ${topLevelType} `))\n : `[${topLevelType}]`\n\n const header = `${headers[getAggregatedSeverity(groups)]} ${formattedTopLevelType}`\n const body = groups\n .sort(\n (a, b) =>\n severityValues[getAggregatedSeverity(a)] - severityValues[getAggregatedSeverity(b)],\n )\n .map((group) => {\n const formattedPath = ` ${chalk.bold(formatPath(group.path) || '(root)')}`\n const formattedMessages = group.problems\n .sort((a, b) => severityValues[a.severity] - severityValues[b.severity])\n .map(({severity, message, helpId}) => {\n const help = helpId ? `\\n See ${generateHelpUrl(helpId)}` : ''\n return ` ${logSymbols[severity]} ${message}${help}`\n })\n .join('\\n')\n\n return `${formattedPath}\\n${formattedMessages}`\n })\n .join('\\n')\n\n return `${header}\\n${body}`\n })\n .join('\\n\\n')\n\n return formatted\n}\n"],"names":["isTty","isatty","headers","error","chalk","bold","bgRed","black","red","warning","bgYellow","yellow","severityValues","formatPath","pathSegments","format","curr","next","mode","kind","name","type","slice","getAggregatedSeverity","groupOrGroups","Array","isArray","flatMap","group","problems","map","problem","severity","find","formatSchemaValidation","validation","unnamedTopLevelTypeCount","Object","entries","reduce","acc","firstSegment","path","topLevelType","push","sort","a","b","aType","aGroups","bType","bGroups","aValue","bValue","localeCompare","groups","formattedTopLevelType","bgWhite","header","body","formattedPath","formattedMessages","message","helpId","help","generateHelpUrl","logSymbols","join"],"mappings":";;;;AAOA,MAAMA,QAAQC,OAAO,CAAC,GAEhBC,UAAU;AAAA,EACdC,OAAOH,QAAQI,MAAMC,KAAKD,MAAME,MAAMF,MAAMG,MAAM,SAAS,CAAC,CAAC,IAAIH,MAAMI,IAAI,SAAS;AAAA,EACpFC,SAAST,QAAQI,MAAMC,KAAKD,MAAMM,SAASN,MAAMG,MAAM,QAAQ,CAAC,CAAC,IAAIH,MAAMO,OAAO,QAAQ;AAC5F,GAEMC,iBAAiB;AAAA,EAACT,OAAO;AAAA,EAAGM,SAAS;AAAC;AAO5C,SAASI,WAAWC,cAA2C;AAC7D,QAAMC,SAASA,CACb,CAACC,MAASC,OAAI,GACdC,OAA2B,aAChB;AACX,QAAI,CAACF,KAAM,QAAO;AAGlB,QAAIA,KAAKG,SAAS,WAAY,QAAOJ,OAAOE,MAAMD,KAAKI,SAAS,OAAO,UAAU,QAAQ;AAEzF,UAAMA,OAAOJ,KAAKI,OAAOJ,KAAKI,OAAO,cAAcJ,KAAKK,IAAI;AAC5D,WAAO,GAAGH,SAAS,UAAU,IAAIE,IAAI,MAAM,IAAIA,IAAI,EAAE,GAAGL,OAAOE,IAAI,CAAC;AAAA,EACtE;AAGA,SAAOF,OAAOD,aAAaQ,MAAM,CAAC,CAAC,EAAEA,MAAM,CAAC;AAC9C;AAEO,SAASC,sBACdC,eACqB;AAErB,UADeC,MAAMC,QAAQF,aAAa,IAAIA,gBAAgB,CAACA,aAAa,GAEzEG,QAASC,CAAAA,UAAUA,MAAMC,SAASC,IAAKC,CAAAA,YAAYA,QAAQC,QAAQ,CAAC,EACpEC,KAAMD,CAAAA,aAAaA,aAAa,OAAO,IACtC,UACA;AACN;AAEO,SAASE,uBAAuBC,YAAoD;AACzF,MAAIC,2BAA2B;AA2D/B,SAxDyBC,OAAOC,QAC9BH,WAAWI,OAAuD,CAACC,KAAKvB,SAAS;AAC/E,UAAM,CAACwB,YAAY,IAAIxB,KAAKyB;AAE5B,QADI,CAACD,gBACDA,aAAatB,SAAS,OAAQ,QAAOqB;AAEzC,UAAMG,eACJF,aAAarB,QAAQ,YAAYqB,aAAapB,IAAI,SAASe,0BAA0B,KACjFP,WAAWW,IAAIG,YAAY,KAAK,CAAA;AAEtCd,WAAAA,SAASe,KAAK3B,IAAI,GAElBuB,IAAIG,YAAY,IAAId,UACbW;AAAAA,EACT,GAAG,CAAA,CAAE,CACP,EAIGK,KAAK,CAACC,GAAGC,MAAM;AACd,UAAM,CAACC,OAAOC,OAAO,IAAIH,GACnB,CAACI,OAAOC,OAAO,IAAIJ,GACnBK,SAASxC,eAAeW,sBAAsB0B,OAAO,CAAC,GACtDI,SAASzC,eAAeW,sBAAsB4B,OAAO,CAAC;AAC5D,WAAIC,WAAWC,SAAeL,MAAMM,cAAcJ,OAAO,OAAO,IACzDE,SAASC;AAAAA,EAClB,CAAC,EACAvB,IAAI,CAAC,CAACa,cAAcY,MAAM,MAAM;AAC/B,UAAMC,wBAAwBxD,QAC1BI,MAAMqD,QAAQrD,MAAMG,MAAM,IAAIoC,YAAY,GAAG,CAAC,IAC9C,IAAIA,YAAY,KAEde,SAAS,GAAGxD,QAAQqB,sBAAsBgC,MAAM,CAAC,CAAC,IAAIC,qBAAqB,IAC3EG,OAAOJ,OACVV,KACC,CAACC,GAAGC,MACFnC,eAAeW,sBAAsBuB,CAAC,CAAC,IAAIlC,eAAeW,sBAAsBwB,CAAC,CAAC,CACtF,EACCjB,IAAKF,CAAAA,UAAU;AACd,YAAMgC,gBAAgB,KAAKxD,MAAMC,KAAKQ,WAAWe,MAAMc,IAAI,KAAK,QAAQ,CAAC,IACnEmB,oBAAoBjC,MAAMC,SAC7BgB,KAAK,CAACC,GAAGC,MAAMnC,eAAekC,EAAEd,QAAQ,IAAIpB,eAAemC,EAAEf,QAAQ,CAAC,EACtEF,IAAI,CAAC;AAAA,QAACE;AAAAA,QAAU8B;AAAAA,QAASC;AAAAA,MAAAA,MAAY;AACpC,cAAMC,OAAOD,SAAS;AAAA,YAAeE,gBAAgBF,MAAM,CAAC,KAAK;AACjE,eAAO,OAAOG,WAAWlC,QAAQ,CAAC,IAAI8B,OAAO,GAAGE,IAAI;AAAA,MACtD,CAAC,EACAG,KAAK;AAAA,CAAI;AAEZ,aAAO,GAAGP,aAAa;AAAA,EAAKC,iBAAiB;AAAA,IAC/C,CAAC,EACAM,KAAK;AAAA,CAAI;AAEZ,WAAO,GAAGT,MAAM;AAAA,EAAKC,IAAI;AAAA,EAC3B,CAAC,EACAQ,KAAK;AAAA;AAAA,CAAM;AAGhB;"}
|
|
@@ -4,54 +4,7 @@ import { fileURLToPath } from "node:url";
|
|
|
4
4
|
import { Worker } from "node:worker_threads";
|
|
5
5
|
import logSymbols from "log-symbols";
|
|
6
6
|
import readPkgUp from "read-pkg-up";
|
|
7
|
-
import {
|
|
8
|
-
import chalk from "chalk";
|
|
9
|
-
const isTty = isatty(1), headers = {
|
|
10
|
-
error: isTty ? chalk.bold(chalk.bgRed(chalk.black(" ERROR "))) : chalk.red("[ERROR]"),
|
|
11
|
-
warning: isTty ? chalk.bold(chalk.bgYellow(chalk.black(" WARN "))) : chalk.yellow("[WARN]")
|
|
12
|
-
}, severityValues = {
|
|
13
|
-
error: 0,
|
|
14
|
-
warning: 1
|
|
15
|
-
};
|
|
16
|
-
function formatPath(pathSegments) {
|
|
17
|
-
const format = ([curr, ...next], mode = "object") => {
|
|
18
|
-
if (!curr) return "";
|
|
19
|
-
if (curr.kind === "property") return format(next, curr.name === "of" ? "array" : "object");
|
|
20
|
-
const name = curr.name ? curr.name : `<anonymous_${curr.type}>`;
|
|
21
|
-
return `${mode === "array" ? `[${name}]` : `.${name}`}${format(next)}`;
|
|
22
|
-
};
|
|
23
|
-
return format(pathSegments.slice(1)).slice(1);
|
|
24
|
-
}
|
|
25
|
-
function getAggregatedSeverity(groupOrGroups) {
|
|
26
|
-
return (Array.isArray(groupOrGroups) ? groupOrGroups : [groupOrGroups]).flatMap((group) => group.problems.map((problem) => problem.severity)).find((severity) => severity === "error") ? "error" : "warning";
|
|
27
|
-
}
|
|
28
|
-
function formatSchemaValidation(validation) {
|
|
29
|
-
let unnamedTopLevelTypeCount = 0;
|
|
30
|
-
return Object.entries(validation.reduce((acc, next) => {
|
|
31
|
-
const [firstSegment] = next.path;
|
|
32
|
-
if (!firstSegment || firstSegment.kind !== "type") return acc;
|
|
33
|
-
const topLevelType = firstSegment.name || `<unnamed_${firstSegment.type}_type_${unnamedTopLevelTypeCount++}>`, problems = acc[topLevelType] ?? [];
|
|
34
|
-
return problems.push(next), acc[topLevelType] = problems, acc;
|
|
35
|
-
}, {})).sort((a, b) => {
|
|
36
|
-
const [aType, aGroups] = a, [bType, bGroups] = b, aValue = severityValues[getAggregatedSeverity(aGroups)], bValue = severityValues[getAggregatedSeverity(bGroups)];
|
|
37
|
-
return aValue === bValue ? aType.localeCompare(bType, "en-US") : aValue - bValue;
|
|
38
|
-
}).map(([topLevelType, groups]) => {
|
|
39
|
-
const formattedTopLevelType = isTty ? chalk.bgWhite(chalk.black(` ${topLevelType} `)) : `[${topLevelType}]`, header = `${headers[getAggregatedSeverity(groups)]} ${formattedTopLevelType}`, body = groups.sort((a, b) => severityValues[getAggregatedSeverity(a)] - severityValues[getAggregatedSeverity(b)]).map((group) => {
|
|
40
|
-
const formattedPath = ` ${chalk.bold(formatPath(group.path) || "(root)")}`, formattedMessages = group.problems.sort((a, b) => severityValues[a.severity] - severityValues[b.severity]).map(({
|
|
41
|
-
severity,
|
|
42
|
-
message
|
|
43
|
-
}) => ` ${logSymbols[severity]} ${message}`).join(`
|
|
44
|
-
`);
|
|
45
|
-
return `${formattedPath}
|
|
46
|
-
${formattedMessages}`;
|
|
47
|
-
}).join(`
|
|
48
|
-
`);
|
|
49
|
-
return `${header}
|
|
50
|
-
${body}`;
|
|
51
|
-
}).join(`
|
|
52
|
-
|
|
53
|
-
`);
|
|
54
|
-
}
|
|
7
|
+
import { getAggregatedSeverity, formatSchemaValidation } from "./formatSchemaValidation.js";
|
|
55
8
|
function generateMetafile(schema) {
|
|
56
9
|
const output = {
|
|
57
10
|
imports: [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateAction.js","sources":["../../src/_internal/cli/actions/schema/formatSchemaValidation.ts","../../src/_internal/cli/actions/schema/metafile.ts","../../src/_internal/cli/actions/schema/validateAction.ts"],"sourcesContent":["import {isatty} from 'node:tty'\n\nimport {type SchemaValidationProblemGroup, type SchemaValidationProblemPath} from '@sanity/types'\nimport chalk from 'chalk'\nimport logSymbols from 'log-symbols'\n\nconst isTty = isatty(1)\n\nconst headers = {\n error: isTty ? chalk.bold(chalk.bgRed(chalk.black(' ERROR '))) : chalk.red('[ERROR]'),\n warning: isTty ? chalk.bold(chalk.bgYellow(chalk.black(' WARN '))) : chalk.yellow('[WARN]'),\n}\n\nconst severityValues = {error: 0, warning: 1}\n\nfunction formatPath(pathSegments: SchemaValidationProblemPath) {\n const format = (\n [curr, ...next]: SchemaValidationProblemPath,\n mode: 'object' | 'array' = 'object',\n ): string => {\n if (!curr) return ''\n if (curr.kind === 'property') return format(next, curr.name === 'of' ? 'array' : 'object')\n\n const name = curr.name ? curr.name : `<anonymous_${curr.type}>`\n return `${mode === 'array' ? `[${name}]` : `.${name}`}${format(next)}`\n }\n\n return format(pathSegments.slice(1)).slice(1) // removes the top-level type and leading `.`\n}\n\nexport function getAggregatedSeverity(\n groupOrGroups: SchemaValidationProblemGroup | SchemaValidationProblemGroup[],\n): 'error' | 'warning' {\n const groups = Array.isArray(groupOrGroups) ? groupOrGroups : [groupOrGroups]\n return groups\n .flatMap((group) => group.problems.map((problem) => problem.severity))\n .find((severity) => severity === 'error')\n ? 'error'\n : 'warning'\n}\n\nexport function formatSchemaValidation(validation: SchemaValidationProblemGroup[]): string {\n let unnamedTopLevelTypeCount = 0\n const validationByType = Object.entries(\n validation.reduce<Record<string, SchemaValidationProblemGroup[]>>((acc, next) => {\n const [firstSegment] = next.path\n if (!firstSegment) return acc\n if (firstSegment.kind !== 'type') return acc\n\n const topLevelType =\n firstSegment.name || `<unnamed_${firstSegment.type}_type_${unnamedTopLevelTypeCount++}>`\n const problems = acc[topLevelType] ?? []\n\n problems.push(next)\n\n acc[topLevelType] = problems\n return acc\n }, {}),\n )\n\n const formatted = validationByType\n .sort((a, b) => {\n const [aType, aGroups] = a\n const [bType, bGroups] = b\n const aValue = severityValues[getAggregatedSeverity(aGroups)]\n const bValue = severityValues[getAggregatedSeverity(bGroups)]\n if (aValue === bValue) return aType.localeCompare(bType, 'en-US')\n return aValue - bValue\n })\n .map(([topLevelType, groups]) => {\n const formattedTopLevelType = isTty\n ? chalk.bgWhite(chalk.black(` ${topLevelType} `))\n : `[${topLevelType}]`\n\n const header = `${headers[getAggregatedSeverity(groups)]} ${formattedTopLevelType}`\n const body = groups\n .sort(\n (a, b) =>\n severityValues[getAggregatedSeverity(a)] - severityValues[getAggregatedSeverity(b)],\n )\n .map((group) => {\n const formattedPath = ` ${chalk.bold(formatPath(group.path) || '(root)')}`\n const formattedMessages = group.problems\n .sort((a, b) => severityValues[a.severity] - severityValues[b.severity])\n .map(({severity, message}) => ` ${logSymbols[severity]} ${message}`)\n .join('\\n')\n\n return `${formattedPath}\\n${formattedMessages}`\n })\n .join('\\n')\n\n return `${header}\\n${body}`\n })\n .join('\\n\\n')\n\n return formatted\n}\n","import {type SeralizedSchemaDebug, type SerializedTypeDebug} from '../../threads/validateSchema'\n\n// This implements the metafile format of ESBuild.\ntype Metafile = {\n inputs: Record<string, MetafileInput>\n outputs: Record<string, MetafileOutput>\n}\n\ntype MetafileOutput = {\n imports: []\n exports: []\n inputs: Record<string, {bytesInOutput: number}>\n bytes: number\n}\n\ntype MetafileInput = {\n bytes: number\n imports: []\n format: 'esm' | 'csj'\n}\n\n/** Converts the */\nexport function generateMetafile(schema: SeralizedSchemaDebug): Metafile {\n const output: MetafileOutput = {\n imports: [],\n exports: [],\n inputs: {},\n bytes: 0,\n }\n\n // Generate a esbuild metafile\n const inputs: Record<string, MetafileInput> = {}\n\n function processType(path: string, entry: SerializedTypeDebug) {\n let childSize = 0\n\n if (entry.fields) {\n for (const [name, fieldEntry] of Object.entries(entry.fields)) {\n processType(`${path}/${name}`, fieldEntry)\n childSize += fieldEntry.size\n }\n }\n\n if (entry.of) {\n for (const [name, fieldEntry] of Object.entries(entry.of)) {\n processType(`${path}/${name}`, fieldEntry)\n childSize += fieldEntry.size\n }\n }\n\n const selfSize = entry.size - childSize\n\n inputs[path] = {\n bytes: selfSize,\n imports: [],\n format: 'esm',\n }\n\n output.inputs[path] = {\n bytesInOutput: selfSize,\n }\n\n output.bytes += selfSize\n }\n\n for (const [name, entry] of Object.entries(schema.types)) {\n const fakePath = `schema/${entry.extends}/${name}`\n processType(fakePath, entry)\n }\n\n for (const [name, entry] of Object.entries(schema.hoisted)) {\n const fakePath = `hoisted/${name}`\n processType(fakePath, entry)\n }\n\n return {outputs: {root: output}, inputs}\n}\n","import {writeFileSync} from 'node:fs'\nimport path from 'node:path'\nimport {fileURLToPath} from 'node:url'\nimport {Worker} from 'node:worker_threads'\n\nimport {type CliCommandArguments, type CliCommandContext} from '@sanity/cli'\nimport logSymbols from 'log-symbols'\nimport readPkgUp from 'read-pkg-up'\n\nimport {\n type ValidateSchemaWorkerData,\n type ValidateSchemaWorkerResult,\n} from '../../threads/validateSchema'\nimport {formatSchemaValidation, getAggregatedSeverity} from './formatSchemaValidation'\nimport {generateMetafile} from './metafile'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\n\ninterface ValidateFlags {\n 'workspace'?: string\n 'format'?: string\n 'level'?: 'error' | 'warning'\n 'debug-metafile-path'?: string\n}\n\nexport type SchemaValidationFormatter = (result: ValidateSchemaWorkerResult) => string\n\nexport default async function validateAction(\n args: CliCommandArguments<ValidateFlags>,\n {workDir, output}: CliCommandContext,\n): Promise<void> {\n const flags = args.extOptions\n\n const rootPkgPath = readPkgUp.sync({cwd: __dirname})?.path\n if (!rootPkgPath) {\n throw new Error('Could not find root directory for `sanity` package')\n }\n\n const workerPath = path.join(\n path.dirname(rootPkgPath),\n 'lib',\n '_internal',\n 'cli',\n 'threads',\n 'validateSchema.cjs',\n )\n\n const level = flags.level || 'warning'\n\n if (level !== 'error' && level !== 'warning') {\n throw new Error(`Invalid level. Available levels are 'error' and 'warning'.`)\n }\n\n const format = flags.format || 'pretty'\n\n if (!['pretty', 'ndjson', 'json'].includes(format)) {\n throw new Error(\n `Did not recognize format '${flags.format}'. Available formats are 'pretty', 'ndjson', and 'json'.`,\n )\n }\n\n let spinner\n\n if (format === 'pretty') {\n spinner = output\n .spinner(\n flags.workspace\n ? `Validating schema from workspace '${flags.workspace}'…`\n : 'Validating schema…',\n )\n .start()\n }\n\n const worker = new Worker(workerPath, {\n workerData: {\n workDir,\n level,\n workspace: flags.workspace,\n debugSerialize: Boolean(flags['debug-metafile-path']),\n } satisfies ValidateSchemaWorkerData,\n env: process.env,\n })\n\n const {validation, serializedDebug} = await new Promise<ValidateSchemaWorkerResult>(\n (resolve, reject) => {\n worker.addListener('message', resolve)\n worker.addListener('error', reject)\n },\n )\n\n const problems = validation.flatMap((group) => group.problems)\n const errorCount = problems.filter((problem) => problem.severity === 'error').length\n const warningCount = problems.filter((problem) => problem.severity === 'warning').length\n\n const overallSeverity = getAggregatedSeverity(validation)\n const didFail = overallSeverity === 'error'\n\n if (flags['debug-metafile-path'] && !didFail) {\n if (!serializedDebug) throw new Error('serializedDebug should always be produced')\n const metafile = generateMetafile(serializedDebug)\n writeFileSync(flags['debug-metafile-path'], JSON.stringify(metafile), 'utf8')\n }\n\n switch (format) {\n case 'ndjson': {\n for (const group of validation) {\n output.print(JSON.stringify(group))\n }\n break\n }\n case 'json': {\n output.print(JSON.stringify(validation))\n break\n }\n default: {\n spinner?.succeed('Validated schema')\n output.print(`\\nValidation results:`)\n output.print(\n `${logSymbols.error} Errors: ${errorCount.toLocaleString('en-US')} error${\n errorCount === 1 ? '' : 's'\n }`,\n )\n if (level !== 'error') {\n output.print(\n `${logSymbols.warning} Warnings: ${warningCount.toLocaleString('en-US')} warning${\n warningCount === 1 ? '' : 's'\n }`,\n )\n }\n output.print()\n\n output.print(formatSchemaValidation(validation))\n\n if (flags['debug-metafile-path']) {\n output.print()\n if (didFail) {\n output.print(`${logSymbols.info} Metafile not written due to validation errors`)\n } else {\n output.print(`${logSymbols.info} Metafile written to: ${flags['debug-metafile-path']}`)\n output.print(` This can be analyzed at https://esbuild.github.io/analyze/`)\n }\n }\n }\n }\n\n process.exitCode = didFail ? 1 : 0\n}\n"],"names":["isTty","isatty","headers","error","chalk","bold","bgRed","black","red","warning","bgYellow","yellow","severityValues","formatPath","pathSegments","format","curr","next","mode","kind","name","type","slice","getAggregatedSeverity","groupOrGroups","Array","isArray","flatMap","group","problems","map","problem","severity","find","formatSchemaValidation","validation","unnamedTopLevelTypeCount","Object","entries","reduce","acc","firstSegment","path","topLevelType","push","sort","a","b","aType","aGroups","bType","bGroups","aValue","bValue","localeCompare","groups","formattedTopLevelType","bgWhite","header","body","formattedPath","formattedMessages","message","logSymbols","join","generateMetafile","schema","output","imports","exports","inputs","bytes","processType","entry","childSize","fields","fieldEntry","size","of","selfSize","bytesInOutput","types","fakePath","extends","hoisted","outputs","root","__dirname","dirname","fileURLToPath","import","url","validateAction","args","workDir","flags","extOptions","rootPkgPath","readPkgUp","sync","cwd","Error","workerPath","level","includes","spinner","workspace","start","worker","Worker","workerData","debugSerialize","Boolean","env","process","serializedDebug","Promise","resolve","reject","addListener","errorCount","filter","length","warningCount","didFail","metafile","writeFileSync","JSON","stringify","print","succeed","toLocaleString","info","exitCode"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"validateAction.js","sources":["../../src/_internal/cli/actions/schema/metafile.ts","../../src/_internal/cli/actions/schema/validateAction.ts"],"sourcesContent":["import {type SeralizedSchemaDebug, type SerializedTypeDebug} from '../../threads/validateSchema'\n\n// This implements the metafile format of ESBuild.\ntype Metafile = {\n inputs: Record<string, MetafileInput>\n outputs: Record<string, MetafileOutput>\n}\n\ntype MetafileOutput = {\n imports: []\n exports: []\n inputs: Record<string, {bytesInOutput: number}>\n bytes: number\n}\n\ntype MetafileInput = {\n bytes: number\n imports: []\n format: 'esm' | 'csj'\n}\n\n/** Converts the */\nexport function generateMetafile(schema: SeralizedSchemaDebug): Metafile {\n const output: MetafileOutput = {\n imports: [],\n exports: [],\n inputs: {},\n bytes: 0,\n }\n\n // Generate a esbuild metafile\n const inputs: Record<string, MetafileInput> = {}\n\n function processType(path: string, entry: SerializedTypeDebug) {\n let childSize = 0\n\n if (entry.fields) {\n for (const [name, fieldEntry] of Object.entries(entry.fields)) {\n processType(`${path}/${name}`, fieldEntry)\n childSize += fieldEntry.size\n }\n }\n\n if (entry.of) {\n for (const [name, fieldEntry] of Object.entries(entry.of)) {\n processType(`${path}/${name}`, fieldEntry)\n childSize += fieldEntry.size\n }\n }\n\n const selfSize = entry.size - childSize\n\n inputs[path] = {\n bytes: selfSize,\n imports: [],\n format: 'esm',\n }\n\n output.inputs[path] = {\n bytesInOutput: selfSize,\n }\n\n output.bytes += selfSize\n }\n\n for (const [name, entry] of Object.entries(schema.types)) {\n const fakePath = `schema/${entry.extends}/${name}`\n processType(fakePath, entry)\n }\n\n for (const [name, entry] of Object.entries(schema.hoisted)) {\n const fakePath = `hoisted/${name}`\n processType(fakePath, entry)\n }\n\n return {outputs: {root: output}, inputs}\n}\n","import {writeFileSync} from 'node:fs'\nimport path from 'node:path'\nimport {fileURLToPath} from 'node:url'\nimport {Worker} from 'node:worker_threads'\n\nimport {type CliCommandArguments, type CliCommandContext} from '@sanity/cli'\nimport logSymbols from 'log-symbols'\nimport readPkgUp from 'read-pkg-up'\n\nimport {\n type ValidateSchemaWorkerData,\n type ValidateSchemaWorkerResult,\n} from '../../threads/validateSchema'\nimport {formatSchemaValidation, getAggregatedSeverity} from './formatSchemaValidation'\nimport {generateMetafile} from './metafile'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\n\ninterface ValidateFlags {\n 'workspace'?: string\n 'format'?: string\n 'level'?: 'error' | 'warning'\n 'debug-metafile-path'?: string\n}\n\nexport type SchemaValidationFormatter = (result: ValidateSchemaWorkerResult) => string\n\nexport default async function validateAction(\n args: CliCommandArguments<ValidateFlags>,\n {workDir, output}: CliCommandContext,\n): Promise<void> {\n const flags = args.extOptions\n\n const rootPkgPath = readPkgUp.sync({cwd: __dirname})?.path\n if (!rootPkgPath) {\n throw new Error('Could not find root directory for `sanity` package')\n }\n\n const workerPath = path.join(\n path.dirname(rootPkgPath),\n 'lib',\n '_internal',\n 'cli',\n 'threads',\n 'validateSchema.cjs',\n )\n\n const level = flags.level || 'warning'\n\n if (level !== 'error' && level !== 'warning') {\n throw new Error(`Invalid level. Available levels are 'error' and 'warning'.`)\n }\n\n const format = flags.format || 'pretty'\n\n if (!['pretty', 'ndjson', 'json'].includes(format)) {\n throw new Error(\n `Did not recognize format '${flags.format}'. Available formats are 'pretty', 'ndjson', and 'json'.`,\n )\n }\n\n let spinner\n\n if (format === 'pretty') {\n spinner = output\n .spinner(\n flags.workspace\n ? `Validating schema from workspace '${flags.workspace}'…`\n : 'Validating schema…',\n )\n .start()\n }\n\n const worker = new Worker(workerPath, {\n workerData: {\n workDir,\n level,\n workspace: flags.workspace,\n debugSerialize: Boolean(flags['debug-metafile-path']),\n } satisfies ValidateSchemaWorkerData,\n env: process.env,\n })\n\n const {validation, serializedDebug} = await new Promise<ValidateSchemaWorkerResult>(\n (resolve, reject) => {\n worker.addListener('message', resolve)\n worker.addListener('error', reject)\n },\n )\n\n const problems = validation.flatMap((group) => group.problems)\n const errorCount = problems.filter((problem) => problem.severity === 'error').length\n const warningCount = problems.filter((problem) => problem.severity === 'warning').length\n\n const overallSeverity = getAggregatedSeverity(validation)\n const didFail = overallSeverity === 'error'\n\n if (flags['debug-metafile-path'] && !didFail) {\n if (!serializedDebug) throw new Error('serializedDebug should always be produced')\n const metafile = generateMetafile(serializedDebug)\n writeFileSync(flags['debug-metafile-path'], JSON.stringify(metafile), 'utf8')\n }\n\n switch (format) {\n case 'ndjson': {\n for (const group of validation) {\n output.print(JSON.stringify(group))\n }\n break\n }\n case 'json': {\n output.print(JSON.stringify(validation))\n break\n }\n default: {\n spinner?.succeed('Validated schema')\n output.print(`\\nValidation results:`)\n output.print(\n `${logSymbols.error} Errors: ${errorCount.toLocaleString('en-US')} error${\n errorCount === 1 ? '' : 's'\n }`,\n )\n if (level !== 'error') {\n output.print(\n `${logSymbols.warning} Warnings: ${warningCount.toLocaleString('en-US')} warning${\n warningCount === 1 ? '' : 's'\n }`,\n )\n }\n output.print()\n\n output.print(formatSchemaValidation(validation))\n\n if (flags['debug-metafile-path']) {\n output.print()\n if (didFail) {\n output.print(`${logSymbols.info} Metafile not written due to validation errors`)\n } else {\n output.print(`${logSymbols.info} Metafile written to: ${flags['debug-metafile-path']}`)\n output.print(` This can be analyzed at https://esbuild.github.io/analyze/`)\n }\n }\n }\n }\n\n process.exitCode = didFail ? 1 : 0\n}\n"],"names":["generateMetafile","schema","output","imports","exports","inputs","bytes","processType","path","entry","childSize","fields","name","fieldEntry","Object","entries","size","of","selfSize","format","bytesInOutput","types","fakePath","extends","hoisted","outputs","root","__dirname","dirname","fileURLToPath","import","url","validateAction","args","workDir","flags","extOptions","rootPkgPath","readPkgUp","sync","cwd","Error","workerPath","join","level","includes","spinner","workspace","start","worker","Worker","workerData","debugSerialize","Boolean","env","process","validation","serializedDebug","Promise","resolve","reject","addListener","problems","flatMap","group","errorCount","filter","problem","severity","length","warningCount","didFail","getAggregatedSeverity","metafile","writeFileSync","JSON","stringify","print","succeed","logSymbols","error","toLocaleString","warning","formatSchemaValidation","info","exitCode"],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@ try {
|
|
|
7
7
|
try {
|
|
8
8
|
buildVersion = buildVersion || // This is replaced by `@sanity/pkg-utils` at build time
|
|
9
9
|
// and must always be references by its full static name, e.g. no optional chaining, no `if (process && process.env)` etc.
|
|
10
|
-
"5.
|
|
10
|
+
"5.3.0-next.4+321e16bb62";
|
|
11
11
|
} catch {
|
|
12
12
|
}
|
|
13
13
|
const SANITY_VERSION = buildVersion || `${version}-dev`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sanity",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.3.0-next.4+321e16bb62",
|
|
4
4
|
"description": "Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -250,12 +250,12 @@
|
|
|
250
250
|
"which": "^5.0.0",
|
|
251
251
|
"xstate": "^5.25.0",
|
|
252
252
|
"yargs": "^17.7.2",
|
|
253
|
-
"@sanity/
|
|
254
|
-
"@sanity/
|
|
255
|
-
"@sanity/
|
|
256
|
-
"@sanity/
|
|
253
|
+
"@sanity/cli": "5.3.0-next.4+321e16bb62",
|
|
254
|
+
"@sanity/mutator": "5.3.0-next.4+321e16bb62",
|
|
255
|
+
"@sanity/schema": "5.3.0-next.4+321e16bb62",
|
|
256
|
+
"@sanity/diff": "5.3.0-next.4+321e16bb62",
|
|
257
257
|
"@sanity/types": "5.2.0",
|
|
258
|
-
"@sanity/util": "5.
|
|
258
|
+
"@sanity/util": "5.3.0-next.4+321e16bb62"
|
|
259
259
|
},
|
|
260
260
|
"devDependencies": {
|
|
261
261
|
"@playwright/experimental-ct-react": "1.56.1",
|
|
@@ -301,13 +301,13 @@
|
|
|
301
301
|
"swr": "2.2.5",
|
|
302
302
|
"vitest": "^3.2.4",
|
|
303
303
|
"vitest-package-exports": "^1.1.1",
|
|
304
|
-
"@repo/
|
|
305
|
-
"@repo/
|
|
306
|
-
"@repo/package.
|
|
307
|
-
"@repo/package.
|
|
308
|
-
"@
|
|
309
|
-
"@repo/
|
|
310
|
-
"@
|
|
304
|
+
"@repo/eslint-config": "5.3.0-next.4+321e16bb62",
|
|
305
|
+
"@repo/dev-aliases": "5.3.0-next.4+321e16bb62",
|
|
306
|
+
"@repo/package.bundle": "5.3.0-next.4+321e16bb62",
|
|
307
|
+
"@repo/package.config": "5.3.0-next.4+321e16bb62",
|
|
308
|
+
"@sanity/codegen": "5.3.0-next.4+321e16bb62",
|
|
309
|
+
"@repo/tsconfig": "5.3.0-next.4+321e16bb62",
|
|
310
|
+
"@repo/test-config": "5.3.0-next.4+321e16bb62"
|
|
311
311
|
},
|
|
312
312
|
"peerDependencies": {
|
|
313
313
|
"react": "^19.2.2",
|