@builder-builder/builder 0.0.25 → 0.0.27

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 (103) hide show
  1. package/dist/client/schema.d.ts +29 -4
  2. package/dist/client/schema.js +3 -1
  3. package/dist/components/Builder.svelte.d.ts +24 -0
  4. package/dist/components/BuilderCollectionButtons.svelte.d.ts +22 -0
  5. package/dist/components/BuilderCollections.svelte.d.ts +23 -0
  6. package/dist/components/BuilderDescription.svelte.d.ts +18 -0
  7. package/dist/components/BuilderLayout.svelte.d.ts +24 -0
  8. package/dist/components/BuilderOption.svelte.d.ts +31 -0
  9. package/dist/components/BuilderOptionSelect.svelte.d.ts +21 -0
  10. package/dist/components/BuilderOptionToggleBoolean.svelte.d.ts +20 -0
  11. package/dist/components/BuilderOptionToggleNumber.svelte.d.ts +21 -0
  12. package/dist/components/BuilderOptionToggleString.svelte.d.ts +21 -0
  13. package/dist/components/BuilderPrice.svelte.d.ts +21 -0
  14. package/dist/components/BuilderRender.svelte.d.ts +39 -0
  15. package/dist/components/config.d.ts +2 -0
  16. package/dist/components/config.js +1 -0
  17. package/dist/components/dispatch.d.ts +1 -0
  18. package/dist/components/dispatch.js +3 -0
  19. package/dist/components/id.d.ts +1 -0
  20. package/dist/components/id.js +3 -0
  21. package/dist/components/index.d.ts +25 -0
  22. package/dist/components/index.js +7441 -0
  23. package/dist/entities/builder/builder.js +2 -1
  24. package/dist/entities/collection/collection.js +2 -1
  25. package/dist/entities/collection/config.d.ts +20 -20
  26. package/dist/entities/collection/config.js +3 -2
  27. package/dist/entities/component/component.d.ts +30 -30
  28. package/dist/entities/component/component.js +2 -1
  29. package/dist/entities/component/config.d.ts +12 -12
  30. package/dist/entities/component/field.d.ts +4 -4
  31. package/dist/entities/component/field.js +4 -3
  32. package/dist/entities/expectation.d.ts +2 -2
  33. package/dist/entities/expectation.js +2 -1
  34. package/dist/entities/index.d.ts +1 -1
  35. package/dist/entities/kind.d.ts +1 -1
  36. package/dist/entities/kind.js +43 -3
  37. package/dist/entities/model/models.d.ts +3 -3
  38. package/dist/entities/option/config.d.ts +4 -4
  39. package/dist/entities/option/option.d.ts +22 -22
  40. package/dist/entities/option/option.js +2 -1
  41. package/dist/entities/option/select.d.ts +1 -1
  42. package/dist/entities/option/select.js +5 -4
  43. package/dist/entities/option/toggle.d.ts +1 -1
  44. package/dist/entities/option/toggle.js +4 -3
  45. package/dist/entities/paths.d.ts +2 -2
  46. package/dist/entities/paths.js +2 -1
  47. package/dist/entities/pricing/expression.js +5 -4
  48. package/dist/entities/pricing/rates.js +2 -1
  49. package/dist/entities/references.d.ts +50 -2
  50. package/dist/entities/references.js +2 -1
  51. package/dist/entities/serialise.d.ts +318 -113
  52. package/dist/entities/serialise.js +4 -3
  53. package/dist/entities/tags.d.ts +1 -1
  54. package/dist/entities/tags.js +2 -1
  55. package/dist/entities/ui/describe.d.ts +126 -34
  56. package/dist/entities/ui/describe.js +3 -2
  57. package/dist/entities/ui/input.d.ts +158 -49
  58. package/dist/entities/ui/input.js +13 -6
  59. package/dist/entities/ui/page.d.ts +124 -32
  60. package/dist/entities/ui/page.js +2 -1
  61. package/dist/entities/ui/pages.d.ts +11 -3
  62. package/dist/entities/ui/pages.js +3 -2
  63. package/dist/entities/validated.d.ts +1 -0
  64. package/dist/entities/when.d.ts +16 -16
  65. package/dist/entities/when.js +2 -2
  66. package/dist/errors/errors.d.ts +10 -0
  67. package/dist/errors/errors.js +6 -0
  68. package/dist/instance.d.ts +7 -7
  69. package/dist/instance.js +4 -4
  70. package/dist/mappers/index.d.ts +1 -1
  71. package/dist/mappers/order.js +4 -2
  72. package/dist/mappers/price.js +1 -2
  73. package/dist/mappers/render/collection.d.ts +9 -0
  74. package/dist/mappers/render/collection.js +27 -0
  75. package/dist/mappers/render/compose.d.ts +5 -0
  76. package/dist/mappers/render/compose.js +15 -0
  77. package/dist/mappers/render/description.d.ts +3 -0
  78. package/dist/mappers/render/description.js +17 -0
  79. package/dist/mappers/render/index.d.ts +3 -1
  80. package/dist/mappers/render/option.d.ts +21 -0
  81. package/dist/mappers/render/option.js +26 -0
  82. package/dist/mappers/render/page.d.ts +11 -0
  83. package/dist/mappers/render/page.js +11 -0
  84. package/dist/mappers/render/paths.d.ts +3 -0
  85. package/dist/mappers/render/paths.js +21 -0
  86. package/dist/mappers/render/render.d.ts +1 -1
  87. package/dist/mappers/render/render.js +33 -98
  88. package/dist/mappers/resolve.d.ts +2 -1
  89. package/dist/mappers/resolve.js +24 -23
  90. package/dist/primitive.d.ts +5 -0
  91. package/dist/primitive.js +6 -1
  92. package/dist/public.d.ts +1 -1
  93. package/dist/references.d.ts +6 -6
  94. package/dist/references.js +3 -2
  95. package/dist/validate/model.js +16 -5
  96. package/dist/validate/paths.js +3 -5
  97. package/dist/validate/pricing.js +5 -6
  98. package/dist/validate/resolve.d.ts +2 -1
  99. package/dist/validate/resolve.js +87 -73
  100. package/dist/validate/ui.js +14 -13
  101. package/package.json +7 -5
  102. package/dist/mappers/render/pages.d.ts +0 -24
  103. package/dist/mappers/render/pages.js +0 -2
