@objectstack/core 1.0.2 → 1.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.
Files changed (125) hide show
  1. package/.turbo/turbo-build.log +58 -0
  2. package/CHANGELOG.md +25 -0
  3. package/dist/index.cjs +4294 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +1777 -0
  6. package/dist/index.d.ts +1776 -21
  7. package/dist/index.js +4246 -23
  8. package/dist/index.js.map +1 -0
  9. package/package.json +4 -4
  10. package/tsconfig.json +1 -3
  11. package/dist/api-registry-plugin.d.ts +0 -54
  12. package/dist/api-registry-plugin.d.ts.map +0 -1
  13. package/dist/api-registry-plugin.js +0 -53
  14. package/dist/api-registry-plugin.test.d.ts +0 -2
  15. package/dist/api-registry-plugin.test.d.ts.map +0 -1
  16. package/dist/api-registry-plugin.test.js +0 -334
  17. package/dist/api-registry.d.ts +0 -259
  18. package/dist/api-registry.d.ts.map +0 -1
  19. package/dist/api-registry.js +0 -600
  20. package/dist/api-registry.test.d.ts +0 -2
  21. package/dist/api-registry.test.d.ts.map +0 -1
  22. package/dist/api-registry.test.js +0 -957
  23. package/dist/contracts/data-engine.d.ts +0 -62
  24. package/dist/contracts/data-engine.d.ts.map +0 -1
  25. package/dist/contracts/data-engine.js +0 -1
  26. package/dist/contracts/http-server.d.ts +0 -119
  27. package/dist/contracts/http-server.d.ts.map +0 -1
  28. package/dist/contracts/http-server.js +0 -11
  29. package/dist/contracts/logger.d.ts +0 -63
  30. package/dist/contracts/logger.d.ts.map +0 -1
  31. package/dist/contracts/logger.js +0 -1
  32. package/dist/dependency-resolver.d.ts +0 -62
  33. package/dist/dependency-resolver.d.ts.map +0 -1
  34. package/dist/dependency-resolver.js +0 -317
  35. package/dist/dependency-resolver.test.d.ts +0 -2
  36. package/dist/dependency-resolver.test.d.ts.map +0 -1
  37. package/dist/dependency-resolver.test.js +0 -241
  38. package/dist/health-monitor.d.ts +0 -65
  39. package/dist/health-monitor.d.ts.map +0 -1
  40. package/dist/health-monitor.js +0 -269
  41. package/dist/health-monitor.test.d.ts +0 -2
  42. package/dist/health-monitor.test.d.ts.map +0 -1
  43. package/dist/health-monitor.test.js +0 -68
  44. package/dist/hot-reload.d.ts +0 -79
  45. package/dist/hot-reload.d.ts.map +0 -1
  46. package/dist/hot-reload.js +0 -313
  47. package/dist/index.d.ts.map +0 -1
  48. package/dist/kernel-base.d.ts +0 -84
  49. package/dist/kernel-base.d.ts.map +0 -1
  50. package/dist/kernel-base.js +0 -219
  51. package/dist/kernel.d.ts +0 -113
  52. package/dist/kernel.d.ts.map +0 -1
  53. package/dist/kernel.js +0 -472
  54. package/dist/kernel.test.d.ts +0 -2
  55. package/dist/kernel.test.d.ts.map +0 -1
  56. package/dist/kernel.test.js +0 -414
  57. package/dist/lite-kernel.d.ts +0 -55
  58. package/dist/lite-kernel.d.ts.map +0 -1
  59. package/dist/lite-kernel.js +0 -112
  60. package/dist/lite-kernel.test.d.ts +0 -2
  61. package/dist/lite-kernel.test.d.ts.map +0 -1
  62. package/dist/lite-kernel.test.js +0 -161
  63. package/dist/logger.d.ts +0 -71
  64. package/dist/logger.d.ts.map +0 -1
  65. package/dist/logger.js +0 -312
  66. package/dist/logger.test.d.ts +0 -2
  67. package/dist/logger.test.d.ts.map +0 -1
  68. package/dist/logger.test.js +0 -92
  69. package/dist/plugin-loader.d.ts +0 -164
  70. package/dist/plugin-loader.d.ts.map +0 -1
  71. package/dist/plugin-loader.js +0 -319
  72. package/dist/plugin-loader.test.d.ts +0 -2
  73. package/dist/plugin-loader.test.d.ts.map +0 -1
  74. package/dist/plugin-loader.test.js +0 -348
  75. package/dist/qa/adapter.d.ts +0 -14
  76. package/dist/qa/adapter.d.ts.map +0 -1
  77. package/dist/qa/adapter.js +0 -1
  78. package/dist/qa/http-adapter.d.ts +0 -16
  79. package/dist/qa/http-adapter.d.ts.map +0 -1
  80. package/dist/qa/http-adapter.js +0 -107
  81. package/dist/qa/index.d.ts +0 -4
  82. package/dist/qa/index.d.ts.map +0 -1
  83. package/dist/qa/index.js +0 -3
  84. package/dist/qa/runner.d.ts +0 -27
  85. package/dist/qa/runner.d.ts.map +0 -1
  86. package/dist/qa/runner.js +0 -157
  87. package/dist/security/index.d.ts +0 -17
  88. package/dist/security/index.d.ts.map +0 -1
  89. package/dist/security/index.js +0 -17
  90. package/dist/security/permission-manager.d.ts +0 -96
  91. package/dist/security/permission-manager.d.ts.map +0 -1
  92. package/dist/security/permission-manager.js +0 -235
  93. package/dist/security/permission-manager.test.d.ts +0 -2
  94. package/dist/security/permission-manager.test.d.ts.map +0 -1
  95. package/dist/security/permission-manager.test.js +0 -220
  96. package/dist/security/plugin-config-validator.d.ts +0 -79
  97. package/dist/security/plugin-config-validator.d.ts.map +0 -1
  98. package/dist/security/plugin-config-validator.js +0 -166
  99. package/dist/security/plugin-config-validator.test.d.ts +0 -2
  100. package/dist/security/plugin-config-validator.test.d.ts.map +0 -1
  101. package/dist/security/plugin-config-validator.test.js +0 -223
  102. package/dist/security/plugin-permission-enforcer.d.ts +0 -154
  103. package/dist/security/plugin-permission-enforcer.d.ts.map +0 -1
  104. package/dist/security/plugin-permission-enforcer.js +0 -323
  105. package/dist/security/plugin-permission-enforcer.test.d.ts +0 -2
  106. package/dist/security/plugin-permission-enforcer.test.d.ts.map +0 -1
  107. package/dist/security/plugin-permission-enforcer.test.js +0 -205
  108. package/dist/security/plugin-signature-verifier.d.ts +0 -96
  109. package/dist/security/plugin-signature-verifier.d.ts.map +0 -1
  110. package/dist/security/plugin-signature-verifier.js +0 -250
  111. package/dist/security/sandbox-runtime.d.ts +0 -115
  112. package/dist/security/sandbox-runtime.d.ts.map +0 -1
  113. package/dist/security/sandbox-runtime.js +0 -311
  114. package/dist/security/security-scanner.d.ts +0 -92
  115. package/dist/security/security-scanner.d.ts.map +0 -1
  116. package/dist/security/security-scanner.js +0 -273
  117. package/dist/types.d.ts +0 -89
  118. package/dist/types.d.ts.map +0 -1
  119. package/dist/types.js +0 -1
  120. package/dist/utils/env.d.ts +0 -20
  121. package/dist/utils/env.d.ts.map +0 -1
  122. package/dist/utils/env.js +0 -46
  123. package/dist/utils/env.test.d.ts +0 -2
  124. package/dist/utils/env.test.d.ts.map +0 -1
  125. package/dist/utils/env.test.js +0 -52
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@objectstack/core",
3
- "version": "1.0.2",
3
+ "version": "1.0.5",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Microkernel Core for ObjectStack",
6
6
  "type": "module",
