@builder-builder/builder 0.0.15 → 0.0.17

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 (52) hide show
  1. package/dist/bb.d.ts +7 -5
  2. package/dist/bb.js +11 -9
  3. package/dist/entities/builder/builder.d.ts +14 -10
  4. package/dist/entities/builder/builder.js +9 -6
  5. package/dist/entities/builder/index.d.ts +1 -2
  6. package/dist/entities/builder/index.js +1 -2
  7. package/dist/entities/index.d.ts +2 -2
  8. package/dist/entities/index.js +1 -1
  9. package/dist/entities/kind.d.ts +1 -1
  10. package/dist/entities/model/methods.d.ts +3 -3
  11. package/dist/entities/pricing/expression.d.ts +70 -0
  12. package/dist/entities/pricing/expression.js +43 -0
  13. package/dist/entities/pricing/index.d.ts +6 -0
  14. package/dist/entities/pricing/index.js +3 -0
  15. package/dist/entities/pricing/pricing.d.ts +17 -0
  16. package/dist/entities/pricing/pricing.js +21 -0
  17. package/dist/entities/pricing/rates.d.ts +3 -0
  18. package/dist/entities/pricing/rates.js +3 -0
  19. package/dist/entities/serialise.d.ts +519 -543
  20. package/dist/entities/serialise.js +38 -33
  21. package/dist/entities/validated.d.ts +3 -3
  22. package/dist/environment.d.ts +1 -1
  23. package/dist/index.d.ts +3 -3
  24. package/dist/index.js +1 -1
  25. package/dist/mappers/index.d.ts +2 -2
  26. package/dist/mappers/index.js +1 -1
  27. package/dist/mappers/price.d.ts +3 -0
  28. package/dist/mappers/price.js +111 -0
  29. package/dist/validate/builder.js +15 -10
  30. package/dist/validate/errors.d.ts +13 -3
  31. package/dist/validate/errors.js +11 -3
  32. package/dist/validate/index.d.ts +1 -1
  33. package/dist/validate/model.js +5 -62
  34. package/dist/validate/paths.d.ts +5 -0
  35. package/dist/validate/paths.js +68 -0
  36. package/dist/validate/pricing.d.ts +5 -3
  37. package/dist/validate/pricing.js +95 -39
  38. package/dist/validate/ui.js +59 -1
  39. package/dist/validate/variants.js +4 -0
  40. package/package.json +1 -10
  41. package/dist/cli.d.ts +0 -2
  42. package/dist/cli.js +0 -53
  43. package/dist/codegen/index.d.ts +0 -7
  44. package/dist/codegen/index.js +0 -212
  45. package/dist/codegen/template.d.ts +0 -5
  46. package/dist/codegen/template.js +0 -17
  47. package/dist/entities/builder/factory.d.ts +0 -7
  48. package/dist/entities/builder/factory.js +0 -4
  49. package/dist/entities/pricing.d.ts +0 -64
  50. package/dist/entities/pricing.js +0 -48
  51. package/dist/mappers/pricing.d.ts +0 -3
  52. package/dist/mappers/pricing.js +0 -101
