@objectstack/runtime 0.9.0 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @objectstack/runtime
2
2
 
3
+ ## 0.9.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @objectstack/spec@0.9.2
9
+ - @objectstack/core@0.9.2
10
+ - @objectstack/types@0.9.2
11
+
12
+ ## 0.9.1
13
+
14
+ ### Patch Changes
15
+
16
+ - Patch release for maintenance and stability improvements. All packages updated with unified versioning.
17
+ - Updated dependencies
18
+ - @objectstack/spec@0.9.1
19
+ - @objectstack/core@0.9.1
20
+ - @objectstack/types@0.9.1
21
+
3
22
  ## 0.8.2
4
23
 
5
24
  ### Patch Changes
package/README.md CHANGED
@@ -12,6 +12,16 @@ The runtime package provides the **Standard Library** for the ObjectStack Operat
12
12
  - **Core Integration**: Re-exports `ObjectKernel` for convenience
13
13
  - **Capability Contracts**: Abstract interfaces for HTTP server and data persistence
14
14
 
15
+ ## 🤖 AI Development Context
16
+
17
+ **Role**: Server Runtime & REST API
18
+ **Usage**:
19
+ - Use `RestServer` to spawn HTTP endpoints.
20
+ - Configures the HTTP layer.
21
+
22
+ **Key Concepts**:
23
+ - `RestServer`: Generates `/api/*` endpoints from ObjectQL schemas.
24
+
15
25
  ## Installation
16
26
 
