@sanity/cli 7.5.0 → 7.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/dist/actions/build/buildApp.js +7 -183
- package/dist/actions/build/buildApp.js.map +1 -1
- package/dist/actions/build/buildStudio.js +6 -213
- package/dist/actions/build/buildStudio.js.map +1 -1
- package/dist/actions/build/shouldAutoUpdate.js +100 -22
- package/dist/actions/build/shouldAutoUpdate.js.map +1 -1
- package/dist/actions/deploy/{createStudioUserApplication.js → createUserApplication.js} +56 -5
- package/dist/actions/deploy/createUserApplication.js.map +1 -0
- package/dist/actions/deploy/deployApp.js +253 -183
- package/dist/actions/deploy/deployApp.js.map +1 -1
- package/dist/actions/deploy/deployChecks.js +284 -0
- package/dist/actions/deploy/deployChecks.js.map +1 -0
- package/dist/actions/deploy/deployRunner.js +78 -0
- package/dist/actions/deploy/deployRunner.js.map +1 -0
- package/dist/actions/deploy/deployStudio.js +200 -197
- package/dist/actions/deploy/deployStudio.js.map +1 -1
- package/dist/actions/deploy/deployStudioSchemasAndManifests.js +2 -3
- package/dist/actions/deploy/deployStudioSchemasAndManifests.js.map +1 -1
- package/dist/actions/deploy/deploymentPlan.js +117 -0
- package/dist/actions/deploy/deploymentPlan.js.map +1 -0
- package/dist/actions/deploy/findUserApplication.js +209 -0
- package/dist/actions/deploy/findUserApplication.js.map +1 -0
- package/dist/actions/deploy/resolveDeployTarget.js +185 -0
- package/dist/actions/deploy/resolveDeployTarget.js.map +1 -0
- package/dist/actions/deploy/urlUtils.js +4 -0
- package/dist/actions/deploy/urlUtils.js.map +1 -1
- package/dist/actions/dev/devAction.js +1 -1
- package/dist/actions/dev/devAction.js.map +1 -1
- package/dist/actions/dev/servers/getDevServerConfig.js +18 -6
- package/dist/actions/dev/servers/getDevServerConfig.js.map +1 -1
- package/dist/actions/dev/servers/startAppDevServer.js +1 -1
- package/dist/actions/dev/servers/startAppDevServer.js.map +1 -1
- package/dist/actions/dev/servers/startStudioDevServer.js +2 -1
- package/dist/actions/dev/servers/startStudioDevServer.js.map +1 -1
- package/dist/actions/manifest/extractCoreAppManifest.js +15 -1
- package/dist/actions/manifest/extractCoreAppManifest.js.map +1 -1
- package/dist/commands/deploy.js +31 -12
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.js +2 -1
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/init.js +2 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/exports/index.d.ts +9 -0
- package/dist/exports/index.js +1 -8
- package/dist/exports/index.js.map +1 -1
- package/dist/server/devServer.js +27 -3
- package/dist/server/devServer.js.map +1 -1
- package/dist/services/userApplications.js.map +1 -1
- package/dist/util/appId.js +13 -5
- package/dist/util/appId.js.map +1 -1
- package/dist/util/compareDependencyVersions.js.map +1 -1
- package/dist/util/determineIsApp.js +1 -1
- package/dist/util/determineIsApp.js.map +1 -1
- package/dist/util/errorMessages.js +2 -0
- package/dist/util/errorMessages.js.map +1 -1
- package/oclif.manifest.json +223 -203
- package/package.json +8 -8
- package/dist/actions/build/handlePrereleaseVersions.js +0 -44
- package/dist/actions/build/handlePrereleaseVersions.js.map +0 -1
- package/dist/actions/deploy/createStudioUserApplication.js.map +0 -1
- package/dist/actions/deploy/createUserApplicationForApp.js +0 -56
- package/dist/actions/deploy/createUserApplicationForApp.js.map +0 -1
- package/dist/actions/deploy/findUserApplicationForApp.js +0 -111
- package/dist/actions/deploy/findUserApplicationForApp.js.map +0 -1
- package/dist/actions/deploy/findUserApplicationForStudio.js +0 -172
- package/dist/actions/deploy/findUserApplicationForStudio.js.map +0 -1
- package/dist/actions/deploy/viewDeployment.js +0 -32
- package/dist/actions/deploy/viewDeployment.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/cli",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.7.0",
|
|
4
4
|
"description": "Sanity CLI tool for managing Sanity projects and organizations",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -114,13 +114,13 @@
|
|
|
114
114
|
"tinyglobby": "^0.2.17",
|
|
115
115
|
"tsx": "^4.22.4",
|
|
116
116
|
"typeid-js": "^1.2.0",
|
|
117
|
-
"vite": "^8.1.
|
|
117
|
+
"vite": "^8.1.3",
|
|
118
118
|
"which": "^6.0.1",
|
|
119
119
|
"yaml": "^2.9.0",
|
|
120
120
|
"zod": "^4.4.3",
|
|
121
|
-
"@sanity/cli-
|
|
122
|
-
"@sanity/workbench-cli": "^1.
|
|
123
|
-
"@sanity/cli-
|
|
121
|
+
"@sanity/cli-core": "^2.2.1",
|
|
122
|
+
"@sanity/workbench-cli": "^1.2.0",
|
|
123
|
+
"@sanity/cli-build": "^3.0.0"
|
|
124
124
|
},
|
|
125
125
|
"devDependencies": {
|
|
126
126
|
"@eslint/compat": "^2.1.0",
|
|
@@ -154,10 +154,10 @@
|
|
|
154
154
|
"sanity": "^6.1.0",
|
|
155
155
|
"typescript": "^5.9.3",
|
|
156
156
|
"vitest": "^4.1.9",
|
|
157
|
-
"@repo/package.config": "0.0.1",
|
|
158
157
|
"@repo/tsconfig": "3.70.0",
|
|
159
|
-
"@
|
|
160
|
-
"@sanity/cli-test": "
|
|
158
|
+
"@repo/package.config": "0.0.1",
|
|
159
|
+
"@sanity/cli-test": "3.0.1",
|
|
160
|
+
"@sanity/eslint-config-cli": "1.1.2"
|
|
161
161
|
},
|
|
162
162
|
"peerDependencies": {
|
|
163
163
|
"babel-plugin-react-compiler": "*"
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { styleText } from 'node:util';
|
|
2
|
-
import { isInteractive } from '@sanity/cli-core';
|
|
3
|
-
import { select } from '@sanity/cli-core/ux';
|
|
4
|
-
/**
|
|
5
|
-
* Handle prerelease versions that cannot be resolved by the auto-updates CDN.
|
|
6
|
-
*
|
|
7
|
-
* In unattended or non-interactive mode, exits with an error. In interactive mode,
|
|
8
|
-
* prompts the user to either disable auto-updates for this build or cancel.
|
|
9
|
-
*
|
|
10
|
-
* Does not return if the build should be cancelled (exits via `output.error`).
|
|
11
|
-
*/ export async function handlePrereleaseVersions({ output, unattendedMode, unresolvedPrerelease }) {
|
|
12
|
-
const prereleaseMessage = `The following packages are using prerelease versions not yet available on the auto-updates CDN:\n\n` + `${unresolvedPrerelease.map((mod)=>` - ${mod.pkg} (${mod.version})`).join('\n')}\n\n` + `Auto-updates cannot be used with prerelease versions. To re-enable auto-updates later, ` + `switch to a non-prerelease version locally and deploy again.`;
|
|
13
|
-
if (unattendedMode || !isInteractive()) {
|
|
14
|
-
output.error(`${prereleaseMessage}\n\n` + `Cannot build with auto-updates in unattended mode when using prerelease versions. ` + `Either switch to a non-prerelease version, or use --no-auto-updates to build without auto-updates.`, {
|
|
15
|
-
exit: 1
|
|
16
|
-
});
|
|
17
|
-
// output.error with exit: 1 throws, but TypeScript doesn't know that
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
const choice = await select({
|
|
21
|
-
choices: [
|
|
22
|
-
{
|
|
23
|
-
name: 'Disable auto-updates for this build and continue',
|
|
24
|
-
value: 'disable-auto-updates'
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
name: 'Cancel build',
|
|
28
|
-
value: 'cancel'
|
|
29
|
-
}
|
|
30
|
-
],
|
|
31
|
-
default: 'disable-auto-updates',
|
|
32
|
-
message: styleText('yellow', prereleaseMessage)
|
|
33
|
-
});
|
|
34
|
-
if (choice === 'cancel') {
|
|
35
|
-
output.error('Declined to continue with build', {
|
|
36
|
-
exit: 1
|
|
37
|
-
});
|
|
38
|
-
// output.error with exit: 1 throws, but TypeScript doesn't know that
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
output.warn('Auto-updates disabled for this build');
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
//# sourceMappingURL=handlePrereleaseVersions.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/build/handlePrereleaseVersions.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {isInteractive, type Output} from '@sanity/cli-core'\nimport {select} from '@sanity/cli-core/ux'\n\nimport {type UnresolvedPrerelease} from '../../util/compareDependencyVersions.js'\n\n/**\n * Handle prerelease versions that cannot be resolved by the auto-updates CDN.\n *\n * In unattended or non-interactive mode, exits with an error. In interactive mode,\n * prompts the user to either disable auto-updates for this build or cancel.\n *\n * Does not return if the build should be cancelled (exits via `output.error`).\n */\nexport async function handlePrereleaseVersions({\n output,\n unattendedMode,\n unresolvedPrerelease,\n}: {\n output: Output\n unattendedMode: boolean\n unresolvedPrerelease: UnresolvedPrerelease[]\n}): Promise<void> {\n const prereleaseMessage =\n `The following packages are using prerelease versions not yet available on the auto-updates CDN:\\n\\n` +\n `${unresolvedPrerelease.map((mod) => ` - ${mod.pkg} (${mod.version})`).join('\\n')}\\n\\n` +\n `Auto-updates cannot be used with prerelease versions. To re-enable auto-updates later, ` +\n `switch to a non-prerelease version locally and deploy again.`\n\n if (unattendedMode || !isInteractive()) {\n output.error(\n `${prereleaseMessage}\\n\\n` +\n `Cannot build with auto-updates in unattended mode when using prerelease versions. ` +\n `Either switch to a non-prerelease version, or use --no-auto-updates to build without auto-updates.`,\n {exit: 1},\n )\n // output.error with exit: 1 throws, but TypeScript doesn't know that\n return\n }\n\n const choice = await select({\n choices: [\n {\n name: 'Disable auto-updates for this build and continue',\n value: 'disable-auto-updates',\n },\n {name: 'Cancel build', value: 'cancel'},\n ],\n default: 'disable-auto-updates',\n message: styleText('yellow', prereleaseMessage),\n })\n\n if (choice === 'cancel') {\n output.error('Declined to continue with build', {exit: 1})\n // output.error with exit: 1 throws, but TypeScript doesn't know that\n return\n }\n\n output.warn('Auto-updates disabled for this build')\n}\n"],"names":["styleText","isInteractive","select","handlePrereleaseVersions","output","unattendedMode","unresolvedPrerelease","prereleaseMessage","map","mod","pkg","version","join","error","exit","choice","choices","name","value","default","message","warn"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAEnC,SAAQC,aAAa,QAAoB,mBAAkB;AAC3D,SAAQC,MAAM,QAAO,sBAAqB;AAI1C;;;;;;;CAOC,GACD,OAAO,eAAeC,yBAAyB,EAC7CC,MAAM,EACNC,cAAc,EACdC,oBAAoB,EAKrB;IACC,MAAMC,oBACJ,CAAC,mGAAmG,CAAC,GACrG,GAAGD,qBAAqBE,GAAG,CAAC,CAACC,MAAQ,CAAC,GAAG,EAAEA,IAAIC,GAAG,CAAC,EAAE,EAAED,IAAIE,OAAO,CAAC,CAAC,CAAC,EAAEC,IAAI,CAAC,MAAM,IAAI,CAAC,GACvF,CAAC,uFAAuF,CAAC,GACzF,CAAC,4DAA4D,CAAC;IAEhE,IAAIP,kBAAkB,CAACJ,iBAAiB;QACtCG,OAAOS,KAAK,CACV,GAAGN,kBAAkB,IAAI,CAAC,GACxB,CAAC,kFAAkF,CAAC,GACpF,CAAC,kGAAkG,CAAC,EACtG;YAACO,MAAM;QAAC;QAEV,qEAAqE;QACrE;IACF;IAEA,MAAMC,SAAS,MAAMb,OAAO;QAC1Bc,SAAS;YACP;gBACEC,MAAM;gBACNC,OAAO;YACT;YACA;gBAACD,MAAM;gBAAgBC,OAAO;YAAQ;SACvC;QACDC,SAAS;QACTC,SAASpB,UAAU,UAAUO;IAC/B;IAEA,IAAIQ,WAAW,UAAU;QACvBX,OAAOS,KAAK,CAAC,mCAAmC;YAACC,MAAM;QAAC;QACxD,qEAAqE;QACrE;IACF;IAEAV,OAAOiB,IAAI,CAAC;AACd"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/createStudioUserApplication.ts"],"sourcesContent":["import {CLIError} from '@oclif/core/errors'\nimport {input} from '@sanity/cli-core/ux'\n\nimport {createUserApplication, type UserApplication} from '../../services/userApplications.js'\nimport {deployDebug} from './deployDebug.js'\nimport {normalizeUrl, validateUrl} from './urlUtils.js'\n\n// TODO: replace with `Promise.withResolvers()` once it lands in node 22\nfunction promiseWithResolvers<T>() {\n let resolve!: (t: T) => void\n let reject!: (err: unknown) => void\n const promise = new Promise<T>((res, rej) => {\n resolve = res\n reject = rej\n })\n return {promise, reject, resolve}\n}\n\ninterface CreateStudioUserApplicationOptions {\n projectId: string\n\n urlType?: 'external' | 'internal'\n}\n\nexport async function createStudioUserApplication(options: CreateStudioUserApplicationOptions) {\n const {projectId, urlType = 'internal'} = options\n const {promise, resolve} = promiseWithResolvers<UserApplication>()\n\n const isExternal = urlType === 'external'\n\n await input({\n message: isExternal ? 'Studio URL (https://...):' : 'Studio hostname (<value>.sanity.studio):',\n // if a string is returned here, it is relayed to the user and prompt allows\n // the user to try again until this function returns true\n validate: async (inp: string) => {\n let appHost: string\n\n if (isExternal) {\n const normalized = normalizeUrl(inp)\n const validation = validateUrl(normalized)\n if (validation !== true) {\n return validation\n }\n appHost = normalized\n } else {\n appHost = inp.replace(/\\.sanity\\.studio$/i, '')\n }\n\n try {\n const response = await createUserApplication({\n appType: 'studio',\n body: {\n appHost,\n type: 'studio',\n urlType,\n },\n projectId,\n })\n resolve(response)\n return true\n } catch (e) {\n // if the name is taken, it should return a 409 so we relay to the user\n if ([402, 409].includes(e?.statusCode)) {\n return e?.response?.body?.message || 'Bad request' // just in case\n }\n\n deployDebug('Error creating user application', e)\n // otherwise, it's a fatal error\n throw new CLIError('Error creating user application', {exit: 1})\n }\n },\n })\n\n return await promise\n}\n"],"names":["CLIError","input","createUserApplication","deployDebug","normalizeUrl","validateUrl","promiseWithResolvers","resolve","reject","promise","Promise","res","rej","createStudioUserApplication","options","projectId","urlType","isExternal","message","validate","inp","appHost","normalized","validation","replace","response","appType","body","type","e","includes","statusCode","exit"],"mappings":"AAAA,SAAQA,QAAQ,QAAO,qBAAoB;AAC3C,SAAQC,KAAK,QAAO,sBAAqB;AAEzC,SAAQC,qBAAqB,QAA6B,qCAAoC;AAC9F,SAAQC,WAAW,QAAO,mBAAkB;AAC5C,SAAQC,YAAY,EAAEC,WAAW,QAAO,gBAAe;AAEvD,wEAAwE;AACxE,SAASC;IACP,IAAIC;IACJ,IAAIC;IACJ,MAAMC,UAAU,IAAIC,QAAW,CAACC,KAAKC;QACnCL,UAAUI;QACVH,SAASI;IACX;IACA,OAAO;QAACH;QAASD;QAAQD;IAAO;AAClC;AAQA,OAAO,eAAeM,4BAA4BC,OAA2C;IAC3F,MAAM,EAACC,SAAS,EAAEC,UAAU,UAAU,EAAC,GAAGF;IAC1C,MAAM,EAACL,OAAO,EAAEF,OAAO,EAAC,GAAGD;IAE3B,MAAMW,aAAaD,YAAY;IAE/B,MAAMf,MAAM;QACViB,SAASD,aAAa,8BAA8B;QACpD,4EAA4E;QAC5E,yDAAyD;QACzDE,UAAU,OAAOC;YACf,IAAIC;YAEJ,IAAIJ,YAAY;gBACd,MAAMK,aAAalB,aAAagB;gBAChC,MAAMG,aAAalB,YAAYiB;gBAC/B,IAAIC,eAAe,MAAM;oBACvB,OAAOA;gBACT;gBACAF,UAAUC;YACZ,OAAO;gBACLD,UAAUD,IAAII,OAAO,CAAC,sBAAsB;YAC9C;YAEA,IAAI;gBACF,MAAMC,WAAW,MAAMvB,sBAAsB;oBAC3CwB,SAAS;oBACTC,MAAM;wBACJN;wBACAO,MAAM;wBACNZ;oBACF;oBACAD;gBACF;gBACAR,QAAQkB;gBACR,OAAO;YACT,EAAE,OAAOI,GAAG;gBACV,uEAAuE;gBACvE,IAAI;oBAAC;oBAAK;iBAAI,CAACC,QAAQ,CAACD,GAAGE,aAAa;oBACtC,OAAOF,GAAGJ,UAAUE,MAAMT,WAAW,cAAc,eAAe;;gBACpE;gBAEAf,YAAY,mCAAmC0B;gBAC/C,gCAAgC;gBAChC,MAAM,IAAI7B,SAAS,mCAAmC;oBAACgC,MAAM;gBAAC;YAChE;QACF;IACF;IAEA,OAAO,MAAMvB;AACf"}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { input, spinner } from '@sanity/cli-core/ux';
|
|
2
|
-
import { customAlphabet } from 'nanoid';
|
|
3
|
-
import { createUserApplication } from '../../services/userApplications.js';
|
|
4
|
-
import { NO_ORGANIZATION_ID } from '../../util/errorMessages.js';
|
|
5
|
-
import { deployDebug } from './deployDebug.js';
|
|
6
|
-
export async function createUserApplicationForApp(organizationId) {
|
|
7
|
-
if (!organizationId) {
|
|
8
|
-
throw new Error(NO_ORGANIZATION_ID);
|
|
9
|
-
}
|
|
10
|
-
// First get the title from the user
|
|
11
|
-
const title = await input({
|
|
12
|
-
message: 'Enter a title for your application:',
|
|
13
|
-
validate: (input)=>input.length > 0 || 'Title is required'
|
|
14
|
-
});
|
|
15
|
-
return tryCreateApp(title, organizationId);
|
|
16
|
-
}
|
|
17
|
-
// appHosts have some restrictions (no uppercase, must start with a letter)
|
|
18
|
-
const generateId = ()=>{
|
|
19
|
-
const letters = 'abcdefghijklmnopqrstuvwxyz';
|
|
20
|
-
const firstChar = customAlphabet(letters, 1)();
|
|
21
|
-
const rest = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 11)();
|
|
22
|
-
return `${firstChar}${rest}`;
|
|
23
|
-
};
|
|
24
|
-
const tryCreateApp = async (title, organizationId)=>{
|
|
25
|
-
// we will likely prepend this with an org ID or other parameter in the future
|
|
26
|
-
const appHost = generateId();
|
|
27
|
-
const spin = spinner('Creating application').start();
|
|
28
|
-
try {
|
|
29
|
-
const response = await createUserApplication({
|
|
30
|
-
appType: 'coreApp',
|
|
31
|
-
body: {
|
|
32
|
-
appHost,
|
|
33
|
-
title,
|
|
34
|
-
type: 'coreApp',
|
|
35
|
-
urlType: 'internal'
|
|
36
|
-
},
|
|
37
|
-
organizationId
|
|
38
|
-
});
|
|
39
|
-
spin.succeed();
|
|
40
|
-
return response;
|
|
41
|
-
} catch (e) {
|
|
42
|
-
// if the name is taken, generate a new one and try again
|
|
43
|
-
if ([
|
|
44
|
-
402,
|
|
45
|
-
409
|
|
46
|
-
].includes(e?.statusCode)) {
|
|
47
|
-
deployDebug('App host taken, retrying with new host');
|
|
48
|
-
return tryCreateApp(title, organizationId);
|
|
49
|
-
}
|
|
50
|
-
spin.fail();
|
|
51
|
-
deployDebug('Error creating core application', e);
|
|
52
|
-
throw e;
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
//# sourceMappingURL=createUserApplicationForApp.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/createUserApplicationForApp.ts"],"sourcesContent":["import {input, spinner} from '@sanity/cli-core/ux'\nimport {customAlphabet} from 'nanoid'\n\nimport {createUserApplication, type UserApplication} from '../../services/userApplications.js'\nimport {NO_ORGANIZATION_ID} from '../../util/errorMessages.js'\nimport {deployDebug} from './deployDebug.js'\n\nexport async function createUserApplicationForApp(\n organizationId?: string,\n): Promise<UserApplication> {\n if (!organizationId) {\n throw new Error(NO_ORGANIZATION_ID)\n }\n\n // First get the title from the user\n const title = await input({\n message: 'Enter a title for your application:',\n validate: (input: string) => input.length > 0 || 'Title is required',\n })\n\n return tryCreateApp(title, organizationId)\n}\n\n// appHosts have some restrictions (no uppercase, must start with a letter)\nconst generateId = () => {\n const letters = 'abcdefghijklmnopqrstuvwxyz'\n const firstChar = customAlphabet(letters, 1)()\n const rest = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 11)()\n return `${firstChar}${rest}`\n}\n\nconst tryCreateApp = async (title: string, organizationId: string) => {\n // we will likely prepend this with an org ID or other parameter in the future\n const appHost = generateId()\n\n const spin = spinner('Creating application').start()\n\n try {\n const response = await createUserApplication({\n appType: 'coreApp',\n body: {\n appHost,\n title,\n type: 'coreApp',\n urlType: 'internal',\n },\n organizationId,\n })\n\n spin.succeed()\n return response\n } catch (e) {\n // if the name is taken, generate a new one and try again\n if ([402, 409].includes(e?.statusCode)) {\n deployDebug('App host taken, retrying with new host')\n return tryCreateApp(title, organizationId)\n }\n\n spin.fail()\n\n deployDebug('Error creating core application', e)\n throw e\n }\n}\n"],"names":["input","spinner","customAlphabet","createUserApplication","NO_ORGANIZATION_ID","deployDebug","createUserApplicationForApp","organizationId","Error","title","message","validate","length","tryCreateApp","generateId","letters","firstChar","rest","appHost","spin","start","response","appType","body","type","urlType","succeed","e","includes","statusCode","fail"],"mappings":"AAAA,SAAQA,KAAK,EAAEC,OAAO,QAAO,sBAAqB;AAClD,SAAQC,cAAc,QAAO,SAAQ;AAErC,SAAQC,qBAAqB,QAA6B,qCAAoC;AAC9F,SAAQC,kBAAkB,QAAO,8BAA6B;AAC9D,SAAQC,WAAW,QAAO,mBAAkB;AAE5C,OAAO,eAAeC,4BACpBC,cAAuB;IAEvB,IAAI,CAACA,gBAAgB;QACnB,MAAM,IAAIC,MAAMJ;IAClB;IAEA,oCAAoC;IACpC,MAAMK,QAAQ,MAAMT,MAAM;QACxBU,SAAS;QACTC,UAAU,CAACX,QAAkBA,MAAMY,MAAM,GAAG,KAAK;IACnD;IAEA,OAAOC,aAAaJ,OAAOF;AAC7B;AAEA,2EAA2E;AAC3E,MAAMO,aAAa;IACjB,MAAMC,UAAU;IAChB,MAAMC,YAAYd,eAAea,SAAS;IAC1C,MAAME,OAAOf,eAAe,wCAAwC;IACpE,OAAO,GAAGc,YAAYC,MAAM;AAC9B;AAEA,MAAMJ,eAAe,OAAOJ,OAAeF;IACzC,8EAA8E;IAC9E,MAAMW,UAAUJ;IAEhB,MAAMK,OAAOlB,QAAQ,wBAAwBmB,KAAK;IAElD,IAAI;QACF,MAAMC,WAAW,MAAMlB,sBAAsB;YAC3CmB,SAAS;YACTC,MAAM;gBACJL;gBACAT;gBACAe,MAAM;gBACNC,SAAS;YACX;YACAlB;QACF;QAEAY,KAAKO,OAAO;QACZ,OAAOL;IACT,EAAE,OAAOM,GAAG;QACV,yDAAyD;QACzD,IAAI;YAAC;YAAK;SAAI,CAACC,QAAQ,CAACD,GAAGE,aAAa;YACtCxB,YAAY;YACZ,OAAOQ,aAAaJ,OAAOF;QAC7B;QAEAY,KAAKW,IAAI;QAETzB,YAAY,mCAAmCsB;QAC/C,MAAMA;IACR;AACF"}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Helper functions to find a user application for a Sanity application.
|
|
3
|
-
*/ import { select, Separator, spinner } from '@sanity/cli-core/ux';
|
|
4
|
-
import { getUserApplication, getUserApplications } from '../../services/userApplications.js';
|
|
5
|
-
import { checkForDeprecatedAppId, getAppId } from '../../util/appId.js';
|
|
6
|
-
import { deployDebug } from './deployDebug.js';
|
|
7
|
-
/**
|
|
8
|
-
* Find a user application for a Sanity application.
|
|
9
|
-
*/ export async function findUserApplicationForApp(options) {
|
|
10
|
-
const { cliConfig, organizationId, output } = options;
|
|
11
|
-
const spin = spinner('Checking application info...').start();
|
|
12
|
-
try {
|
|
13
|
-
checkForDeprecatedAppId({
|
|
14
|
-
cliConfig,
|
|
15
|
-
output
|
|
16
|
-
});
|
|
17
|
-
deployDebug('Checking for a user application as specified in the local app config');
|
|
18
|
-
const userApplication = await findUserApplication(options);
|
|
19
|
-
if (userApplication) {
|
|
20
|
-
deployDebug('Found a user application as configured');
|
|
21
|
-
spin.succeed();
|
|
22
|
-
return userApplication;
|
|
23
|
-
}
|
|
24
|
-
const appId = getAppId(cliConfig);
|
|
25
|
-
// If there's an appId in the application config but there's no userApplication,
|
|
26
|
-
// then the provided application ID doesn’t exist in the org
|
|
27
|
-
if (appId) {
|
|
28
|
-
spin.clear();
|
|
29
|
-
output.error('The `appId` provided in your configuration’s `deployment` object cannot be found in your organization', {
|
|
30
|
-
exit: 1,
|
|
31
|
-
suggestions: [
|
|
32
|
-
'Verify the appId in your configuration matches an existing application'
|
|
33
|
-
]
|
|
34
|
-
});
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
// Done checking local application info
|
|
38
|
-
// Update the spinner text to indicate the next operation
|
|
39
|
-
spin.text = 'No application ID configured; checking for existing applications...';
|
|
40
|
-
// Get a list of existing applications to select from.
|
|
41
|
-
// This will fail if the org ID is malformed or the user doesn’t have access to the org ID
|
|
42
|
-
const userApplications = await getUserApplications({
|
|
43
|
-
appType: 'coreApp',
|
|
44
|
-
organizationId
|
|
45
|
-
});
|
|
46
|
-
// If no applications are found, return null
|
|
47
|
-
if (!userApplications?.length) {
|
|
48
|
-
spin.info('No application ID configured');
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
// No app ID configured, done checking for existing applications;
|
|
52
|
-
// retain this spinner text for clarity
|
|
53
|
-
spin.info('No application ID configured');
|
|
54
|
-
// Enumerate the available applications
|
|
55
|
-
const choices = userApplications.map((app)=>({
|
|
56
|
-
name: app.title ?? app.appHost,
|
|
57
|
-
value: app.appHost
|
|
58
|
-
}));
|
|
59
|
-
// Ask the user to select an existing app or create a new one
|
|
60
|
-
const selected = await select({
|
|
61
|
-
choices: [
|
|
62
|
-
{
|
|
63
|
-
name: 'New application deployment',
|
|
64
|
-
value: 'NEW_APP'
|
|
65
|
-
},
|
|
66
|
-
new Separator(' ════ Existing applications: ════ '),
|
|
67
|
-
...choices
|
|
68
|
-
],
|
|
69
|
-
loop: false,
|
|
70
|
-
message: 'Would you like to create a new application deployment, or deploy to an existing one?',
|
|
71
|
-
pageSize: 10
|
|
72
|
-
});
|
|
73
|
-
// If the user wants to create a new deployed application, return null
|
|
74
|
-
if (selected === 'NEW_APP') {
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
return userApplications.find((app)=>app.appHost === selected);
|
|
78
|
-
} catch (error) {
|
|
79
|
-
// User can't access applications for the org
|
|
80
|
-
if (error?.statusCode === 403) {
|
|
81
|
-
spin.clear();
|
|
82
|
-
deployDebug('User does not have permission to get applications for the org, or the org ID is malformed/doesn’t exist', error);
|
|
83
|
-
output.error(`You don’t have permission to view applications for the configured organization ID ("${organizationId}")`, {
|
|
84
|
-
exit: 1,
|
|
85
|
-
suggestions: [
|
|
86
|
-
'Verify that you’ve entered the correct organization ID',
|
|
87
|
-
'Ask your Sanity organization’s admin to provide you with the proper permissions'
|
|
88
|
-
]
|
|
89
|
-
});
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
// We've failed for some other reason
|
|
93
|
-
spin.clear();
|
|
94
|
-
deployDebug('Error finding user application for app', error);
|
|
95
|
-
output.error(error);
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
function findUserApplication(options) {
|
|
100
|
-
const { cliConfig } = options;
|
|
101
|
-
const appId = getAppId(cliConfig);
|
|
102
|
-
if (!appId) {
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
105
|
-
return getUserApplication({
|
|
106
|
-
appId,
|
|
107
|
-
isSdkApp: true
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
//# sourceMappingURL=findUserApplicationForApp.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/findUserApplicationForApp.ts"],"sourcesContent":["/**\n * Helper functions to find a user application for a Sanity application.\n */\n\nimport {type CliConfig, type Output} from '@sanity/cli-core'\nimport {select, Separator, spinner} from '@sanity/cli-core/ux'\n\nimport {\n getUserApplication,\n getUserApplications,\n type UserApplication,\n} from '../../services/userApplications.js'\nimport {checkForDeprecatedAppId, getAppId} from '../../util/appId.js'\nimport {deployDebug} from './deployDebug.js'\n\ninterface FindUserApplicationForAppOptions {\n cliConfig: CliConfig\n organizationId: string\n output: Output\n}\n\n/**\n * Find a user application for a Sanity application.\n */\nexport async function findUserApplicationForApp(\n options: FindUserApplicationForAppOptions,\n): Promise<UserApplication | null> {\n const {cliConfig, organizationId, output} = options\n\n const spin = spinner('Checking application info...').start()\n\n try {\n checkForDeprecatedAppId({cliConfig, output})\n\n deployDebug('Checking for a user application as specified in the local app config')\n const userApplication = await findUserApplication(options)\n\n if (userApplication) {\n deployDebug('Found a user application as configured')\n spin.succeed()\n return userApplication\n }\n\n const appId = getAppId(cliConfig)\n\n // If there's an appId in the application config but there's no userApplication,\n // then the provided application ID doesn’t exist in the org\n if (appId) {\n spin.clear()\n output.error(\n 'The `appId` provided in your configuration’s `deployment` object cannot be found in your organization',\n {\n exit: 1,\n suggestions: ['Verify the appId in your configuration matches an existing application'],\n },\n )\n return null\n }\n\n // Done checking local application info\n // Update the spinner text to indicate the next operation\n spin.text = 'No application ID configured; checking for existing applications...'\n\n // Get a list of existing applications to select from.\n // This will fail if the org ID is malformed or the user doesn’t have access to the org ID\n const userApplications = await getUserApplications({\n appType: 'coreApp',\n organizationId,\n })\n\n // If no applications are found, return null\n if (!userApplications?.length) {\n spin.info('No application ID configured')\n return null\n }\n\n // No app ID configured, done checking for existing applications;\n // retain this spinner text for clarity\n spin.info('No application ID configured')\n\n // Enumerate the available applications\n const choices = userApplications.map((app) => ({\n name: app.title ?? app.appHost,\n value: app.appHost,\n }))\n\n // Ask the user to select an existing app or create a new one\n const selected = await select({\n choices: [\n {name: 'New application deployment', value: 'NEW_APP'},\n new Separator(' ════ Existing applications: ════ '),\n ...choices,\n ],\n loop: false,\n message:\n 'Would you like to create a new application deployment, or deploy to an existing one?',\n pageSize: 10,\n })\n\n // If the user wants to create a new deployed application, return null\n if (selected === 'NEW_APP') {\n return null\n }\n\n return userApplications.find((app) => app.appHost === selected)!\n } catch (error) {\n // User can't access applications for the org\n if (error?.statusCode === 403) {\n spin.clear()\n deployDebug(\n 'User does not have permission to get applications for the org, or the org ID is malformed/doesn’t exist',\n error,\n )\n output.error(\n `You don’t have permission to view applications for the configured organization ID (\"${organizationId}\")`,\n {\n exit: 1,\n suggestions: [\n 'Verify that you’ve entered the correct organization ID',\n 'Ask your Sanity organization’s admin to provide you with the proper permissions',\n ],\n },\n )\n return null\n }\n\n // We've failed for some other reason\n spin.clear()\n deployDebug('Error finding user application for app', error)\n output.error(error)\n return null\n }\n}\n\nfunction findUserApplication(\n options: FindUserApplicationForAppOptions,\n): Promise<UserApplication | null> | null {\n const {cliConfig} = options\n\n const appId = getAppId(cliConfig)\n\n if (!appId) {\n return null\n }\n\n return getUserApplication({appId, isSdkApp: true})\n}\n"],"names":["select","Separator","spinner","getUserApplication","getUserApplications","checkForDeprecatedAppId","getAppId","deployDebug","findUserApplicationForApp","options","cliConfig","organizationId","output","spin","start","userApplication","findUserApplication","succeed","appId","clear","error","exit","suggestions","text","userApplications","appType","length","info","choices","map","app","name","title","appHost","value","selected","loop","message","pageSize","find","statusCode","isSdkApp"],"mappings":"AAAA;;CAEC,GAGD,SAAQA,MAAM,EAAEC,SAAS,EAAEC,OAAO,QAAO,sBAAqB;AAE9D,SACEC,kBAAkB,EAClBC,mBAAmB,QAEd,qCAAoC;AAC3C,SAAQC,uBAAuB,EAAEC,QAAQ,QAAO,sBAAqB;AACrE,SAAQC,WAAW,QAAO,mBAAkB;AAQ5C;;CAEC,GACD,OAAO,eAAeC,0BACpBC,OAAyC;IAEzC,MAAM,EAACC,SAAS,EAAEC,cAAc,EAAEC,MAAM,EAAC,GAAGH;IAE5C,MAAMI,OAAOX,QAAQ,gCAAgCY,KAAK;IAE1D,IAAI;QACFT,wBAAwB;YAACK;YAAWE;QAAM;QAE1CL,YAAY;QACZ,MAAMQ,kBAAkB,MAAMC,oBAAoBP;QAElD,IAAIM,iBAAiB;YACnBR,YAAY;YACZM,KAAKI,OAAO;YACZ,OAAOF;QACT;QAEA,MAAMG,QAAQZ,SAASI;QAEvB,gFAAgF;QAChF,4DAA4D;QAC5D,IAAIQ,OAAO;YACTL,KAAKM,KAAK;YACVP,OAAOQ,KAAK,CACV,yGACA;gBACEC,MAAM;gBACNC,aAAa;oBAAC;iBAAyE;YACzF;YAEF,OAAO;QACT;QAEA,uCAAuC;QACvC,yDAAyD;QACzDT,KAAKU,IAAI,GAAG;QAEZ,sDAAsD;QACtD,0FAA0F;QAC1F,MAAMC,mBAAmB,MAAMpB,oBAAoB;YACjDqB,SAAS;YACTd;QACF;QAEA,4CAA4C;QAC5C,IAAI,CAACa,kBAAkBE,QAAQ;YAC7Bb,KAAKc,IAAI,CAAC;YACV,OAAO;QACT;QAEA,iEAAiE;QACjE,uCAAuC;QACvCd,KAAKc,IAAI,CAAC;QAEV,uCAAuC;QACvC,MAAMC,UAAUJ,iBAAiBK,GAAG,CAAC,CAACC,MAAS,CAAA;gBAC7CC,MAAMD,IAAIE,KAAK,IAAIF,IAAIG,OAAO;gBAC9BC,OAAOJ,IAAIG,OAAO;YACpB,CAAA;QAEA,6DAA6D;QAC7D,MAAME,WAAW,MAAMnC,OAAO;YAC5B4B,SAAS;gBACP;oBAACG,MAAM;oBAA8BG,OAAO;gBAAS;gBACrD,IAAIjC,UAAU;mBACX2B;aACJ;YACDQ,MAAM;YACNC,SACE;YACFC,UAAU;QACZ;QAEA,sEAAsE;QACtE,IAAIH,aAAa,WAAW;YAC1B,OAAO;QACT;QAEA,OAAOX,iBAAiBe,IAAI,CAAC,CAACT,MAAQA,IAAIG,OAAO,KAAKE;IACxD,EAAE,OAAOf,OAAO;QACd,6CAA6C;QAC7C,IAAIA,OAAOoB,eAAe,KAAK;YAC7B3B,KAAKM,KAAK;YACVZ,YACE,2GACAa;YAEFR,OAAOQ,KAAK,CACV,CAAC,oFAAoF,EAAET,eAAe,EAAE,CAAC,EACzG;gBACEU,MAAM;gBACNC,aAAa;oBACX;oBACA;iBACD;YACH;YAEF,OAAO;QACT;QAEA,qCAAqC;QACrCT,KAAKM,KAAK;QACVZ,YAAY,0CAA0Ca;QACtDR,OAAOQ,KAAK,CAACA;QACb,OAAO;IACT;AACF;AAEA,SAASJ,oBACPP,OAAyC;IAEzC,MAAM,EAACC,SAAS,EAAC,GAAGD;IAEpB,MAAMS,QAAQZ,SAASI;IAEvB,IAAI,CAACQ,OAAO;QACV,OAAO;IACT;IAEA,OAAOf,mBAAmB;QAACe;QAAOuB,UAAU;IAAI;AAClD"}
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Helper functions to find a user application for a Sanity studio.
|
|
3
|
-
*/ import { exitCodes } from '@sanity/cli-core';
|
|
4
|
-
import { select, Separator, spinner } from '@sanity/cli-core/ux';
|
|
5
|
-
import { createUserApplication, getUserApplication, getUserApplications } from '../../services/userApplications.js';
|
|
6
|
-
import { deployDebug } from './deployDebug.js';
|
|
7
|
-
import { normalizeUrl, validateUrl } from './urlUtils.js';
|
|
8
|
-
export async function findUserApplicationForStudio(options) {
|
|
9
|
-
const { appHost, appId, output, projectId, unattended = false, urlType = 'internal' } = options;
|
|
10
|
-
const spin = spinner('Checking project info').start();
|
|
11
|
-
const userApplication = await findUserApplication({
|
|
12
|
-
appHost,
|
|
13
|
-
appId,
|
|
14
|
-
output,
|
|
15
|
-
projectId,
|
|
16
|
-
spin,
|
|
17
|
-
urlType
|
|
18
|
-
});
|
|
19
|
-
spin.succeed();
|
|
20
|
-
if (userApplication) {
|
|
21
|
-
return userApplication;
|
|
22
|
-
}
|
|
23
|
-
// No user application found, so let's list out the existing user applications
|
|
24
|
-
// along with an option to create a new one
|
|
25
|
-
let userApplications = [];
|
|
26
|
-
// Get existing user applications (if any),
|
|
27
|
-
// based on the configured project ID
|
|
28
|
-
if (projectId) {
|
|
29
|
-
const allApps = await getUserApplications({
|
|
30
|
-
appType: 'studio',
|
|
31
|
-
projectId
|
|
32
|
-
});
|
|
33
|
-
// Filter by urlType so external deploys only see external studios and vice versa
|
|
34
|
-
userApplications = allApps?.filter((app)=>app.urlType === urlType) ?? [];
|
|
35
|
-
}
|
|
36
|
-
// If no applications are found, return null
|
|
37
|
-
if (!userApplications?.length) {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
// In unattended mode, we can't prompt the user to select a studio.
|
|
41
|
-
// Return null and let the caller handle the error messaging.
|
|
42
|
-
if (unattended) {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
// If there are user applications, allow the user to select one of the existing host names,
|
|
46
|
-
// or to create a new one
|
|
47
|
-
const newLabel = urlType === 'external' ? 'Register new external studio URL' : 'Create new studio hostname';
|
|
48
|
-
const selectMessage = urlType === 'external' ? 'Select existing external studio, or register a new one' : 'Select existing studio hostname, or create a new one';
|
|
49
|
-
const choices = userApplications.map((app)=>({
|
|
50
|
-
name: app.title ?? app.appHost,
|
|
51
|
-
value: app.appHost
|
|
52
|
-
}));
|
|
53
|
-
const selected = await select({
|
|
54
|
-
choices: [
|
|
55
|
-
{
|
|
56
|
-
name: newLabel,
|
|
57
|
-
value: 'NEW_STUDIO'
|
|
58
|
-
},
|
|
59
|
-
new Separator(),
|
|
60
|
-
...choices
|
|
61
|
-
],
|
|
62
|
-
message: selectMessage
|
|
63
|
-
});
|
|
64
|
-
// If the user wants to create a new deployed application, return null
|
|
65
|
-
if (selected === 'NEW_STUDIO') {
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
// Otherwise, return the selected user application
|
|
69
|
-
return userApplications.find((app)=>app.appHost === selected);
|
|
70
|
-
}
|
|
71
|
-
async function findUserApplication(options) {
|
|
72
|
-
const { appHost, appId, output, projectId, urlType } = options;
|
|
73
|
-
let { spin } = options;
|
|
74
|
-
let userApplication;
|
|
75
|
-
// If the config has an appId, check for apps with that ID
|
|
76
|
-
if (appId) {
|
|
77
|
-
try {
|
|
78
|
-
userApplication = await getUserApplication({
|
|
79
|
-
appId,
|
|
80
|
-
isSdkApp: false,
|
|
81
|
-
projectId
|
|
82
|
-
});
|
|
83
|
-
if (userApplication) {
|
|
84
|
-
return userApplication;
|
|
85
|
-
}
|
|
86
|
-
// If appID is specified but no app is found with it, throw an error
|
|
87
|
-
throw new Error(`Cannot find app with app ID ${appId}`);
|
|
88
|
-
} catch (error) {
|
|
89
|
-
spin.fail();
|
|
90
|
-
deployDebug('Error finding user application', error);
|
|
91
|
-
output.error(`Error finding user application: ${error?.message}`, {
|
|
92
|
-
exit: 1
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
// As a fallback, if studioHost (deprecated) is configured, check for apps with that host
|
|
97
|
-
if (appHost) {
|
|
98
|
-
// For external URLs, validate and normalize before lookup/creation
|
|
99
|
-
const resolvedHost = urlType === 'external' ? normalizeUrl(appHost) : appHost;
|
|
100
|
-
if (urlType === 'external') {
|
|
101
|
-
const validation = validateUrl(resolvedHost);
|
|
102
|
-
if (validation !== true) {
|
|
103
|
-
spin.fail();
|
|
104
|
-
output.error(validation, {
|
|
105
|
-
exit: exitCodes.USAGE_ERROR
|
|
106
|
-
});
|
|
107
|
-
return null;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
try {
|
|
111
|
-
userApplication = await getUserApplication({
|
|
112
|
-
appHost: resolvedHost,
|
|
113
|
-
isSdkApp: false,
|
|
114
|
-
projectId
|
|
115
|
-
});
|
|
116
|
-
// We've found the application — return it
|
|
117
|
-
if (userApplication) {
|
|
118
|
-
return userApplication;
|
|
119
|
-
}
|
|
120
|
-
// Otherwise, try to create an app with the configured host
|
|
121
|
-
try {
|
|
122
|
-
if (urlType === 'external') {
|
|
123
|
-
output.log('Your project has not been registered with an external studio URL.');
|
|
124
|
-
output.log(`Registering ${resolvedHost}`);
|
|
125
|
-
} else {
|
|
126
|
-
output.log('Your project has not been assigned a studio hostname.');
|
|
127
|
-
output.log(`Creating https://${resolvedHost}.sanity.studio`);
|
|
128
|
-
}
|
|
129
|
-
output.log('');
|
|
130
|
-
spin = spinner(urlType === 'external' ? 'Registering external studio' : 'Creating studio hostname').start();
|
|
131
|
-
const response = await createUserApplication({
|
|
132
|
-
appType: 'studio',
|
|
133
|
-
body: {
|
|
134
|
-
appHost: resolvedHost,
|
|
135
|
-
type: 'studio',
|
|
136
|
-
urlType
|
|
137
|
-
},
|
|
138
|
-
projectId
|
|
139
|
-
});
|
|
140
|
-
spin.succeed();
|
|
141
|
-
return response;
|
|
142
|
-
} catch (e) {
|
|
143
|
-
spin.fail();
|
|
144
|
-
// if the name is taken, it should return a 409 so we relay to the user
|
|
145
|
-
if ([
|
|
146
|
-
402,
|
|
147
|
-
409
|
|
148
|
-
].includes(e?.statusCode)) {
|
|
149
|
-
output.error(e?.response?.body?.message || 'Bad request', {
|
|
150
|
-
exit: 1
|
|
151
|
-
});
|
|
152
|
-
return null;
|
|
153
|
-
}
|
|
154
|
-
// otherwise, it's a fatal error
|
|
155
|
-
deployDebug('Error creating user application from config', e);
|
|
156
|
-
output.error(`Error creating user application from config: ${e instanceof Error ? e.message : e}`, {
|
|
157
|
-
exit: 1
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
} catch (error) {
|
|
161
|
-
spin.fail();
|
|
162
|
-
deployDebug('Error finding user application', error);
|
|
163
|
-
output.error(`Error finding user application: ${error instanceof Error ? error.message : error.toString()}`, {
|
|
164
|
-
exit: 1
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
// If no appID and no appHost, just return and proceed to check for studios with the project ID
|
|
169
|
-
return null;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
//# sourceMappingURL=findUserApplicationForStudio.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/findUserApplicationForStudio.ts"],"sourcesContent":["/**\n * Helper functions to find a user application for a Sanity studio.\n */\n\nimport {exitCodes, type Output} from '@sanity/cli-core'\nimport {select, Separator, spinner, type SpinnerInstance} from '@sanity/cli-core/ux'\n\nimport {\n createUserApplication,\n getUserApplication,\n getUserApplications,\n type UserApplication,\n} from '../../services/userApplications.js'\nimport {deployDebug} from './deployDebug.js'\nimport {normalizeUrl, validateUrl} from './urlUtils.js'\n\ninterface FindUserApplicationForStudioOptions {\n output: Output\n projectId: string\n\n appHost?: string\n appId?: string\n unattended?: boolean\n urlType?: 'external' | 'internal'\n}\n\nexport async function findUserApplicationForStudio(options: FindUserApplicationForStudioOptions) {\n const {appHost, appId, output, projectId, unattended = false, urlType = 'internal'} = options\n\n const spin = spinner('Checking project info').start()\n\n const userApplication = await findUserApplication({\n appHost,\n appId,\n output,\n projectId,\n spin,\n urlType,\n })\n\n spin.succeed()\n\n if (userApplication) {\n return userApplication\n }\n\n // No user application found, so let's list out the existing user applications\n // along with an option to create a new one\n let userApplications: Array<UserApplication> = []\n\n // Get existing user applications (if any),\n // based on the configured project ID\n if (projectId) {\n const allApps = await getUserApplications({\n appType: 'studio',\n projectId,\n })\n // Filter by urlType so external deploys only see external studios and vice versa\n userApplications = allApps?.filter((app) => app.urlType === urlType) ?? []\n }\n\n // If no applications are found, return null\n if (!userApplications?.length) {\n return null\n }\n\n // In unattended mode, we can't prompt the user to select a studio.\n // Return null and let the caller handle the error messaging.\n if (unattended) {\n return null\n }\n\n // If there are user applications, allow the user to select one of the existing host names,\n // or to create a new one\n const newLabel =\n urlType === 'external' ? 'Register new external studio URL' : 'Create new studio hostname'\n const selectMessage =\n urlType === 'external'\n ? 'Select existing external studio, or register a new one'\n : 'Select existing studio hostname, or create a new one'\n\n const choices = userApplications.map((app) => ({\n name: app.title ?? app.appHost,\n value: app.appHost,\n }))\n\n const selected = await select({\n choices: [{name: newLabel, value: 'NEW_STUDIO'}, new Separator(), ...choices],\n message: selectMessage,\n })\n\n // If the user wants to create a new deployed application, return null\n if (selected === 'NEW_STUDIO') {\n return null\n }\n\n // Otherwise, return the selected user application\n return userApplications.find((app) => app.appHost === selected)!\n}\n\ninterface FindUserApplicationFromConfigOptions {\n output: Output\n projectId: string\n spin: SpinnerInstance\n urlType: 'external' | 'internal'\n\n appHost?: string\n appId?: string\n}\n\nasync function findUserApplication(\n options: FindUserApplicationFromConfigOptions,\n): Promise<UserApplication | null> {\n const {appHost, appId, output, projectId, urlType} = options\n let {spin} = options\n\n let userApplication: UserApplication | null\n\n // If the config has an appId, check for apps with that ID\n if (appId) {\n try {\n userApplication = await getUserApplication({appId, isSdkApp: false, projectId})\n\n if (userApplication) {\n return userApplication\n }\n\n // If appID is specified but no app is found with it, throw an error\n throw new Error(`Cannot find app with app ID ${appId}`)\n } catch (error) {\n spin.fail()\n deployDebug('Error finding user application', error)\n output.error(`Error finding user application: ${error?.message}`, {exit: 1})\n }\n }\n\n // As a fallback, if studioHost (deprecated) is configured, check for apps with that host\n if (appHost) {\n // For external URLs, validate and normalize before lookup/creation\n const resolvedHost = urlType === 'external' ? normalizeUrl(appHost) : appHost\n\n if (urlType === 'external') {\n const validation = validateUrl(resolvedHost)\n if (validation !== true) {\n spin.fail()\n output.error(validation, {exit: exitCodes.USAGE_ERROR})\n return null\n }\n }\n\n try {\n userApplication = await getUserApplication({\n appHost: resolvedHost,\n isSdkApp: false,\n projectId,\n })\n\n // We've found the application — return it\n if (userApplication) {\n return userApplication\n }\n\n // Otherwise, try to create an app with the configured host\n try {\n if (urlType === 'external') {\n output.log('Your project has not been registered with an external studio URL.')\n output.log(`Registering ${resolvedHost}`)\n } else {\n output.log('Your project has not been assigned a studio hostname.')\n output.log(`Creating https://${resolvedHost}.sanity.studio`)\n }\n output.log('')\n spin = spinner(\n urlType === 'external' ? 'Registering external studio' : 'Creating studio hostname',\n ).start()\n\n const response = await createUserApplication({\n appType: 'studio',\n body: {\n appHost: resolvedHost,\n type: 'studio',\n urlType,\n },\n projectId,\n })\n spin.succeed()\n\n return response\n } catch (e) {\n spin.fail()\n // if the name is taken, it should return a 409 so we relay to the user\n if ([402, 409].includes(e?.statusCode)) {\n output.error(e?.response?.body?.message || 'Bad request', {exit: 1})\n return null\n }\n // otherwise, it's a fatal error\n deployDebug('Error creating user application from config', e)\n output.error(\n `Error creating user application from config: ${e instanceof Error ? e.message : e}`,\n {exit: 1},\n )\n }\n } catch (error) {\n spin.fail()\n deployDebug('Error finding user application', error)\n output.error(\n `Error finding user application: ${error instanceof Error ? error.message : error.toString()}`,\n {exit: 1},\n )\n }\n }\n\n // If no appID and no appHost, just return and proceed to check for studios with the project ID\n return null\n}\n"],"names":["exitCodes","select","Separator","spinner","createUserApplication","getUserApplication","getUserApplications","deployDebug","normalizeUrl","validateUrl","findUserApplicationForStudio","options","appHost","appId","output","projectId","unattended","urlType","spin","start","userApplication","findUserApplication","succeed","userApplications","allApps","appType","filter","app","length","newLabel","selectMessage","choices","map","name","title","value","selected","message","find","isSdkApp","Error","error","fail","exit","resolvedHost","validation","USAGE_ERROR","log","response","body","type","e","includes","statusCode","toString"],"mappings":"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"}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod/mini';
|
|
2
|
-
/**
|
|
3
|
-
* A view record as persisted to the application service: `type`, `name`, `src`,
|
|
4
|
-
* plus any view-type-specific attributes (passed through for storage).
|
|
5
|
-
*/ const viewRecordSchema = z.looseObject({
|
|
6
|
-
name: z.string().check(z.regex(/^[a-zA-Z0-9_-]+$/, 'View `name` must match /^[a-zA-Z0-9_-]+$/')),
|
|
7
|
-
src: z.string(),
|
|
8
|
-
type: z.enum([
|
|
9
|
-
'panel'
|
|
10
|
-
])
|
|
11
|
-
});
|
|
12
|
-
/**
|
|
13
|
-
* Payload registering an app's views with the application service on deploy.
|
|
14
|
-
*
|
|
15
|
-
* Phase 1 stub: the service that stores views does not exist yet, so the
|
|
16
|
-
* payload is validated and logged only — never sent. Builds the contract the
|
|
17
|
-
* application-service endpoint will accept.
|
|
18
|
-
*/ const viewDeploymentPayloadSchema = z.object({
|
|
19
|
-
applicationId: z.string(),
|
|
20
|
-
views: z.array(viewRecordSchema)
|
|
21
|
-
});
|
|
22
|
-
/**
|
|
23
|
-
* Validate an app's declared views into the application-service payload.
|
|
24
|
-
* Throws (via Zod) when a view declaration is malformed.
|
|
25
|
-
*/ export function buildViewDeploymentPayload(input) {
|
|
26
|
-
return viewDeploymentPayloadSchema.parse({
|
|
27
|
-
applicationId: input.applicationId,
|
|
28
|
-
views: input.views ?? []
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
//# sourceMappingURL=viewDeployment.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/viewDeployment.ts"],"sourcesContent":["import {z} from 'zod/mini'\n\n/**\n * A view record as persisted to the application service: `type`, `name`, `src`,\n * plus any view-type-specific attributes (passed through for storage).\n */\nconst viewRecordSchema = z.looseObject({\n name: z.string().check(z.regex(/^[a-zA-Z0-9_-]+$/, 'View `name` must match /^[a-zA-Z0-9_-]+$/')),\n src: z.string(),\n type: z.enum(['panel']),\n})\n\n/**\n * Payload registering an app's views with the application service on deploy.\n *\n * Phase 1 stub: the service that stores views does not exist yet, so the\n * payload is validated and logged only — never sent. Builds the contract the\n * application-service endpoint will accept.\n */\nconst viewDeploymentPayloadSchema = z.object({\n applicationId: z.string(),\n views: z.array(viewRecordSchema),\n})\n\ntype ViewDeploymentPayload = z.infer<typeof viewDeploymentPayloadSchema>\n\n/**\n * Validate an app's declared views into the application-service payload.\n * Throws (via Zod) when a view declaration is malformed.\n */\nexport function buildViewDeploymentPayload(input: {\n applicationId: string\n views?: ReadonlyArray<Record<string, unknown>>\n}): ViewDeploymentPayload {\n return viewDeploymentPayloadSchema.parse({\n applicationId: input.applicationId,\n views: input.views ?? [],\n })\n}\n"],"names":["z","viewRecordSchema","looseObject","name","string","check","regex","src","type","enum","viewDeploymentPayloadSchema","object","applicationId","views","array","buildViewDeploymentPayload","input","parse"],"mappings":"AAAA,SAAQA,CAAC,QAAO,WAAU;AAE1B;;;CAGC,GACD,MAAMC,mBAAmBD,EAAEE,WAAW,CAAC;IACrCC,MAAMH,EAAEI,MAAM,GAAGC,KAAK,CAACL,EAAEM,KAAK,CAAC,oBAAoB;IACnDC,KAAKP,EAAEI,MAAM;IACbI,MAAMR,EAAES,IAAI,CAAC;QAAC;KAAQ;AACxB;AAEA;;;;;;CAMC,GACD,MAAMC,8BAA8BV,EAAEW,MAAM,CAAC;IAC3CC,eAAeZ,EAAEI,MAAM;IACvBS,OAAOb,EAAEc,KAAK,CAACb;AACjB;AAIA;;;CAGC,GACD,OAAO,SAASc,2BAA2BC,KAG1C;IACC,OAAON,4BAA4BO,KAAK,CAAC;QACvCL,eAAeI,MAAMJ,aAAa;QAClCC,OAAOG,MAAMH,KAAK,IAAI,EAAE;IAC1B;AACF"}
|