@sanity/cli 6.4.0 → 6.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +201 -103
- package/dist/actions/build/buildApp.js +46 -17
- package/dist/actions/build/buildApp.js.map +1 -1
- package/dist/actions/build/buildStaticFiles.js +3 -1
- package/dist/actions/build/buildStaticFiles.js.map +1 -1
- package/dist/actions/build/buildStudio.js +80 -30
- package/dist/actions/build/buildStudio.js.map +1 -1
- package/dist/actions/build/buildVendorDependencies.js +10 -9
- package/dist/actions/build/buildVendorDependencies.js.map +1 -1
- package/dist/actions/build/checkRequiredDependencies.js +6 -9
- package/dist/actions/build/checkRequiredDependencies.js.map +1 -1
- package/dist/actions/build/checkStudioDependencyVersions.js +10 -11
- package/dist/actions/build/checkStudioDependencyVersions.js.map +1 -1
- package/dist/actions/build/getAutoUpdatesImportMap.js +9 -0
- package/dist/actions/build/getAutoUpdatesImportMap.js.map +1 -1
- package/dist/actions/build/getViteConfig.js +4 -2
- package/dist/actions/build/getViteConfig.js.map +1 -1
- package/dist/actions/build/renderDocument.js.map +1 -1
- package/dist/actions/build/renderDocumentWorker/addTimestampImportMapScriptToHtml.js +34 -14
- package/dist/actions/build/renderDocumentWorker/addTimestampImportMapScriptToHtml.js.map +1 -1
- package/dist/actions/build/renderDocumentWorker/getDocumentHtml.js +2 -2
- package/dist/actions/build/renderDocumentWorker/getDocumentHtml.js.map +1 -1
- package/dist/actions/build/renderDocumentWorker/renderDocumentWorker.js +2 -2
- package/dist/actions/build/renderDocumentWorker/renderDocumentWorker.js.map +1 -1
- package/dist/actions/codemods/reactIconsV3.js +3 -3
- package/dist/actions/codemods/reactIconsV3.js.map +1 -1
- package/dist/actions/deploy/deployApp.js +1 -1
- package/dist/actions/deploy/deployApp.js.map +1 -1
- package/dist/actions/deploy/deployStudio.js +1 -2
- package/dist/actions/deploy/deployStudio.js.map +1 -1
- package/dist/actions/dev/startStudioDevServer.js +3 -4
- package/dist/actions/dev/startStudioDevServer.js.map +1 -1
- package/dist/actions/doctor/types.js.map +1 -1
- package/dist/actions/graphql/resolveGraphQLApisFromWorkspaces.js.map +1 -1
- package/dist/actions/init/bootstrapTemplate.js.map +1 -1
- package/dist/actions/init/checkNextJsReactCompatibility.js +3 -3
- package/dist/actions/init/checkNextJsReactCompatibility.js.map +1 -1
- package/dist/actions/init/initAction.js +287 -0
- package/dist/actions/init/initAction.js.map +1 -0
- package/dist/actions/init/initApp.js +7 -16
- package/dist/actions/init/initApp.js.map +1 -1
- package/dist/actions/init/initError.js +10 -0
- package/dist/actions/init/initError.js.map +1 -0
- package/dist/actions/init/initHelpers.js +3 -12
- package/dist/actions/init/initHelpers.js.map +1 -1
- package/dist/actions/init/initNextJs.js +17 -20
- package/dist/actions/init/initNextJs.js.map +1 -1
- package/dist/actions/init/initStudio.js +11 -20
- package/dist/actions/init/initStudio.js.map +1 -1
- package/dist/actions/init/plan/getPlan.js +15 -0
- package/dist/actions/init/plan/getPlan.js.map +1 -0
- package/dist/actions/init/plan/verifyCoupon.js +35 -0
- package/dist/actions/init/plan/verifyCoupon.js.map +1 -0
- package/dist/actions/init/plan/verifyPlan.js +34 -0
- package/dist/actions/init/plan/verifyPlan.js.map +1 -0
- package/dist/actions/init/project/createProjectFromName.js +44 -0
- package/dist/actions/init/project/createProjectFromName.js.map +1 -0
- package/dist/actions/init/project/getOrCreateDataset.js +126 -0
- package/dist/actions/init/project/getOrCreateDataset.js.map +1 -0
- package/dist/actions/init/project/getOrCreateProject.js +128 -0
- package/dist/actions/init/project/getOrCreateProject.js.map +1 -0
- package/dist/actions/init/project/getProjectDetails.js +87 -0
- package/dist/actions/init/project/getProjectDetails.js.map +1 -0
- package/dist/actions/init/project/getProjectOutputPath.js +17 -0
- package/dist/actions/init/project/getProjectOutputPath.js.map +1 -0
- package/dist/actions/init/project/promptForAppTemplateSetup.js +112 -0
- package/dist/actions/init/project/promptForAppTemplateSetup.js.map +1 -0
- package/dist/actions/init/project/promptForProjectCreation.js +40 -0
- package/dist/actions/init/project/promptForProjectCreation.js.map +1 -0
- package/dist/actions/init/project/promptUserForNewOrganization.js +12 -0
- package/dist/actions/init/project/promptUserForNewOrganization.js.map +1 -0
- package/dist/actions/init/project/promptUserForOrganization.js +38 -0
- package/dist/actions/init/project/promptUserForOrganization.js.map +1 -0
- package/dist/actions/init/scaffoldTemplate.js +23 -29
- package/dist/actions/init/scaffoldTemplate.js.map +1 -1
- package/dist/actions/init/types.js +47 -1
- package/dist/actions/init/types.js.map +1 -1
- package/dist/actions/manifest/extractAppManifest.js +3 -2
- package/dist/actions/manifest/extractAppManifest.js.map +1 -1
- package/dist/actions/manifest/types.js +9 -1
- package/dist/actions/manifest/types.js.map +1 -1
- package/dist/actions/manifest/writeManifestFile.js +1 -2
- package/dist/actions/manifest/writeManifestFile.js.map +1 -1
- package/dist/actions/schema/uploadSchemaToLexicon.js +1 -2
- package/dist/actions/schema/uploadSchemaToLexicon.js.map +1 -1
- package/dist/actions/versions/buildPackageArray.js +3 -3
- package/dist/actions/versions/buildPackageArray.js.map +1 -1
- package/dist/actions/versions/findSanityModulesVersions.js +3 -3
- package/dist/actions/versions/findSanityModulesVersions.js.map +1 -1
- package/dist/commands/datasets/copy.js.map +1 -1
- package/dist/commands/init.js +11 -911
- package/dist/commands/init.js.map +1 -1
- package/dist/constants.js +8 -0
- package/dist/constants.js.map +1 -0
- package/dist/server/previewServer.js +1 -1
- package/dist/server/previewServer.js.map +1 -1
- package/dist/server/vite/plugin-sanity-build-entries.js +2 -1
- package/dist/server/vite/plugin-sanity-build-entries.js.map +1 -1
- package/dist/services/datasets.js.map +1 -1
- package/dist/services/userApplications.js.map +1 -1
- package/dist/telemetry/init.telemetry.js.map +1 -1
- package/dist/util/compareDependencyVersions.js +5 -6
- package/dist/util/compareDependencyVersions.js.map +1 -1
- package/dist/util/createExpiringConfig.js +1 -1
- package/dist/util/createExpiringConfig.js.map +1 -1
- package/dist/util/packageManager/installationInfo/analyzeIssues.js +7 -7
- package/dist/util/packageManager/installationInfo/analyzeIssues.js.map +1 -1
- package/dist/util/packageManager/installationInfo/types.js.map +1 -1
- package/dist/util/packageManager/packageManagerChoice.js +2 -2
- package/dist/util/packageManager/packageManagerChoice.js.map +1 -1
- package/dist/util/packageManager/preferredPm.js +106 -0
- package/dist/util/packageManager/preferredPm.js.map +1 -0
- package/oclif.manifest.json +526 -526
- package/package.json +27 -26
- package/dist/util/getLocalPackageVersion.js +0 -55
- package/dist/util/getLocalPackageVersion.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/init/scaffoldTemplate.ts"],"sourcesContent":["import {type Output, type TelemetryUserProperties} from '@sanity/cli-core'\nimport {select} from '@sanity/cli-core/ux'\nimport {type TelemetryTrace} from '@sanity/telemetry'\n\nimport {promptForTypeScript} from '../../prompts/init/promptForTypescript.js'\nimport {type InitStepResult} from '../../telemetry/init.telemetry.js'\nimport {installDeclaredPackages} from '../../util/packageManager/installPackages.js'\nimport {type PackageManager} from '../../util/packageManager/packageManagerChoice.js'\nimport {bootstrapTemplate} from './bootstrapTemplate.js'\nimport {tryGitInit} from './git.js'\nimport {writeStagingEnvIfNeeded} from './initHelpers.js'\nimport {type RepoInfo} from './remoteTemplate.js'\nimport {resolvePackageManager} from './resolvePackageManager.js'\nimport templates from './templates/index.js'\nimport {type ProjectTemplate} from './types.js'\n\ninterface SelectedTemplate {\n template: ProjectTemplate | undefined\n templateName: string\n useTypeScript: boolean
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/init/scaffoldTemplate.ts"],"sourcesContent":["import {type Output, type TelemetryUserProperties} from '@sanity/cli-core'\nimport {select} from '@sanity/cli-core/ux'\nimport {type TelemetryTrace} from '@sanity/telemetry'\n\nimport {promptForTypeScript} from '../../prompts/init/promptForTypescript.js'\nimport {type InitStepResult} from '../../telemetry/init.telemetry.js'\nimport {installDeclaredPackages} from '../../util/packageManager/installPackages.js'\nimport {type PackageManager} from '../../util/packageManager/packageManagerChoice.js'\nimport {bootstrapTemplate} from './bootstrapTemplate.js'\nimport {tryGitInit} from './git.js'\nimport {flagOrDefault, shouldPrompt, writeStagingEnvIfNeeded} from './initHelpers.js'\nimport {type RepoInfo} from './remoteTemplate.js'\nimport {resolvePackageManager} from './resolvePackageManager.js'\nimport templates from './templates/index.js'\nimport {type InitOptions, type ProjectTemplate} from './types.js'\n\ninterface SelectedTemplate {\n template: ProjectTemplate | undefined\n templateName: string\n useTypeScript: boolean\n}\n\nasync function promptForTemplate(params: {\n template?: string\n unattended: boolean\n}): Promise<string> {\n const defaultTemplate = params.unattended || params.template ? params.template || 'clean' : null\n if (defaultTemplate) {\n return defaultTemplate\n }\n\n return select({\n choices: [\n {\n name: 'Clean project with no predefined schema types',\n value: 'clean',\n },\n {\n name: 'Blog (schema)',\n value: 'blog',\n },\n {\n name: 'E-commerce (Shopify)',\n value: 'shopify',\n },\n {\n name: 'Movie project (schema + sample data)',\n value: 'moviedb',\n },\n ],\n message: 'Select project template',\n })\n}\n\nexport async function selectTemplate({\n options,\n remoteTemplateInfo,\n trace,\n}: {\n options: InitOptions\n remoteTemplateInfo: RepoInfo | undefined\n trace: TelemetryTrace<TelemetryUserProperties, InitStepResult>\n}): Promise<SelectedTemplate> {\n const {template, typescript, unattended} = options\n const templateName = await promptForTemplate({template, unattended})\n trace.log({\n selectedOption: templateName,\n step: 'selectProjectTemplate',\n })\n\n const resolvedTemplate = templates[templateName]\n\n let useTypeScript = flagOrDefault(typescript, true)\n if (!remoteTemplateInfo && resolvedTemplate && resolvedTemplate.typescriptOnly === true) {\n useTypeScript = true\n } else if (shouldPrompt(unattended, typescript)) {\n useTypeScript = await promptForTypeScript()\n trace.log({\n selectedOption: useTypeScript ? 'yes' : 'no',\n step: 'useTypeScript',\n })\n }\n\n return {\n template: resolvedTemplate,\n templateName,\n useTypeScript,\n }\n}\n\nexport async function scaffoldAndInstall({\n datasetName,\n defaults,\n displayName,\n options,\n organizationId,\n output,\n outputPath,\n projectId,\n remoteTemplateInfo,\n sluggedName,\n templateName,\n trace,\n useTypeScript,\n workDir,\n}: {\n datasetName: string\n defaults: {projectName: string}\n displayName: string\n options: InitOptions\n organizationId: string | undefined\n output: Output\n outputPath: string\n projectId: string\n remoteTemplateInfo: RepoInfo | undefined\n sluggedName: string\n templateName: string\n trace: TelemetryTrace<TelemetryUserProperties, InitStepResult>\n useTypeScript: boolean\n workDir: string\n}): Promise<{pkgManager: PackageManager}> {\n const {autoUpdates, git, overwriteFiles, packageManager, templateToken, unattended} = options\n const noGit = typeof git === 'boolean' && !git ? true : undefined\n\n await bootstrapTemplate({\n autoUpdates,\n bearerToken: templateToken,\n dataset: datasetName,\n organizationId,\n output,\n outputPath,\n overwriteFiles,\n packageName: sluggedName,\n projectId,\n projectName: displayName || defaults.projectName,\n remoteTemplateInfo,\n templateName,\n useTypeScript,\n })\n\n const pkgManager = await resolvePackageManager({\n interactive: !unattended,\n output,\n packageManager: packageManager as PackageManager,\n targetDir: outputPath,\n })\n\n trace.log({\n selectedOption: pkgManager,\n step: 'selectPackageManager',\n })\n\n // Now for the slow part... installing dependencies\n await installDeclaredPackages(outputPath, pkgManager, {\n output,\n workDir,\n })\n\n const useGit = !noGit && (git === undefined || Boolean(git))\n const commitMessage = git\n await writeStagingEnvIfNeeded(output, outputPath)\n\n // Try initializing a git repository\n if (useGit) {\n tryGitInit(outputPath, typeof commitMessage === 'string' ? commitMessage : undefined)\n }\n\n return {pkgManager}\n}\n"],"names":["select","promptForTypeScript","installDeclaredPackages","bootstrapTemplate","tryGitInit","flagOrDefault","shouldPrompt","writeStagingEnvIfNeeded","resolvePackageManager","templates","promptForTemplate","params","defaultTemplate","unattended","template","choices","name","value","message","selectTemplate","options","remoteTemplateInfo","trace","typescript","templateName","log","selectedOption","step","resolvedTemplate","useTypeScript","typescriptOnly","scaffoldAndInstall","datasetName","defaults","displayName","organizationId","output","outputPath","projectId","sluggedName","workDir","autoUpdates","git","overwriteFiles","packageManager","templateToken","noGit","undefined","bearerToken","dataset","packageName","projectName","pkgManager","interactive","targetDir","useGit","Boolean","commitMessage"],"mappings":"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"}
|
|
@@ -1,3 +1,49 @@
|
|
|
1
|
-
|
|
1
|
+
const VALID_PACKAGE_MANAGERS = new Set([
|
|
2
|
+
'npm',
|
|
3
|
+
'pnpm',
|
|
4
|
+
'yarn'
|
|
5
|
+
]);
|
|
6
|
+
function narrowPackageManager(value) {
|
|
7
|
+
return value !== undefined && VALID_PACKAGE_MANAGERS.has(value) ? value : undefined;
|
|
8
|
+
}
|
|
9
|
+
const VALID_VISIBILITIES = new Set([
|
|
10
|
+
'private',
|
|
11
|
+
'public'
|
|
12
|
+
]);
|
|
13
|
+
function narrowVisibility(value) {
|
|
14
|
+
return value !== undefined && VALID_VISIBILITIES.has(value) ? value : undefined;
|
|
15
|
+
}
|
|
16
|
+
export function flagsToInitOptions(flags, isUnattended, args, mcpMode) {
|
|
17
|
+
return {
|
|
18
|
+
argType: args?.type,
|
|
19
|
+
autoUpdates: flags['auto-updates'],
|
|
20
|
+
bare: flags.bare,
|
|
21
|
+
coupon: flags.coupon,
|
|
22
|
+
dataset: flags.dataset,
|
|
23
|
+
datasetDefault: flags['dataset-default'],
|
|
24
|
+
env: flags.env,
|
|
25
|
+
fromCreate: flags['from-create'],
|
|
26
|
+
git: flags['no-git'] ? false : flags.git,
|
|
27
|
+
importDataset: flags['import-dataset'],
|
|
28
|
+
mcpMode,
|
|
29
|
+
nextjsAddConfigFiles: flags['nextjs-add-config-files'],
|
|
30
|
+
nextjsAppendEnv: flags['nextjs-append-env'],
|
|
31
|
+
nextjsEmbedStudio: flags['nextjs-embed-studio'],
|
|
32
|
+
organization: flags.organization,
|
|
33
|
+
outputPath: flags['output-path'],
|
|
34
|
+
overwriteFiles: flags['overwrite-files'],
|
|
35
|
+
packageManager: narrowPackageManager(flags['package-manager']),
|
|
36
|
+
project: flags.project,
|
|
37
|
+
projectName: flags['project-name'] ?? flags['create-project'],
|
|
38
|
+
projectPlan: flags['project-plan'],
|
|
39
|
+
provider: flags.provider,
|
|
40
|
+
reconfigure: flags.reconfigure,
|
|
41
|
+
template: flags.template,
|
|
42
|
+
templateToken: flags['template-token'],
|
|
43
|
+
typescript: flags.typescript,
|
|
44
|
+
unattended: isUnattended,
|
|
45
|
+
visibility: narrowVisibility(flags.visibility)
|
|
46
|
+
};
|
|
47
|
+
}
|
|
2
48
|
|
|
3
49
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/init/types.ts"],"sourcesContent":["import {Framework} from '@vercel/frameworks'\n\nimport {GenerateConfigOptions} from './createStudioConfig'\n\nexport type VersionedFramework = Framework & {\n detectedVersion?: string\n}\n\nexport interface ProjectTemplate {\n configTemplate?: ((variables: GenerateConfigOptions['variables']) => string) | string\n datasetUrl?: string\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n entry?: string\n importPrompt?: string\n scripts?: Record<string, string>\n type?: 'commonjs' | 'module'\n typescriptOnly?: boolean\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/init/types.ts"],"sourcesContent":["import {type CLITelemetryStore, type Output} from '@sanity/cli-core'\nimport {type Framework} from '@vercel/frameworks'\n\nimport {type GenerateConfigOptions} from './createStudioConfig.js'\n\nexport type VersionedFramework = Framework & {\n detectedVersion?: string\n}\n\nexport interface ProjectTemplate {\n configTemplate?: ((variables: GenerateConfigOptions['variables']) => string) | string\n datasetUrl?: string\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n entry?: string\n importPrompt?: string\n scripts?: Record<string, string>\n type?: 'commonjs' | 'module'\n typescriptOnly?: boolean\n}\n\nexport interface InitOptions {\n autoUpdates: boolean\n bare: boolean\n datasetDefault: boolean\n fromCreate: boolean\n mcpMode: 'auto' | 'prompt' | 'skip'\n unattended: boolean\n\n argType?: string\n coupon?: string\n dataset?: string\n env?: string\n git?: boolean | string\n importDataset?: boolean\n nextjsAddConfigFiles?: boolean\n nextjsAppendEnv?: boolean\n nextjsEmbedStudio?: boolean\n organization?: string\n outputPath?: string\n overwriteFiles?: boolean\n packageManager?: 'npm' | 'pnpm' | 'yarn'\n project?: string\n projectName?: string\n projectPlan?: string\n provider?: string\n reconfigure?: boolean\n template?: string\n templateToken?: string\n typescript?: boolean\n visibility?: 'private' | 'public'\n}\n\nexport interface InitContext {\n output: Output\n telemetry: CLITelemetryStore\n workDir: string\n}\n\ninterface InitCommandFlags {\n 'auto-updates': boolean\n bare: boolean\n 'dataset-default': boolean\n 'from-create': boolean\n mcp: boolean\n 'no-git': boolean\n\n coupon?: string\n 'create-project'?: string\n dataset?: string\n env?: string\n git?: string\n 'import-dataset'?: boolean\n 'nextjs-add-config-files'?: boolean\n 'nextjs-append-env'?: boolean\n 'nextjs-embed-studio'?: boolean\n organization?: string\n 'output-path'?: string\n 'overwrite-files'?: boolean\n 'package-manager'?: string\n project?: string\n 'project-name'?: string\n 'project-plan'?: string\n provider?: string\n reconfigure?: boolean\n template?: string\n 'template-token'?: string\n typescript?: boolean\n visibility?: string\n}\n\ninterface InitCommandArgs {\n type?: string\n}\n\nconst VALID_PACKAGE_MANAGERS = new Set<string>(['npm', 'pnpm', 'yarn'])\nfunction narrowPackageManager(value: string | undefined): InitOptions['packageManager'] {\n return value !== undefined && VALID_PACKAGE_MANAGERS.has(value)\n ? (value as InitOptions['packageManager'])\n : undefined\n}\n\nconst VALID_VISIBILITIES = new Set<string>(['private', 'public'])\nfunction narrowVisibility(value: string | undefined): InitOptions['visibility'] {\n return value !== undefined && VALID_VISIBILITIES.has(value)\n ? (value as InitOptions['visibility'])\n : undefined\n}\n\nexport function flagsToInitOptions(\n flags: InitCommandFlags,\n isUnattended: boolean,\n args: InitCommandArgs | undefined,\n mcpMode: InitOptions['mcpMode'],\n): InitOptions {\n return {\n argType: args?.type,\n autoUpdates: flags['auto-updates'],\n bare: flags.bare,\n coupon: flags.coupon,\n dataset: flags.dataset,\n datasetDefault: flags['dataset-default'],\n env: flags.env,\n fromCreate: flags['from-create'],\n git: flags['no-git'] ? false : flags.git,\n importDataset: flags['import-dataset'],\n mcpMode,\n nextjsAddConfigFiles: flags['nextjs-add-config-files'],\n nextjsAppendEnv: flags['nextjs-append-env'],\n nextjsEmbedStudio: flags['nextjs-embed-studio'],\n organization: flags.organization,\n outputPath: flags['output-path'],\n overwriteFiles: flags['overwrite-files'],\n packageManager: narrowPackageManager(flags['package-manager']),\n project: flags.project,\n projectName: flags['project-name'] ?? flags['create-project'],\n projectPlan: flags['project-plan'],\n provider: flags.provider,\n reconfigure: flags.reconfigure,\n template: flags.template,\n templateToken: flags['template-token'],\n typescript: flags.typescript,\n unattended: isUnattended,\n visibility: narrowVisibility(flags.visibility),\n }\n}\n"],"names":["VALID_PACKAGE_MANAGERS","Set","narrowPackageManager","value","undefined","has","VALID_VISIBILITIES","narrowVisibility","flagsToInitOptions","flags","isUnattended","args","mcpMode","argType","type","autoUpdates","bare","coupon","dataset","datasetDefault","env","fromCreate","git","importDataset","nextjsAddConfigFiles","nextjsAppendEnv","nextjsEmbedStudio","organization","outputPath","overwriteFiles","packageManager","project","projectName","projectPlan","provider","reconfigure","template","templateToken","typescript","unattended","visibility"],"mappings":"AA+FA,MAAMA,yBAAyB,IAAIC,IAAY;IAAC;IAAO;IAAQ;CAAO;AACtE,SAASC,qBAAqBC,KAAyB;IACrD,OAAOA,UAAUC,aAAaJ,uBAAuBK,GAAG,CAACF,SACpDA,QACDC;AACN;AAEA,MAAME,qBAAqB,IAAIL,IAAY;IAAC;IAAW;CAAS;AAChE,SAASM,iBAAiBJ,KAAyB;IACjD,OAAOA,UAAUC,aAAaE,mBAAmBD,GAAG,CAACF,SAChDA,QACDC;AACN;AAEA,OAAO,SAASI,mBACdC,KAAuB,EACvBC,YAAqB,EACrBC,IAAiC,EACjCC,OAA+B;IAE/B,OAAO;QACLC,SAASF,MAAMG;QACfC,aAAaN,KAAK,CAAC,eAAe;QAClCO,MAAMP,MAAMO,IAAI;QAChBC,QAAQR,MAAMQ,MAAM;QACpBC,SAAST,MAAMS,OAAO;QACtBC,gBAAgBV,KAAK,CAAC,kBAAkB;QACxCW,KAAKX,MAAMW,GAAG;QACdC,YAAYZ,KAAK,CAAC,cAAc;QAChCa,KAAKb,KAAK,CAAC,SAAS,GAAG,QAAQA,MAAMa,GAAG;QACxCC,eAAed,KAAK,CAAC,iBAAiB;QACtCG;QACAY,sBAAsBf,KAAK,CAAC,0BAA0B;QACtDgB,iBAAiBhB,KAAK,CAAC,oBAAoB;QAC3CiB,mBAAmBjB,KAAK,CAAC,sBAAsB;QAC/CkB,cAAclB,MAAMkB,YAAY;QAChCC,YAAYnB,KAAK,CAAC,cAAc;QAChCoB,gBAAgBpB,KAAK,CAAC,kBAAkB;QACxCqB,gBAAgB5B,qBAAqBO,KAAK,CAAC,kBAAkB;QAC7DsB,SAAStB,MAAMsB,OAAO;QACtBC,aAAavB,KAAK,CAAC,eAAe,IAAIA,KAAK,CAAC,iBAAiB;QAC7DwB,aAAaxB,KAAK,CAAC,eAAe;QAClCyB,UAAUzB,MAAMyB,QAAQ;QACxBC,aAAa1B,MAAM0B,WAAW;QAC9BC,UAAU3B,MAAM2B,QAAQ;QACxBC,eAAe5B,KAAK,CAAC,iBAAiB;QACtC6B,YAAY7B,MAAM6B,UAAU;QAC5BC,YAAY7B;QACZ8B,YAAYjC,iBAAiBE,MAAM+B,UAAU;IAC/C;AACF"}
|
|
@@ -3,6 +3,7 @@ import { relative, resolve } from 'node:path';
|
|
|
3
3
|
import { getCliConfig } from '@sanity/cli-core';
|
|
4
4
|
import { spinner } from '@sanity/cli-core/ux';
|
|
5
5
|
import { getErrorMessage } from '../../util/getErrorMessage.js';
|
|
6
|
+
import { coreAppManifestSchema } from './types.js';
|
|
6
7
|
/**
|
|
7
8
|
* Resolves app.icon from config (a file path) to an SVG string for the manifest.
|
|
8
9
|
* The manifest expects the SVG string inline, not a path.
|
|
@@ -49,7 +50,7 @@ import { getErrorMessage } from '../../util/getErrorMessage.js';
|
|
|
49
50
|
spin.succeed('Manifest creation skipped: no icon or title found in app configuration');
|
|
50
51
|
return undefined;
|
|
51
52
|
}
|
|
52
|
-
const manifest = {
|
|
53
|
+
const manifest = coreAppManifestSchema.parse({
|
|
53
54
|
version: '1',
|
|
54
55
|
...icon ? {
|
|
55
56
|
icon
|
|
@@ -57,7 +58,7 @@ import { getErrorMessage } from '../../util/getErrorMessage.js';
|
|
|
57
58
|
...app.title ? {
|
|
58
59
|
title: app.title
|
|
59
60
|
} : {}
|
|
60
|
-
};
|
|
61
|
+
});
|
|
61
62
|
spin.succeed(`Extracted manifest`);
|
|
62
63
|
return manifest;
|
|
63
64
|
} catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/manifest/extractAppManifest.ts"],"sourcesContent":["import {readFile} from 'node:fs/promises'\nimport {relative, resolve} from 'node:path'\n\nimport {getCliConfig} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\n\nimport {getErrorMessage} from '../../util/getErrorMessage.js'\nimport {type
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/manifest/extractAppManifest.ts"],"sourcesContent":["import {readFile} from 'node:fs/promises'\nimport {relative, resolve} from 'node:path'\n\nimport {getCliConfig} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\n\nimport {getErrorMessage} from '../../util/getErrorMessage.js'\nimport {type CoreAppManifest, coreAppManifestSchema} from './types.js'\n\ninterface ExtractAppManifestOptions {\n workDir: string\n}\n\n/**\n * Resolves app.icon from config (a file path) to an SVG string for the manifest.\n * The manifest expects the SVG string inline, not a path.\n * Brett sanitizes SVGs so it's skipped here.\n */\nasync function readIconFromPath(workDir: string, iconPath: string): Promise<string> {\n const resolvedPath = resolve(workDir, iconPath)\n const pathRelativeToWorkDir = relative(workDir, resolvedPath)\n if (pathRelativeToWorkDir.startsWith('..')) {\n throw new Error(\n `Icon path \"${iconPath}\" resolves outside the project directory and is not allowed.`,\n )\n }\n\n let content: string\n try {\n content = await readFile(resolvedPath, 'utf8')\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new Error(\n `Could not read icon file at \"${iconPath}\" (resolved: ${resolvedPath}): ${message}`,\n {cause: err},\n )\n }\n\n const trimmed = content.trim()\n if (!/<svg[\\s>]/i.test(trimmed)) {\n throw new Error(\n `Icon file at \"${iconPath}\" does not contain an SVG element. App manifest icons must be SVG files.`,\n )\n }\n\n return trimmed\n}\n\n/**\n *\n * This functions slightly differently from the studio manifest extraction function.\n * We don't need to parse very complicated information like schemas and tools.\n * The app icon in config is a file path (e.g. relative to project root); its content is read and inlined in the manifest.\n */\nexport async function extractAppManifest(\n options: ExtractAppManifestOptions,\n): Promise<CoreAppManifest | undefined> {\n const {workDir} = options\n const {app} = await getCliConfig(workDir)\n if (!app) {\n return undefined\n }\n\n const spin = spinner('Extracting manifest').start()\n\n try {\n let icon: string | undefined\n if (app.icon) {\n icon = await readIconFromPath(workDir, app.icon)\n }\n\n if (!icon && !app.title) {\n spin.succeed('Manifest creation skipped: no icon or title found in app configuration')\n return undefined\n }\n\n const manifest: CoreAppManifest = coreAppManifestSchema.parse({\n version: '1',\n ...(icon ? {icon} : {}),\n ...(app.title ? {title: app.title} : {}),\n })\n\n spin.succeed(`Extracted manifest`)\n\n return manifest\n } catch (err) {\n const message = getErrorMessage(err)\n spin.fail(message)\n throw err\n }\n}\n"],"names":["readFile","relative","resolve","getCliConfig","spinner","getErrorMessage","coreAppManifestSchema","readIconFromPath","workDir","iconPath","resolvedPath","pathRelativeToWorkDir","startsWith","Error","content","err","message","String","cause","trimmed","trim","test","extractAppManifest","options","app","undefined","spin","start","icon","title","succeed","manifest","parse","version","fail"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,mBAAkB;AACzC,SAAQC,QAAQ,EAAEC,OAAO,QAAO,YAAW;AAE3C,SAAQC,YAAY,QAAO,mBAAkB;AAC7C,SAAQC,OAAO,QAAO,sBAAqB;AAE3C,SAAQC,eAAe,QAAO,gCAA+B;AAC7D,SAA8BC,qBAAqB,QAAO,aAAY;AAMtE;;;;CAIC,GACD,eAAeC,iBAAiBC,OAAe,EAAEC,QAAgB;IAC/D,MAAMC,eAAeR,QAAQM,SAASC;IACtC,MAAME,wBAAwBV,SAASO,SAASE;IAChD,IAAIC,sBAAsBC,UAAU,CAAC,OAAO;QAC1C,MAAM,IAAIC,MACR,CAAC,WAAW,EAAEJ,SAAS,4DAA4D,CAAC;IAExF;IAEA,IAAIK;IACJ,IAAI;QACFA,UAAU,MAAMd,SAASU,cAAc;IACzC,EAAE,OAAOK,KAAK;QACZ,MAAMC,UAAUD,eAAeF,QAAQE,IAAIC,OAAO,GAAGC,OAAOF;QAC5D,MAAM,IAAIF,MACR,CAAC,6BAA6B,EAAEJ,SAAS,aAAa,EAAEC,aAAa,GAAG,EAAEM,SAAS,EACnF;YAACE,OAAOH;QAAG;IAEf;IAEA,MAAMI,UAAUL,QAAQM,IAAI;IAC5B,IAAI,CAAC,aAAaC,IAAI,CAACF,UAAU;QAC/B,MAAM,IAAIN,MACR,CAAC,cAAc,EAAEJ,SAAS,wEAAwE,CAAC;IAEvG;IAEA,OAAOU;AACT;AAEA;;;;;CAKC,GACD,OAAO,eAAeG,mBACpBC,OAAkC;IAElC,MAAM,EAACf,OAAO,EAAC,GAAGe;IAClB,MAAM,EAACC,GAAG,EAAC,GAAG,MAAMrB,aAAaK;IACjC,IAAI,CAACgB,KAAK;QACR,OAAOC;IACT;IAEA,MAAMC,OAAOtB,QAAQ,uBAAuBuB,KAAK;IAEjD,IAAI;QACF,IAAIC;QACJ,IAAIJ,IAAII,IAAI,EAAE;YACZA,OAAO,MAAMrB,iBAAiBC,SAASgB,IAAII,IAAI;QACjD;QAEA,IAAI,CAACA,QAAQ,CAACJ,IAAIK,KAAK,EAAE;YACvBH,KAAKI,OAAO,CAAC;YACb,OAAOL;QACT;QAEA,MAAMM,WAA4BzB,sBAAsB0B,KAAK,CAAC;YAC5DC,SAAS;YACT,GAAIL,OAAO;gBAACA;YAAI,IAAI,CAAC,CAAC;YACtB,GAAIJ,IAAIK,KAAK,GAAG;gBAACA,OAAOL,IAAIK,KAAK;YAAA,IAAI,CAAC,CAAC;QACzC;QAEAH,KAAKI,OAAO,CAAC,CAAC,kBAAkB,CAAC;QAEjC,OAAOC;IACT,EAAE,OAAOhB,KAAK;QACZ,MAAMC,UAAUX,gBAAgBU;QAChCW,KAAKQ,IAAI,CAAClB;QACV,MAAMD;IACR;AACF"}
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { z } from 'zod/mini';
|
|
2
2
|
export const SANITY_WORKSPACE_SCHEMA_ID_PREFIX = '_.schemas';
|
|
3
|
-
export const SANITY_WORKSPACE_SCHEMA_TYPE = 'system.schema';
|
|
4
3
|
export const CURRENT_WORKSPACE_SCHEMA_VERSION = '2025-05-01';
|
|
4
|
+
/**
|
|
5
|
+
* Core-app application manifest. Mirrors the workbench's
|
|
6
|
+
* `CoreAppUserApplicationManifest` schema. Strictly validated via zod
|
|
7
|
+
* since the CLI produces the payload in full.
|
|
8
|
+
*/ export const coreAppManifestSchema = z.object({
|
|
9
|
+
icon: z.optional(z.string()),
|
|
10
|
+
title: z.optional(z.string()),
|
|
11
|
+
version: z.string()
|
|
12
|
+
});
|
|
5
13
|
export const extractManifestWorkerData = z.object({
|
|
6
14
|
configPath: z.string(),
|
|
7
15
|
workDir: z.string()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/manifest/types.ts"],"sourcesContent":["import {type SanityDocumentLike} from '@sanity/types'\nimport {type MediaLibraryConfig} from 'sanity'\nimport {z} from 'zod/mini'\n\nexport const SANITY_WORKSPACE_SCHEMA_ID_PREFIX = '_.schemas'\nexport const
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/manifest/types.ts"],"sourcesContent":["import {type SanityDocumentLike} from '@sanity/types'\nimport {type MediaLibraryConfig} from 'sanity'\nimport {z} from 'zod/mini'\n\nexport const SANITY_WORKSPACE_SCHEMA_ID_PREFIX = '_.schemas'\nexport const CURRENT_WORKSPACE_SCHEMA_VERSION = '2025-05-01'\n\nexport type ManifestSerializable =\n | boolean\n | ManifestSerializable[]\n | number\n | string\n | {[k: string]: ManifestSerializable}\n\nexport interface CreateManifest {\n createdAt: string\n studioVersion: string | null\n version: number\n workspaces: ManifestWorkspaceFile[]\n}\n\n/**\n * Core-app application manifest. Mirrors the workbench's\n * `CoreAppUserApplicationManifest` schema. Strictly validated via zod\n * since the CLI produces the payload in full.\n */\nexport const coreAppManifestSchema = z.object({\n icon: z.optional(z.string()),\n title: z.optional(z.string()),\n version: z.string(),\n})\n\nexport type CoreAppManifest = z.infer<typeof coreAppManifestSchema>\n\nexport interface ManifestWorkspaceFile extends Omit<CreateWorkspaceManifest, 'schema' | 'tools'> {\n schema: string // filename\n tools: string // filename\n}\n\nexport interface CreateWorkspaceManifest {\n basePath: string\n dataset: string\n /**\n * returns null in the case of the icon not being able to be stringified\n */\n icon: string | null\n name: string\n projectId: string\n schema: ManifestSchemaType[]\n tools: ManifestTool[]\n\n mediaLibrary?: MediaLibraryConfig\n subtitle?: string\n title?: string\n}\n\nexport interface ManifestSchemaType {\n name: string\n type: string\n\n deprecated?: {\n reason: string\n }\n fields?: ManifestField[]\n fieldsets?: ManifestFieldset[]\n hidden?: 'conditional' | boolean\n lists?: ManifestTitledValue[]\n //portable text\n marks?: {\n annotations?: ManifestArrayMember[]\n decorators?: ManifestTitledValue[]\n }\n of?: ManifestArrayMember[]\n options?: Record<string, ManifestSerializable>\n preview?: {\n select: Record<string, string>\n }\n readOnly?: 'conditional' | boolean\n styles?: ManifestTitledValue[]\n title?: string\n to?: ManifestReferenceMember[]\n validation?: ManifestValidationGroup[]\n\n // userland (assignable to ManifestSerializable | undefined)\n // not included to add some typesafty to extractManifest\n // [index: string]: unknown\n}\n\nexport interface ManifestFieldset {\n [index: string]: ManifestSerializable | undefined\n name: string\n\n title?: string\n}\n\nexport interface ManifestTitledValue {\n value: string\n\n title?: string\n}\n\ntype ManifestArrayMember = Omit<ManifestSchemaType, 'name'> & {name?: string}\ntype ManifestReferenceMember = Omit<ManifestSchemaType, 'name'> & {name?: string}\nexport type ManifestField = ManifestSchemaType & {fieldset?: string}\n\nexport interface ManifestValidationGroup {\n rules: ManifestValidationRule[]\n\n level?: 'error' | 'info' | 'warning'\n message?: string\n}\n\nexport type ManifestValidationRule = {\n [index: string]: ManifestSerializable | undefined\n constraint?: ManifestSerializable\n flag: string\n}\n\nexport interface ManifestTool {\n /**\n * returns null in the case of the icon not being able to be stringified\n */\n icon: string | null\n name: string\n title: string\n type: string | null\n}\n\nexport type DefaultWorkspaceSchemaId = `${typeof SANITY_WORKSPACE_SCHEMA_ID_PREFIX}.${string}`\ntype PrefixedWorkspaceSchemaId = `${DefaultWorkspaceSchemaId}.${string}`\nexport type WorkspaceSchemaId = DefaultWorkspaceSchemaId | PrefixedWorkspaceSchemaId\n\nexport interface StoredWorkspaceSchema extends SanityDocumentLike {\n _id: WorkspaceSchemaId\n _type: 'system.schema'\n /**\n * The API expects JSON coming in, but will store a string to save on attribute paths.\n * Consumers must use JSON.parse on the value, but we deploy to the API using ManifestSchemaType[]\n */\n schema: ManifestSchemaType[] | string\n /* api-like version string: date at which the format had a meaningful change */\n version: typeof CURRENT_WORKSPACE_SCHEMA_VERSION | undefined\n workspace: {\n name: string\n title?: string\n }\n\n tag?: string\n}\n\nexport const extractManifestWorkerData = z.object({configPath: z.string(), workDir: z.string()})\n\nexport type ExtractManifestWorkerData = z.infer<typeof extractManifestWorkerData>\n"],"names":["z","SANITY_WORKSPACE_SCHEMA_ID_PREFIX","CURRENT_WORKSPACE_SCHEMA_VERSION","coreAppManifestSchema","object","icon","optional","string","title","version","extractManifestWorkerData","configPath","workDir"],"mappings":"AAEA,SAAQA,CAAC,QAAO,WAAU;AAE1B,OAAO,MAAMC,oCAAoC,YAAW;AAC5D,OAAO,MAAMC,mCAAmC,aAAY;AAgB5D;;;;CAIC,GACD,OAAO,MAAMC,wBAAwBH,EAAEI,MAAM,CAAC;IAC5CC,MAAML,EAAEM,QAAQ,CAACN,EAAEO,MAAM;IACzBC,OAAOR,EAAEM,QAAQ,CAACN,EAAEO,MAAM;IAC1BE,SAAST,EAAEO,MAAM;AACnB,GAAE;AAwHF,OAAO,MAAMG,4BAA4BV,EAAEI,MAAM,CAAC;IAACO,YAAYX,EAAEO,MAAM;IAAIK,SAASZ,EAAEO,MAAM;AAAE,GAAE"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { isAbsolute, join, resolve } from 'node:path';
|
|
3
|
-
import { subdebug } from '@sanity/cli-core';
|
|
4
|
-
import { getLocalPackageVersion } from '../../util/getLocalPackageVersion.js';
|
|
3
|
+
import { getLocalPackageVersion, subdebug } from '@sanity/cli-core';
|
|
5
4
|
import { writeWorkspaceFiles } from './writeWorkspaceFiles.js';
|
|
6
5
|
const MANIFEST_FILENAME = 'create-manifest.json';
|
|
7
6
|
const debug = subdebug('writeManifestFile');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/manifest/writeManifestFile.ts"],"sourcesContent":["import {mkdir, writeFile} from 'node:fs/promises'\nimport {isAbsolute, join, resolve} from 'node:path'\n\nimport {subdebug} from '@sanity/cli-core'\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/manifest/writeManifestFile.ts"],"sourcesContent":["import {mkdir, writeFile} from 'node:fs/promises'\nimport {isAbsolute, join, resolve} from 'node:path'\n\nimport {getLocalPackageVersion, subdebug} from '@sanity/cli-core'\n\nimport {type CreateManifest, type CreateWorkspaceManifest} from './types.js'\nimport {writeWorkspaceFiles} from './writeWorkspaceFiles.js'\n\nconst MANIFEST_FILENAME = 'create-manifest.json'\n\nconst debug = subdebug('writeManifestFile')\n\nexport async function writeManifestFile({\n outPath,\n workDir,\n workspaceManifests,\n}: {\n outPath: string\n workDir: string\n workspaceManifests: CreateWorkspaceManifest[]\n}) {\n const staticPath = isAbsolute(outPath) ? outPath : resolve(join(workDir, outPath))\n debug('Writing manifest to %s', staticPath)\n const path = join(staticPath, MANIFEST_FILENAME)\n\n await mkdir(staticPath, {recursive: true})\n\n const workspaceFiles = await writeWorkspaceFiles(workspaceManifests, staticPath)\n\n const manifest: CreateManifest = {\n /**\n * Version history:\n * 1: Initial release.\n * 2: Added tools file.\n * 3. Added studioVersion field.\n */\n createdAt: new Date().toISOString(),\n studioVersion: await getLocalPackageVersion('sanity', workDir),\n version: 3,\n workspaces: workspaceFiles,\n }\n\n await writeFile(path, JSON.stringify(manifest, null, 2))\n}\n"],"names":["mkdir","writeFile","isAbsolute","join","resolve","getLocalPackageVersion","subdebug","writeWorkspaceFiles","MANIFEST_FILENAME","debug","writeManifestFile","outPath","workDir","workspaceManifests","staticPath","path","recursive","workspaceFiles","manifest","createdAt","Date","toISOString","studioVersion","version","workspaces","JSON","stringify"],"mappings":"AAAA,SAAQA,KAAK,EAAEC,SAAS,QAAO,mBAAkB;AACjD,SAAQC,UAAU,EAAEC,IAAI,EAAEC,OAAO,QAAO,YAAW;AAEnD,SAAQC,sBAAsB,EAAEC,QAAQ,QAAO,mBAAkB;AAGjE,SAAQC,mBAAmB,QAAO,2BAA0B;AAE5D,MAAMC,oBAAoB;AAE1B,MAAMC,QAAQH,SAAS;AAEvB,OAAO,eAAeI,kBAAkB,EACtCC,OAAO,EACPC,OAAO,EACPC,kBAAkB,EAKnB;IACC,MAAMC,aAAaZ,WAAWS,WAAWA,UAAUP,QAAQD,KAAKS,SAASD;IACzEF,MAAM,0BAA0BK;IAChC,MAAMC,OAAOZ,KAAKW,YAAYN;IAE9B,MAAMR,MAAMc,YAAY;QAACE,WAAW;IAAI;IAExC,MAAMC,iBAAiB,MAAMV,oBAAoBM,oBAAoBC;IAErE,MAAMI,WAA2B;QAC/B;;;;;KAKC,GACDC,WAAW,IAAIC,OAAOC,WAAW;QACjCC,eAAe,MAAMjB,uBAAuB,UAAUO;QACtDW,SAAS;QACTC,YAAYP;IACd;IAEA,MAAMhB,UAAUc,MAAMU,KAAKC,SAAS,CAACR,UAAU,MAAM;AACvD"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { styleText } from 'node:util';
|
|
2
2
|
import { ux } from '@oclif/core/ux';
|
|
3
|
-
import { doImport, getProjectCliClient, resolveLocalPackage, subdebug } from '@sanity/cli-core';
|
|
3
|
+
import { doImport, getLocalPackageVersion, getProjectCliClient, resolveLocalPackage, subdebug } from '@sanity/cli-core';
|
|
4
4
|
import { spinner } from '@sanity/cli-core/ux';
|
|
5
5
|
import { SCHEMA_API_VERSION } from '../../services/schemas.js';
|
|
6
|
-
import { getLocalPackageVersion } from '../../util/getLocalPackageVersion.js';
|
|
7
6
|
const iconResolverPath = new URL('../manifest/iconResolver.js', import.meta.url).href;
|
|
8
7
|
const debug = subdebug('uploadSchemaToLexicon');
|
|
9
8
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/schema/uploadSchemaToLexicon.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {ux} from '@oclif/core/ux'\nimport {doImport
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/schema/uploadSchemaToLexicon.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {ux} from '@oclif/core/ux'\nimport {\n doImport,\n getLocalPackageVersion,\n getProjectCliClient,\n resolveLocalPackage,\n subdebug,\n} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {type StudioManifest, type Workspace} from 'sanity'\n\nimport {SCHEMA_API_VERSION} from '../../services/schemas.js'\n\nconst iconResolverPath = new URL('../manifest/iconResolver.js', import.meta.url).href\n\ninterface UploadSchemaToLexiconOptions {\n projectId: string\n workDir: string\n workspaces: Workspace[]\n\n verbose?: boolean\n}\n\nconst debug = subdebug('uploadSchemaToLexicon')\n\n/**\n * Uploads the schemas to Lexicon and returns the studio manifest\n * @param options - The options for the uploadSchemaToLexicon function\n * @returns The studio manifest\n */\nexport async function uploadSchemaToLexicon(\n options: UploadSchemaToLexiconOptions,\n): Promise<StudioManifest | null> {\n const {projectId, verbose, workDir, workspaces} = options\n const spin = spinner('Generating studio manifest').start()\n\n try {\n const schemaDescriptors = new Map<string, string>()\n\n const client = await getProjectCliClient({\n apiVersion: SCHEMA_API_VERSION,\n projectId,\n requestTagPrefix: 'sanity.cli.deploy',\n requireUser: true,\n })\n\n const [bundleVersion, {generateStudioManifest, uploadSchema}] = await Promise.all([\n getLocalPackageVersion('sanity', workDir),\n resolveLocalPackage<typeof import('sanity')>('sanity', workDir),\n ])\n\n if (!bundleVersion) {\n throw new Error('Failed to find sanity version')\n }\n\n for (const workspace of workspaces) {\n const workspaceClient = client.withConfig({\n dataset: workspace.dataset,\n projectId: workspace.projectId,\n })\n\n try {\n debug('Uploading schema to lexicon for workspace %o', {\n dataset: workspace.dataset,\n projectId: workspace.projectId,\n })\n const descriptorId = await uploadSchema(workspace.schema, workspaceClient)\n\n if (!descriptorId) {\n throw new Error(\n `Failed to get schema descriptor ID for workspace \"${workspace.name}\": upload returned empty result`,\n )\n }\n\n schemaDescriptors.set(workspace.name, descriptorId)\n debug(\n `Uploaded schema for workspace \"${workspace.name}\" to Lexicon with descriptor ID: ${descriptorId}`,\n )\n } catch (error) {\n debug('Error uploading schema to lexicon for workspace %o', error)\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n throw new Error(\n `Failed to upload schema for workspace \"${workspace.name}\": ${errorMessage}`,\n {cause: error},\n )\n }\n }\n\n // Lazy import to avoid pulling in @sanity/ui at module load time\n const {resolveIcon} = await doImport(iconResolverPath)\n\n // Generate studio manifest using the shared utility\n const manifest = await generateStudioManifest({\n buildId: JSON.stringify(Date.now()),\n bundleVersion,\n // @todo replace with import from @sanity/schema/_internal in future\n resolveIcon: async (workspace) =>\n (await resolveIcon({\n icon: workspace.icon,\n subtitle: workspace.subtitle,\n title: workspace.title || workspace.name || 'default',\n workDir,\n })) ?? undefined,\n resolveSchemaDescriptorId: (workspace) => schemaDescriptors.get(workspace.name),\n workspaces,\n })\n\n spin.succeed('Generated studio manifest')\n\n const studioManifest = manifest.workspaces.length === 0 ? null : manifest\n\n if (verbose) {\n if (studioManifest) {\n for (const workspace of studioManifest.workspaces) {\n ux.stdout(\n styleText(\n 'gray',\n `↳ projectId: ${workspace.projectId}, dataset: ${workspace.dataset}, schemaDescriptorId: ${workspace.schemaDescriptorId}`,\n ),\n )\n }\n } else {\n ux.stdout(`${styleText('gray', '↳ No workspaces found')}`)\n }\n }\n\n return studioManifest\n } catch (error) {\n spin.fail(error instanceof Error ? error.message : 'Unknown error')\n throw error\n }\n}\n"],"names":["styleText","ux","doImport","getLocalPackageVersion","getProjectCliClient","resolveLocalPackage","subdebug","spinner","SCHEMA_API_VERSION","iconResolverPath","URL","url","href","debug","uploadSchemaToLexicon","options","projectId","verbose","workDir","workspaces","spin","start","schemaDescriptors","Map","client","apiVersion","requestTagPrefix","requireUser","bundleVersion","generateStudioManifest","uploadSchema","Promise","all","Error","workspace","workspaceClient","withConfig","dataset","descriptorId","schema","name","set","error","errorMessage","message","cause","resolveIcon","manifest","buildId","JSON","stringify","Date","now","icon","subtitle","title","undefined","resolveSchemaDescriptorId","get","succeed","studioManifest","length","stdout","schemaDescriptorId","fail"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { getLocalPackageVersion } from '@sanity/cli-core';
|
|
2
|
+
import { valid } from 'semver';
|
|
3
3
|
import { trimHashFromVersion } from '../../util/trimHashFromVersion.js';
|
|
4
4
|
import { tryFindLatestVersion } from './tryFindLatestVersion.js';
|
|
5
5
|
/**
|
|
@@ -7,7 +7,7 @@ import { tryFindLatestVersion } from './tryFindLatestVersion.js';
|
|
|
7
7
|
*
|
|
8
8
|
* @internal
|
|
9
9
|
*/ function isPinnedVersion(version) {
|
|
10
|
-
return !!
|
|
10
|
+
return !!valid(version);
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* Build an array of package versions.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/versions/buildPackageArray.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/versions/buildPackageArray.ts"],"sourcesContent":["import {getLocalPackageVersion} from '@sanity/cli-core'\nimport {valid} from 'semver'\n\nimport {trimHashFromVersion} from '../../util/trimHashFromVersion.js'\nimport {tryFindLatestVersion} from './tryFindLatestVersion.js'\n\n/**\n * Check if a version is pinned.\n *\n * @internal\n */\nfunction isPinnedVersion(version: string): boolean {\n return !!valid(version)\n}\n\n/**\n * @internal\n */\ninterface PromisedModuleVersionInfo {\n declared: string\n installed: Promise<string | undefined>\n isGlobal: boolean\n isPinned: boolean\n latest: Promise<string | undefined>\n name: string\n}\n\n/**\n * Build an array of package versions.\n *\n * @internal\n */\nexport function buildPackageArray(\n packages: Record<string, string>,\n workDir: string,\n cliVersion: string,\n): PromisedModuleVersionInfo[] {\n const modules = []\n const latest = tryFindLatestVersion('@sanity/cli')\n modules.push({\n declared: `^${cliVersion}`,\n installed: Promise.resolve(trimHashFromVersion(cliVersion)),\n isGlobal: true,\n isPinned: false,\n latest: latest.then((version) => version),\n name: '@sanity/cli',\n })\n\n return [\n ...modules,\n ...Object.keys(packages).map((pkgName) => {\n const latest = tryFindLatestVersion(pkgName)\n const localVersion = getLocalPackageVersion(pkgName, workDir)\n return {\n declared: packages[pkgName],\n installed: localVersion.then((version) =>\n version ? trimHashFromVersion(version) : undefined,\n ),\n isGlobal: false,\n isPinned: isPinnedVersion(packages[pkgName]),\n latest: latest.then((version) => version),\n name: pkgName,\n }\n }),\n ]\n}\n"],"names":["getLocalPackageVersion","valid","trimHashFromVersion","tryFindLatestVersion","isPinnedVersion","version","buildPackageArray","packages","workDir","cliVersion","modules","latest","push","declared","installed","Promise","resolve","isGlobal","isPinned","then","name","Object","keys","map","pkgName","localVersion","undefined"],"mappings":"AAAA,SAAQA,sBAAsB,QAAO,mBAAkB;AACvD,SAAQC,KAAK,QAAO,SAAQ;AAE5B,SAAQC,mBAAmB,QAAO,oCAAmC;AACrE,SAAQC,oBAAoB,QAAO,4BAA2B;AAE9D;;;;CAIC,GACD,SAASC,gBAAgBC,OAAe;IACtC,OAAO,CAAC,CAACJ,MAAMI;AACjB;AAcA;;;;CAIC,GACD,OAAO,SAASC,kBACdC,QAAgC,EAChCC,OAAe,EACfC,UAAkB;IAElB,MAAMC,UAAU,EAAE;IAClB,MAAMC,SAASR,qBAAqB;IACpCO,QAAQE,IAAI,CAAC;QACXC,UAAU,CAAC,CAAC,EAAEJ,YAAY;QAC1BK,WAAWC,QAAQC,OAAO,CAACd,oBAAoBO;QAC/CQ,UAAU;QACVC,UAAU;QACVP,QAAQA,OAAOQ,IAAI,CAAC,CAACd,UAAYA;QACjCe,MAAM;IACR;IAEA,OAAO;WACFV;WACAW,OAAOC,IAAI,CAACf,UAAUgB,GAAG,CAAC,CAACC;YAC5B,MAAMb,SAASR,qBAAqBqB;YACpC,MAAMC,eAAezB,uBAAuBwB,SAAShB;YACrD,OAAO;gBACLK,UAAUN,QAAQ,CAACiB,QAAQ;gBAC3BV,WAAWW,aAAaN,IAAI,CAAC,CAACd,UAC5BA,UAAUH,oBAAoBG,WAAWqB;gBAE3CT,UAAU;gBACVC,UAAUd,gBAAgBG,QAAQ,CAACiB,QAAQ;gBAC3Cb,QAAQA,OAAOQ,IAAI,CAAC,CAACd,UAAYA;gBACjCe,MAAMI;YACR;QACF;KACD;AACH"}
|
|
@@ -2,7 +2,7 @@ import path from 'node:path';
|
|
|
2
2
|
import { readPackageJson } from '@sanity/cli-core';
|
|
3
3
|
import { spinner } from '@sanity/cli-core/ux';
|
|
4
4
|
import promiseProps from 'promise-props-recursive';
|
|
5
|
-
import
|
|
5
|
+
import { compare, minVersion } from 'semver';
|
|
6
6
|
import { getCliVersion } from '../../util/getCliVersion.js';
|
|
7
7
|
import { buildPackageArray } from './buildPackageArray.js';
|
|
8
8
|
import { filterSanityModules } from './filterSanityModules.js';
|
|
@@ -28,8 +28,8 @@ import { versionsDebug } from './versionsDebug.js';
|
|
|
28
28
|
const packages = Object.values(versions);
|
|
29
29
|
versionsDebug('packages:', packages);
|
|
30
30
|
return packages.map((mod)=>{
|
|
31
|
-
const current = mod.installed ||
|
|
32
|
-
const needsUpdate = mod.latest ?
|
|
31
|
+
const current = mod.installed || minVersion(mod.declared)?.toString() || '';
|
|
32
|
+
const needsUpdate = mod.latest ? compare(current, mod.latest) === -1 : false;
|
|
33
33
|
return {
|
|
34
34
|
...mod,
|
|
35
35
|
needsUpdate
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/versions/findSanityModulesVersions.ts"],"sourcesContent":["import path from 'node:path'\n\nimport {readPackageJson} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport promiseProps from 'promise-props-recursive'\nimport
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/versions/findSanityModulesVersions.ts"],"sourcesContent":["import path from 'node:path'\n\nimport {readPackageJson} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport promiseProps from 'promise-props-recursive'\nimport {compare, minVersion} from 'semver'\n\nimport {getCliVersion} from '../../util/getCliVersion.js'\nimport {buildPackageArray} from './buildPackageArray.js'\nimport {filterSanityModules} from './filterSanityModules.js'\nimport {type ModuleVersionInfo, type ModuleVersionResult} from './types.js'\nimport {versionsDebug} from './versionsDebug.js'\n\n/**\n * @internal\n */\ninterface PrintVersionArgs {\n cwd: string\n}\n\n/**\n * Print the versions of the all sanity and `@sanity/*` packages.\n *\n * @internal\n */\nexport async function findSanityModulesVersions(\n args: PrintVersionArgs,\n): Promise<ModuleVersionResult[]> {\n const {cwd} = args\n const cliVersion = await getCliVersion()\n\n versionsDebug(`Sanity CLI version: ${cliVersion}`)\n\n const packageJsonPath = path.join(cwd, 'package.json')\n versionsDebug(`Reading package.json from ${packageJsonPath}`)\n // Declared @sanity/* modules and their wanted versions in package.json\n const packageJson = await readPackageJson(packageJsonPath)\n versionsDebug('Resolved package.json:', packageJson)\n\n const filteredSanityModules = filterSanityModules(packageJson)\n versionsDebug('sanity modules:', filteredSanityModules)\n\n const spin = spinner('Resolving latest versions').start()\n\n try {\n const versions = await promiseProps<ModuleVersionInfo[]>(\n buildPackageArray(filteredSanityModules, cwd, cliVersion),\n )\n\n const packages = Object.values(versions)\n versionsDebug('packages:', packages)\n\n return packages.map((mod) => {\n const current = mod.installed || minVersion(mod.declared)?.toString() || ''\n const needsUpdate = mod.latest ? compare(current, mod.latest) === -1 : false\n\n return {...mod, needsUpdate}\n })\n } catch (error) {\n versionsDebug('Error finding sanity modules versions:', error)\n throw error\n } finally {\n spin.stop()\n }\n}\n"],"names":["path","readPackageJson","spinner","promiseProps","compare","minVersion","getCliVersion","buildPackageArray","filterSanityModules","versionsDebug","findSanityModulesVersions","args","cwd","cliVersion","packageJsonPath","join","packageJson","filteredSanityModules","spin","start","versions","packages","Object","values","map","mod","current","installed","declared","toString","needsUpdate","latest","error","stop"],"mappings":"AAAA,OAAOA,UAAU,YAAW;AAE5B,SAAQC,eAAe,QAAO,mBAAkB;AAChD,SAAQC,OAAO,QAAO,sBAAqB;AAC3C,OAAOC,kBAAkB,0BAAyB;AAClD,SAAQC,OAAO,EAAEC,UAAU,QAAO,SAAQ;AAE1C,SAAQC,aAAa,QAAO,8BAA6B;AACzD,SAAQC,iBAAiB,QAAO,yBAAwB;AACxD,SAAQC,mBAAmB,QAAO,2BAA0B;AAE5D,SAAQC,aAAa,QAAO,qBAAoB;AAShD;;;;CAIC,GACD,OAAO,eAAeC,0BACpBC,IAAsB;IAEtB,MAAM,EAACC,GAAG,EAAC,GAAGD;IACd,MAAME,aAAa,MAAMP;IAEzBG,cAAc,CAAC,oBAAoB,EAAEI,YAAY;IAEjD,MAAMC,kBAAkBd,KAAKe,IAAI,CAACH,KAAK;IACvCH,cAAc,CAAC,0BAA0B,EAAEK,iBAAiB;IAC5D,uEAAuE;IACvE,MAAME,cAAc,MAAMf,gBAAgBa;IAC1CL,cAAc,0BAA0BO;IAExC,MAAMC,wBAAwBT,oBAAoBQ;IAClDP,cAAc,mBAAmBQ;IAEjC,MAAMC,OAAOhB,QAAQ,6BAA6BiB,KAAK;IAEvD,IAAI;QACF,MAAMC,WAAW,MAAMjB,aACrBI,kBAAkBU,uBAAuBL,KAAKC;QAGhD,MAAMQ,WAAWC,OAAOC,MAAM,CAACH;QAC/BX,cAAc,aAAaY;QAE3B,OAAOA,SAASG,GAAG,CAAC,CAACC;YACnB,MAAMC,UAAUD,IAAIE,SAAS,IAAItB,WAAWoB,IAAIG,QAAQ,GAAGC,cAAc;YACzE,MAAMC,cAAcL,IAAIM,MAAM,GAAG3B,QAAQsB,SAASD,IAAIM,MAAM,MAAM,CAAC,IAAI;YAEvE,OAAO;gBAAC,GAAGN,GAAG;gBAAEK;YAAW;QAC7B;IACF,EAAE,OAAOE,OAAO;QACdvB,cAAc,0CAA0CuB;QACxD,MAAMA;IACR,SAAU;QACRd,KAAKe,IAAI;IACX;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/datasets/copy.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exit} from '@oclif/core/errors'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {Table} from 'console-table-printer'\nimport {formatDistance} from 'date-fns/formatDistance'\nimport {formatDistanceToNow} from 'date-fns/formatDistanceToNow'\nimport {parseISO} from 'date-fns/parseISO'\n\nimport {validateDatasetName} from '../../actions/dataset/validateDatasetName.js'\nimport {promptForDataset} from '../../prompts/promptForDataset.js'\nimport {promptForDatasetName} from '../../prompts/promptForDatasetName.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {\n copyDataset,\n type CopyJobProgressEvent,\n type DatasetCopyJob,\n followCopyJobProgress,\n listDatasetCopyJobs,\n listDatasets,\n} from '../../services/datasets.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst copyDatasetDebug = subdebug('dataset:copy')\n\nexport class CopyDatasetCommand extends SanityCommand<typeof CopyDatasetCommand> {\n static override args = {\n source: Args.string({\n description: 'Name of the dataset to copy from',\n required: false,\n }),\n target: Args.string({\n description: 'Name of the dataset to copy to',\n required: false,\n }),\n }\n\n static override description = 'Copy a dataset or manage copy jobs'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively copy a dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> source-dataset',\n description: 'Copy from source-dataset (prompts for target)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> source-dataset target-dataset',\n description: 'Copy from source-dataset to target-dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --skip-history source target',\n description: 'Copy without preserving document history (faster for large datasets)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --skip-content-releases source target',\n description: 'Copy without content release documents',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --detach source target',\n description: 'Start copy job without waiting for completion',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --attach <job-id>',\n description: 'Attach to a running copy job to follow progress',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --list',\n description: 'List all dataset copy jobs',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --list --offset 2 --limit 10',\n description: 'List copy jobs with pagination',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to copy dataset in',\n semantics: 'override',\n }),\n attach: Flags.string({\n description: 'Attach to the running copy process to show progress',\n exclusive: ['list', 'detach', 'skip-history'],\n required: false,\n }),\n detach: Flags.boolean({\n description: 'Start the copy without waiting for it to finish',\n exclusive: ['list', 'attach'],\n required: false,\n }),\n limit: Flags.integer({\n dependsOn: ['list'],\n description: 'Maximum number of jobs returned (default 10, max 1000)',\n max: 1000,\n required: false,\n }),\n list: Flags.boolean({\n description: 'Lists all dataset copy jobs',\n exclusive: ['attach', 'detach', 'skip-history'],\n required: false,\n }),\n offset: Flags.integer({\n dependsOn: ['list'],\n description: 'Start position in the list of jobs (default 0)',\n required: false,\n }),\n 'skip-content-releases': Flags.boolean({\n description: \"Don't copy content release documents to the target dataset\",\n exclusive: ['list', 'attach'],\n required: false,\n }),\n 'skip-history': Flags.boolean({\n description: \"Don't preserve document history on copy\",\n exclusive: ['list', 'attach'],\n required: false,\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:copy']\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(CopyDatasetCommand)\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [\n {grant: 'read', permission: 'sanity.project.datasets'},\n {grant: 'create', permission: 'sanity.project.datasets'},\n ],\n }),\n })\n\n // Route to appropriate mode\n if (flags.list) {\n return this.handleListMode(projectId, flags)\n }\n\n if (flags.attach) {\n return this.handleAttachMode(projectId, flags.attach)\n }\n\n return this.handleCopyMode(projectId, args, flags)\n }\n\n private displayCopyJobsTable(jobs: DatasetCopyJob[]): void {\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'id', title: 'Job ID'},\n {alignment: 'left', name: 'sourceDataset', title: 'Source Dataset'},\n {alignment: 'left', name: 'targetDataset', title: 'Target Dataset'},\n {alignment: 'left', name: 'state', title: 'State'},\n {alignment: 'left', name: 'withHistory', title: 'With history'},\n {alignment: 'left', name: 'timeStarted', title: 'Time started'},\n {alignment: 'left', name: 'timeTaken', title: 'Time taken'},\n ],\n title: 'Dataset copy jobs for this project in descending order',\n })\n\n for (const job of jobs) {\n const {createdAt, id, sourceDataset, state, targetDataset, updatedAt, withHistory} = job\n\n let timeStarted = ''\n if (createdAt !== '') {\n timeStarted = formatDistanceToNow(parseISO(createdAt))\n }\n\n let timeTaken = ''\n if (updatedAt !== '') {\n timeTaken = formatDistance(parseISO(updatedAt), parseISO(createdAt))\n }\n\n let color: '' | 'green' | 'red' | 'yellow'\n switch (state) {\n case 'completed': {\n color = 'green'\n break\n }\n case 'failed': {\n color = 'red'\n break\n }\n case 'pending': {\n color = 'yellow'\n break\n }\n default: {\n color = ''\n }\n }\n\n table.addRow(\n {\n id,\n sourceDataset,\n state,\n targetDataset,\n timeStarted: `${timeStarted} ago`,\n timeTaken,\n withHistory,\n },\n {color},\n )\n }\n\n table.printTable()\n }\n\n private async handleAttachMode(projectId: string, jobId: string): Promise<void> {\n copyDatasetDebug('Attaching to copy job %s', jobId)\n\n if (jobId.trim() === '') {\n this.error('Please supply a valid jobId', {exit: 1})\n }\n\n try {\n await this.subscribeToProgress(projectId, jobId)\n this.log(`Job ${styleText('green', jobId)} completed`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to attach to copy job: %s', message, error)\n this.error(`Failed to attach to copy job: ${message}`, {exit: 1})\n }\n }\n\n private async handleCopyMode(\n projectId: string,\n args: {source?: string; target?: string},\n flags: {'skip-content-releases'?: boolean; 'skip-history'?: boolean; detach?: boolean},\n ): Promise<void> {\n copyDatasetDebug('Starting copy mode')\n\n const skipHistory = Boolean(flags['skip-history'])\n const skipContentReleases = Boolean(flags['skip-content-releases'])\n\n // Get and validate source dataset\n let sourceDataset = args.source\n if (sourceDataset) {\n const nameError = validateDatasetName(sourceDataset)\n if (nameError) {\n this.error(nameError, {exit: 1})\n }\n }\n\n let datasetsResponse\n try {\n datasetsResponse = await listDatasets(projectId)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to fetch datasets: %s', message, error)\n this.error(`Failed to fetch datasets: ${message}`, {exit: 1})\n }\n\n const datasetNames = new Set(datasetsResponse.map((ds) => ds.name))\n\n // Prompt for source if not provided\n if (!sourceDataset) {\n sourceDataset = await promptForDataset({\n datasets: datasetsResponse,\n })\n }\n\n if (!datasetNames.has(sourceDataset)) {\n this.error(`Source dataset \"${sourceDataset}\" doesn't exist`, {exit: 1})\n }\n\n // Get and validate target dataset\n let targetDataset = args.target\n if (targetDataset) {\n const nameError = validateDatasetName(targetDataset)\n if (nameError) {\n this.error(nameError, {exit: 1})\n }\n } else {\n targetDataset = await promptForDatasetName({\n message: 'Target dataset name:',\n })\n }\n\n if (datasetNames.has(targetDataset)) {\n this.error(`Target dataset \"${targetDataset}\" already exists`, {exit: 1})\n }\n\n // Start the copy job\n try {\n this.log(\n `Copying dataset ${styleText('green', sourceDataset)} to ${styleText('green', targetDataset)}...`,\n )\n\n if (!skipHistory) {\n this.log(\n `Note: You can run this command with flag '--skip-history'. The flag will reduce copy time in larger datasets.`,\n )\n }\n\n const response = await copyDataset({\n projectId,\n skipContentReleases,\n skipHistory,\n sourceDataset,\n targetDataset,\n })\n\n this.log(`Job ${styleText('green', response.jobId)} started`)\n\n if (flags.detach) {\n return\n }\n\n await this.subscribeToProgress(projectId, response.jobId)\n this.log(`Job ${styleText('green', response.jobId)} completed`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Dataset copying failed: %s', message, error)\n this.error(`Dataset copying failed: ${message}`, {exit: 1})\n }\n }\n\n private async handleListMode(\n projectId: string,\n flags: {limit?: number; offset?: number},\n ): Promise<void> {\n copyDatasetDebug('Listing dataset copy jobs')\n\n try {\n const jobs = await listDatasetCopyJobs({\n limit: flags.limit,\n offset: flags.offset,\n projectId,\n })\n\n if (jobs.length === 0) {\n this.log(\"This project doesn't have any dataset copy jobs\")\n return\n }\n\n this.displayCopyJobsTable(jobs)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to list dataset copy jobs: %s', message, error)\n this.error(`Failed to list dataset copy jobs: ${message}`, {exit: 1})\n }\n }\n\n private async subscribeToProgress(projectId: string, jobId: string): Promise<void> {\n let currentProgress = 0\n const spin = spinner('').start()\n\n return new Promise<void>((resolve, reject) => {\n const sigintHandler = () => {\n subscription.unsubscribe()\n spin.fail('Copy interrupted.')\n exit(130)\n }\n\n const subscription = followCopyJobProgress({jobId, projectId}).subscribe({\n complete: () => {\n process.off('SIGINT', sigintHandler)\n spin.succeed('Copy finished.')\n resolve()\n },\n error: (err) => {\n process.off('SIGINT', sigintHandler)\n spin.fail('Copy failed.')\n reject(err)\n },\n next: (event: CopyJobProgressEvent) => {\n if (typeof event.progress === 'number') {\n currentProgress = event.progress\n }\n spin.text = `Copy in progress: ${currentProgress}%`\n },\n })\n\n process.once('SIGINT', sigintHandler)\n })\n }\n}\n"],"names":["styleText","Args","Flags","exit","SanityCommand","subdebug","spinner","Table","formatDistance","formatDistanceToNow","parseISO","validateDatasetName","promptForDataset","promptForDatasetName","promptForProject","copyDataset","followCopyJobProgress","listDatasetCopyJobs","listDatasets","getProjectIdFlag","copyDatasetDebug","CopyDatasetCommand","args","source","string","description","required","target","examples","command","flags","semantics","attach","exclusive","detach","boolean","limit","integer","dependsOn","max","list","offset","hiddenAliases","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","handleListMode","handleAttachMode","handleCopyMode","displayCopyJobsTable","jobs","table","columns","alignment","name","title","job","createdAt","id","sourceDataset","state","targetDataset","updatedAt","withHistory","timeStarted","timeTaken","color","addRow","printTable","jobId","trim","error","subscribeToProgress","log","message","Error","String","skipHistory","Boolean","skipContentReleases","nameError","datasetsResponse","datasetNames","Set","map","ds","datasets","has","response","length","currentProgress","spin","start","Promise","resolve","reject","sigintHandler","subscription","unsubscribe","fail","subscribe","complete","process","off","succeed","err","next","event","progress","text","once"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/datasets/copy.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exit} from '@oclif/core/errors'\nimport {SanityCommand, subdebug} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {Table} from 'console-table-printer'\nimport {formatDistance} from 'date-fns/formatDistance'\nimport {formatDistanceToNow} from 'date-fns/formatDistanceToNow'\nimport {parseISO} from 'date-fns/parseISO'\n\nimport {validateDatasetName} from '../../actions/dataset/validateDatasetName.js'\nimport {promptForDataset} from '../../prompts/promptForDataset.js'\nimport {promptForDatasetName} from '../../prompts/promptForDatasetName.js'\nimport {promptForProject} from '../../prompts/promptForProject.js'\nimport {\n copyDataset,\n type CopyJobProgressEvent,\n type DatasetCopyJob,\n followCopyJobProgress,\n listDatasetCopyJobs,\n listDatasets,\n} from '../../services/datasets.js'\nimport {getProjectIdFlag} from '../../util/sharedFlags.js'\n\nconst copyDatasetDebug = subdebug('dataset:copy')\n\nexport class CopyDatasetCommand extends SanityCommand<typeof CopyDatasetCommand> {\n static override args = {\n source: Args.string({\n description: 'Name of the dataset to copy from',\n required: false,\n }),\n target: Args.string({\n description: 'Name of the dataset to copy to',\n required: false,\n }),\n }\n\n static override description = 'Copy a dataset or manage copy jobs'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Interactively copy a dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> source-dataset',\n description: 'Copy from source-dataset (prompts for target)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> source-dataset target-dataset',\n description: 'Copy from source-dataset to target-dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --skip-history source target',\n description: 'Copy without preserving document history (faster for large datasets)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --skip-content-releases source target',\n description: 'Copy without content release documents',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --detach source target',\n description: 'Start copy job without waiting for completion',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --attach <job-id>',\n description: 'Attach to a running copy job to follow progress',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --list',\n description: 'List all dataset copy jobs',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --list --offset 2 --limit 10',\n description: 'List copy jobs with pagination',\n },\n ]\n\n static override flags = {\n ...getProjectIdFlag({\n description: 'Project ID to copy dataset in',\n semantics: 'override',\n }),\n attach: Flags.string({\n description: 'Attach to the running copy process to show progress',\n exclusive: ['list', 'detach', 'skip-history'],\n required: false,\n }),\n detach: Flags.boolean({\n description: 'Start the copy without waiting for it to finish',\n exclusive: ['list', 'attach'],\n required: false,\n }),\n limit: Flags.integer({\n dependsOn: ['list'],\n description: 'Maximum number of jobs returned (default 10, max 1000)',\n max: 1000,\n required: false,\n }),\n list: Flags.boolean({\n description: 'Lists all dataset copy jobs',\n exclusive: ['attach', 'detach', 'skip-history'],\n required: false,\n }),\n offset: Flags.integer({\n dependsOn: ['list'],\n description: 'Start position in the list of jobs (default 0)',\n required: false,\n }),\n 'skip-content-releases': Flags.boolean({\n description: \"Don't copy content release documents to the target dataset\",\n exclusive: ['list', 'attach'],\n required: false,\n }),\n 'skip-history': Flags.boolean({\n description: \"Don't preserve document history on copy\",\n exclusive: ['list', 'attach'],\n required: false,\n }),\n }\n\n static override hiddenAliases: string[] = ['dataset:copy']\n\n public async run(): Promise<void> {\n const {args, flags} = await this.parse(CopyDatasetCommand)\n\n const projectId = await this.getProjectId({\n fallback: () =>\n promptForProject({\n requiredPermissions: [\n {grant: 'read', permission: 'sanity.project.datasets'},\n {grant: 'create', permission: 'sanity.project.datasets'},\n ],\n }),\n })\n\n // Route to appropriate mode\n if (flags.list) {\n return this.handleListMode(projectId, flags)\n }\n\n if (flags.attach) {\n return this.handleAttachMode(projectId, flags.attach)\n }\n\n return this.handleCopyMode(projectId, args, flags)\n }\n\n private displayCopyJobsTable(jobs: DatasetCopyJob[]): void {\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'id', title: 'Job ID'},\n {alignment: 'left', name: 'sourceDataset', title: 'Source Dataset'},\n {alignment: 'left', name: 'targetDataset', title: 'Target Dataset'},\n {alignment: 'left', name: 'state', title: 'State'},\n {alignment: 'left', name: 'withHistory', title: 'With history'},\n {alignment: 'left', name: 'timeStarted', title: 'Time started'},\n {alignment: 'left', name: 'timeTaken', title: 'Time taken'},\n ],\n title: 'Dataset copy jobs for this project in descending order',\n })\n\n for (const job of jobs) {\n const {createdAt, id, sourceDataset, state, targetDataset, updatedAt, withHistory} = job\n\n let timeStarted = ''\n if (createdAt !== '') {\n timeStarted = formatDistanceToNow(parseISO(createdAt))\n }\n\n let timeTaken = ''\n if (updatedAt !== '') {\n timeTaken = formatDistance(parseISO(updatedAt), parseISO(createdAt))\n }\n\n let color: '' | 'green' | 'red' | 'yellow'\n switch (state) {\n case 'completed': {\n color = 'green'\n break\n }\n case 'failed': {\n color = 'red'\n break\n }\n case 'pending': {\n color = 'yellow'\n break\n }\n default: {\n color = ''\n }\n }\n\n table.addRow(\n {\n id,\n sourceDataset,\n state,\n targetDataset,\n timeStarted: `${timeStarted} ago`,\n timeTaken,\n withHistory,\n },\n {color},\n )\n }\n\n table.printTable()\n }\n\n private async handleAttachMode(projectId: string, jobId: string): Promise<void> {\n copyDatasetDebug('Attaching to copy job %s', jobId)\n\n if (jobId.trim() === '') {\n this.error('Please supply a valid jobId', {exit: 1})\n }\n\n try {\n await this.subscribeToProgress(projectId, jobId)\n this.log(`Job ${styleText('green', jobId)} completed`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to attach to copy job: %s', message, error)\n this.error(`Failed to attach to copy job: ${message}`, {exit: 1})\n }\n }\n\n private async handleCopyMode(\n projectId: string,\n args: {source?: string; target?: string},\n flags: {detach?: boolean; 'skip-content-releases'?: boolean; 'skip-history'?: boolean},\n ): Promise<void> {\n copyDatasetDebug('Starting copy mode')\n\n const skipHistory = Boolean(flags['skip-history'])\n const skipContentReleases = Boolean(flags['skip-content-releases'])\n\n // Get and validate source dataset\n let sourceDataset = args.source\n if (sourceDataset) {\n const nameError = validateDatasetName(sourceDataset)\n if (nameError) {\n this.error(nameError, {exit: 1})\n }\n }\n\n let datasetsResponse\n try {\n datasetsResponse = await listDatasets(projectId)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to fetch datasets: %s', message, error)\n this.error(`Failed to fetch datasets: ${message}`, {exit: 1})\n }\n\n const datasetNames = new Set(datasetsResponse.map((ds) => ds.name))\n\n // Prompt for source if not provided\n if (!sourceDataset) {\n sourceDataset = await promptForDataset({\n datasets: datasetsResponse,\n })\n }\n\n if (!datasetNames.has(sourceDataset)) {\n this.error(`Source dataset \"${sourceDataset}\" doesn't exist`, {exit: 1})\n }\n\n // Get and validate target dataset\n let targetDataset = args.target\n if (targetDataset) {\n const nameError = validateDatasetName(targetDataset)\n if (nameError) {\n this.error(nameError, {exit: 1})\n }\n } else {\n targetDataset = await promptForDatasetName({\n message: 'Target dataset name:',\n })\n }\n\n if (datasetNames.has(targetDataset)) {\n this.error(`Target dataset \"${targetDataset}\" already exists`, {exit: 1})\n }\n\n // Start the copy job\n try {\n this.log(\n `Copying dataset ${styleText('green', sourceDataset)} to ${styleText('green', targetDataset)}...`,\n )\n\n if (!skipHistory) {\n this.log(\n `Note: You can run this command with flag '--skip-history'. The flag will reduce copy time in larger datasets.`,\n )\n }\n\n const response = await copyDataset({\n projectId,\n skipContentReleases,\n skipHistory,\n sourceDataset,\n targetDataset,\n })\n\n this.log(`Job ${styleText('green', response.jobId)} started`)\n\n if (flags.detach) {\n return\n }\n\n await this.subscribeToProgress(projectId, response.jobId)\n this.log(`Job ${styleText('green', response.jobId)} completed`)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Dataset copying failed: %s', message, error)\n this.error(`Dataset copying failed: ${message}`, {exit: 1})\n }\n }\n\n private async handleListMode(\n projectId: string,\n flags: {limit?: number; offset?: number},\n ): Promise<void> {\n copyDatasetDebug('Listing dataset copy jobs')\n\n try {\n const jobs = await listDatasetCopyJobs({\n limit: flags.limit,\n offset: flags.offset,\n projectId,\n })\n\n if (jobs.length === 0) {\n this.log(\"This project doesn't have any dataset copy jobs\")\n return\n }\n\n this.displayCopyJobsTable(jobs)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n copyDatasetDebug('Failed to list dataset copy jobs: %s', message, error)\n this.error(`Failed to list dataset copy jobs: ${message}`, {exit: 1})\n }\n }\n\n private async subscribeToProgress(projectId: string, jobId: string): Promise<void> {\n let currentProgress = 0\n const spin = spinner('').start()\n\n return new Promise<void>((resolve, reject) => {\n const sigintHandler = () => {\n subscription.unsubscribe()\n spin.fail('Copy interrupted.')\n exit(130)\n }\n\n const subscription = followCopyJobProgress({jobId, projectId}).subscribe({\n complete: () => {\n process.off('SIGINT', sigintHandler)\n spin.succeed('Copy finished.')\n resolve()\n },\n error: (err) => {\n process.off('SIGINT', sigintHandler)\n spin.fail('Copy failed.')\n reject(err)\n },\n next: (event: CopyJobProgressEvent) => {\n if (typeof event.progress === 'number') {\n currentProgress = event.progress\n }\n spin.text = `Copy in progress: ${currentProgress}%`\n },\n })\n\n process.once('SIGINT', sigintHandler)\n })\n }\n}\n"],"names":["styleText","Args","Flags","exit","SanityCommand","subdebug","spinner","Table","formatDistance","formatDistanceToNow","parseISO","validateDatasetName","promptForDataset","promptForDatasetName","promptForProject","copyDataset","followCopyJobProgress","listDatasetCopyJobs","listDatasets","getProjectIdFlag","copyDatasetDebug","CopyDatasetCommand","args","source","string","description","required","target","examples","command","flags","semantics","attach","exclusive","detach","boolean","limit","integer","dependsOn","max","list","offset","hiddenAliases","run","parse","projectId","getProjectId","fallback","requiredPermissions","grant","permission","handleListMode","handleAttachMode","handleCopyMode","displayCopyJobsTable","jobs","table","columns","alignment","name","title","job","createdAt","id","sourceDataset","state","targetDataset","updatedAt","withHistory","timeStarted","timeTaken","color","addRow","printTable","jobId","trim","error","subscribeToProgress","log","message","Error","String","skipHistory","Boolean","skipContentReleases","nameError","datasetsResponse","datasetNames","Set","map","ds","datasets","has","response","length","currentProgress","spin","start","Promise","resolve","reject","sigintHandler","subscription","unsubscribe","fail","subscribe","complete","process","off","succeed","err","next","event","progress","text","once"],"mappings":"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"}
|