@@ -12,10 +12,10 @@
12
12
  "@types/node": "^25.1.0"
13
13
  },
14
14
  "dependencies": {
15
- "pino": "^8.17.0",
15
+ "pino": "^10.3.0",
16
16
  "pino-pretty": "^10.3.0",
17
17
  "zod": "^4.3.6",
18
- "@objectstack/spec": "1.0.2"
18
+ "@objectstack/spec": "1.0.5"
19
19
  },
20
20
  "peerDependencies": {
21
21
  "pino": "^8.0.0"
@@ -26,7 +26,7 @@
26
26
  }
27
27
  },
28
28
  "scripts": {
29
- "build": "tsc",
29
+ "build": "tsup --config ../../tsup.config.ts",
30
30
  "test": "vitest run",
31
31
  "test:watch": "vitest"
32
32
  }
package/tsconfig.json CHANGED
@@ -2,9 +2,7 @@
2
2
  "extends": "../../tsconfig.json",
3
3
  "compilerOptions": {
4
4
  "outDir": "./dist",
5
- "rootDir": "./src",
6
- "moduleResolution": "bundler",
7
- "module": "esnext"
5
+ "rootDir": "./src"
8
6
  },
9
7
  "include": ["src/**/*"],
10
8
  "exclude": []
@@ -1,54 +0,0 @@
1
- import type { Plugin } from './types.js';
2
- import type { ConflictResolutionStrategy } from '@objectstack/spec/api';
3
- /**
4
- * API Registry Plugin Configuration
5
- */
6
- export interface ApiRegistryPluginConfig {
7
- /**
8
- * Conflict resolution strategy for route conflicts
9
- * @default 'error'
10
- */
11
- conflictResolution?: ConflictResolutionStrategy;
12
- /**
13
- * Registry version
14
- * @default '1.0.0'
15
- */
16
- version?: string;
17
- }
18
- /**
19
- * API Registry Plugin
20
- *
21
- * Registers the API Registry service in the kernel, making it available
22
- * to all plugins for endpoint registration and discovery.
23
- *
24
- * **Usage:**
25
- * ```typescript
26
- * const kernel = new ObjectKernel();
27
- *
28
- * // Register API Registry Plugin
29
- * kernel.use(createApiRegistryPlugin({ conflictResolution: 'priority' }));
30
- *
31
- * // In other plugins, access the API Registry
32
- * const plugin: Plugin = {
33
- * name: 'my-plugin',
34
- * init: async (ctx) => {
35
- * const registry = ctx.getService<ApiRegistry>('api-registry');
36
- *
37
- * // Register plugin APIs
38
- * registry.registerApi({
39
- * id: 'my_plugin_api',
40
- * name: 'My Plugin API',
41
- * type: 'rest',
42
- * version: 'v1',
43
- * basePath: '/api/v1/my-plugin',
44
- * endpoints: [...]
45
- * });
46
- * }
47
- * };
48
- * ```
49
- *
50
- * @param config - Plugin configuration
51
- * @returns Plugin instance
52
- */
53
- export declare function createApiRegistryPlugin(config?: ApiRegistryPluginConfig): Plugin;
54
- //# sourceMappingURL=api-registry-plugin.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"api-registry-plugin.d.ts","sourceRoot":"","sources":["../src/api-registry-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,YAAY,CAAC;AAExD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAExE;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,0BAA0B,CAAC;IAEhD;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,GAAE,uBAA4B,GACnC,MAAM,CA2BR"}
@@ -1,53 +0,0 @@
1
- import { ApiRegistry } from './api-registry.js';
2
- /**
3
- * API Registry Plugin
4
- *
5
- * Registers the API Registry service in the kernel, making it available
6
- * to all plugins for endpoint registration and discovery.
7
- *
8
- * **Usage:**
9
- * ```typescript
10
- * const kernel = new ObjectKernel();
11
- *
12
- * // Register API Registry Plugin
13
- * kernel.use(createApiRegistryPlugin({ conflictResolution: 'priority' }));
14
- *
15
- * // In other plugins, access the API Registry
16
- * const plugin: Plugin = {
17
- * name: 'my-plugin',
18
- * init: async (ctx) => {
19
- * const registry = ctx.getService<ApiRegistry>('api-registry');
20
- *
21
- * // Register plugin APIs
22
- * registry.registerApi({
23
- * id: 'my_plugin_api',
24
- * name: 'My Plugin API',
25
- * type: 'rest',
26
- * version: 'v1',
27
- * basePath: '/api/v1/my-plugin',
28
- * endpoints: [...]
29
- * });
30
- * }
31
- * };
32
- * ```
33
- *
34
- * @param config - Plugin configuration
35
- * @returns Plugin instance
36
- */
37
- export function createApiRegistryPlugin(config = {}) {
38
- const { conflictResolution = 'error', version = '1.0.0', } = config;
39
- return {
40
- name: 'com.objectstack.core.api-registry',
41
- version: '1.0.0',
42
- init: async (ctx) => {
43
- // Create API Registry instance
44
- const registry = new ApiRegistry(ctx.logger, conflictResolution, version);
45
- // Register as a service
46
- ctx.registerService('api-registry', registry);
47
- ctx.logger.info('API Registry plugin initialized', {
48
- conflictResolution,
49
- version,
50
- });
51
- },
52
- };
53
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=api-registry-plugin.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"api-registry-plugin.test.d.ts","sourceRoot":"","sources":["../src/api-registry-plugin.test.ts"],"names":[],"mappings":""}
@@ -1,334 +0,0 @@
1
- import { describe, it, expect, beforeEach } from 'vitest';
2
- import { ObjectKernel } from './kernel';
3
- import { createApiRegistryPlugin } from './api-registry-plugin';
4
- import { ApiRegistry } from './api-registry';
5
- describe('API Registry Plugin', () => {
6
- let kernel;
7
- beforeEach(() => {
8
- kernel = new ObjectKernel({
9
- skipSystemValidation: true
10
- });
11
- });
12
- describe('Plugin Registration', () => {
13
- it('should register API Registry as a service', async () => {
14
- await kernel.use(createApiRegistryPlugin());
15
- await kernel.bootstrap();
16
- const registry = kernel.getService('api-registry');
17
- expect(registry).toBeDefined();
18
- expect(registry).toBeInstanceOf(ApiRegistry);
19
- await kernel.shutdown();
20
- });
21
- it('should register with custom conflict resolution', async () => {
22
- await kernel.use(createApiRegistryPlugin({
23
- conflictResolution: 'priority',
24
- version: '2.0.0',
25
- }));
26
- await kernel.bootstrap();
27
- const registry = kernel.getService('api-registry');
28
- const snapshot = registry.getRegistry();
29
- expect(snapshot.conflictResolution).toBe('priority');
30
- expect(snapshot.version).toBe('2.0.0');
31
- await kernel.shutdown();
32
- });
33
- });
34
- describe('Integration with Plugins', () => {
35
- it('should allow plugins to register APIs', async () => {
36
- await kernel.use(createApiRegistryPlugin());
37
- const testPlugin = {
38
- name: 'test-plugin',
39
- init: async (ctx) => {
40
- const registry = ctx.getService('api-registry');
41
- const api = {
42
- id: 'test_api',
43
- name: 'Test API',
44
- type: 'rest',
45
- version: 'v1',
46
- basePath: '/api/test',
47
- endpoints: [
48
- {
49
- id: 'get_test',
50
- method: 'GET',
51
- path: '/api/test/hello',
52
- summary: 'Test endpoint',
53
- responses: [
54
- {
55
- statusCode: 200,
56
- description: 'Success',
57
- },
58
- ],
59
- },
60
- ],
61
- };
62
- registry.registerApi(api);
63
- },
64
- };
65
- await kernel.use(testPlugin);
66
- await kernel.bootstrap();
67
- const registry = kernel.getService('api-registry');
68
- const api = registry.getApi('test_api');
69
- expect(api).toBeDefined();
70
- expect(api?.name).toBe('Test API');
71
- expect(api?.endpoints.length).toBe(1);
72
- await kernel.shutdown();
73
- });
74
- it('should allow multiple plugins to register APIs', async () => {
75
- await kernel.use(createApiRegistryPlugin());
76
- const plugin1 = {
77
- name: 'plugin-1',
78
- init: async (ctx) => {
79
- const registry = ctx.getService('api-registry');
80
- registry.registerApi({
81
- id: 'api1',
82
- name: 'API 1',
83
- type: 'rest',
84
- version: 'v1',
85
- basePath: '/api/plugin1',
86
- endpoints: [
87
- {
88
- id: 'endpoint1',
89
- method: 'GET',
90
- path: '/api/plugin1/data',
91
- responses: [],
92
- },
93
- ],
94
- });
95
- },
96
- };
97
- const plugin2 = {
98
- name: 'plugin-2',
99
- init: async (ctx) => {
100
- const registry = ctx.getService('api-registry');
101
- registry.registerApi({
102
- id: 'api2',
103
- name: 'API 2',
104
- type: 'graphql',
105
- version: 'v1',
106
- basePath: '/graphql',
107
- endpoints: [
108
- {
109
- id: 'query',
110
- path: '/graphql',
111
- responses: [],
112
- },
113
- ],
114
- });
115
- },
116
- };
117
- await kernel.use(plugin1);
118
- await kernel.use(plugin2);
119
- await kernel.bootstrap();
120
- const registry = kernel.getService('api-registry');
121
- const stats = registry.getStats();
122
- expect(stats.totalApis).toBe(2);
123
- expect(stats.apisByType.rest).toBe(1);
124
- expect(stats.apisByType.graphql).toBe(1);
125
- await kernel.shutdown();
126
- });
127
- it('should support API discovery across plugins', async () => {
128
- await kernel.use(createApiRegistryPlugin());
129
- const dataPlugin = {
130
- name: 'data-plugin',
131
- init: async (ctx) => {
132
- const registry = ctx.getService('api-registry');
133
- registry.registerApi({
134
- id: 'customer_api',
135
- name: 'Customer API',
136
- type: 'rest',
137
- version: 'v1',
138
- basePath: '/api/v1/customers',
139
- endpoints: [],
140
- metadata: {
141
- status: 'active',
142
- tags: ['crm', 'data'],
143
- },
144
- });
145
- registry.registerApi({
146
- id: 'product_api',
147
- name: 'Product API',
148
- type: 'rest',
149
- version: 'v1',
150
- basePath: '/api/v1/products',
151
- endpoints: [],
152
- metadata: {
153
- status: 'active',
154
- tags: ['inventory', 'data'],
155
- },
156
- });
157
- },
158
- };
159
- const analyticsPlugin = {
160
- name: 'analytics-plugin',
161
- init: async (ctx) => {
162
- const registry = ctx.getService('api-registry');
163
- registry.registerApi({
164
- id: 'analytics_api',
165
- name: 'Analytics API',
166
- type: 'rest',
167
- version: 'v1',
168
- basePath: '/api/v1/analytics',
169
- endpoints: [],
170
- metadata: {
171
- status: 'beta',
172
- tags: ['analytics', 'reporting'],
173
- },
174
- });
175
- },
176
- };
177
- await kernel.use(dataPlugin);
178
- await kernel.use(analyticsPlugin);
179
- await kernel.bootstrap();
180
- const registry = kernel.getService('api-registry');
181
- // Find all data APIs
182
- const dataApis = registry.findApis({ tags: ['data'] });
183
- expect(dataApis.total).toBe(2);
184
- // Find active APIs
185
- const activeApis = registry.findApis({ status: 'active' });
186
- expect(activeApis.total).toBe(2);
187
- // Find CRM APIs
188
- const crmApis = registry.findApis({ tags: ['crm'] });
189
- expect(crmApis.total).toBe(1);
190
- expect(crmApis.apis[0].id).toBe('customer_api');
191
- await kernel.shutdown();
192
- });
193
- it('should handle route conflicts based on strategy', async () => {
194
- await kernel.use(createApiRegistryPlugin({
195
- conflictResolution: 'priority',
196
- }));
197
- const corePlugin = {
198
- name: 'core-plugin',
199
- init: async (ctx) => {
200
- const registry = ctx.getService('api-registry');
201
- registry.registerApi({
202
- id: 'core_api',
203
- name: 'Core API',
204
- type: 'rest',
205
- version: 'v1',
206
- basePath: '/api',
207
- endpoints: [
208
- {
209
- id: 'core_endpoint',
210
- method: 'GET',
211
- path: '/api/data/:object',
212
- priority: 900, // High priority
213
- summary: 'Core data endpoint',
214
- responses: [],
215
- },
216
- ],
217
- });
218
- },
219
- };
220
- const pluginOverride = {
221
- name: 'plugin-override',
222
- init: async (ctx) => {
223
- const registry = ctx.getService('api-registry');
224
- registry.registerApi({
225
- id: 'plugin_api',
226
- name: 'Plugin API',
227
- type: 'rest',
228
- version: 'v1',
229
- basePath: '/api',
230
- endpoints: [
231
- {
232
- id: 'plugin_endpoint',
233
- method: 'GET',
234
- path: '/api/data/:object',
235
- priority: 300, // Lower priority
236
- summary: 'Plugin data endpoint',
237
- responses: [],
238
- },
239
- ],
240
- });
241
- },
242
- };
243
- await kernel.use(corePlugin);
244
- await kernel.use(pluginOverride);
245
- await kernel.bootstrap();
246
- const registry = kernel.getService('api-registry');
247
- const result = registry.findEndpointByRoute('GET', '/api/data/:object');
248
- // Core API should win due to higher priority
249
- expect(result?.api.id).toBe('core_api');
250
- expect(result?.endpoint.id).toBe('core_endpoint');
251
- await kernel.shutdown();
252
- });
253
- it('should support cleanup on plugin unload', async () => {
254
- await kernel.use(createApiRegistryPlugin());
255
- const dynamicPlugin = {
256
- name: 'dynamic-plugin',
257
- init: async (ctx) => {
258
- const registry = ctx.getService('api-registry');
259
- registry.registerApi({
260
- id: 'dynamic_api',
261
- name: 'Dynamic API',
262
- type: 'rest',
263
- version: 'v1',
264
- basePath: '/api/dynamic',
265
- endpoints: [
266
- {
267
- id: 'test',
268
- method: 'GET',
269
- path: '/api/dynamic/test',
270
- responses: [],
271
- },
272
- ],
273
- });
274
- },
275
- destroy: async () => {
276
- // In a real scenario, this would use ctx to access registry
277
- // For now, we'll test the registry's unregister capability
278
- },
279
- };
280
- await kernel.use(dynamicPlugin);
281
- await kernel.bootstrap();
282
- const registry = kernel.getService('api-registry');
283
- expect(registry.getApi('dynamic_api')).toBeDefined();
284
- // Unregister the API
285
- registry.unregisterApi('dynamic_api');
286
- expect(registry.getApi('dynamic_api')).toBeUndefined();
287
- await kernel.shutdown();
288
- });
289
- });
290
- describe('API Registry Lifecycle', () => {
291
- it('should be available during plugin start phase', async () => {
292
- await kernel.use(createApiRegistryPlugin());
293
- let registryAvailable = false;
294
- const testPlugin = {
295
- name: 'test-plugin',
296
- init: async () => {
297
- // Init phase
298
- },
299
- start: async (ctx) => {
300
- // Start phase - registry should be available
301
- const registry = ctx.getService('api-registry');
302
- registryAvailable = registry !== undefined;
303
- },
304
- };
305
- await kernel.use(testPlugin);
306
- await kernel.bootstrap();
307
- expect(registryAvailable).toBe(true);
308
- await kernel.shutdown();
309
- });
310
- it('should provide consistent registry across all plugins', async () => {
311
- await kernel.use(createApiRegistryPlugin());
312
- let registry1;
313
- let registry2;
314
- const plugin1 = {
315
- name: 'plugin-1',
316
- init: async (ctx) => {
317
- registry1 = ctx.getService('api-registry');
318
- },
319
- };
320
- const plugin2 = {
321
- name: 'plugin-2',
322
- init: async (ctx) => {
323
- registry2 = ctx.getService('api-registry');
324
- },
325
- };
326
- await kernel.use(plugin1);
327
- await kernel.use(plugin2);
328
- await kernel.bootstrap();
329
- // Same registry instance should be shared
330
- expect(registry1).toBe(registry2);
331
- await kernel.shutdown();
332
- });
333
- });
334
- });