@sanity/cli 7.11.0 → 7.12.1

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 (171) hide show
  1. package/dist/actions/build/buildApp.js +10 -7
  2. package/dist/actions/build/buildApp.js.map +1 -1
  3. package/dist/actions/build/buildStudio.js +9 -6
  4. package/dist/actions/build/buildStudio.js.map +1 -1
  5. package/dist/actions/build/types.js.map +1 -1
  6. package/dist/actions/deploy/deployApp.js +205 -162
  7. package/dist/actions/deploy/deployApp.js.map +1 -1
  8. package/dist/actions/deploy/deployChecks.js +1 -1
  9. package/dist/actions/deploy/deployChecks.js.map +1 -1
  10. package/dist/actions/deploy/deployStudio.js +126 -87
  11. package/dist/actions/deploy/deployStudio.js.map +1 -1
  12. package/dist/actions/deploy/resolveDeployTarget.js +5 -9
  13. package/dist/actions/deploy/resolveDeployTarget.js.map +1 -1
  14. package/dist/actions/dev/devAction.js +1 -2
  15. package/dist/actions/dev/devAction.js.map +1 -1
  16. package/dist/actions/dev/servers/getDevServerConfig.js +8 -2
  17. package/dist/actions/dev/servers/getDevServerConfig.js.map +1 -1
  18. package/dist/actions/init/bootstrapLocalTemplate.js +18 -9
  19. package/dist/actions/init/bootstrapLocalTemplate.js.map +1 -1
  20. package/dist/actions/init/createAppCliConfig.js.map +1 -1
  21. package/dist/actions/init/createCliConfig.js.map +1 -1
  22. package/dist/commands/backups/disable.js +4 -4
  23. package/dist/commands/backups/disable.js.map +1 -1
  24. package/dist/commands/backups/download.js +7 -7
  25. package/dist/commands/backups/download.js.map +1 -1
  26. package/dist/commands/backups/enable.js +4 -4
  27. package/dist/commands/backups/enable.js.map +1 -1
  28. package/dist/commands/backups/list.js +7 -7
  29. package/dist/commands/backups/list.js.map +1 -1
  30. package/dist/commands/codemod.js +5 -5
  31. package/dist/commands/codemod.js.map +1 -1
  32. package/dist/commands/cors/add.js +1 -1
  33. package/dist/commands/cors/add.js.map +1 -1
  34. package/dist/commands/cors/delete.js +4 -4
  35. package/dist/commands/cors/delete.js.map +1 -1
  36. package/dist/commands/cors/list.js +2 -2
  37. package/dist/commands/cors/list.js.map +1 -1
  38. package/dist/commands/datasets/alias/create.js +5 -5
  39. package/dist/commands/datasets/alias/create.js.map +1 -1
  40. package/dist/commands/datasets/alias/delete.js +2 -2
  41. package/dist/commands/datasets/alias/delete.js.map +1 -1
  42. package/dist/commands/datasets/alias/link.js +5 -5
  43. package/dist/commands/datasets/alias/link.js.map +1 -1
  44. package/dist/commands/datasets/alias/unlink.js +3 -3
  45. package/dist/commands/datasets/alias/unlink.js.map +1 -1
  46. package/dist/commands/datasets/copy.js +7 -7
  47. package/dist/commands/datasets/copy.js.map +1 -1
  48. package/dist/commands/datasets/create.js +3 -3
  49. package/dist/commands/datasets/create.js.map +1 -1
  50. package/dist/commands/datasets/delete.js +2 -2
  51. package/dist/commands/datasets/delete.js.map +1 -1
  52. package/dist/commands/datasets/embeddings/disable.js +3 -3
  53. package/dist/commands/datasets/embeddings/disable.js.map +1 -1
  54. package/dist/commands/datasets/embeddings/enable.js +5 -5
  55. package/dist/commands/datasets/embeddings/enable.js.map +1 -1
  56. package/dist/commands/datasets/embeddings/status.js +3 -3
  57. package/dist/commands/datasets/embeddings/status.js.map +1 -1
  58. package/dist/commands/datasets/export.js +6 -6
  59. package/dist/commands/datasets/export.js.map +1 -1
  60. package/dist/commands/datasets/import.js +3 -3
  61. package/dist/commands/datasets/import.js.map +1 -1
  62. package/dist/commands/datasets/list.js +2 -2
  63. package/dist/commands/datasets/list.js.map +1 -1
  64. package/dist/commands/datasets/visibility/get.js +2 -2
  65. package/dist/commands/datasets/visibility/get.js.map +1 -1
  66. package/dist/commands/datasets/visibility/set.js +3 -3
  67. package/dist/commands/datasets/visibility/set.js.map +1 -1
  68. package/dist/commands/deploy.js +2 -2
  69. package/dist/commands/deploy.js.map +1 -1
  70. package/dist/commands/dev.js +2 -2
  71. package/dist/commands/dev.js.map +1 -1
  72. package/dist/commands/docs/read.js +1 -1
  73. package/dist/commands/docs/read.js.map +1 -1
  74. package/dist/commands/docs/search.js +3 -3
  75. package/dist/commands/docs/search.js.map +1 -1
  76. package/dist/commands/doctor.js +3 -3
  77. package/dist/commands/doctor.js.map +1 -1
  78. package/dist/commands/documents/create.js +3 -3
  79. package/dist/commands/documents/create.js.map +1 -1
  80. package/dist/commands/documents/delete.js +3 -3
  81. package/dist/commands/documents/delete.js.map +1 -1
  82. package/dist/commands/documents/get.js +2 -2
  83. package/dist/commands/documents/get.js.map +1 -1
  84. package/dist/commands/documents/query.js +2 -2
  85. package/dist/commands/documents/query.js.map +1 -1
  86. package/dist/commands/documents/validate.js +3 -3
  87. package/dist/commands/documents/validate.js.map +1 -1
  88. package/dist/commands/graphql/deploy.js +13 -13
  89. package/dist/commands/graphql/deploy.js.map +1 -1
  90. package/dist/commands/graphql/list.js +2 -2
  91. package/dist/commands/graphql/list.js.map +1 -1
  92. package/dist/commands/graphql/undeploy.js +2 -2
  93. package/dist/commands/graphql/undeploy.js.map +1 -1
  94. package/dist/commands/hooks/attempt.js +2 -2
  95. package/dist/commands/hooks/attempt.js.map +1 -1
  96. package/dist/commands/hooks/create.js +3 -3
  97. package/dist/commands/hooks/create.js.map +1 -1
  98. package/dist/commands/hooks/delete.js +4 -4
  99. package/dist/commands/hooks/delete.js.map +1 -1
  100. package/dist/commands/hooks/list.js +2 -2
  101. package/dist/commands/hooks/list.js.map +1 -1
  102. package/dist/commands/hooks/logs.js +5 -5
  103. package/dist/commands/hooks/logs.js.map +1 -1
  104. package/dist/commands/login.js +2 -2
  105. package/dist/commands/login.js.map +1 -1
  106. package/dist/commands/logout.js +2 -2
  107. package/dist/commands/logout.js.map +1 -1
  108. package/dist/commands/manifest/extract.js +3 -3
  109. package/dist/commands/manifest/extract.js.map +1 -1
  110. package/dist/commands/mcp/configure.js +4 -4
  111. package/dist/commands/mcp/configure.js.map +1 -1
  112. package/dist/commands/media/create-aspect.js +3 -3
  113. package/dist/commands/media/create-aspect.js.map +1 -1
  114. package/dist/commands/media/delete-aspect.js +1 -1
  115. package/dist/commands/media/delete-aspect.js.map +1 -1
  116. package/dist/commands/media/deploy-aspect.js +4 -4
  117. package/dist/commands/media/deploy-aspect.js.map +1 -1
  118. package/dist/commands/media/export.js +7 -7
  119. package/dist/commands/media/export.js.map +1 -1
  120. package/dist/commands/media/import.js +6 -6
  121. package/dist/commands/media/import.js.map +1 -1
  122. package/dist/commands/migrations/create.js +4 -4
  123. package/dist/commands/migrations/create.js.map +1 -1
  124. package/dist/commands/migrations/list.js +2 -2
  125. package/dist/commands/migrations/list.js.map +1 -1
  126. package/dist/commands/migrations/run.js +14 -14
  127. package/dist/commands/migrations/run.js.map +1 -1
  128. package/dist/commands/openapi/get.js +3 -3
  129. package/dist/commands/openapi/get.js.map +1 -1
  130. package/dist/commands/openapi/list.js +2 -2
  131. package/dist/commands/openapi/list.js.map +1 -1
  132. package/dist/commands/organizations/create.js +5 -5
  133. package/dist/commands/organizations/create.js.map +1 -1
  134. package/dist/commands/organizations/delete.js +6 -6
  135. package/dist/commands/organizations/delete.js.map +1 -1
  136. package/dist/commands/organizations/get.js +3 -3
  137. package/dist/commands/organizations/get.js.map +1 -1
  138. package/dist/commands/organizations/list.js +2 -2
  139. package/dist/commands/organizations/list.js.map +1 -1
  140. package/dist/commands/organizations/update.js +6 -6
  141. package/dist/commands/organizations/update.js.map +1 -1
  142. package/dist/commands/preview.js +2 -2
  143. package/dist/commands/preview.js.map +1 -1
  144. package/dist/commands/projects/create.js +2 -2
  145. package/dist/commands/projects/create.js.map +1 -1
  146. package/dist/commands/projects/list.js +2 -2
  147. package/dist/commands/projects/list.js.map +1 -1
  148. package/dist/commands/schemas/delete.js +2 -2
  149. package/dist/commands/schemas/delete.js.map +1 -1
  150. package/dist/commands/schemas/deploy.js +2 -2
  151. package/dist/commands/schemas/deploy.js.map +1 -1
  152. package/dist/commands/schemas/list.js +1 -1
  153. package/dist/commands/schemas/list.js.map +1 -1
  154. package/dist/commands/schemas/validate.js +2 -1
  155. package/dist/commands/schemas/validate.js.map +1 -1
  156. package/dist/commands/skills/install.js +2 -2
  157. package/dist/commands/skills/install.js.map +1 -1
  158. package/dist/commands/telemetry/disable.js +2 -2
  159. package/dist/commands/telemetry/disable.js.map +1 -1
  160. package/dist/commands/telemetry/enable.js +2 -2
  161. package/dist/commands/telemetry/enable.js.map +1 -1
  162. package/dist/commands/tokens/create.js +2 -2
  163. package/dist/commands/tokens/create.js.map +1 -1
  164. package/dist/commands/tokens/delete.js +2 -2
  165. package/dist/commands/tokens/delete.js.map +1 -1
  166. package/dist/commands/tokens/list.js +2 -2
  167. package/dist/commands/tokens/list.js.map +1 -1
  168. package/dist/commands/users/invite.js +3 -3
  169. package/dist/commands/users/invite.js.map +1 -1
  170. package/oclif.manifest.json +331 -331
  171. package/package.json +5 -5
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/media/import.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exitCodes, getProjectCliClient, SanityCommand} from '@sanity/cli-core'\nimport {boxen, spinner} from '@sanity/cli-core/ux'\nimport {SanityClient} from '@sanity/client'\nimport {type OperatorFunction, pipe, scan, tap} from 'rxjs'\n\nimport {importer, type State} from '../../actions/media/importMedia.js'\nimport {importMediaDebug} from '../../actions/media/importMediaDebug.js'\nimport {promptForMediaLibrary} from '../../prompts/promptForMediaLibrary.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {getMediaLibraries} from '../../services/mediaLibraries.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nexport class MediaImportCommand extends SanityCommand<typeof MediaImportCommand> {\n static override args = {\n source: Args.string({\n description: 'Image file or folder to import from',\n required: true,\n }),\n }\n\n static override description = 'Import a set of assets to the target media library.'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> products',\n description: 'Import all assets from the \"products\" directory',\n },\n {\n command: '<%= config.bin %> <%= command.id %> gallery.tar.gz',\n description: 'Import all assets from \"gallery\" archive',\n },\n {\n command: '<%= config.bin %> <%= command.id %> products --replace-aspects',\n description: 'Import all assets from the \"products\" directory and replace aspects',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to import media to',\n semantics: 'override',\n }),\n 'media-library-id': Flags.string({\n description: 'The id of the target media library',\n }),\n 'replace-aspects': Flags.boolean({\n description:\n 'Replace existing aspect data. All versions will be replaced (e.g. published and draft aspect data)',\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(MediaImportCommand)\n const {source} = args\n const replaceAspects = flags['replace-aspects']\n\n const projectId = await this.getProjectId({fallback: () => promptForProject({})})\n\n const cliConfig = await this.tryGetCliConfig()\n const dataset = cliConfig.api?.dataset\n\n let mediaLibraries\n try {\n mediaLibraries = await getMediaLibraries(projectId)\n } catch (error) {\n importMediaDebug('Error listing media libraries', error)\n this.error(\n `Failed to list media libraries:\\n${error instanceof Error ? error.message : error}`,\n {\n exit: 1,\n },\n )\n }\n\n if (mediaLibraries.length === 0) {\n this.error('No active media libraries found in this project', {exit: 1})\n }\n\n let mediaLibraryId = flags['media-library-id']\n if (!mediaLibraryId) {\n if (this.isUnattended()) {\n this.error('Media library ID is required. Pass it with `--media-library-id <id>`.', {\n exit: exitCodes.USAGE_ERROR,\n })\n }\n try {\n mediaLibraryId = await promptForMediaLibrary({mediaLibraries})\n } catch (error) {\n importMediaDebug('Error selecting media library', error)\n this.error(\n `Failed to select media library:\\n${error instanceof Error ? error.message : error}`,\n {\n exit: 1,\n },\n )\n }\n }\n\n if (!mediaLibraries.some((library) => library.id === mediaLibraryId)) {\n this.error(`Media library with id \"${mediaLibraryId}\" not found`, {exit: 1})\n }\n\n const projectClient = await getProjectCliClient({\n apiVersion: 'v2025-02-19',\n dataset,\n perspective: 'drafts',\n projectId,\n requestTagPrefix: 'sanity.mediaLibraryCli.import',\n requireUser: true,\n '~experimental_resource': {\n id: mediaLibraryId,\n type: 'media-library',\n },\n })\n\n this.log(\n boxen(\n `\n Importing to media library: ${mediaLibraryId.padEnd(37)}\n Importing from path: ${source}\n `,\n {\n borderColor: 'yellow',\n borderStyle: 'round',\n },\n ),\n )\n\n const spin = spinner('Beginning import…').start()\n\n await this.importAssets({projectClient, replaceAspects, source, spin})\n }\n\n private async importAssets(options: {\n projectClient: SanityClient\n replaceAspects: boolean\n source: string\n spin: ReturnType<typeof spinner>\n }): Promise<void> {\n const {projectClient, replaceAspects, source, spin} = options\n\n return new Promise<void>((resolve, reject) => {\n const subscription = importer({\n client: projectClient,\n replaceAspects,\n sourcePath: source,\n spinner: spin,\n })\n .pipe(this.reportResult(spin))\n .subscribe({\n complete: () => {\n resolve()\n },\n error: (error: unknown) => {\n const message = error instanceof Error ? error.message : String(error)\n spin.stop()\n reject(new Error(message))\n },\n })\n\n // Cleanup on Ctrl+C\n process.once('SIGINT', () => {\n subscription.unsubscribe()\n spin.fail('Import interrupted.')\n process.exit(130)\n })\n }).catch((error) => {\n this.error(styleText('red', error.message), {exit: 1})\n })\n }\n\n private reportResult(\n spin: ReturnType<typeof spinner>,\n ): OperatorFunction<State, [number, State | undefined]> {\n let previousState: State | undefined\n\n return pipe(\n scan<State, [number, State | undefined]>(\n (processedAssetsCount, state) => [processedAssetsCount[0] + 1, state],\n [0, undefined],\n ),\n tap({\n complete: () => spin.succeed(`Imported ${previousState?.fileCount} assets`),\n next: ([processedAssetsCount, state]) => {\n previousState = state\n spin.text = `${processedAssetsCount} of ${state?.fileCount} assets imported ${styleText('dim', state?.asset.originalFilename ?? '')}`\n },\n }),\n )\n }\n}\n"],"names":["styleText","Args","Flags","exitCodes","getProjectCliClient","SanityCommand","boxen","spinner","pipe","scan","tap","importer","importMediaDebug","promptForMediaLibrary","promptForProject","getMediaLibraries","getProjectIdFlag","MediaImportCommand","args","source","string","description","required","examples","command","flags","semantics","boolean","run","parse","replaceAspects","projectId","getProjectId","fallback","cliConfig","tryGetCliConfig","dataset","api","mediaLibraries","error","Error","message","exit","length","mediaLibraryId","isUnattended","USAGE_ERROR","some","library","id","projectClient","apiVersion","perspective","requestTagPrefix","requireUser","type","log","padEnd","borderColor","borderStyle","spin","start","importAssets","options","Promise","resolve","reject","subscription","client","sourcePath","reportResult","subscribe","complete","String","stop","process","once","unsubscribe","fail","catch","previousState","processedAssetsCount","state","undefined","succeed","fileCount","next","text","asset","originalFilename"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/media/import.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exitCodes, getProjectCliClient, SanityCommand} from '@sanity/cli-core'\nimport {boxen, spinner} from '@sanity/cli-core/ux'\nimport {SanityClient} from '@sanity/client'\nimport {type OperatorFunction, pipe, scan, tap} from 'rxjs'\n\nimport {importer, type State} from '../../actions/media/importMedia.js'\nimport {importMediaDebug} from '../../actions/media/importMediaDebug.js'\nimport {promptForMediaLibrary} from '../../prompts/promptForMediaLibrary.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {getMediaLibraries} from '../../services/mediaLibraries.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nexport class MediaImportCommand extends SanityCommand<typeof MediaImportCommand> {\n static override args = {\n source: Args.string({\n description: 'Image file or folder to import from',\n required: true,\n }),\n }\n\n static override description = 'Import a set of assets to the target media library.'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> products',\n description: 'Import all assets from the \"products\" directory',\n },\n {\n command: '<%= config.bin %> <%= command.id %> gallery.tar.gz',\n description: 'Import all assets from \"gallery\" archive',\n },\n {\n command: '<%= config.bin %> <%= command.id %> products --replace-aspects',\n description: 'Import all assets from the \"products\" directory and replace aspects',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to import media to',\n semantics: 'override',\n }),\n 'media-library-id': Flags.string({\n description: 'The id of the target media library',\n }),\n 'replace-aspects': Flags.boolean({\n description:\n 'Replace existing aspect data. All versions will be replaced (e.g. published and draft aspect data)',\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(MediaImportCommand)\n const {source} = args\n const replaceAspects = flags['replace-aspects']\n\n const projectId = await this.getProjectId({fallback: () => promptForProject({})})\n\n const cliConfig = await this.tryGetCliConfig()\n const dataset = cliConfig.api?.dataset\n\n let mediaLibraries\n try {\n mediaLibraries = await getMediaLibraries(projectId)\n } catch (error) {\n importMediaDebug('Error listing media libraries', error)\n this.error(\n `Failed to list media libraries:\\n${error instanceof Error ? error.message : error}`,\n {\n exit: exitCodes.RUNTIME_ERROR,\n },\n )\n }\n\n if (mediaLibraries.length === 0) {\n this.error('No active media libraries found in this project', {exit: exitCodes.RUNTIME_ERROR})\n }\n\n let mediaLibraryId = flags['media-library-id']\n if (!mediaLibraryId) {\n if (this.isUnattended()) {\n this.error('Media library ID is required. Pass it with `--media-library-id <id>`.', {\n exit: exitCodes.USAGE_ERROR,\n })\n }\n try {\n mediaLibraryId = await promptForMediaLibrary({mediaLibraries})\n } catch (error) {\n importMediaDebug('Error selecting media library', error)\n this.error(\n `Failed to select media library:\\n${error instanceof Error ? error.message : error}`,\n {\n exit: exitCodes.RUNTIME_ERROR,\n },\n )\n }\n }\n\n if (!mediaLibraries.some((library) => library.id === mediaLibraryId)) {\n this.error(`Media library with id \"${mediaLibraryId}\" not found`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n const projectClient = await getProjectCliClient({\n apiVersion: 'v2025-02-19',\n dataset,\n perspective: 'drafts',\n projectId,\n requestTagPrefix: 'sanity.mediaLibraryCli.import',\n requireUser: true,\n '~experimental_resource': {\n id: mediaLibraryId,\n type: 'media-library',\n },\n })\n\n this.log(\n boxen(\n `\n Importing to media library: ${mediaLibraryId.padEnd(37)}\n Importing from path: ${source}\n `,\n {\n borderColor: 'yellow',\n borderStyle: 'round',\n },\n ),\n )\n\n const spin = spinner('Beginning import…').start()\n\n await this.importAssets({projectClient, replaceAspects, source, spin})\n }\n\n private async importAssets(options: {\n projectClient: SanityClient\n replaceAspects: boolean\n source: string\n spin: ReturnType<typeof spinner>\n }): Promise<void> {\n const {projectClient, replaceAspects, source, spin} = options\n\n return new Promise<void>((resolve, reject) => {\n const subscription = importer({\n client: projectClient,\n replaceAspects,\n sourcePath: source,\n spinner: spin,\n })\n .pipe(this.reportResult(spin))\n .subscribe({\n complete: () => {\n resolve()\n },\n error: (error: unknown) => {\n const message = error instanceof Error ? error.message : String(error)\n spin.stop()\n reject(new Error(message))\n },\n })\n\n // Cleanup on Ctrl+C\n process.once('SIGINT', () => {\n subscription.unsubscribe()\n spin.fail('Import interrupted.')\n process.exit(exitCodes.SIGINT)\n })\n }).catch((error) => {\n this.error(styleText('red', error.message), {exit: exitCodes.RUNTIME_ERROR})\n })\n }\n\n private reportResult(\n spin: ReturnType<typeof spinner>,\n ): OperatorFunction<State, [number, State | undefined]> {\n let previousState: State | undefined\n\n return pipe(\n scan<State, [number, State | undefined]>(\n (processedAssetsCount, state) => [processedAssetsCount[0] + 1, state],\n [0, undefined],\n ),\n tap({\n complete: () => spin.succeed(`Imported ${previousState?.fileCount} assets`),\n next: ([processedAssetsCount, state]) => {\n previousState = state\n spin.text = `${processedAssetsCount} of ${state?.fileCount} assets imported ${styleText('dim', state?.asset.originalFilename ?? '')}`\n },\n }),\n )\n }\n}\n"],"names":["styleText","Args","Flags","exitCodes","getProjectCliClient","SanityCommand","boxen","spinner","pipe","scan","tap","importer","importMediaDebug","promptForMediaLibrary","promptForProject","getMediaLibraries","getProjectIdFlag","MediaImportCommand","args","source","string","description","required","examples","command","flags","semantics","boolean","run","parse","replaceAspects","projectId","getProjectId","fallback","cliConfig","tryGetCliConfig","dataset","api","mediaLibraries","error","Error","message","exit","RUNTIME_ERROR","length","mediaLibraryId","isUnattended","USAGE_ERROR","some","library","id","projectClient","apiVersion","perspective","requestTagPrefix","requireUser","type","log","padEnd","borderColor","borderStyle","spin","start","importAssets","options","Promise","resolve","reject","subscription","client","sourcePath","reportResult","subscribe","complete","String","stop","process","once","unsubscribe","fail","SIGINT","catch","previousState","processedAssetsCount","state","undefined","succeed","fileCount","next","text","asset","originalFilename"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { access, mkdir, writeFile } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { styleText } from 'node:util';
4
4
  import { Args } from '@oclif/core';
5
- import { SanityCommand } from '@sanity/cli-core';
5
+ import { exitCodes, SanityCommand } from '@sanity/cli-core';
6
6
  import { confirm, input, select } from '@sanity/cli-core/ux';
7
7
  import { MIGRATIONS_DIRECTORY } from '../../actions/migration/constants.js';
8
8
  import { minimalAdvanced, minimalSimple, renameField, renameType, stringToPTE } from '../../actions/migration/templates/index.js';
@@ -62,7 +62,7 @@ export class CreateMigrationCommand extends SanityCommand {
62
62
  const sluggedName = title.toLowerCase().normalize('NFD').replaceAll(/\p{Mn}/gu, '').replaceAll(/\s+/g, '-').replaceAll(/[^a-z0-9-]/g, '');
63
63
  if (!sluggedName) {
64
64
  this.error(`Could not derive a valid migration name from title ${JSON.stringify(title)}. Use a title that contains at least one letter or number.`, {
65
- exit: 1
65
+ exit: exitCodes.RUNTIME_ERROR
66
66
  });
67
67
  }
68
68
  const destDir = path.join(workDir, MIGRATIONS_DIRECTORY, sluggedName);
@@ -93,7 +93,7 @@ export class CreateMigrationCommand extends SanityCommand {
93
93
  } catch (error) {
94
94
  const message = error instanceof Error ? error.message : String(error);
95
95
  this.error(`Failed to create migration directory: ${message}`, {
96
- exit: 1
96
+ exit: exitCodes.RUNTIME_ERROR
97
97
  });
98
98
  }
99
99
  try {
@@ -101,7 +101,7 @@ export class CreateMigrationCommand extends SanityCommand {
101
101
  } catch (error) {
102
102
  const message = error instanceof Error ? error.message : String(error);
103
103
  this.error(`Failed to create migration file: ${message}`, {
104
- exit: 1
104
+ exit: exitCodes.RUNTIME_ERROR
105
105
  });
106
106
  }
107
107
  return true;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/migrations/create.ts"],"sourcesContent":["import {access, mkdir, writeFile} from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Args} from '@oclif/core'\nimport {SanityCommand} from '@sanity/cli-core'\nimport {confirm, input, select} from '@sanity/cli-core/ux'\n\nimport {MIGRATIONS_DIRECTORY} from '../../actions/migration/constants.js'\nimport {\n minimalAdvanced,\n minimalSimple,\n renameField,\n renameType,\n stringToPTE,\n} from '../../actions/migration/templates/index.js'\n\nconst TEMPLATES = [\n {name: 'Minimalistic migration to get you started', template: minimalSimple},\n {name: 'Rename an object type', template: renameType},\n {name: 'Rename a field', template: renameField},\n {name: 'Convert string field to Portable Text', template: stringToPTE},\n {\n name: 'Advanced template using async iterators providing more fine grained control',\n template: minimalAdvanced,\n },\n]\n\nexport class CreateMigrationCommand extends SanityCommand<typeof CreateMigrationCommand> {\n static override args = {\n title: Args.string({\n description: 'Title of migration',\n required: false,\n }),\n }\n\n static override description = 'Create a new migration within your project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Create a new migration, prompting for title and options',\n },\n {\n command: '<%= config.bin %> <%= command.id %> \"Rename field from location to address\"',\n description: 'Create a new migration with the provided title, prompting for options',\n },\n ]\n\n static override hiddenAliases = ['migration:create']\n\n public async run(): Promise<void> {\n const {args} = await this.parse(CreateMigrationCommand)\n const {directory: workDir} = await this.getProjectRoot()\n\n const title = await this.promptForTitle(args.title)\n const types = await this.promptForDocumentTypes()\n const {template} = await this.promptForTemplate()\n\n const renderedTemplate = (template || minimalSimple)({\n documentTypes: types\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean),\n migrationName: title,\n })\n\n const sluggedName = title\n .toLowerCase()\n .normalize('NFD')\n .replaceAll(/\\p{Mn}/gu, '')\n .replaceAll(/\\s+/g, '-')\n .replaceAll(/[^a-z0-9-]/g, '')\n\n if (!sluggedName) {\n this.error(\n `Could not derive a valid migration name from title ${JSON.stringify(\n title,\n )}. Use a title that contains at least one letter or number.`,\n {exit: 1},\n )\n }\n\n const destDir = path.join(workDir, MIGRATIONS_DIRECTORY, sluggedName)\n const definitionFile = path.join(destDir, 'index.ts')\n\n const dirCreated = await this.createMigrationFile(destDir, definitionFile, renderedTemplate)\n\n if (dirCreated) {\n this.log()\n this.log(`${styleText('green', '✓')} Migration created!`)\n this.log()\n this.log('Next steps:')\n this.log(\n `Open ${styleText(\n 'bold',\n definitionFile,\n )} in your code editor and write the code for your migration.`,\n )\n this.log(\n `Dry run the migration with:\\n\\`${styleText(\n 'bold',\n `sanity migration run ${sluggedName} --project=<projectId> --dataset <dataset> `,\n )}\\``,\n )\n this.log(\n `Run the migration against a dataset with:\\n \\`${styleText(\n 'bold',\n `sanity migration run ${sluggedName} --project=<projectId> --dataset <dataset> --no-dry-run`,\n )}\\``,\n )\n this.log()\n this.log(\n `👉 Learn more about schema and content migrations at ${styleText(\n 'bold',\n 'https://www.sanity.io/docs/schema-and-content-migrations',\n )}`,\n )\n }\n }\n\n private async createMigrationFile(\n destDir: string,\n definitionFile: string,\n renderedTemplate: string,\n ): Promise<boolean> {\n const dirExists = await access(destDir)\n .then(() => true)\n .catch(() => false)\n\n if (dirExists) {\n const shouldOverwrite = await this.promptForOverwrite(destDir)\n if (!shouldOverwrite) return false\n }\n\n try {\n await mkdir(destDir, {recursive: true})\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.error(`Failed to create migration directory: ${message}`, {exit: 1})\n }\n\n try {\n await writeFile(definitionFile, renderedTemplate)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.error(`Failed to create migration file: ${message}`, {exit: 1})\n }\n\n return true\n }\n\n private async promptForDocumentTypes(): Promise<string> {\n return input({\n message:\n 'Type of documents to migrate. You can add multiple types separated by comma (optional)',\n })\n }\n\n private async promptForOverwrite(destDir: string): Promise<boolean> {\n return confirm({\n default: false,\n message: `Migration directory ${styleText('cyan', destDir)} already exists. Overwrite?`,\n })\n }\n\n private async promptForTemplate(): Promise<{\n name: string\n template: (params: {documentTypes: string[]; migrationName: string}) => string\n }> {\n const templatesByName = Object.fromEntries(TEMPLATES.map((t) => [t.name, t]))\n const templateName = await select({\n choices: TEMPLATES.map((definedTemplate) => ({\n name: definedTemplate.name,\n value: definedTemplate.name,\n })),\n message: 'Select a template',\n })\n\n return templatesByName[templateName]!\n }\n\n private async promptForTitle(providedTitle?: string): Promise<string> {\n if (providedTitle?.trim()) {\n return providedTitle\n }\n\n return input({\n message: 'Title of migration (e.g. \"Rename field from location to address\")',\n validate: (value) => {\n if (!value.trim()) {\n return 'Title cannot be empty'\n }\n\n return true\n },\n })\n }\n}\n"],"names":["access","mkdir","writeFile","path","styleText","Args","SanityCommand","confirm","input","select","MIGRATIONS_DIRECTORY","minimalAdvanced","minimalSimple","renameField","renameType","stringToPTE","TEMPLATES","name","template","CreateMigrationCommand","args","title","string","description","required","examples","command","hiddenAliases","run","parse","directory","workDir","getProjectRoot","promptForTitle","types","promptForDocumentTypes","promptForTemplate","renderedTemplate","documentTypes","split","map","t","trim","filter","Boolean","migrationName","sluggedName","toLowerCase","normalize","replaceAll","error","JSON","stringify","exit","destDir","join","definitionFile","dirCreated","createMigrationFile","log","dirExists","then","catch","shouldOverwrite","promptForOverwrite","recursive","message","Error","String","default","templatesByName","Object","fromEntries","templateName","choices","definedTemplate","value","providedTitle","validate"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/migrations/create.ts"],"sourcesContent":["import {access, mkdir, writeFile} from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Args} from '@oclif/core'\nimport {exitCodes, SanityCommand} from '@sanity/cli-core'\nimport {confirm, input, select} from '@sanity/cli-core/ux'\n\nimport {MIGRATIONS_DIRECTORY} from '../../actions/migration/constants.js'\nimport {\n minimalAdvanced,\n minimalSimple,\n renameField,\n renameType,\n stringToPTE,\n} from '../../actions/migration/templates/index.js'\n\nconst TEMPLATES = [\n {name: 'Minimalistic migration to get you started', template: minimalSimple},\n {name: 'Rename an object type', template: renameType},\n {name: 'Rename a field', template: renameField},\n {name: 'Convert string field to Portable Text', template: stringToPTE},\n {\n name: 'Advanced template using async iterators providing more fine grained control',\n template: minimalAdvanced,\n },\n]\n\nexport class CreateMigrationCommand extends SanityCommand<typeof CreateMigrationCommand> {\n static override args = {\n title: Args.string({\n description: 'Title of migration',\n required: false,\n }),\n }\n\n static override description = 'Create a new migration within your project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Create a new migration, prompting for title and options',\n },\n {\n command: '<%= config.bin %> <%= command.id %> \"Rename field from location to address\"',\n description: 'Create a new migration with the provided title, prompting for options',\n },\n ]\n\n static override hiddenAliases = ['migration:create']\n\n public async run(): Promise<void> {\n const {args} = await this.parse(CreateMigrationCommand)\n const {directory: workDir} = await this.getProjectRoot()\n\n const title = await this.promptForTitle(args.title)\n const types = await this.promptForDocumentTypes()\n const {template} = await this.promptForTemplate()\n\n const renderedTemplate = (template || minimalSimple)({\n documentTypes: types\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean),\n migrationName: title,\n })\n\n const sluggedName = title\n .toLowerCase()\n .normalize('NFD')\n .replaceAll(/\\p{Mn}/gu, '')\n .replaceAll(/\\s+/g, '-')\n .replaceAll(/[^a-z0-9-]/g, '')\n\n if (!sluggedName) {\n this.error(\n `Could not derive a valid migration name from title ${JSON.stringify(\n title,\n )}. Use a title that contains at least one letter or number.`,\n {exit: exitCodes.RUNTIME_ERROR},\n )\n }\n\n const destDir = path.join(workDir, MIGRATIONS_DIRECTORY, sluggedName)\n const definitionFile = path.join(destDir, 'index.ts')\n\n const dirCreated = await this.createMigrationFile(destDir, definitionFile, renderedTemplate)\n\n if (dirCreated) {\n this.log()\n this.log(`${styleText('green', '✓')} Migration created!`)\n this.log()\n this.log('Next steps:')\n this.log(\n `Open ${styleText(\n 'bold',\n definitionFile,\n )} in your code editor and write the code for your migration.`,\n )\n this.log(\n `Dry run the migration with:\\n\\`${styleText(\n 'bold',\n `sanity migration run ${sluggedName} --project=<projectId> --dataset <dataset> `,\n )}\\``,\n )\n this.log(\n `Run the migration against a dataset with:\\n \\`${styleText(\n 'bold',\n `sanity migration run ${sluggedName} --project=<projectId> --dataset <dataset> --no-dry-run`,\n )}\\``,\n )\n this.log()\n this.log(\n `👉 Learn more about schema and content migrations at ${styleText(\n 'bold',\n 'https://www.sanity.io/docs/schema-and-content-migrations',\n )}`,\n )\n }\n }\n\n private async createMigrationFile(\n destDir: string,\n definitionFile: string,\n renderedTemplate: string,\n ): Promise<boolean> {\n const dirExists = await access(destDir)\n .then(() => true)\n .catch(() => false)\n\n if (dirExists) {\n const shouldOverwrite = await this.promptForOverwrite(destDir)\n if (!shouldOverwrite) return false\n }\n\n try {\n await mkdir(destDir, {recursive: true})\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.error(`Failed to create migration directory: ${message}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n try {\n await writeFile(definitionFile, renderedTemplate)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.error(`Failed to create migration file: ${message}`, {exit: exitCodes.RUNTIME_ERROR})\n }\n\n return true\n }\n\n private async promptForDocumentTypes(): Promise<string> {\n return input({\n message:\n 'Type of documents to migrate. You can add multiple types separated by comma (optional)',\n })\n }\n\n private async promptForOverwrite(destDir: string): Promise<boolean> {\n return confirm({\n default: false,\n message: `Migration directory ${styleText('cyan', destDir)} already exists. Overwrite?`,\n })\n }\n\n private async promptForTemplate(): Promise<{\n name: string\n template: (params: {documentTypes: string[]; migrationName: string}) => string\n }> {\n const templatesByName = Object.fromEntries(TEMPLATES.map((t) => [t.name, t]))\n const templateName = await select({\n choices: TEMPLATES.map((definedTemplate) => ({\n name: definedTemplate.name,\n value: definedTemplate.name,\n })),\n message: 'Select a template',\n })\n\n return templatesByName[templateName]!\n }\n\n private async promptForTitle(providedTitle?: string): Promise<string> {\n if (providedTitle?.trim()) {\n return providedTitle\n }\n\n return input({\n message: 'Title of migration (e.g. \"Rename field from location to address\")',\n validate: (value) => {\n if (!value.trim()) {\n return 'Title cannot be empty'\n }\n\n return true\n },\n })\n }\n}\n"],"names":["access","mkdir","writeFile","path","styleText","Args","exitCodes","SanityCommand","confirm","input","select","MIGRATIONS_DIRECTORY","minimalAdvanced","minimalSimple","renameField","renameType","stringToPTE","TEMPLATES","name","template","CreateMigrationCommand","args","title","string","description","required","examples","command","hiddenAliases","run","parse","directory","workDir","getProjectRoot","promptForTitle","types","promptForDocumentTypes","promptForTemplate","renderedTemplate","documentTypes","split","map","t","trim","filter","Boolean","migrationName","sluggedName","toLowerCase","normalize","replaceAll","error","JSON","stringify","exit","RUNTIME_ERROR","destDir","join","definitionFile","dirCreated","createMigrationFile","log","dirExists","then","catch","shouldOverwrite","promptForOverwrite","recursive","message","Error","String","default","templatesByName","Object","fromEntries","templateName","choices","definedTemplate","value","providedTitle","validate"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { styleText } from 'node:util';
2
- import { SanityCommand, subdebug } from '@sanity/cli-core';
2
+ import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
3
3
  import { Table } from 'console-table-printer';
4
4
  import { resolveMigrations } from '../../actions/migration/resolveMigrations.js';
5
5
  const listMigrationDebug = subdebug('migration:list');
@@ -55,7 +55,7 @@ export class ListMigrationCommand extends SanityCommand {
55
55
  }
56
56
  listMigrationDebug('Failed to list migrations:', error);
57
57
  this.error(`List migrations failed: ${error instanceof Error ? error.message : String(error)}`, {
58
- exit: 1
58
+ exit: exitCodes.RUNTIME_ERROR
59
59
  });
60
60
  }
