@abraca/schema 2.3.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.
Files changed (92) hide show
  1. package/dist/abracadabra-schema.cjs +853 -0
  2. package/dist/abracadabra-schema.cjs.map +1 -0
  3. package/dist/abracadabra-schema.esm.js +781 -0
  4. package/dist/abracadabra-schema.esm.js.map +1 -0
  5. package/dist/index.d.ts +2538 -0
  6. package/package.json +41 -0
  7. package/src/crdt.ts +63 -0
  8. package/src/generated/calendar.ts +35 -0
  9. package/src/generated/chart.ts +35 -0
  10. package/src/generated/checklist.ts +35 -0
  11. package/src/generated/dashboard.ts +35 -0
  12. package/src/generated/doc.ts +35 -0
  13. package/src/generated/gallery.ts +35 -0
  14. package/src/generated/graph.ts +35 -0
  15. package/src/generated/json-schema/calendar.json +140 -0
  16. package/src/generated/json-schema/chart.json +164 -0
  17. package/src/generated/json-schema/checklist.json +138 -0
  18. package/src/generated/json-schema/dashboard.json +122 -0
  19. package/src/generated/json-schema/doc.json +122 -0
  20. package/src/generated/json-schema/gallery.json +157 -0
  21. package/src/generated/json-schema/graph.json +125 -0
  22. package/src/generated/json-schema/kanban.json +145 -0
  23. package/src/generated/json-schema/map.json +125 -0
  24. package/src/generated/json-schema/outline.json +122 -0
  25. package/src/generated/json-schema/overview.json +122 -0
  26. package/src/generated/json-schema/plugin-manifest.json +221 -0
  27. package/src/generated/json-schema/prose.json +122 -0
  28. package/src/generated/json-schema/sheets.json +135 -0
  29. package/src/generated/json-schema/slides.json +129 -0
  30. package/src/generated/json-schema/table.json +136 -0
  31. package/src/generated/json-schema/timeline.json +122 -0
  32. package/src/generated/kanban.ts +35 -0
  33. package/src/generated/map.ts +35 -0
  34. package/src/generated/markdown/calendar.md +59 -0
  35. package/src/generated/markdown/chart.md +62 -0
  36. package/src/generated/markdown/checklist.md +58 -0
  37. package/src/generated/markdown/dashboard.md +56 -0
  38. package/src/generated/markdown/doc.md +56 -0
  39. package/src/generated/markdown/gallery.md +61 -0
  40. package/src/generated/markdown/graph.md +57 -0
  41. package/src/generated/markdown/kanban.md +62 -0
  42. package/src/generated/markdown/map.md +57 -0
  43. package/src/generated/markdown/outline.md +56 -0
  44. package/src/generated/markdown/overview.md +56 -0
  45. package/src/generated/markdown/prose.md +56 -0
  46. package/src/generated/markdown/sheets.md +59 -0
  47. package/src/generated/markdown/slides.md +57 -0
  48. package/src/generated/markdown/table.md +58 -0
  49. package/src/generated/markdown/timeline.md +56 -0
  50. package/src/generated/outline.ts +35 -0
  51. package/src/generated/overview.ts +35 -0
  52. package/src/generated/prose.ts +35 -0
  53. package/src/generated/rust/calendar.rs +125 -0
  54. package/src/generated/rust/chart.rs +151 -0
  55. package/src/generated/rust/checklist.rs +123 -0
  56. package/src/generated/rust/dashboard.rs +101 -0
  57. package/src/generated/rust/doc.rs +101 -0
  58. package/src/generated/rust/gallery.rs +146 -0
  59. package/src/generated/rust/graph.rs +104 -0
  60. package/src/generated/rust/kanban.rs +127 -0
  61. package/src/generated/rust/map.rs +104 -0
  62. package/src/generated/rust/outline.rs +101 -0
  63. package/src/generated/rust/overview.rs +101 -0
  64. package/src/generated/rust/prose.rs +101 -0
  65. package/src/generated/rust/sheets.rs +110 -0
  66. package/src/generated/rust/slides.rs +111 -0
  67. package/src/generated/rust/table.rs +121 -0
  68. package/src/generated/rust/timeline.rs +101 -0
  69. package/src/generated/sheets.ts +35 -0
  70. package/src/generated/slides.ts +35 -0
  71. package/src/generated/table.ts +35 -0
  72. package/src/generated/timeline.ts +35 -0
  73. package/src/index.ts +389 -0
  74. package/src/manifest/plugin-manifest.ts +212 -0
  75. package/src/query.ts +150 -0
  76. package/src/types/calendar.ts +23 -0
  77. package/src/types/chart.ts +36 -0
  78. package/src/types/checklist.ts +22 -0
  79. package/src/types/dashboard.ts +18 -0
  80. package/src/types/doc.ts +19 -0
  81. package/src/types/gallery.ts +24 -0
  82. package/src/types/graph.ts +21 -0
  83. package/src/types/kanban.ts +27 -0
  84. package/src/types/map.ts +21 -0
  85. package/src/types/outline.ts +17 -0
  86. package/src/types/overview.ts +17 -0
  87. package/src/types/prose.ts +19 -0
  88. package/src/types/sheets.ts +24 -0
  89. package/src/types/slides.ts +22 -0
  90. package/src/types/table.ts +22 -0
  91. package/src/types/timeline.ts +18 -0
  92. package/src/types/universal.ts +59 -0
