@sanity/cli 8.8.0 → 8.9.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/deploy/deployApp.js +1 -0
- package/dist/actions/deploy/deployApp.js.map +1 -1
- package/dist/actions/deploy/deployStudio.js +1 -0
- package/dist/actions/deploy/deployStudio.js.map +1 -1
- package/dist/actions/typegen/parseTypegenConfig.js +21 -0
- package/dist/actions/typegen/parseTypegenConfig.js.map +1 -0
- package/dist/commands/typegen/generate.js +4 -3
- package/dist/commands/typegen/generate.js.map +1 -1
- package/dist/server/vite/plugin-typegen.js +3 -2
- package/dist/server/vite/plugin-typegen.js.map +1 -1
- package/oclif.manifest.json +619 -619
- package/package.json +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/deployApp.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip} from 'node:zlib'\n\nimport {\n type CoreAppManifest,\n extractCoreAppManifest,\n readIconFromPath,\n resolveTitleUpdate,\n} from '@sanity/cli-build/_internal/manifest'\nimport {type AppVisibility, exitCodes} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {getCoreAppUrl} from '@sanity/cli-core/util'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {\n createCoreApp,\n deployConfig,\n deployWorkbenchApp,\n getApplicationUrl,\n getWorkbench,\n resolveInstallationId,\n resolveWorkbenchConfig,\n summarizeConfig,\n toWorkbenchPayload,\n} from '@sanity/workbench-cli/deploy'\nimport {c as createTar} from 'tar'\n\nimport {\n createDeployment,\n updateUserApplication,\n type UserApplication,\n type UserApplicationResolved,\n} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {EXTERNAL_APP_NOT_SUPPORTED, NO_ORGANIZATION_ID} from '../../util/errorMessages.js'\nimport {buildApp} from '../build/buildApp.js'\nimport {createUserApplication} from './createUserApplication.js'\nimport {\n checkAppId,\n checkAppTarget,\n checkAutoUpdates,\n checkBuild,\n checkPackageVersion,\n type DeployCheckReporter,\n verifyOutputDir,\n} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {listDeploymentFiles, reportInterfaces} from './deploymentPlan.js'\nimport {type DeployPayload, type DeployResult, runDeploy} from './deployRunner.js'\nimport {findUserApplication} from './findUserApplication.js'\nimport {type DeployAppOptions} from './types.js'\n\nconst APP_PACKAGE = '@sanity/sdk-react'\n\nexport function deployApp(options: DeployAppOptions): Promise<void> {\n return runDeploy(options, {\n listFiles: ({projectRoot, sourceDir}) => listDeploymentFiles(sourceDir, projectRoot.directory),\n run: runAppDeployment,\n type: 'coreApp',\n })\n}\n\n/** Validates the deploy, syncs the title from the manifest, and ships the build. */\nasync function runAppDeployment(\n options: DeployAppOptions,\n reporter: DeployCheckReporter,\n): Promise<DeployResult | void> {\n const {cliConfig, flags, output, sourceDir} = options\n const workDir = options.projectRoot.directory\n const organizationId = cliConfig.app?.organizationId\n const appId = getAppId(cliConfig)\n const workbench = getWorkbench(cliConfig)\n // A config (the Media Library) is not an app — it resolves through its own\n // brand and persists to the org's installation instead of hosting an application.\n const config = resolveWorkbenchConfig(cliConfig)\n const dryRun = !!flags['dry-run']\n\n const deployConfigOnly = !!config\n const deployApplication = !config && (!workbench || workbench.hasInterfaces)\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.slug\n : ''\n\n // A federated app with no entry, view or service would ship a remote with\n // nothing to load — reported first so it fails before any prompt or API call.\n if (workbench) {\n try {\n workbench.assertDeployable()\n } catch (err) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: getErrorMessage(err),\n solution: 'Declare at least one entry, view, or service in the app',\n status: 'fail',\n })\n }\n }\n\n // A config with no fields would overwrite the org's live config with an empty\n // snapshot, so block it here — same \"nothing to deploy\" gate an app gets.\n if (config && config.fields.length === 0) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'Nothing to deploy: the media library config declares no fields.',\n solution: 'Add at least one field to the media library config',\n status: 'fail',\n })\n }\n\n const isAutoUpdating = checkAutoUpdates(reporter, {cliConfig, flags})\n\n // An application ships the SDK runtime; a media-library config stamps its\n // `sanity` version instead.\n let version: string | null = null\n if (deployApplication) {\n version = await checkPackageVersion(reporter, {moduleName: APP_PACKAGE, workDir})\n } else if (deployConfigOnly) {\n version = await checkPackageVersion(reporter, {moduleName: 'sanity', workDir})\n }\n\n reporter.report(\n organizationId\n ? {message: `Organization: ${organizationId}`, status: 'pass'}\n : {\n message: NO_ORGANIZATION_ID,\n solution: 'Add `app.organizationId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n\n checkAppId(reporter, {cliConfig})\n\n let application: UserApplicationResolved | null = null\n let appCreated = false\n let workbenchApp: object | undefined\n if (flags.external) {\n reporter.report({\n message: EXTERNAL_APP_NOT_SUPPORTED,\n solution: 'Remove the --external flag — apps deploy to Sanity hosting',\n status: 'fail',\n })\n } else if (deployApplication && workbench) {\n workbenchApp = (\n await checkAppTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n organizationId,\n slug: workbench.slug,\n title: appTitle,\n })\n )?.application\n } else if (deployApplication) {\n ;({application, created: appCreated} = await resolveAppApplication(options, {dryRun, reporter}))\n }\n\n // A first deploy mints the app id and the build inlines it; --no-build would\n // ship an existing bundle carrying a different id, so it can't be a first deploy.\n if (deployApplication && workbench && !appId && !flags.external && !flags.build) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'A first deploy cannot skip the build (--no-build)',\n solution: 'Drop --no-build so the new application id is inlined into the build',\n status: 'fail',\n })\n }\n\n // Read up front so a bad icon path fails before we create or build.\n const appIcon =\n !dryRun && workbench?.icon ? await readIconFromPath(workDir, workbench.icon) : undefined\n\n // Create the app before the build so the bundle carries its real id. A\n // redeploy already has it from `deployment.appId`; a dry run skips creation.\n let applicationId = appId\n let applicationCreated = false\n let rollbackApp: (() => Promise<void>) | undefined\n if (!dryRun && deployApplication && workbench && organizationId && !applicationId) {\n const created = await createCoreApp({\n isSingleton: workbench.isSingleton,\n name: workbench.name,\n organizationId,\n slug: workbench.slug,\n title: appTitle,\n visibility: workbench.visibility,\n })\n workbenchApp = created.application\n applicationId = created.application.id\n rollbackApp = created.rollback\n applicationCreated = true\n }\n\n // A record created above is stranded at its slug (and blocks retries) if any\n // step before it fully deploys fails, so undo the creation on failure.\n try {\n await checkBuild(reporter, {\n build: () =>\n buildApp({\n applicationId: workbench ? applicationId : undefined,\n autoUpdatesEnabled: isAutoUpdating,\n calledFromDeploy: true,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n }),\n skipReason: flags.build\n ? undefined\n : 'Build skipped (--no-build) — validating existing output directory',\n successMessage: 'App built',\n })\n\n await verifyOutputDir({\n isWorkbenchApp: workbench !== null || config !== null,\n reporter,\n sourceDir,\n })\n\n // Workbench apps and configs ship a federation remote and don't read the\n // core-app manifest; only plain core-apps do. Manifests aren't strictly\n // essential, so a failure warns and continues.\n let manifest: CoreAppManifest | undefined\n if (!workbench && !config) {\n try {\n manifest = await extractCoreAppManifest({workDir})\n } catch (err) {\n deployDebug('Error extracting app manifest', err)\n reporter.report({\n message: `Error extracting app manifest: ${getErrorMessage(err)}`,\n status: 'warn',\n })\n }\n }\n\n // Resolve the installation in both modes so the report — dry-run and real —\n // shows whether the config is deployable; a missing one fails the deploy here.\n let installationId: string | undefined\n let configSummary: string | undefined\n const configAppType = config?.appType\n if (deployConfigOnly && organizationId && config && configAppType) {\n installationId = await resolveInstallationId({appType: configAppType, organizationId})\n configSummary = summarizeConfig(config)\n reporter.report(\n installationId\n ? {message: configSummary, status: 'pass'}\n : {\n exitCode: exitCodes.USAGE_ERROR,\n message: `No active \"${configAppType}\" installation for organization \"${organizationId}\"`,\n solution:\n 'Install the Media Library for the organization before deploying its config',\n status: 'fail',\n },\n )\n }\n\n const interfaces = deployApplication && workbench ? reportInterfaces(reporter, workbench) : null\n\n // Applied after the app is live (see below) so a failed deploy never leaves\n // the org's installation config without its application.\n const deployApplicationConfig = async (): Promise<void> => {\n if (installationId && version && configAppType && organizationId) {\n await deployConfig({\n appType: configAppType,\n installationId,\n organizationId,\n output,\n sourceDir,\n version,\n })\n }\n }\n\n const payload: DeployPayload = {\n appId: appId ?? null,\n isAutoUpdating,\n ...(organizationId ? {organizationId} : {}),\n type: 'coreApp',\n version,\n ...toWorkbenchPayload(workbench, {config: configSummary, interfaces, title: appTitle}),\n ...(configSummary ? {config: configSummary} : {}),\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return {application: null, payload}\n\n // A config-only singleton ships no application, only its config.\n if (!deployApplication) {\n await deployApplicationConfig()\n if (installationId && version) {\n return {application: null, installationId, payload}\n }\n return\n }\n\n // A real deploy already exited on a version-resolution failure; this narrows the type.\n if (!version) return\n\n // The app was created (or resolved from `deployment.appId`) before the build,\n // so this only ships the deployment; plain coreApps use user-applications below.\n if (workbench && organizationId && applicationId) {\n await deployWorkbenchApp({\n app: cliConfig.app,\n applicationId,\n icon: appIcon,\n isApp: true,\n isAutoUpdating,\n // Once the deployment is live, a metadata-sync or later config failure\n // must not delete the app.\n onDeployed: () => {\n rollbackApp = undefined\n },\n sourceDir,\n title: appTitle,\n version,\n visibility: workbench.visibility,\n })\n await deployApplicationConfig()\n const url = getApplicationUrl({id: applicationId, organizationId, type: 'coreApp'})\n logAppDeployed({\n applicationId,\n cliConfig,\n created: applicationCreated,\n organizationId,\n output,\n title: appTitle,\n url,\n })\n return {\n action: applicationCreated ? 'create' : 'update',\n application: workbenchApp ?? null,\n payload,\n url,\n }\n }\n\n // A real deploy has already exited if anything failed; landing here without a\n // resolved application means the deploy target was never resolved.\n if (!application) return\n\n application = await syncApplicationMetadata({\n application,\n manifest,\n output,\n visibility: cliConfig.app?.visibility,\n })\n await shipAppDeployment({application, isAutoUpdating, manifest, sourceDir, version})\n logAppDeployed({\n applicationId: application.id,\n cliConfig,\n created: appCreated,\n organizationId: application.organizationId,\n output,\n title: application.title,\n })\n return {\n action: appCreated ? 'create' : 'update',\n application,\n payload,\n url: getCoreAppUrl(application.organizationId, application.id),\n }\n } catch (err) {\n await rollbackApp?.()\n throw err\n }\n}\n\n/**\n * Finds the application a real deploy targets, creating one when none is\n * configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveAppApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplicationResolved | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const organizationId = cliConfig.app?.organizationId ?? ''\n // Create name from --title or `app.title` config; blank falls back to the prompt\n const title = flags.title?.trim() || cliConfig.app?.title?.trim() || undefined\n\n if (dryRun) {\n await checkAppTarget(reporter, {appId: getAppId(cliConfig), organizationId, title})\n return {application: null, created: false}\n }\n\n let application = await findUserApplication({\n cliConfig,\n organizationId,\n output,\n title,\n unattended: !!flags.yes,\n })\n deployDebug('User application found', application)\n\n if (!application) {\n deployDebug('No user application found. Creating a new one')\n application = await createUserApplication(organizationId, title, cliConfig.app?.visibility)\n deployDebug('User application created', application)\n return {application, created: true}\n }\n\n return {application, created: false}\n}\n\n/**\n * Syncs application metadata on redeploy when it has changed: the title from the\n * manifest and the dashboard visibility from config. Sends a single PATCH with\n * only the changed fields, and skips the request entirely when nothing changed.\n */\nexport async function syncApplicationMetadata({\n application,\n manifest,\n output,\n visibility,\n}: {\n application: UserApplicationResolved\n manifest: CoreAppManifest | undefined\n output: DeployAppOptions['output']\n visibility: AppVisibility | undefined\n}): Promise<UserApplicationResolved> {\n const titleUpdate = resolveTitleUpdate(manifest, application)\n // Treat an unset server value as `default` so a config of `default` is a no-op.\n const visibilityChanged =\n visibility !== undefined && visibility !== (application.dashboardStatus ?? 'default')\n\n if (!titleUpdate && !visibilityChanged) return application\n\n if (titleUpdate) {\n deployDebug('Updating application title from manifest', titleUpdate)\n output.log(\n titleUpdate.from\n ? `Updating title from \"${titleUpdate.from}\" to \"${titleUpdate.to}\"`\n : `Setting application title to \"${titleUpdate.to}\"`,\n )\n }\n if (visibilityChanged) {\n output.log(`Setting dashboard visibility to \"${visibility}\"`)\n }\n\n const spin = spinner('Updating application').start()\n try {\n const updated = await updateUserApplication({\n applicationId: application.id,\n appType: 'coreApp',\n body: {\n ...(titleUpdate ? {title: titleUpdate.to} : {}),\n ...(visibilityChanged ? {dashboardStatus: visibility} : {}),\n },\n })\n spin.succeed()\n return updated\n } catch (err) {\n spin.fail()\n const message = getErrorMessage(err)\n deployDebug('Error updating application metadata', {message})\n output.warn(`Error updating application metadata: ${message}`)\n return application\n }\n}\n\nasync function shipAppDeployment({\n application,\n isAutoUpdating,\n manifest,\n sourceDir,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n manifest: CoreAppManifest | undefined\n sourceDir: string\n version: string\n}): Promise<void> {\n const tarball = createTar({cwd: dirname(sourceDir)}, [basename(sourceDir)]).pipe(createGzip())\n\n const spin = spinner('Deploying...').start()\n try {\n await createDeployment({\n applicationId: application.id,\n isApp: true,\n isAutoUpdating,\n manifest,\n tarball,\n version,\n })\n } catch (error) {\n spin.clear()\n throw error\n }\n spin.succeed()\n}\n\nexport function logAppDeployed({\n applicationId,\n cliConfig,\n created,\n organizationId,\n output,\n title,\n url = getCoreAppUrl(organizationId, applicationId),\n}: {\n applicationId: string\n cliConfig: DeployAppOptions['cliConfig']\n created: boolean\n organizationId: string\n output: DeployAppOptions['output']\n title: string | null\n url?: string\n}): void {\n const named = title ? ` — \"${title}\"` : ''\n output.log(`\\nSuccess! Application deployed to ${styleText('cyan', url)}${named}`)\n output.log(created ? 'Created a new application.' : 'Updated the existing application.')\n\n if (getAppId(cliConfig)) return\n\n output.log(`\\n════ ${styleText('bold', 'Next step:')} ════`)\n if (created) {\n output.log(\n styleText(\n 'yellow',\n '\\nDeploying again without `deployment.appId` creates another new application.',\n ),\n )\n }\n output.log(\n styleText('bold', '\\nAdd the deployment.appId to your sanity.cli.js or sanity.cli.ts file:'),\n )\n output.log(`\n${styleText(\n 'dim',\n `app: {\n // your application config here…\n}`,\n)},\n${styleText(\n ['bold', 'green'],\n `deployment: {\n appId: '${applicationId}',\n}\\n`,\n)}`)\n}\n"],"names":["basename","dirname","styleText","createGzip","extractCoreAppManifest","readIconFromPath","resolveTitleUpdate","exitCodes","getErrorMessage","getCoreAppUrl","spinner","createCoreApp","deployConfig","deployWorkbenchApp","getApplicationUrl","getWorkbench","resolveInstallationId","resolveWorkbenchConfig","summarizeConfig","toWorkbenchPayload","c","createTar","createDeployment","updateUserApplication","getAppId","EXTERNAL_APP_NOT_SUPPORTED","NO_ORGANIZATION_ID","buildApp","createUserApplication","checkAppId","checkAppTarget","checkAutoUpdates","checkBuild","checkPackageVersion","verifyOutputDir","deployDebug","listDeploymentFiles","reportInterfaces","runDeploy","findUserApplication","APP_PACKAGE","deployApp","options","listFiles","projectRoot","sourceDir","directory","run","runAppDeployment","type","reporter","cliConfig","flags","output","workDir","organizationId","app","appId","workbench","config","dryRun","deployConfigOnly","deployApplication","hasInterfaces","appTitle","title","trim","slug","assertDeployable","err","report","exitCode","USAGE_ERROR","message","solution","status","fields","length","isAutoUpdating","version","moduleName","application","appCreated","workbenchApp","external","isWorkbenchApp","created","resolveAppApplication","build","appIcon","icon","undefined","applicationId","applicationCreated","rollbackApp","isSingleton","name","visibility","id","rollback","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","successMessage","manifest","installationId","configSummary","configAppType","appType","interfaces","deployApplicationConfig","payload","isApp","onDeployed","url","logAppDeployed","action","syncApplicationMetadata","shipAppDeployment","unattended","yes","titleUpdate","visibilityChanged","dashboardStatus","log","from","to","spin","start","updated","body","succeed","fail","warn","tarball","cwd","pipe","error","clear","named"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/deploy/deployApp.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip} from 'node:zlib'\n\nimport {\n type CoreAppManifest,\n extractCoreAppManifest,\n readIconFromPath,\n resolveTitleUpdate,\n} from '@sanity/cli-build/_internal/manifest'\nimport {type AppVisibility, exitCodes} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {getCoreAppUrl} from '@sanity/cli-core/util'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {\n createCoreApp,\n deployConfig,\n deployWorkbenchApp,\n getApplicationUrl,\n getWorkbench,\n resolveInstallationId,\n resolveWorkbenchConfig,\n summarizeConfig,\n toWorkbenchPayload,\n} from '@sanity/workbench-cli/deploy'\nimport {c as createTar} from 'tar'\n\nimport {\n createDeployment,\n updateUserApplication,\n type UserApplication,\n type UserApplicationResolved,\n} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {EXTERNAL_APP_NOT_SUPPORTED, NO_ORGANIZATION_ID} from '../../util/errorMessages.js'\nimport {buildApp} from '../build/buildApp.js'\nimport {createUserApplication} from './createUserApplication.js'\nimport {\n checkAppId,\n checkAppTarget,\n checkAutoUpdates,\n checkBuild,\n checkPackageVersion,\n type DeployCheckReporter,\n verifyOutputDir,\n} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {listDeploymentFiles, reportInterfaces} from './deploymentPlan.js'\nimport {type DeployPayload, type DeployResult, runDeploy} from './deployRunner.js'\nimport {findUserApplication} from './findUserApplication.js'\nimport {type DeployAppOptions} from './types.js'\n\nconst APP_PACKAGE = '@sanity/sdk-react'\n\nexport function deployApp(options: DeployAppOptions): Promise<void> {\n return runDeploy(options, {\n listFiles: ({projectRoot, sourceDir}) => listDeploymentFiles(sourceDir, projectRoot.directory),\n run: runAppDeployment,\n type: 'coreApp',\n })\n}\n\n/** Validates the deploy, syncs the title from the manifest, and ships the build. */\nasync function runAppDeployment(\n options: DeployAppOptions,\n reporter: DeployCheckReporter,\n): Promise<DeployResult | void> {\n const {cliConfig, flags, output, sourceDir} = options\n const workDir = options.projectRoot.directory\n const organizationId = cliConfig.app?.organizationId\n const appId = getAppId(cliConfig)\n const workbench = getWorkbench(cliConfig)\n // A config (the Media Library) is not an app — it resolves through its own\n // brand and persists to the org's installation instead of hosting an application.\n const config = resolveWorkbenchConfig(cliConfig)\n const dryRun = !!flags['dry-run']\n\n const deployConfigOnly = !!config\n const deployApplication = !config && (!workbench || workbench.hasInterfaces)\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.slug\n : ''\n\n // A federated app with no entry, view or service would ship a remote with\n // nothing to load — reported first so it fails before any prompt or API call.\n if (workbench) {\n try {\n workbench.assertDeployable()\n } catch (err) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: getErrorMessage(err),\n solution: 'Declare at least one entry, view, or service in the app',\n status: 'fail',\n })\n }\n }\n\n // A config with no fields would overwrite the org's live config with an empty\n // snapshot, so block it here — same \"nothing to deploy\" gate an app gets.\n if (config && config.fields.length === 0) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'Nothing to deploy: the media library config declares no fields.',\n solution: 'Add at least one field to the media library config',\n status: 'fail',\n })\n }\n\n const isAutoUpdating = checkAutoUpdates(reporter, {cliConfig, flags})\n\n // An application ships the SDK runtime; a media-library config stamps its\n // `sanity` version instead.\n let version: string | null = null\n if (deployApplication) {\n version = await checkPackageVersion(reporter, {moduleName: APP_PACKAGE, workDir})\n } else if (deployConfigOnly) {\n version = await checkPackageVersion(reporter, {moduleName: 'sanity', workDir})\n }\n\n reporter.report(\n organizationId\n ? {message: `Organization: ${organizationId}`, status: 'pass'}\n : {\n message: NO_ORGANIZATION_ID,\n solution: 'Add `app.organizationId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n\n checkAppId(reporter, {cliConfig})\n\n let application: UserApplicationResolved | null = null\n let appCreated = false\n let workbenchApp: object | undefined\n if (flags.external) {\n reporter.report({\n message: EXTERNAL_APP_NOT_SUPPORTED,\n solution: 'Remove the --external flag — apps deploy to Sanity hosting',\n status: 'fail',\n })\n } else if (deployApplication && workbench) {\n workbenchApp = (\n await checkAppTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n organizationId,\n slug: workbench.slug,\n title: appTitle,\n })\n )?.application\n } else if (deployApplication) {\n ;({application, created: appCreated} = await resolveAppApplication(options, {dryRun, reporter}))\n }\n\n // A first deploy mints the app id and the build inlines it; --no-build would\n // ship an existing bundle carrying a different id, so it can't be a first deploy.\n if (deployApplication && workbench && !appId && !flags.external && !flags.build) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'A first deploy cannot skip the build (--no-build)',\n solution: 'Drop --no-build so the new application id is inlined into the build',\n status: 'fail',\n })\n }\n\n // Read up front so a bad icon path fails before we create or build.\n const appIcon =\n !dryRun && workbench?.icon ? await readIconFromPath(workDir, workbench.icon) : undefined\n\n // Create the app before the build so the bundle carries its real id. A\n // redeploy already has it from `deployment.appId`; a dry run skips creation.\n let applicationId = appId\n let applicationCreated = false\n let rollbackApp: (() => Promise<void>) | undefined\n if (!dryRun && deployApplication && workbench && organizationId && !applicationId) {\n const created = await createCoreApp({\n isSingleton: workbench.isSingleton,\n name: workbench.name,\n organizationId,\n slug: workbench.slug,\n title: appTitle,\n visibility: workbench.visibility,\n })\n workbenchApp = created.application\n applicationId = created.application.id\n rollbackApp = created.rollback\n applicationCreated = true\n }\n\n // A record created above is stranded at its slug (and blocks retries) if any\n // step before it fully deploys fails, so undo the creation on failure.\n try {\n await checkBuild(reporter, {\n build: () =>\n buildApp({\n applicationId: workbench ? applicationId : undefined,\n autoUpdatesEnabled: isAutoUpdating,\n calledFromDeploy: true,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n }),\n skipReason: flags.build\n ? undefined\n : 'Build skipped (--no-build) — validating existing output directory',\n successMessage: 'App built',\n })\n\n await verifyOutputDir({\n isWorkbenchApp: workbench !== null || config !== null,\n reporter,\n sourceDir,\n })\n\n // Workbench apps and configs ship a federation remote and don't read the\n // core-app manifest; only plain core-apps do. Manifests aren't strictly\n // essential, so a failure warns and continues.\n let manifest: CoreAppManifest | undefined\n if (!workbench && !config) {\n try {\n manifest = await extractCoreAppManifest({workDir})\n } catch (err) {\n deployDebug('Error extracting app manifest', err)\n reporter.report({\n message: `Error extracting app manifest: ${getErrorMessage(err)}`,\n status: 'warn',\n })\n }\n }\n\n // Resolve the installation in both modes so the report — dry-run and real —\n // shows whether the config is deployable; a missing one fails the deploy here.\n let installationId: string | undefined\n let configSummary: string | undefined\n const configAppType = config?.appType\n if (deployConfigOnly && organizationId && config && configAppType) {\n installationId = await resolveInstallationId({appType: configAppType, organizationId})\n configSummary = summarizeConfig(config)\n reporter.report(\n installationId\n ? {message: configSummary, status: 'pass'}\n : {\n exitCode: exitCodes.USAGE_ERROR,\n message: `No active \"${configAppType}\" installation for organization \"${organizationId}\"`,\n solution:\n 'Install the Media Library for the organization before deploying its config',\n status: 'fail',\n },\n )\n }\n\n const interfaces = deployApplication && workbench ? reportInterfaces(reporter, workbench) : null\n\n // Applied after the app is live (see below) so a failed deploy never leaves\n // the org's installation config without its application.\n const deployApplicationConfig = async (): Promise<void> => {\n if (installationId && version && configAppType && organizationId) {\n await deployConfig({\n appType: configAppType,\n installationId,\n organizationId,\n output,\n sourceDir,\n version,\n })\n }\n }\n\n const payload: DeployPayload = {\n appId: appId ?? null,\n isAutoUpdating,\n ...(organizationId ? {organizationId} : {}),\n type: 'coreApp',\n version,\n ...toWorkbenchPayload(workbench, {config: configSummary, interfaces, title: appTitle}),\n ...(configSummary ? {config: configSummary} : {}),\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return {application: null, payload}\n\n // A config-only singleton ships no application, only its config.\n if (!deployApplication) {\n await deployApplicationConfig()\n if (installationId && version) {\n return {application: null, installationId, payload}\n }\n return\n }\n\n // A real deploy already exited on a version-resolution failure; this narrows the type.\n if (!version) return\n\n // The app was created (or resolved from `deployment.appId`) before the build,\n // so this only ships the deployment; plain coreApps use user-applications below.\n if (workbench && organizationId && applicationId) {\n await deployWorkbenchApp({\n app: cliConfig.app,\n applicationId,\n icon: appIcon,\n isApp: true,\n isAutoUpdating,\n // Once the deployment is live, a metadata-sync or later config failure\n // must not delete the app.\n onDeployed: () => {\n rollbackApp = undefined\n },\n slug: workbench.slug,\n sourceDir,\n title: appTitle,\n version,\n visibility: workbench.visibility,\n })\n await deployApplicationConfig()\n const url = getApplicationUrl({id: applicationId, organizationId, type: 'coreApp'})\n logAppDeployed({\n applicationId,\n cliConfig,\n created: applicationCreated,\n organizationId,\n output,\n title: appTitle,\n url,\n })\n return {\n action: applicationCreated ? 'create' : 'update',\n application: workbenchApp ?? null,\n payload,\n url,\n }\n }\n\n // A real deploy has already exited if anything failed; landing here without a\n // resolved application means the deploy target was never resolved.\n if (!application) return\n\n application = await syncApplicationMetadata({\n application,\n manifest,\n output,\n visibility: cliConfig.app?.visibility,\n })\n await shipAppDeployment({application, isAutoUpdating, manifest, sourceDir, version})\n logAppDeployed({\n applicationId: application.id,\n cliConfig,\n created: appCreated,\n organizationId: application.organizationId,\n output,\n title: application.title,\n })\n return {\n action: appCreated ? 'create' : 'update',\n application,\n payload,\n url: getCoreAppUrl(application.organizationId, application.id),\n }\n } catch (err) {\n await rollbackApp?.()\n throw err\n }\n}\n\n/**\n * Finds the application a real deploy targets, creating one when none is\n * configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveAppApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplicationResolved | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const organizationId = cliConfig.app?.organizationId ?? ''\n // Create name from --title or `app.title` config; blank falls back to the prompt\n const title = flags.title?.trim() || cliConfig.app?.title?.trim() || undefined\n\n if (dryRun) {\n await checkAppTarget(reporter, {appId: getAppId(cliConfig), organizationId, title})\n return {application: null, created: false}\n }\n\n let application = await findUserApplication({\n cliConfig,\n organizationId,\n output,\n title,\n unattended: !!flags.yes,\n })\n deployDebug('User application found', application)\n\n if (!application) {\n deployDebug('No user application found. Creating a new one')\n application = await createUserApplication(organizationId, title, cliConfig.app?.visibility)\n deployDebug('User application created', application)\n return {application, created: true}\n }\n\n return {application, created: false}\n}\n\n/**\n * Syncs application metadata on redeploy when it has changed: the title from the\n * manifest and the dashboard visibility from config. Sends a single PATCH with\n * only the changed fields, and skips the request entirely when nothing changed.\n */\nexport async function syncApplicationMetadata({\n application,\n manifest,\n output,\n visibility,\n}: {\n application: UserApplicationResolved\n manifest: CoreAppManifest | undefined\n output: DeployAppOptions['output']\n visibility: AppVisibility | undefined\n}): Promise<UserApplicationResolved> {\n const titleUpdate = resolveTitleUpdate(manifest, application)\n // Treat an unset server value as `default` so a config of `default` is a no-op.\n const visibilityChanged =\n visibility !== undefined && visibility !== (application.dashboardStatus ?? 'default')\n\n if (!titleUpdate && !visibilityChanged) return application\n\n if (titleUpdate) {\n deployDebug('Updating application title from manifest', titleUpdate)\n output.log(\n titleUpdate.from\n ? `Updating title from \"${titleUpdate.from}\" to \"${titleUpdate.to}\"`\n : `Setting application title to \"${titleUpdate.to}\"`,\n )\n }\n if (visibilityChanged) {\n output.log(`Setting dashboard visibility to \"${visibility}\"`)\n }\n\n const spin = spinner('Updating application').start()\n try {\n const updated = await updateUserApplication({\n applicationId: application.id,\n appType: 'coreApp',\n body: {\n ...(titleUpdate ? {title: titleUpdate.to} : {}),\n ...(visibilityChanged ? {dashboardStatus: visibility} : {}),\n },\n })\n spin.succeed()\n return updated\n } catch (err) {\n spin.fail()\n const message = getErrorMessage(err)\n deployDebug('Error updating application metadata', {message})\n output.warn(`Error updating application metadata: ${message}`)\n return application\n }\n}\n\nasync function shipAppDeployment({\n application,\n isAutoUpdating,\n manifest,\n sourceDir,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n manifest: CoreAppManifest | undefined\n sourceDir: string\n version: string\n}): Promise<void> {\n const tarball = createTar({cwd: dirname(sourceDir)}, [basename(sourceDir)]).pipe(createGzip())\n\n const spin = spinner('Deploying...').start()\n try {\n await createDeployment({\n applicationId: application.id,\n isApp: true,\n isAutoUpdating,\n manifest,\n tarball,\n version,\n })\n } catch (error) {\n spin.clear()\n throw error\n }\n spin.succeed()\n}\n\nexport function logAppDeployed({\n applicationId,\n cliConfig,\n created,\n organizationId,\n output,\n title,\n url = getCoreAppUrl(organizationId, applicationId),\n}: {\n applicationId: string\n cliConfig: DeployAppOptions['cliConfig']\n created: boolean\n organizationId: string\n output: DeployAppOptions['output']\n title: string | null\n url?: string\n}): void {\n const named = title ? ` — \"${title}\"` : ''\n output.log(`\\nSuccess! Application deployed to ${styleText('cyan', url)}${named}`)\n output.log(created ? 'Created a new application.' : 'Updated the existing application.')\n\n if (getAppId(cliConfig)) return\n\n output.log(`\\n════ ${styleText('bold', 'Next step:')} ════`)\n if (created) {\n output.log(\n styleText(\n 'yellow',\n '\\nDeploying again without `deployment.appId` creates another new application.',\n ),\n )\n }\n output.log(\n styleText('bold', '\\nAdd the deployment.appId to your sanity.cli.js or sanity.cli.ts file:'),\n )\n output.log(`\n${styleText(\n 'dim',\n `app: {\n // your application config here…\n}`,\n)},\n${styleText(\n ['bold', 'green'],\n `deployment: {\n appId: '${applicationId}',\n}\\n`,\n)}`)\n}\n"],"names":["basename","dirname","styleText","createGzip","extractCoreAppManifest","readIconFromPath","resolveTitleUpdate","exitCodes","getErrorMessage","getCoreAppUrl","spinner","createCoreApp","deployConfig","deployWorkbenchApp","getApplicationUrl","getWorkbench","resolveInstallationId","resolveWorkbenchConfig","summarizeConfig","toWorkbenchPayload","c","createTar","createDeployment","updateUserApplication","getAppId","EXTERNAL_APP_NOT_SUPPORTED","NO_ORGANIZATION_ID","buildApp","createUserApplication","checkAppId","checkAppTarget","checkAutoUpdates","checkBuild","checkPackageVersion","verifyOutputDir","deployDebug","listDeploymentFiles","reportInterfaces","runDeploy","findUserApplication","APP_PACKAGE","deployApp","options","listFiles","projectRoot","sourceDir","directory","run","runAppDeployment","type","reporter","cliConfig","flags","output","workDir","organizationId","app","appId","workbench","config","dryRun","deployConfigOnly","deployApplication","hasInterfaces","appTitle","title","trim","slug","assertDeployable","err","report","exitCode","USAGE_ERROR","message","solution","status","fields","length","isAutoUpdating","version","moduleName","application","appCreated","workbenchApp","external","isWorkbenchApp","created","resolveAppApplication","build","appIcon","icon","undefined","applicationId","applicationCreated","rollbackApp","isSingleton","name","visibility","id","rollback","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","successMessage","manifest","installationId","configSummary","configAppType","appType","interfaces","deployApplicationConfig","payload","isApp","onDeployed","url","logAppDeployed","action","syncApplicationMetadata","shipAppDeployment","unattended","yes","titleUpdate","visibilityChanged","dashboardStatus","log","from","to","spin","start","updated","body","succeed","fail","warn","tarball","cwd","pipe","error","clear","named"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/deployStudio.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip, type Gzip} from 'node:zlib'\n\nimport {formatSchemaValidation, SchemaExtractionError} from '@sanity/cli-build/_internal/extract'\nimport {readIconFromPath} from '@sanity/cli-build/_internal/manifest'\nimport {exitCodes} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {\n type BrettAccess,\n type BrettWorkspace,\n createStudio,\n deployWorkbenchApp,\n getApplicationUrl,\n getWorkbench,\n toWorkbenchPayload,\n} from '@sanity/workbench-cli/deploy'\nimport {type StudioManifest} from 'sanity'\nimport {c as createTar} from 'tar'\n\nimport {createDeployment, type UserApplication} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {NO_ORGANIZATION_ID, NO_PROJECT_ID} from '../../util/errorMessages.js'\nimport {buildStudio} from '../build/buildStudio.js'\nimport {createStudioUserApplication} from './createUserApplication.js'\nimport {\n checkAutoUpdates,\n checkBuild,\n checkPackageVersion,\n checkStudioTarget,\n type DeployCheckReporter,\n verifyOutputDir,\n} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {listDeploymentFiles, reportInterfaces} from './deploymentPlan.js'\nimport {type DeployPayload, type DeployResult, runDeploy} from './deployRunner.js'\nimport {deployStudioSchemasAndManifests} from './deployStudioSchemasAndManifests.js'\nimport {findUserApplicationForStudio} from './findUserApplication.js'\nimport {type DeployAppOptions} from './types.js'\n\nconst STUDIO_PACKAGE = 'sanity'\n\nexport function deployStudio(options: DeployAppOptions): Promise<void> {\n return runDeploy(options, {\n listFiles: ({flags, projectRoot, sourceDir}) =>\n flags.external ? Promise.resolve([]) : listDeploymentFiles(sourceDir, projectRoot.directory),\n run: runStudioDeployment,\n type: 'studio',\n })\n}\n\n/** Validates the deploy, extracts and uploads the schema, and ships the build. */\nasync function runStudioDeployment(\n options: DeployAppOptions,\n reporter: DeployCheckReporter,\n): Promise<DeployResult | void> {\n const {cliConfig, flags, output, sourceDir} = options\n const workDir = options.projectRoot.directory\n const isExternal = !!flags.external\n const workbench = getWorkbench(cliConfig)\n const isWorkbenchApp = workbench !== null\n const projectId = cliConfig.api?.projectId\n const organizationId = cliConfig.app?.organizationId\n const appId = getAppId(cliConfig)\n const dryRun = !!flags['dry-run']\n\n // A federated app deploys through Sanity's build/hosting pipeline, which\n // --external skips — fail before doing any other work.\n if (isExternal && isWorkbenchApp) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'Deploying a federated application to an external host is not yet supported',\n solution: 'Remove the --external flag to deploy to Sanity hosting',\n status: 'fail',\n })\n }\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.slug\n : ''\n\n const isAutoUpdating = checkAutoUpdates(reporter, {cliConfig, flags})\n\n const version = await checkPackageVersion(reporter, {\n moduleName: STUDIO_PACKAGE,\n workDir,\n })\n\n reporter.report(\n projectId\n ? {message: `Project: ${projectId}`, status: 'pass'}\n : {\n message: NO_PROJECT_ID,\n solution: 'Add `api.projectId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n\n // Workbench studios deploy to Brett (which needs the org); plain studios\n // resolve/create on user-applications, unchanged.\n let application: UserApplication | null = null\n let studioCreated = false\n let workbenchApp: object | undefined\n if (workbench && !isExternal) {\n reporter.report(\n organizationId\n ? {message: `Organization: ${organizationId}`, status: 'pass'}\n : {\n message: NO_ORGANIZATION_ID,\n solution: 'Add `app.organizationId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n workbenchApp = (\n await checkStudioTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n organizationId,\n slug: workbench.slug,\n title: appTitle,\n })\n )?.application\n } else {\n ;({application, created: studioCreated} = await resolveStudioApplication(options, {\n dryRun,\n reporter,\n }))\n }\n\n // A first deploy mints the app id and the build inlines it; --no-build would\n // ship an existing bundle carrying a different id, so it can't be a first deploy.\n if (workbench && !isExternal && !appId && !flags.build) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'A first deploy cannot skip the build (--no-build)',\n solution: 'Drop --no-build so the new application id is inlined into the build',\n status: 'fail',\n })\n }\n\n // Read up front so a bad icon path fails before we create or build.\n const appIcon =\n !dryRun && !isExternal && workbench?.icon\n ? await readIconFromPath(workDir, workbench.icon)\n : undefined\n\n // Create the studio before the build so the bundle carries its real id. A\n // redeploy already has it from `deployment.appId`; a dry run skips creation.\n let applicationId = appId\n let applicationCreated = false\n let rollbackApp: (() => Promise<void>) | undefined\n if (!dryRun && workbench && !isExternal && organizationId && !applicationId) {\n const created = await createStudio({\n name: workbench.name,\n organizationId,\n projectId,\n slug: workbench.slug,\n title: appTitle,\n visibility: workbench.visibility,\n })\n workbenchApp = created.application\n applicationId = created.application.id\n rollbackApp = created.rollback\n applicationCreated = true\n }\n\n // A record created above is stranded at its slug (and blocks retries) if any\n // step before it fully deploys fails, so undo the creation on failure.\n try {\n await checkBuild(reporter, {\n build: () =>\n buildStudio({\n applicationId: workbench ? applicationId : undefined,\n autoUpdatesEnabled: isAutoUpdating,\n calledFromDeploy: true,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n }),\n skipReason: studioBuildSkipReason({build: flags.build, isExternal}),\n successMessage: 'Studio built',\n })\n\n if (!isExternal) {\n await verifyOutputDir({isWorkbenchApp, reporter, sourceDir})\n }\n\n // An external studio hosts its own bundle, so nothing registers.\n const interfaces = workbench && !isExternal ? reportInterfaces(reporter, workbench) : null\n\n const payload: DeployPayload = {\n appId: appId ?? null,\n isAutoUpdating,\n ...(organizationId ? {organizationId} : {}),\n ...(projectId ? {projectId} : {}),\n type: 'studio',\n version,\n ...toWorkbenchPayload(workbench, {interfaces, title: appTitle}),\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return {application: null, payload}\n\n // A real deploy has already exited if anything failed; landing here without a\n // resolved version means the deploy target was never resolved.\n if (!version) return\n\n const studioManifest = await uploadStudioSchema(options, {\n applicationId: workbench ? applicationId : undefined,\n isExternal,\n })\n // The studio was created (or resolved from `deployment.appId`) before the\n // build, so this only ships the deployment; plain studios use user-applications.\n if (workbench && !isExternal && organizationId && applicationId) {\n await deployWorkbenchApp({\n access: toAccess(studioManifest),\n app: cliConfig.app,\n applicationId,\n icon: appIcon,\n isApp: false,\n isAutoUpdating,\n label: 'Deploying studio',\n // Once the deployment is live, a metadata-sync failure must not delete\n // the studio.\n onDeployed: () => {\n rollbackApp = undefined\n },\n sourceDir,\n title: appTitle,\n version,\n visibility: workbench.visibility,\n workspaces: toWorkspaces(studioManifest),\n })\n const url = getApplicationUrl({id: applicationId, organizationId, type: 'studio'})\n logWorkbenchStudioDeployed({applicationId, cliConfig, output, url})\n return {\n action: applicationCreated ? 'create' : 'update',\n application: workbenchApp ?? null,\n payload,\n url,\n }\n }\n\n if (!application) return\n const location = await shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n })\n\n return {\n action: studioCreated ? 'create' : 'update',\n application,\n payload,\n url: location,\n }\n } catch (err) {\n await rollbackApp?.()\n throw err\n }\n}\n\n/**\n * Finds the application a real deploy targets, registering a studio host when\n * none is configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveStudioApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplication | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const isExternal = !!flags.external\n const appId = getAppId(cliConfig)\n // Sets the title on a newly registered studio; blank falls back to undefined\n const title = flags.title?.trim() || undefined\n\n if (dryRun) {\n await checkStudioTarget(reporter, {\n appId,\n isExternal,\n projectId: cliConfig.api?.projectId,\n studioHost: cliConfig.studioHost,\n title,\n urlFlag: flags.url,\n })\n return {application: null, created: false}\n }\n\n const projectId = cliConfig.api?.projectId ?? ''\n // `created` is true when a configured-but-unregistered host was just registered.\n const {application, created} = await findUserApplicationForStudio({\n appId,\n isExternal,\n output,\n projectId,\n studioHost: cliConfig.studioHost,\n title,\n unattended: !!flags.yes,\n urlFlag: flags.url,\n })\n\n if (!application) {\n if (isExternal) {\n output.log('Your project has not been registered with an external studio URL.')\n output.log('Please enter the full URL where your studio is hosted.')\n } else {\n output.log('Your project has not been assigned a studio hostname.')\n output.log('To deploy your Sanity Studio to our hosted sanity.studio service,')\n output.log('you will need one. Please enter the subdomain you want to use.')\n }\n\n const registered = await createStudioUserApplication({\n projectId,\n title,\n urlType: isExternal ? 'external' : 'internal',\n })\n deployDebug('Created user application', registered)\n return {application: registered, created: true}\n }\n\n deployDebug('Found user application', application)\n return {application, created}\n}\n\n/** Extracts the studio schema and manifest and uploads them to the schema store. */\nasync function uploadStudioSchema(\n options: DeployAppOptions,\n {applicationId, isExternal}: {applicationId?: string; isExternal: boolean},\n): Promise<StudioManifest | null> {\n const {cliConfig, flags, output, projectRoot, sourceDir} = options\n\n let studioManifest: StudioManifest | null = null\n try {\n studioManifest = await deployStudioSchemasAndManifests(\n {\n applicationId,\n configPath: projectRoot.path,\n isExternal,\n outPath: `${sourceDir}/static`,\n projectId: cliConfig.api?.projectId ?? '',\n schemaRequired: flags['schema-required'],\n verbose: flags.verbose,\n workDir: projectRoot.directory,\n },\n output,\n )\n } catch (error) {\n deployDebug('Error deploying studio schemas and manifests', error)\n if (error instanceof SchemaExtractionError && error.validation?.length) {\n output.error(formatSchemaValidation(error.validation), {exit: exitCodes.RUNTIME_ERROR})\n }\n output.error(`Error deploying studio schemas and manifests: ${error}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (!studioManifest) {\n output.error('Failed to generate studio manifest. Please check your schemas and manifests.', {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n return studioManifest\n}\n\nasync function shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n isExternal: boolean\n options: DeployAppOptions\n studioManifest: StudioManifest | null\n version: string\n}): Promise<string> {\n const {cliConfig, output, sourceDir} = options\n\n let tarball: Gzip | undefined\n if (!isExternal) {\n tarball = createTar({cwd: dirname(sourceDir)}, [basename(sourceDir)]).pipe(createGzip())\n }\n\n const spin = spinner(isExternal ? 'Registering studio' : 'Deploying to sanity.studio').start()\n let location: string\n try {\n ;({location} = await createDeployment({\n applicationId: application.id,\n isApp: false,\n isAutoUpdating,\n manifest: studioManifest,\n projectId: cliConfig.api?.projectId,\n tarball,\n version,\n }))\n } catch (error) {\n spin.fail()\n throw error\n }\n spin.succeed()\n\n const named = application.title ? ` — \"${application.title}\"` : ''\n output.log(\n isExternal\n ? `\\nSuccess! Studio registered${named}`\n : `\\nSuccess! Studio deployed to ${styleText('cyan', location)}${named}`,\n )\n\n if (getAppId(cliConfig)) return location\n\n const example = `Example:\nexport default defineCliConfig({\n //…\n deployment: {\n ${styleText('cyan', `appId: '${application.id}'`)},\n },\n //…\n})`\n output.log(`\\nAdd ${styleText('cyan', `appId: '${application.id}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n output.log(`\\n${example}`)\n\n return location\n}\n\n/**\n * One `datasets` access entry per unique workspace dataset, with a `resourceId`\n * of `\"<projectId>.<dataset>\"`. Deduped, since workspaces can share a dataset.\n */\nfunction toAccess(manifest: StudioManifest | null): BrettAccess[] {\n const resourceIds = new Set(\n (manifest?.workspaces ?? []).map((w) => `${w.projectId}.${w.dataset}`),\n )\n return [...resourceIds].map(\n (resourceId) => ({resourceId, resourceType: 'dataset'}) satisfies BrettAccess,\n )\n}\n\nfunction toWorkspaces(manifest: StudioManifest | null): BrettWorkspace[] {\n return (manifest?.workspaces ?? []).map((workspace) => ({\n basePath: workspace.basePath,\n dataset: workspace.dataset,\n icon: workspace.icon,\n name: workspace.name,\n projectId: workspace.projectId,\n schemaDescriptorId: workspace.schemaDescriptorId,\n subtitle: workspace.subtitle,\n title: workspace.title,\n }))\n}\n\n/** Renders the workbench studio's deploy result; the appId hint shows only when none is configured. */\nfunction logWorkbenchStudioDeployed({\n applicationId,\n cliConfig,\n output,\n url,\n}: {\n applicationId: string\n cliConfig: DeployAppOptions['cliConfig']\n output: DeployAppOptions['output']\n url: string\n}): void {\n output.log(`\\nSuccess! Studio deployed to ${styleText('cyan', url)}`)\n if (getAppId(cliConfig)) return\n\n output.log(`\\nAdd ${styleText('cyan', `appId: '${applicationId}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n}\n\nfunction studioBuildSkipReason({build, isExternal}: {build: boolean; isExternal: boolean}) {\n if (isExternal) return 'Build skipped for externally hosted studios'\n if (!build) return 'Build skipped (--no-build) — validating existing output directory'\n return\n}\n"],"names":["basename","dirname","styleText","createGzip","formatSchemaValidation","SchemaExtractionError","readIconFromPath","exitCodes","spinner","createStudio","deployWorkbenchApp","getApplicationUrl","getWorkbench","toWorkbenchPayload","c","createTar","createDeployment","getAppId","NO_ORGANIZATION_ID","NO_PROJECT_ID","buildStudio","createStudioUserApplication","checkAutoUpdates","checkBuild","checkPackageVersion","checkStudioTarget","verifyOutputDir","deployDebug","listDeploymentFiles","reportInterfaces","runDeploy","deployStudioSchemasAndManifests","findUserApplicationForStudio","STUDIO_PACKAGE","deployStudio","options","listFiles","flags","projectRoot","sourceDir","external","Promise","resolve","directory","run","runStudioDeployment","type","reporter","cliConfig","output","workDir","isExternal","workbench","isWorkbenchApp","projectId","api","organizationId","app","appId","dryRun","report","exitCode","USAGE_ERROR","message","solution","status","appTitle","title","trim","slug","isAutoUpdating","version","moduleName","application","studioCreated","workbenchApp","created","resolveStudioApplication","build","appIcon","icon","undefined","applicationId","applicationCreated","rollbackApp","name","visibility","id","rollback","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","studioBuildSkipReason","successMessage","interfaces","payload","studioManifest","uploadStudioSchema","access","toAccess","isApp","label","onDeployed","workspaces","toWorkspaces","url","logWorkbenchStudioDeployed","action","location","shipStudioDeployment","err","studioHost","urlFlag","unattended","yes","log","registered","urlType","configPath","path","outPath","schemaRequired","verbose","error","validation","length","exit","RUNTIME_ERROR","tarball","cwd","pipe","spin","start","manifest","fail","succeed","named","example","resourceIds","Set","map","w","dataset","resourceId","resourceType","workspace","basePath","schemaDescriptorId","subtitle"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/deploy/deployStudio.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip, type Gzip} from 'node:zlib'\n\nimport {formatSchemaValidation, SchemaExtractionError} from '@sanity/cli-build/_internal/extract'\nimport {readIconFromPath} from '@sanity/cli-build/_internal/manifest'\nimport {exitCodes} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {\n type BrettAccess,\n type BrettWorkspace,\n createStudio,\n deployWorkbenchApp,\n getApplicationUrl,\n getWorkbench,\n toWorkbenchPayload,\n} from '@sanity/workbench-cli/deploy'\nimport {type StudioManifest} from 'sanity'\nimport {c as createTar} from 'tar'\n\nimport {createDeployment, type UserApplication} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {NO_ORGANIZATION_ID, NO_PROJECT_ID} from '../../util/errorMessages.js'\nimport {buildStudio} from '../build/buildStudio.js'\nimport {createStudioUserApplication} from './createUserApplication.js'\nimport {\n checkAutoUpdates,\n checkBuild,\n checkPackageVersion,\n checkStudioTarget,\n type DeployCheckReporter,\n verifyOutputDir,\n} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {listDeploymentFiles, reportInterfaces} from './deploymentPlan.js'\nimport {type DeployPayload, type DeployResult, runDeploy} from './deployRunner.js'\nimport {deployStudioSchemasAndManifests} from './deployStudioSchemasAndManifests.js'\nimport {findUserApplicationForStudio} from './findUserApplication.js'\nimport {type DeployAppOptions} from './types.js'\n\nconst STUDIO_PACKAGE = 'sanity'\n\nexport function deployStudio(options: DeployAppOptions): Promise<void> {\n return runDeploy(options, {\n listFiles: ({flags, projectRoot, sourceDir}) =>\n flags.external ? Promise.resolve([]) : listDeploymentFiles(sourceDir, projectRoot.directory),\n run: runStudioDeployment,\n type: 'studio',\n })\n}\n\n/** Validates the deploy, extracts and uploads the schema, and ships the build. */\nasync function runStudioDeployment(\n options: DeployAppOptions,\n reporter: DeployCheckReporter,\n): Promise<DeployResult | void> {\n const {cliConfig, flags, output, sourceDir} = options\n const workDir = options.projectRoot.directory\n const isExternal = !!flags.external\n const workbench = getWorkbench(cliConfig)\n const isWorkbenchApp = workbench !== null\n const projectId = cliConfig.api?.projectId\n const organizationId = cliConfig.app?.organizationId\n const appId = getAppId(cliConfig)\n const dryRun = !!flags['dry-run']\n\n // A federated app deploys through Sanity's build/hosting pipeline, which\n // --external skips — fail before doing any other work.\n if (isExternal && isWorkbenchApp) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'Deploying a federated application to an external host is not yet supported',\n solution: 'Remove the --external flag to deploy to Sanity hosting',\n status: 'fail',\n })\n }\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.slug\n : ''\n\n const isAutoUpdating = checkAutoUpdates(reporter, {cliConfig, flags})\n\n const version = await checkPackageVersion(reporter, {\n moduleName: STUDIO_PACKAGE,\n workDir,\n })\n\n reporter.report(\n projectId\n ? {message: `Project: ${projectId}`, status: 'pass'}\n : {\n message: NO_PROJECT_ID,\n solution: 'Add `api.projectId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n\n // Workbench studios deploy to Brett (which needs the org); plain studios\n // resolve/create on user-applications, unchanged.\n let application: UserApplication | null = null\n let studioCreated = false\n let workbenchApp: object | undefined\n if (workbench && !isExternal) {\n reporter.report(\n organizationId\n ? {message: `Organization: ${organizationId}`, status: 'pass'}\n : {\n message: NO_ORGANIZATION_ID,\n solution: 'Add `app.organizationId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n workbenchApp = (\n await checkStudioTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n organizationId,\n slug: workbench.slug,\n title: appTitle,\n })\n )?.application\n } else {\n ;({application, created: studioCreated} = await resolveStudioApplication(options, {\n dryRun,\n reporter,\n }))\n }\n\n // A first deploy mints the app id and the build inlines it; --no-build would\n // ship an existing bundle carrying a different id, so it can't be a first deploy.\n if (workbench && !isExternal && !appId && !flags.build) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'A first deploy cannot skip the build (--no-build)',\n solution: 'Drop --no-build so the new application id is inlined into the build',\n status: 'fail',\n })\n }\n\n // Read up front so a bad icon path fails before we create or build.\n const appIcon =\n !dryRun && !isExternal && workbench?.icon\n ? await readIconFromPath(workDir, workbench.icon)\n : undefined\n\n // Create the studio before the build so the bundle carries its real id. A\n // redeploy already has it from `deployment.appId`; a dry run skips creation.\n let applicationId = appId\n let applicationCreated = false\n let rollbackApp: (() => Promise<void>) | undefined\n if (!dryRun && workbench && !isExternal && organizationId && !applicationId) {\n const created = await createStudio({\n name: workbench.name,\n organizationId,\n projectId,\n slug: workbench.slug,\n title: appTitle,\n visibility: workbench.visibility,\n })\n workbenchApp = created.application\n applicationId = created.application.id\n rollbackApp = created.rollback\n applicationCreated = true\n }\n\n // A record created above is stranded at its slug (and blocks retries) if any\n // step before it fully deploys fails, so undo the creation on failure.\n try {\n await checkBuild(reporter, {\n build: () =>\n buildStudio({\n applicationId: workbench ? applicationId : undefined,\n autoUpdatesEnabled: isAutoUpdating,\n calledFromDeploy: true,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n }),\n skipReason: studioBuildSkipReason({build: flags.build, isExternal}),\n successMessage: 'Studio built',\n })\n\n if (!isExternal) {\n await verifyOutputDir({isWorkbenchApp, reporter, sourceDir})\n }\n\n // An external studio hosts its own bundle, so nothing registers.\n const interfaces = workbench && !isExternal ? reportInterfaces(reporter, workbench) : null\n\n const payload: DeployPayload = {\n appId: appId ?? null,\n isAutoUpdating,\n ...(organizationId ? {organizationId} : {}),\n ...(projectId ? {projectId} : {}),\n type: 'studio',\n version,\n ...toWorkbenchPayload(workbench, {interfaces, title: appTitle}),\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return {application: null, payload}\n\n // A real deploy has already exited if anything failed; landing here without a\n // resolved version means the deploy target was never resolved.\n if (!version) return\n\n const studioManifest = await uploadStudioSchema(options, {\n applicationId: workbench ? applicationId : undefined,\n isExternal,\n })\n // The studio was created (or resolved from `deployment.appId`) before the\n // build, so this only ships the deployment; plain studios use user-applications.\n if (workbench && !isExternal && organizationId && applicationId) {\n await deployWorkbenchApp({\n access: toAccess(studioManifest),\n app: cliConfig.app,\n applicationId,\n icon: appIcon,\n isApp: false,\n isAutoUpdating,\n label: 'Deploying studio',\n // Once the deployment is live, a metadata-sync failure must not delete\n // the studio.\n onDeployed: () => {\n rollbackApp = undefined\n },\n slug: workbench.slug,\n sourceDir,\n title: appTitle,\n version,\n visibility: workbench.visibility,\n workspaces: toWorkspaces(studioManifest),\n })\n const url = getApplicationUrl({id: applicationId, organizationId, type: 'studio'})\n logWorkbenchStudioDeployed({applicationId, cliConfig, output, url})\n return {\n action: applicationCreated ? 'create' : 'update',\n application: workbenchApp ?? null,\n payload,\n url,\n }\n }\n\n if (!application) return\n const location = await shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n })\n\n return {\n action: studioCreated ? 'create' : 'update',\n application,\n payload,\n url: location,\n }\n } catch (err) {\n await rollbackApp?.()\n throw err\n }\n}\n\n/**\n * Finds the application a real deploy targets, registering a studio host when\n * none is configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveStudioApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplication | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const isExternal = !!flags.external\n const appId = getAppId(cliConfig)\n // Sets the title on a newly registered studio; blank falls back to undefined\n const title = flags.title?.trim() || undefined\n\n if (dryRun) {\n await checkStudioTarget(reporter, {\n appId,\n isExternal,\n projectId: cliConfig.api?.projectId,\n studioHost: cliConfig.studioHost,\n title,\n urlFlag: flags.url,\n })\n return {application: null, created: false}\n }\n\n const projectId = cliConfig.api?.projectId ?? ''\n // `created` is true when a configured-but-unregistered host was just registered.\n const {application, created} = await findUserApplicationForStudio({\n appId,\n isExternal,\n output,\n projectId,\n studioHost: cliConfig.studioHost,\n title,\n unattended: !!flags.yes,\n urlFlag: flags.url,\n })\n\n if (!application) {\n if (isExternal) {\n output.log('Your project has not been registered with an external studio URL.')\n output.log('Please enter the full URL where your studio is hosted.')\n } else {\n output.log('Your project has not been assigned a studio hostname.')\n output.log('To deploy your Sanity Studio to our hosted sanity.studio service,')\n output.log('you will need one. Please enter the subdomain you want to use.')\n }\n\n const registered = await createStudioUserApplication({\n projectId,\n title,\n urlType: isExternal ? 'external' : 'internal',\n })\n deployDebug('Created user application', registered)\n return {application: registered, created: true}\n }\n\n deployDebug('Found user application', application)\n return {application, created}\n}\n\n/** Extracts the studio schema and manifest and uploads them to the schema store. */\nasync function uploadStudioSchema(\n options: DeployAppOptions,\n {applicationId, isExternal}: {applicationId?: string; isExternal: boolean},\n): Promise<StudioManifest | null> {\n const {cliConfig, flags, output, projectRoot, sourceDir} = options\n\n let studioManifest: StudioManifest | null = null\n try {\n studioManifest = await deployStudioSchemasAndManifests(\n {\n applicationId,\n configPath: projectRoot.path,\n isExternal,\n outPath: `${sourceDir}/static`,\n projectId: cliConfig.api?.projectId ?? '',\n schemaRequired: flags['schema-required'],\n verbose: flags.verbose,\n workDir: projectRoot.directory,\n },\n output,\n )\n } catch (error) {\n deployDebug('Error deploying studio schemas and manifests', error)\n if (error instanceof SchemaExtractionError && error.validation?.length) {\n output.error(formatSchemaValidation(error.validation), {exit: exitCodes.RUNTIME_ERROR})\n }\n output.error(`Error deploying studio schemas and manifests: ${error}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (!studioManifest) {\n output.error('Failed to generate studio manifest. Please check your schemas and manifests.', {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n return studioManifest\n}\n\nasync function shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n isExternal: boolean\n options: DeployAppOptions\n studioManifest: StudioManifest | null\n version: string\n}): Promise<string> {\n const {cliConfig, output, sourceDir} = options\n\n let tarball: Gzip | undefined\n if (!isExternal) {\n tarball = createTar({cwd: dirname(sourceDir)}, [basename(sourceDir)]).pipe(createGzip())\n }\n\n const spin = spinner(isExternal ? 'Registering studio' : 'Deploying to sanity.studio').start()\n let location: string\n try {\n ;({location} = await createDeployment({\n applicationId: application.id,\n isApp: false,\n isAutoUpdating,\n manifest: studioManifest,\n projectId: cliConfig.api?.projectId,\n tarball,\n version,\n }))\n } catch (error) {\n spin.fail()\n throw error\n }\n spin.succeed()\n\n const named = application.title ? ` — \"${application.title}\"` : ''\n output.log(\n isExternal\n ? `\\nSuccess! Studio registered${named}`\n : `\\nSuccess! Studio deployed to ${styleText('cyan', location)}${named}`,\n )\n\n if (getAppId(cliConfig)) return location\n\n const example = `Example:\nexport default defineCliConfig({\n //…\n deployment: {\n ${styleText('cyan', `appId: '${application.id}'`)},\n },\n //…\n})`\n output.log(`\\nAdd ${styleText('cyan', `appId: '${application.id}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n output.log(`\\n${example}`)\n\n return location\n}\n\n/**\n * One `datasets` access entry per unique workspace dataset, with a `resourceId`\n * of `\"<projectId>.<dataset>\"`. Deduped, since workspaces can share a dataset.\n */\nfunction toAccess(manifest: StudioManifest | null): BrettAccess[] {\n const resourceIds = new Set(\n (manifest?.workspaces ?? []).map((w) => `${w.projectId}.${w.dataset}`),\n )\n return [...resourceIds].map(\n (resourceId) => ({resourceId, resourceType: 'dataset'}) satisfies BrettAccess,\n )\n}\n\nfunction toWorkspaces(manifest: StudioManifest | null): BrettWorkspace[] {\n return (manifest?.workspaces ?? []).map((workspace) => ({\n basePath: workspace.basePath,\n dataset: workspace.dataset,\n icon: workspace.icon,\n name: workspace.name,\n projectId: workspace.projectId,\n schemaDescriptorId: workspace.schemaDescriptorId,\n subtitle: workspace.subtitle,\n title: workspace.title,\n }))\n}\n\n/** Renders the workbench studio's deploy result; the appId hint shows only when none is configured. */\nfunction logWorkbenchStudioDeployed({\n applicationId,\n cliConfig,\n output,\n url,\n}: {\n applicationId: string\n cliConfig: DeployAppOptions['cliConfig']\n output: DeployAppOptions['output']\n url: string\n}): void {\n output.log(`\\nSuccess! Studio deployed to ${styleText('cyan', url)}`)\n if (getAppId(cliConfig)) return\n\n output.log(`\\nAdd ${styleText('cyan', `appId: '${applicationId}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n}\n\nfunction studioBuildSkipReason({build, isExternal}: {build: boolean; isExternal: boolean}) {\n if (isExternal) return 'Build skipped for externally hosted studios'\n if (!build) return 'Build skipped (--no-build) — validating existing output directory'\n return\n}\n"],"names":["basename","dirname","styleText","createGzip","formatSchemaValidation","SchemaExtractionError","readIconFromPath","exitCodes","spinner","createStudio","deployWorkbenchApp","getApplicationUrl","getWorkbench","toWorkbenchPayload","c","createTar","createDeployment","getAppId","NO_ORGANIZATION_ID","NO_PROJECT_ID","buildStudio","createStudioUserApplication","checkAutoUpdates","checkBuild","checkPackageVersion","checkStudioTarget","verifyOutputDir","deployDebug","listDeploymentFiles","reportInterfaces","runDeploy","deployStudioSchemasAndManifests","findUserApplicationForStudio","STUDIO_PACKAGE","deployStudio","options","listFiles","flags","projectRoot","sourceDir","external","Promise","resolve","directory","run","runStudioDeployment","type","reporter","cliConfig","output","workDir","isExternal","workbench","isWorkbenchApp","projectId","api","organizationId","app","appId","dryRun","report","exitCode","USAGE_ERROR","message","solution","status","appTitle","title","trim","slug","isAutoUpdating","version","moduleName","application","studioCreated","workbenchApp","created","resolveStudioApplication","build","appIcon","icon","undefined","applicationId","applicationCreated","rollbackApp","name","visibility","id","rollback","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","studioBuildSkipReason","successMessage","interfaces","payload","studioManifest","uploadStudioSchema","access","toAccess","isApp","label","onDeployed","workspaces","toWorkspaces","url","logWorkbenchStudioDeployed","action","location","shipStudioDeployment","err","studioHost","urlFlag","unattended","yes","log","registered","urlType","configPath","path","outPath","schemaRequired","verbose","error","validation","length","exit","RUNTIME_ERROR","tarball","cwd","pipe","spin","start","manifest","fail","succeed","named","example","resourceIds","Set","map","w","dataset","resourceId","resourceType","workspace","basePath","schemaDescriptorId","subtitle"],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { configDefinition } from '@sanity/codegen';
|
|
2
|
+
import { isValiError, parse } from 'valibot';
|
|
3
|
+
/**
|
|
4
|
+
* Applies `@sanity/codegen` schema defaults to a partial typegen config.
|
|
5
|
+
*
|
|
6
|
+
* `@sanity/codegen` 8.1.0 moved `configDefinition` from Zod to Valibot, so the
|
|
7
|
+
* schema is no longer callable as `configDefinition.parse()`.
|
|
8
|
+
*/ export function parseTypegenConfig(input = {}) {
|
|
9
|
+
try {
|
|
10
|
+
return parse(configDefinition, input);
|
|
11
|
+
} catch (error) {
|
|
12
|
+
if (isValiError(error)) {
|
|
13
|
+
throw new TypeError(`Error in typegen config\n ${error.issues.map((issue)=>issue.message).join('\n')}`, {
|
|
14
|
+
cause: error
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
throw error;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=parseTypegenConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/typegen/parseTypegenConfig.ts"],"sourcesContent":["import {configDefinition, type TypeGenConfig} from '@sanity/codegen'\nimport {isValiError, parse} from 'valibot'\n\n/**\n * Applies `@sanity/codegen` schema defaults to a partial typegen config.\n *\n * `@sanity/codegen` 8.1.0 moved `configDefinition` from Zod to Valibot, so the\n * schema is no longer callable as `configDefinition.parse()`.\n */\nexport function parseTypegenConfig(input: unknown = {}): TypeGenConfig {\n try {\n return parse(configDefinition, input)\n } catch (error) {\n if (isValiError(error)) {\n throw new TypeError(\n `Error in typegen config\\n ${error.issues.map((issue) => issue.message).join('\\n')}`,\n {cause: error},\n )\n }\n throw error\n }\n}\n"],"names":["configDefinition","isValiError","parse","parseTypegenConfig","input","error","TypeError","issues","map","issue","message","join","cause"],"mappings":"AAAA,SAAQA,gBAAgB,QAA2B,kBAAiB;AACpE,SAAQC,WAAW,EAAEC,KAAK,QAAO,UAAS;AAE1C;;;;;CAKC,GACD,OAAO,SAASC,mBAAmBC,QAAiB,CAAC,CAAC;IACpD,IAAI;QACF,OAAOF,MAAMF,kBAAkBI;IACjC,EAAE,OAAOC,OAAO;QACd,IAAIJ,YAAYI,QAAQ;YACtB,MAAM,IAAIC,UACR,CAAC,0BAA0B,EAAED,MAAME,MAAM,CAACC,GAAG,CAAC,CAACC,QAAUA,MAAMC,OAAO,EAAEC,IAAI,CAAC,OAAO,EACpF;gBAACC,OAAOP;YAAK;QAEjB;QACA,MAAMA;IACR;AACF"}
|
|
@@ -4,9 +4,10 @@ import { Flags } from '@oclif/core';
|
|
|
4
4
|
import { CLIError } from '@oclif/core/errors';
|
|
5
5
|
import { exitCodes, SanityCommand } from '@sanity/cli-core';
|
|
6
6
|
import { spinner } from '@sanity/cli-core/ux';
|
|
7
|
-
import {
|
|
7
|
+
import { readConfig, runTypegenGenerate, runTypegenWatcher, TypegenWatchModeTrace, TypesGeneratedTrace } from '@sanity/codegen';
|
|
8
8
|
import omit from 'lodash-es/omit.js';
|
|
9
9
|
import once from 'lodash-es/once.js';
|
|
10
|
+
import { parseTypegenConfig } from '../../actions/typegen/parseTypegenConfig.js';
|
|
10
11
|
import { createTypegenProgressRenderer } from '../../actions/typegen/renderTypegenProgress.js';
|
|
11
12
|
const description = `Sanity TypeGen
|
|
12
13
|
|
|
@@ -87,7 +88,7 @@ export class TypegenGenerateCommand extends SanityCommand {
|
|
|
87
88
|
The config from the Sanity CLI config is used.
|
|
88
89
|
`));
|
|
89
90
|
return {
|
|
90
|
-
config:
|
|
91
|
+
config: parseTypegenConfig(config.typegen || {}),
|
|
91
92
|
path: rootDir.path,
|
|
92
93
|
type: 'cli',
|
|
93
94
|
workDir
|
|
@@ -106,7 +107,7 @@ export class TypegenGenerateCommand extends SanityCommand {
|
|
|
106
107
|
}
|
|
107
108
|
spin.succeed(`Config loaded from sanity.cli.ts`);
|
|
108
109
|
return {
|
|
109
|
-
config:
|
|
110
|
+
config: parseTypegenConfig(config.typegen || {}),
|
|
110
111
|
path: rootDir.path,
|
|
111
112
|
type: 'cli',
|
|
112
113
|
workDir
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/typegen/generate.ts"],"sourcesContent":["import {stat} from 'node:fs/promises'\nimport {styleText} from 'node:util'\n\nimport {Flags} from '@oclif/core'\nimport {CLIError} from '@oclif/core/errors'\nimport {exitCodes, SanityCommand} from '@sanity/cli-core'\nimport {spinner, type SpinnerInstance} from '@sanity/cli-core/ux'\nimport {\n configDefinition,\n readConfig,\n runTypegenGenerate,\n runTypegenWatcher,\n type TypeGenConfig,\n TypegenWatchModeTrace,\n TypesGeneratedTrace,\n} from '@sanity/codegen'\nimport omit from 'lodash-es/omit.js'\nimport once from 'lodash-es/once.js'\n\nimport {createTypegenProgressRenderer} from '../../actions/typegen/renderTypegenProgress.js'\n\nconst description = `Sanity TypeGen\n\n${styleText('bold', 'Configuration:')}\nThis command can utilize configuration settings defined in a \\`sanity-typegen.json\\` file. These settings include:\n\n- \"path\": Specifies a glob pattern to locate your TypeScript or JavaScript files.\n Default: \"./src/**/*.{ts,tsx,js,jsx}\"\n\n- \"schema\": Defines the path to your Sanity schema file. This file should be generated using the \\`sanity schema extract\\` command.\n Default: \"schema.json\"\n\n- \"generates\": Indicates the path where the generated TypeScript type definitions will be saved.\n Default: \"./sanity.types.ts\"\n\nThe default configuration values listed above are used if not overridden in your \\`sanity-typegen.json\\` configuration file. To customize the behavior of the type generation, adjust these properties in the configuration file according to your project's needs.\n\n${styleText('bold', 'Note:')}\n- The \\`sanity schema extract\\` command is a prerequisite for extracting your Sanity Studio schema into a \\`schema.json\\` file, which is then used by the \\`sanity typegen generate\\` command to generate type definitions.`.trim()\n\nexport class TypegenGenerateCommand extends SanityCommand<typeof TypegenGenerateCommand> {\n static override description = description\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: `Generate TypeScript type definitions from a Sanity Studio schema extracted using the \\`sanity schema extract\\` command.`,\n },\n ]\n\n static override flags = {\n 'config-path': Flags.string({\n description:\n '[Default: sanity-typegen.json] Specifies the path to the typegen configuration file. This file should be a JSON file that contains settings for the type generation process.',\n }),\n watch: Flags.boolean({\n default: false,\n description: '[Default: false] Run the typegen in watch mode',\n }),\n }\n\n static override hiddenAliases: string[] = ['typegen:generate']\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(TypegenGenerateCommand)\n\n if (flags.watch) {\n await this.runWatcher()\n return\n }\n\n await this.runSingle()\n }\n\n private async getConfig(): Promise<{\n config: TypeGenConfig\n path?: string\n type: 'cli' | 'legacy'\n workDir: string\n }> {\n const spin = spinner({}).start('Loading config…')\n\n try {\n const {flags} = await this.parse(TypegenGenerateCommand)\n const rootDir = await this.getProjectRoot()\n const config = await this.getCliConfig()\n\n const configPath = flags['config-path']\n const workDir = rootDir.directory\n\n const legacyConfigPath = configPath || 'sanity-typegen.json'\n let hasLegacyConfig = false\n\n try {\n const file = await stat(legacyConfigPath)\n hasLegacyConfig = file.isFile()\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ENOENT' && configPath) {\n spin.fail()\n this.error(`Typegen config file not found: ${configPath}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (err instanceof Error && 'code' in err && err.code !== 'ENOENT') {\n spin.fail()\n this.error(`Error when checking if typegen config file exists: ${legacyConfigPath}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n if (config?.typegen && hasLegacyConfig) {\n spin.warn(\n styleText(\n 'yellow',\n `You've specified typegen in your Sanity CLI config, but also have a typegen config.\n\n The config from the Sanity CLI config is used.\n `,\n ),\n )\n\n return {\n config: configDefinition.parse(config.typegen || {}),\n path: rootDir.path,\n type: 'cli',\n workDir,\n }\n }\n\n if (hasLegacyConfig) {\n spin.warn(\n styleText(\n 'yellow',\n `The separate typegen config has been deprecated. Use \\`typegen\\` in the sanity CLI config instead.\n\n See: https://www.sanity.io/docs/help/configuring-typegen-in-sanity-cli-config`,\n ),\n )\n return {\n config: await readConfig(legacyConfigPath),\n path: legacyConfigPath,\n type: 'legacy',\n workDir,\n }\n }\n\n spin.succeed(`Config loaded from sanity.cli.ts`)\n\n return {\n config: configDefinition.parse(config.typegen || {}),\n path: rootDir.path,\n type: 'cli',\n workDir,\n }\n } catch (err) {\n // The config-file checks above already reported a user-facing error via\n // `this.error()` (an oclif CLIError). Re-throw those as-is instead of\n // wrapping them a second time and failing the spinner twice.\n if (err instanceof CLIError) throw err\n spin.fail()\n this.error(`An error occurred during config loading: ${err}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async runSingle(): Promise<void> {\n const trace = this.telemetry.trace(TypesGeneratedTrace)\n let spin: SpinnerInstance | undefined\n\n try {\n const {config: typegenConfig, type: typegenConfigMethod, workDir} = await this.getConfig()\n trace.start()\n\n spin = spinner({}).start('Loading schema…')\n const result = await runTypegenGenerate({\n config: typegenConfig,\n onProgress: createTypegenProgressRenderer(spin, {\n formatGeneratedCode: typegenConfig.formatGeneratedCode,\n generates: typegenConfig.generates,\n schema: typegenConfig.schema,\n }),\n workDir,\n })\n\n const traceStats = omit(result, 'code', 'duration')\n\n trace.log({\n configMethod: typegenConfigMethod,\n configOverloadClientMethods: typegenConfig.overloadClientMethods,\n ...traceStats,\n })\n trace.complete()\n } catch (error) {\n if (spin?.isSpinning) {\n spin.fail()\n }\n trace.error(error instanceof Error ? error : new Error(String(error)))\n this.error(`${error instanceof Error ? error.message : 'Unknown error'}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async runWatcher(): Promise<void> {\n const trace = this.telemetry.trace(TypegenWatchModeTrace)\n let spin: SpinnerInstance | undefined\n\n try {\n const {config: typegenConfig, workDir} = await this.getConfig()\n trace.start()\n\n let resolve: () => void = () => {}\n const promise = new Promise<void>((res) => {\n resolve = res\n })\n\n const watchSpin = spinner({}).start('Loading schema…')\n spin = watchSpin\n const rendererContext = {\n formatGeneratedCode: typegenConfig.formatGeneratedCode,\n generates: typegenConfig.generates,\n schema: typegenConfig.schema,\n }\n let renderProgress = createTypegenProgressRenderer(watchSpin, rendererContext)\n\n const typegenWatcher = runTypegenWatcher({\n config: typegenConfig,\n onProgress: (event) => {\n // 'schemaLoaded' is the first event of every generation cycle; the\n // renderer accumulates per-run state, so start each cycle fresh.\n if (event.type === 'schemaLoaded') {\n renderProgress = createTypegenProgressRenderer(watchSpin, rendererContext)\n }\n renderProgress(event)\n },\n workDir,\n })\n\n const stop = once(async () => {\n process.off('SIGINT', stop)\n process.off('SIGTERM', stop)\n\n if (watchSpin.isSpinning) {\n watchSpin.stop()\n }\n\n trace.log({\n step: 'stopped',\n ...typegenWatcher.getStats(),\n })\n trace.complete()\n\n try {\n await typegenWatcher.stop()\n } catch {\n // We're shutting down; a failure to close the watcher shouldn't hang\n // the process or surface as an unhandled rejection.\n }\n resolve()\n })\n\n process.on('SIGINT', stop)\n process.on('SIGTERM', stop)\n\n await promise\n } catch (error) {\n if (spin?.isSpinning) {\n spin.fail()\n }\n trace.error(error instanceof Error ? error : new Error(String(error)))\n this.error(`${error instanceof Error ? error.message : 'Unknown error'}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n}\n"],"names":["stat","styleText","Flags","CLIError","exitCodes","SanityCommand","spinner","configDefinition","readConfig","runTypegenGenerate","runTypegenWatcher","TypegenWatchModeTrace","TypesGeneratedTrace","omit","once","createTypegenProgressRenderer","description","trim","TypegenGenerateCommand","examples","command","flags","string","watch","boolean","default","hiddenAliases","run","parse","runWatcher","runSingle","getConfig","spin","start","rootDir","getProjectRoot","config","getCliConfig","configPath","workDir","directory","legacyConfigPath","hasLegacyConfig","file","isFile","err","Error","code","fail","error","exit","RUNTIME_ERROR","typegen","warn","path","type","succeed","trace","telemetry","typegenConfig","typegenConfigMethod","result","onProgress","formatGeneratedCode","generates","schema","traceStats","log","configMethod","configOverloadClientMethods","overloadClientMethods","complete","isSpinning","String","message","resolve","promise","Promise","res","watchSpin","rendererContext","renderProgress","typegenWatcher","event","stop","process","off","step","getStats","on"],"mappings":"AAAA,SAAQA,IAAI,QAAO,mBAAkB;AACrC,SAAQC,SAAS,QAAO,YAAW;AAEnC,SAAQC,KAAK,QAAO,cAAa;AACjC,SAAQC,QAAQ,QAAO,qBAAoB;AAC3C,SAAQC,SAAS,EAAEC,aAAa,QAAO,mBAAkB;AACzD,SAAQC,OAAO,QAA6B,sBAAqB;AACjE,SACEC,gBAAgB,EAChBC,UAAU,EACVC,kBAAkB,EAClBC,iBAAiB,EAEjBC,qBAAqB,EACrBC,mBAAmB,QACd,kBAAiB;AACxB,OAAOC,UAAU,oBAAmB;AACpC,OAAOC,UAAU,oBAAmB;AAEpC,SAAQC,6BAA6B,QAAO,iDAAgD;AAE5F,MAAMC,cAAc,CAAC;;AAErB,EAAEf,UAAU,QAAQ,kBAAkB;;;;;;;;;;;;;;AActC,EAAEA,UAAU,QAAQ,SAAS;2NAC8L,CAAC,CAACgB,IAAI;AAEjO,OAAO,MAAMC,+BAA+Bb;IAC1C,OAAgBW,cAAcA,YAAW;IAEzC,OAAgBG,WAAW;QACzB;YACEC,SAAS;YACTJ,aAAa,CAAC,uHAAuH,CAAC;QACxI;KACD,CAAA;IAED,OAAgBK,QAAQ;QACtB,eAAenB,MAAMoB,MAAM,CAAC;YAC1BN,aACE;QACJ;QACAO,OAAOrB,MAAMsB,OAAO,CAAC;YACnBC,SAAS;YACTT,aAAa;QACf;IACF,EAAC;IAED,OAAgBU,gBAA0B;QAAC;KAAmB,CAAA;IAE9D,MAAaC,MAAqB;QAChC,MAAM,EAACN,KAAK,EAAC,GAAG,MAAM,IAAI,CAACO,KAAK,CAACV;QAEjC,IAAIG,MAAME,KAAK,EAAE;YACf,MAAM,IAAI,CAACM,UAAU;YACrB;QACF;QAEA,MAAM,IAAI,CAACC,SAAS;IACtB;IAEA,MAAcC,YAKX;QACD,MAAMC,OAAO1B,QAAQ,CAAC,GAAG2B,KAAK,CAAC;QAE/B,IAAI;YACF,MAAM,EAACZ,KAAK,EAAC,GAAG,MAAM,IAAI,CAACO,KAAK,CAACV;YACjC,MAAMgB,UAAU,MAAM,IAAI,CAACC,cAAc;YACzC,MAAMC,SAAS,MAAM,IAAI,CAACC,YAAY;YAEtC,MAAMC,aAAajB,KAAK,CAAC,cAAc;YACvC,MAAMkB,UAAUL,QAAQM,SAAS;YAEjC,MAAMC,mBAAmBH,cAAc;YACvC,IAAII,kBAAkB;YAEtB,IAAI;gBACF,MAAMC,OAAO,MAAM3C,KAAKyC;gBACxBC,kBAAkBC,KAAKC,MAAM;YAC/B,EAAE,OAAOC,KAAK;gBACZ,IAAIA,eAAeC,SAAS,UAAUD,OAAOA,IAAIE,IAAI,KAAK,YAAYT,YAAY;oBAChFN,KAAKgB,IAAI;oBACT,IAAI,CAACC,KAAK,CAAC,CAAC,+BAA+B,EAAEX,YAAY,EAAE;wBACzDY,MAAM9C,UAAU+C,aAAa;oBAC/B;gBACF;gBAEA,IAAIN,eAAeC,SAAS,UAAUD,OAAOA,IAAIE,IAAI,KAAK,UAAU;oBAClEf,KAAKgB,IAAI;oBACT,IAAI,CAACC,KAAK,CAAC,CAAC,mDAAmD,EAAER,kBAAkB,EAAE;wBACnFS,MAAM9C,UAAU+C,aAAa;oBAC/B;gBACF;YACF;YAEA,IAAIf,QAAQgB,WAAWV,iBAAiB;gBACtCV,KAAKqB,IAAI,CACPpD,UACE,UACA,CAAC;;;IAGT,CAAC;gBAIG,OAAO;oBACLmC,QAAQ7B,iBAAiBqB,KAAK,CAACQ,OAAOgB,OAAO,IAAI,CAAC;oBAClDE,MAAMpB,QAAQoB,IAAI;oBAClBC,MAAM;oBACNhB;gBACF;YACF;YAEA,IAAIG,iBAAiB;gBACnBV,KAAKqB,IAAI,CACPpD,UACE,UACA,CAAC;;iFAEoE,CAAC;gBAG1E,OAAO;oBACLmC,QAAQ,MAAM5B,WAAWiC;oBACzBa,MAAMb;oBACNc,MAAM;oBACNhB;gBACF;YACF;YAEAP,KAAKwB,OAAO,CAAC,CAAC,gCAAgC,CAAC;YAE/C,OAAO;gBACLpB,QAAQ7B,iBAAiBqB,KAAK,CAACQ,OAAOgB,OAAO,IAAI,CAAC;gBAClDE,MAAMpB,QAAQoB,IAAI;gBAClBC,MAAM;gBACNhB;YACF;QACF,EAAE,OAAOM,KAAK;YACZ,wEAAwE;YACxE,sEAAsE;YACtE,6DAA6D;YAC7D,IAAIA,eAAe1C,UAAU,MAAM0C;YACnCb,KAAKgB,IAAI;YACT,IAAI,CAACC,KAAK,CAAC,CAAC,yCAAyC,EAAEJ,KAAK,EAAE;gBAC5DK,MAAM9C,UAAU+C,aAAa;YAC/B;QACF;IACF;IAEA,MAAcrB,YAA2B;QACvC,MAAM2B,QAAQ,IAAI,CAACC,SAAS,CAACD,KAAK,CAAC7C;QACnC,IAAIoB;QAEJ,IAAI;YACF,MAAM,EAACI,QAAQuB,aAAa,EAAEJ,MAAMK,mBAAmB,EAAErB,OAAO,EAAC,GAAG,MAAM,IAAI,CAACR,SAAS;YACxF0B,MAAMxB,KAAK;YAEXD,OAAO1B,QAAQ,CAAC,GAAG2B,KAAK,CAAC;YACzB,MAAM4B,SAAS,MAAMpD,mBAAmB;gBACtC2B,QAAQuB;gBACRG,YAAY/C,8BAA8BiB,MAAM;oBAC9C+B,qBAAqBJ,cAAcI,mBAAmB;oBACtDC,WAAWL,cAAcK,SAAS;oBAClCC,QAAQN,cAAcM,MAAM;gBAC9B;gBACA1B;YACF;YAEA,MAAM2B,aAAarD,KAAKgD,QAAQ,QAAQ;YAExCJ,MAAMU,GAAG,CAAC;gBACRC,cAAcR;gBACdS,6BAA6BV,cAAcW,qBAAqB;gBAChE,GAAGJ,UAAU;YACf;YACAT,MAAMc,QAAQ;QAChB,EAAE,OAAOtB,OAAO;YACd,IAAIjB,MAAMwC,YAAY;gBACpBxC,KAAKgB,IAAI;YACX;YACAS,MAAMR,KAAK,CAACA,iBAAiBH,QAAQG,QAAQ,IAAIH,MAAM2B,OAAOxB;YAC9D,IAAI,CAACA,KAAK,CAAC,GAAGA,iBAAiBH,QAAQG,MAAMyB,OAAO,GAAG,iBAAiB,EAAE;gBACxExB,MAAM9C,UAAU+C,aAAa;YAC/B;QACF;IACF;IAEA,MAActB,aAA4B;QACxC,MAAM4B,QAAQ,IAAI,CAACC,SAAS,CAACD,KAAK,CAAC9C;QACnC,IAAIqB;QAEJ,IAAI;YACF,MAAM,EAACI,QAAQuB,aAAa,EAAEpB,OAAO,EAAC,GAAG,MAAM,IAAI,CAACR,SAAS;YAC7D0B,MAAMxB,KAAK;YAEX,IAAI0C,UAAsB,KAAO;YACjC,MAAMC,UAAU,IAAIC,QAAc,CAACC;gBACjCH,UAAUG;YACZ;YAEA,MAAMC,YAAYzE,QAAQ,CAAC,GAAG2B,KAAK,CAAC;YACpCD,OAAO+C;YACP,MAAMC,kBAAkB;gBACtBjB,qBAAqBJ,cAAcI,mBAAmB;gBACtDC,WAAWL,cAAcK,SAAS;gBAClCC,QAAQN,cAAcM,MAAM;YAC9B;YACA,IAAIgB,iBAAiBlE,8BAA8BgE,WAAWC;YAE9D,MAAME,iBAAiBxE,kBAAkB;gBACvC0B,QAAQuB;gBACRG,YAAY,CAACqB;oBACX,mEAAmE;oBACnE,iEAAiE;oBACjE,IAAIA,MAAM5B,IAAI,KAAK,gBAAgB;wBACjC0B,iBAAiBlE,8BAA8BgE,WAAWC;oBAC5D;oBACAC,eAAeE;gBACjB;gBACA5C;YACF;YAEA,MAAM6C,OAAOtE,KAAK;gBAChBuE,QAAQC,GAAG,CAAC,UAAUF;gBACtBC,QAAQC,GAAG,CAAC,WAAWF;gBAEvB,IAAIL,UAAUP,UAAU,EAAE;oBACxBO,UAAUK,IAAI;gBAChB;gBAEA3B,MAAMU,GAAG,CAAC;oBACRoB,MAAM;oBACN,GAAGL,eAAeM,QAAQ,EAAE;gBAC9B;gBACA/B,MAAMc,QAAQ;gBAEd,IAAI;oBACF,MAAMW,eAAeE,IAAI;gBAC3B,EAAE,OAAM;gBACN,qEAAqE;gBACrE,oDAAoD;gBACtD;gBACAT;YACF;YAEAU,QAAQI,EAAE,CAAC,UAAUL;YACrBC,QAAQI,EAAE,CAAC,WAAWL;YAEtB,MAAMR;QACR,EAAE,OAAO3B,OAAO;YACd,IAAIjB,MAAMwC,YAAY;gBACpBxC,KAAKgB,IAAI;YACX;YACAS,MAAMR,KAAK,CAACA,iBAAiBH,QAAQG,QAAQ,IAAIH,MAAM2B,OAAOxB;YAC9D,IAAI,CAACA,KAAK,CAAC,GAAGA,iBAAiBH,QAAQG,MAAMyB,OAAO,GAAG,iBAAiB,EAAE;gBACxExB,MAAM9C,UAAU+C,aAAa;YAC/B;QACF;IACF;AACF"}
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/typegen/generate.ts"],"sourcesContent":["import {stat} from 'node:fs/promises'\nimport {styleText} from 'node:util'\n\nimport {Flags} from '@oclif/core'\nimport {CLIError} from '@oclif/core/errors'\nimport {exitCodes, SanityCommand} from '@sanity/cli-core'\nimport {spinner, type SpinnerInstance} from '@sanity/cli-core/ux'\nimport {\n readConfig,\n runTypegenGenerate,\n runTypegenWatcher,\n type TypeGenConfig,\n TypegenWatchModeTrace,\n TypesGeneratedTrace,\n} from '@sanity/codegen'\nimport omit from 'lodash-es/omit.js'\nimport once from 'lodash-es/once.js'\n\nimport {parseTypegenConfig} from '../../actions/typegen/parseTypegenConfig.js'\nimport {createTypegenProgressRenderer} from '../../actions/typegen/renderTypegenProgress.js'\n\nconst description = `Sanity TypeGen\n\n${styleText('bold', 'Configuration:')}\nThis command can utilize configuration settings defined in a \\`sanity-typegen.json\\` file. These settings include:\n\n- \"path\": Specifies a glob pattern to locate your TypeScript or JavaScript files.\n Default: \"./src/**/*.{ts,tsx,js,jsx}\"\n\n- \"schema\": Defines the path to your Sanity schema file. This file should be generated using the \\`sanity schema extract\\` command.\n Default: \"schema.json\"\n\n- \"generates\": Indicates the path where the generated TypeScript type definitions will be saved.\n Default: \"./sanity.types.ts\"\n\nThe default configuration values listed above are used if not overridden in your \\`sanity-typegen.json\\` configuration file. To customize the behavior of the type generation, adjust these properties in the configuration file according to your project's needs.\n\n${styleText('bold', 'Note:')}\n- The \\`sanity schema extract\\` command is a prerequisite for extracting your Sanity Studio schema into a \\`schema.json\\` file, which is then used by the \\`sanity typegen generate\\` command to generate type definitions.`.trim()\n\nexport class TypegenGenerateCommand extends SanityCommand<typeof TypegenGenerateCommand> {\n static override description = description\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: `Generate TypeScript type definitions from a Sanity Studio schema extracted using the \\`sanity schema extract\\` command.`,\n },\n ]\n\n static override flags = {\n 'config-path': Flags.string({\n description:\n '[Default: sanity-typegen.json] Specifies the path to the typegen configuration file. This file should be a JSON file that contains settings for the type generation process.',\n }),\n watch: Flags.boolean({\n default: false,\n description: '[Default: false] Run the typegen in watch mode',\n }),\n }\n\n static override hiddenAliases: string[] = ['typegen:generate']\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(TypegenGenerateCommand)\n\n if (flags.watch) {\n await this.runWatcher()\n return\n }\n\n await this.runSingle()\n }\n\n private async getConfig(): Promise<{\n config: TypeGenConfig\n path?: string\n type: 'cli' | 'legacy'\n workDir: string\n }> {\n const spin = spinner({}).start('Loading config…')\n\n try {\n const {flags} = await this.parse(TypegenGenerateCommand)\n const rootDir = await this.getProjectRoot()\n const config = await this.getCliConfig()\n\n const configPath = flags['config-path']\n const workDir = rootDir.directory\n\n const legacyConfigPath = configPath || 'sanity-typegen.json'\n let hasLegacyConfig = false\n\n try {\n const file = await stat(legacyConfigPath)\n hasLegacyConfig = file.isFile()\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ENOENT' && configPath) {\n spin.fail()\n this.error(`Typegen config file not found: ${configPath}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (err instanceof Error && 'code' in err && err.code !== 'ENOENT') {\n spin.fail()\n this.error(`Error when checking if typegen config file exists: ${legacyConfigPath}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n if (config?.typegen && hasLegacyConfig) {\n spin.warn(\n styleText(\n 'yellow',\n `You've specified typegen in your Sanity CLI config, but also have a typegen config.\n\n The config from the Sanity CLI config is used.\n `,\n ),\n )\n\n return {\n config: parseTypegenConfig(config.typegen || {}),\n path: rootDir.path,\n type: 'cli',\n workDir,\n }\n }\n\n if (hasLegacyConfig) {\n spin.warn(\n styleText(\n 'yellow',\n `The separate typegen config has been deprecated. Use \\`typegen\\` in the sanity CLI config instead.\n\n See: https://www.sanity.io/docs/help/configuring-typegen-in-sanity-cli-config`,\n ),\n )\n return {\n config: await readConfig(legacyConfigPath),\n path: legacyConfigPath,\n type: 'legacy',\n workDir,\n }\n }\n\n spin.succeed(`Config loaded from sanity.cli.ts`)\n\n return {\n config: parseTypegenConfig(config.typegen || {}),\n path: rootDir.path,\n type: 'cli',\n workDir,\n }\n } catch (err) {\n // The config-file checks above already reported a user-facing error via\n // `this.error()` (an oclif CLIError). Re-throw those as-is instead of\n // wrapping them a second time and failing the spinner twice.\n if (err instanceof CLIError) throw err\n spin.fail()\n this.error(`An error occurred during config loading: ${err}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async runSingle(): Promise<void> {\n const trace = this.telemetry.trace(TypesGeneratedTrace)\n let spin: SpinnerInstance | undefined\n\n try {\n const {config: typegenConfig, type: typegenConfigMethod, workDir} = await this.getConfig()\n trace.start()\n\n spin = spinner({}).start('Loading schema…')\n const result = await runTypegenGenerate({\n config: typegenConfig,\n onProgress: createTypegenProgressRenderer(spin, {\n formatGeneratedCode: typegenConfig.formatGeneratedCode,\n generates: typegenConfig.generates,\n schema: typegenConfig.schema,\n }),\n workDir,\n })\n\n const traceStats = omit(result, 'code', 'duration')\n\n trace.log({\n configMethod: typegenConfigMethod,\n configOverloadClientMethods: typegenConfig.overloadClientMethods,\n ...traceStats,\n })\n trace.complete()\n } catch (error) {\n if (spin?.isSpinning) {\n spin.fail()\n }\n trace.error(error instanceof Error ? error : new Error(String(error)))\n this.error(`${error instanceof Error ? error.message : 'Unknown error'}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n\n private async runWatcher(): Promise<void> {\n const trace = this.telemetry.trace(TypegenWatchModeTrace)\n let spin: SpinnerInstance | undefined\n\n try {\n const {config: typegenConfig, workDir} = await this.getConfig()\n trace.start()\n\n let resolve: () => void = () => {}\n const promise = new Promise<void>((res) => {\n resolve = res\n })\n\n const watchSpin = spinner({}).start('Loading schema…')\n spin = watchSpin\n const rendererContext = {\n formatGeneratedCode: typegenConfig.formatGeneratedCode,\n generates: typegenConfig.generates,\n schema: typegenConfig.schema,\n }\n let renderProgress = createTypegenProgressRenderer(watchSpin, rendererContext)\n\n const typegenWatcher = runTypegenWatcher({\n config: typegenConfig,\n onProgress: (event) => {\n // 'schemaLoaded' is the first event of every generation cycle; the\n // renderer accumulates per-run state, so start each cycle fresh.\n if (event.type === 'schemaLoaded') {\n renderProgress = createTypegenProgressRenderer(watchSpin, rendererContext)\n }\n renderProgress(event)\n },\n workDir,\n })\n\n const stop = once(async () => {\n process.off('SIGINT', stop)\n process.off('SIGTERM', stop)\n\n if (watchSpin.isSpinning) {\n watchSpin.stop()\n }\n\n trace.log({\n step: 'stopped',\n ...typegenWatcher.getStats(),\n })\n trace.complete()\n\n try {\n await typegenWatcher.stop()\n } catch {\n // We're shutting down; a failure to close the watcher shouldn't hang\n // the process or surface as an unhandled rejection.\n }\n resolve()\n })\n\n process.on('SIGINT', stop)\n process.on('SIGTERM', stop)\n\n await promise\n } catch (error) {\n if (spin?.isSpinning) {\n spin.fail()\n }\n trace.error(error instanceof Error ? error : new Error(String(error)))\n this.error(`${error instanceof Error ? error.message : 'Unknown error'}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n}\n"],"names":["stat","styleText","Flags","CLIError","exitCodes","SanityCommand","spinner","readConfig","runTypegenGenerate","runTypegenWatcher","TypegenWatchModeTrace","TypesGeneratedTrace","omit","once","parseTypegenConfig","createTypegenProgressRenderer","description","trim","TypegenGenerateCommand","examples","command","flags","string","watch","boolean","default","hiddenAliases","run","parse","runWatcher","runSingle","getConfig","spin","start","rootDir","getProjectRoot","config","getCliConfig","configPath","workDir","directory","legacyConfigPath","hasLegacyConfig","file","isFile","err","Error","code","fail","error","exit","RUNTIME_ERROR","typegen","warn","path","type","succeed","trace","telemetry","typegenConfig","typegenConfigMethod","result","onProgress","formatGeneratedCode","generates","schema","traceStats","log","configMethod","configOverloadClientMethods","overloadClientMethods","complete","isSpinning","String","message","resolve","promise","Promise","res","watchSpin","rendererContext","renderProgress","typegenWatcher","event","stop","process","off","step","getStats","on"],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { logSymbols } from '@sanity/cli-core/ux';
|
|
4
|
-
import {
|
|
4
|
+
import { runTypegenGenerate, TypegenWatchModeTrace, TypesGeneratedTrace } from '@sanity/codegen';
|
|
5
5
|
import debounce from 'lodash-es/debounce.js';
|
|
6
6
|
import mean from 'lodash-es/mean.js';
|
|
7
7
|
import once from 'lodash-es/once.js';
|
|
8
8
|
import picomatch from 'picomatch';
|
|
9
|
+
import { parseTypegenConfig } from '../../actions/typegen/parseTypegenConfig.js';
|
|
9
10
|
import { toForwardSlashes } from '../../util/toForwardSlashes.js';
|
|
10
11
|
/** Default debounce delay in milliseconds */ const DEFAULT_DEBOUNCE_MS = 1000;
|
|
11
12
|
/**
|
|
@@ -34,7 +35,7 @@ import { toForwardSlashes } from '../../util/toForwardSlashes.js';
|
|
|
34
35
|
const { config: inputConfig, output = console, telemetryLogger, workDir } = options;
|
|
35
36
|
// Apply defaults through the same schema as `sanity typegen generate`,
|
|
36
37
|
// so watch mode and manual generation produce identical output
|
|
37
|
-
const config =
|
|
38
|
+
const config = parseTypegenConfig(inputConfig);
|
|
38
39
|
// Build query patterns from config
|
|
39
40
|
const queryPatterns = Array.isArray(config.path) ? config.path : [
|
|
40
41
|
config.path
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/vite/plugin-typegen.ts"],"sourcesContent":["import {existsSync} from 'node:fs'\nimport path from 'node:path'\n\nimport {CLITelemetryStore} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\nimport {\n configDefinition,\n type GenerationResult,\n runTypegenGenerate,\n type TypeGenConfig,\n TypegenWatchModeTrace,\n TypesGeneratedTrace,\n} from '@sanity/codegen'\nimport debounce from 'lodash-es/debounce.js'\nimport mean from 'lodash-es/mean.js'\nimport once from 'lodash-es/once.js'\nimport picomatch from 'picomatch'\nimport {type Plugin} from 'vite'\n\nimport {toForwardSlashes} from '../../util/toForwardSlashes.js'\n\n/** Default debounce delay in milliseconds */\nconst DEFAULT_DEBOUNCE_MS = 1000\n\n/**\n * Delay before initial generation to allow Vite to finish startup\n * and avoid race conditions with module resolution.\n */\nconst INITIAL_GENERATION_DELAY_MS = 1000\n\n/**\n * Options for the Sanity typegen Vite plugin.\n *\n * @internal\n */\ninterface TypegenPluginOptions {\n /**\n * Typegen configuration from sanity.cli.ts.\n * All fields are optional and will use sensible defaults.\n */\n config: Partial<TypeGenConfig>\n\n /**\n * Working directory containing the Sanity configuration.\n * This should be the root of your Sanity Studio project.\n */\n workDir: string\n\n /**\n * Logger for output messages. Must implement `log`, `info`, and `error` methods.\n * @defaultValue `console`\n */\n output?: Pick<Console, 'error' | 'info' | 'log'>\n\n /**\n * Telemetry logger for the Sanity CLI tooling.\n */\n telemetryLogger?: CLITelemetryStore\n}\n\n/**\n * Creates a Vite plugin that automatically generates TypeScript types during development and build.\n *\n * **During development:**\n * The plugin performs an initial generation when the dev server starts, then watches\n * for file changes and re-generates types when relevant files are modified.\n *\n * **During build:**\n * The plugin generates types once at the end of the build process.\n *\n * **Prerequisites:**\n * The schema.json file must exist before typegen can run. Run `sanity schema extract`\n * first to generate the schema file.\n *\n * @param options - Configuration options for the plugin\n * @returns A Vite plugin configured for typegen\n *\n * @internal\n */\nexport function sanityTypegenPlugin(options: TypegenPluginOptions): Plugin {\n const {config: inputConfig, output = console, telemetryLogger, workDir} = options\n\n // Apply defaults through the same schema as `sanity typegen generate`,\n // so watch mode and manual generation produce identical output\n const config: TypeGenConfig = configDefinition.parse(inputConfig)\n\n // Build query patterns from config\n const queryPatterns = Array.isArray(config.path) ? config.path : [config.path]\n\n // Resolved after Vite config is available\n let resolvedSchemaPath: string\n\n // State for concurrency control\n let isGenerating = false\n let pendingGeneration = false\n\n // Stats for telemetry\n const startTime = Date.now()\n const stats: {failedCount: number; successfulDurations: number[]} = {\n failedCount: 0,\n successfulDurations: [],\n }\n\n /**\n * Runs type generation with concurrency control.\n * If generation is already running, queues one more generation to run after completion.\n * Returns the generation result, or null if generation was skipped or failed.\n */\n async function runGeneration(isBuilding = false): Promise<GenerationResult | null> {\n if (isGenerating) {\n pendingGeneration = true\n return null\n }\n\n isGenerating = true\n pendingGeneration = false\n\n const generationStartTime = Date.now()\n\n try {\n // Validate schema.json exists\n if (!existsSync(resolvedSchemaPath)) {\n output.error(\n `${logSymbols.error} Schema file not found: ${config.schema}\\n` +\n `Run \"sanity schema extract\" first to generate the schema file.`,\n )\n return null\n }\n\n const result = await runTypegenGenerate({\n config,\n workDir,\n })\n\n if (isBuilding) {\n // Add newline for better formatting in build output\n output.log('')\n }\n\n if (result.filesWithErrors > 0) {\n output.log(\n logSymbols.warning,\n `Generated types to ${config.generates} (with errors in ${result.filesWithErrors} file${result.filesWithErrors === 1 ? '' : 's'})`,\n )\n } else {\n output.log(logSymbols.success, `Generated types to ${config.generates}`)\n }\n\n // Track stats for telemetry (all completed generations count as successful)\n stats.successfulDurations.push(Date.now() - generationStartTime)\n\n return result\n } catch (err) {\n output.error(\n `${logSymbols.error} Generation failed: ${err instanceof Error ? err.message : String(err)}`,\n )\n stats.failedCount++\n return null\n } finally {\n isGenerating = false\n\n // If a change came in during generation, run again\n if (pendingGeneration) {\n pendingGeneration = false\n void runGeneration()\n }\n }\n }\n\n const debouncedGenerate = debounce(() => {\n void runGeneration()\n }, DEFAULT_DEBOUNCE_MS)\n\n // Create a matcher function from query patterns\n const isQueryMatch = picomatch(queryPatterns)\n\n return {\n name: 'sanity/typegen',\n\n configResolved() {\n const rootDir = workDir\n\n resolvedSchemaPath = path.isAbsolute(config.schema)\n ? config.schema\n : path.join(rootDir, config.schema)\n },\n\n configureServer(server) {\n const trace = telemetryLogger?.trace(TypegenWatchModeTrace)\n trace?.start()\n trace?.log({step: 'started'})\n\n // Build absolute patterns for query files\n const absoluteQueryPatterns = queryPatterns.map((pattern) =>\n path.isAbsolute(pattern) ? pattern : path.join(workDir, pattern),\n )\n\n // Add query patterns AND schema.json to Vite's watcher\n server.watcher.add([...absoluteQueryPatterns, resolvedSchemaPath])\n\n // Listen for file changes\n const handleChange = (filePath: string) => {\n const relativePath = path.isAbsolute(filePath) ? path.relative(workDir, filePath) : filePath\n // Normalize to forward slashes for cross-platform picomatch compatibility\n const normalizedPath = toForwardSlashes(relativePath)\n\n // Trigger on schema.json change OR matching query file\n if (filePath === resolvedSchemaPath || isQueryMatch(normalizedPath)) {\n debouncedGenerate()\n }\n }\n\n // Prepare function to log \"stopped\" event to trace and complete the trace\n const onClose = once(() => {\n // Cancel any pending debounced extractions\n debouncedGenerate.cancel()\n\n if (trace) {\n trace.log({\n averageGenerationDuration: mean(stats.successfulDurations) || 0,\n generationFailedCount: stats.failedCount,\n generationSuccessfulCount: stats.successfulDurations.length,\n step: 'stopped',\n watcherDuration: Date.now() - startTime,\n })\n trace.complete()\n }\n\n // Clean up process listeners (must always run, not just when trace exists)\n process.off('SIGTERM', onClose)\n process.off('SIGINT', onClose)\n })\n\n server.watcher.on('change', handleChange)\n server.watcher.on('add', handleChange)\n server.watcher.on('unlink', handleChange)\n\n // Call the onClose method when watcher is closed or when process is stopped/killed\n server.watcher.on('close', onClose)\n process.on('SIGTERM', onClose)\n process.on('SIGINT', onClose)\n\n // Run initial generation after server is ready\n const startGeneration = () => {\n setTimeout(() => {\n // Notify about typegen enabled\n output.info(logSymbols.info, 'Typegen enabled. Watching:')\n for (const pattern of queryPatterns) {\n output.info(` - ${pattern}`)\n }\n output.info(` - ${config.schema} (schema)`)\n\n // Perform first generation\n void runGeneration()\n }, INITIAL_GENERATION_DELAY_MS)\n }\n\n if (server.httpServer) {\n server.httpServer.once('listening', startGeneration)\n } else {\n // Middleware mode - no HTTP server, run generation immediately\n startGeneration()\n }\n },\n\n async buildEnd() {\n // Build mode: One-time generation with telemetry tracking\n const result = await runGeneration(true)\n\n // Only log telemetry if generation completed successfully\n if (result && telemetryLogger) {\n const trace = telemetryLogger.trace(TypesGeneratedTrace)\n trace.start()\n trace.log({\n configMethod: 'cli',\n configOverloadClientMethods: config.overloadClientMethods ?? false,\n emptyUnionTypeNodesGenerated: result.emptyUnionTypeNodesGenerated,\n filesWithErrors: result.filesWithErrors,\n outputSize: result.code.length,\n queriesCount: result.queriesCount,\n queryFilesCount: result.queryFilesCount,\n schemaTypesCount: result.schemaTypesCount,\n typeNodesGenerated: result.typeNodesGenerated,\n unknownTypeNodesGenerated: result.unknownTypeNodesGenerated,\n unknownTypeNodesRatio:\n result.typeNodesGenerated > 0\n ? result.unknownTypeNodesGenerated / result.typeNodesGenerated\n : 0,\n })\n trace.complete()\n }\n },\n } satisfies Plugin\n}\n"],"names":["existsSync","path","logSymbols","configDefinition","runTypegenGenerate","TypegenWatchModeTrace","TypesGeneratedTrace","debounce","mean","once","picomatch","toForwardSlashes","DEFAULT_DEBOUNCE_MS","INITIAL_GENERATION_DELAY_MS","sanityTypegenPlugin","options","config","inputConfig","output","console","telemetryLogger","workDir","parse","queryPatterns","Array","isArray","resolvedSchemaPath","isGenerating","pendingGeneration","startTime","Date","now","stats","failedCount","successfulDurations","runGeneration","isBuilding","generationStartTime","error","schema","result","log","filesWithErrors","warning","generates","success","push","err","Error","message","String","debouncedGenerate","isQueryMatch","name","configResolved","rootDir","isAbsolute","join","configureServer","server","trace","start","step","absoluteQueryPatterns","map","pattern","watcher","add","handleChange","filePath","relativePath","relative","normalizedPath","onClose","cancel","averageGenerationDuration","generationFailedCount","generationSuccessfulCount","length","watcherDuration","complete","process","off","on","startGeneration","setTimeout","info","httpServer","buildEnd","configMethod","configOverloadClientMethods","overloadClientMethods","emptyUnionTypeNodesGenerated","outputSize","code","queriesCount","queryFilesCount","schemaTypesCount","typeNodesGenerated","unknownTypeNodesGenerated","unknownTypeNodesRatio"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/server/vite/plugin-typegen.ts"],"sourcesContent":["import {existsSync} from 'node:fs'\nimport path from 'node:path'\n\nimport {CLITelemetryStore} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\nimport {\n type GenerationResult,\n runTypegenGenerate,\n type TypeGenConfig,\n TypegenWatchModeTrace,\n TypesGeneratedTrace,\n} from '@sanity/codegen'\nimport debounce from 'lodash-es/debounce.js'\nimport mean from 'lodash-es/mean.js'\nimport once from 'lodash-es/once.js'\nimport picomatch from 'picomatch'\nimport {type Plugin} from 'vite'\n\nimport {parseTypegenConfig} from '../../actions/typegen/parseTypegenConfig.js'\nimport {toForwardSlashes} from '../../util/toForwardSlashes.js'\n\n/** Default debounce delay in milliseconds */\nconst DEFAULT_DEBOUNCE_MS = 1000\n\n/**\n * Delay before initial generation to allow Vite to finish startup\n * and avoid race conditions with module resolution.\n */\nconst INITIAL_GENERATION_DELAY_MS = 1000\n\n/**\n * Options for the Sanity typegen Vite plugin.\n *\n * @internal\n */\ninterface TypegenPluginOptions {\n /**\n * Typegen configuration from sanity.cli.ts.\n * All fields are optional and will use sensible defaults.\n */\n config: Partial<TypeGenConfig>\n\n /**\n * Working directory containing the Sanity configuration.\n * This should be the root of your Sanity Studio project.\n */\n workDir: string\n\n /**\n * Logger for output messages. Must implement `log`, `info`, and `error` methods.\n * @defaultValue `console`\n */\n output?: Pick<Console, 'error' | 'info' | 'log'>\n\n /**\n * Telemetry logger for the Sanity CLI tooling.\n */\n telemetryLogger?: CLITelemetryStore\n}\n\n/**\n * Creates a Vite plugin that automatically generates TypeScript types during development and build.\n *\n * **During development:**\n * The plugin performs an initial generation when the dev server starts, then watches\n * for file changes and re-generates types when relevant files are modified.\n *\n * **During build:**\n * The plugin generates types once at the end of the build process.\n *\n * **Prerequisites:**\n * The schema.json file must exist before typegen can run. Run `sanity schema extract`\n * first to generate the schema file.\n *\n * @param options - Configuration options for the plugin\n * @returns A Vite plugin configured for typegen\n *\n * @internal\n */\nexport function sanityTypegenPlugin(options: TypegenPluginOptions): Plugin {\n const {config: inputConfig, output = console, telemetryLogger, workDir} = options\n\n // Apply defaults through the same schema as `sanity typegen generate`,\n // so watch mode and manual generation produce identical output\n const config: TypeGenConfig = parseTypegenConfig(inputConfig)\n\n // Build query patterns from config\n const queryPatterns = Array.isArray(config.path) ? config.path : [config.path]\n\n // Resolved after Vite config is available\n let resolvedSchemaPath: string\n\n // State for concurrency control\n let isGenerating = false\n let pendingGeneration = false\n\n // Stats for telemetry\n const startTime = Date.now()\n const stats: {failedCount: number; successfulDurations: number[]} = {\n failedCount: 0,\n successfulDurations: [],\n }\n\n /**\n * Runs type generation with concurrency control.\n * If generation is already running, queues one more generation to run after completion.\n * Returns the generation result, or null if generation was skipped or failed.\n */\n async function runGeneration(isBuilding = false): Promise<GenerationResult | null> {\n if (isGenerating) {\n pendingGeneration = true\n return null\n }\n\n isGenerating = true\n pendingGeneration = false\n\n const generationStartTime = Date.now()\n\n try {\n // Validate schema.json exists\n if (!existsSync(resolvedSchemaPath)) {\n output.error(\n `${logSymbols.error} Schema file not found: ${config.schema}\\n` +\n `Run \"sanity schema extract\" first to generate the schema file.`,\n )\n return null\n }\n\n const result = await runTypegenGenerate({\n config,\n workDir,\n })\n\n if (isBuilding) {\n // Add newline for better formatting in build output\n output.log('')\n }\n\n if (result.filesWithErrors > 0) {\n output.log(\n logSymbols.warning,\n `Generated types to ${config.generates} (with errors in ${result.filesWithErrors} file${result.filesWithErrors === 1 ? '' : 's'})`,\n )\n } else {\n output.log(logSymbols.success, `Generated types to ${config.generates}`)\n }\n\n // Track stats for telemetry (all completed generations count as successful)\n stats.successfulDurations.push(Date.now() - generationStartTime)\n\n return result\n } catch (err) {\n output.error(\n `${logSymbols.error} Generation failed: ${err instanceof Error ? err.message : String(err)}`,\n )\n stats.failedCount++\n return null\n } finally {\n isGenerating = false\n\n // If a change came in during generation, run again\n if (pendingGeneration) {\n pendingGeneration = false\n void runGeneration()\n }\n }\n }\n\n const debouncedGenerate = debounce(() => {\n void runGeneration()\n }, DEFAULT_DEBOUNCE_MS)\n\n // Create a matcher function from query patterns\n const isQueryMatch = picomatch(queryPatterns)\n\n return {\n name: 'sanity/typegen',\n\n configResolved() {\n const rootDir = workDir\n\n resolvedSchemaPath = path.isAbsolute(config.schema)\n ? config.schema\n : path.join(rootDir, config.schema)\n },\n\n configureServer(server) {\n const trace = telemetryLogger?.trace(TypegenWatchModeTrace)\n trace?.start()\n trace?.log({step: 'started'})\n\n // Build absolute patterns for query files\n const absoluteQueryPatterns = queryPatterns.map((pattern) =>\n path.isAbsolute(pattern) ? pattern : path.join(workDir, pattern),\n )\n\n // Add query patterns AND schema.json to Vite's watcher\n server.watcher.add([...absoluteQueryPatterns, resolvedSchemaPath])\n\n // Listen for file changes\n const handleChange = (filePath: string) => {\n const relativePath = path.isAbsolute(filePath) ? path.relative(workDir, filePath) : filePath\n // Normalize to forward slashes for cross-platform picomatch compatibility\n const normalizedPath = toForwardSlashes(relativePath)\n\n // Trigger on schema.json change OR matching query file\n if (filePath === resolvedSchemaPath || isQueryMatch(normalizedPath)) {\n debouncedGenerate()\n }\n }\n\n // Prepare function to log \"stopped\" event to trace and complete the trace\n const onClose = once(() => {\n // Cancel any pending debounced extractions\n debouncedGenerate.cancel()\n\n if (trace) {\n trace.log({\n averageGenerationDuration: mean(stats.successfulDurations) || 0,\n generationFailedCount: stats.failedCount,\n generationSuccessfulCount: stats.successfulDurations.length,\n step: 'stopped',\n watcherDuration: Date.now() - startTime,\n })\n trace.complete()\n }\n\n // Clean up process listeners (must always run, not just when trace exists)\n process.off('SIGTERM', onClose)\n process.off('SIGINT', onClose)\n })\n\n server.watcher.on('change', handleChange)\n server.watcher.on('add', handleChange)\n server.watcher.on('unlink', handleChange)\n\n // Call the onClose method when watcher is closed or when process is stopped/killed\n server.watcher.on('close', onClose)\n process.on('SIGTERM', onClose)\n process.on('SIGINT', onClose)\n\n // Run initial generation after server is ready\n const startGeneration = () => {\n setTimeout(() => {\n // Notify about typegen enabled\n output.info(logSymbols.info, 'Typegen enabled. Watching:')\n for (const pattern of queryPatterns) {\n output.info(` - ${pattern}`)\n }\n output.info(` - ${config.schema} (schema)`)\n\n // Perform first generation\n void runGeneration()\n }, INITIAL_GENERATION_DELAY_MS)\n }\n\n if (server.httpServer) {\n server.httpServer.once('listening', startGeneration)\n } else {\n // Middleware mode - no HTTP server, run generation immediately\n startGeneration()\n }\n },\n\n async buildEnd() {\n // Build mode: One-time generation with telemetry tracking\n const result = await runGeneration(true)\n\n // Only log telemetry if generation completed successfully\n if (result && telemetryLogger) {\n const trace = telemetryLogger.trace(TypesGeneratedTrace)\n trace.start()\n trace.log({\n configMethod: 'cli',\n configOverloadClientMethods: config.overloadClientMethods ?? false,\n emptyUnionTypeNodesGenerated: result.emptyUnionTypeNodesGenerated,\n filesWithErrors: result.filesWithErrors,\n outputSize: result.code.length,\n queriesCount: result.queriesCount,\n queryFilesCount: result.queryFilesCount,\n schemaTypesCount: result.schemaTypesCount,\n typeNodesGenerated: result.typeNodesGenerated,\n unknownTypeNodesGenerated: result.unknownTypeNodesGenerated,\n unknownTypeNodesRatio:\n result.typeNodesGenerated > 0\n ? result.unknownTypeNodesGenerated / result.typeNodesGenerated\n : 0,\n })\n trace.complete()\n }\n },\n } satisfies Plugin\n}\n"],"names":["existsSync","path","logSymbols","runTypegenGenerate","TypegenWatchModeTrace","TypesGeneratedTrace","debounce","mean","once","picomatch","parseTypegenConfig","toForwardSlashes","DEFAULT_DEBOUNCE_MS","INITIAL_GENERATION_DELAY_MS","sanityTypegenPlugin","options","config","inputConfig","output","console","telemetryLogger","workDir","queryPatterns","Array","isArray","resolvedSchemaPath","isGenerating","pendingGeneration","startTime","Date","now","stats","failedCount","successfulDurations","runGeneration","isBuilding","generationStartTime","error","schema","result","log","filesWithErrors","warning","generates","success","push","err","Error","message","String","debouncedGenerate","isQueryMatch","name","configResolved","rootDir","isAbsolute","join","configureServer","server","trace","start","step","absoluteQueryPatterns","map","pattern","watcher","add","handleChange","filePath","relativePath","relative","normalizedPath","onClose","cancel","averageGenerationDuration","generationFailedCount","generationSuccessfulCount","length","watcherDuration","complete","process","off","on","startGeneration","setTimeout","info","httpServer","buildEnd","configMethod","configOverloadClientMethods","overloadClientMethods","emptyUnionTypeNodesGenerated","outputSize","code","queriesCount","queryFilesCount","schemaTypesCount","typeNodesGenerated","unknownTypeNodesGenerated","unknownTypeNodesRatio"],"mappings":"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"}
|