@builder-builder/builder 0.0.9 → 0.0.11

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 (191) hide show
  1. package/dist/bb.d.ts +28 -0
  2. package/dist/bb.js +49 -0
  3. package/dist/check.d.ts +1 -1
  4. package/dist/check.js +4 -2
  5. package/dist/entities/builder/bind.d.ts +4 -0
  6. package/dist/entities/builder/builder.d.ts +17 -490
  7. package/dist/entities/builder/builder.js +19 -76
  8. package/dist/entities/builder/factory.d.ts +7 -0
  9. package/dist/entities/builder/factory.js +4 -0
  10. package/dist/entities/builder/index.d.ts +3 -6
  11. package/dist/entities/builder/index.js +1 -2
  12. package/dist/entities/collection/collection.d.ts +71 -20
  13. package/dist/entities/collection/collection.js +10 -27
  14. package/dist/entities/collection/config.d.ts +40 -1049
  15. package/dist/entities/collection/config.js +11 -11
  16. package/dist/entities/collection/expectation.d.ts +8 -4
  17. package/dist/entities/collection/index.d.ts +3 -3
  18. package/dist/entities/collection/index.js +1 -1
  19. package/dist/entities/collection/when.d.ts +6 -5
  20. package/dist/entities/component/component.d.ts +272 -300
  21. package/dist/entities/component/component.js +9 -8
  22. package/dist/entities/component/details.d.ts +35 -60
  23. package/dist/entities/component/details.js +9 -9
  24. package/dist/entities/component/expectation.d.ts +7 -4
  25. package/dist/entities/component/expectation.js +0 -3
  26. package/dist/entities/component/field.d.ts +50 -0
  27. package/dist/entities/component/field.js +41 -0
  28. package/dist/entities/component/index.d.ts +5 -3
  29. package/dist/entities/component/index.js +3 -2
  30. package/dist/entities/component/when.d.ts +5 -5
  31. package/dist/entities/component/when.js +2 -2
  32. package/dist/entities/entry.d.ts +4 -0
  33. package/dist/entities/expectation.d.ts +10 -22
  34. package/dist/entities/expectation.js +2 -7
  35. package/dist/entities/index.d.ts +21 -16
  36. package/dist/entities/index.js +10 -8
  37. package/dist/entities/kind.d.ts +9 -0
  38. package/dist/entities/kind.js +5 -0
  39. package/dist/entities/model/bind.d.ts +83 -0
  40. package/dist/entities/model/expectation.d.ts +16 -0
  41. package/dist/entities/model/index.d.ts +7 -0
  42. package/dist/entities/model/index.js +2 -0
  43. package/dist/entities/model/methods.d.ts +57 -0
  44. package/dist/entities/{builder → model}/methods.js +8 -8
  45. package/dist/entities/model/model.d.ts +39 -0
  46. package/dist/entities/model/model.js +73 -0
  47. package/dist/entities/model/models.d.ts +39 -0
  48. package/dist/entities/model/models.js +14 -0
  49. package/dist/entities/{builder → model}/state.d.ts +10 -10
  50. package/dist/entities/option/index.d.ts +2 -2
  51. package/dist/entities/option/index.js +2 -2
  52. package/dist/entities/option/option.d.ts +216 -214
  53. package/dist/entities/option/option.js +9 -8
  54. package/dist/entities/option/select.d.ts +2 -12
  55. package/dist/entities/option/select.js +6 -3
  56. package/dist/entities/option/toggle.d.ts +2 -9
  57. package/dist/entities/option/toggle.js +3 -3
  58. package/dist/entities/option/values.d.ts +4 -24
  59. package/dist/entities/option/values.js +10 -4
  60. package/dist/entities/option/when.d.ts +6 -5
  61. package/dist/entities/refs.d.ts +6 -0
  62. package/dist/entities/refs.js +1 -0
  63. package/dist/entities/serialise.d.ts +393 -3568
  64. package/dist/entities/serialise.js +160 -31
  65. package/dist/entities/ui/describe.d.ts +23 -57
  66. package/dist/entities/ui/describe.js +4 -5
  67. package/dist/entities/ui/index.d.ts +4 -9
  68. package/dist/entities/ui/index.js +2 -4
  69. package/dist/entities/ui/page.d.ts +23 -57
  70. package/dist/entities/ui/page.js +4 -5
  71. package/dist/entities/ui/pages.d.ts +18 -403
  72. package/dist/entities/ui/pages.js +7 -7
  73. package/dist/entities/ui/ui.d.ts +22 -1575
  74. package/dist/entities/ui/ui.js +15 -28
  75. package/dist/entities/ui/uis.d.ts +5 -9
  76. package/dist/entities/ui/uis.js +12 -19
  77. package/dist/entities/validated.d.ts +35 -0
  78. package/dist/entities/validated.js +1 -0
  79. package/dist/entities/when.d.ts +79 -70
  80. package/dist/entities/when.js +11 -7
  81. package/dist/environment.d.ts +5 -0
  82. package/dist/environment.js +2 -0
  83. package/dist/exception.d.ts +8 -3
  84. package/dist/exception.js +3 -0
  85. package/dist/index.d.ts +21 -24
  86. package/dist/index.js +5 -10
  87. package/dist/instance.d.ts +56 -0
  88. package/dist/instance.js +10 -0
  89. package/dist/mappers/index.d.ts +7 -5
  90. package/dist/mappers/index.js +5 -3
  91. package/dist/mappers/instance.d.ts +3 -0
  92. package/dist/mappers/instance.js +35 -0
  93. package/dist/mappers/order.d.ts +6 -0
  94. package/dist/mappers/order.js +22 -0
  95. package/dist/mappers/render/pages.d.ts +4 -4
  96. package/dist/mappers/render/render.d.ts +2 -3
  97. package/dist/mappers/render/render.js +83 -78
  98. package/dist/mappers/resolve.d.ts +5 -9
  99. package/dist/mappers/resolve.js +25 -33
  100. package/dist/mappers/variants/index.d.ts +1 -0
  101. package/dist/mappers/variants/index.js +1 -0
  102. package/dist/mappers/variants/option-graph.d.ts +19 -0
  103. package/dist/mappers/{models → variants}/option-graph.js +33 -22
  104. package/dist/mappers/variants/variants.d.ts +3 -0
  105. package/dist/mappers/variants/variants.js +57 -0
  106. package/dist/private.d.ts +4 -0
  107. package/dist/private.js +4 -0
  108. package/dist/references.d.ts +27 -36
  109. package/dist/references.js +19 -12
  110. package/dist/serialisable.d.ts +1 -9
  111. package/dist/serialisable.js +2 -3
  112. package/dist/validate/brand.d.ts +14 -0
  113. package/dist/validate/brand.js +17 -0
  114. package/dist/validate/builder.d.ts +4 -0
  115. package/dist/validate/builder.js +27 -0
  116. package/dist/validate/expectations.d.ts +10 -0
  117. package/dist/validate/expectations.js +12 -0
  118. package/dist/validate/index.d.ts +18 -0
  119. package/dist/validate/index.js +9 -0
  120. package/dist/validate/instance.d.ts +19 -0
  121. package/dist/validate/instance.js +46 -0
  122. package/dist/validate/model.d.ts +36 -0
  123. package/dist/validate/model.js +196 -0
  124. package/dist/validate/resolve.d.ts +16 -0
  125. package/dist/validate/resolve.js +91 -0
  126. package/dist/validate/result.d.ts +8 -0
  127. package/dist/validate/result.js +4 -0
  128. package/dist/validate/ui.d.ts +8 -0
  129. package/dist/validate/ui.js +77 -0
  130. package/dist/validate/variants.d.ts +59 -0
  131. package/dist/validate/variants.js +102 -0
  132. package/package.json +12 -9
  133. package/dist/entities/builder/builders.d.ts +0 -20
  134. package/dist/entities/builder/builders.js +0 -18
  135. package/dist/entities/builder/expectation.d.ts +0 -12
  136. package/dist/entities/builder/methods.d.ts +0 -58
  137. package/dist/entities/builder/parameter.d.ts +0 -62
  138. package/dist/entities/builder/parameter.js +0 -18
  139. package/dist/entities/builder/validate.d.ts +0 -3
  140. package/dist/entities/builder/validate.js +0 -108
  141. package/dist/entities/errors.d.ts +0 -21
  142. package/dist/entities/ui/label.d.ts +0 -18
  143. package/dist/entities/ui/label.js +0 -12
  144. package/dist/entities/ui/parameter.d.ts +0 -7
  145. package/dist/entities/ui/parameter.js +0 -29
  146. package/dist/entities/ui/validate.d.ts +0 -8
  147. package/dist/entities/ui/validate.js +0 -21
  148. package/dist/entities/validate.d.ts +0 -28
  149. package/dist/mappers/assert/builder.d.ts +0 -2
  150. package/dist/mappers/assert/builder.js +0 -46
  151. package/dist/mappers/assert/expectation.d.ts +0 -2
  152. package/dist/mappers/assert/expectation.js +0 -23
  153. package/dist/mappers/assert/index.d.ts +0 -6
  154. package/dist/mappers/assert/index.js +0 -4
  155. package/dist/mappers/assert/model.d.ts +0 -13
  156. package/dist/mappers/assert/model.js +0 -47
  157. package/dist/mappers/assert/models.d.ts +0 -33
  158. package/dist/mappers/assert/models.js +0 -74
  159. package/dist/mappers/assert/ui.d.ts +0 -2
  160. package/dist/mappers/assert/ui.js +0 -22
  161. package/dist/mappers/instance/index.d.ts +0 -1
  162. package/dist/mappers/instance/index.js +0 -1
  163. package/dist/mappers/instance/instance.d.ts +0 -4
  164. package/dist/mappers/instance/instance.js +0 -33
  165. package/dist/mappers/models/component-graph.d.ts +0 -9
  166. package/dist/mappers/models/component-graph.js +0 -51
  167. package/dist/mappers/models/graph.d.ts +0 -12
  168. package/dist/mappers/models/graph.js +0 -17
  169. package/dist/mappers/models/index.d.ts +0 -1
  170. package/dist/mappers/models/index.js +0 -1
  171. package/dist/mappers/models/models.d.ts +0 -3
  172. package/dist/mappers/models/models.js +0 -37
  173. package/dist/mappers/models/option-graph.d.ts +0 -9
  174. package/dist/mappers/order/index.d.ts +0 -2
  175. package/dist/mappers/order/index.js +0 -1
  176. package/dist/mappers/order/order.d.ts +0 -14
  177. package/dist/mappers/order/order.js +0 -31
  178. package/dist/model.d.ts +0 -14
  179. package/dist/walker/index.d.ts +0 -2
  180. package/dist/walker/index.js +0 -1
  181. package/dist/walker/walkable.d.ts +0 -4
  182. package/dist/walker/walkable.js +0 -4
  183. package/dist/walker/walker.d.ts +0 -18
  184. package/dist/walker/walker.js +0 -103
  185. package/dist/walker/walkers.d.ts +0 -8
  186. package/dist/walker/walkers.js +0 -51
  187. /package/dist/entities/builder/{expectation.js → bind.js} +0 -0
  188. /package/dist/entities/{builder/state.js → entry.js} +0 -0
  189. /package/dist/entities/{errors.js → model/bind.js} +0 -0
  190. /package/dist/entities/{validate.js → model/expectation.js} +0 -0
  191. /package/dist/{model.js → entities/model/state.js} +0 -0
