@dwast/verifactu-lib 0.1.0-beta.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/aeat/client.d.ts +57 -0
- package/dist/aeat/client.d.ts.map +1 -0
- package/dist/aeat/client.js +87 -0
- package/dist/aeat/client.js.map +1 -0
- package/dist/aeat/index.d.ts +2 -0
- package/dist/aeat/index.d.ts.map +1 -0
- package/dist/aeat/index.js +2 -0
- package/dist/aeat/index.js.map +1 -0
- package/dist/core/hash/chain.d.ts +97 -0
- package/dist/core/hash/chain.d.ts.map +1 -0
- package/dist/core/hash/chain.js +115 -0
- package/dist/core/hash/chain.js.map +1 -0
- package/dist/core/hash/index.d.ts +2 -0
- package/dist/core/hash/index.d.ts.map +1 -0
- package/dist/core/hash/index.js +2 -0
- package/dist/core/hash/index.js.map +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +5 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/models/event.d.ts +25 -0
- package/dist/core/models/event.d.ts.map +1 -0
- package/dist/core/models/event.js +2 -0
- package/dist/core/models/event.js.map +1 -0
- package/dist/core/models/index.d.ts +3 -0
- package/dist/core/models/index.d.ts.map +1 -0
- package/dist/core/models/index.js +3 -0
- package/dist/core/models/index.js.map +1 -0
- package/dist/core/models/invoice.d.ts +90 -0
- package/dist/core/models/invoice.d.ts.map +1 -0
- package/dist/core/models/invoice.js +2 -0
- package/dist/core/models/invoice.js.map +1 -0
- package/dist/core/qr/index.d.ts +2 -0
- package/dist/core/qr/index.d.ts.map +1 -0
- package/dist/core/qr/index.js +2 -0
- package/dist/core/qr/index.js.map +1 -0
- package/dist/core/qr/qr.d.ts +13 -0
- package/dist/core/qr/qr.d.ts.map +1 -0
- package/dist/core/qr/qr.js +16 -0
- package/dist/core/qr/qr.js.map +1 -0
- package/dist/core/xml/generator.d.ts +32 -0
- package/dist/core/xml/generator.d.ts.map +1 -0
- package/dist/core/xml/generator.js +103 -0
- package/dist/core/xml/generator.js.map +1 -0
- package/dist/core/xml/index.d.ts +2 -0
- package/dist/core/xml/index.d.ts.map +1 -0
- package/dist/core/xml/index.js +2 -0
- package/dist/core/xml/index.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/integration/index.d.ts +3 -0
- package/dist/integration/index.d.ts.map +1 -0
- package/dist/integration/index.js +3 -0
- package/dist/integration/index.js.map +1 -0
- package/dist/integration/repository.d.ts +77 -0
- package/dist/integration/repository.d.ts.map +1 -0
- package/dist/integration/repository.js +2 -0
- package/dist/integration/repository.js.map +1 -0
- package/dist/integration/service.d.ts +36 -0
- package/dist/integration/service.d.ts.map +1 -0
- package/dist/integration/service.js +140 -0
- package/dist/integration/service.js.map +1 -0
- package/package.json +58 -0
- package/readme.md +89 -0
- package/src/aeat/client.ts +137 -0
- package/src/aeat/index.ts +1 -0
- package/src/core/hash/chain.ts +169 -0
- package/src/core/hash/index.ts +1 -0
- package/src/core/index.ts +4 -0
- package/src/core/models/event.ts +25 -0
- package/src/core/models/index.ts +2 -0
- package/src/core/models/invoice.ts +105 -0
- package/src/core/qr/index.ts +1 -0
- package/src/core/qr/qr.ts +19 -0
- package/src/core/xml/generator.ts +133 -0
- package/src/core/xml/index.ts +1 -0
- package/src/index.ts +3 -0
- package/src/integration/index.ts +2 -0
- package/src/integration/repository.ts +86 -0
- package/src/integration/schema.sql +51 -0
- package/src/integration/service.ts +158 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cliente para los servicios web de AEAT (Verifactu).
|
|
3
|
+
*
|
|
4
|
+
* Capa de red, separada del núcleo puro. Depende de credenciales y entornos
|
|
5
|
+
* (producción vs. pruebas), por lo que no debe acoplarse a la lógica de
|
|
6
|
+
* negocio.
|
|
7
|
+
*
|
|
8
|
+
* NOTA: los endpoints y el formato de petición/respuesta deben ajustarse a
|
|
9
|
+
* la documentación oficial de la AEAT (remisión voluntaria / bajo
|
|
10
|
+
* requerimiento). Este cliente expone una implementación base con `fetch`
|
|
11
|
+
* y rutas configurables.
|
|
12
|
+
*/
|
|
13
|
+
export interface VerifactuClientConfig {
|
|
14
|
+
/** URL base del servicio AEAT. */
|
|
15
|
+
baseUrl: string;
|
|
16
|
+
/** Token de autenticación (OAuth) o certificado. */
|
|
17
|
+
authToken?: string;
|
|
18
|
+
/** Ruta del endpoint de envío de registros. */
|
|
19
|
+
sendPath?: string;
|
|
20
|
+
/** Ruta del endpoint de consulta de estado. */
|
|
21
|
+
statusPath?: string;
|
|
22
|
+
/** Timeout de petición en ms. */
|
|
23
|
+
timeoutMs?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface SendResult {
|
|
26
|
+
/** Identificador de la operación devuelto por AEAT. */
|
|
27
|
+
operationId: string;
|
|
28
|
+
/** Estado de la respuesta. */
|
|
29
|
+
status: 'OK' | 'ERROR';
|
|
30
|
+
/** Mensaje de la AEAT. */
|
|
31
|
+
message?: string;
|
|
32
|
+
/** Código de error de AEAT (si lo hay). */
|
|
33
|
+
errorCode?: string;
|
|
34
|
+
/** Cuerpo completo de la respuesta (para auditoría). */
|
|
35
|
+
rawResponse?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Cliente de servicios AEAT para Verifactu.
|
|
39
|
+
*/
|
|
40
|
+
export declare class VerifactuClient {
|
|
41
|
+
private readonly config;
|
|
42
|
+
constructor(config: VerifactuClientConfig);
|
|
43
|
+
/**
|
|
44
|
+
* Envía un registro (factura o evento) a AEAT.
|
|
45
|
+
*/
|
|
46
|
+
sendRecord(xml: string): Promise<SendResult>;
|
|
47
|
+
/**
|
|
48
|
+
* Consulta el estado de una operación enviada.
|
|
49
|
+
*/
|
|
50
|
+
getOperationStatus(operationId: string): Promise<SendResult>;
|
|
51
|
+
/**
|
|
52
|
+
* Parsea la respuesta de AEAT. La estructura exacta depende del servicio;
|
|
53
|
+
* este es un mapeo base que el consumidor puede sobrescribir.
|
|
54
|
+
*/
|
|
55
|
+
protected parseResponse(raw: string, httpStatus: number): SendResult;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/aeat/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,qBAAqB;IACpC,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC;IACvB,0BAA0B;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAUD;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;gBAE5B,MAAM,EAAE,qBAAqB;IASzC;;OAEG;IACG,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IA0BlD;;OAEG;IACG,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAkBlE;;;OAGG;IACH,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,UAAU;CAqBrE"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cliente de servicios AEAT para Verifactu.
|
|
3
|
+
*/
|
|
4
|
+
export class VerifactuClient {
|
|
5
|
+
config;
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.config = {
|
|
8
|
+
sendPath: '/verifactu/registro',
|
|
9
|
+
statusPath: '/verifactu/estado',
|
|
10
|
+
timeoutMs: 10_000,
|
|
11
|
+
...config,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Envía un registro (factura o evento) a AEAT.
|
|
16
|
+
*/
|
|
17
|
+
async sendRecord(xml) {
|
|
18
|
+
const url = `${this.config.baseUrl}${this.config.sendPath}`;
|
|
19
|
+
const headers = {
|
|
20
|
+
'Content-Type': 'application/xml',
|
|
21
|
+
Accept: 'application/json',
|
|
22
|
+
};
|
|
23
|
+
if (this.config.authToken) {
|
|
24
|
+
headers.Authorization = `Bearer ${this.config.authToken}`;
|
|
25
|
+
}
|
|
26
|
+
const controller = new AbortController();
|
|
27
|
+
const timer = setTimeout(() => controller.abort(), this.config.timeoutMs);
|
|
28
|
+
try {
|
|
29
|
+
const res = await fetch(url, {
|
|
30
|
+
method: 'POST',
|
|
31
|
+
headers,
|
|
32
|
+
body: xml,
|
|
33
|
+
signal: controller.signal,
|
|
34
|
+
});
|
|
35
|
+
const raw = await res.text();
|
|
36
|
+
return this.parseResponse(raw, res.status);
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
clearTimeout(timer);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Consulta el estado de una operación enviada.
|
|
44
|
+
*/
|
|
45
|
+
async getOperationStatus(operationId) {
|
|
46
|
+
const url = `${this.config.baseUrl}${this.config.statusPath}/${encodeURIComponent(operationId)}`;
|
|
47
|
+
const headers = { Accept: 'application/json' };
|
|
48
|
+
if (this.config.authToken) {
|
|
49
|
+
headers.Authorization = `Bearer ${this.config.authToken}`;
|
|
50
|
+
}
|
|
51
|
+
const controller = new AbortController();
|
|
52
|
+
const timer = setTimeout(() => controller.abort(), this.config.timeoutMs);
|
|
53
|
+
try {
|
|
54
|
+
const res = await fetch(url, { method: 'GET', headers, signal: controller.signal });
|
|
55
|
+
const raw = await res.text();
|
|
56
|
+
return this.parseResponse(raw, res.status);
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
clearTimeout(timer);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Parsea la respuesta de AEAT. La estructura exacta depende del servicio;
|
|
64
|
+
* este es un mapeo base que el consumidor puede sobrescribir.
|
|
65
|
+
*/
|
|
66
|
+
parseResponse(raw, httpStatus) {
|
|
67
|
+
let operationId = '';
|
|
68
|
+
let status = httpStatus >= 200 && httpStatus < 300 ? 'OK' : 'ERROR';
|
|
69
|
+
let message;
|
|
70
|
+
let errorCode;
|
|
71
|
+
try {
|
|
72
|
+
const json = JSON.parse(raw);
|
|
73
|
+
operationId = String(json.operationId ?? json.id ?? '');
|
|
74
|
+
if (json.status === 'OK' || json.status === 'ERROR') {
|
|
75
|
+
status = json.status;
|
|
76
|
+
}
|
|
77
|
+
message = json.message;
|
|
78
|
+
errorCode = json.errorCode;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Respuesta no JSON: se conserva el cuerpo como mensaje.
|
|
82
|
+
message = raw;
|
|
83
|
+
}
|
|
84
|
+
return { operationId, status, message, errorCode, rawResponse: raw };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/aeat/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/aeat/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/aeat/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calcula el hash SHA-256 de un dato en hexadecimal MAYÚSCULA.
|
|
3
|
+
* Verifactu exige el hash en hexadecimal en mayúsculas (64 caracteres).
|
|
4
|
+
*/
|
|
5
|
+
export declare function sha256(data: string | Buffer): string;
|
|
6
|
+
/**
|
|
7
|
+
* Concatena los campos de un registro en el formato Verifactu:
|
|
8
|
+
* `nombreCampo1=valor1&nombreCampo2=valor2&...`
|
|
9
|
+
*
|
|
10
|
+
* Reglas de normalización (AEAT):
|
|
11
|
+
* - Se eliminan los espacios al inicio y final de cada valor (trim).
|
|
12
|
+
* - Los campos vacíos o ausentes se incluyen como `nombreCampo=` (sin valor).
|
|
13
|
+
* - No se aplica URL-encoding ni escaping a caracteres especiales.
|
|
14
|
+
*/
|
|
15
|
+
export declare function concatenateFields(fields: Array<[string, string | null | undefined]>): string;
|
|
16
|
+
/**
|
|
17
|
+
* Campos de un registro de alta (RegistroAlta) para el cálculo de la huella.
|
|
18
|
+
*/
|
|
19
|
+
export interface RegistroAltaInput {
|
|
20
|
+
/** Identificador del emisor (NIF). */
|
|
21
|
+
idEmisorFactura: string;
|
|
22
|
+
/** Número y serie de la factura. */
|
|
23
|
+
numSerieFactura: string;
|
|
24
|
+
/** Fecha de expedición de la factura. */
|
|
25
|
+
fechaExpedicionFactura: string;
|
|
26
|
+
/** Tipo de factura (F1, F2, ...). */
|
|
27
|
+
tipoFactura: string;
|
|
28
|
+
/** Cuota total. */
|
|
29
|
+
cuotaTotal: string;
|
|
30
|
+
/** Importe total. */
|
|
31
|
+
importeTotal: string;
|
|
32
|
+
/** Huella (hash) del registro anterior, o null para el primero. */
|
|
33
|
+
huellaAnterior: string | null;
|
|
34
|
+
/** Fecha/hora de generación con huso horario. */
|
|
35
|
+
fechaHoraHusoGenRegistro: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Campos de un registro de anulación (RegistroAnulacion).
|
|
39
|
+
*/
|
|
40
|
+
export interface RegistroAnulacionInput {
|
|
41
|
+
/** Identificador del emisor de la factura anulada. */
|
|
42
|
+
idEmisorFacturaAnulada: string;
|
|
43
|
+
/** Número y serie de la factura anulada. */
|
|
44
|
+
numSerieFacturaAnulada: string;
|
|
45
|
+
/** Fecha de expedición de la factura anulada. */
|
|
46
|
+
fechaExpedicionFacturaAnulada: string;
|
|
47
|
+
/** Huella (hash) del registro anterior. */
|
|
48
|
+
huellaAnterior: string | null;
|
|
49
|
+
/** Fecha/hora de generación con huso horario. */
|
|
50
|
+
fechaHoraHusoGenRegistro: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Construye la cadena canónica a hashear de un registro de alta.
|
|
54
|
+
*/
|
|
55
|
+
export declare function concatenateRegistroAlta(input: RegistroAltaInput): string;
|
|
56
|
+
/**
|
|
57
|
+
* Construye la cadena canónica a hashear de un registro de anulación.
|
|
58
|
+
*/
|
|
59
|
+
export declare function concatenateRegistroAnulacion(input: RegistroAnulacionInput): string;
|
|
60
|
+
/**
|
|
61
|
+
* Calcula la huella (hash) de un registro de alta.
|
|
62
|
+
*/
|
|
63
|
+
export declare function computeRegistroAlta(input: RegistroAltaInput): string;
|
|
64
|
+
/**
|
|
65
|
+
* Calcula la huella (hash) de un registro de anulación.
|
|
66
|
+
*/
|
|
67
|
+
export declare function computeRegistroAnulacion(input: RegistroAnulacionInput): string;
|
|
68
|
+
/**
|
|
69
|
+
* Verifica que el hash de un registro de alta coincide con el esperado.
|
|
70
|
+
*/
|
|
71
|
+
export declare function verifyRegistroAlta(input: RegistroAltaInput, expectedHash: string): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Verifica que el hash de un registro de anulación coincide con el esperado.
|
|
74
|
+
*/
|
|
75
|
+
export declare function verifyRegistroAnulacion(input: RegistroAnulacionInput, expectedHash: string): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Cadena de hash con estado, para encadenar registros de forma secuencial.
|
|
78
|
+
*/
|
|
79
|
+
export declare class HashChain {
|
|
80
|
+
private _lastHash;
|
|
81
|
+
private _count;
|
|
82
|
+
/** Hash del último registro encadenado, o `null` si aún no hay ninguno. */
|
|
83
|
+
get lastHash(): string | null;
|
|
84
|
+
/** Número de registros encadenados hasta ahora. */
|
|
85
|
+
get count(): number;
|
|
86
|
+
/**
|
|
87
|
+
* Encadena un nuevo registro de alta y devuelve su huella.
|
|
88
|
+
*/
|
|
89
|
+
pushAlta(input: Omit<RegistroAltaInput, 'huellaAnterior'>): string;
|
|
90
|
+
/**
|
|
91
|
+
* Encadena un nuevo registro de anulación y devuelve su huella.
|
|
92
|
+
*/
|
|
93
|
+
pushAnulacion(input: Omit<RegistroAnulacionInput, 'huellaAnterior'>): string;
|
|
94
|
+
/** Reinicia la cadena. */
|
|
95
|
+
reset(): void;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=chain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain.d.ts","sourceRoot":"","sources":["../../../src/core/hash/chain.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAEpD;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,GAAG,MAAM,CAO5F;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,eAAe,EAAE,MAAM,CAAC;IACxB,oCAAoC;IACpC,eAAe,EAAE,MAAM,CAAC;IACxB,yCAAyC;IACzC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iDAAiD;IACjD,wBAAwB,EAAE,MAAM,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,sDAAsD;IACtD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,4CAA4C;IAC5C,sBAAsB,EAAE,MAAM,CAAC;IAC/B,iDAAiD;IACjD,6BAA6B,EAAE,MAAM,CAAC;IACtC,2CAA2C;IAC3C,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iDAAiD;IACjD,wBAAwB,EAAE,MAAM,CAAC;CAClC;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAWxE;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CAQlF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAEpE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CAE9E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAE1F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,sBAAsB,EAC7B,YAAY,EAAE,MAAM,GACnB,OAAO,CAET;AAED;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,MAAM,CAAK;IAEnB,2EAA2E;IAC3E,IAAI,QAAQ,IAAI,MAAM,GAAG,IAAI,CAE5B;IAED,mDAAmD;IACnD,IAAI,KAAK,IAAI,MAAM,CAElB;IAED;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,GAAG,MAAM;IAOlE;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,sBAAsB,EAAE,gBAAgB,CAAC,GAAG,MAAM;IAO5E,0BAA0B;IAC1B,KAAK,IAAI,IAAI;CAId"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
/**
|
|
3
|
+
* Calcula el hash SHA-256 de un dato en hexadecimal MAYÚSCULA.
|
|
4
|
+
* Verifactu exige el hash en hexadecimal en mayúsculas (64 caracteres).
|
|
5
|
+
*/
|
|
6
|
+
export function sha256(data) {
|
|
7
|
+
return createHash('sha256').update(data).digest('hex').toUpperCase();
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Concatena los campos de un registro en el formato Verifactu:
|
|
11
|
+
* `nombreCampo1=valor1&nombreCampo2=valor2&...`
|
|
12
|
+
*
|
|
13
|
+
* Reglas de normalización (AEAT):
|
|
14
|
+
* - Se eliminan los espacios al inicio y final de cada valor (trim).
|
|
15
|
+
* - Los campos vacíos o ausentes se incluyen como `nombreCampo=` (sin valor).
|
|
16
|
+
* - No se aplica URL-encoding ni escaping a caracteres especiales.
|
|
17
|
+
*/
|
|
18
|
+
export function concatenateFields(fields) {
|
|
19
|
+
return fields
|
|
20
|
+
.map(([name, value]) => {
|
|
21
|
+
const trimmed = value ? value.trim() : '';
|
|
22
|
+
return `${name}=${trimmed}`;
|
|
23
|
+
})
|
|
24
|
+
.join('&');
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Construye la cadena canónica a hashear de un registro de alta.
|
|
28
|
+
*/
|
|
29
|
+
export function concatenateRegistroAlta(input) {
|
|
30
|
+
return concatenateFields([
|
|
31
|
+
['IDEmisorFactura', input.idEmisorFactura],
|
|
32
|
+
['NumSerieFactura', input.numSerieFactura],
|
|
33
|
+
['FechaExpedicionFactura', input.fechaExpedicionFactura],
|
|
34
|
+
['TipoFactura', input.tipoFactura],
|
|
35
|
+
['CuotaTotal', input.cuotaTotal],
|
|
36
|
+
['ImporteTotal', input.importeTotal],
|
|
37
|
+
['Huella', input.huellaAnterior],
|
|
38
|
+
['FechaHoraHusoGenRegistro', input.fechaHoraHusoGenRegistro],
|
|
39
|
+
]);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Construye la cadena canónica a hashear de un registro de anulación.
|
|
43
|
+
*/
|
|
44
|
+
export function concatenateRegistroAnulacion(input) {
|
|
45
|
+
return concatenateFields([
|
|
46
|
+
['IDEmisorFacturaAnulada', input.idEmisorFacturaAnulada],
|
|
47
|
+
['NumSerieFacturaAnulada', input.numSerieFacturaAnulada],
|
|
48
|
+
['FechaExpedicionFacturaAnulada', input.fechaExpedicionFacturaAnulada],
|
|
49
|
+
['Huella', input.huellaAnterior],
|
|
50
|
+
['FechaHoraHusoGenRegistro', input.fechaHoraHusoGenRegistro],
|
|
51
|
+
]);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Calcula la huella (hash) de un registro de alta.
|
|
55
|
+
*/
|
|
56
|
+
export function computeRegistroAlta(input) {
|
|
57
|
+
return sha256(concatenateRegistroAlta(input));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Calcula la huella (hash) de un registro de anulación.
|
|
61
|
+
*/
|
|
62
|
+
export function computeRegistroAnulacion(input) {
|
|
63
|
+
return sha256(concatenateRegistroAnulacion(input));
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Verifica que el hash de un registro de alta coincide con el esperado.
|
|
67
|
+
*/
|
|
68
|
+
export function verifyRegistroAlta(input, expectedHash) {
|
|
69
|
+
return computeRegistroAlta(input).toLowerCase() === expectedHash.toLowerCase();
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Verifica que el hash de un registro de anulación coincide con el esperado.
|
|
73
|
+
*/
|
|
74
|
+
export function verifyRegistroAnulacion(input, expectedHash) {
|
|
75
|
+
return computeRegistroAnulacion(input).toLowerCase() === expectedHash.toLowerCase();
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Cadena de hash con estado, para encadenar registros de forma secuencial.
|
|
79
|
+
*/
|
|
80
|
+
export class HashChain {
|
|
81
|
+
_lastHash = null;
|
|
82
|
+
_count = 0;
|
|
83
|
+
/** Hash del último registro encadenado, o `null` si aún no hay ninguno. */
|
|
84
|
+
get lastHash() {
|
|
85
|
+
return this._lastHash;
|
|
86
|
+
}
|
|
87
|
+
/** Número de registros encadenados hasta ahora. */
|
|
88
|
+
get count() {
|
|
89
|
+
return this._count;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Encadena un nuevo registro de alta y devuelve su huella.
|
|
93
|
+
*/
|
|
94
|
+
pushAlta(input) {
|
|
95
|
+
const hash = computeRegistroAlta({ ...input, huellaAnterior: this._lastHash });
|
|
96
|
+
this._lastHash = hash;
|
|
97
|
+
this._count += 1;
|
|
98
|
+
return hash;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Encadena un nuevo registro de anulación y devuelve su huella.
|
|
102
|
+
*/
|
|
103
|
+
pushAnulacion(input) {
|
|
104
|
+
const hash = computeRegistroAnulacion({ ...input, huellaAnterior: this._lastHash });
|
|
105
|
+
this._lastHash = hash;
|
|
106
|
+
this._count += 1;
|
|
107
|
+
return hash;
|
|
108
|
+
}
|
|
109
|
+
/** Reinicia la cadena. */
|
|
110
|
+
reset() {
|
|
111
|
+
this._lastHash = null;
|
|
112
|
+
this._count = 0;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=chain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain.js","sourceRoot":"","sources":["../../../src/core/hash/chain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/hash/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/hash/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tipos de evento de registro Verifactu.
|
|
3
|
+
* - ALTA: alta de una factura.
|
|
4
|
+
* - ANULACION: anulación de una factura previamente registrada.
|
|
5
|
+
* - MODIFICACION: modificación de una factura.
|
|
6
|
+
*/
|
|
7
|
+
export type EventType = 'ALTA' | 'ANULACION' | 'MODIFICACION';
|
|
8
|
+
/**
|
|
9
|
+
* Evento de registro Verifactu.
|
|
10
|
+
*/
|
|
11
|
+
export interface Event {
|
|
12
|
+
/** Tipo de evento. */
|
|
13
|
+
type: EventType;
|
|
14
|
+
/** Fecha/hora del evento en formato ISO 8601. */
|
|
15
|
+
fechaHora: string;
|
|
16
|
+
/** Referencia a la factura asociada. */
|
|
17
|
+
invoiceId: string;
|
|
18
|
+
/** Motivo de anulación (obligatorio si type === 'ANULACION'). */
|
|
19
|
+
motivoAnulacion?: string;
|
|
20
|
+
/** Referencia a la factura que se anula (para ANULACION). */
|
|
21
|
+
facturaAnulada?: string;
|
|
22
|
+
/** Metadatos adicionales. */
|
|
23
|
+
metadata?: Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=event.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../../src/core/models/event.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,WAAW,GAAG,cAAc,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,sBAAsB;IACtB,IAAI,EAAE,SAAS,CAAC;IAChB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event.js","sourceRoot":"","sources":["../../../src/core/models/event.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/models/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/models/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Datos identificativos del emisor de la factura.
|
|
3
|
+
* Verifactu exige identificar al emisor (NIF, nombre/razón social).
|
|
4
|
+
*/
|
|
5
|
+
export interface Emisor {
|
|
6
|
+
/** NIF del emisor. */
|
|
7
|
+
nif: string;
|
|
8
|
+
/** Nombre o razón social. */
|
|
9
|
+
nombreRazon: string;
|
|
10
|
+
/** Código de país (ISO 3166-1 alpha-2). Opcional si es España. */
|
|
11
|
+
pais?: string;
|
|
12
|
+
/** Código postal. */
|
|
13
|
+
codigoPostal?: string;
|
|
14
|
+
/** Municipio. */
|
|
15
|
+
municipio?: string;
|
|
16
|
+
/** Dirección. */
|
|
17
|
+
direccion?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Identificación de la factura.
|
|
21
|
+
*/
|
|
22
|
+
export interface FacturaId {
|
|
23
|
+
/** Serie de la factura (opcional). */
|
|
24
|
+
serie?: string;
|
|
25
|
+
/** Número de la factura. */
|
|
26
|
+
numero: string;
|
|
27
|
+
/** Fecha de expedición en formato ISO (YYYY-MM-DD). */
|
|
28
|
+
fechaExpedicion: string;
|
|
29
|
+
/** Fecha de operación (opcional). */
|
|
30
|
+
fechaOperacion?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Tipo de factura Verifactu (F1–F9).
|
|
34
|
+
*/
|
|
35
|
+
export type TipoFactura = 'F1' | 'F2' | 'F3' | 'F4' | 'F5' | 'F6' | 'F7' | 'F8' | 'F9';
|
|
36
|
+
/**
|
|
37
|
+
* Tipo de desglose Verifactu (S1–S6).
|
|
38
|
+
*/
|
|
39
|
+
export type TipoDesglose = 'S1' | 'S2' | 'S3' | 'S4' | 'S5' | 'S6';
|
|
40
|
+
/**
|
|
41
|
+
* Detalle de IVA de una línea de desglose.
|
|
42
|
+
*/
|
|
43
|
+
export interface DetalleIva {
|
|
44
|
+
/** Tipo impositivo (%). */
|
|
45
|
+
tipoImpositivo: number;
|
|
46
|
+
/** Base imponible. */
|
|
47
|
+
baseImponible: number;
|
|
48
|
+
/** Cuota repercutida. */
|
|
49
|
+
cuotaRepercutida: number;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Desglose de la operación por tipo de operación e IVA.
|
|
53
|
+
*/
|
|
54
|
+
export interface DesgloseTipoOperacion {
|
|
55
|
+
/** Clave de tipo de operación (p. ej. '01'). */
|
|
56
|
+
tipoOperacion: string;
|
|
57
|
+
/** Detalles de IVA. */
|
|
58
|
+
detallesIva: DetalleIva[];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Desglose completo de la factura.
|
|
62
|
+
*/
|
|
63
|
+
export interface Desglose {
|
|
64
|
+
/** Desglose por tipo de operación. */
|
|
65
|
+
tipoOperaciones: DesgloseTipoOperacion[];
|
|
66
|
+
/** Cuota total de la factura. */
|
|
67
|
+
cuotaTotal: number;
|
|
68
|
+
/** Importe total de la factura. */
|
|
69
|
+
importeTotal: number;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Factura en el modelo de datos Verifactu.
|
|
73
|
+
*/
|
|
74
|
+
export interface Invoice {
|
|
75
|
+
/** Identificación de la factura. */
|
|
76
|
+
id: FacturaId;
|
|
77
|
+
/** Emisor de la factura. */
|
|
78
|
+
emisor: Emisor;
|
|
79
|
+
/** Desglose de la factura. */
|
|
80
|
+
desglose: Desglose;
|
|
81
|
+
/** Tipo de factura. */
|
|
82
|
+
tipoFactura: TipoFactura;
|
|
83
|
+
/** Tipo de desglose. */
|
|
84
|
+
tipoDesglose: TipoDesglose;
|
|
85
|
+
/** Descripción de la operación. */
|
|
86
|
+
descripcion?: string;
|
|
87
|
+
/** Metadatos adicionales libres. */
|
|
88
|
+
metadata?: Record<string, unknown>;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=invoice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invoice.d.ts","sourceRoot":"","sources":["../../../src/core/models/invoice.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,sBAAsB;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,eAAe,EAAE,MAAM,CAAC;IACxB,qCAAqC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GACnB,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,CAAC;AAET;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,2BAA2B;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,sBAAsB;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,yBAAyB;IACzB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,gDAAgD;IAChD,aAAa,EAAE,MAAM,CAAC;IACtB,uBAAuB;IACvB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,sCAAsC;IACtC,eAAe,EAAE,qBAAqB,EAAE,CAAC;IACzC,iCAAiC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,oCAAoC;IACpC,EAAE,EAAE,SAAS,CAAC;IACd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,QAAQ,EAAE,QAAQ,CAAC;IACnB,uBAAuB;IACvB,WAAW,EAAE,WAAW,CAAC;IACzB,wBAAwB;IACxB,YAAY,EAAE,YAAY,CAAC;IAC3B,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invoice.js","sourceRoot":"","sources":["../../../src/core/models/invoice.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/qr/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/qr/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Construye el payload del QR Verifactu.
|
|
3
|
+
*
|
|
4
|
+
* El QR Verifactu codifica una URL de verificación que incluye el hash del
|
|
5
|
+
* registro, de modo que cualquier persona pueda verificar la integridad de
|
|
6
|
+
* la factura contra la AEAT.
|
|
7
|
+
*
|
|
8
|
+
* @param hash Hash del registro (encadenado).
|
|
9
|
+
* @param baseUrl URL base de verificación de la AEAT.
|
|
10
|
+
* @param extraParams Parámetros adicionales a incluir en la URL.
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildQrPayload(hash: string, baseUrl?: string, extraParams?: Record<string, string>): string;
|
|
13
|
+
//# sourceMappingURL=qr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr.d.ts","sourceRoot":"","sources":["../../../src/core/qr/qr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,SAA8D,EACrE,WAAW,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACvC,MAAM,CAGR"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Construye el payload del QR Verifactu.
|
|
3
|
+
*
|
|
4
|
+
* El QR Verifactu codifica una URL de verificación que incluye el hash del
|
|
5
|
+
* registro, de modo que cualquier persona pueda verificar la integridad de
|
|
6
|
+
* la factura contra la AEAT.
|
|
7
|
+
*
|
|
8
|
+
* @param hash Hash del registro (encadenado).
|
|
9
|
+
* @param baseUrl URL base de verificación de la AEAT.
|
|
10
|
+
* @param extraParams Parámetros adicionales a incluir en la URL.
|
|
11
|
+
*/
|
|
12
|
+
export function buildQrPayload(hash, baseUrl = 'https://www2.agenciatributaria.gob.es/verifactu/verificar', extraParams = {}) {
|
|
13
|
+
const params = new URLSearchParams({ hash, ...extraParams });
|
|
14
|
+
return `${baseUrl}?${params.toString()}`;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=qr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr.js","sourceRoot":"","sources":["../../../src/core/qr/qr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAY,EACZ,OAAO,GAAG,2DAA2D,EACrE,cAAsC,EAAE;IAExC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,IAAI,EAAE,GAAG,WAAW,EAAE,CAAC,CAAC;IAC7D,OAAO,GAAG,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;AAC3C,CAAC"}
|