@nano-app/frontend 0.3.1 → 0.3.3

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 (60) hide show
  1. package/bin/generate-stores.mjs +128 -0
  2. package/dist/auto-register.d.ts +6 -0
  3. package/dist/auto-register.js +9 -0
  4. package/dist/auto-register.mjs +310 -0
  5. package/dist/auto-register.ts +336 -0
  6. package/dist/index.d.ts +3 -2
  7. package/dist/index.js +12 -2
  8. package/dist/state/RenderManager.d.ts +47 -0
  9. package/dist/state/RenderManager.js +78 -0
  10. package/dist/store/{ApiClient.d.ts → ApiStore.d.ts} +4 -3
  11. package/dist/store/{ApiClient.js → ApiStore.js} +10 -10
  12. package/dist/store/AppStore.d.ts +25 -0
  13. package/dist/store/AppStore.js +59 -0
  14. package/dist/store/RenderManager.d.ts +47 -0
  15. package/dist/store/RenderManager.js +78 -0
  16. package/dist/store/StateManager.d.ts +4 -0
  17. package/dist/store/StateManager.js +10 -0
  18. package/dist/store/StoreManager.d.ts +8 -9
  19. package/dist/store/StoreManager.js +14 -28
  20. package/dist/store/stores.d.ts +6 -0
  21. package/dist/store/stores.js +9 -0
  22. package/dist/ui/Controller.d.ts +13 -14
  23. package/dist/ui/Controller.js +41 -8
  24. package/dist/ui/createComponent.d.ts +17 -4
  25. package/dist/ui/createComponent.js +25 -18
  26. package/dist/utils/pathUtils.d.ts +14 -0
  27. package/dist/utils/pathUtils.js +43 -0
  28. package/package.json +8 -6
  29. package/dist/api/ApiClient.d.ts +0 -16
  30. package/dist/api/ApiClient.js +0 -69
  31. package/dist/api/QueryBuilder.d.ts +0 -8
  32. package/dist/api/QueryBuilder.js +0 -51
  33. package/dist/components/Controller.d.ts +0 -16
  34. package/dist/components/Controller.js +0 -29
  35. package/dist/config/index.d.ts +0 -21
  36. package/dist/config/index.js +0 -10
  37. package/dist/hooks/useComponent.d.ts +0 -8
  38. package/dist/hooks/useComponent.js +0 -10
  39. package/dist/plugin/index.d.ts +0 -11
  40. package/dist/plugin/index.js +0 -134
  41. package/dist/store/StoreClient.d.ts +0 -11
  42. package/dist/store/StoreClient.js +0 -40
  43. package/dist/store/bootstrapApp.d.ts +0 -19
  44. package/dist/store/bootstrapApp.js +0 -25
  45. package/dist/store/setStores.d.ts +0 -8
  46. package/dist/store/setStores.js +0 -23
  47. package/dist/types/api.d.ts +0 -7
  48. package/dist/types/api.js +0 -2
  49. package/dist/ui/Component.d.ts +0 -4
  50. package/dist/ui/Component.js +0 -49
  51. package/dist/ui/StoreProvider.d.ts +0 -18
  52. package/dist/ui/StoreProvider.js +0 -62
  53. package/dist/ui/defineController.d.ts +0 -23
  54. package/dist/ui/defineController.js +0 -14
  55. package/dist/ui/defineView.d.ts +0 -3
  56. package/dist/ui/defineView.js +0 -44
  57. package/dist/ui/definers.d.ts +0 -1
  58. package/dist/ui/definers.js +0 -59
  59. package/dist/ui/useComponent.d.ts +0 -2
  60. 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,6 @@
