@builder-builder/builder 0.0.12 → 0.0.14

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 (66) hide show
  1. package/dist/cli.d.ts +2 -0
  2. package/dist/cli.js +53 -0
  3. package/dist/codegen/index.d.ts +7 -0
  4. package/dist/codegen/index.js +212 -0
  5. package/dist/codegen/template.d.ts +5 -0
  6. package/dist/codegen/template.js +17 -0
  7. package/dist/entities/index.d.ts +3 -3
  8. package/dist/entities/index.js +1 -1
  9. package/dist/entities/kind.d.ts +1 -1
  10. package/dist/entities/serialise.d.ts +554 -8
  11. package/dist/entities/serialise.js +5 -3
  12. package/dist/entities/ui/describe.d.ts +222 -8
  13. package/dist/entities/ui/describe.js +5 -5
  14. package/dist/entities/ui/index.d.ts +2 -0
  15. package/dist/entities/ui/index.js +1 -0
  16. package/dist/entities/ui/input.d.ts +334 -0
  17. package/dist/entities/ui/input.js +39 -0
  18. package/dist/entities/ui/page.d.ts +222 -8
  19. package/dist/entities/ui/page.js +5 -5
  20. package/dist/entities/ui/ui.d.ts +3 -3
  21. package/dist/entities/ui/ui.js +7 -4
  22. package/dist/entities/validated.d.ts +23 -21
  23. package/dist/entities/when.d.ts +2 -2
  24. package/dist/index.d.ts +3 -3
  25. package/dist/index.js +1 -1
  26. package/dist/mappers/index.d.ts +3 -2
  27. package/dist/mappers/index.js +1 -1
  28. package/dist/mappers/instance.js +10 -6
  29. package/dist/mappers/order.js +5 -2
  30. package/dist/mappers/render/index.d.ts +1 -1
  31. package/dist/mappers/render/pages.d.ts +8 -0
  32. package/dist/mappers/render/pages.js +2 -1
  33. package/dist/mappers/render/render.js +31 -54
  34. package/dist/mappers/resolve.d.ts +13 -4
  35. package/dist/mappers/resolve.js +73 -16
  36. package/dist/mappers/variants/index.d.ts +2 -1
  37. package/dist/mappers/variants/index.js +2 -1
  38. package/dist/mappers/variants/option-graph.d.ts +2 -2
  39. package/dist/mappers/variants/option-graph.js +6 -3
  40. package/dist/mappers/variants/variants.d.ts +5 -2
  41. package/dist/mappers/variants/variants.js +11 -7
  42. package/dist/paths.d.ts +0 -1
  43. package/dist/paths.js +0 -8
  44. package/dist/validate/brand.d.ts +0 -7
  45. package/dist/validate/brand.js +12 -6
  46. package/dist/validate/builder.d.ts +2 -1
  47. package/dist/validate/builder.js +14 -12
  48. package/dist/validate/errors.d.ts +130 -0
  49. package/dist/validate/errors.js +141 -0
  50. package/dist/validate/expectations.d.ts +3 -10
  51. package/dist/validate/expectations.js +8 -10
  52. package/dist/validate/index.d.ts +8 -14
  53. package/dist/validate/index.js +4 -7
  54. package/dist/validate/instance.d.ts +2 -15
  55. package/dist/validate/instance.js +42 -40
  56. package/dist/validate/model.d.ts +4 -31
  57. package/dist/validate/model.js +157 -173
  58. package/dist/validate/resolve.d.ts +3 -15
  59. package/dist/validate/resolve.js +66 -71
  60. package/dist/validate/result.d.ts +1 -7
  61. package/dist/validate/result.js +1 -4
  62. package/dist/validate/ui.d.ts +4 -4
  63. package/dist/validate/ui.js +80 -62
  64. package/dist/validate/variants.d.ts +2 -53
  65. package/dist/validate/variants.js +83 -86
  66. package/package.json +14 -3
