@sanity/cli 8.6.0 → 8.8.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 (103) hide show
  1. package/README.md +918 -40
  2. package/dist/actions/api/distillApiRoutes.js +1 -1
  3. package/dist/actions/api/distillApiRoutes.js.map +1 -1
  4. package/dist/actions/api/resolveEndpoint.js +1 -1
  5. package/dist/actions/api/resolveEndpoint.js.map +1 -1
  6. package/dist/actions/backup/archiveDir.js +7 -3
  7. package/dist/actions/backup/archiveDir.js.map +1 -1
  8. package/dist/actions/context/resolveOrganizationId.js +17 -0
  9. package/dist/actions/context/resolveOrganizationId.js.map +1 -0
  10. package/dist/actions/context/waitForJob.js +24 -0
  11. package/dist/actions/context/waitForJob.js.map +1 -0
  12. package/dist/actions/context/watchJob.js +32 -0
  13. package/dist/actions/context/watchJob.js.map +1 -0
  14. package/dist/actions/deploy/deployApp.js +6 -6
  15. package/dist/actions/deploy/deployApp.js.map +1 -1
  16. package/dist/actions/deploy/deployStudio.js +6 -6
  17. package/dist/actions/deploy/deployStudio.js.map +1 -1
  18. package/dist/actions/exec/execScript.js +6 -18
  19. package/dist/actions/exec/execScript.js.map +1 -1
  20. package/dist/actions/exec/runScript.worker.js +21 -0
  21. package/dist/actions/exec/runScript.worker.js.map +1 -0
  22. package/dist/actions/init/initAction.js +1 -1
  23. package/dist/actions/init/initAction.js.map +1 -1
  24. package/dist/actions/media/importMedia.js +4 -2
  25. package/dist/actions/media/importMedia.js.map +1 -1
  26. package/dist/commands/backups/download.js +8 -17
  27. package/dist/commands/backups/download.js.map +1 -1
  28. package/dist/commands/backups/list.js +1 -1
  29. package/dist/commands/backups/list.js.map +1 -1
  30. package/dist/commands/context/build.js +111 -0
  31. package/dist/commands/context/build.js.map +1 -0
  32. package/dist/commands/context/create.js +106 -0
  33. package/dist/commands/context/create.js.map +1 -0
  34. package/dist/commands/context/delete.js +68 -0
  35. package/dist/commands/context/delete.js.map +1 -0
  36. package/dist/commands/context/get.js +95 -0
  37. package/dist/commands/context/get.js.map +1 -0
  38. package/dist/commands/context/imports/create.js +270 -0
  39. package/dist/commands/context/imports/create.js.map +1 -0
  40. package/dist/commands/context/imports/delete.js +73 -0
  41. package/dist/commands/context/imports/delete.js.map +1 -0
  42. package/dist/commands/context/imports/download.js +65 -0
  43. package/dist/commands/context/imports/download.js.map +1 -0
  44. package/dist/commands/context/imports/get.js +93 -0
  45. package/dist/commands/context/imports/get.js.map +1 -0
  46. package/dist/commands/context/imports/list.js +105 -0
  47. package/dist/commands/context/imports/list.js.map +1 -0
  48. package/dist/commands/context/jobs/get.js +90 -0
  49. package/dist/commands/context/jobs/get.js.map +1 -0
  50. package/dist/commands/context/list.js +109 -0
  51. package/dist/commands/context/list.js.map +1 -0
  52. package/dist/commands/context/refresh.js +46 -0
  53. package/dist/commands/context/refresh.js.map +1 -0
  54. package/dist/commands/context/update.js +127 -0
  55. package/dist/commands/context/update.js.map +1 -0
  56. package/dist/commands/datasets/alias/delete.js +4 -9
  57. package/dist/commands/datasets/alias/delete.js.map +1 -1
  58. package/dist/commands/datasets/alias/unlink.js +4 -9
  59. package/dist/commands/datasets/alias/unlink.js.map +1 -1
  60. package/dist/commands/datasets/copy.js +1 -1
  61. package/dist/commands/datasets/copy.js.map +1 -1
  62. package/dist/commands/datasets/delete.js +4 -9
  63. package/dist/commands/datasets/delete.js.map +1 -1
  64. package/dist/commands/graphql/undeploy.js +4 -9
  65. package/dist/commands/graphql/undeploy.js.map +1 -1
  66. package/dist/commands/init.js +1 -1
  67. package/dist/commands/init.js.map +1 -1
  68. package/dist/commands/media/create-aspect.js +5 -6
  69. package/dist/commands/media/create-aspect.js.map +1 -1
  70. package/dist/commands/media/delete-aspect.js +7 -23
  71. package/dist/commands/media/delete-aspect.js.map +1 -1
  72. package/dist/commands/media/deploy-aspect.js +4 -9
  73. package/dist/commands/media/deploy-aspect.js.map +1 -1
  74. package/dist/commands/media/export.js +3 -7
  75. package/dist/commands/media/export.js.map +1 -1
  76. package/dist/commands/media/import.js +3 -7
  77. package/dist/commands/media/import.js.map +1 -1
  78. package/dist/commands/organizations/create.js +4 -9
  79. package/dist/commands/organizations/create.js.map +1 -1
  80. package/dist/commands/schemas/delete.js +3 -8
  81. package/dist/commands/schemas/delete.js.map +1 -1
  82. package/dist/commands/tokens/delete.js +4 -7
  83. package/dist/commands/tokens/delete.js.map +1 -1
  84. package/dist/commands/users/invite.js +8 -18
  85. package/dist/commands/users/invite.js.map +1 -1
  86. package/dist/exports/index.js +1 -1
  87. package/dist/exports/index.js.map +1 -1
  88. package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js +18 -0
  89. package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js.map +1 -1
  90. package/dist/generated/apiRoutes.js +11 -9
  91. package/dist/generated/apiRoutes.js.map +1 -1
  92. package/dist/prompts/promptForOrganization.js +19 -0
  93. package/dist/prompts/promptForOrganization.js.map +1 -0
  94. package/dist/services/context.js +132 -0
  95. package/dist/services/context.js.map +1 -0
  96. package/dist/util/extractDocumentsFromNdjsonOrTarball.js.map +1 -1
  97. package/dist/util/sharedFlags.js +24 -0
  98. package/dist/util/sharedFlags.js.map +1 -1
  99. package/oclif.config.js +1 -0
  100. package/oclif.manifest.json +1931 -1133
  101. package/package.json +20 -26
  102. package/dist/util/dates.js +0 -125
  103. package/dist/util/dates.js.map +0 -1
@@ -1,6 +1,7 @@
1
1
  import { Args, Flags } from '@oclif/core';
2
2
  import { CLIError } from '@oclif/core/errors';
3
3
  import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
4
+ import { requiredWhenUnattended } from '@sanity/cli-core/flags';
4
5
  import { input } from '@sanity/cli-core/ux';
5
6
  import { processAliasName } from '../../../actions/dataset/processAliasName.js';
6
7
  import { validateDatasetAliasName } from '../../../actions/dataset/validateDatasetAliasName.js';
@@ -36,10 +37,9 @@ export class UnlinkAliasCommand extends SanityCommand {
36
37
  description: 'Project ID to unlink dataset alias in',
37
38
  semantics: 'override'
38
39
  }),
39
- force: Flags.boolean({
40
- description: 'Skip confirmation prompt and unlink immediately',
41
- required: false
42
- })
40
+ force: requiredWhenUnattended(Flags.boolean({
41
+ description: 'Skip confirmation prompt and unlink immediately'
42
+ }))
43
43
  };
