@objectstack/core 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.
Files changed (91) hide show
  1. package/{ENHANCED_FEATURES.md → ADVANCED_FEATURES.md} +13 -13
  2. package/CHANGELOG.md +15 -0
  3. package/PHASE2_IMPLEMENTATION.md +388 -0
  4. package/README.md +60 -11
  5. package/REFACTORING_SUMMARY.md +40 -0
  6. package/dist/api-registry-plugin.test.js +20 -20
  7. package/dist/dependency-resolver.d.ts +62 -0
  8. package/dist/dependency-resolver.d.ts.map +1 -0
  9. package/dist/dependency-resolver.js +317 -0
  10. package/dist/dependency-resolver.test.d.ts +2 -0
  11. package/dist/dependency-resolver.test.d.ts.map +1 -0
  12. package/dist/dependency-resolver.test.js +241 -0
  13. package/dist/health-monitor.d.ts +65 -0
  14. package/dist/health-monitor.d.ts.map +1 -0
  15. package/dist/health-monitor.js +269 -0
  16. package/dist/health-monitor.test.d.ts +2 -0
  17. package/dist/health-monitor.test.d.ts.map +1 -0
  18. package/dist/health-monitor.test.js +68 -0
  19. package/dist/hot-reload.d.ts +79 -0
  20. package/dist/hot-reload.d.ts.map +1 -0
  21. package/dist/hot-reload.js +313 -0
  22. package/dist/index.d.ts +4 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +5 -1
  25. package/dist/kernel-base.d.ts +2 -2
  26. package/dist/kernel-base.js +2 -2
  27. package/dist/kernel.d.ts +79 -31
  28. package/dist/kernel.d.ts.map +1 -1
  29. package/dist/kernel.js +383 -73
  30. package/dist/kernel.test.js +373 -122
  31. package/dist/lite-kernel.d.ts +55 -0
  32. package/dist/lite-kernel.d.ts.map +1 -0
  33. package/dist/lite-kernel.js +112 -0
  34. package/dist/lite-kernel.test.d.ts +2 -0
  35. package/dist/lite-kernel.test.d.ts.map +1 -0
  36. package/dist/lite-kernel.test.js +161 -0
  37. package/dist/logger.d.ts +3 -2
  38. package/dist/logger.d.ts.map +1 -1
  39. package/dist/logger.js +61 -18
  40. package/dist/plugin-loader.d.ts +11 -0
  41. package/dist/plugin-loader.d.ts.map +1 -1
  42. package/dist/plugin-loader.js +34 -10
  43. package/dist/plugin-loader.test.js +9 -0
  44. package/dist/security/index.d.ts +3 -0
  45. package/dist/security/index.d.ts.map +1 -1
  46. package/dist/security/index.js +4 -0
  47. package/dist/security/permission-manager.d.ts +96 -0
  48. package/dist/security/permission-manager.d.ts.map +1 -0
  49. package/dist/security/permission-manager.js +235 -0
  50. package/dist/security/permission-manager.test.d.ts +2 -0
  51. package/dist/security/permission-manager.test.d.ts.map +1 -0
  52. package/dist/security/permission-manager.test.js +220 -0
  53. package/dist/security/plugin-signature-verifier.js +3 -3
  54. package/dist/security/sandbox-runtime.d.ts +115 -0
  55. package/dist/security/sandbox-runtime.d.ts.map +1 -0
  56. package/dist/security/sandbox-runtime.js +310 -0
  57. package/dist/security/security-scanner.d.ts +92 -0
  58. package/dist/security/security-scanner.d.ts.map +1 -0
  59. package/dist/security/security-scanner.js +273 -0
  60. package/examples/{enhanced-kernel-example.ts → kernel-features-example.ts} +6 -6
  61. package/examples/phase2-integration.ts +355 -0
  62. package/package.json +2 -2
  63. package/src/api-registry-plugin.test.ts +20 -20
  64. package/src/dependency-resolver.test.ts +287 -0
  65. package/src/dependency-resolver.ts +388 -0
  66. package/src/health-monitor.test.ts +81 -0
  67. package/src/health-monitor.ts +316 -0
  68. package/src/hot-reload.ts +388 -0
  69. package/src/index.ts +6 -1
  70. package/src/kernel-base.ts +2 -2
  71. package/src/kernel.test.ts +469 -134
  72. package/src/kernel.ts +464 -78
  73. package/src/lite-kernel.test.ts +200 -0
  74. package/src/lite-kernel.ts +135 -0
  75. package/src/logger.ts +64 -18
  76. package/src/plugin-loader.test.ts +10 -1
  77. package/src/plugin-loader.ts +42 -13
  78. package/src/security/index.ts +19 -0
  79. package/src/security/permission-manager.test.ts +256 -0
  80. package/src/security/permission-manager.ts +336 -0
  81. package/src/security/plugin-signature-verifier.ts +3 -3
  82. package/src/security/sandbox-runtime.ts +432 -0
  83. package/src/security/security-scanner.ts +365 -0
  84. package/dist/enhanced-kernel.d.ts +0 -103
  85. package/dist/enhanced-kernel.d.ts.map +0 -1
  86. package/dist/enhanced-kernel.js +0 -403
  87. package/dist/enhanced-kernel.test.d.ts +0 -2
  88. package/dist/enhanced-kernel.test.d.ts.map +0 -1
  89. package/dist/enhanced-kernel.test.js +0 -412
  90. package/src/enhanced-kernel.test.ts +0 -535
  91. package/src/enhanced-kernel.ts +0 -496
