@objectstack/core 4.0.1 → 4.0.3
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/.turbo/turbo-build.log +11 -11
- package/CHANGELOG.md +13 -0
- package/dist/index.cjs +66 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -1
- package/dist/index.d.ts +28 -1
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/fallbacks/fallbacks.test.ts +2 -2
- package/src/fallbacks/index.ts +3 -0
- package/src/fallbacks/memory-metadata.ts +50 -0
- package/src/kernel.ts +28 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectstack/core",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.3",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Microkernel Core for ObjectStack",
|
|
6
6
|
"type": "module",
|
|
@@ -14,15 +14,15 @@
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"@types/node": "^25.
|
|
17
|
+
"@types/node": "^25.6.0",
|
|
18
18
|
"typescript": "^6.0.2",
|
|
19
|
-
"vitest": "^4.1.
|
|
19
|
+
"vitest": "^4.1.4"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"pino": "^10.3.1",
|
|
23
23
|
"pino-pretty": "^13.1.3",
|
|
24
24
|
"zod": "^4.3.6",
|
|
25
|
-
"@objectstack/spec": "4.0.
|
|
25
|
+
"@objectstack/spec": "4.0.3"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"pino": "^8.0.0"
|
|
@@ -6,8 +6,8 @@ import { createMemoryI18n, resolveLocale } from './memory-i18n';
|
|
|
6
6
|
import { CORE_FALLBACK_FACTORIES } from './index';
|
|
7
7
|
|
|
8
8
|
describe('CORE_FALLBACK_FACTORIES', () => {
|
|
9
|
-
it('should have exactly
|
|
10
|
-
expect(Object.keys(CORE_FALLBACK_FACTORIES)).toEqual(['cache', 'queue', 'job', 'i18n']);
|
|
9
|
+
it('should have exactly 5 entries: metadata, cache, queue, job, i18n', () => {
|
|
10
|
+
expect(Object.keys(CORE_FALLBACK_FACTORIES)).toEqual(['metadata', 'cache', 'queue', 'job', 'i18n']);
|
|
11
11
|
});
|
|
12
12
|
|
|
13
13
|
it('should map to factory functions', () => {
|
package/src/fallbacks/index.ts
CHANGED
|
@@ -4,11 +4,13 @@ import { createMemoryCache } from './memory-cache.js';
|
|
|
4
4
|
import { createMemoryQueue } from './memory-queue.js';
|
|
5
5
|
import { createMemoryJob } from './memory-job.js';
|
|
6
6
|
import { createMemoryI18n } from './memory-i18n.js';
|
|
7
|
+
import { createMemoryMetadata } from './memory-metadata.js';
|
|
7
8
|
|
|
8
9
|
export { createMemoryCache } from './memory-cache.js';
|
|
9
10
|
export { createMemoryQueue } from './memory-queue.js';
|
|
10
11
|
export { createMemoryJob } from './memory-job.js';
|
|
11
12
|
export { createMemoryI18n, resolveLocale } from './memory-i18n.js';
|
|
13
|
+
export { createMemoryMetadata } from './memory-metadata.js';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* Map of core-criticality service names to their in-memory fallback factories.
|
|
@@ -16,6 +18,7 @@ export { createMemoryI18n, resolveLocale } from './memory-i18n.js';
|
|
|
16
18
|
* when no real plugin provides the service.
|
|
17
19
|
*/
|
|
18
20
|
export const CORE_FALLBACK_FACTORIES: Record<string, () => Record<string, any>> = {
|
|
21
|
+
metadata: createMemoryMetadata,
|
|
19
22
|
cache: createMemoryCache,
|
|
20
23
|
queue: createMemoryQueue,
|
|
21
24
|
job: createMemoryJob,
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* In-memory metadata service fallback.
|
|
5
|
+
*
|
|
6
|
+
* Implements the IMetadataService contract with a simple Map-of-Maps store.
|
|
7
|
+
* Used by ObjectKernel as an automatic fallback when no real metadata plugin
|
|
8
|
+
* (e.g. MetadataPlugin with file-system persistence) is registered.
|
|
9
|
+
*/
|
|
10
|
+
export function createMemoryMetadata() {
|
|
11
|
+
// type -> name -> data
|
|
12
|
+
const store = new Map<string, Map<string, any>>();
|
|
13
|
+
|
|
14
|
+
function getTypeMap(type: string): Map<string, any> {
|
|
15
|
+
let map = store.get(type);
|
|
16
|
+
if (!map) {
|
|
17
|
+
map = new Map();
|
|
18
|
+
store.set(type, map);
|
|
19
|
+
}
|
|
20
|
+
return map;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
_fallback: true, _serviceName: 'metadata',
|
|
25
|
+
async register(type: string, name: string, data: any): Promise<void> {
|
|
26
|
+
getTypeMap(type).set(name, data);
|
|
27
|
+
},
|
|
28
|
+
async get(type: string, name: string): Promise<any> {
|
|
29
|
+
return getTypeMap(type).get(name);
|
|
30
|
+
},
|
|
31
|
+
async list(type: string): Promise<any[]> {
|
|
32
|
+
return Array.from(getTypeMap(type).values());
|
|
33
|
+
},
|
|
34
|
+
async unregister(type: string, name: string): Promise<void> {
|
|
35
|
+
getTypeMap(type).delete(name);
|
|
36
|
+
},
|
|
37
|
+
async exists(type: string, name: string): Promise<boolean> {
|
|
38
|
+
return getTypeMap(type).has(name);
|
|
39
|
+
},
|
|
40
|
+
async listNames(type: string): Promise<string[]> {
|
|
41
|
+
return Array.from(getTypeMap(type).keys());
|
|
42
|
+
},
|
|
43
|
+
async getObject(name: string): Promise<any> {
|
|
44
|
+
return getTypeMap('object').get(name);
|
|
45
|
+
},
|
|
46
|
+
async listObjects(): Promise<any[]> {
|
|
47
|
+
return Array.from(getTypeMap('object').values());
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
package/src/kernel.ts
CHANGED
|
@@ -213,6 +213,28 @@ export class ObjectKernel {
|
|
|
213
213
|
return this;
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Pre-inject in-memory fallbacks for 'core' services that were not registered
|
|
218
|
+
* by plugins during Phase 1. Called before Phase 2 so that all core services
|
|
219
|
+
* (e.g. 'metadata', 'cache', 'queue') are resolvable via ctx.getService()
|
|
220
|
+
* when plugin start() methods execute.
|
|
221
|
+
*/
|
|
222
|
+
private preInjectCoreFallbacks() {
|
|
223
|
+
if (this.config.skipSystemValidation) return;
|
|
224
|
+
for (const [serviceName, criticality] of Object.entries(ServiceRequirementDef)) {
|
|
225
|
+
if (criticality !== 'core') continue;
|
|
226
|
+
const hasService = this.services.has(serviceName) || this.pluginLoader.hasService(serviceName);
|
|
227
|
+
if (!hasService) {
|
|
228
|
+
const factory = CORE_FALLBACK_FACTORIES[serviceName];
|
|
229
|
+
if (factory) {
|
|
230
|
+
const fallback = factory();
|
|
231
|
+
this.registerService(serviceName, fallback);
|
|
232
|
+
this.logger.debug(`[Kernel] Pre-injected in-memory fallback for '${serviceName}' before Phase 2`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
216
238
|
/**
|
|
217
239
|
* Validate Critical System Requirements
|
|
218
240
|
*/
|
|
@@ -291,6 +313,12 @@ export class ObjectKernel {
|
|
|
291
313
|
await this.initPluginWithTimeout(plugin);
|
|
292
314
|
}
|
|
293
315
|
|
|
316
|
+
// Pre-inject in-memory fallbacks for 'core' services that were not
|
|
317
|
+
// registered by any plugin during Phase 1. This ensures services like
|
|
318
|
+
// 'metadata', 'cache', 'queue', etc. are always available when plugins
|
|
319
|
+
// call ctx.getService() during their start() methods.
|
|
320
|
+
this.preInjectCoreFallbacks();
|
|
321
|
+
|
|
294
322
|
// Phase 2: Start - Plugins execute business logic
|
|
295
323
|
this.logger.info('Phase 2: Start plugins');
|
|
296
324
|
this.state = 'running';
|