44
44
  static hiddenAliases = [
45
45
  'dataset:alias:unlink'
@@ -100,11 +100,6 @@ export class UnlinkAliasCommand extends SanityCommand {
100
100
  if (force) {
101
101
  this.warn(`'--force' used: skipping confirmation, unlinking alias "${displayName}"`);
102
102
  } else {
103
- if (this.isUnattended()) {
104
- this.error('Unlinking a dataset alias requires confirmation. Re-run with `--force`.', {
105
- exit: exitCodes.USAGE_ERROR
106
- });
107
- }
108
103
  await this.confirmUnlink(linkedAlias.datasetName);
109
104
  }
110
105
  const result = await unlinkAlias(projectId, apiName);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/commands/datasets/alias/unlink.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {CLIError} from '@oclif/core/errors'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {input} from '@sanity/cli-core/ux'\n\nimport {processAliasName} from '../../../actions/dataset/processAliasName.js'\nimport {validateDatasetAliasName} from '../../../actions/dataset/validateDatasetAliasName.js'\nimport {promptForDatasetAliasName} from '../../../prompts/promptForDatasetAliasName.js'\nimport {promptForProject} from '../../../prompts/promptForProject.js'\nimport {listAliases, unlinkAlias} from '../../../services/datasetAliases.js'\nimport {getProjectIdFlag} from '../../../util/sharedFlags.js'\n\nconst unlinkAliasDebug = subdebug('dataset:alias:unlink')\n\nexport class UnlinkAliasCommand extends SanityCommand<typeof UnlinkAliasCommand> {\n static override args = {\n aliasName: Args.string({\n description: 'Dataset alias name to unlink',\n required: false,\n }),\n }\n\n static override description = 'Unlink a dataset alias from its dataset in the project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Unlink an alias with interactive selection',\n },\n {\n command: '<%= config.bin %> <%= command.id %> conference',\n description: 'Unlink alias \"conference\" with confirmation prompt',\n },\n {\n command: '<%= config.bin %> <%= command.id %> conference --force',\n description: 'Unlink alias \"conference\" without confirmation prompt',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to unlink dataset alias in',\n semantics: 'override',\n }),\n force: Flags.boolean({\n description: 'Skip confirmation prompt and unlink immediately',\n required: false,\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:alias:unlink']\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(UnlinkAliasCommand)\n const {force} = flags\n\n if (!args.aliasName && this.isUnattended()) {\n this.error('Dataset alias name is required. Pass it as the `<aliasName>` argument.', {\n exit: exitCodes.USAGE_ERROR,\n })\n }\n\n if (args.aliasName) {\n const {apiName} = processAliasName(args.aliasName)\n const nameError = validateDatasetAliasName(apiName)\n if (nameError) {\n this.error(nameError, {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: 'update', permission: 'sanity.project.datasets'},\n ],\n }),\n })\n\n try {\n const aliasNameInput = args.aliasName || (await promptForDatasetAliasName())\n const {apiName, displayName} = processAliasName(aliasNameInput)\n\n const nameError = validateDatasetAliasName(apiName)\n if (nameError) {\n this.error(nameError, {exit: exitCodes.USAGE_ERROR})\n }\n\n const aliases = await listAliases(projectId)\n\n // get the current alias from the remote alias list\n const linkedAlias = aliases.find((elem) => elem.name === apiName)\n if (!linkedAlias) {\n this.error(`Dataset alias \"${displayName}\" does not exist`, {exit: exitCodes.RUNTIME_ERROR})\n }\n\n if (!linkedAlias.datasetName) {\n this.error(`Dataset alias \"${displayName}\" is not linked to a dataset`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (force) {\n this.warn(`'--force' used: skipping confirmation, unlinking alias \"${displayName}\"`)\n } else {\n if (this.isUnattended()) {\n this.error('Unlinking a dataset alias requires confirmation. Re-run with `--force`.', {\n exit: exitCodes.USAGE_ERROR,\n })\n }\n await this.confirmUnlink(linkedAlias.datasetName)\n }\n\n const result = await unlinkAlias(projectId, apiName)\n this.log(`Dataset alias ${displayName} unlinked from ${result.datasetName} successfully`)\n } catch (error) {\n if (error instanceof CLIError) throw error\n unlinkAliasDebug('Error unlinking dataset alias', error)\n this.error(\n `Dataset alias unlink failed: ${error instanceof Error ? error.message : String(error)}`,\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n }\n\n private async confirmUnlink(datasetName: string): Promise<void> {\n await input({\n message: `Are you ABSOLUTELY sure you want to unlink this alias from the \"${datasetName}\" dataset?\\n Type YES/NO:`,\n validate: (input) => {\n const response = input.toLowerCase().trim()\n return (\n response === 'yes' || 'Type YES to confirm or Ctrl + C to cancel dataset alias unlink.'\n )\n },\n })\n }\n}\n"],"names":["Args","Flags","CLIError","exitCodes","SanityCommand","subdebug","input","processAliasName","validateDatasetAliasName","promptForDatasetAliasName","promptForProject","listAliases","unlinkAlias","getProjectIdFlag","unlinkAliasDebug","UnlinkAliasCommand","args","aliasName","string","description","required","examples","command","flags","semantics","force","boolean","hiddenAliases","run","parse","isUnattended","error","exit","USAGE_ERROR","apiName","nameError","projectId","getProjectId","fallback","requiredPermissions","grant","permission","aliasNameInput","displayName","aliases","linkedAlias","find","elem","name","RUNTIME_ERROR","datasetName","warn","confirmUnlink","result","log","Error","message","String","validate","response","toLowerCase","trim"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/commands/datasets/alias/unlink.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {CLIError} from '@oclif/core/errors'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {requiredWhenUnattended} from '@sanity/cli-core/flags'\nimport {input} from '@sanity/cli-core/ux'\n\nimport {processAliasName} from '../../../actions/dataset/processAliasName.js'\nimport {validateDatasetAliasName} from '../../../actions/dataset/validateDatasetAliasName.js'\nimport {promptForDatasetAliasName} from '../../../prompts/promptForDatasetAliasName.js'\nimport {promptForProject} from '../../../prompts/promptForProject.js'\nimport {listAliases, unlinkAlias} from '../../../services/datasetAliases.js'\nimport {getProjectIdFlag} from '../../../util/sharedFlags.js'\n\nconst unlinkAliasDebug = subdebug('dataset:alias:unlink')\n\nexport class UnlinkAliasCommand extends SanityCommand<typeof UnlinkAliasCommand> {\n static override args = {\n aliasName: Args.string({\n description: 'Dataset alias name to unlink',\n required: false,\n }),\n }\n\n static override description = 'Unlink a dataset alias from its dataset in the project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Unlink an alias with interactive selection',\n },\n {\n command: '<%= config.bin %> <%= command.id %> conference',\n description: 'Unlink alias \"conference\" with confirmation prompt',\n },\n {\n command: '<%= config.bin %> <%= command.id %> conference --force',\n description: 'Unlink alias \"conference\" without confirmation prompt',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to unlink dataset alias in',\n semantics: 'override',\n }),\n force: requiredWhenUnattended(\n Flags.boolean({\n description: 'Skip confirmation prompt and unlink immediately',\n }),\n ),\n }\n\n static override hiddenAliases: string[] = ['dataset:alias:unlink']\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(UnlinkAliasCommand)\n const {force} = flags\n\n if (!args.aliasName && this.isUnattended()) {\n this.error('Dataset alias name is required. Pass it as the `<aliasName>` argument.', {\n exit: exitCodes.USAGE_ERROR,\n })\n }\n\n if (args.aliasName) {\n const {apiName} = processAliasName(args.aliasName)\n const nameError = validateDatasetAliasName(apiName)\n if (nameError) {\n this.error(nameError, {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: 'update', permission: 'sanity.project.datasets'},\n ],\n }),\n })\n\n try {\n const aliasNameInput = args.aliasName || (await promptForDatasetAliasName())\n const {apiName, displayName} = processAliasName(aliasNameInput)\n\n const nameError = validateDatasetAliasName(apiName)\n if (nameError) {\n this.error(nameError, {exit: exitCodes.USAGE_ERROR})\n }\n\n const aliases = await listAliases(projectId)\n\n // get the current alias from the remote alias list\n const linkedAlias = aliases.find((elem) => elem.name === apiName)\n if (!linkedAlias) {\n this.error(`Dataset alias \"${displayName}\" does not exist`, {exit: exitCodes.RUNTIME_ERROR})\n }\n\n if (!linkedAlias.datasetName) {\n this.error(`Dataset alias \"${displayName}\" is not linked to a dataset`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (force) {\n this.warn(`'--force' used: skipping confirmation, unlinking alias \"${displayName}\"`)\n } else {\n await this.confirmUnlink(linkedAlias.datasetName)\n }\n\n const result = await unlinkAlias(projectId, apiName)\n this.log(`Dataset alias ${displayName} unlinked from ${result.datasetName} successfully`)\n } catch (error) {\n if (error instanceof CLIError) throw error\n unlinkAliasDebug('Error unlinking dataset alias', error)\n this.error(\n `Dataset alias unlink failed: ${error instanceof Error ? error.message : String(error)}`,\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n }\n\n private async confirmUnlink(datasetName: string): Promise<void> {\n await input({\n message: `Are you ABSOLUTELY sure you want to unlink this alias from the \"${datasetName}\" dataset?\\n Type YES/NO:`,\n validate: (input) => {\n const response = input.toLowerCase().trim()\n return (\n response === 'yes' || 'Type YES to confirm or Ctrl + C to cancel dataset alias unlink.'\n )\n },\n })\n }\n}\n"],"names":["Args","Flags","CLIError","exitCodes","SanityCommand","subdebug","requiredWhenUnattended","input","processAliasName","validateDatasetAliasName","promptForDatasetAliasName","promptForProject","listAliases","unlinkAlias","getProjectIdFlag","unlinkAliasDebug","UnlinkAliasCommand","args","aliasName","string","description","required","examples","command","flags","semantics","force","boolean","hiddenAliases","run","parse","isUnattended","error","exit","USAGE_ERROR","apiName","nameError","projectId","getProjectId","fallback","requiredPermissions","grant","permission","aliasNameInput","displayName","aliases","linkedAlias","find","elem","name","RUNTIME_ERROR","datasetName","warn","confirmUnlink","result","log","Error","message","String","validate","response","toLowerCase","trim"],"mappings":"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"}
@@ -2,6 +2,7 @@ import { styleText } from 'node:util';
2
2
  import { Args, Flags } from '@oclif/core';
3
3
  import { exit } from '@oclif/core/errors';
4
4
  import { exitCodes } from '@sanity/cli-core';
5
+ import { formatDuration, formatTimeAgo } from '@sanity/cli-core/dates';
5
6
  import { subdebug } from '@sanity/cli-core/debug';
6
7
  import { getCliExecutionContext } from '@sanity/cli-core/executionContext';
7
8
  import { SanityCommand } from '@sanity/cli-core/SanityCommand';
@@ -11,7 +12,6 @@ import { promptForDataset } from '../../prompts/promptForDataset.js';
11
12
  import { promptForDatasetName } from '../../prompts/promptForDatasetName.js';
12
13
  import { promptForProject } from '../../prompts/promptForProject.js';
13
14
  import { copyDataset, followCopyJobProgress, listDatasetCopyJobs, listDatasets } from '../../services/datasets.js';
14
- import { formatDuration, formatTimeAgo } from '../../util/dates.js';
15
15
  import { formatCliErrorMessages } from '../../util/formatCliErrorMessages.js';
16
16
  import { Table } from '../../util/responsiveTable.js';
17
17
  import { getProjectIdFlag } from '../../util/sharedFlags.js';
@@ -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'\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
+ {"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 {formatDuration, formatTimeAgo} from '@sanity/cli-core/dates'\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 {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","formatDuration","formatTimeAgo","subdebug","getCliExecutionContext","SanityCommand","spinner","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","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,7 @@
1
1
  import { styleText } from 'node:util';
2
2
  import { Args, Flags } from '@oclif/core';
3
3
  import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
4
+ import { requiredWhenUnattended } from '@sanity/cli-core/flags';
4
5
  import { input, logSymbols } from '@sanity/cli-core/ux';
5
6
  import { validateDatasetName } from '../../actions/dataset/validateDatasetName.js';
6
7
  import { promptForProject } from '../../prompts/promptForProject.js';
@@ -31,10 +32,9 @@ export class DeleteDatasetCommand extends SanityCommand {
31
32
  description: 'Project ID to delete dataset from',
32
33
  semantics: 'override'
33
34
  }),
34
- force: Flags.boolean({
35
- description: 'Do not prompt for delete confirmation - forcefully delete',
36
- required: false
37
- })
35
+ force: requiredWhenUnattended(Flags.boolean({
36
+ description: 'Do not prompt for delete confirmation - forcefully delete'
37
+ }))
38
38
  };
