@neta-art/cohub 8.11.0 → 8.12.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/dist/board/animation.js +14 -2
- package/dist/board/core/file-preview.d.ts +2 -2
- package/dist/board/core/file-preview.js +2 -2
- package/dist/board/index.d.ts +2 -1
- package/dist/board/index.js +2 -1
- package/dist/board/mutation.js +2 -1
- package/dist/board/render/board-background.d.ts +16 -0
- package/dist/board/render/{themes/clean-theme.js → board-background.js} +28 -35
- package/dist/board/render/index.d.ts +3 -3
- package/dist/board/render/index.js +2 -2
- package/dist/board/render/renderers/file-card-renderer.js +3 -32
- package/dist/board/replay.d.ts +52 -0
- package/dist/board/replay.js +261 -0
- package/dist/board/semantic-document.d.ts +9 -2
- package/dist/board/semantic-document.js +1 -3
- package/dist/chunks/environment.d.ts +296 -9
- package/dist/chunks/environment.js +1 -0
- package/dist/chunks/http.d.ts +54 -4
- package/dist/chunks/http.js +67 -12
- package/dist/chunks/websocket.d.ts +1 -1
- package/dist/http.d.ts +3 -3
- package/dist/index.d.ts +11 -4
- package/dist/index.js +201 -51
- package/dist/protocol/dist/board-animation.d.ts +1 -0
- package/dist/protocol/dist/board-animation.js +34 -0
- package/dist/protocol/dist/board-authoring.d.ts +2 -1
- package/dist/protocol/dist/board-capability-registry.js +53 -3
- package/dist/protocol/dist/board-codec.js +149 -2
- package/dist/protocol/dist/board-constants.js +29 -7
- package/dist/protocol/dist/board-document.d.ts +30 -16
- package/dist/protocol/dist/board-document.js +15 -12
- package/dist/protocol/dist/board-effect.d.ts +4 -2
- package/dist/protocol/dist/board-effect.js +3 -2
- package/dist/protocol/dist/board.d.ts +148 -3
- package/dist/protocol/dist/board.js +7 -0
- package/dist/protocol/dist/index.d.ts +4 -2
- package/dist/protocol/dist/provenance.d.ts +21 -0
- package/dist/types.d.ts +1 -1
- package/docs/app-runtime-guide.md +7 -4
- package/package.json +1 -1
- package/dist/board/render/themes/board-theme-registry.d.ts +0 -22
- package/dist/board/render/themes/board-theme-registry.js +0 -13
- package/dist/board/render/themes/clean-theme.d.ts +0 -5
package/dist/index.js
CHANGED
|
@@ -8,8 +8,8 @@ import { z } from "zod";
|
|
|
8
8
|
const BOARD_DOCUMENT_KIND = "cohub.board";
|
|
9
9
|
const BOARD_MANIFEST_KIND = "cohub.board.manifest";
|
|
10
10
|
const idSchema = z.string().min(1).max(160);
|
|
11
|
-
const jsonObjectSchema = z.record(z.string(), z.unknown());
|
|
12
|
-
const finiteSchema = z.number().finite();
|
|
11
|
+
const jsonObjectSchema$1 = z.record(z.string(), z.unknown());
|
|
12
|
+
const finiteSchema$1 = z.number().finite();
|
|
13
13
|
z.object({
|
|
14
14
|
kind: z.literal(BOARD_MANIFEST_KIND),
|
|
15
15
|
version: z.literal(1),
|
|
@@ -17,18 +17,18 @@ z.object({
|
|
|
17
17
|
title: z.string().min(1).max(255)
|
|
18
18
|
});
|
|
19
19
|
z.object({
|
|
20
|
-
centerX: finiteSchema,
|
|
21
|
-
centerY: finiteSchema,
|
|
22
|
-
zoom: finiteSchema.positive()
|
|
20
|
+
centerX: finiteSchema$1,
|
|
21
|
+
centerY: finiteSchema$1,
|
|
22
|
+
zoom: finiteSchema$1.positive()
|
|
23
23
|
});
|
|
24
24
|
const BoardCameraFocusSchema = z.discriminatedUnion("type", [
|
|
25
25
|
z.object({
|
|
26
26
|
type: z.literal("rect"),
|
|
27
27
|
rect: z.object({
|
|
28
|
-
x: finiteSchema,
|
|
29
|
-
y: finiteSchema,
|
|
30
|
-
width: finiteSchema.positive(),
|
|
31
|
-
height: finiteSchema.positive()
|
|
28
|
+
x: finiteSchema$1,
|
|
29
|
+
y: finiteSchema$1,
|
|
30
|
+
width: finiteSchema$1.positive(),
|
|
31
|
+
height: finiteSchema$1.positive()
|
|
32
32
|
})
|
|
33
33
|
}),
|
|
34
34
|
z.object({
|
|
@@ -47,9 +47,9 @@ const BoardCameraFocusSchema = z.discriminatedUnion("type", [
|
|
|
47
47
|
const BoardCameraFocusParamsSchema = z.object({
|
|
48
48
|
focus: BoardCameraFocusSchema,
|
|
49
49
|
fit: z.enum(["contain", "cover"]).default("contain"),
|
|
50
|
-
padding: finiteSchema.nonnegative().default(32),
|
|
51
|
-
minZoom: finiteSchema.positive().optional(),
|
|
52
|
-
maxZoom: finiteSchema.positive().optional()
|
|
50
|
+
padding: finiteSchema$1.nonnegative().default(32),
|
|
51
|
+
minZoom: finiteSchema$1.positive().optional(),
|
|
52
|
+
maxZoom: finiteSchema$1.positive().optional()
|
|
53
53
|
}).superRefine((value, context) => {
|
|
54
54
|
if (value.minZoom !== void 0 && value.maxZoom !== void 0 && value.minZoom > value.maxZoom) context.addIssue({
|
|
55
55
|
code: "custom",
|
|
@@ -62,17 +62,17 @@ z.object({
|
|
|
62
62
|
type: z.string().min(1).max(40),
|
|
63
63
|
parentId: idSchema.nullable(),
|
|
64
64
|
orderKey: z.string().max(4096).nullable(),
|
|
65
|
-
x: finiteSchema,
|
|
66
|
-
y: finiteSchema,
|
|
67
|
-
width: finiteSchema.positive(),
|
|
68
|
-
height: finiteSchema.positive(),
|
|
69
|
-
rotation: finiteSchema,
|
|
65
|
+
x: finiteSchema$1,
|
|
66
|
+
y: finiteSchema$1,
|
|
67
|
+
width: finiteSchema$1.positive(),
|
|
68
|
+
height: finiteSchema$1.positive(),
|
|
69
|
+
rotation: finiteSchema$1,
|
|
70
70
|
refKind: z.string().max(40).nullable(),
|
|
71
71
|
refPath: z.string().max(4096).nullable(),
|
|
72
72
|
refUrl: z.string().max(4096).nullable(),
|
|
73
|
-
view: jsonObjectSchema,
|
|
74
|
-
style: jsonObjectSchema,
|
|
75
|
-
data: jsonObjectSchema
|
|
73
|
+
view: jsonObjectSchema$1,
|
|
74
|
+
style: jsonObjectSchema$1,
|
|
75
|
+
data: jsonObjectSchema$1
|
|
76
76
|
});
|
|
77
77
|
const stripBoardServerFields = (value) => {
|
|
78
78
|
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
@@ -86,7 +86,7 @@ const BoardCreateInputSchema = z.object({
|
|
|
86
86
|
/** Reused by clients when board creation is interrupted and retried. */
|
|
87
87
|
mutationId: z.string().max(128).optional(),
|
|
88
88
|
title: z.string().min(1).max(255).optional(),
|
|
89
|
-
metadata: jsonObjectSchema.optional(),
|
|
89
|
+
metadata: jsonObjectSchema$1.optional(),
|
|
90
90
|
items: z.array(BoardAuthoringItemSchema).max(5e4).optional(),
|
|
91
91
|
connections: z.array(BoardConnectionSchema).max(5e4).optional(),
|
|
92
92
|
effects: z.array(BoardCreateEffectInputSchema).max(5e4).optional(),
|
|
@@ -132,17 +132,24 @@ z.object({
|
|
|
132
132
|
effectIds: z.array(idSchema).max(5e4).optional(),
|
|
133
133
|
compositionIds: z.array(idSchema).max(5e4).optional(),
|
|
134
134
|
viewport: z.object({
|
|
135
|
-
x: finiteSchema,
|
|
136
|
-
y: finiteSchema,
|
|
137
|
-
width: finiteSchema.positive(),
|
|
138
|
-
height: finiteSchema.positive()
|
|
135
|
+
x: finiteSchema$1,
|
|
136
|
+
y: finiteSchema$1,
|
|
137
|
+
width: finiteSchema$1.positive(),
|
|
138
|
+
height: finiteSchema$1.positive()
|
|
139
139
|
}).optional()
|
|
140
140
|
});
|
|
141
|
+
z.object({
|
|
142
|
+
/** Return transactions with `version < before`. Omit for the newest page. */
|
|
143
|
+
before: z.number().int().positive().optional(),
|
|
144
|
+
limit: z.number().int().min(1).max(500).default(200),
|
|
145
|
+
/** Include the current rows on the newest page (default true). Tail refreshes turn this off. */
|
|
146
|
+
snapshot: z.boolean().default(true)
|
|
147
|
+
});
|
|
141
148
|
/** Persisted on `boards.metadata.playback`: how a Board plays when opened. */
|
|
142
149
|
const BoardPlaybackPolicySchema = z.object({
|
|
143
150
|
compositionId: idSchema,
|
|
144
151
|
/** Delay before the first local playback after opening the Board, in milliseconds. */
|
|
145
|
-
delayMs: finiteSchema.nonnegative().default(0)
|
|
152
|
+
delayMs: finiteSchema$1.nonnegative().default(0)
|
|
146
153
|
});
|
|
147
154
|
function parseBoardPlaybackPolicy(metadata) {
|
|
148
155
|
const parsed = BoardPlaybackPolicySchema.safeParse(metadata.playback);
|
|
@@ -153,8 +160,8 @@ z.discriminatedUnion("type", [
|
|
|
153
160
|
commandId: idSchema,
|
|
154
161
|
type: z.literal("play"),
|
|
155
162
|
compositionId: idSchema,
|
|
156
|
-
position: finiteSchema.nonnegative().optional(),
|
|
157
|
-
timeScale: finiteSchema.positive().max(4).optional(),
|
|
163
|
+
position: finiteSchema$1.nonnegative().optional(),
|
|
164
|
+
timeScale: finiteSchema$1.positive().max(4).optional(),
|
|
158
165
|
shared: z.boolean().optional(),
|
|
159
166
|
seed: idSchema.optional()
|
|
160
167
|
}),
|
|
@@ -167,7 +174,7 @@ z.discriminatedUnion("type", [
|
|
|
167
174
|
commandId: idSchema,
|
|
168
175
|
type: z.literal("seek"),
|
|
169
176
|
playbackId: z.string().uuid(),
|
|
170
|
-
position: finiteSchema.nonnegative()
|
|
177
|
+
position: finiteSchema$1.nonnegative()
|
|
171
178
|
}),
|
|
172
179
|
z.object({
|
|
173
180
|
commandId: idSchema,
|
|
@@ -176,9 +183,49 @@ z.discriminatedUnion("type", [
|
|
|
176
183
|
})
|
|
177
184
|
]);
|
|
178
185
|
//#endregion
|
|
186
|
+
//#region ../protocol/dist/board-animation.js
|
|
187
|
+
const extensionKindSchema = z.string().regex(/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)+$/).max(160);
|
|
188
|
+
const jsonObjectSchema = z.record(z.string(), z.unknown());
|
|
189
|
+
const finiteSchema = z.number().finite();
|
|
190
|
+
/** Parameters shared by the built-in deal entrance preset. */
|
|
191
|
+
const BoardDealParamsSchema = z.object({
|
|
192
|
+
lift: finiteSchema.nonnegative().max(2e3).optional(),
|
|
193
|
+
swing: finiteSchema.nonnegative().max(2e3).optional(),
|
|
194
|
+
curve: finiteSchema.nonnegative().max(2e3).optional(),
|
|
195
|
+
tilt: finiteSchema.nonnegative().max(180).optional(),
|
|
196
|
+
scale: finiteSchema.positive().max(2).optional(),
|
|
197
|
+
duration: finiteSchema.positive().max(1e4).optional(),
|
|
198
|
+
landing: finiteSchema.nonnegative().max(1e4).optional()
|
|
199
|
+
}).strict();
|
|
200
|
+
/** A versioned, reusable animation preset reference. */
|
|
201
|
+
const BoardAnimationSpecSchema = z.object({
|
|
202
|
+
kind: extensionKindSchema,
|
|
203
|
+
kindVersion: z.number().int().positive().default(1),
|
|
204
|
+
params: jsonObjectSchema.default({})
|
|
205
|
+
}).strict().superRefine((spec, context) => {
|
|
206
|
+
if (spec.kind !== "effects.deal" || spec.kindVersion !== 1) return;
|
|
207
|
+
const parsed = BoardDealParamsSchema.safeParse(spec.params);
|
|
208
|
+
if (parsed.success) return;
|
|
209
|
+
context.addIssue({
|
|
210
|
+
code: "custom",
|
|
211
|
+
message: parsed.error.issues[0]?.message ?? "invalid effects.deal parameters",
|
|
212
|
+
path: ["params", ...parsed.error.issues[0]?.path ?? []]
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
/** Board-wide default motion policies. Omitted policies mean no motion. */
|
|
216
|
+
const BoardMotionSchema = z.object({ enter: BoardAnimationSpecSchema.optional() }).strict();
|
|
217
|
+
//#endregion
|
|
179
218
|
//#region ../protocol/dist/board-capability-registry.js
|
|
180
219
|
const CLIPS = new Set(BOARD_BUILTIN_CLIP_KINDS);
|
|
181
|
-
new Set(BOARD_BUILTIN_EFFECT_KINDS);
|
|
220
|
+
const EFFECTS = new Set(BOARD_BUILTIN_EFFECT_KINDS);
|
|
221
|
+
const BUILTIN_VERSIONS = new Set(BOARD_BUILTIN_CAPABILITIES.map((c) => `${c.kind}:${c.id}@${c.version}`));
|
|
222
|
+
/**
|
|
223
|
+
* True when a built-in renderer exists for exactly this kind@version. A known
|
|
224
|
+
* kind at an unknown version is not built-in: it must not pass as one.
|
|
225
|
+
*/
|
|
226
|
+
function isBuiltinBoardCapability(kind, id, version) {
|
|
227
|
+
return BUILTIN_VERSIONS.has(`${kind}:${id}@${version}`);
|
|
228
|
+
}
|
|
182
229
|
const record = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
183
230
|
const finite = (value) => typeof value === "number" && Number.isFinite(value);
|
|
184
231
|
function validateBuiltinBoardClip(clip, path = "clip") {
|
|
@@ -212,6 +259,47 @@ function validateBuiltinBoardClip(clip, path = "clip") {
|
|
|
212
259
|
}
|
|
213
260
|
return errors;
|
|
214
261
|
}
|
|
262
|
+
function validateBuiltinBoardEffect(effect, path = "effect") {
|
|
263
|
+
const diagnostics = [];
|
|
264
|
+
if (effect.lifecycle === "on-enter") {
|
|
265
|
+
if (effect.target.type !== "item") diagnostics.push({
|
|
266
|
+
severity: "error",
|
|
267
|
+
code: "INVALID_BOARD_EFFECT",
|
|
268
|
+
message: "on-enter effects must target an item",
|
|
269
|
+
path: `${path}.target`
|
|
270
|
+
});
|
|
271
|
+
if (effect.timeOrigin !== "activation") diagnostics.push({
|
|
272
|
+
severity: "error",
|
|
273
|
+
code: "INVALID_BOARD_EFFECT",
|
|
274
|
+
message: "on-enter effects must use activation time",
|
|
275
|
+
path: `${path}.timeOrigin`
|
|
276
|
+
});
|
|
277
|
+
} else if (EFFECTS.has(effect.kind) && effect.target.type !== "item") diagnostics.push({
|
|
278
|
+
severity: "error",
|
|
279
|
+
code: "INVALID_BOARD_EFFECT",
|
|
280
|
+
message: `${effect.kind} must target an item`,
|
|
281
|
+
path: `${path}.target`
|
|
282
|
+
});
|
|
283
|
+
if (effect.kind === "effects.deal" && effect.kindVersion === 1) {
|
|
284
|
+
if (effect.lifecycle !== "on-enter") diagnostics.push({
|
|
285
|
+
severity: "error",
|
|
286
|
+
code: "INVALID_BOARD_EFFECT",
|
|
287
|
+
message: "effects.deal must use the on-enter lifecycle",
|
|
288
|
+
path: `${path}.lifecycle`
|
|
289
|
+
});
|
|
290
|
+
const parsed = BoardDealParamsSchema.safeParse(effect.params);
|
|
291
|
+
if (!parsed.success) diagnostics.push({
|
|
292
|
+
severity: "error",
|
|
293
|
+
code: "INVALID_BOARD_EFFECT",
|
|
294
|
+
message: parsed.error.issues[0]?.message ?? "invalid effects.deal parameters",
|
|
295
|
+
path: `${path}.params`
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
return diagnostics;
|
|
299
|
+
}
|
|
300
|
+
function estimateBuiltinBoardEffectCost(effect) {
|
|
301
|
+
return isBuiltinBoardCapability("effect", effect.kind, effect.kindVersion) ? { drawCalls: 1 } : {};
|
|
302
|
+
}
|
|
215
303
|
function estimateBuiltinBoardClipCost(clip) {
|
|
216
304
|
switch (clip.kind) {
|
|
217
305
|
case "effects.particles": {
|
|
@@ -352,7 +440,18 @@ const BoardViewportSchema = z.object({
|
|
|
352
440
|
zoom: z.number().finite().min(.05).max(8)
|
|
353
441
|
});
|
|
354
442
|
const BoardAppearanceSchema = z.object({
|
|
355
|
-
|
|
443
|
+
/** Legacy field retained when reading older Board documents; not used for rendering. */
|
|
444
|
+
theme: z.string().min(1).optional(),
|
|
445
|
+
/** Board-wide motion policies. Omitted policies mean no motion. */
|
|
446
|
+
motion: BoardMotionSchema.optional(),
|
|
447
|
+
/** Legacy field retained when reading older Board documents; not used for rendering. */
|
|
448
|
+
mood: z.enum([
|
|
449
|
+
"clean",
|
|
450
|
+
"playful",
|
|
451
|
+
"arcane",
|
|
452
|
+
"cyber",
|
|
453
|
+
"natural"
|
|
454
|
+
]).optional(),
|
|
356
455
|
background: z.object({
|
|
357
456
|
kind: z.enum([
|
|
358
457
|
"solid",
|
|
@@ -386,14 +485,7 @@ const BoardAppearanceSchema = z.object({
|
|
|
386
485
|
visible: false,
|
|
387
486
|
size: 24,
|
|
388
487
|
opacity: .12
|
|
389
|
-
})
|
|
390
|
-
mood: z.enum([
|
|
391
|
-
"clean",
|
|
392
|
-
"playful",
|
|
393
|
-
"arcane",
|
|
394
|
-
"cyber",
|
|
395
|
-
"natural"
|
|
396
|
-
]).default("clean")
|
|
488
|
+
})
|
|
397
489
|
});
|
|
398
490
|
/** Optional visual chrome still carried by a few older shapes. */
|
|
399
491
|
const BoardItemStyleSchema = z.object({
|
|
@@ -695,14 +787,12 @@ z.object({
|
|
|
695
787
|
kind: z.literal(BOARD_DOCUMENT_KIND),
|
|
696
788
|
version: z.literal(1),
|
|
697
789
|
appearance: BoardAppearanceSchema.default({
|
|
698
|
-
theme: "clean",
|
|
699
790
|
background: { kind: "solid" },
|
|
700
791
|
grid: {
|
|
701
792
|
visible: false,
|
|
702
793
|
size: 24,
|
|
703
794
|
opacity: .12
|
|
704
|
-
}
|
|
705
|
-
mood: "clean"
|
|
795
|
+
}
|
|
706
796
|
}),
|
|
707
797
|
viewport: BoardViewportSchema,
|
|
708
798
|
items: z.array(BoardItemSchema),
|
|
@@ -1294,6 +1384,12 @@ const buildAppRuntimeCloseRequest = () => ({
|
|
|
1294
1384
|
version: 1,
|
|
1295
1385
|
type: "close.request"
|
|
1296
1386
|
});
|
|
1387
|
+
const buildAppRuntimeConfigureRequest = (input) => ({
|
|
1388
|
+
protocol: APP_RUNTIME_PROTOCOL,
|
|
1389
|
+
version: 1,
|
|
1390
|
+
type: "configure.request",
|
|
1391
|
+
...input
|
|
1392
|
+
});
|
|
1297
1393
|
//#endregion
|
|
1298
1394
|
//#region ../protocol/dist/app-navigation.js
|
|
1299
1395
|
const APP_NAVIGATION_PROTOCOL = "cohub.app.navigation";
|
|
@@ -2452,6 +2548,14 @@ var AppRuntimeApi = class {
|
|
|
2452
2548
|
requestClose() {
|
|
2453
2549
|
this.transport.notify?.(buildAppRuntimeCloseRequest());
|
|
2454
2550
|
}
|
|
2551
|
+
/**
|
|
2552
|
+
* Requests the host to update the overlay's geometry or pointer hit regions.
|
|
2553
|
+
* Only meaningful when the App was opened as an `overlay` surface; the host
|
|
2554
|
+
* is free to clamp or ignore values that violate its layout policy.
|
|
2555
|
+
*/
|
|
2556
|
+
requestConfigure(input) {
|
|
2557
|
+
this.transport.notify?.(buildAppRuntimeConfigureRequest(input));
|
|
2558
|
+
}
|
|
2455
2559
|
async getAccessToken(options) {
|
|
2456
2560
|
await this.ensureStorageKeys();
|
|
2457
2561
|
if (this.token && !options?.forceRefresh) return this.token;
|
|
@@ -2553,7 +2657,7 @@ var AppRuntimeApi = class {
|
|
|
2553
2657
|
* One consent: create a viewer-owned Space (full `CreateSpaceInput`, same
|
|
2554
2658
|
* as `spaces.create`) and grant the scopes on it. Never silent — each
|
|
2555
2659
|
* confirm mints a new Space. The host creates with the viewer's account
|
|
2556
|
-
* token
|
|
2660
|
+
* token.
|
|
2557
2661
|
* `{ granted: false, space }` means the Space was created but not provisioned;
|
|
2558
2662
|
* no grant was issued. A viewer deny is `{ granted: false, space: null }`.
|
|
2559
2663
|
*/
|
|
@@ -2766,6 +2870,11 @@ var CohubClient = class {
|
|
|
2766
2870
|
onContextChanged: (listener) => this.appRuntime.onContextChanged(listener),
|
|
2767
2871
|
/** Ask the host to close this App's surface. */
|
|
2768
2872
|
requestClose: () => this.appRuntime.requestClose(),
|
|
2873
|
+
/**
|
|
2874
|
+
* Request that the host update this overlay's geometry or pointer hit
|
|
2875
|
+
* regions. Only meaningful for `overlay` surfaces; ignored otherwise.
|
|
2876
|
+
*/
|
|
2877
|
+
requestConfigure: (input) => this.appRuntime.requestConfigure(input),
|
|
2769
2878
|
embed: {
|
|
2770
2879
|
/** Host another App's public page in an iframe and forward the shell location to it. */
|
|
2771
2880
|
attach: attachAppEmbed },
|
|
@@ -3130,6 +3239,20 @@ const isDefinitiveAuthorizationFailure = (error) => error instanceof AppAuthoriz
|
|
|
3130
3239
|
403,
|
|
3131
3240
|
404
|
|
3132
3241
|
].includes(error.status);
|
|
3242
|
+
/**
|
|
3243
|
+
* Whether a new authorize request asks for exactly the consent a pending
|
|
3244
|
+
* dialog already shows: same scopes, same target and same mode. Such a request
|
|
3245
|
+
* joins the dialog instead of replacing it, so an App that asks twice (for
|
|
3246
|
+
* example on every context update) gets one dialog and one shared answer.
|
|
3247
|
+
*/
|
|
3248
|
+
function isSameConsent(pending, next) {
|
|
3249
|
+
if (next.createSpace || pending.createSpace) return false;
|
|
3250
|
+
if (Boolean(pending.selectSpace) !== next.selectSpace) return false;
|
|
3251
|
+
if (pending.spaceId !== next.spaceId) return false;
|
|
3252
|
+
const a = normalizePermissionScopes(pending.scopes);
|
|
3253
|
+
const b = normalizePermissionScopes(next.scopes);
|
|
3254
|
+
return a.length === b.length && a.every((scope) => b.includes(scope));
|
|
3255
|
+
}
|
|
3133
3256
|
function sanitizeReason(value) {
|
|
3134
3257
|
if (typeof value !== "string") return void 0;
|
|
3135
3258
|
const trimmed = value.trim();
|
|
@@ -3352,7 +3475,7 @@ function createAppBridgeCore(config) {
|
|
|
3352
3475
|
return Array.from(bySpace.values());
|
|
3353
3476
|
}
|
|
3354
3477
|
function allowsOwnerAutoAuthorization() {
|
|
3355
|
-
return authorizationContext.surface === "background" || authorizationContext.surface === "app";
|
|
3478
|
+
return authorizationContext.surface === "background" || authorizationContext.surface === "app" || authorizationContext.surface === "overlay";
|
|
3356
3479
|
}
|
|
3357
3480
|
async function ensureBaseToken(forceRefresh = false) {
|
|
3358
3481
|
if (appToken && !forceRefresh) return appToken;
|
|
@@ -3683,7 +3806,18 @@ function createAppBridgeCore(config) {
|
|
|
3683
3806
|
}, true);
|
|
3684
3807
|
return;
|
|
3685
3808
|
}
|
|
3686
|
-
if (state.pendingAuth)
|
|
3809
|
+
if (state.pendingAuth) {
|
|
3810
|
+
if (isSameConsent(state.pendingAuth, {
|
|
3811
|
+
scopes,
|
|
3812
|
+
spaceId,
|
|
3813
|
+
selectSpace,
|
|
3814
|
+
createSpace
|
|
3815
|
+
})) {
|
|
3816
|
+
state.pendingAuth.joinedRequestIds = [...state.pendingAuth.joinedRequestIds ?? [], data.requestId];
|
|
3817
|
+
return;
|
|
3818
|
+
}
|
|
3819
|
+
dismissPendingAuth();
|
|
3820
|
+
}
|
|
3687
3821
|
if (createSpace) {
|
|
3688
3822
|
mintedSpace = null;
|
|
3689
3823
|
state.pendingAuth = {
|
|
@@ -3753,12 +3887,16 @@ function createAppBridgeCore(config) {
|
|
|
3753
3887
|
}, true);
|
|
3754
3888
|
}
|
|
3755
3889
|
}
|
|
3890
|
+
/** Answers the dialog's request and every request that joined it. */
|
|
3891
|
+
function replyPendingAuth(pending, payload) {
|
|
3892
|
+
for (const requestId of [pending.requestId, ...pending.joinedRequestIds ?? []]) replyForRequest(requestId, payload, true);
|
|
3893
|
+
}
|
|
3756
3894
|
function dismissPendingAuth() {
|
|
3757
3895
|
if (!state.pendingAuth) return;
|
|
3758
|
-
|
|
3896
|
+
replyPendingAuth(state.pendingAuth, {
|
|
3759
3897
|
type: "cohub.app.authorize.result",
|
|
3760
3898
|
token: null
|
|
3761
|
-
}
|
|
3899
|
+
});
|
|
3762
3900
|
state.pendingAuth = null;
|
|
3763
3901
|
state.authOpen = false;
|
|
3764
3902
|
state.authError = null;
|
|
@@ -3822,7 +3960,7 @@ function createAppBridgeCore(config) {
|
|
|
3822
3960
|
if (pending.createSpace) {
|
|
3823
3961
|
mintedSpace ??= await createViewerSpace(pending.createSpace);
|
|
3824
3962
|
if (!mintedSpace.provisioned) {
|
|
3825
|
-
|
|
3963
|
+
replyPendingAuth(pending, authorizeResult(null, mintedSpace.id, mintedSpace.name ?? pending.createSpace.name));
|
|
3826
3964
|
state.authOpen = false;
|
|
3827
3965
|
state.pendingAuth = null;
|
|
3828
3966
|
mintedSpace = null;
|
|
@@ -3834,7 +3972,7 @@ function createAppBridgeCore(config) {
|
|
|
3834
3972
|
const result = await authorize(pending.scopes, requestedSpaceId);
|
|
3835
3973
|
setGrantedAppScopes(await getViewerUuid(), app.id, result.scopes, result.spaceId);
|
|
3836
3974
|
if (pending.selectSpace || pending.createSpace) writeLastPickedSpace(result.spaceId);
|
|
3837
|
-
|
|
3975
|
+
replyPendingAuth(pending, authorizeResult(result.token, result.spaceId, spaceName));
|
|
3838
3976
|
state.authOpen = false;
|
|
3839
3977
|
state.pendingAuth = null;
|
|
3840
3978
|
mintedSpace = null;
|
|
@@ -4033,6 +4171,15 @@ var BoardExtensionRegistry = class {
|
|
|
4033
4171
|
const diagnostics = [];
|
|
4034
4172
|
const composition = parsed.data;
|
|
4035
4173
|
const cost = { ...ZERO_COST };
|
|
4174
|
+
for (const effect of input.effects ?? []) {
|
|
4175
|
+
diagnostics.push(...validateBuiltinBoardEffect(effect, `effects.${effect.id}`));
|
|
4176
|
+
if (!this.#extensions.has(`effect:${effect.kind}@${effect.kindVersion}`)) diagnostics.push({
|
|
4177
|
+
severity: "warning",
|
|
4178
|
+
code: "UNKNOWN_EFFECT",
|
|
4179
|
+
message: `No renderer is registered for ${effect.kind}@${effect.kindVersion}`,
|
|
4180
|
+
path: `effects.${effect.id}`
|
|
4181
|
+
});
|
|
4182
|
+
}
|
|
4036
4183
|
const events = [];
|
|
4037
4184
|
for (const clip of composition.timeline.clips) {
|
|
4038
4185
|
const definition = this.#extensions.get(`clip:${clip.kind}@${clip.kindVersion}`);
|
|
@@ -4066,7 +4213,10 @@ var BoardExtensionRegistry = class {
|
|
|
4066
4213
|
active[key] += event.cost[key] * event.direction;
|
|
4067
4214
|
cost[key] = Math.max(cost[key], active[key]);
|
|
4068
4215
|
}
|
|
4069
|
-
for (const effect of input.effects ?? [])
|
|
4216
|
+
for (const effect of input.effects ?? []) {
|
|
4217
|
+
const estimate = estimateBuiltinBoardEffectCost(effect);
|
|
4218
|
+
for (const key of Object.keys(cost)) cost[key] += estimate[key] ?? 0;
|
|
4219
|
+
}
|
|
4070
4220
|
const limits = input.limits ?? DEFAULT_BOARD_LIMITS;
|
|
4071
4221
|
for (const key of Object.keys(cost)) if (cost[key] > limits[key]) diagnostics.push({
|
|
4072
4222
|
severity: "warning",
|
|
@@ -4087,4 +4237,4 @@ function createBoardExtensionRegistry() {
|
|
|
4087
4237
|
}
|
|
4088
4238
|
const BOARD_CHANNELS = BOARD_ANIMATION_CHANNELS;
|
|
4089
4239
|
//#endregion
|
|
4090
|
-
export { APP_COMPOSER_CHIP_CONTENT_MAX_BYTES, APP_COMPOSER_CHIP_KEY_MAX_LENGTH, APP_COMPOSER_CHIP_LABEL_MAX_LENGTH, APP_SURFACE_READY_TIMEOUT_MS, APP_SURFACE_REQUEST_TIMEOUT_MS, AppCommerceApi, AppRealtimeApi, AppRefParseError, AppRoom, AppRuntimeApi, AppRuntimeApi as WorkRuntimeApi, AppSurfaceApi, AppsApi, BILLING_ACCESS_BLOCKED_ERROR_CODE, BOARD_ANIMATION_CHANNEL_CAPABILITIES, BOARD_CHANNELS, BOARD_COLOR_IDS, BOARD_GEO_KINDS, BillingApi, BoardAuthoringItemSchema, BoardClient, BoardCompositionInputSchema, BoardCompositionSchema, BoardEffectInputSchema, BoardEffectSchema, BoardExtensionRegistry, BoardItemPatchSchema, BoardPlaybackPolicySchema, BoardSemanticCommandSchema, COHUB_ENVIRONMENTS, COHUB_SOURCE_HEADER, COHUB_SOURCE_HEADER_NAMES, CohubClient, CohubHttpClient, DEFAULT_BOARD_LIMITS, DESKTOP_COMMAND_DEFAULT_TIMEOUT_MS, DESKTOP_COMMAND_MAX_TIMEOUT_MS, DESKTOP_COMMAND_PAYLOAD_MAX_BYTES, DESKTOP_COMMAND_PENDING_TTL_SECONDS, DESKTOP_COMMAND_SETTLEMENT_GRACE_SECONDS, DESKTOP_COMMAND_TERMINAL_TTL_SECONDS, DESKTOP_COMMAND_VERSION, DesktopCommandsApi, FEATURE_NOT_ENTITLED_ERROR_CODE, GenerationPolicyError, HttpError, PERMISSIONS, ParentBridgeTransport, PopupBrokerTransport, REQUEST_SOURCE_VIA_MAX_LENGTH, ReferencesApi, ReferralsApi, SessionGenerationStreamClient, SessionPatchReducer, SpacePublicFilesApi, UiCommandsApi, UsersApi, VoiceApi, VoiceInputClient, WebsocketClient, WorkCommerceApi, WorkRealtimeApi, WorkRefParseError, WorkRoom, WorkSurfaceApi, assertGenerationRequestAllowedByPolicy, attachAppEmbed, buildAppSurfaceRequest, buildSpaceInvitePath, buildSpacePath, clearGrantedAppScopes, compileComposition, composition, createAppBridgeCore, createAppBridgeCore as createWorkBridgeCore, createAppRuntime, createAppRuntime as createWorkRuntime, createBoardExtensionRegistry, createCohubClient, createHttpClient, createSessionGenerationStreamClient, createSessionPatchReducer, createSlugAppIdResolver, createSlugAppIdResolver as createSlugWorkIdResolver, createVoiceInputClient, createWebsocketClient, decodeGenerationPolicy, encodeGenerationPolicy, extractBillingPayload, filterDiscoverableGenerationModels, filterGenerationDeclarationsByPolicy, findGenerationModelPolicy, formatAppRef, formatWorkRef, getAllowedGenerationModelIds, getCohubContext, hasGrantedAppScopes, hasRequestSourceIdentity, isAppId, isBillingAccessBlockedCode, isBillingAccessBlockedError, isDesktopCallMethod, isFeatureNotEntitledError, isGenerationModelHidden, isHttpErrorCode, isRequestSourceClientId, isRequestSourceEmpty, isRequestSourceUuid, isTerminalDesktopCommandStatus, isUuid, isWorkId, joinApiUrl, matchesUnauthorizedErrorToken, mergeRequestSourceIntoMeta, normalizeBaseUrl, normalizeGenerationPolicy, normalizeRequestSource, normalizeVoiceInputWebsocketUrl, normalizeWebsocketUrl, parseAppRef, parseAppSurfaceReady, parseAppSurfaceResponse, parseAssistantMessageCommit, parseBoardCompositionInput, parseBoardEffectInput, parseBoardPlaybackPolicy, parseDesktopCommand, parseGenerationPolicyFromEnv, parseRequestSourceFromHeaders, parseWorkRef, proceduralClip, readRequestSourceFromEnv, requestSourceToHeaders, resolveApiBaseUrl, resolveAppTransport, resolveAppTransport as resolveWorkTransport, resolveCohubEnvironment, resolveExecutionAppId, resolveExecutionToken, resolveRequestSourceChannel, resolveVoiceInputWebsocketUrl, resolveWebsocketUrl, sampleCompositionTracks, sampleEasing, sampleTrack, sanitizeAccessToken, scopeListHasPermission, setGrantedAppScopes, track };
|
|
4240
|
+
export { APP_COMPOSER_CHIP_CONTENT_MAX_BYTES, APP_COMPOSER_CHIP_KEY_MAX_LENGTH, APP_COMPOSER_CHIP_LABEL_MAX_LENGTH, APP_SURFACE_READY_TIMEOUT_MS, APP_SURFACE_REQUEST_TIMEOUT_MS, AppCommerceApi, AppRealtimeApi, AppRefParseError, AppRoom, AppRuntimeApi, AppRuntimeApi as WorkRuntimeApi, AppSurfaceApi, AppsApi, BILLING_ACCESS_BLOCKED_ERROR_CODE, BOARD_ANIMATION_CHANNEL_CAPABILITIES, BOARD_CHANNELS, BOARD_COLOR_IDS, BOARD_GEO_KINDS, BillingApi, BoardAnimationSpecSchema, BoardAuthoringItemSchema, BoardClient, BoardCompositionInputSchema, BoardCompositionSchema, BoardDealParamsSchema, BoardEffectInputSchema, BoardEffectSchema, BoardExtensionRegistry, BoardItemPatchSchema, BoardPlaybackPolicySchema, BoardSemanticCommandSchema, COHUB_ENVIRONMENTS, COHUB_SOURCE_HEADER, COHUB_SOURCE_HEADER_NAMES, CohubClient, CohubHttpClient, DEFAULT_BOARD_LIMITS, DESKTOP_COMMAND_DEFAULT_TIMEOUT_MS, DESKTOP_COMMAND_MAX_TIMEOUT_MS, DESKTOP_COMMAND_PAYLOAD_MAX_BYTES, DESKTOP_COMMAND_PENDING_TTL_SECONDS, DESKTOP_COMMAND_SETTLEMENT_GRACE_SECONDS, DESKTOP_COMMAND_TERMINAL_TTL_SECONDS, DESKTOP_COMMAND_VERSION, DesktopCommandsApi, FEATURE_NOT_ENTITLED_ERROR_CODE, GenerationPolicyError, HttpError, PERMISSIONS, ParentBridgeTransport, PopupBrokerTransport, REQUEST_SOURCE_VIA_MAX_LENGTH, ReferencesApi, ReferralsApi, SessionGenerationStreamClient, SessionPatchReducer, SpacePublicFilesApi, UiCommandsApi, UsersApi, VoiceApi, VoiceInputClient, WebsocketClient, WorkCommerceApi, WorkRealtimeApi, WorkRefParseError, WorkRoom, WorkSurfaceApi, assertGenerationRequestAllowedByPolicy, attachAppEmbed, buildAppSurfaceRequest, buildSpaceInvitePath, buildSpacePath, clearGrantedAppScopes, compileComposition, composition, createAppBridgeCore, createAppBridgeCore as createWorkBridgeCore, createAppRuntime, createAppRuntime as createWorkRuntime, createBoardExtensionRegistry, createCohubClient, createHttpClient, createSessionGenerationStreamClient, createSessionPatchReducer, createSlugAppIdResolver, createSlugAppIdResolver as createSlugWorkIdResolver, createVoiceInputClient, createWebsocketClient, decodeGenerationPolicy, encodeGenerationPolicy, extractBillingPayload, filterDiscoverableGenerationModels, filterGenerationDeclarationsByPolicy, findGenerationModelPolicy, formatAppRef, formatWorkRef, getAllowedGenerationModelIds, getCohubContext, hasGrantedAppScopes, hasRequestSourceIdentity, isAppId, isBillingAccessBlockedCode, isBillingAccessBlockedError, isDesktopCallMethod, isFeatureNotEntitledError, isGenerationModelHidden, isHttpErrorCode, isRequestSourceClientId, isRequestSourceEmpty, isRequestSourceUuid, isTerminalDesktopCommandStatus, isUuid, isWorkId, joinApiUrl, matchesUnauthorizedErrorToken, mergeRequestSourceIntoMeta, normalizeBaseUrl, normalizeGenerationPolicy, normalizeRequestSource, normalizeVoiceInputWebsocketUrl, normalizeWebsocketUrl, parseAppRef, parseAppSurfaceReady, parseAppSurfaceResponse, parseAssistantMessageCommit, parseBoardCompositionInput, parseBoardEffectInput, parseBoardPlaybackPolicy, parseDesktopCommand, parseGenerationPolicyFromEnv, parseRequestSourceFromHeaders, parseWorkRef, proceduralClip, readRequestSourceFromEnv, requestSourceToHeaders, resolveApiBaseUrl, resolveAppTransport, resolveAppTransport as resolveWorkTransport, resolveCohubEnvironment, resolveExecutionAppId, resolveExecutionToken, resolveRequestSourceChannel, resolveVoiceInputWebsocketUrl, resolveWebsocketUrl, sampleCompositionTracks, sampleEasing, sampleTrack, sanitizeAccessToken, scopeListHasPermission, setGrantedAppScopes, track };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
//#region ../protocol/dist/board-animation.js
|
|
3
|
+
const extensionKindSchema = z.string().regex(/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)+$/).max(160);
|
|
4
|
+
const jsonObjectSchema = z.record(z.string(), z.unknown());
|
|
5
|
+
const finiteSchema = z.number().finite();
|
|
6
|
+
/** Parameters shared by the built-in deal entrance preset. */
|
|
7
|
+
const BoardDealParamsSchema = z.object({
|
|
8
|
+
lift: finiteSchema.nonnegative().max(2e3).optional(),
|
|
9
|
+
swing: finiteSchema.nonnegative().max(2e3).optional(),
|
|
10
|
+
curve: finiteSchema.nonnegative().max(2e3).optional(),
|
|
11
|
+
tilt: finiteSchema.nonnegative().max(180).optional(),
|
|
12
|
+
scale: finiteSchema.positive().max(2).optional(),
|
|
13
|
+
duration: finiteSchema.positive().max(1e4).optional(),
|
|
14
|
+
landing: finiteSchema.nonnegative().max(1e4).optional()
|
|
15
|
+
}).strict();
|
|
16
|
+
/** A versioned, reusable animation preset reference. */
|
|
17
|
+
const BoardAnimationSpecSchema = z.object({
|
|
18
|
+
kind: extensionKindSchema,
|
|
19
|
+
kindVersion: z.number().int().positive().default(1),
|
|
20
|
+
params: jsonObjectSchema.default({})
|
|
21
|
+
}).strict().superRefine((spec, context) => {
|
|
22
|
+
if (spec.kind !== "effects.deal" || spec.kindVersion !== 1) return;
|
|
23
|
+
const parsed = BoardDealParamsSchema.safeParse(spec.params);
|
|
24
|
+
if (parsed.success) return;
|
|
25
|
+
context.addIssue({
|
|
26
|
+
code: "custom",
|
|
27
|
+
message: parsed.error.issues[0]?.message ?? "invalid effects.deal parameters",
|
|
28
|
+
path: ["params", ...parsed.error.issues[0]?.path ?? []]
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
/** Board-wide default motion policies. Omitted policies mean no motion. */
|
|
32
|
+
const BoardMotionSchema = z.object({ enter: BoardAnimationSpecSchema.optional() }).strict();
|
|
33
|
+
//#endregion
|
|
34
|
+
export { BoardAnimationSpecSchema, BoardDealParamsSchema, BoardMotionSchema };
|
|
@@ -1140,10 +1140,11 @@ declare const BoardSemanticCommandSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
1140
1140
|
type: z.ZodLiteral<"board">;
|
|
1141
1141
|
}, z.core.$strict>], "type">;
|
|
1142
1142
|
kind: z.ZodString;
|
|
1143
|
-
kindVersion: z.ZodNumber
|
|
1143
|
+
kindVersion: z.ZodDefault<z.ZodNumber>;
|
|
1144
1144
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
1145
1145
|
lifecycle: z.ZodEnum<{
|
|
1146
1146
|
manual: "manual";
|
|
1147
|
+
"on-enter": "on-enter";
|
|
1147
1148
|
persistent: "persistent";
|
|
1148
1149
|
"when-visible": "when-visible";
|
|
1149
1150
|
}>;
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
import { BOARD_BUILTIN_CLIP_KINDS, BOARD_BUILTIN_EFFECT_KINDS, DEFAULT_BOARD_RENDER_LIMITS } from "./board-constants.js";
|
|
1
|
+
import { BOARD_BUILTIN_CAPABILITIES, BOARD_BUILTIN_CLIP_KINDS, BOARD_BUILTIN_EFFECT_KINDS, DEFAULT_BOARD_RENDER_LIMITS } from "./board-constants.js";
|
|
2
2
|
import { BoardCameraFocusParamsSchema } from "./board.js";
|
|
3
|
+
import { BoardDealParamsSchema } from "./board-animation.js";
|
|
3
4
|
//#region ../protocol/dist/board-capability-registry.js
|
|
4
5
|
const CLIPS = new Set(BOARD_BUILTIN_CLIP_KINDS);
|
|
5
|
-
new Set(BOARD_BUILTIN_EFFECT_KINDS);
|
|
6
|
+
const EFFECTS = new Set(BOARD_BUILTIN_EFFECT_KINDS);
|
|
7
|
+
const BUILTIN_VERSIONS = new Set(BOARD_BUILTIN_CAPABILITIES.map((c) => `${c.kind}:${c.id}@${c.version}`));
|
|
8
|
+
/**
|
|
9
|
+
* True when a built-in renderer exists for exactly this kind@version. A known
|
|
10
|
+
* kind at an unknown version is not built-in: it must not pass as one.
|
|
11
|
+
*/
|
|
12
|
+
function isBuiltinBoardCapability(kind, id, version) {
|
|
13
|
+
return BUILTIN_VERSIONS.has(`${kind}:${id}@${version}`);
|
|
14
|
+
}
|
|
6
15
|
const record = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
7
16
|
const finite = (value) => typeof value === "number" && Number.isFinite(value);
|
|
8
17
|
function validateBuiltinBoardClip(clip, path = "clip") {
|
|
@@ -36,6 +45,47 @@ function validateBuiltinBoardClip(clip, path = "clip") {
|
|
|
36
45
|
}
|
|
37
46
|
return errors;
|
|
38
47
|
}
|
|
48
|
+
function validateBuiltinBoardEffect(effect, path = "effect") {
|
|
49
|
+
const diagnostics = [];
|
|
50
|
+
if (effect.lifecycle === "on-enter") {
|
|
51
|
+
if (effect.target.type !== "item") diagnostics.push({
|
|
52
|
+
severity: "error",
|
|
53
|
+
code: "INVALID_BOARD_EFFECT",
|
|
54
|
+
message: "on-enter effects must target an item",
|
|
55
|
+
path: `${path}.target`
|
|
56
|
+
});
|
|
57
|
+
if (effect.timeOrigin !== "activation") diagnostics.push({
|
|
58
|
+
severity: "error",
|
|
59
|
+
code: "INVALID_BOARD_EFFECT",
|
|
60
|
+
message: "on-enter effects must use activation time",
|
|
61
|
+
path: `${path}.timeOrigin`
|
|
62
|
+
});
|
|
63
|
+
} else if (EFFECTS.has(effect.kind) && effect.target.type !== "item") diagnostics.push({
|
|
64
|
+
severity: "error",
|
|
65
|
+
code: "INVALID_BOARD_EFFECT",
|
|
66
|
+
message: `${effect.kind} must target an item`,
|
|
67
|
+
path: `${path}.target`
|
|
68
|
+
});
|
|
69
|
+
if (effect.kind === "effects.deal" && effect.kindVersion === 1) {
|
|
70
|
+
if (effect.lifecycle !== "on-enter") diagnostics.push({
|
|
71
|
+
severity: "error",
|
|
72
|
+
code: "INVALID_BOARD_EFFECT",
|
|
73
|
+
message: "effects.deal must use the on-enter lifecycle",
|
|
74
|
+
path: `${path}.lifecycle`
|
|
75
|
+
});
|
|
76
|
+
const parsed = BoardDealParamsSchema.safeParse(effect.params);
|
|
77
|
+
if (!parsed.success) diagnostics.push({
|
|
78
|
+
severity: "error",
|
|
79
|
+
code: "INVALID_BOARD_EFFECT",
|
|
80
|
+
message: parsed.error.issues[0]?.message ?? "invalid effects.deal parameters",
|
|
81
|
+
path: `${path}.params`
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return diagnostics;
|
|
85
|
+
}
|
|
86
|
+
function estimateBuiltinBoardEffectCost(effect) {
|
|
87
|
+
return isBuiltinBoardCapability("effect", effect.kind, effect.kindVersion) ? { drawCalls: 1 } : {};
|
|
88
|
+
}
|
|
39
89
|
function estimateBuiltinBoardClipCost(clip) {
|
|
40
90
|
switch (clip.kind) {
|
|
41
91
|
case "effects.particles": {
|
|
@@ -70,4 +120,4 @@ function estimateBuiltinBoardClipCost(clip) {
|
|
|
70
120
|
}
|
|
71
121
|
}
|
|
72
122
|
//#endregion
|
|
73
|
-
export { estimateBuiltinBoardClipCost, validateBuiltinBoardClip };
|
|
123
|
+
export { estimateBuiltinBoardClipCost, estimateBuiltinBoardEffectCost, isBuiltinBoardCapability, validateBuiltinBoardClip, validateBuiltinBoardEffect };
|