@nano-app/backend 0.6.5 → 0.7.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.
@@ -1,60 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.QueryBuilder = void 0;
4
- const OPERATORS = {
5
- eq: (f, v) => ({ [f]: v }),
6
- ne: (f, v) => ({ [f]: { not: v } }),
7
- ge: (f, v) => ({ [f]: { gte: v } }),
8
- le: (f, v) => ({ [f]: { lte: v } }),
9
- contains: (f, v) => ({ [f]: { contains: v, mode: 'insensitive' } }),
10
- startswith: (f, v) => ({ [f]: { startsWith: v, mode: 'insensitive' } }),
11
- endswith: (f, v) => ({ [f]: { endsWith: v, mode: 'insensitive' } }),
12
- };
13
- function parseValue(value) {
14
- if (!isNaN(Number(value)))
15
- return Number(value);
16
- if (value === 'true')
17
- return true;
18
- if (value === 'false')
19
- return false;
20
- return value;
21
- }
22
- function parseExpression(expr) {
23
- const [field, op, ...rest] = expr.trim().split(' ');
24
- if (!OPERATORS[op])
25
- throw { message: `Operador '${op}' no soportado` };
26
- return OPERATORS[op](field, parseValue(rest.join(' ')));
27
- }
28
- function buildFilter(filter) {
29
- if (!filter)
30
- return {};
31
- if (filter.includes(' or '))
32
- return { OR: filter.split(' or ').map(parseExpression) };
33
- if (filter.includes(' and '))
34
- return { AND: filter.split(' and ').map(parseExpression) };
35
- return parseExpression(filter);
36
- }
37
- function buildExpand(expand) {
38
- return expand?.split(',').reduce((acc, key) => ({ ...acc, [key]: true }), {});
39
- }
40
- function buildOrderBy(orderby) {
41
- if (!orderby)
42
- return undefined;
43
- const [field, direction] = orderby.split(' ');
44
- if (direction !== 'asc' && direction !== 'desc')
45
- return undefined;
46
- // Soporta campos anidados: "subscription.price desc" → { subscription: { price: 'desc' } }
47
- return field.split('.').reduceRight((acc, part) => ({ [part]: acc }), direction);
48
- }
49
- class QueryBuilder {
50
- static build(query) {
51
- return {
52
- where: buildFilter(query.filter),
53
- include: buildExpand(query.expand),
54
- take: query.top ? Number(query.top) : undefined,
55
- skip: query.skip ? Number(query.skip) : undefined,
56
- orderBy: buildOrderBy(query.orderby),
57
- };
58
- }
59
- }
60
- exports.QueryBuilder = QueryBuilder;
@@ -1,12 +0,0 @@
1
- import "dotenv/config";
2
- declare const Prisma: any;
3
- type GeneratedPrismaClient = typeof Prisma;
4
- export type AppModels = Omit<GeneratedPrismaClient, `$${string}` | symbol>;
5
- /** Cliente Prisma. getModel retorna el tipo correcto según el nombre del modelo. */
6
- export declare class PrismaClient {
7
- private prisma;
8
- getModel<K extends keyof AppModels>(entityName: K): AppModels[K];
9
- /** Para consultas que comparan columnas u otras condiciones no soportadas en findMany */
10
- queryRaw<T = unknown>(strings: TemplateStringsArray, ...values: any[]): Promise<T>;
11
- }
12
- export {};
@@ -1,34 +0,0 @@
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.PrismaClient = void 0;
7
- require("dotenv/config");
8
- const path_1 = __importDefault(require("path"));
9
- const adapter_pg_1 = require("@prisma/adapter-pg");
10
- // Crea el adaptador a la base de datos
11
- if (!process.env.DATABASE_URL) {
12
- throw { message: 'DATABASE_URL no está configurada' };
13
- }
14
- const adapter = new adapter_pg_1.PrismaPg({
15
- connectionString: process.env.DATABASE_URL
16
- });
17
- // Carga el cliente generado por el binario
18
- const clientPath = path_1.default.join(process.cwd(), "node_modules/.prisma/prisma-client/client");
19
- const client = require(clientPath);
20
- const Prisma = client.PrismaClient ?? client.default?.PrismaClient ?? client;
21
- // Crea una instancia de Prisma
22
- const prismaInstance = new Prisma({ adapter });
23
- /** Cliente Prisma. getModel retorna el tipo correcto según el nombre del modelo. */
24
- class PrismaClient {
25
- prisma = prismaInstance;
26
- getModel(entityName) {
27
- return this.prisma[entityName];
28
- }
29
- /** Para consultas que comparan columnas u otras condiciones no soportadas en findMany */
30
- async queryRaw(strings, ...values) {
31
- return this.prisma.$queryRaw(strings, ...values);
32
- }
33
- }
34
- exports.PrismaClient = PrismaClient;
@@ -1,6 +0,0 @@
1
- export type ApiResponse<T = any> = {
2
- success?: boolean;
3
- result?: T;
4
- message?: string;
5
- warning?: boolean;
6
- };
package/dist/types/api.js DELETED
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,29 +0,0 @@
1
- import type { Endpoint } from "../index";
2
- import type { ErrorRequestHandler, RequestHandler } from "express";
3
- import type { Options } from "express-rate-limit";
4
- export type NanoAppConfig = {
5
- endpoints: Endpoint[];
6
- enableEntities?: boolean;
7
- errorMiddleware?: ErrorRequestHandler;
8
- middlewares?: RequestHandler[];
9
- port?: number;
10
- rateLimit?: Partial<Options>;
11
- expressConfig?: Partial<Express.Application>;
12
- setters?: Record<string, any>;
13
- morgan?: {
14
- tokens?: Record<string, any>;
15
- format?: string;
16
- };
17
- apiKeys?: {
18
- /** Habilita los endpoints y middleware de API keys. Por defecto: false */
19
- enabled: boolean;
20
- /** Ruta base para los endpoints de gestión. Por defecto: /api-keys */
21
- path?: string;
22
- /**
23
- * Middleware de autenticación custom (ej: JWT de usuario).
24
- * Si se provee, se ejecuta primero. Si falla, se intenta validar con API key.
25
- * Si ambos fallan, retorna 401.
26
- */
27
- middleware?: RequestHandler;
28
- };
29
- };
package/dist/types/app.js DELETED
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,8 +0,0 @@
1
- export type QueryParams = {
2
- id?: string;
3
- filter?: string;
4
- expand?: string;
5
- top?: string;
6
- skip?: string;
7
- orderby?: string;
8
- };
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,6 +0,0 @@
1
- import type { ApiResponse } from "../index";
2
- export declare class Formatter {
3
- static price(value: number): string;
4
- static logDate(date?: Date): string;
5
- static sanitizeAndParse(result: ApiResponse): ApiResponse;
6
- }
@@ -1,31 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Formatter = void 0;
4
- class Formatter {
5
- static price(value) {
6
- return `$${new Intl.NumberFormat("de-DE", { maximumFractionDigits: 0 }).format(value || 0)}`;
7
- }
8
- static logDate(date = new Date()) {
9
- return new Intl.DateTimeFormat("es-ES", {
10
- year: "2-digit",
11
- month: "2-digit",
12
- day: "2-digit",
13
- hour: "2-digit",
14
- minute: "2-digit",
15
- second: "2-digit",
16
- }).format(date);
17
- }
18
- static sanitizeAndParse(result) {
19
- const jsonString = JSON.stringify(result);
20
- // La expresión regular busca exactamente la clave "password": "cualquier_valor"
21
- // donde:
22
- // - "password" se encuentra entre comillas.
23
- // - Puede haber espacios opcionales alrededor de los dos puntos.
24
- // - El valor se asume estar entre comillas.
25
- const regex = /("password"\s*:\s*)"[^"]*"/gi;
26
- // Reemplazamos el valor por el literal JSON null (sin comillas)
27
- const sanitizedString = jsonString.replace(regex, '$1null');
28
- return JSON.parse(sanitizedString);
29
- }
30
- }
31
- exports.Formatter = Formatter;