@valbuild/core 0.15.0 → 0.17.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.
- package/ROADMAP.md +106 -0
- package/dist/declarations/src/ValApi.d.ts +26 -0
- package/dist/declarations/src/expr/eval.d.ts +1 -1
- package/dist/declarations/src/future/fetchVal.d.ts +5 -0
- package/dist/declarations/src/index.d.ts +38 -9
- package/dist/declarations/src/initSchema.d.ts +2 -10
- package/dist/declarations/src/initVal.d.ts +3 -21
- package/dist/declarations/src/module.d.ts +2 -14
- package/dist/declarations/src/patch/index.d.ts +1 -1
- package/dist/declarations/src/patch/util.d.ts +2 -0
- package/dist/declarations/src/schema/array.d.ts +3 -2
- package/dist/declarations/src/schema/boolean.d.ts +3 -2
- package/dist/declarations/src/schema/image.d.ts +4 -3
- package/dist/declarations/src/schema/index.d.ts +8 -7
- package/dist/declarations/src/schema/keyOf.d.ts +23 -0
- package/dist/declarations/src/schema/literal.d.ts +3 -2
- package/dist/declarations/src/schema/number.d.ts +3 -2
- package/dist/declarations/src/schema/object.d.ts +3 -2
- package/dist/declarations/src/schema/record.d.ts +19 -0
- package/dist/declarations/src/schema/richtext.d.ts +3 -2
- package/dist/declarations/src/schema/string.d.ts +3 -2
- package/dist/declarations/src/schema/union.d.ts +4 -2
- package/dist/declarations/src/schema/validation/ValidationError.d.ts +14 -0
- package/dist/declarations/src/schema/validation/ValidationFix.d.ts +2 -0
- package/dist/declarations/src/selector/SelectorProxy.d.ts +7 -0
- package/dist/declarations/src/selector/array.d.ts +2 -13
- package/dist/declarations/src/selector/file.d.ts +1 -4
- package/dist/declarations/src/selector/future/array.d.ts +17 -0
- package/dist/declarations/src/selector/future/boolean.d.ts +2 -0
- package/dist/declarations/src/selector/future/file.d.ts +9 -0
- package/dist/declarations/src/selector/{i18n.d.ts → future/i18n.d.ts} +2 -2
- package/dist/declarations/src/selector/future/index.d.ts +81 -0
- package/dist/declarations/src/selector/future/number.d.ts +2 -0
- package/dist/declarations/src/selector/future/object.d.ts +10 -0
- package/dist/declarations/src/selector/future/primitive.d.ts +9 -0
- package/dist/declarations/src/selector/{remote.d.ts → future/remote.d.ts} +1 -1
- package/dist/declarations/src/selector/future/string.d.ts +2 -0
- package/dist/declarations/src/selector/index.d.ts +5 -32
- package/dist/declarations/src/selector/object.d.ts +2 -9
- package/dist/declarations/src/selector/primitive.d.ts +3 -9
- package/dist/declarations/src/source/{i18n.d.ts → future/i18n.d.ts} +2 -2
- package/dist/declarations/src/source/{remote.d.ts → future/remote.d.ts} +3 -3
- package/dist/declarations/src/source/index.d.ts +4 -3
- package/dist/declarations/src/val/index.d.ts +2 -2
- package/dist/index-369caccf.esm.js +550 -0
- package/dist/{index-06df0a5b.esm.js → index-3e3e839e.esm.js} +190 -555
- package/dist/{index-9663f28a.cjs.dev.js → index-486c7fbf.cjs.dev.js} +224 -617
- package/dist/{index-b2270f8f.cjs.prod.js → index-601a7d73.cjs.prod.js} +224 -617
- package/dist/index-8706c87e.cjs.prod.js +582 -0
- package/dist/index-a6e642dd.cjs.dev.js +582 -0
- package/dist/ops-0d09f8ee.cjs.prod.js +684 -0
- package/dist/ops-23a5abb2.esm.js +671 -0
- package/dist/ops-f3015423.cjs.dev.js +684 -0
- package/dist/valbuild-core.cjs.dev.js +640 -633
- package/dist/valbuild-core.cjs.prod.js +640 -633
- package/dist/valbuild-core.esm.js +578 -572
- package/expr/dist/valbuild-core-expr.cjs.dev.js +8 -8
- package/expr/dist/valbuild-core-expr.cjs.prod.js +8 -8
- package/expr/dist/valbuild-core-expr.esm.js +2 -2
- package/package.json +2 -2
- package/patch/dist/valbuild-core-patch.cjs.dev.js +32 -23
- package/patch/dist/valbuild-core-patch.cjs.prod.js +32 -23
- package/patch/dist/valbuild-core-patch.esm.js +12 -4
- package/src/ValApi.ts +85 -0
- package/src/expr/eval.test.ts +2 -2
- package/src/expr/eval.ts +2 -2
- package/src/expr/repl.ts +2 -2
- package/src/{fetchVal.test.ts → future/fetchVal.test.ts} +57 -57
- package/src/{fetchVal.ts → future/fetchVal.ts} +17 -22
- package/src/index.ts +51 -14
- package/src/initSchema.ts +11 -12
- package/src/initVal.ts +42 -52
- package/src/module.test.ts +40 -40
- package/src/module.ts +53 -43
- package/src/patch/deref.test.ts +1 -1
- package/src/patch/deref.ts +1 -1
- package/src/patch/index.ts +1 -0
- package/src/patch/json.test.ts +0 -1
- package/src/patch/util.ts +7 -0
- package/src/schema/array.ts +45 -4
- package/src/schema/boolean.ts +14 -3
- package/src/schema/{i18n.ts → future/i18n.ts} +15 -11
- package/src/schema/{oneOf.ts → future/oneOf.ts} +21 -18
- package/src/schema/image.ts +66 -6
- package/src/schema/index.ts +37 -13
- package/src/schema/keyOf.ts +167 -0
- package/src/schema/literal.ts +24 -3
- package/src/schema/number.ts +14 -3
- package/src/schema/object.ts +50 -7
- package/src/schema/record.ts +103 -0
- package/src/schema/richtext.ts +63 -3
- package/src/schema/string.ts +14 -3
- package/src/schema/union.ts +4 -3
- package/src/schema/validation/ValidationError.ts +16 -0
- package/src/schema/validation/ValidationFix.ts +6 -0
- package/src/schema/validation.test.ts +291 -0
- package/src/selector/SelectorProxy.ts +16 -16
- package/src/selector/array.ts +2 -26
- package/src/selector/file.ts +1 -9
- package/src/selector/{ExprProxy.test.ts → future/ExprProxy.test.ts} +2 -2
- package/src/selector/{ExprProxy.ts → future/ExprProxy.ts} +9 -2
- package/src/selector/{SelectorProxy.test.ts → future/SelectorProxy.test.ts} +4 -4
- package/src/selector/future/SelectorProxy.ts +238 -0
- package/src/selector/future/array.ts +37 -0
- package/src/selector/future/boolean.ts +4 -0
- package/src/selector/future/file.ts +14 -0
- package/src/selector/{i18n.ts → future/i18n.ts} +2 -2
- package/src/selector/future/index.ts +165 -0
- package/src/selector/future/number.ts +4 -0
- package/src/selector/future/object.ts +22 -0
- package/src/selector/future/primitive.ts +17 -0
- package/src/selector/{remote.ts → future/remote.ts} +1 -1
- package/src/selector/{selector.test.ts → future/selector.test.ts} +8 -28
- package/src/selector/{selectorOf.ts → future/selectorOf.ts} +1 -1
- package/src/selector/future/string.ts +4 -0
- package/src/selector/index.ts +4 -46
- package/src/selector/object.ts +2 -19
- package/src/selector/primitive.ts +3 -16
- package/src/source/{i18n.ts → future/i18n.ts} +2 -2
- package/src/source/{remote.ts → future/remote.ts} +3 -3
- package/src/source/index.ts +3 -2
- package/src/val/array.ts +1 -1
- package/src/val/index.ts +2 -2
- package/src/val/object.ts +1 -1
- package/dist/createClass-012eebbf.esm.js +0 -109
- package/dist/createClass-a436dbfe.cjs.dev.js +0 -116
- package/dist/createClass-de7426aa.cjs.prod.js +0 -116
- package/dist/declarations/src/fetchVal.d.ts +0 -5
- package/dist/declarations/src/schema/i18n.d.ts +0 -21
- package/dist/declarations/src/schema/oneOf.d.ts +0 -22
- package/dist/ops-6fae92a1.esm.js +0 -12
- package/dist/ops-87cdbafc.cjs.dev.js +0 -14
- package/dist/ops-ae4d1bc2.cjs.prod.js +0 -14
package/src/module.ts
CHANGED
@@ -4,16 +4,15 @@ import {
|
|
4
4
|
GenericSelector,
|
5
5
|
SelectorOf,
|
6
6
|
SelectorSource,
|
7
|
-
|
7
|
+
GetSource,
|
8
|
+
GetSchema,
|
9
|
+
Path,
|
8
10
|
} from "./selector";
|
9
|
-
import { Source
|
10
|
-
import { newSelectorProxy } from "./selector/SelectorProxy";
|
11
|
+
import { Source } from "./source";
|
11
12
|
import { ModuleId, ModulePath, SourcePath } from "./val";
|
12
13
|
import { Expr } from "./expr";
|
13
14
|
import { ArraySchema, SerializedArraySchema } from "./schema/array";
|
14
|
-
import { I18nSchema, SerializedI18nSchema } from "./schema/i18n";
|
15
15
|
import { UnionSchema, SerializedUnionSchema } from "./schema/union";
|
16
|
-
import { OneOfSchema, SerializedOneOfSchema } from "./schema/oneOf";
|
17
16
|
import { Json } from "./Json";
|
18
17
|
import { RichTextSchema, SerializedRichTextSchema } from "./schema/richtext";
|
19
18
|
import {
|
@@ -43,11 +42,15 @@ export function content<T extends Schema<SelectorSource>>(
|
|
43
42
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
44
43
|
source: SchemaTypeOf<T>
|
45
44
|
): ValModule<SchemaTypeOf<T>> {
|
46
|
-
return
|
45
|
+
return {
|
46
|
+
[GetSource]: source,
|
47
|
+
[GetSchema]: schema,
|
48
|
+
[Path]: id as SourcePath,
|
49
|
+
} as unknown as ValModule<SchemaTypeOf<T>>;
|
47
50
|
}
|
48
51
|
|
49
|
-
export function
|
50
|
-
const sourceOrExpr = valModule[
|
52
|
+
export function getSource(valModule: ValModule<SelectorSource>): Source {
|
53
|
+
const sourceOrExpr = valModule[GetSource];
|
51
54
|
if (sourceOrExpr instanceof Expr) {
|
52
55
|
throw Error("Cannot get raw source of an Expr");
|
53
56
|
}
|
@@ -100,14 +103,14 @@ function isArraySchema(
|
|
100
103
|
);
|
101
104
|
}
|
102
105
|
|
103
|
-
function isI18nSchema(
|
104
|
-
|
105
|
-
): schema is I18nSchema<readonly string[]> | SerializedI18nSchema {
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
}
|
106
|
+
// function isI18nSchema(
|
107
|
+
// schema: Schema<SelectorSource> | SerializedSchema
|
108
|
+
// ): schema is I18nSchema<readonly string[]> | SerializedI18nSchema {
|
109
|
+
// return (
|
110
|
+
// schema instanceof I18nSchema ||
|
111
|
+
// (typeof schema === "object" && "type" in schema && schema.type === "i18n")
|
112
|
+
// );
|
113
|
+
// }
|
111
114
|
|
112
115
|
function isUnionSchema(
|
113
116
|
schema: Schema<SelectorSource> | SerializedSchema
|
@@ -144,15 +147,14 @@ function isImageSchema(
|
|
144
147
|
);
|
145
148
|
}
|
146
149
|
|
147
|
-
//
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
}
|
150
|
+
// function isOneOfSchema(
|
151
|
+
// schema: Schema<SelectorSource> | SerializedSchema
|
152
|
+
// ): schema is OneOfSchema<GenericSelector<SourceArray>> | SerializedOneOfSchema {
|
153
|
+
// return (
|
154
|
+
// schema instanceof OneOfSchema ||
|
155
|
+
// (typeof schema === "object" && "type" in schema && schema.type === "oneOf")
|
156
|
+
// );
|
157
|
+
// }
|
156
158
|
|
157
159
|
export function resolvePath(
|
158
160
|
path: ModulePath,
|
@@ -204,23 +206,23 @@ export function resolvePath(
|
|
204
206
|
}
|
205
207
|
resolvedSource = resolvedSource[part];
|
206
208
|
resolvedSchema = resolvedSchema.items[part];
|
207
|
-
|
208
|
-
if (!resolvedSchema.locales.includes(part)) {
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
}
|
215
|
-
if (!Object.keys(resolvedSource).includes(part)) {
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
}
|
222
|
-
resolvedSource = resolvedSource[part];
|
223
|
-
resolvedSchema = resolvedSchema.item;
|
209
|
+
// } else if (isI18nSchema(resolvedSchema)) {
|
210
|
+
// if (!resolvedSchema.locales.includes(part)) {
|
211
|
+
// throw Error(
|
212
|
+
// `Invalid path: i18n schema ${resolvedSchema} supports locales ${resolvedSchema.locales.join(
|
213
|
+
// ", "
|
214
|
+
// )}, but found: ${part}`
|
215
|
+
// );
|
216
|
+
// }
|
217
|
+
// if (!Object.keys(resolvedSource).includes(part)) {
|
218
|
+
// throw Error(
|
219
|
+
// `Schema type error: expected source to be type of i18n with locale ${part}, but got ${JSON.stringify(
|
220
|
+
// Object.keys(resolvedSource)
|
221
|
+
// )}`
|
222
|
+
// );
|
223
|
+
// }
|
224
|
+
// resolvedSource = resolvedSource[part];
|
225
|
+
// resolvedSchema = resolvedSchema.item;
|
224
226
|
} else if (isImageSchema(resolvedSchema)) {
|
225
227
|
return {
|
226
228
|
path: origParts
|
@@ -270,7 +272,15 @@ export function resolvePath(
|
|
270
272
|
throw Error(`Invalid path: ${parts.join(".")} is not a valid path`);
|
271
273
|
}
|
272
274
|
return {
|
273
|
-
path
|
275
|
+
path: origParts
|
276
|
+
.map((p) => {
|
277
|
+
if (!Number.isNaN(Number(p))) {
|
278
|
+
return p;
|
279
|
+
} else {
|
280
|
+
return JSON.stringify(p);
|
281
|
+
}
|
282
|
+
})
|
283
|
+
.join("."), // TODO: create a function generate path from parts (not sure if this always works)
|
274
284
|
schema: resolvedSchema,
|
275
285
|
source: resolvedSource,
|
276
286
|
};
|
package/src/patch/deref.test.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { file } from "../source/file";
|
2
2
|
import { result } from "../fp";
|
3
|
-
import { remote } from "../source/remote";
|
3
|
+
import { remote } from "../source/future/remote";
|
4
4
|
import { derefPatch, DerefPatchResult } from "./deref";
|
5
5
|
import { JSONOps } from "./json";
|
6
6
|
import { PatchError } from "./ops";
|
package/src/patch/deref.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { FILE_REF_PROP, isFile } from "../source/file";
|
2
2
|
import { result } from "../fp";
|
3
|
-
import { isRemote, REMOTE_REF_PROP } from "../source/remote";
|
3
|
+
import { isRemote, REMOTE_REF_PROP } from "../source/future/remote";
|
4
4
|
import { Ops, PatchError } from "./ops";
|
5
5
|
import { Patch } from "./patch";
|
6
6
|
|
package/src/patch/index.ts
CHANGED
package/src/patch/json.test.ts
CHANGED
package/src/patch/util.ts
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
import { array, result } from "../fp";
|
2
2
|
import { PatchError, ReadonlyJSONValue, ToMutable } from "./ops";
|
3
|
+
import { splitModuleIdAndModulePath } from "../module";
|
4
|
+
import { SourcePath } from "../val";
|
3
5
|
|
4
6
|
export function isNotRoot(path: string[]): path is array.NonEmptyArray<string> {
|
5
7
|
return array.isNonEmpty(path);
|
@@ -65,3 +67,8 @@ export function parseAndValidateArrayIndex(
|
|
65
67
|
}
|
66
68
|
return result.ok(Number(value));
|
67
69
|
}
|
70
|
+
|
71
|
+
export function sourceToPatchPath(sourcePath: SourcePath) {
|
72
|
+
const [, modulePath] = splitModuleIdAndModulePath(sourcePath);
|
73
|
+
return modulePath.split(".").map((p) => JSON.parse(p).toString());
|
74
|
+
}
|
package/src/schema/array.ts
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
2
2
|
import { Schema, SchemaTypeOf, SerializedSchema } from ".";
|
3
3
|
import { SelectorSource } from "../selector";
|
4
|
+
import { createValPathOfItem } from "../selector/SelectorProxy";
|
4
5
|
import { SourcePath } from "../val";
|
6
|
+
import { ValidationErrors } from "./validation/ValidationError";
|
5
7
|
|
6
8
|
export type SerializedArraySchema = {
|
7
9
|
type: "array";
|
@@ -16,11 +18,46 @@ export class ArraySchema<T extends Schema<SelectorSource>> extends Schema<
|
|
16
18
|
super();
|
17
19
|
}
|
18
20
|
|
19
|
-
validate(src: SchemaTypeOf<T>[]):
|
20
|
-
|
21
|
+
validate(path: SourcePath, src: SchemaTypeOf<T>[]): ValidationErrors {
|
22
|
+
let error: ValidationErrors = false;
|
23
|
+
|
24
|
+
if (this.opt && (src === null || src === undefined)) {
|
25
|
+
return false;
|
26
|
+
}
|
27
|
+
|
28
|
+
if (typeof src !== "object" || !Array.isArray(src)) {
|
29
|
+
return {
|
30
|
+
[path]: [{ message: `Expected 'array', got '${typeof src}'` }],
|
31
|
+
} as ValidationErrors;
|
32
|
+
}
|
33
|
+
src.forEach((i, idx) => {
|
34
|
+
const subPath = createValPathOfItem(path, idx);
|
35
|
+
if (!subPath) {
|
36
|
+
error = this.appendValidationError(
|
37
|
+
error,
|
38
|
+
path,
|
39
|
+
`Internal error: could not create path at ${
|
40
|
+
!path && typeof path === "string" ? "<empty string>" : path
|
41
|
+
} at index ${idx}`, // Should! never happen
|
42
|
+
src
|
43
|
+
);
|
44
|
+
} else {
|
45
|
+
const subError = this.item.validate(subPath, i);
|
46
|
+
if (subError && error) {
|
47
|
+
error = {
|
48
|
+
...subError,
|
49
|
+
...error,
|
50
|
+
};
|
51
|
+
} else if (subError) {
|
52
|
+
error = subError;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
});
|
56
|
+
|
57
|
+
return error;
|
21
58
|
}
|
22
59
|
|
23
|
-
|
60
|
+
assert(src: SchemaTypeOf<T>[]): boolean {
|
24
61
|
if (this.opt && (src === null || src === undefined)) {
|
25
62
|
return true;
|
26
63
|
}
|
@@ -28,7 +65,11 @@ export class ArraySchema<T extends Schema<SelectorSource>> extends Schema<
|
|
28
65
|
return false;
|
29
66
|
}
|
30
67
|
|
31
|
-
|
68
|
+
for (const item of src) {
|
69
|
+
if (!this.item.assert(item)) {
|
70
|
+
return false;
|
71
|
+
}
|
72
|
+
}
|
32
73
|
return typeof src === "object" && Array.isArray(src);
|
33
74
|
}
|
34
75
|
|
package/src/schema/boolean.ts
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
2
2
|
import { Schema, SerializedSchema } from ".";
|
3
3
|
import { SourcePath } from "../val";
|
4
|
+
import { ValidationErrors } from "./validation/ValidationError";
|
4
5
|
|
5
6
|
export type SerializedBooleanSchema = {
|
6
7
|
type: "boolean";
|
@@ -11,11 +12,21 @@ export class BooleanSchema<Src extends boolean | null> extends Schema<Src> {
|
|
11
12
|
constructor(readonly opt: boolean = false) {
|
12
13
|
super();
|
13
14
|
}
|
14
|
-
validate(src: Src):
|
15
|
-
|
15
|
+
validate(path: SourcePath, src: Src): ValidationErrors {
|
16
|
+
if (this.opt && (src === null || src === undefined)) {
|
17
|
+
return false;
|
18
|
+
}
|
19
|
+
if (typeof src !== "boolean") {
|
20
|
+
return {
|
21
|
+
[path]: [
|
22
|
+
{ message: `Expected 'boolean', got '${typeof src}'`, value: src },
|
23
|
+
],
|
24
|
+
} as ValidationErrors;
|
25
|
+
}
|
26
|
+
return false;
|
16
27
|
}
|
17
28
|
|
18
|
-
|
29
|
+
assert(src: Src): boolean {
|
19
30
|
if (this.opt && (src === null || src === undefined)) {
|
20
31
|
return true;
|
21
32
|
}
|
@@ -1,7 +1,8 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
2
|
-
import { Schema, SchemaTypeOf, SerializedSchema } from "
|
3
|
-
import { I18nCompatibleSource, I18nSource } from "
|
4
|
-
import { SourcePath } from "
|
2
|
+
import { Schema, SchemaTypeOf, SerializedSchema } from "..";
|
3
|
+
import { I18nCompatibleSource, I18nSource } from "../../source/future/i18n";
|
4
|
+
import { SourcePath } from "../../val";
|
5
|
+
import { ValidationErrors } from "../validation/ValidationError";
|
5
6
|
|
6
7
|
export type SerializedI18nSchema = {
|
7
8
|
type: "i18n";
|
@@ -22,12 +23,13 @@ export class I18nSchema<Locales extends readonly string[]> extends Schema<
|
|
22
23
|
}
|
23
24
|
|
24
25
|
validate(
|
26
|
+
path: SourcePath,
|
25
27
|
src: I18nSource<Locales, SchemaTypeOf<Schema<I18nCompatibleSource>>>
|
26
|
-
):
|
28
|
+
): ValidationErrors {
|
27
29
|
throw new Error("Method not implemented.");
|
28
30
|
}
|
29
31
|
|
30
|
-
|
32
|
+
assert(
|
31
33
|
src: I18nSource<Locales, SchemaTypeOf<Schema<I18nCompatibleSource>>>
|
32
34
|
): boolean {
|
33
35
|
throw new Error("Method not implemented.");
|
@@ -41,12 +43,14 @@ export class I18nSchema<Locales extends readonly string[]> extends Schema<
|
|
41
43
|
}
|
42
44
|
|
43
45
|
serialize(): SerializedSchema {
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
throw new Error("Method not implemented.");
|
47
|
+
|
48
|
+
// return {
|
49
|
+
// type: "i18n",
|
50
|
+
// item: this.item.serialize(),
|
51
|
+
// locales: this.locales,
|
52
|
+
// opt: this.opt,
|
53
|
+
// };
|
50
54
|
}
|
51
55
|
}
|
52
56
|
|
@@ -1,9 +1,10 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
2
|
-
import { Schema, SerializedSchema } from "
|
3
|
-
import { ValModuleBrand } from "
|
4
|
-
import { GenericSelector } from "
|
5
|
-
import { Source, SourceArray } from "
|
6
|
-
import {
|
2
|
+
import { Schema, SerializedSchema } from "..";
|
3
|
+
import { ValModuleBrand } from "../../module";
|
4
|
+
import { GenericSelector } from "../../selector/future";
|
5
|
+
import { Source, SourceArray } from "../../source";
|
6
|
+
import { SourcePath } from "../../val";
|
7
|
+
import { ValidationErrors } from "../validation/ValidationError";
|
7
8
|
|
8
9
|
export type SerializedOneOfSchema = {
|
9
10
|
type: "oneOf";
|
@@ -26,10 +27,10 @@ export class OneOfSchema<
|
|
26
27
|
constructor(readonly selector: Sel, readonly opt: boolean = false) {
|
27
28
|
super();
|
28
29
|
}
|
29
|
-
validate(src: OneOfSelector<Sel>):
|
30
|
+
validate(path: SourcePath, src: OneOfSelector<Sel>): ValidationErrors {
|
30
31
|
throw new Error("Method not implemented.");
|
31
32
|
}
|
32
|
-
|
33
|
+
assert(src: OneOfSelector<Sel>): boolean {
|
33
34
|
throw new Error("Method not implemented.");
|
34
35
|
}
|
35
36
|
optional(): Schema<OneOfSelector<Sel> | null> {
|
@@ -37,17 +38,19 @@ export class OneOfSchema<
|
|
37
38
|
}
|
38
39
|
|
39
40
|
serialize(): SerializedSchema {
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
41
|
+
throw new Error("Method not implemented.");
|
42
|
+
|
43
|
+
// const path = getValPath(this.selector);
|
44
|
+
// if (!path) {
|
45
|
+
// throw new Error(
|
46
|
+
// "Cannot serialize oneOf schema with empty selector. Make sure a Val module is used."
|
47
|
+
// );
|
48
|
+
// }
|
49
|
+
// return {
|
50
|
+
// type: "oneOf",
|
51
|
+
// selector: path,
|
52
|
+
// opt: this.opt,
|
53
|
+
// };
|
51
54
|
}
|
52
55
|
}
|
53
56
|
|
package/src/schema/image.ts
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
2
2
|
import { Schema, SerializedSchema } from ".";
|
3
|
+
import { VAL_EXTENSION } from "../source";
|
3
4
|
import { FileSource, FILE_REF_PROP } from "../source/file";
|
4
5
|
import { SourcePath } from "../val";
|
6
|
+
import { ValidationErrors } from "./validation/ValidationError";
|
5
7
|
|
6
8
|
export type ImageOptions = {
|
7
9
|
ext: ["jpg"] | ["webp"];
|
@@ -29,13 +31,71 @@ export class ImageSchema<
|
|
29
31
|
super();
|
30
32
|
}
|
31
33
|
|
32
|
-
validate(src: Src):
|
33
|
-
|
34
|
+
validate(path: SourcePath, src: Src): ValidationErrors {
|
35
|
+
if (this.opt && (src === null || src === undefined)) {
|
36
|
+
return false;
|
37
|
+
}
|
38
|
+
if (src === null || src === undefined) {
|
39
|
+
return {
|
40
|
+
[path]: [
|
41
|
+
{
|
42
|
+
message: `Non-optional image was null or undefined.`,
|
43
|
+
value: src,
|
44
|
+
},
|
45
|
+
],
|
46
|
+
} as ValidationErrors;
|
47
|
+
}
|
48
|
+
if (typeof src[FILE_REF_PROP] !== "string") {
|
49
|
+
return {
|
50
|
+
[path]: [
|
51
|
+
{
|
52
|
+
message: `Image did not have a file reference string. Got: ${typeof src[
|
53
|
+
FILE_REF_PROP
|
54
|
+
]}`,
|
55
|
+
value: src,
|
56
|
+
},
|
57
|
+
],
|
58
|
+
} as ValidationErrors;
|
59
|
+
}
|
60
|
+
|
61
|
+
if (src[VAL_EXTENSION] !== "file") {
|
62
|
+
return {
|
63
|
+
[path]: [
|
64
|
+
{
|
65
|
+
message: `Image did not have the valid file extension type. Got: ${src[VAL_EXTENSION]}`,
|
66
|
+
value: src,
|
67
|
+
},
|
68
|
+
],
|
69
|
+
} as ValidationErrors;
|
70
|
+
}
|
71
|
+
if (src.metadata) {
|
72
|
+
return {
|
73
|
+
[path]: [
|
74
|
+
{
|
75
|
+
message: `Found metadata, but it could not be validated. Image metadata must be an object with the required props: width (positive number), height (positive number) and sha256 (string of length 64 of the base16 hash).`, // These validation errors will have to be picked up by logic outside of this package and revalidated. Reasons: 1) we have to read files to verify the metadata, which is handled differently in different runtimes (Browser, QuickJS, Node.js); 2) we want to keep this package dependency free.
|
76
|
+
value: src,
|
77
|
+
fixes: ["image:replace-metadata"],
|
78
|
+
},
|
79
|
+
],
|
80
|
+
} as ValidationErrors;
|
81
|
+
}
|
82
|
+
|
83
|
+
return {
|
84
|
+
[path]: [
|
85
|
+
{
|
86
|
+
message: `Could not validate Image metadata.`,
|
87
|
+
value: src,
|
88
|
+
fixes: ["image:add-metadata"],
|
89
|
+
},
|
90
|
+
],
|
91
|
+
} as ValidationErrors;
|
34
92
|
}
|
35
93
|
|
36
|
-
|
37
|
-
|
38
|
-
|
94
|
+
assert(src: Src): boolean {
|
95
|
+
if (this.opt && (src === null || src === undefined)) {
|
96
|
+
return true;
|
97
|
+
}
|
98
|
+
return src?.[FILE_REF_PROP] === "image" && src?.[VAL_EXTENSION] === "file";
|
39
99
|
}
|
40
100
|
|
41
101
|
optional(): Schema<Src | null> {
|
@@ -57,7 +117,7 @@ export const image = (
|
|
57
117
|
return new ImageSchema(options);
|
58
118
|
};
|
59
119
|
|
60
|
-
export const
|
120
|
+
export const convertFileSource = (
|
61
121
|
src: FileSource<ImageMetadata>
|
62
122
|
): { url: string; metadata?: ImageMetadata } => {
|
63
123
|
// TODO: /public should be configurable
|
package/src/schema/index.ts
CHANGED
@@ -1,41 +1,65 @@
|
|
1
1
|
import { SelectorSource } from "../selector";
|
2
|
-
import { RemoteCompatibleSource, RemoteSource } from "../source/remote";
|
2
|
+
// import { RemoteCompatibleSource, RemoteSource } from "../source/remote";
|
3
3
|
import { SourcePath } from "../val";
|
4
4
|
import { SerializedArraySchema } from "./array";
|
5
5
|
import { SerializedBooleanSchema } from "./boolean";
|
6
|
-
import { SerializedI18nSchema } from "./i18n";
|
7
6
|
import { SerializedImageSchema } from "./image";
|
7
|
+
import { SerializedKeyOfSchema } from "./keyOf";
|
8
8
|
import { SerializedLiteralSchema } from "./literal";
|
9
9
|
import { SerializedNumberSchema } from "./number";
|
10
10
|
import { SerializedObjectSchema } from "./object";
|
11
|
-
import {
|
11
|
+
import { SerializedRecordSchema } from "./record";
|
12
12
|
import { SerializedRichTextSchema } from "./richtext";
|
13
13
|
import { SerializedStringSchema } from "./string";
|
14
14
|
import { SerializedUnionSchema } from "./union";
|
15
|
+
import { ValidationErrors } from "./validation/ValidationError";
|
16
|
+
// import { SerializedI18nSchema } from "./future/i18n";
|
17
|
+
// import { SerializedOneOfSchema } from "./future/oneOf";
|
15
18
|
|
16
19
|
export type SerializedSchema =
|
20
|
+
// | SerializedOneOfSchema
|
21
|
+
// | SerializedI18nSchema
|
17
22
|
| SerializedStringSchema
|
18
23
|
| SerializedLiteralSchema
|
19
24
|
| SerializedBooleanSchema
|
20
25
|
| SerializedNumberSchema
|
21
26
|
| SerializedObjectSchema
|
22
|
-
| SerializedOneOfSchema
|
23
27
|
| SerializedArraySchema
|
24
28
|
| SerializedUnionSchema
|
25
29
|
| SerializedRichTextSchema
|
26
|
-
|
|
27
|
-
|
|
30
|
+
| SerializedRecordSchema
|
31
|
+
| SerializedKeyOfSchema
|
32
|
+
| SerializedImageSchema;
|
28
33
|
|
29
34
|
export abstract class Schema<Src extends SelectorSource> {
|
30
|
-
abstract validate(src: Src):
|
31
|
-
abstract
|
35
|
+
abstract validate(path: SourcePath, src: Src): ValidationErrors;
|
36
|
+
abstract assert(src: Src): boolean; // TODO: false | Record<SourcePath, string[]>;
|
32
37
|
abstract optional(): Schema<Src | null>;
|
33
38
|
abstract serialize(): SerializedSchema;
|
34
|
-
remote(): Src extends RemoteCompatibleSource
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
+
// remote(): Src extends RemoteCompatibleSource
|
40
|
+
// ? Schema<RemoteSource<Src>>
|
41
|
+
// : never {
|
42
|
+
// // TODO: Schema<never, "Cannot create remote schema from non-remote source.">
|
43
|
+
// throw new Error("You need Val Ultra to use .remote()");
|
44
|
+
// }
|
45
|
+
|
46
|
+
/** MUTATES! since internal and perf sensitive */
|
47
|
+
protected appendValidationError(
|
48
|
+
current: ValidationErrors,
|
49
|
+
path: SourcePath,
|
50
|
+
message: string,
|
51
|
+
value?: unknown
|
52
|
+
): ValidationErrors {
|
53
|
+
if (current) {
|
54
|
+
if (current[path]) {
|
55
|
+
current[path].push({ message, value });
|
56
|
+
} else {
|
57
|
+
current[path] = [{ message, value }];
|
58
|
+
}
|
59
|
+
return current;
|
60
|
+
} else {
|
61
|
+
return { [path]: [{ message, value }] } as ValidationErrors;
|
62
|
+
}
|
39
63
|
}
|
40
64
|
}
|
41
65
|
|