@sanity/runtime-cli 17.13.1-next.g13a83b0 → 17.13.1-next.g5faa770
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 +19 -19
- package/dist/actions/blueprints/pre-deploy.js +3 -3
- package/dist/actions/blueprints/stacks.d.ts +2 -5
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +2 -0
- package/dist/cores/blueprints/deploy.js +2 -0
- package/dist/cores/blueprints/plan.js +2 -0
- package/dist/utils/blueprints/stamp-installation-config-version.d.ts +9 -0
- package/dist/utils/blueprints/stamp-installation-config-version.js +28 -0
- package/dist/utils/bundles/prepare-asset.d.ts +38 -0
- package/dist/utils/bundles/prepare-asset.js +271 -0
- package/dist/utils/bundles/types.d.ts +61 -0
- package/dist/utils/bundles/types.js +1 -0
- package/dist/utils/display/blueprints-formatting.d.ts +5 -1
- package/dist/utils/display/blueprints-formatting.js +15 -2
- package/dist/utils/types.d.ts +9 -0
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
- package/dist/utils/studios/prepare-asset.d.ts +0 -6
- package/dist/utils/studios/prepare-asset.js +0 -166
package/README.md
CHANGED
|
@@ -90,7 +90,7 @@ EXAMPLES
|
|
|
90
90
|
$ sanity-run blueprints add function --name my-function --fn-type document-create --fn-type document-update --lang js
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
_See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
93
|
+
_See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/blueprints/add.ts)_
|
|
94
94
|
|
|
95
95
|
## `sanity-run blueprints config`
|
|
96
96
|
|
|
@@ -127,7 +127,7 @@ EXAMPLES
|
|
|
127
127
|
$ sanity-run blueprints config --edit --project-id <projectId> --stack <name-or-id>
|
|
128
128
|
```
|
|
129
129
|
|
|
130
|
-
_See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
130
|
+
_See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/blueprints/config.ts)_
|
|
131
131
|
|
|
132
132
|
## `sanity-run blueprints deploy`
|
|
133
133
|
|
|
@@ -183,7 +183,7 @@ EXAMPLES
|
|
|
183
183
|
$ sanity-run blueprints deploy --new-stack-name <new-name>
|
|
184
184
|
```
|
|
185
185
|
|
|
186
|
-
_See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
186
|
+
_See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/blueprints/deploy.ts)_
|
|
187
187
|
|
|
188
188
|
## `sanity-run blueprints destroy`
|
|
189
189
|
|
|
@@ -221,7 +221,7 @@ EXAMPLES
|
|
|
221
221
|
$ sanity-run blueprints destroy --stack <name-or-id> --project-id <projectId> --force --no-wait
|
|
222
222
|
```
|
|
223
223
|
|
|
224
|
-
_See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
224
|
+
_See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/blueprints/destroy.ts)_
|
|
225
225
|
|
|
226
226
|
## `sanity-run blueprints doctor`
|
|
227
227
|
|
|
@@ -253,7 +253,7 @@ EXAMPLES
|
|
|
253
253
|
$ sanity-run blueprints doctor --fix
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
-
_See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
256
|
+
_See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/blueprints/doctor.ts)_
|
|
257
257
|
|
|
258
258
|
## `sanity-run blueprints info`
|
|
259
259
|
|
|
@@ -291,7 +291,7 @@ EXAMPLES
|
|
|
291
291
|
$ sanity-run blueprints info --organization-id <orgId> --stack <name-or-id>
|
|
292
292
|
```
|
|
293
293
|
|
|
294
|
-
_See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
294
|
+
_See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/blueprints/info.ts)_
|
|
295
295
|
|
|
296
296
|
## `sanity-run blueprints init [DIR]`
|
|
297
297
|
|
|
@@ -355,7 +355,7 @@ EXAMPLES
|
|
|
355
355
|
$ sanity-run blueprints init old-stack --type <json|js|ts> --project-id <projectId> --stack-id <existingStackId>
|
|
356
356
|
```
|
|
357
357
|
|
|
358
|
-
_See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
358
|
+
_See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/blueprints/init.ts)_
|
|
359
359
|
|
|
360
360
|
## `sanity-run blueprints logs`
|
|
361
361
|
|
|
@@ -401,7 +401,7 @@ EXAMPLES
|
|
|
401
401
|
$ sanity-run blueprints logs --before 2026-05-01T00:00:00Z
|
|
402
402
|
```
|
|
403
403
|
|
|
404
|
-
_See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
404
|
+
_See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/blueprints/logs.ts)_
|
|
405
405
|
|
|
406
406
|
## `sanity-run blueprints mint-deploy-token`
|
|
407
407
|
|
|
@@ -446,7 +446,7 @@ EXAMPLES
|
|
|
446
446
|
$ sanity-run blueprints mint-deploy-token --organization-id <orgId>
|
|
447
447
|
```
|
|
448
448
|
|
|
449
|
-
_See code: [src/commands/blueprints/mint-deploy-token.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
449
|
+
_See code: [src/commands/blueprints/mint-deploy-token.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/blueprints/mint-deploy-token.ts)_
|
|
450
450
|
|
|
451
451
|
## `sanity-run blueprints plan`
|
|
452
452
|
|
|
@@ -479,7 +479,7 @@ EXAMPLES
|
|
|
479
479
|
$ sanity-run blueprints plan --organization-id <orgId> --stack <name-or-id>
|
|
480
480
|
```
|
|
481
481
|
|
|
482
|
-
_See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
482
|
+
_See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/blueprints/plan.ts)_
|
|
483
483
|
|
|
484
484
|
## `sanity-run blueprints promote`
|
|
485
485
|
|
|
@@ -515,7 +515,7 @@ EXAMPLES
|
|
|
515
515
|
$ sanity-run blueprints promote --new-stack-name <new-name>
|
|
516
516
|
```
|
|
517
517
|
|
|
518
|
-
_See code: [src/commands/blueprints/promote.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
518
|
+
_See code: [src/commands/blueprints/promote.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/blueprints/promote.ts)_
|
|
519
519
|
|
|
520
520
|
## `sanity-run blueprints stacks`
|
|
521
521
|
|
|
@@ -556,7 +556,7 @@ EXAMPLES
|
|
|
556
556
|
$ sanity-run blueprints stacks --organization-id <organizationId> --include-projects
|
|
557
557
|
```
|
|
558
558
|
|
|
559
|
-
_See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
559
|
+
_See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/blueprints/stacks.ts)_
|
|
560
560
|
|
|
561
561
|
## `sanity-run functions add`
|
|
562
562
|
|
|
@@ -608,7 +608,7 @@ EXAMPLES
|
|
|
608
608
|
$ sanity-run functions add --name my-function --type document-create --type document-update --lang js
|
|
609
609
|
```
|
|
610
610
|
|
|
611
|
-
_See code: [src/commands/functions/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
611
|
+
_See code: [src/commands/functions/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/functions/add.ts)_
|
|
612
612
|
|
|
613
613
|
## `sanity-run functions dev`
|
|
614
614
|
|
|
@@ -643,7 +643,7 @@ EXAMPLES
|
|
|
643
643
|
$ sanity-run functions dev --timeout 60
|
|
644
644
|
```
|
|
645
645
|
|
|
646
|
-
_See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
646
|
+
_See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/functions/dev.ts)_
|
|
647
647
|
|
|
648
648
|
## `sanity-run functions env add NAME KEY VALUE`
|
|
649
649
|
|
|
@@ -676,7 +676,7 @@ EXAMPLES
|
|
|
676
676
|
$ sanity-run functions env add --stack <name-or-id> MyFunction API_URL https://api.example.com/
|
|
677
677
|
```
|
|
678
678
|
|
|
679
|
-
_See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
679
|
+
_See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/functions/env/add.ts)_
|
|
680
680
|
|
|
681
681
|
## `sanity-run functions env list NAME`
|
|
682
682
|
|
|
@@ -706,7 +706,7 @@ EXAMPLES
|
|
|
706
706
|
$ sanity-run functions env list --stack <name-or-id> MyFunction
|
|
707
707
|
```
|
|
708
708
|
|
|
709
|
-
_See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
709
|
+
_See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/functions/env/list.ts)_
|
|
710
710
|
|
|
711
711
|
## `sanity-run functions env remove NAME KEY`
|
|
712
712
|
|
|
@@ -738,7 +738,7 @@ EXAMPLES
|
|
|
738
738
|
$ sanity-run functions env remove --stack <name-or-id> MyFunction API_URL
|
|
739
739
|
```
|
|
740
740
|
|
|
741
|
-
_See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
741
|
+
_See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/functions/env/remove.ts)_
|
|
742
742
|
|
|
743
743
|
## `sanity-run functions logs [NAME]`
|
|
744
744
|
|
|
@@ -778,7 +778,7 @@ EXAMPLES
|
|
|
778
778
|
$ sanity-run functions logs <name> --delete
|
|
779
779
|
```
|
|
780
780
|
|
|
781
|
-
_See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
781
|
+
_See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/functions/logs.ts)_
|
|
782
782
|
|
|
783
783
|
## `sanity-run functions test [NAME]`
|
|
784
784
|
|
|
@@ -836,7 +836,7 @@ EXAMPLES
|
|
|
836
836
|
$ sanity-run functions test <name> --event update --data-before '{ "title": "before" }' --data-after '{ "title": "after" }'
|
|
837
837
|
```
|
|
838
838
|
|
|
839
|
-
_See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.
|
|
839
|
+
_See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v17.13.1-next.g5faa770/src/commands/functions/test.ts)_
|
|
840
840
|
|
|
841
841
|
## `sanity-run help [COMMAND]`
|
|
842
842
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { SANITY_FUNCTION_PREFIX } from '../../constants.js';
|
|
2
2
|
import { resolveDeployedResources } from '../../utils/blueprints/resolve-deployed-resources.js';
|
|
3
|
+
import { BUNDLE_SPECS, prepareBundleAsset, } from '../../utils/bundles/prepare-asset.js';
|
|
3
4
|
import { CODE_OPERATION_UNCONFIRMED, EXIT_OPERATION_UNCONFIRMED } from '../../utils/exit-codes.js';
|
|
4
5
|
import { prepareAsset as prepareFunctionAsset } from '../../utils/functions/prepare-asset.js';
|
|
5
6
|
import { runCommand } from '../../utils/package-manager.js';
|
|
6
|
-
import { prepareStudioAsset } from '../../utils/studios/prepare-asset.js';
|
|
7
7
|
import { setupLogPolling } from './logs-polling.js';
|
|
8
8
|
import { getOperationStateInfo } from './operations-state.js';
|
|
9
9
|
import { processAssets } from './process-assets.js';
|
|
@@ -13,9 +13,9 @@ import { updateStack } from './stacks.js';
|
|
|
13
13
|
*/
|
|
14
14
|
const preDeployConfigs = [
|
|
15
15
|
{
|
|
16
|
-
resourceType:
|
|
16
|
+
resourceType: (type) => type in BUNDLE_SPECS,
|
|
17
17
|
async prepareAsset(options) {
|
|
18
|
-
return
|
|
18
|
+
return prepareBundleAsset({
|
|
19
19
|
resource: options.resource,
|
|
20
20
|
blueprintFileDir: options.blueprintFileDir,
|
|
21
21
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Blueprint } from '@sanity/blueprints-parser';
|
|
2
2
|
import type { Logger } from '../../utils/logger.js';
|
|
3
|
-
import type { AuthParams, ScopeType, Stack, StackMutation, StackSummary } from '../../utils/types.js';
|
|
3
|
+
import type { AuthParams, ScopeType, Stack, StackMutation, StackSummary, UpdatedStack } from '../../utils/types.js';
|
|
4
4
|
export declare const stacksUrl: string;
|
|
5
5
|
type ListStacksResponse = {
|
|
6
6
|
ok: true;
|
|
@@ -46,10 +46,7 @@ export declare function createEmptyStack({ token, scopeType, scopeId, name, logg
|
|
|
46
46
|
type UpdateStackResponse = {
|
|
47
47
|
ok: true;
|
|
48
48
|
error: null;
|
|
49
|
-
stack:
|
|
50
|
-
operationId: string;
|
|
51
|
-
changeCount?: number;
|
|
52
|
-
};
|
|
49
|
+
stack: UpdatedStack;
|
|
53
50
|
} | {
|
|
54
51
|
ok: false;
|
|
55
52
|
error: string;
|
package/dist/constants.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export declare const SANITY_PROJECT_CORS = "sanity.project.cors";
|
|
|
13
13
|
export declare const SANITY_PROJECT_DATASET = "sanity.project.dataset";
|
|
14
14
|
export declare const SANITY_PROJECT_WEBHOOK = "sanity.project.webhook";
|
|
15
15
|
export declare const SANITY_STUDIO = "sanity.studio";
|
|
16
|
+
export declare const SANITY_APPLICATION = "sanity.application";
|
|
17
|
+
export declare const SANITY_INSTALLATION_CONFIG = "sanity.installation.config";
|
|
16
18
|
export declare const EVENT_DOCUMENT_PUBLISH = "document-publish";
|
|
17
19
|
export declare const EVENT_DOCUMENT_CREATE = "document-create";
|
|
18
20
|
export declare const EVENT_DOCUMENT_UPDATE = "document-update";
|
package/dist/constants.js
CHANGED
|
@@ -12,6 +12,8 @@ export const SANITY_PROJECT_CORS = 'sanity.project.cors';
|
|
|
12
12
|
export const SANITY_PROJECT_DATASET = 'sanity.project.dataset';
|
|
13
13
|
export const SANITY_PROJECT_WEBHOOK = 'sanity.project.webhook';
|
|
14
14
|
export const SANITY_STUDIO = 'sanity.studio';
|
|
15
|
+
export const SANITY_APPLICATION = 'sanity.application';
|
|
16
|
+
export const SANITY_INSTALLATION_CONFIG = 'sanity.installation.config';
|
|
15
17
|
export const EVENT_DOCUMENT_PUBLISH = 'document-publish';
|
|
16
18
|
export const EVENT_DOCUMENT_CREATE = 'document-create';
|
|
17
19
|
export const EVENT_DOCUMENT_UPDATE = 'document-update';
|
|
@@ -6,6 +6,7 @@ import { checkUserPermission } from '../../actions/sanity/access.js';
|
|
|
6
6
|
import { getClientMetadata } from '../../utils/blueprints/deploy-metadata.js';
|
|
7
7
|
import { extractDurableConfig } from '../../utils/blueprints/extract-durable-config.js';
|
|
8
8
|
import { createHintCollector } from '../../utils/blueprints/hints.js';
|
|
9
|
+
import { stampInstallationConfigVersion } from '../../utils/blueprints/stamp-installation-config-version.js';
|
|
9
10
|
import { createWaitFor } from '../../utils/blueprints/wait-for.js';
|
|
10
11
|
import { formatStudioUrls } from '../../utils/display/blueprints-formatting.js';
|
|
11
12
|
import { check, niceId, severe } from '../../utils/display/presenters.js';
|
|
@@ -42,6 +43,7 @@ export async function blueprintDeployCore(options) {
|
|
|
42
43
|
}
|
|
43
44
|
const resources = [...blueprint.resources];
|
|
44
45
|
await extractDurableConfig(resources, blueprintFileDir);
|
|
46
|
+
await stampInstallationConfigVersion(resources, blueprintFileDir);
|
|
45
47
|
let spinner;
|
|
46
48
|
const preDeployResult = await preDeploy({
|
|
47
49
|
scopeType,
|
|
@@ -2,6 +2,7 @@ import { dirname } from 'node:path';
|
|
|
2
2
|
import { planStack, resolveStackIdByNameOrId } from '../../actions/blueprints/stacks.js';
|
|
3
3
|
import { extractDurableConfig } from '../../utils/blueprints/extract-durable-config.js';
|
|
4
4
|
import { createHintCollector } from '../../utils/blueprints/hints.js';
|
|
5
|
+
import { stampInstallationConfigVersion } from '../../utils/blueprints/stamp-installation-config-version.js';
|
|
5
6
|
import { formatDeploymentPlan, formatResourceTree, hasActionableChanges, } from '../../utils/display/blueprints-formatting.js';
|
|
6
7
|
import { runCommand } from '../../utils/package-manager.js';
|
|
7
8
|
import { styleText } from '../../utils/style-text.js';
|
|
@@ -12,6 +13,7 @@ export async function blueprintPlanCore(options) {
|
|
|
12
13
|
const { scopeType, scopeId, stackId: blueprintStackId, parsedBlueprint, resources, fileInfo, } = blueprint;
|
|
13
14
|
log(`${styleText(['bold', 'blueBright'], 'Local Blueprint')} ${styleText('dim', `(${fileInfo.fileName})`)}`);
|
|
14
15
|
await extractDurableConfig(resources, dirname(fileInfo.blueprintFilePath));
|
|
16
|
+
await stampInstallationConfigVersion(resources, dirname(fileInfo.blueprintFilePath));
|
|
15
17
|
log(formatResourceTree(resources));
|
|
16
18
|
if (!token || !scopeType || !scopeId) {
|
|
17
19
|
log(styleText('dim', 'Unable to retrieve live Stack deployment for comparison'));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BlueprintResource } from '@sanity/blueprints';
|
|
2
|
+
/**
|
|
3
|
+
* Stamps the installed `sanity` version onto each media-library config resource
|
|
4
|
+
* before pre-deploy. The version is a label Brett stores on the config snapshot,
|
|
5
|
+
* mirroring what `sanity deploy` sends for a media-library config; it is not what
|
|
6
|
+
* the runtime loads. Other installation config types are left alone: the
|
|
7
|
+
* media-library tie to the `sanity` package is specific to it.
|
|
8
|
+
*/
|
|
9
|
+
export declare const stampInstallationConfigVersion: (resources: BlueprintResource[], blueprintFileDir: string) => Promise<void>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { getLocalPackageVersion } from '@sanity/cli-core/package-manager';
|
|
3
|
+
import { SANITY_INSTALLATION_CONFIG } from '../../constants.js';
|
|
4
|
+
/**
|
|
5
|
+
* Stamps the installed `sanity` version onto each media-library config resource
|
|
6
|
+
* before pre-deploy. The version is a label Brett stores on the config snapshot,
|
|
7
|
+
* mirroring what `sanity deploy` sends for a media-library config; it is not what
|
|
8
|
+
* the runtime loads. Other installation config types are left alone: the
|
|
9
|
+
* media-library tie to the `sanity` package is specific to it.
|
|
10
|
+
*/
|
|
11
|
+
export const stampInstallationConfigVersion = async (resources, blueprintFileDir) => {
|
|
12
|
+
for (const resource of resources) {
|
|
13
|
+
if (resource.type !== SANITY_INSTALLATION_CONFIG)
|
|
14
|
+
continue;
|
|
15
|
+
const config = resource;
|
|
16
|
+
if (config.appType !== 'media-library')
|
|
17
|
+
continue;
|
|
18
|
+
// Update values not included in the blueprint.
|
|
19
|
+
if (config.version !== undefined)
|
|
20
|
+
continue;
|
|
21
|
+
const workDir = resolve(blueprintFileDir, config.root);
|
|
22
|
+
const version = await getLocalPackageVersion('sanity', workDir);
|
|
23
|
+
if (!version) {
|
|
24
|
+
throw new Error(`Unable to determine the installed 'sanity' version for installation config resource '${config.name}'; is 'sanity' installed in '${config.root}'?`);
|
|
25
|
+
}
|
|
26
|
+
config.version = version;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type BuildStudioEventListener } from '@sanity/cli-build/_internal/build';
|
|
2
|
+
import type { Output } from '@sanity/cli-core';
|
|
3
|
+
import type { AssetPrepResult } from '../types.js';
|
|
4
|
+
import type { BlueprintApplicationResource, BlueprintInstallationConfigResource, BlueprintStudioResource } from './types.js';
|
|
5
|
+
export type BundleResource = BlueprintStudioResource | BlueprintApplicationResource | BlueprintInstallationConfigResource;
|
|
6
|
+
type BuildContext<R extends BundleResource> = {
|
|
7
|
+
resource: R;
|
|
8
|
+
appId: string | undefined;
|
|
9
|
+
workDir: string;
|
|
10
|
+
outDir: string;
|
|
11
|
+
output: Output;
|
|
12
|
+
eventListener: Partial<BuildStudioEventListener>;
|
|
13
|
+
};
|
|
14
|
+
type BuildResult = {
|
|
15
|
+
mismatchedPackages?: string[];
|
|
16
|
+
};
|
|
17
|
+
export declare const BUNDLE_SPECS: {
|
|
18
|
+
'sanity.studio': {
|
|
19
|
+
requiresAppId: true;
|
|
20
|
+
build: typeof buildStudioBundle;
|
|
21
|
+
};
|
|
22
|
+
'sanity.application': {
|
|
23
|
+
requiresAppId: true;
|
|
24
|
+
build: typeof buildApplicationBundle;
|
|
25
|
+
};
|
|
26
|
+
'sanity.installation.config': {
|
|
27
|
+
requiresAppId: false;
|
|
28
|
+
build: typeof buildInstallationConfigBundle;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export declare function prepareBundleAsset<R extends BundleResource>({ blueprintFileDir, resource, }: {
|
|
32
|
+
blueprintFileDir: string;
|
|
33
|
+
resource: R;
|
|
34
|
+
}): Promise<AssetPrepResult>;
|
|
35
|
+
declare function buildStudioBundle({ resource, appId, workDir, outDir, output, eventListener, }: BuildContext<BlueprintStudioResource>): Promise<BuildResult>;
|
|
36
|
+
declare function buildApplicationBundle({ resource, appId, workDir, outDir, output, eventListener, }: BuildContext<BlueprintApplicationResource>): Promise<BuildResult>;
|
|
37
|
+
declare function buildInstallationConfigBundle({ resource, workDir, outDir, output, eventListener, }: BuildContext<BlueprintInstallationConfigResource>): Promise<BuildResult>;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { createWriteStream } from 'node:fs';
|
|
2
|
+
import { mkdtemp, readFile, rm, stat } from 'node:fs/promises';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import path, { basename, dirname, join } from 'node:path';
|
|
5
|
+
import { pipeline } from 'node:stream/promises';
|
|
6
|
+
import { createGzip } from 'node:zlib';
|
|
7
|
+
import { buildApp, buildStudio, compareDependencyVersions, } from '@sanity/cli-build/_internal/build';
|
|
8
|
+
import { getLocalPackageVersion } from '@sanity/cli-core';
|
|
9
|
+
import { pack } from 'tar-fs';
|
|
10
|
+
export const BUNDLE_SPECS = {
|
|
11
|
+
'sanity.studio': { requiresAppId: true, build: buildStudioBundle },
|
|
12
|
+
'sanity.application': { requiresAppId: true, build: buildApplicationBundle },
|
|
13
|
+
'sanity.installation.config': { requiresAppId: false, build: buildInstallationConfigBundle },
|
|
14
|
+
};
|
|
15
|
+
export async function prepareBundleAsset({ blueprintFileDir, resource, }) {
|
|
16
|
+
// The lookup can't prove it yields the spec matching this R, so it's asserted once here.
|
|
17
|
+
const spec = BUNDLE_SPECS[resource.type];
|
|
18
|
+
const appId = getAppId(resource);
|
|
19
|
+
if (spec.requiresAppId && !appId) {
|
|
20
|
+
return {
|
|
21
|
+
success: false,
|
|
22
|
+
async cleanup() { },
|
|
23
|
+
error: `Unable to determine appId for ${resource.type} resource '${resource.name}'`,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
let cleanup = async () => { };
|
|
27
|
+
const assetPath = String(resource.root);
|
|
28
|
+
const workDir = path.resolve(blueprintFileDir, assetPath);
|
|
29
|
+
// Defence in depth alongside blueprints-node's own check: an absolute path or one
|
|
30
|
+
// that climbs above the blueprint dir would bundle files outside the project.
|
|
31
|
+
if (path.isAbsolute(assetPath) || path.relative(blueprintFileDir, workDir).startsWith('..')) {
|
|
32
|
+
return {
|
|
33
|
+
success: false,
|
|
34
|
+
cleanup,
|
|
35
|
+
error: `Property 'root' on resource with type '${resource.type}' must be under the blueprint directory`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const workDirStat = await stat(workDir);
|
|
40
|
+
if (!workDirStat.isDirectory()) {
|
|
41
|
+
return {
|
|
42
|
+
success: false,
|
|
43
|
+
cleanup,
|
|
44
|
+
error: `Property 'root' on resource with type '${resource.type}' must be a directory`,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
50
|
+
return {
|
|
51
|
+
success: false,
|
|
52
|
+
cleanup,
|
|
53
|
+
error: `Unable to read given 'root' on resource with type '${resource.type}': ${msg}`,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const outDir = await mkdtemp(join(tmpdir(), `bundle-`));
|
|
58
|
+
const outFile = `${outDir}.tar.gz`;
|
|
59
|
+
cleanup = async () => {
|
|
60
|
+
await rm(outDir, { force: true, recursive: true });
|
|
61
|
+
await rm(outFile, { force: true });
|
|
62
|
+
};
|
|
63
|
+
let mismatchedPackages;
|
|
64
|
+
try {
|
|
65
|
+
;
|
|
66
|
+
({ mismatchedPackages } = await spec.build({
|
|
67
|
+
resource,
|
|
68
|
+
appId,
|
|
69
|
+
workDir,
|
|
70
|
+
outDir,
|
|
71
|
+
output: createSilentOutput(),
|
|
72
|
+
eventListener,
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
77
|
+
return {
|
|
78
|
+
success: false,
|
|
79
|
+
cleanup,
|
|
80
|
+
error: message,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
await pipeline(pack(dirname(outDir), { entries: [basename(outDir)] }), createGzip(), createWriteStream(outFile));
|
|
84
|
+
const buffer = await readFile(outFile);
|
|
85
|
+
return {
|
|
86
|
+
success: true,
|
|
87
|
+
cleanup,
|
|
88
|
+
outputBuffer: buffer,
|
|
89
|
+
fileExtension: 'tar.gz',
|
|
90
|
+
assetParameter: 'root',
|
|
91
|
+
metadata: {
|
|
92
|
+
sanityVersion: await getInstalledSanityVersion(workDir),
|
|
93
|
+
mismatchedPackages,
|
|
94
|
+
assetBytes: buffer.length,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
return {
|
|
100
|
+
success: false,
|
|
101
|
+
cleanup,
|
|
102
|
+
error: error instanceof Error ? error.message : String(error),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async function buildStudioBundle({ resource, appId, workDir, outDir, output, eventListener, }) {
|
|
107
|
+
let mismatchedPackages;
|
|
108
|
+
await buildStudio({
|
|
109
|
+
appId,
|
|
110
|
+
autoUpdatesEnabled: resource.autoUpdates.enabled,
|
|
111
|
+
checkAppId() { },
|
|
112
|
+
async compareDependencyVersions(packages) {
|
|
113
|
+
const result = await compareDependencyVersions(packages, workDir, { appId });
|
|
114
|
+
mismatchedPackages = result.mismatched.map((m) => m.pkg);
|
|
115
|
+
return result;
|
|
116
|
+
},
|
|
117
|
+
determineBasePath() {
|
|
118
|
+
return resource.basePath ?? '/';
|
|
119
|
+
},
|
|
120
|
+
// a studio is a standalone app, not a workbench module-federation app
|
|
121
|
+
isApp: false,
|
|
122
|
+
isBlueprints: true,
|
|
123
|
+
isWorkbenchApp: false,
|
|
124
|
+
minify: resource.minify ?? true,
|
|
125
|
+
outDir,
|
|
126
|
+
output,
|
|
127
|
+
reactCompiler: resource.reactCompiler || false,
|
|
128
|
+
schemaExtraction: undefined,
|
|
129
|
+
sourceMap: resource.sourceMap ?? false,
|
|
130
|
+
stats: false,
|
|
131
|
+
unattendedMode: true,
|
|
132
|
+
// TODO pass in vite config from the studio resource
|
|
133
|
+
vite: undefined,
|
|
134
|
+
workDir,
|
|
135
|
+
eventListener,
|
|
136
|
+
});
|
|
137
|
+
return { mismatchedPackages };
|
|
138
|
+
}
|
|
139
|
+
async function buildApplicationBundle({ resource, appId, workDir, outDir, output, eventListener, }) {
|
|
140
|
+
const views = resource.views ?? [];
|
|
141
|
+
const [window, extraWindow] = views.filter((v) => v.type === 'app');
|
|
142
|
+
if (extraWindow) {
|
|
143
|
+
throw new Error(`Application resource '${resource.name}' declares more than one window view; at most one is allowed`);
|
|
144
|
+
}
|
|
145
|
+
await buildApp({
|
|
146
|
+
...sharedBuildAppOptions({ appId, workDir, outDir, output, eventListener }),
|
|
147
|
+
appId,
|
|
148
|
+
appTitle: resource.title,
|
|
149
|
+
entry: window?.src,
|
|
150
|
+
workbenchAppId: appId,
|
|
151
|
+
exposes: {
|
|
152
|
+
views: views.map(toWorkbenchView),
|
|
153
|
+
webWorkers: resource.webWorkers,
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
// a workbench app never auto-updates, so no dependency mismatches are compared
|
|
157
|
+
return {};
|
|
158
|
+
}
|
|
159
|
+
async function buildInstallationConfigBundle({ resource, workDir, outDir, output, eventListener, }) {
|
|
160
|
+
await buildApp({
|
|
161
|
+
...sharedBuildAppOptions({ appId: undefined, workDir, outDir, output, eventListener }),
|
|
162
|
+
appId: undefined,
|
|
163
|
+
appTitle: undefined,
|
|
164
|
+
entry: undefined,
|
|
165
|
+
workbenchAppId: undefined,
|
|
166
|
+
exposes: { config: { appType: resource.appType, fields: resource.fields } },
|
|
167
|
+
});
|
|
168
|
+
return {};
|
|
169
|
+
}
|
|
170
|
+
// Options a workbench build (application or installation config) always sets the
|
|
171
|
+
// same way; each caller adds only what differs (identity, entry, exposes).
|
|
172
|
+
function sharedBuildAppOptions({ appId, workDir, outDir, output, eventListener, }) {
|
|
173
|
+
return {
|
|
174
|
+
autoUpdatesEnabled: false,
|
|
175
|
+
checkAppId() { },
|
|
176
|
+
async compareDependencyVersions(packages) {
|
|
177
|
+
return compareDependencyVersions(packages, workDir, { appId });
|
|
178
|
+
},
|
|
179
|
+
determineBasePath() {
|
|
180
|
+
return '/';
|
|
181
|
+
},
|
|
182
|
+
isWorkbenchApp: true,
|
|
183
|
+
isBlueprints: true,
|
|
184
|
+
minify: true,
|
|
185
|
+
outDir,
|
|
186
|
+
output,
|
|
187
|
+
reactCompiler: false,
|
|
188
|
+
schemaExtraction: undefined,
|
|
189
|
+
sourceMap: false,
|
|
190
|
+
stats: false,
|
|
191
|
+
unattendedMode: true,
|
|
192
|
+
vite: undefined,
|
|
193
|
+
workDir,
|
|
194
|
+
eventListener,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
// blueprints-node emits `type` (window views as `app`); workbench-cli discriminates on `surface`.
|
|
198
|
+
function toWorkbenchView(view) {
|
|
199
|
+
switch (view.type) {
|
|
200
|
+
case 'app': {
|
|
201
|
+
const { type: _type, ...rest } = view;
|
|
202
|
+
return { ...rest, surface: 'window' };
|
|
203
|
+
}
|
|
204
|
+
case 'panel': {
|
|
205
|
+
const { type, ...rest } = view;
|
|
206
|
+
return { ...rest, surface: type };
|
|
207
|
+
}
|
|
208
|
+
case 'asset_source': {
|
|
209
|
+
const { type, ...rest } = view;
|
|
210
|
+
return { ...rest, surface: type };
|
|
211
|
+
}
|
|
212
|
+
case 'tile': {
|
|
213
|
+
const { type, ...rest } = view;
|
|
214
|
+
return { ...rest, surface: type };
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const eventListener = {
|
|
219
|
+
onBuildFail({ message }) {
|
|
220
|
+
throw new Error(message);
|
|
221
|
+
},
|
|
222
|
+
onInvalidStyledComponentsVersionRange({ message }) {
|
|
223
|
+
throw new Error(message);
|
|
224
|
+
},
|
|
225
|
+
onNoDeclaredStyledComponentsVersion({ message }) {
|
|
226
|
+
throw new Error(message);
|
|
227
|
+
},
|
|
228
|
+
onNoInstalledSanityVersion({ message }) {
|
|
229
|
+
throw new Error(message);
|
|
230
|
+
},
|
|
231
|
+
onNoInstalledStyledComponentsVersion({ message }) {
|
|
232
|
+
throw new Error(message);
|
|
233
|
+
},
|
|
234
|
+
onPreReleaseInNonInteractiveAutoUpdate({ message }) {
|
|
235
|
+
throw new Error(message);
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
function createSilentOutput() {
|
|
239
|
+
return {
|
|
240
|
+
error(input, options) {
|
|
241
|
+
if (typeof options?.exit === 'number') {
|
|
242
|
+
if (input instanceof Error) {
|
|
243
|
+
throw input;
|
|
244
|
+
}
|
|
245
|
+
throw new Error(input);
|
|
246
|
+
}
|
|
247
|
+
return undefined;
|
|
248
|
+
},
|
|
249
|
+
log() { },
|
|
250
|
+
warn(input) {
|
|
251
|
+
return input;
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
async function getInstalledSanityVersion(workDir) {
|
|
256
|
+
try {
|
|
257
|
+
return (await getLocalPackageVersion('sanity', workDir)) ?? undefined;
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
return undefined;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function getAppId(resource) {
|
|
264
|
+
if ('externalId' in resource && typeof resource.externalId === 'string' && resource.externalId) {
|
|
265
|
+
return resource.externalId;
|
|
266
|
+
}
|
|
267
|
+
else if (resource.lifecycle?.ownershipAction?.type === 'attach') {
|
|
268
|
+
return resource.lifecycle.ownershipAction.id;
|
|
269
|
+
}
|
|
270
|
+
return undefined;
|
|
271
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { BlueprintProjectResourceLifecycle, BlueprintResource, BlueprintStudioResource as PublishedStudioResource } from '@sanity/blueprints';
|
|
2
|
+
/** Studios point at their directory with `root`, same as applications. */
|
|
3
|
+
export type BlueprintStudioResource = Omit<PublishedStudioResource, 'src'> & {
|
|
4
|
+
root: string;
|
|
5
|
+
};
|
|
6
|
+
type ApplicationDock = {
|
|
7
|
+
group?: 'system' | 'applications' | 'user';
|
|
8
|
+
order?: number;
|
|
9
|
+
};
|
|
10
|
+
type ChildBase = {
|
|
11
|
+
name: string;
|
|
12
|
+
title: string;
|
|
13
|
+
src: string;
|
|
14
|
+
};
|
|
15
|
+
type WindowView = ChildBase & {
|
|
16
|
+
type: 'app';
|
|
17
|
+
dock?: ApplicationDock;
|
|
18
|
+
};
|
|
19
|
+
type PanelView = ChildBase & {
|
|
20
|
+
type: 'panel';
|
|
21
|
+
dock?: ApplicationDock;
|
|
22
|
+
};
|
|
23
|
+
type AssetSourceView = ChildBase & {
|
|
24
|
+
type: 'asset_source';
|
|
25
|
+
};
|
|
26
|
+
type TileView = ChildBase & {
|
|
27
|
+
type: 'tile';
|
|
28
|
+
size: 'small' | 'large' | 'banner';
|
|
29
|
+
order?: number;
|
|
30
|
+
};
|
|
31
|
+
type WebWorker = ChildBase & {
|
|
32
|
+
type: 'worker';
|
|
33
|
+
};
|
|
34
|
+
export type ApplicationView = WindowView | PanelView | AssetSourceView | TileView;
|
|
35
|
+
export interface BlueprintApplicationResource extends BlueprintResource<BlueprintProjectResourceLifecycle> {
|
|
36
|
+
type: 'sanity.application';
|
|
37
|
+
slug: string;
|
|
38
|
+
title: string;
|
|
39
|
+
/** Application directory, relative to the blueprint file; contains package.json. */
|
|
40
|
+
root: string;
|
|
41
|
+
icon?: string;
|
|
42
|
+
visibility?: 'default' | 'unlisted' | 'disabled';
|
|
43
|
+
views?: ApplicationView[];
|
|
44
|
+
webWorkers?: WebWorker[];
|
|
45
|
+
}
|
|
46
|
+
type InstallationConfigField = {
|
|
47
|
+
name: string;
|
|
48
|
+
title: string;
|
|
49
|
+
src: string;
|
|
50
|
+
public?: boolean;
|
|
51
|
+
};
|
|
52
|
+
export interface BlueprintInstallationConfigResource extends BlueprintResource {
|
|
53
|
+
type: 'sanity.installation.config';
|
|
54
|
+
appType: 'media-library';
|
|
55
|
+
/** Build directory, relative to the blueprint file; contains package.json. Field `src` resolves against it. */
|
|
56
|
+
root: string;
|
|
57
|
+
fields: InstallationConfigField[];
|
|
58
|
+
/** Stamped by the CLI before pre-deploy; the authored shape from blueprints-node has none. */
|
|
59
|
+
version?: string;
|
|
60
|
+
}
|
|
61
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,7 +4,11 @@ import type { DeploymentPlan } from '../../actions/blueprints/stacks.js';
|
|
|
4
4
|
import { type BlueprintResourceRecord, type Stack, type StackSummary } from '../types.js';
|
|
5
5
|
export declare function formatTitle(title: string, name: string): string;
|
|
6
6
|
export declare function formatDeployedResourceTree(resources: BlueprintResourceRecord[] | undefined, verbose?: boolean): string;
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Returns hosted Studio URLs, one line per Studio from resource-ish shapes
|
|
9
|
+
* Searches `parameters`, `resolvedParameters` and root for `studioHost`
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatStudioUrls(resources: (BlueprintResource | BlueprintResourceRecord)[] | undefined): string[];
|
|
8
12
|
export declare function formatResourceTree(resources: BlueprintResource[] | undefined, verbose?: boolean): string;
|
|
9
13
|
export declare function formatStackInfo(stack: Stack | StackSummary | Blueprint, isCurrentStack?: boolean): string;
|
|
10
14
|
export declare function formatStacksListing(stacks: StackSummary[], currentStackId?: string): string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { formatDateTime, formatElapsed } from '@sanity/cli-core/dates';
|
|
2
2
|
import { treeify } from 'array-treeify';
|
|
3
|
-
import { SANITY_ACCESS_ROBOT, SANITY_ACCESS_ROLE, SANITY_FUNCTION_DOCUMENT, SANITY_FUNCTION_DURABLE, SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_PUBSUB, SANITY_FUNCTION_SCHEDULED, SANITY_FUNCTION_SYNC_TAG_INVALIDATE, SANITY_PROJECT, SANITY_PROJECT_CORS, SANITY_PROJECT_DATASET, SANITY_PROJECT_WEBHOOK, SANITY_STUDIO, } from '../../constants.js';
|
|
3
|
+
import { SANITY_ACCESS_ROBOT, SANITY_ACCESS_ROLE, SANITY_APPLICATION, SANITY_FUNCTION_DOCUMENT, SANITY_FUNCTION_DURABLE, SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_PUBSUB, SANITY_FUNCTION_SCHEDULED, SANITY_FUNCTION_SYNC_TAG_INVALIDATE, SANITY_INSTALLATION_CONFIG, SANITY_PROJECT, SANITY_PROJECT_CORS, SANITY_PROJECT_DATASET, SANITY_PROJECT_WEBHOOK, SANITY_STUDIO, } from '../../constants.js';
|
|
4
4
|
import { styleText } from '../style-text.js';
|
|
5
5
|
import { isCorsOriginResource, isDatasetResource, isRobotResource, isRoleResource, isStudioResource, isWebhookResource, } from '../types.js';
|
|
6
6
|
import { capitalize, niceId, renderSection } from './presenters.js';
|
|
@@ -65,6 +65,14 @@ const RESOURCE_CATEGORIES = {
|
|
|
65
65
|
return isStudioResource(res) ? arrayifyStudio(res) : [];
|
|
66
66
|
},
|
|
67
67
|
},
|
|
68
|
+
[SANITY_APPLICATION]: {
|
|
69
|
+
label: 'Applications',
|
|
70
|
+
displayNameAttribute: 'title',
|
|
71
|
+
},
|
|
72
|
+
[SANITY_INSTALLATION_CONFIG]: {
|
|
73
|
+
label: 'Installation configs',
|
|
74
|
+
displayNameAttribute: 'name',
|
|
75
|
+
},
|
|
68
76
|
};
|
|
69
77
|
const categoryByLabel = Object.values(RESOURCE_CATEGORIES).reduce((acc, curr) => {
|
|
70
78
|
acc[curr.label] = curr;
|
|
@@ -165,6 +173,10 @@ export function formatDeployedResourceTree(resources, verbose = false) {
|
|
|
165
173
|
(res) => ({ name: res.name, type: res.type, ...(res.resolvedParameters ?? res.parameters) }), verbose);
|
|
166
174
|
return `${treeify(output)}\n`;
|
|
167
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Returns hosted Studio URLs, one line per Studio from resource-ish shapes
|
|
178
|
+
* Searches `parameters`, `resolvedParameters` and root for `studioHost`
|
|
179
|
+
*/
|
|
168
180
|
export function formatStudioUrls(resources) {
|
|
169
181
|
if (!resources)
|
|
170
182
|
return [];
|
|
@@ -172,7 +184,8 @@ export function formatStudioUrls(resources) {
|
|
|
172
184
|
for (const res of resources) {
|
|
173
185
|
if (res.type !== SANITY_STUDIO)
|
|
174
186
|
continue;
|
|
175
|
-
const
|
|
187
|
+
const { resolvedParameters, parameters } = res;
|
|
188
|
+
const host = studioHost(resolvedParameters ?? parameters ?? res);
|
|
176
189
|
if (host)
|
|
177
190
|
lines.push(`Studio ${styleText(['bold', 'green'], res.name)} ${studioUrl(host)}`);
|
|
178
191
|
}
|
package/dist/utils/types.d.ts
CHANGED
|
@@ -65,6 +65,15 @@ interface StackBase {
|
|
|
65
65
|
export interface Stack extends StackBase {
|
|
66
66
|
resources: Array<BlueprintResourceRecord>;
|
|
67
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Shape returned by `PUT /stacks/{id}`
|
|
70
|
+
* The authored document is echoed by the API: resources without `parameters` or `resolvedParameters`.
|
|
71
|
+
*/
|
|
72
|
+
export interface UpdatedStack extends StackBase {
|
|
73
|
+
resources: BlueprintResource[];
|
|
74
|
+
operationId: string;
|
|
75
|
+
changeCount?: number;
|
|
76
|
+
}
|
|
68
77
|
export interface StackSummary extends StackBase {
|
|
69
78
|
resourceCount: number;
|
|
70
79
|
}
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { BlueprintStudioResource } from '@sanity/blueprints';
|
|
2
|
-
import type { AssetPrepResult } from '../types.js';
|
|
3
|
-
export declare function prepareStudioAsset({ blueprintFileDir, resource, }: {
|
|
4
|
-
blueprintFileDir: string;
|
|
5
|
-
resource: BlueprintStudioResource;
|
|
6
|
-
}): Promise<AssetPrepResult>;
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import { createWriteStream } from 'node:fs';
|
|
2
|
-
import { mkdtemp, readFile, rm, stat } from 'node:fs/promises';
|
|
3
|
-
import { tmpdir } from 'node:os';
|
|
4
|
-
import path, { basename, dirname, join } from 'node:path';
|
|
5
|
-
import { pipeline } from 'node:stream/promises';
|
|
6
|
-
import { createGzip } from 'node:zlib';
|
|
7
|
-
import { buildStudio, compareDependencyVersions } from '@sanity/cli-build/_internal/build';
|
|
8
|
-
import { getLocalPackageVersion } from '@sanity/cli-core';
|
|
9
|
-
import { pack } from 'tar-fs';
|
|
10
|
-
export async function prepareStudioAsset({ blueprintFileDir, resource, }) {
|
|
11
|
-
// validate resource has an appId
|
|
12
|
-
const appId = getAppId(resource);
|
|
13
|
-
if (!appId) {
|
|
14
|
-
return {
|
|
15
|
-
success: false,
|
|
16
|
-
async cleanup() {
|
|
17
|
-
// no op
|
|
18
|
-
},
|
|
19
|
-
error: `Unable to determine appId for sanity.studio resource '${resource.name}'`,
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
let cleanup = async () => {
|
|
23
|
-
// no op
|
|
24
|
-
};
|
|
25
|
-
const studioPath = path.resolve(blueprintFileDir, resource.src);
|
|
26
|
-
// set only when auto-updates is on, because the build compares versions only then
|
|
27
|
-
let mismatchedPackages;
|
|
28
|
-
try {
|
|
29
|
-
const studioPathStat = await stat(studioPath);
|
|
30
|
-
if (!studioPathStat.isDirectory()) {
|
|
31
|
-
return {
|
|
32
|
-
success: false,
|
|
33
|
-
cleanup,
|
|
34
|
-
error: `Property 'src' on resource with type '${resource.type}' must be a directory`,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
catch (error) {
|
|
39
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
40
|
-
return {
|
|
41
|
-
success: false,
|
|
42
|
-
cleanup,
|
|
43
|
-
error: `Unable to read given 'src' on resource with type '${resource.type}': ${msg}`,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
try {
|
|
47
|
-
const outDir = await mkdtemp(join(tmpdir(), `studio-build-`));
|
|
48
|
-
const outFile = `${outDir}.tar.gz`;
|
|
49
|
-
cleanup = async () => {
|
|
50
|
-
await rm(outDir, { force: true, recursive: true });
|
|
51
|
-
await rm(outFile, { force: true });
|
|
52
|
-
};
|
|
53
|
-
try {
|
|
54
|
-
await buildStudio({
|
|
55
|
-
appId,
|
|
56
|
-
autoUpdatesEnabled: resource.autoUpdates.enabled,
|
|
57
|
-
checkAppId() { },
|
|
58
|
-
async compareDependencyVersions(packages) {
|
|
59
|
-
const result = await compareDependencyVersions(packages, studioPath, { appId });
|
|
60
|
-
mismatchedPackages = result.mismatched.map((m) => m.pkg);
|
|
61
|
-
return result;
|
|
62
|
-
},
|
|
63
|
-
determineBasePath() {
|
|
64
|
-
return resource.basePath ?? '/';
|
|
65
|
-
},
|
|
66
|
-
isApp: false,
|
|
67
|
-
isWorkbenchApp: false,
|
|
68
|
-
minify: resource.minify ?? true,
|
|
69
|
-
outDir,
|
|
70
|
-
output: createSilentOutput(),
|
|
71
|
-
reactCompiler: resource.reactCompiler || false,
|
|
72
|
-
schemaExtraction: undefined,
|
|
73
|
-
sourceMap: resource.sourceMap ?? false,
|
|
74
|
-
stats: false,
|
|
75
|
-
unattendedMode: true,
|
|
76
|
-
// TODO pass in vite config from the studio resource
|
|
77
|
-
vite: undefined,
|
|
78
|
-
workDir: studioPath,
|
|
79
|
-
eventListener: {
|
|
80
|
-
onBuildFail({ message }) {
|
|
81
|
-
throw new Error(message);
|
|
82
|
-
},
|
|
83
|
-
onInvalidStyledComponentsVersionRange({ message }) {
|
|
84
|
-
throw new Error(message);
|
|
85
|
-
},
|
|
86
|
-
onNoDeclaredStyledComponentsVersion({ message }) {
|
|
87
|
-
throw new Error(message);
|
|
88
|
-
},
|
|
89
|
-
onNoInstalledSanityVersion({ message }) {
|
|
90
|
-
throw new Error(message);
|
|
91
|
-
},
|
|
92
|
-
onNoInstalledStyledComponentsVersion({ message }) {
|
|
93
|
-
throw new Error(message);
|
|
94
|
-
},
|
|
95
|
-
onPreReleaseInNonInteractiveAutoUpdate({ message }) {
|
|
96
|
-
throw new Error(message);
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
catch (error) {
|
|
102
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
103
|
-
return {
|
|
104
|
-
success: false,
|
|
105
|
-
cleanup,
|
|
106
|
-
error: message,
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
// tar/gzip/write the built output
|
|
110
|
-
await pipeline(pack(dirname(outDir), { entries: [basename(outDir)] }), createGzip(), createWriteStream(outFile));
|
|
111
|
-
const buffer = await readFile(outFile);
|
|
112
|
-
return {
|
|
113
|
-
success: true,
|
|
114
|
-
cleanup,
|
|
115
|
-
outputBuffer: buffer,
|
|
116
|
-
fileExtension: 'tar.gz',
|
|
117
|
-
assetParameter: 'src',
|
|
118
|
-
metadata: {
|
|
119
|
-
sanityVersion: await getInstalledSanityVersion(studioPath),
|
|
120
|
-
mismatchedPackages,
|
|
121
|
-
assetBytes: buffer.length,
|
|
122
|
-
},
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
catch (error) {
|
|
126
|
-
return {
|
|
127
|
-
success: false,
|
|
128
|
-
cleanup,
|
|
129
|
-
error: error instanceof Error ? error.message : String(error),
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
function createSilentOutput() {
|
|
134
|
-
return {
|
|
135
|
-
error(input, options) {
|
|
136
|
-
if (typeof options?.exit === 'number') {
|
|
137
|
-
if (input instanceof Error) {
|
|
138
|
-
throw input;
|
|
139
|
-
}
|
|
140
|
-
throw new Error(input);
|
|
141
|
-
}
|
|
142
|
-
return undefined;
|
|
143
|
-
},
|
|
144
|
-
log() { },
|
|
145
|
-
warn(input) {
|
|
146
|
-
return input;
|
|
147
|
-
},
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
async function getInstalledSanityVersion(studioPath) {
|
|
151
|
-
try {
|
|
152
|
-
return (await getLocalPackageVersion('sanity', studioPath)) ?? undefined;
|
|
153
|
-
}
|
|
154
|
-
catch {
|
|
155
|
-
return undefined;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
function getAppId(resource) {
|
|
159
|
-
if ('externalId' in resource && typeof resource.externalId === 'string' && resource.externalId) {
|
|
160
|
-
return resource.externalId;
|
|
161
|
-
}
|
|
162
|
-
else if (resource.lifecycle?.ownershipAction?.type === 'attach') {
|
|
163
|
-
return resource.lifecycle.ownershipAction.id;
|
|
164
|
-
}
|
|
165
|
-
return undefined;
|
|
166
|
-
}
|