@nano-app/frontend 0.1.0 → 0.3.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.
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -9
- package/dist/store/ApiClient.d.ts +12 -0
- package/dist/store/ApiClient.js +51 -0
- package/dist/store/StoreClient.d.ts +0 -14
- package/dist/store/StoreClient.js +8 -33
- package/dist/store/StoreManager.d.ts +8 -3
- package/dist/store/StoreManager.js +19 -36
- package/dist/ui/Controller.d.ts +9 -6
- package/dist/ui/Controller.js +10 -2
- package/dist/ui/createComponent.d.ts +2 -8
- package/dist/ui/createComponent.js +7 -23
- package/dist/utils/QueryBuilder.d.ts +19 -0
- package/dist/utils/QueryBuilder.js +29 -0
- package/package.json +19 -17
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./api/QueryBuilder";
|
|
3
|
-
export { default as StoreManager } from "./store/StoreManager";
|
|
1
|
+
export * from "./store/ApiClient";
|
|
4
2
|
export * from "./store/StoreClient";
|
|
5
|
-
export * from "./
|
|
3
|
+
export * from "./store/StoreManager";
|
|
6
4
|
export * from "./ui/Controller";
|
|
5
|
+
export * from "./ui/createComponent";
|
|
6
|
+
export * from "./utils/QueryBuilder";
|
|
7
7
|
export * from "./utils/Toast";
|
|
8
8
|
export * from "./utils/TokenHelper";
|
|
9
9
|
export type { ApiResponse } from "@nano-app/backend";
|
package/dist/index.js
CHANGED
|
@@ -13,17 +13,12 @@ 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
|
-
};
|
|
19
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports
|
|
21
|
-
__exportStar(require("./api/ApiClient"), exports);
|
|
22
|
-
__exportStar(require("./api/QueryBuilder"), exports);
|
|
23
|
-
var StoreManager_1 = require("./store/StoreManager");
|
|
24
|
-
Object.defineProperty(exports, "StoreManager", { enumerable: true, get: function () { return __importDefault(StoreManager_1).default; } });
|
|
17
|
+
__exportStar(require("./store/ApiClient"), exports);
|
|
25
18
|
__exportStar(require("./store/StoreClient"), exports);
|
|
26
|
-
__exportStar(require("./
|
|
19
|
+
__exportStar(require("./store/StoreManager"), exports);
|
|
27
20
|
__exportStar(require("./ui/Controller"), exports);
|
|
21
|
+
__exportStar(require("./ui/createComponent"), exports);
|
|
22
|
+
__exportStar(require("./utils/QueryBuilder"), exports);
|
|
28
23
|
__exportStar(require("./utils/Toast"), exports);
|
|
29
24
|
__exportStar(require("./utils/TokenHelper"), exports);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ApiResponse } from "@nano-app/backend";
|
|
2
|
+
import { StoreClient } from "./StoreClient";
|
|
3
|
+
export type ApiRequest = (query: string, body?: unknown) => Promise<ApiResponse>;
|
|
4
|
+
export declare class ApiClient extends StoreClient {
|
|
5
|
+
private baseUrl;
|
|
6
|
+
constructor(baseUrl?: string);
|
|
7
|
+
create: ApiRequest;
|
|
8
|
+
read: ApiRequest;
|
|
9
|
+
update: ApiRequest;
|
|
10
|
+
delete: ApiRequest;
|
|
11
|
+
private request;
|
|
12
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApiClient = void 0;
|
|
4
|
+
const StoreClient_1 = require("./StoreClient");
|
|
5
|
+
const QueryBuilder_1 = require("../utils/QueryBuilder");
|
|
6
|
+
const TokenHelper_1 = require("../utils/TokenHelper");
|
|
7
|
+
const Toast_1 = require("../utils/Toast");
|
|
8
|
+
class ApiClient extends StoreClient_1.StoreClient {
|
|
9
|
+
baseUrl;
|
|
10
|
+
constructor(baseUrl = "/api") {
|
|
11
|
+
super();
|
|
12
|
+
this.baseUrl = baseUrl;
|
|
13
|
+
}
|
|
14
|
+
create = (entity, body) => this.request("POST", entity, body);
|
|
15
|
+
read = async (query, params = {}) => {
|
|
16
|
+
const path = query.split("?")[0];
|
|
17
|
+
const response = await this.request("GET", QueryBuilder_1.QueryBuilder.build(query, params));
|
|
18
|
+
this.set(`/${path}`, response.result);
|
|
19
|
+
return response;
|
|
20
|
+
};
|
|
21
|
+
update = (entity, body) => this.request("PUT", entity, body);
|
|
22
|
+
delete = (entity, id) => this.request("DELETE", entity, id);
|
|
23
|
+
async request(method, path, body) {
|
|
24
|
+
let oResponse = { result: null, success: false, message: "", warning: false };
|
|
25
|
+
this.set("/busyCount", (this.get("/busyCount") || 0) + 1);
|
|
26
|
+
this.set("/busy", true);
|
|
27
|
+
try {
|
|
28
|
+
oResponse = await fetch(`${this.baseUrl}${path}`, {
|
|
29
|
+
method,
|
|
30
|
+
headers: {
|
|
31
|
+
"Content-Type": "application/json",
|
|
32
|
+
Authorization: `Bearer ${TokenHelper_1.TokenHelper.get()}`,
|
|
33
|
+
},
|
|
34
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
35
|
+
})
|
|
36
|
+
.then((res) => res.json())
|
|
37
|
+
.then((res) => Toast_1.Toast.apiResponse(res));
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
console.error(error);
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
const remaining = this.get("/busyCount") - 1;
|
|
44
|
+
this.set("/busyCount", remaining);
|
|
45
|
+
if (remaining < 1)
|
|
46
|
+
this.set("/busy", false);
|
|
47
|
+
}
|
|
48
|
+
return oResponse;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.ApiClient = ApiClient;
|
|
@@ -1,25 +1,11 @@
|
|
|
1
1
|
export type StoreData = Record<string, any>;
|
|
2
|
-
/**
|
|
3
|
-
* Clase base para manejar el estado de Zustand
|
|
4
|
-
* Zustand solo almacena valores, los métodos se ejecutan desde la clase
|
|
5
|
-
*/
|
|
6
2
|
export declare class StoreClient {
|
|
7
3
|
private getStore;
|
|
8
4
|
private setFn;
|
|
9
5
|
private getFn;
|
|
10
6
|
constructor(initialData?: StoreData);
|
|
11
|
-
/**
|
|
12
|
-
* Ejecuta el hook para suscribirse al store (reactividad)
|
|
13
|
-
*/
|
|
14
7
|
use: () => StoreData;
|
|
15
|
-
/**
|
|
16
|
-
* Setter y Getter del store
|
|
17
|
-
*/
|
|
18
8
|
set(path: string, value: any): void;
|
|
19
9
|
get(path: string): any;
|
|
20
|
-
/**
|
|
21
|
-
* Maneja el estado (Set o Get) navegando por el path
|
|
22
|
-
* @private
|
|
23
|
-
*/
|
|
24
10
|
private manageState;
|
|
25
11
|
}
|
|
@@ -2,14 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StoreClient = void 0;
|
|
4
4
|
const zustand_1 = require("zustand");
|
|
5
|
-
/**
|
|
6
|
-
* Clase base para manejar el estado de Zustand
|
|
7
|
-
* Zustand solo almacena valores, los métodos se ejecutan desde la clase
|
|
8
|
-
*/
|
|
9
5
|
class StoreClient {
|
|
10
6
|
getStore;
|
|
11
|
-
setFn
|
|
12
|
-
getFn
|
|
7
|
+
setFn;
|
|
8
|
+
getFn;
|
|
13
9
|
constructor(initialData = {}) {
|
|
14
10
|
this.getStore = (0, zustand_1.create)()((set, get) => {
|
|
15
11
|
this.setFn = set;
|
|
@@ -17,48 +13,27 @@ class StoreClient {
|
|
|
17
13
|
return initialData;
|
|
18
14
|
});
|
|
19
15
|
}
|
|
20
|
-
/**
|
|
21
|
-
* Ejecuta el hook para suscribirse al store (reactividad)
|
|
22
|
-
*/
|
|
23
16
|
use = () => this.getStore();
|
|
24
|
-
/**
|
|
25
|
-
* Setter y Getter del store
|
|
26
|
-
*/
|
|
27
17
|
set(path, value) {
|
|
28
|
-
if (!this.setFn)
|
|
29
|
-
return;
|
|
30
18
|
const { oNewState } = this.manageState(path, true, value);
|
|
31
19
|
this.setFn((state) => ({ ...state, ...oNewState }));
|
|
32
20
|
}
|
|
33
21
|
get(path) {
|
|
34
|
-
if (!this.getFn)
|
|
35
|
-
return undefined;
|
|
36
22
|
const { value } = this.manageState(path);
|
|
37
23
|
return value;
|
|
38
24
|
}
|
|
39
|
-
/**
|
|
40
|
-
* Maneja el estado (Set o Get) navegando por el path
|
|
41
|
-
* @private
|
|
42
|
-
*/
|
|
43
25
|
manageState(sPath, isSet = false, value) {
|
|
44
|
-
// Obtiene el path y el último valor
|
|
45
26
|
const aPath = sPath.split("/").filter(s => s !== "");
|
|
46
27
|
const lastProp = aPath.pop() || "";
|
|
47
|
-
// Valida si es el path inicial (Utiliza todo el objeto)
|
|
48
28
|
const oNewState = aPath.length === 0
|
|
49
29
|
? this.getFn()
|
|
50
|
-
:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}, this.getFn());
|
|
57
|
-
// Setea el nuevo valor si debe
|
|
58
|
-
if (isSet) {
|
|
30
|
+
: aPath.reduce((oObject, sKey) => {
|
|
31
|
+
if (!oObject[sKey])
|
|
32
|
+
oObject[sKey] = {};
|
|
33
|
+
return oObject[sKey];
|
|
34
|
+
}, this.getFn());
|
|
35
|
+
if (isSet)
|
|
59
36
|
oNewState[lastProp] = value;
|
|
60
|
-
}
|
|
61
|
-
// Retorna el nuevo estado y el valor de la property enviada
|
|
62
37
|
return { oNewState, value: lastProp ? oNewState[lastProp] : oNewState };
|
|
63
38
|
}
|
|
64
39
|
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { ApiClient } from "
|
|
1
|
+
import { ApiClient } from "./ApiClient";
|
|
2
2
|
import { StoreClient } from "./StoreClient";
|
|
3
|
-
export type
|
|
3
|
+
export type NanoAppConfig = Record<string, StoreEntry>;
|
|
4
|
+
export type StoreEntry = {
|
|
5
|
+
type: "api" | "local";
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
path?: string;
|
|
8
|
+
data?: any;
|
|
9
|
+
};
|
|
4
10
|
export declare class StoreManager {
|
|
5
11
|
private stores;
|
|
6
12
|
constructor();
|
|
7
|
-
addStore(name: string, store: ApiClient | StoreClient): void;
|
|
8
13
|
getStore(name: string): ApiClient | StoreClient;
|
|
9
14
|
}
|
|
10
15
|
declare const _default: StoreManager;
|
|
@@ -5,54 +5,37 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.StoreManager = void 0;
|
|
7
7
|
const path_1 = __importDefault(require("path"));
|
|
8
|
-
const
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const ApiClient_1 = require("./ApiClient");
|
|
9
10
|
const StoreClient_1 = require("./StoreClient");
|
|
10
|
-
let userConfig = {};
|
|
11
|
-
try {
|
|
12
|
-
// Carga nano-app.config.cjs desde la raíz del proyecto del usuario.
|
|
13
|
-
// .cjs es CommonJS puro — Node.js lo ejecuta sincrónicamente sin compilador.
|
|
14
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
15
|
-
const mod = require(path_1.default.join(process.cwd(), "nano-app.config.cjs"));
|
|
16
|
-
userConfig = mod?.default ?? mod;
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
// sin config → el manager empieza vacío
|
|
20
|
-
}
|
|
21
|
-
function readJsonPath(filePath) {
|
|
22
|
-
try {
|
|
23
|
-
// fs solo existe en Node.js — en el browser este bloque nunca se ejecuta
|
|
24
|
-
// porque el StoreManager ya fue inicializado en el servidor
|
|
25
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
26
|
-
const fs = require("fs");
|
|
27
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
28
|
-
const path = require("path");
|
|
29
|
-
const abs = path.resolve(process.cwd(), filePath);
|
|
30
|
-
return JSON.parse(fs.readFileSync(abs, "utf-8"));
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
return {};
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
11
|
class StoreManager {
|
|
37
12
|
stores = {};
|
|
38
13
|
constructor() {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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;
|
|
19
|
+
}
|
|
20
|
+
catch { }
|
|
21
|
+
// Crea los stores
|
|
22
|
+
Object.entries(config)
|
|
23
|
+
.forEach(([name, entry]) => {
|
|
42
24
|
if (entry.type === "api") {
|
|
43
25
|
this.stores[name] = new ApiClient_1.ApiClient(entry.baseUrl ?? "/api");
|
|
44
26
|
}
|
|
45
27
|
else {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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 { }
|
|
49
35
|
this.stores[name] = new StoreClient_1.StoreClient(data);
|
|
50
36
|
}
|
|
51
37
|
});
|
|
52
38
|
}
|
|
53
|
-
addStore(name, store) {
|
|
54
|
-
this.stores[name] = store;
|
|
55
|
-
}
|
|
56
39
|
getStore(name) {
|
|
57
40
|
return this.stores[name];
|
|
58
41
|
}
|
package/dist/ui/Controller.d.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { StoreClient } from "../store/StoreClient";
|
|
2
|
+
import { useRouter } from "next/navigation";
|
|
3
|
+
import { StoreManager } from "../store/StoreManager";
|
|
5
4
|
export declare abstract class Controller<Params = {}> {
|
|
6
|
-
|
|
7
|
-
pathname: ReturnType<typeof usePathname>;
|
|
5
|
+
protected storeManager: StoreManager;
|
|
8
6
|
params: Params & {
|
|
9
7
|
children?: ReactNode;
|
|
10
8
|
};
|
|
11
|
-
|
|
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;
|
|
12
15
|
onInit(): void;
|
|
13
16
|
onRender(): void;
|
|
14
17
|
}
|
package/dist/ui/Controller.js
CHANGED
|
@@ -2,10 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Controller = void 0;
|
|
4
4
|
class Controller {
|
|
5
|
+
storeManager;
|
|
6
|
+
params = {};
|
|
5
7
|
router;
|
|
6
8
|
pathname;
|
|
7
|
-
params
|
|
8
|
-
|
|
9
|
+
constructor(storeManager, params) {
|
|
10
|
+
this.storeManager = storeManager;
|
|
11
|
+
this.params = params;
|
|
12
|
+
this.onInit();
|
|
13
|
+
}
|
|
14
|
+
getStore(name) {
|
|
15
|
+
return this.storeManager.getStore(name);
|
|
16
|
+
}
|
|
9
17
|
onInit() { }
|
|
10
18
|
onRender() { }
|
|
11
19
|
}
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { Controller } from "./Controller";
|
|
2
|
-
|
|
2
|
+
import storeInstance from "../store/StoreManager";
|
|
3
|
+
export type ControllerClass<C extends Controller> = new (storeManager: typeof storeInstance, params: Record<string, any>) => C;
|
|
3
4
|
export type ViewFn<C extends Controller> = (controller: C) => React.ReactNode;
|
|
4
|
-
/**
|
|
5
|
-
* Crea un componente React uniendo stores, controller y view.
|
|
6
|
-
*
|
|
7
|
-
* @param stores - Nombres de los stores a los que se suscribe el componente.
|
|
8
|
-
* @param ControllerClass - Clase del controller (se instancia una vez al montar).
|
|
9
|
-
* @param view - Función que recibe la instancia del controller y retorna JSX.
|
|
10
|
-
*/
|
|
11
5
|
export declare function createComponent<C extends Controller>(stores: string[], ControllerClass: ControllerClass<C>, view: ViewFn<C>): (params?: Record<string, any>) => React.ReactNode;
|
|
@@ -7,33 +7,17 @@ exports.createComponent = createComponent;
|
|
|
7
7
|
const react_1 = require("react");
|
|
8
8
|
const navigation_1 = require("next/navigation");
|
|
9
9
|
const StoreManager_1 = __importDefault(require("../store/StoreManager"));
|
|
10
|
-
/**
|
|
11
|
-
* Crea un componente React uniendo stores, controller y view.
|
|
12
|
-
*
|
|
13
|
-
* @param stores - Nombres de los stores a los que se suscribe el componente.
|
|
14
|
-
* @param ControllerClass - Clase del controller (se instancia una vez al montar).
|
|
15
|
-
* @param view - Función que recibe la instancia del controller y retorna JSX.
|
|
16
|
-
*/
|
|
17
10
|
function createComponent(stores, ControllerClass, view) {
|
|
18
11
|
return function (params = {}) {
|
|
19
|
-
// Suscribe reactivamente a cada store declarado — Zustand re-renderiza cuando cambian
|
|
20
12
|
stores.forEach((name) => StoreManager_1.default.getStore(name)?.use());
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
ref.current.
|
|
26
|
-
}
|
|
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);
|
|
27
18
|
const c = ref.current;
|
|
28
|
-
|
|
29
|
-
c.
|
|
30
|
-
c.pathname = (0, navigation_1.usePathname)();
|
|
31
|
-
c.params = params;
|
|
32
|
-
// Inyecta el mapa de stores en cada render para que los métodos lean valores frescos
|
|
33
|
-
stores.forEach((name) => {
|
|
34
|
-
c.store[name] = StoreManager_1.default.getStore(name);
|
|
35
|
-
});
|
|
36
|
-
// Ejecuta onRender en cada render
|
|
19
|
+
c.router = router;
|
|
20
|
+
c.pathname = pathname;
|
|
37
21
|
c.onRender();
|
|
38
22
|
return view(c);
|
|
39
23
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
type Filter = {
|
|
2
|
+
op: string;
|
|
3
|
+
value: any;
|
|
4
|
+
};
|
|
5
|
+
export type Filters = {
|
|
6
|
+
and?: boolean;
|
|
7
|
+
filters?: Record<string, Filter>;
|
|
8
|
+
};
|
|
9
|
+
export type QueryParams = {
|
|
10
|
+
skip?: number;
|
|
11
|
+
top?: number;
|
|
12
|
+
filters?: Filters;
|
|
13
|
+
expand?: string;
|
|
14
|
+
orderby?: string;
|
|
15
|
+
};
|
|
16
|
+
export declare class QueryBuilder {
|
|
17
|
+
static build(path: string, params?: QueryParams): string;
|
|
18
|
+
}
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QueryBuilder = void 0;
|
|
4
|
+
function buildFilters(filters) {
|
|
5
|
+
if (!filters)
|
|
6
|
+
return "";
|
|
7
|
+
return Object.entries(filters.filters ?? {})
|
|
8
|
+
.map(([key, { op, value }]) => `${key} ${op} ${value}`)
|
|
9
|
+
.join(filters.and ? " and " : " or ");
|
|
10
|
+
}
|
|
11
|
+
class QueryBuilder {
|
|
12
|
+
static build(path, params = {}) {
|
|
13
|
+
const { skip, filters, expand, orderby, top } = params;
|
|
14
|
+
const queryParams = [];
|
|
15
|
+
const filtersQuery = buildFilters(filters);
|
|
16
|
+
if (filtersQuery)
|
|
17
|
+
queryParams.push(`filter=${filtersQuery}`);
|
|
18
|
+
if (expand)
|
|
19
|
+
queryParams.push(`expand=${expand}`);
|
|
20
|
+
if (orderby)
|
|
21
|
+
queryParams.push(`orderby=${orderby}`);
|
|
22
|
+
if (top != null)
|
|
23
|
+
queryParams.push(`top=${top}`);
|
|
24
|
+
if (skip != null)
|
|
25
|
+
queryParams.push(`skip=${skip}`);
|
|
26
|
+
return queryParams.length ? `${path}?${queryParams.join("&")}` : path;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.QueryBuilder = QueryBuilder;
|
package/package.json
CHANGED
|
@@ -1,40 +1,39 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nano-app/frontend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "View + Controller frontend architecture for React/Next.js",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": {
|
|
9
|
+
"import": "./dist/index.js",
|
|
9
10
|
"require": "./dist/index.js",
|
|
10
11
|
"types": "./dist/index.d.ts"
|
|
11
|
-
},
|
|
12
|
-
"./plugin": {
|
|
13
|
-
"require": "./dist/plugin/index.js",
|
|
14
|
-
"types": "./dist/plugin/index.d.ts"
|
|
15
12
|
}
|
|
16
13
|
},
|
|
17
|
-
"files": [
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
18
17
|
"scripts": {
|
|
19
18
|
"build": "tsc",
|
|
20
|
-
"
|
|
19
|
+
"publish": "npm run build && npm publish --access public"
|
|
21
20
|
},
|
|
22
|
-
"keywords": [
|
|
21
|
+
"keywords": [
|
|
22
|
+
"architecture",
|
|
23
|
+
"typescript",
|
|
24
|
+
"react",
|
|
25
|
+
"next",
|
|
26
|
+
"controller",
|
|
27
|
+
"view"
|
|
28
|
+
],
|
|
23
29
|
"author": "Cristian Serrano",
|
|
24
30
|
"license": "MIT",
|
|
25
|
-
"repository": {
|
|
26
|
-
"type": "git",
|
|
27
|
-
"url": "git+https://github.com/Nano-Nathan/nano-app.git"
|
|
28
|
-
},
|
|
29
31
|
"peerDependencies": {
|
|
32
|
+
"@nano-app/backend": "file:../backend",
|
|
30
33
|
"next": ">=14.0.0",
|
|
31
34
|
"react": ">=18.0.0",
|
|
32
35
|
"react-dom": ">=18.0.0",
|
|
33
|
-
"zustand": ">=5.0.0"
|
|
34
|
-
"@nano-app/backend": "file:../backend"
|
|
35
|
-
},
|
|
36
|
-
"dependencies": {
|
|
37
|
-
"jiti": "^1.21.0"
|
|
36
|
+
"zustand": ">=5.0.0"
|
|
38
37
|
},
|
|
39
38
|
"devDependencies": {
|
|
40
39
|
"@types/node": "^20.0.0",
|
|
@@ -44,5 +43,8 @@
|
|
|
44
43
|
"react-dom": "^18.0.0",
|
|
45
44
|
"typescript": "^5.3.0",
|
|
46
45
|
"zustand": "^5.0.0"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"fs": "^0.0.1-security"
|
|
47
49
|
}
|
|
48
50
|
}
|