@sanity/cli 8.15.0 → 8.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -6
- package/dist/actions/deploy/deployChecks.js +44 -1
- package/dist/actions/deploy/deployChecks.js.map +1 -1
- package/dist/actions/deploy/deployStudio.js +40 -25
- package/dist/actions/deploy/deployStudio.js.map +1 -1
- package/dist/actions/typegen/fetchResourceSchema.js +40 -0
- package/dist/actions/typegen/fetchResourceSchema.js.map +1 -0
- package/dist/actions/typegen/generateResourceTypes.js +115 -0
- package/dist/actions/typegen/generateResourceTypes.js.map +1 -0
- package/dist/actions/typegen/parseTypegenResources.js +92 -0
- package/dist/actions/typegen/parseTypegenResources.js.map +1 -0
- package/dist/commands/deploy.js +6 -3
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/typegen/generate.js +59 -5
- package/dist/commands/typegen/generate.js.map +1 -1
- package/dist/exports/runtime.d.ts +2 -2
- package/dist/exports/runtime.js.map +1 -1
- package/dist/server/vite/plugin-typegen.js +10 -0
- package/dist/server/vite/plugin-typegen.js.map +1 -1
- package/dist/services/schemas.js +36 -0
- package/dist/services/schemas.js.map +1 -1
- package/oclif.manifest.json +1694 -1691
- package/package.json +6 -5
|
@@ -33,6 +33,16 @@ import { toForwardSlashes } from '../../util/toForwardSlashes.js';
|
|
|
33
33
|
* @internal
|
|
34
34
|
*/ export function sanityTypegenPlugin(options) {
|
|
35
35
|
const { config: inputConfig, output = console, telemetryLogger, workDir } = options;
|
|
36
|
+
// Generating per resource is not supported here yet. Without this check the plugin would
|
|
37
|
+
// generate from the top-level `schema`, which a resources config does not use.
|
|
38
|
+
if (inputConfig.resources !== undefined) {
|
|
39
|
+
return {
|
|
40
|
+
configResolved () {
|
|
41
|
+
output.log(logSymbols.warning, 'Typegen during "sanity dev" does not support typegen.resources yet. Run "sanity typegen generate" instead.');
|
|
42
|
+
},
|
|
43
|
+
name: 'sanity/typegen'
|
|
44
|
+
};
|
|
45
|
+
}
|
|
36
46
|
// Apply defaults through the same schema as `sanity typegen generate`,
|
|
37
47
|
// so watch mode and manual generation produce identical output
|
|
38
48
|
const config = parseTypegenConfig(inputConfig);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/vite/plugin-typegen.ts"],"sourcesContent":["import {existsSync} from 'node:fs'\nimport path from 'node:path'\n\nimport {CLITelemetryStore} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\nimport {\n type GenerationResult,\n runTypegenGenerate,\n type TypeGenConfig,\n TypegenWatchModeTrace,\n TypesGeneratedTrace,\n} from '@sanity/codegen'\nimport debounce from 'lodash-es/debounce.js'\nimport mean from 'lodash-es/mean.js'\nimport once from 'lodash-es/once.js'\nimport picomatch from 'picomatch'\nimport {type Plugin} from 'vite'\n\nimport {parseTypegenConfig} from '../../actions/typegen/parseTypegenConfig.js'\nimport {toForwardSlashes} from '../../util/toForwardSlashes.js'\n\n/** Default debounce delay in milliseconds */\nconst DEFAULT_DEBOUNCE_MS = 1000\n\n/**\n * Delay before initial generation to allow Vite to finish startup\n * and avoid race conditions with module resolution.\n */\nconst INITIAL_GENERATION_DELAY_MS = 1000\n\n/**\n * Options for the Sanity typegen Vite plugin.\n *\n * @internal\n */\ninterface TypegenPluginOptions {\n /**\n * Typegen configuration from sanity.cli.ts.\n * All fields are optional and will use sensible defaults.\n */\n config: Partial<TypeGenConfig>\n\n /**\n * Working directory containing the Sanity configuration.\n * This should be the root of your Sanity Studio project.\n */\n workDir: string\n\n /**\n * Logger for output messages. Must implement `log`, `info`, and `error` methods.\n * @defaultValue `console`\n */\n output?: Pick<Console, 'error' | 'info' | 'log'>\n\n /**\n * Telemetry logger for the Sanity CLI tooling.\n */\n telemetryLogger?: CLITelemetryStore\n}\n\n/**\n * Creates a Vite plugin that automatically generates TypeScript types during development and build.\n *\n * **During development:**\n * The plugin performs an initial generation when the dev server starts, then watches\n * for file changes and re-generates types when relevant files are modified.\n *\n * **During build:**\n * The plugin generates types once at the end of the build process.\n *\n * **Prerequisites:**\n * The schema.json file must exist before typegen can run. Run `sanity schema extract`\n * first to generate the schema file.\n *\n * @param options - Configuration options for the plugin\n * @returns A Vite plugin configured for typegen\n *\n * @internal\n */\nexport function sanityTypegenPlugin(options: TypegenPluginOptions): Plugin {\n const {config: inputConfig, output = console, telemetryLogger, workDir} = options\n\n // Apply defaults through the same schema as `sanity typegen generate`,\n // so watch mode and manual generation produce identical output\n const config: TypeGenConfig = parseTypegenConfig(inputConfig)\n\n // Build query patterns from config\n const queryPatterns = Array.isArray(config.path) ? config.path : [config.path]\n\n // Resolved after Vite config is available\n let resolvedSchemaPath: string\n\n // State for concurrency control\n let isGenerating = false\n let pendingGeneration = false\n\n // Stats for telemetry\n const startTime = Date.now()\n const stats: {failedCount: number; successfulDurations: number[]} = {\n failedCount: 0,\n successfulDurations: [],\n }\n\n /**\n * Runs type generation with concurrency control.\n * If generation is already running, queues one more generation to run after completion.\n * Returns the generation result, or null if generation was skipped or failed.\n */\n async function runGeneration(isBuilding = false): Promise<GenerationResult | null> {\n if (isGenerating) {\n pendingGeneration = true\n return null\n }\n\n isGenerating = true\n pendingGeneration = false\n\n const generationStartTime = Date.now()\n\n try {\n // Validate schema.json exists\n if (!existsSync(resolvedSchemaPath)) {\n output.error(\n `${logSymbols.error} Schema file not found: ${config.schema}\\n` +\n `Run \"sanity schema extract\" first to generate the schema file.`,\n )\n return null\n }\n\n const result = await runTypegenGenerate({\n config,\n workDir,\n })\n\n if (isBuilding) {\n // Add newline for better formatting in build output\n output.log('')\n }\n\n if (result.filesWithErrors > 0) {\n output.log(\n logSymbols.warning,\n `Generated types to ${config.generates} (with errors in ${result.filesWithErrors} file${result.filesWithErrors === 1 ? '' : 's'})`,\n )\n } else {\n output.log(logSymbols.success, `Generated types to ${config.generates}`)\n }\n\n // Track stats for telemetry (all completed generations count as successful)\n stats.successfulDurations.push(Date.now() - generationStartTime)\n\n return result\n } catch (err) {\n output.error(\n `${logSymbols.error} Generation failed: ${err instanceof Error ? err.message : String(err)}`,\n )\n stats.failedCount++\n return null\n } finally {\n isGenerating = false\n\n // If a change came in during generation, run again\n if (pendingGeneration) {\n pendingGeneration = false\n void runGeneration()\n }\n }\n }\n\n const debouncedGenerate = debounce(() => {\n void runGeneration()\n }, DEFAULT_DEBOUNCE_MS)\n\n // Create a matcher function from query patterns\n const isQueryMatch = picomatch(queryPatterns)\n\n return {\n name: 'sanity/typegen',\n\n configResolved() {\n const rootDir = workDir\n\n resolvedSchemaPath = path.isAbsolute(config.schema)\n ? config.schema\n : path.join(rootDir, config.schema)\n },\n\n configureServer(server) {\n const trace = telemetryLogger?.trace(TypegenWatchModeTrace)\n trace?.start()\n trace?.log({step: 'started'})\n\n // Build absolute patterns for query files\n const absoluteQueryPatterns = queryPatterns.map((pattern) =>\n path.isAbsolute(pattern) ? pattern : path.join(workDir, pattern),\n )\n\n // Add query patterns AND schema.json to Vite's watcher\n server.watcher.add([...absoluteQueryPatterns, resolvedSchemaPath])\n\n // Listen for file changes\n const handleChange = (filePath: string) => {\n const relativePath = path.isAbsolute(filePath) ? path.relative(workDir, filePath) : filePath\n // Normalize to forward slashes for cross-platform picomatch compatibility\n const normalizedPath = toForwardSlashes(relativePath)\n\n // Trigger on schema.json change OR matching query file\n if (filePath === resolvedSchemaPath || isQueryMatch(normalizedPath)) {\n debouncedGenerate()\n }\n }\n\n // Prepare function to log \"stopped\" event to trace and complete the trace\n const onClose = once(() => {\n // Cancel any pending debounced extractions\n debouncedGenerate.cancel()\n\n if (trace) {\n trace.log({\n averageGenerationDuration: mean(stats.successfulDurations) || 0,\n generationFailedCount: stats.failedCount,\n generationSuccessfulCount: stats.successfulDurations.length,\n step: 'stopped',\n watcherDuration: Date.now() - startTime,\n })\n trace.complete()\n }\n\n // Clean up process listeners (must always run, not just when trace exists)\n process.off('SIGTERM', onClose)\n process.off('SIGINT', onClose)\n })\n\n server.watcher.on('change', handleChange)\n server.watcher.on('add', handleChange)\n server.watcher.on('unlink', handleChange)\n\n // Call the onClose method when watcher is closed or when process is stopped/killed\n server.watcher.on('close', onClose)\n process.on('SIGTERM', onClose)\n process.on('SIGINT', onClose)\n\n // Run initial generation after server is ready\n const startGeneration = () => {\n setTimeout(() => {\n // Notify about typegen enabled\n output.info(logSymbols.info, 'Typegen enabled. Watching:')\n for (const pattern of queryPatterns) {\n output.info(` - ${pattern}`)\n }\n output.info(` - ${config.schema} (schema)`)\n\n // Perform first generation\n void runGeneration()\n }, INITIAL_GENERATION_DELAY_MS)\n }\n\n if (server.httpServer) {\n server.httpServer.once('listening', startGeneration)\n } else {\n // Middleware mode - no HTTP server, run generation immediately\n startGeneration()\n }\n },\n\n async buildEnd() {\n // Build mode: One-time generation with telemetry tracking\n const result = await runGeneration(true)\n\n // Only log telemetry if generation completed successfully\n if (result && telemetryLogger) {\n const trace = telemetryLogger.trace(TypesGeneratedTrace)\n trace.start()\n trace.log({\n configMethod: 'cli',\n configOverloadClientMethods: config.overloadClientMethods ?? false,\n emptyUnionTypeNodesGenerated: result.emptyUnionTypeNodesGenerated,\n filesWithErrors: result.filesWithErrors,\n outputSize: result.code.length,\n queriesCount: result.queriesCount,\n queryFilesCount: result.queryFilesCount,\n schemaTypesCount: result.schemaTypesCount,\n typeNodesGenerated: result.typeNodesGenerated,\n unknownTypeNodesGenerated: result.unknownTypeNodesGenerated,\n unknownTypeNodesRatio:\n result.typeNodesGenerated > 0\n ? result.unknownTypeNodesGenerated / result.typeNodesGenerated\n : 0,\n })\n trace.complete()\n }\n },\n } satisfies Plugin\n}\n"],"names":["existsSync","path","logSymbols","runTypegenGenerate","TypegenWatchModeTrace","TypesGeneratedTrace","debounce","mean","once","picomatch","parseTypegenConfig","toForwardSlashes","DEFAULT_DEBOUNCE_MS","INITIAL_GENERATION_DELAY_MS","sanityTypegenPlugin","options","config","inputConfig","output","console","telemetryLogger","workDir","queryPatterns","Array","isArray","resolvedSchemaPath","isGenerating","pendingGeneration","startTime","Date","now","stats","failedCount","successfulDurations","runGeneration","isBuilding","generationStartTime","error","schema","result","log","filesWithErrors","warning","generates","success","push","err","Error","message","String","debouncedGenerate","isQueryMatch","name","configResolved","rootDir","isAbsolute","join","configureServer","server","trace","start","step","absoluteQueryPatterns","map","pattern","watcher","add","handleChange","filePath","relativePath","relative","normalizedPath","onClose","cancel","averageGenerationDuration","generationFailedCount","generationSuccessfulCount","length","watcherDuration","complete","process","off","on","startGeneration","setTimeout","info","httpServer","buildEnd","configMethod","configOverloadClientMethods","overloadClientMethods","emptyUnionTypeNodesGenerated","outputSize","code","queriesCount","queryFilesCount","schemaTypesCount","typeNodesGenerated","unknownTypeNodesGenerated","unknownTypeNodesRatio"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/server/vite/plugin-typegen.ts"],"sourcesContent":["import {existsSync} from 'node:fs'\nimport path from 'node:path'\n\nimport {type CliConfig, CLITelemetryStore} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\nimport {\n type GenerationResult,\n runTypegenGenerate,\n type TypeGenConfig,\n TypegenWatchModeTrace,\n TypesGeneratedTrace,\n} from '@sanity/codegen'\nimport debounce from 'lodash-es/debounce.js'\nimport mean from 'lodash-es/mean.js'\nimport once from 'lodash-es/once.js'\nimport picomatch from 'picomatch'\nimport {type Plugin} from 'vite'\n\nimport {parseTypegenConfig} from '../../actions/typegen/parseTypegenConfig.js'\nimport {toForwardSlashes} from '../../util/toForwardSlashes.js'\n\n/** Default debounce delay in milliseconds */\nconst DEFAULT_DEBOUNCE_MS = 1000\n\n/**\n * Delay before initial generation to allow Vite to finish startup\n * and avoid race conditions with module resolution.\n */\nconst INITIAL_GENERATION_DELAY_MS = 1000\n\n/**\n * Options for the Sanity typegen Vite plugin.\n *\n * @internal\n */\ninterface TypegenPluginOptions {\n /**\n * Typegen configuration from sanity.cli.ts.\n * All fields are optional and will use sensible defaults.\n */\n config: Partial<TypeGenConfig> & Pick<NonNullable<CliConfig['typegen']>, 'resources'>\n\n /**\n * Working directory containing the Sanity configuration.\n * This should be the root of your Sanity Studio project.\n */\n workDir: string\n\n /**\n * Logger for output messages. Must implement `log`, `info`, and `error` methods.\n * @defaultValue `console`\n */\n output?: Pick<Console, 'error' | 'info' | 'log'>\n\n /**\n * Telemetry logger for the Sanity CLI tooling.\n */\n telemetryLogger?: CLITelemetryStore\n}\n\n/**\n * Creates a Vite plugin that automatically generates TypeScript types during development and build.\n *\n * **During development:**\n * The plugin performs an initial generation when the dev server starts, then watches\n * for file changes and re-generates types when relevant files are modified.\n *\n * **During build:**\n * The plugin generates types once at the end of the build process.\n *\n * **Prerequisites:**\n * The schema.json file must exist before typegen can run. Run `sanity schema extract`\n * first to generate the schema file.\n *\n * @param options - Configuration options for the plugin\n * @returns A Vite plugin configured for typegen\n *\n * @internal\n */\nexport function sanityTypegenPlugin(options: TypegenPluginOptions): Plugin {\n const {config: inputConfig, output = console, telemetryLogger, workDir} = options\n\n // Generating per resource is not supported here yet. Without this check the plugin would\n // generate from the top-level `schema`, which a resources config does not use.\n if (inputConfig.resources !== undefined) {\n return {\n configResolved() {\n output.log(\n logSymbols.warning,\n 'Typegen during \"sanity dev\" does not support typegen.resources yet. Run \"sanity typegen generate\" instead.',\n )\n },\n name: 'sanity/typegen',\n } satisfies Plugin\n }\n\n // Apply defaults through the same schema as `sanity typegen generate`,\n // so watch mode and manual generation produce identical output\n const config: TypeGenConfig = parseTypegenConfig(inputConfig)\n\n // Build query patterns from config\n const queryPatterns = Array.isArray(config.path) ? config.path : [config.path]\n\n // Resolved after Vite config is available\n let resolvedSchemaPath: string\n\n // State for concurrency control\n let isGenerating = false\n let pendingGeneration = false\n\n // Stats for telemetry\n const startTime = Date.now()\n const stats: {failedCount: number; successfulDurations: number[]} = {\n failedCount: 0,\n successfulDurations: [],\n }\n\n /**\n * Runs type generation with concurrency control.\n * If generation is already running, queues one more generation to run after completion.\n * Returns the generation result, or null if generation was skipped or failed.\n */\n async function runGeneration(isBuilding = false): Promise<GenerationResult | null> {\n if (isGenerating) {\n pendingGeneration = true\n return null\n }\n\n isGenerating = true\n pendingGeneration = false\n\n const generationStartTime = Date.now()\n\n try {\n // Validate schema.json exists\n if (!existsSync(resolvedSchemaPath)) {\n output.error(\n `${logSymbols.error} Schema file not found: ${config.schema}\\n` +\n `Run \"sanity schema extract\" first to generate the schema file.`,\n )\n return null\n }\n\n const result = await runTypegenGenerate({\n config,\n workDir,\n })\n\n if (isBuilding) {\n // Add newline for better formatting in build output\n output.log('')\n }\n\n if (result.filesWithErrors > 0) {\n output.log(\n logSymbols.warning,\n `Generated types to ${config.generates} (with errors in ${result.filesWithErrors} file${result.filesWithErrors === 1 ? '' : 's'})`,\n )\n } else {\n output.log(logSymbols.success, `Generated types to ${config.generates}`)\n }\n\n // Track stats for telemetry (all completed generations count as successful)\n stats.successfulDurations.push(Date.now() - generationStartTime)\n\n return result\n } catch (err) {\n output.error(\n `${logSymbols.error} Generation failed: ${err instanceof Error ? err.message : String(err)}`,\n )\n stats.failedCount++\n return null\n } finally {\n isGenerating = false\n\n // If a change came in during generation, run again\n if (pendingGeneration) {\n pendingGeneration = false\n void runGeneration()\n }\n }\n }\n\n const debouncedGenerate = debounce(() => {\n void runGeneration()\n }, DEFAULT_DEBOUNCE_MS)\n\n // Create a matcher function from query patterns\n const isQueryMatch = picomatch(queryPatterns)\n\n return {\n name: 'sanity/typegen',\n\n configResolved() {\n const rootDir = workDir\n\n resolvedSchemaPath = path.isAbsolute(config.schema)\n ? config.schema\n : path.join(rootDir, config.schema)\n },\n\n configureServer(server) {\n const trace = telemetryLogger?.trace(TypegenWatchModeTrace)\n trace?.start()\n trace?.log({step: 'started'})\n\n // Build absolute patterns for query files\n const absoluteQueryPatterns = queryPatterns.map((pattern) =>\n path.isAbsolute(pattern) ? pattern : path.join(workDir, pattern),\n )\n\n // Add query patterns AND schema.json to Vite's watcher\n server.watcher.add([...absoluteQueryPatterns, resolvedSchemaPath])\n\n // Listen for file changes\n const handleChange = (filePath: string) => {\n const relativePath = path.isAbsolute(filePath) ? path.relative(workDir, filePath) : filePath\n // Normalize to forward slashes for cross-platform picomatch compatibility\n const normalizedPath = toForwardSlashes(relativePath)\n\n // Trigger on schema.json change OR matching query file\n if (filePath === resolvedSchemaPath || isQueryMatch(normalizedPath)) {\n debouncedGenerate()\n }\n }\n\n // Prepare function to log \"stopped\" event to trace and complete the trace\n const onClose = once(() => {\n // Cancel any pending debounced extractions\n debouncedGenerate.cancel()\n\n if (trace) {\n trace.log({\n averageGenerationDuration: mean(stats.successfulDurations) || 0,\n generationFailedCount: stats.failedCount,\n generationSuccessfulCount: stats.successfulDurations.length,\n step: 'stopped',\n watcherDuration: Date.now() - startTime,\n })\n trace.complete()\n }\n\n // Clean up process listeners (must always run, not just when trace exists)\n process.off('SIGTERM', onClose)\n process.off('SIGINT', onClose)\n })\n\n server.watcher.on('change', handleChange)\n server.watcher.on('add', handleChange)\n server.watcher.on('unlink', handleChange)\n\n // Call the onClose method when watcher is closed or when process is stopped/killed\n server.watcher.on('close', onClose)\n process.on('SIGTERM', onClose)\n process.on('SIGINT', onClose)\n\n // Run initial generation after server is ready\n const startGeneration = () => {\n setTimeout(() => {\n // Notify about typegen enabled\n output.info(logSymbols.info, 'Typegen enabled. Watching:')\n for (const pattern of queryPatterns) {\n output.info(` - ${pattern}`)\n }\n output.info(` - ${config.schema} (schema)`)\n\n // Perform first generation\n void runGeneration()\n }, INITIAL_GENERATION_DELAY_MS)\n }\n\n if (server.httpServer) {\n server.httpServer.once('listening', startGeneration)\n } else {\n // Middleware mode - no HTTP server, run generation immediately\n startGeneration()\n }\n },\n\n async buildEnd() {\n // Build mode: One-time generation with telemetry tracking\n const result = await runGeneration(true)\n\n // Only log telemetry if generation completed successfully\n if (result && telemetryLogger) {\n const trace = telemetryLogger.trace(TypesGeneratedTrace)\n trace.start()\n trace.log({\n configMethod: 'cli',\n configOverloadClientMethods: config.overloadClientMethods ?? false,\n emptyUnionTypeNodesGenerated: result.emptyUnionTypeNodesGenerated,\n filesWithErrors: result.filesWithErrors,\n outputSize: result.code.length,\n queriesCount: result.queriesCount,\n queryFilesCount: result.queryFilesCount,\n schemaTypesCount: result.schemaTypesCount,\n typeNodesGenerated: result.typeNodesGenerated,\n unknownTypeNodesGenerated: result.unknownTypeNodesGenerated,\n unknownTypeNodesRatio:\n result.typeNodesGenerated > 0\n ? result.unknownTypeNodesGenerated / result.typeNodesGenerated\n : 0,\n })\n trace.complete()\n }\n },\n } satisfies Plugin\n}\n"],"names":["existsSync","path","logSymbols","runTypegenGenerate","TypegenWatchModeTrace","TypesGeneratedTrace","debounce","mean","once","picomatch","parseTypegenConfig","toForwardSlashes","DEFAULT_DEBOUNCE_MS","INITIAL_GENERATION_DELAY_MS","sanityTypegenPlugin","options","config","inputConfig","output","console","telemetryLogger","workDir","resources","undefined","configResolved","log","warning","name","queryPatterns","Array","isArray","resolvedSchemaPath","isGenerating","pendingGeneration","startTime","Date","now","stats","failedCount","successfulDurations","runGeneration","isBuilding","generationStartTime","error","schema","result","filesWithErrors","generates","success","push","err","Error","message","String","debouncedGenerate","isQueryMatch","rootDir","isAbsolute","join","configureServer","server","trace","start","step","absoluteQueryPatterns","map","pattern","watcher","add","handleChange","filePath","relativePath","relative","normalizedPath","onClose","cancel","averageGenerationDuration","generationFailedCount","generationSuccessfulCount","length","watcherDuration","complete","process","off","on","startGeneration","setTimeout","info","httpServer","buildEnd","configMethod","configOverloadClientMethods","overloadClientMethods","emptyUnionTypeNodesGenerated","outputSize","code","queriesCount","queryFilesCount","schemaTypesCount","typeNodesGenerated","unknownTypeNodesGenerated","unknownTypeNodesRatio"],"mappings":"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"}
|
package/dist/services/schemas.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { getGlobalCliClient } from '@sanity/cli-core';
|
|
2
|
+
import { EXPERIMENTAL_API_WARNING, isHttpError } from '@sanity/client';
|
|
2
3
|
export const SCHEMA_API_VERSION = 'v2025-03-01';
|
|
4
|
+
/** The dataset schema binding endpoint is only available on the experimental API version. */ export const SCHEMA_BINDING_API_VERSION = 'vX';
|
|
5
|
+
export const SCHEMA_DESCRIPTOR_API_VERSION = 'v2025-06-01';
|
|
3
6
|
async function getSchemaClient() {
|
|
4
7
|
return await getGlobalCliClient({
|
|
5
8
|
apiVersion: SCHEMA_API_VERSION,
|
|
@@ -26,6 +29,39 @@ export async function deleteSchema(dataset, projectId, id) {
|
|
|
26
29
|
url: `/projects/${projectId}/datasets/${dataset}/schemas/${id}`
|
|
27
30
|
});
|
|
28
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Gets the schema bound to a dataset, or `null` when the dataset has no binding.
|
|
34
|
+
*/ export async function getDatasetSchemaBinding(projectId, dataset) {
|
|
35
|
+
const client = await getGlobalCliClient({
|
|
36
|
+
apiVersion: SCHEMA_BINDING_API_VERSION,
|
|
37
|
+
// The endpoint has no stable version yet, and the warning would interrupt command output.
|
|
38
|
+
// The client splits the warning header on commas, so its second clause is matched separately.
|
|
39
|
+
ignoreWarnings: [
|
|
40
|
+
EXPERIMENTAL_API_WARNING,
|
|
41
|
+
'which will change without warning'
|
|
42
|
+
],
|
|
43
|
+
requireUser: true
|
|
44
|
+
});
|
|
45
|
+
try {
|
|
46
|
+
return await client.request({
|
|
47
|
+
url: `/schemas/dataset/${encodeURIComponent(`${projectId}.${dataset}`)}`
|
|
48
|
+
});
|
|
49
|
+
} catch (err) {
|
|
50
|
+
if (isHttpError(err) && err.statusCode === 404) return null;
|
|
51
|
+
throw err;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Gets a schema descriptor from Lexicon by its ID, such as a binding's `schemaVersion`.
|
|
56
|
+
*/ export async function getSchemaDescriptor(id) {
|
|
57
|
+
const client = await getGlobalCliClient({
|
|
58
|
+
apiVersion: SCHEMA_DESCRIPTOR_API_VERSION,
|
|
59
|
+
requireUser: true
|
|
60
|
+
});
|
|
61
|
+
return client.request({
|
|
62
|
+
url: `/descriptors/schemas/${encodeURIComponent(id)}`
|
|
63
|
+
});
|
|
64
|
+
}
|
|
29
65
|
export async function updateSchemas(dataset, projectId, schemas) {
|
|
30
66
|
const client = await getSchemaClient();
|
|
31
67
|
return client.request({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/services/schemas.ts"],"sourcesContent":["import {type StoredWorkspaceSchema} from '@sanity/cli-build/_internal/manifest'\nimport {getGlobalCliClient} from '@sanity/cli-core'\n\nexport const SCHEMA_API_VERSION = 'v2025-03-01'\n\nasync function getSchemaClient() {\n return await getGlobalCliClient({\n apiVersion: SCHEMA_API_VERSION,\n requireUser: true,\n })\n}\n\nexport async function getSchemas(dataset: string, projectId: string, id?: string) {\n const client = await getSchemaClient()\n\n return client.request<StoredWorkspaceSchema[]>({\n method: 'GET',\n url: `/projects/${projectId}/datasets/${dataset}/schemas${id ? `/${id}` : ''}`,\n })\n}\n\nexport async function deleteSchema(dataset: string, projectId: string, id: string) {\n const exists = await getSchemas(dataset, projectId, id)\n\n if (exists?.length === 0) {\n return {\n deleted: false,\n }\n }\n\n const client = await getSchemaClient()\n\n return client.request({\n method: 'DELETE',\n url: `/projects/${projectId}/datasets/${dataset}/schemas/${id}`,\n })\n}\n\nexport async function updateSchemas<T>(dataset: string, projectId: string, schemas: T) {\n const client = await getSchemaClient()\n\n return client.request({\n body: {\n schemas,\n },\n method: 'PUT',\n url: `/projects/${projectId}/datasets/${dataset}/schemas`,\n })\n}\n"],"names":["getGlobalCliClient","SCHEMA_API_VERSION","getSchemaClient","apiVersion","requireUser","getSchemas","dataset","projectId","id","client","request","method","url","deleteSchema","exists","length","deleted","updateSchemas","schemas","body"],"mappings":"AACA,SAAQA,kBAAkB,QAAO,mBAAkB;
|
|
1
|
+
{"version":3,"sources":["../../src/services/schemas.ts"],"sourcesContent":["import {type StoredWorkspaceSchema} from '@sanity/cli-build/_internal/manifest'\nimport {getGlobalCliClient} from '@sanity/cli-core'\nimport {EXPERIMENTAL_API_WARNING, isHttpError} from '@sanity/client'\nimport {type SchemaSummary} from '@sanity/schema-descriptor-utils'\n\nexport const SCHEMA_API_VERSION = 'v2025-03-01'\n\n/** The dataset schema binding endpoint is only available on the experimental API version. */\nexport const SCHEMA_BINDING_API_VERSION = 'vX'\n\nexport const SCHEMA_DESCRIPTOR_API_VERSION = 'v2025-06-01'\n\n/**\n * The schema bound to a dataset, as returned by `GET /schemas/dataset/:projectId.:dataset`.\n * Only `_meta` is used: its `types` are hydrated for display and cannot be compiled.\n */\nexport interface DatasetSchemaBinding {\n _meta: {\n producer: 'api' | 'blueprint' | 'mcp' | 'studio'\n /** The Lexicon descriptor ID of the bound schema. Also returned as the `ETag`. */\n schemaVersion: string\n source: string | null\n sourceLabel: string | null\n }\n name: string\n}\n\nasync function getSchemaClient() {\n return await getGlobalCliClient({\n apiVersion: SCHEMA_API_VERSION,\n requireUser: true,\n })\n}\n\nexport async function getSchemas(dataset: string, projectId: string, id?: string) {\n const client = await getSchemaClient()\n\n return client.request<StoredWorkspaceSchema[]>({\n method: 'GET',\n url: `/projects/${projectId}/datasets/${dataset}/schemas${id ? `/${id}` : ''}`,\n })\n}\n\nexport async function deleteSchema(dataset: string, projectId: string, id: string) {\n const exists = await getSchemas(dataset, projectId, id)\n\n if (exists?.length === 0) {\n return {\n deleted: false,\n }\n }\n\n const client = await getSchemaClient()\n\n return client.request({\n method: 'DELETE',\n url: `/projects/${projectId}/datasets/${dataset}/schemas/${id}`,\n })\n}\n\n/**\n * Gets the schema bound to a dataset, or `null` when the dataset has no binding.\n */\nexport async function getDatasetSchemaBinding(\n projectId: string,\n dataset: string,\n): Promise<DatasetSchemaBinding | null> {\n const client = await getGlobalCliClient({\n apiVersion: SCHEMA_BINDING_API_VERSION,\n // The endpoint has no stable version yet, and the warning would interrupt command output.\n // The client splits the warning header on commas, so its second clause is matched separately.\n ignoreWarnings: [EXPERIMENTAL_API_WARNING, 'which will change without warning'],\n requireUser: true,\n })\n\n try {\n return await client.request<DatasetSchemaBinding>({\n url: `/schemas/dataset/${encodeURIComponent(`${projectId}.${dataset}`)}`,\n })\n } catch (err) {\n if (isHttpError(err) && err.statusCode === 404) return null\n throw err\n }\n}\n\n/**\n * Gets a schema descriptor from Lexicon by its ID, such as a binding's `schemaVersion`.\n */\nexport async function getSchemaDescriptor(id: string): Promise<SchemaSummary> {\n const client = await getGlobalCliClient({\n apiVersion: SCHEMA_DESCRIPTOR_API_VERSION,\n requireUser: true,\n })\n\n return client.request<SchemaSummary>({\n url: `/descriptors/schemas/${encodeURIComponent(id)}`,\n })\n}\n\nexport async function updateSchemas<T>(dataset: string, projectId: string, schemas: T) {\n const client = await getSchemaClient()\n\n return client.request({\n body: {\n schemas,\n },\n method: 'PUT',\n url: `/projects/${projectId}/datasets/${dataset}/schemas`,\n })\n}\n"],"names":["getGlobalCliClient","EXPERIMENTAL_API_WARNING","isHttpError","SCHEMA_API_VERSION","SCHEMA_BINDING_API_VERSION","SCHEMA_DESCRIPTOR_API_VERSION","getSchemaClient","apiVersion","requireUser","getSchemas","dataset","projectId","id","client","request","method","url","deleteSchema","exists","length","deleted","getDatasetSchemaBinding","ignoreWarnings","encodeURIComponent","err","statusCode","getSchemaDescriptor","updateSchemas","schemas","body"],"mappings":"AACA,SAAQA,kBAAkB,QAAO,mBAAkB;AACnD,SAAQC,wBAAwB,EAAEC,WAAW,QAAO,iBAAgB;AAGpE,OAAO,MAAMC,qBAAqB,cAAa;AAE/C,2FAA2F,GAC3F,OAAO,MAAMC,6BAA6B,KAAI;AAE9C,OAAO,MAAMC,gCAAgC,cAAa;AAiB1D,eAAeC;IACb,OAAO,MAAMN,mBAAmB;QAC9BO,YAAYJ;QACZK,aAAa;IACf;AACF;AAEA,OAAO,eAAeC,WAAWC,OAAe,EAAEC,SAAiB,EAAEC,EAAW;IAC9E,MAAMC,SAAS,MAAMP;IAErB,OAAOO,OAAOC,OAAO,CAA0B;QAC7CC,QAAQ;QACRC,KAAK,CAAC,UAAU,EAAEL,UAAU,UAAU,EAAED,QAAQ,QAAQ,EAAEE,KAAK,CAAC,CAAC,EAAEA,IAAI,GAAG,IAAI;IAChF;AACF;AAEA,OAAO,eAAeK,aAAaP,OAAe,EAAEC,SAAiB,EAAEC,EAAU;IAC/E,MAAMM,SAAS,MAAMT,WAAWC,SAASC,WAAWC;IAEpD,IAAIM,QAAQC,WAAW,GAAG;QACxB,OAAO;YACLC,SAAS;QACX;IACF;IAEA,MAAMP,SAAS,MAAMP;IAErB,OAAOO,OAAOC,OAAO,CAAC;QACpBC,QAAQ;QACRC,KAAK,CAAC,UAAU,EAAEL,UAAU,UAAU,EAAED,QAAQ,SAAS,EAAEE,IAAI;IACjE;AACF;AAEA;;CAEC,GACD,OAAO,eAAeS,wBACpBV,SAAiB,EACjBD,OAAe;IAEf,MAAMG,SAAS,MAAMb,mBAAmB;QACtCO,YAAYH;QACZ,0FAA0F;QAC1F,8FAA8F;QAC9FkB,gBAAgB;YAACrB;YAA0B;SAAoC;QAC/EO,aAAa;IACf;IAEA,IAAI;QACF,OAAO,MAAMK,OAAOC,OAAO,CAAuB;YAChDE,KAAK,CAAC,iBAAiB,EAAEO,mBAAmB,GAAGZ,UAAU,CAAC,EAAED,SAAS,GAAG;QAC1E;IACF,EAAE,OAAOc,KAAK;QACZ,IAAItB,YAAYsB,QAAQA,IAAIC,UAAU,KAAK,KAAK,OAAO;QACvD,MAAMD;IACR;AACF;AAEA;;CAEC,GACD,OAAO,eAAeE,oBAAoBd,EAAU;IAClD,MAAMC,SAAS,MAAMb,mBAAmB;QACtCO,YAAYF;QACZG,aAAa;IACf;IAEA,OAAOK,OAAOC,OAAO,CAAgB;QACnCE,KAAK,CAAC,qBAAqB,EAAEO,mBAAmBX,KAAK;IACvD;AACF;AAEA,OAAO,eAAee,cAAiBjB,OAAe,EAAEC,SAAiB,EAAEiB,OAAU;IACnF,MAAMf,SAAS,MAAMP;IAErB,OAAOO,OAAOC,OAAO,CAAC;QACpBe,MAAM;YACJD;QACF;QACAb,QAAQ;QACRC,KAAK,CAAC,UAAU,EAAEL,UAAU,UAAU,EAAED,QAAQ,QAAQ,CAAC;IAC3D;AACF"}
|