package/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
- import { builders, collectionConfig, collectionExpectation, collectionWhen, componentDetails, componentExpectation, componentWhen, detailExpectation, optionExpectation, optionWhen, uis } from './entities/index.js';
2
- import { createInstance, createModels } from './mappers/index.js';
3
- export const builder = builders;
1
+ export { bb } from './bb.js';
2
+ export { Builder, builder, detailBoolean, detailNumber, detailString, model, parameter, ref, select, serialise, toggleBoolean, toggleNumber, toggleString } from './entities/index.js';
3
+ export { BuilderException } from './exception.js';
4
+ export { ordinal } from './mappers/index.js';
5
+ import { collectionConfig, collectionExpectation, collectionWhen, componentDetails, componentExpectation, componentWhen, optionExpectation, optionWhen, uis } from './entities/index.js';
4
6
  export const collection = Object.assign(collectionConfig, {
5
7
  ...collectionWhen
6
8
  });
@@ -10,14 +12,7 @@ export const component = Object.assign(componentDetails, {
10
12
  export const has = {
11
13
  collection: collectionExpectation,
12
14
  component: componentExpectation,
13
- detail: detailExpectation,
14
15
  option: optionExpectation
15
16
  };
16
- export const instance = createInstance;
17
- export const models = createModels;
18
17
  export const option = optionWhen;
19
18
  export const ui = uis;
20
- export { BuilderException } from './exception.js';
21
- export { BuilderSerialisedSchema } from './entities/builder/index.js';
22
- export { deserialise, parameter, select, serialise, toggleBoolean, toggleNumber, toggleString } from './entities/index.js';
23
- export { order, ordinal, render } from './mappers/index.js';
@@ -0,0 +1,56 @@
1
+ import * as v from 'valibot';
2
+ import { type BuilderPrimitive } from './primitive.js';
3
+ export type BuilderInstance = {
4
+ readonly [key: string]: BuilderPrimitive | BuilderInstances;
5
+ };
6
+ export declare const BuilderInstanceSchema: v.GenericSchema<BuilderInstance>;
7
+ export declare const BuilderInstancesSchema: v.SchemaWithPipe<readonly [v.ArraySchema<v.GenericSchema<BuilderInstance>, undefined>, v.ReadonlyAction<BuilderInstance[]>]>;
8
+ export type BuilderInstances = v.InferOutput<typeof BuilderInstancesSchema>;
9
+ export type BuilderInstanceInput = Readonly<Record<string, unknown>>;
10
+ export declare const BuilderVariantSchema: v.SchemaWithPipe<readonly [v.ObjectSchema<{
11
+ readonly instance: v.GenericSchema<BuilderInstance>;
12
+ readonly details: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.NullableSchema<v.UnionSchema<[v.StringSchema<undefined>, v.BooleanSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>, undefined>, undefined>;
13
+ }, undefined>, v.ReadonlyAction<{
14
+ instance: BuilderInstance;
15
+ details?: {
16
+ [x: string]: string | number | boolean | null;
17
+ } | undefined;
18
+ }>]>;
19
+ export type BuilderVariant = v.InferOutput<typeof BuilderVariantSchema>;
20
+ export declare const BuilderVariantsSchema: v.SchemaWithPipe<readonly [v.ArraySchema<v.SchemaWithPipe<readonly [v.ObjectSchema<{
21
+ readonly instance: v.GenericSchema<BuilderInstance>;
22
+ readonly details: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.NullableSchema<v.UnionSchema<[v.StringSchema<undefined>, v.BooleanSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>, undefined>, undefined>;
23
+ }, undefined>, v.ReadonlyAction<{
24
+ instance: BuilderInstance;
25
+ details?: {
26
+ [x: string]: string | number | boolean | null;
27
+ } | undefined;
28
+ }>]>, undefined>, v.ReadonlyAction<Readonly<{
29
+ instance: BuilderInstance;
30
+ details?: {
31
+ [x: string]: string | number | boolean | null;
32
+ } | undefined;
33
+ }>[]>]>;
34
+ export type BuilderVariants = v.InferOutput<typeof BuilderVariantsSchema>;
35
+ export declare const BuilderComponentVariantsSchema: v.SchemaWithPipe<readonly [v.RecordSchema<v.StringSchema<undefined>, v.SchemaWithPipe<readonly [v.ArraySchema<v.SchemaWithPipe<readonly [v.ObjectSchema<{
36
+ readonly instance: v.GenericSchema<BuilderInstance>;
37
+ readonly details: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.NullableSchema<v.UnionSchema<[v.StringSchema<undefined>, v.BooleanSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>, undefined>, undefined>;
38
+ }, undefined>, v.ReadonlyAction<{
39
+ instance: BuilderInstance;
40
+ details?: {
41
+ [x: string]: string | number | boolean | null;
42
+ } | undefined;
43
+ }>]>, undefined>, v.ReadonlyAction<Readonly<{
44
+ instance: BuilderInstance;
45
+ details?: {
46
+ [x: string]: string | number | boolean | null;
47
+ } | undefined;
48
+ }>[]>]>, undefined>, v.ReadonlyAction<{
49
+ readonly [x: string]: readonly Readonly<{
50
+ instance: BuilderInstance;
51
+ details?: {
52
+ [x: string]: string | number | boolean | null;
53
+ } | undefined;
54
+ }>[];
55
+ }>]>;
56
+ export type BuilderComponentVariants = v.InferOutput<typeof BuilderComponentVariantsSchema>;
@@ -0,0 +1,10 @@
1
+ import * as v from 'valibot';
2
+ import { BuilderPrimitiveSchema } from './primitive.js';
3
+ export const BuilderInstanceSchema = v.pipe(v.record(v.string(), v.union([BuilderPrimitiveSchema, v.lazy(() => BuilderInstancesSchema)])), v.readonly());
4
+ export const BuilderInstancesSchema = v.pipe(v.array(BuilderInstanceSchema), v.readonly());
5
+ export const BuilderVariantSchema = v.pipe(v.object({
6
+ instance: BuilderInstanceSchema,
7
+ details: v.optional(v.record(v.string(), BuilderPrimitiveSchema))
8
+ }), v.readonly());
9
+ export const BuilderVariantsSchema = v.pipe(v.array(BuilderVariantSchema), v.readonly());
10
+ export const BuilderComponentVariantsSchema = v.pipe(v.record(v.string(), BuilderVariantsSchema), v.readonly());
@@ -1,7 +1,9 @@
1
- export type { BuilderErrorInvalidCollection, BuilderErrorInvalidOption, BuilderErrorInvalidVariant, BuilderErrorMissingComponent, BuilderErrorMissingDetail, BuilderErrorMissingVariant, BuilderErrorUnexpectedComponent, BuilderErrorUnexpectedDetail } from './assert/index';
2
- export type { BuilderOrder } from './order/index';
1
+ export type { BuilderComponentVariantsValidationResult, BuilderErrorDuplicateName, BuilderErrorInvalidCollection, BuilderErrorInvalidCollectionBounds, BuilderErrorInvalidDetail, BuilderErrorInvalidInput, BuilderErrorInvalidOption, BuilderErrorInvalidPath, BuilderErrorInvalidPathReason, BuilderErrorInvalidSelectMapKey, BuilderErrorInvalidVariant, BuilderErrorMissingComponent, BuilderErrorMissingDetail, BuilderErrorMissingReference, BuilderErrorMissingVariant, BuilderErrorUnboundParameter, BuilderErrorUnexpectedComponent, BuilderErrorUnexpectedDetail, BuilderErrorUnmetExpectation, BuilderErrorUnvalidated, BuilderInstanceValidationResult, BuilderModelValidationResult, BuilderUIValidationResult, BuilderValidationResult, BuilderVariantsValidationOptions } from '../validate/index';
2
+ export type { BuilderOrder } from './order';
3
3
  export type { BuilderRenderOption, BuilderRenderOptions, BuilderRenderPage, BuilderRenderPages, BuilderRenderResult, BuilderRenderUpdate } from './render/index';
4
- export { createInstance } from './instance/index.js';
5
- export { createModels } from './models/index.js';
6
- export { order } from './order/index.js';
4
+ export { assertValidated, validateBuilder, validateInstance, validateModel, validateUI, validateVariants } from '../validate/index.js';
5
+ export { createInstance } from './instance.js';
6
+ export { createVariants } from './variants/index.js';
7
+ export { order } from './order.js';
7
8
  export { ordinal, render } from './render/index.js';
9
+ export { resolveCollection, resolveComponent, resolveOption } from './resolve.js';
@@ -1,4 +1,6 @@
1
- export { createInstance } from './instance/index.js';
2
- export { createModels } from './models/index.js';
3
- export { order } from './order/index.js';
1
+ export { assertValidated, validateBuilder, validateInstance, validateModel, validateUI, validateVariants } from '../validate/index.js';
2
+ export { createInstance } from './instance.js';
3
+ export { createVariants } from './variants/index.js';
4
+ export { order } from './order.js';
4
5
  export { ordinal, render } from './render/index.js';
6
+ export { resolveCollection, resolveComponent, resolveOption } from './resolve.js';
@@ -0,0 +1,3 @@
1
+ import type { BuilderModelValidated, BuilderRefEntities, BuilderValidated } from '../entities/index';
2
+ import type { BuilderInstance, BuilderInstanceInput } from '../instance';
3
+ export declare function createInstance(entity: BuilderValidated | BuilderModelValidated, partial?: BuilderInstanceInput, refs?: BuilderRefEntities): BuilderInstance;
@@ -0,0 +1,35 @@
1
+ import { check } from '../check.js';
2
+ import { optionValueSchema } from '../entities/index.js';
3
+ import { resolveCollection, resolveOption } from './resolve.js';
4
+ export function createInstance(entity, partial = {}, refs = []) {
5
+ const model = 'model' in entity ? entity.model : entity;
6
+ return buildInstance(model, partial, refs);
7
+ }
8
+ function buildInstance(model, partial, refs) {
9
+ let instance = { ...partial };
10
+ model.options.forEach((option) => {
11
+ const { name } = option;
12
+ const payload = resolveOption(option, instance, refs);
13
+ if (payload == null) {
14
+ return;
15
+ }
16
+ const existing = instance[name];
17
+ if (check.is(optionValueSchema(payload), existing)) {
18
+ return;
19
+ }
20
+ instance = { ...instance, [name]: payload.defaultValue };
21
+ });
22
+ model.collections.forEach((collection) => {
23
+ const { name } = collection;
24
+ const payload = resolveCollection(collection, instance, refs);
25
+ if (payload == null) {
26
+ return;
27
+ }
28
+ const existing = instance[name];
29
+ const existingItems = Array.isArray(existing) ? existing : [];
30
+ const count = Math.max(existingItems.length, payload.min);
31
+ const items = Array.from({ length: count }, (_, index) => buildInstance(payload.model, existingItems[index] ?? {}, refs));
32
+ instance = { ...instance, [name]: items };
33
+ });
34
+ return instance;
35
+ }
@@ -0,0 +1,6 @@
1
+ import type { BuilderComponentVariantsValidated, BuilderInstanceValidated, BuilderModelValidated, BuilderRefEntities } from '../entities/index';
2
+ import type { BuilderVariant } from '../instance';
3
+ export interface BuilderOrder {
4
+ readonly [key: string]: BuilderVariant | BuilderOrder | ReadonlyArray<BuilderOrder> | null;
5
+ }
6
+ export declare function order(model: BuilderModelValidated, instance: BuilderInstanceValidated, variants: BuilderComponentVariantsValidated, refs?: BuilderRefEntities): BuilderOrder;
@@ -0,0 +1,22 @@
1
+ import { resolveCollection, resolveComponent } from './resolve.js';
2
+ export function order(model, instance, variants, refs = []) {
3
+ const result = {};
4
+ model.components.forEach((component) => {
5
+ if (resolveComponent(component, instance, refs) == null) {
6
+ return;
7
+ }
8
+ const componentVariants = variants[component.name] ?? [];
9
+ result[component.name] =
10
+ componentVariants.find((variant) => Object.entries(variant.instance).every(([key, value]) => instance[key] === value)) ?? null;
11
+ });
12
+ model.collections.forEach((collection) => {
13
+ const { name } = collection;
14
+ const payload = resolveCollection(collection, instance, refs);
15
+ if (payload == null) {
16
+ return;
17
+ }
18
+ const itemInstances = instance[name];
19
+ result[name] = itemInstances.map((itemInstance) => order(payload.model, itemInstance, variants, refs));
20
+ });
21
+ return result;
22
+ }
@@ -1,11 +1,11 @@
1
- import type { BuilderOptionValues } from '../../entities/index';
1
+ import type { BuilderOptionValuesSerialised } from '../../entities/index';
2
2
  import type { BuilderPrimitive } from '../../primitive';
3
- import type { BuilderModel } from '../../model';
4
- export type BuilderRenderUpdate = (model: BuilderModel, primitive: BuilderPrimitive) => BuilderModel;
3
+ import type { BuilderInstance } from '../../instance';
4
+ export type BuilderRenderUpdate = (model: BuilderInstance, primitive: BuilderPrimitive) => BuilderInstance;
5
5
  export type BuilderRenderOption = Readonly<{
6
6
  value: BuilderPrimitive;
7
7
  update: BuilderRenderUpdate;
8
- option: BuilderOptionValues;
8
+ option: BuilderOptionValuesSerialised;
9
9
  }>;
10
10
  export type BuilderRenderOptions = ReadonlyArray<BuilderRenderOption>;
11
11
  export type BuilderRenderPage = Readonly<{
@@ -1,8 +1,7 @@
1
- import type { BuilderDescription, BuilderUIGeneric } from '../../entities/index';
2
- import type { BuilderModel } from '../../model';
1
+ import type { BuilderDescription, BuilderInstanceValidated, BuilderRefEntities, BuilderValidated } from '../../entities/index';
3
2
  import type { BuilderRenderPages } from './pages';
4
3
  export type BuilderRenderResult = Readonly<{
5
4
  layout: BuilderRenderPages;
6
5
  description: BuilderDescription;
7
6
  }>;
8
- export declare function render(ui: BuilderUIGeneric, rootModel: BuilderModel): BuilderRenderResult;
7
+ export declare function render(builder: BuilderValidated, instance: BuilderInstanceValidated, refs?: BuilderRefEntities): BuilderRenderResult;
@@ -1,112 +1,117 @@
1
1
  import * as v from 'valibot';
2
- import { assertModel, assertUI } from '../assert/index.js';
3
2
  import { check } from '../../check.js';
3
+ import { BuilderInstancesSchema } from '../../instance.js';
4
4
  import { readPath } from '../../paths.js';
5
- import { resolveCollection, resolveOption } from '../resolve.js';
5
+ import { resolveCollection, resolveOption, resolveRef } from '../resolve.js';
6
6
  import { ordinal } from './ordinal.js';
7
- export function render(ui, rootModel) {
8
- assertUI(ui);
9
- const rootBuilder = ui.builder;
10
- assertModel(rootBuilder, rootModel);
7
+ export function render(builder, instance, refs = []) {
11
8
  const layout = [];
12
9
  const description = [];
13
- walk(rootBuilder, rootModel, [], [], ui.items);
10
+ walkTree(builder.ui);
14
11
  return { layout, description };
15
- function walk(builder, model, collectionPath, labelContext, items) {
16
- function composeLabel(label) {
17
- if (labelContext.length === 0) {
18
- return label.label;
19
- }
20
- return `${labelContext.join(', ')}, ${label.label}`;
21
- }
12
+ function walkTree(ui) {
13
+ ui.uis.forEach((nested) => walkTree(nested));
14
+ walkItems(ui.items, builder.model, [], [], instance);
15
+ }
16
+ function walkItems(items, model, collectionPath, labelContext, currentInstance) {
22
17
  items.forEach((item) => {
23
- if (item.type === 'pages') {
24
- const collection = findCollection(builder, model, item.name);
25
- if (!collection) {
26
- return;
27
- }
28
- const models = model[collection.name];
29
- models.forEach((collectionModel, itemIndex) => {
30
- const labelSegment = `${ordinal(itemIndex)} ${item.label.label}`;
31
- walk(collection.payload.builder, collectionModel, [...collectionPath, item.name, itemIndex], [...labelContext, labelSegment], item.items);
32
- });
33
- return;
34
- }
35
18
  if (item.type === 'page') {
36
- const options = item.paths.flatMap((path) => {
37
- const option = findResolvedOption(builder, model, path);
38
- if (!option) {
39
- return [];
40
- }
41
- const fullPath = [...collectionPath, ...path];
42
- return [
43
- {
44
- option: option.payload,
45
- value: readPath(model, fullPath),
46
- update: (updateModel, updateValue) => setPath(updateModel, fullPath, updateValue)
47
- }
48
- ];
49
- });
50
- if (options.length === 0) {
51
- return;
52
- }
53
- layout.push({ label: composeLabel(item.label), options });
19
+ emitPage(item, model, collectionPath, labelContext, currentInstance);
54
20
  return;
55
21
  }
56
22
  if (item.type === 'describe') {
57
- const composedLabel = composeLabel(item.label);
58
- const values = item.paths.flatMap((path) => {
59
- const option = findResolvedOption(builder, model, path);
60
- if (!option) {
61
- return [];
62
- }
63
- const fullPath = [...collectionPath, ...path];
64
- const value = readPath(model, fullPath);
65
- if (value == null) {
66
- return [];
67
- }
68
- return [value];
69
- });
70
- if (values.length === 0) {
71
- return;
23
+ emitDescribe(item, model, labelContext, currentInstance);
24
+ return;
25
+ }
26
+ const collection = findCollection(model, currentInstance, item.name);
27
+ if (collection == null) {
28
+ return;
29
+ }
30
+ const itemInstances = currentInstance[item.name];
31
+ check.assert(BuilderInstancesSchema, itemInstances, 'Collection field is not an array! ❌');
32
+ itemInstances.forEach((itemInstance, index) => {
33
+ walkItems(item.items, collection.model, [...collectionPath, item.name, index], [...labelContext, `${ordinal(index)} ${composeLabel(item.label)}`], itemInstance);
34
+ });
35
+ });
36
+ }
37
+ function emitPage(page, model, collectionPath, labelContext, currentInstance) {
38
+ const options = page.paths.flatMap((path) => {
39
+ const option = findOption(model, currentInstance, path);
40
+ if (option == null) {
41
+ return [];
42
+ }
43
+ const fullPath = [...collectionPath, ...path];
44
+ return [
45
+ {
46
+ option,
47
+ value: readPath(currentInstance, path),
48
+ update: (updateInstance, updateValue) => setPath(updateInstance, fullPath, updateValue)
72
49
  }
73
- description.push([composedLabel, values.join(' ')]);
50
+ ];
51
+ });
52
+ if (options.length === 0) {
53
+ return;
54
+ }
55
+ layout.push({ label: composeLabel(page.label, labelContext), options });
56
+ }
57
+ function emitDescribe(describe, model, labelContext, currentInstance) {
58
+ const composedLabel = composeLabel(describe.label, labelContext);
59
+ const values = describe.paths.flatMap((path) => {
60
+ const option = findOption(model, currentInstance, path);
61
+ if (option == null) {
62
+ return [];
63
+ }
64
+ const value = readPath(currentInstance, path);
65
+ if (value == null) {
66
+ return [];
74
67
  }
68
+ return [value];
75
69
  });
70
+ if (values.length === 0) {
71
+ return;
72
+ }
73
+ description.push([composedLabel, values.join(' ')]);
74
+ }
75
+ function composeLabel(label, labelContext = []) {
76
+ const resolved = resolveRef(label, refs);
77
+ check.assert(v.string(), resolved, 'Label did not resolve to a string! ❌');
78
+ if (labelContext.length === 0) {
79
+ return resolved;
80
+ }
81
+ return `${labelContext.join(', ')}, ${resolved}`;
76
82
  }
77
- function findResolvedOption(builder, model, path) {
83
+ function findOption(model, instance, path) {
78
84
  const optionName = path.at(-1);
79
85
  check.assert(v.string(), optionName);
80
86
  const collectionPairs = path.slice(0, -1);
81
- const resolved = descendPairs(builder, model, collectionPairs);
82
- if (!resolved) {
87
+ const descended = descendPairs(model, instance, collectionPairs);
88
+ if (!descended) {
83
89
  return null;
84
90
  }
85
- return (resolved.builder.options
86
- .map((entry) => resolveOption(entry, resolved.model))
87
- .find((entry) => entry?.name === optionName) ?? null);
91
+ const [scopeModel, scopeInstance] = descended;
92
+ const entry = scopeModel.options.find((option) => option.name === optionName);
93
+ return entry == null ? null : resolveOption(entry, scopeInstance, refs);
88
94
  }
89
- function descendPairs(currentBuilder, currentModel, remaining) {
95
+ function descendPairs(model, instance, remaining) {
90
96
  if (remaining.length === 0) {
91
- return { builder: currentBuilder, model: currentModel };
97
+ return [model, instance];
92
98
  }
93
- const [collectionName, modelIndex, ...rest] = remaining;
99
+ const [collectionName, instanceIndex, ...rest] = remaining;
94
100
  check.assert(v.string(), collectionName);
95
- check.assert(v.number(), modelIndex);
96
- const collection = findCollection(currentBuilder, currentModel, collectionName);
101
+ check.assert(v.number(), instanceIndex);
102
+ const collection = findCollection(model, instance, collectionName);
97
103
  if (!collection) {
98
104
  return null;
99
105
  }
100
- const nextModel = currentModel[collection.name].at(modelIndex);
101
- if (!nextModel) {
106
+ const nextInstance = instance[collectionName].at(instanceIndex);
107
+ if (!nextInstance) {
102
108
  return null;
103
109
  }
104
- return descendPairs(collection.payload.builder, nextModel, rest);
110
+ return descendPairs(collection.model, nextInstance, rest);
105
111
  }
106
- function findCollection(builder, model, collectionName) {
107
- return (builder.collections
108
- .map((entry) => resolveCollection(entry, model))
109
- .find((collection) => collection?.name === collectionName) ?? null);
112
+ function findCollection(model, instance, collectionName) {
113
+ const entry = model.collections.find((candidate) => candidate.name === collectionName);
114
+ return entry == null ? null : resolveCollection(entry, instance, refs);
110
115
  }
111
116
  }
112
117
  function setPath(container, path, value) {
@@ -1,9 +1,5 @@
1
- import type { BuilderCollectionConfig, BuilderCollectionValidated, BuilderComponentDetails, BuilderComponentValidated, BuilderExpectations, BuilderOptionValidated, BuilderOptionValues, BuilderValidated } from '../entities/index';
2
- import type { BuilderPaths } from '../paths';
3
- import { BuilderCollection, BuilderComponent, BuilderOption } from '../entities/index.js';
4
- export type BuilderOptionResolved = BuilderOption<string, BuilderOptionValues, BuilderPaths>;
5
- export type BuilderComponentResolved = BuilderComponent<string, BuilderComponentDetails<BuilderExpectations>, BuilderPaths>;
6
- export type BuilderCollectionResolved = BuilderCollection<string, BuilderCollectionConfig<BuilderValidated, number, number>, BuilderPaths>;
7
- export declare function resolveOption(option: BuilderOptionValidated, model: unknown): BuilderOptionResolved | null;
8
- export declare function resolveComponent(component: BuilderComponentValidated, model: unknown): BuilderComponentResolved | null;
9
- export declare function resolveCollection(collection: BuilderCollectionValidated, model: unknown): BuilderCollectionResolved | null;
1
+ import type { BuilderCollectionConfigValidated, BuilderCollectionValidated, BuilderComponentDetailsSerialised, BuilderComponentValidated, BuilderOptionValidated, BuilderOptionValuesSerialised, BuilderRefEntities } from '../entities/index';
2
+ export declare function resolveOption(option: BuilderOptionValidated, model: unknown, refs?: BuilderRefEntities): BuilderOptionValuesSerialised | null;
3
+ export declare function resolveComponent(component: BuilderComponentValidated, model: unknown, refs?: BuilderRefEntities): BuilderComponentDetailsSerialised | null;
4
+ export declare function resolveCollection(collection: BuilderCollectionValidated, model: unknown, refs?: BuilderRefEntities): BuilderCollectionConfigValidated | null;
5
+ export declare function resolveRef(value: unknown, refs: BuilderRefEntities): unknown;
@@ -1,41 +1,33 @@
1
1
  import { check } from '../check.js';
2
- import { BuilderCollection, BuilderCollectionConfigSchema, BuilderComponent, BuilderComponentDetailsSchema, BuilderOption, BuilderOptionValuesSchema } from '../entities/index.js';
2
+ import { BuilderCollectionConfigSerialisedSchema, BuilderComponentDetailsSerialisedSchema, BuilderOptionValuesSerialisedSchema } from '../entities/index.js';
3
3
  import { BuilderPathsSchema, readPath } from '../paths.js';
4
- export function resolveOption(option, model) {
5
- if (check.is(BuilderOptionValuesSchema, option.payload)) {
6
- return new BuilderOption(option.name, option.payload);
7
- }
8
- check.assert(BuilderPathsSchema, option.gatePaths);
9
- const result = resolveWhen(option.gatePaths, option.payload, model);
10
- if (!result) {
11
- return null;
12
- }
13
- return new BuilderOption(option.name, result);
4
+ import { BuilderRefSerialisedSchema } from '../references.js';
5
+ export function resolveOption(option, model, refs = []) {
6
+ return resolveEntry(option, BuilderOptionValuesSerialisedSchema, model, refs);
14
7
  }
15
- export function resolveComponent(component, model) {
16
- if (check.is(BuilderComponentDetailsSchema, component.payload)) {
17
- return new BuilderComponent(component.name, component.payload);
18
- }
19
- check.assert(BuilderPathsSchema, component.gatePaths);
20
- const result = resolveWhen(component.gatePaths, component.payload, model);
21
- if (!result) {
22
- return null;
23
- }
24
- return new BuilderComponent(component.name, result);
8
+ export function resolveComponent(component, model, refs = []) {
9
+ return resolveEntry(component, BuilderComponentDetailsSerialisedSchema, model, refs);
10
+ }
11
+ export function resolveCollection(collection, model, refs = []) {
12
+ return resolveEntry(collection, BuilderCollectionConfigSerialisedSchema, model, refs);
25
13
  }
26
- export function resolveCollection(collection, model) {
27
- if (check.is(BuilderCollectionConfigSchema, collection.payload)) {
28
- return new BuilderCollection(collection.name, collection.payload);
14
+ export function resolveRef(value, refs) {
15
+ if (!check.is(BuilderRefSerialisedSchema, value)) {
16
+ return value;
29
17
  }
30
- check.assert(BuilderPathsSchema, collection.gatePaths);
31
- const result = resolveWhen(collection.gatePaths, collection.payload, model);
32
- if (!result) {
33
- return null;
18
+ const found = refs.find((entry) => entry.id === value.id);
19
+ return found?.serialised ?? value;
20
+ }
21
+ function resolveEntry(entry, schema, model, refs = []) {
22
+ const payload = resolveRef(entry.payload, refs);
23
+ if (check.is(schema, payload)) {
24
+ return payload;
34
25
  }
35
- return new BuilderCollection(collection.name, result);
26
+ check.assert(BuilderPathsSchema, entry.paths);
27
+ return pickWhenBranch(payload, entry.paths, model);
36
28
  }
37
- function resolveWhen(gatePaths, config, model) {
38
- if (!gatePaths.every((path) => !!readPath(model, path))) {
29
+ function pickWhenBranch(config, gates, instance) {
30
+ if (!gates.every((path) => readPath(instance, path) != null)) {
39
31
  return null;
40
32
  }
41
33
  switch (config.type) {
@@ -44,10 +36,10 @@ function resolveWhen(gatePaths, config, model) {
44
36
  }
45
37
  case 'match': {
46
38
  const selectMap = config.selectMap;
47
- return selectMap[`${readPath(model, config.matchPath)}`];
39
+ return selectMap[`${readPath(instance, config.matchPath)}`] ?? null;
48
40
  }
49
41
  case 'unless': {
50
- const value = readPath(model, config.unlessPath);
42
+ const value = readPath(instance, config.unlessPath);
51
43
  if (config.disabledValues.includes(value)) {
52
44
  return null;
53
45
  }
@@ -0,0 +1 @@
1
+ export { createVariants } from './variants.js';
@@ -0,0 +1 @@
1
+ export { createVariants } from './variants.js';
@@ -0,0 +1,19 @@
1
+ import type { BuilderOptionValidated, BuilderWhen } from '../../entities/index';
2
+ import type { BuilderInstances } from '../../instance';
3
+ import type { BuilderPaths } from '../../paths';
4
+ export type GraphKeys = ReadonlySet<string>;
5
+ export type GraphPath = {
6
+ name: string;
7
+ keys: GraphKeys;
8
+ instances: BuilderInstances;
9
+ };
10
+ export type GraphPaths = ReadonlyArray<GraphPath>;
11
+ export declare function crossProduct(left: BuilderInstances, right: BuilderInstances): BuilderInstances;
12
+ export declare function dependencyKeys(payload: unknown | BuilderWhen, paths?: BuilderPaths): ReadonlyArray<string>;
13
+ export declare class BuilderOptionGraph {
14
+ #private;
15
+ readonly paths: GraphPaths;
16
+ constructor(paths?: GraphPaths);
17
+ get(name: string): GraphPath;
18
+ add(option: BuilderOptionValidated): BuilderOptionGraph;
19
+ }