@@ -1,64 +0,0 @@
1
- import * as v from 'valibot';
2
- export declare const BuilderPricingReduceSchema: v.PicklistSchema<["product", "sum", "first"], undefined>;
3
- export type BuilderPricingReduce = v.InferOutput<typeof BuilderPricingReduceSchema>;
4
- export type BuilderPricingTagExpression = {
5
- readonly kind: 'tag';
6
- readonly value: string;
7
- } | {
8
- readonly kind: 'modelTags';
9
- } | {
10
- readonly kind: 'variantTags';
11
- };
12
- export declare const BuilderPricingTagExpressionSchema: v.GenericSchema<BuilderPricingTagExpression>;
13
- export type BuilderPricingExpression = {
14
- readonly kind: 'num';
15
- readonly value: number;
16
- } | {
17
- readonly kind: 'variantPrice';
18
- } | {
19
- readonly kind: 'rate';
20
- readonly rate: string;
21
- readonly tag: BuilderPricingTagExpression;
22
- readonly reduce?: BuilderPricingReduce;
23
- } | {
24
- readonly kind: 'variants';
25
- readonly tag?: BuilderPricingTagExpression;
26
- readonly expression: BuilderPricingExpression;
27
- readonly reduce?: BuilderPricingReduce;
28
- } | {
29
- readonly kind: 'add';
30
- readonly left: BuilderPricingExpression;
31
- readonly right: BuilderPricingExpression;
32
- } | {
33
- readonly kind: 'sub';
34
- readonly left: BuilderPricingExpression;
35
- readonly right: BuilderPricingExpression;
36
- } | {
37
- readonly kind: 'mul';
38
- readonly left: BuilderPricingExpression;
39
- readonly right: BuilderPricingExpression;
40
- } | {
41
- readonly kind: 'div';
42
- readonly left: BuilderPricingExpression;
43
- readonly right: BuilderPricingExpression;
44
- };
45
- export declare const BuilderPricingExpressionSchema: v.GenericSchema<BuilderPricingExpression>;
46
- export type BuilderPricing = {
47
- readonly rates: Record<string, Record<string, number>>;
48
- readonly formula: BuilderPricingExpression;
49
- };
50
- export declare const BuilderPricingSchema: v.SchemaWithPipe<readonly [v.ObjectSchema<{
51
- readonly rates: v.SchemaWithPipe<readonly [v.RecordSchema<v.StringSchema<undefined>, v.RecordSchema<v.StringSchema<undefined>, v.NumberSchema<undefined>, undefined>, undefined>, v.ReadonlyAction<{
52
- [x: string]: {
53
- [x: string]: number;
54
- };
55
- }>]>;
56
- readonly formula: v.GenericSchema<BuilderPricingExpression>;
57
- }, undefined>, v.ReadonlyAction<{
58
- readonly rates: Readonly<{
59
- [x: string]: {
60
- [x: string]: number;
61
- };
62
- }>;
63
- formula: BuilderPricingExpression;
64
- }>]>;
@@ -1,48 +0,0 @@
1
- import * as v from 'valibot';
2
- import { serialisable } from '../serialisable.js';
3
- export const BuilderPricingReduceSchema = v.picklist(['product', 'sum', 'first']);
4
- export const BuilderPricingTagExpressionSchema = v.variant('kind', [
5
- v.object({ kind: v.literal('tag'), value: v.string() }),
6
- v.object({ kind: v.literal('modelTags') }),
7
- v.object({ kind: v.literal('variantTags') })
8
- ]);
9
- export const BuilderPricingExpressionSchema = v.lazy(() => v.variant('kind', [
10
- v.object({ kind: v.literal('num'), value: v.number() }),
11
- v.object({ kind: v.literal('variantPrice') }),
12
- v.object({
13
- kind: v.literal('rate'),
14
- rate: v.string(),
15
- tag: BuilderPricingTagExpressionSchema,
16
- reduce: v.optional(BuilderPricingReduceSchema)
17
- }),
18
- v.object({
19
- kind: v.literal('variants'),
20
- tag: v.optional(BuilderPricingTagExpressionSchema),
21
- expression: BuilderPricingExpressionSchema,
22
- reduce: v.optional(BuilderPricingReduceSchema)
23
- }),
24
- v.object({
25
- kind: v.literal('add'),
26
- left: BuilderPricingExpressionSchema,
27
- right: BuilderPricingExpressionSchema
28
- }),
29
- v.object({
30
- kind: v.literal('sub'),
31
- left: BuilderPricingExpressionSchema,
32
- right: BuilderPricingExpressionSchema
33
- }),
34
- v.object({
35
- kind: v.literal('mul'),
36
- left: BuilderPricingExpressionSchema,
37
- right: BuilderPricingExpressionSchema
38
- }),
39
- v.object({
40
- kind: v.literal('div'),
41
- left: BuilderPricingExpressionSchema,
42
- right: BuilderPricingExpressionSchema
43
- })
44
- ]));
45
- export const BuilderPricingSchema = serialisable(v.object({
46
- rates: v.pipe(v.record(v.string(), v.record(v.string(), v.number())), v.readonly()),
47
- formula: BuilderPricingExpressionSchema
48
- }));
@@ -1,3 +0,0 @@
1
- import type { BuilderModelValidated, BuilderRefEntities } from '../entities/index';
2
- import type { BuilderOrder } from './order';
3
- export declare function pricing(model: BuilderModelValidated, pricingInput: unknown, order: BuilderOrder, refs?: BuilderRefEntities): number;
@@ -1,101 +0,0 @@
1
- import * as v from 'valibot';
2
- import { check } from '../check.js';
3
- import { BuilderPricingSchema } from '../entities/index.js';
4
- import { BuilderVariantSchema } from '../instance.js';
5
- import { resolveRef } from './resolve.js';
6
- export function pricing(model, pricingInput, order, refs = []) {
7
- const resolved = resolveRef(pricingInput, refs);
8
- check.assert(BuilderPricingSchema, resolved, 'Pricing did not resolve to a pricing entity! ❌');
9
- const { rates, formula } = resolved;
10
- const modelTags = model.tags ?? [];
11
- const variants = collectVariants(order);
12
- return evaluate(formula);
13
- function evaluate(expression, currentVariant = null) {
14
- switch (expression.kind) {
15
- case 'num':
16
- return expression.value;
17
- case 'variantPrice':
18
- return variantPrice(currentVariant);
19
- case 'rate':
20
- return evaluateRate(expression, currentVariant);
21
- case 'variants':
22
- return evaluateVariants(expression);
23
- case 'add':
24
- return (evaluate(expression.left, currentVariant) + evaluate(expression.right, currentVariant));
25
- case 'sub':
26
- return (evaluate(expression.left, currentVariant) - evaluate(expression.right, currentVariant));
27
- case 'mul':
28
- return (evaluate(expression.left, currentVariant) * evaluate(expression.right, currentVariant));
29
- case 'div':
30
- return (evaluate(expression.left, currentVariant) / evaluate(expression.right, currentVariant));
31
- }
32
- }
33
- function evaluateRate(expression, currentVariant) {
34
- const table = rates[expression.rate];
35
- check.truthy(table, `Pricing: rate '${expression.rate}' not found! ❌`);
36
- const tagOrTags = resolveTagExpression(expression.tag, currentVariant);
37
- const keys = Array.isArray(tagOrTags) ? tagOrTags : [tagOrTags];
38
- const matches = keys
39
- .map((key) => table[key])
40
- .filter((value) => typeof value === 'number');
41
- check.truthy(matches.length > 0, `Pricing: rate '${expression.rate}' has no entry for keys [${keys.join(', ')}]! ❌`);
42
- return reduceValues(matches, expression.reduce ?? 'product');
43
- }
44
- function evaluateVariants(expression) {
45
- const { tag } = expression;
46
- const candidates = tag ? variants.filter((variant) => matchesFilter(variant, tag)) : variants;
47
- const results = candidates.map((variant) => evaluate(expression.expression, variant));
48
- return reduceValues(results, expression.reduce ?? 'sum');
49
- }
50
- function resolveTagExpression(tag, currentVariant) {
51
- switch (tag.kind) {
52
- case 'tag':
53
- return tag.value;
54
- case 'modelTags':
55
- return modelTags;
56
- case 'variantTags':
57
- check.truthy(currentVariant, 'Pricing: variantTags used outside variants iteration! ❌');
58
- return currentVariant.tags ?? [];
59
- }
60
- }
61
- function matchesFilter(variant, filter) {
62
- if (filter.kind === 'tag') {
63
- return (variant.tags ?? []).includes(filter.value);
64
- }
65
- if (filter.kind === 'modelTags') {
66
- return (variant.tags ?? []).some((tag) => modelTags.includes(tag));
67
- }
68
- check.falsy(true, 'Pricing: variantTags is not a valid variants.tag filter! ❌');
69
- return false;
70
- }
71
- }
72
- function reduceValues(values, mode) {
73
- if (mode === 'product') {
74
- return values.reduce((accumulator, value) => accumulator * value, 1);
75
- }
76
- if (mode === 'sum') {
77
- return values.reduce((accumulator, value) => accumulator + value, 0);
78
- }
79
- check.truthy(values.length > 0, 'Pricing: cannot reduce empty set with "first"! ❌');
80
- return values[0];
81
- }
82
- function variantPrice(variant) {
83
- check.truthy(variant, 'Pricing: variantPrice used outside variants iteration! ❌');
84
- const price = variant.details?.price;
85
- check.assert(v.number(), price, 'Pricing: variant missing numeric price detail! ❌');
86
- return price;
87
- }
88
- function collectVariants(order) {
89
- return Object.values(order).flatMap((value) => {
90
- if (value == null) {
91
- return [];
92
- }
93
- if (check.is(BuilderVariantSchema, value)) {
94
- return [value];
95
- }
96
- if (Array.isArray(value)) {
97
- return value.flatMap(collectVariants);
98
- }
99
- return collectVariants(value);
100
- });
101
- }