@builder-builder/builder 0.0.1

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 (82) hide show
  1. package/README.md +38 -0
  2. package/dist/assert/assert.d.ts +28 -0
  3. package/dist/assert/assert.js +28 -0
  4. package/dist/assert/expectation.d.ts +20 -0
  5. package/dist/assert/expectation.js +21 -0
  6. package/dist/assert/index.d.ts +3 -0
  7. package/dist/assert/index.js +2 -0
  8. package/dist/config.d.ts +14 -0
  9. package/dist/config.js +1 -0
  10. package/dist/core/builder.d.ts +61 -0
  11. package/dist/core/builder.js +72 -0
  12. package/dist/core/collection/collection.d.ts +33 -0
  13. package/dist/core/collection/collection.js +55 -0
  14. package/dist/core/collection/index.d.ts +4 -0
  15. package/dist/core/collection/index.js +2 -0
  16. package/dist/core/collection/method.d.ts +51 -0
  17. package/dist/core/collection/method.js +11 -0
  18. package/dist/core/component/component.d.ts +14 -0
  19. package/dist/core/component/component.js +17 -0
  20. package/dist/core/component/graph.d.ts +13 -0
  21. package/dist/core/component/graph.js +52 -0
  22. package/dist/core/component/index.d.ts +4 -0
  23. package/dist/core/component/index.js +2 -0
  24. package/dist/core/component/method.d.ts +13 -0
  25. package/dist/core/component/method.js +1 -0
  26. package/dist/core/graph.d.ts +8 -0
  27. package/dist/core/graph.js +1 -0
  28. package/dist/core/index.d.ts +8 -0
  29. package/dist/core/index.js +4 -0
  30. package/dist/core/option/graph.d.ts +11 -0
  31. package/dist/core/option/graph.js +78 -0
  32. package/dist/core/option/index.d.ts +9 -0
  33. package/dist/core/option/index.js +5 -0
  34. package/dist/core/option/method.d.ts +52 -0
  35. package/dist/core/option/method.js +9 -0
  36. package/dist/core/option/option.d.ts +22 -0
  37. package/dist/core/option/option.js +49 -0
  38. package/dist/core/option/select.d.ts +17 -0
  39. package/dist/core/option/select.js +30 -0
  40. package/dist/core/option/toggle.d.ts +14 -0
  41. package/dist/core/option/toggle.js +27 -0
  42. package/dist/index.d.ts +16 -0
  43. package/dist/index.js +6 -0
  44. package/dist/invariant.d.ts +1 -0
  45. package/dist/invariant.js +6 -0
  46. package/dist/paths.d.ts +14 -0
  47. package/dist/paths.js +8 -0
  48. package/dist/prettify.d.ts +3 -0
  49. package/dist/prettify.js +1 -0
  50. package/dist/resolve/index.d.ts +9 -0
  51. package/dist/resolve/index.js +5 -0
  52. package/dist/resolve/instance.d.ts +3 -0
  53. package/dist/resolve/instance.js +26 -0
  54. package/dist/resolve/models.d.ts +3 -0
  55. package/dist/resolve/models.js +10 -0
  56. package/dist/resolve/order.d.ts +18 -0
  57. package/dist/resolve/order.js +24 -0
  58. package/dist/resolve/render.d.ts +21 -0
  59. package/dist/resolve/render.js +182 -0
  60. package/dist/resolve/validate.d.ts +32 -0
  61. package/dist/resolve/validate.js +50 -0
  62. package/dist/schemas/description.d.ts +5 -0
  63. package/dist/schemas/description.js +3 -0
  64. package/dist/schemas/index.d.ts +10 -0
  65. package/dist/schemas/index.js +5 -0
  66. package/dist/schemas/layout.d.ts +52 -0
  67. package/dist/schemas/layout.js +6 -0
  68. package/dist/schemas/primitives.d.ts +9 -0
  69. package/dist/schemas/primitives.js +5 -0
  70. package/dist/schemas/serialise.d.ts +1077 -0
  71. package/dist/schemas/serialise.js +141 -0
  72. package/dist/schemas/ui.d.ts +96 -0
  73. package/dist/schemas/ui.js +23 -0
  74. package/dist/serialise/deserialise.d.ts +9 -0
  75. package/dist/serialise/deserialise.js +108 -0
  76. package/dist/serialise/index.d.ts +4 -0
  77. package/dist/serialise/index.js +3 -0
  78. package/dist/serialise/serialise.d.ts +10 -0
  79. package/dist/serialise/serialise.js +123 -0
  80. package/dist/ui.d.ts +18 -0
  81. package/dist/ui.js +35 -0
  82. package/package.json +70 -0
