@objectstack/rest 1.1.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/dist/index.cjs ADDED
@@ -0,0 +1,788 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ RestServer: () => RestServer,
24
+ RouteGroupBuilder: () => RouteGroupBuilder,
25
+ RouteManager: () => RouteManager,
26
+ createApiRegistryPlugin: () => createApiRegistryPlugin,
27
+ createRestApiPlugin: () => createRestApiPlugin
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/route-manager.ts
32
+ var RouteManager = class {
33
+ constructor(server) {
34
+ this.server = server;
35
+ this.routes = /* @__PURE__ */ new Map();
36
+ }
37
+ /**
38
+ * Register a route
39
+ * @param entry - Route entry with method, path, handler, and metadata
40
+ */
41
+ register(entry) {
42
+ if (typeof entry.handler === "string") {
43
+ throw new Error(
44
+ `String-based route handlers are not supported yet. Received handler identifier "${entry.handler}". Please provide a RouteHandler function instead.`
45
+ );
46
+ }
47
+ const handler = entry.handler;
48
+ const routeEntry = {
49
+ method: entry.method,
50
+ path: entry.path,
51
+ handler,
52
+ metadata: entry.metadata,
53
+ security: entry.security
54
+ };
55
+ const key = this.getRouteKey(entry.method, entry.path);
56
+ this.routes.set(key, routeEntry);
57
+ this.registerWithServer(routeEntry);
58
+ }
59
+ /**
60
+ * Register multiple routes
61
+ * @param entries - Array of route entries
62
+ */
63
+ registerMany(entries) {
64
+ entries.forEach((entry) => this.register(entry));
65
+ }
66
+ /**
67
+ * Unregister a route
68
+ * @param method - HTTP method
69
+ * @param path - Route path
70
+ */
71
+ unregister(method, path) {
72
+ const key = this.getRouteKey(method, path);
73
+ this.routes.delete(key);
74
+ }
75
+ /**
76
+ * Get route by method and path
77
+ * @param method - HTTP method
78
+ * @param path - Route path
79
+ */
80
+ get(method, path) {
81
+ const key = this.getRouteKey(method, path);
82
+ return this.routes.get(key);
83
+ }
84
+ /**
85
+ * Get all routes
86
+ */
87
+ getAll() {
88
+ return Array.from(this.routes.values());
89
+ }
90
+ /**
91
+ * Get routes by method
92
+ * @param method - HTTP method
93
+ */
94
+ getByMethod(method) {
95
+ return this.getAll().filter((route) => route.method === method);
96
+ }
97
+ /**
98
+ * Get routes by path prefix
99
+ * @param prefix - Path prefix
100
+ */
101
+ getByPrefix(prefix) {
102
+ return this.getAll().filter((route) => route.path.startsWith(prefix));
103
+ }
104
+ /**
105
+ * Get routes by tag
106
+ * @param tag - Tag name
107
+ */
108
+ getByTag(tag) {
109
+ return this.getAll().filter(
110
+ (route) => route.metadata?.tags?.includes(tag)
111
+ );
112
+ }
113
+ /**
114
+ * Create a route group with common prefix
115
+ * @param prefix - Common path prefix
116
+ * @param configure - Function to configure routes in the group
117
+ */
118
+ group(prefix, configure) {
119
+ const builder = new RouteGroupBuilder(this, prefix);
120
+ configure(builder);
121
+ }
122
+ /**
123
+ * Get route count
124
+ */
125
+ count() {
126
+ return this.routes.size;
127
+ }
128
+ /**
129
+ * Clear all routes
130
+ */
131
+ clear() {
132
+ this.routes.clear();
133
+ }
134
+ /**
135
+ * Get route key for storage
136
+ */
137
+ getRouteKey(method, path) {
138
+ return `${method}:${path}`;
139
+ }
140
+ /**
141
+ * Register route with underlying server
142
+ */
143
+ registerWithServer(entry) {
144
+ const { method, path, handler } = entry;
145
+ switch (method) {
146
+ case "GET":
147
+ this.server.get(path, handler);
148
+ break;
149
+ case "POST":
150
+ this.server.post(path, handler);
151
+ break;
152
+ case "PUT":
153
+ this.server.put(path, handler);
154
+ break;
155
+ case "DELETE":
156
+ this.server.delete(path, handler);
157
+ break;
158
+ case "PATCH":
159
+ this.server.patch(path, handler);
160
+ break;
161
+ default:
162
+ throw new Error(`Unsupported HTTP method: ${method}`);
163
+ }
164
+ }
165
+ };
166
+ var RouteGroupBuilder = class {
167
+ constructor(manager, prefix) {
168
+ this.manager = manager;
169
+ this.prefix = prefix;
170
+ }
171
+ /**
172
+ * Register GET route in group
173
+ */
174
+ get(path, handler, metadata) {
175
+ this.manager.register({
176
+ method: "GET",
177
+ path: this.resolvePath(path),
178
+ handler,
179
+ metadata
180
+ });
181
+ return this;
182
+ }
183
+ /**
184
+ * Register POST route in group
185
+ */
186
+ post(path, handler, metadata) {
187
+ this.manager.register({
188
+ method: "POST",
189
+ path: this.resolvePath(path),
190
+ handler,
191
+ metadata
192
+ });
193
+ return this;
194
+ }
195
+ /**
196
+ * Register PUT route in group
197
+ */
198
+ put(path, handler, metadata) {
199
+ this.manager.register({
200
+ method: "PUT",
201
+ path: this.resolvePath(path),
202
+ handler,
203
+ metadata
204
+ });
205
+ return this;
206
+ }
207
+ /**
208
+ * Register PATCH route in group
209
+ */
210
+ patch(path, handler, metadata) {
211
+ this.manager.register({
212
+ method: "PATCH",
213
+ path: this.resolvePath(path),
214
+ handler,
215
+ metadata
216
+ });
217
+ return this;
218
+ }
219
+ /**
220
+ * Register DELETE route in group
221
+ */
222
+ delete(path, handler, metadata) {
223
+ this.manager.register({
224
+ method: "DELETE",
225
+ path: this.resolvePath(path),
226
+ handler,
227
+ metadata
228
+ });
229
+ return this;
230
+ }
231
+ /**
232
+ * Resolve full path with prefix
233
+ */
234
+ resolvePath(path) {
235
+ const normalizedPrefix = this.prefix.endsWith("/") ? this.prefix.slice(0, -1) : this.prefix;
236
+ const normalizedPath = path.startsWith("/") ? path : "/" + path;
237
+ return normalizedPrefix + normalizedPath;
238
+ }
239
+ };
240
+
241
+ // src/rest-server.ts
242
+ var RestServer = class {
243
+ constructor(server, protocol, config = {}) {
244
+ this.protocol = protocol;
245
+ this.config = this.normalizeConfig(config);
246
+ this.routeManager = new RouteManager(server);
247
+ }
248
+ /**
249
+ * Normalize configuration with defaults
250
+ */
251
+ normalizeConfig(config) {
252
+ const api = config.api ?? {};
253
+ const crud = config.crud ?? {};
254
+ const metadata = config.metadata ?? {};
255
+ const batch = config.batch ?? {};
256
+ const routes = config.routes ?? {};
257
+ return {
258
+ api: {
259
+ version: api.version ?? "v1",
260
+ basePath: api.basePath ?? "/api",
261
+ apiPath: api.apiPath,
262
+ enableCrud: api.enableCrud ?? true,
263
+ enableMetadata: api.enableMetadata ?? true,
264
+ enableUi: api.enableUi ?? true,
265
+ enableBatch: api.enableBatch ?? true,
266
+ enableDiscovery: api.enableDiscovery ?? true,
267
+ documentation: api.documentation,
268
+ responseFormat: api.responseFormat
269
+ },
270
+ crud: {
271
+ operations: crud.operations ?? {
272
+ create: true,
273
+ read: true,
274
+ update: true,
275
+ delete: true,
276
+ list: true
277
+ },
278
+ patterns: crud.patterns,
279
+ dataPrefix: crud.dataPrefix ?? "/data",
280
+ objectParamStyle: crud.objectParamStyle ?? "path"
281
+ },
282
+ metadata: {
283
+ prefix: metadata.prefix ?? "/meta",
284
+ enableCache: metadata.enableCache ?? true,
285
+ cacheTtl: metadata.cacheTtl ?? 3600,
286
+ endpoints: metadata.endpoints ?? {
287
+ types: true,
288
+ items: true,
289
+ item: true,
290
+ schema: true
291
+ }
292
+ },
293
+ batch: {
294
+ maxBatchSize: batch.maxBatchSize ?? 200,
295
+ enableBatchEndpoint: batch.enableBatchEndpoint ?? true,
296
+ operations: batch.operations ?? {
297
+ createMany: true,
298
+ updateMany: true,
299
+ deleteMany: true,
300
+ upsertMany: true
301
+ },
302
+ defaultAtomic: batch.defaultAtomic ?? true
303
+ },
304
+ routes: {
305
+ includeObjects: routes.includeObjects,
306
+ excludeObjects: routes.excludeObjects,
307
+ nameTransform: routes.nameTransform ?? "none",
308
+ overrides: routes.overrides
309
+ }
310
+ };
311
+ }
312
+ /**
313
+ * Get the full API base path
314
+ */
315
+ getApiBasePath() {
316
+ const { api } = this.config;
317
+ return api.apiPath ?? `${api.basePath}/${api.version}`;
318
+ }
319
+ /**
320
+ * Register all REST API routes
321
+ */
322
+ registerRoutes() {
323
+ const basePath = this.getApiBasePath();
324
+ if (this.config.api.enableDiscovery) {
325
+ this.registerDiscoveryEndpoints(basePath);
326
+ }
327
+ if (this.config.api.enableMetadata) {
328
+ this.registerMetadataEndpoints(basePath);
329
+ }
330
+ if (this.config.api.enableUi) {
331
+ this.registerUiEndpoints(basePath);
332
+ }
333
+ if (this.config.api.enableCrud) {
334
+ this.registerCrudEndpoints(basePath);
335
+ }
336
+ if (this.config.api.enableBatch) {
337
+ this.registerBatchEndpoints(basePath);
338
+ }
339
+ }
340
+ /**
341
+ * Register discovery endpoints
342
+ */
343
+ registerDiscoveryEndpoints(basePath) {
344
+ this.routeManager.register({
345
+ method: "GET",
346
+ path: basePath,
347
+ handler: async (_req, res) => {
348
+ try {
349
+ const discovery = await this.protocol.getDiscovery();
350
+ discovery.version = this.config.api.version;
351
+ if (discovery.endpoints) {
352
+ if (this.config.api.enableCrud) {
353
+ discovery.endpoints.data = `${basePath}${this.config.crud.dataPrefix}`;
354
+ }
355
+ if (this.config.api.enableMetadata) {
356
+ discovery.endpoints.metadata = `${basePath}${this.config.metadata.prefix}`;
357
+ }
358
+ if (this.config.api.enableUi) {
359
+ discovery.endpoints.ui = `${basePath}/ui`;
360
+ }
361
+ if (discovery.endpoints.auth) {
362
+ discovery.endpoints.auth = `${basePath}/auth`;
363
+ }
364
+ }
365
+ res.json(discovery);
366
+ } catch (error) {
367
+ res.status(500).json({ error: error.message });
368
+ }
369
+ },
370
+ metadata: {
371
+ summary: "Get API discovery information",
372
+ tags: ["discovery"]
373
+ }
374
+ });
375
+ }
376
+ /**
377
+ * Register metadata endpoints
378
+ */
379
+ registerMetadataEndpoints(basePath) {
380
+ const { metadata } = this.config;
381
+ const metaPath = `${basePath}${metadata.prefix}`;
382
+ if (metadata.endpoints.types !== false) {
383
+ this.routeManager.register({
384
+ method: "GET",
385
+ path: metaPath,
386
+ handler: async (_req, res) => {
387
+ try {
388
+ const types = await this.protocol.getMetaTypes();
389
+ res.json(types);
390
+ } catch (error) {
391
+ res.status(500).json({ error: error.message });
392
+ }
393
+ },
394
+ metadata: {
395
+ summary: "List all metadata types",
396
+ tags: ["metadata"]
397
+ }
398
+ });
399
+ }
400
+ if (metadata.endpoints.items !== false) {
401
+ this.routeManager.register({
402
+ method: "GET",
403
+ path: `${metaPath}/:type`,
404
+ handler: async (req, res) => {
405
+ try {
406
+ const items = await this.protocol.getMetaItems({ type: req.params.type });
407
+ res.json(items);
408
+ } catch (error) {
409
+ res.status(404).json({ error: error.message });
410
+ }
411
+ },
412
+ metadata: {
413
+ summary: "List metadata items of a type",
414
+ tags: ["metadata"]
415
+ }
416
+ });
417
+ }
418
+ if (metadata.endpoints.item !== false) {
419
+ this.routeManager.register({
420
+ method: "GET",
421
+ path: `${metaPath}/:type/:name`,
422
+ handler: async (req, res) => {
423
+ try {
424
+ if (metadata.enableCache && this.protocol.getMetaItemCached) {
425
+ const cacheRequest = {
426
+ ifNoneMatch: req.headers["if-none-match"],
427
+ ifModifiedSince: req.headers["if-modified-since"]
428
+ };
429
+ const result = await this.protocol.getMetaItemCached({
430
+ type: req.params.type,
431
+ name: req.params.name,
432
+ cacheRequest
433
+ });
434
+ if (result.notModified) {
435
+ res.status(304).send();
436
+ return;
437
+ }
438
+ if (result.etag) {
439
+ const etagValue = result.etag.weak ? `W/"${result.etag.value}"` : `"${result.etag.value}"`;
440
+ res.header("ETag", etagValue);
441
+ }
442
+ if (result.lastModified) {
443
+ res.header("Last-Modified", new Date(result.lastModified).toUTCString());
444
+ }
445
+ if (result.cacheControl) {
446
+ const directives = result.cacheControl.directives.join(", ");
447
+ const maxAge = result.cacheControl.maxAge ? `, max-age=${result.cacheControl.maxAge}` : "";
448
+ res.header("Cache-Control", directives + maxAge);
449
+ }
450
+ res.json(result.data);
451
+ } else {
452
+ const item = await this.protocol.getMetaItem({ type: req.params.type, name: req.params.name });
453
+ res.json(item);
454
+ }
455
+ } catch (error) {
456
+ res.status(404).json({ error: error.message });
457
+ }
458
+ },
459
+ metadata: {
460
+ summary: "Get specific metadata item",
461
+ tags: ["metadata"]
462
+ }
463
+ });
464
+ }
465
+ this.routeManager.register({
466
+ method: "PUT",
467
+ path: `${metaPath}/:type/:name`,
468
+ handler: async (req, res) => {
469
+ try {
470
+ if (!this.protocol.saveMetaItem) {
471
+ res.status(501).json({ error: "Save operation not supported by protocol implementation" });
472
+ return;
473
+ }
474
+ const result = await this.protocol.saveMetaItem({
475
+ type: req.params.type,
476
+ name: req.params.name,
477
+ item: req.body
478
+ });
479
+ res.json(result);
480
+ } catch (error) {
481
+ res.status(400).json({ error: error.message });
482
+ }
483
+ },
484
+ metadata: {
485
+ summary: "Save specific metadata item",
486
+ tags: ["metadata"]
487
+ }
488
+ });
489
+ }
490
+ /**
491
+ * Register UI endpoints
492
+ */
493
+ registerUiEndpoints(basePath) {
494
+ const uiPath = `${basePath}/ui`;
495
+ this.routeManager.register({
496
+ method: "GET",
497
+ path: `${uiPath}/view/:object/:type`,
498
+ handler: async (req, res) => {
499
+ try {
500
+ if (this.protocol.getUiView) {
501
+ const view = await this.protocol.getUiView({
502
+ object: req.params.object,
503
+ type: req.params.type
504
+ });
505
+ res.json(view);
506
+ } else {
507
+ res.status(501).json({ error: "UI View resolution not supported by protocol implementation" });
508
+ }
509
+ } catch (error) {
510
+ res.status(404).json({ error: error.message });
511
+ }
512
+ },
513
+ metadata: {
514
+ summary: "Resolve UI View for object",
515
+ tags: ["ui"]
516
+ }
517
+ });
518
+ }
519
+ /**
520
+ * Register CRUD endpoints for data operations
521
+ */
522
+ registerCrudEndpoints(basePath) {
523
+ const { crud } = this.config;
524
+ const dataPath = `${basePath}${crud.dataPrefix}`;
525
+ const operations = crud.operations;
526
+ if (operations.list) {
527
+ this.routeManager.register({
528
+ method: "GET",
529
+ path: `${dataPath}/:object`,
530
+ handler: async (req, res) => {
531
+ try {
532
+ const result = await this.protocol.findData({
533
+ object: req.params.object,
534
+ query: req.query
535
+ });
536
+ res.json(result);
537
+ } catch (error) {
538
+ res.status(400).json({ error: error.message });
539
+ }
540
+ },
541
+ metadata: {
542
+ summary: "Query records",
543
+ tags: ["data", "crud"]
544
+ }
545
+ });
546
+ }
547
+ if (operations.read) {
548
+ this.routeManager.register({
549
+ method: "GET",
550
+ path: `${dataPath}/:object/:id`,
551
+ handler: async (req, res) => {
552
+ try {
553
+ const result = await this.protocol.getData({
554
+ object: req.params.object,
555
+ id: req.params.id
556
+ });
557
+ res.json(result);
558
+ } catch (error) {
559
+ res.status(404).json({ error: error.message });
560
+ }
561
+ },
562
+ metadata: {
563
+ summary: "Get record by ID",
564
+ tags: ["data", "crud"]
565
+ }
566
+ });
567
+ }
568
+ if (operations.create) {
569
+ this.routeManager.register({
570
+ method: "POST",
571
+ path: `${dataPath}/:object`,
572
+ handler: async (req, res) => {
573
+ try {
574
+ const result = await this.protocol.createData({
575
+ object: req.params.object,
576
+ data: req.body
577
+ });
578
+ res.status(201).json(result);
579
+ } catch (error) {
580
+ res.status(400).json({ error: error.message });
581
+ }
582
+ },
583
+ metadata: {
584
+ summary: "Create record",
585
+ tags: ["data", "crud"]
586
+ }
587
+ });
588
+ }
589
+ if (operations.update) {
590
+ this.routeManager.register({
591
+ method: "PATCH",
592
+ path: `${dataPath}/:object/:id`,
593
+ handler: async (req, res) => {
594
+ try {
595
+ const result = await this.protocol.updateData({
596
+ object: req.params.object,
597
+ id: req.params.id,
598
+ data: req.body
599
+ });
600
+ res.json(result);
601
+ } catch (error) {
602
+ res.status(400).json({ error: error.message });
603
+ }
604
+ },
605
+ metadata: {
606
+ summary: "Update record",
607
+ tags: ["data", "crud"]
608
+ }
609
+ });
610
+ }
611
+ if (operations.delete) {
612
+ this.routeManager.register({
613
+ method: "DELETE",
614
+ path: `${dataPath}/:object/:id`,
615
+ handler: async (req, res) => {
616
+ try {
617
+ const result = await this.protocol.deleteData({
618
+ object: req.params.object,
619
+ id: req.params.id
620
+ });
621
+ res.json(result);
622
+ } catch (error) {
623
+ res.status(400).json({ error: error.message });
624
+ }
625
+ },
626
+ metadata: {
627
+ summary: "Delete record",
628
+ tags: ["data", "crud"]
629
+ }
630
+ });
631
+ }
632
+ }
633
+ /**
634
+ * Register batch operation endpoints
635
+ */
636
+ registerBatchEndpoints(basePath) {
637
+ const { crud, batch } = this.config;
638
+ const dataPath = `${basePath}${crud.dataPrefix}`;
639
+ const operations = batch.operations;
640
+ if (batch.enableBatchEndpoint && this.protocol.batchData) {
641
+ this.routeManager.register({
642
+ method: "POST",
643
+ path: `${dataPath}/:object/batch`,
644
+ handler: async (req, res) => {
645
+ try {
646
+ const result = await this.protocol.batchData({
647
+ object: req.params.object,
648
+ request: req.body
649
+ });
650
+ res.json(result);
651
+ } catch (error) {
652
+ res.status(400).json({ error: error.message });
653
+ }
654
+ },
655
+ metadata: {
656
+ summary: "Batch operations",
657
+ tags: ["data", "batch"]
658
+ }
659
+ });
660
+ }
661
+ if (operations.createMany && this.protocol.createManyData) {
662
+ this.routeManager.register({
663
+ method: "POST",
664
+ path: `${dataPath}/:object/createMany`,
665
+ handler: async (req, res) => {
666
+ try {
667
+ const result = await this.protocol.createManyData({
668
+ object: req.params.object,
669
+ records: req.body || []
670
+ });
671
+ res.status(201).json(result);
672
+ } catch (error) {
673
+ res.status(400).json({ error: error.message });
674
+ }
675
+ },
676
+ metadata: {
677
+ summary: "Create multiple records",
678
+ tags: ["data", "batch"]
679
+ }
680
+ });
681
+ }
682
+ if (operations.updateMany && this.protocol.updateManyData) {
683
+ this.routeManager.register({
684
+ method: "POST",
685
+ path: `${dataPath}/:object/updateMany`,
686
+ handler: async (req, res) => {
687
+ try {
688
+ const result = await this.protocol.updateManyData({
689
+ object: req.params.object,
690
+ ...req.body
691
+ });
692
+ res.json(result);
693
+ } catch (error) {
694
+ res.status(400).json({ error: error.message });
695
+ }
696
+ },
697
+ metadata: {
698
+ summary: "Update multiple records",
699
+ tags: ["data", "batch"]
700
+ }
701
+ });
702
+ }
703
+ if (operations.deleteMany && this.protocol.deleteManyData) {
704
+ this.routeManager.register({
705
+ method: "POST",
706
+ path: `${dataPath}/:object/deleteMany`,
707
+ handler: async (req, res) => {
708
+ try {
709
+ const result = await this.protocol.deleteManyData({
710
+ object: req.params.object,
711
+ ...req.body
712
+ });
713
+ res.json(result);
714
+ } catch (error) {
715
+ res.status(400).json({ error: error.message });
716
+ }
717
+ },
718
+ metadata: {
719
+ summary: "Delete multiple records",
720
+ tags: ["data", "batch"]
721
+ }
722
+ });
723
+ }
724
+ }
725
+ /**
726
+ * Get the route manager
727
+ */
728
+ getRouteManager() {
729
+ return this.routeManager;
730
+ }
731
+ /**
732
+ * Get all registered routes
733
+ */
734
+ getRoutes() {
735
+ return this.routeManager.getAll();
736
+ }
737
+ };
738
+
739
+ // src/rest-api-plugin.ts
740
+ function createRestApiPlugin(config = {}) {
741
+ return {
742
+ name: "com.objectstack.rest.api",
743
+ version: "1.0.0",
744
+ init: async (_ctx) => {
745
+ },
746
+ start: async (ctx) => {
747
+ const serverService = config.serverServiceName || "http.server";
748
+ const protocolService = config.protocolServiceName || "protocol";
749
+ let server;
750
+ let protocol;
751
+ try {
752
+ server = ctx.getService(serverService);
753
+ } catch (e) {
754
+ }
755
+ try {
756
+ protocol = ctx.getService(protocolService);
757
+ } catch (e) {
758
+ }
759
+ if (!server) {
760
+ ctx.logger.warn(`RestApiPlugin: HTTP Server service '${serverService}' not found. REST routes skipped.`);
761
+ return;
762
+ }
763
+ if (!protocol) {
764
+ ctx.logger.warn(`RestApiPlugin: Protocol service '${protocolService}' not found. REST routes skipped.`);
765
+ return;
766
+ }
767
+ ctx.logger.info("Hydrating REST API from Protocol...");
768
+ try {
769
+ const restServer = new RestServer(server, protocol, config.api);
770
+ restServer.registerRoutes();
771
+ ctx.logger.info("REST API successfully registered");
772
+ } catch (err) {
773
+ ctx.logger.error("Failed to register REST API routes", { error: err.message });
774
+ throw err;
775
+ }
776
+ }
777
+ };
778
+ }
779
+ var createApiRegistryPlugin = createRestApiPlugin;
780
+ // Annotate the CommonJS export names for ESM import in node:
781
+ 0 && (module.exports = {
782
+ RestServer,
783
+ RouteGroupBuilder,
784
+ RouteManager,
785
+ createApiRegistryPlugin,
786
+ createRestApiPlugin
787
+ });
788
+ //# sourceMappingURL=index.cjs.map