@valbuild/core 0.12.0 → 0.13.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 (71) hide show
  1. package/jest.config.js +4 -0
  2. package/package.json +1 -1
  3. package/src/Json.ts +4 -0
  4. package/src/expr/README.md +193 -0
  5. package/src/expr/eval.test.ts +202 -0
  6. package/src/expr/eval.ts +248 -0
  7. package/src/expr/expr.ts +91 -0
  8. package/src/expr/index.ts +3 -0
  9. package/src/expr/parser.test.ts +158 -0
  10. package/src/expr/parser.ts +229 -0
  11. package/src/expr/repl.ts +93 -0
  12. package/src/expr/tokenizer.test.ts +539 -0
  13. package/src/expr/tokenizer.ts +117 -0
  14. package/src/fetchVal.test.ts +164 -0
  15. package/src/fetchVal.ts +211 -0
  16. package/src/fp/array.ts +30 -0
  17. package/src/fp/index.ts +3 -0
  18. package/src/fp/result.ts +214 -0
  19. package/src/fp/util.ts +52 -0
  20. package/src/index.ts +55 -0
  21. package/src/initSchema.ts +45 -0
  22. package/src/initVal.ts +96 -0
  23. package/src/module.test.ts +170 -0
  24. package/src/module.ts +333 -0
  25. package/src/patch/deref.test.ts +300 -0
  26. package/src/patch/deref.ts +128 -0
  27. package/src/patch/index.ts +11 -0
  28. package/src/patch/json.test.ts +583 -0
  29. package/src/patch/json.ts +304 -0
  30. package/src/patch/operation.ts +74 -0
  31. package/src/patch/ops.ts +83 -0
  32. package/src/patch/parse.test.ts +202 -0
  33. package/src/patch/parse.ts +187 -0
  34. package/src/patch/patch.ts +46 -0
  35. package/src/patch/util.ts +67 -0
  36. package/src/schema/array.ts +52 -0
  37. package/src/schema/boolean.ts +38 -0
  38. package/src/schema/i18n.ts +65 -0
  39. package/src/schema/image.ts +70 -0
  40. package/src/schema/index.ts +46 -0
  41. package/src/schema/literal.ts +42 -0
  42. package/src/schema/number.ts +45 -0
  43. package/src/schema/object.ts +67 -0
  44. package/src/schema/oneOf.ts +60 -0
  45. package/src/schema/richtext.ts +417 -0
  46. package/src/schema/string.ts +49 -0
  47. package/src/schema/union.ts +62 -0
  48. package/src/selector/ExprProxy.test.ts +203 -0
  49. package/src/selector/ExprProxy.ts +209 -0
  50. package/src/selector/SelectorProxy.test.ts +172 -0
  51. package/src/selector/SelectorProxy.ts +237 -0
  52. package/src/selector/array.ts +37 -0
  53. package/src/selector/boolean.ts +4 -0
  54. package/src/selector/file.ts +14 -0
  55. package/src/selector/i18n.ts +13 -0
  56. package/src/selector/index.ts +159 -0
  57. package/src/selector/number.ts +4 -0
  58. package/src/selector/object.ts +22 -0
  59. package/src/selector/primitive.ts +17 -0
  60. package/src/selector/remote.ts +9 -0
  61. package/src/selector/selector.test.ts +453 -0
  62. package/src/selector/selectorOf.ts +7 -0
  63. package/src/selector/string.ts +4 -0
  64. package/src/source/file.ts +45 -0
  65. package/src/source/i18n.ts +60 -0
  66. package/src/source/index.ts +50 -0
  67. package/src/source/remote.ts +54 -0
  68. package/src/val/array.ts +10 -0
  69. package/src/val/index.ts +90 -0
  70. package/src/val/object.ts +13 -0
  71. package/src/val/primitive.ts +8 -0
