@objectstack/core 4.0.3 → 4.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/README.md +95 -10
- package/dist/index.cjs +169 -507
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -223
- package/dist/index.d.ts +24 -223
- package/dist/index.js +175 -505
- package/dist/index.js.map +1 -1
- package/dist/logger.cjs +177 -0
- package/dist/logger.cjs.map +1 -0
- package/dist/logger.d.cts +26 -0
- package/dist/logger.d.ts +26 -0
- package/dist/logger.js +158 -0
- package/dist/logger.js.map +1 -0
- package/package.json +36 -15
- package/.turbo/turbo-build.log +0 -22
- package/ADVANCED_FEATURES.md +0 -380
- package/API_REGISTRY.md +0 -392
- package/CHANGELOG.md +0 -465
- package/PHASE2_IMPLEMENTATION.md +0 -388
- package/REFACTORING_SUMMARY.md +0 -40
- package/examples/api-registry-example.ts +0 -559
- package/examples/kernel-features-example.ts +0 -311
- package/examples/phase2-integration.ts +0 -357
- package/src/api-registry-plugin.test.ts +0 -393
- package/src/api-registry-plugin.ts +0 -89
- package/src/api-registry.test.ts +0 -1089
- package/src/api-registry.ts +0 -739
- package/src/contracts/data-engine.ts +0 -57
- package/src/contracts/http-server.ts +0 -151
- package/src/contracts/logger.ts +0 -72
- package/src/dependency-resolver.test.ts +0 -287
- package/src/dependency-resolver.ts +0 -390
- package/src/fallbacks/fallbacks.test.ts +0 -281
- package/src/fallbacks/index.ts +0 -26
- package/src/fallbacks/memory-cache.ts +0 -34
- package/src/fallbacks/memory-i18n.ts +0 -112
- package/src/fallbacks/memory-job.ts +0 -23
- package/src/fallbacks/memory-metadata.ts +0 -50
- package/src/fallbacks/memory-queue.ts +0 -28
- package/src/health-monitor.test.ts +0 -81
- package/src/health-monitor.ts +0 -318
- package/src/hot-reload.ts +0 -382
- package/src/index.ts +0 -50
- package/src/kernel-base.ts +0 -273
- package/src/kernel.test.ts +0 -624
- package/src/kernel.ts +0 -631
- package/src/lite-kernel.test.ts +0 -248
- package/src/lite-kernel.ts +0 -137
- package/src/logger.test.ts +0 -116
- package/src/logger.ts +0 -355
- package/src/namespace-resolver.test.ts +0 -130
- package/src/namespace-resolver.ts +0 -188
- package/src/package-manager.test.ts +0 -225
- package/src/package-manager.ts +0 -428
- package/src/plugin-loader.test.ts +0 -421
- package/src/plugin-loader.ts +0 -484
- package/src/qa/adapter.ts +0 -16
- package/src/qa/http-adapter.ts +0 -116
- package/src/qa/index.ts +0 -5
- package/src/qa/runner.ts +0 -189
- package/src/security/index.ts +0 -50
- package/src/security/permission-manager.test.ts +0 -256
- package/src/security/permission-manager.ts +0 -338
- package/src/security/plugin-config-validator.test.ts +0 -276
- package/src/security/plugin-config-validator.ts +0 -193
- package/src/security/plugin-permission-enforcer.test.ts +0 -251
- package/src/security/plugin-permission-enforcer.ts +0 -436
- package/src/security/plugin-signature-verifier.ts +0 -403
- package/src/security/sandbox-runtime.ts +0 -462
- package/src/security/security-scanner.ts +0 -367
- package/src/types.ts +0 -120
- package/src/utils/env.test.ts +0 -62
- package/src/utils/env.ts +0 -53
- package/tsconfig.json +0 -10
- package/vitest.config.ts +0 -10
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* ObjectKernel Features Example
|
|
5
|
-
*
|
|
6
|
-
* Demonstrates advanced plugin features:
|
|
7
|
-
* - Version compatibility
|
|
8
|
-
* - Service factories with lifecycle management
|
|
9
|
-
* - Plugin timeout control
|
|
10
|
-
* - Startup failure rollback
|
|
11
|
-
* - Health checks
|
|
12
|
-
* - Performance metrics
|
|
13
|
-
* - Graceful shutdown
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import {
|
|
17
|
-
ObjectKernel,
|
|
18
|
-
PluginMetadata,
|
|
19
|
-
ServiceLifecycle,
|
|
20
|
-
PluginContext
|
|
21
|
-
} from '../index.js';
|
|
22
|
-
|
|
23
|
-
// ============================================================================
|
|
24
|
-
// Example 1: Database Plugin with Health Checks
|
|
25
|
-
// ============================================================================
|
|
26
|
-
|
|
27
|
-
const databasePlugin: PluginMetadata = {
|
|
28
|
-
name: 'database',
|
|
29
|
-
version: '1.0.0',
|
|
30
|
-
startupTimeout: 10000, // 10 second timeout
|
|
31
|
-
|
|
32
|
-
async init(ctx: PluginContext) {
|
|
33
|
-
ctx.logger.info('Initializing database plugin');
|
|
34
|
-
|
|
35
|
-
// Register database service using factory
|
|
36
|
-
// This creates a singleton that's initialized once
|
|
37
|
-
const db = {
|
|
38
|
-
connected: false,
|
|
39
|
-
async connect() {
|
|
40
|
-
ctx.logger.info('Connecting to database...');
|
|
41
|
-
await new Promise(resolve => setTimeout(resolve, 100)); // Simulate connection
|
|
42
|
-
this.connected = true;
|
|
43
|
-
ctx.logger.info('Database connected');
|
|
44
|
-
},
|
|
45
|
-
async disconnect() {
|
|
46
|
-
ctx.logger.info('Disconnecting from database...');
|
|
47
|
-
this.connected = false;
|
|
48
|
-
},
|
|
49
|
-
async query(sql: string) {
|
|
50
|
-
if (!this.connected) {
|
|
51
|
-
throw new Error('Database not connected');
|
|
52
|
-
}
|
|
53
|
-
return { rows: [] };
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
ctx.registerService('db', db);
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
async start(ctx: PluginContext) {
|
|
61
|
-
const db = ctx.getService<any>('db');
|
|
62
|
-
await db.connect();
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
async destroy() {
|
|
66
|
-
// Cleanup on shutdown
|
|
67
|
-
console.log('Cleaning up database connection');
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
async healthCheck() {
|
|
71
|
-
// Health check returns status
|
|
72
|
-
return {
|
|
73
|
-
healthy: true,
|
|
74
|
-
message: 'Database is operational',
|
|
75
|
-
details: {
|
|
76
|
-
connections: 5,
|
|
77
|
-
responseTime: 45
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
// ============================================================================
|
|
84
|
-
// Example 2: API Plugin with Dependencies
|
|
85
|
-
// ============================================================================
|
|
86
|
-
|
|
87
|
-
const apiPlugin: PluginMetadata = {
|
|
88
|
-
name: 'api',
|
|
89
|
-
version: '2.1.0',
|
|
90
|
-
dependencies: ['database'], // Requires database plugin to be loaded first
|
|
91
|
-
|
|
92
|
-
async init(ctx: PluginContext) {
|
|
93
|
-
ctx.logger.info('Initializing API plugin');
|
|
94
|
-
|
|
95
|
-
// Access database service (guaranteed to exist due to dependencies)
|
|
96
|
-
const db = ctx.getService<any>('db');
|
|
97
|
-
|
|
98
|
-
const api = {
|
|
99
|
-
async getUsers() {
|
|
100
|
-
return await db.query('SELECT * FROM users');
|
|
101
|
-
},
|
|
102
|
-
async createUser(data: any) {
|
|
103
|
-
return await db.query('INSERT INTO users VALUES ...', data);
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
ctx.registerService('api', api);
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
async healthCheck() {
|
|
111
|
-
return {
|
|
112
|
-
healthy: true,
|
|
113
|
-
message: 'API is ready',
|
|
114
|
-
details: {
|
|
115
|
-
routes: 15,
|
|
116
|
-
activeRequests: 3
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
// ============================================================================
|
|
123
|
-
// Example 3: Cache Plugin with Scoped Services
|
|
124
|
-
// ============================================================================
|
|
125
|
-
|
|
126
|
-
const cachePlugin: PluginMetadata = {
|
|
127
|
-
name: 'cache',
|
|
128
|
-
version: '1.2.3',
|
|
129
|
-
|
|
130
|
-
async init(ctx: PluginContext) {
|
|
131
|
-
ctx.logger.info('Initializing cache plugin');
|
|
132
|
-
|
|
133
|
-
// Simple in-memory cache
|
|
134
|
-
const cache = new Map<string, any>();
|
|
135
|
-
|
|
136
|
-
ctx.registerService('cache', {
|
|
137
|
-
get(key: string) {
|
|
138
|
-
return cache.get(key);
|
|
139
|
-
},
|
|
140
|
-
set(key: string, value: any) {
|
|
141
|
-
cache.set(key, value);
|
|
142
|
-
},
|
|
143
|
-
clear() {
|
|
144
|
-
cache.clear();
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
},
|
|
148
|
-
|
|
149
|
-
async healthCheck() {
|
|
150
|
-
return {
|
|
151
|
-
healthy: true,
|
|
152
|
-
message: 'Cache is operational'
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
// ============================================================================
|
|
158
|
-
// Example 4: Using Service Factories
|
|
159
|
-
// ============================================================================
|
|
160
|
-
|
|
161
|
-
async function setupServiceFactories(kernel: ObjectKernel) {
|
|
162
|
-
// Singleton: Created once, shared across all requests
|
|
163
|
-
kernel.registerServiceFactory(
|
|
164
|
-
'logger-service',
|
|
165
|
-
(ctx) => {
|
|
166
|
-
return {
|
|
167
|
-
log: (message: string) => {
|
|
168
|
-
ctx.logger.info(message);
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
|
-
},
|
|
172
|
-
ServiceLifecycle.SINGLETON
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
// Transient: New instance on every request
|
|
176
|
-
kernel.registerServiceFactory(
|
|
177
|
-
'request-id',
|
|
178
|
-
() => {
|
|
179
|
-
return `req-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
|
|
180
|
-
},
|
|
181
|
-
ServiceLifecycle.TRANSIENT
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
// Scoped: One instance per scope (e.g., per HTTP request)
|
|
185
|
-
kernel.registerServiceFactory(
|
|
186
|
-
'user-session',
|
|
187
|
-
() => {
|
|
188
|
-
return {
|
|
189
|
-
id: Math.random().toString(36),
|
|
190
|
-
data: new Map<string, any>()
|
|
191
|
-
};
|
|
192
|
-
},
|
|
193
|
-
ServiceLifecycle.SCOPED
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// ============================================================================
|
|
198
|
-
// Main Application
|
|
199
|
-
// ============================================================================
|
|
200
|
-
|
|
201
|
-
async function main() {
|
|
202
|
-
console.log('🚀 Starting ObjectKernel Advanced Features Example\n');
|
|
203
|
-
|
|
204
|
-
// Create object kernel with configuration
|
|
205
|
-
const kernel = new ObjectKernel({
|
|
206
|
-
logger: {
|
|
207
|
-
level: 'info',
|
|
208
|
-
format: 'pretty'
|
|
209
|
-
},
|
|
210
|
-
defaultStartupTimeout: 30000, // 30 seconds
|
|
211
|
-
gracefulShutdown: true,
|
|
212
|
-
shutdownTimeout: 60000, // 60 seconds
|
|
213
|
-
rollbackOnFailure: true, // Rollback on failure
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
// Setup service factories
|
|
217
|
-
await setupServiceFactories(kernel);
|
|
218
|
-
|
|
219
|
-
// Register plugins
|
|
220
|
-
await kernel.use(databasePlugin);
|
|
221
|
-
await kernel.use(cachePlugin);
|
|
222
|
-
await kernel.use(apiPlugin);
|
|
223
|
-
|
|
224
|
-
console.log('📦 Plugins registered\n');
|
|
225
|
-
|
|
226
|
-
// Bootstrap kernel
|
|
227
|
-
console.log('⚡ Bootstrapping kernel...\n');
|
|
228
|
-
await kernel.bootstrap();
|
|
229
|
-
|
|
230
|
-
console.log('\n✅ Kernel started successfully!\n');
|
|
231
|
-
|
|
232
|
-
// Show plugin metrics
|
|
233
|
-
console.log('📊 Plugin Startup Metrics:');
|
|
234
|
-
const metrics = kernel.getPluginMetrics();
|
|
235
|
-
for (const [name, time] of metrics) {
|
|
236
|
-
console.log(` ${name}: ${time}ms`);
|
|
237
|
-
}
|
|
238
|
-
console.log('');
|
|
239
|
-
|
|
240
|
-
// Check plugin health
|
|
241
|
-
console.log('🏥 Plugin Health Status:');
|
|
242
|
-
const healthStatuses = await kernel.checkAllPluginsHealth();
|
|
243
|
-
for (const [name, health] of healthStatuses) {
|
|
244
|
-
const status = health.healthy ? '✅' : '❌';
|
|
245
|
-
console.log(` ${status} ${name}: ${health.message}`);
|
|
246
|
-
if (health.details) {
|
|
247
|
-
console.log(` Details:`, health.details);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
console.log('');
|
|
251
|
-
|
|
252
|
-
// Use services
|
|
253
|
-
console.log('🔧 Using services:');
|
|
254
|
-
const db = kernel.getService<any>('db');
|
|
255
|
-
console.log(' Database connected:', db.connected);
|
|
256
|
-
|
|
257
|
-
const cache = kernel.getService<any>('cache');
|
|
258
|
-
cache.set('user:1', { name: 'John Doe' });
|
|
259
|
-
console.log(' Cached user:', cache.get('user:1'));
|
|
260
|
-
|
|
261
|
-
const api = kernel.getService<any>('api');
|
|
262
|
-
console.log(' API ready:', !!api);
|
|
263
|
-
console.log('');
|
|
264
|
-
|
|
265
|
-
// Test service factories
|
|
266
|
-
console.log('🏭 Testing Service Factories:');
|
|
267
|
-
|
|
268
|
-
// Singleton - same instance
|
|
269
|
-
const logger1 = await kernel.getServiceAsync('logger-service');
|
|
270
|
-
const logger2 = await kernel.getServiceAsync('logger-service');
|
|
271
|
-
console.log(' Singleton test:', logger1 === logger2 ? 'PASS ✅' : 'FAIL ❌');
|
|
272
|
-
|
|
273
|
-
// Transient - different instances
|
|
274
|
-
const id1 = await kernel.getServiceAsync('request-id');
|
|
275
|
-
const id2 = await kernel.getServiceAsync('request-id');
|
|
276
|
-
console.log(' Transient test:', id1 !== id2 ? 'PASS ✅' : 'FAIL ❌');
|
|
277
|
-
console.log(' Generated IDs:', id1, 'and', id2);
|
|
278
|
-
|
|
279
|
-
// Scoped - same within scope, different across scopes
|
|
280
|
-
const session1a = await kernel.getServiceAsync('user-session', 'request-1');
|
|
281
|
-
const session1b = await kernel.getServiceAsync('user-session', 'request-1');
|
|
282
|
-
const session2 = await kernel.getServiceAsync('user-session', 'request-2');
|
|
283
|
-
console.log(' Scoped (same scope):', session1a === session1b ? 'PASS ✅' : 'FAIL ❌');
|
|
284
|
-
console.log(' Scoped (diff scope):', session1a !== session2 ? 'PASS ✅' : 'FAIL ❌');
|
|
285
|
-
console.log('');
|
|
286
|
-
|
|
287
|
-
// Register custom shutdown handler
|
|
288
|
-
kernel.onShutdown(async () => {
|
|
289
|
-
console.log('🧹 Running custom cleanup...');
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
// Simulate running for a bit
|
|
293
|
-
console.log('⏳ Running for 2 seconds...\n');
|
|
294
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
295
|
-
|
|
296
|
-
// Graceful shutdown
|
|
297
|
-
console.log('🛑 Initiating graceful shutdown...\n');
|
|
298
|
-
await kernel.shutdown();
|
|
299
|
-
|
|
300
|
-
console.log('\n✅ Shutdown complete!\n');
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// Run the example
|
|
304
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
305
|
-
main().catch(error => {
|
|
306
|
-
console.error('❌ Error:', error);
|
|
307
|
-
process.exit(1);
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
export { main };
|
|
@@ -1,357 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Phase 2 Integration Example
|
|
5
|
-
*
|
|
6
|
-
* This example demonstrates how to use all Phase 2 components together
|
|
7
|
-
* in a real-world scenario.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
ObjectKernel,
|
|
12
|
-
PluginHealthMonitor,
|
|
13
|
-
HotReloadManager,
|
|
14
|
-
DependencyResolver,
|
|
15
|
-
PluginPermissionManager,
|
|
16
|
-
PluginSandboxRuntime,
|
|
17
|
-
PluginSecurityScanner
|
|
18
|
-
} from '@objectstack/core';
|
|
19
|
-
|
|
20
|
-
import type { Plugin } from '@objectstack/core';
|
|
21
|
-
import type {
|
|
22
|
-
PluginHealthCheck,
|
|
23
|
-
HotReloadConfig,
|
|
24
|
-
PermissionSet,
|
|
25
|
-
SandboxConfig
|
|
26
|
-
} from '@objectstack/spec/system';
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Example: Enterprise Plugin Platform with Phase 2 Features
|
|
30
|
-
*/
|
|
31
|
-
export class EnterprisePluginPlatform {
|
|
32
|
-
private kernel: ObjectKernel;
|
|
33
|
-
private healthMonitor: PluginHealthMonitor;
|
|
34
|
-
private hotReload: HotReloadManager;
|
|
35
|
-
private depResolver: DependencyResolver;
|
|
36
|
-
private permManager: PluginPermissionManager;
|
|
37
|
-
private sandbox: PluginSandboxRuntime;
|
|
38
|
-
private scanner: PluginSecurityScanner;
|
|
39
|
-
|
|
40
|
-
constructor() {
|
|
41
|
-
// Initialize kernel
|
|
42
|
-
this.kernel = new ObjectKernel({
|
|
43
|
-
logger: {
|
|
44
|
-
level: 'info',
|
|
45
|
-
name: 'EnterprisePluginPlatform',
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
// Initialize Phase 2 components
|
|
50
|
-
this.healthMonitor = new PluginHealthMonitor(this.kernel.logger);
|
|
51
|
-
this.hotReload = new HotReloadManager(this.kernel.logger);
|
|
52
|
-
this.depResolver = new DependencyResolver(this.kernel.logger);
|
|
53
|
-
this.permManager = new PluginPermissionManager(this.kernel.logger);
|
|
54
|
-
this.sandbox = new PluginSandboxRuntime(this.kernel.logger);
|
|
55
|
-
this.scanner = new PluginSecurityScanner(this.kernel.logger);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Install and configure a plugin with full Phase 2 features
|
|
60
|
-
*/
|
|
61
|
-
async installPlugin(
|
|
62
|
-
plugin: Plugin,
|
|
63
|
-
config: {
|
|
64
|
-
health?: PluginHealthCheck;
|
|
65
|
-
hotReload?: HotReloadConfig;
|
|
66
|
-
permissions?: PermissionSet;
|
|
67
|
-
sandbox?: SandboxConfig;
|
|
68
|
-
securityScan?: boolean;
|
|
69
|
-
}
|
|
70
|
-
): Promise<void> {
|
|
71
|
-
const pluginName = plugin.name;
|
|
72
|
-
const pluginVersion = plugin.version || '1.0.0';
|
|
73
|
-
|
|
74
|
-
this.kernel.logger.info(`Installing plugin: ${pluginName} v${pluginVersion}`);
|
|
75
|
-
|
|
76
|
-
// Step 1: Security Scan
|
|
77
|
-
if (config.securityScan !== false) {
|
|
78
|
-
this.kernel.logger.info('Running security scan...');
|
|
79
|
-
|
|
80
|
-
const scanResult = await this.scanner.scan({
|
|
81
|
-
pluginId: pluginName,
|
|
82
|
-
version: pluginVersion,
|
|
83
|
-
// In real implementation, would provide actual files and dependencies
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
if (!scanResult.passed) {
|
|
87
|
-
throw new Error(
|
|
88
|
-
`Security scan failed: Score ${scanResult.score}/100, ` +
|
|
89
|
-
`Critical: ${scanResult.summary.critical}, ` +
|
|
90
|
-
`High: ${scanResult.summary.high}`
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
this.kernel.logger.info(
|
|
95
|
-
`Security scan passed: ${scanResult.score}/100`
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Step 2: Register Permissions
|
|
100
|
-
if (config.permissions) {
|
|
101
|
-
this.permManager.registerPermissions(pluginName, config.permissions);
|
|
102
|
-
|
|
103
|
-
// Auto-grant all permissions (in production, would prompt user)
|
|
104
|
-
this.permManager.grantAllPermissions(pluginName, 'system');
|
|
105
|
-
|
|
106
|
-
this.kernel.logger.info(
|
|
107
|
-
`Permissions registered: ${config.permissions.permissions.length} permissions`
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Step 3: Create Sandbox
|
|
112
|
-
if (config.sandbox) {
|
|
113
|
-
this.sandbox.createSandbox(pluginName, config.sandbox);
|
|
114
|
-
this.kernel.logger.info(`Sandbox created: ${config.sandbox.level} level`);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Step 4: Register for Health Monitoring
|
|
118
|
-
if (config.health) {
|
|
119
|
-
this.healthMonitor.registerPlugin(pluginName, config.health);
|
|
120
|
-
this.kernel.logger.info(
|
|
121
|
-
`Health monitoring configured: ${config.health.interval}ms interval`
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Step 5: Register for Hot Reload
|
|
126
|
-
if (config.hotReload) {
|
|
127
|
-
this.hotReload.registerPlugin(pluginName, config.hotReload);
|
|
128
|
-
this.kernel.logger.info(
|
|
129
|
-
`Hot reload enabled: ${config.hotReload.stateStrategy} state strategy`
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Step 6: Register with Kernel
|
|
134
|
-
this.kernel.use(plugin);
|
|
135
|
-
|
|
136
|
-
this.kernel.logger.info(`Plugin ${pluginName} installed successfully`);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Bootstrap the platform
|
|
141
|
-
*/
|
|
142
|
-
async start(): Promise<void> {
|
|
143
|
-
// Bootstrap kernel (will init and start all plugins)
|
|
144
|
-
await this.kernel.bootstrap();
|
|
145
|
-
|
|
146
|
-
// Start health monitoring for all registered plugins
|
|
147
|
-
for (const [pluginName, plugin] of this.kernel['plugins']) {
|
|
148
|
-
if (this.healthMonitor['healthChecks'].has(pluginName)) {
|
|
149
|
-
this.healthMonitor.startMonitoring(pluginName, plugin);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
this.kernel.logger.info('Platform started successfully');
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Shutdown the platform
|
|
158
|
-
*/
|
|
159
|
-
async shutdown(): Promise<void> {
|
|
160
|
-
this.kernel.logger.info('Shutting down platform...');
|
|
161
|
-
|
|
162
|
-
// Stop health monitoring
|
|
163
|
-
this.healthMonitor.shutdown();
|
|
164
|
-
|
|
165
|
-
// Shutdown sandbox
|
|
166
|
-
this.sandbox.shutdown();
|
|
167
|
-
|
|
168
|
-
// Shutdown kernel
|
|
169
|
-
await this.kernel.shutdown();
|
|
170
|
-
|
|
171
|
-
this.kernel.logger.info('Platform shutdown complete');
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Get platform health status
|
|
176
|
-
*/
|
|
177
|
-
getHealthStatus(): Record<string, any> {
|
|
178
|
-
const statuses = this.healthMonitor.getAllHealthStatuses();
|
|
179
|
-
const summary: Record<string, any> = {
|
|
180
|
-
totalPlugins: statuses.size,
|
|
181
|
-
healthy: 0,
|
|
182
|
-
degraded: 0,
|
|
183
|
-
unhealthy: 0,
|
|
184
|
-
failed: 0,
|
|
185
|
-
plugins: {},
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
for (const [pluginName, status] of statuses) {
|
|
189
|
-
summary[status]++;
|
|
190
|
-
summary.plugins[pluginName] = {
|
|
191
|
-
status,
|
|
192
|
-
report: this.healthMonitor.getHealthReport(pluginName),
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return summary;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Perform hot reload of a plugin
|
|
201
|
-
*/
|
|
202
|
-
async reloadPlugin(pluginName: string): Promise<void> {
|
|
203
|
-
this.kernel.logger.info(`Hot reloading plugin: ${pluginName}`);
|
|
204
|
-
|
|
205
|
-
const plugin = this.kernel['plugins'].get(pluginName);
|
|
206
|
-
if (!plugin) {
|
|
207
|
-
throw new Error(`Plugin not found: ${pluginName}`);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Get current state (simplified - would need plugin cooperation)
|
|
211
|
-
const getState = () => ({
|
|
212
|
-
timestamp: Date.now(),
|
|
213
|
-
// ... plugin state
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
// Restore state (simplified - would need plugin cooperation)
|
|
217
|
-
const restoreState = (state: Record<string, any>) => {
|
|
218
|
-
this.kernel.logger.info(`Restoring state from ${new Date(state.timestamp)}`);
|
|
219
|
-
// ... restore plugin state
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
await this.hotReload.reloadPlugin(
|
|
223
|
-
pluginName,
|
|
224
|
-
plugin,
|
|
225
|
-
plugin.version || '1.0.0',
|
|
226
|
-
getState,
|
|
227
|
-
restoreState
|
|
228
|
-
);
|
|
229
|
-
|
|
230
|
-
this.kernel.logger.info(`Plugin ${pluginName} reloaded successfully`);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Example Usage
|
|
236
|
-
*/
|
|
237
|
-
async function example() {
|
|
238
|
-
const platform = new EnterprisePluginPlatform();
|
|
239
|
-
|
|
240
|
-
// Define a sample plugin
|
|
241
|
-
const myPlugin: Plugin = {
|
|
242
|
-
name: 'com.example.my-plugin',
|
|
243
|
-
version: '1.0.0',
|
|
244
|
-
dependencies: ['com.objectstack.engine.objectql'],
|
|
245
|
-
|
|
246
|
-
async init(ctx) {
|
|
247
|
-
ctx.logger.info('MyPlugin initializing...');
|
|
248
|
-
// Initialize plugin
|
|
249
|
-
},
|
|
250
|
-
|
|
251
|
-
async start(ctx) {
|
|
252
|
-
ctx.logger.info('MyPlugin starting...');
|
|
253
|
-
// Start plugin services
|
|
254
|
-
},
|
|
255
|
-
|
|
256
|
-
async destroy() {
|
|
257
|
-
console.log('MyPlugin destroying...');
|
|
258
|
-
// Cleanup
|
|
259
|
-
},
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
// Install plugin with full Phase 2 features
|
|
263
|
-
await platform.installPlugin(myPlugin, {
|
|
264
|
-
// Health monitoring
|
|
265
|
-
health: {
|
|
266
|
-
interval: 30000, // Check every 30 seconds
|
|
267
|
-
timeout: 5000,
|
|
268
|
-
failureThreshold: 3,
|
|
269
|
-
successThreshold: 1,
|
|
270
|
-
autoRestart: true,
|
|
271
|
-
maxRestartAttempts: 3,
|
|
272
|
-
restartBackoff: 'exponential',
|
|
273
|
-
},
|
|
274
|
-
|
|
275
|
-
// Hot reload
|
|
276
|
-
hotReload: {
|
|
277
|
-
enabled: true,
|
|
278
|
-
watchPatterns: ['plugins/my-plugin/**/*.ts'],
|
|
279
|
-
debounceDelay: 1000,
|
|
280
|
-
preserveState: true,
|
|
281
|
-
stateStrategy: 'memory',
|
|
282
|
-
shutdownTimeout: 30000,
|
|
283
|
-
},
|
|
284
|
-
|
|
285
|
-
// Permissions
|
|
286
|
-
permissions: {
|
|
287
|
-
permissions: [
|
|
288
|
-
{
|
|
289
|
-
id: 'read-data',
|
|
290
|
-
resource: 'data.object',
|
|
291
|
-
actions: ['read'],
|
|
292
|
-
scope: 'plugin',
|
|
293
|
-
description: 'Read object data',
|
|
294
|
-
required: true,
|
|
295
|
-
},
|
|
296
|
-
{
|
|
297
|
-
id: 'write-data',
|
|
298
|
-
resource: 'data.object',
|
|
299
|
-
actions: ['create', 'update'],
|
|
300
|
-
scope: 'plugin',
|
|
301
|
-
description: 'Write object data',
|
|
302
|
-
required: false,
|
|
303
|
-
},
|
|
304
|
-
],
|
|
305
|
-
defaultGrant: 'prompt',
|
|
306
|
-
},
|
|
307
|
-
|
|
308
|
-
// Sandbox
|
|
309
|
-
sandbox: {
|
|
310
|
-
enabled: true,
|
|
311
|
-
level: 'standard',
|
|
312
|
-
filesystem: {
|
|
313
|
-
mode: 'restricted',
|
|
314
|
-
allowedPaths: ['/app/plugins/my-plugin'],
|
|
315
|
-
deniedPaths: ['/etc', '/root'],
|
|
316
|
-
},
|
|
317
|
-
network: {
|
|
318
|
-
mode: 'restricted',
|
|
319
|
-
allowedHosts: ['api.example.com'],
|
|
320
|
-
maxConnections: 10,
|
|
321
|
-
},
|
|
322
|
-
process: {
|
|
323
|
-
allowSpawn: false,
|
|
324
|
-
},
|
|
325
|
-
memory: {
|
|
326
|
-
maxHeap: 100 * 1024 * 1024, // 100 MB
|
|
327
|
-
},
|
|
328
|
-
},
|
|
329
|
-
|
|
330
|
-
// Security scanning
|
|
331
|
-
securityScan: true,
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
// Start platform
|
|
335
|
-
await platform.start();
|
|
336
|
-
|
|
337
|
-
// Get health status
|
|
338
|
-
const health = platform.getHealthStatus();
|
|
339
|
-
console.log('Platform Health:', health);
|
|
340
|
-
|
|
341
|
-
// Simulate hot reload after some time
|
|
342
|
-
setTimeout(async () => {
|
|
343
|
-
await platform.reloadPlugin('com.example.my-plugin');
|
|
344
|
-
}, 60000);
|
|
345
|
-
|
|
346
|
-
// Shutdown on SIGINT
|
|
347
|
-
process.on('SIGINT', async () => {
|
|
348
|
-
await platform.shutdown();
|
|
349
|
-
process.exit(0);
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
// Run example if this file is executed directly (ES Module compatible)
|
|
354
|
-
// Note: In ES modules, use import.meta.url instead of require.main
|
|
355
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
356
|
-
example().catch(console.error);
|
|
357
|
-
}
|