@tutti-os/workbench-snapshot 0.0.208 → 0.0.210

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 CHANGED
@@ -9,3 +9,9 @@ helpers, and the published JSON schema at:
9
9
  ```text
10
10
  @tutti-os/workbench-snapshot/schema.json
11
11
  ```
12
+
13
+ Snapshots may include an additive `layoutBasis` containing the surface size and
14
+ layout constraints used to produce persisted frames. Workbench hosts use that
15
+ basis to restore window and space frames relative to a different surface.
16
+ Snapshots written before this field existed remain valid schema-version-1
17
+ snapshots and restore through the host's conservative legacy bounds policy.
package/dist/index.d.ts CHANGED
@@ -19,6 +19,7 @@ interface WorkbenchSnapshotV1 {
19
19
  activeNodeId?: string | null;
20
20
  spaces?: WorkbenchSnapshotSpaceV1[];
21
21
  activeSpaceId?: string | null;
22
+ layoutBasis?: WorkbenchSnapshotLayoutBasisV1;
22
23
  metadata?: Record<string, unknown>;
23
24
  }
24
25
  interface WorkbenchFrameV1 {
@@ -27,6 +28,26 @@ interface WorkbenchFrameV1 {
27
28
  width: number;
28
29
  height: number;
29
30
  }
31
+ interface WorkbenchSnapshotSizeV1 {
32
+ width: number;
33
+ height: number;
34
+ }
35
+ interface WorkbenchSnapshotSafeAreaV1 {
36
+ top: number;
37
+ right: number;
38
+ bottom: number;
39
+ left: number;
40
+ }
41
+ interface WorkbenchSnapshotLayoutConstraintsV1 {
42
+ minWidth: number;
43
+ minHeight: number;
44
+ surfacePadding: number;
45
+ safeArea: WorkbenchSnapshotSafeAreaV1;
46
+ }
47
+ interface WorkbenchSnapshotLayoutBasisV1 {
48
+ surfaceSize: WorkbenchSnapshotSizeV1;
49
+ layoutConstraints: WorkbenchSnapshotLayoutConstraintsV1;
50
+ }
30
51
  interface WorkbenchSnapshotNodeV1 {
31
52
  id: string;
32
53
  kind: string;
@@ -103,6 +124,9 @@ var properties = {
103
124
  "null"
104
125
  ]
105
126
  },
127
+ layoutBasis: {
128
+ $ref: "#/$defs/layoutBasis"
129
+ },
106
130
  metadata: {
107
131
  type: "object"
108
132
  }
@@ -134,6 +158,95 @@ var $defs = {
134
158
  }
135
159
  }
136
160
  },
161
+ size: {
162
+ type: "object",
163
+ additionalProperties: false,
164
+ required: [
165
+ "width",
166
+ "height"
167
+ ],
168
+ properties: {
169
+ width: {
170
+ type: "number",
171
+ exclusiveMinimum: 0
172
+ },
173
+ height: {
174
+ type: "number",
175
+ exclusiveMinimum: 0
176
+ }
177
+ }
178
+ },
179
+ safeArea: {
180
+ type: "object",
181
+ additionalProperties: false,
182
+ required: [
183
+ "top",
184
+ "right",
185
+ "bottom",
186
+ "left"
187
+ ],
188
+ properties: {
189
+ top: {
190
+ type: "number",
191
+ minimum: 0
192
+ },
193
+ right: {
194
+ type: "number",
195
+ minimum: 0
196
+ },
197
+ bottom: {
198
+ type: "number",
199
+ minimum: 0
200
+ },
201
+ left: {
202
+ type: "number",
203
+ minimum: 0
204
+ }
205
+ }
206
+ },
207
+ layoutConstraints: {
208
+ type: "object",
209
+ additionalProperties: false,
210
+ required: [
211
+ "minWidth",
212
+ "minHeight",
213
+ "surfacePadding",
214
+ "safeArea"
215
+ ],
216
+ properties: {
217
+ minWidth: {
218
+ type: "number",
219
+ minimum: 0
220
+ },
221
+ minHeight: {
222
+ type: "number",
223
+ minimum: 0
224
+ },
225
+ surfacePadding: {
226
+ type: "number",
227
+ minimum: 0
228
+ },
229
+ safeArea: {
230
+ $ref: "#/$defs/safeArea"
231
+ }
232
+ }
233
+ },
234
+ layoutBasis: {
235
+ type: "object",
236
+ additionalProperties: false,
237
+ required: [
238
+ "surfaceSize",
239
+ "layoutConstraints"
240
+ ],
241
+ properties: {
242
+ surfaceSize: {
243
+ $ref: "#/$defs/size"
244
+ },
245
+ layoutConstraints: {
246
+ $ref: "#/$defs/layoutConstraints"
247
+ }
248
+ }
249
+ },
137
250
  node: {
138
251
  type: "object",
139
252
  additionalProperties: false,
@@ -256,4 +369,4 @@ declare function validateWorkbenchSnapshot(value: unknown): WorkbenchSnapshotVal
256
369
  declare function assertValidWorkbenchSnapshot(value: unknown): asserts value is WorkbenchSnapshotV1;
257
370
  declare function formatWorkbenchSnapshotValidationIssues(issues: WorkbenchSnapshotValidationIssue[]): string;
258
371
 
259
- export { type WorkbenchFrame, type WorkbenchFrameV1, type WorkbenchSnapshot, type WorkbenchSnapshotDisplayModeV1, type WorkbenchSnapshotNode, type WorkbenchSnapshotNodeAdapterStateV1, type WorkbenchSnapshotNodeV1, type WorkbenchSnapshotSchemaVersion, type WorkbenchSnapshotSpaceV1, type WorkbenchSnapshotV1, type WorkbenchSnapshotValidationIssue, type WorkbenchSnapshotValidationResult, assertValidWorkbenchSnapshot, formatWorkbenchSnapshotValidationIssues, migrateWorkbenchSnapshot, normalizeWorkbenchSnapshot, parseWorkbenchSnapshot, serializeWorkbenchSnapshot, validateWorkbenchSnapshot, schema as workbenchSnapshotJsonSchema, workbenchSnapshotLimits, workbenchSnapshotSchemaVersion };
372
+ export { type WorkbenchFrame, type WorkbenchFrameV1, type WorkbenchSnapshot, type WorkbenchSnapshotDisplayModeV1, type WorkbenchSnapshotLayoutBasisV1, type WorkbenchSnapshotLayoutConstraintsV1, type WorkbenchSnapshotNode, type WorkbenchSnapshotNodeAdapterStateV1, type WorkbenchSnapshotNodeV1, type WorkbenchSnapshotSafeAreaV1, type WorkbenchSnapshotSchemaVersion, type WorkbenchSnapshotSizeV1, type WorkbenchSnapshotSpaceV1, type WorkbenchSnapshotV1, type WorkbenchSnapshotValidationIssue, type WorkbenchSnapshotValidationResult, assertValidWorkbenchSnapshot, formatWorkbenchSnapshotValidationIssues, migrateWorkbenchSnapshot, normalizeWorkbenchSnapshot, parseWorkbenchSnapshot, serializeWorkbenchSnapshot, validateWorkbenchSnapshot, schema as workbenchSnapshotJsonSchema, workbenchSnapshotLimits, workbenchSnapshotSchemaVersion };
package/dist/index.js CHANGED
@@ -34,6 +34,7 @@ function validateWorkbenchSnapshot(value) {
34
34
  "activeNodeId",
35
35
  "spaces",
36
36
  "activeSpaceId",
37
+ "layoutBasis",
37
38
  "metadata"
38
39
  ],
39
40
  issues
@@ -65,6 +66,9 @@ function validateWorkbenchSnapshot(value) {
65
66
  }
66
67
  }
67
68
  validateOptionalStringOrNull(value.activeSpaceId, "activeSpaceId", issues);
69
+ if (value.layoutBasis !== void 0) {
70
+ validateLayoutBasis(value.layoutBasis, "layoutBasis", issues);
71
+ }
68
72
  const serializedBytes = serializedByteLength(value);
69
73
  if (serializedBytes > workbenchSnapshotLimits.maxSerializedBytes) {
70
74
  issues.push({
@@ -249,6 +253,85 @@ function validateFrame(value, path, issues) {
249
253
  });
250
254
  }
251
255
  }
256
+ function validateLayoutBasis(value, path, issues) {
257
+ if (!isRecord(value)) {
258
+ issues.push({ path, message: "layout basis must be an object" });
259
+ return;
260
+ }
261
+ validateAllowedKeys(
262
+ value,
263
+ path,
264
+ ["surfaceSize", "layoutConstraints"],
265
+ issues
266
+ );
267
+ validateSize(value.surfaceSize, `${path}.surfaceSize`, issues);
268
+ validateLayoutConstraints(
269
+ value.layoutConstraints,
270
+ `${path}.layoutConstraints`,
271
+ issues
272
+ );
273
+ }
274
+ function validateSize(value, path, issues) {
275
+ if (!isRecord(value)) {
276
+ issues.push({ path, message: "size must be an object" });
277
+ return;
278
+ }
279
+ validateAllowedKeys(value, path, ["width", "height"], issues);
280
+ validatePositiveFiniteNumber(value.width, `${path}.width`, issues);
281
+ validatePositiveFiniteNumber(value.height, `${path}.height`, issues);
282
+ }
283
+ function validateLayoutConstraints(value, path, issues) {
284
+ if (!isRecord(value)) {
285
+ issues.push({ path, message: "layout constraints must be an object" });
286
+ return;
287
+ }
288
+ validateAllowedKeys(
289
+ value,
290
+ path,
291
+ ["minWidth", "minHeight", "surfacePadding", "safeArea"],
292
+ issues
293
+ );
294
+ validateNonNegativeFiniteNumber(value.minWidth, `${path}.minWidth`, issues);
295
+ validateNonNegativeFiniteNumber(value.minHeight, `${path}.minHeight`, issues);
296
+ validateNonNegativeFiniteNumber(
297
+ value.surfacePadding,
298
+ `${path}.surfacePadding`,
299
+ issues
300
+ );
301
+ const safeAreaPath = `${path}.safeArea`;
302
+ if (!isRecord(value.safeArea)) {
303
+ issues.push({
304
+ path: safeAreaPath,
305
+ message: "safe area must be an object"
306
+ });
307
+ return;
308
+ }
309
+ validateAllowedKeys(
310
+ value.safeArea,
311
+ safeAreaPath,
312
+ ["top", "right", "bottom", "left"],
313
+ issues
314
+ );
315
+ for (const edge of ["top", "right", "bottom", "left"]) {
316
+ validateNonNegativeFiniteNumber(
317
+ value.safeArea[edge],
318
+ `${safeAreaPath}.${edge}`,
319
+ issues
320
+ );
321
+ }
322
+ }
323
+ function validatePositiveFiniteNumber(value, path, issues) {
324
+ validateFiniteNumber(value, path, issues);
325
+ if (typeof value === "number" && Number.isFinite(value) && value <= 0) {
326
+ issues.push({ path, message: "value must be greater than zero" });
327
+ }
328
+ }
329
+ function validateNonNegativeFiniteNumber(value, path, issues) {
330
+ validateFiniteNumber(value, path, issues);
331
+ if (typeof value === "number" && Number.isFinite(value) && value < 0) {
332
+ issues.push({ path, message: "value must be non-negative" });
333
+ }
334
+ }
252
335
  function validateFiniteNumber(value, path, issues) {
253
336
  if (typeof value !== "number" || !Number.isFinite(value)) {
254
337
  issues.push({ path, message: "value must be a finite number" });
@@ -303,6 +386,7 @@ function normalizeWorkbenchSnapshot(value) {
303
386
  activeNodeId,
304
387
  spaces,
305
388
  activeSpaceId,
389
+ layoutBasis: value.layoutBasis ? normalizeLayoutBasis(value.layoutBasis) : void 0,
306
390
  metadata: value.metadata
307
391
  });
308
392
  }
