@golemui/core 1.3.0 → 1.4.0-rc.0

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.
@@ -1,30 +1,8 @@
1
- import { State } from '../model';
2
- /**
3
- * Conditionally applies a reducer function based on a predicate
4
- *
5
- * This higher-order reducer creates a new reducer that only applies the given
6
- * reducer function when the predicate function returns true for the current state.
7
- * If the predicate returns false, the state is returned unchanged.
8
- *
9
- * @param predicate - A function that takes the current state and returns a boolean
10
- * indicating whether the reducer should be applied
11
- * @param reducerFn - The reducer function to apply when the predicate returns true
12
- *
13
- * @returns A new reducer function that conditionally applies the given reducer
14
- *
15
- * @example
16
- * ```typescript
17
- * // Only increment if count is less than 10
18
- * const conditionalIncrement = reduceIf(
19
- * (state: { count: number }) => state.count < 10,
20
- * (state) => ({ ...state, count: state.count + 1 })
21
- * );
22
- *
23
- * conditionalIncrement({ count: 5 }); // returns { count: 6 }
24
- * conditionalIncrement({ count: 10 }); // returns { count: 10 } (unchanged)
25
- * ```
26
- */
27
- export declare const reduceIf: (predicate: (state: State) => boolean, reducerFn: (state: State) => State) => (state: State) => State;
28
1
  export declare const hasWhen: (val: unknown) => val is {
29
2
  when: string;
30
3
  };
4
+ /**
5
+ * Compares arrays by their elements and plain objects by their properties,
6
+ * everything else is comppared by reference using `===`.
7
+ */
8
+ export declare function deepEqual(a: unknown, b: unknown): boolean;
@@ -1,25 +1,3 @@
1
1
  import { Observable } from 'rxjs';
2
- import { LayoutWidget } from '../form-widget';
3
- import { DotPath, Uid } from '../shared';
4
2
  import { State } from './model';
5
- export declare const dataByPath$: <T = any>(path: DotPath) => import('rxjs').UnaryFunction<Observable<State>, Observable<T>>;
6
- export declare const validationByPath$: (path: DotPath) => import('rxjs').UnaryFunction<Observable<State>, Observable<import('../shared').ValidationStatus>>;
7
- export declare const injectedValidationByPath$: (path: DotPath) => import('rxjs').UnaryFunction<Observable<State>, Observable<import('../shared').ValidationStatus>>;
8
- /**
9
- * Emits the current calculated widget for the given uid
10
- * Re triggers on widget changes OR store.lang changes
11
- */
12
- export declare const calculatedWidgetsByUid$: (uid: Uid) => (state$: Observable<State>) => Observable<import('../form-widget').NonFunctionWidget<string, any, any>>;
13
- export declare const calculatedLayoutChildrenByUid$: (uid: Uid) => import('rxjs').UnaryFunction<Observable<State>, Observable<(import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, /*elided*/ any> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]>>;
14
- export declare const selectWidgetFlags: import('rxjs').UnaryFunction<Observable<State>, Observable<Record<string, {
15
- hidden?: boolean;
16
- readonly?: boolean;
17
- disabled?: boolean;
18
- }>>>;
19
- export declare const widgetFlagsByUid$: (uid: Uid) => import('rxjs').UnaryFunction<Observable<State>, Observable<{
20
- hidden?: boolean;
21
- readonly?: boolean;
22
- disabled?: boolean;
23
- }>>;
24
- export declare const touchedControlsByPath$: (path: DotPath) => import('rxjs').UnaryFunction<Observable<State>, Observable<boolean>>;
25
3
  export declare const formHealth: (store: Observable<State>) => Observable<import('./model').FormHealth>;
