@builder-builder/builder 0.0.27 → 0.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/dist/bb.js +9 -10
  2. package/dist/client/client.d.ts +2 -1
  3. package/dist/client/client.js +4 -1
  4. package/dist/client/public.d.ts +2 -2
  5. package/dist/client/public.js +1 -1
  6. package/dist/client/schema.d.ts +126 -45
  7. package/dist/client/schema.js +6 -1
  8. package/dist/components/BuilderOption.svelte.d.ts +12 -12
  9. package/dist/components/BuilderOptionValueBoolean.svelte.d.ts +20 -0
  10. package/dist/components/BuilderOptionValueNumber.svelte.d.ts +21 -0
  11. package/dist/components/BuilderOptionValueSelect.svelte.d.ts +21 -0
  12. package/dist/components/BuilderOptionValueString.svelte.d.ts +21 -0
  13. package/dist/components/BuilderRender.svelte.d.ts +2 -2
  14. package/dist/components/index.d.ts +8 -8
  15. package/dist/components/index.js +4376 -4258
  16. package/dist/components/index.min.js +3 -0
  17. package/dist/entities/collection/collection.d.ts +191 -401
  18. package/dist/entities/collection/collection.js +7 -4
  19. package/dist/entities/collection/{when.d.ts → condition.d.ts} +4 -5
  20. package/dist/entities/collection/condition.js +2 -0
  21. package/dist/entities/collection/config.d.ts +62 -80
  22. package/dist/entities/collection/index.d.ts +4 -4
  23. package/dist/entities/collection/index.js +2 -2
  24. package/dist/entities/component/component.d.ts +71 -83
  25. package/dist/entities/component/component.js +4 -4
  26. package/dist/entities/component/condition.d.ts +10 -0
  27. package/dist/entities/component/{when.js → condition.js} +3 -9
  28. package/dist/entities/component/config.d.ts +33 -33
  29. package/dist/entities/component/config.js +18 -16
  30. package/dist/entities/component/detail.d.ts +61 -0
  31. package/dist/entities/component/detail.js +71 -0
  32. package/dist/entities/component/index.d.ts +6 -6
  33. package/dist/entities/component/index.js +3 -3
  34. package/dist/entities/{when.d.ts → condition.d.ts} +23 -36
  35. package/dist/entities/{when.js → condition.js} +20 -25
  36. package/dist/entities/expectation.d.ts +135 -3
  37. package/dist/entities/expectation.js +6 -2
  38. package/dist/entities/index.d.ts +9 -9
  39. package/dist/entities/index.js +4 -4
  40. package/dist/entities/kind.d.ts +4 -4
  41. package/dist/entities/kind.js +24 -25
  42. package/dist/entities/model/bind.d.ts +5 -5
  43. package/dist/entities/model/methods.d.ts +18 -27
  44. package/dist/entities/model/methods.js +4 -22
  45. package/dist/entities/model/model.d.ts +3 -1
  46. package/dist/entities/model/model.js +25 -27
  47. package/dist/entities/option/condition.d.ts +9 -0
  48. package/dist/entities/option/condition.js +2 -0
  49. package/dist/entities/option/config.d.ts +47 -72
  50. package/dist/entities/option/config.js +6 -6
  51. package/dist/entities/option/expectation.d.ts +6 -1
  52. package/dist/entities/option/expectation.js +2 -2
  53. package/dist/entities/option/index.d.ts +8 -8
  54. package/dist/entities/option/index.js +4 -4
  55. package/dist/entities/option/option.d.ts +179 -210
  56. package/dist/entities/option/option.js +4 -4
  57. package/dist/entities/option/select.d.ts +16 -43
  58. package/dist/entities/option/select.js +8 -31
  59. package/dist/entities/option/value.d.ts +73 -0
  60. package/dist/entities/option/value.js +99 -0
  61. package/dist/entities/paths.d.ts +2 -2
  62. package/dist/entities/pricing/expression.d.ts +16 -39
  63. package/dist/entities/pricing/expression.js +1 -16
  64. package/dist/entities/pricing/index.d.ts +1 -1
  65. package/dist/entities/pricing/rates.d.ts +1 -1
  66. package/dist/entities/references.d.ts +124 -84
  67. package/dist/entities/serialise.d.ts +175 -109
  68. package/dist/entities/serialise.js +32 -27
  69. package/dist/entities/ui/describe.d.ts +1 -1
  70. package/dist/entities/ui/input.d.ts +2 -2
  71. package/dist/entities/ui/page.d.ts +1 -1
  72. package/dist/entities/ui/pages.d.ts +2 -2
  73. package/dist/entities/validated.d.ts +3 -3
  74. package/dist/environment.d.ts +2 -2
  75. package/dist/errors/errors.d.ts +94 -58
  76. package/dist/errors/errors.js +41 -7
  77. package/dist/errors/exception.d.ts +3 -3
  78. package/dist/errors/index.d.ts +1 -1
  79. package/dist/errors/index.js +1 -1
  80. package/dist/errors/public.d.ts +1 -1
  81. package/dist/index.d.ts +1 -1
  82. package/dist/index.js +1 -1
  83. package/dist/instance.d.ts +53 -9
  84. package/dist/instance.js +6 -2
  85. package/dist/mappers/dependencies.d.ts +3 -0
  86. package/dist/mappers/dependencies.js +45 -0
  87. package/dist/mappers/index.d.ts +2 -2
  88. package/dist/mappers/index.js +2 -1
  89. package/dist/mappers/instance.js +26 -21
  90. package/dist/mappers/price.js +6 -4
  91. package/dist/mappers/resolve.js +23 -22
  92. package/dist/mappers/variants/index.d.ts +1 -2
  93. package/dist/mappers/variants/index.js +1 -2
  94. package/dist/mappers/variants/option-graph.d.ts +1 -2
  95. package/dist/mappers/variants/option-graph.js +4 -18
  96. package/dist/mappers/variants/variants.d.ts +3 -6
  97. package/dist/mappers/variants/variants.js +34 -11
  98. package/dist/primitive.d.ts +3 -0
  99. package/dist/primitive.js +2 -0
  100. package/dist/public.d.ts +20 -20
  101. package/dist/public.js +17 -9
  102. package/dist/validate/builder.d.ts +2 -2
  103. package/dist/validate/builder.js +15 -15
  104. package/dist/validate/expectations.d.ts +2 -2
  105. package/dist/validate/expectations.js +23 -5
  106. package/dist/validate/instance.d.ts +2 -2
  107. package/dist/validate/instance.js +31 -13
  108. package/dist/validate/model.d.ts +4 -4
  109. package/dist/validate/model.js +57 -51
  110. package/dist/validate/paths.d.ts +2 -2
  111. package/dist/validate/paths.js +19 -14
  112. package/dist/validate/pricing.d.ts +4 -4
  113. package/dist/validate/pricing.js +31 -31
  114. package/dist/validate/resolve.d.ts +2 -2
  115. package/dist/validate/resolve.js +27 -31
  116. package/dist/validate/ui.d.ts +4 -4
  117. package/dist/validate/ui.js +38 -38
  118. package/dist/validate/variants.d.ts +3 -3
  119. package/dist/validate/variants.js +32 -31
  120. package/package.json +4 -2
  121. package/dist/components/BuilderOptionSelect.svelte.d.ts +0 -21
  122. package/dist/components/BuilderOptionToggleBoolean.svelte.d.ts +0 -20
  123. package/dist/components/BuilderOptionToggleNumber.svelte.d.ts +0 -21
  124. package/dist/components/BuilderOptionToggleString.svelte.d.ts +0 -21
  125. package/dist/entities/collection/when.js +0 -2
  126. package/dist/entities/component/field.d.ts +0 -59
  127. package/dist/entities/component/field.js +0 -52
  128. package/dist/entities/component/when.d.ts +0 -11
  129. package/dist/entities/option/toggle.d.ts +0 -45
  130. package/dist/entities/option/toggle.js +0 -66
  131. package/dist/entities/option/when.d.ts +0 -10
  132. package/dist/entities/option/when.js +0 -2
