@objectstack/runtime 1.0.4 → 1.0.6

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.d.ts CHANGED
@@ -1,15 +1,629 @@
1
- export { ObjectKernel } from '@objectstack/core';
2
- export { Runtime } from './runtime.js';
3
- export type { RuntimeConfig } from './runtime.js';
4
- export { DriverPlugin } from './driver-plugin.js';
5
- export { AppPlugin } from './app-plugin.js';
6
- export { createApiRegistryPlugin } from './api-registry-plugin.js';
7
- export type { ApiRegistryConfig } from './api-registry-plugin.js';
8
- export { HttpServer } from './http-server.js';
9
- export { HttpDispatcher } from './http-dispatcher.js';
10
- export type { HttpProtocolContext, HttpDispatcherResult } from './http-dispatcher.js';
11
- export { RestServer } from './rest-server.js';
12
- export { RouteManager, RouteGroupBuilder } from './route-manager.js';
13
- export type { RouteEntry } from './route-manager.js';
14
- export { MiddlewareManager } from './middleware.js';
1
+ import { Plugin, ObjectKernel, IHttpServer, ObjectKernelConfig, PluginContext, RouteHandler, Middleware } from '@objectstack/core';
15
2
  export * from '@objectstack/core';
3
+ export { ObjectKernel } from '@objectstack/core';
4
+ import { RestServerConfig, ObjectStackProtocol } from '@objectstack/spec/api';
5
+ import { Shared, System } from '@objectstack/spec';
6
+ import { z } from 'zod';
7
+ import { MiddlewareConfig, MiddlewareType } from '@objectstack/spec/system';
8
+
9
+ interface ApiRegistryConfig {
10
+ serverServiceName?: string;
11
+ protocolServiceName?: string;
12
+ api?: RestServerConfig;
13
+ }
14
+ /**
15
+ * ApiRegistryPlugin
16
+ *
17
+ * Responsibilities:
18
+ * 1. Consumes 'http.server' (or configured service)
19
+ * 2. Consumes 'protocol' (ObjectStackProtocol)
20
+ * 3. Instantiates RestServer to auto-generate routes
21
+ */
22
+ declare function createApiRegistryPlugin(config?: ApiRegistryConfig): Plugin;
23
+
24
+ interface RuntimeConfig {
25
+ /**
26
+ * Optional existing server instance (e.g. Hono, Express app)
27
+ * If provided, Runtime will use it as the 'http.server' service.
28
+ * If not provided, Runtime expects a server plugin (like HonoServerPlugin) to be registered manually.
29
+ */
30
+ server?: IHttpServer;
31
+ /**
32
+ * API Registry Configuration
33
+ */
34
+ api?: ApiRegistryConfig;
35
+ /**
36
+ * Kernel Configuration
37
+ */
38
+ kernel?: ObjectKernelConfig;
39
+ }
40
+ /**
41
+ * ObjectStack Runtime
42
+ *
43
+ * High-level entry point for bootstrapping an ObjectStack application.
44
+ * Wraps ObjectKernel and provides standard orchestration for:
45
+ * - HTTP Server binding
46
+ * - API Registry (REST Routes)
47
+ * - Plugin Management
48
+ */
49
+ declare class Runtime {
50
+ readonly kernel: ObjectKernel;
51
+ constructor(config?: RuntimeConfig);
52
+ /**
53
+ * Register a plugin
54
+ */
55
+ use(plugin: Plugin): this;
56
+ /**
57
+ * Start the runtime
58
+ * 1. Initializes all plugins (init phase)
59
+ * 2. Starts all plugins (start phase)
60
+ */
61
+ start(): Promise<this>;
62
+ /**
63
+ * Get the kernel instance
64
+ */
65
+ getKernel(): ObjectKernel;
66
+ }
67
+
68
+ /**
69
+ * Driver Plugin
70
+ *
71
+ * Generic plugin wrapper for ObjectQL drivers.
72
+ * Registers a driver with the ObjectQL engine.
73
+ *
74
+ * Dependencies: None (Registers service for ObjectQL to discover)
75
+ * Services: driver.{name}
76
+ *
77
+ * @example
78
+ * const memoryDriver = new InMemoryDriver();
79
+ * const driverPlugin = new DriverPlugin(memoryDriver, 'memory');
80
+ * kernel.use(driverPlugin);
81
+ */
82
+ declare class DriverPlugin implements Plugin {
83
+ name: string;
84
+ version: string;
85
+ private driver;
86
+ constructor(driver: any, driverName?: string);
87
+ init: (ctx: PluginContext) => Promise<void>;
88
+ start: (ctx: PluginContext) => Promise<void>;
89
+ }
90
+
91
+ /**
92
+ * AppPlugin
93
+ *
94
+ * Adapts a generic App Bundle (Manifest + Runtime Code) into a Kernel Plugin.
95
+ *
96
+ * Responsibilities:
97
+ * 1. Register App Manifest as a service (for ObjectQL discovery)
98
+ * 2. Execute Runtime `onEnable` hook (for code logic)
99
+ */
100
+ declare class AppPlugin implements Plugin {
101
+ name: string;
102
+ version?: string;
103
+ private bundle;
104
+ constructor(bundle: any);
105
+ init: (ctx: PluginContext) => Promise<void>;
106
+ start: (ctx: PluginContext) => Promise<void>;
107
+ }
108
+
109
+ /**
110
+ * HttpServer - Unified HTTP Server Abstraction
111
+ *
112
+ * Provides a framework-agnostic HTTP server interface that wraps
113
+ * underlying server implementations (Hono, Express, Fastify, etc.)
114
+ *
115
+ * This class serves as an adapter between the IHttpServer interface
116
+ * and concrete server implementations, allowing plugins to register
117
+ * routes and middleware without depending on specific frameworks.
118
+ *
119
+ * Features:
120
+ * - Unified route registration API
121
+ * - Middleware management with ordering
122
+ * - Request/response lifecycle hooks
123
+ * - Framework-agnostic abstractions
124
+ */
125
+ declare class HttpServer implements IHttpServer {
126
+ protected server: IHttpServer;
127
+ protected routes: Map<string, RouteHandler>;
128
+ protected middlewares: Middleware[];
129
+ /**
130
+ * Create an HTTP server wrapper
131
+ * @param server - The underlying server implementation (Hono, Express, etc.)
132
+ */
133
+ constructor(server: IHttpServer);
134
+ /**
135
+ * Register a GET route handler
136
+ * @param path - Route path (e.g., '/api/users/:id')
137
+ * @param handler - Route handler function
138
+ */
139
+ get(path: string, handler: RouteHandler): void;
140
+ /**
141
+ * Register a POST route handler
142
+ * @param path - Route path
143
+ * @param handler - Route handler function
144
+ */
145
+ post(path: string, handler: RouteHandler): void;
146
+ /**
147
+ * Register a PUT route handler
148
+ * @param path - Route path
149
+ * @param handler - Route handler function
150
+ */
151
+ put(path: string, handler: RouteHandler): void;
152
+ /**
153
+ * Register a DELETE route handler
154
+ * @param path - Route path
155
+ * @param handler - Route handler function
156
+ */
157
+ delete(path: string, handler: RouteHandler): void;
158
+ /**
159
+ * Register a PATCH route handler
160
+ * @param path - Route path
161
+ * @param handler - Route handler function
162
+ */
163
+ patch(path: string, handler: RouteHandler): void;
164
+ /**
165
+ * Register middleware
166
+ * @param path - Optional path to apply middleware to (if omitted, applies globally)
167
+ * @param handler - Middleware function
168
+ */
169
+ use(path: string | Middleware, handler?: Middleware): void;
170
+ /**
171
+ * Start the HTTP server
172
+ * @param port - Port number to listen on
173
+ * @returns Promise that resolves when server is ready
174
+ */
175
+ listen(port: number): Promise<void>;
176
+ /**
177
+ * Stop the HTTP server
178
+ * @returns Promise that resolves when server is stopped
179
+ */
180
+ close(): Promise<void>;
181
+ /**
182
+ * Get registered routes
183
+ * @returns Map of route keys to handlers
184
+ */
185
+ getRoutes(): Map<string, RouteHandler>;
186
+ /**
187
+ * Get registered middlewares
188
+ * @returns Array of middleware functions
189
+ */
190
+ getMiddlewares(): Middleware[];
191
+ }
192
+
193
+ interface HttpProtocolContext {
194
+ request: any;
195
+ response?: any;
196
+ }
197
+ interface HttpDispatcherResult {
198
+ handled: boolean;
199
+ response?: {
200
+ status: number;
201
+ body?: any;
202
+ headers?: Record<string, string>;
203
+ };
204
+ result?: any;
205
+ }
206
+ declare class HttpDispatcher {
207
+ private kernel;
208
+ constructor(kernel: ObjectKernel);
209
+ private success;
210
+ private error;
211
+ private ensureBroker;
212
+ /**
213
+ * Generates the discovery JSON response for the API root
214
+ */
215
+ getDiscoveryInfo(prefix: string): {
216
+ name: string;
217
+ version: string;
218
+ environment: string | undefined;
219
+ routes: {
220
+ data: string;
221
+ metadata: string;
222
+ auth: string;
223
+ graphql: string | undefined;
224
+ storage: string | undefined;
225
+ analytics: string | undefined;
226
+ hub: string | undefined;
227
+ };
228
+ features: {
229
+ graphql: boolean;
230
+ search: boolean;
231
+ websockets: boolean;
232
+ files: boolean;
233
+ analytics: boolean;
234
+ hub: boolean;
235
+ };
236
+ locale: {
237
+ default: string;
238
+ supported: string[];
239
+ timezone: string;
240
+ };
241
+ };
242
+ /**
243
+ * Handles GraphQL requests
244
+ */
245
+ handleGraphQL(body: {
246
+ query: string;
247
+ variables?: any;
248
+ }, context: HttpProtocolContext): Promise<any>;
249
+ /**
250
+ * Handles Auth requests
251
+ * path: sub-path after /auth/
252
+ */
253
+ handleAuth(path: string, method: string, body: any, context: HttpProtocolContext): Promise<HttpDispatcherResult>;
254
+ /**
255
+ * Handles Metadata requests
256
+ * Standard: /metadata/:type/:name
257
+ * Fallback for backward compat: /metadata (all objects), /metadata/:objectName (get object)
258
+ */
259
+ handleMetadata(path: string, context: HttpProtocolContext, method?: string, body?: any): Promise<HttpDispatcherResult>;
260
+ /**
261
+ * Handles Data requests
262
+ * path: sub-path after /data/ (e.g. "contacts", "contacts/123", "contacts/query")
263
+ */
264
+ handleData(path: string, method: string, body: any, query: any, context: HttpProtocolContext): Promise<HttpDispatcherResult>;
265
+ /**
266
+ * Handles Analytics requests
267
+ * path: sub-path after /analytics/
268
+ */
269
+ handleAnalytics(path: string, method: string, body: any, context: HttpProtocolContext): Promise<HttpDispatcherResult>;
270
+ /**
271
+ * Handles Hub requests
272
+ * path: sub-path after /hub/
273
+ */
274
+ handleHub(path: string, method: string, body: any, query: any, context: HttpProtocolContext): Promise<HttpDispatcherResult>;
275
+ /**
276
+ * Handles Storage requests
277
+ * path: sub-path after /storage/
278
+ */
279
+ handleStorage(path: string, method: string, file: any, context: HttpProtocolContext): Promise<HttpDispatcherResult>;
280
+ /**
281
+ * Handles Automation requests
282
+ * path: sub-path after /automation/
283
+ */
284
+ handleAutomation(path: string, method: string, body: any, context: HttpProtocolContext): Promise<HttpDispatcherResult>;
285
+ private getServicesMap;
286
+ private getService;
287
+ private capitalize;
288
+ /**
289
+ * Main Dispatcher Entry Point
290
+ * Routes the request to the appropriate handler based on path and precedence
291
+ */
292
+ dispatch(method: string, path: string, body: any, query: any, context: HttpProtocolContext): Promise<HttpDispatcherResult>;
293
+ /**
294
+ * Handles Custom API Endpoints defined in metadata
295
+ */
296
+ handleApiEndpoint(path: string, method: string, body: any, query: any, context: HttpProtocolContext): Promise<HttpDispatcherResult>;
297
+ }
298
+
299
+ type RouteHandlerMetadata = System.RouteHandlerMetadata;
300
+ type HttpMethod = z.infer<typeof Shared.HttpMethod>;
301
+ /**
302
+ * Route Entry
303
+ * Internal representation of registered routes
304
+ */
305
+ interface RouteEntry {
306
+ method: HttpMethod;
307
+ path: string;
308
+ handler: RouteHandler;
309
+ metadata?: RouteHandlerMetadata['metadata'];
310
+ security?: RouteHandlerMetadata['security'];
311
+ }
312
+ /**
313
+ * RouteManager
314
+ *
315
+ * Manages route registration and organization for HTTP servers.
316
+ * Provides:
317
+ * - Route registration with metadata
318
+ * - Route lookup and querying
319
+ * - Bulk route registration
320
+ * - Route grouping by prefix
321
+ *
322
+ * @example
323
+ * const manager = new RouteManager(server);
324
+ *
325
+ * // Register individual route
326
+ * manager.register({
327
+ * method: 'GET',
328
+ * path: '/api/users/:id',
329
+ * handler: getUserHandler,
330
+ * metadata: {
331
+ * summary: 'Get user by ID',
332
+ * tags: ['users']
333
+ * }
334
+ * });
335
+ *
336
+ * // Register route group
337
+ * manager.group('/api/users', (group) => {
338
+ * group.get('/', listUsersHandler);
339
+ * group.post('/', createUserHandler);
340
+ * group.get('/:id', getUserHandler);
341
+ * });
342
+ */
343
+ declare class RouteManager {
344
+ private server;
345
+ private routes;
346
+ constructor(server: IHttpServer);
347
+ /**
348
+ * Register a route
349
+ * @param entry - Route entry with method, path, handler, and metadata
350
+ */
351
+ register(entry: Omit<RouteEntry, 'handler'> & {
352
+ handler: RouteHandler | string;
353
+ }): void;
354
+ /**
355
+ * Register multiple routes
356
+ * @param entries - Array of route entries
357
+ */
358
+ registerMany(entries: Array<Omit<RouteEntry, 'handler'> & {
359
+ handler: RouteHandler | string;
360
+ }>): void;
361
+ /**
362
+ * Unregister a route
363
+ * @param method - HTTP method
364
+ * @param path - Route path
365
+ */
366
+ unregister(method: HttpMethod, path: string): void;
367
+ /**
368
+ * Get route by method and path
369
+ * @param method - HTTP method
370
+ * @param path - Route path
371
+ */
372
+ get(method: HttpMethod, path: string): RouteEntry | undefined;
373
+ /**
374
+ * Get all routes
375
+ */
376
+ getAll(): RouteEntry[];
377
+ /**
378
+ * Get routes by method
379
+ * @param method - HTTP method
380
+ */
381
+ getByMethod(method: HttpMethod): RouteEntry[];
382
+ /**
383
+ * Get routes by path prefix
384
+ * @param prefix - Path prefix
385
+ */
386
+ getByPrefix(prefix: string): RouteEntry[];
387
+ /**
388
+ * Get routes by tag
389
+ * @param tag - Tag name
390
+ */
391
+ getByTag(tag: string): RouteEntry[];
392
+ /**
393
+ * Create a route group with common prefix
394
+ * @param prefix - Common path prefix
395
+ * @param configure - Function to configure routes in the group
396
+ */
397
+ group(prefix: string, configure: (group: RouteGroupBuilder) => void): void;
398
+ /**
399
+ * Get route count
400
+ */
401
+ count(): number;
402
+ /**
403
+ * Clear all routes
404
+ */
405
+ clear(): void;
406
+ /**
407
+ * Get route key for storage
408
+ */
409
+ private getRouteKey;
410
+ /**
411
+ * Register route with underlying server
412
+ */
413
+ private registerWithServer;
414
+ }
415
+ /**
416
+ * RouteGroupBuilder
417
+ *
418
+ * Builder for creating route groups with common prefix
419
+ */
420
+ declare class RouteGroupBuilder {
421
+ private manager;
422
+ private prefix;
423
+ constructor(manager: RouteManager, prefix: string);
424
+ /**
425
+ * Register GET route in group
426
+ */
427
+ get(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this;
428
+ /**
429
+ * Register POST route in group
430
+ */
431
+ post(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this;
432
+ /**
433
+ * Register PUT route in group
434
+ */
435
+ put(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this;
436
+ /**
437
+ * Register PATCH route in group
438
+ */
439
+ patch(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this;
440
+ /**
441
+ * Register DELETE route in group
442
+ */
443
+ delete(path: string, handler: RouteHandler, metadata?: RouteHandlerMetadata['metadata']): this;
444
+ /**
445
+ * Resolve full path with prefix
446
+ */
447
+ private resolvePath;
448
+ }
449
+
450
+ /**
451
+ * RestServer
452
+ *
453
+ * Provides automatic REST API endpoint generation for ObjectStack.
454
+ * Generates standard RESTful CRUD endpoints, metadata endpoints, and batch operations
455
+ * based on the configured protocol provider.
456
+ *
457
+ * Features:
458
+ * - Automatic CRUD endpoint generation (GET, POST, PUT, PATCH, DELETE)
459
+ * - Metadata API endpoints (/meta)
460
+ * - Batch operation endpoints (/batch, /createMany, /updateMany, /deleteMany)
461
+ * - Discovery endpoint
462
+ * - Configurable path prefixes and patterns
463
+ *
464
+ * @example
465
+ * const restServer = new RestServer(httpServer, protocolProvider, {
466
+ * api: {
467
+ * version: 'v1',
468
+ * basePath: '/api'
469
+ * },
470
+ * crud: {
471
+ * dataPrefix: '/data'
472
+ * }
473
+ * });
474
+ *
475
+ * restServer.registerRoutes();
476
+ */
477
+ declare class RestServer {
478
+ private protocol;
479
+ private config;
480
+ private routeManager;
481
+ constructor(server: IHttpServer, protocol: ObjectStackProtocol, config?: RestServerConfig);
482
+ /**
483
+ * Normalize configuration with defaults
484
+ */
485
+ private normalizeConfig;
486
+ /**
487
+ * Get the full API base path
488
+ */
489
+ private getApiBasePath;
490
+ /**
491
+ * Register all REST API routes
492
+ */
493
+ registerRoutes(): void;
494
+ /**
495
+ * Register discovery endpoints
496
+ */
497
+ private registerDiscoveryEndpoints;
498
+ /**
499
+ * Register metadata endpoints
500
+ */
501
+ private registerMetadataEndpoints;
502
+ /**
503
+ * Register CRUD endpoints for data operations
504
+ */
505
+ private registerCrudEndpoints;
506
+ /**
507
+ * Register batch operation endpoints
508
+ */
509
+ private registerBatchEndpoints;
510
+ /**
511
+ * Get the route manager
512
+ */
513
+ getRouteManager(): RouteManager;
514
+ /**
515
+ * Get all registered routes
516
+ */
517
+ getRoutes(): RouteEntry[];
518
+ }
519
+
520
+ /**
521
+ * Middleware Entry
522
+ * Internal representation of registered middleware
523
+ */
524
+ interface MiddlewareEntry {
525
+ name: string;
526
+ type: MiddlewareType;
527
+ middleware: Middleware;
528
+ order: number;
529
+ enabled: boolean;
530
+ paths?: {
531
+ include?: string[];
532
+ exclude?: string[];
533
+ };
534
+ }
535
+ /**
536
+ * MiddlewareManager
537
+ *
538
+ * Manages middleware registration, ordering, and execution.
539
+ * Provides fine-grained control over middleware chains with:
540
+ * - Execution order management
541
+ * - Path-based filtering
542
+ * - Enable/disable individual middleware
543
+ * - Middleware categorization by type
544
+ *
545
+ * @example
546
+ * const manager = new MiddlewareManager();
547
+ *
548
+ * // Register middleware with configuration
549
+ * manager.register({
550
+ * name: 'auth',
551
+ * type: 'authentication',
552
+ * order: 10,
553
+ * paths: { exclude: ['/health', '/metrics'] }
554
+ * }, authMiddleware);
555
+ *
556
+ * // Get sorted middleware chain
557
+ * const chain = manager.getMiddlewareChain();
558
+ * chain.forEach(mw => server.use(mw));
559
+ */
560
+ declare class MiddlewareManager {
561
+ private middlewares;
562
+ constructor();
563
+ /**
564
+ * Register middleware with configuration
565
+ * @param config - Middleware configuration
566
+ * @param middleware - Middleware function
567
+ */
568
+ register(config: MiddlewareConfig, middleware: Middleware): void;
569
+ /**
570
+ * Unregister middleware by name
571
+ * @param name - Middleware name
572
+ */
573
+ unregister(name: string): void;
574
+ /**
575
+ * Enable middleware by name
576
+ * @param name - Middleware name
577
+ */
578
+ enable(name: string): void;
579
+ /**
580
+ * Disable middleware by name
581
+ * @param name - Middleware name
582
+ */
583
+ disable(name: string): void;
584
+ /**
585
+ * Get middleware entry by name
586
+ * @param name - Middleware name
587
+ */
588
+ get(name: string): MiddlewareEntry | undefined;
589
+ /**
590
+ * Get all middleware entries
591
+ */
592
+ getAll(): MiddlewareEntry[];
593
+ /**
594
+ * Get middleware by type
595
+ * @param type - Middleware type
596
+ */
597
+ getByType(type: MiddlewareType): MiddlewareEntry[];
598
+ /**
599
+ * Get middleware chain sorted by order
600
+ * Returns only enabled middleware
601
+ */
602
+ getMiddlewareChain(): Middleware[];
603
+ /**
604
+ * Get middleware chain with path filtering
605
+ * @param path - Request path to match against
606
+ */
607
+ getMiddlewareChainForPath(path: string): Middleware[];
608
+ /**
609
+ * Match path against pattern (simple glob matching)
610
+ * @param path - Request path
611
+ * @param pattern - Pattern to match (supports * wildcard)
612
+ */
613
+ private matchPath;
614
+ /**
615
+ * Clear all middleware
616
+ */
617
+ clear(): void;
618
+ /**
619
+ * Get middleware count
620
+ */
621
+ count(): number;
622
+ /**
623
+ * Create a composite middleware from the chain
624
+ * This can be used to apply all middleware at once
625
+ */
626
+ createCompositeMiddleware(): Middleware;
627
+ }
628
+
629
+ export { type ApiRegistryConfig, AppPlugin, DriverPlugin, HttpDispatcher, type HttpDispatcherResult, type HttpProtocolContext, HttpServer, MiddlewareManager, RestServer, type RouteEntry, RouteGroupBuilder, RouteManager, Runtime, type RuntimeConfig, createApiRegistryPlugin };