@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
package/dist/index.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
2
8
|
var __export = (target, all) => {
|
|
3
9
|
for (var name in all)
|
|
4
10
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -95,7 +101,13 @@ var ObjectKernelBase = class {
|
|
|
95
101
|
}
|
|
96
102
|
},
|
|
97
103
|
logger: this.logger,
|
|
98
|
-
getKernel: () => this
|
|
104
|
+
getKernel: () => this,
|
|
105
|
+
registerServiceFactory: (_name, _factory, _lifecycle, _dependencies) => {
|
|
106
|
+
throw new Error("[KernelBase] registerServiceFactory not supported \u2014 use ObjectKernel");
|
|
107
|
+
},
|
|
108
|
+
getServiceScoped: async (_name, _scopeId) => {
|
|
109
|
+
throw new Error("[KernelBase] getServiceScoped not supported \u2014 use ObjectKernel");
|
|
110
|
+
}
|
|
99
111
|
};
|
|
100
112
|
}
|
|
101
113
|
/**
|
|
@@ -214,144 +226,58 @@ var ObjectKernelBase = class {
|
|
|
214
226
|
}
|
|
215
227
|
};
|
|
216
228
|
|
|
217
|
-
// src/utils/env.ts
|
|
218
|
-
var isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
|
|
219
|
-
function getEnv(key, defaultValue) {
|
|
220
|
-
if (typeof process !== "undefined" && process.env) {
|
|
221
|
-
return process.env[key] || defaultValue;
|
|
222
|
-
}
|
|
223
|
-
try {
|
|
224
|
-
if (typeof globalThis !== "undefined" && globalThis.process?.env) {
|
|
225
|
-
return globalThis.process.env[key] || defaultValue;
|
|
226
|
-
}
|
|
227
|
-
} catch (e) {
|
|
228
|
-
}
|
|
229
|
-
return defaultValue;
|
|
230
|
-
}
|
|
231
|
-
function safeExit(code = 0) {
|
|
232
|
-
if (isNode) {
|
|
233
|
-
process.exit(code);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
function getMemoryUsage() {
|
|
237
|
-
if (isNode) {
|
|
238
|
-
return process.memoryUsage();
|
|
239
|
-
}
|
|
240
|
-
return { heapUsed: 0, heapTotal: 0 };
|
|
241
|
-
}
|
|
242
|
-
|
|
243
229
|
// src/logger.ts
|
|
230
|
+
var LEVEL_ORDER = {
|
|
231
|
+
debug: 0,
|
|
232
|
+
info: 1,
|
|
233
|
+
warn: 2,
|
|
234
|
+
error: 3,
|
|
235
|
+
fatal: 4,
|
|
236
|
+
silent: 5
|
|
237
|
+
};
|
|
238
|
+
var LEVEL_COLORS = {
|
|
239
|
+
debug: "\x1B[36m",
|
|
240
|
+
info: "\x1B[32m",
|
|
241
|
+
warn: "\x1B[33m",
|
|
242
|
+
error: "\x1B[31m",
|
|
243
|
+
fatal: "\x1B[35m",
|
|
244
|
+
silent: ""
|
|
245
|
+
};
|
|
246
|
+
var RESET = "\x1B[0m";
|
|
244
247
|
var ObjectLogger = class _ObjectLogger {
|
|
245
|
-
|
|
246
|
-
constructor(config = {}) {
|
|
247
|
-
this.isNode = isNode;
|
|
248
|
+
constructor(config = {}, bindings = {}) {
|
|
248
249
|
this.config = {
|
|
249
250
|
name: config.name,
|
|
250
251
|
level: config.level ?? "info",
|
|
251
|
-
format: config.format ??
|
|
252
|
+
format: config.format ?? "pretty",
|
|
252
253
|
redact: config.redact ?? ["password", "token", "secret", "key"],
|
|
253
254
|
sourceLocation: config.sourceLocation ?? false,
|
|
254
255
|
file: config.file,
|
|
255
|
-
rotation: config.rotation ?? {
|
|
256
|
-
maxSize: "10m",
|
|
257
|
-
maxFiles: 5
|
|
258
|
-
}
|
|
256
|
+
rotation: config.rotation ?? { maxSize: "10m", maxFiles: 5 }
|
|
259
257
|
};
|
|
260
|
-
|
|
261
|
-
|
|
258
|
+
this.bindings = bindings;
|
|
259
|
+
if (this.config.file && typeof process !== "undefined") {
|
|
260
|
+
this.openFileStream(this.config.file);
|
|
262
261
|
}
|
|
263
262
|
}
|
|
264
|
-
|
|
265
|
-
* Initialize Pino logger for Node.js
|
|
266
|
-
*/
|
|
267
|
-
async initPinoLogger() {
|
|
268
|
-
if (!this.isNode) return;
|
|
263
|
+
openFileStream(path) {
|
|
269
264
|
try {
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
redact: {
|
|
276
|
-
paths: this.config.redact,
|
|
277
|
-
censor: "***REDACTED***"
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
if (this.config.name) {
|
|
281
|
-
pinoOptions.name = this.config.name;
|
|
282
|
-
}
|
|
283
|
-
const targets = [];
|
|
284
|
-
if (this.config.format === "pretty") {
|
|
285
|
-
let hasPretty = false;
|
|
286
|
-
try {
|
|
287
|
-
this.require.resolve("pino-pretty");
|
|
288
|
-
hasPretty = true;
|
|
289
|
-
} catch (e) {
|
|
290
|
-
}
|
|
291
|
-
if (hasPretty) {
|
|
292
|
-
targets.push({
|
|
293
|
-
target: "pino-pretty",
|
|
294
|
-
options: {
|
|
295
|
-
colorize: true,
|
|
296
|
-
translateTime: "SYS:standard",
|
|
297
|
-
ignore: "pid,hostname"
|
|
298
|
-
},
|
|
299
|
-
level: this.config.level
|
|
300
|
-
});
|
|
301
|
-
} else {
|
|
302
|
-
console.warn("[Logger] pino-pretty not found. Install it for pretty logging: pnpm add -D pino-pretty");
|
|
303
|
-
targets.push({
|
|
304
|
-
target: "pino/file",
|
|
305
|
-
options: { destination: 1 },
|
|
306
|
-
level: this.config.level
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
} else if (this.config.format === "json") {
|
|
310
|
-
targets.push({
|
|
311
|
-
target: "pino/file",
|
|
312
|
-
options: { destination: 1 },
|
|
313
|
-
// stdout
|
|
314
|
-
level: this.config.level
|
|
315
|
-
});
|
|
316
|
-
} else {
|
|
317
|
-
targets.push({
|
|
318
|
-
target: "pino/file",
|
|
319
|
-
options: { destination: 1 },
|
|
320
|
-
level: this.config.level
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
if (this.config.file) {
|
|
324
|
-
targets.push({
|
|
325
|
-
target: "pino/file",
|
|
326
|
-
options: {
|
|
327
|
-
destination: this.config.file,
|
|
328
|
-
mkdir: true
|
|
329
|
-
},
|
|
330
|
-
level: this.config.level
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
if (targets.length > 0) {
|
|
334
|
-
pinoOptions.transport = targets.length === 1 ? targets[0] : { targets };
|
|
335
|
-
}
|
|
336
|
-
this.pinoInstance = pino(pinoOptions);
|
|
337
|
-
this.pinoLogger = this.pinoInstance;
|
|
338
|
-
} catch (error) {
|
|
339
|
-
console.warn("[Logger] Pino not available, falling back to console:", error);
|
|
340
|
-
this.pinoLogger = null;
|
|
265
|
+
const fs = __require("fs");
|
|
266
|
+
const dir = __require("path").dirname(path);
|
|
267
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
268
|
+
this.fileStream = fs.createWriteStream(path, { flags: "a" });
|
|
269
|
+
} catch {
|
|
341
270
|
}
|
|
342
271
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
272
|
+
isEnabled(level) {
|
|
273
|
+
return LEVEL_ORDER[level] >= LEVEL_ORDER[this.config.level];
|
|
274
|
+
}
|
|
346
275
|
redactSensitive(obj) {
|
|
347
276
|
if (!obj || typeof obj !== "object") return obj;
|
|
348
277
|
const redacted = Array.isArray(obj) ? [...obj] : { ...obj };
|
|
349
278
|
for (const key in redacted) {
|
|
350
|
-
const
|
|
351
|
-
|
|
352
|
-
(pattern) => lowerKey.includes(pattern.toLowerCase())
|
|
353
|
-
);
|
|
354
|
-
if (shouldRedact) {
|
|
279
|
+
const lower = key.toLowerCase();
|
|
280
|
+
if (this.config.redact.some((p) => lower.includes(p.toLowerCase()))) {
|
|
355
281
|
redacted[key] = "***REDACTED***";
|
|
356
282
|
} else if (typeof redacted[key] === "object" && redacted[key] !== null) {
|
|
357
283
|
redacted[key] = this.redactSensitive(redacted[key]);
|
|
@@ -359,146 +285,89 @@ var ObjectLogger = class _ObjectLogger {
|
|
|
359
285
|
}
|
|
360
286
|
return redacted;
|
|
361
287
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
288
|
+
write(level, message, meta, error) {
|
|
289
|
+
if (!this.isEnabled(level)) return;
|
|
290
|
+
const context = this.redactSensitive({
|
|
291
|
+
...this.bindings,
|
|
292
|
+
...meta,
|
|
293
|
+
...error ? { error: { message: error.message, stack: error.stack } } : {}
|
|
294
|
+
});
|
|
295
|
+
const hasContext = Object.keys(context).length > 0;
|
|
296
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
297
|
+
let line;
|
|
366
298
|
if (this.config.format === "json") {
|
|
367
|
-
|
|
368
|
-
|
|
299
|
+
line = JSON.stringify({
|
|
300
|
+
time: ts,
|
|
369
301
|
level,
|
|
370
|
-
|
|
302
|
+
...this.config.name ? { name: this.config.name } : {},
|
|
303
|
+
msg: message,
|
|
371
304
|
...context
|
|
372
305
|
});
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
306
|
+
} else if (this.config.format === "text") {
|
|
307
|
+
const parts = [ts, level.toUpperCase(), message];
|
|
308
|
+
if (hasContext) parts.push(JSON.stringify(context));
|
|
309
|
+
line = parts.join(" | ");
|
|
310
|
+
} else {
|
|
311
|
+
const color = LEVEL_COLORS[level] || "";
|
|
312
|
+
const label = this.config.name ? `[${this.config.name}] ` : "";
|
|
313
|
+
line = `${color}${ts} ${level.toUpperCase()}${RESET} ${label}${message}`;
|
|
314
|
+
if (hasContext) line += ` ${JSON.stringify(context)}`;
|
|
315
|
+
}
|
|
316
|
+
const out = line + "\n";
|
|
317
|
+
if (typeof process !== "undefined" && process.stderr) {
|
|
318
|
+
if (level === "error" || level === "fatal") {
|
|
319
|
+
process.stderr.write(out);
|
|
320
|
+
} else {
|
|
321
|
+
process.stdout?.write(out);
|
|
378
322
|
}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
// Green
|
|
386
|
-
warn: "\x1B[33m",
|
|
387
|
-
// Yellow
|
|
388
|
-
error: "\x1B[31m",
|
|
389
|
-
// Red
|
|
390
|
-
fatal: "\x1B[35m",
|
|
391
|
-
// Magenta
|
|
392
|
-
silent: ""
|
|
393
|
-
};
|
|
394
|
-
const reset = "\x1B[0m";
|
|
395
|
-
const color = levelColors[level] || "";
|
|
396
|
-
let output = `${color}[${level.toUpperCase()}]${reset} ${message}`;
|
|
397
|
-
if (context && Object.keys(context).length > 0) {
|
|
398
|
-
output += ` ${JSON.stringify(context, null, 2)}`;
|
|
323
|
+
} else if (typeof console !== "undefined") {
|
|
324
|
+
const fn = level === "error" || level === "fatal" ? console.error : level === "warn" ? console.warn : level === "debug" ? console.debug : console.log;
|
|
325
|
+
fn(line);
|
|
326
|
+
}
|
|
327
|
+
if (this.fileStream) {
|
|
328
|
+
this.fileStream.write(out);
|
|
399
329
|
}
|
|
400
|
-
return output;
|
|
401
|
-
}
|
|
402
|
-
/**
|
|
403
|
-
* Log using browser console
|
|
404
|
-
*/
|
|
405
|
-
logBrowser(level, message, context, error) {
|
|
406
|
-
const redactedContext = context ? this.redactSensitive(context) : void 0;
|
|
407
|
-
const mergedContext = error ? { ...redactedContext, error: { message: error.message, stack: error.stack } } : redactedContext;
|
|
408
|
-
const formatted = this.formatBrowserLog(level, message, mergedContext);
|
|
409
|
-
const consoleMethod = level === "debug" ? "debug" : level === "info" ? "log" : level === "warn" ? "warn" : level === "error" || level === "fatal" ? "error" : "log";
|
|
410
|
-
console[consoleMethod](formatted);
|
|
411
330
|
}
|
|
412
|
-
/**
|
|
413
|
-
* Public logging methods
|
|
414
|
-
*/
|
|
415
331
|
debug(message, meta) {
|
|
416
|
-
|
|
417
|
-
this.pinoLogger.debug(meta || {}, message);
|
|
418
|
-
} else {
|
|
419
|
-
this.logBrowser("debug", message, meta);
|
|
420
|
-
}
|
|
332
|
+
this.write("debug", message, meta);
|
|
421
333
|
}
|
|
422
334
|
info(message, meta) {
|
|
423
|
-
|
|
424
|
-
this.pinoLogger.info(meta || {}, message);
|
|
425
|
-
} else {
|
|
426
|
-
this.logBrowser("info", message, meta);
|
|
427
|
-
}
|
|
335
|
+
this.write("info", message, meta);
|
|
428
336
|
}
|
|
429
337
|
warn(message, meta) {
|
|
430
|
-
|
|
431
|
-
this.pinoLogger.warn(meta || {}, message);
|
|
432
|
-
} else {
|
|
433
|
-
this.logBrowser("warn", message, meta);
|
|
434
|
-
}
|
|
338
|
+
this.write("warn", message, meta);
|
|
435
339
|
}
|
|
436
340
|
error(message, errorOrMeta, meta) {
|
|
437
|
-
let error;
|
|
438
|
-
let context = {};
|
|
439
341
|
if (errorOrMeta instanceof Error) {
|
|
440
|
-
error
|
|
441
|
-
context = meta || {};
|
|
442
|
-
} else {
|
|
443
|
-
context = errorOrMeta || {};
|
|
444
|
-
}
|
|
445
|
-
if (this.isNode && this.pinoLogger) {
|
|
446
|
-
const errorContext = error ? { err: error, ...context } : context;
|
|
447
|
-
this.pinoLogger.error(errorContext, message);
|
|
342
|
+
this.write("error", message, meta, errorOrMeta);
|
|
448
343
|
} else {
|
|
449
|
-
this.
|
|
344
|
+
this.write("error", message, errorOrMeta);
|
|
450
345
|
}
|
|
451
346
|
}
|
|
452
347
|
fatal(message, errorOrMeta, meta) {
|
|
453
|
-
let error;
|
|
454
|
-
let context = {};
|
|
455
348
|
if (errorOrMeta instanceof Error) {
|
|
456
|
-
|
|
457
|
-
context = meta || {};
|
|
458
|
-
} else {
|
|
459
|
-
context = errorOrMeta || {};
|
|
460
|
-
}
|
|
461
|
-
if (this.isNode && this.pinoLogger) {
|
|
462
|
-
const errorContext = error ? { err: error, ...context } : context;
|
|
463
|
-
this.pinoLogger.fatal(errorContext, message);
|
|
349
|
+
this.write("fatal", message, meta, errorOrMeta);
|
|
464
350
|
} else {
|
|
465
|
-
this.
|
|
351
|
+
this.write("fatal", message, errorOrMeta);
|
|
466
352
|
}
|
|
467
353
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
*/
|
|
354
|
+
log(message, ...args) {
|
|
355
|
+
this.info(message, args.length > 0 ? { args } : void 0);
|
|
356
|
+
}
|
|
472
357
|
child(context) {
|
|
473
|
-
const
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
childLogger.pinoInstance = this.pinoInstance;
|
|
477
|
-
}
|
|
478
|
-
return childLogger;
|
|
358
|
+
const child = new _ObjectLogger(this.config, { ...this.bindings, ...context });
|
|
359
|
+
child.fileStream = this.fileStream;
|
|
360
|
+
return child;
|
|
479
361
|
}
|
|
480
|
-
/**
|
|
481
|
-
* Set trace context for distributed tracing
|
|
482
|
-
*/
|
|
483
362
|
withTrace(traceId, spanId) {
|
|
484
363
|
return this.child({ traceId, spanId });
|
|
485
364
|
}
|
|
486
|
-
/**
|
|
487
|
-
* Cleanup resources
|
|
488
|
-
*/
|
|
489
365
|
async destroy() {
|
|
490
|
-
if (this.
|
|
491
|
-
await new Promise((resolve) =>
|
|
492
|
-
|
|
493
|
-
});
|
|
366
|
+
if (this.fileStream) {
|
|
367
|
+
await new Promise((resolve) => this.fileStream.end(resolve));
|
|
368
|
+
this.fileStream = void 0;
|
|
494
369
|
}
|
|
495
370
|
}
|
|
496
|
-
/**
|
|
497
|
-
* Compatibility method for console.log usage
|
|
498
|
-
*/
|
|
499
|
-
log(message, ...args) {
|
|
500
|
-
this.info(message, args.length > 0 ? { args } : void 0);
|
|
501
|
-
}
|
|
502
371
|
};
|
|
503
372
|
function createLogger(config) {
|
|
504
373
|
return new ObjectLogger(config);
|
|
@@ -919,13 +788,13 @@ var PluginLoader = class {
|
|
|
919
788
|
const scope = this.scopedServices.get(scopeId);
|
|
920
789
|
let instance = scope.get(registration.name);
|
|
921
790
|
if (!instance) {
|
|
922
|
-
instance = await this.createServiceInstance(registration);
|
|
791
|
+
instance = await this.createServiceInstance(registration, scopeId);
|
|
923
792
|
scope.set(registration.name, instance);
|
|
924
793
|
this.logger.debug(`Scoped service created: ${registration.name} (scope: ${scopeId})`);
|
|
925
794
|
}
|
|
926
795
|
return instance;
|
|
927
796
|
}
|
|
928
|
-
async createServiceInstance(registration) {
|
|
797
|
+
async createServiceInstance(registration, scopeId) {
|
|
929
798
|
if (!this.context) {
|
|
930
799
|
throw new Error(`[PluginLoader] Context not set - cannot create service '${registration.name}'`);
|
|
931
800
|
}
|
|
@@ -934,13 +803,39 @@ var PluginLoader = class {
|
|
|
934
803
|
}
|
|
935
804
|
this.creating.add(registration.name);
|
|
936
805
|
try {
|
|
937
|
-
return await registration.factory(this.context);
|
|
806
|
+
return await registration.factory(this.context, scopeId);
|
|
938
807
|
} finally {
|
|
939
808
|
this.creating.delete(registration.name);
|
|
940
809
|
}
|
|
941
810
|
}
|
|
942
811
|
};
|
|
943
812
|
|
|
813
|
+
// src/utils/env.ts
|
|
814
|
+
var isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
|
|
815
|
+
function getEnv(key, defaultValue) {
|
|
816
|
+
if (typeof process !== "undefined" && process.env) {
|
|
817
|
+
return process.env[key] || defaultValue;
|
|
818
|
+
}
|
|
819
|
+
try {
|
|
820
|
+
if (typeof globalThis !== "undefined" && globalThis.process?.env) {
|
|
821
|
+
return globalThis.process.env[key] || defaultValue;
|
|
822
|
+
}
|
|
823
|
+
} catch (e) {
|
|
824
|
+
}
|
|
825
|
+
return defaultValue;
|
|
826
|
+
}
|
|
827
|
+
function safeExit(code = 0) {
|
|
828
|
+
if (isNode) {
|
|
829
|
+
process.exit(code);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
function getMemoryUsage() {
|
|
833
|
+
if (isNode) {
|
|
834
|
+
return process.memoryUsage();
|
|
835
|
+
}
|
|
836
|
+
return { heapUsed: 0, heapTotal: 0 };
|
|
837
|
+
}
|
|
838
|
+
|
|
944
839
|
// src/fallbacks/memory-cache.ts
|
|
945
840
|
function createMemoryCache() {
|
|
946
841
|
const store = /* @__PURE__ */ new Map();
|
|
@@ -1031,6 +926,22 @@ function createMemoryJob() {
|
|
|
1031
926
|
}
|
|
1032
927
|
|
|
1033
928
|
// src/fallbacks/memory-i18n.ts
|
|
929
|
+
function deepMerge(target, source) {
|
|
930
|
+
const result = { ...target };
|
|
931
|
+
for (const key of Object.keys(source)) {
|
|
932
|
+
const tVal = target[key];
|
|
933
|
+
const sVal = source[key];
|
|
934
|
+
if (tVal && sVal && typeof tVal === "object" && !Array.isArray(tVal) && typeof sVal === "object" && !Array.isArray(sVal)) {
|
|
935
|
+
result[key] = deepMerge(
|
|
936
|
+
tVal,
|
|
937
|
+
sVal
|
|
938
|
+
);
|
|
939
|
+
} else {
|
|
940
|
+
result[key] = sVal;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
return result;
|
|
944
|
+
}
|
|
1034
945
|
function resolveLocale(requestedLocale, availableLocales) {
|
|
1035
946
|
if (availableLocales.length === 0) return void 0;
|
|
1036
947
|
if (availableLocales.includes(requestedLocale)) return requestedLocale;
|
|
@@ -1076,8 +987,12 @@ function createMemoryI18n() {
|
|
|
1076
987
|
return resolveTranslations(locale) ?? {};
|
|
1077
988
|
},
|
|
1078
989
|
loadTranslations(locale, data) {
|
|
1079
|
-
const existing = translations.get(locale)
|
|
1080
|
-
|
|
990
|
+
const existing = translations.get(locale);
|
|
991
|
+
if (existing) {
|
|
992
|
+
translations.set(locale, deepMerge(existing, data));
|
|
993
|
+
} else {
|
|
994
|
+
translations.set(locale, { ...data });
|
|
995
|
+
}
|
|
1081
996
|
},
|
|
1082
997
|
getLocales() {
|
|
1083
998
|
return [...translations.keys()];
|
|
@@ -1166,6 +1081,9 @@ var ObjectKernel = class {
|
|
|
1166
1081
|
registerService: (name, service) => {
|
|
1167
1082
|
this.registerService(name, service);
|
|
1168
1083
|
},
|
|
1084
|
+
registerServiceFactory: (name, factory, lifecycle, dependencies) => {
|
|
1085
|
+
this.registerServiceFactory(name, factory, lifecycle, dependencies);
|
|
1086
|
+
},
|
|
1169
1087
|
getService: (name) => {
|
|
1170
1088
|
const service = this.services.get(name);
|
|
1171
1089
|
if (service) {
|
|
@@ -1219,6 +1137,9 @@ var ObjectKernel = class {
|
|
|
1219
1137
|
getServices: () => {
|
|
1220
1138
|
return new Map(this.services);
|
|
1221
1139
|
},
|
|
1140
|
+
getServiceScoped: (name, scopeId) => {
|
|
1141
|
+
return this.pluginLoader.getService(name, scopeId);
|
|
1142
|
+
},
|
|
1222
1143
|
logger: this.logger,
|
|
1223
1144
|
getKernel: () => this
|
|
1224
1145
|
// Type compatibility
|
|
@@ -1360,6 +1281,7 @@ var ObjectKernel = class {
|
|
|
1360
1281
|
const result = await this.startPluginWithTimeout(plugin);
|
|
1361
1282
|
if (!result.success) {
|
|
1362
1283
|
this.logger.error(`Plugin startup failed: ${plugin.name}`, result.error);
|
|
1284
|
+
console.error(`[Kernel] Plugin startup failed: ${plugin.name}`, result.error instanceof Error ? result.error.message : result.error, result.error instanceof Error ? result.error.stack : "");
|
|
1363
1285
|
if (this.config.rollbackOnFailure) {
|
|
1364
1286
|
this.logger.warn("Rolling back started plugins...");
|
|
1365
1287
|
await this.rollbackStartedPlugins();
|
|
@@ -1392,17 +1314,19 @@ var ObjectKernel = class {
|
|
|
1392
1314
|
try {
|
|
1393
1315
|
const shutdownPromise = this.performShutdown();
|
|
1394
1316
|
const timeoutPromise = new Promise((_, reject) => {
|
|
1395
|
-
setTimeout(() => {
|
|
1317
|
+
const t = setTimeout(() => {
|
|
1396
1318
|
reject(new Error("Shutdown timeout exceeded"));
|
|
1397
1319
|
}, this.config.shutdownTimeout);
|
|
1320
|
+
if (t.unref) t.unref();
|
|
1398
1321
|
});
|
|
1399
1322
|
await Promise.race([shutdownPromise, timeoutPromise]);
|
|
1400
1323
|
this.state = "stopped";
|
|
1401
1324
|
this.logger.info("\u2705 Graceful shutdown complete");
|
|
1402
1325
|
} catch (error) {
|
|
1403
|
-
this.logger.error("Shutdown
|
|
1326
|
+
this.logger.error("Shutdown timed out \u2014 forcing exit", error);
|
|
1404
1327
|
this.state = "stopped";
|
|
1405
|
-
|
|
1328
|
+
await this.logger.destroy();
|
|
1329
|
+
process.exit(1);
|
|
1406
1330
|
} finally {
|
|
1407
1331
|
await this.logger.destroy();
|
|
1408
1332
|
}
|
|
@@ -1442,6 +1366,13 @@ var ObjectKernel = class {
|
|
|
1442
1366
|
async getServiceAsync(name, scopeId) {
|
|
1443
1367
|
return await this.pluginLoader.getService(name, scopeId);
|
|
1444
1368
|
}
|
|
1369
|
+
/**
|
|
1370
|
+
* Clear all scoped service instances for a given scope (e.g., projectId).
|
|
1371
|
+
* Releases driver connections and metadata caches for idle projects.
|
|
1372
|
+
*/
|
|
1373
|
+
clearScope(scopeId) {
|
|
1374
|
+
this.pluginLoader.clearScope(scopeId);
|
|
1375
|
+
}
|
|
1445
1376
|
/**
|
|
1446
1377
|
* Check if kernel is running
|
|
1447
1378
|
*/
|
|
@@ -3021,6 +2952,12 @@ var SecurePluginContext = class {
|
|
|
3021
2952
|
getKernel() {
|
|
3022
2953
|
return this.baseContext.getKernel();
|
|
3023
2954
|
}
|
|
2955
|
+
registerServiceFactory(name, factory, lifecycle, dependencies) {
|
|
2956
|
+
this.baseContext.registerServiceFactory(name, factory, lifecycle, dependencies);
|
|
2957
|
+
}
|
|
2958
|
+
getServiceScoped(name, scopeId) {
|
|
2959
|
+
return this.baseContext.getServiceScoped(name, scopeId);
|
|
2960
|
+
}
|
|
3024
2961
|
};
|
|
3025
2962
|
function createPluginPermissionEnforcer(logger) {
|
|
3026
2963
|
return new PluginPermissionEnforcer(logger);
|
|
@@ -4690,272 +4627,6 @@ var NamespaceResolver = class {
|
|
|
4690
4627
|
return `${shortName}_${ns}`;
|
|
4691
4628
|
}
|
|
4692
4629
|
};
|
|
4693
|
-
|
|
4694
|
-
// src/package-manager.ts
|
|
4695
|
-
var PackageManager = class {
|
|
4696
|
-
constructor(logger, options = {}) {
|
|
4697
|
-
this.packages = /* @__PURE__ */ new Map();
|
|
4698
|
-
this.snapshots = /* @__PURE__ */ new Map();
|
|
4699
|
-
this.logger = logger.child({ component: "PackageManager" });
|
|
4700
|
-
this.dependencyResolver = new DependencyResolver(logger);
|
|
4701
|
-
this.namespaceResolver = new NamespaceResolver(logger);
|
|
4702
|
-
this.platformVersion = options.platformVersion || "3.0.0";
|
|
4703
|
-
}
|
|
4704
|
-
/**
|
|
4705
|
-
* Install a package with full dependency resolution and namespace checking.
|
|
4706
|
-
*/
|
|
4707
|
-
async install(packageId, version, manifest) {
|
|
4708
|
-
this.logger.info("Installing package", { packageId, version });
|
|
4709
|
-
if (this.packages.has(packageId)) {
|
|
4710
|
-
const existing = this.packages.get(packageId);
|
|
4711
|
-
if (existing.status === "installed") {
|
|
4712
|
-
return {
|
|
4713
|
-
success: false,
|
|
4714
|
-
packageId,
|
|
4715
|
-
version,
|
|
4716
|
-
installedDependencies: [],
|
|
4717
|
-
namespaceConflicts: [],
|
|
4718
|
-
errorMessage: `Package ${packageId}@${existing.version} is already installed. Use upgrade instead.`
|
|
4719
|
-
};
|
|
4720
|
-
}
|
|
4721
|
-
}
|
|
4722
|
-
const engine = manifest.engine?.objectstack;
|
|
4723
|
-
if (engine) {
|
|
4724
|
-
const platformSemver = SemanticVersionManager.parse(this.platformVersion);
|
|
4725
|
-
if (!SemanticVersionManager.satisfies(platformSemver, engine)) {
|
|
4726
|
-
return {
|
|
4727
|
-
success: false,
|
|
4728
|
-
packageId,
|
|
4729
|
-
version,
|
|
4730
|
-
installedDependencies: [],
|
|
4731
|
-
namespaceConflicts: [],
|
|
4732
|
-
errorMessage: `Package requires platform ${engine}, but current platform is v${this.platformVersion}`
|
|
4733
|
-
};
|
|
4734
|
-
}
|
|
4735
|
-
}
|
|
4736
|
-
const namespaces = this.namespaceResolver.extractNamespaces(manifest);
|
|
4737
|
-
const nsCheck = this.namespaceResolver.checkAvailability(packageId, namespaces);
|
|
4738
|
-
if (!nsCheck.available) {
|
|
4739
|
-
return {
|
|
4740
|
-
success: false,
|
|
4741
|
-
packageId,
|
|
4742
|
-
version,
|
|
4743
|
-
installedDependencies: [],
|
|
4744
|
-
namespaceConflicts: nsCheck.conflicts.map((c) => ({
|
|
4745
|
-
namespace: c.namespace,
|
|
4746
|
-
existingPackageId: c.existingPackageId
|
|
4747
|
-
})),
|
|
4748
|
-
errorMessage: `Namespace conflicts detected: ${nsCheck.conflicts.map((c) => c.namespace).join(", ")}`
|
|
4749
|
-
};
|
|
4750
|
-
}
|
|
4751
|
-
const deps = manifest.dependencies;
|
|
4752
|
-
const depNames = deps ? Object.keys(deps) : [];
|
|
4753
|
-
const missingDeps = depNames.filter((d) => !this.packages.has(d));
|
|
4754
|
-
if (missingDeps.length > 0) {
|
|
4755
|
-
return {
|
|
4756
|
-
success: false,
|
|
4757
|
-
packageId,
|
|
4758
|
-
version,
|
|
4759
|
-
installedDependencies: [],
|
|
4760
|
-
namespaceConflicts: [],
|
|
4761
|
-
errorMessage: `Missing dependencies: ${missingDeps.join(", ")}`
|
|
4762
|
-
};
|
|
4763
|
-
}
|
|
4764
|
-
this.packages.set(packageId, {
|
|
4765
|
-
packageId,
|
|
4766
|
-
version,
|
|
4767
|
-
manifest,
|
|
4768
|
-
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4769
|
-
status: "installed",
|
|
4770
|
-
namespaces,
|
|
4771
|
-
dependencies: depNames
|
|
4772
|
-
});
|
|
4773
|
-
this.namespaceResolver.register(packageId, namespaces);
|
|
4774
|
-
this.logger.info("Package installed", { packageId, version, namespaces: namespaces.length });
|
|
4775
|
-
return {
|
|
4776
|
-
success: true,
|
|
4777
|
-
packageId,
|
|
4778
|
-
version,
|
|
4779
|
-
installedDependencies: depNames,
|
|
4780
|
-
namespaceConflicts: []
|
|
4781
|
-
};
|
|
4782
|
-
}
|
|
4783
|
-
/**
|
|
4784
|
-
* Uninstall a package, checking for dependents first.
|
|
4785
|
-
*/
|
|
4786
|
-
async uninstall(packageId) {
|
|
4787
|
-
const pkg = this.packages.get(packageId);
|
|
4788
|
-
if (!pkg) {
|
|
4789
|
-
return { success: false, errorMessage: `Package ${packageId} is not installed` };
|
|
4790
|
-
}
|
|
4791
|
-
const dependents = [];
|
|
4792
|
-
for (const [id, record] of this.packages) {
|
|
4793
|
-
if (id !== packageId && record.dependencies.includes(packageId)) {
|
|
4794
|
-
dependents.push(id);
|
|
4795
|
-
}
|
|
4796
|
-
}
|
|
4797
|
-
if (dependents.length > 0) {
|
|
4798
|
-
return {
|
|
4799
|
-
success: false,
|
|
4800
|
-
errorMessage: `Cannot uninstall ${packageId}: depended upon by ${dependents.join(", ")}`
|
|
4801
|
-
};
|
|
4802
|
-
}
|
|
4803
|
-
this.namespaceResolver.unregister(packageId);
|
|
4804
|
-
this.packages.delete(packageId);
|
|
4805
|
-
this.snapshots.delete(packageId);
|
|
4806
|
-
this.logger.info("Package uninstalled", { packageId });
|
|
4807
|
-
return { success: true };
|
|
4808
|
-
}
|
|
4809
|
-
/**
|
|
4810
|
-
* Upgrade a package: snapshot → update → register.
|
|
4811
|
-
*/
|
|
4812
|
-
async upgrade(packageId, newVersion, newManifest) {
|
|
4813
|
-
const existing = this.packages.get(packageId);
|
|
4814
|
-
if (!existing) {
|
|
4815
|
-
return {
|
|
4816
|
-
success: false,
|
|
4817
|
-
packageId,
|
|
4818
|
-
fromVersion: "",
|
|
4819
|
-
toVersion: newVersion,
|
|
4820
|
-
snapshot: { packageId, previousVersion: "", previousManifest: {}, previousNamespaces: [], installedAt: "", createdAt: (/* @__PURE__ */ new Date()).toISOString() },
|
|
4821
|
-
errorMessage: `Package ${packageId} is not installed`
|
|
4822
|
-
};
|
|
4823
|
-
}
|
|
4824
|
-
const snapshot = {
|
|
4825
|
-
packageId,
|
|
4826
|
-
previousVersion: existing.version,
|
|
4827
|
-
previousManifest: existing.manifest,
|
|
4828
|
-
previousNamespaces: [...existing.namespaces],
|
|
4829
|
-
installedAt: existing.installedAt,
|
|
4830
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4831
|
-
};
|
|
4832
|
-
this.snapshots.set(packageId, snapshot);
|
|
4833
|
-
const engine = newManifest.engine?.objectstack;
|
|
4834
|
-
if (engine) {
|
|
4835
|
-
const platformSemver = SemanticVersionManager.parse(this.platformVersion);
|
|
4836
|
-
if (!SemanticVersionManager.satisfies(platformSemver, engine)) {
|
|
4837
|
-
return {
|
|
4838
|
-
success: false,
|
|
4839
|
-
packageId,
|
|
4840
|
-
fromVersion: existing.version,
|
|
4841
|
-
toVersion: newVersion,
|
|
4842
|
-
snapshot,
|
|
4843
|
-
errorMessage: `New version requires platform ${engine}, current is v${this.platformVersion}`
|
|
4844
|
-
};
|
|
4845
|
-
}
|
|
4846
|
-
}
|
|
4847
|
-
const newNamespaces = this.namespaceResolver.extractNamespaces(newManifest);
|
|
4848
|
-
this.namespaceResolver.unregister(packageId);
|
|
4849
|
-
const nsCheck = this.namespaceResolver.checkAvailability(packageId, newNamespaces);
|
|
4850
|
-
if (!nsCheck.available) {
|
|
4851
|
-
this.namespaceResolver.register(packageId, existing.namespaces);
|
|
4852
|
-
return {
|
|
4853
|
-
success: false,
|
|
4854
|
-
packageId,
|
|
4855
|
-
fromVersion: existing.version,
|
|
4856
|
-
toVersion: newVersion,
|
|
4857
|
-
snapshot,
|
|
4858
|
-
errorMessage: `Namespace conflicts in new version: ${nsCheck.conflicts.map((c) => c.namespace).join(", ")}`
|
|
4859
|
-
};
|
|
4860
|
-
}
|
|
4861
|
-
this.namespaceResolver.register(packageId, newNamespaces);
|
|
4862
|
-
const deps = newManifest.dependencies;
|
|
4863
|
-
this.packages.set(packageId, {
|
|
4864
|
-
packageId,
|
|
4865
|
-
version: newVersion,
|
|
4866
|
-
manifest: newManifest,
|
|
4867
|
-
installedAt: existing.installedAt,
|
|
4868
|
-
status: "installed",
|
|
4869
|
-
namespaces: newNamespaces,
|
|
4870
|
-
dependencies: deps ? Object.keys(deps) : []
|
|
4871
|
-
});
|
|
4872
|
-
this.logger.info("Package upgraded", { packageId, from: existing.version, to: newVersion });
|
|
4873
|
-
return {
|
|
4874
|
-
success: true,
|
|
4875
|
-
packageId,
|
|
4876
|
-
fromVersion: existing.version,
|
|
4877
|
-
toVersion: newVersion,
|
|
4878
|
-
snapshot
|
|
4879
|
-
};
|
|
4880
|
-
}
|
|
4881
|
-
/**
|
|
4882
|
-
* Rollback a package to its pre-upgrade snapshot.
|
|
4883
|
-
*/
|
|
4884
|
-
async rollback(packageId) {
|
|
4885
|
-
const snapshot = this.snapshots.get(packageId);
|
|
4886
|
-
if (!snapshot) {
|
|
4887
|
-
return {
|
|
4888
|
-
success: false,
|
|
4889
|
-
packageId,
|
|
4890
|
-
restoredVersion: "",
|
|
4891
|
-
errorMessage: `No upgrade snapshot found for ${packageId}`
|
|
4892
|
-
};
|
|
4893
|
-
}
|
|
4894
|
-
this.namespaceResolver.unregister(packageId);
|
|
4895
|
-
this.namespaceResolver.register(packageId, snapshot.previousNamespaces);
|
|
4896
|
-
const deps = snapshot.previousManifest.dependencies;
|
|
4897
|
-
this.packages.set(packageId, {
|
|
4898
|
-
packageId,
|
|
4899
|
-
version: snapshot.previousVersion,
|
|
4900
|
-
manifest: snapshot.previousManifest,
|
|
4901
|
-
installedAt: snapshot.installedAt,
|
|
4902
|
-
status: "installed",
|
|
4903
|
-
namespaces: snapshot.previousNamespaces,
|
|
4904
|
-
dependencies: deps ? Object.keys(deps) : []
|
|
4905
|
-
});
|
|
4906
|
-
this.snapshots.delete(packageId);
|
|
4907
|
-
this.logger.info("Package rolled back", { packageId, to: snapshot.previousVersion });
|
|
4908
|
-
return {
|
|
4909
|
-
success: true,
|
|
4910
|
-
packageId,
|
|
4911
|
-
restoredVersion: snapshot.previousVersion
|
|
4912
|
-
};
|
|
4913
|
-
}
|
|
4914
|
-
/**
|
|
4915
|
-
* Get an installed package record.
|
|
4916
|
-
*/
|
|
4917
|
-
getPackage(packageId) {
|
|
4918
|
-
return this.packages.get(packageId);
|
|
4919
|
-
}
|
|
4920
|
-
/**
|
|
4921
|
-
* List all installed packages.
|
|
4922
|
-
*/
|
|
4923
|
-
listPackages() {
|
|
4924
|
-
return Array.from(this.packages.values());
|
|
4925
|
-
}
|
|
4926
|
-
/**
|
|
4927
|
-
* Resolve dependencies for a set of packages.
|
|
4928
|
-
*/
|
|
4929
|
-
resolveDependencies(packages) {
|
|
4930
|
-
return this.dependencyResolver.resolve(packages);
|
|
4931
|
-
}
|
|
4932
|
-
/**
|
|
4933
|
-
* Check namespace availability for a package's metadata.
|
|
4934
|
-
*/
|
|
4935
|
-
checkNamespaces(packageId, config) {
|
|
4936
|
-
const namespaces = this.namespaceResolver.extractNamespaces(config);
|
|
4937
|
-
const result = this.namespaceResolver.checkAvailability(packageId, namespaces);
|
|
4938
|
-
return {
|
|
4939
|
-
available: result.available,
|
|
4940
|
-
conflicts: result.conflicts.map((c) => ({
|
|
4941
|
-
namespace: c.namespace,
|
|
4942
|
-
existingPackageId: c.existingPackageId
|
|
4943
|
-
}))
|
|
4944
|
-
};
|
|
4945
|
-
}
|
|
4946
|
-
/**
|
|
4947
|
-
* Get the namespace resolver instance.
|
|
4948
|
-
*/
|
|
4949
|
-
getNamespaceResolver() {
|
|
4950
|
-
return this.namespaceResolver;
|
|
4951
|
-
}
|
|
4952
|
-
/**
|
|
4953
|
-
* Get a snapshot for a given package (if available).
|
|
4954
|
-
*/
|
|
4955
|
-
getSnapshot(packageId) {
|
|
4956
|
-
return this.snapshots.get(packageId);
|
|
4957
|
-
}
|
|
4958
|
-
};
|
|
4959
4630
|
export {
|
|
4960
4631
|
ApiRegistry,
|
|
4961
4632
|
CORE_FALLBACK_FACTORIES,
|
|
@@ -4966,7 +4637,6 @@ export {
|
|
|
4966
4637
|
ObjectKernel,
|
|
4967
4638
|
ObjectKernelBase,
|
|
4968
4639
|
ObjectLogger,
|
|
4969
|
-
PackageManager,
|
|
4970
4640
|
PluginConfigValidator,
|
|
4971
4641
|
PluginHealthMonitor,
|
|
4972
4642
|
PluginLoader,
|