@nano-app/backend 0.6.5 → 0.7.1
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/LICENSE +21 -0
- package/README.md +233 -0
- package/build/index.d.ts +150 -0
- package/build/index.js +544 -0
- package/build/nano-app.js +41 -0
- package/package.json +67 -27
- package/dist/app.d.ts +0 -9
- package/dist/app.js +0 -74
- package/dist/auth/ApiKeys.d.ts +0 -25
- package/dist/auth/ApiKeys.js +0 -146
- package/dist/auth/ApiKeysEndpoint.d.ts +0 -19
- package/dist/auth/ApiKeysEndpoint.js +0 -36
- package/dist/http/Endpoint.d.ts +0 -17
- package/dist/http/Endpoint.js +0 -59
- package/dist/http/Router.d.ts +0 -6
- package/dist/http/Router.js +0 -20
- package/dist/index.d.ts +0 -12
- package/dist/index.js +0 -28
- package/dist/odata/Entities.d.ts +0 -10
- package/dist/odata/Entities.js +0 -52
- package/dist/odata/QueryBuilder.d.ts +0 -10
- package/dist/odata/QueryBuilder.js +0 -60
- package/dist/prisma/Client.d.ts +0 -12
- package/dist/prisma/Client.js +0 -34
- package/dist/types/api.d.ts +0 -6
- package/dist/types/api.js +0 -2
- package/dist/types/app.d.ts +0 -29
- package/dist/types/app.js +0 -2
- package/dist/types/odata.d.ts +0 -8
- package/dist/types/odata.js +0 -2
- package/dist/utils/Formatter.d.ts +0 -6
- package/dist/utils/Formatter.js +0 -31
|
@@ -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;
|
package/dist/prisma/Client.d.ts
DELETED
|
@@ -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 {};
|
package/dist/prisma/Client.js
DELETED
|
@@ -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;
|
package/dist/types/api.d.ts
DELETED
package/dist/types/api.js
DELETED
package/dist/types/app.d.ts
DELETED
|
@@ -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
package/dist/types/odata.d.ts
DELETED
package/dist/types/odata.js
DELETED
package/dist/utils/Formatter.js
DELETED
|
@@ -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;
|