@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.
Files changed (132) hide show
  1. package/dist/bb.js +9 -10
  2. package/dist/client/client.d.ts +2 -1
  3. package/dist/client/client.js +4 -1
  4. package/dist/client/public.d.ts +2 -2
  5. package/dist/client/public.js +1 -1
  6. package/dist/client/schema.d.ts +126 -45
  7. package/dist/client/schema.js +6 -1
  8. package/dist/components/BuilderOption.svelte.d.ts +12 -12
  9. package/dist/components/BuilderOptionValueBoolean.svelte.d.ts +20 -0
  10. package/dist/components/BuilderOptionValueNumber.svelte.d.ts +21 -0
  11. package/dist/components/BuilderOptionValueSelect.svelte.d.ts +21 -0
  12. package/dist/components/BuilderOptionValueString.svelte.d.ts +21 -0
  13. package/dist/components/BuilderRender.svelte.d.ts +2 -2
  14. package/dist/components/index.d.ts +8 -8
  15. package/dist/components/index.js +4376 -4258
  16. package/dist/components/index.min.js +3 -0
  17. package/dist/entities/collection/collection.d.ts +191 -401
  18. package/dist/entities/collection/collection.js +7 -4
  19. package/dist/entities/collection/{when.d.ts → condition.d.ts} +4 -5
  20. package/dist/entities/collection/condition.js +2 -0
  21. package/dist/entities/collection/config.d.ts +62 -80
  22. package/dist/entities/collection/index.d.ts +4 -4
  23. package/dist/entities/collection/index.js +2 -2
  24. package/dist/entities/component/component.d.ts +71 -83
  25. package/dist/entities/component/component.js +4 -4
  26. package/dist/entities/component/condition.d.ts +10 -0
  27. package/dist/entities/component/{when.js → condition.js} +3 -9
  28. package/dist/entities/component/config.d.ts +33 -33
  29. package/dist/entities/component/config.js +18 -16
  30. package/dist/entities/component/detail.d.ts +61 -0
  31. package/dist/entities/component/detail.js +71 -0
  32. package/dist/entities/component/index.d.ts +6 -6
  33. package/dist/entities/component/index.js +3 -3
  34. package/dist/entities/{when.d.ts → condition.d.ts} +23 -36
  35. package/dist/entities/{when.js → condition.js} +20 -25
  36. package/dist/entities/expectation.d.ts +135 -3
  37. package/dist/entities/expectation.js +6 -2
  38. package/dist/entities/index.d.ts +9 -9
  39. package/dist/entities/index.js +4 -4
  40. package/dist/entities/kind.d.ts +4 -4
  41. package/dist/entities/kind.js +24 -25
  42. package/dist/entities/model/bind.d.ts +5 -5
  43. package/dist/entities/model/methods.d.ts +18 -27
  44. package/dist/entities/model/methods.js +4 -22
  45. package/dist/entities/model/model.d.ts +3 -1
  46. package/dist/entities/model/model.js +25 -27
  47. package/dist/entities/option/condition.d.ts +9 -0
  48. package/dist/entities/option/condition.js +2 -0
  49. package/dist/entities/option/config.d.ts +47 -72
  50. package/dist/entities/option/config.js +6 -6
  51. package/dist/entities/option/expectation.d.ts +6 -1
  52. package/dist/entities/option/expectation.js +2 -2
  53. package/dist/entities/option/index.d.ts +8 -8
  54. package/dist/entities/option/index.js +4 -4
  55. package/dist/entities/option/option.d.ts +179 -210
  56. package/dist/entities/option/option.js +4 -4
  57. package/dist/entities/option/select.d.ts +16 -43
  58. package/dist/entities/option/select.js +8 -31
  59. package/dist/entities/option/value.d.ts +73 -0
  60. package/dist/entities/option/value.js +99 -0
  61. package/dist/entities/paths.d.ts +2 -2
  62. package/dist/entities/pricing/expression.d.ts +16 -39
  63. package/dist/entities/pricing/expression.js +1 -16
  64. package/dist/entities/pricing/index.d.ts +1 -1
  65. package/dist/entities/pricing/rates.d.ts +1 -1
  66. package/dist/entities/references.d.ts +124 -84
  67. package/dist/entities/serialise.d.ts +175 -109
  68. package/dist/entities/serialise.js +32 -27
  69. package/dist/entities/ui/describe.d.ts +1 -1
  70. package/dist/entities/ui/input.d.ts +2 -2
  71. package/dist/entities/ui/page.d.ts +1 -1
  72. package/dist/entities/ui/pages.d.ts +2 -2
  73. package/dist/entities/validated.d.ts +3 -3
  74. package/dist/environment.d.ts +2 -2
  75. package/dist/errors/errors.d.ts +94 -58
  76. package/dist/errors/errors.js +41 -7
  77. package/dist/errors/exception.d.ts +3 -3
  78. package/dist/errors/index.d.ts +1 -1
  79. package/dist/errors/index.js +1 -1
  80. package/dist/errors/public.d.ts +1 -1
  81. package/dist/index.d.ts +1 -1
  82. package/dist/index.js +1 -1
  83. package/dist/instance.d.ts +53 -9
  84. package/dist/instance.js +6 -2
  85. package/dist/mappers/dependencies.d.ts +3 -0
  86. package/dist/mappers/dependencies.js +45 -0
  87. package/dist/mappers/index.d.ts +2 -2
  88. package/dist/mappers/index.js +2 -1
  89. package/dist/mappers/instance.js +26 -21
  90. package/dist/mappers/price.js +6 -4
  91. package/dist/mappers/resolve.js +23 -22
  92. package/dist/mappers/variants/index.d.ts +1 -2
  93. package/dist/mappers/variants/index.js +1 -2
  94. package/dist/mappers/variants/option-graph.d.ts +1 -2
  95. package/dist/mappers/variants/option-graph.js +4 -18
  96. package/dist/mappers/variants/variants.d.ts +3 -6
  97. package/dist/mappers/variants/variants.js +34 -11
  98. package/dist/primitive.d.ts +3 -0
  99. package/dist/primitive.js +2 -0
  100. package/dist/public.d.ts +20 -20
  101. package/dist/public.js +17 -9
  102. package/dist/validate/builder.d.ts +2 -2
  103. package/dist/validate/builder.js +15 -15
  104. package/dist/validate/expectations.d.ts +2 -2
  105. package/dist/validate/expectations.js +23 -5
  106. package/dist/validate/instance.d.ts +2 -2
  107. package/dist/validate/instance.js +31 -13
  108. package/dist/validate/model.d.ts +4 -4
  109. package/dist/validate/model.js +57 -51
  110. package/dist/validate/paths.d.ts +2 -2
  111. package/dist/validate/paths.js +19 -14
  112. package/dist/validate/pricing.d.ts +4 -4
  113. package/dist/validate/pricing.js +31 -31
  114. package/dist/validate/resolve.d.ts +2 -2
  115. package/dist/validate/resolve.js +27 -31
  116. package/dist/validate/ui.d.ts +4 -4
  117. package/dist/validate/ui.js +38 -38
  118. package/dist/validate/variants.d.ts +3 -3
  119. package/dist/validate/variants.js +32 -31
  120. package/package.json +4 -2
  121. package/dist/components/BuilderOptionSelect.svelte.d.ts +0 -21
  122. package/dist/components/BuilderOptionToggleBoolean.svelte.d.ts +0 -20
  123. package/dist/components/BuilderOptionToggleNumber.svelte.d.ts +0 -21
  124. package/dist/components/BuilderOptionToggleString.svelte.d.ts +0 -21
  125. package/dist/entities/collection/when.js +0 -2
  126. package/dist/entities/component/field.d.ts +0 -59
  127. package/dist/entities/component/field.js +0 -52
  128. package/dist/entities/component/when.d.ts +0 -11
  129. package/dist/entities/option/toggle.d.ts +0 -45
  130. package/dist/entities/option/toggle.js +0 -66
  131. package/dist/entities/option/when.d.ts +0 -10
  132. package/dist/entities/option/when.js +0 -2
