@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.
- package/bin/generate-stores.mjs +128 -0
- package/dist/auto-register.d.ts +6 -0
- package/dist/auto-register.js +9 -0
- package/dist/auto-register.mjs +310 -0
- package/dist/auto-register.ts +336 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +12 -2
- package/dist/state/RenderManager.d.ts +47 -0
- package/dist/state/RenderManager.js +78 -0
- package/dist/store/{ApiClient.d.ts → ApiStore.d.ts} +4 -3
- package/dist/store/{ApiClient.js → ApiStore.js} +10 -10
- package/dist/store/AppStore.d.ts +25 -0
- package/dist/store/AppStore.js +59 -0
- package/dist/store/RenderManager.d.ts +47 -0
- package/dist/store/RenderManager.js +78 -0
- package/dist/store/StateManager.d.ts +4 -0
- package/dist/store/StateManager.js +10 -0
- package/dist/store/StoreManager.d.ts +8 -9
- package/dist/store/StoreManager.js +14 -28
- package/dist/store/stores.d.ts +6 -0
- package/dist/store/stores.js +9 -0
- package/dist/ui/Controller.d.ts +13 -14
- package/dist/ui/Controller.js +41 -8
- package/dist/ui/createComponent.d.ts +17 -4
- package/dist/ui/createComponent.js +25 -18
- package/dist/utils/pathUtils.d.ts +14 -0
- package/dist/utils/pathUtils.js +43 -0
- package/package.json +8 -6
- package/dist/api/ApiClient.d.ts +0 -16
- package/dist/api/ApiClient.js +0 -69
- package/dist/api/QueryBuilder.d.ts +0 -8
- package/dist/api/QueryBuilder.js +0 -51
- package/dist/components/Controller.d.ts +0 -16
- package/dist/components/Controller.js +0 -29
- package/dist/config/index.d.ts +0 -21
- package/dist/config/index.js +0 -10
- package/dist/hooks/useComponent.d.ts +0 -8
- package/dist/hooks/useComponent.js +0 -10
- package/dist/plugin/index.d.ts +0 -11
- package/dist/plugin/index.js +0 -134
- package/dist/store/StoreClient.d.ts +0 -11
- package/dist/store/StoreClient.js +0 -40
- package/dist/store/bootstrapApp.d.ts +0 -19
- package/dist/store/bootstrapApp.js +0 -25
- package/dist/store/setStores.d.ts +0 -8
- package/dist/store/setStores.js +0 -23
- package/dist/types/api.d.ts +0 -7
- package/dist/types/api.js +0 -2
- package/dist/ui/Component.d.ts +0 -4
- package/dist/ui/Component.js +0 -49
- package/dist/ui/StoreProvider.d.ts +0 -18
- package/dist/ui/StoreProvider.js +0 -62
- package/dist/ui/defineController.d.ts +0 -23
- package/dist/ui/defineController.js +0 -14
- package/dist/ui/defineView.d.ts +0 -3
- package/dist/ui/defineView.js +0 -44
- package/dist/ui/definers.d.ts +0 -1
- package/dist/ui/definers.js +0 -59
- package/dist/ui/useComponent.d.ts +0 -2
- 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();
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
type: "
|
|
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?:
|
|
7
|
+
data?: Record<string, unknown>;
|
|
9
8
|
};
|
|
10
9
|
export declare class StoreManager {
|
|
11
10
|
private stores;
|
|
12
|
-
|
|
13
|
-
getStore(name: string):
|
|
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
|
|
8
|
-
const
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
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
|
|
15
|
+
this.stores.set(entry.name, new ApiStore_1.ApiStore(entry.data ?? {}, entry.name, entry.path ?? "/api"));
|
|
26
16
|
}
|
|
27
17
|
else {
|
|
28
|
-
|
|
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
|
-
|
|
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;
|
package/dist/ui/Controller.d.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
params:
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
}
|
package/dist/ui/Controller.js
CHANGED
|
@@ -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
|
-
|
|
6
|
-
params
|
|
7
|
-
router
|
|
8
|
-
pathname;
|
|
9
|
-
constructor(
|
|
10
|
-
|
|
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
|
-
|
|
15
|
-
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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.
|
|
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
|
}
|
package/dist/api/ApiClient.d.ts
DELETED
|
@@ -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
|
-
}
|
package/dist/api/ApiClient.js
DELETED
|
@@ -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;
|
package/dist/api/QueryBuilder.js
DELETED
|
@@ -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;
|