@sanity/cli 7.8.0 → 7.10.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 +132 -0
- package/dist/actions/auth/login/getProvider.js +7 -2
- package/dist/actions/auth/login/getProvider.js.map +1 -1
- package/dist/actions/dataset/create.js +2 -2
- package/dist/actions/dataset/create.js.map +1 -1
- package/dist/actions/deploy/createUserApplication.js +8 -5
- package/dist/actions/deploy/createUserApplication.js.map +1 -1
- package/dist/actions/deploy/deployApp.js +43 -20
- package/dist/actions/deploy/deployApp.js.map +1 -1
- package/dist/actions/deploy/deployChecks.js +9 -8
- package/dist/actions/deploy/deployChecks.js.map +1 -1
- package/dist/actions/deploy/deployStudio.js +12 -9
- package/dist/actions/deploy/deployStudio.js.map +1 -1
- package/dist/actions/deploy/resolveDeployTarget.js +3 -2
- package/dist/actions/deploy/resolveDeployTarget.js.map +1 -1
- package/dist/actions/deploy/urlUtils.js +0 -4
- package/dist/actions/deploy/urlUtils.js.map +1 -1
- package/dist/actions/documents/types.js.map +1 -1
- package/dist/actions/documents/validate.js +2 -1
- package/dist/actions/documents/validate.js.map +1 -1
- package/dist/actions/manifest/extractCoreAppManifest.js +6 -1
- package/dist/actions/manifest/extractCoreAppManifest.js.map +1 -1
- package/dist/actions/organizations/getOrganization.js +7 -3
- package/dist/actions/organizations/getOrganization.js.map +1 -1
- package/dist/actions/organizations/validateOrganizationSlug.js +20 -0
- package/dist/actions/organizations/validateOrganizationSlug.js.map +1 -0
- package/dist/actions/undeploy/adapters.js +3 -3
- package/dist/actions/undeploy/adapters.js.map +1 -1
- package/dist/actions/undeploy/runUndeploy.js +20 -6
- package/dist/actions/undeploy/runUndeploy.js.map +1 -1
- package/dist/actions/undeploy/undeployPlan.js +18 -3
- package/dist/actions/undeploy/undeployPlan.js.map +1 -1
- package/dist/commands/documents/validate.js +18 -17
- package/dist/commands/documents/validate.js.map +1 -1
- package/dist/commands/hooks/create.js +4 -0
- package/dist/commands/hooks/create.js.map +1 -1
- package/dist/commands/hooks/delete.js +5 -0
- package/dist/commands/hooks/delete.js.map +1 -1
- package/dist/commands/hooks/logs.js +5 -0
- package/dist/commands/hooks/logs.js.map +1 -1
- package/dist/commands/install.js +1 -1
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/organizations/create.js +79 -0
- package/dist/commands/organizations/create.js.map +1 -0
- package/dist/commands/organizations/delete.js +100 -0
- package/dist/commands/organizations/delete.js.map +1 -0
- package/dist/commands/organizations/get.js +48 -0
- package/dist/commands/organizations/get.js.map +1 -0
- package/dist/commands/organizations/list.js +60 -0
- package/dist/commands/organizations/list.js.map +1 -0
- package/dist/commands/organizations/update.js +115 -0
- package/dist/commands/organizations/update.js.map +1 -0
- package/dist/commands/projects/create.js +2 -1
- package/dist/commands/projects/create.js.map +1 -1
- package/dist/commands/undeploy.js +13 -1
- package/dist/commands/undeploy.js.map +1 -1
- package/dist/prompts/promptForOrganizationName.js +2 -1
- package/dist/prompts/promptForOrganizationName.js.map +1 -1
- package/dist/server/devServer.js.map +1 -1
- package/dist/services/organizations.js +45 -2
- package/dist/services/organizations.js.map +1 -1
- package/dist/services/userApplications.js.map +1 -1
- package/dist/topicAliases.js +7 -0
- package/dist/topicAliases.js.map +1 -1
- package/dist/util/organizationAliases.js +12 -0
- package/dist/util/organizationAliases.js.map +1 -0
- package/oclif.config.js +1 -0
- package/oclif.manifest.json +1342 -1094
- package/package.json +27 -27
package/README.md
CHANGED
|
@@ -6,6 +6,7 @@ Code for sanity cli
|
|
|
6
6
|
|
|
7
7
|
- [@sanity/cli](#sanitycli)
|
|
8
8
|
- [Commands](#commands)
|
|
9
|
+
|
|
9
10
|
<!-- tocstop -->
|
|
10
11
|
|
|
11
12
|
# Commands
|
|
@@ -95,6 +96,11 @@ Code for sanity cli
|
|
|
95
96
|
- [`sanity migrations run [ID]`](#sanity-migrations-run-id)
|
|
96
97
|
- [`sanity openapi get SLUG`](#sanity-openapi-get-slug)
|
|
97
98
|
- [`sanity openapi list`](#sanity-openapi-list)
|
|
99
|
+
- [`sanity organizations create`](#sanity-organizations-create)
|
|
100
|
+
- [`sanity organizations delete ORGANIZATIONID`](#sanity-organizations-delete-organizationid)
|
|
101
|
+
- [`sanity organizations get ORGANIZATIONID`](#sanity-organizations-get-organizationid)
|
|
102
|
+
- [`sanity organizations list`](#sanity-organizations-list)
|
|
103
|
+
- [`sanity organizations update ORGANIZATIONID`](#sanity-organizations-update-organizationid)
|
|
98
104
|
- [`sanity preview [OUTPUTDIR]`](#sanity-preview-outputdir)
|
|
99
105
|
- [`sanity projects create [PROJECTNAME]`](#sanity-projects-create-projectname)
|
|
100
106
|
- [`sanity projects list`](#sanity-projects-list)
|
|
@@ -2919,6 +2925,132 @@ EXAMPLES
|
|
|
2919
2925
|
$ sanity openapi list --web
|
|
2920
2926
|
```
|
|
2921
2927
|
|
|
2928
|
+
## `sanity organizations create`
|
|
2929
|
+
|
|
2930
|
+
Create a new organization
|
|
2931
|
+
|
|
2932
|
+
```
|
|
2933
|
+
USAGE
|
|
2934
|
+
$ sanity organizations create [--default-role <value>] [--name <value>]
|
|
2935
|
+
|
|
2936
|
+
FLAGS
|
|
2937
|
+
--default-role=<value> Default role assigned to new members
|
|
2938
|
+
--name=<value> Organization name
|
|
2939
|
+
|
|
2940
|
+
DESCRIPTION
|
|
2941
|
+
Create a new organization
|
|
2942
|
+
|
|
2943
|
+
EXAMPLES
|
|
2944
|
+
Interactively create an organization
|
|
2945
|
+
|
|
2946
|
+
$ sanity organizations create
|
|
2947
|
+
|
|
2948
|
+
Create an organization named "Acme Corp"
|
|
2949
|
+
|
|
2950
|
+
$ sanity organizations create --name "Acme Corp"
|
|
2951
|
+
|
|
2952
|
+
Create an organization with a default member role
|
|
2953
|
+
|
|
2954
|
+
$ sanity organizations create --name "Acme Corp" --default-role member
|
|
2955
|
+
```
|
|
2956
|
+
|
|
2957
|
+
## `sanity organizations delete ORGANIZATIONID`
|
|
2958
|
+
|
|
2959
|
+
Delete an organization
|
|
2960
|
+
|
|
2961
|
+
```
|
|
2962
|
+
USAGE
|
|
2963
|
+
$ sanity organizations delete ORGANIZATIONID [--force]
|
|
2964
|
+
|
|
2965
|
+
ARGUMENTS
|
|
2966
|
+
ORGANIZATIONID Organization ID to delete
|
|
2967
|
+
|
|
2968
|
+
FLAGS
|
|
2969
|
+
--force Do not prompt for delete confirmation - forcefully delete
|
|
2970
|
+
|
|
2971
|
+
DESCRIPTION
|
|
2972
|
+
Delete an organization
|
|
2973
|
+
|
|
2974
|
+
EXAMPLES
|
|
2975
|
+
Delete an organization (prompts for confirmation)
|
|
2976
|
+
|
|
2977
|
+
$ sanity organizations delete org-abc123
|
|
2978
|
+
|
|
2979
|
+
Delete an organization without confirmation
|
|
2980
|
+
|
|
2981
|
+
$ sanity organizations delete org-abc123 --force
|
|
2982
|
+
```
|
|
2983
|
+
|
|
2984
|
+
## `sanity organizations get ORGANIZATIONID`
|
|
2985
|
+
|
|
2986
|
+
Get details of an organization
|
|
2987
|
+
|
|
2988
|
+
```
|
|
2989
|
+
USAGE
|
|
2990
|
+
$ sanity organizations get ORGANIZATIONID
|
|
2991
|
+
|
|
2992
|
+
ARGUMENTS
|
|
2993
|
+
ORGANIZATIONID Organization ID
|
|
2994
|
+
|
|
2995
|
+
DESCRIPTION
|
|
2996
|
+
Get details of an organization
|
|
2997
|
+
|
|
2998
|
+
EXAMPLES
|
|
2999
|
+
Get details of a specific organization
|
|
3000
|
+
|
|
3001
|
+
$ sanity organizations get org-abc123
|
|
3002
|
+
```
|
|
3003
|
+
|
|
3004
|
+
## `sanity organizations list`
|
|
3005
|
+
|
|
3006
|
+
List organizations you are a member of
|
|
3007
|
+
|
|
3008
|
+
```
|
|
3009
|
+
USAGE
|
|
3010
|
+
$ sanity organizations list
|
|
3011
|
+
|
|
3012
|
+
DESCRIPTION
|
|
3013
|
+
List organizations you are a member of
|
|
3014
|
+
|
|
3015
|
+
EXAMPLES
|
|
3016
|
+
List all your organizations
|
|
3017
|
+
|
|
3018
|
+
$ sanity organizations list
|
|
3019
|
+
```
|
|
3020
|
+
|
|
3021
|
+
## `sanity organizations update ORGANIZATIONID`
|
|
3022
|
+
|
|
3023
|
+
Update an organization
|
|
3024
|
+
|
|
3025
|
+
```
|
|
3026
|
+
USAGE
|
|
3027
|
+
$ sanity organizations update ORGANIZATIONID [--default-role <value>] [--name <value>] [--slug <value>]
|
|
3028
|
+
|
|
3029
|
+
ARGUMENTS
|
|
3030
|
+
ORGANIZATIONID Organization ID
|
|
3031
|
+
|
|
3032
|
+
FLAGS
|
|
3033
|
+
--default-role=<value> New default role for new members
|
|
3034
|
+
--name=<value> New organization name
|
|
3035
|
+
--slug=<value> New URL slug (requires authSAML feature on the organization)
|
|
3036
|
+
|
|
3037
|
+
DESCRIPTION
|
|
3038
|
+
Update an organization
|
|
3039
|
+
|
|
3040
|
+
EXAMPLES
|
|
3041
|
+
Rename an organization
|
|
3042
|
+
|
|
3043
|
+
$ sanity organizations update org-abc123 --name "New Name"
|
|
3044
|
+
|
|
3045
|
+
Set the organization slug (requires authSAML feature)
|
|
3046
|
+
|
|
3047
|
+
$ sanity organizations update org-abc123 --slug new-slug
|
|
3048
|
+
|
|
3049
|
+
Change the default member role
|
|
3050
|
+
|
|
3051
|
+
$ sanity organizations update org-abc123 --default-role viewer
|
|
3052
|
+
```
|
|
3053
|
+
|
|
2922
3054
|
## `sanity preview [OUTPUTDIR]`
|
|
2923
3055
|
|
|
2924
3056
|
Start a local server to preview a production build
|
|
@@ -49,8 +49,13 @@ const debug = subdebug('login:getProvider');
|
|
|
49
49
|
if (providers.length === 0) {
|
|
50
50
|
return undefined;
|
|
51
51
|
}
|
|
52
|
-
if (!isInteractive()
|
|
53
|
-
|
|
52
|
+
if (!isInteractive()) {
|
|
53
|
+
if (realProviderNames.length === 1) {
|
|
54
|
+
return providers.find((provider)=>provider.name === realProviderNames[0]);
|
|
55
|
+
}
|
|
56
|
+
if (realProviderNames.length > 1) {
|
|
57
|
+
throw new Error(`Multiple login providers available: ${realProviderNames.join(', ')}. ` + 'Use `--provider <name>` to select one in unattended mode.');
|
|
58
|
+
}
|
|
54
59
|
}
|
|
55
60
|
const provider = await promptForProviders(providers);
|
|
56
61
|
if (provider.name === 'sso') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/actions/auth/login/getProvider.ts"],"sourcesContent":["import {isInteractive, subdebug} from '@sanity/cli-core'\nimport {input, spinner, type SpinnerInstance} from '@sanity/cli-core/ux'\n\nimport {promptForProviders} from '../../../prompts/promptForProviders.js'\nimport {getProviders, getVercelProviderUrl} from '../../../services/auth.js'\nimport {type LoginProvider} from '../types.js'\nimport {getSSOProvider} from './getSSOProvider.js'\n\nconst debug = subdebug('login:getProvider')\n\n/**\n * Prompt the user to select a login provider, or use the specified provider if given.\n *\n * @param options - Options for the provider resolve operation\n * @returns Promise that resolves to the selected login provider\n * @internal\n */\nexport async function getProvider({\n experimental,\n orgSlug,\n specifiedProvider,\n ssoProvider,\n}: {\n experimental: boolean | undefined\n orgSlug: string | undefined\n specifiedProvider: string | undefined\n ssoProvider: string | undefined\n}): Promise<LoginProvider | undefined> {\n if (specifiedProvider === 'vercel') {\n return {\n name: 'vercel',\n title: 'Vercel',\n url: await getVercelProviderUrl(),\n }\n }\n\n let spin: SpinnerInstance | undefined\n\n try {\n if (orgSlug) {\n return getSSOProvider(orgSlug, ssoProvider)\n }\n\n spin = spinner('Fetching providers...').start()\n // Fetch and prompt for login provider to use\n let {providers} = await getProviders()\n if (experimental) {\n providers = [...providers, {name: 'sso', title: 'SSO', url: '_not_used_'}]\n }\n spin.stop()\n\n // Real providers excludes the synthetic SSO entry used by --experimental\n const realProviderNames = providers.filter((p) => p.name !== 'sso').map((p) => p.name)\n\n if (specifiedProvider) {\n const provider = providers.find((prov) => prov.name === specifiedProvider)\n if (!provider) {\n throw new Error(\n `Cannot find login provider with name \"${specifiedProvider}\". ` +\n (realProviderNames.length > 0\n ? `Available providers: ${realProviderNames.join(', ')}`\n : 'No providers are available'),\n )\n }\n return provider\n }\n\n if (providers.length === 0) {\n return undefined\n }\n\n if (!isInteractive()
|
|
1
|
+
{"version":3,"sources":["../../../../src/actions/auth/login/getProvider.ts"],"sourcesContent":["import {isInteractive, subdebug} from '@sanity/cli-core'\nimport {input, spinner, type SpinnerInstance} from '@sanity/cli-core/ux'\n\nimport {promptForProviders} from '../../../prompts/promptForProviders.js'\nimport {getProviders, getVercelProviderUrl} from '../../../services/auth.js'\nimport {type LoginProvider} from '../types.js'\nimport {getSSOProvider} from './getSSOProvider.js'\n\nconst debug = subdebug('login:getProvider')\n\n/**\n * Prompt the user to select a login provider, or use the specified provider if given.\n *\n * @param options - Options for the provider resolve operation\n * @returns Promise that resolves to the selected login provider\n * @internal\n */\nexport async function getProvider({\n experimental,\n orgSlug,\n specifiedProvider,\n ssoProvider,\n}: {\n experimental: boolean | undefined\n orgSlug: string | undefined\n specifiedProvider: string | undefined\n ssoProvider: string | undefined\n}): Promise<LoginProvider | undefined> {\n if (specifiedProvider === 'vercel') {\n return {\n name: 'vercel',\n title: 'Vercel',\n url: await getVercelProviderUrl(),\n }\n }\n\n let spin: SpinnerInstance | undefined\n\n try {\n if (orgSlug) {\n return getSSOProvider(orgSlug, ssoProvider)\n }\n\n spin = spinner('Fetching providers...').start()\n // Fetch and prompt for login provider to use\n let {providers} = await getProviders()\n if (experimental) {\n providers = [...providers, {name: 'sso', title: 'SSO', url: '_not_used_'}]\n }\n spin.stop()\n\n // Real providers excludes the synthetic SSO entry used by --experimental\n const realProviderNames = providers.filter((p) => p.name !== 'sso').map((p) => p.name)\n\n if (specifiedProvider) {\n const provider = providers.find((prov) => prov.name === specifiedProvider)\n if (!provider) {\n throw new Error(\n `Cannot find login provider with name \"${specifiedProvider}\". ` +\n (realProviderNames.length > 0\n ? `Available providers: ${realProviderNames.join(', ')}`\n : 'No providers are available'),\n )\n }\n return provider\n }\n\n if (providers.length === 0) {\n return undefined\n }\n\n if (!isInteractive()) {\n if (realProviderNames.length === 1) {\n return providers.find((provider) => provider.name === realProviderNames[0])\n }\n\n if (realProviderNames.length > 1) {\n throw new Error(\n `Multiple login providers available: ${realProviderNames.join(', ')}. ` +\n 'Use `--provider <name>` to select one in unattended mode.',\n )\n }\n }\n\n const provider = await promptForProviders(providers)\n if (provider.name === 'sso') {\n const orgSlug = await input({message: 'Organization slug:'})\n return getSSOProvider(orgSlug)\n }\n\n return provider\n } catch (err) {\n spin?.stop()\n debug('Error retrieving providers', err)\n throw err\n }\n}\n"],"names":["isInteractive","subdebug","input","spinner","promptForProviders","getProviders","getVercelProviderUrl","getSSOProvider","debug","getProvider","experimental","orgSlug","specifiedProvider","ssoProvider","name","title","url","spin","start","providers","stop","realProviderNames","filter","p","map","provider","find","prov","Error","length","join","undefined","message","err"],"mappings":"AAAA,SAAQA,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACxD,SAAQC,KAAK,EAAEC,OAAO,QAA6B,sBAAqB;AAExE,SAAQC,kBAAkB,QAAO,yCAAwC;AACzE,SAAQC,YAAY,EAAEC,oBAAoB,QAAO,4BAA2B;AAE5E,SAAQC,cAAc,QAAO,sBAAqB;AAElD,MAAMC,QAAQP,SAAS;AAEvB;;;;;;CAMC,GACD,OAAO,eAAeQ,YAAY,EAChCC,YAAY,EACZC,OAAO,EACPC,iBAAiB,EACjBC,WAAW,EAMZ;IACC,IAAID,sBAAsB,UAAU;QAClC,OAAO;YACLE,MAAM;YACNC,OAAO;YACPC,KAAK,MAAMV;QACb;IACF;IAEA,IAAIW;IAEJ,IAAI;QACF,IAAIN,SAAS;YACX,OAAOJ,eAAeI,SAASE;QACjC;QAEAI,OAAOd,QAAQ,yBAAyBe,KAAK;QAC7C,6CAA6C;QAC7C,IAAI,EAACC,SAAS,EAAC,GAAG,MAAMd;QACxB,IAAIK,cAAc;YAChBS,YAAY;mBAAIA;gBAAW;oBAACL,MAAM;oBAAOC,OAAO;oBAAOC,KAAK;gBAAY;aAAE;QAC5E;QACAC,KAAKG,IAAI;QAET,yEAAyE;QACzE,MAAMC,oBAAoBF,UAAUG,MAAM,CAAC,CAACC,IAAMA,EAAET,IAAI,KAAK,OAAOU,GAAG,CAAC,CAACD,IAAMA,EAAET,IAAI;QAErF,IAAIF,mBAAmB;YACrB,MAAMa,WAAWN,UAAUO,IAAI,CAAC,CAACC,OAASA,KAAKb,IAAI,KAAKF;YACxD,IAAI,CAACa,UAAU;gBACb,MAAM,IAAIG,MACR,CAAC,sCAAsC,EAAEhB,kBAAkB,GAAG,CAAC,GAC5DS,CAAAA,kBAAkBQ,MAAM,GAAG,IACxB,CAAC,qBAAqB,EAAER,kBAAkBS,IAAI,CAAC,OAAO,GACtD,4BAA2B;YAErC;YACA,OAAOL;QACT;QAEA,IAAIN,UAAUU,MAAM,KAAK,GAAG;YAC1B,OAAOE;QACT;QAEA,IAAI,CAAC/B,iBAAiB;YACpB,IAAIqB,kBAAkBQ,MAAM,KAAK,GAAG;gBAClC,OAAOV,UAAUO,IAAI,CAAC,CAACD,WAAaA,SAASX,IAAI,KAAKO,iBAAiB,CAAC,EAAE;YAC5E;YAEA,IAAIA,kBAAkBQ,MAAM,GAAG,GAAG;gBAChC,MAAM,IAAID,MACR,CAAC,oCAAoC,EAAEP,kBAAkBS,IAAI,CAAC,MAAM,EAAE,CAAC,GACrE;YAEN;QACF;QAEA,MAAML,WAAW,MAAMrB,mBAAmBe;QAC1C,IAAIM,SAASX,IAAI,KAAK,OAAO;YAC3B,MAAMH,UAAU,MAAMT,MAAM;gBAAC8B,SAAS;YAAoB;YAC1D,OAAOzB,eAAeI;QACxB;QAEA,OAAOc;IACT,EAAE,OAAOQ,KAAK;QACZhB,MAAMG;QACNZ,MAAM,8BAA8ByB;QACpC,MAAMA;IACR;AACF"}
|
|
@@ -16,7 +16,7 @@ const debug = subdebug('dataset:create');
|
|
|
16
16
|
* @returns Promise resolving when dataset is created
|
|
17
17
|
* @throws Error if dataset creation fails
|
|
18
18
|
*/ export async function createDataset(options) {
|
|
19
|
-
const { datasetName, embeddings, embeddingsProjection, forcePublic = false, isUnattended = false, output, projectFeatures, projectId, visibility } = options;
|
|
19
|
+
const { datasetName, embeddings, embeddingsProjection, forcePublic = false, isUnattended = false, output, projectFeatures, projectId, silent = false, visibility } = options;
|
|
20
20
|
const canCreatePrivate = projectFeatures.includes('privateDataset') && !forcePublic;
|
|
21
21
|
// Determine the appropriate ACL mode
|
|
22
22
|
const aclMode = await determineDatasetAclMode({
|
|
@@ -42,7 +42,7 @@ const debug = subdebug('dataset:create');
|
|
|
42
42
|
projectId
|
|
43
43
|
});
|
|
44
44
|
spin.succeed();
|
|
45
|
-
output.log(`Dataset created successfully`);
|
|
45
|
+
if (!silent) output.log(`Dataset created successfully`);
|
|
46
46
|
return newDataset;
|
|
47
47
|
} catch (error) {
|
|
48
48
|
debug('Error creating dataset', {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/dataset/create.ts"],"sourcesContent":["import {type Output, subdebug} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {type DatasetAclMode, DatasetResponse} from '@sanity/client'\n\nimport {createDataset as createDatasetService} from '../../services/datasets.js'\nimport {validateProjection} from '../../util/validateProjection.js'\nimport {determineDatasetAclMode} from './determineDatasetAclMode.js'\n\nconst debug = subdebug('dataset:create')\n\n/**\n * Options for creating a dataset\n */\ninterface CreateDatasetOptions {\n /**\n * Name of the dataset to create\n */\n datasetName: string\n\n /**\n * Output instance for logging\n */\n output: Output\n\n /**\n * Array of project features to determine capabilities\n * Used to check if private datasets are available\n */\n projectFeatures: string[]\n\n /**\n * Project ID where the dataset will be created\n */\n projectId: string\n\n /**\n * Whether to enable embeddings for the new dataset\n */\n embeddings?: boolean\n\n /**\n * GROQ projection for embeddings indexing (e.g. \"\\{ title, body \\}\")\n * Only used when embeddings is true\n */\n embeddingsProjection?: string\n\n /**\n * Whether to force disable private dataset creation\n * Used when default config is selected (which forces public datasets)\n */\n forcePublic?: boolean\n\n /**\n * Whether to run in unattended mode (no prompts)\n */\n isUnattended?: boolean\n\n /**\n * Requested visibility mode from flags/options\n */\n visibility?: string\n}\n\n/**\n * Creates a new dataset with the appropriate ACL mode.\n *\n * This action handles the business logic for:\n * - Determining the appropriate ACL mode based on project capabilities\n * - Creating the dataset via the service layer\n * - Handling errors and providing user feedback\n *\n * @param options - Configuration options\n * @returns Promise resolving when dataset is created\n * @throws Error if dataset creation fails\n */\nexport async function createDataset(options: CreateDatasetOptions): Promise<DatasetResponse> {\n const {\n datasetName,\n embeddings,\n embeddingsProjection,\n forcePublic = false,\n isUnattended = false,\n output,\n projectFeatures,\n projectId,\n visibility,\n } = options\n\n const canCreatePrivate = projectFeatures.includes('privateDataset') && !forcePublic\n\n // Determine the appropriate ACL mode\n const aclMode: DatasetAclMode = await determineDatasetAclMode({\n canCreatePrivate,\n isUnattended,\n output,\n visibility,\n })\n\n if (embeddingsProjection) {\n validateProjection(embeddingsProjection)\n }\n\n try {\n const spin = spinner('Creating dataset').start()\n const newDataset = await createDatasetService({\n aclMode,\n datasetName,\n embeddings: embeddings\n ? {enabled: true, ...(embeddingsProjection ? {projection: embeddingsProjection} : {})}\n : undefined,\n projectId,\n })\n spin.succeed()\n output.log(`Dataset created successfully`)\n return newDataset\n } catch (error) {\n debug('Error creating dataset', {datasetName, error})\n throw error\n }\n}\n"],"names":["subdebug","spinner","createDataset","createDatasetService","validateProjection","determineDatasetAclMode","debug","options","datasetName","embeddings","embeddingsProjection","forcePublic","isUnattended","output","projectFeatures","projectId","visibility","canCreatePrivate","includes","aclMode","spin","start","newDataset","enabled","projection","undefined","succeed","log","error"],"mappings":"AAAA,SAAqBA,QAAQ,QAAO,mBAAkB;AACtD,SAAQC,OAAO,QAAO,sBAAqB;AAG3C,SAAQC,iBAAiBC,oBAAoB,QAAO,6BAA4B;AAChF,SAAQC,kBAAkB,QAAO,mCAAkC;AACnE,SAAQC,uBAAuB,QAAO,+BAA8B;AAEpE,MAAMC,QAAQN,SAAS;
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/dataset/create.ts"],"sourcesContent":["import {type Output, subdebug} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {type DatasetAclMode, DatasetResponse} from '@sanity/client'\n\nimport {createDataset as createDatasetService} from '../../services/datasets.js'\nimport {validateProjection} from '../../util/validateProjection.js'\nimport {determineDatasetAclMode} from './determineDatasetAclMode.js'\n\nconst debug = subdebug('dataset:create')\n\n/**\n * Options for creating a dataset\n */\ninterface CreateDatasetOptions {\n /**\n * Name of the dataset to create\n */\n datasetName: string\n\n /**\n * Output instance for logging\n */\n output: Output\n\n /**\n * Array of project features to determine capabilities\n * Used to check if private datasets are available\n */\n projectFeatures: string[]\n\n /**\n * Project ID where the dataset will be created\n */\n projectId: string\n\n /**\n * Whether to enable embeddings for the new dataset\n */\n embeddings?: boolean\n\n /**\n * GROQ projection for embeddings indexing (e.g. \"\\{ title, body \\}\")\n * Only used when embeddings is true\n */\n embeddingsProjection?: string\n\n /**\n * Whether to force disable private dataset creation\n * Used when default config is selected (which forces public datasets)\n */\n forcePublic?: boolean\n\n /**\n * Whether to run in unattended mode (no prompts)\n */\n isUnattended?: boolean\n\n /**\n * Whether to omit human-readable success output\n */\n silent?: boolean\n\n /**\n * Requested visibility mode from flags/options\n */\n visibility?: string\n}\n\n/**\n * Creates a new dataset with the appropriate ACL mode.\n *\n * This action handles the business logic for:\n * - Determining the appropriate ACL mode based on project capabilities\n * - Creating the dataset via the service layer\n * - Handling errors and providing user feedback\n *\n * @param options - Configuration options\n * @returns Promise resolving when dataset is created\n * @throws Error if dataset creation fails\n */\nexport async function createDataset(options: CreateDatasetOptions): Promise<DatasetResponse> {\n const {\n datasetName,\n embeddings,\n embeddingsProjection,\n forcePublic = false,\n isUnattended = false,\n output,\n projectFeatures,\n projectId,\n silent = false,\n visibility,\n } = options\n\n const canCreatePrivate = projectFeatures.includes('privateDataset') && !forcePublic\n\n // Determine the appropriate ACL mode\n const aclMode: DatasetAclMode = await determineDatasetAclMode({\n canCreatePrivate,\n isUnattended,\n output,\n visibility,\n })\n\n if (embeddingsProjection) {\n validateProjection(embeddingsProjection)\n }\n\n try {\n const spin = spinner('Creating dataset').start()\n const newDataset = await createDatasetService({\n aclMode,\n datasetName,\n embeddings: embeddings\n ? {enabled: true, ...(embeddingsProjection ? {projection: embeddingsProjection} : {})}\n : undefined,\n projectId,\n })\n spin.succeed()\n if (!silent) output.log(`Dataset created successfully`)\n return newDataset\n } catch (error) {\n debug('Error creating dataset', {datasetName, error})\n throw error\n }\n}\n"],"names":["subdebug","spinner","createDataset","createDatasetService","validateProjection","determineDatasetAclMode","debug","options","datasetName","embeddings","embeddingsProjection","forcePublic","isUnattended","output","projectFeatures","projectId","silent","visibility","canCreatePrivate","includes","aclMode","spin","start","newDataset","enabled","projection","undefined","succeed","log","error"],"mappings":"AAAA,SAAqBA,QAAQ,QAAO,mBAAkB;AACtD,SAAQC,OAAO,QAAO,sBAAqB;AAG3C,SAAQC,iBAAiBC,oBAAoB,QAAO,6BAA4B;AAChF,SAAQC,kBAAkB,QAAO,mCAAkC;AACnE,SAAQC,uBAAuB,QAAO,+BAA8B;AAEpE,MAAMC,QAAQN,SAAS;AA4DvB;;;;;;;;;;;CAWC,GACD,OAAO,eAAeE,cAAcK,OAA6B;IAC/D,MAAM,EACJC,WAAW,EACXC,UAAU,EACVC,oBAAoB,EACpBC,cAAc,KAAK,EACnBC,eAAe,KAAK,EACpBC,MAAM,EACNC,eAAe,EACfC,SAAS,EACTC,SAAS,KAAK,EACdC,UAAU,EACX,GAAGV;IAEJ,MAAMW,mBAAmBJ,gBAAgBK,QAAQ,CAAC,qBAAqB,CAACR;IAExE,qCAAqC;IACrC,MAAMS,UAA0B,MAAMf,wBAAwB;QAC5Da;QACAN;QACAC;QACAI;IACF;IAEA,IAAIP,sBAAsB;QACxBN,mBAAmBM;IACrB;IAEA,IAAI;QACF,MAAMW,OAAOpB,QAAQ,oBAAoBqB,KAAK;QAC9C,MAAMC,aAAa,MAAMpB,qBAAqB;YAC5CiB;YACAZ;YACAC,YAAYA,aACR;gBAACe,SAAS;gBAAM,GAAId,uBAAuB;oBAACe,YAAYf;gBAAoB,IAAI,CAAC,CAAC;YAAC,IACnFgB;YACJX;QACF;QACAM,KAAKM,OAAO;QACZ,IAAI,CAACX,QAAQH,OAAOe,GAAG,CAAC,CAAC,4BAA4B,CAAC;QACtD,OAAOL;IACT,EAAE,OAAOM,OAAO;QACdvB,MAAM,0BAA0B;YAACE;YAAaqB;QAAK;QACnD,MAAMA;IACR;AACF"}
|
|
@@ -78,7 +78,7 @@ export async function createStudioUserApplication(options) {
|
|
|
78
78
|
});
|
|
79
79
|
return await promise;
|
|
80
80
|
}
|
|
81
|
-
export async function createUserApplication(organizationId, title) {
|
|
81
|
+
export async function createUserApplication(organizationId, title, visibility) {
|
|
82
82
|
if (!organizationId) {
|
|
83
83
|
throw new Error(NO_ORGANIZATION_ID);
|
|
84
84
|
}
|
|
@@ -86,9 +86,9 @@ export async function createUserApplication(organizationId, title) {
|
|
|
86
86
|
message: 'Enter a title for your application:',
|
|
87
87
|
validate: (value)=>value.length > 0 || 'Title is required'
|
|
88
88
|
});
|
|
89
|
-
return tryCreateApp(resolvedTitle, organizationId);
|
|
89
|
+
return tryCreateApp(resolvedTitle, organizationId, visibility);
|
|
90
90
|
}
|
|
91
|
-
const tryCreateApp = async (title, organizationId)=>{
|
|
91
|
+
const tryCreateApp = async (title, organizationId, visibility)=>{
|
|
92
92
|
// we will likely prepend this with an org ID or other parameter in the future
|
|
93
93
|
const appHost = generateAppSlug();
|
|
94
94
|
const spin = spinner('Creating application').start();
|
|
@@ -99,7 +99,10 @@ const tryCreateApp = async (title, organizationId)=>{
|
|
|
99
99
|
appHost,
|
|
100
100
|
title,
|
|
101
101
|
type: 'coreApp',
|
|
102
|
-
urlType: 'internal'
|
|
102
|
+
urlType: 'internal',
|
|
103
|
+
...visibility ? {
|
|
104
|
+
dashboardStatus: visibility
|
|
105
|
+
} : {}
|
|
103
106
|
},
|
|
104
107
|
organizationId
|
|
105
108
|
});
|
|
@@ -112,7 +115,7 @@ const tryCreateApp = async (title, organizationId)=>{
|
|
|
112
115
|
409
|
|
113
116
|
].includes(e?.statusCode)) {
|
|
114
117
|
deployDebug('App host taken, retrying with new host');
|
|
115
|
-
return tryCreateApp(title, organizationId);
|
|
118
|
+
return tryCreateApp(title, organizationId, visibility);
|
|
116
119
|
}
|
|
117
120
|
spin.fail();
|
|
118
121
|
deployDebug('Error creating core application', e);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/createUserApplication.ts"],"sourcesContent":["import {CLIError} from '@oclif/core/errors'\nimport {input, spinner} from '@sanity/cli-core/ux'\nimport {customAlphabet} from 'nanoid'\n\nimport {\n createUserApplication as createUserApplicationRequest,\n type UserApplication,\n type UserApplicationResolved,\n} from '../../services/userApplications.js'\nimport {NO_ORGANIZATION_ID} from '../../util/errorMessages.js'\nimport {deployDebug} from './deployDebug.js'\nimport {normalizeUrl, validateUrl} from './urlUtils.js'\n\nconst LETTERS = 'abcdefghijklmnopqrstuvwxyz'\n\n// appHosts have some restrictions (no uppercase, must start with a letter)\nexport function generateAppSlug(): string {\n const firstChar = customAlphabet(LETTERS, 1)()\n const rest = customAlphabet(`${LETTERS}0123456789`, 11)()\n return `${firstChar}${rest}`\n}\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 title?: string\n urlType?: 'external' | 'internal'\n}\n\nexport async function createStudioUserApplication(options: CreateStudioUserApplicationOptions) {\n const {projectId, title, 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 createUserApplicationRequest({\n appType: 'studio',\n body: {appHost, title, type: 'studio', urlType},\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\nexport async function createUserApplication(\n organizationId?: string,\n title?: string,\n): Promise<UserApplicationResolved> {\n if (!organizationId) {\n throw new Error(NO_ORGANIZATION_ID)\n }\n\n const resolvedTitle =\n title ??\n (await input({\n message: 'Enter a title for your application:',\n validate: (value: string) => value.length > 0 || 'Title is required',\n }))\n\n return tryCreateApp(resolvedTitle, organizationId)\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 = generateAppSlug()\n\n const spin = spinner('Creating application').start()\n\n try {\n const response = await createUserApplicationRequest({\n appType: 'coreApp',\n body: {appHost
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/deploy/createUserApplication.ts"],"sourcesContent":["import {CLIError} from '@oclif/core/errors'\nimport {type AppVisibility} from '@sanity/cli-core'\nimport {input, spinner} from '@sanity/cli-core/ux'\nimport {customAlphabet} from 'nanoid'\n\nimport {\n createUserApplication as createUserApplicationRequest,\n type UserApplication,\n type UserApplicationResolved,\n} from '../../services/userApplications.js'\nimport {NO_ORGANIZATION_ID} from '../../util/errorMessages.js'\nimport {deployDebug} from './deployDebug.js'\nimport {normalizeUrl, validateUrl} from './urlUtils.js'\n\nconst LETTERS = 'abcdefghijklmnopqrstuvwxyz'\n\n// appHosts have some restrictions (no uppercase, must start with a letter)\nexport function generateAppSlug(): string {\n const firstChar = customAlphabet(LETTERS, 1)()\n const rest = customAlphabet(`${LETTERS}0123456789`, 11)()\n return `${firstChar}${rest}`\n}\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 title?: string\n urlType?: 'external' | 'internal'\n}\n\nexport async function createStudioUserApplication(options: CreateStudioUserApplicationOptions) {\n const {projectId, title, 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 createUserApplicationRequest({\n appType: 'studio',\n body: {appHost, title, type: 'studio', urlType},\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\nexport async function createUserApplication(\n organizationId?: string,\n title?: string,\n visibility?: AppVisibility,\n): Promise<UserApplicationResolved> {\n if (!organizationId) {\n throw new Error(NO_ORGANIZATION_ID)\n }\n\n const resolvedTitle =\n title ??\n (await input({\n message: 'Enter a title for your application:',\n validate: (value: string) => value.length > 0 || 'Title is required',\n }))\n\n return tryCreateApp(resolvedTitle, organizationId, visibility)\n}\n\nconst tryCreateApp = async (title: string, organizationId: string, visibility?: AppVisibility) => {\n // we will likely prepend this with an org ID or other parameter in the future\n const appHost = generateAppSlug()\n\n const spin = spinner('Creating application').start()\n\n try {\n const response = await createUserApplicationRequest({\n appType: 'coreApp',\n body: {\n appHost,\n title,\n type: 'coreApp',\n urlType: 'internal',\n ...(visibility ? {dashboardStatus: visibility} : {}),\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, visibility)\n }\n\n spin.fail()\n\n deployDebug('Error creating core application', e)\n throw e\n }\n}\n"],"names":["CLIError","input","spinner","customAlphabet","createUserApplication","createUserApplicationRequest","NO_ORGANIZATION_ID","deployDebug","normalizeUrl","validateUrl","LETTERS","generateAppSlug","firstChar","rest","promiseWithResolvers","resolve","reject","promise","Promise","res","rej","createStudioUserApplication","options","projectId","title","urlType","isExternal","message","validate","inp","appHost","normalized","validation","replace","response","appType","body","type","e","includes","statusCode","exit","organizationId","visibility","Error","resolvedTitle","value","length","tryCreateApp","spin","start","dashboardStatus","succeed","fail"],"mappings":"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"}
|
|
@@ -3,8 +3,9 @@ import { styleText } from 'node:util';
|
|
|
3
3
|
import { createGzip } from 'node:zlib';
|
|
4
4
|
import { exitCodes } from '@sanity/cli-core';
|
|
5
5
|
import { getErrorMessage } from '@sanity/cli-core/errors';
|
|
6
|
+
import { getCoreAppUrl } from '@sanity/cli-core/util';
|
|
6
7
|
import { spinner } from '@sanity/cli-core/ux';
|
|
7
|
-
import { buildExposes, deployConfig, deployCoreApp as deployWorkbenchCoreApp, getWorkbench, resolveInstallationId, summarizeConfig } from '@sanity/workbench-cli/deploy';
|
|
8
|
+
import { buildExposes, deployConfig, deployCoreApp as deployWorkbenchCoreApp, getApplicationUrl, getWorkbench, resolveInstallationId, summarizeConfig } from '@sanity/workbench-cli/deploy';
|
|
8
9
|
import { pack } from 'tar-fs';
|
|
9
10
|
import { createDeployment, updateUserApplication } from '../../services/userApplications.js';
|
|
10
11
|
import { getAppId } from '../../util/appId.js';
|
|
@@ -17,7 +18,6 @@ import { deployDebug } from './deployDebug.js';
|
|
|
17
18
|
import { listDeploymentFiles, reportExposes } from './deploymentPlan.js';
|
|
18
19
|
import { runDeploy } from './deployRunner.js';
|
|
19
20
|
import { findUserApplication } from './findUserApplication.js';
|
|
20
|
-
import { getCoreAppUrl } from './urlUtils.js';
|
|
21
21
|
const APP_PACKAGE = '@sanity/sdk-react';
|
|
22
22
|
export function deployApp(options) {
|
|
23
23
|
return runDeploy(options, {
|
|
@@ -90,7 +90,6 @@ export function deployApp(options) {
|
|
|
90
90
|
status: 'fail'
|
|
91
91
|
});
|
|
92
92
|
} else if (deployApplication && workbench) {
|
|
93
|
-
// Both modes, so a bad appId fails before the build rather than at the POST.
|
|
94
93
|
await checkAppTarget(reporter, {
|
|
95
94
|
appId,
|
|
96
95
|
isWorkbenchApp: true,
|
|
@@ -169,10 +168,11 @@ export function deployApp(options) {
|
|
|
169
168
|
}
|
|
170
169
|
// Dry run stops here — everything below mutates.
|
|
171
170
|
if (dryRun) return;
|
|
172
|
-
if (installationId && version && configAppType) {
|
|
171
|
+
if (installationId && version && configAppType && organizationId) {
|
|
173
172
|
await deployConfig({
|
|
174
173
|
appType: configAppType,
|
|
175
174
|
installationId,
|
|
175
|
+
organizationId,
|
|
176
176
|
output,
|
|
177
177
|
sourceDir,
|
|
178
178
|
version
|
|
@@ -213,7 +213,13 @@ export function deployApp(options) {
|
|
|
213
213
|
slug,
|
|
214
214
|
sourceDir,
|
|
215
215
|
title: appTitle,
|
|
216
|
-
version
|
|
216
|
+
version,
|
|
217
|
+
visibility: workbench.visibility
|
|
218
|
+
});
|
|
219
|
+
const url = getApplicationUrl({
|
|
220
|
+
id: applicationId,
|
|
221
|
+
organizationId,
|
|
222
|
+
type: 'coreApp'
|
|
217
223
|
});
|
|
218
224
|
logAppDeployed({
|
|
219
225
|
applicationId,
|
|
@@ -221,7 +227,8 @@ export function deployApp(options) {
|
|
|
221
227
|
created: !appId,
|
|
222
228
|
organizationId,
|
|
223
229
|
output,
|
|
224
|
-
title: appTitle
|
|
230
|
+
title: appTitle,
|
|
231
|
+
url
|
|
225
232
|
});
|
|
226
233
|
return {
|
|
227
234
|
applicationType: 'coreApp',
|
|
@@ -240,17 +247,18 @@ export function deployApp(options) {
|
|
|
240
247
|
slug
|
|
241
248
|
},
|
|
242
249
|
title: appTitle,
|
|
243
|
-
url
|
|
250
|
+
url
|
|
244
251
|
}
|
|
245
252
|
};
|
|
246
253
|
}
|
|
247
254
|
// A real deploy has already exited if anything failed; landing here without a
|
|
248
255
|
// resolved application means the deploy target was never resolved.
|
|
249
256
|
if (!application) return;
|
|
250
|
-
application = await
|
|
257
|
+
application = await syncApplicationMetadata({
|
|
251
258
|
application,
|
|
252
259
|
manifest,
|
|
253
|
-
output
|
|
260
|
+
output,
|
|
261
|
+
visibility: cliConfig.app?.visibility
|
|
254
262
|
});
|
|
255
263
|
await shipAppDeployment({
|
|
256
264
|
application,
|
|
@@ -307,7 +315,7 @@ export function deployApp(options) {
|
|
|
307
315
|
deployDebug('User application found', application);
|
|
308
316
|
if (!application) {
|
|
309
317
|
deployDebug('No user application found. Creating a new one');
|
|
310
|
-
application = await createUserApplication(organizationId, title);
|
|
318
|
+
application = await createUserApplication(organizationId, title, cliConfig.app?.visibility);
|
|
311
319
|
deployDebug('User application created', application);
|
|
312
320
|
return {
|
|
313
321
|
application,
|
|
@@ -319,18 +327,34 @@ export function deployApp(options) {
|
|
|
319
327
|
created: false
|
|
320
328
|
};
|
|
321
329
|
}
|
|
322
|
-
/**
|
|
330
|
+
/**
|
|
331
|
+
* Syncs application metadata on redeploy when it has changed: the title from the
|
|
332
|
+
* manifest and the dashboard visibility from config. Sends a single PATCH with
|
|
333
|
+
* only the changed fields, and skips the request entirely when nothing changed.
|
|
334
|
+
*/ export async function syncApplicationMetadata({ application, manifest, output, visibility }) {
|
|
323
335
|
const titleUpdate = resolveTitleUpdate(manifest, application);
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
336
|
+
// Treat an unset server value as `default` so a config of `default` is a no-op.
|
|
337
|
+
const visibilityChanged = visibility !== undefined && visibility !== (application.dashboardStatus ?? 'default');
|
|
338
|
+
if (!titleUpdate && !visibilityChanged) return application;
|
|
339
|
+
if (titleUpdate) {
|
|
340
|
+
deployDebug('Updating application title from manifest', titleUpdate);
|
|
341
|
+
output.log(titleUpdate.from ? `Updating title from "${titleUpdate.from}" to "${titleUpdate.to}"` : `Setting application title to "${titleUpdate.to}"`);
|
|
342
|
+
}
|
|
343
|
+
if (visibilityChanged) {
|
|
344
|
+
output.log(`Setting dashboard visibility to "${visibility}"`);
|
|
345
|
+
}
|
|
346
|
+
const spin = spinner('Updating application').start();
|
|
328
347
|
try {
|
|
329
348
|
const updated = await updateUserApplication({
|
|
330
349
|
applicationId: application.id,
|
|
331
350
|
appType: 'coreApp',
|
|
332
351
|
body: {
|
|
333
|
-
|
|
352
|
+
...titleUpdate ? {
|
|
353
|
+
title: titleUpdate.to
|
|
354
|
+
} : {},
|
|
355
|
+
...visibilityChanged ? {
|
|
356
|
+
dashboardStatus: visibility
|
|
357
|
+
} : {}
|
|
334
358
|
}
|
|
335
359
|
});
|
|
336
360
|
spin.succeed();
|
|
@@ -338,10 +362,10 @@ export function deployApp(options) {
|
|
|
338
362
|
} catch (err) {
|
|
339
363
|
spin.fail();
|
|
340
364
|
const message = getErrorMessage(err);
|
|
341
|
-
deployDebug('Error updating application
|
|
365
|
+
deployDebug('Error updating application metadata', {
|
|
342
366
|
message
|
|
343
367
|
});
|
|
344
|
-
output.warn(`Error updating application
|
|
368
|
+
output.warn(`Error updating application metadata: ${message}`);
|
|
345
369
|
return application;
|
|
346
370
|
}
|
|
347
371
|
}
|
|
@@ -367,8 +391,7 @@ async function shipAppDeployment({ application, isAutoUpdating, manifest, source
|
|
|
367
391
|
}
|
|
368
392
|
spin.succeed();
|
|
369
393
|
}
|
|
370
|
-
export function logAppDeployed({ applicationId, cliConfig, created, organizationId, output, title }) {
|
|
371
|
-
const url = getCoreAppUrl(organizationId, applicationId);
|
|
394
|
+
export function logAppDeployed({ applicationId, cliConfig, created, organizationId, output, title, url = getCoreAppUrl(organizationId, applicationId) }) {
|
|
372
395
|
const named = title ? ` — "${title}"` : '';
|
|
373
396
|
output.log(`\nSuccess! Application deployed to ${styleText('cyan', url)}${named}`);
|
|
374
397
|
output.log(created ? 'Created a new application.' : 'Updated the existing application.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/deployApp.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip} from 'node:zlib'\n\nimport {exitCodes} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {\n buildExposes,\n deployConfig,\n deployCoreApp as deployWorkbenchCoreApp,\n getWorkbench,\n resolveInstallationId,\n summarizeConfig,\n} from '@sanity/workbench-cli/deploy'\nimport {pack} from 'tar-fs'\n\nimport {\n createDeployment,\n updateUserApplication,\n type UserApplication,\n type UserApplicationResolved,\n} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {EXTERNAL_APP_NOT_SUPPORTED, NO_ORGANIZATION_ID} from '../../util/errorMessages.js'\nimport {buildApp} from '../build/buildApp.js'\nimport {extractCoreAppManifest, resolveTitleUpdate} from '../manifest/extractCoreAppManifest.js'\nimport {type CoreAppManifest} from '../manifest/types.js'\nimport {createUserApplication, generateAppSlug} from './createUserApplication.js'\nimport {\n checkAppId,\n checkAppTarget,\n checkAutoUpdates,\n checkBuild,\n checkPackageVersion,\n type DeployCheckReporter,\n verifyOutputDir,\n} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {listDeploymentFiles, reportExposes} from './deploymentPlan.js'\nimport {type DeployResult, runDeploy} from './deployRunner.js'\nimport {findUserApplication} from './findUserApplication.js'\nimport {type DeployAppOptions} from './types.js'\nimport {getCoreAppUrl} from './urlUtils.js'\n\nconst APP_PACKAGE = '@sanity/sdk-react'\n\nexport function deployApp(options: DeployAppOptions): Promise<void> {\n return runDeploy(options, {\n listFiles: ({projectRoot, sourceDir}) => listDeploymentFiles(sourceDir, projectRoot.directory),\n run: runAppDeployment,\n type: 'coreApp',\n })\n}\n\n/** Validates the deploy, syncs the title from the manifest, and ships the build. */\nasync function runAppDeployment(\n options: DeployAppOptions,\n reporter: DeployCheckReporter,\n): Promise<DeployResult | void> {\n const {cliConfig, flags, output, sourceDir} = options\n const workDir = options.projectRoot.directory\n const organizationId = cliConfig.app?.organizationId\n const appId = getAppId(cliConfig)\n const workbench = getWorkbench(cliConfig)\n const dryRun = !!flags['dry-run']\n\n // A singleton (the Media Library) persists its config instead of hosting an\n // application; anything that exposes a view or service still ships one.\n const deploySingletonConfig = workbench?.deploySingletonConfig ?? false\n const deployApplication = !workbench || workbench.hasInterfaces\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.name\n : ''\n\n // A federated app with no entry, view or service would ship a remote with\n // nothing to load — reported first so it fails before any prompt or API call.\n if (workbench) {\n try {\n workbench.assertDeployable()\n } catch (err) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: getErrorMessage(err),\n solution: 'Declare at least one entry, view, or service in the app',\n status: 'fail',\n })\n }\n }\n\n const isAutoUpdating = checkAutoUpdates(reporter, {cliConfig, flags})\n\n // An application ships the SDK runtime; a media-library config stamps its\n // `sanity` version instead.\n let version: string | null = null\n if (deployApplication) {\n version = await checkPackageVersion(reporter, {moduleName: APP_PACKAGE, workDir})\n } else if (deploySingletonConfig) {\n version = await checkPackageVersion(reporter, {moduleName: 'sanity', workDir})\n }\n\n reporter.report(\n organizationId\n ? {message: `Organization: ${organizationId}`, status: 'pass'}\n : {\n message: NO_ORGANIZATION_ID,\n solution: 'Add `app.organizationId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n\n checkAppId(reporter, {cliConfig})\n\n let application: UserApplicationResolved | null = null\n let appCreated = false\n if (flags.external) {\n reporter.report({\n message: EXTERNAL_APP_NOT_SUPPORTED,\n solution: 'Remove the --external flag — apps deploy to Sanity hosting',\n status: 'fail',\n })\n } else if (deployApplication && workbench) {\n // Both modes, so a bad appId fails before the build rather than at the POST.\n await checkAppTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n slug: workbench.slug,\n title: appTitle,\n })\n } else if (deployApplication) {\n ;({application, created: appCreated} = await resolveAppApplication(options, {dryRun, reporter}))\n }\n\n await checkBuild(reporter, {\n build: () =>\n buildApp({\n autoUpdatesEnabled: isAutoUpdating,\n calledFromDeploy: true,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n }),\n skipReason: flags.build\n ? undefined\n : 'Build skipped (--no-build) — validating existing output directory',\n successMessage: 'App built',\n })\n\n await verifyOutputDir({isWorkbenchApp: workbench !== null, reporter, sourceDir})\n\n // Manifests aren't strictly essential, so a failure warns and continues\n let manifest: CoreAppManifest | undefined\n try {\n manifest = await extractCoreAppManifest({workDir})\n } catch (err) {\n deployDebug('Error extracting app manifest', err)\n reporter.report({\n message: `Error extracting app manifest: ${getErrorMessage(err)}`,\n status: 'warn',\n })\n }\n\n // Resolve the installation in both modes so the report — dry-run and real —\n // shows whether the config is deployable; a missing one fails the deploy here.\n let installationId: string | undefined\n let config: string | undefined\n const configAppType = workbench?.config?.appType\n if (deploySingletonConfig && organizationId && workbench?.config && configAppType) {\n installationId = await resolveInstallationId({appType: configAppType, organizationId})\n config = summarizeConfig(workbench.config)\n reporter.report(\n installationId\n ? {config, message: config, status: 'pass'}\n : {\n exitCode: exitCodes.USAGE_ERROR,\n message: `No active \"${configAppType}\" installation for organization \"${organizationId}\"`,\n solution: 'Install the Media Library for the organization before deploying its config',\n status: 'fail',\n },\n )\n }\n\n // Report the exposes deploying with the application, both modes.\n const exposes = deployApplication && workbench ? reportExposes(reporter, workbench) : []\n\n // Surface the app's explicit singleton flag when set, both modes.\n if (deployApplication && workbench?.isSingleton !== undefined) {\n reporter.report({\n isSingleton: workbench.isSingleton,\n message: `Singleton: ${workbench.isSingleton}`,\n status: 'pass',\n })\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return\n\n if (installationId && version && configAppType) {\n await deployConfig({\n appType: configAppType,\n installationId,\n output,\n sourceDir,\n version,\n })\n }\n\n // A config-only singleton ships no application, only its config.\n if (!deployApplication) {\n if (installationId && version) {\n return {\n applicationType: 'coreApp',\n applicationVersion: version,\n ...(config ? {config} : {}),\n installationId,\n target: null,\n }\n }\n return\n }\n\n // A real deploy already exited on a version-resolution failure; this narrows the type.\n if (!version) return\n\n // Workbench apps deploy to Brett; plain coreApps use user-applications.\n if (workbench && organizationId) {\n const appId = getAppId(cliConfig)\n const slug = workbench.slug ?? generateAppSlug()\n const {applicationId} = await deployWorkbenchCoreApp({\n appId,\n interfaces: buildExposes(workbench, {\n appName: workbench.name,\n appTitle,\n exposesAppView: workbench.entry !== undefined,\n version,\n }),\n isAutoUpdating,\n isSingleton: workbench.isSingleton,\n organizationId,\n slug,\n sourceDir,\n title: appTitle,\n version,\n })\n logAppDeployed({\n applicationId,\n cliConfig,\n created: !appId,\n organizationId,\n output,\n title: appTitle,\n })\n return {\n applicationType: 'coreApp',\n applicationVersion: version,\n ...(exposes.length > 0 ? {exposes} : {}),\n ...(workbench.isSingleton === undefined ? {} : {isSingleton: workbench.isSingleton}),\n target: {\n action: appId ? 'update' : 'create',\n applicationId,\n // A redeploy ignores the slug, so only a create reports the one it used.\n ...(appId ? {} : {slug}),\n title: appTitle,\n url: getCoreAppUrl(organizationId, applicationId),\n },\n }\n }\n\n // A real deploy has already exited if anything failed; landing here without a\n // resolved application means the deploy target was never resolved.\n if (!application) return\n\n application = await syncApplicationTitle({application, manifest, output})\n await shipAppDeployment({application, isAutoUpdating, manifest, sourceDir, version})\n logAppDeployed({\n applicationId: application.id,\n cliConfig,\n created: appCreated,\n organizationId: application.organizationId,\n output,\n title: application.title,\n })\n return {\n applicationType: 'coreApp',\n applicationVersion: version,\n target: {\n action: appCreated ? 'create' : 'update',\n applicationId: application.id,\n title: application.title ?? null,\n url: getCoreAppUrl(application.organizationId, application.id),\n },\n }\n}\n\n/**\n * Finds the application a real deploy targets, creating one when none is\n * configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveAppApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplicationResolved | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const organizationId = cliConfig.app?.organizationId ?? ''\n // Create name from --title or `app.title` config; blank falls back to the prompt\n const title = flags.title?.trim() || cliConfig.app?.title?.trim() || undefined\n\n if (dryRun) {\n await checkAppTarget(reporter, {appId: getAppId(cliConfig), organizationId, title})\n return {application: null, created: false}\n }\n\n let application = await findUserApplication({\n cliConfig,\n organizationId,\n output,\n title,\n unattended: !!flags.yes,\n })\n deployDebug('User application found', application)\n\n if (!application) {\n deployDebug('No user application found. Creating a new one')\n application = await createUserApplication(organizationId, title)\n deployDebug('User application created', application)\n return {application, created: true}\n }\n\n return {application, created: false}\n}\n\n/** Syncs the application title from the manifest when it has changed. */\nasync function syncApplicationTitle({\n application,\n manifest,\n output,\n}: {\n application: UserApplicationResolved\n manifest: CoreAppManifest | undefined\n output: DeployAppOptions['output']\n}): Promise<UserApplicationResolved> {\n const titleUpdate = resolveTitleUpdate(manifest, application)\n if (!titleUpdate) return application\n\n deployDebug('Updating application title from manifest', titleUpdate)\n output.log(\n titleUpdate.from\n ? `Updating title from \"${titleUpdate.from}\" to \"${titleUpdate.to}\"`\n : `Setting application title to \"${titleUpdate.to}\"`,\n )\n const spin = spinner('Updating application title').start()\n try {\n const updated = await updateUserApplication({\n applicationId: application.id,\n appType: 'coreApp',\n body: {title: titleUpdate.to},\n })\n spin.succeed()\n return updated\n } catch (err) {\n spin.fail()\n const message = getErrorMessage(err)\n deployDebug('Error updating application title', {message})\n output.warn(`Error updating application title: ${message}`)\n return application\n }\n}\n\nasync function shipAppDeployment({\n application,\n isAutoUpdating,\n manifest,\n sourceDir,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n manifest: CoreAppManifest | undefined\n sourceDir: string\n version: string\n}): Promise<void> {\n const tarball = pack(dirname(sourceDir), {entries: [basename(sourceDir)]}).pipe(createGzip())\n\n const spin = spinner('Deploying...').start()\n try {\n await createDeployment({\n applicationId: application.id,\n isApp: true,\n isAutoUpdating,\n manifest,\n tarball,\n version,\n })\n } catch (error) {\n spin.clear()\n throw error\n }\n spin.succeed()\n}\n\nexport function logAppDeployed({\n applicationId,\n cliConfig,\n created,\n organizationId,\n output,\n title,\n}: {\n applicationId: string\n cliConfig: DeployAppOptions['cliConfig']\n created: boolean\n organizationId: string\n output: DeployAppOptions['output']\n title: string | null\n}): void {\n const url = getCoreAppUrl(organizationId, applicationId)\n const named = title ? ` — \"${title}\"` : ''\n output.log(`\\nSuccess! Application deployed to ${styleText('cyan', url)}${named}`)\n output.log(created ? 'Created a new application.' : 'Updated the existing application.')\n\n if (getAppId(cliConfig)) return\n\n output.log(`\\n════ ${styleText('bold', 'Next step:')} ════`)\n if (created) {\n output.log(\n styleText(\n 'yellow',\n '\\nDeploying again without `deployment.appId` creates another new application.',\n ),\n )\n }\n output.log(\n styleText('bold', '\\nAdd the deployment.appId to your sanity.cli.js or sanity.cli.ts file:'),\n )\n output.log(`\n${styleText(\n 'dim',\n `app: {\n // your application config here…\n}`,\n)},\n${styleText(\n ['bold', 'green'],\n `deployment: {\n appId: '${applicationId}',\n}\\n`,\n)}`)\n}\n"],"names":["basename","dirname","styleText","createGzip","exitCodes","getErrorMessage","spinner","buildExposes","deployConfig","deployCoreApp","deployWorkbenchCoreApp","getWorkbench","resolveInstallationId","summarizeConfig","pack","createDeployment","updateUserApplication","getAppId","EXTERNAL_APP_NOT_SUPPORTED","NO_ORGANIZATION_ID","buildApp","extractCoreAppManifest","resolveTitleUpdate","createUserApplication","generateAppSlug","checkAppId","checkAppTarget","checkAutoUpdates","checkBuild","checkPackageVersion","verifyOutputDir","deployDebug","listDeploymentFiles","reportExposes","runDeploy","findUserApplication","getCoreAppUrl","APP_PACKAGE","deployApp","options","listFiles","projectRoot","sourceDir","directory","run","runAppDeployment","type","reporter","cliConfig","flags","output","workDir","organizationId","app","appId","workbench","dryRun","deploySingletonConfig","deployApplication","hasInterfaces","appTitle","title","trim","name","assertDeployable","err","report","exitCode","USAGE_ERROR","message","solution","status","isAutoUpdating","version","moduleName","application","appCreated","external","isWorkbenchApp","slug","created","resolveAppApplication","build","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","undefined","successMessage","manifest","installationId","config","configAppType","appType","exposes","isSingleton","applicationType","applicationVersion","target","applicationId","interfaces","appName","exposesAppView","entry","logAppDeployed","length","action","url","syncApplicationTitle","shipAppDeployment","id","unattended","yes","titleUpdate","log","from","to","spin","start","updated","body","succeed","fail","warn","tarball","entries","pipe","isApp","error","clear","named"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/deploy/deployApp.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip} from 'node:zlib'\n\nimport {type AppVisibility, exitCodes} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {getCoreAppUrl} from '@sanity/cli-core/util'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {\n buildExposes,\n deployConfig,\n deployCoreApp as deployWorkbenchCoreApp,\n getApplicationUrl,\n getWorkbench,\n resolveInstallationId,\n summarizeConfig,\n} from '@sanity/workbench-cli/deploy'\nimport {pack} from 'tar-fs'\n\nimport {\n createDeployment,\n updateUserApplication,\n type UserApplication,\n type UserApplicationResolved,\n} from '../../services/userApplications.js'\nimport {getAppId} from '../../util/appId.js'\nimport {EXTERNAL_APP_NOT_SUPPORTED, NO_ORGANIZATION_ID} from '../../util/errorMessages.js'\nimport {buildApp} from '../build/buildApp.js'\nimport {extractCoreAppManifest, resolveTitleUpdate} from '../manifest/extractCoreAppManifest.js'\nimport {type CoreAppManifest} from '../manifest/types.js'\nimport {createUserApplication, generateAppSlug} from './createUserApplication.js'\nimport {\n checkAppId,\n checkAppTarget,\n checkAutoUpdates,\n checkBuild,\n checkPackageVersion,\n type DeployCheckReporter,\n verifyOutputDir,\n} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {listDeploymentFiles, reportExposes} from './deploymentPlan.js'\nimport {type DeployResult, runDeploy} from './deployRunner.js'\nimport {findUserApplication} from './findUserApplication.js'\nimport {type DeployAppOptions} from './types.js'\n\nconst APP_PACKAGE = '@sanity/sdk-react'\n\nexport function deployApp(options: DeployAppOptions): Promise<void> {\n return runDeploy(options, {\n listFiles: ({projectRoot, sourceDir}) => listDeploymentFiles(sourceDir, projectRoot.directory),\n run: runAppDeployment,\n type: 'coreApp',\n })\n}\n\n/** Validates the deploy, syncs the title from the manifest, and ships the build. */\nasync function runAppDeployment(\n options: DeployAppOptions,\n reporter: DeployCheckReporter,\n): Promise<DeployResult | void> {\n const {cliConfig, flags, output, sourceDir} = options\n const workDir = options.projectRoot.directory\n const organizationId = cliConfig.app?.organizationId\n const appId = getAppId(cliConfig)\n const workbench = getWorkbench(cliConfig)\n const dryRun = !!flags['dry-run']\n\n // A singleton (the Media Library) persists its config instead of hosting an\n // application; anything that exposes a view or service still ships one.\n const deploySingletonConfig = workbench?.deploySingletonConfig ?? false\n const deployApplication = !workbench || workbench.hasInterfaces\n\n const appTitle = workbench\n ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.name\n : ''\n\n // A federated app with no entry, view or service would ship a remote with\n // nothing to load — reported first so it fails before any prompt or API call.\n if (workbench) {\n try {\n workbench.assertDeployable()\n } catch (err) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: getErrorMessage(err),\n solution: 'Declare at least one entry, view, or service in the app',\n status: 'fail',\n })\n }\n }\n\n const isAutoUpdating = checkAutoUpdates(reporter, {cliConfig, flags})\n\n // An application ships the SDK runtime; a media-library config stamps its\n // `sanity` version instead.\n let version: string | null = null\n if (deployApplication) {\n version = await checkPackageVersion(reporter, {moduleName: APP_PACKAGE, workDir})\n } else if (deploySingletonConfig) {\n version = await checkPackageVersion(reporter, {moduleName: 'sanity', workDir})\n }\n\n reporter.report(\n organizationId\n ? {message: `Organization: ${organizationId}`, status: 'pass'}\n : {\n message: NO_ORGANIZATION_ID,\n solution: 'Add `app.organizationId` to sanity.cli.ts',\n status: 'fail',\n },\n )\n\n checkAppId(reporter, {cliConfig})\n\n let application: UserApplicationResolved | null = null\n let appCreated = false\n if (flags.external) {\n reporter.report({\n message: EXTERNAL_APP_NOT_SUPPORTED,\n solution: 'Remove the --external flag — apps deploy to Sanity hosting',\n status: 'fail',\n })\n } else if (deployApplication && workbench) {\n await checkAppTarget(reporter, {\n appId,\n isWorkbenchApp: true,\n slug: workbench.slug,\n title: appTitle,\n })\n } else if (deployApplication) {\n ;({application, created: appCreated} = await resolveAppApplication(options, {dryRun, reporter}))\n }\n\n await checkBuild(reporter, {\n build: () =>\n buildApp({\n autoUpdatesEnabled: isAutoUpdating,\n calledFromDeploy: true,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n }),\n skipReason: flags.build\n ? undefined\n : 'Build skipped (--no-build) — validating existing output directory',\n successMessage: 'App built',\n })\n\n await verifyOutputDir({isWorkbenchApp: workbench !== null, reporter, sourceDir})\n\n // Manifests aren't strictly essential, so a failure warns and continues\n let manifest: CoreAppManifest | undefined\n try {\n manifest = await extractCoreAppManifest({workDir})\n } catch (err) {\n deployDebug('Error extracting app manifest', err)\n reporter.report({\n message: `Error extracting app manifest: ${getErrorMessage(err)}`,\n status: 'warn',\n })\n }\n\n // Resolve the installation in both modes so the report — dry-run and real —\n // shows whether the config is deployable; a missing one fails the deploy here.\n let installationId: string | undefined\n let config: string | undefined\n const configAppType = workbench?.config?.appType\n if (deploySingletonConfig && organizationId && workbench?.config && configAppType) {\n installationId = await resolveInstallationId({appType: configAppType, organizationId})\n config = summarizeConfig(workbench.config)\n reporter.report(\n installationId\n ? {config, message: config, status: 'pass'}\n : {\n exitCode: exitCodes.USAGE_ERROR,\n message: `No active \"${configAppType}\" installation for organization \"${organizationId}\"`,\n solution: 'Install the Media Library for the organization before deploying its config',\n status: 'fail',\n },\n )\n }\n\n // Report the exposes deploying with the application, both modes.\n const exposes = deployApplication && workbench ? reportExposes(reporter, workbench) : []\n\n // Surface the app's explicit singleton flag when set, both modes.\n if (deployApplication && workbench?.isSingleton !== undefined) {\n reporter.report({\n isSingleton: workbench.isSingleton,\n message: `Singleton: ${workbench.isSingleton}`,\n status: 'pass',\n })\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return\n\n if (installationId && version && configAppType && organizationId) {\n await deployConfig({\n appType: configAppType,\n installationId,\n organizationId,\n output,\n sourceDir,\n version,\n })\n }\n\n // A config-only singleton ships no application, only its config.\n if (!deployApplication) {\n if (installationId && version) {\n return {\n applicationType: 'coreApp',\n applicationVersion: version,\n ...(config ? {config} : {}),\n installationId,\n target: null,\n }\n }\n return\n }\n\n // A real deploy already exited on a version-resolution failure; this narrows the type.\n if (!version) return\n\n // Workbench apps deploy to Brett; plain coreApps use user-applications.\n if (workbench && organizationId) {\n const appId = getAppId(cliConfig)\n const slug = workbench.slug ?? generateAppSlug()\n const {applicationId} = await deployWorkbenchCoreApp({\n appId,\n interfaces: buildExposes(workbench, {\n appName: workbench.name,\n appTitle,\n exposesAppView: workbench.entry !== undefined,\n version,\n }),\n isAutoUpdating,\n isSingleton: workbench.isSingleton,\n organizationId,\n slug,\n sourceDir,\n title: appTitle,\n version,\n visibility: workbench.visibility,\n })\n const url = getApplicationUrl({id: applicationId, organizationId, type: 'coreApp'})\n logAppDeployed({\n applicationId,\n cliConfig,\n created: !appId,\n organizationId,\n output,\n title: appTitle,\n url,\n })\n return {\n applicationType: 'coreApp',\n applicationVersion: version,\n ...(exposes.length > 0 ? {exposes} : {}),\n ...(workbench.isSingleton === undefined ? {} : {isSingleton: workbench.isSingleton}),\n target: {\n action: appId ? 'update' : 'create',\n applicationId,\n // A redeploy ignores the slug, so only a create reports the one it used.\n ...(appId ? {} : {slug}),\n title: appTitle,\n url,\n },\n }\n }\n\n // A real deploy has already exited if anything failed; landing here without a\n // resolved application means the deploy target was never resolved.\n if (!application) return\n\n application = await syncApplicationMetadata({\n application,\n manifest,\n output,\n visibility: cliConfig.app?.visibility,\n })\n await shipAppDeployment({application, isAutoUpdating, manifest, sourceDir, version})\n logAppDeployed({\n applicationId: application.id,\n cliConfig,\n created: appCreated,\n organizationId: application.organizationId,\n output,\n title: application.title,\n })\n return {\n applicationType: 'coreApp',\n applicationVersion: version,\n target: {\n action: appCreated ? 'create' : 'update',\n applicationId: application.id,\n title: application.title ?? null,\n url: getCoreAppUrl(application.organizationId, application.id),\n },\n }\n}\n\n/**\n * Finds the application a real deploy targets, creating one when none is\n * configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveAppApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplicationResolved | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const organizationId = cliConfig.app?.organizationId ?? ''\n // Create name from --title or `app.title` config; blank falls back to the prompt\n const title = flags.title?.trim() || cliConfig.app?.title?.trim() || undefined\n\n if (dryRun) {\n await checkAppTarget(reporter, {appId: getAppId(cliConfig), organizationId, title})\n return {application: null, created: false}\n }\n\n let application = await findUserApplication({\n cliConfig,\n organizationId,\n output,\n title,\n unattended: !!flags.yes,\n })\n deployDebug('User application found', application)\n\n if (!application) {\n deployDebug('No user application found. Creating a new one')\n application = await createUserApplication(organizationId, title, cliConfig.app?.visibility)\n deployDebug('User application created', application)\n return {application, created: true}\n }\n\n return {application, created: false}\n}\n\n/**\n * Syncs application metadata on redeploy when it has changed: the title from the\n * manifest and the dashboard visibility from config. Sends a single PATCH with\n * only the changed fields, and skips the request entirely when nothing changed.\n */\nexport async function syncApplicationMetadata({\n application,\n manifest,\n output,\n visibility,\n}: {\n application: UserApplicationResolved\n manifest: CoreAppManifest | undefined\n output: DeployAppOptions['output']\n visibility: AppVisibility | undefined\n}): Promise<UserApplicationResolved> {\n const titleUpdate = resolveTitleUpdate(manifest, application)\n // Treat an unset server value as `default` so a config of `default` is a no-op.\n const visibilityChanged =\n visibility !== undefined && visibility !== (application.dashboardStatus ?? 'default')\n\n if (!titleUpdate && !visibilityChanged) return application\n\n if (titleUpdate) {\n deployDebug('Updating application title from manifest', titleUpdate)\n output.log(\n titleUpdate.from\n ? `Updating title from \"${titleUpdate.from}\" to \"${titleUpdate.to}\"`\n : `Setting application title to \"${titleUpdate.to}\"`,\n )\n }\n if (visibilityChanged) {\n output.log(`Setting dashboard visibility to \"${visibility}\"`)\n }\n\n const spin = spinner('Updating application').start()\n try {\n const updated = await updateUserApplication({\n applicationId: application.id,\n appType: 'coreApp',\n body: {\n ...(titleUpdate ? {title: titleUpdate.to} : {}),\n ...(visibilityChanged ? {dashboardStatus: visibility} : {}),\n },\n })\n spin.succeed()\n return updated\n } catch (err) {\n spin.fail()\n const message = getErrorMessage(err)\n deployDebug('Error updating application metadata', {message})\n output.warn(`Error updating application metadata: ${message}`)\n return application\n }\n}\n\nasync function shipAppDeployment({\n application,\n isAutoUpdating,\n manifest,\n sourceDir,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n manifest: CoreAppManifest | undefined\n sourceDir: string\n version: string\n}): Promise<void> {\n const tarball = pack(dirname(sourceDir), {entries: [basename(sourceDir)]}).pipe(createGzip())\n\n const spin = spinner('Deploying...').start()\n try {\n await createDeployment({\n applicationId: application.id,\n isApp: true,\n isAutoUpdating,\n manifest,\n tarball,\n version,\n })\n } catch (error) {\n spin.clear()\n throw error\n }\n spin.succeed()\n}\n\nexport function logAppDeployed({\n applicationId,\n cliConfig,\n created,\n organizationId,\n output,\n title,\n url = getCoreAppUrl(organizationId, applicationId),\n}: {\n applicationId: string\n cliConfig: DeployAppOptions['cliConfig']\n created: boolean\n organizationId: string\n output: DeployAppOptions['output']\n title: string | null\n url?: string\n}): void {\n const named = title ? ` — \"${title}\"` : ''\n output.log(`\\nSuccess! Application deployed to ${styleText('cyan', url)}${named}`)\n output.log(created ? 'Created a new application.' : 'Updated the existing application.')\n\n if (getAppId(cliConfig)) return\n\n output.log(`\\n════ ${styleText('bold', 'Next step:')} ════`)\n if (created) {\n output.log(\n styleText(\n 'yellow',\n '\\nDeploying again without `deployment.appId` creates another new application.',\n ),\n )\n }\n output.log(\n styleText('bold', '\\nAdd the deployment.appId to your sanity.cli.js or sanity.cli.ts file:'),\n )\n output.log(`\n${styleText(\n 'dim',\n `app: {\n // your application config here…\n}`,\n)},\n${styleText(\n ['bold', 'green'],\n `deployment: {\n appId: '${applicationId}',\n}\\n`,\n)}`)\n}\n"],"names":["basename","dirname","styleText","createGzip","exitCodes","getErrorMessage","getCoreAppUrl","spinner","buildExposes","deployConfig","deployCoreApp","deployWorkbenchCoreApp","getApplicationUrl","getWorkbench","resolveInstallationId","summarizeConfig","pack","createDeployment","updateUserApplication","getAppId","EXTERNAL_APP_NOT_SUPPORTED","NO_ORGANIZATION_ID","buildApp","extractCoreAppManifest","resolveTitleUpdate","createUserApplication","generateAppSlug","checkAppId","checkAppTarget","checkAutoUpdates","checkBuild","checkPackageVersion","verifyOutputDir","deployDebug","listDeploymentFiles","reportExposes","runDeploy","findUserApplication","APP_PACKAGE","deployApp","options","listFiles","projectRoot","sourceDir","directory","run","runAppDeployment","type","reporter","cliConfig","flags","output","workDir","organizationId","app","appId","workbench","dryRun","deploySingletonConfig","deployApplication","hasInterfaces","appTitle","title","trim","name","assertDeployable","err","report","exitCode","USAGE_ERROR","message","solution","status","isAutoUpdating","version","moduleName","application","appCreated","external","isWorkbenchApp","slug","created","resolveAppApplication","build","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","undefined","successMessage","manifest","installationId","config","configAppType","appType","exposes","isSingleton","applicationType","applicationVersion","target","applicationId","interfaces","appName","exposesAppView","entry","visibility","url","id","logAppDeployed","length","action","syncApplicationMetadata","shipAppDeployment","unattended","yes","titleUpdate","visibilityChanged","dashboardStatus","log","from","to","spin","start","updated","body","succeed","fail","warn","tarball","entries","pipe","isApp","error","clear","named"],"mappings":"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"}
|