@@ -7,57 +7,101 @@ export declare const BuilderInstanceSchema: v.GenericSchema<BuilderInstance>;
7
7
  export declare const BuilderInstancesSchema: v.SchemaWithPipe<readonly [v.ArraySchema<v.GenericSchema<BuilderInstance>, undefined>, v.ReadonlyAction<BuilderInstance[]>]>;
8
8
  export type BuilderInstances = v.InferOutput<typeof BuilderInstancesSchema>;
9
9
  export type BuilderInstanceInput = Readonly<Record<string, unknown>>;
10
+ export declare const BuilderVariantDetailSchema: v.SchemaWithPipe<readonly [v.ObjectSchema<{
11
+ readonly kind: v.PicklistSchema<["string", "boolean", "number", "price", "image"], undefined>;
12
+ readonly value: v.NullableSchema<v.NullableSchema<v.UnionSchema<[v.StringSchema<undefined>, v.BooleanSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>, undefined>;
13
+ }, undefined>, v.ReadonlyAction<{
14
+ kind: "string" | "number" | "boolean" | "price" | "image";
15
+ value: string | number | boolean | null;
16
+ }>]>;
17
+ export type BuilderVariantDetail = v.InferOutput<typeof BuilderVariantDetailSchema>;
10
18
  export declare const BuilderComponentVariantSchema: v.SchemaWithPipe<readonly [v.ObjectSchema<{
11
19
  readonly instance: v.GenericSchema<BuilderInstance>;
12
- readonly details: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, v.NullableSchema<v.UnionSchema<[v.StringSchema<undefined>, v.BooleanSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>, undefined>, undefined>;
20
+ readonly details: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, v.SchemaWithPipe<readonly [v.ObjectSchema<{
21
+ readonly kind: v.PicklistSchema<["string", "boolean", "number", "price", "image"], undefined>;
22
+ readonly value: v.NullableSchema<v.NullableSchema<v.UnionSchema<[v.StringSchema<undefined>, v.BooleanSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>, undefined>;
23
+ }, undefined>, v.ReadonlyAction<{
24
+ kind: "string" | "number" | "boolean" | "price" | "image";
25
+ value: string | number | boolean | null;
26
+ }>]>, undefined>, undefined>;
13
27
  readonly tags: v.OptionalSchema<v.SchemaWithPipe<readonly [v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, v.ReadonlyAction<string[]>]>, undefined>;
14
28
  }, undefined>, v.ReadonlyAction<{
15
29
  instance: BuilderInstance;
16
30
  details?: {
17
- [x: string]: string | number | boolean | null;
31
+ readonly [x: string]: Readonly<{
32
+ kind: "string" | "number" | "boolean" | "price" | "image";
33
+ value: string | number | boolean | null;
34
+ }>;
18
35
  } | undefined;
19
36
  tags?: readonly string[] | undefined;
20
37
  }>]>;
21
38
  export type BuilderComponentVariant = v.InferOutput<typeof BuilderComponentVariantSchema>;
22
39
  export declare const BuilderComponentVariantsSchema: v.SchemaWithPipe<readonly [v.ArraySchema<v.SchemaWithPipe<readonly [v.ObjectSchema<{
23
40
  readonly instance: v.GenericSchema<BuilderInstance>;
24
- readonly details: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, v.NullableSchema<v.UnionSchema<[v.StringSchema<undefined>, v.BooleanSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>, undefined>, undefined>;
41
+ readonly details: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, v.SchemaWithPipe<readonly [v.ObjectSchema<{
42
+ readonly kind: v.PicklistSchema<["string", "boolean", "number", "price", "image"], undefined>;
43
+ readonly value: v.NullableSchema<v.NullableSchema<v.UnionSchema<[v.StringSchema<undefined>, v.BooleanSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>, undefined>;
44
+ }, undefined>, v.ReadonlyAction<{
45
+ kind: "string" | "number" | "boolean" | "price" | "image";
46
+ value: string | number | boolean | null;
47
+ }>]>, undefined>, undefined>;
25
48
  readonly tags: v.OptionalSchema<v.SchemaWithPipe<readonly [v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, v.ReadonlyAction<string[]>]>, undefined>;
26
49
  }, undefined>, v.ReadonlyAction<{
27
50
  instance: BuilderInstance;
28
51
  details?: {
29
- [x: string]: string | number | boolean | null;
52
+ readonly [x: string]: Readonly<{
53
+ kind: "string" | "number" | "boolean" | "price" | "image";
54
+ value: string | number | boolean | null;
55
+ }>;
30
56
  } | undefined;
31
57
  tags?: readonly string[] | undefined;
32
58
  }>]>, undefined>, v.ReadonlyAction<Readonly<{
33
59
  instance: BuilderInstance;
34
60
  details?: {
35
- [x: string]: string | number | boolean | null;
61
+ readonly [x: string]: Readonly<{
62
+ kind: "string" | "number" | "boolean" | "price" | "image";
63
+ value: string | number | boolean | null;
64
+ }>;
36
65
  } | undefined;
37
66
  tags?: readonly string[] | undefined;
38
67
  }>[]>]>;
39
68
  export type BuilderComponentVariants = v.InferOutput<typeof BuilderComponentVariantsSchema>;
40
69
  export declare const BuilderVariantsSchema: v.SchemaWithPipe<readonly [v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, v.SchemaWithPipe<readonly [v.ArraySchema<v.SchemaWithPipe<readonly [v.ObjectSchema<{
41
70
  readonly instance: v.GenericSchema<BuilderInstance>;
42
- readonly details: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, v.NullableSchema<v.UnionSchema<[v.StringSchema<undefined>, v.BooleanSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>, undefined>, undefined>;
71
+ readonly details: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, v.SchemaWithPipe<readonly [v.ObjectSchema<{
72
+ readonly kind: v.PicklistSchema<["string", "boolean", "number", "price", "image"], undefined>;
73
+ readonly value: v.NullableSchema<v.NullableSchema<v.UnionSchema<[v.StringSchema<undefined>, v.BooleanSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>, undefined>;
74
+ }, undefined>, v.ReadonlyAction<{
75
+ kind: "string" | "number" | "boolean" | "price" | "image";
76
+ value: string | number | boolean | null;
77
+ }>]>, undefined>, undefined>;
43
78
  readonly tags: v.OptionalSchema<v.SchemaWithPipe<readonly [v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>, v.ReadonlyAction<string[]>]>, undefined>;
44
79
  }, undefined>, v.ReadonlyAction<{
45
80
  instance: BuilderInstance;
46
81
  details?: {
47
- [x: string]: string | number | boolean | null;
82
+ readonly [x: string]: Readonly<{
83
+ kind: "string" | "number" | "boolean" | "price" | "image";
84
+ value: string | number | boolean | null;
85
+ }>;
48
86
  } | undefined;
49
87
  tags?: readonly string[] | undefined;
50
88
  }>]>, undefined>, v.ReadonlyAction<Readonly<{
51
89
  instance: BuilderInstance;
52
90
  details?: {
53
- [x: string]: string | number | boolean | null;
91
+ readonly [x: string]: Readonly<{
92
+ kind: "string" | "number" | "boolean" | "price" | "image";
93
+ value: string | number | boolean | null;
94
+ }>;
54
95
  } | undefined;
55
96
  tags?: readonly string[] | undefined;
56
97
  }>[]>]>, undefined>, v.ReadonlyAction<{
57
98
  readonly [x: string]: readonly Readonly<{
58
99
  instance: BuilderInstance;
59
100
  details?: {
60
- [x: string]: string | number | boolean | null;
101
+ readonly [x: string]: Readonly<{
102
+ kind: "string" | "number" | "boolean" | "price" | "image";
103
+ value: string | number | boolean | null;
104
+ }>;
61
105
  } | undefined;
62
106
  tags?: readonly string[] | undefined;
63
107
  }>[];
package/dist/instance.js CHANGED
@@ -1,11 +1,15 @@
1
1
  import * as v from 'valibot';
2
- import { BuilderTagsSchema } from './entities/index.js';
2
+ import { BuilderComponentDetailKindSchema, BuilderTagsSchema } from './entities/index.js';
3
3
  import { BuilderPrimitiveSchema, NameSchema } from './primitive.js';
4
4
  export const BuilderInstanceSchema = v.pipe(v.record(NameSchema, v.union([BuilderPrimitiveSchema, v.lazy(() => BuilderInstancesSchema)])), v.readonly());
5
5
  export const BuilderInstancesSchema = v.pipe(v.array(BuilderInstanceSchema), v.readonly());
6
+ export const BuilderVariantDetailSchema = v.pipe(v.object({
7
+ kind: BuilderComponentDetailKindSchema,
8
+ value: v.nullable(BuilderPrimitiveSchema)
9
+ }), v.readonly());
6
10
  export const BuilderComponentVariantSchema = v.pipe(v.object({
7
11
  instance: BuilderInstanceSchema,
8
- details: v.optional(v.record(NameSchema, BuilderPrimitiveSchema)),
12
+ details: v.optional(v.record(NameSchema, BuilderVariantDetailSchema)),
9
13
  tags: v.optional(BuilderTagsSchema)
10
14
  }), v.readonly());
11
15
  export const BuilderComponentVariantsSchema = v.pipe(v.array(BuilderComponentVariantSchema), v.readonly());
@@ -0,0 +1,3 @@
1
+ import type { BuilderModelValidated } from '../entities/index';
2
+ export declare function dependencies(model: BuilderModelValidated): ReadonlyArray<string>;
3
+ export declare function dependencyKeys(payload: unknown, paths?: unknown): ReadonlyArray<string>;
@@ -0,0 +1,45 @@
1
+ import { BuilderPathSchema, BuilderPathsSchema, BuilderConditionMatchSchema, BuilderConditionUnlessSchema } from '../entities/index.js';
2
+ import { check } from '../errors/index.js';
3
+ export function dependencies(model) {
4
+ const entries = [...model.options, ...model.collections, ...model.components];
5
+ const names = new Set(entries.map((entry) => entry.name));
6
+ const ordered = [];
7
+ const visiting = new Set();
8
+ const visit = (name) => {
9
+ if (ordered.includes(name)) {
10
+ return true;
11
+ }
12
+ if (visiting.has(name)) {
13
+ return false;
14
+ }
15
+ const entry = entries.find((candidate) => candidate.name === name);
16
+ check.invariant(entry);
17
+ visiting.add(name);
18
+ const resolved = dependencyKeys(entry.payload, entry.paths)
19
+ .filter((dependency) => names.has(dependency))
20
+ .map((dependency) => visit(dependency))
21
+ .every(Boolean);
22
+ visiting.delete(name);
23
+ if (resolved) {
24
+ ordered.push(name);
25
+ }
26
+ return resolved;
27
+ };
28
+ names.forEach((name) => visit(name));
29
+ return ordered;
30
+ }
31
+ export function dependencyKeys(payload, paths = []) {
32
+ const conditionPaths = check.is(BuilderPathsSchema, paths) ? paths : [];
33
+ const keys = new Set(conditionPaths.map(([first]) => String(first)));
34
+ if (check.is(BuilderConditionMatchSchema, payload) &&
35
+ check.is(BuilderPathSchema, payload.matchPath)) {
36
+ const [firstMatchSegment] = payload.matchPath;
37
+ keys.add(String(firstMatchSegment));
38
+ }
39
+ else if (check.is(BuilderConditionUnlessSchema, payload) &&
40
+ check.is(BuilderPathSchema, payload.unlessPath)) {
41
+ const [firstUnlessSegment] = payload.unlessPath;
42
+ keys.add(String(firstUnlessSegment));
43
+ }
44
+ return Array.from(keys);
45
+ }
@@ -1,9 +1,9 @@
1
1
  export type { BuilderOrder } from './order';
2
2
  export type { BuilderRenderCollection, BuilderRenderCollectionAddRemove, BuilderRenderCollections, BuilderRenderMetadata, BuilderRenderOption, BuilderRenderOptions, BuilderRenderOptionUpdate, BuilderRenderPage, BuilderRenderPages, BuilderRenderResult } from './render/index';
3
- export type { BuilderOptionGraph } from './variants/index';
3
+ export { dependencies, dependencyKeys } from './dependencies.js';
4
4
  export { createInstance } from './instance.js';
5
5
  export { order } from './order.js';
6
6
  export { price } from './price.js';
7
7
  export { ordinal, render } from './render/index.js';
8
8
  export { resolveCollection, resolveCollections, resolveComponent, resolveComponents, resolveOption, resolveOptions } from './resolve.js';
9
- export { createVariants, optionGraph, variantsFor } from './variants/index.js';
9
+ export { createVariants } from './variants/index.js';
@@ -1,6 +1,7 @@
1
+ export { dependencies, dependencyKeys } from './dependencies.js';
1
2
  export { createInstance } from './instance.js';
2
3
  export { order } from './order.js';
3
4
  export { price } from './price.js';
4
5
  export { ordinal, render } from './render/index.js';
5
6
  export { resolveCollection, resolveCollections, resolveComponent, resolveComponents, resolveOption, resolveOptions } from './resolve.js';
6
- export { createVariants, optionGraph, variantsFor } from './variants/index.js';
7
+ export { createVariants } from './variants/index.js';
@@ -1,6 +1,7 @@
1
1
  import { modelsMerge, optionValueSchema } from '../entities/index.js';
2
2
  import { check } from '../errors/index.js';
3
3
  import { BuilderInstanceSchema, BuilderInstancesSchema } from '../instance.js';
4
+ import { dependencies } from './dependencies.js';
4
5
  import { resolveCollection, resolveOption } from './resolve.js';
5
6
  export function createInstance(entity, partial = {}, references = []) {
6
7
  const model = 'model' in entity ? entity.model : entity;
@@ -10,31 +11,35 @@ export function createInstance(entity, partial = {}, references = []) {
10
11
  }
11
12
  function buildInstance(model, partial, references) {
12
13
  const merged = modelsMerge(model);
14
+ const names = dependencies(merged);
13
15
  let instance = { ...partial };
14
- merged.options.forEach((option) => {
15
- const { name } = option;
16
- const payload = resolveOption(option, model, instance, references);
17
- if (payload == null) {
16
+ names.forEach((name) => {
17
+ const option = merged.options.find((entry) => entry.name === name);
18
+ if (option != null) {
19
+ const payload = resolveOption(option, model, instance, references);
20
+ if (payload == null) {
21
+ return;
22
+ }
23
+ if (check.is(optionValueSchema(payload), instance[name])) {
24
+ return;
25
+ }
26
+ instance = { ...instance, [name]: payload.defaultValue };
18
27
  return;
19
28
  }
20
- if (check.is(optionValueSchema(payload), instance[name])) {
21
- return;
22
- }
23
- instance = { ...instance, [name]: payload.defaultValue };
24
- });
25
- merged.collections.forEach((collection) => {
26
- const { name } = collection;
27
- const payload = resolveCollection(collection, model, instance, references);
28
- if (payload == null) {
29
- return;
29
+ const collection = merged.collections.find((entry) => entry.name === name);
30
+ if (collection != null) {
31
+ const payload = resolveCollection(collection, model, instance, references);
32
+ if (payload == null) {
33
+ return;
34
+ }
35
+ const existing = instance[name];
36
+ const existingItems = check.is(BuilderInstancesSchema, existing)
37
+ ? existing
38
+ : [];
39
+ const count = Math.min(Math.max(existingItems.length, payload.min), payload.max);
40
+ const items = Array.from({ length: count }, (_, index) => buildInstance(payload.model, existingItems[index] ?? {}, references));
41
+ instance = { ...instance, [name]: items };
30
42
  }
31
- const existing = instance[name];
32
- const existingItems = check.is(BuilderInstancesSchema, existing)
33
- ? existing
34
- : [];
35
- const count = Math.max(existingItems.length, payload.min);
36
- const items = Array.from({ length: count }, (_, index) => buildInstance(payload.model, existingItems[index] ?? {}, references));
37
- instance = { ...instance, [name]: items };
38
43
  });
39
44
  return instance;
40
45
  }
@@ -16,8 +16,10 @@ export function price(pricingInput, order) {
16
16
  }
17
17
  switch (expression.kind) {
18
18
  case 'variantPrice':
19
+ check.invariant(variant);
19
20
  return variantPrice(variant);
20
21
  case 'lookup':
22
+ check.invariant(variant);
21
23
  return evaluateLookup(expression, variant);
22
24
  case 'variants':
23
25
  return evaluateVariants(expression);
@@ -50,8 +52,8 @@ export function price(pricingInput, order) {
50
52
  return value;
51
53
  }
52
54
  function variantPrice(variant) {
53
- const candidate = variant?.details?.price;
54
- return check.is(NumberSchema, candidate) ? candidate : null;
55
+ const price = Object.values(variant.details ?? {}).find((detail) => detail.kind === 'price');
56
+ return check.is(NumberSchema, price?.value) ? price?.value : null;
55
57
  }
56
58
  function evaluateLookup(expression, variant) {
57
59
  const keys = resolveKey(expression.key, variant);
@@ -75,9 +77,9 @@ export function price(pricingInput, order) {
75
77
  function resolveKey(key, variant) {
76
78
  switch (key.kind) {
77
79
  case 'variantTags':
78
- return variant?.tags ?? [];
80
+ return variant.tags ?? [];
79
81
  case 'option': {
80
- const value = variant?.instance?.[key.name];
82
+ const value = variant.instance[key.name];
81
83
  return value == null ? [] : [String(value)];
82
84
  }
83
85
  }
@@ -1,26 +1,26 @@
1
1
  import * as v from 'valibot';
2
- import { BuilderCollectionConfigSerialisedSchema, BuilderCollectionWhenSerialisedSchema, BuilderComponentConfigSerialisedSchema, BuilderComponentWhenSerialisedSchema, BuilderOptionConfigSerialisedSchema, BuilderOptionWhenSerialisedSchema, BuilderPathsSchema, modelsMerge, whenBranches } from '../entities/index.js';
2
+ import { BuilderCollectionConfigSerialisedSchema, BuilderCollectionConditionSerialisedSchema, BuilderComponentConfigSerialisedSchema, BuilderComponentConditionSerialisedSchema, BuilderOptionConfigSerialisedSchema, BuilderOptionConditionSerialisedSchema, BuilderPathsSchema, modelsMerge, conditionBranches } from '../entities/index.js';
3
3
  import { check } from '../errors/index.js';
4
4
  import { BuilderInstanceSchema, BuilderInstancesSchema } from '../instance.js';
5
5
  import { BuilderPrimitiveSchema, NameSchema, NumberSchema } from '../primitive.js';
6
6
  import { BuilderRefSerialisedSchema, paramable } from '../references.js';
7
7
  export function resolveOption(option, model, instance, references = []) {
8
- return resolveEntryInstance(option, BuilderOptionConfigSerialisedSchema, BuilderOptionWhenSerialisedSchema, model, instance, references);
8
+ return resolveEntryInstance(option, BuilderOptionConfigSerialisedSchema, BuilderOptionConditionSerialisedSchema, model, instance, references);
9
9
  }
10
10
  export function resolveOptions(option, references = []) {
11
- return resolveEntryExhaustive(option, BuilderOptionConfigSerialisedSchema, BuilderOptionWhenSerialisedSchema, references);
11
+ return resolveEntryExhaustive(option, BuilderOptionConfigSerialisedSchema, BuilderOptionConditionSerialisedSchema, references);
12
12
  }
13
13
  export function resolveComponent(component, model, instance, references = []) {
14
- return resolveEntryInstance(component, BuilderComponentConfigSerialisedSchema, BuilderComponentWhenSerialisedSchema, model, instance, references);
14
+ return resolveEntryInstance(component, BuilderComponentConfigSerialisedSchema, BuilderComponentConditionSerialisedSchema, model, instance, references);
15
15
  }
16
16
  export function resolveComponents(component, references = []) {
17
- return resolveEntryExhaustive(component, BuilderComponentConfigSerialisedSchema, BuilderComponentWhenSerialisedSchema, references);
17
+ return resolveEntryExhaustive(component, BuilderComponentConfigSerialisedSchema, BuilderComponentConditionSerialisedSchema, references);
18
18
  }
19
19
  export function resolveCollection(collection, model, instance, references = []) {
20
- return resolveEntryInstance(collection, BuilderCollectionConfigSerialisedSchema, BuilderCollectionWhenSerialisedSchema, model, instance, references);
20
+ return resolveEntryInstance(collection, BuilderCollectionConfigSerialisedSchema, BuilderCollectionConditionSerialisedSchema, model, instance, references);
21
21
  }
22
22
  export function resolveCollections(collection, references = []) {
23
- return resolveEntryExhaustive(collection, BuilderCollectionConfigSerialisedSchema, BuilderCollectionWhenSerialisedSchema, references);
23
+ return resolveEntryExhaustive(collection, BuilderCollectionConfigSerialisedSchema, BuilderCollectionConditionSerialisedSchema, references);
24
24
  }
25
25
  export function resolveReference(value, references, schema = v.unknown()) {
26
26
  let resolved = value;
@@ -72,28 +72,29 @@ export function resolveItems(model, instance, pairs, references = []) {
72
72
  }
73
73
  return resolveItems(resolved.model, item, rest, references);
74
74
  }
75
- function resolveEntryInstance(entry, schema, whenSchema, model, instance, references) {
76
- const payload = resolveReference(entry.payload, references, paramable(v.union([schema, whenSchema])));
75
+ function resolveEntryInstance(entry, schema, conditionSchema, model, instance, references) {
76
+ const payload = resolveReference(entry.payload, references, paramable(v.union([schema, conditionSchema])));
77
+ if (entry.paths != null) {
78
+ check.assert(BuilderPathsSchema, entry.paths);
79
+ if (!entry.paths.every((path) => Boolean(resolvePath(model, instance, path, references)?.value))) {
80
+ return null;
81
+ }
82
+ }
77
83
  if (check.is(schema, payload)) {
78
84
  return payload;
79
85
  }
80
- check.assert(BuilderPathsSchema, entry.paths);
81
86
  const config = payload;
82
- if (!entry.paths.every((path) => Boolean(resolvePath(model, instance, path, references)?.value))) {
83
- return null;
84
- }
85
87
  switch (config.type) {
86
- case 'enable': {
87
- return config.payload;
88
- }
89
88
  case 'match': {
90
- const selectMap = config.selectMap;
91
- const matched = resolvePath(model, instance, config.matchPath, references);
92
- return selectMap[`${matched?.value}`] ?? null;
89
+ const value = resolvePath(model, instance, config.matchPath, references)?.value;
90
+ if (value == null) {
91
+ return null;
92
+ }
93
+ return config.selectMap[`${value}`] ?? null;
93
94
  }
94
95
  case 'unless': {
95
96
  const value = resolvePath(model, instance, config.unlessPath, references)?.value;
96
- if (!value) {
97
+ if (value == null) {
97
98
  return null;
98
99
  }
99
100
  check.assert(BuilderPrimitiveSchema, value);
@@ -104,6 +105,6 @@ function resolveEntryInstance(entry, schema, whenSchema, model, instance, refere
104
105
  }
105
106
  }
106
107
  }
107
- function resolveEntryExhaustive(entry, schema, whenSchema, references) {
108
- return whenBranches(resolveReference(entry.payload, references, paramable(v.union([schema, whenSchema]))), schema);
108
+ function resolveEntryExhaustive(entry, schema, conditionSchema, references) {
109
+ return conditionBranches(resolveReference(entry.payload, references, paramable(v.union([schema, conditionSchema]))), schema);
109
110
  }
@@ -1,2 +1 @@
1
- export { BuilderOptionGraph } from './option-graph.js';
2
- export { createVariants, optionGraph, variantsFor } from './variants.js';
1
+ export { createVariants } from './variants.js';
@@ -1,2 +1 @@
1
- export { BuilderOptionGraph } from './option-graph.js';
2
- export { createVariants, optionGraph, variantsFor } from './variants.js';
1
+ export { createVariants } from './variants.js';
@@ -1,4 +1,4 @@
1
- import type { BuilderModelValidated, BuilderOptionValidated, BuilderPaths } from '../../entities/index';
1
+ import type { BuilderModelValidated, BuilderOptionValidated } from '../../entities/index';
2
2
  import type { BuilderInstances } from '../../instance';
3
3
  export type GraphKeys = ReadonlySet<string>;
4
4
  export type GraphPath = {
@@ -8,7 +8,6 @@ export type GraphPath = {
8
8
  };
9
9
  export type GraphPaths = ReadonlyArray<GraphPath>;
10
10
  export declare function crossProduct(left: BuilderInstances, right: BuilderInstances): BuilderInstances;
11
- export declare function dependencyKeys(payload: unknown, paths?: BuilderPaths): ReadonlyArray<string>;
12
11
  export declare class BuilderOptionGraph {
13
12
  #private;
14
13
  readonly paths: GraphPaths;
@@ -1,5 +1,5 @@
1
- import { BuilderPathSchema, BuilderWhenMatchSchema, BuilderWhenUnlessSchema } from '../../entities/index.js';
2
1
  import { check } from '../../errors/index.js';
2
+ import { dependencyKeys } from '../dependencies.js';
3
3
  import { resolveOption } from '../resolve.js';
4
4
  export function crossProduct(left, right) {
5
5
  return left.flatMap((leftModel) => right.flatMap((rightModel) => {
@@ -11,20 +11,6 @@ export function crossProduct(left, right) {
11
11
  return [{ ...leftModel, ...rightModel }];
12
12
  }));
13
13
  }
14
- export function dependencyKeys(payload, paths = []) {
15
- const keys = new Set(paths.map(([first]) => String(first)));
16
- if (check.is(BuilderWhenMatchSchema, payload)) {
17
- check.assert(BuilderPathSchema, payload.matchPath);
18
- const [firstMatchSegment] = payload.matchPath;
19
- keys.add(String(firstMatchSegment));
20
- }
21
- else if (check.is(BuilderWhenUnlessSchema, payload)) {
22
- check.assert(BuilderPathSchema, payload.unlessPath);
23
- const [firstUnlessSegment] = payload.unlessPath;
24
- keys.add(String(firstUnlessSegment));
25
- }
26
- return Array.from(keys);
27
- }
28
14
  export class BuilderOptionGraph {
29
15
  paths;
30
16
  constructor(paths = []) {
@@ -83,13 +69,13 @@ export class BuilderOptionGraph {
83
69
  }, { keys: new Set([...first.keys, first.name]), instances: first.instances });
84
70
  }
85
71
  #optionValues(name, values) {
86
- if (values.type === 'select') {
72
+ if (values.kind === 'select') {
87
73
  return [...values.options];
88
74
  }
89
- if (values.valueType === 'boolean') {
75
+ if (values.kind === 'boolean') {
90
76
  return values.isOptional ? [true, false, null] : [true, false];
91
77
  }
92
- if (values.valueType === 'string') {
78
+ if (values.kind === 'string') {
93
79
  return values.isOptional ? [name, null] : [name];
94
80
  }
95
81
  return values.isOptional ? [1, null] : [1];
@@ -1,6 +1,3 @@
1
- import type { BuilderCollectionValidated, BuilderComponentValidated, BuilderModelValidated, BuilderValidated } from '../../entities/index';
2
- import type { BuilderVariants, BuilderInstances } from '../../instance';
3
- import { BuilderOptionGraph } from './option-graph.js';
4
- export declare function createVariants(entity: BuilderValidated | BuilderModelValidated): BuilderVariants;
5
- export declare function optionGraph(model: BuilderModelValidated): BuilderOptionGraph;
6
- export declare function variantsFor(entity: BuilderComponentValidated | BuilderCollectionValidated, options: BuilderOptionGraph): BuilderInstances;
1
+ import type { BuilderModelValidated, BuilderReferences, BuilderValidated } from '../../entities/index';
2
+ import type { BuilderVariants } from '../../instance';
3
+ export declare function createVariants(entity: BuilderValidated | BuilderModelValidated, references?: BuilderReferences): BuilderVariants;
@@ -1,34 +1,57 @@
1
1
  import { BuilderModelSerialisedSchema, BuilderSerialisedSchema, modelsMerge } from '../../entities/index.js';
2
2
  import { check } from '../../errors/index.js';
3
- import { resolveCollection } from '../resolve.js';
4
- import { BuilderOptionGraph, crossProduct, dependencyKeys } from './option-graph.js';
5
- export function createVariants(entity) {
3
+ import { dependencies, dependencyKeys } from '../dependencies.js';
4
+ import { resolveCollection, resolveComponent } from '../resolve.js';
5
+ import { BuilderOptionGraph, crossProduct } from './option-graph.js';
6
+ export function createVariants(entity, references = []) {
6
7
  const model = check.is(BuilderSerialisedSchema, entity) ? entity.model : entity;
7
- return buildVariants(model);
8
+ return buildVariants(model, references);
8
9
  }
9
- function buildVariants(model) {
10
+ function buildVariants(model, references) {
10
11
  const merged = modelsMerge(model);
11
12
  const options = optionGraph(merged);
12
13
  const nestedVariants = merged.collections.flatMap((entry) => variantsFor(entry, options).flatMap((instance) => {
13
- const resolved = resolveCollection(entry, merged, instance);
14
+ const resolved = resolveCollection(entry, merged, instance, references);
14
15
  if (resolved == null) {
15
16
  return [];
16
17
  }
17
18
  check.assert(BuilderModelSerialisedSchema, resolved.model);
18
- return [buildVariants(resolved.model)];
19
+ return [buildVariants(resolved.model, references)];
19
20
  }));
20
21
  return {
21
22
  ...nestedVariants.reduce((accumulated, component) => ({ ...accumulated, ...component }), {}),
22
23
  ...Object.fromEntries(merged.components.map((component) => [
23
24
  component.name,
24
- variantsFor(component, options).map((instance) => ({ instance }))
25
+ componentVariants(component, merged, options, references)
25
26
  ]))
26
27
  };
27
28
  }
28
- export function optionGraph(model) {
29
- return model.options.reduce((graph, option) => graph.add(option, model), new BuilderOptionGraph());
29
+ function componentVariants(component, model, options, references) {
30
+ return variantsFor(component, options).map((instance) => {
31
+ const resolved = resolveComponent(component, model, instance, references);
32
+ const declarations = resolved?.details ?? [];
33
+ const details = Object.fromEntries(declarations.map((declaration) => {
34
+ const { name, kind } = declaration;
35
+ return [name, { kind, value: null }];
36
+ }));
37
+ if (Object.keys(details).length === 0) {
38
+ return { instance };
39
+ }
40
+ return { instance, details };
41
+ });
42
+ }
43
+ function optionGraph(model) {
44
+ const names = dependencies(model);
45
+ let graph = new BuilderOptionGraph();
46
+ names.forEach((name) => {
47
+ const option = model.options.find((entry) => entry.name === name);
48
+ if (option != null) {
49
+ graph = graph.add(option, model);
50
+ }
51
+ });
52
+ return graph;
30
53
  }
31
- export function variantsFor(entity, options) {
54
+ function variantsFor(entity, options) {
32
55
  const keys = new Set(dependencyKeys(entity.payload, entity.paths));
33
56
  const graphPaths = Array.from(keys)
34
57
  .map((key) => options.get(key))
@@ -4,7 +4,10 @@ export declare const NumberSchema: v.NumberSchema<undefined>;
4
4
  export declare const BooleanSchema: v.BooleanSchema<undefined>;
5
5
  export declare const NameSchema: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
6
6
  export declare const IdSchema: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
7
+ export declare const UrlSchema: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.UrlAction<string, undefined>]>;
7
8
  export declare const BuilderPrimitiveSchema: v.NullableSchema<v.UnionSchema<[v.StringSchema<undefined>, v.BooleanSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>;
8
9
  export type BuilderPrimitive = v.InferOutput<typeof BuilderPrimitiveSchema>;
9
10
  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)[]>]>;
10
11
  export type BuilderPrimitives = v.InferOutput<typeof BuilderPrimitivesSchema>;
12
+ export declare const BuilderPrimitivesNonEmptySchema: v.SchemaWithPipe<readonly [v.TupleWithRestSchema<[v.NullableSchema<v.UnionSchema<[v.StringSchema<undefined>, v.BooleanSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>], v.NullableSchema<v.UnionSchema<[v.StringSchema<undefined>, v.BooleanSchema<undefined>, v.NumberSchema<undefined>], undefined>, undefined>, undefined>, v.ReadonlyAction<[string | number | boolean | null, ...(string | number | boolean | null)[]]>]>;
13
+ export type BuilderPrimitivesNonEmpty = v.InferOutput<typeof BuilderPrimitivesNonEmptySchema>;
package/dist/primitive.js CHANGED
@@ -4,5 +4,7 @@ export const NumberSchema = v.number();
4
4
  export const BooleanSchema = v.boolean();
5
5
  export const NameSchema = v.pipe(StringSchema, v.minLength(1));
6
6
  export const IdSchema = v.pipe(StringSchema, v.minLength(1));
7
+ export const UrlSchema = v.pipe(StringSchema, v.url());
7
8
  export const BuilderPrimitiveSchema = v.nullable(v.union([StringSchema, BooleanSchema, NumberSchema]));
8
9
  export const BuilderPrimitivesSchema = v.pipe(v.array(BuilderPrimitiveSchema), v.readonly());
10
+ export const BuilderPrimitivesNonEmptySchema = v.pipe(v.tupleWithRest([BuilderPrimitiveSchema], BuilderPrimitiveSchema), v.readonly());