61
61
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/migrations/list.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {Table} from 'console-table-printer'\n\nimport {resolveMigrations} from '../../actions/migration/resolveMigrations.js'\n\nconst listMigrationDebug = subdebug('migration:list')\n\nexport class ListMigrationCommand extends SanityCommand<typeof ListMigrationCommand> {\n static override description = 'List available migrations'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'List all available migrations in the project',\n },\n ]\n\n static override hiddenAliases = ['migration:list']\n\n public async run(): Promise<void> {\n const {directory: workDir} = await this.getProjectRoot()\n\n try {\n const migrations = await resolveMigrations(workDir)\n\n if (migrations.length === 0) {\n this.log('No migrations found in migrations folder of the project')\n this.log(\n `\\nRun ${styleText('green', '`sanity migration create <NAME>`')} to create a new migration`,\n )\n return\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: `Found ${migrations.length} migrations in project`,\n })\n\n for (const definedMigration of migrations) {\n table.addRow({id: definedMigration.id, title: definedMigration.migration.title})\n }\n table.printTable()\n this.log('\\nRun `sanity migration run <ID>` to run a migration')\n listMigrationDebug(`Successfully listed ${migrations.length} migrations`)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n this.log('No migrations folder found in the project')\n this.log(\n `\\nRun ${styleText('green', '`sanity migration create <NAME>`')} to create a new migration`,\n )\n return\n }\n listMigrationDebug('Failed to list migrations:', error)\n this.error(\n `List migrations failed: ${error instanceof Error ? error.message : String(error)}`,\n {\n exit: 1,\n },\n )\n }\n }\n}\n"],"names":["styleText","SanityCommand","subdebug","Table","resolveMigrations","listMigrationDebug","ListMigrationCommand","description","examples","command","hiddenAliases","run","directory","workDir","getProjectRoot","migrations","length","log","table","columns","alignment","name","title","definedMigration","addRow","id","migration","printTable","error","code","Error","message","String","exit"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACxD,SAAQC,KAAK,QAAO,wBAAuB;AAE3C,SAAQC,iBAAiB,QAAO,+CAA8C;AAE9E,MAAMC,qBAAqBH,SAAS;AAEpC,OAAO,MAAMI,6BAA6BL;IACxC,OAAgBM,cAAc,4BAA2B;IAEzD,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTF,aAAa;QACf;KACD,CAAA;IAED,OAAgBG,gBAAgB;QAAC;KAAiB,CAAA;IAElD,MAAaC,MAAqB;QAChC,MAAM,EAACC,WAAWC,OAAO,EAAC,GAAG,MAAM,IAAI,CAACC,cAAc;QAEtD,IAAI;YACF,MAAMC,aAAa,MAAMX,kBAAkBS;YAE3C,IAAIE,WAAWC,MAAM,KAAK,GAAG;gBAC3B,IAAI,CAACC,GAAG,CAAC;gBACT,IAAI,CAACA,GAAG,CACN,CAAC,MAAM,EAAEjB,UAAU,SAAS,oCAAoC,0BAA0B,CAAC;gBAE7F;YACF;YAEA,MAAMkB,QAAQ,IAAIf,MAAM;gBACtBgB,SAAS;oBACP;wBAACC,WAAW;wBAAQC,MAAM;wBAAMC,OAAO;oBAAI;oBAC3C;wBAACF,WAAW;wBAAQC,MAAM;wBAASC,OAAO;oBAAO;iBAClD;gBACDA,OAAO,CAAC,MAAM,EAAEP,WAAWC,MAAM,CAAC,sBAAsB,CAAC;YAC3D;YAEA,KAAK,MAAMO,oBAAoBR,WAAY;gBACzCG,MAAMM,MAAM,CAAC;oBAACC,IAAIF,iBAAiBE,EAAE;oBAAEH,OAAOC,iBAAiBG,SAAS,CAACJ,KAAK;gBAAA;YAChF;YACAJ,MAAMS,UAAU;YAChB,IAAI,CAACV,GAAG,CAAC;YACTZ,mBAAmB,CAAC,oBAAoB,EAAEU,WAAWC,MAAM,CAAC,WAAW,CAAC;QAC1E,EAAE,OAAOY,OAAO;YACd,IAAI,AAACA,MAAgCC,IAAI,KAAK,UAAU;gBACtD,IAAI,CAACZ,GAAG,CAAC;gBACT,IAAI,CAACA,GAAG,CACN,CAAC,MAAM,EAAEjB,UAAU,SAAS,oCAAoC,0BAA0B,CAAC;gBAE7F;YACF;YACAK,mBAAmB,8BAA8BuB;YACjD,IAAI,CAACA,KAAK,CACR,CAAC,wBAAwB,EAAEA,iBAAiBE,QAAQF,MAAMG,OAAO,GAAGC,OAAOJ,QAAQ,EACnF;gBACEK,MAAM;YACR;QAEJ;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/commands/migrations/list.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {Table} from 'console-table-printer'\n\nimport {resolveMigrations} from '../../actions/migration/resolveMigrations.js'\n\nconst listMigrationDebug = subdebug('migration:list')\n\nexport class ListMigrationCommand extends SanityCommand<typeof ListMigrationCommand> {\n static override description = 'List available migrations'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'List all available migrations in the project',\n },\n ]\n\n static override hiddenAliases = ['migration:list']\n\n public async run(): Promise<void> {\n const {directory: workDir} = await this.getProjectRoot()\n\n try {\n const migrations = await resolveMigrations(workDir)\n\n if (migrations.length === 0) {\n this.log('No migrations found in migrations folder of the project')\n this.log(\n `\\nRun ${styleText('green', '`sanity migration create <NAME>`')} to create a new migration`,\n )\n return\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: `Found ${migrations.length} migrations in project`,\n })\n\n for (const definedMigration of migrations) {\n table.addRow({id: definedMigration.id, title: definedMigration.migration.title})\n }\n table.printTable()\n this.log('\\nRun `sanity migration run <ID>` to run a migration')\n listMigrationDebug(`Successfully listed ${migrations.length} migrations`)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n this.log('No migrations folder found in the project')\n this.log(\n `\\nRun ${styleText('green', '`sanity migration create <NAME>`')} to create a new migration`,\n )\n return\n }\n listMigrationDebug('Failed to list migrations:', error)\n this.error(\n `List migrations failed: ${error instanceof Error ? error.message : String(error)}`,\n {\n exit: exitCodes.RUNTIME_ERROR,\n },\n )\n }\n }\n}\n"],"names":["styleText","exitCodes","SanityCommand","subdebug","Table","resolveMigrations","listMigrationDebug","ListMigrationCommand","description","examples","command","hiddenAliases","run","directory","workDir","getProjectRoot","migrations","length","log","table","columns","alignment","name","title","definedMigration","addRow","id","migration","printTable","error","code","Error","message","String","exit","RUNTIME_ERROR"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SAAQC,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACnE,SAAQC,KAAK,QAAO,wBAAuB;AAE3C,SAAQC,iBAAiB,QAAO,+CAA8C;AAE9E,MAAMC,qBAAqBH,SAAS;AAEpC,OAAO,MAAMI,6BAA6BL;IACxC,OAAgBM,cAAc,4BAA2B;IAEzD,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTF,aAAa;QACf;KACD,CAAA;IAED,OAAgBG,gBAAgB;QAAC;KAAiB,CAAA;IAElD,MAAaC,MAAqB;QAChC,MAAM,EAACC,WAAWC,OAAO,EAAC,GAAG,MAAM,IAAI,CAACC,cAAc;QAEtD,IAAI;YACF,MAAMC,aAAa,MAAMX,kBAAkBS;YAE3C,IAAIE,WAAWC,MAAM,KAAK,GAAG;gBAC3B,IAAI,CAACC,GAAG,CAAC;gBACT,IAAI,CAACA,GAAG,CACN,CAAC,MAAM,EAAElB,UAAU,SAAS,oCAAoC,0BAA0B,CAAC;gBAE7F;YACF;YAEA,MAAMmB,QAAQ,IAAIf,MAAM;gBACtBgB,SAAS;oBACP;wBAACC,WAAW;wBAAQC,MAAM;wBAAMC,OAAO;oBAAI;oBAC3C;wBAACF,WAAW;wBAAQC,MAAM;wBAASC,OAAO;oBAAO;iBAClD;gBACDA,OAAO,CAAC,MAAM,EAAEP,WAAWC,MAAM,CAAC,sBAAsB,CAAC;YAC3D;YAEA,KAAK,MAAMO,oBAAoBR,WAAY;gBACzCG,MAAMM,MAAM,CAAC;oBAACC,IAAIF,iBAAiBE,EAAE;oBAAEH,OAAOC,iBAAiBG,SAAS,CAACJ,KAAK;gBAAA;YAChF;YACAJ,MAAMS,UAAU;YAChB,IAAI,CAACV,GAAG,CAAC;YACTZ,mBAAmB,CAAC,oBAAoB,EAAEU,WAAWC,MAAM,CAAC,WAAW,CAAC;QAC1E,EAAE,OAAOY,OAAO;YACd,IAAI,AAACA,MAAgCC,IAAI,KAAK,UAAU;gBACtD,IAAI,CAACZ,GAAG,CAAC;gBACT,IAAI,CAACA,GAAG,CACN,CAAC,MAAM,EAAElB,UAAU,SAAS,oCAAoC,0BAA0B,CAAC;gBAE7F;YACF;YACAM,mBAAmB,8BAA8BuB;YACjD,IAAI,CAACA,KAAK,CACR,CAAC,wBAAwB,EAAEA,iBAAiBE,QAAQF,MAAMG,OAAO,GAAGC,OAAOJ,QAAQ,EACnF;gBACEK,MAAMjC,UAAUkC,aAAa;YAC/B;QAEJ;IACF;AACF"}
@@ -1,7 +1,7 @@
1
1
  import path from 'node:path';
2
2
  import { styleText } from 'node:util';
3
3
  import { Args, Flags } from '@oclif/core';
4
- import { getProjectCliClient, SanityCommand, subdebug } from '@sanity/cli-core';
4
+ import { exitCodes, getProjectCliClient, SanityCommand, subdebug } from '@sanity/cli-core';
5
5
  import { confirm, spinner } from '@sanity/cli-core/ux';
6
6
  import { DEFAULT_MUTATION_CONCURRENCY, dryRun, MAX_MUTATION_CONCURRENCY, run } from '@sanity/migrate';
7
7
  import { Table } from 'console-table-printer';
@@ -86,14 +86,14 @@ export class RunMigrationCommand extends SanityCommand {
86
86
  // any other failure (e.g. a syntax error in a migration file).
87
87
  if (error.code !== 'ENOENT') {
88
88
  this.error(`Failed to list migrations: ${error instanceof Error ? error.message : String(error)}`, {
89
- exit: 1
89
+ exit: exitCodes.RUNTIME_ERROR
90
90
  });
91
91
  }
92
92
  }
93
93
  if (migrations.length === 0) {
94
94
  this.log('\nNo migrations found in the project');
95
95
  this.log(`Run ${styleText('green', '`sanity migration create <NAME>`')} to create a new migration`);
96
- this.exit(1);
96
+ this.exit(exitCodes.RUNTIME_ERROR);
97
97
  }
98
98
  const table = new Table({
99
99
  columns: [
@@ -118,7 +118,7 @@ export class RunMigrationCommand extends SanityCommand {
118
118
  }
119
119
  table.printTable();
120
120
  this.log('\nRun `sanity migration run <ID>` to run a migration');
121
- this.exit(1);
121
+ this.exit(exitCodes.RUNTIME_ERROR);
122
122
  }
123
123
  const cliConfig = await this.getCliConfig();
124
124
  const projectId = await this.getProjectId({
@@ -132,17 +132,17 @@ export class RunMigrationCommand extends SanityCommand {
132
132
  const apiVersion = ensureApiVersionFormat(flags['api-version'] ?? DEFAULT_API_VERSION);
133
133
  if (dataset && !project || project && !dataset) {
134
134
  this.error('If either --dataset or --project is provided, both must be provided', {
135
- exit: 1
135
+ exit: exitCodes.RUNTIME_ERROR
136
136
  });
137
137
  }
138
138
  if (!project && !projectId) {
139
139
  this.error('sanity.cli.js does not contain a project identifier ("api.projectId") and no --project option was provided.', {
140
- exit: 1
140
+ exit: exitCodes.RUNTIME_ERROR
141
141
  });
142
142
  }
143
143
  if (!dataset && !datasetFromConfig) {
144
144
  this.error('sanity.cli.js does not contain a dataset identifier ("api.dataset") and no --dataset option was provided.', {
145
- exit: 1
145
+ exit: exitCodes.RUNTIME_ERROR
146
146
  });
147
147
  }
148
148
  const candidates = await resolveMigrationScript(workDir, id);
@@ -150,14 +150,14 @@ export class RunMigrationCommand extends SanityCommand {
150
150
  if (resolvedScripts.length > 1) {
151
151
  // todo: consider prompt user about which one to run? note: it's likely a mistake if multiple files resolve to the same name
152
152
  this.error(`Found multiple migrations for "${id}" in ${styleText('cyan', migrationsDirectoryPath)}: \n - ${candidates.map((candidate)=>path.relative(migrationsDirectoryPath, candidate.absolutePath)).join('\n - ')}`, {
153
- exit: 1
153
+ exit: exitCodes.RUNTIME_ERROR
154
154
  });
155
155
  }
156
156
  const script = resolvedScripts[0];
157
157
  if (!script) {
158
158
  this.error(`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
159
159
  Tried the following files:\n - ${candidates.map((candidate)=>path.relative(migrationsDirectoryPath, candidate.absolutePath)).join('\n - ')}`, {
160
- exit: 1
160
+ exit: exitCodes.RUNTIME_ERROR
161
161
  });
162
162
  }
163
163
  const mod = script.mod;
@@ -165,25 +165,25 @@ export class RunMigrationCommand extends SanityCommand {
165
165
  // todo: consider adding support for up/down as separate named exports
166
166
  // For now, make sure we reserve the names for future use
167
167
  this.error('Named "up"/"down" migration exports are not supported at this time, please export your migration as the default export', {
168
- exit: 1
168
+ exit: exitCodes.RUNTIME_ERROR
169
169
  });
170
170
  }
171
171
  const migration = mod.default;
172
172
  if (fromExport && !dry) {
173
173
  this.error('Can only dry run migrations from a dataset export file', {
174
- exit: 1
174
+ exit: exitCodes.RUNTIME_ERROR
175
175
  });
176
176
  }
177
177
  const concurrency = flags.concurrency;
178
178
  if (concurrency !== undefined) {
179
179
  if (concurrency > MAX_MUTATION_CONCURRENCY) {
180
180
  this.error(`Concurrency exceeds the maximum allowed value of ${MAX_MUTATION_CONCURRENCY}`, {
181
- exit: 1
181
+ exit: exitCodes.RUNTIME_ERROR
182
182
  });
183
183
  }
184
184
  if (concurrency < 1) {
185
185
  this.error(`Concurrency must be a positive number, got ${concurrency}`, {
186
- exit: 1
186
+ exit: exitCodes.RUNTIME_ERROR
187
187
  });
188
188
  }
189
189
  }
@@ -298,7 +298,7 @@ export class RunMigrationCommand extends SanityCommand {
298
298
  });
299
299
  if (!response) {
300
300
  runMigrationDebug('User aborted migration');
301
- this.exit(1);
301
+ this.exit(exitCodes.RUNTIME_ERROR);
302
302
  }
303
303
  }
304
304
  }
@@ -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 {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} from '@sanity/migrate'\nimport {Table} from 'console-table-printer'\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'\n\nconst runMigrationDebug = subdebug('migration:run')\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 project: Flags.string({\n description:\n 'Project ID of the dataset to migrate. Defaults to the projectId configured in your Sanity CLI config.',\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: 1},\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(1)\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 table.printTable()\n this.log('\\nRun `sanity migration run <ID>` to run a migration')\n\n this.exit(1)\n }\n\n const cliConfig = await this.getCliConfig()\n const projectId = await this.getProjectId({deprecatedFlagName: 'project'})\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', {exit: 1})\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: 1},\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: 1},\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: 1},\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: 1},\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: 1,\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', {exit: 1})\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: 1,\n })\n }\n\n if (concurrency < 1) {\n this.error(`Concurrency must be a positive number, got ${concurrency}`, {exit: 1})\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 try {\n await run(\n {\n api: apiConfig,\n concurrency,\n onProgress: this.createProgress(spin, flags, id, dry, apiConfig, migration),\n },\n migration,\n )\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 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(1)\n }\n }\n}\n"],"names":["path","styleText","Args","Flags","getProjectCliClient","SanityCommand","subdebug","confirm","spinner","DEFAULT_MUTATION_CONCURRENCY","dryRun","MAX_MUTATION_CONCURRENCY","run","Table","DEFAULT_API_VERSION","MIGRATIONS_DIRECTORY","ensureApiVersionFormat","prettyFormat","resolveMigrations","isLoadableMigrationScript","resolveMigrationScript","runMigrationDebug","RunMigrationCommand","args","id","string","description","required","examples","command","flags","concurrency","integer","default","boolean","allowNo","dataset","progress","project","hiddenAliases","parse","directory","workDir","getProjectRoot","migrationsDirectoryPath","join","warn","migrations","error","code","Error","message","String","exit","length","log","table","columns","alignment","name","title","definedMigration","addRow","migration","printTable","cliConfig","getCliConfig","projectId","getProjectId","deprecatedFlagName","datasetFromConfig","api","fromExport","dry","apiVersion","candidates","resolvedScripts","filter","candidate","map","relative","absolutePath","script","mod","undefined","projectClient","requireUser","projectConfig","config","apiConfig","apiHost","token","dryRunHandler","promptConfirmMigrate","spin","start","onProgress","createProgress","stop","progressSpinner","done","text","documents","mutations","completedTransactions","stopAndPersist","symbol","transaction","currentTransactions","documentTypes","pending","indentSize","subject","mutation","exportPath","response"],"mappings":"AAAA,OAAOA,UAAU,YAAW;AAC5B,SAAQC,SAAS,QAAO,YAAW;AAEnC,SAAQC,IAAI,EAAEC,KAAK,QAAO,cAAa;AACvC,SAAQC,mBAAmB,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAC7E,SAAQC,OAAO,EAAEC,OAAO,QAAO,sBAAqB;AACpD,SAEEC,4BAA4B,EAC5BC,MAAM,EACNC,wBAAwB,EAGxBC,GAAG,QACE,kBAAiB;AACxB,SAAQC,KAAK,QAAO,wBAAuB;AAE3C,SAAQC,mBAAmB,EAAEC,oBAAoB,QAAO,uCAAsC;AAC9F,SAAQC,sBAAsB,QAAO,oDAAmD;AACxF,SAAQC,YAAY,QAAO,qDAAoD;AAC/E,SAAQC,iBAAiB,QAAO,+CAA8C;AAC9E,SACEC,yBAAyB,EACzBC,sBAAsB,QACjB,oDAAmD;AAE1D,MAAMC,oBAAoBf,SAAS;AAInC,OAAO,MAAMgB,4BAA4BjB;IACvC,OAAgBkB,OAAO;QACrBC,IAAItB,KAAKuB,MAAM,CAAC;YACdC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,oCAAmC;IAEjE,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SACE;YACFH,aAAa;QACf;QACA;YACEG,SACE;YACFH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtB,eAAe3B,MAAMsB,MAAM,CAAC;YAC1BC,aAAa,CAAC,+CAA+C,EAAEZ,oBAAoB,CAAC,CAAC;QACvF;QACAiB,aAAa5B,MAAM6B,OAAO,CAAC;YACzBC,SAASxB;YACTiB,aAAa,CAAC,qEAAqE,EAAEf,yBAAyB,WAAW,EAAEF,6BAA6B,CAAC,CAAC;QAC5J;QACAF,SAASJ,MAAM+B,OAAO,CAAC;YACrBC,SAAS;YACTF,SAAS;YACTP,aACE;QACJ;QACAU,SAASjC,MAAMsB,MAAM,CAAC;YACpBC,aACE;QACJ;QACA,WAAWvB,MAAM+B,OAAO,CAAC;YACvBC,SAAS;YACTF,SAAS;YACTP,aACE;QACJ;QACA,eAAevB,MAAMsB,MAAM,CAAC;YAC1BC,aACE;QACJ;QACAW,UAAUlC,MAAM+B,OAAO,CAAC;YACtBC,SAAS;YACTF,SAAS;YACTP,aACE;QACJ;QACAY,SAASnC,MAAMsB,MAAM,CAAC;YACpBC,aACE;QACJ;IACF,EAAC;IAED,OAAgBa,gBAAgB;QAAC;KAAgB,CAAA;IAEjD,MAAa3B,MAAqB;QAChC,MAAM,EAACW,IAAI,EAAEO,KAAK,EAAC,GAAG,MAAM,IAAI,CAACU,KAAK,CAAClB;QACvC,MAAM,EAACmB,WAAWC,OAAO,EAAC,GAAG,MAAM,IAAI,CAACC,cAAc;QACtD,MAAMnB,KAAKD,KAAKC,EAAE;QAClB,MAAMoB,0BAA0B5C,KAAK6C,IAAI,CAACH,SAAS3B;QAEnD,wEAAwE;QACxE,wEAAwE;QACxE,IAAI,CAACS,IAAI;YACP,IAAI,CAACsB,IAAI,CAAC7C,UAAU,OAAO;YAE3B,IAAI8C,aAA4D,EAAE;YAClE,IAAI;gBACFA,aAAa,MAAM7B,kBAAkBwB;YACvC,EAAE,OAAOM,OAAO;gBACd,uEAAuE;gBACvE,+DAA+D;gBAC/D,IAAI,AAACA,MAAgCC,IAAI,KAAK,UAAU;oBACtD,IAAI,CAACD,KAAK,CACR,CAAC,2BAA2B,EAAEA,iBAAiBE,QAAQF,MAAMG,OAAO,GAAGC,OAAOJ,QAAQ,EACtF;wBAACK,MAAM;oBAAC;gBAEZ;YACF;YAEA,IAAIN,WAAWO,MAAM,KAAK,GAAG;gBAC3B,IAAI,CAACC,GAAG,CAAC;gBACT,IAAI,CAACA,GAAG,CACN,CAAC,IAAI,EAAEtD,UAAU,SAAS,oCAAoC,0BAA0B,CAAC;gBAE3F,IAAI,CAACoD,IAAI,CAAC;YACZ;YAEA,MAAMG,QAAQ,IAAI3C,MAAM;gBACtB4C,SAAS;oBACP;wBAACC,WAAW;wBAAQC,MAAM;wBAAMC,OAAO;oBAAI;oBAC3C;wBAACF,WAAW;wBAAQC,MAAM;wBAASC,OAAO;oBAAO;iBAClD;gBACDA,OAAO,CAAC,2BAA2B,CAAC;YACtC;YAEA,KAAK,MAAMC,oBAAoBd,WAAY;gBACzCS,MAAMM,MAAM,CAAC;oBAACtC,IAAIqC,iBAAiBrC,EAAE;oBAAEoC,OAAOC,iBAAiBE,SAAS,CAACH,KAAK;gBAAA;YAChF;YACAJ,MAAMQ,UAAU;YAChB,IAAI,CAACT,GAAG,CAAC;YAET,IAAI,CAACF,IAAI,CAAC;QACZ;QAEA,MAAMY,YAAY,MAAM,IAAI,CAACC,YAAY;QACzC,MAAMC,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YAACC,oBAAoB;QAAS;QACxE,MAAMC,oBAAoBL,UAAUM,GAAG,EAAEnC;QAEzC,MAAMoC,aAAa1C,KAAK,CAAC,cAAc;QACvC,MAAM2C,MAAM3C,KAAK,CAAC,UAAU;QAC5B,MAAMM,UAAUN,MAAMM,OAAO;QAC7B,MAAME,UAAUR,MAAMQ,OAAO;QAC7B,MAAMoC,aAAa1D,uBAAuBc,KAAK,CAAC,cAAc,IAAIhB;QAElE,IAAI,AAACsB,WAAW,CAACE,WAAaA,WAAW,CAACF,SAAU;YAClD,IAAI,CAACY,KAAK,CAAC,uEAAuE;gBAACK,MAAM;YAAC;QAC5F;QAEA,IAAI,CAACf,WAAW,CAAC6B,WAAW;YAC1B,IAAI,CAACnB,KAAK,CACR,+GACA;gBAACK,MAAM;YAAC;QAEZ;QAEA,IAAI,CAACjB,WAAW,CAACkC,mBAAmB;YAClC,IAAI,CAACtB,KAAK,CACR,6GACA;gBAACK,MAAM;YAAC;QAEZ;QAEA,MAAMsB,aAAa,MAAMvD,uBAAuBsB,SAASlB;QACzD,MAAMoD,kBAAkBD,WAAWE,MAAM,CAAC,CAACC,YAAc3D,0BAA0B2D;QAEnF,IAAIF,gBAAgBtB,MAAM,GAAG,GAAG;YAC9B,4HAA4H;YAC5H,IAAI,CAACN,KAAK,CACR,CAAC,+BAA+B,EAAExB,GAAG,KAAK,EAAEvB,UAAU,QAAQ2C,yBAAyB,OAAO,EAAE+B,WAC7FI,GAAG,CAAC,CAACD,YAAc9E,KAAKgF,QAAQ,CAACpC,yBAAyBkC,UAAUG,YAAY,GAChFpC,IAAI,CAAC,UAAU,EAClB;gBAACQ,MAAM;YAAC;QAEZ;QAEA,MAAM6B,SAASN,eAAe,CAAC,EAAE;QACjC,IAAI,CAACM,QAAQ;YACX,IAAI,CAAClC,KAAK,CACR,CAAC,wBAAwB,EAAExB,GAAG,KAAK,EAAEvB,UAAU,QAAQ2C,yBAAyB;gCACxD,EAAE+B,WAC9BI,GAAG,CAAC,CAACD,YAAc9E,KAAKgF,QAAQ,CAACpC,yBAAyBkC,UAAUG,YAAY,GAChFpC,IAAI,CAAC,UAAU,EACX;gBAACQ,MAAM;YAAC;QAEZ;QAEA,MAAM8B,MAAMD,OAAOC,GAAG;QACtB,IAAI,QAAQA,OAAO,UAAUA,KAAK;YAChC,sEAAsE;YACtE,yDAAyD;YACzD,IAAI,CAACnC,KAAK,CACR,0HACA;gBACEK,MAAM;YACR;QAEJ;QAEA,MAAMU,YAAuBoB,IAAIlD,OAAO;QAExC,IAAIuC,cAAc,CAACC,KAAK;YACtB,IAAI,CAACzB,KAAK,CAAC,0DAA0D;gBAACK,MAAM;YAAC;QAC/E;QAEA,MAAMtB,cAAcD,MAAMC,WAAW;QACrC,IAAIA,gBAAgBqD,WAAW;YAC7B,IAAIrD,cAAcpB,0BAA0B;gBAC1C,IAAI,CAACqC,KAAK,CAAC,CAAC,iDAAiD,EAAErC,0BAA0B,EAAE;oBACzF0C,MAAM;gBACR;YACF;YAEA,IAAItB,cAAc,GAAG;gBACnB,IAAI,CAACiB,KAAK,CAAC,CAAC,2CAA2C,EAAEjB,aAAa,EAAE;oBAACsB,MAAM;gBAAC;YAClF;QACF;QAEA,MAAMgC,gBAAgB,MAAMjF,oBAAoB;YAC9CsE;YACAP,WAAY7B,WAAW6B;YACvBmB,aAAa;QACf;QACA,MAAMC,gBAAgBF,cAAcG,MAAM;QAE1C,MAAMC,YAAuB;YAC3BC,SAASH,cAAcG,OAAO;YAC9BhB;YACAtC,SAAUA,WAAWkC;YACrBH,WAAY7B,WAAW6B;YACvBwB,OAAOJ,cAAcI,KAAK;QAC5B;QACA,IAAIlB,KAAK;YACP,MAAM,IAAI,CAACmB,aAAa,CAACpE,IAAIuC,WAAW0B,WAAWjB;YACnD;QACF;QAEA,IAAI,CAACjB,GAAG,CACN,CAAC,EAAE,EAAEtD,UAAU;YAAC;YAAU;SAAO,EAAE,wDAAwD;QAE7F,IAAI,CAACsD,GAAG,CACN,CAAC,qDAAqD,EAAEtD,UAAU,QAAQ,iBAAiB,mGAAmG,CAAC;QAGjM,IAAI6B,MAAMvB,OAAO,EAAE;YACjB,MAAM,IAAI,CAACsF,oBAAoB,CAACJ;QAClC;QAEA,MAAMK,OAAOtF,QAAQ,CAAC,mBAAmB,EAAEgB,GAAG,CAAC,CAAC,EAAEuE,KAAK;QACvD,IAAI;YACF,MAAMnF,IACJ;gBACE2D,KAAKkB;gBACL1D;gBACAiE,YAAY,IAAI,CAACC,cAAc,CAACH,MAAMhE,OAAON,IAAIiD,KAAKgB,WAAW1B;YACnE,GACAA;QAEJ,SAAU;YACR+B,KAAKI,IAAI;QACX;IACF;IAEQD,eACNE,eAA2C,EAC3CrE,KAAwB,EACxBN,EAAU,EACViD,GAAY,EACZgB,SAAoB,EACpB1B,SAAoB,EACpB;QACA,OAAO,SAASiC,WAAW3D,QAA2B;YACpD,IAAI,CAACP,MAAMO,QAAQ,EAAE;gBACnB8D,gBAAgBD,IAAI;gBACpB;YACF;YACA,IAAI7D,SAAS+D,IAAI,EAAE;gBACjBD,gBAAgBE,IAAI,GAAG,CAAC,WAAW,EAAE7E,GAAG;;eAEjC,EAAEvB,UAAU,QAAQwF,UAAUtB,SAAS,EAAE;eACzC,EAAElE,UAAU,QAAQwF,UAAUrD,OAAO,EAAE;;EAEpD,EAAEC,SAASiE,SAAS,CAAC;EACrB,EAAEjE,SAASkE,SAAS,CAAC;EACrB,EAAEtG,UAAU,SAASmD,OAAOf,SAASmE,qBAAqB,CAAClD,MAAM,GAAG,wBAAwB,CAAC;gBACvF6C,gBAAgBM,cAAc,CAAC;oBAACC,QAAQzG,UAAU,SAAS;gBAAI;gBAC/D;YACF;YAEA,KAAK,MAAM0G,eAAe;gBAAC;mBAAStE,SAASuE,mBAAmB;aAAC,CAAE;gBACjET,gBAAgBE,IAAI,GAAG,CAAC,mBAAmB,EAAE7E,GAAG,EAAE,EAAEiD,MAAM,mBAAmB,MAAM;;kBAEzE,EAAExE,UAAU,QAAQwF,UAAUtB,SAAS,EAAE;kBACzC,EAAElE,UAAU,QAAQwF,UAAUrD,OAAO,EAAE;kBACvC,EAAEnC,UAAU,QAAQ8D,UAAU8C,aAAa,EAAEhE,KAAK,QAAQ,IAAI;;EAE9E,EAAER,SAASiE,SAAS,CAAC;EACrB,EAAEjE,SAASkE,SAAS,CAAC;EACrB,EAAEtG,UAAU,QAAQmD,OAAOf,SAASyE,OAAO,GAAG;EAC9C,EAAE7G,UAAU,SAASmD,OAAOf,SAASmE,qBAAqB,CAAClD,MAAM,GAAG;;EAEpE,EACEqD,eAAe,CAACtE,SAAS+D,IAAI,GACzB,CAAC,EAAE,EAAEnF,aAAa;oBAAC8F,YAAY;oBAAGhD;oBAAWiD,SAASL;gBAAW,IAAI,GACrE,IACJ;YACE;QACF;IACF;IAEA,MAAcf,cACZpE,EAAU,EACVuC,SAAoB,EACpB0B,SAAoB,EACpBjB,UAA8B,EAC9B;QACA,IAAI,CAACjB,GAAG,CAAC,CAAC,mBAAmB,EAAE/B,GAAG,aAAa,CAAC;QAEhD,IAAIgD,YAAY;YACd,IAAI,CAACjB,GAAG,CAAC,CAAC,aAAa,EAAEtD,UAAU,QAAQuE,aAAa;QAC1D;QAEA,IAAI,CAACjB,GAAG;QACR,IAAI,CAACA,GAAG,CAAC,CAAC,aAAa,EAAEtD,UAAU,QAAQwF,UAAUtB,SAAS,GAAG;QACjE,IAAI,CAACZ,GAAG,CAAC,CAAC,aAAa,EAAEtD,UAAU,QAAQwF,UAAUrD,OAAO,GAAG;QAE/D,WAAW,MAAM6E,YAAYvG,OAAO;YAAC6D,KAAKkB;YAAWyB,YAAY1C;QAAU,GAAGT,WAAY;YACxF,IAAI,CAACkD,UAAU;YACf,IAAI,CAAC1D,GAAG;YACR,IAAI,CAACA,GAAG,CACNtC,aAAa;gBACX8C;gBACAiD,SAASC;YACX;QAEJ;IACF;IAEA,MAAcpB,qBAAqBJ,SAAoB,EAAE;QACvD,MAAM0B,WAAW,MAAM5G,QAAQ;YAC7B4C,SAAS,CAAC,+BAA+B,EAAElD,UACzC;gBAAC;gBAAU;aAAO,EAClBwF,UAAUrD,OAAO,EACjB,YAAY,EAAEnC,UAAU;gBAAC;gBAAU;aAAO,EAAEwF,UAAUtB,SAAS,EAAE,uBAAuB,CAAC;QAC7F;QAEA,IAAI,CAACgD,UAAU;YACb9F,kBAAkB;YAClB,IAAI,CAACgC,IAAI,CAAC;QACZ;IACF;AACF"}
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} from '@sanity/migrate'\nimport {Table} from 'console-table-printer'\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'\n\nconst runMigrationDebug = subdebug('migration:run')\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 project: Flags.string({\n description:\n 'Project ID of the dataset to migrate. Defaults to the projectId configured in your Sanity CLI config.',\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 table.printTable()\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({deprecatedFlagName: 'project'})\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 try {\n await run(\n {\n api: apiConfig,\n concurrency,\n onProgress: this.createProgress(spin, flags, id, dry, apiConfig, migration),\n },\n migration,\n )\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 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","Table","DEFAULT_API_VERSION","MIGRATIONS_DIRECTORY","ensureApiVersionFormat","prettyFormat","resolveMigrations","isLoadableMigrationScript","resolveMigrationScript","runMigrationDebug","RunMigrationCommand","args","id","string","description","required","examples","command","flags","concurrency","integer","default","boolean","allowNo","dataset","progress","project","hiddenAliases","parse","directory","workDir","getProjectRoot","migrationsDirectoryPath","join","warn","migrations","error","code","Error","message","String","exit","RUNTIME_ERROR","length","log","table","columns","alignment","name","title","definedMigration","addRow","migration","printTable","cliConfig","getCliConfig","projectId","getProjectId","deprecatedFlagName","datasetFromConfig","api","fromExport","dry","apiVersion","candidates","resolvedScripts","filter","candidate","map","relative","absolutePath","script","mod","undefined","projectClient","requireUser","projectConfig","config","apiConfig","apiHost","token","dryRunHandler","promptConfirmMigrate","spin","start","onProgress","createProgress","stop","progressSpinner","done","text","documents","mutations","completedTransactions","stopAndPersist","symbol","transaction","currentTransactions","documentTypes","pending","indentSize","subject","mutation","exportPath","response"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { Args, Flags } from '@oclif/core';
2
- import { SanityCommand, subdebug } from '@sanity/cli-core';
2
+ import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
3
3
  import open from 'open';
