@sanity/cli 8.25.0 → 8.27.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 (127) hide show
  1. package/README.md +3 -2
  2. package/dist/actions/build/shouldAutoUpdate.js +1 -26
  3. package/dist/actions/build/shouldAutoUpdate.js.map +1 -1
  4. package/dist/actions/context/mcpEndpoint.js +165 -0
  5. package/dist/actions/context/mcpEndpoint.js.map +1 -0
  6. package/dist/actions/context/resolveOrganizationId.js +8 -1
  7. package/dist/actions/context/resolveOrganizationId.js.map +1 -1
  8. package/dist/actions/deploy/deployApp.js +10 -3
  9. package/dist/actions/deploy/deployApp.js.map +1 -1
  10. package/dist/actions/deploy/deployStudio.js +11 -4
  11. package/dist/actions/deploy/deployStudio.js.map +1 -1
  12. package/dist/actions/init/initAction.js +3 -3
  13. package/dist/actions/init/initAction.js.map +1 -1
  14. package/dist/actions/init/plan/verifyCoupon.js +0 -1
  15. package/dist/actions/init/plan/verifyCoupon.js.map +1 -1
  16. package/dist/actions/init/scaffoldTemplate.js +1 -1
  17. package/dist/actions/init/scaffoldTemplate.js.map +1 -1
  18. package/dist/commands/api.js +10 -0
  19. package/dist/commands/api.js.map +1 -1
  20. package/dist/commands/backups/download.js +6 -0
  21. package/dist/commands/backups/download.js.map +1 -1
  22. package/dist/commands/context/create.js +8 -22
  23. package/dist/commands/context/create.js.map +1 -1
  24. package/dist/commands/context/delete.js +8 -1
  25. package/dist/commands/context/delete.js.map +1 -1
  26. package/dist/commands/context/issues/list.js +0 -5
  27. package/dist/commands/context/issues/list.js.map +1 -1
  28. package/dist/commands/context/list.js +6 -14
  29. package/dist/commands/context/list.js.map +1 -1
  30. package/dist/commands/context/mcp/create.js +152 -0
  31. package/dist/commands/context/mcp/create.js.map +1 -0
  32. package/dist/commands/context/mcp/delete.js +82 -0
  33. package/dist/commands/context/mcp/delete.js.map +1 -0
  34. package/dist/commands/context/mcp/get.js +42 -0
  35. package/dist/commands/context/mcp/get.js.map +1 -0
  36. package/dist/commands/context/mcp/list.js +87 -0
  37. package/dist/commands/context/mcp/list.js.map +1 -0
  38. package/dist/commands/context/mcp/status.js +98 -0
  39. package/dist/commands/context/mcp/status.js.map +1 -0
  40. package/dist/commands/context/mcp/update.js +225 -0
  41. package/dist/commands/context/mcp/update.js.map +1 -0
  42. package/dist/commands/context/query.js +6 -14
  43. package/dist/commands/context/query.js.map +1 -1
  44. package/dist/commands/context/update.js +12 -1
  45. package/dist/commands/context/update.js.map +1 -1
  46. package/dist/commands/datasets/create.js +6 -0
  47. package/dist/commands/datasets/create.js.map +1 -1
  48. package/dist/commands/datasets/embeddings/enable.js +6 -0
  49. package/dist/commands/datasets/embeddings/enable.js.map +1 -1
  50. package/dist/commands/datasets/import.js +6 -0
  51. package/dist/commands/datasets/import.js.map +1 -1
  52. package/dist/commands/deploy.js +7 -0
  53. package/dist/commands/deploy.js.map +1 -1
  54. package/dist/commands/documents/validate.js +6 -0
  55. package/dist/commands/documents/validate.js.map +1 -1
  56. package/dist/commands/exec.js +4 -2
  57. package/dist/commands/exec.js.map +1 -1
  58. package/dist/commands/init.js +13 -0
  59. package/dist/commands/init.js.map +1 -1
  60. package/dist/commands/manifest/extract.js +6 -0
  61. package/dist/commands/manifest/extract.js.map +1 -1
  62. package/dist/commands/media/create-aspect.js +7 -0
  63. package/dist/commands/media/create-aspect.js.map +1 -1
  64. package/dist/commands/migrations/run.js +6 -0
  65. package/dist/commands/migrations/run.js.map +1 -1
  66. package/dist/commands/organizations/create.js +6 -0
  67. package/dist/commands/organizations/create.js.map +1 -1
  68. package/dist/commands/organizations/update.js +6 -0
  69. package/dist/commands/organizations/update.js.map +1 -1
  70. package/dist/commands/schemas/delete.js +6 -0
  71. package/dist/commands/schemas/delete.js.map +1 -1
  72. package/dist/commands/schemas/deploy.js +6 -0
  73. package/dist/commands/schemas/deploy.js.map +1 -1
  74. package/dist/commands/schemas/extract.js +28 -3
  75. package/dist/commands/schemas/extract.js.map +1 -1
  76. package/dist/commands/schemas/list.js +6 -0
  77. package/dist/commands/schemas/list.js.map +1 -1
  78. package/dist/commands/schemas/validate.js +6 -0
  79. package/dist/commands/schemas/validate.js.map +1 -1
  80. package/dist/commands/tokens/rotate.js +6 -0
  81. package/dist/commands/tokens/rotate.js.map +1 -1
  82. package/dist/commands/typegen/generate.js +25 -1
  83. package/dist/commands/typegen/generate.js.map +1 -1
  84. package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js +6 -0
  85. package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js.map +1 -1
  86. package/dist/generated/apiRoutes.js +22 -0
  87. package/dist/generated/apiRoutes.js.map +1 -1
  88. package/dist/hooks/prerun/setupTelemetry.js +2 -3
  89. package/dist/hooks/prerun/setupTelemetry.js.map +1 -1
  90. package/dist/prompts/promptForText.js +12 -0
  91. package/dist/prompts/promptForText.js.map +1 -0
  92. package/dist/services/context.js +174 -1
  93. package/dist/services/context.js.map +1 -1
  94. package/dist/services/telemetry.js +4 -2
  95. package/dist/services/telemetry.js.map +1 -1
  96. package/dist/telemetry/cli.telemetry.js +1 -1
  97. package/dist/telemetry/cli.telemetry.js.map +1 -1
  98. package/dist/telemetry/init.telemetry.js +1 -1
  99. package/dist/telemetry/init.telemetry.js.map +1 -1
  100. package/dist/telemetry/typegen.telemetry.js +12 -0
  101. package/dist/telemetry/typegen.telemetry.js.map +1 -0
  102. package/dist/util/parseArguments.js +12 -40
  103. package/dist/util/parseArguments.js.map +1 -1
  104. package/dist/util/sharedFlags.js.map +1 -1
  105. package/dist/util/telemetry/cliCommandIdentity.js +222 -0
  106. package/dist/util/telemetry/cliCommandIdentity.js.map +1 -0
  107. package/dist/util/telemetry/cliTelemetryFlags.js +186 -0
  108. package/dist/util/telemetry/cliTelemetryFlags.js.map +1 -0
  109. package/dist/util/telemetry/commandTelemetry.js +56 -11
  110. package/dist/util/telemetry/commandTelemetry.js.map +1 -1
  111. package/dist/util/telemetry/createTelemetryStore.js +13 -5
  112. package/dist/util/telemetry/createTelemetryStore.js.map +1 -1
  113. package/dist/util/telemetry/createTraceId.js +3 -3
  114. package/dist/util/telemetry/createTraceId.js.map +1 -1
  115. package/dist/util/telemetry/flushTelemetryFiles.js +14 -4
  116. package/dist/util/telemetry/flushTelemetryFiles.js.map +1 -1
  117. package/dist/util/telemetry/logger.js +1 -1
  118. package/dist/util/telemetry/logger.js.map +1 -1
  119. package/dist/util/telemetry/readNDJSON.js +1 -1
  120. package/dist/util/telemetry/readNDJSON.js.map +1 -1
  121. package/dist/util/telemetry/sanitizeTelemetryEvent.js +304 -0
  122. package/dist/util/telemetry/sanitizeTelemetryEvent.js.map +1 -0
  123. package/dist/util/telemetry/trace.js +4 -7
  124. package/dist/util/telemetry/trace.js.map +1 -1
  125. package/oclif.config.js +1 -1
  126. package/oclif.manifest.json +2380 -1526
  127. package/package.json +8 -11
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/documents/validate.ts"],"sourcesContent":["import {stat} from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Flags} from '@oclif/core'\nimport {exitCodes} from '@sanity/cli-core'\nimport {ProjectRootNotFoundError} from '@sanity/cli-core/errors'\nimport {SanityCommand} from '@sanity/cli-core/SanityCommand'\nimport {type CliConfig} from '@sanity/cli-core/types'\nimport {confirm, logSymbols} from '@sanity/cli-core/ux'\n\nimport {type Level} from '../../actions/documents/types.js'\nimport {validateDocuments} from '../../actions/documents/validate.js'\nimport {reporters} from '../../actions/documents/validation/reporters/index.js'\nimport {getDatasetFlag, getProjectIdFlag} from '../../util/sharedFlags.js'\n\nexport class ValidateDocumentsCommand extends SanityCommand<typeof ValidateDocumentsCommand> {\n static description = 'Validate documents in a dataset against the studio schema'\n\n static examples = [\n {\n command: '<%= config.bin %> <%= command.id %> --workspace default',\n description: 'Validates all documents in a Sanity project with more than one workspace',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --workspace default --dataset staging',\n description: 'Override the dataset specified in the workspace',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --yes > report.txt',\n description: 'Save the results of the report into a file',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --level info',\n description: 'Report out info level validation markers too',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --project abc123 --dataset production',\n description: 'Validate documents in a specific project and dataset',\n },\n ]\n\n static flags = {\n ...getProjectIdFlag({\n description:\n 'Override the project ID used. By default, this is derived from the given workspace',\n semantics: 'specify',\n }),\n ...getDatasetFlag({\n description:\n 'Override the dataset used. By default, this is derived from the given workspace',\n semantics: 'specify',\n }),\n file: Flags.string({\n description:\n 'Path to an NDJSON file or tar archive containing an NDJSON file (optionally gzip-compressed)',\n }),\n format: Flags.string({\n description:\n 'The output format used to print the found validation markers and report progress',\n options: ['json', 'ndjson', 'pretty'],\n }),\n level: Flags.custom<Level>({\n default: 'warning',\n description: 'The minimum level reported. Defaults to warning',\n options: ['error', 'warning', 'info'],\n })(),\n 'max-custom-validation-concurrency': Flags.integer({\n default: 5,\n description: 'Specify how many custom validators can run concurrently',\n }),\n 'max-fetch-concurrency': Flags.integer({\n default: 25,\n description: 'Specify how many `client.fetch` requests are allowed to run concurrently',\n }),\n workspace: Flags.string({\n description: 'The name of the workspace to use when downloading and validating all documents',\n }),\n yes: Flags.boolean({\n char: 'y',\n default: false,\n description: 'Skips the first confirmation prompt',\n }),\n }\n\n static override hiddenAliases: string[] = ['document:validate']\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(ValidateDocumentsCommand)\n const {\n dataset,\n file,\n format,\n level,\n 'max-custom-validation-concurrency': maxCustomValidationConcurrency,\n 'max-fetch-concurrency': maxFetchConcurrency,\n project: projectId,\n workspace,\n } = flags\n const unattendedMode = this.isUnattended()\n\n let workDir: string\n let cliConfig: CliConfig\n try {\n const root = await this.getProjectRoot()\n workDir = root.directory\n cliConfig = await this.getCliConfig()\n } catch (err) {\n if (err instanceof ProjectRootNotFoundError) {\n return this.output.error(\n 'This command must be run from within a Sanity project directory (requires studio schema for validation)',\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n throw err\n }\n\n let ndjsonFilePath\n if (file) {\n const filePath = path.resolve(workDir, file)\n\n let fileStat\n try {\n fileStat = await stat(filePath)\n } catch {\n return this.output.error(\n `File not found: ${file}. Pass an existing NDJSON file or tar archive with \\`--file <path>\\`.`,\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n if (!fileStat.isFile()) {\n return this.output.error(\n `Invalid file path: ${file} is not a file. Pass an NDJSON file or tar archive with \\`--file <path>\\`.`,\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n ndjsonFilePath = filePath\n }\n\n if (!unattendedMode) {\n this.output.log(\n `${styleText('yellow', `${logSymbols.warning} Warning:`)} This command ${\n file\n ? 'reads all documents from your input file'\n : 'downloads all documents from your dataset'\n } and processes them through your local schema within a ` +\n `simulated browser environment.\\n`,\n )\n this.output.log(`Potential pitfalls:\\n`)\n this.output.log(\n `- Processes all documents locally (excluding assets). Large datasets may require more resources.`,\n )\n this.output.log(\n `- Executes all custom validation functions. Some functions may need to be refactored for compatibility.`,\n )\n this.output.log(\n `- Not all standard browser features are available and may cause issues while loading your Studio.`,\n )\n this.output.log(\n `- Adheres to document permissions. Ensure this account can see all desired documents.`,\n )\n if (file) {\n this.output.log(\n `- Checks for missing document references against the live dataset if not found in your file.`,\n )\n }\n\n const confirmed = await confirm({\n default: true,\n message: `Are you sure you want to continue?`,\n })\n\n if (!confirmed) {\n this.output.log('Validation cancelled')\n return this.exit(exitCodes.USER_ABORT)\n }\n }\n\n try {\n const overallLevel = await validateDocuments({\n dataset,\n level,\n maxCustomValidationConcurrency,\n maxFetchConcurrency,\n ndjsonFilePath,\n projectId,\n reporter: (worker) => {\n const reporter =\n format && format in reporters\n ? reporters[format as keyof typeof reporters]\n : reporters.pretty\n\n return reporter({flags, output: this.output, worker})\n },\n studioHost: cliConfig.studioHost,\n workDir,\n workspace,\n })\n\n if (overallLevel === 'error') {\n return this.exit(exitCodes.RUNTIME_ERROR)\n }\n } catch (err) {\n return this.output.error(err instanceof Error ? err.message : String(err), {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n}\n"],"names":["stat","path","styleText","Flags","exitCodes","ProjectRootNotFoundError","SanityCommand","confirm","logSymbols","validateDocuments","reporters","getDatasetFlag","getProjectIdFlag","ValidateDocumentsCommand","description","examples","command","flags","semantics","file","string","format","options","level","custom","default","integer","workspace","yes","boolean","char","hiddenAliases","run","parse","dataset","maxCustomValidationConcurrency","maxFetchConcurrency","project","projectId","unattendedMode","isUnattended","workDir","cliConfig","root","getProjectRoot","directory","getCliConfig","err","output","error","exit","RUNTIME_ERROR","ndjsonFilePath","filePath","resolve","fileStat","USAGE_ERROR","isFile","log","warning","confirmed","message","USER_ABORT","overallLevel","reporter","worker","pretty","studioHost","Error","String"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/documents/validate.ts"],"sourcesContent":["import {stat} from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Flags} from '@oclif/core'\nimport {exitCodes} from '@sanity/cli-core'\nimport {ProjectRootNotFoundError} from '@sanity/cli-core/errors'\nimport {SanityCommand} from '@sanity/cli-core/SanityCommand'\nimport {type CliConfig} from '@sanity/cli-core/types'\nimport {confirm, logSymbols} from '@sanity/cli-core/ux'\n\nimport {type Level} from '../../actions/documents/types.js'\nimport {validateDocuments} from '../../actions/documents/validate.js'\nimport {reporters} from '../../actions/documents/validation/reporters/index.js'\nimport {getDatasetFlag, getProjectIdFlag} from '../../util/sharedFlags.js'\nimport {defineCommandTelemetry} from '../../util/telemetry/commandTelemetry.js'\n\nexport class ValidateDocumentsCommand extends SanityCommand<typeof ValidateDocumentsCommand> {\n static description = 'Validate documents in a dataset against the studio schema'\n\n static examples = [\n {\n command: '<%= config.bin %> <%= command.id %> --workspace default',\n description: 'Validates all documents in a Sanity project with more than one workspace',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --workspace default --dataset staging',\n description: 'Override the dataset specified in the workspace',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --yes > report.txt',\n description: 'Save the results of the report into a file',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --level info',\n description: 'Report out info level validation markers too',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --project abc123 --dataset production',\n description: 'Validate documents in a specific project and dataset',\n },\n ]\n\n static flags = {\n ...getProjectIdFlag({\n description:\n 'Override the project ID used. By default, this is derived from the given workspace',\n semantics: 'specify',\n }),\n ...getDatasetFlag({\n description:\n 'Override the dataset used. By default, this is derived from the given workspace',\n semantics: 'specify',\n }),\n file: Flags.string({\n description:\n 'Path to an NDJSON file or tar archive containing an NDJSON file (optionally gzip-compressed)',\n }),\n format: Flags.string({\n description:\n 'The output format used to print the found validation markers and report progress',\n options: ['json', 'ndjson', 'pretty'],\n }),\n level: Flags.custom<Level>({\n default: 'warning',\n description: 'The minimum level reported. Defaults to warning',\n options: ['error', 'warning', 'info'],\n })(),\n 'max-custom-validation-concurrency': Flags.integer({\n default: 5,\n description: 'Specify how many custom validators can run concurrently',\n }),\n 'max-fetch-concurrency': Flags.integer({\n default: 25,\n description: 'Specify how many `client.fetch` requests are allowed to run concurrently',\n }),\n workspace: Flags.string({\n description: 'The name of the workspace to use when downloading and validating all documents',\n }),\n yes: Flags.boolean({\n char: 'y',\n default: false,\n description: 'Skips the first confirmation prompt',\n }),\n }\n\n static override hiddenAliases: string[] = ['document:validate']\n\n static telemetry = defineCommandTelemetry(this.flags, {redact: ['file']})\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(ValidateDocumentsCommand)\n const {\n dataset,\n file,\n format,\n level,\n 'max-custom-validation-concurrency': maxCustomValidationConcurrency,\n 'max-fetch-concurrency': maxFetchConcurrency,\n project: projectId,\n workspace,\n } = flags\n const unattendedMode = this.isUnattended()\n\n let workDir: string\n let cliConfig: CliConfig\n try {\n const root = await this.getProjectRoot()\n workDir = root.directory\n cliConfig = await this.getCliConfig()\n } catch (err) {\n if (err instanceof ProjectRootNotFoundError) {\n return this.output.error(\n 'This command must be run from within a Sanity project directory (requires studio schema for validation)',\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n throw err\n }\n\n let ndjsonFilePath\n if (file) {\n const filePath = path.resolve(workDir, file)\n\n let fileStat\n try {\n fileStat = await stat(filePath)\n } catch {\n return this.output.error(\n `File not found: ${file}. Pass an existing NDJSON file or tar archive with \\`--file <path>\\`.`,\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n if (!fileStat.isFile()) {\n return this.output.error(\n `Invalid file path: ${file} is not a file. Pass an NDJSON file or tar archive with \\`--file <path>\\`.`,\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n ndjsonFilePath = filePath\n }\n\n if (!unattendedMode) {\n this.output.log(\n `${styleText('yellow', `${logSymbols.warning} Warning:`)} This command ${\n file\n ? 'reads all documents from your input file'\n : 'downloads all documents from your dataset'\n } and processes them through your local schema within a ` +\n `simulated browser environment.\\n`,\n )\n this.output.log(`Potential pitfalls:\\n`)\n this.output.log(\n `- Processes all documents locally (excluding assets). Large datasets may require more resources.`,\n )\n this.output.log(\n `- Executes all custom validation functions. Some functions may need to be refactored for compatibility.`,\n )\n this.output.log(\n `- Not all standard browser features are available and may cause issues while loading your Studio.`,\n )\n this.output.log(\n `- Adheres to document permissions. Ensure this account can see all desired documents.`,\n )\n if (file) {\n this.output.log(\n `- Checks for missing document references against the live dataset if not found in your file.`,\n )\n }\n\n const confirmed = await confirm({\n default: true,\n message: `Are you sure you want to continue?`,\n })\n\n if (!confirmed) {\n this.output.log('Validation cancelled')\n return this.exit(exitCodes.USER_ABORT)\n }\n }\n\n try {\n const overallLevel = await validateDocuments({\n dataset,\n level,\n maxCustomValidationConcurrency,\n maxFetchConcurrency,\n ndjsonFilePath,\n projectId,\n reporter: (worker) => {\n const reporter =\n format && format in reporters\n ? reporters[format as keyof typeof reporters]\n : reporters.pretty\n\n return reporter({flags, output: this.output, worker})\n },\n studioHost: cliConfig.studioHost,\n workDir,\n workspace,\n })\n\n if (overallLevel === 'error') {\n return this.exit(exitCodes.RUNTIME_ERROR)\n }\n } catch (err) {\n return this.output.error(err instanceof Error ? err.message : String(err), {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n}\n"],"names":["stat","path","styleText","Flags","exitCodes","ProjectRootNotFoundError","SanityCommand","confirm","logSymbols","validateDocuments","reporters","getDatasetFlag","getProjectIdFlag","defineCommandTelemetry","ValidateDocumentsCommand","description","examples","command","flags","semantics","file","string","format","options","level","custom","default","integer","workspace","yes","boolean","char","hiddenAliases","telemetry","redact","run","parse","dataset","maxCustomValidationConcurrency","maxFetchConcurrency","project","projectId","unattendedMode","isUnattended","workDir","cliConfig","root","getProjectRoot","directory","getCliConfig","err","output","error","exit","RUNTIME_ERROR","ndjsonFilePath","filePath","resolve","fileStat","USAGE_ERROR","isFile","log","warning","confirmed","message","USER_ABORT","overallLevel","reporter","worker","pretty","studioHost","Error","String"],"mappings":"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"}
@@ -40,10 +40,12 @@ export class ExecCommand extends SanityCommand {
40
40
  };
41
41
  static strict = false;
42
42
  async run() {
43
- const { args, argv, flags } = await this.parse(ExecCommand);
43
+ const { args, flags, raw } = await this.parse(ExecCommand);
44
44
  const { directory: workDir } = await this.getProjectRoot();
45
+ // oclif may reorder duplicate unparsed argv, while raw tokens preserve their original order.
46
+ const extraArguments = raw.filter((token)=>token.type === 'arg').slice(1).map((token)=>token.input);
45
47
  await execScript({
46
- extraArguments: argv.slice(1),
48
+ extraArguments,
47
49
  flags,
48
50
  scriptPath: args.script,
49
51
  workDir
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/exec.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {SanityCommand} from '@sanity/cli-core'\n\nimport {execScript} from '../actions/exec/execScript.js'\n\nexport class ExecCommand extends SanityCommand<typeof ExecCommand> {\n static override args = {\n script: Args.file({\n description: 'Path to the script to execute',\n exists: true,\n required: true,\n }),\n }\n\n static override description = 'Executes a script within the Sanity Studio context'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> some/script.js',\n description: 'Run the script at some/script.js in Sanity context',\n },\n {\n command: '<%= config.bin %> <%= command.id %> migrations/fullname.ts --with-user-token',\n description:\n \"Run the script at migrations/fullname.ts and configure `getCliClient()` from `sanity/cli` to include the current user's token\",\n },\n {\n command: '<%= config.bin %> <%= command.id %> scripts/browserScript.js --mock-browser-env',\n description: 'Run the script at scripts/browserScript.js in a mock browser environment',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> --mock-browser-env myscript.js -- --dry-run positional-argument',\n description:\n \"Pass arbitrary arguments to scripts by separating them with a `--`. Arguments are available in `process.argv` as they would in regular node scripts (eg the following command would yield a `process.argv` of: `['/path/to/node', '/path/to/myscript.js', '--dry-run', 'positional-argument']`)\",\n },\n ]\n\n static override flags = {\n 'mock-browser-env': Flags.boolean({\n default: false,\n description: 'Mock a browser environment with jsdom',\n }),\n 'with-user-token': Flags.boolean({\n default: false,\n description: 'Include your auth token in getCliClient()',\n }),\n }\n\n static override strict = false\n\n public async run(): Promise<void> {\n const {args, argv, flags} = await this.parse(ExecCommand)\n const {directory: workDir} = await this.getProjectRoot()\n\n await execScript({\n extraArguments: (argv as string[]).slice(1), // Remove the script path from argv\n flags,\n scriptPath: args.script,\n workDir,\n })\n }\n}\n"],"names":["Args","Flags","SanityCommand","execScript","ExecCommand","args","script","file","description","exists","required","examples","command","flags","boolean","default","strict","run","argv","parse","directory","workDir","getProjectRoot","extraArguments","slice","scriptPath"],"mappings":"AAAA,SAAQA,IAAI,EAAEC,KAAK,QAAO,cAAa;AACvC,SAAQC,aAAa,QAAO,mBAAkB;AAE9C,SAAQC,UAAU,QAAO,gCAA+B;AAExD,OAAO,MAAMC,oBAAoBF;IAC/B,OAAgBG,OAAO;QACrBC,QAAQN,KAAKO,IAAI,CAAC;YAChBC,aAAa;YACbC,QAAQ;YACRC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBF,cAAc,qDAAoD;IAElF,OAAgBG,WAAW;QACzB;YACEC,SAAS;YACTJ,aAAa;QACf;QACA;YACEI,SAAS;YACTJ,aACE;QACJ;QACA;YACEI,SAAS;YACTJ,aAAa;QACf;QACA;YACEI,SACE;YACFJ,aACE;QACJ;KACD,CAAA;IAED,OAAgBK,QAAQ;QACtB,oBAAoBZ,MAAMa,OAAO,CAAC;YAChCC,SAAS;YACTP,aAAa;QACf;QACA,mBAAmBP,MAAMa,OAAO,CAAC;YAC/BC,SAAS;YACTP,aAAa;QACf;IACF,EAAC;IAED,OAAgBQ,SAAS,MAAK;IAE9B,MAAaC,MAAqB;QAChC,MAAM,EAACZ,IAAI,EAAEa,IAAI,EAAEL,KAAK,EAAC,GAAG,MAAM,IAAI,CAACM,KAAK,CAACf;QAC7C,MAAM,EAACgB,WAAWC,OAAO,EAAC,GAAG,MAAM,IAAI,CAACC,cAAc;QAEtD,MAAMnB,WAAW;YACfoB,gBAAgB,AAACL,KAAkBM,KAAK,CAAC;YACzCX;YACAY,YAAYpB,KAAKC,MAAM;YACvBe;QACF;IACF;AACF"}
1
+ {"version":3,"sources":["../../src/commands/exec.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {SanityCommand} from '@sanity/cli-core'\n\nimport {execScript} from '../actions/exec/execScript.js'\n\nexport class ExecCommand extends SanityCommand<typeof ExecCommand> {\n static override args = {\n script: Args.file({\n description: 'Path to the script to execute',\n exists: true,\n required: true,\n }),\n }\n\n static override description = 'Executes a script within the Sanity Studio context'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> some/script.js',\n description: 'Run the script at some/script.js in Sanity context',\n },\n {\n command: '<%= config.bin %> <%= command.id %> migrations/fullname.ts --with-user-token',\n description:\n \"Run the script at migrations/fullname.ts and configure `getCliClient()` from `sanity/cli` to include the current user's token\",\n },\n {\n command: '<%= config.bin %> <%= command.id %> scripts/browserScript.js --mock-browser-env',\n description: 'Run the script at scripts/browserScript.js in a mock browser environment',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> --mock-browser-env myscript.js -- --dry-run positional-argument',\n description:\n \"Pass arbitrary arguments to scripts by separating them with a `--`. Arguments are available in `process.argv` as they would in regular node scripts (eg the following command would yield a `process.argv` of: `['/path/to/node', '/path/to/myscript.js', '--dry-run', 'positional-argument']`)\",\n },\n ]\n\n static override flags = {\n 'mock-browser-env': Flags.boolean({\n default: false,\n description: 'Mock a browser environment with jsdom',\n }),\n 'with-user-token': Flags.boolean({\n default: false,\n description: 'Include your auth token in getCliClient()',\n }),\n }\n\n static override strict = false\n\n public async run(): Promise<void> {\n const {args, flags, raw} = await this.parse(ExecCommand)\n const {directory: workDir} = await this.getProjectRoot()\n // oclif may reorder duplicate unparsed argv, while raw tokens preserve their original order.\n const extraArguments = raw\n .filter((token) => token.type === 'arg')\n .slice(1)\n .map((token) => token.input)\n\n await execScript({\n extraArguments,\n flags,\n scriptPath: args.script,\n workDir,\n })\n }\n}\n"],"names":["Args","Flags","SanityCommand","execScript","ExecCommand","args","script","file","description","exists","required","examples","command","flags","boolean","default","strict","run","raw","parse","directory","workDir","getProjectRoot","extraArguments","filter","token","type","slice","map","input","scriptPath"],"mappings":"AAAA,SAAQA,IAAI,EAAEC,KAAK,QAAO,cAAa;AACvC,SAAQC,aAAa,QAAO,mBAAkB;AAE9C,SAAQC,UAAU,QAAO,gCAA+B;AAExD,OAAO,MAAMC,oBAAoBF;IAC/B,OAAgBG,OAAO;QACrBC,QAAQN,KAAKO,IAAI,CAAC;YAChBC,aAAa;YACbC,QAAQ;YACRC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBF,cAAc,qDAAoD;IAElF,OAAgBG,WAAW;QACzB;YACEC,SAAS;YACTJ,aAAa;QACf;QACA;YACEI,SAAS;YACTJ,aACE;QACJ;QACA;YACEI,SAAS;YACTJ,aAAa;QACf;QACA;YACEI,SACE;YACFJ,aACE;QACJ;KACD,CAAA;IAED,OAAgBK,QAAQ;QACtB,oBAAoBZ,MAAMa,OAAO,CAAC;YAChCC,SAAS;YACTP,aAAa;QACf;QACA,mBAAmBP,MAAMa,OAAO,CAAC;YAC/BC,SAAS;YACTP,aAAa;QACf;IACF,EAAC;IAED,OAAgBQ,SAAS,MAAK;IAE9B,MAAaC,MAAqB;QAChC,MAAM,EAACZ,IAAI,EAAEQ,KAAK,EAAEK,GAAG,EAAC,GAAG,MAAM,IAAI,CAACC,KAAK,CAACf;QAC5C,MAAM,EAACgB,WAAWC,OAAO,EAAC,GAAG,MAAM,IAAI,CAACC,cAAc;QACtD,6FAA6F;QAC7F,MAAMC,iBAAiBL,IACpBM,MAAM,CAAC,CAACC,QAAUA,MAAMC,IAAI,KAAK,OACjCC,KAAK,CAAC,GACNC,GAAG,CAAC,CAACH,QAAUA,MAAMI,KAAK;QAE7B,MAAM1B,WAAW;YACfoB;YACAV;YACAiB,YAAYzB,KAAKC,MAAM;YACvBe;QACF;IACF;AACF"}
@@ -5,6 +5,7 @@ import { initAction } from '../actions/init/initAction.js';
5
5
  import { InitError } from '../actions/init/initError.js';
6
6
  import { flagsToInitOptions } from '../actions/init/types.js';
7
7
  import { getProjectIdFlag } from '../util/sharedFlags.js';
8
+ import { defineCommandTelemetry } from '../util/telemetry/commandTelemetry.js';
8
9
  export class InitCommand extends SanityCommand {
9
10
  static args = {
10
11
  type: Args.string({
@@ -254,6 +255,18 @@ export class InitCommand extends SanityCommand {
254
255
  description: 'Unattended mode, answers "yes" to any "yes/no" prompt and otherwise uses defaults'
255
256
  })
256
257
  };
258
+ static telemetry = defineCommandTelemetry(this.flags, {
259
+ redact: [
260
+ 'template-token',
261
+ 'template',
262
+ 'git',
263
+ 'env',
264
+ 'output-path',
265
+ 'project-name',
266
+ 'create-project',
267
+ 'coupon'
268
+ ]
269
+ });
257
270
  async run() {
258
271
  let mcpMode = 'prompt';
259
272
  if (!this.flags.mcp || !this.resolveIsInteractive()) {
@@ -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'\nimport {getProjectIdFlag} from '../util/sharedFlags.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 dashboard: Flags.boolean({\n description: 'Set up the project to run in the Sanity Dashboard (beta)',\n exclusive: ['bare', 'env'],\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 install: Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Install dependencies after scaffolding',\n exclusive: ['bare'],\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 ...getProjectIdFlag({\n description: 'Project ID to use for the studio',\n exclusive: ['create-project', 'project-name'],\n semantics: 'specify',\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 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","getProjectIdFlag","InitCommand","args","type","string","hidden","description","enableJsonFlag","examples","command","flags","boolean","allowNo","default","exclusive","bare","coupon","helpValue","deprecated","message","dashboard","dataset","env","parse","input","startsWith","git","undefined","helpLabel","install","mcp","helpGroup","organization","options","semantics","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'\nimport {getProjectIdFlag} from '../util/sharedFlags.js'\nimport {defineCommandTelemetry} from '../util/telemetry/commandTelemetry.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 dashboard: Flags.boolean({\n description: 'Set up the project to run in the Sanity Dashboard (beta)',\n exclusive: ['bare', 'env'],\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 install: Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Install dependencies after scaffolding',\n exclusive: ['bare'],\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 ...getProjectIdFlag({\n description: 'Project ID to use for the studio',\n exclusive: ['create-project', 'project-name'],\n semantics: 'specify',\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 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 static telemetry = defineCommandTelemetry(this.flags, {\n redact: [\n 'template-token',\n 'template',\n 'git',\n 'env',\n 'output-path',\n 'project-name',\n 'create-project',\n 'coupon',\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","getProjectIdFlag","defineCommandTelemetry","InitCommand","args","type","string","hidden","description","enableJsonFlag","examples","command","flags","boolean","allowNo","default","exclusive","bare","coupon","helpValue","deprecated","message","dashboard","dataset","env","parse","input","startsWith","git","undefined","helpLabel","install","mcp","helpGroup","organization","options","semantics","provider","quickstart","reconfigure","version","skills","template","typescript","visibility","yes","char","telemetry","redact","run","mcpMode","resolveIsInteractive","isUnattended","skillsMode","output","workDir","process","cwd","error","exit","exitCode"],"mappings":"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"}
@@ -3,6 +3,7 @@ import { formatSchemaValidation, SchemaExtractionError } from '@sanity/cli-build
3
3
  import { exitCodes, findProjectRoot, SanityCommand } from '@sanity/cli-core';
4
4
  import { manifestDebug } from '../../actions/manifest/debug.js';
5
5
  import { extractManifest } from '../../actions/manifest/extractManifest.js';
6
+ import { defineCommandTelemetry } from '../../util/telemetry/commandTelemetry.js';
6
7
  const description = `
7
8
  Extract studio configuration as JSON manifest files.
8
9
 
@@ -26,6 +27,11 @@ export class ExtractManifestCommand extends SanityCommand {
26
27
  description: 'Optional path to specify destination directory of the manifest files'
27
28
  })
28
29
  };
30
+ static telemetry = defineCommandTelemetry(this.flags, {
31
+ redact: [
32
+ 'path'
33
+ ]
34
+ });
29
35
  async run() {
30
36
  const { flags } = await this.parse(ExtractManifestCommand);
31
37
  try {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/manifest/extract.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {formatSchemaValidation, SchemaExtractionError} from '@sanity/cli-build/_internal/extract'\nimport {exitCodes, findProjectRoot, SanityCommand} from '@sanity/cli-core'\n\nimport {manifestDebug} from '../../actions/manifest/debug.js'\nimport {extractManifest} from '../../actions/manifest/extractManifest.js'\n\nconst description = `\nExtract studio configuration as JSON manifest files.\n\nNote: This command is experimental and subject to change. It is currently intended for use with Create only.\n`.trim()\n\nexport class ExtractManifestCommand extends SanityCommand<typeof ExtractManifestCommand> {\n static override description = description\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Extracts manifests',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --path /public/static',\n description: 'Extracts manifests into /public/static',\n },\n ]\n\n static override flags = {\n path: Flags.string({\n default: 'dist/static',\n description: 'Optional path to specify destination directory of the manifest files',\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(ExtractManifestCommand)\n\n try {\n const projectRoot = await findProjectRoot(process.cwd())\n await extractManifest({\n outPath: flags.path,\n path: projectRoot.path,\n workDir: projectRoot.directory,\n })\n } catch (error) {\n manifestDebug('Error extracting manifest in command', error)\n if (\n error instanceof SchemaExtractionError &&\n error.validation &&\n error.validation.length > 0\n ) {\n this.output.log(formatSchemaValidation(error.validation))\n this.exit(exitCodes.RUNTIME_ERROR)\n }\n\n this.error(\n `Failed to extract manifest:\\n${error instanceof Error ? error.message : String(error)}`,\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n }\n}\n"],"names":["Flags","formatSchemaValidation","SchemaExtractionError","exitCodes","findProjectRoot","SanityCommand","manifestDebug","extractManifest","description","trim","ExtractManifestCommand","examples","command","flags","path","string","default","run","parse","projectRoot","process","cwd","outPath","workDir","directory","error","validation","length","output","log","exit","RUNTIME_ERROR","Error","message","String"],"mappings":"AAAA,SAAQA,KAAK,QAAO,cAAa;AACjC,SAAQC,sBAAsB,EAAEC,qBAAqB,QAAO,sCAAqC;AACjG,SAAQC,SAAS,EAAEC,eAAe,EAAEC,aAAa,QAAO,mBAAkB;AAE1E,SAAQC,aAAa,QAAO,kCAAiC;AAC7D,SAAQC,eAAe,QAAO,4CAA2C;AAEzE,MAAMC,cAAc,CAAC;;;;AAIrB,CAAC,CAACC,IAAI;AAEN,OAAO,MAAMC,+BAA+BL;IAC1C,OAAgBG,cAAcA,YAAW;IAEzC,OAAgBG,WAAW;QACzB;YACEC,SAAS;YACTJ,aAAa;QACf;QACA;YACEI,SAAS;YACTJ,aAAa;QACf;KACD,CAAA;IAED,OAAgBK,QAAQ;QACtBC,MAAMd,MAAMe,MAAM,CAAC;YACjBC,SAAS;YACTR,aAAa;QACf;IACF,EAAC;IAED,MAAaS,MAAqB;QAChC,MAAM,EAACJ,KAAK,EAAC,GAAG,MAAM,IAAI,CAACK,KAAK,CAACR;QAEjC,IAAI;YACF,MAAMS,cAAc,MAAMf,gBAAgBgB,QAAQC,GAAG;YACrD,MAAMd,gBAAgB;gBACpBe,SAAST,MAAMC,IAAI;gBACnBA,MAAMK,YAAYL,IAAI;gBACtBS,SAASJ,YAAYK,SAAS;YAChC;QACF,EAAE,OAAOC,OAAO;YACdnB,cAAc,wCAAwCmB;YACtD,IACEA,iBAAiBvB,yBACjBuB,MAAMC,UAAU,IAChBD,MAAMC,UAAU,CAACC,MAAM,GAAG,GAC1B;gBACA,IAAI,CAACC,MAAM,CAACC,GAAG,CAAC5B,uBAAuBwB,MAAMC,UAAU;gBACvD,IAAI,CAACI,IAAI,CAAC3B,UAAU4B,aAAa;YACnC;YAEA,IAAI,CAACN,KAAK,CACR,CAAC,6BAA6B,EAAEA,iBAAiBO,QAAQP,MAAMQ,OAAO,GAAGC,OAAOT,QAAQ,EACxF;gBAACK,MAAM3B,UAAU4B,aAAa;YAAA;QAElC;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/commands/manifest/extract.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {formatSchemaValidation, SchemaExtractionError} from '@sanity/cli-build/_internal/extract'\nimport {exitCodes, findProjectRoot, SanityCommand} from '@sanity/cli-core'\n\nimport {manifestDebug} from '../../actions/manifest/debug.js'\nimport {extractManifest} from '../../actions/manifest/extractManifest.js'\nimport {defineCommandTelemetry} from '../../util/telemetry/commandTelemetry.js'\n\nconst description = `\nExtract studio configuration as JSON manifest files.\n\nNote: This command is experimental and subject to change. It is currently intended for use with Create only.\n`.trim()\n\nexport class ExtractManifestCommand extends SanityCommand<typeof ExtractManifestCommand> {\n static override description = description\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Extracts manifests',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --path /public/static',\n description: 'Extracts manifests into /public/static',\n },\n ]\n\n static override flags = {\n path: Flags.string({\n default: 'dist/static',\n description: 'Optional path to specify destination directory of the manifest files',\n }),\n }\n\n static telemetry = defineCommandTelemetry(this.flags, {redact: ['path']})\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(ExtractManifestCommand)\n\n try {\n const projectRoot = await findProjectRoot(process.cwd())\n await extractManifest({\n outPath: flags.path,\n path: projectRoot.path,\n workDir: projectRoot.directory,\n })\n } catch (error) {\n manifestDebug('Error extracting manifest in command', error)\n if (\n error instanceof SchemaExtractionError &&\n error.validation &&\n error.validation.length > 0\n ) {\n this.output.log(formatSchemaValidation(error.validation))\n this.exit(exitCodes.RUNTIME_ERROR)\n }\n\n this.error(\n `Failed to extract manifest:\\n${error instanceof Error ? error.message : String(error)}`,\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n }\n}\n"],"names":["Flags","formatSchemaValidation","SchemaExtractionError","exitCodes","findProjectRoot","SanityCommand","manifestDebug","extractManifest","defineCommandTelemetry","description","trim","ExtractManifestCommand","examples","command","flags","path","string","default","telemetry","redact","run","parse","projectRoot","process","cwd","outPath","workDir","directory","error","validation","length","output","log","exit","RUNTIME_ERROR","Error","message","String"],"mappings":"AAAA,SAAQA,KAAK,QAAO,cAAa;AACjC,SAAQC,sBAAsB,EAAEC,qBAAqB,QAAO,sCAAqC;AACjG,SAAQC,SAAS,EAAEC,eAAe,EAAEC,aAAa,QAAO,mBAAkB;AAE1E,SAAQC,aAAa,QAAO,kCAAiC;AAC7D,SAAQC,eAAe,QAAO,4CAA2C;AACzE,SAAQC,sBAAsB,QAAO,2CAA0C;AAE/E,MAAMC,cAAc,CAAC;;;;AAIrB,CAAC,CAACC,IAAI;AAEN,OAAO,MAAMC,+BAA+BN;IAC1C,OAAgBI,cAAcA,YAAW;IAEzC,OAAgBG,WAAW;QACzB;YACEC,SAAS;YACTJ,aAAa;QACf;QACA;YACEI,SAAS;YACTJ,aAAa;QACf;KACD,CAAA;IAED,OAAgBK,QAAQ;QACtBC,MAAMf,MAAMgB,MAAM,CAAC;YACjBC,SAAS;YACTR,aAAa;QACf;IACF,EAAC;IAED,OAAOS,YAAYV,uBAAuB,IAAI,CAACM,KAAK,EAAE;QAACK,QAAQ;YAAC;SAAO;IAAA,GAAE;IAEzE,MAAaC,MAAqB;QAChC,MAAM,EAACN,KAAK,EAAC,GAAG,MAAM,IAAI,CAACO,KAAK,CAACV;QAEjC,IAAI;YACF,MAAMW,cAAc,MAAMlB,gBAAgBmB,QAAQC,GAAG;YACrD,MAAMjB,gBAAgB;gBACpBkB,SAASX,MAAMC,IAAI;gBACnBA,MAAMO,YAAYP,IAAI;gBACtBW,SAASJ,YAAYK,SAAS;YAChC;QACF,EAAE,OAAOC,OAAO;YACdtB,cAAc,wCAAwCsB;YACtD,IACEA,iBAAiB1B,yBACjB0B,MAAMC,UAAU,IAChBD,MAAMC,UAAU,CAACC,MAAM,GAAG,GAC1B;gBACA,IAAI,CAACC,MAAM,CAACC,GAAG,CAAC/B,uBAAuB2B,MAAMC,UAAU;gBACvD,IAAI,CAACI,IAAI,CAAC9B,UAAU+B,aAAa;YACnC;YAEA,IAAI,CAACN,KAAK,CACR,CAAC,6BAA6B,EAAEA,iBAAiBO,QAAQP,MAAMQ,OAAO,GAAGC,OAAOT,QAAQ,EACxF;gBAACK,MAAM9B,UAAU+B,aAAa;YAAA;QAElC;IACF;AACF"}
@@ -9,6 +9,7 @@ import { createPublishedId } from '@sanity/id-utils';
9
9
  import camelCase from 'lodash-es/camelCase.js';
10
10
  import { getMediaLibraryConfig } from '../../actions/media/getMediaLibraryConfig.js';
11
11
  import { NO_MEDIA_LIBRARY_ASPECTS_PATH } from '../../util/errorMessages.js';
12
+ import { defineCommandTelemetry } from '../../util/telemetry/commandTelemetry.js';
12
13
  const createAspectDebug = subdebug('media:create-aspect');
13
14
  export class MediaCreateAspectCommand extends SanityCommand {
14
15
  static description = 'Create a new aspect definition file';
@@ -26,6 +27,12 @@ export class MediaCreateAspectCommand extends SanityCommand {
26
27
  description: 'Aspect title'
27
28
  }))
28
29
  };
30
+ static telemetry = defineCommandTelemetry(this.flags, {
31
+ redact: [
32
+ 'name',
33
+ 'title'
34
+ ]
35
+ });
29
36
  async run() {
30
37
  const cliConfig = await this.getCliConfig();
31
38
  const mediaLibrary = getMediaLibraryConfig(cliConfig);
@@ -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 {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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"}
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'\nimport {defineCommandTelemetry} from '../../util/telemetry/commandTelemetry.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 static telemetry = defineCommandTelemetry(this.flags, {redact: ['name', 'title']})\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","defineCommandTelemetry","createAspectDebug","MediaCreateAspectCommand","description","examples","command","flags","name","string","title","telemetry","redact","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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"}
@@ -11,6 +11,7 @@ import { resolveMigrations } from '../../actions/migration/resolveMigrations.js'
11
11
  import { isLoadableMigrationScript, resolveMigrationScript } from '../../actions/migration/resolveMigrationScript.js';
12
12
  import { Table } from '../../util/responsiveTable.js';
13
13
  import { getProjectIdFlag } from '../../util/sharedFlags.js';
14
+ import { defineCommandTelemetry } from '../../util/telemetry/commandTelemetry.js';
14
15
  const runMigrationDebug = subdebug('migration:run');
15
16
  /**
16
17
  * Renders the `cause` chain of an error the way oclif's own error printer would.
@@ -90,6 +91,11 @@ export class RunMigrationCommand extends SanityCommand {
90
91
  static hiddenAliases = [
91
92
  'migration:run'
92
93
  ];
94
+ static telemetry = defineCommandTelemetry(this.flags, {
95
+ redact: [
96
+ 'from-export'
97
+ ]
98
+ });
93
99
  async run() {
94
100
  const { args, flags } = await this.parse(RunMigrationCommand);
95
101
  const { directory: workDir } = await this.getProjectRoot();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/migrations/run.ts"],"sourcesContent":["import path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exitCodes, getProjectCliClient, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {confirm, spinner} from '@sanity/cli-core/ux'\nimport {\n type APIConfig,\n DEFAULT_MUTATION_CONCURRENCY,\n dryRun,\n MAX_MUTATION_CONCURRENCY,\n type Migration,\n type MigrationProgress,\n run,\n UnknownTransactionOutcomeError,\n} from '@sanity/migrate'\n\nimport {DEFAULT_API_VERSION, MIGRATIONS_DIRECTORY} from '../../actions/migration/constants.js'\nimport {ensureApiVersionFormat} from '../../actions/migration/ensureApiVersionFormat.js'\nimport {prettyFormat} from '../../actions/migration/prettyMutationFormatter.js'\nimport {resolveMigrations} from '../../actions/migration/resolveMigrations.js'\nimport {\n isLoadableMigrationScript,\n resolveMigrationScript,\n} from '../../actions/migration/resolveMigrationScript.js'\nimport {Table} from '../../util/responsiveTable.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst runMigrationDebug = subdebug('migration:run')\n\n/**\n * Renders the `cause` chain of an error the way oclif's own error printer would.\n *\n * Used when printing an error ourselves to bypass oclif's hard word wrapping:\n * the underlying transport error (a timeout, a dropped connection) is the part\n * that explains _why_ the outcome is unknown, so it should not be dropped just\n * because the top-level message is printed separately.\n */\nfunction formatCauseChain(error: unknown): string[] {\n const lines: string[] = []\n let cause: unknown = error instanceof Error ? error.cause : undefined\n\n while (cause instanceof Error) {\n lines.push(`Caused by: ${cause.name}: ${cause.message}`)\n if ('code' in cause && typeof cause.code === 'string') {\n lines.push(`Code: ${cause.code}`)\n }\n cause = cause.cause\n }\n\n return lines\n}\n\nexport type RunMigrationFlags = RunMigrationCommand['flags']\n\nexport class RunMigrationCommand extends SanityCommand<typeof RunMigrationCommand> {\n static override args = {\n id: Args.string({\n description: 'ID',\n required: false,\n }),\n }\n\n static override description = 'Run a migration against a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> <id>',\n description: 'dry run the migration',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> <id> --no-dry-run --project xyz --dataset staging',\n description: 'execute the migration against a dataset',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> <id> --from-export=production.tar.gz --no-dry-run --project xyz --dataset staging',\n description: 'execute the migration using a dataset export as the source',\n },\n ]\n\n static override flags = {\n 'api-version': Flags.string({\n description: `API version to use when migrating. Defaults to ${DEFAULT_API_VERSION}.`,\n }),\n concurrency: Flags.integer({\n default: DEFAULT_MUTATION_CONCURRENCY,\n description: `How many mutation requests to run in parallel. Must be between 1 and ${MAX_MUTATION_CONCURRENCY}. Default: ${DEFAULT_MUTATION_CONCURRENCY}.`,\n }),\n confirm: Flags.boolean({\n allowNo: true,\n default: true,\n description:\n 'Prompt for confirmation before running the migration (default: true). Use --no-confirm to skip.',\n }),\n dataset: Flags.string({\n description:\n 'Dataset to migrate. Defaults to the dataset configured in your Sanity CLI config.',\n }),\n 'dry-run': Flags.boolean({\n allowNo: true,\n default: true,\n description:\n 'By default the migration runs in dry mode. Use --no-dry-run to migrate dataset.',\n }),\n 'from-export': Flags.string({\n description:\n 'Use a local dataset export as source for migration instead of calling the Sanity API. Note: this is only supported for dry runs.',\n }),\n progress: Flags.boolean({\n allowNo: true,\n default: true,\n description:\n 'Display progress during migration (default: true). Use --no-progress to hide output.',\n }),\n ...getProjectIdFlag({\n description: 'Project ID of the dataset to migrate',\n semantics: 'override',\n }),\n }\n\n static override hiddenAliases = ['migration:run']\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(RunMigrationCommand)\n const {directory: workDir} = await this.getProjectRoot()\n const id = args.id\n const migrationsDirectoryPath = path.join(workDir, MIGRATIONS_DIRECTORY)\n\n // Listing migrations (no id given) only needs a project root, mirroring\n // `sanity migrations list` — it must not require api.projectId/dataset.\n if (!id) {\n this.warn(styleText('red', 'Error: Migration ID must be provided'))\n\n let migrations: Awaited<ReturnType<typeof resolveMigrations>> = []\n try {\n migrations = await resolveMigrations(workDir)\n } catch (error) {\n // A missing migrations folder is expected for a fresh project; surface\n // any other failure (e.g. a syntax error in a migration file).\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n this.error(\n `Failed to list migrations: ${error instanceof Error ? error.message : String(error)}`,\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n }\n\n if (migrations.length === 0) {\n this.log('\\nNo migrations found in the project')\n this.log(\n `Run ${styleText('green', '`sanity migration create <NAME>`')} to create a new migration`,\n )\n this.exit(exitCodes.RUNTIME_ERROR)\n }\n\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'id', title: 'ID'},\n {alignment: 'left', name: 'title', title: 'Title'},\n ],\n title: `Migrations found in project`,\n })\n\n for (const definedMigration of migrations) {\n table.addRow({id: definedMigration.id, title: definedMigration.migration.title})\n }\n this.log(table.render())\n this.log('\\nRun `sanity migration run <ID>` to run a migration')\n\n this.exit(exitCodes.RUNTIME_ERROR)\n }\n\n const cliConfig = await this.getCliConfig()\n const projectId = await this.getProjectId()\n const datasetFromConfig = cliConfig.api?.dataset\n\n const fromExport = flags['from-export']\n const dry = flags['dry-run']\n const dataset = flags.dataset\n const project = flags.project\n const apiVersion = ensureApiVersionFormat(flags['api-version'] ?? DEFAULT_API_VERSION)\n\n if ((dataset && !project) || (project && !dataset)) {\n this.error('If either --dataset or --project is provided, both must be provided', {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (!project && !projectId) {\n this.error(\n 'sanity.cli.js does not contain a project identifier (\"api.projectId\") and no --project option was provided.',\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n\n if (!dataset && !datasetFromConfig) {\n this.error(\n 'sanity.cli.js does not contain a dataset identifier (\"api.dataset\") and no --dataset option was provided.',\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n\n const candidates = await resolveMigrationScript(workDir, id)\n const resolvedScripts = candidates.filter((candidate) => isLoadableMigrationScript(candidate))\n\n if (resolvedScripts.length > 1) {\n // todo: consider prompt user about which one to run? note: it's likely a mistake if multiple files resolve to the same name\n this.error(\n `Found multiple migrations for \"${id}\" in ${styleText('cyan', migrationsDirectoryPath)}: \\n - ${candidates\n .map((candidate) => path.relative(migrationsDirectoryPath, candidate.absolutePath))\n .join('\\n - ')}`,\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n\n const script = resolvedScripts[0]\n if (!script) {\n this.error(\n `No migration found for \"${id}\" in ${styleText('cyan', migrationsDirectoryPath)}. Make sure that the migration file exists and exports a valid migration as its default export.\\n\n Tried the following files:\\n - ${candidates\n .map((candidate) => path.relative(migrationsDirectoryPath, candidate.absolutePath))\n .join('\\n - ')}`,\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n\n const mod = script.mod\n if ('up' in mod || 'down' in mod) {\n // todo: consider adding support for up/down as separate named exports\n // For now, make sure we reserve the names for future use\n this.error(\n 'Named \"up\"/\"down\" migration exports are not supported at this time, please export your migration as the default export',\n {\n exit: exitCodes.RUNTIME_ERROR,\n },\n )\n }\n\n const migration: Migration = mod.default\n\n if (fromExport && !dry) {\n this.error('Can only dry run migrations from a dataset export file', {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n const concurrency = flags.concurrency\n if (concurrency !== undefined) {\n if (concurrency > MAX_MUTATION_CONCURRENCY) {\n this.error(`Concurrency exceeds the maximum allowed value of ${MAX_MUTATION_CONCURRENCY}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (concurrency < 1) {\n this.error(`Concurrency must be a positive number, got ${concurrency}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n const projectClient = await getProjectCliClient({\n apiVersion,\n projectId: (project ?? projectId)!,\n requireUser: true,\n })\n const projectConfig = projectClient.config()\n\n const apiConfig: APIConfig = {\n apiHost: projectConfig.apiHost,\n apiVersion,\n dataset: (dataset ?? datasetFromConfig)!,\n projectId: (project ?? projectId)!,\n token: projectConfig.token!,\n } as const\n if (dry) {\n await this.dryRunHandler(id, migration, apiConfig, fromExport)\n return\n }\n\n this.log(\n `\\n${styleText(['yellow', 'bold'], 'Note: During migrations, your webhooks stay active.')}`,\n )\n this.log(\n `To adjust them, launch the management interface with ${styleText('cyan', 'sanity manage')}, navigate to the API settings, and toggle the webhooks before and after the migration as needed.\\n`,\n )\n\n if (flags.confirm) {\n await this.promptConfirmMigrate(apiConfig)\n }\n\n const spin = spinner(`Running migration \"${id}\"`).start()\n const onProgress = this.createProgress(spin, flags, id, dry, apiConfig, migration)\n let lastProgress: MigrationProgress | undefined\n\n try {\n await run(\n {\n api: apiConfig,\n concurrency,\n onProgress: (progress) => {\n lastProgress = progress\n onProgress(progress)\n },\n },\n migration,\n )\n } catch (err) {\n // ora's `stop()` clears the spinner region, taking the multi-line progress\n // block with it. Persist a failure summary first, so the transaction counts\n // (the only record of what was committed before the failure) survive.\n this.persistFailureSummary(spin, flags, id, apiConfig, lastProgress)\n\n if (err instanceof UnknownTransactionOutcomeError) {\n // oclif hard-wraps error messages, which splits the transaction log URLs\n // across lines and makes them impossible to copy. Print the recovery\n // instructions ourselves and rethrow something short for the exit code.\n this.logToStderr(err.message)\n for (const line of formatCauseChain(err)) {\n this.logToStderr(line)\n }\n\n const count = err.transactionIds.length\n this.error(\n `Migration \"${id}\" failed: the ${count === 1 ? 'outcome' : 'outcomes'} of ${count} ${\n count === 1 ? 'transaction' : 'transactions'\n } ${count === 1 ? 'is' : 'are'} unknown. See the transaction log details above.`,\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n\n throw err\n } finally {\n spin.stop()\n }\n }\n\n private createProgress(\n progressSpinner: ReturnType<typeof spinner>,\n flags: RunMigrationFlags,\n id: string,\n dry: boolean,\n apiConfig: APIConfig,\n migration: Migration,\n ) {\n return function onProgress(progress: MigrationProgress) {\n if (!flags.progress) {\n progressSpinner.stop()\n return\n }\n if (progress.done) {\n progressSpinner.text = `Migration \"${id}\" completed.\n\n Project id: ${styleText('bold', apiConfig.projectId)}\n Dataset: ${styleText('bold', apiConfig.dataset)}\n\n ${progress.documents} documents processed.\n ${progress.mutations} mutations generated.\n ${styleText('green', String(progress.completedTransactions.length))} transactions committed.`\n progressSpinner.stopAndPersist({symbol: styleText('green', '✔')})\n return\n }\n\n for (const transaction of [null, ...progress.currentTransactions]) {\n progressSpinner.text = `Running migration \"${id}\" ${dry ? 'in dry mode...' : '...'}\n\n Project id: ${styleText('bold', apiConfig.projectId)}\n Dataset: ${styleText('bold', apiConfig.dataset)}\n Document type: ${styleText('bold', migration.documentTypes?.join(',') ?? '')}\n\n ${progress.documents} documents processed…\n ${progress.mutations} mutations generated…\n ${styleText('blue', String(progress.pending))} requests pending…\n ${styleText('green', String(progress.completedTransactions.length))} transactions committed.\n\n ${\n transaction && !progress.done\n ? `» ${prettyFormat({indentSize: 2, migration, subject: transaction})}`\n : ''\n }`\n }\n }\n }\n\n private async dryRunHandler(\n id: string,\n migration: Migration,\n apiConfig: APIConfig,\n fromExport: string | undefined,\n ) {\n this.log(`Running migration \"${id}\" in dry mode`)\n\n if (fromExport) {\n this.log(`Using export ${styleText('cyan', fromExport)}`)\n }\n\n this.log()\n this.log(`Project id: ${styleText('bold', apiConfig.projectId)}`)\n this.log(`Dataset: ${styleText('bold', apiConfig.dataset)}`)\n\n for await (const mutation of dryRun({api: apiConfig, exportPath: fromExport}, migration)) {\n if (!mutation) continue\n this.log()\n this.log(\n prettyFormat({\n migration,\n subject: mutation,\n }),\n )\n }\n }\n\n /**\n * Persist the last reported progress with a failure marker.\n *\n * Only the `progress.done` path finalizes the spinner on its own, so without\n * this the entire progress block is wiped when the migration fails partway.\n */\n private persistFailureSummary(\n progressSpinner: ReturnType<typeof spinner>,\n flags: RunMigrationFlags,\n id: string,\n apiConfig: APIConfig,\n progress: MigrationProgress | undefined,\n ) {\n // With `--no-progress` the spinner was already stopped and nothing was ever\n // rendered; a `done` progress event has already persisted its own summary.\n if (!flags.progress || !progress || progress.done) return\n\n progressSpinner.text = `Migration \"${id}\" failed.\n\n Project id: ${styleText('bold', apiConfig.projectId)}\n Dataset: ${styleText('bold', apiConfig.dataset)}\n\n ${progress.documents} documents processed.\n ${progress.mutations} mutations generated.\n ${styleText('green', String(progress.completedTransactions.length))} transactions committed.`\n progressSpinner.stopAndPersist({symbol: styleText('red', '✖')})\n }\n\n private async promptConfirmMigrate(apiConfig: APIConfig) {\n const response = await confirm({\n message: `This migration will run on the ${styleText(\n ['yellow', 'bold'],\n apiConfig.dataset,\n )} dataset in ${styleText(['yellow', 'bold'], apiConfig.projectId)} project. Are you sure?`,\n })\n\n if (!response) {\n runMigrationDebug('User aborted migration')\n this.exit(exitCodes.RUNTIME_ERROR)\n }\n }\n}\n"],"names":["path","styleText","Args","Flags","exitCodes","getProjectCliClient","SanityCommand","subdebug","confirm","spinner","DEFAULT_MUTATION_CONCURRENCY","dryRun","MAX_MUTATION_CONCURRENCY","run","UnknownTransactionOutcomeError","DEFAULT_API_VERSION","MIGRATIONS_DIRECTORY","ensureApiVersionFormat","prettyFormat","resolveMigrations","isLoadableMigrationScript","resolveMigrationScript","Table","getProjectIdFlag","runMigrationDebug","formatCauseChain","error","lines","cause","Error","undefined","push","name","message","code","RunMigrationCommand","args","id","string","description","required","examples","command","flags","concurrency","integer","default","boolean","allowNo","dataset","progress","semantics","hiddenAliases","parse","directory","workDir","getProjectRoot","migrationsDirectoryPath","join","warn","migrations","String","exit","RUNTIME_ERROR","length","log","table","columns","alignment","title","definedMigration","addRow","migration","render","cliConfig","getCliConfig","projectId","getProjectId","datasetFromConfig","api","fromExport","dry","project","apiVersion","candidates","resolvedScripts","filter","candidate","map","relative","absolutePath","script","mod","projectClient","requireUser","projectConfig","config","apiConfig","apiHost","token","dryRunHandler","promptConfirmMigrate","spin","start","onProgress","createProgress","lastProgress","err","persistFailureSummary","logToStderr","line","count","transactionIds","stop","progressSpinner","done","text","documents","mutations","completedTransactions","stopAndPersist","symbol","transaction","currentTransactions","documentTypes","pending","indentSize","subject","mutation","exportPath","response"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/migrations/run.ts"],"sourcesContent":["import path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exitCodes, getProjectCliClient, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {confirm, spinner} from '@sanity/cli-core/ux'\nimport {\n type APIConfig,\n DEFAULT_MUTATION_CONCURRENCY,\n dryRun,\n MAX_MUTATION_CONCURRENCY,\n type Migration,\n type MigrationProgress,\n run,\n UnknownTransactionOutcomeError,\n} from '@sanity/migrate'\n\nimport {DEFAULT_API_VERSION, MIGRATIONS_DIRECTORY} from '../../actions/migration/constants.js'\nimport {ensureApiVersionFormat} from '../../actions/migration/ensureApiVersionFormat.js'\nimport {prettyFormat} from '../../actions/migration/prettyMutationFormatter.js'\nimport {resolveMigrations} from '../../actions/migration/resolveMigrations.js'\nimport {\n isLoadableMigrationScript,\n resolveMigrationScript,\n} from '../../actions/migration/resolveMigrationScript.js'\nimport {Table} from '../../util/responsiveTable.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\nimport {defineCommandTelemetry} from '../../util/telemetry/commandTelemetry.js'\n\nconst runMigrationDebug = subdebug('migration:run')\n\n/**\n * Renders the `cause` chain of an error the way oclif's own error printer would.\n *\n * Used when printing an error ourselves to bypass oclif's hard word wrapping:\n * the underlying transport error (a timeout, a dropped connection) is the part\n * that explains _why_ the outcome is unknown, so it should not be dropped just\n * because the top-level message is printed separately.\n */\nfunction formatCauseChain(error: unknown): string[] {\n const lines: string[] = []\n let cause: unknown = error instanceof Error ? error.cause : undefined\n\n while (cause instanceof Error) {\n lines.push(`Caused by: ${cause.name}: ${cause.message}`)\n if ('code' in cause && typeof cause.code === 'string') {\n lines.push(`Code: ${cause.code}`)\n }\n cause = cause.cause\n }\n\n return lines\n}\n\nexport type RunMigrationFlags = RunMigrationCommand['flags']\n\nexport class RunMigrationCommand extends SanityCommand<typeof RunMigrationCommand> {\n static override args = {\n id: Args.string({\n description: 'ID',\n required: false,\n }),\n }\n\n static override description = 'Run a migration against a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> <id>',\n description: 'dry run the migration',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> <id> --no-dry-run --project xyz --dataset staging',\n description: 'execute the migration against a dataset',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> <id> --from-export=production.tar.gz --no-dry-run --project xyz --dataset staging',\n description: 'execute the migration using a dataset export as the source',\n },\n ]\n\n static override flags = {\n 'api-version': Flags.string({\n description: `API version to use when migrating. Defaults to ${DEFAULT_API_VERSION}.`,\n }),\n concurrency: Flags.integer({\n default: DEFAULT_MUTATION_CONCURRENCY,\n description: `How many mutation requests to run in parallel. Must be between 1 and ${MAX_MUTATION_CONCURRENCY}. Default: ${DEFAULT_MUTATION_CONCURRENCY}.`,\n }),\n confirm: Flags.boolean({\n allowNo: true,\n default: true,\n description:\n 'Prompt for confirmation before running the migration (default: true). Use --no-confirm to skip.',\n }),\n dataset: Flags.string({\n description:\n 'Dataset to migrate. Defaults to the dataset configured in your Sanity CLI config.',\n }),\n 'dry-run': Flags.boolean({\n allowNo: true,\n default: true,\n description:\n 'By default the migration runs in dry mode. Use --no-dry-run to migrate dataset.',\n }),\n 'from-export': Flags.string({\n description:\n 'Use a local dataset export as source for migration instead of calling the Sanity API. Note: this is only supported for dry runs.',\n }),\n progress: Flags.boolean({\n allowNo: true,\n default: true,\n description:\n 'Display progress during migration (default: true). Use --no-progress to hide output.',\n }),\n ...getProjectIdFlag({\n description: 'Project ID of the dataset to migrate',\n semantics: 'override',\n }),\n }\n\n static override hiddenAliases = ['migration:run']\n\n static telemetry = defineCommandTelemetry(this.flags, {redact: ['from-export']})\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(RunMigrationCommand)\n const {directory: workDir} = await this.getProjectRoot()\n const id = args.id\n const migrationsDirectoryPath = path.join(workDir, MIGRATIONS_DIRECTORY)\n\n // Listing migrations (no id given) only needs a project root, mirroring\n // `sanity migrations list` — it must not require api.projectId/dataset.\n if (!id) {\n this.warn(styleText('red', 'Error: Migration ID must be provided'))\n\n let migrations: Awaited<ReturnType<typeof resolveMigrations>> = []\n try {\n migrations = await resolveMigrations(workDir)\n } catch (error) {\n // A missing migrations folder is expected for a fresh project; surface\n // any other failure (e.g. a syntax error in a migration file).\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n this.error(\n `Failed to list migrations: ${error instanceof Error ? error.message : String(error)}`,\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n }\n\n if (migrations.length === 0) {\n this.log('\\nNo migrations found in the project')\n this.log(\n `Run ${styleText('green', '`sanity migration create <NAME>`')} to create a new migration`,\n )\n this.exit(exitCodes.RUNTIME_ERROR)\n }\n\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'id', title: 'ID'},\n {alignment: 'left', name: 'title', title: 'Title'},\n ],\n title: `Migrations found in project`,\n })\n\n for (const definedMigration of migrations) {\n table.addRow({id: definedMigration.id, title: definedMigration.migration.title})\n }\n this.log(table.render())\n this.log('\\nRun `sanity migration run <ID>` to run a migration')\n\n this.exit(exitCodes.RUNTIME_ERROR)\n }\n\n const cliConfig = await this.getCliConfig()\n const projectId = await this.getProjectId()\n const datasetFromConfig = cliConfig.api?.dataset\n\n const fromExport = flags['from-export']\n const dry = flags['dry-run']\n const dataset = flags.dataset\n const project = flags.project\n const apiVersion = ensureApiVersionFormat(flags['api-version'] ?? DEFAULT_API_VERSION)\n\n if ((dataset && !project) || (project && !dataset)) {\n this.error('If either --dataset or --project is provided, both must be provided', {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (!project && !projectId) {\n this.error(\n 'sanity.cli.js does not contain a project identifier (\"api.projectId\") and no --project option was provided.',\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n\n if (!dataset && !datasetFromConfig) {\n this.error(\n 'sanity.cli.js does not contain a dataset identifier (\"api.dataset\") and no --dataset option was provided.',\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n\n const candidates = await resolveMigrationScript(workDir, id)\n const resolvedScripts = candidates.filter((candidate) => isLoadableMigrationScript(candidate))\n\n if (resolvedScripts.length > 1) {\n // todo: consider prompt user about which one to run? note: it's likely a mistake if multiple files resolve to the same name\n this.error(\n `Found multiple migrations for \"${id}\" in ${styleText('cyan', migrationsDirectoryPath)}: \\n - ${candidates\n .map((candidate) => path.relative(migrationsDirectoryPath, candidate.absolutePath))\n .join('\\n - ')}`,\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n\n const script = resolvedScripts[0]\n if (!script) {\n this.error(\n `No migration found for \"${id}\" in ${styleText('cyan', migrationsDirectoryPath)}. Make sure that the migration file exists and exports a valid migration as its default export.\\n\n Tried the following files:\\n - ${candidates\n .map((candidate) => path.relative(migrationsDirectoryPath, candidate.absolutePath))\n .join('\\n - ')}`,\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n\n const mod = script.mod\n if ('up' in mod || 'down' in mod) {\n // todo: consider adding support for up/down as separate named exports\n // For now, make sure we reserve the names for future use\n this.error(\n 'Named \"up\"/\"down\" migration exports are not supported at this time, please export your migration as the default export',\n {\n exit: exitCodes.RUNTIME_ERROR,\n },\n )\n }\n\n const migration: Migration = mod.default\n\n if (fromExport && !dry) {\n this.error('Can only dry run migrations from a dataset export file', {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n const concurrency = flags.concurrency\n if (concurrency !== undefined) {\n if (concurrency > MAX_MUTATION_CONCURRENCY) {\n this.error(`Concurrency exceeds the maximum allowed value of ${MAX_MUTATION_CONCURRENCY}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (concurrency < 1) {\n this.error(`Concurrency must be a positive number, got ${concurrency}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n const projectClient = await getProjectCliClient({\n apiVersion,\n projectId: (project ?? projectId)!,\n requireUser: true,\n })\n const projectConfig = projectClient.config()\n\n const apiConfig: APIConfig = {\n apiHost: projectConfig.apiHost,\n apiVersion,\n dataset: (dataset ?? datasetFromConfig)!,\n projectId: (project ?? projectId)!,\n token: projectConfig.token!,\n } as const\n if (dry) {\n await this.dryRunHandler(id, migration, apiConfig, fromExport)\n return\n }\n\n this.log(\n `\\n${styleText(['yellow', 'bold'], 'Note: During migrations, your webhooks stay active.')}`,\n )\n this.log(\n `To adjust them, launch the management interface with ${styleText('cyan', 'sanity manage')}, navigate to the API settings, and toggle the webhooks before and after the migration as needed.\\n`,\n )\n\n if (flags.confirm) {\n await this.promptConfirmMigrate(apiConfig)\n }\n\n const spin = spinner(`Running migration \"${id}\"`).start()\n const onProgress = this.createProgress(spin, flags, id, dry, apiConfig, migration)\n let lastProgress: MigrationProgress | undefined\n\n try {\n await run(\n {\n api: apiConfig,\n concurrency,\n onProgress: (progress) => {\n lastProgress = progress\n onProgress(progress)\n },\n },\n migration,\n )\n } catch (err) {\n // ora's `stop()` clears the spinner region, taking the multi-line progress\n // block with it. Persist a failure summary first, so the transaction counts\n // (the only record of what was committed before the failure) survive.\n this.persistFailureSummary(spin, flags, id, apiConfig, lastProgress)\n\n if (err instanceof UnknownTransactionOutcomeError) {\n // oclif hard-wraps error messages, which splits the transaction log URLs\n // across lines and makes them impossible to copy. Print the recovery\n // instructions ourselves and rethrow something short for the exit code.\n this.logToStderr(err.message)\n for (const line of formatCauseChain(err)) {\n this.logToStderr(line)\n }\n\n const count = err.transactionIds.length\n this.error(\n `Migration \"${id}\" failed: the ${count === 1 ? 'outcome' : 'outcomes'} of ${count} ${\n count === 1 ? 'transaction' : 'transactions'\n } ${count === 1 ? 'is' : 'are'} unknown. See the transaction log details above.`,\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n\n throw err\n } finally {\n spin.stop()\n }\n }\n\n private createProgress(\n progressSpinner: ReturnType<typeof spinner>,\n flags: RunMigrationFlags,\n id: string,\n dry: boolean,\n apiConfig: APIConfig,\n migration: Migration,\n ) {\n return function onProgress(progress: MigrationProgress) {\n if (!flags.progress) {\n progressSpinner.stop()\n return\n }\n if (progress.done) {\n progressSpinner.text = `Migration \"${id}\" completed.\n\n Project id: ${styleText('bold', apiConfig.projectId)}\n Dataset: ${styleText('bold', apiConfig.dataset)}\n\n ${progress.documents} documents processed.\n ${progress.mutations} mutations generated.\n ${styleText('green', String(progress.completedTransactions.length))} transactions committed.`\n progressSpinner.stopAndPersist({symbol: styleText('green', '✔')})\n return\n }\n\n for (const transaction of [null, ...progress.currentTransactions]) {\n progressSpinner.text = `Running migration \"${id}\" ${dry ? 'in dry mode...' : '...'}\n\n Project id: ${styleText('bold', apiConfig.projectId)}\n Dataset: ${styleText('bold', apiConfig.dataset)}\n Document type: ${styleText('bold', migration.documentTypes?.join(',') ?? '')}\n\n ${progress.documents} documents processed…\n ${progress.mutations} mutations generated…\n ${styleText('blue', String(progress.pending))} requests pending…\n ${styleText('green', String(progress.completedTransactions.length))} transactions committed.\n\n ${\n transaction && !progress.done\n ? `» ${prettyFormat({indentSize: 2, migration, subject: transaction})}`\n : ''\n }`\n }\n }\n }\n\n private async dryRunHandler(\n id: string,\n migration: Migration,\n apiConfig: APIConfig,\n fromExport: string | undefined,\n ) {\n this.log(`Running migration \"${id}\" in dry mode`)\n\n if (fromExport) {\n this.log(`Using export ${styleText('cyan', fromExport)}`)\n }\n\n this.log()\n this.log(`Project id: ${styleText('bold', apiConfig.projectId)}`)\n this.log(`Dataset: ${styleText('bold', apiConfig.dataset)}`)\n\n for await (const mutation of dryRun({api: apiConfig, exportPath: fromExport}, migration)) {\n if (!mutation) continue\n this.log()\n this.log(\n prettyFormat({\n migration,\n subject: mutation,\n }),\n )\n }\n }\n\n /**\n * Persist the last reported progress with a failure marker.\n *\n * Only the `progress.done` path finalizes the spinner on its own, so without\n * this the entire progress block is wiped when the migration fails partway.\n */\n private persistFailureSummary(\n progressSpinner: ReturnType<typeof spinner>,\n flags: RunMigrationFlags,\n id: string,\n apiConfig: APIConfig,\n progress: MigrationProgress | undefined,\n ) {\n // With `--no-progress` the spinner was already stopped and nothing was ever\n // rendered; a `done` progress event has already persisted its own summary.\n if (!flags.progress || !progress || progress.done) return\n\n progressSpinner.text = `Migration \"${id}\" failed.\n\n Project id: ${styleText('bold', apiConfig.projectId)}\n Dataset: ${styleText('bold', apiConfig.dataset)}\n\n ${progress.documents} documents processed.\n ${progress.mutations} mutations generated.\n ${styleText('green', String(progress.completedTransactions.length))} transactions committed.`\n progressSpinner.stopAndPersist({symbol: styleText('red', '✖')})\n }\n\n private async promptConfirmMigrate(apiConfig: APIConfig) {\n const response = await confirm({\n message: `This migration will run on the ${styleText(\n ['yellow', 'bold'],\n apiConfig.dataset,\n )} dataset in ${styleText(['yellow', 'bold'], apiConfig.projectId)} project. Are you sure?`,\n })\n\n if (!response) {\n runMigrationDebug('User aborted migration')\n this.exit(exitCodes.RUNTIME_ERROR)\n }\n }\n}\n"],"names":["path","styleText","Args","Flags","exitCodes","getProjectCliClient","SanityCommand","subdebug","confirm","spinner","DEFAULT_MUTATION_CONCURRENCY","dryRun","MAX_MUTATION_CONCURRENCY","run","UnknownTransactionOutcomeError","DEFAULT_API_VERSION","MIGRATIONS_DIRECTORY","ensureApiVersionFormat","prettyFormat","resolveMigrations","isLoadableMigrationScript","resolveMigrationScript","Table","getProjectIdFlag","defineCommandTelemetry","runMigrationDebug","formatCauseChain","error","lines","cause","Error","undefined","push","name","message","code","RunMigrationCommand","args","id","string","description","required","examples","command","flags","concurrency","integer","default","boolean","allowNo","dataset","progress","semantics","hiddenAliases","telemetry","redact","parse","directory","workDir","getProjectRoot","migrationsDirectoryPath","join","warn","migrations","String","exit","RUNTIME_ERROR","length","log","table","columns","alignment","title","definedMigration","addRow","migration","render","cliConfig","getCliConfig","projectId","getProjectId","datasetFromConfig","api","fromExport","dry","project","apiVersion","candidates","resolvedScripts","filter","candidate","map","relative","absolutePath","script","mod","projectClient","requireUser","projectConfig","config","apiConfig","apiHost","token","dryRunHandler","promptConfirmMigrate","spin","start","onProgress","createProgress","lastProgress","err","persistFailureSummary","logToStderr","line","count","transactionIds","stop","progressSpinner","done","text","documents","mutations","completedTransactions","stopAndPersist","symbol","transaction","currentTransactions","documentTypes","pending","indentSize","subject","mutation","exportPath","response"],"mappings":"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"}
@@ -7,6 +7,7 @@ import { validateOrganizationName } from '../../actions/organizations/validateOr
7
7
  import { promptForOrganizationName } from '../../prompts/promptForOrganizationName.js';
8
8
  import { createOrganization } from '../../services/organizations.js';
9
9
  import { organizationAliases } from '../../util/organizationAliases.js';
10
+ import { defineCommandTelemetry } from '../../util/telemetry/commandTelemetry.js';
10
11
  const createOrgDebug = subdebug('organizations:create');
11
12
  export class CreateOrganizationCommand extends SanityCommand {
12
13
  static description = 'Create a new organization';
@@ -34,6 +35,11 @@ export class CreateOrganizationCommand extends SanityCommand {
34
35
  }))
35
36
  };
36
37
  static hiddenAliases = organizationAliases('create');
38
+ static telemetry = defineCommandTelemetry(this.flags, {
39
+ redact: [
40
+ 'name'
41
+ ]
42
+ });
37
43
  async run() {
38
44
  const { 'default-role': defaultRoleFlag, name: nameFlag } = this.flags;
39
45
  const defaultRole = defaultRoleFlag?.trim();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/organizations/create.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {type FlagInput} from '@oclif/core/interfaces'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {requiredWhenUnattended} from '@sanity/cli-core/flags'\nimport {spinner} from '@sanity/cli-core/ux'\n\nimport {validateOrganizationName} from '../../actions/organizations/validateOrganizationName.js'\nimport {promptForOrganizationName} from '../../prompts/promptForOrganizationName.js'\nimport {createOrganization} from '../../services/organizations.js'\nimport {organizationAliases} from '../../util/organizationAliases.js'\n\nconst createOrgDebug = subdebug('organizations:create')\n\nexport class CreateOrganizationCommand extends SanityCommand<typeof CreateOrganizationCommand> {\n static override description = 'Create a new organization'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively create an organization',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --name \"Acme Corp\"',\n description: 'Create an organization named \"Acme Corp\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --name \"Acme Corp\" --default-role member',\n description: 'Create an organization with a default member role',\n },\n ]\n\n static override flags = {\n 'default-role': Flags.string({\n description: 'Default role assigned to new members',\n required: false,\n }),\n name: requiredWhenUnattended(\n Flags.string({\n description: 'Organization name',\n }),\n ),\n } satisfies FlagInput\n\n static override hiddenAliases = organizationAliases('create')\n\n public async run(): Promise<void> {\n const {'default-role': defaultRoleFlag, name: nameFlag} = this.flags\n\n const defaultRole = defaultRoleFlag?.trim()\n if (defaultRole === '') {\n this.error('Default role cannot be empty', {exit: exitCodes.RUNTIME_ERROR})\n }\n\n let name: string\n if (nameFlag === undefined) {\n name = await promptForOrganizationName()\n } else {\n const trimmedName = nameFlag.trim()\n const validation = validateOrganizationName(trimmedName)\n if (validation !== true) {\n this.error(validation, {exit: exitCodes.RUNTIME_ERROR})\n }\n name = trimmedName\n }\n\n const spin = spinner('Creating organization').start()\n try {\n const org = await createOrganization(name, defaultRole)\n spin.succeed('Organization created')\n this.log(`ID: ${org.id}`)\n this.log(`Name: ${org.name}`)\n } catch (error) {\n spin.fail()\n createOrgDebug('Error creating organization', error)\n this.error(`Failed to create organization: ${getErrorMessage(error)}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n}\n"],"names":["Flags","exitCodes","SanityCommand","subdebug","getErrorMessage","requiredWhenUnattended","spinner","validateOrganizationName","promptForOrganizationName","createOrganization","organizationAliases","createOrgDebug","CreateOrganizationCommand","description","examples","command","flags","string","required","name","hiddenAliases","run","defaultRoleFlag","nameFlag","defaultRole","trim","error","exit","RUNTIME_ERROR","undefined","trimmedName","validation","spin","start","org","succeed","log","id","fail"],"mappings":"AAAA,SAAQA,KAAK,QAAO,cAAa;AAEjC,SAAQC,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACnE,SAAQC,eAAe,QAAO,0BAAyB;AACvD,SAAQC,sBAAsB,QAAO,yBAAwB;AAC7D,SAAQC,OAAO,QAAO,sBAAqB;AAE3C,SAAQC,wBAAwB,QAAO,0DAAyD;AAChG,SAAQC,yBAAyB,QAAO,6CAA4C;AACpF,SAAQC,kBAAkB,QAAO,kCAAiC;AAClE,SAAQC,mBAAmB,QAAO,oCAAmC;AAErE,MAAMC,iBAAiBR,SAAS;AAEhC,OAAO,MAAMS,kCAAkCV;IAC7C,OAAgBW,cAAc,4BAA2B;IAEzD,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTF,aAAa;QACf;QACA;YACEE,SAAS;YACTF,aAAa;QACf;QACA;YACEE,SAAS;YACTF,aAAa;QACf;KACD,CAAA;IAED,OAAgBG,QAAQ;QACtB,gBAAgBhB,MAAMiB,MAAM,CAAC;YAC3BJ,aAAa;YACbK,UAAU;QACZ;QACAC,MAAMd,uBACJL,MAAMiB,MAAM,CAAC;YACXJ,aAAa;QACf;IAEJ,EAAqB;IAErB,OAAgBO,gBAAgBV,oBAAoB,UAAS;IAE7D,MAAaW,MAAqB;QAChC,MAAM,EAAC,gBAAgBC,eAAe,EAAEH,MAAMI,QAAQ,EAAC,GAAG,IAAI,CAACP,KAAK;QAEpE,MAAMQ,cAAcF,iBAAiBG;QACrC,IAAID,gBAAgB,IAAI;YACtB,IAAI,CAACE,KAAK,CAAC,gCAAgC;gBAACC,MAAM1B,UAAU2B,aAAa;YAAA;QAC3E;QAEA,IAAIT;QACJ,IAAII,aAAaM,WAAW;YAC1BV,OAAO,MAAMX;QACf,OAAO;YACL,MAAMsB,cAAcP,SAASE,IAAI;YACjC,MAAMM,aAAaxB,yBAAyBuB;YAC5C,IAAIC,eAAe,MAAM;gBACvB,IAAI,CAACL,KAAK,CAACK,YAAY;oBAACJ,MAAM1B,UAAU2B,aAAa;gBAAA;YACvD;YACAT,OAAOW;QACT;QAEA,MAAME,OAAO1B,QAAQ,yBAAyB2B,KAAK;QACnD,IAAI;YACF,MAAMC,MAAM,MAAMzB,mBAAmBU,MAAMK;YAC3CQ,KAAKG,OAAO,CAAC;YACb,IAAI,CAACC,GAAG,CAAC,CAAC,MAAM,EAAEF,IAAIG,EAAE,EAAE;YAC1B,IAAI,CAACD,GAAG,CAAC,CAAC,MAAM,EAAEF,IAAIf,IAAI,EAAE;QAC9B,EAAE,OAAOO,OAAO;YACdM,KAAKM,IAAI;YACT3B,eAAe,+BAA+Be;YAC9C,IAAI,CAACA,KAAK,CAAC,CAAC,+BAA+B,EAAEtB,gBAAgBsB,QAAQ,EAAE;gBACrEC,MAAM1B,UAAU2B,aAAa;YAC/B;QACF;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/commands/organizations/create.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {type FlagInput} from '@oclif/core/interfaces'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {requiredWhenUnattended} from '@sanity/cli-core/flags'\nimport {spinner} from '@sanity/cli-core/ux'\n\nimport {validateOrganizationName} from '../../actions/organizations/validateOrganizationName.js'\nimport {promptForOrganizationName} from '../../prompts/promptForOrganizationName.js'\nimport {createOrganization} from '../../services/organizations.js'\nimport {organizationAliases} from '../../util/organizationAliases.js'\nimport {defineCommandTelemetry} from '../../util/telemetry/commandTelemetry.js'\n\nconst createOrgDebug = subdebug('organizations:create')\n\nexport class CreateOrganizationCommand extends SanityCommand<typeof CreateOrganizationCommand> {\n static override description = 'Create a new organization'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively create an organization',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --name \"Acme Corp\"',\n description: 'Create an organization named \"Acme Corp\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --name \"Acme Corp\" --default-role member',\n description: 'Create an organization with a default member role',\n },\n ]\n\n static override flags = {\n 'default-role': Flags.string({\n description: 'Default role assigned to new members',\n required: false,\n }),\n name: requiredWhenUnattended(\n Flags.string({\n description: 'Organization name',\n }),\n ),\n } satisfies FlagInput\n\n static override hiddenAliases = organizationAliases('create')\n\n static telemetry = defineCommandTelemetry(this.flags, {redact: ['name']})\n\n public async run(): Promise<void> {\n const {'default-role': defaultRoleFlag, name: nameFlag} = this.flags\n\n const defaultRole = defaultRoleFlag?.trim()\n if (defaultRole === '') {\n this.error('Default role cannot be empty', {exit: exitCodes.RUNTIME_ERROR})\n }\n\n let name: string\n if (nameFlag === undefined) {\n name = await promptForOrganizationName()\n } else {\n const trimmedName = nameFlag.trim()\n const validation = validateOrganizationName(trimmedName)\n if (validation !== true) {\n this.error(validation, {exit: exitCodes.RUNTIME_ERROR})\n }\n name = trimmedName\n }\n\n const spin = spinner('Creating organization').start()\n try {\n const org = await createOrganization(name, defaultRole)\n spin.succeed('Organization created')\n this.log(`ID: ${org.id}`)\n this.log(`Name: ${org.name}`)\n } catch (error) {\n spin.fail()\n createOrgDebug('Error creating organization', error)\n this.error(`Failed to create organization: ${getErrorMessage(error)}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n}\n"],"names":["Flags","exitCodes","SanityCommand","subdebug","getErrorMessage","requiredWhenUnattended","spinner","validateOrganizationName","promptForOrganizationName","createOrganization","organizationAliases","defineCommandTelemetry","createOrgDebug","CreateOrganizationCommand","description","examples","command","flags","string","required","name","hiddenAliases","telemetry","redact","run","defaultRoleFlag","nameFlag","defaultRole","trim","error","exit","RUNTIME_ERROR","undefined","trimmedName","validation","spin","start","org","succeed","log","id","fail"],"mappings":"AAAA,SAAQA,KAAK,QAAO,cAAa;AAEjC,SAAQC,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACnE,SAAQC,eAAe,QAAO,0BAAyB;AACvD,SAAQC,sBAAsB,QAAO,yBAAwB;AAC7D,SAAQC,OAAO,QAAO,sBAAqB;AAE3C,SAAQC,wBAAwB,QAAO,0DAAyD;AAChG,SAAQC,yBAAyB,QAAO,6CAA4C;AACpF,SAAQC,kBAAkB,QAAO,kCAAiC;AAClE,SAAQC,mBAAmB,QAAO,oCAAmC;AACrE,SAAQC,sBAAsB,QAAO,2CAA0C;AAE/E,MAAMC,iBAAiBT,SAAS;AAEhC,OAAO,MAAMU,kCAAkCX;IAC7C,OAAgBY,cAAc,4BAA2B;IAEzD,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTF,aAAa;QACf;QACA;YACEE,SAAS;YACTF,aAAa;QACf;QACA;YACEE,SAAS;YACTF,aAAa;QACf;KACD,CAAA;IAED,OAAgBG,QAAQ;QACtB,gBAAgBjB,MAAMkB,MAAM,CAAC;YAC3BJ,aAAa;YACbK,UAAU;QACZ;QACAC,MAAMf,uBACJL,MAAMkB,MAAM,CAAC;YACXJ,aAAa;QACf;IAEJ,EAAqB;IAErB,OAAgBO,gBAAgBX,oBAAoB,UAAS;IAE7D,OAAOY,YAAYX,uBAAuB,IAAI,CAACM,KAAK,EAAE;QAACM,QAAQ;YAAC;SAAO;IAAA,GAAE;IAEzE,MAAaC,MAAqB;QAChC,MAAM,EAAC,gBAAgBC,eAAe,EAAEL,MAAMM,QAAQ,EAAC,GAAG,IAAI,CAACT,KAAK;QAEpE,MAAMU,cAAcF,iBAAiBG;QACrC,IAAID,gBAAgB,IAAI;YACtB,IAAI,CAACE,KAAK,CAAC,gCAAgC;gBAACC,MAAM7B,UAAU8B,aAAa;YAAA;QAC3E;QAEA,IAAIX;QACJ,IAAIM,aAAaM,WAAW;YAC1BZ,OAAO,MAAMZ;QACf,OAAO;YACL,MAAMyB,cAAcP,SAASE,IAAI;YACjC,MAAMM,aAAa3B,yBAAyB0B;YAC5C,IAAIC,eAAe,MAAM;gBACvB,IAAI,CAACL,KAAK,CAACK,YAAY;oBAACJ,MAAM7B,UAAU8B,aAAa;gBAAA;YACvD;YACAX,OAAOa;QACT;QAEA,MAAME,OAAO7B,QAAQ,yBAAyB8B,KAAK;QACnD,IAAI;YACF,MAAMC,MAAM,MAAM5B,mBAAmBW,MAAMO;YAC3CQ,KAAKG,OAAO,CAAC;YACb,IAAI,CAACC,GAAG,CAAC,CAAC,MAAM,EAAEF,IAAIG,EAAE,EAAE;YAC1B,IAAI,CAACD,GAAG,CAAC,CAAC,MAAM,EAAEF,IAAIjB,IAAI,EAAE;QAC9B,EAAE,OAAOS,OAAO;YACdM,KAAKM,IAAI;YACT7B,eAAe,+BAA+BiB;YAC9C,IAAI,CAACA,KAAK,CAAC,CAAC,+BAA+B,EAAEzB,gBAAgByB,QAAQ,EAAE;gBACrEC,MAAM7B,UAAU8B,aAAa;YAC/B;QACF;IACF;AACF"}
@@ -7,6 +7,7 @@ import { validateOrganizationName } from '../../actions/organizations/validateOr
7
7
  import { validateOrganizationSlug } from '../../actions/organizations/validateOrganizationSlug.js';
8
8
  import { updateOrganization } from '../../services/organizations.js';
9
9
  import { organizationAliases } from '../../util/organizationAliases.js';
10
+ import { defineCommandTelemetry } from '../../util/telemetry/commandTelemetry.js';
10
11
  const updateOrgDebug = subdebug('organizations:update');
11
12
  const UPDATE_FLAGS = [
12
13
  'name',
@@ -59,6 +60,11 @@ export class UpdateOrganizationCommand extends SanityCommand {
59
60
  })
60
61
  };
61
62
  static hiddenAliases = organizationAliases('update');
63
+ static telemetry = defineCommandTelemetry(this.flags, {
64
+ redact: [
65
+ 'name'
66
+ ]
67
+ });
62
68
  async run() {
63
69
  const { organizationId } = this.args;
64
70
  const { 'default-role': defaultRole, name, slug } = this.flags;