@sanity/cli 6.5.3 → 6.7.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 +18 -5
- package/bin/run.js +3 -1
- package/dist/actions/auth/login/login.js +39 -13
- package/dist/actions/auth/login/login.js.map +1 -1
- package/dist/actions/auth/login/validateToken.js +39 -0
- package/dist/actions/auth/login/validateToken.js.map +1 -0
- package/dist/actions/build/buildApp.js +4 -5
- package/dist/actions/build/buildApp.js.map +1 -1
- package/dist/actions/build/buildStaticFiles.js +12 -4
- package/dist/actions/build/buildStaticFiles.js.map +1 -1
- package/dist/actions/build/buildStudio.js +6 -14
- package/dist/actions/build/buildStudio.js.map +1 -1
- package/dist/actions/build/{getStudioEnvironmentVariables.js → getEnvironmentVariables.js} +15 -19
- package/dist/actions/build/getEnvironmentVariables.js.map +1 -0
- package/dist/actions/deploy/deployStudio.js +1 -2
- package/dist/actions/deploy/deployStudio.js.map +1 -1
- package/dist/actions/deploy/deployStudioSchemasAndManifests.js +1 -2
- package/dist/actions/deploy/deployStudioSchemasAndManifests.js.map +1 -1
- package/dist/actions/deploy/deployStudioSchemasAndManifests.worker.js +1 -1
- package/dist/actions/deploy/deployStudioSchemasAndManifests.worker.js.map +1 -1
- package/dist/actions/dev/startStudioDevServer.js +1 -1
- package/dist/actions/dev/startStudioDevServer.js.map +1 -1
- package/dist/actions/documents/validateDocuments.worker.js +1 -2
- package/dist/actions/documents/validateDocuments.worker.js.map +1 -1
- package/dist/actions/graphql/SchemaError.js +1 -1
- package/dist/actions/graphql/SchemaError.js.map +1 -1
- package/dist/actions/init/initAction.js +32 -1
- package/dist/actions/init/initAction.js.map +1 -1
- package/dist/actions/init/scaffoldTemplate.js +32 -18
- package/dist/actions/init/scaffoldTemplate.js.map +1 -1
- package/dist/actions/init/templates/index.js +2 -0
- package/dist/actions/init/templates/index.js.map +1 -1
- package/dist/actions/init/templates/pageBuilder.js +32 -0
- package/dist/actions/init/templates/pageBuilder.js.map +1 -0
- package/dist/actions/init/types.js +2 -1
- package/dist/actions/init/types.js.map +1 -1
- package/dist/actions/manifest/extractManifest.js +1 -1
- package/dist/actions/manifest/extractManifest.js.map +1 -1
- package/dist/actions/manifest/extractManifest.worker.js +1 -1
- package/dist/actions/manifest/extractManifest.worker.js.map +1 -1
- package/dist/actions/mcp/editorConfigs.js +51 -11
- package/dist/actions/mcp/editorConfigs.js.map +1 -1
- package/dist/actions/mcp/promptForMCPSetup.js +16 -11
- package/dist/actions/mcp/promptForMCPSetup.js.map +1 -1
- package/dist/actions/mcp/setupMCP.js +180 -61
- package/dist/actions/mcp/setupMCP.js.map +1 -1
- package/dist/actions/mcp/types.js.map +1 -1
- package/dist/actions/schema/deploySchemas.js +1 -1
- package/dist/actions/schema/deploySchemas.js.map +1 -1
- package/dist/actions/schema/extractSanityWorkspace.worker.js +1 -1
- package/dist/actions/schema/extractSanityWorkspace.worker.js.map +1 -1
- package/dist/actions/schema/extractSchema.js +1 -4
- package/dist/actions/schema/extractSchema.js.map +1 -1
- package/dist/actions/schema/extractSchemaWatcher.js +1 -4
- package/dist/actions/schema/extractSchemaWatcher.js.map +1 -1
- package/dist/actions/schema/getExtractOptions.js +8 -18
- package/dist/actions/schema/getExtractOptions.js.map +1 -1
- package/dist/actions/schema/types.js +0 -6
- package/dist/actions/schema/types.js.map +1 -1
- package/dist/actions/schema/validateAction.js +1 -1
- package/dist/actions/schema/validateAction.js.map +1 -1
- package/dist/actions/schema/validateSchema.worker.js +1 -2
- package/dist/actions/schema/validateSchema.worker.js.map +1 -1
- package/dist/actions/schema/watchExtractSchema.js +1 -1
- package/dist/actions/schema/watchExtractSchema.js.map +1 -1
- package/dist/actions/skills/readSkillState.js +54 -0
- package/dist/actions/skills/readSkillState.js.map +1 -0
- package/dist/actions/skills/setupSkills.js +73 -0
- package/dist/actions/skills/setupSkills.js.map +1 -0
- package/dist/commands/build.js +9 -22
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/cors/add.js +5 -5
- package/dist/commands/cors/add.js.map +1 -1
- package/dist/commands/datasets/export.js +9 -0
- package/dist/commands/datasets/export.js.map +1 -1
- package/dist/commands/docs/read.js +33 -12
- package/dist/commands/docs/read.js.map +1 -1
- package/dist/commands/init.js +12 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.js +28 -5
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/manifest/extract.js +1 -2
- package/dist/commands/manifest/extract.js.map +1 -1
- package/dist/commands/mcp/configure.js +2 -1
- package/dist/commands/mcp/configure.js.map +1 -1
- package/dist/commands/schemas/deploy.js +1 -2
- package/dist/commands/schemas/deploy.js.map +1 -1
- package/dist/exports/_internal.d.ts +2 -1
- package/dist/exports/_internal.js +1 -1
- package/dist/exports/_internal.js.map +1 -1
- package/dist/server/devServer.js +25 -4
- package/dist/server/devServer.js.map +1 -1
- package/dist/server/previewServer.js +1 -1
- package/dist/server/previewServer.js.map +1 -1
- package/dist/services/mcp.js +1 -1
- package/dist/services/mcp.js.map +1 -1
- package/dist/telemetry/init.telemetry.js.map +1 -1
- package/oclif.manifest.json +237 -205
- package/package.json +15 -16
- package/templates/page-builder/README.md +9 -0
- package/templates/page-builder/schemaTypes/hero.js +31 -0
- package/templates/page-builder/schemaTypes/index.js +19 -0
- package/templates/page-builder/static/.gitkeep +0 -0
- package/dist/actions/build/buildDebug.js +0 -4
- package/dist/actions/build/buildDebug.js.map +0 -1
- package/dist/actions/build/buildVendorDependencies.js +0 -149
- package/dist/actions/build/buildVendorDependencies.js.map +0 -1
- package/dist/actions/build/checkStudioDependencyVersions.js +0 -155
- package/dist/actions/build/checkStudioDependencyVersions.js.map +0 -1
- package/dist/actions/build/createExternalFromImportMap.js +0 -11
- package/dist/actions/build/createExternalFromImportMap.js.map +0 -1
- package/dist/actions/build/decorateIndexWithAutoGeneratedWarning.js +0 -13
- package/dist/actions/build/decorateIndexWithAutoGeneratedWarning.js.map +0 -1
- package/dist/actions/build/decorateIndexWithBridgeScript.js +0 -17
- package/dist/actions/build/decorateIndexWithBridgeScript.js.map +0 -1
- package/dist/actions/build/decorateIndexWithStagingScript.js +0 -16
- package/dist/actions/build/decorateIndexWithStagingScript.js.map +0 -1
- package/dist/actions/build/getAppEnvVars.js +0 -9
- package/dist/actions/build/getAppEnvVars.js.map +0 -1
- package/dist/actions/build/getEntryModule.js +0 -46
- package/dist/actions/build/getEntryModule.js.map +0 -1
- package/dist/actions/build/getPossibleDocumentComponentLocations.js +0 -11
- package/dist/actions/build/getPossibleDocumentComponentLocations.js.map +0 -1
- package/dist/actions/build/getStudioEnvVars.js +0 -9
- package/dist/actions/build/getStudioEnvVars.js.map +0 -1
- package/dist/actions/build/getStudioEnvironmentVariables.js.map +0 -1
- package/dist/actions/build/getViteConfig.js +0 -219
- package/dist/actions/build/getViteConfig.js.map +0 -1
- package/dist/actions/build/normalizeBasePath.js +0 -9
- package/dist/actions/build/normalizeBasePath.js.map +0 -1
- package/dist/actions/build/renderDocument.js +0 -50
- package/dist/actions/build/renderDocument.js.map +0 -1
- package/dist/actions/build/renderDocument.worker.js +0 -9
- package/dist/actions/build/renderDocument.worker.js.map +0 -1
- package/dist/actions/build/renderDocumentWorker/addTimestampImportMapScriptToHtml.js +0 -79
- package/dist/actions/build/renderDocumentWorker/addTimestampImportMapScriptToHtml.js.map +0 -1
- package/dist/actions/build/renderDocumentWorker/components/BasicDocument.js +0 -61
- package/dist/actions/build/renderDocumentWorker/components/BasicDocument.js.map +0 -1
- package/dist/actions/build/renderDocumentWorker/components/DefaultDocument.js +0 -165
- package/dist/actions/build/renderDocumentWorker/components/DefaultDocument.js.map +0 -1
- package/dist/actions/build/renderDocumentWorker/components/Favicons.js +0 -28
- package/dist/actions/build/renderDocumentWorker/components/Favicons.js.map +0 -1
- package/dist/actions/build/renderDocumentWorker/components/GlobalErrorHandler.js +0 -178
- package/dist/actions/build/renderDocumentWorker/components/GlobalErrorHandler.js.map +0 -1
- package/dist/actions/build/renderDocumentWorker/components/NoJavascript.js +0 -51
- package/dist/actions/build/renderDocumentWorker/components/NoJavascript.js.map +0 -1
- package/dist/actions/build/renderDocumentWorker/getDocumentComponent.js +0 -41
- package/dist/actions/build/renderDocumentWorker/getDocumentComponent.js.map +0 -1
- package/dist/actions/build/renderDocumentWorker/getDocumentHtml.js +0 -55
- package/dist/actions/build/renderDocumentWorker/getDocumentHtml.js.map +0 -1
- package/dist/actions/build/renderDocumentWorker/renderDocumentWorker.js +0 -31
- package/dist/actions/build/renderDocumentWorker/renderDocumentWorker.js.map +0 -1
- package/dist/actions/build/renderDocumentWorker/tryLoadDocumentComponent.js +0 -30
- package/dist/actions/build/renderDocumentWorker/tryLoadDocumentComponent.js.map +0 -1
- package/dist/actions/build/renderDocumentWorker/types.js +0 -5
- package/dist/actions/build/renderDocumentWorker/types.js.map +0 -1
- package/dist/actions/build/writeSanityRuntime.js +0 -64
- package/dist/actions/build/writeSanityRuntime.js.map +0 -1
- package/dist/actions/docs/normalizeDocsPath.js +0 -15
- package/dist/actions/docs/normalizeDocsPath.js.map +0 -1
- package/dist/actions/schema/extractSanitySchema.worker.js +0 -33
- package/dist/actions/schema/extractSanitySchema.worker.js.map +0 -1
- package/dist/actions/schema/formatSchemaValidation.js +0 -78
- package/dist/actions/schema/formatSchemaValidation.js.map +0 -1
- package/dist/actions/schema/matchSchemaPattern.js +0 -22
- package/dist/actions/schema/matchSchemaPattern.js.map +0 -1
- package/dist/actions/schema/runSchemaExtraction.js +0 -39
- package/dist/actions/schema/runSchemaExtraction.js.map +0 -1
- package/dist/actions/schema/utils/SchemaExtractionError.js +0 -10
- package/dist/actions/schema/utils/SchemaExtractionError.js.map +0 -1
- package/dist/actions/schema/utils/extractValidationFromSchemaError.js +0 -12
- package/dist/actions/schema/utils/extractValidationFromSchemaError.js.map +0 -1
- package/dist/constants.js +0 -8
- package/dist/constants.js.map +0 -1
- package/dist/server/vite/plugin-sanity-build-entries.js +0 -67
- package/dist/server/vite/plugin-sanity-build-entries.js.map +0 -1
- package/dist/server/vite/plugin-sanity-favicons.js +0 -72
- package/dist/server/vite/plugin-sanity-favicons.js.map +0 -1
- package/dist/server/vite/plugin-sanity-runtime-rewrite.js +0 -18
- package/dist/server/vite/plugin-sanity-runtime-rewrite.js.map +0 -1
- package/dist/server/vite/plugin-schema-extraction.js +0 -201
- package/dist/server/vite/plugin-schema-extraction.js.map +0 -1
- package/dist/telemetry/build.telemetry.js +0 -13
- package/dist/telemetry/build.telemetry.js.map +0 -1
- package/dist/telemetry/extractSchema.telemetry.js +0 -18
- package/dist/telemetry/extractSchema.telemetry.js.map +0 -1
- package/dist/util/getWorkspace.js +0 -18
- package/dist/util/getWorkspace.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/cors/add.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {confirm, logSymbols} from '@sanity/cli-core/ux'\nimport {oneline} from 'oneline'\n\nimport {filterAndValidateOrigin} from '../../actions/cors/filterAndValidateOrigin.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {createCorsOrigin} from '../../services/cors.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst addCorsDebug = subdebug('cors:add')\n\nexport class Add extends SanityCommand<typeof Add> {\n static override args = {\n origin: Args.string({\n description: 'Origin to allow (e.g., https://example.com)',\n required: true,\n }),\n }\n\n static override description = 'Add a CORS origin to the project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively add a CORS origin',\n },\n {\n command: '<%= config.bin %> <%= command.id %> http://localhost:3000 --no-credentials',\n description: 'Add a localhost origin without credentials',\n },\n {\n command: '<%= config.bin %> <%= command.id %> https://myapp.com --credentials',\n description: 'Add a production origin with credentials allowed',\n },\n {\n command: '<%= config.bin %> <%= command.id %> https://myapp.com --project-id abc123',\n description: 'Add a CORS origin for a specific project',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to add CORS origin to',\n semantics: 'override',\n }),\n credentials: Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Allow credentials (token/cookie) to be sent from this origin',\n required: false,\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(Add)\n const {origin} = args\n\n // Ensure we have project context\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'create', permission: 'sanity.project.cors'}],\n }),\n })\n\n // Check if the origin argument looks like a file path and warn\n try {\n const isFile = fs.existsSync(path.join(process.cwd(), args.origin))\n if (isFile) {\n this.warn(`Origin \"${args.origin}?\" Remember to quote values (sanity cors add \"*\")`)\n }\n } catch {\n // Ignore errors checking if it's a file\n }\n\n const filteredOrigin = await filterAndValidateOrigin(origin, this.output)\n const hasWildcard = origin.includes('*')\n\n if (hasWildcard) {\n const confirmed = await this.promptForWildcardConfirmation(origin)\n if (!confirmed) {\n this.error('Operation cancelled', {exit: 1})\n }\n }\n\n const allowCredentials =\n flags.credentials === undefined\n ? await this.promptForCredentials(hasWildcard)\n : Boolean(flags.credentials)\n\n if (filteredOrigin !== origin) {\n this.log(`Normalized origin to: ${filteredOrigin}`)\n }\n\n try {\n const response = await createCorsOrigin({\n allowCredentials,\n origin: filteredOrigin,\n projectId,\n })\n\n addCorsDebug(`CORS origin added successfully`, response)\n\n this.log('CORS origin added successfully')\n } catch (error) {\n const err = error as Error\n\n addCorsDebug(`Error adding CORS origin`, err)\n this.error(`CORS origin addition failed:\\n${err.message}`, {exit: 1})\n }\n }\n\n /**\n * Prompt the user for credentials\n *\n * @param hasWildcard - Whether the origin contains a wildcard\n * @returns - Whether to allow credentials\n */\n private async promptForCredentials(hasWildcard: boolean) {\n this.log('')\n if (hasWildcard) {\n this.log(oneline`\n ${styleText('yellow', `${logSymbols.warning} Warning:`)}\n We ${styleText(['red', 'underline'], 'HIGHLY')} recommend NOT allowing credentials\n on origins containing wildcards. If you are logged in to a studio, people will\n be able to send requests ${styleText('underline', 'on your behalf')} to read and modify\n data, from any matching origin. Please tread carefully!\n `)\n } else {\n this.log(oneline`\n ${styleText('yellow', `${logSymbols.warning} Warning:`)}\n Should this origin be allowed to send requests using authentication tokens or\n session cookies? Be aware that any script on this origin will be able to send\n requests ${styleText('underline', 'on your behalf')} to read and modify data if you\n are logged in to a Sanity studio. If this origin hosts a studio, you will need\n this, otherwise you should probably answer \"No\" (n).\n `)\n }\n\n this.log('')\n\n return confirm({\n default: false,\n message: oneline`\n Allow credentials to be sent from this origin? Please read the warning above.\n `,\n })\n }\n\n /**\n * Prompt the user for wildcard confirmation\n *\n * @param origin - The origin to check for wildcards\n * @returns - Whether to allow the origin\n */\n private async promptForWildcardConfirmation(origin: string) {\n this.log('')\n this.log(styleText('yellow', `${logSymbols.warning} Warning: Examples of allowed origins:`))\n\n if (origin === '*') {\n this.log('- http://www.some-malicious.site')\n this.log('- https://not.what-you-were-expecting.com')\n this.log('- https://high-traffic-site.com')\n this.log('- http://192.168.1.1:8080')\n } else {\n this.log(`- ${origin.replace(/:\\*/, ':1234').replaceAll('*', 'foo')}`)\n this.log(`- ${origin.replace(/:\\*/, ':3030').replaceAll('*', 'foo.bar')}`)\n }\n\n this.log('')\n\n return confirm({\n default: false,\n message: oneline`\n Using wildcards can be ${styleText('red', 'risky')}.\n Are you ${styleText('underline', 'absolutely sure')} you want to allow this origin?`,\n })\n }\n}\n"],"names":["fs","path","styleText","Args","Flags","SanityCommand","subdebug","confirm","logSymbols","oneline","filterAndValidateOrigin","promptForProject","createCorsOrigin","getProjectIdFlag","addCorsDebug","Add","args","origin","string","description","required","examples","command","flags","semantics","credentials","boolean","allowNo","default","undefined","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","isFile","existsSync","join","process","cwd","warn","filteredOrigin","output","hasWildcard","includes","confirmed","promptForWildcardConfirmation","error","exit","allowCredentials","promptForCredentials","Boolean","log","response","err","message","warning","replace","replaceAll"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/cors/add.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {confirm, logSymbols} from '@sanity/cli-core/ux'\nimport {oneline} from 'oneline'\n\nimport {filterAndValidateOrigin} from '../../actions/cors/filterAndValidateOrigin.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {createCorsOrigin} from '../../services/cors.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst addCorsDebug = subdebug('cors:add')\n\nexport class Add extends SanityCommand<typeof Add> {\n static override args = {\n origin: Args.string({\n description: 'Origin to allow (e.g., https://example.com)',\n required: true,\n }),\n }\n\n static override description = 'Add a CORS origin to the project'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively add a CORS origin',\n },\n {\n command: '<%= config.bin %> <%= command.id %> http://localhost:3000 --no-credentials',\n description: 'Add a localhost origin without credentials',\n },\n {\n command: '<%= config.bin %> <%= command.id %> https://myapp.com --credentials',\n description: 'Add a production origin with credentials allowed',\n },\n {\n command: '<%= config.bin %> <%= command.id %> https://myapp.com --project-id abc123',\n description: 'Add a CORS origin for a specific project',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to add CORS origin to',\n semantics: 'override',\n }),\n credentials: Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Allow credentials (token/cookie) to be sent from this origin',\n required: false,\n }),\n }\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(Add)\n const {origin} = args\n\n // Ensure we have project context\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [{grant: 'create', permission: 'sanity.project.cors'}],\n }),\n })\n\n // Check if the origin argument looks like a file path and warn\n try {\n const isFile = fs.existsSync(path.join(process.cwd(), args.origin))\n if (isFile) {\n this.warn(`Origin \"${args.origin}?\" Remember to quote values (sanity cors add \"*\")`)\n }\n } catch {\n // Ignore errors checking if it's a file\n }\n\n const filteredOrigin = await filterAndValidateOrigin(origin, this.output)\n const hasWildcard = origin.includes('*')\n\n if (hasWildcard) {\n const confirmed = await this.promptForWildcardConfirmation(origin)\n if (!confirmed) {\n this.error('Operation cancelled', {exit: 1})\n }\n }\n\n const allowCredentials =\n flags.credentials === undefined\n ? await this.promptForCredentials(hasWildcard)\n : Boolean(flags.credentials)\n\n if (filteredOrigin !== origin) {\n this.log(`Normalized origin to: ${filteredOrigin}`)\n }\n\n try {\n const response = await createCorsOrigin({\n allowCredentials,\n origin: filteredOrigin,\n projectId,\n })\n\n addCorsDebug(`CORS origin added successfully`, response)\n\n this.log('CORS origin added successfully')\n } catch (error) {\n const err = error as Error\n\n addCorsDebug(`Error adding CORS origin`, err)\n this.error(`CORS origin addition failed:\\n${err.message}`, {exit: 1})\n }\n }\n\n /**\n * Prompt the user for credentials\n *\n * @param hasWildcard - Whether the origin contains a wildcard\n * @returns - Whether to allow credentials\n */\n private async promptForCredentials(hasWildcard: boolean) {\n this.log('')\n if (hasWildcard) {\n this.log(oneline`\n ${styleText('yellow', `${logSymbols.warning} Warning:`)}\n We ${styleText(['red', 'underline'], 'HIGHLY')} recommend NOT allowing credentials\n on origins containing wildcards. If you are logged in to a Sanity studio or an app built with\n the Sanity App SDK, people will be able to send requests ${styleText('underline', 'on your behalf')}\n to read and modify data, from any matching origin. Please tread carefully!\n `)\n } else {\n this.log(oneline`\n ${styleText('yellow', `${logSymbols.warning} Warning:`)}\n Should this origin be allowed to send requests using authentication tokens or\n session cookies? Be aware that any script on this origin will be able to send\n requests ${styleText('underline', 'on your behalf')} to read and modify data if you\n are logged in to a Sanity studio or app. If this origin hosts a studio or an app built with\n the Sanity App SDK, you will need this, otherwise you should probably answer \"No\" (n).\n `)\n }\n\n this.log('')\n\n return confirm({\n default: false,\n message: oneline`\n Allow credentials to be sent from this origin? Please read the warning above.\n `,\n })\n }\n\n /**\n * Prompt the user for wildcard confirmation\n *\n * @param origin - The origin to check for wildcards\n * @returns - Whether to allow the origin\n */\n private async promptForWildcardConfirmation(origin: string) {\n this.log('')\n this.log(styleText('yellow', `${logSymbols.warning} Warning: Examples of allowed origins:`))\n\n if (origin === '*') {\n this.log('- http://www.some-malicious.site')\n this.log('- https://not.what-you-were-expecting.com')\n this.log('- https://high-traffic-site.com')\n this.log('- http://192.168.1.1:8080')\n } else {\n this.log(`- ${origin.replace(/:\\*/, ':1234').replaceAll('*', 'foo')}`)\n this.log(`- ${origin.replace(/:\\*/, ':3030').replaceAll('*', 'foo.bar')}`)\n }\n\n this.log('')\n\n return confirm({\n default: false,\n message: oneline`\n Using wildcards can be ${styleText('red', 'risky')}.\n Are you ${styleText('underline', 'absolutely sure')} you want to allow this origin?`,\n })\n }\n}\n"],"names":["fs","path","styleText","Args","Flags","SanityCommand","subdebug","confirm","logSymbols","oneline","filterAndValidateOrigin","promptForProject","createCorsOrigin","getProjectIdFlag","addCorsDebug","Add","args","origin","string","description","required","examples","command","flags","semantics","credentials","boolean","allowNo","default","undefined","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","isFile","existsSync","join","process","cwd","warn","filteredOrigin","output","hasWildcard","includes","confirmed","promptForWildcardConfirmation","error","exit","allowCredentials","promptForCredentials","Boolean","log","response","err","message","warning","replace","replaceAll"],"mappings":"AAAA,OAAOA,QAAQ,UAAS;AACxB,OAAOC,UAAU,YAAW;AAC5B,SAAQC,SAAS,QAAO,YAAW;AAEnC,SAAQC,IAAI,EAAEC,KAAK,QAAO,cAAa;AACvC,SAAQC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACxD,SAAQC,OAAO,EAAEC,UAAU,QAAO,sBAAqB;AACvD,SAAQC,OAAO,QAAO,UAAS;AAE/B,SAAQC,uBAAuB,QAAO,gDAA+C;AACrF,SAAQC,gBAAgB,QAAO,oCAAmC;AAClE,SAAQC,gBAAgB,QAAO,yBAAwB;AACvD,SAAQC,gBAAgB,QAAO,4BAA2B;AAE1D,MAAMC,eAAeR,SAAS;AAE9B,OAAO,MAAMS,YAAYV;IACvB,OAAgBW,OAAO;QACrBC,QAAQd,KAAKe,MAAM,CAAC;YAClBC,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,OAAgBD,cAAc,mCAAkC;IAEhE,OAAgBE,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtB,GAAGV,iBAAiB;YAClBM,aAAa;YACbK,WAAW;QACb,EAAE;QACFC,aAAarB,MAAMsB,OAAO,CAAC;YACzBC,SAAS;YACTC,SAASC;YACTV,aAAa;YACbC,UAAU;QACZ;IACF,EAAC;IAED,MAAaU,MAAqB;QAChC,MAAM,EAACd,IAAI,EAAEO,KAAK,EAAC,GAAG,MAAM,IAAI,CAACQ,KAAK,CAAChB;QACvC,MAAM,EAACE,MAAM,EAAC,GAAGD;QAEjB,iCAAiC;QACjC,MAAMgB,YAAY,MAAM,IAAI,CAACC,YAAY,CAAC;YACxCC,UAAU,IACRvB,iBAAiB;oBACfwB,qBAAqB;wBAAC;4BAACC,OAAO;4BAAUC,YAAY;wBAAqB;qBAAE;gBAC7E;QACJ;QAEA,+DAA+D;QAC/D,IAAI;YACF,MAAMC,SAAStC,GAAGuC,UAAU,CAACtC,KAAKuC,IAAI,CAACC,QAAQC,GAAG,IAAI1B,KAAKC,MAAM;YACjE,IAAIqB,QAAQ;gBACV,IAAI,CAACK,IAAI,CAAC,CAAC,QAAQ,EAAE3B,KAAKC,MAAM,CAAC,iDAAiD,CAAC;YACrF;QACF,EAAE,OAAM;QACN,wCAAwC;QAC1C;QAEA,MAAM2B,iBAAiB,MAAMlC,wBAAwBO,QAAQ,IAAI,CAAC4B,MAAM;QACxE,MAAMC,cAAc7B,OAAO8B,QAAQ,CAAC;QAEpC,IAAID,aAAa;YACf,MAAME,YAAY,MAAM,IAAI,CAACC,6BAA6B,CAAChC;YAC3D,IAAI,CAAC+B,WAAW;gBACd,IAAI,CAACE,KAAK,CAAC,uBAAuB;oBAACC,MAAM;gBAAC;YAC5C;QACF;QAEA,MAAMC,mBACJ7B,MAAME,WAAW,KAAKI,YAClB,MAAM,IAAI,CAACwB,oBAAoB,CAACP,eAChCQ,QAAQ/B,MAAME,WAAW;QAE/B,IAAImB,mBAAmB3B,QAAQ;YAC7B,IAAI,CAACsC,GAAG,CAAC,CAAC,sBAAsB,EAAEX,gBAAgB;QACpD;QAEA,IAAI;YACF,MAAMY,WAAW,MAAM5C,iBAAiB;gBACtCwC;gBACAnC,QAAQ2B;gBACRZ;YACF;YAEAlB,aAAa,CAAC,8BAA8B,CAAC,EAAE0C;YAE/C,IAAI,CAACD,GAAG,CAAC;QACX,EAAE,OAAOL,OAAO;YACd,MAAMO,MAAMP;YAEZpC,aAAa,CAAC,wBAAwB,CAAC,EAAE2C;YACzC,IAAI,CAACP,KAAK,CAAC,CAAC,8BAA8B,EAAEO,IAAIC,OAAO,EAAE,EAAE;gBAACP,MAAM;YAAC;QACrE;IACF;IAEA;;;;;GAKC,GACD,MAAcE,qBAAqBP,WAAoB,EAAE;QACvD,IAAI,CAACS,GAAG,CAAC;QACT,IAAIT,aAAa;YACf,IAAI,CAACS,GAAG,CAAC9C,OAAO,CAAC;MACjB,EAAEP,UAAU,UAAU,GAAGM,WAAWmD,OAAO,CAAC,SAAS,CAAC,EAAE;SACrD,EAAEzD,UAAU;gBAAC;gBAAO;aAAY,EAAE,UAAU;;+DAEU,EAAEA,UAAU,aAAa,kBAAkB;;IAEtG,CAAC;QACD,OAAO;YACL,IAAI,CAACqD,GAAG,CAAC9C,OAAO,CAAC;MACjB,EAAEP,UAAU,UAAU,GAAGM,WAAWmD,OAAO,CAAC,SAAS,CAAC,EAAE;;;eAG/C,EAAEzD,UAAU,aAAa,kBAAkB;;;IAGtD,CAAC;QACD;QAEA,IAAI,CAACqD,GAAG,CAAC;QAET,OAAOhD,QAAQ;YACbqB,SAAS;YACT8B,SAASjD,OAAO,CAAC;;IAEnB,CAAC;QACD;IACF;IAEA;;;;;GAKC,GACD,MAAcwC,8BAA8BhC,MAAc,EAAE;QAC1D,IAAI,CAACsC,GAAG,CAAC;QACT,IAAI,CAACA,GAAG,CAACrD,UAAU,UAAU,GAAGM,WAAWmD,OAAO,CAAC,sCAAsC,CAAC;QAE1F,IAAI1C,WAAW,KAAK;YAClB,IAAI,CAACsC,GAAG,CAAC;YACT,IAAI,CAACA,GAAG,CAAC;YACT,IAAI,CAACA,GAAG,CAAC;YACT,IAAI,CAACA,GAAG,CAAC;QACX,OAAO;YACL,IAAI,CAACA,GAAG,CAAC,CAAC,EAAE,EAAEtC,OAAO2C,OAAO,CAAC,OAAO,SAASC,UAAU,CAAC,KAAK,QAAQ;YACrE,IAAI,CAACN,GAAG,CAAC,CAAC,EAAE,EAAEtC,OAAO2C,OAAO,CAAC,OAAO,SAASC,UAAU,CAAC,KAAK,YAAY;QAC3E;QAEA,IAAI,CAACN,GAAG,CAAC;QAET,OAAOhD,QAAQ;YACbqB,SAAS;YACT8B,SAASjD,OAAO,CAAC;6BACM,EAAEP,UAAU,OAAO,SAAS;cAC3C,EAAEA,UAAU,aAAa,mBAAmB,+BAA+B,CAAC;QACtF;IACF;AACF"}
|
|
@@ -41,6 +41,10 @@ export class DatasetExportCommand extends SanityCommand {
|
|
|
41
41
|
{
|
|
42
42
|
command: '<%= config.bin %> <%= command.id %> staging staging.tar.gz --types products,shops',
|
|
43
43
|
description: 'Export specific document types'
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
command: '<%= config.bin %> <%= command.id %> moviedb moviedb.tar.gz --no-strict-asset-verification',
|
|
47
|
+
description: 'Export dataset without aborting on asset verification failures'
|
|
44
48
|
}
|
|
45
49
|
];
|
|
46
50
|
static flags = {
|
|
@@ -72,6 +76,10 @@ export class DatasetExportCommand extends SanityCommand {
|
|
|
72
76
|
default: false,
|
|
73
77
|
description: 'Export only published versions of documents'
|
|
74
78
|
}),
|
|
79
|
+
'no-strict-asset-verification': Flags.boolean({
|
|
80
|
+
default: false,
|
|
81
|
+
description: 'Do not abort the export when an asset fails hash or content-length verification'
|
|
82
|
+
}),
|
|
75
83
|
overwrite: Flags.boolean({
|
|
76
84
|
default: false,
|
|
77
85
|
description: 'Overwrite any file with the same name'
|
|
@@ -183,6 +191,7 @@ dataset: ${dataset.padEnd(46)}`, {
|
|
|
183
191
|
onProgress,
|
|
184
192
|
outputPath,
|
|
185
193
|
raw: flags.raw,
|
|
194
|
+
strictAssetVerification: !flags['no-strict-asset-verification'],
|
|
186
195
|
types: flags.types ? flags.types.split(',') : undefined
|
|
187
196
|
};
|
|
188
197
|
const start = Date.now();
|
|
@@ -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\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 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 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","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 {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,8 +1,34 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
2
|
import { SanityCommand } from '@sanity/cli-core';
|
|
3
3
|
import open from 'open';
|
|
4
|
-
import { normalizeDocsPath } from '../../actions/docs/normalizeDocsPath.js';
|
|
5
4
|
import { readDoc } from '../../services/docs.js';
|
|
5
|
+
function isSanityHostname(hostname) {
|
|
6
|
+
return hostname === 'sanity.io' || hostname.endsWith('.sanity.io');
|
|
7
|
+
}
|
|
8
|
+
function parseDocsInput(input) {
|
|
9
|
+
try {
|
|
10
|
+
const url = new URL(input);
|
|
11
|
+
if (isSanityHostname(url.hostname)) {
|
|
12
|
+
return {
|
|
13
|
+
readPath: url.pathname,
|
|
14
|
+
webPath: `${url.pathname}${url.search}${url.hash}`
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
} catch {
|
|
18
|
+
// Input is not an absolute URL.
|
|
19
|
+
}
|
|
20
|
+
if (input.startsWith('/') && !input.startsWith('//')) {
|
|
21
|
+
const url = new URL(input, 'https://www.sanity.io');
|
|
22
|
+
return {
|
|
23
|
+
readPath: url.pathname,
|
|
24
|
+
webPath: `${url.pathname}${url.search}${url.hash}`
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
readPath: input,
|
|
29
|
+
webPath: input
|
|
30
|
+
};
|
|
31
|
+
}
|
|
6
32
|
export class DocsReadCommand extends SanityCommand {
|
|
7
33
|
static args = {
|
|
8
34
|
path: Args.string({
|
|
@@ -41,32 +67,27 @@ export class DocsReadCommand extends SanityCommand {
|
|
|
41
67
|
const { args, flags } = await this.parse(DocsReadCommand);
|
|
42
68
|
const { path: input } = args;
|
|
43
69
|
const { web } = flags;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// Validate the normalized path
|
|
47
|
-
if (!path.startsWith('/')) {
|
|
70
|
+
const { readPath, webPath } = parseDocsInput(input);
|
|
71
|
+
if (!readPath.startsWith('/')) {
|
|
48
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', {
|
|
49
73
|
exit: 1
|
|
50
74
|
});
|
|
51
75
|
}
|
|
52
|
-
|
|
53
|
-
if (path.includes('..') || !path.startsWith('/docs/')) {
|
|
76
|
+
if (readPath.includes('..') || !readPath.startsWith('/docs/')) {
|
|
54
77
|
this.error('Invalid path. Must be a valid Sanity docs path starting with /docs/\nExample: /docs/studio/installation', {
|
|
55
78
|
exit: 1
|
|
56
79
|
});
|
|
57
80
|
}
|
|
58
|
-
// Open in web browser if --web or -w flag is provided
|
|
59
81
|
if (web) {
|
|
60
|
-
const url = `https://www.sanity.io${
|
|
82
|
+
const url = `https://www.sanity.io${webPath}`;
|
|
61
83
|
this.log(`Opening ${url}`);
|
|
62
84
|
await open(url);
|
|
63
85
|
return;
|
|
64
86
|
}
|
|
65
|
-
|
|
66
|
-
this.log(`Reading article: ${path}`);
|
|
87
|
+
this.log(`Reading article: ${readPath}`);
|
|
67
88
|
try {
|
|
68
89
|
const content = await readDoc({
|
|
69
|
-
path
|
|
90
|
+
path: readPath
|
|
70
91
|
});
|
|
71
92
|
this.log('\n---\n');
|
|
72
93
|
this.log(content);
|
|
@@ -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 {
|
|
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"}
|
package/dist/commands/init.js
CHANGED
|
@@ -202,6 +202,11 @@ export class InitCommand extends SanityCommand {
|
|
|
202
202
|
description: 'Reconfigure an existing project',
|
|
203
203
|
hidden: true
|
|
204
204
|
}),
|
|
205
|
+
skills: Flags.boolean({
|
|
206
|
+
allowNo: true,
|
|
207
|
+
default: true,
|
|
208
|
+
description: 'Install Sanity agent skills globally for detected AI editors'
|
|
209
|
+
}),
|
|
205
210
|
template: Flags.string({
|
|
206
211
|
description: 'Project template to use [default: "clean"]',
|
|
207
212
|
exclusive: [
|
|
@@ -244,8 +249,14 @@ export class InitCommand extends SanityCommand {
|
|
|
244
249
|
} else if (this.flags.yes) {
|
|
245
250
|
mcpMode = 'auto';
|
|
246
251
|
}
|
|
252
|
+
// Mirror MCP's environment gating: skip skills install in non-production
|
|
253
|
+
// Sanity envs so e2e / UI tests don't run the bundled skills CLI.
|
|
254
|
+
let skillsMode = 'auto';
|
|
255
|
+
if (!this.flags.skills || !this.resolveIsInteractive() || getSanityEnv() !== 'production') {
|
|
256
|
+
skillsMode = 'skip';
|
|
257
|
+
}
|
|
247
258
|
try {
|
|
248
|
-
await initAction(flagsToInitOptions(this.flags, this.isUnattended(), this.args, mcpMode), {
|
|
259
|
+
await initAction(flagsToInitOptions(this.flags, this.isUnattended(), this.args, mcpMode, skillsMode), {
|
|
249
260
|
output: this.output,
|
|
250
261
|
telemetry: this.telemetry,
|
|
251
262
|
workDir: process.cwd()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/commands/init.ts"],"sourcesContent":["import {Args, Command, Flags} from '@oclif/core'\nimport {CLIError} from '@oclif/core/errors'\nimport {SanityCommand} from '@sanity/cli-core'\n\nimport {initAction} from '../actions/init/initAction.js'\nimport {InitError} from '../actions/init/initError.js'\nimport {flagsToInitOptions} from '../actions/init/types.js'\nimport {getSanityEnv} from '../util/getSanityEnv.js'\n\nexport class InitCommand extends SanityCommand<typeof InitCommand> {\n static override args = {type: Args.string({hidden: true})}\n static override description = 'Initialize a new Sanity Studio, project and/or app'\n static override enableJsonFlag = true\n\n static override examples = [\n '<%= config.bin %> <%= command.id %>',\n {\n command: '<%= config.bin %> <%= command.id %> --dataset-default',\n description: 'Initialize a new project with a public dataset named \"production\"',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> -y --project abc123 --dataset production --output-path ~/myproj',\n description: 'Initialize a project with the given project ID and dataset to the given path',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> -y --project abc123 --dataset staging --template moviedb --output-path .',\n description:\n 'Initialize a project with the given project ID and dataset using the moviedb template to the given path',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> -y --project-name \"Movies Unlimited\" --dataset moviedb --visibility private --template moviedb --output-path /Users/espenh/movies-unlimited',\n description: 'Create a brand new project with name \"Movies Unlimited\"',\n },\n ] satisfies Array<Command.Example>\n\n static override flags = {\n 'auto-updates': Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Enable auto updates of studio versions',\n exclusive: ['bare'],\n }),\n bare: Flags.boolean({\n description:\n 'Skip the Studio initialization and only print the selected project ID and dataset name to stdout',\n }),\n coupon: Flags.string({\n description:\n 'Optionally select a coupon for a new project (cannot be used with --project-plan)',\n exclusive: ['project-plan'],\n helpValue: '<code>',\n }),\n 'create-project': Flags.string({\n deprecated: {message: 'Use --project-name instead'},\n description: 'Create a new project with the given name',\n helpValue: '<name>',\n hidden: true,\n }),\n dataset: Flags.string({\n description: 'Dataset name for the studio',\n exclusive: ['dataset-default'],\n helpValue: '<name>',\n }),\n 'dataset-default': Flags.boolean({\n description: 'Set up a project with a public dataset named \"production\"',\n }),\n env: Flags.string({\n description: 'Write environment variables to file',\n exclusive: ['bare'],\n helpValue: '<filename>',\n parse: async (input) => {\n if (!input.startsWith('.env')) {\n throw new CLIError('Env filename (`--env`) must start with `.env`')\n }\n return input\n },\n }),\n 'from-create': Flags.boolean({\n description: 'Internal flag to indicate that the command is run from create-sanity',\n hidden: true,\n }),\n git: Flags.string({\n default: undefined,\n description: 'Specify a commit message for initial commit, or disable git init',\n exclusive: ['bare'],\n // oclif doesn't indent correctly with custom help labels, thus leading space :/\n helpLabel: ' --[no-]git',\n helpValue: '<message>',\n }),\n 'import-dataset': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Import template sample dataset',\n }),\n mcp: Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Enable AI editor integration (MCP) setup',\n }),\n 'nextjs-add-config-files': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Add config files to Next.js project',\n helpGroup: 'Next.js',\n }),\n 'nextjs-append-env': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Append project ID and dataset to .env file',\n helpGroup: 'Next.js',\n }),\n 'nextjs-embed-studio': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Embed the Studio in Next.js application',\n helpGroup: 'Next.js',\n }),\n // oclif doesn't support a boolean/string flag combination, but listing both a\n // `--git` and a `--no-git` flag in help breaks conventions, so we hide this one,\n // but use it to \"combine\" the two in the actual logic.\n 'no-git': Flags.boolean({\n description: 'Disable git initialization',\n exclusive: ['git'],\n hidden: true,\n }),\n organization: Flags.string({\n description: 'Organization ID to use for the project',\n helpValue: '<id>',\n }),\n 'output-path': Flags.string({\n description: 'Path to write studio project to',\n exclusive: ['bare'],\n helpValue: '<path>',\n }),\n 'overwrite-files': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Overwrite existing files',\n }),\n 'package-manager': Flags.string({\n description: 'Specify which package manager to use [allowed: npm, yarn, pnpm]',\n exclusive: ['bare'],\n helpValue: '<manager>',\n options: ['npm', 'yarn', 'pnpm'],\n }),\n project: Flags.string({\n aliases: ['project-id'],\n description: 'Project ID to use for the studio',\n exclusive: ['create-project', 'project-name'],\n helpValue: '<id>',\n }),\n 'project-name': Flags.string({\n description: 'Create a new project with the given name',\n exclusive: ['project', 'create-project'],\n helpValue: '<name>',\n }),\n 'project-plan': Flags.string({\n description: 'Optionally select a plan for a new project',\n helpValue: '<name>',\n }),\n provider: Flags.string({\n description: 'Login provider to use',\n helpValue: '<provider>',\n }),\n quickstart: Flags.boolean({\n deprecated: true,\n description:\n 'Used for initializing a project from a server schema that is saved in the Journey API',\n hidden: true,\n }),\n reconfigure: Flags.boolean({\n deprecated: {\n message: 'This flag is no longer supported',\n version: '3.0.0',\n },\n description: 'Reconfigure an existing project',\n hidden: true,\n }),\n template: Flags.string({\n description: 'Project template to use [default: \"clean\"]',\n exclusive: ['bare'],\n helpValue: '<template>',\n }),\n // Porting over a beta flag\n // Oclif doesn't seem to support something in beta so hiding for now\n 'template-token': Flags.string({\n description: 'Used for accessing private GitHub repo templates',\n hidden: true,\n }),\n typescript: Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Enable TypeScript support',\n exclusive: ['bare'],\n }),\n visibility: Flags.string({\n description: 'Visibility mode for dataset',\n helpValue: '<mode>',\n options: ['public', 'private'],\n }),\n yes: Flags.boolean({\n char: 'y',\n default: false,\n description:\n 'Unattended mode, answers \"yes\" to any \"yes/no\" prompt and otherwise uses defaults',\n }),\n }\n\n public async run(): Promise<void> {\n let mcpMode: 'auto' | 'prompt' | 'skip' = 'prompt'\n if (!this.flags.mcp || !this.resolveIsInteractive() || getSanityEnv() !== 'production') {\n mcpMode = 'skip'\n } else if (this.flags.yes) {\n mcpMode = 'auto'\n }\n\n try {\n await initAction(flagsToInitOptions(this.flags, this.isUnattended(), this.args, mcpMode), {\n output: this.output,\n telemetry: this.telemetry,\n workDir: process.cwd(),\n })\n } catch (error) {\n if (error instanceof InitError) {\n this.error(error.message, {exit: error.exitCode})\n }\n throw error\n }\n }\n}\n"],"names":["Args","Flags","CLIError","SanityCommand","initAction","InitError","flagsToInitOptions","getSanityEnv","InitCommand","args","type","string","hidden","description","enableJsonFlag","examples","command","flags","boolean","allowNo","default","exclusive","bare","coupon","helpValue","deprecated","message","dataset","env","parse","input","startsWith","git","undefined","helpLabel","mcp","helpGroup","organization","options","project","aliases","provider","quickstart","reconfigure","version","template","typescript","visibility","yes","char","run","mcpMode","resolveIsInteractive","isUnattended","output","telemetry","workDir","process","cwd","error","exit","exitCode"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/commands/init.ts"],"sourcesContent":["import {Args, Command, Flags} from '@oclif/core'\nimport {CLIError} from '@oclif/core/errors'\nimport {SanityCommand} from '@sanity/cli-core'\n\nimport {initAction} from '../actions/init/initAction.js'\nimport {InitError} from '../actions/init/initError.js'\nimport {flagsToInitOptions} from '../actions/init/types.js'\nimport {getSanityEnv} from '../util/getSanityEnv.js'\n\nexport class InitCommand extends SanityCommand<typeof InitCommand> {\n static override args = {type: Args.string({hidden: true})}\n static override description = 'Initialize a new Sanity Studio, project and/or app'\n static override enableJsonFlag = true\n\n static override examples = [\n '<%= config.bin %> <%= command.id %>',\n {\n command: '<%= config.bin %> <%= command.id %> --dataset-default',\n description: 'Initialize a new project with a public dataset named \"production\"',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> -y --project abc123 --dataset production --output-path ~/myproj',\n description: 'Initialize a project with the given project ID and dataset to the given path',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> -y --project abc123 --dataset staging --template moviedb --output-path .',\n description:\n 'Initialize a project with the given project ID and dataset using the moviedb template to the given path',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> -y --project-name \"Movies Unlimited\" --dataset moviedb --visibility private --template moviedb --output-path /Users/espenh/movies-unlimited',\n description: 'Create a brand new project with name \"Movies Unlimited\"',\n },\n ] satisfies Array<Command.Example>\n\n static override flags = {\n 'auto-updates': Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Enable auto updates of studio versions',\n exclusive: ['bare'],\n }),\n bare: Flags.boolean({\n description:\n 'Skip the Studio initialization and only print the selected project ID and dataset name to stdout',\n }),\n coupon: Flags.string({\n description:\n 'Optionally select a coupon for a new project (cannot be used with --project-plan)',\n exclusive: ['project-plan'],\n helpValue: '<code>',\n }),\n 'create-project': Flags.string({\n deprecated: {message: 'Use --project-name instead'},\n description: 'Create a new project with the given name',\n helpValue: '<name>',\n hidden: true,\n }),\n dataset: Flags.string({\n description: 'Dataset name for the studio',\n exclusive: ['dataset-default'],\n helpValue: '<name>',\n }),\n 'dataset-default': Flags.boolean({\n description: 'Set up a project with a public dataset named \"production\"',\n }),\n env: Flags.string({\n description: 'Write environment variables to file',\n exclusive: ['bare'],\n helpValue: '<filename>',\n parse: async (input) => {\n if (!input.startsWith('.env')) {\n throw new CLIError('Env filename (`--env`) must start with `.env`')\n }\n return input\n },\n }),\n 'from-create': Flags.boolean({\n description: 'Internal flag to indicate that the command is run from create-sanity',\n hidden: true,\n }),\n git: Flags.string({\n default: undefined,\n description: 'Specify a commit message for initial commit, or disable git init',\n exclusive: ['bare'],\n // oclif doesn't indent correctly with custom help labels, thus leading space :/\n helpLabel: ' --[no-]git',\n helpValue: '<message>',\n }),\n 'import-dataset': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Import template sample dataset',\n }),\n mcp: Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Enable AI editor integration (MCP) setup',\n }),\n 'nextjs-add-config-files': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Add config files to Next.js project',\n helpGroup: 'Next.js',\n }),\n 'nextjs-append-env': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Append project ID and dataset to .env file',\n helpGroup: 'Next.js',\n }),\n 'nextjs-embed-studio': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Embed the Studio in Next.js application',\n helpGroup: 'Next.js',\n }),\n // oclif doesn't support a boolean/string flag combination, but listing both a\n // `--git` and a `--no-git` flag in help breaks conventions, so we hide this one,\n // but use it to \"combine\" the two in the actual logic.\n 'no-git': Flags.boolean({\n description: 'Disable git initialization',\n exclusive: ['git'],\n hidden: true,\n }),\n organization: Flags.string({\n description: 'Organization ID to use for the project',\n helpValue: '<id>',\n }),\n 'output-path': Flags.string({\n description: 'Path to write studio project to',\n exclusive: ['bare'],\n helpValue: '<path>',\n }),\n 'overwrite-files': Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Overwrite existing files',\n }),\n 'package-manager': Flags.string({\n description: 'Specify which package manager to use [allowed: npm, yarn, pnpm]',\n exclusive: ['bare'],\n helpValue: '<manager>',\n options: ['npm', 'yarn', 'pnpm'],\n }),\n project: Flags.string({\n aliases: ['project-id'],\n description: 'Project ID to use for the studio',\n exclusive: ['create-project', 'project-name'],\n helpValue: '<id>',\n }),\n 'project-name': Flags.string({\n description: 'Create a new project with the given name',\n exclusive: ['project', 'create-project'],\n helpValue: '<name>',\n }),\n 'project-plan': Flags.string({\n description: 'Optionally select a plan for a new project',\n helpValue: '<name>',\n }),\n provider: Flags.string({\n description: 'Login provider to use',\n helpValue: '<provider>',\n }),\n quickstart: Flags.boolean({\n deprecated: true,\n description:\n 'Used for initializing a project from a server schema that is saved in the Journey API',\n hidden: true,\n }),\n reconfigure: Flags.boolean({\n deprecated: {\n message: 'This flag is no longer supported',\n version: '3.0.0',\n },\n description: 'Reconfigure an existing project',\n hidden: true,\n }),\n skills: Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Install Sanity agent skills globally for detected AI editors',\n }),\n template: Flags.string({\n description: 'Project template to use [default: \"clean\"]',\n exclusive: ['bare'],\n helpValue: '<template>',\n }),\n // Porting over a beta flag\n // Oclif doesn't seem to support something in beta so hiding for now\n 'template-token': Flags.string({\n description: 'Used for accessing private GitHub repo templates',\n hidden: true,\n }),\n typescript: Flags.boolean({\n allowNo: true,\n default: undefined,\n description: 'Enable TypeScript support',\n exclusive: ['bare'],\n }),\n visibility: Flags.string({\n description: 'Visibility mode for dataset',\n helpValue: '<mode>',\n options: ['public', 'private'],\n }),\n yes: Flags.boolean({\n char: 'y',\n default: false,\n description:\n 'Unattended mode, answers \"yes\" to any \"yes/no\" prompt and otherwise uses defaults',\n }),\n }\n\n public async run(): Promise<void> {\n let mcpMode: 'auto' | 'prompt' | 'skip' = 'prompt'\n if (!this.flags.mcp || !this.resolveIsInteractive() || getSanityEnv() !== 'production') {\n mcpMode = 'skip'\n } else if (this.flags.yes) {\n mcpMode = 'auto'\n }\n\n // Mirror MCP's environment gating: skip skills install in non-production\n // Sanity envs so e2e / UI tests don't run the bundled skills CLI.\n let skillsMode: 'auto' | 'prompt' | 'skip' = 'auto'\n if (!this.flags.skills || !this.resolveIsInteractive() || getSanityEnv() !== 'production') {\n skillsMode = 'skip'\n }\n\n try {\n await initAction(\n flagsToInitOptions(this.flags, this.isUnattended(), this.args, mcpMode, skillsMode),\n {\n output: this.output,\n telemetry: this.telemetry,\n workDir: process.cwd(),\n },\n )\n } catch (error) {\n if (error instanceof InitError) {\n this.error(error.message, {exit: error.exitCode})\n }\n throw error\n }\n }\n}\n"],"names":["Args","Flags","CLIError","SanityCommand","initAction","InitError","flagsToInitOptions","getSanityEnv","InitCommand","args","type","string","hidden","description","enableJsonFlag","examples","command","flags","boolean","allowNo","default","exclusive","bare","coupon","helpValue","deprecated","message","dataset","env","parse","input","startsWith","git","undefined","helpLabel","mcp","helpGroup","organization","options","project","aliases","provider","quickstart","reconfigure","version","skills","template","typescript","visibility","yes","char","run","mcpMode","resolveIsInteractive","skillsMode","isUnattended","output","telemetry","workDir","process","cwd","error","exit","exitCode"],"mappings":"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"}
|
package/dist/commands/login.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { text } from 'node:stream/consumers';
|
|
1
2
|
import { Flags } from '@oclif/core';
|
|
2
3
|
import { SanityCommand } from '@sanity/cli-core';
|
|
3
4
|
import { login } from '../actions/auth/login/login.js';
|
|
@@ -19,6 +20,10 @@ export class LoginCommand extends SanityCommand {
|
|
|
19
20
|
{
|
|
20
21
|
command: '<%= config.bin %> <%= command.id %> --sso my-organization --sso-provider "Okta SSO"',
|
|
21
22
|
description: 'Log in using a specific SSO provider within an organization'
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
command: '<%= config.bin %> <%= command.id %> --with-token < token.txt',
|
|
26
|
+
description: 'Log in using a token from standard input'
|
|
22
27
|
}
|
|
23
28
|
];
|
|
24
29
|
static flags = {
|
|
@@ -34,14 +39,16 @@ export class LoginCommand extends SanityCommand {
|
|
|
34
39
|
provider: Flags.string({
|
|
35
40
|
description: 'Log in using the given provider',
|
|
36
41
|
exclusive: [
|
|
37
|
-
'sso'
|
|
42
|
+
'sso',
|
|
43
|
+
'with-token'
|
|
38
44
|
],
|
|
39
45
|
helpValue: '<providerId>'
|
|
40
46
|
}),
|
|
41
47
|
sso: Flags.string({
|
|
42
48
|
description: 'Log in using Single Sign-On, using the given organization slug',
|
|
43
49
|
exclusive: [
|
|
44
|
-
'provider'
|
|
50
|
+
'provider',
|
|
51
|
+
'with-token'
|
|
45
52
|
],
|
|
46
53
|
helpValue: '<slug>'
|
|
47
54
|
}),
|
|
@@ -51,16 +58,26 @@ export class LoginCommand extends SanityCommand {
|
|
|
51
58
|
],
|
|
52
59
|
description: 'Select a specific SSO provider by name (use with --sso)',
|
|
53
60
|
helpValue: '<name>'
|
|
61
|
+
}),
|
|
62
|
+
'with-token': Flags.boolean({
|
|
63
|
+
description: 'Read token from standard input',
|
|
64
|
+
exclusive: [
|
|
65
|
+
'provider',
|
|
66
|
+
'sso'
|
|
67
|
+
]
|
|
54
68
|
})
|
|
55
69
|
};
|
|
56
70
|
async run() {
|
|
57
71
|
const { flags } = await this.parse(LoginCommand);
|
|
72
|
+
const { 'sso-provider': ssoProvider, 'with-token': withToken, ...loginFlags } = flags;
|
|
58
73
|
try {
|
|
74
|
+
const token = withToken ? await readTokenFromStdin() : undefined;
|
|
59
75
|
await login({
|
|
60
|
-
...
|
|
76
|
+
...loginFlags,
|
|
61
77
|
output: this.output,
|
|
62
|
-
ssoProvider
|
|
63
|
-
telemetry: this.telemetry
|
|
78
|
+
ssoProvider,
|
|
79
|
+
telemetry: this.telemetry,
|
|
80
|
+
token
|
|
64
81
|
});
|
|
65
82
|
this.log('Login successful');
|
|
66
83
|
} catch (error) {
|
|
@@ -71,5 +88,11 @@ export class LoginCommand extends SanityCommand {
|
|
|
71
88
|
}
|
|
72
89
|
}
|
|
73
90
|
}
|
|
91
|
+
async function readTokenFromStdin() {
|
|
92
|
+
if (process.stdin.isTTY) {
|
|
93
|
+
throw new Error('Token is required on standard input. Run `sanity login --with-token < token.txt`.');
|
|
94
|
+
}
|
|
95
|
+
return text(process.stdin);
|
|
96
|
+
}
|
|
74
97
|
|
|
75
98
|
//# sourceMappingURL=login.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/commands/login.ts"],"sourcesContent":["import {Command, Flags} from '@oclif/core'\nimport {type FlagInput} from '@oclif/core/interfaces'\nimport {SanityCommand} from '@sanity/cli-core'\n\nimport {login} from '../actions/auth/login/login.js'\n\nexport class LoginCommand extends SanityCommand<typeof LoginCommand> {\n static override description = 'Log in to your Sanity account'\n static override examples: Array<Command.Example> = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Log in using default settings',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --provider github --no-open',\n description: 'Login with GitHub provider, but do not open a browser window automatically',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --sso my-organization',\n description: 'Log in using Single Sign-On with the \"my-organization\" slug',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> --sso my-organization --sso-provider \"Okta SSO\"',\n description: 'Log in using a specific SSO provider within an organization',\n },\n ]\n static override flags = {\n experimental: Flags.boolean({\n default: false,\n hidden: true,\n }),\n open: Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Open a browser window to log in (`--no-open` only prints URL)',\n }),\n provider: Flags.string({\n description: 'Log in using the given provider',\n exclusive: ['sso'],\n helpValue: '<providerId>',\n }),\n sso: Flags.string({\n description: 'Log in using Single Sign-On, using the given organization slug',\n exclusive: ['provider'],\n helpValue: '<slug>',\n }),\n 'sso-provider': Flags.string({\n dependsOn: ['sso'],\n description: 'Select a specific SSO provider by name (use with --sso)',\n helpValue: '<name>',\n }),\n } satisfies FlagInput\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(LoginCommand)\n\n try {\n await login({\n ...
|
|
1
|
+
{"version":3,"sources":["../../src/commands/login.ts"],"sourcesContent":["import {text} from 'node:stream/consumers'\n\nimport {Command, Flags} from '@oclif/core'\nimport {type FlagInput} from '@oclif/core/interfaces'\nimport {SanityCommand} from '@sanity/cli-core'\n\nimport {login} from '../actions/auth/login/login.js'\n\nexport class LoginCommand extends SanityCommand<typeof LoginCommand> {\n static override description = 'Log in to your Sanity account'\n static override examples: Array<Command.Example> = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Log in using default settings',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --provider github --no-open',\n description: 'Login with GitHub provider, but do not open a browser window automatically',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --sso my-organization',\n description: 'Log in using Single Sign-On with the \"my-organization\" slug',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> --sso my-organization --sso-provider \"Okta SSO\"',\n description: 'Log in using a specific SSO provider within an organization',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --with-token < token.txt',\n description: 'Log in using a token from standard input',\n },\n ]\n static override flags = {\n experimental: Flags.boolean({\n default: false,\n hidden: true,\n }),\n open: Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Open a browser window to log in (`--no-open` only prints URL)',\n }),\n provider: Flags.string({\n description: 'Log in using the given provider',\n exclusive: ['sso', 'with-token'],\n helpValue: '<providerId>',\n }),\n sso: Flags.string({\n description: 'Log in using Single Sign-On, using the given organization slug',\n exclusive: ['provider', 'with-token'],\n helpValue: '<slug>',\n }),\n 'sso-provider': Flags.string({\n dependsOn: ['sso'],\n description: 'Select a specific SSO provider by name (use with --sso)',\n helpValue: '<name>',\n }),\n 'with-token': Flags.boolean({\n description: 'Read token from standard input',\n exclusive: ['provider', 'sso'],\n }),\n } satisfies FlagInput\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(LoginCommand)\n const {'sso-provider': ssoProvider, 'with-token': withToken, ...loginFlags} = flags\n\n try {\n const token = withToken ? await readTokenFromStdin() : undefined\n\n await login({\n ...loginFlags,\n output: this.output,\n ssoProvider,\n telemetry: this.telemetry,\n token,\n })\n this.log('Login successful')\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.error(`Login failed: ${message}`, {exit: 1})\n }\n }\n}\n\nasync function readTokenFromStdin(): Promise<string> {\n if (process.stdin.isTTY) {\n throw new Error(\n 'Token is required on standard input. Run `sanity login --with-token < token.txt`.',\n )\n }\n\n return text(process.stdin)\n}\n"],"names":["text","Flags","SanityCommand","login","LoginCommand","description","examples","command","flags","experimental","boolean","default","hidden","open","allowNo","provider","string","exclusive","helpValue","sso","dependsOn","run","parse","ssoProvider","withToken","loginFlags","token","readTokenFromStdin","undefined","output","telemetry","log","error","message","Error","String","exit","process","stdin","isTTY"],"mappings":"AAAA,SAAQA,IAAI,QAAO,wBAAuB;AAE1C,SAAiBC,KAAK,QAAO,cAAa;AAE1C,SAAQC,aAAa,QAAO,mBAAkB;AAE9C,SAAQC,KAAK,QAAO,iCAAgC;AAEpD,OAAO,MAAMC,qBAAqBF;IAChC,OAAgBG,cAAc,gCAA+B;IAC7D,OAAgBC,WAAmC;QACjD;YACEC,SAAS;YACTF,aAAa;QACf;QACA;YACEE,SAAS;YACTF,aAAa;QACf;QACA;YACEE,SAAS;YACTF,aAAa;QACf;QACA;YACEE,SACE;YACFF,aAAa;QACf;QACA;YACEE,SAAS;YACTF,aAAa;QACf;KACD,CAAA;IACD,OAAgBG,QAAQ;QACtBC,cAAcR,MAAMS,OAAO,CAAC;YAC1BC,SAAS;YACTC,QAAQ;QACV;QACAC,MAAMZ,MAAMS,OAAO,CAAC;YAClBI,SAAS;YACTH,SAAS;YACTN,aAAa;QACf;QACAU,UAAUd,MAAMe,MAAM,CAAC;YACrBX,aAAa;YACbY,WAAW;gBAAC;gBAAO;aAAa;YAChCC,WAAW;QACb;QACAC,KAAKlB,MAAMe,MAAM,CAAC;YAChBX,aAAa;YACbY,WAAW;gBAAC;gBAAY;aAAa;YACrCC,WAAW;QACb;QACA,gBAAgBjB,MAAMe,MAAM,CAAC;YAC3BI,WAAW;gBAAC;aAAM;YAClBf,aAAa;YACba,WAAW;QACb;QACA,cAAcjB,MAAMS,OAAO,CAAC;YAC1BL,aAAa;YACbY,WAAW;gBAAC;gBAAY;aAAM;QAChC;IACF,EAAqB;IAErB,MAAaI,MAAqB;QAChC,MAAM,EAACb,KAAK,EAAC,GAAG,MAAM,IAAI,CAACc,KAAK,CAAClB;QACjC,MAAM,EAAC,gBAAgBmB,WAAW,EAAE,cAAcC,SAAS,EAAE,GAAGC,YAAW,GAAGjB;QAE9E,IAAI;YACF,MAAMkB,QAAQF,YAAY,MAAMG,uBAAuBC;YAEvD,MAAMzB,MAAM;gBACV,GAAGsB,UAAU;gBACbI,QAAQ,IAAI,CAACA,MAAM;gBACnBN;gBACAO,WAAW,IAAI,CAACA,SAAS;gBACzBJ;YACF;YACA,IAAI,CAACK,GAAG,CAAC;QACX,EAAE,OAAOC,OAAO;YACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;YAChE,IAAI,CAACA,KAAK,CAAC,CAAC,cAAc,EAAEC,SAAS,EAAE;gBAACG,MAAM;YAAC;QACjD;IACF;AACF;AAEA,eAAeT;IACb,IAAIU,QAAQC,KAAK,CAACC,KAAK,EAAE;QACvB,MAAM,IAAIL,MACR;IAEJ;IAEA,OAAOlC,KAAKqC,QAAQC,KAAK;AAC3B"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
|
+
import { formatSchemaValidation, SchemaExtractionError } from '@sanity/cli-build/_internal/extract';
|
|
2
3
|
import { SanityCommand } from '@sanity/cli-core';
|
|
3
4
|
import { manifestDebug } from '../../actions/manifest/debug.js';
|
|
4
5
|
import { extractManifest } from '../../actions/manifest/extractManifest.js';
|
|
5
|
-
import { formatSchemaValidation } from '../../actions/schema/formatSchemaValidation.js';
|
|
6
|
-
import { SchemaExtractionError } from '../../actions/schema/utils/SchemaExtractionError.js';
|
|
7
6
|
const description = `
|
|
8
7
|
Extract studio configuration as JSON manifest files.
|
|
9
8
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/manifest/extract.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/manifest/extract.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {formatSchemaValidation, SchemaExtractionError} from '@sanity/cli-build/_internal/extract'\nimport {SanityCommand} from '@sanity/cli-core'\n\nimport {manifestDebug} from '../../actions/manifest/debug.js'\nimport {extractManifest} from '../../actions/manifest/extractManifest.js'\n\nconst description = `\nExtract studio configuration as JSON manifest files.\n\nNote: This command is experimental and subject to change. It is currently intended for use with Create only.\n`.trim()\n\nexport class ExtractManifestCommand extends SanityCommand<typeof ExtractManifestCommand> {\n static override description = description\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Extracts manifests',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --path /public/static',\n description: 'Extracts manifests into /public/static',\n },\n ]\n\n static override flags = {\n path: Flags.string({\n default: 'dist/static',\n description: 'Optional path to specify destination directory of the manifest files',\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(ExtractManifestCommand)\n\n try {\n await extractManifest(flags.path)\n } catch (error) {\n manifestDebug('Error extracting manifest in command', error)\n if (\n error instanceof SchemaExtractionError &&\n error.validation &&\n error.validation.length > 0\n ) {\n this.output.log(formatSchemaValidation(error.validation))\n this.exit(1)\n }\n\n this.error(\n `Failed to extract manifest:\\n${error instanceof Error ? error.message : String(error)}`,\n {exit: 1},\n )\n }\n }\n}\n"],"names":["Flags","formatSchemaValidation","SchemaExtractionError","SanityCommand","manifestDebug","extractManifest","description","trim","ExtractManifestCommand","examples","command","flags","path","string","default","run","parse","error","validation","length","output","log","exit","Error","message","String"],"mappings":"AAAA,SAAQA,KAAK,QAAO,cAAa;AACjC,SAAQC,sBAAsB,EAAEC,qBAAqB,QAAO,sCAAqC;AACjG,SAAQC,aAAa,QAAO,mBAAkB;AAE9C,SAAQC,aAAa,QAAO,kCAAiC;AAC7D,SAAQC,eAAe,QAAO,4CAA2C;AAEzE,MAAMC,cAAc,CAAC;;;;AAIrB,CAAC,CAACC,IAAI;AAEN,OAAO,MAAMC,+BAA+BL;IAC1C,OAAgBG,cAAcA,YAAW;IAEzC,OAAgBG,WAAW;QACzB;YACEC,SAAS;YACTJ,aAAa;QACf;QACA;YACEI,SAAS;YACTJ,aAAa;QACf;KACD,CAAA;IAED,OAAgBK,QAAQ;QACtBC,MAAMZ,MAAMa,MAAM,CAAC;YACjBC,SAAS;YACTR,aAAa;QACf;IACF,EAAC;IAED,MAAaS,MAAqB;QAChC,MAAM,EAACJ,KAAK,EAAC,GAAG,MAAM,IAAI,CAACK,KAAK,CAACR;QAEjC,IAAI;YACF,MAAMH,gBAAgBM,MAAMC,IAAI;QAClC,EAAE,OAAOK,OAAO;YACdb,cAAc,wCAAwCa;YACtD,IACEA,iBAAiBf,yBACjBe,MAAMC,UAAU,IAChBD,MAAMC,UAAU,CAACC,MAAM,GAAG,GAC1B;gBACA,IAAI,CAACC,MAAM,CAACC,GAAG,CAACpB,uBAAuBgB,MAAMC,UAAU;gBACvD,IAAI,CAACI,IAAI,CAAC;YACZ;YAEA,IAAI,CAACL,KAAK,CACR,CAAC,6BAA6B,EAAEA,iBAAiBM,QAAQN,MAAMO,OAAO,GAAGC,OAAOR,QAAQ,EACxF;gBAACK,MAAM;YAAC;QAEZ;IACF;AACF"}
|
|
@@ -36,7 +36,8 @@ export class ConfigureMcpCommand extends SanityCommand {
|
|
|
36
36
|
try {
|
|
37
37
|
const mcpResult = await setupMCP({
|
|
38
38
|
explicit: true,
|
|
39
|
-
mode: isInteractive() ? 'prompt' : 'auto'
|
|
39
|
+
mode: isInteractive() ? 'prompt' : 'auto',
|
|
40
|
+
skillsMode: 'skip'
|
|
40
41
|
});
|
|
41
42
|
trace.log({
|
|
42
43
|
configuredEditors: mcpResult.configuredEditors,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/mcp/configure.ts"],"sourcesContent":["import {isInteractive, SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {ensureAuthenticated} from '../../actions/auth/ensureAuthenticated.js'\nimport {setupMCP} from '../../actions/mcp/setupMCP.js'\nimport {LoginError} from '../../errors/LoginError.js'\nimport {MCPConfigureTrace} from '../../telemetry/mcp.telemetry.js'\nimport {getErrorMessage, toError} from '../../util/getErrorMessage.js'\n\nconst debug = subdebug('mcp:configure')\n\nexport class ConfigureMcpCommand extends SanityCommand<typeof ConfigureMcpCommand> {\n static override description =\n 'Configure Sanity MCP server for AI editors (Antigravity, Claude Code, Cline, Cline CLI, Codex CLI, Cursor, Gemini CLI, GitHub Copilot CLI, MCPorter, OpenCode, VS Code, VS Code Insiders, Zed)'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Configure Sanity MCP server for detected AI editors',\n },\n ]\n\n public async run(): Promise<void> {\n const trace = this.telemetry.trace(MCPConfigureTrace)\n trace.start()\n\n try {\n await ensureAuthenticated({output: this.output, telemetry: this.telemetry})\n } catch (error) {\n debug('Authentication check failed: %O', error)\n trace.error(toError(error))\n\n if (error instanceof LoginError) {\n this.error(\n `Failed to verify authentication credentials: ${error.message}. Try running \\`sanity login\\`.`,\n {exit: 1},\n )\n }\n\n this.error(`Failed to check authentication: ${getErrorMessage(error)}`, {exit: 1})\n }\n\n try {\n const mcpResult = await setupMCP({explicit: true
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/mcp/configure.ts"],"sourcesContent":["import {isInteractive, SanityCommand, subdebug} from '@sanity/cli-core'\n\nimport {ensureAuthenticated} from '../../actions/auth/ensureAuthenticated.js'\nimport {setupMCP} from '../../actions/mcp/setupMCP.js'\nimport {LoginError} from '../../errors/LoginError.js'\nimport {MCPConfigureTrace} from '../../telemetry/mcp.telemetry.js'\nimport {getErrorMessage, toError} from '../../util/getErrorMessage.js'\n\nconst debug = subdebug('mcp:configure')\n\nexport class ConfigureMcpCommand extends SanityCommand<typeof ConfigureMcpCommand> {\n static override description =\n 'Configure Sanity MCP server for AI editors (Antigravity, Claude Code, Cline, Cline CLI, Codex CLI, Cursor, Gemini CLI, GitHub Copilot CLI, MCPorter, OpenCode, VS Code, VS Code Insiders, Zed)'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Configure Sanity MCP server for detected AI editors',\n },\n ]\n\n public async run(): Promise<void> {\n const trace = this.telemetry.trace(MCPConfigureTrace)\n trace.start()\n\n try {\n await ensureAuthenticated({output: this.output, telemetry: this.telemetry})\n } catch (error) {\n debug('Authentication check failed: %O', error)\n trace.error(toError(error))\n\n if (error instanceof LoginError) {\n this.error(\n `Failed to verify authentication credentials: ${error.message}. Try running \\`sanity login\\`.`,\n {exit: 1},\n )\n }\n\n this.error(`Failed to check authentication: ${getErrorMessage(error)}`, {exit: 1})\n }\n\n try {\n const mcpResult = await setupMCP({\n explicit: true,\n mode: isInteractive() ? 'prompt' : 'auto',\n skillsMode: 'skip',\n })\n\n trace.log({\n configuredEditors: mcpResult.configuredEditors,\n detectedEditors: mcpResult.detectedEditors,\n })\n\n if (mcpResult.error) {\n trace.error(mcpResult.error)\n } else {\n trace.complete()\n }\n } catch (error) {\n trace.error(toError(error))\n this.error(getErrorMessage(error), {exit: 1})\n }\n }\n}\n"],"names":["isInteractive","SanityCommand","subdebug","ensureAuthenticated","setupMCP","LoginError","MCPConfigureTrace","getErrorMessage","toError","debug","ConfigureMcpCommand","description","examples","command","run","trace","telemetry","start","output","error","message","exit","mcpResult","explicit","mode","skillsMode","log","configuredEditors","detectedEditors","complete"],"mappings":"AAAA,SAAQA,aAAa,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AAEvE,SAAQC,mBAAmB,QAAO,4CAA2C;AAC7E,SAAQC,QAAQ,QAAO,gCAA+B;AACtD,SAAQC,UAAU,QAAO,6BAA4B;AACrD,SAAQC,iBAAiB,QAAO,mCAAkC;AAClE,SAAQC,eAAe,EAAEC,OAAO,QAAO,gCAA+B;AAEtE,MAAMC,QAAQP,SAAS;AAEvB,OAAO,MAAMQ,4BAA4BT;IACvC,OAAgBU,cACd,iMAAgM;IAElM,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTF,aAAa;QACf;KACD,CAAA;IAED,MAAaG,MAAqB;QAChC,MAAMC,QAAQ,IAAI,CAACC,SAAS,CAACD,KAAK,CAACT;QACnCS,MAAME,KAAK;QAEX,IAAI;YACF,MAAMd,oBAAoB;gBAACe,QAAQ,IAAI,CAACA,MAAM;gBAAEF,WAAW,IAAI,CAACA,SAAS;YAAA;QAC3E,EAAE,OAAOG,OAAO;YACdV,MAAM,mCAAmCU;YACzCJ,MAAMI,KAAK,CAACX,QAAQW;YAEpB,IAAIA,iBAAiBd,YAAY;gBAC/B,IAAI,CAACc,KAAK,CACR,CAAC,6CAA6C,EAAEA,MAAMC,OAAO,CAAC,+BAA+B,CAAC,EAC9F;oBAACC,MAAM;gBAAC;YAEZ;YAEA,IAAI,CAACF,KAAK,CAAC,CAAC,gCAAgC,EAAEZ,gBAAgBY,QAAQ,EAAE;gBAACE,MAAM;YAAC;QAClF;QAEA,IAAI;YACF,MAAMC,YAAY,MAAMlB,SAAS;gBAC/BmB,UAAU;gBACVC,MAAMxB,kBAAkB,WAAW;gBACnCyB,YAAY;YACd;YAEAV,MAAMW,GAAG,CAAC;gBACRC,mBAAmBL,UAAUK,iBAAiB;gBAC9CC,iBAAiBN,UAAUM,eAAe;YAC5C;YAEA,IAAIN,UAAUH,KAAK,EAAE;gBACnBJ,MAAMI,KAAK,CAACG,UAAUH,KAAK;YAC7B,OAAO;gBACLJ,MAAMc,QAAQ;YAChB;QACF,EAAE,OAAOV,OAAO;YACdJ,MAAMI,KAAK,CAACX,QAAQW;YACpB,IAAI,CAACA,KAAK,CAACZ,gBAAgBY,QAAQ;gBAACE,MAAM;YAAC;QAC7C;IACF;AACF"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { styleText } from 'node:util';
|
|
2
2
|
import { Flags } from '@oclif/core';
|
|
3
3
|
import { CLIError } from '@oclif/core/errors';
|
|
4
|
+
import { formatSchemaValidation, SchemaExtractionError } from '@sanity/cli-build/_internal/extract';
|
|
4
5
|
import { SanityCommand } from '@sanity/cli-core';
|
|
5
6
|
import { deploySchemas } from '../../actions/schema/deploySchemas.js';
|
|
6
|
-
import { formatSchemaValidation } from '../../actions/schema/formatSchemaValidation.js';
|
|
7
7
|
import { schemasDeployDebug } from '../../actions/schema/utils/debug.js';
|
|
8
|
-
import { SchemaExtractionError } from '../../actions/schema/utils/SchemaExtractionError.js';
|
|
9
8
|
import { parseTag } from '../../actions/schema/utils/schemaStoreValidation.js';
|
|
10
9
|
const description = `
|
|
11
10
|
Deploy schema documents into workspace datasets.
|