4
4
  const getOpenapiDebug = subdebug('openapi:get');
5
5
  export class GetOpenApiCommand extends SanityCommand {
@@ -59,11 +59,11 @@ export class GetOpenApiCommand extends SanityCommand {
59
59
  getOpenapiDebug(`Error fetching OpenAPI spec ${slug}`, error);
60
60
  if (error instanceof Response && error.status === 404) {
61
61
  this.error(`OpenAPI specification not found. ${slug}`, {
62
- exit: 1
62
+ exit: exitCodes.RUNTIME_ERROR
63
63
  });
64
64
  }
65
65
  this.error('The OpenAPI service is currently unavailable. Please try again later.', {
66
- exit: 1
66
+ exit: exitCodes.RUNTIME_ERROR
67
67
  });
68
68
  }
69
69
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/openapi/get.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport open from 'open'\n\nconst getOpenapiDebug = subdebug('openapi:get')\n\nexport class GetOpenApiCommand extends SanityCommand<typeof GetOpenApiCommand> {\n static override args = {\n slug: Args.string({\n description: 'Slug of the OpenAPI specification to retrieve',\n required: true,\n }),\n }\n\n static override description = 'Get an OpenAPI specification by slug'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> query',\n description: 'Get a specification (YAML format, default)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> query --format=json',\n description: 'Get specification in JSON format',\n },\n {\n command: '<%= config.bin %> <%= command.id %> query --web',\n description: 'Open specification in browser',\n },\n {\n command: '<%= config.bin %> <%= command.id %> query > query-api.yaml',\n description: 'Pipe to file',\n },\n ]\n\n static override flags = {\n format: Flags.string({\n default: 'yaml',\n description: 'Output format: yaml (default), json',\n options: ['yaml', 'json'],\n }),\n web: Flags.boolean({\n char: 'w',\n description: 'Open in web browser',\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(GetOpenApiCommand)\n const {slug} = args\n const {format, web} = flags\n\n if (web) {\n const url = `https://www.sanity.io/docs/http-reference/${slug}`\n this.log(`Opening ${url}`)\n await open(url)\n return\n }\n\n try {\n const specContent = await this.getSpecContent(slug, format)\n\n this.log(specContent)\n } catch (error) {\n getOpenapiDebug(`Error fetching OpenAPI spec ${slug}`, error)\n\n if (error instanceof Response && error.status === 404) {\n this.error(`OpenAPI specification not found. ${slug}`, {exit: 1})\n }\n\n this.error('The OpenAPI service is currently unavailable. Please try again later.', {\n exit: 1,\n })\n }\n }\n\n private async getSpecContent(slug: string, format: string): Promise<string> {\n const url = new URL(`https://www.sanity.io/docs/api/openapi/${slug}`)\n url.searchParams.set('format', format)\n const response = await fetch(url, {\n signal: AbortSignal.timeout(10_000),\n })\n\n if (response.ok) {\n return response.text()\n }\n\n throw response\n }\n}\n"],"names":["Args","Flags","SanityCommand","subdebug","open","getOpenapiDebug","GetOpenApiCommand","args","slug","string","description","required","examples","command","flags","format","default","options","web","boolean","char","run","parse","url","log","specContent","getSpecContent","error","Response","status","exit","URL","searchParams","set","response","fetch","signal","AbortSignal","timeout","ok","text"],"mappings":"AAAA,SAAQA,IAAI,EAAEC,KAAK,QAAO,cAAa;AACvC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACxD,OAAOC,UAAU,OAAM;AAEvB,MAAMC,kBAAkBF,SAAS;AAEjC,OAAO,MAAMG,0BAA0BJ;IACrC,OAAgBK,OAAO;QACrBC,MAAMR,KAAKS,MAAM,CAAC;YAChBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,uCAAsC;IAEpE,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtBC,QAAQd,MAAMQ,MAAM,CAAC;YACnBO,SAAS;YACTN,aAAa;YACbO,SAAS;gBAAC;gBAAQ;aAAO;QAC3B;QACAC,KAAKjB,MAAMkB,OAAO,CAAC;YACjBC,MAAM;YACNV,aAAa;QACf;IACF,EAAC;IAED,MAAaW,MAAqB;QAChC,MAAM,EAACd,IAAI,EAAEO,KAAK,EAAC,GAAG,MAAM,IAAI,CAACQ,KAAK,CAAChB;QACvC,MAAM,EAACE,IAAI,EAAC,GAAGD;QACf,MAAM,EAACQ,MAAM,EAAEG,GAAG,EAAC,GAAGJ;QAEtB,IAAII,KAAK;YACP,MAAMK,MAAM,CAAC,0CAA0C,EAAEf,MAAM;YAC/D,IAAI,CAACgB,GAAG,CAAC,CAAC,QAAQ,EAAED,KAAK;YACzB,MAAMnB,KAAKmB;YACX;QACF;QAEA,IAAI;YACF,MAAME,cAAc,MAAM,IAAI,CAACC,cAAc,CAAClB,MAAMO;YAEpD,IAAI,CAACS,GAAG,CAACC;QACX,EAAE,OAAOE,OAAO;YACdtB,gBAAgB,CAAC,4BAA4B,EAAEG,MAAM,EAAEmB;YAEvD,IAAIA,iBAAiBC,YAAYD,MAAME,MAAM,KAAK,KAAK;gBACrD,IAAI,CAACF,KAAK,CAAC,CAAC,iCAAiC,EAAEnB,MAAM,EAAE;oBAACsB,MAAM;gBAAC;YACjE;YAEA,IAAI,CAACH,KAAK,CAAC,yEAAyE;gBAClFG,MAAM;YACR;QACF;IACF;IAEA,MAAcJ,eAAelB,IAAY,EAAEO,MAAc,EAAmB;QAC1E,MAAMQ,MAAM,IAAIQ,IAAI,CAAC,uCAAuC,EAAEvB,MAAM;QACpEe,IAAIS,YAAY,CAACC,GAAG,CAAC,UAAUlB;QAC/B,MAAMmB,WAAW,MAAMC,MAAMZ,KAAK;YAChCa,QAAQC,YAAYC,OAAO,CAAC;QAC9B;QAEA,IAAIJ,SAASK,EAAE,EAAE;YACf,OAAOL,SAASM,IAAI;QACtB;QAEA,MAAMN;IACR;AACF"}
1
+ {"version":3,"sources":["../../../src/commands/openapi/get.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport open from 'open'\n\nconst getOpenapiDebug = subdebug('openapi:get')\n\nexport class GetOpenApiCommand extends SanityCommand<typeof GetOpenApiCommand> {\n static override args = {\n slug: Args.string({\n description: 'Slug of the OpenAPI specification to retrieve',\n required: true,\n }),\n }\n\n static override description = 'Get an OpenAPI specification by slug'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> query',\n description: 'Get a specification (YAML format, default)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> query --format=json',\n description: 'Get specification in JSON format',\n },\n {\n command: '<%= config.bin %> <%= command.id %> query --web',\n description: 'Open specification in browser',\n },\n {\n command: '<%= config.bin %> <%= command.id %> query > query-api.yaml',\n description: 'Pipe to file',\n },\n ]\n\n static override flags = {\n format: Flags.string({\n default: 'yaml',\n description: 'Output format: yaml (default), json',\n options: ['yaml', 'json'],\n }),\n web: Flags.boolean({\n char: 'w',\n description: 'Open in web browser',\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(GetOpenApiCommand)\n const {slug} = args\n const {format, web} = flags\n\n if (web) {\n const url = `https://www.sanity.io/docs/http-reference/${slug}`\n this.log(`Opening ${url}`)\n await open(url)\n return\n }\n\n try {\n const specContent = await this.getSpecContent(slug, format)\n\n this.log(specContent)\n } catch (error) {\n getOpenapiDebug(`Error fetching OpenAPI spec ${slug}`, error)\n\n if (error instanceof Response && error.status === 404) {\n this.error(`OpenAPI specification not found. ${slug}`, {exit: exitCodes.RUNTIME_ERROR})\n }\n\n this.error('The OpenAPI service is currently unavailable. Please try again later.', {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async getSpecContent(slug: string, format: string): Promise<string> {\n const url = new URL(`https://www.sanity.io/docs/api/openapi/${slug}`)\n url.searchParams.set('format', format)\n const response = await fetch(url, {\n signal: AbortSignal.timeout(10_000),\n })\n\n if (response.ok) {\n return response.text()\n }\n\n throw response\n }\n}\n"],"names":["Args","Flags","exitCodes","SanityCommand","subdebug","open","getOpenapiDebug","GetOpenApiCommand","args","slug","string","description","required","examples","command","flags","format","default","options","web","boolean","char","run","parse","url","log","specContent","getSpecContent","error","Response","status","exit","RUNTIME_ERROR","URL","searchParams","set","response","fetch","signal","AbortSignal","timeout","ok","text"],"mappings":"AAAA,SAAQA,IAAI,EAAEC,KAAK,QAAO,cAAa;AACvC,SAAQC,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACnE,OAAOC,UAAU,OAAM;AAEvB,MAAMC,kBAAkBF,SAAS;AAEjC,OAAO,MAAMG,0BAA0BJ;IACrC,OAAgBK,OAAO;QACrBC,MAAMT,KAAKU,MAAM,CAAC;YAChBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,uCAAsC;IAEpE,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtBC,QAAQf,MAAMS,MAAM,CAAC;YACnBO,SAAS;YACTN,aAAa;YACbO,SAAS;gBAAC;gBAAQ;aAAO;QAC3B;QACAC,KAAKlB,MAAMmB,OAAO,CAAC;YACjBC,MAAM;YACNV,aAAa;QACf;IACF,EAAC;IAED,MAAaW,MAAqB;QAChC,MAAM,EAACd,IAAI,EAAEO,KAAK,EAAC,GAAG,MAAM,IAAI,CAACQ,KAAK,CAAChB;QACvC,MAAM,EAACE,IAAI,EAAC,GAAGD;QACf,MAAM,EAACQ,MAAM,EAAEG,GAAG,EAAC,GAAGJ;QAEtB,IAAII,KAAK;YACP,MAAMK,MAAM,CAAC,0CAA0C,EAAEf,MAAM;YAC/D,IAAI,CAACgB,GAAG,CAAC,CAAC,QAAQ,EAAED,KAAK;YACzB,MAAMnB,KAAKmB;YACX;QACF;QAEA,IAAI;YACF,MAAME,cAAc,MAAM,IAAI,CAACC,cAAc,CAAClB,MAAMO;YAEpD,IAAI,CAACS,GAAG,CAACC;QACX,EAAE,OAAOE,OAAO;YACdtB,gBAAgB,CAAC,4BAA4B,EAAEG,MAAM,EAAEmB;YAEvD,IAAIA,iBAAiBC,YAAYD,MAAME,MAAM,KAAK,KAAK;gBACrD,IAAI,CAACF,KAAK,CAAC,CAAC,iCAAiC,EAAEnB,MAAM,EAAE;oBAACsB,MAAM7B,UAAU8B,aAAa;gBAAA;YACvF;YAEA,IAAI,CAACJ,KAAK,CAAC,yEAAyE;gBAClFG,MAAM7B,UAAU8B,aAAa;YAC/B;QACF;IACF;IAEA,MAAcL,eAAelB,IAAY,EAAEO,MAAc,EAAmB;QAC1E,MAAMQ,MAAM,IAAIS,IAAI,CAAC,uCAAuC,EAAExB,MAAM;QACpEe,IAAIU,YAAY,CAACC,GAAG,CAAC,UAAUnB;QAC/B,MAAMoB,WAAW,MAAMC,MAAMb,KAAK;YAChCc,QAAQC,YAAYC,OAAO,CAAC;QAC9B;QAEA,IAAIJ,SAASK,EAAE,EAAE;YACf,OAAOL,SAASM,IAAI;QACtB;QAEA,MAAMN;IACR;AACF"}
@@ -1,5 +1,5 @@
1
1
  import { Flags } from '@oclif/core';
2
- import { SanityCommand, subdebug } from '@sanity/cli-core';
2
+ import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
3
3
  import open from 'open';
4
4
  const listOpenapiDebug = subdebug('openapi:list');
5
5
  export class ListOpenApiCommand extends SanityCommand {
@@ -42,7 +42,7 @@ export class ListOpenApiCommand extends SanityCommand {
42
42
  } catch (error) {
43
43
  listOpenapiDebug('Error fetching OpenAPI specs', error);
44
44
  this.error('The OpenAPI service is currently unavailable. Please try again later.', {
45
- exit: 1
45
+ exit: exitCodes.RUNTIME_ERROR
46
46
  });
47
47
  }
48
48
  if (json) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/openapi/list.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport open from 'open'\n\ninterface OpenAPISpec {\n description: string\n slug: string\n title: string\n}\n\nconst listOpenapiDebug = subdebug('openapi:list')\n\nexport class ListOpenApiCommand extends SanityCommand<typeof ListOpenApiCommand> {\n static override description = 'List all available OpenAPI specifications'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'List all available OpenAPI specs',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --json',\n description: 'List with JSON output',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --web',\n description: 'Open HTTP Reference in browser',\n },\n ]\n\n static override flags = {\n json: Flags.boolean({\n description: 'Output JSON',\n }),\n web: Flags.boolean({\n char: 'w',\n description: 'Open HTTP Reference in web browser',\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(ListOpenApiCommand)\n const {json, web} = flags\n\n if (web) {\n const url = 'https://www.sanity.io/docs/http-reference'\n this.log(`Opening ${url}`)\n await open(url)\n return\n }\n\n let specs: OpenAPISpec[]\n try {\n specs = await this.getSpecs()\n } catch (error) {\n listOpenapiDebug('Error fetching OpenAPI specs', error)\n\n this.error('The OpenAPI service is currently unavailable. Please try again later.', {\n exit: 1,\n })\n }\n\n if (json) {\n this.log(JSON.stringify(specs, null, 2))\n return\n }\n\n if (specs.length === 0) {\n this.log('No OpenAPI specifications available.')\n return\n }\n\n // Human-readable table format\n this.log(`\\nFound ${specs.length} OpenAPI specification(s):\\n`)\n\n for (const spec of specs) {\n this.log(`Title: ${spec.title}`)\n this.log(`Slug: ${spec.slug}`)\n if (spec.description) {\n this.log(`Description: ${spec.description}`)\n }\n this.log('')\n }\n\n this.log(`Use 'sanity openapi get <slug>' to retrieve a specific specification.`)\n }\n\n private async getSpecs(): Promise<OpenAPISpec[]> {\n const response = await fetch('https://www.sanity.io/docs/api/openapi', {\n signal: AbortSignal.timeout(10_000),\n })\n\n if (response.ok) {\n const data = await response.json()\n return Array.isArray(data?.specs) ? data.specs : []\n }\n\n throw response\n }\n}\n"],"names":["Flags","SanityCommand","subdebug","open","listOpenapiDebug","ListOpenApiCommand","description","examples","command","flags","json","boolean","web","char","run","parse","url","log","specs","getSpecs","error","exit","JSON","stringify","length","spec","title","slug","response","fetch","signal","AbortSignal","timeout","ok","data","Array","isArray"],"mappings":"AAAA,SAAQA,KAAK,QAAO,cAAa;AACjC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACxD,OAAOC,UAAU,OAAM;AAQvB,MAAMC,mBAAmBF,SAAS;AAElC,OAAO,MAAMG,2BAA2BJ;IACtC,OAAgBK,cAAc,4CAA2C;IAEzE,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;QACtBC,MAAMV,MAAMW,OAAO,CAAC;YAClBL,aAAa;QACf;QACAM,KAAKZ,MAAMW,OAAO,CAAC;YACjBE,MAAM;YACNP,aAAa;QACf;IACF,EAAC;IAED,MAAaQ,MAAqB;QAChC,MAAM,EAACL,KAAK,EAAC,GAAG,MAAM,IAAI,CAACM,KAAK,CAACV;QACjC,MAAM,EAACK,IAAI,EAAEE,GAAG,EAAC,GAAGH;QAEpB,IAAIG,KAAK;YACP,MAAMI,MAAM;YACZ,IAAI,CAACC,GAAG,CAAC,CAAC,QAAQ,EAAED,KAAK;YACzB,MAAMb,KAAKa;YACX;QACF;QAEA,IAAIE;QACJ,IAAI;YACFA,QAAQ,MAAM,IAAI,CAACC,QAAQ;QAC7B,EAAE,OAAOC,OAAO;YACdhB,iBAAiB,gCAAgCgB;YAEjD,IAAI,CAACA,KAAK,CAAC,yEAAyE;gBAClFC,MAAM;YACR;QACF;QAEA,IAAIX,MAAM;YACR,IAAI,CAACO,GAAG,CAACK,KAAKC,SAAS,CAACL,OAAO,MAAM;YACrC;QACF;QAEA,IAAIA,MAAMM,MAAM,KAAK,GAAG;YACtB,IAAI,CAACP,GAAG,CAAC;YACT;QACF;QAEA,8BAA8B;QAC9B,IAAI,CAACA,GAAG,CAAC,CAAC,QAAQ,EAAEC,MAAMM,MAAM,CAAC,4BAA4B,CAAC;QAE9D,KAAK,MAAMC,QAAQP,MAAO;YACxB,IAAI,CAACD,GAAG,CAAC,CAAC,OAAO,EAAEQ,KAAKC,KAAK,EAAE;YAC/B,IAAI,CAACT,GAAG,CAAC,CAAC,MAAM,EAAEQ,KAAKE,IAAI,EAAE;YAC7B,IAAIF,KAAKnB,WAAW,EAAE;gBACpB,IAAI,CAACW,GAAG,CAAC,CAAC,aAAa,EAAEQ,KAAKnB,WAAW,EAAE;YAC7C;YACA,IAAI,CAACW,GAAG,CAAC;QACX;QAEA,IAAI,CAACA,GAAG,CAAC,CAAC,qEAAqE,CAAC;IAClF;IAEA,MAAcE,WAAmC;QAC/C,MAAMS,WAAW,MAAMC,MAAM,0CAA0C;YACrEC,QAAQC,YAAYC,OAAO,CAAC;QAC9B;QAEA,IAAIJ,SAASK,EAAE,EAAE;YACf,MAAMC,OAAO,MAAMN,SAASlB,IAAI;YAChC,OAAOyB,MAAMC,OAAO,CAACF,MAAMhB,SAASgB,KAAKhB,KAAK,GAAG,EAAE;QACrD;QAEA,MAAMU;IACR;AACF"}
1
+ {"version":3,"sources":["../../../src/commands/openapi/list.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport open from 'open'\n\ninterface OpenAPISpec {\n description: string\n slug: string\n title: string\n}\n\nconst listOpenapiDebug = subdebug('openapi:list')\n\nexport class ListOpenApiCommand extends SanityCommand<typeof ListOpenApiCommand> {\n static override description = 'List all available OpenAPI specifications'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'List all available OpenAPI specs',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --json',\n description: 'List with JSON output',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --web',\n description: 'Open HTTP Reference in browser',\n },\n ]\n\n static override flags = {\n json: Flags.boolean({\n description: 'Output JSON',\n }),\n web: Flags.boolean({\n char: 'w',\n description: 'Open HTTP Reference in web browser',\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(ListOpenApiCommand)\n const {json, web} = flags\n\n if (web) {\n const url = 'https://www.sanity.io/docs/http-reference'\n this.log(`Opening ${url}`)\n await open(url)\n return\n }\n\n let specs: OpenAPISpec[]\n try {\n specs = await this.getSpecs()\n } catch (error) {\n listOpenapiDebug('Error fetching OpenAPI specs', error)\n\n this.error('The OpenAPI service is currently unavailable. Please try again later.', {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (json) {\n this.log(JSON.stringify(specs, null, 2))\n return\n }\n\n if (specs.length === 0) {\n this.log('No OpenAPI specifications available.')\n return\n }\n\n // Human-readable table format\n this.log(`\\nFound ${specs.length} OpenAPI specification(s):\\n`)\n\n for (const spec of specs) {\n this.log(`Title: ${spec.title}`)\n this.log(`Slug: ${spec.slug}`)\n if (spec.description) {\n this.log(`Description: ${spec.description}`)\n }\n this.log('')\n }\n\n this.log(`Use 'sanity openapi get <slug>' to retrieve a specific specification.`)\n }\n\n private async getSpecs(): Promise<OpenAPISpec[]> {\n const response = await fetch('https://www.sanity.io/docs/api/openapi', {\n signal: AbortSignal.timeout(10_000),\n })\n\n if (response.ok) {\n const data = await response.json()\n return Array.isArray(data?.specs) ? data.specs : []\n }\n\n throw response\n }\n}\n"],"names":["Flags","exitCodes","SanityCommand","subdebug","open","listOpenapiDebug","ListOpenApiCommand","description","examples","command","flags","json","boolean","web","char","run","parse","url","log","specs","getSpecs","error","exit","RUNTIME_ERROR","JSON","stringify","length","spec","title","slug","response","fetch","signal","AbortSignal","timeout","ok","data","Array","isArray"],"mappings":"AAAA,SAAQA,KAAK,QAAO,cAAa;AACjC,SAAQC,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACnE,OAAOC,UAAU,OAAM;AAQvB,MAAMC,mBAAmBF,SAAS;AAElC,OAAO,MAAMG,2BAA2BJ;IACtC,OAAgBK,cAAc,4CAA2C;IAEzE,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;QACtBC,MAAMX,MAAMY,OAAO,CAAC;YAClBL,aAAa;QACf;QACAM,KAAKb,MAAMY,OAAO,CAAC;YACjBE,MAAM;YACNP,aAAa;QACf;IACF,EAAC;IAED,MAAaQ,MAAqB;QAChC,MAAM,EAACL,KAAK,EAAC,GAAG,MAAM,IAAI,CAACM,KAAK,CAACV;QACjC,MAAM,EAACK,IAAI,EAAEE,GAAG,EAAC,GAAGH;QAEpB,IAAIG,KAAK;YACP,MAAMI,MAAM;YACZ,IAAI,CAACC,GAAG,CAAC,CAAC,QAAQ,EAAED,KAAK;YACzB,MAAMb,KAAKa;YACX;QACF;QAEA,IAAIE;QACJ,IAAI;YACFA,QAAQ,MAAM,IAAI,CAACC,QAAQ;QAC7B,EAAE,OAAOC,OAAO;YACdhB,iBAAiB,gCAAgCgB;YAEjD,IAAI,CAACA,KAAK,CAAC,yEAAyE;gBAClFC,MAAMrB,UAAUsB,aAAa;YAC/B;QACF;QAEA,IAAIZ,MAAM;YACR,IAAI,CAACO,GAAG,CAACM,KAAKC,SAAS,CAACN,OAAO,MAAM;YACrC;QACF;QAEA,IAAIA,MAAMO,MAAM,KAAK,GAAG;YACtB,IAAI,CAACR,GAAG,CAAC;YACT;QACF;QAEA,8BAA8B;QAC9B,IAAI,CAACA,GAAG,CAAC,CAAC,QAAQ,EAAEC,MAAMO,MAAM,CAAC,4BAA4B,CAAC;QAE9D,KAAK,MAAMC,QAAQR,MAAO;YACxB,IAAI,CAACD,GAAG,CAAC,CAAC,OAAO,EAAES,KAAKC,KAAK,EAAE;YAC/B,IAAI,CAACV,GAAG,CAAC,CAAC,MAAM,EAAES,KAAKE,IAAI,EAAE;YAC7B,IAAIF,KAAKpB,WAAW,EAAE;gBACpB,IAAI,CAACW,GAAG,CAAC,CAAC,aAAa,EAAES,KAAKpB,WAAW,EAAE;YAC7C;YACA,IAAI,CAACW,GAAG,CAAC;QACX;QAEA,IAAI,CAACA,GAAG,CAAC,CAAC,qEAAqE,CAAC;IAClF;IAEA,MAAcE,WAAmC;QAC/C,MAAMU,WAAW,MAAMC,MAAM,0CAA0C;YACrEC,QAAQC,YAAYC,OAAO,CAAC;QAC9B;QAEA,IAAIJ,SAASK,EAAE,EAAE;YACf,MAAMC,OAAO,MAAMN,SAASnB,IAAI;YAChC,OAAO0B,MAAMC,OAAO,CAACF,MAAMjB,SAASiB,KAAKjB,KAAK,GAAG,EAAE;QACrD;QAEA,MAAMW;IACR;AACF"}
@@ -1,5 +1,5 @@
1
1
  import { Flags } from '@oclif/core';
2
- import { SanityCommand, subdebug } from '@sanity/cli-core';
2
+ import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
3
3
  import { getErrorMessage } from '@sanity/cli-core/errors';
4
4
  import { spinner } from '@sanity/cli-core/ux';
5
5
  import { validateOrganizationName } from '../../actions/organizations/validateOrganizationName.js';
@@ -39,14 +39,14 @@ export class CreateOrganizationCommand extends SanityCommand {
39
39
  const defaultRole = defaultRoleFlag?.trim();
40
40
  if (defaultRole === '') {
41
41
  this.error('Default role cannot be empty', {
42
- exit: 1
42
+ exit: exitCodes.RUNTIME_ERROR
43
43
  });
44
44
  }
45
45
  let name;
46
46
  if (nameFlag === undefined) {
47
47
  if (this.isUnattended()) {
48
48
  this.error('Organization name is required. Provide it with the --name flag.', {
49
- exit: 1
49
+ exit: exitCodes.RUNTIME_ERROR
50
50
  });
51
51
  }
52
52
  name = await promptForOrganizationName();
@@ -55,7 +55,7 @@ export class CreateOrganizationCommand extends SanityCommand {
55
55
  const validation = validateOrganizationName(trimmedName);
56
56
  if (validation !== true) {
57
57
  this.error(validation, {
58
- exit: 1
58
+ exit: exitCodes.RUNTIME_ERROR
59
59
  });
60
60
  }
61
61
  name = trimmedName;
@@ -70,7 +70,7 @@ export class CreateOrganizationCommand extends SanityCommand {
70
70
  spin.fail();
71
71
  createOrgDebug('Error creating organization', error);
72
72
  this.error(`Failed to create organization: ${getErrorMessage(error)}`, {
73
- exit: 1
73
+ exit: exitCodes.RUNTIME_ERROR
74
74
  });
75
75
  }
76
76
  }
@@ -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 {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\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: Flags.string({\n description: 'Organization name',\n required: false,\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: 1})\n }\n\n let name: string\n if (nameFlag === undefined) {\n if (this.isUnattended()) {\n this.error('Organization name is required. Provide it with the --name flag.', {exit: 1})\n }\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: 1})\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: 1,\n })\n }\n }\n}\n"],"names":["Flags","SanityCommand","subdebug","getErrorMessage","spinner","validateOrganizationName","promptForOrganizationName","createOrganization","organizationAliases","createOrgDebug","CreateOrganizationCommand","description","examples","command","flags","string","required","name","hiddenAliases","run","defaultRoleFlag","nameFlag","defaultRole","trim","error","exit","undefined","isUnattended","trimmedName","validation","spin","start","org","succeed","log","id","fail"],"mappings":"AAAA,SAAQA,KAAK,QAAO,cAAa;AAEjC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACxD,SAAQC,eAAe,QAAO,0BAAyB;AACvD,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,iBAAiBP,SAAS;AAEhC,OAAO,MAAMQ,kCAAkCT;IAC7C,OAAgBU,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,gBAAgBd,MAAMe,MAAM,CAAC;YAC3BJ,aAAa;YACbK,UAAU;QACZ;QACAC,MAAMjB,MAAMe,MAAM,CAAC;YACjBJ,aAAa;YACbK,UAAU;QACZ;IACF,EAAqB;IAErB,OAAgBE,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,MAAM;YAAC;QACrD;QAEA,IAAIR;QACJ,IAAII,aAAaK,WAAW;YAC1B,IAAI,IAAI,CAACC,YAAY,IAAI;gBACvB,IAAI,CAACH,KAAK,CAAC,mEAAmE;oBAACC,MAAM;gBAAC;YACxF;YACAR,OAAO,MAAMX;QACf,OAAO;YACL,MAAMsB,cAAcP,SAASE,IAAI;YACjC,MAAMM,aAAaxB,yBAAyBuB;YAC5C,IAAIC,eAAe,MAAM;gBACvB,IAAI,CAACL,KAAK,CAACK,YAAY;oBAACJ,MAAM;gBAAC;YACjC;YACAR,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,EAAErB,gBAAgBqB,QAAQ,EAAE;gBACrEC,MAAM;YACR;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 {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: Flags.string({\n description: 'Organization name',\n required: false,\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 if (this.isUnattended()) {\n this.error('Organization name is required. Provide it with the --name flag.', {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\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","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","isUnattended","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,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,iBAAiBP,SAAS;AAEhC,OAAO,MAAMQ,kCAAkCT;IAC7C,OAAgBU,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,gBAAgBf,MAAMgB,MAAM,CAAC;YAC3BJ,aAAa;YACbK,UAAU;QACZ;QACAC,MAAMlB,MAAMgB,MAAM,CAAC;YACjBJ,aAAa;YACbK,UAAU;QACZ;IACF,EAAqB;IAErB,OAAgBE,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,MAAMzB,UAAU0B,aAAa;YAAA;QAC3E;QAEA,IAAIT;QACJ,IAAII,aAAaM,WAAW;YAC1B,IAAI,IAAI,CAACC,YAAY,IAAI;gBACvB,IAAI,CAACJ,KAAK,CAAC,mEAAmE;oBAC5EC,MAAMzB,UAAU0B,aAAa;gBAC/B;YACF;YACAT,OAAO,MAAMX;QACf,OAAO;YACL,MAAMuB,cAAcR,SAASE,IAAI;YACjC,MAAMO,aAAazB,yBAAyBwB;YAC5C,IAAIC,eAAe,MAAM;gBACvB,IAAI,CAACN,KAAK,CAACM,YAAY;oBAACL,MAAMzB,UAAU0B,aAAa;gBAAA;YACvD;YACAT,OAAOY;QACT;QAEA,MAAME,OAAO3B,QAAQ,yBAAyB4B,KAAK;QACnD,IAAI;YACF,MAAMC,MAAM,MAAM1B,mBAAmBU,MAAMK;YAC3CS,KAAKG,OAAO,CAAC;YACb,IAAI,CAACC,GAAG,CAAC,CAAC,MAAM,EAAEF,IAAIG,EAAE,EAAE;YAC1B,IAAI,CAACD,GAAG,CAAC,CAAC,MAAM,EAAEF,IAAIhB,IAAI,EAAE;QAC9B,EAAE,OAAOO,OAAO;YACdO,KAAKM,IAAI;YACT5B,eAAe,+BAA+Be;YAC9C,IAAI,CAACA,KAAK,CAAC,CAAC,+BAA+B,EAAErB,gBAAgBqB,QAAQ,EAAE;gBACrEC,MAAMzB,UAAU0B,aAAa;YAC/B;QACF;IACF;AACF"}