@@ -349,6 +433,27 @@ function normalizeFrame(frame) {
349
433
  )
350
434
  };
351
435
  }
436
+ function normalizeLayoutBasis(layoutBasis) {
437
+ return {
438
+ surfaceSize: {
439
+ width: normalizeNumber(layoutBasis.surfaceSize.width),
440
+ height: normalizeNumber(layoutBasis.surfaceSize.height)
441
+ },
442
+ layoutConstraints: {
443
+ minWidth: normalizeNumber(layoutBasis.layoutConstraints.minWidth),
444
+ minHeight: normalizeNumber(layoutBasis.layoutConstraints.minHeight),
445
+ surfacePadding: normalizeNumber(
446
+ layoutBasis.layoutConstraints.surfacePadding
447
+ ),
448
+ safeArea: {
449
+ top: normalizeNumber(layoutBasis.layoutConstraints.safeArea.top),
450
+ right: normalizeNumber(layoutBasis.layoutConstraints.safeArea.right),
451
+ bottom: normalizeNumber(layoutBasis.layoutConstraints.safeArea.bottom),
452
+ left: normalizeNumber(layoutBasis.layoutConstraints.safeArea.left)
453
+ }
454
+ }
455
+ };
456
+ }
352
457
  function normalizeNumber(value) {
353
458
  return Object.is(value, -0) ? 0 : Number(value.toFixed(3));
354
459
  }
@@ -408,6 +513,7 @@ var schema_default = {
408
513
  items: { $ref: "#/$defs/space" }
409
514
  },
410
515
  activeSpaceId: { type: ["string", "null"] },
516
+ layoutBasis: { $ref: "#/$defs/layoutBasis" },
411
517
  metadata: { type: "object" }
412
518
  },
413
519
  $defs: {
@@ -422,6 +528,46 @@ var schema_default = {
422
528
  height: { type: "number", minimum: 120 }
423
529
  }
424
530
  },
