@builder-builder/builder 0.0.27 → 0.0.29
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.js +9 -10
- package/dist/client/client.d.ts +2 -1
- package/dist/client/client.js +4 -1
- package/dist/client/public.d.ts +2 -2
- package/dist/client/public.js +1 -1
- package/dist/client/schema.d.ts +126 -45
- package/dist/client/schema.js +6 -1
- package/dist/components/BuilderOption.svelte.d.ts +12 -12
- package/dist/components/BuilderOptionValueBoolean.svelte.d.ts +20 -0
- package/dist/components/BuilderOptionValueNumber.svelte.d.ts +21 -0
- package/dist/components/BuilderOptionValueSelect.svelte.d.ts +21 -0
- package/dist/components/BuilderOptionValueString.svelte.d.ts +21 -0
- package/dist/components/BuilderRender.svelte.d.ts +2 -2
- package/dist/components/index.d.ts +8 -8
- package/dist/components/index.js +4376 -4258
- package/dist/components/index.min.js +3 -0
- package/dist/entities/collection/collection.d.ts +191 -401
- package/dist/entities/collection/collection.js +7 -4
- package/dist/entities/collection/{when.d.ts → condition.d.ts} +4 -5
- package/dist/entities/collection/condition.js +2 -0
- package/dist/entities/collection/config.d.ts +62 -80
- package/dist/entities/collection/index.d.ts +4 -4
- package/dist/entities/collection/index.js +2 -2
- package/dist/entities/component/component.d.ts +71 -83
- package/dist/entities/component/component.js +4 -4
- package/dist/entities/component/condition.d.ts +10 -0
- package/dist/entities/component/{when.js → condition.js} +3 -9
- package/dist/entities/component/config.d.ts +33 -33
- package/dist/entities/component/config.js +18 -16
- package/dist/entities/component/detail.d.ts +61 -0
- package/dist/entities/component/detail.js +71 -0
- package/dist/entities/component/index.d.ts +6 -6
- package/dist/entities/component/index.js +3 -3
- package/dist/entities/{when.d.ts → condition.d.ts} +23 -36
- package/dist/entities/{when.js → condition.js} +20 -25
- package/dist/entities/expectation.d.ts +135 -3
- package/dist/entities/expectation.js +6 -2
- package/dist/entities/index.d.ts +9 -9
- package/dist/entities/index.js +4 -4
- package/dist/entities/kind.d.ts +4 -4
- package/dist/entities/kind.js +24 -25
- package/dist/entities/model/bind.d.ts +5 -5
- package/dist/entities/model/methods.d.ts +18 -27
- package/dist/entities/model/methods.js +4 -22
- package/dist/entities/model/model.d.ts +3 -1
- package/dist/entities/model/model.js +25 -27
- package/dist/entities/option/condition.d.ts +9 -0
- package/dist/entities/option/condition.js +2 -0
- package/dist/entities/option/config.d.ts +47 -72
- package/dist/entities/option/config.js +6 -6
- package/dist/entities/option/expectation.d.ts +6 -1
- package/dist/entities/option/expectation.js +2 -2
- package/dist/entities/option/index.d.ts +8 -8
- package/dist/entities/option/index.js +4 -4
- package/dist/entities/option/option.d.ts +179 -210
- package/dist/entities/option/option.js +4 -4
- package/dist/entities/option/select.d.ts +16 -43
- package/dist/entities/option/select.js +8 -31
- package/dist/entities/option/value.d.ts +73 -0
- package/dist/entities/option/value.js +99 -0
- package/dist/entities/paths.d.ts +2 -2
- package/dist/entities/pricing/expression.d.ts +16 -39
- package/dist/entities/pricing/expression.js +1 -16
- package/dist/entities/pricing/index.d.ts +1 -1
- package/dist/entities/pricing/rates.d.ts +1 -1
- package/dist/entities/references.d.ts +124 -84
- package/dist/entities/serialise.d.ts +175 -109
- package/dist/entities/serialise.js +32 -27
- package/dist/entities/ui/describe.d.ts +1 -1
- package/dist/entities/ui/input.d.ts +2 -2
- package/dist/entities/ui/page.d.ts +1 -1
- package/dist/entities/ui/pages.d.ts +2 -2
- package/dist/entities/validated.d.ts +3 -3
- package/dist/environment.d.ts +2 -2
- package/dist/errors/errors.d.ts +94 -58
- package/dist/errors/errors.js +41 -7
- package/dist/errors/exception.d.ts +3 -3
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/errors/public.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/instance.d.ts +53 -9
- package/dist/instance.js +6 -2
- package/dist/mappers/dependencies.d.ts +3 -0
- package/dist/mappers/dependencies.js +45 -0
- package/dist/mappers/index.d.ts +2 -2
- package/dist/mappers/index.js +2 -1
- package/dist/mappers/instance.js +26 -21
- package/dist/mappers/price.js +6 -4
- package/dist/mappers/resolve.js +23 -22
- package/dist/mappers/variants/index.d.ts +1 -2
- package/dist/mappers/variants/index.js +1 -2
- package/dist/mappers/variants/option-graph.d.ts +1 -2
- package/dist/mappers/variants/option-graph.js +4 -18
- package/dist/mappers/variants/variants.d.ts +3 -6
- package/dist/mappers/variants/variants.js +34 -11
- package/dist/primitive.d.ts +3 -0
- package/dist/primitive.js +2 -0
- package/dist/public.d.ts +20 -20
- package/dist/public.js +17 -9
- package/dist/validate/builder.d.ts +2 -2
- package/dist/validate/builder.js +15 -15
- package/dist/validate/expectations.d.ts +2 -2
- package/dist/validate/expectations.js +23 -5
- package/dist/validate/instance.d.ts +2 -2
- package/dist/validate/instance.js +31 -13
- package/dist/validate/model.d.ts +4 -4
- package/dist/validate/model.js +57 -51
- package/dist/validate/paths.d.ts +2 -2
- package/dist/validate/paths.js +19 -14
- package/dist/validate/pricing.d.ts +4 -4
- package/dist/validate/pricing.js +31 -31
- package/dist/validate/resolve.d.ts +2 -2
- package/dist/validate/resolve.js +27 -31
- package/dist/validate/ui.d.ts +4 -4
- package/dist/validate/ui.js +38 -38
- package/dist/validate/variants.d.ts +3 -3
- package/dist/validate/variants.js +32 -31
- package/package.json +4 -2
- package/dist/components/BuilderOptionSelect.svelte.d.ts +0 -21
- package/dist/components/BuilderOptionToggleBoolean.svelte.d.ts +0 -20
- package/dist/components/BuilderOptionToggleNumber.svelte.d.ts +0 -21
- package/dist/components/BuilderOptionToggleString.svelte.d.ts +0 -21
- package/dist/entities/collection/when.js +0 -2
- package/dist/entities/component/field.d.ts +0 -59
- package/dist/entities/component/field.js +0 -52
- package/dist/entities/component/when.d.ts +0 -11
- package/dist/entities/option/toggle.d.ts +0 -45
- package/dist/entities/option/toggle.js +0 -66
- package/dist/entities/option/when.d.ts +0 -10
- package/dist/entities/option/when.js +0 -2
package/dist/public.d.ts
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
export type { BB, BBOptions, BuilderEntityValidators } from './bb';
|
|
2
|
-
export type { Builder, BuilderBindings, BuilderBindingsSerialised, BuilderCollection, BuilderCollectionConfig, BuilderCollectionConfigSerialised, BuilderCollections, BuilderCollectionSerialised, BuilderCollectionsSerialised,
|
|
2
|
+
export type { Builder, BuilderBindings, BuilderBindingsSerialised, BuilderCollection, BuilderCollectionConfig, BuilderCollectionConfigSerialised, BuilderCollections, BuilderCollectionSerialised, BuilderCollectionsSerialised, BuilderCollectionCondition, BuilderCollectionConditionSerialised, BuilderComponent, BuilderComponentConfig, BuilderComponentConfigSerialised, BuilderComponentDetail, BuilderComponentDetailKind, BuilderComponentDetails, BuilderComponentDetailSerialised, BuilderComponentDetailsSerialised, BuilderComponents, BuilderComponentSerialised, BuilderComponentsSerialised, BuilderComponentCondition, BuilderComponentConditionSerialised, BuilderDescription, BuilderDescriptionItem, BuilderEntityKind, BuilderEntitySerialised, BuilderExpectation, BuilderExpectationKind, BuilderExpectations, BuilderExpectationSerialised, BuilderExpectationsSerialised, BuilderInstanceOf, BuilderInstanceValidated, BuilderMatchConfig, BuilderMatchSelectMap, BuilderModel, BuilderModels, BuilderModelSerialised, BuilderModelValidated, BuilderOption, BuilderOptionConfig, BuilderOptionConfigSerialised, BuilderOptions, BuilderOptionSerialised, BuilderOptionsSerialised, BuilderOptionCondition, BuilderOptionConditionSerialised, BuilderPath, BuilderPaths, BuilderPricing, BuilderPricingExpression, BuilderPricingLookupKey, BuilderPricingReduce, BuilderPricingSerialised, BuilderReference, BuilderReferences, BuilderSelectConfig, BuilderSerialised, BuilderTags, BuilderValueConfig, BuilderValueConfigSerialised, BuilderValueKind, BuilderValueOptionLabels, BuilderValueOptions, BuilderUI, BuilderUIDescribe, BuilderUIDescribeSerialised, BuilderUIInput, BuilderUIInputMetadata, BuilderUIInputMetadataSerialised, BuilderUIInputs, BuilderUIInputSerialised, BuilderUIInputsSerialised, BuilderUIItem, BuilderUIItems, BuilderUIItemsSerialised, BuilderUIPage, BuilderUIPages, BuilderUIPageSerialised, BuilderUIPagesSerialised, BuilderUIs, BuilderUISerialised, BuilderUIsSerialised, BuilderUIValidated, BuilderUnlessConfig, BuilderValidated, BuilderVariantsValidated, BuilderCondition, BuilderConditionConfig, BuilderConditionSerialised } from './entities/index';
|
|
3
3
|
export type { BuilderEnvironment } from './environment';
|
|
4
|
-
export type {
|
|
5
|
-
export type {
|
|
6
|
-
export type { BuilderComponentVariant, BuilderComponentVariants, BuilderInstance, BuilderInstanceInput, BuilderInstances, BuilderVariants } from './instance';
|
|
4
|
+
export type { BuilderIssue, BuilderIssueLocation, BuilderIssues } from './errors/index';
|
|
5
|
+
export type { BuilderIssueKind } from './errors/index.js';
|
|
6
|
+
export type { BuilderComponentVariant, BuilderComponentVariants, BuilderInstance, BuilderInstanceInput, BuilderInstances, BuilderVariantDetail, BuilderVariants } from './instance';
|
|
7
7
|
export type { BuilderOrder, BuilderRenderCollection, BuilderRenderCollectionAddRemove, BuilderRenderCollections, BuilderRenderMetadata, BuilderRenderOption, BuilderRenderOptions, BuilderRenderOptionUpdate, BuilderRenderPage, BuilderRenderPages, BuilderRenderResult } from './mappers/index';
|
|
8
8
|
export type { BuilderPrimitive, BuilderPrimitives } from './primitive';
|
|
9
9
|
export type { BuilderParameter, BuilderParameterSerialised, BuilderRef, Paramable, ParamableSerialised } from './references';
|
|
10
10
|
export type { BuilderInstanceValidationResult, BuilderModelValidationResult, BuilderPricingValidationResult, BuilderUIValidationResult, BuilderValidationResult, BuilderVariantsValidationOptions, BuilderVariantsValidationResult } from './validate/index';
|
|
11
11
|
export { bb } from './bb.js';
|
|
12
|
-
export { builder,
|
|
12
|
+
export { builder, input, match, model, pricing, serialise, unless } from './entities/index.js';
|
|
13
13
|
export { BuilderException } from './errors/index.js';
|
|
14
14
|
export { ordinal } from './mappers/index.js';
|
|
15
15
|
export { parameter, ref } from './references.js';
|
|
16
|
-
import { collectionConfig, collectionExpectation, componentConfig, componentExpectation, optionExpectation, uis } from './entities/index.js';
|
|
17
|
-
export declare const collection: typeof collectionConfig
|
|
18
|
-
|
|
19
|
-
match: <const MatchPayload extends import("./references").Paramable<import("./public").BuilderCollectionConfig<import("./references").Paramable<import("./entities/model").BuilderModelGeneric>, import("./references").Paramable<number>, import("./references").Paramable<number>>>, const MatchPath extends import("./references").Paramable<import("./public").BuilderPath>, const SelectMap extends import("./references").Paramable<import("./public").BuilderMatchSelectMap<import("./references").Paramable<import("./public").BuilderCollectionConfig<import("./references").Paramable<import("./entities/model").BuilderModelGeneric>, import("./references").Paramable<number>, import("./references").Paramable<number>>>>>>(matchPath: MatchPath, selectMap: SelectMap) => import("./public").BuilderMatchConfig<MatchPayload, MatchPath, SelectMap>;
|
|
20
|
-
unless: <const Values extends import("./references").Paramable<import("./public").BuilderCollectionConfig<import("./references").Paramable<import("./entities/model").BuilderModelGeneric>, import("./references").Paramable<number>, import("./references").Paramable<number>>>, const UnlessPath extends import("./references").Paramable<import("./public").BuilderPath>>(unlessPath: UnlessPath, disabledValues: import("./primitive").BuilderPrimitives, values: Values) => import("./public").BuilderUnlessConfig<Values, UnlessPath>;
|
|
21
|
-
};
|
|
22
|
-
export declare const component: typeof componentConfig & {
|
|
23
|
-
enable: <const Payload extends import("./references").Paramable<import("./public").BuilderComponentConfig>>(payload?: Payload) => import("./public").BuilderEnableConfig<Payload>;
|
|
24
|
-
match: <const Payload extends import("./references").Paramable<import("./public").BuilderComponentConfig>, const MatchPath extends import("./references").Paramable<import("./public").BuilderPath>, const SelectMap extends import("./references").Paramable<import("./public").BuilderMatchSelectMap<import("./references").Paramable<import("./public").BuilderComponentConfig>>>>(matchPath: MatchPath, selectMap: SelectMap) => import("./public").BuilderMatchConfig<Payload, MatchPath, SelectMap>;
|
|
25
|
-
unless: <const UnlessPath extends import("./references").Paramable<import("./public").BuilderPath>, const Payload extends import("./references").Paramable<import("./public").BuilderComponentConfig>>(unlessPath: UnlessPath, disabledValues: import("./primitive").BuilderPrimitives, payload?: Payload) => import("./public").BuilderUnlessConfig<Payload, UnlessPath>;
|
|
26
|
-
};
|
|
16
|
+
import { collectionConfig, collectionExpectation, componentConfig, componentExpectation, detailBoolean, detailImage, detailNumber, detailPrice, detailString, optionExpectation, valueBoolean, valueNumber, valueSelect, valueString, uis } from './entities/index.js';
|
|
17
|
+
export declare const collection: typeof collectionConfig;
|
|
18
|
+
export declare const component: typeof componentConfig;
|
|
27
19
|
export declare const has: {
|
|
28
20
|
collection: typeof collectionExpectation;
|
|
29
21
|
component: typeof componentExpectation;
|
|
30
22
|
option: typeof optionExpectation;
|
|
31
23
|
};
|
|
32
|
-
export declare const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
24
|
+
export declare const detail: {
|
|
25
|
+
boolean: typeof detailBoolean;
|
|
26
|
+
image: typeof detailImage;
|
|
27
|
+
number: typeof detailNumber;
|
|
28
|
+
price: typeof detailPrice;
|
|
29
|
+
string: typeof detailString;
|
|
36
30
|
};
|
|
37
31
|
export declare const ui: typeof uis;
|
|
32
|
+
export declare const value: {
|
|
33
|
+
boolean: typeof valueBoolean;
|
|
34
|
+
number: typeof valueNumber;
|
|
35
|
+
select: typeof valueSelect;
|
|
36
|
+
string: typeof valueString;
|
|
37
|
+
};
|
package/dist/public.js
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
export { bb } from './bb.js';
|
|
2
|
-
export { builder,
|
|
2
|
+
export { builder, input, match, model, pricing, serialise, unless } from './entities/index.js';
|
|
3
3
|
export { BuilderException } from './errors/index.js';
|
|
4
4
|
export { ordinal } from './mappers/index.js';
|
|
5
5
|
export { parameter, ref } from './references.js';
|
|
6
|
-
import { collectionConfig, collectionExpectation,
|
|
7
|
-
export const collection =
|
|
8
|
-
|
|
9
|
-
});
|
|
10
|
-
export const component = Object.assign(componentConfig, {
|
|
11
|
-
...componentWhen
|
|
12
|
-
});
|
|
6
|
+
import { collectionConfig, collectionExpectation, componentConfig, componentExpectation, detailBoolean, detailImage, detailNumber, detailPrice, detailString, optionExpectation, valueBoolean, valueNumber, valueSelect, valueString, uis } from './entities/index.js';
|
|
7
|
+
export const collection = collectionConfig;
|
|
8
|
+
export const component = componentConfig;
|
|
13
9
|
export const has = {
|
|
14
10
|
collection: collectionExpectation,
|
|
15
11
|
component: componentExpectation,
|
|
16
12
|
option: optionExpectation
|
|
17
13
|
};
|
|
18
|
-
export const
|
|
14
|
+
export const detail = {
|
|
15
|
+
boolean: detailBoolean,
|
|
16
|
+
image: detailImage,
|
|
17
|
+
number: detailNumber,
|
|
18
|
+
price: detailPrice,
|
|
19
|
+
string: detailString
|
|
20
|
+
};
|
|
19
21
|
export const ui = uis;
|
|
22
|
+
export const value = {
|
|
23
|
+
boolean: valueBoolean,
|
|
24
|
+
number: valueNumber,
|
|
25
|
+
select: valueSelect,
|
|
26
|
+
string: valueString
|
|
27
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { BuilderReferences, BuilderValidated, ValidationResult } from '../entities/index';
|
|
2
|
-
import {
|
|
2
|
+
import { BuilderIssuesScope } from '../errors/index.js';
|
|
3
3
|
export type BuilderValidationResult = ValidationResult<BuilderValidated>;
|
|
4
|
-
export declare function validateBuilder(input: unknown, references?: BuilderReferences,
|
|
4
|
+
export declare function validateBuilder(input: unknown, references?: BuilderReferences, issues?: BuilderIssuesScope): BuilderValidationResult;
|
package/dist/validate/builder.js
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import { builder, BuilderSerialisedSchema, modelsMerge, serialise } from '../entities/index.js';
|
|
2
|
-
import {
|
|
2
|
+
import { BuilderIssuesScope, check } from '../errors/index.js';
|
|
3
3
|
import { validate } from './brand.js';
|
|
4
4
|
import { checkModelExpectations, validateModelStructure } from './model.js';
|
|
5
5
|
import { checkPricingExpectations, validatePricingStructure } from './pricing.js';
|
|
6
6
|
import { resolver } from './resolve.js';
|
|
7
7
|
import { checkUIExpectations, validateUIStructure } from './ui.js';
|
|
8
8
|
const EMPTY_BUILDER = validate(serialise.builder(builder()));
|
|
9
|
-
export function validateBuilder(input, references = [],
|
|
9
|
+
export function validateBuilder(input, references = [], issues = new BuilderIssuesScope(input)) {
|
|
10
10
|
if (!check.is(BuilderSerialisedSchema, input)) {
|
|
11
|
-
|
|
12
|
-
return [EMPTY_BUILDER, errors.
|
|
11
|
+
issues.entityInvalid('builder');
|
|
12
|
+
return [EMPTY_BUILDER, issues.errors, issues.warnings];
|
|
13
13
|
}
|
|
14
|
-
const resolve = resolver(
|
|
15
|
-
const validatedModel =
|
|
14
|
+
const resolve = resolver(issues, references, input.bindings);
|
|
15
|
+
const validatedModel = issues.scope('model', () => validateModelStructure(input.model, resolve, issues));
|
|
16
16
|
const mergedModel = modelsMerge(validatedModel);
|
|
17
|
-
|
|
18
|
-
checkModelExpectations(mergedModel, validatedModel,
|
|
17
|
+
issues.scope('model', () => {
|
|
18
|
+
checkModelExpectations(mergedModel, validatedModel, issues);
|
|
19
19
|
});
|
|
20
|
-
const validatedUI =
|
|
21
|
-
const validated = validateUIStructure(input.ui, resolve,
|
|
22
|
-
checkUIExpectations(mergedModel, validated,
|
|
20
|
+
const validatedUI = issues.scope('ui', () => {
|
|
21
|
+
const validated = validateUIStructure(input.ui, resolve, issues);
|
|
22
|
+
checkUIExpectations(mergedModel, validated, issues);
|
|
23
23
|
return validated;
|
|
24
24
|
});
|
|
25
|
-
const validatedPricing =
|
|
26
|
-
const validated = validatePricingStructure(input.pricing, resolve,
|
|
27
|
-
checkPricingExpectations(mergedModel, validated,
|
|
25
|
+
const validatedPricing = issues.scope('pricing', () => {
|
|
26
|
+
const validated = validatePricingStructure(input.pricing, resolve, issues);
|
|
27
|
+
checkPricingExpectations(mergedModel, validated, issues);
|
|
28
28
|
return validated;
|
|
29
29
|
});
|
|
30
30
|
const data = validate({
|
|
@@ -33,5 +33,5 @@ export function validateBuilder(input, references = [], errors = new BuilderErro
|
|
|
33
33
|
ui: validate(validatedUI),
|
|
34
34
|
pricing: validate(validatedPricing)
|
|
35
35
|
});
|
|
36
|
-
return [data, errors.
|
|
36
|
+
return [data, issues.errors, issues.warnings];
|
|
37
37
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { BuilderExpectationsSerialised, BuilderModelSerialised } from '../entities/index';
|
|
2
|
-
import type {
|
|
3
|
-
export declare function checkExpectations(model: BuilderModelSerialised, expectations: BuilderExpectationsSerialised,
|
|
2
|
+
import type { BuilderIssuesScope } from '../errors/index';
|
|
3
|
+
export declare function checkExpectations(model: BuilderModelSerialised, expectations: BuilderExpectationsSerialised, issues: BuilderIssuesScope): void;
|
|
@@ -1,10 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { BuilderOptionConfigSerialisedSchema } from '../entities/index.js';
|
|
2
|
+
import { check } from '../errors/index.js';
|
|
3
|
+
export function checkExpectations(model, expectations, issues) {
|
|
4
|
+
expectations.forEach(({ kind, name, payload }, index) => {
|
|
5
|
+
issues.scope(index, () => {
|
|
6
|
+
const entry = model[`${kind}s`].find((candidate) => candidate.name === name);
|
|
7
|
+
if (entry == null) {
|
|
8
|
+
issues.modelUnmetExpectation();
|
|
5
9
|
return;
|
|
6
10
|
}
|
|
7
|
-
|
|
11
|
+
if (payload != null && !isExpectedOption(entry.payload, payload)) {
|
|
12
|
+
issues.modelInvalidExpectation();
|
|
13
|
+
}
|
|
8
14
|
});
|
|
9
15
|
});
|
|
10
16
|
}
|
|
17
|
+
function isExpectedOption(payload, expectation) {
|
|
18
|
+
if (!check.is(BuilderOptionConfigSerialisedSchema, payload)) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
if (expectation.kind === 'select') {
|
|
22
|
+
if (payload.kind !== 'select') {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return expectation.options.every((option) => payload.options.includes(option));
|
|
26
|
+
}
|
|
27
|
+
return payload.kind === expectation.kind;
|
|
28
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BuilderInstanceValidated, BuilderModelValidated, ValidationResult } from '../entities/index';
|
|
2
2
|
import type { BuilderInstance } from '../instance';
|
|
3
|
-
import {
|
|
3
|
+
import { BuilderIssuesScope } from '../errors/index.js';
|
|
4
4
|
export type BuilderInstanceValidationResult = ValidationResult<BuilderInstanceValidated>;
|
|
5
|
-
export declare function validateInstance(model: BuilderModelValidated, instance: BuilderInstance,
|
|
5
|
+
export declare function validateInstance(model: BuilderModelValidated, instance: BuilderInstance, issues?: BuilderIssuesScope): BuilderInstanceValidationResult;
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import { optionValueSchema } from '../entities/index.js';
|
|
2
|
-
import {
|
|
1
|
+
import { modelsMerge, optionValueSchema } from '../entities/index.js';
|
|
2
|
+
import { BuilderIssuesScope, check } from '../errors/index.js';
|
|
3
3
|
import { BuilderInstancesSchema } from '../instance.js';
|
|
4
4
|
import { resolveCollection, resolveOption } from '../mappers/index.js';
|
|
5
5
|
import { validate } from './brand.js';
|
|
6
|
-
export function validateInstance(model, instance,
|
|
7
|
-
|
|
6
|
+
export function validateInstance(model, instance, issues = new BuilderIssuesScope(instance)) {
|
|
7
|
+
issues.scope('instance', () => {
|
|
8
8
|
checkInstance(model, instance);
|
|
9
9
|
});
|
|
10
|
-
return [validate(instance), errors.
|
|
10
|
+
return [validate(instance), issues.errors, issues.warnings];
|
|
11
11
|
function checkInstance(scopeModel, scopeInstance) {
|
|
12
|
-
scopeModel
|
|
12
|
+
const merged = modelsMerge(scopeModel);
|
|
13
|
+
merged.options.forEach((option) => {
|
|
13
14
|
const { name } = option;
|
|
14
15
|
const payload = resolveOption(option, scopeModel, scopeInstance);
|
|
15
16
|
if (!payload) {
|
|
@@ -17,12 +18,12 @@ export function validateInstance(model, instance, errors = new BuilderErrorsScop
|
|
|
17
18
|
}
|
|
18
19
|
const value = scopeInstance[name];
|
|
19
20
|
if (!check.is(optionValueSchema(payload), value)) {
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
issues.scope(name, () => {
|
|
22
|
+
issues.instanceInvalidOption();
|
|
22
23
|
});
|
|
23
24
|
}
|
|
24
25
|
});
|
|
25
|
-
|
|
26
|
+
merged.collections.forEach((collection) => {
|
|
26
27
|
const { name } = collection;
|
|
27
28
|
const payload = resolveCollection(collection, scopeModel, scopeInstance);
|
|
28
29
|
if (!payload) {
|
|
@@ -30,18 +31,35 @@ export function validateInstance(model, instance, errors = new BuilderErrorsScop
|
|
|
30
31
|
}
|
|
31
32
|
const existing = scopeInstance[name];
|
|
32
33
|
if (!check.is(BuilderInstancesSchema, existing)) {
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
issues.scope(name, () => {
|
|
35
|
+
issues.instanceInvalidCollection();
|
|
35
36
|
});
|
|
36
37
|
return;
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
+
issues.scope(name, () => {
|
|
40
|
+
if (existing.length < payload.min) {
|
|
41
|
+
issues.instanceInvalidCollectionMin();
|
|
42
|
+
}
|
|
43
|
+
else if (existing.length > payload.max) {
|
|
44
|
+
issues.instanceInvalidCollectionMax();
|
|
45
|
+
}
|
|
39
46
|
existing.forEach((itemInstance, index) => {
|
|
40
|
-
|
|
47
|
+
issues.scope(index, () => {
|
|
41
48
|
checkInstance(payload.model, itemInstance);
|
|
42
49
|
});
|
|
43
50
|
});
|
|
44
51
|
});
|
|
45
52
|
});
|
|
53
|
+
const declaredNames = new Set([
|
|
54
|
+
...merged.options.map((option) => option.name),
|
|
55
|
+
...merged.collections.map((collection) => collection.name)
|
|
56
|
+
]);
|
|
57
|
+
Object.keys(scopeInstance).forEach((key) => {
|
|
58
|
+
if (!declaredNames.has(key)) {
|
|
59
|
+
issues.scope(key, () => {
|
|
60
|
+
issues.instanceUnexpectedKey();
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
});
|
|
46
64
|
}
|
|
47
65
|
}
|
package/dist/validate/model.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { BuilderModelSerialised, BuilderModelValidated, BuilderReferences, ValidationResult } from '../entities/index';
|
|
2
2
|
import type { ParamableSerialised } from '../references';
|
|
3
3
|
import type { BuilderResolve } from './resolve';
|
|
4
|
-
import {
|
|
4
|
+
import { BuilderIssuesScope } from '../errors/index.js';
|
|
5
5
|
export type BuilderModelValidationResult = ValidationResult<BuilderModelValidated>;
|
|
6
|
-
export declare function validateModel(input: unknown, references?: BuilderReferences,
|
|
7
|
-
export declare function checkModelExpectations(mergedModel: BuilderModelSerialised, rootModel: BuilderModelSerialised,
|
|
8
|
-
export declare function validateModelStructure(input: ParamableSerialised<BuilderModelSerialised>, resolve: BuilderResolve,
|
|
6
|
+
export declare function validateModel(input: unknown, references?: BuilderReferences, issues?: BuilderIssuesScope): BuilderModelValidationResult;
|
|
7
|
+
export declare function checkModelExpectations(mergedModel: BuilderModelSerialised, rootModel: BuilderModelSerialised, issues: BuilderIssuesScope): void;
|
|
8
|
+
export declare function validateModelStructure(input: ParamableSerialised<BuilderModelSerialised>, resolve: BuilderResolve, issues: BuilderIssuesScope): BuilderModelValidated;
|
package/dist/validate/model.js
CHANGED
|
@@ -1,40 +1,41 @@
|
|
|
1
1
|
import * as v from 'valibot';
|
|
2
|
-
import { BuilderCollectionConfigSerialisedSchema, BuilderComponentConfigSerialisedSchema, BuilderModelSerialisedSchema, BuilderOptionConfigSerialisedSchema, BuilderPathsSchema,
|
|
3
|
-
import {
|
|
2
|
+
import { BuilderCollectionConfigSerialisedSchema, BuilderComponentConfigSerialisedSchema, BuilderModelSerialisedSchema, BuilderOptionConfigSerialisedSchema, BuilderPathsSchema, BuilderConditionSerialisedSchema, conditionBranches, model, modelsMerge, serialise, validateCollectionConfig, validateComponentConfig, validateValue } from '../entities/index.js';
|
|
3
|
+
import { BuilderIssuesScope, check } from '../errors/index.js';
|
|
4
|
+
import { dependencies } from '../mappers/index.js';
|
|
4
5
|
import { isParamable } from '../references.js';
|
|
5
6
|
import { validate } from './brand.js';
|
|
6
7
|
import { checkExpectations } from './expectations.js';
|
|
7
8
|
import { checkPath } from './paths.js';
|
|
8
9
|
import { resolver } from './resolve.js';
|
|
9
10
|
const EMPTY_MODEL = validate(serialise.model(model()));
|
|
10
|
-
export function validateModel(input, references = [],
|
|
11
|
+
export function validateModel(input, references = [], issues = new BuilderIssuesScope(input)) {
|
|
11
12
|
if (!check.is(BuilderModelSerialisedSchema, input)) {
|
|
12
|
-
|
|
13
|
-
return [EMPTY_MODEL, errors.
|
|
13
|
+
issues.entityInvalid('model');
|
|
14
|
+
return [EMPTY_MODEL, issues.errors, issues.warnings];
|
|
14
15
|
}
|
|
15
|
-
const resolve = resolver(
|
|
16
|
-
const structure = validateModelStructure(input, resolve,
|
|
16
|
+
const resolve = resolver(issues, references);
|
|
17
|
+
const structure = validateModelStructure(input, resolve, issues);
|
|
17
18
|
const merged = modelsMerge(structure);
|
|
18
19
|
const data = validate(merged);
|
|
19
|
-
checkModelExpectations(data, structure,
|
|
20
|
-
return [data, errors.
|
|
20
|
+
checkModelExpectations(data, structure, issues);
|
|
21
|
+
return [data, issues.errors, issues.warnings];
|
|
21
22
|
}
|
|
22
|
-
export function checkModelExpectations(mergedModel, rootModel,
|
|
23
|
+
export function checkModelExpectations(mergedModel, rootModel, issues) {
|
|
23
24
|
recurse(rootModel);
|
|
24
25
|
function recurse(node) {
|
|
25
|
-
|
|
26
|
-
checkExpectations(mergedModel, node.expectations,
|
|
26
|
+
issues.scope('expectations', () => {
|
|
27
|
+
checkExpectations(mergedModel, node.expectations, issues);
|
|
27
28
|
});
|
|
28
|
-
|
|
29
|
+
issues.scope('models', () => {
|
|
29
30
|
node.models.forEach((nested, nestedIndex) => {
|
|
30
|
-
|
|
31
|
+
issues.scope(nestedIndex, () => {
|
|
31
32
|
recurse(nested);
|
|
32
33
|
});
|
|
33
34
|
});
|
|
34
35
|
});
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
|
-
export function validateModelStructure(input, resolve,
|
|
38
|
+
export function validateModelStructure(input, resolve, issues) {
|
|
38
39
|
const seenGlobal = {
|
|
39
40
|
option: new Set(),
|
|
40
41
|
component: new Set(),
|
|
@@ -47,41 +48,42 @@ export function validateModelStructure(input, resolve, errors) {
|
|
|
47
48
|
return validate(serialise.model(model()));
|
|
48
49
|
}
|
|
49
50
|
const modelInput = resolved;
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
whenBranches(resolved.payload, BuilderOptionConfigSerialisedSchema)
|
|
51
|
+
const childModels = issues.scope('models', () => modelInput.models.flatMap((part, partIndex) => issues.scope(partIndex, () => [walkStructure(part)])));
|
|
52
|
+
const options = issues.scope('options', () => walkEntries(modelInput.options, 'option', (resolved) => {
|
|
53
|
+
conditionBranches(resolved.payload, BuilderOptionConfigSerialisedSchema)
|
|
54
54
|
.filter((config) => !isParamable(config))
|
|
55
55
|
.forEach((config) => {
|
|
56
|
-
if (config.type === '
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
else if (config.type === 'toggle') {
|
|
60
|
-
validateToggle(config, [], errors);
|
|
56
|
+
if (config.type === 'value') {
|
|
57
|
+
validateValue(config, [], issues);
|
|
61
58
|
}
|
|
62
59
|
});
|
|
63
60
|
}));
|
|
64
|
-
const components =
|
|
65
|
-
|
|
61
|
+
const components = issues.scope('components', () => walkEntries(modelInput.components, 'component', (resolved) => {
|
|
62
|
+
conditionBranches(resolved.payload, BuilderComponentConfigSerialisedSchema)
|
|
66
63
|
.filter((config) => !isParamable(config))
|
|
67
64
|
.forEach((config) => {
|
|
68
|
-
validateComponentConfig(config, [],
|
|
65
|
+
validateComponentConfig(config, [], issues);
|
|
69
66
|
});
|
|
70
67
|
}));
|
|
71
|
-
const collections =
|
|
72
|
-
|
|
68
|
+
const collections = issues.scope('collections', () => walkEntries(modelInput.collections, 'collection', (resolved) => {
|
|
69
|
+
conditionBranches(resolved.payload, BuilderCollectionConfigSerialisedSchema)
|
|
73
70
|
.filter((config) => !isParamable(config))
|
|
74
71
|
.forEach((config) => {
|
|
75
|
-
validateCollectionConfig(config, [],
|
|
72
|
+
validateCollectionConfig(config, [], issues);
|
|
76
73
|
});
|
|
77
74
|
}));
|
|
78
|
-
|
|
75
|
+
const validatedModel = {
|
|
79
76
|
...modelInput,
|
|
80
77
|
models: childModels,
|
|
81
78
|
options,
|
|
82
79
|
components,
|
|
83
80
|
collections
|
|
84
81
|
};
|
|
82
|
+
const ordered = new Set(dependencies(validatedModel));
|
|
83
|
+
if ([...options, ...collections, ...components].some((entry) => !ordered.has(entry.name))) {
|
|
84
|
+
issues.modelCircularDependency();
|
|
85
|
+
}
|
|
86
|
+
return validatedModel;
|
|
85
87
|
function payloadSchemaFor(kind) {
|
|
86
88
|
if (kind === 'option') {
|
|
87
89
|
return BuilderOptionConfigSerialisedSchema;
|
|
@@ -95,7 +97,7 @@ export function validateModelStructure(input, resolve, errors) {
|
|
|
95
97
|
const seenLocal = new Set();
|
|
96
98
|
const items = [];
|
|
97
99
|
entries.forEach((entry, entryIndex) => {
|
|
98
|
-
|
|
100
|
+
issues.scope(entryIndex, () => {
|
|
99
101
|
const resolved = resolveEntry(entry, seenLocal, kind);
|
|
100
102
|
if (resolved == null) {
|
|
101
103
|
return;
|
|
@@ -109,33 +111,33 @@ export function validateModelStructure(input, resolve, errors) {
|
|
|
109
111
|
function resolveEntry(entry, seenLocal, kind) {
|
|
110
112
|
let paths = entry.paths;
|
|
111
113
|
if (entry.paths != null) {
|
|
112
|
-
const resolvedPaths =
|
|
114
|
+
const resolvedPaths = issues.scope('paths', () => resolve(entry.paths, BuilderPathsSchema));
|
|
113
115
|
paths = resolvedPaths ?? entry.paths;
|
|
114
116
|
}
|
|
115
|
-
const payloadSchema = v.union([payloadSchemaFor(kind),
|
|
116
|
-
const payload =
|
|
117
|
+
const payloadSchema = v.union([payloadSchemaFor(kind), BuilderConditionSerialisedSchema]);
|
|
118
|
+
const payload = issues.scope('payload', () => resolve(entry.payload, payloadSchema));
|
|
117
119
|
const resolvedEntry = { ...entry, paths, payload: payload ?? entry.payload };
|
|
118
120
|
if (seenLocal.has(resolvedEntry.name)) {
|
|
119
121
|
if (kind === 'option') {
|
|
120
|
-
|
|
122
|
+
issues.modelDuplicateOption();
|
|
121
123
|
}
|
|
122
124
|
else if (kind === 'component') {
|
|
123
|
-
|
|
125
|
+
issues.modelDuplicateComponent();
|
|
124
126
|
}
|
|
125
127
|
else {
|
|
126
|
-
|
|
128
|
+
issues.modelDuplicateCollection();
|
|
127
129
|
}
|
|
128
130
|
return null;
|
|
129
131
|
}
|
|
130
132
|
if (seenGlobal[kind].has(resolvedEntry.name)) {
|
|
131
133
|
if (kind === 'option') {
|
|
132
|
-
|
|
134
|
+
issues.modelOverriddenOption();
|
|
133
135
|
}
|
|
134
136
|
else if (kind === 'component') {
|
|
135
|
-
|
|
137
|
+
issues.modelOverriddenComponent();
|
|
136
138
|
}
|
|
137
139
|
else {
|
|
138
|
-
|
|
140
|
+
issues.modelOverriddenCollection();
|
|
139
141
|
}
|
|
140
142
|
}
|
|
141
143
|
seenLocal.add(resolvedEntry.name);
|
|
@@ -144,27 +146,31 @@ export function validateModelStructure(input, resolve, errors) {
|
|
|
144
146
|
return resolvedEntry;
|
|
145
147
|
}
|
|
146
148
|
function checkPaths(entry) {
|
|
147
|
-
if (skipPathValidation) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
149
|
const { paths, payload } = entry;
|
|
151
150
|
if (Array.isArray(paths)) {
|
|
152
|
-
|
|
151
|
+
issues.scope('paths', () => {
|
|
153
152
|
paths.forEach((path, pathIndex) => {
|
|
154
|
-
|
|
155
|
-
checkPath(modelInput, path,
|
|
153
|
+
issues.scope(pathIndex, () => {
|
|
154
|
+
checkPath(modelInput, path, issues);
|
|
156
155
|
});
|
|
157
156
|
});
|
|
158
157
|
});
|
|
159
158
|
}
|
|
160
|
-
if (!check.is(
|
|
159
|
+
if (!check.is(BuilderConditionSerialisedSchema, payload)) {
|
|
161
160
|
return;
|
|
162
161
|
}
|
|
163
162
|
if (payload.type === 'match' && Array.isArray(payload.matchPath)) {
|
|
164
|
-
|
|
163
|
+
issues.scope('payload', () => issues.scope('matchPath', () => checkPath(modelInput, payload.matchPath, issues)));
|
|
165
164
|
}
|
|
166
|
-
if (payload.type === 'unless'
|
|
167
|
-
|
|
165
|
+
if (payload.type === 'unless') {
|
|
166
|
+
if (payload.disabledValues.length === 0) {
|
|
167
|
+
issues.scope('payload', () => issues.scope('disabledValues', () => {
|
|
168
|
+
issues.entityEmptyDisabledValues();
|
|
169
|
+
}));
|
|
170
|
+
}
|
|
171
|
+
if (Array.isArray(payload.unlessPath)) {
|
|
172
|
+
issues.scope('payload', () => issues.scope('unlessPath', () => checkPath(modelInput, payload.unlessPath, issues)));
|
|
173
|
+
}
|
|
168
174
|
}
|
|
169
175
|
}
|
|
170
176
|
}
|
package/dist/validate/paths.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { BuilderModelSerialised, BuilderPath } from '../entities/index';
|
|
2
|
-
import type {
|
|
3
|
-
export declare function checkPath(model: BuilderModelSerialised, path: BuilderPath,
|
|
2
|
+
import type { BuilderIssuesScope } from '../errors/index';
|
|
3
|
+
export declare function checkPath(model: BuilderModelSerialised, path: BuilderPath, issues: BuilderIssuesScope): void;
|
package/dist/validate/paths.js
CHANGED
|
@@ -2,19 +2,24 @@ import { BuilderModelSerialisedSchema } from '../entities/index.js';
|
|
|
2
2
|
import { check } from '../errors/index.js';
|
|
3
3
|
import { resolveCollections } from '../mappers/index.js';
|
|
4
4
|
import { NameSchema, NumberSchema } from '../primitive.js';
|
|
5
|
-
export function checkPath(model, path,
|
|
5
|
+
export function checkPath(model, path, issues) {
|
|
6
6
|
if (path.length === 0) {
|
|
7
|
-
|
|
7
|
+
issues.pathEmpty();
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const [firstSegment] = path;
|
|
11
|
+
if (check.is(NameSchema, firstSegment) &&
|
|
12
|
+
model.expectations.some((expectation) => expectation.name === firstSegment)) {
|
|
8
13
|
return;
|
|
9
14
|
}
|
|
10
15
|
const lastIndex = path.length - 1;
|
|
11
|
-
const models = walkPath([model], path.slice(0, -1), 0,
|
|
16
|
+
const models = walkPath([model], path.slice(0, -1), 0, issues);
|
|
12
17
|
if (models == null) {
|
|
13
18
|
return;
|
|
14
19
|
}
|
|
15
20
|
const optionName = path.at(-1);
|
|
16
21
|
if (!check.is(NameSchema, optionName)) {
|
|
17
|
-
|
|
22
|
+
issues.scope(lastIndex, () => issues.pathInvalidSegment());
|
|
18
23
|
return;
|
|
19
24
|
}
|
|
20
25
|
if (models.some((model) => model.options.some((option) => option.name === optionName))) {
|
|
@@ -22,27 +27,27 @@ export function checkPath(model, path, errors) {
|
|
|
22
27
|
}
|
|
23
28
|
const isCollection = models.some((model) => model.collections.some((entry) => entry.name === optionName));
|
|
24
29
|
if (isCollection) {
|
|
25
|
-
|
|
30
|
+
issues.scope(lastIndex, () => issues.pathTargetIsCollection());
|
|
26
31
|
return;
|
|
27
32
|
}
|
|
28
33
|
const isComponent = models.some((model) => model.components.some((entry) => entry.name === optionName));
|
|
29
34
|
if (isComponent) {
|
|
30
|
-
|
|
35
|
+
issues.scope(lastIndex, () => issues.pathTargetIsComponent());
|
|
31
36
|
return;
|
|
32
37
|
}
|
|
33
|
-
|
|
38
|
+
issues.scope(lastIndex, () => issues.pathMissingOption());
|
|
34
39
|
}
|
|
35
|
-
function walkPath(models, remaining, offset,
|
|
40
|
+
function walkPath(models, remaining, offset, issues) {
|
|
36
41
|
if (remaining.length === 0) {
|
|
37
42
|
return models;
|
|
38
43
|
}
|
|
39
44
|
const [collectionName, index, ...rest] = remaining;
|
|
40
45
|
if (!check.is(NameSchema, collectionName)) {
|
|
41
|
-
|
|
46
|
+
issues.scope(offset, () => issues.pathInvalidSegment());
|
|
42
47
|
return null;
|
|
43
48
|
}
|
|
44
49
|
if (!check.is(NumberSchema, index)) {
|
|
45
|
-
|
|
50
|
+
issues.scope(offset + 1, () => issues.pathInvalidSegment());
|
|
46
51
|
return null;
|
|
47
52
|
}
|
|
48
53
|
const collectionConfigs = models.flatMap((model) => {
|
|
@@ -50,7 +55,7 @@ function walkPath(models, remaining, offset, errors) {
|
|
|
50
55
|
return collection == null ? [] : resolveCollections(collection);
|
|
51
56
|
});
|
|
52
57
|
if (collectionConfigs.length === 0) {
|
|
53
|
-
|
|
58
|
+
issues.scope(offset, () => issues.pathMissingCollection());
|
|
54
59
|
return null;
|
|
55
60
|
}
|
|
56
61
|
const indexableConfigs = collectionConfigs.filter(({ max }) => !check.is(NumberSchema, max) || index < max);
|
|
@@ -61,13 +66,13 @@ function walkPath(models, remaining, offset, errors) {
|
|
|
61
66
|
}
|
|
62
67
|
return max > highest ? max : highest;
|
|
63
68
|
}, 0);
|
|
64
|
-
|
|
69
|
+
issues.scope(offset + 1, () => issues.pathInvalidIndex(max));
|
|
65
70
|
return null;
|
|
66
71
|
}
|
|
67
72
|
const next = indexableConfigs.flatMap((collectionConfig) => check.is(BuilderModelSerialisedSchema, collectionConfig.model) ? [collectionConfig.model] : []);
|
|
68
73
|
if (next.length === 0) {
|
|
69
|
-
|
|
74
|
+
issues.scope(offset, () => issues.pathMissingCollection());
|
|
70
75
|
return null;
|
|
71
76
|
}
|
|
72
|
-
return walkPath(next, rest, offset + 2,
|
|
77
|
+
return walkPath(next, rest, offset + 2, issues);
|
|
73
78
|
}
|