@builder-builder/builder 0.0.27 → 0.0.28

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 (98) hide show
  1. package/dist/bb.js +4 -4
  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 +79 -18
  7. package/dist/client/schema.js +6 -1
  8. package/dist/components/BuilderRender.svelte.d.ts +2 -2
  9. package/dist/components/index.js +4377 -4303
  10. package/dist/components/index.min.js +3 -0
  11. package/dist/entities/collection/collection.d.ts +66 -66
  12. package/dist/entities/collection/config.d.ts +17 -17
  13. package/dist/entities/collection/when.d.ts +1 -1
  14. package/dist/entities/component/component.d.ts +64 -64
  15. package/dist/entities/component/config.d.ts +33 -33
  16. package/dist/entities/component/config.js +18 -16
  17. package/dist/entities/component/detail.d.ts +61 -0
  18. package/dist/entities/component/detail.js +71 -0
  19. package/dist/entities/component/index.d.ts +2 -2
  20. package/dist/entities/component/index.js +1 -1
  21. package/dist/entities/component/when.d.ts +2 -2
  22. package/dist/entities/expectation.d.ts +1 -1
  23. package/dist/entities/index.d.ts +4 -4
  24. package/dist/entities/index.js +1 -1
  25. package/dist/entities/kind.d.ts +3 -3
  26. package/dist/entities/kind.js +20 -20
  27. package/dist/entities/model/methods.d.ts +1 -1
  28. package/dist/entities/option/config.d.ts +7 -7
  29. package/dist/entities/option/config.js +1 -1
  30. package/dist/entities/option/index.d.ts +4 -4
  31. package/dist/entities/option/index.js +2 -2
  32. package/dist/entities/option/option.d.ts +22 -22
  33. package/dist/entities/option/select.d.ts +1 -1
  34. package/dist/entities/option/toggle.d.ts +9 -9
  35. package/dist/entities/option/toggle.js +15 -10
  36. package/dist/entities/option/when.d.ts +1 -1
  37. package/dist/entities/paths.d.ts +2 -2
  38. package/dist/entities/pricing/expression.d.ts +16 -39
  39. package/dist/entities/pricing/expression.js +1 -16
  40. package/dist/entities/pricing/index.d.ts +1 -1
  41. package/dist/entities/pricing/rates.d.ts +1 -1
  42. package/dist/entities/references.d.ts +24 -24
  43. package/dist/entities/serialise.d.ts +31 -32
  44. package/dist/entities/serialise.js +7 -7
  45. package/dist/entities/ui/describe.d.ts +1 -1
  46. package/dist/entities/ui/input.d.ts +1 -1
  47. package/dist/entities/ui/page.d.ts +1 -1
  48. package/dist/entities/ui/pages.d.ts +2 -2
  49. package/dist/entities/validated.d.ts +2 -2
  50. package/dist/entities/when.d.ts +5 -5
  51. package/dist/environment.d.ts +2 -2
  52. package/dist/errors/errors.d.ts +86 -55
  53. package/dist/errors/errors.js +36 -5
  54. package/dist/errors/exception.d.ts +3 -3
  55. package/dist/errors/index.d.ts +1 -1
  56. package/dist/errors/index.js +1 -1
  57. package/dist/errors/public.d.ts +1 -1
  58. package/dist/index.d.ts +1 -1
  59. package/dist/index.js +1 -1
  60. package/dist/instance.d.ts +53 -9
  61. package/dist/instance.js +6 -2
  62. package/dist/mappers/dependencies.d.ts +3 -0
  63. package/dist/mappers/dependencies.js +44 -0
  64. package/dist/mappers/index.d.ts +2 -2
  65. package/dist/mappers/index.js +2 -1
  66. package/dist/mappers/instance.js +26 -21
  67. package/dist/mappers/price.js +6 -4
  68. package/dist/mappers/variants/index.d.ts +1 -2
  69. package/dist/mappers/variants/index.js +1 -2
  70. package/dist/mappers/variants/option-graph.d.ts +1 -2
  71. package/dist/mappers/variants/option-graph.js +3 -17
  72. package/dist/mappers/variants/variants.d.ts +3 -6
  73. package/dist/mappers/variants/variants.js +34 -11
  74. package/dist/primitive.d.ts +3 -0
  75. package/dist/primitive.js +2 -0
  76. package/dist/public.d.ts +8 -8
  77. package/dist/public.js +1 -1
  78. package/dist/validate/builder.d.ts +2 -2
  79. package/dist/validate/builder.js +15 -15
  80. package/dist/validate/expectations.d.ts +2 -2
  81. package/dist/validate/expectations.js +3 -3
  82. package/dist/validate/instance.d.ts +2 -2
  83. package/dist/validate/instance.js +31 -13
  84. package/dist/validate/model.d.ts +4 -4
  85. package/dist/validate/model.js +51 -42
  86. package/dist/validate/paths.d.ts +2 -2
  87. package/dist/validate/paths.js +19 -14
  88. package/dist/validate/pricing.d.ts +4 -4
  89. package/dist/validate/pricing.js +31 -31
  90. package/dist/validate/resolve.d.ts +2 -2
  91. package/dist/validate/resolve.js +18 -18
  92. package/dist/validate/ui.d.ts +4 -4
  93. package/dist/validate/ui.js +38 -38
  94. package/dist/validate/variants.d.ts +3 -3
  95. package/dist/validate/variants.js +32 -31
  96. package/package.json +4 -2
  97. package/dist/entities/component/field.d.ts +0 -59
  98. package/dist/entities/component/field.js +0 -52