39
39
  static hiddenAliases = [
40
40
  'dataset:delete'
@@ -62,11 +62,6 @@ export class DeleteDatasetCommand extends SanityCommand {
62
62
  if (force) {
63
63
  this.warn(`'--force' used: skipping confirmation, deleting dataset "${datasetName}"`);
64
64
  } else {
65
- if (this.isUnattended()) {
66
- this.error('Dataset deletion requires confirmation. Re-run with `--force`.', {
67
- exit: exitCodes.USAGE_ERROR
68
- });
69
- }
70
65
  try {
71
66
  const project = await getProjectById(projectId);
72
67
  this.log(styleText('yellow', `${logSymbols.warning} Deleting dataset "${styleText([
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/datasets/delete.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {input, logSymbols} from '@sanity/cli-core/ux'\n\nimport {validateDatasetName} from '../../actions/dataset/validateDatasetName.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {deleteDataset} from '../../services/datasets.js'\nimport {getProjectById} from '../../services/projects.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst deleteDatasetDebug = subdebug('dataset:delete')\n\nexport class DeleteDatasetCommand extends SanityCommand<typeof DeleteDatasetCommand> {\n static override args = {\n datasetName: Args.string({\n description: 'Dataset name to delete',\n required: true,\n }),\n }\n\n static override description = 'Delete a dataset from the project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset',\n description: 'Delete a specific dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset --force',\n description: 'Delete a specific dataset without confirmation',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to delete dataset from',\n semantics: 'override',\n }),\n force: Flags.boolean({\n description: 'Do not prompt for delete confirmation - forcefully delete',\n required: false,\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:delete']\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(DeleteDatasetCommand)\n const {force} = flags\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'delete', permission: 'sanity.project.datasets'}],\n }),\n })\n\n const datasetName = args.datasetName\n\n const dsError = validateDatasetName(datasetName)\n if (dsError) {\n this.error(dsError, {exit: exitCodes.USAGE_ERROR})\n }\n\n if (force) {\n this.warn(`'--force' used: skipping confirmation, deleting dataset \"${datasetName}\"`)\n } else {\n if (this.isUnattended()) {\n this.error('Dataset deletion requires confirmation. Re-run with `--force`.', {\n exit: exitCodes.USAGE_ERROR,\n })\n }\n try {\n const project = await getProjectById(projectId)\n this.log(\n styleText(\n 'yellow',\n `${logSymbols.warning} Deleting dataset \"${styleText(['bold', 'underline'], datasetName)}\" from project \"${styleText(['bold', 'underline'], project.displayName)} (${styleText(['bold', 'underline'], project.id)})\"\\n`,\n ),\n )\n } catch (error) {\n const err = error instanceof Error ? error : new Error(`${error}`)\n deleteDatasetDebug(`Error getting project ${projectId}`, err)\n this.error(`Project retrieval failed: ${err.message}`, {exit: exitCodes.RUNTIME_ERROR})\n }\n\n await input({\n message: `Delete dataset \"${datasetName}\"?\\n Type the dataset name to confirm:`,\n validate: (input) => {\n const trimmed = input.trim()\n return (\n trimmed === datasetName ||\n `Dataset name doesn't match. Enter \"${datasetName}\" or press Ctrl+C to cancel.`\n )\n },\n })\n }\n\n try {\n await deleteDataset({datasetName, projectId})\n this.log('Dataset deleted successfully')\n } catch (error) {\n const err = error instanceof Error ? error : new Error(`${error}`)\n deleteDatasetDebug(`Error deleting dataset ${datasetName}`, err)\n this.error(`Dataset deletion failed: ${err.message}`, {exit: exitCodes.RUNTIME_ERROR})\n }\n }\n}\n"],"names":["styleText","Args","Flags","exitCodes","SanityCommand","subdebug","input","logSymbols","validateDatasetName","promptForProject","deleteDataset","getProjectById","getProjectIdFlag","deleteDatasetDebug","DeleteDatasetCommand","args","datasetName","string","description","required","examples","command","flags","semantics","force","boolean","hiddenAliases","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","dsError","error","exit","USAGE_ERROR","warn","isUnattended","project","log","warning","displayName","id","err","Error","message","RUNTIME_ERROR","validate","trimmed","trim"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/datasets/delete.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {requiredWhenUnattended} from '@sanity/cli-core/flags'\nimport {input, logSymbols} from '@sanity/cli-core/ux'\n\nimport {validateDatasetName} from '../../actions/dataset/validateDatasetName.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {deleteDataset} from '../../services/datasets.js'\nimport {getProjectById} from '../../services/projects.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst deleteDatasetDebug = subdebug('dataset:delete')\n\nexport class DeleteDatasetCommand extends SanityCommand<typeof DeleteDatasetCommand> {\n static override args = {\n datasetName: Args.string({\n description: 'Dataset name to delete',\n required: true,\n }),\n }\n\n static override description = 'Delete a dataset from the project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset',\n description: 'Delete a specific dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset --force',\n description: 'Delete a specific dataset without confirmation',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to delete dataset from',\n semantics: 'override',\n }),\n force: requiredWhenUnattended(\n Flags.boolean({\n description: 'Do not prompt for delete confirmation - forcefully delete',\n }),\n ),\n }\n\n static override hiddenAliases: string[] = ['dataset:delete']\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(DeleteDatasetCommand)\n const {force} = flags\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'delete', permission: 'sanity.project.datasets'}],\n }),\n })\n\n const datasetName = args.datasetName\n\n const dsError = validateDatasetName(datasetName)\n if (dsError) {\n this.error(dsError, {exit: exitCodes.USAGE_ERROR})\n }\n\n if (force) {\n this.warn(`'--force' used: skipping confirmation, deleting dataset \"${datasetName}\"`)\n } else {\n try {\n const project = await getProjectById(projectId)\n this.log(\n styleText(\n 'yellow',\n `${logSymbols.warning} Deleting dataset \"${styleText(['bold', 'underline'], datasetName)}\" from project \"${styleText(['bold', 'underline'], project.displayName)} (${styleText(['bold', 'underline'], project.id)})\"\\n`,\n ),\n )\n } catch (error) {\n const err = error instanceof Error ? error : new Error(`${error}`)\n deleteDatasetDebug(`Error getting project ${projectId}`, err)\n this.error(`Project retrieval failed: ${err.message}`, {exit: exitCodes.RUNTIME_ERROR})\n }\n\n await input({\n message: `Delete dataset \"${datasetName}\"?\\n Type the dataset name to confirm:`,\n validate: (input) => {\n const trimmed = input.trim()\n return (\n trimmed === datasetName ||\n `Dataset name doesn't match. Enter \"${datasetName}\" or press Ctrl+C to cancel.`\n )\n },\n })\n }\n\n try {\n await deleteDataset({datasetName, projectId})\n this.log('Dataset deleted successfully')\n } catch (error) {\n const err = error instanceof Error ? error : new Error(`${error}`)\n deleteDatasetDebug(`Error deleting dataset ${datasetName}`, err)\n this.error(`Dataset deletion failed: ${err.message}`, {exit: exitCodes.RUNTIME_ERROR})\n }\n }\n}\n"],"names":["styleText","Args","Flags","exitCodes","SanityCommand","subdebug","requiredWhenUnattended","input","logSymbols","validateDatasetName","promptForProject","deleteDataset","getProjectById","getProjectIdFlag","deleteDatasetDebug","DeleteDatasetCommand","args","datasetName","string","description","required","examples","command","flags","semantics","force","boolean","hiddenAliases","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","dsError","error","exit","USAGE_ERROR","warn","project","log","warning","displayName","id","err","Error","message","RUNTIME_ERROR","validate","trimmed","trim"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { Flags } from '@oclif/core';
2
2
  import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
3
+ import { requiredWhenUnattended } from '@sanity/cli-core/flags';
3
4
  import { confirm } from '@sanity/cli-core/ux';
4
5
  import { getGraphQLAPIs } from '../../actions/graphql/getGraphQLAPIs.js';
5
6
  import { promptForProject } from '../../prompts/promptForProject.js';
@@ -51,10 +52,9 @@ export class Undeploy extends SanityCommand {
51
52
  description: 'Dataset to undeploy GraphQL API from',
52
53
  semantics: 'override'
53
54
  }),
54
- force: Flags.boolean({
55
- description: 'Skip confirmation prompt',
56
- required: false
57
- }),
55
+ force: requiredWhenUnattended(Flags.boolean({
56
+ description: 'Skip confirmation prompt'
57
+ })),
58
58
  project: Flags.string({
59
59
  deprecated: {
60
60
  to: 'project-id'
@@ -123,11 +123,6 @@ export class Undeploy extends SanityCommand {
123
123
  }
124
124
  // Confirm deletion unless --force is used
125
125
  if (!force) {
126
- if (this.isUnattended()) {
127
- this.error('GraphQL API undeploy requires confirmation. Pass `--force` to continue.', {
128
- exit: exitCodes.USAGE_ERROR
129
- });
130
- }
131
126
  const confirmMessage = tag === 'default' ? `Delete the GraphQL API for dataset "${dataset}" in project ${projectId}?` : `Delete the GraphQL API for dataset "${dataset}" in project ${projectId} with tag "${tag}"?`;
132
127
  const confirmed = await confirm({
133
128
  default: false,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/graphql/undeploy.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {confirm} from '@sanity/cli-core/ux'\n\nimport {getGraphQLAPIs} from '../../actions/graphql/getGraphQLAPIs.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {deleteGraphQLAPI} from '../../services/graphql.js'\nimport {getDatasetFlag, getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst undeployGraphqlDebug = subdebug('graphql:undeploy')\n\nexport class Undeploy extends SanityCommand<typeof Undeploy> {\n static override description = 'Remove a deployed GraphQL API'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Undeploy GraphQL API for current project and dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --api ios',\n description: 'Undeploy API with ID \"ios\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --dataset staging',\n description: 'Undeploy GraphQL API for staging dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --dataset staging --tag next',\n description: 'Undeploy GraphQL API for staging dataset with \"next\" tag',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --force',\n description: 'Undeploy GraphQL API without confirmation prompt',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --project-id abc123 --dataset production',\n description: 'Undeploy GraphQL API for a specific project and dataset',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to undeploy GraphQL API from',\n semantics: 'override',\n }),\n api: Flags.string({\n description: 'Undeploy API with this ID',\n exclusive: ['project-id', 'project'],\n required: false,\n }),\n ...getDatasetFlag({description: 'Dataset to undeploy GraphQL API from', semantics: 'override'}),\n force: Flags.boolean({\n description: 'Skip confirmation prompt',\n required: false,\n }),\n project: Flags.string({\n deprecated: {to: 'project-id'},\n description: 'Project ID to delete GraphQL API for',\n hidden: true,\n required: false,\n }),\n tag: Flags.string({\n default: 'default',\n description: 'Tag to undeploy GraphQL API from',\n required: false,\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(Undeploy)\n const {api: apiFlag, dataset: datasetFlag, force, tag: tagFlag} = flags\n\n let projectId: string | undefined\n let dataset = datasetFlag\n let tag = tagFlag\n\n // If specifying --api, use it for the flags not provided\n if (apiFlag) {\n const workDir = (await this.getProjectRoot()).directory\n const apiDefs = await getGraphQLAPIs(workDir)\n const apiDef = apiDefs.find((def) => def.id === apiFlag)\n\n if (!apiDef) {\n this.error(`GraphQL API \"${apiFlag}\" not found`, {exit: exitCodes.RUNTIME_ERROR})\n }\n\n projectId = apiDef.projectId\n\n if (dataset && dataset !== apiDef.dataset) {\n this.warn(`Both --api and --dataset specified, using --dataset ${dataset}`)\n } else {\n dataset = apiDef.dataset\n }\n\n if (tag && tag !== 'default' && apiDef.tag && tag !== apiDef.tag) {\n this.warn(`Both --api and --tag specified, using --tag ${tag}`)\n } else {\n tag = apiDef.tag || 'default'\n }\n }\n\n // Get projectId from config if not specified\n if (!projectId) {\n projectId = await this.getProjectId({\n deprecatedFlagName: 'project',\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'manage', permission: 'sanity.project.graphql'}],\n }),\n })\n }\n\n // Get dataset from CLI config if not specified\n if (!dataset) {\n const cliConfig = await this.tryGetCliConfig()\n dataset = cliConfig.api?.dataset\n }\n\n if (!dataset) {\n this.error(\n 'Dataset is required. Pass it with `--dataset <name>` or configure it in your project.',\n {\n exit: exitCodes.USAGE_ERROR,\n },\n )\n }\n\n // Confirm deletion unless --force is used\n if (!force) {\n if (this.isUnattended()) {\n this.error('GraphQL API undeploy requires confirmation. Pass `--force` to continue.', {\n exit: exitCodes.USAGE_ERROR,\n })\n }\n\n const confirmMessage =\n tag === 'default'\n ? `Delete the GraphQL API for dataset \"${dataset}\" in project ${projectId}?`\n : `Delete the GraphQL API for dataset \"${dataset}\" in project ${projectId} with tag \"${tag}\"?`\n\n const confirmed = await confirm({\n default: false,\n message: confirmMessage,\n })\n\n if (!confirmed) {\n this.log('GraphQL API undeploy cancelled')\n this.exit(exitCodes.USER_ABORT)\n }\n }\n\n try {\n await deleteGraphQLAPI({\n dataset,\n projectId,\n tag,\n })\n\n this.log('GraphQL API deleted')\n } catch (error) {\n const err = error instanceof Error ? error : new Error(`${error}`)\n undeployGraphqlDebug(`Error deleting GraphQL API for ${dataset}/${tag}`, err)\n this.error(`GraphQL API deletion failed:\\n${err.message}`, {exit: exitCodes.RUNTIME_ERROR})\n }\n }\n}\n"],"names":["Flags","exitCodes","SanityCommand","subdebug","confirm","getGraphQLAPIs","promptForProject","deleteGraphQLAPI","getDatasetFlag","getProjectIdFlag","undeployGraphqlDebug","Undeploy","description","examples","command","flags","semantics","api","string","exclusive","required","force","boolean","project","deprecated","to","hidden","tag","default","run","parse","apiFlag","dataset","datasetFlag","tagFlag","projectId","workDir","getProjectRoot","directory","apiDefs","apiDef","find","def","id","error","exit","RUNTIME_ERROR","warn","getProjectId","deprecatedFlagName","fallback","requiredPermissions","grant","permission","cliConfig","tryGetCliConfig","USAGE_ERROR","isUnattended","confirmMessage","confirmed","message","log","USER_ABORT","err","Error"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/graphql/undeploy.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {requiredWhenUnattended} from '@sanity/cli-core/flags'\nimport {confirm} from '@sanity/cli-core/ux'\n\nimport {getGraphQLAPIs} from '../../actions/graphql/getGraphQLAPIs.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {deleteGraphQLAPI} from '../../services/graphql.js'\nimport {getDatasetFlag, getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst undeployGraphqlDebug = subdebug('graphql:undeploy')\n\nexport class Undeploy extends SanityCommand<typeof Undeploy> {\n static override description = 'Remove a deployed GraphQL API'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Undeploy GraphQL API for current project and dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --api ios',\n description: 'Undeploy API with ID \"ios\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --dataset staging',\n description: 'Undeploy GraphQL API for staging dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --dataset staging --tag next',\n description: 'Undeploy GraphQL API for staging dataset with \"next\" tag',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --force',\n description: 'Undeploy GraphQL API without confirmation prompt',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --project-id abc123 --dataset production',\n description: 'Undeploy GraphQL API for a specific project and dataset',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to undeploy GraphQL API from',\n semantics: 'override',\n }),\n api: Flags.string({\n description: 'Undeploy API with this ID',\n exclusive: ['project-id', 'project'],\n required: false,\n }),\n ...getDatasetFlag({description: 'Dataset to undeploy GraphQL API from', semantics: 'override'}),\n force: requiredWhenUnattended(\n Flags.boolean({\n description: 'Skip confirmation prompt',\n }),\n ),\n project: Flags.string({\n deprecated: {to: 'project-id'},\n description: 'Project ID to delete GraphQL API for',\n hidden: true,\n required: false,\n }),\n tag: Flags.string({\n default: 'default',\n description: 'Tag to undeploy GraphQL API from',\n required: false,\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(Undeploy)\n const {api: apiFlag, dataset: datasetFlag, force, tag: tagFlag} = flags\n\n let projectId: string | undefined\n let dataset = datasetFlag\n let tag = tagFlag\n\n // If specifying --api, use it for the flags not provided\n if (apiFlag) {\n const workDir = (await this.getProjectRoot()).directory\n const apiDefs = await getGraphQLAPIs(workDir)\n const apiDef = apiDefs.find((def) => def.id === apiFlag)\n\n if (!apiDef) {\n this.error(`GraphQL API \"${apiFlag}\" not found`, {exit: exitCodes.RUNTIME_ERROR})\n }\n\n projectId = apiDef.projectId\n\n if (dataset && dataset !== apiDef.dataset) {\n this.warn(`Both --api and --dataset specified, using --dataset ${dataset}`)\n } else {\n dataset = apiDef.dataset\n }\n\n if (tag && tag !== 'default' && apiDef.tag && tag !== apiDef.tag) {\n this.warn(`Both --api and --tag specified, using --tag ${tag}`)\n } else {\n tag = apiDef.tag || 'default'\n }\n }\n\n // Get projectId from config if not specified\n if (!projectId) {\n projectId = await this.getProjectId({\n deprecatedFlagName: 'project',\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'manage', permission: 'sanity.project.graphql'}],\n }),\n })\n }\n\n // Get dataset from CLI config if not specified\n if (!dataset) {\n const cliConfig = await this.tryGetCliConfig()\n dataset = cliConfig.api?.dataset\n }\n\n if (!dataset) {\n this.error(\n 'Dataset is required. Pass it with `--dataset <name>` or configure it in your project.',\n {\n exit: exitCodes.USAGE_ERROR,\n },\n )\n }\n\n // Confirm deletion unless --force is used\n if (!force) {\n const confirmMessage =\n tag === 'default'\n ? `Delete the GraphQL API for dataset \"${dataset}\" in project ${projectId}?`\n : `Delete the GraphQL API for dataset \"${dataset}\" in project ${projectId} with tag \"${tag}\"?`\n\n const confirmed = await confirm({\n default: false,\n message: confirmMessage,\n })\n\n if (!confirmed) {\n this.log('GraphQL API undeploy cancelled')\n this.exit(exitCodes.USER_ABORT)\n }\n }\n\n try {\n await deleteGraphQLAPI({\n dataset,\n projectId,\n tag,\n })\n\n this.log('GraphQL API deleted')\n } catch (error) {\n const err = error instanceof Error ? error : new Error(`${error}`)\n undeployGraphqlDebug(`Error deleting GraphQL API for ${dataset}/${tag}`, err)\n this.error(`GraphQL API deletion failed:\\n${err.message}`, {exit: exitCodes.RUNTIME_ERROR})\n }\n }\n}\n"],"names":["Flags","exitCodes","SanityCommand","subdebug","requiredWhenUnattended","confirm","getGraphQLAPIs","promptForProject","deleteGraphQLAPI","getDatasetFlag","getProjectIdFlag","undeployGraphqlDebug","Undeploy","description","examples","command","flags","semantics","api","string","exclusive","required","force","boolean","project","deprecated","to","hidden","tag","default","run","parse","apiFlag","dataset","datasetFlag","tagFlag","projectId","workDir","getProjectRoot","directory","apiDefs","apiDef","find","def","id","error","exit","RUNTIME_ERROR","warn","getProjectId","deprecatedFlagName","fallback","requiredPermissions","grant","permission","cliConfig","tryGetCliConfig","USAGE_ERROR","confirmMessage","confirmed","message","log","USER_ABORT","err","Error"],"mappings":"AAAA,SAAQA,KAAK,QAAO,cAAa;AACjC,SAAQC,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACnE,SAAQC,sBAAsB,QAAO,yBAAwB;AAC7D,SAAQC,OAAO,QAAO,sBAAqB;AAE3C,SAAQC,cAAc,QAAO,0CAAyC;AACtE,SAAQC,gBAAgB,QAAO,oCAAmC;AAClE,SAAQC,gBAAgB,QAAO,4BAA2B;AAC1D,SAAQC,cAAc,EAAEC,gBAAgB,QAAO,4BAA2B;AAE1E,MAAMC,uBAAuBR,SAAS;AAEtC,OAAO,MAAMS,iBAAiBV;IAC5B,OAAgBW,cAAc,gCAA+B;IAE7D,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTF,aAAa;QACf;QACA;YACEE,SAAS;YACTF,aAAa;QACf;QACA;YACEE,SAAS;YACTF,aAAa;QACf;QACA;YACEE,SAAS;YACTF,aAAa;QACf;QACA;YACEE,SAAS;YACTF,aAAa;QACf;QACA;YACEE,SAAS;YACTF,aAAa;QACf;KACD,CAAA;IAED,OAAgBG,QAAQ;QACtB,GAAGN,iBAAiB;YAClBG,aAAa;YACbI,WAAW;QACb,EAAE;QACFC,KAAKlB,MAAMmB,MAAM,CAAC;YAChBN,aAAa;YACbO,WAAW;gBAAC;gBAAc;aAAU;YACpCC,UAAU;QACZ;QACA,GAAGZ,eAAe;YAACI,aAAa;YAAwCI,WAAW;QAAU,EAAE;QAC/FK,OAAOlB,uBACLJ,MAAMuB,OAAO,CAAC;YACZV,aAAa;QACf;QAEFW,SAASxB,MAAMmB,MAAM,CAAC;YACpBM,YAAY;gBAACC,IAAI;YAAY;YAC7Bb,aAAa;YACbc,QAAQ;YACRN,UAAU;QACZ;QACAO,KAAK5B,MAAMmB,MAAM,CAAC;YAChBU,SAAS;YACThB,aAAa;YACbQ,UAAU;QACZ;IACF,EAAC;IAED,MAAaS,MAAqB;QAChC,MAAM,EAACd,KAAK,EAAC,GAAG,MAAM,IAAI,CAACe,KAAK,CAACnB;QACjC,MAAM,EAACM,KAAKc,OAAO,EAAEC,SAASC,WAAW,EAAEZ,KAAK,EAAEM,KAAKO,OAAO,EAAC,GAAGnB;QAElE,IAAIoB;QACJ,IAAIH,UAAUC;QACd,IAAIN,MAAMO;QAEV,yDAAyD;QACzD,IAAIH,SAAS;YACX,MAAMK,UAAU,AAAC,CAAA,MAAM,IAAI,CAACC,cAAc,EAAC,EAAGC,SAAS;YACvD,MAAMC,UAAU,MAAMlC,eAAe+B;YACrC,MAAMI,SAASD,QAAQE,IAAI,CAAC,CAACC,MAAQA,IAAIC,EAAE,KAAKZ;YAEhD,IAAI,CAACS,QAAQ;gBACX,IAAI,CAACI,KAAK,CAAC,CAAC,aAAa,EAAEb,QAAQ,WAAW,CAAC,EAAE;oBAACc,MAAM7C,UAAU8C,aAAa;gBAAA;YACjF;YAEAX,YAAYK,OAAOL,SAAS;YAE5B,IAAIH,WAAWA,YAAYQ,OAAOR,OAAO,EAAE;gBACzC,IAAI,CAACe,IAAI,CAAC,CAAC,oDAAoD,EAAEf,SAAS;YAC5E,OAAO;gBACLA,UAAUQ,OAAOR,OAAO;YAC1B;YAEA,IAAIL,OAAOA,QAAQ,aAAaa,OAAOb,GAAG,IAAIA,QAAQa,OAAOb,GAAG,EAAE;gBAChE,IAAI,CAACoB,IAAI,CAAC,CAAC,4CAA4C,EAAEpB,KAAK;YAChE,OAAO;gBACLA,MAAMa,OAAOb,GAAG,IAAI;YACtB;QACF;QAEA,6CAA6C;QAC7C,IAAI,CAACQ,WAAW;YACdA,YAAY,MAAM,IAAI,CAACa,YAAY,CAAC;gBAClCC,oBAAoB;gBACpBC,UAAU,IACR5C,iBAAiB;wBACf6C,qBAAqB;4BAAC;gCAACC,OAAO;gCAAUC,YAAY;4BAAwB;yBAAE;oBAChF;YACJ;QACF;QAEA,+CAA+C;QAC/C,IAAI,CAACrB,SAAS;YACZ,MAAMsB,YAAY,MAAM,IAAI,CAACC,eAAe;YAC5CvB,UAAUsB,UAAUrC,GAAG,EAAEe;QAC3B;QAEA,IAAI,CAACA,SAAS;YACZ,IAAI,CAACY,KAAK,CACR,yFACA;gBACEC,MAAM7C,UAAUwD,WAAW;YAC7B;QAEJ;QAEA,0CAA0C;QAC1C,IAAI,CAACnC,OAAO;YACV,MAAMoC,iBACJ9B,QAAQ,YACJ,CAAC,oCAAoC,EAAEK,QAAQ,aAAa,EAAEG,UAAU,CAAC,CAAC,GAC1E,CAAC,oCAAoC,EAAEH,QAAQ,aAAa,EAAEG,UAAU,WAAW,EAAER,IAAI,EAAE,CAAC;YAElG,MAAM+B,YAAY,MAAMtD,QAAQ;gBAC9BwB,SAAS;gBACT+B,SAASF;YACX;YAEA,IAAI,CAACC,WAAW;gBACd,IAAI,CAACE,GAAG,CAAC;gBACT,IAAI,CAACf,IAAI,CAAC7C,UAAU6D,UAAU;YAChC;QACF;QAEA,IAAI;YACF,MAAMtD,iBAAiB;gBACrByB;gBACAG;gBACAR;YACF;YAEA,IAAI,CAACiC,GAAG,CAAC;QACX,EAAE,OAAOhB,OAAO;YACd,MAAMkB,MAAMlB,iBAAiBmB,QAAQnB,QAAQ,IAAImB,MAAM,GAAGnB,OAAO;YACjElC,qBAAqB,CAAC,+BAA+B,EAAEsB,QAAQ,CAAC,EAAEL,KAAK,EAAEmC;YACzE,IAAI,CAAClB,KAAK,CAAC,CAAC,8BAA8B,EAAEkB,IAAIH,OAAO,EAAE,EAAE;gBAACd,MAAM7C,UAAU8C,aAAa;YAAA;QAC3F;IACF;AACF"}
@@ -230,7 +230,7 @@ export class InitCommand extends SanityCommand {
230
230
  'unstable--workbench': Flags.boolean({
231
231
  allowNo: true,
232
232
  default: undefined,
233
- description: 'Opt into workbench: scaffolds the CLI config with unstable_defineApp',
233
+ description: 'Opt into workbench: scaffolds the CLI config with defineApplication',
234
234
  // Internal-only while workbench is unstable — keep it out of help/docs
235
235
  hidden: true
236
236
  }),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/init.ts"],"sourcesContent":["import {Args, Command, Flags} from '@oclif/core'\nimport {CLIError} from '@oclif/core/errors'\nimport {SanityCommand} from '@sanity/cli-core'\n\nimport {initAction} from '../actions/init/initAction.js'\nimport {InitError} from '../actions/init/initError.js'\nimport {flagsToInitOptions} from '../actions/init/types.js'\n\nexport class InitCommand extends SanityCommand<typeof InitCommand> {\n static override args = {type: Args.string({hidden: true})}\n static override description = 'Initialize a new Sanity Studio, project and/or app'\n static override enableJsonFlag = true\n\n static override examples = [\n '<%= config.bin %> <%= command.id %>',\n {\n command: '<%= config.bin %> <%= command.id %> --dataset-default',\n description: 'Initialize a new project with a public dataset named \"production\"',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> -y --project abc123 --dataset production --output-path ~/myproj',\n description: 'Initialize a project with the given project ID and dataset to the given path',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> -y --project abc123 --dataset staging --template moviedb --output-path .',\n description:\n 'Initialize a project with the given project ID and dataset using the moviedb template to the given path',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> -y --project-name \"Movies Unlimited\" --dataset moviedb --visibility private --template moviedb --output-path /Users/espenh/movies-unlimited',\n description: 'Create a brand new project with name \"Movies Unlimited\"',\n },\n ] satisfies Array<Command.Example>\n\n static override flags = {\n 'auto-updates': Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Enable auto updates of studio versions',\n exclusive: ['bare'],\n }),\n bare: Flags.boolean({\n description:\n 'Skip the Studio initialization and only print the selected project ID and dataset name to stdout',\n }),\n coupon: Flags.string({\n description:\n 'Optionally select a coupon for a new project (cannot be used with --project-plan)',\n exclusive: ['project-plan'],\n helpValue: '<code>',\n }),\n 'create-project': Flags.string({\n deprecated: {message: 'Use --project-name instead'},\n description: 'Create a new project with the given name',\n helpValue: '<name>',\n hidden: true,\n }),\n dataset: Flags.string({\n description: 'Dataset name for the studio',\n exclusive: ['dataset-default'],\n helpValue: '<name>',\n }),\n 'dataset-default': Flags.boolean({\n description: 'Set up a project with a public dataset named \"production\"',\n }),\n env: Flags.string({\n description: 'Write environment variables to file',\n exclusive: ['bare'],\n helpValue: '<filename>',\n parse: async (input) => {\n if (!input.startsWith('.env')) {\n throw new CLIError('Env filename (`--env`) must start with `.env`')\n }\n return input\n },\n }),\n 'from-create': Flags.boolean({\n description: 'Internal flag to indicate that the command is run from create-sanity',\n hidden: true,\n }),\n git: Flags.string({\n default: undefined,\n description: 'Specify a commit message for initial commit, or disable git init',\n exclusive: ['bare'],\n // oclif doesn't indent correctly with custom help labels, thus leading space :/\n helpLabel: ' --[no-]git',\n helpValue: '<message>',\n }),\n 'import-dataset': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Import template sample dataset',\n }),\n mcp: Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Enable AI editor integration (MCP) setup',\n }),\n 'nextjs-add-config-files': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Add config files to Next.js project',\n helpGroup: 'Next.js',\n }),\n 'nextjs-append-env': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Append project ID and dataset to .env file',\n helpGroup: 'Next.js',\n }),\n 'nextjs-embed-studio': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Embed the Studio in Next.js application',\n helpGroup: 'Next.js',\n }),\n // oclif doesn't support a boolean/string flag combination, but listing both a\n // `--git` and a `--no-git` flag in help breaks conventions, so we hide this one,\n // but use it to \"combine\" the two in the actual logic.\n 'no-git': Flags.boolean({\n description: 'Disable git initialization',\n exclusive: ['git'],\n hidden: true,\n }),\n organization: Flags.string({\n description:\n 'Organization ID to use for the project (required for unattended project creation)',\n helpValue: '<id>',\n }),\n 'output-path': Flags.string({\n description: 'Path to write studio project to',\n exclusive: ['bare'],\n helpValue: '<path>',\n }),\n 'overwrite-files': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Overwrite existing files',\n }),\n 'package-manager': Flags.string({\n description: 'Specify which package manager to use [allowed: npm, yarn, pnpm]',\n exclusive: ['bare'],\n helpValue: '<manager>',\n options: ['npm', 'yarn', 'pnpm'],\n }),\n project: Flags.string({\n aliases: ['project-id'],\n description: 'Project ID to use for the studio',\n exclusive: ['create-project', 'project-name'],\n helpValue: '<id>',\n }),\n 'project-name': Flags.string({\n description: 'Create a new project with the given name',\n exclusive: ['project', 'create-project'],\n helpValue: '<name>',\n }),\n 'project-plan': Flags.string({\n description: 'Optionally select a plan for a new project',\n helpValue: '<name>',\n }),\n provider: Flags.string({\n description: 'Login provider to use',\n helpValue: '<provider>',\n }),\n quickstart: Flags.boolean({\n deprecated: true,\n description:\n 'Used for initializing a project from a server schema that is saved in the Journey API',\n hidden: true,\n }),\n reconfigure: Flags.boolean({\n deprecated: {\n message: 'This flag is no longer supported',\n version: '3.0.0',\n },\n description: 'Reconfigure an existing project',\n hidden: true,\n }),\n skills: Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Install Sanity agent skills globally for detected AI editors',\n }),\n template: Flags.string({\n description: 'Project template to use [default: \"clean\"]',\n exclusive: ['bare'],\n helpValue: '<template>',\n }),\n // Porting over a beta flag\n // Oclif doesn't seem to support something in beta so hiding for now\n 'template-token': Flags.string({\n description: 'Used for accessing private GitHub repo templates',\n hidden: true,\n }),\n typescript: Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Enable TypeScript support',\n exclusive: ['bare'],\n }),\n 'unstable--workbench': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Opt into workbench: scaffolds the CLI config with unstable_defineApp',\n // Internal-only while workbench is unstable — keep it out of help/docs\n hidden: true,\n }),\n visibility: Flags.string({\n description: 'Visibility mode for dataset',\n helpValue: '<mode>',\n options: ['public', 'private'],\n }),\n yes: Flags.boolean({\n char: 'y',\n default: false,\n description:\n 'Unattended mode, answers \"yes\" to any \"yes/no\" prompt and otherwise uses defaults',\n }),\n }\n\n public async run(): Promise<void> {\n let mcpMode: 'auto' | 'prompt' | 'skip' = 'prompt'\n if (!this.flags.mcp || !this.resolveIsInteractive()) {\n mcpMode = 'skip'\n } else if (this.isUnattended()) {\n // Any unattended run (e.g. --yes, --json) configures MCP with defaults rather than prompting\n mcpMode = 'auto'\n }\n\n // Mirror MCP's environment gating: skip install in test environments\n // ensure e2e / CI tests don't run the bundled skills CLI.\n let skillsMode: 'auto' | 'prompt' | 'skip' = 'auto'\n if (!this.flags.skills || !this.resolveIsInteractive()) {\n skillsMode = 'skip'\n }\n\n try {\n await initAction(\n flagsToInitOptions(this.flags, this.isUnattended(), this.args, mcpMode, skillsMode),\n {\n output: this.output,\n telemetry: this.telemetry,\n workDir: process.cwd(),\n },\n )\n } catch (error) {\n if (error instanceof InitError) {\n this.error(error.message, {exit: error.exitCode})\n }\n throw error\n }\n }\n}\n"],"names":["Args","Flags","CLIError","SanityCommand","initAction","InitError","flagsToInitOptions","InitCommand","args","type","string","hidden","description","enableJsonFlag","examples","command","flags","boolean","allowNo","default","exclusive","bare","coupon","helpValue","deprecated","message","dataset","env","parse","input","startsWith","git","undefined","helpLabel","mcp","helpGroup","organization","options","project","aliases","provider","quickstart","reconfigure","version","skills","template","typescript","visibility","yes","char","run","mcpMode","resolveIsInteractive","isUnattended","skillsMode","output","telemetry","workDir","process","cwd","error","exit","exitCode"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/commands/init.ts"],"sourcesContent":["import {Args, Command, Flags} from '@oclif/core'\nimport {CLIError} from '@oclif/core/errors'\nimport {SanityCommand} from '@sanity/cli-core'\n\nimport {initAction} from '../actions/init/initAction.js'\nimport {InitError} from '../actions/init/initError.js'\nimport {flagsToInitOptions} from '../actions/init/types.js'\n\nexport class InitCommand extends SanityCommand<typeof InitCommand> {\n static override args = {type: Args.string({hidden: true})}\n static override description = 'Initialize a new Sanity Studio, project and/or app'\n static override enableJsonFlag = true\n\n static override examples = [\n '<%= config.bin %> <%= command.id %>',\n {\n command: '<%= config.bin %> <%= command.id %> --dataset-default',\n description: 'Initialize a new project with a public dataset named \"production\"',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> -y --project abc123 --dataset production --output-path ~/myproj',\n description: 'Initialize a project with the given project ID and dataset to the given path',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> -y --project abc123 --dataset staging --template moviedb --output-path .',\n description:\n 'Initialize a project with the given project ID and dataset using the moviedb template to the given path',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> -y --project-name \"Movies Unlimited\" --dataset moviedb --visibility private --template moviedb --output-path /Users/espenh/movies-unlimited',\n description: 'Create a brand new project with name \"Movies Unlimited\"',\n },\n ] satisfies Array<Command.Example>\n\n static override flags = {\n 'auto-updates': Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Enable auto updates of studio versions',\n exclusive: ['bare'],\n }),\n bare: Flags.boolean({\n description:\n 'Skip the Studio initialization and only print the selected project ID and dataset name to stdout',\n }),\n coupon: Flags.string({\n description:\n 'Optionally select a coupon for a new project (cannot be used with --project-plan)',\n exclusive: ['project-plan'],\n helpValue: '<code>',\n }),\n 'create-project': Flags.string({\n deprecated: {message: 'Use --project-name instead'},\n description: 'Create a new project with the given name',\n helpValue: '<name>',\n hidden: true,\n }),\n dataset: Flags.string({\n description: 'Dataset name for the studio',\n exclusive: ['dataset-default'],\n helpValue: '<name>',\n }),\n 'dataset-default': Flags.boolean({\n description: 'Set up a project with a public dataset named \"production\"',\n }),\n env: Flags.string({\n description: 'Write environment variables to file',\n exclusive: ['bare'],\n helpValue: '<filename>',\n parse: async (input) => {\n if (!input.startsWith('.env')) {\n throw new CLIError('Env filename (`--env`) must start with `.env`')\n }\n return input\n },\n }),\n 'from-create': Flags.boolean({\n description: 'Internal flag to indicate that the command is run from create-sanity',\n hidden: true,\n }),\n git: Flags.string({\n default: undefined,\n description: 'Specify a commit message for initial commit, or disable git init',\n exclusive: ['bare'],\n // oclif doesn't indent correctly with custom help labels, thus leading space :/\n helpLabel: ' --[no-]git',\n helpValue: '<message>',\n }),\n 'import-dataset': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Import template sample dataset',\n }),\n mcp: Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Enable AI editor integration (MCP) setup',\n }),\n 'nextjs-add-config-files': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Add config files to Next.js project',\n helpGroup: 'Next.js',\n }),\n 'nextjs-append-env': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Append project ID and dataset to .env file',\n helpGroup: 'Next.js',\n }),\n 'nextjs-embed-studio': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Embed the Studio in Next.js application',\n helpGroup: 'Next.js',\n }),\n // oclif doesn't support a boolean/string flag combination, but listing both a\n // `--git` and a `--no-git` flag in help breaks conventions, so we hide this one,\n // but use it to \"combine\" the two in the actual logic.\n 'no-git': Flags.boolean({\n description: 'Disable git initialization',\n exclusive: ['git'],\n hidden: true,\n }),\n organization: Flags.string({\n description:\n 'Organization ID to use for the project (required for unattended project creation)',\n helpValue: '<id>',\n }),\n 'output-path': Flags.string({\n description: 'Path to write studio project to',\n exclusive: ['bare'],\n helpValue: '<path>',\n }),\n 'overwrite-files': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Overwrite existing files',\n }),\n 'package-manager': Flags.string({\n description: 'Specify which package manager to use [allowed: npm, yarn, pnpm]',\n exclusive: ['bare'],\n helpValue: '<manager>',\n options: ['npm', 'yarn', 'pnpm'],\n }),\n project: Flags.string({\n aliases: ['project-id'],\n description: 'Project ID to use for the studio',\n exclusive: ['create-project', 'project-name'],\n helpValue: '<id>',\n }),\n 'project-name': Flags.string({\n description: 'Create a new project with the given name',\n exclusive: ['project', 'create-project'],\n helpValue: '<name>',\n }),\n 'project-plan': Flags.string({\n description: 'Optionally select a plan for a new project',\n helpValue: '<name>',\n }),\n provider: Flags.string({\n description: 'Login provider to use',\n helpValue: '<provider>',\n }),\n quickstart: Flags.boolean({\n deprecated: true,\n description:\n 'Used for initializing a project from a server schema that is saved in the Journey API',\n hidden: true,\n }),\n reconfigure: Flags.boolean({\n deprecated: {\n message: 'This flag is no longer supported',\n version: '3.0.0',\n },\n description: 'Reconfigure an existing project',\n hidden: true,\n }),\n skills: Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Install Sanity agent skills globally for detected AI editors',\n }),\n template: Flags.string({\n description: 'Project template to use [default: \"clean\"]',\n exclusive: ['bare'],\n helpValue: '<template>',\n }),\n // Porting over a beta flag\n // Oclif doesn't seem to support something in beta so hiding for now\n 'template-token': Flags.string({\n description: 'Used for accessing private GitHub repo templates',\n hidden: true,\n }),\n typescript: Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Enable TypeScript support',\n exclusive: ['bare'],\n }),\n 'unstable--workbench': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Opt into workbench: scaffolds the CLI config with defineApplication',\n // Internal-only while workbench is unstable — keep it out of help/docs\n hidden: true,\n }),\n visibility: Flags.string({\n description: 'Visibility mode for dataset',\n helpValue: '<mode>',\n options: ['public', 'private'],\n }),\n yes: Flags.boolean({\n char: 'y',\n default: false,\n description:\n 'Unattended mode, answers \"yes\" to any \"yes/no\" prompt and otherwise uses defaults',\n }),\n }\n\n public async run(): Promise<void> {\n let mcpMode: 'auto' | 'prompt' | 'skip' = 'prompt'\n if (!this.flags.mcp || !this.resolveIsInteractive()) {\n mcpMode = 'skip'\n } else if (this.isUnattended()) {\n // Any unattended run (e.g. --yes, --json) configures MCP with defaults rather than prompting\n mcpMode = 'auto'\n }\n\n // Mirror MCP's environment gating: skip install in test environments\n // ensure e2e / CI tests don't run the bundled skills CLI.\n let skillsMode: 'auto' | 'prompt' | 'skip' = 'auto'\n if (!this.flags.skills || !this.resolveIsInteractive()) {\n skillsMode = 'skip'\n }\n\n try {\n await initAction(\n flagsToInitOptions(this.flags, this.isUnattended(), this.args, mcpMode, skillsMode),\n {\n output: this.output,\n telemetry: this.telemetry,\n workDir: process.cwd(),\n },\n )\n } catch (error) {\n if (error instanceof InitError) {\n this.error(error.message, {exit: error.exitCode})\n }\n throw error\n }\n }\n}\n"],"names":["Args","Flags","CLIError","SanityCommand","initAction","InitError","flagsToInitOptions","InitCommand","args","type","string","hidden","description","enableJsonFlag","examples","command","flags","boolean","allowNo","default","exclusive","bare","coupon","helpValue","deprecated","message","dataset","env","parse","input","startsWith","git","undefined","helpLabel","mcp","helpGroup","organization","options","project","aliases","provider","quickstart","reconfigure","version","skills","template","typescript","visibility","yes","char","run","mcpMode","resolveIsInteractive","isUnattended","skillsMode","output","telemetry","workDir","process","cwd","error","exit","exitCode"],"mappings":"AAAA,SAAQA,IAAI,EAAWC,KAAK,QAAO,cAAa;AAChD,SAAQC,QAAQ,QAAO,qBAAoB;AAC3C,SAAQC,aAAa,QAAO,mBAAkB;AAE9C,SAAQC,UAAU,QAAO,gCAA+B;AACxD,SAAQC,SAAS,QAAO,+BAA8B;AACtD,SAAQC,kBAAkB,QAAO,2BAA0B;AAE3D,OAAO,MAAMC,oBAAoBJ;IAC/B,OAAgBK,OAAO;QAACC,MAAMT,KAAKU,MAAM,CAAC;YAACC,QAAQ;QAAI;IAAE,EAAC;IAC1D,OAAgBC,cAAc,qDAAoD;IAClF,OAAgBC,iBAAiB,KAAI;IAErC,OAAgBC,WAAW;QACzB;QACA;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SACE;YACFH,aAAa;QACf;QACA;YACEG,SACE;YACFH,aACE;QACJ;QACA;YACEG,SACE;YACFH,aAAa;QACf;KACD,CAAiC;IAElC,OAAgBI,QAAQ;QACtB,gBAAgBf,MAAMgB,OAAO,CAAC;YAC5BC,SAAS;YACTC,SAAS;YACTP,aAAa;YACbQ,WAAW;gBAAC;aAAO;QACrB;QACAC,MAAMpB,MAAMgB,OAAO,CAAC;YAClBL,aACE;QACJ;QACAU,QAAQrB,MAAMS,MAAM,CAAC;YACnBE,aACE;YACFQ,WAAW;gBAAC;aAAe;YAC3BG,WAAW;QACb;QACA,kBAAkBtB,MAAMS,MAAM,CAAC;YAC7Bc,YAAY;gBAACC,SAAS;YAA4B;YAClDb,aAAa;YACbW,WAAW;YACXZ,QAAQ;QACV;QACAe,SAASzB,MAAMS,MAAM,CAAC;YACpBE,aAAa;YACbQ,WAAW;gBAAC;aAAkB;YAC9BG,WAAW;QACb;QACA,mBAAmBtB,MAAMgB,OAAO,CAAC;YAC/BL,aAAa;QACf;QACAe,KAAK1B,MAAMS,MAAM,CAAC;YAChBE,aAAa;YACbQ,WAAW;gBAAC;aAAO;YACnBG,WAAW;YACXK,OAAO,OAAOC;gBACZ,IAAI,CAACA,MAAMC,UAAU,CAAC,SAAS;oBAC7B,MAAM,IAAI5B,SAAS;gBACrB;gBACA,OAAO2B;YACT;QACF;QACA,eAAe5B,MAAMgB,OAAO,CAAC;YAC3BL,aAAa;YACbD,QAAQ;QACV;QACAoB,KAAK9B,MAAMS,MAAM,CAAC;YAChBS,SAASa;YACTpB,aAAa;YACbQ,WAAW;gBAAC;aAAO;YACnB,gFAAgF;YAChFa,WAAW;YACXV,WAAW;QACb;QACA,kBAAkBtB,MAAMgB,OAAO,CAAC;YAC9BC,SAAS;YACTC,SAASa;YACTpB,aAAa;QACf;QACAsB,KAAKjC,MAAMgB,OAAO,CAAC;YACjBC,SAAS;YACTC,SAAS;YACTP,aAAa;QACf;QACA,2BAA2BX,MAAMgB,OAAO,CAAC;YACvCC,SAAS;YACTC,SAASa;YACTpB,aAAa;YACbuB,WAAW;QACb;QACA,qBAAqBlC,MAAMgB,OAAO,CAAC;YACjCC,SAAS;YACTC,SAASa;YACTpB,aAAa;YACbuB,WAAW;QACb;QACA,uBAAuBlC,MAAMgB,OAAO,CAAC;YACnCC,SAAS;YACTC,SAASa;YACTpB,aAAa;YACbuB,WAAW;QACb;QACA,8EAA8E;QAC9E,iFAAiF;QACjF,uDAAuD;QACvD,UAAUlC,MAAMgB,OAAO,CAAC;YACtBL,aAAa;YACbQ,WAAW;gBAAC;aAAM;YAClBT,QAAQ;QACV;QACAyB,cAAcnC,MAAMS,MAAM,CAAC;YACzBE,aACE;YACFW,WAAW;QACb;QACA,eAAetB,MAAMS,MAAM,CAAC;YAC1BE,aAAa;YACbQ,WAAW;gBAAC;aAAO;YACnBG,WAAW;QACb;QACA,mBAAmBtB,MAAMgB,OAAO,CAAC;YAC/BC,SAAS;YACTC,SAASa;YACTpB,aAAa;QACf;QACA,mBAAmBX,MAAMS,MAAM,CAAC;YAC9BE,aAAa;YACbQ,WAAW;gBAAC;aAAO;YACnBG,WAAW;YACXc,SAAS;gBAAC;gBAAO;gBAAQ;aAAO;QAClC;QACAC,SAASrC,MAAMS,MAAM,CAAC;YACpB6B,SAAS;gBAAC;aAAa;YACvB3B,aAAa;YACbQ,WAAW;gBAAC;gBAAkB;aAAe;YAC7CG,WAAW;QACb;QACA,gBAAgBtB,MAAMS,MAAM,CAAC;YAC3BE,aAAa;YACbQ,WAAW;gBAAC;gBAAW;aAAiB;YACxCG,WAAW;QACb;QACA,gBAAgBtB,MAAMS,MAAM,CAAC;YAC3BE,aAAa;YACbW,WAAW;QACb;QACAiB,UAAUvC,MAAMS,MAAM,CAAC;YACrBE,aAAa;YACbW,WAAW;QACb;QACAkB,YAAYxC,MAAMgB,OAAO,CAAC;YACxBO,YAAY;YACZZ,aACE;YACFD,QAAQ;QACV;QACA+B,aAAazC,MAAMgB,OAAO,CAAC;YACzBO,YAAY;gBACVC,SAAS;gBACTkB,SAAS;YACX;YACA/B,aAAa;YACbD,QAAQ;QACV;QACAiC,QAAQ3C,MAAMgB,OAAO,CAAC;YACpBC,SAAS;YACTC,SAAS;YACTP,aAAa;QACf;QACAiC,UAAU5C,MAAMS,MAAM,CAAC;YACrBE,aAAa;YACbQ,WAAW;gBAAC;aAAO;YACnBG,WAAW;QACb;QACA,2BAA2B;QAC3B,oEAAoE;QACpE,kBAAkBtB,MAAMS,MAAM,CAAC;YAC7BE,aAAa;YACbD,QAAQ;QACV;QACAmC,YAAY7C,MAAMgB,OAAO,CAAC;YACxBC,SAAS;YACTC,SAASa;YACTpB,aAAa;YACbQ,WAAW;gBAAC;aAAO;QACrB;QACA,uBAAuBnB,MAAMgB,OAAO,CAAC;YACnCC,SAAS;YACTC,SAASa;YACTpB,aAAa;YACb,uEAAuE;YACvED,QAAQ;QACV;QACAoC,YAAY9C,MAAMS,MAAM,CAAC;YACvBE,aAAa;YACbW,WAAW;YACXc,SAAS;gBAAC;gBAAU;aAAU;QAChC;QACAW,KAAK/C,MAAMgB,OAAO,CAAC;YACjBgC,MAAM;YACN9B,SAAS;YACTP,aACE;QACJ;IACF,EAAC;IAED,MAAasC,MAAqB;QAChC,IAAIC,UAAsC;QAC1C,IAAI,CAAC,IAAI,CAACnC,KAAK,CAACkB,GAAG,IAAI,CAAC,IAAI,CAACkB,oBAAoB,IAAI;YACnDD,UAAU;QACZ,OAAO,IAAI,IAAI,CAACE,YAAY,IAAI;YAC9B,6FAA6F;YAC7FF,UAAU;QACZ;QAEA,qEAAqE;QACrE,0DAA0D;QAC1D,IAAIG,aAAyC;QAC7C,IAAI,CAAC,IAAI,CAACtC,KAAK,CAAC4B,MAAM,IAAI,CAAC,IAAI,CAACQ,oBAAoB,IAAI;YACtDE,aAAa;QACf;QAEA,IAAI;YACF,MAAMlD,WACJE,mBAAmB,IAAI,CAACU,KAAK,EAAE,IAAI,CAACqC,YAAY,IAAI,IAAI,CAAC7C,IAAI,EAAE2C,SAASG,aACxE;gBACEC,QAAQ,IAAI,CAACA,MAAM;gBACnBC,WAAW,IAAI,CAACA,SAAS;gBACzBC,SAASC,QAAQC,GAAG;YACtB;QAEJ,EAAE,OAAOC,OAAO;YACd,IAAIA,iBAAiBvD,WAAW;gBAC9B,IAAI,CAACuD,KAAK,CAACA,MAAMnC,OAAO,EAAE;oBAACoC,MAAMD,MAAME,QAAQ;gBAAA;YACjD;YACA,MAAMF;QACR;IACF;AACF"}
@@ -3,6 +3,7 @@ import path from 'node:path';
3
3
  import { styleText } from 'node:util';
4
4
  import { Flags } from '@oclif/core';
5
5
  import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
6
+ import { requiredWhenUnattended } from '@sanity/cli-core/flags';
6
7
  import { input } from '@sanity/cli-core/ux';
7
8
  import { createPublishedId } from '@sanity/id-utils';
8
9
  import camelCase from 'lodash-es/camelCase.js';
@@ -21,9 +22,9 @@ export class MediaCreateAspectCommand extends SanityCommand {
21
22
  name: Flags.string({
22
23
  description: 'Aspect name. Defaults to the title in camel case'
23
24
  }),
24
- title: Flags.string({
25
+ title: requiredWhenUnattended(Flags.string({
25
26
  description: 'Aspect title'
26
- })
27
+ }))
27
28
  };
28
29
  async run() {
29
30
  const cliConfig = await this.getCliConfig();
@@ -33,11 +34,9 @@ export class MediaCreateAspectCommand extends SanityCommand {
33
34
  exit: exitCodes.RUNTIME_ERROR
34
35
  });
35
36
  }
36
- const title = this.flags.title ?? (this.isUnattended() ? this.error('Aspect title is required. Pass it with `--title <title>`.', {
37
- exit: exitCodes.USAGE_ERROR
38
- }) : await input({
37
+ const title = this.flags.title ?? await input({
39
38
  message: 'Title'
40
- }));
39
+ });
41
40
  const defaultName = createPublishedId(camelCase(title));
42
41
  const name = this.flags.name ?? (this.isUnattended() ? defaultName : await input({
43
42
  default: defaultName,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/media/create-aspect.ts"],"sourcesContent":["import fs, {access, mkdir} from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Flags} from '@oclif/core'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {input} from '@sanity/cli-core/ux'\nimport {createPublishedId} from '@sanity/id-utils'\nimport camelCase from 'lodash-es/camelCase.js'\n\nimport {getMediaLibraryConfig} from '../../actions/media/getMediaLibraryConfig.js'\nimport {NO_MEDIA_LIBRARY_ASPECTS_PATH} from '../../util/errorMessages.js'\n\nconst createAspectDebug = subdebug('media:create-aspect')\n\nexport class MediaCreateAspectCommand extends SanityCommand<typeof MediaCreateAspectCommand> {\n static override description = 'Create a new aspect definition file'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Create a new aspect definition file',\n },\n ]\n\n static override flags = {\n name: Flags.string({description: 'Aspect name. Defaults to the title in camel case'}),\n title: Flags.string({description: 'Aspect title'}),\n }\n\n public async run(): Promise<void> {\n const cliConfig = await this.getCliConfig()\n const mediaLibrary = getMediaLibraryConfig(cliConfig)\n if (mediaLibrary?.aspectsPath === undefined) {\n this.error(NO_MEDIA_LIBRARY_ASPECTS_PATH, {exit: exitCodes.RUNTIME_ERROR})\n }\n\n const title =\n this.flags.title ??\n (this.isUnattended()\n ? this.error('Aspect title is required. Pass it with `--title <title>`.', {\n exit: exitCodes.USAGE_ERROR,\n })\n : await input({message: 'Title'}))\n\n const defaultName = createPublishedId(camelCase(title))\n const name =\n this.flags.name ??\n (this.isUnattended()\n ? defaultName\n : await input({\n default: defaultName,\n message: 'Name',\n }))\n\n try {\n const safeName = createPublishedId(camelCase(name))\n const destinationPath = path.resolve(mediaLibrary.aspectsPath, `${safeName}.ts`)\n const relativeDestinationPath = path.relative(process.cwd(), destinationPath)\n\n await mkdir(path.resolve(mediaLibrary.aspectsPath), {\n recursive: true,\n })\n\n const destinationPathExists = await access(destinationPath).then(\n () => true,\n () => false,\n )\n if (destinationPathExists) {\n this.error(`A file already exists at ${styleText('bold', relativeDestinationPath)}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n await fs.writeFile(\n destinationPath,\n template({\n name: safeName,\n title,\n }),\n )\n\n this.log(\n `${styleText('green', '✓')} Aspect created! ${styleText('bold', relativeDestinationPath)}`,\n )\n this.log()\n this.log('Next steps:')\n this.log(\n `Open ${styleText('bold', relativeDestinationPath)} in your code editor and customize the aspect.`,\n )\n this.log()\n this.log('Deploy this aspect by running:')\n this.log(styleText('bold', `sanity media deploy-aspect ${safeName}`))\n this.log()\n this.log('Deploy all aspects by running:')\n this.log(styleText('bold', `sanity media deploy-aspect --all`))\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n createAspectDebug('Failed to create aspect', error)\n this.error(`Failed to create aspect: ${message}`, {exit: exitCodes.RUNTIME_ERROR})\n }\n }\n}\n\nfunction template({name, title}: {name: string; title: string}) {\n return `import {defineAssetAspect, defineField} from 'sanity'\n\nexport default defineAssetAspect({\n name: '${name}',\n title: '${title}',\n type: 'object',\n fields: [\n defineField({\n name: 'string',\n title: 'Plain String',\n type: 'string',\n }),\n ],\n})\n`\n}\n"],"names":["fs","access","mkdir","path","styleText","Flags","exitCodes","SanityCommand","subdebug","input","createPublishedId","camelCase","getMediaLibraryConfig","NO_MEDIA_LIBRARY_ASPECTS_PATH","createAspectDebug","MediaCreateAspectCommand","description","examples","command","flags","name","string","title","run","cliConfig","getCliConfig","mediaLibrary","aspectsPath","undefined","error","exit","RUNTIME_ERROR","isUnattended","USAGE_ERROR","message","defaultName","default","safeName","destinationPath","resolve","relativeDestinationPath","relative","process","cwd","recursive","destinationPathExists","then","writeFile","template","log","Error","String"],"mappings":"AAAA,OAAOA,MAAKC,MAAM,EAAEC,KAAK,QAAO,mBAAkB;AAClD,OAAOC,UAAU,YAAW;AAC5B,SAAQC,SAAS,QAAO,YAAW;AAEnC,SAAQC,KAAK,QAAO,cAAa;AACjC,SAAQC,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACnE,SAAQC,KAAK,QAAO,sBAAqB;AACzC,SAAQC,iBAAiB,QAAO,mBAAkB;AAClD,OAAOC,eAAe,yBAAwB;AAE9C,SAAQC,qBAAqB,QAAO,+CAA8C;AAClF,SAAQC,6BAA6B,QAAO,8BAA6B;AAEzE,MAAMC,oBAAoBN,SAAS;AAEnC,OAAO,MAAMO,iCAAiCR;IAC5C,OAAgBS,cAAc,sCAAqC;IAEnE,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTF,aAAa;QACf;KACD,CAAA;IAED,OAAgBG,QAAQ;QACtBC,MAAMf,MAAMgB,MAAM,CAAC;YAACL,aAAa;QAAkD;QACnFM,OAAOjB,MAAMgB,MAAM,CAAC;YAACL,aAAa;QAAc;IAClD,EAAC;IAED,MAAaO,MAAqB;QAChC,MAAMC,YAAY,MAAM,IAAI,CAACC,YAAY;QACzC,MAAMC,eAAed,sBAAsBY;QAC3C,IAAIE,cAAcC,gBAAgBC,WAAW;YAC3C,IAAI,CAACC,KAAK,CAAChB,+BAA+B;gBAACiB,MAAMxB,UAAUyB,aAAa;YAAA;QAC1E;QAEA,MAAMT,QACJ,IAAI,CAACH,KAAK,CAACG,KAAK,IACf,CAAA,IAAI,CAACU,YAAY,KACd,IAAI,CAACH,KAAK,CAAC,6DAA6D;YACtEC,MAAMxB,UAAU2B,WAAW;QAC7B,KACA,MAAMxB,MAAM;YAACyB,SAAS;QAAO,EAAC;QAEpC,MAAMC,cAAczB,kBAAkBC,UAAUW;QAChD,MAAMF,OACJ,IAAI,CAACD,KAAK,CAACC,IAAI,IACd,CAAA,IAAI,CAACY,YAAY,KACdG,cACA,MAAM1B,MAAM;YACV2B,SAASD;YACTD,SAAS;QACX,EAAC;QAEP,IAAI;YACF,MAAMG,WAAW3B,kBAAkBC,UAAUS;YAC7C,MAAMkB,kBAAkBnC,KAAKoC,OAAO,CAACb,aAAaC,WAAW,EAAE,GAAGU,SAAS,GAAG,CAAC;YAC/E,MAAMG,0BAA0BrC,KAAKsC,QAAQ,CAACC,QAAQC,GAAG,IAAIL;YAE7D,MAAMpC,MAAMC,KAAKoC,OAAO,CAACb,aAAaC,WAAW,GAAG;gBAClDiB,WAAW;YACb;YAEA,MAAMC,wBAAwB,MAAM5C,OAAOqC,iBAAiBQ,IAAI,CAC9D,IAAM,MACN,IAAM;YAER,IAAID,uBAAuB;gBACzB,IAAI,CAAChB,KAAK,CAAC,CAAC,yBAAyB,EAAEzB,UAAU,QAAQoC,0BAA0B,EAAE;oBACnFV,MAAMxB,UAAUyB,aAAa;gBAC/B;YACF;YAEA,MAAM/B,GAAG+C,SAAS,CAChBT,iBACAU,SAAS;gBACP5B,MAAMiB;gBACNf;YACF;YAGF,IAAI,CAAC2B,GAAG,CACN,GAAG7C,UAAU,SAAS,KAAK,iBAAiB,EAAEA,UAAU,QAAQoC,0BAA0B;YAE5F,IAAI,CAACS,GAAG;YACR,IAAI,CAACA,GAAG,CAAC;YACT,IAAI,CAACA,GAAG,CACN,CAAC,KAAK,EAAE7C,UAAU,QAAQoC,yBAAyB,8CAA8C,CAAC;YAEpG,IAAI,CAACS,GAAG;YACR,IAAI,CAACA,GAAG,CAAC;YACT,IAAI,CAACA,GAAG,CAAC7C,UAAU,QAAQ,CAAC,2BAA2B,EAAEiC,UAAU;YACnE,IAAI,CAACY,GAAG;YACR,IAAI,CAACA,GAAG,CAAC;YACT,IAAI,CAACA,GAAG,CAAC7C,UAAU,QAAQ,CAAC,gCAAgC,CAAC;QAC/D,EAAE,OAAOyB,OAAO;YACd,MAAMK,UAAUL,iBAAiBqB,QAAQrB,MAAMK,OAAO,GAAGiB,OAAOtB;YAChEf,kBAAkB,2BAA2Be;YAC7C,IAAI,CAACA,KAAK,CAAC,CAAC,yBAAyB,EAAEK,SAAS,EAAE;gBAACJ,MAAMxB,UAAUyB,aAAa;YAAA;QAClF;IACF;AACF;AAEA,SAASiB,SAAS,EAAC5B,IAAI,EAAEE,KAAK,EAAgC;IAC5D,OAAO,CAAC;;;SAGD,EAAEF,KAAK;UACN,EAAEE,MAAM;;;;;;;;;;AAUlB,CAAC;AACD"}
1
+ {"version":3,"sources":["../../../src/commands/media/create-aspect.ts"],"sourcesContent":["import fs, {access, mkdir} from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Flags} from '@oclif/core'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {requiredWhenUnattended} from '@sanity/cli-core/flags'\nimport {input} from '@sanity/cli-core/ux'\nimport {createPublishedId} from '@sanity/id-utils'\nimport camelCase from 'lodash-es/camelCase.js'\n\nimport {getMediaLibraryConfig} from '../../actions/media/getMediaLibraryConfig.js'\nimport {NO_MEDIA_LIBRARY_ASPECTS_PATH} from '../../util/errorMessages.js'\n\nconst createAspectDebug = subdebug('media:create-aspect')\n\nexport class MediaCreateAspectCommand extends SanityCommand<typeof MediaCreateAspectCommand> {\n static override description = 'Create a new aspect definition file'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Create a new aspect definition file',\n },\n ]\n\n static override flags = {\n name: Flags.string({description: 'Aspect name. Defaults to the title in camel case'}),\n title: requiredWhenUnattended(Flags.string({description: 'Aspect title'})),\n }\n\n public async run(): Promise<void> {\n const cliConfig = await this.getCliConfig()\n const mediaLibrary = getMediaLibraryConfig(cliConfig)\n if (mediaLibrary?.aspectsPath === undefined) {\n this.error(NO_MEDIA_LIBRARY_ASPECTS_PATH, {exit: exitCodes.RUNTIME_ERROR})\n }\n\n const title = this.flags.title ?? (await input({message: 'Title'}))\n\n const defaultName = createPublishedId(camelCase(title))\n const name =\n this.flags.name ??\n (this.isUnattended()\n ? defaultName\n : await input({\n default: defaultName,\n message: 'Name',\n }))\n\n try {\n const safeName = createPublishedId(camelCase(name))\n const destinationPath = path.resolve(mediaLibrary.aspectsPath, `${safeName}.ts`)\n const relativeDestinationPath = path.relative(process.cwd(), destinationPath)\n\n await mkdir(path.resolve(mediaLibrary.aspectsPath), {\n recursive: true,\n })\n\n const destinationPathExists = await access(destinationPath).then(\n () => true,\n () => false,\n )\n if (destinationPathExists) {\n this.error(`A file already exists at ${styleText('bold', relativeDestinationPath)}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n await fs.writeFile(\n destinationPath,\n template({\n name: safeName,\n title,\n }),\n )\n\n this.log(\n `${styleText('green', '✓')} Aspect created! ${styleText('bold', relativeDestinationPath)}`,\n )\n this.log()\n this.log('Next steps:')\n this.log(\n `Open ${styleText('bold', relativeDestinationPath)} in your code editor and customize the aspect.`,\n )\n this.log()\n this.log('Deploy this aspect by running:')\n this.log(styleText('bold', `sanity media deploy-aspect ${safeName}`))\n this.log()\n this.log('Deploy all aspects by running:')\n this.log(styleText('bold', `sanity media deploy-aspect --all`))\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n createAspectDebug('Failed to create aspect', error)\n this.error(`Failed to create aspect: ${message}`, {exit: exitCodes.RUNTIME_ERROR})\n }\n }\n}\n\nfunction template({name, title}: {name: string; title: string}) {\n return `import {defineAssetAspect, defineField} from 'sanity'\n\nexport default defineAssetAspect({\n name: '${name}',\n title: '${title}',\n type: 'object',\n fields: [\n defineField({\n name: 'string',\n title: 'Plain String',\n type: 'string',\n }),\n ],\n})\n`\n}\n"],"names":["fs","access","mkdir","path","styleText","Flags","exitCodes","SanityCommand","subdebug","requiredWhenUnattended","input","createPublishedId","camelCase","getMediaLibraryConfig","NO_MEDIA_LIBRARY_ASPECTS_PATH","createAspectDebug","MediaCreateAspectCommand","description","examples","command","flags","name","string","title","run","cliConfig","getCliConfig","mediaLibrary","aspectsPath","undefined","error","exit","RUNTIME_ERROR","message","defaultName","isUnattended","default","safeName","destinationPath","resolve","relativeDestinationPath","relative","process","cwd","recursive","destinationPathExists","then","writeFile","template","log","Error","String"],"mappings":"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"}