17
27
  ```bash
@@ -268,6 +278,302 @@ See the `examples/` directory for complete examples:
268
278
  4. **Use hooks**: Decouple plugins with event system
269
279
  5. **Handle errors**: Implement proper error handling in lifecycle methods
270
280
 
281
+ ## Common Plugin Patterns
282
+
283
+ ### Service Provider Pattern
284
+
285
+ ```typescript
286
+ import { Plugin, PluginContext } from '@objectstack/core';
287
+
288
+ export class DatabasePlugin implements Plugin {
289
+ name = 'database';
290
+ private connection: any;
291
+
292
+ async init(ctx: PluginContext) {
293
+ // Initialize connection
294
+ this.connection = await createConnection({
295
+ host: 'localhost',
296
+ database: 'myapp'
297
+ });
298
+
299
+ // Register as service
300
+ ctx.registerService('database', this.connection);
301
+
302
+ ctx.logger.info('Database connected');
303
+ }
304
+
305
+ async destroy() {
306
+ // Cleanup
307
+ await this.connection.close();
308
+ }
309
+ }
310
+ ```
311
+
312
+ ### Service Consumer Pattern
313
+
314
+ ```typescript
315
+ import { Plugin, PluginContext } from '@objectstack/core';
316
+
317
+ export class RepositoryPlugin implements Plugin {
318
+ name = 'repository';
319
+ dependencies = ['database']; // Ensure database loads first
320
+
321
+ async init(ctx: PluginContext) {
322
+ // Get dependency
323
+ const db = ctx.getService('database');
324
+
325
+ // Create and register repository
326
+ const repo = new UserRepository(db);
327
+ ctx.registerService('user-repository', repo);
328
+ }
329
+ }
330
+ ```
331
+
332
+ ### Event-Driven Pattern
333
+
334
+ ```typescript
335
+ import { Plugin, PluginContext } from '@objectstack/core';
336
+
337
+ // Publisher
338
+ export class DataPlugin implements Plugin {
339
+ name = 'data';
340
+
341
+ async init(ctx: PluginContext) {
342
+ const service = {
343
+ async create(entity: string, data: any) {
344
+ const result = await db.insert(entity, data);
345
+
346
+ // Trigger event
347
+ await ctx.trigger('data:created', { entity, data: result });
348
+
349
+ return result;
350
+ }
351
+ };
352
+
353
+ ctx.registerService('data', service);
354
+ }
355
+ }
356
+
357
+ // Subscriber
358
+ export class AuditPlugin implements Plugin {
359
+ name = 'audit';
360
+ dependencies = ['data'];
361
+
362
+ async init(ctx: PluginContext) {
363
+ // Listen to events
364
+ ctx.hook('data:created', async ({ entity, data }) => {
365
+ ctx.logger.info(`Audit: ${entity} created`, { id: data.id });
366
+
367
+ await auditLog.write({
368
+ action: 'create',
369
+ entity,
370
+ entityId: data.id,
371
+ timestamp: new Date()
372
+ });
373
+ });
374
+ }
375
+ }
376
+ ```
377
+
378
+ ### Configuration Pattern
379
+
380
+ ```typescript
381
+ import { Plugin, PluginContext } from '@objectstack/core';
382
+ import { z } from 'zod';
383
+
384
+ const ConfigSchema = z.object({
385
+ apiKey: z.string(),
386
+ endpoint: z.string().url(),
387
+ timeout: z.number().default(5000)
388
+ });
389
+
390
+ export class ApiPlugin implements Plugin {
391
+ name = 'api-client';
392
+
393
+ constructor(private config: z.infer<typeof ConfigSchema>) {
394
+ // Validate config
395
+ ConfigSchema.parse(config);
396
+ }
397
+
398
+ async init(ctx: PluginContext) {
399
+ const client = new ApiClient({
400
+ apiKey: this.config.apiKey,
401
+ endpoint: this.config.endpoint,
402
+ timeout: this.config.timeout
403
+ });
404
+
405
+ ctx.registerService('api-client', client);
406
+ }
407
+ }
408
+
409
+ // Usage
410
+ kernel.use(new ApiPlugin({
411
+ apiKey: process.env.API_KEY,
412
+ endpoint: 'https://api.example.com',
413
+ timeout: 10000
414
+ }));
415
+ ```
416
+
417
+ ### Factory Pattern
418
+
419
+ ```typescript
420
+ import { Plugin, PluginContext } from '@objectstack/core';
421
+
422
+ export class ConnectionPoolPlugin implements Plugin {
423
+ name = 'connection-pool';
424
+ private pool: any;
425
+
426
+ async init(ctx: PluginContext) {
427
+ this.pool = {
428
+ connections: new Map(),
429
+
430
+ getConnection(name: string) {
431
+ if (!this.connections.has(name)) {
432
+ this.connections.set(name, createConnection(name));
433
+ }
434
+ return this.connections.get(name);
435
+ },
436
+
437
+ closeAll() {
438
+ for (const conn of this.connections.values()) {
439
+ conn.close();
440
+ }
441
+ this.connections.clear();
442
+ }
443
+ };
444
+
445
+ ctx.registerService('connection-pool', this.pool);
446
+ }
447
+
448
+ async destroy() {
449
+ // Use stored reference from init phase
450
+ if (this.pool) {
451
+ this.pool.closeAll();
452
+ }
453
+ }
454
+ }
455
+ ```
456
+
457
+ ### Middleware Pattern
458
+
459
+ ```typescript
460
+ import { Plugin, PluginContext } from '@objectstack/core';
461
+
462
+ export class LoggingMiddleware implements Plugin {
463
+ name = 'logging-middleware';
464
+ dependencies = ['http-server'];
465
+
466
+ async start(ctx: PluginContext) {
467
+ const server = ctx.getService('http-server');
468
+
469
+ // Register middleware
470
+ server.use(async (req, res, next) => {
471
+ const start = Date.now();
472
+
473
+ ctx.logger.info('Request', {
474
+ method: req.method,
475
+ path: req.path
476
+ });
477
+
478
+ await next();
479
+
480
+ const duration = Date.now() - start;
481
+ ctx.logger.info('Response', {
482
+ method: req.method,
483
+ path: req.path,
484
+ status: res.statusCode,
485
+ duration
486
+ });
487
+ });
488
+ }
489
+ }
490
+ ```
491
+
492
+ ### Lazy Loading Pattern
493
+
494
+ ```typescript
495
+ import { Plugin, PluginContext } from '@objectstack/core';
496
+
497
+ export class HeavyServicePlugin implements Plugin {
498
+ name = 'heavy-service';
499
+ private instance: any = null;
500
+
501
+ async init(ctx: PluginContext) {
502
+ // Register factory instead of instance
503
+ const factory = {
504
+ async getInstance() {
505
+ if (!this.instance) {
506
+ ctx.logger.info('Lazy loading heavy service...');
507
+ this.instance = await loadHeavyService();
508
+ }
509
+ return this.instance;
510
+ }
511
+ };
512
+
513
+ ctx.registerService('heavy-service', factory);
514
+ }
515
+ }
516
+
517
+ // Usage
518
+ const factory = kernel.getService('heavy-service');
519
+ const service = await factory.getInstance(); // Loaded only when needed
520
+ ```
521
+
522
+ ### Health Check Pattern
523
+
524
+ ```typescript
525
+ import { Plugin, PluginContext } from '@objectstack/core';
526
+
527
+ export class HealthCheckPlugin implements Plugin {
528
+ name = 'health-check';
529
+ dependencies = ['http-server', 'database', 'cache'];
530
+
531
+ async start(ctx: PluginContext) {
532
+ const server = ctx.getService('http-server');
533
+
534
+ server.get('/health', async (req, res) => {
535
+ const checks = await Promise.all([
536
+ this.checkDatabase(ctx),
537
+ this.checkCache(ctx),
538
+ this.checkDiskSpace()
539
+ ]);
540
+
541
+ const healthy = checks.every(c => c.healthy);
542
+
543
+ res.status(healthy ? 200 : 503).json({
544
+ status: healthy ? 'healthy' : 'unhealthy',
545
+ checks
546
+ });
547
+ });
548
+ }
549
+
550
+ private async checkDatabase(ctx: PluginContext) {
551
+ try {
552
+ const db = ctx.getService('database');
553
+ await db.ping();
554
+ return { name: 'database', healthy: true };
555
+ } catch (error) {
556
+ return { name: 'database', healthy: false, error: error.message };
557
+ }
558
+ }
559
+
560
+ private async checkCache(ctx: PluginContext) {
561
+ try {
562
+ const cache = ctx.getService('cache');
563
+ await cache.ping();
564
+ return { name: 'cache', healthy: true };
565
+ } catch (error) {
566
+ return { name: 'cache', healthy: false, error: error.message };
567
+ }
568
+ }
569
+
570
+ private async checkDiskSpace() {
571
+ // Implementation
572
+ return { name: 'disk', healthy: true };
573
+ }
574
+ }
575
+ ```
576
+
271
577
  ## Documentation
272
578
 
273
579
  - [MiniKernel Guide](../../MINI_KERNEL_GUIDE.md) - Complete API documentation and patterns
package/dist/index.d.ts CHANGED
@@ -4,5 +4,6 @@ export { AppPlugin } from './app-plugin.js';
4
4
  export { HttpServer } from './http-server.js';
5
5
  export { RestServer } from './rest-server.js';
6
6
  export { RouteManager, RouteGroupBuilder } from './route-manager.js';
7
+ export type { RouteEntry } from './route-manager.js';
7
8
  export { MiddlewareManager } from './middleware.js';
8
9
  export * from '@objectstack/core';
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@objectstack/runtime",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "description": "ObjectStack Core Runtime & Query Engine",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "dependencies": {
9
- "@objectstack/core": "0.9.0",
10
- "@objectstack/types": "0.9.0",
11
- "@objectstack/spec": "0.9.0"
9
+ "@objectstack/core": "0.9.2",
10
+ "@objectstack/spec": "0.9.2",
11
+ "@objectstack/types": "0.9.2"
12
12
  },
13
13
  "devDependencies": {
14
14
  "typescript": "^5.0.0"
package/src/index.ts CHANGED
@@ -9,6 +9,7 @@ export { AppPlugin } from './app-plugin.js';
9
9
  export { HttpServer } from './http-server.js';
10
10
  export { RestServer } from './rest-server.js';
11
11
  export { RouteManager, RouteGroupBuilder } from './route-manager.js';
12
+ export type { RouteEntry } from './route-manager.js';
12
13
  export { MiddlewareManager } from './middleware.js';
13
14
 
14
15
  // Export Types