1
+ declare const _default: {
2
+ name: string;
3
+ type: string;
4
+ data: {};
5
+ }[];
6
+ export default _default;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = [
4
+ {
5
+ name: "app",
6
+ type: "app",
7
+ data: {},
8
+ }
9
+ ];
@@ -0,0 +1,310 @@
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
+ "isRegister": false,
32
+ "navbar": {
33
+ "tabs": [],
34
+ "selectedTabKey": "home",
35
+ "selectedTab": {},
36
+ "isMenuOpen": false
37
+ },
38
+ "form": {
39
+ "data": {},
40
+ "validate": []
41
+ },
42
+ "drawer": {
43
+ "isOpen": false,
44
+ "formType": "",
45
+ "title": ""
46
+ },
47
+ "totales": {},
48
+ "config": {
49
+ "theme": "dark"
50
+ }
51
+ }
52
+ },
53
+ {
54
+ "name": "const",
55
+ "type": "app",
56
+ "data": {
57
+ "alias": "42974117.prex",
58
+ "stepSkipTop": 20,
59
+ "tabs": (rolId = 0) => [
60
+ { key: "home", href: "/", label: "Home", minRole: -1 },
61
+ { key: "resumen", href: "/resumen", label: "Resumen", minRole: -1 },
62
+ { key: "admin", href: "/admin", label: "Administración", minRole: -1 },
63
+ { key: "uli", href: "/", label: "Uli :v", minRole: -1 },
64
+ { key: "luka", href: "/", label: "Lucas :v", minRole: -1 }].
65
+ filter((tab) => tab.minRole >= rolId),
66
+ "initialForms": {
67
+ "User": {
68
+ "rolId": 1,
69
+ "status": "PENDING"
70
+ },
71
+ "Collection": {
72
+ "total_months": 1,
73
+ "start_date": "2026-03-01T00:00:00.000Z"
74
+ }
75
+ },
76
+ "tableColumns": {
77
+ "Users": [
78
+ "name",
79
+ "phone",
80
+ "mail",
81
+ "pending",
82
+ "favor",
83
+ "rol.name",
84
+ "status"
85
+ ],
86
+ "Collections": [
87
+ "user.name",
88
+ "price",
89
+ "description",
90
+ "start_date",
91
+ "total_months",
92
+ "subscription.description"
93
+ ],
94
+ "Subscriptions": [
95
+ "description",
96
+ "price"
97
+ ]
98
+ },
99
+ "formField": {
100
+ "pay": [
101
+ {
102
+ "fieldName": "total",
103
+ "valueType": "price",
104
+ "isRequired": true
105
+ }
106
+ ],
107
+ "login": [
108
+ {
109
+ "fieldName": "mail",
110
+ "inputType": "email",
111
+ "isRequired": true
112
+ },
113
+ {
114
+ "fieldName": "password",
115
+ "inputType": "password",
116
+ "isRequired": true
117
+ }
118
+ ],
119
+ "register": [
120
+ {
121
+ "fieldName": "name",
122
+ "isRequired": true
123
+ },
124
+ {
125
+ "fieldName": "phone",
126
+ "isRequired": true
127
+ },
128
+ {
129
+ "fieldName": "mail",
130
+ "inputType": "email",
131
+ "isRequired": true
132
+ },
133
+ {
134
+ "fieldName": "password",
135
+ "inputType": "password",
136
+ "isRequired": true
137
+ },
138
+ {
139
+ "fieldName": "confirmPassword",
140
+ "inputType": "password",
141
+ "isRequired": true
142
+ }
143
+ ],
144
+ "Users": [
145
+ {
146
+ "fieldName": "name",
147
+ "isRequired": true
148
+ },
149
+ {
150
+ "fieldName": "mail",
151
+ "inputType": "email",
152
+ "isRequired": true
153
+ },
154
+ {
155
+ "fieldName": "rolId",
156
+ "valueType": "number",
157
+ "isRequired": true,
158
+ "inputType": "select",
159
+ "select": {
160
+ "items": "/Roles",
161
+ "itemKey": "id",
162
+ "showValues": [
163
+ "name"
164
+ ]
165
+ }
166
+ },
167
+ {
168
+ "fieldName": "status",
169
+ "inputType": "select",
170
+ "isRequired": true,
171
+ "select": {
172
+ "items": "/UserStatusItems",
173
+ "itemKey": "key",
174
+ "showValues": [
175
+ "text"
176
+ ]
177
+ }
178
+ },
179
+ {
180
+ "fieldName": "pending",
181
+ "valueType": "price"
182
+ },
183
+ {
184
+ "fieldName": "favor",
185
+ "valueType": "price"
186
+ }
187
+ ],
188
+ "Collections": [
189
+ {
190
+ "fieldName": "userId",
191
+ "valueType": "number",
192
+ "inputType": "select",
193
+ "isRequired": true,
194
+ "select": {
195
+ "items": "Users",
196
+ "itemKey": "id",
197
+ "showValues": [
198
+ "name"
199
+ ]
200
+ }
201
+ },
202
+ {
203
+ "fieldName": "price",
204
+ "valueType": "price",
205
+ "isRequired": true
206
+ },
207
+ {
208
+ "fieldName": "description",
209
+ "isRequired": true
210
+ },
211
+ {
212
+ "fieldName": "total_months",
213
+ "valueType": "number",
214
+ "isRequired": true
215
+ },
216
+ {
217
+ "fieldName": "start_date",
218
+ "valueType": "date",
219
+ "inputType": "date",
220
+ "isRequired": true
221
+ },
222
+ {
223
+ "fieldName": "subscriptionId",
224
+ "valueType": "number",
225
+ "inputType": "select",
226
+ "select": {
227
+ "items": "Subscriptions",
228
+ "itemKey": "id",
229
+ "showValues": [
230
+ "description"
231
+ ]
232
+ }
233
+ }
234
+ ],
235
+ "Subscriptions": [
236
+ {
237
+ "fieldName": "description",
238
+ "isRequired": true
239
+ },
240
+ {
241
+ "fieldName": "price",
242
+ "valueType": "price",
243
+ "isRequired": true
244
+ }
245
+ ]
246
+ },
247
+ "expandFields": {
248
+ "Users": "rol",
249
+ "Collections": "user,subscription"
250
+ }
251
+ }
252
+ },
253
+ {
254
+ "name": "i18n",
255
+ "type": "app",
256
+ "data": {
257
+ "login": {
258
+ "header": (isRegister) => isRegister ? "REGISTRARSE" : "INICIAR SESIÓN",
259
+ "footer": (isRegister) => isRegister ? "o iniciar sesión" : "o registrarse",
260
+ "buttonText": (isRegister) => isRegister ? "Crear" : "Ingresar"
261
+ },
262
+ "create": (entity) => `Crear ${entity}`,
263
+ "edit": (entity) => `Editar ${entity}`,
264
+ "mapping": {
265
+ "name": "Nombre",
266
+ "phone": "Teléfono",
267
+ "mail": "Mail",
268
+ "pending": "Pendiente",
269
+ "favor": "A favor",
270
+ "rolId": "Rol",
271
+ "rol.name": "Rol",
272
+ "status": "Estado",
273
+ "password": "Contraseña",
274
+ "confirmPassword": "Repetir contraseña",
275
+ "user.name": "Usuario",
276
+ "userId": "Usuario",
277
+ "price": "Precio",
278
+ "description": "Descripción",
279
+ "start_date": "Fecha de inicio",
280
+ "total_months": "Meses totales",
281
+ "subscription.description": "Subscripción",
282
+ "subscriptionId": "Subscripción",
283
+ "last_pay": "Último pago",
284
+ "first_month": "Mes de inicio",
285
+ "current_month": "Último mes pagado",
286
+ "payed_months": "Meses pagados",
287
+ "actions": "Acciones",
288
+ "created_at": "Creado",
289
+ "Users": "Usuarios",
290
+ "Collections": "Cuotas",
291
+ "Subscriptions": "Subscripciones",
292
+ "total": "TOTAL"
293
+ },
294
+ "months": {
295
+ "1": "Enero",
296
+ "2": "Febrero",
297
+ "3": "Marzo",
298
+ "4": "Abril",
299
+ "5": "Mayo",
300
+ "6": "Junio",
301
+ "7": "Julio",
302
+ "8": "Agosto",
303
+ "9": "Septiembre",
304
+ "10": "Octubre",
305
+ "11": "Noviembre",
306
+ "12": "Diciembre"
307
+ }
308
+ }
309
+ }
310
+ ];