@pimia/sdk 0.20.0 → 0.27.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/README.md +80 -0
- package/dist/api.d.ts +1020 -116
- package/dist/central-api.d.ts +1928 -0
- package/dist/central-api.js +9 -0
- package/dist/central.d.ts +607 -0
- package/dist/central.js +257 -0
- package/dist/client.d.ts +261 -1
- package/dist/client.js +212 -2
- package/dist/errors.d.ts +11 -0
- package/dist/errors.js +24 -0
- package/dist/index.d.ts +23 -3
- package/dist/index.js +21 -2
- package/dist/tokens.d.ts +45 -0
- package/dist/tokens.js +53 -0
- package/package.json +5 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file was auto-generated by openapi-typescript.
|
|
3
|
+
* Do not make direct changes to the file.
|
|
4
|
+
*
|
|
5
|
+
* Generado con `npm run generate:types` (scripts/generate-types.mjs), que
|
|
6
|
+
* añade UN transform al generador: `format: binary` sale como `Blob` y no
|
|
7
|
+
* como `string`. El porqué, en ese fichero.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,607 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cliente del PLANO CENTRAL de Pimia para el integrador (cuenta de
|
|
3
|
+
* desarrollador): su cartera de clientes, los vínculos con cada instancia, sus
|
|
4
|
+
* clients OAuth, las invitaciones, el patrocinio y el traspaso de propiedad.
|
|
5
|
+
*
|
|
6
|
+
* No es el cliente de un tenant ({@link PimiaClient}, que habla con
|
|
7
|
+
* `https://{tenant}.pimia.es/api/v1` con un token OAuth por instancia): este
|
|
8
|
+
* habla con el ÁPICE (`https://pimia.es/api`) con el **token personal de
|
|
9
|
+
* Sanctum** de la cuenta de desarrollador, acotado por plano
|
|
10
|
+
* (galeote/factSaas#731): `desarrollador` abre `/desarrollador/*` y `central`
|
|
11
|
+
* abre invitaciones, patrocinio y traspaso. Cada operación del contrato dice
|
|
12
|
+
* cuál exige (`x-pimia-required-ability`); un token sin ella recibe un
|
|
13
|
+
* {@link MissingAbilityError} con la habilidad que falta.
|
|
14
|
+
*
|
|
15
|
+
* Lo que NO hace, a propósito: refrescar nada (el token personal no caduca ni
|
|
16
|
+
* rota; se revoca desde el panel) ni leer contenido fiscal de ningún cliente —
|
|
17
|
+
* a los datos de una instancia se llega por OAuth consentido, con el otro
|
|
18
|
+
* cliente.
|
|
19
|
+
*
|
|
20
|
+
* Los tipos salen de `spec/pimia-central-v1.json` (`./central-api`).
|
|
21
|
+
*/
|
|
22
|
+
import type { operations } from './central-api.js';
|
|
23
|
+
/** El cuerpo JSON que pide una operación del contrato. */
|
|
24
|
+
type Body<O extends keyof operations> = operations[O] extends {
|
|
25
|
+
requestBody: {
|
|
26
|
+
content: {
|
|
27
|
+
'application/json': infer B;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
} ? B : operations[O] extends {
|
|
31
|
+
requestBody?: {
|
|
32
|
+
content: {
|
|
33
|
+
'application/json': infer B;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
} ? B : never;
|
|
37
|
+
/**
|
|
38
|
+
* Cuerpo de `POST /billing/sponsorship`: la instancia y el plan de canal con
|
|
39
|
+
* que se paga; `return_url` (1.4.0) es a dónde vuelve el integrador desde el
|
|
40
|
+
* Checkout del canal —solo se acepta el origen del panel central o el del
|
|
41
|
+
* ápice; lo demás vuelve al panel Vue—.
|
|
42
|
+
*/
|
|
43
|
+
export type SponsorshipRequest = Body<'billing.sponsor'>;
|
|
44
|
+
/** Cuerpo de `POST /billing/portal` (1.4.0): `return_url`, con la misma regla que el patrocinio. */
|
|
45
|
+
export type BillingPortalRequest = Body<'billing.portal'>;
|
|
46
|
+
/** Cuerpo de `POST /tenant-invitations`: a quién se invita y quién paga (`billing`). */
|
|
47
|
+
export type TenantInvitationRequest = Body<'tenantInvitation.store'>;
|
|
48
|
+
/** Cuerpo de `POST /tenants/{slug}/transfer-ownership`: el usuario de la instancia que pasa a ser dueño. */
|
|
49
|
+
export type TransferOwnershipRequest = Body<'tenant.transferOwnership'>;
|
|
50
|
+
/**
|
|
51
|
+
* Cuerpo de `PUT /desarrollador/catalogo`: el catálogo del integrador ENTERO —
|
|
52
|
+
* cabecera (nombre comercial, soporte, moneda ISO 4217, enlace de contratación)
|
|
53
|
+
* y filas (`kind` ∈ `base|module|app`, `slug`, `price_cents` en subunidades de
|
|
54
|
+
* esa moneda, `contract_url` propio opcional, `enabled`)—. Lo que no venga deja
|
|
55
|
+
* de existir.
|
|
56
|
+
*/
|
|
57
|
+
export type CatalogoDelIntegradorRequest = Body<'integradorCatalogo.update'>;
|
|
58
|
+
/**
|
|
59
|
+
* Cuerpo de `POST /desarrollador/tenants/{slug}/activaciones`: qué se activa al
|
|
60
|
+
* cliente (`kind` ∈ `base|module|app`, `slug`; `plan_id` solo si hay varios
|
|
61
|
+
* planes de canal).
|
|
62
|
+
*/
|
|
63
|
+
export type ActivacionMayoristaRequest = Body<'integradorActivacion.store'>;
|
|
64
|
+
export type IntegradorDominioRequest = Body<'integradorDominio.store'>;
|
|
65
|
+
export type IntegradorTokenRequest = Body<'integradorToken.store'>;
|
|
66
|
+
export interface PimiaCentralClientOptions {
|
|
67
|
+
/** El ápice, sin `/api`: `https://pimia.es` (o `https://taskai.work` en dev). */
|
|
68
|
+
baseUrl: string;
|
|
69
|
+
/**
|
|
70
|
+
* El token personal de la cuenta de desarrollador, o una función que lo
|
|
71
|
+
* devuelva (para leerlo de un secreto en cada llamada). Se manda como
|
|
72
|
+
* `Authorization: Bearer`.
|
|
73
|
+
*/
|
|
74
|
+
token: string | (() => string | Promise<string>);
|
|
75
|
+
/** `fetch` a usar (por defecto, el global). Útil para tests y proxies. */
|
|
76
|
+
fetch?: typeof globalThis.fetch;
|
|
77
|
+
/** Cabeceras fijas para todas las llamadas. */
|
|
78
|
+
headers?: Record<string, string>;
|
|
79
|
+
}
|
|
80
|
+
export interface CentralRequestOptions {
|
|
81
|
+
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
82
|
+
query?: Record<string, string | number | boolean | undefined | null | Array<string | number>>;
|
|
83
|
+
body?: unknown;
|
|
84
|
+
headers?: Record<string, string>;
|
|
85
|
+
signal?: AbortSignal;
|
|
86
|
+
}
|
|
87
|
+
export interface CentralResponseMeta {
|
|
88
|
+
status: number;
|
|
89
|
+
requestId?: string;
|
|
90
|
+
}
|
|
91
|
+
export interface CentralResponseWithMeta<T> {
|
|
92
|
+
data: T;
|
|
93
|
+
meta: CentralResponseMeta;
|
|
94
|
+
}
|
|
95
|
+
export declare class PimiaCentralClient {
|
|
96
|
+
private readonly baseUrl;
|
|
97
|
+
private readonly token;
|
|
98
|
+
private readonly doFetch;
|
|
99
|
+
private readonly extraHeaders;
|
|
100
|
+
constructor(options: PimiaCentralClientOptions);
|
|
101
|
+
/** `GET /desarrollador/overview`: la cartera, con la atribución de cada alta. */
|
|
102
|
+
overview(): Promise<{
|
|
103
|
+
data: {
|
|
104
|
+
cartera: {
|
|
105
|
+
id: string;
|
|
106
|
+
name: string;
|
|
107
|
+
status: string;
|
|
108
|
+
plan: string | null;
|
|
109
|
+
created_at: string | null;
|
|
110
|
+
trial_ends_at: string | null;
|
|
111
|
+
relacion: string;
|
|
112
|
+
billing_mode: string | null;
|
|
113
|
+
la_pago_yo: boolean;
|
|
114
|
+
marca_blanca: boolean;
|
|
115
|
+
origen: {
|
|
116
|
+
client_id: string;
|
|
117
|
+
name: string;
|
|
118
|
+
atribuido: boolean;
|
|
119
|
+
} | null;
|
|
120
|
+
}[];
|
|
121
|
+
resumen: {
|
|
122
|
+
total: number;
|
|
123
|
+
activos: number;
|
|
124
|
+
suspendidos: number;
|
|
125
|
+
};
|
|
126
|
+
cuota: {
|
|
127
|
+
usada: number;
|
|
128
|
+
limite: number;
|
|
129
|
+
ilimitada: boolean;
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
}>;
|
|
133
|
+
/** `GET /desarrollador/salud`: clients, webhooks y propuestas, solo los propios. */
|
|
134
|
+
salud(): Promise<{
|
|
135
|
+
data: {
|
|
136
|
+
clients: {
|
|
137
|
+
client_id: string;
|
|
138
|
+
name: string;
|
|
139
|
+
revoked_at: string | null;
|
|
140
|
+
tokens_vivos: number;
|
|
141
|
+
ultimo_uso: string | null;
|
|
142
|
+
}[];
|
|
143
|
+
webhooks: {
|
|
144
|
+
id: number;
|
|
145
|
+
tenant_id: string | null;
|
|
146
|
+
url: string;
|
|
147
|
+
events: string[];
|
|
148
|
+
disabled_at: string | null;
|
|
149
|
+
consecutive_failures: number;
|
|
150
|
+
entregas_7d: {
|
|
151
|
+
delivered: number;
|
|
152
|
+
pending: number;
|
|
153
|
+
dead: number;
|
|
154
|
+
};
|
|
155
|
+
}[];
|
|
156
|
+
approvals: {
|
|
157
|
+
abiertas: number;
|
|
158
|
+
por_tenant: {
|
|
159
|
+
tenant_id: string;
|
|
160
|
+
abiertas: number;
|
|
161
|
+
}[];
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
}>;
|
|
165
|
+
/** `GET /desarrollador/facturacion`: lo que el integrador paga a Pimia (canal y asientos). */
|
|
166
|
+
facturacion(): Promise<{
|
|
167
|
+
data: {
|
|
168
|
+
canal: {
|
|
169
|
+
estado: string;
|
|
170
|
+
asientos: number;
|
|
171
|
+
quantity: number;
|
|
172
|
+
descuadre: boolean;
|
|
173
|
+
termina_en: string | null;
|
|
174
|
+
} | null;
|
|
175
|
+
asientos: {
|
|
176
|
+
tenant_id: string;
|
|
177
|
+
rol: string;
|
|
178
|
+
en_mora: boolean;
|
|
179
|
+
gracia_hasta: string | null;
|
|
180
|
+
suspendido_desde: string | null;
|
|
181
|
+
}[];
|
|
182
|
+
en_mora: number;
|
|
183
|
+
anadidos: {
|
|
184
|
+
activaciones: number;
|
|
185
|
+
total_cents: number;
|
|
186
|
+
total: string;
|
|
187
|
+
por_tenant: {
|
|
188
|
+
tenant_id: string;
|
|
189
|
+
activaciones: number;
|
|
190
|
+
total_cents: number;
|
|
191
|
+
}[];
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
}>;
|
|
195
|
+
get links(): {
|
|
196
|
+
list: () => Promise<{
|
|
197
|
+
data: {
|
|
198
|
+
id: number;
|
|
199
|
+
link_code: string;
|
|
200
|
+
status: string;
|
|
201
|
+
tenant: {
|
|
202
|
+
id: string;
|
|
203
|
+
name: string;
|
|
204
|
+
status: string;
|
|
205
|
+
} | null;
|
|
206
|
+
requester: {
|
|
207
|
+
id: number;
|
|
208
|
+
name: string;
|
|
209
|
+
email: string;
|
|
210
|
+
} | null;
|
|
211
|
+
requested_at: string | null;
|
|
212
|
+
accepted_at: string | null;
|
|
213
|
+
revoked_at: string | null;
|
|
214
|
+
created_at: string | null;
|
|
215
|
+
}[];
|
|
216
|
+
}>;
|
|
217
|
+
/** Un código `DEV-XXXX-XXXX` que el cliente teclea en su instancia. */
|
|
218
|
+
generateCode: () => Promise<{
|
|
219
|
+
message: "C\u00F3digo de vinculaci\u00F3n generado.";
|
|
220
|
+
data: {
|
|
221
|
+
id: number;
|
|
222
|
+
link_code: string;
|
|
223
|
+
status: string;
|
|
224
|
+
tenant: {
|
|
225
|
+
id: string;
|
|
226
|
+
name: string;
|
|
227
|
+
status: string;
|
|
228
|
+
} | null;
|
|
229
|
+
requester: {
|
|
230
|
+
id: number;
|
|
231
|
+
name: string;
|
|
232
|
+
email: string;
|
|
233
|
+
} | null;
|
|
234
|
+
requested_at: string | null;
|
|
235
|
+
accepted_at: string | null;
|
|
236
|
+
revoked_at: string | null;
|
|
237
|
+
created_at: string | null;
|
|
238
|
+
};
|
|
239
|
+
}>;
|
|
240
|
+
accept: (id: number | string) => Promise<{
|
|
241
|
+
message: "Vinculaci\u00F3n aceptada.";
|
|
242
|
+
data: {
|
|
243
|
+
id: number;
|
|
244
|
+
link_code: string;
|
|
245
|
+
status: string;
|
|
246
|
+
tenant: {
|
|
247
|
+
id: string;
|
|
248
|
+
name: string;
|
|
249
|
+
status: string;
|
|
250
|
+
} | null;
|
|
251
|
+
requester: {
|
|
252
|
+
id: number;
|
|
253
|
+
name: string;
|
|
254
|
+
email: string;
|
|
255
|
+
} | null;
|
|
256
|
+
requested_at: string | null;
|
|
257
|
+
accepted_at: string | null;
|
|
258
|
+
revoked_at: string | null;
|
|
259
|
+
created_at: string | null;
|
|
260
|
+
};
|
|
261
|
+
}>;
|
|
262
|
+
reject: (id: number | string) => Promise<{
|
|
263
|
+
message: "Solicitud rechazada.";
|
|
264
|
+
}>;
|
|
265
|
+
};
|
|
266
|
+
get clients(): {
|
|
267
|
+
list: () => Promise<{
|
|
268
|
+
data: {
|
|
269
|
+
client_id: string;
|
|
270
|
+
name: string;
|
|
271
|
+
confidential: boolean;
|
|
272
|
+
scope: string;
|
|
273
|
+
registration_tenant_id: string;
|
|
274
|
+
revoked_at: string;
|
|
275
|
+
created_at: string;
|
|
276
|
+
}[];
|
|
277
|
+
}>;
|
|
278
|
+
/**
|
|
279
|
+
* Reclamar un client confidencial CON su secreto: la única prueba de
|
|
280
|
+
* propiedad que el núcleo acepta (RFC 7591). El secreto no se guarda.
|
|
281
|
+
*/
|
|
282
|
+
claim: (body: Body<"desarrolladorLink.claimClient">) => Promise<{
|
|
283
|
+
message: string;
|
|
284
|
+
}>;
|
|
285
|
+
};
|
|
286
|
+
get catalogo(): {
|
|
287
|
+
/**
|
|
288
|
+
* `GET /desarrollador/catalogo`: el catálogo propio (`perfil`, `currency`,
|
|
289
|
+
* `items`) y lo que se puede revender (`disponibles`: Pimia base, los
|
|
290
|
+
* módulos opcionales ofrecidos y las apps integradas activas).
|
|
291
|
+
*/
|
|
292
|
+
get: () => Promise<{
|
|
293
|
+
data: {
|
|
294
|
+
perfil: {
|
|
295
|
+
nombre_comercial: string;
|
|
296
|
+
soporte_url: string | null;
|
|
297
|
+
soporte_email: string | null;
|
|
298
|
+
} | null;
|
|
299
|
+
currency: string | null;
|
|
300
|
+
contract_url: string | null;
|
|
301
|
+
items: {
|
|
302
|
+
kind: string;
|
|
303
|
+
slug: string;
|
|
304
|
+
name: string;
|
|
305
|
+
description: string | null;
|
|
306
|
+
price_cents: number;
|
|
307
|
+
price: string | null;
|
|
308
|
+
contract_url: string | null;
|
|
309
|
+
enabled: boolean;
|
|
310
|
+
}[];
|
|
311
|
+
disponibles: {
|
|
312
|
+
base: {
|
|
313
|
+
slug: string;
|
|
314
|
+
name: string;
|
|
315
|
+
description: string | null;
|
|
316
|
+
wholesale_price_cents: number | null;
|
|
317
|
+
wholesale_price: string | null;
|
|
318
|
+
}[];
|
|
319
|
+
modules: {
|
|
320
|
+
slug: string;
|
|
321
|
+
name: string;
|
|
322
|
+
description: string | null;
|
|
323
|
+
wholesale_price_cents: number | null;
|
|
324
|
+
wholesale_price: string | null;
|
|
325
|
+
}[];
|
|
326
|
+
apps: {
|
|
327
|
+
slug: string;
|
|
328
|
+
name: string;
|
|
329
|
+
description: string | null;
|
|
330
|
+
wholesale_price_cents: number | null;
|
|
331
|
+
wholesale_price: string | null;
|
|
332
|
+
}[];
|
|
333
|
+
};
|
|
334
|
+
};
|
|
335
|
+
}>;
|
|
336
|
+
/**
|
|
337
|
+
* `PUT /desarrollador/catalogo`: reemplaza el catálogo ENTERO. Es lo que
|
|
338
|
+
* el cliente del integrador ve en la pantalla de plan de su instancia en
|
|
339
|
+
* vez de los precios de Pimia; el precio es minorista y no toca el
|
|
340
|
+
* dinero de Pimia.
|
|
341
|
+
*/
|
|
342
|
+
replace: (body: CatalogoDelIntegradorRequest) => Promise<{
|
|
343
|
+
data: {
|
|
344
|
+
perfil: {
|
|
345
|
+
nombre_comercial: string;
|
|
346
|
+
soporte_url: string | null;
|
|
347
|
+
soporte_email: string | null;
|
|
348
|
+
} | null;
|
|
349
|
+
currency: string | null;
|
|
350
|
+
contract_url: string | null;
|
|
351
|
+
items: {
|
|
352
|
+
kind: string;
|
|
353
|
+
slug: string;
|
|
354
|
+
name: string;
|
|
355
|
+
description: string | null;
|
|
356
|
+
price_cents: number;
|
|
357
|
+
price: string | null;
|
|
358
|
+
contract_url: string | null;
|
|
359
|
+
enabled: boolean;
|
|
360
|
+
}[];
|
|
361
|
+
disponibles: {
|
|
362
|
+
base: {
|
|
363
|
+
slug: string;
|
|
364
|
+
name: string;
|
|
365
|
+
description: string | null;
|
|
366
|
+
wholesale_price_cents: number | null;
|
|
367
|
+
wholesale_price: string | null;
|
|
368
|
+
}[];
|
|
369
|
+
modules: {
|
|
370
|
+
slug: string;
|
|
371
|
+
name: string;
|
|
372
|
+
description: string | null;
|
|
373
|
+
wholesale_price_cents: number | null;
|
|
374
|
+
wholesale_price: string | null;
|
|
375
|
+
}[];
|
|
376
|
+
apps: {
|
|
377
|
+
slug: string;
|
|
378
|
+
name: string;
|
|
379
|
+
description: string | null;
|
|
380
|
+
wholesale_price_cents: number | null;
|
|
381
|
+
wholesale_price: string | null;
|
|
382
|
+
}[];
|
|
383
|
+
};
|
|
384
|
+
};
|
|
385
|
+
}>;
|
|
386
|
+
};
|
|
387
|
+
get activaciones(): {
|
|
388
|
+
/**
|
|
389
|
+
* `GET /desarrollador/tenants/{slug}/activaciones`: la base (su asiento),
|
|
390
|
+
* los módulos y apps activos y lo que le cuestan al integrador al mes.
|
|
391
|
+
*/
|
|
392
|
+
list: (tenantSlug: string) => Promise<{
|
|
393
|
+
data: {
|
|
394
|
+
base: {
|
|
395
|
+
active: boolean;
|
|
396
|
+
price_cents: number | null;
|
|
397
|
+
price: string | null;
|
|
398
|
+
plan: string | null;
|
|
399
|
+
};
|
|
400
|
+
items: {
|
|
401
|
+
kind: string;
|
|
402
|
+
slug: string;
|
|
403
|
+
name: string;
|
|
404
|
+
active_since: string;
|
|
405
|
+
price_cents: number | null;
|
|
406
|
+
price: string | null;
|
|
407
|
+
}[];
|
|
408
|
+
total_cents: number;
|
|
409
|
+
total: string;
|
|
410
|
+
};
|
|
411
|
+
}>;
|
|
412
|
+
/**
|
|
413
|
+
* `POST /desarrollador/tenants/{slug}/activaciones`: activar la base, un
|
|
414
|
+
* módulo o una app. La base es el asiento (la primera vez devuelve
|
|
415
|
+
* `checkout_url`); un módulo o una app exigen la base viva y se cobran
|
|
416
|
+
* al integrador como partida de su canal, sin prorrateo, en la factura
|
|
417
|
+
* del mes. Idempotente (`already_active`). Es lo que llama el webhook del
|
|
418
|
+
* integrador cuando su cliente le compra algo.
|
|
419
|
+
*/
|
|
420
|
+
activate: (tenantSlug: string, body: ActivacionMayoristaRequest) => Promise<string | {
|
|
421
|
+
message: "Completa el alta de tu suscripci\u00F3n de canal para activar la licencia de este cliente." | "El cliente ya lo ten\u00EDa encendido por su cuenta: no se te cobra ni se le toca." | "Ya estaba activo." | "Activado: se cobra en tu canal desde la pr\u00F3xima factura.";
|
|
422
|
+
data: {
|
|
423
|
+
already_active: boolean;
|
|
424
|
+
inherited: boolean;
|
|
425
|
+
checkout_url: string | null;
|
|
426
|
+
quantity: number | null;
|
|
427
|
+
activation: {
|
|
428
|
+
[key: string]: unknown;
|
|
429
|
+
} | null;
|
|
430
|
+
};
|
|
431
|
+
}>;
|
|
432
|
+
/**
|
|
433
|
+
* `DELETE /desarrollador/tenants/{slug}/activaciones/{kind}/{item}`: dar de
|
|
434
|
+
* baja. El módulo se apaga y deja de cobrarse; la app se desinstala de
|
|
435
|
+
* todas las empresas; la base suelta el asiento.
|
|
436
|
+
*/
|
|
437
|
+
deactivate: (tenantSlug: string, kind: "base" | "module" | "app", item: string) => Promise<{
|
|
438
|
+
message: string;
|
|
439
|
+
data: {
|
|
440
|
+
quantity: number | null;
|
|
441
|
+
};
|
|
442
|
+
}>;
|
|
443
|
+
};
|
|
444
|
+
get dominios(): {
|
|
445
|
+
/** `GET /desarrollador/dominios`: sus nombres de login, con el `upstream` y el bloque de proxy de cada uno. */
|
|
446
|
+
list: () => Promise<{
|
|
447
|
+
data: {
|
|
448
|
+
slug: string;
|
|
449
|
+
host: string;
|
|
450
|
+
enabled: boolean;
|
|
451
|
+
login_url: string;
|
|
452
|
+
upstream: string;
|
|
453
|
+
proxy_secret: string;
|
|
454
|
+
proxy: string;
|
|
455
|
+
created_at: string | null;
|
|
456
|
+
}[];
|
|
457
|
+
}>;
|
|
458
|
+
/**
|
|
459
|
+
* `POST /desarrollador/dominios`: declarar el nombre público que el
|
|
460
|
+
* integrador sirve (`host`, p. ej. `login.erpstudio.es`) y su etiqueta
|
|
461
|
+
* interna (`slug`). Pimia no emite certificados ni toca DNS: devuelve
|
|
462
|
+
* `upstream` (`https://login-<slug>.<central>`), a donde su proxy tiene
|
|
463
|
+
* que reenviar con `Host` interno y el nombre público en
|
|
464
|
+
* `X-Forwarded-Host`, y `proxy`, el bloque de Caddy listo para pegar.
|
|
465
|
+
*/
|
|
466
|
+
declare: (body: IntegradorDominioRequest) => Promise<{
|
|
467
|
+
message: "Nombre declarado. Apunta tu proxy al upstream y reenv\u00EDa el nombre p\u00FAblico en X-Forwarded-Host.";
|
|
468
|
+
data: {
|
|
469
|
+
slug: string;
|
|
470
|
+
host: string;
|
|
471
|
+
enabled: boolean;
|
|
472
|
+
login_url: string;
|
|
473
|
+
upstream: string;
|
|
474
|
+
proxy_secret: string;
|
|
475
|
+
proxy: string;
|
|
476
|
+
created_at: string | null;
|
|
477
|
+
};
|
|
478
|
+
}>;
|
|
479
|
+
/** `DELETE /desarrollador/dominios/{slug}`: retirar el nombre; el host interno deja de contestar. */
|
|
480
|
+
remove: (slug: string) => Promise<{
|
|
481
|
+
message: string;
|
|
482
|
+
}>;
|
|
483
|
+
};
|
|
484
|
+
get tokens(): {
|
|
485
|
+
/** `GET /desarrollador/tokens`: los tokens de máquina vivos (nunca los de una sesión del panel). */
|
|
486
|
+
list: () => Promise<{
|
|
487
|
+
data: {
|
|
488
|
+
id: number;
|
|
489
|
+
name: string;
|
|
490
|
+
abilities: string[];
|
|
491
|
+
last_used_at: string | null;
|
|
492
|
+
expires_at: string | null;
|
|
493
|
+
created_at: string | null;
|
|
494
|
+
}[];
|
|
495
|
+
}>;
|
|
496
|
+
/**
|
|
497
|
+
* `POST /desarrollador/tokens`: acuñar un token de máquina, acotado a la
|
|
498
|
+
* habilidad `desarrollador` y nada más. El token en claro (`data.token`)
|
|
499
|
+
* se devuelve UNA vez: guárdalo en tu servidor.
|
|
500
|
+
*/
|
|
501
|
+
create: (body: IntegradorTokenRequest) => Promise<{
|
|
502
|
+
message: "Token creado. Gu\u00E1rdalo ahora: no se vuelve a ense\u00F1ar.";
|
|
503
|
+
data: {
|
|
504
|
+
token: string;
|
|
505
|
+
id: number;
|
|
506
|
+
name: string;
|
|
507
|
+
abilities: unknown[];
|
|
508
|
+
last_used_at: string | null;
|
|
509
|
+
expires_at: string | null;
|
|
510
|
+
created_at: string | null;
|
|
511
|
+
};
|
|
512
|
+
}>;
|
|
513
|
+
/** `DELETE /desarrollador/tokens/{id}`: revocarlo. */
|
|
514
|
+
revoke: (id: number | string) => Promise<{
|
|
515
|
+
message: string;
|
|
516
|
+
}>;
|
|
517
|
+
};
|
|
518
|
+
get invitations(): {
|
|
519
|
+
list: () => Promise<{
|
|
520
|
+
data: {
|
|
521
|
+
id: string;
|
|
522
|
+
email: string;
|
|
523
|
+
company_name: string;
|
|
524
|
+
billing: string;
|
|
525
|
+
status: string;
|
|
526
|
+
expires_at: string;
|
|
527
|
+
accepted_tenant_id: string;
|
|
528
|
+
accepted_at: string;
|
|
529
|
+
created_at: string;
|
|
530
|
+
}[];
|
|
531
|
+
}>;
|
|
532
|
+
/** El cliente se registra y nace dueño; `billing` dice quién paga. */
|
|
533
|
+
create: (body: TenantInvitationRequest) => Promise<{
|
|
534
|
+
message: string;
|
|
535
|
+
data: {
|
|
536
|
+
id: string;
|
|
537
|
+
email: string;
|
|
538
|
+
company_name: string;
|
|
539
|
+
billing: string;
|
|
540
|
+
status: string;
|
|
541
|
+
expires_at: string;
|
|
542
|
+
accepted_tenant_id: string;
|
|
543
|
+
accepted_at: string;
|
|
544
|
+
created_at: string;
|
|
545
|
+
};
|
|
546
|
+
}>;
|
|
547
|
+
revoke: (id: number | string) => Promise<{
|
|
548
|
+
message: "Invitaci\u00F3n revocada.";
|
|
549
|
+
}>;
|
|
550
|
+
};
|
|
551
|
+
get billing(): {
|
|
552
|
+
/**
|
|
553
|
+
* `POST /billing/portal` (1.4.0): la URL del portal de Stripe de la
|
|
554
|
+
* cuenta del integrador —las facturas del canal y el método de pago
|
|
555
|
+
* viven allí, no en Pimia—. 404 si la cuenta no tiene cliente de Stripe
|
|
556
|
+
* todavía (nunca patrocinó a nadie).
|
|
557
|
+
*/
|
|
558
|
+
portal: (body?: BillingPortalRequest) => Promise<{
|
|
559
|
+
data: {
|
|
560
|
+
portal_url: string;
|
|
561
|
+
};
|
|
562
|
+
}>;
|
|
563
|
+
};
|
|
564
|
+
get sponsorship(): {
|
|
565
|
+
/** Asumir la licencia de un cliente: un asiento más en el plan de canal. */
|
|
566
|
+
sponsor: (body: SponsorshipRequest) => Promise<string | {
|
|
567
|
+
message: "Completa el alta de tu suscripci\u00F3n de canal para activar el patrocinio." | "Asumida la licencia de la instancia.";
|
|
568
|
+
data: {
|
|
569
|
+
checkout_url: string | null;
|
|
570
|
+
};
|
|
571
|
+
}>;
|
|
572
|
+
/** Soltar un cliente patrocinado (queda en gracia y puede rescatarse). */
|
|
573
|
+
release: (tenantSlug: string) => Promise<string | {
|
|
574
|
+
message: "Has dejado de pagar la licencia de esta instancia.";
|
|
575
|
+
}>;
|
|
576
|
+
};
|
|
577
|
+
get tenants(): {
|
|
578
|
+
/**
|
|
579
|
+
* `GET /tenants/{slug}/users` (1.4.0): quién pertenece a la instancia
|
|
580
|
+
* —nombre, correo, rol, `is_owner`—. Es a quién se le puede traspasar:
|
|
581
|
+
* `transferOwnership` pide el `user_id` de alguien que ya está dentro.
|
|
582
|
+
*/
|
|
583
|
+
users: (slug: string) => Promise<{
|
|
584
|
+
data: {
|
|
585
|
+
id: number;
|
|
586
|
+
name: string;
|
|
587
|
+
email: string;
|
|
588
|
+
role: string;
|
|
589
|
+
invited_at: string | null;
|
|
590
|
+
is_owner: boolean;
|
|
591
|
+
}[];
|
|
592
|
+
}>;
|
|
593
|
+
/** Traspasar la propiedad de la instancia a un usuario de la misma, antes de entregarla. */
|
|
594
|
+
transferOwnership: (slug: string, body: TransferOwnershipRequest) => Promise<{
|
|
595
|
+
message: string;
|
|
596
|
+
data: {
|
|
597
|
+
tenant_id: string;
|
|
598
|
+
owner_id: number;
|
|
599
|
+
billing_mode: "sponsor" | "self";
|
|
600
|
+
};
|
|
601
|
+
}>;
|
|
602
|
+
};
|
|
603
|
+
request<T = unknown>(path: string, options?: CentralRequestOptions): Promise<T>;
|
|
604
|
+
requestWithMeta<T = unknown>(path: string, options?: CentralRequestOptions): Promise<CentralResponseWithMeta<T>>;
|
|
605
|
+
private urlFor;
|
|
606
|
+
}
|
|
607
|
+
export {};
|