@sanity/runtime-cli 17.13.1-next.g2772647 → 17.13.1-next.g4fa31d1
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.d.ts +1 -0
- package/dist/actions/blueprints/pre-deploy.js +7 -4
- package/dist/actions/blueprints/stacks.d.ts +4 -0
- package/dist/actions/blueprints/stacks.js +25 -12
- package/dist/baseCommands.js +7 -2
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +1 -0
- package/dist/cores/blueprints/deploy.js +12 -3
- package/dist/cores/blueprints/destroy.js +28 -17
- package/dist/cores/blueprints/plan.js +2 -0
- package/dist/cores/index.d.ts +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/{applications → bundles}/prepare-asset.d.ts +13 -6
- package/dist/utils/{applications → bundles}/prepare-asset.js +45 -19
- package/dist/utils/{applications → bundles}/types.d.ts +15 -0
- package/dist/utils/display/blueprints-formatting.js +5 -1
- package/dist/utils/request-id.d.ts +4 -0
- package/dist/utils/request-id.js +19 -0
- package/oclif.manifest.json +1002 -1002
- package/package.json +1 -1
- /package/dist/utils/{applications → bundles}/types.js +0 -0
|
@@ -7,15 +7,16 @@ import { createGzip } from 'node:zlib';
|
|
|
7
7
|
import { buildApp, buildStudio, compareDependencyVersions, } from '@sanity/cli-build/_internal/build';
|
|
8
8
|
import { getLocalPackageVersion } from '@sanity/cli-core';
|
|
9
9
|
import { pack } from 'tar-fs';
|
|
10
|
-
export const
|
|
11
|
-
'sanity.studio': { build: buildStudioBundle },
|
|
12
|
-
'sanity.application': { build: buildApplicationBundle },
|
|
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 },
|
|
13
14
|
};
|
|
14
|
-
export async function
|
|
15
|
+
export async function prepareBundleAsset({ blueprintFileDir, resource, }) {
|
|
15
16
|
// The lookup can't prove it yields the spec matching this R, so it's asserted once here.
|
|
16
|
-
const spec =
|
|
17
|
+
const spec = BUNDLE_SPECS[resource.type];
|
|
17
18
|
const appId = getAppId(resource);
|
|
18
|
-
if (!appId) {
|
|
19
|
+
if (spec.requiresAppId && !appId) {
|
|
19
20
|
return {
|
|
20
21
|
success: false,
|
|
21
22
|
async cleanup() { },
|
|
@@ -25,6 +26,15 @@ export async function prepareApplicationAsset({ blueprintFileDir, resource, }) {
|
|
|
25
26
|
let cleanup = async () => { };
|
|
26
27
|
const assetPath = String(resource.root);
|
|
27
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
|
+
}
|
|
28
38
|
try {
|
|
29
39
|
const workDirStat = await stat(workDir);
|
|
30
40
|
if (!workDirStat.isDirectory()) {
|
|
@@ -44,7 +54,7 @@ export async function prepareApplicationAsset({ blueprintFileDir, resource, }) {
|
|
|
44
54
|
};
|
|
45
55
|
}
|
|
46
56
|
try {
|
|
47
|
-
const outDir = await mkdtemp(join(tmpdir(), `
|
|
57
|
+
const outDir = await mkdtemp(join(tmpdir(), `bundle-`));
|
|
48
58
|
const outFile = `${outDir}.tar.gz`;
|
|
49
59
|
cleanup = async () => {
|
|
50
60
|
await rm(outDir, { force: true, recursive: true });
|
|
@@ -132,24 +142,45 @@ async function buildApplicationBundle({ resource, appId, workDir, outDir, output
|
|
|
132
142
|
if (extraWindow) {
|
|
133
143
|
throw new Error(`Application resource '${resource.name}' declares more than one window view; at most one is allowed`);
|
|
134
144
|
}
|
|
135
|
-
let mismatchedPackages;
|
|
136
145
|
await buildApp({
|
|
146
|
+
...sharedBuildAppOptions({ appId, workDir, outDir, output, eventListener }),
|
|
137
147
|
appId,
|
|
138
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 {
|
|
139
174
|
autoUpdatesEnabled: false,
|
|
140
175
|
checkAppId() { },
|
|
141
176
|
async compareDependencyVersions(packages) {
|
|
142
|
-
|
|
143
|
-
mismatchedPackages = result.mismatched.map((m) => m.pkg);
|
|
144
|
-
return result;
|
|
177
|
+
return compareDependencyVersions(packages, workDir, { appId });
|
|
145
178
|
},
|
|
146
179
|
determineBasePath() {
|
|
147
180
|
return '/';
|
|
148
181
|
},
|
|
149
|
-
entry: window?.src,
|
|
150
182
|
isWorkbenchApp: true,
|
|
151
183
|
isBlueprints: true,
|
|
152
|
-
workbenchAppId: appId,
|
|
153
184
|
minify: true,
|
|
154
185
|
outDir,
|
|
155
186
|
output,
|
|
@@ -161,12 +192,7 @@ async function buildApplicationBundle({ resource, appId, workDir, outDir, output
|
|
|
161
192
|
vite: undefined,
|
|
162
193
|
workDir,
|
|
163
194
|
eventListener,
|
|
164
|
-
|
|
165
|
-
views: views.map(toWorkbenchView),
|
|
166
|
-
webWorkers: resource.webWorkers,
|
|
167
|
-
},
|
|
168
|
-
});
|
|
169
|
-
return { mismatchedPackages };
|
|
195
|
+
};
|
|
170
196
|
}
|
|
171
197
|
// blueprints-node emits `type` (window views as `app`); workbench-cli discriminates on `surface`.
|
|
172
198
|
function toWorkbenchView(view) {
|
|
@@ -43,4 +43,19 @@ export interface BlueprintApplicationResource extends BlueprintResource<Blueprin
|
|
|
43
43
|
views?: ApplicationView[];
|
|
44
44
|
webWorkers?: WebWorker[];
|
|
45
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
|
+
}
|
|
46
61
|
export {};
|
|
@@ -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_APPLICATION, 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';
|
|
@@ -69,6 +69,10 @@ const RESOURCE_CATEGORIES = {
|
|
|
69
69
|
label: 'Applications',
|
|
70
70
|
displayNameAttribute: 'title',
|
|
71
71
|
},
|
|
72
|
+
[SANITY_INSTALLATION_CONFIG]: {
|
|
73
|
+
label: 'Installation configs',
|
|
74
|
+
displayNameAttribute: 'name',
|
|
75
|
+
},
|
|
72
76
|
};
|
|
73
77
|
const categoryByLabel = Object.values(RESOURCE_CATEGORIES).reduce((acc, curr) => {
|
|
74
78
|
acc[curr.label] = curr;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const REQUEST_ID_HEADER = "x-request-id";
|
|
2
|
+
/** Stack PUT/POST/DELETE success bodies also carry `requestId`; error bodies do not. */
|
|
3
|
+
export declare function getRequestId(response?: Response, body?: unknown): string | undefined;
|
|
4
|
+
export declare function withRequestId(message: string, requestId?: string): string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const REQUEST_ID_HEADER = 'x-request-id';
|
|
2
|
+
/** Stack PUT/POST/DELETE success bodies also carry `requestId`; error bodies do not. */
|
|
3
|
+
export function getRequestId(response, body) {
|
|
4
|
+
const fromHeader = response?.headers.get(REQUEST_ID_HEADER);
|
|
5
|
+
if (fromHeader)
|
|
6
|
+
return fromHeader;
|
|
7
|
+
if (body && typeof body === 'object' && 'requestId' in body) {
|
|
8
|
+
const fromBody = body.requestId;
|
|
9
|
+
if (typeof fromBody === 'string' && fromBody)
|
|
10
|
+
return fromBody;
|
|
11
|
+
}
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
export function withRequestId(message, requestId) {
|
|
15
|
+
if (!requestId)
|
|
16
|
+
return message;
|
|
17
|
+
const suffix = `(request ID ${requestId})`;
|
|
18
|
+
return message.endsWith('.') ? `${message.slice(0, -1)} ${suffix}.` : `${message} ${suffix}`;
|
|
19
|
+
}
|