@sanity/cli 7.10.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.
- package/README.md +31 -22
- package/dist/actions/auth/ensureAuthenticated.js +2 -0
- package/dist/actions/auth/ensureAuthenticated.js.map +1 -1
- package/dist/actions/auth/login/loginInstructions.js +19 -0
- package/dist/actions/auth/login/loginInstructions.js.map +1 -0
- package/dist/actions/dataset/resolveDataset.js +7 -1
- package/dist/actions/dataset/resolveDataset.js.map +1 -1
- package/dist/actions/deploy/deployApp.js +17 -12
- package/dist/actions/deploy/deployApp.js.map +1 -1
- package/dist/actions/deploy/deployStudio.js +2 -0
- package/dist/actions/deploy/deployStudio.js.map +1 -1
- package/dist/actions/graphql/resolveApiGeneration.js +9 -6
- package/dist/actions/graphql/resolveApiGeneration.js.map +1 -1
- package/dist/actions/init/initAction.js +23 -15
- package/dist/actions/init/initAction.js.map +1 -1
- package/dist/actions/manifest/extractCoreAppManifest.js +5 -3
- package/dist/actions/manifest/extractCoreAppManifest.js.map +1 -1
- package/dist/actions/migration/constants.js +10 -0
- package/dist/actions/migration/constants.js.map +1 -0
- package/dist/actions/migration/ensureApiVersionFormat.js +16 -0
- package/dist/actions/migration/ensureApiVersionFormat.js.map +1 -0
- package/dist/actions/migration/fileExists.js +13 -0
- package/dist/actions/migration/fileExists.js.map +1 -0
- package/dist/actions/migration/prettyMutationFormatter.js +155 -0
- package/dist/actions/migration/prettyMutationFormatter.js.map +1 -0
- package/dist/actions/migration/resolveMigrationScript.js +75 -0
- package/dist/actions/migration/resolveMigrationScript.js.map +1 -0
- package/dist/actions/migration/resolveMigrations.js +50 -0
- package/dist/actions/migration/resolveMigrations.js.map +1 -0
- package/dist/actions/migration/templates/index.js +7 -0
- package/dist/actions/migration/templates/index.js.map +1 -0
- package/dist/actions/migration/templates/minimalAdvanced.js +21 -0
- package/dist/actions/migration/templates/minimalAdvanced.js.map +1 -0
- package/dist/actions/migration/templates/minimalSimple.js +61 -0
- package/dist/actions/migration/templates/minimalSimple.js.map +1 -0
- package/dist/actions/migration/templates/renameField.js +20 -0
- package/dist/actions/migration/templates/renameField.js.map +1 -0
- package/dist/actions/migration/templates/renameType.js +19 -0
- package/dist/actions/migration/templates/renameType.js.map +1 -0
- package/dist/actions/migration/templates/stringToPTE.js +32 -0
- package/dist/actions/migration/templates/stringToPTE.js.map +1 -0
- package/dist/actions/migration/tree.js +111 -0
- package/dist/actions/migration/tree.js.map +1 -0
- package/dist/actions/preview/previewAction.js +33 -1
- package/dist/actions/preview/previewAction.js.map +1 -1
- package/dist/actions/schema/listSchemas.js +6 -4
- package/dist/actions/schema/listSchemas.js.map +1 -1
- package/dist/actions/tokens/validateRole.js +2 -1
- package/dist/actions/tokens/validateRole.js.map +1 -1
- package/dist/actions/undeploy/runUndeploy.js +13 -4
- package/dist/actions/undeploy/runUndeploy.js.map +1 -1
- package/dist/commands/backups/disable.js +5 -1
- package/dist/commands/backups/disable.js.map +1 -1
- package/dist/commands/backups/download.js +30 -6
- package/dist/commands/backups/download.js.map +1 -1
- package/dist/commands/backups/enable.js +5 -1
- package/dist/commands/backups/enable.js.map +1 -1
- package/dist/commands/backups/list.js +5 -1
- package/dist/commands/backups/list.js.map +1 -1
- package/dist/commands/cors/add.js +15 -7
- package/dist/commands/cors/add.js.map +1 -1
- package/dist/commands/cors/delete.js +6 -1
- package/dist/commands/cors/delete.js.map +1 -1
- package/dist/commands/datasets/alias/create.js +25 -18
- package/dist/commands/datasets/alias/create.js.map +1 -1
- package/dist/commands/datasets/alias/delete.js +15 -8
- package/dist/commands/datasets/alias/delete.js.map +1 -1
- package/dist/commands/datasets/alias/link.js +39 -17
- package/dist/commands/datasets/alias/link.js.map +1 -1
- package/dist/commands/datasets/alias/unlink.js +23 -2
- package/dist/commands/datasets/alias/unlink.js.map +1 -1
- package/dist/commands/datasets/copy.js +18 -2
- package/dist/commands/datasets/copy.js.map +1 -1
- package/dist/commands/datasets/create.js +8 -2
- package/dist/commands/datasets/create.js.map +1 -1
- package/dist/commands/datasets/delete.js +14 -17
- package/dist/commands/datasets/delete.js.map +1 -1
- package/dist/commands/datasets/embeddings/disable.js +3 -0
- package/dist/commands/datasets/embeddings/disable.js.map +1 -1
- package/dist/commands/datasets/embeddings/enable.js +5 -2
- package/dist/commands/datasets/embeddings/enable.js.map +1 -1
- package/dist/commands/datasets/embeddings/status.js +3 -0
- package/dist/commands/datasets/embeddings/status.js.map +1 -1
- package/dist/commands/datasets/export.js +27 -15
- package/dist/commands/datasets/export.js.map +1 -1
- package/dist/commands/datasets/import.js +3 -3
- package/dist/commands/datasets/import.js.map +1 -1
- package/dist/commands/datasets/visibility/get.js +2 -2
- package/dist/commands/datasets/visibility/get.js.map +1 -1
- package/dist/commands/datasets/visibility/set.js +2 -2
- package/dist/commands/datasets/visibility/set.js.map +1 -1
- package/dist/commands/docs/read.js +3 -3
- package/dist/commands/docs/read.js.map +1 -1
- package/dist/commands/documents/create.js +18 -13
- package/dist/commands/documents/create.js.map +1 -1
- package/dist/commands/documents/delete.js +3 -3
- package/dist/commands/documents/delete.js.map +1 -1
- package/dist/commands/documents/get.js +3 -3
- package/dist/commands/documents/get.js.map +1 -1
- package/dist/commands/documents/query.js +3 -3
- package/dist/commands/documents/query.js.map +1 -1
- package/dist/commands/documents/validate.js +29 -26
- package/dist/commands/documents/validate.js.map +1 -1
- package/dist/commands/graphql/deploy.js +20 -16
- package/dist/commands/graphql/deploy.js.map +1 -1
- package/dist/commands/graphql/undeploy.js +15 -18
- package/dist/commands/graphql/undeploy.js.map +1 -1
- package/dist/commands/hooks/delete.js +2 -2
- package/dist/commands/hooks/delete.js.map +1 -1
- package/dist/commands/hooks/logs.js +2 -2
- package/dist/commands/hooks/logs.js.map +1 -1
- package/dist/commands/login.js +2 -1
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/media/create-aspect.js +20 -8
- package/dist/commands/media/create-aspect.js.map +1 -1
- package/dist/commands/media/delete-aspect.js +31 -16
- package/dist/commands/media/delete-aspect.js.map +1 -1
- package/dist/commands/media/deploy-aspect.js +10 -5
- package/dist/commands/media/deploy-aspect.js.map +1 -1
- package/dist/commands/media/export.js +9 -4
- package/dist/commands/media/export.js.map +1 -1
- package/dist/commands/media/import.js +6 -1
- package/dist/commands/media/import.js.map +1 -1
- package/dist/commands/migrations/create.js +150 -0
- package/dist/commands/migrations/create.js.map +1 -0
- package/dist/commands/migrations/list.js +64 -0
- package/dist/commands/migrations/list.js.map +1 -0
- package/dist/commands/migrations/run.js +306 -0
- package/dist/commands/migrations/run.js.map +1 -0
- package/dist/commands/preview.js +1 -0
- package/dist/commands/preview.js.map +1 -1
- package/dist/commands/projects/create.js +2 -1
- package/dist/commands/projects/create.js.map +1 -1
- package/dist/commands/schemas/delete.js +23 -2
- package/dist/commands/schemas/delete.js.map +1 -1
- package/dist/commands/schemas/deploy.js +6 -4
- package/dist/commands/schemas/deploy.js.map +1 -1
- package/dist/commands/schemas/extract.js +22 -1
- package/dist/commands/schemas/extract.js.map +1 -1
- package/dist/commands/schemas/list.js +8 -8
- package/dist/commands/schemas/list.js.map +1 -1
- package/dist/commands/tokens/{add.js → create.js} +25 -18
- package/dist/commands/tokens/create.js.map +1 -0
- package/dist/commands/tokens/delete.js +41 -23
- package/dist/commands/tokens/delete.js.map +1 -1
- package/dist/commands/undeploy.js +2 -7
- package/dist/commands/undeploy.js.map +1 -1
- package/dist/commands/users/invite.js +25 -3
- package/dist/commands/users/invite.js.map +1 -1
- package/dist/topicAliases.js +3 -0
- package/dist/topicAliases.js.map +1 -1
- package/dist/util/formatCliErrorMessages.js +5 -0
- package/dist/util/formatCliErrorMessages.js.map +1 -0
- package/oclif.config.js +5 -1
- package/oclif.manifest.json +326 -121
- package/package.json +7 -7
- 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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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:
|
|
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.
|
|
269
|
-
exit:
|
|
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('
|
|
176
|
-
exit:
|
|
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:
|
|
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
|
+
{"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:
|
|
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
|
+
{"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:
|
|
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:
|
|
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
|
+
{"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('
|
|
87
|
-
exit:
|
|
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';
|