@@ -0,0 +1,67 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import { Schema, SchemaTypeOf, SerializedSchema } from ".";
3
+ import { SelectorSource } from "../selector";
4
+ import { SourcePath } from "../val";
5
+
6
+ export type SerializedObjectSchema = {
7
+ type: "object";
8
+ items: Record<string, SerializedSchema>;
9
+ opt: boolean;
10
+ };
11
+
12
+ type ObjectSchemaProps = { [key: string]: Schema<SelectorSource> };
13
+ type ObjectSchemaSrcOf<Props extends ObjectSchemaProps> = {
14
+ [key in keyof Props]: SchemaTypeOf<Props[key]>;
15
+ };
16
+
17
+ export class ObjectSchema<Props extends ObjectSchemaProps> extends Schema<
18
+ ObjectSchemaSrcOf<Props>
19
+ > {
20
+ constructor(readonly items: Props, readonly opt: boolean = false) {
21
+ super();
22
+ }
23
+
24
+ validate(
25
+ src: ObjectSchemaSrcOf<Props>
26
+ ): false | Record<SourcePath, string[]> {
27
+ throw new Error("Method not implemented.");
28
+ }
29
+
30
+ match(src: ObjectSchemaSrcOf<Props>): boolean {
31
+ if (this.opt && (src === null || src === undefined)) {
32
+ return true;
33
+ }
34
+ if (!src) {
35
+ return false;
36
+ }
37
+
38
+ // TODO: checks all props
39
+
40
+ return typeof src === "object" && !Array.isArray(src);
41
+ }
42
+
43
+ optional(): Schema<ObjectSchemaSrcOf<Props> | null> {
44
+ return new ObjectSchema(this.items, true);
45
+ }
46
+
47
+ serialize(): SerializedSchema {
48
+ return {
49
+ type: "object",
50
+ items: Object.fromEntries(
51
+ Object.entries(this.items).map(([key, schema]) => [
52
+ key,
53
+ schema.serialize(),
54
+ ])
55
+ ),
56
+ opt: this.opt,
57
+ };
58
+ }
59
+ }
60
+
61
+ export const object = <Props extends ObjectSchemaProps>(
62
+ schema: Props
63
+ ): Schema<{
64
+ [key in keyof Props]: SchemaTypeOf<Props[key]>;
65
+ }> => {
66
+ return new ObjectSchema(schema);
67
+ };
@@ -0,0 +1,60 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import { Schema, SerializedSchema } from ".";
3
+ import { ValModuleBrand } from "../module";
4
+ import { GenericSelector } from "../selector";
5
+ import { Source, SourceArray } from "../source";
6
+ import { getValPath, SourcePath } from "../val";
7
+
8
+ export type SerializedOneOfSchema = {
9
+ type: "oneOf";
10
+ selector: SourcePath;
11
+ opt: boolean;
12
+ };
13
+
14
+ type OneOfSelector<Sel extends GenericSelector<SourceArray>> =
15
+ Sel extends GenericSelector<infer S>
16
+ ? S extends (infer IS)[]
17
+ ? IS extends Source
18
+ ? GenericSelector<IS>
19
+ : never
20
+ : never
21
+ : never;
22
+
23
+ export class OneOfSchema<
24
+ Sel extends GenericSelector<SourceArray>
25
+ > extends Schema<OneOfSelector<Sel>> {
26
+ constructor(readonly selector: Sel, readonly opt: boolean = false) {
27
+ super();
28
+ }
29
+ validate(src: OneOfSelector<Sel>): false | Record<SourcePath, string[]> {
30
+ throw new Error("Method not implemented.");
31
+ }
32
+ match(src: OneOfSelector<Sel>): boolean {
33
+ throw new Error("Method not implemented.");
34
+ }
35
+ optional(): Schema<OneOfSelector<Sel> | null> {
36
+ return new OneOfSchema(this.selector, true);
37
+ }
38
+
39
+ serialize(): SerializedSchema {
40
+ const path = getValPath(this.selector);
41
+ if (!path) {
42
+ throw new Error(
43
+ "Cannot serialize oneOf schema with empty selector. Make sure a Val module is used."
44
+ );
45
+ }
46
+ return {
47
+ type: "oneOf",
48
+ selector: path,
49
+ opt: this.opt,
50
+ };
51
+ }
52
+ }
53
+
54
+ export const oneOf = <
55
+ Src extends GenericSelector<SourceArray> & ValModuleBrand // ValModuleBrand enforces call site to pass in a val module - selectors are not allowed. The reason is that this should make it easier to patch. We might be able to relax this constraint in the future
56
+ >(
57
+ valModule: Src
58
+ ): Schema<OneOfSelector<Src>> => {
59
+ return new OneOfSchema(valModule);
60
+ };
@@ -0,0 +1,417 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import { Schema, SerializedSchema } from ".";
3
+ import { content } from "../module";
4
+ import { VAL_EXTENSION } from "../source";
5
+ import { SourcePath } from "../val";
6
+
7
+ export type SerializedRichTextSchema = {
8
+ type: "richtext";
9
+ opt: boolean;
10
+ };
11
+
12
+ type Node = {
13
+ version: 1;
14
+ };
15
+
16
+ type NodeType = Node & {
17
+ format: FormatType;
18
+ direction: DirectionType;
19
+ indent: number;
20
+ };
21
+
22
+ type FormatType =
23
+ | "left"
24
+ | "start"
25
+ | "center"
26
+ | "right"
27
+ | "end"
28
+ | "justify"
29
+ | "";
30
+ type DirectionType = "ltr" | "rtl" | null;
31
+
32
+ export type TextNode = Node & {
33
+ format: FormatType | number;
34
+ detail: number;
35
+ mode: "normal" | "code" | "quote";
36
+ style: string;
37
+ text: string;
38
+ type: "text";
39
+ direction?: DirectionType;
40
+ indent?: number;
41
+ };
42
+
43
+ export type ImageNode = Node & {
44
+ altText: string;
45
+ height: number;
46
+ width: number;
47
+ maxWidth: number;
48
+ src: string;
49
+ type: "image";
50
+ };
51
+
52
+ export type ParagraphNode<VN = TextNode> = NodeType & {
53
+ children: (TextNode | VN)[];
54
+ type: "paragraph";
55
+ };
56
+
57
+ export type HeadingNode<HT extends HeadingTags = HeadingTags> = NodeType & {
58
+ children: TextNode[];
59
+ type: "heading";
60
+ tag: HT;
61
+ };
62
+
63
+ export type ListItemNode<VN = TextNode> = NodeType & {
64
+ children: (TextNode | VN)[];
65
+ type: "listitem";
66
+ value: number;
67
+ checked?: boolean;
68
+ };
69
+
70
+ export type ListNode<VN = TextNode> = NodeType & {
71
+ children: ListItemNode<VN>[];
72
+ type: "list";
73
+ tag: "ol" | "ul";
74
+ listType: "number" | "bullet" | "check";
75
+ start?: number;
76
+ };
77
+
78
+ type HeadingTags = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
79
+ export type RootNode<HT extends HeadingTags, VN> = Node & {
80
+ children: (HeadingNode<HT> | ParagraphNode<VN> | ListNode<VN>)[];
81
+ type: "root";
82
+ format: FormatType;
83
+ direction: DirectionType;
84
+ indent: number;
85
+ };
86
+
87
+ type ValNode = ImageNode;
88
+
89
+ export type RichText<
90
+ HT extends HeadingTags = HeadingTags,
91
+ VN extends TextNode | ValNode = TextNode
92
+ > = RootNode<HT, VN>;
93
+
94
+ export class RichTextSchema<Src extends RichText | null> extends Schema<Src> {
95
+ validate(src: Src): false | Record<SourcePath, string[]> {
96
+ throw new Error("Method not implemented.");
97
+ }
98
+ match(src: Src): boolean {
99
+ // TODO:
100
+ return true;
101
+ }
102
+
103
+ optional(): Schema<RichText<HeadingTags, TextNode> | null> {
104
+ return new RichTextSchema(true);
105
+ }
106
+ serialize(): SerializedSchema {
107
+ return {
108
+ type: "richtext",
109
+ opt: this.opt,
110
+ };
111
+ }
112
+ constructor(readonly opt: boolean = false) {
113
+ super();
114
+ }
115
+ }
116
+
117
+ export const richtext = (): Schema<RichText> => {
118
+ return new RichTextSchema();
119
+ };
120
+
121
+ {
122
+ const a = content("/test/richtext1", richtext(), {
123
+ children: [
124
+ {
125
+ children: [
126
+ {
127
+ detail: 0,
128
+ format: 0,
129
+ mode: "normal",
130
+ style: "",
131
+ text: "Heading 1",
132
+ type: "text",
133
+ version: 1,
134
+ },
135
+ ],
136
+ direction: "ltr",
137
+ format: "",
138
+ indent: 0,
139
+ type: "heading",
140
+ version: 1,
141
+ tag: "h1",
142
+ },
143
+ {
144
+ children: [
145
+ {
146
+ detail: 0,
147
+ format: 0,
148
+ mode: "normal",
149
+ style: "",
150
+ text: "Heading 2",
151
+ type: "text",
152
+ version: 1,
153
+ },
154
+ ],
155
+ direction: "ltr",
156
+ format: "",
157
+ indent: 0,
158
+ type: "heading",
159
+ version: 1,
160
+ tag: "h2",
161
+ },
162
+ {
163
+ children: [],
164
+ direction: "ltr",
165
+ format: "",
166
+ indent: 0,
167
+ type: "paragraph",
168
+ version: 1,
169
+ },
170
+ {
171
+ children: [
172
+ {
173
+ detail: 0,
174
+ format: 0,
175
+ mode: "normal",
176
+ style: "",
177
+ text: "Normal",
178
+ type: "text",
179
+ version: 1,
180
+ },
181
+ ],
182
+ direction: "ltr",
183
+ format: "",
184
+ indent: 0,
185
+ type: "paragraph",
186
+ version: 1,
187
+ },
188
+ {
189
+ children: [
190
+ {
191
+ detail: 0,
192
+ format: 0,
193
+ mode: "normal",
194
+ style: "font-size: 20px;",
195
+ text: "Normal Font size 20",
196
+ type: "text",
197
+ version: 1,
198
+ },
199
+ ],
200
+ direction: "ltr",
201
+ format: "",
202
+ indent: 0,
203
+ type: "paragraph",
204
+ version: 1,
205
+ },
206
+ {
207
+ children: [
208
+ {
209
+ detail: 0,
210
+ format: 0,
211
+ mode: "normal",
212
+ style: "font-family: serif;",
213
+ text: "Normal font type serif",
214
+ type: "text",
215
+ version: 1,
216
+ },
217
+ ],
218
+ direction: "ltr",
219
+ format: "",
220
+ indent: 0,
221
+ type: "paragraph",
222
+ version: 1,
223
+ },
224
+ {
225
+ children: [
226
+ {
227
+ detail: 0,
228
+ format: 1,
229
+ mode: "normal",
230
+ style: "font-family: serif;",
231
+ text: "Serif and bold",
232
+ type: "text",
233
+ version: 1,
234
+ },
235
+ ],
236
+ direction: "ltr",
237
+ format: "",
238
+ indent: 0,
239
+ type: "paragraph",
240
+ version: 1,
241
+ },
242
+ {
243
+ children: [
244
+ {
245
+ detail: 0,
246
+ format: 2,
247
+ mode: "normal",
248
+ style: "",
249
+ text: "Arial and italic",
250
+ type: "text",
251
+ version: 1,
252
+ },
253
+ ],
254
+ direction: "ltr",
255
+ format: "",
256
+ indent: 0,
257
+ type: "paragraph",
258
+ version: 1,
259
+ },
260
+ {
261
+ children: [],
262
+ direction: null,
263
+ format: "",
264
+ indent: 0,
265
+ type: "paragraph",
266
+ version: 1,
267
+ },
268
+ {
269
+ children: [
270
+ {
271
+ children: [
272
+ {
273
+ detail: 0,
274
+ format: 0,
275
+ mode: "normal",
276
+ style: "",
277
+ text: "Num list 1",
278
+ type: "text",
279
+ version: 1,
280
+ },
281
+ ],
282
+ direction: "ltr",
283
+ format: "",
284
+ indent: 0,
285
+ type: "listitem",
286
+ version: 1,
287
+ value: 1,
288
+ },
289
+ {
290
+ children: [
291
+ {
292
+ detail: 0,
293
+ format: 0,
294
+ mode: "normal",
295
+ style: "",
296
+ text: "Num list 2",
297
+ type: "text",
298
+ version: 1,
299
+ },
300
+ // TODO: image
301
+ // {
302
+ // altText: "",
303
+ // height: 0,
304
+ // maxWidth: 0,
305
+ // src: "https://picsum.photos/id/237/200/300",
306
+ // type: "image",
307
+ // version: 1,
308
+ // width: 0,
309
+ // },
310
+ ],
311
+ direction: "ltr",
312
+ format: "",
313
+ indent: 0,
314
+ type: "listitem",
315
+ version: 1,
316
+ value: 2,
317
+ },
318
+ ],
319
+ direction: "ltr",
320
+ format: "",
321
+ indent: 0,
322
+ type: "list",
323
+ version: 1,
324
+ listType: "number",
325
+ start: 1,
326
+ tag: "ol",
327
+ },
328
+ {
329
+ children: [],
330
+ direction: null,
331
+ format: "",
332
+ indent: 0,
333
+ type: "paragraph",
334
+ version: 1,
335
+ },
336
+ {
337
+ children: [
338
+ {
339
+ children: [
340
+ {
341
+ detail: 0,
342
+ format: 0,
343
+ mode: "normal",
344
+ style: "",
345
+ text: "Bullet list 1",
346
+ type: "text",
347
+ version: 1,
348
+ },
349
+ ],
350
+ direction: "ltr",
351
+ format: "",
352
+ indent: 0,
353
+ type: "listitem",
354
+ version: 1,
355
+ value: 1,
356
+ },
357
+ {
358
+ children: [
359
+ {
360
+ detail: 0,
361
+ format: 0,
362
+ mode: "normal",
363
+ style: "",
364
+ text: "Bullet list 2",
365
+ type: "text",
366
+ version: 1,
367
+ },
368
+ ],
369
+ direction: "ltr",
370
+ format: "",
371
+ indent: 0,
372
+ type: "listitem",
373
+ version: 1,
374
+ value: 2,
375
+ },
376
+ ],
377
+ direction: "ltr",
378
+ format: "",
379
+ indent: 0,
380
+ type: "list",
381
+ version: 1,
382
+ listType: "bullet",
383
+ start: 1,
384
+ tag: "ul",
385
+ },
386
+ {
387
+ children: [],
388
+ direction: null,
389
+ format: "",
390
+ indent: 0,
391
+ type: "paragraph",
392
+ version: 1,
393
+ },
394
+ {
395
+ children: [],
396
+ direction: "ltr",
397
+ format: "",
398
+ indent: 0,
399
+ type: "paragraph",
400
+ version: 1,
401
+ },
402
+ {
403
+ children: [],
404
+ direction: null,
405
+ format: "",
406
+ indent: 0,
407
+ type: "paragraph",
408
+ version: 1,
409
+ },
410
+ ],
411
+ direction: "ltr",
412
+ format: "",
413
+ indent: 0,
414
+ type: "root",
415
+ version: 1,
416
+ });
417
+ }
@@ -0,0 +1,49 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import { Schema, SerializedSchema } from ".";
3
+ import { SourcePath } from "../val";
4
+
5
+ type StringOptions = {
6
+ maxLength?: number;
7
+ minLength?: number;
8
+ };
9
+
10
+ export type SerializedStringSchema = {
11
+ type: "string";
12
+ options?: StringOptions;
13
+ opt: boolean;
14
+ };
15
+
16
+ export class StringSchema<Src extends string | null> extends Schema<Src> {
17
+ constructor(readonly options?: StringOptions, readonly opt: boolean = false) {
18
+ super();
19
+ }
20
+
21
+ validate(src: Src): false | Record<SourcePath, string[]> {
22
+ throw new Error("Method not implemented.");
23
+ }
24
+
25
+ match(src: Src): boolean {
26
+ if (this.opt && (src === null || src === undefined)) {
27
+ return true;
28
+ }
29
+ return typeof src === "string";
30
+ }
31
+
32
+ optional(): Schema<Src | null> {
33
+ return new StringSchema<Src | null>(this.options, true);
34
+ }
35
+
36
+ serialize(): SerializedSchema {
37
+ return {
38
+ type: "string",
39
+ options: this.options,
40
+ opt: this.opt,
41
+ };
42
+ }
43
+ }
44
+
45
+ export const string = <T extends string>(
46
+ options?: StringOptions
47
+ ): Schema<T> => {
48
+ return new StringSchema(options);
49
+ };
@@ -0,0 +1,62 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import { Schema, SerializedSchema } from ".";
3
+ import { SelectorSource } from "../selector";
4
+ import { SourceObject } from "../source";
5
+ import { SourcePath } from "../val";
6
+
7
+ export type SerializedUnionSchema = {
8
+ type: "union";
9
+ key: string;
10
+ items: SerializedSchema[];
11
+ opt: boolean;
12
+ };
13
+
14
+ type SourceOf<
15
+ Key extends string,
16
+ T extends Schema<SourceObject & { [k in Key]: string }>[]
17
+ > = T extends Schema<infer S>[]
18
+ ? S extends SelectorSource
19
+ ? S
20
+ : never
21
+ : never;
22
+
23
+ export class UnionSchema<
24
+ Key extends string,
25
+ T extends Schema<SourceObject & { [k in Key]: string }>[]
26
+ > extends Schema<SourceOf<Key, T>> {
27
+ validate(src: SourceOf<Key, T>): false | Record<SourcePath, string[]> {
28
+ throw new Error("Method not implemented.");
29
+ }
30
+ match(src: SourceOf<Key, T>): boolean {
31
+ throw new Error("Method not implemented.");
32
+ }
33
+ optional(): Schema<SourceOf<Key, T> | null> {
34
+ throw new Error("Method not implemented.");
35
+ }
36
+ serialize(): SerializedSchema {
37
+ return {
38
+ type: "union",
39
+ key: this.key,
40
+ items: this.items.map((o) => o.serialize()),
41
+ opt: this.opt,
42
+ };
43
+ }
44
+
45
+ constructor(
46
+ readonly key: Key,
47
+ readonly items: T,
48
+ readonly opt: boolean = false
49
+ ) {
50
+ super();
51
+ }
52
+ }
53
+
54
+ export const union = <
55
+ Key extends string,
56
+ T extends Schema<SourceObject & { [k in Key]: string }>[]
57
+ >(
58
+ key: Key,
59
+ ...objects: T
60
+ ): Schema<SourceOf<Key, T>> => {
61
+ return new UnionSchema(key, objects);
62
+ };