@builder-builder/builder 0.0.24 → 0.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/dist/client/client.d.ts +3 -1
  2. package/dist/client/client.js +29 -20
  3. package/dist/client/index.d.ts +1 -4
  4. package/dist/client/index.js +1 -2
  5. package/dist/client/public.d.ts +4 -0
  6. package/dist/client/public.js +2 -0
  7. package/dist/client/schema.d.ts +26 -18
  8. package/dist/client/schema.js +7 -1
  9. package/dist/entities/builder/builder.js +2 -1
  10. package/dist/entities/collection/collection.d.ts +2 -2
  11. package/dist/entities/collection/collection.js +2 -1
  12. package/dist/entities/collection/config.d.ts +21 -21
  13. package/dist/entities/collection/config.js +4 -3
  14. package/dist/entities/component/component.d.ts +32 -32
  15. package/dist/entities/component/component.js +2 -1
  16. package/dist/entities/component/config.d.ts +13 -13
  17. package/dist/entities/component/config.js +1 -1
  18. package/dist/entities/component/field.d.ts +4 -4
  19. package/dist/entities/component/field.js +4 -3
  20. package/dist/entities/expectation.d.ts +3 -3
  21. package/dist/entities/expectation.js +2 -1
  22. package/dist/entities/index.d.ts +1 -1
  23. package/dist/entities/kind.d.ts +4 -4
  24. package/dist/entities/kind.js +44 -4
  25. package/dist/entities/model/models.d.ts +3 -3
  26. package/dist/entities/option/config.d.ts +4 -4
  27. package/dist/entities/option/option.d.ts +24 -24
  28. package/dist/entities/option/option.js +2 -1
  29. package/dist/entities/option/select.d.ts +2 -2
  30. package/dist/entities/option/select.js +12 -9
  31. package/dist/entities/option/toggle.d.ts +2 -2
  32. package/dist/entities/option/toggle.js +5 -4
  33. package/dist/entities/paths.d.ts +4 -4
  34. package/dist/entities/paths.js +2 -1
  35. package/dist/entities/pricing/expression.js +5 -4
  36. package/dist/entities/pricing/rates.d.ts +1 -1
  37. package/dist/entities/pricing/rates.js +2 -1
  38. package/dist/entities/references.d.ts +2 -2
  39. package/dist/entities/references.js +2 -1
  40. package/dist/entities/serialise.d.ts +204 -116
  41. package/dist/entities/serialise.js +4 -3
  42. package/dist/entities/tags.d.ts +1 -1
  43. package/dist/entities/tags.js +2 -1
  44. package/dist/entities/ui/describe.d.ts +79 -35
  45. package/dist/entities/ui/describe.js +5 -4
  46. package/dist/entities/ui/input.d.ts +93 -49
  47. package/dist/entities/ui/input.js +5 -4
  48. package/dist/entities/ui/page.d.ts +77 -33
  49. package/dist/entities/ui/page.js +4 -3
  50. package/dist/entities/ui/pages.d.ts +5 -5
  51. package/dist/entities/ui/pages.js +5 -4
  52. package/dist/entities/validated.d.ts +1 -0
  53. package/dist/entities/when.d.ts +16 -16
  54. package/dist/entities/when.js +2 -2
  55. package/dist/errors/check.d.ts +2 -3
  56. package/dist/errors/check.js +5 -10
  57. package/dist/errors/errors.d.ts +241 -158
  58. package/dist/errors/errors.js +149 -173
  59. package/dist/errors/exception.d.ts +6 -4
  60. package/dist/errors/exception.js +11 -66
  61. package/dist/errors/index.d.ts +2 -4
  62. package/dist/errors/index.js +2 -2
  63. package/dist/errors/public.d.ts +2 -0
  64. package/dist/errors/public.js +1 -0
  65. package/dist/index.d.ts +4 -36
  66. package/dist/index.js +4 -19
  67. package/dist/instance.d.ts +7 -7
  68. package/dist/instance.js +4 -4
  69. package/dist/mappers/index.d.ts +1 -1
  70. package/dist/mappers/price.js +2 -3
  71. package/dist/mappers/render/collection.d.ts +9 -0
  72. package/dist/mappers/render/collection.js +27 -0
  73. package/dist/mappers/render/compose.d.ts +5 -0
  74. package/dist/mappers/render/compose.js +15 -0
  75. package/dist/mappers/render/description.d.ts +3 -0
  76. package/dist/mappers/render/description.js +17 -0
  77. package/dist/mappers/render/index.d.ts +3 -1
  78. package/dist/mappers/render/option.d.ts +20 -0
  79. package/dist/mappers/render/option.js +25 -0
  80. package/dist/mappers/render/page.d.ts +11 -0
  81. package/dist/mappers/render/page.js +11 -0
  82. package/dist/mappers/render/paths.d.ts +3 -0
  83. package/dist/mappers/render/paths.js +21 -0
  84. package/dist/mappers/render/render.d.ts +1 -1
  85. package/dist/mappers/render/render.js +33 -98
  86. package/dist/mappers/resolve.d.ts +2 -1
  87. package/dist/mappers/resolve.js +26 -25
  88. package/dist/mappers/variants/option-graph.js +11 -4
  89. package/dist/mappers/variants/variants.js +7 -6
  90. package/dist/primitive.d.ts +5 -0
  91. package/dist/primitive.js +6 -1
  92. package/dist/public.d.ts +37 -0
  93. package/dist/public.js +19 -0
  94. package/dist/references.d.ts +6 -6
  95. package/dist/references.js +3 -2
  96. package/dist/validate/brand.js +2 -4
  97. package/dist/validate/builder.d.ts +2 -2
  98. package/dist/validate/builder.js +3 -3
  99. package/dist/validate/expectations.d.ts +2 -2
  100. package/dist/validate/expectations.js +1 -1
  101. package/dist/validate/index.d.ts +0 -1
  102. package/dist/validate/instance.d.ts +2 -2
  103. package/dist/validate/instance.js +6 -6
  104. package/dist/validate/model.d.ts +4 -4
  105. package/dist/validate/model.js +129 -101
  106. package/dist/validate/paths.d.ts +2 -2
  107. package/dist/validate/paths.js +47 -25
  108. package/dist/validate/pricing.d.ts +4 -4
  109. package/dist/validate/pricing.js +30 -18
  110. package/dist/validate/resolve.d.ts +4 -3
  111. package/dist/validate/resolve.js +88 -63
  112. package/dist/validate/ui.d.ts +4 -4
  113. package/dist/validate/ui.js +17 -16
  114. package/dist/validate/variants.d.ts +2 -2
  115. package/dist/validate/variants.js +16 -16
  116. package/package.json +11 -7
  117. package/dist/mappers/render/pages.d.ts +0 -24
  118. package/dist/mappers/render/pages.js +0 -2
  119. package/dist/private.d.ts +0 -3
  120. package/dist/private.js +0 -3