@@ -1,9 +1,11 @@
1
+ import { modelsMerge } from '../entities/index.js';
1
2
  import { check } from '../errors/index.js';
2
3
  import { BuilderInstancesSchema } from '../instance.js';
3
4
  import { resolveCollection, resolveComponent } from './resolve.js';
4
5
  export function order(model, instance, variants, references = []) {
5
6
  const result = {};
6
- model.components.forEach((component) => {
7
+ const merged = modelsMerge(model);
8
+ merged.components.forEach((component) => {
7
9
  if (resolveComponent(component, model, instance, references) == null) {
8
10
  return;
9
11
  }
@@ -11,7 +13,7 @@ export function order(model, instance, variants, references = []) {
11
13
  result[component.name] =
12
14
  componentVariants.find((variant) => Object.entries(variant.instance).every(([key, value]) => instance[key] === value)) ?? null;
13
15
  });
14
- model.collections.forEach((collection) => {
16
+ merged.collections.forEach((collection) => {
15
17
  const { name } = collection;
16
18
  const payload = resolveCollection(collection, model, instance, references);
17
19
  if (payload == null) {
@@ -1,8 +1,7 @@
1
- import * as v from 'valibot';
2
1
  import { BuilderPricingExpressionSchema } from '../entities/index.js';
3
2
  import { check } from '../errors/index.js';
4
3
  import { BuilderComponentVariantSchema } from '../instance.js';
5
- const NumberSchema = v.number();
4
+ import { NumberSchema } from '../primitive.js';
6
5
  export function price(pricingInput, order) {
7
6
  const { rates, formula } = pricingInput;
8
7
  if (formula == null) {
@@ -0,0 +1,9 @@
1
+ import type { BuilderPath, BuilderReferences, BuilderValidated } from '../../entities/index';
2
+ import type { BuilderInstance } from '../../instance';
3
+ export type BuilderRenderCollectionAddRemove = (instance: BuilderInstance) => BuilderInstance;
4
+ export type BuilderRenderCollection = Readonly<{
5
+ add?: BuilderRenderCollectionAddRemove;
6
+ remove?: BuilderRenderCollectionAddRemove;
7
+ }>;
8
+ export type BuilderRenderCollections = Readonly<Record<string, BuilderRenderCollection>>;
9
+ export declare function renderCollection(itemsPath: BuilderPath, index: number, min: number, max: number, length: number, builder: BuilderValidated, references: BuilderReferences): BuilderRenderCollection;
@@ -0,0 +1,27 @@
1
+ import { createInstance } from '../instance.js';
2
+ import { readPath, writePath } from './paths.js';
3
+ export function renderCollection(itemsPath, index, min, max, length, builder, references) {
4
+ let handlers = {};
5
+ if (length < max) {
6
+ handlers = {
7
+ ...handlers,
8
+ add: (updateInstance) => {
9
+ const current = (readPath(updateInstance, itemsPath) ?? []);
10
+ const clone = current[index] ?? {};
11
+ const next = [...current.slice(0, index + 1), clone, ...current.slice(index + 1)];
12
+ return createInstance(builder, writePath(updateInstance, itemsPath, next), references);
13
+ }
14
+ };
15
+ }
16
+ if (length > min) {
17
+ handlers = {
18
+ ...handlers,
19
+ remove: (updateInstance) => {
20
+ const current = (readPath(updateInstance, itemsPath) ?? []);
21
+ const next = [...current.slice(0, index), ...current.slice(index + 1)];
22
+ return createInstance(builder, writePath(updateInstance, itemsPath, next), references);
23
+ }
24
+ };
25
+ }
26
+ return handlers;
27
+ }
@@ -0,0 +1,5 @@
1
+ import type { BuilderReferences } from '../../entities/index';
2
+ import type { BuilderRenderMetadata } from './option';
3
+ export declare function composeLabel(label: unknown, labels: ReadonlyArray<string>, references: BuilderReferences): string;
4
+ export declare function composeString(value: unknown, references: BuilderReferences): string;
5
+ export declare function composeMetadata(value: unknown, references: BuilderReferences): BuilderRenderMetadata;
@@ -0,0 +1,15 @@
1
+ import { resolveReference } from '../resolve.js';
2
+ import { StringSchema } from '../../primitive.js';
3
+ import { BuilderRenderMetadataSchema } from './option.js';
4
+ export function composeLabel(label, labels, references) {
5
+ return [...labels, composeString(label, references)]
6
+ .filter((segment) => segment !== '')
7
+ .join(', ');
8
+ }
9
+ export function composeString(value, references) {
10
+ return resolveReference(value, references, StringSchema);
11
+ }
12
+ export function composeMetadata(value, references) {
13
+ const resolved = resolveReference(value, references, BuilderRenderMetadataSchema);
14
+ return Object.fromEntries(Object.entries(resolved).map(([key, entry]) => [key, resolveReference(entry, references)]));
15
+ }
@@ -0,0 +1,3 @@
1
+ import type { BuilderDescriptionItem, BuilderModelValidated, BuilderReferences, BuilderUIDescribeValidated } from '../../entities/index';
2
+ import type { BuilderInstance } from '../../instance';
3
+ export declare function renderDescription(describe: BuilderUIDescribeValidated, label: string, model: BuilderModelValidated, instance: BuilderInstance, references: BuilderReferences): BuilderDescriptionItem | null;
@@ -0,0 +1,17 @@
1
+ import { check } from '../../errors/index.js';
2
+ import { BuilderPrimitiveSchema } from '../../primitive.js';
3
+ import { resolvePath } from '../resolve.js';
4
+ export function renderDescription(describe, label, model, instance, references) {
5
+ const values = describe.inputs.flatMap((input) => {
6
+ const found = resolvePath(model, instance, input.path, references);
7
+ if (found?.value == null) {
8
+ return [];
9
+ }
10
+ check.assert(BuilderPrimitiveSchema, found.value);
11
+ return [found.value];
12
+ });
13
+ if (values.length === 0) {
14
+ return null;
15
+ }
16
+ return [label, values.join(' ')];
17
+ }
@@ -1,4 +1,6 @@
1
- export type { BuilderRenderMetadata, BuilderRenderOption, BuilderRenderOptions, BuilderRenderPage, BuilderRenderPages, BuilderRenderUpdate } from './pages';
1
+ export type { BuilderRenderCollection, BuilderRenderCollectionAddRemove, BuilderRenderCollections } from './collection';
2
+ export type { BuilderRenderMetadata, BuilderRenderOption, BuilderRenderOptionUpdate, BuilderRenderOptions } from './option';
3
+ export type { BuilderRenderPage, BuilderRenderPages } from './page';
2
4
  export type { BuilderRenderResult } from './render';
3
5
  export { render } from './render.js';
4
6
  export { ordinal } from './ordinal.js';
@@ -0,0 +1,21 @@
1
+ import type { BuilderModelValidated, BuilderOptionConfigSerialised, BuilderPath, BuilderReferences, BuilderUIInputValidated, BuilderValidated } from '../../entities/index';
2
+ import type { BuilderInstance } from '../../instance';
3
+ import type { BuilderPrimitive } from '../../primitive';
4
+ import * as v from 'valibot';
5
+ export type BuilderRenderOptionUpdate = (instance: BuilderInstance, primitive: BuilderPrimitive) => BuilderInstance;
6
+ export declare const BuilderRenderMetadataSchema: v.SchemaWithPipe<readonly [v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, v.UnknownSchema, undefined>, v.ReadonlyAction<{
7
+ [x: string]: unknown;
8
+ }>]>;
9
+ export type BuilderRenderMetadata = v.InferOutput<typeof BuilderRenderMetadataSchema>;
10
+ export type BuilderRenderOption = Readonly<{
11
+ name: string;
12
+ value: BuilderPrimitive;
13
+ update: BuilderRenderOptionUpdate;
14
+ option: BuilderOptionConfigSerialised;
15
+ displayName?: string;
16
+ kind?: string;
17
+ placeholderLabel?: string;
18
+ metadata?: BuilderRenderMetadata;
19
+ }>;
20
+ export type BuilderRenderOptions = ReadonlyArray<BuilderRenderOption>;
21
+ export declare function renderOption(input: BuilderUIInputValidated, path: BuilderPath, builder: BuilderValidated, model: BuilderModelValidated, instance: BuilderInstance, references: BuilderReferences): BuilderRenderOption | null;
@@ -0,0 +1,26 @@
1
+ import * as v from 'valibot';
2
+ import { check } from '../../errors/index.js';
3
+ import { BuilderPrimitiveSchema, NameSchema } from '../../primitive.js';
4
+ import { createInstance } from '../instance.js';
5
+ import { resolvePath } from '../resolve.js';
6
+ import { composeMetadata, composeString } from './compose.js';
7
+ import { writePath } from './paths.js';
8
+ export const BuilderRenderMetadataSchema = v.pipe(v.record(NameSchema, v.unknown()), v.readonly());
9
+ export function renderOption(input, path, builder, model, instance, references) {
10
+ const found = resolvePath(model, instance, input.path, references);
11
+ if (found == null) {
12
+ return null;
13
+ }
14
+ const fullPath = [...path, ...input.path];
15
+ check.assert(BuilderPrimitiveSchema, found.value);
16
+ return {
17
+ name: found.name,
18
+ option: found.payload,
19
+ value: found.value,
20
+ update: (updateInstance, updateValue) => createInstance(builder, writePath(updateInstance, fullPath, updateValue), references),
21
+ displayName: input.displayName && composeString(input.displayName, references),
22
+ kind: input.kind && composeString(input.kind, references),
23
+ placeholderLabel: input.placeholderLabel && composeString(input.placeholderLabel, references),
24
+ metadata: input.metadata && composeMetadata(input.metadata, references)
25
+ };
26
+ }
@@ -0,0 +1,11 @@
1
+ import type { BuilderModelValidated, BuilderPath, BuilderReferences, BuilderUIPageValidated, BuilderValidated } from '../../entities/index';
2
+ import type { BuilderInstance } from '../../instance';
3
+ import type { BuilderRenderCollections } from './collection';
4
+ import type { BuilderRenderOptions } from './option';
5
+ export type BuilderRenderPage = Readonly<{
6
+ label: string;
7
+ options: BuilderRenderOptions;
8
+ collections: BuilderRenderCollections;
9
+ }>;
10
+ export type BuilderRenderPages = ReadonlyArray<BuilderRenderPage>;
11
+ export declare function renderPage(page: BuilderUIPageValidated, label: string, path: BuilderPath, collections: BuilderRenderCollections, builder: BuilderValidated, model: BuilderModelValidated, instance: BuilderInstance, references: BuilderReferences): BuilderRenderPage | null;
@@ -0,0 +1,11 @@
1
+ import { renderOption } from './option.js';
2
+ export function renderPage(page, label, path, collections, builder, model, instance, references) {
3
+ const options = page.inputs.flatMap((input) => {
4
+ const option = renderOption(input, path, builder, model, instance, references);
5
+ return option == null ? [] : [option];
6
+ });
7
+ if (options.length === 0) {
8
+ return null;
9
+ }
10
+ return { label, options, collections };
11
+ }
@@ -0,0 +1,3 @@
1
+ import type { BuilderPath } from '../../entities/index';
2
+ export declare function readPath(container: unknown, path: BuilderPath): unknown;
3
+ export declare function writePath(container: unknown, path: BuilderPath, value: unknown): unknown;
@@ -0,0 +1,21 @@
1
+ import { check } from '../../errors/index.js';
2
+ import { NumberSchema } from '../../primitive.js';
3
+ export function readPath(container, path) {
4
+ return path.reduce((current, segment) => current == null ? undefined : current[segment], container);
5
+ }
6
+ export function writePath(container, path, value) {
7
+ if (path.length === 0) {
8
+ return value;
9
+ }
10
+ const [head, ...tail] = path;
11
+ if (check.is(NumberSchema, head)) {
12
+ const next = Array.isArray(container) ? [...container] : [];
13
+ next[head] = writePath(next[head], tail, value);
14
+ return next;
15
+ }
16
+ const next = container != null && !Array.isArray(container)
17
+ ? { ...container }
18
+ : {};
19
+ next[head] = writePath(next[head], tail, value);
20
+ return next;
21
+ }
@@ -1,5 +1,5 @@
1
1
  import type { BuilderDescription, BuilderInstanceValidated, BuilderReferences, BuilderValidated } from '../../entities/index';
2
- import type { BuilderRenderPages } from './pages';
2
+ import type { BuilderRenderPages } from './page';
3
3
  export type BuilderRenderResult = Readonly<{
4
4
  layout: BuilderRenderPages;
5
5
  description: BuilderDescription;
@@ -1,120 +1,55 @@
1
- import * as v from 'valibot';
2
1
  import { check } from '../../errors/index.js';
3
2
  import { BuilderInstancesSchema } from '../../instance.js';
4
- import { BuilderPrimitiveSchema } from '../../primitive.js';
5
- import { createInstance } from '../instance.js';
6
- import { resolveCollection, resolvePath, resolveReference } from '../resolve.js';
3
+ import { resolveCollection } from '../resolve.js';
4
+ import { renderCollection } from './collection.js';
5
+ import { composeLabel, composeString } from './compose.js';
6
+ import { renderDescription } from './description.js';
7
7
  import { ordinal } from './ordinal.js';
8
- import { BuilderRenderMetadataSchema } from './pages.js';
8
+ import { renderPage } from './page.js';
9
9
  export function render(builder, instance, references = []) {
10
10
  const layout = [];
11
11
  const description = [];
12
- walkTree(builder.ui);
12
+ renderUITree(builder.ui);
13
13
  return { layout, description };
14
- function walkTree(ui) {
15
- ui.uis.forEach((nested) => walkTree(nested));
16
- walkItems(ui.items, builder.model, [], [], instance);
14
+ function renderUITree(ui) {
15
+ ui.uis.forEach(renderUITree);
16
+ renderUIItems(ui.items, builder.model, instance, [], [], {});
17
17
  }
18
- function walkItems(items, model, collectionPath, labelContext, currentInstance) {
18
+ function renderUIItems(items, model, instance, labels, path, collections) {
19
19
  items.forEach((item) => {
20
20
  if (item.type === 'page') {
21
- emitPage(item, model, collectionPath, labelContext, currentInstance);
21
+ const page = renderPage(item, composeLabel(item.label, labels, references), path, collections, builder, model, instance, references);
22
+ if (page != null) {
23
+ layout.push(page);
24
+ }
22
25
  return;
23
26
  }
24
27
  if (item.type === 'describe') {
25
- emitDescribe(item, model, labelContext, currentInstance);
28
+ const descriptionItem = renderDescription(item, composeLabel(item.label, labels, references), model, instance, references);
29
+ if (descriptionItem != null) {
30
+ description.push(descriptionItem);
31
+ }
26
32
  return;
27
33
  }
28
- const collection = findCollection(model, currentInstance, item.name);
34
+ const definition = model.collections.find((candidate) => candidate.name === item.name);
35
+ if (definition == null) {
36
+ return;
37
+ }
38
+ const collection = resolveCollection(definition, model, instance, references);
29
39
  if (collection == null) {
30
40
  return;
31
41
  }
32
- const itemInstances = currentInstance[item.name];
33
- check.assert(BuilderInstancesSchema, itemInstances);
34
- const mergedItemModel = collection.model;
35
- itemInstances.forEach((itemInstance, index) => {
36
- walkItems(item.items, mergedItemModel, [...collectionPath, item.name, index], [...labelContext, `${ordinal(index)} ${composeLabel(item.label)}`], itemInstance);
42
+ const instances = instance[item.name];
43
+ check.assert(BuilderInstancesSchema, instances);
44
+ const itemsPath = [...path, item.name];
45
+ const { min, max } = collection;
46
+ const { length } = instances;
47
+ instances.forEach((itemInstance, index) => {
48
+ renderUIItems(item.items, collection.model, itemInstance, [...labels, `${ordinal(index)} ${composeString(item.label, references)}`], [...itemsPath, index], {
49
+ ...collections,
50
+ [item.name]: renderCollection(itemsPath, index, min, max, length, builder, references)
51
+ });
37
52
  });
38
53
  });
39
54
  }
40
- function emitPage(page, model, collectionPath, labelContext, currentInstance) {
41
- const options = page.inputs.flatMap((input) => {
42
- const { path } = input;
43
- const found = resolvePath(model, currentInstance, path, references);
44
- if (found == null) {
45
- return [];
46
- }
47
- const fullPath = [...collectionPath, ...path];
48
- check.assert(BuilderPrimitiveSchema, found.value);
49
- return [
50
- {
51
- name: found.name,
52
- option: found.payload,
53
- value: found.value,
54
- update: (updateInstance, updateValue) => createInstance(builder, setPath(updateInstance, fullPath, updateValue), references),
55
- displayName: input.displayName && composeString(input.displayName),
56
- kind: input.kind && composeString(input.kind),
57
- metadata: input.metadata && composeMetadata(input.metadata)
58
- }
59
- ];
60
- });
61
- if (options.length === 0) {
62
- return;
63
- }
64
- layout.push({ label: composeLabel(page.label, labelContext), options });
65
- }
66
- function emitDescribe(describe, model, labelContext, currentInstance) {
67
- const composedLabel = composeLabel(describe.label, labelContext);
68
- const values = describe.inputs.flatMap((input) => {
69
- const { path } = input;
70
- const found = resolvePath(model, currentInstance, path, references);
71
- if (found?.value == null) {
72
- return [];
73
- }
74
- check.assert(BuilderPrimitiveSchema, found.value);
75
- return [found.value];
76
- });
77
- if (values.length === 0) {
78
- return;
79
- }
80
- description.push([composedLabel, values.join(' ')]);
81
- }
82
- function composeLabel(label, labelContext = []) {
83
- const resolved = resolveReference(label, references);
84
- check.assert(v.string(), resolved);
85
- if (labelContext.length === 0) {
86
- return resolved;
87
- }
88
- if (resolved === '') {
89
- return labelContext.join(', ');
90
- }
91
- return `${labelContext.join(', ')}, ${resolved}`;
92
- }
93
- function composeString(value) {
94
- const resolved = resolveReference(value, references);
95
- check.assert(v.string(), resolved);
96
- return resolved;
97
- }
98
- function composeMetadata(value) {
99
- const resolved = resolveReference(value, references);
100
- check.assert(BuilderRenderMetadataSchema, resolved);
101
- return Object.fromEntries(Object.entries(resolved).map(([key, entry]) => [key, resolveReference(entry, references)]));
102
- }
103
- function findCollection(model, instance, collectionName) {
104
- const entry = model.collections.find((candidate) => candidate.name === collectionName);
105
- return entry == null ? null : resolveCollection(entry, model, instance, references);
106
- }
107
- }
108
- function setPath(container, path, value) {
109
- const [head, ...tail] = path;
110
- if (typeof head === 'number') {
111
- const arrayContainer = container ? [...container] : [];
112
- arrayContainer[head] = tail.length === 0 ? value : setPath(arrayContainer[head], tail, value);
113
- return arrayContainer;
114
- }
115
- const objectContainer = container ? container : {};
116
- return {
117
- ...objectContainer,
118
- [head]: tail.length === 0 ? value : setPath(objectContainer[head], tail, value)
119
- };
120
55
  }
@@ -1,12 +1,13 @@
1
1
  import type { BuilderCollectionConfigsSerialised, BuilderCollectionConfigValidated, BuilderCollectionSerialised, BuilderCollectionValidated, BuilderComponentConfigsSerialised, BuilderComponentConfigValidated, BuilderComponentSerialised, BuilderComponentValidated, BuilderModelValidated, BuilderOptionConfigsSerialised, BuilderOptionConfigValidated, BuilderOptionSerialised, BuilderOptionValidated, BuilderPath, BuilderReferences } from '../entities/index';
2
2
  import type { BuilderInstance } from '../instance';
3
+ import * as v from 'valibot';
3
4
  export declare function resolveOption(option: BuilderOptionValidated, model: BuilderModelValidated, instance: unknown, references?: BuilderReferences): BuilderOptionConfigValidated | null;
4
5
  export declare function resolveOptions(option: BuilderOptionSerialised, references?: BuilderReferences): BuilderOptionConfigsSerialised;
5
6
  export declare function resolveComponent(component: BuilderComponentValidated, model: BuilderModelValidated, instance: unknown, references?: BuilderReferences): BuilderComponentConfigValidated | null;
6
7
  export declare function resolveComponents(component: BuilderComponentSerialised, references?: BuilderReferences): BuilderComponentConfigsSerialised;
7
8
  export declare function resolveCollection(collection: BuilderCollectionValidated, model: BuilderModelValidated, instance: unknown, references?: BuilderReferences): BuilderCollectionConfigValidated | null;
8
9
  export declare function resolveCollections(collection: BuilderCollectionSerialised, references?: BuilderReferences): BuilderCollectionConfigsSerialised;
9
- export declare function resolveReference(value: unknown, references: BuilderReferences): unknown;
10
+ export declare function resolveReference<Schema extends v.GenericSchema = v.GenericSchema<unknown>>(value: unknown, references: BuilderReferences, schema?: Schema): v.InferOutput<Schema>;
10
11
  export type ResolvedPath = {
11
12
  readonly name: string;
12
13
  readonly payload: BuilderOptionConfigValidated;
@@ -1,38 +1,40 @@
1
1
  import * as v from 'valibot';
2
- import { BuilderCollectionConfigSerialisedSchema, BuilderComponentConfigSerialisedSchema, BuilderOptionConfigSerialisedSchema, BuilderPathsSchema, BuilderWhenSerialisedSchema, modelsMerge, whenBranches } from '../entities/index.js';
2
+ import { BuilderCollectionConfigSerialisedSchema, BuilderCollectionWhenSerialisedSchema, BuilderComponentConfigSerialisedSchema, BuilderComponentWhenSerialisedSchema, BuilderOptionConfigSerialisedSchema, BuilderOptionWhenSerialisedSchema, BuilderPathsSchema, modelsMerge, whenBranches } from '../entities/index.js';
3
3
  import { check } from '../errors/index.js';
4
4
  import { BuilderInstanceSchema, BuilderInstancesSchema } from '../instance.js';
5
- import { BuilderPrimitiveSchema } from '../primitive.js';
6
- import { BuilderRefSerialisedSchema } from '../references.js';
5
+ import { BuilderPrimitiveSchema, NameSchema, NumberSchema } from '../primitive.js';
6
+ import { BuilderRefSerialisedSchema, paramable } from '../references.js';
7
7
  export function resolveOption(option, model, instance, references = []) {
8
- return resolveEntryInstance(option, BuilderOptionConfigSerialisedSchema, model, instance, references);
8
+ return resolveEntryInstance(option, BuilderOptionConfigSerialisedSchema, BuilderOptionWhenSerialisedSchema, model, instance, references);
9
9
  }
10
10
  export function resolveOptions(option, references = []) {
11
- return resolveEntryExhaustive(option, BuilderOptionConfigSerialisedSchema, references);
11
+ return resolveEntryExhaustive(option, BuilderOptionConfigSerialisedSchema, BuilderOptionWhenSerialisedSchema, references);
12
12
  }
13
13
  export function resolveComponent(component, model, instance, references = []) {
14
- return resolveEntryInstance(component, BuilderComponentConfigSerialisedSchema, model, instance, references);
14
+ return resolveEntryInstance(component, BuilderComponentConfigSerialisedSchema, BuilderComponentWhenSerialisedSchema, model, instance, references);
15
15
  }
16
16
  export function resolveComponents(component, references = []) {
17
- return resolveEntryExhaustive(component, BuilderComponentConfigSerialisedSchema, references);
17
+ return resolveEntryExhaustive(component, BuilderComponentConfigSerialisedSchema, BuilderComponentWhenSerialisedSchema, references);
18
18
  }
19
19
  export function resolveCollection(collection, model, instance, references = []) {
20
- return resolveEntryInstance(collection, BuilderCollectionConfigSerialisedSchema, model, instance, references);
20
+ return resolveEntryInstance(collection, BuilderCollectionConfigSerialisedSchema, BuilderCollectionWhenSerialisedSchema, model, instance, references);
21
21
  }
22
22
  export function resolveCollections(collection, references = []) {
23
- return resolveEntryExhaustive(collection, BuilderCollectionConfigSerialisedSchema, references);
23
+ return resolveEntryExhaustive(collection, BuilderCollectionConfigSerialisedSchema, BuilderCollectionWhenSerialisedSchema, references);
24
24
  }
25
- export function resolveReference(value, references) {
26
- if (!check.is(BuilderRefSerialisedSchema, value)) {
27
- return value;
25
+ export function resolveReference(value, references, schema = v.unknown()) {
26
+ let resolved = value;
27
+ if (check.is(BuilderRefSerialisedSchema, value)) {
28
+ const found = references.find((entry) => entry.id === value.id);
29
+ check.invariant(found);
30
+ resolved = found.serialised;
28
31
  }
29
- const found = references.find((entry) => entry.id === value.id);
30
- check.invariant(found);
31
- return found.serialised;
32
+ check.assert(schema, resolved);
33
+ return resolved;
32
34
  }
33
35
  export function resolvePath(model, instance, path, references = []) {
34
36
  const optionName = path.at(-1);
35
- check.assert(v.string(), optionName);
37
+ check.assert(NameSchema, optionName);
36
38
  const descended = resolveItems(model, instance, path.slice(0, -1), references);
37
39
  if (descended == null) {
38
40
  return null;
@@ -53,8 +55,8 @@ export function resolveItems(model, instance, pairs, references = []) {
53
55
  return [model, instance];
54
56
  }
55
57
  const [name, index, ...rest] = pairs;
56
- check.assert(v.string(), name);
57
- check.assert(v.number(), index);
58
+ check.assert(NameSchema, name);
59
+ check.assert(NumberSchema, index);
58
60
  const merged = modelsMerge(model);
59
61
  const collection = merged.collections.find((entry) => entry.name === name);
60
62
  check.invariant(collection);
@@ -70,12 +72,11 @@ export function resolveItems(model, instance, pairs, references = []) {
70
72
  }
71
73
  return resolveItems(resolved.model, item, rest, references);
72
74
  }
73
- function resolveEntryInstance(entry, schema, model, instance, references) {
74
- const payload = resolveReference(entry.payload, references);
75
+ function resolveEntryInstance(entry, schema, whenSchema, model, instance, references) {
76
+ const payload = resolveReference(entry.payload, references, paramable(v.union([schema, whenSchema])));
75
77
  if (check.is(schema, payload)) {
76
78
  return payload;
77
79
  }
78
- check.assert(BuilderWhenSerialisedSchema, payload);
79
80
  check.assert(BuilderPathsSchema, entry.paths);
80
81
  const config = payload;
81
82
  if (!entry.paths.every((path) => Boolean(resolvePath(model, instance, path, references)?.value))) {
@@ -103,6 +104,6 @@ function resolveEntryInstance(entry, schema, model, instance, references) {
103
104
  }
104
105
  }
105
106
  }
106
- function resolveEntryExhaustive(entry, schema, references) {
107
- return whenBranches(resolveReference(entry.payload, references), schema);
107
+ function resolveEntryExhaustive(entry, schema, whenSchema, references) {
108
+ return whenBranches(resolveReference(entry.payload, references, paramable(v.union([schema, whenSchema]))), schema);
108
109
  }
@@ -1,4 +1,9 @@
1
1
  import * as v from 'valibot';
2
+ export declare const StringSchema: v.StringSchema<undefined>;
3
+ export declare const NumberSchema: v.NumberSchema<undefined>;
4
+ export declare const BooleanSchema: v.BooleanSchema<undefined>;
5
+ export declare const NameSchema: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
6
+ export declare const IdSchema: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
2
7
  export declare const BuilderPrimitiveSchema: v.NullableSchema<v.UnionSchema<[v.StringSchema<undefined>, v.BooleanSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>;
3
8
  export type BuilderPrimitive = v.InferOutput<typeof BuilderPrimitiveSchema>;
4
9
  export declare const BuilderPrimitivesSchema: v.SchemaWithPipe<readonly [v.ArraySchema<v.NullableSchema<v.UnionSchema<[v.StringSchema<undefined>, v.BooleanSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>, undefined>, v.ReadonlyAction<(string | number | boolean | null)[]>]>;
package/dist/primitive.js CHANGED
@@ -1,3 +1,8 @@
1
1
  import * as v from 'valibot';
2
- export const BuilderPrimitiveSchema = v.nullable(v.union([v.string(), v.boolean(), v.number()]));
2
+ export const StringSchema = v.string();
3
+ export const NumberSchema = v.number();
4
+ export const BooleanSchema = v.boolean();
5
+ export const NameSchema = v.pipe(StringSchema, v.minLength(1));
6
+ export const IdSchema = v.pipe(StringSchema, v.minLength(1));
7
+ export const BuilderPrimitiveSchema = v.nullable(v.union([StringSchema, BooleanSchema, NumberSchema]));
3
8
  export const BuilderPrimitivesSchema = v.pipe(v.array(BuilderPrimitiveSchema), v.readonly());
package/dist/public.d.ts CHANGED
@@ -4,7 +4,7 @@ export type { BuilderEnvironment } from './environment';
4
4
  export type { BuilderError, BuilderErrorLocation, BuilderErrors } from './errors/index';
5
5
  export type { BuilderErrorKind } from './errors/index.js';
6
6
  export type { BuilderComponentVariant, BuilderComponentVariants, BuilderInstance, BuilderInstanceInput, BuilderInstances, BuilderVariants } from './instance';
7
- export type { BuilderOrder, BuilderRenderMetadata, BuilderRenderOption, BuilderRenderOptions, BuilderRenderPage, BuilderRenderPages, BuilderRenderResult, BuilderRenderUpdate } from './mappers/index';
7
+ export type { BuilderOrder, BuilderRenderCollection, BuilderRenderCollectionAddRemove, BuilderRenderCollections, BuilderRenderMetadata, BuilderRenderOption, BuilderRenderOptions, BuilderRenderOptionUpdate, BuilderRenderPage, BuilderRenderPages, BuilderRenderResult } from './mappers/index';
8
8
  export type { BuilderPrimitive, BuilderPrimitives } from './primitive';
9
9
  export type { BuilderParameter, BuilderParameterSerialised, BuilderRef, Paramable, ParamableSerialised } from './references';
10
10
  export type { BuilderInstanceValidationResult, BuilderModelValidationResult, BuilderPricingValidationResult, BuilderUIValidationResult, BuilderValidationResult, BuilderVariantsValidationOptions, BuilderVariantsValidationResult } from './validate/index';
@@ -9,8 +9,8 @@ export declare class BuilderParameter<const Name extends string = string> {
9
9
  export declare const BuilderParameterSchema: v.InstanceSchema<typeof BuilderParameter, undefined>;
10
10
  export declare const BuilderParameterSerialisedSchema: v.SchemaWithPipe<readonly [v.ObjectSchema<{
11
11
  readonly type: v.LiteralSchema<"parameter", undefined>;
12
- readonly id: v.StringSchema<undefined>;
13
- readonly name: v.StringSchema<undefined>;
12
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
13
+ readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
14
14
  }, undefined>, v.ReadonlyAction<{
15
15
  type: "parameter";
16
16
  id: string;
@@ -25,7 +25,7 @@ export declare class BuilderRef {
25
25
  export declare const BuilderRefSchema: v.InstanceSchema<typeof BuilderRef, undefined>;
26
26
  export declare const BuilderRefSerialisedSchema: v.SchemaWithPipe<readonly [v.ObjectSchema<{
27
27
  readonly type: v.LiteralSchema<"ref", undefined>;
28
- readonly id: v.StringSchema<undefined>;
28
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
29
29
  }, undefined>, v.ReadonlyAction<{
30
30
  type: "ref";
31
31
  id: string;
@@ -35,15 +35,15 @@ export declare function parameter<const Name extends string>(name: Name): Builde
35
35
  export declare function ref(id: string): BuilderRef;
36
36
  export declare function paramable<Schema extends v.GenericSchema>(paramable: Schema): v.UnionSchema<[v.SchemaWithPipe<readonly [v.ObjectSchema<{
37
37
  readonly type: v.LiteralSchema<"parameter", undefined>;
38
- readonly id: v.StringSchema<undefined>;
39
- readonly name: v.StringSchema<undefined>;
38
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
39
+ readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
40
40
  }, undefined>, v.ReadonlyAction<{
41
41
  type: "parameter";
42
42
  id: string;
43
43
  name: string;
44
44
  }>]>, v.SchemaWithPipe<readonly [v.ObjectSchema<{
45
45
  readonly type: v.LiteralSchema<"ref", undefined>;
46
- readonly id: v.StringSchema<undefined>;
46
+ readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
47
47
  }, undefined>, v.ReadonlyAction<{
48
48
  type: "ref";
49
49
  id: string;
@@ -1,5 +1,6 @@
1
1
  import * as v from 'valibot';
2
2
  import { check } from './errors/index.js';
3
+ import { IdSchema, NameSchema } from './primitive.js';
3
4
  export class BuilderParameter {
4
5
  id;
5
6
  name;
@@ -9,7 +10,7 @@ export class BuilderParameter {
9
10
  }
10
11
  }
11
12
  export const BuilderParameterSchema = v.instance(BuilderParameter);
12
- export const BuilderParameterSerialisedSchema = v.pipe(v.object({ type: v.literal('parameter'), id: v.string(), name: v.string() }), v.readonly());
13
+ export const BuilderParameterSerialisedSchema = v.pipe(v.object({ type: v.literal('parameter'), id: IdSchema, name: NameSchema }), v.readonly());
13
14
  export class BuilderRef {
14
15
  type = 'ref';
15
16
  id;
@@ -18,7 +19,7 @@ export class BuilderRef {
18
19
  }
19
20
  }
20
21
  export const BuilderRefSchema = v.instance(BuilderRef);
21
- export const BuilderRefSerialisedSchema = v.pipe(v.object({ type: v.literal('ref'), id: v.string() }), v.readonly());
22
+ export const BuilderRefSerialisedSchema = v.pipe(v.object({ type: v.literal('ref'), id: IdSchema }), v.readonly());
22
23
  export function parameter(name) {
23
24
  return new BuilderParameter(name);
24
25
  }