@sanity/cli 6.1.7 → 6.2.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 +105 -103
- package/dist/actions/build/buildStudio.js +1 -1
- package/dist/actions/build/buildStudio.js.map +1 -1
- package/dist/actions/debug/gatherDebugInfo.js +130 -81
- package/dist/actions/debug/gatherDebugInfo.js.map +1 -1
- package/dist/actions/debug/output.js +25 -0
- package/dist/actions/debug/output.js.map +1 -0
- package/dist/actions/debug/types.js.map +1 -1
- package/dist/actions/mcp/setupMCP.js +5 -5
- package/dist/actions/mcp/setupMCP.js.map +1 -1
- package/dist/actions/schema/getExtractOptions.js.map +1 -1
- package/dist/commands/{backup → backups}/disable.js +3 -0
- package/dist/commands/backups/disable.js.map +1 -0
- package/dist/commands/{backup → backups}/download.js +3 -0
- package/dist/commands/backups/download.js.map +1 -0
- package/dist/commands/{backup → backups}/enable.js +3 -0
- package/dist/commands/backups/enable.js.map +1 -0
- package/dist/commands/{backup → backups}/list.js +3 -0
- package/dist/commands/backups/list.js.map +1 -0
- package/dist/commands/{dataset → datasets}/alias/create.js +3 -0
- package/dist/commands/datasets/alias/create.js.map +1 -0
- package/dist/commands/{dataset → datasets}/alias/delete.js +3 -0
- package/dist/commands/datasets/alias/delete.js.map +1 -0
- package/dist/commands/{dataset → datasets}/alias/link.js +3 -0
- package/dist/commands/datasets/alias/link.js.map +1 -0
- package/dist/commands/{dataset → datasets}/alias/unlink.js +3 -0
- package/dist/commands/datasets/alias/unlink.js.map +1 -0
- package/dist/commands/{dataset → datasets}/copy.js +3 -0
- package/dist/commands/datasets/copy.js.map +1 -0
- package/dist/commands/{dataset → datasets}/create.js +3 -0
- package/dist/commands/datasets/create.js.map +1 -0
- package/dist/commands/{dataset → datasets}/delete.js +3 -0
- package/dist/commands/datasets/delete.js.map +1 -0
- package/dist/commands/{dataset → datasets}/embeddings/disable.js +3 -0
- package/dist/commands/datasets/embeddings/disable.js.map +1 -0
- package/dist/commands/{dataset → datasets}/embeddings/enable.js +3 -0
- package/dist/commands/datasets/embeddings/enable.js.map +1 -0
- package/dist/commands/{dataset → datasets}/embeddings/status.js +3 -0
- package/dist/commands/datasets/embeddings/status.js.map +1 -0
- package/dist/commands/{dataset → datasets}/export.js +3 -0
- package/dist/commands/datasets/export.js.map +1 -0
- package/dist/commands/{dataset → datasets}/import.js +3 -0
- package/dist/commands/datasets/import.js.map +1 -0
- package/dist/commands/{dataset → datasets}/list.js +3 -0
- package/dist/commands/datasets/list.js.map +1 -0
- package/dist/commands/{dataset → datasets}/visibility/get.js +3 -0
- package/dist/commands/datasets/visibility/get.js.map +1 -0
- package/dist/commands/{dataset → datasets}/visibility/set.js +3 -0
- package/dist/commands/datasets/visibility/set.js.map +1 -0
- package/dist/commands/debug.js +189 -74
- package/dist/commands/debug.js.map +1 -1
- package/dist/commands/documents/create.js +3 -0
- package/dist/commands/documents/create.js.map +1 -1
- package/dist/commands/documents/delete.js +3 -0
- package/dist/commands/documents/delete.js.map +1 -1
- package/dist/commands/documents/get.js +3 -0
- package/dist/commands/documents/get.js.map +1 -1
- package/dist/commands/documents/query.js +3 -0
- package/dist/commands/documents/query.js.map +1 -1
- package/dist/commands/documents/validate.js +3 -0
- package/dist/commands/documents/validate.js.map +1 -1
- package/dist/commands/{hook → hooks}/attempt.js +3 -0
- package/dist/commands/hooks/attempt.js.map +1 -0
- package/dist/commands/{hook → hooks}/create.js +3 -0
- package/dist/commands/hooks/create.js.map +1 -0
- package/dist/commands/{hook → hooks}/delete.js +3 -0
- package/dist/commands/hooks/delete.js.map +1 -0
- package/dist/commands/{hook → hooks}/list.js +3 -0
- package/dist/commands/hooks/list.js.map +1 -0
- package/dist/commands/{hook → hooks}/logs.js +3 -0
- package/dist/commands/hooks/logs.js.map +1 -0
- package/dist/commands/init.js +65 -13
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mcp/configure.js +3 -2
- package/dist/commands/mcp/configure.js.map +1 -1
- package/dist/commands/preview.js +1 -0
- package/dist/commands/preview.js.map +1 -1
- package/dist/commands/projects/create.js +3 -0
- package/dist/commands/projects/create.js.map +1 -1
- package/dist/commands/projects/list.js +3 -0
- package/dist/commands/projects/list.js.map +1 -1
- package/dist/commands/{schema → schemas}/delete.js +3 -0
- package/dist/commands/schemas/delete.js.map +1 -0
- package/dist/commands/{schema → schemas}/deploy.js +3 -0
- package/dist/commands/schemas/deploy.js.map +1 -0
- package/dist/commands/{schema → schemas}/extract.js +3 -0
- package/dist/commands/schemas/extract.js.map +1 -0
- package/dist/commands/{schema → schemas}/list.js +3 -0
- package/dist/commands/schemas/list.js.map +1 -0
- package/dist/commands/{schema → schemas}/validate.js +3 -0
- package/dist/commands/schemas/validate.js.map +1 -0
- package/dist/commands/tokens/add.js +3 -0
- package/dist/commands/tokens/add.js.map +1 -1
- package/dist/commands/tokens/delete.js +3 -0
- package/dist/commands/tokens/delete.js.map +1 -1
- package/dist/commands/tokens/list.js +3 -0
- package/dist/commands/tokens/list.js.map +1 -1
- package/dist/commands/users/invite.js +3 -0
- package/dist/commands/users/invite.js.map +1 -1
- package/dist/commands/users/list.js +3 -0
- package/dist/commands/users/list.js.map +1 -1
- package/dist/hooks/commandNotFound/topicAliases.js +71 -0
- package/dist/hooks/commandNotFound/topicAliases.js.map +1 -0
- package/dist/services/mcp.js +32 -44
- package/dist/services/mcp.js.map +1 -1
- package/dist/topicAliases.js +51 -0
- package/dist/topicAliases.js.map +1 -0
- package/oclif.config.js +20 -7
- package/oclif.manifest.json +321 -209
- package/package.json +22 -21
- package/dist/actions/debug/formatters.js +0 -22
- package/dist/actions/debug/formatters.js.map +0 -1
- package/dist/actions/debug/getGlobalConfigLocation.js +0 -7
- package/dist/actions/debug/getGlobalConfigLocation.js.map +0 -1
- package/dist/commands/backup/disable.js.map +0 -1
- package/dist/commands/backup/download.js.map +0 -1
- package/dist/commands/backup/enable.js.map +0 -1
- package/dist/commands/backup/list.js.map +0 -1
- package/dist/commands/dataset/alias/create.js.map +0 -1
- package/dist/commands/dataset/alias/delete.js.map +0 -1
- package/dist/commands/dataset/alias/link.js.map +0 -1
- package/dist/commands/dataset/alias/unlink.js.map +0 -1
- package/dist/commands/dataset/copy.js.map +0 -1
- package/dist/commands/dataset/create.js.map +0 -1
- package/dist/commands/dataset/delete.js.map +0 -1
- package/dist/commands/dataset/embeddings/disable.js.map +0 -1
- package/dist/commands/dataset/embeddings/enable.js.map +0 -1
- package/dist/commands/dataset/embeddings/status.js.map +0 -1
- package/dist/commands/dataset/export.js.map +0 -1
- package/dist/commands/dataset/import.js.map +0 -1
- package/dist/commands/dataset/list.js.map +0 -1
- package/dist/commands/dataset/visibility/get.js.map +0 -1
- package/dist/commands/dataset/visibility/set.js.map +0 -1
- package/dist/commands/hook/attempt.js.map +0 -1
- package/dist/commands/hook/create.js.map +0 -1
- package/dist/commands/hook/delete.js.map +0 -1
- package/dist/commands/hook/list.js.map +0 -1
- package/dist/commands/hook/logs.js.map +0 -1
- package/dist/commands/schema/delete.js.map +0 -1
- package/dist/commands/schema/deploy.js.map +0 -1
- package/dist/commands/schema/extract.js.map +0 -1
- package/dist/commands/schema/list.js.map +0 -1
- package/dist/commands/schema/validate.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/datasets/import.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\n\nimport {Args, Flags} from '@oclif/core'\nimport {getProjectCliClient, SanityCommand} from '@sanity/cli-core'\nimport {createRequester} from '@sanity/cli-core/request'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {sanityImport} from '@sanity/import'\nimport prettyMs from 'pretty-ms'\n\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {getDatasetFlag, getProjectIdFlag} from '../../util/sharedFlags.js'\n\ninterface ProgressEvent {\n step: string\n\n current?: number\n total?: number\n update?: string\n}\n\nfunction getAssetsBase(source: string): string | undefined {\n if (/^https?:\\/\\//i.test(source) || source === '-') {\n return undefined\n }\n\n try {\n const fileStats = fs.statSync(source)\n const sourceIsFolder = fileStats.isDirectory()\n return sourceIsFolder ? source : path.dirname(source)\n } catch {\n return undefined\n }\n}\n\nasync function getUriStream(uri: string): Promise<NodeJS.ReadableStream> {\n const request = createRequester({\n middleware: {promise: {onlyBody: false}},\n })\n\n try {\n const response = (await request({stream: true, url: uri})) as {body: NodeJS.ReadableStream}\n return response.body\n } catch (err) {\n throw new Error(`Error fetching source:\\n${(err as Error).message}`)\n }\n}\n\nfunction getPercentage(opts: ProgressEvent): string {\n if (!opts.total) {\n return ''\n }\n\n const percent = Math.floor(((opts.current || 0) / opts.total) * 100)\n return `[${percent}%] `\n}\n\nexport class ImportDatasetCommand extends SanityCommand<typeof ImportDatasetCommand> {\n static override args = {\n source: Args.string({\n description: 'Source file (use \"-\" for stdin)',\n required: true,\n }),\n targetDataset: Args.string({\n description: 'Target dataset (prefer --dataset flag instead)',\n required: false,\n }),\n }\n\n static override description = 'Import documents to a Sanity dataset'\n\n static override examples = [\n {\n command:\n '<%= config.bin %> <%= command.id %> -d staging -t someSecretToken my-dataset.ndjson',\n description: 'Import \"./my-dataset.ndjson\" into dataset \"staging\"',\n },\n {\n command: 'cat my-dataset.ndjson | <%= config.bin %> <%= command.id %> -d test -t someToken -',\n description: 'Import into dataset \"test\" from stdin',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> -p projectId -d staging -t someSecretToken my-dataset.ndjson',\n description: 'Import with explicit project ID (overrides CLI configuration)',\n },\n ]\n\n static override flags = {\n 'allow-assets-in-different-dataset': Flags.boolean({\n default: false,\n description: 'Allow asset documents to reference different project/dataset',\n }),\n 'allow-failing-assets': Flags.boolean({\n default: false,\n description: 'Skip assets that cannot be fetched/uploaded',\n }),\n 'allow-replacement-characters': Flags.boolean({\n default: false,\n description: 'Allow unicode replacement characters in imported documents',\n }),\n 'allow-system-documents': Flags.boolean({\n default: false,\n description: 'Imports system documents',\n }),\n 'asset-concurrency': Flags.integer({\n description: 'Number of parallel asset imports',\n }),\n ...getDatasetFlag({\n description: 'Dataset to import to',\n semantics: 'specify',\n }),\n missing: Flags.boolean({\n default: false,\n description: 'Skip documents that already exist',\n exclusive: ['replace'],\n }),\n ...getProjectIdFlag({\n description: 'Project ID to import to',\n semantics: 'override',\n }),\n project: Flags.string({\n deprecated: {to: 'project-id'},\n description: 'Project ID to import to',\n hidden: true,\n }),\n replace: Flags.boolean({\n default: false,\n description: 'Replace documents with the same IDs',\n exclusive: ['missing'],\n }),\n 'replace-assets': Flags.boolean({\n default: false,\n description: 'Skip reuse of existing assets',\n }),\n 'skip-cross-dataset-references': Flags.boolean({\n default: false,\n description: 'Skips references to other datasets',\n }),\n token: Flags.string({\n char: 't',\n description: 'Token to authenticate with',\n env: 'SANITY_IMPORT_TOKEN',\n required: false,\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:import']\n\n private currentProgress?: ReturnType<typeof spinner>\n private currentStep?: string\n private spinInterval?: NodeJS.Timeout | null\n private stepStart?: number\n\n private static async getStream(source: string): Promise<NodeJS.ReadableStream> {\n if (/^https?:\\/\\//i.test(source)) {\n return getUriStream(source)\n }\n\n return source === '-' ? process.stdin : fs.createReadStream(source)\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(ImportDatasetCommand)\n\n const {\n 'allow-assets-in-different-dataset': allowAssetsInDifferentDataset,\n 'allow-failing-assets': allowFailingAssets,\n 'allow-replacement-characters': allowReplacementCharacters,\n 'allow-system-documents': allowSystemDocuments,\n 'asset-concurrency': assetConcurrency,\n dataset: datasetFlag,\n missing,\n replace,\n 'replace-assets': replaceAssets,\n 'skip-cross-dataset-references': skipCrossDatasetReferences,\n token,\n } = flags\n\n const projectId = await this.getProjectId({\n deprecatedFlagName: 'project',\n fallback: () => promptForProject({}),\n })\n\n const {source, targetDataset: targetDatasetArg} = args\n\n if (targetDatasetArg && !datasetFlag) {\n this.warn(\n 'Positional dataset argument is deprecated. Use the --dataset flag instead: --dataset <name>',\n )\n }\n\n const dataset = datasetFlag ?? targetDatasetArg\n if (!dataset) {\n this.error('Missing dataset. Use the --dataset flag to specify a dataset: --dataset <name>', {\n exit: 1,\n })\n }\n\n const tokenString: string | undefined = token\n if (!tokenString) {\n this.error('Flag `--token` is required (or set SANITY_IMPORT_TOKEN)', {exit: 1})\n }\n\n let operation: 'create' | 'createIfNotExists' | 'createOrReplace' = 'create'\n let releasesOperation: 'fail' | 'ignore' | 'replace' = 'fail'\n\n if (replace || missing) {\n operation = replace ? 'createOrReplace' : 'createIfNotExists'\n releasesOperation = replace ? 'replace' : 'ignore'\n }\n\n const client = await getProjectCliClient({\n apiVersion: 'v2025-02-19',\n dataset,\n projectId,\n token: tokenString,\n })\n\n try {\n const stream = await ImportDatasetCommand.getStream(source)\n const assetsBase = getAssetsBase(source)\n\n const importOptions = {\n allowAssetsInDifferentDataset,\n allowFailingAssets,\n allowReplacementCharacters,\n allowSystemDocuments,\n client,\n onProgress: this.onProgress.bind(this),\n operation,\n releasesOperation,\n replaceAssets,\n skipCrossDatasetReferences,\n tag: 'sanity.import',\n targetDataset: dataset,\n targetProjectId: projectId,\n ...(assetsBase ? {assetsBase} : {}),\n ...(assetConcurrency === undefined ? {} : {assetConcurrency}),\n }\n\n const {numDocs, warnings} = await sanityImport(stream as NodeJS.ReadableStream, importOptions)\n\n if (this.stepStart) {\n const timeSpent = prettyMs(Date.now() - this.stepStart, {secondsDecimalDigits: 2})\n if (this.currentProgress) {\n if (this.spinInterval) {\n clearInterval(this.spinInterval)\n this.spinInterval = null\n }\n this.currentProgress.text = `[100%] ${this.currentStep} (${timeSpent})`\n this.currentProgress.succeed()\n }\n }\n\n this.log('Done! Imported %d documents to dataset \"%s\"\\n', numDocs, dataset)\n this.printWarnings(warnings)\n } catch (err) {\n if (this.spinInterval) {\n clearInterval(this.spinInterval)\n this.spinInterval = null\n }\n\n if (this.currentProgress) {\n this.currentProgress.fail()\n }\n\n if ((err as Error).name === 'ReplacementCharError') {\n this.error(\n `Import failed due to unicode replacement characters in the data.\\n${(err as Error).message}\\n\\nIf you are certain you want to proceed with the import despite potentially corrupt data, re-run the import with the \\`--allow-replacement-characters\\` flag set.`,\n {exit: 1},\n )\n } else {\n this.error((err as Error).stack || (err as Error).message, {exit: 1})\n }\n }\n }\n\n private onProgress(opts: ProgressEvent): void {\n const lengthComputable = opts.total\n const sameStep = opts.step === this.currentStep\n const percent = getPercentage(opts)\n\n if (lengthComputable && opts.total === opts.current && this.spinInterval) {\n clearInterval(this.spinInterval)\n this.spinInterval = null\n }\n\n if (sameStep && !lengthComputable) {\n return\n }\n\n if (sameStep) {\n if (this.stepStart) {\n const timeSpent = prettyMs(Date.now() - this.stepStart, {secondsDecimalDigits: 2})\n if (this.currentProgress) {\n this.currentProgress.text = `${percent}${opts.step} (${timeSpent})`\n this.currentProgress.render()\n }\n }\n return\n }\n\n // Moved to a new step\n const prevStep = this.currentStep\n const prevStepStart = this.stepStart\n this.stepStart = Date.now()\n this.currentStep = opts.step\n\n if (this.spinInterval) {\n clearInterval(this.spinInterval)\n this.spinInterval = null\n }\n\n if (this.currentProgress && this.currentProgress.succeed && prevStepStart) {\n const timeSpent = prettyMs(Date.now() - prevStepStart, {\n secondsDecimalDigits: 2,\n })\n this.currentProgress.text = `[100%] ${prevStep} (${timeSpent})`\n this.currentProgress.succeed()\n }\n\n this.currentProgress = spinner(`[0%] ${opts.step} (0.00s)`).start()\n\n if (!lengthComputable) {\n this.spinInterval = setInterval(() => {\n if (this.stepStart && this.currentProgress) {\n const timeSpent = prettyMs(Date.now() - this.stepStart, {\n secondsDecimalDigits: 2,\n })\n this.currentProgress.text = `${percent}${opts.step} (${timeSpent})`\n this.currentProgress.render()\n }\n }, 60)\n }\n }\n\n private printWarnings(warnings: Array<{message: string; type?: string; url?: string}>): void {\n const assetFails = warnings.filter((warn) => warn.type === 'asset')\n\n if (assetFails.length === 0) {\n return\n }\n\n this.warn(`Failed to import the following ${assetFails.length > 1 ? 'assets' : 'asset'}:`)\n\n for (const warning of assetFails) {\n if (warning.url) {\n this.warn(` ${warning.url}`)\n }\n }\n }\n}\n"],"names":["fs","path","Args","Flags","getProjectCliClient","SanityCommand","createRequester","spinner","sanityImport","prettyMs","promptForProject","getDatasetFlag","getProjectIdFlag","getAssetsBase","source","test","undefined","fileStats","statSync","sourceIsFolder","isDirectory","dirname","getUriStream","uri","request","middleware","promise","onlyBody","response","stream","url","body","err","Error","message","getPercentage","opts","total","percent","Math","floor","current","ImportDatasetCommand","args","string","description","required","targetDataset","examples","command","flags","boolean","default","integer","semantics","missing","exclusive","project","deprecated","to","hidden","replace","token","char","env","hiddenAliases","currentProgress","currentStep","spinInterval","stepStart","getStream","process","stdin","createReadStream","run","parse","allowAssetsInDifferentDataset","allowFailingAssets","allowReplacementCharacters","allowSystemDocuments","assetConcurrency","dataset","datasetFlag","replaceAssets","skipCrossDatasetReferences","projectId","getProjectId","deprecatedFlagName","fallback","targetDatasetArg","warn","error","exit","tokenString","operation","releasesOperation","client","apiVersion","assetsBase","importOptions","onProgress","bind","tag","targetProjectId","numDocs","warnings","timeSpent","Date","now","secondsDecimalDigits","clearInterval","text","succeed","log","printWarnings","fail","name","stack","lengthComputable","sameStep","step","render","prevStep","prevStepStart","start","setInterval","assetFails","filter","type","length","warning"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/datasets/list.ts"],"sourcesContent":["import {SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {listDatasetAliases, listDatasets} from '../../services/datasets.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst listDatasetDebug = subdebug('dataset:list')\n\nexport class ListDatasetCommand extends SanityCommand<typeof ListDatasetCommand> {\n static override description = 'List datasets of your project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'List datasets of your project',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --project-id abc123',\n description: 'List datasets for a specific project',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to list datasets for',\n semantics: 'override',\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:list']\n\n public async run(): Promise<void> {\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'read', permission: 'sanity.project.datasets'}],\n }),\n })\n\n const [datasets, aliases] = await Promise.allSettled([\n listDatasets(projectId),\n listDatasetAliases(projectId),\n ])\n\n if (datasets.status === 'rejected') {\n const err = datasets.reason as Error\n listDatasetDebug(`Error listing datasets for project ${projectId}`, err)\n this.error(`Dataset list retrieval failed: ${err.message}`, {exit: 1})\n }\n\n const datasetList = datasets.value\n if (datasetList.length === 0) {\n this.log('No datasets found for this project.')\n } else {\n for (const dataset of datasetList) {\n this.log(dataset.name)\n }\n }\n\n if (aliases.status === 'fulfilled' && aliases.value.length > 0) {\n for (const alias of aliases.value) {\n const targetDataset = alias.datasetName || '<unlinked>'\n this.log(`~${alias.name} -> ${targetDataset}`)\n }\n } else if (aliases.status === 'rejected') {\n listDatasetDebug(`Warning: Could not fetch aliases for project ${projectId}`, aliases.reason)\n }\n }\n}\n"],"names":["SanityCommand","subdebug","promptForProject","listDatasetAliases","listDatasets","getProjectIdFlag","listDatasetDebug","ListDatasetCommand","description","examples","command","flags","semantics","hiddenAliases","run","projectId","getProjectId","fallback","requiredPermissions","grant","permission","datasets","aliases","Promise","allSettled","status","err","reason","error","message","exit","datasetList","value","length","log","dataset","name","alias","targetDataset","datasetName"],"mappings":"AAAA,SAAQA,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAExD,SAAQC,gBAAgB,QAAO,oCAAmC;AAClE,SAAQC,kBAAkB,EAAEC,YAAY,QAAO,6BAA4B;AAC3E,SAAQC,gBAAgB,QAAO,4BAA2B;AAE1D,MAAMC,mBAAmBL,SAAS;AAElC,OAAO,MAAMM,2BAA2BP;IACtC,OAAgBQ,cAAc,gCAA+B;IAE7D,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTF,aAAa;QACf;QACA;YACEE,SAAS;YACTF,aAAa;QACf;KACD,CAAA;IAED,OAAgBG,QAAQ;QACtB,GAAGN,iBAAiB;YAClBG,aAAa;YACbI,WAAW;QACb,EAAE;IACJ,EAAC;IAED,OAAgBC,gBAA0B;QAAC;KAAe,CAAA;IAE1D,MAAaC,MAAqB;QAChC,MAAMC,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,UAAU,IACRf,iBAAiB;oBACfgB,qBAAqB;wBAAC;4BAACC,OAAO;4BAAQC,YAAY;wBAAyB;qBAAE;gBAC/E;QACJ;QAEA,MAAM,CAACC,UAAUC,QAAQ,GAAG,MAAMC,QAAQC,UAAU,CAAC;YACnDpB,aAAaW;YACbZ,mBAAmBY;SACpB;QAED,IAAIM,SAASI,MAAM,KAAK,YAAY;YAClC,MAAMC,MAAML,SAASM,MAAM;YAC3BrB,iBAAiB,CAAC,mCAAmC,EAAES,WAAW,EAAEW;YACpE,IAAI,CAACE,KAAK,CAAC,CAAC,+BAA+B,EAAEF,IAAIG,OAAO,EAAE,EAAE;gBAACC,MAAM;YAAC;QACtE;QAEA,MAAMC,cAAcV,SAASW,KAAK;QAClC,IAAID,YAAYE,MAAM,KAAK,GAAG;YAC5B,IAAI,CAACC,GAAG,CAAC;QACX,OAAO;YACL,KAAK,MAAMC,WAAWJ,YAAa;gBACjC,IAAI,CAACG,GAAG,CAACC,QAAQC,IAAI;YACvB;QACF;QAEA,IAAId,QAAQG,MAAM,KAAK,eAAeH,QAAQU,KAAK,CAACC,MAAM,GAAG,GAAG;YAC9D,KAAK,MAAMI,SAASf,QAAQU,KAAK,CAAE;gBACjC,MAAMM,gBAAgBD,MAAME,WAAW,IAAI;gBAC3C,IAAI,CAACL,GAAG,CAAC,CAAC,CAAC,EAAEG,MAAMD,IAAI,CAAC,IAAI,EAAEE,eAAe;YAC/C;QACF,OAAO,IAAIhB,QAAQG,MAAM,KAAK,YAAY;YACxCnB,iBAAiB,CAAC,6CAA6C,EAAES,WAAW,EAAEO,QAAQK,MAAM;QAC9F;IACF;AACF"}
|
|
@@ -25,6 +25,9 @@ export class DatasetVisibilityGetCommand extends SanityCommand {
|
|
|
25
25
|
semantics: 'override'
|
|
26
26
|
})
|
|
27
27
|
};
|
|
28
|
+
static hiddenAliases = [
|
|
29
|
+
'dataset:visibility:get'
|
|
30
|
+
];
|
|
28
31
|
async run() {
|
|
29
32
|
const { args } = await this.parse(DatasetVisibilityGetCommand);
|
|
30
33
|
const { dataset } = args;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/datasets/visibility/get.ts"],"sourcesContent":["import {Args} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {validateDatasetName} from '../../../actions/dataset/validateDatasetName.js'\nimport {promptForProject} from '../../../prompts/promptForProject.js'\nimport {listDatasets} from '../../../services/datasets.js'\nimport {getProjectIdFlag} from '../../../util/sharedFlags.js'\n\nconst getDebug = subdebug('dataset:visibility:get')\n\nexport class DatasetVisibilityGetCommand extends SanityCommand<typeof DatasetVisibilityGetCommand> {\n static override args = {\n dataset: Args.string({\n description: 'The name of the dataset to get visibility for',\n required: true,\n }),\n }\n\n static override description = 'Get the visibility of a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset',\n description: 'Check the visibility of a dataset',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to get dataset visibility for',\n semantics: 'override',\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:visibility:get']\n\n public async run(): Promise<void> {\n const {args} = await this.parse(DatasetVisibilityGetCommand)\n const {dataset} = args\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'read', permission: 'sanity.project.datasets'}],\n }),\n })\n\n const dsError = validateDatasetName(dataset)\n if (dsError) {\n this.error(dsError, {exit: 1})\n }\n\n let current\n try {\n const datasets = await listDatasets(projectId)\n current = datasets.find((curr: {name: string}) => curr.name === dataset)\n } catch (error) {\n getDebug(`Error listing datasets`, error)\n this.error(\n `Failed to list datasets: ${error instanceof Error ? error.message : String(error)}`,\n {exit: 1},\n )\n }\n\n if (!current) {\n this.error(`Dataset not found: ${dataset}`, {exit: 1})\n }\n\n this.log(current.aclMode)\n }\n}\n"],"names":["Args","SanityCommand","subdebug","validateDatasetName","promptForProject","listDatasets","getProjectIdFlag","getDebug","DatasetVisibilityGetCommand","args","dataset","string","description","required","examples","command","flags","semantics","hiddenAliases","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","dsError","error","exit","current","datasets","find","curr","name","Error","message","String","log","aclMode"],"mappings":"AAAA,SAAQA,IAAI,QAAO,cAAa;AAChC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAExD,SAAQC,mBAAmB,QAAO,kDAAiD;AACnF,SAAQC,gBAAgB,QAAO,uCAAsC;AACrE,SAAQC,YAAY,QAAO,gCAA+B;AAC1D,SAAQC,gBAAgB,QAAO,+BAA8B;AAE7D,MAAMC,WAAWL,SAAS;AAE1B,OAAO,MAAMM,oCAAoCP;IAC/C,OAAgBQ,OAAO;QACrBC,SAASV,KAAKW,MAAM,CAAC;YACnBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,kCAAiC;IAE/D,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtB,GAAGV,iBAAiB;YAClBM,aAAa;YACbK,WAAW;QACb,EAAE;IACJ,EAAC;IAED,OAAgBC,gBAA0B;QAAC;KAAyB,CAAA;IAEpE,MAAaC,MAAqB;QAChC,MAAM,EAACV,IAAI,EAAC,GAAG,MAAM,IAAI,CAACW,KAAK,CAACZ;QAChC,MAAM,EAACE,OAAO,EAAC,GAAGD;QAElB,MAAMY,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,UAAU,IACRnB,iBAAiB;oBACfoB,qBAAqB;wBAAC;4BAACC,OAAO;4BAAQC,YAAY;wBAAyB;qBAAE;gBAC/E;QACJ;QAEA,MAAMC,UAAUxB,oBAAoBO;QACpC,IAAIiB,SAAS;YACX,IAAI,CAACC,KAAK,CAACD,SAAS;gBAACE,MAAM;YAAC;QAC9B;QAEA,IAAIC;QACJ,IAAI;YACF,MAAMC,WAAW,MAAM1B,aAAagB;YACpCS,UAAUC,SAASC,IAAI,CAAC,CAACC,OAAyBA,KAAKC,IAAI,KAAKxB;QAClE,EAAE,OAAOkB,OAAO;YACdrB,SAAS,CAAC,sBAAsB,CAAC,EAAEqB;YACnC,IAAI,CAACA,KAAK,CACR,CAAC,yBAAyB,EAAEA,iBAAiBO,QAAQP,MAAMQ,OAAO,GAAGC,OAAOT,QAAQ,EACpF;gBAACC,MAAM;YAAC;QAEZ;QAEA,IAAI,CAACC,SAAS;YACZ,IAAI,CAACF,KAAK,CAAC,CAAC,mBAAmB,EAAElB,SAAS,EAAE;gBAACmB,MAAM;YAAC;QACtD;QAEA,IAAI,CAACS,GAAG,CAACR,QAAQS,OAAO;IAC1B;AACF"}
|
|
@@ -37,6 +37,9 @@ export class DatasetVisibilitySetCommand extends SanityCommand {
|
|
|
37
37
|
semantics: 'override'
|
|
38
38
|
})
|
|
39
39
|
};
|
|
40
|
+
static hiddenAliases = [
|
|
41
|
+
'dataset:visibility:set'
|
|
42
|
+
];
|
|
40
43
|
async run() {
|
|
41
44
|
const { args } = await this.parse(DatasetVisibilitySetCommand);
|
|
42
45
|
const { dataset, mode } = args;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/datasets/visibility/set.ts"],"sourcesContent":["import {Args} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {DatasetsResponse} from '@sanity/client'\n\nimport {validateDatasetName} from '../../../actions/dataset/validateDatasetName.js'\nimport {promptForProject} from '../../../prompts/promptForProject.js'\nimport {editDatasetAcl, listDatasets} from '../../../services/datasets.js'\nimport {getProjectIdFlag} from '../../../util/sharedFlags.js'\n\nconst setDatasetVisibilityDebug = subdebug('dataset:visibility:set')\n\nexport class DatasetVisibilitySetCommand extends SanityCommand<typeof DatasetVisibilitySetCommand> {\n static override args = {\n dataset: Args.string({\n description: 'The name of the dataset to set visibility for',\n required: true,\n }),\n mode: Args.string({\n description: 'The visibility mode to set',\n options: ['public', 'private'],\n required: true,\n }),\n }\n\n static override description = 'Set the visibility of a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset private',\n description: 'Make a dataset private',\n },\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset public',\n description: 'Make a dataset public',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to set dataset visibility for',\n semantics: 'override',\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:visibility:set']\n\n public async run(): Promise<void> {\n const {args} = await this.parse(DatasetVisibilitySetCommand)\n const {dataset, mode} = args\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [\n {grant: 'read', permission: 'sanity.project.datasets'},\n {grant: 'update', permission: 'sanity.project.datasets'},\n ],\n }),\n })\n\n const dsError = validateDatasetName(dataset)\n if (dsError) {\n this.error(dsError, {exit: 1})\n }\n\n let datasets: DatasetsResponse\n\n try {\n datasets = await listDatasets(projectId)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n setDatasetVisibilityDebug(`Failed to list datasets: ${message}`, error)\n this.error(`Failed to list datasets: ${message}`, {exit: 1})\n }\n\n const current = datasets.find((curr: {name: string}) => curr.name === dataset)\n\n if (!current) {\n this.error(`Dataset \"${dataset}\" not found`, {exit: 1})\n }\n\n if (current.aclMode === mode) {\n this.log(`Dataset already in \"${mode}\" mode`)\n return\n }\n\n if (mode === 'private') {\n this.log(\n 'Please note that while documents are private, assets (files and images) are still public',\n )\n }\n\n try {\n await editDatasetAcl({\n aclMode: mode as 'private' | 'public',\n datasetName: dataset,\n projectId,\n })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n setDatasetVisibilityDebug(`Failed to edit dataset: ${message}`, error)\n this.error(`Failed to edit dataset: ${message}`, {exit: 1})\n }\n this.log('Dataset visibility changed')\n }\n}\n"],"names":["Args","SanityCommand","subdebug","validateDatasetName","promptForProject","editDatasetAcl","listDatasets","getProjectIdFlag","setDatasetVisibilityDebug","DatasetVisibilitySetCommand","args","dataset","string","description","required","mode","options","examples","command","flags","semantics","hiddenAliases","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","dsError","error","exit","datasets","message","Error","String","current","find","curr","name","aclMode","log","datasetName"],"mappings":"AAAA,SAAQA,IAAI,QAAO,cAAa;AAChC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAGxD,SAAQC,mBAAmB,QAAO,kDAAiD;AACnF,SAAQC,gBAAgB,QAAO,uCAAsC;AACrE,SAAQC,cAAc,EAAEC,YAAY,QAAO,gCAA+B;AAC1E,SAAQC,gBAAgB,QAAO,+BAA8B;AAE7D,MAAMC,4BAA4BN,SAAS;AAE3C,OAAO,MAAMO,oCAAoCR;IAC/C,OAAgBS,OAAO;QACrBC,SAASX,KAAKY,MAAM,CAAC;YACnBC,aAAa;YACbC,UAAU;QACZ;QACAC,MAAMf,KAAKY,MAAM,CAAC;YAChBC,aAAa;YACbG,SAAS;gBAAC;gBAAU;aAAU;YAC9BF,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,kCAAiC;IAE/D,OAAgBI,WAAW;QACzB;YACEC,SAAS;YACTL,aAAa;QACf;QACA;YACEK,SAAS;YACTL,aAAa;QACf;KACD,CAAA;IAED,OAAgBM,QAAQ;QACtB,GAAGZ,iBAAiB;YAClBM,aAAa;YACbO,WAAW;QACb,EAAE;IACJ,EAAC;IAED,OAAgBC,gBAA0B;QAAC;KAAyB,CAAA;IAEpE,MAAaC,MAAqB;QAChC,MAAM,EAACZ,IAAI,EAAC,GAAG,MAAM,IAAI,CAACa,KAAK,CAACd;QAChC,MAAM,EAACE,OAAO,EAAEI,IAAI,EAAC,GAAGL;QAExB,MAAMc,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,UAAU,IACRtB,iBAAiB;oBACfuB,qBAAqB;wBACnB;4BAACC,OAAO;4BAAQC,YAAY;wBAAyB;wBACrD;4BAACD,OAAO;4BAAUC,YAAY;wBAAyB;qBACxD;gBACH;QACJ;QAEA,MAAMC,UAAU3B,oBAAoBQ;QACpC,IAAImB,SAAS;YACX,IAAI,CAACC,KAAK,CAACD,SAAS;gBAACE,MAAM;YAAC;QAC9B;QAEA,IAAIC;QAEJ,IAAI;YACFA,WAAW,MAAM3B,aAAakB;QAChC,EAAE,OAAOO,OAAO;YACd,MAAMG,UAAUH,iBAAiBI,QAAQJ,MAAMG,OAAO,GAAGE,OAAOL;YAChEvB,0BAA0B,CAAC,yBAAyB,EAAE0B,SAAS,EAAEH;YACjE,IAAI,CAACA,KAAK,CAAC,CAAC,yBAAyB,EAAEG,SAAS,EAAE;gBAACF,MAAM;YAAC;QAC5D;QAEA,MAAMK,UAAUJ,SAASK,IAAI,CAAC,CAACC,OAAyBA,KAAKC,IAAI,KAAK7B;QAEtE,IAAI,CAAC0B,SAAS;YACZ,IAAI,CAACN,KAAK,CAAC,CAAC,SAAS,EAAEpB,QAAQ,WAAW,CAAC,EAAE;gBAACqB,MAAM;YAAC;QACvD;QAEA,IAAIK,QAAQI,OAAO,KAAK1B,MAAM;YAC5B,IAAI,CAAC2B,GAAG,CAAC,CAAC,oBAAoB,EAAE3B,KAAK,MAAM,CAAC;YAC5C;QACF;QAEA,IAAIA,SAAS,WAAW;YACtB,IAAI,CAAC2B,GAAG,CACN;QAEJ;QAEA,IAAI;YACF,MAAMrC,eAAe;gBACnBoC,SAAS1B;gBACT4B,aAAahC;gBACba;YACF;QACF,EAAE,OAAOO,OAAO;YACd,MAAMG,UAAUH,iBAAiBI,QAAQJ,MAAMG,OAAO,GAAGE,OAAOL;YAChEvB,0BAA0B,CAAC,wBAAwB,EAAE0B,SAAS,EAAEH;YAChE,IAAI,CAACA,KAAK,CAAC,CAAC,wBAAwB,EAAEG,SAAS,EAAE;gBAACF,MAAM;YAAC;QAC3D;QACA,IAAI,CAACU,GAAG,CAAC;IACX;AACF"}
|
package/dist/commands/debug.js
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import { styleText } from 'node:util';
|
|
3
2
|
import { Flags } from '@oclif/core';
|
|
4
3
|
import { ProjectRootNotFoundError, SanityCommand } from '@sanity/cli-core';
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import { formatObject, printKeyValue } from '../actions/debug/formatters.js';
|
|
8
|
-
import { gatherDebugInfo } from '../actions/debug/gatherDebugInfo.js';
|
|
9
|
-
import { getGlobalConfigLocation } from '../actions/debug/getGlobalConfigLocation.js';
|
|
10
|
-
import { getDisplayName, getFormatters } from '../actions/versions/getFormatters.js';
|
|
4
|
+
import { gatherAuthInfo, gatherCliInfo, gatherProjectInfo, gatherResolvedWorkspaces, gatherStudioWorkspaces, gatherUserInfo } from '../actions/debug/gatherDebugInfo.js';
|
|
5
|
+
import { formatKeyValue, sectionHeader } from '../actions/debug/output.js';
|
|
11
6
|
export class Debug extends SanityCommand {
|
|
12
7
|
static description = 'Provides diagnostic info for Sanity Studio troubleshooting';
|
|
13
8
|
static examples = [
|
|
@@ -18,89 +13,209 @@ export class Debug extends SanityCommand {
|
|
|
18
13
|
secrets: Flags.boolean({
|
|
19
14
|
default: false,
|
|
20
15
|
description: 'Include API keys in output'
|
|
16
|
+
}),
|
|
17
|
+
verbose: Flags.boolean({
|
|
18
|
+
default: false,
|
|
19
|
+
description: 'Show full error details including stack traces'
|
|
21
20
|
})
|
|
22
21
|
};
|
|
23
22
|
async run() {
|
|
24
23
|
const { flags } = this;
|
|
24
|
+
let projectDirectory;
|
|
25
25
|
try {
|
|
26
|
-
|
|
26
|
+
const projectRoot = await this.getProjectRoot();
|
|
27
|
+
projectDirectory = projectRoot.directory;
|
|
28
|
+
} catch (err) {
|
|
29
|
+
if (!(err instanceof ProjectRootNotFoundError)) throw err;
|
|
30
|
+
}
|
|
31
|
+
// Try loading CLI config, capturing errors
|
|
32
|
+
let cliConfigLoad;
|
|
33
|
+
if (projectDirectory) {
|
|
27
34
|
try {
|
|
28
|
-
|
|
35
|
+
cliConfigLoad = {
|
|
36
|
+
value: await this.getCliConfig()
|
|
37
|
+
};
|
|
29
38
|
} catch (err) {
|
|
30
|
-
|
|
39
|
+
cliConfigLoad = {
|
|
40
|
+
error: err instanceof Error ? err : new Error(String(err))
|
|
41
|
+
};
|
|
31
42
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
Roles: project && 'userRoles' in project ? project.userRoles : undefined
|
|
48
|
-
});
|
|
43
|
+
}
|
|
44
|
+
const projectId = cliConfigLoad?.value?.api?.projectId;
|
|
45
|
+
// Gather project info once, shared between Project and Studio sections
|
|
46
|
+
const project = projectDirectory ? await gatherProjectInfo(projectDirectory) : undefined;
|
|
47
|
+
// Pre-load studio workspaces so we know if the config is valid
|
|
48
|
+
let studioLoad;
|
|
49
|
+
if (project?.studioConfigPath && projectDirectory) {
|
|
50
|
+
try {
|
|
51
|
+
studioLoad = {
|
|
52
|
+
value: await gatherStudioWorkspaces(projectDirectory)
|
|
53
|
+
};
|
|
54
|
+
} catch (err) {
|
|
55
|
+
studioLoad = {
|
|
56
|
+
error: err instanceof Error ? err : new Error(String(err))
|
|
57
|
+
};
|
|
49
58
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
}
|
|
60
|
+
// Section 1: User
|
|
61
|
+
const user = await this.printUserSection(projectId);
|
|
62
|
+
const userId = user instanceof Error ? undefined : user.id;
|
|
63
|
+
// Section 2: Authentication (only when logged in)
|
|
64
|
+
await this.printAuthSection(flags.secrets);
|
|
65
|
+
// Section 3: CLI
|
|
66
|
+
await this.printCliSection();
|
|
67
|
+
// Section 4: Project
|
|
68
|
+
this.printProjectSection(project, cliConfigLoad, studioLoad);
|
|
69
|
+
// Section 5: Studio (when studio config file exists)
|
|
70
|
+
if (projectDirectory && project?.studioConfigPath && studioLoad) {
|
|
71
|
+
await this.printStudioSection(projectDirectory, studioLoad, flags.verbose, projectId, userId);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async printAuthSection(includeSecrets) {
|
|
75
|
+
const auth = await gatherAuthInfo(includeSecrets);
|
|
76
|
+
if (!auth.hasToken) return;
|
|
77
|
+
this.log(sectionHeader('Authentication'));
|
|
78
|
+
const padTo = 10 // "Auth token" is the longest key
|
|
79
|
+
;
|
|
80
|
+
this.log(formatKeyValue('Auth token', auth.authToken, {
|
|
81
|
+
padTo
|
|
82
|
+
}));
|
|
83
|
+
this.log(formatKeyValue('User type', auth.userType, {
|
|
84
|
+
padTo
|
|
85
|
+
}));
|
|
86
|
+
if (!includeSecrets) {
|
|
87
|
+
this.log(' (run with --secrets to reveal token)');
|
|
88
|
+
}
|
|
89
|
+
this.log('');
|
|
90
|
+
}
|
|
91
|
+
async printCliSection() {
|
|
92
|
+
this.log(sectionHeader('CLI'));
|
|
93
|
+
try {
|
|
94
|
+
const cliInfo = await gatherCliInfo();
|
|
95
|
+
const padTo = 9 // "Installed" is the longest key
|
|
96
|
+
;
|
|
97
|
+
this.log(formatKeyValue('Version', cliInfo.version, {
|
|
98
|
+
padTo
|
|
99
|
+
}));
|
|
100
|
+
this.log(formatKeyValue('Installed', cliInfo.installContext, {
|
|
101
|
+
padTo
|
|
102
|
+
}));
|
|
103
|
+
} catch {
|
|
104
|
+
this.log(` ${styleText('red', 'Unable to determine CLI version')}`);
|
|
105
|
+
}
|
|
106
|
+
this.log('');
|
|
107
|
+
}
|
|
108
|
+
printConfigStatus(label, fileName, loadResult, padTo) {
|
|
109
|
+
if (!fileName) {
|
|
110
|
+
this.log(formatKeyValue(label, `${styleText('red', '\u274C')} not found`, {
|
|
111
|
+
padTo
|
|
112
|
+
}));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (loadResult?.error) {
|
|
116
|
+
this.log(formatKeyValue(label, `${styleText('yellow', '\u26A0\uFE0F')} ${styleText('yellow', fileName)} (has errors)`, {
|
|
117
|
+
padTo
|
|
118
|
+
}));
|
|
119
|
+
} else {
|
|
120
|
+
this.log(formatKeyValue(label, `${styleText('green', '\u2705')} ${styleText('yellow', fileName)}`, {
|
|
121
|
+
padTo
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
printProjectSection(project, cliConfigLoad, studioLoad) {
|
|
126
|
+
this.log(sectionHeader('Project'));
|
|
127
|
+
if (!project) {
|
|
128
|
+
this.log(' No project found\n');
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const padTo = 14;
|
|
132
|
+
this.log(formatKeyValue('Root path', project.rootPath, {
|
|
133
|
+
padTo
|
|
134
|
+
}));
|
|
135
|
+
this.printConfigStatus('CLI config', project.cliConfigPath, cliConfigLoad, padTo);
|
|
136
|
+
this.printConfigStatus('Studio config', project.studioConfigPath, studioLoad, padTo);
|
|
137
|
+
this.log('');
|
|
138
|
+
}
|
|
139
|
+
async printStudioSection(projectDirectory, studioLoad, verbose, projectId, userId) {
|
|
140
|
+
this.log(sectionHeader('Studio'));
|
|
141
|
+
if (studioLoad.error) {
|
|
142
|
+
this.log(` ${styleText('red', 'Failed to load studio configuration:')}`);
|
|
143
|
+
if (verbose) {
|
|
144
|
+
this.log(` ${studioLoad.error.stack ?? studioLoad.error.message}\n`);
|
|
145
|
+
} else {
|
|
146
|
+
this.log(` ${truncate(studioLoad.error.message)}\n`);
|
|
58
147
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
this.log(' Workspaces:');
|
|
151
|
+
for (const ws of studioLoad.value){
|
|
152
|
+
const label = ws.name ?? 'default';
|
|
153
|
+
this.log(` ${label}`);
|
|
154
|
+
this.log(formatKeyValue('Project ID', ws.projectId, {
|
|
155
|
+
indent: 6,
|
|
156
|
+
padTo: 10
|
|
157
|
+
}));
|
|
158
|
+
this.log(formatKeyValue('Dataset', ws.dataset, {
|
|
159
|
+
indent: 6,
|
|
160
|
+
padTo: 10
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
// Full resolution: try to resolve plugins and get roles
|
|
164
|
+
try {
|
|
165
|
+
const resolved = await gatherResolvedWorkspaces(projectDirectory, userId);
|
|
166
|
+
this.log('');
|
|
167
|
+
this.log(' Resolved configuration:');
|
|
168
|
+
for (const ws of resolved){
|
|
169
|
+
this.log(` ${ws.name} (${ws.title})`);
|
|
170
|
+
if (ws.roles.length > 0) {
|
|
171
|
+
this.log(formatKeyValue('Roles', ws.roles, {
|
|
172
|
+
indent: 6,
|
|
173
|
+
padTo: 5
|
|
174
|
+
}));
|
|
68
175
|
}
|
|
69
176
|
}
|
|
70
|
-
|
|
71
|
-
this.log(
|
|
72
|
-
|
|
73
|
-
'
|
|
74
|
-
'
|
|
75
|
-
]);
|
|
76
|
-
this.log(` ${formatObject(globalCfg).replaceAll('\n', '\n ')}\n`);
|
|
77
|
-
// Project configuration (projectDir/sanity.cli.ts)
|
|
78
|
-
if (!projectRoot) {
|
|
79
|
-
this.log('No project found\n');
|
|
80
|
-
} else if (projectConfig instanceof Error) {
|
|
81
|
-
this.log(`CLI configuration error: ${styleText('red', projectConfig.message)}\n`);
|
|
82
|
-
} else if (projectConfig) {
|
|
83
|
-
const configLocation = ` (${styleText('yellow', path.relative(process.cwd(), projectRoot.path))})`;
|
|
84
|
-
this.log(`Project config${configLocation}:`);
|
|
85
|
-
this.log(` ${formatObject(projectConfig).replaceAll('\n', '\n ')}`);
|
|
177
|
+
} catch (err) {
|
|
178
|
+
this.log('');
|
|
179
|
+
if (verbose && err instanceof Error && err.stack) {
|
|
180
|
+
this.log(` ${styleText('dim', 'Unable to resolve full studio configuration:')}`);
|
|
181
|
+
this.log(` ${styleText('dim', err.stack)}`);
|
|
86
182
|
} else {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// Print installed package versions
|
|
90
|
-
if (versions) {
|
|
91
|
-
this.log('\nPackage versions:');
|
|
92
|
-
const { formatName, versionLength } = getFormatters(versions);
|
|
93
|
-
for (const mod of versions){
|
|
94
|
-
const version = padStart(mod.installed || '<missing>', versionLength);
|
|
95
|
-
const latest = mod.installed === mod.latest ? styleText('green', '(up to date)') : `(latest: ${styleText('yellow', mod.latest)})`;
|
|
96
|
-
this.log(`${formatName(getDisplayName(mod))} ${version} ${latest}`);
|
|
97
|
-
}
|
|
98
|
-
this.log('');
|
|
183
|
+
const reason = truncate(err instanceof Error ? err.message : String(err));
|
|
184
|
+
this.log(` ${styleText('dim', `(unable to resolve full studio configuration: ${reason})`)}`);
|
|
99
185
|
}
|
|
100
|
-
} catch (error) {
|
|
101
|
-
this.error(`Failed to gather debug information: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
102
186
|
}
|
|
187
|
+
this.log('');
|
|
103
188
|
}
|
|
189
|
+
async printUserSection(projectId) {
|
|
190
|
+
this.log(`\n${sectionHeader('User')}`);
|
|
191
|
+
const user = await gatherUserInfo(projectId);
|
|
192
|
+
if (user instanceof Error) {
|
|
193
|
+
this.log(` ${user.message}\n`);
|
|
194
|
+
return user;
|
|
195
|
+
}
|
|
196
|
+
const padTo = 8 // "Provider" is the longest key
|
|
197
|
+
;
|
|
198
|
+
this.log(formatKeyValue('Name', user.name, {
|
|
199
|
+
padTo
|
|
200
|
+
}));
|
|
201
|
+
this.log(formatKeyValue('Email', user.email, {
|
|
202
|
+
padTo
|
|
203
|
+
}));
|
|
204
|
+
this.log(formatKeyValue('ID', user.id, {
|
|
205
|
+
padTo
|
|
206
|
+
}));
|
|
207
|
+
this.log(formatKeyValue('Provider', user.provider, {
|
|
208
|
+
padTo
|
|
209
|
+
}));
|
|
210
|
+
this.log('');
|
|
211
|
+
return user;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const MAX_ERROR_LENGTH = 200;
|
|
215
|
+
function truncate(str) {
|
|
216
|
+
const collapsed = str.replaceAll(/\s*\n\s*/g, ' ').trim();
|
|
217
|
+
if (collapsed.length <= MAX_ERROR_LENGTH) return collapsed;
|
|
218
|
+
return `${collapsed.slice(0, MAX_ERROR_LENGTH)}...`;
|
|
104
219
|
}
|
|
105
220
|
|
|
106
221
|
//# sourceMappingURL=debug.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/commands/debug.ts"],"sourcesContent":["import path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Flags} from '@oclif/core'\nimport {ProjectRootNotFoundError, SanityCommand} from '@sanity/cli-core'\nimport omit from 'lodash-es/omit.js'\nimport padStart from 'lodash-es/padStart.js'\n\nimport {formatObject, printKeyValue} from '../actions/debug/formatters.js'\nimport {gatherDebugInfo} from '../actions/debug/gatherDebugInfo.js'\nimport {getGlobalConfigLocation} from '../actions/debug/getGlobalConfigLocation.js'\nimport {getDisplayName, getFormatters} from '../actions/versions/getFormatters.js'\n\nexport class Debug extends SanityCommand<typeof Debug> {\n static override description = 'Provides diagnostic info for Sanity Studio troubleshooting'\n\n static override examples = [\n '<%= config.bin %> <%= command.id %>',\n '<%= config.bin %> <%= command.id %> --secrets',\n ]\n\n static override flags = {\n secrets: Flags.boolean({\n default: false,\n description: 'Include API keys in output',\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = this\n\n try {\n let projectRoot\n try {\n projectRoot = await this.getProjectRoot()\n } catch (err) {\n if (!(err instanceof ProjectRootNotFoundError)) throw err\n }\n\n const cliConfig = projectRoot ? await this.getCliConfig() : undefined\n\n const {auth, globalConfig, project, projectConfig, user, versions} = await gatherDebugInfo({\n cliConfig,\n includeSecrets: flags.secrets,\n projectRoot,\n })\n\n this.output.log('\\nUser:')\n if (user instanceof Error) {\n this.log(` ${styleText('red', user.message)}\\n`)\n } else if (user) {\n printKeyValue({\n ID: user.id,\n Name: user.name,\n // eslint-disable-next-line perfectionist/sort-objects\n Email: user.email,\n Roles: project && 'userRoles' in project ? project.userRoles : undefined,\n })\n }\n\n // Project info (API-based)\n if (project && 'id' in project) {\n this.log('Project:')\n printKeyValue({\n ID: project.id,\n // eslint-disable-next-line perfectionist/sort-objects\n 'Display name': project.displayName,\n })\n }\n\n // Auth info\n if (auth.hasToken) {\n this.log('Authentication:')\n printKeyValue({\n 'Auth token': flags.secrets ? auth.authToken : `<redacted>`,\n 'User type': globalConfig.authType || 'normal',\n })\n\n if (!flags.secrets) {\n this.log(' (run with --secrets to reveal token)\\n')\n }\n }\n\n // Global configuration (user home dir config file)\n this.log(`Global config (${styleText('yellow', getGlobalConfigLocation())}):`)\n const globalCfg = omit(globalConfig, ['authType', 'authToken'])\n this.log(` ${formatObject(globalCfg).replaceAll('\\n', '\\n ')}\\n`)\n\n // Project configuration (projectDir/sanity.cli.ts)\n if (!projectRoot) {\n this.log('No project found\\n')\n } else if (projectConfig instanceof Error) {\n this.log(`CLI configuration error: ${styleText('red', projectConfig.message)}\\n`)\n } else if (projectConfig) {\n const configLocation = ` (${styleText('yellow', path.relative(process.cwd(), projectRoot.path))})`\n\n this.log(`Project config${configLocation}:`)\n this.log(` ${formatObject(projectConfig).replaceAll('\\n', '\\n ')}`)\n } else {\n this.log('No CLI configuration file found\\n')\n }\n\n // Print installed package versions\n if (versions) {\n this.log('\\nPackage versions:')\n\n const {formatName, versionLength} = getFormatters(versions)\n for (const mod of versions) {\n const version = padStart(mod.installed || '<missing>', versionLength)\n const latest =\n mod.installed === mod.latest\n ? styleText('green', '(up to date)')\n : `(latest: ${styleText('yellow', mod.latest)})`\n\n this.log(`${formatName(getDisplayName(mod))} ${version} ${latest}`)\n }\n\n this.log('')\n }\n } catch (error) {\n this.error(\n `Failed to gather debug information: ${error instanceof Error ? error.message : 'Unknown error'}`,\n )\n }\n }\n}\n"],"names":["path","styleText","Flags","ProjectRootNotFoundError","SanityCommand","omit","padStart","formatObject","printKeyValue","gatherDebugInfo","getGlobalConfigLocation","getDisplayName","getFormatters","Debug","description","examples","flags","secrets","boolean","default","run","projectRoot","getProjectRoot","err","cliConfig","getCliConfig","undefined","auth","globalConfig","project","projectConfig","user","versions","includeSecrets","output","log","Error","message","ID","id","Name","name","Email","email","Roles","userRoles","displayName","hasToken","authToken","authType","globalCfg","replaceAll","configLocation","relative","process","cwd","formatName","versionLength","mod","version","installed","latest","error"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/commands/debug.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Flags} from '@oclif/core'\nimport {ProjectRootNotFoundError, SanityCommand} from '@sanity/cli-core'\n\nimport {\n gatherAuthInfo,\n gatherCliInfo,\n gatherProjectInfo,\n gatherResolvedWorkspaces,\n gatherStudioWorkspaces,\n gatherUserInfo,\n} from '../actions/debug/gatherDebugInfo.js'\nimport {formatKeyValue, sectionHeader} from '../actions/debug/output.js'\nimport {type StudioWorkspace, type UserInfo} from '../actions/debug/types.js'\n\ntype ConfigLoadResult<T> = {error: Error; value?: never} | {error?: never; value: T}\n\nexport class Debug extends SanityCommand<typeof Debug> {\n static override description = 'Provides diagnostic info for Sanity Studio troubleshooting'\n\n static override examples = [\n '<%= config.bin %> <%= command.id %>',\n '<%= config.bin %> <%= command.id %> --secrets',\n ]\n\n static override flags = {\n secrets: Flags.boolean({\n default: false,\n description: 'Include API keys in output',\n }),\n verbose: Flags.boolean({\n default: false,\n description: 'Show full error details including stack traces',\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = this\n\n let projectDirectory: string | undefined\n try {\n const projectRoot = await this.getProjectRoot()\n projectDirectory = projectRoot.directory\n } catch (err) {\n if (!(err instanceof ProjectRootNotFoundError)) throw err\n }\n\n // Try loading CLI config, capturing errors\n let cliConfigLoad: ConfigLoadResult<Awaited<ReturnType<typeof this.getCliConfig>>> | undefined\n if (projectDirectory) {\n try {\n cliConfigLoad = {value: await this.getCliConfig()}\n } catch (err) {\n cliConfigLoad = {error: err instanceof Error ? err : new Error(String(err))}\n }\n }\n\n const projectId = cliConfigLoad?.value?.api?.projectId\n\n // Gather project info once, shared between Project and Studio sections\n const project = projectDirectory ? await gatherProjectInfo(projectDirectory) : undefined\n\n // Pre-load studio workspaces so we know if the config is valid\n let studioLoad: ConfigLoadResult<StudioWorkspace[]> | undefined\n if (project?.studioConfigPath && projectDirectory) {\n try {\n studioLoad = {value: await gatherStudioWorkspaces(projectDirectory)}\n } catch (err) {\n studioLoad = {error: err instanceof Error ? err : new Error(String(err))}\n }\n }\n\n // Section 1: User\n const user = await this.printUserSection(projectId)\n const userId = user instanceof Error ? undefined : user.id\n\n // Section 2: Authentication (only when logged in)\n await this.printAuthSection(flags.secrets)\n\n // Section 3: CLI\n await this.printCliSection()\n\n // Section 4: Project\n this.printProjectSection(project, cliConfigLoad, studioLoad)\n\n // Section 5: Studio (when studio config file exists)\n if (projectDirectory && project?.studioConfigPath && studioLoad) {\n await this.printStudioSection(projectDirectory, studioLoad, flags.verbose, projectId, userId)\n }\n }\n\n private async printAuthSection(includeSecrets: boolean): Promise<void> {\n const auth = await gatherAuthInfo(includeSecrets)\n if (!auth.hasToken) return\n\n this.log(sectionHeader('Authentication'))\n const padTo = 10 // \"Auth token\" is the longest key\n this.log(formatKeyValue('Auth token', auth.authToken, {padTo}))\n this.log(formatKeyValue('User type', auth.userType, {padTo}))\n\n if (!includeSecrets) {\n this.log(' (run with --secrets to reveal token)')\n }\n this.log('')\n }\n\n private async printCliSection(): Promise<void> {\n this.log(sectionHeader('CLI'))\n\n try {\n const cliInfo = await gatherCliInfo()\n const padTo = 9 // \"Installed\" is the longest key\n this.log(formatKeyValue('Version', cliInfo.version, {padTo}))\n this.log(formatKeyValue('Installed', cliInfo.installContext, {padTo}))\n } catch {\n this.log(` ${styleText('red', 'Unable to determine CLI version')}`)\n }\n this.log('')\n }\n\n private printConfigStatus(\n label: string,\n fileName: string | undefined,\n loadResult: ConfigLoadResult<unknown> | undefined,\n padTo: number,\n ): void {\n if (!fileName) {\n this.log(formatKeyValue(label, `${styleText('red', '\\u274C')} not found`, {padTo}))\n return\n }\n\n if (loadResult?.error) {\n this.log(\n formatKeyValue(\n label,\n `${styleText('yellow', '\\u26A0\\uFE0F')} ${styleText('yellow', fileName)} (has errors)`,\n {padTo},\n ),\n )\n } else {\n this.log(\n formatKeyValue(label, `${styleText('green', '\\u2705')} ${styleText('yellow', fileName)}`, {\n padTo,\n }),\n )\n }\n }\n\n private printProjectSection(\n project: Awaited<ReturnType<typeof gatherProjectInfo>>,\n cliConfigLoad: ConfigLoadResult<unknown> | undefined,\n studioLoad: ConfigLoadResult<unknown> | undefined,\n ): void {\n this.log(sectionHeader('Project'))\n\n if (!project) {\n this.log(' No project found\\n')\n return\n }\n\n const padTo = 14\n this.log(formatKeyValue('Root path', project.rootPath, {padTo}))\n this.printConfigStatus('CLI config', project.cliConfigPath, cliConfigLoad, padTo)\n this.printConfigStatus('Studio config', project.studioConfigPath, studioLoad, padTo)\n this.log('')\n }\n\n private async printStudioSection(\n projectDirectory: string,\n studioLoad: ConfigLoadResult<StudioWorkspace[]>,\n verbose: boolean,\n projectId: string | undefined,\n userId: string | undefined,\n ): Promise<void> {\n this.log(sectionHeader('Studio'))\n\n if (studioLoad.error) {\n this.log(` ${styleText('red', 'Failed to load studio configuration:')}`)\n if (verbose) {\n this.log(` ${studioLoad.error.stack ?? studioLoad.error.message}\\n`)\n } else {\n this.log(` ${truncate(studioLoad.error.message)}\\n`)\n }\n return\n }\n\n this.log(' Workspaces:')\n for (const ws of studioLoad.value) {\n const label = ws.name ?? 'default'\n this.log(` ${label}`)\n this.log(formatKeyValue('Project ID', ws.projectId, {indent: 6, padTo: 10}))\n this.log(formatKeyValue('Dataset', ws.dataset, {indent: 6, padTo: 10}))\n }\n\n // Full resolution: try to resolve plugins and get roles\n try {\n const resolved = await gatherResolvedWorkspaces(projectDirectory, userId)\n\n this.log('')\n this.log(' Resolved configuration:')\n for (const ws of resolved) {\n this.log(` ${ws.name} (${ws.title})`)\n if (ws.roles.length > 0) {\n this.log(formatKeyValue('Roles', ws.roles, {indent: 6, padTo: 5}))\n }\n }\n } catch (err) {\n this.log('')\n if (verbose && err instanceof Error && err.stack) {\n this.log(` ${styleText('dim', 'Unable to resolve full studio configuration:')}`)\n this.log(` ${styleText('dim', err.stack)}`)\n } else {\n const reason = truncate(err instanceof Error ? err.message : String(err))\n this.log(\n ` ${styleText('dim', `(unable to resolve full studio configuration: ${reason})`)}`,\n )\n }\n }\n this.log('')\n }\n\n private async printUserSection(projectId: string | undefined): Promise<Error | UserInfo> {\n this.log(`\\n${sectionHeader('User')}`)\n\n const user = await gatherUserInfo(projectId)\n if (user instanceof Error) {\n this.log(` ${user.message}\\n`)\n return user\n }\n\n const padTo = 8 // \"Provider\" is the longest key\n this.log(formatKeyValue('Name', user.name, {padTo}))\n this.log(formatKeyValue('Email', user.email, {padTo}))\n this.log(formatKeyValue('ID', user.id, {padTo}))\n this.log(formatKeyValue('Provider', user.provider, {padTo}))\n this.log('')\n return user\n }\n}\n\nconst MAX_ERROR_LENGTH = 200\n\nfunction truncate(str: string): string {\n const collapsed = str.replaceAll(/\\s*\\n\\s*/g, ' ').trim()\n if (collapsed.length <= MAX_ERROR_LENGTH) return collapsed\n return `${collapsed.slice(0, MAX_ERROR_LENGTH)}...`\n}\n"],"names":["styleText","Flags","ProjectRootNotFoundError","SanityCommand","gatherAuthInfo","gatherCliInfo","gatherProjectInfo","gatherResolvedWorkspaces","gatherStudioWorkspaces","gatherUserInfo","formatKeyValue","sectionHeader","Debug","description","examples","flags","secrets","boolean","default","verbose","run","projectDirectory","projectRoot","getProjectRoot","directory","err","cliConfigLoad","value","getCliConfig","error","Error","String","projectId","api","project","undefined","studioLoad","studioConfigPath","user","printUserSection","userId","id","printAuthSection","printCliSection","printProjectSection","printStudioSection","includeSecrets","auth","hasToken","log","padTo","authToken","userType","cliInfo","version","installContext","printConfigStatus","label","fileName","loadResult","rootPath","cliConfigPath","stack","message","truncate","ws","name","indent","dataset","resolved","title","roles","length","reason","email","provider","MAX_ERROR_LENGTH","str","collapsed","replaceAll","trim","slice"],"mappings":"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"}
|
|
@@ -70,6 +70,9 @@ export class CreateDocumentCommand extends SanityCommand {
|
|
|
70
70
|
description: 'Write the documents whenever the target file or buffer changes'
|
|
71
71
|
})
|
|
72
72
|
};
|
|
73
|
+
static hiddenAliases = [
|
|
74
|
+
'document:create'
|
|
75
|
+
];
|
|
73
76
|
client;
|
|
74
77
|
async run() {
|
|
75
78
|
const { args, flags } = await this.parse(CreateDocumentCommand);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/documents/create.ts"],"sourcesContent":["import {randomUUID} from 'node:crypto'\nimport fs from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\n\nimport {Args, Flags} from '@oclif/core'\nimport {getProjectCliClient, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {type MultipleMutationResult, type Mutation} from '@sanity/client'\nimport {watch as chokidarWatch} from 'chokidar'\nimport {execa, execaSync} from 'execa'\nimport json5 from 'json5'\nimport isEqual from 'lodash-es/isEqual.js'\nimport isPlainObject from 'lodash-es/isPlainObject.js'\n\nimport {DOCUMENTS_API_VERSION} from '../../actions/documents/constants.js'\nimport {getEditor, registerUnlinkOnSigInt} from '../../actions/documents/editor.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {isIdentifiedSanityDocument, isSanityDocumentish} from '../../util/isSanityDocumentish.js'\nimport {getDatasetFlag, getProjectIdFlag} from '../../util/sharedFlags.js'\n\nexport type MutationOperationName = 'create' | 'createIfNotExists' | 'createOrReplace'\n\nconst createDocumentDebug = subdebug('documents:create')\n\nexport class CreateDocumentCommand extends SanityCommand<typeof CreateDocumentCommand> {\n static override args = {\n file: Args.string({\n description: 'JSON file to create document(s) from',\n required: false,\n }),\n }\n\n static override description = 'Create one or more documents'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> myDocument.json',\n description: 'Create the document specified in \"myDocument.json\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Open configured $EDITOR and create the specified document(s)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --id myDocId --replace',\n description:\n 'Fetch document with the ID \"myDocId\" and open configured $EDITOR with the current document content (if any). Replace document with the edited version when the editor closes',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --id myDocId --watch --replace --json5',\n description:\n 'Open configured $EDITOR and replace the document with the given content on each save. Use JSON5 file extension and parser for simplified syntax.',\n },\n {\n command: '<%= config.bin %> <%= command.id %> myDocument.json --project-id abc123',\n description: 'Create documents in a specific project',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to create document(s) in',\n semantics: 'override',\n }),\n ...getDatasetFlag({\n description: 'Dataset to create document(s) in',\n semantics: 'override',\n }),\n id: Flags.string({\n description:\n 'Specify a document ID to use. Will fetch remote document ID and populate editor.',\n }),\n json5: Flags.boolean({\n description: 'Use JSON5 file type to allow a \"simplified\" version of JSON',\n }),\n missing: Flags.boolean({\n description: \"On duplicate document IDs, don't modify the target document(s)\",\n }),\n replace: Flags.boolean({\n description:\n 'On duplicate document IDs, replace existing document with specified document(s)',\n }),\n watch: Flags.boolean({\n description: 'Write the documents whenever the target file or buffer changes',\n }),\n }\n\n private client!: Awaited<ReturnType<typeof getProjectCliClient>>\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(CreateDocumentCommand)\n const {file} = args\n const {dataset, id, json5: useJson5, missing, replace, watch} = flags\n\n const cliConfig = await this.tryGetCliConfig()\n\n const projectId = await this.getProjectId({fallback: () => promptForProject({})})\n\n if (!cliConfig.api?.dataset && !dataset) {\n this.error(\n 'No dataset specified. Either configure a dataset in sanity.cli.ts or use the --dataset flag',\n {exit: 1},\n )\n }\n\n const targetDataset = dataset || cliConfig.api?.dataset\n\n this.client = await getProjectCliClient({\n apiVersion: DOCUMENTS_API_VERSION,\n dataset: targetDataset,\n projectId,\n requireUser: true,\n })\n\n if (replace && missing) {\n this.error('Cannot use both --replace and --missing', {exit: 1})\n }\n\n if (id && file) {\n this.error('Cannot use --id when specifying a file path', {exit: 1})\n }\n\n let operation: MutationOperationName = 'create'\n if (replace || missing) {\n operation = replace ? 'createOrReplace' : 'createIfNotExists'\n }\n\n if (file) {\n try {\n const contentPath = path.resolve(process.cwd(), file)\n const content = json5.parse(await fs.readFile(contentPath, 'utf8'))\n const result = await this.writeDocuments(content, operation)\n this.log(this.getResultMessage(result, operation))\n return\n } catch (error) {\n const err = error as Error\n createDocumentDebug(`Error creating documents from file ${file}`, err)\n this.error(`Failed to create documents: ${err.message}`, {exit: 1})\n }\n }\n\n try {\n // Create a temporary file and use that as source, opening an editor on it\n const docId = id || randomUUID()\n const ext = useJson5 ? 'json5' : 'json'\n // Add UUID prefix to prevent predictable file names and potential conflicts\n const tmpFile = path.join(os.tmpdir(), 'sanity-cli', `${randomUUID()}-${docId}.${ext}`)\n const stringify = useJson5 ? json5.stringify : JSON.stringify\n const defaultValue = (id && (await this.client.getDocument(id))) || {\n _id: docId,\n _type: 'specify-me',\n }\n\n // Create temp directory with restricted permissions (owner only)\n const tempDir = path.join(os.tmpdir(), 'sanity-cli')\n await fs.mkdir(tempDir, {\n mode: 0o700, // rwx------ (owner read/write/execute only)\n recursive: true,\n })\n\n // Write file with restricted permissions (owner read/write only)\n await fs.writeFile(tmpFile, stringify(defaultValue, null, 2), {\n encoding: 'utf8',\n mode: 0o600, // rw------- (owner read/write only)\n })\n\n const editor = getEditor()\n const readAndPerformCreatesFromFile = this.readAndPerformCreatesFromFile.bind(this, operation)\n\n if (watch) {\n // If we're in watch mode, we want to run the creation on each change (if it validates)\n registerUnlinkOnSigInt(tmpFile)\n this.log(`Watch mode: ${tmpFile}`)\n this.log('Watch mode: Will write documents on each save.')\n this.log('Watch mode: Press Ctrl + C to cancel watch mode.')\n\n // Add race condition protection\n let isProcessing = false\n chokidarWatch(tmpFile).on('change', async () => {\n if (isProcessing) {\n return // Skip if already processing\n }\n isProcessing = true\n\n this.log('')\n try {\n await readAndPerformCreatesFromFile(tmpFile, defaultValue)\n } finally {\n isProcessing = false\n }\n })\n execa(editor.bin, [...editor.args, tmpFile], {stdio: 'inherit'})\n } else {\n // While in normal mode, we just want to wait for the editor to close and run the thing once\n execaSync(editor.bin, [...editor.args, tmpFile], {stdio: 'inherit'})\n await readAndPerformCreatesFromFile(tmpFile, defaultValue)\n await fs.unlink(tmpFile).catch(() => {})\n }\n } catch (error) {\n const err = error as Error\n createDocumentDebug('Error in editor workflow', err)\n this.error(`Failed to create documents: ${err.message}`, {exit: 1})\n }\n }\n\n private getErrorMessage(message: string, index: number, isSingle: boolean): string {\n return isSingle ? `Document ${message}` : `Document at index ${index} ${message}`\n }\n\n /**\n * Formats the result message for document operations\n */\n private getResultMessage(\n result: MultipleMutationResult,\n operation: MutationOperationName,\n ): string {\n const joiner = '\\n - '\n if (operation === 'createOrReplace') {\n return `Upserted:\\n - ${result.results.map((res) => res.id).join(joiner)}`\n }\n\n if (operation === 'create') {\n return `Created:\\n - ${result.results.map((res) => res.id).join(joiner)}`\n }\n\n // \"Missing\" (createIfNotExists)\n const created: string[] = []\n const skipped: string[] = []\n for (const res of result.results) {\n if (res.operation === 'update') {\n skipped.push(res.id)\n } else {\n created.push(res.id)\n }\n }\n\n if (created.length > 0 && skipped.length > 0) {\n return [\n `Created:\\n - ${created.join(joiner)}`,\n `Skipped (already exists):${joiner}${skipped.join(joiner)}`,\n ].join('\\n\\n')\n } else if (created.length > 0) {\n return `Created:\\n - ${created.join(joiner)}`\n }\n\n return `Skipped (already exists):\\n - ${skipped.join(joiner)}`\n }\n\n /**\n * Reads and processes documents from a file for creation\n */\n private async readAndPerformCreatesFromFile(\n operation: MutationOperationName,\n filePath: string,\n defaultValue: unknown,\n ): Promise<void> {\n let content\n try {\n content = json5.parse(await fs.readFile(filePath, 'utf8'))\n } catch (err) {\n const error = err as Error\n createDocumentDebug(`Failed to read input file ${filePath}`, error)\n this.log(`Failed to read input: ${error.message}`)\n return\n }\n\n if (isEqual(content, defaultValue)) {\n this.log('Value not modified, doing nothing.')\n this.log('Modify document to trigger creation.')\n return\n }\n\n try {\n const writeResult = await this.writeDocuments(content, operation)\n this.log(this.getResultMessage(writeResult, operation))\n } catch (err) {\n const error = err as Error\n createDocumentDebug(`Failed to write documents`, error)\n let errorMessage = `Failed to write documents: ${error.message}`\n if (error.message.includes('already exists')) {\n errorMessage += '\\nPerhaps you want to use `--replace` or `--missing`?'\n }\n this.error(errorMessage, {exit: 1})\n }\n }\n\n /**\n * Validates a document for Sanity requirements\n */\n private validateDocument(doc: unknown, index: number, arr: unknown[]): void {\n const isSingle = arr.length === 1\n\n if (!isPlainObject(doc)) {\n throw new Error(this.getErrorMessage('must be an object', index, isSingle))\n }\n\n if (!isSanityDocumentish(doc)) {\n throw new Error(\n this.getErrorMessage('must have a `_type` property of type string', index, isSingle),\n )\n }\n\n // Enhanced validations for Sanity document constraints\n const docObj = doc as Record<string, unknown>\n\n // Validate _type is non-empty\n const typeValue = docObj._type?.toString().trim()\n if (!typeValue) {\n throw new Error(this.getErrorMessage('_type cannot be empty', index, isSingle))\n }\n\n // Validate _type format (alphanumeric, underscore, hyphen, dot)\n if (!/^[a-zA-Z][a-zA-Z0-9_.-]*$/.test(typeValue)) {\n throw new Error(\n this.getErrorMessage(\n '_type must start with a letter and contain only alphanumeric characters, underscores, hyphens, and dots',\n index,\n isSingle,\n ),\n )\n }\n\n // Validate _id format if present\n if (docObj._id && typeof docObj._id === 'string') {\n const idValue = docObj._id.trim()\n if (!idValue) {\n throw new Error(this.getErrorMessage('_id cannot be empty', index, isSingle))\n }\n\n // Sanity document IDs can contain alphanumeric chars, hyphens, underscores, and dots\n if (!/^[a-zA-Z0-9_.-]+$/.test(idValue)) {\n throw new Error(\n this.getErrorMessage(\n '_id can only contain alphanumeric characters, underscores, hyphens, and dots',\n index,\n isSingle,\n ),\n )\n }\n\n // Check length constraints (Sanity has reasonable limits)\n if (idValue.length > 200) {\n throw new Error(\n this.getErrorMessage('_id cannot be longer than 200 characters', index, isSingle),\n )\n }\n }\n\n // Warn about reserved fields (these are managed by Sanity)\n const reservedFields = ['_rev', '_updatedAt', '_createdAt']\n for (const field of reservedFields) {\n if (field in docObj) {\n // Note: We don't throw an error here as these might be present in fetched documents\n // that are being re-uploaded, but we could add a debug warning\n createDocumentDebug(\n `Warning: Document ${index} contains reserved field '${field}' which will be ignored by Sanity`,\n )\n }\n }\n }\n\n /**\n * Writes documents to Sanity using the specified operation\n */\n private async writeDocuments(\n documents: {_id?: string; _type: string} | {_id?: string; _type: string}[],\n operation: MutationOperationName,\n ): Promise<MultipleMutationResult> {\n const docs = Array.isArray(documents) ? documents : [documents]\n if (docs.length === 0) {\n throw new Error('No documents provided')\n }\n\n const mutations = docs.map((doc, index): Mutation => {\n this.validateDocument(doc, index, docs)\n if (operation === 'create') {\n return {create: doc}\n }\n\n if (operation === 'createIfNotExists') {\n if (isIdentifiedSanityDocument(doc)) {\n return {createIfNotExists: doc}\n }\n\n throw new Error(`Missing required _id attribute for ${operation}`)\n }\n\n if (operation === 'createOrReplace') {\n if (isIdentifiedSanityDocument(doc)) {\n return {createOrReplace: doc}\n }\n\n throw new Error(`Missing required _id attribute for ${operation}`)\n }\n\n throw new Error(`Unsupported operation ${operation}`)\n })\n\n return this.client.transaction(mutations).commit()\n }\n}\n"],"names":["randomUUID","fs","os","path","Args","Flags","getProjectCliClient","SanityCommand","subdebug","watch","chokidarWatch","execa","execaSync","json5","isEqual","isPlainObject","DOCUMENTS_API_VERSION","getEditor","registerUnlinkOnSigInt","promptForProject","isIdentifiedSanityDocument","isSanityDocumentish","getDatasetFlag","getProjectIdFlag","createDocumentDebug","CreateDocumentCommand","args","file","string","description","required","examples","command","flags","semantics","id","boolean","missing","replace","client","run","parse","dataset","useJson5","cliConfig","tryGetCliConfig","projectId","getProjectId","fallback","api","error","exit","targetDataset","apiVersion","requireUser","operation","contentPath","resolve","process","cwd","content","readFile","result","writeDocuments","log","getResultMessage","err","message","docId","ext","tmpFile","join","tmpdir","stringify","JSON","defaultValue","getDocument","_id","_type","tempDir","mkdir","mode","recursive","writeFile","encoding","editor","readAndPerformCreatesFromFile","bind","isProcessing","on","bin","stdio","unlink","catch","getErrorMessage","index","isSingle","joiner","results","map","res","created","skipped","push","length","filePath","writeResult","errorMessage","includes","validateDocument","doc","arr","Error","docObj","typeValue","toString","trim","test","idValue","reservedFields","field","documents","docs","Array","isArray","mutations","create","createIfNotExists","createOrReplace","transaction","commit"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/documents/create.ts"],"sourcesContent":["import {randomUUID} from 'node:crypto'\nimport fs from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\n\nimport {Args, Flags} from '@oclif/core'\nimport {getProjectCliClient, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {type MultipleMutationResult, type Mutation} from '@sanity/client'\nimport {watch as chokidarWatch} from 'chokidar'\nimport {execa, execaSync} from 'execa'\nimport json5 from 'json5'\nimport isEqual from 'lodash-es/isEqual.js'\nimport isPlainObject from 'lodash-es/isPlainObject.js'\n\nimport {DOCUMENTS_API_VERSION} from '../../actions/documents/constants.js'\nimport {getEditor, registerUnlinkOnSigInt} from '../../actions/documents/editor.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {isIdentifiedSanityDocument, isSanityDocumentish} from '../../util/isSanityDocumentish.js'\nimport {getDatasetFlag, getProjectIdFlag} from '../../util/sharedFlags.js'\n\nexport type MutationOperationName = 'create' | 'createIfNotExists' | 'createOrReplace'\n\nconst createDocumentDebug = subdebug('documents:create')\n\nexport class CreateDocumentCommand extends SanityCommand<typeof CreateDocumentCommand> {\n static override args = {\n file: Args.string({\n description: 'JSON file to create document(s) from',\n required: false,\n }),\n }\n\n static override description = 'Create one or more documents'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> myDocument.json',\n description: 'Create the document specified in \"myDocument.json\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Open configured $EDITOR and create the specified document(s)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --id myDocId --replace',\n description:\n 'Fetch document with the ID \"myDocId\" and open configured $EDITOR with the current document content (if any). Replace document with the edited version when the editor closes',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --id myDocId --watch --replace --json5',\n description:\n 'Open configured $EDITOR and replace the document with the given content on each save. Use JSON5 file extension and parser for simplified syntax.',\n },\n {\n command: '<%= config.bin %> <%= command.id %> myDocument.json --project-id abc123',\n description: 'Create documents in a specific project',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to create document(s) in',\n semantics: 'override',\n }),\n ...getDatasetFlag({\n description: 'Dataset to create document(s) in',\n semantics: 'override',\n }),\n id: Flags.string({\n description:\n 'Specify a document ID to use. Will fetch remote document ID and populate editor.',\n }),\n json5: Flags.boolean({\n description: 'Use JSON5 file type to allow a \"simplified\" version of JSON',\n }),\n missing: Flags.boolean({\n description: \"On duplicate document IDs, don't modify the target document(s)\",\n }),\n replace: Flags.boolean({\n description:\n 'On duplicate document IDs, replace existing document with specified document(s)',\n }),\n watch: Flags.boolean({\n description: 'Write the documents whenever the target file or buffer changes',\n }),\n }\n\n static override hiddenAliases: string[] = ['document:create']\n\n private client!: Awaited<ReturnType<typeof getProjectCliClient>>\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(CreateDocumentCommand)\n const {file} = args\n const {dataset, id, json5: useJson5, missing, replace, watch} = flags\n\n const cliConfig = await this.tryGetCliConfig()\n\n const projectId = await this.getProjectId({fallback: () => promptForProject({})})\n\n if (!cliConfig.api?.dataset && !dataset) {\n this.error(\n 'No dataset specified. Either configure a dataset in sanity.cli.ts or use the --dataset flag',\n {exit: 1},\n )\n }\n\n const targetDataset = dataset || cliConfig.api?.dataset\n\n this.client = await getProjectCliClient({\n apiVersion: DOCUMENTS_API_VERSION,\n dataset: targetDataset,\n projectId,\n requireUser: true,\n })\n\n if (replace && missing) {\n this.error('Cannot use both --replace and --missing', {exit: 1})\n }\n\n if (id && file) {\n this.error('Cannot use --id when specifying a file path', {exit: 1})\n }\n\n let operation: MutationOperationName = 'create'\n if (replace || missing) {\n operation = replace ? 'createOrReplace' : 'createIfNotExists'\n }\n\n if (file) {\n try {\n const contentPath = path.resolve(process.cwd(), file)\n const content = json5.parse(await fs.readFile(contentPath, 'utf8'))\n const result = await this.writeDocuments(content, operation)\n this.log(this.getResultMessage(result, operation))\n return\n } catch (error) {\n const err = error as Error\n createDocumentDebug(`Error creating documents from file ${file}`, err)\n this.error(`Failed to create documents: ${err.message}`, {exit: 1})\n }\n }\n\n try {\n // Create a temporary file and use that as source, opening an editor on it\n const docId = id || randomUUID()\n const ext = useJson5 ? 'json5' : 'json'\n // Add UUID prefix to prevent predictable file names and potential conflicts\n const tmpFile = path.join(os.tmpdir(), 'sanity-cli', `${randomUUID()}-${docId}.${ext}`)\n const stringify = useJson5 ? json5.stringify : JSON.stringify\n const defaultValue = (id && (await this.client.getDocument(id))) || {\n _id: docId,\n _type: 'specify-me',\n }\n\n // Create temp directory with restricted permissions (owner only)\n const tempDir = path.join(os.tmpdir(), 'sanity-cli')\n await fs.mkdir(tempDir, {\n mode: 0o700, // rwx------ (owner read/write/execute only)\n recursive: true,\n })\n\n // Write file with restricted permissions (owner read/write only)\n await fs.writeFile(tmpFile, stringify(defaultValue, null, 2), {\n encoding: 'utf8',\n mode: 0o600, // rw------- (owner read/write only)\n })\n\n const editor = getEditor()\n const readAndPerformCreatesFromFile = this.readAndPerformCreatesFromFile.bind(this, operation)\n\n if (watch) {\n // If we're in watch mode, we want to run the creation on each change (if it validates)\n registerUnlinkOnSigInt(tmpFile)\n this.log(`Watch mode: ${tmpFile}`)\n this.log('Watch mode: Will write documents on each save.')\n this.log('Watch mode: Press Ctrl + C to cancel watch mode.')\n\n // Add race condition protection\n let isProcessing = false\n chokidarWatch(tmpFile).on('change', async () => {\n if (isProcessing) {\n return // Skip if already processing\n }\n isProcessing = true\n\n this.log('')\n try {\n await readAndPerformCreatesFromFile(tmpFile, defaultValue)\n } finally {\n isProcessing = false\n }\n })\n execa(editor.bin, [...editor.args, tmpFile], {stdio: 'inherit'})\n } else {\n // While in normal mode, we just want to wait for the editor to close and run the thing once\n execaSync(editor.bin, [...editor.args, tmpFile], {stdio: 'inherit'})\n await readAndPerformCreatesFromFile(tmpFile, defaultValue)\n await fs.unlink(tmpFile).catch(() => {})\n }\n } catch (error) {\n const err = error as Error\n createDocumentDebug('Error in editor workflow', err)\n this.error(`Failed to create documents: ${err.message}`, {exit: 1})\n }\n }\n\n private getErrorMessage(message: string, index: number, isSingle: boolean): string {\n return isSingle ? `Document ${message}` : `Document at index ${index} ${message}`\n }\n\n /**\n * Formats the result message for document operations\n */\n private getResultMessage(\n result: MultipleMutationResult,\n operation: MutationOperationName,\n ): string {\n const joiner = '\\n - '\n if (operation === 'createOrReplace') {\n return `Upserted:\\n - ${result.results.map((res) => res.id).join(joiner)}`\n }\n\n if (operation === 'create') {\n return `Created:\\n - ${result.results.map((res) => res.id).join(joiner)}`\n }\n\n // \"Missing\" (createIfNotExists)\n const created: string[] = []\n const skipped: string[] = []\n for (const res of result.results) {\n if (res.operation === 'update') {\n skipped.push(res.id)\n } else {\n created.push(res.id)\n }\n }\n\n if (created.length > 0 && skipped.length > 0) {\n return [\n `Created:\\n - ${created.join(joiner)}`,\n `Skipped (already exists):${joiner}${skipped.join(joiner)}`,\n ].join('\\n\\n')\n } else if (created.length > 0) {\n return `Created:\\n - ${created.join(joiner)}`\n }\n\n return `Skipped (already exists):\\n - ${skipped.join(joiner)}`\n }\n\n /**\n * Reads and processes documents from a file for creation\n */\n private async readAndPerformCreatesFromFile(\n operation: MutationOperationName,\n filePath: string,\n defaultValue: unknown,\n ): Promise<void> {\n let content\n try {\n content = json5.parse(await fs.readFile(filePath, 'utf8'))\n } catch (err) {\n const error = err as Error\n createDocumentDebug(`Failed to read input file ${filePath}`, error)\n this.log(`Failed to read input: ${error.message}`)\n return\n }\n\n if (isEqual(content, defaultValue)) {\n this.log('Value not modified, doing nothing.')\n this.log('Modify document to trigger creation.')\n return\n }\n\n try {\n const writeResult = await this.writeDocuments(content, operation)\n this.log(this.getResultMessage(writeResult, operation))\n } catch (err) {\n const error = err as Error\n createDocumentDebug(`Failed to write documents`, error)\n let errorMessage = `Failed to write documents: ${error.message}`\n if (error.message.includes('already exists')) {\n errorMessage += '\\nPerhaps you want to use `--replace` or `--missing`?'\n }\n this.error(errorMessage, {exit: 1})\n }\n }\n\n /**\n * Validates a document for Sanity requirements\n */\n private validateDocument(doc: unknown, index: number, arr: unknown[]): void {\n const isSingle = arr.length === 1\n\n if (!isPlainObject(doc)) {\n throw new Error(this.getErrorMessage('must be an object', index, isSingle))\n }\n\n if (!isSanityDocumentish(doc)) {\n throw new Error(\n this.getErrorMessage('must have a `_type` property of type string', index, isSingle),\n )\n }\n\n // Enhanced validations for Sanity document constraints\n const docObj = doc as Record<string, unknown>\n\n // Validate _type is non-empty\n const typeValue = docObj._type?.toString().trim()\n if (!typeValue) {\n throw new Error(this.getErrorMessage('_type cannot be empty', index, isSingle))\n }\n\n // Validate _type format (alphanumeric, underscore, hyphen, dot)\n if (!/^[a-zA-Z][a-zA-Z0-9_.-]*$/.test(typeValue)) {\n throw new Error(\n this.getErrorMessage(\n '_type must start with a letter and contain only alphanumeric characters, underscores, hyphens, and dots',\n index,\n isSingle,\n ),\n )\n }\n\n // Validate _id format if present\n if (docObj._id && typeof docObj._id === 'string') {\n const idValue = docObj._id.trim()\n if (!idValue) {\n throw new Error(this.getErrorMessage('_id cannot be empty', index, isSingle))\n }\n\n // Sanity document IDs can contain alphanumeric chars, hyphens, underscores, and dots\n if (!/^[a-zA-Z0-9_.-]+$/.test(idValue)) {\n throw new Error(\n this.getErrorMessage(\n '_id can only contain alphanumeric characters, underscores, hyphens, and dots',\n index,\n isSingle,\n ),\n )\n }\n\n // Check length constraints (Sanity has reasonable limits)\n if (idValue.length > 200) {\n throw new Error(\n this.getErrorMessage('_id cannot be longer than 200 characters', index, isSingle),\n )\n }\n }\n\n // Warn about reserved fields (these are managed by Sanity)\n const reservedFields = ['_rev', '_updatedAt', '_createdAt']\n for (const field of reservedFields) {\n if (field in docObj) {\n // Note: We don't throw an error here as these might be present in fetched documents\n // that are being re-uploaded, but we could add a debug warning\n createDocumentDebug(\n `Warning: Document ${index} contains reserved field '${field}' which will be ignored by Sanity`,\n )\n }\n }\n }\n\n /**\n * Writes documents to Sanity using the specified operation\n */\n private async writeDocuments(\n documents: {_id?: string; _type: string} | {_id?: string; _type: string}[],\n operation: MutationOperationName,\n ): Promise<MultipleMutationResult> {\n const docs = Array.isArray(documents) ? documents : [documents]\n if (docs.length === 0) {\n throw new Error('No documents provided')\n }\n\n const mutations = docs.map((doc, index): Mutation => {\n this.validateDocument(doc, index, docs)\n if (operation === 'create') {\n return {create: doc}\n }\n\n if (operation === 'createIfNotExists') {\n if (isIdentifiedSanityDocument(doc)) {\n return {createIfNotExists: doc}\n }\n\n throw new Error(`Missing required _id attribute for ${operation}`)\n }\n\n if (operation === 'createOrReplace') {\n if (isIdentifiedSanityDocument(doc)) {\n return {createOrReplace: doc}\n }\n\n throw new Error(`Missing required _id attribute for ${operation}`)\n }\n\n throw new Error(`Unsupported operation ${operation}`)\n })\n\n return this.client.transaction(mutations).commit()\n }\n}\n"],"names":["randomUUID","fs","os","path","Args","Flags","getProjectCliClient","SanityCommand","subdebug","watch","chokidarWatch","execa","execaSync","json5","isEqual","isPlainObject","DOCUMENTS_API_VERSION","getEditor","registerUnlinkOnSigInt","promptForProject","isIdentifiedSanityDocument","isSanityDocumentish","getDatasetFlag","getProjectIdFlag","createDocumentDebug","CreateDocumentCommand","args","file","string","description","required","examples","command","flags","semantics","id","boolean","missing","replace","hiddenAliases","client","run","parse","dataset","useJson5","cliConfig","tryGetCliConfig","projectId","getProjectId","fallback","api","error","exit","targetDataset","apiVersion","requireUser","operation","contentPath","resolve","process","cwd","content","readFile","result","writeDocuments","log","getResultMessage","err","message","docId","ext","tmpFile","join","tmpdir","stringify","JSON","defaultValue","getDocument","_id","_type","tempDir","mkdir","mode","recursive","writeFile","encoding","editor","readAndPerformCreatesFromFile","bind","isProcessing","on","bin","stdio","unlink","catch","getErrorMessage","index","isSingle","joiner","results","map","res","created","skipped","push","length","filePath","writeResult","errorMessage","includes","validateDocument","doc","arr","Error","docObj","typeValue","toString","trim","test","idValue","reservedFields","field","documents","docs","Array","isArray","mutations","create","createIfNotExists","createOrReplace","transaction","commit"],"mappings":"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"}
|