@sanity/cli 6.0.0-alpha.17 → 6.0.0-alpha.19

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 (249) hide show
  1. package/README.md +833 -912
  2. package/dist/SanityHelp.js +74 -21
  3. package/dist/SanityHelp.js.map +1 -1
  4. package/dist/actions/build/buildApp.js +42 -15
  5. package/dist/actions/build/buildApp.js.map +1 -1
  6. package/dist/actions/build/buildStudio.js +21 -9
  7. package/dist/actions/build/buildStudio.js.map +1 -1
  8. package/dist/actions/build/buildVendorDependencies.js +3 -16
  9. package/dist/actions/build/buildVendorDependencies.js.map +1 -1
  10. package/dist/actions/build/checkStudioDependencyVersions.js +7 -7
  11. package/dist/actions/build/checkStudioDependencyVersions.js.map +1 -1
  12. package/dist/actions/build/createExternalFromImportMap.js +1 -1
  13. package/dist/actions/build/createExternalFromImportMap.js.map +1 -1
  14. package/dist/actions/build/determineBasePath.js +5 -2
  15. package/dist/actions/build/determineBasePath.js.map +1 -1
  16. package/dist/actions/build/getViteConfig.js +47 -4
  17. package/dist/actions/build/getViteConfig.js.map +1 -1
  18. package/dist/actions/build/handlePrereleaseVersions.js +44 -0
  19. package/dist/actions/build/handlePrereleaseVersions.js.map +1 -0
  20. package/dist/actions/build/renderDocumentWorker/components/GlobalErrorHandler.js +1 -0
  21. package/dist/actions/build/renderDocumentWorker/components/GlobalErrorHandler.js.map +1 -1
  22. package/dist/actions/build/types.js.map +1 -1
  23. package/dist/actions/build/writeSanityRuntime.js +4 -3
  24. package/dist/actions/build/writeSanityRuntime.js.map +1 -1
  25. package/dist/actions/dataset/create.js +7 -1
  26. package/dist/actions/dataset/create.js.map +1 -1
  27. package/dist/actions/dataset/resolveDataset.js +26 -0
  28. package/dist/actions/dataset/resolveDataset.js.map +1 -0
  29. package/dist/actions/deploy/deployApp.js +1 -8
  30. package/dist/actions/deploy/deployApp.js.map +1 -1
  31. package/dist/actions/deploy/deployStudio.js +1 -0
  32. package/dist/actions/deploy/deployStudio.js.map +1 -1
  33. package/dist/actions/dev/getDashboardAppUrl.js +48 -0
  34. package/dist/actions/dev/getDashboardAppUrl.js.map +1 -0
  35. package/dist/actions/dev/getDevServerConfig.js +7 -3
  36. package/dist/actions/dev/getDevServerConfig.js.map +1 -1
  37. package/dist/actions/dev/startAppDevServer.js +3 -3
  38. package/dist/actions/dev/startAppDevServer.js.map +1 -1
  39. package/dist/actions/dev/startStudioDevServer.js +12 -12
  40. package/dist/actions/dev/startStudioDevServer.js.map +1 -1
  41. package/dist/actions/documents/types.js.map +1 -1
  42. package/dist/actions/documents/validate.js +11 -2
  43. package/dist/actions/documents/validate.js.map +1 -1
  44. package/dist/actions/documents/validateDocuments.worker.js +2 -2
  45. package/dist/actions/documents/validateDocuments.worker.js.map +1 -1
  46. package/dist/actions/documents/validation/reporters/jsonReporter.js +1 -1
  47. package/dist/actions/documents/validation/reporters/jsonReporter.js.map +1 -1
  48. package/dist/actions/documents/validation/reporters/ndjsonReporter.js +1 -1
  49. package/dist/actions/documents/validation/reporters/ndjsonReporter.js.map +1 -1
  50. package/dist/actions/graphql/SchemaError.js +1 -1
  51. package/dist/actions/graphql/SchemaError.js.map +1 -1
  52. package/dist/actions/graphql/__tests__/fixtures/many-self-refs.js +540 -0
  53. package/dist/actions/graphql/__tests__/fixtures/many-self-refs.js.map +1 -0
  54. package/dist/actions/graphql/__tests__/fixtures/test-studio.js +1143 -0
  55. package/dist/actions/graphql/__tests__/fixtures/test-studio.js.map +1 -0
  56. package/dist/actions/graphql/__tests__/fixtures/union-refs.js +591 -0
  57. package/dist/actions/graphql/__tests__/fixtures/union-refs.js.map +1 -0
  58. package/dist/actions/graphql/__tests__/helpers.js +23 -0
  59. package/dist/actions/graphql/__tests__/helpers.js.map +1 -0
  60. package/dist/actions/graphql/extractFromSanitySchema.js +2 -1
  61. package/dist/actions/graphql/extractFromSanitySchema.js.map +1 -1
  62. package/dist/actions/graphql/gen1/generateTypeFilters.js +1 -1
  63. package/dist/actions/graphql/gen1/generateTypeFilters.js.map +1 -1
  64. package/dist/actions/graphql/gen1/generateTypeQueries.js +2 -1
  65. package/dist/actions/graphql/gen1/generateTypeQueries.js.map +1 -1
  66. package/dist/actions/graphql/gen2/generateTypeQueries.js +1 -1
  67. package/dist/actions/graphql/gen2/generateTypeQueries.js.map +1 -1
  68. package/dist/actions/graphql/gen3/generateTypeQueries.js +1 -1
  69. package/dist/actions/graphql/gen3/generateTypeQueries.js.map +1 -1
  70. package/dist/actions/graphql/getGraphQLAPIs.js +2 -10
  71. package/dist/actions/graphql/getGraphQLAPIs.js.map +1 -1
  72. package/dist/actions/graphql/getGraphQLAPIs.worker.js +1 -1
  73. package/dist/actions/graphql/getGraphQLAPIs.worker.js.map +1 -1
  74. package/dist/actions/graphql/types.js.map +1 -1
  75. package/dist/actions/init/bootstrapLocalTemplate.js +1 -1
  76. package/dist/actions/init/bootstrapLocalTemplate.js.map +1 -1
  77. package/dist/actions/manifest/extractAppManifest.js.map +1 -1
  78. package/dist/actions/manifest/extractManifest.js +1 -22
  79. package/dist/actions/manifest/extractManifest.js.map +1 -1
  80. package/dist/actions/manifest/types.js.map +1 -1
  81. package/dist/actions/schema/deploySchemas.js +57 -80
  82. package/dist/actions/schema/deploySchemas.js.map +1 -1
  83. package/dist/actions/schema/extractSanityWorkspace.worker.js +24 -0
  84. package/dist/actions/schema/extractSanityWorkspace.worker.js.map +1 -0
  85. package/dist/actions/schema/extractSchemaWatcher.js +9 -7
  86. package/dist/actions/schema/extractSchemaWatcher.js.map +1 -1
  87. package/dist/actions/schema/matchSchemaPattern.js +22 -0
  88. package/dist/actions/schema/matchSchemaPattern.js.map +1 -0
  89. package/dist/actions/schema/runSchemaExtraction.js.map +1 -1
  90. package/dist/actions/schema/types.js +4 -0
  91. package/dist/actions/schema/types.js.map +1 -1
  92. package/dist/actions/schema/utils/schemaStoreValidation.js +1 -7
  93. package/dist/actions/schema/utils/schemaStoreValidation.js.map +1 -1
  94. package/dist/actions/schema/utils/uniqByProjectIdDataset.js +1 -1
  95. package/dist/actions/schema/utils/uniqByProjectIdDataset.js.map +1 -1
  96. package/dist/actions/schema/watchExtractSchema.js +2 -1
  97. package/dist/actions/schema/watchExtractSchema.js.map +1 -1
  98. package/dist/actions/versions/getFormatters.js +1 -1
  99. package/dist/actions/versions/getFormatters.js.map +1 -1
  100. package/dist/commands/backup/disable.js +0 -6
  101. package/dist/commands/backup/disable.js.map +1 -1
  102. package/dist/commands/backup/download.js +0 -6
  103. package/dist/commands/backup/download.js.map +1 -1
  104. package/dist/commands/backup/enable.js +0 -6
  105. package/dist/commands/backup/enable.js.map +1 -1
  106. package/dist/commands/backup/list.js +4 -7
  107. package/dist/commands/backup/list.js.map +1 -1
  108. package/dist/commands/cors/add.js +0 -6
  109. package/dist/commands/cors/add.js.map +1 -1
  110. package/dist/commands/cors/delete.js +0 -6
  111. package/dist/commands/cors/delete.js.map +1 -1
  112. package/dist/commands/cors/list.js +0 -6
  113. package/dist/commands/cors/list.js.map +1 -1
  114. package/dist/commands/dataset/alias/create.js +23 -7
  115. package/dist/commands/dataset/alias/create.js.map +1 -1
  116. package/dist/commands/dataset/alias/delete.js +17 -7
  117. package/dist/commands/dataset/alias/delete.js.map +1 -1
  118. package/dist/commands/dataset/alias/link.js +17 -7
  119. package/dist/commands/dataset/alias/link.js.map +1 -1
  120. package/dist/commands/dataset/alias/unlink.js +17 -7
  121. package/dist/commands/dataset/alias/unlink.js.map +1 -1
  122. package/dist/commands/dataset/copy.js +42 -30
  123. package/dist/commands/dataset/copy.js.map +1 -1
  124. package/dist/commands/dataset/create.js +29 -7
  125. package/dist/commands/dataset/create.js.map +1 -1
  126. package/dist/commands/dataset/delete.js +13 -7
  127. package/dist/commands/dataset/delete.js.map +1 -1
  128. package/dist/commands/dataset/embeddings/disable.js +74 -0
  129. package/dist/commands/dataset/embeddings/disable.js.map +1 -0
  130. package/dist/commands/dataset/embeddings/enable.js +138 -0
  131. package/dist/commands/dataset/embeddings/enable.js.map +1 -0
  132. package/dist/commands/dataset/embeddings/status.js +69 -0
  133. package/dist/commands/dataset/embeddings/status.js.map +1 -0
  134. package/dist/commands/dataset/export.js +30 -18
  135. package/dist/commands/dataset/export.js.map +1 -1
  136. package/dist/commands/dataset/list.js +19 -7
  137. package/dist/commands/dataset/list.js.map +1 -1
  138. package/dist/commands/dataset/visibility/get.js +15 -7
  139. package/dist/commands/dataset/visibility/get.js.map +1 -1
  140. package/dist/commands/dataset/visibility/set.js +19 -7
  141. package/dist/commands/dataset/visibility/set.js.map +1 -1
  142. package/dist/commands/debug.js +2 -1
  143. package/dist/commands/debug.js.map +1 -1
  144. package/dist/commands/documents/create.js +2 -7
  145. package/dist/commands/documents/create.js.map +1 -1
  146. package/dist/commands/documents/delete.js +0 -6
  147. package/dist/commands/documents/delete.js.map +1 -1
  148. package/dist/commands/documents/get.js +0 -6
  149. package/dist/commands/documents/get.js.map +1 -1
  150. package/dist/commands/documents/query.js +0 -6
  151. package/dist/commands/documents/query.js.map +1 -1
  152. package/dist/commands/graphql/deploy.js +1 -1
  153. package/dist/commands/graphql/deploy.js.map +1 -1
  154. package/dist/commands/graphql/list.js +0 -6
  155. package/dist/commands/graphql/list.js.map +1 -1
  156. package/dist/commands/graphql/undeploy.js +0 -6
  157. package/dist/commands/graphql/undeploy.js.map +1 -1
  158. package/dist/commands/hook/attempt.js +0 -6
  159. package/dist/commands/hook/attempt.js.map +1 -1
  160. package/dist/commands/hook/create.js +0 -6
  161. package/dist/commands/hook/create.js.map +1 -1
  162. package/dist/commands/hook/delete.js +0 -6
  163. package/dist/commands/hook/delete.js.map +1 -1
  164. package/dist/commands/hook/list.js +0 -6
  165. package/dist/commands/hook/list.js.map +1 -1
  166. package/dist/commands/hook/logs.js +1 -7
  167. package/dist/commands/hook/logs.js.map +1 -1
  168. package/dist/commands/init.js +13 -7
  169. package/dist/commands/init.js.map +1 -1
  170. package/dist/commands/manage.js +0 -1
  171. package/dist/commands/manage.js.map +1 -1
  172. package/dist/commands/media/create-aspect.js +1 -1
  173. package/dist/commands/media/create-aspect.js.map +1 -1
  174. package/dist/commands/media/delete-aspect.js +0 -6
  175. package/dist/commands/media/delete-aspect.js.map +1 -1
  176. package/dist/commands/media/deploy-aspect.js +1 -6
  177. package/dist/commands/media/deploy-aspect.js.map +1 -1
  178. package/dist/commands/media/export.js +0 -6
  179. package/dist/commands/media/export.js.map +1 -1
  180. package/dist/commands/media/import.js +0 -6
  181. package/dist/commands/media/import.js.map +1 -1
  182. package/dist/commands/projects/list.js +2 -1
  183. package/dist/commands/projects/list.js.map +1 -1
  184. package/dist/commands/schema/delete.js +0 -6
  185. package/dist/commands/schema/delete.js.map +1 -1
  186. package/dist/commands/schema/deploy.js +11 -27
  187. package/dist/commands/schema/deploy.js.map +1 -1
  188. package/dist/commands/tokens/add.js +0 -6
  189. package/dist/commands/tokens/add.js.map +1 -1
  190. package/dist/commands/tokens/delete.js +0 -6
  191. package/dist/commands/tokens/delete.js.map +1 -1
  192. package/dist/commands/tokens/list.js +0 -6
  193. package/dist/commands/tokens/list.js.map +1 -1
  194. package/dist/commands/users/invite.js +0 -6
  195. package/dist/commands/users/invite.js.map +1 -1
  196. package/dist/commands/users/list.js +1 -7
  197. package/dist/commands/users/list.js.map +1 -1
  198. package/dist/commands/versions.js +1 -1
  199. package/dist/commands/versions.js.map +1 -1
  200. package/dist/exports/index.d.ts +62 -2
  201. package/dist/exports/index.js.map +1 -1
  202. package/dist/prompts/promptForProject.js +64 -0
  203. package/dist/prompts/promptForProject.js.map +1 -0
  204. package/dist/prompts/selectMediaLibrary.js +1 -1
  205. package/dist/prompts/selectMediaLibrary.js.map +1 -1
  206. package/dist/server/devServer.js +4 -2
  207. package/dist/server/devServer.js.map +1 -1
  208. package/dist/server/vite/plugin-schema-extraction.js +201 -0
  209. package/dist/server/vite/plugin-schema-extraction.js.map +1 -0
  210. package/dist/server/vite/plugin-typegen.js +217 -0
  211. package/dist/server/vite/plugin-typegen.js.map +1 -0
  212. package/dist/services/datasets.js +7 -5
  213. package/dist/services/datasets.js.map +1 -1
  214. package/dist/services/embeddings.js +25 -0
  215. package/dist/services/embeddings.js.map +1 -0
  216. package/dist/services/grants.js +13 -0
  217. package/dist/services/grants.js.map +1 -0
  218. package/dist/services/graphql.js.map +1 -1
  219. package/dist/services/schemas.js +1 -1
  220. package/dist/services/schemas.js.map +1 -1
  221. package/dist/types/grants.js +3 -0
  222. package/dist/types/grants.js.map +1 -0
  223. package/dist/types.js.map +1 -1
  224. package/dist/util/checkProjectPermissions.js +21 -0
  225. package/dist/util/checkProjectPermissions.js.map +1 -0
  226. package/dist/util/compareDependencyVersions.js +28 -7
  227. package/dist/util/compareDependencyVersions.js.map +1 -1
  228. package/dist/util/errorMessages.js +0 -1
  229. package/dist/util/errorMessages.js.map +1 -1
  230. package/dist/util/getSharedServerConfig.js +1 -0
  231. package/dist/util/getSharedServerConfig.js.map +1 -1
  232. package/dist/util/packageManager/getPeerDependencies.js +44 -0
  233. package/dist/util/packageManager/getPeerDependencies.js.map +1 -0
  234. package/dist/util/sharedFlags.js +19 -0
  235. package/dist/util/sharedFlags.js.map +1 -0
  236. package/dist/util/toForwardSlashes.js +8 -0
  237. package/dist/util/toForwardSlashes.js.map +1 -0
  238. package/oclif.manifest.json +639 -379
  239. package/package.json +23 -22
  240. package/dist/actions/dev/getCoreAppUrl.js +0 -10
  241. package/dist/actions/dev/getCoreAppUrl.js.map +0 -1
  242. package/dist/actions/schema/schemaStoreTypes.js +0 -19
  243. package/dist/actions/schema/schemaStoreTypes.js.map +0 -1
  244. package/dist/actions/schema/utils/manifestExtractor.js +0 -29
  245. package/dist/actions/schema/utils/manifestExtractor.js.map +0 -1
  246. package/dist/actions/schema/utils/manifestReader.js +0 -71
  247. package/dist/actions/schema/utils/manifestReader.js.map +0 -1
  248. package/dist/util/workerChannels.js +0 -172
  249. package/dist/util/workerChannels.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/commands/dataset/alias/unlink.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {input} from '@sanity/cli-core/ux'\n\nimport {processAliasName} from '../../../actions/dataset/processAliasName.js'\nimport {validateDatasetAliasName} from '../../../actions/dataset/validateDatasetAliasName.js'\nimport {promptForDatasetAliasName} from '../../../prompts/promptForDatasetAliasName.js'\nimport {listAliases, unlinkAlias} from '../../../services/datasetAliases.js'\nimport {NO_PROJECT_ID} from '../../../util/errorMessages.js'\n\nconst unlinkAliasDebug = subdebug('dataset:alias:unlink')\n\nexport class UnlinkAliasCommand extends SanityCommand<typeof UnlinkAliasCommand> {\n static override args = {\n aliasName: Args.string({\n description: 'Dataset alias name to unlink',\n required: false,\n }),\n }\n\n static override description = 'Unlink a dataset alias from its dataset within your project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Unlink an alias with interactive selection',\n },\n {\n command: '<%= config.bin %> <%= command.id %> conference',\n description: 'Unlink alias \"conference\" with confirmation prompt',\n },\n {\n command: '<%= config.bin %> <%= command.id %> ~conference',\n description: 'Unlink alias with explicit ~ prefix',\n },\n {\n command: '<%= config.bin %> <%= command.id %> conference --force',\n description: 'Unlink alias \"conference\" without confirmation prompt',\n },\n ]\n\n static override flags = {\n force: Flags.boolean({\n description: 'Skip confirmation prompt and unlink immediately',\n required: false,\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(UnlinkAliasCommand)\n const {force} = flags\n\n const projectId = await this.getProjectId()\n if (!projectId) {\n this.error(NO_PROJECT_ID, {exit: 1})\n }\n\n try {\n const aliasNameInput = args.aliasName || (await promptForDatasetAliasName())\n const {apiName, displayName} = processAliasName(aliasNameInput)\n\n const nameError = validateDatasetAliasName(apiName)\n if (nameError) {\n this.error(nameError, {exit: 1})\n }\n\n const aliases = await listAliases(projectId)\n\n // get the current alias from the remote alias list\n const linkedAlias = aliases.find((elem) => elem.name === apiName)\n if (!linkedAlias) {\n this.error(`Dataset alias \"${displayName}\" does not exist`, {exit: 1})\n }\n\n if (!linkedAlias.datasetName) {\n this.error(`Dataset alias \"${displayName}\" is not linked to a dataset`, {exit: 1})\n }\n\n if (force) {\n this.warn(`'--force' used: skipping confirmation, unlinking alias \"${displayName}\"`)\n } else {\n await this.confirmUnlink(linkedAlias.datasetName)\n }\n\n const result = await unlinkAlias(projectId, apiName)\n this.log(`Dataset alias ${displayName} unlinked from ${result.datasetName} successfully`)\n } catch (error) {\n unlinkAliasDebug('Error unlinking dataset alias', error)\n this.error(\n `Dataset alias unlink failed: ${error instanceof Error ? error.message : String(error)}`,\n {exit: 1},\n )\n }\n }\n\n private async confirmUnlink(datasetName: string): Promise<void> {\n await input({\n message: `Are you ABSOLUTELY sure you want to unlink this alias from the \"${datasetName}\" dataset?\\n Type YES/NO:`,\n validate: (input) => {\n const response = input.toLowerCase().trim()\n return (\n response === 'yes' || 'Type YES to confirm or Ctrl + C to cancel dataset alias unlink.'\n )\n },\n })\n }\n}\n"],"names":["Args","Flags","SanityCommand","subdebug","input","processAliasName","validateDatasetAliasName","promptForDatasetAliasName","listAliases","unlinkAlias","NO_PROJECT_ID","unlinkAliasDebug","UnlinkAliasCommand","args","aliasName","string","description","required","examples","command","flags","force","boolean","run","parse","projectId","getProjectId","error","exit","aliasNameInput","apiName","displayName","nameError","aliases","linkedAlias","find","elem","name","datasetName","warn","confirmUnlink","result","log","Error","message","String","validate","response","toLowerCase","trim"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/commands/dataset/alias/unlink.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {input} from '@sanity/cli-core/ux'\n\nimport {processAliasName} from '../../../actions/dataset/processAliasName.js'\nimport {validateDatasetAliasName} from '../../../actions/dataset/validateDatasetAliasName.js'\nimport {promptForDatasetAliasName} from '../../../prompts/promptForDatasetAliasName.js'\nimport {promptForProject} from '../../../prompts/promptForProject.js'\nimport {listAliases, unlinkAlias} from '../../../services/datasetAliases.js'\nimport {projectIdFlag} from '../../../util/sharedFlags.js'\n\nconst unlinkAliasDebug = subdebug('dataset:alias:unlink')\n\nexport class UnlinkAliasCommand extends SanityCommand<typeof UnlinkAliasCommand> {\n static override args = {\n aliasName: Args.string({\n description: 'Dataset alias name to unlink',\n required: false,\n }),\n }\n\n static override description = 'Unlink a dataset alias from its dataset within your project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Unlink an alias with interactive selection',\n },\n {\n command: '<%= config.bin %> <%= command.id %> conference',\n description: 'Unlink alias \"conference\" with confirmation prompt',\n },\n {\n command: '<%= config.bin %> <%= command.id %> ~conference',\n description: 'Unlink alias with explicit ~ prefix',\n },\n {\n command: '<%= config.bin %> <%= command.id %> conference --force',\n description: 'Unlink alias \"conference\" without confirmation prompt',\n },\n ]\n\n static override flags = {\n ...projectIdFlag,\n force: Flags.boolean({\n description: 'Skip confirmation prompt and unlink immediately',\n required: false,\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(UnlinkAliasCommand)\n const {force} = flags\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [\n {grant: 'read', permission: 'sanity.project.datasets'},\n {grant: 'update', permission: 'sanity.project.datasets'},\n ],\n }),\n })\n\n try {\n const aliasNameInput = args.aliasName || (await promptForDatasetAliasName())\n const {apiName, displayName} = processAliasName(aliasNameInput)\n\n const nameError = validateDatasetAliasName(apiName)\n if (nameError) {\n this.error(nameError, {exit: 1})\n }\n\n const aliases = await listAliases(projectId)\n\n // get the current alias from the remote alias list\n const linkedAlias = aliases.find((elem) => elem.name === apiName)\n if (!linkedAlias) {\n this.error(`Dataset alias \"${displayName}\" does not exist`, {exit: 1})\n }\n\n if (!linkedAlias.datasetName) {\n this.error(`Dataset alias \"${displayName}\" is not linked to a dataset`, {exit: 1})\n }\n\n if (force) {\n this.warn(`'--force' used: skipping confirmation, unlinking alias \"${displayName}\"`)\n } else {\n await this.confirmUnlink(linkedAlias.datasetName)\n }\n\n const result = await unlinkAlias(projectId, apiName)\n this.log(`Dataset alias ${displayName} unlinked from ${result.datasetName} successfully`)\n } catch (error) {\n unlinkAliasDebug('Error unlinking dataset alias', error)\n this.error(\n `Dataset alias unlink failed: ${error instanceof Error ? error.message : String(error)}`,\n {exit: 1},\n )\n }\n }\n\n private async confirmUnlink(datasetName: string): Promise<void> {\n await input({\n message: `Are you ABSOLUTELY sure you want to unlink this alias from the \"${datasetName}\" dataset?\\n Type YES/NO:`,\n validate: (input) => {\n const response = input.toLowerCase().trim()\n return (\n response === 'yes' || 'Type YES to confirm or Ctrl + C to cancel dataset alias unlink.'\n )\n },\n })\n }\n}\n"],"names":["Args","Flags","SanityCommand","subdebug","input","processAliasName","validateDatasetAliasName","promptForDatasetAliasName","promptForProject","listAliases","unlinkAlias","projectIdFlag","unlinkAliasDebug","UnlinkAliasCommand","args","aliasName","string","description","required","examples","command","flags","force","boolean","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","aliasNameInput","apiName","displayName","nameError","error","exit","aliases","linkedAlias","find","elem","name","datasetName","warn","confirmUnlink","result","log","Error","message","String","validate","response","toLowerCase","trim"],"mappings":"AAAA,SAAQA,IAAI,EAAEC,KAAK,QAAO,cAAa;AACvC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACxD,SAAQC,KAAK,QAAO,sBAAqB;AAEzC,SAAQC,gBAAgB,QAAO,+CAA8C;AAC7E,SAAQC,wBAAwB,QAAO,uDAAsD;AAC7F,SAAQC,yBAAyB,QAAO,gDAA+C;AACvF,SAAQC,gBAAgB,QAAO,uCAAsC;AACrE,SAAQC,WAAW,EAAEC,WAAW,QAAO,sCAAqC;AAC5E,SAAQC,aAAa,QAAO,+BAA8B;AAE1D,MAAMC,mBAAmBT,SAAS;AAElC,OAAO,MAAMU,2BAA2BX;IACtC,OAAgBY,OAAO;QACrBC,WAAWf,KAAKgB,MAAM,CAAC;YACrBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,8DAA6D;IAE3F,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;QACtB,GAAGV,aAAa;QAChBW,OAAOrB,MAAMsB,OAAO,CAAC;YACnBN,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,MAAaM,MAAqB;QAChC,MAAM,EAACV,IAAI,EAAEO,KAAK,EAAC,GAAG,MAAM,IAAI,CAACI,KAAK,CAACZ;QACvC,MAAM,EAACS,KAAK,EAAC,GAAGD;QAEhB,MAAMK,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,UAAU,IACRpB,iBAAiB;oBACfqB,qBAAqB;wBACnB;4BAACC,OAAO;4BAAQC,YAAY;wBAAyB;wBACrD;4BAACD,OAAO;4BAAUC,YAAY;wBAAyB;qBACxD;gBACH;QACJ;QAEA,IAAI;YACF,MAAMC,iBAAiBlB,KAAKC,SAAS,IAAK,MAAMR;YAChD,MAAM,EAAC0B,OAAO,EAAEC,WAAW,EAAC,GAAG7B,iBAAiB2B;YAEhD,MAAMG,YAAY7B,yBAAyB2B;YAC3C,IAAIE,WAAW;gBACb,IAAI,CAACC,KAAK,CAACD,WAAW;oBAACE,MAAM;gBAAC;YAChC;YAEA,MAAMC,UAAU,MAAM7B,YAAYiB;YAElC,mDAAmD;YACnD,MAAMa,cAAcD,QAAQE,IAAI,CAAC,CAACC,OAASA,KAAKC,IAAI,KAAKT;YACzD,IAAI,CAACM,aAAa;gBAChB,IAAI,CAACH,KAAK,CAAC,CAAC,eAAe,EAAEF,YAAY,gBAAgB,CAAC,EAAE;oBAACG,MAAM;gBAAC;YACtE;YAEA,IAAI,CAACE,YAAYI,WAAW,EAAE;gBAC5B,IAAI,CAACP,KAAK,CAAC,CAAC,eAAe,EAAEF,YAAY,4BAA4B,CAAC,EAAE;oBAACG,MAAM;gBAAC;YAClF;YAEA,IAAIf,OAAO;gBACT,IAAI,CAACsB,IAAI,CAAC,CAAC,wDAAwD,EAAEV,YAAY,CAAC,CAAC;YACrF,OAAO;gBACL,MAAM,IAAI,CAACW,aAAa,CAACN,YAAYI,WAAW;YAClD;YAEA,MAAMG,SAAS,MAAMpC,YAAYgB,WAAWO;YAC5C,IAAI,CAACc,GAAG,CAAC,CAAC,cAAc,EAAEb,YAAY,eAAe,EAAEY,OAAOH,WAAW,CAAC,aAAa,CAAC;QAC1F,EAAE,OAAOP,OAAO;YACdxB,iBAAiB,iCAAiCwB;YAClD,IAAI,CAACA,KAAK,CACR,CAAC,6BAA6B,EAAEA,iBAAiBY,QAAQZ,MAAMa,OAAO,GAAGC,OAAOd,QAAQ,EACxF;gBAACC,MAAM;YAAC;QAEZ;IACF;IAEA,MAAcQ,cAAcF,WAAmB,EAAiB;QAC9D,MAAMvC,MAAM;YACV6C,SAAS,CAAC,gEAAgE,EAAEN,YAAY,0BAA0B,CAAC;YACnHQ,UAAU,CAAC/C;gBACT,MAAMgD,WAAWhD,MAAMiD,WAAW,GAAGC,IAAI;gBACzC,OACEF,aAAa,SAAS;YAE1B;QACF;IACF;AACF"}
@@ -4,12 +4,15 @@ import { exit } from '@oclif/core/errors';
4
4
  import { SanityCommand, subdebug } from '@sanity/cli-core';
5
5
  import { spinner } from '@sanity/cli-core/ux';
6
6
  import { Table } from 'console-table-printer';
7
- import { formatDistance, formatDistanceToNow, parseISO } from 'date-fns';
7
+ import { formatDistance } from 'date-fns/formatDistance';
8
+ import { formatDistanceToNow } from 'date-fns/formatDistanceToNow';
9
+ import { parseISO } from 'date-fns/parseISO';
8
10
  import { validateDatasetName } from '../../actions/dataset/validateDatasetName.js';
9
11
  import { promptForDataset } from '../../prompts/promptForDataset.js';
10
12
  import { promptForDatasetName } from '../../prompts/promptForDatasetName.js';
13
+ import { promptForProject } from '../../prompts/promptForProject.js';
11
14
  import { copyDataset, followCopyJobProgress, listDatasetCopyJobs, listDatasets } from '../../services/datasets.js';
12
- import { NO_PROJECT_ID } from '../../util/errorMessages.js';
15
+ import { projectIdFlag } from '../../util/sharedFlags.js';
13
16
  const copyDatasetDebug = subdebug('dataset:copy');
14
17
  export class CopyDatasetCommand extends SanityCommand {
15
18
  static args = {
@@ -58,6 +61,7 @@ export class CopyDatasetCommand extends SanityCommand {
58
61
  }
59
62
  ];
60
63
  static flags = {
64
+ ...projectIdFlag,
61
65
  attach: Flags.string({
62
66
  description: 'Attach to the running copy process to show progress',
63
67
  exclusive: [
@@ -108,24 +112,30 @@ export class CopyDatasetCommand extends SanityCommand {
108
112
  required: false
109
113
  })
110
114
  };
111
- projectId;
112
115
  async run() {
113
116
  const { args, flags } = await this.parse(CopyDatasetCommand);
114
- const projectId = await this.getProjectId();
115
- if (!projectId) {
116
- this.error(NO_PROJECT_ID, {
117
- exit: 1
118
- });
119
- }
120
- this.projectId = projectId;
117
+ const projectId = await this.getProjectId({
118
+ fallback: ()=>promptForProject({
119
+ requiredPermissions: [
120
+ {
121
+ grant: 'read',
122
+ permission: 'sanity.project.datasets'
123
+ },
124
+ {
125
+ grant: 'create',
126
+ permission: 'sanity.project.datasets'
127
+ }
128
+ ]
129
+ })
130
+ });
121
131
  // Route to appropriate mode
122
132
  if (flags.list) {
123
- return this.handleListMode(flags);
133
+ return this.handleListMode(projectId, flags);
124
134
  }
125
135
  if (flags.attach) {
126
- return this.handleAttachMode(flags.attach);
136
+ return this.handleAttachMode(projectId, flags.attach);
127
137
  }
128
- return this.handleCopyMode(args, flags);
138
+ return this.handleCopyMode(projectId, args, flags);
129
139
  }
130
140
  displayCopyJobsTable(jobs) {
131
141
  const table = new Table({
@@ -214,15 +224,15 @@ export class CopyDatasetCommand extends SanityCommand {
214
224
  }
215
225
  table.printTable();
216
226
  }
217
- async handleAttachMode(jobId) {
227
+ async handleAttachMode(projectId, jobId) {
218
228
  copyDatasetDebug('Attaching to copy job %s', jobId);
219
- if (!jobId || typeof jobId !== 'string' || jobId.trim() === '') {
229
+ if (jobId.trim() === '') {
220
230
  this.error('Please supply a valid jobId', {
221
231
  exit: 1
222
232
  });
223
233
  }
224
234
  try {
225
- await this.subscribeToProgress(jobId);
235
+ await this.subscribeToProgress(projectId, jobId);
226
236
  this.log(`Job ${styleText('green', jobId)} completed`);
227
237
  } catch (error) {
228
238
  const message = error instanceof Error ? error.message : String(error);
@@ -232,7 +242,7 @@ export class CopyDatasetCommand extends SanityCommand {
232
242
  });
233
243
  }
234
244
  }
235
- async handleCopyMode(args, flags) {
245
+ async handleCopyMode(projectId, args, flags) {
236
246
  copyDatasetDebug('Starting copy mode');
237
247
  const skipHistory = Boolean(flags['skip-history']);
238
248
  // Get and validate source dataset
@@ -247,7 +257,7 @@ export class CopyDatasetCommand extends SanityCommand {
247
257
  }
248
258
  let datasetsResponse;
249
259
  try {
250
- datasetsResponse = await listDatasets(this.projectId);
260
+ datasetsResponse = await listDatasets(projectId);
251
261
  } catch (error) {
252
262
  const message = error instanceof Error ? error.message : String(error);
253
263
  copyDatasetDebug('Failed to fetch datasets: %s', message, error);
@@ -293,7 +303,7 @@ export class CopyDatasetCommand extends SanityCommand {
293
303
  this.log(`Note: You can run this command with flag '--skip-history'. The flag will reduce copy time in larger datasets.`);
294
304
  }
295
305
  const response = await copyDataset({
296
- projectId: this.projectId,
306
+ projectId,
297
307
  skipHistory,
298
308
  sourceDataset,
299
309
  targetDataset
@@ -302,7 +312,7 @@ export class CopyDatasetCommand extends SanityCommand {
302
312
  if (flags.detach) {
303
313
  return;
304
314
  }
305
- await this.subscribeToProgress(response.jobId);
315
+ await this.subscribeToProgress(projectId, response.jobId);
306
316
  this.log(`Job ${styleText('green', response.jobId)} completed`);
307
317
  } catch (error) {
308
318
  const message = error instanceof Error ? error.message : String(error);
@@ -312,13 +322,13 @@ export class CopyDatasetCommand extends SanityCommand {
312
322
  });
313
323
  }
314
324
  }
315
- async handleListMode(flags) {
325
+ async handleListMode(projectId, flags) {
316
326
  copyDatasetDebug('Listing dataset copy jobs');
317
327
  try {
318
328
  const jobs = await listDatasetCopyJobs({
319
329
  limit: flags.limit,
320
330
  offset: flags.offset,
321
- projectId: this.projectId
331
+ projectId
322
332
  });
323
333
  if (jobs.length === 0) {
324
334
  this.log("This project doesn't have any dataset copy jobs");
@@ -333,19 +343,26 @@ export class CopyDatasetCommand extends SanityCommand {
333
343
  });
334
344
  }
335
345
  }
336
- async subscribeToProgress(jobId) {
346
+ async subscribeToProgress(projectId, jobId) {
337
347
  let currentProgress = 0;
338
348
  const spin = spinner('').start();
339
349
  return new Promise((resolve, reject)=>{
350
+ const sigintHandler = ()=>{
351
+ subscription.unsubscribe();
352
+ spin.fail('Copy interrupted.');
353
+ exit(130);
354
+ };
340
355
  const subscription = followCopyJobProgress({
341
356
  jobId,
342
- projectId: this.projectId
357
+ projectId
343
358
  }).subscribe({
344
359
  complete: ()=>{
360
+ process.off('SIGINT', sigintHandler);
345
361
  spin.succeed('Copy finished.');
346
362
  resolve();
347
363
  },
348
364
  error: (err)=>{
365
+ process.off('SIGINT', sigintHandler);
349
366
  spin.fail('Copy failed.');
350
367
  reject(err);
351
368
  },
@@ -356,12 +373,7 @@ export class CopyDatasetCommand extends SanityCommand {
356
373
  spin.text = `Copy in progress: ${currentProgress}%`;
357
374
  }
358
375
  });
359
- // Cleanup on process termination - use 'once' to prevent memory leaks
360
- process.once('SIGINT', ()=>{
361
- subscription.unsubscribe();
362
- spin.fail('Copy interrupted.');
363
- exit(130);
364
- });
376
+ process.once('SIGINT', sigintHandler);
365
377
  });
366
378
  }
367
379
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/dataset/copy.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exit} from '@oclif/core/errors'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {Table} from 'console-table-printer'\nimport {formatDistance, formatDistanceToNow, parseISO} from 'date-fns'\n\nimport {validateDatasetName} from '../../actions/dataset/validateDatasetName.js'\nimport {promptForDataset} from '../../prompts/promptForDataset.js'\nimport {promptForDatasetName} from '../../prompts/promptForDatasetName.js'\nimport {\n copyDataset,\n type CopyJobProgressEvent,\n type DatasetCopyJob,\n followCopyJobProgress,\n listDatasetCopyJobs,\n listDatasets,\n} from '../../services/datasets.js'\nimport {NO_PROJECT_ID} from '../../util/errorMessages.js'\n\nconst copyDatasetDebug = subdebug('dataset:copy')\n\nexport class CopyDatasetCommand extends SanityCommand<typeof CopyDatasetCommand> {\n static override args = {\n source: Args.string({\n description: 'Name of the dataset to copy from',\n required: false,\n }),\n target: Args.string({\n description: 'Name of the dataset to copy to',\n required: false,\n }),\n }\n\n static override description =\n 'Manages dataset copying, including starting a new copy job, listing copy jobs and following the progress of a running copy job'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively copy a dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> source-dataset',\n description: 'Copy from source-dataset (prompts for target)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> source-dataset target-dataset',\n description: 'Copy from source-dataset to target-dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --skip-history source target',\n description: 'Copy without preserving document history (faster for large datasets)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --detach source target',\n description: 'Start copy job without waiting for completion',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --attach <job-id>',\n description: 'Attach to a running copy job to follow progress',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --list',\n description: 'List all dataset copy jobs',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --list --offset 2 --limit 10',\n description: 'List copy jobs with pagination',\n },\n ]\n\n static override flags = {\n attach: Flags.string({\n description: 'Attach to the running copy process to show progress',\n exclusive: ['list', 'detach', 'skip-history'],\n required: false,\n }),\n detach: Flags.boolean({\n description: 'Start the copy without waiting for it to finish',\n exclusive: ['list', 'attach'],\n required: false,\n }),\n limit: Flags.integer({\n dependsOn: ['list'],\n description: 'Maximum number of jobs returned (default 10, max 1000)',\n max: 1000,\n required: false,\n }),\n list: Flags.boolean({\n description: 'Lists all dataset copy jobs',\n exclusive: ['attach', 'detach', 'skip-history'],\n required: false,\n }),\n offset: Flags.integer({\n dependsOn: ['list'],\n description: 'Start position in the list of jobs (default 0)',\n required: false,\n }),\n 'skip-history': Flags.boolean({\n description: \"Don't preserve document history on copy\",\n exclusive: ['list', 'attach'],\n required: false,\n }),\n }\n\n private projectId!: string\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(CopyDatasetCommand)\n\n const projectId = await this.getProjectId()\n if (!projectId) {\n this.error(NO_PROJECT_ID, {exit: 1})\n }\n\n this.projectId = projectId\n\n // Route to appropriate mode\n if (flags.list) {\n return this.handleListMode(flags)\n }\n\n if (flags.attach) {\n return this.handleAttachMode(flags.attach)\n }\n\n return this.handleCopyMode(args, flags)\n }\n\n private displayCopyJobsTable(jobs: DatasetCopyJob[]): void {\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'id', title: 'Job ID'},\n {alignment: 'left', name: 'sourceDataset', title: 'Source Dataset'},\n {alignment: 'left', name: 'targetDataset', title: 'Target Dataset'},\n {alignment: 'left', name: 'state', title: 'State'},\n {alignment: 'left', name: 'withHistory', title: 'With history'},\n {alignment: 'left', name: 'timeStarted', title: 'Time started'},\n {alignment: 'left', name: 'timeTaken', title: 'Time taken'},\n ],\n title: 'Dataset copy jobs for this project in descending order',\n })\n\n for (const job of jobs) {\n const {createdAt, id, sourceDataset, state, targetDataset, updatedAt, withHistory} = job\n\n let timeStarted = ''\n if (createdAt !== '') {\n timeStarted = formatDistanceToNow(parseISO(createdAt))\n }\n\n let timeTaken = ''\n if (updatedAt !== '') {\n timeTaken = formatDistance(parseISO(updatedAt), parseISO(createdAt))\n }\n\n let color: '' | 'green' | 'red' | 'yellow' = ''\n switch (state) {\n case 'completed': {\n color = 'green'\n break\n }\n case 'failed': {\n color = 'red'\n break\n }\n case 'pending': {\n color = 'yellow'\n break\n }\n default: {\n color = ''\n }\n }\n\n table.addRow(\n {\n id,\n sourceDataset,\n state,\n targetDataset,\n timeStarted: `${timeStarted} ago`,\n timeTaken,\n withHistory,\n },\n {color},\n )\n }\n\n table.printTable()\n }\n\n private async handleAttachMode(jobId: string): Promise<void> {\n copyDatasetDebug('Attaching to copy job %s', jobId)\n\n if (!jobId || typeof jobId !== 'string' || jobId.trim() === '') {\n this.error('Please supply a valid jobId', {exit: 1})\n }\n\n try {\n await this.subscribeToProgress(jobId)\n this.log(`Job ${styleText('green', jobId)} completed`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to attach to copy job: %s', message, error)\n this.error(`Failed to attach to copy job: ${message}`, {exit: 1})\n }\n }\n\n private async handleCopyMode(\n args: {source?: string; target?: string},\n flags: {detach?: boolean; 'skip-history'?: boolean},\n ): Promise<void> {\n copyDatasetDebug('Starting copy mode')\n\n const skipHistory = Boolean(flags['skip-history'])\n\n // Get and validate source dataset\n let sourceDataset = args.source\n if (sourceDataset) {\n const nameError = validateDatasetName(sourceDataset)\n if (nameError) {\n this.error(nameError, {exit: 1})\n }\n }\n\n let datasetsResponse\n try {\n datasetsResponse = await listDatasets(this.projectId)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to fetch datasets: %s', message, error)\n this.error(`Failed to fetch datasets: ${message}`, {exit: 1})\n }\n\n const datasetNames = new Set(datasetsResponse.map((ds) => ds.name))\n\n // Prompt for source if not provided\n if (!sourceDataset) {\n sourceDataset = await promptForDataset({\n datasets: datasetsResponse,\n })\n }\n\n if (!datasetNames.has(sourceDataset)) {\n this.error(`Source dataset \"${sourceDataset}\" doesn't exist`, {exit: 1})\n }\n\n // Get and validate target dataset\n let targetDataset = args.target\n if (targetDataset) {\n const nameError = validateDatasetName(targetDataset)\n if (nameError) {\n this.error(nameError, {exit: 1})\n }\n } else {\n targetDataset = await promptForDatasetName({\n message: 'Target dataset name:',\n })\n }\n\n if (datasetNames.has(targetDataset)) {\n this.error(`Target dataset \"${targetDataset}\" already exists`, {exit: 1})\n }\n\n // Start the copy job\n try {\n this.log(\n `Copying dataset ${styleText('green', sourceDataset)} to ${styleText('green', targetDataset)}...`,\n )\n\n if (!skipHistory) {\n this.log(\n `Note: You can run this command with flag '--skip-history'. The flag will reduce copy time in larger datasets.`,\n )\n }\n\n const response = await copyDataset({\n projectId: this.projectId,\n skipHistory,\n sourceDataset,\n targetDataset,\n })\n\n this.log(`Job ${styleText('green', response.jobId)} started`)\n\n if (flags.detach) {\n return\n }\n\n await this.subscribeToProgress(response.jobId)\n this.log(`Job ${styleText('green', response.jobId)} completed`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Dataset copying failed: %s', message, error)\n this.error(`Dataset copying failed: ${message}`, {exit: 1})\n }\n }\n\n private async handleListMode(flags: {limit?: number; offset?: number}): Promise<void> {\n copyDatasetDebug('Listing dataset copy jobs')\n\n try {\n const jobs = await listDatasetCopyJobs({\n limit: flags.limit,\n offset: flags.offset,\n projectId: this.projectId,\n })\n\n if (jobs.length === 0) {\n this.log(\"This project doesn't have any dataset copy jobs\")\n return\n }\n\n this.displayCopyJobsTable(jobs)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to list dataset copy jobs: %s', message, error)\n this.error(`Failed to list dataset copy jobs: ${message}`, {exit: 1})\n }\n }\n\n private async subscribeToProgress(jobId: string): Promise<void> {\n let currentProgress = 0\n const spin = spinner('').start()\n\n return new Promise<void>((resolve, reject) => {\n const subscription = followCopyJobProgress({jobId, projectId: this.projectId}).subscribe({\n complete: () => {\n spin.succeed('Copy finished.')\n resolve()\n },\n error: (err) => {\n spin.fail('Copy failed.')\n reject(err)\n },\n next: (event: CopyJobProgressEvent) => {\n if (typeof event.progress === 'number') {\n currentProgress = event.progress\n }\n spin.text = `Copy in progress: ${currentProgress}%`\n },\n })\n\n // Cleanup on process termination - use 'once' to prevent memory leaks\n process.once('SIGINT', () => {\n subscription.unsubscribe()\n spin.fail('Copy interrupted.')\n exit(130)\n })\n })\n }\n}\n"],"names":["styleText","Args","Flags","exit","SanityCommand","subdebug","spinner","Table","formatDistance","formatDistanceToNow","parseISO","validateDatasetName","promptForDataset","promptForDatasetName","copyDataset","followCopyJobProgress","listDatasetCopyJobs","listDatasets","NO_PROJECT_ID","copyDatasetDebug","CopyDatasetCommand","args","source","string","description","required","target","examples","command","flags","attach","exclusive","detach","boolean","limit","integer","dependsOn","max","list","offset","projectId","run","parse","getProjectId","error","handleListMode","handleAttachMode","handleCopyMode","displayCopyJobsTable","jobs","table","columns","alignment","name","title","job","createdAt","id","sourceDataset","state","targetDataset","updatedAt","withHistory","timeStarted","timeTaken","color","addRow","printTable","jobId","trim","subscribeToProgress","log","message","Error","String","skipHistory","Boolean","nameError","datasetsResponse","datasetNames","Set","map","ds","datasets","has","response","length","currentProgress","spin","start","Promise","resolve","reject","subscription","subscribe","complete","succeed","err","fail","next","event","progress","text","process","once","unsubscribe"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/dataset/copy.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exit} from '@oclif/core/errors'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {Table} from 'console-table-printer'\nimport {formatDistance} from 'date-fns/formatDistance'\nimport {formatDistanceToNow} from 'date-fns/formatDistanceToNow'\nimport {parseISO} from 'date-fns/parseISO'\n\nimport {validateDatasetName} from '../../actions/dataset/validateDatasetName.js'\nimport {promptForDataset} from '../../prompts/promptForDataset.js'\nimport {promptForDatasetName} from '../../prompts/promptForDatasetName.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {\n copyDataset,\n type CopyJobProgressEvent,\n type DatasetCopyJob,\n followCopyJobProgress,\n listDatasetCopyJobs,\n listDatasets,\n} from '../../services/datasets.js'\nimport {projectIdFlag} from '../../util/sharedFlags.js'\n\nconst copyDatasetDebug = subdebug('dataset:copy')\n\nexport class CopyDatasetCommand extends SanityCommand<typeof CopyDatasetCommand> {\n static override args = {\n source: Args.string({\n description: 'Name of the dataset to copy from',\n required: false,\n }),\n target: Args.string({\n description: 'Name of the dataset to copy to',\n required: false,\n }),\n }\n\n static override description =\n 'Manages dataset copying, including starting a new copy job, listing copy jobs and following the progress of a running copy job'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively copy a dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> source-dataset',\n description: 'Copy from source-dataset (prompts for target)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> source-dataset target-dataset',\n description: 'Copy from source-dataset to target-dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --skip-history source target',\n description: 'Copy without preserving document history (faster for large datasets)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --detach source target',\n description: 'Start copy job without waiting for completion',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --attach <job-id>',\n description: 'Attach to a running copy job to follow progress',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --list',\n description: 'List all dataset copy jobs',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --list --offset 2 --limit 10',\n description: 'List copy jobs with pagination',\n },\n ]\n\n static override flags = {\n ...projectIdFlag,\n attach: Flags.string({\n description: 'Attach to the running copy process to show progress',\n exclusive: ['list', 'detach', 'skip-history'],\n required: false,\n }),\n detach: Flags.boolean({\n description: 'Start the copy without waiting for it to finish',\n exclusive: ['list', 'attach'],\n required: false,\n }),\n limit: Flags.integer({\n dependsOn: ['list'],\n description: 'Maximum number of jobs returned (default 10, max 1000)',\n max: 1000,\n required: false,\n }),\n list: Flags.boolean({\n description: 'Lists all dataset copy jobs',\n exclusive: ['attach', 'detach', 'skip-history'],\n required: false,\n }),\n offset: Flags.integer({\n dependsOn: ['list'],\n description: 'Start position in the list of jobs (default 0)',\n required: false,\n }),\n 'skip-history': Flags.boolean({\n description: \"Don't preserve document history on copy\",\n exclusive: ['list', 'attach'],\n required: false,\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(CopyDatasetCommand)\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [\n {grant: 'read', permission: 'sanity.project.datasets'},\n {grant: 'create', permission: 'sanity.project.datasets'},\n ],\n }),\n })\n\n // Route to appropriate mode\n if (flags.list) {\n return this.handleListMode(projectId, flags)\n }\n\n if (flags.attach) {\n return this.handleAttachMode(projectId, flags.attach)\n }\n\n return this.handleCopyMode(projectId, args, flags)\n }\n\n private displayCopyJobsTable(jobs: DatasetCopyJob[]): void {\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'id', title: 'Job ID'},\n {alignment: 'left', name: 'sourceDataset', title: 'Source Dataset'},\n {alignment: 'left', name: 'targetDataset', title: 'Target Dataset'},\n {alignment: 'left', name: 'state', title: 'State'},\n {alignment: 'left', name: 'withHistory', title: 'With history'},\n {alignment: 'left', name: 'timeStarted', title: 'Time started'},\n {alignment: 'left', name: 'timeTaken', title: 'Time taken'},\n ],\n title: 'Dataset copy jobs for this project in descending order',\n })\n\n for (const job of jobs) {\n const {createdAt, id, sourceDataset, state, targetDataset, updatedAt, withHistory} = job\n\n let timeStarted = ''\n if (createdAt !== '') {\n timeStarted = formatDistanceToNow(parseISO(createdAt))\n }\n\n let timeTaken = ''\n if (updatedAt !== '') {\n timeTaken = formatDistance(parseISO(updatedAt), parseISO(createdAt))\n }\n\n let color: '' | 'green' | 'red' | 'yellow' = ''\n switch (state) {\n case 'completed': {\n color = 'green'\n break\n }\n case 'failed': {\n color = 'red'\n break\n }\n case 'pending': {\n color = 'yellow'\n break\n }\n default: {\n color = ''\n }\n }\n\n table.addRow(\n {\n id,\n sourceDataset,\n state,\n targetDataset,\n timeStarted: `${timeStarted} ago`,\n timeTaken,\n withHistory,\n },\n {color},\n )\n }\n\n table.printTable()\n }\n\n private async handleAttachMode(projectId: string, jobId: string): Promise<void> {\n copyDatasetDebug('Attaching to copy job %s', jobId)\n\n if (jobId.trim() === '') {\n this.error('Please supply a valid jobId', {exit: 1})\n }\n\n try {\n await this.subscribeToProgress(projectId, jobId)\n this.log(`Job ${styleText('green', jobId)} completed`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to attach to copy job: %s', message, error)\n this.error(`Failed to attach to copy job: ${message}`, {exit: 1})\n }\n }\n\n private async handleCopyMode(\n projectId: string,\n args: {source?: string; target?: string},\n flags: {detach?: boolean; 'skip-history'?: boolean},\n ): Promise<void> {\n copyDatasetDebug('Starting copy mode')\n\n const skipHistory = Boolean(flags['skip-history'])\n\n // Get and validate source dataset\n let sourceDataset = args.source\n if (sourceDataset) {\n const nameError = validateDatasetName(sourceDataset)\n if (nameError) {\n this.error(nameError, {exit: 1})\n }\n }\n\n let datasetsResponse\n try {\n datasetsResponse = await listDatasets(projectId)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to fetch datasets: %s', message, error)\n this.error(`Failed to fetch datasets: ${message}`, {exit: 1})\n }\n\n const datasetNames = new Set(datasetsResponse.map((ds) => ds.name))\n\n // Prompt for source if not provided\n if (!sourceDataset) {\n sourceDataset = await promptForDataset({\n datasets: datasetsResponse,\n })\n }\n\n if (!datasetNames.has(sourceDataset)) {\n this.error(`Source dataset \"${sourceDataset}\" doesn't exist`, {exit: 1})\n }\n\n // Get and validate target dataset\n let targetDataset = args.target\n if (targetDataset) {\n const nameError = validateDatasetName(targetDataset)\n if (nameError) {\n this.error(nameError, {exit: 1})\n }\n } else {\n targetDataset = await promptForDatasetName({\n message: 'Target dataset name:',\n })\n }\n\n if (datasetNames.has(targetDataset)) {\n this.error(`Target dataset \"${targetDataset}\" already exists`, {exit: 1})\n }\n\n // Start the copy job\n try {\n this.log(\n `Copying dataset ${styleText('green', sourceDataset)} to ${styleText('green', targetDataset)}...`,\n )\n\n if (!skipHistory) {\n this.log(\n `Note: You can run this command with flag '--skip-history'. The flag will reduce copy time in larger datasets.`,\n )\n }\n\n const response = await copyDataset({\n projectId,\n skipHistory,\n sourceDataset,\n targetDataset,\n })\n\n this.log(`Job ${styleText('green', response.jobId)} started`)\n\n if (flags.detach) {\n return\n }\n\n await this.subscribeToProgress(projectId, response.jobId)\n this.log(`Job ${styleText('green', response.jobId)} completed`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Dataset copying failed: %s', message, error)\n this.error(`Dataset copying failed: ${message}`, {exit: 1})\n }\n }\n\n private async handleListMode(projectId: string, flags: {limit?: number; offset?: number}): Promise<void> {\n copyDatasetDebug('Listing dataset copy jobs')\n\n try {\n const jobs = await listDatasetCopyJobs({\n limit: flags.limit,\n offset: flags.offset,\n projectId,\n })\n\n if (jobs.length === 0) {\n this.log(\"This project doesn't have any dataset copy jobs\")\n return\n }\n\n this.displayCopyJobsTable(jobs)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to list dataset copy jobs: %s', message, error)\n this.error(`Failed to list dataset copy jobs: ${message}`, {exit: 1})\n }\n }\n\n private async subscribeToProgress(projectId: string, jobId: string): Promise<void> {\n let currentProgress = 0\n const spin = spinner('').start()\n\n return new Promise<void>((resolve, reject) => {\n const sigintHandler = () => {\n subscription.unsubscribe()\n spin.fail('Copy interrupted.')\n exit(130)\n }\n\n const subscription = followCopyJobProgress({jobId, projectId}).subscribe({\n complete: () => {\n process.off('SIGINT', sigintHandler)\n spin.succeed('Copy finished.')\n resolve()\n },\n error: (err) => {\n process.off('SIGINT', sigintHandler)\n spin.fail('Copy failed.')\n reject(err)\n },\n next: (event: CopyJobProgressEvent) => {\n if (typeof event.progress === 'number') {\n currentProgress = event.progress\n }\n spin.text = `Copy in progress: ${currentProgress}%`\n },\n })\n\n process.once('SIGINT', sigintHandler)\n })\n }\n}\n"],"names":["styleText","Args","Flags","exit","SanityCommand","subdebug","spinner","Table","formatDistance","formatDistanceToNow","parseISO","validateDatasetName","promptForDataset","promptForDatasetName","promptForProject","copyDataset","followCopyJobProgress","listDatasetCopyJobs","listDatasets","projectIdFlag","copyDatasetDebug","CopyDatasetCommand","args","source","string","description","required","target","examples","command","flags","attach","exclusive","detach","boolean","limit","integer","dependsOn","max","list","offset","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","handleListMode","handleAttachMode","handleCopyMode","displayCopyJobsTable","jobs","table","columns","alignment","name","title","job","createdAt","id","sourceDataset","state","targetDataset","updatedAt","withHistory","timeStarted","timeTaken","color","addRow","printTable","jobId","trim","error","subscribeToProgress","log","message","Error","String","skipHistory","Boolean","nameError","datasetsResponse","datasetNames","Set","map","ds","datasets","has","response","length","currentProgress","spin","start","Promise","resolve","reject","sigintHandler","subscription","unsubscribe","fail","subscribe","complete","process","off","succeed","err","next","event","progress","text","once"],"mappings":"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"}
@@ -3,9 +3,10 @@ import { SanityCommand, subdebug } from '@sanity/cli-core';
3
3
  import { createDataset } from '../../actions/dataset/create.js';
4
4
  import { validateDatasetName } from '../../actions/dataset/validateDatasetName.js';
5
5
  import { promptForDatasetName } from '../../prompts/promptForDatasetName.js';
6
+ import { promptForProject } from '../../prompts/promptForProject.js';
6
7
  import { listDatasets } from '../../services/datasets.js';
7
8
  import { getProjectFeatures } from '../../services/getProjectFeatures.js';
8
- import { NO_PROJECT_ID } from '../../util/errorMessages.js';
9
+ import { projectIdFlag } from '../../util/sharedFlags.js';
9
10
  const createDatasetDebug = subdebug('dataset:create');
10
11
  const ALLOWED_ACL_MODES = [
11
12
  'custom',
@@ -35,6 +36,17 @@ export class CreateDatasetCommand extends SanityCommand {
35
36
  }
36
37
  ];
37
38
  static flags = {
39
+ ...projectIdFlag,
40
+ embeddings: Flags.boolean({
41
+ default: false,
42
+ description: 'Enable embeddings for this dataset'
43
+ }),
44
+ 'embeddings-projection': Flags.string({
45
+ dependsOn: [
46
+ 'embeddings'
47
+ ],
48
+ description: 'GROQ projection for embeddings indexing (e.g. "{ title, body }")'
49
+ }),
38
50
  visibility: Flags.string({
39
51
  description: 'Set visibility for this dataset (custom/private/public)',
40
52
  options: ALLOWED_ACL_MODES,
@@ -45,12 +57,20 @@ export class CreateDatasetCommand extends SanityCommand {
45
57
  const { args, flags } = await this.parse(CreateDatasetCommand);
46
58
  const { visibility } = flags;
47
59
  // Ensure we have project context
48
- const projectId = await this.getProjectId();
49
- if (!projectId) {
50
- this.error(NO_PROJECT_ID, {
51
- exit: 1
52
- });
53
- }
60
+ const projectId = await this.getProjectId({
61
+ fallback: ()=>promptForProject({
62
+ requiredPermissions: [
63
+ {
64
+ grant: 'read',
65
+ permission: 'sanity.project.datasets'
66
+ },
67
+ {
68
+ grant: 'create',
69
+ permission: 'sanity.project.datasets'
70
+ }
71
+ ]
72
+ })
73
+ });
54
74
  // Get dataset name from args or prompt
55
75
  let { name: datasetName } = args;
56
76
  if (datasetName) {
@@ -89,6 +109,8 @@ export class CreateDatasetCommand extends SanityCommand {
89
109
  try {
90
110
  await createDataset({
91
111
  datasetName,
112
+ embeddings: flags.embeddings,
113
+ embeddingsProjection: flags['embeddings-projection'],
92
114
  output: this.output,
93
115
  projectFeatures,
94
116
  projectId,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/dataset/create.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {createDataset} from '../../actions/dataset/create.js'\nimport {validateDatasetName} from '../../actions/dataset/validateDatasetName.js'\nimport {promptForDatasetName} from '../../prompts/promptForDatasetName.js'\nimport {listDatasets} from '../../services/datasets.js'\nimport {getProjectFeatures} from '../../services/getProjectFeatures.js'\nimport {NO_PROJECT_ID} from '../../util/errorMessages.js'\n\nconst createDatasetDebug = subdebug('dataset:create')\n\nconst ALLOWED_ACL_MODES = ['custom', 'private', 'public']\n\nexport class CreateDatasetCommand extends SanityCommand<typeof CreateDatasetCommand> {\n static override args = {\n name: Args.string({\n description: 'Name of the dataset to create',\n required: false,\n }),\n }\n\n static override description = 'Create a new dataset within your project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively create a dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset',\n description: 'Create a dataset named \"my-dataset\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset --visibility private',\n description: 'Create a private dataset named \"my-dataset\"',\n },\n ]\n\n static override flags = {\n visibility: Flags.string({\n description: 'Set visibility for this dataset (custom/private/public)',\n options: ALLOWED_ACL_MODES,\n required: false,\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(CreateDatasetCommand)\n const {visibility} = flags\n\n // Ensure we have project context\n const projectId = await this.getProjectId()\n if (!projectId) {\n this.error(NO_PROJECT_ID, {exit: 1})\n }\n\n // Get dataset name from args or prompt\n let {name: datasetName} = args\n if (datasetName) {\n const nameError = validateDatasetName(datasetName)\n if (nameError) {\n this.error(nameError, {exit: 1})\n }\n } else {\n datasetName = await promptForDatasetName()\n }\n\n let datasets: string[]\n let projectFeatures: string[]\n\n try {\n const [datasetsResponse, featuresResponse] = await Promise.all([\n listDatasets(projectId),\n getProjectFeatures(projectId),\n ])\n datasets = datasetsResponse.map((ds) => ds.name)\n projectFeatures = featuresResponse\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n createDatasetDebug(`Failed to fetch project data: ${message}`, error)\n this.error(`Failed to fetch project data: ${message}`, {exit: 1})\n }\n\n if (datasets.includes(datasetName)) {\n this.error(`Dataset \"${datasetName}\" already exists`, {exit: 1})\n }\n\n const canCreatePrivate = projectFeatures.includes('privateDataset')\n createDatasetDebug('%s create private datasets', canCreatePrivate ? 'Can' : 'Cannot')\n\n try {\n await createDataset({\n datasetName,\n output: this.output,\n projectFeatures,\n projectId,\n visibility,\n })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.error(`Failed to create dataset: ${message}`, {exit: 1})\n }\n }\n}\n"],"names":["Args","Flags","SanityCommand","subdebug","createDataset","validateDatasetName","promptForDatasetName","listDatasets","getProjectFeatures","NO_PROJECT_ID","createDatasetDebug","ALLOWED_ACL_MODES","CreateDatasetCommand","args","name","string","description","required","examples","command","flags","visibility","options","run","parse","projectId","getProjectId","error","exit","datasetName","nameError","datasets","projectFeatures","datasetsResponse","featuresResponse","Promise","all","map","ds","message","Error","String","includes","canCreatePrivate","output"],"mappings":"AAAA,SAAQA,IAAI,EAAEC,KAAK,QAAO,cAAa;AACvC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAExD,SAAQC,aAAa,QAAO,kCAAiC;AAC7D,SAAQC,mBAAmB,QAAO,+CAA8C;AAChF,SAAQC,oBAAoB,QAAO,wCAAuC;AAC1E,SAAQC,YAAY,QAAO,6BAA4B;AACvD,SAAQC,kBAAkB,QAAO,uCAAsC;AACvE,SAAQC,aAAa,QAAO,8BAA6B;AAEzD,MAAMC,qBAAqBP,SAAS;AAEpC,MAAMQ,oBAAoB;IAAC;IAAU;IAAW;CAAS;AAEzD,OAAO,MAAMC,6BAA6BV;IACxC,OAAgBW,OAAO;QACrBC,MAAMd,KAAKe,MAAM,CAAC;YAChBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,2CAA0C;IAExE,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtBC,YAAYpB,MAAMc,MAAM,CAAC;YACvBC,aAAa;YACbM,SAASX;YACTM,UAAU;QACZ;IACF,EAAC;IAED,MAAaM,MAAqB;QAChC,MAAM,EAACV,IAAI,EAAEO,KAAK,EAAC,GAAG,MAAM,IAAI,CAACI,KAAK,CAACZ;QACvC,MAAM,EAACS,UAAU,EAAC,GAAGD;QAErB,iCAAiC;QACjC,MAAMK,YAAY,MAAM,IAAI,CAACC,YAAY;QACzC,IAAI,CAACD,WAAW;YACd,IAAI,CAACE,KAAK,CAAClB,eAAe;gBAACmB,MAAM;YAAC;QACpC;QAEA,uCAAuC;QACvC,IAAI,EAACd,MAAMe,WAAW,EAAC,GAAGhB;QAC1B,IAAIgB,aAAa;YACf,MAAMC,YAAYzB,oBAAoBwB;YACtC,IAAIC,WAAW;gBACb,IAAI,CAACH,KAAK,CAACG,WAAW;oBAACF,MAAM;gBAAC;YAChC;QACF,OAAO;YACLC,cAAc,MAAMvB;QACtB;QAEA,IAAIyB;QACJ,IAAIC;QAEJ,IAAI;YACF,MAAM,CAACC,kBAAkBC,iBAAiB,GAAG,MAAMC,QAAQC,GAAG,CAAC;gBAC7D7B,aAAakB;gBACbjB,mBAAmBiB;aACpB;YACDM,WAAWE,iBAAiBI,GAAG,CAAC,CAACC,KAAOA,GAAGxB,IAAI;YAC/CkB,kBAAkBE;QACpB,EAAE,OAAOP,OAAO;YACd,MAAMY,UAAUZ,iBAAiBa,QAAQb,MAAMY,OAAO,GAAGE,OAAOd;YAChEjB,mBAAmB,CAAC,8BAA8B,EAAE6B,SAAS,EAAEZ;YAC/D,IAAI,CAACA,KAAK,CAAC,CAAC,8BAA8B,EAAEY,SAAS,EAAE;gBAACX,MAAM;YAAC;QACjE;QAEA,IAAIG,SAASW,QAAQ,CAACb,cAAc;YAClC,IAAI,CAACF,KAAK,CAAC,CAAC,SAAS,EAAEE,YAAY,gBAAgB,CAAC,EAAE;gBAACD,MAAM;YAAC;QAChE;QAEA,MAAMe,mBAAmBX,gBAAgBU,QAAQ,CAAC;QAClDhC,mBAAmB,8BAA8BiC,mBAAmB,QAAQ;QAE5E,IAAI;YACF,MAAMvC,cAAc;gBAClByB;gBACAe,QAAQ,IAAI,CAACA,MAAM;gBACnBZ;gBACAP;gBACAJ;YACF;QACF,EAAE,OAAOM,OAAO;YACd,MAAMY,UAAUZ,iBAAiBa,QAAQb,MAAMY,OAAO,GAAGE,OAAOd;YAChE,IAAI,CAACA,KAAK,CAAC,CAAC,0BAA0B,EAAEY,SAAS,EAAE;gBAACX,MAAM;YAAC;QAC7D;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/commands/dataset/create.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {createDataset} from '../../actions/dataset/create.js'\nimport {validateDatasetName} from '../../actions/dataset/validateDatasetName.js'\nimport {promptForDatasetName} from '../../prompts/promptForDatasetName.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {listDatasets} from '../../services/datasets.js'\nimport {getProjectFeatures} from '../../services/getProjectFeatures.js'\nimport {projectIdFlag} from '../../util/sharedFlags.js'\n\nconst createDatasetDebug = subdebug('dataset:create')\n\nconst ALLOWED_ACL_MODES = ['custom', 'private', 'public']\n\nexport class CreateDatasetCommand extends SanityCommand<typeof CreateDatasetCommand> {\n static override args = {\n name: Args.string({\n description: 'Name of the dataset to create',\n required: false,\n }),\n }\n\n static override description = 'Create a new dataset within your project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively create a dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset',\n description: 'Create a dataset named \"my-dataset\"',\n },\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset --visibility private',\n description: 'Create a private dataset named \"my-dataset\"',\n },\n ]\n\n static override flags = {\n ...projectIdFlag,\n embeddings: Flags.boolean({\n default: false,\n description: 'Enable embeddings for this dataset',\n }),\n 'embeddings-projection': Flags.string({\n dependsOn: ['embeddings'],\n description: 'GROQ projection for embeddings indexing (e.g. \"{ title, body }\")',\n }),\n visibility: Flags.string({\n description: 'Set visibility for this dataset (custom/private/public)',\n options: ALLOWED_ACL_MODES,\n required: false,\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(CreateDatasetCommand)\n const {visibility} = flags\n\n // Ensure we have project context\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [\n {grant: 'read', permission: 'sanity.project.datasets'},\n {grant: 'create', permission: 'sanity.project.datasets'},\n ],\n }),\n })\n\n // Get dataset name from args or prompt\n let {name: datasetName} = args\n if (datasetName) {\n const nameError = validateDatasetName(datasetName)\n if (nameError) {\n this.error(nameError, {exit: 1})\n }\n } else {\n datasetName = await promptForDatasetName()\n }\n\n let datasets: string[]\n let projectFeatures: string[]\n\n try {\n const [datasetsResponse, featuresResponse] = await Promise.all([\n listDatasets(projectId),\n getProjectFeatures(projectId),\n ])\n datasets = datasetsResponse.map((ds) => ds.name)\n projectFeatures = featuresResponse\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n createDatasetDebug(`Failed to fetch project data: ${message}`, error)\n this.error(`Failed to fetch project data: ${message}`, {exit: 1})\n }\n\n if (datasets.includes(datasetName)) {\n this.error(`Dataset \"${datasetName}\" already exists`, {exit: 1})\n }\n\n const canCreatePrivate = projectFeatures.includes('privateDataset')\n createDatasetDebug('%s create private datasets', canCreatePrivate ? 'Can' : 'Cannot')\n\n try {\n await createDataset({\n datasetName,\n embeddings: flags.embeddings,\n embeddingsProjection: flags['embeddings-projection'],\n output: this.output,\n projectFeatures,\n projectId,\n visibility,\n })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.error(`Failed to create dataset: ${message}`, {exit: 1})\n }\n }\n}\n"],"names":["Args","Flags","SanityCommand","subdebug","createDataset","validateDatasetName","promptForDatasetName","promptForProject","listDatasets","getProjectFeatures","projectIdFlag","createDatasetDebug","ALLOWED_ACL_MODES","CreateDatasetCommand","args","name","string","description","required","examples","command","flags","embeddings","boolean","default","dependsOn","visibility","options","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","datasetName","nameError","error","exit","datasets","projectFeatures","datasetsResponse","featuresResponse","Promise","all","map","ds","message","Error","String","includes","canCreatePrivate","embeddingsProjection","output"],"mappings":"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"}
@@ -3,9 +3,10 @@ import { Args, Flags } from '@oclif/core';
3
3
  import { SanityCommand, subdebug } from '@sanity/cli-core';
4
4
  import { input, logSymbols } from '@sanity/cli-core/ux';
5
5
  import { validateDatasetName } from '../../actions/dataset/validateDatasetName.js';
6
+ import { promptForProject } from '../../prompts/promptForProject.js';
6
7
  import { deleteDataset } from '../../services/datasets.js';
7
8
  import { getProjectById } from '../../services/projects.js';
8
- import { NO_PROJECT_ID } from '../../util/errorMessages.js';
9
+ import { projectIdFlag } from '../../util/sharedFlags.js';
9
10
  const deleteDatasetDebug = subdebug('dataset:delete');
10
11
  export class DeleteDatasetCommand extends SanityCommand {
11
12
  static args = {
@@ -26,6 +27,7 @@ export class DeleteDatasetCommand extends SanityCommand {
26
27
  }
27
28
  ];
28
29
  static flags = {
30
+ ...projectIdFlag,
29
31
  force: Flags.boolean({
30
32
  description: 'Do not prompt for delete confirmation - forcefully delete',
31
33
  required: false
@@ -34,12 +36,16 @@ export class DeleteDatasetCommand extends SanityCommand {
34
36
  async run() {
35
37
  const { args, flags } = await this.parse(DeleteDatasetCommand);
36
38
  const { force } = flags;
37
- const projectId = await this.getProjectId();
38
- if (!projectId) {
39
- this.error(NO_PROJECT_ID, {
40
- exit: 1
41
- });
42
- }
39
+ const projectId = await this.getProjectId({
40
+ fallback: ()=>promptForProject({
41
+ requiredPermissions: [
42
+ {
43
+ grant: 'delete',
44
+ permission: 'sanity.project.datasets'
45
+ }
46
+ ]
47
+ })
48
+ });
43
49
  const datasetName = args.datasetName;
44
50
  const dsError = validateDatasetName(datasetName);
45
51
  if (dsError) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/dataset/delete.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {input, logSymbols} from '@sanity/cli-core/ux'\n\nimport {validateDatasetName} from '../../actions/dataset/validateDatasetName.js'\nimport {deleteDataset} from '../../services/datasets.js'\nimport {getProjectById} from '../../services/projects.js'\nimport {NO_PROJECT_ID} from '../../util/errorMessages.js'\n\nconst deleteDatasetDebug = subdebug('dataset:delete')\n\nexport class DeleteDatasetCommand extends SanityCommand<typeof DeleteDatasetCommand> {\n static override args = {\n datasetName: Args.string({\n description: 'Dataset name to delete',\n required: true,\n }),\n }\n\n static override description = 'Delete a dataset within your project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset',\n description: 'Delete a specific dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset --force',\n description: 'Delete a specific dataset without confirmation',\n },\n ]\n\n static override flags = {\n force: Flags.boolean({\n description: 'Do not prompt for delete confirmation - forcefully delete',\n required: false,\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(DeleteDatasetCommand)\n const {force} = flags\n\n const projectId = await this.getProjectId()\n if (!projectId) {\n this.error(NO_PROJECT_ID, {exit: 1})\n }\n\n const datasetName = args.datasetName\n\n const dsError = validateDatasetName(datasetName)\n if (dsError) {\n this.error(dsError, {exit: 1})\n }\n\n if (force) {\n this.warn(`'--force' used: skipping confirmation, deleting dataset \"${datasetName}\"`)\n } else {\n try {\n const project = await getProjectById(projectId)\n this.log(\n styleText(\n 'yellow',\n `${logSymbols.warning} Deleting dataset \"${styleText(['bold', 'underline'], datasetName)}\" from project \"${styleText(['bold', 'underline'], project.displayName)} (${styleText(['bold', 'underline'], project.id)})\"\\n`,\n ),\n )\n } catch (error) {\n const err = error instanceof Error ? error : new Error(`${error}`)\n deleteDatasetDebug(`Error getting project ${projectId}`, err)\n this.error(`Project retrieval failed: ${err.message}`, {exit: 1})\n }\n\n try {\n await input({\n message:\n 'Are you ABSOLUTELY sure you want to delete this dataset?\\n Type the name of the dataset to confirm delete:',\n validate: (input) => {\n const trimmed = input.trim()\n return trimmed === datasetName || 'Incorrect dataset name. Ctrl + C to cancel delete.'\n },\n })\n } catch (error) {\n const err = error instanceof Error ? error : new Error(`${error}`)\n deleteDatasetDebug(`User cancelled`, err)\n this.error(`User cancelled`, {exit: 1})\n }\n }\n\n try {\n await deleteDataset({datasetName, projectId})\n this.log('Dataset deleted successfully')\n } catch (error) {\n const err = error instanceof Error ? error : new Error(`${error}`)\n deleteDatasetDebug(`Error deleting dataset ${datasetName}`, err)\n this.error(`Dataset deletion failed: ${err.message}`, {exit: 1})\n }\n }\n}\n"],"names":["styleText","Args","Flags","SanityCommand","subdebug","input","logSymbols","validateDatasetName","deleteDataset","getProjectById","NO_PROJECT_ID","deleteDatasetDebug","DeleteDatasetCommand","args","datasetName","string","description","required","examples","command","flags","force","boolean","run","parse","projectId","getProjectId","error","exit","dsError","warn","project","log","warning","displayName","id","err","Error","message","validate","trimmed","trim"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/dataset/delete.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {input, logSymbols} from '@sanity/cli-core/ux'\n\nimport {validateDatasetName} from '../../actions/dataset/validateDatasetName.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {deleteDataset} from '../../services/datasets.js'\nimport {getProjectById} from '../../services/projects.js'\nimport {projectIdFlag} from '../../util/sharedFlags.js'\n\nconst deleteDatasetDebug = subdebug('dataset:delete')\n\nexport class DeleteDatasetCommand extends SanityCommand<typeof DeleteDatasetCommand> {\n static override args = {\n datasetName: Args.string({\n description: 'Dataset name to delete',\n required: true,\n }),\n }\n\n static override description = 'Delete a dataset within your project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset',\n description: 'Delete a specific dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset --force',\n description: 'Delete a specific dataset without confirmation',\n },\n ]\n\n static override flags = {\n ...projectIdFlag,\n force: Flags.boolean({\n description: 'Do not prompt for delete confirmation - forcefully delete',\n required: false,\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(DeleteDatasetCommand)\n const {force} = flags\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [\n {grant: 'delete', permission: 'sanity.project.datasets'},\n ],\n }),\n })\n\n const datasetName = args.datasetName\n\n const dsError = validateDatasetName(datasetName)\n if (dsError) {\n this.error(dsError, {exit: 1})\n }\n\n if (force) {\n this.warn(`'--force' used: skipping confirmation, deleting dataset \"${datasetName}\"`)\n } else {\n try {\n const project = await getProjectById(projectId)\n this.log(\n styleText(\n 'yellow',\n `${logSymbols.warning} Deleting dataset \"${styleText(['bold', 'underline'], datasetName)}\" from project \"${styleText(['bold', 'underline'], project.displayName)} (${styleText(['bold', 'underline'], project.id)})\"\\n`,\n ),\n )\n } catch (error) {\n const err = error instanceof Error ? error : new Error(`${error}`)\n deleteDatasetDebug(`Error getting project ${projectId}`, err)\n this.error(`Project retrieval failed: ${err.message}`, {exit: 1})\n }\n\n try {\n await input({\n message:\n 'Are you ABSOLUTELY sure you want to delete this dataset?\\n Type the name of the dataset to confirm delete:',\n validate: (input) => {\n const trimmed = input.trim()\n return trimmed === datasetName || 'Incorrect dataset name. Ctrl + C to cancel delete.'\n },\n })\n } catch (error) {\n const err = error instanceof Error ? error : new Error(`${error}`)\n deleteDatasetDebug(`User cancelled`, err)\n this.error(`User cancelled`, {exit: 1})\n }\n }\n\n try {\n await deleteDataset({datasetName, projectId})\n this.log('Dataset deleted successfully')\n } catch (error) {\n const err = error instanceof Error ? error : new Error(`${error}`)\n deleteDatasetDebug(`Error deleting dataset ${datasetName}`, err)\n this.error(`Dataset deletion failed: ${err.message}`, {exit: 1})\n }\n }\n}\n"],"names":["styleText","Args","Flags","SanityCommand","subdebug","input","logSymbols","validateDatasetName","promptForProject","deleteDataset","getProjectById","projectIdFlag","deleteDatasetDebug","DeleteDatasetCommand","args","datasetName","string","description","required","examples","command","flags","force","boolean","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","dsError","error","exit","warn","project","log","warning","displayName","id","err","Error","message","validate","trimmed","trim"],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import { styleText } from 'node:util';
2
+ import { Args } from '@oclif/core';
3
+ import { SanityCommand, subdebug } from '@sanity/cli-core';
4
+ import { resolveDataset } from '../../../actions/dataset/resolveDataset.js';
5
+ import { promptForProject } from '../../../prompts/promptForProject.js';
6
+ import { setEmbeddingsSettings } from '../../../services/embeddings.js';
7
+ import { projectIdFlag } from '../../../util/sharedFlags.js';
8
+ const debug = subdebug('dataset:embeddings:disable');
9
+ export class DatasetEmbeddingsDisableCommand extends SanityCommand {
10
+ static args = {
11
+ dataset: Args.string({
12
+ description: 'Dataset name to disable embeddings for',
13
+ required: false
14
+ })
15
+ };
16
+ static description = 'Disable embeddings for a dataset';
17
+ static examples = [
18
+ {
19
+ command: '<%= config.bin %> <%= command.id %> production',
20
+ description: 'Disable embeddings for the production dataset'
21
+ }
22
+ ];
23
+ static flags = {
24
+ ...projectIdFlag
25
+ };
26
+ async run() {
27
+ const { args } = await this.parse(DatasetEmbeddingsDisableCommand);
28
+ let { dataset } = args;
29
+ const projectId = await this.getProjectId({
30
+ fallback: ()=>promptForProject({
31
+ requiredPermissions: [
32
+ {
33
+ grant: 'read',
34
+ permission: 'sanity.project.datasets'
35
+ },
36
+ {
37
+ grant: 'update',
38
+ permission: 'sanity.project.datasets'
39
+ }
40
+ ]
41
+ })
42
+ });
43
+ try {
44
+ ;
45
+ ({ dataset } = await resolveDataset({
46
+ dataset,
47
+ projectId
48
+ }));
49
+ } catch (error) {
50
+ const message = error instanceof Error ? error.message : String(error);
51
+ debug(`Failed to resolve dataset: ${message}`, error);
52
+ this.error(message, {
53
+ exit: 1
54
+ });
55
+ }
56
+ try {
57
+ await setEmbeddingsSettings({
58
+ dataset,
59
+ enabled: false,
60
+ projectId
61
+ });
62
+ } catch (error) {
63
+ const message = error instanceof Error ? error.message : String(error);
64
+ debug(`Failed to disable embeddings: ${message}`, error);
65
+ this.error(`Failed to disable embeddings: ${message}`, {
66
+ exit: 1
67
+ });
68
+ }
69
+ this.log(styleText('green', `Disabled embeddings for dataset ${dataset}.`));
70
+ this.log(styleText('yellow', 'Note: Existing embedding data will be removed.'));
71
+ }
72
+ }
73
+
74
+ //# sourceMappingURL=disable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/commands/dataset/embeddings/disable.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {resolveDataset} from '../../../actions/dataset/resolveDataset.js'\nimport {promptForProject} from '../../../prompts/promptForProject.js'\nimport {setEmbeddingsSettings} from '../../../services/embeddings.js'\nimport {projectIdFlag} from '../../../util/sharedFlags.js'\n\nconst debug = subdebug('dataset:embeddings:disable')\n\nexport class DatasetEmbeddingsDisableCommand extends SanityCommand<\n typeof DatasetEmbeddingsDisableCommand\n> {\n static override args = {\n dataset: Args.string({\n description: 'Dataset name to disable embeddings for',\n required: false,\n }),\n }\n\n static override description = 'Disable embeddings for a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> production',\n description: 'Disable embeddings for the production dataset',\n },\n ]\n\n static override flags = {\n ...projectIdFlag,\n }\n\n public async run(): Promise<void> {\n const {args} = await this.parse(DatasetEmbeddingsDisableCommand)\n let {dataset} = args\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [\n {grant: 'read', permission: 'sanity.project.datasets'},\n {grant: 'update', permission: 'sanity.project.datasets'},\n ],\n }),\n })\n\n try {\n ;({dataset} = await resolveDataset({dataset, projectId}))\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n debug(`Failed to resolve dataset: ${message}`, error)\n this.error(message, {exit: 1})\n }\n\n try {\n await setEmbeddingsSettings({dataset, enabled: false, projectId})\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n debug(`Failed to disable embeddings: ${message}`, error)\n this.error(`Failed to disable embeddings: ${message}`, {exit: 1})\n }\n\n this.log(styleText('green', `Disabled embeddings for dataset ${dataset}.`))\n this.log(styleText('yellow', 'Note: Existing embedding data will be removed.'))\n }\n}\n"],"names":["styleText","Args","SanityCommand","subdebug","resolveDataset","promptForProject","setEmbeddingsSettings","projectIdFlag","debug","DatasetEmbeddingsDisableCommand","args","dataset","string","description","required","examples","command","flags","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","error","message","Error","String","exit","enabled","log"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SAAQC,IAAI,QAAO,cAAa;AAChC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAExD,SAAQC,cAAc,QAAO,6CAA4C;AACzE,SAAQC,gBAAgB,QAAO,uCAAsC;AACrE,SAAQC,qBAAqB,QAAO,kCAAiC;AACrE,SAAQC,aAAa,QAAO,+BAA8B;AAE1D,MAAMC,QAAQL,SAAS;AAEvB,OAAO,MAAMM,wCAAwCP;IAGnD,OAAgBQ,OAAO;QACrBC,SAASV,KAAKW,MAAM,CAAC;YACnBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,mCAAkC;IAEhE,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtB,GAAGV,aAAa;IAClB,EAAC;IAED,MAAaW,MAAqB;QAChC,MAAM,EAACR,IAAI,EAAC,GAAG,MAAM,IAAI,CAACS,KAAK,CAACV;QAChC,IAAI,EAACE,OAAO,EAAC,GAAGD;QAEhB,MAAMU,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,UAAU,IACRjB,iBAAiB;oBACfkB,qBAAqB;wBACnB;4BAACC,OAAO;4BAAQC,YAAY;wBAAyB;wBACrD;4BAACD,OAAO;4BAAUC,YAAY;wBAAyB;qBACxD;gBACH;QACJ;QAEA,IAAI;;YACA,CAAA,EAACd,OAAO,EAAC,GAAG,MAAMP,eAAe;gBAACO;gBAASS;YAAS,EAAC;QACzD,EAAE,OAAOM,OAAO;YACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;YAChElB,MAAM,CAAC,2BAA2B,EAAEmB,SAAS,EAAED;YAC/C,IAAI,CAACA,KAAK,CAACC,SAAS;gBAACG,MAAM;YAAC;QAC9B;QAEA,IAAI;YACF,MAAMxB,sBAAsB;gBAACK;gBAASoB,SAAS;gBAAOX;YAAS;QACjE,EAAE,OAAOM,OAAO;YACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;YAChElB,MAAM,CAAC,8BAA8B,EAAEmB,SAAS,EAAED;YAClD,IAAI,CAACA,KAAK,CAAC,CAAC,8BAA8B,EAAEC,SAAS,EAAE;gBAACG,MAAM;YAAC;QACjE;QAEA,IAAI,CAACE,GAAG,CAAChC,UAAU,SAAS,CAAC,gCAAgC,EAAEW,QAAQ,CAAC,CAAC;QACzE,IAAI,CAACqB,GAAG,CAAChC,UAAU,UAAU;IAC/B;AACF"}