@@ -0,0 +1,11 @@
1
+ import type { GraphPath, GraphPaths } from '../graph';
2
+ import { BuilderOption } from './option.js';
3
+ export type BuilderOptionGraphs = ReadonlyArray<BuilderOptionGraph>;
4
+ export declare class BuilderOptionGraph {
5
+ readonly paths: GraphPaths;
6
+ constructor(paths?: GraphPaths);
7
+ static merge(...graphs: BuilderOptionGraphs): BuilderOptionGraph;
8
+ has(name: string): boolean;
9
+ get(name: string): GraphPath;
10
+ add(option: BuilderOption): BuilderOptionGraph;
11
+ }
@@ -0,0 +1,78 @@
1
+ import * as v from 'valibot';
2
+ import { invariant } from '../../invariant.js';
3
+ import { BuilderOption } from './option.js';
4
+ import { BuilderSelectType } from './select.js';
5
+ export class BuilderOptionGraph {
6
+ paths;
7
+ constructor(paths = []) {
8
+ this.paths = paths;
9
+ }
10
+ static merge(...graphs) {
11
+ return new BuilderOptionGraph(graphs.flatMap((graph) => graph.paths));
12
+ }
13
+ has(name) {
14
+ return this.paths.some((graphPath) => graphPath.name === name);
15
+ }
16
+ get(name) {
17
+ const graphPath = this.paths.find((graphPath) => graphPath.name === name);
18
+ invariant(graphPath, `Option '${name}' not found in graph! ❌`);
19
+ return graphPath;
20
+ }
21
+ add(option) {
22
+ const dependencyKeys = option.dependencyKeys();
23
+ if (dependencyKeys.length === 0) {
24
+ const values = optionValues(option);
25
+ return new BuilderOptionGraph([
26
+ ...this.paths,
27
+ {
28
+ name: option.name,
29
+ keys: new Set(),
30
+ models: values.map((value) => ({ [option.name]: value }))
31
+ }
32
+ ]);
33
+ }
34
+ const merged = mergePaths(new Set(dependencyKeys), this.paths);
35
+ const finalModels = [];
36
+ merged.models.forEach((model) => {
37
+ const result = option.resolve(model);
38
+ if (result) {
39
+ optionValues(result).forEach((value) => {
40
+ finalModels.push({ ...model, [result.name]: value });
41
+ });
42
+ }
43
+ else {
44
+ finalModels.push({ ...model });
45
+ }
46
+ });
47
+ return new BuilderOptionGraph([
48
+ ...this.paths,
49
+ { name: option.name, keys: merged.keys, models: finalModels }
50
+ ]);
51
+ }
52
+ }
53
+ function mergePaths(dependencyKeys, graphPaths) {
54
+ const dependencyPaths = Array.from(dependencyKeys).map((dependencyKey) => {
55
+ const dependencyPath = graphPaths.find((graphPath) => graphPath.name === dependencyKey);
56
+ invariant(dependencyPath, `Option dependency '${dependencyKey}' not found in graph! ❌`);
57
+ return dependencyPath;
58
+ });
59
+ const [first, ...rest] = dependencyPaths;
60
+ return rest.reduce((merged, next) => {
61
+ const keys = new Set([...merged.keys, ...next.keys, next.name]);
62
+ const models = next.models.flatMap((nextModel) => merged.models.map((mergedModel) => ({ ...nextModel, ...mergedModel })));
63
+ return { keys, models };
64
+ }, { keys: new Set([...first.keys, first.name]), models: first.models });
65
+ }
66
+ function optionValues(option) {
67
+ const values = option.values;
68
+ if (v.is(v.instance(BuilderSelectType), values)) {
69
+ return [...values.options];
70
+ }
71
+ if (values.valueSchema.expects.includes('boolean')) {
72
+ return values.isOptional ? [true, false, null] : [true, false];
73
+ }
74
+ if (values.valueSchema.expects.includes('string')) {
75
+ return values.isOptional ? [option.name, null] : [option.name];
76
+ }
77
+ return values.isOptional ? [1, null] : [1];
78
+ }
@@ -0,0 +1,9 @@
1
+ export type { BuilderOptionEnableConfig, BuilderOptionMatchConfig, BuilderOptionMethod, BuilderOptionUnlessConfig, BuilderOptionWhenConfig } from './method';
2
+ export type { BuilderOptionGraphs } from './graph';
3
+ export type { BuilderOptionEntries, BuilderOptionValues, BuilderSelectTypeGeneric, BuilderToggleTypeGeneric, BuilderOptionValueSchema } from './option';
4
+ export type { BuilderSelectTypeLabels, BuilderSelectTypeValues } from './select';
5
+ export { enable, match, unless } from './method.js';
6
+ export { BuilderOptionGraph } from './graph.js';
7
+ export { BuilderOption } from './option.js';
8
+ export { select, BuilderSelectType } from './select.js';
9
+ export { BuilderToggleType, toggleBoolean, toggleNumber, toggleString } from './toggle.js';
@@ -0,0 +1,5 @@
1
+ export { enable, match, unless } from './method.js';
2
+ export { BuilderOptionGraph } from './graph.js';
3
+ export { BuilderOption } from './option.js';
4
+ export { select, BuilderSelectType } from './select.js';
5
+ export { BuilderToggleType, toggleBoolean, toggleNumber, toggleString } from './toggle.js';
@@ -0,0 +1,52 @@
1
+ import type { BuilderPrimitive } from '../../config';
2
+ import type { BuilderPath, BuilderPaths, BuilderResolvePath, BuilderValidPath } from '../../paths';
3
+ import type { BuilderStateMerge, BuilderState } from '../builder';
4
+ import type { Builder } from '../builder';
5
+ import type { BuilderOptionValues } from './option';
6
+ import type { BuilderOption } from './option';
7
+ export type BuilderOptionEnableConfig<Values extends BuilderOptionValues = BuilderOptionValues> = {
8
+ readonly type: 'enable';
9
+ readonly values: Values;
10
+ };
11
+ export type BuilderOptionMatchConfig<SelectMap extends Record<string, BuilderOptionValues | null> = Record<string, BuilderOptionValues | null>, MatchPath extends BuilderPath = BuilderPath> = {
12
+ readonly type: 'match';
13
+ readonly matchPath: MatchPath;
14
+ readonly selectMap: SelectMap;
15
+ };
16
+ export type BuilderOptionUnlessConfig<Values extends BuilderOptionValues = BuilderOptionValues, UnlessPath extends BuilderPath = BuilderPath> = {
17
+ readonly type: 'unless';
18
+ readonly unlessPath: UnlessPath;
19
+ readonly disabledValues: ReadonlyArray<BuilderPrimitive>;
20
+ readonly values: Values;
21
+ };
22
+ export type BuilderOptionWhenConfig = BuilderOptionEnableConfig<BuilderOptionValues> | BuilderOptionMatchConfig<Record<string, BuilderOptionValues | null>> | BuilderOptionUnlessConfig<BuilderOptionValues>;
23
+ export type BuilderOptionWhenConfigValues<Config extends BuilderOptionWhenConfig> = Config extends BuilderOptionEnableConfig<infer Values> ? Values : Config extends BuilderOptionUnlessConfig<infer Values> ? Values : Config extends BuilderOptionMatchConfig<infer SelectMapType> ? NonNullable<SelectMapType[keyof SelectMapType]> & BuilderOptionValues : never;
24
+ export type BuilderOptionMethod<State extends BuilderState> = {
25
+ <const Name extends string, const Values extends BuilderOptionValues>(name: Name, values: Values): Builder<BuilderStateMerge<State, {
26
+ model: State['model'] & {
27
+ [K in Name]: Values['value'];
28
+ };
29
+ options: [...State['options'], BuilderOption<Name, Values>];
30
+ }>>;
31
+ when: <const GatePaths extends ReadonlyArray<BuilderValidPath<State['model']>>, const Name extends string, const Config extends BuilderOptionWhenConfig>(gatePaths: GatePaths, name: Name, config: Config & WhenConfigConstrained<State['model'], Config>) => Builder<BuilderStateMerge<State, {
32
+ model: State['model'] & {
33
+ [K in Name]: BuilderOptionWhenConfigValues<Config>['value'] | OptionWhenNullability<State['model'], GatePaths, Config>;
34
+ };
35
+ options: [...State['options'], BuilderOption<Name, BuilderOptionWhenConfigValues<Config>>];
36
+ }>>;
37
+ };
38
+ export declare function enable<const Values extends BuilderOptionValues>(values: Values): BuilderOptionEnableConfig<Values>;
39
+ export declare function match<const MatchPath extends BuilderPath, const SelectMap extends Record<string, BuilderOptionValues | null>>(matchPath: MatchPath, selectMap: SelectMap): BuilderOptionMatchConfig<SelectMap, MatchPath>;
40
+ export declare function unless<const Values extends BuilderOptionValues, const UnlessPath extends BuilderPath>(unlessPath: UnlessPath, disabledValues: ReadonlyArray<BuilderPrimitive>, values: Values): BuilderOptionUnlessConfig<Values, UnlessPath>;
41
+ type OptionConfigNullable<Config extends BuilderOptionWhenConfig> = Config extends BuilderOptionUnlessConfig ? null : Config extends BuilderOptionMatchConfig<infer SelectMapType> ? null extends SelectMapType[keyof SelectMapType] ? null : never : never;
42
+ type OptionGatePathNullable<Model, Path extends BuilderPath> = null extends BuilderResolvePath<Model, Path> ? null : never;
43
+ type OptionGatePathsNullable<Model, GatePaths extends BuilderPaths> = GatePaths extends readonly [
44
+ infer Head extends BuilderPath,
45
+ ...infer Tail extends BuilderPaths
46
+ ] ? OptionGatePathNullable<Model, Head> | OptionGatePathsNullable<Model, Tail> : never;
47
+ type OptionWhenNullability<Model, GatePaths extends BuilderPaths, Config extends BuilderOptionWhenConfig> = OptionGatePathsNullable<Model, GatePaths> | OptionConfigNullable<Config>;
48
+ type MatchKeyOfConfig<Model, Config extends BuilderOptionWhenConfig> = Config extends BuilderOptionMatchConfig<any, infer MatchPath> ? BuilderResolvePath<Model, MatchPath> & string : string;
49
+ type WhenConfigConstrained<Model, Config extends BuilderOptionWhenConfig> = Config extends BuilderOptionMatchConfig<any, infer MatchPath> ? BuilderOptionMatchConfig<Record<MatchKeyOfConfig<Model, Config>, BuilderOptionValues | null>, MatchPath & Readonly<BuilderValidPath<Model>>> : Config extends BuilderOptionUnlessConfig ? Config & {
50
+ readonly unlessPath: Readonly<BuilderValidPath<Model>>;
51
+ } : Config;
52
+ export {};
@@ -0,0 +1,9 @@
1
+ export function enable(values) {
2
+ return { type: 'enable', values };
3
+ }
4
+ export function match(matchPath, selectMap) {
5
+ return { type: 'match', matchPath, selectMap };
6
+ }
7
+ export function unless(unlessPath, disabledValues, values) {
8
+ return { type: 'unless', unlessPath, disabledValues, values };
9
+ }
@@ -0,0 +1,22 @@
1
+ import type { BuilderPaths } from '../../paths';
2
+ import type { BuilderOptionWhenConfig } from './method';
3
+ import type { BuilderSelectType, BuilderSelectTypeValues } from './select';
4
+ import type { BuilderToggleType } from './toggle';
5
+ import * as v from 'valibot';
6
+ export type BuilderOptionValueSchema = v.GenericSchema<string | number | boolean | null>;
7
+ export type BuilderSelectTypeGeneric = BuilderSelectType<BuilderSelectTypeValues, BuilderOptionValueSchema>;
8
+ export type BuilderToggleTypeGeneric = BuilderToggleType<BuilderOptionValueSchema>;
9
+ export type BuilderOptionValues = BuilderSelectTypeGeneric | BuilderToggleTypeGeneric;
10
+ export type BuilderOptionEntries = ReadonlyArray<BuilderOption>;
11
+ export declare class BuilderOption<const Name extends string = string, const Values extends BuilderOptionValues = BuilderOptionValues> {
12
+ readonly model: {
13
+ [K in Name]: Values['value'];
14
+ };
15
+ readonly name: Name;
16
+ readonly values: Values;
17
+ readonly gatePaths: BuilderPaths;
18
+ readonly config: BuilderOptionWhenConfig | null;
19
+ constructor(name: Name, values: Values, gatePaths?: BuilderPaths, config?: BuilderOptionWhenConfig | null);
20
+ resolve(model: unknown): BuilderOption<Name> | null;
21
+ dependencyKeys(): ReadonlyArray<string>;
22
+ }
@@ -0,0 +1,49 @@
1
+ import * as v from 'valibot';
2
+ import { readPath } from '../../paths.js';
3
+ export class BuilderOption {
4
+ name;
5
+ values;
6
+ gatePaths;
7
+ config;
8
+ constructor(name, values, gatePaths = [], config = null) {
9
+ this.name = name;
10
+ this.values = values;
11
+ this.gatePaths = gatePaths;
12
+ this.config = config;
13
+ }
14
+ resolve(model) {
15
+ if (this.config === null) {
16
+ return this;
17
+ }
18
+ if (!this.gatePaths.every((path) => !!readPath(model, path))) {
19
+ return null;
20
+ }
21
+ switch (this.config.type) {
22
+ case 'enable': {
23
+ return this;
24
+ }
25
+ case 'match': {
26
+ const matchPath = this.config.matchPath;
27
+ const entry = this.config.selectMap[String(readPath(model, matchPath))];
28
+ return entry ? new BuilderOption(this.name, entry) : null;
29
+ }
30
+ case 'unless': {
31
+ const value = readPath(model, this.config.unlessPath);
32
+ return !this.config.disabledValues.includes(value)
33
+ ? this
34
+ : null;
35
+ }
36
+ }
37
+ }
38
+ dependencyKeys() {
39
+ const keys = new Set(this.gatePaths.map((path) => String(path[0])));
40
+ if (this.config?.type === 'match') {
41
+ const matchPath = this.config.matchPath;
42
+ keys.add(String(matchPath[0]));
43
+ }
44
+ else if (this.config?.type === 'unless') {
45
+ keys.add(String(this.config.unlessPath[0]));
46
+ }
47
+ return Array.from(keys);
48
+ }
49
+ }
@@ -0,0 +1,17 @@
1
+ import type { BuilderOptionValueSchema } from './option';
2
+ import * as v from 'valibot';
3
+ export type BuilderSelectTypeValues = readonly [string, ...ReadonlyArray<string>];
4
+ export type BuilderSelectTypeLabels<Values extends BuilderSelectTypeValues> = Partial<Record<Values[number], string>>;
5
+ export declare class BuilderSelectType<const Values extends BuilderSelectTypeValues = BuilderSelectTypeValues, const ValueSchema extends BuilderOptionValueSchema = BuilderOptionValueSchema> {
6
+ readonly value: v.InferOutput<ValueSchema>;
7
+ readonly options: Values;
8
+ readonly valueSchema: ValueSchema;
9
+ readonly defaultValue: v.InferOutput<ValueSchema>;
10
+ readonly isOptional: boolean;
11
+ readonly optionLabels: BuilderSelectTypeLabels<Values>;
12
+ constructor(values: Values, valueSchema: ValueSchema, defaultValue: v.InferOutput<ValueSchema>, optional?: boolean, optionLabels?: BuilderSelectTypeLabels<Values>);
13
+ default(newDefault: v.InferOutput<ValueSchema>): BuilderSelectType<Values, ValueSchema>;
14
+ optional(): BuilderSelectType<Values, v.NullableSchema<ValueSchema, undefined>>;
15
+ labels(optionLabels: BuilderSelectTypeLabels<Values>): BuilderSelectType<Values, ValueSchema>;
16
+ }
17
+ export declare function select<const Values extends BuilderSelectTypeValues>(values: Values): BuilderSelectType<Values, v.UnionSchema<v.LiteralSchema<Values[number], undefined>[], undefined>>;
@@ -0,0 +1,30 @@
1
+ import * as v from 'valibot';
2
+ export class BuilderSelectType {
3
+ options;
4
+ valueSchema;
5
+ defaultValue;
6
+ isOptional;
7
+ optionLabels;
8
+ constructor(values, valueSchema, defaultValue, optional = false, optionLabels = {}) {
9
+ this.options = values;
10
+ this.valueSchema = valueSchema;
11
+ this.defaultValue = defaultValue;
12
+ this.isOptional = optional;
13
+ this.optionLabels = optionLabels;
14
+ }
15
+ default(newDefault) {
16
+ return new BuilderSelectType(this.options, this.valueSchema, newDefault, this.isOptional, this.optionLabels);
17
+ }
18
+ optional() {
19
+ const { options, defaultValue } = this;
20
+ return new BuilderSelectType(options, v.nullable(this.valueSchema), defaultValue, true, this.optionLabels);
21
+ }
22
+ labels(optionLabels) {
23
+ return new BuilderSelectType(this.options, this.valueSchema, this.defaultValue, this.isOptional, optionLabels);
24
+ }
25
+ }
26
+ export function select(values) {
27
+ const [defaultValue] = values;
28
+ const valueSchema = v.union(values.map((value) => v.literal(value)));
29
+ return new BuilderSelectType(values, valueSchema, defaultValue, false);
30
+ }
@@ -0,0 +1,14 @@
1
+ import type { BuilderOptionValueSchema } from './option';
2
+ import * as v from 'valibot';
3
+ export declare class BuilderToggleType<const ValueSchema extends BuilderOptionValueSchema = BuilderOptionValueSchema> {
4
+ readonly value: v.InferOutput<ValueSchema>;
5
+ readonly valueSchema: ValueSchema;
6
+ readonly defaultValue: v.InferOutput<ValueSchema>;
7
+ readonly isOptional: boolean;
8
+ constructor(valueSchema: ValueSchema, defaultValue: v.InferOutput<ValueSchema>, optional?: boolean);
9
+ default(newDefault: v.InferOutput<ValueSchema>): BuilderToggleType<ValueSchema>;
10
+ optional(): BuilderToggleType<v.NullableSchema<ValueSchema, undefined>>;
11
+ }
12
+ export declare function toggleString(): BuilderToggleType<v.StringSchema<undefined>>;
13
+ export declare function toggleBoolean(): BuilderToggleType<v.BooleanSchema<undefined>>;
14
+ export declare function toggleNumber(): BuilderToggleType<v.NumberSchema<undefined>>;
@@ -0,0 +1,27 @@
1
+ import * as v from 'valibot';
2
+ export class BuilderToggleType {
3
+ valueSchema;
4
+ defaultValue;
5
+ isOptional;
6
+ constructor(valueSchema, defaultValue, optional) {
7
+ this.valueSchema = valueSchema;
8
+ this.defaultValue = defaultValue;
9
+ this.isOptional = optional || false;
10
+ }
11
+ default(newDefault) {
12
+ return new BuilderToggleType(this.valueSchema, newDefault, this.isOptional);
13
+ }
14
+ optional() {
15
+ const { valueSchema, defaultValue } = this;
16
+ return new BuilderToggleType(v.nullable(valueSchema), defaultValue, true);
17
+ }
18
+ }
19
+ export function toggleString() {
20
+ return new BuilderToggleType(v.string(), '');
21
+ }
22
+ export function toggleBoolean() {
23
+ return new BuilderToggleType(v.boolean(), false);
24
+ }
25
+ export function toggleNumber() {
26
+ return new BuilderToggleType(v.number(), 0);
27
+ }
@@ -0,0 +1,16 @@
1
+ export type { BuilderModelAsserted, BuilderUIModelAsserted } from './assert/assert';
2
+ export type { BuilderExpectations } from './assert/index';
3
+ export type { BuilderData, BuilderModel, BuilderModelMutable, BuilderModels, BuilderPrimitive, BuilderPrimitives, BuilderVariant, BuilderVariants } from './config';
4
+ export type { Builder, BuilderCollectionConfig, BuilderCollectionEntries, BuilderCollectionModelOf, BuilderCollectionNamesOf, BuilderCollectionOf, BuilderComponentEntries, BuilderComponentNamesOf, BuilderFactory, BuilderGeneric, BuilderModelOf, BuilderOptionEntries, BuilderOptionValues, BuilderPart, BuilderParts, BuilderSelectTypeLabels, BuilderSelectTypeValues, BuilderState, BuilderStateOf } from './core/index';
5
+ export type { BuilderModelPaths, BuilderResolvePath, BuilderValidPath } from './paths';
6
+ export type { BuilderPath, BuilderPaths } from './schemas/index';
7
+ export type { BuilderDataValidated, BuilderDescription, BuilderDescriptionItem, BuilderErrorComponentMissing, BuilderErrorComponentUnexpected, BuilderErrorsValidate, BuilderErrorValidate, BuilderErrorVariantInvalid, BuilderErrorVariantMissing, BuilderLayout, BuilderLayoutOption, BuilderLayoutOptions, BuilderLayoutPage, BuilderOrder, BuilderRenderLayoutOption, BuilderRenderLayoutOptions, BuilderRenderPage, BuilderRenderPages, BuilderRenderResult, BuilderValidateResult } from './resolve/index';
8
+ export type { BuilderUICollection, BuilderUIDescribe, BuilderUIItem, BuilderUIItems, BuilderUIPage } from './schemas/index';
9
+ export type { BuilderUI, BuilderUIFactory, BuilderUIPart, BuilderUIParts } from './ui';
10
+ export type { BuilderCollectionSerialised, BuilderCollectionWhenConfigSerialised, BuilderComponentSerialised, BuilderOptionSerialised, BuilderOptionWhenConfigSerialised, BuilderSelectTypeSerialised, BuilderSerialised, BuilderToggleTypeSerialised, BuilderUISerialised, BuilderValuesSerialised } from './serialise/index';
11
+ export { BuilderExpectation } from './assert/expectation.js';
12
+ export { assert, component, option } from './assert/index.js';
13
+ export { builder, BuilderCollection, BuilderComponent, BuilderOption, BuilderSelectType, BuilderToggleType, collection, enable, match, select, toggleBoolean, toggleNumber, toggleString, unless } from './core/index.js';
14
+ export { instance, models, order, ordinal, render, validate } from './resolve/index.js';
15
+ export { deserialise, serialise } from './serialise/index.js';
16
+ export { ui } from './ui.js';
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { BuilderExpectation } from './assert/expectation.js';
2
+ export { assert, component, option } from './assert/index.js';
3
+ export { builder, BuilderCollection, BuilderComponent, BuilderOption, BuilderSelectType, BuilderToggleType, collection, enable, match, select, toggleBoolean, toggleNumber, toggleString, unless } from './core/index.js';
4
+ export { instance, models, order, ordinal, render, validate } from './resolve/index.js';
5
+ export { deserialise, serialise } from './serialise/index.js';
6
+ export { ui } from './ui.js';
@@ -0,0 +1 @@
1
+ export declare function invariant<Input>(input: Input, message?: `${string}! ❌`): asserts input is Exclude<Input, null | undefined | '' | 0 | false>;
@@ -0,0 +1,6 @@
1
+ const DEFAULT_INVARIANT_MESSAGE = 'Unexpected falsy value! ❌';
2
+ export function invariant(input, message = DEFAULT_INVARIANT_MESSAGE) {
3
+ if (!input) {
4
+ throw new Error(message);
5
+ }
6
+ }
@@ -0,0 +1,14 @@
1
+ export type { BuilderPath, BuilderPaths } from './schemas/index';
2
+ import type { BuilderGeneric, BuilderModelOf } from './core/index';
3
+ import type { BuilderPath, BuilderPrimitive } from './schemas/index';
4
+ export type BuilderValidPath<Model, Depth extends ReadonlyArray<never> = []> = Depth['length'] extends 10 ? never : Model extends BuilderPrimitive | null ? never : Model extends ReadonlyArray<infer Item> ? [number] | [number, ...BuilderValidPath<Item, [...Depth, never]>] : {
5
+ [K in keyof Model & string]: [K] | (Model[K] extends BuilderPrimitive | null ? never : [K, ...BuilderValidPath<Model[K], [...Depth, never]>]);
6
+ }[keyof Model & string];
7
+ export type BuilderModelPaths<B extends BuilderGeneric> = ReadonlyArray<BuilderValidPath<BuilderModelOf<B>>>;
8
+ export type BuilderResolvePath<Model, Path extends BuilderPath> = Path extends readonly [
9
+ infer Head extends keyof Model & string
10
+ ] ? Model[Head] : Path extends readonly [
11
+ infer Head extends keyof Model & string,
12
+ ...infer Tail extends BuilderPath
13
+ ] ? Model[Head] extends ReadonlyArray<infer Item> ? Tail extends readonly [number, ...infer Rest extends BuilderPath] ? BuilderResolvePath<Item, Rest> : never : BuilderResolvePath<Model[Head], Tail> : never;
14
+ export declare function readPath(model: unknown, path: BuilderPath): unknown;
package/dist/paths.js ADDED
@@ -0,0 +1,8 @@
1
+ export function readPath(model, path) {
2
+ return path.reduce((current, segment) => {
3
+ if (current == null) {
4
+ return null;
5
+ }
6
+ return current[segment];
7
+ }, model);
8
+ }
@@ -0,0 +1,3 @@
1
+ export type Prettify<Input> = {
2
+ [Key in keyof Input]: Input[Key];
3
+ } & {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ export type { BuilderOrder } from './order';
2
+ export type { BuilderRenderLayoutOption, BuilderRenderLayoutOptions, BuilderRenderPage, BuilderRenderPages, BuilderRenderResult } from './render';
3
+ export type { BuilderDataValidated, BuilderErrorVariantInvalid, BuilderErrorComponentMissing, BuilderErrorVariantMissing, BuilderErrorComponentUnexpected, BuilderErrorValidate, BuilderErrorsValidate, BuilderValidateResult } from './validate';
4
+ export type { BuilderDescription, BuilderDescriptionItem, BuilderLayout, BuilderLayoutOption, BuilderLayoutOptions, BuilderLayoutPage } from '../schemas/index';
5
+ export { instance } from './instance.js';
6
+ export { models } from './models.js';
7
+ export { order } from './order.js';
8
+ export { ordinal, render } from './render.js';
9
+ export { validate } from './validate.js';
@@ -0,0 +1,5 @@
1
+ export { instance } from './instance.js';
2
+ export { models } from './models.js';
3
+ export { order } from './order.js';
4
+ export { ordinal, render } from './render.js';
5
+ export { validate } from './validate.js';
@@ -0,0 +1,3 @@
1
+ import type { BuilderGeneric, BuilderModelOf } from '../core/index';
2
+ import type { BuilderModelMutable } from '../config';
3
+ export declare function instance<const B extends BuilderGeneric>(builder: B, partial?: BuilderModelMutable): BuilderModelOf<B>;
@@ -0,0 +1,26 @@
1
+ import * as v from 'valibot';
2
+ import { resolveCollectionModels } from '../core/index.js';
3
+ export function instance(builder, partial = {}) {
4
+ const model = partial;
5
+ builder.options.forEach((entry) => {
6
+ const option = entry.resolve(model);
7
+ if (!option) {
8
+ return;
9
+ }
10
+ if (!v.is(option.values.valueSchema, model[option.name])) {
11
+ model[option.name] = option.values.defaultValue;
12
+ }
13
+ });
14
+ builder.collections.forEach((entry) => {
15
+ const collection = entry.resolve(model);
16
+ if (!collection) {
17
+ return;
18
+ }
19
+ const existing = model[collection.name];
20
+ const collectionModels = existing != null ? resolveCollectionModels(model, collection.name) : [];
21
+ model[collection.name] = Array.from({
22
+ length: Math.max(collectionModels.length, collection.min)
23
+ }).map((_, index) => instance(collection.builder, collectionModels[index] || {}));
24
+ });
25
+ return model;
26
+ }
@@ -0,0 +1,3 @@
1
+ import type { BuilderData } from '../config';
2
+ import type { BuilderGeneric } from '../core/index';
3
+ export declare function models(builder: BuilderGeneric): BuilderData;
@@ -0,0 +1,10 @@
1
+ export function models(builder) {
2
+ const collectionModels = builder.collections.flatMap((entry) => {
3
+ return [models(entry.builder)];
4
+ });
5
+ const wrapped = Object.fromEntries(builder.componentGraph.paths.map((path) => [path.name, path.models.map((model) => ({ model }))]));
6
+ return {
7
+ ...collectionModels.reduce((merged, component) => ({ ...merged, ...component }), {}),
8
+ ...wrapped
9
+ };
10
+ }
@@ -0,0 +1,18 @@
1
+ import type { BuilderModel, BuilderVariant } from '../config';
2
+ import type { BuilderCollection, BuilderCollectionEntries, BuilderComponentEntries, BuilderComponentNamesOf, BuilderGeneric, BuilderTupleOf } from '../core/index';
3
+ import type { BuilderDataValidated } from './validate';
4
+ export type BuilderOrder<B extends BuilderGeneric> = B extends {
5
+ readonly _components: infer Components extends BuilderComponentEntries;
6
+ readonly _collections: infer Collections extends BuilderCollectionEntries;
7
+ } ? Prettify<ComponentsOrder<Components> & CollectionsOrder<Collections>> : Record<string, unknown>;
8
+ export declare function order<const B extends BuilderGeneric>(builder: B, model: BuilderModel, componentModels: BuilderDataValidated): BuilderOrder<B>;
9
+ import type { Prettify } from '../prettify';
10
+ type ComponentsOrder<Components extends BuilderComponentEntries> = {
11
+ readonly [Name in BuilderComponentNamesOf<Components>]: BuilderVariant | null;
12
+ };
13
+ type CollectionsOrder<Collections extends BuilderCollectionEntries> = Collections extends readonly [
14
+ infer Head extends BuilderCollection,
15
+ ...infer Tail extends BuilderCollectionEntries
16
+ ] ? Record<Head['name'], CollectionOrderOf<Head>> & CollectionsOrder<Tail> : {};
17
+ type CollectionOrderOf<Input extends BuilderCollection> = Input extends BuilderCollection<any, infer CollectionRecipe extends BuilderGeneric, infer Min, infer Max> ? number extends Min ? ReadonlyArray<BuilderOrder<CollectionRecipe>> : number extends Max ? ReadonlyArray<BuilderOrder<CollectionRecipe>> : Min extends Max ? BuilderTupleOf<BuilderOrder<CollectionRecipe>, Min> : ReadonlyArray<BuilderOrder<CollectionRecipe>> : ReadonlyArray<Record<string, unknown>>;
18
+ export {};
@@ -0,0 +1,24 @@
1
+ import { resolveCollectionModels } from '../core/index.js';
2
+ export function order(builder, model, componentModels) {
3
+ const result = {};
4
+ const resolved = {};
5
+ builder.components.forEach((component) => {
6
+ const active = component.resolve(resolved);
7
+ if (!active) {
8
+ return;
9
+ }
10
+ resolved[active.name] = active;
11
+ const variants = componentModels[active.name] ?? [];
12
+ result[active.name] =
13
+ variants.find((variant) => Object.entries(variant.model).every(([key, value]) => model[key] === value)) ?? null;
14
+ });
15
+ builder.collections.forEach((entry) => {
16
+ const collection = entry.resolve(model);
17
+ if (!collection) {
18
+ return;
19
+ }
20
+ const itemModels = resolveCollectionModels(model, collection.name);
21
+ result[collection.name] = itemModels.map((itemModel) => order(collection.builder, itemModel, componentModels));
22
+ });
23
+ return result;
24
+ }
@@ -0,0 +1,21 @@
1
+ import type { BuilderGeneric, BuilderOption } from '../core/index';
2
+ import type { BuilderModel } from '../config';
3
+ import type { BuilderDescription, BuilderUIItems, BuilderPrimitive } from '../schemas/index';
4
+ import { BuilderUI } from '../ui.js';
5
+ export type BuilderRenderLayoutOption = {
6
+ readonly value: BuilderPrimitive | null;
7
+ update(model: BuilderModel, value: BuilderPrimitive | null): BuilderModel;
8
+ readonly option: BuilderOption;
9
+ };
10
+ export type BuilderRenderLayoutOptions = ReadonlyArray<BuilderRenderLayoutOption>;
11
+ export type BuilderRenderPage = {
12
+ readonly label: string | null;
13
+ readonly options: BuilderRenderLayoutOptions;
14
+ };
15
+ export type BuilderRenderPages = ReadonlyArray<BuilderRenderPage>;
16
+ export type BuilderRenderResult = {
17
+ readonly layout: BuilderRenderPages;
18
+ readonly description: BuilderDescription;
19
+ };
20
+ export declare function render(rootBuilder: BuilderGeneric, rootModel: BuilderModel, input: BuilderUI | BuilderUIItems): BuilderRenderResult;
21
+ export declare function ordinal(index: number): string;