@@ -0,0 +1,141 @@
1
+ import { builderError } from '../exception.js';
2
+ export class BuilderValidateErrors {
3
+ #errors = [];
4
+ #location = [];
5
+ get errors() {
6
+ return this.#errors;
7
+ }
8
+ scope(part, fn) {
9
+ this.#location = [...this.#location, part];
10
+ try {
11
+ return fn();
12
+ }
13
+ finally {
14
+ this.#location = this.#location.slice(0, -1);
15
+ }
16
+ }
17
+ invalidInput(target) {
18
+ return this.#addError({
19
+ ...builderError('invalid-input', this.#location),
20
+ target
21
+ });
22
+ }
23
+ invalidOption(name, value) {
24
+ return this.#addError({
25
+ ...builderError('invalid-option', this.#location),
26
+ name,
27
+ value
28
+ });
29
+ }
30
+ invalidCollection(name) {
31
+ return this.#addError({
32
+ ...builderError('invalid-collection', this.#location),
33
+ name
34
+ });
35
+ }
36
+ duplicateName(name) {
37
+ return this.#addError({
38
+ ...builderError('duplicate-name', this.#location),
39
+ name
40
+ });
41
+ }
42
+ invalidCollectionBounds(name, min, max) {
43
+ return this.#addError({
44
+ ...builderError('invalid-collection-bounds', this.#location),
45
+ name,
46
+ min,
47
+ max
48
+ });
49
+ }
50
+ invalidPath(reason) {
51
+ return this.#addError({
52
+ ...builderError('invalid-path', this.#location),
53
+ reason
54
+ });
55
+ }
56
+ invalidSelectMapKey(key) {
57
+ return this.#addError({
58
+ ...builderError('invalid-select-map-key', this.#location),
59
+ key
60
+ });
61
+ }
62
+ unboundParameter(name) {
63
+ return this.#addError({
64
+ ...builderError('unbound-parameter', this.#location),
65
+ name
66
+ });
67
+ }
68
+ missingReference(id) {
69
+ return this.#addError({
70
+ ...builderError('missing-reference', this.#location),
71
+ id
72
+ });
73
+ }
74
+ unmetExpectation(expectationKind, name) {
75
+ return this.#addError({
76
+ ...builderError('unmet-expectation', this.#location),
77
+ expectationKind,
78
+ name
79
+ });
80
+ }
81
+ unvalidated(value) {
82
+ return this.#addError({
83
+ ...builderError('unvalidated', this.#location),
84
+ value
85
+ });
86
+ }
87
+ missingComponent(component) {
88
+ return this.#addError({
89
+ ...builderError('missing-component', this.#location),
90
+ component
91
+ });
92
+ }
93
+ unexpectedComponent(component) {
94
+ return this.#addError({
95
+ ...builderError('unexpected-component', this.#location),
96
+ component
97
+ });
98
+ }
99
+ missingVariant(component, instance) {
100
+ return this.#addError({
101
+ ...builderError('missing-variant', this.#location),
102
+ component,
103
+ instance
104
+ });
105
+ }
106
+ invalidVariant(component, instance) {
107
+ return this.#addError({
108
+ ...builderError('invalid-variant', this.#location),
109
+ component,
110
+ instance
111
+ });
112
+ }
113
+ missingDetail(component, detail, instance) {
114
+ return this.#addError({
115
+ ...builderError('missing-detail', this.#location),
116
+ component,
117
+ detail,
118
+ instance
119
+ });
120
+ }
121
+ unexpectedDetail(component, detail, instance) {
122
+ return this.#addError({
123
+ ...builderError('unexpected-detail', this.#location),
124
+ component,
125
+ detail,
126
+ instance
127
+ });
128
+ }
129
+ invalidDetail(component, detail, instance) {
130
+ return this.#addError({
131
+ ...builderError('invalid-detail', this.#location),
132
+ component,
133
+ detail,
134
+ instance
135
+ });
136
+ }
137
+ #addError(error) {
138
+ this.#errors = [...this.#errors, error];
139
+ return error;
140
+ }
141
+ }
@@ -1,10 +1,3 @@
1
- import type { BuilderExpectationKind, BuilderExpectationsSerialised, BuilderModelSerialised } from '../entities/index';
2
- import type { BuilderErrorLocation, BuilderErrors } from '../exception';
3
- export declare function builderErrorUnmetExpectation(expectationKind: BuilderExpectationKind, name: string, location?: BuilderErrorLocation): {
4
- expectationKind: "option" | "component" | "collection";
5
- name: string;
6
- kind: "unmet-expectation";
7
- location: BuilderErrorLocation;
8
- };
9
- export type BuilderErrorUnmetExpectation = ReturnType<typeof builderErrorUnmetExpectation>;
10
- export declare function checkExpectations(model: BuilderModelSerialised, expectations: BuilderExpectationsSerialised, location: BuilderErrorLocation): BuilderErrors;
1
+ import type { BuilderExpectationsSerialised, BuilderModelSerialised } from '../entities/index';
2
+ import type { BuilderValidateErrors } from './errors';
3
+ export declare function checkExpectations(model: BuilderModelSerialised, expectations: BuilderExpectationsSerialised, errors: BuilderValidateErrors): void;
@@ -1,12 +1,10 @@
1
- import { builderError } from '../exception.js';
2
- export function builderErrorUnmetExpectation(expectationKind, name, location = []) {
3
- return { ...builderError('unmet-expectation', location), expectationKind, name };
4
- }
5
- export function checkExpectations(model, expectations, location) {
6
- return expectations.flatMap(({ kind, name }, index) => {
7
- if (model[`${kind}s`].some((entry) => entry.name === name)) {
8
- return [];
9
- }
10
- return [builderErrorUnmetExpectation(kind, name, [...location, index])];
1
+ export function checkExpectations(model, expectations, errors) {
2
+ expectations.forEach(({ kind, name }, index) => {
3
+ errors.scope(index, () => {
4
+ if (model[`${kind}s`].some((entry) => entry.name === name)) {
5
+ return;
6
+ }
7
+ errors.unmetExpectation(kind, name);
8
+ });
11
9
  });
12
10
  }
@@ -1,18 +1,12 @@
1
- export type { BuilderErrorUnvalidated } from './brand';
2
1
  export type { BuilderValidationResult } from './builder';
3
- export type { BuilderErrorUnmetExpectation } from './expectations';
4
- export type { BuilderErrorInvalidCollection, BuilderErrorInvalidOption, BuilderInstanceValidationResult } from './instance';
5
- export type { BuilderErrorDuplicateName, BuilderErrorInvalidCollectionBounds, BuilderErrorInvalidPath, BuilderErrorInvalidPathReason, BuilderErrorInvalidSelectMapKey, BuilderModelValidationResult } from './model';
6
- export type { BuilderErrorMissingReference, BuilderErrorUnboundParameter } from './resolve';
7
- export type { BuilderErrorInvalidInput } from './result';
2
+ export type { BuilderErrorDuplicateName, BuilderErrorInvalidCollection, BuilderErrorInvalidCollectionBounds, BuilderErrorInvalidDetail, BuilderErrorInvalidInput, BuilderErrorInvalidOption, BuilderErrorInvalidPath, BuilderErrorInvalidPathReason, BuilderErrorInvalidSelectMapKey, BuilderErrorInvalidVariant, BuilderErrorMissingComponent, BuilderErrorMissingDetail, BuilderErrorMissingReference, BuilderErrorMissingVariant, BuilderErrorUnboundParameter, BuilderErrorUnexpectedComponent, BuilderErrorUnexpectedDetail, BuilderErrorUnmetExpectation, BuilderErrorUnvalidated, BuilderInvalidInputTarget } from './errors';
3
+ export type { BuilderInstanceValidationResult } from './instance';
4
+ export type { BuilderModelValidationResult } from './model';
8
5
  export type { BuilderUIValidationResult } from './ui';
9
- export type { BuilderComponentVariantsValidationResult, BuilderErrorInvalidDetail, BuilderErrorInvalidVariant, BuilderErrorMissingComponent, BuilderErrorMissingDetail, BuilderErrorMissingVariant, BuilderErrorUnexpectedComponent, BuilderErrorUnexpectedDetail, BuilderVariantsValidationOptions } from './variants';
10
- export { assertValidated, builderErrorUnvalidated } from './brand.js';
6
+ export type { BuilderComponentVariantsValidationResult, BuilderVariantsValidationOptions } from './variants';
7
+ export { assertValidated } from './brand.js';
11
8
  export { validateBuilder } from './builder.js';
12
- export { builderErrorUnmetExpectation } from './expectations.js';
13
- export { builderErrorInvalidCollection, builderErrorInvalidOption, validateInstance } from './instance.js';
14
- export { builderErrorDuplicateName, builderErrorInvalidCollectionBounds, builderErrorInvalidPath, builderErrorInvalidSelectMapKey, validateModel } from './model.js';
15
- export { builderErrorMissingReference, builderErrorUnboundParameter } from './resolve.js';
16
- export { builderErrorInvalidInput } from './result.js';
9
+ export { validateInstance } from './instance.js';
10
+ export { validateModel } from './model.js';
17
11
  export { validateUI } from './ui.js';
18
- export { builderErrorInvalidDetail, builderErrorInvalidVariant, builderErrorMissingComponent, builderErrorMissingDetail, builderErrorMissingVariant, builderErrorUnexpectedComponent, builderErrorUnexpectedDetail, validateVariants } from './variants.js';
12
+ export { validateVariants } from './variants.js';
@@ -1,9 +1,6 @@
1
- export { assertValidated, builderErrorUnvalidated } from './brand.js';
1
+ export { assertValidated } from './brand.js';
2
2
  export { validateBuilder } from './builder.js';
3
- export { builderErrorUnmetExpectation } from './expectations.js';
4
- export { builderErrorInvalidCollection, builderErrorInvalidOption, validateInstance } from './instance.js';
5
- export { builderErrorDuplicateName, builderErrorInvalidCollectionBounds, builderErrorInvalidPath, builderErrorInvalidSelectMapKey, validateModel } from './model.js';
6
- export { builderErrorMissingReference, builderErrorUnboundParameter } from './resolve.js';
7
- export { builderErrorInvalidInput } from './result.js';
3
+ export { validateInstance } from './instance.js';
4
+ export { validateModel } from './model.js';
8
5
  export { validateUI } from './ui.js';
9
- export { builderErrorInvalidDetail, builderErrorInvalidVariant, builderErrorMissingComponent, builderErrorMissingDetail, builderErrorMissingVariant, builderErrorUnexpectedComponent, builderErrorUnexpectedDetail, validateVariants } from './variants.js';
6
+ export { validateVariants } from './variants.js';
@@ -1,19 +1,6 @@
1
1
  import type { BuilderInstanceValidated, BuilderModelValidated } from '../entities/index';
2
- import type { BuilderErrorLocation } from '../exception';
3
2
  import type { BuilderInstance } from '../instance';
4
3
  import type { ValidationResult } from './result';
5
- export declare function builderErrorInvalidOption(name: string, value: unknown, location?: BuilderErrorLocation): {
6
- name: string;
7
- value: unknown;
8
- kind: "invalid-option";
9
- location: BuilderErrorLocation;
10
- };
11
- export type BuilderErrorInvalidOption = ReturnType<typeof builderErrorInvalidOption>;
12
- export declare function builderErrorInvalidCollection(name: string, location?: BuilderErrorLocation): {
13
- name: string;
14
- kind: "invalid-collection";
15
- location: BuilderErrorLocation;
16
- };
17
- export type BuilderErrorInvalidCollection = ReturnType<typeof builderErrorInvalidCollection>;
4
+ import { BuilderValidateErrors } from './errors.js';
18
5
  export type BuilderInstanceValidationResult = ValidationResult<BuilderInstanceValidated>;
19
- export declare function validateInstance(model: BuilderModelValidated, instance: BuilderInstance): BuilderInstanceValidationResult;
6
+ export declare function validateInstance(model: BuilderModelValidated, instance: BuilderInstance, errors?: BuilderValidateErrors): BuilderInstanceValidationResult;
@@ -1,46 +1,48 @@
1
1
  import { check } from '../check.js';
2
2
  import { optionValueSchema } from '../entities/index.js';
3
- import { builderError } from '../exception.js';
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 builderErrorInvalidOption(name, value, location = []) {
7
- return { ...builderError('invalid-option', location), name, value };
8
- }
9
- export function builderErrorInvalidCollection(name, location = []) {
10
- return { ...builderError('invalid-collection', location), name };
11
- }
12
- export function validateInstance(model, instance) {
13
- const errors = checkInstance(model, instance, ['instance']);
14
- return [validate(instance), errors];
15
- }
16
- function checkInstance(model, instance, location) {
17
- const { options, collections } = model;
18
- const optionErrors = options.flatMap((option) => {
19
- const { name } = option;
20
- const payload = resolveOption(option, instance);
21
- if (!payload) {
22
- return [];
23
- }
24
- const value = instance[name];
25
- if (!check.is(optionValueSchema(payload), value)) {
26
- return [builderErrorInvalidOption(name, value, [...location, name])];
27
- }
28
- return [];
29
- });
30
- const collectionErrors = collections.flatMap((collection) => {
31
- const { name } = collection;
32
- const payload = resolveCollection(collection, instance);
33
- if (!payload) {
34
- return [];
35
- }
36
- const existing = instance[name];
37
- if (!Array.isArray(existing)) {
38
- return [builderErrorInvalidCollection(name, [...location, name])];
39
- }
40
- return existing.flatMap((itemInstance, index) => checkInstance(payload.model, itemInstance, [...location, name, index]).map((error) => ({
41
- ...error,
42
- name: `${name}[${index}].${error.name}`
43
- })));
6
+ import { BuilderValidateErrors } from './errors.js';
7
+ export function validateInstance(model, instance, errors = new BuilderValidateErrors()) {
8
+ errors.scope('instance', () => {
9
+ checkInstance(model, instance);
44
10
  });
45
- return [...optionErrors, ...collectionErrors];
11
+ return [validate(instance), errors.errors];
12
+ function checkInstance(scopeModel, scopeInstance, namePrefix = '') {
13
+ scopeModel.options.forEach((option) => {
14
+ const { name } = option;
15
+ const payload = resolveOption(option, scopeModel, scopeInstance);
16
+ if (!payload) {
17
+ return;
18
+ }
19
+ const value = scopeInstance[name];
20
+ if (!check.is(optionValueSchema(payload), value)) {
21
+ errors.scope(name, () => {
22
+ errors.invalidOption(`${namePrefix}${name}`, value);
23
+ });
24
+ }
25
+ });
26
+ scopeModel.collections.forEach((collection) => {
27
+ const { name } = collection;
28
+ const payload = resolveCollection(collection, scopeModel, scopeInstance);
29
+ if (!payload) {
30
+ return;
31
+ }
32
+ const existing = scopeInstance[name];
33
+ if (!check.is(BuilderInstancesSchema, existing)) {
34
+ errors.scope(name, () => {
35
+ errors.invalidCollection(`${namePrefix}${name}`);
36
+ });
37
+ return;
38
+ }
39
+ errors.scope(name, () => {
40
+ existing.forEach((itemInstance, index) => {
41
+ errors.scope(index, () => {
42
+ checkInstance(payload.model, itemInstance, `${namePrefix}${name}[${index}].`);
43
+ });
44
+ });
45
+ });
46
+ });
47
+ }
46
48
  }
@@ -1,36 +1,9 @@
1
1
  import type { BuilderModelSerialised, BuilderModelValidated, BuilderRefEntities } from '../entities/index';
2
- import type { BuilderErrorLocation, BuilderErrors } from '../exception';
3
2
  import type { ParamableSerialised } from '../references';
4
3
  import type { BuilderResolve } from './resolve';
5
4
  import type { ValidationResult } from './result';
5
+ import { BuilderValidateErrors } from './errors.js';
6
6
  export type BuilderModelValidationResult = ValidationResult<BuilderModelValidated>;
7
- export declare function builderErrorDuplicateName(name: string, location?: BuilderErrorLocation): {
8
- name: string;
9
- kind: "duplicate-name";
10
- location: BuilderErrorLocation;
11
- };
12
- export type BuilderErrorDuplicateName = ReturnType<typeof builderErrorDuplicateName>;
13
- export declare function builderErrorInvalidCollectionBounds(name: string, min: number, max: number, location?: BuilderErrorLocation): {
14
- name: string;
15
- min: number;
16
- max: number;
17
- kind: "invalid-collection-bounds";
18
- location: BuilderErrorLocation;
19
- };
20
- export type BuilderErrorInvalidCollectionBounds = ReturnType<typeof builderErrorInvalidCollectionBounds>;
21
- export type BuilderErrorInvalidPathReason = 'shape' | 'out-of-bounds' | 'missing-collection' | 'option-not-found';
22
- export declare function builderErrorInvalidPath(reason: BuilderErrorInvalidPathReason, location?: BuilderErrorLocation): {
23
- reason: BuilderErrorInvalidPathReason;
24
- kind: "invalid-path";
25
- location: BuilderErrorLocation;
26
- };
27
- export type BuilderErrorInvalidPath = ReturnType<typeof builderErrorInvalidPath>;
28
- export declare function builderErrorInvalidSelectMapKey(key: string, location?: BuilderErrorLocation): {
29
- key: string;
30
- kind: "invalid-select-map-key";
31
- location: BuilderErrorLocation;
32
- };
33
- export type BuilderErrorInvalidSelectMapKey = ReturnType<typeof builderErrorInvalidSelectMapKey>;
34
- export declare function validateModel(input: unknown, references?: BuilderRefEntities): BuilderModelValidationResult;
35
- export declare function checkModelExpectations(mergedModel: BuilderModelSerialised, model: BuilderModelSerialised, location: BuilderErrorLocation): BuilderErrors;
36
- export declare function validateModelStructure(input: ParamableSerialised<BuilderModelSerialised>, resolve: BuilderResolve, location: BuilderErrorLocation): BuilderModelValidationResult;
7
+ export declare function validateModel(input: unknown, references?: BuilderRefEntities, errors?: BuilderValidateErrors): BuilderModelValidationResult;
8
+ export declare function checkModelExpectations(mergedModel: BuilderModelSerialised, rootModel: BuilderModelSerialised, errors: BuilderValidateErrors): void;
9
+ export declare function validateModelStructure(input: ParamableSerialised<BuilderModelSerialised>, resolve: BuilderResolve, errors: BuilderValidateErrors): BuilderModelValidated;