@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,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RenderManager = void 0;
4
+ /**
5
+ {
6
+ store1: {
7
+ path1: {
8
+ component1: true,
9
+ component2: true,
10
+ },
11
+ path2: {
12
+ component1: true,
13
+ },
14
+ path3: {
15
+ component1: true,
16
+ },
17
+ }
18
+ }
19
+ */
20
+ class RenderManager {
21
+ dependenciesMap = new Map();
22
+ hooksMap = new Map();
23
+ /**
24
+ * Registra un hook de re-render para un componente
25
+ * @param componentId - El id del componente
26
+ * @param hook - El hook de re-render
27
+ */
28
+ register(componentId, hook) {
29
+ this.hooksMap.set(componentId, hook);
30
+ }
31
+ /**
32
+ * Agrega una dependencia de path a un componente
33
+ * @param componentId - El id del componente
34
+ * @param path - El path del estado
35
+ * @param storeName - El nombre del store
36
+ */
37
+ dependsOn(componentId, path, storeName) {
38
+ // Si no existe el store, crea un nuevo mapa
39
+ if (!this.dependenciesMap.has(storeName)) {
40
+ this.dependenciesMap.set(storeName, new Map());
41
+ }
42
+ // Si no existe el path, crea un nuevo conjunto
43
+ if (!this.dependenciesMap.get(storeName)?.has(path)) {
44
+ this.dependenciesMap.get(storeName)?.set(path, new Set());
45
+ }
46
+ // Agrega el componente al conjunto de dependencias
47
+ this.dependenciesMap.get(storeName)?.get(path)?.add(componentId);
48
+ }
49
+ /**
50
+ * Actualiza los componentes que dependen de este path
51
+ * @param path - El path del estado
52
+ * @param storeName - El nombre del store
53
+ */
54
+ refresh(path, storeName) {
55
+ // Obtiene los componentes que dependen de este path
56
+ const components = this.dependenciesMap.get(storeName)?.get(path);
57
+ // Si hay componentes que dependen de este path, actualiza cada uno
58
+ if (components) {
59
+ components.forEach((componentId) => {
60
+ this.hooksMap.get(componentId)?.();
61
+ });
62
+ }
63
+ }
64
+ /**
65
+ * Elimina un componente del manager
66
+ * @param componentId - El id del componente
67
+ */
68
+ unregister(componentId) {
69
+ this.hooksMap.delete(componentId);
70
+ this.dependenciesMap.forEach((store) => {
71
+ store.forEach((path) => {
72
+ path.delete(componentId);
73
+ });
74
+ });
75
+ }
76
+ }
77
+ exports.RenderManager = RenderManager;
78
+ exports.default = new RenderManager();
@@ -0,0 +1,4 @@
1
+ export declare class StateManager {
2
+ private state;
3
+ constructor(initialState?: Record<string, any>);
4
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StateManager = void 0;
4
+ class StateManager {
5
+ state = {};
6
+ constructor(initialState = {}) {
7
+ this.state = initialState;
8
+ }
9
+ }
10
+ exports.StateManager = StateManager;
@@ -1,16 +1,15 @@
1
- import { ApiClient } from "./ApiClient";
2
- import { StoreClient } from "./StoreClient";
3
- export type NanoAppConfig = Record<string, StoreEntry>;
4
- export type StoreEntry = {
5
- type: "api" | "local";
6
- baseUrl?: string;
1
+ import { ApiStore } from "./ApiStore";
2
+ import { AppStore } from "./AppStore";
3
+ type StoreEntry = {
4
+ name: string;
5
+ type: "app" | "api";
7
6
  path?: string;
8
- data?: any;
7
+ data?: Record<string, unknown>;
9
8
  };
10
9
  export declare class StoreManager {
11
10
  private stores;
12
- constructor();
13
- getStore(name: string): ApiClient | StoreClient;
11
+ init(entries: StoreEntry[]): void;
12
+ getStore(name: string): AppStore | ApiStore;
14
13
  }
15
14
  declare const _default: StoreManager;
16
15
  export default _default;
@@ -1,43 +1,29 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.StoreManager = void 0;
7
- const path_1 = __importDefault(require("path"));
8
- const fs_1 = __importDefault(require("fs"));
9
- const ApiClient_1 = require("./ApiClient");
10
- const StoreClient_1 = require("./StoreClient");
4
+ const ApiStore_1 = require("./ApiStore");
5
+ const AppStore_1 = require("./AppStore");
11
6
  class StoreManager {
12
- stores = {};
13
- constructor() {
14
- // Carga la configuración
15
- let config = { app: { type: "local", data: {} } };
16
- try {
17
- const mod = require(path_1.default.join(process.cwd(), "nano-app.config.cjs"));
18
- config = mod?.default ?? mod;
7
+ stores = new Map();
8
+ init(entries) {
9
+ if (entries.length === 0) {
10
+ this.stores.set("app", new AppStore_1.AppStore({}));
11
+ return;
19
12
  }
20
- catch { }
21
- // Crea los stores
22
- Object.entries(config)
23
- .forEach(([name, entry]) => {
13
+ entries.forEach(entry => {
24
14
  if (entry.type === "api") {
25
- this.stores[name] = new ApiClient_1.ApiClient(entry.baseUrl ?? "/api");
15
+ this.stores.set(entry.name, new ApiStore_1.ApiStore(entry.data ?? {}, entry.name, entry.path ?? "/api"));
26
16
  }
27
17
  else {
28
- let data = {};
29
- try {
30
- data = entry.path
31
- ? JSON.parse(fs_1.default.readFileSync(path_1.default.resolve(process.cwd(), entry.path), "utf-8"))
32
- : (entry.data ?? {});
33
- }
34
- catch { }
35
- this.stores[name] = new StoreClient_1.StoreClient(data);
18
+ this.stores.set(entry.name, new AppStore_1.AppStore(entry.data ?? {}, entry.name));
36
19
  }
37
20
  });
38
21
  }
39
22
  getStore(name) {
40
- return this.stores[name];
23
+ const store = this.stores.get(name);
24
+ if (!store)
25
+ throw new Error(`Store "${name}" no encontrado.`);
26
+ return store;
41
27
  }
42
28
  }
43
29
  exports.StoreManager = StoreManager;
@@ -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
+ ];
@@ -1,17 +1,16 @@
1
- import { ReactNode } from "react";
2
- import { useRouter } from "next/navigation";
3
- import { StoreManager } from "../store/StoreManager";
4
- export declare abstract class Controller<Params = {}> {
5
- protected storeManager: StoreManager;
6
- params: Params & {
7
- children?: ReactNode;
8
- };
9
- router: ReturnType<typeof useRouter>;
10
- pathname: string | null;
11
- constructor(storeManager: StoreManager, params: Params & {
12
- children?: ReactNode;
13
- });
14
- protected getStore(name: string): import("..").StoreClient | import("..").ApiClient;
1
+ import { ReactParams } from "./createComponent";
2
+ import { ApiResponse } from "@nano-app/backend";
3
+ export declare abstract class Controller {
4
+ private componentId;
5
+ params: ReactParams;
6
+ constructor(params: ReactParams);
7
+ get<T = any>(path: string, name?: string): T;
8
+ read<T = any>(path: string, params?: {}, name?: string): Promise<ApiResponse<T>>;
9
+ set(path: string, value: any, name?: string): void;
10
+ create<T = any>(path: string, body: any, name?: string): Promise<ApiResponse<T>>;
11
+ update<T = any>(path: string, body: any, name?: string): Promise<ApiResponse<T>>;
12
+ delete<T = any>(path: string, id: any, name?: string): Promise<ApiResponse<T>>;
13
+ destroy(): void;
15
14
  onInit(): void;
16
15
  onRender(): void;
17
16
  }
@@ -1,18 +1,51 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.Controller = void 0;
7
+ const StoreManager_1 = __importDefault(require("../store/StoreManager"));
8
+ const RenderManager_1 = __importDefault(require("../store/RenderManager"));
4
9
  class Controller {
5
- storeManager;
6
- params = {};
7
- router;
8
- pathname;
9
- constructor(storeManager, params) {
10
- this.storeManager = storeManager;
10
+ componentId;
11
+ params;
12
+ // public router!: ReturnType<typeof useRouter>;
13
+ // public pathname!: string | null;
14
+ constructor(params) {
15
+ // Registra el componente para reactividad
16
+ this.componentId = Symbol();
17
+ RenderManager_1.default.register(this.componentId, params.hook || (() => { }));
18
+ // Inicializa los parámetros
11
19
  this.params = params;
20
+ // Inicializa el controller
12
21
  this.onInit();
13
22
  }
14
- getStore(name) {
15
- return this.storeManager.getStore(name);
23
+ get(path, name = 'app') {
24
+ // Registra el path como dependencia
25
+ RenderManager_1.default.dependsOn(this.componentId, path, name);
26
+ // Retorna el valor del store
27
+ return StoreManager_1.default.getStore(name)?.get(path) || undefined;
28
+ }
29
+ read(path, params = {}, name = 'api') {
30
+ // Registra el path como dependencia
31
+ RenderManager_1.default.dependsOn(this.componentId, path, "api");
32
+ // Retorna el valor de la api
33
+ return StoreManager_1.default.getStore(name)?.read(path, params);
34
+ }
35
+ set(path, value, name = 'app') {
36
+ StoreManager_1.default.getStore(name)?.set(path, value);
37
+ }
38
+ create(path, body, name = 'api') {
39
+ return StoreManager_1.default.getStore(name)?.create(path, body);
40
+ }
41
+ update(path, body, name = 'api') {
42
+ return StoreManager_1.default.getStore(name)?.update(path, body);
43
+ }
44
+ delete(path, id, name = 'api') {
45
+ return StoreManager_1.default.getStore(name)?.delete(path, id);
46
+ }
47
+ destroy() {
48
+ RenderManager_1.default.unregister(this.componentId);
16
49
  }
17
50
  onInit() { }
18
51
  onRender() { }
@@ -1,5 +1,18 @@
1
+ import { ReactNode } from "react";
1
2
  import { Controller } from "./Controller";
2
- import storeInstance from "../store/StoreManager";
3
- export type ControllerClass<C extends Controller> = new (storeManager: typeof storeInstance, params: Record<string, any>) => C;
4
- export type ViewFn<C extends Controller> = (controller: C) => React.ReactNode;
5
- export declare function createComponent<C extends Controller>(stores: string[], ControllerClass: ControllerClass<C>, view: ViewFn<C>): (params?: Record<string, any>) => React.ReactNode;
3
+ export type ReactParams = Record<string, unknown> & {
4
+ children?: ReactNode;
5
+ hook?: () => void;
6
+ };
7
+ export type CreateComponentProps<C> = {
8
+ controller?: new (params: ReactParams) => C;
9
+ view?: (controller: C) => ReactNode;
10
+ hooks?: (controller: C) => void;
11
+ };
12
+ /**
13
+ * Crea un componente reactivo que se actualiza automáticamente cuando los datos de los stores cambian.
14
+ * @param ControllerClass - Clase del controller
15
+ * @param view - Función que renderiza el componente
16
+ * @returns - Función que retorna el componente reactivo
17
+ */
18
+ export declare function createComponent<C extends Controller = Controller>({ controller, view, hooks }: CreateComponentProps<C>): (params?: ReactParams) => ReactNode;
@@ -1,24 +1,31 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.createComponent = createComponent;
7
4
  const react_1 = require("react");
8
- const navigation_1 = require("next/navigation");
9
- const StoreManager_1 = __importDefault(require("../store/StoreManager"));
10
- function createComponent(stores, ControllerClass, view) {
11
- return function (params = {}) {
12
- stores.forEach((name) => StoreManager_1.default.getStore(name)?.use());
13
- const router = (0, navigation_1.useRouter)();
14
- const pathname = (0, navigation_1.usePathname)();
15
- const ref = (0, react_1.useRef)(undefined);
16
- if (!ref.current)
17
- ref.current = new ControllerClass(StoreManager_1.default, params);
18
- const c = ref.current;
19
- c.router = router;
20
- c.pathname = pathname;
21
- c.onRender();
22
- return view(c);
5
+ const Controller_1 = require("./Controller");
6
+ class BaseController extends Controller_1.Controller {
7
+ }
8
+ const BaseView = ({ params: { children } }) => children;
9
+ /**
10
+ * Crea un componente reactivo que se actualiza automáticamente cuando los datos de los stores cambian.
11
+ * @param ControllerClass - Clase del controller
12
+ * @param view - Función que renderiza el componente
13
+ * @returns - Función que retorna el componente reactivo
14
+ */
15
+ function createComponent({ controller, view, hooks }) {
16
+ return function (params) {
17
+ // Hook para re-renderizar el componente
18
+ const [, setTick] = (0, react_1.useState)(0);
19
+ // Instancia el controller
20
+ const controllerRef = (0, react_1.useRef)();
21
+ if (!controllerRef.current) {
22
+ controllerRef.current = new (controller || BaseController)({ ...params, hook: () => setTick((t) => t + 1) });
23
+ }
24
+ // Ejecuta las hooks del usuario
25
+ if (hooks)
26
+ hooks(controllerRef.current);
27
+ // Cleanup del componente
28
+ (0, react_1.useEffect)(() => () => controllerRef.current?.destroy(), []);
29
+ return view ? view(controllerRef.current) : BaseView(controllerRef.current);
23
30
  };
24
31
  }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Resuelve un path slash-based sobre un objeto y retorna el valor en esa ruta.
3
+ * Retorna undefined de forma segura si algún segmento no existe.
4
+ *
5
+ * Ejemplo: resolvePath(state, "/user/profile/name")
6
+ */
7
+ export declare function resolvePath(obj: unknown, path: string): unknown;
8
+ /**
9
+ * Retorna un nuevo objeto con el valor en el path slash-based asignado de forma inmutable.
10
+ * Los objetos intermedios se clonan superficialmente. Los nodos intermedios faltantes se crean.
11
+ *
12
+ * Ejemplo: setPath(state, "/user/profile/name", "Alice")
13
+ */
14
+ export declare function setPath(obj: unknown, path: string, value: unknown): Record<string, unknown>;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolvePath = resolvePath;
4
+ exports.setPath = setPath;
5
+ /**
6
+ * Resuelve un path slash-based sobre un objeto y retorna el valor en esa ruta.
7
+ * Retorna undefined de forma segura si algún segmento no existe.
8
+ *
9
+ * Ejemplo: resolvePath(state, "/user/profile/name")
10
+ */
11
+ function resolvePath(obj, path) {
12
+ const segments = path.split("/").filter((s) => s !== "");
13
+ let current = obj;
14
+ for (const segment of segments) {
15
+ if (current === null || current === undefined || typeof current !== "object") {
16
+ return undefined;
17
+ }
18
+ current = current[segment];
19
+ }
20
+ return current;
21
+ }
22
+ /**
23
+ * Retorna un nuevo objeto con el valor en el path slash-based asignado de forma inmutable.
24
+ * Los objetos intermedios se clonan superficialmente. Los nodos intermedios faltantes se crean.
25
+ *
26
+ * Ejemplo: setPath(state, "/user/profile/name", "Alice")
27
+ */
28
+ function setPath(obj, path, value) {
29
+ const segments = path.split("/").filter((s) => s !== "");
30
+ const root = obj && typeof obj === "object" ? { ...obj } : {};
31
+ if (segments.length === 0)
32
+ return root;
33
+ let node = root;
34
+ for (let i = 0; i < segments.length - 1; i++) {
35
+ const key = segments[i];
36
+ const child = node[key];
37
+ const cloned = child && typeof child === "object" ? { ...child } : {};
38
+ node[key] = cloned;
39
+ node = cloned;
40
+ }
41
+ node[segments[segments.length - 1]] = value;
42
+ return root;
43
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nano-app/frontend",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "View + Controller frontend architecture for React/Next.js",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -11,8 +11,12 @@
11
11
  "types": "./dist/index.d.ts"
12
12
  }
13
13
  },
14
+ "bin":{
15
+ "generate-stores": "./bin/generate-stores.mjs"
16
+ },
14
17
  "files": [
15
- "dist"
18
+ "dist",
19
+ "bin"
16
20
  ],
17
21
  "scripts": {
18
22
  "build": "tsc",
@@ -33,7 +37,8 @@
33
37
  "next": ">=14.0.0",
34
38
  "react": ">=18.0.0",
35
39
  "react-dom": ">=18.0.0",
36
- "zustand": ">=5.0.0"
40
+ "zustand": ">=5.0.0",
41
+ "fs": "^0.0.1-security"
37
42
  },
38
43
  "devDependencies": {
39
44
  "@types/node": "^20.0.0",
@@ -43,8 +48,5 @@
43
48
  "react-dom": "^18.0.0",
44
49
  "typescript": "^5.3.0",
45
50
  "zustand": "^5.0.0"
46
- },
47
- "dependencies": {
48
- "fs": "^0.0.1-security"
49
51
  }
50
52
  }
@@ -1,16 +0,0 @@
1
- import type { ApiResponse } from "@nano-app/backend";
2
- import { StoreClient } from "../store/StoreClient";
3
- export type ApiRequest = (query: string, body?: unknown) => Promise<ApiResponse>;
4
- /**
5
- * Cliente de API que extiende StoreClient y expone CRUD.
6
- * @param baseUrl - Prefijo de todas las peticiones. Por defecto "/api".
7
- */
8
- export declare class ApiClient extends StoreClient {
9
- private baseUrl;
10
- constructor(baseUrl?: string);
11
- create: ApiRequest;
12
- read: ApiRequest;
13
- update: ApiRequest;
14
- delete: ApiRequest;
15
- private request;
16
- }
@@ -1,69 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ApiClient = void 0;
4
- const StoreClient_1 = require("../store/StoreClient");
5
- const QueryBuilder_1 = require("./QueryBuilder");
6
- const TokenHelper_1 = require("../utils/TokenHelper");
7
- const Toast_1 = require("../utils/Toast");
8
- /**
9
- * Cliente de API que extiende StoreClient y expone CRUD.
10
- * @param baseUrl - Prefijo de todas las peticiones. Por defecto "/api".
11
- */
12
- class ApiClient extends StoreClient_1.StoreClient {
13
- baseUrl;
14
- constructor(baseUrl = "/api") {
15
- super();
16
- this.baseUrl = baseUrl;
17
- }
18
- create = async (entity, body) => {
19
- return this.request("POST", entity, body);
20
- };
21
- read = async (query, params = {}) => {
22
- const path = query.split("?")[0];
23
- const response = await this.request("GET", QueryBuilder_1.QueryBuilder.build(query, params));
24
- this.set(`/${path}`, response.result);
25
- return response;
26
- };
27
- update = async (entity, body) => {
28
- return this.request("PUT", entity, body);
29
- };
30
- delete = async (entity, id) => {
31
- return this.request("DELETE", entity, id);
32
- };
33
- async request(method, path, body) {
34
- let oResponse = {
35
- result: null,
36
- success: false,
37
- message: "",
38
- warning: false,
39
- };
40
- this.set("/busyCount", (this.get("/busyCount") || 0) + 1);
41
- this.set("/busy", true);
42
- try {
43
- oResponse = await fetch(`${this.baseUrl}${path}`, {
44
- method,
45
- headers: {
46
- "Content-Type": "application/json",
47
- Authorization: `Bearer ${TokenHelper_1.TokenHelper.get()}`,
48
- },
49
- body: body ? JSON.stringify(body) : undefined,
50
- })
51
- .then((response) => response.json())
52
- .then((response) => Toast_1.Toast.apiResponse(response));
53
- }
54
- catch (error) {
55
- console.error(error);
56
- }
57
- finally {
58
- this.set("/busyCount", this.get("/busyCount") - 1);
59
- if (this.get("/busyCount") <= 0) {
60
- this.set("/busy", false);
61
- }
62
- if (method !== "GET") {
63
- this.set("/refresh", !this.get("/refresh"));
64
- }
65
- }
66
- return oResponse;
67
- }
68
- }
69
- exports.ApiClient = ApiClient;
@@ -1,8 +0,0 @@
1
- export declare class QueryBuilder {
2
- private static readonly ISO_DATE_REGEX;
3
- private static buildFilters;
4
- /**
5
- * Construye una query OData a partir de un objeto de filtros.
6
- */
7
- static build(path: string, params?: Record<string, unknown>): string;
8
- }
@@ -1,51 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.QueryBuilder = void 0;
4
- const DEFAULT_STEP_SKIP_TOP = 10;
5
- class QueryBuilder {
6
- static ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d+)?Z?)?$/;
7
- static buildFilters(filters = {}) {
8
- const filterParts = [];
9
- Object.entries(filters).forEach(([key, value]) => {
10
- if (value !== undefined && value !== null) {
11
- if (typeof value === "string") {
12
- if (QueryBuilder.ISO_DATE_REGEX.test(value)) {
13
- filterParts.push(`${key} ge ${value}`);
14
- }
15
- else {
16
- filterParts.push(`${key} contains ${value}`);
17
- }
18
- }
19
- else {
20
- filterParts.push(`${key} eq ${value}`);
21
- }
22
- }
23
- });
24
- return filterParts.length > 0 ? filterParts.join(" and ") : "";
25
- }
26
- /**
27
- * Construye una query OData a partir de un objeto de filtros.
28
- */
29
- static build(path, params = {}) {
30
- const { skip, filters, expand, orderby, top = 10, ...otherParams } = params;
31
- const queryParams = Object.entries(otherParams).map(([key, value]) => `${key}=${value}`);
32
- const filtersQuery = this.buildFilters(filters ?? {});
33
- if (filtersQuery) {
34
- queryParams.push(`filter=${filtersQuery}`);
35
- }
36
- if (expand) {
37
- queryParams.push(`expand=${expand}`);
38
- }
39
- if (orderby) {
40
- queryParams.push(`orderby=${orderby}`);
41
- }
42
- if (top) {
43
- queryParams.push(`top=${top}`);
44
- }
45
- if (skip) {
46
- queryParams.push(`skip=${skip}`);
47
- }
48
- return `${path}?${queryParams.join("&")}`;
49
- }
50
- }
51
- exports.QueryBuilder = QueryBuilder;
@@ -1,16 +0,0 @@
1
- import { usePathname, useRouter } from "next/navigation";
2
- import { ApiClient } from "../api/ApiClient";
3
- import { StoreClient } from "../store/StoreClient";
4
- export declare abstract class Controller {
5
- private storeManager;
6
- private isInitialized;
7
- protected router?: ReturnType<typeof useRouter>;
8
- protected pathname?: ReturnType<typeof usePathname>;
9
- protected onInit(): void;
10
- protected getStore(model: 'api'): ApiClient;
11
- protected getStore(model?: 'app'): StoreClient;
12
- protected getStore(model: string): ApiClient | StoreClient;
13
- params: any;
14
- deps(): any[];
15
- render(params: any): void;
16
- }
@@ -1,29 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Controller = void 0;
4
- const navigation_1 = require("next/navigation");
5
- const StoreManager_1 = require("../store/StoreManager");
6
- class Controller {
7
- storeManager = new StoreManager_1.StoreManager();
8
- isInitialized = false;
9
- router;
10
- pathname;
11
- onInit() { }
12
- getStore(model = 'app') {
13
- return this.storeManager.getStore(model);
14
- }
15
- params = {};
16
- deps() { return []; }
17
- render(params) {
18
- this.params = params;
19
- this.router = (0, navigation_1.useRouter)();
20
- this.pathname = (0, navigation_1.usePathname)();
21
- // Inicializa el controlador si no ha sido inicializado
22
- if (!this.isInitialized) {
23
- this.isInitialized = true;
24
- this.onInit();
25
- this.storeManager.init();
26
- }
27
- }
28
- }
29
- exports.Controller = Controller;