531
+ size: {
532
+ type: "object",
533
+ additionalProperties: false,
534
+ required: ["width", "height"],
535
+ properties: {
536
+ width: { type: "number", exclusiveMinimum: 0 },
537
+ height: { type: "number", exclusiveMinimum: 0 }
538
+ }
539
+ },
540
+ safeArea: {
541
+ type: "object",
542
+ additionalProperties: false,
543
+ required: ["top", "right", "bottom", "left"],
544
+ properties: {
545
+ top: { type: "number", minimum: 0 },
546
+ right: { type: "number", minimum: 0 },
547
+ bottom: { type: "number", minimum: 0 },
548
+ left: { type: "number", minimum: 0 }
549
+ }
550
+ },
551
+ layoutConstraints: {
552
+ type: "object",
553
+ additionalProperties: false,
554
+ required: ["minWidth", "minHeight", "surfacePadding", "safeArea"],
555
+ properties: {
556
+ minWidth: { type: "number", minimum: 0 },
557
+ minHeight: { type: "number", minimum: 0 },
558
+ surfacePadding: { type: "number", minimum: 0 },
559
+ safeArea: { $ref: "#/$defs/safeArea" }
560
+ }
561
+ },
562
+ layoutBasis: {
563
+ type: "object",
564
+ additionalProperties: false,
565
+ required: ["surfaceSize", "layoutConstraints"],
566
+ properties: {
567
+ surfaceSize: { $ref: "#/$defs/size" },
568
+ layoutConstraints: { $ref: "#/$defs/layoutConstraints" }
569
+ }
570
+ },
425
571
  node: {
426
572
  type: "object",
427
573
  additionalProperties: false,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/limits.ts","../src/types.ts","../src/validate.ts","../src/normalize.ts","../src/migrate.ts","../src/schema.json","../src/serialize.ts"],"sourcesContent":["export const workbenchSnapshotLimits = {\n maxSerializedBytes: 512 * 1024,\n maxNodes: 128,\n maxNodeIDLength: 160,\n maxKindLength: 120,\n maxTitleLength: 240,\n minFrameWidth: 160,\n minFrameHeight: 120,\n maxFrameCoordinate: 1_000_000,\n maxFrameSize: 1_000_000\n} as const;\n","export const workbenchSnapshotSchemaVersion = 1 as const;\n\nexport type WorkbenchSnapshotSchemaVersion =\n typeof workbenchSnapshotSchemaVersion;\n\nexport interface WorkbenchSnapshotV1 {\n schemaVersion: WorkbenchSnapshotSchemaVersion;\n nodes: WorkbenchSnapshotNodeV1[];\n nodeStack?: string[];\n activeNodeId?: string | null;\n spaces?: WorkbenchSnapshotSpaceV1[];\n activeSpaceId?: string | null;\n metadata?: Record<string, unknown>;\n}\n\nexport interface WorkbenchFrameV1 {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface WorkbenchSnapshotNodeV1 {\n id: string;\n kind: string;\n title: string;\n frame: WorkbenchFrameV1;\n displayMode?: WorkbenchSnapshotDisplayModeV1;\n restoreFrame?: WorkbenchFrameV1 | null;\n isMinimized?: boolean;\n minimizedAtUnixMs?: number | null;\n data?: unknown;\n adapterState?: WorkbenchSnapshotNodeAdapterStateV1;\n}\n\nexport type WorkbenchSnapshotDisplayModeV1 = \"floating\" | \"fullscreen\";\n\nexport interface WorkbenchSnapshotNodeAdapterStateV1 {\n [key: string]: unknown;\n}\n\nexport interface WorkbenchSnapshotSpaceV1 {\n id: string;\n name: string;\n nodeIds: string[];\n frame?: WorkbenchFrameV1 | null;\n data?: unknown;\n}\n\nexport type WorkbenchSnapshot = WorkbenchSnapshotV1;\nexport type WorkbenchSnapshotNode = WorkbenchSnapshotNodeV1;\nexport type WorkbenchFrame = WorkbenchFrameV1;\n","import { workbenchSnapshotLimits } from \"./limits.ts\";\nimport {\n workbenchSnapshotSchemaVersion,\n type WorkbenchFrameV1,\n type WorkbenchSnapshotDisplayModeV1,\n type WorkbenchSnapshotV1\n} from \"./types.ts\";\n\nexport interface WorkbenchSnapshotValidationIssue {\n path: string;\n message: string;\n}\n\nexport interface WorkbenchSnapshotValidationResult {\n ok: boolean;\n issues: WorkbenchSnapshotValidationIssue[];\n}\n\nconst displayModes = new Set<WorkbenchSnapshotDisplayModeV1>([\n \"floating\",\n \"fullscreen\"\n]);\n\nexport function validateWorkbenchSnapshot(\n value: unknown\n): WorkbenchSnapshotValidationResult {\n const issues: WorkbenchSnapshotValidationIssue[] = [];\n\n if (!isRecord(value)) {\n return issue(\"snapshot\", \"snapshot must be an object\");\n }\n validateAllowedKeys(\n value,\n \"snapshot\",\n [\n \"schemaVersion\",\n \"nodes\",\n \"nodeStack\",\n \"activeNodeId\",\n \"spaces\",\n \"activeSpaceId\",\n \"metadata\"\n ],\n issues\n );\n\n if (value.schemaVersion !== workbenchSnapshotSchemaVersion) {\n issues.push({\n path: \"schemaVersion\",\n message: \"unsupported workbench snapshot schema version\"\n });\n }\n\n if (!Array.isArray(value.nodes)) {\n issues.push({ path: \"nodes\", message: \"nodes must be an array\" });\n } else {\n if (value.nodes.length > workbenchSnapshotLimits.maxNodes) {\n issues.push({\n path: \"nodes\",\n message: `nodes must contain at most ${workbenchSnapshotLimits.maxNodes} items`\n });\n }\n validateNodes(value.nodes, issues);\n }\n\n validateStringArray(value.nodeStack, \"nodeStack\", issues, true);\n validateOptionalStringOrNull(value.activeNodeId, \"activeNodeId\", issues);\n\n if (value.spaces !== undefined) {\n if (!Array.isArray(value.spaces)) {\n issues.push({ path: \"spaces\", message: \"spaces must be an array\" });\n } else {\n validateSpaces(value.spaces, issues);\n }\n }\n\n validateOptionalStringOrNull(value.activeSpaceId, \"activeSpaceId\", issues);\n\n const serializedBytes = serializedByteLength(value);\n if (serializedBytes > workbenchSnapshotLimits.maxSerializedBytes) {\n issues.push({\n path: \"snapshot\",\n message: `snapshot must serialize to at most ${workbenchSnapshotLimits.maxSerializedBytes} bytes`\n });\n }\n\n return { ok: issues.length === 0, issues };\n}\n\nexport function assertValidWorkbenchSnapshot(\n value: unknown\n): asserts value is WorkbenchSnapshotV1 {\n const result = validateWorkbenchSnapshot(value);\n if (!result.ok) {\n throw new Error(formatWorkbenchSnapshotValidationIssues(result.issues));\n }\n}\n\nexport function formatWorkbenchSnapshotValidationIssues(\n issues: WorkbenchSnapshotValidationIssue[]\n): string {\n if (issues.length === 0) {\n return \"workbench snapshot is valid\";\n }\n\n return issues.map((item) => `${item.path}: ${item.message}`).join(\"; \");\n}\n\nfunction validateNodes(\n nodes: unknown[],\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n const ids = new Set<string>();\n\n nodes.forEach((node, index) => {\n const path = `nodes[${index}]`;\n if (!isRecord(node)) {\n issues.push({ path, message: \"node must be an object\" });\n return;\n }\n validateAllowedKeys(\n node,\n path,\n [\n \"id\",\n \"kind\",\n \"title\",\n \"frame\",\n \"displayMode\",\n \"restoreFrame\",\n \"isMinimized\",\n \"minimizedAtUnixMs\",\n \"data\",\n \"adapterState\"\n ],\n issues\n );\n\n const id = validateRequiredString(node.id, `${path}.id`, issues, {\n maxLength: workbenchSnapshotLimits.maxNodeIDLength\n });\n if (id) {\n if (ids.has(id)) {\n issues.push({ path: `${path}.id`, message: \"node id must be unique\" });\n }\n ids.add(id);\n }\n\n validateRequiredString(node.kind, `${path}.kind`, issues, {\n maxLength: workbenchSnapshotLimits.maxKindLength\n });\n validateRequiredString(node.title, `${path}.title`, issues, {\n allowEmpty: true,\n maxLength: workbenchSnapshotLimits.maxTitleLength\n });\n validateFrame(node.frame, `${path}.frame`, issues);\n\n if (\n node.displayMode !== undefined &&\n !displayModes.has(node.displayMode as WorkbenchSnapshotDisplayModeV1)\n ) {\n issues.push({\n path: `${path}.displayMode`,\n message: \"displayMode must be floating or fullscreen\"\n });\n }\n\n if (node.restoreFrame !== undefined && node.restoreFrame !== null) {\n validateFrame(node.restoreFrame, `${path}.restoreFrame`, issues);\n }\n\n if (\n node.isMinimized !== undefined &&\n typeof node.isMinimized !== \"boolean\"\n ) {\n issues.push({\n path: `${path}.isMinimized`,\n message: \"isMinimized must be a boolean\"\n });\n }\n\n validateOptionalNonNegativeIntegerOrNull(\n node.minimizedAtUnixMs,\n `${path}.minimizedAtUnixMs`,\n issues\n );\n });\n}\n\nfunction validateSpaces(\n spaces: unknown[],\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n spaces.forEach((space, index) => {\n const path = `spaces[${index}]`;\n if (!isRecord(space)) {\n issues.push({ path, message: \"space must be an object\" });\n return;\n }\n validateAllowedKeys(\n space,\n path,\n [\"id\", \"name\", \"nodeIds\", \"frame\", \"data\"],\n issues\n );\n\n validateRequiredString(space.id, `${path}.id`, issues);\n validateRequiredString(space.name, `${path}.name`, issues, {\n allowEmpty: true\n });\n validateStringArray(space.nodeIds, `${path}.nodeIds`, issues, false);\n\n if (space.frame !== undefined && space.frame !== null) {\n validateFrame(space.frame, `${path}.frame`, issues);\n }\n });\n}\n\nfunction validateRequiredString(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[],\n options: { allowEmpty?: boolean; maxLength?: number } = {}\n): string | null {\n if (typeof value !== \"string\") {\n issues.push({ path, message: \"value must be a string\" });\n return null;\n }\n\n const trimmed = value.trim();\n if (!options.allowEmpty && trimmed === \"\") {\n issues.push({ path, message: \"value must not be empty\" });\n return null;\n }\n\n if (options.maxLength !== undefined && value.length > options.maxLength) {\n issues.push({\n path,\n message: `value must be at most ${options.maxLength} characters`\n });\n }\n\n return trimmed;\n}\n\nfunction validateStringArray(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[],\n optional: boolean\n): void {\n if (value === undefined && optional) {\n return;\n }\n if (!Array.isArray(value)) {\n issues.push({ path, message: \"value must be an array\" });\n return;\n }\n\n value.forEach((item, index) => {\n if (typeof item !== \"string\" || item.trim() === \"\") {\n issues.push({\n path: `${path}[${index}]`,\n message: \"value must be a non-empty string\"\n });\n }\n });\n}\n\nfunction validateOptionalStringOrNull(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n if (value === undefined || value === null || typeof value === \"string\") {\n return;\n }\n issues.push({ path, message: \"value must be a string or null\" });\n}\n\nfunction validateOptionalNonNegativeIntegerOrNull(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n if (value === undefined || value === null) {\n return;\n }\n if (typeof value !== \"number\" || !Number.isInteger(value) || value < 0) {\n issues.push({\n path,\n message: \"value must be a non-negative integer or null\"\n });\n }\n}\n\nfunction validateFrame(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n if (!isRecord(value)) {\n issues.push({ path, message: \"frame must be an object\" });\n return;\n }\n validateAllowedKeys(value, path, [\"x\", \"y\", \"width\", \"height\"], issues);\n\n validateFiniteNumber(value.x, `${path}.x`, issues);\n validateFiniteNumber(value.y, `${path}.y`, issues);\n validateFiniteNumber(value.width, `${path}.width`, issues);\n validateFiniteNumber(value.height, `${path}.height`, issues);\n\n const frame = value as Partial<WorkbenchFrameV1>;\n if (\n typeof frame.width === \"number\" &&\n frame.width < workbenchSnapshotLimits.minFrameWidth\n ) {\n issues.push({\n path: `${path}.width`,\n message: `width must be at least ${workbenchSnapshotLimits.minFrameWidth}`\n });\n }\n if (\n typeof frame.height === \"number\" &&\n frame.height < workbenchSnapshotLimits.minFrameHeight\n ) {\n issues.push({\n path: `${path}.height`,\n message: `height must be at least ${workbenchSnapshotLimits.minFrameHeight}`\n });\n }\n}\n\nfunction validateFiniteNumber(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n issues.push({ path, message: \"value must be a finite number\" });\n }\n}\n\nfunction validateAllowedKeys(\n value: Record<string, unknown>,\n path: string,\n allowedKeys: string[],\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n const allowed = new Set(allowedKeys);\n for (const key of Object.keys(value)) {\n if (!allowed.has(key)) {\n issues.push({\n path: `${path}.${key}`,\n message: \"field is not part of the workbench snapshot contract\"\n });\n }\n }\n}\n\nfunction serializedByteLength(value: unknown): number {\n try {\n return new TextEncoder().encode(JSON.stringify(value)).byteLength;\n } catch {\n return Number.POSITIVE_INFINITY;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction issue(\n path: string,\n message: string\n): WorkbenchSnapshotValidationResult {\n return { ok: false, issues: [{ path, message }] };\n}\n","import { workbenchSnapshotLimits } from \"./limits.ts\";\nimport {\n workbenchSnapshotSchemaVersion,\n type WorkbenchFrameV1,\n type WorkbenchSnapshotNodeV1,\n type WorkbenchSnapshotSpaceV1,\n type WorkbenchSnapshotV1\n} from \"./types.ts\";\nimport { assertValidWorkbenchSnapshot } from \"./validate.ts\";\n\nexport function normalizeWorkbenchSnapshot(\n value: WorkbenchSnapshotV1\n): WorkbenchSnapshotV1 {\n assertValidWorkbenchSnapshot(value);\n\n const nodes = value.nodes.map(normalizeNode).sort(compareByID);\n const nodeIDs = new Set(nodes.map((node) => node.id));\n const nodeStack = uniqueStrings(value.nodeStack ?? []).filter((id) =>\n nodeIDs.has(id)\n );\n\n for (const node of nodes) {\n if (!nodeStack.includes(node.id)) {\n nodeStack.push(node.id);\n }\n }\n\n const activeNodeId =\n value.activeNodeId && nodeIDs.has(value.activeNodeId)\n ? value.activeNodeId\n : (nodeStack.at(-1) ?? null);\n\n const spaces = value.spaces?.map(normalizeSpace).sort(compareByID);\n const spaceIDs = new Set(spaces?.map((space) => space.id) ?? []);\n const activeSpaceId =\n value.activeSpaceId && spaceIDs.has(value.activeSpaceId)\n ? value.activeSpaceId\n : (spaces?.[0]?.id ?? null);\n\n return stripUndefined({\n schemaVersion: workbenchSnapshotSchemaVersion,\n nodes,\n nodeStack,\n activeNodeId,\n spaces,\n activeSpaceId,\n metadata: value.metadata\n });\n}\n\nfunction normalizeNode(node: WorkbenchSnapshotNodeV1): WorkbenchSnapshotNodeV1 {\n return stripUndefined({\n id: node.id.trim(),\n kind: node.kind.trim(),\n title: node.title,\n frame: normalizeFrame(node.frame),\n displayMode: node.displayMode ?? \"floating\",\n restoreFrame: node.restoreFrame ? normalizeFrame(node.restoreFrame) : null,\n isMinimized: node.isMinimized ?? false,\n minimizedAtUnixMs: normalizeMinimizedAtUnixMs(node),\n data: node.data,\n adapterState: node.adapterState\n });\n}\n\nfunction normalizeMinimizedAtUnixMs(\n node: WorkbenchSnapshotNodeV1\n): number | null | undefined {\n if (node.isMinimized !== true) {\n return undefined;\n }\n return node.minimizedAtUnixMs ?? undefined;\n}\n\nfunction normalizeSpace(\n space: WorkbenchSnapshotSpaceV1\n): WorkbenchSnapshotSpaceV1 {\n return stripUndefined({\n id: space.id.trim(),\n name: space.name,\n nodeIds: uniqueStrings(space.nodeIds),\n frame: space.frame ? normalizeFrame(space.frame) : null,\n data: space.data\n });\n}\n\nfunction normalizeFrame(frame: WorkbenchFrameV1): WorkbenchFrameV1 {\n return {\n x: normalizeNumber(frame.x),\n y: normalizeNumber(frame.y),\n width: Math.max(\n workbenchSnapshotLimits.minFrameWidth,\n normalizeNumber(frame.width)\n ),\n height: Math.max(\n workbenchSnapshotLimits.minFrameHeight,\n normalizeNumber(frame.height)\n )\n };\n}\n\nfunction normalizeNumber(value: number): number {\n return Object.is(value, -0) ? 0 : Number(value.toFixed(3));\n}\n\nfunction compareByID<T extends { id: string }>(left: T, right: T): number {\n return left.id.localeCompare(right.id);\n}\n\nfunction uniqueStrings(values: string[]): string[] {\n return Array.from(\n new Set(values.map((value) => value.trim()).filter(Boolean))\n );\n}\n\nfunction stripUndefined<T extends Record<string, unknown>>(value: T): T {\n return Object.fromEntries(\n Object.entries(value).filter(([, entryValue]) => entryValue !== undefined)\n ) as T;\n}\n","import {\n workbenchSnapshotSchemaVersion,\n type WorkbenchSnapshotV1\n} from \"./types.ts\";\nimport { normalizeWorkbenchSnapshot } from \"./normalize.ts\";\nimport { assertValidWorkbenchSnapshot } from \"./validate.ts\";\n\nexport function migrateWorkbenchSnapshot(value: unknown): WorkbenchSnapshotV1 {\n if (!isRecord(value)) {\n throw new Error(\"workbench snapshot must be an object\");\n }\n\n if (value.schemaVersion === workbenchSnapshotSchemaVersion) {\n assertValidWorkbenchSnapshot(value);\n return normalizeWorkbenchSnapshot(value);\n }\n\n throw new Error(\n `unsupported workbench snapshot schema version: ${String(value.schemaVersion)}`\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n","{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://tutti.local/schemas/workbench-snapshot.v1.json\",\n \"title\": \"WorkbenchSnapshotV1\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"schemaVersion\", \"nodes\"],\n \"properties\": {\n \"schemaVersion\": { \"const\": 1 },\n \"nodes\": {\n \"type\": \"array\",\n \"maxItems\": 128,\n \"items\": { \"$ref\": \"#/$defs/node\" }\n },\n \"nodeStack\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\", \"minLength\": 1 }\n },\n \"activeNodeId\": { \"type\": [\"string\", \"null\"] },\n \"spaces\": {\n \"type\": \"array\",\n \"items\": { \"$ref\": \"#/$defs/space\" }\n },\n \"activeSpaceId\": { \"type\": [\"string\", \"null\"] },\n \"metadata\": { \"type\": \"object\" }\n },\n \"$defs\": {\n \"frame\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"x\", \"y\", \"width\", \"height\"],\n \"properties\": {\n \"x\": { \"type\": \"number\" },\n \"y\": { \"type\": \"number\" },\n \"width\": { \"type\": \"number\", \"minimum\": 160 },\n \"height\": { \"type\": \"number\", \"minimum\": 120 }\n }\n },\n \"node\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"id\", \"kind\", \"title\", \"frame\"],\n \"properties\": {\n \"id\": { \"type\": \"string\", \"minLength\": 1, \"maxLength\": 160 },\n \"kind\": { \"type\": \"string\", \"minLength\": 1, \"maxLength\": 120 },\n \"title\": { \"type\": \"string\", \"maxLength\": 240 },\n \"frame\": { \"$ref\": \"#/$defs/frame\" },\n \"displayMode\": { \"enum\": [\"floating\", \"fullscreen\"] },\n \"restoreFrame\": {\n \"anyOf\": [{ \"$ref\": \"#/$defs/frame\" }, { \"type\": \"null\" }]\n },\n \"isMinimized\": { \"type\": \"boolean\" },\n \"minimizedAtUnixMs\": {\n \"type\": [\"integer\", \"null\"],\n \"minimum\": 0\n },\n \"data\": true,\n \"adapterState\": { \"type\": \"object\" }\n }\n },\n \"space\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"id\", \"name\", \"nodeIds\"],\n \"properties\": {\n \"id\": { \"type\": \"string\", \"minLength\": 1 },\n \"name\": { \"type\": \"string\" },\n \"nodeIds\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\", \"minLength\": 1 }\n },\n \"frame\": {\n \"anyOf\": [{ \"$ref\": \"#/$defs/frame\" }, { \"type\": \"null\" }]\n },\n \"data\": true\n }\n }\n }\n}\n","import { migrateWorkbenchSnapshot } from \"./migrate.ts\";\nimport { normalizeWorkbenchSnapshot } from \"./normalize.ts\";\nimport type { WorkbenchSnapshotV1 } from \"./types.ts\";\nimport { assertValidWorkbenchSnapshot } from \"./validate.ts\";\n\nexport function serializeWorkbenchSnapshot(\n snapshot: WorkbenchSnapshotV1\n): string {\n const normalized = normalizeWorkbenchSnapshot(snapshot);\n assertValidWorkbenchSnapshot(normalized);\n return JSON.stringify(normalized);\n}\n\nexport function parseWorkbenchSnapshot(\n serialized: string\n): WorkbenchSnapshotV1 {\n const parsed = JSON.parse(serialized) as unknown;\n return migrateWorkbenchSnapshot(parsed);\n}\n"],"mappings":"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","names":["isRecord"]}