@@ -0,0 +1,92 @@
1
+ import { Observable } from 'rxjs';
2
+ import { FormWidget, NonFunctionWidget } from '../form-widget';
3
+ import { Uid } from '../shared';
4
+ import { State } from './model';
5
+ /**
6
+ * One render-ready snapshot of everything a widget component needs from the store, so a binding
7
+ * can serve a widget from a single subscription (or a single snapshot read) instead of one
8
+ * subscription per store slice.
9
+ *
10
+ * Hidden widgets are reported as they are: `widget` is `undefined` and `hidden` is `true`. This
11
+ * differs from the calculated-widget lookup, which holds no entry for a hidden widget and
12
+ * therefore leaves subscribers holding the last visible value.
13
+ */
14
+ export type WidgetViewModel<T = unknown> = {
15
+ uid: Uid;
16
+ /**
17
+ * The fully calculated widget (`calculatedWidgets[uid].current`), `undefined` while the widget
18
+ * is hidden or absent from the current derive.
19
+ */
20
+ widget: NonFunctionWidget<string> | undefined;
21
+ /**
22
+ * A layout widget's visible children, with repeater row indexes already applied to each child's
23
+ * `uid` and `path`. Empty for non-layout widgets and while hidden. Bindings can hand these nodes
24
+ * straight to their widget renderer without applying the indexes themselves.
25
+ */
26
+ children: FormWidget<string>[];
27
+ /**
28
+ * For a repeater input, one fully indexed row layout node per row of its array value, ready to
29
+ * render. Empty for non-repeater widgets and while hidden. Row order matches the data array, so
30
+ * a row's position in this list is also its index in the value. The one exception is an errored
31
+ * derive, where a row the failed derive never resolved is left out until the form recovers.
32
+ */
33
+ rows: NonFunctionWidget<string>[];
34
+ /** The BCP 47 language tag of the current locale. */
35
+ lang: string;
36
+ /** The form data at the widget's path, `undefined` for widgets without a path. */
37
+ value: T | undefined;
38
+ /**
39
+ * Schema and injected validation messages merged into one list. Empty until the form has been
40
+ * touched, so nothing shows before the user interacts.
41
+ */
42
+ errors: string[];
43
+ /** Whether this control has been touched and may display its errors. */
44
+ touched: boolean;
45
+ /**
46
+ * True when the form has been touched and is currently invalid. This is what action widgets
47
+ * (submit buttons) render as their `invalid` state.
48
+ */
49
+ formInvalid: boolean;
50
+ /** The widget's `hidden` flag for the current derive. */
51
+ hidden: boolean;
52
+ };
53
+ /**
54
+ * Reads one widget's view model out of a state snapshot. Pure and uncached: every call builds
55
+ * fresh objects. Use {@link createWidgetViewModelReader} when reference stability across calls
56
+ * matters (change detection, `distinctUntilChanged`, React's `useSyncExternalStore`).
57
+ *
58
+ * @param state - A store state snapshot (`store.getState()`).
59
+ * @param uid - The widget's uid, including repeater row indexes when the widget lives inside a
60
+ * repeater row (e.g. `firstName[0]`).
61
+ * @returns The widget's view model.
62
+ * @example
63
+ * const vm = widgetViewModel<string>(store.getState(), 'firstName');
64
+ * vm.value; // the data at the widget's path
65
+ * vm.errors; // [] until the form is touched
66
+ */
67
+ export declare function widgetViewModel<T = unknown>(state: State, uid: Uid): WidgetViewModel<T>;
68
+ /**
69
+ * Creates a memoizing reader over {@link widgetViewModel}: for a given uid it returns the exact
70
+ * same object until one of that widget's state slices changes, and reuses the `children` / `rows`
71
+ * / `errors` arrays while their own inputs are unchanged. Create one reader per store and keep it
72
+ * for the store's lifetime.
73
+ *
74
+ * @returns A reader function over a state snapshot and a uid.
75
+ * @example
76
+ * const readViewModel = createWidgetViewModelReader();
77
+ * const a = readViewModel(store.getState(), 'firstName');
78
+ * // ... an unrelated widget changes ...
79
+ * const b = readViewModel(store.getState(), 'firstName');
80
+ * a === b; // true
81
+ */
82
+ export declare function createWidgetViewModelReader(): <T = unknown>(state: State, uid: Uid) => WidgetViewModel<T>;
83
+ /**
84
+ * RxJS operator form of {@link widgetViewModel} for subscribe-based bindings: maps the store's
85
+ * `state$` to the widget's view model and emits only when the view model actually changed.
86
+ *
87
+ * @param uid - The widget's uid, row indexes included when it lives inside a repeater row.
88
+ * @returns An operator from a state stream to a view model stream.
89
+ * @example
90
+ * store.state$.pipe(widgetViewModel$('firstName')).subscribe((vm) => { ... });
91
+ */
92
+ export declare const widgetViewModel$: <T = unknown>(uid: Uid) => (state$: Observable<State>) => Observable<WidgetViewModel<T>>;
@@ -1,5 +1,5 @@
1
1
  import { FormWidget } from '../form-widget';
