@objectstack/core 0.9.1 → 1.0.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.
Files changed (94) hide show
  1. package/{ENHANCED_FEATURES.md → ADVANCED_FEATURES.md} +13 -13
  2. package/CHANGELOG.md +21 -0
  3. package/PHASE2_IMPLEMENTATION.md +388 -0
  4. package/README.md +12 -341
  5. package/REFACTORING_SUMMARY.md +40 -0
  6. package/dist/api-registry-plugin.test.js +23 -21
  7. package/dist/api-registry.test.js +2 -2
  8. package/dist/dependency-resolver.d.ts +62 -0
  9. package/dist/dependency-resolver.d.ts.map +1 -0
  10. package/dist/dependency-resolver.js +317 -0
  11. package/dist/dependency-resolver.test.d.ts +2 -0
  12. package/dist/dependency-resolver.test.d.ts.map +1 -0
  13. package/dist/dependency-resolver.test.js +241 -0
  14. package/dist/health-monitor.d.ts +65 -0
  15. package/dist/health-monitor.d.ts.map +1 -0
  16. package/dist/health-monitor.js +269 -0
  17. package/dist/health-monitor.test.d.ts +2 -0
  18. package/dist/health-monitor.test.d.ts.map +1 -0
  19. package/dist/health-monitor.test.js +68 -0
  20. package/dist/hot-reload.d.ts +79 -0
  21. package/dist/hot-reload.d.ts.map +1 -0
  22. package/dist/hot-reload.js +313 -0
  23. package/dist/index.d.ts +4 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +5 -1
  26. package/dist/kernel-base.d.ts +2 -2
  27. package/dist/kernel-base.js +2 -2
  28. package/dist/kernel.d.ts +89 -31
  29. package/dist/kernel.d.ts.map +1 -1
  30. package/dist/kernel.js +430 -73
  31. package/dist/kernel.test.js +375 -122
  32. package/dist/lite-kernel.d.ts +55 -0
  33. package/dist/lite-kernel.d.ts.map +1 -0
  34. package/dist/lite-kernel.js +112 -0
  35. package/dist/lite-kernel.test.d.ts +2 -0
  36. package/dist/lite-kernel.test.d.ts.map +1 -0
  37. package/dist/lite-kernel.test.js +161 -0
  38. package/dist/logger.d.ts +2 -2
  39. package/dist/logger.d.ts.map +1 -1
  40. package/dist/logger.js +26 -7
  41. package/dist/plugin-loader.d.ts +15 -0
  42. package/dist/plugin-loader.d.ts.map +1 -1
  43. package/dist/plugin-loader.js +40 -10
  44. package/dist/plugin-loader.test.js +9 -0
  45. package/dist/security/index.d.ts +3 -0
  46. package/dist/security/index.d.ts.map +1 -1
  47. package/dist/security/index.js +4 -0
  48. package/dist/security/permission-manager.d.ts +96 -0
  49. package/dist/security/permission-manager.d.ts.map +1 -0
  50. package/dist/security/permission-manager.js +235 -0
  51. package/dist/security/permission-manager.test.d.ts +2 -0
  52. package/dist/security/permission-manager.test.d.ts.map +1 -0
  53. package/dist/security/permission-manager.test.js +220 -0
  54. package/dist/security/plugin-permission-enforcer.d.ts +1 -1
  55. package/dist/security/sandbox-runtime.d.ts +115 -0
  56. package/dist/security/sandbox-runtime.d.ts.map +1 -0
  57. package/dist/security/sandbox-runtime.js +310 -0
  58. package/dist/security/security-scanner.d.ts +92 -0
  59. package/dist/security/security-scanner.d.ts.map +1 -0
  60. package/dist/security/security-scanner.js +273 -0
  61. package/examples/{enhanced-kernel-example.ts → kernel-features-example.ts} +6 -6
  62. package/examples/phase2-integration.ts +355 -0
  63. package/package.json +3 -2
  64. package/src/api-registry-plugin.test.ts +23 -21
  65. package/src/api-registry.test.ts +2 -2
  66. package/src/dependency-resolver.test.ts +287 -0
  67. package/src/dependency-resolver.ts +388 -0
  68. package/src/health-monitor.test.ts +81 -0
  69. package/src/health-monitor.ts +316 -0
  70. package/src/hot-reload.ts +388 -0
  71. package/src/index.ts +6 -1
  72. package/src/kernel-base.ts +2 -2
  73. package/src/kernel.test.ts +471 -134
  74. package/src/kernel.ts +518 -76
  75. package/src/lite-kernel.test.ts +200 -0
  76. package/src/lite-kernel.ts +135 -0
  77. package/src/logger.ts +28 -7
  78. package/src/plugin-loader.test.ts +10 -1
  79. package/src/plugin-loader.ts +49 -13
  80. package/src/security/index.ts +19 -0
  81. package/src/security/permission-manager.test.ts +256 -0
  82. package/src/security/permission-manager.ts +336 -0
  83. package/src/security/plugin-permission-enforcer.test.ts +1 -1
  84. package/src/security/plugin-permission-enforcer.ts +1 -1
  85. package/src/security/sandbox-runtime.ts +432 -0
  86. package/src/security/security-scanner.ts +365 -0
  87. package/dist/enhanced-kernel.d.ts +0 -103
  88. package/dist/enhanced-kernel.d.ts.map +0 -1
  89. package/dist/enhanced-kernel.js +0 -403
  90. package/dist/enhanced-kernel.test.d.ts +0 -2
  91. package/dist/enhanced-kernel.test.d.ts.map +0 -1
  92. package/dist/enhanced-kernel.test.js +0 -412
  93. package/src/enhanced-kernel.test.ts +0 -535
  94. package/src/enhanced-kernel.ts +0 -496
