@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,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manejo de errores Express para @gzl10/baserow
|
|
3
|
+
*
|
|
4
|
+
* Convertidores y middlewares para transformar BaserowError en respuestas HTTP apropiadas.
|
|
5
|
+
* Proporciona mapeo automático de errores de Baserow a códigos de estado HTTP estándar.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import express from 'express'
|
|
10
|
+
* import { BaserowClient, express as baserowExpress } from '@gzl10/baserow'
|
|
11
|
+
*
|
|
12
|
+
* const app = express()
|
|
13
|
+
*
|
|
14
|
+
* // Setup middlewares
|
|
15
|
+
* app.use('/api', baserowExpress.baserowAuth(config))
|
|
16
|
+
*
|
|
17
|
+
* // Routes
|
|
18
|
+
* app.get('/api/table/:id', async (req, res, next) => {
|
|
19
|
+
* try {
|
|
20
|
+
* const table = await req.baserow!.database(123).table(parseInt(req.params.id)).get()
|
|
21
|
+
* res.json(baserowExpress.serializeTable(table))
|
|
22
|
+
* } catch (error) {
|
|
23
|
+
* next(error) // Será manejado por errorHandler()
|
|
24
|
+
* }
|
|
25
|
+
* })
|
|
26
|
+
*
|
|
27
|
+
* // Error handler global (debe ir al final)
|
|
28
|
+
* app.use(baserowExpress.errorHandler())
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @since 1.0.0
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import { BaserowError, BaserowNotFoundError, BaserowValidationError, BaserowRateLimitError } from '../types'
|
|
35
|
+
import type { ExpressRequest, ExpressResponse, ExpressNextFunction } from './middleware'
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Formato estándar para respuestas de error
|
|
39
|
+
*/
|
|
40
|
+
export interface ErrorResponse {
|
|
41
|
+
error: string
|
|
42
|
+
code: string
|
|
43
|
+
status: number
|
|
44
|
+
details?: any
|
|
45
|
+
timestamp?: string
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Convierte BaserowError a código de estado HTTP apropiado
|
|
50
|
+
*
|
|
51
|
+
* Mapea los tipos de error específicos de Baserow a códigos HTTP estándar:
|
|
52
|
+
* - BaserowNotFoundError → 404
|
|
53
|
+
* - BaserowValidationError → 400
|
|
54
|
+
* - BaserowRateLimitError → 429
|
|
55
|
+
* - BaserowError (generic auth) → 401
|
|
56
|
+
* - Otros BaserowError → 500
|
|
57
|
+
*
|
|
58
|
+
* @param error - Error de Baserow a convertir
|
|
59
|
+
* @returns Código de estado HTTP apropiado
|
|
60
|
+
*/
|
|
61
|
+
export function getHttpStatusCode(error: BaserowError): number {
|
|
62
|
+
if (error instanceof BaserowNotFoundError) {
|
|
63
|
+
return 404
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (error instanceof BaserowValidationError) {
|
|
67
|
+
return 400
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (error instanceof BaserowRateLimitError) {
|
|
71
|
+
return 429
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Detectar errores de auth por status code o mensaje
|
|
75
|
+
if (error.status === 401 || error.message?.toLowerCase().includes('auth')) {
|
|
76
|
+
return 401
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Usar status del error si está disponible
|
|
80
|
+
if (error.status) {
|
|
81
|
+
return error.status
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Default para errores desconocidos
|
|
85
|
+
return 500
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Convierte BaserowError a formato de respuesta Express estándar
|
|
90
|
+
*
|
|
91
|
+
* Crea un objeto de error normalizado que incluye toda la información relevante
|
|
92
|
+
* sin exponer detalles internos sensibles.
|
|
93
|
+
*
|
|
94
|
+
* @param error - Error de Baserow a serializar
|
|
95
|
+
* @returns Objeto de error serializado para respuesta HTTP
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```typescript
|
|
99
|
+
* try {
|
|
100
|
+
* await someBaserowOperation()
|
|
101
|
+
* } catch (error) {
|
|
102
|
+
* const response = serializeError(error as BaserowError)
|
|
103
|
+
* res.status(response.status).json(response)
|
|
104
|
+
* }
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export function serializeError(error: BaserowError): ErrorResponse {
|
|
108
|
+
const status = getHttpStatusCode(error)
|
|
109
|
+
|
|
110
|
+
const response: ErrorResponse = {
|
|
111
|
+
error: error.message || 'Unknown Baserow error',
|
|
112
|
+
code: error.constructor.name.replace('Error', '').toUpperCase(),
|
|
113
|
+
status,
|
|
114
|
+
timestamp: new Date().toISOString()
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Agregar detalles específicos para ciertos tipos de error
|
|
118
|
+
if (error instanceof BaserowValidationError) {
|
|
119
|
+
response.details = {
|
|
120
|
+
fieldErrors: error.fieldErrors
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (error instanceof BaserowRateLimitError) {
|
|
125
|
+
response.details = {
|
|
126
|
+
retryAfter: error.retryAfter
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (error instanceof BaserowNotFoundError) {
|
|
131
|
+
response.details = {
|
|
132
|
+
message: error.message
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return response
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Convierte Error genérico a formato de respuesta Express
|
|
141
|
+
*
|
|
142
|
+
* Maneja errores que no son específicos de Baserow (por ejemplo, errores de red,
|
|
143
|
+
* errores de validación de entrada, etc.).
|
|
144
|
+
*
|
|
145
|
+
* @param error - Error genérico a serializar
|
|
146
|
+
* @returns Objeto de error serializado
|
|
147
|
+
*/
|
|
148
|
+
export function serializeGenericError(error: Error): ErrorResponse {
|
|
149
|
+
return {
|
|
150
|
+
error: error.message || 'Internal server error',
|
|
151
|
+
code: 'INTERNAL_ERROR',
|
|
152
|
+
status: 500,
|
|
153
|
+
timestamp: new Date().toISOString()
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Middleware Express para manejo automático de errores Baserow
|
|
159
|
+
*
|
|
160
|
+
* Convierte automáticamente errores de Baserow en respuestas HTTP apropiadas.
|
|
161
|
+
* Debe ser usado como el último middleware de la aplicación.
|
|
162
|
+
*
|
|
163
|
+
* @param options - Opciones de configuración del error handler
|
|
164
|
+
* @returns Middleware Express para manejo de errores
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```typescript
|
|
168
|
+
* import { express as baserowExpress } from '@gzl10/baserow'
|
|
169
|
+
*
|
|
170
|
+
* // Al final de la configuración de middlewares
|
|
171
|
+
* app.use(baserowExpress.errorHandler({
|
|
172
|
+
* includeStack: process.env.NODE_ENV === 'development',
|
|
173
|
+
* logger: console
|
|
174
|
+
* }))
|
|
175
|
+
*
|
|
176
|
+
* // Ejemplo de error personalizado en ruta
|
|
177
|
+
* app.get('/api/custom', async (req, res, next) => {
|
|
178
|
+
* try {
|
|
179
|
+
* // Operación que puede fallar
|
|
180
|
+
* const data = await req.baserow!.database(999).table(123).rows.list()
|
|
181
|
+
* res.json(data)
|
|
182
|
+
* } catch (error) {
|
|
183
|
+
* next(error) // Automáticamente convierte BaserowError a HTTP response
|
|
184
|
+
* }
|
|
185
|
+
* })
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
export function errorHandler(
|
|
189
|
+
options: {
|
|
190
|
+
includeStack?: boolean
|
|
191
|
+
logger?: { error: (message: any) => void }
|
|
192
|
+
} = {}
|
|
193
|
+
) {
|
|
194
|
+
return (error: any, req: ExpressRequest, res: ExpressResponse, next: ExpressNextFunction) => {
|
|
195
|
+
// Si ya se envió la respuesta, pasar al error handler por defecto
|
|
196
|
+
if ((res as any).headersSent) {
|
|
197
|
+
return next(error)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
let response: ErrorResponse
|
|
201
|
+
|
|
202
|
+
if (error instanceof BaserowError) {
|
|
203
|
+
response = serializeError(error)
|
|
204
|
+
} else if (error instanceof Error) {
|
|
205
|
+
response = serializeGenericError(error)
|
|
206
|
+
} else {
|
|
207
|
+
// Error desconocido
|
|
208
|
+
response = {
|
|
209
|
+
error: 'Unknown error occurred',
|
|
210
|
+
code: 'UNKNOWN_ERROR',
|
|
211
|
+
status: 500,
|
|
212
|
+
timestamp: new Date().toISOString()
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Agregar stack trace en desarrollo
|
|
217
|
+
if (options.includeStack && error instanceof Error) {
|
|
218
|
+
;(response as any).stack = error.stack
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Log del error
|
|
222
|
+
if (options.logger) {
|
|
223
|
+
options.logger.error(
|
|
224
|
+
'Baserow API Error: ' +
|
|
225
|
+
JSON.stringify({
|
|
226
|
+
error: response,
|
|
227
|
+
url: (req as any).url,
|
|
228
|
+
method: (req as any).method,
|
|
229
|
+
stack: error instanceof Error ? error.stack : undefined
|
|
230
|
+
})
|
|
231
|
+
)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
res.status(response.status).json(response)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Handler de errores simplificado para casos básicos
|
|
240
|
+
*
|
|
241
|
+
* Versión simplificada del error handler que solo maneja errores de Baserow
|
|
242
|
+
* sin opciones de configuración adicionales.
|
|
243
|
+
*
|
|
244
|
+
* @returns Middleware Express básico para errores
|
|
245
|
+
*/
|
|
246
|
+
export function simpleErrorHandler() {
|
|
247
|
+
return (error: any, _req: ExpressRequest, res: ExpressResponse, next: ExpressNextFunction) => {
|
|
248
|
+
if ((res as any).headersSent) {
|
|
249
|
+
return next(error)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (error instanceof BaserowError) {
|
|
253
|
+
const response = serializeError(error)
|
|
254
|
+
return res.status(response.status).json(response)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Para errores no-Baserow, pasar al siguiente handler
|
|
258
|
+
next(error)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilidades Express para @gzl10/baserow
|
|
3
|
+
*
|
|
4
|
+
* Colección de middlewares, error handlers y serializadores opcionales
|
|
5
|
+
* para facilitar la integración con Express sin crear dependencias directas.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { BaserowClient, express } from '@gzl10/baserow'
|
|
10
|
+
*
|
|
11
|
+
* const client = new BaserowClient({ url, token })
|
|
12
|
+
* const app = express()
|
|
13
|
+
*
|
|
14
|
+
* // Setup middlewares
|
|
15
|
+
* app.use('/api', express.baserowContext(client))
|
|
16
|
+
* app.use('/api', express.requireAuth())
|
|
17
|
+
*
|
|
18
|
+
* // Routes
|
|
19
|
+
* app.get('/api/tables/:tableId/rows', async (req, res, next) => {
|
|
20
|
+
* try {
|
|
21
|
+
* const rows = await req.baserow!.database(123).table(456).rows.list()
|
|
22
|
+
* res.json(express.serializePaginated(rows))
|
|
23
|
+
* } catch (error) {
|
|
24
|
+
* next(error)
|
|
25
|
+
* }
|
|
26
|
+
* })
|
|
27
|
+
*
|
|
28
|
+
* // Error handling
|
|
29
|
+
* app.use(express.errorHandler())
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @since 1.0.0
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
// Middlewares
|
|
36
|
+
export {
|
|
37
|
+
baserowContext,
|
|
38
|
+
baserowAuth,
|
|
39
|
+
requireAuth,
|
|
40
|
+
baserowCleanup,
|
|
41
|
+
type ExpressRequest,
|
|
42
|
+
type ExpressResponse,
|
|
43
|
+
type ExpressNextFunction,
|
|
44
|
+
type ExpressMiddleware
|
|
45
|
+
} from './middleware'
|
|
46
|
+
|
|
47
|
+
// Error handling
|
|
48
|
+
export {
|
|
49
|
+
errorHandler,
|
|
50
|
+
simpleErrorHandler,
|
|
51
|
+
serializeError,
|
|
52
|
+
serializeGenericError,
|
|
53
|
+
getHttpStatusCode,
|
|
54
|
+
type ErrorResponse
|
|
55
|
+
} from './errors'
|
|
56
|
+
|
|
57
|
+
// Serializadores
|
|
58
|
+
export {
|
|
59
|
+
serializePaginated,
|
|
60
|
+
serializeRowsWithMeta,
|
|
61
|
+
serializeTable,
|
|
62
|
+
serializeDatabase,
|
|
63
|
+
serializeWorkspace,
|
|
64
|
+
cleanField,
|
|
65
|
+
createSuccessResponse,
|
|
66
|
+
serializeQueryOptions,
|
|
67
|
+
type PaginatedResponse,
|
|
68
|
+
type RowsResponse
|
|
69
|
+
} from './serializers'
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Middlewares Express opcionales para @gzl10/baserow
|
|
3
|
+
*
|
|
4
|
+
* Utilidades que facilitan la integración con Express sin crear dependencias directas.
|
|
5
|
+
* Los tipos Express son inferidos dinámicamente para evitar dependency en @types/express.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import express from 'express'
|
|
10
|
+
* import { BaserowClient, express as baserowExpress } from '@gzl10/baserow'
|
|
11
|
+
*
|
|
12
|
+
* const app = express()
|
|
13
|
+
* const client = await BaserowClient.create({ url, token })
|
|
14
|
+
*
|
|
15
|
+
* // Attach client to request
|
|
16
|
+
* app.use('/api', baserowExpress.baserowContext(client))
|
|
17
|
+
*
|
|
18
|
+
* // Auto-create client per request with auth from headers
|
|
19
|
+
* app.use('/api', baserowExpress.baserowAuth({
|
|
20
|
+
* url: process.env.BASEROW_URL!,
|
|
21
|
+
* token: process.env.BASEROW_TOKEN!
|
|
22
|
+
* }))
|
|
23
|
+
*
|
|
24
|
+
* // Routes now have access to req.baserow
|
|
25
|
+
* app.get('/api/rows', async (req, res) => {
|
|
26
|
+
* const rows = await req.baserow!.database(123).table(456).rows.list()
|
|
27
|
+
* res.json(rows)
|
|
28
|
+
* })
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @since 1.0.0
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import type { BaserowConfig } from '../types'
|
|
35
|
+
import { ClientWithToken } from '../ClientWithToken'
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Tipos Express mínimos sin dependencias
|
|
39
|
+
*/
|
|
40
|
+
export interface ExpressRequest {
|
|
41
|
+
[key: string]: any
|
|
42
|
+
headers: { [key: string]: string | string[] | undefined }
|
|
43
|
+
baserow?: ClientWithToken
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ExpressResponse {
|
|
47
|
+
status(code: number): ExpressResponse
|
|
48
|
+
json(body: any): ExpressResponse
|
|
49
|
+
send(body?: any): ExpressResponse
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface ExpressNextFunction {
|
|
53
|
+
(error?: any): void
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type ExpressMiddleware = (
|
|
57
|
+
req: ExpressRequest,
|
|
58
|
+
res: ExpressResponse,
|
|
59
|
+
next: ExpressNextFunction
|
|
60
|
+
) => void | Promise<void>
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Middleware para attachar cliente Baserow al request
|
|
64
|
+
*
|
|
65
|
+
* Agrega el cliente a `req.baserow` para uso en routes subsecuentes.
|
|
66
|
+
* El cliente debe ser creado externamente y reutilizado.
|
|
67
|
+
*
|
|
68
|
+
* @param client - Cliente Baserow configurado
|
|
69
|
+
* @returns Middleware Express
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* import { BaserowClient, express as baserowExpress } from '@gzl10/baserow'
|
|
74
|
+
*
|
|
75
|
+
* const client = await BaserowClient.create({ url, token })
|
|
76
|
+
* app.use('/api', baserowExpress.baserowContext(client))
|
|
77
|
+
*
|
|
78
|
+
* // En las rutas
|
|
79
|
+
* app.get('/api/tables', async (req, res) => {
|
|
80
|
+
* const tables = await req.baserow!.database(123).tables.findMany()
|
|
81
|
+
* res.json(tables)
|
|
82
|
+
* })
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export function baserowContext(client: ClientWithToken): ExpressMiddleware {
|
|
86
|
+
return (req: ExpressRequest, _res: ExpressResponse, next: ExpressNextFunction) => {
|
|
87
|
+
req.baserow = client
|
|
88
|
+
next()
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Middleware para auto-crear cliente Baserow por request
|
|
94
|
+
*
|
|
95
|
+
* Crea un nuevo cliente para cada request basado en la configuración.
|
|
96
|
+
* Útil cuando cada request puede tener diferentes tokens o configuraciones.
|
|
97
|
+
*
|
|
98
|
+
* @param config - Configuración base de Baserow
|
|
99
|
+
* @returns Middleware Express
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* import { express as baserowExpress } from '@gzl10/baserow'
|
|
104
|
+
*
|
|
105
|
+
* app.use('/api', baserowExpress.baserowAuth({
|
|
106
|
+
* url: process.env.BASEROW_URL!,
|
|
107
|
+
* token: process.env.BASEROW_TOKEN! // Puede ser sobrescrito por headers
|
|
108
|
+
* }))
|
|
109
|
+
*
|
|
110
|
+
* // Cliente auto-creado por request disponible en req.baserow
|
|
111
|
+
* app.get('/api/data', async (req, res) => {
|
|
112
|
+
* const rows = await req.baserow!.database(123).table(456).rows.list()
|
|
113
|
+
* res.json(rows)
|
|
114
|
+
* })
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
export function baserowAuth(config: BaserowConfig): ExpressMiddleware {
|
|
118
|
+
return (req: ExpressRequest, _res: ExpressResponse, next: ExpressNextFunction) => {
|
|
119
|
+
try {
|
|
120
|
+
// Permitir override del token vía headers
|
|
121
|
+
const authHeader = req.headers.authorization as string
|
|
122
|
+
const token = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : config.token
|
|
123
|
+
|
|
124
|
+
const clientConfig: BaserowConfig = {
|
|
125
|
+
...config,
|
|
126
|
+
token
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
req.baserow = new ClientWithToken(clientConfig)
|
|
130
|
+
next()
|
|
131
|
+
} catch (error) {
|
|
132
|
+
next(error)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Middleware para requerir autenticación Baserow
|
|
139
|
+
*
|
|
140
|
+
* Valida que existe un cliente Baserow válido en el request.
|
|
141
|
+
* Debe usarse después de `baserowContext` o `baserowAuth`.
|
|
142
|
+
*
|
|
143
|
+
* @returns Middleware Express
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* import { express as baserowExpress } from '@gzl10/baserow'
|
|
148
|
+
*
|
|
149
|
+
* app.use('/api', baserowExpress.baserowAuth(config))
|
|
150
|
+
* app.use('/api', baserowExpress.requireAuth())
|
|
151
|
+
*
|
|
152
|
+
* app.get('/api/protected', async (req, res) => {
|
|
153
|
+
* // req.baserow está garantizado aquí
|
|
154
|
+
* const data = await req.baserow!.database(123).table(456).rows.list()
|
|
155
|
+
* res.json(data)
|
|
156
|
+
* })
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
export function requireAuth(): ExpressMiddleware {
|
|
160
|
+
return async (req: ExpressRequest, res: ExpressResponse, next: ExpressNextFunction) => {
|
|
161
|
+
try {
|
|
162
|
+
if (!req.baserow) {
|
|
163
|
+
res.status(401).json({
|
|
164
|
+
error: 'Baserow client not found. Use baserowAuth() middleware first.',
|
|
165
|
+
code: 'BASEROW_CLIENT_MISSING'
|
|
166
|
+
})
|
|
167
|
+
return
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Opcional: verificar conectividad
|
|
171
|
+
const isConnected = await req.baserow.health()
|
|
172
|
+
if (!isConnected) {
|
|
173
|
+
res.status(503).json({
|
|
174
|
+
error: 'Baserow server not accessible',
|
|
175
|
+
code: 'BASEROW_UNAVAILABLE'
|
|
176
|
+
})
|
|
177
|
+
return
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
next()
|
|
181
|
+
} catch (error) {
|
|
182
|
+
next(error)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Middleware para cleanup automático de recursos Baserow
|
|
189
|
+
*
|
|
190
|
+
* Limpia el cliente Baserow al final del request para evitar memory leaks.
|
|
191
|
+
* Especialmente útil cuando se usan clientes per-request.
|
|
192
|
+
*
|
|
193
|
+
* @returns Middleware Express
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```typescript
|
|
197
|
+
* import { express as baserowExpress } from '@gzl10/baserow'
|
|
198
|
+
*
|
|
199
|
+
* app.use('/api', baserowExpress.baserowAuth(config))
|
|
200
|
+
* // ... otras rutas ...
|
|
201
|
+
* app.use('/api', baserowExpress.baserowCleanup()) // Debe ir al final
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
export function baserowCleanup(): ExpressMiddleware {
|
|
205
|
+
return (req: ExpressRequest, _res: ExpressResponse, next: ExpressNextFunction) => {
|
|
206
|
+
// Cleanup después de que la respuesta se envíe
|
|
207
|
+
if (req.baserow) {
|
|
208
|
+
const cleanup = () => {
|
|
209
|
+
try {
|
|
210
|
+
req.baserow?.destroy()
|
|
211
|
+
delete req.baserow
|
|
212
|
+
} catch (error) {
|
|
213
|
+
// Log error pero no fallar el request
|
|
214
|
+
// eslint-disable-next-line no-console
|
|
215
|
+
console.warn('Error cleaning up Baserow client:', error)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Cleanup en el próximo tick después de enviar response
|
|
220
|
+
process.nextTick(cleanup)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
next()
|
|
224
|
+
}
|
|
225
|
+
}
|