@nubiia/mcp-freematica 0.6.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 +485 -0
- package/dist/clients/base-client.d.ts +31 -0
- package/dist/clients/base-client.js +102 -0
- package/dist/clients/base-client.js.map +1 -0
- package/dist/clients/fiql-builder.d.ts +118 -0
- package/dist/clients/fiql-builder.js +257 -0
- package/dist/clients/fiql-builder.js.map +1 -0
- package/dist/clients/freematica-client.d.ts +659 -0
- package/dist/clients/freematica-client.js +1327 -0
- package/dist/clients/freematica-client.js.map +1 -0
- package/dist/clients/hardened-base-client.d.ts +143 -0
- package/dist/clients/hardened-base-client.js +366 -0
- package/dist/clients/hardened-base-client.js.map +1 -0
- package/dist/config.d.ts +104 -0
- package/dist/config.js +105 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +71 -0
- package/dist/logger.js +114 -0
- package/dist/logger.js.map +1 -0
- package/dist/schemas/albaranes.d.ts +124 -0
- package/dist/schemas/albaranes.js +250 -0
- package/dist/schemas/albaranes.js.map +1 -0
- package/dist/schemas/cartera.d.ts +70 -0
- package/dist/schemas/cartera.js +104 -0
- package/dist/schemas/cartera.js.map +1 -0
- package/dist/schemas/contratos.d.ts +7 -0
- package/dist/schemas/contratos.js +2 -0
- package/dist/schemas/contratos.js.map +1 -0
- package/dist/schemas/facturas-electronicas.d.ts +60 -0
- package/dist/schemas/facturas-electronicas.js +79 -0
- package/dist/schemas/facturas-electronicas.js.map +1 -0
- package/dist/schemas/facturas-ventas.d.ts +118 -0
- package/dist/schemas/facturas-ventas.js +153 -0
- package/dist/schemas/facturas-ventas.js.map +1 -0
- package/dist/schemas/filters.d.ts +92 -0
- package/dist/schemas/filters.js +76 -0
- package/dist/schemas/filters.js.map +1 -0
- package/dist/schemas/master-data.d.ts +26 -0
- package/dist/schemas/master-data.js +86 -0
- package/dist/schemas/master-data.js.map +1 -0
- package/dist/schemas/pagination.d.ts +14 -0
- package/dist/schemas/pagination.js +27 -0
- package/dist/schemas/pagination.js.map +1 -0
- package/dist/schemas/pedidos-compras.d.ts +92 -0
- package/dist/schemas/pedidos-compras.js +189 -0
- package/dist/schemas/pedidos-compras.js.map +1 -0
- package/dist/server-instructions.d.ts +1 -0
- package/dist/server-instructions.js +83 -0
- package/dist/server-instructions.js.map +1 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.js +41 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/albaranes.d.ts +16 -0
- package/dist/tools/albaranes.js +202 -0
- package/dist/tools/albaranes.js.map +1 -0
- package/dist/tools/calendarios.d.ts +13 -0
- package/dist/tools/calendarios.js +82 -0
- package/dist/tools/calendarios.js.map +1 -0
- package/dist/tools/cartera.d.ts +13 -0
- package/dist/tools/cartera.js +78 -0
- package/dist/tools/cartera.js.map +1 -0
- package/dist/tools/clientes.d.ts +3 -0
- package/dist/tools/clientes.js +48 -0
- package/dist/tools/clientes.js.map +1 -0
- package/dist/tools/contabilidad.d.ts +14 -0
- package/dist/tools/contabilidad.js +259 -0
- package/dist/tools/contabilidad.js.map +1 -0
- package/dist/tools/contactos-clientes.d.ts +3 -0
- package/dist/tools/contactos-clientes.js +25 -0
- package/dist/tools/contactos-clientes.js.map +1 -0
- package/dist/tools/contratos.d.ts +10 -0
- package/dist/tools/contratos.js +35 -0
- package/dist/tools/contratos.js.map +1 -0
- package/dist/tools/facturas-compras.d.ts +13 -0
- package/dist/tools/facturas-compras.js +131 -0
- package/dist/tools/facturas-compras.js.map +1 -0
- package/dist/tools/facturas-electronicas.d.ts +17 -0
- package/dist/tools/facturas-electronicas.js +268 -0
- package/dist/tools/facturas-electronicas.js.map +1 -0
- package/dist/tools/facturas-ventas.d.ts +16 -0
- package/dist/tools/facturas-ventas.js +181 -0
- package/dist/tools/facturas-ventas.js.map +1 -0
- package/dist/tools/helpers.d.ts +17 -0
- package/dist/tools/helpers.js +36 -0
- package/dist/tools/helpers.js.map +1 -0
- package/dist/tools/localizaciones.d.ts +17 -0
- package/dist/tools/localizaciones.js +192 -0
- package/dist/tools/localizaciones.js.map +1 -0
- package/dist/tools/master-data.d.ts +10 -0
- package/dist/tools/master-data.js +70 -0
- package/dist/tools/master-data.js.map +1 -0
- package/dist/tools/oportunidades-negocio.d.ts +3 -0
- package/dist/tools/oportunidades-negocio.js +68 -0
- package/dist/tools/oportunidades-negocio.js.map +1 -0
- package/dist/tools/pedidos-compras.d.ts +14 -0
- package/dist/tools/pedidos-compras.js +105 -0
- package/dist/tools/pedidos-compras.js.map +1 -0
- package/dist/tools/personal.d.ts +13 -0
- package/dist/tools/personal.js +154 -0
- package/dist/tools/personal.js.map +1 -0
- package/dist/tools/prl.d.ts +47 -0
- package/dist/tools/prl.js +242 -0
- package/dist/tools/prl.js.map +1 -0
- package/dist/tools/proveedores.d.ts +14 -0
- package/dist/tools/proveedores.js +122 -0
- package/dist/tools/proveedores.js.map +1 -0
- package/dist/transports/http.d.ts +12 -0
- package/dist/transports/http.js +110 -0
- package/dist/transports/http.js.map +1 -0
- package/dist/transports/stdio.d.ts +12 -0
- package/dist/transports/stdio.js +15 -0
- package/dist/transports/stdio.js.map +1 -0
- package/dist/types/api-envelope.d.ts +27 -0
- package/dist/types/api-envelope.js +2 -0
- package/dist/types/api-envelope.js.map +1 -0
- package/dist/types/clientes.d.ts +9 -0
- package/dist/types/clientes.js +2 -0
- package/dist/types/clientes.js.map +1 -0
- package/dist/types/contactos-clientes.d.ts +7 -0
- package/dist/types/contactos-clientes.js +2 -0
- package/dist/types/contactos-clientes.js.map +1 -0
- package/dist/types/contratos.d.ts +8 -0
- package/dist/types/contratos.js +2 -0
- package/dist/types/contratos.js.map +1 -0
- package/dist/types/master-data.d.ts +9 -0
- package/dist/types/master-data.js +2 -0
- package/dist/types/master-data.js.map +1 -0
- package/dist/types/oportunidades-negocio.d.ts +8 -0
- package/dist/types/oportunidades-negocio.js +2 -0
- package/dist/types/oportunidades-negocio.js.map +1 -0
- package/dist/utils/size-guardrail.d.ts +22 -0
- package/dist/utils/size-guardrail.js +31 -0
- package/dist/utils/size-guardrail.js.map +1 -0
- package/package.json +90 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FIQL (Feed Item Query Language) builder para el API de Freemática.
|
|
3
|
+
*
|
|
4
|
+
* FIQL es un lenguaje de consulta basado en texto para filtrar recursos REST,
|
|
5
|
+
* definido en draft-nottingham-atompub-fiql (https://tools.ietf.org/id/draft-nottingham-atompub-fiql-00.txt).
|
|
6
|
+
*
|
|
7
|
+
* Operadores soportados:
|
|
8
|
+
* - `==` igual (eq)
|
|
9
|
+
* - `!=` distinto (ne)
|
|
10
|
+
* - `=gt=` mayor que
|
|
11
|
+
* - `=lt=` menor que
|
|
12
|
+
* - `=ge=` mayor o igual
|
|
13
|
+
* - `=le=` menor o igual
|
|
14
|
+
* - `=in=` in list (valor: array → `=in=(v1,v2,v3)`)
|
|
15
|
+
* - `;` AND (combina expresiones)
|
|
16
|
+
* - `,` OR (combina expresiones)
|
|
17
|
+
*
|
|
18
|
+
* Caracteres que requieren escape en valores FIQL:
|
|
19
|
+
* `;` `,` `(` `)` `"` `'` espacios → percent-encoding (%3B, %2C, %28, %29, %22, %27, %20)
|
|
20
|
+
* `=` → %3D (evita ambigüedad con operadores FIQL del tipo `=op=`)
|
|
21
|
+
* `!` → %21 (evita ambigüedad con el operador `!=`)
|
|
22
|
+
* El `==` en un valor se convierte en `%3D%3D` automáticamente.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Operadores escalares soportados.
|
|
26
|
+
*
|
|
27
|
+
* - `eq` → `==` Igual (por defecto)
|
|
28
|
+
* - `ne` → `!=` Distinto
|
|
29
|
+
* - `gt` → `=gt=` Mayor que
|
|
30
|
+
* - `lt` → `=lt=` Menor que
|
|
31
|
+
* - `ge` → `=ge=` Mayor o igual
|
|
32
|
+
* - `le` → `=le=` Menor o igual
|
|
33
|
+
* - `in` → `=in=` En lista (valor: array)
|
|
34
|
+
* - `lk` → `=lk=` Like / búsqueda parcial. **EXTENSIÓN NO ESTÁNDAR de Freemática.**
|
|
35
|
+
* El operador `=lk=` no forma parte de la especificación FIQL original.
|
|
36
|
+
* Se usa para búsquedas de texto parcial en campos como `NOMBRE_PRO`.
|
|
37
|
+
* No hay evidencia documental en la colección Postman; se asume por convención
|
|
38
|
+
* del API Freemática. Si el API no lo soporta, usar `==` con wildcards `%`.
|
|
39
|
+
*/
|
|
40
|
+
export type FiqlOp = 'eq' | 'ne' | 'gt' | 'lt' | 'ge' | 'le' | 'in' | 'lk';
|
|
41
|
+
/** Valor escalar (primitivo o con operador explícito). */
|
|
42
|
+
export type FiqlValue = string | number | boolean | {
|
|
43
|
+
op: FiqlOp;
|
|
44
|
+
value: string | number | string[] | number[];
|
|
45
|
+
};
|
|
46
|
+
/** Un grupo plano de key → FiqlValue (se tratan como AND entre sí). */
|
|
47
|
+
export type FiqlGroup = Record<string, FiqlValue | undefined>;
|
|
48
|
+
/**
|
|
49
|
+
* Entrada del builder. Puede ser:
|
|
50
|
+
* - Un grupo plano `{ campo: valor, ... }` → se combinan con AND (`;`)
|
|
51
|
+
* - Un objeto con `and` o `or` que contiene arrays de grupos → composición explícita
|
|
52
|
+
*/
|
|
53
|
+
export type FiqlFilters = FiqlGroup | {
|
|
54
|
+
and?: FiqlGroup[];
|
|
55
|
+
or?: FiqlGroup[];
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Construye una cadena FIQL a partir de un objeto de filtros tipado.
|
|
59
|
+
*
|
|
60
|
+
* ### Formato de entrada
|
|
61
|
+
*
|
|
62
|
+
* **Grupo plano** (se unen con AND):
|
|
63
|
+
* ```ts
|
|
64
|
+
* buildFiql({ COD_CLI: '123', ESTADO: 'activo' })
|
|
65
|
+
* // → 'COD_CLI==123;ESTADO==activo'
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* **Operador explícito**:
|
|
69
|
+
* ```ts
|
|
70
|
+
* buildFiql({ IMPORTE: { op: 'gt', value: 1000 } })
|
|
71
|
+
* // → 'IMPORTE=gt=1000'
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* **Operador IN con array**:
|
|
75
|
+
* ```ts
|
|
76
|
+
* buildFiql({ COD_CLI: { op: 'in', value: ['A1', 'A2'] } })
|
|
77
|
+
* // → 'COD_CLI=in=(A1,A2)'
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* **Composición AND/OR**:
|
|
81
|
+
* ```ts
|
|
82
|
+
* buildFiql({
|
|
83
|
+
* and: [{ EMPRESA: '1' }, { DELEGACION: 'MAD' }],
|
|
84
|
+
* })
|
|
85
|
+
* // → 'EMPRESA==1;DELEGACION==MAD'
|
|
86
|
+
*
|
|
87
|
+
* buildFiql({
|
|
88
|
+
* or: [{ ESTADO: 'activo' }, { ESTADO: 'pendiente' }],
|
|
89
|
+
* })
|
|
90
|
+
* // → 'ESTADO==activo,ESTADO==pendiente'
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* ### Reglas
|
|
94
|
+
* - Los valores `undefined` se omiten silenciosamente.
|
|
95
|
+
* - Si todos los filtros son `undefined` o el objeto está vacío → retorna `""`.
|
|
96
|
+
* - Los caracteres reservados FIQL (`;`, `,`, `(`, `)`, `"`, `'`, espacio, `=`, `!`)
|
|
97
|
+
* en los valores se percent-encodean automáticamente.
|
|
98
|
+
* - Las claves `and`/`or` sólo activan composición si su valor es un `Array`.
|
|
99
|
+
* Si el valor es un string, number u otro tipo primitivo, se tratan como
|
|
100
|
+
* nombres de campo ordinarios (ej. `{ and: 'val' }` → `AND==val`).
|
|
101
|
+
*
|
|
102
|
+
* @param filters - Filtros en formato FiqlFilters.
|
|
103
|
+
* @returns Cadena FIQL. Vacía si no hay ningún filtro activo.
|
|
104
|
+
*/
|
|
105
|
+
export declare function buildFiql(filters: FiqlFilters): string;
|
|
106
|
+
/**
|
|
107
|
+
* Añade el parámetro `rquery` a una URL si la cadena FIQL es no vacía.
|
|
108
|
+
*
|
|
109
|
+
* Si `fiql` es una cadena vacía, no se hace nada (no se añade el parámetro).
|
|
110
|
+
*
|
|
111
|
+
* @param url - Objeto URL a mutar.
|
|
112
|
+
* @param fiql - Cadena FIQL generada con `buildFiql()`.
|
|
113
|
+
* @example
|
|
114
|
+
* const url = new URL('https://api.example.com/clientes');
|
|
115
|
+
* appendRquery(url, buildFiql({ COD_CLI: '123' }));
|
|
116
|
+
* // url.href → 'https://api.example.com/clientes?rquery=COD_CLI%3D%3D123'
|
|
117
|
+
*/
|
|
118
|
+
export declare function appendRquery(url: URL, fiql: string): void;
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FIQL (Feed Item Query Language) builder para el API de Freemática.
|
|
3
|
+
*
|
|
4
|
+
* FIQL es un lenguaje de consulta basado en texto para filtrar recursos REST,
|
|
5
|
+
* definido en draft-nottingham-atompub-fiql (https://tools.ietf.org/id/draft-nottingham-atompub-fiql-00.txt).
|
|
6
|
+
*
|
|
7
|
+
* Operadores soportados:
|
|
8
|
+
* - `==` igual (eq)
|
|
9
|
+
* - `!=` distinto (ne)
|
|
10
|
+
* - `=gt=` mayor que
|
|
11
|
+
* - `=lt=` menor que
|
|
12
|
+
* - `=ge=` mayor o igual
|
|
13
|
+
* - `=le=` menor o igual
|
|
14
|
+
* - `=in=` in list (valor: array → `=in=(v1,v2,v3)`)
|
|
15
|
+
* - `;` AND (combina expresiones)
|
|
16
|
+
* - `,` OR (combina expresiones)
|
|
17
|
+
*
|
|
18
|
+
* Caracteres que requieren escape en valores FIQL:
|
|
19
|
+
* `;` `,` `(` `)` `"` `'` espacios → percent-encoding (%3B, %2C, %28, %29, %22, %27, %20)
|
|
20
|
+
* `=` → %3D (evita ambigüedad con operadores FIQL del tipo `=op=`)
|
|
21
|
+
* `!` → %21 (evita ambigüedad con el operador `!=`)
|
|
22
|
+
* El `==` en un valor se convierte en `%3D%3D` automáticamente.
|
|
23
|
+
*/
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Internals
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
const OP_MAP = {
|
|
28
|
+
eq: '==',
|
|
29
|
+
ne: '!=',
|
|
30
|
+
gt: '=gt=',
|
|
31
|
+
lt: '=lt=',
|
|
32
|
+
ge: '=ge=',
|
|
33
|
+
le: '=le=',
|
|
34
|
+
in: '=in=',
|
|
35
|
+
lk: '=lk=',
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Caracteres reservados en FIQL que deben ser percent-encoded dentro de valores.
|
|
39
|
+
*
|
|
40
|
+
* Según la gramática FIQL, los caracteres `;` `,` `(` `)` son delimitadores
|
|
41
|
+
* de la expresión. Las comillas `"` y `'` se usan en comparadores. El espacio
|
|
42
|
+
* también debe codificarse. Los caracteres `=` y `!` forman los operadores
|
|
43
|
+
* FIQL (`==`, `!=`, `=gt=`, etc.) y DEBEN escaparse en valores para evitar
|
|
44
|
+
* ambigüedad semántica en el parser del servidor.
|
|
45
|
+
*
|
|
46
|
+
* Ejemplos de ambigüedad sin escape:
|
|
47
|
+
* `CAMPO==x=gt=0` → parser puede interpretar `x=gt=0` como sub-operador
|
|
48
|
+
* `CAMPO==123==EVIL` → parser puede ver un doble operador
|
|
49
|
+
*/
|
|
50
|
+
const FIQL_RESERVED_RE = /[;,()"' =!]/g;
|
|
51
|
+
const RESERVED_ENCODE_MAP = {
|
|
52
|
+
';': '%3B',
|
|
53
|
+
',': '%2C',
|
|
54
|
+
'(': '%28',
|
|
55
|
+
')': '%29',
|
|
56
|
+
'"': '%22',
|
|
57
|
+
"'": '%27',
|
|
58
|
+
' ': '%20',
|
|
59
|
+
'=': '%3D',
|
|
60
|
+
'!': '%21',
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Escapa caracteres reservados FIQL en un valor escalar.
|
|
64
|
+
*
|
|
65
|
+
* Los únicos caracteres que se encodean son los que tienen significado
|
|
66
|
+
* estructural en FIQL. El resto se deja tal cual para evitar doble-encoding
|
|
67
|
+
* con los valores que ya contienen percent-encoding legítimo.
|
|
68
|
+
*
|
|
69
|
+
* @param raw - Valor a escapar (string).
|
|
70
|
+
* @returns Valor con caracteres reservados percent-encoded.
|
|
71
|
+
*/
|
|
72
|
+
function escapeFiqlValue(raw) {
|
|
73
|
+
return raw.replace(FIQL_RESERVED_RE, (ch) => RESERVED_ENCODE_MAP[ch] ?? ch);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Convierte un valor primitivo a string FIQL escapado.
|
|
77
|
+
*
|
|
78
|
+
* @param val - Primitivo (`string | number | boolean`).
|
|
79
|
+
* @returns Representación FIQL del valor.
|
|
80
|
+
*/
|
|
81
|
+
function primitiveToFiql(val) {
|
|
82
|
+
return escapeFiqlValue(String(val));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Genera una expresión FIQL simple para `campo operador valor`.
|
|
86
|
+
*
|
|
87
|
+
* @param key - Nombre del campo.
|
|
88
|
+
* @param fiqlValue - Valor o descriptor con operador.
|
|
89
|
+
* @returns Expresión FIQL (ej. `COD_CLI==123`) o `null` si el valor es
|
|
90
|
+
* `undefined` o no aplica.
|
|
91
|
+
*/
|
|
92
|
+
function buildExpression(key, fiqlValue) {
|
|
93
|
+
if (typeof fiqlValue === 'object' && fiqlValue !== null && 'op' in fiqlValue) {
|
|
94
|
+
const { op, value } = fiqlValue;
|
|
95
|
+
const fiqlOp = OP_MAP[op];
|
|
96
|
+
if (op === 'in') {
|
|
97
|
+
const arr = Array.isArray(value) ? value : [value];
|
|
98
|
+
if (arr.length === 0)
|
|
99
|
+
return '';
|
|
100
|
+
const encoded = arr.map((v) => escapeFiqlValue(String(v))).join(',');
|
|
101
|
+
return `${key}${fiqlOp}(${encoded})`;
|
|
102
|
+
}
|
|
103
|
+
const scalar = Array.isArray(value) ? value[0] : value;
|
|
104
|
+
return `${key}${fiqlOp}${primitiveToFiql(scalar)}`;
|
|
105
|
+
}
|
|
106
|
+
// Primitivo → operador por defecto es `==`
|
|
107
|
+
return `${key}==${primitiveToFiql(fiqlValue)}`;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Convierte un grupo de filtros planos a una lista de expresiones FIQL
|
|
111
|
+
* (omite las claves con valor `undefined`).
|
|
112
|
+
*
|
|
113
|
+
* @param group - Mapa de campo → valor.
|
|
114
|
+
* @returns Array de expresiones FIQL individuales.
|
|
115
|
+
*/
|
|
116
|
+
function groupToExpressions(group) {
|
|
117
|
+
const expressions = [];
|
|
118
|
+
for (const [key, value] of Object.entries(group)) {
|
|
119
|
+
if (value === undefined)
|
|
120
|
+
continue;
|
|
121
|
+
const expr = buildExpression(key, value);
|
|
122
|
+
if (expr)
|
|
123
|
+
expressions.push(expr);
|
|
124
|
+
}
|
|
125
|
+
return expressions;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Detecta si el objeto es una composición `{ and?, or? }` o un grupo plano.
|
|
129
|
+
*
|
|
130
|
+
* La detección es estricta: para ser considerada composición, las claves
|
|
131
|
+
* `and`/`or` DEBEN tener un valor `Array` (o `undefined`). Si `and`/`or`
|
|
132
|
+
* contienen un valor no-array (ej. `string`, `number`) se tratan como
|
|
133
|
+
* nombres de campo ordinarios del grupo plano, evitando el bug de type
|
|
134
|
+
* confusion donde `{ and: 'string' }` iteraría char a char el string.
|
|
135
|
+
*
|
|
136
|
+
* ### Aclaración semántica sobre claves `and` / `or`
|
|
137
|
+
*
|
|
138
|
+
* Si tu modelo tiene un campo real llamado `and` o `or` con un valor escalar
|
|
139
|
+
* (string/number/boolean), pásalo como grupo plano: `{ and: 'valor' }` se
|
|
140
|
+
* trata como `AND==valor`. No hay ambigüedad siempre que el valor no sea un
|
|
141
|
+
* Array de FiqlGroup.
|
|
142
|
+
*
|
|
143
|
+
* @param filters - Input del builder.
|
|
144
|
+
* @returns `true` si es composición explícita con `and`/`or` en formato array.
|
|
145
|
+
*/
|
|
146
|
+
function isComposition(filters) {
|
|
147
|
+
// Si `and` está presente pero no es array (ni undefined) → grupo plano
|
|
148
|
+
if ('and' in filters && filters['and'] !== undefined && !Array.isArray(filters['and'])) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
// Si `or` está presente pero no es array (ni undefined) → grupo plano
|
|
152
|
+
if ('or' in filters && filters['or'] !== undefined && !Array.isArray(filters['or'])) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
// Es composición si al menos una clave es un array
|
|
156
|
+
return (('and' in filters && Array.isArray(filters['and'])) ||
|
|
157
|
+
('or' in filters && Array.isArray(filters['or'])));
|
|
158
|
+
}
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
// Public API
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
162
|
+
/**
|
|
163
|
+
* Construye una cadena FIQL a partir de un objeto de filtros tipado.
|
|
164
|
+
*
|
|
165
|
+
* ### Formato de entrada
|
|
166
|
+
*
|
|
167
|
+
* **Grupo plano** (se unen con AND):
|
|
168
|
+
* ```ts
|
|
169
|
+
* buildFiql({ COD_CLI: '123', ESTADO: 'activo' })
|
|
170
|
+
* // → 'COD_CLI==123;ESTADO==activo'
|
|
171
|
+
* ```
|
|
172
|
+
*
|
|
173
|
+
* **Operador explícito**:
|
|
174
|
+
* ```ts
|
|
175
|
+
* buildFiql({ IMPORTE: { op: 'gt', value: 1000 } })
|
|
176
|
+
* // → 'IMPORTE=gt=1000'
|
|
177
|
+
* ```
|
|
178
|
+
*
|
|
179
|
+
* **Operador IN con array**:
|
|
180
|
+
* ```ts
|
|
181
|
+
* buildFiql({ COD_CLI: { op: 'in', value: ['A1', 'A2'] } })
|
|
182
|
+
* // → 'COD_CLI=in=(A1,A2)'
|
|
183
|
+
* ```
|
|
184
|
+
*
|
|
185
|
+
* **Composición AND/OR**:
|
|
186
|
+
* ```ts
|
|
187
|
+
* buildFiql({
|
|
188
|
+
* and: [{ EMPRESA: '1' }, { DELEGACION: 'MAD' }],
|
|
189
|
+
* })
|
|
190
|
+
* // → 'EMPRESA==1;DELEGACION==MAD'
|
|
191
|
+
*
|
|
192
|
+
* buildFiql({
|
|
193
|
+
* or: [{ ESTADO: 'activo' }, { ESTADO: 'pendiente' }],
|
|
194
|
+
* })
|
|
195
|
+
* // → 'ESTADO==activo,ESTADO==pendiente'
|
|
196
|
+
* ```
|
|
197
|
+
*
|
|
198
|
+
* ### Reglas
|
|
199
|
+
* - Los valores `undefined` se omiten silenciosamente.
|
|
200
|
+
* - Si todos los filtros son `undefined` o el objeto está vacío → retorna `""`.
|
|
201
|
+
* - Los caracteres reservados FIQL (`;`, `,`, `(`, `)`, `"`, `'`, espacio, `=`, `!`)
|
|
202
|
+
* en los valores se percent-encodean automáticamente.
|
|
203
|
+
* - Las claves `and`/`or` sólo activan composición si su valor es un `Array`.
|
|
204
|
+
* Si el valor es un string, number u otro tipo primitivo, se tratan como
|
|
205
|
+
* nombres de campo ordinarios (ej. `{ and: 'val' }` → `AND==val`).
|
|
206
|
+
*
|
|
207
|
+
* @param filters - Filtros en formato FiqlFilters.
|
|
208
|
+
* @returns Cadena FIQL. Vacía si no hay ningún filtro activo.
|
|
209
|
+
*/
|
|
210
|
+
export function buildFiql(filters) {
|
|
211
|
+
if (isComposition(filters)) {
|
|
212
|
+
const parts = [];
|
|
213
|
+
if (filters.and && filters.and.length > 0) {
|
|
214
|
+
const andExprs = [];
|
|
215
|
+
for (const group of filters.and) {
|
|
216
|
+
andExprs.push(...groupToExpressions(group));
|
|
217
|
+
}
|
|
218
|
+
if (andExprs.length > 0) {
|
|
219
|
+
parts.push(andExprs.join(';'));
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (filters.or && filters.or.length > 0) {
|
|
223
|
+
const orExprs = [];
|
|
224
|
+
for (const group of filters.or) {
|
|
225
|
+
const groupExprs = groupToExpressions(group);
|
|
226
|
+
if (groupExprs.length > 0) {
|
|
227
|
+
orExprs.push(...groupExprs);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (orExprs.length > 0) {
|
|
231
|
+
parts.push(orExprs.join(','));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return parts.join(';');
|
|
235
|
+
}
|
|
236
|
+
// Grupo plano → AND
|
|
237
|
+
const expressions = groupToExpressions(filters);
|
|
238
|
+
return expressions.join(';');
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Añade el parámetro `rquery` a una URL si la cadena FIQL es no vacía.
|
|
242
|
+
*
|
|
243
|
+
* Si `fiql` es una cadena vacía, no se hace nada (no se añade el parámetro).
|
|
244
|
+
*
|
|
245
|
+
* @param url - Objeto URL a mutar.
|
|
246
|
+
* @param fiql - Cadena FIQL generada con `buildFiql()`.
|
|
247
|
+
* @example
|
|
248
|
+
* const url = new URL('https://api.example.com/clientes');
|
|
249
|
+
* appendRquery(url, buildFiql({ COD_CLI: '123' }));
|
|
250
|
+
* // url.href → 'https://api.example.com/clientes?rquery=COD_CLI%3D%3D123'
|
|
251
|
+
*/
|
|
252
|
+
export function appendRquery(url, fiql) {
|
|
253
|
+
if (fiql.length === 0)
|
|
254
|
+
return;
|
|
255
|
+
url.searchParams.set('rquery', fiql);
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=fiql-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fiql-builder.js","sourceRoot":"","sources":["../../src/clients/fiql-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAuCH,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,MAAM,MAAM,GAA2B;IACrC,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,MAAM;IACV,EAAE,EAAE,MAAM;IACV,EAAE,EAAE,MAAM;IACV,EAAE,EAAE,MAAM;IACV,EAAE,EAAE,MAAM;IACV,EAAE,EAAE,MAAM;CACX,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAExC,MAAM,mBAAmB,GAA2B;IAClD,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;CACX,CAAC;AAEF;;;;;;;;;GASG;AACH,SAAS,eAAe,CAAC,GAAW;IAClC,OAAO,GAAG,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;GAKG;AACH,SAAS,eAAe,CAAC,GAA8B;IACrD,OAAO,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,eAAe,CAAC,GAAW,EAAE,SAAoB;IACxD,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,IAAI,IAAI,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7E,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;QAE1B,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAChB,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACnD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YAChC,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACrE,OAAO,GAAG,GAAG,GAAG,MAAM,IAAI,OAAO,GAAG,CAAC;QACvC,CAAC;QAED,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QACvD,OAAO,GAAG,GAAG,GAAG,MAAM,GAAG,eAAe,CAAC,MAAmC,CAAC,EAAE,CAAC;IAClF,CAAC;IAED,2CAA2C;IAC3C,OAAO,GAAG,GAAG,KAAK,eAAe,CAAC,SAAsC,CAAC,EAAE,CAAC;AAC9E,CAAC;AAED;;;;;;GAMG;AACH,SAAS,kBAAkB,CAAC,KAAgB;IAC1C,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,MAAM,IAAI,GAAG,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACzC,IAAI,IAAI;YAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAS,aAAa,CACpB,OAAoB;IAEpB,uEAAuE;IACvE,IAAI,KAAK,IAAI,OAAO,IAAK,OAAmC,CAAC,KAAK,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAE,OAAmC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACjJ,OAAO,KAAK,CAAC;IACf,CAAC;IACD,sEAAsE;IACtE,IAAI,IAAI,IAAI,OAAO,IAAK,OAAmC,CAAC,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAE,OAAmC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QAC9I,OAAO,KAAK,CAAC;IACf,CAAC;IACD,mDAAmD;IACnD,OAAO,CACL,CAAC,KAAK,IAAI,OAAO,IAAI,KAAK,CAAC,OAAO,CAAE,OAAmC,CAAC,KAAK,CAAC,CAAC,CAAC;QAChF,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,CAAC,OAAO,CAAE,OAAmC,CAAC,IAAI,CAAC,CAAC,CAAC,CAC/E,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,MAAM,UAAU,SAAS,CAAC,OAAoB;IAC5C,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,IAAI,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1C,MAAM,QAAQ,GAAa,EAAE,CAAC;YAC9B,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;gBAChC,QAAQ,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;YAC9C,CAAC;YACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,EAAE,IAAI,OAAO,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxC,MAAM,OAAO,GAAa,EAAE,CAAC;YAC7B,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;gBAC/B,MAAM,UAAU,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;gBAC7C,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC1B,OAAO,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;YACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,oBAAoB;IACpB,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAChD,OAAO,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAC,GAAQ,EAAE,IAAY;IACjD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC9B,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC"}
|