@gzl10/baserow 1.2.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/CHANGELOG.md +435 -0
- package/README.md +847 -0
- package/dist/index.d.ts +8749 -0
- package/dist/index.js +11167 -0
- package/dist/index.js.map +1 -0
- package/package.json +91 -0
- package/src/BaserowClient.ts +501 -0
- package/src/ClientWithCreds.ts +545 -0
- package/src/ClientWithCredsWs.ts +852 -0
- package/src/ClientWithToken.ts +171 -0
- package/src/contexts/DatabaseClientContext.ts +114 -0
- package/src/contexts/DatabaseContext.ts +870 -0
- package/src/contexts/DatabaseTokenContext.ts +331 -0
- package/src/contexts/FieldContext.ts +399 -0
- package/src/contexts/RowContext.ts +99 -0
- package/src/contexts/TableClientContext.ts +291 -0
- package/src/contexts/TableContext.ts +1247 -0
- package/src/contexts/TableOnlyContext.ts +74 -0
- package/src/contexts/WorkspaceContext.ts +490 -0
- package/src/express/errors.ts +260 -0
- package/src/express/index.ts +69 -0
- package/src/express/middleware.ts +225 -0
- package/src/express/serializers.ts +314 -0
- package/src/index.ts +247 -0
- package/src/presets/performance.ts +262 -0
- package/src/services/AuthService.ts +472 -0
- package/src/services/DatabaseService.ts +246 -0
- package/src/services/DatabaseTokenService.ts +186 -0
- package/src/services/FieldService.ts +1543 -0
- package/src/services/RowService.ts +982 -0
- package/src/services/SchemaControlService.ts +420 -0
- package/src/services/TableService.ts +781 -0
- package/src/services/WorkspaceService.ts +113 -0
- package/src/services/core/BaseAuthClient.ts +111 -0
- package/src/services/core/BaseClient.ts +107 -0
- package/src/services/core/BaseService.ts +71 -0
- package/src/services/core/HttpService.ts +115 -0
- package/src/services/core/ValidationService.ts +149 -0
- package/src/types/auth.ts +177 -0
- package/src/types/core.ts +91 -0
- package/src/types/errors.ts +105 -0
- package/src/types/fields.ts +456 -0
- package/src/types/index.ts +222 -0
- package/src/types/requests.ts +333 -0
- package/src/types/responses.ts +50 -0
- package/src/types/schema.ts +446 -0
- package/src/types/tokens.ts +36 -0
- package/src/types.ts +11 -0
- package/src/utils/auth.ts +174 -0
- package/src/utils/axios.ts +647 -0
- package/src/utils/field-cache.ts +164 -0
- package/src/utils/httpFactory.ts +66 -0
- package/src/utils/jwt-decoder.ts +188 -0
- package/src/utils/jwtTokens.ts +50 -0
- package/src/utils/performance.ts +105 -0
- package/src/utils/prisma-mapper.ts +961 -0
- package/src/utils/validation.ts +463 -0
- package/src/validators/schema.ts +419 -0
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
import type { Table } from './core'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tipos TypeScript para el sistema de definición declarativa de schemas
|
|
5
|
+
*
|
|
6
|
+
* Permite definir esquemas de base de datos completos usando un formato
|
|
7
|
+
* JSON/TypeScript que luego puede ser aplicado usando database().loadSchema()
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const ecommerceSchema: DatabaseSchema = {
|
|
12
|
+
* version: "1.0.0",
|
|
13
|
+
* tables: [
|
|
14
|
+
* {
|
|
15
|
+
* name: "clientes",
|
|
16
|
+
* fields: [
|
|
17
|
+
* { name: "nombre", type: "text" },
|
|
18
|
+
* { name: "email", type: "email" },
|
|
19
|
+
* {
|
|
20
|
+
* name: "categoria",
|
|
21
|
+
* type: "single_select",
|
|
22
|
+
* config: {
|
|
23
|
+
* options: [
|
|
24
|
+
* { value: "Premium", color: "blue" }
|
|
25
|
+
* ]
|
|
26
|
+
* }
|
|
27
|
+
* }
|
|
28
|
+
* ]
|
|
29
|
+
* }
|
|
30
|
+
* ],
|
|
31
|
+
* relationships: [
|
|
32
|
+
* {
|
|
33
|
+
* name: "cliente",
|
|
34
|
+
* sourceTable: "pedidos",
|
|
35
|
+
* targetTable: "clientes"
|
|
36
|
+
* }
|
|
37
|
+
* ]
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Schema completo de una base de datos
|
|
45
|
+
*/
|
|
46
|
+
export interface DatabaseSchema {
|
|
47
|
+
/** Versión del schema para control de cambios */
|
|
48
|
+
version?: string
|
|
49
|
+
/** Descripción del propósito de la base de datos */
|
|
50
|
+
description?: string
|
|
51
|
+
/** Definición de todas las tablas */
|
|
52
|
+
tables: TableSchema[]
|
|
53
|
+
/** Relaciones entre tablas (se crean después de las tablas) */
|
|
54
|
+
relationships?: RelationshipSchema[]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Schema de una tabla individual
|
|
59
|
+
*/
|
|
60
|
+
export interface TableSchema {
|
|
61
|
+
/** Nombre de la tabla */
|
|
62
|
+
name: string
|
|
63
|
+
/** Descripción opcional de la tabla */
|
|
64
|
+
description?: string
|
|
65
|
+
/** Definición de todos los campos de la tabla */
|
|
66
|
+
fields: FieldSchema[]
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Schema de un campo individual
|
|
71
|
+
*/
|
|
72
|
+
export interface FieldSchema {
|
|
73
|
+
/** Nombre del campo */
|
|
74
|
+
name: string
|
|
75
|
+
/** Tipo de campo de Baserow */
|
|
76
|
+
type: FieldType
|
|
77
|
+
/** Descripción opcional del campo */
|
|
78
|
+
description?: string
|
|
79
|
+
/** Configuración específica según el tipo de campo */
|
|
80
|
+
config?: FieldConfig
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Schema de una relación entre tablas
|
|
85
|
+
*/
|
|
86
|
+
export interface RelationshipSchema {
|
|
87
|
+
/** Nombre del campo de relación */
|
|
88
|
+
name: string
|
|
89
|
+
/** Tabla que contiene la relación (tabla origen) */
|
|
90
|
+
sourceTable: string
|
|
91
|
+
/** Tabla objetivo de la relación */
|
|
92
|
+
targetTable: string
|
|
93
|
+
/** Descripción opcional de la relación */
|
|
94
|
+
description?: string
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Tipos de campos soportados por Baserow
|
|
99
|
+
*/
|
|
100
|
+
export type FieldType =
|
|
101
|
+
// Campos de texto
|
|
102
|
+
| 'text'
|
|
103
|
+
| 'long_text'
|
|
104
|
+
| 'url'
|
|
105
|
+
| 'email'
|
|
106
|
+
| 'phone_number'
|
|
107
|
+
|
|
108
|
+
// Campos numéricos
|
|
109
|
+
| 'number'
|
|
110
|
+
| 'rating'
|
|
111
|
+
|
|
112
|
+
// Campos de fecha
|
|
113
|
+
| 'date'
|
|
114
|
+
| 'last_modified'
|
|
115
|
+
| 'created_on'
|
|
116
|
+
| 'last_modified_by'
|
|
117
|
+
| 'created_by'
|
|
118
|
+
|
|
119
|
+
// Campos de selección
|
|
120
|
+
| 'single_select'
|
|
121
|
+
| 'multiple_select'
|
|
122
|
+
|
|
123
|
+
// Campos booleanos
|
|
124
|
+
| 'boolean'
|
|
125
|
+
|
|
126
|
+
// Campos de relación
|
|
127
|
+
| 'link_row'
|
|
128
|
+
| 'formula'
|
|
129
|
+
|
|
130
|
+
// Campos avanzados
|
|
131
|
+
| 'file'
|
|
132
|
+
| 'autonumber'
|
|
133
|
+
| 'count'
|
|
134
|
+
| 'rollup'
|
|
135
|
+
| 'lookup'
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Configuración específica por tipo de campo
|
|
139
|
+
*/
|
|
140
|
+
export type FieldConfig =
|
|
141
|
+
| TextFieldConfig
|
|
142
|
+
| NumberFieldConfig
|
|
143
|
+
| DateFieldConfig
|
|
144
|
+
| SelectFieldConfig
|
|
145
|
+
| MultiSelectFieldConfig
|
|
146
|
+
| BooleanFieldConfig
|
|
147
|
+
| LinkRowFieldConfig
|
|
148
|
+
| FormulaFieldConfig
|
|
149
|
+
| FileFieldConfig
|
|
150
|
+
| CountFieldConfig
|
|
151
|
+
| RollupFieldConfig
|
|
152
|
+
| LookupFieldConfig
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Configuración para campos de texto
|
|
156
|
+
*/
|
|
157
|
+
export interface TextFieldConfig {
|
|
158
|
+
/** Valor por defecto */
|
|
159
|
+
default?: string
|
|
160
|
+
/** Texto de placeholder */
|
|
161
|
+
placeholder?: string
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Configuración para campos numéricos
|
|
166
|
+
*/
|
|
167
|
+
export interface NumberFieldConfig {
|
|
168
|
+
/** Número de decimales (0 para enteros) */
|
|
169
|
+
decimals?: number
|
|
170
|
+
/** Valor mínimo permitido */
|
|
171
|
+
min?: number
|
|
172
|
+
/** Valor máximo permitido */
|
|
173
|
+
max?: number
|
|
174
|
+
/** Valor por defecto */
|
|
175
|
+
default?: number
|
|
176
|
+
/** Prefijo (ej: "$") */
|
|
177
|
+
prefix?: string
|
|
178
|
+
/** Sufijo (ej: " €") */
|
|
179
|
+
suffix?: string
|
|
180
|
+
/** Formato de separadores */
|
|
181
|
+
separators?: 'COMMA_PERIOD' | 'PERIOD_COMMA'
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Configuración para campos de fecha
|
|
186
|
+
*/
|
|
187
|
+
export interface DateFieldConfig {
|
|
188
|
+
/** Incluir tiempo además de fecha */
|
|
189
|
+
includeTime?: boolean
|
|
190
|
+
/** Formato de fecha */
|
|
191
|
+
format?: 'ISO' | 'US' | 'EU'
|
|
192
|
+
/** Formato de hora */
|
|
193
|
+
timeFormat?: '24' | '12'
|
|
194
|
+
/** Valor por defecto */
|
|
195
|
+
default?: string
|
|
196
|
+
/** Zona horaria */
|
|
197
|
+
timezone?: string
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Configuración para campos single_select
|
|
202
|
+
*/
|
|
203
|
+
export interface SelectFieldConfig {
|
|
204
|
+
/** Opciones disponibles */
|
|
205
|
+
options: SelectOption[]
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Configuración para campos multiple_select
|
|
210
|
+
*/
|
|
211
|
+
export interface MultiSelectFieldConfig {
|
|
212
|
+
/** Opciones disponibles */
|
|
213
|
+
options: SelectOption[]
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Opción para campos de selección
|
|
218
|
+
*/
|
|
219
|
+
export interface SelectOption {
|
|
220
|
+
/** Valor de la opción */
|
|
221
|
+
value: string
|
|
222
|
+
/** Color de la opción */
|
|
223
|
+
color: SelectOptionColor
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Colores disponibles para opciones de select
|
|
228
|
+
*/
|
|
229
|
+
export type SelectOptionColor =
|
|
230
|
+
| 'blue'
|
|
231
|
+
| 'green'
|
|
232
|
+
| 'red'
|
|
233
|
+
| 'yellow'
|
|
234
|
+
| 'orange'
|
|
235
|
+
| 'purple'
|
|
236
|
+
| 'pink'
|
|
237
|
+
| 'brown'
|
|
238
|
+
| 'gray'
|
|
239
|
+
| 'dark_blue'
|
|
240
|
+
| 'dark_green'
|
|
241
|
+
| 'dark_red'
|
|
242
|
+
| 'dark_yellow'
|
|
243
|
+
| 'dark_orange'
|
|
244
|
+
| 'dark_purple'
|
|
245
|
+
| 'dark_pink'
|
|
246
|
+
| 'dark_brown'
|
|
247
|
+
| 'dark_gray'
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Configuración para campos boolean
|
|
251
|
+
*/
|
|
252
|
+
export interface BooleanFieldConfig {
|
|
253
|
+
/** Valor por defecto */
|
|
254
|
+
default?: boolean
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Configuración para campos link_row (relaciones)
|
|
259
|
+
*/
|
|
260
|
+
export interface LinkRowFieldConfig {
|
|
261
|
+
/** ID de la tabla objetivo */
|
|
262
|
+
targetTableId?: number
|
|
263
|
+
/** Nombre de la tabla objetivo (se resuelve en runtime) */
|
|
264
|
+
targetTableName?: string
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Configuración para campos de fórmula
|
|
269
|
+
*/
|
|
270
|
+
export interface FormulaFieldConfig {
|
|
271
|
+
/** Fórmula a ejecutar */
|
|
272
|
+
formula: string
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Configuración para campos de archivo
|
|
277
|
+
*/
|
|
278
|
+
export interface FileFieldConfig {
|
|
279
|
+
/** Tipos de archivo permitidos */
|
|
280
|
+
allowedFileTypes?: string[]
|
|
281
|
+
/** Tamaño máximo en bytes */
|
|
282
|
+
maxFileSize?: number
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Configuración para campos count
|
|
287
|
+
*/
|
|
288
|
+
export interface CountFieldConfig {
|
|
289
|
+
/** ID de la tabla a contar */
|
|
290
|
+
targetTableId?: number
|
|
291
|
+
/** Nombre de la tabla a contar (se resuelve en runtime) */
|
|
292
|
+
targetTableName?: string
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Configuración para campos rollup
|
|
297
|
+
*/
|
|
298
|
+
export interface RollupFieldConfig {
|
|
299
|
+
/** ID de la tabla objetivo */
|
|
300
|
+
targetTableId?: number
|
|
301
|
+
/** Nombre de la tabla objetivo */
|
|
302
|
+
targetTableName?: string
|
|
303
|
+
/** ID del campo objetivo */
|
|
304
|
+
targetFieldId?: number
|
|
305
|
+
/** Nombre del campo objetivo */
|
|
306
|
+
targetFieldName?: string
|
|
307
|
+
/** Función de agregación */
|
|
308
|
+
aggregation: 'sum' | 'avg' | 'min' | 'max' | 'count'
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Configuración para campos lookup
|
|
313
|
+
*/
|
|
314
|
+
export interface LookupFieldConfig {
|
|
315
|
+
/** ID de la tabla objetivo */
|
|
316
|
+
targetTableId?: number
|
|
317
|
+
/** Nombre de la tabla objetivo */
|
|
318
|
+
targetTableName?: string
|
|
319
|
+
/** ID del campo objetivo */
|
|
320
|
+
targetFieldId?: number
|
|
321
|
+
/** Nombre del campo objetivo */
|
|
322
|
+
targetFieldName?: string
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Opciones para cargar un schema
|
|
327
|
+
*/
|
|
328
|
+
export interface LoadSchemaOptions {
|
|
329
|
+
/** Modo de carga */
|
|
330
|
+
mode?: LoadSchemaMode
|
|
331
|
+
/** Versión del schema (para tracking) */
|
|
332
|
+
version?: string
|
|
333
|
+
/** Forzar carga aunque no haya cambios */
|
|
334
|
+
force?: boolean
|
|
335
|
+
/** Limpiar tablas que no estén en el schema */
|
|
336
|
+
cleanup?: boolean
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Modos de carga de schema
|
|
341
|
+
*/
|
|
342
|
+
export type LoadSchemaMode =
|
|
343
|
+
/** Solo crear, no actualizar existentes */
|
|
344
|
+
| 'create-only'
|
|
345
|
+
/** Crear y actualizar campos existentes */
|
|
346
|
+
| 'update'
|
|
347
|
+
/** Recrear todo desde cero */
|
|
348
|
+
| 'recreate'
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Resultado de cargar un schema
|
|
352
|
+
*/
|
|
353
|
+
export interface LoadSchemaResult {
|
|
354
|
+
/** Tablas creadas/actualizadas */
|
|
355
|
+
tables: Table[]
|
|
356
|
+
/** Tablas indexadas por nombre para fácil acceso */
|
|
357
|
+
tablesByName: Record<string, Table>
|
|
358
|
+
/** Información de control del schema */
|
|
359
|
+
schemaControl: SchemaControl
|
|
360
|
+
/** Lista de cambios aplicados */
|
|
361
|
+
changes: SchemaChange[]
|
|
362
|
+
/** Estadísticas de la operación */
|
|
363
|
+
stats: LoadSchemaStats
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Información de control del schema cargado
|
|
368
|
+
*/
|
|
369
|
+
export interface SchemaControl {
|
|
370
|
+
/** ID único del control */
|
|
371
|
+
id: string
|
|
372
|
+
/** Versión del schema */
|
|
373
|
+
version: string
|
|
374
|
+
/** Hash del schema para detectar cambios */
|
|
375
|
+
schemaHash: string
|
|
376
|
+
/** Fecha de carga */
|
|
377
|
+
loadedAt: Date
|
|
378
|
+
/** Nombres de tablas creadas por este schema */
|
|
379
|
+
tablesCreated: string[]
|
|
380
|
+
/** Estado del schema */
|
|
381
|
+
status: SchemaControlStatus
|
|
382
|
+
/** Opciones usadas para la carga */
|
|
383
|
+
loadOptions: LoadSchemaOptions
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Estados del control de schema
|
|
388
|
+
*/
|
|
389
|
+
export type SchemaControlStatus =
|
|
390
|
+
/** Schema activo y actualizado */
|
|
391
|
+
| 'active'
|
|
392
|
+
/** Schema desactualizado */
|
|
393
|
+
| 'outdated'
|
|
394
|
+
/** Error en la carga */
|
|
395
|
+
| 'error'
|
|
396
|
+
/** Carga en progreso */
|
|
397
|
+
| 'loading'
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Tipos de cambios aplicados durante la carga
|
|
401
|
+
*/
|
|
402
|
+
export interface SchemaChange {
|
|
403
|
+
/** Tipo de cambio */
|
|
404
|
+
type: SchemaChangeType
|
|
405
|
+
/** Elemento afectado */
|
|
406
|
+
target: string
|
|
407
|
+
/** Descripción del cambio */
|
|
408
|
+
description: string
|
|
409
|
+
/** Detalles adicionales */
|
|
410
|
+
details?: any
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Tipos de cambios de schema
|
|
415
|
+
*/
|
|
416
|
+
export type SchemaChangeType =
|
|
417
|
+
| 'table_created'
|
|
418
|
+
| 'table_updated'
|
|
419
|
+
| 'table_deleted'
|
|
420
|
+
| 'field_created'
|
|
421
|
+
| 'field_updated'
|
|
422
|
+
| 'field_deleted'
|
|
423
|
+
| 'relationship_created'
|
|
424
|
+
| 'relationship_updated'
|
|
425
|
+
| 'relationship_deleted'
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Estadísticas de la operación de carga
|
|
429
|
+
*/
|
|
430
|
+
export interface LoadSchemaStats {
|
|
431
|
+
/** Tiempo total de ejecución en ms */
|
|
432
|
+
duration: number
|
|
433
|
+
/** Número de tablas procesadas */
|
|
434
|
+
tablesProcessed: number
|
|
435
|
+
/** Número de campos procesados */
|
|
436
|
+
fieldsProcessed: number
|
|
437
|
+
/** Número de relaciones procesadas */
|
|
438
|
+
relationshipsProcessed: number
|
|
439
|
+
/** Número de errores encontrados */
|
|
440
|
+
errors: number
|
|
441
|
+
/** Número de warnings */
|
|
442
|
+
warnings: number
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// Re-export tipos necesarios de otros archivos
|
|
446
|
+
export type { Table, Field, Row } from './index'
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tipos relacionados con Database Tokens de Baserow
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Prefijo único para identificar tokens creados por la librería
|
|
7
|
+
* vs tokens creados manualmente por usuarios
|
|
8
|
+
*/
|
|
9
|
+
export const LIBRARY_TOKEN_PREFIX = 'br-lib:'
|
|
10
|
+
|
|
11
|
+
export interface DatabaseTokenPermissions {
|
|
12
|
+
create: boolean
|
|
13
|
+
read: boolean
|
|
14
|
+
update: boolean
|
|
15
|
+
delete: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface DatabaseToken {
|
|
19
|
+
id: number
|
|
20
|
+
name: string
|
|
21
|
+
token: string
|
|
22
|
+
workspace: number
|
|
23
|
+
permissions: DatabaseTokenPermissions
|
|
24
|
+
created_on: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface CreateDatabaseTokenRequest {
|
|
28
|
+
name: string
|
|
29
|
+
permissions: DatabaseTokenPermissions
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface UpdateDatabaseTokenRequest {
|
|
33
|
+
name?: string
|
|
34
|
+
permissions?: DatabaseTokenPermissions
|
|
35
|
+
rotate_token?: boolean
|
|
36
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tipos TypeScript para Baserow API
|
|
3
|
+
*
|
|
4
|
+
* DEPRECATED: Este archivo mantiene compatibilidad hacia atrás.
|
|
5
|
+
* Usa imports específicos desde src/types/ para mejor tree-shaking.
|
|
6
|
+
*
|
|
7
|
+
* @deprecated Use imports from './types/index.js' instead
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Re-export todo desde el nuevo index modular
|
|
11
|
+
export * from './types/index'
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { HttpClient } from './axios'
|
|
2
|
+
import { BaserowCredentials, BaserowError, LoginResponse, Logger } from '../types'
|
|
3
|
+
import { validateRequired, validateString, validateUrl } from './validation'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Opciones para la verificación de login
|
|
7
|
+
*/
|
|
8
|
+
export interface VerifyLoginOptions {
|
|
9
|
+
/** Timeout en milisegundos (default: 10000) */
|
|
10
|
+
timeout?: number
|
|
11
|
+
/** Logger para debug (opcional) */
|
|
12
|
+
logger?: Logger
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Verificar si las credenciales de Baserow son válidas sin crear cliente
|
|
17
|
+
*
|
|
18
|
+
* Esta función es útil para:
|
|
19
|
+
* - Validar credenciales en formularios de login
|
|
20
|
+
* - Health checks de credenciales
|
|
21
|
+
* - Verificación de configuración antes de inicializar la aplicación
|
|
22
|
+
*
|
|
23
|
+
* @param url URL base de Baserow (ej: 'https://baserow.gzl10.com')
|
|
24
|
+
* @param credentials Credenciales de usuario (email y password)
|
|
25
|
+
* @param options Opciones adicionales (timeout, logger)
|
|
26
|
+
* @returns Promise<boolean> - true si las credenciales son válidas
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* import { verifyLogin } from '@gzl10/baserow'
|
|
31
|
+
*
|
|
32
|
+
* const isValid = await verifyLogin('https://baserow.gzl10.com', {
|
|
33
|
+
* email: 'user@example.com',
|
|
34
|
+
* password: 'password123'
|
|
35
|
+
* })
|
|
36
|
+
*
|
|
37
|
+
* if (isValid) {
|
|
38
|
+
* // Proceder a crear BaserowAdmin
|
|
39
|
+
* const admin = await BaserowAdmin.create({ ... })
|
|
40
|
+
* } else {
|
|
41
|
+
* // Mostrar error en UI
|
|
42
|
+
* console.error('Credenciales inválidas')
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export async function verifyLogin(
|
|
47
|
+
url: string,
|
|
48
|
+
credentials: BaserowCredentials,
|
|
49
|
+
options: VerifyLoginOptions = {}
|
|
50
|
+
): Promise<boolean> {
|
|
51
|
+
// Validación de parámetros
|
|
52
|
+
validateRequired(url, 'url')
|
|
53
|
+
validateRequired(credentials, 'credentials')
|
|
54
|
+
validateString(credentials.email, 'email')
|
|
55
|
+
validateString(credentials.password, 'password')
|
|
56
|
+
|
|
57
|
+
if (!validateUrl(url)) {
|
|
58
|
+
throw new Error('url must be a valid URL')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const { timeout = 10000, logger } = options
|
|
62
|
+
|
|
63
|
+
// Crear HttpClient temporal (sin almacenar estado)
|
|
64
|
+
let tempHttp: HttpClient | undefined
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
tempHttp = new HttpClient({
|
|
68
|
+
baseURL: `${url.replace(/\/$/, '')}/api`,
|
|
69
|
+
token: '', // Sin token inicial
|
|
70
|
+
timeout,
|
|
71
|
+
logger
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
logger?.info?.('BaserowAuth: Verifying credentials...')
|
|
75
|
+
|
|
76
|
+
// Intentar login con las credenciales proporcionadas
|
|
77
|
+
const loginData = {
|
|
78
|
+
username: credentials.email,
|
|
79
|
+
password: credentials.password
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const response = await tempHttp.post<LoginResponse>('/user/token-auth/', loginData)
|
|
83
|
+
|
|
84
|
+
// Si llegamos aquí, el login fue exitoso
|
|
85
|
+
logger?.info?.(`BaserowAuth: Credentials valid for user ${response.user.username}`)
|
|
86
|
+
return true
|
|
87
|
+
} catch (error) {
|
|
88
|
+
// Manejar diferentes tipos de errores
|
|
89
|
+
if (error instanceof BaserowError) {
|
|
90
|
+
switch (error.status) {
|
|
91
|
+
case 401:
|
|
92
|
+
// Credenciales inválidas
|
|
93
|
+
logger?.warn?.('BaserowAuth: Invalid credentials provided')
|
|
94
|
+
return false
|
|
95
|
+
|
|
96
|
+
case 400:
|
|
97
|
+
// Bad request (formato incorrecto)
|
|
98
|
+
logger?.warn?.('BaserowAuth: Bad request - invalid data format')
|
|
99
|
+
return false
|
|
100
|
+
|
|
101
|
+
case 403:
|
|
102
|
+
// Usuario bloqueado o sin permisos
|
|
103
|
+
logger?.warn?.('BaserowAuth: User forbidden or blocked')
|
|
104
|
+
return false
|
|
105
|
+
|
|
106
|
+
case 429:
|
|
107
|
+
// Rate limit - técnicamente las credenciales podrían ser válidas
|
|
108
|
+
logger?.warn?.('BaserowAuth: Rate limited - cannot verify at this time')
|
|
109
|
+
return false
|
|
110
|
+
|
|
111
|
+
case 500:
|
|
112
|
+
case 502:
|
|
113
|
+
case 503:
|
|
114
|
+
case 504:
|
|
115
|
+
// Errores del servidor
|
|
116
|
+
logger?.error?.('BaserowAuth: Server error during login verification')
|
|
117
|
+
return false
|
|
118
|
+
|
|
119
|
+
default:
|
|
120
|
+
// Otros errores HTTP
|
|
121
|
+
logger?.error?.(`BaserowAuth: HTTP error ${error.status}: ${error.message}`)
|
|
122
|
+
return false
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Errores de red, timeout, etc.
|
|
127
|
+
logger?.error?.('BaserowAuth: Network or connection error:', error)
|
|
128
|
+
return false
|
|
129
|
+
} finally {
|
|
130
|
+
// Limpieza: el HttpClient temporal se garbage-collectea automáticamente
|
|
131
|
+
// No necesitamos limpiar tokens porque no los almacenamos
|
|
132
|
+
tempHttp = undefined
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Verificar si una URL de Baserow es accesible (health check básico)
|
|
138
|
+
*
|
|
139
|
+
* @param url URL base de Baserow
|
|
140
|
+
* @param options Opciones de verificación
|
|
141
|
+
* @returns Promise<boolean> - true si el servidor es accesible
|
|
142
|
+
*/
|
|
143
|
+
export async function verifyBaserowHealth(
|
|
144
|
+
url: string,
|
|
145
|
+
options: Pick<VerifyLoginOptions, 'timeout' | 'logger'> = {}
|
|
146
|
+
): Promise<boolean> {
|
|
147
|
+
validateRequired(url, 'url')
|
|
148
|
+
|
|
149
|
+
if (!validateUrl(url)) {
|
|
150
|
+
throw new Error('url must be a valid URL')
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const { timeout = 5000, logger } = options
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
logger?.info?.('BaserowAuth: Checking Baserow health...')
|
|
157
|
+
|
|
158
|
+
// Usar endpoint público de health que no requiere autenticación
|
|
159
|
+
const healthUrl = `${url.replace(/\/$/, '')}/api/_health/`
|
|
160
|
+
const response = await fetch(healthUrl, {
|
|
161
|
+
method: 'GET',
|
|
162
|
+
headers: { 'Content-Type': 'application/json' },
|
|
163
|
+
signal: AbortSignal.timeout(timeout)
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
const isHealthy = response.ok
|
|
167
|
+
logger?.info?.(`BaserowAuth: Baserow health check ${isHealthy ? 'passed' : 'failed'}`)
|
|
168
|
+
|
|
169
|
+
return isHealthy
|
|
170
|
+
} catch (error) {
|
|
171
|
+
logger?.error?.('BaserowAuth: Health check failed:', error)
|
|
172
|
+
return false
|
|
173
|
+
}
|
|
174
|
+
}
|