@@ -0,0 +1,112 @@
1
+ import { createLogger } from './logger.js';
2
+ import { ObjectKernelBase } from './kernel-base.js';
3
+ /**
4
+ * ObjectKernel - MiniKernel Architecture
5
+ *
6
+ * A highly modular, plugin-based microkernel that:
7
+ * - Manages plugin lifecycle (init, start, destroy)
8
+ * - Provides dependency injection via service registry
9
+ * - Implements event/hook system for inter-plugin communication
10
+ * - Handles dependency resolution (topological sort)
11
+ * - Provides configurable logging for server and browser
12
+ *
13
+ * Core philosophy:
14
+ * - Business logic is completely separated into plugins
15
+ * - Kernel only manages lifecycle, DI, and hooks
16
+ * - Plugins are loaded as equal building blocks
17
+ */
18
+ export class LiteKernel extends ObjectKernelBase {
19
+ constructor(config) {
20
+ const logger = createLogger(config?.logger);
21
+ super(logger);
22
+ // Initialize context after logger is created
23
+ this.context = this.createContext();
24
+ }
25
+ /**
26
+ * Register a plugin
27
+ * @param plugin - Plugin instance
28
+ */
29
+ use(plugin) {
30
+ this.validateIdle();
31
+ const pluginName = plugin.name;
32
+ if (this.plugins.has(pluginName)) {
33
+ throw new Error(`[Kernel] Plugin '${pluginName}' already registered`);
34
+ }
35
+ this.plugins.set(pluginName, plugin);
36
+ return this;
37
+ }
38
+ /**
39
+ * Bootstrap the kernel
40
+ * 1. Resolve dependencies (topological sort)
41
+ * 2. Init phase - plugins register services
42
+ * 3. Start phase - plugins execute business logic
43
+ * 4. Trigger 'kernel:ready' hook
44
+ */
45
+ async bootstrap() {
46
+ this.validateState('idle');
47
+ this.state = 'initializing';
48
+ this.logger.info('Bootstrap started');
49
+ // Resolve dependencies
50
+ const orderedPlugins = this.resolveDependencies();
51
+ // Phase 1: Init - Plugins register services
52
+ this.logger.info('Phase 1: Init plugins');
53
+ for (const plugin of orderedPlugins) {
54
+ await this.runPluginInit(plugin);
55
+ }
56
+ // Phase 2: Start - Plugins execute business logic
57
+ this.logger.info('Phase 2: Start plugins');
58
+ this.state = 'running';
59
+ for (const plugin of orderedPlugins) {
60
+ await this.runPluginStart(plugin);
61
+ }
62
+ // Trigger ready hook
63
+ await this.triggerHook('kernel:ready');
64
+ this.logger.info('✅ Bootstrap complete', {
65
+ pluginCount: this.plugins.size
66
+ });
67
+ }
68
+ /**
69
+ * Shutdown the kernel
70
+ * Calls destroy on all plugins in reverse order
71
+ */
72
+ async shutdown() {
73
+ await this.destroy();
74
+ }
75
+ /**
76
+ * Graceful shutdown - destroy all plugins in reverse order
77
+ */
78
+ async destroy() {
79
+ if (this.state === 'stopped') {
80
+ this.logger.warn('Kernel already stopped');
81
+ return;
82
+ }
83
+ this.state = 'stopping';
84
+ this.logger.info('Shutdown started');
85
+ // Trigger shutdown hook
86
+ await this.triggerHook('kernel:shutdown');
87
+ // Destroy plugins in reverse order
88
+ const orderedPlugins = this.resolveDependencies();
89
+ for (const plugin of orderedPlugins.reverse()) {
90
+ await this.runPluginDestroy(plugin);
91
+ }
92
+ this.state = 'stopped';
93
+ this.logger.info('✅ Shutdown complete');
94
+ // Cleanup logger resources
95
+ if (this.logger && typeof this.logger.destroy === 'function') {
96
+ await this.logger.destroy();
97
+ }
98
+ }
99
+ /**
100
+ * Get a service from the registry
101
+ * Convenience method for external access
102
+ */
103
+ getService(name) {
104
+ return this.context.getService(name);
105
+ }
106
+ /**
107
+ * Check if kernel is running
108
+ */
109
+ isRunning() {
110
+ return this.state === 'running';
111
+ }
112
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=lite-kernel.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lite-kernel.test.d.ts","sourceRoot":"","sources":["../src/lite-kernel.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,161 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { LiteKernel } from './lite-kernel';
3
+ describe('LiteKernel with Configurable Logger', () => {
4
+ let kernel;
5
+ beforeEach(() => {
6
+ kernel = new LiteKernel();
7
+ });
8
+ describe('Logger Configuration', () => {
9
+ it('should create kernel with default logger', () => {
10
+ expect(kernel).toBeDefined();
11
+ });
12
+ it('should create kernel with custom logger config', async () => {
13
+ const customKernel = new LiteKernel({
14
+ logger: {
15
+ level: 'debug',
16
+ format: 'pretty',
17
+ sourceLocation: true
18
+ }
19
+ });
20
+ expect(customKernel).toBeDefined();
21
+ // Cleanup
22
+ await customKernel.bootstrap();
23
+ await customKernel.shutdown();
24
+ });
25
+ it('should create kernel with file logging config', async () => {
26
+ const fileKernel = new LiteKernel({
27
+ logger: {
28
+ level: 'info',
29
+ format: 'json',
30
+ file: '/tmp/test-kernel.log'
31
+ }
32
+ });
33
+ expect(fileKernel).toBeDefined();
34
+ // Cleanup
35
+ await fileKernel.bootstrap();
36
+ await fileKernel.shutdown();
37
+ });
38
+ });
39
+ describe('Plugin Context Logger', () => {
40
+ it('should provide logger to plugins', async () => {
41
+ let loggerReceived = false;
42
+ const testPlugin = {
43
+ name: 'test-plugin',
44
+ init: async (ctx) => {
45
+ if (ctx.logger) {
46
+ loggerReceived = true;
47
+ ctx.logger.info('Plugin initialized', { plugin: 'test-plugin' });
48
+ }
49
+ }
50
+ };
51
+ kernel.use(testPlugin);
52
+ await kernel.bootstrap();
53
+ expect(loggerReceived).toBe(true);
54
+ await kernel.shutdown();
55
+ });
56
+ it('should allow plugins to use all log levels', async () => {
57
+ const logCalls = [];
58
+ const loggingPlugin = {
59
+ name: 'logging-plugin',
60
+ init: async (ctx) => {
61
+ ctx.logger.debug('Debug message');
62
+ logCalls.push('debug');
63
+ ctx.logger.info('Info message');
64
+ logCalls.push('info');
65
+ ctx.logger.warn('Warning message');
66
+ logCalls.push('warn');
67
+ ctx.logger.error('Error message');
68
+ logCalls.push('error');
69
+ }
70
+ };
71
+ kernel.use(loggingPlugin);
72
+ await kernel.bootstrap();
73
+ expect(logCalls).toContain('debug');
74
+ expect(logCalls).toContain('info');
75
+ expect(logCalls).toContain('warn');
76
+ expect(logCalls).toContain('error');
77
+ await kernel.shutdown();
78
+ });
79
+ it('should support metadata in logs', async () => {
80
+ const metadataPlugin = {
81
+ name: 'metadata-plugin',
82
+ init: async (ctx) => {
83
+ ctx.logger.info('User action', {
84
+ userId: '123',
85
+ action: 'create',
86
+ resource: 'document'
87
+ });
88
+ }
89
+ };
90
+ kernel.use(metadataPlugin);
91
+ await kernel.bootstrap();
92
+ await kernel.shutdown();
93
+ });
94
+ });
95
+ describe('Kernel Lifecycle Logging', () => {
96
+ it('should log bootstrap process', async () => {
97
+ const plugin = {
98
+ name: 'lifecycle-test',
99
+ init: async () => {
100
+ // Init logic
101
+ },
102
+ start: async () => {
103
+ // Start logic
104
+ }
105
+ };
106
+ kernel.use(plugin);
107
+ await kernel.bootstrap();
108
+ expect(kernel.isRunning()).toBe(true);
109
+ await kernel.shutdown();
110
+ });
111
+ it('should log shutdown process', async () => {
112
+ const plugin = {
113
+ name: 'shutdown-test',
114
+ init: async () => { },
115
+ destroy: async () => {
116
+ // Cleanup
117
+ }
118
+ };
119
+ kernel.use(plugin);
120
+ await kernel.bootstrap();
121
+ await kernel.shutdown();
122
+ expect(kernel.getState()).toBe('stopped');
123
+ });
124
+ });
125
+ describe('Environment Compatibility', () => {
126
+ it('should work in Node.js environment', async () => {
127
+ const nodeKernel = new LiteKernel({
128
+ logger: {
129
+ level: 'info',
130
+ format: 'json'
131
+ }
132
+ });
133
+ const plugin = {
134
+ name: 'node-test',
135
+ init: async (ctx) => {
136
+ ctx.logger.info('Running in Node.js');
137
+ }
138
+ };
139
+ nodeKernel.use(plugin);
140
+ await nodeKernel.bootstrap();
141
+ await nodeKernel.shutdown();
142
+ });
143
+ it('should support browser-friendly logging', async () => {
144
+ const browserKernel = new LiteKernel({
145
+ logger: {
146
+ level: 'info',
147
+ format: 'pretty'
148
+ }
149
+ });
150
+ const plugin = {
151
+ name: 'browser-test',
152
+ init: async (ctx) => {
153
+ ctx.logger.info('Browser-friendly format');
154
+ }
155
+ };
156
+ browserKernel.use(plugin);
157
+ await browserKernel.bootstrap();
158
+ await browserKernel.shutdown();
159
+ });
160
+ });
161
+ });
package/dist/logger.d.ts CHANGED
@@ -20,6 +20,7 @@ export declare class ObjectLogger implements Logger {
20
20
  private isNode;
21
21
  private pinoLogger?;
22
22
  private pinoInstance?;
23
+ private require?;
23
24
  constructor(config?: Partial<LoggerConfig>);
24
25
  /**
25
26
  * Initialize Pino logger for Node.js
@@ -43,8 +44,8 @@ export declare class ObjectLogger implements Logger {
43
44
  debug(message: string, meta?: Record<string, any>): void;
44
45
  info(message: string, meta?: Record<string, any>): void;
45
46
  warn(message: string, meta?: Record<string, any>): void;
46
- error(message: string, error?: Error, meta?: Record<string, any>): void;
47
- fatal(message: string, error?: Error, meta?: Record<string, any>): void;
47
+ error(message: string, errorOrMeta?: Error | Record<string, any>, meta?: Record<string, any>): void;
48
+ fatal(message: string, errorOrMeta?: Error | Record<string, any>, meta?: Record<string, any>): void;
48
49
  /**
49
50
  * Create a child logger with additional context
50
51
  * Note: Child loggers share the parent's Pino instance
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,0BAA0B,CAAC;AACvE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAE1D;;;;;;;;;;;;;;GAcG;AACH,qBAAa,YAAa,YAAW,MAAM;IACvC,OAAO,CAAC,MAAM,CAAkJ;IAChK,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,UAAU,CAAC,CAAM;IACzB,OAAO,CAAC,YAAY,CAAC,CAAM;gBAEf,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IAwB9C;;OAEG;IACH,OAAO,CAAC,cAAc;IA+EtB;;OAEG;IACH,OAAO,CAAC,eAAe;IAqBvB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAsCxB;;OAEG;IACH,OAAO,CAAC,UAAU;IAelB;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQxD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQvD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQvD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IASvE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IASvE;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,YAAY;IAYjD;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY;IAIzD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ9B;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;CAG7C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAEzE"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,0BAA0B,CAAC;AACvE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAE1D;;;;;;;;;;;;;;GAcG;AACH,qBAAa,YAAa,YAAW,MAAM;IACvC,OAAO,CAAC,MAAM,CAAkJ;IAChK,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,UAAU,CAAC,CAAM;IACzB,OAAO,CAAC,YAAY,CAAC,CAAM;IAC3B,OAAO,CAAC,OAAO,CAAC,CAAM;gBAEV,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IAwB9C;;OAEG;IACH,OAAO,CAAC,cAAc;IAuGtB;;OAEG;IACH,OAAO,CAAC,eAAe;IAqBvB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAuCxB;;OAEG;IACH,OAAO,CAAC,UAAU;IAelB;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQxD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQvD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQvD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAmBnG,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAmBnG;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,YAAY;IAYjD;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY;IAIzD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ9B;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;CAG7C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAEzE"}
package/dist/logger.js CHANGED
@@ -42,8 +42,12 @@ export class ObjectLogger {
42
42
  if (!this.isNode)
43
43
  return;
44
44
  try {
45
- // Dynamic import for Pino (Node.js only)
46
- const pino = require('pino');
45
+ // Create require function dynamically for Node.js (avoids bundling issues in browser)
46
+ // @ts-ignore - dynamic import of Node.js module
47
+ const { createRequire } = eval('require("module")');
48
+ this.require = createRequire(import.meta.url);
49
+ // Synchronous import for Pino using createRequire (works in ESM)
50
+ const pino = this.require('pino');
47
51
  // Build Pino options
48
52
  const pinoOptions = {
49
53
  level: this.config.level,
@@ -60,15 +64,35 @@ export class ObjectLogger {
60
64
  const targets = [];
61
65
  // Console transport
62
66
  if (this.config.format === 'pretty') {
63
- targets.push({
64
- target: 'pino-pretty',
65
- options: {
66
- colorize: true,
67
- translateTime: 'SYS:standard',
68
- ignore: 'pid,hostname'
69
- },
70
- level: this.config.level
71
- });
67
+ // Check if pino-pretty is available
68
+ let hasPretty = false;
69
+ try {
70
+ this.require.resolve('pino-pretty');
71
+ hasPretty = true;
72
+ }
73
+ catch (e) {
74
+ // ignore
75
+ }
76
+ if (hasPretty) {
77
+ targets.push({
78
+ target: 'pino-pretty',
79
+ options: {
80
+ colorize: true,
81
+ translateTime: 'SYS:standard',
82
+ ignore: 'pid,hostname'
83
+ },
84
+ level: this.config.level
85
+ });
86
+ }
87
+ else {
88
+ console.warn('[Logger] pino-pretty not found. Install it for pretty logging: pnpm add -D pino-pretty');
89
+ // Fallback to text/simple
90
+ targets.push({
91
+ target: 'pino/file',
92
+ options: { destination: 1 },
93
+ level: this.config.level
94
+ });
95
+ }
72
96
  }
73
97
  else if (this.config.format === 'json') {
74
98
  // JSON to stdout
@@ -155,7 +179,8 @@ export class ObjectLogger {
155
179
  info: '\x1b[32m', // Green
156
180
  warn: '\x1b[33m', // Yellow
157
181
  error: '\x1b[31m', // Red
158
- fatal: '\x1b[35m' // Magenta
182
+ fatal: '\x1b[35m', // Magenta
183
+ silent: ''
159
184
  };
160
185
  const reset = '\x1b[0m';
161
186
  const color = levelColors[level] || '';
@@ -206,22 +231,40 @@ export class ObjectLogger {
206
231
  this.logBrowser('warn', message, meta);
207
232
  }
208
233
  }
209
- error(message, error, meta) {
234
+ error(message, errorOrMeta, meta) {
235
+ let error;
236
+ let context = {};
237
+ if (errorOrMeta instanceof Error) {
238
+ error = errorOrMeta;
239
+ context = meta || {};
240
+ }
241
+ else {
242
+ context = errorOrMeta || {};
243
+ }
210
244
  if (this.isNode && this.pinoLogger) {
211
- const errorContext = error ? { err: error, ...meta } : meta || {};
245
+ const errorContext = error ? { err: error, ...context } : context;
212
246
  this.pinoLogger.error(errorContext, message);
213
247
  }
214
248
  else {
215
- this.logBrowser('error', message, meta, error);
249
+ this.logBrowser('error', message, context, error);
216
250
  }
217
251
  }
218
- fatal(message, error, meta) {
252
+ fatal(message, errorOrMeta, meta) {
253
+ let error;
254
+ let context = {};
255
+ if (errorOrMeta instanceof Error) {
256
+ error = errorOrMeta;
257
+ context = meta || {};
258
+ }
259
+ else {
260
+ context = errorOrMeta || {};
261
+ }
219
262
  if (this.isNode && this.pinoLogger) {
220
- const errorContext = error ? { err: error, ...meta } : meta || {};
263
+ const errorContext = error ? { err: error, ...context } : context;
221
264
  this.pinoLogger.fatal(errorContext, message);
222
265
  }
223
266
  else {
224
- this.logBrowser('fatal', message, meta, error);
267
+ this.logBrowser('fatal', message, context, error);
225
268
  }
226
269
  }
227
270
  /**
@@ -96,11 +96,22 @@ export interface VersionCompatibility {
96
96
  */
97
97
  export declare class PluginLoader {
98
98
  private logger;
99
+ private context?;
100
+ private configValidator;
99
101
  private loadedPlugins;
100
102
  private serviceFactories;
101
103
  private serviceInstances;
102
104
  private scopedServices;
105
+ private creating;
103
106
  constructor(logger: Logger);
107
+ /**
108
+ * Set the plugin context for service factories
109
+ */
110
+ setContext(context: PluginContext): void;
111
+ /**
112
+ * Get a synchronous service instance if it exists (Sync Helper)
113
+ */
114
+ getServiceInstance<T>(name: string): T | undefined;
104
115
  /**
105
116
  * Load a plugin asynchronously with validation
106
117
  */
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-loader.d.ts","sourceRoot":"","sources":["../src/plugin-loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin-loader.d.ts","sourceRoot":"","sources":["../src/plugin-loader.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { PluginConfigValidator } from './security/plugin-config-validator.js';
1
2
  /**
2
3
  * Service Lifecycle Types
3
4
  * Defines how services are instantiated and managed
@@ -21,7 +22,21 @@ export class PluginLoader {
21
22
  this.serviceFactories = new Map();
22
23
  this.serviceInstances = new Map();
23
24
  this.scopedServices = new Map();
25
+ this.creating = new Set();
24
26
  this.logger = logger;
27
+ this.configValidator = new PluginConfigValidator(logger);
28
+ }
29
+ /**
30
+ * Set the plugin context for service factories
31
+ */
32
+ setContext(context) {
33
+ this.context = context;
34
+ }
35
+ /**
36
+ * Get a synchronous service instance if it exists (Sync Helper)
37
+ */
38
+ getServiceInstance(name) {
39
+ return this.serviceInstances.get(name);
25
40
  }
26
41
  /**
27
42
  * Load a plugin asynchronously with validation
@@ -234,14 +249,14 @@ export class PluginLoader {
234
249
  if (!plugin.configSchema) {
235
250
  return;
236
251
  }
237
- if (!config) {
238
- this.logger.debug(`Plugin ${plugin.name} has configuration schema but no config provided`);
252
+ if (config === undefined) {
253
+ // In loadPlugin, we often don't have the config yet.
254
+ // We skip validation here or valid against empty object if schema allows?
255
+ // For now, let's keep the logging behavior but note it's delegating
256
+ this.logger.debug(`Plugin ${plugin.name} has configuration schema (config validation postponed)`);
239
257
  return;
240
258
  }
241
- // Configuration validation is now implemented in PluginConfigValidator
242
- // This is a placeholder that logs the validation would happen
243
- // The actual validation should be done by the caller when config is available
244
- this.logger.debug(`Plugin ${plugin.name} has configuration schema (use PluginConfigValidator for validation)`);
259
+ this.configValidator.validatePluginConfig(plugin, config);
245
260
  }
246
261
  async verifyPluginSignature(plugin) {
247
262
  if (!plugin.signature) {
@@ -281,9 +296,18 @@ export class PluginLoader {
281
296
  return instance;
282
297
  }
283
298
  async createServiceInstance(registration) {
284
- // This is a simplified version - in real implementation,
285
- // we would need to pass proper context with resolved dependencies
286
- const mockContext = {};
287
- return await registration.factory(mockContext);
299
+ if (!this.context) {
300
+ throw new Error(`[PluginLoader] Context not set - cannot create service '${registration.name}'`);
301
+ }
302
+ if (this.creating.has(registration.name)) {
303
+ throw new Error(`Circular dependency detected: ${Array.from(this.creating).join(' -> ')} -> ${registration.name}`);
304
+ }
305
+ this.creating.add(registration.name);
306
+ try {
307
+ return await registration.factory(this.context);
308
+ }
309
+ finally {
310
+ this.creating.delete(registration.name);
311
+ }
288
312
  }
289
313
  }
@@ -6,6 +6,15 @@ describe('PluginLoader', () => {
6
6
  beforeEach(() => {
7
7
  const logger = createLogger({ level: 'error' }); // Suppress logs in tests
8
8
  loader = new PluginLoader(logger);
9
+ loader.setContext({
10
+ registerService: () => { },
11
+ getService: () => { throw new Error('Mock service not found'); },
12
+ hook: () => { },
13
+ trigger: async () => { },
14
+ getServices: () => new Map(),
15
+ logger: logger,
16
+ getKernel: () => ({})
17
+ });
9
18
  });
10
19
  describe('Plugin Loading', () => {
11
20
  it('should load a valid plugin', async () => {
@@ -11,4 +11,7 @@
11
11
  export { PluginSignatureVerifier, type PluginSignatureConfig, type SignatureVerificationResult, } from './plugin-signature-verifier.js';
12
12
  export { PluginConfigValidator, createPluginConfigValidator, } from './plugin-config-validator.js';
13
13
  export { PluginPermissionEnforcer, SecurePluginContext, createPluginPermissionEnforcer, type PluginPermissions, type PermissionCheckResult, } from './plugin-permission-enforcer.js';
14
+ export { PluginPermissionManager, type PermissionGrant, type PermissionCheckResult as PluginPermissionCheckResult, } from './permission-manager.js';
15
+ export { PluginSandboxRuntime, type SandboxContext, type ResourceUsage, } from './sandbox-runtime.js';
16
+ export { PluginSecurityScanner, type ScanTarget, type SecurityIssue, } from './security-scanner.js';
14
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,GACjC,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,qBAAqB,EACrB,2BAA2B,GAC5B,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,8BAA8B,EAC9B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,GAC3B,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,GACjC,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,qBAAqB,EACrB,2BAA2B,GAC5B,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,8BAA8B,EAC9B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,GAC3B,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EACL,uBAAuB,EACvB,KAAK,eAAe,EACpB,KAAK,qBAAqB,IAAI,2BAA2B,GAC1D,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,aAAa,GACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,qBAAqB,EACrB,KAAK,UAAU,EACf,KAAK,aAAa,GACnB,MAAM,uBAAuB,CAAC"}
@@ -11,3 +11,7 @@
11
11
  export { PluginSignatureVerifier, } from './plugin-signature-verifier.js';
12
12
  export { PluginConfigValidator, createPluginConfigValidator, } from './plugin-config-validator.js';
13
13
  export { PluginPermissionEnforcer, SecurePluginContext, createPluginPermissionEnforcer, } from './plugin-permission-enforcer.js';
14
+ // Advanced security components (Phase 2)
15
+ export { PluginPermissionManager, } from './permission-manager.js';
16
+ export { PluginSandboxRuntime, } from './sandbox-runtime.js';
17
+ export { PluginSecurityScanner, } from './security-scanner.js';