2
- import { $Errors } from '../shared';
2
+ import { $Errors, DotPath } from '../shared';
3
3
  import { State } from '../store/model';
4
4
  /**
5
5
  * Flattens the hierarchical form structure into a single-level array of form widgets.
@@ -21,16 +21,29 @@ import { State } from '../store/model';
21
21
  */
22
22
  export declare function flattenForm(widgets: FormWidget[]): FormWidget[];
23
23
  /**
24
- * Calculates validation variables to be used in reactive expressions
25
- * e.g. `{ invalidAge: '!!$errors.age' }` or { disabled { when: '$formIsInvalid' } }
24
+ * The validation variables reactive expressions can read.
26
25
  */
27
- export declare function calculateValidationVariables(state: State): {
26
+ export type ValidationVariables = {
28
27
  $formIsInvalid: boolean;
29
28
  $errors: $Errors;
30
29
  };
30
+ /**
31
+ * Calculates validation variables to be used in reactive expressions
32
+ * e.g. `{ invalidAge: '!!$errors.age' }` or { disabled { when: '$formIsInvalid' } }
33
+ */
34
+ export declare function calculateValidationVariables(state: State): ValidationVariables;
35
+ /**
36
+ * The data path a widget owns: an input widget's `path`, or a function widget's `path` when it
37
+ * returns a control. A function widget is stored as the callable itself, so `isInputWidget` is
38
+ * false for it and its path is the one the decoder stamped on the function object.
39
+ *
40
+ * @param widget - A `resolvedSources` entry, or a `calculatedWidgets` `current` / `source`.
41
+ * @returns The path, or `undefined` for a widget that owns none.
42
+ */
43
+ export declare function inputPath(widget: FormWidget<string> | undefined): DotPath | undefined;
31
44
  /**
32
45
  * Returns a copy of the form data with values for currently-hidden input widgets removed.
33
- * Paths are derived from the flat form widget map so this works even though hidden widgets
34
- * are absent from calculatedWidgets.
46
+ * Paths come from `resolvedSources`, so hidden repeater row inputs are pruned too and hidden
47
+ * widgets absent from calculatedWidgets are still covered.
35
48
  */
36
49
  export declare function pruneHiddenData(state: State): Record<string, any>;
@@ -1,3 +1,4 @@
1
+ import { Evaluator } from 'subscript/justin';
1
2
  import { $Errors, ExpressionFunctions, ReactiveExpression } from '../shared';
2
3
  import { State } from '../store/model';
3
4
  /**
@@ -13,5 +14,14 @@ export type RepeaterItemExpressionScope = {
13
14
  export type ExpressionExtraScope = RepeaterItemExpressionScope & {
14
15
  $fn?: ExpressionFunctions;
15
16
  };
17
+ export declare const COMPILED_EXPRESSION_CACHE_LIMIT = 2000;
18
+ /**
19
+ * Returns the compiled evaluator for an expression, compiling on the first call.
20
+ *
21
+ * Row-rewritten `when` expressions are distinct per row, so the cache grows with the row
22
+ * count and is cleared when it reaches the limit. The next call recompiles. A failed parse
23
+ * is never cached, so an invalid expression throws the same error on every call.
24
+ */
25
+ export declare function compileExpression(expression: string): Evaluator;
16
26
  export declare function expressionIsTrue(expression: ReactiveExpression, $form: State['data'], $meta: State['meta'], $errors: $Errors, $formIsInvalid: boolean, extraScope?: ExpressionExtraScope): boolean;
17
27
  export declare function normalizeArrayIndexes(expression: string): string;
@@ -48,6 +48,25 @@ import { DotPath } from '../shared';
48
48
  * ```
49
49
  */
50
50
  export declare const get: <T = any>(obj: Record<string, any>, path: DotPath) => T;
51
+ /**
52
+ * Tells whether every segment of a dot-separated path is present in the object.
53
+ *
54
+ * Unlike `get`, a leaf that is present but holds `undefined` counts as existing, which is
55
+ * what distinguishes "the value was never written" from "the value was cleared".
56
+ *
57
+ * @param object - The object to look the path up in
58
+ * @param path - A dot-separated path (e.g. "user.profile.name" or "users.0.name").
59
+ * An empty path returns false.
60
+ * @returns True when every segment exists, false otherwise
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * pathExists({ user: { name: undefined } }, 'user.name'); // true
65
+ * pathExists({ user: {} }, 'user.name'); // false
66
+ * pathExists({ users: [{ name: 'Alice' }] }, 'users.1'); // false
67
+ * ```
68
+ */
69
+ export declare const pathExists: (object: Record<string, any>, path: DotPath) => boolean;
51
70
  /**
52
71
  * Sets the value at path of object by mutation.
53
72
  * If a portion of path doesn't exist, it's created.
@@ -119,10 +138,25 @@ export declare const get: <T = any>(obj: Record<string, any>, path: DotPath) =>
119
138
  * ```
120
139
  */
121
140
  export declare const set: (object: Record<string, any>, path: DotPath, value: any) => Record<string, any>;
141
+ /**
142
+ * Returns a copy of `object` with `value` set at `path`, copying only the containers along
143
+ * the path. Untouched siblings keep their references and `object` is never modified, so the
144
+ * result can be compared to the input by reference at any level. Missing containers are
145
+ * created like {@link set}: an array when the next key is an index, an object otherwise.
146
+ * @param object - The object to copy and write into.
147
+ * @param path - Dot-separated path, array indexes as numeric segments.
148
+ * @param value - The value to set at the path.
149
+ * @returns A new root object with the value set.
150
+ * @example
151
+ * const next = copyOnWriteSet({ a: { b: 1 }, c: { d: 2 } }, 'a.b', 3);
152
+ * next.a.b; // 3
153
+ * next.c; // the input's c, by reference
154
+ */
155
+ export declare const copyOnWriteSet: (object: Record<string, any>, path: DotPath, value: any) => Record<string, any>;
122
156
  /**
123
157
  * Removes the property at the given dot-path from object by mutation.
124
158
  * After deletion, any ancestor plain objects that become empty are also removed.
125
- * Ancestor arrays that become empty are left in place — upward pruning stops as
159
+ * Ancestor arrays that become empty are left in place, upward pruning stops as
126
160
  * soon as an array boundary is encountered.
127
161
  *
128
162
  * @param object - The object to modify
@@ -144,7 +178,7 @@ export declare const set: (object: Record<string, any>, path: DotPath, value: an
144
178
  * ```typescript
145
179
  * const obj = { a: { b: { c: 1 } } };
146
180
  * unset(obj, 'a.b.c');
147
- * // Result: {} — 'b' and 'a' are pruned because they became empty objects
181
+ * // Result: {} ('b' and 'a' are pruned because they became empty objects)
148
182
  * ```
149
183
  *
150
184
  * @example
@@ -152,25 +186,10 @@ export declare const set: (object: Record<string, any>, path: DotPath, value: an
152
186
  * ```typescript
153
187
  * const obj = { items: [{ name: 'Alice' }] };
154
188
  * unset(obj, 'items.0.name');
155
- * // Result: { items: [{}] } — the empty object is kept inside the array
189
+ * // Result: { items: [{}] } (the empty object is kept inside the array)
156
190
  * ```
157
191
  */
158
192
  export declare const unset: <T extends Record<string, any>>(object: T, path: DotPath) => T;
159
- /**
160
- * Deletes a key from an object and returns the same mutated object.
161
- *
162
- * @param object - The object to remove the key from.
163
- * @param key - The property name to delete.
164
- * @returns The same object, with the specified key removed.
165
- *
166
- * @example
167
- * ```ts
168
- * const obj = { a: 1, b: 2, c: 3 };
169
- * deleteKey(obj, "b");
170
- * console.log(obj); // { a: 1, c: 3 }
171
- * ```
172
- */
173
- export declare const deleteKey: (object: Record<string, any>, key: string) => Record<string, any>;
174
193
  /**
175
194
  * Deep-clones plain objects and arrays while preserving function references
176
195
  * (and other non-plain values) by reference. Functions are stateless widget
@@ -1,5 +1,45 @@
1
- import { FormWidget, NonFunctionWidget } from '../form-widget';
1
+ import { FormWidget, InputWidget, LayoutWidget, NonFunctionWidget } from '../form-widget';
2
2
  import { Uid } from '../shared';
3
+ import { RepeaterItemScope, State } from '../store/model';
4
+ /**
5
+ * A repeater input widget as the core reads it: an input with a layout template under `props.template`.
6
+ */
7
+ export type RepeaterTemplateWidget = InputWidget<string> & {
8
+ type: 'repeater';
9
+ props: {
10
+ template: LayoutWidget<string>;
11
+ };
12
+ };
13
+ export declare const isRepeaterWidget: (widget: FormWidget<string>) => widget is RepeaterTemplateWidget;
14
+ /** `"abc[0][1]"` -> `[0, 1]`, `"abc"` -> `[]`. */
15
+ export declare const extractRepeaterIndexes: (uid: string) => number[];
16
+ /**
17
+ * The two maps `expandSources` builds from the form and the data.
18
+ */
19
+ export type ExpandedSources = {
20
+ resolvedSources: Record<Uid, FormWidget<string>>;
21
+ repeaterItemScopes: Record<Uid, RepeaterItemScope>;
22
+ };
23
+ /**
24
+ * Walks the flat form and the current data and returns every widget that exists for that data.
25
+ *
26
+ * `resolvedSources` holds the `flatForm` widgets by reference plus, for every repeater row, one entry
27
+ * per template widget (the row layout node included) with the row indexes written into `uid` and `path`.
28
+ * Nested repeater containers are entries too and are recursed with their concrete path. Function widgets
29
+ * stay callable (see {@link makeRepeaterItemConfig}), `when` expressions are not rewritten here.
30
+ *
31
+ * `repeaterItemScopes` maps every row widget uid to the innermost item that owns it.
32
+ *
33
+ * @param flatForm - The flattened form definition keyed by uid.
34
+ * @param data - The current form data the repeater arrays are read from.
35
+ * @returns Both maps, rebuilt from scratch.
36
+ *
37
+ * @example
38
+ * const { resolvedSources, repeaterItemScopes } = expandSources(flatForm, { users: [{}, {}] });
39
+ * resolvedSources['name[1]'].path; // 'users.1.name'
40
+ * repeaterItemScopes['name[1]']; // { itemPath: 'users.1', index: 1 }
41
+ */
42
+ export declare function expandSources(flatForm: State['flatForm'], data: Record<string, any>): ExpandedSources;
3
43
  /**
4
44
  * Derives a concrete widget config for a specific repeater item by materializing the provided indexes into the
5
45
  * widget's `uid` (and `path` for input widgets).
@@ -46,7 +86,8 @@ export declare function transformRepeaterItemWhenExpression(expression: string,
46
86
  *
47
87
  * @param widget - A widget already materialized for a repeater item (see {@link makeRepeaterItemConfig}).
48
88
  * @param repeaterIndexes - Ordered list of indexes for each nesting level.
49
- * @returns A new widget config with item-concrete `when` expressions. The original is not mutated.
89
+ * @returns A new widget config with item-concrete `when` expressions, or the input widget by
90
+ * reference when no flag field has a `when` expression. The original is never mutated.
50
91
  *
51
92
  * @example
52
93
  * // repeaterIndexes = [1]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@golemui/core",
3
- "version": "1.3.0",
3
+ "version": "1.4.0-rc.0",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -1,3 +0,0 @@
1
- import { ADD_WIDGET } from '../actions';
2
- import { State } from '../model';
3
- export declare function addWidget(state: State, action: ADD_WIDGET): State;
@@ -1,10 +0,0 @@
1
- import { State } from '../model';
2
- /**
3
- * Walks every repeater's live array data and derives, per item, the same concrete widgets the renderer mounts for that item.
4
- * Produces two maps keyed by materialized uid, both rebuilt from scratch on every run:
5
- * - `repeaterItemScopes`: which item owns each widget (binds `$item` / `$index`).
6
- * - `materializedRepeaterWidgets`: the item-concrete widget configs, with uid and path baked, `when` expressions rewritten for the item's row, and function widgets resolved.
7
- *
8
- * `calculateWidgetFlags` and `calculateWidgetProps` consume these maps, so this stage must run before them in the pipeline.
9
- */
10
- export declare const materializeRepeaterItems: (state: State) => State;
@@ -1,3 +0,0 @@
1
- import { REMOVE_WIDGET } from '../actions';
2
- import { State } from '../model';
3
- export declare function removeWidget(state: State, action: REMOVE_WIDGET): State;
@@ -1,71 +0,0 @@
1
- /**
2
- * A function type that transforms a value of type A to type B
3
- */
4
- type Func<A, B> = (arg: A) => B;
5
- /**
6
- * Performs left-to-right function composition (pipeline).
7
- * The output of each function is passed as input to the next function.
8
- *
9
- * @typeParam A - The initial value type
10
- * @param value - The initial value to pipe through the functions
11
- * @param fns - Functions to apply in sequence
12
- * @returns The result after applying all functions
13
- *
14
- * @example
15
- * ```typescript
16
- * const addOne = (x: number) => x + 1;
17
- * const double = (x: number) => x * 2;
18
- * const toString = (x: number) => `Result: ${x}`;
19
- *
20
- * const result = pipe(5, addOne, double, toString); // 5 -> 6 -> 12 -> "Result: 12"
21
- * ```
22
- */
23
- declare function pipe<A>(value: A): A;
24
- /** @see {@link pipe} */
25
- declare function pipe<A, B>(value: A, fn1: Func<A, B>): B;
26
- /** @see {@link pipe} */
27
- declare function pipe<A, B, C>(value: A, fn1: Func<A, B>, fn2: Func<B, C>): C;
28
- /** @see {@link pipe} */
29
- declare function pipe<A, B, C, D>(value: A, fn1: Func<A, B>, fn2: Func<B, C>, fn3: Func<C, D>): D;
30
- /** @see {@link pipe} */
31
- declare function pipe<A, B, C, D, E>(value: A, fn1: Func<A, B>, fn2: Func<B, C>, fn3: Func<C, D>, fn4: Func<D, E>): E;
32
- /** @see {@link pipe} */
33
- declare function pipe<A, B, C, D, E, F>(value: A, fn1: Func<A, B>, fn2: Func<B, C>, fn3: Func<C, D>, fn4: Func<D, E>, fn5: Func<E, F>): F;
34
- /** @see {@link pipe} */
35
- declare function pipe<A, B, C, D, E, F, G>(value: A, fn1: Func<A, B>, fn2: Func<B, C>, fn3: Func<C, D>, fn4: Func<D, E>, fn5: Func<E, F>, fn6: Func<F, G>): G;
36
- /** @see {@link pipe} */
37
- declare function pipe<A, B, C, D, E, F, G, H>(value: A, fn1: Func<A, B>, fn2: Func<B, C>, fn3: Func<C, D>, fn4: Func<D, E>, fn5: Func<E, F>, fn6: Func<F, G>, fn7: Func<G, H>): H;
38
- /**
39
- * Performs right-to-left function composition.
40
- * The output of each function is passed as input to the previous function.
41
- *
42
- * @typeParam A - The input type of the composed function
43
- * @returns A new function that applies all the given functions from right to left
44
- *
45
- * @example
46
- * Basic composition
47
- * ```typescript
48
- * const addOne = (x: number) => x + 1;
49
- * const double = (x: number) => x * 2;
50
- * const toString = (x: number) => `Result: ${x}`;
51
- *
52
- * const transform = compose(toString, double, addOne); // Applies: addOne -> double -> toString
53
- * console.log(transform(5)); // "Result: 12"
54
- * ```
55
- */
56
- declare function compose<A>(fn1: Func<A, A>): Func<A, A>;
57
- /** @see {@link compose} */
58
- declare function compose<A, B>(fn1: Func<A, B>, fn2: Func<B, A>): Func<B, B>;
59
- /** @see {@link compose} */
60
- declare function compose<A, B, C>(fn1: Func<B, C>, fn2: Func<A, B>): Func<A, C>;
61
- /** @see {@link compose} */
62
- declare function compose<A, B, C, D>(fn1: Func<C, D>, fn2: Func<B, C>, fn3: Func<A, B>): Func<A, D>;
63
- /** @see {@link compose} */
64
- declare function compose<A, B, C, D, E>(fn1: Func<D, E>, fn2: Func<C, D>, fn3: Func<B, C>, fn4: Func<A, B>): Func<A, E>;
65
- /** @see {@link compose} */
66
- declare function compose<A, B, C, D, E, F>(fn1: Func<E, F>, fn2: Func<D, E>, fn3: Func<C, D>, fn4: Func<B, C>, fn5: Func<A, B>): Func<A, F>;
67
- /** @see {@link compose} */
68
- declare function compose<A, B, C, D, E, F, G>(fn1: Func<F, G>, fn2: Func<E, F>, fn3: Func<D, E>, fn4: Func<C, D>, fn5: Func<B, C>, fn6: Func<A, B>): Func<A, G>;
69
- /** @see {@link compose} */
70
- declare function compose<A, B, C, D, E, F, G, H>(fn1: Func<G, H>, fn2: Func<F, G>, fn3: Func<E, F>, fn4: Func<D, E>, fn5: Func<C, D>, fn6: Func<B, C>, fn7: Func<A, B>): Func<A, H>;
71
- export { compose, pipe };