@nano-app/frontend 0.3.2 → 0.3.4

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 (50) hide show
  1. package/bin/generate-stores.mjs +128 -0
  2. package/dist/auto-register.mjs +327 -0
  3. package/dist/index.d.ts +3 -2
  4. package/dist/index.js +12 -2
  5. package/dist/store/{ApiClient.d.ts → ApiStore.d.ts} +4 -3
  6. package/dist/store/{ApiClient.js → ApiStore.js} +11 -11
  7. package/dist/store/AppStore.d.ts +25 -0
  8. package/dist/store/AppStore.js +59 -0
  9. package/dist/store/RenderManager.d.ts +47 -0
  10. package/dist/store/RenderManager.js +78 -0
  11. package/dist/store/StoreManager.d.ts +8 -9
  12. package/dist/store/StoreManager.js +14 -28
  13. package/dist/ui/Controller.d.ts +18 -15
  14. package/dist/ui/Controller.js +43 -14
  15. package/dist/ui/createComponent.d.ts +16 -4
  16. package/dist/ui/createComponent.js +26 -18
  17. package/dist/utils/QueryBuilder.js +4 -2
  18. package/package.json +6 -2
  19. package/dist/api/ApiClient.d.ts +0 -16
  20. package/dist/api/ApiClient.js +0 -69
  21. package/dist/api/QueryBuilder.d.ts +0 -8
  22. package/dist/api/QueryBuilder.js +0 -51
  23. package/dist/components/Controller.d.ts +0 -16
  24. package/dist/components/Controller.js +0 -29
  25. package/dist/config/index.d.ts +0 -21
  26. package/dist/config/index.js +0 -10
  27. package/dist/hooks/useComponent.d.ts +0 -8
  28. package/dist/hooks/useComponent.js +0 -10
  29. package/dist/plugin/index.d.ts +0 -11
  30. package/dist/plugin/index.js +0 -134
  31. package/dist/store/StoreClient.d.ts +0 -11
  32. package/dist/store/StoreClient.js +0 -40
  33. package/dist/store/bootstrapApp.d.ts +0 -19
  34. package/dist/store/bootstrapApp.js +0 -25
  35. package/dist/store/setStores.d.ts +0 -8
  36. package/dist/store/setStores.js +0 -23
  37. package/dist/types/api.d.ts +0 -7
  38. package/dist/types/api.js +0 -2
  39. package/dist/ui/Component.d.ts +0 -4
  40. package/dist/ui/Component.js +0 -49
  41. package/dist/ui/StoreProvider.d.ts +0 -18
  42. package/dist/ui/StoreProvider.js +0 -62
  43. package/dist/ui/defineController.d.ts +0 -23
  44. package/dist/ui/defineController.js +0 -14
  45. package/dist/ui/defineView.d.ts +0 -3
  46. package/dist/ui/defineView.js +0 -44
  47. package/dist/ui/definers.d.ts +0 -1
  48. package/dist/ui/definers.js +0 -59
  49. package/dist/ui/useComponent.d.ts +0 -2
  50. package/dist/ui/useComponent.js +0 -9
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { createRequire } from "module";
4
+ import { readdirSync, mkdirSync, writeFileSync, existsSync } from "fs";
5
+ import { resolve, join } from "path";
6
+
7
+ const cwd = process.cwd();
8
+ const srcDir = join(cwd, "src");
9
+ const outDir = join(cwd, "node_modules", "@nano-app", "frontend", "dist");
10
+ const outFile = join(outDir, "auto-register.mjs");
11
+
12
+ // Busca recursivamente archivos *.store.ts
13
+ function findStoreFiles(dir) {
14
+ const results = [];
15
+ if (!existsSync(dir)) return results;
16
+
17
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
18
+ const fullPath = join(dir, entry.name);
19
+ if (entry.isDirectory()) {
20
+ results.push(...findStoreFiles(fullPath));
21
+ } else if (entry.isFile() && entry.name.endsWith(".store.ts")) {
22
+ results.push(fullPath);
23
+ }
24
+ }
25
+ return results;
26
+ }
27
+
28
+ // Importa un archivo .ts usando jiti (transpilador de Next.js)
29
+ function loadStoreFile(filePath) {
30
+ try {
31
+ const jitiPath = resolve(cwd, "node_modules", "jiti", "lib", "jiti.cjs");
32
+ const require = createRequire(import.meta.url);
33
+ const jiti = require(jitiPath);
34
+ const load = jiti(filePath, { interopDefault: true });
35
+ const mod = load(filePath);
36
+ return mod?.default ?? mod;
37
+ } catch (err) {
38
+ console.error(` [ERROR] No se pudo cargar ${filePath}: ${err.message}`);
39
+ return null;
40
+ }
41
+ }
42
+
43
+ // Valida que el objeto tenga la forma correcta
44
+ function validateEntry(entry, filePath) {
45
+ if (!entry || typeof entry !== "object") {
46
+ console.warn(` [WARN] ${filePath}: el export default no es un objeto, se ignora.`);
47
+ return false;
48
+ }
49
+ if (entry.type !== "app" && entry.type !== "api") {
50
+ console.warn(` [WARN] ${filePath}: type debe ser "app" o "api", se ignora.`);
51
+ return false;
52
+ }
53
+ if (entry.type === "api" && !entry.path) {
54
+ console.warn(` [WARN] ${filePath}: type "api" requiere un campo "path", se ignora.`);
55
+ return false;
56
+ }
57
+ return true;
58
+ }
59
+
60
+ // Serializa el objeto de datos a string JS (soporta funciones)
61
+ function serialize(value, indent = 0) {
62
+ const pad = " ".repeat(indent);
63
+ const padInner = " ".repeat(indent + 1);
64
+
65
+ if (value === null) return "null";
66
+ if (value === undefined) return "undefined";
67
+ if (typeof value === "function") return value.toString();
68
+ if (typeof value === "string") return JSON.stringify(value);
69
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
70
+
71
+ if (Array.isArray(value)) {
72
+ if (value.length === 0) return "[]";
73
+ const items = value.map((v) => `${padInner}${serialize(v, indent + 1)}`).join(",\n");
74
+ return `[\n${items}\n${pad}]`;
75
+ }
76
+
77
+ if (typeof value === "object") {
78
+ const entries = Object.entries(value);
79
+ if (entries.length === 0) return "{}";
80
+ const lines = entries
81
+ .map(([k, v]) => `${padInner}${JSON.stringify(k)}: ${serialize(v, indent + 1)}`)
82
+ .join(",\n");
83
+ return `{\n${lines}\n${pad}}`;
84
+ }
85
+
86
+ return String(value);
87
+ }
88
+
89
+ // ─── Main ────────────────────────────────────────────────────────────────────
90
+
91
+ const storeFiles = findStoreFiles(srcDir);
92
+ console.log(`\n[nano-app] Buscando archivos *.store.ts en ${srcDir}`);
93
+ console.log(`[nano-app] Encontrados: ${storeFiles.length}\n`);
94
+
95
+ const entries = [];
96
+
97
+ for (const filePath of storeFiles) {
98
+ console.log(` Procesando: ${filePath.replace(cwd, ".")}`);
99
+ const mod = loadStoreFile(filePath);
100
+ if (mod && validateEntry(mod, filePath)) {
101
+ const name = filePath
102
+ .replace(srcDir, "")
103
+ .replace(/\\/g, "/")
104
+ .replace(/^\//, "")
105
+ .replace(/\.store\.ts$/, "")
106
+ .split("/")
107
+ .pop();
108
+
109
+ entries.push({ name, ...mod });
110
+ console.log(` ✓ Store "${name}" (${mod.type})`);
111
+ }
112
+ }
113
+
114
+ // Genera el archivo de salida
115
+ mkdirSync(outDir, { recursive: true });
116
+
117
+ const serializedEntries = entries
118
+ .map((entry) => ` ${serialize(entry, 1)}`)
119
+ .join(",\n");
120
+
121
+ const output = `// Auto-generado por @nano-app
122
+ // No editar manualmente.
123
+ export default [\n${serializedEntries}\n];\n`;
124
+
125
+ writeFileSync(outFile, output, "utf-8");
126
+
127
+ console.log(`\n[nano-app] Archivo generado: ${outFile.replace(cwd, ".")}`);
128
+ console.log(`[nano-app] Stores registrados: ${entries.map((e) => `"${e.name}"`).join(", ") || "(ninguno — se usará store app vacío)"}\n`);
@@ -0,0 +1,327 @@
1
+ // Auto-generado por @nano-app
2
+ // No editar manualmente.
3
+ export default [
4
+ {
5
+ "name": "api",
6
+ "type": "api",
7
+ "path": "/api",
8
+ "data": {
9
+ "busy": true,
10
+ "DefaultItems": [],
11
+ "UserStatusItems": [
12
+ {
13
+ "key": "SUSPENDED",
14
+ "text": "Suspendido"
15
+ },
16
+ {
17
+ "key": "PENDING",
18
+ "text": "Pendiente"
19
+ },
20
+ {
21
+ "key": "ACTIVE",
22
+ "text": "Activo"
23
+ }
24
+ ]
25
+ }
26
+ },
27
+ {
28
+ "name": "app",
29
+ "type": "app",
30
+ "data": {
31
+ "login": {
32
+ "isRegister": false
33
+ },
34
+ "navbar": {
35
+ "tabs": [],
36
+ "selectedTabKey": "home",
37
+ "selectedTab": {},
38
+ "isMenuOpen": false
39
+ },
40
+ "form": {
41
+ "data": {},
42
+ "validate": []
43
+ },
44
+ "drawer": {
45
+ "isOpen": false,
46
+ "formType": "",
47
+ "title": ""
48
+ },
49
+ "config": {
50
+ "theme": "dark"
51
+ }
52
+ }
53
+ },
54
+ {
55
+ "name": "const",
56
+ "type": "app",
57
+ "data": {
58
+ "alias": "42974117.prex",
59
+ "stepSkipTop": 20,
60
+ "tabs": (rolId = 0) => [
61
+ { key: "home", href: "/", label: "Home", minRole: -1 },
62
+ { key: "resumen", href: "/resumen", label: "Resumen", minRole: -1 },
63
+ { key: "admin", href: "/admin", label: "Administración", minRole: -1 },
64
+ { key: "uli", href: "/", label: "Uli :v", minRole: -1 },
65
+ { key: "luka", href: "/", label: "Lucas :v", minRole: -1 }].
66
+ filter((tab) => tab.minRole <= rolId),
67
+ "initialForms": {
68
+ "User": {
69
+ "rolId": 1,
70
+ "status": "PENDING"
71
+ },
72
+ "Collection": {
73
+ "total_months": 1,
74
+ "start_date": "2026-03-01T00:00:00.000Z"
75
+ }
76
+ },
77
+ "tableColumns": {
78
+ "Users": [
79
+ "name",
80
+ "phone",
81
+ "mail",
82
+ "pending",
83
+ "favor",
84
+ "rol.name",
85
+ "status"
86
+ ],
87
+ "Collections": [
88
+ "user.name",
89
+ "price",
90
+ "description",
91
+ "start_date",
92
+ "total_months",
93
+ "subscription.description"
94
+ ],
95
+ "Subscriptions": [
96
+ "description",
97
+ "price"
98
+ ]
99
+ },
100
+ "formField": {
101
+ "pay": [
102
+ {
103
+ "fieldName": "total",
104
+ "valueType": "price",
105
+ "isRequired": true
106
+ }
107
+ ],
108
+ "login": [
109
+ {
110
+ "fieldName": "mail",
111
+ "inputType": "email",
112
+ "isRequired": true
113
+ },
114
+ {
115
+ "fieldName": "password",
116
+ "inputType": "password",
117
+ "isRequired": true,
118
+ "validateFn": (oForm) =>
119
+ (oForm.password?.length || 0) < 4 ?
120
+ "La contraseña debe tener al menos 4 caracteres" :
121
+ ""
122
+ }
123
+ ],
124
+ "register": [
125
+ {
126
+ "fieldName": "name",
127
+ "isRequired": true
128
+ },
129
+ {
130
+ "fieldName": "phone",
131
+ "isRequired": true
132
+ },
133
+ {
134
+ "fieldName": "mail",
135
+ "inputType": "email",
136
+ "isRequired": true
137
+ },
138
+ {
139
+ "fieldName": "password",
140
+ "inputType": "password",
141
+ "isRequired": true,
142
+ "validateFn": (oForm) =>
143
+ (oForm.password?.length || 0) < 4 ?
144
+ "La contraseña debe tener al menos 4 caracteres" :
145
+ ""
146
+ },
147
+ {
148
+ "fieldName": "confirmPassword",
149
+ "inputType": "password",
150
+ "isRequired": true,
151
+ "validateFn": (oForm) =>
152
+ oForm.confirmPassword != oForm.password ?
153
+ 'Las contraseñas no coinciden' :
154
+ ''
155
+ }
156
+ ],
157
+ "Users": [
158
+ {
159
+ "fieldName": "name",
160
+ "isRequired": true
161
+ },
162
+ {
163
+ "fieldName": "mail",
164
+ "inputType": "email",
165
+ "isRequired": true
166
+ },
167
+ {
168
+ "fieldName": "rolId",
169
+ "valueType": "number",
170
+ "isRequired": true,
171
+ "inputType": "select",
172
+ "select": {
173
+ "items": "/Roles",
174
+ "itemKey": "id",
175
+ "showValues": [
176
+ "name"
177
+ ]
178
+ }
179
+ },
180
+ {
181
+ "fieldName": "status",
182
+ "inputType": "select",
183
+ "isRequired": true,
184
+ "select": {
185
+ "items": "/UserStatusItems",
186
+ "itemKey": "key",
187
+ "showValues": [
188
+ "text"
189
+ ]
190
+ }
191
+ },
192
+ {
193
+ "fieldName": "pending",
194
+ "valueType": "price"
195
+ },
196
+ {
197
+ "fieldName": "favor",
198
+ "valueType": "price"
199
+ }
200
+ ],
201
+ "Collections": [
202
+ {
203
+ "fieldName": "userId",
204
+ "valueType": "number",
205
+ "inputType": "select",
206
+ "isRequired": true,
207
+ "select": {
208
+ "items": "Users",
209
+ "itemKey": "id",
210
+ "showValues": [
211
+ "name"
212
+ ]
213
+ }
214
+ },
215
+ {
216
+ "fieldName": "price",
217
+ "valueType": "price",
218
+ "isRequired": true
219
+ },
220
+ {
221
+ "fieldName": "description",
222
+ "isRequired": true
223
+ },
224
+ {
225
+ "fieldName": "total_months",
226
+ "valueType": "number",
227
+ "isRequired": true
228
+ },
229
+ {
230
+ "fieldName": "start_date",
231
+ "valueType": "date",
232
+ "inputType": "date",
233
+ "isRequired": true
234
+ },
235
+ {
236
+ "fieldName": "subscriptionId",
237
+ "valueType": "number",
238
+ "inputType": "select",
239
+ "select": {
240
+ "items": "Subscriptions",
241
+ "itemKey": "id",
242
+ "showValues": [
243
+ "description"
244
+ ]
245
+ }
246
+ }
247
+ ],
248
+ "Subscriptions": [
249
+ {
250
+ "fieldName": "description",
251
+ "isRequired": true
252
+ },
253
+ {
254
+ "fieldName": "price",
255
+ "valueType": "price",
256
+ "isRequired": true
257
+ }
258
+ ]
259
+ },
260
+ "expandFields": {
261
+ "Users": "rol",
262
+ "Collections": "user,subscription"
263
+ }
264
+ }
265
+ },
266
+ {
267
+ "name": "i18n",
268
+ "type": "app",
269
+ "data": {
270
+ "loginTexts": (isRegister) => ({
271
+ headerText: isRegister ? "REGISTRARSE" : "INICIAR SESIÓN",
272
+ footerText: isRegister ? "o iniciar sesión" : "o registrarse",
273
+ buttonText: isRegister ? "Crear" : "Ingresar",
274
+ formType: isRegister ? "register" : "login"
275
+ }),
276
+ "button": {
277
+ "confirm": "Confirmar"
278
+ },
279
+ "create": (entity) => `Crear ${entity}`,
280
+ "edit": (entity) => `Editar ${entity}`,
281
+ "mapping": {
282
+ "name": "Nombre",
283
+ "phone": "Teléfono",
284
+ "mail": "Mail",
285
+ "pending": "Pendiente",
286
+ "favor": "A favor",
287
+ "rolId": "Rol",
288
+ "rol.name": "Rol",
289
+ "status": "Estado",
290
+ "password": "Contraseña",
291
+ "confirmPassword": "Repetir contraseña",
292
+ "user.name": "Usuario",
293
+ "userId": "Usuario",
294
+ "price": "Precio",
295
+ "description": "Descripción",
296
+ "start_date": "Fecha de inicio",
297
+ "total_months": "Meses totales",
298
+ "subscription.description": "Subscripción",
299
+ "subscriptionId": "Subscripción",
300
+ "last_pay": "Último pago",
301
+ "first_month": "Mes de inicio",
302
+ "current_month": "Último mes pagado",
303
+ "payed_months": "Meses pagados",
304
+ "actions": "Acciones",
305
+ "created_at": "Creado",
306
+ "Users": "Usuarios",
307
+ "Collections": "Cuotas",
308
+ "Subscriptions": "Subscripciones",
309
+ "total": "TOTAL"
310
+ },
311
+ "months": {
312
+ "1": "Enero",
313
+ "2": "Febrero",
314
+ "3": "Marzo",
315
+ "4": "Abril",
316
+ "5": "Mayo",
317
+ "6": "Junio",
318
+ "7": "Julio",
319
+ "8": "Agosto",
320
+ "9": "Septiembre",
321
+ "10": "Octubre",
322
+ "11": "Noviembre",
323
+ "12": "Diciembre"
324
+ }
325
+ }
326
+ }
327
+ ];
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- export * from "./store/ApiClient";
2
- export * from "./store/StoreClient";
1
+ export * from "./store/ApiStore";
2
+ export * from "./store/AppStore";
3
3
  export * from "./store/StoreManager";
4
+ export * from "./store/RenderManager";
4
5
  export * from "./ui/Controller";
5
6
  export * from "./ui/createComponent";
6
7
  export * from "./utils/QueryBuilder";
package/dist/index.js CHANGED
@@ -13,12 +13,22 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
13
13
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
16
19
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./store/ApiClient"), exports);
18
- __exportStar(require("./store/StoreClient"), exports);
20
+ const StoreManager_1 = __importDefault(require("./store/StoreManager"));
21
+ __exportStar(require("./store/ApiStore"), exports);
22
+ __exportStar(require("./store/AppStore"), exports);
19
23
  __exportStar(require("./store/StoreManager"), exports);
24
+ __exportStar(require("./store/RenderManager"), exports);
20
25
  __exportStar(require("./ui/Controller"), exports);
21
26
  __exportStar(require("./ui/createComponent"), exports);
22
27
  __exportStar(require("./utils/QueryBuilder"), exports);
23
28
  __exportStar(require("./utils/Toast"), exports);
24
29
  __exportStar(require("./utils/TokenHelper"), exports);
30
+ // Inicializa los stores si existen
31
+ try {
32
+ StoreManager_1.default.init(require('./auto-register.mjs').default);
33
+ }
34
+ catch (e) { }
@@ -1,9 +1,10 @@
1
1
  import type { ApiResponse } from "@nano-app/backend";
2
- import { StoreClient } from "./StoreClient";
2
+ import { AppStore, StoreData } from "./AppStore";
3
3
  export type ApiRequest = (query: string, body?: unknown) => Promise<ApiResponse>;
4
- export declare class ApiClient extends StoreClient {
4
+ export declare class ApiStore extends AppStore {
5
5
  private baseUrl;
6
- constructor(baseUrl?: string);
6
+ private busyCount;
7
+ constructor(initialData?: StoreData, storeName?: string, baseUrl?: string);
7
8
  create: ApiRequest;
8
9
  read: ApiRequest;
9
10
  update: ApiRequest;
@@ -1,28 +1,29 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ApiClient = void 0;
4
- const StoreClient_1 = require("./StoreClient");
3
+ exports.ApiStore = void 0;
4
+ const AppStore_1 = require("./AppStore");
5
5
  const QueryBuilder_1 = require("../utils/QueryBuilder");
6
6
  const TokenHelper_1 = require("../utils/TokenHelper");
7
7
  const Toast_1 = require("../utils/Toast");
8
- class ApiClient extends StoreClient_1.StoreClient {
8
+ class ApiStore extends AppStore_1.AppStore {
9
9
  baseUrl;
10
- constructor(baseUrl = "/api") {
11
- super();
10
+ busyCount = 0;
11
+ constructor(initialData = {}, storeName = "", baseUrl = "/api") {
12
+ super({}, storeName);
12
13
  this.baseUrl = baseUrl;
13
14
  }
14
15
  create = (entity, body) => this.request("POST", entity, body);
15
16
  read = async (query, params = {}) => {
16
17
  const path = query.split("?")[0];
17
18
  const response = await this.request("GET", QueryBuilder_1.QueryBuilder.build(query, params));
18
- this.set(`/${path}`, response.result);
19
+ this.set(`${path}`, response.result);
19
20
  return response;
20
21
  };
21
22
  update = (entity, body) => this.request("PUT", entity, body);
22
23
  delete = (entity, id) => this.request("DELETE", entity, id);
23
24
  async request(method, path, body) {
24
25
  let oResponse = { result: null, success: false, message: "", warning: false };
25
- this.set("/busyCount", (this.get("/busyCount") || 0) + 1);
26
+ this.busyCount++;
26
27
  this.set("/busy", true);
27
28
  try {
28
29
  oResponse = await fetch(`${this.baseUrl}${path}`, {
@@ -40,12 +41,11 @@ class ApiClient extends StoreClient_1.StoreClient {
40
41
  console.error(error);
41
42
  }
42
43
  finally {
43
- const remaining = this.get("/busyCount") - 1;
44
- this.set("/busyCount", remaining);
45
- if (remaining < 1)
44
+ this.busyCount--;
45
+ if (this.busyCount < 1)
46
46
  this.set("/busy", false);
47
47
  }
48
48
  return oResponse;
49
49
  }
50
50
  }
51
- exports.ApiClient = ApiClient;
51
+ exports.ApiStore = ApiStore;
@@ -0,0 +1,25 @@
1
+ export type StoreData = Record<string, any>;
2
+ export declare class AppStore {
3
+ protected name: string;
4
+ private state;
5
+ constructor(initialData?: StoreData, name?: string);
6
+ /**
7
+ * Gestiona el estado de la store
8
+ * @param path - El path del estado
9
+ * @param value - El valor a asignar
10
+ * @returns El valor del estado
11
+ */
12
+ private manageState;
13
+ /**
14
+ * Obtiene el valor del estado
15
+ * @param path - El path del estado
16
+ * @returns El valor del estado
17
+ */
18
+ get(path: string): any;
19
+ /**
20
+ * Asigna un valor al estado
21
+ * @param path - El path del estado
22
+ * @param value - El valor a asignar
23
+ */
24
+ set(path: string, value: any): void;
25
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AppStore = void 0;
7
+ const RenderManager_1 = __importDefault(require("./RenderManager"));
8
+ class AppStore {
9
+ name;
10
+ state;
11
+ constructor(initialData = {}, name = "app") {
12
+ this.name = name;
13
+ this.state = initialData;
14
+ }
15
+ /**
16
+ * Gestiona el estado de la store
17
+ * @param path - El path del estado
18
+ * @param value - El valor a asignar
19
+ * @returns El valor del estado
20
+ */
21
+ manageState(path, value) {
22
+ // Divide el path en segmentos y obtiene el ultimo segmento
23
+ const segments = path.split("/").filter(Boolean);
24
+ if (segments.length === 0)
25
+ return this.state;
26
+ const last = segments.pop();
27
+ // Recorre los segmentos y crea el objeto si no existe
28
+ let current = this.state;
29
+ for (const seg of segments) {
30
+ if (current[seg] == null)
31
+ current[seg] = {};
32
+ current = current[seg];
33
+ }
34
+ // Si se proporciona un valor, lo asigna al ultimo segmento
35
+ if (arguments.length >= 2) {
36
+ current[last] = value;
37
+ }
38
+ // Retorna el valor del ultimo segmento
39
+ return current[last];
40
+ }
41
+ /**
42
+ * Obtiene el valor del estado
43
+ * @param path - El path del estado
44
+ * @returns El valor del estado
45
+ */
46
+ get(path) {
47
+ return this.manageState(path);
48
+ }
49
+ /**
50
+ * Asigna un valor al estado
51
+ * @param path - El path del estado
52
+ * @param value - El valor a asignar
53
+ */
54
+ set(path, value) {
55
+ this.manageState(path, value);
56
+ RenderManager_1.default.refresh(path, this.name);
57
+ }
58
+ }
59
+ exports.AppStore = AppStore;
@@ -0,0 +1,47 @@
1
+ type ComponentId = symbol;
2
+ /**
3
+ {
4
+ store1: {
5
+ path1: {
6
+ component1: true,
7
+ component2: true,
8
+ },
9
+ path2: {
10
+ component1: true,
11
+ },
12
+ path3: {
13
+ component1: true,
14
+ },
15
+ }
16
+ }
17
+ */
18
+ export declare class RenderManager {
19
+ private dependenciesMap;
20
+ private hooksMap;
21
+ /**
22
+ * Registra un hook de re-render para un componente
23
+ * @param componentId - El id del componente
24
+ * @param hook - El hook de re-render
25
+ */
26
+ register(componentId: ComponentId, hook: () => void): void;
27
+ /**
28
+ * Agrega una dependencia de path a un componente
29
+ * @param componentId - El id del componente
30
+ * @param path - El path del estado
31
+ * @param storeName - El nombre del store
32
+ */
33
+ dependsOn(componentId: ComponentId, path: string, storeName: string): void;
34
+ /**
35
+ * Actualiza los componentes que dependen de este path
36
+ * @param path - El path del estado
37
+ * @param storeName - El nombre del store
38
+ */
39
+ refresh(path: string, storeName: string): void;
40
+ /**
41
+ * Elimina un componente del manager
42
+ * @param componentId - El id del componente
43
+ */
44
+ unregister(componentId: ComponentId): void;
45
+ }
46
+ declare const _default: RenderManager;
47
+ export default _default;