@@ -0,0 +1,37 @@
1
+ export type { BB, BBOptions, BuilderEntityValidators } from './bb';
2
+ export type { Builder, BuilderBindings, BuilderBindingsSerialised, BuilderCollection, BuilderCollectionConfig, BuilderCollectionConfigSerialised, BuilderCollections, BuilderCollectionSerialised, BuilderCollectionsSerialised, BuilderCollectionWhen, BuilderCollectionWhenSerialised, BuilderComponent, BuilderComponentConfig, BuilderComponentConfigSerialised, BuilderComponentField, BuilderComponentFields, BuilderComponentFieldSerialised, BuilderComponentFieldsSerialised, BuilderComponentFieldValueType, BuilderComponents, BuilderComponentSerialised, BuilderComponentsSerialised, BuilderComponentWhen, BuilderComponentWhenSerialised, BuilderDescription, BuilderDescriptionItem, BuilderEnableConfig, BuilderEntityKind, BuilderEntitySerialised, BuilderExpectation, BuilderExpectationKind, BuilderExpectations, BuilderExpectationSerialised, BuilderExpectationsSerialised, BuilderInstanceOf, BuilderInstanceValidated, BuilderMatchConfig, BuilderMatchSelectMap, BuilderModel, BuilderModels, BuilderModelSerialised, BuilderModelValidated, BuilderOption, BuilderOptionConfig, BuilderOptionConfigSerialised, BuilderOptions, BuilderOptionSerialised, BuilderOptionsSerialised, BuilderOptionWhen, BuilderOptionWhenSerialised, BuilderPath, BuilderPaths, BuilderPricing, BuilderPricingExpression, BuilderPricingLookupKey, BuilderPricingReduce, BuilderPricingSerialised, BuilderReference, BuilderReferences, BuilderSelectConfig, BuilderSelectConfigLabels, BuilderSelectConfigSerialised, BuilderSelectConfigValues, BuilderSerialised, BuilderTags, BuilderToggleConfig, BuilderToggleConfigSerialised, BuilderToggleValueType, BuilderUI, BuilderUIDescribe, BuilderUIDescribeSerialised, BuilderUIInput, BuilderUIInputMetadata, BuilderUIInputMetadataSerialised, BuilderUIInputs, BuilderUIInputSerialised, BuilderUIInputsSerialised, BuilderUIItem, BuilderUIItems, BuilderUIItemsSerialised, BuilderUIPage, BuilderUIPages, BuilderUIPageSerialised, BuilderUIPagesSerialised, BuilderUIs, BuilderUISerialised, BuilderUIsSerialised, BuilderUIValidated, BuilderUnlessConfig, BuilderValidated, BuilderVariantsValidated, BuilderWhen, BuilderWhenConfig, BuilderWhenSerialised } from './entities/index';
3
+ export type { BuilderEnvironment } from './environment';
4
+ export type { BuilderError, BuilderErrorLocation, BuilderErrors } from './errors/index';
5
+ export type { BuilderErrorKind } from './errors/index.js';
6
+ export type { BuilderComponentVariant, BuilderComponentVariants, BuilderInstance, BuilderInstanceInput, BuilderInstances, BuilderVariants } from './instance';
7
+ export type { BuilderOrder, BuilderRenderCollection, BuilderRenderCollectionAddRemove, BuilderRenderCollections, BuilderRenderMetadata, BuilderRenderOption, BuilderRenderOptions, BuilderRenderOptionUpdate, BuilderRenderPage, BuilderRenderPages, BuilderRenderResult } from './mappers/index';
8
+ export type { BuilderPrimitive, BuilderPrimitives } from './primitive';
9
+ export type { BuilderParameter, BuilderParameterSerialised, BuilderRef, Paramable, ParamableSerialised } from './references';
10
+ export type { BuilderInstanceValidationResult, BuilderModelValidationResult, BuilderPricingValidationResult, BuilderUIValidationResult, BuilderValidationResult, BuilderVariantsValidationOptions, BuilderVariantsValidationResult } from './validate/index';
11
+ export { bb } from './bb.js';
12
+ export { builder, detailBoolean, detailNumber, detailString, input, model, pricing, select, serialise, toggleBoolean, toggleNumber, toggleString } from './entities/index.js';
13
+ export { BuilderException } from './errors/index.js';
14
+ export { ordinal } from './mappers/index.js';
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
+ enable: <const Values extends import("./references").Paramable<import("./public").BuilderCollectionConfig<import("./references").Paramable<import("./entities/model").BuilderModelGeneric>, import("./references").Paramable<number>, import("./references").Paramable<number>>>>(values: Values) => import("./public").BuilderEnableConfig<Values>;
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
+ };
27
+ export declare const has: {
28
+ collection: typeof collectionExpectation;
29
+ component: typeof componentExpectation;
30
+ option: typeof optionExpectation;
31
+ };
32
+ export declare const option: {
33
+ enable: <const Values extends import("./references").Paramable<import("./public").BuilderSelectConfig<readonly [string, ...string[]], import("valibot").GenericSchema<string | null>> | import("./public").BuilderToggleConfig<import("valibot").GenericSchema<string | number | boolean | null>>>>(values: Values) => import("./public").BuilderEnableConfig<Values>;
34
+ match: <const MatchPayload extends import("./references").Paramable<import("./public").BuilderSelectConfig<readonly [string, ...string[]], import("valibot").GenericSchema<string | null>> | import("./public").BuilderToggleConfig<import("valibot").GenericSchema<string | number | boolean | null>>>, const MatchPath extends import("./references").Paramable<import("./public").BuilderPath>, const SelectMap extends import("./references").Paramable<import("./public").BuilderMatchSelectMap<import("./references").Paramable<import("./public").BuilderSelectConfig<readonly [string, ...string[]], import("valibot").GenericSchema<string | null>> | import("./public").BuilderToggleConfig<import("valibot").GenericSchema<string | number | boolean | null>>>>>>(matchPath: MatchPath, selectMap: SelectMap) => import("./public").BuilderMatchConfig<MatchPayload, MatchPath, SelectMap>;
35
+ unless: <const Values extends import("./references").Paramable<import("./public").BuilderSelectConfig<readonly [string, ...string[]], import("valibot").GenericSchema<string | null>> | import("./public").BuilderToggleConfig<import("valibot").GenericSchema<string | number | boolean | null>>>, const UnlessPath extends import("./references").Paramable<import("./public").BuilderPath>>(unlessPath: UnlessPath, disabledValues: import("./primitive").BuilderPrimitives, values: Values) => import("./public").BuilderUnlessConfig<Values, UnlessPath>;
36
+ };
37
+ export declare const ui: typeof uis;
package/dist/public.js ADDED
@@ -0,0 +1,19 @@
1
+ export { bb } from './bb.js';
2
+ export { builder, detailBoolean, detailNumber, detailString, input, model, pricing, select, serialise, toggleBoolean, toggleNumber, toggleString } from './entities/index.js';
3
+ export { BuilderException } from './errors/index.js';
4
+ export { ordinal } from './mappers/index.js';
5
+ export { parameter, ref } from './references.js';
6
+ import { collectionConfig, collectionExpectation, collectionWhen, componentConfig, componentExpectation, componentWhen, optionExpectation, optionWhen, uis } from './entities/index.js';
7
+ export const collection = Object.assign(collectionConfig, {
8
+ ...collectionWhen
9
+ });
10
+ export const component = Object.assign(componentConfig, {
11
+ ...componentWhen
12
+ });
13
+ export const has = {
14
+ collection: collectionExpectation,
15
+ component: componentExpectation,
16
+ option: optionExpectation
17
+ };
18
+ export const option = optionWhen;
19
+ export const ui = uis;
@@ -9,8 +9,8 @@ export declare class BuilderParameter<const Name extends string = string> {
9
9
  export declare const BuilderParameterSchema: v.InstanceSchema<typeof BuilderParameter, undefined>;
10
10
  export declare const BuilderParameterSerialisedSchema: v.SchemaWithPipe<readonly [v.ObjectSchema<{
11
11
  readonly type: v.LiteralSchema<"parameter", undefined>;
12
- readonly id: v.StringSchema<undefined>;
13
- readonly name: v.StringSchema<undefined>;
12
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
13
+ readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
14
14
  }, undefined>, v.ReadonlyAction<{
15
15
  type: "parameter";
16
16
  id: string;
@@ -25,7 +25,7 @@ export declare class BuilderRef {
25
25
  export declare const BuilderRefSchema: v.InstanceSchema<typeof BuilderRef, undefined>;
26
26
  export declare const BuilderRefSerialisedSchema: v.SchemaWithPipe<readonly [v.ObjectSchema<{
27
27
  readonly type: v.LiteralSchema<"ref", undefined>;
28
- readonly id: v.StringSchema<undefined>;
28
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
29
29
  }, undefined>, v.ReadonlyAction<{
30
30
  type: "ref";
31
31
  id: string;
@@ -35,15 +35,15 @@ export declare function parameter<const Name extends string>(name: Name): Builde
35
35
  export declare function ref(id: string): BuilderRef;
36
36
  export declare function paramable<Schema extends v.GenericSchema>(paramable: Schema): v.UnionSchema<[v.SchemaWithPipe<readonly [v.ObjectSchema<{
37
37
  readonly type: v.LiteralSchema<"parameter", undefined>;
38
- readonly id: v.StringSchema<undefined>;
39
- readonly name: v.StringSchema<undefined>;
38
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
39
+ readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
40
40
  }, undefined>, v.ReadonlyAction<{
41
41
  type: "parameter";
42
42
  id: string;
43
43
  name: string;
44
44
  }>]>, v.SchemaWithPipe<readonly [v.ObjectSchema<{
45
45
  readonly type: v.LiteralSchema<"ref", undefined>;
46
- readonly id: v.StringSchema<undefined>;
46
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
47
47
  }, undefined>, v.ReadonlyAction<{
48
48
  type: "ref";
49
49
  id: string;
@@ -1,5 +1,6 @@
1
1
  import * as v from 'valibot';
2
2
  import { check } from './errors/index.js';
3
+ import { IdSchema, NameSchema } from './primitive.js';
3
4
  export class BuilderParameter {
4
5
  id;
5
6
  name;
@@ -9,7 +10,7 @@ export class BuilderParameter {
9
10
  }
10
11
  }
11
12
  export const BuilderParameterSchema = v.instance(BuilderParameter);
12
- export const BuilderParameterSerialisedSchema = v.pipe(v.object({ type: v.literal('parameter'), id: v.string(), name: v.string() }), v.readonly());
13
+ export const BuilderParameterSerialisedSchema = v.pipe(v.object({ type: v.literal('parameter'), id: IdSchema, name: NameSchema }), v.readonly());
13
14
  export class BuilderRef {
14
15
  type = 'ref';
15
16
  id;
@@ -18,7 +19,7 @@ export class BuilderRef {
18
19
  }
19
20
  }
20
21
  export const BuilderRefSchema = v.instance(BuilderRef);
21
- export const BuilderRefSerialisedSchema = v.pipe(v.object({ type: v.literal('ref'), id: v.string() }), v.readonly());
22
+ export const BuilderRefSerialisedSchema = v.pipe(v.object({ type: v.literal('ref'), id: IdSchema }), v.readonly());
22
23
  export function parameter(name) {
23
24
  return new BuilderParameter(name);
24
25
  }
@@ -1,4 +1,4 @@
1
- import { BuilderException, BuilderValidateErrors } from '../errors/index.js';
1
+ import { BuilderException } from '../errors/index.js';
2
2
  const VALIDATED_ENTITIES = new WeakSet();
3
3
  export function validate(value) {
4
4
  VALIDATED_ENTITIES.add(value);
@@ -6,8 +6,6 @@ export function validate(value) {
6
6
  }
7
7
  export function assertValidated(value) {
8
8
  if (typeof value !== 'object' || value === null || !VALIDATED_ENTITIES.has(value)) {
9
- const errors = new BuilderValidateErrors();
10
- errors.unvalidated(value);
11
- throw new BuilderException({ category: 'validation', errors: errors.errors });
9
+ throw new BuilderException({ category: 'invariant', value });
12
10
  }
13
11
  }
@@ -1,4 +1,4 @@
1
1
  import type { BuilderReferences, BuilderValidated, ValidationResult } from '../entities/index';
2
- import { BuilderValidateErrors } from '../errors/index.js';
2
+ import { BuilderErrorsScope } from '../errors/index.js';
3
3
  export type BuilderValidationResult = ValidationResult<BuilderValidated>;
4
- export declare function validateBuilder(input: unknown, references?: BuilderReferences, errors?: BuilderValidateErrors): BuilderValidationResult;
4
+ export declare function validateBuilder(input: unknown, references?: BuilderReferences, errors?: BuilderErrorsScope): BuilderValidationResult;
@@ -1,14 +1,14 @@
1
1
  import { builder, BuilderSerialisedSchema, modelsMerge, serialise } from '../entities/index.js';
2
- import { BuilderValidateErrors, check } from '../errors/index.js';
2
+ import { BuilderErrorsScope, 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 = [], errors = new BuilderValidateErrors()) {
9
+ export function validateBuilder(input, references = [], errors = new BuilderErrorsScope(input)) {
10
10
  if (!check.is(BuilderSerialisedSchema, input)) {
11
- errors.invalidEntity('builder');
11
+ errors.entityInvalid('builder');
12
12
  return [EMPTY_BUILDER, errors.errors];
13
13
  }
14
14
  const resolve = resolver(errors, references, input.bindings);
@@ -1,3 +1,3 @@
1
1
  import type { BuilderExpectationsSerialised, BuilderModelSerialised } from '../entities/index';
2
- import type { BuilderValidateErrors } from '../errors/index';
3
- export declare function checkExpectations(model: BuilderModelSerialised, expectations: BuilderExpectationsSerialised, errors: BuilderValidateErrors): void;
2
+ import type { BuilderErrorsScope } from '../errors/index';
3
+ export declare function checkExpectations(model: BuilderModelSerialised, expectations: BuilderExpectationsSerialised, errors: BuilderErrorsScope): void;
@@ -4,7 +4,7 @@ export function checkExpectations(model, expectations, errors) {
4
4
  if (model[`${kind}s`].some((entry) => entry.name === name)) {
5
5
  return;
6
6
  }
7
- errors.unmetExpectation(kind, name);
7
+ errors.modelUnmetExpectation();
8
8
  });
9
9
  });
10
10
  }
@@ -1,5 +1,4 @@
1
1
  export type { BuilderValidatedMap, ValidationResult } from '../entities/index';
2
- export type { BuilderErrorKind, BuilderValidateErrors } from '../errors/index';
3
2
  export type { BuilderValidatedBrand } from './brand';
4
3
  export type { BuilderValidationResult } from './builder';
5
4
  export type { BuilderInstanceValidationResult } from './instance';
@@ -1,5 +1,5 @@
1
1
  import type { BuilderInstanceValidated, BuilderModelValidated, ValidationResult } from '../entities/index';
2
2
  import type { BuilderInstance } from '../instance';
3
- import { BuilderValidateErrors } from '../errors/index.js';
3
+ import { BuilderErrorsScope } from '../errors/index.js';
4
4
  export type BuilderInstanceValidationResult = ValidationResult<BuilderInstanceValidated>;
5
- export declare function validateInstance(model: BuilderModelValidated, instance: BuilderInstance, errors?: BuilderValidateErrors): BuilderInstanceValidationResult;
5
+ export declare function validateInstance(model: BuilderModelValidated, instance: BuilderInstance, errors?: BuilderErrorsScope): BuilderInstanceValidationResult;
@@ -1,14 +1,14 @@
1
1
  import { optionValueSchema } from '../entities/index.js';
2
- import { BuilderValidateErrors, check } from '../errors/index.js';
2
+ import { BuilderErrorsScope, 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, errors = new BuilderValidateErrors()) {
6
+ export function validateInstance(model, instance, errors = new BuilderErrorsScope(instance)) {
7
7
  errors.scope('instance', () => {
8
8
  checkInstance(model, instance);
9
9
  });
10
10
  return [validate(instance), errors.errors];
11
- function checkInstance(scopeModel, scopeInstance, namePrefix = '') {
11
+ function checkInstance(scopeModel, scopeInstance) {
12
12
  scopeModel.options.forEach((option) => {
13
13
  const { name } = option;
14
14
  const payload = resolveOption(option, scopeModel, scopeInstance);
@@ -18,7 +18,7 @@ export function validateInstance(model, instance, errors = new BuilderValidateEr
18
18
  const value = scopeInstance[name];
19
19
  if (!check.is(optionValueSchema(payload), value)) {
20
20
  errors.scope(name, () => {
21
- errors.invalidOption(`${namePrefix}${name}`, value);
21
+ errors.instanceInvalidOption();
22
22
  });
23
23
  }
24
24
  });
@@ -31,14 +31,14 @@ export function validateInstance(model, instance, errors = new BuilderValidateEr
31
31
  const existing = scopeInstance[name];
32
32
  if (!check.is(BuilderInstancesSchema, existing)) {
33
33
  errors.scope(name, () => {
34
- errors.invalidCollection(`${namePrefix}${name}`);
34
+ errors.instanceInvalidCollection();
35
35
  });
36
36
  return;
37
37
  }
38
38
  errors.scope(name, () => {
39
39
  existing.forEach((itemInstance, index) => {
40
40
  errors.scope(index, () => {
41
- checkInstance(payload.model, itemInstance, `${namePrefix}${name}[${index}].`);
41
+ checkInstance(payload.model, itemInstance);
42
42
  });
43
43
  });
44
44
  });
@@ -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 { BuilderValidateErrors } from '../errors/index.js';
4
+ import { BuilderErrorsScope } from '../errors/index.js';
5
5
  export type BuilderModelValidationResult = ValidationResult<BuilderModelValidated>;
6
- export declare function validateModel(input: unknown, references?: BuilderReferences, errors?: BuilderValidateErrors): BuilderModelValidationResult;
7
- export declare function checkModelExpectations(mergedModel: BuilderModelSerialised, rootModel: BuilderModelSerialised, errors: BuilderValidateErrors): void;
8
- export declare function validateModelStructure(input: ParamableSerialised<BuilderModelSerialised>, resolve: BuilderResolve, errors: BuilderValidateErrors): BuilderModelValidated;
6
+ export declare function validateModel(input: unknown, references?: BuilderReferences, errors?: BuilderErrorsScope): BuilderModelValidationResult;
7
+ export declare function checkModelExpectations(mergedModel: BuilderModelSerialised, rootModel: BuilderModelSerialised, errors: BuilderErrorsScope): void;
8
+ export declare function validateModelStructure(input: ParamableSerialised<BuilderModelSerialised>, resolve: BuilderResolve, errors: BuilderErrorsScope): BuilderModelValidated;
@@ -1,19 +1,21 @@
1
- import { BuilderCollectionConfigSerialisedSchema, BuilderComponentConfigSerialisedSchema, BuilderModelSerialisedSchema, BuilderOptionConfigSerialisedSchema, BuilderWhenSerialisedSchema, whenBranches, model, modelsMerge, serialise, validateCollectionConfig, validateComponentConfig, validateSelect, validateToggle } from '../entities/index.js';
2
- import { BuilderValidateErrors, check } from '../errors/index.js';
1
+ import * as v from 'valibot';
2
+ import { BuilderCollectionConfigSerialisedSchema, BuilderComponentConfigSerialisedSchema, BuilderModelSerialisedSchema, BuilderOptionConfigSerialisedSchema, BuilderPathsSchema, BuilderWhenSerialisedSchema, whenBranches, model, modelsMerge, serialise, validateCollectionConfig, validateComponentConfig, validateSelect, validateToggle } from '../entities/index.js';
3
+ import { BuilderErrorsScope, check } from '../errors/index.js';
3
4
  import { isParamable } from '../references.js';
4
5
  import { validate } from './brand.js';
5
6
  import { checkExpectations } from './expectations.js';
6
7
  import { checkPath } from './paths.js';
7
8
  import { resolver } from './resolve.js';
8
9
  const EMPTY_MODEL = validate(serialise.model(model()));
9
- export function validateModel(input, references = [], errors = new BuilderValidateErrors()) {
10
+ export function validateModel(input, references = [], errors = new BuilderErrorsScope(input)) {
10
11
  if (!check.is(BuilderModelSerialisedSchema, input)) {
11
- errors.invalidEntity('model');
12
+ errors.entityInvalid('model');
12
13
  return [EMPTY_MODEL, errors.errors];
13
14
  }
14
15
  const resolve = resolver(errors, references);
15
16
  const structure = validateModelStructure(input, resolve, errors);
16
- const data = validate(modelsMerge(structure));
17
+ const merged = modelsMerge(structure);
18
+ const data = validate(merged);
17
19
  checkModelExpectations(data, structure, errors);
18
20
  return [data, errors.errors];
19
21
  }
@@ -33,111 +35,137 @@ export function checkModelExpectations(mergedModel, rootModel, errors) {
33
35
  }
34
36
  }
35
37
  export function validateModelStructure(input, resolve, errors) {
36
- const resolved = resolve(input);
37
- if (!check.is(BuilderModelSerialisedSchema, resolved)) {
38
- return validate(serialise.model(model()));
39
- }
40
- const modelInput = resolved;
41
- const skipPathValidation = modelInput.expectations.length > 0;
42
- const childModels = errors.scope('models', () => modelInput.models.flatMap((part, partIndex) => errors.scope(partIndex, () => [validateModelStructure(part, resolve, errors)])));
43
- const options = errors.scope('options', () => walkEntries(modelInput.options, (resolved) => {
44
- whenBranches(resolved.payload, BuilderOptionConfigSerialisedSchema)
45
- .filter((config) => !isParamable(config))
46
- .forEach((config) => {
47
- if (config.type === 'select') {
48
- validateSelect(config, [], errors);
49
- }
50
- else if (config.type === 'toggle') {
51
- validateToggle(config, [], errors);
52
- }
53
- });
54
- }));
55
- const components = errors.scope('components', () => walkEntries(modelInput.components, (resolved) => {
56
- whenBranches(resolved.payload, BuilderComponentConfigSerialisedSchema)
57
- .filter((config) => !isParamable(config))
58
- .forEach((config) => {
59
- validateComponentConfig(config, [], errors);
60
- });
61
- }));
62
- const collections = errors.scope('collections', () => walkEntries(modelInput.collections, (resolved) => {
63
- whenBranches(resolved.payload, BuilderCollectionConfigSerialisedSchema)
64
- .filter((config) => !isParamable(config))
65
- .forEach((config) => {
66
- validateCollectionConfig(config, [], errors);
67
- });
68
- }));
69
- return {
70
- ...modelInput,
71
- models: childModels,
72
- options,
73
- components,
74
- collections
38
+ const seenGlobal = {
39
+ option: new Set(),
40
+ component: new Set(),
41
+ collection: new Set()
75
42
  };
76
- function walkEntries(entries, validateBranches) {
77
- const seen = new Set();
78
- const items = [];
79
- entries.forEach((entry, entryIndex) => {
80
- errors.scope(entryIndex, () => {
81
- const resolved = resolveEntry(entry, seen);
82
- if (resolved == null) {
83
- return;
43
+ return walkStructure(input);
44
+ function walkStructure(input) {
45
+ const resolved = resolve(input, BuilderModelSerialisedSchema);
46
+ if (resolved == null) {
47
+ return validate(serialise.model(model()));
48
+ }
49
+ const modelInput = resolved;
50
+ const skipPathValidation = modelInput.expectations.length > 0;
51
+ const childModels = errors.scope('models', () => modelInput.models.flatMap((part, partIndex) => errors.scope(partIndex, () => [walkStructure(part)])));
52
+ const options = errors.scope('options', () => walkEntries(modelInput.options, 'option', (resolved) => {
53
+ whenBranches(resolved.payload, BuilderOptionConfigSerialisedSchema)
54
+ .filter((config) => !isParamable(config))
55
+ .forEach((config) => {
56
+ if (config.type === 'select') {
57
+ validateSelect(config, [], errors);
58
+ }
59
+ else if (config.type === 'toggle') {
60
+ validateToggle(config, [], errors);
84
61
  }
85
- validateBranches(resolved);
86
- items.push(resolved);
87
62
  });
88
- });
89
- return items;
90
- }
91
- function resolveEntry(entry, seen) {
92
- let paths = entry.paths;
93
- if (entry.paths != null) {
94
- const resolvedPaths = errors.scope('paths', () => resolve(entry.paths));
95
- paths = resolvedPaths ?? entry.paths;
96
- }
97
- const payload = errors.scope('payload', () => resolve(entry.payload));
98
- const resolvedEntry = { ...entry, paths, payload: payload ?? entry.payload };
99
- if (seen.has(resolvedEntry.name)) {
100
- errors.duplicateName(resolvedEntry.name);
101
- return null;
102
- }
103
- seen.add(resolvedEntry.name);
104
- checkPaths(resolvedEntry);
105
- return resolvedEntry;
106
- }
107
- function checkPaths(entry) {
108
- if (skipPathValidation) {
109
- return;
110
- }
111
- const { paths, payload } = entry;
112
- if (Array.isArray(paths)) {
113
- errors.scope('paths', () => {
114
- paths.forEach((path, pathIndex) => {
115
- errors.scope(pathIndex, () => {
116
- checkPath(modelInput, path, errors);
117
- });
118
- });
63
+ }));
64
+ const components = errors.scope('components', () => walkEntries(modelInput.components, 'component', (resolved) => {
65
+ whenBranches(resolved.payload, BuilderComponentConfigSerialisedSchema)
66
+ .filter((config) => !isParamable(config))
67
+ .forEach((config) => {
68
+ validateComponentConfig(config, [], errors);
119
69
  });
70
+ }));
71
+ const collections = errors.scope('collections', () => walkEntries(modelInput.collections, 'collection', (resolved) => {
72
+ whenBranches(resolved.payload, BuilderCollectionConfigSerialisedSchema)
73
+ .filter((config) => !isParamable(config))
74
+ .forEach((config) => {
75
+ validateCollectionConfig(config, [], errors);
76
+ });
77
+ }));
78
+ return {
79
+ ...modelInput,
80
+ models: childModels,
81
+ options,
82
+ components,
83
+ collections
84
+ };
85
+ function payloadSchemaFor(kind) {
86
+ if (kind === 'option') {
87
+ return BuilderOptionConfigSerialisedSchema;
88
+ }
89
+ if (kind === 'component') {
90
+ return BuilderComponentConfigSerialisedSchema;
91
+ }
92
+ return BuilderCollectionConfigSerialisedSchema;
120
93
  }
121
- checkWhenPaths(payload);
122
- }
123
- function checkWhenPaths(payload) {
124
- if (!check.is(BuilderWhenSerialisedSchema, payload)) {
125
- return;
126
- }
127
- if (payload.type === 'match' && Array.isArray(payload.matchPath)) {
128
- errors.scope('payload', () => {
129
- errors.scope('matchPath', () => {
130
- checkPath(modelInput, payload.matchPath, errors);
94
+ function walkEntries(entries, kind, validateBranches) {
95
+ const seenLocal = new Set();
96
+ const items = [];
97
+ entries.forEach((entry, entryIndex) => {
98
+ errors.scope(entryIndex, () => {
99
+ const resolved = resolveEntry(entry, seenLocal, kind);
100
+ if (resolved == null) {
101
+ return;
102
+ }
103
+ validateBranches(resolved);
104
+ items.push(resolved);
131
105
  });
132
106
  });
133
- return;
107
+ return items;
134
108
  }
135
- if (payload.type === 'unless' && Array.isArray(payload.unlessPath)) {
136
- errors.scope('payload', () => {
137
- errors.scope('unlessPath', () => {
138
- checkPath(modelInput, payload.unlessPath, errors);
109
+ function resolveEntry(entry, seenLocal, kind) {
110
+ let paths = entry.paths;
111
+ if (entry.paths != null) {
112
+ const resolvedPaths = errors.scope('paths', () => resolve(entry.paths, BuilderPathsSchema));
113
+ paths = resolvedPaths ?? entry.paths;
114
+ }
115
+ const payloadSchema = v.union([payloadSchemaFor(kind), BuilderWhenSerialisedSchema]);
116
+ const payload = errors.scope('payload', () => resolve(entry.payload, payloadSchema));
117
+ const resolvedEntry = { ...entry, paths, payload: payload ?? entry.payload };
118
+ if (seenLocal.has(resolvedEntry.name)) {
119
+ if (kind === 'option') {
120
+ errors.modelDuplicateOption();
121
+ }
122
+ else if (kind === 'component') {
123
+ errors.modelDuplicateComponent();
124
+ }
125
+ else {
126
+ errors.modelDuplicateCollection();
127
+ }
128
+ return null;
129
+ }
130
+ if (seenGlobal[kind].has(resolvedEntry.name)) {
131
+ if (kind === 'option') {
132
+ errors.modelOverriddenOption();
133
+ }
134
+ else if (kind === 'component') {
135
+ errors.modelOverriddenComponent();
136
+ }
137
+ else {
138
+ errors.modelOverriddenCollection();
139
+ }
140
+ }
141
+ seenLocal.add(resolvedEntry.name);
142
+ seenGlobal[kind].add(resolvedEntry.name);
143
+ checkPaths(resolvedEntry);
144
+ return resolvedEntry;
145
+ }
146
+ function checkPaths(entry) {
147
+ if (skipPathValidation) {
148
+ return;
149
+ }
150
+ const { paths, payload } = entry;
151
+ if (Array.isArray(paths)) {
152
+ errors.scope('paths', () => {
153
+ paths.forEach((path, pathIndex) => {
154
+ errors.scope(pathIndex, () => {
155
+ checkPath(modelInput, path, errors);
156
+ });
157
+ });
139
158
  });
140
- });
159
+ }
160
+ if (!check.is(BuilderWhenSerialisedSchema, payload)) {
161
+ return;
162
+ }
163
+ if (payload.type === 'match' && Array.isArray(payload.matchPath)) {
164
+ errors.scope('payload', () => errors.scope('matchPath', () => checkPath(modelInput, payload.matchPath, errors)));
165
+ }
166
+ if (payload.type === 'unless' && Array.isArray(payload.unlessPath)) {
167
+ errors.scope('payload', () => errors.scope('unlessPath', () => checkPath(modelInput, payload.unlessPath, errors)));
168
+ }
141
169
  }
142
170
  }
143
171
  }
@@ -1,3 +1,3 @@
1
1
  import type { BuilderModelSerialised, BuilderPath } from '../entities/index';
2
- import type { BuilderValidateErrors } from '../errors/index';
3
- export declare function checkPath(model: BuilderModelSerialised, path: BuilderPath, errors: BuilderValidateErrors): void;
2
+ import type { BuilderErrorsScope } from '../errors/index';
3
+ export declare function checkPath(model: BuilderModelSerialised, path: BuilderPath, errors: BuilderErrorsScope): void;