@neta-art/cohub 5.10.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -50
- package/dist/board/animation.d.ts +157 -67
- package/dist/board/animation.js +161 -306
- package/dist/board/core/connections.js +4 -4
- package/dist/board/core/export-plan.js +1 -1
- package/dist/board/core/shape-types.js +0 -1
- package/dist/board/geometry.js +4 -4
- package/dist/board/index.d.ts +8 -7
- package/dist/board/index.js +8 -9
- package/dist/board/mutation.d.ts +2 -17
- package/dist/board/mutation.js +2 -93
- package/dist/board/render/renderers/text-card-renderer.js +1 -1
- package/dist/board/semantic-document.d.ts +30 -0
- package/dist/board/semantic-document.js +271 -0
- package/dist/board/semantic-mutation.d.ts +10 -0
- package/dist/board/semantic-mutation.js +203 -0
- package/dist/chunks/http.d.ts +27 -95
- package/dist/chunks/http.js +628 -1610
- package/dist/chunks/transport.js +1 -1
- package/dist/chunks/websocket.d.ts +3462 -533
- package/dist/chunks/websocket.js +1 -1
- package/dist/http.d.ts +3 -3
- package/dist/index.d.ts +158 -299
- package/dist/index.js +1207 -499
- package/dist/protocol/dist/board-authoring.d.ts +1305 -0
- package/dist/protocol/dist/board-authoring.js +291 -0
- package/dist/protocol/dist/board-capability-registry.d.ts +2 -0
- package/dist/protocol/dist/board-capability-registry.js +74 -0
- package/dist/protocol/dist/board-codec.d.ts +2 -0
- package/dist/protocol/dist/board-codec.js +19 -0
- package/dist/protocol/dist/board-composition.d.ts +383 -0
- package/dist/protocol/dist/board-composition.js +310 -0
- package/dist/protocol/dist/board-connection.d.ts +16 -16
- package/dist/protocol/dist/board-connection.js +16 -16
- package/dist/protocol/dist/board-constants.js +0 -25
- package/dist/protocol/dist/board-document.d.ts +34 -3
- package/dist/protocol/dist/board-document.js +3 -1
- package/dist/protocol/dist/board-effect.d.ts +94 -0
- package/dist/protocol/dist/board-effect.js +53 -0
- package/dist/protocol/dist/board-json.js +16 -0
- package/dist/protocol/dist/board-node.d.ts +1 -12
- package/dist/protocol/dist/board-node.js +1 -81
- package/dist/protocol/dist/board.d.ts +42 -245
- package/dist/protocol/dist/board.js +56 -117
- package/dist/protocol/dist/index.d.ts +9 -4
- package/dist/types.d.ts +4 -1
- package/docs/work-runtime-guide.md +19 -3
- package/package.json +2 -2
- package/dist/board/codec.d.ts +0 -27
- package/dist/board/codec.js +0 -277
- package/dist/board/nodes.d.ts +0 -113
- package/dist/board/nodes.js +0 -154
- package/dist/protocol/dist/board-content.js +0 -26
- package/dist/protocol/dist/identifiers.js +0 -10
- package/dist/protocol/dist/index.js +0 -14
- package/dist/protocol/dist/provenance.js +0 -15
- package/dist/protocol/dist/public-identifiers.js +0 -38
- package/dist/protocol/dist/realtime/board-awareness.js +0 -119
- package/dist/protocol/dist/ui-command.js +0 -2
- package/dist/protocol/dist/work-promotion-stats.js +0 -11
- package/dist/protocol/dist/work-surface.js +0 -2
- package/dist/protocol/dist/work-view-stats.js +0 -3
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import "./board-constants.js";
|
|
2
|
+
import { BoardConnectionPatchSchema, BoardConnectionSchema } from "./board-connection.js";
|
|
3
|
+
import { BoardCompositionInputSchema } from "./board-composition.js";
|
|
4
|
+
import { BoardEffectInputSchema } from "./board-effect.js";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
//#region ../protocol/dist/board-authoring.js
|
|
7
|
+
const BOARD_AUTHORING_COLOR_IDS = [
|
|
8
|
+
"brand",
|
|
9
|
+
"neutral",
|
|
10
|
+
"black",
|
|
11
|
+
"white",
|
|
12
|
+
"blue",
|
|
13
|
+
"green",
|
|
14
|
+
"amber",
|
|
15
|
+
"violet",
|
|
16
|
+
"rose"
|
|
17
|
+
];
|
|
18
|
+
const BOARD_AUTHORING_GEO_KINDS = [
|
|
19
|
+
"rectangle",
|
|
20
|
+
"rounded",
|
|
21
|
+
"ellipse",
|
|
22
|
+
"diamond",
|
|
23
|
+
"triangle"
|
|
24
|
+
];
|
|
25
|
+
const idSchema = z.string().min(1).max(160);
|
|
26
|
+
const jsonObjectSchema = z.record(z.string(), z.unknown());
|
|
27
|
+
const finiteSchema = z.number().finite();
|
|
28
|
+
const extensionTypeSchema = z.string().regex(/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)+$/).max(160);
|
|
29
|
+
const BoardAuthoringFrameSchema = z.object({
|
|
30
|
+
x: finiteSchema,
|
|
31
|
+
y: finiteSchema,
|
|
32
|
+
width: finiteSchema.positive(),
|
|
33
|
+
height: finiteSchema.positive(),
|
|
34
|
+
rotation: finiteSchema.default(0)
|
|
35
|
+
}).strict();
|
|
36
|
+
const pointSchema = z.object({
|
|
37
|
+
x: finiteSchema,
|
|
38
|
+
y: finiteSchema,
|
|
39
|
+
p: finiteSchema.min(0).max(1).default(.5)
|
|
40
|
+
}).strict();
|
|
41
|
+
const worldPointSchema = z.object({
|
|
42
|
+
x: finiteSchema,
|
|
43
|
+
y: finiteSchema
|
|
44
|
+
}).strict();
|
|
45
|
+
const cropSchema = z.object({
|
|
46
|
+
x: finiteSchema.min(0).max(1),
|
|
47
|
+
y: finiteSchema.min(0).max(1),
|
|
48
|
+
w: finiteSchema.min(0).max(1),
|
|
49
|
+
h: finiteSchema.min(0).max(1)
|
|
50
|
+
}).strict();
|
|
51
|
+
const BoardItemStyleSchema = z.object({
|
|
52
|
+
color: z.enum(BOARD_AUTHORING_COLOR_IDS).optional(),
|
|
53
|
+
strokeWidth: finiteSchema.min(1).max(64).optional(),
|
|
54
|
+
fillOpacity: finiteSchema.min(0).max(1).optional()
|
|
55
|
+
}).strict();
|
|
56
|
+
const sourceSnapshotSchema = z.record(z.string(), z.unknown());
|
|
57
|
+
function isSafeBoardSourcePath(value) {
|
|
58
|
+
return value.length > 0 && value.length <= 4096 && !value.startsWith("/") && !value.startsWith("\\") && !value.includes("\\") && value.split("/").every((part) => part.length > 0 && part !== "." && part !== "..");
|
|
59
|
+
}
|
|
60
|
+
const BoardItemSourceSchema = z.object({
|
|
61
|
+
kind: z.literal("space-file"),
|
|
62
|
+
path: z.string().refine(isSafeBoardSourcePath, "source path must be a safe relative Board file path"),
|
|
63
|
+
snapshot: sourceSnapshotSchema.optional()
|
|
64
|
+
}).strict();
|
|
65
|
+
const baseFields = {
|
|
66
|
+
id: idSchema,
|
|
67
|
+
frame: BoardAuthoringFrameSchema,
|
|
68
|
+
parentId: idSchema.nullable().optional(),
|
|
69
|
+
locked: z.boolean().optional(),
|
|
70
|
+
metadata: jsonObjectSchema.optional()
|
|
71
|
+
};
|
|
72
|
+
const styledBaseFields = {
|
|
73
|
+
...baseFields,
|
|
74
|
+
style: BoardItemStyleSchema.optional()
|
|
75
|
+
};
|
|
76
|
+
const BoardTextAuthoringItemSchema = z.object({
|
|
77
|
+
...styledBaseFields,
|
|
78
|
+
type: z.literal("text"),
|
|
79
|
+
props: z.object({
|
|
80
|
+
text: z.string().default(""),
|
|
81
|
+
fontSize: finiteSchema.min(2).max(512).default(24)
|
|
82
|
+
}).strict()
|
|
83
|
+
}).strict();
|
|
84
|
+
const BoardGeoAuthoringItemSchema = z.object({
|
|
85
|
+
...styledBaseFields,
|
|
86
|
+
type: z.literal("geo"),
|
|
87
|
+
props: z.object({
|
|
88
|
+
shape: z.enum(BOARD_AUTHORING_GEO_KINDS).default("rectangle"),
|
|
89
|
+
text: z.string().default("")
|
|
90
|
+
}).strict()
|
|
91
|
+
}).strict();
|
|
92
|
+
const BoardDrawAuthoringItemSchema = z.object({
|
|
93
|
+
...styledBaseFields,
|
|
94
|
+
type: z.literal("draw"),
|
|
95
|
+
props: z.object({ points: z.array(pointSchema).min(1) }).strict()
|
|
96
|
+
}).strict();
|
|
97
|
+
const BoardArrowAuthoringItemSchema = z.object({
|
|
98
|
+
...styledBaseFields,
|
|
99
|
+
type: z.literal("arrow"),
|
|
100
|
+
props: z.object({
|
|
101
|
+
start: worldPointSchema,
|
|
102
|
+
end: worldPointSchema,
|
|
103
|
+
bend: finiteSchema.min(-.85).max(.85).default(0),
|
|
104
|
+
arrowStart: z.boolean().default(false),
|
|
105
|
+
arrowEnd: z.boolean().default(true),
|
|
106
|
+
label: z.string().default("")
|
|
107
|
+
}).strict()
|
|
108
|
+
}).strict();
|
|
109
|
+
const BoardFrameAuthoringItemSchema = z.object({
|
|
110
|
+
...styledBaseFields,
|
|
111
|
+
type: z.literal("frame"),
|
|
112
|
+
props: z.object({ label: z.string().default("Frame") }).strict()
|
|
113
|
+
}).strict();
|
|
114
|
+
const fileBackedFields = {
|
|
115
|
+
...baseFields,
|
|
116
|
+
style: z.object({}).strict().optional(),
|
|
117
|
+
source: BoardItemSourceSchema
|
|
118
|
+
};
|
|
119
|
+
const BoardImageAuthoringItemSchema = z.object({
|
|
120
|
+
...fileBackedFields,
|
|
121
|
+
type: z.literal("image"),
|
|
122
|
+
props: z.object({ crop: cropSchema.optional() }).strict()
|
|
123
|
+
}).strict();
|
|
124
|
+
const BoardVideoAuthoringItemSchema = z.object({
|
|
125
|
+
...fileBackedFields,
|
|
126
|
+
type: z.literal("video"),
|
|
127
|
+
props: z.object({}).strict()
|
|
128
|
+
}).strict();
|
|
129
|
+
const BoardAudioAuthoringItemSchema = z.object({
|
|
130
|
+
...fileBackedFields,
|
|
131
|
+
type: z.literal("audio"),
|
|
132
|
+
props: z.object({}).strict()
|
|
133
|
+
}).strict();
|
|
134
|
+
const BoardFileAuthoringItemSchema = z.object({
|
|
135
|
+
...fileBackedFields,
|
|
136
|
+
type: z.literal("file"),
|
|
137
|
+
props: z.object({}).strict()
|
|
138
|
+
}).strict();
|
|
139
|
+
const BoardTaskAuthoringItemSchema = z.object({
|
|
140
|
+
...baseFields,
|
|
141
|
+
type: z.literal("task"),
|
|
142
|
+
props: z.object({
|
|
143
|
+
taskRunId: z.string().min(1),
|
|
144
|
+
snapshot: z.record(z.string(), z.unknown())
|
|
145
|
+
}).strict(),
|
|
146
|
+
style: z.object({}).strict().optional()
|
|
147
|
+
}).strict();
|
|
148
|
+
const builtinItemSchemas = [
|
|
149
|
+
BoardTextAuthoringItemSchema,
|
|
150
|
+
BoardGeoAuthoringItemSchema,
|
|
151
|
+
BoardDrawAuthoringItemSchema,
|
|
152
|
+
BoardArrowAuthoringItemSchema,
|
|
153
|
+
BoardFrameAuthoringItemSchema,
|
|
154
|
+
BoardImageAuthoringItemSchema,
|
|
155
|
+
BoardVideoAuthoringItemSchema,
|
|
156
|
+
BoardAudioAuthoringItemSchema,
|
|
157
|
+
BoardFileAuthoringItemSchema,
|
|
158
|
+
BoardTaskAuthoringItemSchema
|
|
159
|
+
];
|
|
160
|
+
const BoardBuiltinAuthoringItemSchema = z.discriminatedUnion("type", builtinItemSchemas);
|
|
161
|
+
const BoardExtensionAuthoringItemSchema = z.object({
|
|
162
|
+
...baseFields,
|
|
163
|
+
type: extensionTypeSchema,
|
|
164
|
+
kindVersion: z.number().int().positive(),
|
|
165
|
+
props: jsonObjectSchema,
|
|
166
|
+
style: jsonObjectSchema.optional(),
|
|
167
|
+
source: z.object({
|
|
168
|
+
kind: z.string().min(1).max(80),
|
|
169
|
+
ref: z.string().min(1).max(4096),
|
|
170
|
+
snapshot: jsonObjectSchema.optional()
|
|
171
|
+
}).strict().optional()
|
|
172
|
+
}).strict();
|
|
173
|
+
const BoardAuthoringItemSchema = z.union([BoardBuiltinAuthoringItemSchema, BoardExtensionAuthoringItemSchema]);
|
|
174
|
+
const framePatchSchema = z.object({
|
|
175
|
+
x: finiteSchema.optional(),
|
|
176
|
+
y: finiteSchema.optional(),
|
|
177
|
+
width: finiteSchema.positive().optional(),
|
|
178
|
+
height: finiteSchema.positive().optional(),
|
|
179
|
+
rotation: finiteSchema.optional()
|
|
180
|
+
}).strict();
|
|
181
|
+
/** JSON Merge Patch semantics, constrained to the stable Item envelope. */
|
|
182
|
+
const BoardItemPatchSchema = z.object({
|
|
183
|
+
frame: framePatchSchema.optional(),
|
|
184
|
+
parentId: idSchema.nullable().optional(),
|
|
185
|
+
locked: z.boolean().nullable().optional(),
|
|
186
|
+
props: jsonObjectSchema.optional(),
|
|
187
|
+
style: jsonObjectSchema.nullable().optional(),
|
|
188
|
+
source: jsonObjectSchema.nullable().optional(),
|
|
189
|
+
metadata: jsonObjectSchema.nullable().optional()
|
|
190
|
+
}).strict().refine((patch) => Object.keys(patch).length > 0, "item patch is empty");
|
|
191
|
+
const BoardConnectionInputSchema = BoardConnectionSchema;
|
|
192
|
+
const stripServerFields = (value) => {
|
|
193
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
194
|
+
const { boardId: _boardId, revision: _revision, ...input } = value;
|
|
195
|
+
return input;
|
|
196
|
+
};
|
|
197
|
+
const BoardEffectCommandInputSchema = z.preprocess(stripServerFields, BoardEffectInputSchema);
|
|
198
|
+
const BoardCompositionCommandInputSchema = z.preprocess(stripServerFields, BoardCompositionInputSchema);
|
|
199
|
+
const BoardSemanticCommandSchema = z.discriminatedUnion("type", [
|
|
200
|
+
z.object({
|
|
201
|
+
type: z.literal("board.patch"),
|
|
202
|
+
patch: z.object({
|
|
203
|
+
title: z.string().min(1).max(255).optional(),
|
|
204
|
+
metadata: jsonObjectSchema.nullable().optional(),
|
|
205
|
+
metadataPatch: jsonObjectSchema.optional()
|
|
206
|
+
}).strict().refine((patch) => Object.keys(patch).length > 0, "board patch is empty")
|
|
207
|
+
}).strict(),
|
|
208
|
+
z.object({
|
|
209
|
+
type: z.literal("item.create"),
|
|
210
|
+
item: BoardAuthoringItemSchema
|
|
211
|
+
}).strict(),
|
|
212
|
+
z.object({
|
|
213
|
+
type: z.literal("item.patch"),
|
|
214
|
+
itemId: idSchema,
|
|
215
|
+
patch: BoardItemPatchSchema
|
|
216
|
+
}).strict(),
|
|
217
|
+
z.object({
|
|
218
|
+
type: z.literal("item.replace"),
|
|
219
|
+
itemId: idSchema,
|
|
220
|
+
item: BoardAuthoringItemSchema
|
|
221
|
+
}).strict(),
|
|
222
|
+
z.object({
|
|
223
|
+
type: z.literal("item.delete"),
|
|
224
|
+
itemId: idSchema,
|
|
225
|
+
cascade: z.boolean().default(false)
|
|
226
|
+
}).strict(),
|
|
227
|
+
z.object({
|
|
228
|
+
type: z.literal("item.reorder"),
|
|
229
|
+
itemId: idSchema,
|
|
230
|
+
index: z.number().int().nonnegative()
|
|
231
|
+
}).strict(),
|
|
232
|
+
z.object({
|
|
233
|
+
type: z.literal("connection.create"),
|
|
234
|
+
connection: BoardConnectionInputSchema
|
|
235
|
+
}).strict(),
|
|
236
|
+
z.object({
|
|
237
|
+
type: z.literal("connection.patch"),
|
|
238
|
+
connectionId: idSchema,
|
|
239
|
+
patch: BoardConnectionPatchSchema
|
|
240
|
+
}).strict(),
|
|
241
|
+
z.object({
|
|
242
|
+
type: z.literal("connection.delete"),
|
|
243
|
+
connectionId: idSchema
|
|
244
|
+
}).strict(),
|
|
245
|
+
z.object({
|
|
246
|
+
type: z.literal("effect.apply"),
|
|
247
|
+
effect: BoardEffectCommandInputSchema
|
|
248
|
+
}).strict(),
|
|
249
|
+
z.object({
|
|
250
|
+
type: z.literal("effect.delete"),
|
|
251
|
+
effectId: idSchema
|
|
252
|
+
}).strict(),
|
|
253
|
+
z.object({
|
|
254
|
+
type: z.literal("composition.apply"),
|
|
255
|
+
composition: BoardCompositionCommandInputSchema
|
|
256
|
+
}).strict(),
|
|
257
|
+
z.object({
|
|
258
|
+
type: z.literal("composition.delete"),
|
|
259
|
+
compositionId: idSchema
|
|
260
|
+
}).strict()
|
|
261
|
+
]);
|
|
262
|
+
const BoardSemanticMutationSchema = z.object({
|
|
263
|
+
mutationId: idSchema,
|
|
264
|
+
baseVersion: z.number().int().nonnegative(),
|
|
265
|
+
clientId: idSchema.optional(),
|
|
266
|
+
undoGroupId: idSchema.optional(),
|
|
267
|
+
/** Validate (including server-side reference checks) without writing. */
|
|
268
|
+
dryRun: z.boolean().default(false),
|
|
269
|
+
commands: z.array(BoardSemanticCommandSchema).min(1).max(5e4)
|
|
270
|
+
}).strict();
|
|
271
|
+
z.object({
|
|
272
|
+
include: z.array(z.enum([
|
|
273
|
+
"items",
|
|
274
|
+
"connections",
|
|
275
|
+
"effects",
|
|
276
|
+
"compositions",
|
|
277
|
+
"playback"
|
|
278
|
+
])).optional(),
|
|
279
|
+
itemIds: z.array(idSchema).max(5e4).optional(),
|
|
280
|
+
connectionIds: z.array(idSchema).max(5e4).optional(),
|
|
281
|
+
effectIds: z.array(idSchema).max(5e4).optional(),
|
|
282
|
+
compositionIds: z.array(idSchema).max(5e4).optional(),
|
|
283
|
+
viewport: z.object({
|
|
284
|
+
x: finiteSchema,
|
|
285
|
+
y: finiteSchema,
|
|
286
|
+
width: finiteSchema.positive(),
|
|
287
|
+
height: finiteSchema.positive()
|
|
288
|
+
}).optional()
|
|
289
|
+
}).strict();
|
|
290
|
+
//#endregion
|
|
291
|
+
export { BOARD_AUTHORING_COLOR_IDS, BOARD_AUTHORING_GEO_KINDS, BoardArrowAuthoringItemSchema, BoardAudioAuthoringItemSchema, BoardAuthoringItemSchema, BoardBuiltinAuthoringItemSchema, BoardDrawAuthoringItemSchema, BoardExtensionAuthoringItemSchema, BoardFileAuthoringItemSchema, BoardFrameAuthoringItemSchema, BoardGeoAuthoringItemSchema, BoardImageAuthoringItemSchema, BoardItemPatchSchema, BoardItemSourceSchema, BoardItemStyleSchema, BoardSemanticCommandSchema, BoardSemanticMutationSchema, BoardTaskAuthoringItemSchema, BoardTextAuthoringItemSchema, BoardVideoAuthoringItemSchema, isSafeBoardSourcePath };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { BOARD_BUILTIN_CLIP_KINDS, BOARD_BUILTIN_EFFECT_KINDS, DEFAULT_BOARD_RENDER_LIMITS } from "./board-constants.js";
|
|
2
|
+
import { BoardCameraFocusParamsSchema } from "./board.js";
|
|
3
|
+
//#region ../protocol/dist/board-capability-registry.js
|
|
4
|
+
const CLIPS = new Set(BOARD_BUILTIN_CLIP_KINDS);
|
|
5
|
+
new Set(BOARD_BUILTIN_EFFECT_KINDS);
|
|
6
|
+
const record = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
7
|
+
const finite = (value) => typeof value === "number" && Number.isFinite(value);
|
|
8
|
+
function validateBuiltinBoardClip(clip, path = "clip") {
|
|
9
|
+
if (!CLIPS.has(clip.kind)) return [];
|
|
10
|
+
const errors = [];
|
|
11
|
+
const error = (message, suffix, coordinateSpace, code = "INVALID_BOARD_CLIP") => {
|
|
12
|
+
errors.push({
|
|
13
|
+
severity: "error",
|
|
14
|
+
code,
|
|
15
|
+
message,
|
|
16
|
+
path: `${path}.${suffix}`,
|
|
17
|
+
...coordinateSpace ? { coordinateSpace } : {}
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
if ((clip.kind.startsWith("motion.") || clip.kind.startsWith("draw.") || clip.kind === "text.reveal" || clip.kind === "effects.trail") && clip.target.type !== "item") error(`${clip.kind} must target an item`, "target");
|
|
21
|
+
if (clip.kind.startsWith("camera.") && clip.target.type !== "camera") error(`${clip.kind} must target the camera`, "target");
|
|
22
|
+
if (clip.kind === "motion.path") {
|
|
23
|
+
const points = clip.params.points;
|
|
24
|
+
if (!Array.isArray(points) || points.length < 2 || points.length > 1e4) error("motion path must contain 2 to 10000 world-offset points", "params.points", "world-offset");
|
|
25
|
+
else for (const [index, point] of points.entries()) if (!record(point) || !finite(point.x) || !finite(point.y)) error("motion path point must contain finite x and y", `params.points.${index}`, "world-offset");
|
|
26
|
+
}
|
|
27
|
+
if (clip.kind === "effects.particles") {
|
|
28
|
+
const count = clip.params.count;
|
|
29
|
+
if (!Number.isSafeInteger(count) || count < 1 || count > DEFAULT_BOARD_RENDER_LIMITS.particles) error(`particle count must be an integer from 1 to ${DEFAULT_BOARD_RENDER_LIMITS.particles}`, "params.count", void 0, "INVALID_PARTICLE_COUNT");
|
|
30
|
+
const bounds = clip.params.bounds;
|
|
31
|
+
if (!record(bounds) || !finite(bounds.x) || !finite(bounds.y) || !finite(bounds.width) || !finite(bounds.height) || bounds.width <= 0 || bounds.height <= 0) error("particles require positive finite world bounds", "params.bounds", "world", "PARTICLE_BOUNDS_REQUIRED");
|
|
32
|
+
}
|
|
33
|
+
if (clip.kind === "camera.focus") {
|
|
34
|
+
const parsed = BoardCameraFocusParamsSchema.safeParse(clip.params);
|
|
35
|
+
if (!parsed.success) error(parsed.error.issues[0]?.message ?? "invalid camera focus", "params", "world");
|
|
36
|
+
}
|
|
37
|
+
return errors;
|
|
38
|
+
}
|
|
39
|
+
function estimateBuiltinBoardClipCost(clip) {
|
|
40
|
+
switch (clip.kind) {
|
|
41
|
+
case "effects.particles": {
|
|
42
|
+
const count = Number.isSafeInteger(clip.params.count) ? Math.max(0, clip.params.count) : 0;
|
|
43
|
+
return {
|
|
44
|
+
particles: count,
|
|
45
|
+
vertices: count * 4,
|
|
46
|
+
dynamicVertices: count * 4,
|
|
47
|
+
drawCalls: 1,
|
|
48
|
+
bufferBytes: count * 48,
|
|
49
|
+
simulationSteps: count
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
case "effects.trail": return {
|
|
53
|
+
vertices: 32,
|
|
54
|
+
dynamicVertices: 32,
|
|
55
|
+
drawCalls: 1,
|
|
56
|
+
bufferBytes: 1024,
|
|
57
|
+
simulationSteps: 16
|
|
58
|
+
};
|
|
59
|
+
case "effects.impact":
|
|
60
|
+
case "effects.flash": return {
|
|
61
|
+
vertices: 64,
|
|
62
|
+
drawCalls: 1
|
|
63
|
+
};
|
|
64
|
+
case "draw.reveal":
|
|
65
|
+
case "draw.handwrite": return {
|
|
66
|
+
drawCalls: 1,
|
|
67
|
+
dynamicVertices: 1
|
|
68
|
+
};
|
|
69
|
+
case "motion.path": return { simulationSteps: Array.isArray(clip.params.points) ? clip.params.points.length : 0 };
|
|
70
|
+
default: return {};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
export { estimateBuiltinBoardClipCost, validateBuiltinBoardClip };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BoardAuthoringItemSchema, BoardItemPatchSchema } from "./board-authoring.js";
|
|
2
|
+
//#region ../protocol/dist/board-codec.js
|
|
3
|
+
const isRecord = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
4
|
+
function applyBoardItemPatch(current, value) {
|
|
5
|
+
const merged = mergePatch(current, BoardItemPatchSchema.parse(value));
|
|
6
|
+
merged.id = current.id;
|
|
7
|
+
merged.type = current.type;
|
|
8
|
+
if ("kindVersion" in current) merged.kindVersion = current.kindVersion;
|
|
9
|
+
return BoardAuthoringItemSchema.parse(merged);
|
|
10
|
+
}
|
|
11
|
+
function mergePatch(current, patch) {
|
|
12
|
+
if (!isRecord(patch)) return patch;
|
|
13
|
+
const result = isRecord(current) ? { ...current } : {};
|
|
14
|
+
for (const [key, value] of Object.entries(patch)) if (value === null) delete result[key];
|
|
15
|
+
else result[key] = isRecord(value) ? mergePatch(result[key], value) : value;
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { applyBoardItemPatch };
|