sovrium 0.1.0 → 0.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/README.md +65 -185
- package/package.json +6 -6
- package/src/application/use-cases/server/static-content-generators.ts +18 -2
- package/src/domain/models/api/activity.ts +87 -0
- package/src/domain/models/api/comments.ts +131 -0
- package/src/domain/models/api/index.ts +9 -0
- package/src/domain/models/api/params.ts +83 -0
- package/src/infrastructure/server/route-setup/openapi-routes/activity-routes.ts +72 -0
- package/src/infrastructure/server/route-setup/openapi-routes/analytics-routes.ts +176 -0
- package/src/infrastructure/server/route-setup/openapi-routes/batch-routes.ts +215 -0
- package/src/infrastructure/server/route-setup/openapi-routes/health-routes.ts +38 -0
- package/src/infrastructure/server/route-setup/openapi-routes/record-routes.ts +444 -0
- package/src/infrastructure/server/route-setup/openapi-routes/table-routes.ts +100 -0
- package/src/infrastructure/server/route-setup/openapi-routes/view-routes.ts +104 -0
- package/src/infrastructure/server/route-setup/openapi-schema.ts +40 -40
- package/src/presentation/styling/parse-style.ts +17 -9
- package/schemas/0.0.1/app.openapi.json +0 -70
- package/schemas/0.0.1/app.schema.json +0 -7961
- package/schemas/0.0.2/app.openapi.json +0 -70
- package/schemas/0.0.2/app.schema.json +0 -7456
- package/schemas/0.1.0/app.openapi.json +0 -80
- package/schemas/0.1.0/app.schema.json +0 -8829
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 ESSENTIAL SERVICES
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Business Source License 1.1
|
|
5
|
+
* found in the LICENSE.md file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { type OpenAPIHono, createRoute } from '@hono/zod-openapi'
|
|
9
|
+
import {
|
|
10
|
+
createCommentResponseSchema,
|
|
11
|
+
getCommentResponseSchema,
|
|
12
|
+
getRecordHistoryResponseSchema,
|
|
13
|
+
listCommentsResponseSchema,
|
|
14
|
+
updateCommentResponseSchema,
|
|
15
|
+
} from '@/domain/models/api/comments'
|
|
16
|
+
import { errorResponseSchema } from '@/domain/models/api/error'
|
|
17
|
+
import {
|
|
18
|
+
commentBodySchema,
|
|
19
|
+
commentIdParamSchema,
|
|
20
|
+
listRecordsQuerySchema,
|
|
21
|
+
recordIdParamSchema,
|
|
22
|
+
tableIdParamSchema,
|
|
23
|
+
} from '@/domain/models/api/params'
|
|
24
|
+
import { createRecordRequestSchema, updateRecordRequestSchema } from '@/domain/models/api/request'
|
|
25
|
+
import {
|
|
26
|
+
createRecordResponseSchema,
|
|
27
|
+
deleteRecordResponseSchema,
|
|
28
|
+
getRecordResponseSchema,
|
|
29
|
+
listRecordsResponseSchema,
|
|
30
|
+
restoreRecordResponseSchema,
|
|
31
|
+
updateRecordResponseSchema,
|
|
32
|
+
} from '@/domain/models/api/tables'
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Register record CRUD routes for OpenAPI schema generation
|
|
36
|
+
*/
|
|
37
|
+
export function registerRecordRoutes(app: OpenAPIHono): void {
|
|
38
|
+
registerCrudRoutes(app)
|
|
39
|
+
registerCommentRoutes(app)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function registerCrudRoutes(app: OpenAPIHono): void {
|
|
43
|
+
// GET /api/tables/{tableId}/records
|
|
44
|
+
app.openapi(
|
|
45
|
+
createRoute({
|
|
46
|
+
method: 'get',
|
|
47
|
+
path: '/api/tables/{tableId}/records',
|
|
48
|
+
summary: 'List records',
|
|
49
|
+
description: 'Returns paginated records for a table with optional sorting and filtering.',
|
|
50
|
+
operationId: 'listRecords',
|
|
51
|
+
tags: ['records'],
|
|
52
|
+
request: { params: tableIdParamSchema, query: listRecordsQuerySchema },
|
|
53
|
+
responses: {
|
|
54
|
+
200: {
|
|
55
|
+
content: { 'application/json': { schema: listRecordsResponseSchema } },
|
|
56
|
+
description: 'List of records',
|
|
57
|
+
},
|
|
58
|
+
401: {
|
|
59
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
60
|
+
description: 'Unauthorized',
|
|
61
|
+
},
|
|
62
|
+
404: {
|
|
63
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
64
|
+
description: 'Table not found',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
}),
|
|
68
|
+
(c) => c.json({} as never)
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
// POST /api/tables/{tableId}/records
|
|
72
|
+
app.openapi(
|
|
73
|
+
createRoute({
|
|
74
|
+
method: 'post',
|
|
75
|
+
path: '/api/tables/{tableId}/records',
|
|
76
|
+
summary: 'Create a record',
|
|
77
|
+
description: 'Creates a new record in the table with the given field values.',
|
|
78
|
+
operationId: 'createRecord',
|
|
79
|
+
tags: ['records'],
|
|
80
|
+
request: {
|
|
81
|
+
params: tableIdParamSchema,
|
|
82
|
+
body: { content: { 'application/json': { schema: createRecordRequestSchema } } },
|
|
83
|
+
},
|
|
84
|
+
responses: {
|
|
85
|
+
201: {
|
|
86
|
+
content: { 'application/json': { schema: createRecordResponseSchema } },
|
|
87
|
+
description: 'Record created',
|
|
88
|
+
},
|
|
89
|
+
400: {
|
|
90
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
91
|
+
description: 'Validation error',
|
|
92
|
+
},
|
|
93
|
+
401: {
|
|
94
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
95
|
+
description: 'Unauthorized',
|
|
96
|
+
},
|
|
97
|
+
404: {
|
|
98
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
99
|
+
description: 'Table not found',
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
}),
|
|
103
|
+
(c) => c.json({} as never, 201)
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
// GET /api/tables/{tableId}/records/{recordId}
|
|
107
|
+
app.openapi(
|
|
108
|
+
createRoute({
|
|
109
|
+
method: 'get',
|
|
110
|
+
path: '/api/tables/{tableId}/records/{recordId}',
|
|
111
|
+
summary: 'Get a record',
|
|
112
|
+
description: 'Returns a single record by ID with all field values.',
|
|
113
|
+
operationId: 'getRecord',
|
|
114
|
+
tags: ['records'],
|
|
115
|
+
request: { params: recordIdParamSchema },
|
|
116
|
+
responses: {
|
|
117
|
+
200: {
|
|
118
|
+
content: { 'application/json': { schema: getRecordResponseSchema } },
|
|
119
|
+
description: 'Record details',
|
|
120
|
+
},
|
|
121
|
+
401: {
|
|
122
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
123
|
+
description: 'Unauthorized',
|
|
124
|
+
},
|
|
125
|
+
404: {
|
|
126
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
127
|
+
description: 'Record not found',
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
}),
|
|
131
|
+
(c) => c.json({} as never)
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
// PATCH /api/tables/{tableId}/records/{recordId}
|
|
135
|
+
app.openapi(
|
|
136
|
+
createRoute({
|
|
137
|
+
method: 'patch',
|
|
138
|
+
path: '/api/tables/{tableId}/records/{recordId}',
|
|
139
|
+
summary: 'Update a record',
|
|
140
|
+
description: 'Updates field values of an existing record.',
|
|
141
|
+
operationId: 'updateRecord',
|
|
142
|
+
tags: ['records'],
|
|
143
|
+
request: {
|
|
144
|
+
params: recordIdParamSchema,
|
|
145
|
+
body: { content: { 'application/json': { schema: updateRecordRequestSchema } } },
|
|
146
|
+
},
|
|
147
|
+
responses: {
|
|
148
|
+
200: {
|
|
149
|
+
content: { 'application/json': { schema: updateRecordResponseSchema } },
|
|
150
|
+
description: 'Record updated',
|
|
151
|
+
},
|
|
152
|
+
400: {
|
|
153
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
154
|
+
description: 'Validation error',
|
|
155
|
+
},
|
|
156
|
+
401: {
|
|
157
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
158
|
+
description: 'Unauthorized',
|
|
159
|
+
},
|
|
160
|
+
404: {
|
|
161
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
162
|
+
description: 'Record not found',
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
}),
|
|
166
|
+
(c) => c.json({} as never)
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
// DELETE /api/tables/{tableId}/records/{recordId}
|
|
170
|
+
app.openapi(
|
|
171
|
+
createRoute({
|
|
172
|
+
method: 'delete',
|
|
173
|
+
path: '/api/tables/{tableId}/records/{recordId}',
|
|
174
|
+
summary: 'Delete a record',
|
|
175
|
+
description: 'Soft-deletes a record. Use the restore endpoint to undo.',
|
|
176
|
+
operationId: 'deleteRecord',
|
|
177
|
+
tags: ['records'],
|
|
178
|
+
request: { params: recordIdParamSchema },
|
|
179
|
+
responses: {
|
|
180
|
+
200: {
|
|
181
|
+
content: { 'application/json': { schema: deleteRecordResponseSchema } },
|
|
182
|
+
description: 'Record deleted',
|
|
183
|
+
},
|
|
184
|
+
401: {
|
|
185
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
186
|
+
description: 'Unauthorized',
|
|
187
|
+
},
|
|
188
|
+
404: {
|
|
189
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
190
|
+
description: 'Record not found',
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
}),
|
|
194
|
+
(c) => c.json({} as never)
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
// POST /api/tables/{tableId}/records/{recordId}/restore
|
|
198
|
+
app.openapi(
|
|
199
|
+
createRoute({
|
|
200
|
+
method: 'post',
|
|
201
|
+
path: '/api/tables/{tableId}/records/{recordId}/restore',
|
|
202
|
+
summary: 'Restore a deleted record',
|
|
203
|
+
description: 'Restores a soft-deleted record back to active state.',
|
|
204
|
+
operationId: 'restoreRecord',
|
|
205
|
+
tags: ['records'],
|
|
206
|
+
request: { params: recordIdParamSchema },
|
|
207
|
+
responses: {
|
|
208
|
+
200: {
|
|
209
|
+
content: { 'application/json': { schema: restoreRecordResponseSchema } },
|
|
210
|
+
description: 'Record restored',
|
|
211
|
+
},
|
|
212
|
+
401: {
|
|
213
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
214
|
+
description: 'Unauthorized',
|
|
215
|
+
},
|
|
216
|
+
404: {
|
|
217
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
218
|
+
description: 'Record not found',
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
}),
|
|
222
|
+
(c) => c.json({} as never)
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
// GET /api/tables/{tableId}/trash
|
|
226
|
+
app.openapi(
|
|
227
|
+
createRoute({
|
|
228
|
+
method: 'get',
|
|
229
|
+
path: '/api/tables/{tableId}/trash',
|
|
230
|
+
summary: 'List deleted records',
|
|
231
|
+
description: 'Returns paginated list of soft-deleted records in the trash.',
|
|
232
|
+
operationId: 'listTrashRecords',
|
|
233
|
+
tags: ['records'],
|
|
234
|
+
request: { params: tableIdParamSchema, query: listRecordsQuerySchema },
|
|
235
|
+
responses: {
|
|
236
|
+
200: {
|
|
237
|
+
content: { 'application/json': { schema: listRecordsResponseSchema } },
|
|
238
|
+
description: 'List of deleted records',
|
|
239
|
+
},
|
|
240
|
+
401: {
|
|
241
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
242
|
+
description: 'Unauthorized',
|
|
243
|
+
},
|
|
244
|
+
404: {
|
|
245
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
246
|
+
description: 'Table not found',
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
}),
|
|
250
|
+
(c) => c.json({} as never)
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
// GET /api/tables/{tableId}/records/{recordId}/history
|
|
254
|
+
app.openapi(
|
|
255
|
+
createRoute({
|
|
256
|
+
method: 'get',
|
|
257
|
+
path: '/api/tables/{tableId}/records/{recordId}/history',
|
|
258
|
+
summary: 'Get record history',
|
|
259
|
+
description: 'Returns the audit trail of changes for a specific record.',
|
|
260
|
+
operationId: 'getRecordHistory',
|
|
261
|
+
tags: ['records'],
|
|
262
|
+
request: { params: recordIdParamSchema },
|
|
263
|
+
responses: {
|
|
264
|
+
200: {
|
|
265
|
+
content: { 'application/json': { schema: getRecordHistoryResponseSchema } },
|
|
266
|
+
description: 'Record history',
|
|
267
|
+
},
|
|
268
|
+
401: {
|
|
269
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
270
|
+
description: 'Unauthorized',
|
|
271
|
+
},
|
|
272
|
+
404: {
|
|
273
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
274
|
+
description: 'Record not found',
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
}),
|
|
278
|
+
(c) => c.json({} as never)
|
|
279
|
+
)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function registerCommentRoutes(app: OpenAPIHono): void {
|
|
283
|
+
// GET /api/tables/{tableId}/records/{recordId}/comments
|
|
284
|
+
app.openapi(
|
|
285
|
+
createRoute({
|
|
286
|
+
method: 'get',
|
|
287
|
+
path: '/api/tables/{tableId}/records/{recordId}/comments',
|
|
288
|
+
summary: 'List comments on a record',
|
|
289
|
+
description: 'Returns paginated comments for a specific record.',
|
|
290
|
+
operationId: 'listComments',
|
|
291
|
+
tags: ['records'],
|
|
292
|
+
request: { params: recordIdParamSchema },
|
|
293
|
+
responses: {
|
|
294
|
+
200: {
|
|
295
|
+
content: { 'application/json': { schema: listCommentsResponseSchema } },
|
|
296
|
+
description: 'List of comments',
|
|
297
|
+
},
|
|
298
|
+
401: {
|
|
299
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
300
|
+
description: 'Unauthorized',
|
|
301
|
+
},
|
|
302
|
+
404: {
|
|
303
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
304
|
+
description: 'Record not found',
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
}),
|
|
308
|
+
(c) => c.json({} as never)
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
// POST /api/tables/{tableId}/records/{recordId}/comments
|
|
312
|
+
app.openapi(
|
|
313
|
+
createRoute({
|
|
314
|
+
method: 'post',
|
|
315
|
+
path: '/api/tables/{tableId}/records/{recordId}/comments',
|
|
316
|
+
summary: 'Create a comment',
|
|
317
|
+
description: 'Adds a comment to a record.',
|
|
318
|
+
operationId: 'createComment',
|
|
319
|
+
tags: ['records'],
|
|
320
|
+
request: {
|
|
321
|
+
params: recordIdParamSchema,
|
|
322
|
+
body: { content: { 'application/json': { schema: commentBodySchema } } },
|
|
323
|
+
},
|
|
324
|
+
responses: {
|
|
325
|
+
201: {
|
|
326
|
+
content: { 'application/json': { schema: createCommentResponseSchema } },
|
|
327
|
+
description: 'Comment created',
|
|
328
|
+
},
|
|
329
|
+
400: {
|
|
330
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
331
|
+
description: 'Validation error',
|
|
332
|
+
},
|
|
333
|
+
401: {
|
|
334
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
335
|
+
description: 'Unauthorized',
|
|
336
|
+
},
|
|
337
|
+
404: {
|
|
338
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
339
|
+
description: 'Record not found',
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
}),
|
|
343
|
+
(c) => c.json({} as never, 201)
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
// GET /api/tables/{tableId}/records/{recordId}/comments/{commentId}
|
|
347
|
+
app.openapi(
|
|
348
|
+
createRoute({
|
|
349
|
+
method: 'get',
|
|
350
|
+
path: '/api/tables/{tableId}/records/{recordId}/comments/{commentId}',
|
|
351
|
+
summary: 'Get a comment',
|
|
352
|
+
description: 'Returns a single comment by ID.',
|
|
353
|
+
operationId: 'getComment',
|
|
354
|
+
tags: ['records'],
|
|
355
|
+
request: { params: commentIdParamSchema },
|
|
356
|
+
responses: {
|
|
357
|
+
200: {
|
|
358
|
+
content: { 'application/json': { schema: getCommentResponseSchema } },
|
|
359
|
+
description: 'Comment details',
|
|
360
|
+
},
|
|
361
|
+
401: {
|
|
362
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
363
|
+
description: 'Unauthorized',
|
|
364
|
+
},
|
|
365
|
+
404: {
|
|
366
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
367
|
+
description: 'Comment not found',
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
}),
|
|
371
|
+
(c) => c.json({} as never)
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
// PATCH /api/tables/{tableId}/records/{recordId}/comments/{commentId}
|
|
375
|
+
app.openapi(
|
|
376
|
+
createRoute({
|
|
377
|
+
method: 'patch',
|
|
378
|
+
path: '/api/tables/{tableId}/records/{recordId}/comments/{commentId}',
|
|
379
|
+
summary: 'Update a comment',
|
|
380
|
+
description: 'Updates the content of a comment. Only the author can update.',
|
|
381
|
+
operationId: 'updateComment',
|
|
382
|
+
tags: ['records'],
|
|
383
|
+
request: {
|
|
384
|
+
params: commentIdParamSchema,
|
|
385
|
+
body: { content: { 'application/json': { schema: commentBodySchema } } },
|
|
386
|
+
},
|
|
387
|
+
responses: {
|
|
388
|
+
200: {
|
|
389
|
+
content: { 'application/json': { schema: updateCommentResponseSchema } },
|
|
390
|
+
description: 'Comment updated',
|
|
391
|
+
},
|
|
392
|
+
400: {
|
|
393
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
394
|
+
description: 'Validation error',
|
|
395
|
+
},
|
|
396
|
+
401: {
|
|
397
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
398
|
+
description: 'Unauthorized',
|
|
399
|
+
},
|
|
400
|
+
403: {
|
|
401
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
402
|
+
description: 'Forbidden',
|
|
403
|
+
},
|
|
404
|
+
404: {
|
|
405
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
406
|
+
description: 'Comment not found',
|
|
407
|
+
},
|
|
408
|
+
},
|
|
409
|
+
}),
|
|
410
|
+
(c) => c.json({} as never)
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
// DELETE /api/tables/{tableId}/records/{recordId}/comments/{commentId}
|
|
414
|
+
app.openapi(
|
|
415
|
+
createRoute({
|
|
416
|
+
method: 'delete',
|
|
417
|
+
path: '/api/tables/{tableId}/records/{recordId}/comments/{commentId}',
|
|
418
|
+
summary: 'Delete a comment',
|
|
419
|
+
description: 'Soft-deletes a comment. Only the author or admin can delete.',
|
|
420
|
+
operationId: 'deleteComment',
|
|
421
|
+
tags: ['records'],
|
|
422
|
+
request: { params: commentIdParamSchema },
|
|
423
|
+
responses: {
|
|
424
|
+
204: {
|
|
425
|
+
description: 'Comment deleted (no content)',
|
|
426
|
+
},
|
|
427
|
+
401: {
|
|
428
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
429
|
+
description: 'Unauthorized',
|
|
430
|
+
},
|
|
431
|
+
403: {
|
|
432
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
433
|
+
description: 'Forbidden',
|
|
434
|
+
},
|
|
435
|
+
404: {
|
|
436
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
437
|
+
description: 'Comment not found',
|
|
438
|
+
},
|
|
439
|
+
},
|
|
440
|
+
}),
|
|
441
|
+
// eslint-disable-next-line unicorn/no-null -- Hono c.body() requires null for 204
|
|
442
|
+
(c) => c.body(null, 204)
|
|
443
|
+
)
|
|
444
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 ESSENTIAL SERVICES
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Business Source License 1.1
|
|
5
|
+
* found in the LICENSE.md file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { type OpenAPIHono, createRoute } from '@hono/zod-openapi'
|
|
9
|
+
import { errorResponseSchema } from '@/domain/models/api/error'
|
|
10
|
+
import { tableIdParamSchema } from '@/domain/models/api/params'
|
|
11
|
+
import {
|
|
12
|
+
getTablePermissionsResponseSchema,
|
|
13
|
+
getTableResponseSchema,
|
|
14
|
+
listTablesResponseSchema,
|
|
15
|
+
} from '@/domain/models/api/tables'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Register table management routes for OpenAPI schema generation
|
|
19
|
+
*/
|
|
20
|
+
export function registerTableRoutes(app: OpenAPIHono): void {
|
|
21
|
+
// GET /api/tables
|
|
22
|
+
app.openapi(
|
|
23
|
+
createRoute({
|
|
24
|
+
method: 'get',
|
|
25
|
+
path: '/api/tables',
|
|
26
|
+
summary: 'List all tables',
|
|
27
|
+
description: 'Returns a list of all tables with summary information.',
|
|
28
|
+
operationId: 'listTables',
|
|
29
|
+
tags: ['tables'],
|
|
30
|
+
responses: {
|
|
31
|
+
200: {
|
|
32
|
+
content: { 'application/json': { schema: listTablesResponseSchema } },
|
|
33
|
+
description: 'List of tables',
|
|
34
|
+
},
|
|
35
|
+
401: {
|
|
36
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
37
|
+
description: 'Unauthorized',
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
}),
|
|
41
|
+
(c) => c.json({} as never)
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
// GET /api/tables/{tableId}
|
|
45
|
+
app.openapi(
|
|
46
|
+
createRoute({
|
|
47
|
+
method: 'get',
|
|
48
|
+
path: '/api/tables/{tableId}',
|
|
49
|
+
summary: 'Get table details',
|
|
50
|
+
description: 'Returns full table definition including fields, views, and permissions.',
|
|
51
|
+
operationId: 'getTable',
|
|
52
|
+
tags: ['tables'],
|
|
53
|
+
request: { params: tableIdParamSchema },
|
|
54
|
+
responses: {
|
|
55
|
+
200: {
|
|
56
|
+
content: { 'application/json': { schema: getTableResponseSchema } },
|
|
57
|
+
description: 'Table details',
|
|
58
|
+
},
|
|
59
|
+
401: {
|
|
60
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
61
|
+
description: 'Unauthorized',
|
|
62
|
+
},
|
|
63
|
+
404: {
|
|
64
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
65
|
+
description: 'Table not found',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
}),
|
|
69
|
+
(c) => c.json({} as never)
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
// GET /api/tables/{tableId}/permissions
|
|
73
|
+
app.openapi(
|
|
74
|
+
createRoute({
|
|
75
|
+
method: 'get',
|
|
76
|
+
path: '/api/tables/{tableId}/permissions',
|
|
77
|
+
summary: 'Get table permissions',
|
|
78
|
+
description:
|
|
79
|
+
"Returns the current user's permissions for the table, including field-level access.",
|
|
80
|
+
operationId: 'getTablePermissions',
|
|
81
|
+
tags: ['tables'],
|
|
82
|
+
request: { params: tableIdParamSchema },
|
|
83
|
+
responses: {
|
|
84
|
+
200: {
|
|
85
|
+
content: { 'application/json': { schema: getTablePermissionsResponseSchema } },
|
|
86
|
+
description: 'Table permissions',
|
|
87
|
+
},
|
|
88
|
+
401: {
|
|
89
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
90
|
+
description: 'Unauthorized',
|
|
91
|
+
},
|
|
92
|
+
404: {
|
|
93
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
94
|
+
description: 'Table not found',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
}),
|
|
98
|
+
(c) => c.json({} as never)
|
|
99
|
+
)
|
|
100
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 ESSENTIAL SERVICES
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Business Source License 1.1
|
|
5
|
+
* found in the LICENSE.md file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { type OpenAPIHono, createRoute } from '@hono/zod-openapi'
|
|
9
|
+
import { errorResponseSchema } from '@/domain/models/api/error'
|
|
10
|
+
import { tableIdParamSchema, viewIdParamSchema } from '@/domain/models/api/params'
|
|
11
|
+
import {
|
|
12
|
+
getViewRecordsResponseSchema,
|
|
13
|
+
getViewResponseSchema,
|
|
14
|
+
listViewsResponseSchema,
|
|
15
|
+
} from '@/domain/models/api/tables'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Register view routes for OpenAPI schema generation
|
|
19
|
+
*/
|
|
20
|
+
export function registerViewRoutes(app: OpenAPIHono): void {
|
|
21
|
+
// GET /api/tables/{tableId}/views
|
|
22
|
+
app.openapi(
|
|
23
|
+
createRoute({
|
|
24
|
+
method: 'get',
|
|
25
|
+
path: '/api/tables/{tableId}/views',
|
|
26
|
+
summary: 'List views',
|
|
27
|
+
description: 'Returns all views defined for a table.',
|
|
28
|
+
operationId: 'listViews',
|
|
29
|
+
tags: ['views'],
|
|
30
|
+
request: { params: tableIdParamSchema },
|
|
31
|
+
responses: {
|
|
32
|
+
200: {
|
|
33
|
+
content: { 'application/json': { schema: listViewsResponseSchema } },
|
|
34
|
+
description: 'List of views',
|
|
35
|
+
},
|
|
36
|
+
401: {
|
|
37
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
38
|
+
description: 'Unauthorized',
|
|
39
|
+
},
|
|
40
|
+
404: {
|
|
41
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
42
|
+
description: 'Table not found',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
}),
|
|
46
|
+
(c) => c.json({} as never)
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
// GET /api/tables/{tableId}/views/{viewId}
|
|
50
|
+
app.openapi(
|
|
51
|
+
createRoute({
|
|
52
|
+
method: 'get',
|
|
53
|
+
path: '/api/tables/{tableId}/views/{viewId}',
|
|
54
|
+
summary: 'Get view details',
|
|
55
|
+
description: 'Returns view configuration including filters, sorts, and visible fields.',
|
|
56
|
+
operationId: 'getView',
|
|
57
|
+
tags: ['views'],
|
|
58
|
+
request: { params: viewIdParamSchema },
|
|
59
|
+
responses: {
|
|
60
|
+
200: {
|
|
61
|
+
content: { 'application/json': { schema: getViewResponseSchema } },
|
|
62
|
+
description: 'View details',
|
|
63
|
+
},
|
|
64
|
+
401: {
|
|
65
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
66
|
+
description: 'Unauthorized',
|
|
67
|
+
},
|
|
68
|
+
404: {
|
|
69
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
70
|
+
description: 'View not found',
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
}),
|
|
74
|
+
(c) => c.json({} as never)
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
// GET /api/tables/{tableId}/views/{viewId}/records
|
|
78
|
+
app.openapi(
|
|
79
|
+
createRoute({
|
|
80
|
+
method: 'get',
|
|
81
|
+
path: '/api/tables/{tableId}/views/{viewId}/records',
|
|
82
|
+
summary: 'Get records through a view',
|
|
83
|
+
description: 'Returns records filtered and sorted according to the view configuration.',
|
|
84
|
+
operationId: 'getViewRecords',
|
|
85
|
+
tags: ['views'],
|
|
86
|
+
request: { params: viewIdParamSchema },
|
|
87
|
+
responses: {
|
|
88
|
+
200: {
|
|
89
|
+
content: { 'application/json': { schema: getViewRecordsResponseSchema } },
|
|
90
|
+
description: 'Filtered records',
|
|
91
|
+
},
|
|
92
|
+
401: {
|
|
93
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
94
|
+
description: 'Unauthorized',
|
|
95
|
+
},
|
|
96
|
+
404: {
|
|
97
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
98
|
+
description: 'View not found',
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
}),
|
|
102
|
+
(c) => c.json({} as never)
|
|
103
|
+
)
|
|
104
|
+
}
|