@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.
- package/dist/actions/context/watchJob.js +9 -3
- package/dist/actions/context/watchJob.js.map +1 -1
- package/dist/actions/deploy/blueprintManaged.js +59 -0
- package/dist/actions/deploy/blueprintManaged.js.map +1 -0
- package/dist/actions/deploy/deployApp.js +117 -1
- package/dist/actions/deploy/deployApp.js.map +1 -1
- package/dist/actions/deploy/deployRunner.js.map +1 -1
- package/dist/actions/deploy/deployStudio.js +6 -31
- package/dist/actions/deploy/deployStudio.js.map +1 -1
- package/dist/actions/exec/runScript.worker.js +6 -2
- package/dist/actions/exec/runScript.worker.js.map +1 -1
- package/dist/actions/init/bootstrapLocalTemplate.js +35 -11
- package/dist/actions/init/bootstrapLocalTemplate.js.map +1 -1
- package/dist/actions/init/createMediaLibraryCliConfig.js +12 -0
- package/dist/actions/init/createMediaLibraryCliConfig.js.map +1 -0
- package/dist/actions/init/determineMediaLibraryTemplate.js +14 -0
- package/dist/actions/init/determineMediaLibraryTemplate.js.map +1 -0
- package/dist/actions/init/initAction.js +35 -6
- package/dist/actions/init/initAction.js.map +1 -1
- package/dist/actions/init/initApp.js +81 -6
- package/dist/actions/init/initApp.js.map +1 -1
- package/dist/actions/init/offerAspectPull.js +81 -0
- package/dist/actions/init/offerAspectPull.js.map +1 -0
- package/dist/actions/init/project/getProjectDetails.js +25 -2
- package/dist/actions/init/project/getProjectDetails.js.map +1 -1
- package/dist/actions/init/templates/index.js +3 -0
- package/dist/actions/init/templates/index.js.map +1 -1
- package/dist/actions/init/templates/mediaLibraryConfig.js +51 -0
- package/dist/actions/init/templates/mediaLibraryConfig.js.map +1 -0
- package/dist/actions/media/aspectName.js +8 -0
- package/dist/actions/media/aspectName.js.map +1 -0
- package/dist/actions/media/aspectSync/contract.js +163 -0
- package/dist/actions/media/aspectSync/contract.js.map +1 -0
- package/dist/actions/media/aspectSync/syncAspects.js +115 -0
- package/dist/actions/media/aspectSync/syncAspects.js.map +1 -0
- package/dist/actions/media/cliConfigFields.js +192 -0
- package/dist/actions/media/cliConfigFields.js.map +1 -0
- package/dist/actions/media/pullAspects.js +225 -0
- package/dist/actions/media/pullAspects.js.map +1 -0
- package/dist/actions/media/resolveMediaLibraryId.js +83 -0
- package/dist/actions/media/resolveMediaLibraryId.js.map +1 -0
- package/dist/commands/context/build.js +2 -2
- package/dist/commands/context/build.js.map +1 -1
- package/dist/commands/context/entries/get.js +83 -0
- package/dist/commands/context/entries/get.js.map +1 -0
- package/dist/commands/context/entries/list.js +82 -0
- package/dist/commands/context/entries/list.js.map +1 -0
- package/dist/commands/context/entries/rebuild.js +95 -0
- package/dist/commands/context/entries/rebuild.js.map +1 -0
- package/dist/commands/context/issues/apply.js +86 -0
- package/dist/commands/context/issues/apply.js.map +1 -0
- package/dist/commands/context/issues/dismiss.js +52 -0
- package/dist/commands/context/issues/dismiss.js.map +1 -0
- package/dist/commands/context/issues/get.js +105 -0
- package/dist/commands/context/issues/get.js.map +1 -0
- package/dist/commands/context/issues/list.js +128 -0
- package/dist/commands/context/issues/list.js.map +1 -0
- package/dist/commands/context/issues/reopen.js +53 -0
- package/dist/commands/context/issues/reopen.js.map +1 -0
- package/dist/commands/context/issues/resolve.js +137 -0
- package/dist/commands/context/issues/resolve.js.map +1 -0
- package/dist/commands/context/jobs/get.js +2 -2
- package/dist/commands/context/jobs/get.js.map +1 -1
- package/dist/commands/context/query.js +92 -0
- package/dist/commands/context/query.js.map +1 -0
- package/dist/commands/deploy.js +13 -0
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/media/prune-aspect-data.js +170 -0
- package/dist/commands/media/prune-aspect-data.js.map +1 -0
- package/dist/commands/media/pull-aspects.js +309 -0
- package/dist/commands/media/pull-aspects.js.map +1 -0
- package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js +17 -0
- package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js.map +1 -1
- package/dist/services/context.js +96 -3
- package/dist/services/context.js.map +1 -1
- package/dist/services/mediaLibraries.js +175 -8
- package/dist/services/mediaLibraries.js.map +1 -1
- package/oclif.manifest.json +2930 -2241
- package/package.json +6 -5
- package/templates/media-library-config/README.md +52 -0
- package/templates/media-library-config/eslint.config.txt +52 -0
- package/templates/media-library-config/src/fields/caption.tsx +29 -0
- package/templates/media-library-config/src/fields/notes.tsx +54 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/init/initAction.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {\n exitCodes,\n type SanityOrgUser,\n subdebug,\n type TelemetryUserProperties,\n} from '@sanity/cli-core'\nimport {logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {type TelemetryTrace} from '@sanity/telemetry'\nimport {type Framework, frameworks} from '@vercel/frameworks'\nimport deburr from 'lodash-es/deburr.js'\n\nimport {promptForConfigFiles} from '../../prompts/init/nextjs.js'\nimport {getCliUser} from '../../services/user.js'\nimport {CLIInitStepCompleted, type InitStepResult} from '../../telemetry/init.telemetry.js'\nimport {detectFrameworkRecord} from '../../util/detectFramework.js'\nimport {formatCliErrorMessages} from '../../util/formatCliErrorMessages.js'\nimport {getProjectDefaults} from '../../util/getProjectDefaults.js'\nimport {validateSession} from '../auth/ensureAuthenticated.js'\nimport {getProviderName, getUserDisplayName} from '../auth/getProviderName.js'\nimport {login} from '../auth/login/login.js'\nimport {LOGIN_REQUIRED_MESSAGE} from '../auth/login/loginInstructions.js'\nimport {detectAvailableEditors} from '../mcp/detectAvailableEditors.js'\nimport {setupMCP} from '../mcp/setupMCP.js'\nimport {setupSkills} from '../skills/setupSkills.js'\nimport {checkNextJsReactCompatibility} from './checkNextJsReactCompatibility.js'\nimport {determineAppTemplate} from './determineAppTemplate.js'\nimport {createOrAppendEnvVars} from './env/createOrAppendEnvVars.js'\nimport {initApp} from './initApp.js'\nimport {InitError} from './initError.js'\nimport {flagOrDefault, shouldPrompt, writeStagingEnvIfNeeded} from './initHelpers.js'\nimport {initNextJs} from './initNextJs.js'\nimport {initStudio} from './initStudio.js'\nimport {getPlan} from './plan/getPlan.js'\nimport {createProjectFromName} from './project/createProjectFromName.js'\nimport {getProjectDetails} from './project/getProjectDetails.js'\nimport {getProjectOutputPath} from './project/getProjectOutputPath.js'\nimport {checkIsRemoteTemplate, getGitHubRepoInfo, type RepoInfo} from './remoteTemplate.js'\nimport {type InitContext, type InitOptions} from './types.js'\n\nconst debug = subdebug('init')\n\nexport async function initAction(options: InitOptions, context: InitContext): Promise<void> {\n const {output, workDir} = context\n\n if (options.argType) {\n throw new InitError(\n options.argType === 'plugin'\n ? 'Initializing plugins through the CLI is no longer supported'\n : `Unknown init type \"${options.argType}\"`,\n 1,\n )\n }\n\n const trace = context.telemetry.trace(CLIInitStepCompleted)\n\n if (options.reconfigure) {\n throw new InitError('--reconfigure is deprecated - manual configuration is now required', 1)\n }\n\n if (options.project && options.organization) {\n throw new InitError(\n 'You have specified both a project and an organization. To move a project to an organization please visit https://www.sanity.io/manage',\n 1,\n )\n }\n\n const defaultConfig = options.datasetDefault\n let showDefaultConfigPrompt = !defaultConfig\n if (options.dataset || options.visibility || options.datasetDefault || options.unattended) {\n showDefaultConfigPrompt = false\n }\n\n const detectedFramework = await detectFrameworkRecord({\n frameworkList: frameworks as readonly Framework[],\n rootPath: workDir,\n })\n const isNextJs = detectedFramework?.slug === 'nextjs'\n\n let remoteTemplateInfo: RepoInfo | undefined\n if (options.template && checkIsRemoteTemplate(options.template)) {\n remoteTemplateInfo = await getGitHubRepoInfo(options.template, options.templateToken)\n }\n\n // Warned before any setup so the user can cancel. Remote templates ship their\n // own `sanity.cli.*`, so there is nothing to swap.\n if (options.dashboard && remoteTemplateInfo) {\n output.warn('--dashboard is ignored for remote templates')\n }\n\n if (detectedFramework && detectedFramework.slug !== 'sanity' && remoteTemplateInfo) {\n throw new InitError(\n `A remote template cannot be used with a detected framework. Detected: ${detectedFramework.name}`,\n 1,\n )\n }\n\n const isAppTemplate = options.template ? determineAppTemplate(options.template) : false\n\n if (options.unattended) {\n checkFlagsInUnattendedMode(options, {isAppTemplate, isNextJs})\n }\n\n trace.start()\n trace.log({\n flags: {\n bare: options.bare,\n coupon: options.coupon,\n defaultConfig,\n env: options.env,\n git: typeof options.git === 'string' ? options.git : undefined,\n plan: options.projectPlan,\n reconfigure: options.reconfigure,\n unattended: options.unattended,\n },\n step: 'start',\n })\n\n const planId = await getPlan(options, output, trace)\n\n let envFilenameDefault = '.env'\n if (detectedFramework && detectedFramework.slug === 'nextjs') {\n envFilenameDefault = '.env.local'\n }\n const envFilename = typeof options.env === 'string' ? options.env : envFilenameDefault\n\n const {user} = await ensureAuthenticated(options, output, trace)\n if (!isAppTemplate) {\n output.log(`${logSymbols.success} Fetching existing projects`)\n output.log('')\n }\n\n let newProject: string | undefined\n if (options.projectName) {\n newProject = await createProjectFromName({\n coupon: options.coupon,\n createProjectName: options.projectName,\n dataset: options.dataset,\n organization: options.organization,\n planId,\n user,\n visibility: options.visibility,\n })\n }\n\n const {datasetName, displayName, isFirstProject, organizationId, projectId} =\n await getProjectDetails({\n coupon: options.coupon,\n dataset: options.dataset,\n datasetDefault: options.datasetDefault,\n isAppTemplate,\n newProject,\n organization: options.organization,\n output,\n planId,\n project: options.project,\n showDefaultConfigPrompt,\n trace,\n unattended: options.unattended,\n user,\n visibility: options.visibility,\n })\n\n if (options.bare) {\n output.log(`${logSymbols.success} Below are your project details`)\n output.log('')\n output.log(`Project ID: ${styleText('cyan', projectId)}`)\n output.log(`Dataset: ${styleText('cyan', datasetName)}`)\n output.log(\n `\\nYou can find your project on Sanity Manage — https://www.sanity.io/manage/project/${projectId}\\n`,\n )\n trace.complete()\n return\n }\n\n // Detect editors once, then share the result with MCP and skills setup so\n // we don't pay the detection cost (filesystem probes + CLI execa calls) twice.\n const detectedEditors =\n options.mcpMode === 'skip' && options.skillsMode === 'skip'\n ? []\n : await detectAvailableEditors()\n\n const mcpResult = await setupMCP({\n editors: detectedEditors,\n mode: options.mcpMode,\n output,\n skillsMode: options.skillsMode,\n })\n\n trace.log({\n configuredEditors: mcpResult.configuredEditors,\n detectedEditors: mcpResult.detectedEditors,\n skipped: mcpResult.skipped,\n step: 'mcpSetup',\n })\n if (mcpResult.error) {\n trace.error(mcpResult.error)\n }\n const mcpConfigured = mcpResult.configuredEditors\n\n async function installSkills(): Promise<void> {\n if (mcpResult.skillsToInstall.length === 0) return\n try {\n const skillsResult = await setupSkills({\n agents: mcpResult.skillsToInstall,\n output,\n })\n trace.log({\n installedAgents: skillsResult.installedAgents,\n skipped: skillsResult.skipped,\n step: 'skillsSetup',\n })\n if (skillsResult.error) {\n trace.error(skillsResult.error)\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n debug('Unexpected error from setupSkills %O', err)\n output.warn(`Could not install Sanity agent skills: ${err.message}`)\n trace.error(err)\n }\n }\n\n // Install skills right after the MCP/skills prompt so the progress + result\n // surface in sequence, rather than trailing the studio \"Success!\" output.\n await installSkills()\n\n const {alreadyConfiguredEditors} = mcpResult\n if (alreadyConfiguredEditors.length > 0) {\n const label =\n alreadyConfiguredEditors.length === 1\n ? `${alreadyConfiguredEditors[0]} already configured for Sanity MCP`\n : `${alreadyConfiguredEditors.length} editors already configured for Sanity MCP`\n spinner(label).start().succeed()\n }\n\n let initNext = flagOrDefault(options.nextjsAddConfigFiles, false)\n if (isNextJs && shouldPrompt(options.unattended, options.nextjsAddConfigFiles)) {\n initNext = await promptForConfigFiles()\n }\n\n trace.log({\n detectedFramework: detectedFramework?.name,\n selectedOption: initNext ? 'yes' : 'no',\n step: 'useDetectedFramework',\n })\n\n const sluggedName = deburr(displayName.toLowerCase())\n .replaceAll(/\\s+/g, '-')\n .replaceAll(/[^a-z0-9-]/g, '')\n\n const initFramework = initNext\n\n const defaults = await getProjectDefaults({isPlugin: false, workDir})\n\n const outputPath = await getProjectOutputPath({\n initFramework,\n outputPath: options.outputPath,\n sluggedName,\n unattended: options.unattended,\n useEnv: Boolean(options.env),\n workDir,\n })\n\n if (isNextJs) {\n await checkNextJsReactCompatibility({\n detectedFramework,\n output,\n outputPath,\n })\n }\n\n if (initNext) {\n if (options.dashboard) {\n output.warn('--dashboard is ignored for Next.js projects')\n }\n await initNextJs({\n datasetName,\n detectedFramework,\n envFilename,\n mcpConfigured,\n options,\n output,\n projectId,\n trace,\n workDir,\n })\n trace.complete()\n return\n }\n\n if (options.env) {\n await createOrAppendEnvVars({\n envVars: {\n DATASET: datasetName,\n PROJECT_ID: projectId,\n },\n filename: envFilename,\n framework: detectedFramework,\n log: false,\n output,\n outputPath,\n })\n await writeStagingEnvIfNeeded(output, outputPath)\n trace.complete()\n return\n }\n\n // The Dashboard is opt-in (no prompt): `--dashboard` swaps the scaffolded\n // `sanity.cli.*` over to `defineApplication` — the branded app is the sole\n // Dashboard opt-in.\n const workbench = flagOrDefault(options.dashboard, false)\n\n const sharedParams = {\n defaults,\n mcpConfigured,\n options,\n organizationId,\n output,\n outputPath,\n remoteTemplateInfo,\n sluggedName,\n trace,\n workbench,\n workDir,\n }\n\n await (isAppTemplate\n ? initApp({...sharedParams, datasetName, projectId})\n : initStudio({\n ...sharedParams,\n datasetName,\n displayName,\n isFirstProject,\n projectId,\n }))\n\n trace.complete()\n}\n\nfunction checkFlagsInUnattendedMode(\n options: InitOptions,\n {isAppTemplate, isNextJs}: {isAppTemplate: boolean; isNextJs: boolean},\n): void {\n debug('Unattended mode, validating required options')\n\n const errors: string[] = []\n\n if (isAppTemplate) {\n if (!options.outputPath) {\n errors.push(\n 'Output path is required in unattended mode. Pass it with `--output-path <path>`.',\n )\n }\n\n if (options.projectName && !options.organization) {\n errors.push(\n 'Organization is required when creating a project in unattended mode. Pass it with `--organization <id>`.',\n )\n } else if (!options.project && !options.organization) {\n errors.push(\n 'Project or organization is required for app templates in unattended mode. ' +\n 'Pass `--project <id>` or `--organization <id>`. To create a project, pass ' +\n '`--project-name <name>` with `--organization <id>`.',\n )\n }\n } else {\n if (!isNextJs && !options.bare && !options.outputPath) {\n errors.push(\n 'Output path is required in unattended mode. Pass it with `--output-path <path>`.',\n )\n }\n\n if (!options.project && !options.projectName) {\n errors.push(\n 'Project is required in unattended mode. Pass it with `--project <id>` or `--project-name <name>`.',\n )\n }\n\n if (!options.project && !options.organization) {\n errors.push(\n 'Organization is required when creating a project in unattended mode. Pass it with `--organization <id>`.',\n )\n }\n }\n\n if (errors.length > 0) {\n throw new InitError(formatCliErrorMessages(errors), exitCodes.USAGE_ERROR)\n }\n}\n\nasync function ensureAuthenticated(\n options: InitOptions,\n output: InitContext['output'],\n trace: TelemetryTrace<TelemetryUserProperties, InitStepResult>,\n): Promise<{user: SanityOrgUser}> {\n const user = await validateSession()\n\n if (user) {\n trace.log({alreadyLoggedIn: true, step: 'login'})\n output.log(\n `${logSymbols.success} You are logged in as ${getUserDisplayName(user)} using ${getProviderName(user.provider)}`,\n )\n return {user}\n }\n\n if (options.unattended) {\n throw new InitError(LOGIN_REQUIRED_MESSAGE, exitCodes.RUNTIME_ERROR)\n }\n\n trace.log({step: 'login'})\n output.warn(LOGIN_REQUIRED_MESSAGE)\n\n try {\n await login({\n output,\n telemetry: trace.newContext('login'),\n })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new InitError(`Login failed: ${message}`, 1)\n }\n\n const loggedInUser = await getCliUser()\n\n output.log(\n `${logSymbols.success} You are logged in as ${getUserDisplayName(loggedInUser)} using ${getProviderName(loggedInUser.provider)}`,\n )\n return {user: loggedInUser}\n}\n"],"names":["styleText","exitCodes","subdebug","logSymbols","spinner","frameworks","deburr","promptForConfigFiles","getCliUser","CLIInitStepCompleted","detectFrameworkRecord","formatCliErrorMessages","getProjectDefaults","validateSession","getProviderName","getUserDisplayName","login","LOGIN_REQUIRED_MESSAGE","detectAvailableEditors","setupMCP","setupSkills","checkNextJsReactCompatibility","determineAppTemplate","createOrAppendEnvVars","initApp","InitError","flagOrDefault","shouldPrompt","writeStagingEnvIfNeeded","initNextJs","initStudio","getPlan","createProjectFromName","getProjectDetails","getProjectOutputPath","checkIsRemoteTemplate","getGitHubRepoInfo","debug","initAction","options","context","output","workDir","argType","trace","telemetry","reconfigure","project","organization","defaultConfig","datasetDefault","showDefaultConfigPrompt","dataset","visibility","unattended","detectedFramework","frameworkList","rootPath","isNextJs","slug","remoteTemplateInfo","template","templateToken","dashboard","warn","name","isAppTemplate","checkFlagsInUnattendedMode","start","log","flags","bare","coupon","env","git","undefined","plan","projectPlan","step","planId","envFilenameDefault","envFilename","user","ensureAuthenticated","success","newProject","projectName","createProjectName","datasetName","displayName","isFirstProject","organizationId","projectId","complete","detectedEditors","mcpMode","skillsMode","mcpResult","editors","mode","configuredEditors","skipped","error","mcpConfigured","installSkills","skillsToInstall","length","skillsResult","agents","installedAgents","err","Error","String","message","alreadyConfiguredEditors","label","succeed","initNext","nextjsAddConfigFiles","selectedOption","sluggedName","toLowerCase","replaceAll","initFramework","defaults","isPlugin","outputPath","useEnv","Boolean","envVars","DATASET","PROJECT_ID","filename","framework","workbench","sharedParams","errors","push","USAGE_ERROR","alreadyLoggedIn","provider","RUNTIME_ERROR","newContext","loggedInUser"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/init/initAction.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {\n exitCodes,\n type SanityOrgUser,\n subdebug,\n type TelemetryUserProperties,\n} from '@sanity/cli-core'\nimport {logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {type TelemetryTrace} from '@sanity/telemetry'\nimport {type Framework, frameworks} from '@vercel/frameworks'\nimport deburr from 'lodash-es/deburr.js'\n\nimport {promptForConfigFiles} from '../../prompts/init/nextjs.js'\nimport {getCliUser} from '../../services/user.js'\nimport {CLIInitStepCompleted, type InitStepResult} from '../../telemetry/init.telemetry.js'\nimport {detectFrameworkRecord} from '../../util/detectFramework.js'\nimport {formatCliErrorMessages} from '../../util/formatCliErrorMessages.js'\nimport {getProjectDefaults} from '../../util/getProjectDefaults.js'\nimport {validateSession} from '../auth/ensureAuthenticated.js'\nimport {getProviderName, getUserDisplayName} from '../auth/getProviderName.js'\nimport {login} from '../auth/login/login.js'\nimport {LOGIN_REQUIRED_MESSAGE} from '../auth/login/loginInstructions.js'\nimport {detectAvailableEditors} from '../mcp/detectAvailableEditors.js'\nimport {setupMCP} from '../mcp/setupMCP.js'\nimport {setupSkills} from '../skills/setupSkills.js'\nimport {checkNextJsReactCompatibility} from './checkNextJsReactCompatibility.js'\nimport {determineAppTemplate} from './determineAppTemplate.js'\nimport {determineMediaLibraryTemplate} from './determineMediaLibraryTemplate.js'\nimport {createOrAppendEnvVars} from './env/createOrAppendEnvVars.js'\nimport {initApp} from './initApp.js'\nimport {InitError} from './initError.js'\nimport {flagOrDefault, shouldPrompt, writeStagingEnvIfNeeded} from './initHelpers.js'\nimport {initNextJs} from './initNextJs.js'\nimport {initStudio} from './initStudio.js'\nimport {getPlan} from './plan/getPlan.js'\nimport {createProjectFromName} from './project/createProjectFromName.js'\nimport {getProjectDetails} from './project/getProjectDetails.js'\nimport {getProjectOutputPath} from './project/getProjectOutputPath.js'\nimport {checkIsRemoteTemplate, getGitHubRepoInfo, type RepoInfo} from './remoteTemplate.js'\nimport {type InitContext, type InitOptions} from './types.js'\n\nconst debug = subdebug('init')\n\nexport async function initAction(options: InitOptions, context: InitContext): Promise<void> {\n const {output, workDir} = context\n\n if (options.argType) {\n throw new InitError(\n options.argType === 'plugin'\n ? 'Initializing plugins through the CLI is no longer supported'\n : `Unknown init type \"${options.argType}\"`,\n 1,\n )\n }\n\n const trace = context.telemetry.trace(CLIInitStepCompleted)\n\n if (options.reconfigure) {\n throw new InitError('--reconfigure is deprecated - manual configuration is now required', 1)\n }\n\n // Media Library config templates ride the app init flow end to end:\n // organization-only project details, app unattended-flag rules, `initApp`.\n // Template-shape differences are handled downstream (bootstrapLocalTemplate\n // and initApp check `determineMediaLibraryTemplate` themselves).\n const isMediaLibraryTemplate = options.template\n ? determineMediaLibraryTemplate(options.template)\n : false\n\n // That template ignores project flags outright (getProjectDetails warns), so\n // the pair is not the move-a-project contradiction this guard is about.\n if (options.project && options.organization && !isMediaLibraryTemplate) {\n throw new InitError(\n 'You have specified both a project and an organization. To move a project to an organization please visit https://www.sanity.io/manage',\n 1,\n )\n }\n\n const defaultConfig = options.datasetDefault\n let showDefaultConfigPrompt = !defaultConfig\n if (options.dataset || options.visibility || options.datasetDefault || options.unattended) {\n showDefaultConfigPrompt = false\n }\n\n const detectedFramework = await detectFrameworkRecord({\n frameworkList: frameworks as readonly Framework[],\n rootPath: workDir,\n })\n const isNextJs = detectedFramework?.slug === 'nextjs'\n\n let remoteTemplateInfo: RepoInfo | undefined\n if (options.template && checkIsRemoteTemplate(options.template)) {\n remoteTemplateInfo = await getGitHubRepoInfo(options.template, options.templateToken)\n }\n\n // Warned before any setup so the user can cancel. Remote templates ship their\n // own `sanity.cli.*`, so there is nothing to swap.\n if (options.dashboard && remoteTemplateInfo) {\n output.warn('--dashboard is ignored for remote templates')\n }\n\n if (detectedFramework && detectedFramework.slug !== 'sanity' && remoteTemplateInfo) {\n throw new InitError(\n `A remote template cannot be used with a detected framework. Detected: ${detectedFramework.name}`,\n 1,\n )\n }\n\n const isAppTemplate = options.template\n ? determineAppTemplate(options.template) || isMediaLibraryTemplate\n : false\n\n // A config app persists to the org's installation, not to a dashboard\n // workbench, so `createMediaLibraryCliConfig` has no slot for --dashboard.\n // Warned rather than silently dropped (same courtesy as remote templates).\n if (options.dashboard && isMediaLibraryTemplate) {\n output.warn('--dashboard is ignored for the media-library-config template')\n }\n\n if (options.unattended) {\n checkFlagsInUnattendedMode(options, {isAppTemplate, isMediaLibraryTemplate, isNextJs})\n }\n\n trace.start()\n trace.log({\n flags: {\n bare: options.bare,\n coupon: options.coupon,\n defaultConfig,\n env: options.env,\n git: typeof options.git === 'string' ? options.git : undefined,\n plan: options.projectPlan,\n reconfigure: options.reconfigure,\n unattended: options.unattended,\n },\n step: 'start',\n })\n\n const planId = await getPlan(options, output, trace)\n\n let envFilenameDefault = '.env'\n if (detectedFramework && detectedFramework.slug === 'nextjs') {\n envFilenameDefault = '.env.local'\n }\n const envFilename = typeof options.env === 'string' ? options.env : envFilenameDefault\n\n const {user} = await ensureAuthenticated(options, output, trace)\n if (!isAppTemplate) {\n output.log(`${logSymbols.success} Fetching existing projects`)\n output.log('')\n }\n\n let newProject: string | undefined\n // A media-library config records only the organization; creating a project\n // from --project-name here would be a throwaway side effect.\n if (options.projectName && isMediaLibraryTemplate) {\n output.warn(\n '--project-name is ignored for the media-library-config template — it only records the organization.',\n )\n }\n if (options.projectName && !isMediaLibraryTemplate) {\n newProject = await createProjectFromName({\n coupon: options.coupon,\n createProjectName: options.projectName,\n dataset: options.dataset,\n organization: options.organization,\n planId,\n user,\n visibility: options.visibility,\n })\n }\n\n const {datasetName, displayName, isFirstProject, organizationId, projectId} =\n await getProjectDetails({\n coupon: options.coupon,\n dataset: options.dataset,\n datasetDefault: options.datasetDefault,\n isAppTemplate,\n isMediaLibraryTemplate,\n newProject,\n organization: options.organization,\n output,\n planId,\n project: options.project,\n showDefaultConfigPrompt,\n trace,\n unattended: options.unattended,\n user,\n visibility: options.visibility,\n })\n\n if (options.bare) {\n output.log(`${logSymbols.success} Below are your project details`)\n output.log('')\n output.log(`Project ID: ${styleText('cyan', projectId)}`)\n output.log(`Dataset: ${styleText('cyan', datasetName)}`)\n output.log(\n `\\nYou can find your project on Sanity Manage — https://www.sanity.io/manage/project/${projectId}\\n`,\n )\n trace.complete()\n return\n }\n\n // Detect editors once, then share the result with MCP and skills setup so\n // we don't pay the detection cost (filesystem probes + CLI execa calls) twice.\n const detectedEditors =\n options.mcpMode === 'skip' && options.skillsMode === 'skip'\n ? []\n : await detectAvailableEditors()\n\n const mcpResult = await setupMCP({\n editors: detectedEditors,\n mode: options.mcpMode,\n output,\n skillsMode: options.skillsMode,\n })\n\n trace.log({\n configuredEditors: mcpResult.configuredEditors,\n detectedEditors: mcpResult.detectedEditors,\n skipped: mcpResult.skipped,\n step: 'mcpSetup',\n })\n if (mcpResult.error) {\n trace.error(mcpResult.error)\n }\n const mcpConfigured = mcpResult.configuredEditors\n\n async function installSkills(): Promise<void> {\n if (mcpResult.skillsToInstall.length === 0) return\n try {\n const skillsResult = await setupSkills({\n agents: mcpResult.skillsToInstall,\n output,\n })\n trace.log({\n installedAgents: skillsResult.installedAgents,\n skipped: skillsResult.skipped,\n step: 'skillsSetup',\n })\n if (skillsResult.error) {\n trace.error(skillsResult.error)\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n debug('Unexpected error from setupSkills %O', err)\n output.warn(`Could not install Sanity agent skills: ${err.message}`)\n trace.error(err)\n }\n }\n\n // Install skills right after the MCP/skills prompt so the progress + result\n // surface in sequence, rather than trailing the studio \"Success!\" output.\n await installSkills()\n\n const {alreadyConfiguredEditors} = mcpResult\n if (alreadyConfiguredEditors.length > 0) {\n const label =\n alreadyConfiguredEditors.length === 1\n ? `${alreadyConfiguredEditors[0]} already configured for Sanity MCP`\n : `${alreadyConfiguredEditors.length} editors already configured for Sanity MCP`\n spinner(label).start().succeed()\n }\n\n let initNext = flagOrDefault(options.nextjsAddConfigFiles, false)\n if (isNextJs && shouldPrompt(options.unattended, options.nextjsAddConfigFiles)) {\n initNext = await promptForConfigFiles()\n }\n\n trace.log({\n detectedFramework: detectedFramework?.name,\n selectedOption: initNext ? 'yes' : 'no',\n step: 'useDetectedFramework',\n })\n\n // The media-library config template skips project selection, so\n // `displayName` is empty and the slug would be too — which would default the\n // output-path prompt to the (usually non-empty) cwd, a default\n // `validateEmptyPath` then refuses. Fall back to the template's own name.\n const sluggedName =\n deburr(displayName.toLowerCase())\n .replaceAll(/\\s+/g, '-')\n .replaceAll(/[^a-z0-9-]/g, '') || (isMediaLibraryTemplate ? 'media-library-config' : '')\n\n const initFramework = initNext\n\n const defaults = await getProjectDefaults({isPlugin: false, workDir})\n\n const outputPath = await getProjectOutputPath({\n initFramework,\n outputPath: options.outputPath,\n sluggedName,\n unattended: options.unattended,\n useEnv: Boolean(options.env),\n workDir,\n })\n\n if (isNextJs) {\n await checkNextJsReactCompatibility({\n detectedFramework,\n output,\n outputPath,\n })\n }\n\n if (initNext) {\n if (options.dashboard) {\n output.warn('--dashboard is ignored for Next.js projects')\n }\n await initNextJs({\n datasetName,\n detectedFramework,\n envFilename,\n mcpConfigured,\n options,\n output,\n projectId,\n trace,\n workDir,\n })\n trace.complete()\n return\n }\n\n if (options.env) {\n await createOrAppendEnvVars({\n envVars: {\n DATASET: datasetName,\n PROJECT_ID: projectId,\n },\n filename: envFilename,\n framework: detectedFramework,\n log: false,\n output,\n outputPath,\n })\n await writeStagingEnvIfNeeded(output, outputPath)\n trace.complete()\n return\n }\n\n // The Dashboard is opt-in (no prompt): `--dashboard` swaps the scaffolded\n // `sanity.cli.*` over to `defineApplication` — the branded app is the sole\n // Dashboard opt-in.\n const workbench = flagOrDefault(options.dashboard, false)\n\n const sharedParams = {\n defaults,\n mcpConfigured,\n options,\n organizationId,\n output,\n outputPath,\n remoteTemplateInfo,\n sluggedName,\n trace,\n workbench,\n workDir,\n }\n\n await (isAppTemplate\n ? initApp({...sharedParams, datasetName, projectId})\n : initStudio({\n ...sharedParams,\n datasetName,\n displayName,\n isFirstProject,\n projectId,\n }))\n\n trace.complete()\n}\n\nfunction checkFlagsInUnattendedMode(\n options: InitOptions,\n {\n isAppTemplate,\n isMediaLibraryTemplate,\n isNextJs,\n }: {isAppTemplate: boolean; isMediaLibraryTemplate: boolean; isNextJs: boolean},\n): void {\n debug('Unattended mode, validating required options')\n\n const errors: string[] = []\n\n if (isAppTemplate) {\n if (!options.outputPath) {\n errors.push(\n 'Output path is required in unattended mode. Pass it with `--output-path <path>`.',\n )\n }\n\n // The media-library config is organization-only, so project flags can't\n // stand in for --organization the way they can for other app templates.\n if (isMediaLibraryTemplate && !options.organization) {\n errors.push(\n 'Organization is required for the media-library-config template in unattended mode. ' +\n 'Pass it with `--organization <id>`.',\n )\n } else if (options.projectName && !options.organization) {\n errors.push(\n 'Organization is required when creating a project in unattended mode. Pass it with `--organization <id>`.',\n )\n } else if (!options.project && !options.organization) {\n errors.push(\n 'Project or organization is required for app templates in unattended mode. ' +\n 'Pass `--project <id>` or `--organization <id>`. To create a project, pass ' +\n '`--project-name <name>` with `--organization <id>`.',\n )\n }\n } else {\n if (!isNextJs && !options.bare && !options.outputPath) {\n errors.push(\n 'Output path is required in unattended mode. Pass it with `--output-path <path>`.',\n )\n }\n\n if (!options.project && !options.projectName) {\n errors.push(\n 'Project is required in unattended mode. Pass it with `--project <id>` or `--project-name <name>`.',\n )\n }\n\n if (!options.project && !options.organization) {\n errors.push(\n 'Organization is required when creating a project in unattended mode. Pass it with `--organization <id>`.',\n )\n }\n }\n\n if (errors.length > 0) {\n throw new InitError(formatCliErrorMessages(errors), exitCodes.USAGE_ERROR)\n }\n}\n\nasync function ensureAuthenticated(\n options: InitOptions,\n output: InitContext['output'],\n trace: TelemetryTrace<TelemetryUserProperties, InitStepResult>,\n): Promise<{user: SanityOrgUser}> {\n const user = await validateSession()\n\n if (user) {\n trace.log({alreadyLoggedIn: true, step: 'login'})\n output.log(\n `${logSymbols.success} You are logged in as ${getUserDisplayName(user)} using ${getProviderName(user.provider)}`,\n )\n return {user}\n }\n\n if (options.unattended) {\n throw new InitError(LOGIN_REQUIRED_MESSAGE, exitCodes.RUNTIME_ERROR)\n }\n\n trace.log({step: 'login'})\n output.warn(LOGIN_REQUIRED_MESSAGE)\n\n try {\n await login({\n output,\n telemetry: trace.newContext('login'),\n })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n throw new InitError(`Login failed: ${message}`, 1)\n }\n\n const loggedInUser = await getCliUser()\n\n output.log(\n `${logSymbols.success} You are logged in as ${getUserDisplayName(loggedInUser)} using ${getProviderName(loggedInUser.provider)}`,\n )\n return {user: loggedInUser}\n}\n"],"names":["styleText","exitCodes","subdebug","logSymbols","spinner","frameworks","deburr","promptForConfigFiles","getCliUser","CLIInitStepCompleted","detectFrameworkRecord","formatCliErrorMessages","getProjectDefaults","validateSession","getProviderName","getUserDisplayName","login","LOGIN_REQUIRED_MESSAGE","detectAvailableEditors","setupMCP","setupSkills","checkNextJsReactCompatibility","determineAppTemplate","determineMediaLibraryTemplate","createOrAppendEnvVars","initApp","InitError","flagOrDefault","shouldPrompt","writeStagingEnvIfNeeded","initNextJs","initStudio","getPlan","createProjectFromName","getProjectDetails","getProjectOutputPath","checkIsRemoteTemplate","getGitHubRepoInfo","debug","initAction","options","context","output","workDir","argType","trace","telemetry","reconfigure","isMediaLibraryTemplate","template","project","organization","defaultConfig","datasetDefault","showDefaultConfigPrompt","dataset","visibility","unattended","detectedFramework","frameworkList","rootPath","isNextJs","slug","remoteTemplateInfo","templateToken","dashboard","warn","name","isAppTemplate","checkFlagsInUnattendedMode","start","log","flags","bare","coupon","env","git","undefined","plan","projectPlan","step","planId","envFilenameDefault","envFilename","user","ensureAuthenticated","success","newProject","projectName","createProjectName","datasetName","displayName","isFirstProject","organizationId","projectId","complete","detectedEditors","mcpMode","skillsMode","mcpResult","editors","mode","configuredEditors","skipped","error","mcpConfigured","installSkills","skillsToInstall","length","skillsResult","agents","installedAgents","err","Error","String","message","alreadyConfiguredEditors","label","succeed","initNext","nextjsAddConfigFiles","selectedOption","sluggedName","toLowerCase","replaceAll","initFramework","defaults","isPlugin","outputPath","useEnv","Boolean","envVars","DATASET","PROJECT_ID","filename","framework","workbench","sharedParams","errors","push","USAGE_ERROR","alreadyLoggedIn","provider","RUNTIME_ERROR","newContext","loggedInUser"],"mappings":"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"}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { styleText } from 'node:util';
|
|
2
|
+
import { isStaging } from '@sanity/cli-core/util';
|
|
2
3
|
import { logSymbols } from '@sanity/cli-core/ux';
|
|
4
|
+
import { getMediaLibrariesForOrganization } from '../../services/mediaLibraries.js';
|
|
3
5
|
import { getInstallCommand } from '../../util/packageManager/installPackages.js';
|
|
6
|
+
import { determineMediaLibraryTemplate } from './determineMediaLibraryTemplate.js';
|
|
4
7
|
import { InitError } from './initError.js';
|
|
5
8
|
import { getPostInitMCPPrompt } from './initHelpers.js';
|
|
9
|
+
import { offerAspectPull } from './offerAspectPull.js';
|
|
6
10
|
import { scaffoldAndInstall, selectTemplate } from './scaffoldTemplate.js';
|
|
7
11
|
export async function initApp({ datasetName, defaults, mcpConfigured, options, organizationId, output, outputPath, projectId, remoteTemplateInfo, sluggedName, trace, workbench, workDir }) {
|
|
8
12
|
const { template: resolvedTemplate, templateName, useTypeScript } = await selectTemplate({
|
|
@@ -32,6 +36,50 @@ export async function initApp({ datasetName, defaults, mcpConfigured, options, o
|
|
|
32
36
|
});
|
|
33
37
|
const isCurrentDir = outputPath === workDir;
|
|
34
38
|
const goToProjectDir = `\n(${styleText('cyan', `cd ${outputPath}`)} to navigate to your new project directory)`;
|
|
39
|
+
if (determineMediaLibraryTemplate(templateName)) {
|
|
40
|
+
output.log(`${logSymbols.success} ${styleText([
|
|
41
|
+
'green',
|
|
42
|
+
'bold'
|
|
43
|
+
], 'Success!')} Your Media Library config app has been scaffolded.`);
|
|
44
|
+
if (!isCurrentDir) output.log(goToProjectDir);
|
|
45
|
+
if (!options.install) {
|
|
46
|
+
output.log(`\nRun ${styleText('cyan', getInstallCommand(pkgManager))} to install dependencies.`);
|
|
47
|
+
}
|
|
48
|
+
let libraries = [];
|
|
49
|
+
if (organizationId) {
|
|
50
|
+
output.log(`\nConfigured for organization ${styleText('cyan', organizationId)}.`);
|
|
51
|
+
libraries = await warnIfNoActiveMediaLibrary(organizationId, output);
|
|
52
|
+
}
|
|
53
|
+
// The deploy mirrors config into the library and deletes stored aspects
|
|
54
|
+
// the config does not declare, so an org that already defines aspects is
|
|
55
|
+
// offered a pull now — while init is interactive and authenticated. Only
|
|
56
|
+
// with exactly one active library; picking one is pull-aspects territory.
|
|
57
|
+
let pulledAspects = false;
|
|
58
|
+
if (libraries.length === 1 && !options.unattended) {
|
|
59
|
+
output.log('');
|
|
60
|
+
pulledAspects = await offerAspectPull({
|
|
61
|
+
library: libraries[0],
|
|
62
|
+
output,
|
|
63
|
+
outputPath
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
output.log('\nField definitions live in `src/fields/` and are registered in `sanity.cli.ts` — see the README for the authoring rules.');
|
|
67
|
+
if (libraries.length > 0 && !pulledAspects) {
|
|
68
|
+
output.log(`\nAlready defining aspects in your Media Library? Generate field modules from them with ${styleText('cyan', 'npx sanity media pull-aspects')}.`);
|
|
69
|
+
}
|
|
70
|
+
output.log('\nRefer to our documentation for a walkthrough:');
|
|
71
|
+
output.log(styleText([
|
|
72
|
+
'blue',
|
|
73
|
+
'underline'
|
|
74
|
+
], 'https://www.sanity.io/docs/media-library'));
|
|
75
|
+
await logMcpConfirmation(mcpConfigured, output);
|
|
76
|
+
output.log('\n');
|
|
77
|
+
output.log(`Other helpful commands:`);
|
|
78
|
+
output.log(`npx sanity docs browse to open the documentation in a browser`);
|
|
79
|
+
output.log(`npx sanity dev to serve your fields to the Media Library live`);
|
|
80
|
+
output.log(`npx sanity deploy to deploy the config to your organization`);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
35
83
|
//output for custom apps here
|
|
36
84
|
output.log(`${logSymbols.success} ${styleText([
|
|
37
85
|
'green',
|
|
@@ -52,17 +100,44 @@ export async function initApp({ datasetName, defaults, mcpConfigured, options, o
|
|
|
52
100
|
'blue',
|
|
53
101
|
'underline'
|
|
54
102
|
], 'https://www.sanity.io/docs/app-sdk/sdk-configuration'));
|
|
55
|
-
|
|
56
|
-
const message = await getPostInitMCPPrompt(mcpConfigured);
|
|
57
|
-
output.log(`\n${message}`);
|
|
58
|
-
output.log(`\nLearn more: ${styleText('cyan', 'https://mcp.sanity.io')}`);
|
|
59
|
-
output.log(`\nHave feedback? Tell us in the community: ${styleText('cyan', 'https://www.sanity.io/community/join')}`);
|
|
60
|
-
}
|
|
103
|
+
await logMcpConfirmation(mcpConfigured, output);
|
|
61
104
|
output.log('\n');
|
|
62
105
|
output.log(`Other helpful commands:`);
|
|
63
106
|
output.log(`npx sanity docs browse to open the documentation in a browser`);
|
|
64
107
|
output.log(`npx sanity dev to start the development server for your app`);
|
|
65
108
|
output.log(`npx sanity deploy to deploy your app`);
|
|
66
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* The post-init MCP confirmation shown by every template branch: which
|
|
112
|
+
* editors were configured during init and where to learn more. No-op when
|
|
113
|
+
* MCP setup was skipped or configured nothing.
|
|
114
|
+
*/ async function logMcpConfirmation(mcpConfigured, output) {
|
|
115
|
+
if (!mcpConfigured || mcpConfigured.length === 0) return;
|
|
116
|
+
const message = await getPostInitMCPPrompt(mcpConfigured);
|
|
117
|
+
output.log(`\n${message}`);
|
|
118
|
+
output.log(`\nLearn more: ${styleText('cyan', 'https://mcp.sanity.io')}`);
|
|
119
|
+
output.log(`\nHave feedback? Tell us in the community: ${styleText('cyan', 'https://www.sanity.io/community/join')}`);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Media Library is provisioned per organization, outside this app (in
|
|
123
|
+
* Manage). Without an active library the dashboard's media area comes up
|
|
124
|
+
* empty, so say so now — init is the one interactive, authenticated moment.
|
|
125
|
+
* API errors (offline, no access to the org, timeout) are swallowed: this is
|
|
126
|
+
* a hint, not a gate.
|
|
127
|
+
*
|
|
128
|
+
* @returns the organization's active libraries — empty also on lookup
|
|
129
|
+
* failure, so follow-up suggestions stay silent in the unknown case.
|
|
130
|
+
*/ export async function warnIfNoActiveMediaLibrary(organizationId, output) {
|
|
131
|
+
try {
|
|
132
|
+
const libraries = await getMediaLibrariesForOrganization(organizationId);
|
|
133
|
+
if (libraries.length > 0) return libraries;
|
|
134
|
+
} catch {
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
const manageUrl = `${isStaging() ? 'https://sanity.work' : 'https://www.sanity.io'}/manage`;
|
|
138
|
+
// No symbol or leading newline: output.warn already prefixes `Warning:`.
|
|
139
|
+
output.warn(`Organization ${organizationId} has no active Media Library, ` + `so the dashboard's media area will be empty. Media Library is provisioned per ` + `organization — enable it in Manage (${manageUrl}) or learn more at ` + `https://www.sanity.io/docs/media-library.`);
|
|
140
|
+
return [];
|
|
141
|
+
}
|
|
67
142
|
|
|
68
143
|
//# sourceMappingURL=initApp.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/init/initApp.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {type Output, type TelemetryUserProperties} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\nimport {type TelemetryTrace} from '@sanity/telemetry'\n\nimport {type InitStepResult} from '../../telemetry/init.telemetry.js'\nimport {getInstallCommand} from '../../util/packageManager/installPackages.js'\nimport {type EditorName} from '../mcp/editorConfigs.js'\nimport {InitError} from './initError.js'\nimport {getPostInitMCPPrompt} from './initHelpers.js'\nimport {type RepoInfo} from './remoteTemplate.js'\nimport {scaffoldAndInstall, selectTemplate} from './scaffoldTemplate.js'\nimport {type InitOptions} from './types.js'\n\nexport async function initApp({\n datasetName,\n defaults,\n mcpConfigured,\n options,\n organizationId,\n output,\n outputPath,\n projectId,\n remoteTemplateInfo,\n sluggedName,\n trace,\n workbench,\n workDir,\n}: {\n datasetName: string\n defaults: {projectName: string}\n mcpConfigured: EditorName[]\n options: InitOptions\n organizationId: string | undefined\n output: Output\n outputPath: string\n projectId: string\n remoteTemplateInfo: RepoInfo | undefined\n sluggedName: string\n trace: TelemetryTrace<TelemetryUserProperties, InitStepResult>\n workbench: boolean\n workDir: string\n}): Promise<void> {\n const {\n template: resolvedTemplate,\n templateName,\n useTypeScript,\n } = await selectTemplate({\n options,\n remoteTemplateInfo,\n trace,\n })\n\n if (!remoteTemplateInfo && !resolvedTemplate) {\n throw new InitError(`Template \"${templateName}\" not found`, 1)\n }\n\n const {pkgManager} = await scaffoldAndInstall({\n datasetName,\n defaults,\n displayName: '',\n options,\n organizationId,\n output,\n outputPath,\n projectId,\n remoteTemplateInfo,\n sluggedName,\n templateName,\n trace,\n useTypeScript,\n workbench,\n workDir,\n })\n\n const isCurrentDir = outputPath === workDir\n const goToProjectDir = `\\n(${styleText('cyan', `cd ${outputPath}`)} to navigate to your new project directory)`\n\n //output for custom apps here\n output.log(\n `${logSymbols.success} ${styleText(['green', 'bold'], 'Success!')} Your custom app has been scaffolded.`,\n )\n if (!isCurrentDir) output.log(goToProjectDir)\n if (!options.install) {\n output.log(`\\nRun ${styleText('cyan', getInstallCommand(pkgManager))} to install dependencies.`)\n }\n\n if (projectId && datasetName) {\n output.log(\n `\\nConfigured with project ${styleText('cyan', projectId)} and dataset ${styleText('cyan', datasetName)}.`,\n )\n output.log(\n 'Edit `src/App.tsx` to change these values or add more project / dataset pairs to your config.',\n )\n } else {\n output.log(\n `\\n${styleText('bold', 'Next')}, configure the project(s) and dataset(s) your app should work with in \\`src/App.tsx\\`.`,\n )\n }\n output.log('\\nRefer to our documentation for a walkthrough:')\n output.log(\n styleText(['blue', 'underline'], 'https://www.sanity.io/docs/app-sdk/sdk-configuration'),\n )\n if (mcpConfigured && mcpConfigured.length > 0) {\n const message = await getPostInitMCPPrompt(mcpConfigured)\n output.log(`\\n${message}`)\n output.log(`\\nLearn more: ${styleText('cyan', 'https://mcp.sanity.io')}`)\n output.log(\n `\\nHave feedback? Tell us in the community: ${styleText('cyan', 'https://www.sanity.io/community/join')}`,\n )\n }\n output.log('\\n')\n output.log(`Other helpful commands:`)\n output.log(`npx sanity docs browse to open the documentation in a browser`)\n output.log(`npx sanity dev to start the development server for your app`)\n output.log(`npx sanity deploy to deploy your app`)\n}\n"],"names":["styleText","logSymbols","getInstallCommand","InitError","getPostInitMCPPrompt","scaffoldAndInstall","selectTemplate","initApp","datasetName","defaults","mcpConfigured","options","organizationId","output","outputPath","projectId","remoteTemplateInfo","sluggedName","trace","workbench","workDir","template","resolvedTemplate","templateName","useTypeScript","pkgManager","displayName","isCurrentDir","goToProjectDir","log","success","install","length","message"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAGnC,SAAQC,UAAU,QAAO,sBAAqB;AAI9C,SAAQC,iBAAiB,QAAO,+CAA8C;AAE9E,SAAQC,SAAS,QAAO,iBAAgB;AACxC,SAAQC,oBAAoB,QAAO,mBAAkB;AAErD,SAAQC,kBAAkB,EAAEC,cAAc,QAAO,wBAAuB;AAGxE,OAAO,eAAeC,QAAQ,EAC5BC,WAAW,EACXC,QAAQ,EACRC,aAAa,EACbC,OAAO,EACPC,cAAc,EACdC,MAAM,EACNC,UAAU,EACVC,SAAS,EACTC,kBAAkB,EAClBC,WAAW,EACXC,KAAK,EACLC,SAAS,EACTC,OAAO,EAeR;IACC,MAAM,EACJC,UAAUC,gBAAgB,EAC1BC,YAAY,EACZC,aAAa,EACd,GAAG,MAAMlB,eAAe;QACvBK;QACAK;QACAE;IACF;IAEA,IAAI,CAACF,sBAAsB,CAACM,kBAAkB;QAC5C,MAAM,IAAInB,UAAU,CAAC,UAAU,EAAEoB,aAAa,WAAW,CAAC,EAAE;IAC9D;IAEA,MAAM,EAACE,UAAU,EAAC,GAAG,MAAMpB,mBAAmB;QAC5CG;QACAC;QACAiB,aAAa;QACbf;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAM;QACAL;QACAM;QACAL;QACAC;IACF;IAEA,MAAMO,eAAeb,eAAeM;IACpC,MAAMQ,iBAAiB,CAAC,GAAG,EAAE5B,UAAU,QAAQ,CAAC,GAAG,EAAEc,YAAY,EAAE,2CAA2C,CAAC;IAE/G,6BAA6B;IAC7BD,OAAOgB,GAAG,CACR,GAAG5B,WAAW6B,OAAO,CAAC,CAAC,EAAE9B,UAAU;QAAC;QAAS;KAAO,EAAE,YAAY,qCAAqC,CAAC;IAE1G,IAAI,CAAC2B,cAAcd,OAAOgB,GAAG,CAACD;IAC9B,IAAI,CAACjB,QAAQoB,OAAO,EAAE;QACpBlB,OAAOgB,GAAG,CAAC,CAAC,MAAM,EAAE7B,UAAU,QAAQE,kBAAkBuB,aAAa,yBAAyB,CAAC;IACjG;IAEA,IAAIV,aAAaP,aAAa;QAC5BK,OAAOgB,GAAG,CACR,CAAC,0BAA0B,EAAE7B,UAAU,QAAQe,WAAW,aAAa,EAAEf,UAAU,QAAQQ,aAAa,CAAC,CAAC;QAE5GK,OAAOgB,GAAG,CACR;IAEJ,OAAO;QACLhB,OAAOgB,GAAG,CACR,CAAC,EAAE,EAAE7B,UAAU,QAAQ,QAAQ,uFAAuF,CAAC;IAE3H;IACAa,OAAOgB,GAAG,CAAC;IACXhB,OAAOgB,GAAG,CACR7B,UAAU;QAAC;QAAQ;KAAY,EAAE;IAEnC,IAAIU,iBAAiBA,cAAcsB,MAAM,GAAG,GAAG;QAC7C,MAAMC,UAAU,MAAM7B,qBAAqBM;QAC3CG,OAAOgB,GAAG,CAAC,CAAC,EAAE,EAAEI,SAAS;QACzBpB,OAAOgB,GAAG,CAAC,CAAC,cAAc,EAAE7B,UAAU,QAAQ,0BAA0B;QACxEa,OAAOgB,GAAG,CACR,CAAC,2CAA2C,EAAE7B,UAAU,QAAQ,yCAAyC;IAE7G;IACAa,OAAOgB,GAAG,CAAC;IACXhB,OAAOgB,GAAG,CAAC,CAAC,uBAAuB,CAAC;IACpChB,OAAOgB,GAAG,CAAC,CAAC,iEAAiE,CAAC;IAC9EhB,OAAOgB,GAAG,CAAC,CAAC,uEAAuE,CAAC;IACpFhB,OAAOgB,GAAG,CAAC,CAAC,6CAA6C,CAAC;AAC5D"}
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/init/initApp.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {type Output, type TelemetryUserProperties} from '@sanity/cli-core'\nimport {isStaging} from '@sanity/cli-core/util'\nimport {logSymbols} from '@sanity/cli-core/ux'\nimport {type TelemetryTrace} from '@sanity/telemetry'\n\nimport {getMediaLibrariesForOrganization, type MediaLibrary} from '../../services/mediaLibraries.js'\nimport {type InitStepResult} from '../../telemetry/init.telemetry.js'\nimport {getInstallCommand} from '../../util/packageManager/installPackages.js'\nimport {type EditorName} from '../mcp/editorConfigs.js'\nimport {determineMediaLibraryTemplate} from './determineMediaLibraryTemplate.js'\nimport {InitError} from './initError.js'\nimport {getPostInitMCPPrompt} from './initHelpers.js'\nimport {offerAspectPull} from './offerAspectPull.js'\nimport {type RepoInfo} from './remoteTemplate.js'\nimport {scaffoldAndInstall, selectTemplate} from './scaffoldTemplate.js'\nimport {type InitOptions} from './types.js'\n\nexport async function initApp({\n datasetName,\n defaults,\n mcpConfigured,\n options,\n organizationId,\n output,\n outputPath,\n projectId,\n remoteTemplateInfo,\n sluggedName,\n trace,\n workbench,\n workDir,\n}: {\n datasetName: string\n defaults: {projectName: string}\n mcpConfigured: EditorName[]\n options: InitOptions\n organizationId: string | undefined\n output: Output\n outputPath: string\n projectId: string\n remoteTemplateInfo: RepoInfo | undefined\n sluggedName: string\n trace: TelemetryTrace<TelemetryUserProperties, InitStepResult>\n workbench: boolean\n workDir: string\n}): Promise<void> {\n const {\n template: resolvedTemplate,\n templateName,\n useTypeScript,\n } = await selectTemplate({\n options,\n remoteTemplateInfo,\n trace,\n })\n\n if (!remoteTemplateInfo && !resolvedTemplate) {\n throw new InitError(`Template \"${templateName}\" not found`, 1)\n }\n\n const {pkgManager} = await scaffoldAndInstall({\n datasetName,\n defaults,\n displayName: '',\n options,\n organizationId,\n output,\n outputPath,\n projectId,\n remoteTemplateInfo,\n sluggedName,\n templateName,\n trace,\n useTypeScript,\n workbench,\n workDir,\n })\n\n const isCurrentDir = outputPath === workDir\n const goToProjectDir = `\\n(${styleText('cyan', `cd ${outputPath}`)} to navigate to your new project directory)`\n\n if (determineMediaLibraryTemplate(templateName)) {\n output.log(\n `${logSymbols.success} ${styleText(['green', 'bold'], 'Success!')} Your Media Library config app has been scaffolded.`,\n )\n if (!isCurrentDir) output.log(goToProjectDir)\n if (!options.install) {\n output.log(\n `\\nRun ${styleText('cyan', getInstallCommand(pkgManager))} to install dependencies.`,\n )\n }\n let libraries: MediaLibrary[] = []\n if (organizationId) {\n output.log(`\\nConfigured for organization ${styleText('cyan', organizationId)}.`)\n libraries = await warnIfNoActiveMediaLibrary(organizationId, output)\n }\n\n // The deploy mirrors config into the library and deletes stored aspects\n // the config does not declare, so an org that already defines aspects is\n // offered a pull now — while init is interactive and authenticated. Only\n // with exactly one active library; picking one is pull-aspects territory.\n let pulledAspects = false\n if (libraries.length === 1 && !options.unattended) {\n output.log('')\n pulledAspects = await offerAspectPull({library: libraries[0], output, outputPath})\n }\n\n output.log(\n '\\nField definitions live in `src/fields/` and are registered in `sanity.cli.ts` — see the README for the authoring rules.',\n )\n if (libraries.length > 0 && !pulledAspects) {\n output.log(\n `\\nAlready defining aspects in your Media Library? Generate field modules from them with ${styleText('cyan', 'npx sanity media pull-aspects')}.`,\n )\n }\n output.log('\\nRefer to our documentation for a walkthrough:')\n output.log(styleText(['blue', 'underline'], 'https://www.sanity.io/docs/media-library'))\n await logMcpConfirmation(mcpConfigured, output)\n output.log('\\n')\n output.log(`Other helpful commands:`)\n output.log(`npx sanity docs browse to open the documentation in a browser`)\n output.log(`npx sanity dev to serve your fields to the Media Library live`)\n output.log(`npx sanity deploy to deploy the config to your organization`)\n return\n }\n\n //output for custom apps here\n output.log(\n `${logSymbols.success} ${styleText(['green', 'bold'], 'Success!')} Your custom app has been scaffolded.`,\n )\n if (!isCurrentDir) output.log(goToProjectDir)\n if (!options.install) {\n output.log(`\\nRun ${styleText('cyan', getInstallCommand(pkgManager))} to install dependencies.`)\n }\n\n if (projectId && datasetName) {\n output.log(\n `\\nConfigured with project ${styleText('cyan', projectId)} and dataset ${styleText('cyan', datasetName)}.`,\n )\n output.log(\n 'Edit `src/App.tsx` to change these values or add more project / dataset pairs to your config.',\n )\n } else {\n output.log(\n `\\n${styleText('bold', 'Next')}, configure the project(s) and dataset(s) your app should work with in \\`src/App.tsx\\`.`,\n )\n }\n output.log('\\nRefer to our documentation for a walkthrough:')\n output.log(\n styleText(['blue', 'underline'], 'https://www.sanity.io/docs/app-sdk/sdk-configuration'),\n )\n await logMcpConfirmation(mcpConfigured, output)\n output.log('\\n')\n output.log(`Other helpful commands:`)\n output.log(`npx sanity docs browse to open the documentation in a browser`)\n output.log(`npx sanity dev to start the development server for your app`)\n output.log(`npx sanity deploy to deploy your app`)\n}\n\n/**\n * The post-init MCP confirmation shown by every template branch: which\n * editors were configured during init and where to learn more. No-op when\n * MCP setup was skipped or configured nothing.\n */\nasync function logMcpConfirmation(mcpConfigured: EditorName[], output: Output): Promise<void> {\n if (!mcpConfigured || mcpConfigured.length === 0) return\n const message = await getPostInitMCPPrompt(mcpConfigured)\n output.log(`\\n${message}`)\n output.log(`\\nLearn more: ${styleText('cyan', 'https://mcp.sanity.io')}`)\n output.log(\n `\\nHave feedback? Tell us in the community: ${styleText('cyan', 'https://www.sanity.io/community/join')}`,\n )\n}\n\n/**\n * Media Library is provisioned per organization, outside this app (in\n * Manage). Without an active library the dashboard's media area comes up\n * empty, so say so now — init is the one interactive, authenticated moment.\n * API errors (offline, no access to the org, timeout) are swallowed: this is\n * a hint, not a gate.\n *\n * @returns the organization's active libraries — empty also on lookup\n * failure, so follow-up suggestions stay silent in the unknown case.\n */\nexport async function warnIfNoActiveMediaLibrary(\n organizationId: string,\n output: Output,\n): Promise<MediaLibrary[]> {\n try {\n const libraries = await getMediaLibrariesForOrganization(organizationId)\n if (libraries.length > 0) return libraries\n } catch {\n return []\n }\n\n const manageUrl = `${isStaging() ? 'https://sanity.work' : 'https://www.sanity.io'}/manage`\n // No symbol or leading newline: output.warn already prefixes `Warning:`.\n output.warn(\n `Organization ${organizationId} has no active Media Library, ` +\n `so the dashboard's media area will be empty. Media Library is provisioned per ` +\n `organization — enable it in Manage (${manageUrl}) or learn more at ` +\n `https://www.sanity.io/docs/media-library.`,\n )\n return []\n}\n"],"names":["styleText","isStaging","logSymbols","getMediaLibrariesForOrganization","getInstallCommand","determineMediaLibraryTemplate","InitError","getPostInitMCPPrompt","offerAspectPull","scaffoldAndInstall","selectTemplate","initApp","datasetName","defaults","mcpConfigured","options","organizationId","output","outputPath","projectId","remoteTemplateInfo","sluggedName","trace","workbench","workDir","template","resolvedTemplate","templateName","useTypeScript","pkgManager","displayName","isCurrentDir","goToProjectDir","log","success","install","libraries","warnIfNoActiveMediaLibrary","pulledAspects","length","unattended","library","logMcpConfirmation","message","manageUrl","warn"],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { confirm, logSymbols, spinner } from '@sanity/cli-core/ux';
|
|
4
|
+
import { getAspects } from '../../services/mediaLibraries.js';
|
|
5
|
+
import { pluralize } from '../../util/pluralize.js';
|
|
6
|
+
import { replaceFieldEntries } from '../media/cliConfigFields.js';
|
|
7
|
+
import { convertAspectDocuments, formatFieldEntries } from '../media/pullAspects.js';
|
|
8
|
+
/** Where the scaffold keeps field modules — the template's `fields[*].src` dir. */ const FIELDS_DIR = path.join('src', 'fields');
|
|
9
|
+
/**
|
|
10
|
+
* Offer to seed the freshly scaffolded config app from the organization's
|
|
11
|
+
* existing aspects. Deploying the config mirrors it into the library —
|
|
12
|
+
* stored aspects the config does not declare get deleted — so a scaffold
|
|
13
|
+
* that starts from the example fields instead of the real ones is a loaded
|
|
14
|
+
* footgun. Pulling at init time defuses it while we are still interactive
|
|
15
|
+
* and authenticated.
|
|
16
|
+
*
|
|
17
|
+
* Only offered when the organization has exactly one active library (no
|
|
18
|
+
* prompt-stacking during init); lookups and conversion errors degrade to a
|
|
19
|
+
* silent skip — the scaffold is complete without this, and
|
|
20
|
+
* `sanity media pull-aspects` covers it later.
|
|
21
|
+
*
|
|
22
|
+
* @returns `true` when the example fields were replaced by pulled modules.
|
|
23
|
+
*/ export async function offerAspectPull({ library, output, outputPath }) {
|
|
24
|
+
const spin = spinner('Checking the media library for existing aspects').start();
|
|
25
|
+
let documents;
|
|
26
|
+
try {
|
|
27
|
+
documents = await getAspects(library.id);
|
|
28
|
+
} catch {
|
|
29
|
+
return false;
|
|
30
|
+
} finally{
|
|
31
|
+
spin.stop();
|
|
32
|
+
}
|
|
33
|
+
if (documents.length === 0) return false;
|
|
34
|
+
const { modules, skipped } = convertAspectDocuments(documents);
|
|
35
|
+
if (modules.length === 0) return false;
|
|
36
|
+
const shouldPull = await confirm({
|
|
37
|
+
default: true,
|
|
38
|
+
message: `Media library ${library.id} already defines ${modules.length} ${pluralize('aspect', modules.length)}. ` + 'Generate field modules from them (replaces the example fields)?'
|
|
39
|
+
});
|
|
40
|
+
if (!shouldPull) return false;
|
|
41
|
+
if (skipped.length > 0) {
|
|
42
|
+
for (const aspect of skipped){
|
|
43
|
+
const errors = aspect.validationErrors.flatMap((group)=>group.map(({ message })=>message));
|
|
44
|
+
output.warn(`Skipped aspect ${aspect.id}: ${[
|
|
45
|
+
...aspect.reasons,
|
|
46
|
+
...errors
|
|
47
|
+
].join('; ')}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// The config edit is resolved before anything touches the disk: bailing
|
|
51
|
+
// after deleting the example modules would leave the scaffold declaring
|
|
52
|
+
// files that no longer exist. On bail the scaffold stays a consistent,
|
|
53
|
+
// working pair (example fields + their declarations), and the caller's
|
|
54
|
+
// `!pulledAspects` branch already points at `sanity media pull-aspects`.
|
|
55
|
+
// The template is `typescriptOnly`, so the scaffold always writes this file.
|
|
56
|
+
const configPath = path.join(outputPath, 'sanity.cli.ts');
|
|
57
|
+
const entryLines = formatFieldEntries(modules, FIELDS_DIR.replaceAll(path.sep, '/')).split('\n');
|
|
58
|
+
const result = replaceFieldEntries(await readFile(configPath, 'utf8'), entryLines);
|
|
59
|
+
if (!result.ok) {
|
|
60
|
+
output.warn(`Could not seed the config from the existing aspects (${result.reason}) — the example fields are kept.`);
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
// The example modules make way for the real ones: entries are replaced
|
|
64
|
+
// wholesale in the config, so files left behind would just be orphans.
|
|
65
|
+
const fieldsDir = path.join(outputPath, FIELDS_DIR);
|
|
66
|
+
await rm(fieldsDir, {
|
|
67
|
+
force: true,
|
|
68
|
+
recursive: true
|
|
69
|
+
});
|
|
70
|
+
await mkdir(fieldsDir, {
|
|
71
|
+
recursive: true
|
|
72
|
+
});
|
|
73
|
+
for (const module of modules){
|
|
74
|
+
await writeFile(path.join(fieldsDir, module.filename), module.source);
|
|
75
|
+
}
|
|
76
|
+
await writeFile(configPath, result.updated);
|
|
77
|
+
output.log(`${logSymbols.success} Generated ${modules.length} field ${pluralize('module', modules.length)} from your media library and declared them in sanity.cli.ts`);
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
//# sourceMappingURL=offerAspectPull.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/init/offerAspectPull.ts"],"sourcesContent":["import {mkdir, readFile, rm, writeFile} from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {type Output} from '@sanity/cli-core'\nimport {confirm, logSymbols, spinner} from '@sanity/cli-core/ux'\n\nimport {getAspects, type MediaLibrary} from '../../services/mediaLibraries.js'\nimport {pluralize} from '../../util/pluralize.js'\nimport {replaceFieldEntries} from '../media/cliConfigFields.js'\nimport {\n convertAspectDocuments,\n formatFieldEntries,\n type PullableAspectDocument,\n} from '../media/pullAspects.js'\n\n/** Where the scaffold keeps field modules — the template's `fields[*].src` dir. */\nconst FIELDS_DIR = path.join('src', 'fields')\n\n/**\n * Offer to seed the freshly scaffolded config app from the organization's\n * existing aspects. Deploying the config mirrors it into the library —\n * stored aspects the config does not declare get deleted — so a scaffold\n * that starts from the example fields instead of the real ones is a loaded\n * footgun. Pulling at init time defuses it while we are still interactive\n * and authenticated.\n *\n * Only offered when the organization has exactly one active library (no\n * prompt-stacking during init); lookups and conversion errors degrade to a\n * silent skip — the scaffold is complete without this, and\n * `sanity media pull-aspects` covers it later.\n *\n * @returns `true` when the example fields were replaced by pulled modules.\n */\nexport async function offerAspectPull({\n library,\n output,\n outputPath,\n}: {\n library: MediaLibrary\n output: Output\n outputPath: string\n}): Promise<boolean> {\n const spin = spinner('Checking the media library for existing aspects').start()\n let documents: PullableAspectDocument[]\n try {\n documents = await getAspects(library.id)\n } catch {\n return false\n } finally {\n spin.stop()\n }\n if (documents.length === 0) return false\n\n const {modules, skipped} = convertAspectDocuments(documents)\n if (modules.length === 0) return false\n\n const shouldPull = await confirm({\n default: true,\n message:\n `Media library ${library.id} already defines ${modules.length} ${pluralize('aspect', modules.length)}. ` +\n 'Generate field modules from them (replaces the example fields)?',\n })\n if (!shouldPull) return false\n\n if (skipped.length > 0) {\n for (const aspect of skipped) {\n const errors = aspect.validationErrors.flatMap((group) => group.map(({message}) => message))\n output.warn(`Skipped aspect ${aspect.id}: ${[...aspect.reasons, ...errors].join('; ')}`)\n }\n }\n\n // The config edit is resolved before anything touches the disk: bailing\n // after deleting the example modules would leave the scaffold declaring\n // files that no longer exist. On bail the scaffold stays a consistent,\n // working pair (example fields + their declarations), and the caller's\n // `!pulledAspects` branch already points at `sanity media pull-aspects`.\n // The template is `typescriptOnly`, so the scaffold always writes this file.\n const configPath = path.join(outputPath, 'sanity.cli.ts')\n const entryLines = formatFieldEntries(modules, FIELDS_DIR.replaceAll(path.sep, '/')).split('\\n')\n\n const result = replaceFieldEntries(await readFile(configPath, 'utf8'), entryLines)\n if (!result.ok) {\n output.warn(\n `Could not seed the config from the existing aspects (${result.reason}) — the example fields are kept.`,\n )\n return false\n }\n\n // The example modules make way for the real ones: entries are replaced\n // wholesale in the config, so files left behind would just be orphans.\n const fieldsDir = path.join(outputPath, FIELDS_DIR)\n await rm(fieldsDir, {force: true, recursive: true})\n await mkdir(fieldsDir, {recursive: true})\n for (const module of modules) {\n await writeFile(path.join(fieldsDir, module.filename), module.source)\n }\n\n await writeFile(configPath, result.updated)\n output.log(\n `${logSymbols.success} Generated ${modules.length} field ${pluralize('module', modules.length)} from your media library and declared them in sanity.cli.ts`,\n )\n return true\n}\n"],"names":["mkdir","readFile","rm","writeFile","path","confirm","logSymbols","spinner","getAspects","pluralize","replaceFieldEntries","convertAspectDocuments","formatFieldEntries","FIELDS_DIR","join","offerAspectPull","library","output","outputPath","spin","start","documents","id","stop","length","modules","skipped","shouldPull","default","message","aspect","errors","validationErrors","flatMap","group","map","warn","reasons","configPath","entryLines","replaceAll","sep","split","result","ok","reason","fieldsDir","force","recursive","module","filename","source","updated","log","success"],"mappings":"AAAA,SAAQA,KAAK,EAAEC,QAAQ,EAAEC,EAAE,EAAEC,SAAS,QAAO,mBAAkB;AAC/D,OAAOC,UAAU,YAAW;AAG5B,SAAQC,OAAO,EAAEC,UAAU,EAAEC,OAAO,QAAO,sBAAqB;AAEhE,SAAQC,UAAU,QAA0B,mCAAkC;AAC9E,SAAQC,SAAS,QAAO,0BAAyB;AACjD,SAAQC,mBAAmB,QAAO,8BAA6B;AAC/D,SACEC,sBAAsB,EACtBC,kBAAkB,QAEb,0BAAyB;AAEhC,iFAAiF,GACjF,MAAMC,aAAaT,KAAKU,IAAI,CAAC,OAAO;AAEpC;;;;;;;;;;;;;;CAcC,GACD,OAAO,eAAeC,gBAAgB,EACpCC,OAAO,EACPC,MAAM,EACNC,UAAU,EAKX;IACC,MAAMC,OAAOZ,QAAQ,mDAAmDa,KAAK;IAC7E,IAAIC;IACJ,IAAI;QACFA,YAAY,MAAMb,WAAWQ,QAAQM,EAAE;IACzC,EAAE,OAAM;QACN,OAAO;IACT,SAAU;QACRH,KAAKI,IAAI;IACX;IACA,IAAIF,UAAUG,MAAM,KAAK,GAAG,OAAO;IAEnC,MAAM,EAACC,OAAO,EAAEC,OAAO,EAAC,GAAGf,uBAAuBU;IAClD,IAAII,QAAQD,MAAM,KAAK,GAAG,OAAO;IAEjC,MAAMG,aAAa,MAAMtB,QAAQ;QAC/BuB,SAAS;QACTC,SACE,CAAC,cAAc,EAAEb,QAAQM,EAAE,CAAC,iBAAiB,EAAEG,QAAQD,MAAM,CAAC,CAAC,EAAEf,UAAU,UAAUgB,QAAQD,MAAM,EAAE,EAAE,CAAC,GACxG;IACJ;IACA,IAAI,CAACG,YAAY,OAAO;IAExB,IAAID,QAAQF,MAAM,GAAG,GAAG;QACtB,KAAK,MAAMM,UAAUJ,QAAS;YAC5B,MAAMK,SAASD,OAAOE,gBAAgB,CAACC,OAAO,CAAC,CAACC,QAAUA,MAAMC,GAAG,CAAC,CAAC,EAACN,OAAO,EAAC,GAAKA;YACnFZ,OAAOmB,IAAI,CAAC,CAAC,eAAe,EAAEN,OAAOR,EAAE,CAAC,EAAE,EAAE;mBAAIQ,OAAOO,OAAO;mBAAKN;aAAO,CAACjB,IAAI,CAAC,OAAO;QACzF;IACF;IAEA,wEAAwE;IACxE,wEAAwE;IACxE,uEAAuE;IACvE,uEAAuE;IACvE,yEAAyE;IACzE,6EAA6E;IAC7E,MAAMwB,aAAalC,KAAKU,IAAI,CAACI,YAAY;IACzC,MAAMqB,aAAa3B,mBAAmBa,SAASZ,WAAW2B,UAAU,CAACpC,KAAKqC,GAAG,EAAE,MAAMC,KAAK,CAAC;IAE3F,MAAMC,SAASjC,oBAAoB,MAAMT,SAASqC,YAAY,SAASC;IACvE,IAAI,CAACI,OAAOC,EAAE,EAAE;QACd3B,OAAOmB,IAAI,CACT,CAAC,qDAAqD,EAAEO,OAAOE,MAAM,CAAC,gCAAgC,CAAC;QAEzG,OAAO;IACT;IAEA,uEAAuE;IACvE,uEAAuE;IACvE,MAAMC,YAAY1C,KAAKU,IAAI,CAACI,YAAYL;IACxC,MAAMX,GAAG4C,WAAW;QAACC,OAAO;QAAMC,WAAW;IAAI;IACjD,MAAMhD,MAAM8C,WAAW;QAACE,WAAW;IAAI;IACvC,KAAK,MAAMC,UAAUxB,QAAS;QAC5B,MAAMtB,UAAUC,KAAKU,IAAI,CAACgC,WAAWG,OAAOC,QAAQ,GAAGD,OAAOE,MAAM;IACtE;IAEA,MAAMhD,UAAUmC,YAAYK,OAAOS,OAAO;IAC1CnC,OAAOoC,GAAG,CACR,GAAG/C,WAAWgD,OAAO,CAAC,WAAW,EAAE7B,QAAQD,MAAM,CAAC,OAAO,EAAEf,UAAU,UAAUgB,QAAQD,MAAM,EAAE,2DAA2D,CAAC;IAE7J,OAAO;AACT"}
|
|
@@ -6,11 +6,13 @@ import { getOrCreateProject } from './getOrCreateProject.js';
|
|
|
6
6
|
import { promptForAppTemplateSetup } from './promptForAppTemplateSetup.js';
|
|
7
7
|
import { promptUserForOrganization } from './promptUserForOrganization.js';
|
|
8
8
|
const debug = subdebug('init');
|
|
9
|
-
export async function getProjectDetails({ coupon, dataset, datasetDefault, isAppTemplate, newProject, organization, output, planId, project, showDefaultConfigPrompt, trace, unattended, user, visibility }) {
|
|
9
|
+
export async function getProjectDetails({ coupon, dataset, datasetDefault, isAppTemplate, isMediaLibraryTemplate = false, newProject, organization, output, planId, project, showDefaultConfigPrompt, trace, unattended, user, visibility }) {
|
|
10
10
|
if (isAppTemplate) {
|
|
11
11
|
const hasProjectFlag = Boolean(project || newProject);
|
|
12
12
|
let appOrganizationId = organization;
|
|
13
|
-
|
|
13
|
+
// A media-library config is organization-only, so the org is always
|
|
14
|
+
// resolved here — project flags can't stand in for it.
|
|
15
|
+
if (!appOrganizationId && (isMediaLibraryTemplate || !hasProjectFlag)) {
|
|
14
16
|
let organizations;
|
|
15
17
|
try {
|
|
16
18
|
organizations = await listOrganizations();
|
|
@@ -24,6 +26,27 @@ export async function getProjectDetails({ coupon, dataset, datasetDefault, isApp
|
|
|
24
26
|
user
|
|
25
27
|
});
|
|
26
28
|
}
|
|
29
|
+
// The media-library config scaffold records only `app.organizationId`, so
|
|
30
|
+
// the project/dataset setup below would create or select resources the
|
|
31
|
+
// template throws away — and picking a project from another organization
|
|
32
|
+
// would silently override the chosen org. Skip it entirely.
|
|
33
|
+
if (isMediaLibraryTemplate) {
|
|
34
|
+
if (hasProjectFlag) {
|
|
35
|
+
output.warn('Project flags are ignored for the media-library-config template — it only records the organization.');
|
|
36
|
+
}
|
|
37
|
+
trace.log({
|
|
38
|
+
datasetName: '',
|
|
39
|
+
selectedOption: 'skip',
|
|
40
|
+
step: 'createOrSelectDataset'
|
|
41
|
+
});
|
|
42
|
+
return {
|
|
43
|
+
datasetName: '',
|
|
44
|
+
displayName: '',
|
|
45
|
+
isFirstProject: false,
|
|
46
|
+
organizationId: appOrganizationId,
|
|
47
|
+
projectId: ''
|
|
48
|
+
};
|
|
49
|
+
}
|
|
27
50
|
const { datasetName: appDatasetName, displayName: appDisplayName, organizationId: resolvedOrganizationId, projectId: appProjectId } = await promptForAppTemplateSetup({
|
|
28
51
|
coupon,
|
|
29
52
|
dataset,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/actions/init/project/getProjectDetails.ts"],"sourcesContent":["import {type SanityOrgUser, subdebug, type TelemetryUserProperties} from '@sanity/cli-core'\nimport {type TelemetryTrace} from '@sanity/telemetry'\n\nimport {listOrganizations, type ProjectOrganization} from '../../../services/organizations.js'\nimport {type InitStepResult} from '../../../telemetry/init.telemetry.js'\nimport {InitError} from '../initError.js'\nimport {type InitContext} from '../types.js'\nimport {getOrCreateDataset} from './getOrCreateDataset.js'\nimport {getOrCreateProject} from './getOrCreateProject.js'\nimport {promptForAppTemplateSetup} from './promptForAppTemplateSetup.js'\nimport {promptUserForOrganization} from './promptUserForOrganization.js'\n\nconst debug = subdebug('init')\n\nexport async function getProjectDetails({\n coupon,\n dataset,\n datasetDefault,\n isAppTemplate,\n newProject,\n organization,\n output,\n planId,\n project,\n showDefaultConfigPrompt,\n trace,\n unattended,\n user,\n visibility,\n}: {\n coupon: string | undefined\n dataset: string | undefined\n datasetDefault: boolean\n isAppTemplate: boolean\n newProject: string | undefined\n organization: string | undefined\n output: InitContext['output']\n planId: string | undefined\n project: string | undefined\n showDefaultConfigPrompt: boolean\n trace: TelemetryTrace<TelemetryUserProperties, InitStepResult>\n unattended: boolean\n user: SanityOrgUser\n visibility: 'private' | 'public' | undefined\n}): Promise<{\n datasetName: string\n displayName: string\n isFirstProject: boolean\n organizationId?: string\n projectId: string\n schemaUrl?: string\n}> {\n if (isAppTemplate) {\n const hasProjectFlag = Boolean(project || newProject)\n let appOrganizationId: string | undefined = organization\n if (!appOrganizationId && !hasProjectFlag) {\n let organizations: ProjectOrganization[]\n try {\n organizations = await listOrganizations()\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err)\n throw new InitError(`Failed to communicate with the Sanity API:\\n${message}`, 1)\n }\n appOrganizationId = await promptUserForOrganization({\n isAppTemplate: true,\n organizations,\n user,\n })\n }\n\n const {\n datasetName: appDatasetName,\n displayName: appDisplayName,\n organizationId: resolvedOrganizationId,\n projectId: appProjectId,\n } = await promptForAppTemplateSetup({\n coupon,\n dataset,\n datasetDefault,\n newProject,\n organization,\n organizationId: appOrganizationId,\n output,\n planId,\n project,\n trace,\n unattended,\n user,\n visibility,\n })\n\n return {\n datasetName: appDatasetName,\n displayName: appDisplayName,\n isFirstProject: false,\n organizationId: resolvedOrganizationId ?? appOrganizationId,\n projectId: appProjectId,\n }\n }\n\n debug('Prompting user to select or create a project')\n const projectResult = await getOrCreateProject({\n coupon,\n newProject,\n organization,\n planId,\n project,\n unattended,\n user,\n })\n debug(`Project with name ${projectResult.displayName} selected`)\n\n debug('Prompting user to select or create a dataset')\n const datasetResult = await getOrCreateDataset({\n dataset,\n defaultConfig: datasetDefault || undefined,\n displayName: projectResult.displayName,\n output,\n projectId: projectResult.projectId,\n showDefaultConfigPrompt,\n unattended,\n visibility,\n })\n debug(`Dataset with name ${datasetResult.datasetName} selected`)\n\n trace.log({\n datasetName: datasetResult.datasetName,\n selectedOption: datasetResult.userAction,\n step: 'createOrSelectDataset',\n visibility,\n })\n\n return {\n datasetName: datasetResult.datasetName,\n displayName: projectResult.displayName,\n isFirstProject: projectResult.isFirstProject,\n organizationId: projectResult.organizationId,\n projectId: projectResult.projectId,\n }\n}\n"],"names":["subdebug","listOrganizations","InitError","getOrCreateDataset","getOrCreateProject","promptForAppTemplateSetup","promptUserForOrganization","debug","getProjectDetails","coupon","dataset","datasetDefault","isAppTemplate","newProject","organization","output","planId","project","showDefaultConfigPrompt","trace","unattended","user","visibility","hasProjectFlag","Boolean","appOrganizationId","organizations","err","message","Error","String","datasetName","
|
|
1
|
+
{"version":3,"sources":["../../../../src/actions/init/project/getProjectDetails.ts"],"sourcesContent":["import {type SanityOrgUser, subdebug, type TelemetryUserProperties} from '@sanity/cli-core'\nimport {type TelemetryTrace} from '@sanity/telemetry'\n\nimport {listOrganizations, type ProjectOrganization} from '../../../services/organizations.js'\nimport {type InitStepResult} from '../../../telemetry/init.telemetry.js'\nimport {InitError} from '../initError.js'\nimport {type InitContext} from '../types.js'\nimport {getOrCreateDataset} from './getOrCreateDataset.js'\nimport {getOrCreateProject} from './getOrCreateProject.js'\nimport {promptForAppTemplateSetup} from './promptForAppTemplateSetup.js'\nimport {promptUserForOrganization} from './promptUserForOrganization.js'\n\nconst debug = subdebug('init')\n\nexport async function getProjectDetails({\n coupon,\n dataset,\n datasetDefault,\n isAppTemplate,\n isMediaLibraryTemplate = false,\n newProject,\n organization,\n output,\n planId,\n project,\n showDefaultConfigPrompt,\n trace,\n unattended,\n user,\n visibility,\n}: {\n coupon: string | undefined\n dataset: string | undefined\n datasetDefault: boolean\n isAppTemplate: boolean\n isMediaLibraryTemplate?: boolean\n newProject: string | undefined\n organization: string | undefined\n output: InitContext['output']\n planId: string | undefined\n project: string | undefined\n showDefaultConfigPrompt: boolean\n trace: TelemetryTrace<TelemetryUserProperties, InitStepResult>\n unattended: boolean\n user: SanityOrgUser\n visibility: 'private' | 'public' | undefined\n}): Promise<{\n datasetName: string\n displayName: string\n isFirstProject: boolean\n organizationId?: string\n projectId: string\n schemaUrl?: string\n}> {\n if (isAppTemplate) {\n const hasProjectFlag = Boolean(project || newProject)\n let appOrganizationId: string | undefined = organization\n // A media-library config is organization-only, so the org is always\n // resolved here — project flags can't stand in for it.\n if (!appOrganizationId && (isMediaLibraryTemplate || !hasProjectFlag)) {\n let organizations: ProjectOrganization[]\n try {\n organizations = await listOrganizations()\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err)\n throw new InitError(`Failed to communicate with the Sanity API:\\n${message}`, 1)\n }\n appOrganizationId = await promptUserForOrganization({\n isAppTemplate: true,\n organizations,\n user,\n })\n }\n\n // The media-library config scaffold records only `app.organizationId`, so\n // the project/dataset setup below would create or select resources the\n // template throws away — and picking a project from another organization\n // would silently override the chosen org. Skip it entirely.\n if (isMediaLibraryTemplate) {\n if (hasProjectFlag) {\n output.warn(\n 'Project flags are ignored for the media-library-config template — it only records the organization.',\n )\n }\n trace.log({datasetName: '', selectedOption: 'skip', step: 'createOrSelectDataset'})\n return {\n datasetName: '',\n displayName: '',\n isFirstProject: false,\n organizationId: appOrganizationId,\n projectId: '',\n }\n }\n\n const {\n datasetName: appDatasetName,\n displayName: appDisplayName,\n organizationId: resolvedOrganizationId,\n projectId: appProjectId,\n } = await promptForAppTemplateSetup({\n coupon,\n dataset,\n datasetDefault,\n newProject,\n organization,\n organizationId: appOrganizationId,\n output,\n planId,\n project,\n trace,\n unattended,\n user,\n visibility,\n })\n\n return {\n datasetName: appDatasetName,\n displayName: appDisplayName,\n isFirstProject: false,\n organizationId: resolvedOrganizationId ?? appOrganizationId,\n projectId: appProjectId,\n }\n }\n\n debug('Prompting user to select or create a project')\n const projectResult = await getOrCreateProject({\n coupon,\n newProject,\n organization,\n planId,\n project,\n unattended,\n user,\n })\n debug(`Project with name ${projectResult.displayName} selected`)\n\n debug('Prompting user to select or create a dataset')\n const datasetResult = await getOrCreateDataset({\n dataset,\n defaultConfig: datasetDefault || undefined,\n displayName: projectResult.displayName,\n output,\n projectId: projectResult.projectId,\n showDefaultConfigPrompt,\n unattended,\n visibility,\n })\n debug(`Dataset with name ${datasetResult.datasetName} selected`)\n\n trace.log({\n datasetName: datasetResult.datasetName,\n selectedOption: datasetResult.userAction,\n step: 'createOrSelectDataset',\n visibility,\n })\n\n return {\n datasetName: datasetResult.datasetName,\n displayName: projectResult.displayName,\n isFirstProject: projectResult.isFirstProject,\n organizationId: projectResult.organizationId,\n projectId: projectResult.projectId,\n }\n}\n"],"names":["subdebug","listOrganizations","InitError","getOrCreateDataset","getOrCreateProject","promptForAppTemplateSetup","promptUserForOrganization","debug","getProjectDetails","coupon","dataset","datasetDefault","isAppTemplate","isMediaLibraryTemplate","newProject","organization","output","planId","project","showDefaultConfigPrompt","trace","unattended","user","visibility","hasProjectFlag","Boolean","appOrganizationId","organizations","err","message","Error","String","warn","log","datasetName","selectedOption","step","displayName","isFirstProject","organizationId","projectId","appDatasetName","appDisplayName","resolvedOrganizationId","appProjectId","projectResult","datasetResult","defaultConfig","undefined","userAction"],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import appSanityUiTemplate from './appSanityUi.js';
|
|
|
3
3
|
import blog from './blog.js';
|
|
4
4
|
import clean from './clean.js';
|
|
5
5
|
import getStartedTemplate from './getStarted.js';
|
|
6
|
+
import mediaLibraryConfig from './mediaLibraryConfig.js';
|
|
6
7
|
import moviedb from './moviedb.js';
|
|
7
8
|
import pageBuilder from './pageBuilder.js';
|
|
8
9
|
import quickstart from './quickstart.js';
|
|
@@ -14,6 +15,8 @@ const templates = {
|
|
|
14
15
|
blog,
|
|
15
16
|
clean,
|
|
16
17
|
'get-started': getStartedTemplate,
|
|
18
|
+
// Unlisted (not in `templateChoices`): `--template media-library-config` only.
|
|
19
|
+
'media-library-config': mediaLibraryConfig,
|
|
17
20
|
moviedb,
|
|
18
21
|
'page-builder': pageBuilder,
|
|
19
22
|
quickstart,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/actions/init/templates/index.ts"],"sourcesContent":["import {type ProjectTemplate} from '../types.js'\nimport appTemplate from './appQuickstart.js'\nimport appSanityUiTemplate from './appSanityUi.js'\nimport blog from './blog.js'\nimport clean from './clean.js'\nimport getStartedTemplate from './getStarted.js'\nimport moviedb from './moviedb.js'\nimport pageBuilder from './pageBuilder.js'\nimport quickstart from './quickstart.js'\nimport shopify from './shopify.js'\nimport shopifyOnline from './shopifyOnline.js'\n\nconst templates: Record<string, ProjectTemplate | undefined> = {\n 'app-quickstart': appTemplate,\n 'app-sanity-ui': appSanityUiTemplate,\n blog,\n clean,\n 'get-started': getStartedTemplate,\n moviedb,\n 'page-builder': pageBuilder,\n quickstart, // empty project that dynamically imports its own schema\n shopify,\n 'shopify-online-storefront': shopifyOnline,\n}\n\nexport default templates\n"],"names":["appTemplate","appSanityUiTemplate","blog","clean","getStartedTemplate","moviedb","pageBuilder","quickstart","shopify","shopifyOnline","templates"],"mappings":"AACA,OAAOA,iBAAiB,qBAAoB;AAC5C,OAAOC,yBAAyB,mBAAkB;AAClD,OAAOC,UAAU,YAAW;AAC5B,OAAOC,WAAW,aAAY;AAC9B,OAAOC,wBAAwB,kBAAiB;AAChD,OAAOC,aAAa,eAAc;AAClC,OAAOC,iBAAiB,mBAAkB;AAC1C,OAAOC,gBAAgB,kBAAiB;AACxC,OAAOC,aAAa,eAAc;AAClC,OAAOC,mBAAmB,qBAAoB;AAE9C,MAAMC,YAAyD;IAC7D,
|
|
1
|
+
{"version":3,"sources":["../../../../src/actions/init/templates/index.ts"],"sourcesContent":["import {type ProjectTemplate} from '../types.js'\nimport appTemplate from './appQuickstart.js'\nimport appSanityUiTemplate from './appSanityUi.js'\nimport blog from './blog.js'\nimport clean from './clean.js'\nimport getStartedTemplate from './getStarted.js'\nimport mediaLibraryConfig from './mediaLibraryConfig.js'\nimport moviedb from './moviedb.js'\nimport pageBuilder from './pageBuilder.js'\nimport quickstart from './quickstart.js'\nimport shopify from './shopify.js'\nimport shopifyOnline from './shopifyOnline.js'\n\nconst templates: Record<string, ProjectTemplate | undefined> = {\n 'app-quickstart': appTemplate,\n 'app-sanity-ui': appSanityUiTemplate,\n blog,\n clean,\n 'get-started': getStartedTemplate,\n // Unlisted (not in `templateChoices`): `--template media-library-config` only.\n 'media-library-config': mediaLibraryConfig,\n moviedb,\n 'page-builder': pageBuilder,\n quickstart, // empty project that dynamically imports its own schema\n shopify,\n 'shopify-online-storefront': shopifyOnline,\n}\n\nexport default templates\n"],"names":["appTemplate","appSanityUiTemplate","blog","clean","getStartedTemplate","mediaLibraryConfig","moviedb","pageBuilder","quickstart","shopify","shopifyOnline","templates"],"mappings":"AACA,OAAOA,iBAAiB,qBAAoB;AAC5C,OAAOC,yBAAyB,mBAAkB;AAClD,OAAOC,UAAU,YAAW;AAC5B,OAAOC,WAAW,aAAY;AAC9B,OAAOC,wBAAwB,kBAAiB;AAChD,OAAOC,wBAAwB,0BAAyB;AACxD,OAAOC,aAAa,eAAc;AAClC,OAAOC,iBAAiB,mBAAkB;AAC1C,OAAOC,gBAAgB,kBAAiB;AACxC,OAAOC,aAAa,eAAc;AAClC,OAAOC,mBAAmB,qBAAoB;AAE9C,MAAMC,YAAyD;IAC7D,kBAAkBX;IAClB,iBAAiBC;IACjBC;IACAC;IACA,eAAeC;IACf,+EAA+E;IAC/E,wBAAwBC;IACxBC;IACA,gBAAgBC;IAChBC;IACAC;IACA,6BAA6BC;AAC/B;AAEA,eAAeC,UAAS"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Media Library config app: field (aspect) definitions for an organization's
|
|
3
|
+
* Media Library, bundled into a federated remote with island-rendered custom
|
|
4
|
+
* inputs. Unlisted — reachable only as `sanity init` with the template flag
|
|
5
|
+
* set to `media-library-config`, not offered in the template prompt.
|
|
6
|
+
*
|
|
7
|
+
* Brings its own dependency set (neither the SDK-app nor the studio base
|
|
8
|
+
* applies): field modules import `sanity` and `@sanity/ui` directly, and the
|
|
9
|
+
* island runtime the build bundles first shipped in `sanity` 6.20.0
|
|
10
|
+
* (`sanity/media-library-island-runtime`), which the range pins as the floor.
|
|
11
|
+
*/ const mediaLibraryConfigTemplate = {
|
|
12
|
+
dependencies: {
|
|
13
|
+
// Matches the @sanity/ui major `sanity` itself depends on, so one copy
|
|
14
|
+
// serves both the field modules and the studio dependency tree.
|
|
15
|
+
'@sanity/ui': '^4.4.10',
|
|
16
|
+
// The react floor @sanity/ui 4 and sanity 6.20 peer-require.
|
|
17
|
+
react: '^19.2.2',
|
|
18
|
+
'react-dom': '^19.2.2',
|
|
19
|
+
sanity: '^6.20.0',
|
|
20
|
+
// Peer of both `sanity` and `@sanity/ui`, imported by @sanity/ui at
|
|
21
|
+
// runtime and bundled into the island build — declared explicitly because
|
|
22
|
+
// installs without auto-installed peers would fail at runtime. (Sanity's
|
|
23
|
+
// own monorepos swap it for the `@sanity/css-in-js` fork via a pnpm
|
|
24
|
+
// override; a scaffolded project has no override, so it needs the real
|
|
25
|
+
// package.)
|
|
26
|
+
'styled-components': '^6.1.18'
|
|
27
|
+
},
|
|
28
|
+
devDependencies: {
|
|
29
|
+
'@sanity/eslint-config-studio': '^7',
|
|
30
|
+
'@types/react': '^19',
|
|
31
|
+
'@types/react-dom': '^19',
|
|
32
|
+
eslint: '^10',
|
|
33
|
+
// typescript-eslint (via eslint-config-studio) only supports TypeScript up to 6.0.x
|
|
34
|
+
typescript: '~6.0',
|
|
35
|
+
// The scaffolded eslint.config.mjs imports it directly (plugin declaration
|
|
36
|
+
// for the restricted-imports override). Same range eslint-config-studio
|
|
37
|
+
// uses, so npm dedupes to one instance — a second copy would make the
|
|
38
|
+
// plugin redefinition conflict.
|
|
39
|
+
'typescript-eslint': '^8'
|
|
40
|
+
},
|
|
41
|
+
scripts: {
|
|
42
|
+
build: 'sanity build',
|
|
43
|
+
deploy: 'sanity deploy',
|
|
44
|
+
dev: 'sanity dev'
|
|
45
|
+
},
|
|
46
|
+
type: 'module',
|
|
47
|
+
typescriptOnly: true
|
|
48
|
+
};
|
|
49
|
+
export default mediaLibraryConfigTemplate;
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=mediaLibraryConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/actions/init/templates/mediaLibraryConfig.ts"],"sourcesContent":["import {type ProjectTemplate} from '../types.js'\n\n/**\n * Media Library config app: field (aspect) definitions for an organization's\n * Media Library, bundled into a federated remote with island-rendered custom\n * inputs. Unlisted — reachable only as `sanity init` with the template flag\n * set to `media-library-config`, not offered in the template prompt.\n *\n * Brings its own dependency set (neither the SDK-app nor the studio base\n * applies): field modules import `sanity` and `@sanity/ui` directly, and the\n * island runtime the build bundles first shipped in `sanity` 6.20.0\n * (`sanity/media-library-island-runtime`), which the range pins as the floor.\n */\nconst mediaLibraryConfigTemplate: ProjectTemplate = {\n dependencies: {\n // Matches the @sanity/ui major `sanity` itself depends on, so one copy\n // serves both the field modules and the studio dependency tree.\n '@sanity/ui': '^4.4.10',\n // The react floor @sanity/ui 4 and sanity 6.20 peer-require.\n react: '^19.2.2',\n 'react-dom': '^19.2.2',\n sanity: '^6.20.0',\n // Peer of both `sanity` and `@sanity/ui`, imported by @sanity/ui at\n // runtime and bundled into the island build — declared explicitly because\n // installs without auto-installed peers would fail at runtime. (Sanity's\n // own monorepos swap it for the `@sanity/css-in-js` fork via a pnpm\n // override; a scaffolded project has no override, so it needs the real\n // package.)\n 'styled-components': '^6.1.18',\n },\n devDependencies: {\n '@sanity/eslint-config-studio': '^7',\n '@types/react': '^19',\n '@types/react-dom': '^19',\n eslint: '^10',\n // typescript-eslint (via eslint-config-studio) only supports TypeScript up to 6.0.x\n typescript: '~6.0',\n // The scaffolded eslint.config.mjs imports it directly (plugin declaration\n // for the restricted-imports override). Same range eslint-config-studio\n // uses, so npm dedupes to one instance — a second copy would make the\n // plugin redefinition conflict.\n 'typescript-eslint': '^8',\n },\n scripts: {\n build: 'sanity build',\n deploy: 'sanity deploy',\n dev: 'sanity dev',\n },\n type: 'module',\n typescriptOnly: true,\n}\n\nexport default mediaLibraryConfigTemplate\n"],"names":["mediaLibraryConfigTemplate","dependencies","react","sanity","devDependencies","eslint","typescript","scripts","build","deploy","dev","type","typescriptOnly"],"mappings":"AAEA;;;;;;;;;;CAUC,GACD,MAAMA,6BAA8C;IAClDC,cAAc;QACZ,uEAAuE;QACvE,gEAAgE;QAChE,cAAc;QACd,6DAA6D;QAC7DC,OAAO;QACP,aAAa;QACbC,QAAQ;QACR,oEAAoE;QACpE,0EAA0E;QAC1E,yEAAyE;QACzE,oEAAoE;QACpE,uEAAuE;QACvE,YAAY;QACZ,qBAAqB;IACvB;IACAC,iBAAiB;QACf,gCAAgC;QAChC,gBAAgB;QAChB,oBAAoB;QACpBC,QAAQ;QACR,oFAAoF;QACpFC,YAAY;QACZ,2EAA2E;QAC3E,wEAAwE;QACxE,sEAAsE;QACtE,gCAAgC;QAChC,qBAAqB;IACvB;IACAC,SAAS;QACPC,OAAO;QACPC,QAAQ;QACRC,KAAK;IACP;IACAC,MAAM;IACNC,gBAAgB;AAClB;AAEA,eAAeZ,2BAA0B"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shape an aspect/field name must have — the single source for every
|
|
3
|
+
* consumer. Names double as the stored `sanity.asset.aspect` document `_id`
|
|
4
|
+
* and as the `aspects.<name>` data key on asset documents, and get
|
|
5
|
+
* interpolated into GROQ by tooling, so the same rule guards all three.
|
|
6
|
+
*/ export const VALID_ASPECT_NAME = /^[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
7
|
+
|
|
8
|
+
//# sourceMappingURL=aspectName.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/media/aspectName.ts"],"sourcesContent":["/**\n * The shape an aspect/field name must have — the single source for every\n * consumer. Names double as the stored `sanity.asset.aspect` document `_id`\n * and as the `aspects.<name>` data key on asset documents, and get\n * interpolated into GROQ by tooling, so the same rule guards all three.\n */\nexport const VALID_ASPECT_NAME = /^[a-zA-Z][a-zA-Z0-9_]*$/\n"],"names":["VALID_ASPECT_NAME"],"mappings":"AAAA;;;;;CAKC,GACD,OAAO,MAAMA,oBAAoB,0BAAyB"}
|