package/README.md CHANGED
@@ -1,364 +1,35 @@
1
1
  # @objectstack/core
2
2
 
3
- Microkernel Core for ObjectStack - A lightweight, plugin-based architecture with enterprise-grade features.
4
-
5
- ## Overview
6
-
7
- This package defines the fundamental runtime mechanics of the ObjectStack architecture:
8
- 1. **Dependency Injection (DI)**: Advanced service registry with factory functions and lifecycle management
9
- 2. **Plugin Lifecycle**: `init` (Registration) -> `start` (Execution) -> `destroy` (Cleanup)
10
- 3. **Event Bus**: Simple hook system (`hook`, `trigger`) for event-driven communication
11
- 4. **Configurable Logging**: Universal logger using [Pino](https://github.com/pinojs/pino) for Node.js and simple console for browsers
12
- 5. **Enhanced Features**: Version compatibility, health checks, timeout control, graceful shutdown, and more
13
-
14
- It is completely agnostic of "Data", "HTTP", or "Apps". It only knows `Plugin` and `Service`.
3
+ The **Kernel** of the ObjectStack architecture. It provides the fundamental building blocks for a modular, plugin-based system.
15
4
 
16
5
  ## Features
17
6
 
18
- ### Core Features
19
- - **Plugin-based Architecture**: Modular microkernel that manages plugin lifecycle
20
- - **Service Registry**: Dependency injection for inter-plugin communication
21
- - **Event/Hook System**: Flexible event-driven communication
22
- - **High-Performance Logging**:
23
- - Node.js: Powered by [Pino](https://github.com/pinojs/pino) - extremely fast, low-overhead structured logging
24
- - Browser: Lightweight console-based logger
25
- - **Environment Detection**: Automatic runtime detection (Node.js/browser)
26
- - **Dependency Resolution**: Automatic topological sorting of plugin dependencies
27
- - **Security**: Automatic sensitive data redaction in logs
28
-
29
- ### Enhanced Features (EnhancedObjectKernel)
30
- - **Async Plugin Loading**: Load plugins asynchronously with validation
31
- - **Version Compatibility**: Semantic versioning support and validation
32
- - **Plugin Signatures**: Security verification (extensible)
33
- - **Configuration Validation**: Zod-based schema validation for plugin configs
34
- - **Service Factories**: Factory-based service instantiation with lifecycle control
35
- - **Service Lifecycles**: Singleton, Transient, and Scoped service management
36
- - **Circular Dependency Detection**: Automatic detection and reporting
37
- - **Lazy Loading**: Services created on-demand
38
- - **Timeout Control**: Configurable timeouts for plugin initialization
39
- - **Failure Rollback**: Automatic rollback on startup failures
40
- - **Health Checks**: Monitor plugin health at runtime
41
- - **Performance Metrics**: Track plugin startup times
42
- - **Graceful Shutdown**: Proper cleanup with timeout control
7
+ - **ObjectKernel**: A robust Dependency Injection (DI) container and plugin manager.
8
+ - **Plugin Architecture**: A standard interface (`Plugin`) with lifecycle hooks (`init`, `start`, `stop`).
9
+ - **Service Management**: Register and resolve services with type safety.
10
+ - **Logging**: Structured logging interface with swappable backends.
43
11
 
44
12
  ## Installation
45
13
 
46
14
  ```bash
47
- npm install @objectstack/core
48
- # or
49
15
  pnpm add @objectstack/core
50
16
  ```
51
17
 
52
- ## Quick Start
53
-
54
- ```typescript
55
- import { ObjectKernel, Plugin, PluginContext } from '@objectstack/core';
56
-
57
- // 1. Define a Plugin
58
- const myPlugin: Plugin = {
59
- name: 'my-plugin',
60
-
61
- async init(ctx: PluginContext) {
62
- ctx.logger.info('Initializing plugin');
63
- ctx.registerService('my-service', { hello: 'world' });
64
- }
65
- };
66
-
67
- // 2. Boot Kernel with logging config
68
- const kernel = new ObjectKernel({
69
- logger: {
70
- level: 'info',
71
- format: 'pretty'
72
- }
73
- });
74
-
75
- kernel.use(myPlugin);
76
- await kernel.bootstrap();
77
-
78
- // 3. Use Service
79
- const service = kernel.getService('my-service');
80
-
81
- // 4. Cleanup
82
- await kernel.shutdown();
83
- ```
84
-
85
- ## 🤖 AI Quick Reference
86
-
87
- **For AI Agents:** This package implements a microkernel architecture. Key concepts:
88
-
89
- 1. **Plugin Lifecycle**: `init()` → `start()` → `destroy()`
90
- 2. **Service Registry**: Share functionality via `ctx.registerService(name, service)` and `ctx.getService(name)`
91
- 3. **Dependencies**: Declare plugin dependencies for automatic load ordering
92
- 4. **Hooks/Events**: Decouple plugins with `ctx.hook(event, handler)` and `ctx.trigger(event, ...args)`
93
- 5. **Logger**: Always use `ctx.logger` for consistent, structured logging
94
-
95
- **Common Plugin Pattern:**
96
- ```typescript
97
- const plugin: Plugin = {
98
- name: 'my-plugin',
99
- dependencies: ['other-plugin'], // Load after these plugins
100
-
101
- async init(ctx: PluginContext) {
102
- // Register services and hooks
103
- const otherService = ctx.getService('other-service');
104
- ctx.registerService('my-service', new MyService(otherService));
105
- ctx.hook('data:created', async (data) => { /* ... */ });
106
- },
107
-
108
- async start(ctx: PluginContext) {
109
- // Execute business logic
110
- const service = ctx.getService('my-service');
111
- await service.initialize();
112
- },
113
-
114
- async destroy() {
115
- // Cleanup resources
116
- await service.close();
117
- }
118
- };
119
- ```
120
-
121
- ## Configurable Logger
122
-
123
- The logger uses **[Pino](https://github.com/pinojs/pino)** for Node.js environments (high-performance, low-overhead) and a simple console-based logger for browsers. It automatically detects the runtime environment.
124
-
125
- ### Why Pino?
126
-
127
- - **Fast**: One of the fastest Node.js loggers available
128
- - **Low Overhead**: Minimal performance impact on your application
129
- - **Structured Logging**: Native JSON output for log aggregation tools
130
- - **Production Ready**: Battle-tested in production environments
131
- - **Feature Rich**: Automatic log rotation, transports, child loggers, and more
132
-
133
- ### Logger Configuration
18
+ ## Basic Usage
134
19
 
135
20
  ```typescript
136
- const kernel = new ObjectKernel({
137
- logger: {
138
- level: 'debug', // 'debug' | 'info' | 'warn' | 'error' | 'fatal'
139
- format: 'pretty', // 'json' | 'text' | 'pretty'
140
- sourceLocation: true, // Include file/line numbers
141
- redact: ['password', 'token', 'apiKey'], // Keys to redact
142
- file: './logs/app.log', // Node.js only
143
- rotation: { // File rotation (Node.js only)
144
- maxSize: '10m',
145
- maxFiles: 5
146
- }
147
- }
148
- });
149
- ```
21
+ import { ObjectKernel } from '@objectstack/core';
150
22
 
151
- ### Using Logger in Plugins
23
+ const kernel = new ObjectKernel();
152
24
 
153
- ```typescript
154
- const myPlugin: Plugin = {
25
+ // Register a simple plugin
26
+ kernel.use({
155
27
  name: 'my-plugin',
156
-
157
- init: async (ctx: PluginContext) => {
158
- // Basic logging
159
- ctx.logger.info('Plugin initialized');
160
- ctx.logger.debug('Debug info', { details: 'data' });
161
- ctx.logger.warn('Warning message');
162
- ctx.logger.error('Error occurred', new Error('Oops'));
163
-
164
- // Sensitive data is automatically redacted
165
- ctx.logger.info('User login', {
166
- username: 'john',
167
- password: 'secret123' // Logged as '***REDACTED***'
168
- });
169
- }
170
- };
171
- ```
172
-
173
- ### Standalone Logger
174
-
175
- ```typescript
176
- import { createLogger } from '@objectstack/core';
177
-
178
- const logger = createLogger({
179
- level: 'info',
180
- format: 'json'
181
- });
182
-
183
- logger.info('Application started');
184
-
185
- // Child logger with context
186
- const requestLogger = logger.child({
187
- requestId: '123',
188
- userId: 'user-456'
189
- });
190
-
191
- requestLogger.info('Processing request');
192
-
193
- // Distributed tracing
194
- const tracedLogger = logger.withTrace('trace-id-123', 'span-id-456');
195
-
196
- // Cleanup
197
- await logger.destroy();
198
- ```
199
-
200
- ## Log Formats
201
-
202
- ### JSON (default for Node.js)
203
- ```json
204
- {"timestamp":"2026-01-29T22:47:36.441Z","level":"info","message":"User action","context":{"userId":"123"}}
205
- ```
206
-
207
- ### Text
208
- ```
209
- 2026-01-29T22:47:36.441Z | INFO | User action | {"userId":"123"}
210
- ```
211
-
212
- ### Pretty (default for browser)
213
- ```
214
- [INFO] User action { userId: '123' }
215
- ```
216
-
217
- ## Plugin Development
218
-
219
- ```typescript
220
- import { Plugin, PluginContext } from '@objectstack/core';
221
-
222
- const databasePlugin: Plugin = {
223
- name: 'database',
224
28
  version: '1.0.0',
225
-
226
- init: async (ctx: PluginContext) => {
227
- const db = await connectToDatabase();
228
- ctx.registerService('db', db);
229
- ctx.logger.info('Database connected');
230
- },
231
-
232
- start: async (ctx: PluginContext) => {
233
- ctx.logger.info('Database ready');
234
- },
235
-
236
- destroy: async () => {
237
- await db.close();
238
- }
239
- };
240
-
241
- const apiPlugin: Plugin = {
242
- name: 'api',
243
- dependencies: ['database'], // Load after database
244
-
245
- init: async (ctx: PluginContext) => {
246
- const db = ctx.getService('db');
247
- const server = createServer(db);
248
- ctx.registerService('api', server);
249
- }
250
- };
251
-
252
- kernel.use(databasePlugin);
253
- kernel.use(apiPlugin);
254
- await kernel.bootstrap();
255
- ```
256
-
257
- ## Enhanced Kernel Usage
258
-
259
- For production applications, use `EnhancedObjectKernel` for advanced features:
260
-
261
- ```typescript
262
- import { EnhancedObjectKernel, PluginMetadata, ServiceLifecycle } from '@objectstack/core';
263
-
264
- // Create enhanced kernel
265
- const kernel = new EnhancedObjectKernel({
266
- logger: { level: 'info', format: 'pretty' },
267
- defaultStartupTimeout: 30000, // 30 seconds
268
- gracefulShutdown: true,
269
- shutdownTimeout: 60000, // 60 seconds
270
- rollbackOnFailure: true, // Rollback on failures
271
- });
272
-
273
- // Plugin with version and health check
274
- const plugin: PluginMetadata = {
275
- name: 'my-plugin',
276
- version: '1.2.3',
277
- startupTimeout: 10000,
278
-
279
29
  async init(ctx) {
280
- ctx.registerService('my-service', serviceInstance);
281
- },
282
-
283
- async healthCheck() {
284
- return {
285
- healthy: true,
286
- message: 'Service is operational'
287
- };
30
+ ctx.logger.info('Plugin initializing...');
288
31
  }
289
- };
290
-
291
- // Register service factory with lifecycle
292
- kernel.registerServiceFactory(
293
- 'database',
294
- async (ctx) => await connectToDatabase(),
295
- ServiceLifecycle.SINGLETON
296
- );
32
+ });
297
33
 
298
- await kernel.use(plugin);
299
34
  await kernel.bootstrap();
300
-
301
- // Check health
302
- const health = await kernel.checkPluginHealth('my-plugin');
303
- console.log(health);
304
-
305
- // Get metrics
306
- const metrics = kernel.getPluginMetrics();
307
- console.log(metrics);
308
-
309
- // Graceful shutdown
310
- await kernel.shutdown();
311
35
  ```
312
-
313
- See [ENHANCED_FEATURES.md](./ENHANCED_FEATURES.md) for comprehensive documentation.
314
- See [examples/enhanced-kernel-example.ts](./examples/enhanced-kernel-example.ts) for a complete example.
315
-
316
- ## Environment Support
317
-
318
- ### Node.js Features (via Pino)
319
- - High-performance structured logging
320
- - Automatic file logging with rotation
321
- - JSON format for log aggregation tools (Elasticsearch, Splunk, etc.)
322
- - Pretty printing for development (via pino-pretty)
323
- - Child loggers with inherited context
324
- - Minimal performance overhead
325
-
326
- ### Browser Features
327
- - Pretty console output with colors
328
- - DevTools integration
329
- - Lightweight implementation
330
- - No external dependencies
331
-
332
- ## Security
333
-
334
- Automatic sensitive data redaction:
335
- - Default keys: `password`, `token`, `secret`, `key`
336
- - Configurable via `redact` option
337
- - Recursive through nested objects
338
-
339
- ## API Reference
340
-
341
- ### ObjectKernel (Basic)
342
- - `ObjectKernel` - Basic microkernel class
343
- - `createLogger(config)` - Create standalone logger
344
- - `Plugin` - Plugin interface
345
- - `PluginContext` - Runtime context for plugins
346
- - `Logger` - Logger interface
347
-
348
- ### EnhancedObjectKernel (Advanced)
349
- - `EnhancedObjectKernel` - Enhanced microkernel with production features
350
- - `PluginLoader` - Plugin loading and validation
351
- - `ServiceLifecycle` - Service lifecycle management (SINGLETON, TRANSIENT, SCOPED)
352
- - `PluginMetadata` - Extended plugin interface with metadata
353
- - `PluginHealthStatus` - Health check result interface
354
-
355
- See [TypeScript definitions](./src/types.ts) for complete API.
356
-
357
- ## Documentation
358
-
359
- - [ENHANCED_FEATURES.md](./ENHANCED_FEATURES.md) - Comprehensive guide to enhanced features
360
- - [examples/enhanced-kernel-example.ts](./examples/enhanced-kernel-example.ts) - Complete working example
361
-
362
- ## License
363
-
364
- Apache-2.0
@@ -0,0 +1,40 @@
1
+ # Kernel Refactoring Summary
2
+
3
+ This document summarizes the critical architectural improvements made to the `packages/core` module to address stability, performance, and correctness issues.
4
+
5
+ ## 1. Dependency Injection Context Fix
6
+ **Problem:** Service factories were receiving an empty object `{}` instead of the real `PluginContext`.
7
+ **Fix:**
8
+ - Updated `PluginLoader.createServiceInstance` to ensure `this.context` is passed to factories.
9
+ - Added `PluginLoader.setContext` method to inject the context from the Kernel.
10
+ - Kernel now properly injects itself and the loader into the context before initialization.
11
+
12
+ ## 2. Sync/Async Gap (Service Availability)
13
+ **Problem:** Services created asynchronously (via `awaitFactory`) were not accessible synchronously immediately after initialization, breaking code that expected `getService` to return an instance if the plugin was loaded.
14
+ **Fix:**
15
+ - Implemented L2 caching via `PluginLoader.getServiceInstance<T>(name: string)`.
16
+ - Kernel's `getService` now checks this synchronous cache first before falling back to the async path.
17
+ - Ensured singleton instances are stored in `serviceInstances` immediately upon creation.
18
+
19
+ ## 3. Runtime Circular Dependency Detection
20
+ **Problem:** Complex service graphs could deadlock or crash the stack if factories recursively requested each other. Static analysis was insufficient for dynamic factories.
21
+ **Fix:**
22
+ - Added a `creating` Set to `PluginLoader`.
23
+ - `createServiceInstance` now tracks which services are currently being built.
24
+ - Throws a descriptive error if a loop is detected (e.g., `Circular dependency detected: serviceA -> serviceB -> serviceA`).
25
+
26
+ ## 4. Enhanced Error Handling
27
+ **Problem:** The Kernel swallowed errors from service factories (like database connection failures) and threw a generic "Service not found" error, making debugging impossible.
28
+ **Fix:**
29
+ - Refined `Kernel.getService` to distinguish between "service registration missing" and "factory execution failed".
30
+ - Factory errors are now re-thrown with their original stack trace and message.
31
+
32
+ ## 5. Configuration Validation
33
+ **Problem:** Configuration validation was a scaffold without implementation.
34
+ **Fix:**
35
+ - Integrated `PluginConfigValidator` (Zod-based) into `PluginLoader`.
36
+ - `validatePluginConfig` now performs actual schema validation against `plugin.configSchema`.
37
+
38
+ ## Verification
39
+ - **Build:** Clean build of `dist` artifacts.
40
+ - **Tests:** 100% Pass rate (380/380 tests) across 22 test suites.
@@ -5,11 +5,13 @@ import { ApiRegistry } from './api-registry';
5
5
  describe('API Registry Plugin', () => {
6
6
  let kernel;
7
7
  beforeEach(() => {
8
- kernel = new ObjectKernel();
8
+ kernel = new ObjectKernel({
9
+ skipSystemValidation: true
10
+ });
9
11
  });
10
12
  describe('Plugin Registration', () => {
11
13
  it('should register API Registry as a service', async () => {
12
- kernel.use(createApiRegistryPlugin());
14
+ await kernel.use(createApiRegistryPlugin());
13
15
  await kernel.bootstrap();
14
16
  const registry = kernel.getService('api-registry');
15
17
  expect(registry).toBeDefined();
@@ -17,7 +19,7 @@ describe('API Registry Plugin', () => {
17
19
  await kernel.shutdown();
18
20
  });
19
21
  it('should register with custom conflict resolution', async () => {
20
- kernel.use(createApiRegistryPlugin({
22
+ await kernel.use(createApiRegistryPlugin({
21
23
  conflictResolution: 'priority',
22
24
  version: '2.0.0',
23
25
  }));
@@ -31,7 +33,7 @@ describe('API Registry Plugin', () => {
31
33
  });
32
34
  describe('Integration with Plugins', () => {
33
35
  it('should allow plugins to register APIs', async () => {
34
- kernel.use(createApiRegistryPlugin());
36
+ await kernel.use(createApiRegistryPlugin());
35
37
  const testPlugin = {
36
38
  name: 'test-plugin',
37
39
  init: async (ctx) => {
@@ -60,7 +62,7 @@ describe('API Registry Plugin', () => {
60
62
  registry.registerApi(api);
61
63
  },
62
64
  };
63
- kernel.use(testPlugin);
65
+ await kernel.use(testPlugin);
64
66
  await kernel.bootstrap();
65
67
  const registry = kernel.getService('api-registry');
66
68
  const api = registry.getApi('test_api');
@@ -70,7 +72,7 @@ describe('API Registry Plugin', () => {
70
72
  await kernel.shutdown();
71
73
  });
72
74
  it('should allow multiple plugins to register APIs', async () => {
73
- kernel.use(createApiRegistryPlugin());
75
+ await kernel.use(createApiRegistryPlugin());
74
76
  const plugin1 = {
75
77
  name: 'plugin-1',
76
78
  init: async (ctx) => {
@@ -112,8 +114,8 @@ describe('API Registry Plugin', () => {
112
114
  });
113
115
  },
114
116
  };
115
- kernel.use(plugin1);
116
- kernel.use(plugin2);
117
+ await kernel.use(plugin1);
118
+ await kernel.use(plugin2);
117
119
  await kernel.bootstrap();
118
120
  const registry = kernel.getService('api-registry');
119
121
  const stats = registry.getStats();
@@ -123,7 +125,7 @@ describe('API Registry Plugin', () => {
123
125
  await kernel.shutdown();
124
126
  });
125
127
  it('should support API discovery across plugins', async () => {
126
- kernel.use(createApiRegistryPlugin());
128
+ await kernel.use(createApiRegistryPlugin());
127
129
  const dataPlugin = {
128
130
  name: 'data-plugin',
129
131
  init: async (ctx) => {
@@ -172,8 +174,8 @@ describe('API Registry Plugin', () => {
172
174
  });
173
175
  },
174
176
  };
175
- kernel.use(dataPlugin);
176
- kernel.use(analyticsPlugin);
177
+ await kernel.use(dataPlugin);
178
+ await kernel.use(analyticsPlugin);
177
179
  await kernel.bootstrap();
178
180
  const registry = kernel.getService('api-registry');
179
181
  // Find all data APIs
@@ -189,7 +191,7 @@ describe('API Registry Plugin', () => {
189
191
  await kernel.shutdown();
190
192
  });
191
193
  it('should handle route conflicts based on strategy', async () => {
192
- kernel.use(createApiRegistryPlugin({
194
+ await kernel.use(createApiRegistryPlugin({
193
195
  conflictResolution: 'priority',
194
196
  }));
195
197
  const corePlugin = {
@@ -238,8 +240,8 @@ describe('API Registry Plugin', () => {
238
240
  });
239
241
  },
240
242
  };
241
- kernel.use(corePlugin);
242
- kernel.use(pluginOverride);
243
+ await kernel.use(corePlugin);
244
+ await kernel.use(pluginOverride);
243
245
  await kernel.bootstrap();
244
246
  const registry = kernel.getService('api-registry');
245
247
  const result = registry.findEndpointByRoute('GET', '/api/data/:object');
@@ -249,7 +251,7 @@ describe('API Registry Plugin', () => {
249
251
  await kernel.shutdown();
250
252
  });
251
253
  it('should support cleanup on plugin unload', async () => {
252
- kernel.use(createApiRegistryPlugin());
254
+ await kernel.use(createApiRegistryPlugin());
253
255
  const dynamicPlugin = {
254
256
  name: 'dynamic-plugin',
255
257
  init: async (ctx) => {
@@ -275,7 +277,7 @@ describe('API Registry Plugin', () => {
275
277
  // For now, we'll test the registry's unregister capability
276
278
  },
277
279
  };
278
- kernel.use(dynamicPlugin);
280
+ await kernel.use(dynamicPlugin);
279
281
  await kernel.bootstrap();
280
282
  const registry = kernel.getService('api-registry');
281
283
  expect(registry.getApi('dynamic_api')).toBeDefined();
@@ -287,7 +289,7 @@ describe('API Registry Plugin', () => {
287
289
  });
288
290
  describe('API Registry Lifecycle', () => {
289
291
  it('should be available during plugin start phase', async () => {
290
- kernel.use(createApiRegistryPlugin());
292
+ await kernel.use(createApiRegistryPlugin());
291
293
  let registryAvailable = false;
292
294
  const testPlugin = {
293
295
  name: 'test-plugin',
@@ -300,13 +302,13 @@ describe('API Registry Plugin', () => {
300
302
  registryAvailable = registry !== undefined;
301
303
  },
302
304
  };
303
- kernel.use(testPlugin);
305
+ await kernel.use(testPlugin);
304
306
  await kernel.bootstrap();
305
307
  expect(registryAvailable).toBe(true);
306
308
  await kernel.shutdown();
307
309
  });
308
310
  it('should provide consistent registry across all plugins', async () => {
309
- kernel.use(createApiRegistryPlugin());
311
+ await kernel.use(createApiRegistryPlugin());
310
312
  let registry1;
311
313
  let registry2;
312
314
  const plugin1 = {
@@ -321,8 +323,8 @@ describe('API Registry Plugin', () => {
321
323
  registry2 = ctx.getService('api-registry');
322
324
  },
323
325
  };
324
- kernel.use(plugin1);
325
- kernel.use(plugin2);
326
+ await kernel.use(plugin1);
327
+ await kernel.use(plugin2);
326
328
  await kernel.bootstrap();
327
329
  // Same registry instance should be shared
328
330
  expect(registry1).toBe(registry2);
@@ -580,8 +580,8 @@ describe('ApiRegistry', () => {
580
580
  endpoints: [],
581
581
  });
582
582
  const snapshot = registry.getRegistry();
583
- expect(snapshot.byType?.rest.length).toBe(2);
584
- expect(snapshot.byType?.graphql.length).toBe(1);
583
+ expect(snapshot.byType?.rest?.length).toBe(2);
584
+ expect(snapshot.byType?.graphql?.length).toBe(1);
585
585
  });
586
586
  });
587
587
  describe('clear', () => {
@@ -0,0 +1,62 @@
1
+ import type { SemanticVersion, VersionConstraint, CompatibilityLevel, DependencyConflict } from '@objectstack/spec/kernel';
2
+ import type { ObjectLogger } from './logger.js';
3
+ /**
4
+ * Semantic Version Parser and Comparator
5
+ *
6
+ * Implements semantic versioning comparison and constraint matching
7
+ */
8
+ export declare class SemanticVersionManager {
9
+ /**
10
+ * Parse a version string into semantic version components
11
+ */
12
+ static parse(versionStr: string): SemanticVersion;
13
+ /**
14
+ * Convert semantic version back to string
15
+ */
16
+ static toString(version: SemanticVersion): string;
17
+ /**
18
+ * Compare two semantic versions
19
+ * Returns: -1 if a < b, 0 if a === b, 1 if a > b
20
+ */
21
+ static compare(a: SemanticVersion, b: SemanticVersion): number;
22
+ /**
23
+ * Check if version satisfies constraint
24
+ */
25
+ static satisfies(version: SemanticVersion, constraint: VersionConstraint): boolean;
26
+ /**
27
+ * Determine compatibility level between two versions
28
+ */
29
+ static getCompatibilityLevel(from: SemanticVersion, to: SemanticVersion): CompatibilityLevel;
30
+ }
31
+ /**
32
+ * Plugin Dependency Resolver
33
+ *
34
+ * Resolves plugin dependencies using topological sorting and conflict detection
35
+ */
36
+ export declare class DependencyResolver {
37
+ private logger;
38
+ constructor(logger: ObjectLogger);
39
+ /**
40
+ * Resolve dependencies using topological sort
41
+ */
42
+ resolve(plugins: Map<string, {
43
+ version?: string;
44
+ dependencies?: string[];
45
+ }>): string[];
46
+ /**
47
+ * Detect dependency conflicts
48
+ */
49
+ detectConflicts(plugins: Map<string, {
50
+ version: string;
51
+ dependencies?: Record<string, VersionConstraint>;
52
+ }>): DependencyConflict[];
53
+ /**
54
+ * Find best version that satisfies all constraints
55
+ */
56
+ findBestVersion(availableVersions: string[], constraints: VersionConstraint[]): string | undefined;
57
+ /**
58
+ * Check if dependencies form a valid DAG (no cycles)
59
+ */
60
+ isAcyclic(dependencies: Map<string, string[]>): boolean;
61
+ }
62
+ //# sourceMappingURL=dependency-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-resolver.d.ts","sourceRoot":"","sources":["../src/dependency-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;GAIG;AACH,qBAAa,sBAAsB;IACjC;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe;IAsBjD;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM;IAWjD;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,eAAe,GAAG,MAAM;IAkB9D;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,iBAAiB,GAAG,OAAO;IAoElF;;OAEG;IACH,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,eAAe,EAAE,EAAE,EAAE,eAAe,GAAG,kBAAkB;CA0B7F;AAED;;;;GAIG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAe;gBAEjB,MAAM,EAAE,YAAY;IAIhC;;OAEG;IACH,OAAO,CACL,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,GAClE,MAAM,EAAE;IAkEX;;OAEG;IACH,eAAe,CACb,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;KAAE,CAAC,GAC1F,kBAAkB,EAAE;IA+EvB;;OAEG;IACH,eAAe,CACb,iBAAiB,EAAE,MAAM,EAAE,EAC3B,WAAW,EAAE,iBAAiB,EAAE,GAC/B,MAAM,GAAG,SAAS;IAoBrB;;OAEG;IACH,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO;CAcxD"}