@sanity/cli 8.0.2 → 8.1.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.
Files changed (66) hide show
  1. package/README.md +4 -4
  2. package/dist/SanityHelp.js.map +1 -1
  3. package/dist/actions/backup/assertDatasetExist.js +2 -1
  4. package/dist/actions/backup/assertDatasetExist.js.map +1 -1
  5. package/dist/actions/build/buildStudio.js +3 -2
  6. package/dist/actions/build/buildStudio.js.map +1 -1
  7. package/dist/actions/build/eventListenerFactory.js +7 -6
  8. package/dist/actions/build/eventListenerFactory.js.map +1 -1
  9. package/dist/actions/build/shouldAutoUpdate.js +2 -1
  10. package/dist/actions/build/shouldAutoUpdate.js.map +1 -1
  11. package/dist/actions/cors/filterAndValidateOrigin.js +3 -2
  12. package/dist/actions/cors/filterAndValidateOrigin.js.map +1 -1
  13. package/dist/actions/deploy/createUserApplication.js +2 -1
  14. package/dist/actions/deploy/createUserApplication.js.map +1 -1
  15. package/dist/actions/deploy/deployRunner.js +3 -2
  16. package/dist/actions/deploy/deployRunner.js.map +1 -1
  17. package/dist/actions/deploy/deployStudio.js +3 -3
  18. package/dist/actions/deploy/deployStudio.js.map +1 -1
  19. package/dist/actions/deploy/findUserApplication.js +8 -7
  20. package/dist/actions/deploy/findUserApplication.js.map +1 -1
  21. package/dist/actions/dev/servers/startAppDevServer.js +2 -1
  22. package/dist/actions/dev/servers/startAppDevServer.js.map +1 -1
  23. package/dist/actions/dev/servers/startStudioDevServer.js +3 -3
  24. package/dist/actions/dev/servers/startStudioDevServer.js.map +1 -1
  25. package/dist/actions/documents/validate.js +5 -2
  26. package/dist/actions/documents/validate.js.map +1 -1
  27. package/dist/actions/init/env/createOrAppendEnvVars.js +2 -1
  28. package/dist/actions/init/env/createOrAppendEnvVars.js.map +1 -1
  29. package/dist/actions/init/env/parseAndUpdateEnvVars.js +2 -2
  30. package/dist/actions/init/env/parseAndUpdateEnvVars.js.map +1 -1
  31. package/dist/actions/init/sdkAppDependencies.js +2 -2
  32. package/dist/actions/init/sdkAppDependencies.js.map +1 -1
  33. package/dist/actions/init/studioDependencies.js +2 -2
  34. package/dist/actions/init/studioDependencies.js.map +1 -1
  35. package/dist/actions/scaffold/scaffoldProject.js +11 -6
  36. package/dist/actions/scaffold/scaffoldProject.js.map +1 -1
  37. package/dist/actions/schema/extractSchema.js +2 -2
  38. package/dist/actions/schema/extractSchema.js.map +1 -1
  39. package/dist/actions/schema/extractSchemaWatcher.js +2 -1
  40. package/dist/actions/schema/extractSchemaWatcher.js.map +1 -1
  41. package/dist/actions/undeploy/runUndeploy.js +2 -2
  42. package/dist/actions/undeploy/runUndeploy.js.map +1 -1
  43. package/dist/commands/backups/list.js +5 -8
  44. package/dist/commands/backups/list.js.map +1 -1
  45. package/dist/commands/datasets/copy.js +5 -7
  46. package/dist/commands/datasets/copy.js.map +1 -1
  47. package/dist/commands/docs/search.js +2 -2
  48. package/dist/commands/docs/search.js.map +1 -1
  49. package/dist/commands/mcp/configure.js +2 -2
  50. package/dist/commands/mcp/configure.js.map +1 -1
  51. package/dist/commands/new.js +1 -2
  52. package/dist/commands/new.js.map +1 -1
  53. package/dist/commands/typegen/generate.js +6 -6
  54. package/dist/commands/typegen/generate.js.map +1 -1
  55. package/dist/services/assets.js +1 -1
  56. package/dist/services/assets.js.map +1 -1
  57. package/dist/services/mintProject.js +27 -3
  58. package/dist/services/mintProject.js.map +1 -1
  59. package/dist/util/appId.js +2 -1
  60. package/dist/util/appId.js.map +1 -1
  61. package/dist/util/dates.js +125 -0
  62. package/dist/util/dates.js.map +1 -0
  63. package/dist/util/getCliVersion.js +1 -11
  64. package/dist/util/getCliVersion.js.map +1 -1
  65. package/oclif.manifest.json +2 -2
  66. package/package.json +5 -8
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/datasets/copy.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exit} from '@oclif/core/errors'\nimport {exitCodes} from '@sanity/cli-core'\nimport {subdebug} from '@sanity/cli-core/debug'\nimport {getCliExecutionContext} from '@sanity/cli-core/executionContext'\nimport {SanityCommand} from '@sanity/cli-core/SanityCommand'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {formatDistance} from 'date-fns/formatDistance'\nimport {formatDistanceToNow} from 'date-fns/formatDistanceToNow'\nimport {parseISO} from 'date-fns/parseISO'\n\nimport {validateDatasetName} from '../../actions/dataset/validateDatasetName.js'\nimport {promptForDataset} from '../../prompts/promptForDataset.js'\nimport {promptForDatasetName} from '../../prompts/promptForDatasetName.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {\n copyDataset,\n type CopyJobProgressEvent,\n type DatasetCopyJob,\n followCopyJobProgress,\n listDatasetCopyJobs,\n listDatasets,\n} from '../../services/datasets.js'\nimport {formatCliErrorMessages} from '../../util/formatCliErrorMessages.js'\nimport {Table} from '../../util/responsiveTable.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst copyDatasetDebug = subdebug('dataset:copy')\n\nexport class CopyDatasetCommand extends SanityCommand<typeof CopyDatasetCommand> {\n static override args = {\n source: Args.string({\n description: 'Name of the dataset to copy from',\n required: false,\n }),\n target: Args.string({\n description: 'Name of the dataset to copy to',\n required: false,\n }),\n }\n\n static override description = 'Copy a dataset or manage copy jobs'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively copy a dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> source-dataset',\n description: 'Copy from source-dataset (prompts for target)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> source-dataset target-dataset',\n description: 'Copy from source-dataset to target-dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --skip-history source target',\n description: 'Copy without preserving document history (faster for large datasets)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --skip-content-releases source target',\n description: 'Copy without content release documents',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --detach source target',\n description: 'Start copy job without waiting for completion',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --attach <job-id>',\n description: 'Attach to a running copy job to follow progress',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --list',\n description: 'List all dataset copy jobs',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --list --offset 2 --limit 10',\n description: 'List copy jobs with pagination',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to copy dataset in',\n semantics: 'override',\n }),\n attach: Flags.string({\n description: 'Attach to the running copy process to show progress',\n exclusive: ['list', 'detach', 'skip-history'],\n required: false,\n }),\n detach: Flags.boolean({\n description: 'Start the copy without waiting for it to finish',\n exclusive: ['list', 'attach'],\n required: false,\n }),\n limit: Flags.integer({\n dependsOn: ['list'],\n description: 'Maximum number of jobs returned (default 10, max 1000)',\n max: 1000,\n required: false,\n }),\n list: Flags.boolean({\n description: 'Lists all dataset copy jobs',\n exclusive: ['attach', 'detach', 'skip-history'],\n required: false,\n }),\n offset: Flags.integer({\n dependsOn: ['list'],\n description: 'Start position in the list of jobs (default 0)',\n required: false,\n }),\n 'skip-content-releases': Flags.boolean({\n description: \"Don't copy content release documents to the target dataset\",\n exclusive: ['list', 'attach'],\n required: false,\n }),\n 'skip-history': Flags.boolean({\n description: \"Don't preserve document history on copy\",\n exclusive: ['list', 'attach'],\n required: false,\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:copy']\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(CopyDatasetCommand)\n\n if (!flags.list && !flags.attach && this.isUnattended()) {\n const errors: string[] = []\n\n if (!args.source) {\n errors.push('Source dataset is required. Pass it as the `<source>` argument.')\n }\n if (!args.target) {\n errors.push('Target dataset is required. Pass it as the `<target>` argument.')\n }\n\n if (errors.length > 0) {\n this.output.error(formatCliErrorMessages(errors), {exit: exitCodes.USAGE_ERROR})\n }\n }\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [\n {grant: 'read', permission: 'sanity.project.datasets'},\n {grant: 'create', permission: 'sanity.project.datasets'},\n ],\n }),\n })\n\n // Route to appropriate mode\n if (flags.list) {\n return this.handleListMode(projectId, flags)\n }\n\n if (flags.attach) {\n return this.handleAttachMode(projectId, flags.attach)\n }\n\n return this.handleCopyMode(projectId, args, flags)\n }\n\n private displayCopyJobsTable(jobs: DatasetCopyJob[]): void {\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'id', title: 'Job ID'},\n {alignment: 'left', name: 'sourceDataset', title: 'Source Dataset'},\n {alignment: 'left', name: 'targetDataset', title: 'Target Dataset'},\n {alignment: 'left', name: 'state', title: 'State'},\n {alignment: 'left', name: 'withHistory', title: 'With history'},\n {alignment: 'left', name: 'timeStarted', title: 'Time started'},\n {alignment: 'left', name: 'timeTaken', title: 'Time taken'},\n ],\n title: 'Dataset copy jobs for this project in descending order',\n })\n\n for (const job of jobs) {\n const {createdAt, id, sourceDataset, state, targetDataset, updatedAt, withHistory} = job\n\n let timeStarted = ''\n if (createdAt !== '') {\n timeStarted = formatDistanceToNow(parseISO(createdAt))\n }\n\n let timeTaken = ''\n if (updatedAt !== '') {\n timeTaken = formatDistance(parseISO(updatedAt), parseISO(createdAt))\n }\n\n let color: '' | 'green' | 'red' | 'yellow'\n switch (state) {\n case 'completed': {\n color = 'green'\n break\n }\n case 'failed': {\n color = 'red'\n break\n }\n case 'pending': {\n color = 'yellow'\n break\n }\n default: {\n color = ''\n }\n }\n\n table.addRow(\n {\n id,\n sourceDataset,\n state,\n targetDataset,\n timeStarted: `${timeStarted} ago`,\n timeTaken,\n withHistory,\n },\n {color},\n )\n }\n\n this.output.log(table.render())\n }\n\n private async handleAttachMode(projectId: string, jobId: string): Promise<void> {\n copyDatasetDebug('Attaching to copy job %s', jobId)\n\n if (jobId.trim() === '') {\n return this.output.error('Please supply a valid jobId', {exit: exitCodes.RUNTIME_ERROR})\n }\n\n try {\n await this.subscribeToProgress(projectId, jobId)\n this.output.log(`Job ${styleText('green', jobId)} completed`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to attach to copy job: %s', message, error)\n return this.output.error(`Failed to attach to copy job: ${message}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async handleCopyMode(\n projectId: string,\n args: {source?: string; target?: string},\n flags: {detach?: boolean; 'skip-content-releases'?: boolean; 'skip-history'?: boolean},\n ): Promise<void> {\n copyDatasetDebug('Starting copy mode')\n\n const skipHistory = Boolean(flags['skip-history'])\n const skipContentReleases = Boolean(flags['skip-content-releases'])\n\n // Surfaced before any prompting so the flag is still actionable: a copy job\n // can't be canceled once started, so mentioning it after the job kicks off\n // leaves nothing to decide.\n if (!skipHistory) {\n this.output.log(\n `Note: You can run this command with flag '--skip-history'. The flag will reduce copy time in larger datasets.`,\n )\n }\n\n // Get and validate source dataset\n let sourceDataset = args.source\n if (sourceDataset) {\n const nameError = validateDatasetName(sourceDataset)\n if (nameError) {\n return this.output.error(nameError, {exit: exitCodes.USAGE_ERROR})\n }\n }\n\n let datasetsResponse\n try {\n datasetsResponse = await listDatasets(projectId)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to fetch datasets: %s', message, error)\n return this.output.error(`Failed to fetch datasets: ${message}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n const datasetNames = new Set(datasetsResponse.map((ds) => ds.name))\n\n // Prompt for source if not provided\n if (!sourceDataset) {\n sourceDataset = await promptForDataset({\n datasets: datasetsResponse,\n })\n }\n\n if (!datasetNames.has(sourceDataset)) {\n return this.output.error(`Source dataset \"${sourceDataset}\" doesn't exist`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n // Get and validate target dataset\n let targetDataset = args.target\n if (targetDataset) {\n const nameError = validateDatasetName(targetDataset)\n if (nameError) {\n return this.output.error(nameError, {exit: exitCodes.USAGE_ERROR})\n }\n } else {\n targetDataset = await promptForDatasetName({\n message: 'Target dataset name:',\n })\n }\n\n if (datasetNames.has(targetDataset)) {\n return this.output.error(`Target dataset \"${targetDataset}\" already exists`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n // Start the copy job\n try {\n this.output.log(\n `Copying dataset ${styleText('green', sourceDataset)} to ${styleText('green', targetDataset)}...`,\n )\n\n const response = await copyDataset({\n projectId,\n skipContentReleases,\n skipHistory,\n sourceDataset,\n targetDataset,\n })\n\n this.output.log(`Job ${styleText('green', response.jobId)} started`)\n\n if (flags.detach) {\n return\n }\n\n await this.subscribeToProgress(projectId, response.jobId)\n this.output.log(`Job ${styleText('green', response.jobId)} completed`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Dataset copying failed: %s', message, error)\n return this.output.error(`Dataset copying failed: ${message}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async handleListMode(\n projectId: string,\n flags: {limit?: number; offset?: number},\n ): Promise<void> {\n copyDatasetDebug('Listing dataset copy jobs')\n\n try {\n const jobs = await listDatasetCopyJobs({\n limit: flags.limit,\n offset: flags.offset,\n projectId,\n })\n\n if (jobs.length === 0) {\n this.output.log(\"This project doesn't have any dataset copy jobs\")\n return\n }\n\n this.displayCopyJobsTable(jobs)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to list dataset copy jobs: %s', message, error)\n return this.output.error(`Failed to list dataset copy jobs: ${message}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async subscribeToProgress(projectId: string, jobId: string): Promise<void> {\n const spin = spinner('').start()\n const hasCliExecutionContext = Boolean(getCliExecutionContext())\n\n return new Promise<void>((resolve, reject) => {\n const sigintHandler = () => {\n subscription.unsubscribe()\n spin.fail('Copy interrupted.')\n exit(130)\n }\n\n const subscription = followCopyJobProgress({jobId, projectId}).subscribe({\n complete: () => {\n if (!hasCliExecutionContext) process.off('SIGINT', sigintHandler)\n spin.succeed('Copy finished.')\n resolve()\n },\n error: (err) => {\n if (!hasCliExecutionContext) process.off('SIGINT', sigintHandler)\n spin.fail('Copy failed.')\n reject(err)\n },\n next: (event: CopyJobProgressEvent) => {\n if (typeof event.progress === 'number') {\n spin.text = `Copy in progress: ${event.progress}%`\n }\n },\n })\n\n if (!hasCliExecutionContext) process.once('SIGINT', sigintHandler)\n })\n }\n}\n"],"names":["styleText","Args","Flags","exit","exitCodes","subdebug","getCliExecutionContext","SanityCommand","spinner","formatDistance","formatDistanceToNow","parseISO","validateDatasetName","promptForDataset","promptForDatasetName","promptForProject","copyDataset","followCopyJobProgress","listDatasetCopyJobs","listDatasets","formatCliErrorMessages","Table","getProjectIdFlag","copyDatasetDebug","CopyDatasetCommand","args","source","string","description","required","target","examples","command","flags","semantics","attach","exclusive","detach","boolean","limit","integer","dependsOn","max","list","offset","hiddenAliases","run","parse","isUnattended","errors","push","length","output","error","USAGE_ERROR","projectId","getProjectId","fallback","requiredPermissions","grant","permission","handleListMode","handleAttachMode","handleCopyMode","displayCopyJobsTable","jobs","table","columns","alignment","name","title","job","createdAt","id","sourceDataset","state","targetDataset","updatedAt","withHistory","timeStarted","timeTaken","color","addRow","log","render","jobId","trim","RUNTIME_ERROR","subscribeToProgress","message","Error","String","skipHistory","Boolean","skipContentReleases","nameError","datasetsResponse","datasetNames","Set","map","ds","datasets","has","response","spin","start","hasCliExecutionContext","Promise","resolve","reject","sigintHandler","subscription","unsubscribe","fail","subscribe","complete","process","off","succeed","err","next","event","progress","text","once"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/datasets/copy.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exit} from '@oclif/core/errors'\nimport {exitCodes} from '@sanity/cli-core'\nimport {subdebug} from '@sanity/cli-core/debug'\nimport {getCliExecutionContext} from '@sanity/cli-core/executionContext'\nimport {SanityCommand} from '@sanity/cli-core/SanityCommand'\nimport {spinner} from '@sanity/cli-core/ux'\n\nimport {validateDatasetName} from '../../actions/dataset/validateDatasetName.js'\nimport {promptForDataset} from '../../prompts/promptForDataset.js'\nimport {promptForDatasetName} from '../../prompts/promptForDatasetName.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {\n copyDataset,\n type CopyJobProgressEvent,\n type DatasetCopyJob,\n followCopyJobProgress,\n listDatasetCopyJobs,\n listDatasets,\n} from '../../services/datasets.js'\nimport {formatDuration, formatTimeAgo} from '../../util/dates.js'\nimport {formatCliErrorMessages} from '../../util/formatCliErrorMessages.js'\nimport {Table} from '../../util/responsiveTable.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst copyDatasetDebug = subdebug('dataset:copy')\n\nexport class CopyDatasetCommand extends SanityCommand<typeof CopyDatasetCommand> {\n static override args = {\n source: Args.string({\n description: 'Name of the dataset to copy from',\n required: false,\n }),\n target: Args.string({\n description: 'Name of the dataset to copy to',\n required: false,\n }),\n }\n\n static override description = 'Copy a dataset or manage copy jobs'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively copy a dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> source-dataset',\n description: 'Copy from source-dataset (prompts for target)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> source-dataset target-dataset',\n description: 'Copy from source-dataset to target-dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --skip-history source target',\n description: 'Copy without preserving document history (faster for large datasets)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --skip-content-releases source target',\n description: 'Copy without content release documents',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --detach source target',\n description: 'Start copy job without waiting for completion',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --attach <job-id>',\n description: 'Attach to a running copy job to follow progress',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --list',\n description: 'List all dataset copy jobs',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --list --offset 2 --limit 10',\n description: 'List copy jobs with pagination',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to copy dataset in',\n semantics: 'override',\n }),\n attach: Flags.string({\n description: 'Attach to the running copy process to show progress',\n exclusive: ['list', 'detach', 'skip-history'],\n required: false,\n }),\n detach: Flags.boolean({\n description: 'Start the copy without waiting for it to finish',\n exclusive: ['list', 'attach'],\n required: false,\n }),\n limit: Flags.integer({\n dependsOn: ['list'],\n description: 'Maximum number of jobs returned (default 10, max 1000)',\n max: 1000,\n required: false,\n }),\n list: Flags.boolean({\n description: 'Lists all dataset copy jobs',\n exclusive: ['attach', 'detach', 'skip-history'],\n required: false,\n }),\n offset: Flags.integer({\n dependsOn: ['list'],\n description: 'Start position in the list of jobs (default 0)',\n required: false,\n }),\n 'skip-content-releases': Flags.boolean({\n description: \"Don't copy content release documents to the target dataset\",\n exclusive: ['list', 'attach'],\n required: false,\n }),\n 'skip-history': Flags.boolean({\n description: \"Don't preserve document history on copy\",\n exclusive: ['list', 'attach'],\n required: false,\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:copy']\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(CopyDatasetCommand)\n\n if (!flags.list && !flags.attach && this.isUnattended()) {\n const errors: string[] = []\n\n if (!args.source) {\n errors.push('Source dataset is required. Pass it as the `<source>` argument.')\n }\n if (!args.target) {\n errors.push('Target dataset is required. Pass it as the `<target>` argument.')\n }\n\n if (errors.length > 0) {\n this.output.error(formatCliErrorMessages(errors), {exit: exitCodes.USAGE_ERROR})\n }\n }\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [\n {grant: 'read', permission: 'sanity.project.datasets'},\n {grant: 'create', permission: 'sanity.project.datasets'},\n ],\n }),\n })\n\n // Route to appropriate mode\n if (flags.list) {\n return this.handleListMode(projectId, flags)\n }\n\n if (flags.attach) {\n return this.handleAttachMode(projectId, flags.attach)\n }\n\n return this.handleCopyMode(projectId, args, flags)\n }\n\n private displayCopyJobsTable(jobs: DatasetCopyJob[]): void {\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'id', title: 'Job ID'},\n {alignment: 'left', name: 'sourceDataset', title: 'Source Dataset'},\n {alignment: 'left', name: 'targetDataset', title: 'Target Dataset'},\n {alignment: 'left', name: 'state', title: 'State'},\n {alignment: 'left', name: 'withHistory', title: 'With history'},\n {alignment: 'left', name: 'timeStarted', title: 'Time started'},\n {alignment: 'left', name: 'timeTaken', title: 'Time taken'},\n ],\n title: 'Dataset copy jobs for this project in descending order',\n })\n\n for (const job of jobs) {\n const {createdAt, id, sourceDataset, state, targetDataset, updatedAt, withHistory} = job\n\n let timeStarted = ''\n if (createdAt !== '') {\n timeStarted = formatTimeAgo(new Date(createdAt))\n }\n\n let timeTaken = ''\n if (createdAt !== '' && updatedAt !== '') {\n timeTaken = formatDuration(new Date(updatedAt).getTime() - new Date(createdAt).getTime())\n }\n\n let color: '' | 'green' | 'red' | 'yellow'\n switch (state) {\n case 'completed': {\n color = 'green'\n break\n }\n case 'failed': {\n color = 'red'\n break\n }\n case 'pending': {\n color = 'yellow'\n break\n }\n default: {\n color = ''\n }\n }\n\n table.addRow(\n {\n id,\n sourceDataset,\n state,\n targetDataset,\n timeStarted,\n timeTaken,\n withHistory,\n },\n {color},\n )\n }\n\n this.output.log(table.render())\n }\n\n private async handleAttachMode(projectId: string, jobId: string): Promise<void> {\n copyDatasetDebug('Attaching to copy job %s', jobId)\n\n if (jobId.trim() === '') {\n return this.output.error('Please supply a valid jobId', {exit: exitCodes.RUNTIME_ERROR})\n }\n\n try {\n await this.subscribeToProgress(projectId, jobId)\n this.output.log(`Job ${styleText('green', jobId)} completed`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to attach to copy job: %s', message, error)\n return this.output.error(`Failed to attach to copy job: ${message}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async handleCopyMode(\n projectId: string,\n args: {source?: string; target?: string},\n flags: {detach?: boolean; 'skip-content-releases'?: boolean; 'skip-history'?: boolean},\n ): Promise<void> {\n copyDatasetDebug('Starting copy mode')\n\n const skipHistory = Boolean(flags['skip-history'])\n const skipContentReleases = Boolean(flags['skip-content-releases'])\n\n // Surfaced before any prompting so the flag is still actionable: a copy job\n // can't be canceled once started, so mentioning it after the job kicks off\n // leaves nothing to decide.\n if (!skipHistory) {\n this.output.log(\n `Note: You can run this command with flag '--skip-history'. The flag will reduce copy time in larger datasets.`,\n )\n }\n\n // Get and validate source dataset\n let sourceDataset = args.source\n if (sourceDataset) {\n const nameError = validateDatasetName(sourceDataset)\n if (nameError) {\n return this.output.error(nameError, {exit: exitCodes.USAGE_ERROR})\n }\n }\n\n let datasetsResponse\n try {\n datasetsResponse = await listDatasets(projectId)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to fetch datasets: %s', message, error)\n return this.output.error(`Failed to fetch datasets: ${message}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n const datasetNames = new Set(datasetsResponse.map((ds) => ds.name))\n\n // Prompt for source if not provided\n if (!sourceDataset) {\n sourceDataset = await promptForDataset({\n datasets: datasetsResponse,\n })\n }\n\n if (!datasetNames.has(sourceDataset)) {\n return this.output.error(`Source dataset \"${sourceDataset}\" doesn't exist`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n // Get and validate target dataset\n let targetDataset = args.target\n if (targetDataset) {\n const nameError = validateDatasetName(targetDataset)\n if (nameError) {\n return this.output.error(nameError, {exit: exitCodes.USAGE_ERROR})\n }\n } else {\n targetDataset = await promptForDatasetName({\n message: 'Target dataset name:',\n })\n }\n\n if (datasetNames.has(targetDataset)) {\n return this.output.error(`Target dataset \"${targetDataset}\" already exists`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n // Start the copy job\n try {\n this.output.log(\n `Copying dataset ${styleText('green', sourceDataset)} to ${styleText('green', targetDataset)}...`,\n )\n\n const response = await copyDataset({\n projectId,\n skipContentReleases,\n skipHistory,\n sourceDataset,\n targetDataset,\n })\n\n this.output.log(`Job ${styleText('green', response.jobId)} started`)\n\n if (flags.detach) {\n return\n }\n\n await this.subscribeToProgress(projectId, response.jobId)\n this.output.log(`Job ${styleText('green', response.jobId)} completed`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Dataset copying failed: %s', message, error)\n return this.output.error(`Dataset copying failed: ${message}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async handleListMode(\n projectId: string,\n flags: {limit?: number; offset?: number},\n ): Promise<void> {\n copyDatasetDebug('Listing dataset copy jobs')\n\n try {\n const jobs = await listDatasetCopyJobs({\n limit: flags.limit,\n offset: flags.offset,\n projectId,\n })\n\n if (jobs.length === 0) {\n this.output.log(\"This project doesn't have any dataset copy jobs\")\n return\n }\n\n this.displayCopyJobsTable(jobs)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to list dataset copy jobs: %s', message, error)\n return this.output.error(`Failed to list dataset copy jobs: ${message}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async subscribeToProgress(projectId: string, jobId: string): Promise<void> {\n const spin = spinner('').start()\n const hasCliExecutionContext = Boolean(getCliExecutionContext())\n\n return new Promise<void>((resolve, reject) => {\n const sigintHandler = () => {\n subscription.unsubscribe()\n spin.fail('Copy interrupted.')\n exit(130)\n }\n\n const subscription = followCopyJobProgress({jobId, projectId}).subscribe({\n complete: () => {\n if (!hasCliExecutionContext) process.off('SIGINT', sigintHandler)\n spin.succeed('Copy finished.')\n resolve()\n },\n error: (err) => {\n if (!hasCliExecutionContext) process.off('SIGINT', sigintHandler)\n spin.fail('Copy failed.')\n reject(err)\n },\n next: (event: CopyJobProgressEvent) => {\n if (typeof event.progress === 'number') {\n spin.text = `Copy in progress: ${event.progress}%`\n }\n },\n })\n\n if (!hasCliExecutionContext) process.once('SIGINT', sigintHandler)\n })\n }\n}\n"],"names":["styleText","Args","Flags","exit","exitCodes","subdebug","getCliExecutionContext","SanityCommand","spinner","validateDatasetName","promptForDataset","promptForDatasetName","promptForProject","copyDataset","followCopyJobProgress","listDatasetCopyJobs","listDatasets","formatDuration","formatTimeAgo","formatCliErrorMessages","Table","getProjectIdFlag","copyDatasetDebug","CopyDatasetCommand","args","source","string","description","required","target","examples","command","flags","semantics","attach","exclusive","detach","boolean","limit","integer","dependsOn","max","list","offset","hiddenAliases","run","parse","isUnattended","errors","push","length","output","error","USAGE_ERROR","projectId","getProjectId","fallback","requiredPermissions","grant","permission","handleListMode","handleAttachMode","handleCopyMode","displayCopyJobsTable","jobs","table","columns","alignment","name","title","job","createdAt","id","sourceDataset","state","targetDataset","updatedAt","withHistory","timeStarted","Date","timeTaken","getTime","color","addRow","log","render","jobId","trim","RUNTIME_ERROR","subscribeToProgress","message","Error","String","skipHistory","Boolean","skipContentReleases","nameError","datasetsResponse","datasetNames","Set","map","ds","datasets","has","response","spin","start","hasCliExecutionContext","Promise","resolve","reject","sigintHandler","subscription","unsubscribe","fail","subscribe","complete","process","off","succeed","err","next","event","progress","text","once"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { styleText } from 'node:util';
2
2
  import { Args, Flags } from '@oclif/core';
3
- import { exitCodes, isInteractive, SanityCommand, subdebug } from '@sanity/cli-core';
3
+ import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
4
4
  import { select } from '@sanity/cli-core/ux';
5
5
  import { readDoc, searchDocs } from '../../services/docs.js';
6
6
  const searchDebug = subdebug('docs:search');
@@ -65,7 +65,7 @@ export class DocsSearchCommand extends SanityCommand {
65
65
  this.log('');
66
66
  }
67
67
  // Show usage hint in non-interactive mode
68
- if (!isInteractive()) {
68
+ if (!this.resolveIsInteractive()) {
69
69
  this.log('Use `sanity docs read <url>` to read an article in terminal.');
70
70
  this.log('Use `sanity docs read <path>` to follow links found within articles.');
71
71
  this.log('');
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/docs/search.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exitCodes, isInteractive, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {select} from '@sanity/cli-core/ux'\n\nimport {readDoc, searchDocs, type SearchResult} from '../../services/docs.js'\n\nconst searchDebug = subdebug('docs:search')\n\nexport class DocsSearchCommand extends SanityCommand<typeof DocsSearchCommand> {\n static override args = {\n query: Args.string({\n description: 'Search query for documentation',\n required: true,\n }),\n }\n\n static override description = 'Search Sanity docs'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> schema',\n description: 'Search for documentation about schemas',\n },\n {\n command: '<%= config.bin %> <%= command.id %> \"groq functions\"',\n description: 'Search with phrase',\n },\n {\n command: '<%= config.bin %> <%= command.id %> \"deployment\" --limit=5',\n description: 'Limit search results',\n },\n ]\n\n static override flags = {\n limit: Flags.integer({\n default: 10,\n description: 'Maximum number of results to return',\n min: 1,\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(DocsSearchCommand)\n const {query} = args\n const {limit} = flags\n\n this.log(`Searching documentation for: \"${query}\"`)\n\n let results: SearchResult[]\n try {\n results = await searchDocs({\n limit,\n query,\n })\n\n if (results.length === 0) {\n this.log('No results found. Try a different search term.')\n return\n }\n } catch (error) {\n searchDebug('error fetching results', error)\n const message =\n error instanceof Error\n ? error.message\n : 'The documentation search API is currently unavailable. Please try again later.'\n this.error(message, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n this.log(`\\nFound ${results.length} result(s):\\n`)\n\n for (const [index, result] of results.entries()) {\n this.log(`${index + 1}. ${result.title}`)\n this.log(` ${styleText('cyan', `URL: https://www.sanity.io${result.path}`)}`)\n if (result.description) {\n this.log(` ${result.description}`)\n }\n this.log('')\n }\n\n // Show usage hint in non-interactive mode\n if (!isInteractive()) {\n this.log('Use `sanity docs read <url>` to read an article in terminal.')\n this.log('Use `sanity docs read <path>` to follow links found within articles.')\n this.log('')\n return\n }\n\n // Interactive selection (only in interactive environments)\n if (results.length > 0) {\n const choices = results.map((result, index) => ({\n description: result.description,\n name: `${index + 1}. ${result.title} (${result.path})`,\n value: index,\n }))\n\n const selectedIndex = await select({\n choices: [...choices, {description: 'Exit without reading', name: 'Exit', value: -1}],\n message: 'Select an article to read in terminal:',\n })\n\n if (typeof selectedIndex === 'number' && selectedIndex >= 0) {\n const selected = results[selectedIndex]\n\n try {\n // Read and display the article\n const content = await readDoc({path: selected.path})\n this.log('\\n---\\n')\n this.log(content)\n } catch (error) {\n this.error(\n `Failed to read article: ${error instanceof Error ? error.message : 'Unknown error'}`,\n {\n exit: exitCodes.RUNTIME_ERROR,\n },\n )\n }\n }\n }\n }\n}\n"],"names":["styleText","Args","Flags","exitCodes","isInteractive","SanityCommand","subdebug","select","readDoc","searchDocs","searchDebug","DocsSearchCommand","args","query","string","description","required","examples","command","flags","limit","integer","default","min","run","parse","log","results","length","error","message","Error","exit","RUNTIME_ERROR","index","result","entries","title","path","choices","map","name","value","selectedIndex","selected","content"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/docs/search.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {select} from '@sanity/cli-core/ux'\n\nimport {readDoc, searchDocs, type SearchResult} from '../../services/docs.js'\n\nconst searchDebug = subdebug('docs:search')\n\nexport class DocsSearchCommand extends SanityCommand<typeof DocsSearchCommand> {\n static override args = {\n query: Args.string({\n description: 'Search query for documentation',\n required: true,\n }),\n }\n\n static override description = 'Search Sanity docs'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> schema',\n description: 'Search for documentation about schemas',\n },\n {\n command: '<%= config.bin %> <%= command.id %> \"groq functions\"',\n description: 'Search with phrase',\n },\n {\n command: '<%= config.bin %> <%= command.id %> \"deployment\" --limit=5',\n description: 'Limit search results',\n },\n ]\n\n static override flags = {\n limit: Flags.integer({\n default: 10,\n description: 'Maximum number of results to return',\n min: 1,\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(DocsSearchCommand)\n const {query} = args\n const {limit} = flags\n\n this.log(`Searching documentation for: \"${query}\"`)\n\n let results: SearchResult[]\n try {\n results = await searchDocs({\n limit,\n query,\n })\n\n if (results.length === 0) {\n this.log('No results found. Try a different search term.')\n return\n }\n } catch (error) {\n searchDebug('error fetching results', error)\n const message =\n error instanceof Error\n ? error.message\n : 'The documentation search API is currently unavailable. Please try again later.'\n this.error(message, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n this.log(`\\nFound ${results.length} result(s):\\n`)\n\n for (const [index, result] of results.entries()) {\n this.log(`${index + 1}. ${result.title}`)\n this.log(` ${styleText('cyan', `URL: https://www.sanity.io${result.path}`)}`)\n if (result.description) {\n this.log(` ${result.description}`)\n }\n this.log('')\n }\n\n // Show usage hint in non-interactive mode\n if (!this.resolveIsInteractive()) {\n this.log('Use `sanity docs read <url>` to read an article in terminal.')\n this.log('Use `sanity docs read <path>` to follow links found within articles.')\n this.log('')\n return\n }\n\n // Interactive selection (only in interactive environments)\n if (results.length > 0) {\n const choices = results.map((result, index) => ({\n description: result.description,\n name: `${index + 1}. ${result.title} (${result.path})`,\n value: index,\n }))\n\n const selectedIndex = await select({\n choices: [...choices, {description: 'Exit without reading', name: 'Exit', value: -1}],\n message: 'Select an article to read in terminal:',\n })\n\n if (typeof selectedIndex === 'number' && selectedIndex >= 0) {\n const selected = results[selectedIndex]\n\n try {\n // Read and display the article\n const content = await readDoc({path: selected.path})\n this.log('\\n---\\n')\n this.log(content)\n } catch (error) {\n this.error(\n `Failed to read article: ${error instanceof Error ? error.message : 'Unknown error'}`,\n {\n exit: exitCodes.RUNTIME_ERROR,\n },\n )\n }\n }\n }\n }\n}\n"],"names":["styleText","Args","Flags","exitCodes","SanityCommand","subdebug","select","readDoc","searchDocs","searchDebug","DocsSearchCommand","args","query","string","description","required","examples","command","flags","limit","integer","default","min","run","parse","log","results","length","error","message","Error","exit","RUNTIME_ERROR","index","result","entries","title","path","resolveIsInteractive","choices","map","name","value","selectedIndex","selected","content"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { exitCodes, isInteractive, SanityCommand, subdebug } from '@sanity/cli-core';
1
+ import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
2
2
  import { getErrorMessage, toError } from '@sanity/cli-core/errors';
3
3
  import { ensureAuthenticated } from '../../actions/auth/ensureAuthenticated.js';
4
4
  import { setupMCP } from '../../actions/mcp/setupMCP.js';
@@ -36,7 +36,7 @@ export class ConfigureMcpCommand extends SanityCommand {
36
36
  try {
37
37
  const mcpResult = await setupMCP({
38
38
  explicit: true,
39
- mode: isInteractive() ? 'prompt' : 'auto',
39
+ mode: this.resolveIsInteractive() ? 'prompt' : 'auto',
40
40
  output: this.output,
41
41
  skillsMode: 'skip'
42
42
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/mcp/configure.ts"],"sourcesContent":["import {exitCodes, isInteractive, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage, toError} from '@sanity/cli-core/errors'\n\nimport {ensureAuthenticated} from '../../actions/auth/ensureAuthenticated.js'\nimport {setupMCP} from '../../actions/mcp/setupMCP.js'\nimport {LoginError} from '../../errors/LoginError.js'\nimport {MCPConfigureTrace} from '../../telemetry/mcp.telemetry.js'\n\nconst debug = subdebug('mcp:configure')\n\nexport class ConfigureMcpCommand extends SanityCommand<typeof ConfigureMcpCommand> {\n static override description =\n 'Configure Sanity MCP server for AI editors (Antigravity, Claude Code, Cline, Cline CLI, Codex CLI, Cursor, Gemini CLI, GitHub Copilot CLI, MCPorter, OpenCode, VS Code, VS Code Insiders, Zed)'\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Configure Sanity MCP server for detected AI editors',\n },\n ]\n\n public async run(): Promise<void> {\n const trace = this.telemetry.trace(MCPConfigureTrace)\n trace.start()\n\n try {\n await ensureAuthenticated({output: this.output, telemetry: this.telemetry})\n } catch (error) {\n debug('Authentication check failed: %O', error)\n trace.error(toError(error))\n\n if (error instanceof LoginError) {\n this.error(\n `Failed to verify authentication credentials: ${error.message}. Try running \\`sanity login\\`.`,\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n\n this.error(`Failed to check authentication: ${getErrorMessage(error)}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n try {\n const mcpResult = await setupMCP({\n explicit: true,\n mode: isInteractive() ? 'prompt' : 'auto',\n output: this.output,\n skillsMode: 'skip',\n })\n\n trace.log({\n configuredEditors: mcpResult.configuredEditors,\n detectedEditors: mcpResult.detectedEditors,\n })\n\n if (mcpResult.error) {\n trace.error(mcpResult.error)\n } else {\n trace.complete()\n }\n } catch (error) {\n trace.error(toError(error))\n this.error(getErrorMessage(error), {exit: exitCodes.RUNTIME_ERROR})\n }\n }\n}\n"],"names":["exitCodes","isInteractive","SanityCommand","subdebug","getErrorMessage","toError","ensureAuthenticated","setupMCP","LoginError","MCPConfigureTrace","debug","ConfigureMcpCommand","description","examples","command","run","trace","telemetry","start","output","error","message","exit","RUNTIME_ERROR","mcpResult","explicit","mode","skillsMode","log","configuredEditors","detectedEditors","complete"],"mappings":"AAAA,SAAQA,SAAS,EAAEC,aAAa,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAClF,SAAQC,eAAe,EAAEC,OAAO,QAAO,0BAAyB;AAEhE,SAAQC,mBAAmB,QAAO,4CAA2C;AAC7E,SAAQC,QAAQ,QAAO,gCAA+B;AACtD,SAAQC,UAAU,QAAO,6BAA4B;AACrD,SAAQC,iBAAiB,QAAO,mCAAkC;AAElE,MAAMC,QAAQP,SAAS;AAEvB,OAAO,MAAMQ,4BAA4BT;IACvC,OAAgBU,cACd,iMAAgM;IAClM,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTF,aAAa;QACf;KACD,CAAA;IAED,MAAaG,MAAqB;QAChC,MAAMC,QAAQ,IAAI,CAACC,SAAS,CAACD,KAAK,CAACP;QACnCO,MAAME,KAAK;QAEX,IAAI;YACF,MAAMZ,oBAAoB;gBAACa,QAAQ,IAAI,CAACA,MAAM;gBAAEF,WAAW,IAAI,CAACA,SAAS;YAAA;QAC3E,EAAE,OAAOG,OAAO;YACdV,MAAM,mCAAmCU;YACzCJ,MAAMI,KAAK,CAACf,QAAQe;YAEpB,IAAIA,iBAAiBZ,YAAY;gBAC/B,IAAI,CAACY,KAAK,CACR,CAAC,6CAA6C,EAAEA,MAAMC,OAAO,CAAC,+BAA+B,CAAC,EAC9F;oBAACC,MAAMtB,UAAUuB,aAAa;gBAAA;YAElC;YAEA,IAAI,CAACH,KAAK,CAAC,CAAC,gCAAgC,EAAEhB,gBAAgBgB,QAAQ,EAAE;gBACtEE,MAAMtB,UAAUuB,aAAa;YAC/B;QACF;QAEA,IAAI;YACF,MAAMC,YAAY,MAAMjB,SAAS;gBAC/BkB,UAAU;gBACVC,MAAMzB,kBAAkB,WAAW;gBACnCkB,QAAQ,IAAI,CAACA,MAAM;gBACnBQ,YAAY;YACd;YAEAX,MAAMY,GAAG,CAAC;gBACRC,mBAAmBL,UAAUK,iBAAiB;gBAC9CC,iBAAiBN,UAAUM,eAAe;YAC5C;YAEA,IAAIN,UAAUJ,KAAK,EAAE;gBACnBJ,MAAMI,KAAK,CAACI,UAAUJ,KAAK;YAC7B,OAAO;gBACLJ,MAAMe,QAAQ;YAChB;QACF,EAAE,OAAOX,OAAO;YACdJ,MAAMI,KAAK,CAACf,QAAQe;YACpB,IAAI,CAACA,KAAK,CAAChB,gBAAgBgB,QAAQ;gBAACE,MAAMtB,UAAUuB,aAAa;YAAA;QACnE;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/commands/mcp/configure.ts"],"sourcesContent":["import {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage, toError} from '@sanity/cli-core/errors'\n\nimport {ensureAuthenticated} from '../../actions/auth/ensureAuthenticated.js'\nimport {setupMCP} from '../../actions/mcp/setupMCP.js'\nimport {LoginError} from '../../errors/LoginError.js'\nimport {MCPConfigureTrace} from '../../telemetry/mcp.telemetry.js'\n\nconst debug = subdebug('mcp:configure')\n\nexport class ConfigureMcpCommand extends SanityCommand<typeof ConfigureMcpCommand> {\n static override description =\n 'Configure Sanity MCP server for AI editors (Antigravity, Claude Code, Cline, Cline CLI, Codex CLI, Cursor, Gemini CLI, GitHub Copilot CLI, MCPorter, OpenCode, VS Code, VS Code Insiders, Zed)'\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Configure Sanity MCP server for detected AI editors',\n },\n ]\n\n public async run(): Promise<void> {\n const trace = this.telemetry.trace(MCPConfigureTrace)\n trace.start()\n\n try {\n await ensureAuthenticated({output: this.output, telemetry: this.telemetry})\n } catch (error) {\n debug('Authentication check failed: %O', error)\n trace.error(toError(error))\n\n if (error instanceof LoginError) {\n this.error(\n `Failed to verify authentication credentials: ${error.message}. Try running \\`sanity login\\`.`,\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n\n this.error(`Failed to check authentication: ${getErrorMessage(error)}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n try {\n const mcpResult = await setupMCP({\n explicit: true,\n mode: this.resolveIsInteractive() ? 'prompt' : 'auto',\n output: this.output,\n skillsMode: 'skip',\n })\n\n trace.log({\n configuredEditors: mcpResult.configuredEditors,\n detectedEditors: mcpResult.detectedEditors,\n })\n\n if (mcpResult.error) {\n trace.error(mcpResult.error)\n } else {\n trace.complete()\n }\n } catch (error) {\n trace.error(toError(error))\n this.error(getErrorMessage(error), {exit: exitCodes.RUNTIME_ERROR})\n }\n }\n}\n"],"names":["exitCodes","SanityCommand","subdebug","getErrorMessage","toError","ensureAuthenticated","setupMCP","LoginError","MCPConfigureTrace","debug","ConfigureMcpCommand","description","examples","command","run","trace","telemetry","start","output","error","message","exit","RUNTIME_ERROR","mcpResult","explicit","mode","resolveIsInteractive","skillsMode","log","configuredEditors","detectedEditors","complete"],"mappings":"AAAA,SAAQA,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACnE,SAAQC,eAAe,EAAEC,OAAO,QAAO,0BAAyB;AAEhE,SAAQC,mBAAmB,QAAO,4CAA2C;AAC7E,SAAQC,QAAQ,QAAO,gCAA+B;AACtD,SAAQC,UAAU,QAAO,6BAA4B;AACrD,SAAQC,iBAAiB,QAAO,mCAAkC;AAElE,MAAMC,QAAQP,SAAS;AAEvB,OAAO,MAAMQ,4BAA4BT;IACvC,OAAgBU,cACd,iMAAgM;IAClM,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTF,aAAa;QACf;KACD,CAAA;IAED,MAAaG,MAAqB;QAChC,MAAMC,QAAQ,IAAI,CAACC,SAAS,CAACD,KAAK,CAACP;QACnCO,MAAME,KAAK;QAEX,IAAI;YACF,MAAMZ,oBAAoB;gBAACa,QAAQ,IAAI,CAACA,MAAM;gBAAEF,WAAW,IAAI,CAACA,SAAS;YAAA;QAC3E,EAAE,OAAOG,OAAO;YACdV,MAAM,mCAAmCU;YACzCJ,MAAMI,KAAK,CAACf,QAAQe;YAEpB,IAAIA,iBAAiBZ,YAAY;gBAC/B,IAAI,CAACY,KAAK,CACR,CAAC,6CAA6C,EAAEA,MAAMC,OAAO,CAAC,+BAA+B,CAAC,EAC9F;oBAACC,MAAMrB,UAAUsB,aAAa;gBAAA;YAElC;YAEA,IAAI,CAACH,KAAK,CAAC,CAAC,gCAAgC,EAAEhB,gBAAgBgB,QAAQ,EAAE;gBACtEE,MAAMrB,UAAUsB,aAAa;YAC/B;QACF;QAEA,IAAI;YACF,MAAMC,YAAY,MAAMjB,SAAS;gBAC/BkB,UAAU;gBACVC,MAAM,IAAI,CAACC,oBAAoB,KAAK,WAAW;gBAC/CR,QAAQ,IAAI,CAACA,MAAM;gBACnBS,YAAY;YACd;YAEAZ,MAAMa,GAAG,CAAC;gBACRC,mBAAmBN,UAAUM,iBAAiB;gBAC9CC,iBAAiBP,UAAUO,eAAe;YAC5C;YAEA,IAAIP,UAAUJ,KAAK,EAAE;gBACnBJ,MAAMI,KAAK,CAACI,UAAUJ,KAAK;YAC7B,OAAO;gBACLJ,MAAMgB,QAAQ;YAChB;QACF,EAAE,OAAOZ,OAAO;YACdJ,MAAMI,KAAK,CAACf,QAAQe;YACpB,IAAI,CAACA,KAAK,CAAChB,gBAAgBgB,QAAQ;gBAACE,MAAMrB,UAAUsB,aAAa;YAAA;QACnE;IACF;AACF"}
@@ -86,7 +86,7 @@ export class NewCommand extends SanityCommand {
86
86
  required: false
87
87
  })
88
88
  };
89
- static description = formatHelpDescription(`Sets up two folders here: ./${STUDIO_DIR}, a Studio where you write and edit your content, ` + `and ./${FRONTEND_DIR}, a Next.js website that reads it. Both are already connected to your ` + 'new project, so you can start them straight away. Use --no-scaffold if you just want the ' + 'project and nothing else.', `The project is real and works immediately, but it is only yours for ${CLAIM_WINDOW_HOURS} hours. Claim it with ` + 'a Sanity account before the deadline and everything you have built stays exactly as it is. ' + 'Claiming is free and takes about a minute. Miss the deadline and the project and its ' + 'content are deleted.', 'Two things to keep private: the claim link, because anyone who opens it becomes the owner, ' + `and the access token saved in ./${STUDIO_ENV_FILE} and ./${FRONTEND_ENV_FILE}, because it ` + 'can read and change everything in the project. Keep both env files out of git, and never ' + 'put the token in code that runs in the browser.', 'Run this command with --instructions for the full agent setup guide.');
89
+ static description = formatHelpDescription(`Sets up two folders here: ./${STUDIO_DIR}, a Studio where you write and edit your content, ` + `and ./${FRONTEND_DIR}, a Next.js website that reads it. Both are already connected to your ` + 'new project, so you can start them straight away. Use --no-scaffold if you just want the ' + 'project and nothing else.', `The project is real and works immediately, but it is only yours for ${CLAIM_WINDOW_HOURS} hours. Claim it with ` + 'a Sanity account before the deadline and everything you have built stays exactly as it is. ' + 'Claiming is free and takes about a minute. Miss the deadline and the project and its ' + 'content are deleted.', 'Two things to keep private: the claim link, because anyone who opens it becomes the owner, ' + `and the access token saved in ./${STUDIO_ENV_FILE}, because it can read and change ` + `everything in the project. ./${FRONTEND_ENV_FILE} has only the project ID and dataset. ` + 'Keep both env files out of git, and never put the token in code that runs in the browser.', 'Run this command with --instructions for the full agent setup guide.');
90
90
  static enableJsonFlag = true;
91
91
  static examples = [
92
92
  {
@@ -316,7 +316,6 @@ export class NewCommand extends SanityCommand {
316
316
  flow.line('The token signs you in: there is no account yet.');
317
317
  flow.gap();
318
318
  }
319
- flow.line('Your content is private until you claim, to read it, you need the token.');
320
319
  flow.line("Treat your token as a password and don't expose it publicly in your app.");
321
320
  flow.gap();
322
321
  flow.line('The claim link and token are printed above but you can recover them ' + `with ${styleText('cyan', 'sanity projects unclaimed')} before the timer runs out on ${formatClaimDeadline(project.expiresAt)}.`);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/new.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {CLIError} from '@oclif/core/errors'\nimport {exitCodes} from '@sanity/cli-core'\nimport {SanityCommand} from '@sanity/cli-core/SanityCommand'\nimport {createFlow, input} from '@sanity/cli-core/ux'\n\nimport {\n FRONTEND_DIR,\n FRONTEND_ENV_FILE,\n getUnavailableScaffoldTarget,\n scaffoldProject,\n type ScaffoldResult,\n STUDIO_DIR,\n STUDIO_ENV_FILE,\n} from '../actions/scaffold/scaffoldProject.js'\nimport {type MintedProject, mintUnclaimedProject} from '../services/mintProject.js'\nimport {\n fetchNewInstructions,\n INSTRUCTIONS_URL,\n InstructionsUnavailableError,\n} from '../services/newInstructions.js'\nimport {formatClaimDeadline} from '../util/formatClaimDeadline.js'\nimport {CLAIM_WINDOW_HOURS, SANITY_NEW_URL} from '../util/mintProjectConstants.js'\nimport {renderNewCommandSplash} from '../util/newCommandSplash.js'\nimport {recordUnclaimedProject} from '../util/unclaimedProjects.js'\n\nconst DEFAULT_PROJECT_NAME = 'My Sanity project'\nconst HELP_DESCRIPTION_WIDTH = 78\n\n/**\n * Prepended to the fetched instructions so an agent cannot read this command's success as the\n * project already existing. The only addition to an otherwise verbatim document.\n */\nconst INSTRUCTIONS_HEADER = '# Nothing has been created yet — follow these steps.'\n\nfunction formatHelpDescription(...paragraphs: string[]): string {\n return paragraphs\n .map((paragraph) => {\n const lines: string[] = []\n let line = ''\n\n for (const word of paragraph.split(/\\s+/u)) {\n if (!line || line.length + word.length + 1 <= HELP_DESCRIPTION_WIDTH) {\n line = line ? `${line} ${word}` : word\n } else {\n lines.push(line)\n line = word\n }\n }\n\n if (line) lines.push(line)\n return lines.join('\\n')\n })\n .join('\\n\\n')\n}\n\nconst FRONTEND_DEV_COMMANDS: Record<\n NonNullable<ScaffoldResult['frontendPackageManager']>,\n string\n> = {\n bun: 'bun dev',\n manual: 'npm run dev',\n npm: 'npm run dev',\n pnpm: 'pnpm dev',\n yarn: 'yarn dev',\n}\n\nfunction frontendDevCommand(packageManager: ScaffoldResult['frontendPackageManager']): string {\n return packageManager ? FRONTEND_DEV_COMMANDS[packageManager] : 'npm run dev'\n}\n\nfunction frontendInstallCommand(packageManager: ScaffoldResult['frontendPackageManager']): string {\n switch (packageManager) {\n case 'bun': {\n return 'bun add next-sanity'\n }\n case 'pnpm': {\n return 'pnpm add --save-prod next-sanity'\n }\n case 'yarn': {\n return 'yarn add next-sanity'\n }\n default: {\n return 'npm install next-sanity'\n }\n }\n}\n\nexport interface NewProjectResult {\n apiHost: string\n claimApiUrl: string\n claimToken: string\n claimUrl: string\n dataset: string\n expiresAt: string\n projectId: string\n terms: {\n notice: string\n url: string\n }\n token: string\n}\n\nfunction toResult(project: MintedProject): NewProjectResult {\n return {\n apiHost: project.apiHost,\n claimApiUrl: project.claimApiUrl,\n claimToken: project.claimToken,\n claimUrl: project.claimUrl,\n dataset: project.datasetName,\n expiresAt: project.expiresAt,\n projectId: project.resourceId,\n terms: {notice: project.termsNotice, url: project.termsUrl},\n token: project.token,\n }\n}\n\nexport class NewCommand extends SanityCommand<typeof NewCommand> {\n static override args = {\n projectName: Args.string({\n description: 'Display name for the new project',\n required: false,\n }),\n }\n\n static override description = formatHelpDescription(\n `Sets up two folders here: ./${STUDIO_DIR}, a Studio where you write and edit your content, ` +\n `and ./${FRONTEND_DIR}, a Next.js website that reads it. Both are already connected to your ` +\n 'new project, so you can start them straight away. Use --no-scaffold if you just want the ' +\n 'project and nothing else.',\n `The project is real and works immediately, but it is only yours for ${CLAIM_WINDOW_HOURS} hours. Claim it with ` +\n 'a Sanity account before the deadline and everything you have built stays exactly as it is. ' +\n 'Claiming is free and takes about a minute. Miss the deadline and the project and its ' +\n 'content are deleted.',\n 'Two things to keep private: the claim link, because anyone who opens it becomes the owner, ' +\n `and the access token saved in ./${STUDIO_ENV_FILE} and ./${FRONTEND_ENV_FILE}, because it ` +\n 'can read and change everything in the project. Keep both env files out of git, and never ' +\n 'put the token in code that runs in the browser.',\n 'Run this command with --instructions for the full agent setup guide.',\n )\n\n static override enableJsonFlag = true\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Create a project with a Studio and a website',\n },\n {\n command: '<%= config.bin %> <%= command.id %> \"My New Project\"',\n description: 'Create a project called \"My New Project\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --yes',\n description: 'Create a project without being asked anything',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --no-scaffold',\n description: 'Create the project only, with no Studio or website',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --json',\n description: 'Create a project and print its details as JSON',\n },\n\n {\n command: '<%= config.bin %> <%= command.id %> --instructions',\n description: 'Print the full setup guide for an AI agent, without creating anything',\n },\n ]\n\n static override flags = {\n instructions: Flags.boolean({\n default: false,\n description: `Print the full setup guide from ${SANITY_NEW_URL} and exit, creating nothing`,\n }),\n scaffold: Flags.boolean({\n allowNo: true,\n default: true,\n description: `Set up a Studio in ./${STUDIO_DIR} and a Next.js website in ./${FRONTEND_DIR} (on by default)`,\n }),\n yes: Flags.boolean({\n char: 'y',\n default: false,\n description: `Skip prompts and use defaults (project: \"${DEFAULT_PROJECT_NAME}\")`,\n }),\n }\n\n static override summary = `Create a Sanity project without an account, and claim it within ${CLAIM_WINDOW_HOURS} hours to keep it.`\n\n public async run(): Promise<NewProjectResult | undefined> {\n const {output} = this\n const json = this.jsonEnabled()\n const flow = createFlow(output.log)\n const invoked = [this.config.bin, ...(this.id?.split(':') ?? [])].join(' ')\n const cwd = process.cwd()\n\n // Runs before every precondition and side effect: this flag creates nothing.\n if (this.flags.instructions) {\n // oclif's `exclusive` does not cover the json flag added by enableJsonFlag, so guard it here.\n if (json) {\n throw new CLIError('--instructions cannot be combined with --json.', {\n code: 'INSTRUCTIONS_JSON_CONFLICT',\n exit: exitCodes.USAGE_ERROR,\n suggestions: [\n `Run \\`${invoked} --instructions\\` for the setup guide as markdown`,\n `Or run \\`${invoked} --json\\` to create a project and print its details as JSON`,\n ],\n })\n }\n\n await this.printInstructions()\n return undefined\n }\n\n const unavailableScaffoldTarget =\n !json && this.flags.scaffold ? await getUnavailableScaffoldTarget(cwd) : undefined\n if (unavailableScaffoldTarget) {\n throw new CLIError(\n `./${unavailableScaffoldTarget} is not an empty directory. No project was created.`,\n {\n code:\n unavailableScaffoldTarget === STUDIO_DIR\n ? 'EXISTING_STUDIO_DIRECTORY'\n : 'EXISTING_FRONTEND_DIRECTORY',\n exit: exitCodes.RUNTIME_ERROR,\n suggestions: [\n `Run this command where ./${unavailableScaffoldTarget} does not exist or is an empty directory`,\n `Or run \\`${invoked} --no-scaffold\\` to create the project without changing ./${unavailableScaffoldTarget}`,\n ],\n },\n )\n }\n\n if (!json) {\n renderNewCommandSplash(output.log)\n flow.intro('Setting up your Sanity project.')\n flow.gap()\n\n if (!this.isUnattended()) {\n flow.note(\n `${styleText('cyan', `${invoked} --yes`)} for a non-interactive flow with defaults.`,\n )\n flow.gap()\n }\n }\n\n let displayName = this.args.projectName?.trim()\n if (!displayName && this.isUnattended()) {\n displayName = DEFAULT_PROJECT_NAME\n } else if (!displayName) {\n displayName =\n (\n await input({\n default: DEFAULT_PROJECT_NAME,\n message: 'Project name',\n })\n ).trim() || DEFAULT_PROJECT_NAME\n }\n\n const spin = json ? undefined : flow.spin('Creating your project...')\n let project: MintedProject\n try {\n project = await mintUnclaimedProject({displayName})\n } catch (err) {\n spin?.fail('Creating your project failed.')\n throw err\n }\n\n const recorded = recordUnclaimedProject(project)\n spin?.succeed(`Created \"${displayName}\"`)\n\n if (!json) {\n flow.result(`Project ID: ${styleText('cyan', project.resourceId)}`)\n flow.result(`Dataset: ${styleText('cyan', project.datasetName)} (where your content lives)`)\n flow.result(`Token: ${styleText('cyan', project.token)}`)\n flow.link(project.claimUrl, {label: 'Claim link:'})\n flow.gap()\n flow.highlight(\n `Claim your project by ${styleText('yellow', formatClaimDeadline(project.expiresAt))} to avoid losing it.`,\n )\n flow.gap()\n flow.line('To use the Sanity CLI before claiming use your token by setting')\n flow.command(`SANITY_AUTH_TOKEN=\"${project.token}\" sanity \"command\"`)\n flow.gap()\n flow.note(\n styleText(\n 'dim',\n 'If you are an agent: give this claim URL to the person you are working for. They have ' +\n 'to open it themselves before the deadline.',\n ),\n )\n flow.gap()\n }\n\n const studioUrl =\n `http://localhost:3333/#token=${encodeURIComponent(project.token)}` +\n `&claim=${encodeURIComponent(project.claimUrl)}`\n\n const printStudioInstructions = () => {\n flow.highlight('Start your Studio:')\n flow.gap()\n flow.command(`cd ${STUDIO_DIR} && npx sanity@latest dev`)\n flow.gap()\n flow.link(studioUrl, {label: 'Then open this link:'})\n flow.gap()\n flow.line('The token signs you in: there is no account yet.')\n }\n const printWebsiteInstructions = (packageManager: ScaffoldResult['frontendPackageManager']) => {\n flow.highlight('In a separate terminal, start your website:')\n flow.gap()\n flow.command(`cd ${FRONTEND_DIR} && ${frontendDevCommand(packageManager)}`)\n flow.gap()\n flow.link('http://localhost:3000', {label: 'Then open this link:'})\n }\n\n let scaffold: ScaffoldResult | undefined\n if (!json && this.flags.scaffold) {\n const scaffoldController = new AbortController()\n const abortScaffold = () => scaffoldController.abort(new Error('SIGINT'))\n process.once('SIGINT', abortScaffold)\n try {\n scaffold = await scaffoldProject({\n cancelSignal: scaffoldController.signal,\n dataset: project.datasetName,\n displayName,\n output,\n projectId: project.resourceId,\n telemetry: this.telemetry,\n token: project.token,\n workDir: cwd,\n })\n scaffoldController.signal.throwIfAborted()\n } catch (err) {\n if (\n scaffoldController.signal.aborted ||\n (err instanceof Error && err.message === 'SIGINT')\n ) {\n throw err\n }\n // Scaffolding is best-effort and may leave files or directories behind when it fails.\n // Partial filesystem state does not prove the scaffold is runnable, so report the failure,\n // continue only with the project/token/claim handoff below, and do not attempt cleanup.\n flow.note(`Automatic setup did not finish: ${err instanceof Error ? err.message : err}`)\n flow.line('The project was created. You do not need to create another one.')\n flow.gap()\n } finally {\n process.off('SIGINT', abortScaffold)\n }\n }\n\n if (scaffold) {\n if (scaffold.frontendPath) {\n flow.result('Created two folders')\n flow.line(`./${STUDIO_DIR}: your Studio, where you write and edit content`)\n flow.line(`./${FRONTEND_DIR}: your website, a Next.js app that reads it`)\n flow.gap()\n printStudioInstructions()\n if (scaffold.frontendDependenciesInstalled === false) {\n flow.gap()\n if (scaffold.frontendDependencyError) {\n flow.line(`Installing website dependencies failed: ${scaffold.frontendDependencyError}`)\n flow.gap()\n }\n flow.highlight('Finish installing your website dependencies')\n flow.gap()\n flow.command(\n `cd ${FRONTEND_DIR} && ${frontendInstallCommand(scaffold.frontendPackageManager)}`,\n )\n }\n flow.gap()\n printWebsiteInstructions(scaffold.frontendPackageManager)\n } else if (scaffold.detectedFramework) {\n flow.result(`Created ./${STUDIO_DIR} for your existing ${scaffold.detectedFramework} app`)\n flow.line(`./${STUDIO_DIR}: your Studio, where you write and edit content`)\n flow.line(`Your existing ${scaffold.detectedFramework} frontend was left unchanged.`)\n flow.gap()\n printStudioInstructions()\n } else {\n flow.result(`Created ./${STUDIO_DIR}`)\n flow.line(`./${STUDIO_DIR}: your Studio, where you write and edit content`)\n flow.line(\n `The website was not created: ${scaffold.frontendCreationError ?? 'automatic setup did not finish'}`,\n )\n flow.gap()\n printStudioInstructions()\n }\n flow.gap()\n }\n\n if (recorded === false && !json) {\n flow.note('The local recovery record was not saved.')\n flow.line('Keep the claim URL and access token from this output.')\n flow.gap()\n }\n\n if (!json) {\n if (!scaffold && !this.flags.scaffold) {\n flow.result('Project created without scaffolding')\n flow.line(\n 'No folders or env files were created. Use the project ID and dataset above in your own setup.',\n )\n flow.gap()\n flow.link(studioUrl, {\n label: 'Once a Studio is running on http://localhost:3333, sign in with:',\n })\n flow.gap()\n flow.line('The token signs you in: there is no account yet.')\n flow.gap()\n }\n\n flow.line('Your content is private until you claim, to read it, you need the token.')\n flow.line(\"Treat your token as a password and don't expose it publicly in your app.\")\n flow.gap()\n flow.line(\n 'The claim link and token are printed above but you can recover them ' +\n `with ${styleText('cyan', 'sanity projects unclaimed')} before the timer runs out on ${formatClaimDeadline(project.expiresAt)}.`,\n )\n flow.gap()\n flow.line(project.termsNotice)\n flow.link(project.termsUrl, {label: 'Terms of Service:'})\n flow.gap()\n flow.line('For more information on how claiming works or how to build your app')\n flow.link(SANITY_NEW_URL, {label: 'visit', outro: true})\n }\n\n return toResult(project)\n }\n\n /**\n * Dumps the guide from sanity.new verbatim, so an agent gets the whole document rather than a\n * summary produced by whatever fetched it.\n */\n private async printInstructions(): Promise<void> {\n let instructions: string\n try {\n instructions = await fetchNewInstructions()\n } catch (err) {\n if (err instanceof InstructionsUnavailableError) {\n throw new CLIError(err.message, {\n code: 'INSTRUCTIONS_UNAVAILABLE',\n exit: exitCodes.RUNTIME_ERROR,\n suggestions: [\n `Fetch them directly: curl -sSL ${INSTRUCTIONS_URL}`,\n `Or open ${SANITY_NEW_URL} in a browser`,\n ],\n })\n }\n throw err\n }\n\n this.output.log(`${INSTRUCTIONS_HEADER}\\n\\n${instructions}`)\n }\n}\n"],"names":["styleText","Args","Flags","CLIError","exitCodes","SanityCommand","createFlow","input","FRONTEND_DIR","FRONTEND_ENV_FILE","getUnavailableScaffoldTarget","scaffoldProject","STUDIO_DIR","STUDIO_ENV_FILE","mintUnclaimedProject","fetchNewInstructions","INSTRUCTIONS_URL","InstructionsUnavailableError","formatClaimDeadline","CLAIM_WINDOW_HOURS","SANITY_NEW_URL","renderNewCommandSplash","recordUnclaimedProject","DEFAULT_PROJECT_NAME","HELP_DESCRIPTION_WIDTH","INSTRUCTIONS_HEADER","formatHelpDescription","paragraphs","map","paragraph","lines","line","word","split","length","push","join","FRONTEND_DEV_COMMANDS","bun","manual","npm","pnpm","yarn","frontendDevCommand","packageManager","frontendInstallCommand","toResult","project","apiHost","claimApiUrl","claimToken","claimUrl","dataset","datasetName","expiresAt","projectId","resourceId","terms","notice","termsNotice","url","termsUrl","token","NewCommand","args","projectName","string","description","required","enableJsonFlag","examples","command","flags","instructions","boolean","default","scaffold","allowNo","yes","char","summary","run","output","json","jsonEnabled","flow","log","invoked","config","bin","id","cwd","process","code","exit","USAGE_ERROR","suggestions","printInstructions","undefined","unavailableScaffoldTarget","RUNTIME_ERROR","intro","gap","isUnattended","note","displayName","trim","message","spin","err","fail","recorded","succeed","result","link","label","highlight","studioUrl","encodeURIComponent","printStudioInstructions","printWebsiteInstructions","scaffoldController","AbortController","abortScaffold","abort","Error","once","cancelSignal","signal","telemetry","workDir","throwIfAborted","aborted","off","frontendPath","frontendDependenciesInstalled","frontendDependencyError","frontendPackageManager","detectedFramework","frontendCreationError","outro"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/commands/new.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {CLIError} from '@oclif/core/errors'\nimport {exitCodes} from '@sanity/cli-core'\nimport {SanityCommand} from '@sanity/cli-core/SanityCommand'\nimport {createFlow, input} from '@sanity/cli-core/ux'\n\nimport {\n FRONTEND_DIR,\n FRONTEND_ENV_FILE,\n getUnavailableScaffoldTarget,\n scaffoldProject,\n type ScaffoldResult,\n STUDIO_DIR,\n STUDIO_ENV_FILE,\n} from '../actions/scaffold/scaffoldProject.js'\nimport {type MintedProject, mintUnclaimedProject} from '../services/mintProject.js'\nimport {\n fetchNewInstructions,\n INSTRUCTIONS_URL,\n InstructionsUnavailableError,\n} from '../services/newInstructions.js'\nimport {formatClaimDeadline} from '../util/formatClaimDeadline.js'\nimport {CLAIM_WINDOW_HOURS, SANITY_NEW_URL} from '../util/mintProjectConstants.js'\nimport {renderNewCommandSplash} from '../util/newCommandSplash.js'\nimport {recordUnclaimedProject} from '../util/unclaimedProjects.js'\n\nconst DEFAULT_PROJECT_NAME = 'My Sanity project'\nconst HELP_DESCRIPTION_WIDTH = 78\n\n/**\n * Prepended to the fetched instructions so an agent cannot read this command's success as the\n * project already existing. The only addition to an otherwise verbatim document.\n */\nconst INSTRUCTIONS_HEADER = '# Nothing has been created yet — follow these steps.'\n\nfunction formatHelpDescription(...paragraphs: string[]): string {\n return paragraphs\n .map((paragraph) => {\n const lines: string[] = []\n let line = ''\n\n for (const word of paragraph.split(/\\s+/u)) {\n if (!line || line.length + word.length + 1 <= HELP_DESCRIPTION_WIDTH) {\n line = line ? `${line} ${word}` : word\n } else {\n lines.push(line)\n line = word\n }\n }\n\n if (line) lines.push(line)\n return lines.join('\\n')\n })\n .join('\\n\\n')\n}\n\nconst FRONTEND_DEV_COMMANDS: Record<\n NonNullable<ScaffoldResult['frontendPackageManager']>,\n string\n> = {\n bun: 'bun dev',\n manual: 'npm run dev',\n npm: 'npm run dev',\n pnpm: 'pnpm dev',\n yarn: 'yarn dev',\n}\n\nfunction frontendDevCommand(packageManager: ScaffoldResult['frontendPackageManager']): string {\n return packageManager ? FRONTEND_DEV_COMMANDS[packageManager] : 'npm run dev'\n}\n\nfunction frontendInstallCommand(packageManager: ScaffoldResult['frontendPackageManager']): string {\n switch (packageManager) {\n case 'bun': {\n return 'bun add next-sanity'\n }\n case 'pnpm': {\n return 'pnpm add --save-prod next-sanity'\n }\n case 'yarn': {\n return 'yarn add next-sanity'\n }\n default: {\n return 'npm install next-sanity'\n }\n }\n}\n\nexport interface NewProjectResult {\n apiHost: string\n claimApiUrl: string\n claimToken: string\n claimUrl: string\n dataset: string\n expiresAt: string\n projectId: string\n terms: {\n notice: string\n url: string\n }\n token: string\n}\n\nfunction toResult(project: MintedProject): NewProjectResult {\n return {\n apiHost: project.apiHost,\n claimApiUrl: project.claimApiUrl,\n claimToken: project.claimToken,\n claimUrl: project.claimUrl,\n dataset: project.datasetName,\n expiresAt: project.expiresAt,\n projectId: project.resourceId,\n terms: {notice: project.termsNotice, url: project.termsUrl},\n token: project.token,\n }\n}\n\nexport class NewCommand extends SanityCommand<typeof NewCommand> {\n static override args = {\n projectName: Args.string({\n description: 'Display name for the new project',\n required: false,\n }),\n }\n\n static override description = formatHelpDescription(\n `Sets up two folders here: ./${STUDIO_DIR}, a Studio where you write and edit your content, ` +\n `and ./${FRONTEND_DIR}, a Next.js website that reads it. Both are already connected to your ` +\n 'new project, so you can start them straight away. Use --no-scaffold if you just want the ' +\n 'project and nothing else.',\n `The project is real and works immediately, but it is only yours for ${CLAIM_WINDOW_HOURS} hours. Claim it with ` +\n 'a Sanity account before the deadline and everything you have built stays exactly as it is. ' +\n 'Claiming is free and takes about a minute. Miss the deadline and the project and its ' +\n 'content are deleted.',\n 'Two things to keep private: the claim link, because anyone who opens it becomes the owner, ' +\n `and the access token saved in ./${STUDIO_ENV_FILE}, because it can read and change ` +\n `everything in the project. ./${FRONTEND_ENV_FILE} has only the project ID and dataset. ` +\n 'Keep both env files out of git, and never put the token in code that runs in the browser.',\n 'Run this command with --instructions for the full agent setup guide.',\n )\n\n static override enableJsonFlag = true\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Create a project with a Studio and a website',\n },\n {\n command: '<%= config.bin %> <%= command.id %> \"My New Project\"',\n description: 'Create a project called \"My New Project\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --yes',\n description: 'Create a project without being asked anything',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --no-scaffold',\n description: 'Create the project only, with no Studio or website',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --json',\n description: 'Create a project and print its details as JSON',\n },\n\n {\n command: '<%= config.bin %> <%= command.id %> --instructions',\n description: 'Print the full setup guide for an AI agent, without creating anything',\n },\n ]\n\n static override flags = {\n instructions: Flags.boolean({\n default: false,\n description: `Print the full setup guide from ${SANITY_NEW_URL} and exit, creating nothing`,\n }),\n scaffold: Flags.boolean({\n allowNo: true,\n default: true,\n description: `Set up a Studio in ./${STUDIO_DIR} and a Next.js website in ./${FRONTEND_DIR} (on by default)`,\n }),\n yes: Flags.boolean({\n char: 'y',\n default: false,\n description: `Skip prompts and use defaults (project: \"${DEFAULT_PROJECT_NAME}\")`,\n }),\n }\n\n static override summary = `Create a Sanity project without an account, and claim it within ${CLAIM_WINDOW_HOURS} hours to keep it.`\n\n public async run(): Promise<NewProjectResult | undefined> {\n const {output} = this\n const json = this.jsonEnabled()\n const flow = createFlow(output.log)\n const invoked = [this.config.bin, ...(this.id?.split(':') ?? [])].join(' ')\n const cwd = process.cwd()\n\n // Runs before every precondition and side effect: this flag creates nothing.\n if (this.flags.instructions) {\n // oclif's `exclusive` does not cover the json flag added by enableJsonFlag, so guard it here.\n if (json) {\n throw new CLIError('--instructions cannot be combined with --json.', {\n code: 'INSTRUCTIONS_JSON_CONFLICT',\n exit: exitCodes.USAGE_ERROR,\n suggestions: [\n `Run \\`${invoked} --instructions\\` for the setup guide as markdown`,\n `Or run \\`${invoked} --json\\` to create a project and print its details as JSON`,\n ],\n })\n }\n\n await this.printInstructions()\n return undefined\n }\n\n const unavailableScaffoldTarget =\n !json && this.flags.scaffold ? await getUnavailableScaffoldTarget(cwd) : undefined\n if (unavailableScaffoldTarget) {\n throw new CLIError(\n `./${unavailableScaffoldTarget} is not an empty directory. No project was created.`,\n {\n code:\n unavailableScaffoldTarget === STUDIO_DIR\n ? 'EXISTING_STUDIO_DIRECTORY'\n : 'EXISTING_FRONTEND_DIRECTORY',\n exit: exitCodes.RUNTIME_ERROR,\n suggestions: [\n `Run this command where ./${unavailableScaffoldTarget} does not exist or is an empty directory`,\n `Or run \\`${invoked} --no-scaffold\\` to create the project without changing ./${unavailableScaffoldTarget}`,\n ],\n },\n )\n }\n\n if (!json) {\n renderNewCommandSplash(output.log)\n flow.intro('Setting up your Sanity project.')\n flow.gap()\n\n if (!this.isUnattended()) {\n flow.note(\n `${styleText('cyan', `${invoked} --yes`)} for a non-interactive flow with defaults.`,\n )\n flow.gap()\n }\n }\n\n let displayName = this.args.projectName?.trim()\n if (!displayName && this.isUnattended()) {\n displayName = DEFAULT_PROJECT_NAME\n } else if (!displayName) {\n displayName =\n (\n await input({\n default: DEFAULT_PROJECT_NAME,\n message: 'Project name',\n })\n ).trim() || DEFAULT_PROJECT_NAME\n }\n\n const spin = json ? undefined : flow.spin('Creating your project...')\n let project: MintedProject\n try {\n project = await mintUnclaimedProject({displayName})\n } catch (err) {\n spin?.fail('Creating your project failed.')\n throw err\n }\n\n const recorded = recordUnclaimedProject(project)\n spin?.succeed(`Created \"${displayName}\"`)\n\n if (!json) {\n flow.result(`Project ID: ${styleText('cyan', project.resourceId)}`)\n flow.result(`Dataset: ${styleText('cyan', project.datasetName)} (where your content lives)`)\n flow.result(`Token: ${styleText('cyan', project.token)}`)\n flow.link(project.claimUrl, {label: 'Claim link:'})\n flow.gap()\n flow.highlight(\n `Claim your project by ${styleText('yellow', formatClaimDeadline(project.expiresAt))} to avoid losing it.`,\n )\n flow.gap()\n flow.line('To use the Sanity CLI before claiming use your token by setting')\n flow.command(`SANITY_AUTH_TOKEN=\"${project.token}\" sanity \"command\"`)\n flow.gap()\n flow.note(\n styleText(\n 'dim',\n 'If you are an agent: give this claim URL to the person you are working for. They have ' +\n 'to open it themselves before the deadline.',\n ),\n )\n flow.gap()\n }\n\n const studioUrl =\n `http://localhost:3333/#token=${encodeURIComponent(project.token)}` +\n `&claim=${encodeURIComponent(project.claimUrl)}`\n\n const printStudioInstructions = () => {\n flow.highlight('Start your Studio:')\n flow.gap()\n flow.command(`cd ${STUDIO_DIR} && npx sanity@latest dev`)\n flow.gap()\n flow.link(studioUrl, {label: 'Then open this link:'})\n flow.gap()\n flow.line('The token signs you in: there is no account yet.')\n }\n const printWebsiteInstructions = (packageManager: ScaffoldResult['frontendPackageManager']) => {\n flow.highlight('In a separate terminal, start your website:')\n flow.gap()\n flow.command(`cd ${FRONTEND_DIR} && ${frontendDevCommand(packageManager)}`)\n flow.gap()\n flow.link('http://localhost:3000', {label: 'Then open this link:'})\n }\n\n let scaffold: ScaffoldResult | undefined\n if (!json && this.flags.scaffold) {\n const scaffoldController = new AbortController()\n const abortScaffold = () => scaffoldController.abort(new Error('SIGINT'))\n process.once('SIGINT', abortScaffold)\n try {\n scaffold = await scaffoldProject({\n cancelSignal: scaffoldController.signal,\n dataset: project.datasetName,\n displayName,\n output,\n projectId: project.resourceId,\n telemetry: this.telemetry,\n token: project.token,\n workDir: cwd,\n })\n scaffoldController.signal.throwIfAborted()\n } catch (err) {\n if (\n scaffoldController.signal.aborted ||\n (err instanceof Error && err.message === 'SIGINT')\n ) {\n throw err\n }\n // Scaffolding is best-effort and may leave files or directories behind when it fails.\n // Partial filesystem state does not prove the scaffold is runnable, so report the failure,\n // continue only with the project/token/claim handoff below, and do not attempt cleanup.\n flow.note(`Automatic setup did not finish: ${err instanceof Error ? err.message : err}`)\n flow.line('The project was created. You do not need to create another one.')\n flow.gap()\n } finally {\n process.off('SIGINT', abortScaffold)\n }\n }\n\n if (scaffold) {\n if (scaffold.frontendPath) {\n flow.result('Created two folders')\n flow.line(`./${STUDIO_DIR}: your Studio, where you write and edit content`)\n flow.line(`./${FRONTEND_DIR}: your website, a Next.js app that reads it`)\n flow.gap()\n printStudioInstructions()\n if (scaffold.frontendDependenciesInstalled === false) {\n flow.gap()\n if (scaffold.frontendDependencyError) {\n flow.line(`Installing website dependencies failed: ${scaffold.frontendDependencyError}`)\n flow.gap()\n }\n flow.highlight('Finish installing your website dependencies')\n flow.gap()\n flow.command(\n `cd ${FRONTEND_DIR} && ${frontendInstallCommand(scaffold.frontendPackageManager)}`,\n )\n }\n flow.gap()\n printWebsiteInstructions(scaffold.frontendPackageManager)\n } else if (scaffold.detectedFramework) {\n flow.result(`Created ./${STUDIO_DIR} for your existing ${scaffold.detectedFramework} app`)\n flow.line(`./${STUDIO_DIR}: your Studio, where you write and edit content`)\n flow.line(`Your existing ${scaffold.detectedFramework} frontend was left unchanged.`)\n flow.gap()\n printStudioInstructions()\n } else {\n flow.result(`Created ./${STUDIO_DIR}`)\n flow.line(`./${STUDIO_DIR}: your Studio, where you write and edit content`)\n flow.line(\n `The website was not created: ${scaffold.frontendCreationError ?? 'automatic setup did not finish'}`,\n )\n flow.gap()\n printStudioInstructions()\n }\n flow.gap()\n }\n\n if (recorded === false && !json) {\n flow.note('The local recovery record was not saved.')\n flow.line('Keep the claim URL and access token from this output.')\n flow.gap()\n }\n\n if (!json) {\n if (!scaffold && !this.flags.scaffold) {\n flow.result('Project created without scaffolding')\n flow.line(\n 'No folders or env files were created. Use the project ID and dataset above in your own setup.',\n )\n flow.gap()\n flow.link(studioUrl, {\n label: 'Once a Studio is running on http://localhost:3333, sign in with:',\n })\n flow.gap()\n flow.line('The token signs you in: there is no account yet.')\n flow.gap()\n }\n\n flow.line(\"Treat your token as a password and don't expose it publicly in your app.\")\n flow.gap()\n flow.line(\n 'The claim link and token are printed above but you can recover them ' +\n `with ${styleText('cyan', 'sanity projects unclaimed')} before the timer runs out on ${formatClaimDeadline(project.expiresAt)}.`,\n )\n flow.gap()\n flow.line(project.termsNotice)\n flow.link(project.termsUrl, {label: 'Terms of Service:'})\n flow.gap()\n flow.line('For more information on how claiming works or how to build your app')\n flow.link(SANITY_NEW_URL, {label: 'visit', outro: true})\n }\n\n return toResult(project)\n }\n\n /**\n * Dumps the guide from sanity.new verbatim, so an agent gets the whole document rather than a\n * summary produced by whatever fetched it.\n */\n private async printInstructions(): Promise<void> {\n let instructions: string\n try {\n instructions = await fetchNewInstructions()\n } catch (err) {\n if (err instanceof InstructionsUnavailableError) {\n throw new CLIError(err.message, {\n code: 'INSTRUCTIONS_UNAVAILABLE',\n exit: exitCodes.RUNTIME_ERROR,\n suggestions: [\n `Fetch them directly: curl -sSL ${INSTRUCTIONS_URL}`,\n `Or open ${SANITY_NEW_URL} in a browser`,\n ],\n })\n }\n throw err\n }\n\n this.output.log(`${INSTRUCTIONS_HEADER}\\n\\n${instructions}`)\n }\n}\n"],"names":["styleText","Args","Flags","CLIError","exitCodes","SanityCommand","createFlow","input","FRONTEND_DIR","FRONTEND_ENV_FILE","getUnavailableScaffoldTarget","scaffoldProject","STUDIO_DIR","STUDIO_ENV_FILE","mintUnclaimedProject","fetchNewInstructions","INSTRUCTIONS_URL","InstructionsUnavailableError","formatClaimDeadline","CLAIM_WINDOW_HOURS","SANITY_NEW_URL","renderNewCommandSplash","recordUnclaimedProject","DEFAULT_PROJECT_NAME","HELP_DESCRIPTION_WIDTH","INSTRUCTIONS_HEADER","formatHelpDescription","paragraphs","map","paragraph","lines","line","word","split","length","push","join","FRONTEND_DEV_COMMANDS","bun","manual","npm","pnpm","yarn","frontendDevCommand","packageManager","frontendInstallCommand","toResult","project","apiHost","claimApiUrl","claimToken","claimUrl","dataset","datasetName","expiresAt","projectId","resourceId","terms","notice","termsNotice","url","termsUrl","token","NewCommand","args","projectName","string","description","required","enableJsonFlag","examples","command","flags","instructions","boolean","default","scaffold","allowNo","yes","char","summary","run","output","json","jsonEnabled","flow","log","invoked","config","bin","id","cwd","process","code","exit","USAGE_ERROR","suggestions","printInstructions","undefined","unavailableScaffoldTarget","RUNTIME_ERROR","intro","gap","isUnattended","note","displayName","trim","message","spin","err","fail","recorded","succeed","result","link","label","highlight","studioUrl","encodeURIComponent","printStudioInstructions","printWebsiteInstructions","scaffoldController","AbortController","abortScaffold","abort","Error","once","cancelSignal","signal","telemetry","workDir","throwIfAborted","aborted","off","frontendPath","frontendDependenciesInstalled","frontendDependencyError","frontendPackageManager","detectedFramework","frontendCreationError","outro"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { stat } from 'node:fs/promises';
2
2
  import { styleText } from 'node:util';
3
3
  import { Flags } from '@oclif/core';
4
4
  import { CLIError } from '@oclif/core/errors';
5
- import { SanityCommand } from '@sanity/cli-core';
5
+ import { exitCodes, SanityCommand } from '@sanity/cli-core';
6
6
  import { spinner } from '@sanity/cli-core/ux';
7
7
  import { configDefinition, readConfig, runTypegenGenerate, runTypegenWatcher, TypegenWatchModeTrace, TypesGeneratedTrace } from '@sanity/codegen';
8
8
  import omit from 'lodash-es/omit.js';
@@ -71,13 +71,13 @@ export class TypegenGenerateCommand extends SanityCommand {
71
71
  if (err instanceof Error && 'code' in err && err.code === 'ENOENT' && configPath) {
72
72
  spin.fail();
73
73
  this.error(`Typegen config file not found: ${configPath}`, {
74
- exit: 1
74
+ exit: exitCodes.RUNTIME_ERROR
75
75
  });
76
76
  }
77
77
  if (err instanceof Error && 'code' in err && err.code !== 'ENOENT') {
78
78
  spin.fail();
79
79
  this.error(`Error when checking if typegen config file exists: ${legacyConfigPath}`, {
80
- exit: 1
80
+ exit: exitCodes.RUNTIME_ERROR
81
81
  });
82
82
  }
83
83
  }
@@ -118,7 +118,7 @@ export class TypegenGenerateCommand extends SanityCommand {
118
118
  if (err instanceof CLIError) throw err;
119
119
  spin.fail();
120
120
  this.error(`An error occurred during config loading: ${err}`, {
121
- exit: 1
121
+ exit: exitCodes.RUNTIME_ERROR
122
122
  });
123
123
  }
124
124
  }
@@ -151,7 +151,7 @@ export class TypegenGenerateCommand extends SanityCommand {
151
151
  }
152
152
  trace.error(error instanceof Error ? error : new Error(String(error)));
153
153
  this.error(`${error instanceof Error ? error.message : 'Unknown error'}`, {
154
- exit: 1
154
+ exit: exitCodes.RUNTIME_ERROR
155
155
  });
156
156
  }
157
157
  }
@@ -213,7 +213,7 @@ export class TypegenGenerateCommand extends SanityCommand {
213
213
  }
214
214
  trace.error(error instanceof Error ? error : new Error(String(error)));
215
215
  this.error(`${error instanceof Error ? error.message : 'Unknown error'}`, {
216
- exit: 1
216
+ exit: exitCodes.RUNTIME_ERROR
217
217
  });
218
218
  }
219
219
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/typegen/generate.ts"],"sourcesContent":["import {stat} from 'node:fs/promises'\nimport {styleText} from 'node:util'\n\nimport {Flags} from '@oclif/core'\nimport {CLIError} from '@oclif/core/errors'\nimport {SanityCommand} from '@sanity/cli-core'\nimport {spinner, type SpinnerInstance} from '@sanity/cli-core/ux'\nimport {\n configDefinition,\n readConfig,\n runTypegenGenerate,\n runTypegenWatcher,\n type TypeGenConfig,\n TypegenWatchModeTrace,\n TypesGeneratedTrace,\n} from '@sanity/codegen'\nimport omit from 'lodash-es/omit.js'\nimport once from 'lodash-es/once.js'\n\nimport {createTypegenProgressRenderer} from '../../actions/typegen/renderTypegenProgress.js'\n\nconst description = `Sanity TypeGen\n\n${styleText('bold', 'Configuration:')}\nThis command can utilize configuration settings defined in a \\`sanity-typegen.json\\` file. These settings include:\n\n- \"path\": Specifies a glob pattern to locate your TypeScript or JavaScript files.\n Default: \"./src/**/*.{ts,tsx,js,jsx}\"\n\n- \"schema\": Defines the path to your Sanity schema file. This file should be generated using the \\`sanity schema extract\\` command.\n Default: \"schema.json\"\n\n- \"generates\": Indicates the path where the generated TypeScript type definitions will be saved.\n Default: \"./sanity.types.ts\"\n\nThe default configuration values listed above are used if not overridden in your \\`sanity-typegen.json\\` configuration file. To customize the behavior of the type generation, adjust these properties in the configuration file according to your project's needs.\n\n${styleText('bold', 'Note:')}\n- The \\`sanity schema extract\\` command is a prerequisite for extracting your Sanity Studio schema into a \\`schema.json\\` file, which is then used by the \\`sanity typegen generate\\` command to generate type definitions.`.trim()\n\nexport class TypegenGenerateCommand extends SanityCommand<typeof TypegenGenerateCommand> {\n static override description = description\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: `Generate TypeScript type definitions from a Sanity Studio schema extracted using the \\`sanity schema extract\\` command.`,\n },\n ]\n\n static override flags = {\n 'config-path': Flags.string({\n description:\n '[Default: sanity-typegen.json] Specifies the path to the typegen configuration file. This file should be a JSON file that contains settings for the type generation process.',\n }),\n watch: Flags.boolean({\n default: false,\n description: '[Default: false] Run the typegen in watch mode',\n }),\n }\n\n static override hiddenAliases: string[] = ['typegen:generate']\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(TypegenGenerateCommand)\n\n if (flags.watch) {\n await this.runWatcher()\n return\n }\n\n await this.runSingle()\n }\n\n private async getConfig(): Promise<{\n config: TypeGenConfig\n path?: string\n type: 'cli' | 'legacy'\n workDir: string\n }> {\n const spin = spinner({}).start('Loading config…')\n\n try {\n const {flags} = await this.parse(TypegenGenerateCommand)\n const rootDir = await this.getProjectRoot()\n const config = await this.getCliConfig()\n\n const configPath = flags['config-path']\n const workDir = rootDir.directory\n\n const legacyConfigPath = configPath || 'sanity-typegen.json'\n let hasLegacyConfig = false\n\n try {\n const file = await stat(legacyConfigPath)\n hasLegacyConfig = file.isFile()\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ENOENT' && configPath) {\n spin.fail()\n this.error(`Typegen config file not found: ${configPath}`, {exit: 1})\n }\n\n if (err instanceof Error && 'code' in err && err.code !== 'ENOENT') {\n spin.fail()\n this.error(`Error when checking if typegen config file exists: ${legacyConfigPath}`, {\n exit: 1,\n })\n }\n }\n\n if (config?.typegen && hasLegacyConfig) {\n spin.warn(\n styleText(\n 'yellow',\n `You've specified typegen in your Sanity CLI config, but also have a typegen config.\n\n The config from the Sanity CLI config is used.\n `,\n ),\n )\n\n return {\n config: configDefinition.parse(config.typegen || {}),\n path: rootDir.path,\n type: 'cli',\n workDir,\n }\n }\n\n if (hasLegacyConfig) {\n spin.warn(\n styleText(\n 'yellow',\n `The separate typegen config has been deprecated. Use \\`typegen\\` in the sanity CLI config instead.\n\n See: https://www.sanity.io/docs/help/configuring-typegen-in-sanity-cli-config`,\n ),\n )\n return {\n config: await readConfig(legacyConfigPath),\n path: legacyConfigPath,\n type: 'legacy',\n workDir,\n }\n }\n\n spin.succeed(`Config loaded from sanity.cli.ts`)\n\n return {\n config: configDefinition.parse(config.typegen || {}),\n path: rootDir.path,\n type: 'cli',\n workDir,\n }\n } catch (err) {\n // The config-file checks above already reported a user-facing error via\n // `this.error()` (an oclif CLIError). Re-throw those as-is instead of\n // wrapping them a second time and failing the spinner twice.\n if (err instanceof CLIError) throw err\n spin.fail()\n this.error(`An error occurred during config loading: ${err}`, {exit: 1})\n }\n }\n\n private async runSingle(): Promise<void> {\n const trace = this.telemetry.trace(TypesGeneratedTrace)\n let spin: SpinnerInstance | undefined\n\n try {\n const {config: typegenConfig, type: typegenConfigMethod, workDir} = await this.getConfig()\n trace.start()\n\n spin = spinner({}).start('Loading schema…')\n const result = await runTypegenGenerate({\n config: typegenConfig,\n onProgress: createTypegenProgressRenderer(spin, {\n formatGeneratedCode: typegenConfig.formatGeneratedCode,\n generates: typegenConfig.generates,\n schema: typegenConfig.schema,\n }),\n workDir,\n })\n\n const traceStats = omit(result, 'code', 'duration')\n\n trace.log({\n configMethod: typegenConfigMethod,\n configOverloadClientMethods: typegenConfig.overloadClientMethods,\n ...traceStats,\n })\n trace.complete()\n } catch (error) {\n if (spin?.isSpinning) {\n spin.fail()\n }\n trace.error(error instanceof Error ? error : new Error(String(error)))\n this.error(`${error instanceof Error ? error.message : 'Unknown error'}`, {exit: 1})\n }\n }\n\n private async runWatcher(): Promise<void> {\n const trace = this.telemetry.trace(TypegenWatchModeTrace)\n let spin: SpinnerInstance | undefined\n\n try {\n const {config: typegenConfig, workDir} = await this.getConfig()\n trace.start()\n\n let resolve: () => void = () => {}\n const promise = new Promise<void>((res) => {\n resolve = res\n })\n\n const watchSpin = spinner({}).start('Loading schema…')\n spin = watchSpin\n const rendererContext = {\n formatGeneratedCode: typegenConfig.formatGeneratedCode,\n generates: typegenConfig.generates,\n schema: typegenConfig.schema,\n }\n let renderProgress = createTypegenProgressRenderer(watchSpin, rendererContext)\n\n const typegenWatcher = runTypegenWatcher({\n config: typegenConfig,\n onProgress: (event) => {\n // 'schemaLoaded' is the first event of every generation cycle; the\n // renderer accumulates per-run state, so start each cycle fresh.\n if (event.type === 'schemaLoaded') {\n renderProgress = createTypegenProgressRenderer(watchSpin, rendererContext)\n }\n renderProgress(event)\n },\n workDir,\n })\n\n const stop = once(async () => {\n process.off('SIGINT', stop)\n process.off('SIGTERM', stop)\n\n if (watchSpin.isSpinning) {\n watchSpin.stop()\n }\n\n trace.log({\n step: 'stopped',\n ...typegenWatcher.getStats(),\n })\n trace.complete()\n\n try {\n await typegenWatcher.stop()\n } catch {\n // We're shutting down; a failure to close the watcher shouldn't hang\n // the process or surface as an unhandled rejection.\n }\n resolve()\n })\n\n process.on('SIGINT', stop)\n process.on('SIGTERM', stop)\n\n await promise\n } catch (error) {\n if (spin?.isSpinning) {\n spin.fail()\n }\n trace.error(error instanceof Error ? error : new Error(String(error)))\n this.error(`${error instanceof Error ? error.message : 'Unknown error'}`, {exit: 1})\n }\n }\n}\n"],"names":["stat","styleText","Flags","CLIError","SanityCommand","spinner","configDefinition","readConfig","runTypegenGenerate","runTypegenWatcher","TypegenWatchModeTrace","TypesGeneratedTrace","omit","once","createTypegenProgressRenderer","description","trim","TypegenGenerateCommand","examples","command","flags","string","watch","boolean","default","hiddenAliases","run","parse","runWatcher","runSingle","getConfig","spin","start","rootDir","getProjectRoot","config","getCliConfig","configPath","workDir","directory","legacyConfigPath","hasLegacyConfig","file","isFile","err","Error","code","fail","error","exit","typegen","warn","path","type","succeed","trace","telemetry","typegenConfig","typegenConfigMethod","result","onProgress","formatGeneratedCode","generates","schema","traceStats","log","configMethod","configOverloadClientMethods","overloadClientMethods","complete","isSpinning","String","message","resolve","promise","Promise","res","watchSpin","rendererContext","renderProgress","typegenWatcher","event","stop","process","off","step","getStats","on"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/typegen/generate.ts"],"sourcesContent":["import {stat} from 'node:fs/promises'\nimport {styleText} from 'node:util'\n\nimport {Flags} from '@oclif/core'\nimport {CLIError} from '@oclif/core/errors'\nimport {exitCodes, SanityCommand} from '@sanity/cli-core'\nimport {spinner, type SpinnerInstance} from '@sanity/cli-core/ux'\nimport {\n configDefinition,\n readConfig,\n runTypegenGenerate,\n runTypegenWatcher,\n type TypeGenConfig,\n TypegenWatchModeTrace,\n TypesGeneratedTrace,\n} from '@sanity/codegen'\nimport omit from 'lodash-es/omit.js'\nimport once from 'lodash-es/once.js'\n\nimport {createTypegenProgressRenderer} from '../../actions/typegen/renderTypegenProgress.js'\n\nconst description = `Sanity TypeGen\n\n${styleText('bold', 'Configuration:')}\nThis command can utilize configuration settings defined in a \\`sanity-typegen.json\\` file. These settings include:\n\n- \"path\": Specifies a glob pattern to locate your TypeScript or JavaScript files.\n Default: \"./src/**/*.{ts,tsx,js,jsx}\"\n\n- \"schema\": Defines the path to your Sanity schema file. This file should be generated using the \\`sanity schema extract\\` command.\n Default: \"schema.json\"\n\n- \"generates\": Indicates the path where the generated TypeScript type definitions will be saved.\n Default: \"./sanity.types.ts\"\n\nThe default configuration values listed above are used if not overridden in your \\`sanity-typegen.json\\` configuration file. To customize the behavior of the type generation, adjust these properties in the configuration file according to your project's needs.\n\n${styleText('bold', 'Note:')}\n- The \\`sanity schema extract\\` command is a prerequisite for extracting your Sanity Studio schema into a \\`schema.json\\` file, which is then used by the \\`sanity typegen generate\\` command to generate type definitions.`.trim()\n\nexport class TypegenGenerateCommand extends SanityCommand<typeof TypegenGenerateCommand> {\n static override description = description\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: `Generate TypeScript type definitions from a Sanity Studio schema extracted using the \\`sanity schema extract\\` command.`,\n },\n ]\n\n static override flags = {\n 'config-path': Flags.string({\n description:\n '[Default: sanity-typegen.json] Specifies the path to the typegen configuration file. This file should be a JSON file that contains settings for the type generation process.',\n }),\n watch: Flags.boolean({\n default: false,\n description: '[Default: false] Run the typegen in watch mode',\n }),\n }\n\n static override hiddenAliases: string[] = ['typegen:generate']\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(TypegenGenerateCommand)\n\n if (flags.watch) {\n await this.runWatcher()\n return\n }\n\n await this.runSingle()\n }\n\n private async getConfig(): Promise<{\n config: TypeGenConfig\n path?: string\n type: 'cli' | 'legacy'\n workDir: string\n }> {\n const spin = spinner({}).start('Loading config…')\n\n try {\n const {flags} = await this.parse(TypegenGenerateCommand)\n const rootDir = await this.getProjectRoot()\n const config = await this.getCliConfig()\n\n const configPath = flags['config-path']\n const workDir = rootDir.directory\n\n const legacyConfigPath = configPath || 'sanity-typegen.json'\n let hasLegacyConfig = false\n\n try {\n const file = await stat(legacyConfigPath)\n hasLegacyConfig = file.isFile()\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ENOENT' && configPath) {\n spin.fail()\n this.error(`Typegen config file not found: ${configPath}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (err instanceof Error && 'code' in err && err.code !== 'ENOENT') {\n spin.fail()\n this.error(`Error when checking if typegen config file exists: ${legacyConfigPath}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n if (config?.typegen && hasLegacyConfig) {\n spin.warn(\n styleText(\n 'yellow',\n `You've specified typegen in your Sanity CLI config, but also have a typegen config.\n\n The config from the Sanity CLI config is used.\n `,\n ),\n )\n\n return {\n config: configDefinition.parse(config.typegen || {}),\n path: rootDir.path,\n type: 'cli',\n workDir,\n }\n }\n\n if (hasLegacyConfig) {\n spin.warn(\n styleText(\n 'yellow',\n `The separate typegen config has been deprecated. Use \\`typegen\\` in the sanity CLI config instead.\n\n See: https://www.sanity.io/docs/help/configuring-typegen-in-sanity-cli-config`,\n ),\n )\n return {\n config: await readConfig(legacyConfigPath),\n path: legacyConfigPath,\n type: 'legacy',\n workDir,\n }\n }\n\n spin.succeed(`Config loaded from sanity.cli.ts`)\n\n return {\n config: configDefinition.parse(config.typegen || {}),\n path: rootDir.path,\n type: 'cli',\n workDir,\n }\n } catch (err) {\n // The config-file checks above already reported a user-facing error via\n // `this.error()` (an oclif CLIError). Re-throw those as-is instead of\n // wrapping them a second time and failing the spinner twice.\n if (err instanceof CLIError) throw err\n spin.fail()\n this.error(`An error occurred during config loading: ${err}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async runSingle(): Promise<void> {\n const trace = this.telemetry.trace(TypesGeneratedTrace)\n let spin: SpinnerInstance | undefined\n\n try {\n const {config: typegenConfig, type: typegenConfigMethod, workDir} = await this.getConfig()\n trace.start()\n\n spin = spinner({}).start('Loading schema…')\n const result = await runTypegenGenerate({\n config: typegenConfig,\n onProgress: createTypegenProgressRenderer(spin, {\n formatGeneratedCode: typegenConfig.formatGeneratedCode,\n generates: typegenConfig.generates,\n schema: typegenConfig.schema,\n }),\n workDir,\n })\n\n const traceStats = omit(result, 'code', 'duration')\n\n trace.log({\n configMethod: typegenConfigMethod,\n configOverloadClientMethods: typegenConfig.overloadClientMethods,\n ...traceStats,\n })\n trace.complete()\n } catch (error) {\n if (spin?.isSpinning) {\n spin.fail()\n }\n trace.error(error instanceof Error ? error : new Error(String(error)))\n this.error(`${error instanceof Error ? error.message : 'Unknown error'}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async runWatcher(): Promise<void> {\n const trace = this.telemetry.trace(TypegenWatchModeTrace)\n let spin: SpinnerInstance | undefined\n\n try {\n const {config: typegenConfig, workDir} = await this.getConfig()\n trace.start()\n\n let resolve: () => void = () => {}\n const promise = new Promise<void>((res) => {\n resolve = res\n })\n\n const watchSpin = spinner({}).start('Loading schema…')\n spin = watchSpin\n const rendererContext = {\n formatGeneratedCode: typegenConfig.formatGeneratedCode,\n generates: typegenConfig.generates,\n schema: typegenConfig.schema,\n }\n let renderProgress = createTypegenProgressRenderer(watchSpin, rendererContext)\n\n const typegenWatcher = runTypegenWatcher({\n config: typegenConfig,\n onProgress: (event) => {\n // 'schemaLoaded' is the first event of every generation cycle; the\n // renderer accumulates per-run state, so start each cycle fresh.\n if (event.type === 'schemaLoaded') {\n renderProgress = createTypegenProgressRenderer(watchSpin, rendererContext)\n }\n renderProgress(event)\n },\n workDir,\n })\n\n const stop = once(async () => {\n process.off('SIGINT', stop)\n process.off('SIGTERM', stop)\n\n if (watchSpin.isSpinning) {\n watchSpin.stop()\n }\n\n trace.log({\n step: 'stopped',\n ...typegenWatcher.getStats(),\n })\n trace.complete()\n\n try {\n await typegenWatcher.stop()\n } catch {\n // We're shutting down; a failure to close the watcher shouldn't hang\n // the process or surface as an unhandled rejection.\n }\n resolve()\n })\n\n process.on('SIGINT', stop)\n process.on('SIGTERM', stop)\n\n await promise\n } catch (error) {\n if (spin?.isSpinning) {\n spin.fail()\n }\n trace.error(error instanceof Error ? error : new Error(String(error)))\n this.error(`${error instanceof Error ? error.message : 'Unknown error'}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n}\n"],"names":["stat","styleText","Flags","CLIError","exitCodes","SanityCommand","spinner","configDefinition","readConfig","runTypegenGenerate","runTypegenWatcher","TypegenWatchModeTrace","TypesGeneratedTrace","omit","once","createTypegenProgressRenderer","description","trim","TypegenGenerateCommand","examples","command","flags","string","watch","boolean","default","hiddenAliases","run","parse","runWatcher","runSingle","getConfig","spin","start","rootDir","getProjectRoot","config","getCliConfig","configPath","workDir","directory","legacyConfigPath","hasLegacyConfig","file","isFile","err","Error","code","fail","error","exit","RUNTIME_ERROR","typegen","warn","path","type","succeed","trace","telemetry","typegenConfig","typegenConfigMethod","result","onProgress","formatGeneratedCode","generates","schema","traceStats","log","configMethod","configOverloadClientMethods","overloadClientMethods","complete","isSpinning","String","message","resolve","promise","Promise","res","watchSpin","rendererContext","renderProgress","typegenWatcher","event","stop","process","off","step","getStats","on"],"mappings":"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"}
@@ -8,7 +8,7 @@ export async function uploadAsset({ assetType, body, contentType, dataset, filen
8
8
  apiVersion: ASSETS_API_VERSION,
9
9
  dataset,
10
10
  projectId,
11
- requestTagPrefix: 'sanity.assets.upload',
11
+ requestTagPrefix: 'sanity.cli.assets.upload',
12
12
  requireUser: true
13
13
  });
14
14
  signal?.throwIfAborted();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/services/assets.ts"],"sourcesContent":["import {type Readable, Transform} from 'node:stream'\n\nimport {getProjectCliClient} from '@sanity/cli-core'\nimport {filter, lastValueFrom, map, Observable, race} from 'rxjs'\n\nexport const ASSETS_API_VERSION = 'v2024-06-24'\n\nexport type AssetType = 'file' | 'image'\n\ninterface UploadAssetOptions {\n assetType: AssetType\n body: Readable\n dataset: string\n filename: string\n fileSize: number\n projectId: string\n\n contentType?: string\n onProgress?: (percent: number) => void\n signal?: AbortSignal\n}\n\nexport async function uploadAsset({\n assetType,\n body,\n contentType,\n dataset,\n filename,\n fileSize,\n onProgress,\n projectId,\n signal,\n}: UploadAssetOptions) {\n signal?.throwIfAborted()\n\n const client = await getProjectCliClient({\n apiVersion: ASSETS_API_VERSION,\n dataset,\n projectId,\n requestTagPrefix: 'sanity.assets.upload',\n requireUser: true,\n })\n signal?.throwIfAborted()\n\n let uploadedBytes = 0\n const uploadStream = new Transform({\n transform(chunk: Buffer, _encoding, callback) {\n uploadedBytes += chunk.length\n onProgress?.((uploadedBytes / fileSize) * 100)\n callback(null, chunk)\n },\n })\n body.on('error', (error) => uploadStream.destroy(error)).pipe(uploadStream)\n\n const response$ = client.observable.assets\n .upload(assetType, uploadStream, {\n ...(contentType ? {contentType} : {}),\n filename,\n tag: 'asset.upload',\n })\n .pipe(\n filter((event) => event.type === 'response'),\n map((event) => event.body.document),\n )\n\n if (!signal) return lastValueFrom(response$)\n\n const abort$ = new Observable<never>((subscriber) => {\n const abortUpload = () => {\n body.destroy()\n uploadStream.destroy()\n subscriber.error(signal.reason instanceof Error ? signal.reason : new Error('SIGINT'))\n }\n\n signal.addEventListener('abort', abortUpload, {once: true})\n return () => signal.removeEventListener('abort', abortUpload)\n })\n\n return lastValueFrom(race(response$, abort$))\n}\n"],"names":["Transform","getProjectCliClient","filter","lastValueFrom","map","Observable","race","ASSETS_API_VERSION","uploadAsset","assetType","body","contentType","dataset","filename","fileSize","onProgress","projectId","signal","throwIfAborted","client","apiVersion","requestTagPrefix","requireUser","uploadedBytes","uploadStream","transform","chunk","_encoding","callback","length","on","error","destroy","pipe","response$","observable","assets","upload","tag","event","type","document","abort$","subscriber","abortUpload","reason","Error","addEventListener","once","removeEventListener"],"mappings":"AAAA,SAAuBA,SAAS,QAAO,cAAa;AAEpD,SAAQC,mBAAmB,QAAO,mBAAkB;AACpD,SAAQC,MAAM,EAAEC,aAAa,EAAEC,GAAG,EAAEC,UAAU,EAAEC,IAAI,QAAO,OAAM;AAEjE,OAAO,MAAMC,qBAAqB,cAAa;AAiB/C,OAAO,eAAeC,YAAY,EAChCC,SAAS,EACTC,IAAI,EACJC,WAAW,EACXC,OAAO,EACPC,QAAQ,EACRC,QAAQ,EACRC,UAAU,EACVC,SAAS,EACTC,MAAM,EACa;IACnBA,QAAQC;IAER,MAAMC,SAAS,MAAMlB,oBAAoB;QACvCmB,YAAYb;QACZK;QACAI;QACAK,kBAAkB;QAClBC,aAAa;IACf;IACAL,QAAQC;IAER,IAAIK,gBAAgB;IACpB,MAAMC,eAAe,IAAIxB,UAAU;QACjCyB,WAAUC,KAAa,EAAEC,SAAS,EAAEC,QAAQ;YAC1CL,iBAAiBG,MAAMG,MAAM;YAC7Bd,aAAa,AAACQ,gBAAgBT,WAAY;YAC1Cc,SAAS,MAAMF;QACjB;IACF;IACAhB,KAAKoB,EAAE,CAAC,SAAS,CAACC,QAAUP,aAAaQ,OAAO,CAACD,QAAQE,IAAI,CAACT;IAE9D,MAAMU,YAAYf,OAAOgB,UAAU,CAACC,MAAM,CACvCC,MAAM,CAAC5B,WAAWe,cAAc;QAC/B,GAAIb,cAAc;YAACA;QAAW,IAAI,CAAC,CAAC;QACpCE;QACAyB,KAAK;IACP,GACCL,IAAI,CACH/B,OAAO,CAACqC,QAAUA,MAAMC,IAAI,KAAK,aACjCpC,IAAI,CAACmC,QAAUA,MAAM7B,IAAI,CAAC+B,QAAQ;IAGtC,IAAI,CAACxB,QAAQ,OAAOd,cAAc+B;IAElC,MAAMQ,SAAS,IAAIrC,WAAkB,CAACsC;QACpC,MAAMC,cAAc;YAClBlC,KAAKsB,OAAO;YACZR,aAAaQ,OAAO;YACpBW,WAAWZ,KAAK,CAACd,OAAO4B,MAAM,YAAYC,QAAQ7B,OAAO4B,MAAM,GAAG,IAAIC,MAAM;QAC9E;QAEA7B,OAAO8B,gBAAgB,CAAC,SAASH,aAAa;YAACI,MAAM;QAAI;QACzD,OAAO,IAAM/B,OAAOgC,mBAAmB,CAAC,SAASL;IACnD;IAEA,OAAOzC,cAAcG,KAAK4B,WAAWQ;AACvC"}
1
+ {"version":3,"sources":["../../src/services/assets.ts"],"sourcesContent":["import {type Readable, Transform} from 'node:stream'\n\nimport {getProjectCliClient} from '@sanity/cli-core'\nimport {filter, lastValueFrom, map, Observable, race} from 'rxjs'\n\nexport const ASSETS_API_VERSION = 'v2024-06-24'\n\nexport type AssetType = 'file' | 'image'\n\ninterface UploadAssetOptions {\n assetType: AssetType\n body: Readable\n dataset: string\n filename: string\n fileSize: number\n projectId: string\n\n contentType?: string\n onProgress?: (percent: number) => void\n signal?: AbortSignal\n}\n\nexport async function uploadAsset({\n assetType,\n body,\n contentType,\n dataset,\n filename,\n fileSize,\n onProgress,\n projectId,\n signal,\n}: UploadAssetOptions) {\n signal?.throwIfAborted()\n\n const client = await getProjectCliClient({\n apiVersion: ASSETS_API_VERSION,\n dataset,\n projectId,\n requestTagPrefix: 'sanity.cli.assets.upload',\n requireUser: true,\n })\n signal?.throwIfAborted()\n\n let uploadedBytes = 0\n const uploadStream = new Transform({\n transform(chunk: Buffer, _encoding, callback) {\n uploadedBytes += chunk.length\n onProgress?.((uploadedBytes / fileSize) * 100)\n callback(null, chunk)\n },\n })\n body.on('error', (error) => uploadStream.destroy(error)).pipe(uploadStream)\n\n const response$ = client.observable.assets\n .upload(assetType, uploadStream, {\n ...(contentType ? {contentType} : {}),\n filename,\n tag: 'asset.upload',\n })\n .pipe(\n filter((event) => event.type === 'response'),\n map((event) => event.body.document),\n )\n\n if (!signal) return lastValueFrom(response$)\n\n const abort$ = new Observable<never>((subscriber) => {\n const abortUpload = () => {\n body.destroy()\n uploadStream.destroy()\n subscriber.error(signal.reason instanceof Error ? signal.reason : new Error('SIGINT'))\n }\n\n signal.addEventListener('abort', abortUpload, {once: true})\n return () => signal.removeEventListener('abort', abortUpload)\n })\n\n return lastValueFrom(race(response$, abort$))\n}\n"],"names":["Transform","getProjectCliClient","filter","lastValueFrom","map","Observable","race","ASSETS_API_VERSION","uploadAsset","assetType","body","contentType","dataset","filename","fileSize","onProgress","projectId","signal","throwIfAborted","client","apiVersion","requestTagPrefix","requireUser","uploadedBytes","uploadStream","transform","chunk","_encoding","callback","length","on","error","destroy","pipe","response$","observable","assets","upload","tag","event","type","document","abort$","subscriber","abortUpload","reason","Error","addEventListener","once","removeEventListener"],"mappings":"AAAA,SAAuBA,SAAS,QAAO,cAAa;AAEpD,SAAQC,mBAAmB,QAAO,mBAAkB;AACpD,SAAQC,MAAM,EAAEC,aAAa,EAAEC,GAAG,EAAEC,UAAU,EAAEC,IAAI,QAAO,OAAM;AAEjE,OAAO,MAAMC,qBAAqB,cAAa;AAiB/C,OAAO,eAAeC,YAAY,EAChCC,SAAS,EACTC,IAAI,EACJC,WAAW,EACXC,OAAO,EACPC,QAAQ,EACRC,QAAQ,EACRC,UAAU,EACVC,SAAS,EACTC,MAAM,EACa;IACnBA,QAAQC;IAER,MAAMC,SAAS,MAAMlB,oBAAoB;QACvCmB,YAAYb;QACZK;QACAI;QACAK,kBAAkB;QAClBC,aAAa;IACf;IACAL,QAAQC;IAER,IAAIK,gBAAgB;IACpB,MAAMC,eAAe,IAAIxB,UAAU;QACjCyB,WAAUC,KAAa,EAAEC,SAAS,EAAEC,QAAQ;YAC1CL,iBAAiBG,MAAMG,MAAM;YAC7Bd,aAAa,AAACQ,gBAAgBT,WAAY;YAC1Cc,SAAS,MAAMF;QACjB;IACF;IACAhB,KAAKoB,EAAE,CAAC,SAAS,CAACC,QAAUP,aAAaQ,OAAO,CAACD,QAAQE,IAAI,CAACT;IAE9D,MAAMU,YAAYf,OAAOgB,UAAU,CAACC,MAAM,CACvCC,MAAM,CAAC5B,WAAWe,cAAc;QAC/B,GAAIb,cAAc;YAACA;QAAW,IAAI,CAAC,CAAC;QACpCE;QACAyB,KAAK;IACP,GACCL,IAAI,CACH/B,OAAO,CAACqC,QAAUA,MAAMC,IAAI,KAAK,aACjCpC,IAAI,CAACmC,QAAUA,MAAM7B,IAAI,CAAC+B,QAAQ;IAGtC,IAAI,CAACxB,QAAQ,OAAOd,cAAc+B;IAElC,MAAMQ,SAAS,IAAIrC,WAAkB,CAACsC;QACpC,MAAMC,cAAc;YAClBlC,KAAKsB,OAAO;YACZR,aAAaQ,OAAO;YACpBW,WAAWZ,KAAK,CAACd,OAAO4B,MAAM,YAAYC,QAAQ7B,OAAO4B,MAAM,GAAG,IAAIC,MAAM;QAC9E;QAEA7B,OAAO8B,gBAAgB,CAAC,SAASH,aAAa;YAACI,MAAM;QAAI;QACzD,OAAO,IAAM/B,OAAOgC,mBAAmB,CAAC,SAASL;IACnD;IAEA,OAAOzC,cAAcG,KAAK4B,WAAWQ;AACvC"}