@@ -0,0 +1,781 @@
1
+ import { z } from "zod";
2
+
3
+ //#region packages/schema/src/crdt.ts
4
+ /** Y.Text marker. Reads as opaque CRDT — schema does not validate the contents. */
5
+ function ytext() {
6
+ return z.custom(() => true).meta({ crdt: "ytext" });
7
+ }
8
+ /** Y.Array<T> marker. Element schema is preserved in metadata for codegen. */
9
+ function yarray(element) {
10
+ return z.custom(() => true).meta({
11
+ crdt: "yarray",
12
+ element
13
+ });
14
+ }
15
+ /** Y.Map<T> marker. Value schema is preserved in metadata for codegen. */
16
+ function ymap(value) {
17
+ return z.custom(() => true).meta({
18
+ crdt: "ymap",
19
+ element: value
20
+ });
21
+ }
22
+ /** Inspect a Zod schema for a CRDT marker. Returns undefined for non-CRDT schemas. */
23
+ function crdtMetaOf(schema) {
24
+ const meta = schema.meta();
25
+ if (meta && typeof meta.crdt === "string") return meta;
26
+ }
27
+
28
+ //#endregion
29
+ //#region packages/schema/src/types/universal.ts
30
+ /**
31
+ * Universal meta keys that may appear on any typed root.
32
+ *
33
+ * Mirrors the canonical list in `page-type-guidelines.md` §4.5 plus the
34
+ * three cross-cutting cover keys (`coverUploadId`/`coverDocId`/
35
+ * `coverMimeType`). Every key is optional. Per-type schemas merge this
36
+ * object via `UniversalMeta.extend({ ... })`.
37
+ *
38
+ * Descendant-only keys (cell formatting, geo, dashboard layout, spatial
39
+ * transforms, EXIF media metadata, etc.) are deliberately excluded —
40
+ * descendants are untyped and unvalidated by the registry, so those
41
+ * keys flow through the untyped meta path without per-type constraints.
42
+ */
43
+ const hexColor = z.string().regex(/^#[0-9a-fA-F]{6}$/);
44
+ const hhmm = z.string().regex(/^[0-2]\d:[0-5]\d$/);
45
+ const UniversalMeta = z.strictObject({
46
+ color: hexColor.optional(),
47
+ icon: z.string().optional(),
48
+ datetimeStart: z.iso.datetime().optional(),
49
+ datetimeEnd: z.iso.datetime().optional(),
50
+ allDay: z.boolean().optional(),
51
+ dateStart: z.iso.date().optional(),
52
+ dateEnd: z.iso.date().optional(),
53
+ timeStart: hhmm.optional(),
54
+ timeEnd: hhmm.optional(),
55
+ tags: z.array(z.string()).optional(),
56
+ checked: z.boolean().optional(),
57
+ priority: z.number().int().min(0).max(4).optional(),
58
+ status: z.string().optional(),
59
+ rating: z.number().min(0).max(5).optional(),
60
+ url: z.string().optional(),
61
+ email: z.string().optional(),
62
+ phone: z.string().optional(),
63
+ number: z.number().optional(),
64
+ unit: z.string().optional(),
65
+ subtitle: z.string().optional(),
66
+ note: z.string().optional(),
67
+ taskProgress: z.number().min(0).max(100).optional(),
68
+ assignedTo: z.string().optional(),
69
+ coverUploadId: z.string().optional(),
70
+ coverDocId: z.string().optional(),
71
+ coverMimeType: z.string().optional(),
72
+ __schemaVersion: z.number().int().min(1).optional()
73
+ });
74
+
75
+ //#endregion
76
+ //#region packages/schema/src/query.ts
77
+ /**
78
+ * V2 query layer — predicate AST.
79
+ *
80
+ * Mirrors InstantDB / Prisma `where` shapes: column → predicate pairs
81
+ * composed with boolean AND/OR/NOT. The Rust compiler at
82
+ * `crates/abracadabra/src/query.rs` walks the same shape and emits
83
+ * indexed SQL against `doc_meta_index`.
84
+ *
85
+ * Columns are restricted to the universal-meta projection: `priority`,
86
+ * `dateStart`, `dateEnd`, `tags`, `status`, `assignedTo`. Anything else
87
+ * is rejected. Adding a column requires both:
88
+ * 1. A new column on `doc_meta_index` (migration in `abracadabra-rs`)
89
+ * 2. A new entry in `META_COLUMNS` below
90
+ *
91
+ * The schema is intentionally narrow — only the operators the v2 query
92
+ * layer can actually execute against indexed columns are accepted. New
93
+ * operators require server changes; the schema is the contract.
94
+ */
95
+ /**
96
+ * Whitelisted indexed columns on `doc_meta_index`. Adding to this list
97
+ * requires a parallel migration on the server. Order is the canonical
98
+ * documentation order — not enforced.
99
+ */
100
+ const META_COLUMNS = [
101
+ "priority",
102
+ "dateStart",
103
+ "dateEnd",
104
+ "tags",
105
+ "status",
106
+ "assignedTo"
107
+ ];
108
+ z.enum(META_COLUMNS);
109
+ const ScalarValue = z.union([
110
+ z.string(),
111
+ z.number(),
112
+ z.boolean(),
113
+ z.null()
114
+ ]);
115
+ /**
116
+ * Numeric / lexicographic comparison operators. Apply to integer
117
+ * (`priority`), date (`dateStart`, `dateEnd`), and string
118
+ * (`status`, `assignedTo`) columns. Strings compare lexicographically
119
+ * — useful for date filtering on the SQLite path where dates are TEXT.
120
+ */
121
+ const RangeOps = z.strictObject({
122
+ eq: ScalarValue.optional(),
123
+ neq: ScalarValue.optional(),
124
+ gt: ScalarValue.optional(),
125
+ gte: ScalarValue.optional(),
126
+ lt: ScalarValue.optional(),
127
+ lte: ScalarValue.optional(),
128
+ in: z.array(ScalarValue).optional(),
129
+ between: z.tuple([ScalarValue, ScalarValue]).optional()
130
+ });
131
+ /**
132
+ * Operators for the `tags` column. `tags` is a JSON array.
133
+ * `contains: "x"` matches when the array includes the string `x`.
134
+ * `containsAll: ["x","y"]` requires all listed tags to be present.
135
+ * `containsAny: ["x","y"]` requires at least one.
136
+ */
137
+ const TagOps = z.strictObject({
138
+ contains: z.string().optional(),
139
+ containsAll: z.array(z.string()).optional(),
140
+ containsAny: z.array(z.string()).optional(),
141
+ isEmpty: z.boolean().optional()
142
+ });
143
+ /** Per-column predicate. `null` => column IS NULL. */
144
+ const ColumnPredicate = z.union([
145
+ ScalarValue,
146
+ RangeOps,
147
+ TagOps
148
+ ]);
149
+ const WhereClauseSchema = z.lazy(() => z.strictObject({
150
+ AND: z.array(WhereClauseSchema).optional(),
151
+ OR: z.array(WhereClauseSchema).optional(),
152
+ NOT: WhereClauseSchema.optional(),
153
+ priority: ColumnPredicate.optional(),
154
+ dateStart: ColumnPredicate.optional(),
155
+ dateEnd: ColumnPredicate.optional(),
156
+ tags: ColumnPredicate.optional(),
157
+ status: ColumnPredicate.optional(),
158
+ assignedTo: ColumnPredicate.optional()
159
+ }));
160
+ /**
161
+ * Parse + normalise a raw `where` object. Returns a discriminated
162
+ * result so call sites can render server-friendly error messages on
163
+ * the wire.
164
+ */
165
+ function parseWhereClause(raw) {
166
+ const parsed = WhereClauseSchema.safeParse(raw);
167
+ if (parsed.success) return {
168
+ ok: true,
169
+ value: parsed.data
170
+ };
171
+ return {
172
+ ok: false,
173
+ errors: parsed.error.issues.map((i) => ({
174
+ path: i.path,
175
+ message: i.message
176
+ }))
177
+ };
178
+ }
179
+
180
+ //#endregion
181
+ //#region packages/schema/src/types/doc.ts
182
+ /**
183
+ * `doc` — the default rich-text page type. Body is a TipTap-backed
184
+ * `Y.Text`; descendants are untyped tree entries.
185
+ */
186
+ const DocMeta = UniversalMeta;
187
+ const Doc = defineDocType({
188
+ name: "doc",
189
+ version: 1,
190
+ meta: DocMeta,
191
+ body: ytext()
192
+ });
193
+ const docSchema = defineSchema({ types: [Doc] });
194
+
195
+ //#endregion
196
+ //#region packages/schema/src/types/prose.ts
197
+ /**
198
+ * `prose` — long-form prose with serif typography. Same body shape as
199
+ * `doc` (Y.Text TipTap content); descendants are untyped.
200
+ */
201
+ const ProseMeta = UniversalMeta;
202
+ const Prose = defineDocType({
203
+ name: "prose",
204
+ version: 1,
205
+ meta: ProseMeta,
206
+ body: ytext()
207
+ });
208
+ const proseSchema = defineSchema({ types: [Prose] });
209
+
210
+ //#endregion
211
+ //#region packages/schema/src/types/kanban.ts
212
+ /**
213
+ * `kanban` — drag-and-drop board. Direct children are columns;
214
+ * grandchildren are cards. Both descendants are untyped tree entries
215
+ * — only the board itself carries `type: "kanban"` and the per-board
216
+ * view-config keys below.
217
+ */
218
+ const KanbanMeta = UniversalMeta.extend({
219
+ kanbanColumnWidth: z.enum([
220
+ "narrow",
221
+ "default",
222
+ "wide"
223
+ ]).optional(),
224
+ kanbanShowIcon: z.boolean().optional(),
225
+ kanbanShowTags: z.boolean().optional(),
226
+ kanbanShowPriority: z.boolean().optional(),
227
+ kanbanShowDueDate: z.boolean().optional(),
228
+ kanbanShowCover: z.boolean().optional()
229
+ });
230
+ const Kanban = defineDocType({
231
+ name: "kanban",
232
+ version: 1,
233
+ meta: KanbanMeta
234
+ });
235
+ const kanbanSchema = defineSchema({ types: [Kanban] });
236
+
237
+ //#endregion
238
+ //#region packages/schema/src/types/gallery.ts
239
+ /**
240
+ * `gallery` — visual grid of items with rich content. Direct children
241
+ * are items (untyped tree entries).
242
+ */
243
+ const GalleryMeta = UniversalMeta.extend({
244
+ galleryColumns: z.number().int().min(1).max(6).optional(),
245
+ galleryAspect: z.enum([
246
+ "square",
247
+ "4:3",
248
+ "3:2",
249
+ "16:9",
250
+ "free"
251
+ ]).optional(),
252
+ galleryCardStyle: z.enum([
253
+ "default",
254
+ "compact",
255
+ "detailed"
256
+ ]).optional(),
257
+ galleryShowLabels: z.boolean().optional(),
258
+ gallerySortBy: z.enum([
259
+ "manual",
260
+ "date",
261
+ "name",
262
+ "rating"
263
+ ]).optional()
264
+ });
265
+ const Gallery = defineDocType({
266
+ name: "gallery",
267
+ version: 1,
268
+ meta: GalleryMeta
269
+ });
270
+ const gallerySchema = defineSchema({ types: [Gallery] });
271
+
272
+ //#endregion
273
+ //#region packages/schema/src/types/table.ts
274
+ /**
275
+ * `table` — collaborative spreadsheet. Direct children are columns;
276
+ * grandchildren are positional cells (row N = Nth child of each
277
+ * column). Descendants are untyped.
278
+ */
279
+ const TableMeta = UniversalMeta.extend({
280
+ tableMode: z.enum(["hierarchy", "flat"]).optional(),
281
+ tableSortDir: z.enum(["asc", "desc"]).optional()
282
+ });
283
+ const Table = defineDocType({
284
+ name: "table",
285
+ version: 1,
286
+ meta: TableMeta
287
+ });
288
+ const tableSchema = defineSchema({ types: [Table] });
289
+
290
+ //#endregion
291
+ //#region packages/schema/src/types/outline.ts
292
+ /**
293
+ * `outline` — hierarchical outline with keyboard navigation. Unlimited
294
+ * descendant nesting; all descendants are untyped.
295
+ */
296
+ const OutlineMeta = UniversalMeta;
297
+ const Outline = defineDocType({
298
+ name: "outline",
299
+ version: 1,
300
+ meta: OutlineMeta
301
+ });
302
+ const outlineSchema = defineSchema({ types: [Outline] });
303
+
304
+ //#endregion
305
+ //#region packages/schema/src/types/checklist.ts
306
+ /**
307
+ * `checklist` — collaborative checklist with sub-tasks and due dates.
308
+ * Unlimited descendant nesting; all descendants are untyped (per-task
309
+ * `checked` / `priority` / `dateEnd` flow through universal keys).
310
+ */
311
+ const ChecklistMeta = UniversalMeta.extend({
312
+ checklistFilter: z.enum([
313
+ "all",
314
+ "active",
315
+ "completed"
316
+ ]).optional(),
317
+ checklistSort: z.enum([
318
+ "manual",
319
+ "priority",
320
+ "due"
321
+ ]).optional()
322
+ });
323
+ const Checklist = defineDocType({
324
+ name: "checklist",
325
+ version: 1,
326
+ meta: ChecklistMeta
327
+ });
328
+ const checklistSchema = defineSchema({ types: [Checklist] });
329
+
330
+ //#endregion
331
+ //#region packages/schema/src/types/graph.ts
332
+ /**
333
+ * `graph` — force-directed knowledge graph rendering. Descendants are
334
+ * untyped (per-node `graphX` / `graphY` / `graphPinned` are written to
335
+ * descendant meta but not validated by the registry).
336
+ */
337
+ const GraphMeta = UniversalMeta.extend({ showRefEdges: z.boolean().optional() });
338
+ const Graph = defineDocType({
339
+ name: "graph",
340
+ version: 1,
341
+ meta: GraphMeta
342
+ });
343
+ const graphSchema = defineSchema({ types: [Graph] });
344
+
345
+ //#endregion
346
+ //#region packages/schema/src/types/timeline.ts
347
+ /**
348
+ * `timeline` — Gantt-style project timeline. Direct children are epics;
349
+ * grandchildren are tasks (both untyped). Per-bar `dateStart` /
350
+ * `dateEnd` / `taskProgress` / `color` use universal keys.
351
+ */
352
+ const TimelineMeta = UniversalMeta;
353
+ const Timeline = defineDocType({
354
+ name: "timeline",
355
+ version: 1,
356
+ meta: TimelineMeta
357
+ });
358
+ const timelineSchema = defineSchema({ types: [Timeline] });
359
+
360
+ //#endregion
361
+ //#region packages/schema/src/types/calendar.ts
362
+ /**
363
+ * `calendar` — event calendar with month/week/day views. Direct
364
+ * children are events (untyped); per-event `datetimeStart` /
365
+ * `datetimeEnd` / `allDay` / `color` use universal keys.
366
+ */
367
+ const CalendarMeta = UniversalMeta.extend({
368
+ calendarWeekStart: z.enum(["sun", "mon"]).optional(),
369
+ calendarView: z.enum([
370
+ "month",
371
+ "week",
372
+ "day"
373
+ ]).optional(),
374
+ calendarShowWeekNumbers: z.boolean().optional()
375
+ });
376
+ const Calendar = defineDocType({
377
+ name: "calendar",
378
+ version: 1,
379
+ meta: CalendarMeta
380
+ });
381
+ const calendarSchema = defineSchema({ types: [Calendar] });
382
+
383
+ //#endregion
384
+ //#region packages/schema/src/types/map.ts
385
+ /**
386
+ * `map` — collaborative world map. Direct children are markers / lines
387
+ * / measure entries (untyped, distinguished by descendant `geoType`
388
+ * key flowing through the untyped meta path).
389
+ */
390
+ const MapMeta = UniversalMeta.extend({ mapShowLabels: z.boolean().optional() });
391
+ const MapDocType = defineDocType({
392
+ name: "map",
393
+ version: 1,
394
+ meta: MapMeta
395
+ });
396
+ const mapSchema = defineSchema({ types: [MapDocType] });
397
+
398
+ //#endregion
399
+ //#region packages/schema/src/types/dashboard.ts
400
+ /**
401
+ * `dashboard` — arranges documents as draggable icons / widgets.
402
+ * Descendants are untyped; per-item `desk*` layout keys flow through
403
+ * the untyped meta path.
404
+ */
405
+ const DashboardMeta = UniversalMeta;
406
+ const Dashboard = defineDocType({
407
+ name: "dashboard",
408
+ version: 1,
409
+ meta: DashboardMeta
410
+ });
411
+ const dashboardSchema = defineSchema({ types: [Dashboard] });
412
+
413
+ //#endregion
414
+ //#region packages/schema/src/types/chart.ts
415
+ /**
416
+ * `chart` — manual data points or aggregation over document trees.
417
+ * Direct children are data points (untyped); per-point `number` /
418
+ * `color` / `tags` use universal keys.
419
+ */
420
+ const ChartMeta = UniversalMeta.extend({
421
+ chartType: z.enum([
422
+ "bar",
423
+ "stacked bar",
424
+ "line",
425
+ "donut",
426
+ "treemap"
427
+ ]).optional(),
428
+ chartMetric: z.enum([
429
+ "value",
430
+ "type",
431
+ "tag",
432
+ "status",
433
+ "priority",
434
+ "activity",
435
+ "completion"
436
+ ]).optional(),
437
+ chartColorScheme: z.enum([
438
+ "default",
439
+ "warm",
440
+ "cool",
441
+ "mono"
442
+ ]).optional(),
443
+ chartLimit: z.number().int().min(3).max(30).optional(),
444
+ chartShowLegend: z.boolean().optional(),
445
+ chartShowValues: z.boolean().optional()
446
+ });
447
+ const Chart = defineDocType({
448
+ name: "chart",
449
+ version: 1,
450
+ meta: ChartMeta
451
+ });
452
+ const chartSchema = defineSchema({ types: [Chart] });
453
+
454
+ //#endregion
455
+ //#region packages/schema/src/types/sheets.ts
456
+ /**
457
+ * `sheets` — spreadsheet with formulas + formatting. Direct children
458
+ * are columns; grandchildren are positional cells (both untyped).
459
+ * Per-cell `formula` / `bold` / `bgColor` / `numberFormat` etc. flow
460
+ * through the untyped meta path.
461
+ */
462
+ const SheetsMeta = UniversalMeta.extend({
463
+ sheetsDefaultColWidth: z.number().min(40).max(500).optional(),
464
+ sheetsDefaultRowHeight: z.number().min(20).max(100).optional(),
465
+ sheetsShowGridlines: z.boolean().optional()
466
+ });
467
+ const Sheets = defineDocType({
468
+ name: "sheets",
469
+ version: 1,
470
+ meta: SheetsMeta
471
+ });
472
+ const sheetsSchema = defineSchema({ types: [Sheets] });
473
+
474
+ //#endregion
475
+ //#region packages/schema/src/types/slides.ts
476
+ /**
477
+ * `slides` — two-axis presentation. Direct children are slides;
478
+ * grandchildren are sub-slides (both untyped); per-slide
479
+ * `slidesTransition` / `color` flow through the universal/untyped
480
+ * paths.
481
+ */
482
+ const SlidesMeta = UniversalMeta.extend({ slidesTheme: z.enum(["dark", "light"]).optional() });
483
+ const Slides = defineDocType({
484
+ name: "slides",
485
+ version: 1,
486
+ meta: SlidesMeta
487
+ });
488
+ const slidesSchema = defineSchema({ types: [Slides] });
489
+
490
+ //#endregion
491
+ //#region packages/schema/src/types/overview.ts
492
+ /**
493
+ * `overview` — space home: activity, people, stats. Descendants are
494
+ * regular pages; no overview-specific config keys today.
495
+ */
496
+ const OverviewMeta = UniversalMeta;
497
+ const Overview = defineDocType({
498
+ name: "overview",
499
+ version: 1,
500
+ meta: OverviewMeta
501
+ });
502
+ const overviewSchema = defineSchema({ types: [Overview] });
503
+
504
+ //#endregion
505
+ //#region packages/schema/src/manifest/plugin-manifest.ts
506
+ /**
507
+ * Runtime validation schema for plugin manifests (manifest v1).
508
+ *
509
+ * The TypeScript types live in `@abraca/plugin/src/manifest.ts` and stay
510
+ * pure — `@abraca/plugin` itself ships zero schemas per `feedback_schema_free_core`.
511
+ * This file is the opt-in Zod validator used by:
512
+ *
513
+ * - the registry server's submission pipeline (verifies submitted manifests
514
+ * before storing the artifact)
515
+ * - the `@abraca/plugin-cli` `validate` command (local pre-submit linting)
516
+ * - hosts (`cou-shell`, `@abraca/nuxt`) before instantiating an external
517
+ * plugin, when they want runtime validation in addition to the
518
+ * compile-time `PluginManifest` typing.
519
+ *
520
+ * The inferred shape is asserted to be structurally identical to
521
+ * `PluginManifest` from `@abraca/plugin` via `_check` type aliases below —
522
+ * if either side drifts, the typecheck fails.
523
+ */
524
+ /**
525
+ * Capabilities with no dynamic suffix. Anything outside this set and the two
526
+ * prefix families (`network[:*]`, `page-type:<slug>`) is rejected.
527
+ *
528
+ * Encoded as a regex pattern (not a `.refine()` callback) so the
529
+ * Zod-to-JSON-Schema codegen captures it — otherwise the registry server's
530
+ * Rust validator would have to re-implement the vocabulary in parallel.
531
+ */
532
+ const CAPABILITY_PATTERN = "^(fs:read|fs:write|clipboard:read|clipboard:write|doc-read|doc-write|awareness|server-runner|command-palette|toolbar|bubble-menu|slash-command|drag-handle|chat:send|chat:read|notifications:show|network|network:\\S+|page-type:[a-z][a-z0-9-]*)$";
533
+ const PluginCapabilitySchema = z.string().regex(new RegExp(CAPABILITY_PATTERN), { message: "unknown plugin capability — see PluginCapability in @abraca/plugin" }).transform((s) => s);
534
+ /** Lowercase-kebab slug. Starts with a letter; no consecutive dashes; no trailing dash. */
535
+ const PluginIdSchema = z.string().regex(/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/, "id must be lowercase-kebab (e.g. 'spatial', 'plugin-coder', 'my-2nd-plugin')");
536
+ /**
537
+ * Strict semver `MAJOR.MINOR.PATCH` with optional pre-release / build metadata.
538
+ * Reference: https://semver.org/spec/v2.0.0.html#backusnaur-form-grammar-for-valid-semver-versions
539
+ */
540
+ const SemverSchema = z.string().regex(/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/, "version must be valid semver (e.g. '1.2.3', '0.1.0-alpha.1')");
541
+ /**
542
+ * Loose semver range — accepts `^1.2.3`, `~1.2`, `>=1.0 <2`, `1.x`, etc.
543
+ * Not parsed here; the registry server runs `semver.validRange` for strict
544
+ * validation. We just guard against obvious junk.
545
+ */
546
+ const SemverRangeSchema = z.string().min(1).max(80).regex(/^[\d.xX*~^<>=|\s&,a-zA-Z+-]+$/, "invalid semver range");
547
+ /** `sha256-<64 hex chars>`. */
548
+ const IntegritySchema = z.string().regex(/^sha256-[0-9a-f]{64}$/, "integrity must be 'sha256-' + 64 lowercase hex chars");
549
+ /** Relative POSIX path. No `..` segments, no absolute, no protocols. */
550
+ const RelativePathSchema = z.string().min(1).max(256).refine((p) => !p.startsWith("/") && !/^[a-z]+:\/\//i.test(p) && !p.split("/").includes(".."), "must be a relative path with no '..' segments");
551
+ const PluginManifestAuthorSchema = z.object({
552
+ github: z.string().min(1).max(64).optional(),
553
+ name: z.string().min(1).max(120).optional(),
554
+ url: z.string().url().max(512).optional(),
555
+ email: z.string().email().max(254).optional()
556
+ });
557
+ const PluginPricingSchema = z.enum([
558
+ "free",
559
+ "optional",
560
+ "paid"
561
+ ]);
562
+ const PluginVersionStatusSchema = z.enum([
563
+ "live",
564
+ "pending",
565
+ "rejected",
566
+ "superseded"
567
+ ]);
568
+ const PluginManifestContributesSchema = z.object({
569
+ pageTypes: z.array(z.string().min(1)).readonly().optional(),
570
+ extensions: z.array(z.string().min(1)).readonly().optional(),
571
+ awarenessFields: z.array(z.string().min(1)).readonly().optional(),
572
+ serverRunners: z.array(z.string().min(1)).readonly().optional(),
573
+ commands: z.array(z.string().min(1)).readonly().optional(),
574
+ settingsPanels: z.array(z.string().min(1)).readonly().optional()
575
+ });
576
+ const PluginManifestSchema = z.object({
577
+ manifestVersion: z.literal(1),
578
+ id: PluginIdSchema,
579
+ name: z.string().min(1).max(80).optional(),
580
+ version: SemverSchema,
581
+ author: PluginManifestAuthorSchema,
582
+ license: z.string().min(1).max(80),
583
+ description: z.string().min(1).max(280),
584
+ readme: z.string().max(1e5).optional(),
585
+ homepage: z.string().url().max(512).optional(),
586
+ repository: z.string().min(3).max(512).optional(),
587
+ minAbracadabraVersion: SemverRangeSchema.optional(),
588
+ entry: RelativePathSchema,
589
+ integrity: IntegritySchema,
590
+ pricing: PluginPricingSchema.optional(),
591
+ screenshots: z.array(RelativePathSchema).max(20).readonly().optional(),
592
+ categories: z.array(z.string().min(1).max(40)).max(10).readonly().optional(),
593
+ capabilities: z.object({
594
+ required: z.array(PluginCapabilitySchema).readonly(),
595
+ optional: z.array(PluginCapabilitySchema).readonly().optional()
596
+ }),
597
+ contributes: PluginManifestContributesSchema.optional(),
598
+ peerDeps: z.record(z.string(), SemverRangeSchema).optional()
599
+ });
600
+ /**
601
+ * Parse and validate a manifest. Always returns a result object — never
602
+ * throws. Useful for surface UIs (the registry submission flow, the CLI's
603
+ * `validate` command) that want to render every issue at once.
604
+ */
605
+ function validatePluginManifest(value) {
606
+ const parsed = PluginManifestSchema.safeParse(value);
607
+ if (parsed.success) return {
608
+ ok: true,
609
+ value: parsed.data
610
+ };
611
+ return {
612
+ ok: false,
613
+ errors: parsed.error.issues.map((i) => ({
614
+ path: i.path,
615
+ message: i.message,
616
+ code: i.code
617
+ }))
618
+ };
619
+ }
620
+
621
+ //#endregion
622
+ //#region packages/schema/src/index.ts
623
+ /**
624
+ * Declare a doc-type. The returned value carries enough type information for
625
+ * downstream codegen and is a `DocType` once registered.
626
+ */
627
+ function defineDocType(spec) {
628
+ return {
629
+ ...spec,
630
+ __resolved: true
631
+ };
632
+ }
633
+ /** Reference another doc-type by name. Resolution happens in {@link defineSchema}. */
634
+ function ref(name) {
635
+ return { __ref: name };
636
+ }
637
+ /**
638
+ * Build a registry from a list of doc-types. Validates that all `ref(...)`
639
+ * targets exist; throws on dangling references.
640
+ *
641
+ * The returned registry carries a phantom `__metaMap` witness inferred from
642
+ * `spec`, so call sites like `provider.docs(schema).get("kanban", id)`
643
+ * see fully-typed meta even though the registry's runtime shape is generic.
644
+ */
645
+ function defineSchema(spec) {
646
+ const types = /* @__PURE__ */ new Map();
647
+ for (const t of spec.types) {
648
+ if (types.has(t.name)) throw new Error(`Duplicate doc-type name: ${t.name}`);
649
+ types.set(t.name, t);
650
+ }
651
+ for (const t of spec.types) for (const child of t.children ?? []) if (!types.has(child.__ref)) throw new Error(`Doc-type "${t.name}" references unknown child doc-type "${child.__ref}"`);
652
+ return {
653
+ types,
654
+ get(name) {
655
+ return types.get(name);
656
+ },
657
+ validateChildType(parent, child) {
658
+ if (!types.has(child)) return {
659
+ ok: false,
660
+ errors: [{
661
+ path: [],
662
+ message: `Unknown doc-type: ${child}`
663
+ }]
664
+ };
665
+ if (parent === null) return {
666
+ ok: false,
667
+ errors: [{
668
+ path: [],
669
+ message: `Doc-type "${child}" cannot be a root document — root-eligibility is reserved for Phase 2`
670
+ }]
671
+ };
672
+ const parentType = types.get(parent);
673
+ if (!parentType) return {
674
+ ok: false,
675
+ errors: [{
676
+ path: [],
677
+ message: `Unknown parent doc-type: ${parent}`
678
+ }]
679
+ };
680
+ if ((parentType.children ?? []).some((c) => c.__ref === child)) return {
681
+ ok: true,
682
+ value: void 0
683
+ };
684
+ return {
685
+ ok: false,
686
+ errors: [{
687
+ path: [],
688
+ message: `Doc-type "${child}" is not an allowed child of "${parent}"`
689
+ }]
690
+ };
691
+ },
692
+ validateMeta(name, value) {
693
+ const t = types.get(name);
694
+ if (!t) return {
695
+ ok: true,
696
+ value
697
+ };
698
+ const parsed = t.meta.safeParse(value);
699
+ if (parsed.success) return {
700
+ ok: true,
701
+ value: parsed.data
702
+ };
703
+ return {
704
+ ok: false,
705
+ errors: parsed.error.issues.map((i) => ({
706
+ path: i.path,
707
+ message: i.message,
708
+ code: i.code
709
+ }))
710
+ };
711
+ }
712
+ };
713
+ }
714
+ /**
715
+ * Apply forward migrations to a meta object.
716
+ *
717
+ * Reads `meta.__schemaVersion` (defaults to `1` if absent) and applies
718
+ * each `migrations[v]` from there up to the schema's declared `version`.
719
+ * Each migration function receives the previous version's meta and
720
+ * returns the next version's meta. The final value carries
721
+ * `__schemaVersion = <highest version reached>`.
722
+ *
723
+ * Behaviour:
724
+ * - **Unknown doc-type**: returns `meta` unchanged. Rule 4 — registries
725
+ * only constrain the types they declare.
726
+ * - **No migrations declared**: returns `meta` unchanged. Useful for
727
+ * freshly-introduced doc-types still at v1.
728
+ * - **Missing migration entry mid-chain**: stops at the highest
729
+ * reachable version. Caller can detect by inspecting
730
+ * `result.__schemaVersion` against `schema.get(typeName)?.version`.
731
+ * - **Non-object meta** (null, undefined, primitives): returns
732
+ * unchanged. Migrations only operate on object meta.
733
+ *
734
+ * Migrations are pure: they receive a meta value and return a new
735
+ * one. They MUST NOT mutate the input (callers may pass shared
736
+ * references).
737
+ *
738
+ * @example
739
+ * // v2 of kanban introduces a new required-shape `boardLayout` key.
740
+ * const Kanban = defineDocType({
741
+ * name: "kanban",
742
+ * version: 2,
743
+ * meta: KanbanMetaV2,
744
+ * migrations: {
745
+ * 1: (oldMeta) => ({ ...oldMeta, boardLayout: "default" }),
746
+ * },
747
+ * });
748
+ * const fresh = runMigrations(kanbanSchema, "kanban", { kanbanShowIcon: true });
749
+ * // fresh.boardLayout === "default"
750
+ * // fresh.__schemaVersion === 2
751
+ */
752
+ function runMigrations(registry, typeName, meta) {
753
+ if (meta === null || typeof meta !== "object") return meta;
754
+ const t = registry.get(typeName);
755
+ if (!t) return meta;
756
+ const target = t.version;
757
+ const migrations = t.migrations;
758
+ const m = meta;
759
+ let currentVersion = typeof m.__schemaVersion === "number" && m.__schemaVersion >= 1 ? m.__schemaVersion : 1;
760
+ if (currentVersion >= target) return meta;
761
+ if (!migrations) return meta;
762
+ let working = meta;
763
+ let migrated = false;
764
+ while (currentVersion < target) {
765
+ const fn = migrations[currentVersion];
766
+ if (typeof fn !== "function") break;
767
+ working = fn(working);
768
+ currentVersion += 1;
769
+ migrated = true;
770
+ }
771
+ if (!migrated) return meta;
772
+ if (working === null || typeof working !== "object") return working;
773
+ return {
774
+ ...working,
775
+ __schemaVersion: currentVersion
776
+ };
777
+ }
778
+
779
+ //#endregion
780
+ export { Calendar, CalendarMeta, Chart, ChartMeta, Checklist, ChecklistMeta, Dashboard, DashboardMeta, Doc, DocMeta, Gallery, GalleryMeta, Graph, GraphMeta, IntegritySchema, Kanban, KanbanMeta, META_COLUMNS, MapDocType, MapMeta, Outline, OutlineMeta, Overview, OverviewMeta, PluginCapabilitySchema, PluginIdSchema, PluginManifestAuthorSchema, PluginManifestContributesSchema, PluginManifestSchema, PluginPricingSchema, PluginVersionStatusSchema, Prose, ProseMeta, RelativePathSchema, SemverRangeSchema, SemverSchema, Sheets, SheetsMeta, Slides, SlidesMeta, Table, TableMeta, Timeline, TimelineMeta, UniversalMeta, WhereClauseSchema, calendarSchema, chartSchema, checklistSchema, crdtMetaOf, dashboardSchema, defineDocType, defineSchema, docSchema, gallerySchema, graphSchema, kanbanSchema, mapSchema, outlineSchema, overviewSchema, parseWhereClause, proseSchema, ref, runMigrations, sheetsSchema, slidesSchema, tableSchema, timelineSchema, validatePluginManifest, yarray, ymap, ytext };
781
+ //# sourceMappingURL=abracadabra-schema.esm.js.map