@@ -1,7 +1,7 @@
1
1
  import type { BuilderModelSerialised, BuilderPricingSerialised, BuilderPricingValidated, BuilderReferences, ValidationResult } from '../entities/index';
2
2
  import type { BuilderResolve } from './resolve';
3
- import { BuilderErrorsScope } from '../errors/index.js';
3
+ import { BuilderIssuesScope } from '../errors/index.js';
4
4
  export type BuilderPricingValidationResult = ValidationResult<BuilderPricingValidated>;
5
- export declare function validatePricing(input: unknown, references?: BuilderReferences, errors?: BuilderErrorsScope): BuilderPricingValidationResult;
6
- export declare function validatePricingStructure(input: BuilderPricingSerialised, resolve: BuilderResolve, errors: BuilderErrorsScope): BuilderPricingSerialised;
7
- export declare function checkPricingExpectations(model: BuilderModelSerialised, pricing: BuilderPricingSerialised, errors: BuilderErrorsScope): void;
5
+ export declare function validatePricing(input: unknown, references?: BuilderReferences, issues?: BuilderIssuesScope): BuilderPricingValidationResult;
6
+ export declare function validatePricingStructure(input: BuilderPricingSerialised, resolve: BuilderResolve, issues: BuilderIssuesScope): BuilderPricingSerialised;
7
+ export declare function checkPricingExpectations(model: BuilderModelSerialised, pricing: BuilderPricingSerialised, issues: BuilderIssuesScope): void;
@@ -1,25 +1,25 @@
1
1
  import { BuilderPricingExpressionSchema, BuilderPricingSerialisedSchema, BuilderRatesSchema, pricing, serialise } from '../entities/index.js';
2
- import { BuilderErrorsScope, check } from '../errors/index.js';
2
+ import { BuilderIssuesScope, check } from '../errors/index.js';
3
3
  import { NumberSchema } from '../primitive.js';
4
4
  import { validate } from './brand.js';
5
5
  import { resolver } from './resolve.js';
6
6
  const EMPTY_PRICING = validate(serialise.pricing(pricing()));
