@sanity/cli 8.16.0 → 8.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -6
- package/dist/actions/build/buildApp.js +2 -2
- package/dist/actions/build/buildApp.js.map +1 -1
- package/dist/actions/deploy/deployChecks.js +44 -1
- package/dist/actions/deploy/deployChecks.js.map +1 -1
- package/dist/actions/deploy/deployStudio.js +40 -25
- package/dist/actions/deploy/deployStudio.js.map +1 -1
- package/dist/actions/dev/servers/getDevServerConfig.js +2 -2
- package/dist/actions/dev/servers/getDevServerConfig.js.map +1 -1
- package/dist/commands/deploy.js +6 -3
- package/dist/commands/deploy.js.map +1 -1
- package/dist/exports/runtime.d.ts +2 -2
- package/dist/exports/runtime.js.map +1 -1
- package/oclif.manifest.json +157 -154
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -140,6 +140,7 @@ Code for sanity cli
|
|
|
140
140
|
- [`sanity users list`](#sanity-users-list)
|
|
141
141
|
- [`sanity versions`](#sanity-versions)
|
|
142
142
|
- [`sanity workflows abort INSTANCEID`](#sanity-workflows-abort-instanceid)
|
|
143
|
+
- [`sanity workflows blueprint generate`](#sanity-workflows-blueprint-generate)
|
|
143
144
|
- [`sanity workflows definition delete NAME`](#sanity-workflows-definition-delete-name)
|
|
144
145
|
- [`sanity workflows definition diff NAME`](#sanity-workflows-definition-diff-name)
|
|
145
146
|
- [`sanity workflows definition list`](#sanity-workflows-definition-list)
|
|
@@ -2027,7 +2028,7 @@ FLAGS
|
|
|
2027
2028
|
--source-maps Enable source maps for built bundles (increases size of bundle)
|
|
2028
2029
|
--title=<value> Title for a newly created application or studio. For apps, use --create to select creation
|
|
2029
2030
|
when the organization already has apps
|
|
2030
|
-
--url=<value> Studio URL for deployment. For external
|
|
2031
|
+
--url=<value> Studio URL for deployment. For external deploys, the full URL. For hosted studios, the
|
|
2031
2032
|
hostname (e.g. "my-studio" or "my-studio.sanity.studio")
|
|
2032
2033
|
--verbose Enable verbose logging
|
|
2033
2034
|
|
|
@@ -2051,6 +2052,10 @@ EXAMPLES
|
|
|
2051
2052
|
|
|
2052
2053
|
$ sanity deploy --external
|
|
2053
2054
|
|
|
2055
|
+
Register an externally hosted studio, served from the provided origin
|
|
2056
|
+
|
|
2057
|
+
$ sanity deploy --external --url https://apps.example.com
|
|
2058
|
+
|
|
2054
2059
|
Create and deploy an App SDK app without prompts. Save application.id as deployment.appId, then omit --create on
|
|
2055
2060
|
later deploys
|
|
2056
2061
|
|
|
@@ -4269,6 +4274,8 @@ DESCRIPTION
|
|
|
4269
4274
|
Note:
|
|
4270
4275
|
- The `sanity schema extract` command is a prerequisite for extracting your Sanity Studio schema into a `schema.json`
|
|
4271
4276
|
file, which is then used by the `sanity typegen generate` command to generate type definitions.
|
|
4277
|
+
- To generate types for several datasets, list them in `typegen.resources` in `sanity.cli.ts` (beta). Each resource
|
|
4278
|
+
uses its own `schema` file, or the schema bound to its dataset when `schema` is omitted.
|
|
4272
4279
|
|
|
4273
4280
|
EXAMPLES
|
|
4274
4281
|
Generate TypeScript type definitions from a Sanity Studio schema extracted using the `sanity schema extract`
|
|
@@ -4435,6 +4442,30 @@ EXAMPLES
|
|
|
4435
4442
|
$ sanity workflows abort wf-instance.abc123 --reason 'superseded by relaunch'
|
|
4436
4443
|
```
|
|
4437
4444
|
|
|
4445
|
+
## `sanity workflows blueprint generate`
|
|
4446
|
+
|
|
4447
|
+
Experimental: generate the Sanity Blueprints runtime the definitions require, next to sanity.workflow.ts. Writes the workflow resources, one function per derived need, the effect-handler registry, and a handler stub per declared effect. Covers every deployment in the config, because the emitted resources module declares them all. These flags and this output may change before the Blueprints backend accepts the sanity.workflow resource.
|
|
4448
|
+
|
|
4449
|
+
```
|
|
4450
|
+
USAGE
|
|
4451
|
+
$ sanity workflows blueprint generate [--check]
|
|
4452
|
+
|
|
4453
|
+
FLAGS
|
|
4454
|
+
--check Experimental: verify the tree on disk still matches the definitions; write nothing and exit non-zero on any
|
|
4455
|
+
difference. The CI drift gate.
|
|
4456
|
+
|
|
4457
|
+
DESCRIPTION
|
|
4458
|
+
Experimental: generate the Sanity Blueprints runtime the definitions require, next to sanity.workflow.ts. Writes the
|
|
4459
|
+
workflow resources, one function per derived need, the effect-handler registry, and a handler stub per declared
|
|
4460
|
+
effect. Covers every deployment in the config, because the emitted resources module declares them all. These flags and
|
|
4461
|
+
this output may change before the Blueprints backend accepts the sanity.workflow resource.
|
|
4462
|
+
|
|
4463
|
+
EXAMPLES
|
|
4464
|
+
$ sanity workflows blueprint generate
|
|
4465
|
+
|
|
4466
|
+
$ sanity workflows blueprint generate --check
|
|
4467
|
+
```
|
|
4468
|
+
|
|
4438
4469
|
## `sanity workflows definition delete NAME`
|
|
4439
4470
|
|
|
4440
4471
|
Delete a deployed workflow definition (every version, or one via --version). Refuses while non-terminal instances exist unless --cascade aborts them first — instances are aborted in place, never deleted.
|
|
@@ -4542,7 +4573,7 @@ DESCRIPTION
|
|
|
4542
4573
|
|
|
4543
4574
|
## `sanity workflows deploy`
|
|
4544
4575
|
|
|
4545
|
-
Validate,
|
|
4576
|
+
Validate workflow definitions, check any generated runtime beside the config against them, then diff and deploy to the resource bound by the selected deployment. A generated runtime that no longer matches the definitions fails the deploy before anything is written; regenerate it with `sanity-workflows blueprint generate`.
|
|
4546
4577
|
|
|
4547
4578
|
```
|
|
4548
4579
|
USAGE
|
|
@@ -4551,11 +4582,13 @@ USAGE
|
|
|
4551
4582
|
|
|
4552
4583
|
FLAGS
|
|
4553
4584
|
--all-tags Deploy every deployment in the config, not just a selection.
|
|
4554
|
-
--check Validate definitions
|
|
4585
|
+
--check Validate definitions and check any generated runtime against them; do not contact the dataset.
|
|
4555
4586
|
--deployment=<value> Deployment name — the unique identity of one deployment in the config.
|
|
4556
|
-
--dry-run Validate
|
|
4587
|
+
--dry-run Validate definitions, check any generated runtime against them, and diff against the deployed
|
|
4588
|
+
version; do not write.
|
|
4557
4589
|
--only=<value> Limit deploy/check/diff to a single workflow definition by name (deployments are selected with
|
|
4558
|
-
--deployment). Every targeted deployment must contain it.
|
|
4590
|
+
--deployment). Every targeted deployment must contain it. The generated-runtime check still
|
|
4591
|
+
covers the whole config, because the generated tree declares every deployment in it.
|
|
4559
4592
|
--[no-]share-defs Share the definition documents newly created by this deploy with Sanity — the full document,
|
|
4560
4593
|
verbatim (structure, names, filters, effect configuration, seeded values), plus its deployment
|
|
4561
4594
|
coordinates (project and dataset, or resource id); never content documents, instances, or your
|
|
@@ -4565,7 +4598,9 @@ FLAGS
|
|
|
4565
4598
|
an environment group).
|
|
4566
4599
|
|
|
4567
4600
|
DESCRIPTION
|
|
4568
|
-
Validate
|
|
4601
|
+
Validate workflow definitions, check any generated runtime beside the config against them, then diff and deploy to the
|
|
4602
|
+
resource bound by the selected deployment. A generated runtime that no longer matches the definitions fails the deploy
|
|
4603
|
+
before anything is written; regenerate it with `sanity-workflows blueprint generate`.
|
|
4569
4604
|
|
|
4570
4605
|
EXAMPLES
|
|
4571
4606
|
$ sanity workflows deploy --deployment review-prod
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { compareDependencyVersions, buildApp as internalBuildApp } from '@sanity/cli-build/_internal/build';
|
|
2
|
-
import { buildAppId, resolveWorkbenchApp, resolveWorkbenchConfig } from '@sanity/workbench-cli/build';
|
|
2
|
+
import { buildAppId, resolveAppEntry, resolveWorkbenchApp, resolveWorkbenchConfig } 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';
|
|
@@ -46,7 +46,7 @@ import { preReleaseEventListenerFactory } from './eventListenerFactory.js';
|
|
|
46
46
|
appId
|
|
47
47
|
}),
|
|
48
48
|
determineBasePath: ()=>determineBasePath(cliConfig, 'app', output),
|
|
49
|
-
entry: app
|
|
49
|
+
entry: resolveAppEntry(app),
|
|
50
50
|
exposes,
|
|
51
51
|
isWorkbenchApp: isWorkbench,
|
|
52
52
|
minify: flags.minify,
|
|
@@ -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
|
|
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 {\n buildAppId,\n resolveAppEntry,\n resolveWorkbenchApp,\n resolveWorkbenchConfig,\n} 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`/`webWorkers` live on the branded `defineApplication` result, not the\n // legacy `app` config object — resolve the workbench capability to read them. A\n // config is not an app: it resolves separately and only expands its `fields`.\n const workbench = resolveWorkbenchApp(cliConfig)\n const workbenchConfig = resolveWorkbenchConfig(cliConfig)\n const exposes = workbench\n ? {views: workbench.views, webWorkers: workbench.webWorkers}\n : workbenchConfig\n ? {config: {appType: workbenchConfig.appType, fields: workbenchConfig.fields}}\n : undefined\n const isWorkbench = !!workbench || !!workbenchConfig\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: resolveAppEntry(app),\n exposes,\n isWorkbenchApp: isWorkbench,\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","resolveAppEntry","resolveWorkbenchApp","resolveWorkbenchConfig","getAppId","warnAboutMissingAppId","determineBasePath","preReleaseEventListenerFactory","options","cliConfig","flags","outDir","output","workDir","app","undefined","workbench","workbenchConfig","exposes","views","webWorkers","config","appType","fields","isWorkbench","appId","appTitle","title","autoUpdatesEnabled","checkAppId","calledFromDeploy","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,SACEC,UAAU,EACVC,eAAe,EACfC,mBAAmB,EACnBC,sBAAsB,QACjB,8BAA6B;AAEpC,SAAQC,QAAQ,QAAO,sBAAqB;AAC5C,SAAQC,qBAAqB,QAAO,sCAAqC;AACzE,SAAQC,iBAAiB,QAAO,yBAAwB;AACxD,SAAQC,8BAA8B,QAAO,4BAA2B;AAGxE;;;;CAIC,GACD,OAAO,eAAeT,SAASU,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,+EAA+E;IAC/E,gFAAgF;IAChF,8EAA8E;IAC9E,MAAMC,YAAYd,oBAAoBO;IACtC,MAAMQ,kBAAkBd,uBAAuBM;IAC/C,MAAMS,UAAUF,YACZ;QAACG,OAAOH,UAAUG,KAAK;QAAEC,YAAYJ,UAAUI,UAAU;IAAA,IACzDH,kBACE;QAACI,QAAQ;YAACC,SAASL,gBAAgBK,OAAO;YAAEC,QAAQN,gBAAgBM,MAAM;QAAA;IAAC,IAC3ER;IACN,MAAMS,cAAc,CAAC,CAACR,aAAa,CAAC,CAACC;IAErC,MAAMQ,QAAQrB,SAASK;IAEvB,MAAMV,iBAAiB;QACrB0B;QACAC,UAAUZ,KAAKa;QACfC,oBAAoBpB,QAAQoB,kBAAkB;QAC9CC,YAAY;YACV,wDAAwD;YACxD,kEAAkE;YAClE,yDAAyD;YACzD,IAAI,CAACJ,SAAS,CAACjB,QAAQsB,gBAAgB,EAAE;gBACvCzB,sBAAsB;oBAACiB,SAAS;oBAAOV;gBAAM;YAC/C;QACF;QACAf,2BAA2B,CAACkC,WAAalC,0BAA0BkC,UAAUlB,SAAS;gBAACY;YAAK;QAC5FnB,mBAAmB,IAAMA,kBAAkBG,WAAW,OAAOG;QAC7DoB,OAAO/B,gBAAgBa;QACvBI;QACAe,gBAAgBT;QAChBU,QAAQxB,MAAMwB,MAAM;QACpBvB;QACAC;QACAuB,eAAe1B,aAAa,mBAAmBA,YAAYA,UAAU0B,aAAa,GAAGpB;QACrFqB,kBAAkB3B,WAAW2B;QAC7BC,WAAWC,QAAQ5B,KAAK,CAAC,cAAc;QACvC6B,OAAO7B,MAAM6B,KAAK;QAClBC,gBAAgB9B,MAAM+B,GAAG;QACzBC,MAAMjC,UAAUiC,IAAI;QACpB,2EAA2E;QAC3E,oFAAoF;QACpFC,gBAAgB3B,YACXR,QAAQoC,aAAa,IAAK,MAAM5C,WAAWgB,aAC5CD;QACJF;QAEAgC,eAAetC,+BAA+BK;IAChD;AACF"}
|
|
@@ -10,6 +10,7 @@ import { getAutoUpdateIssueMessage, getAutoUpdateMigrationHint, resolveAutoUpdat
|
|
|
10
10
|
import { checkDir } from './checkDir.js';
|
|
11
11
|
import { deployDebug } from './deployDebug.js';
|
|
12
12
|
import { resolveAppDeployTarget, resolveStudioDeployTarget, resolveWorkbenchApp, resolveWorkbenchStudio } from './resolveDeployTarget.js';
|
|
13
|
+
import { normalizeUrl, validateUrl } from './urlUtils.js';
|
|
13
14
|
export async function checkPackageVersion(reporter, { moduleName, workDir }) {
|
|
14
15
|
const version = await getLocalPackageVersion(moduleName, workDir);
|
|
15
16
|
reporter.report(version ? {
|
|
@@ -64,6 +65,48 @@ export function checkAutoUpdates(reporter, { cliConfig, flags }) {
|
|
|
64
65
|
});
|
|
65
66
|
}
|
|
66
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* The origin a federated studio deployed with --external is registered
|
|
70
|
+
* at. Only a first deploy registers one; a redeploy keeps the URL it has.
|
|
71
|
+
*/ export function checkExternalUrl(reporter, { appId, url }) {
|
|
72
|
+
if (appId) return undefined;
|
|
73
|
+
if (!url) {
|
|
74
|
+
reporter.report({
|
|
75
|
+
exitCode: exitCodes.USAGE_ERROR,
|
|
76
|
+
message: 'A first external deploy needs the URL your host serves the build from',
|
|
77
|
+
solution: 'Pass it with --url, for example --url https://studio.example.com',
|
|
78
|
+
status: 'fail'
|
|
79
|
+
});
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
const normalized = normalizeUrl(url);
|
|
83
|
+
const validation = validateUrl(normalized);
|
|
84
|
+
if (validation !== true) {
|
|
85
|
+
reporter.report({
|
|
86
|
+
exitCode: exitCodes.USAGE_ERROR,
|
|
87
|
+
message: validation,
|
|
88
|
+
solution: 'Pass --url with an http or https URL, for example --url https://studio.example.com',
|
|
89
|
+
status: 'fail'
|
|
90
|
+
});
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
// The Dashboard loads the remote from the origin root, so a path would never be fetched.
|
|
94
|
+
const { hash, origin, pathname, search } = new URL(normalized);
|
|
95
|
+
if (pathname !== '/' || search || hash) {
|
|
96
|
+
reporter.report({
|
|
97
|
+
exitCode: exitCodes.USAGE_ERROR,
|
|
98
|
+
message: '--url must be an origin with no path, query or hash',
|
|
99
|
+
solution: 'Pass the origin your host serves the build from, for example --url https://studio.example.com',
|
|
100
|
+
status: 'fail'
|
|
101
|
+
});
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
reporter.report({
|
|
105
|
+
message: `Registers at ${origin}`,
|
|
106
|
+
status: 'pass'
|
|
107
|
+
});
|
|
108
|
+
return origin;
|
|
109
|
+
}
|
|
67
110
|
export async function checkBuild(reporter, { build, skipReason, successMessage }) {
|
|
68
111
|
if (skipReason) {
|
|
69
112
|
reporter.report({
|
|
@@ -343,7 +386,7 @@ export function describeAppTargetError(err, organizationId) {
|
|
|
343
386
|
*/ export async function checkStudioTarget(reporter, options) {
|
|
344
387
|
const { title } = options;
|
|
345
388
|
const resolve = options.isWorkbenchApp ? resolveWorkbenchStudio(options) : resolveStudioDeployTarget(options);
|
|
346
|
-
//
|
|
389
|
+
// A workbench studio's target is its slug, even when its build is hosted externally.
|
|
347
390
|
const isExternal = options.isWorkbenchApp ? false : options.isExternal;
|
|
348
391
|
return runStep(reporter, {
|
|
349
392
|
debug: deployDebug,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/deployChecks.ts"],"sourcesContent":["import {type CliConfig, exitCodes, getLocalPackageVersion} 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 {checkBuiltOutput} from '@sanity/workbench-cli/deploy'\n\nimport {resolveAppIdIssue} from '../../util/appId.js'\nimport {type Check, type CheckReporter, runStep} from '../../util/checks.js'\nimport {APP_ID_NOT_FOUND_IN_ORGANIZATION} from '../../util/errorMessages.js'\nimport {\n getAutoUpdateIssueMessage,\n getAutoUpdateMigrationHint,\n resolveAutoUpdates,\n} from '../build/shouldAutoUpdate.js'\nimport {checkDir} from './checkDir.js'\nimport {deployDebug} from './deployDebug.js'\nimport {\n type AppDeployTargetResolution,\n type DeployTargetApp,\n resolveAppDeployTarget,\n resolveStudioDeployTarget,\n resolveWorkbenchApp,\n resolveWorkbenchStudio,\n type StudioDeployTargetResolution,\n} from './resolveDeployTarget.js'\nimport {type DeployFlags} from './types.js'\n\n/**\n * Where a deploy resolves to, computed once from the deploy-target verdict. The\n * dry-run report and its JSON both read this, so the human and machine outputs\n * can't drift.\n */\nexport interface DeployTarget {\n /** Whether the deploy creates a new application/studio or updates an existing one. */\n action: 'create' | 'update'\n /** `null` until the deploy creates the application. */\n id: string | null\n title: string | null\n type: 'coreApp' | 'studio'\n url: string | null\n\n /** Absent on a plain app, whose backend reports `appHost` instead. */\n slug?: string\n}\n\nexport interface DeployCheck extends Check {\n /** The backend's record, verbatim; `--json` reports it once the deploy succeeds. */\n application?: object\n /** Set on the deploy-target check with the resolved target both reporters read. */\n target?: DeployTarget\n}\n\nexport type DeployCheckReporter = CheckReporter<DeployCheck>\n\nexport async function checkPackageVersion(\n reporter: DeployCheckReporter,\n {moduleName, workDir}: {moduleName: string; workDir: string},\n): Promise<string | null> {\n const version = await getLocalPackageVersion(moduleName, workDir)\n reporter.report(\n version\n ? {message: `Using ${moduleName} ${version}`, status: 'pass'}\n : {\n message: `Failed to find installed ${moduleName} version`,\n solution: `Install ${moduleName} in this project`,\n status: 'fail',\n },\n )\n return version\n}\n\nexport function checkAutoUpdates(\n reporter: DeployCheckReporter,\n {cliConfig, flags}: {cliConfig: CliConfig; flags: DeployFlags},\n): boolean {\n const {enabled, issue} = resolveAutoUpdates({cliConfig, flags})\n\n if (issue) {\n reporter.report({\n message: getAutoUpdateIssueMessage(issue),\n // A config conflict makes a real deploy refuse to run; deprecations only warn\n status: issue.type === 'conflicting-config' ? 'fail' : 'warn',\n })\n\n // The deprecated top-level config also gets the styled migration edit, the\n // same second warning the build/dev path prints through shouldAutoUpdate.\n if (issue.type === 'deprecated-config') {\n reporter.report({\n message: getAutoUpdateMigrationHint(cliConfig.autoUpdates),\n status: 'warn',\n })\n }\n }\n\n return enabled\n}\n\n/**\n * The dry-run form of the `app.id` config check a real deploy runs in\n * `findUserApplication`: a conflict fails (both `app.id` and `deployment.appId`\n * set), the deprecated config alone warns.\n */\nexport function checkAppId(\n reporter: DeployCheckReporter,\n {cliConfig}: {cliConfig: CliConfig},\n): void {\n const issue = resolveAppIdIssue(cliConfig)\n if (issue === 'conflicting-config') {\n reporter.report({\n message: 'Both `app.id` (deprecated) and `deployment.appId` are set',\n solution: 'Remove `app.id` from sanity.cli.ts',\n status: 'fail',\n })\n } else if (issue === 'deprecated-config') {\n reporter.report({\n message: 'The `app.id` config is deprecated',\n solution: 'Move it to `deployment.appId` in sanity.cli.ts',\n status: 'warn',\n })\n }\n}\n\nexport async function checkBuild(\n reporter: DeployCheckReporter,\n {\n build,\n skipReason,\n successMessage,\n }: {build: () => Promise<void>; skipReason: string | undefined; successMessage: string},\n): Promise<void> {\n if (skipReason) {\n reporter.report({message: skipReason, status: 'skip'})\n return\n }\n\n await runStep(reporter, {\n debug: deployDebug,\n formatError: (err) => `Build failed: ${getErrorMessage(err)}`,\n name: 'build',\n solution: 'Fix the build error above, then retry',\n work: async () => {\n await build()\n reporter.report({message: successMessage, status: 'pass'})\n },\n })\n}\n\n/**\n * The deploy directory must exist and hold the right build output: a federation\n * remote for a workbench app, an `index.html` SPA otherwise.\n */\nexport async function verifyOutputDir({\n isWorkbenchApp,\n reporter,\n sourceDir,\n}: {\n isWorkbenchApp: boolean\n reporter: DeployCheckReporter\n sourceDir: string\n}): Promise<void> {\n const spin = spinner('Verifying local content...').start()\n const verifyBuild = isWorkbenchApp ? checkBuiltOutput : checkDir\n try {\n await verifyBuild(sourceDir)\n spin.succeed()\n } catch (err) {\n spin.fail()\n deployDebug('Error checking directory', err)\n reporter.report({\n message: getErrorMessage(err),\n solution: 'Run the build first, or check the output directory',\n status: 'fail',\n })\n }\n}\n\n/**\n * The single diagnosis for each app deploy-target verdict, shared by the\n * dry-run report and the real deploy's unattended error paths so message,\n * fix, and exit code can't drift between the two.\n */\nexport function describeAppTarget(\n resolution: AppDeployTargetResolution,\n {title}: {title?: string} = {},\n): DeployCheck {\n switch (resolution.type) {\n case 'blocked': {\n return {message: `Deploy target not resolved — ${resolution.message}`, status: 'skip'}\n }\n case 'found': {\n const {application} = resolution\n const title = application.title ?? application.appHost\n const url = application.url ?? getCoreAppUrl(application.organizationId, application.id)\n return {\n application,\n message: `Deploys to existing application \"${title}\" at ${url}`,\n status: 'pass',\n target: {\n action: 'update',\n id: application.id,\n title: application.title,\n type: 'coreApp',\n url,\n },\n }\n }\n case 'invalid': {\n return {\n message: APP_ID_NOT_FOUND_IN_ORGANIZATION,\n solution: 'Check `deployment.appId` matches an app in your organization',\n status: 'fail',\n }\n }\n case 'needs-input': {\n return {\n exitCode: exitCodes.USAGE_ERROR,\n message: `No \\`deployment.appId\\` configured (${resolution.existing.length} existing ${resolution.existing.length === 1 ? 'application' : 'applications'} to choose from)`,\n solution:\n 'Set `deployment.appId` in sanity.cli.ts to deploy to an existing app, or run `sanity deploy --create --title \"<name>\" --yes` to create a new one',\n status: 'fail',\n }\n }\n case 'slug-taken': {\n return describeSlugTaken(resolution)\n }\n // Without --title, creating an app needs a prompt no unattended run can answer\n case 'would-create': {\n const {appHost} = resolution\n if (title) {\n return {\n message: `Would create a new application \"${title}\"${appHost ? ` with slug \"${appHost}\"` : ''}`,\n status: 'pass',\n target: {\n action: 'create',\n id: null,\n ...(appHost ? {slug: appHost} : {}),\n title,\n type: 'coreApp',\n url: null,\n },\n }\n }\n return {\n exitCode: exitCodes.USAGE_ERROR,\n message: 'No application to deploy to — creating one needs a title',\n solution:\n 'Pass `--title \"<name>\"` or set `app.title` in sanity.cli.ts to create one, or set `deployment.appId` to deploy to an existing app',\n status: 'fail',\n }\n }\n }\n}\n\n/** One diagnosis for both the app and studio verdicts: they share a slug namespace. */\nfunction describeSlugTaken({\n appHost,\n existing,\n}: {\n appHost: string\n existing: DeployTargetApp\n}): DeployCheck {\n return {\n application: existing,\n exitCode: exitCodes.USAGE_ERROR,\n message: `An application already exists at slug \"${appHost}\" in this organization (app ID ${existing.id})`,\n solution: `Add \\`deployment: {appId: '${existing.id}'}\\` to sanity.cli.ts to redeploy it`,\n status: 'fail',\n target: {\n action: 'update',\n id: existing.id,\n title: existing.title,\n type: existing.type,\n url: existing.url ?? null,\n },\n }\n}\n\nexport function describeAppTargetError(err: unknown, organizationId: string | undefined): string {\n return (err as {statusCode?: number})?.statusCode === 403\n ? `You don’t have permission to view applications for the configured organization ID (\"${organizationId}\"). Verify the organization ID, or ask your organization’s admin for access.`\n : `Failed to resolve deploy target: ${getErrorMessage(err)}`\n}\n\n/**\n * Reports the app deploy target as a check and returns the resolved target;\n * `isWorkbenchApp` selects the backend. Both modes run it — a real deploy uses\n * it to reject a bad `appId` before building.\n */\nexport async function checkAppTarget(\n reporter: DeployCheckReporter,\n options:\n | {\n appId: string | undefined\n create?: boolean\n isWorkbenchApp?: false\n organizationId: string | undefined\n title?: string\n }\n | {\n appId: string | undefined\n isWorkbenchApp: true\n organizationId?: string\n slug?: string\n title?: string\n },\n): Promise<DeployCheck | null> {\n const {title} = options\n if (options.isWorkbenchApp) {\n const {appId, organizationId, slug} = options\n return runStep(reporter, {\n debug: deployDebug,\n name: 'target',\n work: async () => {\n const resolution = await resolveWorkbenchApp({appId, organizationId, slug})\n const check = describeAppTarget(resolution, {title})\n reporter.report(check)\n return check\n },\n })\n }\n\n const {appId, create, organizationId} = options\n return runStep(reporter, {\n debug: deployDebug,\n formatError: (err) => describeAppTargetError(err, organizationId),\n name: 'target',\n work: async () => {\n const check = describeAppTarget(\n await resolveAppDeployTarget({appId, create, organizationId}),\n {\n title,\n },\n )\n reporter.report(check)\n return check\n },\n })\n}\n\n/** Same contract as {@link describeAppTarget}, for the studio verdicts. */\nexport function describeStudioTarget(\n resolution: StudioDeployTargetResolution,\n {isExternal, isWorkbench, title}: {isExternal: boolean; isWorkbench?: boolean; title?: string},\n): DeployCheck {\n const studioUrl = (host: string) => (isExternal ? host : `https://${host}.sanity.studio`)\n\n switch (resolution.type) {\n case 'blocked': {\n return {message: `Deploy target not resolved — ${resolution.message}`, status: 'skip'}\n }\n case 'found': {\n const {appHost} = resolution.application\n const url = resolution.application.url ?? (appHost ? studioUrl(appHost) : null)\n return {\n application: resolution.application,\n message: `Deploys to existing studio ${url}`,\n status: 'pass',\n target: {\n action: 'update',\n id: resolution.application.id,\n title: resolution.application.title,\n type: 'studio',\n url,\n },\n }\n }\n case 'invalid': {\n return {\n // A bad host is a usage error; other invalid targets exit 1\n exitCode: resolution.reason === 'invalid-host' ? exitCodes.USAGE_ERROR : 1,\n message: resolution.message,\n solution: 'Check `studioHost` and `deployment.appId` in sanity.cli.ts',\n status: 'fail',\n }\n }\n case 'needs-input': {\n return {\n exitCode: exitCodes.USAGE_ERROR,\n message: isExternal ? 'No external studio URL configured' : 'No studio hostname configured',\n solution: isExternal\n ? 'Set `studioHost` in sanity.cli.ts, or pass the full URL with --url'\n : 'Set `studioHost` in sanity.cli.ts, or pass a hostname with --url',\n status: 'fail',\n }\n }\n case 'slug-taken': {\n return describeSlugTaken(resolution)\n }\n case 'would-create': {\n const appHost = resolution.appHost\n const url = isWorkbench ? null : studioUrl(appHost)\n const result = {\n status: 'pass',\n target: {action: 'create', id: null, title: title || null, type: 'studio', url},\n } as const\n const titled = title ? ` titled \"${title}\"` : ''\n\n if (isExternal) {\n return {\n message: `Would register external studio at ${appHost}${titled}`,\n ...result,\n }\n }\n\n if (isWorkbench) {\n return {\n message: `Would create a new studio${title ? ` \"${title}\"` : ''} with slug \"${appHost}\" (name availability is checked on deploy)`,\n ...result,\n target: {...result.target, slug: appHost},\n }\n }\n\n return {\n message: `Would create studio hostname ${url}${titled} (name availability is checked on deploy)`,\n ...result,\n }\n }\n }\n}\n\n/**\n * Reports the studio deploy target as a check and returns the resolved target;\n * `isWorkbenchApp` selects the backend. Both modes run it — a real deploy uses\n * it to reject a bad `appId` before building.\n */\nexport async function checkStudioTarget(\n reporter: DeployCheckReporter,\n options:\n | {\n appId: string | undefined\n isExternal: boolean\n isWorkbenchApp?: false\n projectId: string | undefined\n studioHost: string | undefined\n title: string | undefined\n urlFlag: string | undefined\n }\n | {\n appId: string | undefined\n isWorkbenchApp: true\n organizationId?: string\n slug: string\n title?: string\n },\n): Promise<DeployCheck | null> {\n const {title} = options\n const resolve = options.isWorkbenchApp\n ? resolveWorkbenchStudio(options)\n : resolveStudioDeployTarget(options)\n // Workbench studios always deploy to Sanity hosting, never an external URL.\n const isExternal = options.isWorkbenchApp ? false : options.isExternal\n\n return runStep(reporter, {\n debug: deployDebug,\n formatError: (err) => `Failed to resolve deploy target: ${getErrorMessage(err)}`,\n name: 'target',\n work: async () => {\n const check = describeStudioTarget(await resolve, {\n isExternal,\n isWorkbench: !!options.isWorkbenchApp,\n title,\n })\n reporter.report(check)\n return check\n },\n })\n}\n"],"names":["exitCodes","getLocalPackageVersion","getErrorMessage","getCoreAppUrl","spinner","checkBuiltOutput","resolveAppIdIssue","runStep","APP_ID_NOT_FOUND_IN_ORGANIZATION","getAutoUpdateIssueMessage","getAutoUpdateMigrationHint","resolveAutoUpdates","checkDir","deployDebug","resolveAppDeployTarget","resolveStudioDeployTarget","resolveWorkbenchApp","resolveWorkbenchStudio","checkPackageVersion","reporter","moduleName","workDir","version","report","message","status","solution","checkAutoUpdates","cliConfig","flags","enabled","issue","type","autoUpdates","checkAppId","checkBuild","build","skipReason","successMessage","debug","formatError","err","name","work","verifyOutputDir","isWorkbenchApp","sourceDir","spin","start","verifyBuild","succeed","fail","describeAppTarget","resolution","title","application","appHost","url","organizationId","id","target","action","exitCode","USAGE_ERROR","existing","length","describeSlugTaken","slug","describeAppTargetError","statusCode","checkAppTarget","options","appId","check","create","describeStudioTarget","isExternal","isWorkbench","studioUrl","host","reason","result","titled","checkStudioTarget","resolve"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/deploy/deployChecks.ts"],"sourcesContent":["import {type CliConfig, exitCodes, getLocalPackageVersion} 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 {checkBuiltOutput} from '@sanity/workbench-cli/deploy'\n\nimport {resolveAppIdIssue} from '../../util/appId.js'\nimport {type Check, type CheckReporter, runStep} from '../../util/checks.js'\nimport {APP_ID_NOT_FOUND_IN_ORGANIZATION} from '../../util/errorMessages.js'\nimport {\n getAutoUpdateIssueMessage,\n getAutoUpdateMigrationHint,\n resolveAutoUpdates,\n} from '../build/shouldAutoUpdate.js'\nimport {checkDir} from './checkDir.js'\nimport {deployDebug} from './deployDebug.js'\nimport {\n type AppDeployTargetResolution,\n type DeployTargetApp,\n resolveAppDeployTarget,\n resolveStudioDeployTarget,\n resolveWorkbenchApp,\n resolveWorkbenchStudio,\n type StudioDeployTargetResolution,\n} from './resolveDeployTarget.js'\nimport {type DeployFlags} from './types.js'\nimport {normalizeUrl, validateUrl} from './urlUtils.js'\n\n/**\n * Where a deploy resolves to, computed once from the deploy-target verdict. The\n * dry-run report and its JSON both read this, so the human and machine outputs\n * can't drift.\n */\nexport interface DeployTarget {\n /** Whether the deploy creates a new application/studio or updates an existing one. */\n action: 'create' | 'update'\n /** `null` until the deploy creates the application. */\n id: string | null\n title: string | null\n type: 'coreApp' | 'studio'\n url: string | null\n\n /** Absent on a plain app, whose backend reports `appHost` instead. */\n slug?: string\n}\n\nexport interface DeployCheck extends Check {\n /** The backend's record, verbatim; `--json` reports it once the deploy succeeds. */\n application?: object\n /** Set on the deploy-target check with the resolved target both reporters read. */\n target?: DeployTarget\n}\n\nexport type DeployCheckReporter = CheckReporter<DeployCheck>\n\nexport async function checkPackageVersion(\n reporter: DeployCheckReporter,\n {moduleName, workDir}: {moduleName: string; workDir: string},\n): Promise<string | null> {\n const version = await getLocalPackageVersion(moduleName, workDir)\n reporter.report(\n version\n ? {message: `Using ${moduleName} ${version}`, status: 'pass'}\n : {\n message: `Failed to find installed ${moduleName} version`,\n solution: `Install ${moduleName} in this project`,\n status: 'fail',\n },\n )\n return version\n}\n\nexport function checkAutoUpdates(\n reporter: DeployCheckReporter,\n {cliConfig, flags}: {cliConfig: CliConfig; flags: DeployFlags},\n): boolean {\n const {enabled, issue} = resolveAutoUpdates({cliConfig, flags})\n\n if (issue) {\n reporter.report({\n message: getAutoUpdateIssueMessage(issue),\n // A config conflict makes a real deploy refuse to run; deprecations only warn\n status: issue.type === 'conflicting-config' ? 'fail' : 'warn',\n })\n\n // The deprecated top-level config also gets the styled migration edit, the\n // same second warning the build/dev path prints through shouldAutoUpdate.\n if (issue.type === 'deprecated-config') {\n reporter.report({\n message: getAutoUpdateMigrationHint(cliConfig.autoUpdates),\n status: 'warn',\n })\n }\n }\n\n return enabled\n}\n\n/**\n * The dry-run form of the `app.id` config check a real deploy runs in\n * `findUserApplication`: a conflict fails (both `app.id` and `deployment.appId`\n * set), the deprecated config alone warns.\n */\nexport function checkAppId(\n reporter: DeployCheckReporter,\n {cliConfig}: {cliConfig: CliConfig},\n): void {\n const issue = resolveAppIdIssue(cliConfig)\n if (issue === 'conflicting-config') {\n reporter.report({\n message: 'Both `app.id` (deprecated) and `deployment.appId` are set',\n solution: 'Remove `app.id` from sanity.cli.ts',\n status: 'fail',\n })\n } else if (issue === 'deprecated-config') {\n reporter.report({\n message: 'The `app.id` config is deprecated',\n solution: 'Move it to `deployment.appId` in sanity.cli.ts',\n status: 'warn',\n })\n }\n}\n\n/**\n * The origin a federated studio deployed with --external is registered\n * at. Only a first deploy registers one; a redeploy keeps the URL it has.\n */\nexport function checkExternalUrl(\n reporter: DeployCheckReporter,\n {appId, url}: {appId: string | undefined; url: string | undefined},\n): string | undefined {\n if (appId) return undefined\n\n if (!url) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'A first external deploy needs the URL your host serves the build from',\n solution: 'Pass it with --url, for example --url https://studio.example.com',\n status: 'fail',\n })\n return undefined\n }\n\n const normalized = normalizeUrl(url)\n const validation = validateUrl(normalized)\n if (validation !== true) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: validation,\n solution:\n 'Pass --url with an http or https URL, for example --url https://studio.example.com',\n status: 'fail',\n })\n return undefined\n }\n\n // The Dashboard loads the remote from the origin root, so a path would never be fetched.\n const {hash, origin, pathname, search} = new URL(normalized)\n if (pathname !== '/' || search || hash) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: '--url must be an origin with no path, query or hash',\n solution:\n 'Pass the origin your host serves the build from, for example --url https://studio.example.com',\n status: 'fail',\n })\n return undefined\n }\n\n reporter.report({message: `Registers at ${origin}`, status: 'pass'})\n return origin\n}\n\nexport async function checkBuild(\n reporter: DeployCheckReporter,\n {\n build,\n skipReason,\n successMessage,\n }: {build: () => Promise<void>; skipReason: string | undefined; successMessage: string},\n): Promise<void> {\n if (skipReason) {\n reporter.report({message: skipReason, status: 'skip'})\n return\n }\n\n await runStep(reporter, {\n debug: deployDebug,\n formatError: (err) => `Build failed: ${getErrorMessage(err)}`,\n name: 'build',\n solution: 'Fix the build error above, then retry',\n work: async () => {\n await build()\n reporter.report({message: successMessage, status: 'pass'})\n },\n })\n}\n\n/**\n * The deploy directory must exist and hold the right build output: a federation\n * remote for a workbench app, an `index.html` SPA otherwise.\n */\nexport async function verifyOutputDir({\n isWorkbenchApp,\n reporter,\n sourceDir,\n}: {\n isWorkbenchApp: boolean\n reporter: DeployCheckReporter\n sourceDir: string\n}): Promise<void> {\n const spin = spinner('Verifying local content...').start()\n const verifyBuild = isWorkbenchApp ? checkBuiltOutput : checkDir\n try {\n await verifyBuild(sourceDir)\n spin.succeed()\n } catch (err) {\n spin.fail()\n deployDebug('Error checking directory', err)\n reporter.report({\n message: getErrorMessage(err),\n solution: 'Run the build first, or check the output directory',\n status: 'fail',\n })\n }\n}\n\n/**\n * The single diagnosis for each app deploy-target verdict, shared by the\n * dry-run report and the real deploy's unattended error paths so message,\n * fix, and exit code can't drift between the two.\n */\nexport function describeAppTarget(\n resolution: AppDeployTargetResolution,\n {title}: {title?: string} = {},\n): DeployCheck {\n switch (resolution.type) {\n case 'blocked': {\n return {message: `Deploy target not resolved — ${resolution.message}`, status: 'skip'}\n }\n case 'found': {\n const {application} = resolution\n const title = application.title ?? application.appHost\n const url = application.url ?? getCoreAppUrl(application.organizationId, application.id)\n return {\n application,\n message: `Deploys to existing application \"${title}\" at ${url}`,\n status: 'pass',\n target: {\n action: 'update',\n id: application.id,\n title: application.title,\n type: 'coreApp',\n url,\n },\n }\n }\n case 'invalid': {\n return {\n message: APP_ID_NOT_FOUND_IN_ORGANIZATION,\n solution: 'Check `deployment.appId` matches an app in your organization',\n status: 'fail',\n }\n }\n case 'needs-input': {\n return {\n exitCode: exitCodes.USAGE_ERROR,\n message: `No \\`deployment.appId\\` configured (${resolution.existing.length} existing ${resolution.existing.length === 1 ? 'application' : 'applications'} to choose from)`,\n solution:\n 'Set `deployment.appId` in sanity.cli.ts to deploy to an existing app, or run `sanity deploy --create --title \"<name>\" --yes` to create a new one',\n status: 'fail',\n }\n }\n case 'slug-taken': {\n return describeSlugTaken(resolution)\n }\n // Without --title, creating an app needs a prompt no unattended run can answer\n case 'would-create': {\n const {appHost} = resolution\n if (title) {\n return {\n message: `Would create a new application \"${title}\"${appHost ? ` with slug \"${appHost}\"` : ''}`,\n status: 'pass',\n target: {\n action: 'create',\n id: null,\n ...(appHost ? {slug: appHost} : {}),\n title,\n type: 'coreApp',\n url: null,\n },\n }\n }\n return {\n exitCode: exitCodes.USAGE_ERROR,\n message: 'No application to deploy to — creating one needs a title',\n solution:\n 'Pass `--title \"<name>\"` or set `app.title` in sanity.cli.ts to create one, or set `deployment.appId` to deploy to an existing app',\n status: 'fail',\n }\n }\n }\n}\n\n/** One diagnosis for both the app and studio verdicts: they share a slug namespace. */\nfunction describeSlugTaken({\n appHost,\n existing,\n}: {\n appHost: string\n existing: DeployTargetApp\n}): DeployCheck {\n return {\n application: existing,\n exitCode: exitCodes.USAGE_ERROR,\n message: `An application already exists at slug \"${appHost}\" in this organization (app ID ${existing.id})`,\n solution: `Add \\`deployment: {appId: '${existing.id}'}\\` to sanity.cli.ts to redeploy it`,\n status: 'fail',\n target: {\n action: 'update',\n id: existing.id,\n title: existing.title,\n type: existing.type,\n url: existing.url ?? null,\n },\n }\n}\n\nexport function describeAppTargetError(err: unknown, organizationId: string | undefined): string {\n return (err as {statusCode?: number})?.statusCode === 403\n ? `You don’t have permission to view applications for the configured organization ID (\"${organizationId}\"). Verify the organization ID, or ask your organization’s admin for access.`\n : `Failed to resolve deploy target: ${getErrorMessage(err)}`\n}\n\n/**\n * Reports the app deploy target as a check and returns the resolved target;\n * `isWorkbenchApp` selects the backend. Both modes run it — a real deploy uses\n * it to reject a bad `appId` before building.\n */\nexport async function checkAppTarget(\n reporter: DeployCheckReporter,\n options:\n | {\n appId: string | undefined\n create?: boolean\n isWorkbenchApp?: false\n organizationId: string | undefined\n title?: string\n }\n | {\n appId: string | undefined\n isWorkbenchApp: true\n organizationId?: string\n slug?: string\n title?: string\n },\n): Promise<DeployCheck | null> {\n const {title} = options\n if (options.isWorkbenchApp) {\n const {appId, organizationId, slug} = options\n return runStep(reporter, {\n debug: deployDebug,\n name: 'target',\n work: async () => {\n const resolution = await resolveWorkbenchApp({appId, organizationId, slug})\n const check = describeAppTarget(resolution, {title})\n reporter.report(check)\n return check\n },\n })\n }\n\n const {appId, create, organizationId} = options\n return runStep(reporter, {\n debug: deployDebug,\n formatError: (err) => describeAppTargetError(err, organizationId),\n name: 'target',\n work: async () => {\n const check = describeAppTarget(\n await resolveAppDeployTarget({appId, create, organizationId}),\n {\n title,\n },\n )\n reporter.report(check)\n return check\n },\n })\n}\n\n/** Same contract as {@link describeAppTarget}, for the studio verdicts. */\nexport function describeStudioTarget(\n resolution: StudioDeployTargetResolution,\n {isExternal, isWorkbench, title}: {isExternal: boolean; isWorkbench?: boolean; title?: string},\n): DeployCheck {\n const studioUrl = (host: string) => (isExternal ? host : `https://${host}.sanity.studio`)\n\n switch (resolution.type) {\n case 'blocked': {\n return {message: `Deploy target not resolved — ${resolution.message}`, status: 'skip'}\n }\n case 'found': {\n const {appHost} = resolution.application\n const url = resolution.application.url ?? (appHost ? studioUrl(appHost) : null)\n return {\n application: resolution.application,\n message: `Deploys to existing studio ${url}`,\n status: 'pass',\n target: {\n action: 'update',\n id: resolution.application.id,\n title: resolution.application.title,\n type: 'studio',\n url,\n },\n }\n }\n case 'invalid': {\n return {\n // A bad host is a usage error; other invalid targets exit 1\n exitCode: resolution.reason === 'invalid-host' ? exitCodes.USAGE_ERROR : 1,\n message: resolution.message,\n solution: 'Check `studioHost` and `deployment.appId` in sanity.cli.ts',\n status: 'fail',\n }\n }\n case 'needs-input': {\n return {\n exitCode: exitCodes.USAGE_ERROR,\n message: isExternal ? 'No external studio URL configured' : 'No studio hostname configured',\n solution: isExternal\n ? 'Set `studioHost` in sanity.cli.ts, or pass the full URL with --url'\n : 'Set `studioHost` in sanity.cli.ts, or pass a hostname with --url',\n status: 'fail',\n }\n }\n case 'slug-taken': {\n return describeSlugTaken(resolution)\n }\n case 'would-create': {\n const appHost = resolution.appHost\n const url = isWorkbench ? null : studioUrl(appHost)\n const result = {\n status: 'pass',\n target: {action: 'create', id: null, title: title || null, type: 'studio', url},\n } as const\n const titled = title ? ` titled \"${title}\"` : ''\n\n if (isExternal) {\n return {\n message: `Would register external studio at ${appHost}${titled}`,\n ...result,\n }\n }\n\n if (isWorkbench) {\n return {\n message: `Would create a new studio${title ? ` \"${title}\"` : ''} with slug \"${appHost}\" (name availability is checked on deploy)`,\n ...result,\n target: {...result.target, slug: appHost},\n }\n }\n\n return {\n message: `Would create studio hostname ${url}${titled} (name availability is checked on deploy)`,\n ...result,\n }\n }\n }\n}\n\n/**\n * Reports the studio deploy target as a check and returns the resolved target;\n * `isWorkbenchApp` selects the backend. Both modes run it — a real deploy uses\n * it to reject a bad `appId` before building.\n */\nexport async function checkStudioTarget(\n reporter: DeployCheckReporter,\n options:\n | {\n appId: string | undefined\n isExternal: boolean\n isWorkbenchApp?: false\n projectId: string | undefined\n studioHost: string | undefined\n title: string | undefined\n urlFlag: string | undefined\n }\n | {\n appId: string | undefined\n isWorkbenchApp: true\n organizationId?: string\n slug: string\n title?: string\n },\n): Promise<DeployCheck | null> {\n const {title} = options\n const resolve = options.isWorkbenchApp\n ? resolveWorkbenchStudio(options)\n : resolveStudioDeployTarget(options)\n // A workbench studio's target is its slug, even when its build is hosted externally.\n const isExternal = options.isWorkbenchApp ? false : options.isExternal\n\n return runStep(reporter, {\n debug: deployDebug,\n formatError: (err) => `Failed to resolve deploy target: ${getErrorMessage(err)}`,\n name: 'target',\n work: async () => {\n const check = describeStudioTarget(await resolve, {\n isExternal,\n isWorkbench: !!options.isWorkbenchApp,\n title,\n })\n reporter.report(check)\n return check\n },\n })\n}\n"],"names":["exitCodes","getLocalPackageVersion","getErrorMessage","getCoreAppUrl","spinner","checkBuiltOutput","resolveAppIdIssue","runStep","APP_ID_NOT_FOUND_IN_ORGANIZATION","getAutoUpdateIssueMessage","getAutoUpdateMigrationHint","resolveAutoUpdates","checkDir","deployDebug","resolveAppDeployTarget","resolveStudioDeployTarget","resolveWorkbenchApp","resolveWorkbenchStudio","normalizeUrl","validateUrl","checkPackageVersion","reporter","moduleName","workDir","version","report","message","status","solution","checkAutoUpdates","cliConfig","flags","enabled","issue","type","autoUpdates","checkAppId","checkExternalUrl","appId","url","undefined","exitCode","USAGE_ERROR","normalized","validation","hash","origin","pathname","search","URL","checkBuild","build","skipReason","successMessage","debug","formatError","err","name","work","verifyOutputDir","isWorkbenchApp","sourceDir","spin","start","verifyBuild","succeed","fail","describeAppTarget","resolution","title","application","appHost","organizationId","id","target","action","existing","length","describeSlugTaken","slug","describeAppTargetError","statusCode","checkAppTarget","options","check","create","describeStudioTarget","isExternal","isWorkbench","studioUrl","host","reason","result","titled","checkStudioTarget","resolve"],"mappings":"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"}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { basename, dirname } from 'node:path';
|
|
1
|
+
import { basename, dirname, relative } from 'node:path';
|
|
2
2
|
import { styleText } from 'node:util';
|
|
3
3
|
import { createGzip } from 'node:zlib';
|
|
4
4
|
import { formatSchemaValidation, SchemaExtractionError } from '@sanity/cli-build/_internal/extract';
|
|
5
5
|
import { readIconFromPath } from '@sanity/cli-build/_internal/manifest';
|
|
6
6
|
import { exitCodes } from '@sanity/cli-core';
|
|
7
7
|
import { spinner } from '@sanity/cli-core/ux';
|
|
8
|
-
import { createStudio, deployWorkbenchApp, getApplicationUrl, getWorkbench, toWorkbenchPayload } from '@sanity/workbench-cli/deploy';
|
|
8
|
+
import { createStudio, deployWorkbenchApp, getApplicationUrl, getWorkbench, getWorkbenchUrl, toWorkbenchPayload } from '@sanity/workbench-cli/deploy';
|
|
9
9
|
import { c as createTar } from 'tar';
|
|
10
10
|
import { createDeployment } from '../../services/userApplications.js';
|
|
11
11
|
import { getAppId } from '../../util/appId.js';
|
|
12
12
|
import { NO_ORGANIZATION_ID, NO_PROJECT_ID } from '../../util/errorMessages.js';
|
|
13
13
|
import { buildStudio } from '../build/buildStudio.js';
|
|
14
14
|
import { createStudioUserApplication } from './createUserApplication.js';
|
|
15
|
-
import { checkAutoUpdates, checkBuild, checkPackageVersion, checkStudioTarget, verifyOutputDir } from './deployChecks.js';
|
|
15
|
+
import { checkAutoUpdates, checkBuild, checkExternalUrl, checkPackageVersion, checkStudioTarget, verifyOutputDir } from './deployChecks.js';
|
|
16
16
|
import { deployDebug } from './deployDebug.js';
|
|
17
17
|
import { listDeploymentFiles, reportInterfaces } from './deploymentPlan.js';
|
|
18
18
|
import { runDeploy } from './deployRunner.js';
|
|
@@ -36,16 +36,9 @@ export function deployStudio(options) {
|
|
|
36
36
|
const organizationId = cliConfig.app?.organizationId;
|
|
37
37
|
const appId = getAppId(cliConfig);
|
|
38
38
|
const dryRun = !!flags['dry-run'];
|
|
39
|
-
// A
|
|
40
|
-
//
|
|
41
|
-
|
|
42
|
-
reporter.report({
|
|
43
|
-
exitCode: exitCodes.USAGE_ERROR,
|
|
44
|
-
message: 'Deploying a federated application to an external host is not yet supported',
|
|
45
|
-
solution: 'Remove the --external flag to deploy to Sanity hosting',
|
|
46
|
-
status: 'fail'
|
|
47
|
-
});
|
|
48
|
-
}
|
|
39
|
+
// A legacy external studio only registers its URL; a federated one is built
|
|
40
|
+
// and deployed like a hosted one, minus the upload.
|
|
41
|
+
const isLegacyExternal = isExternal && !isWorkbenchApp;
|
|
49
42
|
const appTitle = workbench ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.slug : '';
|
|
50
43
|
const isAutoUpdating = checkAutoUpdates(reporter, {
|
|
51
44
|
cliConfig,
|
|
@@ -68,7 +61,8 @@ export function deployStudio(options) {
|
|
|
68
61
|
let application = null;
|
|
69
62
|
let studioCreated = false;
|
|
70
63
|
let workbenchApp;
|
|
71
|
-
|
|
64
|
+
let externalUrl;
|
|
65
|
+
if (workbench) {
|
|
72
66
|
reporter.report(organizationId ? {
|
|
73
67
|
message: `Organization: ${organizationId}`,
|
|
74
68
|
status: 'pass'
|
|
@@ -84,6 +78,10 @@ export function deployStudio(options) {
|
|
|
84
78
|
slug: workbench.slug,
|
|
85
79
|
title: appTitle
|
|
86
80
|
}))?.application;
|
|
81
|
+
if (isExternal) externalUrl = checkExternalUrl(reporter, {
|
|
82
|
+
appId,
|
|
83
|
+
url: flags.url
|
|
84
|
+
});
|
|
87
85
|
} else {
|
|
88
86
|
;
|
|
89
87
|
({ application, created: studioCreated } = await resolveStudioApplication(options, {
|
|
@@ -91,9 +89,11 @@ export function deployStudio(options) {
|
|
|
91
89
|
reporter
|
|
92
90
|
}));
|
|
93
91
|
}
|
|
92
|
+
// A redeploy follows how the application was registered, so --external is only needed once.
|
|
93
|
+
const isExternallyHosted = isExternal || !!workbenchApp?.externalUrl;
|
|
94
94
|
// A first deploy mints the app id and the build inlines it; --no-build would
|
|
95
95
|
// ship an existing bundle carrying a different id, so it can't be a first deploy.
|
|
96
|
-
if (workbench && !
|
|
96
|
+
if (workbench && !appId && !flags.build) {
|
|
97
97
|
reporter.report({
|
|
98
98
|
exitCode: exitCodes.USAGE_ERROR,
|
|
99
99
|
message: 'A first deploy cannot skip the build (--no-build)',
|
|
@@ -102,14 +102,15 @@ export function deployStudio(options) {
|
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
104
|
// Read up front so a bad icon path fails before we create or build.
|
|
105
|
-
const appIcon = !dryRun &&
|
|
105
|
+
const appIcon = !dryRun && workbench?.icon ? await readIconFromPath(workDir, workbench.icon) : undefined;
|
|
106
106
|
// Create the studio before the build so the bundle carries its real id. A
|
|
107
107
|
// redeploy already has it from `deployment.appId`; a dry run skips creation.
|
|
108
108
|
let applicationId = appId;
|
|
109
109
|
let applicationCreated = false;
|
|
110
110
|
let rollbackApp;
|
|
111
|
-
if (!dryRun && workbench &&
|
|
111
|
+
if (!dryRun && workbench && organizationId && !applicationId) {
|
|
112
112
|
const created = await createStudio({
|
|
113
|
+
externalUrl,
|
|
113
114
|
name: workbench.name,
|
|
114
115
|
organizationId,
|
|
115
116
|
projectId,
|
|
@@ -138,19 +139,18 @@ export function deployStudio(options) {
|
|
|
138
139
|
}),
|
|
139
140
|
skipReason: studioBuildSkipReason({
|
|
140
141
|
build: flags.build,
|
|
141
|
-
|
|
142
|
+
isLegacyExternal
|
|
142
143
|
}),
|
|
143
144
|
successMessage: 'Studio built'
|
|
144
145
|
});
|
|
145
|
-
if (!
|
|
146
|
+
if (!isLegacyExternal) {
|
|
146
147
|
await verifyOutputDir({
|
|
147
148
|
isWorkbenchApp,
|
|
148
149
|
reporter,
|
|
149
150
|
sourceDir
|
|
150
151
|
});
|
|
151
152
|
}
|
|
152
|
-
|
|
153
|
-
const interfaces = workbench && !isExternal ? reportInterfaces(reporter, workbench) : null;
|
|
153
|
+
const interfaces = workbench ? reportInterfaces(reporter, workbench) : null;
|
|
154
154
|
const payload = {
|
|
155
155
|
appId: appId ?? null,
|
|
156
156
|
isAutoUpdating,
|
|
@@ -177,11 +177,11 @@ export function deployStudio(options) {
|
|
|
177
177
|
if (!version) return;
|
|
178
178
|
const studioManifest = await uploadStudioSchema(options, {
|
|
179
179
|
applicationId: workbench ? applicationId : undefined,
|
|
180
|
-
isExternal
|
|
180
|
+
isExternal: isLegacyExternal
|
|
181
181
|
});
|
|
182
182
|
// The studio was created (or resolved from `deployment.appId`) before the
|
|
183
183
|
// build, so this only ships the deployment; plain studios use user-applications.
|
|
184
|
-
if (workbench &&
|
|
184
|
+
if (workbench && organizationId && applicationId) {
|
|
185
185
|
await deployWorkbenchApp({
|
|
186
186
|
access: toAccess(studioManifest),
|
|
187
187
|
app: cliConfig.app,
|
|
@@ -189,6 +189,7 @@ export function deployStudio(options) {
|
|
|
189
189
|
icon: appIcon,
|
|
190
190
|
isApp: false,
|
|
191
191
|
isAutoUpdating,
|
|
192
|
+
isExternal: isExternallyHosted,
|
|
192
193
|
label: 'Deploying studio',
|
|
193
194
|
// Once the deployment is live, a metadata-sync failure must not delete
|
|
194
195
|
// the studio.
|
|
@@ -213,6 +214,12 @@ export function deployStudio(options) {
|
|
|
213
214
|
output,
|
|
214
215
|
url
|
|
215
216
|
});
|
|
217
|
+
if (isExternallyHosted) logExternalHost({
|
|
218
|
+
built: flags.build,
|
|
219
|
+
organizationId,
|
|
220
|
+
output,
|
|
221
|
+
sourceDir
|
|
222
|
+
});
|
|
216
223
|
return {
|
|
217
224
|
action: applicationCreated ? 'create' : 'update',
|
|
218
225
|
application: workbenchApp ?? null,
|
|
@@ -409,8 +416,16 @@ function toWorkspaces(manifest) {
|
|
|
409
416
|
output.log(`to the \`deployment\` section in sanity.cli.js or sanity.cli.ts`);
|
|
410
417
|
output.log(`to avoid prompting for application id on next deploy.`);
|
|
411
418
|
}
|
|
412
|
-
function
|
|
413
|
-
|
|
419
|
+
/** Tells the customer what their host must do for the Dashboard to load the studio from it. */ function logExternalHost({ built, organizationId, output, sourceDir }) {
|
|
420
|
+
const dir = `${relative(process.cwd(), sourceDir) || '.'}/`;
|
|
421
|
+
output.log(`
|
|
422
|
+
The Dashboard loads this studio from your host, which must:
|
|
423
|
+
1. Serve ${dir} unchanged at the root of its URL (/mf-manifest.json, /remoteEntry-*.js, /static/*)
|
|
424
|
+
2. Send Access-Control-Allow-Origin for ${getWorkbenchUrl(organizationId)}
|
|
425
|
+
3. Respond without cookies or a sign-in${built ? `\n\nThis deploy rebuilt ${dir}: copy it to your host before opening the studio in the Dashboard.` : ''}`);
|
|
426
|
+
}
|
|
427
|
+
function studioBuildSkipReason({ build, isLegacyExternal }) {
|
|
428
|
+
if (isLegacyExternal) return 'Build skipped for externally hosted studios';
|
|
414
429
|
if (!build) return 'Build skipped (--no-build) — validating existing output directory';
|
|
415
430
|
return;
|
|
416
431
|
}
|
|
@@ -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 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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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/deploy/deployStudio.ts"],"sourcesContent":["import {basename, dirname, relative} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip, type Gzip} from 'node:zlib'\n\nimport {formatSchemaValidation, SchemaExtractionError} from '@sanity/cli-build/_internal/extract'\nimport {readIconFromPath} from '@sanity/cli-build/_internal/manifest'\nimport {exitCodes} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {\n type BrettAccess,\n type BrettWorkspace,\n createStudio,\n deployWorkbenchApp,\n getApplicationUrl,\n getWorkbench,\n getWorkbenchUrl,\n toWorkbenchPayload,\n} from '@sanity/workbench-cli/deploy'\nimport {type StudioManifest} from 'sanity'\nimport {c as createTar} from 'tar'\n\nimport {createDeployment, type UserApplication} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {NO_ORGANIZATION_ID, NO_PROJECT_ID} from '../../util/errorMessages.js'\nimport {buildStudio} from '../build/buildStudio.js'\nimport {createStudioUserApplication} from './createUserApplication.js'\nimport {\n checkAutoUpdates,\n checkBuild,\n checkExternalUrl,\n checkPackageVersion,\n checkStudioTarget,\n type DeployCheckReporter,\n verifyOutputDir,\n} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {listDeploymentFiles, reportInterfaces} from './deploymentPlan.js'\nimport {type DeployPayload, type DeployResult, runDeploy} from './deployRunner.js'\nimport {deployStudioSchemasAndManifests} from './deployStudioSchemasAndManifests.js'\nimport {findUserApplicationForStudio} from './findUserApplication.js'\nimport {type DeployAppOptions} from './types.js'\n\nconst STUDIO_PACKAGE = 'sanity'\n\nexport function deployStudio(options: DeployAppOptions): Promise<void> {\n return runDeploy(options, {\n listFiles: ({flags, projectRoot, sourceDir}) =>\n flags.external ? Promise.resolve([]) : listDeploymentFiles(sourceDir, projectRoot.directory),\n run: runStudioDeployment,\n type: 'studio',\n })\n}\n\n/** Validates the deploy, extracts and uploads the schema, and ships the build. */\nasync function runStudioDeployment(\n options: DeployAppOptions,\n reporter: DeployCheckReporter,\n): Promise<DeployResult | void> {\n const {cliConfig, flags, output, sourceDir} = options\n const workDir = options.projectRoot.directory\n const isExternal = !!flags.external\n const workbench = getWorkbench(cliConfig)\n const isWorkbenchApp = workbench !== null\n const projectId = cliConfig.api?.projectId\n const organizationId = cliConfig.app?.organizationId\n const appId = getAppId(cliConfig)\n const dryRun = !!flags['dry-run']\n // A legacy external studio only registers its URL; a federated one is built\n // and deployed like a hosted one, minus the upload.\n const isLegacyExternal = isExternal && !isWorkbenchApp\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.slug\n : ''\n\n const isAutoUpdating = checkAutoUpdates(reporter, {cliConfig, flags})\n\n const version = await checkPackageVersion(reporter, {\n moduleName: STUDIO_PACKAGE,\n workDir,\n })\n\n reporter.report(\n projectId\n ? {message: `Project: ${projectId}`, status: 'pass'}\n : {\n message: NO_PROJECT_ID,\n solution: 'Add `api.projectId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n\n // Workbench studios deploy to Brett (which needs the org); plain studios\n // resolve/create on user-applications, unchanged.\n let application: UserApplication | null = null\n let studioCreated = false\n let workbenchApp: {externalUrl?: string} | undefined\n let externalUrl: string | undefined\n if (workbench) {\n reporter.report(\n organizationId\n ? {message: `Organization: ${organizationId}`, status: 'pass'}\n : {\n message: NO_ORGANIZATION_ID,\n solution: 'Add `app.organizationId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n workbenchApp = (\n await checkStudioTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n organizationId,\n slug: workbench.slug,\n title: appTitle,\n })\n )?.application\n if (isExternal) externalUrl = checkExternalUrl(reporter, {appId, url: flags.url})\n } else {\n ;({application, created: studioCreated} = await resolveStudioApplication(options, {\n dryRun,\n reporter,\n }))\n }\n // A redeploy follows how the application was registered, so --external is only needed once.\n const isExternallyHosted = isExternal || !!workbenchApp?.externalUrl\n\n // A first deploy mints the app id and the build inlines it; --no-build would\n // ship an existing bundle carrying a different id, so it can't be a first deploy.\n if (workbench && !appId && !flags.build) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'A first deploy cannot skip the build (--no-build)',\n solution: 'Drop --no-build so the new application id is inlined into the build',\n status: 'fail',\n })\n }\n\n // Read up front so a bad icon path fails before we create or build.\n const appIcon =\n !dryRun && workbench?.icon ? await readIconFromPath(workDir, workbench.icon) : undefined\n\n // Create the studio before the build so the bundle carries its real id. A\n // redeploy already has it from `deployment.appId`; a dry run skips creation.\n let applicationId = appId\n let applicationCreated = false\n let rollbackApp: (() => Promise<void>) | undefined\n if (!dryRun && workbench && organizationId && !applicationId) {\n const created = await createStudio({\n externalUrl,\n name: workbench.name,\n organizationId,\n projectId,\n slug: workbench.slug,\n title: appTitle,\n visibility: workbench.visibility,\n })\n workbenchApp = created.application\n applicationId = created.application.id\n rollbackApp = created.rollback\n applicationCreated = true\n }\n\n // A record created above is stranded at its slug (and blocks retries) if any\n // step before it fully deploys fails, so undo the creation on failure.\n try {\n await checkBuild(reporter, {\n build: () =>\n buildStudio({\n applicationId: workbench ? applicationId : undefined,\n autoUpdatesEnabled: isAutoUpdating,\n calledFromDeploy: true,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n }),\n skipReason: studioBuildSkipReason({build: flags.build, isLegacyExternal}),\n successMessage: 'Studio built',\n })\n\n if (!isLegacyExternal) {\n await verifyOutputDir({isWorkbenchApp, reporter, sourceDir})\n }\n\n const interfaces = workbench ? reportInterfaces(reporter, workbench) : null\n\n const payload: DeployPayload = {\n appId: appId ?? null,\n isAutoUpdating,\n ...(organizationId ? {organizationId} : {}),\n ...(projectId ? {projectId} : {}),\n type: 'studio',\n version,\n ...toWorkbenchPayload(workbench, {interfaces, title: appTitle}),\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return {application: null, payload}\n\n // A real deploy has already exited if anything failed; landing here without a\n // resolved version means the deploy target was never resolved.\n if (!version) return\n\n const studioManifest = await uploadStudioSchema(options, {\n applicationId: workbench ? applicationId : undefined,\n isExternal: isLegacyExternal,\n })\n // The studio was created (or resolved from `deployment.appId`) before the\n // build, so this only ships the deployment; plain studios use user-applications.\n if (workbench && organizationId && applicationId) {\n await deployWorkbenchApp({\n access: toAccess(studioManifest),\n app: cliConfig.app,\n applicationId,\n icon: appIcon,\n isApp: false,\n isAutoUpdating,\n isExternal: isExternallyHosted,\n label: 'Deploying studio',\n // 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 if (isExternallyHosted)\n logExternalHost({built: flags.build, organizationId, output, sourceDir})\n return {\n action: applicationCreated ? 'create' : 'update',\n application: workbenchApp ?? null,\n payload,\n url,\n }\n }\n\n if (!application) return\n const location = await shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n })\n\n return {\n action: studioCreated ? 'create' : 'update',\n application,\n payload,\n url: location,\n }\n } catch (err) {\n await rollbackApp?.()\n throw err\n }\n}\n\n/**\n * Finds the application a real deploy targets, registering a studio host when\n * none is configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveStudioApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplication | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const isExternal = !!flags.external\n const appId = getAppId(cliConfig)\n // Sets the title on a newly registered studio; blank falls back to undefined\n const title = flags.title?.trim() || undefined\n\n if (dryRun) {\n await checkStudioTarget(reporter, {\n appId,\n isExternal,\n projectId: cliConfig.api?.projectId,\n studioHost: cliConfig.studioHost,\n title,\n urlFlag: flags.url,\n })\n return {application: null, created: false}\n }\n\n const projectId = cliConfig.api?.projectId ?? ''\n // `created` is true when a configured-but-unregistered host was just registered.\n const {application, created} = await findUserApplicationForStudio({\n appId,\n isExternal,\n output,\n projectId,\n studioHost: cliConfig.studioHost,\n title,\n unattended: !!flags.yes,\n urlFlag: flags.url,\n })\n\n if (!application) {\n if (isExternal) {\n output.log('Your project has not been registered with an external studio URL.')\n output.log('Please enter the full URL where your studio is hosted.')\n } else {\n output.log('Your project has not been assigned a studio hostname.')\n output.log('To deploy your Sanity Studio to our hosted sanity.studio service,')\n output.log('you will need one. Please enter the subdomain you want to use.')\n }\n\n const registered = await createStudioUserApplication({\n projectId,\n title,\n urlType: isExternal ? 'external' : 'internal',\n })\n deployDebug('Created user application', registered)\n return {application: registered, created: true}\n }\n\n deployDebug('Found user application', application)\n return {application, created}\n}\n\n/** Extracts the studio schema and manifest and uploads them to the schema store. */\nasync function uploadStudioSchema(\n options: DeployAppOptions,\n {applicationId, isExternal}: {applicationId?: string; isExternal: boolean},\n): Promise<StudioManifest | null> {\n const {cliConfig, flags, output, projectRoot, sourceDir} = options\n\n let studioManifest: StudioManifest | null = null\n try {\n studioManifest = await deployStudioSchemasAndManifests(\n {\n applicationId,\n configPath: projectRoot.path,\n isExternal,\n outPath: `${sourceDir}/static`,\n projectId: cliConfig.api?.projectId ?? '',\n schemaRequired: flags['schema-required'],\n verbose: flags.verbose,\n workDir: projectRoot.directory,\n },\n output,\n )\n } catch (error) {\n deployDebug('Error deploying studio schemas and manifests', error)\n if (error instanceof SchemaExtractionError && error.validation?.length) {\n output.error(formatSchemaValidation(error.validation), {exit: exitCodes.RUNTIME_ERROR})\n }\n output.error(`Error deploying studio schemas and manifests: ${error}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (!studioManifest) {\n output.error('Failed to generate studio manifest. Please check your schemas and manifests.', {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n return studioManifest\n}\n\nasync function shipStudioDeployment({\n application,\n isAutoUpdating,\n isExternal,\n options,\n studioManifest,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n isExternal: boolean\n options: DeployAppOptions\n studioManifest: StudioManifest | null\n version: string\n}): Promise<string> {\n const {cliConfig, output, sourceDir} = options\n\n let tarball: Gzip | undefined\n if (!isExternal) {\n tarball = createTar({cwd: dirname(sourceDir)}, [basename(sourceDir)]).pipe(createGzip())\n }\n\n const spin = spinner(isExternal ? 'Registering studio' : 'Deploying to sanity.studio').start()\n let location: string\n try {\n ;({location} = await createDeployment({\n applicationId: application.id,\n isApp: false,\n isAutoUpdating,\n manifest: studioManifest,\n projectId: cliConfig.api?.projectId,\n tarball,\n version,\n }))\n } catch (error) {\n spin.fail()\n throw error\n }\n spin.succeed()\n\n const named = application.title ? ` — \"${application.title}\"` : ''\n output.log(\n isExternal\n ? `\\nSuccess! Studio registered${named}`\n : `\\nSuccess! Studio deployed to ${styleText('cyan', location)}${named}`,\n )\n\n if (getAppId(cliConfig)) return location\n\n const example = `Example:\nexport default defineCliConfig({\n //…\n deployment: {\n ${styleText('cyan', `appId: '${application.id}'`)},\n },\n //…\n})`\n output.log(`\\nAdd ${styleText('cyan', `appId: '${application.id}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n output.log(`\\n${example}`)\n\n return location\n}\n\n/**\n * One `datasets` access entry per unique workspace dataset, with a `resourceId`\n * of `\"<projectId>.<dataset>\"`. Deduped, since workspaces can share a dataset.\n */\nfunction toAccess(manifest: StudioManifest | null): BrettAccess[] {\n const resourceIds = new Set(\n (manifest?.workspaces ?? []).map((w) => `${w.projectId}.${w.dataset}`),\n )\n return [...resourceIds].map(\n (resourceId) => ({resourceId, resourceType: 'dataset'}) satisfies BrettAccess,\n )\n}\n\nfunction toWorkspaces(manifest: StudioManifest | null): BrettWorkspace[] {\n return (manifest?.workspaces ?? []).map((workspace) => ({\n basePath: workspace.basePath,\n dataset: workspace.dataset,\n icon: workspace.icon,\n name: workspace.name,\n projectId: workspace.projectId,\n schemaDescriptorId: workspace.schemaDescriptorId,\n subtitle: workspace.subtitle,\n title: workspace.title,\n }))\n}\n\n/** Renders the workbench studio's deploy result; the appId hint shows only when none is configured. */\nfunction logWorkbenchStudioDeployed({\n applicationId,\n cliConfig,\n output,\n url,\n}: {\n applicationId: string\n cliConfig: DeployAppOptions['cliConfig']\n output: DeployAppOptions['output']\n url: string\n}): void {\n output.log(`\\nSuccess! Studio deployed to ${styleText('cyan', url)}`)\n if (getAppId(cliConfig)) return\n\n output.log(`\\nAdd ${styleText('cyan', `appId: '${applicationId}'`)}`)\n output.log(`to the \\`deployment\\` section in sanity.cli.js or sanity.cli.ts`)\n output.log(`to avoid prompting for application id on next deploy.`)\n}\n\n/** Tells the customer what their host must do for the Dashboard to load the studio from it. */\nfunction logExternalHost({\n built,\n organizationId,\n output,\n sourceDir,\n}: {\n built: boolean\n organizationId: string\n output: DeployAppOptions['output']\n sourceDir: string\n}): void {\n const dir = `${relative(process.cwd(), sourceDir) || '.'}/`\n output.log(`\nThe Dashboard loads this studio from your host, which must:\n 1. Serve ${dir} unchanged at the root of its URL (/mf-manifest.json, /remoteEntry-*.js, /static/*)\n 2. Send Access-Control-Allow-Origin for ${getWorkbenchUrl(organizationId)}\n 3. Respond without cookies or a sign-in${built ? `\\n\\nThis deploy rebuilt ${dir}: copy it to your host before opening the studio in the Dashboard.` : ''}`)\n}\n\nfunction studioBuildSkipReason({\n build,\n isLegacyExternal,\n}: {\n build: boolean\n isLegacyExternal: boolean\n}) {\n if (isLegacyExternal) return 'Build skipped for externally hosted studios'\n if (!build) return 'Build skipped (--no-build) — validating existing output directory'\n return\n}\n"],"names":["basename","dirname","relative","styleText","createGzip","formatSchemaValidation","SchemaExtractionError","readIconFromPath","exitCodes","spinner","createStudio","deployWorkbenchApp","getApplicationUrl","getWorkbench","getWorkbenchUrl","toWorkbenchPayload","c","createTar","createDeployment","getAppId","NO_ORGANIZATION_ID","NO_PROJECT_ID","buildStudio","createStudioUserApplication","checkAutoUpdates","checkBuild","checkExternalUrl","checkPackageVersion","checkStudioTarget","verifyOutputDir","deployDebug","listDeploymentFiles","reportInterfaces","runDeploy","deployStudioSchemasAndManifests","findUserApplicationForStudio","STUDIO_PACKAGE","deployStudio","options","listFiles","flags","projectRoot","sourceDir","external","Promise","resolve","directory","run","runStudioDeployment","type","reporter","cliConfig","output","workDir","isExternal","workbench","isWorkbenchApp","projectId","api","organizationId","app","appId","dryRun","isLegacyExternal","appTitle","title","trim","slug","isAutoUpdating","version","moduleName","report","message","status","solution","application","studioCreated","workbenchApp","externalUrl","url","created","resolveStudioApplication","isExternallyHosted","build","exitCode","USAGE_ERROR","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","logWorkbenchStudioDeployed","logExternalHost","built","action","location","shipStudioDeployment","err","studioHost","urlFlag","unattended","yes","log","registered","urlType","configPath","path","outPath","schemaRequired","verbose","error","validation","length","exit","RUNTIME_ERROR","tarball","cwd","pipe","spin","start","manifest","fail","succeed","named","example","resourceIds","Set","map","w","dataset","resourceId","resourceType","workspace","basePath","schemaDescriptorId","subtitle","dir","process"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import path from 'node:path';
|
|
|
2
2
|
import { getSanityEnvVar } from '@sanity/cli-core';
|
|
3
3
|
import { logSymbols, spinner } from '@sanity/cli-core/ux';
|
|
4
4
|
import { isWorkbenchApp } from '@sanity/workbench-cli';
|
|
5
|
-
import { resolveWorkbenchConfig } from '@sanity/workbench-cli/build';
|
|
5
|
+
import { resolveAppEntry, resolveWorkbenchConfig } from '@sanity/workbench-cli/build';
|
|
6
6
|
import { determineIsApp } from '../../../util/determineIsApp.js';
|
|
7
7
|
import { getSharedServerConfig } from '../../../util/getSharedServerConfig.js';
|
|
8
8
|
import { resolveReactStrictMode } from '../../../util/resolveReactStrictMode.js';
|
|
@@ -39,7 +39,7 @@ export function getDevServerConfig({ cliConfig, flags, httpPort, output, workDir
|
|
|
39
39
|
bundledDev,
|
|
40
40
|
// The app's navigable entry. A branded app that omits `entry` has no app
|
|
41
41
|
// view: the runtime/federation skip the `./App` render path entirely.
|
|
42
|
-
entry: app
|
|
42
|
+
entry: resolveAppEntry(app),
|
|
43
43
|
exposes: isWorkbenchApp(app) ? {
|
|
44
44
|
views: app.views,
|
|
45
45
|
webWorkers: app.webWorkers
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/actions/dev/servers/getDevServerConfig.ts"],"sourcesContent":["import path from 'node:path'\n\nimport {type CliConfig, getSanityEnvVar, type Output} from '@sanity/cli-core'\nimport {logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\nimport {resolveWorkbenchConfig} from '@sanity/workbench-cli/build'\n\nimport {type DevServerOptions} from '../../../server/devServer.js'\nimport {determineIsApp} from '../../../util/determineIsApp.js'\nimport {getSharedServerConfig} from '../../../util/getSharedServerConfig.js'\nimport {resolveReactStrictMode} from '../../../util/resolveReactStrictMode.js'\nimport {type DevFlags} from '../types.js'\n\nexport function getDevServerConfig({\n cliConfig,\n flags,\n httpPort,\n output,\n workDir,\n}: {\n cliConfig?: CliConfig\n flags: DevFlags\n httpPort?: number\n output: Output\n workDir: string\n}): Omit<DevServerOptions, 'spinner'> {\n const configSpinner = spinner('Checking configuration files...')\n\n const baseConfig = getSharedServerConfig({\n cliConfig,\n flags: {\n host: flags.host,\n port: flags.port,\n },\n workDir,\n })\n\n configSpinner.succeed()\n\n const isApp = cliConfig ? determineIsApp(cliConfig) : false\n const reactStrictMode = resolveReactStrictMode(cliConfig)\n // `views`/`webWorkers` are declared via `defineApplication`, so read them off\n // the branded app result rather than the legacy `app` config type. A config is\n // not an app — it resolves separately and expands only its `fields`.\n const app = cliConfig?.app\n const workbenchConfig = resolveWorkbenchConfig(cliConfig)\n\n const envBasePath = getSanityEnvVar('BASEPATH', isApp ?? false)\n if (envBasePath && cliConfig?.project?.basePath) {\n output.warn(\n `Overriding configured base path (${cliConfig.project.basePath}) with value from environment variable (${envBasePath})`,\n )\n }\n\n // Unstable opt-in to Vite's experimental bundled dev mode, via\n // `unstable_bundledDev` in sanity.cli.ts. Defaults to off.\n const bundledDev = cliConfig?.unstable_bundledDev ?? false\n if (bundledDev) {\n output.log(`${logSymbols.info} Running dev server with experimental Vite bundled dev mode`)\n }\n\n return {\n ...baseConfig,\n bundledDev,\n // The app's navigable entry. A branded app that omits `entry` has no app\n // view: the runtime/federation skip the `./App` render path entirely.\n entry: app
|
|
1
|
+
{"version":3,"sources":["../../../../src/actions/dev/servers/getDevServerConfig.ts"],"sourcesContent":["import path from 'node:path'\n\nimport {type CliConfig, getSanityEnvVar, type Output} from '@sanity/cli-core'\nimport {logSymbols, spinner} from '@sanity/cli-core/ux'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\nimport {resolveAppEntry, resolveWorkbenchConfig} from '@sanity/workbench-cli/build'\n\nimport {type DevServerOptions} from '../../../server/devServer.js'\nimport {determineIsApp} from '../../../util/determineIsApp.js'\nimport {getSharedServerConfig} from '../../../util/getSharedServerConfig.js'\nimport {resolveReactStrictMode} from '../../../util/resolveReactStrictMode.js'\nimport {type DevFlags} from '../types.js'\n\nexport function getDevServerConfig({\n cliConfig,\n flags,\n httpPort,\n output,\n workDir,\n}: {\n cliConfig?: CliConfig\n flags: DevFlags\n httpPort?: number\n output: Output\n workDir: string\n}): Omit<DevServerOptions, 'spinner'> {\n const configSpinner = spinner('Checking configuration files...')\n\n const baseConfig = getSharedServerConfig({\n cliConfig,\n flags: {\n host: flags.host,\n port: flags.port,\n },\n workDir,\n })\n\n configSpinner.succeed()\n\n const isApp = cliConfig ? determineIsApp(cliConfig) : false\n const reactStrictMode = resolveReactStrictMode(cliConfig)\n // `views`/`webWorkers` are declared via `defineApplication`, so read them off\n // the branded app result rather than the legacy `app` config type. A config is\n // not an app — it resolves separately and expands only its `fields`.\n const app = cliConfig?.app\n const workbenchConfig = resolveWorkbenchConfig(cliConfig)\n\n const envBasePath = getSanityEnvVar('BASEPATH', isApp ?? false)\n if (envBasePath && cliConfig?.project?.basePath) {\n output.warn(\n `Overriding configured base path (${cliConfig.project.basePath}) with value from environment variable (${envBasePath})`,\n )\n }\n\n // Unstable opt-in to Vite's experimental bundled dev mode, via\n // `unstable_bundledDev` in sanity.cli.ts. Defaults to off.\n const bundledDev = cliConfig?.unstable_bundledDev ?? false\n if (bundledDev) {\n output.log(`${logSymbols.info} Running dev server with experimental Vite bundled dev mode`)\n }\n\n return {\n ...baseConfig,\n bundledDev,\n // The app's navigable entry. A branded app that omits `entry` has no app\n // view: the runtime/federation skip the `./App` render path entirely.\n entry: resolveAppEntry(app),\n exposes: isWorkbenchApp(app)\n ? {views: app.views, webWorkers: app.webWorkers}\n : workbenchConfig\n ? {config: {appType: workbenchConfig.appType, fields: workbenchConfig.fields}}\n : undefined,\n // `devAction` passes an explicit port when a running workbench claimed the\n // configured one; otherwise the shared resolution stands.\n httpPort: httpPort ?? baseConfig.httpPort,\n isWorkbenchApp: isWorkbenchApp(app) || !!workbenchConfig,\n reactCompiler: cliConfig && 'reactCompiler' in cliConfig ? cliConfig.reactCompiler : undefined,\n reactStrictMode,\n staticPath: path.join(workDir, 'static'),\n typegen: cliConfig?.typegen,\n workbenchAppId: isWorkbenchApp(app) ? app.slug : undefined,\n }\n}\n"],"names":["path","getSanityEnvVar","logSymbols","spinner","isWorkbenchApp","resolveAppEntry","resolveWorkbenchConfig","determineIsApp","getSharedServerConfig","resolveReactStrictMode","getDevServerConfig","cliConfig","flags","httpPort","output","workDir","configSpinner","baseConfig","host","port","succeed","isApp","reactStrictMode","app","workbenchConfig","envBasePath","project","basePath","warn","bundledDev","unstable_bundledDev","log","info","entry","exposes","views","webWorkers","config","appType","fields","undefined","reactCompiler","staticPath","join","typegen","workbenchAppId","slug"],"mappings":"AAAA,OAAOA,UAAU,YAAW;AAE5B,SAAwBC,eAAe,QAAoB,mBAAkB;AAC7E,SAAQC,UAAU,EAAEC,OAAO,QAAO,sBAAqB;AACvD,SAAQC,cAAc,QAAO,wBAAuB;AACpD,SAAQC,eAAe,EAAEC,sBAAsB,QAAO,8BAA6B;AAGnF,SAAQC,cAAc,QAAO,kCAAiC;AAC9D,SAAQC,qBAAqB,QAAO,yCAAwC;AAC5E,SAAQC,sBAAsB,QAAO,0CAAyC;AAG9E,OAAO,SAASC,mBAAmB,EACjCC,SAAS,EACTC,KAAK,EACLC,QAAQ,EACRC,MAAM,EACNC,OAAO,EAOR;IACC,MAAMC,gBAAgBb,QAAQ;IAE9B,MAAMc,aAAaT,sBAAsB;QACvCG;QACAC,OAAO;YACLM,MAAMN,MAAMM,IAAI;YAChBC,MAAMP,MAAMO,IAAI;QAClB;QACAJ;IACF;IAEAC,cAAcI,OAAO;IAErB,MAAMC,QAAQV,YAAYJ,eAAeI,aAAa;IACtD,MAAMW,kBAAkBb,uBAAuBE;IAC/C,8EAA8E;IAC9E,+EAA+E;IAC/E,qEAAqE;IACrE,MAAMY,MAAMZ,WAAWY;IACvB,MAAMC,kBAAkBlB,uBAAuBK;IAE/C,MAAMc,cAAcxB,gBAAgB,YAAYoB,SAAS;IACzD,IAAII,eAAed,WAAWe,SAASC,UAAU;QAC/Cb,OAAOc,IAAI,CACT,CAAC,iCAAiC,EAAEjB,UAAUe,OAAO,CAACC,QAAQ,CAAC,wCAAwC,EAAEF,YAAY,CAAC,CAAC;IAE3H;IAEA,+DAA+D;IAC/D,2DAA2D;IAC3D,MAAMI,aAAalB,WAAWmB,uBAAuB;IACrD,IAAID,YAAY;QACdf,OAAOiB,GAAG,CAAC,GAAG7B,WAAW8B,IAAI,CAAC,2DAA2D,CAAC;IAC5F;IAEA,OAAO;QACL,GAAGf,UAAU;QACbY;QACA,yEAAyE;QACzE,sEAAsE;QACtEI,OAAO5B,gBAAgBkB;QACvBW,SAAS9B,eAAemB,OACpB;YAACY,OAAOZ,IAAIY,KAAK;YAAEC,YAAYb,IAAIa,UAAU;QAAA,IAC7CZ,kBACE;YAACa,QAAQ;gBAACC,SAASd,gBAAgBc,OAAO;gBAAEC,QAAQf,gBAAgBe,MAAM;YAAA;QAAC,IAC3EC;QACN,2EAA2E;QAC3E,0DAA0D;QAC1D3B,UAAUA,YAAYI,WAAWJ,QAAQ;QACzCT,gBAAgBA,eAAemB,QAAQ,CAAC,CAACC;QACzCiB,eAAe9B,aAAa,mBAAmBA,YAAYA,UAAU8B,aAAa,GAAGD;QACrFlB;QACAoB,YAAY1C,KAAK2C,IAAI,CAAC5B,SAAS;QAC/B6B,SAASjC,WAAWiC;QACpBC,gBAAgBzC,eAAemB,OAAOA,IAAIuB,IAAI,GAAGN;IACnD;AACF"}
|
package/dist/commands/deploy.js
CHANGED
|
@@ -33,6 +33,10 @@ export class DeployCommand extends SanityCommand {
|
|
|
33
33
|
command: '<%= config.bin %> <%= command.id %> --external',
|
|
34
34
|
description: 'Register an externally hosted studio (studioHost contains full URL)'
|
|
35
35
|
},
|
|
36
|
+
{
|
|
37
|
+
command: '<%= config.bin %> <%= command.id %> --external --url https://apps.example.com',
|
|
38
|
+
description: 'Register an externally hosted studio, served from the provided origin'
|
|
39
|
+
},
|
|
36
40
|
{
|
|
37
41
|
command: '<%= config.bin %> <%= command.id %> --create --title "My App" --yes --json',
|
|
38
42
|
description: 'Create and deploy an App SDK app without prompts. Save application.id as deployment.appId, then omit --create on later deploys'
|
|
@@ -73,8 +77,7 @@ export class DeployCommand extends SanityCommand {
|
|
|
73
77
|
description: 'Register an externally hosted studio',
|
|
74
78
|
exclusive: [
|
|
75
79
|
'source-maps',
|
|
76
|
-
'minify'
|
|
77
|
-
'build'
|
|
80
|
+
'minify'
|
|
78
81
|
]
|
|
79
82
|
}),
|
|
80
83
|
json: Flags.boolean({
|
|
@@ -99,7 +102,7 @@ export class DeployCommand extends SanityCommand {
|
|
|
99
102
|
description: 'Title for a newly created application or studio. For apps, use --create to select creation when the organization already has apps'
|
|
100
103
|
}),
|
|
101
104
|
url: Flags.string({
|
|
102
|
-
description: 'Studio URL for deployment. For external
|
|
105
|
+
description: 'Studio URL for deployment. For external deploys, the full URL. For hosted studios, the hostname (e.g. "my-studio" or "my-studio.sanity.studio")'
|
|
103
106
|
}),
|
|
104
107
|
verbose: Flags.boolean({
|
|
105
108
|
default: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/commands/deploy.ts"],"sourcesContent":["import path from 'node:path'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exitCodes, SanityCommand} from '@sanity/cli-core'\nimport {confirm} from '@sanity/cli-core/ux'\nimport {getWorkbench, resolveWorkbenchConfig} from '@sanity/workbench-cli/deploy'\n\nimport {deployApp} from '../actions/deploy/deployApp.js'\nimport {deployDebug} from '../actions/deploy/deployDebug.js'\nimport {deployStudio} from '../actions/deploy/deployStudio.js'\nimport {getAppId} from '../util/appId.js'\nimport {determineIsApp} from '../util/determineIsApp.js'\nimport {dirIsEmptyOrNonExistent} from '../util/dirIsEmptyOrNonExistent.js'\n\nexport class DeployCommand extends SanityCommand<typeof DeployCommand> {\n static override args = {\n sourceDir: Args.directory({\n description: 'Source directory',\n }),\n }\n\n static override description = 'Builds and deploys Sanity Studio or application to Sanity hosting'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Build and deploy the studio to Sanity hosting',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --no-minify --source-maps',\n description: 'Deploys non-minified build with source maps',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --schema-required',\n description:\n 'Fail fast on schema store fails - for when other services rely on the stored schema',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --external',\n description: 'Register an externally hosted studio (studioHost contains full URL)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --create --title \"My App\" --yes --json',\n description:\n 'Create and deploy an App SDK app without prompts. Save application.id as deployment.appId, then omit --create on later deploys',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --create --title \"My App\" --dry-run --json',\n description: 'Preview a new App SDK deployment without creating or uploading anything',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --url my-studio --yes',\n description: 'Deploy a studio without prompts using its hostname',\n },\n ]\n\n static override flags = {\n 'auto-updates': Flags.boolean({\n allowNo: true,\n deprecated: true,\n description: 'Automatically update the studio to the latest version',\n }),\n build: Flags.boolean({\n allowNo: true,\n default: true,\n description:\n 'Build the studio before deploying (use --no-build to deploy existing `dist/` output)',\n }),\n create: Flags.boolean({\n description: 'Create a new App SDK app, even if the organization has other apps',\n exclusive: ['external', 'url'],\n }),\n 'dry-run': Flags.boolean({\n default: false,\n description: 'Report what would be deployed without uploading or creating anything',\n }),\n external: Flags.boolean({\n default: false,\n description: 'Register an externally hosted studio',\n exclusive: ['source-maps', 'minify', 'build'],\n }),\n json: Flags.boolean({\n char: 'j',\n default: false,\n description: 'Output the result as JSON',\n }),\n minify: Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Minify built JavaScript (use --no-minify to skip for faster builds)',\n }),\n 'schema-required': Flags.boolean({\n default: false,\n description: 'Fail if schema deployment fails',\n }),\n 'source-maps': Flags.boolean({\n default: false,\n description: 'Enable source maps for built bundles (increases size of bundle)',\n }),\n title: Flags.string({\n description:\n 'Title for a newly created application or studio. For apps, use --create to select creation when the organization already has apps',\n }),\n url: Flags.string({\n description:\n 'Studio URL for deployment. For external studios, the full URL. For hosted studios, the hostname (e.g. \"my-studio\" or \"my-studio.sanity.studio\")',\n }),\n verbose: Flags.boolean({\n default: false,\n description: 'Enable verbose logging',\n }),\n yes: Flags.boolean({\n char: 'y',\n default: false,\n description:\n 'Unattended mode, answers \"yes\" to any \"yes/no\" prompt and otherwise uses defaults',\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(DeployCommand)\n\n const cliConfig = await this.getCliConfig()\n const projectRoot = await this.getProjectRoot()\n\n const isApp = determineIsApp(cliConfig)\n\n if (flags.create) {\n if (!isApp) {\n return this.output.error(\n '--create is only supported for App SDK apps. For a studio, use --url <hostname>.',\n )\n }\n if (getAppId(cliConfig)) {\n return this.output.error(\n '--create cannot be used with a configured app ID. Omit --create to deploy to that app, or remove deployment.appId and app.id to create a new one.',\n )\n }\n if (getWorkbench(cliConfig) || resolveWorkbenchConfig(cliConfig)) {\n return this.output.error(\n '--create is not supported for this app configuration. Omit --create and run sanity deploy.',\n )\n }\n }\n\n const defaultOutputDir = path.resolve(path.join(projectRoot.directory, 'dist'))\n const sourceDir = path.resolve(process.cwd(), this.args.sourceDir || defaultOutputDir)\n\n // Skip the directory check if the studio is externally hosted\n if (this.args.sourceDir && this.args.sourceDir !== 'dist' && !flags.external) {\n let relativeOutput = path.relative(process.cwd(), sourceDir)\n if (relativeOutput[0] !== '.') {\n relativeOutput = `./${relativeOutput}`\n }\n\n if (!this.isUnattended() && !flags['dry-run']) {\n const isEmpty = await dirIsEmptyOrNonExistent(sourceDir)\n const shouldProceed =\n isEmpty ||\n (await confirm({\n default: false,\n message: `\"${relativeOutput}\" is not empty, do you want to proceed?`,\n }))\n\n if (!shouldProceed) {\n this.output.error('Cancelled.', {exit: exitCodes.RUNTIME_ERROR})\n }\n }\n\n // Keep --json's stdout clean for the payload\n if (!flags.json) this.output.log(`Building to ${relativeOutput}\\n`)\n }\n\n // Force yes downstream: build/app resolution otherwise prompts for prerelease/version choices\n const deployFlags = this.isUnattended() || flags['dry-run'] ? {...flags, yes: true} : flags\n\n if (isApp) {\n deployDebug('Deploying app')\n await deployApp({\n cliConfig,\n flags: deployFlags,\n output: this.output,\n projectRoot,\n sourceDir,\n })\n } else {\n deployDebug('Deploying studio')\n await deployStudio({\n cliConfig,\n flags: deployFlags,\n output: this.output,\n projectRoot,\n sourceDir,\n })\n }\n }\n}\n"],"names":["path","Args","Flags","exitCodes","SanityCommand","confirm","getWorkbench","resolveWorkbenchConfig","deployApp","deployDebug","deployStudio","getAppId","determineIsApp","dirIsEmptyOrNonExistent","DeployCommand","args","sourceDir","directory","description","examples","command","flags","boolean","allowNo","deprecated","build","default","create","exclusive","external","json","char","minify","title","string","url","verbose","yes","run","parse","cliConfig","getCliConfig","projectRoot","getProjectRoot","isApp","output","error","defaultOutputDir","resolve","join","process","cwd","relativeOutput","relative","isUnattended","isEmpty","shouldProceed","message","exit","RUNTIME_ERROR","log","deployFlags"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/commands/deploy.ts"],"sourcesContent":["import path from 'node:path'\n\nimport {Args, Flags} from '@oclif/core'\nimport {exitCodes, SanityCommand} from '@sanity/cli-core'\nimport {confirm} from '@sanity/cli-core/ux'\nimport {getWorkbench, resolveWorkbenchConfig} from '@sanity/workbench-cli/deploy'\n\nimport {deployApp} from '../actions/deploy/deployApp.js'\nimport {deployDebug} from '../actions/deploy/deployDebug.js'\nimport {deployStudio} from '../actions/deploy/deployStudio.js'\nimport {getAppId} from '../util/appId.js'\nimport {determineIsApp} from '../util/determineIsApp.js'\nimport {dirIsEmptyOrNonExistent} from '../util/dirIsEmptyOrNonExistent.js'\n\nexport class DeployCommand extends SanityCommand<typeof DeployCommand> {\n static override args = {\n sourceDir: Args.directory({\n description: 'Source directory',\n }),\n }\n\n static override description = 'Builds and deploys Sanity Studio or application to Sanity hosting'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'Build and deploy the studio to Sanity hosting',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --no-minify --source-maps',\n description: 'Deploys non-minified build with source maps',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --schema-required',\n description:\n 'Fail fast on schema store fails - for when other services rely on the stored schema',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --external',\n description: 'Register an externally hosted studio (studioHost contains full URL)',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --external --url https://apps.example.com',\n description: 'Register an externally hosted studio, served from the provided origin',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --create --title \"My App\" --yes --json',\n description:\n 'Create and deploy an App SDK app without prompts. Save application.id as deployment.appId, then omit --create on later deploys',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --create --title \"My App\" --dry-run --json',\n description: 'Preview a new App SDK deployment without creating or uploading anything',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --url my-studio --yes',\n description: 'Deploy a studio without prompts using its hostname',\n },\n ]\n\n static override flags = {\n 'auto-updates': Flags.boolean({\n allowNo: true,\n deprecated: true,\n description: 'Automatically update the studio to the latest version',\n }),\n build: Flags.boolean({\n allowNo: true,\n default: true,\n description:\n 'Build the studio before deploying (use --no-build to deploy existing `dist/` output)',\n }),\n create: Flags.boolean({\n description: 'Create a new App SDK app, even if the organization has other apps',\n exclusive: ['external', 'url'],\n }),\n 'dry-run': Flags.boolean({\n default: false,\n description: 'Report what would be deployed without uploading or creating anything',\n }),\n external: Flags.boolean({\n default: false,\n description: 'Register an externally hosted studio',\n exclusive: ['source-maps', 'minify'],\n }),\n json: Flags.boolean({\n char: 'j',\n default: false,\n description: 'Output the result as JSON',\n }),\n minify: Flags.boolean({\n allowNo: true,\n default: true,\n description: 'Minify built JavaScript (use --no-minify to skip for faster builds)',\n }),\n 'schema-required': Flags.boolean({\n default: false,\n description: 'Fail if schema deployment fails',\n }),\n 'source-maps': Flags.boolean({\n default: false,\n description: 'Enable source maps for built bundles (increases size of bundle)',\n }),\n title: Flags.string({\n description:\n 'Title for a newly created application or studio. For apps, use --create to select creation when the organization already has apps',\n }),\n url: Flags.string({\n description:\n 'Studio URL for deployment. For external deploys, the full URL. For hosted studios, the hostname (e.g. \"my-studio\" or \"my-studio.sanity.studio\")',\n }),\n verbose: Flags.boolean({\n default: false,\n description: 'Enable verbose logging',\n }),\n yes: Flags.boolean({\n char: 'y',\n default: false,\n description:\n 'Unattended mode, answers \"yes\" to any \"yes/no\" prompt and otherwise uses defaults',\n }),\n }\n\n public async run(): Promise<void> {\n const {flags} = await this.parse(DeployCommand)\n\n const cliConfig = await this.getCliConfig()\n const projectRoot = await this.getProjectRoot()\n\n const isApp = determineIsApp(cliConfig)\n\n if (flags.create) {\n if (!isApp) {\n return this.output.error(\n '--create is only supported for App SDK apps. For a studio, use --url <hostname>.',\n )\n }\n if (getAppId(cliConfig)) {\n return this.output.error(\n '--create cannot be used with a configured app ID. Omit --create to deploy to that app, or remove deployment.appId and app.id to create a new one.',\n )\n }\n if (getWorkbench(cliConfig) || resolveWorkbenchConfig(cliConfig)) {\n return this.output.error(\n '--create is not supported for this app configuration. Omit --create and run sanity deploy.',\n )\n }\n }\n\n const defaultOutputDir = path.resolve(path.join(projectRoot.directory, 'dist'))\n const sourceDir = path.resolve(process.cwd(), this.args.sourceDir || defaultOutputDir)\n\n // Skip the directory check if the studio is externally hosted\n if (this.args.sourceDir && this.args.sourceDir !== 'dist' && !flags.external) {\n let relativeOutput = path.relative(process.cwd(), sourceDir)\n if (relativeOutput[0] !== '.') {\n relativeOutput = `./${relativeOutput}`\n }\n\n if (!this.isUnattended() && !flags['dry-run']) {\n const isEmpty = await dirIsEmptyOrNonExistent(sourceDir)\n const shouldProceed =\n isEmpty ||\n (await confirm({\n default: false,\n message: `\"${relativeOutput}\" is not empty, do you want to proceed?`,\n }))\n\n if (!shouldProceed) {\n this.output.error('Cancelled.', {exit: exitCodes.RUNTIME_ERROR})\n }\n }\n\n // Keep --json's stdout clean for the payload\n if (!flags.json) this.output.log(`Building to ${relativeOutput}\\n`)\n }\n\n // Force yes downstream: build/app resolution otherwise prompts for prerelease/version choices\n const deployFlags = this.isUnattended() || flags['dry-run'] ? {...flags, yes: true} : flags\n\n if (isApp) {\n deployDebug('Deploying app')\n await deployApp({\n cliConfig,\n flags: deployFlags,\n output: this.output,\n projectRoot,\n sourceDir,\n })\n } else {\n deployDebug('Deploying studio')\n await deployStudio({\n cliConfig,\n flags: deployFlags,\n output: this.output,\n projectRoot,\n sourceDir,\n })\n }\n }\n}\n"],"names":["path","Args","Flags","exitCodes","SanityCommand","confirm","getWorkbench","resolveWorkbenchConfig","deployApp","deployDebug","deployStudio","getAppId","determineIsApp","dirIsEmptyOrNonExistent","DeployCommand","args","sourceDir","directory","description","examples","command","flags","boolean","allowNo","deprecated","build","default","create","exclusive","external","json","char","minify","title","string","url","verbose","yes","run","parse","cliConfig","getCliConfig","projectRoot","getProjectRoot","isApp","output","error","defaultOutputDir","resolve","join","process","cwd","relativeOutput","relative","isUnattended","isEmpty","shouldProceed","message","exit","RUNTIME_ERROR","log","deployFlags"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { AssetSource, AssetSourceComponentProps } from "@sanity/types";
|
|
2
|
-
import { AssetSourceComponent, AssetSourceViewComponents, DefinedService, DefinedView, PanelComponent, PanelViewComponents, PanelViewProps, ServiceCallback, ServiceContext, ServiceInfo, ServiceType, TileComponent, TileSize, TileViewComponents, TileViewProps, ViewComponentsBySurface, ViewSurface, unstable_defineService, unstable_defineView } from "@sanity/workbench-cli";
|
|
3
|
-
export { type AssetSource, type AssetSourceComponent, type AssetSourceComponentProps, type AssetSourceViewComponents, type DefinedService, type DefinedView, type PanelComponent, type PanelViewComponents, type PanelViewProps, type ServiceCallback, type ServiceContext, type ServiceInfo, type ServiceType, type TileComponent, type TileSize, type TileViewComponents, type TileViewProps, type ViewComponentsBySurface, type ViewSurface, unstable_defineService, unstable_defineView };
|
|
2
|
+
import { AssetSourceComponent, AssetSourceViewComponents, DefinedService, DefinedView, PanelComponent, PanelViewComponents, PanelViewProps, ServiceBus, ServiceCallback, ServiceContext, ServiceInfo, ServiceType, TileComponent, TileSize, TileViewComponents, TileViewProps, ViewComponentsBySurface, ViewSurface, unstable_defineService, unstable_defineView } from "@sanity/workbench-cli";
|
|
3
|
+
export { type AssetSource, type AssetSourceComponent, type AssetSourceComponentProps, type AssetSourceViewComponents, type DefinedService, type DefinedView, type PanelComponent, type PanelViewComponents, type PanelViewProps, type ServiceBus, type ServiceCallback, type ServiceContext, type ServiceInfo, type ServiceType, type TileComponent, type TileSize, type TileViewComponents, type TileViewProps, type ViewComponentsBySurface, type ViewSurface, unstable_defineService, unstable_defineView };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/exports/runtime.ts"],"sourcesContent":["// Browser-safe runtime authoring helpers for the module-federation extension API.\n//\n// View/service src files bundle to the browser, so this entry re-exports ONLY\n// from dependency-light, browser-safe modules — it must never import\n// `@sanity/cli-core` or anything Node-only, or it would drag the CLI into the\n// frontend bundle. The `sanity` runtime package re-exports from here, so the\n// same constraint protects it.\n//\n// `defineApplication` is config-time (Node) and stays on the main `@sanity/cli`\n// entry; only the runtime helpers live here.\nexport type {AssetSource, AssetSourceComponentProps} from '@sanity/types'\nexport type {\n AssetSourceComponent,\n AssetSourceViewComponents,\n DefinedService,\n DefinedView,\n PanelComponent,\n PanelViewComponents,\n PanelViewProps,\n ServiceCallback,\n ServiceContext,\n ServiceInfo,\n ServiceType,\n TileComponent,\n TileSize,\n TileViewComponents,\n TileViewProps,\n ViewComponentsBySurface,\n ViewSurface,\n} from '@sanity/workbench-cli'\nexport {unstable_defineService, unstable_defineView} from '@sanity/workbench-cli'\n"],"names":["unstable_defineService","unstable_defineView"],"mappings":"AAAA,kFAAkF;AAClF,EAAE;AACF,8EAA8E;AAC9E,qEAAqE;AACrE,8EAA8E;AAC9E,6EAA6E;AAC7E,+BAA+B;AAC/B,EAAE;AACF,gFAAgF;AAChF,6CAA6C;
|
|
1
|
+
{"version":3,"sources":["../../src/exports/runtime.ts"],"sourcesContent":["// Browser-safe runtime authoring helpers for the module-federation extension API.\n//\n// View/service src files bundle to the browser, so this entry re-exports ONLY\n// from dependency-light, browser-safe modules — it must never import\n// `@sanity/cli-core` or anything Node-only, or it would drag the CLI into the\n// frontend bundle. The `sanity` runtime package re-exports from here, so the\n// same constraint protects it.\n//\n// `defineApplication` is config-time (Node) and stays on the main `@sanity/cli`\n// entry; only the runtime helpers live here.\nexport type {AssetSource, AssetSourceComponentProps} from '@sanity/types'\nexport type {\n AssetSourceComponent,\n AssetSourceViewComponents,\n DefinedService,\n DefinedView,\n PanelComponent,\n PanelViewComponents,\n PanelViewProps,\n ServiceBus,\n ServiceCallback,\n ServiceContext,\n ServiceInfo,\n ServiceType,\n TileComponent,\n TileSize,\n TileViewComponents,\n TileViewProps,\n ViewComponentsBySurface,\n ViewSurface,\n} from '@sanity/workbench-cli'\nexport {unstable_defineService, unstable_defineView} from '@sanity/workbench-cli'\n"],"names":["unstable_defineService","unstable_defineView"],"mappings":"AAAA,kFAAkF;AAClF,EAAE;AACF,8EAA8E;AAC9E,qEAAqE;AACrE,8EAA8E;AAC9E,6EAA6E;AAC7E,+BAA+B;AAC/B,EAAE;AACF,gFAAgF;AAChF,6CAA6C;AAsB7C,SAAQA,sBAAsB,EAAEC,mBAAmB,QAAO,wBAAuB"}
|
package/oclif.manifest.json
CHANGED
|
@@ -359,6 +359,10 @@
|
|
|
359
359
|
"command": "<%= config.bin %> <%= command.id %> --external",
|
|
360
360
|
"description": "Register an externally hosted studio (studioHost contains full URL)"
|
|
361
361
|
},
|
|
362
|
+
{
|
|
363
|
+
"command": "<%= config.bin %> <%= command.id %> --external --url https://apps.example.com",
|
|
364
|
+
"description": "Register an externally hosted studio, served from the provided origin"
|
|
365
|
+
},
|
|
362
366
|
{
|
|
363
367
|
"command": "<%= config.bin %> <%= command.id %> --create --title \"My App\" --yes --json",
|
|
364
368
|
"description": "Create and deploy an App SDK app without prompts. Save application.id as deployment.appId, then omit --create on later deploys"
|
|
@@ -406,8 +410,7 @@
|
|
|
406
410
|
"description": "Register an externally hosted studio",
|
|
407
411
|
"exclusive": [
|
|
408
412
|
"source-maps",
|
|
409
|
-
"minify"
|
|
410
|
-
"build"
|
|
413
|
+
"minify"
|
|
411
414
|
],
|
|
412
415
|
"name": "external",
|
|
413
416
|
"allowNo": false,
|
|
@@ -446,7 +449,7 @@
|
|
|
446
449
|
"type": "option"
|
|
447
450
|
},
|
|
448
451
|
"url": {
|
|
449
|
-
"description": "Studio URL for deployment. For external
|
|
452
|
+
"description": "Studio URL for deployment. For external deploys, the full URL. For hosted studios, the hostname (e.g. \"my-studio\" or \"my-studio.sanity.studio\")",
|
|
450
453
|
"name": "url",
|
|
451
454
|
"hasDynamicHelp": false,
|
|
452
455
|
"multiple": false,
|
|
@@ -2321,6 +2324,130 @@
|
|
|
2321
2324
|
"update.js"
|
|
2322
2325
|
]
|
|
2323
2326
|
},
|
|
2327
|
+
"docs:browse": {
|
|
2328
|
+
"aliases": [],
|
|
2329
|
+
"args": {},
|
|
2330
|
+
"description": "Open Sanity docs in your browser",
|
|
2331
|
+
"flags": {},
|
|
2332
|
+
"hasDynamicHelp": false,
|
|
2333
|
+
"hiddenAliases": [],
|
|
2334
|
+
"id": "docs:browse",
|
|
2335
|
+
"pluginAlias": "@sanity/cli",
|
|
2336
|
+
"pluginName": "@sanity/cli",
|
|
2337
|
+
"pluginType": "core",
|
|
2338
|
+
"strict": true,
|
|
2339
|
+
"enableJsonFlag": false,
|
|
2340
|
+
"isESM": true,
|
|
2341
|
+
"relativePath": [
|
|
2342
|
+
"dist",
|
|
2343
|
+
"commands",
|
|
2344
|
+
"docs",
|
|
2345
|
+
"browse.js"
|
|
2346
|
+
]
|
|
2347
|
+
},
|
|
2348
|
+
"docs:read": {
|
|
2349
|
+
"aliases": [],
|
|
2350
|
+
"args": {
|
|
2351
|
+
"path": {
|
|
2352
|
+
"description": "Path or URL to article, found in search results and docs content as links",
|
|
2353
|
+
"name": "path",
|
|
2354
|
+
"required": true
|
|
2355
|
+
}
|
|
2356
|
+
},
|
|
2357
|
+
"description": "Read an article in terminal",
|
|
2358
|
+
"examples": [
|
|
2359
|
+
{
|
|
2360
|
+
"command": "<%= config.bin %> <%= command.id %> /docs/studio/installation",
|
|
2361
|
+
"description": "Read as markdown in terminal"
|
|
2362
|
+
},
|
|
2363
|
+
{
|
|
2364
|
+
"command": "<%= config.bin %> <%= command.id %> https://www.sanity.io/docs/studio/installation",
|
|
2365
|
+
"description": "Read using full URL"
|
|
2366
|
+
},
|
|
2367
|
+
{
|
|
2368
|
+
"command": "<%= config.bin %> <%= command.id %> /docs/studio/installation --web",
|
|
2369
|
+
"description": "Open in web browser"
|
|
2370
|
+
},
|
|
2371
|
+
{
|
|
2372
|
+
"command": "<%= config.bin %> <%= command.id %> https://www.sanity.io/docs/studio/installation -w",
|
|
2373
|
+
"description": "Open using full URL in web browser"
|
|
2374
|
+
}
|
|
2375
|
+
],
|
|
2376
|
+
"flags": {
|
|
2377
|
+
"web": {
|
|
2378
|
+
"aliases": [
|
|
2379
|
+
"w"
|
|
2380
|
+
],
|
|
2381
|
+
"description": "Open in a web browser",
|
|
2382
|
+
"name": "web",
|
|
2383
|
+
"allowNo": false,
|
|
2384
|
+
"type": "boolean"
|
|
2385
|
+
}
|
|
2386
|
+
},
|
|
2387
|
+
"hasDynamicHelp": false,
|
|
2388
|
+
"hiddenAliases": [],
|
|
2389
|
+
"id": "docs:read",
|
|
2390
|
+
"pluginAlias": "@sanity/cli",
|
|
2391
|
+
"pluginName": "@sanity/cli",
|
|
2392
|
+
"pluginType": "core",
|
|
2393
|
+
"strict": true,
|
|
2394
|
+
"isESM": true,
|
|
2395
|
+
"relativePath": [
|
|
2396
|
+
"dist",
|
|
2397
|
+
"commands",
|
|
2398
|
+
"docs",
|
|
2399
|
+
"read.js"
|
|
2400
|
+
]
|
|
2401
|
+
},
|
|
2402
|
+
"docs:search": {
|
|
2403
|
+
"aliases": [],
|
|
2404
|
+
"args": {
|
|
2405
|
+
"query": {
|
|
2406
|
+
"description": "Search query for documentation",
|
|
2407
|
+
"name": "query",
|
|
2408
|
+
"required": true
|
|
2409
|
+
}
|
|
2410
|
+
},
|
|
2411
|
+
"description": "Search Sanity docs",
|
|
2412
|
+
"examples": [
|
|
2413
|
+
{
|
|
2414
|
+
"command": "<%= config.bin %> <%= command.id %> schema",
|
|
2415
|
+
"description": "Search for documentation about schemas"
|
|
2416
|
+
},
|
|
2417
|
+
{
|
|
2418
|
+
"command": "<%= config.bin %> <%= command.id %> \"groq functions\"",
|
|
2419
|
+
"description": "Search with phrase"
|
|
2420
|
+
},
|
|
2421
|
+
{
|
|
2422
|
+
"command": "<%= config.bin %> <%= command.id %> \"deployment\" --limit=5",
|
|
2423
|
+
"description": "Limit search results"
|
|
2424
|
+
}
|
|
2425
|
+
],
|
|
2426
|
+
"flags": {
|
|
2427
|
+
"limit": {
|
|
2428
|
+
"description": "Maximum number of results to return",
|
|
2429
|
+
"name": "limit",
|
|
2430
|
+
"default": 10,
|
|
2431
|
+
"hasDynamicHelp": false,
|
|
2432
|
+
"multiple": false,
|
|
2433
|
+
"type": "option"
|
|
2434
|
+
}
|
|
2435
|
+
},
|
|
2436
|
+
"hasDynamicHelp": false,
|
|
2437
|
+
"hiddenAliases": [],
|
|
2438
|
+
"id": "docs:search",
|
|
2439
|
+
"pluginAlias": "@sanity/cli",
|
|
2440
|
+
"pluginName": "@sanity/cli",
|
|
2441
|
+
"pluginType": "core",
|
|
2442
|
+
"strict": true,
|
|
2443
|
+
"isESM": true,
|
|
2444
|
+
"relativePath": [
|
|
2445
|
+
"dist",
|
|
2446
|
+
"commands",
|
|
2447
|
+
"docs",
|
|
2448
|
+
"search.js"
|
|
2449
|
+
]
|
|
2450
|
+
},
|
|
2324
2451
|
"datasets:copy": {
|
|
2325
2452
|
"aliases": [],
|
|
2326
2453
|
"args": {
|
|
@@ -2943,130 +3070,6 @@
|
|
|
2943
3070
|
"list.js"
|
|
2944
3071
|
]
|
|
2945
3072
|
},
|
|
2946
|
-
"docs:browse": {
|
|
2947
|
-
"aliases": [],
|
|
2948
|
-
"args": {},
|
|
2949
|
-
"description": "Open Sanity docs in your browser",
|
|
2950
|
-
"flags": {},
|
|
2951
|
-
"hasDynamicHelp": false,
|
|
2952
|
-
"hiddenAliases": [],
|
|
2953
|
-
"id": "docs:browse",
|
|
2954
|
-
"pluginAlias": "@sanity/cli",
|
|
2955
|
-
"pluginName": "@sanity/cli",
|
|
2956
|
-
"pluginType": "core",
|
|
2957
|
-
"strict": true,
|
|
2958
|
-
"enableJsonFlag": false,
|
|
2959
|
-
"isESM": true,
|
|
2960
|
-
"relativePath": [
|
|
2961
|
-
"dist",
|
|
2962
|
-
"commands",
|
|
2963
|
-
"docs",
|
|
2964
|
-
"browse.js"
|
|
2965
|
-
]
|
|
2966
|
-
},
|
|
2967
|
-
"docs:read": {
|
|
2968
|
-
"aliases": [],
|
|
2969
|
-
"args": {
|
|
2970
|
-
"path": {
|
|
2971
|
-
"description": "Path or URL to article, found in search results and docs content as links",
|
|
2972
|
-
"name": "path",
|
|
2973
|
-
"required": true
|
|
2974
|
-
}
|
|
2975
|
-
},
|
|
2976
|
-
"description": "Read an article in terminal",
|
|
2977
|
-
"examples": [
|
|
2978
|
-
{
|
|
2979
|
-
"command": "<%= config.bin %> <%= command.id %> /docs/studio/installation",
|
|
2980
|
-
"description": "Read as markdown in terminal"
|
|
2981
|
-
},
|
|
2982
|
-
{
|
|
2983
|
-
"command": "<%= config.bin %> <%= command.id %> https://www.sanity.io/docs/studio/installation",
|
|
2984
|
-
"description": "Read using full URL"
|
|
2985
|
-
},
|
|
2986
|
-
{
|
|
2987
|
-
"command": "<%= config.bin %> <%= command.id %> /docs/studio/installation --web",
|
|
2988
|
-
"description": "Open in web browser"
|
|
2989
|
-
},
|
|
2990
|
-
{
|
|
2991
|
-
"command": "<%= config.bin %> <%= command.id %> https://www.sanity.io/docs/studio/installation -w",
|
|
2992
|
-
"description": "Open using full URL in web browser"
|
|
2993
|
-
}
|
|
2994
|
-
],
|
|
2995
|
-
"flags": {
|
|
2996
|
-
"web": {
|
|
2997
|
-
"aliases": [
|
|
2998
|
-
"w"
|
|
2999
|
-
],
|
|
3000
|
-
"description": "Open in a web browser",
|
|
3001
|
-
"name": "web",
|
|
3002
|
-
"allowNo": false,
|
|
3003
|
-
"type": "boolean"
|
|
3004
|
-
}
|
|
3005
|
-
},
|
|
3006
|
-
"hasDynamicHelp": false,
|
|
3007
|
-
"hiddenAliases": [],
|
|
3008
|
-
"id": "docs:read",
|
|
3009
|
-
"pluginAlias": "@sanity/cli",
|
|
3010
|
-
"pluginName": "@sanity/cli",
|
|
3011
|
-
"pluginType": "core",
|
|
3012
|
-
"strict": true,
|
|
3013
|
-
"isESM": true,
|
|
3014
|
-
"relativePath": [
|
|
3015
|
-
"dist",
|
|
3016
|
-
"commands",
|
|
3017
|
-
"docs",
|
|
3018
|
-
"read.js"
|
|
3019
|
-
]
|
|
3020
|
-
},
|
|
3021
|
-
"docs:search": {
|
|
3022
|
-
"aliases": [],
|
|
3023
|
-
"args": {
|
|
3024
|
-
"query": {
|
|
3025
|
-
"description": "Search query for documentation",
|
|
3026
|
-
"name": "query",
|
|
3027
|
-
"required": true
|
|
3028
|
-
}
|
|
3029
|
-
},
|
|
3030
|
-
"description": "Search Sanity docs",
|
|
3031
|
-
"examples": [
|
|
3032
|
-
{
|
|
3033
|
-
"command": "<%= config.bin %> <%= command.id %> schema",
|
|
3034
|
-
"description": "Search for documentation about schemas"
|
|
3035
|
-
},
|
|
3036
|
-
{
|
|
3037
|
-
"command": "<%= config.bin %> <%= command.id %> \"groq functions\"",
|
|
3038
|
-
"description": "Search with phrase"
|
|
3039
|
-
},
|
|
3040
|
-
{
|
|
3041
|
-
"command": "<%= config.bin %> <%= command.id %> \"deployment\" --limit=5",
|
|
3042
|
-
"description": "Limit search results"
|
|
3043
|
-
}
|
|
3044
|
-
],
|
|
3045
|
-
"flags": {
|
|
3046
|
-
"limit": {
|
|
3047
|
-
"description": "Maximum number of results to return",
|
|
3048
|
-
"name": "limit",
|
|
3049
|
-
"default": 10,
|
|
3050
|
-
"hasDynamicHelp": false,
|
|
3051
|
-
"multiple": false,
|
|
3052
|
-
"type": "option"
|
|
3053
|
-
}
|
|
3054
|
-
},
|
|
3055
|
-
"hasDynamicHelp": false,
|
|
3056
|
-
"hiddenAliases": [],
|
|
3057
|
-
"id": "docs:search",
|
|
3058
|
-
"pluginAlias": "@sanity/cli",
|
|
3059
|
-
"pluginName": "@sanity/cli",
|
|
3060
|
-
"pluginType": "core",
|
|
3061
|
-
"strict": true,
|
|
3062
|
-
"isESM": true,
|
|
3063
|
-
"relativePath": [
|
|
3064
|
-
"dist",
|
|
3065
|
-
"commands",
|
|
3066
|
-
"docs",
|
|
3067
|
-
"search.js"
|
|
3068
|
-
]
|
|
3069
|
-
},
|
|
3070
3073
|
"documents:create": {
|
|
3071
3074
|
"aliases": [],
|
|
3072
3075
|
"args": {
|
|
@@ -4078,32 +4081,6 @@
|
|
|
4078
4081
|
"extract.js"
|
|
4079
4082
|
]
|
|
4080
4083
|
},
|
|
4081
|
-
"mcp:configure": {
|
|
4082
|
-
"aliases": [],
|
|
4083
|
-
"args": {},
|
|
4084
|
-
"description": "Configure Sanity MCP server for AI editors (Antigravity, Claude Code, Cline, Cline CLI, Codex CLI, Cursor, Gemini CLI, GitHub Copilot CLI, MCPorter, OpenCode, VS Code, VS Code Insiders, Zed)",
|
|
4085
|
-
"examples": [
|
|
4086
|
-
{
|
|
4087
|
-
"command": "<%= config.bin %> <%= command.id %>",
|
|
4088
|
-
"description": "Configure Sanity MCP server for detected AI editors"
|
|
4089
|
-
}
|
|
4090
|
-
],
|
|
4091
|
-
"flags": {},
|
|
4092
|
-
"hasDynamicHelp": false,
|
|
4093
|
-
"hiddenAliases": [],
|
|
4094
|
-
"id": "mcp:configure",
|
|
4095
|
-
"pluginAlias": "@sanity/cli",
|
|
4096
|
-
"pluginName": "@sanity/cli",
|
|
4097
|
-
"pluginType": "core",
|
|
4098
|
-
"strict": true,
|
|
4099
|
-
"isESM": true,
|
|
4100
|
-
"relativePath": [
|
|
4101
|
-
"dist",
|
|
4102
|
-
"commands",
|
|
4103
|
-
"mcp",
|
|
4104
|
-
"configure.js"
|
|
4105
|
-
]
|
|
4106
|
-
},
|
|
4107
4084
|
"media:create-aspect": {
|
|
4108
4085
|
"aliases": [],
|
|
4109
4086
|
"args": {},
|
|
@@ -4719,6 +4696,32 @@
|
|
|
4719
4696
|
"list.js"
|
|
4720
4697
|
]
|
|
4721
4698
|
},
|
|
4699
|
+
"mcp:configure": {
|
|
4700
|
+
"aliases": [],
|
|
4701
|
+
"args": {},
|
|
4702
|
+
"description": "Configure Sanity MCP server for AI editors (Antigravity, Claude Code, Cline, Cline CLI, Codex CLI, Cursor, Gemini CLI, GitHub Copilot CLI, MCPorter, OpenCode, VS Code, VS Code Insiders, Zed)",
|
|
4703
|
+
"examples": [
|
|
4704
|
+
{
|
|
4705
|
+
"command": "<%= config.bin %> <%= command.id %>",
|
|
4706
|
+
"description": "Configure Sanity MCP server for detected AI editors"
|
|
4707
|
+
}
|
|
4708
|
+
],
|
|
4709
|
+
"flags": {},
|
|
4710
|
+
"hasDynamicHelp": false,
|
|
4711
|
+
"hiddenAliases": [],
|
|
4712
|
+
"id": "mcp:configure",
|
|
4713
|
+
"pluginAlias": "@sanity/cli",
|
|
4714
|
+
"pluginName": "@sanity/cli",
|
|
4715
|
+
"pluginType": "core",
|
|
4716
|
+
"strict": true,
|
|
4717
|
+
"isESM": true,
|
|
4718
|
+
"relativePath": [
|
|
4719
|
+
"dist",
|
|
4720
|
+
"commands",
|
|
4721
|
+
"mcp",
|
|
4722
|
+
"configure.js"
|
|
4723
|
+
]
|
|
4724
|
+
},
|
|
4722
4725
|
"organizations:create": {
|
|
4723
4726
|
"aliases": [],
|
|
4724
4727
|
"args": {},
|
|
@@ -7055,5 +7058,5 @@
|
|
|
7055
7058
|
]
|
|
7056
7059
|
}
|
|
7057
7060
|
},
|
|
7058
|
-
"version": "8.
|
|
7061
|
+
"version": "8.17.1"
|
|
7059
7062
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/cli",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.17.1",
|
|
4
4
|
"description": "Sanity CLI tool for managing Sanity projects and organizations",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"@oclif/plugin-help": "^6.2.53",
|
|
64
64
|
"@oclif/plugin-not-found": "^3.2.88",
|
|
65
65
|
"@sanity/cli-build": "^6.4.5",
|
|
66
|
-
"@sanity/cli-core": "^3.9.
|
|
66
|
+
"@sanity/cli-core": "^3.9.2",
|
|
67
67
|
"@sanity/client": "^8.9.0",
|
|
68
68
|
"@sanity/codegen": "^8.2.0",
|
|
69
69
|
"@sanity/descriptors": "^1.3.0",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"@sanity/telemetry": "^1.1.0",
|
|
79
79
|
"@sanity/template-validator": "^3.1.1",
|
|
80
80
|
"@sanity/types": "^6.17.0",
|
|
81
|
-
"@sanity/workbench-cli": "^2.
|
|
81
|
+
"@sanity/workbench-cli": "^2.10.0",
|
|
82
82
|
"@sanity/worker-channels": "^2.0.0",
|
|
83
83
|
"@sanity/workflow-cli": "0.36.0",
|
|
84
84
|
"@sanity/workflow-engine": "0.36.0",
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
"@eslint/compat": "^2.1.0",
|
|
128
128
|
"@repo/package.config": "0.0.1",
|
|
129
129
|
"@repo/tsconfig": "3.70.0",
|
|
130
|
-
"@sanity/cli-test": "19.0.
|
|
130
|
+
"@sanity/cli-test": "19.0.2",
|
|
131
131
|
"@sanity/eslint-config-cli": "1.1.3",
|
|
132
132
|
"@sanity/pkg-utils": "^12.3.4",
|
|
133
133
|
"@swc/cli": "^0.8.1",
|