@plitzi/sdk-schema 0.37.8 → 0.37.9

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.
@@ -1,27 +1,37 @@
1
1
  import { isValidElementId as e } from "./elementId.mjs";
2
- import { findLayoutCycle as t } from "@plitzi/sdk-shared/schema/layoutChain";
2
+ import { isInstance as t, propNameProblem as n } from "./components.mjs";
3
+ import { findLayoutCycle as r } from "@plitzi/sdk-shared/schema/layoutChain";
3
4
  //#region src/helpers/schemaValidator.ts
4
- var n = /* @__PURE__ */ new Set([
5
+ var i = /* @__PURE__ */ new Set([
5
6
  "UNRESOLVED_BINDING_SOURCE",
6
7
  "MISMATCHED_BINDING_SOURCE",
7
- "UNRESOLVED_INTERACTION_TARGET"
8
- ]), r = (e) => !n.has(e.code), i = (n) => {
9
- let r = [], i = [], { flat: a, pages: o, pageFolders: s, variables: c } = n, l = (e) => !!a[e], u = (e) => a[e], d = () => Object.values(a).filter((e) => e?.definition?.type === "layoutContainer" && !e.definition.parentId).map((e) => e.id), f = () => [...o, ...d()], p = () => !a || typeof a != "object" ? (r.push({
8
+ "UNRESOLVED_INTERACTION_TARGET",
9
+ "UNRESOLVED_COMPONENT",
10
+ "UNKNOWN_COMPONENT_SLOT"
11
+ ]), a = (e) => !i.has(e.code), o = (i, a) => {
12
+ let s = [], c = [], { flat: l, pages: u, pageFolders: d, variables: f, components: p } = i, m = a?.baseElementId, h = (e) => !!l[e], g = (e) => l[e], _ = () => Object.values(l).filter((e) => e?.definition?.type === "layoutContainer" && !e.definition.parentId).map((e) => e.id), v = () => [.../* @__PURE__ */ new Set([
13
+ ...u,
14
+ ..._(),
15
+ ...m ? [m] : []
16
+ ])], y = () => !l || typeof l != "object" ? (s.push({
10
17
  code: "INVALID_FLAT",
11
18
  message: "Schema.flat must be a valid Record<string, Element>"
12
- }), !1) : Array.isArray(o) ? Array.isArray(s) ? Array.isArray(c) ? !0 : (r.push({
19
+ }), !1) : Array.isArray(u) ? Array.isArray(d) ? Array.isArray(f) ? !p || typeof p != "object" ? (s.push({
20
+ code: "INVALID_COMPONENTS",
21
+ message: "Schema.components must be a Record<string, SpaceComponent>"
22
+ }), !1) : !0 : (s.push({
13
23
  code: "INVALID_VARIABLES",
14
24
  message: "Schema.variables must be an array"
15
- }), !1) : (r.push({
25
+ }), !1) : (s.push({
16
26
  code: "INVALID_PAGE_FOLDERS",
17
27
  message: "Schema.pageFolders must be an array"
18
- }), !1) : (r.push({
28
+ }), !1) : (s.push({
19
29
  code: "INVALID_PAGES",
20
30
  message: "Schema.pages must be an array of element IDs"
21
- }), !1), m = () => {
22
- Object.entries(a).forEach(([e, t]) => {
31
+ }), !1), b = () => {
32
+ Object.entries(l).forEach(([e, t]) => {
23
33
  if (!t) {
24
- r.push({
34
+ s.push({
25
35
  code: "NULL_ELEMENT",
26
36
  message: `Element with id "${e}" is null or undefined`,
27
37
  elementId: e
@@ -29,47 +39,47 @@ var n = /* @__PURE__ */ new Set([
29
39
  return;
30
40
  }
31
41
  if (!t.id) {
32
- r.push({
42
+ s.push({
33
43
  code: "MISSING_ID",
34
44
  message: `Element at key "${e}" has no id property`
35
45
  });
36
46
  return;
37
47
  }
38
- if (t.id !== e && r.push({
48
+ if (t.id !== e && s.push({
39
49
  code: "ID_MISMATCH",
40
50
  message: `Element id "${t.id}" doesn't match flat key "${e}"`,
41
51
  elementId: e
42
52
  }), !t.definition) {
43
- r.push({
53
+ s.push({
44
54
  code: "MISSING_DEFINITION",
45
55
  message: "Element missing definition",
46
56
  elementId: e
47
57
  });
48
58
  return;
49
59
  }
50
- let { definition: n, attributes: a } = t;
51
- n.type || r.push({
60
+ let { definition: n, attributes: r } = t;
61
+ n.type || s.push({
52
62
  code: "MISSING_TYPE",
53
63
  message: "Element missing definition.type",
54
64
  elementId: e
55
- }), n.label === void 0 && r.push({
65
+ }), n.label === void 0 && s.push({
56
66
  code: "MISSING_LABEL",
57
67
  message: "Element missing definition.label",
58
68
  elementId: e
59
- }), n.rootId || r.push({
69
+ }), n.rootId || s.push({
60
70
  code: "MISSING_ROOT_ID",
61
71
  message: "Element missing definition.rootId",
62
72
  elementId: e
63
- }), (!n.styleSelectors || typeof n.styleSelectors != "object") && r.push({
73
+ }), (!n.styleSelectors || typeof n.styleSelectors != "object") && s.push({
64
74
  code: "MISSING_STYLE_SELECTORS",
65
75
  message: "Element missing or invalid definition.styleSelectors",
66
76
  elementId: e
67
- }), a || i.push({
77
+ }), r || c.push({
68
78
  code: "MISSING_ATTRIBUTES",
69
79
  message: "Element has no attributes",
70
80
  elementId: e
71
81
  }), n.items && (Array.isArray(n.items) ? n.items.forEach((t, n) => {
72
- l(t) || r.push({
82
+ h(t) || s.push({
73
83
  code: "ORPHANED_ITEM_REFERENCE",
74
84
  message: `Element "${e}" references non-existent child "${t}" at items[${n}]`,
75
85
  elementId: e,
@@ -78,24 +88,24 @@ var n = /* @__PURE__ */ new Set([
78
88
  index: n
79
89
  }
80
90
  });
81
- }) : r.push({
91
+ }) : s.push({
82
92
  code: "INVALID_ITEMS",
83
93
  message: "Element.definition.items must be an array",
84
94
  elementId: e
85
- })), n.parentId && !l(n.parentId) && r.push({
95
+ })), n.parentId && !h(n.parentId) && s.push({
86
96
  code: "ORPHANED_PARENT_REFERENCE",
87
97
  message: `Element "${e}" has parentId "${n.parentId}" but parent doesn't exist in flat`,
88
98
  elementId: e,
89
99
  details: { parentId: n.parentId }
90
100
  });
91
101
  });
92
- }, h = () => {
93
- Object.values(a).forEach((e) => {
102
+ }, x = () => {
103
+ Object.values(l).forEach((e) => {
94
104
  if (!e?.definition) return;
95
105
  let { id: t, definition: n } = e;
96
106
  if (n.items && n.items.forEach((e) => {
97
- let n = u(e);
98
- n?.definition && n.definition.parentId !== t && r.push({
107
+ let n = g(e);
108
+ n?.definition && n.definition.parentId !== t && s.push({
99
109
  code: "PARENT_CHILD_MISMATCH",
100
110
  message: `Element "${e}" is in "${t}".items but has parentId "${n.definition.parentId}"`,
101
111
  elementId: e,
@@ -105,87 +115,87 @@ var n = /* @__PURE__ */ new Set([
105
115
  }
106
116
  });
107
117
  }), n.parentId) {
108
- let e = u(n.parentId);
118
+ let e = g(n.parentId);
109
119
  if (!e?.definition) return;
110
- let i = e.definition.items || [];
111
- i.includes(t) || r.push({
120
+ let r = e.definition.items || [];
121
+ r.includes(t) || s.push({
112
122
  code: "PARENT_CHILD_MISMATCH",
113
123
  message: `Element "${t}" has parentId "${n.parentId}" but parent doesn't have it in items`,
114
124
  elementId: t,
115
125
  details: {
116
126
  parentId: n.parentId,
117
- parentItems: i
127
+ parentItems: r
118
128
  }
119
129
  });
120
130
  }
121
131
  });
122
- }, g = () => {
123
- let e = /* @__PURE__ */ new Set(), t = /* @__PURE__ */ new Set(), n = (i) => {
124
- if (t.has(i)) return r.push({
132
+ }, S = () => {
133
+ let e = /* @__PURE__ */ new Set(), t = /* @__PURE__ */ new Set(), n = (r) => {
134
+ if (t.has(r)) return s.push({
125
135
  code: "CIRCULAR_REFERENCE",
126
- message: `Circular reference detected involving element "${i}"`,
127
- elementId: i
136
+ message: `Circular reference detected involving element "${r}"`,
137
+ elementId: r
128
138
  }), !0;
129
- if (e.has(i)) return !1;
130
- e.add(i), t.add(i);
131
- let a = u(i);
132
- if (a?.definition?.items) {
133
- for (let e of a.definition.items) if (n(e)) return t.delete(i), !0;
139
+ if (e.has(r)) return !1;
140
+ e.add(r), t.add(r);
141
+ let i = g(r);
142
+ if (i?.definition?.items) {
143
+ for (let e of i.definition.items) if (n(e)) return t.delete(r), !0;
134
144
  }
135
- let o = /* @__PURE__ */ new Set(), s = a;
136
- for (; s?.definition?.parentId;) {
137
- if (o.has(s.id)) return r.push({
145
+ let a = /* @__PURE__ */ new Set(), o = i;
146
+ for (; o?.definition?.parentId;) {
147
+ if (a.has(o.id)) return s.push({
138
148
  code: "CIRCULAR_PARENT_REFERENCE",
139
- message: `Circular parent reference detected involving element "${s.id}"`,
140
- elementId: s.id
149
+ message: `Circular parent reference detected involving element "${o.id}"`,
150
+ elementId: o.id
141
151
  }), !0;
142
- o.add(s.id), s = u(s.definition.parentId);
152
+ a.add(o.id), o = g(o.definition.parentId);
143
153
  }
144
- return t.delete(i), !1;
154
+ return t.delete(r), !1;
145
155
  };
146
- Object.keys(a).forEach((t) => {
156
+ Object.keys(l).forEach((t) => {
147
157
  e.has(t) || n(t);
148
158
  });
149
- }, _ = () => {
159
+ }, C = () => {
150
160
  let e = /* @__PURE__ */ new Set(), t = 0;
151
- o.forEach((n, i) => {
152
- e.has(n) && r.push({
161
+ u.forEach((n, r) => {
162
+ e.has(n) && s.push({
153
163
  code: "DUPLICATE_PAGE",
154
- message: `Duplicate page ID "${n}" in pages array at index ${i}`,
164
+ message: `Duplicate page ID "${n}" in pages array at index ${r}`,
155
165
  elementId: n
156
166
  }), e.add(n);
157
- let a = u(n);
158
- if (!a) {
159
- r.push({
167
+ let i = g(n);
168
+ if (!i) {
169
+ s.push({
160
170
  code: "INVALID_PAGE_REFERENCE",
161
171
  message: `Page ID "${n}" in pages array doesn't exist in flat`,
162
172
  elementId: n
163
173
  });
164
174
  return;
165
175
  }
166
- a.definition.type !== "page" && r.push({
176
+ i.definition.type !== "page" && s.push({
167
177
  code: "INVALID_PAGE_TYPE",
168
- message: `Element "${n}" in pages array has type "${a.definition.type}" instead of "page"`,
178
+ message: `Element "${n}" in pages array has type "${i.definition.type}" instead of "page"`,
169
179
  elementId: n
170
- }), a.definition.rootId !== n && r.push({
180
+ }), i.definition.rootId !== n && s.push({
171
181
  code: "PAGE_ROOT_ID_MISMATCH",
172
- message: `Page "${n}" has rootId "${a.definition.rootId}" instead of its own ID`,
182
+ message: `Page "${n}" has rootId "${i.definition.rootId}" instead of its own ID`,
173
183
  elementId: n
174
- }), a.attributes?.default && t++;
175
- }), t === 0 && o.length > 0 ? i.push({
184
+ }), i.attributes?.default && t++;
185
+ }), t === 0 && u.length > 0 ? c.push({
176
186
  code: "NO_DEFAULT_PAGE",
177
187
  message: "No default page found in schema"
178
- }) : t > 1 && i.push({
188
+ }) : t > 1 && c.push({
179
189
  code: "MULTIPLE_DEFAULT_PAGES",
180
190
  message: `Found ${t} default pages, expected 1`
181
191
  });
182
- }, v = () => {
183
- f().forEach((e) => {
184
- let t = u(e);
192
+ }, w = () => {
193
+ v().forEach((e) => {
194
+ let t = g(e);
185
195
  if (!t) return;
186
- let n = (t) => {
187
- let i = u(t);
188
- i?.definition && (i.definition.rootId !== e && r.push({
196
+ let n = /* @__PURE__ */ new Set([e]), r = (t) => {
197
+ let i = g(t);
198
+ i?.definition && !n.has(t) && (n.add(t), i.definition.rootId !== e && s.push({
189
199
  code: "ROOT_ID_MISMATCH",
190
200
  message: `Element "${t}" has rootId "${i.definition.rootId}" but should be "${e}" (its root's ID)`,
191
201
  elementId: t,
@@ -193,124 +203,124 @@ var n = /* @__PURE__ */ new Set([
193
203
  expectedRootId: e,
194
204
  actualRootId: i.definition.rootId
195
205
  }
196
- }), i.definition.items && i.definition.items.forEach((e) => n(e)));
206
+ }), i.definition.items && i.definition.items.forEach((e) => r(e)));
197
207
  };
198
- t.definition.items && t.definition.items.forEach((e) => n(e));
208
+ t.definition.items && t.definition.items.forEach((e) => r(e));
199
209
  });
200
- }, y = () => {
210
+ }, T = () => {
201
211
  let e = /* @__PURE__ */ new Set();
202
- s.forEach((t, n) => {
212
+ d.forEach((t, n) => {
203
213
  if (!t.id) {
204
- r.push({
214
+ s.push({
205
215
  code: "INVALID_FOLDER",
206
216
  message: `Page folder at index ${n} has no id`
207
217
  });
208
218
  return;
209
219
  }
210
- e.has(t.id) && r.push({
220
+ e.has(t.id) && s.push({
211
221
  code: "DUPLICATE_FOLDER",
212
222
  message: `Duplicate folder ID "${t.id}"`,
213
223
  elementId: t.id
214
- }), e.add(t.id), t.parentId && (e.has(t.parentId) || r.push({
224
+ }), e.add(t.id), t.parentId && (e.has(t.parentId) || s.push({
215
225
  code: "ORPHANED_FOLDER_PARENT",
216
226
  message: `Folder "${t.id}" has non-existent parent "${t.parentId}"`,
217
227
  elementId: t.id,
218
228
  details: { parentId: t.parentId }
219
229
  }));
220
230
  });
221
- }, b = () => {
231
+ }, E = () => {
222
232
  let e = /* @__PURE__ */ new Set();
223
- d().forEach((n) => {
224
- let i = t(u, n);
225
- i.length === 0 || e.has(i[0]) || (i.forEach((t) => e.add(t)), r.push({
233
+ _().forEach((t) => {
234
+ let n = r(g, t);
235
+ n.length === 0 || e.has(n[0]) || (n.forEach((t) => e.add(t)), s.push({
226
236
  code: "LAYOUT_CYCLE",
227
- message: `Layouts sit inside each other in a circle: ${i.join(" → ")}`,
228
- elementId: n,
229
- details: { cycle: i }
237
+ message: `Layouts sit inside each other in a circle: ${n.join(" → ")}`,
238
+ elementId: t,
239
+ details: { cycle: n }
230
240
  }));
231
241
  });
232
- }, x = (e) => {
233
- let t = /* @__PURE__ */ new Set(), n = (e) => {
234
- if (t.has(e)) return;
235
- t.add(e);
236
- let r = u(e);
237
- r?.definition?.items && r.definition.items.forEach((e) => n(e));
238
- }, r = /* @__PURE__ */ new Set(), o = (e) => {
239
- if (r.has(e)) return;
240
- r.add(e), n(e);
241
- let t = u(e)?.attributes;
242
- t?.layout && o(t.layout), t?.layoutContainer && n(t.layoutContainer);
242
+ }, D = () => {
243
+ let e = /* @__PURE__ */ new Set(), t = (n) => {
244
+ if (e.has(n)) return;
245
+ e.add(n);
246
+ let r = g(n);
247
+ r?.definition?.items && r.definition.items.forEach((e) => t(e));
248
+ }, n = /* @__PURE__ */ new Set(), r = (e) => {
249
+ if (n.has(e)) return;
250
+ n.add(e), t(e);
251
+ let i = g(e)?.attributes;
252
+ i?.layout && r(i.layout), i?.layoutContainer && t(i.layoutContainer);
243
253
  };
244
- e ? o(e) : f().forEach(o);
245
- let s = new Set(f());
246
- Object.keys(a).forEach((e) => {
247
- let n = u(e);
248
- n && !t.has(e) && n.definition.type !== "page" && !s.has(e) && i.push({
254
+ m ? r(m) : v().forEach(r);
255
+ let i = new Set(v());
256
+ Object.keys(l).forEach((t) => {
257
+ let n = g(t);
258
+ n && !e.has(t) && n.definition.type !== "page" && !i.has(t) && c.push({
249
259
  code: "ORPHANED_ELEMENT",
250
- message: `Element "${e}" is not reachable from any page or layout`,
251
- elementId: e
260
+ message: `Element "${t}" is not reachable from any page or layout`,
261
+ elementId: t
252
262
  });
253
263
  });
254
- }, S = () => {
264
+ }, O = () => {
255
265
  let e = /* @__PURE__ */ new Set();
256
- c.forEach((t, n) => {
266
+ f.forEach((t, n) => {
257
267
  if (!t.name) {
258
- r.push({
268
+ s.push({
259
269
  code: "INVALID_VARIABLE",
260
270
  message: `Variable at index ${n} has no name`
261
271
  });
262
272
  return;
263
273
  }
264
- e.has(t.name) && r.push({
274
+ e.has(t.name) && s.push({
265
275
  code: "DUPLICATE_VARIABLE",
266
276
  message: `Duplicate variable name "${t.name}"`,
267
277
  details: { variableName: t.name }
268
- }), e.add(t.name), t.type || i.push({
278
+ }), e.add(t.name), t.type || c.push({
269
279
  code: "MISSING_VARIABLE_TYPE",
270
280
  message: `Variable "${t.name}" has no type`,
271
281
  details: { variableName: t.name }
272
282
  });
273
283
  });
274
- }, C = () => {
275
- Object.values(a).forEach((t) => {
276
- t && (e(t.id) || r.push({
284
+ }, k = () => {
285
+ Object.values(l).forEach((t) => {
286
+ t && (e(t.id) || s.push({
277
287
  code: "INVALID_ELEMENT_ID",
278
288
  message: `Element "${t.id}" has a name that must start with a letter, then letters, numbers, hyphens and underscores (no hyphen or underscore at the start, and no hyphen at the end)`,
279
289
  elementId: t.id
280
290
  }));
281
291
  });
282
- }, w = (e) => {
283
- let t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Map();
284
- Object.values(a).forEach((r) => {
285
- if (!r) return;
286
- t.add(r.id);
287
- let a = e?.[r.definition.type];
288
- a && i.set(r.id, a), n.add(r.definition.type);
289
- }), Object.values(a).forEach((a) => {
290
- a && a.definition.bindings && Object.entries(a.definition.bindings).forEach(([o, s]) => {
291
- (s ?? []).forEach((s) => {
292
- let c = s.source.split(".")[0], l = c.indexOf("_");
292
+ }, A = (e) => {
293
+ let t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Map();
294
+ Object.values(l).forEach((i) => {
295
+ if (!i) return;
296
+ t.add(i.id);
297
+ let a = e?.[i.definition.type];
298
+ a && r.set(i.id, a), n.add(i.definition.type);
299
+ }), Object.values(l).forEach((i) => {
300
+ i && i.definition.bindings && Object.entries(i.definition.bindings).forEach(([a, o]) => {
301
+ (o ?? []).forEach((o) => {
302
+ let c = o.source.split(".")[0], l = c.indexOf("_");
293
303
  if (l === -1) return;
294
- let u = c.slice(0, l), d = c.slice(l + 1), f = `Element "${a.id}" binds ${o}.${s.to} to "${s.source}"`;
304
+ let u = c.slice(0, l), d = c.slice(l + 1), f = `Element "${i.id}" binds ${a}.${o.to} to "${o.source}"`;
295
305
  if (!t.has(d)) {
296
- (e || n.has(u)) && r.push({
306
+ (e || n.has(u)) && s.push({
297
307
  code: "UNRESOLVED_BINDING_SOURCE",
298
308
  message: `${f}, but no element answers to the name "${d}"`,
299
- elementId: a.id,
309
+ elementId: i.id,
300
310
  details: {
301
- source: s.source,
311
+ source: o.source,
302
312
  elementId: d
303
313
  }
304
314
  });
305
315
  return;
306
316
  }
307
- let p = i.get(d);
308
- p && p !== u && r.push({
317
+ let p = r.get(d);
318
+ p && p !== u && s.push({
309
319
  code: "MISMATCHED_BINDING_SOURCE",
310
320
  message: `${f}, but "${d}" publishes its source as "${p}_${d}"`,
311
- elementId: a.id,
321
+ elementId: i.id,
312
322
  details: {
313
- source: s.source,
323
+ source: o.source,
314
324
  elementId: d,
315
325
  expected: `${p}_${d}`
316
326
  }
@@ -318,87 +328,190 @@ var n = /* @__PURE__ */ new Set([
318
328
  });
319
329
  });
320
330
  });
321
- }, T = () => {
322
- let t = new Set(Object.keys(a));
323
- Object.values(a).forEach((n) => {
324
- let a = n?.definition.interactions;
325
- if (!a) return;
326
- let o = Object.keys(a);
327
- Object.entries(a).forEach(([a, s]) => {
328
- e(a) || r.push({
331
+ }, j = () => {
332
+ let t = new Set(Object.keys(l));
333
+ Object.values(l).forEach((n) => {
334
+ let r = n?.definition.interactions;
335
+ if (!r) return;
336
+ let i = Object.keys(r);
337
+ Object.entries(r).forEach(([r, a]) => {
338
+ e(r) || s.push({
329
339
  code: "INVALID_INTERACTION_ID",
330
- message: `Interaction "${a}" on element "${n.id}" has a name that must start with a letter, then letters, numbers, hyphens and underscores — a later step reads it as {{ ${a}.field }}`,
340
+ message: `Interaction "${r}" on element "${n.id}" has a name that must start with a letter, then letters, numbers, hyphens and underscores — a later step reads it as {{ ${r}.field }}`,
331
341
  elementId: n.id
332
- }), s.id !== a && r.push({
342
+ }), a.id !== r && s.push({
333
343
  code: "INTERACTION_ID_MISMATCH",
334
- message: `Interaction id "${s.id}" on element "${n.id}" doesn't match its key "${a}"`,
344
+ message: `Interaction id "${a.id}" on element "${n.id}" doesn't match its key "${r}"`,
335
345
  elementId: n.id
336
346
  }), ["beforeNode", "afterNode"].forEach((e) => {
337
- let t = s[e];
338
- t && !o.includes(t) && r.push({
347
+ let t = a[e];
348
+ t && !i.includes(t) && s.push({
339
349
  code: "BROKEN_FLOW_LINK",
340
- message: `Interaction "${s.id}" on element "${n.id}" names ${e} "${t}", which is not a node of this flow`,
350
+ message: `Interaction "${a.id}" on element "${n.id}" names ${e} "${t}", which is not a node of this flow`,
341
351
  elementId: n.id
342
352
  });
343
- }), s.flowId && !o.includes(s.flowId) && r.push({
353
+ }), a.flowId && !i.includes(a.flowId) && s.push({
344
354
  code: "BROKEN_FLOW_ID",
345
- message: `Interaction "${s.id}" on element "${n.id}" belongs to flow "${s.flowId}", which is not a node of this flow`,
355
+ message: `Interaction "${a.id}" on element "${n.id}" belongs to flow "${a.flowId}", which is not a node of this flow`,
346
356
  elementId: n.id
347
- }), s.type === "callback" && s.elementId && !t.has(s.elementId) && r.push({
357
+ }), a.type === "callback" && a.elementId && !t.has(a.elementId) && s.push({
348
358
  code: "UNRESOLVED_INTERACTION_TARGET",
349
- message: `Interaction "${s.id}" on element "${n.id}" runs against "${s.elementId}", but no element answers to that name`,
359
+ message: `Interaction "${a.id}" on element "${n.id}" runs against "${a.elementId}", but no element answers to that name`,
350
360
  elementId: n.id
351
361
  });
352
- let c = s.type === "trigger" && s.action === "onSubmit" && s.enabled ? u(s.elementId ?? n.id) : void 0;
353
- c?.definition.type === "form" && c.attributes.managedByInteractions !== !0 && i.push({
362
+ let o = a.type === "trigger" && a.action === "onSubmit" && a.enabled ? g(a.elementId ?? n.id) : void 0;
363
+ o?.definition.type === "form" && o.attributes.managedByInteractions !== !0 && c.push({
354
364
  code: "FORM_SUBMIT_UNMANAGED",
355
- message: `Form "${c.id}" has an onSubmit flow but is not managedByInteractions, so the browser submits it natively and the flow never runs — set managedByInteractions: true`,
356
- elementId: c.id
365
+ message: `Form "${o.id}" has an onSubmit flow but is not managedByInteractions, so the browser submits it natively and the flow never runs — set managedByInteractions: true`,
366
+ elementId: o.id
357
367
  });
358
368
  });
359
369
  });
360
- }, E = () => {
361
- Object.values(a).forEach((e) => {
370
+ }, M = () => {
371
+ Object.values(l).forEach((e) => {
362
372
  if (!e || !e.definition.bindings) return;
363
373
  let t = /* @__PURE__ */ new Set();
364
- Object.entries(e.definition.bindings).forEach(([n, i]) => {
365
- (i ?? []).forEach((i) => {
366
- if (!i.id) {
367
- r.push({
374
+ Object.entries(e.definition.bindings).forEach(([n, r]) => {
375
+ (r ?? []).forEach((r) => {
376
+ if (!r.id) {
377
+ s.push({
368
378
  code: "MISSING_BINDING_ID",
369
- message: `Element "${e.id}" has a ${n} binding to "${i.to}" with no id`,
379
+ message: `Element "${e.id}" has a ${n} binding to "${r.to}" with no id`,
370
380
  elementId: e.id
371
381
  });
372
382
  return;
373
383
  }
374
- t.has(i.id) && r.push({
384
+ t.has(r.id) && s.push({
375
385
  code: "DUPLICATE_BINDING_ID",
376
- message: `Element "${e.id}" has two bindings called "${i.id}"`,
386
+ message: `Element "${e.id}" has two bindings called "${r.id}"`,
377
387
  elementId: e.id,
378
- details: { bindingId: i.id }
379
- }), t.add(i.id);
388
+ details: { bindingId: r.id }
389
+ }), t.add(r.id);
380
390
  });
381
391
  });
382
392
  });
383
- };
384
- return { validate: (e) => {
385
- let { baseElementId: t } = e ?? {};
386
- return p() ? (m(), h(), g(), _(), v(), y(), b(), x(t), S(), C(), w(e?.sourceTypes), E(), T(), {
387
- valid: r.length === 0,
388
- errors: r,
389
- warnings: i
390
- }) : {
391
- valid: !1,
392
- errors: r,
393
- warnings: i
393
+ }, N = () => {
394
+ let r = new Map(Object.keys(l).map((e) => [e, ""])), u = (e) => e ? `component "${e}"` : "the pages", d = /* @__PURE__ */ new Map();
395
+ Object.entries(p).forEach(([t, l]) => {
396
+ let d = `Component "${t}"`;
397
+ l.id !== t && s.push({
398
+ code: "COMPONENT_ID_MISMATCH",
399
+ message: `${d} has id "${l.id}"`,
400
+ componentId: t
401
+ }), e(t) || s.push({
402
+ code: "INVALID_COMPONENT_ID",
403
+ message: `${d} has a name that must start with a letter, then letters, numbers, hyphens and underscores`,
404
+ componentId: t
405
+ });
406
+ let f = l.flat[l.rootId];
407
+ if (!f) {
408
+ s.push({
409
+ code: "COMPONENT_ROOT_MISSING",
410
+ message: `${d} is rooted at "${l.rootId}", which is not an element of its tree`,
411
+ componentId: t
412
+ });
413
+ return;
414
+ }
415
+ f.definition.parentId && s.push({
416
+ code: "COMPONENT_ROOT_HAS_PARENT",
417
+ message: `${d} is rooted at "${l.rootId}", which names a parent — a component's root has none`,
418
+ elementId: l.rootId,
419
+ componentId: t
420
+ }), Object.keys(l.flat).forEach((e) => {
421
+ let n = r.get(e);
422
+ n === void 0 ? r.set(e, t) : s.push({
423
+ code: "DUPLICATE_ELEMENT_ID",
424
+ message: `"${e}" names an element of ${u(n)} and one of ${u(t)} — an id is one element in the whole space`,
425
+ elementId: e,
426
+ componentId: t
427
+ });
428
+ }), Object.keys(l.props ?? {}).forEach((e) => {
429
+ let r = n(e);
430
+ r && s.push({
431
+ code: "INVALID_COMPONENT_PROP",
432
+ message: `${d}: ${r}`,
433
+ componentId: t
434
+ });
435
+ }), (l.slots ?? []).forEach((e) => {
436
+ Object.hasOwn(l.flat, e) || s.push({
437
+ code: "MISSING_COMPONENT_SLOT",
438
+ message: `${d} declares slot "${e}", which is not an element of its tree`,
439
+ componentId: t
440
+ });
441
+ });
442
+ let p = o({
443
+ ...i,
444
+ flat: l.flat,
445
+ pages: [],
446
+ pageFolders: [],
447
+ components: {}
448
+ }, {
449
+ baseElementId: l.rootId,
450
+ sourceTypes: a?.sourceTypes
451
+ }).validate();
452
+ p.errors.forEach((e) => s.push({
453
+ ...e,
454
+ message: `${d}: ${e.message}`,
455
+ componentId: t
456
+ })), p.warnings.forEach((e) => c.push({
457
+ ...e,
458
+ message: `${d}: ${e.message}`,
459
+ componentId: t
460
+ }));
461
+ }), [["", l], ...Object.entries(p).map(([e, t]) => [e, t.flat])].forEach(([e, n]) => {
462
+ Object.values(n).forEach((r) => {
463
+ if (!r || !t(r)) return;
464
+ let i = r.attributes.referenceId, a = typeof i == "string" ? p[i] : void 0;
465
+ if (!a || typeof i != "string") {
466
+ s.push({
467
+ code: "UNRESOLVED_COMPONENT",
468
+ message: `Instance "${r.id}" places component "${String(i)}", which this space does not declare`,
469
+ elementId: r.id,
470
+ ...e ? { componentId: e } : {}
471
+ });
472
+ return;
473
+ }
474
+ e && d.set(e, (d.get(e) ?? /* @__PURE__ */ new Set()).add(i)), (r.definition.items ?? []).forEach((t) => {
475
+ let o = n[t]?.attributes.slot ?? a.slots?.[0];
476
+ (typeof o != "string" || !a.slots?.includes(o)) && s.push({
477
+ code: "UNKNOWN_COMPONENT_SLOT",
478
+ message: `"${t}" fills ${typeof o == "string" ? `slot "${o}"` : "a slot"} of instance "${r.id}", but component "${i}" declares ${a.slots?.length ? `only ${a.slots.map((e) => `"${e}"`).join(", ")}` : "no slots"}`,
479
+ elementId: t,
480
+ ...e ? { componentId: e } : {}
481
+ });
482
+ });
483
+ });
484
+ });
485
+ let f = /* @__PURE__ */ new Set(), m = (e, t) => {
486
+ if (t.includes(e)) {
487
+ let n = [...t.slice(t.indexOf(e)), e];
488
+ n.some((e) => f.has(e)) || (n.forEach((e) => f.add(e)), s.push({
489
+ code: "COMPONENT_CYCLE",
490
+ message: `Components place each other in a circle: ${n.join(" → ")}`,
491
+ componentId: e,
492
+ details: { cycle: n }
493
+ }));
494
+ return;
495
+ }
496
+ d.get(e)?.forEach((n) => m(n, [...t, e]));
394
497
  };
498
+ Object.keys(p).forEach((e) => m(e, []));
499
+ };
500
+ return { validate: () => y() ? (b(), x(), S(), C(), w(), T(), E(), D(), O(), k(), A(a?.sourceTypes), M(), j(), m || N(), {
501
+ valid: s.length === 0,
502
+ errors: s,
503
+ warnings: c
504
+ }) : {
505
+ valid: !1,
506
+ errors: s,
507
+ warnings: c
395
508
  } };
396
- }, a = (e, t) => i(e).validate(t), o = (e, t, n) => {
397
- let r = a(e, t);
509
+ }, s = (e, t) => o(e, t).validate(), c = (e, t, n) => {
510
+ let r = s(e, t);
398
511
  if (!r.valid) {
399
512
  let e = `Invalid schema${n ? ` (${n})` : ""}: ${r.errors.map((e) => e.message).join("; ")}`;
400
513
  throw Error(e);
401
514
  }
402
- }, s = (e, t) => a(e, t).valid;
515
+ }, l = (e, t) => s(e, t).valid;
403
516
  //#endregion
404
- export { n as REFERENCE_ERROR_CODES, o as assertSchemaValid, r as isIntegrityError, s as isSchemaValid, a as validateSchema };
517
+ export { i as REFERENCE_ERROR_CODES, c as assertSchemaValid, a as isIntegrityError, l as isSchemaValid, s as validateSchema };