@sanity/workbench-cli 2.1.0 → 2.2.1
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 +1 -1
- package/dist/_exports/build.d.ts +4 -4
- package/dist/_exports/build.js +2 -1
- package/dist/_exports/build.js.map +1 -1
- package/dist/_exports/defineApp-DldjQwq6.d.ts +375 -0
- package/dist/_exports/deploy.d.ts +10 -9
- package/dist/_exports/deploy.js +1 -0
- package/dist/_exports/deploy.js.map +1 -1
- package/dist/_exports/dev.d.ts +1 -1
- package/dist/_exports/index.d.ts +23 -16
- package/dist/_exports/index.js +2 -1
- package/dist/_exports/index.js.map +1 -1
- package/dist/_exports/preview.d.ts +1 -1
- package/dist/_exports/{registry-DI7hnTof.d.ts → registry-HE_dEHFa.d.ts} +38 -15
- package/dist/_exports/resolveWorkbenchConfig-6iznHbED.d.ts +60 -0
- package/dist/_exports/{summarizeInterfaces-DLsq6P43.d.ts → summarizeInterfaces-CjkeWwkY.d.ts} +20 -17
- package/dist/_exports/undeploy.d.ts +12 -9
- package/dist/actions/build/artifact.js +1 -1
- package/dist/actions/build/artifact.js.map +1 -1
- package/dist/actions/build/views/artifact.js +1 -1
- package/dist/actions/build/views/artifact.js.map +1 -1
- package/dist/actions/build/vite/optimize-deps.js +3 -3
- package/dist/actions/build/vite/optimize-deps.js.map +1 -1
- package/dist/actions/build/vite/plugins/plugin-module-federation.js +1 -2
- package/dist/actions/build/vite/plugins/plugin-module-federation.js.map +1 -1
- package/dist/actions/build/vite/plugins/plugin-sanity-federation-runtime.js +1 -1
- package/dist/actions/build/vite/plugins/plugin-sanity-federation-runtime.js.map +1 -1
- package/dist/actions/build/vite/workbench-vite-plugins.js +1 -1
- package/dist/actions/build/vite/workbench-vite-plugins.js.map +1 -1
- package/dist/actions/deploy/deployPayload.js +0 -3
- package/dist/actions/deploy/deployPayload.js.map +1 -1
- package/dist/actions/deploy/deployWorkbenchApp.js +46 -4
- package/dist/actions/deploy/deployWorkbenchApp.js.map +1 -1
- package/dist/actions/deploy/getWorkbench.js +4 -5
- package/dist/actions/deploy/getWorkbench.js.map +1 -1
- package/dist/actions/deploy/summarizeInterfaces.js +14 -10
- package/dist/actions/deploy/summarizeInterfaces.js.map +1 -1
- package/dist/actions/deploy/viewDeployment.js +17 -5
- package/dist/actions/deploy/viewDeployment.js.map +1 -1
- package/dist/actions/dev/deriveConfigs.js +9 -6
- package/dist/actions/dev/deriveConfigs.js.map +1 -1
- package/dist/actions/dev/exposesSetId.js +2 -2
- package/dist/actions/dev/exposesSetId.js.map +1 -1
- package/dist/actions/dev/registry.js +31 -25
- package/dist/actions/dev/registry.js.map +1 -1
- package/dist/actions/dev/startDevManifestWatcher.js.map +1 -1
- package/dist/actions/dev/startDevServerRegistration.js +35 -60
- package/dist/actions/dev/startDevServerRegistration.js.map +1 -1
- package/dist/actions/dev/startWorkbenchDevServer.js +3 -3
- package/dist/actions/dev/startWorkbenchDevServer.js.map +1 -1
- package/dist/actions/preview/serveBuiltApplication.js +1 -1
- package/dist/actions/preview/serveBuiltApplication.js.map +1 -1
- package/dist/actions/preview/startWorkbenchPreview.js +1 -1
- package/dist/actions/preview/startWorkbenchPreview.js.map +1 -1
- package/dist/actions/undeploy/workbenchUndeployAdapter.js +24 -33
- package/dist/actions/undeploy/workbenchUndeployAdapter.js.map +1 -1
- package/dist/appId.js +13 -9
- package/dist/appId.js.map +1 -1
- package/dist/applicationReference.js +12 -0
- package/dist/applicationReference.js.map +1 -0
- package/dist/contract.js +69 -31
- package/dist/contract.js.map +1 -1
- package/dist/defineApp.js +52 -59
- package/dist/defineApp.js.map +1 -1
- package/dist/defineView.js +3 -3
- package/dist/defineView.js.map +1 -1
- package/dist/deriveInterfaces.js +45 -19
- package/dist/deriveInterfaces.js.map +1 -1
- package/dist/resolveWorkbenchApp.js +13 -9
- package/dist/resolveWorkbenchApp.js.map +1 -1
- package/dist/resolveWorkbenchConfig.js +30 -0
- package/dist/resolveWorkbenchConfig.js.map +1 -0
- package/dist/services/applications.js +7 -1
- package/dist/services/applications.js.map +1 -1
- package/package.json +2 -2
- package/dist/_exports/contract-DyG11fQ7.d.ts +0 -45
- package/dist/_exports/defineApp-DSvQx8rf.d.ts +0 -151
- package/dist/_exports/resolveWorkbenchApp-Be9eU8mu.d.ts +0 -41
package/dist/appId.js
CHANGED
|
@@ -9,18 +9,22 @@
|
|
|
9
9
|
* advertised by `sanity start` resolve to the same id. `sanity deploy` resolves
|
|
10
10
|
* its own id from the applications API.
|
|
11
11
|
*/ export async function buildAppId(app) {
|
|
12
|
-
const canonical = (interfaces)=>(interfaces ?? []).map((i)=>[
|
|
13
|
-
i.type,
|
|
14
|
-
i.name,
|
|
15
|
-
i.src
|
|
16
|
-
]).toSorted();
|
|
17
12
|
const shape = JSON.stringify({
|
|
18
|
-
config: app.config ?? null,
|
|
19
13
|
entry: app.entry ?? null,
|
|
14
|
+
// Identity, not address: the id keys on `name` (which defaults to `slug`). The
|
|
15
|
+
// address (`slug`) is deliberately absent, so renaming it never shifts the id.
|
|
16
|
+
name: app.name,
|
|
20
17
|
organizationId: app.organizationId,
|
|
21
|
-
services:
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
services: app.webWorkers.map((webWorker)=>[
|
|
19
|
+
webWorker.type,
|
|
20
|
+
webWorker.name,
|
|
21
|
+
webWorker.src
|
|
22
|
+
]).toSorted(),
|
|
23
|
+
views: app.views.map((view)=>[
|
|
24
|
+
view.surface,
|
|
25
|
+
view.name,
|
|
26
|
+
view.src
|
|
27
|
+
]).toSorted()
|
|
24
28
|
});
|
|
25
29
|
// eslint-disable-next-line n/no-unsupported-features/node-builtins -- the Web Crypto global is available on our Node target and in the browser
|
|
26
30
|
const digest = await globalThis.crypto.subtle.digest('SHA-256', new TextEncoder().encode(shape));
|
package/dist/appId.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/appId.ts"],"sourcesContent":["import {type ResolvedWorkbenchApp} from './resolveWorkbenchApp.js'\n\n/**\n * File the build writes into its output, carrying the id compiled into the\n * bundle. `sanity start` serves a build without recompiling, so it reads this\n * instead of recomputing — a deploy inlines the API id, not the shape hash.\n */\nexport const SANITY_APP_ID_FILE = 'sanity-app-id.txt'\n\n/**\n * The `build`/`start` id — a hash of the app's declared shape (its identity, not\n * its code), so the bundle inlined by `sanity build` and the registry entry\n * advertised by `sanity start` resolve to the same id. `sanity deploy` resolves\n * its own id from the applications API.\n */\nexport async function buildAppId(app: ResolvedWorkbenchApp): Promise<string> {\n const
|
|
1
|
+
{"version":3,"sources":["../src/appId.ts"],"sourcesContent":["import {type ResolvedWorkbenchApp} from './resolveWorkbenchApp.js'\n\n/**\n * File the build writes into its output, carrying the id compiled into the\n * bundle. `sanity start` serves a build without recompiling, so it reads this\n * instead of recomputing — a deploy inlines the API id, not the shape hash.\n */\nexport const SANITY_APP_ID_FILE = 'sanity-app-id.txt'\n\n/**\n * The `build`/`start` id — a hash of the app's declared shape (its identity, not\n * its code), so the bundle inlined by `sanity build` and the registry entry\n * advertised by `sanity start` resolve to the same id. `sanity deploy` resolves\n * its own id from the applications API.\n */\nexport async function buildAppId(app: ResolvedWorkbenchApp): Promise<string> {\n const shape = JSON.stringify({\n entry: app.entry ?? null,\n // Identity, not address: the id keys on `name` (which defaults to `slug`). The\n // address (`slug`) is deliberately absent, so renaming it never shifts the id.\n name: app.name,\n organizationId: app.organizationId,\n services: app.webWorkers\n .map((webWorker): [string, string, string] => [webWorker.type, webWorker.name, webWorker.src])\n .toSorted(),\n views: app.views\n .map((view): [string, string, string] => [view.surface, view.name, view.src])\n .toSorted(),\n })\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(shape))\n return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, '0')).join('')\n}\n"],"names":["SANITY_APP_ID_FILE","buildAppId","app","shape","JSON","stringify","entry","name","organizationId","services","webWorkers","map","webWorker","type","src","toSorted","views","view","surface","digest","globalThis","crypto","subtle","TextEncoder","encode","Array","from","Uint8Array","byte","toString","padStart","join"],"mappings":"AAEA;;;;CAIC,GACD,OAAO,MAAMA,qBAAqB,oBAAmB;AAErD;;;;;CAKC,GACD,OAAO,eAAeC,WAAWC,GAAyB;IACxD,MAAMC,QAAQC,KAAKC,SAAS,CAAC;QAC3BC,OAAOJ,IAAII,KAAK,IAAI;QACpB,+EAA+E;QAC/E,+EAA+E;QAC/EC,MAAML,IAAIK,IAAI;QACdC,gBAAgBN,IAAIM,cAAc;QAClCC,UAAUP,IAAIQ,UAAU,CACrBC,GAAG,CAAC,CAACC,YAAwC;gBAACA,UAAUC,IAAI;gBAAED,UAAUL,IAAI;gBAAEK,UAAUE,GAAG;aAAC,EAC5FC,QAAQ;QACXC,OAAOd,IAAIc,KAAK,CACbL,GAAG,CAAC,CAACM,OAAmC;gBAACA,KAAKC,OAAO;gBAAED,KAAKV,IAAI;gBAAEU,KAAKH,GAAG;aAAC,EAC3EC,QAAQ;IACb;IACA,+IAA+I;IAC/I,MAAMI,SAAS,MAAMC,WAAWC,MAAM,CAACC,MAAM,CAACH,MAAM,CAAC,WAAW,IAAII,cAAcC,MAAM,CAACrB;IACzF,OAAOsB,MAAMC,IAAI,CAAC,IAAIC,WAAWR,SAAS,CAACS,OAASA,KAAKC,QAAQ,CAAC,IAAIC,QAAQ,CAAC,GAAG,MAAMC,IAAI,CAAC;AAC/F"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The qualified, globally-unique handle for an application: `sanity/<name>` for
|
|
3
|
+
* singletons (always Sanity-owned), `<organizationId>/<name>` otherwise. Mirrors
|
|
4
|
+
* brett's server-side composition so a locally served app carries the same
|
|
5
|
+
* reference the deployed one would — the CLI is the authority for local apps,
|
|
6
|
+
* which never reach brett.
|
|
7
|
+
* @public
|
|
8
|
+
*/ export function applicationReference(app) {
|
|
9
|
+
return `${app.isSingleton ? 'sanity' : app.organizationId}/${app.name}`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=applicationReference.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/applicationReference.ts"],"sourcesContent":["/**\n * The qualified, globally-unique handle for an application: `sanity/<name>` for\n * singletons (always Sanity-owned), `<organizationId>/<name>` otherwise. Mirrors\n * brett's server-side composition so a locally served app carries the same\n * reference the deployed one would — the CLI is the authority for local apps,\n * which never reach brett.\n * @public\n */\nexport function applicationReference(app: {\n isSingleton: boolean\n name: string\n organizationId: string\n}): string {\n return `${app.isSingleton ? 'sanity' : app.organizationId}/${app.name}`\n}\n"],"names":["applicationReference","app","isSingleton","organizationId","name"],"mappings":"AAAA;;;;;;;CAOC,GACD,OAAO,SAASA,qBAAqBC,GAIpC;IACC,OAAO,GAAGA,IAAIC,WAAW,GAAG,WAAWD,IAAIE,cAAc,CAAC,CAAC,EAAEF,IAAIG,IAAI,EAAE;AACzE"}
|
package/dist/contract.js
CHANGED
|
@@ -5,11 +5,8 @@ import { z } from 'zod/mini';
|
|
|
5
5
|
/** @internal */ export const VIEW_CONTRACT_VERSION = 1;
|
|
6
6
|
/** @internal */ export const SERVICE_CONTRACT_VERSION = 1;
|
|
7
7
|
/** @internal */ export const MEDIA_LIBRARY_CONFIG_CONTRACT_VERSION = 1;
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
* for {@link InterfaceType} and the build; add a type by registering it here.
|
|
11
|
-
* @internal
|
|
12
|
-
*/ export const VIEW_COMPONENTS = {
|
|
8
|
+
/** Component slots per view surface; windows load outside the component artifact path. @internal */ export const VIEW_COMPONENTS = {
|
|
9
|
+
app: [],
|
|
13
10
|
asset_source: [
|
|
14
11
|
'asset_source'
|
|
15
12
|
],
|
|
@@ -32,22 +29,25 @@ import { z } from 'zod/mini';
|
|
|
32
29
|
'large',
|
|
33
30
|
'banner'
|
|
34
31
|
]);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
const DockGroupSchema = z.enum([
|
|
33
|
+
'dock.system',
|
|
34
|
+
'dock.applications',
|
|
35
|
+
'dock.user'
|
|
36
|
+
]);
|
|
37
|
+
/** @internal */ export const DockSchema = z.object({
|
|
38
|
+
group: z.optional(DockGroupSchema),
|
|
39
|
+
order: z.optional(z.number())
|
|
40
|
+
});
|
|
41
|
+
/** @internal */ export const ViewPlacementMetadataSchema = z.object({
|
|
42
|
+
dock: DockSchema
|
|
42
43
|
});
|
|
43
44
|
/**
|
|
44
|
-
* A tile's interface metadata: its footprint `size` and an optional `
|
|
45
|
+
* A tile's interface metadata: its footprint `size` and an optional `order`
|
|
45
46
|
* the dashboard sorts on, ascending. Both are authored as top-level view fields
|
|
46
47
|
* (see {@link InterfaceDeclarationSchema}) but stored on the record as metadata.
|
|
47
|
-
* Mirrors `app`'s dock metadata; tile is the first view type to carry any.
|
|
48
48
|
* @internal
|
|
49
49
|
*/ export const TileInterfaceMetadataSchema = z.object({
|
|
50
|
-
|
|
50
|
+
order: z.optional(z.number()),
|
|
51
51
|
size: TileSizeSchema
|
|
52
52
|
});
|
|
53
53
|
/**
|
|
@@ -61,16 +61,16 @@ import { z } from 'zod/mini';
|
|
|
61
61
|
tile: VIEW_CONTRACT_VERSION,
|
|
62
62
|
worker: SERVICE_CONTRACT_VERSION
|
|
63
63
|
};
|
|
64
|
-
/** @internal */ export function interfaceContractVersion(
|
|
65
|
-
const version = INTERFACE_CONTRACT_VERSIONS[
|
|
64
|
+
/** @internal */ export function interfaceContractVersion(kind) {
|
|
65
|
+
const version = INTERFACE_CONTRACT_VERSIONS[kind];
|
|
66
66
|
return version === undefined ? undefined : String(version);
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
69
69
|
* The module-federation id a build exposes an interface at. Dev stamps the same
|
|
70
70
|
* id a deploy would, so the workbench loads a local interface like a deployed one.
|
|
71
71
|
* @internal
|
|
72
|
-
*/ export function interfaceModuleId(
|
|
73
|
-
switch(
|
|
72
|
+
*/ export function interfaceModuleId(kind, name) {
|
|
73
|
+
switch(kind){
|
|
74
74
|
case 'app':
|
|
75
75
|
{
|
|
76
76
|
return 'App';
|
|
@@ -87,7 +87,7 @@ import { z } from 'zod/mini';
|
|
|
87
87
|
}
|
|
88
88
|
default:
|
|
89
89
|
{
|
|
90
|
-
throw new Error(`Cannot derive a moduleId for unknown interface
|
|
90
|
+
throw new Error(`Cannot derive a moduleId for unknown interface kind: ${kind}`);
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
}
|
|
@@ -99,7 +99,7 @@ function extensionDeclarationFields(kind) {
|
|
|
99
99
|
src: z.string()
|
|
100
100
|
};
|
|
101
101
|
}
|
|
102
|
-
// Every interface
|
|
102
|
+
// Every interface shares `name` + `src` + a display `title`,
|
|
103
103
|
// which Brett requires on the record each becomes.
|
|
104
104
|
function interfaceDeclarationFields(kind) {
|
|
105
105
|
return {
|
|
@@ -108,30 +108,67 @@ function interfaceDeclarationFields(kind) {
|
|
|
108
108
|
};
|
|
109
109
|
}
|
|
110
110
|
const PanelViewSchema = z.object({
|
|
111
|
-
|
|
112
|
-
...interfaceDeclarationFields('View')
|
|
111
|
+
surface: z.literal('panel'),
|
|
112
|
+
...interfaceDeclarationFields('View'),
|
|
113
|
+
dock: z.optional(DockSchema)
|
|
114
|
+
});
|
|
115
|
+
/** @public */ export function definePanelView(view) {
|
|
116
|
+
return {
|
|
117
|
+
...view,
|
|
118
|
+
surface: 'panel'
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
const WindowViewSchema = z.object({
|
|
122
|
+
surface: z.literal('app'),
|
|
123
|
+
...interfaceDeclarationFields('View'),
|
|
124
|
+
dock: z.optional(DockSchema)
|
|
113
125
|
});
|
|
126
|
+
/** @public */ export function defineWindowView(view) {
|
|
127
|
+
return {
|
|
128
|
+
...view,
|
|
129
|
+
surface: 'app'
|
|
130
|
+
};
|
|
131
|
+
}
|
|
114
132
|
const AssetSourceViewSchema = z.object({
|
|
115
|
-
|
|
133
|
+
surface: z.literal('asset_source'),
|
|
116
134
|
...interfaceDeclarationFields('View')
|
|
117
135
|
});
|
|
136
|
+
/** @public */ export function defineAssetSourceView(view) {
|
|
137
|
+
return {
|
|
138
|
+
...view,
|
|
139
|
+
surface: 'asset_source'
|
|
140
|
+
};
|
|
141
|
+
}
|
|
118
142
|
const TileViewSchema = z.object({
|
|
119
|
-
|
|
143
|
+
surface: z.literal('tile'),
|
|
120
144
|
...interfaceDeclarationFields('View'),
|
|
121
|
-
/** Sort position within its layout track, ascending. Optional. */
|
|
145
|
+
/** Sort position within its layout track, ascending. Optional. */ order: z.optional(z.number()),
|
|
122
146
|
/** Footprint family the dashboard lays the tile out by. */ size: TileSizeSchema
|
|
123
147
|
});
|
|
124
|
-
/** @
|
|
148
|
+
/** @public */ export function defineTileView(view) {
|
|
149
|
+
return {
|
|
150
|
+
...view,
|
|
151
|
+
surface: 'tile'
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/** @internal */ export const InterfaceDeclarationSchema = z.discriminatedUnion('surface', [
|
|
155
|
+
WindowViewSchema,
|
|
125
156
|
PanelViewSchema,
|
|
126
157
|
AssetSourceViewSchema,
|
|
127
158
|
TileViewSchema
|
|
128
159
|
]);
|
|
129
|
-
const
|
|
160
|
+
const WebWorkerSchema = z.object({
|
|
130
161
|
type: z.literal('worker'),
|
|
131
|
-
...interfaceDeclarationFields('
|
|
162
|
+
...interfaceDeclarationFields('Web worker')
|
|
132
163
|
});
|
|
164
|
+
/** @public */ export function defineWebWorker(webWorker) {
|
|
165
|
+
return {
|
|
166
|
+
...webWorker,
|
|
167
|
+
type: 'worker'
|
|
168
|
+
};
|
|
169
|
+
}
|
|
133
170
|
/** @internal */ export const ServiceDeclarationSchema = z.discriminatedUnion('type', [
|
|
134
|
-
|
|
171
|
+
WebWorkerSchema
|
|
135
172
|
]);
|
|
136
173
|
const MediaLibraryFieldSchema = z.object({
|
|
137
174
|
...extensionDeclarationFields('Field'),
|
|
@@ -148,7 +185,8 @@ const MediaLibraryConfigSchema = z.object({
|
|
|
148
185
|
fields: z.array(MediaLibraryFieldSchema).check(z.refine((fields)=>new Set(fields.map((field)=>field.name)).size === fields.length, 'Field `name` must be unique within a media library'))
|
|
149
186
|
});
|
|
150
187
|
/**
|
|
151
|
-
*
|
|
188
|
+
* A workbench config's built value, keyed by `appType`; deploys as a versioned
|
|
189
|
+
* snapshot, not an interface.
|
|
152
190
|
* @internal
|
|
153
191
|
*/ export const ConfigSchema = z.discriminatedUnion('appType', [
|
|
154
192
|
MediaLibraryConfigSchema
|
package/dist/contract.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/contract.ts"],"sourcesContent":["import {z} from 'zod/mini'\n\n// Shared module-federation extension contract: interface (view/service) and\n// config declaration schemas, plus the versions the build stamps.\n// `zod/mini` keeps the bundle small.\n\n/** @internal */\nexport const VIEW_CONTRACT_VERSION = 1\n\n/** @internal */\nexport const SERVICE_CONTRACT_VERSION = 1\n\n/** @internal */\nexport const MEDIA_LIBRARY_CONFIG_CONTRACT_VERSION = 1\n\n/**\n * A view component. The return is opaque so the runtime helpers carry no React\n * dependency — the generated artifact renders it with the app's own React.\n * @public\n */\nexport type ViewComponent<TProps> = (props: TProps) => unknown\n\n/** @public */\nexport interface ViewComponentBaseProps<TView> {\n view: TView\n}\n\n/**\n * Component slots each interface type exposes, in render order. Source of truth\n * for {@link InterfaceType} and the build; add a type by registering it here.\n * @internal\n */\nexport const VIEW_COMPONENTS = {\n asset_source: ['asset_source'],\n panel: ['title', 'panel'],\n tile: ['tile'],\n} as const satisfies Record<string, readonly string[]>\n\n/** @public */\nexport type InterfaceType = keyof typeof VIEW_COMPONENTS\n\n/**\n * A tile's footprint family — the shape it occupies on the dashboard. Modelled\n * on iOS WidgetKit families, not a linear scale: `banner` is full-width and\n * shallow, which a `small`→`large` magnitude can't express. The host maps a\n * family to a layout slot; the component reads it to render per footprint.\n * @public\n */\nexport const TileSizeSchema = z.enum(['small', 'large', 'banner'])\n\n/** @public */\nexport type TileSize = z.infer<typeof TileSizeSchema>\n\n/** @public */\nexport type ServiceType = 'worker'\n\n/**\n * The `app` interface's dock-placement metadata. Interface metadata is\n * discriminated on `type`; `app` is the only type with a shape so far.\n * @internal\n */\nexport const AppInterfaceMetadataSchema = z.object({\n group: z.optional(z.string()),\n priority: z.optional(z.number()),\n})\n\n/** @internal */\nexport type AppInterfaceMetadata = z.infer<typeof AppInterfaceMetadataSchema>\n\n/**\n * A tile's interface metadata: its footprint `size` and an optional `priority`\n * the dashboard sorts on, ascending. Both are authored as top-level view fields\n * (see {@link InterfaceDeclarationSchema}) but stored on the record as metadata.\n * Mirrors `app`'s dock metadata; tile is the first view type to carry any.\n * @internal\n */\nexport const TileInterfaceMetadataSchema = z.object({\n priority: z.optional(z.number()),\n size: TileSizeSchema,\n})\n\n/** @internal */\nexport type TileInterfaceMetadata = z.infer<typeof TileInterfaceMetadataSchema>\n\n/**\n * The contract version each interface type advertises, so the host can check it\n * renders/runs what it expects.\n * @internal\n */\nconst INTERFACE_CONTRACT_VERSIONS = {\n app: undefined,\n asset_source: VIEW_CONTRACT_VERSION,\n panel: VIEW_CONTRACT_VERSION,\n tile: VIEW_CONTRACT_VERSION,\n worker: SERVICE_CONTRACT_VERSION,\n} as const\n\n/** Every interface type an app exposes — an `app` view, a view, or a service. */\nexport type InterfaceKind = keyof typeof INTERFACE_CONTRACT_VERSIONS\n\n/** @internal */\nexport function interfaceContractVersion(type: InterfaceKind): string | undefined {\n const version = INTERFACE_CONTRACT_VERSIONS[type]\n return version === undefined ? undefined : String(version)\n}\n\n/**\n * The module-federation id a build exposes an interface at. Dev stamps the same\n * id a deploy would, so the workbench loads a local interface like a deployed one.\n * @internal\n */\nexport function interfaceModuleId(type: string, name: string): string {\n switch (type) {\n case 'app': {\n return 'App'\n }\n case 'asset_source':\n case 'panel':\n case 'tile': {\n return `views/${name}`\n }\n case 'worker': {\n return `services/${name}`\n }\n default: {\n throw new Error(`Cannot derive a moduleId for unknown interface type: ${type}`)\n }\n }\n}\n\n// Shared `name` + `src`; `kind` only tailors the validation message.\nfunction extensionDeclarationFields(kind: 'Field' | 'Service' | 'View') {\n const pattern = /^[a-zA-Z0-9_-]+$/\n return {\n name: z.string().check(z.regex(pattern, `${kind} \\`name\\` must match ${pattern}`)),\n src: z.string(),\n }\n}\n\n// Every interface (view, service) shares `name` + `src` + a display `title`,\n// which Brett requires on the record each becomes.\nfunction interfaceDeclarationFields(kind: 'Service' | 'View') {\n return {\n ...extensionDeclarationFields(kind),\n title: z.string(`${kind} \\`title\\` is required`),\n }\n}\n\nconst PanelViewSchema = z.object({\n type: z.literal('panel'),\n ...interfaceDeclarationFields('View'),\n})\n\nconst AssetSourceViewSchema = z.object({\n type: z.literal('asset_source'),\n ...interfaceDeclarationFields('View'),\n})\n\nconst TileViewSchema = z.object({\n type: z.literal('tile'),\n ...interfaceDeclarationFields('View'),\n /** Sort position within its layout track, ascending. Optional. */\n priority: z.optional(z.number()),\n /** Footprint family the dashboard lays the tile out by. */\n size: TileSizeSchema,\n})\n\n/** @internal */\nexport const InterfaceDeclarationSchema = z.discriminatedUnion('type', [\n PanelViewSchema,\n AssetSourceViewSchema,\n TileViewSchema,\n])\n\nconst WorkerServiceSchema = z.object({\n type: z.literal('worker'),\n ...interfaceDeclarationFields('Service'),\n})\n\n/** @internal */\nexport const ServiceDeclarationSchema = z.discriminatedUnion('type', [WorkerServiceSchema])\n\nconst MediaLibraryFieldSchema = z.object({\n ...extensionDeclarationFields('Field'),\n public: z.optional(z.boolean()),\n title: z.string(),\n})\n\n/**\n * Stamped where the config crosses a boundary so the authoring model doesn't carry a constant discriminator.\n * @internal\n */\nexport const INSTALLATION_CONFIG_TYPE = 'installation_config'\n\n// `appType` is stamped by `unstable_defineMediaLibrary`, never authored.\nconst MediaLibraryConfigSchema = z.object({\n appType: z.literal('media-library'),\n fields: z\n .array(MediaLibraryFieldSchema)\n .check(\n z.refine(\n (fields) => new Set(fields.map((field) => field.name)).size === fields.length,\n 'Field `name` must be unique within a media library',\n ),\n ),\n})\n\n/**\n * An app's optional config, keyed by `appType`; deploys as a versioned snapshot, not an interface.\n * @internal\n */\nexport const ConfigSchema = z.discriminatedUnion('appType', [MediaLibraryConfigSchema])\n"],"names":["z","VIEW_CONTRACT_VERSION","SERVICE_CONTRACT_VERSION","MEDIA_LIBRARY_CONFIG_CONTRACT_VERSION","VIEW_COMPONENTS","asset_source","panel","tile","TileSizeSchema","enum","AppInterfaceMetadataSchema","object","group","optional","string","priority","number","TileInterfaceMetadataSchema","size","INTERFACE_CONTRACT_VERSIONS","app","undefined","worker","interfaceContractVersion","type","version","String","interfaceModuleId","name","Error","extensionDeclarationFields","kind","pattern","check","regex","src","interfaceDeclarationFields","title","PanelViewSchema","literal","AssetSourceViewSchema","TileViewSchema","InterfaceDeclarationSchema","discriminatedUnion","WorkerServiceSchema","ServiceDeclarationSchema","MediaLibraryFieldSchema","public","boolean","INSTALLATION_CONFIG_TYPE","MediaLibraryConfigSchema","appType","fields","array","refine","Set","map","field","length","ConfigSchema"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/contract.ts"],"sourcesContent":["import {z} from 'zod/mini'\n\n// Shared module-federation extension contract: interface (view/service) and\n// config declaration schemas, plus the versions the build stamps.\n// `zod/mini` keeps the bundle small.\n\n/** @internal */\nexport const VIEW_CONTRACT_VERSION = 1\n\n/** @internal */\nexport const SERVICE_CONTRACT_VERSION = 1\n\n/** @internal */\nexport const MEDIA_LIBRARY_CONFIG_CONTRACT_VERSION = 1\n\n/**\n * A view component. The return is opaque so the runtime helpers carry no React\n * dependency — the generated artifact renders it with the app's own React.\n * @public\n */\nexport type ViewComponent<TProps> = (props: TProps) => unknown\n\n/** @public */\nexport interface ViewComponentBaseProps<TView> {\n view: TView\n}\n\n/** Component slots per view surface; windows load outside the component artifact path. @internal */\nexport const VIEW_COMPONENTS = {\n app: [],\n asset_source: ['asset_source'],\n panel: ['title', 'panel'],\n tile: ['tile'],\n} as const satisfies Record<string, readonly string[]>\n\n/** @public */\nexport type ViewSurface = keyof typeof VIEW_COMPONENTS\n\n/**\n * A tile's footprint family — the shape it occupies on the dashboard. Modelled\n * on iOS WidgetKit families, not a linear scale: `banner` is full-width and\n * shallow, which a `small`→`large` magnitude can't express. The host maps a\n * family to a layout slot; the component reads it to render per footprint.\n * @public\n */\nexport const TileSizeSchema = z.enum(['small', 'large', 'banner'])\n\n/** @public */\nexport type TileSize = z.infer<typeof TileSizeSchema>\n\n/** @public */\nexport type ServiceType = 'worker'\n\nconst DockGroupSchema = z.enum(['dock.system', 'dock.applications', 'dock.user'])\n\n/** @public */\nexport type DockGroup = z.output<typeof DockGroupSchema>\n\n/** @internal */\nexport const DockSchema = z.object({\n group: z.optional(DockGroupSchema),\n order: z.optional(z.number()),\n})\n\n/** @internal */\nexport type Dock = z.infer<typeof DockSchema>\n\n/** @internal */\nexport const ViewPlacementMetadataSchema = z.object({dock: DockSchema})\n\n/** @internal */\nexport type ViewPlacementMetadata = z.infer<typeof ViewPlacementMetadataSchema>\n\n/**\n * A tile's interface metadata: its footprint `size` and an optional `order`\n * the dashboard sorts on, ascending. Both are authored as top-level view fields\n * (see {@link InterfaceDeclarationSchema}) but stored on the record as metadata.\n * @internal\n */\nexport const TileInterfaceMetadataSchema = z.object({\n order: z.optional(z.number()),\n size: TileSizeSchema,\n})\n\n/** @internal */\nexport type TileInterfaceMetadata = z.infer<typeof TileInterfaceMetadataSchema>\n\n/**\n * The contract version each interface type advertises, so the host can check it\n * renders/runs what it expects.\n * @internal\n */\nconst INTERFACE_CONTRACT_VERSIONS = {\n app: undefined,\n asset_source: VIEW_CONTRACT_VERSION,\n panel: VIEW_CONTRACT_VERSION,\n tile: VIEW_CONTRACT_VERSION,\n worker: SERVICE_CONTRACT_VERSION,\n} as const\n\n/** Every interface type an app exposes — an `app` view, a view, or a service. */\nexport type InterfaceKind = keyof typeof INTERFACE_CONTRACT_VERSIONS\n\n/** @internal */\nexport function interfaceContractVersion(kind: InterfaceKind): string | undefined {\n const version = INTERFACE_CONTRACT_VERSIONS[kind]\n return version === undefined ? undefined : String(version)\n}\n\n/**\n * The module-federation id a build exposes an interface at. Dev stamps the same\n * id a deploy would, so the workbench loads a local interface like a deployed one.\n * @internal\n */\nexport function interfaceModuleId(kind: string, name: string): string {\n switch (kind) {\n case 'app': {\n return 'App'\n }\n case 'asset_source':\n case 'panel':\n case 'tile': {\n return `views/${name}`\n }\n case 'worker': {\n return `services/${name}`\n }\n default: {\n throw new Error(`Cannot derive a moduleId for unknown interface kind: ${kind}`)\n }\n }\n}\n\n// Shared `name` + `src`; `kind` only tailors the validation message.\nfunction extensionDeclarationFields(kind: 'Field' | 'View' | 'Web worker') {\n const pattern = /^[a-zA-Z0-9_-]+$/\n return {\n name: z.string().check(z.regex(pattern, `${kind} \\`name\\` must match ${pattern}`)),\n src: z.string(),\n }\n}\n\n// Every interface shares `name` + `src` + a display `title`,\n// which Brett requires on the record each becomes.\nfunction interfaceDeclarationFields(kind: 'View' | 'Web worker') {\n return {\n ...extensionDeclarationFields(kind),\n title: z.string(`${kind} \\`title\\` is required`),\n }\n}\n\nconst PanelViewSchema = z.object({\n surface: z.literal('panel'),\n ...interfaceDeclarationFields('View'),\n dock: z.optional(DockSchema),\n})\n\n/** @public */\nexport type PanelView = z.output<typeof PanelViewSchema>\n\n/** @public */\nexport type DefinePanelViewInput = Omit<PanelView, 'surface'>\n\n/** @public */\nexport function definePanelView(view: DefinePanelViewInput): PanelView {\n return {...view, surface: 'panel'}\n}\n\nconst WindowViewSchema = z.object({\n surface: z.literal('app'),\n ...interfaceDeclarationFields('View'),\n dock: z.optional(DockSchema),\n})\n\n/** @public */\nexport type WindowView = z.output<typeof WindowViewSchema>\n\n/** @public */\nexport type DefineWindowViewInput = Omit<WindowView, 'surface'>\n\n/** @public */\nexport function defineWindowView(view: DefineWindowViewInput): WindowView {\n return {...view, surface: 'app'}\n}\n\nconst AssetSourceViewSchema = z.object({\n surface: z.literal('asset_source'),\n ...interfaceDeclarationFields('View'),\n})\n\n/** @public */\nexport type AssetSourceView = z.output<typeof AssetSourceViewSchema>\n\n/** @public */\nexport type DefineAssetSourceViewInput = Omit<AssetSourceView, 'surface'>\n\n/** @public */\nexport function defineAssetSourceView(view: DefineAssetSourceViewInput): AssetSourceView {\n return {...view, surface: 'asset_source'}\n}\n\nconst TileViewSchema = z.object({\n surface: z.literal('tile'),\n ...interfaceDeclarationFields('View'),\n /** Sort position within its layout track, ascending. Optional. */\n order: z.optional(z.number()),\n /** Footprint family the dashboard lays the tile out by. */\n size: TileSizeSchema,\n})\n\n/** @public */\nexport type TileView = z.output<typeof TileViewSchema>\n\n/** @public */\nexport type DefineTileViewInput = Omit<TileView, 'surface'>\n\n/** @public */\nexport function defineTileView(view: DefineTileViewInput): TileView {\n return {...view, surface: 'tile'}\n}\n\n/** @internal */\nexport const InterfaceDeclarationSchema = z.discriminatedUnion('surface', [\n WindowViewSchema,\n PanelViewSchema,\n AssetSourceViewSchema,\n TileViewSchema,\n])\n\n/** @public */\nexport type ViewDeclaration = z.output<typeof InterfaceDeclarationSchema>\n\nconst WebWorkerSchema = z.object({\n type: z.literal('worker'),\n ...interfaceDeclarationFields('Web worker'),\n})\n\n/** @public */\nexport type WebWorker = z.output<typeof WebWorkerSchema>\n\n/** @public */\nexport type DefineWebWorkerInput = Omit<WebWorker, 'type'>\n\n/** @public */\nexport function defineWebWorker(webWorker: DefineWebWorkerInput): WebWorker {\n return {...webWorker, type: 'worker'}\n}\n\n/** @internal */\nexport const ServiceDeclarationSchema = z.discriminatedUnion('type', [WebWorkerSchema])\n\nconst MediaLibraryFieldSchema = z.object({\n ...extensionDeclarationFields('Field'),\n public: z.optional(z.boolean()),\n title: z.string(),\n})\n\n/**\n * Stamped where the config crosses a boundary so the authoring model doesn't carry a constant discriminator.\n * @internal\n */\nexport const INSTALLATION_CONFIG_TYPE = 'installation_config'\n\n// `appType` is stamped by `unstable_defineMediaLibrary`, never authored.\nconst MediaLibraryConfigSchema = z.object({\n appType: z.literal('media-library'),\n fields: z\n .array(MediaLibraryFieldSchema)\n .check(\n z.refine(\n (fields) => new Set(fields.map((field) => field.name)).size === fields.length,\n 'Field `name` must be unique within a media library',\n ),\n ),\n})\n\n/**\n * A workbench config's built value, keyed by `appType`; deploys as a versioned\n * snapshot, not an interface.\n * @internal\n */\nexport const ConfigSchema = z.discriminatedUnion('appType', [MediaLibraryConfigSchema])\n\n/**\n * The `{appType, fields}` config value the build expands into a federation\n * remote and the deploy summarizes.\n * @internal\n */\nexport type WorkbenchConfigValue = z.output<typeof ConfigSchema>\n"],"names":["z","VIEW_CONTRACT_VERSION","SERVICE_CONTRACT_VERSION","MEDIA_LIBRARY_CONFIG_CONTRACT_VERSION","VIEW_COMPONENTS","app","asset_source","panel","tile","TileSizeSchema","enum","DockGroupSchema","DockSchema","object","group","optional","order","number","ViewPlacementMetadataSchema","dock","TileInterfaceMetadataSchema","size","INTERFACE_CONTRACT_VERSIONS","undefined","worker","interfaceContractVersion","kind","version","String","interfaceModuleId","name","Error","extensionDeclarationFields","pattern","string","check","regex","src","interfaceDeclarationFields","title","PanelViewSchema","surface","literal","definePanelView","view","WindowViewSchema","defineWindowView","AssetSourceViewSchema","defineAssetSourceView","TileViewSchema","defineTileView","InterfaceDeclarationSchema","discriminatedUnion","WebWorkerSchema","type","defineWebWorker","webWorker","ServiceDeclarationSchema","MediaLibraryFieldSchema","public","boolean","INSTALLATION_CONFIG_TYPE","MediaLibraryConfigSchema","appType","fields","array","refine","Set","map","field","length","ConfigSchema"],"mappings":"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"}
|
package/dist/defineApp.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod/mini';
|
|
2
2
|
import { APP_SLUG_PATTERN } from './appSlug.js';
|
|
3
|
-
import {
|
|
3
|
+
import { DockSchema, InterfaceDeclarationSchema, ServiceDeclarationSchema } from './contract.js';
|
|
4
4
|
/**
|
|
5
5
|
* Dashboard visibility values. Mirrors `APP_VISIBILITIES` in `@sanity/cli-core`
|
|
6
6
|
* (which can't be imported here — pulling the barrel into this lean module bloats
|
|
@@ -17,16 +17,10 @@ import { ConfigSchema, InterfaceDeclarationSchema, ServiceDeclarationSchema } fr
|
|
|
17
17
|
'coreApp',
|
|
18
18
|
'studio',
|
|
19
19
|
'canvas',
|
|
20
|
-
'dashboard'
|
|
21
|
-
'media-library'
|
|
22
|
-
]);
|
|
23
|
-
/** Dock groups an app can place itself into. */ const DockGroupSchema = z.enum([
|
|
24
|
-
'dock.system',
|
|
25
|
-
'dock.applications',
|
|
26
|
-
'dock.user'
|
|
20
|
+
'dashboard'
|
|
27
21
|
]);
|
|
28
22
|
/**
|
|
29
|
-
* Runtime-validation schema for `
|
|
23
|
+
* Runtime-validation schema for `defineApplication`.
|
|
30
24
|
* @internal
|
|
31
25
|
*/ export const DefineAppInputSchema = z.object({
|
|
32
26
|
/**
|
|
@@ -34,31 +28,34 @@ import { ConfigSchema, InterfaceDeclarationSchema, ServiceDeclarationSchema } fr
|
|
|
34
28
|
* from the public `DefineAppInput` type.
|
|
35
29
|
* @internal
|
|
36
30
|
*/ applicationType: z.optional(ApplicationType),
|
|
37
|
-
/**
|
|
38
|
-
* Deployed as a versioned snapshot on the app's org installation, not the
|
|
39
|
-
* application service. Singletons only. Internal, so excluded from the public
|
|
40
|
-
* `DefineAppInput` and set via `@ts-expect-error` like `applicationType`.
|
|
41
|
-
* @internal
|
|
42
|
-
*/ config: z.optional(ConfigSchema),
|
|
31
|
+
/** Default placement inherited by panel and window views. */ dock: z.optional(DockSchema),
|
|
43
32
|
/**
|
|
44
33
|
* App entrypoint module. Defaults to `./src/App.tsx` when omitted. The build
|
|
45
34
|
* derives the app's navigable `app` view from it. SDK apps only — setting it
|
|
46
35
|
* on a studio is rejected (studio app views are not yet implemented).
|
|
47
36
|
*/ entry: z.optional(z.string("must be a path to the app's entry file")),
|
|
48
|
-
/** Dock group to render in. Defaults to `dock.applications` when omitted. */ group: z.optional(DockGroupSchema),
|
|
49
37
|
/** Optional icon override (path to an SVG). Wins over manifest/studio icon. */ icon: z.optional(z.string()),
|
|
50
38
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
/** Background services the app runs (e.g. a `worker` emitting dock badges). */ services: z.optional(z.array(ServiceDeclarationSchema, 'must be an array of services').check(z.refine((services)=>new Set(services.map((service)=>service.name)).size === services.length, 'Service `name` must be unique within an app'))),
|
|
39
|
+
* Stable identity, distinct from the `slug` address. Defaults to `slug` when
|
|
40
|
+
* omitted. Identity keys — the build id and derived interface ids — are built
|
|
41
|
+
* from this, so renaming the slug no longer changes identity.
|
|
42
|
+
*/ name: z.optional(z.string().check(z.regex(APP_SLUG_PATTERN, 'App `name` must be lowercase alphanumerics and hyphens, starting with a letter and ending with an alphanumeric'))),
|
|
43
|
+
/** Organization that owns the app — the workbench runs and deploys against it. */ organizationId: z.string("App `organizationId` is required — pass the owning organization's ID to `defineApplication`"),
|
|
57
44
|
slug: z.string('App `slug` is required — the hostname the application is created at on deploy').check(z.regex(APP_SLUG_PATTERN, 'App `slug` must be lowercase alphanumerics and hyphens, starting with a letter and ending with an alphanumeric')),
|
|
58
45
|
/** User-facing app title. Wins over studio.config.ts title on merge. */ title: z.string(),
|
|
59
|
-
/** Views the app exposes (e.g. dock panels). */ views: z.optional(z.array(InterfaceDeclarationSchema, 'must be an array of
|
|
60
|
-
/** Dashboard visibility of the app. Defaults to `default` when omitted. */ visibility: z.optional(z.enum(APP_VISIBILITIES))
|
|
61
|
-
|
|
46
|
+
/** Views the app exposes (e.g. a window, dock panels, and tiles). */ views: z.optional(z.array(InterfaceDeclarationSchema, 'must be an array of views')),
|
|
47
|
+
/** Dashboard visibility of the app. Defaults to `default` when omitted. */ visibility: z.optional(z.enum(APP_VISIBILITIES)),
|
|
48
|
+
/** Background web workers the app runs. */ webWorkers: z.optional(z.array(ServiceDeclarationSchema, 'must be an array of web workers'))
|
|
49
|
+
}).check(z.refine((input)=>{
|
|
50
|
+
const names = [
|
|
51
|
+
...input.entry === undefined ? [] : [
|
|
52
|
+
input.name ?? input.slug
|
|
53
|
+
],
|
|
54
|
+
...(input.views ?? []).map((view)=>view.name),
|
|
55
|
+
...(input.webWorkers ?? []).map((webWorker)=>webWorker.name)
|
|
56
|
+
];
|
|
57
|
+
return new Set(names).size === names.length;
|
|
58
|
+
}, '`name` must be unique across views and web workers. Rename one of the duplicates.'), // Studio app views are not implemented yet. A studio that declares `entry`
|
|
62
59
|
// (the SDK app-view entrypoint) is rejected here rather than silently
|
|
63
60
|
// generating one; studios keep navigating via their existing render path.
|
|
64
61
|
z.refine((input)=>!(input.applicationType === 'studio' && input.entry !== undefined), {
|
|
@@ -66,14 +63,6 @@ z.refine((input)=>!(input.applicationType === 'studio' && input.entry !== undefi
|
|
|
66
63
|
path: [
|
|
67
64
|
'entry'
|
|
68
65
|
]
|
|
69
|
-
})).check(// An config belongs to a Sanity-owned singleton (the Media
|
|
70
|
-
// Library). A non-singleton declaring one is rejected — see
|
|
71
|
-
// {@link readConfig} for the runtime guard.
|
|
72
|
-
z.refine((input)=>!(input.config && !input.isSingleton), {
|
|
73
|
-
error: '`config` is only supported for singleton apps',
|
|
74
|
-
path: [
|
|
75
|
-
'config'
|
|
76
|
-
]
|
|
77
66
|
}));
|
|
78
67
|
/**
|
|
79
68
|
* Nominal brand the CLI discriminates on to enable the workbench build/deploy
|
|
@@ -82,31 +71,19 @@ z.refine((input)=>!(input.config && !input.isSingleton), {
|
|
|
82
71
|
* `Symbol.for` rather than importing it, so it stays internal to this module.
|
|
83
72
|
*/ const WORKBENCH_APP = Symbol.for('sanity.workbench.defineApp');
|
|
84
73
|
/**
|
|
85
|
-
* Whether `app` is a branded `
|
|
74
|
+
* Whether `app` is a branded `defineApplication(...)` result — the sole
|
|
86
75
|
* workbench opt-in.
|
|
87
76
|
* @public
|
|
88
77
|
*/ export function isWorkbenchApp(app) {
|
|
89
78
|
return typeof app === 'object' && app !== null && WORKBENCH_APP in app;
|
|
90
79
|
}
|
|
91
|
-
/**
|
|
92
|
-
* The app's config, or `undefined` when it declares none. Throws
|
|
93
|
-
* when a non-singleton declares one — configs belong to Sanity-owned singletons,
|
|
94
|
-
* so build/dev/deploy all read it through here to reject the combination
|
|
95
|
-
* consistently.
|
|
96
|
-
* @internal
|
|
97
|
-
*/ export function readConfig(app) {
|
|
98
|
-
if (app.config && !app.isSingleton) {
|
|
99
|
-
throw new Error('`config` is only supported for singleton apps');
|
|
100
|
-
}
|
|
101
|
-
return app.config;
|
|
102
|
-
}
|
|
103
80
|
/**
|
|
104
81
|
* Declare a Sanity Workbench application. Identity at runtime — returns the same
|
|
105
82
|
* object reference, tagged with the workbench brand. Field validation (the
|
|
106
83
|
* `slug` pattern etc.) runs at build time in the CLI via `DefineAppInputSchema`;
|
|
107
84
|
* this helper stays a thin, pure identity wrapper.
|
|
108
85
|
* @public
|
|
109
|
-
*/ export function
|
|
86
|
+
*/ export function defineApplication(input) {
|
|
110
87
|
return Object.defineProperty(input, WORKBENCH_APP, {
|
|
111
88
|
configurable: false,
|
|
112
89
|
enumerable: false,
|
|
@@ -115,20 +92,36 @@ z.refine((input)=>!(input.config && !input.isSingleton), {
|
|
|
115
92
|
});
|
|
116
93
|
}
|
|
117
94
|
/**
|
|
118
|
-
*
|
|
95
|
+
* Nominal brand the CLI discriminates a config on. A config is *not* an app: it
|
|
96
|
+
* carries no `slug`/`title`/application identity, only a target `appType`, its
|
|
97
|
+
* owning `organizationId`, and its `fields`. Registered via `Symbol.for` so the
|
|
98
|
+
* marker survives module-realm boundaries — `@sanity/cli-core` re-derives the
|
|
99
|
+
* same global symbol rather than importing it.
|
|
100
|
+
*/ const WORKBENCH_CONFIG = Symbol.for('sanity.workbench.defineConfig');
|
|
101
|
+
/**
|
|
102
|
+
* Whether `app` is a branded `unstable_defineMediaLibrary(...)` config — a
|
|
103
|
+
* config-carrier rather than an app. Configs live in `cliConfig.app` alongside
|
|
104
|
+
* apps but resolve through `resolveWorkbenchConfig`, not `resolveWorkbenchApp`.
|
|
105
|
+
* @public
|
|
106
|
+
*/ export function isWorkbenchConfig(app) {
|
|
107
|
+
return typeof app === 'object' && app !== null && WORKBENCH_CONFIG in app;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Declare the Sanity Media Library config. The Media Library is a Sanity-owned
|
|
111
|
+
* singleton, so this is not an app — it carries no slug or title, only the
|
|
112
|
+
* target `appType`, its owning organization, and the `fields` it contributes to
|
|
113
|
+
* the installation's config.
|
|
119
114
|
* @public
|
|
120
115
|
*/ export function unstable_defineMediaLibrary(input) {
|
|
121
|
-
return
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
slug: 'media-library',
|
|
131
|
-
title: 'Media Library'
|
|
116
|
+
return Object.defineProperty({
|
|
117
|
+
appType: 'media-library',
|
|
118
|
+
fields: input.fields ?? [],
|
|
119
|
+
organizationId: input.organizationId
|
|
120
|
+
}, WORKBENCH_CONFIG, {
|
|
121
|
+
configurable: false,
|
|
122
|
+
enumerable: false,
|
|
123
|
+
value: true,
|
|
124
|
+
writable: false
|
|
132
125
|
});
|
|
133
126
|
}
|
|
134
127
|
|
package/dist/defineApp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/defineApp.ts"],"sourcesContent":["import {z} from 'zod/mini'\n\nimport {APP_SLUG_PATTERN} from './appSlug.js'\nimport {ConfigSchema, InterfaceDeclarationSchema, ServiceDeclarationSchema} from './contract.js'\n\n/**\n * Dashboard visibility values. Mirrors `APP_VISIBILITIES` in `@sanity/cli-core`\n * (which can't be imported here — pulling the barrel into this lean module bloats\n * the config-load path). Kept in sync by a type test in `defineApp.test.ts`.\n */\nconst APP_VISIBILITIES = ['default', 'unlisted', 'disabled'] as const\n\n/**\n * Internal application discriminator. Sanity-owned singleton apps only;\n * validated by the schema but excluded from the public `DefineAppInput` type.\n */\nconst ApplicationType = z.enum(['coreApp', 'studio', 'canvas', 'dashboard', 'media-library'])\n\n/** Dock groups an app can place itself into. */\nconst DockGroupSchema = z.enum(['dock.system', 'dock.applications', 'dock.user'])\n\n/**\n * Dock group identifier. The API does not block a user app from declaring a\n * reserved group (e.g. `dock.system`); priority conventions keep Sanity-owned\n * apps ahead.\n * @public\n */\nexport type DockGroup = z.output<typeof DockGroupSchema>\n\n/**\n * Runtime-validation schema for `unstable_defineApp`.\n * @internal\n */\nexport const DefineAppInputSchema = z\n .object({\n /**\n * Internal — Sanity-owned singleton apps only. Validated here but excluded\n * from the public `DefineAppInput` type.\n * @internal\n */\n applicationType: z.optional(ApplicationType),\n /**\n * Deployed as a versioned snapshot on the app's org installation, not the\n * application service. Singletons only. Internal, so excluded from the public\n * `DefineAppInput` and set via `@ts-expect-error` like `applicationType`.\n * @internal\n */\n config: z.optional(ConfigSchema),\n /**\n * App entrypoint module. Defaults to `./src/App.tsx` when omitted. The build\n * derives the app's navigable `app` view from it. SDK apps only — setting it\n * on a studio is rejected (studio app views are not yet implemented).\n */\n entry: z.optional(z.string(\"must be a path to the app's entry file\")),\n /** Dock group to render in. Defaults to `dock.applications` when omitted. */\n group: z.optional(DockGroupSchema),\n /** Optional icon override (path to an SVG). Wins over manifest/studio icon. */\n icon: z.optional(z.string()),\n /**\n * Sanity-owned app deployed once, installed per org; excluded from the public `DefineAppInput`.\n * @internal\n */\n isSingleton: z.optional(z.boolean()),\n /** Organization that owns the app — the workbench runs and deploys against it. */\n organizationId: z.string(\n \"App `organizationId` is required — pass the owning organization's ID to `unstable_defineApp`\",\n ),\n /** Sort position within the group, ascending. Defaults to `100` when omitted. */\n priority: z.optional(z.number()),\n /** Background services the app runs (e.g. a `worker` emitting dock badges). */\n services: z.optional(\n z\n .array(ServiceDeclarationSchema, 'must be an array of services')\n .check(\n z.refine(\n (services) => new Set(services.map((service) => service.name)).size === services.length,\n 'Service `name` must be unique within an app',\n ),\n ),\n ),\n slug: z\n .string('App `slug` is required — the hostname the application is created at on deploy')\n .check(\n z.regex(\n APP_SLUG_PATTERN,\n 'App `slug` must be lowercase alphanumerics and hyphens, starting with a letter and ending with an alphanumeric',\n ),\n ),\n /** User-facing app title. Wins over studio.config.ts title on merge. */\n title: z.string(),\n /** Views the app exposes (e.g. dock panels). */\n views: z.optional(\n z\n .array(InterfaceDeclarationSchema, 'must be an array of panels')\n .check(\n z.refine(\n (views) => new Set(views.map((view) => view.name)).size === views.length,\n 'View `name` must be unique within an app',\n ),\n ),\n ),\n /** Dashboard visibility of the app. Defaults to `default` when omitted. */\n visibility: z.optional(z.enum(APP_VISIBILITIES)),\n })\n .check(\n // Studio app views are not implemented yet. A studio that declares `entry`\n // (the SDK app-view entrypoint) is rejected here rather than silently\n // generating one; studios keep navigating via their existing render path.\n z.refine((input) => !(input.applicationType === 'studio' && input.entry !== undefined), {\n error: 'App views for studios are not implemented yet',\n path: ['entry'],\n }),\n )\n .check(\n // An config belongs to a Sanity-owned singleton (the Media\n // Library). A non-singleton declaring one is rejected — see\n // {@link readConfig} for the runtime guard.\n z.refine((input) => !(input.config && !input.isSingleton), {\n error: '`config` is only supported for singleton apps',\n path: ['config'],\n }),\n )\n\n/**\n * User-facing input for `unstable_defineApp`. Excludes the internal\n * `applicationType`, `isSingleton`, and `config`.\n * @public\n */\nexport type DefineAppInput = Omit<\n z.output<typeof DefineAppInputSchema>,\n 'applicationType' | 'config' | 'isSingleton'\n>\n\n/**\n * Nominal brand the CLI discriminates on to enable the workbench build/deploy\n * codepath. Registered via `Symbol.for` so the marker survives module-realm\n * boundaries — `@sanity/cli-core` re-derives the same global symbol with\n * `Symbol.for` rather than importing it, so it stays internal to this module.\n */\nconst WORKBENCH_APP: unique symbol = Symbol.for('sanity.workbench.defineApp')\n\n/**\n * The branded result of `unstable_defineApp`. Carries the same fields as the\n * input plus the internal brand — users only ever see `DefineAppInput`.\n * @public\n */\nexport type DefineAppResult = DefineAppInput & {readonly [WORKBENCH_APP]: true}\n\n/**\n * A branded app as the CLI reads it — the full schema shape, including the\n * internal fields `DefineAppInput` omits. Schema-derived so the narrowing\n * can't drift from what the schema validates.\n * @public\n */\nexport type WorkbenchApp = DefineAppResult & z.output<typeof DefineAppInputSchema>\n\n/**\n * Whether `app` is a branded `unstable_defineApp(...)` result — the sole\n * workbench opt-in.\n * @public\n */\nexport function isWorkbenchApp(app: unknown): app is WorkbenchApp {\n return typeof app === 'object' && app !== null && WORKBENCH_APP in app\n}\n\n/**\n * The app's config, or `undefined` when it declares none. Throws\n * when a non-singleton declares one — configs belong to Sanity-owned singletons,\n * so build/dev/deploy all read it through here to reject the combination\n * consistently.\n * @internal\n */\nexport function readConfig(app: WorkbenchApp): WorkbenchApp['config'] | undefined {\n if (app.config && !app.isSingleton) {\n throw new Error('`config` is only supported for singleton apps')\n }\n return app.config\n}\n\n/**\n * Declare a Sanity Workbench application. Identity at runtime — returns the same\n * object reference, tagged with the workbench brand. Field validation (the\n * `slug` pattern etc.) runs at build time in the CLI via `DefineAppInputSchema`;\n * this helper stays a thin, pure identity wrapper.\n * @public\n */\nexport function unstable_defineApp(input: DefineAppInput): DefineAppResult {\n return Object.defineProperty(input, WORKBENCH_APP, {\n configurable: false,\n enumerable: false,\n value: true,\n writable: false,\n }) as DefineAppResult\n}\n\n/**\n * One custom field a media library exposes. `src` default-exports a `defineField(...)` schema type.\n * @public\n */\nexport interface MediaLibraryField {\n /** Unique within the media library. */\n name: string\n src: string\n title: string\n\n /** Readable outside the owning organization. */\n public?: boolean\n}\n\n/**\n * Sanity-owned singleton, so authors don't name or title the app — only `organizationId` is required.\n * @public\n */\nexport interface DefineMediaLibraryInput {\n /** Organization that owns the media library — the CLI runs and deploys against it. */\n organizationId: string\n\n fields?: MediaLibraryField[]\n}\n\n/**\n * Declare the Sanity Media Library as a workbench app — a singleton whose `fields` become its config.\n * @public\n */\nexport function unstable_defineMediaLibrary(input: DefineMediaLibraryInput): DefineAppResult {\n return unstable_defineApp({\n // @ts-expect-error -- `applicationType`/`isSingleton`/`config` are internal, excluded from `DefineAppInput`; Sanity-owned apps set them\n applicationType: 'media-library',\n config: input.fields?.length ? {appType: 'media-library', fields: input.fields} : undefined,\n isSingleton: true,\n organizationId: input.organizationId,\n slug: 'media-library',\n title: 'Media Library',\n })\n}\n"],"names":["z","APP_SLUG_PATTERN","ConfigSchema","InterfaceDeclarationSchema","ServiceDeclarationSchema","APP_VISIBILITIES","ApplicationType","enum","DockGroupSchema","DefineAppInputSchema","object","applicationType","optional","config","entry","string","group","icon","isSingleton","boolean","organizationId","priority","number","services","array","check","refine","Set","map","service","name","size","length","slug","regex","title","views","view","visibility","input","undefined","error","path","WORKBENCH_APP","Symbol","for","isWorkbenchApp","app","readConfig","Error","unstable_defineApp","Object","defineProperty","configurable","enumerable","value","writable","unstable_defineMediaLibrary","fields","appType"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/defineApp.ts"],"sourcesContent":["import {z} from 'zod/mini'\n\nimport {APP_SLUG_PATTERN} from './appSlug.js'\nimport {DockSchema, InterfaceDeclarationSchema, ServiceDeclarationSchema} from './contract.js'\n\n/**\n * Dashboard visibility values. Mirrors `APP_VISIBILITIES` in `@sanity/cli-core`\n * (which can't be imported here — pulling the barrel into this lean module bloats\n * the config-load path). Kept in sync by a type test in `defineApp.test.ts`.\n */\nconst APP_VISIBILITIES = ['default', 'unlisted', 'disabled'] as const\n\n/**\n * Internal application discriminator. Sanity-owned singleton apps only;\n * validated by the schema but excluded from the public `DefineAppInput` type.\n */\nconst ApplicationType = z.enum(['coreApp', 'studio', 'canvas', 'dashboard'])\n\n/**\n * Runtime-validation schema for `defineApplication`.\n * @internal\n */\nexport const DefineAppInputSchema = z\n .object({\n /**\n * Internal — Sanity-owned singleton apps only. Validated here but excluded\n * from the public `DefineAppInput` type.\n * @internal\n */\n applicationType: z.optional(ApplicationType),\n /** Default placement inherited by panel and window views. */\n dock: z.optional(DockSchema),\n /**\n * App entrypoint module. Defaults to `./src/App.tsx` when omitted. The build\n * derives the app's navigable `app` view from it. SDK apps only — setting it\n * on a studio is rejected (studio app views are not yet implemented).\n */\n entry: z.optional(z.string(\"must be a path to the app's entry file\")),\n /** Optional icon override (path to an SVG). Wins over manifest/studio icon. */\n icon: z.optional(z.string()),\n /**\n * Stable identity, distinct from the `slug` address. Defaults to `slug` when\n * omitted. Identity keys — the build id and derived interface ids — are built\n * from this, so renaming the slug no longer changes identity.\n */\n name: z.optional(\n z\n .string()\n .check(\n z.regex(\n APP_SLUG_PATTERN,\n 'App `name` must be lowercase alphanumerics and hyphens, starting with a letter and ending with an alphanumeric',\n ),\n ),\n ),\n /** Organization that owns the app — the workbench runs and deploys against it. */\n organizationId: z.string(\n \"App `organizationId` is required — pass the owning organization's ID to `defineApplication`\",\n ),\n slug: z\n .string('App `slug` is required — the hostname the application is created at on deploy')\n .check(\n z.regex(\n APP_SLUG_PATTERN,\n 'App `slug` must be lowercase alphanumerics and hyphens, starting with a letter and ending with an alphanumeric',\n ),\n ),\n /** User-facing app title. Wins over studio.config.ts title on merge. */\n title: z.string(),\n /** Views the app exposes (e.g. a window, dock panels, and tiles). */\n views: z.optional(z.array(InterfaceDeclarationSchema, 'must be an array of views')),\n /** Dashboard visibility of the app. Defaults to `default` when omitted. */\n visibility: z.optional(z.enum(APP_VISIBILITIES)),\n /** Background web workers the app runs. */\n webWorkers: z.optional(z.array(ServiceDeclarationSchema, 'must be an array of web workers')),\n })\n .check(\n z.refine((input) => {\n const names = [\n ...(input.entry === undefined ? [] : [input.name ?? input.slug]),\n ...(input.views ?? []).map((view) => view.name),\n ...(input.webWorkers ?? []).map((webWorker) => webWorker.name),\n ]\n return new Set(names).size === names.length\n }, '`name` must be unique across views and web workers. Rename one of the duplicates.'),\n // Studio app views are not implemented yet. A studio that declares `entry`\n // (the SDK app-view entrypoint) is rejected here rather than silently\n // generating one; studios keep navigating via their existing render path.\n z.refine((input) => !(input.applicationType === 'studio' && input.entry !== undefined), {\n error: 'App views for studios are not implemented yet',\n path: ['entry'],\n }),\n )\n\n/**\n * User-facing input for `defineApplication`. Excludes the internal\n * `applicationType`.\n * @public\n */\nexport type DefineAppInput = Omit<z.output<typeof DefineAppInputSchema>, 'applicationType'>\n\n/**\n * Nominal brand the CLI discriminates on to enable the workbench build/deploy\n * codepath. Registered via `Symbol.for` so the marker survives module-realm\n * boundaries — `@sanity/cli-core` re-derives the same global symbol with\n * `Symbol.for` rather than importing it, so it stays internal to this module.\n */\nconst WORKBENCH_APP: unique symbol = Symbol.for('sanity.workbench.defineApp')\n\n/**\n * The branded result of `defineApplication`. Carries the same fields as the\n * input plus the internal brand — users only ever see `DefineAppInput`.\n * @public\n */\nexport type DefineAppResult = DefineAppInput & {readonly [WORKBENCH_APP]: true}\n\n/**\n * A branded app as the CLI reads it — the full schema shape, including the\n * internal fields `DefineAppInput` omits. Schema-derived so the narrowing\n * can't drift from what the schema validates.\n * @public\n */\nexport type WorkbenchApp = DefineAppResult & z.output<typeof DefineAppInputSchema>\n\n/**\n * Whether `app` is a branded `defineApplication(...)` result — the sole\n * workbench opt-in.\n * @public\n */\nexport function isWorkbenchApp(app: unknown): app is WorkbenchApp {\n return typeof app === 'object' && app !== null && WORKBENCH_APP in app\n}\n\n/**\n * Declare a Sanity Workbench application. Identity at runtime — returns the same\n * object reference, tagged with the workbench brand. Field validation (the\n * `slug` pattern etc.) runs at build time in the CLI via `DefineAppInputSchema`;\n * this helper stays a thin, pure identity wrapper.\n * @public\n */\nexport function defineApplication(input: DefineAppInput): DefineAppResult {\n return Object.defineProperty(input, WORKBENCH_APP, {\n configurable: false,\n enumerable: false,\n value: true,\n writable: false,\n }) as DefineAppResult\n}\n\n/**\n * One custom field a media library exposes. `src` default-exports a `defineField(...)` schema type.\n * @public\n */\nexport interface MediaLibraryField {\n /** Unique within the media library. */\n name: string\n src: string\n title: string\n\n /** Readable outside the owning organization. */\n public?: boolean\n}\n\n/**\n * Sanity-owned singleton, so authors don't name or title the app — only `organizationId` is required.\n * @public\n */\nexport interface DefineMediaLibraryInput {\n /** Organization that owns the media library — the CLI runs and deploys against it. */\n organizationId: string\n\n fields?: MediaLibraryField[]\n}\n\n/**\n * Nominal brand the CLI discriminates a config on. A config is *not* an app: it\n * carries no `slug`/`title`/application identity, only a target `appType`, its\n * owning `organizationId`, and its `fields`. Registered via `Symbol.for` so the\n * marker survives module-realm boundaries — `@sanity/cli-core` re-derives the\n * same global symbol rather than importing it.\n */\nconst WORKBENCH_CONFIG: unique symbol = Symbol.for('sanity.workbench.defineConfig')\n\n/**\n * A branded workbench config as the CLI reads it: bound to its target app by\n * `appType`, not carrying its own app identity. The deploy/undeploy/build paths\n * discriminate it via {@link isWorkbenchConfig}.\n * @public\n */\nexport interface WorkbenchConfig {\n appType: 'media-library'\n fields: MediaLibraryField[]\n organizationId: string\n readonly [WORKBENCH_CONFIG]: true\n}\n\n/**\n * Whether `app` is a branded `unstable_defineMediaLibrary(...)` config — a\n * config-carrier rather than an app. Configs live in `cliConfig.app` alongside\n * apps but resolve through `resolveWorkbenchConfig`, not `resolveWorkbenchApp`.\n * @public\n */\nexport function isWorkbenchConfig(app: unknown): app is WorkbenchConfig {\n return typeof app === 'object' && app !== null && WORKBENCH_CONFIG in app\n}\n\n/**\n * Declare the Sanity Media Library config. The Media Library is a Sanity-owned\n * singleton, so this is not an app — it carries no slug or title, only the\n * target `appType`, its owning organization, and the `fields` it contributes to\n * the installation's config.\n * @public\n */\nexport function unstable_defineMediaLibrary(input: DefineMediaLibraryInput): WorkbenchConfig {\n return Object.defineProperty(\n {appType: 'media-library', fields: input.fields ?? [], organizationId: input.organizationId},\n WORKBENCH_CONFIG,\n {configurable: false, enumerable: false, value: true, writable: false},\n ) as WorkbenchConfig\n}\n"],"names":["z","APP_SLUG_PATTERN","DockSchema","InterfaceDeclarationSchema","ServiceDeclarationSchema","APP_VISIBILITIES","ApplicationType","enum","DefineAppInputSchema","object","applicationType","optional","dock","entry","string","icon","name","check","regex","organizationId","slug","title","views","array","visibility","webWorkers","refine","input","names","undefined","map","view","webWorker","Set","size","length","error","path","WORKBENCH_APP","Symbol","for","isWorkbenchApp","app","defineApplication","Object","defineProperty","configurable","enumerable","value","writable","WORKBENCH_CONFIG","isWorkbenchConfig","unstable_defineMediaLibrary","appType","fields"],"mappings":"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"}
|
package/dist/defineView.js
CHANGED
|
@@ -4,14 +4,14 @@ import { VIEW_CONTRACT_VERSION } from './contract.js';
|
|
|
4
4
|
* and the props each component receives — `"panel"` yields a `{title, panel}`
|
|
5
5
|
* record whose components are typed with the panel props.
|
|
6
6
|
*
|
|
7
|
-
* Returns the component(s) tagged with their
|
|
7
|
+
* Returns the component(s) tagged with their surface and contract version, for
|
|
8
8
|
* the CLI build to generate render artifacts from. Used as the default export of
|
|
9
9
|
* a view's `src` file.
|
|
10
10
|
* @public
|
|
11
|
-
*/ export function unstable_defineView(
|
|
11
|
+
*/ export function unstable_defineView(surface, components) {
|
|
12
12
|
return {
|
|
13
13
|
components,
|
|
14
|
-
|
|
14
|
+
surface,
|
|
15
15
|
version: VIEW_CONTRACT_VERSION
|
|
16
16
|
};
|
|
17
17
|
}
|
package/dist/defineView.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/defineView.ts"],"sourcesContent":["import {type AssetSourceComponentProps} from '@sanity/types'\n\nimport {\n type
|
|
1
|
+
{"version":3,"sources":["../src/defineView.ts"],"sourcesContent":["import {type AssetSourceComponentProps} from '@sanity/types'\n\nimport {\n type TileSize,\n VIEW_CONTRACT_VERSION,\n type ViewComponent,\n type ViewComponentBaseProps,\n type ViewSurface,\n} from './contract.js'\n\n/** @public */\nexport type WindowViewProps = ViewComponentBaseProps<{\n name: string\n src: string\n surface: 'app'\n title: string\n}>\n\n/**\n * Props a panel component receives: its interface record, minus the\n * service-assigned `id`/`deployment_id` a local dev server can't provide. Mirrors\n * the `panel` record the workbench host renders from (the wire format owned by\n * `@sanity/workbench`); drift is guarded by the stamped contract version.\n * @public\n */\nexport type PanelViewProps = ViewComponentBaseProps<{\n name: string\n src: string\n surface: 'panel'\n title: string\n}>\n\n/**\n * The component slots a `panel` view exposes — each its own module-federation\n * island, typed with the panel props.\n * @public\n */\nexport interface PanelViewComponents {\n panel: ViewComponent<PanelViewProps>\n title: ViewComponent<PanelViewProps>\n}\n\n/**\n * A panel's view-component slot — the module-federation expose for one island.\n * @public\n */\nexport type PanelComponent = keyof PanelViewComponents\n\n/**\n * The component slots an `asset_source` view exposes — a single picker island,\n * typed with the studio asset-source props it renders behind. The props are\n * `@sanity/types`' `AssetSourceComponentProps` directly, so an authored picker\n * receives exactly what a studio `AssetSource.component` does.\n * @public\n */\nexport interface AssetSourceViewComponents {\n asset_source: ViewComponent<AssetSourceComponentProps>\n}\n\n/**\n * An asset source's view-component slot — the module-federation expose for its\n * one island.\n * @public\n */\nexport type AssetSourceComponent = keyof AssetSourceViewComponents\n\n/**\n * Props a tile component receives: its own interface record plus its footprint\n * `size`, so it can render per family. Mirrors the\n * `tile` record the dashboard host renders from; drift is guarded by the stamped\n * contract version. Placement `order` is host-only metadata, not surfaced here.\n * @public\n */\nexport type TileViewProps = ViewComponentBaseProps<{\n name: string\n size: TileSize\n src: string\n surface: 'tile'\n title: string\n}>\n\n/**\n * The component slot a `tile` view exposes — a single island, typed with the\n * tile props.\n * @public\n */\nexport interface TileViewComponents {\n tile: ViewComponent<TileViewProps>\n}\n\n/**\n * A tile's view-component slot — the module-federation expose for its one island.\n * @public\n */\nexport type TileComponent = keyof TileViewComponents\n\n/**\n * The components each view surface exposes.\n * @public\n */\nexport interface ViewComponentsBySurface {\n app: ViewComponent<WindowViewProps>\n asset_source: AssetSourceViewComponents\n panel: PanelViewComponents\n tile: TileViewComponents\n}\n\n/**\n * The result of `unstable_defineView`: the author's component(s), the view surface,\n * and the internal contract version the build artifact targets.\n * @public\n */\nexport interface DefinedView<TSurface extends ViewSurface = ViewSurface> {\n readonly components: ViewComponentsBySurface[TSurface]\n readonly surface: TSurface\n /** @internal */\n readonly version: typeof VIEW_CONTRACT_VERSION\n}\n\n/**\n * Define a Sanity Workbench view. The first argument narrows the component shape\n * and the props each component receives — `\"panel\"` yields a `{title, panel}`\n * record whose components are typed with the panel props.\n *\n * Returns the component(s) tagged with their surface and contract version, for\n * the CLI build to generate render artifacts from. Used as the default export of\n * a view's `src` file.\n * @public\n */\nexport function unstable_defineView<TSurface extends ViewSurface>(\n surface: TSurface,\n components: ViewComponentsBySurface[TSurface],\n): DefinedView<TSurface> {\n return {components, surface, version: VIEW_CONTRACT_VERSION}\n}\n"],"names":["VIEW_CONTRACT_VERSION","unstable_defineView","surface","components","version"],"mappings":"AAEA,SAEEA,qBAAqB,QAIhB,gBAAe;AA+GtB;;;;;;;;;CASC,GACD,OAAO,SAASC,oBACdC,OAAiB,EACjBC,UAA6C;IAE7C,OAAO;QAACA;QAAYD;QAASE,SAASJ;IAAqB;AAC7D"}
|