@sanity/cli 7.15.1 → 7.17.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 +87 -0
- package/dist/actions/build/shouldAutoUpdate.js +28 -5
- package/dist/actions/build/shouldAutoUpdate.js.map +1 -1
- package/dist/actions/deploy/deployApp.js +4 -8
- package/dist/actions/deploy/deployApp.js.map +1 -1
- package/dist/actions/deploy/deployChecks.js +49 -31
- package/dist/actions/deploy/deployChecks.js.map +1 -1
- package/dist/actions/deploy/deployRunner.js +1 -1
- package/dist/actions/deploy/deployRunner.js.map +1 -1
- package/dist/actions/deploy/deployStudio.js +12 -10
- package/dist/actions/deploy/deployStudio.js.map +1 -1
- package/dist/actions/deploy/deploymentPlan.js +2 -2
- package/dist/actions/deploy/deploymentPlan.js.map +1 -1
- package/dist/actions/deploy/resolveDeployTarget.js +13 -13
- package/dist/actions/deploy/resolveDeployTarget.js.map +1 -1
- package/dist/actions/init/bootstrapLocalTemplate.js +2 -3
- package/dist/actions/init/bootstrapLocalTemplate.js.map +1 -1
- package/dist/actions/init/createAppCliConfig.js.map +1 -1
- package/dist/actions/init/createCliConfig.js.map +1 -1
- package/dist/actions/init/initNextJs.js +1 -1
- package/dist/actions/init/initNextJs.js.map +1 -1
- package/dist/actions/init/initStudio.js +10 -6
- package/dist/actions/init/initStudio.js.map +1 -1
- package/dist/actions/init/templates/appSanityUi.js +1 -1
- package/dist/actions/init/templates/appSanityUi.js.map +1 -1
- package/dist/actions/init/templates/getStarted.js +2 -2
- package/dist/actions/init/templates/getStarted.js.map +1 -1
- package/dist/actions/init/templates/nextjs/schemaTypes/blog.js +4 -4
- package/dist/actions/init/templates/nextjs/schemaTypes/blog.js.map +1 -1
- package/dist/actions/init/templates/shopify.js +5 -5
- package/dist/actions/init/templates/shopify.js.map +1 -1
- package/dist/actions/init/templates/shopifyOnline.js +3 -3
- package/dist/actions/init/templates/shopifyOnline.js.map +1 -1
- package/dist/actions/manifest/extractCoreAppManifest.js +7 -7
- package/dist/actions/manifest/extractCoreAppManifest.js.map +1 -1
- package/dist/actions/scaffold/createFrontend.js +107 -0
- package/dist/actions/scaffold/createFrontend.js.map +1 -0
- package/dist/actions/scaffold/scaffoldProject.js +202 -0
- package/dist/actions/scaffold/scaffoldProject.js.map +1 -0
- package/dist/commands/backups/list.js +1 -1
- package/dist/commands/backups/list.js.map +1 -1
- package/dist/commands/migrations/list.js +1 -1
- package/dist/commands/migrations/list.js.map +1 -1
- package/dist/commands/migrations/run.js +1 -1
- package/dist/commands/migrations/run.js.map +1 -1
- package/dist/commands/new.js +309 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/organizations/list.js +1 -1
- package/dist/commands/organizations/list.js.map +1 -1
- package/dist/commands/projects/unclaimed.js +205 -0
- package/dist/commands/projects/unclaimed.js.map +1 -0
- package/dist/commands/tokens/list.js +1 -1
- package/dist/commands/tokens/list.js.map +1 -1
- package/dist/commands/users/list.js +5 -1
- package/dist/commands/users/list.js.map +1 -1
- package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js +4 -0
- package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js.map +1 -1
- package/dist/exports/runtime.d.ts +24 -0
- package/dist/exports/runtime.js.map +1 -1
- package/dist/services/mintProject.js +91 -0
- package/dist/services/mintProject.js.map +1 -0
- package/dist/services/projects.js +19 -0
- package/dist/services/projects.js.map +1 -1
- package/dist/util/formatClaimDeadline.js +15 -0
- package/dist/util/formatClaimDeadline.js.map +1 -0
- package/dist/util/mintProjectConstants.js +6 -0
- package/dist/util/mintProjectConstants.js.map +1 -0
- package/dist/util/newCommandSplash.js +27 -0
- package/dist/util/newCommandSplash.js.map +1 -0
- package/dist/util/packageManager/installPackages.js +57 -28
- package/dist/util/packageManager/installPackages.js.map +1 -1
- package/dist/util/unclaimedProjects.js +105 -0
- package/dist/util/unclaimedProjects.js.map +1 -0
- package/oclif.config.js +1 -0
- package/oclif.manifest.json +111 -1
- package/package.json +6 -6
- package/templates/get-started/plugins/sanity-plugin-tutorial/GetStartedTutorial.tsx +1 -1
- package/templates/shopify/components/inputs/CollectionHidden.tsx +1 -1
- package/templates/shopify/components/inputs/ProductHidden.tsx +1 -1
- package/templates/shopify/components/inputs/ProductVariantHidden.tsx +1 -1
- package/templates/shopify/components/inputs/ProxyString.tsx +1 -1
- package/templates/shopify/components/media/ShopifyDocumentStatus.tsx +3 -1
- package/templates/shopify/constants.ts +3 -1
- package/templates/shopify/plugins/customDocumentActions/shopifyDelete.tsx +1 -1
- package/templates/shopify/plugins/customDocumentActions/shopifyLink.ts +1 -1
- package/templates/shopify/schemaTypes/documents/collection.tsx +1 -1
- package/templates/shopify/schemaTypes/documents/colorTheme.tsx +1 -1
- package/templates/shopify/schemaTypes/documents/page.ts +1 -1
- package/templates/shopify/schemaTypes/documents/product.tsx +1 -1
- package/templates/shopify/schemaTypes/documents/productVariant.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/collection/collectionGroupType.ts +1 -1
- package/templates/shopify/schemaTypes/objects/hotspot/imageWithProductHotspotsType.ts +1 -1
- package/templates/shopify/schemaTypes/objects/link/linkEmailType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/link/linkExternalType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/link/linkInternalType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/link/linkProductType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/module/accordionType.ts +1 -1
- package/templates/shopify/schemaTypes/objects/module/callToActionType.tsx +2 -1
- package/templates/shopify/schemaTypes/objects/module/calloutType.ts +1 -1
- package/templates/shopify/schemaTypes/objects/module/collectionReferenceType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/module/gridType.ts +1 -1
- package/templates/shopify/schemaTypes/objects/module/imageFeatureType.ts +1 -1
- package/templates/shopify/schemaTypes/objects/module/imageFeaturesType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/module/instagramType.ts +1 -1
- package/templates/shopify/schemaTypes/objects/module/productFeaturesType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/module/productReferenceType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/shopify/collectionRuleType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/shopify/optionType.tsx +1 -1
- package/templates/shopify/schemaTypes/objects/shopify/productWithVariantType.tsx +1 -1
- package/templates/shopify/schemaTypes/singletons/homeType.ts +1 -1
- package/templates/shopify/schemaTypes/singletons/settingsType.ts +5 -1
- package/templates/shopify/structure/pageStructure.ts +1 -1
- package/templates/shopify/structure/productStructure.ts +1 -1
- package/templates/shopify-online-storefront/components/inputs/CollectionHidden.tsx +1 -1
- package/templates/shopify-online-storefront/components/inputs/ProductHidden.tsx +1 -1
- package/templates/shopify-online-storefront/components/inputs/ProductVariantHidden.tsx +1 -1
- package/templates/shopify-online-storefront/components/inputs/ProxyString.tsx +1 -1
- package/templates/shopify-online-storefront/components/media/ShopifyDocumentStatus.tsx +3 -1
- package/templates/shopify-online-storefront/plugins/shopifyDocumentActions/shopifyDelete.tsx +1 -1
- package/templates/shopify-online-storefront/plugins/shopifyDocumentActions/shopifyLink.ts +1 -1
- package/templates/shopify-online-storefront/schemaTypes/documents/collection.tsx +1 -1
- package/templates/shopify-online-storefront/schemaTypes/documents/product.tsx +1 -1
- package/templates/shopify-online-storefront/schemaTypes/documents/productVariant.tsx +1 -1
- package/templates/shopify-online-storefront/schemaTypes/objects/accordion.ts +1 -1
- package/templates/shopify-online-storefront/schemaTypes/objects/callout.ts +1 -1
- package/templates/shopify-online-storefront/schemaTypes/objects/option.ts +1 -1
- package/templates/shopify-online-storefront/schemaTypes/objects/shopifyCollectionRule.tsx +1 -1
- package/templates/shopify-online-storefront/structure/productStructure.ts +1 -1
package/README.md
CHANGED
|
@@ -95,6 +95,7 @@ Code for sanity cli
|
|
|
95
95
|
- [`sanity migrations create [TITLE]`](#sanity-migrations-create-title)
|
|
96
96
|
- [`sanity migrations list`](#sanity-migrations-list)
|
|
97
97
|
- [`sanity migrations run [ID]`](#sanity-migrations-run-id)
|
|
98
|
+
- [`sanity new [PROJECTNAME]`](#sanity-new-projectname)
|
|
98
99
|
- [`sanity openapi get SLUG`](#sanity-openapi-get-slug)
|
|
99
100
|
- [`sanity openapi list`](#sanity-openapi-list)
|
|
100
101
|
- [`sanity organizations create`](#sanity-organizations-create)
|
|
@@ -105,6 +106,7 @@ Code for sanity cli
|
|
|
105
106
|
- [`sanity preview [OUTPUTDIR]`](#sanity-preview-outputdir)
|
|
106
107
|
- [`sanity projects create [PROJECTNAME]`](#sanity-projects-create-projectname)
|
|
107
108
|
- [`sanity projects list`](#sanity-projects-list)
|
|
109
|
+
- [`sanity projects unclaimed`](#sanity-projects-unclaimed)
|
|
108
110
|
- [`sanity schemas delete`](#sanity-schemas-delete)
|
|
109
111
|
- [`sanity schemas deploy`](#sanity-schemas-deploy)
|
|
110
112
|
- [`sanity schemas extract`](#sanity-schemas-extract)
|
|
@@ -2964,6 +2966,67 @@ EXAMPLES
|
|
|
2964
2966
|
$ sanity migrations run <id> --from-export=production.tar.gz --no-dry-run --project xyz --dataset staging
|
|
2965
2967
|
```
|
|
2966
2968
|
|
|
2969
|
+
## `sanity new [PROJECTNAME]`
|
|
2970
|
+
|
|
2971
|
+
Create a Sanity project without an account, and claim it within 72 hours to keep it.
|
|
2972
|
+
|
|
2973
|
+
```
|
|
2974
|
+
USAGE
|
|
2975
|
+
$ sanity new [PROJECTNAME] [--json] [--scaffold] [-y]
|
|
2976
|
+
|
|
2977
|
+
ARGUMENTS
|
|
2978
|
+
[PROJECTNAME] Display name for the new project
|
|
2979
|
+
|
|
2980
|
+
FLAGS
|
|
2981
|
+
-y, --yes Skip prompts and use defaults (project: "My Sanity project")
|
|
2982
|
+
--[no-]scaffold Set up a Studio in ./sanity and a Next.js website in ./web (on by default)
|
|
2983
|
+
|
|
2984
|
+
GLOBAL FLAGS
|
|
2985
|
+
--json Format output as json.
|
|
2986
|
+
|
|
2987
|
+
DESCRIPTION
|
|
2988
|
+
Create a Sanity project without an account, and claim it within 72 hours to keep it.
|
|
2989
|
+
|
|
2990
|
+
Sets up two folders here: ./sanity, a Studio where you write and edit your
|
|
2991
|
+
content, and ./web, a Next.js website that reads it. Both are already
|
|
2992
|
+
connected to your new project, so you can start them straight away. Use
|
|
2993
|
+
--no-scaffold if you just want the project and nothing else.
|
|
2994
|
+
|
|
2995
|
+
The project is real and works immediately, but it is only yours for 72 hours.
|
|
2996
|
+
Claim it with a Sanity account before the deadline and everything you have
|
|
2997
|
+
built stays exactly as it is. Claiming is free and takes about a minute. Miss
|
|
2998
|
+
the deadline and the project and its content are deleted.
|
|
2999
|
+
|
|
3000
|
+
Two things to keep private: the claim link, because anyone who opens it
|
|
3001
|
+
becomes the owner, and the access token saved in ./sanity/.env.local and
|
|
3002
|
+
./web/.env.local, because it can read and change everything in the project.
|
|
3003
|
+
Keep both env files out of git, and never put the token in code that runs in
|
|
3004
|
+
the browser.
|
|
3005
|
+
|
|
3006
|
+
Fetch https://sanity.new for full instructions, or point your AI agent at it.
|
|
3007
|
+
|
|
3008
|
+
EXAMPLES
|
|
3009
|
+
Create a project with a Studio and a website
|
|
3010
|
+
|
|
3011
|
+
$ sanity new
|
|
3012
|
+
|
|
3013
|
+
Create a project called "My New Project"
|
|
3014
|
+
|
|
3015
|
+
$ sanity new "My New Project"
|
|
3016
|
+
|
|
3017
|
+
Create a project without being asked anything
|
|
3018
|
+
|
|
3019
|
+
$ sanity new --yes
|
|
3020
|
+
|
|
3021
|
+
Create the project only, with no Studio or website
|
|
3022
|
+
|
|
3023
|
+
$ sanity new --no-scaffold
|
|
3024
|
+
|
|
3025
|
+
Create a project and print its details as JSON
|
|
3026
|
+
|
|
3027
|
+
$ sanity new --json
|
|
3028
|
+
```
|
|
3029
|
+
|
|
2967
3030
|
## `sanity openapi get SLUG`
|
|
2968
3031
|
|
|
2969
3032
|
Get an OpenAPI specification by slug
|
|
@@ -3255,6 +3318,30 @@ EXAMPLES
|
|
|
3255
3318
|
$ sanity projects list --sort=members --order=asc
|
|
3256
3319
|
```
|
|
3257
3320
|
|
|
3321
|
+
## `sanity projects unclaimed`
|
|
3322
|
+
|
|
3323
|
+
Recover details for unclaimed projects created on this machine
|
|
3324
|
+
|
|
3325
|
+
```
|
|
3326
|
+
USAGE
|
|
3327
|
+
$ sanity projects unclaimed [--project-id <value>]
|
|
3328
|
+
|
|
3329
|
+
FLAGS
|
|
3330
|
+
--project-id=<value> Project ID to recover
|
|
3331
|
+
|
|
3332
|
+
DESCRIPTION
|
|
3333
|
+
Recover details for unclaimed projects created on this machine
|
|
3334
|
+
|
|
3335
|
+
EXAMPLES
|
|
3336
|
+
List locally recorded unclaimed projects
|
|
3337
|
+
|
|
3338
|
+
$ sanity projects unclaimed
|
|
3339
|
+
|
|
3340
|
+
Show recovery details for one project
|
|
3341
|
+
|
|
3342
|
+
$ sanity projects unclaimed --project-id abc123
|
|
3343
|
+
```
|
|
3344
|
+
|
|
3258
3345
|
## `sanity schemas delete`
|
|
3259
3346
|
|
|
3260
3347
|
Delete schema documents by id
|
|
@@ -1,12 +1,30 @@
|
|
|
1
1
|
import { styleText } from 'node:util';
|
|
2
|
+
import { isWorkbenchApp } from '@sanity/workbench-cli';
|
|
2
3
|
/**
|
|
3
|
-
* Owns the auto-update rules
|
|
4
|
-
*
|
|
5
|
-
* Returns plain facts so each surface (deploy warnings, dry-run checks)
|
|
6
|
-
* decides its own presentation.
|
|
4
|
+
* Owns the auto-update rules and returns plain facts, so each surface (build,
|
|
5
|
+
* dev, deploy warnings, dry-run checks) decides its own presentation.
|
|
7
6
|
*
|
|
8
7
|
* @internal
|
|
9
|
-
*/ export function resolveAutoUpdates(
|
|
8
|
+
*/ export function resolveAutoUpdates(sources) {
|
|
9
|
+
const settings = resolveConfiguredAutoUpdates(sources);
|
|
10
|
+
// A workbench app takes `sanity` from the shell's shared runtime, so it has no
|
|
11
|
+
// version of its own to pin.
|
|
12
|
+
// TODO(SDK-1045): confirm the long-term story with the studio team.
|
|
13
|
+
if (settings.enabled && isWorkbenchApp(sources.cliConfig?.app)) {
|
|
14
|
+
// A config conflict still fails — it's a problem with the config itself.
|
|
15
|
+
return settings.issue?.type === 'conflicting-config' ? {
|
|
16
|
+
enabled: false,
|
|
17
|
+
issue: settings.issue
|
|
18
|
+
} : {
|
|
19
|
+
enabled: false,
|
|
20
|
+
issue: {
|
|
21
|
+
type: 'unsupported'
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return settings;
|
|
26
|
+
}
|
|
27
|
+
function resolveConfiguredAutoUpdates({ cliConfig, flags }) {
|
|
10
28
|
// Flags always take precedence over config
|
|
11
29
|
if ('auto-updates' in flags) {
|
|
12
30
|
const enabled = Boolean(flags['auto-updates']);
|
|
@@ -61,6 +79,10 @@ import { styleText } from 'node:util';
|
|
|
61
79
|
{
|
|
62
80
|
return `The ${issue.flag} flag is deprecated for deploy and build commands. Set the autoUpdates option in the deployment section of sanity.cli.ts or sanity.cli.js instead.`;
|
|
63
81
|
}
|
|
82
|
+
case 'unsupported':
|
|
83
|
+
{
|
|
84
|
+
return "Auto-updates aren't supported yet — using the installed package versions";
|
|
85
|
+
}
|
|
64
86
|
}
|
|
65
87
|
}
|
|
66
88
|
/**
|
|
@@ -100,6 +122,7 @@ import { styleText } from 'node:util';
|
|
|
100
122
|
break;
|
|
101
123
|
}
|
|
102
124
|
case 'deprecated-flag':
|
|
125
|
+
case 'unsupported':
|
|
103
126
|
{
|
|
104
127
|
output.warn(getAutoUpdateIssueMessage(issue));
|
|
105
128
|
break;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/build/shouldAutoUpdate.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {type CliConfig, type Output} from '@sanity/cli-core'\n\nimport {type DeployFlags} from '../deploy/types.js'\nimport {type DevFlags} from '../dev/types.js'\nimport {type BuildFlags} from './types.js'\n\ninterface AutoUpdateSources {\n cliConfig: CliConfig\n flags: BuildFlags | DeployFlags | DevFlags\n}\n\n/**\n * The single auto-update configuration problem to surface, if any.\n * Flag usage takes precedence over config problems: when the deprecated flag\n * is passed, config is not consulted, so config issues are not reported.\n */\ntype AutoUpdateIssue =\n | {flag: '--auto-updates' | '--no-auto-updates'; type: 'deprecated-flag'}\n | {type: 'conflicting-config'}\n | {type: 'deprecated-config'}\n\nexport interface AutoUpdateSettings {\n enabled: boolean\n issue: AutoUpdateIssue | null\n}\n\n/**\n * Owns the auto-update rules
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/build/shouldAutoUpdate.ts"],"sourcesContent":["import {styleText} from 'node:util'\n\nimport {type CliConfig, type Output} from '@sanity/cli-core'\nimport {isWorkbenchApp} from '@sanity/workbench-cli'\n\nimport {type DeployFlags} from '../deploy/types.js'\nimport {type DevFlags} from '../dev/types.js'\nimport {type BuildFlags} from './types.js'\n\ninterface AutoUpdateSources {\n cliConfig: CliConfig\n flags: BuildFlags | DeployFlags | DevFlags\n}\n\n/**\n * The single auto-update configuration problem to surface, if any.\n * Flag usage takes precedence over config problems: when the deprecated flag\n * is passed, config is not consulted, so config issues are not reported.\n */\ntype AutoUpdateIssue =\n | {flag: '--auto-updates' | '--no-auto-updates'; type: 'deprecated-flag'}\n | {type: 'conflicting-config'}\n | {type: 'deprecated-config'}\n | {type: 'unsupported'}\n\nexport interface AutoUpdateSettings {\n enabled: boolean\n issue: AutoUpdateIssue | null\n}\n\n/**\n * Owns the auto-update rules and returns plain facts, so each surface (build,\n * dev, deploy warnings, dry-run checks) decides its own presentation.\n *\n * @internal\n */\nexport function resolveAutoUpdates(sources: AutoUpdateSources): AutoUpdateSettings {\n const settings = resolveConfiguredAutoUpdates(sources)\n\n // A workbench app takes `sanity` from the shell's shared runtime, so it has no\n // version of its own to pin.\n // TODO(SDK-1045): confirm the long-term story with the studio team.\n if (settings.enabled && isWorkbenchApp(sources.cliConfig?.app)) {\n // A config conflict still fails — it's a problem with the config itself.\n return settings.issue?.type === 'conflicting-config'\n ? {enabled: false, issue: settings.issue}\n : {enabled: false, issue: {type: 'unsupported'}}\n }\n\n return settings\n}\n\nfunction resolveConfiguredAutoUpdates({cliConfig, flags}: AutoUpdateSources): AutoUpdateSettings {\n // Flags always take precedence over config\n if ('auto-updates' in flags) {\n const enabled = Boolean(flags['auto-updates'])\n return {\n enabled,\n issue: {flag: enabled ? '--auto-updates' : '--no-auto-updates', type: 'deprecated-flag'},\n }\n }\n\n const hasOldConfig = cliConfig && 'autoUpdates' in cliConfig\n\n const hasNewConfig =\n cliConfig &&\n 'deployment' in cliConfig &&\n cliConfig.deployment &&\n 'autoUpdates' in cliConfig.deployment\n\n if (hasNewConfig) {\n return {\n enabled: Boolean(cliConfig?.deployment?.autoUpdates),\n issue: hasOldConfig ? {type: 'conflicting-config'} : null,\n }\n }\n\n if (hasOldConfig) {\n return {enabled: Boolean(cliConfig?.autoUpdates), issue: {type: 'deprecated-config'}}\n }\n\n return {enabled: false, issue: null}\n}\n\n/**\n * The user-facing message for an auto-update configuration problem.\n * Shared by every surface that reports the issue (deploy warnings, dry-run\n * checks) so the wording has one home.\n *\n * @internal\n */\nexport function getAutoUpdateIssueMessage(issue: AutoUpdateIssue): string {\n switch (issue.type) {\n case 'conflicting-config': {\n return 'Found both `autoUpdates` (deprecated) and `deployment.autoUpdates` in sanity.cli.js/.ts. Please remove the deprecated top level `autoUpdates` config.'\n }\n case 'deprecated-config': {\n return 'The autoUpdates config has moved to deployment.autoUpdates.'\n }\n case 'deprecated-flag': {\n return `The ${issue.flag} flag is deprecated for deploy and build commands. Set the autoUpdates option in the deployment section of sanity.cli.ts or sanity.cli.js instead.`\n }\n case 'unsupported': {\n return \"Auto-updates aren't supported yet — using the installed package versions\"\n }\n }\n}\n\n/**\n * The styled before/after edit that migrates the deprecated top-level\n * `autoUpdates` to `deployment.autoUpdates`. Lives here so every surface that\n * reports the deprecated config (deploy warnings, dry-run checks) shows the\n * same migration hint.\n *\n * @internal\n */\nexport function getAutoUpdateMigrationHint(currentValue: unknown): string {\n return `Please update sanity.cli.ts or sanity.cli.js and make the following change:\n ${styleText('red', `- autoUpdates: ${currentValue},`)}\n ${styleText('green', `+ deployment: {autoUpdates: ${currentValue}}`)}\n`\n}\n\n/**\n * Resolves the auto-update setting and prints any configuration problem.\n * @remarks Throws an error if both the old and new auto update config are used; throws a warning if the old config is used, or if the auto updates flags are used.\n * @internal\n */\nexport function shouldAutoUpdate({\n cliConfig,\n flags,\n output,\n}: AutoUpdateSources & {output: Output}): boolean {\n const {enabled, issue} = resolveAutoUpdates({cliConfig, flags})\n\n switch (issue?.type) {\n case 'conflicting-config': {\n output.error(getAutoUpdateIssueMessage(issue), {exit: 1})\n break\n }\n case 'deprecated-config': {\n output.warn(getAutoUpdateIssueMessage(issue))\n output.warn(getAutoUpdateMigrationHint(cliConfig.autoUpdates))\n break\n }\n case 'deprecated-flag':\n case 'unsupported': {\n output.warn(getAutoUpdateIssueMessage(issue))\n break\n }\n default: {\n break\n }\n }\n\n return enabled\n}\n"],"names":["styleText","isWorkbenchApp","resolveAutoUpdates","sources","settings","resolveConfiguredAutoUpdates","enabled","cliConfig","app","issue","type","flags","Boolean","flag","hasOldConfig","hasNewConfig","deployment","autoUpdates","getAutoUpdateIssueMessage","getAutoUpdateMigrationHint","currentValue","shouldAutoUpdate","output","error","exit","warn"],"mappings":"AAAA,SAAQA,SAAS,QAAO,YAAW;AAGnC,SAAQC,cAAc,QAAO,wBAAuB;AA2BpD;;;;;CAKC,GACD,OAAO,SAASC,mBAAmBC,OAA0B;IAC3D,MAAMC,WAAWC,6BAA6BF;IAE9C,+EAA+E;IAC/E,6BAA6B;IAC7B,oEAAoE;IACpE,IAAIC,SAASE,OAAO,IAAIL,eAAeE,QAAQI,SAAS,EAAEC,MAAM;QAC9D,yEAAyE;QACzE,OAAOJ,SAASK,KAAK,EAAEC,SAAS,uBAC5B;YAACJ,SAAS;YAAOG,OAAOL,SAASK,KAAK;QAAA,IACtC;YAACH,SAAS;YAAOG,OAAO;gBAACC,MAAM;YAAa;QAAC;IACnD;IAEA,OAAON;AACT;AAEA,SAASC,6BAA6B,EAACE,SAAS,EAAEI,KAAK,EAAoB;IACzE,2CAA2C;IAC3C,IAAI,kBAAkBA,OAAO;QAC3B,MAAML,UAAUM,QAAQD,KAAK,CAAC,eAAe;QAC7C,OAAO;YACLL;YACAG,OAAO;gBAACI,MAAMP,UAAU,mBAAmB;gBAAqBI,MAAM;YAAiB;QACzF;IACF;IAEA,MAAMI,eAAeP,aAAa,iBAAiBA;IAEnD,MAAMQ,eACJR,aACA,gBAAgBA,aAChBA,UAAUS,UAAU,IACpB,iBAAiBT,UAAUS,UAAU;IAEvC,IAAID,cAAc;QAChB,OAAO;YACLT,SAASM,QAAQL,WAAWS,YAAYC;YACxCR,OAAOK,eAAe;gBAACJ,MAAM;YAAoB,IAAI;QACvD;IACF;IAEA,IAAII,cAAc;QAChB,OAAO;YAACR,SAASM,QAAQL,WAAWU;YAAcR,OAAO;gBAACC,MAAM;YAAmB;QAAC;IACtF;IAEA,OAAO;QAACJ,SAAS;QAAOG,OAAO;IAAI;AACrC;AAEA;;;;;;CAMC,GACD,OAAO,SAASS,0BAA0BT,KAAsB;IAC9D,OAAQA,MAAMC,IAAI;QAChB,KAAK;YAAsB;gBACzB,OAAO;YACT;QACA,KAAK;YAAqB;gBACxB,OAAO;YACT;QACA,KAAK;YAAmB;gBACtB,OAAO,CAAC,IAAI,EAAED,MAAMI,IAAI,CAAC,kJAAkJ,CAAC;YAC9K;QACA,KAAK;YAAe;gBAClB,OAAO;YACT;IACF;AACF;AAEA;;;;;;;CAOC,GACD,OAAO,SAASM,2BAA2BC,YAAqB;IAC9D,OAAO,CAAC;EACR,EAAEpB,UAAU,OAAO,CAAC,gBAAgB,EAAEoB,aAAa,CAAC,CAAC,EAAE;EACvD,EAAEpB,UAAU,SAAS,CAAC,6BAA6B,EAAEoB,aAAa,CAAC,CAAC,EAAE;AACxE,CAAC;AACD;AAEA;;;;CAIC,GACD,OAAO,SAASC,iBAAiB,EAC/Bd,SAAS,EACTI,KAAK,EACLW,MAAM,EAC+B;IACrC,MAAM,EAAChB,OAAO,EAAEG,KAAK,EAAC,GAAGP,mBAAmB;QAACK;QAAWI;IAAK;IAE7D,OAAQF,OAAOC;QACb,KAAK;YAAsB;gBACzBY,OAAOC,KAAK,CAACL,0BAA0BT,QAAQ;oBAACe,MAAM;gBAAC;gBACvD;YACF;QACA,KAAK;YAAqB;gBACxBF,OAAOG,IAAI,CAACP,0BAA0BT;gBACtCa,OAAOG,IAAI,CAACN,2BAA2BZ,UAAUU,WAAW;gBAC5D;YACF;QACA,KAAK;QACL,KAAK;YAAe;gBAClBK,OAAOG,IAAI,CAACP,0BAA0BT;gBACtC;YACF;QACA;YAAS;gBACP;YACF;IACF;IAEA,OAAOH;AACT"}
|
|
@@ -5,7 +5,7 @@ import { exitCodes } from '@sanity/cli-core';
|
|
|
5
5
|
import { getErrorMessage } from '@sanity/cli-core/errors';
|
|
6
6
|
import { getCoreAppUrl } from '@sanity/cli-core/util';
|
|
7
7
|
import { spinner } from '@sanity/cli-core/ux';
|
|
8
|
-
import {
|
|
8
|
+
import { createCoreApp, deployConfig, deployWorkbenchApp, getApplicationUrl, getWorkbench, resolveInstallationId, summarizeConfig } from '@sanity/workbench-cli/deploy';
|
|
9
9
|
import { pack } from 'tar-fs';
|
|
10
10
|
import { createDeployment, updateUserApplication } from '../../services/userApplications.js';
|
|
11
11
|
import { getAppId } from '../../util/appId.js';
|
|
@@ -37,7 +37,7 @@ export function deployApp(options) {
|
|
|
37
37
|
// application; anything that exposes a view or service still ships one.
|
|
38
38
|
const deploySingletonConfig = workbench?.deploySingletonConfig ?? false;
|
|
39
39
|
const deployApplication = !workbench || workbench.hasInterfaces;
|
|
40
|
-
const appTitle = workbench ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.
|
|
40
|
+
const appTitle = workbench ? flags.title?.trim() || cliConfig.app?.title?.trim() || workbench.slug : '';
|
|
41
41
|
// A federated app with no entry, view or service would ship a remote with
|
|
42
42
|
// nothing to load — reported first so it fails before any prompt or API call.
|
|
43
43
|
if (workbench) {
|
|
@@ -241,14 +241,10 @@ export function deployApp(options) {
|
|
|
241
241
|
// so this only ships the deployment; plain coreApps use user-applications below.
|
|
242
242
|
if (workbench && organizationId && applicationId) {
|
|
243
243
|
await deployWorkbenchApp({
|
|
244
|
+
app: cliConfig.app,
|
|
244
245
|
applicationId,
|
|
245
246
|
icon: appIcon,
|
|
246
|
-
|
|
247
|
-
appName: workbench.name,
|
|
248
|
-
appTitle,
|
|
249
|
-
exposesAppView: workbench.entry !== undefined,
|
|
250
|
-
version
|
|
251
|
-
}),
|
|
247
|
+
isApp: true,
|
|
252
248
|
isAutoUpdating,
|
|
253
249
|
// Once the deployment is live, a metadata-sync or later config failure
|
|
254
250
|
// must not delete the app.
|
|
@@ -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 {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 createCoreApp,\n deployConfig,\n deployWorkbenchApp,\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 {\n extractCoreAppManifest,\n readIconFromPath,\n resolveTitleUpdate,\n} from '../manifest/extractCoreAppManifest.js'\nimport {type CoreAppManifest} from '../manifest/types.js'\nimport {createUserApplication} from './createUserApplication.js'\nimport {\n checkAppId,\n checkAppTarget,\n checkAutoUpdates,\n checkBuild,\n checkPackageVersion,\n type DeployCheckReporter,\n verifyOutputDir,\n} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {listDeploymentFiles, 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 organizationId,\n slug: workbench.slug,\n title: appTitle,\n })\n } else if (deployApplication) {\n ;({application, created: appCreated} = await resolveAppApplication(options, {dryRun, reporter}))\n }\n\n // A first deploy mints the app id and the build inlines it; --no-build would\n // ship an existing bundle carrying a different id, so it can't be a first deploy.\n if (deployApplication && workbench && !appId && !flags.external && !flags.build) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'A first deploy cannot skip the build (--no-build)',\n solution: 'Drop --no-build so the new application id is inlined into the build',\n status: 'fail',\n })\n }\n\n // Read up front so a bad icon path fails before we create or build.\n const appIcon =\n !dryRun && workbench?.icon ? await readIconFromPath(workDir, workbench.icon) : undefined\n\n // Create the app before the build so the bundle carries its real id. A\n // redeploy already has it from `deployment.appId`; a dry run skips creation.\n let applicationId = appId\n let applicationCreated = false\n let rollbackApp: (() => Promise<void>) | undefined\n if (!dryRun && deployApplication && workbench && organizationId && !applicationId) {\n ;({applicationId, rollback: rollbackApp} = await createCoreApp({\n isSingleton: workbench.isSingleton,\n organizationId,\n slug: workbench.slug,\n title: appTitle,\n visibility: workbench.visibility,\n }))\n applicationCreated = true\n }\n\n // A record created above is stranded at its slug (and blocks retries) if any\n // step before it fully deploys fails, so undo the creation on failure.\n try {\n await checkBuild(reporter, {\n build: () =>\n buildApp({\n applicationId: workbench ? applicationId : undefined,\n autoUpdatesEnabled: isAutoUpdating,\n calledFromDeploy: true,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n }),\n skipReason: flags.build\n ? undefined\n : 'Build skipped (--no-build) — validating existing output directory',\n successMessage: 'App built',\n })\n\n await verifyOutputDir({isWorkbenchApp: workbench !== null, reporter, sourceDir})\n\n // Workbench apps ship their icon straight to Brett (below) and don't read the\n // core-app manifest; only plain core-apps do. Manifests aren't strictly\n // essential, so a failure warns and continues.\n let manifest: CoreAppManifest | undefined\n if (!workbench) {\n try {\n manifest = await extractCoreAppManifest({workDir})\n } catch (err) {\n deployDebug('Error extracting app manifest', err)\n reporter.report({\n message: `Error extracting app manifest: ${getErrorMessage(err)}`,\n status: 'warn',\n })\n }\n }\n\n // Resolve the installation in both modes so the report — dry-run and real —\n // shows whether the config is deployable; a missing one fails the deploy here.\n let installationId: string | undefined\n let 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:\n '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 // Applied after the app is live (see below) so a failed deploy never leaves\n // the org's installation config without its application.\n const deployApplicationConfig = async (): Promise<void> => {\n if (installationId && version && configAppType && organizationId) {\n await deployConfig({\n appType: configAppType,\n installationId,\n organizationId,\n output,\n sourceDir,\n version,\n })\n }\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return\n\n // A config-only singleton ships no application, only its config.\n if (!deployApplication) {\n await deployApplicationConfig()\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 // The app was created (or resolved from `deployment.appId`) before the build,\n // so this only ships the deployment; plain coreApps use user-applications below.\n if (workbench && organizationId && applicationId) {\n await deployWorkbenchApp({\n applicationId,\n icon: appIcon,\n interfaces: buildExposes(workbench, {\n appName: workbench.name,\n appTitle,\n exposesAppView: workbench.entry !== undefined,\n version,\n }),\n isAutoUpdating,\n // Once the deployment is live, a metadata-sync or later config failure\n // must not delete the app.\n onDeployed: () => {\n rollbackApp = undefined\n },\n sourceDir,\n title: appTitle,\n version,\n visibility: workbench.visibility,\n })\n await deployApplicationConfig()\n const url = getApplicationUrl({id: applicationId, organizationId, type: 'coreApp'})\n logAppDeployed({\n applicationId,\n cliConfig,\n created: applicationCreated,\n organizationId,\n output,\n title: appTitle,\n url,\n })\n return {\n applicationType: 'coreApp',\n applicationVersion: version,\n ...(exposes.length > 0 ? {exposes} : {}),\n ...(workbench.isSingleton === undefined ? {} : {isSingleton: workbench.isSingleton}),\n target: {\n action: applicationCreated ? 'create' : 'update',\n applicationId,\n // A redeploy targets an existing app; only a create reports the slug.\n ...(applicationCreated ? {slug: workbench.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 } catch (err) {\n await rollbackApp?.()\n throw err\n }\n}\n\n/**\n * Finds the application a real deploy targets, creating one when none is\n * configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveAppApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplicationResolved | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const organizationId = cliConfig.app?.organizationId ?? ''\n // Create name from --title or `app.title` config; blank falls back to the prompt\n const title = flags.title?.trim() || cliConfig.app?.title?.trim() || undefined\n\n if (dryRun) {\n await checkAppTarget(reporter, {appId: getAppId(cliConfig), organizationId, title})\n return {application: null, created: false}\n }\n\n let application = await findUserApplication({\n cliConfig,\n organizationId,\n output,\n title,\n unattended: !!flags.yes,\n })\n deployDebug('User application found', application)\n\n if (!application) {\n deployDebug('No user application found. Creating a new one')\n application = await createUserApplication(organizationId, title, cliConfig.app?.visibility)\n deployDebug('User application created', application)\n return {application, created: true}\n }\n\n return {application, created: false}\n}\n\n/**\n * Syncs application metadata on redeploy when it has changed: the title from the\n * manifest and the dashboard visibility from config. Sends a single PATCH with\n * only the changed fields, and skips the request entirely when nothing changed.\n */\nexport async function syncApplicationMetadata({\n application,\n manifest,\n output,\n visibility,\n}: {\n application: UserApplicationResolved\n manifest: CoreAppManifest | undefined\n output: DeployAppOptions['output']\n visibility: AppVisibility | undefined\n}): Promise<UserApplicationResolved> {\n const titleUpdate = resolveTitleUpdate(manifest, application)\n // Treat an unset server value as `default` so a config of `default` is a no-op.\n const visibilityChanged =\n visibility !== undefined && visibility !== (application.dashboardStatus ?? 'default')\n\n if (!titleUpdate && !visibilityChanged) return application\n\n if (titleUpdate) {\n deployDebug('Updating application title from manifest', titleUpdate)\n output.log(\n titleUpdate.from\n ? `Updating title from \"${titleUpdate.from}\" to \"${titleUpdate.to}\"`\n : `Setting application title to \"${titleUpdate.to}\"`,\n )\n }\n if (visibilityChanged) {\n output.log(`Setting dashboard visibility to \"${visibility}\"`)\n }\n\n const spin = spinner('Updating application').start()\n try {\n const updated = await updateUserApplication({\n applicationId: application.id,\n appType: 'coreApp',\n body: {\n ...(titleUpdate ? {title: titleUpdate.to} : {}),\n ...(visibilityChanged ? {dashboardStatus: visibility} : {}),\n },\n })\n spin.succeed()\n return updated\n } catch (err) {\n spin.fail()\n const message = getErrorMessage(err)\n deployDebug('Error updating application metadata', {message})\n output.warn(`Error updating application metadata: ${message}`)\n return application\n }\n}\n\nasync function shipAppDeployment({\n application,\n isAutoUpdating,\n manifest,\n sourceDir,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n manifest: CoreAppManifest | undefined\n sourceDir: string\n version: string\n}): Promise<void> {\n const tarball = 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","createCoreApp","deployConfig","deployWorkbenchApp","getApplicationUrl","getWorkbench","resolveInstallationId","summarizeConfig","pack","createDeployment","updateUserApplication","getAppId","EXTERNAL_APP_NOT_SUPPORTED","NO_ORGANIZATION_ID","buildApp","extractCoreAppManifest","readIconFromPath","resolveTitleUpdate","createUserApplication","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","appIcon","icon","undefined","applicationId","applicationCreated","rollbackApp","rollback","isSingleton","visibility","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","successMessage","manifest","installationId","config","configAppType","appType","exposes","deployApplicationConfig","applicationType","applicationVersion","target","interfaces","appName","exposesAppView","entry","onDeployed","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":"AAAA,SAAQA,QAAQ,EAAEC,OAAO,QAAO,YAAW;AAC3C,SAAQC,SAAS,QAAO,YAAW;AACnC,SAAQC,UAAU,QAAO,YAAW;AAEpC,SAA4BC,SAAS,QAAO,mBAAkB;AAC9D,SAAQC,eAAe,QAAO,0BAAyB;AACvD,SAAQC,aAAa,QAAO,wBAAuB;AACnD,SAAQC,OAAO,QAAO,sBAAqB;AAC3C,SACEC,YAAY,EACZC,aAAa,EACbC,YAAY,EACZC,kBAAkB,EAClBC,iBAAiB,EACjBC,YAAY,EACZC,qBAAqB,EACrBC,eAAe,QACV,+BAA8B;AACrC,SAAQC,IAAI,QAAO,SAAQ;AAE3B,SACEC,gBAAgB,EAChBC,qBAAqB,QAGhB,qCAAoC;AAC3C,SAAQC,QAAQ,QAAO,sBAAqB;AAC5C,SAAQC,0BAA0B,EAAEC,kBAAkB,QAAO,8BAA6B;AAC1F,SAAQC,QAAQ,QAAO,uBAAsB;AAC7C,SACEC,sBAAsB,EACtBC,gBAAgB,EAChBC,kBAAkB,QACb,wCAAuC;AAE9C,SAAQC,qBAAqB,QAAO,6BAA4B;AAChE,SACEC,UAAU,EACVC,cAAc,EACdC,gBAAgB,EAChBC,UAAU,EACVC,mBAAmB,EAEnBC,eAAe,QACV,oBAAmB;AAC1B,SAAQC,WAAW,QAAO,mBAAkB;AAC5C,SAAQC,mBAAmB,EAAEC,aAAa,QAAO,sBAAqB;AACtE,SAA2BC,SAAS,QAAO,oBAAmB;AAC9D,SAAQC,mBAAmB,QAAO,2BAA0B;AAG5D,MAAMC,cAAc;AAEpB,OAAO,SAASC,UAAUC,OAAyB;IACjD,OAAOJ,UAAUI,SAAS;QACxBC,WAAW,CAAC,EAACC,WAAW,EAAEC,SAAS,EAAC,GAAKT,oBAAoBS,WAAWD,YAAYE,SAAS;QAC7FC,KAAKC;QACLC,MAAM;IACR;AACF;AAEA,kFAAkF,GAClF,eAAeD,iBACbN,OAAyB,EACzBQ,QAA6B;IAE7B,MAAM,EAACC,SAAS,EAAEC,KAAK,EAAEC,MAAM,EAAER,SAAS,EAAC,GAAGH;IAC9C,MAAMY,UAAUZ,QAAQE,WAAW,CAACE,SAAS;IAC7C,MAAMS,iBAAiBJ,UAAUK,GAAG,EAAED;IACtC,MAAME,QAAQpC,SAAS8B;IACvB,MAAMO,YAAY3C,aAAaoC;IAC/B,MAAMQ,SAAS,CAAC,CAACP,KAAK,CAAC,UAAU;IAEjC,4EAA4E;IAC5E,wEAAwE;IACxE,MAAMQ,wBAAwBF,WAAWE,yBAAyB;IAClE,MAAMC,oBAAoB,CAACH,aAAaA,UAAUI,aAAa;IAE/D,MAAMC,WAAWL,YACbN,MAAMY,KAAK,EAAEC,UAAUd,UAAUK,GAAG,EAAEQ,OAAOC,UAAUP,UAAUQ,IAAI,GACrE;IAEJ,0EAA0E;IAC1E,8EAA8E;IAC9E,IAAIR,WAAW;QACb,IAAI;YACFA,UAAUS,gBAAgB;QAC5B,EAAE,OAAOC,KAAK;YACZlB,SAASmB,MAAM,CAAC;gBACdC,UAAUhE,UAAUiE,WAAW;gBAC/BC,SAASjE,gBAAgB6D;gBACzBK,UAAU;gBACVC,QAAQ;YACV;QACF;IACF;IAEA,MAAMC,iBAAiB5C,iBAAiBmB,UAAU;QAACC;QAAWC;IAAK;IAEnE,0EAA0E;IAC1E,4BAA4B;IAC5B,IAAIwB,UAAyB;IAC7B,IAAIf,mBAAmB;QACrBe,UAAU,MAAM3C,oBAAoBiB,UAAU;YAAC2B,YAAYrC;YAAac;QAAO;IACjF,OAAO,IAAIM,uBAAuB;QAChCgB,UAAU,MAAM3C,oBAAoBiB,UAAU;YAAC2B,YAAY;YAAUvB;QAAO;IAC9E;IAEAJ,SAASmB,MAAM,CACbd,iBACI;QAACiB,SAAS,CAAC,cAAc,EAAEjB,gBAAgB;QAAEmB,QAAQ;IAAM,IAC3D;QACEF,SAASjD;QACTkD,UAAU;QACVC,QAAQ;IACV;IAGN7C,WAAWqB,UAAU;QAACC;IAAS;IAE/B,IAAI2B,cAA8C;IAClD,IAAIC,aAAa;IACjB,IAAI3B,MAAM4B,QAAQ,EAAE;QAClB9B,SAASmB,MAAM,CAAC;YACdG,SAASlD;YACTmD,UAAU;YACVC,QAAQ;QACV;IACF,OAAO,IAAIb,qBAAqBH,WAAW;QACzC,MAAM5B,eAAeoB,UAAU;YAC7BO;YACAwB,gBAAgB;YAChB1B;YACA2B,MAAMxB,UAAUwB,IAAI;YACpBlB,OAAOD;QACT;IACF,OAAO,IAAIF,mBAAmB;;QAC1B,CAAA,EAACiB,WAAW,EAAEK,SAASJ,UAAU,EAAC,GAAG,MAAMK,sBAAsB1C,SAAS;YAACiB;YAAQT;QAAQ,EAAC;IAChG;IAEA,6EAA6E;IAC7E,kFAAkF;IAClF,IAAIW,qBAAqBH,aAAa,CAACD,SAAS,CAACL,MAAM4B,QAAQ,IAAI,CAAC5B,MAAMiC,KAAK,EAAE;QAC/EnC,SAASmB,MAAM,CAAC;YACdC,UAAUhE,UAAUiE,WAAW;YAC/BC,SAAS;YACTC,UAAU;YACVC,QAAQ;QACV;IACF;IAEA,oEAAoE;IACpE,MAAMY,UACJ,CAAC3B,UAAUD,WAAW6B,OAAO,MAAM7D,iBAAiB4B,SAASI,UAAU6B,IAAI,IAAIC;IAEjF,uEAAuE;IACvE,6EAA6E;IAC7E,IAAIC,gBAAgBhC;IACpB,IAAIiC,qBAAqB;IACzB,IAAIC;IACJ,IAAI,CAAChC,UAAUE,qBAAqBH,aAAaH,kBAAkB,CAACkC,eAAe;;QAC/E,CAAA,EAACA,aAAa,EAAEG,UAAUD,WAAW,EAAC,GAAG,MAAMhF,cAAc;YAC7DkF,aAAanC,UAAUmC,WAAW;YAClCtC;YACA2B,MAAMxB,UAAUwB,IAAI;YACpBlB,OAAOD;YACP+B,YAAYpC,UAAUoC,UAAU;QAClC,EAAC;QACDJ,qBAAqB;IACvB;IAEA,6EAA6E;IAC7E,uEAAuE;IACvE,IAAI;QACF,MAAM1D,WAAWkB,UAAU;YACzBmC,OAAO,IACL7D,SAAS;oBACPiE,eAAe/B,YAAY+B,gBAAgBD;oBAC3CO,oBAAoBpB;oBACpBqB,kBAAkB;oBAClB7C;oBACAC;oBACA6C,QAAQpD;oBACRQ;oBACAC;gBACF;YACF4C,YAAY9C,MAAMiC,KAAK,GACnBG,YACA;YACJW,gBAAgB;QAClB;QAEA,MAAMjE,gBAAgB;YAAC+C,gBAAgBvB,cAAc;YAAMR;YAAUL;QAAS;QAE9E,8EAA8E;QAC9E,wEAAwE;QACxE,+CAA+C;QAC/C,IAAIuD;QACJ,IAAI,CAAC1C,WAAW;YACd,IAAI;gBACF0C,WAAW,MAAM3E,uBAAuB;oBAAC6B;gBAAO;YAClD,EAAE,OAAOc,KAAK;gBACZjC,YAAY,iCAAiCiC;gBAC7ClB,SAASmB,MAAM,CAAC;oBACdG,SAAS,CAAC,+BAA+B,EAAEjE,gBAAgB6D,MAAM;oBACjEM,QAAQ;gBACV;YACF;QACF;QAEA,4EAA4E;QAC5E,+EAA+E;QAC/E,IAAI2B;QACJ,IAAIC;QACJ,MAAMC,gBAAgB7C,WAAW4C,QAAQE;QACzC,IAAI5C,yBAAyBL,kBAAkBG,WAAW4C,UAAUC,eAAe;YACjFF,iBAAiB,MAAMrF,sBAAsB;gBAACwF,SAASD;gBAAehD;YAAc;YACpF+C,SAASrF,gBAAgByC,UAAU4C,MAAM;YACzCpD,SAASmB,MAAM,CACbgC,iBACI;gBAACC;gBAAQ9B,SAAS8B;gBAAQ5B,QAAQ;YAAM,IACxC;gBACEJ,UAAUhE,UAAUiE,WAAW;gBAC/BC,SAAS,CAAC,WAAW,EAAE+B,cAAc,iCAAiC,EAAEhD,eAAe,CAAC,CAAC;gBACzFkB,UACE;gBACFC,QAAQ;YACV;QAER;QAEA,iEAAiE;QACjE,MAAM+B,UAAU5C,qBAAqBH,YAAYrB,cAAca,UAAUQ,aAAa,EAAE;QAExF,kEAAkE;QAClE,IAAIG,qBAAqBH,WAAWmC,gBAAgBL,WAAW;YAC7DtC,SAASmB,MAAM,CAAC;gBACdwB,aAAanC,UAAUmC,WAAW;gBAClCrB,SAAS,CAAC,WAAW,EAAEd,UAAUmC,WAAW,EAAE;gBAC9CnB,QAAQ;YACV;QACF;QAEA,4EAA4E;QAC5E,yDAAyD;QACzD,MAAMgC,0BAA0B;YAC9B,IAAIL,kBAAkBzB,WAAW2B,iBAAiBhD,gBAAgB;gBAChE,MAAM3C,aAAa;oBACjB4F,SAASD;oBACTF;oBACA9C;oBACAF;oBACAR;oBACA+B;gBACF;YACF;QACF;QAEA,iDAAiD;QACjD,IAAIjB,QAAQ;QAEZ,iEAAiE;QACjE,IAAI,CAACE,mBAAmB;YACtB,MAAM6C;YACN,IAAIL,kBAAkBzB,SAAS;gBAC7B,OAAO;oBACL+B,iBAAiB;oBACjBC,oBAAoBhC;oBACpB,GAAI0B,SAAS;wBAACA;oBAAM,IAAI,CAAC,CAAC;oBAC1BD;oBACAQ,QAAQ;gBACV;YACF;YACA;QACF;QAEA,uFAAuF;QACvF,IAAI,CAACjC,SAAS;QAEd,8EAA8E;QAC9E,iFAAiF;QACjF,IAAIlB,aAAaH,kBAAkBkC,eAAe;YAChD,MAAM5E,mBAAmB;gBACvB4E;gBACAF,MAAMD;gBACNwB,YAAYpG,aAAagD,WAAW;oBAClCqD,SAASrD,UAAUQ,IAAI;oBACvBH;oBACAiD,gBAAgBtD,UAAUuD,KAAK,KAAKzB;oBACpCZ;gBACF;gBACAD;gBACA,uEAAuE;gBACvE,2BAA2B;gBAC3BuC,YAAY;oBACVvB,cAAcH;gBAChB;gBACA3C;gBACAmB,OAAOD;gBACPa;gBACAkB,YAAYpC,UAAUoC,UAAU;YAClC;YACA,MAAMY;YACN,MAAMS,MAAMrG,kBAAkB;gBAACsG,IAAI3B;gBAAelC;gBAAgBN,MAAM;YAAS;YACjFoE,eAAe;gBACb5B;gBACAtC;gBACAgC,SAASO;gBACTnC;gBACAF;gBACAW,OAAOD;gBACPoD;YACF;YACA,OAAO;gBACLR,iBAAiB;gBACjBC,oBAAoBhC;gBACpB,GAAI6B,QAAQa,MAAM,GAAG,IAAI;oBAACb;gBAAO,IAAI,CAAC,CAAC;gBACvC,GAAI/C,UAAUmC,WAAW,KAAKL,YAAY,CAAC,IAAI;oBAACK,aAAanC,UAAUmC,WAAW;gBAAA,CAAC;gBACnFgB,QAAQ;oBACNU,QAAQ7B,qBAAqB,WAAW;oBACxCD;oBACA,sEAAsE;oBACtE,GAAIC,qBAAqB;wBAACR,MAAMxB,UAAUwB,IAAI;oBAAA,IAAI,CAAC,CAAC;oBACpDlB,OAAOD;oBACPoD;gBACF;YACF;QACF;QAEA,8EAA8E;QAC9E,mEAAmE;QACnE,IAAI,CAACrC,aAAa;QAElBA,cAAc,MAAM0C,wBAAwB;YAC1C1C;YACAsB;YACA/C;YACAyC,YAAY3C,UAAUK,GAAG,EAAEsC;QAC7B;QACA,MAAM2B,kBAAkB;YAAC3C;YAAaH;YAAgByB;YAAUvD;YAAW+B;QAAO;QAClFyC,eAAe;YACb5B,eAAeX,YAAYsC,EAAE;YAC7BjE;YACAgC,SAASJ;YACTxB,gBAAgBuB,YAAYvB,cAAc;YAC1CF;YACAW,OAAOc,YAAYd,KAAK;QAC1B;QACA,OAAO;YACL2C,iBAAiB;YACjBC,oBAAoBhC;YACpBiC,QAAQ;gBACNU,QAAQxC,aAAa,WAAW;gBAChCU,eAAeX,YAAYsC,EAAE;gBAC7BpD,OAAOc,YAAYd,KAAK,IAAI;gBAC5BmD,KAAK3G,cAAcsE,YAAYvB,cAAc,EAAEuB,YAAYsC,EAAE;YAC/D;QACF;IACF,EAAE,OAAOhD,KAAK;QACZ,MAAMuB;QACN,MAAMvB;IACR;AACF;AAEA;;;CAGC,GACD,eAAegB,sBACb1C,OAAyB,EACzB,EAACiB,MAAM,EAAET,QAAQ,EAAmD;IAEpE,MAAM,EAACC,SAAS,EAAEC,KAAK,EAAEC,MAAM,EAAC,GAAGX;IACnC,MAAMa,iBAAiBJ,UAAUK,GAAG,EAAED,kBAAkB;IACxD,iFAAiF;IACjF,MAAMS,QAAQZ,MAAMY,KAAK,EAAEC,UAAUd,UAAUK,GAAG,EAAEQ,OAAOC,UAAUuB;IAErE,IAAI7B,QAAQ;QACV,MAAM7B,eAAeoB,UAAU;YAACO,OAAOpC,SAAS8B;YAAYI;YAAgBS;QAAK;QACjF,OAAO;YAACc,aAAa;YAAMK,SAAS;QAAK;IAC3C;IAEA,IAAIL,cAAc,MAAMvC,oBAAoB;QAC1CY;QACAI;QACAF;QACAW;QACA0D,YAAY,CAAC,CAACtE,MAAMuE,GAAG;IACzB;IACAxF,YAAY,0BAA0B2C;IAEtC,IAAI,CAACA,aAAa;QAChB3C,YAAY;QACZ2C,cAAc,MAAMlD,sBAAsB2B,gBAAgBS,OAAOb,UAAUK,GAAG,EAAEsC;QAChF3D,YAAY,4BAA4B2C;QACxC,OAAO;YAACA;YAAaK,SAAS;QAAI;IACpC;IAEA,OAAO;QAACL;QAAaK,SAAS;IAAK;AACrC;AAEA;;;;CAIC,GACD,OAAO,eAAeqC,wBAAwB,EAC5C1C,WAAW,EACXsB,QAAQ,EACR/C,MAAM,EACNyC,UAAU,EAMX;IACC,MAAM8B,cAAcjG,mBAAmByE,UAAUtB;IACjD,gFAAgF;IAChF,MAAM+C,oBACJ/B,eAAeN,aAAaM,eAAgBhB,CAAAA,YAAYgD,eAAe,IAAI,SAAQ;IAErF,IAAI,CAACF,eAAe,CAACC,mBAAmB,OAAO/C;IAE/C,IAAI8C,aAAa;QACfzF,YAAY,4CAA4CyF;QACxDvE,OAAO0E,GAAG,CACRH,YAAYI,IAAI,GACZ,CAAC,qBAAqB,EAAEJ,YAAYI,IAAI,CAAC,MAAM,EAAEJ,YAAYK,EAAE,CAAC,CAAC,CAAC,GAClE,CAAC,8BAA8B,EAAEL,YAAYK,EAAE,CAAC,CAAC,CAAC;IAE1D;IACA,IAAIJ,mBAAmB;QACrBxE,OAAO0E,GAAG,CAAC,CAAC,iCAAiC,EAAEjC,WAAW,CAAC,CAAC;IAC9D;IAEA,MAAMoC,OAAOzH,QAAQ,wBAAwB0H,KAAK;IAClD,IAAI;QACF,MAAMC,UAAU,MAAMhH,sBAAsB;YAC1CqE,eAAeX,YAAYsC,EAAE;YAC7BZ,SAAS;YACT6B,MAAM;gBACJ,GAAIT,cAAc;oBAAC5D,OAAO4D,YAAYK,EAAE;gBAAA,IAAI,CAAC,CAAC;gBAC9C,GAAIJ,oBAAoB;oBAACC,iBAAiBhC;gBAAU,IAAI,CAAC,CAAC;YAC5D;QACF;QACAoC,KAAKI,OAAO;QACZ,OAAOF;IACT,EAAE,OAAOhE,KAAK;QACZ8D,KAAKK,IAAI;QACT,MAAM/D,UAAUjE,gBAAgB6D;QAChCjC,YAAY,uCAAuC;YAACqC;QAAO;QAC3DnB,OAAOmF,IAAI,CAAC,CAAC,qCAAqC,EAAEhE,SAAS;QAC7D,OAAOM;IACT;AACF;AAEA,eAAe2C,kBAAkB,EAC/B3C,WAAW,EACXH,cAAc,EACdyB,QAAQ,EACRvD,SAAS,EACT+B,OAAO,EAOR;IACC,MAAM6D,UAAUvH,KAAKf,QAAQ0C,YAAY;QAAC6F,SAAS;YAACxI,SAAS2C;SAAW;IAAA,GAAG8F,IAAI,CAACtI;IAEhF,MAAM6H,OAAOzH,QAAQ,gBAAgB0H,KAAK;IAC1C,IAAI;QACF,MAAMhH,iBAAiB;YACrBsE,eAAeX,YAAYsC,EAAE;YAC7BwB,OAAO;YACPjE;YACAyB;YACAqC;YACA7D;QACF;IACF,EAAE,OAAOiE,OAAO;QACdX,KAAKY,KAAK;QACV,MAAMD;IACR;IACAX,KAAKI,OAAO;AACd;AAEA,OAAO,SAASjB,eAAe,EAC7B5B,aAAa,EACbtC,SAAS,EACTgC,OAAO,EACP5B,cAAc,EACdF,MAAM,EACNW,KAAK,EACLmD,MAAM3G,cAAc+C,gBAAgBkC,cAAc,EASnD;IACC,MAAMsD,QAAQ/E,QAAQ,CAAC,IAAI,EAAEA,MAAM,CAAC,CAAC,GAAG;IACxCX,OAAO0E,GAAG,CAAC,CAAC,mCAAmC,EAAE3H,UAAU,QAAQ+G,OAAO4B,OAAO;IACjF1F,OAAO0E,GAAG,CAAC5C,UAAU,+BAA+B;IAEpD,IAAI9D,SAAS8B,YAAY;IAEzBE,OAAO0E,GAAG,CAAC,CAAC,OAAO,EAAE3H,UAAU,QAAQ,cAAc,KAAK,CAAC;IAC3D,IAAI+E,SAAS;QACX9B,OAAO0E,GAAG,CACR3H,UACE,UACA;IAGN;IACAiD,OAAO0E,GAAG,CACR3H,UAAU,QAAQ;IAEpBiD,OAAO0E,GAAG,CAAC,CAAC;AACd,EAAE3H,UACA,OACA,CAAC;;CAEF,CAAC,EACA;AACF,EAAEA,UACA;QAAC;QAAQ;KAAQ,EACjB,CAAC;UACO,EAAEqF,cAAc;GACvB,CAAC,GACD;AACH"}
|
|
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 createCoreApp,\n deployConfig,\n deployWorkbenchApp,\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 {\n extractCoreAppManifest,\n readIconFromPath,\n resolveTitleUpdate,\n} from '../manifest/extractCoreAppManifest.js'\nimport {type CoreAppManifest} from '../manifest/types.js'\nimport {createUserApplication} from './createUserApplication.js'\nimport {\n checkAppId,\n checkAppTarget,\n checkAutoUpdates,\n checkBuild,\n checkPackageVersion,\n type DeployCheckReporter,\n verifyOutputDir,\n} from './deployChecks.js'\nimport {deployDebug} from './deployDebug.js'\nimport {listDeploymentFiles, 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.slug\n : ''\n\n // A federated app with no entry, view or service would ship a remote with\n // nothing to load — reported first so it fails before any prompt or API call.\n if (workbench) {\n try {\n workbench.assertDeployable()\n } catch (err) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: getErrorMessage(err),\n solution: 'Declare at least one entry, view, or service in the app',\n status: 'fail',\n })\n }\n }\n\n 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 organizationId,\n slug: workbench.slug,\n title: appTitle,\n })\n } else if (deployApplication) {\n ;({application, created: appCreated} = await resolveAppApplication(options, {dryRun, reporter}))\n }\n\n // A first deploy mints the app id and the build inlines it; --no-build would\n // ship an existing bundle carrying a different id, so it can't be a first deploy.\n if (deployApplication && workbench && !appId && !flags.external && !flags.build) {\n reporter.report({\n exitCode: exitCodes.USAGE_ERROR,\n message: 'A first deploy cannot skip the build (--no-build)',\n solution: 'Drop --no-build so the new application id is inlined into the build',\n status: 'fail',\n })\n }\n\n // Read up front so a bad icon path fails before we create or build.\n const appIcon =\n !dryRun && workbench?.icon ? await readIconFromPath(workDir, workbench.icon) : undefined\n\n // Create the app before the build so the bundle carries its real id. A\n // redeploy already has it from `deployment.appId`; a dry run skips creation.\n let applicationId = appId\n let applicationCreated = false\n let rollbackApp: (() => Promise<void>) | undefined\n if (!dryRun && deployApplication && workbench && organizationId && !applicationId) {\n ;({applicationId, rollback: rollbackApp} = await createCoreApp({\n isSingleton: workbench.isSingleton,\n organizationId,\n slug: workbench.slug,\n title: appTitle,\n visibility: workbench.visibility,\n }))\n applicationCreated = true\n }\n\n // A record created above is stranded at its slug (and blocks retries) if any\n // step before it fully deploys fails, so undo the creation on failure.\n try {\n await checkBuild(reporter, {\n build: () =>\n buildApp({\n applicationId: workbench ? applicationId : undefined,\n autoUpdatesEnabled: isAutoUpdating,\n calledFromDeploy: true,\n cliConfig,\n flags,\n outDir: sourceDir,\n output,\n workDir,\n }),\n skipReason: flags.build\n ? undefined\n : 'Build skipped (--no-build) — validating existing output directory',\n successMessage: 'App built',\n })\n\n await verifyOutputDir({isWorkbenchApp: workbench !== null, reporter, sourceDir})\n\n // Workbench apps ship their icon straight to Brett (below) and don't read the\n // core-app manifest; only plain core-apps do. Manifests aren't strictly\n // essential, so a failure warns and continues.\n let manifest: CoreAppManifest | undefined\n if (!workbench) {\n try {\n manifest = await extractCoreAppManifest({workDir})\n } catch (err) {\n deployDebug('Error extracting app manifest', err)\n reporter.report({\n message: `Error extracting app manifest: ${getErrorMessage(err)}`,\n status: 'warn',\n })\n }\n }\n\n // Resolve the installation in both modes so the report — dry-run and real —\n // shows whether the config is deployable; a missing one fails the deploy here.\n let installationId: string | undefined\n let 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:\n '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 // Applied after the app is live (see below) so a failed deploy never leaves\n // the org's installation config without its application.\n const deployApplicationConfig = async (): Promise<void> => {\n if (installationId && version && configAppType && organizationId) {\n await deployConfig({\n appType: configAppType,\n installationId,\n organizationId,\n output,\n sourceDir,\n version,\n })\n }\n }\n\n // Dry run stops here — everything below mutates.\n if (dryRun) return\n\n // A config-only singleton ships no application, only its config.\n if (!deployApplication) {\n await deployApplicationConfig()\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 // The app was created (or resolved from `deployment.appId`) before the build,\n // so this only ships the deployment; plain coreApps use user-applications below.\n if (workbench && organizationId && applicationId) {\n await deployWorkbenchApp({\n app: cliConfig.app,\n applicationId,\n icon: appIcon,\n isApp: true,\n isAutoUpdating,\n // Once the deployment is live, a metadata-sync or later config failure\n // must not delete the app.\n onDeployed: () => {\n rollbackApp = undefined\n },\n sourceDir,\n title: appTitle,\n version,\n visibility: workbench.visibility,\n })\n await deployApplicationConfig()\n const url = getApplicationUrl({id: applicationId, organizationId, type: 'coreApp'})\n logAppDeployed({\n applicationId,\n cliConfig,\n created: applicationCreated,\n organizationId,\n output,\n title: appTitle,\n url,\n })\n return {\n applicationType: 'coreApp',\n applicationVersion: version,\n ...(exposes.length > 0 ? {exposes} : {}),\n ...(workbench.isSingleton === undefined ? {} : {isSingleton: workbench.isSingleton}),\n target: {\n action: applicationCreated ? 'create' : 'update',\n applicationId,\n // A redeploy targets an existing app; only a create reports the slug.\n ...(applicationCreated ? {slug: workbench.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 } catch (err) {\n await rollbackApp?.()\n throw err\n }\n}\n\n/**\n * Finds the application a real deploy targets, creating one when none is\n * configured. A dry run resolves and reports the target read-only instead.\n */\nasync function resolveAppApplication(\n options: DeployAppOptions,\n {dryRun, reporter}: {dryRun: boolean; reporter: DeployCheckReporter},\n): Promise<{application: UserApplicationResolved | null; created: boolean}> {\n const {cliConfig, flags, output} = options\n const organizationId = cliConfig.app?.organizationId ?? ''\n // Create name from --title or `app.title` config; blank falls back to the prompt\n const title = flags.title?.trim() || cliConfig.app?.title?.trim() || undefined\n\n if (dryRun) {\n await checkAppTarget(reporter, {appId: getAppId(cliConfig), organizationId, title})\n return {application: null, created: false}\n }\n\n let application = await findUserApplication({\n cliConfig,\n organizationId,\n output,\n title,\n unattended: !!flags.yes,\n })\n deployDebug('User application found', application)\n\n if (!application) {\n deployDebug('No user application found. Creating a new one')\n application = await createUserApplication(organizationId, title, cliConfig.app?.visibility)\n deployDebug('User application created', application)\n return {application, created: true}\n }\n\n return {application, created: false}\n}\n\n/**\n * Syncs application metadata on redeploy when it has changed: the title from the\n * manifest and the dashboard visibility from config. Sends a single PATCH with\n * only the changed fields, and skips the request entirely when nothing changed.\n */\nexport async function syncApplicationMetadata({\n application,\n manifest,\n output,\n visibility,\n}: {\n application: UserApplicationResolved\n manifest: CoreAppManifest | undefined\n output: DeployAppOptions['output']\n visibility: AppVisibility | undefined\n}): Promise<UserApplicationResolved> {\n const titleUpdate = resolveTitleUpdate(manifest, application)\n // Treat an unset server value as `default` so a config of `default` is a no-op.\n const visibilityChanged =\n visibility !== undefined && visibility !== (application.dashboardStatus ?? 'default')\n\n if (!titleUpdate && !visibilityChanged) return application\n\n if (titleUpdate) {\n deployDebug('Updating application title from manifest', titleUpdate)\n output.log(\n titleUpdate.from\n ? `Updating title from \"${titleUpdate.from}\" to \"${titleUpdate.to}\"`\n : `Setting application title to \"${titleUpdate.to}\"`,\n )\n }\n if (visibilityChanged) {\n output.log(`Setting dashboard visibility to \"${visibility}\"`)\n }\n\n const spin = spinner('Updating application').start()\n try {\n const updated = await updateUserApplication({\n applicationId: application.id,\n appType: 'coreApp',\n body: {\n ...(titleUpdate ? {title: titleUpdate.to} : {}),\n ...(visibilityChanged ? {dashboardStatus: visibility} : {}),\n },\n })\n spin.succeed()\n return updated\n } catch (err) {\n spin.fail()\n const message = getErrorMessage(err)\n deployDebug('Error updating application metadata', {message})\n output.warn(`Error updating application metadata: ${message}`)\n return application\n }\n}\n\nasync function shipAppDeployment({\n application,\n isAutoUpdating,\n manifest,\n sourceDir,\n version,\n}: {\n application: UserApplication\n isAutoUpdating: boolean\n manifest: CoreAppManifest | undefined\n sourceDir: string\n version: string\n}): Promise<void> {\n const tarball = 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","createCoreApp","deployConfig","deployWorkbenchApp","getApplicationUrl","getWorkbench","resolveInstallationId","summarizeConfig","pack","createDeployment","updateUserApplication","getAppId","EXTERNAL_APP_NOT_SUPPORTED","NO_ORGANIZATION_ID","buildApp","extractCoreAppManifest","readIconFromPath","resolveTitleUpdate","createUserApplication","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","slug","assertDeployable","err","report","exitCode","USAGE_ERROR","message","solution","status","isAutoUpdating","version","moduleName","application","appCreated","external","isWorkbenchApp","created","resolveAppApplication","build","appIcon","icon","undefined","applicationId","applicationCreated","rollbackApp","rollback","isSingleton","visibility","autoUpdatesEnabled","calledFromDeploy","outDir","skipReason","successMessage","manifest","installationId","config","configAppType","appType","exposes","deployApplicationConfig","applicationType","applicationVersion","target","isApp","onDeployed","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","error","clear","named"],"mappings":"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"}
|
|
@@ -110,7 +110,7 @@ export async function checkBuild(reporter, { build, skipReason, successMessage }
|
|
|
110
110
|
* The single diagnosis for each app deploy-target verdict, shared by the
|
|
111
111
|
* dry-run report and the real deploy's unattended error paths so message,
|
|
112
112
|
* fix, and exit code can't drift between the two.
|
|
113
|
-
*/ export function describeAppTarget(resolution, {
|
|
113
|
+
*/ export function describeAppTarget(resolution, { title } = {}) {
|
|
114
114
|
switch(resolution.type){
|
|
115
115
|
case 'blocked':
|
|
116
116
|
{
|
|
@@ -152,36 +152,23 @@ export async function checkBuild(reporter, { build, skipReason, successMessage }
|
|
|
152
152
|
status: 'fail'
|
|
153
153
|
};
|
|
154
154
|
}
|
|
155
|
-
// A deployment with no `appId` collides with an app already at this slug —
|
|
156
|
-
// point at the existing app's id so a redeploy targets it instead of failing.
|
|
157
155
|
case 'slug-taken':
|
|
158
156
|
{
|
|
159
|
-
|
|
160
|
-
return {
|
|
161
|
-
exitCode: exitCodes.USAGE_ERROR,
|
|
162
|
-
message: `An application already exists at slug "${application.appHost}" in this organization (app ID ${application.id})`,
|
|
163
|
-
solution: `Add \`deployment: {appId: '${application.id}'}\` to sanity.cli.ts to redeploy it`,
|
|
164
|
-
status: 'fail',
|
|
165
|
-
target: {
|
|
166
|
-
action: 'update',
|
|
167
|
-
applicationId: application.id,
|
|
168
|
-
title: application.title,
|
|
169
|
-
url: application.url ?? null
|
|
170
|
-
}
|
|
171
|
-
};
|
|
157
|
+
return describeSlugTaken(resolution);
|
|
172
158
|
}
|
|
173
159
|
// Without --title, creating an app needs a prompt no unattended run can answer
|
|
174
160
|
case 'would-create':
|
|
175
161
|
{
|
|
162
|
+
const { appHost } = resolution;
|
|
176
163
|
if (title) {
|
|
177
164
|
return {
|
|
178
|
-
message: `Would create a new application "${title}"${
|
|
165
|
+
message: `Would create a new application "${title}"${appHost ? ` with slug "${appHost}"` : ''}`,
|
|
179
166
|
status: 'pass',
|
|
180
167
|
target: {
|
|
181
168
|
action: 'create',
|
|
182
169
|
applicationId: null,
|
|
183
|
-
...
|
|
184
|
-
slug
|
|
170
|
+
...appHost ? {
|
|
171
|
+
slug: appHost
|
|
185
172
|
} : {},
|
|
186
173
|
title,
|
|
187
174
|
url: null
|
|
@@ -197,6 +184,20 @@ export async function checkBuild(reporter, { build, skipReason, successMessage }
|
|
|
197
184
|
}
|
|
198
185
|
}
|
|
199
186
|
}
|
|
187
|
+
/** One diagnosis for both the app and studio verdicts: they share a slug namespace. */ function describeSlugTaken({ appHost, existing }) {
|
|
188
|
+
return {
|
|
189
|
+
exitCode: exitCodes.USAGE_ERROR,
|
|
190
|
+
message: `An application already exists at slug "${appHost}" in this organization (app ID ${existing.id})`,
|
|
191
|
+
solution: `Add \`deployment: {appId: '${existing.id}'}\` to sanity.cli.ts to redeploy it`,
|
|
192
|
+
status: 'fail',
|
|
193
|
+
target: {
|
|
194
|
+
action: 'update',
|
|
195
|
+
applicationId: existing.id,
|
|
196
|
+
title: existing.title,
|
|
197
|
+
url: existing.url ?? null
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
}
|
|
200
201
|
export function describeAppTargetError(err, organizationId) {
|
|
201
202
|
return err?.statusCode === 403 ? `You don’t have permission to view applications for the configured organization ID ("${organizationId}"). Verify the organization ID, or ask your organization’s admin for access.` : `Failed to resolve deploy target: ${getErrorMessage(err)}`;
|
|
202
203
|
}
|
|
@@ -218,7 +219,6 @@ export function describeAppTargetError(err, organizationId) {
|
|
|
218
219
|
slug
|
|
219
220
|
});
|
|
220
221
|
const check = describeAppTarget(resolution, {
|
|
221
|
-
slug,
|
|
222
222
|
title
|
|
223
223
|
});
|
|
224
224
|
reporter.report(check);
|
|
@@ -286,16 +286,16 @@ export function describeAppTargetError(err, organizationId) {
|
|
|
286
286
|
status: 'fail'
|
|
287
287
|
};
|
|
288
288
|
}
|
|
289
|
+
case 'slug-taken':
|
|
290
|
+
{
|
|
291
|
+
return describeSlugTaken(resolution);
|
|
292
|
+
}
|
|
289
293
|
case 'would-create':
|
|
290
294
|
{
|
|
291
|
-
|
|
292
|
-
const url = isWorkbench ? null : studioUrl(
|
|
293
|
-
const
|
|
294
|
-
return {
|
|
295
|
-
message: isExternal ? `Would register external studio at ${resolution.appHost}${titled}` : `Would create studio hostname ${url ?? resolution.appHost}${titled} (name availability is checked on deploy)`,
|
|
295
|
+
const appHost = resolution.appHost;
|
|
296
|
+
const url = isWorkbench ? null : studioUrl(appHost);
|
|
297
|
+
const result = {
|
|
296
298
|
status: 'pass',
|
|
297
|
-
// `title || null`, not `?? null`, so target.title tracks the same
|
|
298
|
-
// truthiness the message's `titled` suffix uses (an empty title is no title)
|
|
299
299
|
target: {
|
|
300
300
|
action: 'create',
|
|
301
301
|
applicationId: null,
|
|
@@ -303,6 +303,27 @@ export function describeAppTargetError(err, organizationId) {
|
|
|
303
303
|
url
|
|
304
304
|
}
|
|
305
305
|
};
|
|
306
|
+
const titled = title ? ` titled "${title}"` : '';
|
|
307
|
+
if (isExternal) {
|
|
308
|
+
return {
|
|
309
|
+
message: `Would register external studio at ${appHost}${titled}`,
|
|
310
|
+
...result
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
if (isWorkbench) {
|
|
314
|
+
return {
|
|
315
|
+
message: `Would create a new studio${title ? ` "${title}"` : ''} with slug "${appHost}" (name availability is checked on deploy)`,
|
|
316
|
+
...result,
|
|
317
|
+
target: {
|
|
318
|
+
...result.target,
|
|
319
|
+
slug: appHost
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
return {
|
|
324
|
+
message: `Would create studio hostname ${url}${titled} (name availability is checked on deploy)`,
|
|
325
|
+
...result
|
|
326
|
+
};
|
|
306
327
|
}
|
|
307
328
|
}
|
|
308
329
|
}
|
|
@@ -312,10 +333,7 @@ export function describeAppTargetError(err, organizationId) {
|
|
|
312
333
|
* it to reject a bad `appId` before building.
|
|
313
334
|
*/ export async function checkStudioTarget(reporter, options) {
|
|
314
335
|
const { title } = options;
|
|
315
|
-
const resolve = options.isWorkbenchApp ? resolveWorkbenchStudio(
|
|
316
|
-
appId: options.appId,
|
|
317
|
-
slug: options.slug
|
|
318
|
-
}) : resolveStudioDeployTarget(options);
|
|
336
|
+
const resolve = options.isWorkbenchApp ? resolveWorkbenchStudio(options) : resolveStudioDeployTarget(options);
|
|
319
337
|
// Workbench studios always deploy to Sanity hosting, never an external URL.
|
|
320
338
|
const isExternal = options.isWorkbenchApp ? false : options.isExternal;
|
|
321
339
|
return runStep(reporter, {
|