@objectstack/runtime 1.0.2 → 1.0.5
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/.turbo/turbo-build.log +22 -0
- package/CHANGELOG.md +33 -0
- package/dist/index.cjs +1586 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +629 -0
- package/dist/index.d.ts +628 -14
- package/dist/index.js +1549 -16
- package/dist/index.js.map +1 -0
- package/package.json +6 -5
- package/src/api-registry-plugin.ts +15 -3
- package/src/rest-server.ts +3 -5
- package/src/route-manager.ts +2 -1
- package/src/runtime.ts +0 -1
- package/tsconfig.json +4 -9
- package/dist/api-registry-plugin.d.ts +0 -16
- package/dist/api-registry-plugin.js +0 -42
- package/dist/app-plugin.d.ts +0 -18
- package/dist/app-plugin.js +0 -80
- package/dist/app-plugin.test.d.ts +0 -1
- package/dist/app-plugin.test.js +0 -80
- package/dist/driver-plugin.d.ts +0 -23
- package/dist/driver-plugin.js +0 -35
- package/dist/http-dispatcher.d.ts +0 -106
- package/dist/http-dispatcher.js +0 -539
- package/dist/http-dispatcher.test.d.ts +0 -1
- package/dist/http-dispatcher.test.js +0 -79
- package/dist/http-server.d.ts +0 -84
- package/dist/http-server.js +0 -125
- package/dist/middleware.d.ts +0 -111
- package/dist/middleware.js +0 -176
- package/dist/rest-server.d.ts +0 -74
- package/dist/rest-server.js +0 -518
- package/dist/route-manager.d.ts +0 -153
- package/dist/route-manager.js +0 -251
- package/dist/runtime.d.ts +0 -45
- package/dist/runtime.js +0 -50
- package/dist/runtime.test.d.ts +0 -1
- package/dist/runtime.test.js +0 -57
package/dist/rest-server.js
DELETED
|
@@ -1,518 +0,0 @@
|
|
|
1
|
-
import { RouteManager } from './route-manager.js';
|
|
2
|
-
/**
|
|
3
|
-
* RestServer
|
|
4
|
-
*
|
|
5
|
-
* Provides automatic REST API endpoint generation for ObjectStack.
|
|
6
|
-
* Generates standard RESTful CRUD endpoints, metadata endpoints, and batch operations
|
|
7
|
-
* based on the configured protocol provider.
|
|
8
|
-
*
|
|
9
|
-
* Features:
|
|
10
|
-
* - Automatic CRUD endpoint generation (GET, POST, PUT, PATCH, DELETE)
|
|
11
|
-
* - Metadata API endpoints (/meta)
|
|
12
|
-
* - Batch operation endpoints (/batch, /createMany, /updateMany, /deleteMany)
|
|
13
|
-
* - Discovery endpoint
|
|
14
|
-
* - Configurable path prefixes and patterns
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* const restServer = new RestServer(httpServer, protocolProvider, {
|
|
18
|
-
* api: {
|
|
19
|
-
* version: 'v1',
|
|
20
|
-
* basePath: '/api'
|
|
21
|
-
* },
|
|
22
|
-
* crud: {
|
|
23
|
-
* dataPrefix: '/data'
|
|
24
|
-
* }
|
|
25
|
-
* });
|
|
26
|
-
*
|
|
27
|
-
* restServer.registerRoutes();
|
|
28
|
-
*/
|
|
29
|
-
export class RestServer {
|
|
30
|
-
constructor(server, protocol, config = {}) {
|
|
31
|
-
this.server = server;
|
|
32
|
-
this.protocol = protocol;
|
|
33
|
-
this.config = this.normalizeConfig(config);
|
|
34
|
-
this.routeManager = new RouteManager(server);
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Normalize configuration with defaults
|
|
38
|
-
*/
|
|
39
|
-
normalizeConfig(config) {
|
|
40
|
-
const api = (config.api ?? {});
|
|
41
|
-
const crud = (config.crud ?? {});
|
|
42
|
-
const metadata = (config.metadata ?? {});
|
|
43
|
-
const batch = (config.batch ?? {});
|
|
44
|
-
const routes = (config.routes ?? {});
|
|
45
|
-
return {
|
|
46
|
-
api: {
|
|
47
|
-
version: api.version ?? 'v1',
|
|
48
|
-
basePath: api.basePath ?? '/api',
|
|
49
|
-
apiPath: api.apiPath,
|
|
50
|
-
enableCrud: api.enableCrud ?? true,
|
|
51
|
-
enableMetadata: api.enableMetadata ?? true,
|
|
52
|
-
enableBatch: api.enableBatch ?? true,
|
|
53
|
-
enableDiscovery: api.enableDiscovery ?? true,
|
|
54
|
-
documentation: api.documentation,
|
|
55
|
-
responseFormat: api.responseFormat,
|
|
56
|
-
},
|
|
57
|
-
crud: {
|
|
58
|
-
operations: crud.operations ?? {
|
|
59
|
-
create: true,
|
|
60
|
-
read: true,
|
|
61
|
-
update: true,
|
|
62
|
-
delete: true,
|
|
63
|
-
list: true,
|
|
64
|
-
},
|
|
65
|
-
patterns: crud.patterns,
|
|
66
|
-
dataPrefix: crud.dataPrefix ?? '/data',
|
|
67
|
-
objectParamStyle: crud.objectParamStyle ?? 'path',
|
|
68
|
-
},
|
|
69
|
-
metadata: {
|
|
70
|
-
prefix: metadata.prefix ?? '/meta',
|
|
71
|
-
enableCache: metadata.enableCache ?? true,
|
|
72
|
-
cacheTtl: metadata.cacheTtl ?? 3600,
|
|
73
|
-
endpoints: metadata.endpoints ?? {
|
|
74
|
-
types: true,
|
|
75
|
-
items: true,
|
|
76
|
-
item: true,
|
|
77
|
-
schema: true,
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
batch: {
|
|
81
|
-
maxBatchSize: batch.maxBatchSize ?? 200,
|
|
82
|
-
enableBatchEndpoint: batch.enableBatchEndpoint ?? true,
|
|
83
|
-
operations: batch.operations ?? {
|
|
84
|
-
createMany: true,
|
|
85
|
-
updateMany: true,
|
|
86
|
-
deleteMany: true,
|
|
87
|
-
upsertMany: true,
|
|
88
|
-
},
|
|
89
|
-
defaultAtomic: batch.defaultAtomic ?? true,
|
|
90
|
-
},
|
|
91
|
-
routes: {
|
|
92
|
-
includeObjects: routes.includeObjects,
|
|
93
|
-
excludeObjects: routes.excludeObjects,
|
|
94
|
-
nameTransform: routes.nameTransform ?? 'none',
|
|
95
|
-
overrides: routes.overrides,
|
|
96
|
-
},
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Get the full API base path
|
|
101
|
-
*/
|
|
102
|
-
getApiBasePath() {
|
|
103
|
-
const { api } = this.config;
|
|
104
|
-
return api.apiPath ?? `${api.basePath}/${api.version}`;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Register all REST API routes
|
|
108
|
-
*/
|
|
109
|
-
registerRoutes() {
|
|
110
|
-
const basePath = this.getApiBasePath();
|
|
111
|
-
// Discovery endpoint
|
|
112
|
-
if (this.config.api.enableDiscovery) {
|
|
113
|
-
this.registerDiscoveryEndpoints(basePath);
|
|
114
|
-
}
|
|
115
|
-
// Metadata endpoints
|
|
116
|
-
if (this.config.api.enableMetadata) {
|
|
117
|
-
this.registerMetadataEndpoints(basePath);
|
|
118
|
-
}
|
|
119
|
-
// CRUD endpoints
|
|
120
|
-
if (this.config.api.enableCrud) {
|
|
121
|
-
this.registerCrudEndpoints(basePath);
|
|
122
|
-
}
|
|
123
|
-
// Batch endpoints
|
|
124
|
-
if (this.config.api.enableBatch) {
|
|
125
|
-
this.registerBatchEndpoints(basePath);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Register discovery endpoints
|
|
130
|
-
*/
|
|
131
|
-
registerDiscoveryEndpoints(basePath) {
|
|
132
|
-
this.routeManager.register({
|
|
133
|
-
method: 'GET',
|
|
134
|
-
path: basePath,
|
|
135
|
-
handler: async (req, res) => {
|
|
136
|
-
try {
|
|
137
|
-
const discovery = await this.protocol.getDiscovery({});
|
|
138
|
-
res.json(discovery);
|
|
139
|
-
}
|
|
140
|
-
catch (error) {
|
|
141
|
-
res.status(500).json({ error: error.message });
|
|
142
|
-
}
|
|
143
|
-
},
|
|
144
|
-
metadata: {
|
|
145
|
-
summary: 'Get API discovery information',
|
|
146
|
-
tags: ['discovery'],
|
|
147
|
-
},
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Register metadata endpoints
|
|
152
|
-
*/
|
|
153
|
-
registerMetadataEndpoints(basePath) {
|
|
154
|
-
const { metadata } = this.config;
|
|
155
|
-
const metaPath = `${basePath}${metadata.prefix}`;
|
|
156
|
-
// GET /meta - List all metadata types
|
|
157
|
-
if (metadata.endpoints.types !== false) {
|
|
158
|
-
this.routeManager.register({
|
|
159
|
-
method: 'GET',
|
|
160
|
-
path: metaPath,
|
|
161
|
-
handler: async (req, res) => {
|
|
162
|
-
try {
|
|
163
|
-
const types = await this.protocol.getMetaTypes({});
|
|
164
|
-
res.json(types);
|
|
165
|
-
}
|
|
166
|
-
catch (error) {
|
|
167
|
-
res.status(500).json({ error: error.message });
|
|
168
|
-
}
|
|
169
|
-
},
|
|
170
|
-
metadata: {
|
|
171
|
-
summary: 'List all metadata types',
|
|
172
|
-
tags: ['metadata'],
|
|
173
|
-
},
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
// GET /meta/:type - List items of a type
|
|
177
|
-
if (metadata.endpoints.items !== false) {
|
|
178
|
-
this.routeManager.register({
|
|
179
|
-
method: 'GET',
|
|
180
|
-
path: `${metaPath}/:type`,
|
|
181
|
-
handler: async (req, res) => {
|
|
182
|
-
try {
|
|
183
|
-
const items = await this.protocol.getMetaItems({ type: req.params.type });
|
|
184
|
-
res.json(items);
|
|
185
|
-
}
|
|
186
|
-
catch (error) {
|
|
187
|
-
res.status(404).json({ error: error.message });
|
|
188
|
-
}
|
|
189
|
-
},
|
|
190
|
-
metadata: {
|
|
191
|
-
summary: 'List metadata items of a type',
|
|
192
|
-
tags: ['metadata'],
|
|
193
|
-
},
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
// GET /meta/:type/:name - Get specific item
|
|
197
|
-
if (metadata.endpoints.item !== false) {
|
|
198
|
-
this.routeManager.register({
|
|
199
|
-
method: 'GET',
|
|
200
|
-
path: `${metaPath}/:type/:name`,
|
|
201
|
-
handler: async (req, res) => {
|
|
202
|
-
try {
|
|
203
|
-
// Check if cached version is available
|
|
204
|
-
if (metadata.enableCache && this.protocol.getMetaItemCached) {
|
|
205
|
-
const cacheRequest = {
|
|
206
|
-
ifNoneMatch: req.headers['if-none-match'],
|
|
207
|
-
ifModifiedSince: req.headers['if-modified-since'],
|
|
208
|
-
};
|
|
209
|
-
const result = await this.protocol.getMetaItemCached({
|
|
210
|
-
type: req.params.type,
|
|
211
|
-
name: req.params.name,
|
|
212
|
-
cacheRequest
|
|
213
|
-
});
|
|
214
|
-
if (result.notModified) {
|
|
215
|
-
res.status(304).send();
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
// Set cache headers
|
|
219
|
-
if (result.etag) {
|
|
220
|
-
const etagValue = result.etag.weak
|
|
221
|
-
? `W/"${result.etag.value}"`
|
|
222
|
-
: `"${result.etag.value}"`;
|
|
223
|
-
res.header('ETag', etagValue);
|
|
224
|
-
}
|
|
225
|
-
if (result.lastModified) {
|
|
226
|
-
res.header('Last-Modified', new Date(result.lastModified).toUTCString());
|
|
227
|
-
}
|
|
228
|
-
if (result.cacheControl) {
|
|
229
|
-
const directives = result.cacheControl.directives.join(', ');
|
|
230
|
-
const maxAge = result.cacheControl.maxAge
|
|
231
|
-
? `, max-age=${result.cacheControl.maxAge}`
|
|
232
|
-
: '';
|
|
233
|
-
res.header('Cache-Control', directives + maxAge);
|
|
234
|
-
}
|
|
235
|
-
res.json(result.data);
|
|
236
|
-
}
|
|
237
|
-
else {
|
|
238
|
-
// Non-cached version
|
|
239
|
-
const item = await this.protocol.getMetaItem({ type: req.params.type, name: req.params.name });
|
|
240
|
-
res.json(item);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
catch (error) {
|
|
244
|
-
res.status(404).json({ error: error.message });
|
|
245
|
-
}
|
|
246
|
-
},
|
|
247
|
-
metadata: {
|
|
248
|
-
summary: 'Get specific metadata item',
|
|
249
|
-
tags: ['metadata'],
|
|
250
|
-
},
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
// PUT /meta/:type/:name - Save metadata item
|
|
254
|
-
// We always register this route, but return 501 if protocol doesn't support it
|
|
255
|
-
// This makes it discoverable even if not implemented
|
|
256
|
-
this.routeManager.register({
|
|
257
|
-
method: 'PUT',
|
|
258
|
-
path: `${metaPath}/:type/:name`,
|
|
259
|
-
handler: async (req, res) => {
|
|
260
|
-
try {
|
|
261
|
-
if (!this.protocol.saveMetaItem) {
|
|
262
|
-
res.status(501).json({ error: 'Save operation not supported by protocol implementation' });
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
const result = await this.protocol.saveMetaItem({
|
|
266
|
-
type: req.params.type,
|
|
267
|
-
name: req.params.name,
|
|
268
|
-
item: req.body
|
|
269
|
-
});
|
|
270
|
-
res.json(result);
|
|
271
|
-
}
|
|
272
|
-
catch (error) {
|
|
273
|
-
res.status(400).json({ error: error.message });
|
|
274
|
-
}
|
|
275
|
-
},
|
|
276
|
-
metadata: {
|
|
277
|
-
summary: 'Save specific metadata item',
|
|
278
|
-
tags: ['metadata'],
|
|
279
|
-
},
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* Register CRUD endpoints for data operations
|
|
284
|
-
*/
|
|
285
|
-
registerCrudEndpoints(basePath) {
|
|
286
|
-
const { crud } = this.config;
|
|
287
|
-
const dataPath = `${basePath}${crud.dataPrefix}`;
|
|
288
|
-
const operations = crud.operations;
|
|
289
|
-
// GET /data/:object - List/query records
|
|
290
|
-
if (operations.list) {
|
|
291
|
-
this.routeManager.register({
|
|
292
|
-
method: 'GET',
|
|
293
|
-
path: `${dataPath}/:object`,
|
|
294
|
-
handler: async (req, res) => {
|
|
295
|
-
try {
|
|
296
|
-
const result = await this.protocol.findData({
|
|
297
|
-
object: req.params.object,
|
|
298
|
-
query: req.query
|
|
299
|
-
});
|
|
300
|
-
res.json(result);
|
|
301
|
-
}
|
|
302
|
-
catch (error) {
|
|
303
|
-
res.status(400).json({ error: error.message });
|
|
304
|
-
}
|
|
305
|
-
},
|
|
306
|
-
metadata: {
|
|
307
|
-
summary: 'Query records',
|
|
308
|
-
tags: ['data', 'crud'],
|
|
309
|
-
},
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
// GET /data/:object/:id - Get single record
|
|
313
|
-
if (operations.read) {
|
|
314
|
-
this.routeManager.register({
|
|
315
|
-
method: 'GET',
|
|
316
|
-
path: `${dataPath}/:object/:id`,
|
|
317
|
-
handler: async (req, res) => {
|
|
318
|
-
try {
|
|
319
|
-
const result = await this.protocol.getData({
|
|
320
|
-
object: req.params.object,
|
|
321
|
-
id: req.params.id
|
|
322
|
-
});
|
|
323
|
-
res.json(result);
|
|
324
|
-
}
|
|
325
|
-
catch (error) {
|
|
326
|
-
res.status(404).json({ error: error.message });
|
|
327
|
-
}
|
|
328
|
-
},
|
|
329
|
-
metadata: {
|
|
330
|
-
summary: 'Get record by ID',
|
|
331
|
-
tags: ['data', 'crud'],
|
|
332
|
-
},
|
|
333
|
-
});
|
|
334
|
-
}
|
|
335
|
-
// POST /data/:object - Create record
|
|
336
|
-
if (operations.create) {
|
|
337
|
-
this.routeManager.register({
|
|
338
|
-
method: 'POST',
|
|
339
|
-
path: `${dataPath}/:object`,
|
|
340
|
-
handler: async (req, res) => {
|
|
341
|
-
try {
|
|
342
|
-
const result = await this.protocol.createData({
|
|
343
|
-
object: req.params.object,
|
|
344
|
-
data: req.body
|
|
345
|
-
});
|
|
346
|
-
res.status(201).json(result);
|
|
347
|
-
}
|
|
348
|
-
catch (error) {
|
|
349
|
-
res.status(400).json({ error: error.message });
|
|
350
|
-
}
|
|
351
|
-
},
|
|
352
|
-
metadata: {
|
|
353
|
-
summary: 'Create record',
|
|
354
|
-
tags: ['data', 'crud'],
|
|
355
|
-
},
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
// PATCH /data/:object/:id - Update record
|
|
359
|
-
if (operations.update) {
|
|
360
|
-
this.routeManager.register({
|
|
361
|
-
method: 'PATCH',
|
|
362
|
-
path: `${dataPath}/:object/:id`,
|
|
363
|
-
handler: async (req, res) => {
|
|
364
|
-
try {
|
|
365
|
-
const result = await this.protocol.updateData({
|
|
366
|
-
object: req.params.object,
|
|
367
|
-
id: req.params.id,
|
|
368
|
-
data: req.body
|
|
369
|
-
});
|
|
370
|
-
res.json(result);
|
|
371
|
-
}
|
|
372
|
-
catch (error) {
|
|
373
|
-
res.status(400).json({ error: error.message });
|
|
374
|
-
}
|
|
375
|
-
},
|
|
376
|
-
metadata: {
|
|
377
|
-
summary: 'Update record',
|
|
378
|
-
tags: ['data', 'crud'],
|
|
379
|
-
},
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
// DELETE /data/:object/:id - Delete record
|
|
383
|
-
if (operations.delete) {
|
|
384
|
-
this.routeManager.register({
|
|
385
|
-
method: 'DELETE',
|
|
386
|
-
path: `${dataPath}/:object/:id`,
|
|
387
|
-
handler: async (req, res) => {
|
|
388
|
-
try {
|
|
389
|
-
const result = await this.protocol.deleteData({
|
|
390
|
-
object: req.params.object,
|
|
391
|
-
id: req.params.id
|
|
392
|
-
});
|
|
393
|
-
res.json(result);
|
|
394
|
-
}
|
|
395
|
-
catch (error) {
|
|
396
|
-
res.status(400).json({ error: error.message });
|
|
397
|
-
}
|
|
398
|
-
},
|
|
399
|
-
metadata: {
|
|
400
|
-
summary: 'Delete record',
|
|
401
|
-
tags: ['data', 'crud'],
|
|
402
|
-
},
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
/**
|
|
407
|
-
* Register batch operation endpoints
|
|
408
|
-
*/
|
|
409
|
-
registerBatchEndpoints(basePath) {
|
|
410
|
-
const { crud, batch } = this.config;
|
|
411
|
-
const dataPath = `${basePath}${crud.dataPrefix}`;
|
|
412
|
-
const operations = batch.operations;
|
|
413
|
-
// POST /data/:object/batch - Generic batch endpoint
|
|
414
|
-
if (batch.enableBatchEndpoint && this.protocol.batchData) {
|
|
415
|
-
this.routeManager.register({
|
|
416
|
-
method: 'POST',
|
|
417
|
-
path: `${dataPath}/:object/batch`,
|
|
418
|
-
handler: async (req, res) => {
|
|
419
|
-
try {
|
|
420
|
-
const result = await this.protocol.batchData({
|
|
421
|
-
object: req.params.object,
|
|
422
|
-
request: req.body
|
|
423
|
-
});
|
|
424
|
-
res.json(result);
|
|
425
|
-
}
|
|
426
|
-
catch (error) {
|
|
427
|
-
res.status(400).json({ error: error.message });
|
|
428
|
-
}
|
|
429
|
-
},
|
|
430
|
-
metadata: {
|
|
431
|
-
summary: 'Batch operations',
|
|
432
|
-
tags: ['data', 'batch'],
|
|
433
|
-
},
|
|
434
|
-
});
|
|
435
|
-
}
|
|
436
|
-
// POST /data/:object/createMany - Bulk create
|
|
437
|
-
if (operations.createMany && this.protocol.createManyData) {
|
|
438
|
-
this.routeManager.register({
|
|
439
|
-
method: 'POST',
|
|
440
|
-
path: `${dataPath}/:object/createMany`,
|
|
441
|
-
handler: async (req, res) => {
|
|
442
|
-
try {
|
|
443
|
-
const result = await this.protocol.createManyData({
|
|
444
|
-
object: req.params.object,
|
|
445
|
-
records: req.body || []
|
|
446
|
-
});
|
|
447
|
-
res.status(201).json(result);
|
|
448
|
-
}
|
|
449
|
-
catch (error) {
|
|
450
|
-
res.status(400).json({ error: error.message });
|
|
451
|
-
}
|
|
452
|
-
},
|
|
453
|
-
metadata: {
|
|
454
|
-
summary: 'Create multiple records',
|
|
455
|
-
tags: ['data', 'batch'],
|
|
456
|
-
},
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
// POST /data/:object/updateMany - Bulk update
|
|
460
|
-
if (operations.updateMany && this.protocol.updateManyData) {
|
|
461
|
-
this.routeManager.register({
|
|
462
|
-
method: 'POST',
|
|
463
|
-
path: `${dataPath}/:object/updateMany`,
|
|
464
|
-
handler: async (req, res) => {
|
|
465
|
-
try {
|
|
466
|
-
const result = await this.protocol.updateManyData({
|
|
467
|
-
object: req.params.object,
|
|
468
|
-
...req.body
|
|
469
|
-
});
|
|
470
|
-
res.json(result);
|
|
471
|
-
}
|
|
472
|
-
catch (error) {
|
|
473
|
-
res.status(400).json({ error: error.message });
|
|
474
|
-
}
|
|
475
|
-
},
|
|
476
|
-
metadata: {
|
|
477
|
-
summary: 'Update multiple records',
|
|
478
|
-
tags: ['data', 'batch'],
|
|
479
|
-
},
|
|
480
|
-
});
|
|
481
|
-
}
|
|
482
|
-
// POST /data/:object/deleteMany - Bulk delete
|
|
483
|
-
if (operations.deleteMany && this.protocol.deleteManyData) {
|
|
484
|
-
this.routeManager.register({
|
|
485
|
-
method: 'POST',
|
|
486
|
-
path: `${dataPath}/:object/deleteMany`,
|
|
487
|
-
handler: async (req, res) => {
|
|
488
|
-
try {
|
|
489
|
-
const result = await this.protocol.deleteManyData({
|
|
490
|
-
object: req.params.object,
|
|
491
|
-
...req.body
|
|
492
|
-
});
|
|
493
|
-
res.json(result);
|
|
494
|
-
}
|
|
495
|
-
catch (error) {
|
|
496
|
-
res.status(400).json({ error: error.message });
|
|
497
|
-
}
|
|
498
|
-
},
|
|
499
|
-
metadata: {
|
|
500
|
-
summary: 'Delete multiple records',
|
|
501
|
-
tags: ['data', 'batch'],
|
|
502
|
-
},
|
|
503
|
-
});
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
/**
|
|
507
|
-
* Get the route manager
|
|
508
|
-
*/
|
|
509
|
-
getRouteManager() {
|
|
510
|
-
return this.routeManager;
|
|
511
|
-
}
|
|
512
|
-
/**
|
|
513
|
-
* Get all registered routes
|
|
514
|
-
*/
|
|
515
|
-
getRoutes() {
|
|
516
|
-
return this.routeManager.getAll();
|
|
517
|
-
}
|
|
518
|
-
}
|
package/dist/route-manager.d.ts
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import { RouteHandler, IHttpServer } from '@objectstack/core';
|
|
2
|
-
import { System, Shared } from '@objectstack/spec';
|
|
3
|
-
type RouteHandlerMetadata = System.RouteHandlerMetadata;
|
|
4
|
-
type HttpMethod = Shared.HttpMethod;
|
|
5
|
-
/**
|
|
6
|
-
* Route Entry
|
|
7
|
-
* Internal representation of registered routes
|
|
8
|
-
*/
|
|
9
|
-
export interface RouteEntry {
|
|
10
|
-
method: HttpMethod;
|
|
11
|
-
path: string;
|
|
12
|
-
handler: RouteHandler;
|
|
13
|
-
metadata?: RouteHandlerMetadata['metadata'];
|
|
14
|
-
security?: RouteHandlerMetadata['security'];
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* RouteManager
|
|
18
|
-
*
|
|
19
|
-
* Manages route registration and organization for HTTP servers.
|
|
20
|
-
* Provides:
|
|
21
|
-
* - Route registration with metadata
|
|
22
|
-
* - Route lookup and querying
|
|
23
|
-
* - Bulk route registration
|
|
24
|
-
* - Route grouping by prefix
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* const manager = new RouteManager(server);
|
|
28
|
-
*
|
|
29
|
-
* // Register individual route
|
|
30
|
-
* manager.register({
|
|
31
|
-
* method: 'GET',
|
|
32
|
-
* path: '/api/users/:id',
|
|
33
|
-
* handler: getUserHandler,
|
|
34
|
-
* metadata: {
|
|
35
|
-
* summary: 'Get user by ID',
|
|
36
|
-
* tags: ['users']
|
|
37
|
-
* }
|
|
38
|
-
* });
|
|
39
|
-
*
|
|
40
|
-
* // Register route group
|
|
41
|
-
* manager.group('/api/users', (group) => {
|
|
42
|
-
* group.get('/', listUsersHandler);
|
|
43
|
-
* group.post('/', createUserHandler);
|
|
44
|
-
* group.get('/:id', getUserHandler);
|
|
45
|
-
* });
|
|
46
|
-
*/
|
|
47
|
-
export declare class RouteManager {
|
|
48
|
-
private server;
|
|
49
|
-
private routes;
|
|
50
|
-
constructor(server: IHttpServer);
|
|
51
|
-
/**
|
|
52
|
-
* Register a route
|
|
53
|
-
* @param entry - Route entry with method, path, handler, and metadata
|
|
54
|
-
*/
|
|
55
|
-
register(entry: Omit<RouteEntry, 'handler'> & {
|
|
56
|
-
handler: RouteHandler | string;
|
|
57
|
-
}): void;
|
|
58
|
-
/**
|
|
59
|
-
* Register multiple routes
|
|
60
|
-
* @param entries - Array of route entries
|
|
61
|
-
*/
|
|
62
|
-
registerMany(entries: Array<Omit<RouteEntry, 'handler'> & {
|
|
63
|
-
handler: RouteHandler | string;
|
|
64
|
-
}>): void;
|
|
65
|
-
/**
|
|
66
|
-
* Unregister a route
|
|
67
|
-
* @param method - HTTP method
|
|
68
|
-
* @param path - Route path
|
|
69
|
-
*/
|
|
70
|
-
unregister(method: HttpMethod, path: string): void;
|
|
71
|
-
/**
|
|
72
|
-
* Get route by method and path
|
|
73
|
-
* @param method - HTTP method
|
|
74
|
-
* @param path - Route path
|
|
75
|
-
*/
|
|
76
|
-
get(method: HttpMethod, path: string): RouteEntry | undefined;
|
|
77
|
-
/**
|
|
78
|
-
* Get all routes
|
|
79
|
-
*/
|
|
80
|
-
getAll(): RouteEntry[];
|
|
81
|
-
/**
|
|
82
|
-
* Get routes by method
|
|
83
|
-
* @param method - HTTP method
|
|
84
|
-
*/
|
|
85
|
-
getByMethod(method: HttpMethod): RouteEntry[];
|
|
86
|
-
/**
|
|
87
|
-
* Get routes by path prefix
|
|
88
|
-
* @param prefix - Path prefix
|
|
89
|
-
*/
|
|
90
|
-
getByPrefix(prefix: string): RouteEntry[];
|
|
91
|
-
/**
|
|
92
|
-
* Get routes by tag
|
|
93
|
-
* @param tag - Tag name
|
|
94
|
-
*/
|
|
95
|
-
getByTag(tag: string): RouteEntry[];
|
|
96
|
-
/**
|
|
97
|
-
* Create a route group with common prefix
|
|
98
|
-
* @param prefix - Common path prefix
|
|
99
|
-
* @param configure - Function to configure routes in the group
|
|
100
|
-
*/
|
|
101
|
-
group(prefix: string, configure: (group: RouteGroupBuilder) => void): void;
|
|
102
|
-
/**
|
|
103
|
-
* Get route count
|
|
104
|
-
*/
|
|
105
|
-
count(): number;
|
|
106
|
-
/**
|
|
107
|
-
* Clear all routes
|
|
108
|
-
*/
|
|
109
|
-
clear(): void;
|
|
110
|
-
/**
|
|
111
|
-
* Get route key for storage
|
|
112
|
-
*/
|
|
113
|
-
private getRouteKey;
|
|
114
|
-
/**
|
|
115
|
-
* Register route with underlying server
|
|
116
|
-
*/
|
|
117
|
-
private registerWithServer;
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* RouteGroupBuilder
|
|
121
|
-
*
|
|
122
|
-
* Builder for creating route groups with common prefix
|
|
123
|
-
*/
|
|
124
|
-
export declare class RouteGroupBuilder {
|
|
125
|
-
private manager;
|
|
126
|
-
private prefix;
|
|
127
|
-
constructor(manager: RouteManager, prefix: string);
|
|
128
|
-
/**
|
|
129
|
-
* Register GET route in group
|
|
130
|
-
*/
|
|
131
|
-
get(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this;
|
|
132
|
-
/**
|
|
133
|
-
* Register POST route in group
|
|
134
|
-
*/
|
|
135
|
-
post(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this;
|
|
136
|
-
/**
|
|
137
|
-
* Register PUT route in group
|
|
138
|
-
*/
|
|
139
|
-
put(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this;
|
|
140
|
-
/**
|
|
141
|
-
* Register PATCH route in group
|
|
142
|
-
*/
|
|
143
|
-
patch(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this;
|
|
144
|
-
/**
|
|
145
|
-
* Register DELETE route in group
|
|
146
|
-
*/
|
|
147
|
-
delete(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this;
|
|
148
|
-
/**
|
|
149
|
-
* Resolve full path with prefix
|
|
150
|
-
*/
|
|
151
|
-
private resolvePath;
|
|
152
|
-
}
|
|
153
|
-
export {};
|