@sanity/cli 7.9.0 → 7.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/README.md +163 -22
  2. package/dist/actions/auth/ensureAuthenticated.js +2 -0
  3. package/dist/actions/auth/ensureAuthenticated.js.map +1 -1
  4. package/dist/actions/auth/login/getProvider.js +7 -2
  5. package/dist/actions/auth/login/getProvider.js.map +1 -1
  6. package/dist/actions/auth/login/loginInstructions.js +19 -0
  7. package/dist/actions/auth/login/loginInstructions.js.map +1 -0
  8. package/dist/actions/dataset/create.js +2 -2
  9. package/dist/actions/dataset/create.js.map +1 -1
  10. package/dist/actions/dataset/resolveDataset.js +7 -1
  11. package/dist/actions/dataset/resolveDataset.js.map +1 -1
  12. package/dist/actions/deploy/createUserApplication.js +8 -5
  13. package/dist/actions/deploy/createUserApplication.js.map +1 -1
  14. package/dist/actions/deploy/deployApp.js +47 -24
  15. package/dist/actions/deploy/deployApp.js.map +1 -1
  16. package/dist/actions/deploy/deployStudio.js +2 -0
  17. package/dist/actions/deploy/deployStudio.js.map +1 -1
  18. package/dist/actions/graphql/resolveApiGeneration.js +9 -6
  19. package/dist/actions/graphql/resolveApiGeneration.js.map +1 -1
  20. package/dist/actions/init/initAction.js +23 -15
  21. package/dist/actions/init/initAction.js.map +1 -1
  22. package/dist/actions/manifest/extractCoreAppManifest.js +11 -4
  23. package/dist/actions/manifest/extractCoreAppManifest.js.map +1 -1
  24. package/dist/actions/migration/constants.js +10 -0
  25. package/dist/actions/migration/constants.js.map +1 -0
  26. package/dist/actions/migration/ensureApiVersionFormat.js +16 -0
  27. package/dist/actions/migration/ensureApiVersionFormat.js.map +1 -0
  28. package/dist/actions/migration/fileExists.js +13 -0
  29. package/dist/actions/migration/fileExists.js.map +1 -0
  30. package/dist/actions/migration/prettyMutationFormatter.js +155 -0
  31. package/dist/actions/migration/prettyMutationFormatter.js.map +1 -0
  32. package/dist/actions/migration/resolveMigrationScript.js +75 -0
  33. package/dist/actions/migration/resolveMigrationScript.js.map +1 -0
  34. package/dist/actions/migration/resolveMigrations.js +50 -0
  35. package/dist/actions/migration/resolveMigrations.js.map +1 -0
  36. package/dist/actions/migration/templates/index.js +7 -0
  37. package/dist/actions/migration/templates/index.js.map +1 -0
  38. package/dist/actions/migration/templates/minimalAdvanced.js +21 -0
  39. package/dist/actions/migration/templates/minimalAdvanced.js.map +1 -0
  40. package/dist/actions/migration/templates/minimalSimple.js +61 -0
  41. package/dist/actions/migration/templates/minimalSimple.js.map +1 -0
  42. package/dist/actions/migration/templates/renameField.js +20 -0
  43. package/dist/actions/migration/templates/renameField.js.map +1 -0
  44. package/dist/actions/migration/templates/renameType.js +19 -0
  45. package/dist/actions/migration/templates/renameType.js.map +1 -0
  46. package/dist/actions/migration/templates/stringToPTE.js +32 -0
  47. package/dist/actions/migration/templates/stringToPTE.js.map +1 -0
  48. package/dist/actions/migration/tree.js +111 -0
  49. package/dist/actions/migration/tree.js.map +1 -0
  50. package/dist/actions/organizations/getOrganization.js +7 -3
  51. package/dist/actions/organizations/getOrganization.js.map +1 -1
  52. package/dist/actions/organizations/validateOrganizationSlug.js +20 -0
  53. package/dist/actions/organizations/validateOrganizationSlug.js.map +1 -0
  54. package/dist/actions/preview/previewAction.js +33 -1
  55. package/dist/actions/preview/previewAction.js.map +1 -1
  56. package/dist/actions/schema/listSchemas.js +6 -4
  57. package/dist/actions/schema/listSchemas.js.map +1 -1
  58. package/dist/actions/tokens/validateRole.js +2 -1
  59. package/dist/actions/tokens/validateRole.js.map +1 -1
  60. package/dist/actions/undeploy/runUndeploy.js +13 -4
  61. package/dist/actions/undeploy/runUndeploy.js.map +1 -1
  62. package/dist/commands/backups/disable.js +5 -1
  63. package/dist/commands/backups/disable.js.map +1 -1
  64. package/dist/commands/backups/download.js +30 -6
  65. package/dist/commands/backups/download.js.map +1 -1
  66. package/dist/commands/backups/enable.js +5 -1
  67. package/dist/commands/backups/enable.js.map +1 -1
  68. package/dist/commands/backups/list.js +5 -1
  69. package/dist/commands/backups/list.js.map +1 -1
  70. package/dist/commands/cors/add.js +15 -7
  71. package/dist/commands/cors/add.js.map +1 -1
  72. package/dist/commands/cors/delete.js +6 -1
  73. package/dist/commands/cors/delete.js.map +1 -1
  74. package/dist/commands/datasets/alias/create.js +25 -18
  75. package/dist/commands/datasets/alias/create.js.map +1 -1
  76. package/dist/commands/datasets/alias/delete.js +15 -8
  77. package/dist/commands/datasets/alias/delete.js.map +1 -1
  78. package/dist/commands/datasets/alias/link.js +39 -17
  79. package/dist/commands/datasets/alias/link.js.map +1 -1
  80. package/dist/commands/datasets/alias/unlink.js +23 -2
  81. package/dist/commands/datasets/alias/unlink.js.map +1 -1
  82. package/dist/commands/datasets/copy.js +18 -2
  83. package/dist/commands/datasets/copy.js.map +1 -1
  84. package/dist/commands/datasets/create.js +8 -2
  85. package/dist/commands/datasets/create.js.map +1 -1
  86. package/dist/commands/datasets/delete.js +14 -17
  87. package/dist/commands/datasets/delete.js.map +1 -1
  88. package/dist/commands/datasets/embeddings/disable.js +3 -0
  89. package/dist/commands/datasets/embeddings/disable.js.map +1 -1
  90. package/dist/commands/datasets/embeddings/enable.js +5 -2
  91. package/dist/commands/datasets/embeddings/enable.js.map +1 -1
  92. package/dist/commands/datasets/embeddings/status.js +3 -0
  93. package/dist/commands/datasets/embeddings/status.js.map +1 -1
  94. package/dist/commands/datasets/export.js +27 -15
  95. package/dist/commands/datasets/export.js.map +1 -1
  96. package/dist/commands/datasets/import.js +3 -3
  97. package/dist/commands/datasets/import.js.map +1 -1
  98. package/dist/commands/datasets/visibility/get.js +2 -2
  99. package/dist/commands/datasets/visibility/get.js.map +1 -1
  100. package/dist/commands/datasets/visibility/set.js +2 -2
  101. package/dist/commands/datasets/visibility/set.js.map +1 -1
  102. package/dist/commands/docs/read.js +3 -3
  103. package/dist/commands/docs/read.js.map +1 -1
  104. package/dist/commands/documents/create.js +18 -13
  105. package/dist/commands/documents/create.js.map +1 -1
  106. package/dist/commands/documents/delete.js +3 -3
  107. package/dist/commands/documents/delete.js.map +1 -1
  108. package/dist/commands/documents/get.js +3 -3
  109. package/dist/commands/documents/get.js.map +1 -1
  110. package/dist/commands/documents/query.js +3 -3
  111. package/dist/commands/documents/query.js.map +1 -1
  112. package/dist/commands/documents/validate.js +29 -26
  113. package/dist/commands/documents/validate.js.map +1 -1
  114. package/dist/commands/graphql/deploy.js +20 -16
  115. package/dist/commands/graphql/deploy.js.map +1 -1
  116. package/dist/commands/graphql/undeploy.js +15 -18
  117. package/dist/commands/graphql/undeploy.js.map +1 -1
  118. package/dist/commands/hooks/create.js +4 -0
  119. package/dist/commands/hooks/create.js.map +1 -1
  120. package/dist/commands/hooks/delete.js +6 -1
  121. package/dist/commands/hooks/delete.js.map +1 -1
  122. package/dist/commands/hooks/logs.js +6 -1
  123. package/dist/commands/hooks/logs.js.map +1 -1
  124. package/dist/commands/install.js +1 -1
  125. package/dist/commands/install.js.map +1 -1
  126. package/dist/commands/login.js +2 -1
  127. package/dist/commands/login.js.map +1 -1
  128. package/dist/commands/media/create-aspect.js +20 -8
  129. package/dist/commands/media/create-aspect.js.map +1 -1
  130. package/dist/commands/media/delete-aspect.js +31 -16
  131. package/dist/commands/media/delete-aspect.js.map +1 -1
  132. package/dist/commands/media/deploy-aspect.js +10 -5
  133. package/dist/commands/media/deploy-aspect.js.map +1 -1
  134. package/dist/commands/media/export.js +9 -4
  135. package/dist/commands/media/export.js.map +1 -1
  136. package/dist/commands/media/import.js +6 -1
  137. package/dist/commands/media/import.js.map +1 -1
  138. package/dist/commands/migrations/create.js +150 -0
  139. package/dist/commands/migrations/create.js.map +1 -0
  140. package/dist/commands/migrations/list.js +64 -0
  141. package/dist/commands/migrations/list.js.map +1 -0
  142. package/dist/commands/migrations/run.js +306 -0
  143. package/dist/commands/migrations/run.js.map +1 -0
  144. package/dist/commands/organizations/create.js +79 -0
  145. package/dist/commands/organizations/create.js.map +1 -0
  146. package/dist/commands/organizations/delete.js +100 -0
  147. package/dist/commands/organizations/delete.js.map +1 -0
  148. package/dist/commands/organizations/get.js +48 -0
  149. package/dist/commands/organizations/get.js.map +1 -0
  150. package/dist/commands/organizations/list.js +60 -0
  151. package/dist/commands/organizations/list.js.map +1 -0
  152. package/dist/commands/organizations/update.js +115 -0
  153. package/dist/commands/organizations/update.js.map +1 -0
  154. package/dist/commands/preview.js +1 -0
  155. package/dist/commands/preview.js.map +1 -1
  156. package/dist/commands/projects/create.js +3 -1
  157. package/dist/commands/projects/create.js.map +1 -1
  158. package/dist/commands/schemas/delete.js +23 -2
  159. package/dist/commands/schemas/delete.js.map +1 -1
  160. package/dist/commands/schemas/deploy.js +6 -4
  161. package/dist/commands/schemas/deploy.js.map +1 -1
  162. package/dist/commands/schemas/extract.js +22 -1
  163. package/dist/commands/schemas/extract.js.map +1 -1
  164. package/dist/commands/schemas/list.js +8 -8
  165. package/dist/commands/schemas/list.js.map +1 -1
  166. package/dist/commands/tokens/{add.js → create.js} +25 -18
  167. package/dist/commands/tokens/create.js.map +1 -0
  168. package/dist/commands/tokens/delete.js +41 -23
  169. package/dist/commands/tokens/delete.js.map +1 -1
  170. package/dist/commands/undeploy.js +2 -7
  171. package/dist/commands/undeploy.js.map +1 -1
  172. package/dist/commands/users/invite.js +25 -3
  173. package/dist/commands/users/invite.js.map +1 -1
  174. package/dist/prompts/promptForOrganizationName.js +2 -1
  175. package/dist/prompts/promptForOrganizationName.js.map +1 -1
  176. package/dist/services/organizations.js +45 -2
  177. package/dist/services/organizations.js.map +1 -1
  178. package/dist/services/userApplications.js.map +1 -1
  179. package/dist/topicAliases.js +10 -0
  180. package/dist/topicAliases.js.map +1 -1
  181. package/dist/util/formatCliErrorMessages.js +5 -0
  182. package/dist/util/formatCliErrorMessages.js.map +1 -0
  183. package/dist/util/organizationAliases.js +12 -0
  184. package/dist/util/organizationAliases.js.map +1 -0
  185. package/oclif.config.js +6 -1
  186. package/oclif.manifest.json +464 -11
  187. package/package.json +28 -28
  188. package/dist/commands/tokens/add.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
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 { boxen, input, spinner } from '@sanity/cli-core/ux';
6
6
  import { exportDataset } from '@sanity/export';
7
7
  import prettyMs from 'pretty-ms';