7
- export function validatePricing(input, references = [], errors = new BuilderErrorsScope(input)) {
7
+ export function validatePricing(input, references = [], issues = new BuilderIssuesScope(input)) {
8
8
  if (!check.is(BuilderPricingSerialisedSchema, input)) {
9
- errors.entityInvalid('pricing');
10
- return [EMPTY_PRICING, errors.errors];
9
+ issues.entityInvalid('pricing');
10
+ return [EMPTY_PRICING, issues.errors, issues.warnings];
11
11
  }
12
- const resolve = resolver(errors, references);
13
- const structure = validatePricingStructure(input, resolve, errors);
14
- return [validate(structure), errors.errors];
12
+ const resolve = resolver(issues, references);
13
+ const structure = validatePricingStructure(input, resolve, issues);
14
+ return [validate(structure), issues.errors, issues.warnings];
15
15
  }
16
- export function validatePricingStructure(input, resolve, errors) {
17
- const rates = errors.scope('rates', () => input.rates.flatMap((entry, index) => {
16
+ export function validatePricingStructure(input, resolve, issues) {
17
+ const rates = issues.scope('rates', () => input.rates.flatMap((entry, index) => {
18
18
  const resolved = resolve(entry, BuilderRatesSchema);
19
19
  if (resolved != null) {
20
20
  return [resolved];
21
21
  }
22
- errors.scope(index, () => errors.pricingInvalidRateValue());
22
+ issues.scope(index, () => issues.pricingInvalidRateValue());
23
23
  return [];
24
24
  }));
25
25
  const formula = input.formula == null ? null : resolveExpression(input.formula);
@@ -30,7 +30,7 @@ export function validatePricingStructure(input, resolve, errors) {
30
30
  function resolveExpression(input) {
31
31
  const resolved = resolve(input, BuilderPricingExpressionSchema);
32
32
  if (resolved == null) {
33
- errors.pricingMalformedExpression();
33
+ issues.pricingMalformedExpression();
34
34
  return null;
35
35
  }
36
36
  if (check.is(NumberSchema, resolved)) {
@@ -40,11 +40,11 @@ export function validatePricingStructure(input, resolve, errors) {
40
40
  return resolved;
41
41
  }
42
42
  if (resolved.kind === 'variants') {
43
- const inner = errors.scope('expression', () => resolveExpression(resolved.expression));
43
+ const inner = issues.scope('expression', () => resolveExpression(resolved.expression));
44
44
  return { ...resolved, expression: inner ?? resolved.expression };
45
45
  }
46
- const left = errors.scope('left', () => resolveExpression(resolved.left));
47
- const right = errors.scope('right', () => resolveExpression(resolved.right));
46
+ const left = issues.scope('left', () => resolveExpression(resolved.left));
47
+ const right = issues.scope('right', () => resolveExpression(resolved.right));
48
48
  return { ...resolved, left: left ?? resolved.left, right: right ?? resolved.right };
49
49
  }
50
50
  function walkExpression(expression, insideVariants) {
@@ -54,33 +54,33 @@ export function validatePricingStructure(input, resolve, errors) {
54
54
  switch (expression.kind) {
55
55
  case 'variantPrice':
56
56
  if (!insideVariants) {
57
- errors.pricingInvalidScope();
57
+ issues.pricingInvalidScope();
58
58
  }
59
59
  return;
60
60
  case 'lookup':
61
- errors.scope('lookup', () => {
61
+ issues.scope('lookup', () => {
62
62
  if (rates.length === 0) {
63
- errors.pricingEmptyRates();
63
+ issues.pricingEmptyRates();
64
64
  }
65
65
  else {
66
66
  const exists = rates.some((entry) => entry[expression.rate] != null);
67
67
  if (!exists) {
68
- errors.pricingMissingRate();
68
+ issues.pricingMissingRate();
69
69
  }
70
70
  }
71
71
  if (!insideVariants) {
72
- errors.pricingInvalidScope();
72
+ issues.pricingInvalidScope();
73
73
  }
74
74
  });
75
75
  return;
76
76
  case 'variants':
77
- errors.scope('variants', () => {
77
+ issues.scope('variants', () => {
78
78
  if (insideVariants) {
79
- errors.pricingNestedVariants();
79
+ issues.pricingNestedVariants();
80
80
  }
81
81
  const inner = expression.expression;
82
82
  check.assert(BuilderPricingExpressionSchema, inner);
83
- errors.scope('expression', () => walkExpression(inner, true));
83
+ issues.scope('expression', () => walkExpression(inner, true));
84
84
  });
85
85
  return;
86
86
  case 'add':
@@ -91,16 +91,16 @@ export function validatePricingStructure(input, resolve, errors) {
91
91
  check.assert(BuilderPricingExpressionSchema, left);
92
92
  check.assert(BuilderPricingExpressionSchema, right);
93
93
  if (expression.kind === 'div' && check.is(NumberSchema, right) && right === 0) {
94
- errors.pricingDivideByZero();
94
+ issues.pricingDivideByZero();
95
95
  }
96
- errors.scope('left', () => walkExpression(left, insideVariants));
97
- errors.scope('right', () => walkExpression(right, insideVariants));
96
+ issues.scope('left', () => walkExpression(left, insideVariants));
97
+ issues.scope('right', () => walkExpression(right, insideVariants));
98
98
  return;
99
99
  }
100
100
  }
101
101
  }
102
102
  }
103
- export function checkPricingExpectations(model, pricing, errors) {
103
+ export function checkPricingExpectations(model, pricing, issues) {
104
104
  if (pricing.formula == null) {
105
105
  return;
106
106
  }
@@ -115,21 +115,21 @@ export function checkPricingExpectations(model, pricing, errors) {
115
115
  }
116
116
  switch (expression.kind) {
117
117
  case 'lookup':
118
- errors.scope('lookup', () => {
118
+ issues.scope('lookup', () => {
119
119
  if (expression.key.kind === 'option' && !optionNames.has(expression.key.name)) {
120
- errors.pricingMissingOption();
120
+ issues.pricingMissingOption();
121
121
  }
122
122
  });
123
123
  return;
124
124
  case 'variants':
125
- errors.scope('variants', () => errors.scope('expression', () => walkExpression(expression.expression)));
125
+ issues.scope('variants', () => issues.scope('expression', () => walkExpression(expression.expression)));
126
126
  return;
127
127
  case 'add':
128
128
  case 'sub':
129
129
  case 'mul':
130
130
  case 'div':
131
- errors.scope('left', () => walkExpression(expression.left));
132
- errors.scope('right', () => walkExpression(expression.right));
131
+ issues.scope('left', () => walkExpression(expression.left));
132
+ issues.scope('right', () => walkExpression(expression.right));
133
133
  return;
134
134
  default:
135
135
  return;
@@ -1,5 +1,5 @@
1
1
  import type { BuilderBindings, BuilderReferences } from '../entities/index';
2
- import type { BuilderErrorsScope } from '../errors/index';
2
+ import type { BuilderIssuesScope } from '../errors/index';
3
3
  import * as v from 'valibot';
4
4
  export type BuilderResolve = <S extends v.GenericSchema = v.GenericSchema<unknown>>(value: unknown, schema?: S) => v.InferOutput<S> | null;
5
- export declare function resolver(errors: BuilderErrorsScope, references?: BuilderReferences, bindings?: BuilderBindings): BuilderResolve;
5
+ export declare function resolver(issues: BuilderIssuesScope, references?: BuilderReferences, bindings?: BuilderBindings): BuilderResolve;
@@ -1,19 +1,19 @@
1
1
  import * as v from 'valibot';
2
- import { BuilderCollectionConfigSerialisedSchema, BuilderModelSerialisedSchema, BuilderPathSchema, BuilderWhenSerialisedSchema } from '../entities/index.js';
2
+ import { BuilderCollectionConfigSerialisedSchema, BuilderModelSerialisedSchema, BuilderPathSchema, BuilderConditionSerialisedSchema } from '../entities/index.js';
3
3
  import { check } from '../errors/index.js';
4
4
  import { NumberSchema, StringSchema } from '../primitive.js';
5
5
  import { BuilderParameterSerialisedSchema, BuilderRefSerialisedSchema } from '../references.js';
6
6
  import { validateModelStructure } from './model.js';
7
- export function resolver(errors, references = [], bindings = {}) {
7
+ export function resolver(issues, references = [], bindings = {}) {
8
8
  const resolving = new Set();
9
9
  function resolve(value, schema = v.unknown()) {
10
- const errorsBefore = errors.errors.length;
10
+ const errorsBefore = issues.errors.length;
11
11
  const resolved = dispatch(value, schema);
12
12
  if (check.is(schema, resolved)) {
13
13
  return resolved;
14
14
  }
15
- if (errors.errors.length === errorsBefore) {
16
- errors.referenceInvalid();
15
+ if (issues.errors.length === errorsBefore) {
16
+ issues.referenceInvalid();
17
17
  }
18
18
  return null;
19
19
  }
@@ -24,8 +24,8 @@ export function resolver(errors, references = [], bindings = {}) {
24
24
  if (check.is(BuilderRefSerialisedSchema, value)) {
25
25
  return resolveReference(value, schema);
26
26
  }
27
- if (check.is(BuilderWhenSerialisedSchema, value)) {
28
- return resolveWhen(value, schema);
27
+ if (check.is(BuilderConditionSerialisedSchema, value)) {
28
+ return resolveCondition(value, schema);
29
29
  }
30
30
  if (check.is(BuilderCollectionConfigSerialisedSchema, value)) {
31
31
  return resolveCollectionConfig(value);
@@ -34,12 +34,12 @@ export function resolver(errors, references = [], bindings = {}) {
34
34
  }
35
35
  function resolveReference(reference, schema) {
36
36
  if (resolving.has(reference.id)) {
37
- errors.referenceCircular();
37
+ issues.referenceCircular();
38
38
  return reference;
39
39
  }
40
40
  const found = references.find((entry) => entry.id === reference.id);
41
41
  if (found == null) {
42
- errors.referenceMissing();
42
+ issues.referenceMissing();
43
43
  return reference;
44
44
  }
45
45
  resolving.add(reference.id);
@@ -52,7 +52,7 @@ export function resolver(errors, references = [], bindings = {}) {
52
52
  }
53
53
  function resolveParameter(parameter, schema) {
54
54
  if (!(parameter.name in bindings)) {
55
- errors.referenceUnboundParameter();
55
+ issues.referenceUnboundParameter();
56
56
  return null;
57
57
  }
58
58
  const binding = bindings[parameter.name];
@@ -61,45 +61,41 @@ export function resolver(errors, references = [], bindings = {}) {
61
61
  }
62
62
  return resolveReference(binding, schema);
63
63
  }
64
- function resolveWhen(when, payloadSchema) {
65
- if (when.type === 'enable') {
66
- const payload = errors.scope('payload', () => resolve(when.payload, payloadSchema));
67
- return { ...when, payload: payload ?? when.payload };
68
- }
69
- if (when.type === 'unless') {
70
- const unlessPath = errors.scope('unlessPath', () => resolve(when.unlessPath, BuilderPathSchema));
71
- const payload = errors.scope('payload', () => resolve(when.payload, payloadSchema));
64
+ function resolveCondition(condition, payloadSchema) {
65
+ if (condition.type === 'unless') {
66
+ const unlessPath = issues.scope('unlessPath', () => resolve(condition.unlessPath, BuilderPathSchema));
67
+ const payload = issues.scope('payload', () => resolve(condition.payload, payloadSchema));
72
68
  return {
73
- ...when,
74
- unlessPath: unlessPath ?? when.unlessPath,
75
- payload: payload ?? when.payload
69
+ ...condition,
70
+ unlessPath: unlessPath ?? condition.unlessPath,
71
+ payload: payload ?? condition.payload
76
72
  };
77
73
  }
78
- const matchPath = errors.scope('matchPath', () => resolve(when.matchPath, BuilderPathSchema));
74
+ const matchPath = issues.scope('matchPath', () => resolve(condition.matchPath, BuilderPathSchema));
79
75
  const selectMapSchema = v.record(StringSchema, v.nullable(v.unknown()));
80
- const map = errors.scope('selectMap', () => resolve(when.selectMap, selectMapSchema));
76
+ const map = issues.scope('selectMap', () => resolve(condition.selectMap, selectMapSchema));
81
77
  if (map == null) {
82
- return { ...when, matchPath: matchPath ?? when.matchPath };
78
+ return { ...condition, matchPath: matchPath ?? condition.matchPath };
83
79
  }
84
- const selectMap = errors.scope('selectMap', () => Object.entries(map).reduce((values, [key, entryValue]) => {
80
+ const selectMap = issues.scope('selectMap', () => Object.entries(map).reduce((values, [key, entryValue]) => {
85
81
  if (entryValue == null) {
86
82
  return { ...values, [key]: null };
87
83
  }
88
- const resolved = errors.scope(key, () => resolve(entryValue, payloadSchema));
84
+ const resolved = issues.scope(key, () => resolve(entryValue, payloadSchema));
89
85
  return { ...values, [key]: resolved ?? entryValue };
90
86
  }, {}));
91
- return { ...when, matchPath: matchPath ?? when.matchPath, selectMap };
87
+ return { ...condition, matchPath: matchPath ?? condition.matchPath, selectMap };
92
88
  }
93
89
  function resolveCollectionConfig(config) {
94
- const model = errors.scope('model', () => {
90
+ const model = issues.scope('model', () => {
95
91
  const resolved = resolve(config.model, BuilderModelSerialisedSchema);
96
92
  if (resolved == null) {
97
93
  return null;
98
94
  }
99
- return validateModelStructure(resolved, resolve, errors);
95
+ return validateModelStructure(resolved, resolve, issues);
100
96
  });
101
- const min = errors.scope('min', () => resolve(config.min, NumberSchema));
102
- const max = errors.scope('max', () => resolve(config.max, NumberSchema));
97
+ const min = issues.scope('min', () => resolve(config.min, NumberSchema));
98
+ const max = issues.scope('max', () => resolve(config.max, NumberSchema));
103
99
  return {
104
100
  ...config,
105
101
  model: model ?? config.model,
@@ -1,7 +1,7 @@
1
1
  import type { BuilderModelSerialised, BuilderReferences, BuilderUISerialised, BuilderUIValidated, ValidationResult } from '../entities/index';
2
2
  import type { BuilderResolve } from './resolve';
3
- import { BuilderErrorsScope } from '../errors/index.js';
3
+ import { BuilderIssuesScope } from '../errors/index.js';
4
4
  export type BuilderUIValidationResult = ValidationResult<BuilderUIValidated>;
5
- export declare function validateUI(input: unknown, references?: BuilderReferences, errors?: BuilderErrorsScope): BuilderUIValidationResult;
6
- export declare function validateUIStructure(ui: BuilderUISerialised, resolve: BuilderResolve, errors: BuilderErrorsScope): BuilderUIValidated;
7
- export declare function checkUIExpectations(mergedModel: BuilderModelSerialised, ui: BuilderUIValidated, errors: BuilderErrorsScope): void;
5
+ export declare function validateUI(input: unknown, references?: BuilderReferences, issues?: BuilderIssuesScope): BuilderUIValidationResult;
6
+ export declare function validateUIStructure(ui: BuilderUISerialised, resolve: BuilderResolve, issues: BuilderIssuesScope): BuilderUIValidated;
7
+ export declare function checkUIExpectations(mergedModel: BuilderModelSerialised, ui: BuilderUIValidated, issues: BuilderIssuesScope): void;
@@ -1,23 +1,23 @@
1
1
  import { BuilderModelSerialisedSchema, BuilderPathSchema, BuilderUIInputMetadataSchema, BuilderUIInputSerialisedSchema, BuilderUIInputsSerialisedSchema, BuilderUIItemSerialisedSchema, BuilderUIItemsSerialisedSchema, BuilderUISerialisedSchema, modelsMerge, serialise, uis, validateUIDescribe, validateUIInput, validateUIPage, validateUIPages } from '../entities/index.js';
2
- import { BuilderErrorsScope, check } from '../errors/index.js';
2
+ import { BuilderIssuesScope, check } from '../errors/index.js';
3
3
  import { resolveCollections } from '../mappers/index.js';
4
4
  import { StringSchema } from '../primitive.js';
5
5
  import { validate } from './brand.js';
6
6
  import { checkExpectations } from './expectations.js';
7
7
  import { checkPath } from './paths.js';
8
8
  import { resolver } from './resolve.js';
9
- export function validateUI(input, references = [], errors = new BuilderErrorsScope(input)) {
9
+ export function validateUI(input, references = [], issues = new BuilderIssuesScope(input)) {
10
10
  if (!check.is(BuilderUISerialisedSchema, input)) {
11
- errors.entityInvalid('ui');
12
- return [validate(serialise.ui(uis())), errors.errors];
11
+ issues.entityInvalid('ui');
12
+ return [validate(serialise.ui(uis())), issues.errors, issues.warnings];
13
13
  }
14
- const resolve = resolver(errors, references);
15
- const structure = validateUIStructure(input, resolve, errors);
16
- return [validate(structure), errors.errors];
14
+ const resolve = resolver(issues, references);
15
+ const structure = validateUIStructure(input, resolve, issues);
16
+ return [validate(structure), issues.errors, issues.warnings];
17
17
  }
18
- export function validateUIStructure(ui, resolve, errors) {
18
+ export function validateUIStructure(ui, resolve, issues) {
19
19
  const childUIs = walkChildUIs();
20
- const items = errors.scope('items', () => walkItems(ui.items));
20
+ const items = issues.scope('items', () => walkItems(ui.items));
21
21
  const data = {
22
22
  ...ui,
23
23
  uis: childUIs,
@@ -25,40 +25,40 @@ export function validateUIStructure(ui, resolve, errors) {
25
25
  };
26
26
  return data;
27
27
  function walkChildUIs() {
28
- return errors.scope('uis', () => ui.uis.flatMap((part, partIndex) => errors.scope(partIndex, () => {
28
+ return issues.scope('uis', () => ui.uis.flatMap((part, partIndex) => issues.scope(partIndex, () => {
29
29
  const resolved = resolve(part, BuilderUISerialisedSchema);
30
30
  if (resolved == null) {
31
31
  return [];
32
32
  }
33
- return [validateUIStructure(resolved, resolve, errors)];
33
+ return [validateUIStructure(resolved, resolve, issues)];
34
34
  })));
35
35
  }
36
36
  function walkItems(parts) {
37
- return parts.map((item, itemIndex) => errors.scope(itemIndex, () => {
37
+ return parts.map((item, itemIndex) => issues.scope(itemIndex, () => {
38
38
  const resolved = resolve(item, BuilderUIItemSerialisedSchema);
39
39
  return walkUIItem((resolved ?? item));
40
40
  }));
41
41
  }
42
42
  function walkUIItem(item) {
43
43
  if (item.type === 'page') {
44
- validateUIPage(item, [], errors);
44
+ validateUIPage(item, [], issues);
45
45
  }
46
46
  else if (item.type === 'pages') {
47
- validateUIPages(item, [], errors);
47
+ validateUIPages(item, [], issues);
48
48
  }
49
49
  else if (item.type === 'describe') {
50
- validateUIDescribe(item, [], errors);
50
+ validateUIDescribe(item, [], issues);
51
51
  }
52
- const label = errors.scope('label', () => resolve(item.label, StringSchema) ?? item.label);
52
+ const label = issues.scope('label', () => resolve(item.label, StringSchema) ?? item.label);
53
53
  if (item.type === 'pages') {
54
- const innerItems = errors.scope('items', () => {
54
+ const innerItems = issues.scope('items', () => {
55
55
  const resolved = resolve(item.items, BuilderUIItemsSerialisedSchema);
56
56
  const resolvedItems = (Array.isArray(resolved) ? resolved : item.items);
57
57
  return walkItems(resolvedItems);
58
58
  });
59
59
  return { ...item, label, items: innerItems };
60
60
  }
61
- const inputs = errors.scope('inputs', () => {
61
+ const inputs = issues.scope('inputs', () => {
62
62
  const resolved = resolve(item.inputs, BuilderUIInputsSerialisedSchema);
63
63
  if (!Array.isArray(resolved)) {
64
64
  return resolved ?? item.inputs;
@@ -68,18 +68,18 @@ export function validateUIStructure(ui, resolve, errors) {
68
68
  return { ...item, label, inputs };
69
69
  }
70
70
  function walkInputs(inputs) {
71
- return inputs.map((entry, entryIndex) => errors.scope(entryIndex, () => {
71
+ return inputs.map((entry, entryIndex) => issues.scope(entryIndex, () => {
72
72
  const resolvedEntry = resolve(entry, BuilderUIInputSerialisedSchema);
73
73
  return walkInput((resolvedEntry ?? entry));
74
74
  }));
75
75
  }
76
76
  function walkInput(value) {
77
- validateUIInput(value, [], errors);
78
- const path = errors.scope('path', () => resolve(value.path, BuilderPathSchema) ?? value.path);
77
+ validateUIInput(value, [], issues);
78
+ const path = issues.scope('path', () => resolve(value.path, BuilderPathSchema) ?? value.path);
79
79
  const displayName = value.displayName &&
80
- errors.scope('displayName', () => resolve(value.displayName, StringSchema) ?? value.displayName);
81
- const kind = value.kind && errors.scope('kind', () => resolve(value.kind, StringSchema) ?? value.kind);
82
- const metadata = value.metadata && errors.scope('metadata', () => walkMetadata(value.metadata));
80
+ issues.scope('displayName', () => resolve(value.displayName, StringSchema) ?? value.displayName);
81
+ const kind = value.kind && issues.scope('kind', () => resolve(value.kind, StringSchema) ?? value.kind);
82
+ const metadata = value.metadata && issues.scope('metadata', () => walkMetadata(value.metadata));
83
83
  return { ...value, path, displayName, kind, metadata };
84
84
  }
85
85
  function walkMetadata(rawMetadata) {
@@ -88,28 +88,28 @@ export function validateUIStructure(ui, resolve, errors) {
88
88
  return rawMetadata;
89
89
  }
90
90
  return Object.entries(resolved).reduce((entries, [key, entryValue]) => {
91
- const resolvedValue = errors.scope(key, () => resolve(entryValue));
91
+ const resolvedValue = issues.scope(key, () => resolve(entryValue));
92
92
  return { ...entries, [key]: resolvedValue ?? entryValue };
93
93
  }, {});
94
94
  }
95
95
  }
96
- export function checkUIExpectations(mergedModel, ui, errors) {
96
+ export function checkUIExpectations(mergedModel, ui, issues) {
97
97
  const expectedOptionNames = collectExpectedOptionNames(ui);
98
- errors.scope('expectations', () => {
99
- checkExpectations(mergedModel, ui.expectations, errors);
98
+ issues.scope('expectations', () => {
99
+ checkExpectations(mergedModel, ui.expectations, issues);
100
100
  });
101
- errors.scope('items', () => walkItems(mergedModel, ui.items));
102
- errors.scope('uis', () => {
101
+ issues.scope('items', () => walkItems(mergedModel, ui.items));
102
+ issues.scope('uis', () => {
103
103
  ui.uis.forEach((nested, nestedIndex) => {
104
- errors.scope(nestedIndex, () => {
105
- checkUIExpectations(mergedModel, nested, errors);
104
+ issues.scope(nestedIndex, () => {
105
+ checkUIExpectations(mergedModel, nested, issues);
106
106
  });
107
107
  });
108
108
  });
109
109
  function walkItems(model, items) {
110
110
  items.forEach((entry, itemIndex) => {
111
111
  const item = entry;
112
- errors.scope(itemIndex, () => {
112
+ issues.scope(itemIndex, () => {
113
113
  if (item.type === 'pages') {
114
114
  walkPages(model, item);
115
115
  return;
@@ -118,8 +118,8 @@ export function checkUIExpectations(mergedModel, ui, errors) {
118
118
  if (!Array.isArray(inputs)) {
119
119
  return;
120
120
  }
121
- errors.scope('inputs', () => inputs.forEach((input, entryIndex) => {
122
- errors.scope(entryIndex, () => walkInput(model, input));
121
+ issues.scope('inputs', () => inputs.forEach((input, entryIndex) => {
122
+ issues.scope(entryIndex, () => walkInput(model, input));
123
123
  }));
124
124
  });
125
125
  });
@@ -132,7 +132,7 @@ export function checkUIExpectations(mergedModel, ui, errors) {
132
132
  const innerModels = resolveCollections(collection).flatMap(({ model: configModel }) => check.is(BuilderModelSerialisedSchema, configModel) ? [configModel] : []);
133
133
  innerModels.forEach((innerModel) => {
134
134
  const mergedInnerModel = modelsMerge(innerModel);
135
- errors.scope('items', () => walkItems(mergedInnerModel, pages.items));
135
+ issues.scope('items', () => walkItems(mergedInnerModel, pages.items));
136
136
  });
137
137
  }
138
138
  function walkInput(model, input) {
@@ -144,8 +144,8 @@ export function checkUIExpectations(mergedModel, ui, errors) {
144
144
  if (typeof leaf === 'string' && expectedOptionNames.has(leaf)) {
145
145
  return;
146
146
  }
147
- errors.scope('path', () => {
148
- checkPath(model, path, errors);
147
+ issues.scope('path', () => {
148
+ checkPath(model, path, issues);
149
149
  });
150
150
  }
151
151
  }
@@ -1,7 +1,7 @@
1
- import type { BuilderModelValidated, BuilderVariantsValidated, ValidationResult } from '../entities/index';
2
- import { BuilderErrorsScope } from '../errors/index.js';
1
+ import type { BuilderModelValidated, BuilderReferences, BuilderVariantsValidated, ValidationResult } from '../entities/index';
2
+ import { BuilderIssuesScope } from '../errors/index.js';
3
3
  export type BuilderVariantsValidationOptions = {
4
4
  readonly partial?: boolean;
5
5
  };
6
6
  export type BuilderVariantsValidationResult = ValidationResult<BuilderVariantsValidated>;
7
- export declare function validateVariants(model: BuilderModelValidated, input: unknown, options?: BuilderVariantsValidationOptions, errors?: BuilderErrorsScope): BuilderVariantsValidationResult;
7
+ export declare function validateVariants(model: BuilderModelValidated, input: unknown, options?: BuilderVariantsValidationOptions, references?: BuilderReferences, issues?: BuilderIssuesScope): BuilderVariantsValidationResult;
@@ -1,46 +1,46 @@
1
1
  import { BuilderComponentConfigSerialisedSchema, detailValueSchema } from '../entities/index.js';
2
- import { BuilderErrorsScope, check } from '../errors/index.js';
2
+ import { BuilderIssuesScope, check } from '../errors/index.js';
3
3
  import { BuilderVariantsSchema } from '../instance.js';
4
4
  import { createVariants } from '../mappers/index.js';
5
5
  import { validate } from './brand.js';
6
- export function validateVariants(model, input, options = {}, errors = new BuilderErrorsScope(input)) {
6
+ export function validateVariants(model, input, options = {}, references = [], issues = new BuilderIssuesScope(input)) {
7
7
  if (!check.is(BuilderVariantsSchema, input)) {
8
- errors.variantsInvalid();
9
- return [validate({}), errors.errors];
8
+ issues.variantsInvalid();
9
+ return [validate({}), issues.errors, issues.warnings];
10
10
  }
11
11
  const variants = input;
12
- const expected = createVariants(model);
12
+ const expected = createVariants(model, references);
13
13
  if (Object.keys(expected).length === 0) {
14
- errors.modelEmptyComponents();
15
- return [validate({}), errors.errors];
14
+ issues.modelEmptyComponents();
15
+ return [validate({}), issues.errors, issues.warnings];
16
16
  }
17
- errors.scope('variants', () => {
17
+ issues.scope('variants', () => {
18
18
  checkVariants();
19
19
  checkComponents();
20
20
  checkDetails();
21
21
  function checkVariants() {
22
22
  Object.entries(expected).forEach(([component, expectedVariants]) => {
23
23
  const componentVariants = variants[component];
24
- errors.scope(component, () => {
24
+ issues.scope(component, () => {
25
25
  if (componentVariants == null) {
26
26
  if (options.partial !== false) {
27
- errors.variantsMissingComponent();
27
+ issues.variantsMissingComponent();
28
28
  }
29
29
  return;
30
30
  }
31
31
  const expectedKeys = new Map(expectedVariants.map(({ instance }) => [sortedKey(instance), instance]));
32
32
  const actualKeys = new Set(componentVariants.map(({ instance }) => sortedKey(instance)));
33
33
  componentVariants.forEach((variant, index) => {
34
- errors.scope(index, () => {
34
+ issues.scope(index, () => {
35
35
  const { instance } = variant;
36
36
  if (!expectedKeys.has(sortedKey(instance))) {
37
- errors.variantsInvalidVariant();
37
+ issues.variantsInvalidVariant();
38
38
  }
39
39
  });
40
40
  });
41
41
  Array.from(expectedKeys).forEach(([key, instance]) => {
42
42
  if (!actualKeys.has(key)) {
43
- errors.variantsMissingVariant(instance);
43
+ issues.variantsMissingVariant(instance);
44
44
  }
45
45
  });
46
46
  });
@@ -48,9 +48,9 @@ export function validateVariants(model, input, options = {}, errors = new Builde
48
48
  }
49
49
  function checkComponents() {
50
50
  Object.keys(variants).forEach((component) => {
51
- errors.scope(component, () => {
51
+ issues.scope(component, () => {
52
52
  if (expected[component] == null) {
53
- errors.variantsUnexpectedComponent();
53
+ issues.variantsUnexpectedComponent();
54
54
  }
55
55
  });
56
56
  });
@@ -58,32 +58,33 @@ export function validateVariants(model, input, options = {}, errors = new Builde
58
58
  function checkDetails() {
59
59
  const componentByName = new Map(model.components.map((entry) => [entry.name, entry]));
60
60
  Object.entries(variants).forEach(([component, componentVariants]) => {
61
- errors.scope(component, () => {
61
+ issues.scope(component, () => {
62
62
  const entry = componentByName.get(component);
63
63
  if (entry == null) {
64
64
  return;
65
65
  }
66
66
  componentVariants.forEach(({ instance, details = {} }, index) => {
67
- errors.scope(index, () => {
67
+ issues.scope(index, () => {
68
68
  const resolved = variantDetails(entry, instance);
69
- const fields = resolved?.fields ?? [];
70
- const expectedNames = new Set(fields.map(({ name }) => name));
71
- errors.scope('details', () => {
72
- fields.forEach(({ name, valueType, isOptional }) => {
73
- errors.scope(name, () => {
74
- if (!(name in details)) {
75
- errors.variantsMissingDetail();
69
+ const expected = resolved?.details ?? [];
70
+ const expectedNames = new Set(expected.map(({ name }) => name));
71
+ issues.scope('details', () => {
72
+ expected.forEach(({ name, kind, isOptional }) => {
73
+ issues.scope(name, () => {
74
+ const detail = details[name];
75
+ if (detail == null) {
76
+ issues.variantsMissingDetail();
76
77
  return;
77
78
  }
78
- if (!check.is(detailValueSchema(valueType, isOptional), details[name])) {
79
- errors.variantsInvalidDetail();
79
+ if (!check.is(detailValueSchema(kind, isOptional), detail.value)) {
80
+ issues.variantsInvalidDetail();
80
81
  }
81
82
  });
82
83
  });
83
- Object.keys(details).forEach((detail) => {
84
- if (!expectedNames.has(detail)) {
85
- errors.scope(detail, () => {
86
- errors.variantsUnexpectedDetail();
84
+ Object.keys(details).forEach((name) => {
85
+ if (!expectedNames.has(name)) {
86
+ issues.scope(name, () => {
87
+ issues.variantsUnexpectedDetail();
87
88
  });
88
89
  }
89
90
  });
@@ -94,7 +95,7 @@ export function validateVariants(model, input, options = {}, errors = new Builde
94
95
  });
95
96
  }
96
97
  });
97
- return [validate(variants), errors.errors];
98
+ return [validate(variants), issues.errors, issues.warnings];
98
99
  }
99
100
  function variantDetails(component, variantInstance) {
100
101
  const { payload } = component;