@opensas/xml-rest-adapter 0.1.0 → 0.2.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/README.md +6 -0
- package/dist/create-adapter.d.ts +1 -2
- package/dist/create-adapter.js +15 -6
- package/dist/errors.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/json.d.ts +1 -0
- package/dist/json.js +19 -0
- package/dist/types.d.ts +4 -0
- package/dist/valid.js +19 -1
- package/package.json +2 -8
package/README.md
CHANGED
|
@@ -2,3 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Proyecto _de uso interno_ que expone mediante una API REST las bases de datos que utilizan el
|
|
4
4
|
formato propio de `xmlEntidad_Accion` para encapsular la lógica de negocio.
|
|
5
|
+
|
|
6
|
+
npm: https://www.npmjs.com/package/@opensas/xml-rest-adapter
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pnpm add @opensas/xml-rest-adapter
|
|
10
|
+
```
|
package/dist/create-adapter.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import type { RequestEvent } from '@sveltejs/kit';
|
|
2
1
|
import type { AppError } from './errors.js';
|
|
3
2
|
import type { Result } from './result.js';
|
|
4
3
|
import type { Aplicacion, Usuario } from './types.js';
|
|
5
4
|
export declare function createXmlRestAdapter(app: Aplicacion): {
|
|
6
5
|
resolveUser: (identity: string | Request) => Promise<Result<Usuario, AppError>>;
|
|
7
|
-
handle: (
|
|
6
|
+
handle: (request: Request, path: string, usuario: Usuario) => Promise<Response>;
|
|
8
7
|
};
|
package/dist/create-adapter.js
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
// createXmlRestAdapter(app) — la función pública principal de la librería. Valida la Aplicacion
|
|
2
|
+
// configurada y devuelve un adapter con dos métodos: `resolveUser(domainUser)` (identidad +
|
|
3
|
+
// permisos, ver auth.ts) y `handle(request, path, usuario)`, que atiende cualquier request
|
|
4
|
+
// GET/POST/PUT/DELETE contra esa app — juntos reemplazan `authUser` (hooks.server.ts) y los 4
|
|
5
|
+
// handlers que hoy viven repartidos en dos `+server.ts` distintos en convenios_web
|
|
6
|
+
// (routes/api/[aplicacion]/[objeto]/+server.ts y .../[objeto]/[id]/+server.ts). `usuario` se pasa
|
|
7
|
+
// separado, no vía `event.locals`: no le impone al consumidor que cablee nada en su propio
|
|
8
|
+
// `hooks.server.ts` (ver docs/proximos-pasos.md). `request`/`path` sueltos, no un objeto tipo
|
|
9
|
+
// `RequestEvent` — `handle` nunca necesitó más que estos dos datos, y un objeto `{params,request}`
|
|
10
|
+
// es la forma que le da SvelteKit a su evento, no un estándar: `Request` (Fetch API) sí lo es,
|
|
11
|
+
// `path` es un `string` plano porque nunca hay más de un segmento que leer (ver
|
|
12
|
+
// docs/proximos-pasos.md, "agnóstico de framework").
|
|
2
13
|
import { resolveUser } from './auth.js';
|
|
3
14
|
import { execXmlConsulta, execXmlSentencia } from './db.js';
|
|
4
15
|
import { appError, jsonError } from './errors.js';
|
|
16
|
+
import { json } from './json.js';
|
|
5
17
|
import { parseRequest } from './parse-request.js';
|
|
6
18
|
function validarAplicacion(app) {
|
|
7
19
|
if (!app.name)
|
|
@@ -55,12 +67,9 @@ export function createXmlRestAdapter(app) {
|
|
|
55
67
|
function resolveUserFn(identity) {
|
|
56
68
|
return resolveUser(app, identity);
|
|
57
69
|
}
|
|
58
|
-
async function handle(
|
|
70
|
+
async function handle(request, path, usuario) {
|
|
59
71
|
try {
|
|
60
|
-
|
|
61
|
-
// el nombre real del param lo tipa `$types` del lado del consumidor, no acá.
|
|
62
|
-
const path = event.params.path ?? '';
|
|
63
|
-
const parsed = await parseRequest(app, event.request, path, usuario);
|
|
72
|
+
const parsed = await parseRequest(app, request, path, usuario);
|
|
64
73
|
if (!parsed.ok)
|
|
65
74
|
return jsonError(parsed.error);
|
|
66
75
|
const { objeto, id, sentencia, archivos, archivoParams } = parsed.data;
|
package/dist/errors.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// Error de negocio estructurado y homogéneo para toda la librería. Se arma con `appError(...)`
|
|
2
2
|
// (título + código + detalle opcional) y se devuelve al cliente con `jsonError(...)`, que lo
|
|
3
3
|
// envuelve en un `Response` JSON con el status HTTP que corresponde al código.
|
|
4
|
-
import { json } from '@sveltejs/kit';
|
|
5
4
|
import { BAD_REQUEST, FORBIDDEN, INTERNAL_ERROR, NOT_FOUND, UNAUTHORIZED, UNPROCESSABLE_ENTITY, } from './http-status.js';
|
|
5
|
+
import { json } from './json.js';
|
|
6
6
|
export const APP_ERROR_CODES = [
|
|
7
7
|
'VALIDATION_ERROR',
|
|
8
8
|
'BAD_REQUEST',
|
package/dist/index.d.ts
CHANGED
|
@@ -4,5 +4,5 @@ export { getDomainUser } from './auth.js';
|
|
|
4
4
|
export { appError, jsonError, type AppError, type AppErrorCode } from './errors.js';
|
|
5
5
|
export { closeAllPools } from './db.js';
|
|
6
6
|
export type { Result } from './result.js';
|
|
7
|
-
export type { Accion, Aplicacion, Authentication, Authorization, Endpoint, Permisos, Usuario, } from './types.js';
|
|
7
|
+
export type { Accion, Aplicacion, Authentication, Authorization, Endpoint, HandleEvent, Permisos, Usuario, } from './types.js';
|
|
8
8
|
export type { DbInfo } from './db.js';
|
package/dist/json.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function json(data: unknown, init?: ResponseInit): Response;
|
package/dist/json.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Reimplementación mínima de `json()` de `@sveltejs/kit` — evita que la librería dependa de
|
|
2
|
+
// `@sveltejs/kit` en runtime (ver docs/proximos-pasos.md, "peerDependencies real vs. de tipos"):
|
|
3
|
+
// antes, `import { json } from '@sveltejs/kit'` en errors.ts/create-adapter.ts obligaba a instalar
|
|
4
|
+
// el paquete completo (y, por peerDependency, arrastraba `svelte`) aunque el consumidor no use
|
|
5
|
+
// SvelteKit para nada — el propio `RequestEvent` que sí necesita la librería es solo un tipo,
|
|
6
|
+
// borrado en tiempo de compilación. Comportamiento idéntico al original (mismo orden de headers,
|
|
7
|
+
// mismo default de `content-type`/`content-length` solo si el caller no los puso ya).
|
|
8
|
+
const textEncoder = new TextEncoder();
|
|
9
|
+
export function json(data, init) {
|
|
10
|
+
const body = JSON.stringify(data);
|
|
11
|
+
const headers = new Headers(init?.headers);
|
|
12
|
+
if (!headers.has('content-length')) {
|
|
13
|
+
headers.set('content-length', textEncoder.encode(body).byteLength.toString());
|
|
14
|
+
}
|
|
15
|
+
if (!headers.has('content-type')) {
|
|
16
|
+
headers.set('content-type', 'application/json');
|
|
17
|
+
}
|
|
18
|
+
return new Response(body, { ...init, headers });
|
|
19
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { DbInfo } from './db.js';
|
|
2
|
+
export type HandleEvent = {
|
|
3
|
+
params: Record<string, string | undefined>;
|
|
4
|
+
request: Request;
|
|
5
|
+
};
|
|
2
6
|
export type Accion = 'consulta' | 'alta' | 'baja' | 'modificacion';
|
|
3
7
|
export type Permisos = Record<string, Accion[]>;
|
|
4
8
|
export type Usuario = {
|
package/dist/valid.js
CHANGED
|
@@ -23,7 +23,25 @@ function toPascalCase(str) {
|
|
|
23
23
|
})
|
|
24
24
|
.join('');
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
// Match exacto primero. Si falla y el segmento tiene un separador `_` explícito, reintenta
|
|
27
|
+
// case-insensitive: un `Endpoint.name` con un acrónimo en mayúsculas (`ActividadCIIU`,
|
|
28
|
+
// `CategoriaCIIU`) nunca coincide con lo que arma `toPascalCase` a partir del segmento de URL
|
|
29
|
+
// (`actividad_ciiu` → `ActividadCiiu`, con "Ciiu" no "CIIU") — ningún algoritmo genérico de
|
|
30
|
+
// snake_case→PascalCase puede adivinar qué partes de un nombre compuesto son sigla.
|
|
31
|
+
// convenios_web nunca tuvo este problema porque su comparación (`isValidObjeto`) ya era
|
|
32
|
+
// case-insensitive — portado acá, pero acotado al caso con separador: sin `_` en el segmento
|
|
33
|
+
// mantenemos el exacto a propósito (`tipodato`, sin límite de palabra explícito, sigue sin
|
|
34
|
+
// matchear `TipoDato` — ver custom-url-casing.fixture.test.ts, cualquier coincidencia ahí sería
|
|
35
|
+
// casualidad, no una reconstrucción real). Encontrado migrando `CctDigitalizacion` en
|
|
36
|
+
// convenios_web (ver docs/todos/rest-baseline-pre-migracion.md).
|
|
37
|
+
const getEndpoint = (app, objeto) => {
|
|
38
|
+
const pascal = toPascalCase(objeto);
|
|
39
|
+
const exact = app.endpoints.find((ep) => ep.name === pascal);
|
|
40
|
+
if (exact || !objeto.includes('_'))
|
|
41
|
+
return exact;
|
|
42
|
+
const normalized = pascal.toLowerCase();
|
|
43
|
+
return app.endpoints.find((ep) => ep.name.toLowerCase() === normalized);
|
|
44
|
+
};
|
|
27
45
|
export function validParams(app, path, withId = 'noId') {
|
|
28
46
|
const [objetoRaw, idRaw] = path.split('/');
|
|
29
47
|
if (!objetoRaw)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opensas/xml-rest-adapter",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"fixture:purge": "docker compose -f docker/fixture/docker-compose.yaml down -v",
|
|
34
34
|
"fixture:start": "docker compose -f docker/fixture/docker-compose.yaml up -d",
|
|
35
35
|
"fixture:stop": "docker compose -f docker/fixture/docker-compose.yaml stop",
|
|
36
|
-
"fixture:status": "docker ps --filter name=fixture-db --format 'table {{.Names}}\\t{{.Status}}'",
|
|
36
|
+
"fixture:status": "docker ps --filter name=xml-rest-adapter-fixture-db --format 'table {{.Names}}\\t{{.Status}}'",
|
|
37
37
|
"gitlab-runner:start": "sudo gitlab-runner start",
|
|
38
38
|
"gitlab-runner:stop": "sudo gitlab-runner stop",
|
|
39
39
|
"gitlab-runner:status": "sudo gitlab-runner status",
|
|
@@ -47,20 +47,14 @@
|
|
|
47
47
|
"sideEffects": [
|
|
48
48
|
"**/*.css"
|
|
49
49
|
],
|
|
50
|
-
"svelte": "./dist/index.js",
|
|
51
50
|
"types": "./dist/index.d.ts",
|
|
52
51
|
"type": "module",
|
|
53
52
|
"exports": {
|
|
54
53
|
".": {
|
|
55
54
|
"types": "./dist/index.d.ts",
|
|
56
|
-
"svelte": "./dist/index.js",
|
|
57
55
|
"default": "./dist/index.js"
|
|
58
56
|
}
|
|
59
57
|
},
|
|
60
|
-
"peerDependencies": {
|
|
61
|
-
"@sveltejs/kit": "^2.0.0",
|
|
62
|
-
"svelte": "^5.0.0"
|
|
63
|
-
},
|
|
64
58
|
"devDependencies": {
|
|
65
59
|
"@eslint/js": "^10.0.1",
|
|
66
60
|
"@playwright/test": "^1.62.1",
|