@@ -1,40 +1,41 @@
1
1
  import * as v from 'valibot';
2
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
+ 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 = [], errors = new BuilderErrorsScope(input)) {
11
+ export function validateModel(input, references = [], issues = new BuilderIssuesScope(input)) {
11
12
  if (!check.is(BuilderModelSerialisedSchema, input)) {
12
- errors.entityInvalid('model');
13
- return [EMPTY_MODEL, errors.errors];
13
+ issues.entityInvalid('model');
14
+ return [EMPTY_MODEL, issues.errors, issues.warnings];
14
15
  }
15
- const resolve = resolver(errors, references);
16
- const structure = validateModelStructure(input, resolve, errors);
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, errors);
20
- return [data, errors.errors];
20
+ checkModelExpectations(data, structure, issues);
21
+ return [data, issues.errors, issues.warnings];
21
22
  }
22
- export function checkModelExpectations(mergedModel, rootModel, errors) {
23
+ export function checkModelExpectations(mergedModel, rootModel, issues) {
23
24
  recurse(rootModel);
24
25
  function recurse(node) {
25
- errors.scope('expectations', () => {
26
- checkExpectations(mergedModel, node.expectations, errors);
26
+ issues.scope('expectations', () => {
27
+ checkExpectations(mergedModel, node.expectations, issues);
27
28
  });
28
- errors.scope('models', () => {
29
+ issues.scope('models', () => {
29
30
  node.models.forEach((nested, nestedIndex) => {
30
- errors.scope(nestedIndex, () => {
31
+ issues.scope(nestedIndex, () => {
31
32
  recurse(nested);
32
33
  });
33
34
  });
34
35
  });
35
36
  }
36
37
  }
37
- export function validateModelStructure(input, resolve, errors) {
38
+ export function validateModelStructure(input, resolve, issues) {
38
39
  const seenGlobal = {
39
40
  option: new Set(),
40
41
  component: new Set(),
@@ -47,41 +48,45 @@ export function validateModelStructure(input, resolve, errors) {
47
48
  return validate(serialise.model(model()));
48
49
  }
49
50
  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) => {
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
53
  whenBranches(resolved.payload, BuilderOptionConfigSerialisedSchema)
54
54
  .filter((config) => !isParamable(config))
55
55
  .forEach((config) => {
56
56
  if (config.type === 'select') {
57
- validateSelect(config, [], errors);
57
+ validateSelect(config, [], issues);
58
58
  }
59
59
  else if (config.type === 'toggle') {
60
- validateToggle(config, [], errors);
60
+ validateToggle(config, [], issues);
61
61
  }
62
62
  });
63
63
  }));
64
- const components = errors.scope('components', () => walkEntries(modelInput.components, 'component', (resolved) => {
64
+ const components = issues.scope('components', () => walkEntries(modelInput.components, 'component', (resolved) => {
65
65
  whenBranches(resolved.payload, BuilderComponentConfigSerialisedSchema)
66
66
  .filter((config) => !isParamable(config))
67
67
  .forEach((config) => {
68
- validateComponentConfig(config, [], errors);
68
+ validateComponentConfig(config, [], issues);
69
69
  });
70
70
  }));
71
- const collections = errors.scope('collections', () => walkEntries(modelInput.collections, 'collection', (resolved) => {
71
+ const collections = issues.scope('collections', () => walkEntries(modelInput.collections, 'collection', (resolved) => {
72
72
  whenBranches(resolved.payload, BuilderCollectionConfigSerialisedSchema)
73
73
  .filter((config) => !isParamable(config))
74
74
  .forEach((config) => {
75
- validateCollectionConfig(config, [], errors);
75
+ validateCollectionConfig(config, [], issues);
76
76
  });
77
77
  }));
78
- return {
78
+ const validatedModel = {
79
79
  ...modelInput,
80
80
  models: childModels,
81
81
  options,
82
82
  components,
83
83
  collections
84
84
  };
85
+ const ordered = new Set(dependencies(validatedModel));
86
+ if ([...options, ...collections, ...components].some((entry) => !ordered.has(entry.name))) {
87
+ issues.modelCircularDependency();
88
+ }
89
+ return validatedModel;
85
90
  function payloadSchemaFor(kind) {
86
91
  if (kind === 'option') {
87
92
  return BuilderOptionConfigSerialisedSchema;
@@ -95,7 +100,7 @@ export function validateModelStructure(input, resolve, errors) {
95
100
  const seenLocal = new Set();
96
101
  const items = [];
97
102
  entries.forEach((entry, entryIndex) => {
98
- errors.scope(entryIndex, () => {
103
+ issues.scope(entryIndex, () => {
99
104
  const resolved = resolveEntry(entry, seenLocal, kind);
100
105
  if (resolved == null) {
101
106
  return;
@@ -109,33 +114,33 @@ export function validateModelStructure(input, resolve, errors) {
109
114
  function resolveEntry(entry, seenLocal, kind) {
110
115
  let paths = entry.paths;
111
116
  if (entry.paths != null) {
112
- const resolvedPaths = errors.scope('paths', () => resolve(entry.paths, BuilderPathsSchema));
117
+ const resolvedPaths = issues.scope('paths', () => resolve(entry.paths, BuilderPathsSchema));
113
118
  paths = resolvedPaths ?? entry.paths;
114
119
  }
115
120
  const payloadSchema = v.union([payloadSchemaFor(kind), BuilderWhenSerialisedSchema]);
116
- const payload = errors.scope('payload', () => resolve(entry.payload, payloadSchema));
121
+ const payload = issues.scope('payload', () => resolve(entry.payload, payloadSchema));
117
122
  const resolvedEntry = { ...entry, paths, payload: payload ?? entry.payload };
118
123
  if (seenLocal.has(resolvedEntry.name)) {
119
124
  if (kind === 'option') {
120
- errors.modelDuplicateOption();
125
+ issues.modelDuplicateOption();
121
126
  }
122
127
  else if (kind === 'component') {
123
- errors.modelDuplicateComponent();
128
+ issues.modelDuplicateComponent();
124
129
  }
125
130
  else {
126
- errors.modelDuplicateCollection();
131
+ issues.modelDuplicateCollection();
127
132
  }
128
133
  return null;
129
134
  }
130
135
  if (seenGlobal[kind].has(resolvedEntry.name)) {
131
136
  if (kind === 'option') {
132
- errors.modelOverriddenOption();
137
+ issues.modelOverriddenOption();
133
138
  }
134
139
  else if (kind === 'component') {
135
- errors.modelOverriddenComponent();
140
+ issues.modelOverriddenComponent();
136
141
  }
137
142
  else {
138
- errors.modelOverriddenCollection();
143
+ issues.modelOverriddenCollection();
139
144
  }
140
145
  }
141
146
  seenLocal.add(resolvedEntry.name);
@@ -144,15 +149,12 @@ export function validateModelStructure(input, resolve, errors) {
144
149
  return resolvedEntry;
145
150
  }
146
151
  function checkPaths(entry) {
147
- if (skipPathValidation) {
148
- return;
149
- }
150
152
  const { paths, payload } = entry;
151
153
  if (Array.isArray(paths)) {
152
- errors.scope('paths', () => {
154
+ issues.scope('paths', () => {
153
155
  paths.forEach((path, pathIndex) => {
154
- errors.scope(pathIndex, () => {
155
- checkPath(modelInput, path, errors);
156
+ issues.scope(pathIndex, () => {
157
+ checkPath(modelInput, path, issues);
156
158
  });
157
159
  });
158
160
  });
@@ -161,10 +163,17 @@ export function validateModelStructure(input, resolve, errors) {
161
163
  return;
162
164
  }
163
165
  if (payload.type === 'match' && Array.isArray(payload.matchPath)) {
164
- errors.scope('payload', () => errors.scope('matchPath', () => checkPath(modelInput, payload.matchPath, errors)));
166
+ issues.scope('payload', () => issues.scope('matchPath', () => checkPath(modelInput, payload.matchPath, issues)));
165
167
  }
166
- if (payload.type === 'unless' && Array.isArray(payload.unlessPath)) {
167
- errors.scope('payload', () => errors.scope('unlessPath', () => checkPath(modelInput, payload.unlessPath, errors)));
168
+ if (payload.type === 'unless') {
169
+ if (payload.disabledValues.length === 0) {
170
+ issues.scope('payload', () => issues.scope('disabledValues', () => {
171
+ issues.entityEmptyDisabledValues();
172
+ }));
173
+ }
174
+ if (Array.isArray(payload.unlessPath)) {
175
+ issues.scope('payload', () => issues.scope('unlessPath', () => checkPath(modelInput, payload.unlessPath, issues)));
176
+ }
168
177
  }
169
178
  }
170
179
  }
@@ -1,3 +1,3 @@
1
1
  import type { BuilderModelSerialised, BuilderPath } from '../entities/index';
2
- import type { BuilderErrorsScope } from '../errors/index';
3
- export declare function checkPath(model: BuilderModelSerialised, path: BuilderPath, errors: BuilderErrorsScope): void;
2
+ import type { BuilderIssuesScope } from '../errors/index';
3
+ export declare function checkPath(model: BuilderModelSerialised, path: BuilderPath, issues: BuilderIssuesScope): void;
@@ -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, errors) {
5
+ export function checkPath(model, path, issues) {
6
6
  if (path.length === 0) {
7
- errors.pathEmpty();
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, errors);
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
- errors.scope(lastIndex, () => errors.pathInvalidSegment());
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
- errors.scope(lastIndex, () => errors.pathTargetIsCollection());
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
- errors.scope(lastIndex, () => errors.pathTargetIsComponent());
35
+ issues.scope(lastIndex, () => issues.pathTargetIsComponent());
31
36
  return;
32
37
  }
33
- errors.scope(lastIndex, () => errors.pathMissingOption());
38
+ issues.scope(lastIndex, () => issues.pathMissingOption());
34
39
  }
35
- function walkPath(models, remaining, offset, errors) {
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
- errors.scope(offset, () => errors.pathInvalidSegment());
46
+ issues.scope(offset, () => issues.pathInvalidSegment());
42
47
  return null;
43
48
  }
44
49
  if (!check.is(NumberSchema, index)) {
45
- errors.scope(offset + 1, () => errors.pathInvalidSegment());
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
- errors.scope(offset, () => errors.pathMissingCollection());
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
- errors.scope(offset + 1, () => errors.pathInvalidIndex(max));
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
- errors.scope(offset, () => errors.pathMissingCollection());
74
+ issues.scope(offset, () => issues.pathMissingCollection());
70
75
  return null;
71
76
  }
72
- return walkPath(next, rest, offset + 2, errors);
77
+ return walkPath(next, rest, offset + 2, issues);
73
78
  }
@@ -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;
@@ -4,16 +4,16 @@ 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
  }
@@ -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];
@@ -63,43 +63,43 @@ export function resolver(errors, references = [], bindings = {}) {
63
63
  }
64
64
  function resolveWhen(when, payloadSchema) {
65
65
  if (when.type === 'enable') {
66
- const payload = errors.scope('payload', () => resolve(when.payload, payloadSchema));
66
+ const payload = issues.scope('payload', () => resolve(when.payload, payloadSchema));
67
67
  return { ...when, payload: payload ?? when.payload };
68
68
  }
69
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));
70
+ const unlessPath = issues.scope('unlessPath', () => resolve(when.unlessPath, BuilderPathSchema));
71
+ const payload = issues.scope('payload', () => resolve(when.payload, payloadSchema));
72
72
  return {
73
73
  ...when,
74
74
  unlessPath: unlessPath ?? when.unlessPath,
75
75
  payload: payload ?? when.payload
76
76
  };
77
77
  }
78
- const matchPath = errors.scope('matchPath', () => resolve(when.matchPath, BuilderPathSchema));
78
+ const matchPath = issues.scope('matchPath', () => resolve(when.matchPath, BuilderPathSchema));
79
79
  const selectMapSchema = v.record(StringSchema, v.nullable(v.unknown()));
80
- const map = errors.scope('selectMap', () => resolve(when.selectMap, selectMapSchema));
80
+ const map = issues.scope('selectMap', () => resolve(when.selectMap, selectMapSchema));
81
81
  if (map == null) {
82
82
  return { ...when, matchPath: matchPath ?? when.matchPath };
83
83
  }
84
- const selectMap = errors.scope('selectMap', () => Object.entries(map).reduce((values, [key, entryValue]) => {
84
+ const selectMap = issues.scope('selectMap', () => Object.entries(map).reduce((values, [key, entryValue]) => {
85
85
  if (entryValue == null) {
86
86
  return { ...values, [key]: null };
87
87
  }
88
- const resolved = errors.scope(key, () => resolve(entryValue, payloadSchema));
88
+ const resolved = issues.scope(key, () => resolve(entryValue, payloadSchema));
89
89
  return { ...values, [key]: resolved ?? entryValue };
90
90
  }, {}));
91
91
  return { ...when, matchPath: matchPath ?? when.matchPath, selectMap };
92
92
  }
93
93
  function resolveCollectionConfig(config) {
94
- const model = errors.scope('model', () => {
94
+ const model = issues.scope('model', () => {
95
95
  const resolved = resolve(config.model, BuilderModelSerialisedSchema);
96
96
  if (resolved == null) {
97
97
  return null;
98
98
  }
99
- return validateModelStructure(resolved, resolve, errors);
99
+ return validateModelStructure(resolved, resolve, issues);
100
100
  });
101
- const min = errors.scope('min', () => resolve(config.min, NumberSchema));
102
- const max = errors.scope('max', () => resolve(config.max, NumberSchema));
101
+ const min = issues.scope('min', () => resolve(config.min, NumberSchema));
102
+ const max = issues.scope('max', () => resolve(config.max, NumberSchema));
103
103
  return {
104
104
  ...config,
105
105
  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;