@builder-builder/builder 0.0.13 → 0.0.15
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/dist/bb.d.ts +3 -1
- package/dist/bb.js +6 -1
- package/dist/check.d.ts +2 -2
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +53 -0
- package/dist/codegen/index.d.ts +7 -0
- package/dist/codegen/index.js +212 -0
- package/dist/codegen/template.d.ts +5 -0
- package/dist/codegen/template.js +17 -0
- package/dist/entities/builder/builder.d.ts +11 -1
- package/dist/entities/builder/builder.js +22 -6
- package/dist/entities/collection/collection.d.ts +7 -1
- package/dist/entities/collection/collection.js +9 -2
- package/dist/entities/collection/config.d.ts +6 -1
- package/dist/entities/collection/config.js +9 -2
- package/dist/entities/component/component.d.ts +41 -1
- package/dist/entities/component/component.js +9 -2
- package/dist/entities/component/details.d.ts +11 -2
- package/dist/entities/component/details.js +9 -2
- package/dist/entities/component/field.d.ts +10 -1
- package/dist/entities/component/field.js +13 -3
- package/dist/entities/index.d.ts +7 -3
- package/dist/entities/index.js +3 -1
- package/dist/entities/kind.d.ts +1 -1
- package/dist/entities/model/model.d.ts +5 -1
- package/dist/entities/model/model.js +10 -3
- package/dist/entities/model/models.js +9 -5
- package/dist/entities/option/option.d.ts +41 -1
- package/dist/entities/option/option.js +9 -2
- package/dist/entities/option/select.d.ts +7 -1
- package/dist/entities/option/select.js +17 -6
- package/dist/entities/option/toggle.d.ts +7 -1
- package/dist/entities/option/toggle.js +16 -4
- package/dist/entities/option/values.d.ts +6 -0
- package/dist/entities/pricing.d.ts +64 -0
- package/dist/entities/pricing.js +48 -0
- package/dist/entities/serialise.d.ts +632 -8
- package/dist/entities/serialise.js +33 -12
- package/dist/entities/tags.d.ts +3 -0
- package/dist/entities/tags.js +2 -0
- package/dist/entities/ui/describe.d.ts +231 -8
- package/dist/entities/ui/describe.js +12 -5
- package/dist/entities/ui/index.d.ts +2 -0
- package/dist/entities/ui/index.js +1 -0
- package/dist/entities/ui/input.d.ts +343 -0
- package/dist/entities/ui/input.js +51 -0
- package/dist/entities/ui/page.d.ts +231 -8
- package/dist/entities/ui/page.js +12 -5
- package/dist/entities/ui/pages.d.ts +5 -1
- package/dist/entities/ui/pages.js +9 -2
- package/dist/entities/ui/ui.d.ts +9 -4
- package/dist/entities/ui/ui.js +29 -11
- package/dist/entities/validated.d.ts +7 -3
- package/dist/exception.d.ts +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/instance.d.ts +9 -0
- package/dist/instance.js +3 -1
- package/dist/mappers/index.d.ts +6 -4
- package/dist/mappers/index.js +3 -2
- package/dist/mappers/pricing.d.ts +3 -0
- package/dist/mappers/pricing.js +101 -0
- package/dist/mappers/render/index.d.ts +1 -1
- package/dist/mappers/render/pages.d.ts +8 -0
- package/dist/mappers/render/pages.js +2 -1
- package/dist/mappers/render/render.js +19 -3
- package/dist/mappers/resolve.d.ts +4 -4
- package/dist/mappers/variants/index.d.ts +2 -1
- package/dist/mappers/variants/index.js +2 -1
- package/dist/mappers/variants/variants.d.ts +5 -2
- package/dist/mappers/variants/variants.js +2 -2
- package/dist/validate/brand.d.ts +0 -7
- package/dist/validate/brand.js +5 -5
- package/dist/validate/builder.d.ts +2 -1
- package/dist/validate/builder.js +19 -13
- package/dist/validate/errors.d.ts +138 -0
- package/dist/validate/errors.js +148 -0
- package/dist/validate/expectations.d.ts +3 -10
- package/dist/validate/expectations.js +8 -10
- package/dist/validate/index.d.ts +10 -14
- package/dist/validate/index.js +5 -7
- package/dist/validate/instance.d.ts +2 -15
- package/dist/validate/instance.js +41 -40
- package/dist/validate/model.d.ts +4 -31
- package/dist/validate/model.js +157 -176
- package/dist/validate/pricing.d.ts +6 -0
- package/dist/validate/pricing.js +71 -0
- package/dist/validate/resolve.d.ts +3 -15
- package/dist/validate/resolve.js +66 -69
- package/dist/validate/result.d.ts +1 -7
- package/dist/validate/result.js +1 -4
- package/dist/validate/ui.d.ts +4 -4
- package/dist/validate/ui.js +80 -62
- package/dist/validate/variants.d.ts +2 -53
- package/dist/validate/variants.js +83 -86
- package/package.json +12 -3
|
@@ -24,10 +24,10 @@ function buildVariants(model) {
|
|
|
24
24
|
]))
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
-
function optionGraph(model) {
|
|
27
|
+
export function optionGraph(model) {
|
|
28
28
|
return model.options.reduce((graph, option) => graph.add(option, model), new BuilderOptionGraph());
|
|
29
29
|
}
|
|
30
|
-
function variantsFor(entity, options) {
|
|
30
|
+
export function variantsFor(entity, options) {
|
|
31
31
|
const keys = new Set(dependencyKeys(entity.payload, entity.paths));
|
|
32
32
|
const graphPaths = Array.from(keys)
|
|
33
33
|
.map((key) => options.get(key))
|
package/dist/validate/brand.d.ts
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
import type { BuilderErrorLocation } from '../exception';
|
|
2
1
|
declare const VALIDATED: unique symbol;
|
|
3
2
|
export type BuilderValidatedBrand = {
|
|
4
3
|
readonly [VALIDATED]: true;
|
|
5
4
|
};
|
|
6
|
-
export declare function builderErrorUnvalidated(value: unknown, location?: BuilderErrorLocation): {
|
|
7
|
-
value: unknown;
|
|
8
|
-
kind: "unvalidated";
|
|
9
|
-
location: BuilderErrorLocation;
|
|
10
|
-
};
|
|
11
|
-
export type BuilderErrorUnvalidated = ReturnType<typeof builderErrorUnvalidated>;
|
|
12
5
|
export declare function validate<Input extends object>(value: Input): Input & BuilderValidatedBrand;
|
|
13
6
|
export declare function assertValidated<Input>(value: Input): asserts value is Input & BuilderValidatedBrand;
|
|
14
7
|
export {};
|
package/dist/validate/brand.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BuilderException } from '../exception.js';
|
|
2
|
+
import { BuilderValidateErrors } from './errors.js';
|
|
2
3
|
const VALIDATED = Symbol('builder.validated');
|
|
3
|
-
export function builderErrorUnvalidated(value, location = []) {
|
|
4
|
-
return { ...builderError('unvalidated', location), value };
|
|
5
|
-
}
|
|
6
4
|
export function validate(value) {
|
|
7
5
|
// Descriptor flags chosen for Svelte 5 `$state` proxy compatibility — `$state`
|
|
8
6
|
// rejects any property that isn't writable, configurable, and enumerable.
|
|
@@ -18,6 +16,8 @@ export function validate(value) {
|
|
|
18
16
|
}
|
|
19
17
|
export function assertValidated(value) {
|
|
20
18
|
if (typeof value !== 'object' || value === null || !(VALIDATED in value)) {
|
|
21
|
-
|
|
19
|
+
const errors = new BuilderValidateErrors();
|
|
20
|
+
errors.unvalidated(value);
|
|
21
|
+
throw new BuilderException(errors.errors);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { BuilderRefEntities, BuilderValidated } from '../entities/index';
|
|
2
2
|
import type { ValidationResult } from './result';
|
|
3
|
+
import { BuilderValidateErrors } from './errors.js';
|
|
3
4
|
export type BuilderValidationResult = ValidationResult<BuilderValidated>;
|
|
4
|
-
export declare function validateBuilder(input: unknown, references?: BuilderRefEntities): BuilderValidationResult;
|
|
5
|
+
export declare function validateBuilder(input: unknown, references?: BuilderRefEntities, errors?: BuilderValidateErrors): BuilderValidationResult;
|
package/dist/validate/builder.js
CHANGED
|
@@ -1,27 +1,33 @@
|
|
|
1
1
|
import { check } from '../check.js';
|
|
2
2
|
import { builder, BuilderSerialisedSchema, modelsMerge, serialise } from '../entities/index.js';
|
|
3
3
|
import { validate } from './brand.js';
|
|
4
|
+
import { BuilderValidateErrors } from './errors.js';
|
|
4
5
|
import { checkModelExpectations, validateModelStructure } from './model.js';
|
|
6
|
+
import { validatePricingStructure } from './pricing.js';
|
|
5
7
|
import { resolver } from './resolve.js';
|
|
6
|
-
import { builderErrorInvalidInput } from './result.js';
|
|
7
8
|
import { checkUIExpectations, validateUIStructure } from './ui.js';
|
|
8
|
-
export function validateBuilder(input, references = []) {
|
|
9
|
+
export function validateBuilder(input, references = [], errors = new BuilderValidateErrors()) {
|
|
9
10
|
if (!check.is(BuilderSerialisedSchema, input)) {
|
|
10
|
-
|
|
11
|
-
return [validate(serialise.builder(builder())), errors];
|
|
11
|
+
errors.invalidInput('builder');
|
|
12
|
+
return [validate(serialise.builder(builder())), errors.errors];
|
|
12
13
|
}
|
|
13
|
-
const resolve = resolver(references, input.bindings);
|
|
14
|
-
const
|
|
15
|
-
const
|
|
14
|
+
const resolve = resolver(errors, references, input.bindings);
|
|
15
|
+
const validatedModel = errors.scope('model', () => validateModelStructure(input.model, resolve, errors));
|
|
16
|
+
const validatedUI = errors.scope('ui', () => validateUIStructure(input.ui, resolve, errors));
|
|
16
17
|
const mergedModel = modelsMerge(validatedModel);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
errors.scope('model', () => {
|
|
19
|
+
checkModelExpectations(mergedModel, validatedModel, errors);
|
|
20
|
+
});
|
|
21
|
+
errors.scope('ui', () => {
|
|
22
|
+
checkUIExpectations(mergedModel, validatedUI, errors);
|
|
23
|
+
});
|
|
24
|
+
if (input.pricing) {
|
|
25
|
+
errors.scope('pricing', () => validatePricingStructure(resolve(input.pricing) ?? input.pricing, errors));
|
|
26
|
+
}
|
|
21
27
|
const data = validate({
|
|
22
|
-
...
|
|
28
|
+
...input,
|
|
23
29
|
model: mergedModel,
|
|
24
30
|
ui: validatedUI
|
|
25
31
|
});
|
|
26
|
-
return [data,
|
|
32
|
+
return [data, errors.errors];
|
|
27
33
|
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { BuilderExpectationKind } from '../entities/index';
|
|
2
|
+
import type { BuilderErrorLocation, BuilderErrors } from '../exception';
|
|
3
|
+
import type { BuilderInstance } from '../instance';
|
|
4
|
+
export type BuilderInvalidInputTarget = 'builder' | 'model' | 'pricing' | 'ui' | 'variants';
|
|
5
|
+
export type BuilderErrorInvalidPathReason = 'shape' | 'out-of-bounds' | 'missing-collection' | 'option-not-found';
|
|
6
|
+
export type BuilderErrorInvalidPricingReason = 'scope' | 'nested-variants' | 'missing-rate' | 'invalid-filter';
|
|
7
|
+
export declare class BuilderValidateErrors {
|
|
8
|
+
#private;
|
|
9
|
+
get errors(): BuilderErrors;
|
|
10
|
+
scope<Result>(part: string | number, fn: () => Result): Result;
|
|
11
|
+
invalidInput(target: BuilderInvalidInputTarget): {
|
|
12
|
+
target: BuilderInvalidInputTarget;
|
|
13
|
+
kind: "invalid-input";
|
|
14
|
+
location: BuilderErrorLocation;
|
|
15
|
+
};
|
|
16
|
+
invalidOption(name: string, value: unknown): {
|
|
17
|
+
name: string;
|
|
18
|
+
value: unknown;
|
|
19
|
+
kind: "invalid-option";
|
|
20
|
+
location: BuilderErrorLocation;
|
|
21
|
+
};
|
|
22
|
+
invalidCollection(name: string): {
|
|
23
|
+
name: string;
|
|
24
|
+
kind: "invalid-collection";
|
|
25
|
+
location: BuilderErrorLocation;
|
|
26
|
+
};
|
|
27
|
+
duplicateName(name: string): {
|
|
28
|
+
name: string;
|
|
29
|
+
kind: "duplicate-name";
|
|
30
|
+
location: BuilderErrorLocation;
|
|
31
|
+
};
|
|
32
|
+
invalidCollectionBounds(name: string, min: number, max: number): {
|
|
33
|
+
name: string;
|
|
34
|
+
min: number;
|
|
35
|
+
max: number;
|
|
36
|
+
kind: "invalid-collection-bounds";
|
|
37
|
+
location: BuilderErrorLocation;
|
|
38
|
+
};
|
|
39
|
+
invalidPath(reason: BuilderErrorInvalidPathReason): {
|
|
40
|
+
reason: BuilderErrorInvalidPathReason;
|
|
41
|
+
kind: "invalid-path";
|
|
42
|
+
location: BuilderErrorLocation;
|
|
43
|
+
};
|
|
44
|
+
invalidSelectMapKey(key: string): {
|
|
45
|
+
key: string;
|
|
46
|
+
kind: "invalid-select-map-key";
|
|
47
|
+
location: BuilderErrorLocation;
|
|
48
|
+
};
|
|
49
|
+
unboundParameter(name: string): {
|
|
50
|
+
name: string;
|
|
51
|
+
kind: "unbound-parameter";
|
|
52
|
+
location: BuilderErrorLocation;
|
|
53
|
+
};
|
|
54
|
+
missingReference(id: string): {
|
|
55
|
+
id: string;
|
|
56
|
+
kind: "missing-reference";
|
|
57
|
+
location: BuilderErrorLocation;
|
|
58
|
+
};
|
|
59
|
+
unmetExpectation(expectationKind: BuilderExpectationKind, name: string): {
|
|
60
|
+
expectationKind: "option" | "component" | "collection";
|
|
61
|
+
name: string;
|
|
62
|
+
kind: "unmet-expectation";
|
|
63
|
+
location: BuilderErrorLocation;
|
|
64
|
+
};
|
|
65
|
+
unvalidated(value: unknown): {
|
|
66
|
+
value: unknown;
|
|
67
|
+
kind: "unvalidated";
|
|
68
|
+
location: BuilderErrorLocation;
|
|
69
|
+
};
|
|
70
|
+
missingComponent(component: string): {
|
|
71
|
+
component: string;
|
|
72
|
+
kind: "missing-component";
|
|
73
|
+
location: BuilderErrorLocation;
|
|
74
|
+
};
|
|
75
|
+
unexpectedComponent(component: string): {
|
|
76
|
+
component: string;
|
|
77
|
+
kind: "unexpected-component";
|
|
78
|
+
location: BuilderErrorLocation;
|
|
79
|
+
};
|
|
80
|
+
missingVariant(component: string, instance: BuilderInstance): {
|
|
81
|
+
component: string;
|
|
82
|
+
instance: BuilderInstance;
|
|
83
|
+
kind: "missing-variant";
|
|
84
|
+
location: BuilderErrorLocation;
|
|
85
|
+
};
|
|
86
|
+
invalidVariant(component: string, instance: BuilderInstance): {
|
|
87
|
+
component: string;
|
|
88
|
+
instance: BuilderInstance;
|
|
89
|
+
kind: "invalid-variant";
|
|
90
|
+
location: BuilderErrorLocation;
|
|
91
|
+
};
|
|
92
|
+
missingDetail(component: string, detail: string, instance: BuilderInstance): {
|
|
93
|
+
component: string;
|
|
94
|
+
detail: string;
|
|
95
|
+
instance: BuilderInstance;
|
|
96
|
+
kind: "missing-detail";
|
|
97
|
+
location: BuilderErrorLocation;
|
|
98
|
+
};
|
|
99
|
+
unexpectedDetail(component: string, detail: string, instance: BuilderInstance): {
|
|
100
|
+
component: string;
|
|
101
|
+
detail: string;
|
|
102
|
+
instance: BuilderInstance;
|
|
103
|
+
kind: "unexpected-detail";
|
|
104
|
+
location: BuilderErrorLocation;
|
|
105
|
+
};
|
|
106
|
+
invalidDetail(component: string, detail: string, instance: BuilderInstance): {
|
|
107
|
+
component: string;
|
|
108
|
+
detail: string;
|
|
109
|
+
instance: BuilderInstance;
|
|
110
|
+
kind: "invalid-detail";
|
|
111
|
+
location: BuilderErrorLocation;
|
|
112
|
+
};
|
|
113
|
+
invalidPricing(reason: BuilderErrorInvalidPricingReason, detail?: string): {
|
|
114
|
+
reason: BuilderErrorInvalidPricingReason;
|
|
115
|
+
detail: string | undefined;
|
|
116
|
+
kind: "invalid-pricing";
|
|
117
|
+
location: BuilderErrorLocation;
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
export type BuilderErrorInvalidInput = ReturnType<BuilderValidateErrors['invalidInput']>;
|
|
121
|
+
export type BuilderErrorInvalidOption = ReturnType<BuilderValidateErrors['invalidOption']>;
|
|
122
|
+
export type BuilderErrorInvalidCollection = ReturnType<BuilderValidateErrors['invalidCollection']>;
|
|
123
|
+
export type BuilderErrorDuplicateName = ReturnType<BuilderValidateErrors['duplicateName']>;
|
|
124
|
+
export type BuilderErrorInvalidCollectionBounds = ReturnType<BuilderValidateErrors['invalidCollectionBounds']>;
|
|
125
|
+
export type BuilderErrorInvalidPath = ReturnType<BuilderValidateErrors['invalidPath']>;
|
|
126
|
+
export type BuilderErrorInvalidSelectMapKey = ReturnType<BuilderValidateErrors['invalidSelectMapKey']>;
|
|
127
|
+
export type BuilderErrorUnboundParameter = ReturnType<BuilderValidateErrors['unboundParameter']>;
|
|
128
|
+
export type BuilderErrorMissingReference = ReturnType<BuilderValidateErrors['missingReference']>;
|
|
129
|
+
export type BuilderErrorUnmetExpectation = ReturnType<BuilderValidateErrors['unmetExpectation']>;
|
|
130
|
+
export type BuilderErrorUnvalidated = ReturnType<BuilderValidateErrors['unvalidated']>;
|
|
131
|
+
export type BuilderErrorMissingComponent = ReturnType<BuilderValidateErrors['missingComponent']>;
|
|
132
|
+
export type BuilderErrorUnexpectedComponent = ReturnType<BuilderValidateErrors['unexpectedComponent']>;
|
|
133
|
+
export type BuilderErrorMissingVariant = ReturnType<BuilderValidateErrors['missingVariant']>;
|
|
134
|
+
export type BuilderErrorInvalidVariant = ReturnType<BuilderValidateErrors['invalidVariant']>;
|
|
135
|
+
export type BuilderErrorMissingDetail = ReturnType<BuilderValidateErrors['missingDetail']>;
|
|
136
|
+
export type BuilderErrorUnexpectedDetail = ReturnType<BuilderValidateErrors['unexpectedDetail']>;
|
|
137
|
+
export type BuilderErrorInvalidDetail = ReturnType<BuilderValidateErrors['invalidDetail']>;
|
|
138
|
+
export type BuilderErrorInvalidPricing = ReturnType<BuilderValidateErrors['invalidPricing']>;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { builderError } from '../exception.js';
|
|
2
|
+
export class BuilderValidateErrors {
|
|
3
|
+
#errors = [];
|
|
4
|
+
#location = [];
|
|
5
|
+
get errors() {
|
|
6
|
+
return this.#errors;
|
|
7
|
+
}
|
|
8
|
+
scope(part, fn) {
|
|
9
|
+
this.#location = [...this.#location, part];
|
|
10
|
+
try {
|
|
11
|
+
return fn();
|
|
12
|
+
}
|
|
13
|
+
finally {
|
|
14
|
+
this.#location = this.#location.slice(0, -1);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
invalidInput(target) {
|
|
18
|
+
return this.#addError({
|
|
19
|
+
...builderError('invalid-input', this.#location),
|
|
20
|
+
target
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
invalidOption(name, value) {
|
|
24
|
+
return this.#addError({
|
|
25
|
+
...builderError('invalid-option', this.#location),
|
|
26
|
+
name,
|
|
27
|
+
value
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
invalidCollection(name) {
|
|
31
|
+
return this.#addError({
|
|
32
|
+
...builderError('invalid-collection', this.#location),
|
|
33
|
+
name
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
duplicateName(name) {
|
|
37
|
+
return this.#addError({
|
|
38
|
+
...builderError('duplicate-name', this.#location),
|
|
39
|
+
name
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
invalidCollectionBounds(name, min, max) {
|
|
43
|
+
return this.#addError({
|
|
44
|
+
...builderError('invalid-collection-bounds', this.#location),
|
|
45
|
+
name,
|
|
46
|
+
min,
|
|
47
|
+
max
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
invalidPath(reason) {
|
|
51
|
+
return this.#addError({
|
|
52
|
+
...builderError('invalid-path', this.#location),
|
|
53
|
+
reason
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
invalidSelectMapKey(key) {
|
|
57
|
+
return this.#addError({
|
|
58
|
+
...builderError('invalid-select-map-key', this.#location),
|
|
59
|
+
key
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
unboundParameter(name) {
|
|
63
|
+
return this.#addError({
|
|
64
|
+
...builderError('unbound-parameter', this.#location),
|
|
65
|
+
name
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
missingReference(id) {
|
|
69
|
+
return this.#addError({
|
|
70
|
+
...builderError('missing-reference', this.#location),
|
|
71
|
+
id
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
unmetExpectation(expectationKind, name) {
|
|
75
|
+
return this.#addError({
|
|
76
|
+
...builderError('unmet-expectation', this.#location),
|
|
77
|
+
expectationKind,
|
|
78
|
+
name
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
unvalidated(value) {
|
|
82
|
+
return this.#addError({
|
|
83
|
+
...builderError('unvalidated', this.#location),
|
|
84
|
+
value
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
missingComponent(component) {
|
|
88
|
+
return this.#addError({
|
|
89
|
+
...builderError('missing-component', this.#location),
|
|
90
|
+
component
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
unexpectedComponent(component) {
|
|
94
|
+
return this.#addError({
|
|
95
|
+
...builderError('unexpected-component', this.#location),
|
|
96
|
+
component
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
missingVariant(component, instance) {
|
|
100
|
+
return this.#addError({
|
|
101
|
+
...builderError('missing-variant', this.#location),
|
|
102
|
+
component,
|
|
103
|
+
instance
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
invalidVariant(component, instance) {
|
|
107
|
+
return this.#addError({
|
|
108
|
+
...builderError('invalid-variant', this.#location),
|
|
109
|
+
component,
|
|
110
|
+
instance
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
missingDetail(component, detail, instance) {
|
|
114
|
+
return this.#addError({
|
|
115
|
+
...builderError('missing-detail', this.#location),
|
|
116
|
+
component,
|
|
117
|
+
detail,
|
|
118
|
+
instance
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
unexpectedDetail(component, detail, instance) {
|
|
122
|
+
return this.#addError({
|
|
123
|
+
...builderError('unexpected-detail', this.#location),
|
|
124
|
+
component,
|
|
125
|
+
detail,
|
|
126
|
+
instance
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
invalidDetail(component, detail, instance) {
|
|
130
|
+
return this.#addError({
|
|
131
|
+
...builderError('invalid-detail', this.#location),
|
|
132
|
+
component,
|
|
133
|
+
detail,
|
|
134
|
+
instance
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
invalidPricing(reason, detail) {
|
|
138
|
+
return this.#addError({
|
|
139
|
+
...builderError('invalid-pricing', this.#location),
|
|
140
|
+
reason,
|
|
141
|
+
detail
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
#addError(error) {
|
|
145
|
+
this.#errors = [...this.#errors, error];
|
|
146
|
+
return error;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
export declare function
|
|
4
|
-
expectationKind: "option" | "component" | "collection";
|
|
5
|
-
name: string;
|
|
6
|
-
kind: "unmet-expectation";
|
|
7
|
-
location: BuilderErrorLocation;
|
|
8
|
-
};
|
|
9
|
-
export type BuilderErrorUnmetExpectation = ReturnType<typeof builderErrorUnmetExpectation>;
|
|
10
|
-
export declare function checkExpectations(model: BuilderModelSerialised, expectations: BuilderExpectationsSerialised, location: BuilderErrorLocation): BuilderErrors;
|
|
1
|
+
import type { BuilderExpectationsSerialised, BuilderModelSerialised } from '../entities/index';
|
|
2
|
+
import type { BuilderValidateErrors } from './errors';
|
|
3
|
+
export declare function checkExpectations(model: BuilderModelSerialised, expectations: BuilderExpectationsSerialised, errors: BuilderValidateErrors): void;
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
return [builderErrorUnmetExpectation(kind, name, [...location, index])];
|
|
1
|
+
export function checkExpectations(model, expectations, errors) {
|
|
2
|
+
expectations.forEach(({ kind, name }, index) => {
|
|
3
|
+
errors.scope(index, () => {
|
|
4
|
+
if (model[`${kind}s`].some((entry) => entry.name === name)) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
errors.unmetExpectation(kind, name);
|
|
8
|
+
});
|
|
11
9
|
});
|
|
12
10
|
}
|
package/dist/validate/index.d.ts
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
export type { BuilderErrorUnvalidated } from './brand';
|
|
2
1
|
export type { BuilderValidationResult } from './builder';
|
|
3
|
-
export type { BuilderErrorUnmetExpectation } from './
|
|
4
|
-
export type {
|
|
5
|
-
export type {
|
|
6
|
-
export type {
|
|
7
|
-
export type { BuilderErrorInvalidInput } from './result';
|
|
2
|
+
export type { BuilderErrorDuplicateName, BuilderErrorInvalidCollection, BuilderErrorInvalidCollectionBounds, BuilderErrorInvalidDetail, BuilderErrorInvalidInput, BuilderErrorInvalidOption, BuilderErrorInvalidPath, BuilderErrorInvalidPathReason, BuilderErrorInvalidPricing, BuilderErrorInvalidPricingReason, BuilderErrorInvalidSelectMapKey, BuilderErrorInvalidVariant, BuilderErrorMissingComponent, BuilderErrorMissingDetail, BuilderErrorMissingReference, BuilderErrorMissingVariant, BuilderErrorUnboundParameter, BuilderErrorUnexpectedComponent, BuilderErrorUnexpectedDetail, BuilderErrorUnmetExpectation, BuilderErrorUnvalidated, BuilderInvalidInputTarget } from './errors';
|
|
3
|
+
export type { BuilderInstanceValidationResult } from './instance';
|
|
4
|
+
export type { BuilderModelValidationResult } from './model';
|
|
5
|
+
export type { BuilderPricingValidationResult } from './pricing';
|
|
8
6
|
export type { BuilderUIValidationResult } from './ui';
|
|
9
|
-
export type { BuilderComponentVariantsValidationResult,
|
|
10
|
-
export { assertValidated
|
|
7
|
+
export type { BuilderComponentVariantsValidationResult, BuilderVariantsValidationOptions } from './variants';
|
|
8
|
+
export { assertValidated } from './brand.js';
|
|
11
9
|
export { validateBuilder } from './builder.js';
|
|
12
|
-
export {
|
|
13
|
-
export {
|
|
14
|
-
export {
|
|
15
|
-
export { builderErrorMissingReference, builderErrorUnboundParameter } from './resolve.js';
|
|
16
|
-
export { builderErrorInvalidInput } from './result.js';
|
|
10
|
+
export { validateInstance } from './instance.js';
|
|
11
|
+
export { validateModel } from './model.js';
|
|
12
|
+
export { validatePricing } from './pricing.js';
|
|
17
13
|
export { validateUI } from './ui.js';
|
|
18
|
-
export {
|
|
14
|
+
export { validateVariants } from './variants.js';
|
package/dist/validate/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
export { assertValidated
|
|
1
|
+
export { assertValidated } from './brand.js';
|
|
2
2
|
export { validateBuilder } from './builder.js';
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
6
|
-
export { builderErrorMissingReference, builderErrorUnboundParameter } from './resolve.js';
|
|
7
|
-
export { builderErrorInvalidInput } from './result.js';
|
|
3
|
+
export { validateInstance } from './instance.js';
|
|
4
|
+
export { validateModel } from './model.js';
|
|
5
|
+
export { validatePricing } from './pricing.js';
|
|
8
6
|
export { validateUI } from './ui.js';
|
|
9
|
-
export {
|
|
7
|
+
export { validateVariants } from './variants.js';
|
|
@@ -1,19 +1,6 @@
|
|
|
1
1
|
import type { BuilderInstanceValidated, BuilderModelValidated } from '../entities/index';
|
|
2
|
-
import type { BuilderErrorLocation } from '../exception';
|
|
3
2
|
import type { BuilderInstance } from '../instance';
|
|
4
3
|
import type { ValidationResult } from './result';
|
|
5
|
-
|
|
6
|
-
name: string;
|
|
7
|
-
value: unknown;
|
|
8
|
-
kind: "invalid-option";
|
|
9
|
-
location: BuilderErrorLocation;
|
|
10
|
-
};
|
|
11
|
-
export type BuilderErrorInvalidOption = ReturnType<typeof builderErrorInvalidOption>;
|
|
12
|
-
export declare function builderErrorInvalidCollection(name: string, location?: BuilderErrorLocation): {
|
|
13
|
-
name: string;
|
|
14
|
-
kind: "invalid-collection";
|
|
15
|
-
location: BuilderErrorLocation;
|
|
16
|
-
};
|
|
17
|
-
export type BuilderErrorInvalidCollection = ReturnType<typeof builderErrorInvalidCollection>;
|
|
4
|
+
import { BuilderValidateErrors } from './errors.js';
|
|
18
5
|
export type BuilderInstanceValidationResult = ValidationResult<BuilderInstanceValidated>;
|
|
19
|
-
export declare function validateInstance(model: BuilderModelValidated, instance: BuilderInstance): BuilderInstanceValidationResult;
|
|
6
|
+
export declare function validateInstance(model: BuilderModelValidated, instance: BuilderInstance, errors?: BuilderValidateErrors): BuilderInstanceValidationResult;
|
|
@@ -1,47 +1,48 @@
|
|
|
1
1
|
import { check } from '../check.js';
|
|
2
2
|
import { optionValueSchema } from '../entities/index.js';
|
|
3
|
-
import { builderError } from '../exception.js';
|
|
4
3
|
import { BuilderInstancesSchema } from '../instance.js';
|
|
5
4
|
import { resolveCollection, resolveOption } from '../mappers/index.js';
|
|
6
5
|
import { validate } from './brand.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return { ...builderError('invalid-collection', location), name };
|
|
12
|
-
}
|
|
13
|
-
export function validateInstance(model, instance) {
|
|
14
|
-
const errors = checkInstance(model, instance, ['instance']);
|
|
15
|
-
return [validate(instance), errors];
|
|
16
|
-
}
|
|
17
|
-
function checkInstance(model, instance, location) {
|
|
18
|
-
const { options, collections } = model;
|
|
19
|
-
const optionErrors = options.flatMap((option) => {
|
|
20
|
-
const { name } = option;
|
|
21
|
-
const payload = resolveOption(option, model, instance);
|
|
22
|
-
if (!payload) {
|
|
23
|
-
return [];
|
|
24
|
-
}
|
|
25
|
-
const value = instance[name];
|
|
26
|
-
if (!check.is(optionValueSchema(payload), value)) {
|
|
27
|
-
return [builderErrorInvalidOption(name, value, [...location, name])];
|
|
28
|
-
}
|
|
29
|
-
return [];
|
|
30
|
-
});
|
|
31
|
-
const collectionErrors = collections.flatMap((collection) => {
|
|
32
|
-
const { name } = collection;
|
|
33
|
-
const payload = resolveCollection(collection, model, instance);
|
|
34
|
-
if (!payload) {
|
|
35
|
-
return [];
|
|
36
|
-
}
|
|
37
|
-
const existing = instance[name];
|
|
38
|
-
if (!check.is(BuilderInstancesSchema, existing)) {
|
|
39
|
-
return [builderErrorInvalidCollection(name, [...location, name])];
|
|
40
|
-
}
|
|
41
|
-
return existing.flatMap((itemInstance, index) => checkInstance(payload.model, itemInstance, [...location, name, index]).map((error) => ({
|
|
42
|
-
...error,
|
|
43
|
-
name: `${name}[${index}].${error.name}`
|
|
44
|
-
})));
|
|
6
|
+
import { BuilderValidateErrors } from './errors.js';
|
|
7
|
+
export function validateInstance(model, instance, errors = new BuilderValidateErrors()) {
|
|
8
|
+
errors.scope('instance', () => {
|
|
9
|
+
checkInstance(model, instance);
|
|
45
10
|
});
|
|
46
|
-
return [
|
|
11
|
+
return [validate(instance), errors.errors];
|
|
12
|
+
function checkInstance(scopeModel, scopeInstance, namePrefix = '') {
|
|
13
|
+
scopeModel.options.forEach((option) => {
|
|
14
|
+
const { name } = option;
|
|
15
|
+
const payload = resolveOption(option, scopeModel, scopeInstance);
|
|
16
|
+
if (!payload) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const value = scopeInstance[name];
|
|
20
|
+
if (!check.is(optionValueSchema(payload), value)) {
|
|
21
|
+
errors.scope(name, () => {
|
|
22
|
+
errors.invalidOption(`${namePrefix}${name}`, value);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
scopeModel.collections.forEach((collection) => {
|
|
27
|
+
const { name } = collection;
|
|
28
|
+
const payload = resolveCollection(collection, scopeModel, scopeInstance);
|
|
29
|
+
if (!payload) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const existing = scopeInstance[name];
|
|
33
|
+
if (!check.is(BuilderInstancesSchema, existing)) {
|
|
34
|
+
errors.scope(name, () => {
|
|
35
|
+
errors.invalidCollection(`${namePrefix}${name}`);
|
|
36
|
+
});
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
errors.scope(name, () => {
|
|
40
|
+
existing.forEach((itemInstance, index) => {
|
|
41
|
+
errors.scope(index, () => {
|
|
42
|
+
checkInstance(payload.model, itemInstance, `${namePrefix}${name}[${index}].`);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
47
48
|
}
|
package/dist/validate/model.d.ts
CHANGED
|
@@ -1,36 +1,9 @@
|
|
|
1
1
|
import type { BuilderModelSerialised, BuilderModelValidated, BuilderRefEntities } from '../entities/index';
|
|
2
|
-
import type { BuilderErrorLocation, BuilderErrors } from '../exception';
|
|
3
2
|
import type { ParamableSerialised } from '../references';
|
|
4
3
|
import type { BuilderResolve } from './resolve';
|
|
5
4
|
import type { ValidationResult } from './result';
|
|
5
|
+
import { BuilderValidateErrors } from './errors.js';
|
|
6
6
|
export type BuilderModelValidationResult = ValidationResult<BuilderModelValidated>;
|
|
7
|
-
export declare function
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
location: BuilderErrorLocation;
|
|
11
|
-
};
|
|
12
|
-
export type BuilderErrorDuplicateName = ReturnType<typeof builderErrorDuplicateName>;
|
|
13
|
-
export declare function builderErrorInvalidCollectionBounds(name: string, min: number, max: number, location?: BuilderErrorLocation): {
|
|
14
|
-
name: string;
|
|
15
|
-
min: number;
|
|
16
|
-
max: number;
|
|
17
|
-
kind: "invalid-collection-bounds";
|
|
18
|
-
location: BuilderErrorLocation;
|
|
19
|
-
};
|
|
20
|
-
export type BuilderErrorInvalidCollectionBounds = ReturnType<typeof builderErrorInvalidCollectionBounds>;
|
|
21
|
-
export type BuilderErrorInvalidPathReason = 'shape' | 'out-of-bounds' | 'missing-collection' | 'option-not-found';
|
|
22
|
-
export declare function builderErrorInvalidPath(reason: BuilderErrorInvalidPathReason, location?: BuilderErrorLocation): {
|
|
23
|
-
reason: BuilderErrorInvalidPathReason;
|
|
24
|
-
kind: "invalid-path";
|
|
25
|
-
location: BuilderErrorLocation;
|
|
26
|
-
};
|
|
27
|
-
export type BuilderErrorInvalidPath = ReturnType<typeof builderErrorInvalidPath>;
|
|
28
|
-
export declare function builderErrorInvalidSelectMapKey(key: string, location?: BuilderErrorLocation): {
|
|
29
|
-
key: string;
|
|
30
|
-
kind: "invalid-select-map-key";
|
|
31
|
-
location: BuilderErrorLocation;
|
|
32
|
-
};
|
|
33
|
-
export type BuilderErrorInvalidSelectMapKey = ReturnType<typeof builderErrorInvalidSelectMapKey>;
|
|
34
|
-
export declare function validateModel(input: unknown, references?: BuilderRefEntities): BuilderModelValidationResult;
|
|
35
|
-
export declare function checkModelExpectations(mergedModel: BuilderModelSerialised, model: BuilderModelSerialised, location: BuilderErrorLocation): BuilderErrors;
|
|
36
|
-
export declare function validateModelStructure(input: ParamableSerialised<BuilderModelSerialised>, resolve: BuilderResolve, location: BuilderErrorLocation): BuilderModelValidationResult;
|
|
7
|
+
export declare function validateModel(input: unknown, references?: BuilderRefEntities, errors?: BuilderValidateErrors): BuilderModelValidationResult;
|
|
8
|
+
export declare function checkModelExpectations(mergedModel: BuilderModelSerialised, rootModel: BuilderModelSerialised, errors: BuilderValidateErrors): void;
|
|
9
|
+
export declare function validateModelStructure(input: ParamableSerialised<BuilderModelSerialised>, resolve: BuilderResolve, errors: BuilderValidateErrors): BuilderModelValidated;
|