@sanity/cli 7.12.1 → 7.13.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/api/resolveEndpoint.ts"],"sourcesContent":["import {parse} from 'node:querystring'\n\nimport {API_DEFAULT_VERSION, API_VERSION_SEGMENT_RE} from './constants.js'\nimport {ApiUsageError, ProjectIdRequiredError} from './errors.js'\nimport {type ApiHost, type ApiRouteEntry} from './types.js'\n\n/**\n * Options for {@link resolveEndpoint}.\n */\nexport interface ResolveEndpointOptions {\n /** The endpoint argument: a path, optionally with placeholders, or a full URL. */\n endpoint: string\n\n /** The generated routing manifest. */\n routes: ApiRouteEntry[]\n\n /** Explicit API version (`--api-version`), wins over everything else. */\n apiVersion?: string\n\n /** Dataset used to fill `{dataset}` / `{datasetName}` placeholders. */\n dataset?: string\n\n /** Force a host family (`--global` / `--project-hosted`), restricting route matching to it. */\n forceHost?: ApiHost\n\n /** Project ID used to fill `{projectId}` placeholders and project-hosted requests. */\n projectId?: string\n}\n\n/**\n * A fully resolved request target.\n */\nexport type ResolvedEndpoint =\n | {\n /** API version path segment, eg `v2021-06-07`. */\n apiVersion: string\n host: ApiHost\n kind: 'path'\n /** Slug of the OpenAPI spec whose paths matched, if any. */\n matchedSlug?: string\n /** Version-less path, without leading slash. */\n path: string\n /** Project ID; always set when `host` is `project`. */\n projectId?: string\n /** Query parameters parsed from the endpoint argument. */\n query: Record<string, string | string[]>\n }\n | {\n kind: 'url'\n query: Record<string, string | string[]>\n /** Absolute URL, used verbatim (query string stripped into `query`). */\n url: string\n }\n\nconst PLACEHOLDER_RE = /^\\{([^{}]+)\\}$/\n\nconst ALLOWED_URL_HOST_RE = /(?:^|\\.)api\\.sanity\\.(?:io|work)$/\n\n/**\n * Resolve the endpoint argument of `sanity api` into a concrete request\n * target: substitute placeholders, split off the query string, determine the\n * host family (via the generated OpenAPI routing manifest) and the API\n * version.\n *\n * Throws {@link ProjectIdRequiredError} when the request needs a project ID\n * that hasn't been provided - the command catches this to resolve one (flags,\n * CLI config or interactive prompt) and retries.\n */\nexport function resolveEndpoint(options: ResolveEndpointOptions): ResolvedEndpoint {\n const {apiVersion, dataset, endpoint, forceHost, projectId, routes} = options\n\n if (/^https?:\\/\\//.test(endpoint)) {\n return resolveUrlEndpoint(endpoint)\n }\n\n const [pathPart = '', ...queryParts] = endpoint.split('?')\n const query = parseQueryString(queryParts.join('?'))\n\n const segments = pathPart.split('/').filter((segment) => segment !== '')\n\n // An API version embedded in the path (eg `v2021-06-07/projects`) is peeled\n // off and re-applied as the version segment of the final URL.\n let embeddedVersion: string | undefined\n if (segments[0] === '{apiVersion}') {\n segments.shift()\n } else if (segments.length > 0 && API_VERSION_SEGMENT_RE.test(segments[0])) {\n embeddedVersion = segments.shift()\n }\n\n // Checked after version peeling so a bare version (eg `v2025-02-19`) is\n // also rejected as an empty path.\n if (segments.length === 0) {\n throw new ApiUsageError('Endpoint path is empty')\n }\n\n const unresolved: string[] = []\n const substituted = segments.map((segment, index) => {\n const placeholder = PLACEHOLDER_RE.exec(segment)?.[1]\n if (!placeholder) return segment\n if (placeholder === 'projectId') {\n if (!projectId) throw new ProjectIdRequiredError()\n return projectId\n }\n // The projects spec names the dataset placeholder `{name}` (eg\n // `projects/{projectId}/datasets/{name}`) - only that context is a\n // dataset; `{name}` elsewhere (eg video renditions) stays unresolved.\n const isDatasetName = placeholder === 'name' && segments[index - 1] === 'datasets'\n if (placeholder === 'dataset' || placeholder === 'datasetName' || isDatasetName) {\n if (!dataset) {\n throw new ApiUsageError(\n `Unable to resolve {${placeholder}} - provide a dataset with --dataset or configure one in sanity.cli.ts`,\n )\n }\n return dataset\n }\n unresolved.push(segment)\n return segment\n })\n\n if (unresolved.length > 0) {\n throw new ApiUsageError(\n `Unable to resolve placeholder(s) ${unresolved.join(', ')} - replace them with actual values`,\n )\n }\n\n // Forcing a host restricts matching to specs served on that host, so the\n // matched spec's default API version still applies when one exists there.\n const candidates = forceHost ? routes.filter((entry) => entry.host === forceHost) : routes\n const match = matchRoutes(substituted, candidates)\n const host = forceHost ?? match?.host ?? 'global'\n\n if (host === 'project' && !projectId) {\n throw new ProjectIdRequiredError()\n }\n\n return {\n apiVersion: apiVersion ?? embeddedVersion ?? match?.defaultApiVersion ?? API_DEFAULT_VERSION,\n host,\n kind: 'path',\n matchedSlug: match?.slug,\n path: substituted.join('/'),\n ...(host === 'project' ? {projectId} : {}),\n query,\n }\n}\n\nfunction resolveUrlEndpoint(endpoint: string): ResolvedEndpoint {\n let url: URL\n try {\n url = new URL(endpoint)\n } catch {\n throw new ApiUsageError(`Invalid URL \"${endpoint}\"`)\n }\n\n // Never put the token on the wire unencrypted\n if (url.protocol !== 'https:') {\n throw new ApiUsageError(\n `Refusing to send requests over \"${url.protocol}//\" - only https:// URLs are supported`,\n )\n }\n\n if (!ALLOWED_URL_HOST_RE.test(url.hostname)) {\n throw new ApiUsageError(\n `Refusing to send authenticated requests to \"${url.hostname}\" - only *.api.sanity.io hosts are supported`,\n )\n }\n\n const query = parseQueryString(url.search.replace(/^\\?/, ''))\n url.search = ''\n\n return {kind: 'url', query, url: url.toString()}\n}\n\ninterface RouteMatch {\n host: ApiHost\n score: number\n slug: string\n\n defaultApiVersion?: string\n}\n\n/**\n * Find the route entry whose path pattern best matches the request segments.\n *\n * A pattern only matches when the request path consumes it completely, and\n * segments are compared pairwise: literal matches score higher than\n * placeholder matches, and a literal mismatch disqualifies the pattern. On\n * equal scores across hosts the global host wins (APIs served on both hosts\n * don't need a project ID there); on equal scores within the same host the\n * first entry wins, keeping the result independent of later entries.\n */\nfunction matchRoutes(segments: string[], routes: ApiRouteEntry[]): RouteMatch | undefined {\n let best: RouteMatch | undefined\n\n for (const entry of routes) {\n for (const pattern of entry.pathPatterns) {\n const score = scorePattern(segments, pattern.split('/'))\n if (score === 0) continue\n const isBetter =\n !best ||\n score > best.score ||\n (score === best.score && best.host === 'project' && entry.host === 'global')\n if (isBetter) {\n best = {\n defaultApiVersion: entry.defaultApiVersion,\n host: entry.host,\n score,\n slug: entry.slug,\n }\n }\n }\n }\n\n return best\n}\n\nfunction scorePattern(segments: string[], patternSegments: string[]): number {\n // A pattern only matches when the request path consumes it completely - a\n // request that is a mere prefix of a longer pattern (eg `data` vs\n // `data/query/{dataset}`) must not inherit that route's host or version.\n if (patternSegments.length > segments.length) return 0\n\n let score = 0\n let literalMatches = 0\n\n for (const [index, patternSegment] of patternSegments.entries()) {\n if (PLACEHOLDER_RE.test(patternSegment)) {\n score += 1\n } else if (patternSegment === segments[index]) {\n score += 2\n literalMatches += 1\n } else {\n return 0\n }\n }\n\n // Require at least one literal segment match so a placeholder-only pattern\n // like `{resourceType}/{resourceId}` can't capture arbitrary paths.\n return literalMatches === 0 ? 0 : score\n}\n\nfunction parseQueryString(queryString: string): Record<string, string | string[]> {\n // node:querystring collects repeated keys into arrays and returns a\n // null-prototype object, so user-supplied keys like `__proto__` stay\n // ordinary own properties. Parsed values are never `undefined`, hence the\n // narrowing cast.\n return parse(queryString) as Record<string, string | string[]>\n}\n"],"names":["parse","API_DEFAULT_VERSION","API_VERSION_SEGMENT_RE","ApiUsageError","ProjectIdRequiredError","PLACEHOLDER_RE","ALLOWED_URL_HOST_RE","resolveEndpoint","options","apiVersion","dataset","endpoint","forceHost","projectId","routes","test","resolveUrlEndpoint","pathPart","queryParts","split","query","parseQueryString","join","segments","filter","segment","embeddedVersion","shift","length","unresolved","substituted","map","index","placeholder","exec","isDatasetName","push","candidates","entry","host","match","matchRoutes","defaultApiVersion","kind","matchedSlug","slug","path","url","URL","protocol","hostname","search","replace","toString","best","pattern","pathPatterns","score","scorePattern","isBetter","patternSegments","literalMatches","patternSegment","entries","queryString"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Which Sanity API host family a request targets.
3
+ *
4
+ * - `global` - `https://api.sanity.io` (projects, organizations, jobs, ...)
5
+ * - `project` - `https://<projectId>.api.sanity.io` (data, agent actions, assets, ...)
6
+ */ /**
7
+ * Minimal shape of an OpenAPI document needed to distill routing information.
8
+ */ export { };
9
+
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/api/types.ts"],"sourcesContent":["/**\n * Which Sanity API host family a request targets.\n *\n * - `global` - `https://api.sanity.io` (projects, organizations, jobs, ...)\n * - `project` - `https://<projectId>.api.sanity.io` (data, agent actions, assets, ...)\n */\nexport type ApiHost = 'global' | 'project'\n\n/**\n * A single API family entry in the generated routing manifest, distilled from\n * a published OpenAPI specification.\n */\nexport interface ApiRouteEntry {\n /** Which host family serves these paths. */\n host: ApiHost\n\n /**\n * Normalized path patterns for the endpoints in this spec: no leading slash and\n * no API version segment. Placeholders (eg `{dataset}`) match any path segment.\n */\n pathPatterns: string[]\n\n /** Spec slug, as used by `sanity openapi get <slug>`. */\n slug: string\n\n /** Human-readable spec title. */\n title: string\n\n /**\n * Default API version declared by the spec's server template (eg `v2021-06-07`),\n * if any.\n */\n defaultApiVersion?: string\n}\n\n/**\n * Minimal shape of an OpenAPI document needed to distill routing information.\n */\nexport interface OpenApiDocument {\n info?: {title?: string}\n paths?: Record<string, unknown>\n servers?: OpenApiServer[]\n}\n\n/**\n * An OpenAPI server entry (subset).\n */\ninterface OpenApiServer {\n url: string\n\n variables?: Record<string, {default?: string}>\n}\n"],"names":[],"mappings":"AAAA;;;;;CAKC,GA8BD;;CAEC,GACD,WAIC"}
@@ -3,6 +3,7 @@ import { buildAppId, resolveWorkbenchApp } from '@sanity/workbench-cli/build';
3
3
  import { getAppId } from '../../util/appId.js';
4
4
  import { warnAboutMissingAppId } from '../../util/warnAboutMissingAppId.js';
5
5
  import { determineBasePath } from './determineBasePath.js';
6
+ import { preReleaseEventListenerFactory } from './eventListenerFactory.js';
6
7
  /**
7
8
  * Build the Sanity app.
8
9
  *
@@ -53,7 +54,8 @@ import { determineBasePath } from './determineBasePath.js';
53
54
  // Shared with deploy: it passes the resolved application id (minted by the
54
55
  // API on a first deploy) to inline; a plain build has none, so it hashes the shape.
55
56
  workbenchAppId: workbench ? options.applicationId ?? await buildAppId(workbench) : undefined,
56
- workDir
57
+ workDir,
58
+ eventListener: preReleaseEventListenerFactory(output)
57
59
  });
58
60
  }
59
61
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/build/buildApp.ts"],"sourcesContent":["import {\n compareDependencyVersions,\n buildApp as internalBuildApp,\n} from '@sanity/cli-build/_internal/build'\nimport {buildAppId, resolveWorkbenchApp} from '@sanity/workbench-cli/build'\n\nimport {getAppId} from '../../util/appId.js'\nimport {warnAboutMissingAppId} from '../../util/warnAboutMissingAppId.js'\nimport {determineBasePath} from './determineBasePath.js'\nimport {type BuildOptions} from './types.js'\n\n/**\n * Build the Sanity app.\n *\n * @internal\n */\nexport async function buildApp(options: BuildOptions): Promise<void> {\n const {cliConfig, flags, outDir, output, workDir} = options\n\n const app = cliConfig && 'app' in cliConfig ? cliConfig.app : undefined\n // `views`/`services` live on the branded `unstable_defineApp` result, not the\n // legacy `app` config object — resolve the workbench capability to read them.\n const workbench = resolveWorkbenchApp(cliConfig)\n const exposes = workbench\n ? {config: workbench.config, services: workbench.services, views: workbench.views}\n : undefined\n\n const appId = getAppId(cliConfig)\n\n await internalBuildApp({\n appId,\n appTitle: app?.title,\n autoUpdatesEnabled: options.autoUpdatesEnabled,\n checkAppId: () => {\n // Warn if auto updates enabled but no appId configured.\n // Skip when called from deploy, since deploy handles appId itself\n // (prompts the user and tells them to add it to config).\n if (!appId && !options.calledFromDeploy) {\n warnAboutMissingAppId({appType: 'app', output})\n }\n },\n compareDependencyVersions: (packages) => compareDependencyVersions(packages, workDir, {appId}),\n determineBasePath: () => determineBasePath(cliConfig, 'app', output),\n entry: app?.entry,\n exposes,\n isWorkbenchApp: !!workbench,\n minify: flags.minify,\n outDir,\n output,\n reactCompiler: cliConfig && 'reactCompiler' in cliConfig ? cliConfig.reactCompiler : undefined,\n schemaExtraction: cliConfig?.schemaExtraction,\n sourceMap: Boolean(flags['source-maps']),\n stats: flags.stats,\n unattendedMode: flags.yes,\n vite: cliConfig.vite,\n // Shared with deploy: it passes the resolved application id (minted by the\n // API on a first deploy) to inline; a plain build has none, so it hashes the shape.\n workbenchAppId: workbench\n ? (options.applicationId ?? (await buildAppId(workbench)))\n : undefined,\n workDir,\n })\n}\n"],"names":["compareDependencyVersions","buildApp","internalBuildApp","buildAppId","resolveWorkbenchApp","getAppId","warnAboutMissingAppId","determineBasePath","options","cliConfig","flags","outDir","output","workDir","app","undefined","workbench","exposes","config","services","views","appId","appTitle","title","autoUpdatesEnabled","checkAppId","calledFromDeploy","appType","packages","entry","isWorkbenchApp","minify","reactCompiler","schemaExtraction","sourceMap","Boolean","stats","unattendedMode","yes","vite","workbenchAppId","applicationId"],"mappings":"AAAA,SACEA,yBAAyB,EACzBC,YAAYC,gBAAgB,QACvB,oCAAmC;AAC1C,SAAQC,UAAU,EAAEC,mBAAmB,QAAO,8BAA6B;AAE3E,SAAQC,QAAQ,QAAO,sBAAqB;AAC5C,SAAQC,qBAAqB,QAAO,sCAAqC;AACzE,SAAQC,iBAAiB,QAAO,yBAAwB;AAGxD;;;;CAIC,GACD,OAAO,eAAeN,SAASO,OAAqB;IAClD,MAAM,EAACC,SAAS,EAAEC,KAAK,EAAEC,MAAM,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGL;IAEpD,MAAMM,MAAML,aAAa,SAASA,YAAYA,UAAUK,GAAG,GAAGC;IAC9D,8EAA8E;IAC9E,8EAA8E;IAC9E,MAAMC,YAAYZ,oBAAoBK;IACtC,MAAMQ,UAAUD,YACZ;QAACE,QAAQF,UAAUE,MAAM;QAAEC,UAAUH,UAAUG,QAAQ;QAAEC,OAAOJ,UAAUI,KAAK;IAAA,IAC/EL;IAEJ,MAAMM,QAAQhB,SAASI;IAEvB,MAAMP,iBAAiB;QACrBmB;QACAC,UAAUR,KAAKS;QACfC,oBAAoBhB,QAAQgB,kBAAkB;QAC9CC,YAAY;YACV,wDAAwD;YACxD,kEAAkE;YAClE,yDAAyD;YACzD,IAAI,CAACJ,SAAS,CAACb,QAAQkB,gBAAgB,EAAE;gBACvCpB,sBAAsB;oBAACqB,SAAS;oBAAOf;gBAAM;YAC/C;QACF;QACAZ,2BAA2B,CAAC4B,WAAa5B,0BAA0B4B,UAAUf,SAAS;gBAACQ;YAAK;QAC5Fd,mBAAmB,IAAMA,kBAAkBE,WAAW,OAAOG;QAC7DiB,OAAOf,KAAKe;QACZZ;QACAa,gBAAgB,CAAC,CAACd;QAClBe,QAAQrB,MAAMqB,MAAM;QACpBpB;QACAC;QACAoB,eAAevB,aAAa,mBAAmBA,YAAYA,UAAUuB,aAAa,GAAGjB;QACrFkB,kBAAkBxB,WAAWwB;QAC7BC,WAAWC,QAAQzB,KAAK,CAAC,cAAc;QACvC0B,OAAO1B,MAAM0B,KAAK;QAClBC,gBAAgB3B,MAAM4B,GAAG;QACzBC,MAAM9B,UAAU8B,IAAI;QACpB,2EAA2E;QAC3E,oFAAoF;QACpFC,gBAAgBxB,YACXR,QAAQiC,aAAa,IAAK,MAAMtC,WAAWa,aAC5CD;QACJF;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/actions/build/buildApp.ts"],"sourcesContent":["import {\n compareDependencyVersions,\n buildApp as internalBuildApp,\n} from '@sanity/cli-build/_internal/build'\nimport {buildAppId, resolveWorkbenchApp} from '@sanity/workbench-cli/build'\n\nimport {getAppId} from '../../util/appId.js'\nimport {warnAboutMissingAppId} from '../../util/warnAboutMissingAppId.js'\nimport {determineBasePath} from './determineBasePath.js'\nimport {preReleaseEventListenerFactory} from './eventListenerFactory.js'\nimport {type BuildOptions} from './types.js'\n\n/**\n * Build the Sanity app.\n *\n * @internal\n */\nexport async function buildApp(options: BuildOptions): Promise<void> {\n const {cliConfig, flags, outDir, output, workDir} = options\n\n const app = cliConfig && 'app' in cliConfig ? cliConfig.app : undefined\n // `views`/`services` live on the branded `unstable_defineApp` result, not the\n // legacy `app` config object — resolve the workbench capability to read them.\n const workbench = resolveWorkbenchApp(cliConfig)\n const exposes = workbench\n ? {config: workbench.config, services: workbench.services, views: workbench.views}\n : undefined\n\n const appId = getAppId(cliConfig)\n\n await internalBuildApp({\n appId,\n appTitle: app?.title,\n autoUpdatesEnabled: options.autoUpdatesEnabled,\n checkAppId: () => {\n // Warn if auto updates enabled but no appId configured.\n // Skip when called from deploy, since deploy handles appId itself\n // (prompts the user and tells them to add it to config).\n if (!appId && !options.calledFromDeploy) {\n warnAboutMissingAppId({appType: 'app', output})\n }\n },\n compareDependencyVersions: (packages) => compareDependencyVersions(packages, workDir, {appId}),\n determineBasePath: () => determineBasePath(cliConfig, 'app', output),\n entry: app?.entry,\n exposes,\n isWorkbenchApp: !!workbench,\n minify: flags.minify,\n outDir,\n output,\n reactCompiler: cliConfig && 'reactCompiler' in cliConfig ? cliConfig.reactCompiler : undefined,\n schemaExtraction: cliConfig?.schemaExtraction,\n sourceMap: Boolean(flags['source-maps']),\n stats: flags.stats,\n unattendedMode: flags.yes,\n vite: cliConfig.vite,\n // Shared with deploy: it passes the resolved application id (minted by the\n // API on a first deploy) to inline; a plain build has none, so it hashes the shape.\n workbenchAppId: workbench\n ? (options.applicationId ?? (await buildAppId(workbench)))\n : undefined,\n workDir,\n\n eventListener: preReleaseEventListenerFactory(output),\n })\n}\n"],"names":["compareDependencyVersions","buildApp","internalBuildApp","buildAppId","resolveWorkbenchApp","getAppId","warnAboutMissingAppId","determineBasePath","preReleaseEventListenerFactory","options","cliConfig","flags","outDir","output","workDir","app","undefined","workbench","exposes","config","services","views","appId","appTitle","title","autoUpdatesEnabled","checkAppId","calledFromDeploy","appType","packages","entry","isWorkbenchApp","minify","reactCompiler","schemaExtraction","sourceMap","Boolean","stats","unattendedMode","yes","vite","workbenchAppId","applicationId","eventListener"],"mappings":"AAAA,SACEA,yBAAyB,EACzBC,YAAYC,gBAAgB,QACvB,oCAAmC;AAC1C,SAAQC,UAAU,EAAEC,mBAAmB,QAAO,8BAA6B;AAE3E,SAAQC,QAAQ,QAAO,sBAAqB;AAC5C,SAAQC,qBAAqB,QAAO,sCAAqC;AACzE,SAAQC,iBAAiB,QAAO,yBAAwB;AACxD,SAAQC,8BAA8B,QAAO,4BAA2B;AAGxE;;;;CAIC,GACD,OAAO,eAAeP,SAASQ,OAAqB;IAClD,MAAM,EAACC,SAAS,EAAEC,KAAK,EAAEC,MAAM,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGL;IAEpD,MAAMM,MAAML,aAAa,SAASA,YAAYA,UAAUK,GAAG,GAAGC;IAC9D,8EAA8E;IAC9E,8EAA8E;IAC9E,MAAMC,YAAYb,oBAAoBM;IACtC,MAAMQ,UAAUD,YACZ;QAACE,QAAQF,UAAUE,MAAM;QAAEC,UAAUH,UAAUG,QAAQ;QAAEC,OAAOJ,UAAUI,KAAK;IAAA,IAC/EL;IAEJ,MAAMM,QAAQjB,SAASK;IAEvB,MAAMR,iBAAiB;QACrBoB;QACAC,UAAUR,KAAKS;QACfC,oBAAoBhB,QAAQgB,kBAAkB;QAC9CC,YAAY;YACV,wDAAwD;YACxD,kEAAkE;YAClE,yDAAyD;YACzD,IAAI,CAACJ,SAAS,CAACb,QAAQkB,gBAAgB,EAAE;gBACvCrB,sBAAsB;oBAACsB,SAAS;oBAAOf;gBAAM;YAC/C;QACF;QACAb,2BAA2B,CAAC6B,WAAa7B,0BAA0B6B,UAAUf,SAAS;gBAACQ;YAAK;QAC5Ff,mBAAmB,IAAMA,kBAAkBG,WAAW,OAAOG;QAC7DiB,OAAOf,KAAKe;QACZZ;QACAa,gBAAgB,CAAC,CAACd;QAClBe,QAAQrB,MAAMqB,MAAM;QACpBpB;QACAC;QACAoB,eAAevB,aAAa,mBAAmBA,YAAYA,UAAUuB,aAAa,GAAGjB;QACrFkB,kBAAkBxB,WAAWwB;QAC7BC,WAAWC,QAAQzB,KAAK,CAAC,cAAc;QACvC0B,OAAO1B,MAAM0B,KAAK;QAClBC,gBAAgB3B,MAAM4B,GAAG;QACzBC,MAAM9B,UAAU8B,IAAI;QACpB,2EAA2E;QAC3E,oFAAoF;QACpFC,gBAAgBxB,YACXR,QAAQiC,aAAa,IAAK,MAAMvC,WAAWc,aAC5CD;QACJF;QAEA6B,eAAenC,+BAA+BK;IAChD;AACF"}
@@ -1,4 +1,6 @@
1
+ import { styleText } from 'node:util';
1
2
  import { compareDependencyVersions, buildStudio as internalBuildStudio } from '@sanity/cli-build/_internal/build';
3
+ import { confirm, logSymbols, select, spinner } from '@sanity/cli-core/ux';
2
4
  import { buildAppId, resolveWorkbenchApp } from '@sanity/workbench-cli/build';
3
5
  import { getAppId } from '../../util/appId.js';
4
6
  import { determineIsApp } from '../../util/determineIsApp.js';
@@ -6,6 +8,7 @@ import { getPackageManagerChoice } from '../../util/packageManager/packageManage
6
8
  import { upgradePackages } from '../../util/packageManager/upgradePackages.js';
7
9
  import { warnAboutMissingAppId } from '../../util/warnAboutMissingAppId.js';
8
10
  import { determineBasePath } from './determineBasePath.js';
11
+ import { checkDependenciesEventListenerFactory, preReleaseEventListenerFactory } from './eventListenerFactory.js';
9
12
  /**
10
13
  * Build the Sanity Studio.
11
14
  *
@@ -20,17 +23,8 @@ import { determineBasePath } from './determineBasePath.js';
20
23
  views: workbench.views
21
24
  } : undefined;
22
25
  const appId = getAppId(cliConfig);
23
- const upgradePkgs = async (options)=>{
24
- await upgradePackages({
25
- packageManager: (await getPackageManagerChoice(workDir, {
26
- interactive: false
27
- })).chosen,
28
- packages: options.packages
29
- }, {
30
- output,
31
- workDir
32
- });
33
- };
26
+ let cleanOutputDirSpinner;
27
+ let buildSpinner;
34
28
  await internalBuildStudio({
35
29
  appId,
36
30
  autoUpdatesEnabled: options.autoUpdatesEnabled,
@@ -61,12 +55,109 @@ import { determineBasePath } from './determineBasePath.js';
61
55
  sourceMap: Boolean(flags['source-maps']),
62
56
  stats: flags.stats,
63
57
  unattendedMode: Boolean(flags.yes),
64
- upgradePackages: upgradePkgs,
65
58
  vite: cliConfig.vite,
66
59
  // Shared with deploy: it passes the resolved application id (minted by the
67
60
  // API on a first deploy) to inline; a plain build has none, so it hashes the shape.
68
61
  workbenchAppId: workbench ? options.applicationId ?? await buildAppId(workbench) : undefined,
69
- workDir
62
+ workDir,
63
+ eventListener: {
64
+ ...preReleaseEventListenerFactory(output),
65
+ ...checkDependenciesEventListenerFactory(output),
66
+ onBuildEnd ({ message }) {
67
+ if (buildSpinner) {
68
+ buildSpinner.text = message;
69
+ buildSpinner.succeed();
70
+ }
71
+ },
72
+ onBuildFail ({ message }) {
73
+ if (buildSpinner) {
74
+ buildSpinner.fail();
75
+ }
76
+ output.error(message, {
77
+ exit: 1
78
+ });
79
+ },
80
+ onBuildStart ({ message }) {
81
+ if (!buildSpinner) {
82
+ buildSpinner = spinner(message).start();
83
+ }
84
+ },
85
+ onCleanOutputDirEnd ({ message }) {
86
+ if (cleanOutputDirSpinner) {
87
+ cleanOutputDirSpinner.text = message;
88
+ cleanOutputDirSpinner.succeed();
89
+ }
90
+ },
91
+ onCleanOutputDirStart ({ message }) {
92
+ if (!cleanOutputDirSpinner) {
93
+ cleanOutputDirSpinner = spinner(message).start();
94
+ }
95
+ },
96
+ async onInteractiveNonDefaultOutputDir ({ message }) {
97
+ const shouldClean = await confirm({
98
+ default: true,
99
+ message
100
+ });
101
+ return {
102
+ shouldClean
103
+ };
104
+ },
105
+ async onVersionMismatchInInteractiveAutoUpdate ({ mismatched, versionMismatchWarning }) {
106
+ const choice = await select({
107
+ choices: [
108
+ {
109
+ name: `Upgrade local versions (recommended). You will need to run the build command again`,
110
+ value: 'upgrade'
111
+ },
112
+ {
113
+ name: `Upgrade and proceed with build`,
114
+ value: 'upgrade-and-proceed'
115
+ },
116
+ {
117
+ name: `Continue anyway`,
118
+ value: 'continue'
119
+ },
120
+ {
121
+ name: 'Cancel',
122
+ value: 'cancel'
123
+ }
124
+ ],
125
+ default: 'upgrade',
126
+ message: styleText('yellow', `${logSymbols.warning} ${versionMismatchWarning}\n\nDo you want to upgrade local versions before deploying?`)
127
+ });
128
+ if (choice === 'cancel') {
129
+ output.error('Declined to continue with build', {
130
+ exit: 1
131
+ });
132
+ return {
133
+ stopBuild: true
134
+ };
135
+ }
136
+ if (choice === 'upgrade' || choice === 'upgrade-and-proceed') {
137
+ await upgradePackages({
138
+ packageManager: (await getPackageManagerChoice(workDir, {
139
+ interactive: false
140
+ })).chosen,
141
+ packages: mismatched.map((res)=>[
142
+ res.pkg,
143
+ res.remote
144
+ ])
145
+ }, {
146
+ output,
147
+ workDir
148
+ });
149
+ return {
150
+ stopBuild: choice === 'upgrade'
151
+ };
152
+ }
153
+ return {
154
+ stopBuild: false
155
+ };
156
+ },
157
+ onVersionMismatchInNonInteractiveAutoUpdate ({ versionMismatchWarning }) {
158
+ output.warn(versionMismatchWarning);
159
+ }
160
+ }
70
161
  });
71
162
  }
72
163
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/actions/build/buildStudio.ts"],"sourcesContent":["import {\n compareDependencyVersions,\n buildStudio as internalBuildStudio,\n} from '@sanity/cli-build/_internal/build'\nimport {buildAppId, resolveWorkbenchApp} from '@sanity/workbench-cli/build'\n\nimport {getAppId} from '../../util/appId.js'\nimport {determineIsApp} from '../../util/determineIsApp.js'\nimport {getPackageManagerChoice} from '../../util/packageManager/packageManagerChoice.js'\nimport {upgradePackages} from '../../util/packageManager/upgradePackages.js'\nimport {warnAboutMissingAppId} from '../../util/warnAboutMissingAppId.js'\nimport {determineBasePath} from './determineBasePath.js'\nimport {type BuildOptions} from './types.js'\n\n/**\n * Build the Sanity Studio.\n *\n * @internal\n */\nexport async function buildStudio(options: BuildOptions): Promise<void> {\n const {calledFromDeploy, cliConfig, flags, outDir, output, workDir} = options\n\n // `views`/`services` live on the branded `unstable_defineApp` result — resolve\n // the workbench capability so it's gated on the brand, like the app build.\n const workbench = resolveWorkbenchApp(cliConfig)\n const exposes = workbench ? {services: workbench.services, views: workbench.views} : undefined\n\n const appId = getAppId(cliConfig)\n\n const upgradePkgs = async (options: {\n packages: [name: string, version: string][]\n }): Promise<void> => {\n await upgradePackages(\n {\n packageManager: (await getPackageManagerChoice(workDir, {interactive: false})).chosen,\n packages: options.packages,\n },\n {output, workDir},\n )\n }\n\n await internalBuildStudio({\n appId,\n autoUpdatesEnabled: options.autoUpdatesEnabled,\n checkAppId: () => {\n // Warn if auto updates enabled but no appId configured.\n // Skip when called from deploy, since deploy handles appId itself\n // (prompts the user and tells them to add it to config).\n if (!appId && !calledFromDeploy) {\n warnAboutMissingAppId({appType: 'studio', output, projectId: cliConfig?.api?.projectId})\n }\n },\n compareDependencyVersions: (packages) => compareDependencyVersions(packages, workDir, {appId}),\n determineBasePath: () => determineBasePath(cliConfig, 'studio', output),\n exposes,\n isApp: determineIsApp(cliConfig),\n isWorkbenchApp: !!workbench,\n minify: Boolean(flags.minify),\n outDir,\n output,\n reactCompiler: cliConfig.reactCompiler,\n schemaExtraction: cliConfig.schemaExtraction,\n sourceMap: Boolean(flags['source-maps']),\n stats: flags.stats,\n unattendedMode: Boolean(flags.yes),\n upgradePackages: upgradePkgs,\n vite: cliConfig.vite,\n // Shared with deploy: it passes the resolved application id (minted by the\n // API on a first deploy) to inline; a plain build has none, so it hashes the shape.\n workbenchAppId: workbench\n ? (options.applicationId ?? (await buildAppId(workbench)))\n : undefined,\n workDir,\n })\n}\n"],"names":["compareDependencyVersions","buildStudio","internalBuildStudio","buildAppId","resolveWorkbenchApp","getAppId","determineIsApp","getPackageManagerChoice","upgradePackages","warnAboutMissingAppId","determineBasePath","options","calledFromDeploy","cliConfig","flags","outDir","output","workDir","workbench","exposes","services","views","undefined","appId","upgradePkgs","packageManager","interactive","chosen","packages","autoUpdatesEnabled","checkAppId","appType","projectId","api","isApp","isWorkbenchApp","minify","Boolean","reactCompiler","schemaExtraction","sourceMap","stats","unattendedMode","yes","vite","workbenchAppId","applicationId"],"mappings":"AAAA,SACEA,yBAAyB,EACzBC,eAAeC,mBAAmB,QAC7B,oCAAmC;AAC1C,SAAQC,UAAU,EAAEC,mBAAmB,QAAO,8BAA6B;AAE3E,SAAQC,QAAQ,QAAO,sBAAqB;AAC5C,SAAQC,cAAc,QAAO,+BAA8B;AAC3D,SAAQC,uBAAuB,QAAO,oDAAmD;AACzF,SAAQC,eAAe,QAAO,+CAA8C;AAC5E,SAAQC,qBAAqB,QAAO,sCAAqC;AACzE,SAAQC,iBAAiB,QAAO,yBAAwB;AAGxD;;;;CAIC,GACD,OAAO,eAAeT,YAAYU,OAAqB;IACrD,MAAM,EAACC,gBAAgB,EAAEC,SAAS,EAAEC,KAAK,EAAEC,MAAM,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGN;IAEtE,+EAA+E;IAC/E,2EAA2E;IAC3E,MAAMO,YAAYd,oBAAoBS;IACtC,MAAMM,UAAUD,YAAY;QAACE,UAAUF,UAAUE,QAAQ;QAAEC,OAAOH,UAAUG,KAAK;IAAA,IAAIC;IAErF,MAAMC,QAAQlB,SAASQ;IAEvB,MAAMW,cAAc,OAAOb;QAGzB,MAAMH,gBACJ;YACEiB,gBAAgB,AAAC,CAAA,MAAMlB,wBAAwBU,SAAS;gBAACS,aAAa;YAAK,EAAC,EAAGC,MAAM;YACrFC,UAAUjB,QAAQiB,QAAQ;QAC5B,GACA;YAACZ;YAAQC;QAAO;IAEpB;IAEA,MAAMf,oBAAoB;QACxBqB;QACAM,oBAAoBlB,QAAQkB,kBAAkB;QAC9CC,YAAY;YACV,wDAAwD;YACxD,kEAAkE;YAClE,yDAAyD;YACzD,IAAI,CAACP,SAAS,CAACX,kBAAkB;gBAC/BH,sBAAsB;oBAACsB,SAAS;oBAAUf;oBAAQgB,WAAWnB,WAAWoB,KAAKD;gBAAS;YACxF;QACF;QACAhC,2BAA2B,CAAC4B,WAAa5B,0BAA0B4B,UAAUX,SAAS;gBAACM;YAAK;QAC5Fb,mBAAmB,IAAMA,kBAAkBG,WAAW,UAAUG;QAChEG;QACAe,OAAO5B,eAAeO;QACtBsB,gBAAgB,CAAC,CAACjB;QAClBkB,QAAQC,QAAQvB,MAAMsB,MAAM;QAC5BrB;QACAC;QACAsB,eAAezB,UAAUyB,aAAa;QACtCC,kBAAkB1B,UAAU0B,gBAAgB;QAC5CC,WAAWH,QAAQvB,KAAK,CAAC,cAAc;QACvC2B,OAAO3B,MAAM2B,KAAK;QAClBC,gBAAgBL,QAAQvB,MAAM6B,GAAG;QACjCnC,iBAAiBgB;QACjBoB,MAAM/B,UAAU+B,IAAI;QACpB,2EAA2E;QAC3E,oFAAoF;QACpFC,gBAAgB3B,YACXP,QAAQmC,aAAa,IAAK,MAAM3C,WAAWe,aAC5CI;QACJL;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/actions/build/buildStudio.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {\n compareDependencyVersions,\n buildStudio as internalBuildStudio,\n} from '@sanity/cli-build/_internal/build'\nimport {confirm, logSymbols, select, spinner} from '@sanity/cli-core/ux'\nimport {buildAppId, resolveWorkbenchApp} from '@sanity/workbench-cli/build'\n\nimport {getAppId} from '../../util/appId.js'\nimport {determineIsApp} from '../../util/determineIsApp.js'\nimport {getPackageManagerChoice} from '../../util/packageManager/packageManagerChoice.js'\nimport {upgradePackages} from '../../util/packageManager/upgradePackages.js'\nimport {warnAboutMissingAppId} from '../../util/warnAboutMissingAppId.js'\nimport {determineBasePath} from './determineBasePath.js'\nimport {\n checkDependenciesEventListenerFactory,\n preReleaseEventListenerFactory,\n} from './eventListenerFactory.js'\nimport {type BuildOptions} from './types.js'\n\n/**\n * Build the Sanity Studio.\n *\n * @internal\n */\nexport async function buildStudio(options: BuildOptions): Promise<void> {\n const {calledFromDeploy, cliConfig, flags, outDir, output, workDir} = options\n\n // `views`/`services` live on the branded `unstable_defineApp` result — resolve\n // the workbench capability so it's gated on the brand, like the app build.\n const workbench = resolveWorkbenchApp(cliConfig)\n const exposes = workbench ? {services: workbench.services, views: workbench.views} : undefined\n\n const appId = getAppId(cliConfig)\n\n let cleanOutputDirSpinner: ReturnType<typeof spinner> | undefined\n let buildSpinner: ReturnType<typeof spinner> | undefined\n\n await internalBuildStudio({\n appId,\n autoUpdatesEnabled: options.autoUpdatesEnabled,\n checkAppId: () => {\n // Warn if auto updates enabled but no appId configured.\n // Skip when called from deploy, since deploy handles appId itself\n // (prompts the user and tells them to add it to config).\n if (!appId && !calledFromDeploy) {\n warnAboutMissingAppId({appType: 'studio', output, projectId: cliConfig?.api?.projectId})\n }\n },\n compareDependencyVersions: (packages) => compareDependencyVersions(packages, workDir, {appId}),\n determineBasePath: () => determineBasePath(cliConfig, 'studio', output),\n exposes,\n isApp: determineIsApp(cliConfig),\n isWorkbenchApp: !!workbench,\n minify: Boolean(flags.minify),\n outDir,\n output,\n reactCompiler: cliConfig.reactCompiler,\n schemaExtraction: cliConfig.schemaExtraction,\n sourceMap: Boolean(flags['source-maps']),\n stats: flags.stats,\n unattendedMode: Boolean(flags.yes),\n vite: cliConfig.vite,\n // Shared with deploy: it passes the resolved application id (minted by the\n // API on a first deploy) to inline; a plain build has none, so it hashes the shape.\n workbenchAppId: workbench\n ? (options.applicationId ?? (await buildAppId(workbench)))\n : undefined,\n workDir,\n\n eventListener: {\n ...preReleaseEventListenerFactory(output),\n\n ...checkDependenciesEventListenerFactory(output),\n\n onBuildEnd({message}) {\n if (buildSpinner) {\n buildSpinner.text = message\n buildSpinner.succeed()\n }\n },\n onBuildFail({message}) {\n if (buildSpinner) {\n buildSpinner.fail()\n }\n\n output.error(message, {exit: 1})\n },\n onBuildStart({message}) {\n if (!buildSpinner) {\n buildSpinner = spinner(message).start()\n }\n },\n onCleanOutputDirEnd({message}) {\n if (cleanOutputDirSpinner) {\n cleanOutputDirSpinner.text = message\n cleanOutputDirSpinner.succeed()\n }\n },\n onCleanOutputDirStart({message}) {\n if (!cleanOutputDirSpinner) {\n cleanOutputDirSpinner = spinner(message).start()\n }\n },\n async onInteractiveNonDefaultOutputDir({message}: {message: string}) {\n const shouldClean = await confirm({\n default: true,\n message,\n })\n return {shouldClean}\n },\n async onVersionMismatchInInteractiveAutoUpdate({mismatched, versionMismatchWarning}) {\n const choice = await select({\n choices: [\n {\n name: `Upgrade local versions (recommended). You will need to run the build command again`,\n value: 'upgrade',\n },\n {\n name: `Upgrade and proceed with build`,\n value: 'upgrade-and-proceed',\n },\n {\n name: `Continue anyway`,\n value: 'continue',\n },\n {name: 'Cancel', value: 'cancel'},\n ],\n default: 'upgrade',\n message: styleText(\n 'yellow',\n `${logSymbols.warning} ${versionMismatchWarning}\\n\\nDo you want to upgrade local versions before deploying?`,\n ),\n })\n\n if (choice === 'cancel') {\n output.error('Declined to continue with build', {exit: 1})\n return {stopBuild: true}\n }\n\n if (choice === 'upgrade' || choice === 'upgrade-and-proceed') {\n await upgradePackages(\n {\n packageManager: (await getPackageManagerChoice(workDir, {interactive: false})).chosen,\n packages: mismatched.map((res) => [res.pkg, res.remote]),\n },\n {output, workDir},\n )\n\n return {stopBuild: choice === 'upgrade'}\n }\n\n return {stopBuild: false}\n },\n onVersionMismatchInNonInteractiveAutoUpdate({versionMismatchWarning}) {\n output.warn(versionMismatchWarning)\n },\n },\n })\n}\n"],"names":["styleText","compareDependencyVersions","buildStudio","internalBuildStudio","confirm","logSymbols","select","spinner","buildAppId","resolveWorkbenchApp","getAppId","determineIsApp","getPackageManagerChoice","upgradePackages","warnAboutMissingAppId","determineBasePath","checkDependenciesEventListenerFactory","preReleaseEventListenerFactory","options","calledFromDeploy","cliConfig","flags","outDir","output","workDir","workbench","exposes","services","views","undefined","appId","cleanOutputDirSpinner","buildSpinner","autoUpdatesEnabled","checkAppId","appType","projectId","api","packages","isApp","isWorkbenchApp","minify","Boolean","reactCompiler","schemaExtraction","sourceMap","stats","unattendedMode","yes","vite","workbenchAppId","applicationId","eventListener","onBuildEnd","message","text","succeed","onBuildFail","fail","error","exit","onBuildStart","start","onCleanOutputDirEnd","onCleanOutputDirStart","onInteractiveNonDefaultOutputDir","shouldClean","default","onVersionMismatchInInteractiveAutoUpdate","mismatched","versionMismatchWarning","choice","choices","name","value","warning","stopBuild","packageManager","interactive","chosen","map","res","pkg","remote","onVersionMismatchInNonInteractiveAutoUpdate","warn"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SACEC,yBAAyB,EACzBC,eAAeC,mBAAmB,QAC7B,oCAAmC;AAC1C,SAAQC,OAAO,EAAEC,UAAU,EAAEC,MAAM,EAAEC,OAAO,QAAO,sBAAqB;AACxE,SAAQC,UAAU,EAAEC,mBAAmB,QAAO,8BAA6B;AAE3E,SAAQC,QAAQ,QAAO,sBAAqB;AAC5C,SAAQC,cAAc,QAAO,+BAA8B;AAC3D,SAAQC,uBAAuB,QAAO,oDAAmD;AACzF,SAAQC,eAAe,QAAO,+CAA8C;AAC5E,SAAQC,qBAAqB,QAAO,sCAAqC;AACzE,SAAQC,iBAAiB,QAAO,yBAAwB;AACxD,SACEC,qCAAqC,EACrCC,8BAA8B,QACzB,4BAA2B;AAGlC;;;;CAIC,GACD,OAAO,eAAef,YAAYgB,OAAqB;IACrD,MAAM,EAACC,gBAAgB,EAAEC,SAAS,EAAEC,KAAK,EAAEC,MAAM,EAAEC,MAAM,EAAEC,OAAO,EAAC,GAAGN;IAEtE,+EAA+E;IAC/E,2EAA2E;IAC3E,MAAMO,YAAYhB,oBAAoBW;IACtC,MAAMM,UAAUD,YAAY;QAACE,UAAUF,UAAUE,QAAQ;QAAEC,OAAOH,UAAUG,KAAK;IAAA,IAAIC;IAErF,MAAMC,QAAQpB,SAASU;IAEvB,IAAIW;IACJ,IAAIC;IAEJ,MAAM7B,oBAAoB;QACxB2B;QACAG,oBAAoBf,QAAQe,kBAAkB;QAC9CC,YAAY;YACV,wDAAwD;YACxD,kEAAkE;YAClE,yDAAyD;YACzD,IAAI,CAACJ,SAAS,CAACX,kBAAkB;gBAC/BL,sBAAsB;oBAACqB,SAAS;oBAAUZ;oBAAQa,WAAWhB,WAAWiB,KAAKD;gBAAS;YACxF;QACF;QACAnC,2BAA2B,CAACqC,WAAarC,0BAA0BqC,UAAUd,SAAS;gBAACM;YAAK;QAC5Ff,mBAAmB,IAAMA,kBAAkBK,WAAW,UAAUG;QAChEG;QACAa,OAAO5B,eAAeS;QACtBoB,gBAAgB,CAAC,CAACf;QAClBgB,QAAQC,QAAQrB,MAAMoB,MAAM;QAC5BnB;QACAC;QACAoB,eAAevB,UAAUuB,aAAa;QACtCC,kBAAkBxB,UAAUwB,gBAAgB;QAC5CC,WAAWH,QAAQrB,KAAK,CAAC,cAAc;QACvCyB,OAAOzB,MAAMyB,KAAK;QAClBC,gBAAgBL,QAAQrB,MAAM2B,GAAG;QACjCC,MAAM7B,UAAU6B,IAAI;QACpB,2EAA2E;QAC3E,oFAAoF;QACpFC,gBAAgBzB,YACXP,QAAQiC,aAAa,IAAK,MAAM3C,WAAWiB,aAC5CI;QACJL;QAEA4B,eAAe;YACb,GAAGnC,+BAA+BM,OAAO;YAEzC,GAAGP,sCAAsCO,OAAO;YAEhD8B,YAAW,EAACC,OAAO,EAAC;gBAClB,IAAItB,cAAc;oBAChBA,aAAauB,IAAI,GAAGD;oBACpBtB,aAAawB,OAAO;gBACtB;YACF;YACAC,aAAY,EAACH,OAAO,EAAC;gBACnB,IAAItB,cAAc;oBAChBA,aAAa0B,IAAI;gBACnB;gBAEAnC,OAAOoC,KAAK,CAACL,SAAS;oBAACM,MAAM;gBAAC;YAChC;YACAC,cAAa,EAACP,OAAO,EAAC;gBACpB,IAAI,CAACtB,cAAc;oBACjBA,eAAezB,QAAQ+C,SAASQ,KAAK;gBACvC;YACF;YACAC,qBAAoB,EAACT,OAAO,EAAC;gBAC3B,IAAIvB,uBAAuB;oBACzBA,sBAAsBwB,IAAI,GAAGD;oBAC7BvB,sBAAsByB,OAAO;gBAC/B;YACF;YACAQ,uBAAsB,EAACV,OAAO,EAAC;gBAC7B,IAAI,CAACvB,uBAAuB;oBAC1BA,wBAAwBxB,QAAQ+C,SAASQ,KAAK;gBAChD;YACF;YACA,MAAMG,kCAAiC,EAACX,OAAO,EAAoB;gBACjE,MAAMY,cAAc,MAAM9D,QAAQ;oBAChC+D,SAAS;oBACTb;gBACF;gBACA,OAAO;oBAACY;gBAAW;YACrB;YACA,MAAME,0CAAyC,EAACC,UAAU,EAAEC,sBAAsB,EAAC;gBACjF,MAAMC,SAAS,MAAMjE,OAAO;oBAC1BkE,SAAS;wBACP;4BACEC,MAAM,CAAC,kFAAkF,CAAC;4BAC1FC,OAAO;wBACT;wBACA;4BACED,MAAM,CAAC,8BAA8B,CAAC;4BACtCC,OAAO;wBACT;wBACA;4BACED,MAAM,CAAC,eAAe,CAAC;4BACvBC,OAAO;wBACT;wBACA;4BAACD,MAAM;4BAAUC,OAAO;wBAAQ;qBACjC;oBACDP,SAAS;oBACTb,SAAStD,UACP,UACA,GAAGK,WAAWsE,OAAO,CAAC,CAAC,EAAEL,uBAAuB,2DAA2D,CAAC;gBAEhH;gBAEA,IAAIC,WAAW,UAAU;oBACvBhD,OAAOoC,KAAK,CAAC,mCAAmC;wBAACC,MAAM;oBAAC;oBACxD,OAAO;wBAACgB,WAAW;oBAAI;gBACzB;gBAEA,IAAIL,WAAW,aAAaA,WAAW,uBAAuB;oBAC5D,MAAM1D,gBACJ;wBACEgE,gBAAgB,AAAC,CAAA,MAAMjE,wBAAwBY,SAAS;4BAACsD,aAAa;wBAAK,EAAC,EAAGC,MAAM;wBACrFzC,UAAU+B,WAAWW,GAAG,CAAC,CAACC,MAAQ;gCAACA,IAAIC,GAAG;gCAAED,IAAIE,MAAM;6BAAC;oBACzD,GACA;wBAAC5D;wBAAQC;oBAAO;oBAGlB,OAAO;wBAACoD,WAAWL,WAAW;oBAAS;gBACzC;gBAEA,OAAO;oBAACK,WAAW;gBAAK;YAC1B;YACAQ,6CAA4C,EAACd,sBAAsB,EAAC;gBAClE/C,OAAO8D,IAAI,CAACf;YACd;QACF;IACF;AACF"}
@@ -0,0 +1,70 @@
1
+ import { styleText } from 'node:util';
2
+ import { select } from '@sanity/cli-core/ux';
3
+ /**
4
+ * Creates check dependency event handlers that are shared between buildStudio and startStudioDevServer.
5
+ */ export function checkDependenciesEventListenerFactory(output) {
6
+ return {
7
+ onIncompatibleDeclaredStyledComponentsVersionRange ({ message }) {
8
+ output.warn(message);
9
+ },
10
+ onIncompatibleInstalledStyledComponentsVersionRange ({ message }) {
11
+ output.warn(message);
12
+ },
13
+ onInvalidStyledComponentsVersionRange ({ message }) {
14
+ output.error(message, {
15
+ exit: 1
16
+ });
17
+ },
18
+ onNoDeclaredStyledComponentsVersion ({ message }) {
19
+ output.error(message, {
20
+ exit: 1
21
+ });
22
+ },
23
+ onNoInstalledSanityVersion ({ message }) {
24
+ output.error(message, {
25
+ exit: 1
26
+ });
27
+ },
28
+ onNoInstalledStyledComponentsVersion ({ message }) {
29
+ output.error(message, {
30
+ exit: 1
31
+ });
32
+ }
33
+ };
34
+ }
35
+ /**
36
+ * Creates pre-release event handlers that are shared between buildApp and buildStudio.
37
+ */ export function preReleaseEventListenerFactory(output) {
38
+ return {
39
+ async onPreReleaseInInteractiveAutoUpdate ({ prereleaseMessage }) {
40
+ const choice = await select({
41
+ choices: [
42
+ {
43
+ name: 'Disable auto-updates for this build and continue',
44
+ value: 'disable-auto-updates'
45
+ },
46
+ {
47
+ name: 'Cancel build',
48
+ value: 'cancel'
49
+ }
50
+ ],
51
+ default: 'disable-auto-updates',
52
+ message: styleText('yellow', prereleaseMessage)
53
+ });
54
+ if (choice === 'cancel') {
55
+ output.error('Declined to continue with build', {
56
+ exit: 1
57
+ });
58
+ return;
59
+ }
60
+ output.warn('Auto-updates disabled for this build');
61
+ },
62
+ onPreReleaseInNonInteractiveAutoUpdate ({ message }) {
63
+ output.error(message, {
64
+ exit: 1
65
+ });
66
+ }
67
+ };
68
+ }
69
+
70
+ //# sourceMappingURL=eventListenerFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/actions/build/eventListenerFactory.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {Output} from '@sanity/cli-core'\nimport {select} from '@sanity/cli-core/ux'\n\n/**\n * Creates check dependency event handlers that are shared between buildStudio and startStudioDevServer.\n */\nexport function checkDependenciesEventListenerFactory(output: Output) {\n return {\n onIncompatibleDeclaredStyledComponentsVersionRange({message}: {message: string}) {\n output.warn(message)\n },\n onIncompatibleInstalledStyledComponentsVersionRange({message}: {message: string}) {\n output.warn(message)\n },\n onInvalidStyledComponentsVersionRange({message}: {message: string}) {\n output.error(message, {exit: 1})\n },\n onNoDeclaredStyledComponentsVersion({message}: {message: string}) {\n output.error(message, {exit: 1})\n },\n onNoInstalledSanityVersion({message}: {message: string}) {\n output.error(message, {exit: 1})\n },\n onNoInstalledStyledComponentsVersion({message}: {message: string}) {\n output.error(message, {exit: 1})\n },\n }\n}\n\n/**\n * Creates pre-release event handlers that are shared between buildApp and buildStudio.\n */\nexport function preReleaseEventListenerFactory(output: Output) {\n return {\n async onPreReleaseInInteractiveAutoUpdate({prereleaseMessage}: {prereleaseMessage: string}) {\n const choice = await select({\n choices: [\n {\n name: 'Disable auto-updates for this build and continue',\n value: 'disable-auto-updates',\n },\n {name: 'Cancel build', value: 'cancel'},\n ],\n default: 'disable-auto-updates',\n message: styleText('yellow', prereleaseMessage),\n })\n\n if (choice === 'cancel') {\n output.error('Declined to continue with build', {exit: 1})\n return\n }\n\n output.warn('Auto-updates disabled for this build')\n },\n onPreReleaseInNonInteractiveAutoUpdate({message}: {message: string}) {\n output.error(message, {exit: 1})\n },\n }\n}\n"],"names":["styleText","select","checkDependenciesEventListenerFactory","output","onIncompatibleDeclaredStyledComponentsVersionRange","message","warn","onIncompatibleInstalledStyledComponentsVersionRange","onInvalidStyledComponentsVersionRange","error","exit","onNoDeclaredStyledComponentsVersion","onNoInstalledSanityVersion","onNoInstalledStyledComponentsVersion","preReleaseEventListenerFactory","onPreReleaseInInteractiveAutoUpdate","prereleaseMessage","choice","choices","name","value","default","onPreReleaseInNonInteractiveAutoUpdate"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAGnC,SAAQC,MAAM,QAAO,sBAAqB;AAE1C;;CAEC,GACD,OAAO,SAASC,sCAAsCC,MAAc;IAClE,OAAO;QACLC,oDAAmD,EAACC,OAAO,EAAoB;YAC7EF,OAAOG,IAAI,CAACD;QACd;QACAE,qDAAoD,EAACF,OAAO,EAAoB;YAC9EF,OAAOG,IAAI,CAACD;QACd;QACAG,uCAAsC,EAACH,OAAO,EAAoB;YAChEF,OAAOM,KAAK,CAACJ,SAAS;gBAACK,MAAM;YAAC;QAChC;QACAC,qCAAoC,EAACN,OAAO,EAAoB;YAC9DF,OAAOM,KAAK,CAACJ,SAAS;gBAACK,MAAM;YAAC;QAChC;QACAE,4BAA2B,EAACP,OAAO,EAAoB;YACrDF,OAAOM,KAAK,CAACJ,SAAS;gBAACK,MAAM;YAAC;QAChC;QACAG,sCAAqC,EAACR,OAAO,EAAoB;YAC/DF,OAAOM,KAAK,CAACJ,SAAS;gBAACK,MAAM;YAAC;QAChC;IACF;AACF;AAEA;;CAEC,GACD,OAAO,SAASI,+BAA+BX,MAAc;IAC3D,OAAO;QACL,MAAMY,qCAAoC,EAACC,iBAAiB,EAA8B;YACxF,MAAMC,SAAS,MAAMhB,OAAO;gBAC1BiB,SAAS;oBACP;wBACEC,MAAM;wBACNC,OAAO;oBACT;oBACA;wBAACD,MAAM;wBAAgBC,OAAO;oBAAQ;iBACvC;gBACDC,SAAS;gBACThB,SAASL,UAAU,UAAUgB;YAC/B;YAEA,IAAIC,WAAW,UAAU;gBACvBd,OAAOM,KAAK,CAAC,mCAAmC;oBAACC,MAAM;gBAAC;gBACxD;YACF;YAEAP,OAAOG,IAAI,CAAC;QACd;QACAgB,wCAAuC,EAACjB,OAAO,EAAoB;YACjEF,OAAOM,KAAK,CAACJ,SAAS;gBAACK,MAAM;YAAC;QAChC;IACF;AACF"}
@@ -10,6 +10,7 @@ import { getProjectById } from '../../../services/projects.js';
10
10
  import { getAppId } from '../../../util/appId.js';
11
11
  import { getPackageManagerChoice } from '../../../util/packageManager/packageManagerChoice.js';
12
12
  import { upgradePackages } from '../../../util/packageManager/upgradePackages.js';
13
+ import { checkDependenciesEventListenerFactory } from '../../build/eventListenerFactory.js';
13
14
  import { shouldAutoUpdate } from '../../build/shouldAutoUpdate.js';
14
15
  import { devDebug } from '../devDebug.js';
15
16
  import { getDashboardAppURL } from './getDashboardAppUrl.js';
@@ -23,7 +24,10 @@ export async function startStudioDevServer(options) {
23
24
  const loadInDashboard = flags['load-in-dashboard'] && !isWorkbenchApp(cliConfig?.app);
24
25
  // Check studio dependency versions
25
26
  await checkStudioDependencyVersions(workDir, output);
26
- const { installedSanityVersion } = await checkRequiredDependencies(options);
27
+ const { installedSanityVersion } = await checkRequiredDependencies({
28
+ ...options,
29
+ ...checkDependenciesEventListenerFactory(output)
30
+ });
27
31
  // Check if auto-updates are enabled
28
32
  const autoUpdatesEnabled = shouldAutoUpdate({
29
33
  cliConfig,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/actions/dev/servers/startStudioDevServer.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {\n checkRequiredDependencies,\n checkStudioDependencyVersions,\n compareDependencyVersions,\n} from '@sanity/cli-build/_internal/build'\nimport {getLocalPackageVersion, isInteractive} from '@sanity/cli-core'\nimport {confirm, logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\nimport {parse as semverParse} from 'semver'\n\nimport {startDevServer} from '../../../server/devServer.js'\nimport {gracefulServerDeath} from '../../../server/gracefulServerDeath.js'\nimport {getProjectById} from '../../../services/projects.js'\nimport {getAppId} from '../../../util/appId.js'\nimport {getPackageManagerChoice} from '../../../util/packageManager/packageManagerChoice.js'\nimport {upgradePackages} from '../../../util/packageManager/upgradePackages.js'\nimport {shouldAutoUpdate} from '../../build/shouldAutoUpdate.js'\nimport {devDebug} from '../devDebug.js'\nimport {type DevActionOptions, type StartDevServerResult} from '../types.js'\nimport {getDashboardAppURL} from './getDashboardAppUrl.js'\nimport {getDevServerConfig} from './getDevServerConfig.js'\n\nexport async function startStudioDevServer(\n options: DevActionOptions,\n): Promise<StartDevServerResult> {\n const {announceUrl = true, cliConfig, flags, httpPort, output, workDir} = options\n const projectId = cliConfig?.api?.projectId\n let organizationId: string | undefined\n\n // Workbench apps don't load through the dashboard, so the flag has no\n // meaning for them and is ignored.\n const loadInDashboard = flags['load-in-dashboard'] && !isWorkbenchApp(cliConfig?.app)\n\n // Check studio dependency versions\n await checkStudioDependencyVersions(workDir, output)\n\n const {installedSanityVersion} = await checkRequiredDependencies(options)\n\n // Check if auto-updates are enabled\n const autoUpdatesEnabled = shouldAutoUpdate({cliConfig, flags, output})\n\n if (autoUpdatesEnabled) {\n // Get the clean version without build metadata: https://semver.org/#spec-item-10\n const cleanSanityVersion = semverParse(installedSanityVersion)?.version\n if (!cleanSanityVersion) {\n throw new Error(`Failed to parse installed Sanity version: ${installedSanityVersion}`)\n }\n\n const sanityDependencies = [\n {name: 'sanity', version: cleanSanityVersion},\n {name: '@sanity/vision', version: cleanSanityVersion},\n ]\n\n output.log(`${logSymbols.info} Running with auto-updates enabled`)\n\n // Check local versions against deployed versions\n let result: Awaited<ReturnType<typeof compareDependencyVersions>> | undefined\n\n const appId = getAppId(cliConfig)\n\n try {\n result = await compareDependencyVersions(sanityDependencies, workDir, {appId})\n } catch (err) {\n output.warn(`Failed to compare local versions against auto-updating versions: ${err}`)\n }\n\n if (result?.unresolvedPrerelease.length) {\n for (const mod of result.unresolvedPrerelease) {\n output.warn(\n `Your local version of ${mod.pkg} (${mod.version}) is a prerelease not available on the auto-updates CDN. The locally installed version will be used.`,\n )\n }\n }\n\n // mismatch between local and auto-updating dependencies\n if (result?.mismatched.length) {\n const message =\n `The following local package versions are different from the versions currently served at runtime.\\n` +\n `When using auto updates, we recommend that you run with the same versions locally as will be used when deploying.\\n\\n` +\n `${result.mismatched.map((mod) => ` - ${mod.pkg} (local version: ${mod.installed}, runtime version: ${mod.remote})`).join('\\n')}\\n\\n`\n\n if (isInteractive()) {\n const shouldUpgrade = await confirm({\n default: true,\n message: styleText('yellow', `${message}Do you want to upgrade local versions?`),\n })\n if (shouldUpgrade) {\n await upgradePackages(\n {\n packageManager: (await getPackageManagerChoice(workDir, {interactive: false})).chosen,\n packages: result.mismatched.map((res) => [res.pkg, res.remote]),\n },\n {output, workDir},\n )\n }\n } else {\n // In this case we warn the user but we don't ask them if they want to upgrade because it's not interactive.\n output.log(styleText('yellow', message))\n }\n }\n }\n\n if (cliConfig?.schemaExtraction?.enabled) {\n output.log(`${logSymbols.info} Running dev server with schema extraction enabled`)\n }\n\n const config = getDevServerConfig({cliConfig, flags, httpPort, output, workDir})\n\n if (loadInDashboard) {\n if (!projectId) {\n output.error('Project Id is required to load in dashboard', {exit: 1})\n }\n\n try {\n const project = await getProjectById(projectId!)\n organizationId = project.organizationId!\n } catch (error) {\n devDebug('Error getting organization id from project id', error)\n output.error('Failed to get organization id from project id', {exit: 1})\n }\n }\n\n try {\n const startTime = Date.now()\n const spin = spinner('Starting dev server').start()\n const {close, server} = await startDevServer(config)\n\n const {info: loggerInfo} = server.config.logger\n const {port} = server.config.server\n const httpHost = config.httpHost || 'localhost'\n\n if (loadInDashboard) {\n spin.succeed()\n\n output.log(`Dev server started on port ${port}`)\n output.log(`View your studio in the Sanity dashboard here:`)\n output.log(\n styleText(\n ['blue', 'underline'],\n await getDashboardAppURL({\n httpHost,\n httpPort: port,\n organizationId: organizationId!,\n }),\n ),\n )\n } else {\n const startupDuration = Date.now() - startTime\n const url = `http://${httpHost || 'localhost'}:${port}${config.basePath}`\n const appType = 'Sanity Studio'\n\n const viteVersion = await getLocalPackageVersion('vite', import.meta.url)\n spin.succeed()\n\n loggerInfo(\n `${appType} ` +\n `using ${styleText('cyan', `vite@${viteVersion}`)} ` +\n `ready in ${styleText('cyan', `${Math.ceil(startupDuration)}ms`)}` +\n (announceUrl ? ` and running at ${styleText('cyan', url)}` : ''),\n )\n }\n\n return {close, server, started: true}\n } catch (err) {\n devDebug('Error starting studio dev server', err)\n throw gracefulServerDeath('dev', config.httpHost, config.httpPort, err)\n }\n}\n"],"names":["styleText","checkRequiredDependencies","checkStudioDependencyVersions","compareDependencyVersions","getLocalPackageVersion","isInteractive","confirm","logSymbols","spinner","isWorkbenchApp","parse","semverParse","startDevServer","gracefulServerDeath","getProjectById","getAppId","getPackageManagerChoice","upgradePackages","shouldAutoUpdate","devDebug","getDashboardAppURL","getDevServerConfig","startStudioDevServer","options","announceUrl","cliConfig","flags","httpPort","output","workDir","projectId","api","organizationId","loadInDashboard","app","installedSanityVersion","autoUpdatesEnabled","cleanSanityVersion","version","Error","sanityDependencies","name","log","info","result","appId","err","warn","unresolvedPrerelease","length","mod","pkg","mismatched","message","map","installed","remote","join","shouldUpgrade","default","packageManager","interactive","chosen","packages","res","schemaExtraction","enabled","config","error","exit","project","startTime","Date","now","spin","start","close","server","loggerInfo","logger","port","httpHost","succeed","startupDuration","url","basePath","appType","viteVersion","Math","ceil","started"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/actions/dev/servers/startStudioDevServer.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {\n checkRequiredDependencies,\n checkStudioDependencyVersions,\n compareDependencyVersions,\n} from '@sanity/cli-build/_internal/build'\nimport {getLocalPackageVersion, isInteractive} from '@sanity/cli-core'\nimport {confirm, logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\nimport {parse as semverParse} from 'semver'\n\nimport {startDevServer} from '../../../server/devServer.js'\nimport {gracefulServerDeath} from '../../../server/gracefulServerDeath.js'\nimport {getProjectById} from '../../../services/projects.js'\nimport {getAppId} from '../../../util/appId.js'\nimport {getPackageManagerChoice} from '../../../util/packageManager/packageManagerChoice.js'\nimport {upgradePackages} from '../../../util/packageManager/upgradePackages.js'\nimport {checkDependenciesEventListenerFactory} from '../../build/eventListenerFactory.js'\nimport {shouldAutoUpdate} from '../../build/shouldAutoUpdate.js'\nimport {devDebug} from '../devDebug.js'\nimport {type DevActionOptions, type StartDevServerResult} from '../types.js'\nimport {getDashboardAppURL} from './getDashboardAppUrl.js'\nimport {getDevServerConfig} from './getDevServerConfig.js'\n\nexport async function startStudioDevServer(\n options: DevActionOptions,\n): Promise<StartDevServerResult> {\n const {announceUrl = true, cliConfig, flags, httpPort, output, workDir} = options\n const projectId = cliConfig?.api?.projectId\n let organizationId: string | undefined\n\n // Workbench apps don't load through the dashboard, so the flag has no\n // meaning for them and is ignored.\n const loadInDashboard = flags['load-in-dashboard'] && !isWorkbenchApp(cliConfig?.app)\n\n // Check studio dependency versions\n await checkStudioDependencyVersions(workDir, output)\n\n const {installedSanityVersion} = await checkRequiredDependencies({\n ...options,\n ...checkDependenciesEventListenerFactory(output),\n })\n\n // Check if auto-updates are enabled\n const autoUpdatesEnabled = shouldAutoUpdate({cliConfig, flags, output})\n\n if (autoUpdatesEnabled) {\n // Get the clean version without build metadata: https://semver.org/#spec-item-10\n const cleanSanityVersion = semverParse(installedSanityVersion)?.version\n if (!cleanSanityVersion) {\n throw new Error(`Failed to parse installed Sanity version: ${installedSanityVersion}`)\n }\n\n const sanityDependencies = [\n {name: 'sanity', version: cleanSanityVersion},\n {name: '@sanity/vision', version: cleanSanityVersion},\n ]\n\n output.log(`${logSymbols.info} Running with auto-updates enabled`)\n\n // Check local versions against deployed versions\n let result: Awaited<ReturnType<typeof compareDependencyVersions>> | undefined\n\n const appId = getAppId(cliConfig)\n\n try {\n result = await compareDependencyVersions(sanityDependencies, workDir, {appId})\n } catch (err) {\n output.warn(`Failed to compare local versions against auto-updating versions: ${err}`)\n }\n\n if (result?.unresolvedPrerelease.length) {\n for (const mod of result.unresolvedPrerelease) {\n output.warn(\n `Your local version of ${mod.pkg} (${mod.version}) is a prerelease not available on the auto-updates CDN. The locally installed version will be used.`,\n )\n }\n }\n\n // mismatch between local and auto-updating dependencies\n if (result?.mismatched.length) {\n const message =\n `The following local package versions are different from the versions currently served at runtime.\\n` +\n `When using auto updates, we recommend that you run with the same versions locally as will be used when deploying.\\n\\n` +\n `${result.mismatched.map((mod) => ` - ${mod.pkg} (local version: ${mod.installed}, runtime version: ${mod.remote})`).join('\\n')}\\n\\n`\n\n if (isInteractive()) {\n const shouldUpgrade = await confirm({\n default: true,\n message: styleText('yellow', `${message}Do you want to upgrade local versions?`),\n })\n if (shouldUpgrade) {\n await upgradePackages(\n {\n packageManager: (await getPackageManagerChoice(workDir, {interactive: false})).chosen,\n packages: result.mismatched.map((res) => [res.pkg, res.remote]),\n },\n {output, workDir},\n )\n }\n } else {\n // In this case we warn the user but we don't ask them if they want to upgrade because it's not interactive.\n output.log(styleText('yellow', message))\n }\n }\n }\n\n if (cliConfig?.schemaExtraction?.enabled) {\n output.log(`${logSymbols.info} Running dev server with schema extraction enabled`)\n }\n\n const config = getDevServerConfig({cliConfig, flags, httpPort, output, workDir})\n\n if (loadInDashboard) {\n if (!projectId) {\n output.error('Project Id is required to load in dashboard', {exit: 1})\n }\n\n try {\n const project = await getProjectById(projectId!)\n organizationId = project.organizationId!\n } catch (error) {\n devDebug('Error getting organization id from project id', error)\n output.error('Failed to get organization id from project id', {exit: 1})\n }\n }\n\n try {\n const startTime = Date.now()\n const spin = spinner('Starting dev server').start()\n const {close, server} = await startDevServer(config)\n\n const {info: loggerInfo} = server.config.logger\n const {port} = server.config.server\n const httpHost = config.httpHost || 'localhost'\n\n if (loadInDashboard) {\n spin.succeed()\n\n output.log(`Dev server started on port ${port}`)\n output.log(`View your studio in the Sanity dashboard here:`)\n output.log(\n styleText(\n ['blue', 'underline'],\n await getDashboardAppURL({\n httpHost,\n httpPort: port,\n organizationId: organizationId!,\n }),\n ),\n )\n } else {\n const startupDuration = Date.now() - startTime\n const url = `http://${httpHost || 'localhost'}:${port}${config.basePath}`\n const appType = 'Sanity Studio'\n\n const viteVersion = await getLocalPackageVersion('vite', import.meta.url)\n spin.succeed()\n\n loggerInfo(\n `${appType} ` +\n `using ${styleText('cyan', `vite@${viteVersion}`)} ` +\n `ready in ${styleText('cyan', `${Math.ceil(startupDuration)}ms`)}` +\n (announceUrl ? ` and running at ${styleText('cyan', url)}` : ''),\n )\n }\n\n return {close, server, started: true}\n } catch (err) {\n devDebug('Error starting studio dev server', err)\n throw gracefulServerDeath('dev', config.httpHost, config.httpPort, err)\n }\n}\n"],"names":["styleText","checkRequiredDependencies","checkStudioDependencyVersions","compareDependencyVersions","getLocalPackageVersion","isInteractive","confirm","logSymbols","spinner","isWorkbenchApp","parse","semverParse","startDevServer","gracefulServerDeath","getProjectById","getAppId","getPackageManagerChoice","upgradePackages","checkDependenciesEventListenerFactory","shouldAutoUpdate","devDebug","getDashboardAppURL","getDevServerConfig","startStudioDevServer","options","announceUrl","cliConfig","flags","httpPort","output","workDir","projectId","api","organizationId","loadInDashboard","app","installedSanityVersion","autoUpdatesEnabled","cleanSanityVersion","version","Error","sanityDependencies","name","log","info","result","appId","err","warn","unresolvedPrerelease","length","mod","pkg","mismatched","message","map","installed","remote","join","shouldUpgrade","default","packageManager","interactive","chosen","packages","res","schemaExtraction","enabled","config","error","exit","project","startTime","Date","now","spin","start","close","server","loggerInfo","logger","port","httpHost","succeed","startupDuration","url","basePath","appType","viteVersion","Math","ceil","started"],"mappings":"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"}