@sanity/workbench-cli 1.8.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_exports/build.d.ts +48 -11
- package/dist/_exports/deploy.d.ts +53 -72
- package/dist/_exports/deploy.js +1 -1
- package/dist/_exports/deploy.js.map +1 -1
- package/dist/_exports/dev.d.ts +36 -0
- package/dist/_exports/index.d.ts +118 -9
- package/dist/_exports/index.js.map +1 -1
- package/dist/_exports/init.d.ts +5 -3
- package/dist/_exports/init.js +2 -1
- package/dist/_exports/init.js.map +1 -1
- package/dist/_exports/preview.d.ts +36 -0
- package/dist/_exports/undeploy.d.ts +50 -11
- package/dist/actions/deploy/deployConfig.js +1 -1
- package/dist/actions/deploy/deployConfig.js.map +1 -1
- package/dist/actions/deploy/deployWorkbenchApp.js +10 -2
- package/dist/actions/deploy/deployWorkbenchApp.js.map +1 -1
- package/dist/actions/deploy/summarizeInterfaces.js +33 -0
- package/dist/actions/deploy/summarizeInterfaces.js.map +1 -0
- package/dist/actions/deploy/viewDeployment.js +3 -1
- package/dist/actions/deploy/viewDeployment.js.map +1 -1
- package/dist/actions/dev/{deriveInterfaces.js → deriveConfigs.js} +3 -54
- package/dist/actions/dev/deriveConfigs.js.map +1 -0
- package/dist/actions/dev/exposesSetId.js +1 -1
- package/dist/actions/dev/exposesSetId.js.map +1 -1
- package/dist/actions/dev/registry.js +12 -2
- package/dist/actions/dev/registry.js.map +1 -1
- package/dist/actions/dev/startDevManifestWatcher.js.map +1 -1
- package/dist/actions/dev/startDevServerRegistration.js +2 -1
- package/dist/actions/dev/startDevServerRegistration.js.map +1 -1
- package/dist/actions/init/cliConfig.js +2 -4
- package/dist/actions/init/cliConfig.js.map +1 -1
- package/dist/actions/preview/startWorkbenchPreview.js +2 -1
- package/dist/actions/preview/startWorkbenchPreview.js.map +1 -1
- package/dist/actions/undeploy/workbenchUndeployAdapter.js +3 -3
- package/dist/actions/undeploy/workbenchUndeployAdapter.js.map +1 -1
- package/dist/appId.js +1 -1
- package/dist/appId.js.map +1 -1
- package/dist/appSlug.js +7 -0
- package/dist/appSlug.js.map +1 -0
- package/dist/contract.js +60 -4
- package/dist/contract.js.map +1 -1
- package/dist/defineApp.js +7 -7
- package/dist/defineApp.js.map +1 -1
- package/dist/defineView.js.map +1 -1
- package/dist/deriveInterfaces.js +63 -0
- package/dist/deriveInterfaces.js.map +1 -0
- package/dist/resolveWorkbenchApp.js +0 -1
- package/dist/resolveWorkbenchApp.js.map +1 -1
- package/dist/services/applications.js.map +1 -1
- package/package.json +7 -6
- package/dist/actions/deploy/buildExposes.js +0 -72
- package/dist/actions/deploy/buildExposes.js.map +0 -1
- package/dist/actions/dev/deriveInterfaces.js.map +0 -1
|
@@ -77,6 +77,42 @@ declare const devServerManifestSchema: z.ZodMiniObject<
|
|
|
77
77
|
},
|
|
78
78
|
z.core.$strip
|
|
79
79
|
>,
|
|
80
|
+
z.ZodMiniObject<
|
|
81
|
+
{
|
|
82
|
+
metadata: z.ZodMiniNull;
|
|
83
|
+
type: z.ZodMiniLiteral<"asset_source">;
|
|
84
|
+
id: z.ZodMiniString<string>;
|
|
85
|
+
moduleId: z.ZodMiniString<string>;
|
|
86
|
+
name: z.ZodMiniString<string>;
|
|
87
|
+
src: z.ZodMiniString<string>;
|
|
88
|
+
title: z.ZodMiniString<string>;
|
|
89
|
+
version: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
90
|
+
},
|
|
91
|
+
z.core.$strip
|
|
92
|
+
>,
|
|
93
|
+
z.ZodMiniObject<
|
|
94
|
+
{
|
|
95
|
+
metadata: z.ZodMiniObject<
|
|
96
|
+
{
|
|
97
|
+
priority: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
|
|
98
|
+
size: z.ZodMiniEnum<{
|
|
99
|
+
small: "small";
|
|
100
|
+
large: "large";
|
|
101
|
+
banner: "banner";
|
|
102
|
+
}>;
|
|
103
|
+
},
|
|
104
|
+
z.core.$strip
|
|
105
|
+
>;
|
|
106
|
+
type: z.ZodMiniLiteral<"tile">;
|
|
107
|
+
id: z.ZodMiniString<string>;
|
|
108
|
+
moduleId: z.ZodMiniString<string>;
|
|
109
|
+
name: z.ZodMiniString<string>;
|
|
110
|
+
src: z.ZodMiniString<string>;
|
|
111
|
+
title: z.ZodMiniString<string>;
|
|
112
|
+
version: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
113
|
+
},
|
|
114
|
+
z.core.$strip
|
|
115
|
+
>,
|
|
80
116
|
z.ZodMiniObject<
|
|
81
117
|
{
|
|
82
118
|
metadata: z.ZodMiniNull;
|
|
@@ -4,6 +4,14 @@ import { UndeployApplicationTarget } from "@sanity/cli-core/undeploy";
|
|
|
4
4
|
import { UndeployConfigTarget } from "@sanity/cli-core/undeploy";
|
|
5
5
|
import { z } from "zod/mini";
|
|
6
6
|
|
|
7
|
+
/** The `asset_source` variant of an app's `views`. @public */
|
|
8
|
+
declare type AssetSourceView = Extract<
|
|
9
|
+
NonNullable<z.output<typeof DefineAppInputSchema>["views"]>[number],
|
|
10
|
+
{
|
|
11
|
+
type: "asset_source";
|
|
12
|
+
}
|
|
13
|
+
>;
|
|
14
|
+
|
|
7
15
|
/**
|
|
8
16
|
* The undeploy adapter for workbench apps, mirroring what a workbench deploy
|
|
9
17
|
* creates: apps that expose interfaces delete their Brett application (the
|
|
@@ -20,10 +28,11 @@ export declare function createWorkbenchUndeployAdapter(options: {
|
|
|
20
28
|
|
|
21
29
|
/**
|
|
22
30
|
* User-facing input for `unstable_defineApp`. Excludes the internal
|
|
23
|
-
* `applicationType`, `isSingleton`, and `config` — validated by the
|
|
24
|
-
*
|
|
25
|
-
* `@ts-expect-error`). A union
|
|
26
|
-
* never both
|
|
31
|
+
* `applicationType`, `isSingleton`, and `config` — validated by the schema but
|
|
32
|
+
* not part of the public surface (Sanity-owned apps set them via
|
|
33
|
+
* `@ts-expect-error`). A union: an app declares an app `entry` (navigable) or
|
|
34
|
+
* panel `views`, never both — but `asset_source` and `tile` views are separate
|
|
35
|
+
* kinds and may accompany either.
|
|
27
36
|
* @public
|
|
28
37
|
*/
|
|
29
38
|
declare type DefineAppInput = Omit<
|
|
@@ -37,7 +46,7 @@ declare type DefineAppInput = Omit<
|
|
|
37
46
|
}
|
|
38
47
|
| {
|
|
39
48
|
entry?: string;
|
|
40
|
-
views?:
|
|
49
|
+
views?: (AssetSourceView | TileView)[];
|
|
41
50
|
}
|
|
42
51
|
);
|
|
43
52
|
|
|
@@ -90,7 +99,6 @@ declare const DefineAppInputSchema: z.ZodMiniObject<
|
|
|
90
99
|
>;
|
|
91
100
|
icon: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
92
101
|
isSingleton: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
|
|
93
|
-
name: z.ZodMiniString<string>;
|
|
94
102
|
organizationId: z.ZodMiniString<string>;
|
|
95
103
|
priority: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
|
|
96
104
|
services: z.ZodMiniOptional<
|
|
@@ -99,7 +107,7 @@ declare const DefineAppInputSchema: z.ZodMiniObject<
|
|
|
99
107
|
[
|
|
100
108
|
z.ZodMiniObject<
|
|
101
109
|
{
|
|
102
|
-
title: z.
|
|
110
|
+
title: z.ZodMiniString<string>;
|
|
103
111
|
name: z.ZodMiniString<string>;
|
|
104
112
|
src: z.ZodMiniString<string>;
|
|
105
113
|
type: z.ZodMiniLiteral<"worker">;
|
|
@@ -119,13 +127,37 @@ declare const DefineAppInputSchema: z.ZodMiniObject<
|
|
|
119
127
|
[
|
|
120
128
|
z.ZodMiniObject<
|
|
121
129
|
{
|
|
122
|
-
title: z.
|
|
130
|
+
title: z.ZodMiniString<string>;
|
|
123
131
|
name: z.ZodMiniString<string>;
|
|
124
132
|
src: z.ZodMiniString<string>;
|
|
125
133
|
type: z.ZodMiniLiteral<"panel">;
|
|
126
134
|
},
|
|
127
135
|
z.core.$strip
|
|
128
136
|
>,
|
|
137
|
+
z.ZodMiniObject<
|
|
138
|
+
{
|
|
139
|
+
title: z.ZodMiniString<string>;
|
|
140
|
+
name: z.ZodMiniString<string>;
|
|
141
|
+
src: z.ZodMiniString<string>;
|
|
142
|
+
type: z.ZodMiniLiteral<"asset_source">;
|
|
143
|
+
},
|
|
144
|
+
z.core.$strip
|
|
145
|
+
>,
|
|
146
|
+
z.ZodMiniObject<
|
|
147
|
+
{
|
|
148
|
+
priority: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
|
|
149
|
+
size: z.ZodMiniEnum<{
|
|
150
|
+
small: "small";
|
|
151
|
+
large: "large";
|
|
152
|
+
banner: "banner";
|
|
153
|
+
}>;
|
|
154
|
+
title: z.ZodMiniString<string>;
|
|
155
|
+
name: z.ZodMiniString<string>;
|
|
156
|
+
src: z.ZodMiniString<string>;
|
|
157
|
+
type: z.ZodMiniLiteral<"tile">;
|
|
158
|
+
},
|
|
159
|
+
z.core.$strip
|
|
160
|
+
>,
|
|
129
161
|
],
|
|
130
162
|
"type"
|
|
131
163
|
>
|
|
@@ -182,13 +214,10 @@ declare interface DeployedExpose {
|
|
|
182
214
|
|
|
183
215
|
/** @public */
|
|
184
216
|
declare interface ResolvedWorkbenchApp {
|
|
185
|
-
/** The app's unique `name` from `unstable_defineApp`. */
|
|
186
|
-
readonly name: string;
|
|
187
217
|
/** Organization that owns the app — part of its build-id identity. */
|
|
188
218
|
readonly organizationId: string;
|
|
189
219
|
/** Background worker services the app declares. */
|
|
190
220
|
readonly services: NonNullable<DefineAppInput["services"]>;
|
|
191
|
-
/** Hostname the application is created at on first deploy. */
|
|
192
221
|
readonly slug: string;
|
|
193
222
|
/** Dock panel views the app declares. */
|
|
194
223
|
readonly views: NonNullable<DefineAppInput["views"]>;
|
|
@@ -206,6 +235,14 @@ declare interface ResolvedWorkbenchApp {
|
|
|
206
235
|
readonly visibility?: AppVisibility;
|
|
207
236
|
}
|
|
208
237
|
|
|
238
|
+
/** The `tile` variant of an app's `views`. @public */
|
|
239
|
+
declare type TileView = Extract<
|
|
240
|
+
NonNullable<z.output<typeof DefineAppInputSchema>["views"]>[number],
|
|
241
|
+
{
|
|
242
|
+
type: "tile";
|
|
243
|
+
}
|
|
244
|
+
>;
|
|
245
|
+
|
|
209
246
|
declare type ViewDeploymentPayload = z.infer<
|
|
210
247
|
typeof viewDeploymentPayloadSchema
|
|
211
248
|
>;
|
|
@@ -226,7 +263,9 @@ declare const viewDeploymentPayloadSchema: z.ZodMiniObject<
|
|
|
226
263
|
name: z.ZodMiniString<string>;
|
|
227
264
|
src: z.ZodMiniString<string>;
|
|
228
265
|
type: z.ZodMiniEnum<{
|
|
266
|
+
asset_source: "asset_source";
|
|
229
267
|
panel: "panel";
|
|
268
|
+
tile: "tile";
|
|
230
269
|
}>;
|
|
231
270
|
},
|
|
232
271
|
z.core.$loose
|
|
@@ -5,7 +5,7 @@ import { subdebug } from '@sanity/cli-core';
|
|
|
5
5
|
import { pack } from 'tar-fs';
|
|
6
6
|
import { getWorkbenchUrl } from '../../services/applications.js';
|
|
7
7
|
import { createConfig, resolveSingletonInstallationId } from '../../services/installations.js';
|
|
8
|
-
import { summarizeExposeGroup } from './
|
|
8
|
+
import { summarizeExposeGroup } from './summarizeInterfaces.js';
|
|
9
9
|
const debug = subdebug('deploy');
|
|
10
10
|
/**
|
|
11
11
|
* The org's active installation for an app type, or `undefined` when none is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/deployConfig.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip} from 'node:zlib'\n\nimport {type Output, subdebug} from '@sanity/cli-core'\nimport {pack} from 'tar-fs'\n\nimport {getWorkbenchUrl} from '../../services/applications.js'\nimport {createConfig, resolveSingletonInstallationId} from '../../services/installations.js'\nimport {summarizeExposeGroup} from './
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/deploy/deployConfig.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {styleText} from 'node:util'\nimport {createGzip} from 'node:zlib'\n\nimport {type Output, subdebug} from '@sanity/cli-core'\nimport {pack} from 'tar-fs'\n\nimport {getWorkbenchUrl} from '../../services/applications.js'\nimport {createConfig, resolveSingletonInstallationId} from '../../services/installations.js'\nimport {summarizeExposeGroup} from './summarizeInterfaces.js'\n\nconst debug = subdebug('deploy')\n\n/**\n * The org's active installation for an app type, or `undefined` when none is\n * installed. Read-only, so `--dry-run` can report deployability.\n * @internal\n */\nexport async function resolveInstallationId(options: {\n appType: string\n organizationId: string\n}): Promise<string | undefined> {\n switch (options.appType) {\n case 'media-library': {\n return resolveSingletonInstallationId(options.organizationId, 'media-library')\n }\n default: {\n throw new Error(`Cannot create config for unknown app type: ${options.appType}`)\n }\n }\n}\n\n/**\n * A report heading and item list for a config; a media library's `fields` are\n * one of potentially many shapes.\n * @internal\n */\nexport function summarizeConfig(config: {\n appType: string\n fields: {name: string; src: string; title: string}[]\n}): string {\n switch (config.appType) {\n case 'media-library': {\n return summarizeExposeGroup('Media library fields', config.fields)\n }\n default: {\n throw new Error(`Cannot create config for unknown app type: ${config.appType}`)\n }\n }\n}\n\n/**\n * Upload the built module-federation remote to the installation as its config\n * snapshot. `installationId` is resolved by the caller so `--dry-run` never\n * reaches this mutating step.\n * @internal\n */\nexport async function deployConfig(options: {\n appType: string\n installationId: string\n organizationId: string\n output: Output\n sourceDir: string\n version: string\n}): Promise<void> {\n const {appType, installationId, organizationId, output, sourceDir, version} = options\n const tarball = pack(dirname(sourceDir), {entries: [basename(sourceDir)]}).pipe(createGzip())\n await createConfig(installationId, {tarball, version})\n\n debug('Deployed config for app type: %s', appType)\n const url = getWorkbenchUrl(organizationId)\n output.log(`\\n🚀 ${styleText('bold', 'Success!')} Config deployed to ${styleText('cyan', url)}`)\n}\n"],"names":["basename","dirname","styleText","createGzip","subdebug","pack","getWorkbenchUrl","createConfig","resolveSingletonInstallationId","summarizeExposeGroup","debug","resolveInstallationId","options","appType","organizationId","Error","summarizeConfig","config","fields","deployConfig","installationId","output","sourceDir","version","tarball","entries","pipe","url","log"],"mappings":"AAAA,SAAQA,QAAQ,EAAEC,OAAO,QAAO,YAAW;AAC3C,SAAQC,SAAS,QAAO,YAAW;AACnC,SAAQC,UAAU,QAAO,YAAW;AAEpC,SAAqBC,QAAQ,QAAO,mBAAkB;AACtD,SAAQC,IAAI,QAAO,SAAQ;AAE3B,SAAQC,eAAe,QAAO,iCAAgC;AAC9D,SAAQC,YAAY,EAAEC,8BAA8B,QAAO,kCAAiC;AAC5F,SAAQC,oBAAoB,QAAO,2BAA0B;AAE7D,MAAMC,QAAQN,SAAS;AAEvB;;;;CAIC,GACD,OAAO,eAAeO,sBAAsBC,OAG3C;IACC,OAAQA,QAAQC,OAAO;QACrB,KAAK;YAAiB;gBACpB,OAAOL,+BAA+BI,QAAQE,cAAc,EAAE;YAChE;QACA;YAAS;gBACP,MAAM,IAAIC,MAAM,CAAC,2CAA2C,EAAEH,QAAQC,OAAO,EAAE;YACjF;IACF;AACF;AAEA;;;;CAIC,GACD,OAAO,SAASG,gBAAgBC,MAG/B;IACC,OAAQA,OAAOJ,OAAO;QACpB,KAAK;YAAiB;gBACpB,OAAOJ,qBAAqB,wBAAwBQ,OAAOC,MAAM;YACnE;QACA;YAAS;gBACP,MAAM,IAAIH,MAAM,CAAC,2CAA2C,EAAEE,OAAOJ,OAAO,EAAE;YAChF;IACF;AACF;AAEA;;;;;CAKC,GACD,OAAO,eAAeM,aAAaP,OAOlC;IACC,MAAM,EAACC,OAAO,EAAEO,cAAc,EAAEN,cAAc,EAAEO,MAAM,EAAEC,SAAS,EAAEC,OAAO,EAAC,GAAGX;IAC9E,MAAMY,UAAUnB,KAAKJ,QAAQqB,YAAY;QAACG,SAAS;YAACzB,SAASsB;SAAW;IAAA,GAAGI,IAAI,CAACvB;IAChF,MAAMI,aAAaa,gBAAgB;QAACI;QAASD;IAAO;IAEpDb,MAAM,oCAAoCG;IAC1C,MAAMc,MAAMrB,gBAAgBQ;IAC5BO,OAAOO,GAAG,CAAC,CAAC,KAAK,EAAE1B,UAAU,QAAQ,YAAY,oBAAoB,EAAEA,UAAU,QAAQyB,MAAM;AACjG"}
|
|
@@ -2,6 +2,7 @@ import { basename, dirname } from 'node:path';
|
|
|
2
2
|
import { createGzip } from 'node:zlib';
|
|
3
3
|
import { spinner } from '@sanity/cli-core/ux';
|
|
4
4
|
import { pack } from 'tar-fs';
|
|
5
|
+
import { deriveInterfaces } from '../../deriveInterfaces.js';
|
|
5
6
|
import { createApplication, createDeployment, deleteApplication, updateApplication } from '../../services/applications.js';
|
|
6
7
|
/**
|
|
7
8
|
* Create a coreApp record (no deployment), so the CLI can build with its id
|
|
@@ -55,7 +56,7 @@ import { createApplication, createDeployment, deleteApplication, updateApplicati
|
|
|
55
56
|
* application once it has an active deployment.
|
|
56
57
|
* @internal
|
|
57
58
|
*/ export async function deployWorkbenchApp(options) {
|
|
58
|
-
const { applicationId, icon,
|
|
59
|
+
const { app, applicationId, icon, isApp, isAutoUpdating, label = 'Deploying...', onDeployed, sourceDir, title, version, visibility, workspaces } = options;
|
|
59
60
|
const tarball = pack(dirname(sourceDir), {
|
|
60
61
|
entries: [
|
|
61
62
|
basename(sourceDir)
|
|
@@ -65,7 +66,14 @@ import { createApplication, createDeployment, deleteApplication, updateApplicati
|
|
|
65
66
|
try {
|
|
66
67
|
await createDeployment({
|
|
67
68
|
applicationId,
|
|
68
|
-
|
|
69
|
+
// Brett assigns the id and resolves modules by `moduleId`, so neither travels.
|
|
70
|
+
interfaces: deriveInterfaces(app, {
|
|
71
|
+
appTitle: title,
|
|
72
|
+
isApp
|
|
73
|
+
}).map(({ id: _id, src: _src, ...iface })=>({
|
|
74
|
+
...iface,
|
|
75
|
+
version
|
|
76
|
+
})),
|
|
69
77
|
isAutoUpdating,
|
|
70
78
|
tarball,
|
|
71
79
|
version,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/deployWorkbenchApp.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {createGzip} from 'node:zlib'\n\nimport {type AppVisibility} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {pack} from 'tar-fs'\n\nimport {\n type BrettInterface,\n type BrettWorkspace,\n createApplication,\n createDeployment,\n deleteApplication,\n updateApplication,\n} from '../../services/applications.js'\n\n/**\n * A freshly created application record: its id, plus a way to undo the creation.\n * The caller builds and deploys with the id, and calls `rollback` if a later\n * step fails so the record isn't stranded at its slug.\n * @internal\n */\nexport interface CreatedApplication {\n applicationId: string\n rollback: () => Promise<void>\n}\n\n/**\n * Create a coreApp record (no deployment), so the CLI can build with its id\n * before shipping the first deployment. First deploy only.\n * @internal\n */\nexport async function createCoreApp(options: {\n isSingleton?: boolean\n organizationId: string\n slug: string\n title: string\n visibility?: AppVisibility\n}): Promise<CreatedApplication> {\n const spin = spinner('Creating application...').start()\n try {\n const {id} = await createApplication({...options, type: 'coreApp'})\n spin.succeed()\n return {applicationId: id, rollback: () => deleteApplication(id)}\n } catch (error) {\n spin.fail()\n throw error\n }\n}\n\n/**\n * Create a studio record (no deployment).\n * @internal\n */\nexport async function createStudio(options: {\n organizationId: string\n projectId: string | undefined\n slug: string\n title: string\n}): Promise<CreatedApplication> {\n const spin = spinner('Creating studio...').start()\n try {\n const {id} = await createApplication({...options, type: 'studio'})\n spin.succeed()\n return {applicationId: id, rollback: () => deleteApplication(id)}\n } catch (error) {\n spin.fail()\n throw error\n }\n}\n\n/**\n * Ship a deployment to an already-created (or `deployment.appId`) application,\n * then sync its mutable metadata (`title`, and `icon`/`visibility` when set)\n * from config. The deploy endpoint ignores these, so a redeploy patches them\n * here alongside the new deployment.\n *\n * `onDeployed` fires the instant the deployment is live, before the metadata\n * sync — so a caller can disarm a create-time rollback that must not delete an\n * application once it has an active deployment.\n * @internal\n */\nexport async function deployWorkbenchApp(options: {\n applicationId: string\n icon?: string\n
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/deploy/deployWorkbenchApp.ts"],"sourcesContent":["import {basename, dirname} from 'node:path'\nimport {createGzip} from 'node:zlib'\n\nimport {type AppVisibility, type CliConfig} from '@sanity/cli-core'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {pack} from 'tar-fs'\n\nimport {deriveInterfaces} from '../../deriveInterfaces.js'\nimport {\n type BrettInterface,\n type BrettWorkspace,\n createApplication,\n createDeployment,\n deleteApplication,\n updateApplication,\n} from '../../services/applications.js'\n\n/**\n * A freshly created application record: its id, plus a way to undo the creation.\n * The caller builds and deploys with the id, and calls `rollback` if a later\n * step fails so the record isn't stranded at its slug.\n * @internal\n */\nexport interface CreatedApplication {\n applicationId: string\n rollback: () => Promise<void>\n}\n\n/**\n * Create a coreApp record (no deployment), so the CLI can build with its id\n * before shipping the first deployment. First deploy only.\n * @internal\n */\nexport async function createCoreApp(options: {\n isSingleton?: boolean\n organizationId: string\n slug: string\n title: string\n visibility?: AppVisibility\n}): Promise<CreatedApplication> {\n const spin = spinner('Creating application...').start()\n try {\n const {id} = await createApplication({...options, type: 'coreApp'})\n spin.succeed()\n return {applicationId: id, rollback: () => deleteApplication(id)}\n } catch (error) {\n spin.fail()\n throw error\n }\n}\n\n/**\n * Create a studio record (no deployment).\n * @internal\n */\nexport async function createStudio(options: {\n organizationId: string\n projectId: string | undefined\n slug: string\n title: string\n visibility?: AppVisibility\n}): Promise<CreatedApplication> {\n const spin = spinner('Creating studio...').start()\n try {\n const {id} = await createApplication({...options, type: 'studio'})\n spin.succeed()\n return {applicationId: id, rollback: () => deleteApplication(id)}\n } catch (error) {\n spin.fail()\n throw error\n }\n}\n\n/**\n * Ship a deployment to an already-created (or `deployment.appId`) application,\n * then sync its mutable metadata (`title`, and `icon`/`visibility` when set)\n * from config. The deploy endpoint ignores these, so a redeploy patches them\n * here alongside the new deployment.\n *\n * `onDeployed` fires the instant the deployment is live, before the metadata\n * sync — so a caller can disarm a create-time rollback that must not delete an\n * application once it has an active deployment.\n * @internal\n */\nexport async function deployWorkbenchApp(options: {\n app: CliConfig['app']\n applicationId: string\n icon?: string\n isApp: boolean\n isAutoUpdating: boolean\n label?: string\n onDeployed?: () => void\n sourceDir: string\n title: string\n version: string\n visibility?: AppVisibility\n workspaces?: readonly BrettWorkspace[]\n}): Promise<void> {\n const {\n app,\n applicationId,\n icon,\n isApp,\n isAutoUpdating,\n label = 'Deploying...',\n onDeployed,\n sourceDir,\n title,\n version,\n visibility,\n workspaces,\n } = options\n const tarball = pack(dirname(sourceDir), {entries: [basename(sourceDir)]}).pipe(createGzip())\n\n const spin = spinner(label).start()\n try {\n await createDeployment({\n applicationId,\n // Brett assigns the id and resolves modules by `moduleId`, so neither travels.\n interfaces: deriveInterfaces(app, {appTitle: title, isApp}).map(\n ({id: _id, src: _src, ...iface}): BrettInterface => ({...iface, version}),\n ),\n isAutoUpdating,\n tarball,\n version,\n workspaces,\n })\n onDeployed?.()\n await updateApplication(applicationId, {\n title,\n ...(icon ? {icon} : {}),\n ...(visibility ? {visibility} : {}),\n })\n spin.succeed()\n } catch (error) {\n spin.clear()\n throw error\n }\n}\n"],"names":["basename","dirname","createGzip","spinner","pack","deriveInterfaces","createApplication","createDeployment","deleteApplication","updateApplication","createCoreApp","options","spin","start","id","type","succeed","applicationId","rollback","error","fail","createStudio","deployWorkbenchApp","app","icon","isApp","isAutoUpdating","label","onDeployed","sourceDir","title","version","visibility","workspaces","tarball","entries","pipe","interfaces","appTitle","map","_id","src","_src","iface","clear"],"mappings":"AAAA,SAAQA,QAAQ,EAAEC,OAAO,QAAO,YAAW;AAC3C,SAAQC,UAAU,QAAO,YAAW;AAGpC,SAAQC,OAAO,QAAO,sBAAqB;AAC3C,SAAQC,IAAI,QAAO,SAAQ;AAE3B,SAAQC,gBAAgB,QAAO,4BAA2B;AAC1D,SAGEC,iBAAiB,EACjBC,gBAAgB,EAChBC,iBAAiB,EACjBC,iBAAiB,QACZ,iCAAgC;AAavC;;;;CAIC,GACD,OAAO,eAAeC,cAAcC,OAMnC;IACC,MAAMC,OAAOT,QAAQ,2BAA2BU,KAAK;IACrD,IAAI;QACF,MAAM,EAACC,EAAE,EAAC,GAAG,MAAMR,kBAAkB;YAAC,GAAGK,OAAO;YAAEI,MAAM;QAAS;QACjEH,KAAKI,OAAO;QACZ,OAAO;YAACC,eAAeH;YAAII,UAAU,IAAMV,kBAAkBM;QAAG;IAClE,EAAE,OAAOK,OAAO;QACdP,KAAKQ,IAAI;QACT,MAAMD;IACR;AACF;AAEA;;;CAGC,GACD,OAAO,eAAeE,aAAaV,OAMlC;IACC,MAAMC,OAAOT,QAAQ,sBAAsBU,KAAK;IAChD,IAAI;QACF,MAAM,EAACC,EAAE,EAAC,GAAG,MAAMR,kBAAkB;YAAC,GAAGK,OAAO;YAAEI,MAAM;QAAQ;QAChEH,KAAKI,OAAO;QACZ,OAAO;YAACC,eAAeH;YAAII,UAAU,IAAMV,kBAAkBM;QAAG;IAClE,EAAE,OAAOK,OAAO;QACdP,KAAKQ,IAAI;QACT,MAAMD;IACR;AACF;AAEA;;;;;;;;;;CAUC,GACD,OAAO,eAAeG,mBAAmBX,OAaxC;IACC,MAAM,EACJY,GAAG,EACHN,aAAa,EACbO,IAAI,EACJC,KAAK,EACLC,cAAc,EACdC,QAAQ,cAAc,EACtBC,UAAU,EACVC,SAAS,EACTC,KAAK,EACLC,OAAO,EACPC,UAAU,EACVC,UAAU,EACX,GAAGtB;IACJ,MAAMuB,UAAU9B,KAAKH,QAAQ4B,YAAY;QAACM,SAAS;YAACnC,SAAS6B;SAAW;IAAA,GAAGO,IAAI,CAAClC;IAEhF,MAAMU,OAAOT,QAAQwB,OAAOd,KAAK;IACjC,IAAI;QACF,MAAMN,iBAAiB;YACrBU;YACA,+EAA+E;YAC/EoB,YAAYhC,iBAAiBkB,KAAK;gBAACe,UAAUR;gBAAOL;YAAK,GAAGc,GAAG,CAC7D,CAAC,EAACzB,IAAI0B,GAAG,EAAEC,KAAKC,IAAI,EAAE,GAAGC,OAAM,GAAsB,CAAA;oBAAC,GAAGA,KAAK;oBAAEZ;gBAAO,CAAA;YAEzEL;YACAQ;YACAH;YACAE;QACF;QACAL;QACA,MAAMnB,kBAAkBQ,eAAe;YACrCa;YACA,GAAIN,OAAO;gBAACA;YAAI,IAAI,CAAC,CAAC;YACtB,GAAIQ,aAAa;gBAACA;YAAU,IAAI,CAAC,CAAC;QACpC;QACApB,KAAKI,OAAO;IACd,EAAE,OAAOG,OAAO;QACdP,KAAKgC,KAAK;QACV,MAAMzB;IACR;AACF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const label = (item)=>item.title === item.name ? item.name : `${item.title} (${item.name})`;
|
|
2
|
+
/**
|
|
3
|
+
* One `Title (name): src` report line per declared entry point.
|
|
4
|
+
* @internal
|
|
5
|
+
*/ export function summarizeExposeGroup(heading, items) {
|
|
6
|
+
return `${heading}:\n${items.map((item)=>` ${label(item)}: ${item.src}`).join('\n')}`;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The deploy summary of an app's exposes: the structured records (for `--json`)
|
|
10
|
+
* and one report line per non-empty group (for the human report).
|
|
11
|
+
* @internal
|
|
12
|
+
*/ export function summarizeInterfaces({ services, views }) {
|
|
13
|
+
const toExpose = (decl)=>({
|
|
14
|
+
name: decl.name,
|
|
15
|
+
src: decl.src,
|
|
16
|
+
title: decl.title,
|
|
17
|
+
type: decl.type
|
|
18
|
+
});
|
|
19
|
+
const viewExposes = (views ?? []).map((view)=>toExpose(view));
|
|
20
|
+
const serviceExposes = (services ?? []).map((service)=>toExpose(service));
|
|
21
|
+
const lines = [];
|
|
22
|
+
if (viewExposes.length > 0) lines.push(summarizeExposeGroup('Views', viewExposes));
|
|
23
|
+
if (serviceExposes.length > 0) lines.push(summarizeExposeGroup('Services', serviceExposes));
|
|
24
|
+
return {
|
|
25
|
+
exposes: [
|
|
26
|
+
...viewExposes,
|
|
27
|
+
...serviceExposes
|
|
28
|
+
],
|
|
29
|
+
lines
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=summarizeInterfaces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/deploy/summarizeInterfaces.ts"],"sourcesContent":["import {type WorkbenchExposes} from '../../resolveWorkbenchApp.js'\n\n/** A view or service as the deploy report and `--json` output surface it. */\nexport interface DeployedExpose {\n name: string\n src: string\n title: string\n type: string\n}\n\nconst label = (item: {name: string; title: string}) =>\n item.title === item.name ? item.name : `${item.title} (${item.name})`\n\n/**\n * One `Title (name): src` report line per declared entry point.\n * @internal\n */\nexport function summarizeExposeGroup(\n heading: string,\n items: readonly {name: string; src: string; title: string}[],\n): string {\n return `${heading}:\\n${items.map((item) => ` ${label(item)}: ${item.src}`).join('\\n')}`\n}\n\n/**\n * The deploy summary of an app's exposes: the structured records (for `--json`)\n * and one report line per non-empty group (for the human report).\n * @internal\n */\nexport function summarizeInterfaces({services, views}: WorkbenchExposes): {\n exposes: DeployedExpose[]\n lines: string[]\n} {\n const toExpose = (decl: DeployedExpose): DeployedExpose => ({\n name: decl.name,\n src: decl.src,\n title: decl.title,\n type: decl.type,\n })\n const viewExposes = (views ?? []).map((view) => toExpose(view))\n const serviceExposes = (services ?? []).map((service) => toExpose(service))\n\n const lines: string[] = []\n if (viewExposes.length > 0) lines.push(summarizeExposeGroup('Views', viewExposes))\n if (serviceExposes.length > 0) lines.push(summarizeExposeGroup('Services', serviceExposes))\n return {exposes: [...viewExposes, ...serviceExposes], lines}\n}\n"],"names":["label","item","title","name","summarizeExposeGroup","heading","items","map","src","join","summarizeInterfaces","services","views","toExpose","decl","type","viewExposes","view","serviceExposes","service","lines","length","push","exposes"],"mappings":"AAUA,MAAMA,QAAQ,CAACC,OACbA,KAAKC,KAAK,KAAKD,KAAKE,IAAI,GAAGF,KAAKE,IAAI,GAAG,GAAGF,KAAKC,KAAK,CAAC,EAAE,EAAED,KAAKE,IAAI,CAAC,CAAC,CAAC;AAEvE;;;CAGC,GACD,OAAO,SAASC,qBACdC,OAAe,EACfC,KAA4D;IAE5D,OAAO,GAAGD,QAAQ,GAAG,EAAEC,MAAMC,GAAG,CAAC,CAACN,OAAS,CAAC,EAAE,EAAED,MAAMC,MAAM,EAAE,EAAEA,KAAKO,GAAG,EAAE,EAAEC,IAAI,CAAC,OAAO;AAC1F;AAEA;;;;CAIC,GACD,OAAO,SAASC,oBAAoB,EAACC,QAAQ,EAAEC,KAAK,EAAmB;IAIrE,MAAMC,WAAW,CAACC,OAA0C,CAAA;YAC1DX,MAAMW,KAAKX,IAAI;YACfK,KAAKM,KAAKN,GAAG;YACbN,OAAOY,KAAKZ,KAAK;YACjBa,MAAMD,KAAKC,IAAI;QACjB,CAAA;IACA,MAAMC,cAAc,AAACJ,CAAAA,SAAS,EAAE,AAAD,EAAGL,GAAG,CAAC,CAACU,OAASJ,SAASI;IACzD,MAAMC,iBAAiB,AAACP,CAAAA,YAAY,EAAE,AAAD,EAAGJ,GAAG,CAAC,CAACY,UAAYN,SAASM;IAElE,MAAMC,QAAkB,EAAE;IAC1B,IAAIJ,YAAYK,MAAM,GAAG,GAAGD,MAAME,IAAI,CAAClB,qBAAqB,SAASY;IACrE,IAAIE,eAAeG,MAAM,GAAG,GAAGD,MAAME,IAAI,CAAClB,qBAAqB,YAAYc;IAC3E,OAAO;QAACK,SAAS;eAAIP;eAAgBE;SAAe;QAAEE;IAAK;AAC7D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/deploy/viewDeployment.ts"],"sourcesContent":["import {z} from 'zod/mini'\n\n/**\n * A view record as persisted to the application service: `type`, `name`, `src`,\n * plus any view-type-specific attributes (passed through for storage).\n */\nconst viewRecordSchema = z.looseObject({\n name: z.string().check(z.regex(/^[a-zA-Z0-9_-]+$/, 'View `name` must match /^[a-zA-Z0-9_-]+$/')),\n src: z.string(),\n type: z.enum(['panel']),\n})\n\n/**\n * Payload registering an app's views with the application service on deploy.\n *\n * Phase 1 stub: the service that stores views does not exist yet, so the\n * payload is validated and logged only — never sent. Builds the contract the\n * application-service endpoint will accept.\n */\nconst viewDeploymentPayloadSchema = z.object({\n applicationId: z.string(),\n views: z.array(viewRecordSchema),\n})\n\nexport type ViewDeploymentPayload = z.infer<typeof viewDeploymentPayloadSchema>\n\n/**\n * Validates an app's declared views into the application-service payload.\n * Throws (via Zod) when a view declaration is malformed.\n */\nexport function buildViewDeploymentPayload(input: {\n applicationId: string\n views?: ReadonlyArray<Record<string, unknown>>\n}): ViewDeploymentPayload {\n return viewDeploymentPayloadSchema.parse({\n applicationId: input.applicationId,\n views: input.views ?? [],\n })\n}\n"],"names":["z","viewRecordSchema","looseObject","name","string","check","regex","src","type","enum","viewDeploymentPayloadSchema","object","applicationId","views","array","buildViewDeploymentPayload","input","parse"],"mappings":"AAAA,SAAQA,CAAC,QAAO,WAAU;AAE1B;;;CAGC,GACD,MAAMC,mBAAmBD,EAAEE,WAAW,CAAC;IACrCC,MAAMH,EAAEI,MAAM,GAAGC,KAAK,CAACL,EAAEM,KAAK,CAAC,oBAAoB;IACnDC,KAAKP,EAAEI,MAAM;IACbI,MAAMR,EAAES,IAAI,CAAC;QAAC;
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/deploy/viewDeployment.ts"],"sourcesContent":["import {z} from 'zod/mini'\n\n/**\n * A view record as persisted to the application service: `type`, `name`, `src`,\n * plus any view-type-specific attributes (passed through for storage).\n */\nconst viewRecordSchema = z.looseObject({\n name: z.string().check(z.regex(/^[a-zA-Z0-9_-]+$/, 'View `name` must match /^[a-zA-Z0-9_-]+$/')),\n src: z.string(),\n type: z.enum(['panel', 'asset_source', 'tile']),\n})\n\n/**\n * Payload registering an app's views with the application service on deploy.\n *\n * Phase 1 stub: the service that stores views does not exist yet, so the\n * payload is validated and logged only — never sent. Builds the contract the\n * application-service endpoint will accept.\n */\nconst viewDeploymentPayloadSchema = z.object({\n applicationId: z.string(),\n views: z.array(viewRecordSchema),\n})\n\nexport type ViewDeploymentPayload = z.infer<typeof viewDeploymentPayloadSchema>\n\n/**\n * Validates an app's declared views into the application-service payload.\n * Throws (via Zod) when a view declaration is malformed.\n */\nexport function buildViewDeploymentPayload(input: {\n applicationId: string\n views?: ReadonlyArray<Record<string, unknown>>\n}): ViewDeploymentPayload {\n return viewDeploymentPayloadSchema.parse({\n applicationId: input.applicationId,\n views: input.views ?? [],\n })\n}\n"],"names":["z","viewRecordSchema","looseObject","name","string","check","regex","src","type","enum","viewDeploymentPayloadSchema","object","applicationId","views","array","buildViewDeploymentPayload","input","parse"],"mappings":"AAAA,SAAQA,CAAC,QAAO,WAAU;AAE1B;;;CAGC,GACD,MAAMC,mBAAmBD,EAAEE,WAAW,CAAC;IACrCC,MAAMH,EAAEI,MAAM,GAAGC,KAAK,CAACL,EAAEM,KAAK,CAAC,oBAAoB;IACnDC,KAAKP,EAAEI,MAAM;IACbI,MAAMR,EAAES,IAAI,CAAC;QAAC;QAAS;QAAgB;KAAO;AAChD;AAEA;;;;;;CAMC,GACD,MAAMC,8BAA8BV,EAAEW,MAAM,CAAC;IAC3CC,eAAeZ,EAAEI,MAAM;IACvBS,OAAOb,EAAEc,KAAK,CAACb;AACjB;AAIA;;;CAGC,GACD,OAAO,SAASc,2BAA2BC,KAG1C;IACC,OAAON,4BAA4BO,KAAK,CAAC;QACvCL,eAAeI,MAAMJ,aAAa;QAClCC,OAAOG,MAAMH,KAAK,IAAI,EAAE;IAC1B;AACF"}
|
|
@@ -1,56 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MEDIA_LIBRARY_CONFIG_CONTRACT_VERSION } from '../../contract.js';
|
|
2
2
|
import { isWorkbenchApp, readConfig } from '../../defineApp.js';
|
|
3
|
-
import { FEDERATION_FILE_NAME, RUNTIME_DIR } from '../build/vite/constants.js';
|
|
4
|
-
/** What a studio exposes as `./App` — the generated entry that renders `sanity.config.ts`. */ const GENERATED_ENTRY = `./${RUNTIME_DIR}/${FEDERATION_FILE_NAME}.jsx`;
|
|
5
|
-
/**
|
|
6
|
-
* Map a workbench app's declarations to its registry interface records. A studio
|
|
7
|
-
* that declares `entry` is rejected (studio app views aren't implemented yet).
|
|
8
|
-
*/ export function deriveInterfaces(app, options) {
|
|
9
|
-
if (!isWorkbenchApp(app)) return undefined;
|
|
10
|
-
if (!options.isApp && app.entry !== undefined) {
|
|
11
|
-
throw new Error('App views for studios are not implemented yet');
|
|
12
|
-
}
|
|
13
|
-
const interfaceId = (type, name)=>`${app.name}-${type}-${name}`;
|
|
14
|
-
const views = (app.views ?? []).map((view)=>({
|
|
15
|
-
id: interfaceId('panel', view.name),
|
|
16
|
-
metadata: null,
|
|
17
|
-
moduleId: interfaceModuleId('panel', view.name),
|
|
18
|
-
name: view.name,
|
|
19
|
-
src: view.src,
|
|
20
|
-
title: view.title ?? view.name,
|
|
21
|
-
type: 'panel',
|
|
22
|
-
version: String(VIEW_CONTRACT_VERSION)
|
|
23
|
-
}));
|
|
24
|
-
const services = (app.services ?? []).map((service)=>({
|
|
25
|
-
id: interfaceId('worker', service.name),
|
|
26
|
-
metadata: null,
|
|
27
|
-
moduleId: interfaceModuleId('worker', service.name),
|
|
28
|
-
name: service.name,
|
|
29
|
-
src: service.src,
|
|
30
|
-
title: service.title ?? service.name,
|
|
31
|
-
type: 'worker',
|
|
32
|
-
version: String(SERVICE_CONTRACT_VERSION)
|
|
33
|
-
}));
|
|
34
|
-
// Tracks what the build exposes as `./App`: an app's declared `entry`, and a
|
|
35
|
-
// studio's generated entry. A dock-only app (no `entry`) exposes none.
|
|
36
|
-
const appEntry = options.isApp ? app.entry : GENERATED_ENTRY;
|
|
37
|
-
const appView = appEntry === undefined ? [] : [
|
|
38
|
-
{
|
|
39
|
-
id: interfaceId('app', app.name),
|
|
40
|
-
metadata: null,
|
|
41
|
-
moduleId: interfaceModuleId('app', app.name),
|
|
42
|
-
name: app.name,
|
|
43
|
-
src: appEntry,
|
|
44
|
-
title: app.title,
|
|
45
|
-
type: 'app'
|
|
46
|
-
}
|
|
47
|
-
];
|
|
48
|
-
return [
|
|
49
|
-
...views,
|
|
50
|
-
...services,
|
|
51
|
-
...appView
|
|
52
|
-
];
|
|
53
|
-
}
|
|
54
3
|
/**
|
|
55
4
|
* The named source files a config's generated module is built from, dispatched
|
|
56
5
|
* per app type — the projection the exposes-set id keys on, so the generic HMR
|
|
@@ -91,7 +40,7 @@ import { FEDERATION_FILE_NAME, RUNTIME_DIR } from '../build/vite/constants.js';
|
|
|
91
40
|
src: field.src,
|
|
92
41
|
title: field.title
|
|
93
42
|
})),
|
|
94
|
-
moduleName: app.
|
|
43
|
+
moduleName: app.slug,
|
|
95
44
|
version: String(MEDIA_LIBRARY_CONFIG_CONTRACT_VERSION)
|
|
96
45
|
};
|
|
97
46
|
return [
|
|
@@ -111,4 +60,4 @@ import { FEDERATION_FILE_NAME, RUNTIME_DIR } from '../build/vite/constants.js';
|
|
|
111
60
|
return Array.from(new Uint8Array(digest), (byte)=>byte.toString(16).padStart(2, '0')).join('');
|
|
112
61
|
}
|
|
113
62
|
|
|
114
|
-
//# sourceMappingURL=
|
|
63
|
+
//# sourceMappingURL=deriveConfigs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/dev/deriveConfigs.ts"],"sourcesContent":["import {type CliConfig} from '@sanity/cli-core'\n\nimport {MEDIA_LIBRARY_CONFIG_CONTRACT_VERSION} from '../../contract.js'\nimport {isWorkbenchApp, readConfig} from '../../defineApp.js'\nimport {type DevServerManifest} from './registry.js'\n\n/** One forwarded interface record on the dev-server registry entry. */\nexport type DevServerInterface = NonNullable<DevServerManifest['interfaces']>[number]\n\n/** One forwarded config on the dev-server registry entry. */\nexport type DevServerConfig = NonNullable<DevServerManifest['configs']>[number]\n\n/**\n * The named source files a config's generated module is built from, dispatched\n * per app type — the projection the exposes-set id keys on, so the generic HMR\n * tracker owns none of the per-type shape. Throws on an app type it can't\n * handle, so a new config family has to register its shape here.\n */\nexport function deriveConfigEntries(config: DevServerConfig): {name: string; src: string}[] {\n switch (config.appType) {\n case 'media-library': {\n return config.fields.map((field) => ({name: field.name, src: field.src}))\n }\n default: {\n throw new Error(`Cannot derive entries for unknown config appType: ${config.appType}`)\n }\n }\n}\n\n/**\n * The fields' schema *values* can't serialize — the workbench loads them from\n * the federation module. `src` stays on so the exposes-set id keys on it and a\n * repoint rebuilds. `appType` routes the config to the singleton (no app id to\n * key on). `id` is a content hash of the entry — it fills the\n * installation-config id slot deployed apps get from the applications API,\n * and the workbench keys change detection on it. `version` is a string, like\n * the one Brett returns on a deployed `activeConfig`.\n */\nexport async function deriveConfigs(app: CliConfig['app']): Promise<DevServerConfig[]> {\n if (!isWorkbenchApp(app)) return []\n const config = readConfig(app)\n if (!config) return []\n const entry = {\n appType: config.appType,\n fields: config.fields.map((field) => ({\n name: field.name,\n public: field.public,\n src: field.src,\n title: field.title,\n })),\n moduleName: app.slug,\n version: String(MEDIA_LIBRARY_CONFIG_CONTRACT_VERSION),\n }\n return [{...entry, id: await contentHash(JSON.stringify(entry))}]\n}\n\n/**\n * SHA-256 of a string, as hex, via the Web Crypto API — available in both Node\n * and the browser. `node:crypto` can't be used: the Vite dev server's dep scan\n * pulls this module into the browser graph.\n */\nasync function contentHash(input: string): Promise<string> {\n // eslint-disable-next-line n/no-unsupported-features/node-builtins -- the Web Crypto global is available on our Node target and in the browser\n const digest = await globalThis.crypto.subtle.digest('SHA-256', new TextEncoder().encode(input))\n return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, '0')).join('')\n}\n"],"names":["MEDIA_LIBRARY_CONFIG_CONTRACT_VERSION","isWorkbenchApp","readConfig","deriveConfigEntries","config","appType","fields","map","field","name","src","Error","deriveConfigs","app","entry","public","title","moduleName","slug","version","String","id","contentHash","JSON","stringify","input","digest","globalThis","crypto","subtle","TextEncoder","encode","Array","from","Uint8Array","byte","toString","padStart","join"],"mappings":"AAEA,SAAQA,qCAAqC,QAAO,oBAAmB;AACvE,SAAQC,cAAc,EAAEC,UAAU,QAAO,qBAAoB;AAS7D;;;;;CAKC,GACD,OAAO,SAASC,oBAAoBC,MAAuB;IACzD,OAAQA,OAAOC,OAAO;QACpB,KAAK;YAAiB;gBACpB,OAAOD,OAAOE,MAAM,CAACC,GAAG,CAAC,CAACC,QAAW,CAAA;wBAACC,MAAMD,MAAMC,IAAI;wBAAEC,KAAKF,MAAME,GAAG;oBAAA,CAAA;YACxE;QACA;YAAS;gBACP,MAAM,IAAIC,MAAM,CAAC,kDAAkD,EAAEP,OAAOC,OAAO,EAAE;YACvF;IACF;AACF;AAEA;;;;;;;;CAQC,GACD,OAAO,eAAeO,cAAcC,GAAqB;IACvD,IAAI,CAACZ,eAAeY,MAAM,OAAO,EAAE;IACnC,MAAMT,SAASF,WAAWW;IAC1B,IAAI,CAACT,QAAQ,OAAO,EAAE;IACtB,MAAMU,QAAQ;QACZT,SAASD,OAAOC,OAAO;QACvBC,QAAQF,OAAOE,MAAM,CAACC,GAAG,CAAC,CAACC,QAAW,CAAA;gBACpCC,MAAMD,MAAMC,IAAI;gBAChBM,QAAQP,MAAMO,MAAM;gBACpBL,KAAKF,MAAME,GAAG;gBACdM,OAAOR,MAAMQ,KAAK;YACpB,CAAA;QACAC,YAAYJ,IAAIK,IAAI;QACpBC,SAASC,OAAOpB;IAClB;IACA,OAAO;QAAC;YAAC,GAAGc,KAAK;YAAEO,IAAI,MAAMC,YAAYC,KAAKC,SAAS,CAACV;QAAO;KAAE;AACnE;AAEA;;;;CAIC,GACD,eAAeQ,YAAYG,KAAa;IACtC,+IAA+I;IAC/I,MAAMC,SAAS,MAAMC,WAAWC,MAAM,CAACC,MAAM,CAACH,MAAM,CAAC,WAAW,IAAII,cAAcC,MAAM,CAACN;IACzF,OAAOO,MAAMC,IAAI,CAAC,IAAIC,WAAWR,SAAS,CAACS,OAASA,KAAKC,QAAQ,CAAC,IAAIC,QAAQ,CAAC,GAAG,MAAMC,IAAI,CAAC;AAC/F"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { deriveConfigEntries } from './
|
|
1
|
+
import { deriveConfigEntries } from './deriveConfigs.js';
|
|
2
2
|
/**
|
|
3
3
|
* Order-independent id of an app's exposed-module set. Keys each interface by
|
|
4
4
|
* its type, name, and source file, and each config by its module
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/dev/exposesSetId.ts"],"sourcesContent":["import {\n deriveConfigEntries,\n type DevServerConfig,\n type DevServerInterface,\n} from './
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/dev/exposesSetId.ts"],"sourcesContent":["import {\n deriveConfigEntries,\n type DevServerConfig,\n type DevServerInterface,\n} from './deriveConfigs.js'\nimport {type DevServerManifest} from './registry.js'\n\ninterface ExposeSet {\n configs?: readonly DevServerConfig[] | undefined\n interfaces?: readonly DevServerInterface[] | undefined\n}\n\n/**\n * Order-independent id of an app's exposed-module set. Keys each interface by\n * its type, name, and source file, and each config by its module\n * identity plus one key per entry (a named source file), so the id changes on\n * any rebuild-worthy edit — add, remove, rename, repoint, or gaining/losing the\n * config module — while reordering and HMR content edits keep it stable.\n */\nexport function exposesSetId({configs, interfaces}: ExposeSet): string {\n const keys = [\n ...(interfaces ?? []).map((iface) => [iface.type, iface.name, iface.src].join('::')),\n ...(configs ?? []).flatMap((config) => [\n ['config', config.appType].join('::'),\n ...deriveConfigEntries(config).map((entry) =>\n ['config', config.appType, entry.name, entry.src].join('::'),\n ),\n ]),\n ]\n if (keys.length === 0) return ''\n return keys.toSorted().join('|')\n}\n\n/**\n * `changed`/`commit` are split so the caller commits only after the rebuild that\n * depends on the new set succeeds — a thrown rebuild retries on the next save.\n */\nexport function trackExposesSet(initial: ExposeSet): {\n changed: (next: ExposeSet) => boolean\n commit: (next: ExposeSet) => void\n} {\n let lastId = exposesSetId(initial)\n return {\n changed: (next) => exposesSetId(next) !== lastId,\n commit: (next) => {\n lastId = exposesSetId(next)\n },\n }\n}\n\nconst serverKey = (server: DevServerManifest): string =>\n `${server.id ?? ''}@${server.host ?? ''}:${server.port}`\n\nconst serverExposesId = (server: DevServerManifest): string =>\n exposesSetId({configs: server.configs, interfaces: server.interfaces})\n\n/**\n * Multi-app counterpart to {@link trackExposesSet}: true when a *known* app's\n * set changed — its remote was rebuilt, so the workbench must full-reload to\n * drop the stale remote-entry. A new/removed app isn't a rebuild.\n */\nexport function createExposesTracker(): {\n hasChanged: (servers: readonly DevServerManifest[]) => boolean\n} {\n let known = new Map<string, string>()\n return {\n hasChanged(servers) {\n const rebuilt = servers.some((server) => {\n const key = serverKey(server)\n return known.has(key) && known.get(key) !== serverExposesId(server)\n })\n known = new Map(servers.map((server) => [serverKey(server), serverExposesId(server)]))\n return rebuilt\n },\n }\n}\n"],"names":["deriveConfigEntries","exposesSetId","configs","interfaces","keys","map","iface","type","name","src","join","flatMap","config","appType","entry","length","toSorted","trackExposesSet","initial","lastId","changed","next","commit","serverKey","server","id","host","port","serverExposesId","createExposesTracker","known","Map","hasChanged","servers","rebuilt","some","key","has","get"],"mappings":"AAAA,SACEA,mBAAmB,QAGd,qBAAoB;AAQ3B;;;;;;CAMC,GACD,OAAO,SAASC,aAAa,EAACC,OAAO,EAAEC,UAAU,EAAY;IAC3D,MAAMC,OAAO;WACR,AAACD,CAAAA,cAAc,EAAE,AAAD,EAAGE,GAAG,CAAC,CAACC,QAAU;gBAACA,MAAMC,IAAI;gBAAED,MAAME,IAAI;gBAAEF,MAAMG,GAAG;aAAC,CAACC,IAAI,CAAC;WAC3E,AAACR,CAAAA,WAAW,EAAE,AAAD,EAAGS,OAAO,CAAC,CAACC,SAAW;gBACrC;oBAAC;oBAAUA,OAAOC,OAAO;iBAAC,CAACH,IAAI,CAAC;mBAC7BV,oBAAoBY,QAAQP,GAAG,CAAC,CAACS,QAClC;wBAAC;wBAAUF,OAAOC,OAAO;wBAAEC,MAAMN,IAAI;wBAAEM,MAAML,GAAG;qBAAC,CAACC,IAAI,CAAC;aAE1D;KACF;IACD,IAAIN,KAAKW,MAAM,KAAK,GAAG,OAAO;IAC9B,OAAOX,KAAKY,QAAQ,GAAGN,IAAI,CAAC;AAC9B;AAEA;;;CAGC,GACD,OAAO,SAASO,gBAAgBC,OAAkB;IAIhD,IAAIC,SAASlB,aAAaiB;IAC1B,OAAO;QACLE,SAAS,CAACC,OAASpB,aAAaoB,UAAUF;QAC1CG,QAAQ,CAACD;YACPF,SAASlB,aAAaoB;QACxB;IACF;AACF;AAEA,MAAME,YAAY,CAACC,SACjB,GAAGA,OAAOC,EAAE,IAAI,GAAG,CAAC,EAAED,OAAOE,IAAI,IAAI,GAAG,CAAC,EAAEF,OAAOG,IAAI,EAAE;AAE1D,MAAMC,kBAAkB,CAACJ,SACvBvB,aAAa;QAACC,SAASsB,OAAOtB,OAAO;QAAEC,YAAYqB,OAAOrB,UAAU;IAAA;AAEtE;;;;CAIC,GACD,OAAO,SAAS0B;IAGd,IAAIC,QAAQ,IAAIC;IAChB,OAAO;QACLC,YAAWC,OAAO;YAChB,MAAMC,UAAUD,QAAQE,IAAI,CAAC,CAACX;gBAC5B,MAAMY,MAAMb,UAAUC;gBACtB,OAAOM,MAAMO,GAAG,CAACD,QAAQN,MAAMQ,GAAG,CAACF,SAASR,gBAAgBJ;YAC9D;YACAM,QAAQ,IAAIC,IAAIE,QAAQ5B,GAAG,CAAC,CAACmB,SAAW;oBAACD,UAAUC;oBAASI,gBAAgBJ;iBAAQ;YACpF,OAAOU;QACT;IACF;AACF"}
|
|
@@ -2,7 +2,7 @@ import { existsSync, mkdirSync, readdirSync, readFileSync, unlinkSync, watch, wr
|
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { coreAppManifestSchema, getSanityDataDir, studioManifestSchema, subdebug } from '@sanity/cli-core';
|
|
4
4
|
import { z } from 'zod/mini';
|
|
5
|
-
import { AppInterfaceMetadataSchema } from '../../contract.js';
|
|
5
|
+
import { AppInterfaceMetadataSchema, TileInterfaceMetadataSchema } from '../../contract.js';
|
|
6
6
|
import { canonicalizeWatchDir } from './canonicalizeWatchDir.js';
|
|
7
7
|
import { getProcessStartTime, isOurProcess } from './processLiveness.js';
|
|
8
8
|
/**
|
|
@@ -55,6 +55,16 @@ const interfaceBaseFields = {
|
|
|
55
55
|
metadata: z.null(),
|
|
56
56
|
type: z.literal('panel')
|
|
57
57
|
}),
|
|
58
|
+
z.object({
|
|
59
|
+
...interfaceBaseFields,
|
|
60
|
+
metadata: z.null(),
|
|
61
|
+
type: z.literal('asset_source')
|
|
62
|
+
}),
|
|
63
|
+
z.object({
|
|
64
|
+
...interfaceBaseFields,
|
|
65
|
+
metadata: TileInterfaceMetadataSchema,
|
|
66
|
+
type: z.literal('tile')
|
|
67
|
+
}),
|
|
58
68
|
z.object({
|
|
59
69
|
...interfaceBaseFields,
|
|
60
70
|
metadata: z.null(),
|
|
@@ -78,7 +88,7 @@ const devServerManifestSchema = z.object({
|
|
|
78
88
|
// Content hash of the config — the workbench's change-detection key
|
|
79
89
|
// (see deriveConfigs).
|
|
80
90
|
id: z.string(),
|
|
81
|
-
// The app's `unstable_defineApp`
|
|
91
|
+
// The app's `unstable_defineApp` slug — the module-federation alias the
|
|
82
92
|
// workbench loads this config's live values from.
|
|
83
93
|
moduleName: z.optional(z.string()),
|
|
84
94
|
// The version the workbench federates this config's module under —
|