@@ -126,31 +126,43 @@ export class DatasetExportCommand extends SanityCommand {
126
126
  // Determine dataset name
127
127
  let dataset = targetDataset;
128
128
  if (!dataset) {
129
+ let defaultDataset;
129
130
  try {
130
131
  // Get default dataset from config (only available when running from a project directory)
131
132
  const cliConfig = await this.tryGetCliConfig();
132
- const defaultDataset = cliConfig.api?.dataset;
133
- if (defaultDataset) {
134
- dataset = defaultDataset;
135
- this.log(`Using default dataset: ${dataset}`);
136
- } else {
133
+ defaultDataset = cliConfig.api?.dataset;
134
+ } catch (error) {
135
+ exportDebug('Error selecting dataset', error);
136
+ this.error(`Failed to select dataset:\n${error instanceof Error ? error.message : error}`, {
137
+ exit: exitCodes.RUNTIME_ERROR
138
+ });
139
+ }
140
+ if (defaultDataset) {
141
+ dataset = defaultDataset;
142
+ this.log(`Using default dataset: ${dataset}`);
143
+ } else if (this.isUnattended()) {
144
+ this.error('Dataset name is required. Pass it as the `<name>` argument.', {
145
+ exit: exitCodes.USAGE_ERROR
146
+ });
147
+ } else {
148
+ try {
137
149
  dataset = await promptForDataset({
138
150
  allowCreation: false,
139
151
  datasets
140
152
  });
153
+ } catch (error) {
154
+ exportDebug('Error selecting dataset', error);
155
+ this.error(`Failed to select dataset:\n${error instanceof Error ? error.message : error}`, {
156
+ exit: exitCodes.RUNTIME_ERROR
157
+ });
141
158
  }
142
- } catch (error) {
143
- exportDebug('Error selecting dataset', error);
144
- this.error(`Failed to select dataset:\n${error instanceof Error ? error.message : error}`, {
145
- exit: 1
146
- });
147
159
  }
148
160
  }
149
161
  // Validate dataset name
150
162
  const dsError = validateDatasetName(dataset);
151
163
  if (dsError) {
152
164
  this.error(dsError, {
153
- exit: 1
165
+ exit: exitCodes.USAGE_ERROR
154
166
  });
155
167
  }
156
168
  // Verify existence of dataset before trying to export from it
@@ -168,7 +180,7 @@ dataset: ${dataset.padEnd(46)}`, {
168
180
  // Determine output path
169
181
  let destinationPath = targetDestination;
170
182
  if (!destinationPath) {
171
- destinationPath = await this.promptForDestination({
183
+ destinationPath = this.isUnattended() ? path.join(process.cwd(), `${dataset}.tar.gz`) : await this.promptForDestination({
172
184
  dataset
173
185
  });
174
186
  }
@@ -265,8 +277,8 @@ dataset: ${dataset.padEnd(46)}`, {
265
277
  const finalPath = looksLikeFile ? dstPath : path.join(dstPath, `${dataset}.tar.gz`);
266
278
  const finalPathStats = await fs.stat(finalPath).catch(noop);
267
279
  if (!flags.overwrite && finalPathStats && finalPathStats.isFile()) {
268
- this.error(`File "${finalPath}" already exists. Use --overwrite flag to overwrite it.`, {
269
- exit: 1
280
+ this.error(`File "${finalPath}" already exists. Pass \`--overwrite\` to replace it.`, {
281
+ exit: exitCodes.USAGE_ERROR
270
282
  });
271
283
  }
272
284
  return finalPath;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/datasets/export.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport {type Writable} from 'node:stream'\n\nimport {Args, Flags} from '@oclif/core'\nimport {getProjectCliClient, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {boxen, input, spinner} from '@sanity/cli-core/ux'\nimport {type DatasetsResponse} from '@sanity/client'\nimport {exportDataset, type ExportOptions, type ExportProgress} from '@sanity/export'\nimport prettyMs from 'pretty-ms'\n\nimport {validateDatasetName} from '../../actions/dataset/validateDatasetName.js'\nimport {promptForDataset} from '../../prompts/promptForDataset.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {listDatasets} from '../../services/datasets.js'\nimport {absolutify} from '../../util/absolutify.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst noop = () => null\nconst exportDebug = subdebug('dataset:export')\n\nexport class DatasetExportCommand extends SanityCommand<typeof DatasetExportCommand> {\n static override args = {\n name: Args.string({\n description: 'Name of the dataset to export',\n }),\n // Args are order dependent\n // eslint-disable-next-line perfectionist/sort-objects\n destination: Args.string({\n description: 'Output destination file path',\n }),\n }\n\n static override description =\n 'Export a dataset to a local gzipped tarball. Assets returning 401, 403, or 404 are excluded from the export.'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> moviedb localPath.tar.gz',\n description: 'Export dataset \"moviedb\" to localPath.tar.gz',\n },\n {\n command: '<%= config.bin %> <%= command.id %> moviedb assetless.tar.gz --no-assets',\n description: 'Export dataset without assets',\n },\n {\n command: '<%= config.bin %> <%= command.id %> staging staging.tar.gz --raw',\n description: 'Export raw documents without asset reference rewriting',\n },\n {\n command: '<%= config.bin %> <%= command.id %> staging staging.tar.gz --types products,shops',\n description: 'Export specific document types',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> moviedb moviedb.tar.gz --no-strict-asset-verification',\n description: 'Export dataset without aborting on asset verification failures',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to export dataset from',\n semantics: 'override',\n }),\n 'asset-concurrency': Flags.integer({\n default: 8,\n description: 'Concurrent number of asset downloads',\n }),\n mode: Flags.string({\n default: 'stream',\n description:\n \"Export mode ('cursor' is faster for large datasets but may miss concurrent changes)\",\n options: ['stream', 'cursor'],\n }),\n 'no-assets': Flags.boolean({\n default: false,\n description: 'Export only non-asset documents and remove references to image assets',\n }),\n 'no-compress': Flags.boolean({\n default: false,\n description: 'Skips compressing tarball entries (still generates a gzip file)',\n }),\n 'no-drafts': Flags.boolean({\n default: false,\n description: 'Export only published versions of documents',\n }),\n 'no-strict-asset-verification': Flags.boolean({\n default: false,\n description:\n 'Do not abort the export when an asset fails hash or content-length verification',\n }),\n overwrite: Flags.boolean({\n default: false,\n description: 'Overwrite any file with the same name',\n }),\n raw: Flags.boolean({\n default: false,\n description: 'Extract only documents, without rewriting asset references',\n }),\n types: Flags.string({\n description: 'Defines which document types to export (comma-separated)',\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:export']\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(DatasetExportCommand)\n const {destination: targetDestination, name: targetDataset} = args\n\n // Get project configuration\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'read', permission: 'sanity.project.datasets'}],\n }),\n })\n\n const projectClient = await getProjectCliClient({\n apiVersion: '2023-05-26',\n projectId,\n requireUser: true,\n })\n\n let datasets: DatasetsResponse\n\n try {\n datasets = await listDatasets(projectId)\n } catch (error) {\n exportDebug('Error listing datasets', error)\n this.error(`Failed to list datasets:\\n${error instanceof Error ? error.message : error}`, {\n exit: 1,\n })\n }\n\n // Determine dataset name\n let dataset = targetDataset\n if (!dataset) {\n try {\n // Get default dataset from config (only available when running from a project directory)\n const cliConfig = await this.tryGetCliConfig()\n const defaultDataset = cliConfig.api?.dataset\n\n if (defaultDataset) {\n dataset = defaultDataset\n this.log(`Using default dataset: ${dataset}`)\n } else {\n dataset = await promptForDataset({allowCreation: false, datasets})\n }\n } catch (error) {\n exportDebug('Error selecting dataset', error)\n this.error(`Failed to select dataset:\\n${error instanceof Error ? error.message : error}`, {\n exit: 1,\n })\n }\n }\n\n // Validate dataset name\n const dsError = validateDatasetName(dataset)\n if (dsError) {\n this.error(dsError, {exit: 1})\n }\n\n // Verify existence of dataset before trying to export from it\n if (!datasets.some((set) => set.name === dataset)) {\n this.error(`Dataset with name \"${dataset}\" not found`, {exit: 1})\n }\n\n this.log(\n boxen(\n `Exporting from:\nprojectId: ${projectId.padEnd(44)}\ndataset: ${dataset.padEnd(46)}`,\n {\n borderColor: 'yellow',\n borderStyle: 'round',\n },\n ),\n )\n\n // Determine output path\n let destinationPath = targetDestination\n if (!destinationPath) {\n destinationPath = await this.promptForDestination({dataset})\n }\n\n const outputPath = await this.getOutputPath(destinationPath, dataset, flags)\n if (!outputPath) {\n this.error('Cancelled', {exit: 1})\n }\n\n // Prepare export options\n const {fail, onProgress, succeed} = this.createProgressHandler()\n const exportOptions: ExportOptions = {\n assetConcurrency: flags['asset-concurrency'],\n assets: !flags['no-assets'],\n client: projectClient,\n compress: !flags['no-compress'],\n dataset,\n drafts: !flags['no-drafts'],\n mode: flags.mode === 'cursor' || flags.mode === 'stream' ? flags.mode : undefined,\n onProgress,\n outputPath,\n raw: flags.raw,\n strictAssetVerification: !flags['no-strict-asset-verification'],\n types: flags.types ? flags.types.split(',') : undefined,\n }\n\n const start = Date.now()\n try {\n await exportDataset(exportOptions)\n succeed()\n this.log(`Export finished (${prettyMs(Date.now() - start)})`)\n } catch (error) {\n fail()\n const err = error instanceof Error ? error : new Error(String(error))\n exportDebug('Export failed', err)\n this.error(`Export failed: ${err.message}`, {exit: 1})\n }\n }\n\n private createProgressHandler() {\n let currentSpinner: ReturnType<typeof spinner> | null = null\n let currentStep = ''\n\n const onProgress = (progress: ExportProgress) => {\n if (progress.step !== currentStep) {\n // Complete previous step\n succeed()\n\n // Start new step\n currentStep = progress.step\n currentSpinner = spinner(progress.step).start()\n } else if (progress.step === currentStep && progress.update && currentSpinner) {\n // Update current step with progress info\n currentSpinner.text = `${progress.step} (${progress.current}/${progress.total})`\n }\n }\n\n const succeed = () => {\n currentSpinner?.succeed()\n }\n\n const fail = () => {\n currentSpinner?.fail()\n }\n\n return {fail, onProgress, succeed}\n }\n\n private async getOutputPath(\n destination: string,\n dataset: string,\n flags: {overwrite?: boolean},\n ): Promise<string | Writable> {\n if (destination === '-') {\n return process.stdout\n }\n\n const dstPath = path.isAbsolute(destination)\n ? destination\n : path.resolve(process.cwd(), destination)\n\n const dstStats = await fs.stat(dstPath).catch(noop)\n const looksLikeFile = dstStats ? dstStats.isFile() : path.basename(dstPath).includes('.')\n\n if (!dstStats) {\n const createPath = looksLikeFile ? path.dirname(dstPath) : dstPath\n try {\n await fs.mkdir(createPath, {recursive: true})\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n const errorWithCode = err as Error & {code?: string}\n if (errorWithCode.code === 'EACCES') {\n this.error(\n `Permission denied: Cannot create directory \"${createPath}\". Please check write permissions.`,\n {\n exit: 1,\n },\n )\n } else {\n this.error(`Failed to create directory \"${createPath}\": ${err.message}`, {\n exit: 1,\n })\n }\n }\n }\n\n const finalPath = looksLikeFile ? dstPath : path.join(dstPath, `${dataset}.tar.gz`)\n const finalPathStats = await fs.stat(finalPath).catch(noop)\n\n if (!flags.overwrite && finalPathStats && finalPathStats.isFile()) {\n this.error(`File \"${finalPath}\" already exists. Use --overwrite flag to overwrite it.`, {\n exit: 1,\n })\n }\n\n return finalPath\n }\n\n private promptForDestination(options: {dataset: string; workDir?: string}): Promise<string> {\n const {dataset, workDir = process.cwd()} = options\n\n const defaultPath = path.join(workDir, `${dataset}.tar.gz`)\n\n return input({\n default: defaultPath,\n message: 'Output path:',\n transformer: (value: string) => absolutify(value.trim()),\n validate: (value: string) => {\n const trimmed = value.trim()\n if (!trimmed) {\n return 'Please provide a valid output path'\n }\n return true\n },\n })\n }\n}\n"],"names":["fs","path","Args","Flags","getProjectCliClient","SanityCommand","subdebug","boxen","input","spinner","exportDataset","prettyMs","validateDatasetName","promptForDataset","promptForProject","listDatasets","absolutify","getProjectIdFlag","noop","exportDebug","DatasetExportCommand","args","name","string","description","destination","examples","command","flags","semantics","integer","default","mode","options","boolean","overwrite","raw","types","hiddenAliases","run","parse","targetDestination","targetDataset","projectId","getProjectId","fallback","requiredPermissions","grant","permission","projectClient","apiVersion","requireUser","datasets","error","Error","message","exit","dataset","cliConfig","tryGetCliConfig","defaultDataset","api","log","allowCreation","dsError","some","set","padEnd","borderColor","borderStyle","destinationPath","promptForDestination","outputPath","getOutputPath","fail","onProgress","succeed","createProgressHandler","exportOptions","assetConcurrency","assets","client","compress","drafts","undefined","strictAssetVerification","split","start","Date","now","err","String","currentSpinner","currentStep","progress","step","update","text","current","total","process","stdout","dstPath","isAbsolute","resolve","cwd","dstStats","stat","catch","looksLikeFile","isFile","basename","includes","createPath","dirname","mkdir","recursive","errorWithCode","code","finalPath","join","finalPathStats","workDir","defaultPath","transformer","value","trim","validate","trimmed"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/datasets/export.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport {type Writable} from 'node:stream'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exitCodes, getProjectCliClient, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {boxen, input, spinner} from '@sanity/cli-core/ux'\nimport {type DatasetsResponse} from '@sanity/client'\nimport {exportDataset, type ExportOptions, type ExportProgress} from '@sanity/export'\nimport prettyMs from 'pretty-ms'\n\nimport {validateDatasetName} from '../../actions/dataset/validateDatasetName.js'\nimport {promptForDataset} from '../../prompts/promptForDataset.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {listDatasets} from '../../services/datasets.js'\nimport {absolutify} from '../../util/absolutify.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst noop = () => null\nconst exportDebug = subdebug('dataset:export')\n\nexport class DatasetExportCommand extends SanityCommand<typeof DatasetExportCommand> {\n static override args = {\n name: Args.string({\n description: 'Name of the dataset to export',\n }),\n // Args are order dependent\n // eslint-disable-next-line perfectionist/sort-objects\n destination: Args.string({\n description: 'Output destination file path',\n }),\n }\n\n static override description =\n 'Export a dataset to a local gzipped tarball. Assets returning 401, 403, or 404 are excluded from the export.'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> moviedb localPath.tar.gz',\n description: 'Export dataset \"moviedb\" to localPath.tar.gz',\n },\n {\n command: '<%= config.bin %> <%= command.id %> moviedb assetless.tar.gz --no-assets',\n description: 'Export dataset without assets',\n },\n {\n command: '<%= config.bin %> <%= command.id %> staging staging.tar.gz --raw',\n description: 'Export raw documents without asset reference rewriting',\n },\n {\n command: '<%= config.bin %> <%= command.id %> staging staging.tar.gz --types products,shops',\n description: 'Export specific document types',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> moviedb moviedb.tar.gz --no-strict-asset-verification',\n description: 'Export dataset without aborting on asset verification failures',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to export dataset from',\n semantics: 'override',\n }),\n 'asset-concurrency': Flags.integer({\n default: 8,\n description: 'Concurrent number of asset downloads',\n }),\n mode: Flags.string({\n default: 'stream',\n description:\n \"Export mode ('cursor' is faster for large datasets but may miss concurrent changes)\",\n options: ['stream', 'cursor'],\n }),\n 'no-assets': Flags.boolean({\n default: false,\n description: 'Export only non-asset documents and remove references to image assets',\n }),\n 'no-compress': Flags.boolean({\n default: false,\n description: 'Skips compressing tarball entries (still generates a gzip file)',\n }),\n 'no-drafts': Flags.boolean({\n default: false,\n description: 'Export only published versions of documents',\n }),\n 'no-strict-asset-verification': Flags.boolean({\n default: false,\n description:\n 'Do not abort the export when an asset fails hash or content-length verification',\n }),\n overwrite: Flags.boolean({\n default: false,\n description: 'Overwrite any file with the same name',\n }),\n raw: Flags.boolean({\n default: false,\n description: 'Extract only documents, without rewriting asset references',\n }),\n types: Flags.string({\n description: 'Defines which document types to export (comma-separated)',\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:export']\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(DatasetExportCommand)\n const {destination: targetDestination, name: targetDataset} = args\n\n // Get project configuration\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'read', permission: 'sanity.project.datasets'}],\n }),\n })\n\n const projectClient = await getProjectCliClient({\n apiVersion: '2023-05-26',\n projectId,\n requireUser: true,\n })\n\n let datasets: DatasetsResponse\n\n try {\n datasets = await listDatasets(projectId)\n } catch (error) {\n exportDebug('Error listing datasets', error)\n this.error(`Failed to list datasets:\\n${error instanceof Error ? error.message : error}`, {\n exit: 1,\n })\n }\n\n // Determine dataset name\n let dataset = targetDataset\n if (!dataset) {\n let defaultDataset: string | undefined\n try {\n // Get default dataset from config (only available when running from a project directory)\n const cliConfig = await this.tryGetCliConfig()\n defaultDataset = cliConfig.api?.dataset\n } catch (error) {\n exportDebug('Error selecting dataset', error)\n this.error(`Failed to select dataset:\\n${error instanceof Error ? error.message : error}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (defaultDataset) {\n dataset = defaultDataset\n this.log(`Using default dataset: ${dataset}`)\n } else if (this.isUnattended()) {\n this.error('Dataset name is required. Pass it as the `<name>` argument.', {\n exit: exitCodes.USAGE_ERROR,\n })\n } else {\n try {\n dataset = await promptForDataset({allowCreation: false, datasets})\n } catch (error) {\n exportDebug('Error selecting dataset', error)\n this.error(\n `Failed to select dataset:\\n${error instanceof Error ? error.message : error}`,\n {\n exit: exitCodes.RUNTIME_ERROR,\n },\n )\n }\n }\n }\n\n // Validate dataset name\n const dsError = validateDatasetName(dataset)\n if (dsError) {\n this.error(dsError, {exit: exitCodes.USAGE_ERROR})\n }\n\n // Verify existence of dataset before trying to export from it\n if (!datasets.some((set) => set.name === dataset)) {\n this.error(`Dataset with name \"${dataset}\" not found`, {exit: 1})\n }\n\n this.log(\n boxen(\n `Exporting from:\nprojectId: ${projectId.padEnd(44)}\ndataset: ${dataset.padEnd(46)}`,\n {\n borderColor: 'yellow',\n borderStyle: 'round',\n },\n ),\n )\n\n // Determine output path\n let destinationPath = targetDestination\n if (!destinationPath) {\n destinationPath = this.isUnattended()\n ? path.join(process.cwd(), `${dataset}.tar.gz`)\n : await this.promptForDestination({dataset})\n }\n\n const outputPath = await this.getOutputPath(destinationPath, dataset, flags)\n if (!outputPath) {\n this.error('Cancelled', {exit: 1})\n }\n\n // Prepare export options\n const {fail, onProgress, succeed} = this.createProgressHandler()\n const exportOptions: ExportOptions = {\n assetConcurrency: flags['asset-concurrency'],\n assets: !flags['no-assets'],\n client: projectClient,\n compress: !flags['no-compress'],\n dataset,\n drafts: !flags['no-drafts'],\n mode: flags.mode === 'cursor' || flags.mode === 'stream' ? flags.mode : undefined,\n onProgress,\n outputPath,\n raw: flags.raw,\n strictAssetVerification: !flags['no-strict-asset-verification'],\n types: flags.types ? flags.types.split(',') : undefined,\n }\n\n const start = Date.now()\n try {\n await exportDataset(exportOptions)\n succeed()\n this.log(`Export finished (${prettyMs(Date.now() - start)})`)\n } catch (error) {\n fail()\n const err = error instanceof Error ? error : new Error(String(error))\n exportDebug('Export failed', err)\n this.error(`Export failed: ${err.message}`, {exit: 1})\n }\n }\n\n private createProgressHandler() {\n let currentSpinner: ReturnType<typeof spinner> | null = null\n let currentStep = ''\n\n const onProgress = (progress: ExportProgress) => {\n if (progress.step !== currentStep) {\n // Complete previous step\n succeed()\n\n // Start new step\n currentStep = progress.step\n currentSpinner = spinner(progress.step).start()\n } else if (progress.step === currentStep && progress.update && currentSpinner) {\n // Update current step with progress info\n currentSpinner.text = `${progress.step} (${progress.current}/${progress.total})`\n }\n }\n\n const succeed = () => {\n currentSpinner?.succeed()\n }\n\n const fail = () => {\n currentSpinner?.fail()\n }\n\n return {fail, onProgress, succeed}\n }\n\n private async getOutputPath(\n destination: string,\n dataset: string,\n flags: {overwrite?: boolean},\n ): Promise<string | Writable> {\n if (destination === '-') {\n return process.stdout\n }\n\n const dstPath = path.isAbsolute(destination)\n ? destination\n : path.resolve(process.cwd(), destination)\n\n const dstStats = await fs.stat(dstPath).catch(noop)\n const looksLikeFile = dstStats ? dstStats.isFile() : path.basename(dstPath).includes('.')\n\n if (!dstStats) {\n const createPath = looksLikeFile ? path.dirname(dstPath) : dstPath\n try {\n await fs.mkdir(createPath, {recursive: true})\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n const errorWithCode = err as Error & {code?: string}\n if (errorWithCode.code === 'EACCES') {\n this.error(\n `Permission denied: Cannot create directory \"${createPath}\". Please check write permissions.`,\n {\n exit: 1,\n },\n )\n } else {\n this.error(`Failed to create directory \"${createPath}\": ${err.message}`, {\n exit: 1,\n })\n }\n }\n }\n\n const finalPath = looksLikeFile ? dstPath : path.join(dstPath, `${dataset}.tar.gz`)\n const finalPathStats = await fs.stat(finalPath).catch(noop)\n\n if (!flags.overwrite && finalPathStats && finalPathStats.isFile()) {\n this.error(`File \"${finalPath}\" already exists. Pass \\`--overwrite\\` to replace it.`, {\n exit: exitCodes.USAGE_ERROR,\n })\n }\n\n return finalPath\n }\n\n private promptForDestination(options: {dataset: string; workDir?: string}): Promise<string> {\n const {dataset, workDir = process.cwd()} = options\n\n const defaultPath = path.join(workDir, `${dataset}.tar.gz`)\n\n return input({\n default: defaultPath,\n message: 'Output path:',\n transformer: (value: string) => absolutify(value.trim()),\n validate: (value: string) => {\n const trimmed = value.trim()\n if (!trimmed) {\n return 'Please provide a valid output path'\n }\n return true\n },\n })\n }\n}\n"],"names":["fs","path","Args","Flags","exitCodes","getProjectCliClient","SanityCommand","subdebug","boxen","input","spinner","exportDataset","prettyMs","validateDatasetName","promptForDataset","promptForProject","listDatasets","absolutify","getProjectIdFlag","noop","exportDebug","DatasetExportCommand","args","name","string","description","destination","examples","command","flags","semantics","integer","default","mode","options","boolean","overwrite","raw","types","hiddenAliases","run","parse","targetDestination","targetDataset","projectId","getProjectId","fallback","requiredPermissions","grant","permission","projectClient","apiVersion","requireUser","datasets","error","Error","message","exit","dataset","defaultDataset","cliConfig","tryGetCliConfig","api","RUNTIME_ERROR","log","isUnattended","USAGE_ERROR","allowCreation","dsError","some","set","padEnd","borderColor","borderStyle","destinationPath","join","process","cwd","promptForDestination","outputPath","getOutputPath","fail","onProgress","succeed","createProgressHandler","exportOptions","assetConcurrency","assets","client","compress","drafts","undefined","strictAssetVerification","split","start","Date","now","err","String","currentSpinner","currentStep","progress","step","update","text","current","total","stdout","dstPath","isAbsolute","resolve","dstStats","stat","catch","looksLikeFile","isFile","basename","includes","createPath","dirname","mkdir","recursive","errorWithCode","code","finalPath","finalPathStats","workDir","defaultPath","transformer","value","trim","validate","trimmed"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
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 { createRequester } from '@sanity/cli-core/request';
6
6
  import { spinner } from '@sanity/cli-core/ux';
7
7
  import { sanityImport } from '@sanity/import';
@@ -172,8 +172,8 @@ export class ImportDatasetCommand extends SanityCommand {
172
172
  let dataset = datasetFlag ?? targetDatasetArg;
173
173
  if (!dataset) {
174
174
  if (this.isUnattended()) {
175
- return this.output.error('Missing dataset. Use the --dataset flag to specify a dataset: --dataset <name>', {
176
- exit: 1
175
+ return this.output.error('Dataset is required. Pass it with `--dataset <name>`.', {
176
+ exit: exitCodes.USAGE_ERROR
177
177
  });
178
178
  }
179
179
  const datasets = await listDatasets(projectId);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/datasets/import.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\n\nimport {Args, Flags} from '@oclif/core'\nimport {getProjectCliClient, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {createRequester} from '@sanity/cli-core/request'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {sanityImport} from '@sanity/import'\nimport prettyMs from 'pretty-ms'\n\nimport {NEW_DATASET_VALUE, promptForDataset} from '../../prompts/promptForDataset.js'\nimport {promptForDatasetName} from '../../prompts/promptForDatasetName.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {createDataset, listDatasets} from '../../services/datasets.js'\nimport {getDatasetFlag, getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst importDebug = subdebug('dataset:import')\n\ninterface ProgressEvent {\n step: string\n\n current?: number\n total?: number\n update?: string\n}\n\nfunction getAssetsBase(source: string): string | undefined {\n if (/^https?:\\/\\//i.test(source) || source === '-') {\n return undefined\n }\n\n try {\n const fileStats = fs.statSync(source)\n const sourceIsFolder = fileStats.isDirectory()\n return sourceIsFolder ? source : path.dirname(source)\n } catch {\n return undefined\n }\n}\n\nasync function getUriStream(uri: string): Promise<NodeJS.ReadableStream> {\n const request = createRequester({\n middleware: {promise: {onlyBody: false}},\n })\n\n try {\n const response = (await request({stream: true, url: uri})) as {body: NodeJS.ReadableStream}\n return response.body\n } catch (err) {\n throw new Error(`Error fetching source:\\n${(err as Error).message}`, {cause: err})\n }\n}\n\nfunction getPercentage(opts: ProgressEvent): string {\n if (!opts.total) {\n return ''\n }\n\n const percent = Math.floor(((opts.current || 0) / opts.total) * 100)\n return `[${percent}%] `\n}\n\nexport class ImportDatasetCommand extends SanityCommand<typeof ImportDatasetCommand> {\n static override args = {\n source: Args.string({\n description: 'Source file (use \"-\" for stdin)',\n required: true,\n }),\n targetDataset: Args.string({\n description: 'Target dataset (prefer --dataset flag instead)',\n required: false,\n }),\n }\n\n static override description = 'Import documents to a Sanity dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> -d staging my-dataset.ndjson',\n description: 'Import \"./my-dataset.ndjson\" into dataset \"staging\"',\n },\n {\n command: 'cat my-dataset.ndjson | <%= config.bin %> <%= command.id %> -d test -',\n description: 'Import into dataset \"test\" from stdin',\n },\n {\n command: '<%= config.bin %> <%= command.id %> -p projectId -d staging my-dataset.ndjson',\n description: 'Import with explicit project ID (overrides CLI configuration)',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> -d staging -t someSecretToken my-dataset.ndjson',\n description: 'Import with an explicit token (e.g. for CI/CD)',\n },\n ]\n\n static override flags = {\n 'allow-assets-in-different-dataset': Flags.boolean({\n default: false,\n description: 'Allow asset documents to reference different project/dataset',\n }),\n 'allow-failing-assets': Flags.boolean({\n default: false,\n description: 'Skip assets that cannot be fetched/uploaded',\n }),\n 'allow-replacement-characters': Flags.boolean({\n default: false,\n description: 'Allow unicode replacement characters in imported documents',\n }),\n 'allow-system-documents': Flags.boolean({\n default: false,\n description: 'Imports system documents',\n }),\n 'asset-concurrency': Flags.integer({\n description: 'Number of parallel asset imports',\n }),\n ...getDatasetFlag({\n description: 'Dataset to import to',\n semantics: 'specify',\n }),\n missing: Flags.boolean({\n default: false,\n description: 'Skip documents that already exist',\n exclusive: ['replace'],\n }),\n ...getProjectIdFlag({\n description: 'Project ID to import to',\n semantics: 'override',\n }),\n project: Flags.string({\n deprecated: {to: 'project-id'},\n description: 'Project ID to import to',\n hidden: true,\n }),\n replace: Flags.boolean({\n default: false,\n description: 'Replace documents with the same IDs',\n exclusive: ['missing'],\n }),\n 'replace-assets': Flags.boolean({\n default: false,\n description: 'Skip reuse of existing assets',\n }),\n 'skip-cross-dataset-references': Flags.boolean({\n default: false,\n description: 'Skips references to other datasets',\n }),\n token: Flags.string({\n char: 't',\n description: 'Token to authenticate with',\n env: 'SANITY_IMPORT_TOKEN',\n required: false,\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:import']\n\n private currentProgress?: ReturnType<typeof spinner>\n private currentStep?: string\n private spinInterval?: NodeJS.Timeout | null\n private stepStart?: number\n\n private static async getStream(source: string): Promise<NodeJS.ReadableStream> {\n if (/^https?:\\/\\//i.test(source)) {\n return getUriStream(source)\n }\n\n return source === '-' ? process.stdin : fs.createReadStream(source)\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(ImportDatasetCommand)\n\n const {\n 'allow-assets-in-different-dataset': allowAssetsInDifferentDataset,\n 'allow-failing-assets': allowFailingAssets,\n 'allow-replacement-characters': allowReplacementCharacters,\n 'allow-system-documents': allowSystemDocuments,\n 'asset-concurrency': assetConcurrency,\n dataset: datasetFlag,\n missing,\n replace,\n 'replace-assets': replaceAssets,\n 'skip-cross-dataset-references': skipCrossDatasetReferences,\n token,\n } = flags\n\n const projectId = await this.getProjectId({\n deprecatedFlagName: 'project',\n fallback: () => promptForProject({}),\n })\n\n const {source, targetDataset: targetDatasetArg} = args\n\n if (targetDatasetArg && !datasetFlag) {\n this.output.warn(\n 'Positional dataset argument is deprecated. Use the --dataset flag instead: --dataset <name>',\n )\n }\n\n let dataset = datasetFlag ?? targetDatasetArg\n if (!dataset) {\n if (this.isUnattended()) {\n return this.output.error(\n 'Missing dataset. Use the --dataset flag to specify a dataset: --dataset <name>',\n {exit: 1},\n )\n }\n\n const datasets = await listDatasets(projectId)\n dataset = await promptForDataset({allowCreation: true, datasets})\n\n if (dataset === NEW_DATASET_VALUE) {\n const newDatasetName = await promptForDatasetName()\n\n try {\n await createDataset({datasetName: newDatasetName, projectId})\n dataset = newDatasetName\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n importDebug(`Failed to create dataset ${newDatasetName}: ${message}`, error)\n return this.output.error(`Failed to create dataset ${newDatasetName}: ${message}`, {\n exit: 1,\n })\n }\n }\n }\n\n let operation: 'create' | 'createIfNotExists' | 'createOrReplace' = 'create'\n let releasesOperation: 'fail' | 'ignore' | 'replace' = 'fail'\n\n if (replace || missing) {\n operation = replace ? 'createOrReplace' : 'createIfNotExists'\n releasesOperation = replace ? 'replace' : 'ignore'\n }\n\n const client = await getProjectCliClient({\n apiVersion: 'v2025-02-19',\n dataset,\n projectId,\n requireUser: true,\n ...(token ? {token} : {}),\n })\n\n try {\n const stream = await ImportDatasetCommand.getStream(source)\n const assetsBase = getAssetsBase(source)\n\n const importOptions = {\n allowAssetsInDifferentDataset,\n allowFailingAssets,\n allowReplacementCharacters,\n allowSystemDocuments,\n client,\n onProgress: this.onProgress.bind(this),\n operation,\n releasesOperation,\n replaceAssets,\n skipCrossDatasetReferences,\n tag: 'sanity.import',\n targetDataset: dataset,\n targetProjectId: projectId,\n ...(assetsBase ? {assetsBase} : {}),\n ...(assetConcurrency === undefined ? {} : {assetConcurrency}),\n }\n\n const {numDocs, warnings} = await sanityImport(stream, importOptions)\n\n if (this.stepStart) {\n const timeSpent = prettyMs(Date.now() - this.stepStart, {secondsDecimalDigits: 2})\n if (this.currentProgress) {\n if (this.spinInterval) {\n clearInterval(this.spinInterval)\n this.spinInterval = null\n }\n this.currentProgress.text = `[100%] ${this.currentStep} (${timeSpent})`\n this.currentProgress.succeed()\n }\n }\n\n this.output.log('Done! Imported %d documents to dataset \"%s\"\\n', numDocs, dataset)\n this.printWarnings(warnings)\n } catch (err) {\n if (this.spinInterval) {\n clearInterval(this.spinInterval)\n this.spinInterval = null\n }\n\n if (this.currentProgress) {\n this.currentProgress.fail()\n }\n\n return (err as Error).name === 'ReplacementCharError'\n ? this.output.error(\n `Import failed due to unicode replacement characters in the data.\\n${(err as Error).message}\\n\\nIf you are certain you want to proceed with the import despite potentially corrupt data, re-run the import with the \\`--allow-replacement-characters\\` flag set.`,\n {exit: 1},\n )\n : this.output.error((err as Error).stack || (err as Error).message, {exit: 1})\n }\n }\n\n private onProgress(opts: ProgressEvent): void {\n const lengthComputable = opts.total\n const sameStep = opts.step === this.currentStep\n const percent = getPercentage(opts)\n\n if (lengthComputable && opts.total === opts.current && this.spinInterval) {\n clearInterval(this.spinInterval)\n this.spinInterval = null\n }\n\n if (sameStep && !lengthComputable) {\n return\n }\n\n if (sameStep) {\n if (this.stepStart) {\n const timeSpent = prettyMs(Date.now() - this.stepStart, {secondsDecimalDigits: 2})\n if (this.currentProgress) {\n this.currentProgress.text = `${percent}${opts.step} (${timeSpent})`\n this.currentProgress.render()\n }\n }\n return\n }\n\n // Moved to a new step\n const prevStep = this.currentStep\n const prevStepStart = this.stepStart\n this.stepStart = Date.now()\n this.currentStep = opts.step\n\n if (this.spinInterval) {\n clearInterval(this.spinInterval)\n this.spinInterval = null\n }\n\n if (this.currentProgress && this.currentProgress.succeed && prevStepStart) {\n const timeSpent = prettyMs(Date.now() - prevStepStart, {\n secondsDecimalDigits: 2,\n })\n this.currentProgress.text = `[100%] ${prevStep} (${timeSpent})`\n this.currentProgress.succeed()\n }\n\n this.currentProgress = spinner(`[0%] ${opts.step} (0.00s)`).start()\n\n if (!lengthComputable) {\n this.spinInterval = setInterval(() => {\n if (this.stepStart && this.currentProgress) {\n const timeSpent = prettyMs(Date.now() - this.stepStart, {\n secondsDecimalDigits: 2,\n })\n this.currentProgress.text = `${percent}${opts.step} (${timeSpent})`\n this.currentProgress.render()\n }\n }, 60)\n }\n }\n\n private printWarnings(warnings: Array<{message: string; type?: string; url?: string}>): void {\n const assetFails = warnings.filter((warn) => warn.type === 'asset')\n\n if (assetFails.length === 0) {\n return\n }\n\n this.output.warn(\n `Failed to import the following ${assetFails.length > 1 ? 'assets' : 'asset'}:`,\n )\n\n for (const warning of assetFails) {\n if (warning.url) {\n this.output.warn(` ${warning.url}`)\n }\n }\n }\n}\n"],"names":["fs","path","Args","Flags","getProjectCliClient","SanityCommand","subdebug","createRequester","spinner","sanityImport","prettyMs","NEW_DATASET_VALUE","promptForDataset","promptForDatasetName","promptForProject","createDataset","listDatasets","getDatasetFlag","getProjectIdFlag","importDebug","getAssetsBase","source","test","undefined","fileStats","statSync","sourceIsFolder","isDirectory","dirname","getUriStream","uri","request","middleware","promise","onlyBody","response","stream","url","body","err","Error","message","cause","getPercentage","opts","total","percent","Math","floor","current","ImportDatasetCommand","args","string","description","required","targetDataset","examples","command","flags","boolean","default","integer","semantics","missing","exclusive","project","deprecated","to","hidden","replace","token","char","env","hiddenAliases","currentProgress","currentStep","spinInterval","stepStart","getStream","process","stdin","createReadStream","run","parse","allowAssetsInDifferentDataset","allowFailingAssets","allowReplacementCharacters","allowSystemDocuments","assetConcurrency","dataset","datasetFlag","replaceAssets","skipCrossDatasetReferences","projectId","getProjectId","deprecatedFlagName","fallback","targetDatasetArg","output","warn","isUnattended","error","exit","datasets","allowCreation","newDatasetName","datasetName","String","operation","releasesOperation","client","apiVersion","requireUser","assetsBase","importOptions","onProgress","bind","tag","targetProjectId","numDocs","warnings","timeSpent","Date","now","secondsDecimalDigits","clearInterval","text","succeed","log","printWarnings","fail","name","stack","lengthComputable","sameStep","step","render","prevStep","prevStepStart","start","setInterval","assetFails","filter","type","length","warning"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/commands/datasets/import.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exitCodes, getProjectCliClient, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {createRequester} from '@sanity/cli-core/request'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {sanityImport} from '@sanity/import'\nimport prettyMs from 'pretty-ms'\n\nimport {NEW_DATASET_VALUE, promptForDataset} from '../../prompts/promptForDataset.js'\nimport {promptForDatasetName} from '../../prompts/promptForDatasetName.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {createDataset, listDatasets} from '../../services/datasets.js'\nimport {getDatasetFlag, getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst importDebug = subdebug('dataset:import')\n\ninterface ProgressEvent {\n step: string\n\n current?: number\n total?: number\n update?: string\n}\n\nfunction getAssetsBase(source: string): string | undefined {\n if (/^https?:\\/\\//i.test(source) || source === '-') {\n return undefined\n }\n\n try {\n const fileStats = fs.statSync(source)\n const sourceIsFolder = fileStats.isDirectory()\n return sourceIsFolder ? source : path.dirname(source)\n } catch {\n return undefined\n }\n}\n\nasync function getUriStream(uri: string): Promise<NodeJS.ReadableStream> {\n const request = createRequester({\n middleware: {promise: {onlyBody: false}},\n })\n\n try {\n const response = (await request({stream: true, url: uri})) as {body: NodeJS.ReadableStream}\n return response.body\n } catch (err) {\n throw new Error(`Error fetching source:\\n${(err as Error).message}`, {cause: err})\n }\n}\n\nfunction getPercentage(opts: ProgressEvent): string {\n if (!opts.total) {\n return ''\n }\n\n const percent = Math.floor(((opts.current || 0) / opts.total) * 100)\n return `[${percent}%] `\n}\n\nexport class ImportDatasetCommand extends SanityCommand<typeof ImportDatasetCommand> {\n static override args = {\n source: Args.string({\n description: 'Source file (use \"-\" for stdin)',\n required: true,\n }),\n targetDataset: Args.string({\n description: 'Target dataset (prefer --dataset flag instead)',\n required: false,\n }),\n }\n\n static override description = 'Import documents to a Sanity dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> -d staging my-dataset.ndjson',\n description: 'Import \"./my-dataset.ndjson\" into dataset \"staging\"',\n },\n {\n command: 'cat my-dataset.ndjson | <%= config.bin %> <%= command.id %> -d test -',\n description: 'Import into dataset \"test\" from stdin',\n },\n {\n command: '<%= config.bin %> <%= command.id %> -p projectId -d staging my-dataset.ndjson',\n description: 'Import with explicit project ID (overrides CLI configuration)',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> -d staging -t someSecretToken my-dataset.ndjson',\n description: 'Import with an explicit token (e.g. for CI/CD)',\n },\n ]\n\n static override flags = {\n 'allow-assets-in-different-dataset': Flags.boolean({\n default: false,\n description: 'Allow asset documents to reference different project/dataset',\n }),\n 'allow-failing-assets': Flags.boolean({\n default: false,\n description: 'Skip assets that cannot be fetched/uploaded',\n }),\n 'allow-replacement-characters': Flags.boolean({\n default: false,\n description: 'Allow unicode replacement characters in imported documents',\n }),\n 'allow-system-documents': Flags.boolean({\n default: false,\n description: 'Imports system documents',\n }),\n 'asset-concurrency': Flags.integer({\n description: 'Number of parallel asset imports',\n }),\n ...getDatasetFlag({\n description: 'Dataset to import to',\n semantics: 'specify',\n }),\n missing: Flags.boolean({\n default: false,\n description: 'Skip documents that already exist',\n exclusive: ['replace'],\n }),\n ...getProjectIdFlag({\n description: 'Project ID to import to',\n semantics: 'override',\n }),\n project: Flags.string({\n deprecated: {to: 'project-id'},\n description: 'Project ID to import to',\n hidden: true,\n }),\n replace: Flags.boolean({\n default: false,\n description: 'Replace documents with the same IDs',\n exclusive: ['missing'],\n }),\n 'replace-assets': Flags.boolean({\n default: false,\n description: 'Skip reuse of existing assets',\n }),\n 'skip-cross-dataset-references': Flags.boolean({\n default: false,\n description: 'Skips references to other datasets',\n }),\n token: Flags.string({\n char: 't',\n description: 'Token to authenticate with',\n env: 'SANITY_IMPORT_TOKEN',\n required: false,\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:import']\n\n private currentProgress?: ReturnType<typeof spinner>\n private currentStep?: string\n private spinInterval?: NodeJS.Timeout | null\n private stepStart?: number\n\n private static async getStream(source: string): Promise<NodeJS.ReadableStream> {\n if (/^https?:\\/\\//i.test(source)) {\n return getUriStream(source)\n }\n\n return source === '-' ? process.stdin : fs.createReadStream(source)\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(ImportDatasetCommand)\n\n const {\n 'allow-assets-in-different-dataset': allowAssetsInDifferentDataset,\n 'allow-failing-assets': allowFailingAssets,\n 'allow-replacement-characters': allowReplacementCharacters,\n 'allow-system-documents': allowSystemDocuments,\n 'asset-concurrency': assetConcurrency,\n dataset: datasetFlag,\n missing,\n replace,\n 'replace-assets': replaceAssets,\n 'skip-cross-dataset-references': skipCrossDatasetReferences,\n token,\n } = flags\n\n const projectId = await this.getProjectId({\n deprecatedFlagName: 'project',\n fallback: () => promptForProject({}),\n })\n\n const {source, targetDataset: targetDatasetArg} = args\n\n if (targetDatasetArg && !datasetFlag) {\n this.output.warn(\n 'Positional dataset argument is deprecated. Use the --dataset flag instead: --dataset <name>',\n )\n }\n\n let dataset = datasetFlag ?? targetDatasetArg\n if (!dataset) {\n if (this.isUnattended()) {\n return this.output.error('Dataset is required. Pass it with `--dataset <name>`.', {\n exit: exitCodes.USAGE_ERROR,\n })\n }\n\n const datasets = await listDatasets(projectId)\n dataset = await promptForDataset({allowCreation: true, datasets})\n\n if (dataset === NEW_DATASET_VALUE) {\n const newDatasetName = await promptForDatasetName()\n\n try {\n await createDataset({datasetName: newDatasetName, projectId})\n dataset = newDatasetName\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n importDebug(`Failed to create dataset ${newDatasetName}: ${message}`, error)\n return this.output.error(`Failed to create dataset ${newDatasetName}: ${message}`, {\n exit: 1,\n })\n }\n }\n }\n\n let operation: 'create' | 'createIfNotExists' | 'createOrReplace' = 'create'\n let releasesOperation: 'fail' | 'ignore' | 'replace' = 'fail'\n\n if (replace || missing) {\n operation = replace ? 'createOrReplace' : 'createIfNotExists'\n releasesOperation = replace ? 'replace' : 'ignore'\n }\n\n const client = await getProjectCliClient({\n apiVersion: 'v2025-02-19',\n dataset,\n projectId,\n requireUser: true,\n ...(token ? {token} : {}),\n })\n\n try {\n const stream = await ImportDatasetCommand.getStream(source)\n const assetsBase = getAssetsBase(source)\n\n const importOptions = {\n allowAssetsInDifferentDataset,\n allowFailingAssets,\n allowReplacementCharacters,\n allowSystemDocuments,\n client,\n onProgress: this.onProgress.bind(this),\n operation,\n releasesOperation,\n replaceAssets,\n skipCrossDatasetReferences,\n tag: 'sanity.import',\n targetDataset: dataset,\n targetProjectId: projectId,\n ...(assetsBase ? {assetsBase} : {}),\n ...(assetConcurrency === undefined ? {} : {assetConcurrency}),\n }\n\n const {numDocs, warnings} = await sanityImport(stream, importOptions)\n\n if (this.stepStart) {\n const timeSpent = prettyMs(Date.now() - this.stepStart, {secondsDecimalDigits: 2})\n if (this.currentProgress) {\n if (this.spinInterval) {\n clearInterval(this.spinInterval)\n this.spinInterval = null\n }\n this.currentProgress.text = `[100%] ${this.currentStep} (${timeSpent})`\n this.currentProgress.succeed()\n }\n }\n\n this.output.log('Done! Imported %d documents to dataset \"%s\"\\n', numDocs, dataset)\n this.printWarnings(warnings)\n } catch (err) {\n if (this.spinInterval) {\n clearInterval(this.spinInterval)\n this.spinInterval = null\n }\n\n if (this.currentProgress) {\n this.currentProgress.fail()\n }\n\n return (err as Error).name === 'ReplacementCharError'\n ? this.output.error(\n `Import failed due to unicode replacement characters in the data.\\n${(err as Error).message}\\n\\nIf you are certain you want to proceed with the import despite potentially corrupt data, re-run the import with the \\`--allow-replacement-characters\\` flag set.`,\n {exit: 1},\n )\n : this.output.error((err as Error).stack || (err as Error).message, {exit: 1})\n }\n }\n\n private onProgress(opts: ProgressEvent): void {\n const lengthComputable = opts.total\n const sameStep = opts.step === this.currentStep\n const percent = getPercentage(opts)\n\n if (lengthComputable && opts.total === opts.current && this.spinInterval) {\n clearInterval(this.spinInterval)\n this.spinInterval = null\n }\n\n if (sameStep && !lengthComputable) {\n return\n }\n\n if (sameStep) {\n if (this.stepStart) {\n const timeSpent = prettyMs(Date.now() - this.stepStart, {secondsDecimalDigits: 2})\n if (this.currentProgress) {\n this.currentProgress.text = `${percent}${opts.step} (${timeSpent})`\n this.currentProgress.render()\n }\n }\n return\n }\n\n // Moved to a new step\n const prevStep = this.currentStep\n const prevStepStart = this.stepStart\n this.stepStart = Date.now()\n this.currentStep = opts.step\n\n if (this.spinInterval) {\n clearInterval(this.spinInterval)\n this.spinInterval = null\n }\n\n if (this.currentProgress && this.currentProgress.succeed && prevStepStart) {\n const timeSpent = prettyMs(Date.now() - prevStepStart, {\n secondsDecimalDigits: 2,\n })\n this.currentProgress.text = `[100%] ${prevStep} (${timeSpent})`\n this.currentProgress.succeed()\n }\n\n this.currentProgress = spinner(`[0%] ${opts.step} (0.00s)`).start()\n\n if (!lengthComputable) {\n this.spinInterval = setInterval(() => {\n if (this.stepStart && this.currentProgress) {\n const timeSpent = prettyMs(Date.now() - this.stepStart, {\n secondsDecimalDigits: 2,\n })\n this.currentProgress.text = `${percent}${opts.step} (${timeSpent})`\n this.currentProgress.render()\n }\n }, 60)\n }\n }\n\n private printWarnings(warnings: Array<{message: string; type?: string; url?: string}>): void {\n const assetFails = warnings.filter((warn) => warn.type === 'asset')\n\n if (assetFails.length === 0) {\n return\n }\n\n this.output.warn(\n `Failed to import the following ${assetFails.length > 1 ? 'assets' : 'asset'}:`,\n )\n\n for (const warning of assetFails) {\n if (warning.url) {\n this.output.warn(` ${warning.url}`)\n }\n }\n }\n}\n"],"names":["fs","path","Args","Flags","exitCodes","getProjectCliClient","SanityCommand","subdebug","createRequester","spinner","sanityImport","prettyMs","NEW_DATASET_VALUE","promptForDataset","promptForDatasetName","promptForProject","createDataset","listDatasets","getDatasetFlag","getProjectIdFlag","importDebug","getAssetsBase","source","test","undefined","fileStats","statSync","sourceIsFolder","isDirectory","dirname","getUriStream","uri","request","middleware","promise","onlyBody","response","stream","url","body","err","Error","message","cause","getPercentage","opts","total","percent","Math","floor","current","ImportDatasetCommand","args","string","description","required","targetDataset","examples","command","flags","boolean","default","integer","semantics","missing","exclusive","project","deprecated","to","hidden","replace","token","char","env","hiddenAliases","currentProgress","currentStep","spinInterval","stepStart","getStream","process","stdin","createReadStream","run","parse","allowAssetsInDifferentDataset","allowFailingAssets","allowReplacementCharacters","allowSystemDocuments","assetConcurrency","dataset","datasetFlag","replaceAssets","skipCrossDatasetReferences","projectId","getProjectId","deprecatedFlagName","fallback","targetDatasetArg","output","warn","isUnattended","error","exit","USAGE_ERROR","datasets","allowCreation","newDatasetName","datasetName","String","operation","releasesOperation","client","apiVersion","requireUser","assetsBase","importOptions","onProgress","bind","tag","targetProjectId","numDocs","warnings","timeSpent","Date","now","secondsDecimalDigits","clearInterval","text","succeed","log","printWarnings","fail","name","stack","lengthComputable","sameStep","step","render","prevStep","prevStepStart","start","setInterval","assetFails","filter","type","length","warning"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { Args } from '@oclif/core';
2
- import { SanityCommand, subdebug } from '@sanity/cli-core';
2
+ import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
3
3
  import { validateDatasetName } from '../../../actions/dataset/validateDatasetName.js';
4
4
  import { promptForProject } from '../../../prompts/promptForProject.js';
5
5
  import { listDatasets } from '../../../services/datasets.js';
@@ -44,7 +44,7 @@ export class DatasetVisibilityGetCommand extends SanityCommand {
44
44
  const dsError = validateDatasetName(dataset);
45
45
  if (dsError) {
46
46
  this.error(dsError, {
47
- exit: 1
47
+ exit: exitCodes.USAGE_ERROR
48
48
  });
49
49
  }
50
50
  let current;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/commands/datasets/visibility/get.ts"],"sourcesContent":["import {Args} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {validateDatasetName} from '../../../actions/dataset/validateDatasetName.js'\nimport {promptForProject} from '../../../prompts/promptForProject.js'\nimport {listDatasets} from '../../../services/datasets.js'\nimport {getProjectIdFlag} from '../../../util/sharedFlags.js'\n\nconst getDebug = subdebug('dataset:visibility:get')\n\nexport class DatasetVisibilityGetCommand extends SanityCommand<typeof DatasetVisibilityGetCommand> {\n static override args = {\n dataset: Args.string({\n description: 'The name of the dataset to get visibility for',\n required: true,\n }),\n }\n\n static override description = 'Get the visibility of a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset',\n description: 'Check the visibility of a dataset',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to get dataset visibility for',\n semantics: 'override',\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:visibility:get']\n\n public async run(): Promise<void> {\n const {args} = await this.parse(DatasetVisibilityGetCommand)\n const {dataset} = args\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'read', permission: 'sanity.project.datasets'}],\n }),\n })\n\n const dsError = validateDatasetName(dataset)\n if (dsError) {\n this.error(dsError, {exit: 1})\n }\n\n let current\n try {\n const datasets = await listDatasets(projectId)\n current = datasets.find((curr: {name: string}) => curr.name === dataset)\n } catch (error) {\n getDebug(`Error listing datasets`, error)\n this.error(\n `Failed to list datasets: ${error instanceof Error ? error.message : String(error)}`,\n {exit: 1},\n )\n }\n\n if (!current) {\n this.error(`Dataset not found: ${dataset}`, {exit: 1})\n }\n\n this.log(current.aclMode)\n }\n}\n"],"names":["Args","SanityCommand","subdebug","validateDatasetName","promptForProject","listDatasets","getProjectIdFlag","getDebug","DatasetVisibilityGetCommand","args","dataset","string","description","required","examples","command","flags","semantics","hiddenAliases","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","dsError","error","exit","current","datasets","find","curr","name","Error","message","String","log","aclMode"],"mappings":"AAAA,SAAQA,IAAI,QAAO,cAAa;AAChC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAExD,SAAQC,mBAAmB,QAAO,kDAAiD;AACnF,SAAQC,gBAAgB,QAAO,uCAAsC;AACrE,SAAQC,YAAY,QAAO,gCAA+B;AAC1D,SAAQC,gBAAgB,QAAO,+BAA8B;AAE7D,MAAMC,WAAWL,SAAS;AAE1B,OAAO,MAAMM,oCAAoCP;IAC/C,OAAgBQ,OAAO;QACrBC,SAASV,KAAKW,MAAM,CAAC;YACnBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,kCAAiC;IAE/D,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtB,GAAGV,iBAAiB;YAClBM,aAAa;YACbK,WAAW;QACb,EAAE;IACJ,EAAC;IAED,OAAgBC,gBAA0B;QAAC;KAAyB,CAAA;IAEpE,MAAaC,MAAqB;QAChC,MAAM,EAACV,IAAI,EAAC,GAAG,MAAM,IAAI,CAACW,KAAK,CAACZ;QAChC,MAAM,EAACE,OAAO,EAAC,GAAGD;QAElB,MAAMY,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,UAAU,IACRnB,iBAAiB;oBACfoB,qBAAqB;wBAAC;4BAACC,OAAO;4BAAQC,YAAY;wBAAyB;qBAAE;gBAC/E;QACJ;QAEA,MAAMC,UAAUxB,oBAAoBO;QACpC,IAAIiB,SAAS;YACX,IAAI,CAACC,KAAK,CAACD,SAAS;gBAACE,MAAM;YAAC;QAC9B;QAEA,IAAIC;QACJ,IAAI;YACF,MAAMC,WAAW,MAAM1B,aAAagB;YACpCS,UAAUC,SAASC,IAAI,CAAC,CAACC,OAAyBA,KAAKC,IAAI,KAAKxB;QAClE,EAAE,OAAOkB,OAAO;YACdrB,SAAS,CAAC,sBAAsB,CAAC,EAAEqB;YACnC,IAAI,CAACA,KAAK,CACR,CAAC,yBAAyB,EAAEA,iBAAiBO,QAAQP,MAAMQ,OAAO,GAAGC,OAAOT,QAAQ,EACpF;gBAACC,MAAM;YAAC;QAEZ;QAEA,IAAI,CAACC,SAAS;YACZ,IAAI,CAACF,KAAK,CAAC,CAAC,mBAAmB,EAAElB,SAAS,EAAE;gBAACmB,MAAM;YAAC;QACtD;QAEA,IAAI,CAACS,GAAG,CAACR,QAAQS,OAAO;IAC1B;AACF"}
1
+ {"version":3,"sources":["../../../../src/commands/datasets/visibility/get.ts"],"sourcesContent":["import {Args} from '@oclif/core'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {validateDatasetName} from '../../../actions/dataset/validateDatasetName.js'\nimport {promptForProject} from '../../../prompts/promptForProject.js'\nimport {listDatasets} from '../../../services/datasets.js'\nimport {getProjectIdFlag} from '../../../util/sharedFlags.js'\n\nconst getDebug = subdebug('dataset:visibility:get')\n\nexport class DatasetVisibilityGetCommand extends SanityCommand<typeof DatasetVisibilityGetCommand> {\n static override args = {\n dataset: Args.string({\n description: 'The name of the dataset to get visibility for',\n required: true,\n }),\n }\n\n static override description = 'Get the visibility of a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset',\n description: 'Check the visibility of a dataset',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to get dataset visibility for',\n semantics: 'override',\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:visibility:get']\n\n public async run(): Promise<void> {\n const {args} = await this.parse(DatasetVisibilityGetCommand)\n const {dataset} = args\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'read', permission: 'sanity.project.datasets'}],\n }),\n })\n\n const dsError = validateDatasetName(dataset)\n if (dsError) {\n this.error(dsError, {exit: exitCodes.USAGE_ERROR})\n }\n\n let current\n try {\n const datasets = await listDatasets(projectId)\n current = datasets.find((curr: {name: string}) => curr.name === dataset)\n } catch (error) {\n getDebug(`Error listing datasets`, error)\n this.error(\n `Failed to list datasets: ${error instanceof Error ? error.message : String(error)}`,\n {exit: 1},\n )\n }\n\n if (!current) {\n this.error(`Dataset not found: ${dataset}`, {exit: 1})\n }\n\n this.log(current.aclMode)\n }\n}\n"],"names":["Args","exitCodes","SanityCommand","subdebug","validateDatasetName","promptForProject","listDatasets","getProjectIdFlag","getDebug","DatasetVisibilityGetCommand","args","dataset","string","description","required","examples","command","flags","semantics","hiddenAliases","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","dsError","error","exit","USAGE_ERROR","current","datasets","find","curr","name","Error","message","String","log","aclMode"],"mappings":"AAAA,SAAQA,IAAI,QAAO,cAAa;AAChC,SAAQC,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAEnE,SAAQC,mBAAmB,QAAO,kDAAiD;AACnF,SAAQC,gBAAgB,QAAO,uCAAsC;AACrE,SAAQC,YAAY,QAAO,gCAA+B;AAC1D,SAAQC,gBAAgB,QAAO,+BAA8B;AAE7D,MAAMC,WAAWL,SAAS;AAE1B,OAAO,MAAMM,oCAAoCP;IAC/C,OAAgBQ,OAAO;QACrBC,SAASX,KAAKY,MAAM,CAAC;YACnBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,kCAAiC;IAE/D,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtB,GAAGV,iBAAiB;YAClBM,aAAa;YACbK,WAAW;QACb,EAAE;IACJ,EAAC;IAED,OAAgBC,gBAA0B;QAAC;KAAyB,CAAA;IAEpE,MAAaC,MAAqB;QAChC,MAAM,EAACV,IAAI,EAAC,GAAG,MAAM,IAAI,CAACW,KAAK,CAACZ;QAChC,MAAM,EAACE,OAAO,EAAC,GAAGD;QAElB,MAAMY,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,UAAU,IACRnB,iBAAiB;oBACfoB,qBAAqB;wBAAC;4BAACC,OAAO;4BAAQC,YAAY;wBAAyB;qBAAE;gBAC/E;QACJ;QAEA,MAAMC,UAAUxB,oBAAoBO;QACpC,IAAIiB,SAAS;YACX,IAAI,CAACC,KAAK,CAACD,SAAS;gBAACE,MAAM7B,UAAU8B,WAAW;YAAA;QAClD;QAEA,IAAIC;QACJ,IAAI;YACF,MAAMC,WAAW,MAAM3B,aAAagB;YACpCU,UAAUC,SAASC,IAAI,CAAC,CAACC,OAAyBA,KAAKC,IAAI,KAAKzB;QAClE,EAAE,OAAOkB,OAAO;YACdrB,SAAS,CAAC,sBAAsB,CAAC,EAAEqB;YACnC,IAAI,CAACA,KAAK,CACR,CAAC,yBAAyB,EAAEA,iBAAiBQ,QAAQR,MAAMS,OAAO,GAAGC,OAAOV,QAAQ,EACpF;gBAACC,MAAM;YAAC;QAEZ;QAEA,IAAI,CAACE,SAAS;YACZ,IAAI,CAACH,KAAK,CAAC,CAAC,mBAAmB,EAAElB,SAAS,EAAE;gBAACmB,MAAM;YAAC;QACtD;QAEA,IAAI,CAACU,GAAG,CAACR,QAAQS,OAAO;IAC1B;AACF"}
@@ -1,5 +1,5 @@
1
1
  import { Args } from '@oclif/core';
2
- import { SanityCommand, subdebug } from '@sanity/cli-core';
2
+ import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
3
3
  import { validateDatasetName } from '../../../actions/dataset/validateDatasetName.js';
4
4
  import { promptForProject } from '../../../prompts/promptForProject.js';
5
5
  import { editDatasetAcl, listDatasets } from '../../../services/datasets.js';
@@ -60,7 +60,7 @@ export class DatasetVisibilitySetCommand extends SanityCommand {
60
60
  const dsError = validateDatasetName(dataset);
61
61
  if (dsError) {
62
62
  this.error(dsError, {
63
- exit: 1
63
+ exit: exitCodes.USAGE_ERROR
64
64
  });
65
65
  }
66
66
  let datasets;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/commands/datasets/visibility/set.ts"],"sourcesContent":["import {Args} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {DatasetsResponse} from '@sanity/client'\n\nimport {validateDatasetName} from '../../../actions/dataset/validateDatasetName.js'\nimport {promptForProject} from '../../../prompts/promptForProject.js'\nimport {editDatasetAcl, listDatasets} from '../../../services/datasets.js'\nimport {getProjectIdFlag} from '../../../util/sharedFlags.js'\n\nconst setDatasetVisibilityDebug = subdebug('dataset:visibility:set')\n\nexport class DatasetVisibilitySetCommand extends SanityCommand<typeof DatasetVisibilitySetCommand> {\n static override args = {\n dataset: Args.string({\n description: 'The name of the dataset to set visibility for',\n required: true,\n }),\n mode: Args.string({\n description: 'The visibility mode to set',\n options: ['public', 'private'],\n required: true,\n }),\n }\n\n static override description = 'Set the visibility of a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset private',\n description: 'Make a dataset private',\n },\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset public',\n description: 'Make a dataset public',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to set dataset visibility for',\n semantics: 'override',\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:visibility:set']\n\n public async run(): Promise<void> {\n const {args} = await this.parse(DatasetVisibilitySetCommand)\n const {dataset, mode} = 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 const dsError = validateDatasetName(dataset)\n if (dsError) {\n this.error(dsError, {exit: 1})\n }\n\n let datasets: DatasetsResponse\n\n try {\n datasets = await listDatasets(projectId)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n setDatasetVisibilityDebug(`Failed to list datasets: ${message}`, error)\n this.error(`Failed to list datasets: ${message}`, {exit: 1})\n }\n\n const current = datasets.find((curr: {name: string}) => curr.name === dataset)\n\n if (!current) {\n this.error(`Dataset \"${dataset}\" not found`, {exit: 1})\n }\n\n if (current.aclMode === mode) {\n this.log(`Dataset already in \"${mode}\" mode`)\n return\n }\n\n if (mode === 'private') {\n this.log(\n 'Please note that while documents are private, assets (files and images) are still public',\n )\n }\n\n try {\n await editDatasetAcl({\n aclMode: mode as 'private' | 'public',\n datasetName: dataset,\n projectId,\n })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n setDatasetVisibilityDebug(`Failed to edit dataset: ${message}`, error)\n this.error(`Failed to edit dataset: ${message}`, {exit: 1})\n }\n this.log('Dataset visibility changed')\n }\n}\n"],"names":["Args","SanityCommand","subdebug","validateDatasetName","promptForProject","editDatasetAcl","listDatasets","getProjectIdFlag","setDatasetVisibilityDebug","DatasetVisibilitySetCommand","args","dataset","string","description","required","mode","options","examples","command","flags","semantics","hiddenAliases","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","dsError","error","exit","datasets","message","Error","String","current","find","curr","name","aclMode","log","datasetName"],"mappings":"AAAA,SAAQA,IAAI,QAAO,cAAa;AAChC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAGxD,SAAQC,mBAAmB,QAAO,kDAAiD;AACnF,SAAQC,gBAAgB,QAAO,uCAAsC;AACrE,SAAQC,cAAc,EAAEC,YAAY,QAAO,gCAA+B;AAC1E,SAAQC,gBAAgB,QAAO,+BAA8B;AAE7D,MAAMC,4BAA4BN,SAAS;AAE3C,OAAO,MAAMO,oCAAoCR;IAC/C,OAAgBS,OAAO;QACrBC,SAASX,KAAKY,MAAM,CAAC;YACnBC,aAAa;YACbC,UAAU;QACZ;QACAC,MAAMf,KAAKY,MAAM,CAAC;YAChBC,aAAa;YACbG,SAAS;gBAAC;gBAAU;aAAU;YAC9BF,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,kCAAiC;IAE/D,OAAgBI,WAAW;QACzB;YACEC,SAAS;YACTL,aAAa;QACf;QACA;YACEK,SAAS;YACTL,aAAa;QACf;KACD,CAAA;IAED,OAAgBM,QAAQ;QACtB,GAAGZ,iBAAiB;YAClBM,aAAa;YACbO,WAAW;QACb,EAAE;IACJ,EAAC;IAED,OAAgBC,gBAA0B;QAAC;KAAyB,CAAA;IAEpE,MAAaC,MAAqB;QAChC,MAAM,EAACZ,IAAI,EAAC,GAAG,MAAM,IAAI,CAACa,KAAK,CAACd;QAChC,MAAM,EAACE,OAAO,EAAEI,IAAI,EAAC,GAAGL;QAExB,MAAMc,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,UAAU,IACRtB,iBAAiB;oBACfuB,qBAAqB;wBACnB;4BAACC,OAAO;4BAAQC,YAAY;wBAAyB;wBACrD;4BAACD,OAAO;4BAAUC,YAAY;wBAAyB;qBACxD;gBACH;QACJ;QAEA,MAAMC,UAAU3B,oBAAoBQ;QACpC,IAAImB,SAAS;YACX,IAAI,CAACC,KAAK,CAACD,SAAS;gBAACE,MAAM;YAAC;QAC9B;QAEA,IAAIC;QAEJ,IAAI;YACFA,WAAW,MAAM3B,aAAakB;QAChC,EAAE,OAAOO,OAAO;YACd,MAAMG,UAAUH,iBAAiBI,QAAQJ,MAAMG,OAAO,GAAGE,OAAOL;YAChEvB,0BAA0B,CAAC,yBAAyB,EAAE0B,SAAS,EAAEH;YACjE,IAAI,CAACA,KAAK,CAAC,CAAC,yBAAyB,EAAEG,SAAS,EAAE;gBAACF,MAAM;YAAC;QAC5D;QAEA,MAAMK,UAAUJ,SAASK,IAAI,CAAC,CAACC,OAAyBA,KAAKC,IAAI,KAAK7B;QAEtE,IAAI,CAAC0B,SAAS;YACZ,IAAI,CAACN,KAAK,CAAC,CAAC,SAAS,EAAEpB,QAAQ,WAAW,CAAC,EAAE;gBAACqB,MAAM;YAAC;QACvD;QAEA,IAAIK,QAAQI,OAAO,KAAK1B,MAAM;YAC5B,IAAI,CAAC2B,GAAG,CAAC,CAAC,oBAAoB,EAAE3B,KAAK,MAAM,CAAC;YAC5C;QACF;QAEA,IAAIA,SAAS,WAAW;YACtB,IAAI,CAAC2B,GAAG,CACN;QAEJ;QAEA,IAAI;YACF,MAAMrC,eAAe;gBACnBoC,SAAS1B;gBACT4B,aAAahC;gBACba;YACF;QACF,EAAE,OAAOO,OAAO;YACd,MAAMG,UAAUH,iBAAiBI,QAAQJ,MAAMG,OAAO,GAAGE,OAAOL;YAChEvB,0BAA0B,CAAC,wBAAwB,EAAE0B,SAAS,EAAEH;YAChE,IAAI,CAACA,KAAK,CAAC,CAAC,wBAAwB,EAAEG,SAAS,EAAE;gBAACF,MAAM;YAAC;QAC3D;QACA,IAAI,CAACU,GAAG,CAAC;IACX;AACF"}
1
+ {"version":3,"sources":["../../../../src/commands/datasets/visibility/set.ts"],"sourcesContent":["import {Args} from '@oclif/core'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {DatasetsResponse} from '@sanity/client'\n\nimport {validateDatasetName} from '../../../actions/dataset/validateDatasetName.js'\nimport {promptForProject} from '../../../prompts/promptForProject.js'\nimport {editDatasetAcl, listDatasets} from '../../../services/datasets.js'\nimport {getProjectIdFlag} from '../../../util/sharedFlags.js'\n\nconst setDatasetVisibilityDebug = subdebug('dataset:visibility:set')\n\nexport class DatasetVisibilitySetCommand extends SanityCommand<typeof DatasetVisibilitySetCommand> {\n static override args = {\n dataset: Args.string({\n description: 'The name of the dataset to set visibility for',\n required: true,\n }),\n mode: Args.string({\n description: 'The visibility mode to set',\n options: ['public', 'private'],\n required: true,\n }),\n }\n\n static override description = 'Set the visibility of a dataset'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset private',\n description: 'Make a dataset private',\n },\n {\n command: '<%= config.bin %> <%= command.id %> my-dataset public',\n description: 'Make a dataset public',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to set dataset visibility for',\n semantics: 'override',\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:visibility:set']\n\n public async run(): Promise<void> {\n const {args} = await this.parse(DatasetVisibilitySetCommand)\n const {dataset, mode} = 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 const dsError = validateDatasetName(dataset)\n if (dsError) {\n this.error(dsError, {exit: exitCodes.USAGE_ERROR})\n }\n\n let datasets: DatasetsResponse\n\n try {\n datasets = await listDatasets(projectId)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n setDatasetVisibilityDebug(`Failed to list datasets: ${message}`, error)\n this.error(`Failed to list datasets: ${message}`, {exit: 1})\n }\n\n const current = datasets.find((curr: {name: string}) => curr.name === dataset)\n\n if (!current) {\n this.error(`Dataset \"${dataset}\" not found`, {exit: 1})\n }\n\n if (current.aclMode === mode) {\n this.log(`Dataset already in \"${mode}\" mode`)\n return\n }\n\n if (mode === 'private') {\n this.log(\n 'Please note that while documents are private, assets (files and images) are still public',\n )\n }\n\n try {\n await editDatasetAcl({\n aclMode: mode as 'private' | 'public',\n datasetName: dataset,\n projectId,\n })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n setDatasetVisibilityDebug(`Failed to edit dataset: ${message}`, error)\n this.error(`Failed to edit dataset: ${message}`, {exit: 1})\n }\n this.log('Dataset visibility changed')\n }\n}\n"],"names":["Args","exitCodes","SanityCommand","subdebug","validateDatasetName","promptForProject","editDatasetAcl","listDatasets","getProjectIdFlag","setDatasetVisibilityDebug","DatasetVisibilitySetCommand","args","dataset","string","description","required","mode","options","examples","command","flags","semantics","hiddenAliases","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","dsError","error","exit","USAGE_ERROR","datasets","message","Error","String","current","find","curr","name","aclMode","log","datasetName"],"mappings":"AAAA,SAAQA,IAAI,QAAO,cAAa;AAChC,SAAQC,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAGnE,SAAQC,mBAAmB,QAAO,kDAAiD;AACnF,SAAQC,gBAAgB,QAAO,uCAAsC;AACrE,SAAQC,cAAc,EAAEC,YAAY,QAAO,gCAA+B;AAC1E,SAAQC,gBAAgB,QAAO,+BAA8B;AAE7D,MAAMC,4BAA4BN,SAAS;AAE3C,OAAO,MAAMO,oCAAoCR;IAC/C,OAAgBS,OAAO;QACrBC,SAASZ,KAAKa,MAAM,CAAC;YACnBC,aAAa;YACbC,UAAU;QACZ;QACAC,MAAMhB,KAAKa,MAAM,CAAC;YAChBC,aAAa;YACbG,SAAS;gBAAC;gBAAU;aAAU;YAC9BF,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,kCAAiC;IAE/D,OAAgBI,WAAW;QACzB;YACEC,SAAS;YACTL,aAAa;QACf;QACA;YACEK,SAAS;YACTL,aAAa;QACf;KACD,CAAA;IAED,OAAgBM,QAAQ;QACtB,GAAGZ,iBAAiB;YAClBM,aAAa;YACbO,WAAW;QACb,EAAE;IACJ,EAAC;IAED,OAAgBC,gBAA0B;QAAC;KAAyB,CAAA;IAEpE,MAAaC,MAAqB;QAChC,MAAM,EAACZ,IAAI,EAAC,GAAG,MAAM,IAAI,CAACa,KAAK,CAACd;QAChC,MAAM,EAACE,OAAO,EAAEI,IAAI,EAAC,GAAGL;QAExB,MAAMc,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,UAAU,IACRtB,iBAAiB;oBACfuB,qBAAqB;wBACnB;4BAACC,OAAO;4BAAQC,YAAY;wBAAyB;wBACrD;4BAACD,OAAO;4BAAUC,YAAY;wBAAyB;qBACxD;gBACH;QACJ;QAEA,MAAMC,UAAU3B,oBAAoBQ;QACpC,IAAImB,SAAS;YACX,IAAI,CAACC,KAAK,CAACD,SAAS;gBAACE,MAAMhC,UAAUiC,WAAW;YAAA;QAClD;QAEA,IAAIC;QAEJ,IAAI;YACFA,WAAW,MAAM5B,aAAakB;QAChC,EAAE,OAAOO,OAAO;YACd,MAAMI,UAAUJ,iBAAiBK,QAAQL,MAAMI,OAAO,GAAGE,OAAON;YAChEvB,0BAA0B,CAAC,yBAAyB,EAAE2B,SAAS,EAAEJ;YACjE,IAAI,CAACA,KAAK,CAAC,CAAC,yBAAyB,EAAEI,SAAS,EAAE;gBAACH,MAAM;YAAC;QAC5D;QAEA,MAAMM,UAAUJ,SAASK,IAAI,CAAC,CAACC,OAAyBA,KAAKC,IAAI,KAAK9B;QAEtE,IAAI,CAAC2B,SAAS;YACZ,IAAI,CAACP,KAAK,CAAC,CAAC,SAAS,EAAEpB,QAAQ,WAAW,CAAC,EAAE;gBAACqB,MAAM;YAAC;QACvD;QAEA,IAAIM,QAAQI,OAAO,KAAK3B,MAAM;YAC5B,IAAI,CAAC4B,GAAG,CAAC,CAAC,oBAAoB,EAAE5B,KAAK,MAAM,CAAC;YAC5C;QACF;QAEA,IAAIA,SAAS,WAAW;YACtB,IAAI,CAAC4B,GAAG,CACN;QAEJ;QAEA,IAAI;YACF,MAAMtC,eAAe;gBACnBqC,SAAS3B;gBACT6B,aAAajC;gBACba;YACF;QACF,EAAE,OAAOO,OAAO;YACd,MAAMI,UAAUJ,iBAAiBK,QAAQL,MAAMI,OAAO,GAAGE,OAAON;YAChEvB,0BAA0B,CAAC,wBAAwB,EAAE2B,SAAS,EAAEJ;YAChE,IAAI,CAACA,KAAK,CAAC,CAAC,wBAAwB,EAAEI,SAAS,EAAE;gBAACH,MAAM;YAAC;QAC3D;QACA,IAAI,CAACW,GAAG,CAAC;IACX;AACF"}
@@ -1,5 +1,5 @@
1
1
  import { Args, Flags } from '@oclif/core';
2
- import { SanityCommand } from '@sanity/cli-core';
2
+ import { exitCodes, SanityCommand } from '@sanity/cli-core';
3
3
  import open from 'open';
4
4
  import { readDoc } from '../../services/docs.js';
5
5
  function isSanityHostname(hostname) {
@@ -70,12 +70,12 @@ export class DocsReadCommand extends SanityCommand {
70
70
  const { readPath, webPath } = parseDocsInput(input);
71
71
  if (!readPath.startsWith('/')) {
72
72
  this.error('Invalid path or URL. Expected a Sanity docs path or URL.\nExamples:\n /docs/studio/installation\n https://www.sanity.io/docs/studio/installation', {
73
- exit: 1
73
+ exit: exitCodes.USAGE_ERROR
74
74
  });
75
75
  }
76
76
  if (readPath.includes('..') || !readPath.startsWith('/docs/')) {
77
77
  this.error('Invalid path. Must be a valid Sanity docs path starting with /docs/\nExample: /docs/studio/installation', {
78
- exit: 1
78
+ exit: exitCodes.USAGE_ERROR
79
79
  });
80
80
  }
81
81
  if (web) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/docs/read.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {SanityCommand} from '@sanity/cli-core'\nimport open from 'open'\n\nimport {readDoc} from '../../services/docs.js'\n\ninterface DocsInput {\n readPath: string\n webPath: string\n}\n\nfunction isSanityHostname(hostname: string): boolean {\n return hostname === 'sanity.io' || hostname.endsWith('.sanity.io')\n}\n\nfunction parseDocsInput(input: string): DocsInput {\n try {\n const url = new URL(input)\n\n if (isSanityHostname(url.hostname)) {\n return {\n readPath: url.pathname,\n webPath: `${url.pathname}${url.search}${url.hash}`,\n }\n }\n } catch {\n // Input is not an absolute URL.\n }\n\n if (input.startsWith('/') && !input.startsWith('//')) {\n const url = new URL(input, 'https://www.sanity.io')\n\n return {\n readPath: url.pathname,\n webPath: `${url.pathname}${url.search}${url.hash}`,\n }\n }\n\n return {\n readPath: input,\n webPath: input,\n }\n}\n\nexport class DocsReadCommand extends SanityCommand<typeof DocsReadCommand> {\n static override args = {\n path: Args.string({\n description: 'Path or URL to article, found in search results and docs content as links',\n required: true,\n }),\n }\n\n static override description = 'Read an article in terminal'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> /docs/studio/installation',\n description: 'Read as markdown in terminal',\n },\n {\n command: '<%= config.bin %> <%= command.id %> https://www.sanity.io/docs/studio/installation',\n description: 'Read using full URL',\n },\n {\n command: '<%= config.bin %> <%= command.id %> /docs/studio/installation --web',\n description: 'Open in web browser',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> https://www.sanity.io/docs/studio/installation -w',\n description: 'Open using full URL in web browser',\n },\n ]\n\n static override flags = {\n web: Flags.boolean({\n aliases: ['w'],\n description: 'Open in a web browser',\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(DocsReadCommand)\n const {path: input} = args\n const {web} = flags\n\n const {readPath, webPath} = parseDocsInput(input)\n\n if (!readPath.startsWith('/')) {\n this.error(\n 'Invalid path or URL. Expected a Sanity docs path or URL.\\nExamples:\\n /docs/studio/installation\\n https://www.sanity.io/docs/studio/installation',\n {\n exit: 1,\n },\n )\n }\n\n if (readPath.includes('..') || !readPath.startsWith('/docs/')) {\n this.error(\n 'Invalid path. Must be a valid Sanity docs path starting with /docs/\\nExample: /docs/studio/installation',\n {\n exit: 1,\n },\n )\n }\n\n if (web) {\n const url = `https://www.sanity.io${webPath}`\n this.log(`Opening ${url}`)\n await open(url)\n return\n }\n\n this.log(`Reading article: ${readPath}`)\n\n try {\n const content = await readDoc({path: readPath})\n this.log('\\n---\\n')\n this.log(content)\n } catch (error) {\n this.error(error instanceof Error ? error.message : 'Failed to read article', {\n exit: 1,\n })\n }\n }\n}\n"],"names":["Args","Flags","SanityCommand","open","readDoc","isSanityHostname","hostname","endsWith","parseDocsInput","input","url","URL","readPath","pathname","webPath","search","hash","startsWith","DocsReadCommand","args","path","string","description","required","examples","command","flags","web","boolean","aliases","run","parse","error","exit","includes","log","content","Error","message"],"mappings":"AAAA,SAAQA,IAAI,EAAEC,KAAK,QAAO,cAAa;AACvC,SAAQC,aAAa,QAAO,mBAAkB;AAC9C,OAAOC,UAAU,OAAM;AAEvB,SAAQC,OAAO,QAAO,yBAAwB;AAO9C,SAASC,iBAAiBC,QAAgB;IACxC,OAAOA,aAAa,eAAeA,SAASC,QAAQ,CAAC;AACvD;AAEA,SAASC,eAAeC,KAAa;IACnC,IAAI;QACF,MAAMC,MAAM,IAAIC,IAAIF;QAEpB,IAAIJ,iBAAiBK,IAAIJ,QAAQ,GAAG;YAClC,OAAO;gBACLM,UAAUF,IAAIG,QAAQ;gBACtBC,SAAS,GAAGJ,IAAIG,QAAQ,GAAGH,IAAIK,MAAM,GAAGL,IAAIM,IAAI,EAAE;YACpD;QACF;IACF,EAAE,OAAM;IACN,gCAAgC;IAClC;IAEA,IAAIP,MAAMQ,UAAU,CAAC,QAAQ,CAACR,MAAMQ,UAAU,CAAC,OAAO;QACpD,MAAMP,MAAM,IAAIC,IAAIF,OAAO;QAE3B,OAAO;YACLG,UAAUF,IAAIG,QAAQ;YACtBC,SAAS,GAAGJ,IAAIG,QAAQ,GAAGH,IAAIK,MAAM,GAAGL,IAAIM,IAAI,EAAE;QACpD;IACF;IAEA,OAAO;QACLJ,UAAUH;QACVK,SAASL;IACX;AACF;AAEA,OAAO,MAAMS,wBAAwBhB;IACnC,OAAgBiB,OAAO;QACrBC,MAAMpB,KAAKqB,MAAM,CAAC;YAChBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,8BAA6B;IAE3D,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SACE;YACFH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtBC,KAAK1B,MAAM2B,OAAO,CAAC;YACjBC,SAAS;gBAAC;aAAI;YACdP,aAAa;QACf;IACF,EAAC;IAED,MAAaQ,MAAqB;QAChC,MAAM,EAACX,IAAI,EAAEO,KAAK,EAAC,GAAG,MAAM,IAAI,CAACK,KAAK,CAACb;QACvC,MAAM,EAACE,MAAMX,KAAK,EAAC,GAAGU;QACtB,MAAM,EAACQ,GAAG,EAAC,GAAGD;QAEd,MAAM,EAACd,QAAQ,EAAEE,OAAO,EAAC,GAAGN,eAAeC;QAE3C,IAAI,CAACG,SAASK,UAAU,CAAC,MAAM;YAC7B,IAAI,CAACe,KAAK,CACR,sJACA;gBACEC,MAAM;YACR;QAEJ;QAEA,IAAIrB,SAASsB,QAAQ,CAAC,SAAS,CAACtB,SAASK,UAAU,CAAC,WAAW;YAC7D,IAAI,CAACe,KAAK,CACR,2GACA;gBACEC,MAAM;YACR;QAEJ;QAEA,IAAIN,KAAK;YACP,MAAMjB,MAAM,CAAC,qBAAqB,EAAEI,SAAS;YAC7C,IAAI,CAACqB,GAAG,CAAC,CAAC,QAAQ,EAAEzB,KAAK;YACzB,MAAMP,KAAKO;YACX;QACF;QAEA,IAAI,CAACyB,GAAG,CAAC,CAAC,iBAAiB,EAAEvB,UAAU;QAEvC,IAAI;YACF,MAAMwB,UAAU,MAAMhC,QAAQ;gBAACgB,MAAMR;YAAQ;YAC7C,IAAI,CAACuB,GAAG,CAAC;YACT,IAAI,CAACA,GAAG,CAACC;QACX,EAAE,OAAOJ,OAAO;YACd,IAAI,CAACA,KAAK,CAACA,iBAAiBK,QAAQL,MAAMM,OAAO,GAAG,0BAA0B;gBAC5EL,MAAM;YACR;QACF;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/commands/docs/read.ts"],"sourcesContent":["import {Args, Flags} from '@oclif/core'\nimport {exitCodes, SanityCommand} from '@sanity/cli-core'\nimport open from 'open'\n\nimport {readDoc} from '../../services/docs.js'\n\ninterface DocsInput {\n readPath: string\n webPath: string\n}\n\nfunction isSanityHostname(hostname: string): boolean {\n return hostname === 'sanity.io' || hostname.endsWith('.sanity.io')\n}\n\nfunction parseDocsInput(input: string): DocsInput {\n try {\n const url = new URL(input)\n\n if (isSanityHostname(url.hostname)) {\n return {\n readPath: url.pathname,\n webPath: `${url.pathname}${url.search}${url.hash}`,\n }\n }\n } catch {\n // Input is not an absolute URL.\n }\n\n if (input.startsWith('/') && !input.startsWith('//')) {\n const url = new URL(input, 'https://www.sanity.io')\n\n return {\n readPath: url.pathname,\n webPath: `${url.pathname}${url.search}${url.hash}`,\n }\n }\n\n return {\n readPath: input,\n webPath: input,\n }\n}\n\nexport class DocsReadCommand extends SanityCommand<typeof DocsReadCommand> {\n static override args = {\n path: Args.string({\n description: 'Path or URL to article, found in search results and docs content as links',\n required: true,\n }),\n }\n\n static override description = 'Read an article in terminal'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> /docs/studio/installation',\n description: 'Read as markdown in terminal',\n },\n {\n command: '<%= config.bin %> <%= command.id %> https://www.sanity.io/docs/studio/installation',\n description: 'Read using full URL',\n },\n {\n command: '<%= config.bin %> <%= command.id %> /docs/studio/installation --web',\n description: 'Open in web browser',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> https://www.sanity.io/docs/studio/installation -w',\n description: 'Open using full URL in web browser',\n },\n ]\n\n static override flags = {\n web: Flags.boolean({\n aliases: ['w'],\n description: 'Open in a web browser',\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(DocsReadCommand)\n const {path: input} = args\n const {web} = flags\n\n const {readPath, webPath} = parseDocsInput(input)\n\n if (!readPath.startsWith('/')) {\n this.error(\n 'Invalid path or URL. Expected a Sanity docs path or URL.\\nExamples:\\n /docs/studio/installation\\n https://www.sanity.io/docs/studio/installation',\n {\n exit: exitCodes.USAGE_ERROR,\n },\n )\n }\n\n if (readPath.includes('..') || !readPath.startsWith('/docs/')) {\n this.error(\n 'Invalid path. Must be a valid Sanity docs path starting with /docs/\\nExample: /docs/studio/installation',\n {\n exit: exitCodes.USAGE_ERROR,\n },\n )\n }\n\n if (web) {\n const url = `https://www.sanity.io${webPath}`\n this.log(`Opening ${url}`)\n await open(url)\n return\n }\n\n this.log(`Reading article: ${readPath}`)\n\n try {\n const content = await readDoc({path: readPath})\n this.log('\\n---\\n')\n this.log(content)\n } catch (error) {\n this.error(error instanceof Error ? error.message : 'Failed to read article', {\n exit: 1,\n })\n }\n }\n}\n"],"names":["Args","Flags","exitCodes","SanityCommand","open","readDoc","isSanityHostname","hostname","endsWith","parseDocsInput","input","url","URL","readPath","pathname","webPath","search","hash","startsWith","DocsReadCommand","args","path","string","description","required","examples","command","flags","web","boolean","aliases","run","parse","error","exit","USAGE_ERROR","includes","log","content","Error","message"],"mappings":"AAAA,SAAQA,IAAI,EAAEC,KAAK,QAAO,cAAa;AACvC,SAAQC,SAAS,EAAEC,aAAa,QAAO,mBAAkB;AACzD,OAAOC,UAAU,OAAM;AAEvB,SAAQC,OAAO,QAAO,yBAAwB;AAO9C,SAASC,iBAAiBC,QAAgB;IACxC,OAAOA,aAAa,eAAeA,SAASC,QAAQ,CAAC;AACvD;AAEA,SAASC,eAAeC,KAAa;IACnC,IAAI;QACF,MAAMC,MAAM,IAAIC,IAAIF;QAEpB,IAAIJ,iBAAiBK,IAAIJ,QAAQ,GAAG;YAClC,OAAO;gBACLM,UAAUF,IAAIG,QAAQ;gBACtBC,SAAS,GAAGJ,IAAIG,QAAQ,GAAGH,IAAIK,MAAM,GAAGL,IAAIM,IAAI,EAAE;YACpD;QACF;IACF,EAAE,OAAM;IACN,gCAAgC;IAClC;IAEA,IAAIP,MAAMQ,UAAU,CAAC,QAAQ,CAACR,MAAMQ,UAAU,CAAC,OAAO;QACpD,MAAMP,MAAM,IAAIC,IAAIF,OAAO;QAE3B,OAAO;YACLG,UAAUF,IAAIG,QAAQ;YACtBC,SAAS,GAAGJ,IAAIG,QAAQ,GAAGH,IAAIK,MAAM,GAAGL,IAAIM,IAAI,EAAE;QACpD;IACF;IAEA,OAAO;QACLJ,UAAUH;QACVK,SAASL;IACX;AACF;AAEA,OAAO,MAAMS,wBAAwBhB;IACnC,OAAgBiB,OAAO;QACrBC,MAAMrB,KAAKsB,MAAM,CAAC;YAChBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,8BAA6B;IAE3D,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SACE;YACFH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtBC,KAAK3B,MAAM4B,OAAO,CAAC;YACjBC,SAAS;gBAAC;aAAI;YACdP,aAAa;QACf;IACF,EAAC;IAED,MAAaQ,MAAqB;QAChC,MAAM,EAACX,IAAI,EAAEO,KAAK,EAAC,GAAG,MAAM,IAAI,CAACK,KAAK,CAACb;QACvC,MAAM,EAACE,MAAMX,KAAK,EAAC,GAAGU;QACtB,MAAM,EAACQ,GAAG,EAAC,GAAGD;QAEd,MAAM,EAACd,QAAQ,EAAEE,OAAO,EAAC,GAAGN,eAAeC;QAE3C,IAAI,CAACG,SAASK,UAAU,CAAC,MAAM;YAC7B,IAAI,CAACe,KAAK,CACR,sJACA;gBACEC,MAAMhC,UAAUiC,WAAW;YAC7B;QAEJ;QAEA,IAAItB,SAASuB,QAAQ,CAAC,SAAS,CAACvB,SAASK,UAAU,CAAC,WAAW;YAC7D,IAAI,CAACe,KAAK,CACR,2GACA;gBACEC,MAAMhC,UAAUiC,WAAW;YAC7B;QAEJ;QAEA,IAAIP,KAAK;YACP,MAAMjB,MAAM,CAAC,qBAAqB,EAAEI,SAAS;YAC7C,IAAI,CAACsB,GAAG,CAAC,CAAC,QAAQ,EAAE1B,KAAK;YACzB,MAAMP,KAAKO;YACX;QACF;QAEA,IAAI,CAAC0B,GAAG,CAAC,CAAC,iBAAiB,EAAExB,UAAU;QAEvC,IAAI;YACF,MAAMyB,UAAU,MAAMjC,QAAQ;gBAACgB,MAAMR;YAAQ;YAC7C,IAAI,CAACwB,GAAG,CAAC;YACT,IAAI,CAACA,GAAG,CAACC;QACX,EAAE,OAAOL,OAAO;YACd,IAAI,CAACA,KAAK,CAACA,iBAAiBM,QAAQN,MAAMO,OAAO,GAAG,0BAA0B;gBAC5EN,MAAM;YACR;QACF;IACF;AACF"}
@@ -3,7 +3,7 @@ import fs from 'node:fs/promises';
3
3
  import os from 'node:os';
4
4
  import path from 'node:path';
5
5
  import { Args, Flags } from '@oclif/core';
6
- import { getProjectCliClient, SanityCommand, subdebug } from '@sanity/cli-core';
6
+ import { exitCodes, getProjectCliClient, SanityCommand, subdebug } from '@sanity/cli-core';
7
7
  import { watch as chokidarWatch } from 'chokidar';
8
8
  import { execa, execaSync } from 'execa';
9
9
  import json5 from 'json5';
@@ -78,13 +78,28 @@ export class CreateDocumentCommand extends SanityCommand {
78
78
  const { args, flags } = await this.parse(CreateDocumentCommand);
79
79
  const { file } = args;
80
80
  const { dataset, id, json5: useJson5, missing, replace, watch } = flags;
81
+ if (!file && this.isUnattended()) {
82
+ this.error('Document input is required in unattended mode. Pass it as the `<file>` argument.', {
83
+ exit: exitCodes.USAGE_ERROR
84
+ });
85
+ }
86
+ if (replace && missing) {
87
+ this.error('Cannot use `--replace` and `--missing` together. Remove one flag and try again.', {
88
+ exit: exitCodes.USAGE_ERROR
89
+ });
90
+ }
91
+ if (id && file) {
92
+ this.error('Cannot use `--id` with the `<file>` argument. Remove `--id` or omit `<file>` and try again.', {
93
+ exit: exitCodes.USAGE_ERROR
94
+ });
95
+ }
81
96
  const cliConfig = await this.tryGetCliConfig();
82
97
  const projectId = await this.getProjectId({
83
98
  fallback: ()=>promptForProject({})
84
99
  });
85
100
  if (!cliConfig.api?.dataset && !dataset) {
86
- this.error('No dataset specified. Either configure a dataset in sanity.cli.ts or use the --dataset flag', {
87
- exit: 1
101
+ this.error('Dataset is required. Pass it with `--dataset <name>` or configure it in `sanity.cli.ts`.', {
102
+ exit: exitCodes.USAGE_ERROR
88
103
  });
89
104
  }
90
105
  const targetDataset = dataset || cliConfig.api?.dataset;
@@ -94,16 +109,6 @@ export class CreateDocumentCommand extends SanityCommand {
94
109
  projectId,
95
110
  requireUser: true
96
111
  });
97
- if (replace && missing) {
98
- this.error('Cannot use both --replace and --missing', {
99
- exit: 1
100
- });
101
- }
102
- if (id && file) {
103
- this.error('Cannot use --id when specifying a file path', {
104
- exit: 1
105
- });
106
- }
107
112
  let operation = 'create';
108
113
  if (replace || missing) {
109
114
  operation = replace ? 'createOrReplace' : 'createIfNotExists';