@plitzi/sdk-schema 0.30.19 → 0.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/helpers/FlatMap.d.ts +10 -9
- package/dist/helpers/FlatMap.mjs +116 -82
- package/dist/helpers/schemaValidator.d.ts +18 -0
- package/dist/helpers/schemaValidator.mjs +281 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +4 -3
- package/package.json +10 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @plitzi/sdk-schema
|
|
2
2
|
|
|
3
|
+
## 0.31.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- v0.31.1
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @plitzi/sdk-shared@0.31.1
|
|
10
|
+
- @plitzi/sdk-style@0.31.1
|
|
11
|
+
|
|
12
|
+
## 0.31.0
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- v0.31.0
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
- @plitzi/sdk-shared@0.31.0
|
|
22
|
+
- @plitzi/sdk-style@0.31.0
|
|
23
|
+
|
|
3
24
|
## 0.30.19
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SchemaValidationResult } from './schemaValidator';
|
|
1
2
|
import { Style, Element, Schema, DropPosition, SchemaVariable } from '@plitzi/sdk-shared';
|
|
2
3
|
export type FlatMapProps = {
|
|
3
4
|
flat?: Schema['flat'];
|
|
@@ -10,9 +11,7 @@ declare class FlatMap {
|
|
|
10
11
|
addElement: (data: Element, to: Element["id"], dropPosition?: DropPosition, initialItems?: Record<Element["id"], Element>) => boolean;
|
|
11
12
|
updateElement: (element?: Element) => boolean;
|
|
12
13
|
moveElement: (from: Element["id"], to: Element["id"], elementId: Element["id"], dropPosition?: DropPosition) => boolean;
|
|
13
|
-
getElement: (elementId: Element["id"]) => Element<
|
|
14
|
-
[key: string]: unknown;
|
|
15
|
-
}, "subType">>;
|
|
14
|
+
getElement: (elementId: Element["id"]) => Element<Record<string, unknown>>;
|
|
16
15
|
cloneElements: (elementId: Element["id"], parentId?: Element["id"], rootId?: Element["id"], excludeRoot?: boolean) => {
|
|
17
16
|
acum: Record<Element["id"], Element>;
|
|
18
17
|
item?: Element;
|
|
@@ -34,16 +33,15 @@ declare class FlatMap {
|
|
|
34
33
|
elementsStyle: Style;
|
|
35
34
|
variables: SchemaVariable[];
|
|
36
35
|
};
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
validate: () => SchemaValidationResult;
|
|
37
|
+
isValid: () => boolean;
|
|
38
|
+
assertValid: (context?: string) => void;
|
|
39
|
+
getElementVariables: (style: Style, elementId: Element["id"], flat?: Record<string, Element<Record<string, unknown>>>, variables?: SchemaVariable[]) => SchemaVariable[];
|
|
40
40
|
static getInstance: (props: FlatMapProps) => FlatMap;
|
|
41
41
|
static addElement: (flat: Schema["flat"], data: Element, to: Element["id"], dropPosition?: DropPosition, initialItems?: Record<Element["id"], Element>) => boolean;
|
|
42
42
|
static updateElement: (flat: Schema["flat"], element: Element) => boolean;
|
|
43
43
|
static moveElement: (flat: Schema["flat"], from: Element["id"], to: Element["id"], elementId: Element["id"], dropPosition?: DropPosition) => boolean;
|
|
44
|
-
static getElement: (flat: Schema["flat"], elementId: Element["id"]) => Element<
|
|
45
|
-
[key: string]: unknown;
|
|
46
|
-
}, "subType">>;
|
|
44
|
+
static getElement: (flat: Schema["flat"], elementId: Element["id"]) => Element<Record<string, unknown>>;
|
|
47
45
|
static cloneElements: (flat: Schema["flat"], elementId: Element["id"], parentId?: Element["id"], rootId?: Element["id"], excludeRoot?: boolean) => {
|
|
48
46
|
acum: Record<Element["id"], Element>;
|
|
49
47
|
item?: Element;
|
|
@@ -66,5 +64,8 @@ declare class FlatMap {
|
|
|
66
64
|
variables: SchemaVariable[];
|
|
67
65
|
};
|
|
68
66
|
static getElementVariables: (schema: Schema, style: Style, elementId: Element["id"]) => SchemaVariable[];
|
|
67
|
+
static validate: (schema: Schema) => SchemaValidationResult;
|
|
68
|
+
static isValid: (schema: Schema) => boolean;
|
|
69
|
+
static assertValid: (schema: Schema, context?: string) => void;
|
|
69
70
|
}
|
|
70
71
|
export default FlatMap;
|
package/dist/helpers/FlatMap.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
1
|
+
import { validateSchema as e } from "./schemaValidator.mjs";
|
|
2
|
+
import { get as t, set as n } from "@plitzi/plitzi-ui/helpers";
|
|
3
|
+
import { generateID as r } from "@plitzi/sdk-shared/helpers/utils";
|
|
4
|
+
import { EMPTY_SCHEMA as i, VARIABLE_REGEX as a } from "@plitzi/sdk-shared/schema/schemaConstants";
|
|
5
|
+
import { EMPTY_STYLE_SCHEMA as o } from "@plitzi/sdk-shared/style/styleConstants";
|
|
6
|
+
import s from "@plitzi/sdk-style/helpers/calculateInheriting";
|
|
6
7
|
//#region src/helpers/FlatMap.ts
|
|
7
|
-
var
|
|
8
|
+
var c = class {
|
|
8
9
|
flat;
|
|
9
10
|
variables;
|
|
10
11
|
constructor(e = {}) {
|
|
@@ -12,7 +13,7 @@ var o = class {
|
|
|
12
13
|
if (!t) throw Error("Flat is required");
|
|
13
14
|
this.flat = t, this.variables = n ?? [];
|
|
14
15
|
}
|
|
15
|
-
addElement = (
|
|
16
|
+
addElement = (e, r, i = "inside", a = {}) => {
|
|
16
17
|
let o;
|
|
17
18
|
if (i !== "custom") {
|
|
18
19
|
if (i !== "inside") {
|
|
@@ -22,26 +23,26 @@ var o = class {
|
|
|
22
23
|
} else o = this.flat[r];
|
|
23
24
|
if (!o) return !1;
|
|
24
25
|
}
|
|
25
|
-
if (i !== "custom" && (this.flat[
|
|
26
|
-
switch (
|
|
26
|
+
if (i !== "custom" && (this.flat[e.id] || !Array.isArray(t(o, "definition.items"))) || !this.isValidElement(e)) return !1;
|
|
27
|
+
switch (n(this.flat, e.id, e), i) {
|
|
27
28
|
case "left":
|
|
28
29
|
case "top": {
|
|
29
|
-
let i =
|
|
30
|
-
if (i.splice(i.findIndex((e) => e === r), 0,
|
|
31
|
-
|
|
30
|
+
let i = t(o, "definition.items", []);
|
|
31
|
+
if (i.splice(i.findIndex((e) => e === r), 0, e.id), !o) return !1;
|
|
32
|
+
n(this.flat, `${o.id}.definition.items`, i), n(this.flat, `${e.id}.definition.parentId`, o.id), n(this.flat, `${e.id}.definition.rootId`, o.definition.rootId);
|
|
32
33
|
break;
|
|
33
34
|
}
|
|
34
35
|
case "right":
|
|
35
36
|
case "bottom": {
|
|
36
|
-
let i =
|
|
37
|
-
if (i.splice(i.findIndex((e) => e === r) + 1, 0,
|
|
38
|
-
|
|
37
|
+
let i = t(o, "definition.items", []);
|
|
38
|
+
if (i.splice(i.findIndex((e) => e === r) + 1, 0, e.id), !o) return !1;
|
|
39
|
+
n(this.flat, `${o.id}.definition.items`, i), n(this.flat, `${e.id}.definition.parentId`, o.id), n(this.flat, `${e.id}.definition.rootId`, o.definition.rootId);
|
|
39
40
|
break;
|
|
40
41
|
}
|
|
41
42
|
case "inside": {
|
|
42
|
-
let i =
|
|
43
|
+
let i = t(o, "definition.items", []);
|
|
43
44
|
if (!o) return !1;
|
|
44
|
-
|
|
45
|
+
n(this.flat, `${r}.definition.items`, [...i, e.id]), n(this.flat, `${e.id}.definition.parentId`, r), n(this.flat, `${e.id}.definition.rootId`, o.definition.rootId);
|
|
45
46
|
break;
|
|
46
47
|
}
|
|
47
48
|
case "custom": break;
|
|
@@ -52,19 +53,19 @@ var o = class {
|
|
|
52
53
|
}), !0;
|
|
53
54
|
};
|
|
54
55
|
updateElement = (e) => !e || !this.flat[e.id] ? !1 : (this.flat[e.id] = e, !0);
|
|
55
|
-
moveElement = (
|
|
56
|
-
if (i === r || !this.flat[
|
|
56
|
+
moveElement = (e, r, i, a = "inside") => {
|
|
57
|
+
if (i === r || !this.flat[e]) return !1;
|
|
57
58
|
let o = this.flat[r];
|
|
58
59
|
if (!o) return !1;
|
|
59
60
|
let s = this.flat[r];
|
|
60
61
|
for (; s;) {
|
|
61
|
-
let
|
|
62
|
-
if (!
|
|
62
|
+
let e = t(s, "definition.parentId");
|
|
63
|
+
if (!e) break;
|
|
63
64
|
if (s.id === i) return !1;
|
|
64
|
-
s = this.flat[
|
|
65
|
+
s = this.flat[e];
|
|
65
66
|
}
|
|
66
67
|
if (!s) return !1;
|
|
67
|
-
let c =
|
|
68
|
+
let c = t(this.flat, `${e}.definition.items`, []).filter((e) => e !== i);
|
|
68
69
|
if ([
|
|
69
70
|
"left",
|
|
70
71
|
"top",
|
|
@@ -74,64 +75,64 @@ var o = class {
|
|
|
74
75
|
if (!o.definition.parentId) return !1;
|
|
75
76
|
let s = this.flat[o.definition.parentId];
|
|
76
77
|
if (!s) return !1;
|
|
77
|
-
let l =
|
|
78
|
-
s.id ===
|
|
78
|
+
let l = t(s, "definition.items", []);
|
|
79
|
+
s.id === e && (l = c);
|
|
79
80
|
let u = l.findIndex((e) => e === r);
|
|
80
|
-
["right", "bottom"].includes(a) && u++, l.splice(u, 0, i),
|
|
81
|
+
["right", "bottom"].includes(a) && u++, l.splice(u, 0, i), n(this.flat, `${e}.definition.items`, c), n(this.flat, `${s.id}.definition.items`, l), n(this.flat, `${i}.definition.parentId`, s.id);
|
|
81
82
|
} else if (a === "inside") {
|
|
82
83
|
if (!this.flat[r]) return !1;
|
|
83
|
-
let a =
|
|
84
|
-
|
|
84
|
+
let a = t(this.flat, `${r}.definition.items`, []);
|
|
85
|
+
e === r && (a = c), a = [...a, i], n(this.flat, `${e}.definition.items`, c), n(this.flat, `${r}.definition.items`, a), n(this.flat, `${i}.definition.parentId`, r);
|
|
85
86
|
}
|
|
86
87
|
return !0;
|
|
87
88
|
};
|
|
88
|
-
getElement = (
|
|
89
|
-
cloneElements = (
|
|
89
|
+
getElement = (e) => t(this.flat, e);
|
|
90
|
+
cloneElements = (e, i = "", a = "", o = !1) => {
|
|
90
91
|
let s = {
|
|
91
92
|
acum: {},
|
|
92
93
|
item: void 0
|
|
93
|
-
}, c = {}, l = this.flat[
|
|
94
|
+
}, c = {}, l = this.flat[e];
|
|
94
95
|
if (!l) return s;
|
|
95
|
-
let u = [
|
|
96
|
-
let
|
|
97
|
-
return
|
|
96
|
+
let u = [e, ...this.childTree(e)].reduce((e, t) => {
|
|
97
|
+
let n = this.flat[t];
|
|
98
|
+
return n ? (c[n.id] = r(n.id), a ? {
|
|
98
99
|
...e,
|
|
99
|
-
[
|
|
100
|
-
...
|
|
100
|
+
[n.id]: {
|
|
101
|
+
...n,
|
|
101
102
|
definition: {
|
|
102
|
-
...
|
|
103
|
+
...n.definition,
|
|
103
104
|
rootId: a
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
107
|
} : {
|
|
107
108
|
...e,
|
|
108
|
-
[
|
|
109
|
+
[n.id]: n
|
|
109
110
|
}) : e;
|
|
110
111
|
}, {});
|
|
111
112
|
try {
|
|
112
|
-
let
|
|
113
|
-
|
|
113
|
+
let t = JSON.stringify(u);
|
|
114
|
+
t = Object.keys(c).reduce((e, t) => e.replace(new RegExp(t, "g"), c[t]), t), s.acum = JSON.parse(t), s.item = s.acum[c[e]];
|
|
114
115
|
} catch (e) {
|
|
115
116
|
return console.error("Error parsing elements", e), {
|
|
116
117
|
acum: {},
|
|
117
118
|
item: void 0
|
|
118
119
|
};
|
|
119
120
|
}
|
|
120
|
-
o && delete s.acum[c[
|
|
121
|
+
o && delete s.acum[c[e]];
|
|
121
122
|
let d = this.flat[i];
|
|
122
|
-
return (!d || !Array.isArray(
|
|
123
|
+
return (!d || !Array.isArray(t(d, "definition.items"))) && (i = t(d, "definition.parentId", t(l, "definition.parentId"))), i && n(s, "item.definition.parentId", i), s;
|
|
123
124
|
};
|
|
124
|
-
removeElement = (
|
|
125
|
-
let i = this.flat[
|
|
126
|
-
if (!i || i.definition.type === "page" && !r || r &&
|
|
127
|
-
let a =
|
|
125
|
+
removeElement = (e, r = !1) => {
|
|
126
|
+
let i = this.flat[e];
|
|
127
|
+
if (!i || i.definition.type === "page" && !r || r && t(i, "attributes.default", !1)) return !1;
|
|
128
|
+
let a = t(i, "definition.items");
|
|
128
129
|
a && a.length > 0 && a.forEach((e) => this.removeElement(e));
|
|
129
|
-
let o =
|
|
130
|
+
let o = t(i, "definition.parentId"), s = o ? this.flat[o] : void 0;
|
|
130
131
|
if (o && s) {
|
|
131
|
-
let { definition: { items:
|
|
132
|
-
|
|
132
|
+
let { definition: { items: t = [] } } = s;
|
|
133
|
+
n(s, "definition.items", t.filter((t) => t !== e)), this.flat[o] = s;
|
|
133
134
|
}
|
|
134
|
-
return delete this.flat[
|
|
135
|
+
return delete this.flat[e], !0;
|
|
135
136
|
};
|
|
136
137
|
addVariables = (e) => {
|
|
137
138
|
if (e && e.length > 0) {
|
|
@@ -152,22 +153,22 @@ var o = class {
|
|
|
152
153
|
return this.variables = this.variables.filter((t) => e.includes(t.name)), t !== this.variables.length;
|
|
153
154
|
};
|
|
154
155
|
removeVariable = (e) => this.removeVariables([e]);
|
|
155
|
-
parentTree = (
|
|
156
|
-
let n = this.flat[
|
|
156
|
+
parentTree = (e) => {
|
|
157
|
+
let n = this.flat[e], r = [];
|
|
157
158
|
if (!n) return r;
|
|
158
159
|
do {
|
|
159
|
-
if (
|
|
160
|
-
let
|
|
161
|
-
|
|
160
|
+
if (t(n, "definition.type") === "page") {
|
|
161
|
+
let e = t(n, "attributes.layout"), i = t(n, "attributes.layoutContainer");
|
|
162
|
+
e && i && r.push(i, ...this.parentTree(i));
|
|
162
163
|
}
|
|
163
|
-
|
|
164
|
+
e !== n.id && r.push(n.id), n = t(this.flat, t(n, "definition.parentId"), void 0);
|
|
164
165
|
} while (n);
|
|
165
166
|
return r;
|
|
166
167
|
};
|
|
167
|
-
childTree = (
|
|
168
|
-
let n = this.flat[
|
|
168
|
+
childTree = (e) => {
|
|
169
|
+
let n = this.flat[e];
|
|
169
170
|
if (!n) return [];
|
|
170
|
-
let r = [], i =
|
|
171
|
+
let r = [], i = t(n, "definition.items");
|
|
171
172
|
return i && i.forEach((e) => r.push(e, ...this.childTree(e))), r;
|
|
172
173
|
};
|
|
173
174
|
isValidElement = (e) => {
|
|
@@ -177,57 +178,81 @@ var o = class {
|
|
|
177
178
|
let { type: i, label: a, styleSelectors: o, rootId: s } = r;
|
|
178
179
|
return !(!i || a === void 0 || typeof o != "object" || s === void 0);
|
|
179
180
|
};
|
|
180
|
-
flatAsTemplate = (
|
|
181
|
-
let
|
|
181
|
+
flatAsTemplate = (e, r, i = !1) => {
|
|
182
|
+
let a = {
|
|
183
|
+
...o,
|
|
184
|
+
platform: {
|
|
185
|
+
desktop: {},
|
|
186
|
+
tablet: {},
|
|
187
|
+
mobile: {}
|
|
188
|
+
}
|
|
189
|
+
}, c = [];
|
|
182
190
|
if (!r) return {
|
|
183
191
|
elements: {
|
|
184
192
|
acum: {},
|
|
185
193
|
item: void 0
|
|
186
194
|
},
|
|
187
|
-
elementsStyle:
|
|
195
|
+
elementsStyle: a,
|
|
188
196
|
variables: c
|
|
189
197
|
};
|
|
190
|
-
let l =
|
|
198
|
+
let l = t(this.flat, r);
|
|
191
199
|
if (!l) return {
|
|
192
200
|
elements: {
|
|
193
201
|
acum: {},
|
|
194
202
|
item: void 0
|
|
195
203
|
},
|
|
196
|
-
elementsStyle:
|
|
204
|
+
elementsStyle: a,
|
|
197
205
|
variables: c
|
|
198
206
|
};
|
|
199
207
|
let u = this.cloneElements(r, l.definition.parentId);
|
|
200
|
-
return u.item ? (Object.values(u.acum).forEach((
|
|
201
|
-
let { id: r } =
|
|
202
|
-
if (
|
|
203
|
-
let { displayMode:
|
|
204
|
-
!(r in
|
|
208
|
+
return u.item ? (Object.values(u.acum).forEach((t) => {
|
|
209
|
+
let { id: r } = t;
|
|
210
|
+
if (n(u.acum, `${r}.definition.rootId`, u.item?.id), s(t, t.definition.type, this.flat, e.platform, {}, { includeSelf: !0 }).tree.forEach((t) => {
|
|
211
|
+
let { displayMode: n, name: r } = t;
|
|
212
|
+
!(r in a.platform[n]) && r in e.platform[n] && (a.platform[n][r] = e.platform[n][r]);
|
|
205
213
|
}), this.variables.length > 0) {
|
|
206
|
-
let
|
|
207
|
-
c = [...c, ...
|
|
214
|
+
let t = this.getElementVariables(e, r, u.acum);
|
|
215
|
+
c = [...c, ...t];
|
|
208
216
|
}
|
|
209
|
-
}),
|
|
217
|
+
}), n(u.acum, `${u.item.id}.definition.parentId`, null), i && delete u.acum[u.item.id], c.length > 1 && (c = [...new Set(c)]), {
|
|
210
218
|
elements: u,
|
|
211
|
-
elementsStyle:
|
|
219
|
+
elementsStyle: a,
|
|
212
220
|
variables: c
|
|
213
221
|
}) : {
|
|
214
222
|
elements: {
|
|
215
223
|
acum: {},
|
|
216
224
|
item: void 0
|
|
217
225
|
},
|
|
218
|
-
elementsStyle:
|
|
226
|
+
elementsStyle: a,
|
|
219
227
|
variables: c
|
|
220
228
|
};
|
|
221
229
|
};
|
|
222
|
-
|
|
223
|
-
|
|
230
|
+
validate = () => e({
|
|
231
|
+
...i.schema,
|
|
232
|
+
flat: this.flat,
|
|
233
|
+
variables: this.variables
|
|
234
|
+
});
|
|
235
|
+
isValid = () => this.validate().valid;
|
|
236
|
+
assertValid = (t) => {
|
|
237
|
+
let n = e({
|
|
238
|
+
...i.schema,
|
|
239
|
+
flat: this.flat,
|
|
240
|
+
variables: this.variables
|
|
241
|
+
});
|
|
242
|
+
if (!n.valid) {
|
|
243
|
+
let e = `Invalid schema${t ? ` (${t})` : ""}: ${n.errors.map((e) => e.message).join("; ")}`;
|
|
244
|
+
throw Error(e);
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
getElementVariables = (e, n, r = this.flat, i = this.variables) => {
|
|
248
|
+
let o = [], s = t(r, `${n}.definition.styleSelectors`);
|
|
224
249
|
if (!s) return o;
|
|
225
|
-
let c = new RegExp(
|
|
226
|
-
return Object.values(s).filter(Boolean).forEach((
|
|
227
|
-
Object.values(
|
|
228
|
-
let n = t
|
|
250
|
+
let c = new RegExp(a, "g");
|
|
251
|
+
return Object.values(s).filter(Boolean).forEach((t) => {
|
|
252
|
+
Object.values(e.platform).forEach((e) => {
|
|
253
|
+
let n = e[t];
|
|
229
254
|
n && [...JSON.stringify(n.attributes).matchAll(c)].forEach((e) => {
|
|
230
|
-
let t =
|
|
255
|
+
let t = i.find((t) => t.name === e[1] || t.name === e[2]);
|
|
231
256
|
t && !o.find((e) => e.name === t.name) && o.push(t);
|
|
232
257
|
});
|
|
233
258
|
});
|
|
@@ -262,6 +287,15 @@ var o = class {
|
|
|
262
287
|
variables: i
|
|
263
288
|
}).getElementVariables(t, n);
|
|
264
289
|
};
|
|
290
|
+
static validate = (t) => e(t);
|
|
291
|
+
static isValid = (t) => e(t).valid;
|
|
292
|
+
static assertValid = (t, n) => {
|
|
293
|
+
let r = e(t);
|
|
294
|
+
if (!r.valid) {
|
|
295
|
+
let e = `Invalid schema${n ? ` (${n})` : ""}: ${r.errors.map((e) => e.message).join("; ")}`;
|
|
296
|
+
throw Error(e);
|
|
297
|
+
}
|
|
298
|
+
};
|
|
265
299
|
};
|
|
266
300
|
//#endregion
|
|
267
|
-
export {
|
|
301
|
+
export { c as default };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Schema } from '@plitzi/sdk-shared';
|
|
2
|
+
export type SchemaValidationOptions = {
|
|
3
|
+
baseElementId?: string;
|
|
4
|
+
};
|
|
5
|
+
export type SchemaValidationError = {
|
|
6
|
+
code: string;
|
|
7
|
+
message: string;
|
|
8
|
+
elementId?: string;
|
|
9
|
+
details?: unknown;
|
|
10
|
+
};
|
|
11
|
+
export type SchemaValidationResult = {
|
|
12
|
+
valid: boolean;
|
|
13
|
+
errors: SchemaValidationError[];
|
|
14
|
+
warnings: SchemaValidationError[];
|
|
15
|
+
};
|
|
16
|
+
export declare const validateSchema: (schema: Schema, options?: SchemaValidationOptions) => SchemaValidationResult;
|
|
17
|
+
export declare const assertSchemaValid: (schema: Schema, options?: SchemaValidationOptions, context?: string) => void;
|
|
18
|
+
export declare const isSchemaValid: (schema: Schema, options?: SchemaValidationOptions) => boolean;
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
//#region src/helpers/schemaValidator.ts
|
|
2
|
+
var e = (e) => {
|
|
3
|
+
let t = [], n = [], { flat: r, pages: i, pageFolders: a, variables: o } = e, s = (e) => !!r[e], c = (e) => r[e], l = () => !r || typeof r != "object" ? (t.push({
|
|
4
|
+
code: "INVALID_FLAT",
|
|
5
|
+
message: "Schema.flat must be a valid Record<string, Element>"
|
|
6
|
+
}), !1) : Array.isArray(i) ? Array.isArray(a) ? Array.isArray(o) ? !0 : (t.push({
|
|
7
|
+
code: "INVALID_VARIABLES",
|
|
8
|
+
message: "Schema.variables must be an array"
|
|
9
|
+
}), !1) : (t.push({
|
|
10
|
+
code: "INVALID_PAGE_FOLDERS",
|
|
11
|
+
message: "Schema.pageFolders must be an array"
|
|
12
|
+
}), !1) : (t.push({
|
|
13
|
+
code: "INVALID_PAGES",
|
|
14
|
+
message: "Schema.pages must be an array of element IDs"
|
|
15
|
+
}), !1), u = () => {
|
|
16
|
+
Object.entries(r).forEach(([e, r]) => {
|
|
17
|
+
if (!r) {
|
|
18
|
+
t.push({
|
|
19
|
+
code: "NULL_ELEMENT",
|
|
20
|
+
message: `Element with id "${e}" is null or undefined`,
|
|
21
|
+
elementId: e
|
|
22
|
+
});
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (!r.id) {
|
|
26
|
+
t.push({
|
|
27
|
+
code: "MISSING_ID",
|
|
28
|
+
message: `Element at key "${e}" has no id property`
|
|
29
|
+
});
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (r.id !== e && t.push({
|
|
33
|
+
code: "ID_MISMATCH",
|
|
34
|
+
message: `Element id "${r.id}" doesn't match flat key "${e}"`,
|
|
35
|
+
elementId: e
|
|
36
|
+
}), !r.definition) {
|
|
37
|
+
t.push({
|
|
38
|
+
code: "MISSING_DEFINITION",
|
|
39
|
+
message: "Element missing definition",
|
|
40
|
+
elementId: e
|
|
41
|
+
});
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
let { definition: i, attributes: a } = r;
|
|
45
|
+
i.type || t.push({
|
|
46
|
+
code: "MISSING_TYPE",
|
|
47
|
+
message: "Element missing definition.type",
|
|
48
|
+
elementId: e
|
|
49
|
+
}), i.label === void 0 && t.push({
|
|
50
|
+
code: "MISSING_LABEL",
|
|
51
|
+
message: "Element missing definition.label",
|
|
52
|
+
elementId: e
|
|
53
|
+
}), i.rootId || t.push({
|
|
54
|
+
code: "MISSING_ROOT_ID",
|
|
55
|
+
message: "Element missing definition.rootId",
|
|
56
|
+
elementId: e
|
|
57
|
+
}), (!i.styleSelectors || typeof i.styleSelectors != "object") && t.push({
|
|
58
|
+
code: "MISSING_STYLE_SELECTORS",
|
|
59
|
+
message: "Element missing or invalid definition.styleSelectors",
|
|
60
|
+
elementId: e
|
|
61
|
+
}), a || n.push({
|
|
62
|
+
code: "MISSING_ATTRIBUTES",
|
|
63
|
+
message: "Element has no attributes",
|
|
64
|
+
elementId: e
|
|
65
|
+
}), i.items && (Array.isArray(i.items) ? i.items.forEach((n, r) => {
|
|
66
|
+
s(n) || t.push({
|
|
67
|
+
code: "ORPHANED_ITEM_REFERENCE",
|
|
68
|
+
message: `Element "${e}" references non-existent child "${n}" at items[${r}]`,
|
|
69
|
+
elementId: e,
|
|
70
|
+
details: {
|
|
71
|
+
childId: n,
|
|
72
|
+
index: r
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}) : t.push({
|
|
76
|
+
code: "INVALID_ITEMS",
|
|
77
|
+
message: "Element.definition.items must be an array",
|
|
78
|
+
elementId: e
|
|
79
|
+
})), i.parentId && !s(i.parentId) && t.push({
|
|
80
|
+
code: "ORPHANED_PARENT_REFERENCE",
|
|
81
|
+
message: `Element "${e}" has parentId "${i.parentId}" but parent doesn't exist in flat`,
|
|
82
|
+
elementId: e,
|
|
83
|
+
details: { parentId: i.parentId }
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}, d = () => {
|
|
87
|
+
Object.values(r).forEach((e) => {
|
|
88
|
+
if (!e?.definition) return;
|
|
89
|
+
let { id: n, definition: r } = e;
|
|
90
|
+
if (r.items && r.items.forEach((e) => {
|
|
91
|
+
let r = c(e);
|
|
92
|
+
r?.definition && r.definition.parentId !== n && t.push({
|
|
93
|
+
code: "PARENT_CHILD_MISMATCH",
|
|
94
|
+
message: `Element "${e}" is in "${n}".items but has parentId "${r.definition.parentId}"`,
|
|
95
|
+
elementId: e,
|
|
96
|
+
details: {
|
|
97
|
+
expectedParent: n,
|
|
98
|
+
actualParent: r.definition.parentId
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}), r.parentId) {
|
|
102
|
+
let e = c(r.parentId);
|
|
103
|
+
if (!e?.definition) return;
|
|
104
|
+
let i = e.definition.items || [];
|
|
105
|
+
i.includes(n) || t.push({
|
|
106
|
+
code: "PARENT_CHILD_MISMATCH",
|
|
107
|
+
message: `Element "${n}" has parentId "${r.parentId}" but parent doesn't have it in items`,
|
|
108
|
+
elementId: n,
|
|
109
|
+
details: {
|
|
110
|
+
parentId: r.parentId,
|
|
111
|
+
parentItems: i
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}, f = () => {
|
|
117
|
+
let e = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), i = (r) => {
|
|
118
|
+
if (n.has(r)) return t.push({
|
|
119
|
+
code: "CIRCULAR_REFERENCE",
|
|
120
|
+
message: `Circular reference detected involving element "${r}"`,
|
|
121
|
+
elementId: r
|
|
122
|
+
}), !0;
|
|
123
|
+
if (e.has(r)) return !1;
|
|
124
|
+
e.add(r), n.add(r);
|
|
125
|
+
let a = c(r);
|
|
126
|
+
if (a?.definition?.items) {
|
|
127
|
+
for (let e of a.definition.items) if (i(e)) return n.delete(r), !0;
|
|
128
|
+
}
|
|
129
|
+
let o = /* @__PURE__ */ new Set(), s = a;
|
|
130
|
+
for (; s?.definition?.parentId;) {
|
|
131
|
+
if (o.has(s.id)) return t.push({
|
|
132
|
+
code: "CIRCULAR_PARENT_REFERENCE",
|
|
133
|
+
message: `Circular parent reference detected involving element "${s.id}"`,
|
|
134
|
+
elementId: s.id
|
|
135
|
+
}), !0;
|
|
136
|
+
o.add(s.id), s = c(s.definition.parentId);
|
|
137
|
+
}
|
|
138
|
+
return n.delete(r), !1;
|
|
139
|
+
};
|
|
140
|
+
Object.keys(r).forEach((t) => {
|
|
141
|
+
e.has(t) || i(t);
|
|
142
|
+
});
|
|
143
|
+
}, p = () => {
|
|
144
|
+
let e = /* @__PURE__ */ new Set(), r = 0;
|
|
145
|
+
i.forEach((n, i) => {
|
|
146
|
+
e.has(n) && t.push({
|
|
147
|
+
code: "DUPLICATE_PAGE",
|
|
148
|
+
message: `Duplicate page ID "${n}" in pages array at index ${i}`,
|
|
149
|
+
elementId: n
|
|
150
|
+
}), e.add(n);
|
|
151
|
+
let a = c(n);
|
|
152
|
+
if (!a) {
|
|
153
|
+
t.push({
|
|
154
|
+
code: "INVALID_PAGE_REFERENCE",
|
|
155
|
+
message: `Page ID "${n}" in pages array doesn't exist in flat`,
|
|
156
|
+
elementId: n
|
|
157
|
+
});
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
a.definition.type !== "page" && t.push({
|
|
161
|
+
code: "INVALID_PAGE_TYPE",
|
|
162
|
+
message: `Element "${n}" in pages array has type "${a.definition.type}" instead of "page"`,
|
|
163
|
+
elementId: n
|
|
164
|
+
}), a.definition.rootId !== n && t.push({
|
|
165
|
+
code: "PAGE_ROOT_ID_MISMATCH",
|
|
166
|
+
message: `Page "${n}" has rootId "${a.definition.rootId}" instead of its own ID`,
|
|
167
|
+
elementId: n
|
|
168
|
+
}), a.attributes?.default && r++;
|
|
169
|
+
}), r === 0 && i.length > 0 ? n.push({
|
|
170
|
+
code: "NO_DEFAULT_PAGE",
|
|
171
|
+
message: "No default page found in schema"
|
|
172
|
+
}) : r > 1 && n.push({
|
|
173
|
+
code: "MULTIPLE_DEFAULT_PAGES",
|
|
174
|
+
message: `Found ${r} default pages, expected 1`
|
|
175
|
+
});
|
|
176
|
+
}, m = () => {
|
|
177
|
+
i.forEach((e) => {
|
|
178
|
+
let n = c(e);
|
|
179
|
+
if (!n) return;
|
|
180
|
+
let r = (n) => {
|
|
181
|
+
let i = c(n);
|
|
182
|
+
i?.definition && (i.definition.rootId !== e && t.push({
|
|
183
|
+
code: "ROOT_ID_MISMATCH",
|
|
184
|
+
message: `Element "${n}" has rootId "${i.definition.rootId}" but should be "${e}" (page's ID)`,
|
|
185
|
+
elementId: n,
|
|
186
|
+
details: {
|
|
187
|
+
expectedRootId: e,
|
|
188
|
+
actualRootId: i.definition.rootId
|
|
189
|
+
}
|
|
190
|
+
}), i.definition.items && i.definition.items.forEach((e) => r(e)));
|
|
191
|
+
};
|
|
192
|
+
n.definition.items && n.definition.items.forEach((e) => r(e));
|
|
193
|
+
});
|
|
194
|
+
}, h = () => {
|
|
195
|
+
let e = /* @__PURE__ */ new Set();
|
|
196
|
+
a.forEach((n, r) => {
|
|
197
|
+
if (!n.id) {
|
|
198
|
+
t.push({
|
|
199
|
+
code: "INVALID_FOLDER",
|
|
200
|
+
message: `Page folder at index ${r} has no id`
|
|
201
|
+
});
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
e.has(n.id) && t.push({
|
|
205
|
+
code: "DUPLICATE_FOLDER",
|
|
206
|
+
message: `Duplicate folder ID "${n.id}"`,
|
|
207
|
+
elementId: n.id
|
|
208
|
+
}), e.add(n.id), n.parentId && (e.has(n.parentId) || t.push({
|
|
209
|
+
code: "ORPHANED_FOLDER_PARENT",
|
|
210
|
+
message: `Folder "${n.id}" has non-existent parent "${n.parentId}"`,
|
|
211
|
+
elementId: n.id,
|
|
212
|
+
details: { parentId: n.parentId }
|
|
213
|
+
}));
|
|
214
|
+
});
|
|
215
|
+
}, g = (e) => {
|
|
216
|
+
let t = /* @__PURE__ */ new Set(), a = (e) => {
|
|
217
|
+
if (t.has(e)) return;
|
|
218
|
+
t.add(e);
|
|
219
|
+
let n = c(e);
|
|
220
|
+
n?.definition?.items && n.definition.items.forEach((e) => a(e));
|
|
221
|
+
};
|
|
222
|
+
if (!e) i.forEach((e) => {
|
|
223
|
+
a(e);
|
|
224
|
+
let t = c(e);
|
|
225
|
+
t?.attributes?.layoutContainer && a(t.attributes.layoutContainer);
|
|
226
|
+
});
|
|
227
|
+
else if (e) {
|
|
228
|
+
a(e);
|
|
229
|
+
let t = c(e);
|
|
230
|
+
t?.attributes?.layoutContainer && a(t.attributes.layoutContainer);
|
|
231
|
+
}
|
|
232
|
+
Object.keys(r).forEach((e) => {
|
|
233
|
+
let r = c(e);
|
|
234
|
+
r && !t.has(e) && r.definition.type !== "page" && n.push({
|
|
235
|
+
code: "ORPHANED_ELEMENT",
|
|
236
|
+
message: `Element "${e}" is not reachable from any page`,
|
|
237
|
+
elementId: e
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
}, _ = () => {
|
|
241
|
+
let e = /* @__PURE__ */ new Set();
|
|
242
|
+
o.forEach((r, i) => {
|
|
243
|
+
if (!r.name) {
|
|
244
|
+
t.push({
|
|
245
|
+
code: "INVALID_VARIABLE",
|
|
246
|
+
message: `Variable at index ${i} has no name`
|
|
247
|
+
});
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
e.has(r.name) && t.push({
|
|
251
|
+
code: "DUPLICATE_VARIABLE",
|
|
252
|
+
message: `Duplicate variable name "${r.name}"`,
|
|
253
|
+
details: { variableName: r.name }
|
|
254
|
+
}), e.add(r.name), r.type || n.push({
|
|
255
|
+
code: "MISSING_VARIABLE_TYPE",
|
|
256
|
+
message: `Variable "${r.name}" has no type`,
|
|
257
|
+
details: { variableName: r.name }
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
};
|
|
261
|
+
return { validate: (e) => {
|
|
262
|
+
let { baseElementId: r } = e ?? {};
|
|
263
|
+
return l() ? (u(), d(), f(), p(), m(), h(), g(r), _(), {
|
|
264
|
+
valid: t.length === 0,
|
|
265
|
+
errors: t,
|
|
266
|
+
warnings: n
|
|
267
|
+
}) : {
|
|
268
|
+
valid: !1,
|
|
269
|
+
errors: t,
|
|
270
|
+
warnings: n
|
|
271
|
+
};
|
|
272
|
+
} };
|
|
273
|
+
}, t = (t, n) => e(t).validate(n), n = (e, n, r) => {
|
|
274
|
+
let i = t(e, n);
|
|
275
|
+
if (!i.valid) {
|
|
276
|
+
let e = `Invalid schema${r ? ` (${r})` : ""}: ${i.errors.map((e) => e.message).join("; ")}`;
|
|
277
|
+
throw Error(e);
|
|
278
|
+
}
|
|
279
|
+
}, r = (e, n) => t(e, n).valid;
|
|
280
|
+
//#endregion
|
|
281
|
+
export { n as assertSchemaValid, r as isSchemaValid, t as validateSchema };
|
package/dist/index.d.ts
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import e from "./helpers/
|
|
2
|
-
import
|
|
3
|
-
|
|
1
|
+
import { assertSchemaValid as e, isSchemaValid as t, validateSchema as n } from "./helpers/schemaValidator.mjs";
|
|
2
|
+
import r from "./helpers/FlatMap.mjs";
|
|
3
|
+
import i, { SchemaActions as a } from "./SchemaReducer.mjs";
|
|
4
|
+
export { r as FlatMap, a as SchemaActions, i as SchemaReducer, e as assertSchemaValid, t as isSchemaValid, n as validateSchema };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plitzi/sdk-schema",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.1",
|
|
4
4
|
"license": "AGPL-3.0",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
"types": "./dist/helpers/FlatMap.d.ts",
|
|
19
19
|
"import": "./dist/helpers/FlatMap.mjs"
|
|
20
20
|
},
|
|
21
|
+
"./helpers/schemaValidator": {
|
|
22
|
+
"types": "./dist/helpers/schemaValidator.d.ts",
|
|
23
|
+
"import": "./dist/helpers/schemaValidator.mjs"
|
|
24
|
+
},
|
|
21
25
|
"./index": {
|
|
22
26
|
"types": "./dist/index.d.ts",
|
|
23
27
|
"import": "./dist/index.mjs"
|
|
@@ -36,15 +40,15 @@
|
|
|
36
40
|
"build:prod": "vite build && node ../sdk-shared/scripts/generate-exports.mjs"
|
|
37
41
|
},
|
|
38
42
|
"dependencies": {
|
|
39
|
-
"@plitzi/plitzi-ui": "^1.6.
|
|
40
|
-
"@plitzi/sdk-shared": "0.
|
|
41
|
-
"@plitzi/sdk-style": "0.
|
|
43
|
+
"@plitzi/plitzi-ui": "^1.6.9",
|
|
44
|
+
"@plitzi/sdk-shared": "0.31.1",
|
|
45
|
+
"@plitzi/sdk-style": "0.31.1",
|
|
42
46
|
"prop-types": "^15.8.1"
|
|
43
47
|
},
|
|
44
48
|
"devDependencies": {
|
|
45
49
|
"eslint": "^9.39.4",
|
|
46
50
|
"typescript": "^6.0.3",
|
|
47
|
-
"vite": "^8.0.
|
|
48
|
-
"vitest": "^4.1.
|
|
51
|
+
"vite": "^8.0.14",
|
|
52
|
+
"vitest": "^4.1.7"
|
|
49
53
|
}
|
|
50
54
|
}
|