@deijose/nix-js 0.1.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.
@@ -0,0 +1,117 @@
1
+ // ═══════════════════════════════════════════════
2
+ // Nix.js ❄️ — Global Stores (Fase 5)
3
+ // ═══════════════════════════════════════════════
4
+ //
5
+ // createStore(initialState, actions?)
6
+ //
7
+ // Crea un store reactivo global. Cada propiedad del estado
8
+ // se convierte en un Signal — legible y escribible.
9
+ // Las acciones reciben directamente los signals del estado.
10
+ //
11
+ // Ejemplo básico:
12
+ //
13
+ // const counter = createStore({ count: 0 });
14
+ // counter.count.value++; // escribe
15
+ // counter.count.value // lee (reactivo en effects/templates)
16
+ //
17
+ // Con acciones:
18
+ //
19
+ // const counter = createStore(
20
+ // { count: 0 },
21
+ // (s) => ({
22
+ // increment: () => s.count.update(n => n + 1),
23
+ // add: (n: number) => s.count.update(c => c + n),
24
+ // reset: () => counter.$reset(),
25
+ // })
26
+ // );
27
+ //
28
+ // counter.increment();
29
+ // counter.add(5);
30
+ // counter.$reset(); // restaura todos los valores iniciales
31
+
32
+ import { Signal, signal } from "./reactivity";
33
+
34
+ // ─── Tipos ────────────────────────────────────────────────────────────────────
35
+
36
+ /** Transforma cada propiedad del estado inicial en su Signal correspondiente. */
37
+ export type StoreSignals<T extends Record<string, unknown>> = {
38
+ readonly [K in keyof T]: Signal<T[K]>;
39
+ };
40
+
41
+ /** Tipo del store tal como lo ve el usuario. */
42
+ export type Store<
43
+ T extends Record<string, unknown>,
44
+ A extends Record<string, unknown> = Record<never, never>,
45
+ > = StoreSignals<T> & A & {
46
+ /**
47
+ * Restaura todos los signals a sus valores iniciales.
48
+ * Equivalente a hacer `signal.value = initialValue` en cada propiedad.
49
+ */
50
+ $reset(): void;
51
+ };
52
+
53
+ // ─── createStore ──────────────────────────────────────────────────────────────
54
+
55
+ /**
56
+ * Crea un store reactivo global.
57
+ *
58
+ * @param initialState Objeto plano con los valores iniciales.
59
+ * @param actionsFactory Función que recibe los signals y retorna acciones.
60
+ *
61
+ * @example
62
+ * // Sin acciones
63
+ * const theme = createStore({ dark: false, fontSize: 16 });
64
+ * theme.dark.value = true;
65
+ *
66
+ * @example
67
+ * // Con acciones
68
+ * const cart = createStore(
69
+ * { items: [] as string[], total: 0 },
70
+ * (s) => ({
71
+ * add: (item: string) => s.items.update(arr => [...arr, item]),
72
+ * clear: () => cart.$reset(),
73
+ * })
74
+ * );
75
+ *
76
+ * cart.add("Manzana");
77
+ * cart.items.value; // ["Manzana"]
78
+ * cart.clear();
79
+ * cart.items.value; // []
80
+ */
81
+ export function createStore<
82
+ T extends Record<string, unknown>,
83
+ A extends Record<string, unknown> = Record<never, never>,
84
+ >(
85
+ initialState: T,
86
+ actionsFactory?: (signals: StoreSignals<T>) => A
87
+ ): Store<T, A> {
88
+ // 1. Crear un Signal por cada propiedad
89
+ const signals = {} as Record<string, Signal<unknown>>;
90
+ for (const key of Object.keys(initialState)) {
91
+ signals[key] = signal(initialState[key]);
92
+ }
93
+
94
+ const typedSignals = signals as unknown as StoreSignals<T>;
95
+
96
+ // 2. $reset: restaura cada signal a su valor inicial
97
+ function $reset() {
98
+ for (const key of Object.keys(initialState)) {
99
+ (signals[key] as Signal<unknown>).value = initialState[key];
100
+ }
101
+ }
102
+
103
+ // 3. Construir el store base
104
+ const store = Object.assign(
105
+ Object.create(null) as object,
106
+ typedSignals,
107
+ { $reset }
108
+ ) as Store<T, A>;
109
+
110
+ // 4. Si hay acciones, crearlas y mezclarlas en el store
111
+ if (actionsFactory) {
112
+ const actions = actionsFactory(typedSignals);
113
+ Object.assign(store, actions);
114
+ }
115
+
116
+ return store;
117
+ }