@builder-builder/builder 0.0.17 → 0.0.19
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/mappers/index.d.ts +1 -1
- package/dist/mappers/index.js +1 -1
- package/dist/mappers/resolve.d.ts +4 -1
- package/dist/mappers/resolve.js +31 -12
- package/dist/validate/brand.js +3 -12
- package/dist/validate/model.js +3 -2
- package/dist/validate/paths.d.ts +1 -2
- package/dist/validate/paths.js +3 -20
- package/dist/validate/ui.js +3 -2
- package/dist/validate/variants.js +14 -3
- package/package.json +1 -1
package/dist/mappers/index.d.ts
CHANGED
|
@@ -8,4 +8,4 @@ export { createVariants, optionGraph, variantsFor } from './variants/index.js';
|
|
|
8
8
|
export { order } from './order.js';
|
|
9
9
|
export { price } from './price.js';
|
|
10
10
|
export { ordinal, render } from './render/index.js';
|
|
11
|
-
export { resolveCollection, resolveComponent, resolveOption } from './resolve.js';
|
|
11
|
+
export { resolveCollection, resolveCollections, resolveComponent, resolveComponents, resolveOption, resolveOptions } from './resolve.js';
|
package/dist/mappers/index.js
CHANGED
|
@@ -4,4 +4,4 @@ export { createVariants, optionGraph, variantsFor } from './variants/index.js';
|
|
|
4
4
|
export { order } from './order.js';
|
|
5
5
|
export { price } from './price.js';
|
|
6
6
|
export { ordinal, render } from './render/index.js';
|
|
7
|
-
export { resolveCollection, resolveComponent, resolveOption } from './resolve.js';
|
|
7
|
+
export { resolveCollection, resolveCollections, resolveComponent, resolveComponents, resolveOption, resolveOptions } from './resolve.js';
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import type { BuilderCollectionConfigValidated, BuilderCollectionValidated, BuilderComponentDetailsValidated, BuilderComponentValidated, BuilderModelValidated, BuilderOptionValidated, BuilderOptionValuesValidated, BuilderRefEntities } from '../entities/index';
|
|
1
|
+
import type { BuilderCollectionConfigSerialised, BuilderCollectionConfigValidated, BuilderCollectionSerialised, BuilderCollectionValidated, BuilderComponentDetailsSerialised, BuilderComponentDetailsValidated, BuilderComponentSerialised, BuilderComponentValidated, BuilderModelValidated, BuilderOptionSerialised, BuilderOptionValidated, BuilderOptionValuesSerialised, BuilderOptionValuesValidated, BuilderRefEntities } from '../entities/index';
|
|
2
2
|
import type { BuilderInstance } from '../instance';
|
|
3
3
|
import type { BuilderPath } from '../paths';
|
|
4
4
|
export declare function resolveOption(option: BuilderOptionValidated, model: BuilderModelValidated, instance: unknown, refs?: BuilderRefEntities): BuilderOptionValuesValidated | null;
|
|
5
|
+
export declare function resolveOptions(option: BuilderOptionSerialised, refs?: BuilderRefEntities): ReadonlyArray<BuilderOptionValuesSerialised>;
|
|
5
6
|
export declare function resolveComponent(component: BuilderComponentValidated, model: BuilderModelValidated, instance: unknown, refs?: BuilderRefEntities): BuilderComponentDetailsValidated | null;
|
|
7
|
+
export declare function resolveComponents(component: BuilderComponentSerialised, refs?: BuilderRefEntities): ReadonlyArray<BuilderComponentDetailsSerialised>;
|
|
6
8
|
export declare function resolveCollection(collection: BuilderCollectionValidated, model: BuilderModelValidated, instance: unknown, refs?: BuilderRefEntities): BuilderCollectionConfigValidated | null;
|
|
9
|
+
export declare function resolveCollections(collection: BuilderCollectionSerialised, refs?: BuilderRefEntities): ReadonlyArray<BuilderCollectionConfigSerialised>;
|
|
7
10
|
export declare function resolveRef(value: unknown, refs: BuilderRefEntities): unknown;
|
|
8
11
|
export type ResolvedPath = {
|
|
9
12
|
readonly name: string;
|
package/dist/mappers/resolve.js
CHANGED
|
@@ -6,13 +6,22 @@ import { BuilderPathsSchema } from '../paths.js';
|
|
|
6
6
|
import { BuilderPrimitiveSchema } from '../primitive.js';
|
|
7
7
|
import { BuilderRefSerialisedSchema } from '../references.js';
|
|
8
8
|
export function resolveOption(option, model, instance, refs = []) {
|
|
9
|
-
return
|
|
9
|
+
return resolveEntryInstance(option, BuilderOptionValuesSerialisedSchema, model, instance, refs);
|
|
10
|
+
}
|
|
11
|
+
export function resolveOptions(option, refs = []) {
|
|
12
|
+
return resolveEntryExhaustive(option, BuilderOptionValuesSerialisedSchema, refs);
|
|
10
13
|
}
|
|
11
14
|
export function resolveComponent(component, model, instance, refs = []) {
|
|
12
|
-
return
|
|
15
|
+
return resolveEntryInstance(component, BuilderComponentDetailsSerialisedSchema, model, instance, refs);
|
|
16
|
+
}
|
|
17
|
+
export function resolveComponents(component, refs = []) {
|
|
18
|
+
return resolveEntryExhaustive(component, BuilderComponentDetailsSerialisedSchema, refs);
|
|
13
19
|
}
|
|
14
20
|
export function resolveCollection(collection, model, instance, refs = []) {
|
|
15
|
-
return
|
|
21
|
+
return resolveEntryInstance(collection, BuilderCollectionConfigSerialisedSchema, model, instance, refs);
|
|
22
|
+
}
|
|
23
|
+
export function resolveCollections(collection, refs = []) {
|
|
24
|
+
return resolveEntryExhaustive(collection, BuilderCollectionConfigSerialisedSchema, refs);
|
|
16
25
|
}
|
|
17
26
|
export function resolveRef(value, refs) {
|
|
18
27
|
if (!check.is(BuilderRefSerialisedSchema, value)) {
|
|
@@ -62,7 +71,7 @@ export function resolveItems(model, instance, pairs, refs = []) {
|
|
|
62
71
|
}
|
|
63
72
|
return resolveItems(resolved.model, item, rest, refs);
|
|
64
73
|
}
|
|
65
|
-
function
|
|
74
|
+
function resolveEntryInstance(entry, schema, model, instance, refs) {
|
|
66
75
|
const payload = resolveRef(entry.payload, refs);
|
|
67
76
|
if (check.is(schema, payload)) {
|
|
68
77
|
return payload;
|
|
@@ -70,7 +79,7 @@ function resolveEntry(entry, schema, model, instance, refs = []) {
|
|
|
70
79
|
check.assert(BuilderWhenSerialisedSchema, payload);
|
|
71
80
|
check.assert(BuilderPathsSchema, entry.paths);
|
|
72
81
|
const config = payload;
|
|
73
|
-
if (!entry.paths.every((path) =>
|
|
82
|
+
if (!entry.paths.every((path) => Boolean(resolvePath(model, instance, path, refs)?.value))) {
|
|
74
83
|
return null;
|
|
75
84
|
}
|
|
76
85
|
switch (config.type) {
|
|
@@ -84,7 +93,7 @@ function resolveEntry(entry, schema, model, instance, refs = []) {
|
|
|
84
93
|
}
|
|
85
94
|
case 'unless': {
|
|
86
95
|
const value = resolvePath(model, instance, config.unlessPath, refs)?.value;
|
|
87
|
-
if (!
|
|
96
|
+
if (!value) {
|
|
88
97
|
return null;
|
|
89
98
|
}
|
|
90
99
|
check.assert(BuilderPrimitiveSchema, value);
|
|
@@ -95,12 +104,22 @@ function resolveEntry(entry, schema, model, instance, refs = []) {
|
|
|
95
104
|
}
|
|
96
105
|
}
|
|
97
106
|
}
|
|
98
|
-
function
|
|
99
|
-
|
|
100
|
-
|
|
107
|
+
function resolveEntryExhaustive(entry, schema, refs) {
|
|
108
|
+
const payload = resolveRef(entry.payload, refs);
|
|
109
|
+
if (check.is(schema, payload)) {
|
|
110
|
+
return [payload];
|
|
101
111
|
}
|
|
102
|
-
if (
|
|
103
|
-
return
|
|
112
|
+
if (!check.is(BuilderWhenSerialisedSchema, payload)) {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
const when = payload;
|
|
116
|
+
switch (when.type) {
|
|
117
|
+
case 'enable':
|
|
118
|
+
case 'unless': {
|
|
119
|
+
return [when.payload];
|
|
120
|
+
}
|
|
121
|
+
case 'match': {
|
|
122
|
+
return Object.values(when.selectMap).filter((branch) => branch != null);
|
|
123
|
+
}
|
|
104
124
|
}
|
|
105
|
-
return true;
|
|
106
125
|
}
|
package/dist/validate/brand.js
CHANGED
|
@@ -1,21 +1,12 @@
|
|
|
1
1
|
import { BuilderException } from '../exception.js';
|
|
2
2
|
import { BuilderValidateErrors } from './errors.js';
|
|
3
|
-
const
|
|
3
|
+
const VALIDATED_ENTITIES = new WeakSet();
|
|
4
4
|
export function validate(value) {
|
|
5
|
-
|
|
6
|
-
// rejects any property that isn't writable, configurable, and enumerable.
|
|
7
|
-
// Symbol keys are skipped by `JSON.stringify` regardless of enumerability,
|
|
8
|
-
// so the brand never leaks through a serialise round-trip.
|
|
9
|
-
Object.defineProperty(value, VALIDATED, {
|
|
10
|
-
value: true,
|
|
11
|
-
writable: true,
|
|
12
|
-
enumerable: true,
|
|
13
|
-
configurable: true
|
|
14
|
-
});
|
|
5
|
+
VALIDATED_ENTITIES.add(value);
|
|
15
6
|
return value;
|
|
16
7
|
}
|
|
17
8
|
export function assertValidated(value) {
|
|
18
|
-
if (typeof value !== 'object' || value === null || !(
|
|
9
|
+
if (typeof value !== 'object' || value === null || !VALIDATED_ENTITIES.has(value)) {
|
|
19
10
|
const errors = new BuilderValidateErrors();
|
|
20
11
|
errors.unvalidated(value);
|
|
21
12
|
throw new BuilderException(errors.errors);
|
package/dist/validate/model.js
CHANGED
|
@@ -2,8 +2,9 @@ import { check } from '../check.js';
|
|
|
2
2
|
import { BuilderModelSerialisedSchema, BuilderWhenSerialisedSchema, model, modelsMerge, serialise } from '../entities/index.js';
|
|
3
3
|
import { validate } from './brand.js';
|
|
4
4
|
import { BuilderValidateErrors } from './errors.js';
|
|
5
|
+
import { resolveCollections } from '../mappers/index.js';
|
|
5
6
|
import { checkExpectations } from './expectations.js';
|
|
6
|
-
import { checkPath
|
|
7
|
+
import { checkPath } from './paths.js';
|
|
7
8
|
import { resolver } from './resolve.js';
|
|
8
9
|
const EMPTY_MODEL = validate(serialise.model(model()));
|
|
9
10
|
export function validateModel(input, references = [], errors = new BuilderValidateErrors()) {
|
|
@@ -135,7 +136,7 @@ export function validateModelStructure(input, resolve, errors) {
|
|
|
135
136
|
}
|
|
136
137
|
}
|
|
137
138
|
function checkCollectionBounds(collection) {
|
|
138
|
-
|
|
139
|
+
resolveCollections(collection).forEach(({ min, max }) => {
|
|
139
140
|
if (typeof min !== 'number' || typeof max !== 'number') {
|
|
140
141
|
return;
|
|
141
142
|
}
|
package/dist/validate/paths.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BuilderModelSerialised } from '../entities/index';
|
|
2
2
|
import type { BuilderPath } from '../paths';
|
|
3
3
|
import type { BuilderValidateErrors } from './errors';
|
|
4
4
|
export declare function checkPath(model: BuilderModelSerialised, path: BuilderPath, errors: BuilderValidateErrors): void;
|
|
5
|
-
export declare function collectionConfigs(collection: BuilderCollectionSerialised): ReadonlyArray<BuilderCollectionConfigSerialised>;
|
package/dist/validate/paths.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as v from 'valibot';
|
|
2
2
|
import { check } from '../check.js';
|
|
3
|
-
import {
|
|
3
|
+
import { BuilderModelSerialisedSchema } from '../entities/index.js';
|
|
4
|
+
import { resolveCollections } from '../mappers/index.js';
|
|
4
5
|
const NumberSchema = v.number();
|
|
5
6
|
const StringSchema = v.string();
|
|
6
7
|
export function checkPath(model, path, errors) {
|
|
@@ -17,24 +18,6 @@ export function checkPath(model, path, errors) {
|
|
|
17
18
|
errors.invalidPath('option-not-found');
|
|
18
19
|
}
|
|
19
20
|
}
|
|
20
|
-
export function collectionConfigs(collection) {
|
|
21
|
-
const { payload } = collection;
|
|
22
|
-
if (check.is(BuilderCollectionConfigSerialisedSchema, payload)) {
|
|
23
|
-
return [payload];
|
|
24
|
-
}
|
|
25
|
-
if (!check.is(BuilderWhenSerialisedSchema, payload)) {
|
|
26
|
-
return [];
|
|
27
|
-
}
|
|
28
|
-
if (payload.type === 'match') {
|
|
29
|
-
if (!check.is(BuilderCollectionSelectMapSerialisedSchema, payload.selectMap)) {
|
|
30
|
-
return [];
|
|
31
|
-
}
|
|
32
|
-
return Object.values(payload.selectMap).flatMap((value) => check.is(BuilderCollectionConfigSerialisedSchema, value) ? [value] : []);
|
|
33
|
-
}
|
|
34
|
-
return check.is(BuilderCollectionConfigSerialisedSchema, payload.payload)
|
|
35
|
-
? [payload.payload]
|
|
36
|
-
: [];
|
|
37
|
-
}
|
|
38
21
|
function walkPath(candidates, remaining, errors) {
|
|
39
22
|
if (remaining.length === 0) {
|
|
40
23
|
return candidates;
|
|
@@ -46,7 +29,7 @@ function walkPath(candidates, remaining, errors) {
|
|
|
46
29
|
}
|
|
47
30
|
const matchedConfigs = candidates.flatMap((current) => {
|
|
48
31
|
const collection = current.collections.find((entry) => entry.name === collectionName);
|
|
49
|
-
return collection == null ? [] : [
|
|
32
|
+
return collection == null ? [] : [resolveCollections(collection)];
|
|
50
33
|
});
|
|
51
34
|
if (matchedConfigs.length === 0) {
|
|
52
35
|
errors.invalidPath('missing-collection');
|
package/dist/validate/ui.js
CHANGED
|
@@ -2,8 +2,9 @@ import { check } from '../check.js';
|
|
|
2
2
|
import { BuilderModelSerialisedSchema, BuilderUIInputMetadataSchema, BuilderUISerialisedSchema, modelsMerge, serialise, uis } from '../entities/index.js';
|
|
3
3
|
import { validate } from './brand.js';
|
|
4
4
|
import { BuilderValidateErrors } from './errors.js';
|
|
5
|
+
import { resolveCollections } from '../mappers/index.js';
|
|
5
6
|
import { checkExpectations } from './expectations.js';
|
|
6
|
-
import { checkPath
|
|
7
|
+
import { checkPath } from './paths.js';
|
|
7
8
|
import { resolver } from './resolve.js';
|
|
8
9
|
export function validateUI(input, references = [], errors = new BuilderValidateErrors()) {
|
|
9
10
|
if (!check.is(BuilderUISerialisedSchema, input)) {
|
|
@@ -118,7 +119,7 @@ export function checkUIExpectations(mergedModel, ui, errors) {
|
|
|
118
119
|
if (collection == null) {
|
|
119
120
|
return;
|
|
120
121
|
}
|
|
121
|
-
const innerModels =
|
|
122
|
+
const innerModels = resolveCollections(collection).flatMap(({ model: configModel }) => check.is(BuilderModelSerialisedSchema, configModel) ? [configModel] : []);
|
|
122
123
|
innerModels.forEach((innerModel) => {
|
|
123
124
|
const mergedInnerModel = modelsMerge(innerModel);
|
|
124
125
|
errors.scope('items', () => walkItems(mergedInnerModel, pages.items));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { check } from '../check.js';
|
|
2
|
-
import { detailValueSchema } from '../entities/index.js';
|
|
2
|
+
import { BuilderComponentDetailsSerialisedSchema, detailValueSchema } from '../entities/index.js';
|
|
3
3
|
import { BuilderComponentVariantsSchema } from '../instance.js';
|
|
4
|
-
import { createVariants
|
|
4
|
+
import { createVariants } from '../mappers/index.js';
|
|
5
5
|
import { validate } from './brand.js';
|
|
6
6
|
import { BuilderValidateErrors } from './errors.js';
|
|
7
7
|
export function validateVariants(model, input, options = {}, errors = new BuilderValidateErrors()) {
|
|
@@ -66,7 +66,7 @@ export function validateVariants(model, input, options = {}, errors = new Builde
|
|
|
66
66
|
}
|
|
67
67
|
componentVariants.forEach(({ instance, details = {} }, index) => {
|
|
68
68
|
errors.scope(index, () => {
|
|
69
|
-
const resolved =
|
|
69
|
+
const resolved = variantDetails(entry, instance);
|
|
70
70
|
const fields = resolved?.fields ?? [];
|
|
71
71
|
const expectedNames = new Set(fields.map(({ name }) => name));
|
|
72
72
|
errors.scope('details', () => {
|
|
@@ -97,6 +97,17 @@ export function validateVariants(model, input, options = {}, errors = new Builde
|
|
|
97
97
|
});
|
|
98
98
|
return [validate(variants), errors.errors];
|
|
99
99
|
}
|
|
100
|
+
function variantDetails(component, variantInstance) {
|
|
101
|
+
const { payload } = component;
|
|
102
|
+
if (check.is(BuilderComponentDetailsSerialisedSchema, payload)) {
|
|
103
|
+
return payload;
|
|
104
|
+
}
|
|
105
|
+
if (payload.type === 'match') {
|
|
106
|
+
const value = variantInstance[String(payload.matchPath.at(-1))];
|
|
107
|
+
return payload.selectMap[String(value)] ?? null;
|
|
108
|
+
}
|
|
109
|
+
return payload.payload;
|
|
110
|
+
}
|
|
100
111
|
function sortedKey(instance) {
|
|
101
112
|
const entries = Object.entries(instance).filter(([, value]) => value != null);
|
|
102
113
|
return JSON.stringify(entries.sort(([keyA], [keyB]) => keyA.localeCompare(keyB)));
|