@controldealquiler/sdk 0.0.0-stage → 1.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/LICENSE +41 -0
- package/README.md +203 -2
- package/THIRD_PARTY_NOTICES +217 -0
- package/dist/cli.js +214 -0
- package/dist/index.d.ts +739 -0
- package/dist/index.js +186 -0
- package/package.json +39 -4
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,739 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
interface OpcionesHttp {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
baseUrl?: string;
|
|
5
|
+
fetch?: typeof fetch;
|
|
6
|
+
/** Reintentos máximos tras el primer intento (por defecto 3). */
|
|
7
|
+
maxReintentos?: number;
|
|
8
|
+
}
|
|
9
|
+
interface Peticion {
|
|
10
|
+
metodo: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
11
|
+
ruta: string;
|
|
12
|
+
cuerpo?: unknown;
|
|
13
|
+
/** Cuerpo ya formado (p. ej. multipart); sustituye a `cuerpo`. */
|
|
14
|
+
cuerpoCrudo?: BodyInit;
|
|
15
|
+
query?: Record<string, string | number | undefined>;
|
|
16
|
+
/** `false` fuerza sin clave; un string fija la clave (para repetir una llamada en otro proceso). */
|
|
17
|
+
idempotencia?: boolean | string;
|
|
18
|
+
cabeceras?: Record<string, string>;
|
|
19
|
+
/** Recibe las cabeceras de la respuesta recibida (la última, tras los reintentos), sea o no un error. */
|
|
20
|
+
alResponder?: (cabeceras: Headers) => void;
|
|
21
|
+
}
|
|
22
|
+
declare class ErrorApiSdk extends Error {
|
|
23
|
+
readonly status: number;
|
|
24
|
+
readonly code: string;
|
|
25
|
+
readonly problema: unknown;
|
|
26
|
+
readonly requestId: string | null;
|
|
27
|
+
/** `requestId`: cabecera `X-Request-Id` de la respuesta de error (o `null`); para citar el fallo al soporte. */
|
|
28
|
+
constructor(status: number, code: string, problema: unknown, requestId?: string | null);
|
|
29
|
+
}
|
|
30
|
+
declare const URL_BASE_SANDBOX = "https://sandbox.controldealquiler.com/api";
|
|
31
|
+
/** Cruce de entornos: una key de producción contra el sandbox, o una de pruebas contra producción. Se lanza antes de `fetch`. */
|
|
32
|
+
declare class ErrorDeEntorno extends Error {
|
|
33
|
+
readonly code: 'KEY_DE_PRODUCCION' | 'KEY_DE_PRUEBAS';
|
|
34
|
+
constructor(code: 'KEY_DE_PRODUCCION' | 'KEY_DE_PRUEBAS');
|
|
35
|
+
}
|
|
36
|
+
declare const admiteIdempotencia: (metodo: string, ruta: string) => boolean;
|
|
37
|
+
declare function esperaDeRetryAfter(valor: string | null, intento: number, ahora?: number): number;
|
|
38
|
+
declare function crearHttp(o: OpcionesHttp): {
|
|
39
|
+
peticion: <T = unknown>(p: Peticion) => Promise<T>;
|
|
40
|
+
};
|
|
41
|
+
type Http = ReturnType<typeof crearHttp>;
|
|
42
|
+
|
|
43
|
+
declare function bytesToBase64(bytes: Uint8Array): string;
|
|
44
|
+
declare function base64ToBytes(b64: string): Uint8Array;
|
|
45
|
+
|
|
46
|
+
interface Sobre {
|
|
47
|
+
wrapped_key: Uint8Array;
|
|
48
|
+
cipher: Uint8Array;
|
|
49
|
+
iv: Uint8Array;
|
|
50
|
+
}
|
|
51
|
+
interface FicheroSellado {
|
|
52
|
+
/** iv||cipher: se sube tal cual al bucket (formato del vault). */
|
|
53
|
+
blob: Uint8Array;
|
|
54
|
+
wrapped_file_key: Uint8Array;
|
|
55
|
+
nombre_cipher: Uint8Array;
|
|
56
|
+
nombre_iv: Uint8Array;
|
|
57
|
+
}
|
|
58
|
+
/** (Sin AAD en AES-GCM, compatible con `envelope.ts` tal cual: el formato no ata el sobre a su cliente.) */
|
|
59
|
+
/** Sella un JSON con la pública del destinatario (un único sobre). */
|
|
60
|
+
declare function sellarJson(valor: unknown, publicaSpki: Uint8Array): Promise<Sobre>;
|
|
61
|
+
/** Abre un sobre con la privada (CryptoKey RSA-OAEP con `decrypt`). */
|
|
62
|
+
declare function abrirJson<T = unknown>(sobre: Sobre, privada: CryptoKey): Promise<T>;
|
|
63
|
+
/** Sella un fichero: clave de fichero aleatoria envuelta; el nombre, sellado con esa misma clave. */
|
|
64
|
+
declare function sellarFichero(contenido: Uint8Array, nombre: string, publicaSpki: Uint8Array): Promise<FicheroSellado>;
|
|
65
|
+
declare function abrirNombreFichero(f: Pick<FicheroSellado, 'wrapped_file_key' | 'nombre_cipher' | 'nombre_iv'>, privada: CryptoKey): Promise<string>;
|
|
66
|
+
declare function abrirContenidoFichero(blob: Uint8Array, wrappedFileKey: Uint8Array, privada: CryptoKey): Promise<Uint8Array>;
|
|
67
|
+
/**
|
|
68
|
+
* Vuelve a envolver la clave de un fichero: la abre con la privada de la agencia y la sella con la pública del
|
|
69
|
+
* cliente. El contenido del objeto no cambia (sigue cifrado con la misma clave); solo cambia a quién se le abre.
|
|
70
|
+
*/
|
|
71
|
+
declare function reenvolverClave(wrapped: Uint8Array, privada: CryptoKey, publicaSpki: Uint8Array): Promise<Uint8Array>;
|
|
72
|
+
|
|
73
|
+
interface SobreB64Cliente {
|
|
74
|
+
wrapped_key_b64: string;
|
|
75
|
+
cipher_b64: string;
|
|
76
|
+
iv_b64: string;
|
|
77
|
+
}
|
|
78
|
+
declare function sellarSobreB64(valor: unknown, spkiB64: string): Promise<SobreB64Cliente>;
|
|
79
|
+
|
|
80
|
+
/** Abre un sobre y devuelve los bytes en claro (el `Descifrador` devuelve bytes; el JSON lo interpreta quien llama). */
|
|
81
|
+
declare function abrirSobreBytes(sobre: Sobre, privada: CryptoKey): Promise<Uint8Array>;
|
|
82
|
+
/** Importa una privada PKCS#8 (DER) como clave RSA-OAEP-SHA256 de solo descifrar. */
|
|
83
|
+
declare function importarPrivadaPkcs8(pkcs8: Uint8Array): Promise<CryptoKey>;
|
|
84
|
+
/** SHA-256 en hexadecimal (el hash del fichero en claro que se declara al subirlo). */
|
|
85
|
+
declare function sha256Hex(bytes: Uint8Array): Promise<string>;
|
|
86
|
+
/** Sobre en la forma JSON de la API (`*_b64`) -> bytes. */
|
|
87
|
+
declare function sobreDeB64(s: {
|
|
88
|
+
wrapped_key_b64: string;
|
|
89
|
+
cipher_b64: string;
|
|
90
|
+
iv_b64: string;
|
|
91
|
+
}): Sobre;
|
|
92
|
+
|
|
93
|
+
interface Descifrador {
|
|
94
|
+
abrirSobre(s: Sobre): Promise<Uint8Array>;
|
|
95
|
+
/** Pública SPKI (base64) de la agencia: a quién se sellan los ficheros subidos. */
|
|
96
|
+
publicaAgenciaSpki(): Promise<string>;
|
|
97
|
+
/**
|
|
98
|
+
* La privada de sobres de la agencia como clave no extraíble, solo en memoria del proceso. La usa `clientes.crear` para
|
|
99
|
+
* re-envolver las claves de los ficheros hacia la llave efímera del alta (el mismo `sellarBorradorParaEfimera` del panel).
|
|
100
|
+
*/
|
|
101
|
+
clavePrivadaSobres(): Promise<CryptoKey>;
|
|
102
|
+
}
|
|
103
|
+
interface OrigenClaveIntegracion {
|
|
104
|
+
/** El PEM mismo (p. ej. sacado de un gestor de secretos). Gana a la variable de entorno y al fichero. */
|
|
105
|
+
pem?: string;
|
|
106
|
+
/** Ruta a un fichero PEM. Solo se lee si no hay `pem` ni variable de entorno. */
|
|
107
|
+
ruta?: string;
|
|
108
|
+
/** Entorno donde buscar `CDA_CLAVE_INTEGRACION_PEM`. Por defecto `process.env`. */
|
|
109
|
+
env?: Record<string, string | undefined>;
|
|
110
|
+
}
|
|
111
|
+
/** Un PEM inválido (o cifrado con contraseña, que el SDK no acepta) da este error fijo: nunca lleva el contenido. */
|
|
112
|
+
declare class ErrorClaveIntegracion extends Error {
|
|
113
|
+
constructor(m: string);
|
|
114
|
+
}
|
|
115
|
+
/** Lee la privada de integración (PEM PKCS#8, sin contraseña) de un fichero. Para leerla también de la opción `pem` o de `CDA_CLAVE_INTEGRACION_PEM` (gestor de secretos, variable de entorno o fichero), usa `descifradorDeClave`. */
|
|
116
|
+
declare function descifradorDeFichero(rutaPem: string, sobreIntegracion: Sobre): Descifrador;
|
|
117
|
+
/** Como `descifradorDeFichero`, con la privada desde el PEM, la variable `CDA_CLAVE_INTEGRACION_PEM` o un fichero, por ese orden. */
|
|
118
|
+
declare function descifradorDeClave(origen: OrigenClaveIntegracion, sobreIntegracion: Sobre): Descifrador;
|
|
119
|
+
|
|
120
|
+
declare const LEASE_WARNING_CODES: readonly ["avalistas_excluidos", "fin_calculado_por_duracion", "mas_de_4_inquilinos", "telefono_sin_atribuir"];
|
|
121
|
+
type LeaseWarningCode = (typeof LEASE_WARNING_CODES)[number];
|
|
122
|
+
|
|
123
|
+
interface ParsedLeaseTenant {
|
|
124
|
+
name: string;
|
|
125
|
+
nif: string | null;
|
|
126
|
+
phone: string | null;
|
|
127
|
+
email: string | null;
|
|
128
|
+
}
|
|
129
|
+
interface ParsedLeaseContract {
|
|
130
|
+
raw_response: string;
|
|
131
|
+
tenants: ParsedLeaseTenant[];
|
|
132
|
+
contract_date: string | null;
|
|
133
|
+
start_date: string | null;
|
|
134
|
+
end_date: string | null;
|
|
135
|
+
monthly_rent: number | null;
|
|
136
|
+
confidence: number | null;
|
|
137
|
+
warning_codes: LeaseWarningCode[];
|
|
138
|
+
/** RC de 20 caracteres con dígitos de control correctos, en mayúsculas y sin repetir. */
|
|
139
|
+
cadastral_refs: string[];
|
|
140
|
+
/** Dirección de la vivienda tal como consta (una línea, sin trocear), máx. 200 caracteres. */
|
|
141
|
+
property_address: string | null;
|
|
142
|
+
/**
|
|
143
|
+
* Solo el lector sin IA de las agencias (`lib/agencia/lectores/contrato.ts`) lo fija, tras parsear (este parser nunca lo lee del JSON): la RC de la VIVIENDA que se importa a su
|
|
144
|
+
* ficha (ya validada por dígitos de control), o null si el contrato no la fija. Ausente en la lectura por IA.
|
|
145
|
+
*/
|
|
146
|
+
cadastral_ref_vivienda?: string | null;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
type MotivoContrato = 'contrato_no_reconocido' | 'sin_inquilinos' | 'firma_no_consta' | 'firma_incoherente' | 'sello_otro_anio' | 'sin_inicio' | 'sin_duracion' | 'fin_no_calculable' | 'sin_renta' | 'renta_no_mensual' | 'renta_ambigua' | 'fecha_inexistente' | 'error_interno';
|
|
150
|
+
|
|
151
|
+
interface VentanaEjercicios {
|
|
152
|
+
anios: number[];
|
|
153
|
+
/** YYYY-MM: último mes admitido del año del alta. */
|
|
154
|
+
hastaMes: string;
|
|
155
|
+
/** Fecha (YYYY-MM-DD) del fin de campaña del año anterior si este sigue incluido; si no, null. */
|
|
156
|
+
caducaAntesDe: string | null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Lo que dice la certificación de la agencia (`agencia_lector`): qué parser y qué conceptos están certificados. */
|
|
160
|
+
interface LectorCertificado {
|
|
161
|
+
parser: string;
|
|
162
|
+
conceptos: string[];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
type MotivoAlta = MotivoContrato | 'sin_texto' | 'lector_fallo' | 'concepto_no_certificado' | 'resumen_anual' | 'fuera_de_ventana' | 'demasiado_grande' | 'tope';
|
|
166
|
+
/** Lo único que se guarda de un contrato leído: fechas, renta y recuento. Sin nombres, NIF ni dirección. */
|
|
167
|
+
interface HuellaAlta {
|
|
168
|
+
inicio: string | null;
|
|
169
|
+
fin: string | null;
|
|
170
|
+
firma: string | null;
|
|
171
|
+
renta: number | null;
|
|
172
|
+
nInquilinos: number;
|
|
173
|
+
parser: string;
|
|
174
|
+
version: string;
|
|
175
|
+
}
|
|
176
|
+
/** Fila de un movimiento: solo importes, fechas y categoría fiscal (constantes del sistema). Sin texto libre. */
|
|
177
|
+
interface FilaAlta {
|
|
178
|
+
tipo: 'income' | 'expense';
|
|
179
|
+
categoria: string;
|
|
180
|
+
importe: number;
|
|
181
|
+
/** Emisión de la factura o pago de la renta (YYYY-MM-DD). */
|
|
182
|
+
fecha: string;
|
|
183
|
+
/** Fecha de imputación de la transacción (YYYY-MM-DD): la que se compara con la ventana. */
|
|
184
|
+
devengo: string;
|
|
185
|
+
/** Periodo de servicio de la fila (YYYY-MM-DD) o `null`: lo que lee el lector, no texto. */
|
|
186
|
+
periodo_desde: string | null;
|
|
187
|
+
periodo_hasta: string | null;
|
|
188
|
+
/** Página del PDF en la que sale la fila (para citarla), o `null`. */
|
|
189
|
+
pagina: number | null;
|
|
190
|
+
}
|
|
191
|
+
type ResultadoLecturaAlta = {
|
|
192
|
+
ok: true;
|
|
193
|
+
tipo: 'contrato';
|
|
194
|
+
contrato: ParsedLeaseContract;
|
|
195
|
+
huella: HuellaAlta;
|
|
196
|
+
direccion: string | null;
|
|
197
|
+
} | {
|
|
198
|
+
ok: true;
|
|
199
|
+
tipo: 'movimiento';
|
|
200
|
+
filas: FilaAlta[];
|
|
201
|
+
huella: string[];
|
|
202
|
+
parser: string;
|
|
203
|
+
version: string;
|
|
204
|
+
direccion: string | null;
|
|
205
|
+
conceptos: string[];
|
|
206
|
+
aRevision: 'prorrata' | null;
|
|
207
|
+
emision: string | null;
|
|
208
|
+
/** Filas leídas pero fuera de la ventana de ejercicios: se quitan con aviso. */
|
|
209
|
+
filasFuera: number;
|
|
210
|
+
/**
|
|
211
|
+
* Rótulo de cada fila de `filas` (mismo orden, ≤200 caracteres): texto libre del PDF. NUNCA va a la BD ni a la
|
|
212
|
+
* respuesta del servidor (`lecturaAGuardar` y `respuestaDe` eligen campos a mano): solo lo usa el navegador de la
|
|
213
|
+
* agencia para el sobre E2EE del titular, donde es el concepto de la transacción.
|
|
214
|
+
*/
|
|
215
|
+
rotulos: string[];
|
|
216
|
+
} | {
|
|
217
|
+
ok: false;
|
|
218
|
+
motivo: MotivoAlta;
|
|
219
|
+
transitorio: boolean;
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
/** Mismo tope que el servidor y el navegador (`leer-alta-navegador.ts`, `leer-fichero.ts`). */
|
|
223
|
+
declare const TOPE_BYTES = 4000000;
|
|
224
|
+
/** Lector vivo de la agencia: `parser` y conceptos certificados (constantes del sistema, sin PII). */
|
|
225
|
+
type LectorVigente = LectorCertificado;
|
|
226
|
+
/** Cajas que se leen en local (las demás no tienen lector). */
|
|
227
|
+
type CajaLectura = 'contract' | 'movimientos';
|
|
228
|
+
type SalidaLectorLocal = {
|
|
229
|
+
resultado: Record<string, unknown>;
|
|
230
|
+
textoSha256: string | undefined;
|
|
231
|
+
} | {
|
|
232
|
+
demasiadoGrande: true;
|
|
233
|
+
};
|
|
234
|
+
interface OpcionesLector {
|
|
235
|
+
caja: CajaLectura;
|
|
236
|
+
lector: LectorVigente | null;
|
|
237
|
+
/** El servidor aplica la ventana: aquí se lee con una ventana abierta, igual que el navegador. */
|
|
238
|
+
ventana?: VentanaEjercicios;
|
|
239
|
+
mime?: string;
|
|
240
|
+
/** Solo para los tests: sustituye a pdf.js. */
|
|
241
|
+
extraer?: (b: Uint8Array) => Promise<string | null>;
|
|
242
|
+
}
|
|
243
|
+
declare function leerFicheroLocal(bytes: Uint8Array, a: OpcionesLector): Promise<SalidaLectorLocal>;
|
|
244
|
+
interface Borradores {
|
|
245
|
+
/**
|
|
246
|
+
* Lee un fichero del borrador: JSON con el resultado de la lectura local; si la API responde `409 AGENCIA_MODO_SERVIDOR`,
|
|
247
|
+
* multipart con el fichero. Un fichero de más de 4 MB se notifica como el navegador (`demasiado_grande`, definitivo).
|
|
248
|
+
*/
|
|
249
|
+
leer(b: string, f: string, bytes: Uint8Array, a: OpcionesLector): Promise<unknown>;
|
|
250
|
+
/**
|
|
251
|
+
* Lo mismo que `leer`, pero devuelve además la lectura local (contrato, dirección y rótulos, que no viajan a la API) para quien
|
|
252
|
+
* arma el alta (`clientes.crear`). `local` es `null` si se leyó por multipart (la lectura la hizo el servidor) o si pesa más de 4 MB.
|
|
253
|
+
*/
|
|
254
|
+
leerDetalle(b: string, f: string, bytes: Uint8Array, a: OpcionesLector): Promise<{
|
|
255
|
+
respuesta: unknown;
|
|
256
|
+
local: ResultadoLecturaAlta | null;
|
|
257
|
+
}>;
|
|
258
|
+
}
|
|
259
|
+
declare function crearBorradores(http: Http): Borradores;
|
|
260
|
+
|
|
261
|
+
/** Todas las cajas de un fichero del alta: `acta` (0 o 1 por contrato) y `movimientos` solo van con paquete. */
|
|
262
|
+
declare const CAJAS: readonly ["contract", "tenant_id", "other", "acta", "movimientos", "foto"];
|
|
263
|
+
type Caja = (typeof CAJAS)[number];
|
|
264
|
+
|
|
265
|
+
type PasoAlta = 'validar' | 'foto' | 'abrir' | 'vivienda' | 'fichero' | 'leer' | 'cotejar' | 'listo' | 'paquete' | 'lote' | 'enlace';
|
|
266
|
+
type Creado = true | false | 'desconocido';
|
|
267
|
+
type Consejo = 'repetir' | 'manifiesto' | 'cuenta';
|
|
268
|
+
interface ContextoAlta {
|
|
269
|
+
ref: string;
|
|
270
|
+
paso: PasoAlta;
|
|
271
|
+
vivienda?: string | number;
|
|
272
|
+
caja?: string;
|
|
273
|
+
fichero?: number;
|
|
274
|
+
loteId?: string;
|
|
275
|
+
indice?: number;
|
|
276
|
+
clientId?: string;
|
|
277
|
+
creado: Creado;
|
|
278
|
+
}
|
|
279
|
+
declare class ErrorAlta extends ErrorApiSdk {
|
|
280
|
+
readonly ref: string;
|
|
281
|
+
readonly paso: PasoAlta;
|
|
282
|
+
readonly vivienda?: string | number;
|
|
283
|
+
readonly caja?: string;
|
|
284
|
+
readonly fichero?: number;
|
|
285
|
+
readonly loteId?: string;
|
|
286
|
+
readonly indice?: number;
|
|
287
|
+
readonly clientId?: string;
|
|
288
|
+
readonly creado: Creado;
|
|
289
|
+
readonly reintentable: boolean;
|
|
290
|
+
readonly consejo: Consejo;
|
|
291
|
+
readonly corta: boolean;
|
|
292
|
+
constructor(ctx: ContextoAlta, info: {
|
|
293
|
+
status: number;
|
|
294
|
+
code: string;
|
|
295
|
+
requestId: string | null;
|
|
296
|
+
problema: unknown;
|
|
297
|
+
}, clase: {
|
|
298
|
+
reintentable: boolean;
|
|
299
|
+
consejo: Consejo;
|
|
300
|
+
corta: boolean;
|
|
301
|
+
}, causa?: unknown);
|
|
302
|
+
}
|
|
303
|
+
declare function codigoDe(err: unknown): {
|
|
304
|
+
status: number;
|
|
305
|
+
code: string;
|
|
306
|
+
requestId: string | null;
|
|
307
|
+
};
|
|
308
|
+
declare function clasificar(code: string, status: number, ctx: ContextoAlta): {
|
|
309
|
+
reintentable: boolean;
|
|
310
|
+
consejo: Consejo;
|
|
311
|
+
corta: boolean;
|
|
312
|
+
};
|
|
313
|
+
/** Envuelve cualquier fallo del alta en `ErrorAlta`; si ya lo es, lo devuelve tal cual. */
|
|
314
|
+
declare function envolver(err: unknown, ctx: ContextoAlta): ErrorAlta;
|
|
315
|
+
|
|
316
|
+
interface OpcionesVarios {
|
|
317
|
+
aLaVez?: 1 | 2;
|
|
318
|
+
repetir?: 0 | 1 | 2;
|
|
319
|
+
}
|
|
320
|
+
interface FallidoAlta extends ContextoAlta {
|
|
321
|
+
status: number;
|
|
322
|
+
code: string;
|
|
323
|
+
requestId: string | null;
|
|
324
|
+
reintentable: boolean;
|
|
325
|
+
consejo: Consejo;
|
|
326
|
+
intentos: number;
|
|
327
|
+
}
|
|
328
|
+
interface InformeVarios {
|
|
329
|
+
completados: Array<ResultadoAlta & {
|
|
330
|
+
ref: string;
|
|
331
|
+
intentos: number;
|
|
332
|
+
}>;
|
|
333
|
+
fallidos: FallidoAlta[];
|
|
334
|
+
noIntentados: string[];
|
|
335
|
+
cortadoPor: {
|
|
336
|
+
status: number;
|
|
337
|
+
code: string;
|
|
338
|
+
requestId: string | null;
|
|
339
|
+
} | null;
|
|
340
|
+
}
|
|
341
|
+
declare function crearVarios(alta: (e: EntradaAlta, previo?: {
|
|
342
|
+
creado: Creado;
|
|
343
|
+
}) => Promise<ResultadoAlta>, entradas: EntradaAlta[], o?: OpcionesVarios, dormir?: (ms: number) => Promise<void>): Promise<InformeVarios>;
|
|
344
|
+
|
|
345
|
+
interface FicheroAlta {
|
|
346
|
+
caja: Caja;
|
|
347
|
+
nombre: string;
|
|
348
|
+
bytes: Uint8Array;
|
|
349
|
+
mime: string;
|
|
350
|
+
}
|
|
351
|
+
interface ViviendaAlta {
|
|
352
|
+
ref?: string;
|
|
353
|
+
provincia: string;
|
|
354
|
+
municipio?: string;
|
|
355
|
+
direccion: string;
|
|
356
|
+
/**
|
|
357
|
+
* Código postal (5 cifras), OBLIGATORIO: el sobre de la vivienda lo exige (`sobreViviendaSchema`) y el dueño lo ve. Desvío
|
|
358
|
+
* del plan (su interfaz no lo traía); nunca se inventa uno (decisión de la Reina, 28-10).
|
|
359
|
+
*/
|
|
360
|
+
cp: string;
|
|
361
|
+
ficheros: FicheroAlta[];
|
|
362
|
+
}
|
|
363
|
+
interface EntradaAlta {
|
|
364
|
+
ref: string;
|
|
365
|
+
email: string;
|
|
366
|
+
nombre?: string;
|
|
367
|
+
viviendas: ViviendaAlta[];
|
|
368
|
+
}
|
|
369
|
+
interface ResultadoAlta {
|
|
370
|
+
estado: 'creado' | 'ya_existia';
|
|
371
|
+
clientId: string;
|
|
372
|
+
/** Enlace para el titular, o `'activado'` si la cuenta ya está activa (no hay enlace que entregar). */
|
|
373
|
+
enlace: string | 'activado';
|
|
374
|
+
correo: 'enviado' | 'no_enviado';
|
|
375
|
+
motivo?: 'CUPO_DIARIO' | 'ENTORNO_PRUEBAS';
|
|
376
|
+
}
|
|
377
|
+
interface DepsAlta {
|
|
378
|
+
http: Http;
|
|
379
|
+
borradores: Borradores;
|
|
380
|
+
descifrador: Descifrador;
|
|
381
|
+
/** `fetch` para subir los objetos a la URL firmada del Storage. */
|
|
382
|
+
fetch?: typeof fetch;
|
|
383
|
+
/** Origen del sitio (`https://controldealquiler.com`) para componer el enlace. */
|
|
384
|
+
origen: string;
|
|
385
|
+
/** Solo para los tests: sustituye a pdf.js. */
|
|
386
|
+
extraer?: OpcionesLector['extraer'];
|
|
387
|
+
/** «Hoy» de Madrid para validar los contratos; por defecto `lib/time/madrid.ts`. */
|
|
388
|
+
hoy?: () => string;
|
|
389
|
+
/** Espera entre sondeos del lote y entre reintentos de lectura (ms). */
|
|
390
|
+
intervaloMs?: number;
|
|
391
|
+
/** Cuánto se espera el resultado del lote antes de rendirse (ms). Por defecto 120 s. */
|
|
392
|
+
maxEsperaMs?: number;
|
|
393
|
+
dormir?: (ms: number) => Promise<void>;
|
|
394
|
+
/**
|
|
395
|
+
* Ficheros de una misma vivienda que se suben y leen a la vez (entero de 1 a 8; fuera de rango se acota). Si no se fija,
|
|
396
|
+
* se usa la sugerencia del servidor (`GET /v1/yo` → `limites.concurrencia_ficheros`) y, si falta o falla, 4.
|
|
397
|
+
* 1 los procesa uno tras otro. Las viviendas siguen en serie. Cada fichero cuesta unas 3 llamadas a la API y la API admite
|
|
398
|
+
* 10 peticiones/s por cuenta con ráfaga de 50 (`apps/web/lib/api/limites.ts`): un 429 se reintenta con `Retry-After`.
|
|
399
|
+
*/
|
|
400
|
+
concurrenciaFicheros?: number;
|
|
401
|
+
/** Uso interno: la sugerencia del servidor, memorizada por cliente (`concurrenciaDelServidor`). */
|
|
402
|
+
concurrenciaSugerida?: () => Promise<number>;
|
|
403
|
+
}
|
|
404
|
+
/** `crearAlta(d, e)` = `crearAltaConContexto(d, e)`. Lanza SIEMPRE `ErrorAlta` (nada más). */
|
|
405
|
+
declare function crearAlta(deps: DepsAlta, e: EntradaAlta): Promise<ResultadoAlta>;
|
|
406
|
+
interface Clientes {
|
|
407
|
+
/**
|
|
408
|
+
* Alta de un cliente con sus viviendas y ficheros por el circuito del panel. Idempotente por `ref`.
|
|
409
|
+
* `previo` es de uso interno de `crearVarios` y del CLI: arrastra `creado: 'desconocido'` entre intentos de una misma `ref`.
|
|
410
|
+
*/
|
|
411
|
+
crear(e: EntradaAlta, previo?: {
|
|
412
|
+
creado: Creado;
|
|
413
|
+
}): Promise<ResultadoAlta>;
|
|
414
|
+
/** Varias altas seguidas: nunca lanza, repite lo transitorio y corta lo que afecta a todos (ver `InformeVarios`). */
|
|
415
|
+
crearVarios(entradas: EntradaAlta[], o?: OpcionesVarios): Promise<InformeVarios>;
|
|
416
|
+
}
|
|
417
|
+
declare function crearClientes(deps: DepsAlta): Clientes;
|
|
418
|
+
|
|
419
|
+
interface ErrorCliente {
|
|
420
|
+
cliente_id: string;
|
|
421
|
+
code: string;
|
|
422
|
+
}
|
|
423
|
+
interface ResultadoMantenimiento {
|
|
424
|
+
entregadas: number;
|
|
425
|
+
imposibles: number;
|
|
426
|
+
/** Un error de un cliente (lote inválido, fallo del servidor…) no tumba la pasada: se recoge aquí y se sigue con los demás. */
|
|
427
|
+
errores: ErrorCliente[];
|
|
428
|
+
/** Sobres que la privada de la agencia no abre o que no validan: se quedan pendientes (ver el residual de F1 arriba). */
|
|
429
|
+
sobresSinAbrir: number;
|
|
430
|
+
/** `false` si en algún momento faltó una cabecera `Date` válida del servidor: en ese caso no se declaró nada. */
|
|
431
|
+
relojServidor: boolean;
|
|
432
|
+
}
|
|
433
|
+
interface Mantenimiento {
|
|
434
|
+
ejecutar(): Promise<ResultadoMantenimiento>;
|
|
435
|
+
}
|
|
436
|
+
interface DepsMantenimiento {
|
|
437
|
+
http: Http;
|
|
438
|
+
descifrador: Descifrador;
|
|
439
|
+
}
|
|
440
|
+
declare function crearMantenimiento(deps: DepsMantenimiento): Mantenimiento;
|
|
441
|
+
|
|
442
|
+
type SobreApi = {
|
|
443
|
+
wrapped_key_b64: string;
|
|
444
|
+
cipher_b64: string;
|
|
445
|
+
iv_b64: string;
|
|
446
|
+
};
|
|
447
|
+
type BuzonApi = {
|
|
448
|
+
buzon_id: string;
|
|
449
|
+
direccion: string;
|
|
450
|
+
activo: boolean;
|
|
451
|
+
};
|
|
452
|
+
type ViviendaApi = {
|
|
453
|
+
vivienda_id: string;
|
|
454
|
+
ref: string | null;
|
|
455
|
+
provincia: string;
|
|
456
|
+
municipio: string | null;
|
|
457
|
+
copia_direccion: SobreApi | null;
|
|
458
|
+
version: string;
|
|
459
|
+
buzones?: BuzonApi[] | undefined;
|
|
460
|
+
};
|
|
461
|
+
type ClienteApi = {
|
|
462
|
+
client_id: string;
|
|
463
|
+
ref: string | null;
|
|
464
|
+
estado: 'invitado' | 'activo' | 'eliminando';
|
|
465
|
+
email: string | null;
|
|
466
|
+
clave_publica_recepcion: string | null;
|
|
467
|
+
desde_borrador: boolean;
|
|
468
|
+
copia_nombre: SobreApi | null;
|
|
469
|
+
renovacion: {
|
|
470
|
+
efectiva: 'automatica' | 'manual';
|
|
471
|
+
propia: 'automatica' | 'manual' | null;
|
|
472
|
+
};
|
|
473
|
+
creado_at: string;
|
|
474
|
+
version: string;
|
|
475
|
+
viviendas?: ViviendaApi[] | undefined;
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
type ModoRenovacion = 'automatica' | 'manual';
|
|
479
|
+
type Incluir = 'viviendas' | 'viviendas.buzones';
|
|
480
|
+
interface OpcionesListar {
|
|
481
|
+
estado?: 'invitado' | 'activo' | 'eliminando';
|
|
482
|
+
cambiado_desde?: string;
|
|
483
|
+
incluir?: Incluir;
|
|
484
|
+
/** Tamaño de página (1-500; por defecto el del servidor). */
|
|
485
|
+
limite?: number;
|
|
486
|
+
}
|
|
487
|
+
interface PaginaClientes {
|
|
488
|
+
clientes: ClienteApi[];
|
|
489
|
+
lapidas: Array<{
|
|
490
|
+
client_id: string;
|
|
491
|
+
ref: string | null;
|
|
492
|
+
}>;
|
|
493
|
+
siguiente: string | null;
|
|
494
|
+
cambios_hasta?: string;
|
|
495
|
+
}
|
|
496
|
+
interface ViviendaEdicion {
|
|
497
|
+
/** `vivienda_id` (property_id). */
|
|
498
|
+
vivienda: string;
|
|
499
|
+
ref?: string | null;
|
|
500
|
+
renovacion?: ModoRenovacion | null;
|
|
501
|
+
/** Corregir la dirección (solo cliente `invitado`): exige `cp` y la provincia sale del CP. */
|
|
502
|
+
direccion?: string;
|
|
503
|
+
cp?: string;
|
|
504
|
+
/** Código INE (5 dígitos); `null` lo limpia. OBLIGATORIO si se manda `direccion`/`cp` (el SDK no deduce el municipio del CP). */
|
|
505
|
+
municipio?: string | null;
|
|
506
|
+
}
|
|
507
|
+
interface EdicionCliente {
|
|
508
|
+
ref?: string | null;
|
|
509
|
+
renovacion?: ModoRenovacion | null;
|
|
510
|
+
/** Nombre del cliente (etiqueta de la agencia). `''` o `null` lo borra. Ausente: no se toca. */
|
|
511
|
+
nombre?: string | null;
|
|
512
|
+
viviendas?: ViviendaEdicion[];
|
|
513
|
+
}
|
|
514
|
+
interface OpcionesEscritura {
|
|
515
|
+
/** Versión esperada del cliente (`version` de `clientes.leer`, o el ETag `"v12"`). `'*'` vale con cualquiera. Obligatoria. */
|
|
516
|
+
ifMatch: string;
|
|
517
|
+
}
|
|
518
|
+
interface Escrito {
|
|
519
|
+
ok: true;
|
|
520
|
+
version: string | number | null;
|
|
521
|
+
}
|
|
522
|
+
interface ClientesGestion {
|
|
523
|
+
/** Itera TODOS los clientes: pide páginas hasta que llega una vacía o no hay `siguiente`. */
|
|
524
|
+
listar(o?: OpcionesListar): AsyncIterableIterator<ClienteApi>;
|
|
525
|
+
listarPagina(o?: OpcionesListar & {
|
|
526
|
+
cursor?: string;
|
|
527
|
+
}): Promise<PaginaClientes>;
|
|
528
|
+
leer(clienteId: string, o?: {
|
|
529
|
+
incluir?: Incluir;
|
|
530
|
+
}): Promise<ClienteApi>;
|
|
531
|
+
editar(clienteId: string, cambios: EdicionCliente, o: OpcionesEscritura): Promise<Escrito>;
|
|
532
|
+
desvincular(clienteId: string, o: OpcionesEscritura): Promise<Escrito>;
|
|
533
|
+
/** Corrige el correo de un cliente `invitado` sin confirmar y le manda un enlace nuevo. */
|
|
534
|
+
correo(clienteId: string, correo: string): Promise<Escrito>;
|
|
535
|
+
revocarEnlace(clienteId: string): Promise<Escrito>;
|
|
536
|
+
}
|
|
537
|
+
interface Viviendas {
|
|
538
|
+
listar(clienteId: string): Promise<ViviendaApi[]>;
|
|
539
|
+
}
|
|
540
|
+
interface Remitentes {
|
|
541
|
+
listar(): Promise<string[]>;
|
|
542
|
+
anadir(correo: string): Promise<{
|
|
543
|
+
remitentes: string[];
|
|
544
|
+
clientesActualizados: number;
|
|
545
|
+
}>;
|
|
546
|
+
quitar(correo: string): Promise<string[]>;
|
|
547
|
+
}
|
|
548
|
+
interface Creditos {
|
|
549
|
+
leer(): Promise<{
|
|
550
|
+
saldo: number;
|
|
551
|
+
}>;
|
|
552
|
+
}
|
|
553
|
+
interface ReglaRenovacion {
|
|
554
|
+
agencia: ModoRenovacion;
|
|
555
|
+
clientes: Array<{
|
|
556
|
+
cliente_id: string;
|
|
557
|
+
renovacion: ModoRenovacion;
|
|
558
|
+
}>;
|
|
559
|
+
viviendas: Array<{
|
|
560
|
+
vivienda_id: string;
|
|
561
|
+
cliente_id: string;
|
|
562
|
+
renovacion: ModoRenovacion;
|
|
563
|
+
}>;
|
|
564
|
+
}
|
|
565
|
+
type FijarRenovacion = {
|
|
566
|
+
nivel: 'agencia';
|
|
567
|
+
renovacion: ModoRenovacion;
|
|
568
|
+
} | {
|
|
569
|
+
nivel: 'cliente';
|
|
570
|
+
cliente_id: string;
|
|
571
|
+
renovacion: ModoRenovacion | null;
|
|
572
|
+
} | {
|
|
573
|
+
nivel: 'vivienda';
|
|
574
|
+
cliente_id: string;
|
|
575
|
+
vivienda_id: string;
|
|
576
|
+
renovacion: ModoRenovacion | null;
|
|
577
|
+
};
|
|
578
|
+
interface RenovacionApi {
|
|
579
|
+
leer(): Promise<ReglaRenovacion>;
|
|
580
|
+
fijar(f: FijarRenovacion): Promise<unknown>;
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Tipos públicos de webhook (v10 § 4.8). Viven como DATOS en `api_webhook_tipo` (migración, columna A); el SDK es
|
|
584
|
+
* público y no importa del servidor, así que los repite aquí y `tests/api/webhook-tipos-sdk.test.ts` los compara con la
|
|
585
|
+
* migración para que no se desfasen.
|
|
586
|
+
*/
|
|
587
|
+
declare const TIPOS_WEBHOOK: readonly ["cliente.activado", "cliente.ido", "lote.terminado", "credencial.caduca_pronto", "mantenimiento.pendiente"];
|
|
588
|
+
type TipoWebhook = (typeof TIPOS_WEBHOOK)[number];
|
|
589
|
+
interface DestinoWebhook {
|
|
590
|
+
webhook_id: string;
|
|
591
|
+
url: string;
|
|
592
|
+
tipos: TipoWebhook[];
|
|
593
|
+
activo: boolean;
|
|
594
|
+
desactivado_motivo: string | null;
|
|
595
|
+
creado_at: string;
|
|
596
|
+
}
|
|
597
|
+
interface EntregaWebhook {
|
|
598
|
+
entrega_id: string;
|
|
599
|
+
evento_id: number;
|
|
600
|
+
tipo: string;
|
|
601
|
+
estado: string;
|
|
602
|
+
intento: number;
|
|
603
|
+
ultimo_codigo: number | null;
|
|
604
|
+
ultimo_motivo: string | null;
|
|
605
|
+
proxima_at: string;
|
|
606
|
+
}
|
|
607
|
+
interface Webhooks {
|
|
608
|
+
listar(): Promise<DestinoWebhook[]>;
|
|
609
|
+
/** El secreto `whsec_…` solo viene en la primera respuesta; un replay de la misma llamada no lo lleva. */
|
|
610
|
+
crear(e: {
|
|
611
|
+
url: string;
|
|
612
|
+
tipos: TipoWebhook[];
|
|
613
|
+
}): Promise<{
|
|
614
|
+
webhook_id: string;
|
|
615
|
+
url: string;
|
|
616
|
+
tipos: TipoWebhook[];
|
|
617
|
+
secreto?: string;
|
|
618
|
+
detail?: string;
|
|
619
|
+
}>;
|
|
620
|
+
borrar(webhookId: string): Promise<{
|
|
621
|
+
webhook_id: string;
|
|
622
|
+
}>;
|
|
623
|
+
rotarSecreto(webhookId: string): Promise<{
|
|
624
|
+
webhook_id: string;
|
|
625
|
+
secreto?: string;
|
|
626
|
+
previo_hasta: string;
|
|
627
|
+
detail?: string;
|
|
628
|
+
}>;
|
|
629
|
+
entregas(webhookId: string, o?: {
|
|
630
|
+
estado?: string;
|
|
631
|
+
cursor?: string;
|
|
632
|
+
limite?: number;
|
|
633
|
+
}): Promise<{
|
|
634
|
+
entregas: EntregaWebhook[];
|
|
635
|
+
siguiente: string | null;
|
|
636
|
+
}>;
|
|
637
|
+
reenviar(webhookId: string, entregaId: string): Promise<{
|
|
638
|
+
entrega_id: string;
|
|
639
|
+
estado: 'pendiente';
|
|
640
|
+
}>;
|
|
641
|
+
}
|
|
642
|
+
interface Gestion {
|
|
643
|
+
clientes: ClientesGestion;
|
|
644
|
+
viviendas: Viviendas;
|
|
645
|
+
remitentes: Remitentes;
|
|
646
|
+
creditos: Creditos;
|
|
647
|
+
renovacion: RenovacionApi;
|
|
648
|
+
webhooks: Webhooks;
|
|
649
|
+
}
|
|
650
|
+
interface DepsGestion {
|
|
651
|
+
http: Http;
|
|
652
|
+
descifrador: Descifrador;
|
|
653
|
+
}
|
|
654
|
+
/** `"v12"` a partir de `12`, `"12"` o `"\"v12\""`; `*` y las etiquetas ya formadas pasan tal cual. */
|
|
655
|
+
declare function etiquetaIfMatch(v: string | number): string;
|
|
656
|
+
declare function crearGestion(deps: DepsGestion): Gestion;
|
|
657
|
+
|
|
658
|
+
declare const FOTO_LADO_MAX = 1600;
|
|
659
|
+
declare const FOTO_CALIDAD = 0.82;
|
|
660
|
+
declare const FOTO_CALIDAD_2 = 0.7;
|
|
661
|
+
declare const FOTO_BYTES_OBJETIVO: number;
|
|
662
|
+
type ResultadoFotoSdk = {
|
|
663
|
+
ok: true;
|
|
664
|
+
bytes: Uint8Array;
|
|
665
|
+
mime: 'image/jpeg';
|
|
666
|
+
} | {
|
|
667
|
+
ok: false;
|
|
668
|
+
error: 'IMAGEN_NO_PROCESABLE';
|
|
669
|
+
};
|
|
670
|
+
/** Lo mínimo de `sharp` que usamos (se tipa a mano: la dependencia es opcional y puede no estar instalada). */
|
|
671
|
+
interface SharpInstancia {
|
|
672
|
+
rotate(): SharpInstancia;
|
|
673
|
+
resize(o: Record<string, unknown>): SharpInstancia;
|
|
674
|
+
clone(): SharpInstancia;
|
|
675
|
+
jpeg(o: {
|
|
676
|
+
quality: number;
|
|
677
|
+
}): SharpInstancia;
|
|
678
|
+
toBuffer(): Promise<Uint8Array>;
|
|
679
|
+
}
|
|
680
|
+
type SharpFn = (entrada: Uint8Array, opciones?: Record<string, unknown>) => SharpInstancia;
|
|
681
|
+
interface DepsFoto {
|
|
682
|
+
/** Solo para los tests: sustituye a la carga de `sharp` (`null` = no instalado). */
|
|
683
|
+
cargarSharp?: () => Promise<SharpFn | null>;
|
|
684
|
+
}
|
|
685
|
+
declare function prepararFoto(bytes: Uint8Array, mime: string, deps?: DepsFoto): Promise<ResultadoFotoSdk>;
|
|
686
|
+
|
|
687
|
+
declare const TOLERANCIA_WEBHOOK_S = 300;
|
|
688
|
+
type MotivoFirmaWebhook = 'CABECERAS' | 'TIMESTAMP' | 'FUERA_DE_VENTANA' | 'SECRETO' | 'FIRMA';
|
|
689
|
+
declare class ErrorFirmaWebhook extends Error {
|
|
690
|
+
readonly motivo: MotivoFirmaWebhook;
|
|
691
|
+
constructor(motivo: MotivoFirmaWebhook);
|
|
692
|
+
}
|
|
693
|
+
type CabecerasWebhook = Headers | Record<string, string | string[] | undefined>;
|
|
694
|
+
interface OpcionesVerificar {
|
|
695
|
+
/** «Ahora» en milisegundos Unix; por defecto `Date.now()`. Solo para tests. */
|
|
696
|
+
ahora?: () => number;
|
|
697
|
+
/** Ventana en segundos a cada lado (por defecto 300). */
|
|
698
|
+
toleranciaS?: number;
|
|
699
|
+
}
|
|
700
|
+
interface WebhookVerificado {
|
|
701
|
+
id: string;
|
|
702
|
+
/** Segundos Unix del intento. */
|
|
703
|
+
timestamp: number;
|
|
704
|
+
}
|
|
705
|
+
/** Verifica o lanza `ErrorFirmaWebhook`. `cuerpo` es el cuerpo CRUDO recibido, sin re-serializar. */
|
|
706
|
+
declare function verificarWebhook(cuerpo: string | Uint8Array, cabeceras: CabecerasWebhook, secreto: string | readonly string[], opciones?: OpcionesVerificar): WebhookVerificado;
|
|
707
|
+
|
|
708
|
+
interface ClienteCda {
|
|
709
|
+
/** Llamada de bajo nivel; las tareas siguientes cuelgan de aquí `clientes`, `borradores`, `mantenimiento`. */
|
|
710
|
+
peticion<T = unknown>(p: Peticion): Promise<T>;
|
|
711
|
+
http: Http;
|
|
712
|
+
descifrador: Descifrador;
|
|
713
|
+
borradores: Borradores;
|
|
714
|
+
clientes: Clientes & ClientesGestion;
|
|
715
|
+
viviendas: Gestion['viviendas'];
|
|
716
|
+
remitentes: Gestion['remitentes'];
|
|
717
|
+
creditos: Gestion['creditos'];
|
|
718
|
+
renovacion: Gestion['renovacion'];
|
|
719
|
+
webhooks: Gestion['webhooks'];
|
|
720
|
+
mantenimiento: Mantenimiento;
|
|
721
|
+
}
|
|
722
|
+
interface OpcionesCliente {
|
|
723
|
+
apiKey: string;
|
|
724
|
+
baseUrl?: string;
|
|
725
|
+
descifrador: Descifrador;
|
|
726
|
+
fetch?: typeof fetch;
|
|
727
|
+
/** Solo para los tests: sustituye a pdf.js al leer actas, contratos y movimientos. */
|
|
728
|
+
extraer?: OpcionesLector['extraer'];
|
|
729
|
+
hoy?: () => string;
|
|
730
|
+
intervaloMs?: number;
|
|
731
|
+
maxEsperaMs?: number;
|
|
732
|
+
dormir?: (ms: number) => Promise<void>;
|
|
733
|
+
/** Ficheros de una vivienda procesados a la vez (1 a 8). Si no se fija, el SDK usa la que sugiere `GET /v1/yo` o, si falta, 4. La API admite 10 peticiones/s por cuenta, ráfaga de 50. */
|
|
734
|
+
concurrenciaFicheros?: number;
|
|
735
|
+
}
|
|
736
|
+
declare function crearCliente(o: OpcionesCliente): ClienteCda;
|
|
737
|
+
|
|
738
|
+
export { ErrorAlta, ErrorApiSdk, ErrorClaveIntegracion, ErrorDeEntorno, ErrorFirmaWebhook, FOTO_BYTES_OBJETIVO, FOTO_CALIDAD, FOTO_CALIDAD_2, FOTO_LADO_MAX, TIPOS_WEBHOOK, TOLERANCIA_WEBHOOK_S, TOPE_BYTES, URL_BASE_SANDBOX, abrirContenidoFichero, abrirJson, abrirNombreFichero, abrirSobreBytes, admiteIdempotencia, base64ToBytes, bytesToBase64, clasificar, codigoDe, crearAlta, crearBorradores, crearCliente, crearClientes, crearGestion, crearHttp, crearMantenimiento, crearVarios, descifradorDeClave, descifradorDeFichero, envolver, esperaDeRetryAfter, etiquetaIfMatch, importarPrivadaPkcs8, leerFicheroLocal, prepararFoto, reenvolverClave, sellarFichero, sellarJson, sellarSobreB64, sha256Hex, sobreDeB64, verificarWebhook };
|
|
739
|
+
export type { Borradores, BuzonApi, CabecerasWebhook, ClienteApi, ClienteCda, Clientes, ClientesGestion, Consejo, ContextoAlta, Creado, Creditos, DepsAlta, DepsGestion, DepsMantenimiento, Descifrador, DestinoWebhook, EdicionCliente, EntradaAlta, EntregaWebhook, ErrorCliente, Escrito, FallidoAlta, FicheroAlta, FicheroSellado, FijarRenovacion, Gestion, Http, Incluir, InformeVarios, LectorVigente, Mantenimiento, ModoRenovacion, MotivoFirmaWebhook, OpcionesCliente, OpcionesEscritura, OpcionesHttp, OpcionesLector, OpcionesListar, OpcionesVarios, OpcionesVerificar, OrigenClaveIntegracion, PaginaClientes, PasoAlta, Peticion, ReglaRenovacion, Remitentes, RenovacionApi, ResultadoAlta, ResultadoFotoSdk, ResultadoMantenimiento, SalidaLectorLocal, Sobre, SobreApi, SobreB64Cliente, TipoWebhook, ViviendaAlta, ViviendaApi, ViviendaEdicion, Viviendas, WebhookVerificado, Webhooks };
|