@sanity/cli 8.22.1 → 8.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/actions/context/watchJob.js +9 -3
  2. package/dist/actions/context/watchJob.js.map +1 -1
  3. package/dist/actions/deploy/blueprintManaged.js +59 -0
  4. package/dist/actions/deploy/blueprintManaged.js.map +1 -0
  5. package/dist/actions/deploy/deployApp.js +117 -1
  6. package/dist/actions/deploy/deployApp.js.map +1 -1
  7. package/dist/actions/deploy/deployRunner.js.map +1 -1
  8. package/dist/actions/deploy/deployStudio.js +6 -31
  9. package/dist/actions/deploy/deployStudio.js.map +1 -1
  10. package/dist/actions/exec/runScript.worker.js +6 -2
  11. package/dist/actions/exec/runScript.worker.js.map +1 -1
  12. package/dist/actions/init/bootstrapLocalTemplate.js +35 -11
  13. package/dist/actions/init/bootstrapLocalTemplate.js.map +1 -1
  14. package/dist/actions/init/createMediaLibraryCliConfig.js +12 -0
  15. package/dist/actions/init/createMediaLibraryCliConfig.js.map +1 -0
  16. package/dist/actions/init/determineMediaLibraryTemplate.js +14 -0
  17. package/dist/actions/init/determineMediaLibraryTemplate.js.map +1 -0
  18. package/dist/actions/init/initAction.js +35 -6
  19. package/dist/actions/init/initAction.js.map +1 -1
  20. package/dist/actions/init/initApp.js +81 -6
  21. package/dist/actions/init/initApp.js.map +1 -1
  22. package/dist/actions/init/offerAspectPull.js +81 -0
  23. package/dist/actions/init/offerAspectPull.js.map +1 -0
  24. package/dist/actions/init/project/getProjectDetails.js +25 -2
  25. package/dist/actions/init/project/getProjectDetails.js.map +1 -1
  26. package/dist/actions/init/templates/index.js +3 -0
  27. package/dist/actions/init/templates/index.js.map +1 -1
  28. package/dist/actions/init/templates/mediaLibraryConfig.js +51 -0
  29. package/dist/actions/init/templates/mediaLibraryConfig.js.map +1 -0
  30. package/dist/actions/media/aspectName.js +8 -0
  31. package/dist/actions/media/aspectName.js.map +1 -0
  32. package/dist/actions/media/aspectSync/contract.js +163 -0
  33. package/dist/actions/media/aspectSync/contract.js.map +1 -0
  34. package/dist/actions/media/aspectSync/syncAspects.js +115 -0
  35. package/dist/actions/media/aspectSync/syncAspects.js.map +1 -0
  36. package/dist/actions/media/cliConfigFields.js +192 -0
  37. package/dist/actions/media/cliConfigFields.js.map +1 -0
  38. package/dist/actions/media/pullAspects.js +225 -0
  39. package/dist/actions/media/pullAspects.js.map +1 -0
  40. package/dist/actions/media/resolveMediaLibraryId.js +83 -0
  41. package/dist/actions/media/resolveMediaLibraryId.js.map +1 -0
  42. package/dist/commands/context/build.js +2 -2
  43. package/dist/commands/context/build.js.map +1 -1
  44. package/dist/commands/context/entries/get.js +83 -0
  45. package/dist/commands/context/entries/get.js.map +1 -0
  46. package/dist/commands/context/entries/list.js +82 -0
  47. package/dist/commands/context/entries/list.js.map +1 -0
  48. package/dist/commands/context/entries/rebuild.js +95 -0
  49. package/dist/commands/context/entries/rebuild.js.map +1 -0
  50. package/dist/commands/context/issues/apply.js +86 -0
  51. package/dist/commands/context/issues/apply.js.map +1 -0
  52. package/dist/commands/context/issues/dismiss.js +52 -0
  53. package/dist/commands/context/issues/dismiss.js.map +1 -0
  54. package/dist/commands/context/issues/get.js +105 -0
  55. package/dist/commands/context/issues/get.js.map +1 -0
  56. package/dist/commands/context/issues/list.js +128 -0
  57. package/dist/commands/context/issues/list.js.map +1 -0
  58. package/dist/commands/context/issues/reopen.js +53 -0
  59. package/dist/commands/context/issues/reopen.js.map +1 -0
  60. package/dist/commands/context/issues/resolve.js +137 -0
  61. package/dist/commands/context/issues/resolve.js.map +1 -0
  62. package/dist/commands/context/jobs/get.js +2 -2
  63. package/dist/commands/context/jobs/get.js.map +1 -1
  64. package/dist/commands/context/query.js +92 -0
  65. package/dist/commands/context/query.js.map +1 -0
  66. package/dist/commands/deploy.js +13 -0
  67. package/dist/commands/deploy.js.map +1 -1
  68. package/dist/commands/media/prune-aspect-data.js +170 -0
  69. package/dist/commands/media/prune-aspect-data.js.map +1 -0
  70. package/dist/commands/media/pull-aspects.js +309 -0
  71. package/dist/commands/media/pull-aspects.js.map +1 -0
  72. package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js +17 -0
  73. package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js.map +1 -1
  74. package/dist/services/context.js +96 -3
  75. package/dist/services/context.js.map +1 -1
  76. package/dist/services/mediaLibraries.js +175 -8
  77. package/dist/services/mediaLibraries.js.map +1 -1
  78. package/oclif.manifest.json +2930 -2241
  79. package/package.json +6 -5
  80. package/templates/media-library-config/README.md +52 -0
  81. package/templates/media-library-config/eslint.config.txt +52 -0
  82. package/templates/media-library-config/src/fields/caption.tsx +29 -0
  83. package/templates/media-library-config/src/fields/notes.tsx +54 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/deploy/deployStudio.ts"],"sourcesContent":["import {basename, dirname, join, relative} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip, type Gzip} from 'node:zlib'\n\nimport {findBlueprintFile, readBlueprint} from '@sanity/blueprints/resolve'\nimport {formatSchemaValidation, SchemaExtractionError} from '@sanity/cli-build/_internal/extract'\nimport {readIconFromPath} from '@sanity/cli-build/_internal/manifest'\nimport {exitCodes} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {\n type BrettAccess,\n type BrettWorkspace,\n createStudio,\n deployWorkbenchApp,\n getApplicationUrl,\n getWorkbench,\n getWorkbenchUrl,\n toWorkbenchPayload,\n} from '@sanity/workbench-cli/deploy'\nimport {type StudioManifest} from 'sanity'\nimport {c as createTar} from 'tar'\n\nimport {createDeployment, type UserApplication} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {NO_ORGANIZATION_ID, NO_PROJECT_ID} from '../../util/errorMessages.js'\nimport {buildStudio} from '../build/buildStudio.js'\nimport {createStudioUserApplication} from './createUserApplication.js'\nimport {\n checkAutoUpdates,\n checkBuild,\n checkExternalUrl,\n checkPackageVersion,\n checkStudioTarget,\n type DeployCheckReporter,\n verifyOutputDir,\n} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {listDeploymentFiles, reportInterfaces} from './deploymentPlan.js'\nimport {type DeployPayload, type DeployResult, runDeploy} from './deployRunner.js'\nimport {deployStudioSchemasAndManifests} from './deployStudioSchemasAndManifests.js'\nimport {findUserApplicationForStudio} from './findUserApplication.js'\nimport {type DeployAppOptions} from './types.js'\n\nconst STUDIO_PACKAGE = 'sanity'\n\nexport function deployStudio(options: DeployAppOptions): Promise<void> {\n return runDeploy(options, {\n listFiles: ({flags, projectRoot, sourceDir}) =>\n flags.external ? Promise.resolve([]) : listDeploymentFiles(sourceDir, projectRoot.directory),\n run: runStudioDeployment,\n type: 'studio',\n })\n}\n\n/** Validates the deploy, extracts and uploads the schema, and ships the build. */\nasync function runStudioDeployment(\n options: DeployAppOptions,\n reporter: DeployCheckReporter,\n): Promise<DeployResult | void> {\n const {cliConfig, flags, output, sourceDir} = options\n const workDir = options.projectRoot.directory\n const isExternal = !!flags.external\n const workbench = getWorkbench(cliConfig)\n const isWorkbenchApp = workbench !== null\n const projectId = cliConfig.api?.projectId\n const organizationId = cliConfig.app?.organizationId\n const appId = getAppId(cliConfig)\n const dryRun = !!flags['dry-run']\n // A legacy external studio only registers its URL; a federated one is built\n // and deployed like a hosted one, minus the upload.\n const isLegacyExternal = isExternal && !isWorkbenchApp\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.slug\n : ''\n\n const isAutoUpdating = checkAutoUpdates(reporter, {cliConfig, flags})\n\n const version = await checkPackageVersion(reporter, {\n moduleName: STUDIO_PACKAGE,\n workDir,\n })\n\n reporter.report(\n projectId\n ? {message: `Project: ${projectId}`, status: 'pass'}\n : {\n message: NO_PROJECT_ID,\n solution: 'Add `api.projectId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n\n if (await isBlueprintStudio(options.projectRoot.directory)) {\n reporter.report({\n message:\n 'Using the `deploy` command for a studio that is referenced by a blueprint is not allowed',\n solution: 'Deploy the studio using the `blueprints deploy` command',\n status: 'fail',\n })\n }\n\n // Workbench studios deploy to Brett (which needs the org); plain studios\n // resolve/create on user-applications, unchanged.\n let application: UserApplication | null = null\n let studioCreated = false\n let workbenchApp: {externalUrl?: string} | undefined\n let externalUrl: string | undefined\n if (workbench) {\n reporter.report(\n organizationId\n ? {message: `Organization: ${organizationId}`, status: 'pass'}\n : {\n message: NO_ORGANIZATION_ID,\n solution: 'Add `app.organizationId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n workbenchApp = (\n await checkStudioTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n organizationId,\n slug: workbench.slug,\n title: appTitle,\n })\n )?.application\n if (isExternal) externalUrl = checkExternalUrl(reporter, {appId, url: flags.url})\n } else {\n ;({application, created: studioCreated} = await resolveStudioApplication(options, {\n dryRun,\n reporter,\n }))\n }\n // A redeploy follows how the application was registered, so --external is only needed once.\n const isExternallyHosted = isExternal || !!workbenchApp?.externalUrl\n\n // A first deploy mints the app id and the build inlines it; --no-build would\n // ship an existing bundle carrying a different id, so it can't be a first deploy.\n if (workbench && !appId && !flags.build) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'A first deploy cannot skip the build (--no-build)',\n solution: 'Drop --no-build so the new application id is inlined into the build',\n status: 'fail',\n })\n }\n\n // Read up front so a bad icon path fails before we create or build.\n const appIcon =\n !dryRun && workbench?.icon ? await readIconFromPath(workDir, workbench.icon) : undefined\n\n // Create the studio before the build so the bundle carries its real id. A\n // redeploy already has it from `deployment.appId`; a dry run skips creation.\n let applicationId = appId\n let applicationCreated = false\n let rollbackApp: (() => Promise<void>) | undefined\n if (!dryRun && workbench && organizationId && !applicationId) {\n const created = await createStudio({\n externalUrl,\n name: workbench.name,\n organizationId,\n projectId,\n slug: workbench.slug,\n title: appTitle,\n visibility: workbench.visibility,\n })\n workbenchApp = created.application\n applicationId = created.application.id\n rollbackApp = created.rollback\n applicationCreated = true\n }\n\n // A record created above is stranded at its slug (and blocks retries) if any\n // step before it fully deploys fails, so undo the creation on failure.\n try {\n const built = await checkBuild(reporter, {\n build: () =>\n buildStudio({\n applicationId: workbench ? applicationId : undefined,\n autoUpdatesEnabled: isAutoUpdating,\n calledFromDeploy: true,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n }),\n skipReason: studioBuildSkipReason({build: flags.build, isLegacyExternal}),\n successMessage: 'Studio built',\n })\n\n let mfManifest = built?.mfManifest\n // A federated build has already read its manifest; anything else verifies the directory.\n if (mfManifest === undefined && !isLegacyExternal) {\n mfManifest = await verifyOutputDir({isWorkbenchApp, reporter, sourceDir})\n }\n\n const interfaces = workbench ? reportInterfaces(reporter, workbench) : null\n\n const payload: DeployPayload = {\n appId: appId ?? null,\n isAutoUpdating,\n ...(organizationId ? {organizationId} : {}),\n ...(projectId ? {projectId} : {}),\n type: 'studio',\n version,\n ...toWorkbenchPayload(workbench, {interfaces, title: appTitle}),\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return {application: null, payload}\n\n // A real deploy has already exited if anything failed; landing here without a\n // resolved version means the deploy target was never resolved.\n if (!version) return\n\n const studioManifest = await uploadStudioSchema(options, {\n applicationId: workbench ? applicationId : undefined,\n isExternal: isLegacyExternal,\n })\n // The studio was created (or resolved from `deployment.appId`) before the\n // build, so this only ships the deployment; plain studios use user-applications.\n if (workbench && organizationId && applicationId) {\n if (!mfManifest) throw new Error('The federated build produced no manifest.')\n await deployWorkbenchApp({\n access: toAccess(studioManifest),\n app: cliConfig.app,\n applicationId,\n icon: appIcon,\n isApp: false,\n isAutoUpdating,\n isExternal: isExternallyHosted,\n label: 'Deploying studio',\n mfManifest,\n // Once the deployment is live, a metadata-sync failure must not delete\n // the studio.\n onDeployed: () => {\n rollbackApp = undefined\n },\n slug: workbench.slug,\n sourceDir,\n title: appTitle,\n version,\n visibility: workbench.visibility,\n workspaces: toWorkspaces(studioManifest),\n })\n const url = getApplicationUrl({\n id: applicationId,\n organizationId,\n slug: workbench.slug,\n type: 'studio',\n })\n logWorkbenchStudioDeployed({applicationId, cliConfig, output, url})\n if (isExternallyHosted)\n logExternalHost({built: flags.build, organizationId, output, sourceDir})\n return {\n action: applicationCreated ? 'create' : 'update',\n application: workbenchApp ?? null,\n payload,\n url,\n }\n }\n\n if (!application) return\n const location = await shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n })\n\n return {\n action: studioCreated ? 'create' : 'update',\n application,\n payload,\n url: location,\n }\n } catch (err) {\n await rollbackApp?.()\n throw err\n }\n}\n\n/**\n * Finds the application a real deploy targets, registering a studio host when\n * none is configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveStudioApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplication | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const isExternal = !!flags.external\n const appId = getAppId(cliConfig)\n // Sets the title on a newly registered studio; blank falls back to undefined\n const title = flags.title?.trim() || undefined\n\n if (dryRun) {\n await checkStudioTarget(reporter, {\n appId,\n isExternal,\n projectId: cliConfig.api?.projectId,\n studioHost: cliConfig.studioHost,\n title,\n urlFlag: flags.url,\n })\n return {application: null, created: false}\n }\n\n const projectId = cliConfig.api?.projectId ?? ''\n // `created` is true when a configured-but-unregistered host was just registered.\n const {application, created} = await findUserApplicationForStudio({\n appId,\n isExternal,\n output,\n projectId,\n studioHost: cliConfig.studioHost,\n title,\n unattended: !!flags.yes,\n urlFlag: flags.url,\n })\n\n if (!application) {\n if (isExternal) {\n output.log('Your project has not been registered with an external studio URL.')\n output.log('Please enter the full URL where your studio is hosted.')\n } else {\n output.log('Your project has not been assigned a studio hostname.')\n output.log('To deploy your Sanity Studio to our hosted sanity.studio service,')\n output.log('you will need one. Please enter the subdomain you want to use.')\n }\n\n const registered = await createStudioUserApplication({\n projectId,\n title,\n urlType: isExternal ? 'external' : 'internal',\n })\n deployDebug('Created user application', registered)\n return {application: registered, created: true}\n }\n\n deployDebug('Found user application', application)\n return {application, created}\n}\n\n/** Extracts the studio schema and manifest and uploads them to the schema store. */\nasync function uploadStudioSchema(\n options: DeployAppOptions,\n {applicationId, isExternal}: {applicationId?: string; isExternal: boolean},\n): Promise<StudioManifest | null> {\n const {cliConfig, flags, output, projectRoot, sourceDir} = options\n\n let studioManifest: StudioManifest | null = null\n try {\n studioManifest = await deployStudioSchemasAndManifests(\n {\n applicationId,\n configPath: projectRoot.path,\n isExternal,\n outPath: `${sourceDir}/static`,\n projectId: cliConfig.api?.projectId ?? '',\n schemaRequired: flags['schema-required'],\n verbose: flags.verbose,\n workDir: projectRoot.directory,\n },\n output,\n )\n } catch (error) {\n deployDebug('Error deploying studio schemas and manifests', error)\n if (error instanceof SchemaExtractionError && error.validation?.length) {\n output.error(formatSchemaValidation(error.validation), {exit: exitCodes.RUNTIME_ERROR})\n }\n output.error(`Error deploying studio schemas and manifests: ${error}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (!studioManifest) {\n output.error('Failed to generate studio manifest. Please check your schemas and manifests.', {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n return studioManifest\n}\n\nasync function shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n isExternal: boolean\n options: DeployAppOptions\n studioManifest: StudioManifest | null\n version: string\n}): Promise<string> {\n const {cliConfig, output, sourceDir} = options\n\n let tarball: Gzip | undefined\n if (!isExternal) {\n tarball = createTar({cwd: dirname(sourceDir)}, [basename(sourceDir)]).pipe(createGzip())\n }\n\n const spin = spinner(isExternal ? 'Registering studio' : 'Deploying to sanity.studio').start()\n let location: string\n try {\n ;({location} = await createDeployment({\n applicationId: application.id,\n isApp: false,\n isAutoUpdating,\n manifest: studioManifest,\n projectId: cliConfig.api?.projectId,\n tarball,\n version,\n }))\n } catch (error) {\n spin.fail()\n throw error\n }\n spin.succeed()\n\n const named = application.title ? ` — \"${application.title}\"` : ''\n output.log(\n isExternal\n ? `\\nSuccess! Studio registered${named}`\n : `\\nSuccess! Studio deployed to ${styleText('cyan', location)}${named}`,\n )\n\n if (getAppId(cliConfig)) return location\n\n const example = `Example:\nexport default defineCliConfig({\n //…\n deployment: {\n ${styleText('cyan', `appId: '${application.id}'`)},\n },\n //…\n})`\n output.log(`\\nAdd ${styleText('cyan', `appId: '${application.id}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n output.log(`\\n${example}`)\n\n return location\n}\n\n/**\n * One `datasets` access entry per unique workspace dataset, with a `resourceId`\n * of `\"<projectId>.<dataset>\"`. Deduped, since workspaces can share a dataset.\n */\nfunction toAccess(manifest: StudioManifest | null): BrettAccess[] {\n const resourceIds = new Set(\n (manifest?.workspaces ?? []).map((w) => `${w.projectId}.${w.dataset}`),\n )\n return [...resourceIds].map(\n (resourceId) => ({resourceId, resourceType: 'dataset'}) satisfies BrettAccess,\n )\n}\n\nfunction toWorkspaces(manifest: StudioManifest | null): BrettWorkspace[] {\n return (manifest?.workspaces ?? []).map((workspace) => ({\n basePath: workspace.basePath,\n dataset: workspace.dataset,\n icon: workspace.icon,\n name: workspace.name,\n projectId: workspace.projectId,\n schemaDescriptorId: workspace.schemaDescriptorId,\n subtitle: workspace.subtitle,\n title: workspace.title,\n }))\n}\n\n/** Renders the workbench studio's deploy result; the appId hint shows only when none is configured. */\nfunction logWorkbenchStudioDeployed({\n applicationId,\n cliConfig,\n output,\n url,\n}: {\n applicationId: string\n cliConfig: DeployAppOptions['cliConfig']\n output: DeployAppOptions['output']\n url: string\n}): void {\n output.log(`\\nSuccess! Studio deployed to ${styleText('cyan', url)}`)\n if (getAppId(cliConfig)) return\n\n output.log(`\\nAdd ${styleText('cyan', `appId: '${applicationId}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n}\n\n/** Tells the customer what their host must do for the Dashboard to load the studio from it. */\nfunction logExternalHost({\n built,\n organizationId,\n output,\n sourceDir,\n}: {\n built: boolean\n organizationId: string\n output: DeployAppOptions['output']\n sourceDir: string\n}): void {\n const dir = `${relative(process.cwd(), sourceDir) || '.'}/`\n output.log(`\nThe Dashboard loads this studio from your host, which must:\n 1. Serve ${dir} unchanged at the root of its URL (/mf-manifest.json, /remoteEntry-*.js, /static/*)\n 2. Send Access-Control-Allow-Origin for ${getWorkbenchUrl(organizationId)}\n 3. Respond without cookies or a sign-in${built ? `\\n\\nThis deploy rebuilt ${dir}: copy it to your host before opening the studio in the Dashboard.` : ''}`)\n}\n\nfunction studioBuildSkipReason({\n build,\n isLegacyExternal,\n}: {\n build: boolean\n isLegacyExternal: boolean\n}) {\n if (isLegacyExternal) return 'Build skipped for externally hosted studios'\n if (!build) return 'Build skipped (--no-build) — validating existing output directory'\n return\n}\n\n/**\n * Determine if the blueprint being deployed is referenced by a blueprint.\n * @param projectRootDir - The root directory of the studio\n */\nasync function isBlueprintStudio(projectRootDir: string): Promise<boolean> {\n try {\n const blueprintFile = findBlueprintFile(projectRootDir)\n if (!blueprintFile) return false\n\n const localBlueprint = await readBlueprint({\n path: blueprintFile,\n })\n\n const blueprintReferencesStudio = localBlueprint.resources.some((r) => {\n if (r.type === 'sanity.studio' && 'root' in r && typeof r.root === 'string') {\n return relative(join(dirname(blueprintFile), r.root), projectRootDir) === ''\n }\n\n return false\n })\n\n return blueprintReferencesStudio\n } catch {\n return false // fail open\n }\n}\n"],"names":["basename","dirname","join","relative","styleText","createGzip","findBlueprintFile","readBlueprint","formatSchemaValidation","SchemaExtractionError","readIconFromPath","exitCodes","spinner","createStudio","deployWorkbenchApp","getApplicationUrl","getWorkbench","getWorkbenchUrl","toWorkbenchPayload","c","createTar","createDeployment","getAppId","NO_ORGANIZATION_ID","NO_PROJECT_ID","buildStudio","createStudioUserApplication","checkAutoUpdates","checkBuild","checkExternalUrl","checkPackageVersion","checkStudioTarget","verifyOutputDir","deployDebug","listDeploymentFiles","reportInterfaces","runDeploy","deployStudioSchemasAndManifests","findUserApplicationForStudio","STUDIO_PACKAGE","deployStudio","options","listFiles","flags","projectRoot","sourceDir","external","Promise","resolve","directory","run","runStudioDeployment","type","reporter","cliConfig","output","workDir","isExternal","workbench","isWorkbenchApp","projectId","api","organizationId","app","appId","dryRun","isLegacyExternal","appTitle","title","trim","slug","isAutoUpdating","version","moduleName","report","message","status","solution","isBlueprintStudio","application","studioCreated","workbenchApp","externalUrl","url","created","resolveStudioApplication","isExternallyHosted","build","exitCode","USAGE_ERROR","appIcon","icon","undefined","applicationId","applicationCreated","rollbackApp","name","visibility","id","rollback","built","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","studioBuildSkipReason","successMessage","mfManifest","interfaces","payload","studioManifest","uploadStudioSchema","Error","access","toAccess","isApp","label","onDeployed","workspaces","toWorkspaces","logWorkbenchStudioDeployed","logExternalHost","action","location","shipStudioDeployment","err","studioHost","urlFlag","unattended","yes","log","registered","urlType","configPath","path","outPath","schemaRequired","verbose","error","validation","length","exit","RUNTIME_ERROR","tarball","cwd","pipe","spin","start","manifest","fail","succeed","named","example","resourceIds","Set","map","w","dataset","resourceId","resourceType","workspace","basePath","schemaDescriptorId","subtitle","dir","process","projectRootDir","blueprintFile","localBlueprint","blueprintReferencesStudio","resources","some","r","root"],"mappings":"AAAA,SAAQA,QAAQ,EAAEC,OAAO,EAAEC,IAAI,EAAEC,QAAQ,QAAO,YAAW;AAC3D,SAAQC,SAAS,QAAO,YAAW;AACnC,SAAQC,UAAU,QAAkB,YAAW;AAE/C,SAAQC,iBAAiB,EAAEC,aAAa,QAAO,6BAA4B;AAC3E,SAAQC,sBAAsB,EAAEC,qBAAqB,QAAO,sCAAqC;AACjG,SAAQC,gBAAgB,QAAO,uCAAsC;AACrE,SAAQC,SAAS,QAAO,mBAAkB;AAC1C,SAAQC,OAAO,QAAO,sBAAqB;AAC3C,SAGEC,YAAY,EACZC,kBAAkB,EAClBC,iBAAiB,EACjBC,YAAY,EACZC,eAAe,EACfC,kBAAkB,QACb,+BAA8B;AAErC,SAAQC,KAAKC,SAAS,QAAO,MAAK;AAElC,SAAQC,gBAAgB,QAA6B,qCAAoC;AACzF,SAAQC,QAAQ,QAAO,sBAAqB;AAC5C,SAAQC,kBAAkB,EAAEC,aAAa,QAAO,8BAA6B;AAC7E,SAAQC,WAAW,QAAO,0BAAyB;AACnD,SAAQC,2BAA2B,QAAO,6BAA4B;AACtE,SACEC,gBAAgB,EAChBC,UAAU,EACVC,gBAAgB,EAChBC,mBAAmB,EACnBC,iBAAiB,EAEjBC,eAAe,QACV,oBAAmB;AAC1B,SAAQC,WAAW,QAAO,mBAAkB;AAC5C,SAAQC,mBAAmB,EAAEC,gBAAgB,QAAO,sBAAqB;AACzE,SAA+CC,SAAS,QAAO,oBAAmB;AAClF,SAAQC,+BAA+B,QAAO,uCAAsC;AACpF,SAAQC,4BAA4B,QAAO,2BAA0B;AAGrE,MAAMC,iBAAiB;AAEvB,OAAO,SAASC,aAAaC,OAAyB;IACpD,OAAOL,UAAUK,SAAS;QACxBC,WAAW,CAAC,EAACC,KAAK,EAAEC,WAAW,EAAEC,SAAS,EAAC,GACzCF,MAAMG,QAAQ,GAAGC,QAAQC,OAAO,CAAC,EAAE,IAAId,oBAAoBW,WAAWD,YAAYK,SAAS;QAC7FC,KAAKC;QACLC,MAAM;IACR;AACF;AAEA,gFAAgF,GAChF,eAAeD,oBACbV,OAAyB,EACzBY,QAA6B;IAE7B,MAAM,EAACC,SAAS,EAAEX,KAAK,EAAEY,MAAM,EAAEV,SAAS,EAAC,GAAGJ;IAC9C,MAAMe,UAAUf,QAAQG,WAAW,CAACK,SAAS;IAC7C,MAAMQ,aAAa,CAAC,CAACd,MAAMG,QAAQ;IACnC,MAAMY,YAAY1C,aAAasC;IAC/B,MAAMK,iBAAiBD,cAAc;IACrC,MAAME,YAAYN,UAAUO,GAAG,EAAED;IACjC,MAAME,iBAAiBR,UAAUS,GAAG,EAAED;IACtC,MAAME,QAAQ1C,SAASgC;IACvB,MAAMW,SAAS,CAAC,CAACtB,KAAK,CAAC,UAAU;IACjC,4EAA4E;IAC5E,oDAAoD;IACpD,MAAMuB,mBAAmBT,cAAc,CAACE;IAExC,MAAMQ,WAAWT,YACbf,MAAMyB,KAAK,EAAEC,UAAUf,UAAUS,GAAG,EAAEK,OAAOC,UAAUX,UAAUY,IAAI,GACrE;IAEJ,MAAMC,iBAAiB5C,iBAAiB0B,UAAU;QAACC;QAAWX;IAAK;IAEnE,MAAM6B,UAAU,MAAM1C,oBAAoBuB,UAAU;QAClDoB,YAAYlC;QACZiB;IACF;IAEAH,SAASqB,MAAM,CACbd,YACI;QAACe,SAAS,CAAC,SAAS,EAAEf,WAAW;QAAEgB,QAAQ;IAAM,IACjD;QACED,SAASnD;QACTqD,UAAU;QACVD,QAAQ;IACV;IAGN,IAAI,MAAME,kBAAkBrC,QAAQG,WAAW,CAACK,SAAS,GAAG;QAC1DI,SAASqB,MAAM,CAAC;YACdC,SACE;YACFE,UAAU;YACVD,QAAQ;QACV;IACF;IAEA,yEAAyE;IACzE,kDAAkD;IAClD,IAAIG,cAAsC;IAC1C,IAAIC,gBAAgB;IACpB,IAAIC;IACJ,IAAIC;IACJ,IAAIxB,WAAW;QACbL,SAASqB,MAAM,CACbZ,iBACI;YAACa,SAAS,CAAC,cAAc,EAAEb,gBAAgB;YAAEc,QAAQ;QAAM,IAC3D;YACED,SAASpD;YACTsD,UAAU;YACVD,QAAQ;QACV;QAENK,eACE,CAAA,MAAMlD,kBAAkBsB,UAAU;YAChCW;YACAL,gBAAgB;YAChBG;YACAQ,MAAMZ,UAAUY,IAAI;YACpBF,OAAOD;QACT,EAAC,GACAY;QACH,IAAItB,YAAYyB,cAAcrD,iBAAiBwB,UAAU;YAACW;YAAOmB,KAAKxC,MAAMwC,GAAG;QAAA;IACjF,OAAO;;QACH,CAAA,EAACJ,WAAW,EAAEK,SAASJ,aAAa,EAAC,GAAG,MAAMK,yBAAyB5C,SAAS;YAChFwB;YACAZ;QACF,EAAC;IACH;IACA,4FAA4F;IAC5F,MAAMiC,qBAAqB7B,cAAc,CAAC,CAACwB,cAAcC;IAEzD,6EAA6E;IAC7E,kFAAkF;IAClF,IAAIxB,aAAa,CAACM,SAAS,CAACrB,MAAM4C,KAAK,EAAE;QACvClC,SAASqB,MAAM,CAAC;YACdc,UAAU7E,UAAU8E,WAAW;YAC/Bd,SAAS;YACTE,UAAU;YACVD,QAAQ;QACV;IACF;IAEA,oEAAoE;IACpE,MAAMc,UACJ,CAACzB,UAAUP,WAAWiC,OAAO,MAAMjF,iBAAiB8C,SAASE,UAAUiC,IAAI,IAAIC;IAEjF,0EAA0E;IAC1E,6EAA6E;IAC7E,IAAIC,gBAAgB7B;IACpB,IAAI8B,qBAAqB;IACzB,IAAIC;IACJ,IAAI,CAAC9B,UAAUP,aAAaI,kBAAkB,CAAC+B,eAAe;QAC5D,MAAMT,UAAU,MAAMvE,aAAa;YACjCqE;YACAc,MAAMtC,UAAUsC,IAAI;YACpBlC;YACAF;YACAU,MAAMZ,UAAUY,IAAI;YACpBF,OAAOD;YACP8B,YAAYvC,UAAUuC,UAAU;QAClC;QACAhB,eAAeG,QAAQL,WAAW;QAClCc,gBAAgBT,QAAQL,WAAW,CAACmB,EAAE;QACtCH,cAAcX,QAAQe,QAAQ;QAC9BL,qBAAqB;IACvB;IAEA,6EAA6E;IAC7E,uEAAuE;IACvE,IAAI;QACF,MAAMM,QAAQ,MAAMxE,WAAWyB,UAAU;YACvCkC,OAAO,IACL9D,YAAY;oBACVoE,eAAenC,YAAYmC,gBAAgBD;oBAC3CS,oBAAoB9B;oBACpB+B,kBAAkB;oBAClBhD;oBACAX;oBACA4D,QAAQ1D;oBACRU;oBACAC;gBACF;YACFgD,YAAYC,sBAAsB;gBAAClB,OAAO5C,MAAM4C,KAAK;gBAAErB;YAAgB;YACvEwC,gBAAgB;QAClB;QAEA,IAAIC,aAAaP,OAAOO;QACxB,yFAAyF;QACzF,IAAIA,eAAef,aAAa,CAAC1B,kBAAkB;YACjDyC,aAAa,MAAM3E,gBAAgB;gBAAC2B;gBAAgBN;gBAAUR;YAAS;QACzE;QAEA,MAAM+D,aAAalD,YAAYvB,iBAAiBkB,UAAUK,aAAa;QAEvE,MAAMmD,UAAyB;YAC7B7C,OAAOA,SAAS;YAChBO;YACA,GAAIT,iBAAiB;gBAACA;YAAc,IAAI,CAAC,CAAC;YAC1C,GAAIF,YAAY;gBAACA;YAAS,IAAI,CAAC,CAAC;YAChCR,MAAM;YACNoB;YACA,GAAGtD,mBAAmBwC,WAAW;gBAACkD;gBAAYxC,OAAOD;YAAQ,EAAE;QACjE;QAEA,iDAAiD;QACjD,IAAIF,QAAQ,OAAO;YAACc,aAAa;YAAM8B;QAAO;QAE9C,8EAA8E;QAC9E,+DAA+D;QAC/D,IAAI,CAACrC,SAAS;QAEd,MAAMsC,iBAAiB,MAAMC,mBAAmBtE,SAAS;YACvDoD,eAAenC,YAAYmC,gBAAgBD;YAC3CnC,YAAYS;QACd;QACA,0EAA0E;QAC1E,iFAAiF;QACjF,IAAIR,aAAaI,kBAAkB+B,eAAe;YAChD,IAAI,CAACc,YAAY,MAAM,IAAIK,MAAM;YACjC,MAAMlG,mBAAmB;gBACvBmG,QAAQC,SAASJ;gBACjB/C,KAAKT,UAAUS,GAAG;gBAClB8B;gBACAF,MAAMD;gBACNyB,OAAO;gBACP5C;gBACAd,YAAY6B;gBACZ8B,OAAO;gBACPT;gBACA,uEAAuE;gBACvE,cAAc;gBACdU,YAAY;oBACVtB,cAAcH;gBAChB;gBACAtB,MAAMZ,UAAUY,IAAI;gBACpBzB;gBACAuB,OAAOD;gBACPK;gBACAyB,YAAYvC,UAAUuC,UAAU;gBAChCqB,YAAYC,aAAaT;YAC3B;YACA,MAAM3B,MAAMpE,kBAAkB;gBAC5BmF,IAAIL;gBACJ/B;gBACAQ,MAAMZ,UAAUY,IAAI;gBACpBlB,MAAM;YACR;YACAoE,2BAA2B;gBAAC3B;gBAAevC;gBAAWC;gBAAQ4B;YAAG;YACjE,IAAIG,oBACFmC,gBAAgB;gBAACrB,OAAOzD,MAAM4C,KAAK;gBAAEzB;gBAAgBP;gBAAQV;YAAS;YACxE,OAAO;gBACL6E,QAAQ5B,qBAAqB,WAAW;gBACxCf,aAAaE,gBAAgB;gBAC7B4B;gBACA1B;YACF;QACF;QAEA,IAAI,CAACJ,aAAa;QAClB,MAAM4C,WAAW,MAAMC,qBAAqB;YAC1C7C;YACAR;YACAd;YACAhB;YACAqE;YACAtC;QACF;QAEA,OAAO;YACLkD,QAAQ1C,gBAAgB,WAAW;YACnCD;YACA8B;YACA1B,KAAKwC;QACP;IACF,EAAE,OAAOE,KAAK;QACZ,MAAM9B;QACN,MAAM8B;IACR;AACF;AAEA;;;CAGC,GACD,eAAexC,yBACb5C,OAAyB,EACzB,EAACwB,MAAM,EAAEZ,QAAQ,EAAmD;IAEpE,MAAM,EAACC,SAAS,EAAEX,KAAK,EAAEY,MAAM,EAAC,GAAGd;IACnC,MAAMgB,aAAa,CAAC,CAACd,MAAMG,QAAQ;IACnC,MAAMkB,QAAQ1C,SAASgC;IACvB,6EAA6E;IAC7E,MAAMc,QAAQzB,MAAMyB,KAAK,EAAEC,UAAUuB;IAErC,IAAI3B,QAAQ;QACV,MAAMlC,kBAAkBsB,UAAU;YAChCW;YACAP;YACAG,WAAWN,UAAUO,GAAG,EAAED;YAC1BkE,YAAYxE,UAAUwE,UAAU;YAChC1D;YACA2D,SAASpF,MAAMwC,GAAG;QACpB;QACA,OAAO;YAACJ,aAAa;YAAMK,SAAS;QAAK;IAC3C;IAEA,MAAMxB,YAAYN,UAAUO,GAAG,EAAED,aAAa;IAC9C,iFAAiF;IACjF,MAAM,EAACmB,WAAW,EAAEK,OAAO,EAAC,GAAG,MAAM9C,6BAA6B;QAChE0B;QACAP;QACAF;QACAK;QACAkE,YAAYxE,UAAUwE,UAAU;QAChC1D;QACA4D,YAAY,CAAC,CAACrF,MAAMsF,GAAG;QACvBF,SAASpF,MAAMwC,GAAG;IACpB;IAEA,IAAI,CAACJ,aAAa;QAChB,IAAItB,YAAY;YACdF,OAAO2E,GAAG,CAAC;YACX3E,OAAO2E,GAAG,CAAC;QACb,OAAO;YACL3E,OAAO2E,GAAG,CAAC;YACX3E,OAAO2E,GAAG,CAAC;YACX3E,OAAO2E,GAAG,CAAC;QACb;QAEA,MAAMC,aAAa,MAAMzG,4BAA4B;YACnDkC;YACAQ;YACAgE,SAAS3E,aAAa,aAAa;QACrC;QACAxB,YAAY,4BAA4BkG;QACxC,OAAO;YAACpD,aAAaoD;YAAY/C,SAAS;QAAI;IAChD;IAEAnD,YAAY,0BAA0B8C;IACtC,OAAO;QAACA;QAAaK;IAAO;AAC9B;AAEA,kFAAkF,GAClF,eAAe2B,mBACbtE,OAAyB,EACzB,EAACoD,aAAa,EAAEpC,UAAU,EAAgD;IAE1E,MAAM,EAACH,SAAS,EAAEX,KAAK,EAAEY,MAAM,EAAEX,WAAW,EAAEC,SAAS,EAAC,GAAGJ;IAE3D,IAAIqE,iBAAwC;IAC5C,IAAI;QACFA,iBAAiB,MAAMzE,gCACrB;YACEwD;YACAwC,YAAYzF,YAAY0F,IAAI;YAC5B7E;YACA8E,SAAS,GAAG1F,UAAU,OAAO,CAAC;YAC9Be,WAAWN,UAAUO,GAAG,EAAED,aAAa;YACvC4E,gBAAgB7F,KAAK,CAAC,kBAAkB;YACxC8F,SAAS9F,MAAM8F,OAAO;YACtBjF,SAASZ,YAAYK,SAAS;QAChC,GACAM;IAEJ,EAAE,OAAOmF,OAAO;QACdzG,YAAY,gDAAgDyG;QAC5D,IAAIA,iBAAiBjI,yBAAyBiI,MAAMC,UAAU,EAAEC,QAAQ;YACtErF,OAAOmF,KAAK,CAAClI,uBAAuBkI,MAAMC,UAAU,GAAG;gBAACE,MAAMlI,UAAUmI,aAAa;YAAA;QACvF;QACAvF,OAAOmF,KAAK,CAAC,CAAC,8CAA8C,EAAEA,OAAO,EAAE;YACrEG,MAAMlI,UAAUmI,aAAa;QAC/B;IACF;IAEA,IAAI,CAAChC,gBAAgB;QACnBvD,OAAOmF,KAAK,CAAC,gFAAgF;YAC3FG,MAAMlI,UAAUmI,aAAa;QAC/B;IACF;IAEA,OAAOhC;AACT;AAEA,eAAec,qBAAqB,EAClC7C,WAAW,EACXR,cAAc,EACdd,UAAU,EACVhB,OAAO,EACPqE,cAAc,EACdtC,OAAO,EAQR;IACC,MAAM,EAAClB,SAAS,EAAEC,MAAM,EAAEV,SAAS,EAAC,GAAGJ;IAEvC,IAAIsG;IACJ,IAAI,CAACtF,YAAY;QACfsF,UAAU3H,UAAU;YAAC4H,KAAK/I,QAAQ4C;QAAU,GAAG;YAAC7C,SAAS6C;SAAW,EAAEoG,IAAI,CAAC5I;IAC7E;IAEA,MAAM6I,OAAOtI,QAAQ6C,aAAa,uBAAuB,8BAA8B0F,KAAK;IAC5F,IAAIxB;IACJ,IAAI;;QACA,CAAA,EAACA,QAAQ,EAAC,GAAG,MAAMtG,iBAAiB;YACpCwE,eAAed,YAAYmB,EAAE;YAC7BiB,OAAO;YACP5C;YACA6E,UAAUtC;YACVlD,WAAWN,UAAUO,GAAG,EAAED;YAC1BmF;YACAvE;QACF,EAAC;IACH,EAAE,OAAOkE,OAAO;QACdQ,KAAKG,IAAI;QACT,MAAMX;IACR;IACAQ,KAAKI,OAAO;IAEZ,MAAMC,QAAQxE,YAAYX,KAAK,GAAG,CAAC,IAAI,EAAEW,YAAYX,KAAK,CAAC,CAAC,CAAC,GAAG;IAChEb,OAAO2E,GAAG,CACRzE,aACI,CAAC,4BAA4B,EAAE8F,OAAO,GACtC,CAAC,8BAA8B,EAAEnJ,UAAU,QAAQuH,YAAY4B,OAAO;IAG5E,IAAIjI,SAASgC,YAAY,OAAOqE;IAEhC,MAAM6B,UAAU,CAAC;;;;IAIf,EAAEpJ,UAAU,QAAQ,CAAC,QAAQ,EAAE2E,YAAYmB,EAAE,CAAC,CAAC,CAAC,EAAE;;;EAGpD,CAAC;IACD3C,OAAO2E,GAAG,CAAC,CAAC,MAAM,EAAE9H,UAAU,QAAQ,CAAC,QAAQ,EAAE2E,YAAYmB,EAAE,CAAC,CAAC,CAAC,GAAG;IACrE3C,OAAO2E,GAAG,CAAC,CAAC,+DAA+D,CAAC;IAC5E3E,OAAO2E,GAAG,CAAC,CAAC,qDAAqD,CAAC;IAClE3E,OAAO2E,GAAG,CAAC,CAAC,EAAE,EAAEsB,SAAS;IAEzB,OAAO7B;AACT;AAEA;;;CAGC,GACD,SAAST,SAASkC,QAA+B;IAC/C,MAAMK,cAAc,IAAIC,IACtB,AAACN,CAAAA,UAAU9B,cAAc,EAAE,AAAD,EAAGqC,GAAG,CAAC,CAACC,IAAM,GAAGA,EAAEhG,SAAS,CAAC,CAAC,EAAEgG,EAAEC,OAAO,EAAE;IAEvE,OAAO;WAAIJ;KAAY,CAACE,GAAG,CACzB,CAACG,aAAgB,CAAA;YAACA;YAAYC,cAAc;QAAS,CAAA;AAEzD;AAEA,SAASxC,aAAa6B,QAA+B;IACnD,OAAO,AAACA,CAAAA,UAAU9B,cAAc,EAAE,AAAD,EAAGqC,GAAG,CAAC,CAACK,YAAe,CAAA;YACtDC,UAAUD,UAAUC,QAAQ;YAC5BJ,SAASG,UAAUH,OAAO;YAC1BlE,MAAMqE,UAAUrE,IAAI;YACpBK,MAAMgE,UAAUhE,IAAI;YACpBpC,WAAWoG,UAAUpG,SAAS;YAC9BsG,oBAAoBF,UAAUE,kBAAkB;YAChDC,UAAUH,UAAUG,QAAQ;YAC5B/F,OAAO4F,UAAU5F,KAAK;QACxB,CAAA;AACF;AAEA,qGAAqG,GACrG,SAASoD,2BAA2B,EAClC3B,aAAa,EACbvC,SAAS,EACTC,MAAM,EACN4B,GAAG,EAMJ;IACC5B,OAAO2E,GAAG,CAAC,CAAC,8BAA8B,EAAE9H,UAAU,QAAQ+E,MAAM;IACpE,IAAI7D,SAASgC,YAAY;IAEzBC,OAAO2E,GAAG,CAAC,CAAC,MAAM,EAAE9H,UAAU,QAAQ,CAAC,QAAQ,EAAEyF,cAAc,CAAC,CAAC,GAAG;IACpEtC,OAAO2E,GAAG,CAAC,CAAC,+DAA+D,CAAC;IAC5E3E,OAAO2E,GAAG,CAAC,CAAC,qDAAqD,CAAC;AACpE;AAEA,6FAA6F,GAC7F,SAAST,gBAAgB,EACvBrB,KAAK,EACLtC,cAAc,EACdP,MAAM,EACNV,SAAS,EAMV;IACC,MAAMuH,MAAM,GAAGjK,SAASkK,QAAQrB,GAAG,IAAInG,cAAc,IAAI,CAAC,CAAC;IAC3DU,OAAO2E,GAAG,CAAC,CAAC;;WAEH,EAAEkC,IAAI;0CACyB,EAAEnJ,gBAAgB6C,gBAAgB;yCACnC,EAAEsC,QAAQ,CAAC,wBAAwB,EAAEgE,IAAI,kEAAkE,CAAC,GAAG,IAAI;AAC5J;AAEA,SAAS3D,sBAAsB,EAC7BlB,KAAK,EACLrB,gBAAgB,EAIjB;IACC,IAAIA,kBAAkB,OAAO;IAC7B,IAAI,CAACqB,OAAO,OAAO;IACnB;AACF;AAEA;;;CAGC,GACD,eAAeT,kBAAkBwF,cAAsB;IACrD,IAAI;QACF,MAAMC,gBAAgBjK,kBAAkBgK;QACxC,IAAI,CAACC,eAAe,OAAO;QAE3B,MAAMC,iBAAiB,MAAMjK,cAAc;YACzC+H,MAAMiC;QACR;QAEA,MAAME,4BAA4BD,eAAeE,SAAS,CAACC,IAAI,CAAC,CAACC;YAC/D,IAAIA,EAAExH,IAAI,KAAK,mBAAmB,UAAUwH,KAAK,OAAOA,EAAEC,IAAI,KAAK,UAAU;gBAC3E,OAAO1K,SAASD,KAAKD,QAAQsK,gBAAgBK,EAAEC,IAAI,GAAGP,oBAAoB;YAC5E;YAEA,OAAO;QACT;QAEA,OAAOG;IACT,EAAE,OAAM;QACN,OAAO,MAAM,YAAY;;IAC3B;AACF"}
1
+ {"version":3,"sources":["../../../src/actions/deploy/deployStudio.ts"],"sourcesContent":["import {basename, dirname, relative} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip, type Gzip} from 'node:zlib'\n\nimport {formatSchemaValidation, SchemaExtractionError} from '@sanity/cli-build/_internal/extract'\nimport {readIconFromPath} from '@sanity/cli-build/_internal/manifest'\nimport {exitCodes} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {\n type BrettAccess,\n type BrettWorkspace,\n createStudio,\n deployWorkbenchApp,\n getApplicationUrl,\n getWorkbench,\n getWorkbenchUrl,\n toWorkbenchPayload,\n} from '@sanity/workbench-cli/deploy'\nimport {type StudioManifest} from 'sanity'\nimport {c as createTar} from 'tar'\n\nimport {createDeployment, type UserApplication} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {NO_ORGANIZATION_ID, NO_PROJECT_ID} from '../../util/errorMessages.js'\nimport {buildStudio} from '../build/buildStudio.js'\nimport {checkBlueprintManaged} from './blueprintManaged.js'\nimport {createStudioUserApplication} from './createUserApplication.js'\nimport {\n checkAutoUpdates,\n checkBuild,\n checkExternalUrl,\n checkPackageVersion,\n checkStudioTarget,\n type DeployCheckReporter,\n verifyOutputDir,\n} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {listDeploymentFiles, reportInterfaces} from './deploymentPlan.js'\nimport {type DeployPayload, type DeployResult, runDeploy} from './deployRunner.js'\nimport {deployStudioSchemasAndManifests} from './deployStudioSchemasAndManifests.js'\nimport {findUserApplicationForStudio} from './findUserApplication.js'\nimport {type DeployAppOptions} from './types.js'\n\nconst STUDIO_PACKAGE = 'sanity'\n\nexport function deployStudio(options: DeployAppOptions): Promise<void> {\n return runDeploy(options, {\n listFiles: ({flags, projectRoot, sourceDir}) =>\n flags.external ? Promise.resolve([]) : listDeploymentFiles(sourceDir, projectRoot.directory),\n run: runStudioDeployment,\n type: 'studio',\n })\n}\n\n/** Validates the deploy, extracts and uploads the schema, and ships the build. */\nasync function runStudioDeployment(\n options: DeployAppOptions,\n reporter: DeployCheckReporter,\n): Promise<DeployResult | void> {\n const {cliConfig, flags, output, sourceDir} = options\n const workDir = options.projectRoot.directory\n const isExternal = !!flags.external\n const workbench = getWorkbench(cliConfig)\n const isWorkbenchApp = workbench !== null\n const projectId = cliConfig.api?.projectId\n const organizationId = cliConfig.app?.organizationId\n const appId = getAppId(cliConfig)\n const dryRun = !!flags['dry-run']\n // A legacy external studio only registers its URL; a federated one is built\n // and deployed like a hosted one, minus the upload.\n const isLegacyExternal = isExternal && !isWorkbenchApp\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.slug\n : ''\n\n const isAutoUpdating = checkAutoUpdates(reporter, {cliConfig, flags})\n\n const version = await checkPackageVersion(reporter, {\n moduleName: STUDIO_PACKAGE,\n workDir,\n })\n\n reporter.report(\n projectId\n ? {message: `Project: ${projectId}`, status: 'pass'}\n : {\n message: NO_PROJECT_ID,\n solution: 'Add `api.projectId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n\n await checkBlueprintManaged(reporter, {kind: 'studio', projectRootDir: workDir})\n\n // Workbench studios deploy to Brett (which needs the org); plain studios\n // resolve/create on user-applications, unchanged.\n let application: UserApplication | null = null\n let studioCreated = false\n let workbenchApp: {externalUrl?: string} | undefined\n let externalUrl: string | undefined\n if (workbench) {\n reporter.report(\n organizationId\n ? {message: `Organization: ${organizationId}`, status: 'pass'}\n : {\n message: NO_ORGANIZATION_ID,\n solution: 'Add `app.organizationId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n workbenchApp = (\n await checkStudioTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n organizationId,\n slug: workbench.slug,\n title: appTitle,\n })\n )?.application\n if (isExternal) externalUrl = checkExternalUrl(reporter, {appId, url: flags.url})\n } else {\n ;({application, created: studioCreated} = await resolveStudioApplication(options, {\n dryRun,\n reporter,\n }))\n }\n // A redeploy follows how the application was registered, so --external is only needed once.\n const isExternallyHosted = isExternal || !!workbenchApp?.externalUrl\n\n // A first deploy mints the app id and the build inlines it; --no-build would\n // ship an existing bundle carrying a different id, so it can't be a first deploy.\n if (workbench && !appId && !flags.build) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'A first deploy cannot skip the build (--no-build)',\n solution: 'Drop --no-build so the new application id is inlined into the build',\n status: 'fail',\n })\n }\n\n // Read up front so a bad icon path fails before we create or build.\n const appIcon =\n !dryRun && workbench?.icon ? await readIconFromPath(workDir, workbench.icon) : undefined\n\n // Create the studio before the build so the bundle carries its real id. A\n // redeploy already has it from `deployment.appId`; a dry run skips creation.\n let applicationId = appId\n let applicationCreated = false\n let rollbackApp: (() => Promise<void>) | undefined\n if (!dryRun && workbench && organizationId && !applicationId) {\n const created = await createStudio({\n externalUrl,\n name: workbench.name,\n organizationId,\n projectId,\n slug: workbench.slug,\n title: appTitle,\n visibility: workbench.visibility,\n })\n workbenchApp = created.application\n applicationId = created.application.id\n rollbackApp = created.rollback\n applicationCreated = true\n }\n\n // A record created above is stranded at its slug (and blocks retries) if any\n // step before it fully deploys fails, so undo the creation on failure.\n try {\n const built = await checkBuild(reporter, {\n build: () =>\n buildStudio({\n applicationId: workbench ? applicationId : undefined,\n autoUpdatesEnabled: isAutoUpdating,\n calledFromDeploy: true,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n }),\n skipReason: studioBuildSkipReason({build: flags.build, isLegacyExternal}),\n successMessage: 'Studio built',\n })\n\n let mfManifest = built?.mfManifest\n // A federated build has already read its manifest; anything else verifies the directory.\n if (mfManifest === undefined && !isLegacyExternal) {\n mfManifest = await verifyOutputDir({isWorkbenchApp, reporter, sourceDir})\n }\n\n const interfaces = workbench ? reportInterfaces(reporter, workbench) : null\n\n const payload: DeployPayload = {\n appId: appId ?? null,\n isAutoUpdating,\n ...(organizationId ? {organizationId} : {}),\n ...(projectId ? {projectId} : {}),\n type: 'studio',\n version,\n ...toWorkbenchPayload(workbench, {interfaces, title: appTitle}),\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return {application: null, payload}\n\n // A real deploy has already exited if anything failed; landing here without a\n // resolved version means the deploy target was never resolved.\n if (!version) return\n\n const studioManifest = await uploadStudioSchema(options, {\n applicationId: workbench ? applicationId : undefined,\n isExternal: isLegacyExternal,\n })\n // The studio was created (or resolved from `deployment.appId`) before the\n // build, so this only ships the deployment; plain studios use user-applications.\n if (workbench && organizationId && applicationId) {\n if (!mfManifest) throw new Error('The federated build produced no manifest.')\n await deployWorkbenchApp({\n access: toAccess(studioManifest),\n app: cliConfig.app,\n applicationId,\n icon: appIcon,\n isApp: false,\n isAutoUpdating,\n isExternal: isExternallyHosted,\n label: 'Deploying studio',\n mfManifest,\n // Once the deployment is live, a metadata-sync failure must not delete\n // the studio.\n onDeployed: () => {\n rollbackApp = undefined\n },\n slug: workbench.slug,\n sourceDir,\n title: appTitle,\n version,\n visibility: workbench.visibility,\n workspaces: toWorkspaces(studioManifest),\n })\n const url = getApplicationUrl({\n id: applicationId,\n organizationId,\n slug: workbench.slug,\n type: 'studio',\n })\n logWorkbenchStudioDeployed({applicationId, cliConfig, output, url})\n if (isExternallyHosted)\n logExternalHost({built: flags.build, organizationId, output, sourceDir})\n return {\n action: applicationCreated ? 'create' : 'update',\n application: workbenchApp ?? null,\n payload,\n url,\n }\n }\n\n if (!application) return\n const location = await shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n })\n\n return {\n action: studioCreated ? 'create' : 'update',\n application,\n payload,\n url: location,\n }\n } catch (err) {\n await rollbackApp?.()\n throw err\n }\n}\n\n/**\n * Finds the application a real deploy targets, registering a studio host when\n * none is configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveStudioApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplication | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const isExternal = !!flags.external\n const appId = getAppId(cliConfig)\n // Sets the title on a newly registered studio; blank falls back to undefined\n const title = flags.title?.trim() || undefined\n\n if (dryRun) {\n await checkStudioTarget(reporter, {\n appId,\n isExternal,\n projectId: cliConfig.api?.projectId,\n studioHost: cliConfig.studioHost,\n title,\n urlFlag: flags.url,\n })\n return {application: null, created: false}\n }\n\n const projectId = cliConfig.api?.projectId ?? ''\n // `created` is true when a configured-but-unregistered host was just registered.\n const {application, created} = await findUserApplicationForStudio({\n appId,\n isExternal,\n output,\n projectId,\n studioHost: cliConfig.studioHost,\n title,\n unattended: !!flags.yes,\n urlFlag: flags.url,\n })\n\n if (!application) {\n if (isExternal) {\n output.log('Your project has not been registered with an external studio URL.')\n output.log('Please enter the full URL where your studio is hosted.')\n } else {\n output.log('Your project has not been assigned a studio hostname.')\n output.log('To deploy your Sanity Studio to our hosted sanity.studio service,')\n output.log('you will need one. Please enter the subdomain you want to use.')\n }\n\n const registered = await createStudioUserApplication({\n projectId,\n title,\n urlType: isExternal ? 'external' : 'internal',\n })\n deployDebug('Created user application', registered)\n return {application: registered, created: true}\n }\n\n deployDebug('Found user application', application)\n return {application, created}\n}\n\n/** Extracts the studio schema and manifest and uploads them to the schema store. */\nasync function uploadStudioSchema(\n options: DeployAppOptions,\n {applicationId, isExternal}: {applicationId?: string; isExternal: boolean},\n): Promise<StudioManifest | null> {\n const {cliConfig, flags, output, projectRoot, sourceDir} = options\n\n let studioManifest: StudioManifest | null = null\n try {\n studioManifest = await deployStudioSchemasAndManifests(\n {\n applicationId,\n configPath: projectRoot.path,\n isExternal,\n outPath: `${sourceDir}/static`,\n projectId: cliConfig.api?.projectId ?? '',\n schemaRequired: flags['schema-required'],\n verbose: flags.verbose,\n workDir: projectRoot.directory,\n },\n output,\n )\n } catch (error) {\n deployDebug('Error deploying studio schemas and manifests', error)\n if (error instanceof SchemaExtractionError && error.validation?.length) {\n output.error(formatSchemaValidation(error.validation), {exit: exitCodes.RUNTIME_ERROR})\n }\n output.error(`Error deploying studio schemas and manifests: ${error}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (!studioManifest) {\n output.error('Failed to generate studio manifest. Please check your schemas and manifests.', {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n return studioManifest\n}\n\nasync function shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n isExternal: boolean\n options: DeployAppOptions\n studioManifest: StudioManifest | null\n version: string\n}): Promise<string> {\n const {cliConfig, output, sourceDir} = options\n\n let tarball: Gzip | undefined\n if (!isExternal) {\n tarball = createTar({cwd: dirname(sourceDir)}, [basename(sourceDir)]).pipe(createGzip())\n }\n\n const spin = spinner(isExternal ? 'Registering studio' : 'Deploying to sanity.studio').start()\n let location: string\n try {\n ;({location} = await createDeployment({\n applicationId: application.id,\n isApp: false,\n isAutoUpdating,\n manifest: studioManifest,\n projectId: cliConfig.api?.projectId,\n tarball,\n version,\n }))\n } catch (error) {\n spin.fail()\n throw error\n }\n spin.succeed()\n\n const named = application.title ? ` — \"${application.title}\"` : ''\n output.log(\n isExternal\n ? `\\nSuccess! Studio registered${named}`\n : `\\nSuccess! Studio deployed to ${styleText('cyan', location)}${named}`,\n )\n\n if (getAppId(cliConfig)) return location\n\n const example = `Example:\nexport default defineCliConfig({\n //…\n deployment: {\n ${styleText('cyan', `appId: '${application.id}'`)},\n },\n //…\n})`\n output.log(`\\nAdd ${styleText('cyan', `appId: '${application.id}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n output.log(`\\n${example}`)\n\n return location\n}\n\n/**\n * One `datasets` access entry per unique workspace dataset, with a `resourceId`\n * of `\"<projectId>.<dataset>\"`. Deduped, since workspaces can share a dataset.\n */\nfunction toAccess(manifest: StudioManifest | null): BrettAccess[] {\n const resourceIds = new Set(\n (manifest?.workspaces ?? []).map((w) => `${w.projectId}.${w.dataset}`),\n )\n return [...resourceIds].map(\n (resourceId) => ({resourceId, resourceType: 'dataset'}) satisfies BrettAccess,\n )\n}\n\nfunction toWorkspaces(manifest: StudioManifest | null): BrettWorkspace[] {\n return (manifest?.workspaces ?? []).map((workspace) => ({\n basePath: workspace.basePath,\n dataset: workspace.dataset,\n icon: workspace.icon,\n name: workspace.name,\n projectId: workspace.projectId,\n schemaDescriptorId: workspace.schemaDescriptorId,\n subtitle: workspace.subtitle,\n title: workspace.title,\n }))\n}\n\n/** Renders the workbench studio's deploy result; the appId hint shows only when none is configured. */\nfunction logWorkbenchStudioDeployed({\n applicationId,\n cliConfig,\n output,\n url,\n}: {\n applicationId: string\n cliConfig: DeployAppOptions['cliConfig']\n output: DeployAppOptions['output']\n url: string\n}): void {\n output.log(`\\nSuccess! Studio deployed to ${styleText('cyan', url)}`)\n if (getAppId(cliConfig)) return\n\n output.log(`\\nAdd ${styleText('cyan', `appId: '${applicationId}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n}\n\n/** Tells the customer what their host must do for the Dashboard to load the studio from it. */\nfunction logExternalHost({\n built,\n organizationId,\n output,\n sourceDir,\n}: {\n built: boolean\n organizationId: string\n output: DeployAppOptions['output']\n sourceDir: string\n}): void {\n const dir = `${relative(process.cwd(), sourceDir) || '.'}/`\n output.log(`\nThe Dashboard loads this studio from your host, which must:\n 1. Serve ${dir} unchanged at the root of its URL (/mf-manifest.json, /remoteEntry-*.js, /static/*)\n 2. Send Access-Control-Allow-Origin for ${getWorkbenchUrl(organizationId)}\n 3. Respond without cookies or a sign-in${built ? `\\n\\nThis deploy rebuilt ${dir}: copy it to your host before opening the studio in the Dashboard.` : ''}`)\n}\n\nfunction studioBuildSkipReason({\n build,\n isLegacyExternal,\n}: {\n build: boolean\n isLegacyExternal: boolean\n}) {\n if (isLegacyExternal) return 'Build skipped for externally hosted studios'\n if (!build) return 'Build skipped (--no-build) — validating existing output directory'\n return\n}\n"],"names":["basename","dirname","relative","styleText","createGzip","formatSchemaValidation","SchemaExtractionError","readIconFromPath","exitCodes","spinner","createStudio","deployWorkbenchApp","getApplicationUrl","getWorkbench","getWorkbenchUrl","toWorkbenchPayload","c","createTar","createDeployment","getAppId","NO_ORGANIZATION_ID","NO_PROJECT_ID","buildStudio","checkBlueprintManaged","createStudioUserApplication","checkAutoUpdates","checkBuild","checkExternalUrl","checkPackageVersion","checkStudioTarget","verifyOutputDir","deployDebug","listDeploymentFiles","reportInterfaces","runDeploy","deployStudioSchemasAndManifests","findUserApplicationForStudio","STUDIO_PACKAGE","deployStudio","options","listFiles","flags","projectRoot","sourceDir","external","Promise","resolve","directory","run","runStudioDeployment","type","reporter","cliConfig","output","workDir","isExternal","workbench","isWorkbenchApp","projectId","api","organizationId","app","appId","dryRun","isLegacyExternal","appTitle","title","trim","slug","isAutoUpdating","version","moduleName","report","message","status","solution","kind","projectRootDir","application","studioCreated","workbenchApp","externalUrl","url","created","resolveStudioApplication","isExternallyHosted","build","exitCode","USAGE_ERROR","appIcon","icon","undefined","applicationId","applicationCreated","rollbackApp","name","visibility","id","rollback","built","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","studioBuildSkipReason","successMessage","mfManifest","interfaces","payload","studioManifest","uploadStudioSchema","Error","access","toAccess","isApp","label","onDeployed","workspaces","toWorkspaces","logWorkbenchStudioDeployed","logExternalHost","action","location","shipStudioDeployment","err","studioHost","urlFlag","unattended","yes","log","registered","urlType","configPath","path","outPath","schemaRequired","verbose","error","validation","length","exit","RUNTIME_ERROR","tarball","cwd","pipe","spin","start","manifest","fail","succeed","named","example","resourceIds","Set","map","w","dataset","resourceId","resourceType","workspace","basePath","schemaDescriptorId","subtitle","dir","process"],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+ import { extname } from 'node:path';
2
+ import { doImport } from '@sanity/cli-core';
1
3
  import { runnerImport } from 'vite';
2
4
  const scriptPath = process.argv[2];
3
5
  const scriptArguments = process.argv.slice(3);
@@ -10,12 +12,14 @@ process.argv = [
10
12
  scriptPath,
11
13
  ...scriptArguments
12
14
  ];
13
- await runnerImport(scriptPath, {
15
+ // Vite's module runner evaluates modules as ESM, which makes `require` calls in CommonJS scripts
16
+ // fail with ERR_AMBIGUOUS_MODULE_SYNTAX. Node loads `.cjs` files natively.
17
+ await (extname(scriptPath) === '.cjs' ? doImport(scriptPath) : runnerImport(scriptPath, {
14
18
  logLevel: 'error',
15
19
  resolve: {
16
20
  tsconfigPaths: true
17
21
  },
18
22
  root: process.env.SANITY_BASE_PATH || process.cwd()
19
- });
23
+ }));
20
24
 
21
25
  //# sourceMappingURL=runScript.worker.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/exec/runScript.worker.ts"],"sourcesContent":["import {runnerImport} from 'vite'\n\nconst scriptPath = process.argv[2]\nconst scriptArguments = process.argv.slice(3)\n\nif (!scriptPath) {\n throw new Error('No script path provided')\n}\n\n// Make process.argv match direct Node script execution rather than exposing this worker.\nprocess.argv = [process.argv[0], scriptPath, ...scriptArguments]\n\nawait runnerImport(scriptPath, {\n logLevel: 'error',\n resolve: {tsconfigPaths: true},\n root: process.env.SANITY_BASE_PATH || process.cwd(),\n})\n"],"names":["runnerImport","scriptPath","process","argv","scriptArguments","slice","Error","logLevel","resolve","tsconfigPaths","root","env","SANITY_BASE_PATH","cwd"],"mappings":"AAAA,SAAQA,YAAY,QAAO,OAAM;AAEjC,MAAMC,aAAaC,QAAQC,IAAI,CAAC,EAAE;AAClC,MAAMC,kBAAkBF,QAAQC,IAAI,CAACE,KAAK,CAAC;AAE3C,IAAI,CAACJ,YAAY;IACf,MAAM,IAAIK,MAAM;AAClB;AAEA,yFAAyF;AACzFJ,QAAQC,IAAI,GAAG;IAACD,QAAQC,IAAI,CAAC,EAAE;IAAEF;OAAeG;CAAgB;AAEhE,MAAMJ,aAAaC,YAAY;IAC7BM,UAAU;IACVC,SAAS;QAACC,eAAe;IAAI;IAC7BC,MAAMR,QAAQS,GAAG,CAACC,gBAAgB,IAAIV,QAAQW,GAAG;AACnD"}
1
+ {"version":3,"sources":["../../../src/actions/exec/runScript.worker.ts"],"sourcesContent":["import {extname} from 'node:path'\n\nimport {doImport} from '@sanity/cli-core'\nimport {runnerImport} from 'vite'\n\nconst scriptPath = process.argv[2]\nconst scriptArguments = process.argv.slice(3)\n\nif (!scriptPath) {\n throw new Error('No script path provided')\n}\n\n// Make process.argv match direct Node script execution rather than exposing this worker.\nprocess.argv = [process.argv[0], scriptPath, ...scriptArguments]\n\n// Vite's module runner evaluates modules as ESM, which makes `require` calls in CommonJS scripts\n// fail with ERR_AMBIGUOUS_MODULE_SYNTAX. Node loads `.cjs` files natively.\nawait (extname(scriptPath) === '.cjs'\n ? doImport(scriptPath)\n : runnerImport(scriptPath, {\n logLevel: 'error',\n resolve: {tsconfigPaths: true},\n root: process.env.SANITY_BASE_PATH || process.cwd(),\n }))\n"],"names":["extname","doImport","runnerImport","scriptPath","process","argv","scriptArguments","slice","Error","logLevel","resolve","tsconfigPaths","root","env","SANITY_BASE_PATH","cwd"],"mappings":"AAAA,SAAQA,OAAO,QAAO,YAAW;AAEjC,SAAQC,QAAQ,QAAO,mBAAkB;AACzC,SAAQC,YAAY,QAAO,OAAM;AAEjC,MAAMC,aAAaC,QAAQC,IAAI,CAAC,EAAE;AAClC,MAAMC,kBAAkBF,QAAQC,IAAI,CAACE,KAAK,CAAC;AAE3C,IAAI,CAACJ,YAAY;IACf,MAAM,IAAIK,MAAM;AAClB;AAEA,yFAAyF;AACzFJ,QAAQC,IAAI,GAAG;IAACD,QAAQC,IAAI,CAAC,EAAE;IAAEF;OAAeG;CAAgB;AAEhE,iGAAiG;AACjG,2EAA2E;AAC3E,MAAON,CAAAA,QAAQG,gBAAgB,SAC3BF,SAASE,cACTD,aAAaC,YAAY;IACvBM,UAAU;IACVC,SAAS;QAACC,eAAe;IAAI;IAC7BC,MAAMR,QAAQS,GAAG,CAACC,gBAAgB,IAAIV,QAAQW,GAAG;AACnD,EAAC"}
@@ -9,9 +9,11 @@ import { copy } from '../../util/copy.js';
9
9
  import { resolveLatestVersions } from '../../util/resolveLatestVersions.js';
10
10
  import { createAppCliConfig } from './createAppCliConfig.js';
11
11
  import { createCliConfig } from './createCliConfig.js';
12
+ import { createMediaLibraryCliConfig } from './createMediaLibraryCliConfig.js';
12
13
  import { createPackageManifest } from './createPackageManifest.js';
13
14
  import { createStudioConfig } from './createStudioConfig.js';
14
15
  import { determineAppTemplate } from './determineAppTemplate.js';
16
+ import { determineMediaLibraryTemplate } from './determineMediaLibraryTemplate.js';
15
17
  import { processTemplate } from './processTemplate.js';
16
18
  import { sdkAppDependencies } from './sdkAppDependencies.js';
17
19
  import { studioDependencies } from './studioDependencies.js';
@@ -26,6 +28,13 @@ export async function bootstrapLocalTemplate(opts) {
26
28
  const sourceDir = path.join(templatesDir, templateName);
27
29
  const sharedDir = path.join(templatesDir, 'shared');
28
30
  const isAppTemplate = determineAppTemplate(templateName);
31
+ const isMediaLibraryTemplate = determineMediaLibraryTemplate(templateName);
32
+ // Media Library config apps bring their own dependency set: neither the
33
+ // SDK-app base nor the studio base applies (see templates/mediaLibraryConfig.ts).
34
+ const baseDependencies = isAppTemplate ? sdkAppDependencies : isMediaLibraryTemplate ? {
35
+ dependencies: {},
36
+ devDependencies: {}
37
+ } : studioDependencies;
29
38
  // Check that we have a template info file (dependencies, plugins etc)
30
39
  const template = templates[templateName];
31
40
  if (!template) {
@@ -38,6 +47,13 @@ export async function bootstrapLocalTemplate(opts) {
38
47
  await copy(sourceDir, outputPath, {
39
48
  rename: useTypeScript ? toTypeScriptPath : undefined
40
49
  });
50
+ // The Media Library template ships its own eslint config (a
51
+ // restricted-imports override for field modules), stored as .txt — same
52
+ // trick as shared/gitignore.txt — so the repo's own ESLint doesn't pick it
53
+ // up as the nearest config for the template files.
54
+ if (isMediaLibraryTemplate) {
55
+ await fs.rename(path.join(outputPath, 'eslint.config.txt'), path.join(outputPath, 'eslint.config.mjs'));
56
+ }
41
57
  debug(`Copying shared template code from : ${sharedDir}`);
42
58
  await copy(path.join(sharedDir, 'gitignore.txt'), outputPath, {
43
59
  rename: ()=>'.gitignore'
@@ -67,8 +83,8 @@ export async function bootstrapLocalTemplate(opts) {
67
83
  // Resolve latest versions of Sanity-dependencies
68
84
  spin = spinner('Resolving latest module versions').start();
69
85
  const dependencyVersions = await resolveLatestVersions({
70
- ...isAppTemplate ? sdkAppDependencies.dependencies : studioDependencies.dependencies,
71
- ...isAppTemplate ? sdkAppDependencies.devDependencies : studioDependencies.devDependencies,
86
+ ...baseDependencies.dependencies,
87
+ ...baseDependencies.devDependencies,
72
88
  ...template.dependencies,
73
89
  ...template.devDependencies
74
90
  });
@@ -76,14 +92,14 @@ export async function bootstrapLocalTemplate(opts) {
76
92
  // Use the resolved version for the given dependency
77
93
  const dependencies = {};
78
94
  for (const dependency of Object.keys({
79
- ...isAppTemplate ? sdkAppDependencies.dependencies : studioDependencies.dependencies,
95
+ ...baseDependencies.dependencies,
80
96
  ...template.dependencies
81
97
  })){
82
98
  dependencies[dependency] = dependencyVersions[dependency];
83
99
  }
84
100
  const devDependencies = {};
85
101
  for (const dependency of Object.keys({
86
- ...isAppTemplate ? sdkAppDependencies.devDependencies : studioDependencies.devDependencies,
102
+ ...baseDependencies.devDependencies,
87
103
  ...template.devDependencies
88
104
  })){
89
105
  devDependencies[dependency] = dependencyVersions[dependency];
@@ -91,7 +107,7 @@ export async function bootstrapLocalTemplate(opts) {
91
107
  let packageJsonName = packageName;
92
108
  /**
93
109
  * Currently app init doesn't ask for a name, so we use the last part of the path
94
- */ if (isAppTemplate) {
110
+ */ if (isAppTemplate || isMediaLibraryTemplate) {
95
111
  packageJsonName = slugify(path.basename(outputPath));
96
112
  }
97
113
  const title = variables.projectName || packageJsonName;
@@ -108,18 +124,24 @@ export async function bootstrapLocalTemplate(opts) {
108
124
  const packageManifest = createPackageManifest({
109
125
  dependencies,
110
126
  devDependencies,
111
- isAppTemplate,
127
+ // Media Library config apps also skip the opinionated prettier config.
128
+ isAppTemplate: isAppTemplate || isMediaLibraryTemplate,
112
129
  name: packageJsonName,
113
130
  scripts: template.scripts,
114
131
  type: template.type
115
132
  });
116
- // ...and a studio config (`sanity.config.[ts|js]`)
117
- const studioConfig = createStudioConfig({
133
+ // ...and a studio config (`sanity.config.[ts|js]`) — only for studio
134
+ // templates. App and media-library scaffolds don't write one, and building
135
+ // it anyway would demand studio variables (projectId) they don't carry.
136
+ const studioConfig = isAppTemplate || isMediaLibraryTemplate ? null : createStudioConfig({
118
137
  template: template.configTemplate,
119
138
  variables
120
139
  });
121
140
  // ...and a CLI config (`sanity.cli.[ts|js]`)
122
- const cliConfig = isAppTemplate ? createAppCliConfig({
141
+ // oxlint-disable-next-line no-nested-ternary -- three scaffold shapes share one write path
142
+ const cliConfig = isMediaLibraryTemplate ? createMediaLibraryCliConfig({
143
+ organizationId: variables.organizationId
144
+ }) : isAppTemplate ? createAppCliConfig({
123
145
  entry: template.entry,
124
146
  isWorkbenchApp: variables.workbench,
125
147
  organizationId: variables.organizationId,
@@ -137,10 +159,12 @@ export async function bootstrapLocalTemplate(opts) {
137
159
  // Write non-template files to disc
138
160
  const codeExt = useTypeScript ? 'ts' : 'js';
139
161
  await Promise.all([
140
- isAppTemplate ? Promise.resolve(null) : writeFileIfNotExists(`sanity.config.${codeExt}`, studioConfig),
162
+ studioConfig === null ? Promise.resolve(null) : writeFileIfNotExists(`sanity.config.${codeExt}`, studioConfig),
141
163
  writeFileIfNotExists(`sanity.cli.${codeExt}`, cliConfig),
142
164
  writeFileIfNotExists('package.json', packageManifest),
143
- writeFileIfNotExists('eslint.config.mjs', `import studio from '@sanity/eslint-config-studio'\n\nexport default [...studio]\n`)
165
+ // The Media Library template ships its own eslint.config.mjs (a
166
+ // restricted-imports override for field modules) in the copied files.
167
+ isMediaLibraryTemplate ? Promise.resolve(null) : writeFileIfNotExists('eslint.config.mjs', `import studio from '@sanity/eslint-config-studio'\n\nexport default [...studio]\n`)
144
168
  ].filter(Boolean));
145
169
  debug('Updating initial template metadata');
146
170
  if (variables.projectId) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/init/bootstrapLocalTemplate.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Output, subdebug} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {toAppSlug} from '@sanity/workbench-cli/init'\nimport deburr from 'lodash-es/deburr.js'\n\nimport {copy} from '../../util/copy.js'\nimport {resolveLatestVersions} from '../../util/resolveLatestVersions.js'\nimport {createAppCliConfig} from './createAppCliConfig.js'\nimport {createCliConfig} from './createCliConfig.js'\nimport {createPackageManifest} from './createPackageManifest.js'\nimport {createStudioConfig, type GenerateConfigOptions} from './createStudioConfig.js'\nimport {determineAppTemplate} from './determineAppTemplate.js'\nimport {processTemplate} from './processTemplate.js'\nimport {sdkAppDependencies} from './sdkAppDependencies.js'\nimport {studioDependencies} from './studioDependencies.js'\nimport templates from './templates/index.js'\nimport {type ProjectTemplate} from './types.js'\nimport {updateInitialTemplateMetadata} from './updateInitialTemplateMetadata.js'\n\nconst debug = subdebug('init:bootstrapRemoteTemplate')\n\ninterface BootstrapLocalOptions {\n output: Output\n outputPath: string\n packageName: string\n templateName: string\n useTypeScript: boolean\n variables: GenerateConfigOptions['variables']\n\n overwriteFiles?: boolean\n}\n\nexport async function bootstrapLocalTemplate(\n opts: BootstrapLocalOptions,\n): Promise<ProjectTemplate> {\n const {output, outputPath, packageName, templateName, useTypeScript, variables} = opts\n // packages/@sanity/cli/src/actions/init/ -> packages/@sanity/cli/src/action -> packages/@sanity/cli/src/\n const cliRoot = path.resolve(import.meta.dirname, '../../..')\n const templatesDir = path.join(cliRoot, 'templates')\n const sourceDir = path.join(templatesDir, templateName)\n const sharedDir = path.join(templatesDir, 'shared')\n const isAppTemplate = determineAppTemplate(templateName)\n\n // Check that we have a template info file (dependencies, plugins etc)\n const template = templates[templateName]\n if (!template) {\n throw new Error(`Template \"${templateName}\" not defined`)\n }\n\n // Copy template files\n debug('Copying files from template \"%s\" to \"%s\"', templateName, outputPath)\n let spin = spinner('Bootstrapping files from template').start()\n\n debug(`Copying template from : ${sourceDir}`)\n await copy(sourceDir, outputPath, {\n rename: useTypeScript ? toTypeScriptPath : undefined,\n })\n debug(`Copying shared template code from : ${sharedDir}`)\n await copy(path.join(sharedDir, 'gitignore.txt'), outputPath, {rename: () => '.gitignore'})\n // Dashboard apps dev and deploy differently, so their docs replace the\n // template's. Studio templates have no overlay.\n if (isAppTemplate && variables.workbench) {\n await copy(path.join(sharedDir, 'dashboard', templateName), outputPath)\n }\n\n if (useTypeScript) {\n await fs.copyFile(path.join(sharedDir, 'tsconfig.json'), path.join(outputPath, 'tsconfig.json'))\n }\n\n spin.succeed()\n\n if (isAppTemplate) {\n const appEntryPath = path.join(outputPath, 'src', 'App.tsx')\n const raw = await fs.readFile(appEntryPath, 'utf8')\n const rendered = processTemplate({\n template: raw,\n variables: {\n dataset: variables.dataset ?? '',\n projectId: variables.projectId ?? '',\n },\n })\n await fs.writeFile(appEntryPath, rendered)\n }\n\n // Merge global and template-specific plugins and dependencies\n\n // Resolve latest versions of Sanity-dependencies\n spin = spinner('Resolving latest module versions').start()\n const dependencyVersions = await resolveLatestVersions({\n ...(isAppTemplate ? sdkAppDependencies.dependencies : studioDependencies.dependencies),\n ...(isAppTemplate ? sdkAppDependencies.devDependencies : studioDependencies.devDependencies),\n ...template.dependencies,\n ...template.devDependencies,\n })\n spin.succeed()\n\n // Use the resolved version for the given dependency\n const dependencies: Record<string, string> = {}\n for (const dependency of Object.keys({\n ...(isAppTemplate ? sdkAppDependencies.dependencies : studioDependencies.dependencies),\n ...template.dependencies,\n })) {\n dependencies[dependency] = dependencyVersions[dependency]\n }\n\n const devDependencies: Record<string, string> = {}\n for (const dependency of Object.keys({\n ...(isAppTemplate ? sdkAppDependencies.devDependencies : studioDependencies.devDependencies),\n ...template.devDependencies,\n })) {\n devDependencies[dependency] = dependencyVersions[dependency]\n }\n\n let packageJsonName: string = packageName\n\n /**\n * Currently app init doesn't ask for a name, so we use the last part of the path\n */\n if (isAppTemplate) {\n packageJsonName = slugify(path.basename(outputPath))\n }\n\n const title = variables.projectName || packageJsonName\n // Default the workbench app `slug` (the hostname the application is created\n // at on deploy). App init never asks for a name (`variables.projectName` is\n // just the cwd basename there), so apps follow their identity — the\n // output-path basename (`packageJsonName`) — while studios slug the entered\n // project name. Fall back to a constant when the source slugifies to\n // nothing (e.g. a fully non-latin name): an empty `slug` fails app config\n // validation, which is exactly what pre-filling it is meant to avoid.\n const slug = toAppSlug(isAppTemplate ? packageJsonName : title) ?? 'sanity-app'\n\n // Now create a package manifest (`package.json`) with the merged dependencies\n spin = spinner('Creating default project files').start()\n const packageManifest = createPackageManifest({\n dependencies,\n devDependencies,\n isAppTemplate,\n name: packageJsonName,\n scripts: template.scripts,\n type: template.type,\n })\n\n // ...and a studio config (`sanity.config.[ts|js]`)\n const studioConfig = createStudioConfig({\n template: template.configTemplate,\n variables,\n })\n\n // ...and a CLI config (`sanity.cli.[ts|js]`)\n const cliConfig = isAppTemplate\n ? createAppCliConfig({\n entry: template.entry!,\n isWorkbenchApp: variables.workbench,\n organizationId: variables.organizationId,\n slug,\n title,\n })\n : createCliConfig({\n autoUpdates: variables.autoUpdates,\n dataset: variables.dataset,\n isWorkbenchApp: variables.workbench,\n organizationId: variables.organizationId,\n projectId: variables.projectId,\n slug,\n title,\n })\n\n // Write non-template files to disc\n const codeExt = useTypeScript ? 'ts' : 'js'\n await Promise.all(\n [\n isAppTemplate\n ? Promise.resolve(null)\n : writeFileIfNotExists(`sanity.config.${codeExt}`, studioConfig),\n writeFileIfNotExists(`sanity.cli.${codeExt}`, cliConfig),\n writeFileIfNotExists('package.json', packageManifest),\n\n writeFileIfNotExists(\n 'eslint.config.mjs',\n `import studio from '@sanity/eslint-config-studio'\\n\\nexport default [...studio]\\n`,\n ),\n ].filter(Boolean),\n )\n\n debug('Updating initial template metadata')\n if (variables.projectId) {\n await updateInitialTemplateMetadata(variables.projectId, `cli-${templateName}`)\n }\n\n // Finish up by providing init process with template-specific info\n spin.succeed()\n return template\n\n async function writeFileIfNotExists(fileName: string, content: string): Promise<void> {\n const filePath = path.join(outputPath, fileName)\n\n if (opts.overwriteFiles) {\n // If overwrite is enabled, just write the file\n await fs.writeFile(filePath, content)\n return\n }\n\n try {\n await fs.writeFile(filePath, content, {flag: 'wx'})\n } catch (err) {\n if (err.code === 'EEXIST') {\n output.warn(`\\n${styleText('yellow', '⚠')} File \"${filePath}\" already exists, skipping`)\n } else {\n throw err\n }\n }\n }\n}\n\nfunction toTypeScriptPath(originalPath: string): string {\n return originalPath.replace(/\\.js$/, '.ts')\n}\n\n/** Lowercase, deburred, spaces to hyphens, everything else stripped. */\nfunction slugify(value: string): string {\n return deburr(value.toLowerCase())\n .replaceAll(/\\s+/g, '-')\n .replaceAll(/[^a-z0-9-]/g, '')\n}\n"],"names":["fs","path","styleText","subdebug","spinner","toAppSlug","deburr","copy","resolveLatestVersions","createAppCliConfig","createCliConfig","createPackageManifest","createStudioConfig","determineAppTemplate","processTemplate","sdkAppDependencies","studioDependencies","templates","updateInitialTemplateMetadata","debug","bootstrapLocalTemplate","opts","output","outputPath","packageName","templateName","useTypeScript","variables","cliRoot","resolve","dirname","templatesDir","join","sourceDir","sharedDir","isAppTemplate","template","Error","spin","start","rename","toTypeScriptPath","undefined","workbench","copyFile","succeed","appEntryPath","raw","readFile","rendered","dataset","projectId","writeFile","dependencyVersions","dependencies","devDependencies","dependency","Object","keys","packageJsonName","slugify","basename","title","projectName","slug","packageManifest","name","scripts","type","studioConfig","configTemplate","cliConfig","entry","isWorkbenchApp","organizationId","autoUpdates","codeExt","Promise","all","writeFileIfNotExists","filter","Boolean","fileName","content","filePath","overwriteFiles","flag","err","code","warn","originalPath","replace","value","toLowerCase","replaceAll"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/actions/init/bootstrapLocalTemplate.ts"],"sourcesContent":["import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport {styleText} from 'node:util'\n\nimport {Output, subdebug} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {toAppSlug} from '@sanity/workbench-cli/init'\nimport deburr from 'lodash-es/deburr.js'\n\nimport {copy} from '../../util/copy.js'\nimport {resolveLatestVersions} from '../../util/resolveLatestVersions.js'\nimport {createAppCliConfig} from './createAppCliConfig.js'\nimport {createCliConfig} from './createCliConfig.js'\nimport {createMediaLibraryCliConfig} from './createMediaLibraryCliConfig.js'\nimport {createPackageManifest} from './createPackageManifest.js'\nimport {createStudioConfig, type GenerateConfigOptions} from './createStudioConfig.js'\nimport {determineAppTemplate} from './determineAppTemplate.js'\nimport {determineMediaLibraryTemplate} from './determineMediaLibraryTemplate.js'\nimport {processTemplate} from './processTemplate.js'\nimport {sdkAppDependencies} from './sdkAppDependencies.js'\nimport {studioDependencies} from './studioDependencies.js'\nimport templates from './templates/index.js'\nimport {type ProjectTemplate} from './types.js'\nimport {updateInitialTemplateMetadata} from './updateInitialTemplateMetadata.js'\n\nconst debug = subdebug('init:bootstrapRemoteTemplate')\n\ninterface BootstrapLocalOptions {\n output: Output\n outputPath: string\n packageName: string\n templateName: string\n useTypeScript: boolean\n variables: GenerateConfigOptions['variables']\n\n overwriteFiles?: boolean\n}\n\nexport async function bootstrapLocalTemplate(\n opts: BootstrapLocalOptions,\n): Promise<ProjectTemplate> {\n const {output, outputPath, packageName, templateName, useTypeScript, variables} = opts\n // packages/@sanity/cli/src/actions/init/ -> packages/@sanity/cli/src/action -> packages/@sanity/cli/src/\n const cliRoot = path.resolve(import.meta.dirname, '../../..')\n const templatesDir = path.join(cliRoot, 'templates')\n const sourceDir = path.join(templatesDir, templateName)\n const sharedDir = path.join(templatesDir, 'shared')\n const isAppTemplate = determineAppTemplate(templateName)\n const isMediaLibraryTemplate = determineMediaLibraryTemplate(templateName)\n // Media Library config apps bring their own dependency set: neither the\n // SDK-app base nor the studio base applies (see templates/mediaLibraryConfig.ts).\n const baseDependencies = isAppTemplate\n ? sdkAppDependencies\n : isMediaLibraryTemplate\n ? {dependencies: {}, devDependencies: {}}\n : studioDependencies\n\n // Check that we have a template info file (dependencies, plugins etc)\n const template = templates[templateName]\n if (!template) {\n throw new Error(`Template \"${templateName}\" not defined`)\n }\n\n // Copy template files\n debug('Copying files from template \"%s\" to \"%s\"', templateName, outputPath)\n let spin = spinner('Bootstrapping files from template').start()\n\n debug(`Copying template from : ${sourceDir}`)\n await copy(sourceDir, outputPath, {\n rename: useTypeScript ? toTypeScriptPath : undefined,\n })\n // The Media Library template ships its own eslint config (a\n // restricted-imports override for field modules), stored as .txt — same\n // trick as shared/gitignore.txt — so the repo's own ESLint doesn't pick it\n // up as the nearest config for the template files.\n if (isMediaLibraryTemplate) {\n await fs.rename(\n path.join(outputPath, 'eslint.config.txt'),\n path.join(outputPath, 'eslint.config.mjs'),\n )\n }\n debug(`Copying shared template code from : ${sharedDir}`)\n await copy(path.join(sharedDir, 'gitignore.txt'), outputPath, {rename: () => '.gitignore'})\n // Dashboard apps dev and deploy differently, so their docs replace the\n // template's. Studio templates have no overlay.\n if (isAppTemplate && variables.workbench) {\n await copy(path.join(sharedDir, 'dashboard', templateName), outputPath)\n }\n\n if (useTypeScript) {\n await fs.copyFile(path.join(sharedDir, 'tsconfig.json'), path.join(outputPath, 'tsconfig.json'))\n }\n\n spin.succeed()\n\n if (isAppTemplate) {\n const appEntryPath = path.join(outputPath, 'src', 'App.tsx')\n const raw = await fs.readFile(appEntryPath, 'utf8')\n const rendered = processTemplate({\n template: raw,\n variables: {\n dataset: variables.dataset ?? '',\n projectId: variables.projectId ?? '',\n },\n })\n await fs.writeFile(appEntryPath, rendered)\n }\n\n // Merge global and template-specific plugins and dependencies\n\n // Resolve latest versions of Sanity-dependencies\n spin = spinner('Resolving latest module versions').start()\n const dependencyVersions = await resolveLatestVersions({\n ...baseDependencies.dependencies,\n ...baseDependencies.devDependencies,\n ...template.dependencies,\n ...template.devDependencies,\n })\n spin.succeed()\n\n // Use the resolved version for the given dependency\n const dependencies: Record<string, string> = {}\n for (const dependency of Object.keys({\n ...baseDependencies.dependencies,\n ...template.dependencies,\n })) {\n dependencies[dependency] = dependencyVersions[dependency]\n }\n\n const devDependencies: Record<string, string> = {}\n for (const dependency of Object.keys({\n ...baseDependencies.devDependencies,\n ...template.devDependencies,\n })) {\n devDependencies[dependency] = dependencyVersions[dependency]\n }\n\n let packageJsonName: string = packageName\n\n /**\n * Currently app init doesn't ask for a name, so we use the last part of the path\n */\n if (isAppTemplate || isMediaLibraryTemplate) {\n packageJsonName = slugify(path.basename(outputPath))\n }\n\n const title = variables.projectName || packageJsonName\n // Default the workbench app `slug` (the hostname the application is created\n // at on deploy). App init never asks for a name (`variables.projectName` is\n // just the cwd basename there), so apps follow their identity — the\n // output-path basename (`packageJsonName`) — while studios slug the entered\n // project name. Fall back to a constant when the source slugifies to\n // nothing (e.g. a fully non-latin name): an empty `slug` fails app config\n // validation, which is exactly what pre-filling it is meant to avoid.\n const slug = toAppSlug(isAppTemplate ? packageJsonName : title) ?? 'sanity-app'\n\n // Now create a package manifest (`package.json`) with the merged dependencies\n spin = spinner('Creating default project files').start()\n const packageManifest = createPackageManifest({\n dependencies,\n devDependencies,\n // Media Library config apps also skip the opinionated prettier config.\n isAppTemplate: isAppTemplate || isMediaLibraryTemplate,\n name: packageJsonName,\n scripts: template.scripts,\n type: template.type,\n })\n\n // ...and a studio config (`sanity.config.[ts|js]`) — only for studio\n // templates. App and media-library scaffolds don't write one, and building\n // it anyway would demand studio variables (projectId) they don't carry.\n const studioConfig =\n isAppTemplate || isMediaLibraryTemplate\n ? null\n : createStudioConfig({\n template: template.configTemplate,\n variables,\n })\n\n // ...and a CLI config (`sanity.cli.[ts|js]`)\n // oxlint-disable-next-line no-nested-ternary -- three scaffold shapes share one write path\n const cliConfig = isMediaLibraryTemplate\n ? createMediaLibraryCliConfig({organizationId: variables.organizationId})\n : isAppTemplate\n ? createAppCliConfig({\n entry: template.entry!,\n isWorkbenchApp: variables.workbench,\n organizationId: variables.organizationId,\n slug,\n title,\n })\n : createCliConfig({\n autoUpdates: variables.autoUpdates,\n dataset: variables.dataset,\n isWorkbenchApp: variables.workbench,\n organizationId: variables.organizationId,\n projectId: variables.projectId,\n slug,\n title,\n })\n\n // Write non-template files to disc\n const codeExt = useTypeScript ? 'ts' : 'js'\n await Promise.all(\n [\n studioConfig === null\n ? Promise.resolve(null)\n : writeFileIfNotExists(`sanity.config.${codeExt}`, studioConfig),\n writeFileIfNotExists(`sanity.cli.${codeExt}`, cliConfig),\n writeFileIfNotExists('package.json', packageManifest),\n\n // The Media Library template ships its own eslint.config.mjs (a\n // restricted-imports override for field modules) in the copied files.\n isMediaLibraryTemplate\n ? Promise.resolve(null)\n : writeFileIfNotExists(\n 'eslint.config.mjs',\n `import studio from '@sanity/eslint-config-studio'\\n\\nexport default [...studio]\\n`,\n ),\n ].filter(Boolean),\n )\n\n debug('Updating initial template metadata')\n if (variables.projectId) {\n await updateInitialTemplateMetadata(variables.projectId, `cli-${templateName}`)\n }\n\n // Finish up by providing init process with template-specific info\n spin.succeed()\n return template\n\n async function writeFileIfNotExists(fileName: string, content: string): Promise<void> {\n const filePath = path.join(outputPath, fileName)\n\n if (opts.overwriteFiles) {\n // If overwrite is enabled, just write the file\n await fs.writeFile(filePath, content)\n return\n }\n\n try {\n await fs.writeFile(filePath, content, {flag: 'wx'})\n } catch (err) {\n if (err.code === 'EEXIST') {\n output.warn(`\\n${styleText('yellow', '⚠')} File \"${filePath}\" already exists, skipping`)\n } else {\n throw err\n }\n }\n }\n}\n\nfunction toTypeScriptPath(originalPath: string): string {\n return originalPath.replace(/\\.js$/, '.ts')\n}\n\n/** Lowercase, deburred, spaces to hyphens, everything else stripped. */\nfunction slugify(value: string): string {\n return deburr(value.toLowerCase())\n .replaceAll(/\\s+/g, '-')\n .replaceAll(/[^a-z0-9-]/g, '')\n}\n"],"names":["fs","path","styleText","subdebug","spinner","toAppSlug","deburr","copy","resolveLatestVersions","createAppCliConfig","createCliConfig","createMediaLibraryCliConfig","createPackageManifest","createStudioConfig","determineAppTemplate","determineMediaLibraryTemplate","processTemplate","sdkAppDependencies","studioDependencies","templates","updateInitialTemplateMetadata","debug","bootstrapLocalTemplate","opts","output","outputPath","packageName","templateName","useTypeScript","variables","cliRoot","resolve","dirname","templatesDir","join","sourceDir","sharedDir","isAppTemplate","isMediaLibraryTemplate","baseDependencies","dependencies","devDependencies","template","Error","spin","start","rename","toTypeScriptPath","undefined","workbench","copyFile","succeed","appEntryPath","raw","readFile","rendered","dataset","projectId","writeFile","dependencyVersions","dependency","Object","keys","packageJsonName","slugify","basename","title","projectName","slug","packageManifest","name","scripts","type","studioConfig","configTemplate","cliConfig","organizationId","entry","isWorkbenchApp","autoUpdates","codeExt","Promise","all","writeFileIfNotExists","filter","Boolean","fileName","content","filePath","overwriteFiles","flag","err","code","warn","originalPath","replace","value","toLowerCase","replaceAll"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { workbenchMediaLibraryConfigTemplate } from '@sanity/workbench-cli/init';
2
+ import { processTemplate } from './processTemplate.js';
3
+ export function createMediaLibraryCliConfig(options) {
4
+ return processTemplate({
5
+ template: workbenchMediaLibraryConfigTemplate,
6
+ variables: {
7
+ organizationId: options.organizationId ?? ''
8
+ }
9
+ });
10
+ }
11
+
12
+ //# sourceMappingURL=createMediaLibraryCliConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/init/createMediaLibraryCliConfig.ts"],"sourcesContent":["import {workbenchMediaLibraryConfigTemplate} from '@sanity/workbench-cli/init'\n\nimport {processTemplate} from './processTemplate.js'\n\nexport function createMediaLibraryCliConfig(options: {organizationId?: string}): string {\n return processTemplate({\n template: workbenchMediaLibraryConfigTemplate,\n variables: {organizationId: options.organizationId ?? ''},\n })\n}\n"],"names":["workbenchMediaLibraryConfigTemplate","processTemplate","createMediaLibraryCliConfig","options","template","variables","organizationId"],"mappings":"AAAA,SAAQA,mCAAmC,QAAO,6BAA4B;AAE9E,SAAQC,eAAe,QAAO,uBAAsB;AAEpD,OAAO,SAASC,4BAA4BC,OAAkC;IAC5E,OAAOF,gBAAgB;QACrBG,UAAUJ;QACVK,WAAW;YAACC,gBAAgBH,QAAQG,cAAc,IAAI;QAAE;IAC1D;AACF"}
@@ -0,0 +1,14 @@
1
+ const mediaLibraryTemplates = new Set([
2
+ 'media-library-config'
3
+ ]);
4
+ /**
5
+ * Media Library config templates follow the app init flow (organization-only,
6
+ * no project/dataset) but scaffold an `unstable_defineMediaLibrary` config
7
+ * instead of `defineApplication`. Kept out of `determineAppTemplate`'s set so
8
+ * the app-template-specific bootstrap branches (`src/App.tsx` processing, the
9
+ * SDK dependency base, the dashboard docs overlay) don't apply.
10
+ */ export function determineMediaLibraryTemplate(templateName) {
11
+ return mediaLibraryTemplates.has(templateName);
12
+ }
13
+
14
+ //# sourceMappingURL=determineMediaLibraryTemplate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/init/determineMediaLibraryTemplate.ts"],"sourcesContent":["const mediaLibraryTemplates = new Set(['media-library-config'])\n\n/**\n * Media Library config templates follow the app init flow (organization-only,\n * no project/dataset) but scaffold an `unstable_defineMediaLibrary` config\n * instead of `defineApplication`. Kept out of `determineAppTemplate`'s set so\n * the app-template-specific bootstrap branches (`src/App.tsx` processing, the\n * SDK dependency base, the dashboard docs overlay) don't apply.\n */\nexport function determineMediaLibraryTemplate(templateName: string): boolean {\n return mediaLibraryTemplates.has(templateName)\n}\n"],"names":["mediaLibraryTemplates","Set","determineMediaLibraryTemplate","templateName","has"],"mappings":"AAAA,MAAMA,wBAAwB,IAAIC,IAAI;IAAC;CAAuB;AAE9D;;;;;;CAMC,GACD,OAAO,SAASC,8BAA8BC,YAAoB;IAChE,OAAOH,sBAAsBI,GAAG,CAACD;AACnC"}
@@ -18,6 +18,7 @@ import { setupMCP } from '../mcp/setupMCP.js';
18
18
  import { setupSkills } from '../skills/setupSkills.js';
19
19
  import { checkNextJsReactCompatibility } from './checkNextJsReactCompatibility.js';
20
20
  import { determineAppTemplate } from './determineAppTemplate.js';
21
+ import { determineMediaLibraryTemplate } from './determineMediaLibraryTemplate.js';
21
22
  import { createOrAppendEnvVars } from './env/createOrAppendEnvVars.js';
22
23
  import { initApp } from './initApp.js';
23
24
  import { InitError } from './initError.js';
@@ -39,7 +40,14 @@ export async function initAction(options, context) {
39
40
  if (options.reconfigure) {
40
41
  throw new InitError('--reconfigure is deprecated - manual configuration is now required', 1);
41
42
  }
42
- if (options.project && options.organization) {
43
+ // Media Library config templates ride the app init flow end to end:
44
+ // organization-only project details, app unattended-flag rules, `initApp`.
45
+ // Template-shape differences are handled downstream (bootstrapLocalTemplate
46
+ // and initApp check `determineMediaLibraryTemplate` themselves).
47
+ const isMediaLibraryTemplate = options.template ? determineMediaLibraryTemplate(options.template) : false;
48
+ // That template ignores project flags outright (getProjectDetails warns), so
49
+ // the pair is not the move-a-project contradiction this guard is about.
50
+ if (options.project && options.organization && !isMediaLibraryTemplate) {
43
51
  throw new InitError('You have specified both a project and an organization. To move a project to an organization please visit https://www.sanity.io/manage', 1);
44
52
  }
45
53
  const defaultConfig = options.datasetDefault;
@@ -64,10 +72,17 @@ export async function initAction(options, context) {
64
72
  if (detectedFramework && detectedFramework.slug !== 'sanity' && remoteTemplateInfo) {
65
73
  throw new InitError(`A remote template cannot be used with a detected framework. Detected: ${detectedFramework.name}`, 1);
66
74
  }
67
- const isAppTemplate = options.template ? determineAppTemplate(options.template) : false;
75
+ const isAppTemplate = options.template ? determineAppTemplate(options.template) || isMediaLibraryTemplate : false;
76
+ // A config app persists to the org's installation, not to a dashboard
77
+ // workbench, so `createMediaLibraryCliConfig` has no slot for --dashboard.
78
+ // Warned rather than silently dropped (same courtesy as remote templates).
79
+ if (options.dashboard && isMediaLibraryTemplate) {
80
+ output.warn('--dashboard is ignored for the media-library-config template');
81
+ }
68
82
  if (options.unattended) {
69
83
  checkFlagsInUnattendedMode(options, {
70
84
  isAppTemplate,
85
+ isMediaLibraryTemplate,
71
86
  isNextJs
72
87
  });
73
88
  }
@@ -97,7 +112,12 @@ export async function initAction(options, context) {
97
112
  output.log('');
98
113
  }
99
114
  let newProject;
100
- if (options.projectName) {
115
+ // A media-library config records only the organization; creating a project
116
+ // from --project-name here would be a throwaway side effect.
117
+ if (options.projectName && isMediaLibraryTemplate) {
118
+ output.warn('--project-name is ignored for the media-library-config template — it only records the organization.');
119
+ }
120
+ if (options.projectName && !isMediaLibraryTemplate) {
101
121
  newProject = await createProjectFromName({
102
122
  coupon: options.coupon,
103
123
  createProjectName: options.projectName,
@@ -113,6 +133,7 @@ export async function initAction(options, context) {
113
133
  dataset: options.dataset,
114
134
  datasetDefault: options.datasetDefault,
115
135
  isAppTemplate,
136
+ isMediaLibraryTemplate,
116
137
  newProject,
117
138
  organization: options.organization,
118
139
  output,
@@ -191,7 +212,11 @@ export async function initAction(options, context) {
191
212
  selectedOption: initNext ? 'yes' : 'no',
192
213
  step: 'useDetectedFramework'
193
214
  });
194
- const sluggedName = deburr(displayName.toLowerCase()).replaceAll(/\s+/g, '-').replaceAll(/[^a-z0-9-]/g, '');
215
+ // The media-library config template skips project selection, so
216
+ // `displayName` is empty and the slug would be too — which would default the
217
+ // output-path prompt to the (usually non-empty) cwd, a default
218
+ // `validateEmptyPath` then refuses. Fall back to the template's own name.
219
+ const sluggedName = deburr(displayName.toLowerCase()).replaceAll(/\s+/g, '-').replaceAll(/[^a-z0-9-]/g, '') || (isMediaLibraryTemplate ? 'media-library-config' : '');
195
220
  const initFramework = initNext;
196
221
  const defaults = await getProjectDefaults({
197
222
  isPlugin: false,
@@ -276,14 +301,18 @@ export async function initAction(options, context) {
276
301
  }));
277
302
  trace.complete();
278
303
  }
279
- function checkFlagsInUnattendedMode(options, { isAppTemplate, isNextJs }) {
304
+ function checkFlagsInUnattendedMode(options, { isAppTemplate, isMediaLibraryTemplate, isNextJs }) {
280
305
  debug('Unattended mode, validating required options');
281
306
  const errors = [];
282
307
  if (isAppTemplate) {
283
308
  if (!options.outputPath) {
284
309
  errors.push('Output path is required in unattended mode. Pass it with `--output-path <path>`.');
285
310
  }
286
- if (options.projectName && !options.organization) {
311
+ // The media-library config is organization-only, so project flags can't
312
+ // stand in for --organization the way they can for other app templates.
313
+ if (isMediaLibraryTemplate && !options.organization) {
314
+ errors.push('Organization is required for the media-library-config template in unattended mode. ' + 'Pass it with `--organization <id>`.');
315
+ } else if (options.projectName && !options.organization) {
287
316
  errors.push('Organization is required when creating a project in unattended mode. Pass it with `--organization <id>`.');
288
317
  } else if (!options.project && !options.organization) {
289
318
  errors.push('Project or organization is required for app templates in unattended mode. ' + 'Pass `--project <id>` or `--organization <id>`. To create a project, pass ' + '`--project-name <name>` with `--organization <id>`.');