@pithos/core 2.2.2 → 2.4.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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/autocompletion.d.ts +129 -1
- package/dist/eidos/abstract-factory/abstract-factory.d.ts +125 -0
- package/dist/eidos/abstract-factory/abstract-factory.d.ts.map +1 -0
- package/dist/eidos/abstract-factory/abstract-factory.js +128 -0
- package/dist/eidos/abstract-factory/abstract-factory.js.map +1 -0
- package/dist/eidos/adapter/adapter.d.ts +97 -0
- package/dist/eidos/adapter/adapter.d.ts.map +1 -0
- package/dist/eidos/adapter/adapter.js +90 -0
- package/dist/eidos/adapter/adapter.js.map +1 -0
- package/dist/eidos/bridge/bridge.d.ts +81 -0
- package/dist/eidos/bridge/bridge.d.ts.map +1 -0
- package/dist/eidos/bridge/bridge.js +75 -0
- package/dist/eidos/bridge/bridge.js.map +1 -0
- package/dist/eidos/builder/builder.d.ts +181 -0
- package/dist/eidos/builder/builder.d.ts.map +1 -0
- package/dist/eidos/builder/builder.js +139 -0
- package/dist/eidos/builder/builder.js.map +1 -0
- package/dist/eidos/chain/chain.d.ts +99 -0
- package/dist/eidos/chain/chain.d.ts.map +1 -0
- package/dist/eidos/chain/chain.js +111 -0
- package/dist/eidos/chain/chain.js.map +1 -0
- package/dist/eidos/command/command.d.ts +267 -0
- package/dist/eidos/command/command.d.ts.map +1 -0
- package/dist/eidos/command/command.js +298 -0
- package/dist/eidos/command/command.js.map +1 -0
- package/dist/eidos/composite/composite.d.ts +168 -0
- package/dist/eidos/composite/composite.d.ts.map +1 -0
- package/dist/eidos/composite/composite.js +157 -0
- package/dist/eidos/composite/composite.js.map +1 -0
- package/dist/eidos/decorator/decorator.d.ts +138 -0
- package/dist/eidos/decorator/decorator.d.ts.map +1 -0
- package/dist/eidos/decorator/decorator.js +143 -0
- package/dist/eidos/decorator/decorator.js.map +1 -0
- package/dist/eidos/facade/facade.d.ts +61 -0
- package/dist/eidos/facade/facade.d.ts.map +1 -0
- package/dist/eidos/facade/facade.js +63 -0
- package/dist/eidos/facade/facade.js.map +1 -0
- package/dist/eidos/factory-method/factory-method.d.ts +76 -0
- package/dist/eidos/factory-method/factory-method.d.ts.map +1 -0
- package/dist/eidos/factory-method/factory-method.js +60 -0
- package/dist/eidos/factory-method/factory-method.js.map +1 -0
- package/dist/eidos/flyweight/flyweight.d.ts +40 -0
- package/dist/eidos/flyweight/flyweight.d.ts.map +1 -0
- package/dist/eidos/flyweight/flyweight.js +41 -0
- package/dist/eidos/flyweight/flyweight.js.map +1 -0
- package/dist/eidos/interpreter/interpreter.d.ts +82 -0
- package/dist/eidos/interpreter/interpreter.d.ts.map +1 -0
- package/dist/eidos/interpreter/interpreter.js +84 -0
- package/dist/eidos/interpreter/interpreter.js.map +1 -0
- package/dist/eidos/iterator/iterator.d.ts +164 -0
- package/dist/eidos/iterator/iterator.d.ts.map +1 -0
- package/dist/eidos/iterator/iterator.js +258 -0
- package/dist/eidos/iterator/iterator.js.map +1 -0
- package/dist/eidos/mediator/mediator.d.ts +102 -0
- package/dist/eidos/mediator/mediator.d.ts.map +1 -0
- package/dist/eidos/mediator/mediator.js +112 -0
- package/dist/eidos/mediator/mediator.js.map +1 -0
- package/dist/eidos/memento/memento.d.ts +103 -0
- package/dist/eidos/memento/memento.d.ts.map +1 -0
- package/dist/eidos/memento/memento.js +114 -0
- package/dist/eidos/memento/memento.js.map +1 -0
- package/dist/eidos/observer/observer.d.ts +96 -0
- package/dist/eidos/observer/observer.d.ts.map +1 -0
- package/dist/eidos/observer/observer.js +117 -0
- package/dist/eidos/observer/observer.js.map +1 -0
- package/dist/eidos/prototype/prototype.d.ts +32 -0
- package/dist/eidos/prototype/prototype.d.ts.map +1 -0
- package/dist/eidos/prototype/prototype.js +33 -0
- package/dist/eidos/prototype/prototype.js.map +1 -0
- package/dist/eidos/proxy/proxy.d.ts +108 -0
- package/dist/eidos/proxy/proxy.d.ts.map +1 -0
- package/dist/eidos/proxy/proxy.js +121 -0
- package/dist/eidos/proxy/proxy.js.map +1 -0
- package/dist/eidos/singleton/singleton.d.ts +76 -0
- package/dist/eidos/singleton/singleton.d.ts.map +1 -0
- package/dist/eidos/singleton/singleton.js +77 -0
- package/dist/eidos/singleton/singleton.js.map +1 -0
- package/dist/eidos/state/state.d.ts +152 -0
- package/dist/eidos/state/state.d.ts.map +1 -0
- package/dist/eidos/state/state.js +85 -0
- package/dist/eidos/state/state.js.map +1 -0
- package/dist/eidos/strategy/strategy.d.ts +148 -0
- package/dist/eidos/strategy/strategy.d.ts.map +1 -0
- package/dist/eidos/strategy/strategy.js +167 -0
- package/dist/eidos/strategy/strategy.js.map +1 -0
- package/dist/eidos/template/template.d.ts +95 -0
- package/dist/eidos/template/template.d.ts.map +1 -0
- package/dist/eidos/template/template.js +110 -0
- package/dist/eidos/template/template.js.map +1 -0
- package/dist/eidos/visitor/visitor.d.ts +78 -0
- package/dist/eidos/visitor/visitor.d.ts.map +1 -0
- package/dist/eidos/visitor/visitor.js +80 -0
- package/dist/eidos/visitor/visitor.js.map +1 -0
- package/dist/zygos/result/index.d.ts +19 -0
- package/dist/zygos/result/index.d.ts.map +1 -0
- package/dist/zygos/result/index.js +29 -0
- package/dist/zygos/result/index.js.map +1 -0
- package/package.json +28 -3
package/dist/autocompletion.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* ❌ const distance = math.geometry.distance; // from autocompletion
|
|
11
11
|
* ✅ import { distance } from 'pithos/math/geometry';
|
|
12
12
|
*
|
|
13
|
-
* Generated on: 2026-03-
|
|
13
|
+
* Generated on: 2026-03-29T23:24:53.486Z
|
|
14
14
|
* */
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -568,6 +568,111 @@ declare const _autocompletion: {
|
|
|
568
568
|
ensurePromise: typeof import('./bridges/ensurePromise.js')['ensurePromise'];
|
|
569
569
|
};
|
|
570
570
|
};
|
|
571
|
+
eidos: {
|
|
572
|
+
abstract_factory: {
|
|
573
|
+
createAbstractFactory: typeof import('./eidos/abstract-factory/abstract-factory.js')['createAbstractFactory'];
|
|
574
|
+
};
|
|
575
|
+
adapter: {
|
|
576
|
+
adapt: typeof import('./eidos/adapter/adapter.js')['adapt'];
|
|
577
|
+
createAdapter: typeof import('./eidos/adapter/adapter.js')['createAdapter'];
|
|
578
|
+
};
|
|
579
|
+
bridge: {
|
|
580
|
+
composeBridges: typeof import('./eidos/bridge/bridge.js')['composeBridges'];
|
|
581
|
+
createBridge: typeof import('./eidos/bridge/bridge.js')['createBridge'];
|
|
582
|
+
};
|
|
583
|
+
builder: {
|
|
584
|
+
createBuilder: typeof import('./eidos/builder/builder.js')['createBuilder'];
|
|
585
|
+
createValidatedBuilder: typeof import('./eidos/builder/builder.js')['createValidatedBuilder'];
|
|
586
|
+
};
|
|
587
|
+
chain: {
|
|
588
|
+
createChain: typeof import('./eidos/chain/chain.js')['createChain'];
|
|
589
|
+
safeChain: typeof import('./eidos/chain/chain.js')['safeChain'];
|
|
590
|
+
};
|
|
591
|
+
command: {
|
|
592
|
+
createCommandStack: typeof import('./eidos/command/command.js')['createCommandStack'];
|
|
593
|
+
createReactiveCommandStack: typeof import('./eidos/command/command.js')['createReactiveCommandStack'];
|
|
594
|
+
safeExecute: typeof import('./eidos/command/command.js')['safeExecute'];
|
|
595
|
+
undoable: typeof import('./eidos/command/command.js')['undoable'];
|
|
596
|
+
undoableState: typeof import('./eidos/command/command.js')['undoableState'];
|
|
597
|
+
};
|
|
598
|
+
composite: {
|
|
599
|
+
branch: typeof import('./eidos/composite/composite.js')['branch'];
|
|
600
|
+
find: typeof import('./eidos/composite/composite.js')['find'];
|
|
601
|
+
flatten: typeof import('./eidos/composite/composite.js')['flatten'];
|
|
602
|
+
fold: typeof import('./eidos/composite/composite.js')['fold'];
|
|
603
|
+
leaf: typeof import('./eidos/composite/composite.js')['leaf'];
|
|
604
|
+
map: typeof import('./eidos/composite/composite.js')['map'];
|
|
605
|
+
};
|
|
606
|
+
decorator: {
|
|
607
|
+
after: typeof import('./eidos/decorator/decorator.js')['after'];
|
|
608
|
+
around: typeof import('./eidos/decorator/decorator.js')['around'];
|
|
609
|
+
before: typeof import('./eidos/decorator/decorator.js')['before'];
|
|
610
|
+
decorate: typeof import('./eidos/decorator/decorator.js')['decorate'];
|
|
611
|
+
};
|
|
612
|
+
facade: {
|
|
613
|
+
createFacade: typeof import('./eidos/facade/facade.js')['createFacade'];
|
|
614
|
+
};
|
|
615
|
+
factory_method: {
|
|
616
|
+
createFactoryMethod: typeof import('./eidos/factory-method/factory-method.js')['createFactoryMethod'];
|
|
617
|
+
};
|
|
618
|
+
flyweight: {
|
|
619
|
+
memoize: typeof import('./eidos/flyweight/flyweight.js')['memoize'];
|
|
620
|
+
};
|
|
621
|
+
interpreter: {
|
|
622
|
+
interpret: typeof import('./eidos/interpreter/interpreter.js')['interpret'];
|
|
623
|
+
};
|
|
624
|
+
iterator: {
|
|
625
|
+
createIterable: typeof import('./eidos/iterator/iterator.js')['createIterable'];
|
|
626
|
+
filter: typeof import('./eidos/iterator/iterator.js')['filter'];
|
|
627
|
+
iterate: typeof import('./eidos/iterator/iterator.js')['iterate'];
|
|
628
|
+
lazyRange: typeof import('./eidos/iterator/iterator.js')['lazyRange'];
|
|
629
|
+
map: typeof import('./eidos/iterator/iterator.js')['map'];
|
|
630
|
+
reduce: typeof import('./eidos/iterator/iterator.js')['reduce'];
|
|
631
|
+
take: typeof import('./eidos/iterator/iterator.js')['take'];
|
|
632
|
+
toArray: typeof import('./eidos/iterator/iterator.js')['toArray'];
|
|
633
|
+
};
|
|
634
|
+
mediator: {
|
|
635
|
+
createMediator: typeof import('./eidos/mediator/mediator.js')['createMediator'];
|
|
636
|
+
};
|
|
637
|
+
memento: {
|
|
638
|
+
createHistory: typeof import('./eidos/memento/memento.js')['createHistory'];
|
|
639
|
+
};
|
|
640
|
+
observer: {
|
|
641
|
+
createObservable: typeof import('./eidos/observer/observer.js')['createObservable'];
|
|
642
|
+
};
|
|
643
|
+
prototype: {
|
|
644
|
+
deepClone: typeof import('./eidos/prototype/prototype.js')['deepClone'];
|
|
645
|
+
deepCloneFull: typeof import('./eidos/prototype/prototype.js')['deepCloneFull'];
|
|
646
|
+
};
|
|
647
|
+
proxy: {
|
|
648
|
+
debounce: typeof import('./eidos/proxy/proxy.js')['debounce'];
|
|
649
|
+
guarded: typeof import('./eidos/proxy/proxy.js')['guarded'];
|
|
650
|
+
lazy: typeof import('./eidos/proxy/proxy.js')['lazy'];
|
|
651
|
+
memoize: typeof import('./eidos/proxy/proxy.js')['memoize'];
|
|
652
|
+
once: typeof import('./eidos/proxy/proxy.js')['once'];
|
|
653
|
+
throttle: typeof import('./eidos/proxy/proxy.js')['throttle'];
|
|
654
|
+
};
|
|
655
|
+
singleton: {
|
|
656
|
+
once: typeof import('./eidos/singleton/singleton.js')['once'];
|
|
657
|
+
singleton: typeof import('./eidos/singleton/singleton.js')['singleton'];
|
|
658
|
+
};
|
|
659
|
+
state: {
|
|
660
|
+
createMachine: typeof import('./eidos/state/state.js')['createMachine'];
|
|
661
|
+
};
|
|
662
|
+
strategy: {
|
|
663
|
+
createStrategies: typeof import('./eidos/strategy/strategy.js')['createStrategies'];
|
|
664
|
+
safeStrategy: typeof import('./eidos/strategy/strategy.js')['safeStrategy'];
|
|
665
|
+
withFallback: typeof import('./eidos/strategy/strategy.js')['withFallback'];
|
|
666
|
+
withValidation: typeof import('./eidos/strategy/strategy.js')['withValidation'];
|
|
667
|
+
};
|
|
668
|
+
template: {
|
|
669
|
+
template: typeof import('./eidos/template/template.js')['template'];
|
|
670
|
+
templateWithDefaults: typeof import('./eidos/template/template.js')['templateWithDefaults'];
|
|
671
|
+
};
|
|
672
|
+
visitor: {
|
|
673
|
+
visit: typeof import('./eidos/visitor/visitor.js')['visit'];
|
|
674
|
+
};
|
|
675
|
+
};
|
|
571
676
|
kanon: {
|
|
572
677
|
index: {
|
|
573
678
|
any: typeof import('./kanon/index.js')['any'];
|
|
@@ -1559,6 +1664,20 @@ declare const _autocompletion: {
|
|
|
1559
1664
|
map: typeof import('./zygos/task.js')['map'];
|
|
1560
1665
|
of: typeof import('./zygos/task.js')['of'];
|
|
1561
1666
|
};
|
|
1667
|
+
index: {
|
|
1668
|
+
err: typeof import('./zygos/result/index.js')['err'];
|
|
1669
|
+
Err: typeof import('./zygos/result/index.js')['Err'];
|
|
1670
|
+
errAsync: typeof import('./zygos/result/index.js')['errAsync'];
|
|
1671
|
+
fromEither: typeof import('./zygos/result/index.js')['fromEither'];
|
|
1672
|
+
fromOption: typeof import('./zygos/result/index.js')['fromOption'];
|
|
1673
|
+
ok: typeof import('./zygos/result/index.js')['ok'];
|
|
1674
|
+
Ok: typeof import('./zygos/result/index.js')['Ok'];
|
|
1675
|
+
okAsync: typeof import('./zygos/result/index.js')['okAsync'];
|
|
1676
|
+
ResultAsync: typeof import('./zygos/result/index.js')['ResultAsync'];
|
|
1677
|
+
safeAsyncTry: typeof import('./zygos/result/index.js')['safeAsyncTry'];
|
|
1678
|
+
safeTry: typeof import('./zygos/result/index.js')['safeTry'];
|
|
1679
|
+
toEither: typeof import('./zygos/result/index.js')['toEither'];
|
|
1680
|
+
};
|
|
1562
1681
|
result: {
|
|
1563
1682
|
err: typeof import('./zygos/result/result.js')['err'];
|
|
1564
1683
|
Err: typeof import('./zygos/result/result.js')['Err'];
|
|
@@ -1611,6 +1730,15 @@ export { arkhe };
|
|
|
1611
1730
|
declare const bridges: typeof _autocompletion.bridges;
|
|
1612
1731
|
export { bridges };
|
|
1613
1732
|
|
|
1733
|
+
/**
|
|
1734
|
+
* @deprecated ⚠️ For autocompletion only.
|
|
1735
|
+
* Use direct imports from 'eidos/...' to preserve tree-shaking.
|
|
1736
|
+
* @example
|
|
1737
|
+
* import { createAbstractFactory } from 'pithos/eidos/abstract-factory/abstract-factory';
|
|
1738
|
+
*/
|
|
1739
|
+
declare const eidos: typeof _autocompletion.eidos;
|
|
1740
|
+
export { eidos };
|
|
1741
|
+
|
|
1614
1742
|
/**
|
|
1615
1743
|
* @deprecated ⚠️ For autocompletion only.
|
|
1616
1744
|
* Use direct imports from 'kanon/...' to preserve tree-shaking.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Functional Abstract Factory Pattern.
|
|
3
|
+
*
|
|
4
|
+
* In OOP, the Abstract Factory pattern requires an AbstractFactory interface,
|
|
5
|
+
* concrete factory classes, abstract product interfaces, and concrete product
|
|
6
|
+
* classes — a deep hierarchy just to produce families of related objects.
|
|
7
|
+
* In functional TypeScript, an abstract factory is a function that returns
|
|
8
|
+
* a record of creator functions. Swapping families is just swapping the factory.
|
|
9
|
+
*
|
|
10
|
+
* The core value of the pattern is intra-family consistency: products created
|
|
11
|
+
* by the same family are guaranteed to be compatible and can collaborate.
|
|
12
|
+
* A single `create("variant")` call returns a coherent record where every
|
|
13
|
+
* creator shares the same family context.
|
|
14
|
+
*
|
|
15
|
+
* @module eidos/abstract-factory
|
|
16
|
+
* @since 2.4.0
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { createAbstractFactory } from "@pithos/core/eidos/abstract-factory/abstract-factory";
|
|
21
|
+
*
|
|
22
|
+
* // Products collaborate: renderForm uses both button and input from the
|
|
23
|
+
* // same family, guaranteeing visual consistency.
|
|
24
|
+
* type UIKit = {
|
|
25
|
+
* button: (label: string) => string;
|
|
26
|
+
* input: (placeholder: string) => string;
|
|
27
|
+
* renderForm: (action: string) => string;
|
|
28
|
+
* };
|
|
29
|
+
*
|
|
30
|
+
* const factory = createAbstractFactory<"light" | "dark", UIKit>({
|
|
31
|
+
* light: () => {
|
|
32
|
+
* const button = (label: string) => `<button class="light">${label}</button>`;
|
|
33
|
+
* const input = (ph: string) => `<input class="light" placeholder="${ph}" />`;
|
|
34
|
+
* return {
|
|
35
|
+
* button,
|
|
36
|
+
* input,
|
|
37
|
+
* renderForm: (action) => `${input(action)}${button("Submit")}`,
|
|
38
|
+
* };
|
|
39
|
+
* },
|
|
40
|
+
* dark: () => {
|
|
41
|
+
* const button = (label: string) => `<button class="dark">${label}</button>`;
|
|
42
|
+
* const input = (ph: string) => `<input class="dark" placeholder="${ph}" />`;
|
|
43
|
+
* return {
|
|
44
|
+
* button,
|
|
45
|
+
* input,
|
|
46
|
+
* renderForm: (action) => `${input(action)}${button("Submit")}`,
|
|
47
|
+
* };
|
|
48
|
+
* },
|
|
49
|
+
* });
|
|
50
|
+
*
|
|
51
|
+
* const ui = factory.create("dark");
|
|
52
|
+
* ui.renderForm("search");
|
|
53
|
+
* // `<input class="dark" ...><button class="dark">Submit</button>`
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
import type { Option } from "../../zygos/option.js";
|
|
57
|
+
/**
|
|
58
|
+
* A Factory is a zero-arg function that produces a product record.
|
|
59
|
+
* Each key in the record is a creator function for one product of the family.
|
|
60
|
+
*
|
|
61
|
+
* @template Products - The record of creator functions
|
|
62
|
+
* @since 2.4.0
|
|
63
|
+
*/
|
|
64
|
+
export type Factory<Products extends Record<string, (...args: never[]) => unknown>> = () => Products;
|
|
65
|
+
/**
|
|
66
|
+
* Creates an abstract factory from a record of named family factories.
|
|
67
|
+
*
|
|
68
|
+
* Each key is a family name, each value is a factory function that produces
|
|
69
|
+
* the product record for that family. All families must produce the same
|
|
70
|
+
* product shape (same keys, same signatures).
|
|
71
|
+
*
|
|
72
|
+
* The real power is intra-family collaboration: since `create` returns a
|
|
73
|
+
* coherent record, products from the same family can reference each other
|
|
74
|
+
* via closure, guaranteeing compatibility without type gymnastics.
|
|
75
|
+
*
|
|
76
|
+
* @template K - Union of family keys
|
|
77
|
+
* @template Products - The record of creator functions each family produces
|
|
78
|
+
* @param families - Record mapping family keys to factory functions
|
|
79
|
+
* @returns An abstract factory with `create`, `get`, and `keys`
|
|
80
|
+
* @since 2.4.0
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* // Products that collaborate: encoder uses the separator from its family
|
|
85
|
+
* type Codec = {
|
|
86
|
+
* encode: (parts: string[]) => string;
|
|
87
|
+
* decode: (raw: string) => string[];
|
|
88
|
+
* };
|
|
89
|
+
*
|
|
90
|
+
* const codecs = createAbstractFactory<"csv" | "tsv", Codec>({
|
|
91
|
+
* csv: () => {
|
|
92
|
+
* const sep = ",";
|
|
93
|
+
* return {
|
|
94
|
+
* encode: (parts) => parts.join(sep),
|
|
95
|
+
* decode: (raw) => raw.split(sep),
|
|
96
|
+
* };
|
|
97
|
+
* },
|
|
98
|
+
* tsv: () => {
|
|
99
|
+
* const sep = "\t";
|
|
100
|
+
* return {
|
|
101
|
+
* encode: (parts) => parts.join(sep),
|
|
102
|
+
* decode: (raw) => raw.split(sep),
|
|
103
|
+
* };
|
|
104
|
+
* },
|
|
105
|
+
* });
|
|
106
|
+
*
|
|
107
|
+
* const csv = codecs.create("csv");
|
|
108
|
+
* csv.decode(csv.encode(["a", "b"])); // ["a", "b"] — round-trip guaranteed
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export declare function createAbstractFactory<K extends string, Products extends Record<string, (...args: never[]) => unknown>>(families: Record<K, Factory<Products>>): {
|
|
112
|
+
/**
|
|
113
|
+
* Create a product family by key. The factory is called each time,
|
|
114
|
+
* producing a fresh product record.
|
|
115
|
+
*/
|
|
116
|
+
create: (key: K) => Products;
|
|
117
|
+
/**
|
|
118
|
+
* Safe lookup for dynamic/runtime keys.
|
|
119
|
+
* Returns `Some(factory)` if the key exists, `None` otherwise.
|
|
120
|
+
*/
|
|
121
|
+
get: (key: string) => Option<Factory<Products>>;
|
|
122
|
+
/** Returns all registered family keys. */
|
|
123
|
+
keys: () => K[];
|
|
124
|
+
};
|
|
125
|
+
//# sourceMappingURL=abstract-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abstract-factory.d.ts","sourceRoot":"","sources":["../../../src/eidos/abstract-factory/abstract-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,MAAM,OAAO,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC,IAChF,MAAM,QAAQ,CAAC;AAEjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAgB,qBAAqB,CACnC,CAAC,SAAS,MAAM,EAChB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC,EAC9D,QAAQ,EAAE,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEpC;;;OAGG;kBACW,CAAC,KAAG,QAAQ;IAE1B;;;OAGG;eACQ,MAAM,KAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAQ7C,0CAA0C;gBAChC,CAAC,EAAE;EAKhB"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Functional Abstract Factory Pattern.
|
|
3
|
+
*
|
|
4
|
+
* In OOP, the Abstract Factory pattern requires an AbstractFactory interface,
|
|
5
|
+
* concrete factory classes, abstract product interfaces, and concrete product
|
|
6
|
+
* classes — a deep hierarchy just to produce families of related objects.
|
|
7
|
+
* In functional TypeScript, an abstract factory is a function that returns
|
|
8
|
+
* a record of creator functions. Swapping families is just swapping the factory.
|
|
9
|
+
*
|
|
10
|
+
* The core value of the pattern is intra-family consistency: products created
|
|
11
|
+
* by the same family are guaranteed to be compatible and can collaborate.
|
|
12
|
+
* A single `create("variant")` call returns a coherent record where every
|
|
13
|
+
* creator shares the same family context.
|
|
14
|
+
*
|
|
15
|
+
* @module eidos/abstract-factory
|
|
16
|
+
* @since 2.4.0
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { createAbstractFactory } from "@pithos/core/eidos/abstract-factory/abstract-factory";
|
|
21
|
+
*
|
|
22
|
+
* // Products collaborate: renderForm uses both button and input from the
|
|
23
|
+
* // same family, guaranteeing visual consistency.
|
|
24
|
+
* type UIKit = {
|
|
25
|
+
* button: (label: string) => string;
|
|
26
|
+
* input: (placeholder: string) => string;
|
|
27
|
+
* renderForm: (action: string) => string;
|
|
28
|
+
* };
|
|
29
|
+
*
|
|
30
|
+
* const factory = createAbstractFactory<"light" | "dark", UIKit>({
|
|
31
|
+
* light: () => {
|
|
32
|
+
* const button = (label: string) => `<button class="light">${label}</button>`;
|
|
33
|
+
* const input = (ph: string) => `<input class="light" placeholder="${ph}" />`;
|
|
34
|
+
* return {
|
|
35
|
+
* button,
|
|
36
|
+
* input,
|
|
37
|
+
* renderForm: (action) => `${input(action)}${button("Submit")}`,
|
|
38
|
+
* };
|
|
39
|
+
* },
|
|
40
|
+
* dark: () => {
|
|
41
|
+
* const button = (label: string) => `<button class="dark">${label}</button>`;
|
|
42
|
+
* const input = (ph: string) => `<input class="dark" placeholder="${ph}" />`;
|
|
43
|
+
* return {
|
|
44
|
+
* button,
|
|
45
|
+
* input,
|
|
46
|
+
* renderForm: (action) => `${input(action)}${button("Submit")}`,
|
|
47
|
+
* };
|
|
48
|
+
* },
|
|
49
|
+
* });
|
|
50
|
+
*
|
|
51
|
+
* const ui = factory.create("dark");
|
|
52
|
+
* ui.renderForm("search");
|
|
53
|
+
* // `<input class="dark" ...><button class="dark">Submit</button>`
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
import { some, none } from "../../zygos/option.js";
|
|
57
|
+
/**
|
|
58
|
+
* Creates an abstract factory from a record of named family factories.
|
|
59
|
+
*
|
|
60
|
+
* Each key is a family name, each value is a factory function that produces
|
|
61
|
+
* the product record for that family. All families must produce the same
|
|
62
|
+
* product shape (same keys, same signatures).
|
|
63
|
+
*
|
|
64
|
+
* The real power is intra-family collaboration: since `create` returns a
|
|
65
|
+
* coherent record, products from the same family can reference each other
|
|
66
|
+
* via closure, guaranteeing compatibility without type gymnastics.
|
|
67
|
+
*
|
|
68
|
+
* @template K - Union of family keys
|
|
69
|
+
* @template Products - The record of creator functions each family produces
|
|
70
|
+
* @param families - Record mapping family keys to factory functions
|
|
71
|
+
* @returns An abstract factory with `create`, `get`, and `keys`
|
|
72
|
+
* @since 2.4.0
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* // Products that collaborate: encoder uses the separator from its family
|
|
77
|
+
* type Codec = {
|
|
78
|
+
* encode: (parts: string[]) => string;
|
|
79
|
+
* decode: (raw: string) => string[];
|
|
80
|
+
* };
|
|
81
|
+
*
|
|
82
|
+
* const codecs = createAbstractFactory<"csv" | "tsv", Codec>({
|
|
83
|
+
* csv: () => {
|
|
84
|
+
* const sep = ",";
|
|
85
|
+
* return {
|
|
86
|
+
* encode: (parts) => parts.join(sep),
|
|
87
|
+
* decode: (raw) => raw.split(sep),
|
|
88
|
+
* };
|
|
89
|
+
* },
|
|
90
|
+
* tsv: () => {
|
|
91
|
+
* const sep = "\t";
|
|
92
|
+
* return {
|
|
93
|
+
* encode: (parts) => parts.join(sep),
|
|
94
|
+
* decode: (raw) => raw.split(sep),
|
|
95
|
+
* };
|
|
96
|
+
* },
|
|
97
|
+
* });
|
|
98
|
+
*
|
|
99
|
+
* const csv = codecs.create("csv");
|
|
100
|
+
* csv.decode(csv.encode(["a", "b"])); // ["a", "b"] — round-trip guaranteed
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export function createAbstractFactory(families) {
|
|
104
|
+
return {
|
|
105
|
+
/**
|
|
106
|
+
* Create a product family by key. The factory is called each time,
|
|
107
|
+
* producing a fresh product record.
|
|
108
|
+
*/
|
|
109
|
+
create: (key) => families[key](),
|
|
110
|
+
/**
|
|
111
|
+
* Safe lookup for dynamic/runtime keys.
|
|
112
|
+
* Returns `Some(factory)` if the key exists, `None` otherwise.
|
|
113
|
+
*/
|
|
114
|
+
get: (key) => {
|
|
115
|
+
if (key in families) {
|
|
116
|
+
// INTENTIONAL: key validated by `in` check, TS can't narrow string to K
|
|
117
|
+
return some(families[key]);
|
|
118
|
+
}
|
|
119
|
+
return none;
|
|
120
|
+
},
|
|
121
|
+
/** Returns all registered family keys. */
|
|
122
|
+
keys: () => {
|
|
123
|
+
// INTENTIONAL: Object.keys returns string[], but we know they're K
|
|
124
|
+
return Object.keys(families);
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=abstract-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abstract-factory.js","sourceRoot":"","sources":["../../../src/eidos/abstract-factory/abstract-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAEH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAa3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,MAAM,UAAU,qBAAqB,CAGnC,QAAsC;IACtC,OAAO;QACL;;;WAGG;QACH,MAAM,EAAE,CAAC,GAAM,EAAY,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;QAE7C;;;WAGG;QACH,GAAG,EAAE,CAAC,GAAW,EAA6B,EAAE;YAC9C,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;gBACpB,wEAAwE;gBACxE,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAQ,CAAC,CAAC,CAAC;YAClC,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,0CAA0C;QAC1C,IAAI,EAAE,GAAQ,EAAE;YACd,mEAAmE;YACnE,OAAO,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAQ,CAAC;QACtC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Functional Adapter Pattern.
|
|
3
|
+
*
|
|
4
|
+
* In OOP, the Adapter pattern requires a Target class, an Adaptee class with
|
|
5
|
+
* an incompatible interface, and an Adapter class that extends/wraps both.
|
|
6
|
+
* In functional TypeScript, an adapter is a pair of mapping functions
|
|
7
|
+
* that transform one function signature into another.
|
|
8
|
+
*
|
|
9
|
+
* @module eidos/adapter
|
|
10
|
+
* @since 2.4.0
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { adapt, createAdapter } from "@pithos/core/eidos/adapter/adapter";
|
|
15
|
+
*
|
|
16
|
+
* // Legacy API returns XML string
|
|
17
|
+
* const legacyFetch = (id: number) => `<user><name>Alice</name></user>`;
|
|
18
|
+
*
|
|
19
|
+
* // Adapt to new API shape: string id in, object out
|
|
20
|
+
* const fetchUser = adapt(
|
|
21
|
+
* legacyFetch,
|
|
22
|
+
* (id: string) => parseInt(id), // map input
|
|
23
|
+
* (xml) => ({ name: "Alice", xml }), // map output
|
|
24
|
+
* );
|
|
25
|
+
*
|
|
26
|
+
* fetchUser("42"); // { name: "Alice", xml: "<user>..." }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* An Adapter transforms a function with one signature into a function
|
|
31
|
+
* with a different signature. Replaces the GoF Adapter class hierarchy.
|
|
32
|
+
*
|
|
33
|
+
* @template FromIn - The source function's input type
|
|
34
|
+
* @template FromOut - The source function's output type
|
|
35
|
+
* @template ToIn - The target input type
|
|
36
|
+
* @template ToOut - The target output type
|
|
37
|
+
* @since 2.4.0
|
|
38
|
+
*/
|
|
39
|
+
export type Adapter<FromIn, FromOut, ToIn, ToOut> = (source: (input: FromIn) => FromOut) => (input: ToIn) => ToOut;
|
|
40
|
+
/**
|
|
41
|
+
* Creates a reusable adapter from input/output mappers.
|
|
42
|
+
* The adapter can then be applied to any source function
|
|
43
|
+
* with the matching signature.
|
|
44
|
+
*
|
|
45
|
+
* @template FromIn - The source function's input type
|
|
46
|
+
* @template FromOut - The source function's output type
|
|
47
|
+
* @template ToIn - The target input type
|
|
48
|
+
* @template ToOut - The target output type
|
|
49
|
+
* @param mapInput - Transforms target input into source input
|
|
50
|
+
* @param mapOutput - Transforms source output into target output
|
|
51
|
+
* @returns A reusable Adapter
|
|
52
|
+
* @since 2.4.0
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* // Adapter from Celsius to Fahrenheit API
|
|
57
|
+
* const celsiusToFahrenheit = createAdapter<number, string, number, string>(
|
|
58
|
+
* (fahrenheit) => (fahrenheit - 32) * 5 / 9, // °F -> °C input
|
|
59
|
+
* (label) => label.replace("°C", "°F"), // output label
|
|
60
|
+
* );
|
|
61
|
+
*
|
|
62
|
+
* const describeCelsius = (temp: number) => `${temp.toFixed(1)}°C`;
|
|
63
|
+
* const describeFahrenheit = celsiusToFahrenheit(describeCelsius);
|
|
64
|
+
*
|
|
65
|
+
* describeFahrenheit(212); // "100.0°F"
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare function createAdapter<FromIn, FromOut, ToIn, ToOut>(mapInput: (input: ToIn) => FromIn, mapOutput: (output: FromOut) => ToOut): Adapter<FromIn, FromOut, ToIn, ToOut>;
|
|
69
|
+
/**
|
|
70
|
+
* Adapts a source function in one shot by mapping both input and output.
|
|
71
|
+
*
|
|
72
|
+
* @template FromIn - The source function's input type
|
|
73
|
+
* @template FromOut - The source function's output type
|
|
74
|
+
* @template ToIn - The target input type
|
|
75
|
+
* @template ToOut - The target output type
|
|
76
|
+
* @param source - The function to adapt
|
|
77
|
+
* @param mapInput - Transforms target input into source input
|
|
78
|
+
* @param mapOutput - Transforms source output into target output
|
|
79
|
+
* @returns The adapted function
|
|
80
|
+
* @since 2.4.0
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* // Adapt a sorting function to work with strings instead of numbers
|
|
85
|
+
* const sortNumbers = (nums: number[]) => [...nums].sort((a, b) => a - b);
|
|
86
|
+
*
|
|
87
|
+
* const sortStrings = adapt(
|
|
88
|
+
* sortNumbers,
|
|
89
|
+
* (strs: string[]) => strs.map(Number),
|
|
90
|
+
* (nums) => nums.map(String),
|
|
91
|
+
* );
|
|
92
|
+
*
|
|
93
|
+
* sortStrings(["3", "1", "2"]); // ["1", "2", "3"]
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export declare function adapt<FromIn, FromOut, ToIn, ToOut>(source: (input: FromIn) => FromOut, mapInput: (input: ToIn) => FromIn, mapOutput: (output: FromOut) => ToOut): (input: ToIn) => ToOut;
|
|
97
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/eidos/adapter/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH;;;;;;;;;GASG;AACH,MAAM,MAAM,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,IAAI,CAClD,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,KAC/B,CAAC,KAAK,EAAE,IAAI,KAAK,KAAK,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EACxD,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,MAAM,EACjC,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,KAAK,GACpC,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAEvC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAChD,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,EAClC,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,MAAM,EACjC,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,KAAK,GACpC,CAAC,KAAK,EAAE,IAAI,KAAK,KAAK,CAExB"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Functional Adapter Pattern.
|
|
3
|
+
*
|
|
4
|
+
* In OOP, the Adapter pattern requires a Target class, an Adaptee class with
|
|
5
|
+
* an incompatible interface, and an Adapter class that extends/wraps both.
|
|
6
|
+
* In functional TypeScript, an adapter is a pair of mapping functions
|
|
7
|
+
* that transform one function signature into another.
|
|
8
|
+
*
|
|
9
|
+
* @module eidos/adapter
|
|
10
|
+
* @since 2.4.0
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { adapt, createAdapter } from "@pithos/core/eidos/adapter/adapter";
|
|
15
|
+
*
|
|
16
|
+
* // Legacy API returns XML string
|
|
17
|
+
* const legacyFetch = (id: number) => `<user><name>Alice</name></user>`;
|
|
18
|
+
*
|
|
19
|
+
* // Adapt to new API shape: string id in, object out
|
|
20
|
+
* const fetchUser = adapt(
|
|
21
|
+
* legacyFetch,
|
|
22
|
+
* (id: string) => parseInt(id), // map input
|
|
23
|
+
* (xml) => ({ name: "Alice", xml }), // map output
|
|
24
|
+
* );
|
|
25
|
+
*
|
|
26
|
+
* fetchUser("42"); // { name: "Alice", xml: "<user>..." }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Creates a reusable adapter from input/output mappers.
|
|
31
|
+
* The adapter can then be applied to any source function
|
|
32
|
+
* with the matching signature.
|
|
33
|
+
*
|
|
34
|
+
* @template FromIn - The source function's input type
|
|
35
|
+
* @template FromOut - The source function's output type
|
|
36
|
+
* @template ToIn - The target input type
|
|
37
|
+
* @template ToOut - The target output type
|
|
38
|
+
* @param mapInput - Transforms target input into source input
|
|
39
|
+
* @param mapOutput - Transforms source output into target output
|
|
40
|
+
* @returns A reusable Adapter
|
|
41
|
+
* @since 2.4.0
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* // Adapter from Celsius to Fahrenheit API
|
|
46
|
+
* const celsiusToFahrenheit = createAdapter<number, string, number, string>(
|
|
47
|
+
* (fahrenheit) => (fahrenheit - 32) * 5 / 9, // °F -> °C input
|
|
48
|
+
* (label) => label.replace("°C", "°F"), // output label
|
|
49
|
+
* );
|
|
50
|
+
*
|
|
51
|
+
* const describeCelsius = (temp: number) => `${temp.toFixed(1)}°C`;
|
|
52
|
+
* const describeFahrenheit = celsiusToFahrenheit(describeCelsius);
|
|
53
|
+
*
|
|
54
|
+
* describeFahrenheit(212); // "100.0°F"
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export function createAdapter(mapInput, mapOutput) {
|
|
58
|
+
return (source) => (input) => mapOutput(source(mapInput(input)));
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Adapts a source function in one shot by mapping both input and output.
|
|
62
|
+
*
|
|
63
|
+
* @template FromIn - The source function's input type
|
|
64
|
+
* @template FromOut - The source function's output type
|
|
65
|
+
* @template ToIn - The target input type
|
|
66
|
+
* @template ToOut - The target output type
|
|
67
|
+
* @param source - The function to adapt
|
|
68
|
+
* @param mapInput - Transforms target input into source input
|
|
69
|
+
* @param mapOutput - Transforms source output into target output
|
|
70
|
+
* @returns The adapted function
|
|
71
|
+
* @since 2.4.0
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* // Adapt a sorting function to work with strings instead of numbers
|
|
76
|
+
* const sortNumbers = (nums: number[]) => [...nums].sort((a, b) => a - b);
|
|
77
|
+
*
|
|
78
|
+
* const sortStrings = adapt(
|
|
79
|
+
* sortNumbers,
|
|
80
|
+
* (strs: string[]) => strs.map(Number),
|
|
81
|
+
* (nums) => nums.map(String),
|
|
82
|
+
* );
|
|
83
|
+
*
|
|
84
|
+
* sortStrings(["3", "1", "2"]); // ["1", "2", "3"]
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export function adapt(source, mapInput, mapOutput) {
|
|
88
|
+
return (input) => mapOutput(source(mapInput(input)));
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/eidos/adapter/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAgBH;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,aAAa,CAC3B,QAAiC,EACjC,SAAqC;IAErC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,KAAK,CACnB,MAAkC,EAClC,QAAiC,EACjC,SAAqC;IAErC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC"}
|