1
+ {"version":3,"sources":["../src/limits.ts","../src/types.ts","../src/validate.ts","../src/normalize.ts","../src/migrate.ts","../src/schema.json","../src/serialize.ts"],"sourcesContent":["export const workbenchSnapshotLimits = {\n maxSerializedBytes: 512 * 1024,\n maxNodes: 128,\n maxNodeIDLength: 160,\n maxKindLength: 120,\n maxTitleLength: 240,\n minFrameWidth: 160,\n minFrameHeight: 120,\n maxFrameCoordinate: 1_000_000,\n maxFrameSize: 1_000_000\n} as const;\n","export const workbenchSnapshotSchemaVersion = 1 as const;\n\nexport type WorkbenchSnapshotSchemaVersion =\n typeof workbenchSnapshotSchemaVersion;\n\nexport interface WorkbenchSnapshotV1 {\n schemaVersion: WorkbenchSnapshotSchemaVersion;\n nodes: WorkbenchSnapshotNodeV1[];\n nodeStack?: string[];\n activeNodeId?: string | null;\n spaces?: WorkbenchSnapshotSpaceV1[];\n activeSpaceId?: string | null;\n layoutBasis?: WorkbenchSnapshotLayoutBasisV1;\n metadata?: Record<string, unknown>;\n}\n\nexport interface WorkbenchFrameV1 {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface WorkbenchSnapshotSizeV1 {\n width: number;\n height: number;\n}\n\nexport interface WorkbenchSnapshotSafeAreaV1 {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\nexport interface WorkbenchSnapshotLayoutConstraintsV1 {\n minWidth: number;\n minHeight: number;\n surfacePadding: number;\n safeArea: WorkbenchSnapshotSafeAreaV1;\n}\n\nexport interface WorkbenchSnapshotLayoutBasisV1 {\n surfaceSize: WorkbenchSnapshotSizeV1;\n layoutConstraints: WorkbenchSnapshotLayoutConstraintsV1;\n}\n\nexport interface WorkbenchSnapshotNodeV1 {\n id: string;\n kind: string;\n title: string;\n frame: WorkbenchFrameV1;\n displayMode?: WorkbenchSnapshotDisplayModeV1;\n restoreFrame?: WorkbenchFrameV1 | null;\n isMinimized?: boolean;\n minimizedAtUnixMs?: number | null;\n data?: unknown;\n adapterState?: WorkbenchSnapshotNodeAdapterStateV1;\n}\n\nexport type WorkbenchSnapshotDisplayModeV1 = \"floating\" | \"fullscreen\";\n\nexport interface WorkbenchSnapshotNodeAdapterStateV1 {\n [key: string]: unknown;\n}\n\nexport interface WorkbenchSnapshotSpaceV1 {\n id: string;\n name: string;\n nodeIds: string[];\n frame?: WorkbenchFrameV1 | null;\n data?: unknown;\n}\n\nexport type WorkbenchSnapshot = WorkbenchSnapshotV1;\nexport type WorkbenchSnapshotNode = WorkbenchSnapshotNodeV1;\nexport type WorkbenchFrame = WorkbenchFrameV1;\n","import { workbenchSnapshotLimits } from \"./limits.ts\";\nimport {\n workbenchSnapshotSchemaVersion,\n type WorkbenchFrameV1,\n type WorkbenchSnapshotDisplayModeV1,\n type WorkbenchSnapshotV1\n} from \"./types.ts\";\n\nexport interface WorkbenchSnapshotValidationIssue {\n path: string;\n message: string;\n}\n\nexport interface WorkbenchSnapshotValidationResult {\n ok: boolean;\n issues: WorkbenchSnapshotValidationIssue[];\n}\n\nconst displayModes = new Set<WorkbenchSnapshotDisplayModeV1>([\n \"floating\",\n \"fullscreen\"\n]);\n\nexport function validateWorkbenchSnapshot(\n value: unknown\n): WorkbenchSnapshotValidationResult {\n const issues: WorkbenchSnapshotValidationIssue[] = [];\n\n if (!isRecord(value)) {\n return issue(\"snapshot\", \"snapshot must be an object\");\n }\n validateAllowedKeys(\n value,\n \"snapshot\",\n [\n \"schemaVersion\",\n \"nodes\",\n \"nodeStack\",\n \"activeNodeId\",\n \"spaces\",\n \"activeSpaceId\",\n \"layoutBasis\",\n \"metadata\"\n ],\n issues\n );\n\n if (value.schemaVersion !== workbenchSnapshotSchemaVersion) {\n issues.push({\n path: \"schemaVersion\",\n message: \"unsupported workbench snapshot schema version\"\n });\n }\n\n if (!Array.isArray(value.nodes)) {\n issues.push({ path: \"nodes\", message: \"nodes must be an array\" });\n } else {\n if (value.nodes.length > workbenchSnapshotLimits.maxNodes) {\n issues.push({\n path: \"nodes\",\n message: `nodes must contain at most ${workbenchSnapshotLimits.maxNodes} items`\n });\n }\n validateNodes(value.nodes, issues);\n }\n\n validateStringArray(value.nodeStack, \"nodeStack\", issues, true);\n validateOptionalStringOrNull(value.activeNodeId, \"activeNodeId\", issues);\n\n if (value.spaces !== undefined) {\n if (!Array.isArray(value.spaces)) {\n issues.push({ path: \"spaces\", message: \"spaces must be an array\" });\n } else {\n validateSpaces(value.spaces, issues);\n }\n }\n\n validateOptionalStringOrNull(value.activeSpaceId, \"activeSpaceId\", issues);\n\n if (value.layoutBasis !== undefined) {\n validateLayoutBasis(value.layoutBasis, \"layoutBasis\", issues);\n }\n\n const serializedBytes = serializedByteLength(value);\n if (serializedBytes > workbenchSnapshotLimits.maxSerializedBytes) {\n issues.push({\n path: \"snapshot\",\n message: `snapshot must serialize to at most ${workbenchSnapshotLimits.maxSerializedBytes} bytes`\n });\n }\n\n return { ok: issues.length === 0, issues };\n}\n\nexport function assertValidWorkbenchSnapshot(\n value: unknown\n): asserts value is WorkbenchSnapshotV1 {\n const result = validateWorkbenchSnapshot(value);\n if (!result.ok) {\n throw new Error(formatWorkbenchSnapshotValidationIssues(result.issues));\n }\n}\n\nexport function formatWorkbenchSnapshotValidationIssues(\n issues: WorkbenchSnapshotValidationIssue[]\n): string {\n if (issues.length === 0) {\n return \"workbench snapshot is valid\";\n }\n\n return issues.map((item) => `${item.path}: ${item.message}`).join(\"; \");\n}\n\nfunction validateNodes(\n nodes: unknown[],\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n const ids = new Set<string>();\n\n nodes.forEach((node, index) => {\n const path = `nodes[${index}]`;\n if (!isRecord(node)) {\n issues.push({ path, message: \"node must be an object\" });\n return;\n }\n validateAllowedKeys(\n node,\n path,\n [\n \"id\",\n \"kind\",\n \"title\",\n \"frame\",\n \"displayMode\",\n \"restoreFrame\",\n \"isMinimized\",\n \"minimizedAtUnixMs\",\n \"data\",\n \"adapterState\"\n ],\n issues\n );\n\n const id = validateRequiredString(node.id, `${path}.id`, issues, {\n maxLength: workbenchSnapshotLimits.maxNodeIDLength\n });\n if (id) {\n if (ids.has(id)) {\n issues.push({ path: `${path}.id`, message: \"node id must be unique\" });\n }\n ids.add(id);\n }\n\n validateRequiredString(node.kind, `${path}.kind`, issues, {\n maxLength: workbenchSnapshotLimits.maxKindLength\n });\n validateRequiredString(node.title, `${path}.title`, issues, {\n allowEmpty: true,\n maxLength: workbenchSnapshotLimits.maxTitleLength\n });\n validateFrame(node.frame, `${path}.frame`, issues);\n\n if (\n node.displayMode !== undefined &&\n !displayModes.has(node.displayMode as WorkbenchSnapshotDisplayModeV1)\n ) {\n issues.push({\n path: `${path}.displayMode`,\n message: \"displayMode must be floating or fullscreen\"\n });\n }\n\n if (node.restoreFrame !== undefined && node.restoreFrame !== null) {\n validateFrame(node.restoreFrame, `${path}.restoreFrame`, issues);\n }\n\n if (\n node.isMinimized !== undefined &&\n typeof node.isMinimized !== \"boolean\"\n ) {\n issues.push({\n path: `${path}.isMinimized`,\n message: \"isMinimized must be a boolean\"\n });\n }\n\n validateOptionalNonNegativeIntegerOrNull(\n node.minimizedAtUnixMs,\n `${path}.minimizedAtUnixMs`,\n issues\n );\n });\n}\n\nfunction validateSpaces(\n spaces: unknown[],\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n spaces.forEach((space, index) => {\n const path = `spaces[${index}]`;\n if (!isRecord(space)) {\n issues.push({ path, message: \"space must be an object\" });\n return;\n }\n validateAllowedKeys(\n space,\n path,\n [\"id\", \"name\", \"nodeIds\", \"frame\", \"data\"],\n issues\n );\n\n validateRequiredString(space.id, `${path}.id`, issues);\n validateRequiredString(space.name, `${path}.name`, issues, {\n allowEmpty: true\n });\n validateStringArray(space.nodeIds, `${path}.nodeIds`, issues, false);\n\n if (space.frame !== undefined && space.frame !== null) {\n validateFrame(space.frame, `${path}.frame`, issues);\n }\n });\n}\n\nfunction validateRequiredString(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[],\n options: { allowEmpty?: boolean; maxLength?: number } = {}\n): string | null {\n if (typeof value !== \"string\") {\n issues.push({ path, message: \"value must be a string\" });\n return null;\n }\n\n const trimmed = value.trim();\n if (!options.allowEmpty && trimmed === \"\") {\n issues.push({ path, message: \"value must not be empty\" });\n return null;\n }\n\n if (options.maxLength !== undefined && value.length > options.maxLength) {\n issues.push({\n path,\n message: `value must be at most ${options.maxLength} characters`\n });\n }\n\n return trimmed;\n}\n\nfunction validateStringArray(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[],\n optional: boolean\n): void {\n if (value === undefined && optional) {\n return;\n }\n if (!Array.isArray(value)) {\n issues.push({ path, message: \"value must be an array\" });\n return;\n }\n\n value.forEach((item, index) => {\n if (typeof item !== \"string\" || item.trim() === \"\") {\n issues.push({\n path: `${path}[${index}]`,\n message: \"value must be a non-empty string\"\n });\n }\n });\n}\n\nfunction validateOptionalStringOrNull(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n if (value === undefined || value === null || typeof value === \"string\") {\n return;\n }\n issues.push({ path, message: \"value must be a string or null\" });\n}\n\nfunction validateOptionalNonNegativeIntegerOrNull(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n if (value === undefined || value === null) {\n return;\n }\n if (typeof value !== \"number\" || !Number.isInteger(value) || value < 0) {\n issues.push({\n path,\n message: \"value must be a non-negative integer or null\"\n });\n }\n}\n\nfunction validateFrame(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n if (!isRecord(value)) {\n issues.push({ path, message: \"frame must be an object\" });\n return;\n }\n validateAllowedKeys(value, path, [\"x\", \"y\", \"width\", \"height\"], issues);\n\n validateFiniteNumber(value.x, `${path}.x`, issues);\n validateFiniteNumber(value.y, `${path}.y`, issues);\n validateFiniteNumber(value.width, `${path}.width`, issues);\n validateFiniteNumber(value.height, `${path}.height`, issues);\n\n const frame = value as Partial<WorkbenchFrameV1>;\n if (\n typeof frame.width === \"number\" &&\n frame.width < workbenchSnapshotLimits.minFrameWidth\n ) {\n issues.push({\n path: `${path}.width`,\n message: `width must be at least ${workbenchSnapshotLimits.minFrameWidth}`\n });\n }\n if (\n typeof frame.height === \"number\" &&\n frame.height < workbenchSnapshotLimits.minFrameHeight\n ) {\n issues.push({\n path: `${path}.height`,\n message: `height must be at least ${workbenchSnapshotLimits.minFrameHeight}`\n });\n }\n}\n\nfunction validateLayoutBasis(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n if (!isRecord(value)) {\n issues.push({ path, message: \"layout basis must be an object\" });\n return;\n }\n validateAllowedKeys(\n value,\n path,\n [\"surfaceSize\", \"layoutConstraints\"],\n issues\n );\n validateSize(value.surfaceSize, `${path}.surfaceSize`, issues);\n validateLayoutConstraints(\n value.layoutConstraints,\n `${path}.layoutConstraints`,\n issues\n );\n}\n\nfunction validateSize(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n if (!isRecord(value)) {\n issues.push({ path, message: \"size must be an object\" });\n return;\n }\n validateAllowedKeys(value, path, [\"width\", \"height\"], issues);\n validatePositiveFiniteNumber(value.width, `${path}.width`, issues);\n validatePositiveFiniteNumber(value.height, `${path}.height`, issues);\n}\n\nfunction validateLayoutConstraints(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n if (!isRecord(value)) {\n issues.push({ path, message: \"layout constraints must be an object\" });\n return;\n }\n validateAllowedKeys(\n value,\n path,\n [\"minWidth\", \"minHeight\", \"surfacePadding\", \"safeArea\"],\n issues\n );\n validateNonNegativeFiniteNumber(value.minWidth, `${path}.minWidth`, issues);\n validateNonNegativeFiniteNumber(value.minHeight, `${path}.minHeight`, issues);\n validateNonNegativeFiniteNumber(\n value.surfacePadding,\n `${path}.surfacePadding`,\n issues\n );\n\n const safeAreaPath = `${path}.safeArea`;\n if (!isRecord(value.safeArea)) {\n issues.push({\n path: safeAreaPath,\n message: \"safe area must be an object\"\n });\n return;\n }\n validateAllowedKeys(\n value.safeArea,\n safeAreaPath,\n [\"top\", \"right\", \"bottom\", \"left\"],\n issues\n );\n for (const edge of [\"top\", \"right\", \"bottom\", \"left\"] as const) {\n validateNonNegativeFiniteNumber(\n value.safeArea[edge],\n `${safeAreaPath}.${edge}`,\n issues\n );\n }\n}\n\nfunction validatePositiveFiniteNumber(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n validateFiniteNumber(value, path, issues);\n if (typeof value === \"number\" && Number.isFinite(value) && value <= 0) {\n issues.push({ path, message: \"value must be greater than zero\" });\n }\n}\n\nfunction validateNonNegativeFiniteNumber(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n validateFiniteNumber(value, path, issues);\n if (typeof value === \"number\" && Number.isFinite(value) && value < 0) {\n issues.push({ path, message: \"value must be non-negative\" });\n }\n}\n\nfunction validateFiniteNumber(\n value: unknown,\n path: string,\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n issues.push({ path, message: \"value must be a finite number\" });\n }\n}\n\nfunction validateAllowedKeys(\n value: Record<string, unknown>,\n path: string,\n allowedKeys: string[],\n issues: WorkbenchSnapshotValidationIssue[]\n): void {\n const allowed = new Set(allowedKeys);\n for (const key of Object.keys(value)) {\n if (!allowed.has(key)) {\n issues.push({\n path: `${path}.${key}`,\n message: \"field is not part of the workbench snapshot contract\"\n });\n }\n }\n}\n\nfunction serializedByteLength(value: unknown): number {\n try {\n return new TextEncoder().encode(JSON.stringify(value)).byteLength;\n } catch {\n return Number.POSITIVE_INFINITY;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction issue(\n path: string,\n message: string\n): WorkbenchSnapshotValidationResult {\n return { ok: false, issues: [{ path, message }] };\n}\n","import { workbenchSnapshotLimits } from \"./limits.ts\";\nimport {\n workbenchSnapshotSchemaVersion,\n type WorkbenchFrameV1,\n type WorkbenchSnapshotLayoutBasisV1,\n type WorkbenchSnapshotNodeV1,\n type WorkbenchSnapshotSpaceV1,\n type WorkbenchSnapshotV1\n} from \"./types.ts\";\nimport { assertValidWorkbenchSnapshot } from \"./validate.ts\";\n\nexport function normalizeWorkbenchSnapshot(\n value: WorkbenchSnapshotV1\n): WorkbenchSnapshotV1 {\n assertValidWorkbenchSnapshot(value);\n\n const nodes = value.nodes.map(normalizeNode).sort(compareByID);\n const nodeIDs = new Set(nodes.map((node) => node.id));\n const nodeStack = uniqueStrings(value.nodeStack ?? []).filter((id) =>\n nodeIDs.has(id)\n );\n\n for (const node of nodes) {\n if (!nodeStack.includes(node.id)) {\n nodeStack.push(node.id);\n }\n }\n\n const activeNodeId =\n value.activeNodeId && nodeIDs.has(value.activeNodeId)\n ? value.activeNodeId\n : (nodeStack.at(-1) ?? null);\n\n const spaces = value.spaces?.map(normalizeSpace).sort(compareByID);\n const spaceIDs = new Set(spaces?.map((space) => space.id) ?? []);\n const activeSpaceId =\n value.activeSpaceId && spaceIDs.has(value.activeSpaceId)\n ? value.activeSpaceId\n : (spaces?.[0]?.id ?? null);\n\n return stripUndefined({\n schemaVersion: workbenchSnapshotSchemaVersion,\n nodes,\n nodeStack,\n activeNodeId,\n spaces,\n activeSpaceId,\n layoutBasis: value.layoutBasis\n ? normalizeLayoutBasis(value.layoutBasis)\n : undefined,\n metadata: value.metadata\n });\n}\n\nfunction normalizeNode(node: WorkbenchSnapshotNodeV1): WorkbenchSnapshotNodeV1 {\n return stripUndefined({\n id: node.id.trim(),\n kind: node.kind.trim(),\n title: node.title,\n frame: normalizeFrame(node.frame),\n displayMode: node.displayMode ?? \"floating\",\n restoreFrame: node.restoreFrame ? normalizeFrame(node.restoreFrame) : null,\n isMinimized: node.isMinimized ?? false,\n minimizedAtUnixMs: normalizeMinimizedAtUnixMs(node),\n data: node.data,\n adapterState: node.adapterState\n });\n}\n\nfunction normalizeMinimizedAtUnixMs(\n node: WorkbenchSnapshotNodeV1\n): number | null | undefined {\n if (node.isMinimized !== true) {\n return undefined;\n }\n return node.minimizedAtUnixMs ?? undefined;\n}\n\nfunction normalizeSpace(\n space: WorkbenchSnapshotSpaceV1\n): WorkbenchSnapshotSpaceV1 {\n return stripUndefined({\n id: space.id.trim(),\n name: space.name,\n nodeIds: uniqueStrings(space.nodeIds),\n frame: space.frame ? normalizeFrame(space.frame) : null,\n data: space.data\n });\n}\n\nfunction normalizeFrame(frame: WorkbenchFrameV1): WorkbenchFrameV1 {\n return {\n x: normalizeNumber(frame.x),\n y: normalizeNumber(frame.y),\n width: Math.max(\n workbenchSnapshotLimits.minFrameWidth,\n normalizeNumber(frame.width)\n ),\n height: Math.max(\n workbenchSnapshotLimits.minFrameHeight,\n normalizeNumber(frame.height)\n )\n };\n}\n\nfunction normalizeLayoutBasis(\n layoutBasis: WorkbenchSnapshotLayoutBasisV1\n): WorkbenchSnapshotLayoutBasisV1 {\n return {\n surfaceSize: {\n width: normalizeNumber(layoutBasis.surfaceSize.width),\n height: normalizeNumber(layoutBasis.surfaceSize.height)\n },\n layoutConstraints: {\n minWidth: normalizeNumber(layoutBasis.layoutConstraints.minWidth),\n minHeight: normalizeNumber(layoutBasis.layoutConstraints.minHeight),\n surfacePadding: normalizeNumber(\n layoutBasis.layoutConstraints.surfacePadding\n ),\n safeArea: {\n top: normalizeNumber(layoutBasis.layoutConstraints.safeArea.top),\n right: normalizeNumber(layoutBasis.layoutConstraints.safeArea.right),\n bottom: normalizeNumber(layoutBasis.layoutConstraints.safeArea.bottom),\n left: normalizeNumber(layoutBasis.layoutConstraints.safeArea.left)\n }\n }\n };\n}\n\nfunction normalizeNumber(value: number): number {\n return Object.is(value, -0) ? 0 : Number(value.toFixed(3));\n}\n\nfunction compareByID<T extends { id: string }>(left: T, right: T): number {\n return left.id.localeCompare(right.id);\n}\n\nfunction uniqueStrings(values: string[]): string[] {\n return Array.from(\n new Set(values.map((value) => value.trim()).filter(Boolean))\n );\n}\n\nfunction stripUndefined<T extends Record<string, unknown>>(value: T): T {\n return Object.fromEntries(\n Object.entries(value).filter(([, entryValue]) => entryValue !== undefined)\n ) as T;\n}\n","import {\n workbenchSnapshotSchemaVersion,\n type WorkbenchSnapshotV1\n} from \"./types.ts\";\nimport { normalizeWorkbenchSnapshot } from \"./normalize.ts\";\nimport { assertValidWorkbenchSnapshot } from \"./validate.ts\";\n\nexport function migrateWorkbenchSnapshot(value: unknown): WorkbenchSnapshotV1 {\n if (!isRecord(value)) {\n throw new Error(\"workbench snapshot must be an object\");\n }\n\n if (value.schemaVersion === workbenchSnapshotSchemaVersion) {\n assertValidWorkbenchSnapshot(value);\n return normalizeWorkbenchSnapshot(value);\n }\n\n throw new Error(\n `unsupported workbench snapshot schema version: ${String(value.schemaVersion)}`\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n","{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://tutti.local/schemas/workbench-snapshot.v1.json\",\n \"title\": \"WorkbenchSnapshotV1\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"schemaVersion\", \"nodes\"],\n \"properties\": {\n \"schemaVersion\": { \"const\": 1 },\n \"nodes\": {\n \"type\": \"array\",\n \"maxItems\": 128,\n \"items\": { \"$ref\": \"#/$defs/node\" }\n },\n \"nodeStack\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\", \"minLength\": 1 }\n },\n \"activeNodeId\": { \"type\": [\"string\", \"null\"] },\n \"spaces\": {\n \"type\": \"array\",\n \"items\": { \"$ref\": \"#/$defs/space\" }\n },\n \"activeSpaceId\": { \"type\": [\"string\", \"null\"] },\n \"layoutBasis\": { \"$ref\": \"#/$defs/layoutBasis\" },\n \"metadata\": { \"type\": \"object\" }\n },\n \"$defs\": {\n \"frame\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"x\", \"y\", \"width\", \"height\"],\n \"properties\": {\n \"x\": { \"type\": \"number\" },\n \"y\": { \"type\": \"number\" },\n \"width\": { \"type\": \"number\", \"minimum\": 160 },\n \"height\": { \"type\": \"number\", \"minimum\": 120 }\n }\n },\n \"size\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"width\", \"height\"],\n \"properties\": {\n \"width\": { \"type\": \"number\", \"exclusiveMinimum\": 0 },\n \"height\": { \"type\": \"number\", \"exclusiveMinimum\": 0 }\n }\n },\n \"safeArea\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"top\", \"right\", \"bottom\", \"left\"],\n \"properties\": {\n \"top\": { \"type\": \"number\", \"minimum\": 0 },\n \"right\": { \"type\": \"number\", \"minimum\": 0 },\n \"bottom\": { \"type\": \"number\", \"minimum\": 0 },\n \"left\": { \"type\": \"number\", \"minimum\": 0 }\n }\n },\n \"layoutConstraints\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"minWidth\", \"minHeight\", \"surfacePadding\", \"safeArea\"],\n \"properties\": {\n \"minWidth\": { \"type\": \"number\", \"minimum\": 0 },\n \"minHeight\": { \"type\": \"number\", \"minimum\": 0 },\n \"surfacePadding\": { \"type\": \"number\", \"minimum\": 0 },\n \"safeArea\": { \"$ref\": \"#/$defs/safeArea\" }\n }\n },\n \"layoutBasis\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"surfaceSize\", \"layoutConstraints\"],\n \"properties\": {\n \"surfaceSize\": { \"$ref\": \"#/$defs/size\" },\n \"layoutConstraints\": { \"$ref\": \"#/$defs/layoutConstraints\" }\n }\n },\n \"node\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"id\", \"kind\", \"title\", \"frame\"],\n \"properties\": {\n \"id\": { \"type\": \"string\", \"minLength\": 1, \"maxLength\": 160 },\n \"kind\": { \"type\": \"string\", \"minLength\": 1, \"maxLength\": 120 },\n \"title\": { \"type\": \"string\", \"maxLength\": 240 },\n \"frame\": { \"$ref\": \"#/$defs/frame\" },\n \"displayMode\": { \"enum\": [\"floating\", \"fullscreen\"] },\n \"restoreFrame\": {\n \"anyOf\": [{ \"$ref\": \"#/$defs/frame\" }, { \"type\": \"null\" }]\n },\n \"isMinimized\": { \"type\": \"boolean\" },\n \"minimizedAtUnixMs\": {\n \"type\": [\"integer\", \"null\"],\n \"minimum\": 0\n },\n \"data\": true,\n \"adapterState\": { \"type\": \"object\" }\n }\n },\n \"space\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"id\", \"name\", \"nodeIds\"],\n \"properties\": {\n \"id\": { \"type\": \"string\", \"minLength\": 1 },\n \"name\": { \"type\": \"string\" },\n \"nodeIds\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\", \"minLength\": 1 }\n },\n \"frame\": {\n \"anyOf\": [{ \"$ref\": \"#/$defs/frame\" }, { \"type\": \"null\" }]\n },\n \"data\": true\n }\n }\n }\n}\n","import { migrateWorkbenchSnapshot } from \"./migrate.ts\";\nimport { normalizeWorkbenchSnapshot } from \"./normalize.ts\";\nimport type { WorkbenchSnapshotV1 } from \"./types.ts\";\nimport { assertValidWorkbenchSnapshot } from \"./validate.ts\";\n\nexport function serializeWorkbenchSnapshot(\n snapshot: WorkbenchSnapshotV1\n): string {\n const normalized = normalizeWorkbenchSnapshot(snapshot);\n assertValidWorkbenchSnapshot(normalized);\n return JSON.stringify(normalized);\n}\n\nexport function parseWorkbenchSnapshot(\n serialized: string\n): WorkbenchSnapshotV1 {\n const parsed = JSON.parse(serialized) as unknown;\n return migrateWorkbenchSnapshot(parsed);\n}\n"],"mappings":";AAAO,IAAM,0BAA0B;AAAA,EACrC,oBAAoB,MAAM;AAAA,EAC1B,UAAU;AAAA,EACV,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,oBAAoB;AAAA,EACpB,cAAc;AAChB;;;ACVO,IAAM,iCAAiC;;;ACkB9C,IAAM,eAAe,oBAAI,IAAoC;AAAA,EAC3D;AAAA,EACA;AACF,CAAC;AAEM,SAAS,0BACd,OACmC;AACnC,QAAM,SAA6C,CAAC;AAEpD,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB,WAAO,MAAM,YAAY,4BAA4B;AAAA,EACvD;AACA;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,EACF;AAEA,MAAI,MAAM,kBAAkB,gCAAgC;AAC1D,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,MAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,GAAG;AAC/B,WAAO,KAAK,EAAE,MAAM,SAAS,SAAS,yBAAyB,CAAC;AAAA,EAClE,OAAO;AACL,QAAI,MAAM,MAAM,SAAS,wBAAwB,UAAU;AACzD,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,SAAS,8BAA8B,wBAAwB,QAAQ;AAAA,MACzE,CAAC;AAAA,IACH;AACA,kBAAc,MAAM,OAAO,MAAM;AAAA,EACnC;AAEA,sBAAoB,MAAM,WAAW,aAAa,QAAQ,IAAI;AAC9D,+BAA6B,MAAM,cAAc,gBAAgB,MAAM;AAEvE,MAAI,MAAM,WAAW,QAAW;AAC9B,QAAI,CAAC,MAAM,QAAQ,MAAM,MAAM,GAAG;AAChC,aAAO,KAAK,EAAE,MAAM,UAAU,SAAS,0BAA0B,CAAC;AAAA,IACpE,OAAO;AACL,qBAAe,MAAM,QAAQ,MAAM;AAAA,IACrC;AAAA,EACF;AAEA,+BAA6B,MAAM,eAAe,iBAAiB,MAAM;AAEzE,MAAI,MAAM,gBAAgB,QAAW;AACnC,wBAAoB,MAAM,aAAa,eAAe,MAAM;AAAA,EAC9D;AAEA,QAAM,kBAAkB,qBAAqB,KAAK;AAClD,MAAI,kBAAkB,wBAAwB,oBAAoB;AAChE,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS,sCAAsC,wBAAwB,kBAAkB;AAAA,IAC3F,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,IAAI,OAAO,WAAW,GAAG,OAAO;AAC3C;AAEO,SAAS,6BACd,OACsC;AACtC,QAAM,SAAS,0BAA0B,KAAK;AAC9C,MAAI,CAAC,OAAO,IAAI;AACd,UAAM,IAAI,MAAM,wCAAwC,OAAO,MAAM,CAAC;AAAA,EACxE;AACF;AAEO,SAAS,wCACd,QACQ;AACR,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,IAAI,CAAC,SAAS,GAAG,KAAK,IAAI,KAAK,KAAK,OAAO,EAAE,EAAE,KAAK,IAAI;AACxE;AAEA,SAAS,cACP,OACA,QACM;AACN,QAAM,MAAM,oBAAI,IAAY;AAE5B,QAAM,QAAQ,CAAC,MAAM,UAAU;AAC7B,UAAM,OAAO,SAAS,KAAK;AAC3B,QAAI,CAAC,SAAS,IAAI,GAAG;AACnB,aAAO,KAAK,EAAE,MAAM,SAAS,yBAAyB,CAAC;AACvD;AAAA,IACF;AACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAEA,UAAM,KAAK,uBAAuB,KAAK,IAAI,GAAG,IAAI,OAAO,QAAQ;AAAA,MAC/D,WAAW,wBAAwB;AAAA,IACrC,CAAC;AACD,QAAI,IAAI;AACN,UAAI,IAAI,IAAI,EAAE,GAAG;AACf,eAAO,KAAK,EAAE,MAAM,GAAG,IAAI,OAAO,SAAS,yBAAyB,CAAC;AAAA,MACvE;AACA,UAAI,IAAI,EAAE;AAAA,IACZ;AAEA,2BAAuB,KAAK,MAAM,GAAG,IAAI,SAAS,QAAQ;AAAA,MACxD,WAAW,wBAAwB;AAAA,IACrC,CAAC;AACD,2BAAuB,KAAK,OAAO,GAAG,IAAI,UAAU,QAAQ;AAAA,MAC1D,YAAY;AAAA,MACZ,WAAW,wBAAwB;AAAA,IACrC,CAAC;AACD,kBAAc,KAAK,OAAO,GAAG,IAAI,UAAU,MAAM;AAEjD,QACE,KAAK,gBAAgB,UACrB,CAAC,aAAa,IAAI,KAAK,WAA6C,GACpE;AACA,aAAO,KAAK;AAAA,QACV,MAAM,GAAG,IAAI;AAAA,QACb,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,iBAAiB,UAAa,KAAK,iBAAiB,MAAM;AACjE,oBAAc,KAAK,cAAc,GAAG,IAAI,iBAAiB,MAAM;AAAA,IACjE;AAEA,QACE,KAAK,gBAAgB,UACrB,OAAO,KAAK,gBAAgB,WAC5B;AACA,aAAO,KAAK;AAAA,QACV,MAAM,GAAG,IAAI;AAAA,QACb,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA;AAAA,MACE,KAAK;AAAA,MACL,GAAG,IAAI;AAAA,MACP;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,SAAS,eACP,QACA,QACM;AACN,SAAO,QAAQ,CAAC,OAAO,UAAU;AAC/B,UAAM,OAAO,UAAU,KAAK;AAC5B,QAAI,CAAC,SAAS,KAAK,GAAG;AACpB,aAAO,KAAK,EAAE,MAAM,SAAS,0BAA0B,CAAC;AACxD;AAAA,IACF;AACA;AAAA,MACE;AAAA,MACA;AAAA,MACA,CAAC,MAAM,QAAQ,WAAW,SAAS,MAAM;AAAA,MACzC;AAAA,IACF;AAEA,2BAAuB,MAAM,IAAI,GAAG,IAAI,OAAO,MAAM;AACrD,2BAAuB,MAAM,MAAM,GAAG,IAAI,SAAS,QAAQ;AAAA,MACzD,YAAY;AAAA,IACd,CAAC;AACD,wBAAoB,MAAM,SAAS,GAAG,IAAI,YAAY,QAAQ,KAAK;AAEnE,QAAI,MAAM,UAAU,UAAa,MAAM,UAAU,MAAM;AACrD,oBAAc,MAAM,OAAO,GAAG,IAAI,UAAU,MAAM;AAAA,IACpD;AAAA,EACF,CAAC;AACH;AAEA,SAAS,uBACP,OACA,MACA,QACA,UAAwD,CAAC,GAC1C;AACf,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,KAAK,EAAE,MAAM,SAAS,yBAAyB,CAAC;AACvD,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,QAAQ,cAAc,YAAY,IAAI;AACzC,WAAO,KAAK,EAAE,MAAM,SAAS,0BAA0B,CAAC;AACxD,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,cAAc,UAAa,MAAM,SAAS,QAAQ,WAAW;AACvE,WAAO,KAAK;AAAA,MACV;AAAA,MACA,SAAS,yBAAyB,QAAQ,SAAS;AAAA,IACrD,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,oBACP,OACA,MACA,QACA,UACM;AACN,MAAI,UAAU,UAAa,UAAU;AACnC;AAAA,EACF;AACA,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,WAAO,KAAK,EAAE,MAAM,SAAS,yBAAyB,CAAC;AACvD;AAAA,EACF;AAEA,QAAM,QAAQ,CAAC,MAAM,UAAU;AAC7B,QAAI,OAAO,SAAS,YAAY,KAAK,KAAK,MAAM,IAAI;AAClD,aAAO,KAAK;AAAA,QACV,MAAM,GAAG,IAAI,IAAI,KAAK;AAAA,QACtB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;AAEA,SAAS,6BACP,OACA,MACA,QACM;AACN,MAAI,UAAU,UAAa,UAAU,QAAQ,OAAO,UAAU,UAAU;AACtE;AAAA,EACF;AACA,SAAO,KAAK,EAAE,MAAM,SAAS,iCAAiC,CAAC;AACjE;AAEA,SAAS,yCACP,OACA,MACA,QACM;AACN,MAAI,UAAU,UAAa,UAAU,MAAM;AACzC;AAAA,EACF;AACA,MAAI,OAAO,UAAU,YAAY,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,GAAG;AACtE,WAAO,KAAK;AAAA,MACV;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACF;AAEA,SAAS,cACP,OACA,MACA,QACM;AACN,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB,WAAO,KAAK,EAAE,MAAM,SAAS,0BAA0B,CAAC;AACxD;AAAA,EACF;AACA,sBAAoB,OAAO,MAAM,CAAC,KAAK,KAAK,SAAS,QAAQ,GAAG,MAAM;AAEtE,uBAAqB,MAAM,GAAG,GAAG,IAAI,MAAM,MAAM;AACjD,uBAAqB,MAAM,GAAG,GAAG,IAAI,MAAM,MAAM;AACjD,uBAAqB,MAAM,OAAO,GAAG,IAAI,UAAU,MAAM;AACzD,uBAAqB,MAAM,QAAQ,GAAG,IAAI,WAAW,MAAM;AAE3D,QAAM,QAAQ;AACd,MACE,OAAO,MAAM,UAAU,YACvB,MAAM,QAAQ,wBAAwB,eACtC;AACA,WAAO,KAAK;AAAA,MACV,MAAM,GAAG,IAAI;AAAA,MACb,SAAS,0BAA0B,wBAAwB,aAAa;AAAA,IAC1E,CAAC;AAAA,EACH;AACA,MACE,OAAO,MAAM,WAAW,YACxB,MAAM,SAAS,wBAAwB,gBACvC;AACA,WAAO,KAAK;AAAA,MACV,MAAM,GAAG,IAAI;AAAA,MACb,SAAS,2BAA2B,wBAAwB,cAAc;AAAA,IAC5E,CAAC;AAAA,EACH;AACF;AAEA,SAAS,oBACP,OACA,MACA,QACM;AACN,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB,WAAO,KAAK,EAAE,MAAM,SAAS,iCAAiC,CAAC;AAC/D;AAAA,EACF;AACA;AAAA,IACE;AAAA,IACA;AAAA,IACA,CAAC,eAAe,mBAAmB;AAAA,IACnC;AAAA,EACF;AACA,eAAa,MAAM,aAAa,GAAG,IAAI,gBAAgB,MAAM;AAC7D;AAAA,IACE,MAAM;AAAA,IACN,GAAG,IAAI;AAAA,IACP;AAAA,EACF;AACF;AAEA,SAAS,aACP,OACA,MACA,QACM;AACN,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB,WAAO,KAAK,EAAE,MAAM,SAAS,yBAAyB,CAAC;AACvD;AAAA,EACF;AACA,sBAAoB,OAAO,MAAM,CAAC,SAAS,QAAQ,GAAG,MAAM;AAC5D,+BAA6B,MAAM,OAAO,GAAG,IAAI,UAAU,MAAM;AACjE,+BAA6B,MAAM,QAAQ,GAAG,IAAI,WAAW,MAAM;AACrE;AAEA,SAAS,0BACP,OACA,MACA,QACM;AACN,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB,WAAO,KAAK,EAAE,MAAM,SAAS,uCAAuC,CAAC;AACrE;AAAA,EACF;AACA;AAAA,IACE;AAAA,IACA;AAAA,IACA,CAAC,YAAY,aAAa,kBAAkB,UAAU;AAAA,IACtD;AAAA,EACF;AACA,kCAAgC,MAAM,UAAU,GAAG,IAAI,aAAa,MAAM;AAC1E,kCAAgC,MAAM,WAAW,GAAG,IAAI,cAAc,MAAM;AAC5E;AAAA,IACE,MAAM;AAAA,IACN,GAAG,IAAI;AAAA,IACP;AAAA,EACF;AAEA,QAAM,eAAe,GAAG,IAAI;AAC5B,MAAI,CAAC,SAAS,MAAM,QAAQ,GAAG;AAC7B,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AACD;AAAA,EACF;AACA;AAAA,IACE,MAAM;AAAA,IACN;AAAA,IACA,CAAC,OAAO,SAAS,UAAU,MAAM;AAAA,IACjC;AAAA,EACF;AACA,aAAW,QAAQ,CAAC,OAAO,SAAS,UAAU,MAAM,GAAY;AAC9D;AAAA,MACE,MAAM,SAAS,IAAI;AAAA,MACnB,GAAG,YAAY,IAAI,IAAI;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,6BACP,OACA,MACA,QACM;AACN,uBAAqB,OAAO,MAAM,MAAM;AACxC,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,SAAS,GAAG;AACrE,WAAO,KAAK,EAAE,MAAM,SAAS,kCAAkC,CAAC;AAAA,EAClE;AACF;AAEA,SAAS,gCACP,OACA,MACA,QACM;AACN,uBAAqB,OAAO,MAAM,MAAM;AACxC,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,QAAQ,GAAG;AACpE,WAAO,KAAK,EAAE,MAAM,SAAS,6BAA6B,CAAC;AAAA,EAC7D;AACF;AAEA,SAAS,qBACP,OACA,MACA,QACM;AACN,MAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,GAAG;AACxD,WAAO,KAAK,EAAE,MAAM,SAAS,gCAAgC,CAAC;AAAA,EAChE;AACF;AAEA,SAAS,oBACP,OACA,MACA,aACA,QACM;AACN,QAAM,UAAU,IAAI,IAAI,WAAW;AACnC,aAAW,OAAO,OAAO,KAAK,KAAK,GAAG;AACpC,QAAI,CAAC,QAAQ,IAAI,GAAG,GAAG;AACrB,aAAO,KAAK;AAAA,QACV,MAAM,GAAG,IAAI,IAAI,GAAG;AAAA,QACpB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,SAAS,qBAAqB,OAAwB;AACpD,MAAI;AACF,WAAO,IAAI,YAAY,EAAE,OAAO,KAAK,UAAU,KAAK,CAAC,EAAE;AAAA,EACzD,QAAQ;AACN,WAAO,OAAO;AAAA,EAChB;AACF;AAEA,SAAS,SAAS,OAAkD;AAClE,SAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,MACP,MACA,SACmC;AACnC,SAAO,EAAE,IAAI,OAAO,QAAQ,CAAC,EAAE,MAAM,QAAQ,CAAC,EAAE;AAClD;;;AC5dO,SAAS,2BACd,OACqB;AACrB,+BAA6B,KAAK;AAElC,QAAM,QAAQ,MAAM,MAAM,IAAI,aAAa,EAAE,KAAK,WAAW;AAC7D,QAAM,UAAU,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;AACpD,QAAM,YAAY,cAAc,MAAM,aAAa,CAAC,CAAC,EAAE;AAAA,IAAO,CAAC,OAC7D,QAAQ,IAAI,EAAE;AAAA,EAChB;AAEA,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,UAAU,SAAS,KAAK,EAAE,GAAG;AAChC,gBAAU,KAAK,KAAK,EAAE;AAAA,IACxB;AAAA,EACF;AAEA,QAAM,eACJ,MAAM,gBAAgB,QAAQ,IAAI,MAAM,YAAY,IAChD,MAAM,eACL,UAAU,GAAG,EAAE,KAAK;AAE3B,QAAM,SAAS,MAAM,QAAQ,IAAI,cAAc,EAAE,KAAK,WAAW;AACjE,QAAM,WAAW,IAAI,IAAI,QAAQ,IAAI,CAAC,UAAU,MAAM,EAAE,KAAK,CAAC,CAAC;AAC/D,QAAM,gBACJ,MAAM,iBAAiB,SAAS,IAAI,MAAM,aAAa,IACnD,MAAM,gBACL,SAAS,CAAC,GAAG,MAAM;AAE1B,SAAO,eAAe;AAAA,IACpB,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,MAAM,cACf,qBAAqB,MAAM,WAAW,IACtC;AAAA,IACJ,UAAU,MAAM;AAAA,EAClB,CAAC;AACH;AAEA,SAAS,cAAc,MAAwD;AAC7E,SAAO,eAAe;AAAA,IACpB,IAAI,KAAK,GAAG,KAAK;AAAA,IACjB,MAAM,KAAK,KAAK,KAAK;AAAA,IACrB,OAAO,KAAK;AAAA,IACZ,OAAO,eAAe,KAAK,KAAK;AAAA,IAChC,aAAa,KAAK,eAAe;AAAA,IACjC,cAAc,KAAK,eAAe,eAAe,KAAK,YAAY,IAAI;AAAA,IACtE,aAAa,KAAK,eAAe;AAAA,IACjC,mBAAmB,2BAA2B,IAAI;AAAA,IAClD,MAAM,KAAK;AAAA,IACX,cAAc,KAAK;AAAA,EACrB,CAAC;AACH;AAEA,SAAS,2BACP,MAC2B;AAC3B,MAAI,KAAK,gBAAgB,MAAM;AAC7B,WAAO;AAAA,EACT;AACA,SAAO,KAAK,qBAAqB;AACnC;AAEA,SAAS,eACP,OAC0B;AAC1B,SAAO,eAAe;AAAA,IACpB,IAAI,MAAM,GAAG,KAAK;AAAA,IAClB,MAAM,MAAM;AAAA,IACZ,SAAS,cAAc,MAAM,OAAO;AAAA,IACpC,OAAO,MAAM,QAAQ,eAAe,MAAM,KAAK,IAAI;AAAA,IACnD,MAAM,MAAM;AAAA,EACd,CAAC;AACH;AAEA,SAAS,eAAe,OAA2C;AACjE,SAAO;AAAA,IACL,GAAG,gBAAgB,MAAM,CAAC;AAAA,IAC1B,GAAG,gBAAgB,MAAM,CAAC;AAAA,IAC1B,OAAO,KAAK;AAAA,MACV,wBAAwB;AAAA,MACxB,gBAAgB,MAAM,KAAK;AAAA,IAC7B;AAAA,IACA,QAAQ,KAAK;AAAA,MACX,wBAAwB;AAAA,MACxB,gBAAgB,MAAM,MAAM;AAAA,IAC9B;AAAA,EACF;AACF;AAEA,SAAS,qBACP,aACgC;AAChC,SAAO;AAAA,IACL,aAAa;AAAA,MACX,OAAO,gBAAgB,YAAY,YAAY,KAAK;AAAA,MACpD,QAAQ,gBAAgB,YAAY,YAAY,MAAM;AAAA,IACxD;AAAA,IACA,mBAAmB;AAAA,MACjB,UAAU,gBAAgB,YAAY,kBAAkB,QAAQ;AAAA,MAChE,WAAW,gBAAgB,YAAY,kBAAkB,SAAS;AAAA,MAClE,gBAAgB;AAAA,QACd,YAAY,kBAAkB;AAAA,MAChC;AAAA,MACA,UAAU;AAAA,QACR,KAAK,gBAAgB,YAAY,kBAAkB,SAAS,GAAG;AAAA,QAC/D,OAAO,gBAAgB,YAAY,kBAAkB,SAAS,KAAK;AAAA,QACnE,QAAQ,gBAAgB,YAAY,kBAAkB,SAAS,MAAM;AAAA,QACrE,MAAM,gBAAgB,YAAY,kBAAkB,SAAS,IAAI;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,OAAuB;AAC9C,SAAO,OAAO,GAAG,OAAO,EAAE,IAAI,IAAI,OAAO,MAAM,QAAQ,CAAC,CAAC;AAC3D;AAEA,SAAS,YAAsC,MAAS,OAAkB;AACxE,SAAO,KAAK,GAAG,cAAc,MAAM,EAAE;AACvC;AAEA,SAAS,cAAc,QAA4B;AACjD,SAAO,MAAM;AAAA,IACX,IAAI,IAAI,OAAO,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC;AAAA,EAC7D;AACF;AAEA,SAAS,eAAkD,OAAa;AACtE,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,UAAU,MAAM,eAAe,MAAS;AAAA,EAC3E;AACF;;;AC5IO,SAAS,yBAAyB,OAAqC;AAC5E,MAAI,CAACA,UAAS,KAAK,GAAG;AACpB,UAAM,IAAI,MAAM,sCAAsC;AAAA,EACxD;AAEA,MAAI,MAAM,kBAAkB,gCAAgC;AAC1D,iCAA6B,KAAK;AAClC,WAAO,2BAA2B,KAAK;AAAA,EACzC;AAEA,QAAM,IAAI;AAAA,IACR,kDAAkD,OAAO,MAAM,aAAa,CAAC;AAAA,EAC/E;AACF;AAEA,SAASA,UAAS,OAAkD;AAClE,SAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;;;ACxBA;AAAA,EACE,SAAW;AAAA,EACX,KAAO;AAAA,EACP,OAAS;AAAA,EACT,MAAQ;AAAA,EACR,sBAAwB;AAAA,EACxB,UAAY,CAAC,iBAAiB,OAAO;AAAA,EACrC,YAAc;AAAA,IACZ,eAAiB,EAAE,OAAS,EAAE;AAAA,IAC9B,OAAS;AAAA,MACP,MAAQ;AAAA,MACR,UAAY;AAAA,MACZ,OAAS,EAAE,MAAQ,eAAe;AAAA,IACpC;AAAA,IACA,WAAa;AAAA,MACX,MAAQ;AAAA,MACR,OAAS,EAAE,MAAQ,UAAU,WAAa,EAAE;AAAA,IAC9C;AAAA,IACA,cAAgB,EAAE,MAAQ,CAAC,UAAU,MAAM,EAAE;AAAA,IAC7C,QAAU;AAAA,MACR,MAAQ;AAAA,MACR,OAAS,EAAE,MAAQ,gBAAgB;AAAA,IACrC;AAAA,IACA,eAAiB,EAAE,MAAQ,CAAC,UAAU,MAAM,EAAE;AAAA,IAC9C,aAAe,EAAE,MAAQ,sBAAsB;AAAA,IAC/C,UAAY,EAAE,MAAQ,SAAS;AAAA,EACjC;AAAA,EACA,OAAS;AAAA,IACP,OAAS;AAAA,MACP,MAAQ;AAAA,MACR,sBAAwB;AAAA,MACxB,UAAY,CAAC,KAAK,KAAK,SAAS,QAAQ;AAAA,MACxC,YAAc;AAAA,QACZ,GAAK,EAAE,MAAQ,SAAS;AAAA,QACxB,GAAK,EAAE,MAAQ,SAAS;AAAA,QACxB,OAAS,EAAE,MAAQ,UAAU,SAAW,IAAI;AAAA,QAC5C,QAAU,EAAE,MAAQ,UAAU,SAAW,IAAI;AAAA,MAC/C;AAAA,IACF;AAAA,IACA,MAAQ;AAAA,MACN,MAAQ;AAAA,MACR,sBAAwB;AAAA,MACxB,UAAY,CAAC,SAAS,QAAQ;AAAA,MAC9B,YAAc;AAAA,QACZ,OAAS,EAAE,MAAQ,UAAU,kBAAoB,EAAE;AAAA,QACnD,QAAU,EAAE,MAAQ,UAAU,kBAAoB,EAAE;AAAA,MACtD;AAAA,IACF;AAAA,IACA,UAAY;AAAA,MACV,MAAQ;AAAA,MACR,sBAAwB;AAAA,MACxB,UAAY,CAAC,OAAO,SAAS,UAAU,MAAM;AAAA,MAC7C,YAAc;AAAA,QACZ,KAAO,EAAE,MAAQ,UAAU,SAAW,EAAE;AAAA,QACxC,OAAS,EAAE,MAAQ,UAAU,SAAW,EAAE;AAAA,QAC1C,QAAU,EAAE,MAAQ,UAAU,SAAW,EAAE;AAAA,QAC3C,MAAQ,EAAE,MAAQ,UAAU,SAAW,EAAE;AAAA,MAC3C;AAAA,IACF;AAAA,IACA,mBAAqB;AAAA,MACnB,MAAQ;AAAA,MACR,sBAAwB;AAAA,MACxB,UAAY,CAAC,YAAY,aAAa,kBAAkB,UAAU;AAAA,MAClE,YAAc;AAAA,QACZ,UAAY,EAAE,MAAQ,UAAU,SAAW,EAAE;AAAA,QAC7C,WAAa,EAAE,MAAQ,UAAU,SAAW,EAAE;AAAA,QAC9C,gBAAkB,EAAE,MAAQ,UAAU,SAAW,EAAE;AAAA,QACnD,UAAY,EAAE,MAAQ,mBAAmB;AAAA,MAC3C;AAAA,IACF;AAAA,IACA,aAAe;AAAA,MACb,MAAQ;AAAA,MACR,sBAAwB;AAAA,MACxB,UAAY,CAAC,eAAe,mBAAmB;AAAA,MAC/C,YAAc;AAAA,QACZ,aAAe,EAAE,MAAQ,eAAe;AAAA,QACxC,mBAAqB,EAAE,MAAQ,4BAA4B;AAAA,MAC7D;AAAA,IACF;AAAA,IACA,MAAQ;AAAA,MACN,MAAQ;AAAA,MACR,sBAAwB;AAAA,MACxB,UAAY,CAAC,MAAM,QAAQ,SAAS,OAAO;AAAA,MAC3C,YAAc;AAAA,QACZ,IAAM,EAAE,MAAQ,UAAU,WAAa,GAAG,WAAa,IAAI;AAAA,QAC3D,MAAQ,EAAE,MAAQ,UAAU,WAAa,GAAG,WAAa,IAAI;AAAA,QAC7D,OAAS,EAAE,MAAQ,UAAU,WAAa,IAAI;AAAA,QAC9C,OAAS,EAAE,MAAQ,gBAAgB;AAAA,QACnC,aAAe,EAAE,MAAQ,CAAC,YAAY,YAAY,EAAE;AAAA,QACpD,cAAgB;AAAA,UACd,OAAS,CAAC,EAAE,MAAQ,gBAAgB,GAAG,EAAE,MAAQ,OAAO,CAAC;AAAA,QAC3D;AAAA,QACA,aAAe,EAAE,MAAQ,UAAU;AAAA,QACnC,mBAAqB;AAAA,UACnB,MAAQ,CAAC,WAAW,MAAM;AAAA,UAC1B,SAAW;AAAA,QACb;AAAA,QACA,MAAQ;AAAA,QACR,cAAgB,EAAE,MAAQ,SAAS;AAAA,MACrC;AAAA,IACF;AAAA,IACA,OAAS;AAAA,MACP,MAAQ;AAAA,MACR,sBAAwB;AAAA,MACxB,UAAY,CAAC,MAAM,QAAQ,SAAS;AAAA,MACpC,YAAc;AAAA,QACZ,IAAM,EAAE,MAAQ,UAAU,WAAa,EAAE;AAAA,QACzC,MAAQ,EAAE,MAAQ,SAAS;AAAA,QAC3B,SAAW;AAAA,UACT,MAAQ;AAAA,UACR,OAAS,EAAE,MAAQ,UAAU,WAAa,EAAE;AAAA,QAC9C;AAAA,QACA,OAAS;AAAA,UACP,OAAS,CAAC,EAAE,MAAQ,gBAAgB,GAAG,EAAE,MAAQ,OAAO,CAAC;AAAA,QAC3D;AAAA,QACA,MAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF;;;AClHO,SAAS,2BACd,UACQ;AACR,QAAM,aAAa,2BAA2B,QAAQ;AACtD,+BAA6B,UAAU;AACvC,SAAO,KAAK,UAAU,UAAU;AAClC;AAEO,SAAS,uBACd,YACqB;AACrB,QAAM,SAAS,KAAK,MAAM,UAAU;AACpC,SAAO,yBAAyB,MAAM;AACxC;","names":["isRecord"]}
package/dist/schema.json CHANGED
@@ -22,6 +22,7 @@
22
22
  "items": { "$ref": "#/$defs/space" }
