@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,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serializadores Express para @gzl10/baserow
|
|
3
|
+
*
|
|
4
|
+
* Utilidades para convertir objetos de Baserow en formatos apropiados para respuestas Express.
|
|
5
|
+
* Proporciona serialización consistente y limpieza de datos para APIs REST.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import express from 'express'
|
|
10
|
+
* import { BaserowClient, express as baserowExpress } from '@gzl10/baserow'
|
|
11
|
+
*
|
|
12
|
+
* app.get('/api/tables/:id/rows', async (req, res, next) => {
|
|
13
|
+
* try {
|
|
14
|
+
* const result = await req.baserow!.database(123).table(456).rows.list()
|
|
15
|
+
* const serialized = baserowExpress.serializePaginated(result)
|
|
16
|
+
* res.json(serialized)
|
|
17
|
+
* } catch (error) {
|
|
18
|
+
* next(error) // Will be handled by baserowExpress.errorHandler()
|
|
19
|
+
* }
|
|
20
|
+
* })
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @since 1.0.0
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import type { Row, Table, Field, Database, Workspace, QueryOptions } from '../types'
|
|
27
|
+
|
|
28
|
+
// Definir tipos locales para los serializers Express
|
|
29
|
+
export interface PaginatedResult<T> {
|
|
30
|
+
results: T[]
|
|
31
|
+
count: number
|
|
32
|
+
next: string | null
|
|
33
|
+
previous: string | null
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Formato estándar para respuestas paginadas
|
|
38
|
+
*/
|
|
39
|
+
export interface PaginatedResponse<T = any> {
|
|
40
|
+
data: T[]
|
|
41
|
+
pagination: {
|
|
42
|
+
count: number
|
|
43
|
+
next: string | null
|
|
44
|
+
previous: string | null
|
|
45
|
+
page: number
|
|
46
|
+
totalPages: number
|
|
47
|
+
}
|
|
48
|
+
meta?: {
|
|
49
|
+
total: number
|
|
50
|
+
filters?: Record<string, any>
|
|
51
|
+
ordering?: string
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Formato para respuestas de filas con metadatos
|
|
57
|
+
*/
|
|
58
|
+
export interface RowsResponse {
|
|
59
|
+
data: Row[]
|
|
60
|
+
fields: Field[]
|
|
61
|
+
table: {
|
|
62
|
+
id: number
|
|
63
|
+
name: string
|
|
64
|
+
database_id: number
|
|
65
|
+
}
|
|
66
|
+
pagination?: PaginatedResponse<Row>['pagination']
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Serializa resultado paginado de Baserow para respuesta Express
|
|
71
|
+
*
|
|
72
|
+
* Convierte el formato interno de paginación de Baserow en un formato
|
|
73
|
+
* estándar y consistente para APIs REST.
|
|
74
|
+
*
|
|
75
|
+
* @param result - Resultado paginado de Baserow
|
|
76
|
+
* @param options - Opciones adicionales de serialización
|
|
77
|
+
* @returns Respuesta paginada formateada
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* import { express as baserowExpress } from '@gzl10/baserow'
|
|
82
|
+
*
|
|
83
|
+
* app.get('/api/rows', async (req, res) => {
|
|
84
|
+
* const result = await req.baserow!.database(123).table(456).rows.list()
|
|
85
|
+
* const response = baserowExpress.serializePaginated(result, {
|
|
86
|
+
* baseUrl: req.baseUrl,
|
|
87
|
+
* includeTotal: true
|
|
88
|
+
* })
|
|
89
|
+
* res.json(response)
|
|
90
|
+
* })
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export function serializePaginated<T>(
|
|
94
|
+
result: PaginatedResult<T>,
|
|
95
|
+
options: {
|
|
96
|
+
baseUrl?: string
|
|
97
|
+
includeTotal?: boolean
|
|
98
|
+
} = {}
|
|
99
|
+
): PaginatedResponse<T> {
|
|
100
|
+
const { baseUrl = '', includeTotal = true } = options
|
|
101
|
+
|
|
102
|
+
// Calcular página actual y total de páginas
|
|
103
|
+
const page = Math.floor((result.previous ? extractPageFromUrl(result.previous) : 0) + 1)
|
|
104
|
+
const totalPages = result.count > 0 ? Math.ceil(result.count / result.results.length) : 1
|
|
105
|
+
|
|
106
|
+
const response: PaginatedResponse<T> = {
|
|
107
|
+
data: result.results,
|
|
108
|
+
pagination: {
|
|
109
|
+
count: result.results.length,
|
|
110
|
+
next: result.next ? makeRelativeUrl(result.next, baseUrl) : null,
|
|
111
|
+
previous: result.previous ? makeRelativeUrl(result.previous, baseUrl) : null,
|
|
112
|
+
page,
|
|
113
|
+
totalPages
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (includeTotal) {
|
|
118
|
+
response.meta = {
|
|
119
|
+
total: result.count
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return response
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Serializa filas de tabla con metadatos completos
|
|
128
|
+
*
|
|
129
|
+
* Incluye datos de filas junto con información de campos y tabla
|
|
130
|
+
* para proporcionar contexto completo en la respuesta.
|
|
131
|
+
*
|
|
132
|
+
* @param rows - Filas de la tabla
|
|
133
|
+
* @param table - Información de la tabla
|
|
134
|
+
* @param fields - Campos de la tabla
|
|
135
|
+
* @returns Respuesta completa con filas y metadatos
|
|
136
|
+
*/
|
|
137
|
+
export function serializeRowsWithMeta(rows: Row[] | PaginatedResult<Row>, table: Table, fields: Field[]): RowsResponse {
|
|
138
|
+
const isPaginated = 'results' in rows
|
|
139
|
+
const rowData = isPaginated ? rows.results : rows
|
|
140
|
+
|
|
141
|
+
const response: RowsResponse = {
|
|
142
|
+
data: rowData,
|
|
143
|
+
fields: fields,
|
|
144
|
+
table: {
|
|
145
|
+
id: table.id,
|
|
146
|
+
name: table.name,
|
|
147
|
+
database_id: table.database_id
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (isPaginated) {
|
|
152
|
+
response.pagination = serializePaginated(rows).pagination
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return response
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Limpia y serializa un campo de Baserow
|
|
160
|
+
*
|
|
161
|
+
* Remueve propiedades internas y normaliza la estructura del campo
|
|
162
|
+
* para respuestas de API.
|
|
163
|
+
*
|
|
164
|
+
* @param field - Campo de Baserow a limpiar
|
|
165
|
+
* @returns Campo serializado
|
|
166
|
+
*/
|
|
167
|
+
export function cleanField(field: Field): Partial<Field> {
|
|
168
|
+
// Propiedades core que siempre incluir
|
|
169
|
+
const cleaned: Partial<Field> = {
|
|
170
|
+
id: field.id,
|
|
171
|
+
name: field.name,
|
|
172
|
+
type: field.type,
|
|
173
|
+
order: field.order,
|
|
174
|
+
primary: field.primary
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Agregar propiedades específicas del tipo si existen
|
|
178
|
+
if ('table_id' in field) cleaned.table_id = field.table_id
|
|
179
|
+
if ('description' in field) cleaned.description = field.description
|
|
180
|
+
if ('read_only' in field) cleaned.read_only = field.read_only
|
|
181
|
+
|
|
182
|
+
// Propiedades específicas de tipos de campo
|
|
183
|
+
if ('number_decimal_places' in field) cleaned.number_decimal_places = field.number_decimal_places
|
|
184
|
+
if ('date_format' in field) cleaned.date_format = field.date_format
|
|
185
|
+
if ('date_include_time' in field) cleaned.date_include_time = field.date_include_time
|
|
186
|
+
if ('select_options' in field) cleaned.select_options = field.select_options
|
|
187
|
+
if ('link_row_table_id' in field) cleaned.link_row_table_id = field.link_row_table_id
|
|
188
|
+
|
|
189
|
+
return cleaned
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Serializa tabla de Baserow para respuesta Express
|
|
194
|
+
*
|
|
195
|
+
* @param table - Tabla de Baserow
|
|
196
|
+
* @param includeFields - Si incluir campos en la respuesta
|
|
197
|
+
* @returns Tabla serializada
|
|
198
|
+
*/
|
|
199
|
+
export function serializeTable(table: Table, includeFields = false): Partial<Table> {
|
|
200
|
+
const serialized: Partial<Table> = {
|
|
201
|
+
id: table.id,
|
|
202
|
+
name: table.name,
|
|
203
|
+
order: table.order,
|
|
204
|
+
database_id: table.database_id
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (includeFields && 'fields' in table && table.fields) {
|
|
208
|
+
;(serialized as any).fields = table.fields
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return serialized
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Serializa database de Baserow para respuesta Express
|
|
216
|
+
*
|
|
217
|
+
* @param database - Database de Baserow
|
|
218
|
+
* @param includeTables - Si incluir tablas en la respuesta
|
|
219
|
+
* @returns Database serializada
|
|
220
|
+
*/
|
|
221
|
+
export function serializeDatabase(database: Database, includeTables = false): Partial<Database> {
|
|
222
|
+
const serialized: Partial<Database> = {
|
|
223
|
+
id: database.id,
|
|
224
|
+
name: database.name,
|
|
225
|
+
order: database.order,
|
|
226
|
+
workspace: database.workspace
|
|
227
|
+
? {
|
|
228
|
+
id: database.workspace.id,
|
|
229
|
+
name: database.workspace.name
|
|
230
|
+
}
|
|
231
|
+
: undefined
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (includeTables && database.tables) {
|
|
235
|
+
serialized.tables = database.tables
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return serialized
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Serializa workspace de Baserow para respuesta Express
|
|
243
|
+
*
|
|
244
|
+
* @param workspace - Workspace de Baserow
|
|
245
|
+
* @returns Workspace serializado
|
|
246
|
+
*/
|
|
247
|
+
export function serializeWorkspace(workspace: Workspace): Partial<Workspace> {
|
|
248
|
+
return {
|
|
249
|
+
id: workspace.id,
|
|
250
|
+
name: workspace.name,
|
|
251
|
+
order: workspace.order
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Crea respuesta de éxito estándar
|
|
257
|
+
*
|
|
258
|
+
* @param data - Datos a incluir en la respuesta
|
|
259
|
+
* @param message - Mensaje opcional de éxito
|
|
260
|
+
* @returns Respuesta estándar de éxito
|
|
261
|
+
*/
|
|
262
|
+
export function createSuccessResponse<T>(data: T, message?: string) {
|
|
263
|
+
return {
|
|
264
|
+
success: true,
|
|
265
|
+
data,
|
|
266
|
+
message,
|
|
267
|
+
timestamp: new Date().toISOString()
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Serializa opciones de query para logging o debugging
|
|
273
|
+
*
|
|
274
|
+
* @param options - Opciones de query de Baserow
|
|
275
|
+
* @returns Opciones limpias para logging
|
|
276
|
+
*/
|
|
277
|
+
export function serializeQueryOptions(options: QueryOptions): Record<string, any> {
|
|
278
|
+
const cleaned: Record<string, any> = {}
|
|
279
|
+
|
|
280
|
+
if (options.page !== undefined) cleaned.page = options.page
|
|
281
|
+
if (options.size !== undefined) cleaned.size = options.size
|
|
282
|
+
if (options.search) cleaned.search = options.search
|
|
283
|
+
if (options.order_by) cleaned.order_by = options.order_by
|
|
284
|
+
if (options.user_field_names !== undefined) cleaned.user_field_names = options.user_field_names
|
|
285
|
+
if (options.filters) cleaned.filters = options.filters
|
|
286
|
+
|
|
287
|
+
return cleaned
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Utilidades internas
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Extrae número de página de URL de paginación
|
|
294
|
+
*/
|
|
295
|
+
function extractPageFromUrl(url: string): number {
|
|
296
|
+
const match = url.match(/[?&]page=(\d+)/)
|
|
297
|
+
return match ? parseInt(match[1], 10) : 1
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Convierte URL absoluta a relativa
|
|
302
|
+
*/
|
|
303
|
+
function makeRelativeUrl(absoluteUrl: string, baseUrl: string): string {
|
|
304
|
+
if (!baseUrl || !absoluteUrl.startsWith('http')) {
|
|
305
|
+
return absoluteUrl
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
try {
|
|
309
|
+
const url = new URL(absoluteUrl)
|
|
310
|
+
return url.pathname + url.search
|
|
311
|
+
} catch {
|
|
312
|
+
return absoluteUrl
|
|
313
|
+
}
|
|
314
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @gzl10/baserow - Cliente TypeScript avanzado para Baserow API v1.35+ (2025)
|
|
3
|
+
*
|
|
4
|
+
* Cliente moderno con arquitectura de 3 clientes especializados, PrismaBaserowMapper
|
|
5
|
+
* para sintaxis familiar, y cobertura completa de 21/22 tipos de campos.
|
|
6
|
+
*
|
|
7
|
+
* **Características principales:**
|
|
8
|
+
* - 🎯 **Arquitectura de 3 Clientes**: Token, Admin Global y Admin Workspace
|
|
9
|
+
* - 🗺️ **PrismaBaserowMapper**: Sintaxis familiar estilo Prisma con 35+ tests
|
|
10
|
+
* - 📋 **21/22 Tipos de Campos**: Cobertura prácticamente completa
|
|
11
|
+
* - 🚀 **HTTP Optimizado**: 36% menos código con axios-retry + axios-rate-limit
|
|
12
|
+
* - ⚡ **Operaciones Bulk**: Procesamiento optimizado con retry logic
|
|
13
|
+
* - 🧪 **Testing Robusto**: 35+ tests de integración + tests del mapper
|
|
14
|
+
*
|
|
15
|
+
* ---
|
|
16
|
+
*
|
|
17
|
+
* ## 🤖 Guía para IA: ¿Qué Cliente Usar?
|
|
18
|
+
*
|
|
19
|
+
* ### 1️⃣ ClientWithToken (Database Token)
|
|
20
|
+
* **✅ Usar cuando:**
|
|
21
|
+
* - Solo necesitas **leer/escribir datos** (CRUD de filas)
|
|
22
|
+
* - Aplicación cliente (frontend, mobile, edge functions)
|
|
23
|
+
* - Scope limitado a tablas específicas predefinidas
|
|
24
|
+
* - No necesitas crear/modificar estructura (tablas, campos, workspaces)
|
|
25
|
+
* - Máxima seguridad (token con permisos granulares)
|
|
26
|
+
*
|
|
27
|
+
* **❌ NO usar cuando:**
|
|
28
|
+
* - Necesitas crear/modificar tablas o campos
|
|
29
|
+
* - Necesitas gestionar workspaces
|
|
30
|
+
* - Necesitas operaciones administrativas
|
|
31
|
+
*
|
|
32
|
+
* **Performance:** ⚡⚡⚡ (Sin overhead de JWT, conexión directa)
|
|
33
|
+
*
|
|
34
|
+
* ### 2️⃣ ClientWithCreds (JWT Global - Multi-Workspace)
|
|
35
|
+
* **✅ Usar cuando:**
|
|
36
|
+
* - Administración de **múltiples workspaces**
|
|
37
|
+
* - Scripts de migración completa entre entornos
|
|
38
|
+
* - Panel de control administrativo multi-tenant
|
|
39
|
+
* - Necesitas API jerárquica: `admin.workspace('X').database('Y').create()`
|
|
40
|
+
* - Operaciones de setup inicial o teardown completo
|
|
41
|
+
*
|
|
42
|
+
* **❌ NO usar cuando:**
|
|
43
|
+
* - Solo trabajas con un workspace específico (usa ClientWithCredsWs)
|
|
44
|
+
* - Solo necesitas datos sin admin (usa ClientWithToken)
|
|
45
|
+
* - Aplicación cliente con scope limitado
|
|
46
|
+
*
|
|
47
|
+
* **Performance:** ⚡⚡ (Overhead de JWT + validación multi-workspace)
|
|
48
|
+
*
|
|
49
|
+
* ### 3️⃣ ClientWithCredsWs (JWT Workspace - Single Workspace)
|
|
50
|
+
* **✅ Usar cuando:**
|
|
51
|
+
* - Administración de **un workspace específico**
|
|
52
|
+
* - API simplificada sin prefijo workspace en cada llamada
|
|
53
|
+
* - Aplicación empresarial con scope de empresa/proyecto único
|
|
54
|
+
* - Necesitas admin pero scope está bien definido
|
|
55
|
+
* - Mejor DX que ClientWithCreds para casos single-workspace
|
|
56
|
+
*
|
|
57
|
+
* **❌ NO usar cuando:**
|
|
58
|
+
* - Necesitas acceso a múltiples workspaces
|
|
59
|
+
* - Solo necesitas datos sin admin (usa ClientWithToken)
|
|
60
|
+
*
|
|
61
|
+
* **Performance:** ⚡⚡ (Overhead de JWT pero scope optimizado)
|
|
62
|
+
*
|
|
63
|
+
* ---
|
|
64
|
+
*
|
|
65
|
+
* ## 📊 Tabla Comparativa de Capacidades
|
|
66
|
+
*
|
|
67
|
+
* | Capability | Token | CredsGlobal | CredsWs |
|
|
68
|
+
* |-------------------------|-------|-------------|---------|
|
|
69
|
+
* | Read/Write Data (CRUD) | ✅ | ✅ | ✅ |
|
|
70
|
+
* | Create/Modify Tables | ❌ | ✅ | ✅ |
|
|
71
|
+
* | Create/Modify Fields | ❌ | ✅ | ✅ |
|
|
72
|
+
* | Manage Workspaces | ❌ | ✅ | ❌ |
|
|
73
|
+
* | Multi-Workspace Access | ❌ | ✅ | ❌ |
|
|
74
|
+
* | Auto-Refresh JWT | ❌ | ✅ | ✅ |
|
|
75
|
+
* | Needs User Credentials | ❌ | ✅ | ✅ |
|
|
76
|
+
* | Hierarchical API | ❌ | ✅ | ✅ |
|
|
77
|
+
* | Granular Permissions | ✅ | ❌ | ❌ |
|
|
78
|
+
* | Performance | ⚡⚡⚡ | ⚡⚡ | ⚡⚡ |
|
|
79
|
+
* | Security (Least Priv) | ⚡⚡⚡ | ⚡ | ⚡⚡ |
|
|
80
|
+
*
|
|
81
|
+
* ---
|
|
82
|
+
*
|
|
83
|
+
* ## 🎯 Árbol de Decisión Rápido
|
|
84
|
+
*
|
|
85
|
+
* ```
|
|
86
|
+
* ¿Necesitas operaciones admin (crear tablas/campos/workspaces)?
|
|
87
|
+
* │
|
|
88
|
+
* ├─ NO → ClientWithToken (Database Token)
|
|
89
|
+
* │ └─ Máxima seguridad, solo datos
|
|
90
|
+
* │
|
|
91
|
+
* └─ SÍ → ¿Múltiples workspaces?
|
|
92
|
+
* │
|
|
93
|
+
* ├─ SÍ → ClientWithCreds (JWT Global)
|
|
94
|
+
* │ └─ API: admin.workspace('X').database('Y')
|
|
95
|
+
* │
|
|
96
|
+
* └─ NO → ClientWithCredsWs (JWT Workspace)
|
|
97
|
+
* └─ API: admin.database('Y') (sin prefijo workspace)
|
|
98
|
+
* ```
|
|
99
|
+
*
|
|
100
|
+
* ---
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* import { BaserowClient, PrismaBaserowMapper } from '@gzl10/baserow'
|
|
105
|
+
* // Importar tipos de configuración con aliases descriptivos
|
|
106
|
+
* import type { TokenConfig, CredentialsConfig, CredentialsWorkspaceConfig } from '@gzl10/baserow'
|
|
107
|
+
* // Importar clases de cliente para tipado avanzado
|
|
108
|
+
* import type { ClientWithToken, ClientWithCreds, ClientWithCredsWs } from '@gzl10/baserow'
|
|
109
|
+
*
|
|
110
|
+
* // === PRISMA MAPPER - CARACTERÍSTICA PRINCIPAL ===
|
|
111
|
+
* const client = await BaserowClient.create({ url, token })
|
|
112
|
+
*
|
|
113
|
+
* // Sintaxis Prisma familiar
|
|
114
|
+
* const prismaQuery = {
|
|
115
|
+
* where: {
|
|
116
|
+
* AND: [
|
|
117
|
+
* { status: 'active' },
|
|
118
|
+
* { age: { gte: 18, lt: 65 } },
|
|
119
|
+
* { email: { contains: '@company.com' } }
|
|
120
|
+
* ]
|
|
121
|
+
* },
|
|
122
|
+
* orderBy: [{ created_at: 'desc' }, { name: 'asc' }],
|
|
123
|
+
* take: 20,
|
|
124
|
+
* skip: 40,
|
|
125
|
+
* select: { id: true, name: true, email: true }
|
|
126
|
+
* }
|
|
127
|
+
*
|
|
128
|
+
* // Transformación automática a Baserow API
|
|
129
|
+
* const baserowOptions = PrismaBaserowMapper.transformPrismaToBaserow(prismaQuery)
|
|
130
|
+
* const rows = await client.database(123).table(456).rows.list(baserowOptions)
|
|
131
|
+
*
|
|
132
|
+
* // === ARQUITECTURA DE 3 CLIENTES ===
|
|
133
|
+
*
|
|
134
|
+
* // 1. Cliente con Database Token (solo datos)
|
|
135
|
+
* const tokenConfig: TokenConfig = {
|
|
136
|
+
* url: 'https://baserow.example.com',
|
|
137
|
+
* token: process.env.BASEROW_DB_TOKEN!
|
|
138
|
+
* }
|
|
139
|
+
* const client = await BaserowClient.create(tokenConfig)
|
|
140
|
+
* const rows = await client.database(123).table(456).rows.list()
|
|
141
|
+
*
|
|
142
|
+
* // 2. Cliente Admin Global (multi-workspace)
|
|
143
|
+
* const adminConfig: CredentialsConfig = {
|
|
144
|
+
* url: 'https://baserow.example.com',
|
|
145
|
+
* credentials: { email: 'admin@example.com', password: 'password' }
|
|
146
|
+
* }
|
|
147
|
+
* const admin = await BaserowClient.create(adminConfig)
|
|
148
|
+
* const workspaces = await admin.workspaces.list()
|
|
149
|
+
* const database = await admin.workspace('Company').databases.create('CRM')
|
|
150
|
+
*
|
|
151
|
+
* // 3. Cliente Admin Workspace (scope específico)
|
|
152
|
+
* const adminWSConfig: CredentialsWorkspaceConfig = {
|
|
153
|
+
* url: 'https://baserow.example.com',
|
|
154
|
+
* credentials: { email: 'admin@example.com', password: 'password' },
|
|
155
|
+
* workspace: 'Company'
|
|
156
|
+
* }
|
|
157
|
+
* const adminWS = await BaserowClient.create(adminWSConfig)
|
|
158
|
+
* const databases = await adminWS.databases.list()
|
|
159
|
+
* const table = await adminWS.database('CRM').tables.create({ name: 'Customers' })
|
|
160
|
+
*
|
|
161
|
+
* // === COBERTURA COMPLETA DE CAMPOS ===
|
|
162
|
+
* // 21/22 tipos de campos soportados incluyendo campos avanzados
|
|
163
|
+
* const textField = await table.field.createText('full_name')
|
|
164
|
+
* const fileField = await table.field.createFile('documents') // ¡Nuevo!
|
|
165
|
+
* const autoField = await table.field.createAutonumber('ticket_id') // ¡Nuevo!
|
|
166
|
+
* const countField = await table.field.createCount('items_count', targetTableId) // ¡Nuevo!
|
|
167
|
+
*
|
|
168
|
+
* // === CONFIGURACIONES DE PERFORMANCE ===
|
|
169
|
+
* import { PERFORMANCE_PRESETS } from '@gzl10/baserow'
|
|
170
|
+
*
|
|
171
|
+
* const prodClient = await BaserowClient.create({
|
|
172
|
+
* url: 'https://baserow.example.com',
|
|
173
|
+
* token: process.env.TOKEN,
|
|
174
|
+
* performance: PERFORMANCE_PRESETS.production // Balanceado: 30s timeout, 3 retries, 10 req/s
|
|
175
|
+
* })
|
|
176
|
+
*
|
|
177
|
+
* // === UTILIDADES EXPRESS OPCIONALES ===
|
|
178
|
+
* import express from 'express'
|
|
179
|
+
* import { express as baserowExpress } from '@gzl10/baserow'
|
|
180
|
+
*
|
|
181
|
+
* const app = express()
|
|
182
|
+
* app.use('/api', baserowExpress.baserowContext(client))
|
|
183
|
+
* app.use(baserowExpress.errorHandler())
|
|
184
|
+
* ```
|
|
185
|
+
*
|
|
186
|
+
* @version 1.1.0+
|
|
187
|
+
* @since 2025
|
|
188
|
+
*/
|
|
189
|
+
|
|
190
|
+
// Cliente principal unificado
|
|
191
|
+
export { BaserowClient } from './BaserowClient'
|
|
192
|
+
|
|
193
|
+
// Clases de cliente especializadas (para tipado avanzado)
|
|
194
|
+
export { ClientWithToken } from './ClientWithToken'
|
|
195
|
+
export { ClientWithCreds } from './ClientWithCreds'
|
|
196
|
+
export { ClientWithCredsWs } from './ClientWithCredsWs'
|
|
197
|
+
|
|
198
|
+
// Tipos esenciales para el usuario
|
|
199
|
+
export type {
|
|
200
|
+
BaserowTokenConfig,
|
|
201
|
+
BaserowCredentialsConfig,
|
|
202
|
+
BaserowCredentialsWorkspaceConfig,
|
|
203
|
+
BaserowUnifiedConfig,
|
|
204
|
+
BaserowCredentials,
|
|
205
|
+
BaserowPerformanceOptions,
|
|
206
|
+
Workspace,
|
|
207
|
+
Database,
|
|
208
|
+
Table,
|
|
209
|
+
Field,
|
|
210
|
+
FieldType,
|
|
211
|
+
Row,
|
|
212
|
+
QueryOptions,
|
|
213
|
+
PrismaLikeQueryOptions,
|
|
214
|
+
FieldOperators,
|
|
215
|
+
WhereClause,
|
|
216
|
+
OrderByClause,
|
|
217
|
+
SelectClause,
|
|
218
|
+
DatabaseToken,
|
|
219
|
+
DatabaseSchema,
|
|
220
|
+
TableSchema,
|
|
221
|
+
FieldSchema,
|
|
222
|
+
RelationshipSchema,
|
|
223
|
+
LoadSchemaOptions,
|
|
224
|
+
LoadSchemaResult,
|
|
225
|
+
SchemaControl
|
|
226
|
+
} from './types'
|
|
227
|
+
|
|
228
|
+
// Aliases descriptivos de configuración (DX-friendly)
|
|
229
|
+
export type { TokenConfig, CredentialsConfig, CredentialsWorkspaceConfig } from './types'
|
|
230
|
+
|
|
231
|
+
// Contextos para tipado avanzado (solo tipos, no instanciables directamente)
|
|
232
|
+
export type { DatabaseContext } from './contexts/DatabaseContext'
|
|
233
|
+
export type { TableContext } from './contexts/TableContext'
|
|
234
|
+
export type { WorkspaceContext } from './contexts/WorkspaceContext'
|
|
235
|
+
|
|
236
|
+
// Errores que puede capturar el usuario
|
|
237
|
+
export { BaserowError, BaserowValidationError, BaserowNotFoundError, BaserowRateLimitError } from './types'
|
|
238
|
+
|
|
239
|
+
// Configuraciones de performance predefinidas
|
|
240
|
+
export { PERFORMANCE_PRESETS, getPerformancePreset } from './presets/performance'
|
|
241
|
+
export type { PerformancePresetKey } from './presets/performance'
|
|
242
|
+
|
|
243
|
+
// Utilidades Prisma Mapper
|
|
244
|
+
export { PrismaBaserowMapper } from './utils/prisma-mapper'
|
|
245
|
+
|
|
246
|
+
// Utilidades Express opcionales (sin dependencias)
|
|
247
|
+
export * as express from './express/index'
|