23
23
  },
24
24
  "activeSpaceId": { "type": ["string", "null"] },
25
+ "layoutBasis": { "$ref": "#/$defs/layoutBasis" },
25
26
  "metadata": { "type": "object" }
26
27
  },
27
28
  "$defs": {
@@ -36,6 +37,46 @@
36
37
  "height": { "type": "number", "minimum": 120 }
37
38
  }
38
39
  },
40
+ "size": {
41
+ "type": "object",
42
+ "additionalProperties": false,
43
+ "required": ["width", "height"],
44
+ "properties": {
45
+ "width": { "type": "number", "exclusiveMinimum": 0 },
46
+ "height": { "type": "number", "exclusiveMinimum": 0 }
47
+ }
48
+ },
49
+ "safeArea": {
50
+ "type": "object",
51
+ "additionalProperties": false,
52
+ "required": ["top", "right", "bottom", "left"],
53
+ "properties": {
54
+ "top": { "type": "number", "minimum": 0 },
55
+ "right": { "type": "number", "minimum": 0 },
56
+ "bottom": { "type": "number", "minimum": 0 },
57
+ "left": { "type": "number", "minimum": 0 }
58
+ }
59
+ },
60
+ "layoutConstraints": {
61
+ "type": "object",
62
+ "additionalProperties": false,
63
+ "required": ["minWidth", "minHeight", "surfacePadding", "safeArea"],
64
+ "properties": {
65
+ "minWidth": { "type": "number", "minimum": 0 },
66
+ "minHeight": { "type": "number", "minimum": 0 },
67
+ "surfacePadding": { "type": "number", "minimum": 0 },
68
+ "safeArea": { "$ref": "#/$defs/safeArea" }
69
+ }
70
+ },
71
+ "layoutBasis": {
72
+ "type": "object",
73
+ "additionalProperties": false,
74
+ "required": ["surfaceSize", "layoutConstraints"],
75
+ "properties": {
76
+ "surfaceSize": { "$ref": "#/$defs/size" },
77
+ "layoutConstraints": { "$ref": "#/$defs/layoutConstraints" }
78
+ }
79
+ },
39
80
  "node": {
40
81
  "type": "object",
41
82
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tutti-os/workbench-snapshot",
3
- "version": "0.0.208",
3
+ "version": "0.0.210",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",