@zintrust/core 0.4.76 → 0.4.77
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/bin/zintrust-main.d.ts +12 -0
- package/bin/zintrust-main.d.ts.map +1 -1
- package/bin/zintrust-main.js +149 -54
- package/package.json +1 -1
- package/src/boot/registry/runtime.d.ts.map +1 -1
- package/src/boot/registry/runtime.js +38 -4
- package/src/cli/commands/TraceCommands.d.ts.map +1 -1
- package/src/cli/commands/TraceCommands.js +43 -51
- package/src/config/logging/KvLogger.d.ts.map +1 -1
- package/src/config/logging/KvLogger.js +18 -6
- package/src/functions/cloudflare.d.ts.map +1 -1
- package/src/functions/cloudflare.js +8 -0
- package/src/http/RequestContext.d.ts.map +1 -1
- package/src/http/RequestContext.js +5 -6
- package/src/index.d.ts +1 -0
- package/src/index.d.ts.map +1 -1
- package/src/index.js +4 -3
- package/src/middleware/ErrorHandlerMiddleware.d.ts.map +1 -1
- package/src/middleware/ErrorHandlerMiddleware.js +2 -0
- package/src/orm/adapters/SQLiteAdapter.d.ts.map +1 -1
- package/src/orm/adapters/SQLiteAdapter.js +2 -1
- package/src/orm/migrations/MigrationStore.d.ts.map +1 -1
- package/src/orm/migrations/MigrationStore.js +352 -16
- package/src/runtime/StartupConfigFileRegistry.d.ts +2 -1
- package/src/runtime/StartupConfigFileRegistry.d.ts.map +1 -1
- package/src/runtime/StartupConfigFileRegistry.js +1 -0
- package/src/runtime/plugins/trace-runtime.d.ts +5 -0
- package/src/runtime/plugins/trace-runtime.d.ts.map +1 -1
- package/src/runtime/plugins/trace-runtime.js +51 -7
- package/src/templates/project/basic/tsconfig.json.tpl +11 -12
- package/src/tools/queue/Queue.d.ts +1 -2
- package/src/tools/queue/Queue.d.ts.map +1 -1
- package/src/tools/queue/Queue.js +1 -2
- package/src/trace/SystemTraceBridge.js +1 -1
- package/src/zintrust.plugins.js +2 -2
- package/src/zintrust.plugins.wg.js +2 -2
package/bin/zintrust-main.d.ts
CHANGED
|
@@ -4,6 +4,18 @@
|
|
|
4
4
|
* This module contains the CLI implementation without a hashbang so that it can
|
|
5
5
|
* be imported by other bin shortcuts (zin/z/zt) without parse errors.
|
|
6
6
|
*/
|
|
7
|
+
type ProjectLocalCliTarget = {
|
|
8
|
+
binPath: string;
|
|
9
|
+
packageRoot: string;
|
|
10
|
+
};
|
|
7
11
|
export declare function run(): Promise<void>;
|
|
12
|
+
export declare const CliLauncherInternal: Readonly<{
|
|
13
|
+
CLI_HANDOFF_ENV_KEY: "ZINTRUST_CLI_HANDOFF";
|
|
14
|
+
findProjectLocalCliTarget: (cwd: string) => ProjectLocalCliTarget | undefined;
|
|
15
|
+
getCurrentPackageRoot: () => string;
|
|
16
|
+
getRealPath: (targetPath: string) => string;
|
|
17
|
+
isWithinDirectory: (targetPath: string, possibleParentPath: string) => boolean;
|
|
18
|
+
resolveProjectLocalCliHandoff: (cwd: string, currentPackageRoot: string, env?: NodeJS.ProcessEnv) => ProjectLocalCliTarget | undefined;
|
|
19
|
+
}>;
|
|
8
20
|
export {};
|
|
9
21
|
//# sourceMappingURL=zintrust-main.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zintrust-main.d.ts","sourceRoot":"","sources":["../../bin/zintrust-main.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"zintrust-main.d.ts","sourceRoot":"","sources":["../../bin/zintrust-main.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,KAAK,qBAAqB,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAmTF,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAMzC;AAED,eAAO,MAAM,mBAAmB;;qCAjSQ,MAAM,KAAG,qBAAqB,GAAG,SAAS;iCAtBhD,MAAM;8BAIP,MAAM,KAAG,MAAM;oCAQT,MAAM,sBAAsB,MAAM,KAAG,OAAO;yCAqC5E,MAAM,sBACS,MAAM,QACrB,MAAM,CAAC,UAAU,KACrB,qBAAqB,GAAG,SAAS;EA0QlC,CAAC;AAEH,OAAO,EAAE,CAAC"}
|
package/bin/zintrust-main.js
CHANGED
|
@@ -5,9 +5,86 @@
|
|
|
5
5
|
* be imported by other bin shortcuts (zin/z/zt) without parse errors.
|
|
6
6
|
*/
|
|
7
7
|
import { Logger } from '../src/config/logger.js';
|
|
8
|
+
import { spawnSync } from 'node:child_process';
|
|
8
9
|
import fs from 'node:fs';
|
|
9
10
|
import path from 'node:path';
|
|
10
11
|
import { fileURLToPath } from 'node:url';
|
|
12
|
+
const CLI_HANDOFF_ENV_KEY = 'ZINTRUST_CLI_HANDOFF';
|
|
13
|
+
const getCurrentPackageRoot = () => {
|
|
14
|
+
return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
15
|
+
};
|
|
16
|
+
const getRealPath = (targetPath) => {
|
|
17
|
+
try {
|
|
18
|
+
return fs.realpathSync(targetPath);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return path.resolve(targetPath);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const isWithinDirectory = (targetPath, possibleParentPath) => {
|
|
25
|
+
const normalizedTarget = getRealPath(targetPath);
|
|
26
|
+
const normalizedParent = getRealPath(possibleParentPath);
|
|
27
|
+
if (normalizedTarget === normalizedParent)
|
|
28
|
+
return true;
|
|
29
|
+
const relativePath = path.relative(normalizedParent, normalizedTarget);
|
|
30
|
+
return relativePath !== '' && !relativePath.startsWith('..') && !path.isAbsolute(relativePath);
|
|
31
|
+
};
|
|
32
|
+
const findProjectLocalCliTarget = (cwd) => {
|
|
33
|
+
let currentDir = path.resolve(cwd);
|
|
34
|
+
while (true) {
|
|
35
|
+
const packageRoot = path.join(currentDir, 'node_modules', '@zintrust', 'core');
|
|
36
|
+
const packageJsonPath = path.join(packageRoot, 'package.json');
|
|
37
|
+
const binCandidates = [
|
|
38
|
+
path.join(packageRoot, 'bin', 'zin.js'),
|
|
39
|
+
path.join(packageRoot, 'bin', 'zin.mjs'),
|
|
40
|
+
path.join(packageRoot, 'bin', 'zin.cjs'),
|
|
41
|
+
path.join(packageRoot, 'bin', 'zin.ts'),
|
|
42
|
+
];
|
|
43
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
44
|
+
const binPath = binCandidates.find((candidate) => fs.existsSync(candidate));
|
|
45
|
+
if (binPath !== undefined) {
|
|
46
|
+
return { binPath, packageRoot };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const parentDir = path.dirname(currentDir);
|
|
50
|
+
if (parentDir === currentDir)
|
|
51
|
+
return undefined;
|
|
52
|
+
currentDir = parentDir;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const resolveProjectLocalCliHandoff = (cwd, currentPackageRoot, env = process.env) => {
|
|
56
|
+
if (env[CLI_HANDOFF_ENV_KEY] === '1')
|
|
57
|
+
return undefined;
|
|
58
|
+
if (isWithinDirectory(cwd, currentPackageRoot))
|
|
59
|
+
return undefined;
|
|
60
|
+
const target = findProjectLocalCliTarget(cwd);
|
|
61
|
+
if (target === undefined)
|
|
62
|
+
return undefined;
|
|
63
|
+
if (getRealPath(target.packageRoot) === getRealPath(currentPackageRoot)) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
return target;
|
|
67
|
+
};
|
|
68
|
+
const handoffToProjectLocalCli = (target, rawArgs) => {
|
|
69
|
+
const result = spawnSync(process.execPath, [target.binPath, ...rawArgs], {
|
|
70
|
+
stdio: 'inherit',
|
|
71
|
+
env: {
|
|
72
|
+
...process.env,
|
|
73
|
+
[CLI_HANDOFF_ENV_KEY]: '1',
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
if (result.error !== undefined) {
|
|
77
|
+
throw result.error;
|
|
78
|
+
}
|
|
79
|
+
process.exit(typeof result.status === 'number' ? result.status : 1);
|
|
80
|
+
};
|
|
81
|
+
const maybeHandoffToProjectLocalCli = (rawArgs) => {
|
|
82
|
+
const localCliTarget = resolveProjectLocalCliHandoff(process.cwd(), getCurrentPackageRoot());
|
|
83
|
+
if (localCliTarget === undefined)
|
|
84
|
+
return false;
|
|
85
|
+
handoffToProjectLocalCli(localCliTarget, rawArgs);
|
|
86
|
+
return true;
|
|
87
|
+
};
|
|
11
88
|
const loadPackageVersionFast = () => {
|
|
12
89
|
try {
|
|
13
90
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -33,6 +110,12 @@ const getArgsFromProcess = () => {
|
|
|
33
110
|
const isVersionRequest = (args) => {
|
|
34
111
|
return args.includes('-v') || args.includes('--version');
|
|
35
112
|
};
|
|
113
|
+
const maybePrintVersionAndExit = (args) => {
|
|
114
|
+
if (!isVersionRequest(args))
|
|
115
|
+
return false;
|
|
116
|
+
printFancyVersion(loadPackageVersionFast());
|
|
117
|
+
return true;
|
|
118
|
+
};
|
|
36
119
|
const printFancyVersion = (version) => {
|
|
37
120
|
const framework = 'ZinTrust Framework';
|
|
38
121
|
const bannerWidth = 46;
|
|
@@ -110,69 +193,81 @@ const handleCliFatal = async (error, context) => {
|
|
|
110
193
|
}
|
|
111
194
|
process.exit(1);
|
|
112
195
|
};
|
|
113
|
-
|
|
196
|
+
const runCliInternal = async () => {
|
|
197
|
+
const { rawArgs: rawArgs0, args: args0 } = getArgsFromProcess();
|
|
198
|
+
if (maybeHandoffToProjectLocalCli(rawArgs0)) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
// Fast path: print version and exit without bootstrapping the CLI.
|
|
202
|
+
// This keeps `zin -v` / `zin --version` snappy and avoids any debug output.
|
|
203
|
+
if (maybePrintVersionAndExit(args0)) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const { EnvFileLoader } = await import('../src/cli/utils/EnvFileLoader.js');
|
|
207
|
+
EnvFileLoader.ensureLoaded();
|
|
208
|
+
// Auto-load install-only CLI extension packages that self-register commands.
|
|
209
|
+
let optionalCliExtensions;
|
|
210
|
+
let optionalCliStatuses = [];
|
|
114
211
|
try {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
212
|
+
({ OptionalCliExtensions: optionalCliExtensions } = await import('../src/cli/OptionalCliExtensions.js'));
|
|
213
|
+
optionalCliStatuses = await optionalCliExtensions.loadForArgs(args0);
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
// best-effort; missing optional extensions must not block the CLI
|
|
217
|
+
}
|
|
218
|
+
const missingOptionalExtension = optionalCliExtensions?.findMissingExtensionForArgs(args0, optionalCliStatuses);
|
|
219
|
+
if (missingOptionalExtension !== undefined) {
|
|
220
|
+
const { ErrorFactory } = await import('../src/exceptions/ZintrustError.js');
|
|
221
|
+
throw ErrorFactory.createCliError(optionalCliExtensions?.getMissingExtensionMessage(missingOptionalExtension) ??
|
|
222
|
+
`Missing optional CLI package: ${missingOptionalExtension.packageName}`);
|
|
223
|
+
}
|
|
224
|
+
// Ensure project-installed adapters/drivers are registered for CLI commands.
|
|
225
|
+
// (This is driven by src/zintrust.plugins.ts generated by `zin plugin install`.)
|
|
226
|
+
try {
|
|
227
|
+
const { PluginAutoImports } = await import('../src/runtime/PluginAutoImports.js');
|
|
228
|
+
const runtimeImportMode = process.env['DOCKER_WORKER'] === 'true' ? 'worker' : 'base';
|
|
229
|
+
const officialImports = await PluginAutoImports.tryImportRuntimeAutoImports(runtimeImportMode);
|
|
230
|
+
if (!officialImports.ok) {
|
|
231
|
+
logPluginAutoImportFailure(args0, 'Official', officialImports.errorMessage);
|
|
134
232
|
}
|
|
135
|
-
const
|
|
136
|
-
if (
|
|
137
|
-
|
|
138
|
-
throw ErrorFactory.createCliError(optionalCliExtensions?.getMissingExtensionMessage(missingOptionalExtension) ??
|
|
139
|
-
`Missing optional CLI package: ${missingOptionalExtension.packageName}`);
|
|
233
|
+
const projectImports = await PluginAutoImports.tryImportProjectAutoImports();
|
|
234
|
+
if (!projectImports.ok && projectImports.reason !== 'not-found') {
|
|
235
|
+
logPluginAutoImportFailure(args0, 'Project', projectImports.errorMessage);
|
|
140
236
|
}
|
|
141
|
-
|
|
142
|
-
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
// best-effort; CLI should still run even if plugins file is missing
|
|
240
|
+
}
|
|
241
|
+
const { CLI } = await import('../src/cli/CLI.js');
|
|
242
|
+
const cli = CLI.create();
|
|
243
|
+
// When executing via tsx (e.g. `npx tsx bin/zin.ts ...`), the script path can
|
|
244
|
+
// appear as the first element of `process.argv.slice(2)`. Commander expects
|
|
245
|
+
// args to start at the command name, so we strip a leading script path if present.
|
|
246
|
+
const { rawArgs, args } = getArgsFromProcess();
|
|
247
|
+
if (shouldDebugArgs(rawArgs)) {
|
|
143
248
|
try {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const officialImports = await PluginAutoImports.tryImportRuntimeAutoImports(runtimeImportMode);
|
|
147
|
-
if (!officialImports.ok) {
|
|
148
|
-
logPluginAutoImportFailure(args0, 'Official', officialImports.errorMessage);
|
|
149
|
-
}
|
|
150
|
-
const projectImports = await PluginAutoImports.tryImportProjectAutoImports();
|
|
151
|
-
if (!projectImports.ok && projectImports.reason !== 'not-found') {
|
|
152
|
-
logPluginAutoImportFailure(args0, 'Project', projectImports.errorMessage);
|
|
153
|
-
}
|
|
249
|
+
process.stderr.write(`[zintrust-cli] process.argv=${JSON.stringify(process.argv)}\n`);
|
|
250
|
+
process.stderr.write(`[zintrust-cli] rawArgs=${JSON.stringify(rawArgs)}\n`);
|
|
154
251
|
}
|
|
155
252
|
catch {
|
|
156
|
-
//
|
|
157
|
-
}
|
|
158
|
-
const { CLI } = await import('../src/cli/CLI.js');
|
|
159
|
-
const cli = CLI.create();
|
|
160
|
-
// When executing via tsx (e.g. `npx tsx bin/zin.ts ...`), the script path can
|
|
161
|
-
// appear as the first element of `process.argv.slice(2)`. Commander expects
|
|
162
|
-
// args to start at the command name, so we strip a leading script path if present.
|
|
163
|
-
const { rawArgs, args } = getArgsFromProcess();
|
|
164
|
-
if (shouldDebugArgs(rawArgs)) {
|
|
165
|
-
try {
|
|
166
|
-
process.stderr.write(`[zintrust-cli] process.argv=${JSON.stringify(process.argv)}\n`);
|
|
167
|
-
process.stderr.write(`[zintrust-cli] rawArgs=${JSON.stringify(rawArgs)}\n`);
|
|
168
|
-
}
|
|
169
|
-
catch {
|
|
170
|
-
// ignore
|
|
171
|
-
}
|
|
253
|
+
// ignore
|
|
172
254
|
}
|
|
173
|
-
|
|
255
|
+
}
|
|
256
|
+
await cli.run(normalizeProxyTargetArgs(args));
|
|
257
|
+
};
|
|
258
|
+
export async function run() {
|
|
259
|
+
try {
|
|
260
|
+
await runCliInternal();
|
|
174
261
|
}
|
|
175
262
|
catch (error) {
|
|
176
263
|
await handleCliFatal(error, 'CLI execution failed');
|
|
177
264
|
}
|
|
178
265
|
}
|
|
266
|
+
export const CliLauncherInternal = Object.freeze({
|
|
267
|
+
CLI_HANDOFF_ENV_KEY,
|
|
268
|
+
findProjectLocalCliTarget,
|
|
269
|
+
getCurrentPackageRoot,
|
|
270
|
+
getRealPath,
|
|
271
|
+
isWithinDirectory,
|
|
272
|
+
resolveProjectLocalCliHandoff,
|
|
273
|
+
});
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../src/boot/registry/runtime.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AASvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../src/boot/registry/runtime.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AASvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AA2O9C,eAAO,MAAM,8BAA8B,GAAI,iBAAiB,gBAAgB,KAAG,IA6BlF,CAAC;AAqUF,eAAO,MAAM,eAAe,GAAI,QAAQ;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,eAAe,EAAE,gBAAgB,CAAC;IAClC,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACrC,KAAG;IAAE,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CA0F7D,CAAC"}
|
|
@@ -384,11 +384,27 @@ const isTraceEnabled = () => {
|
|
|
384
384
|
const raw = readEnvString('TRACE_ENABLED').trim().toLowerCase();
|
|
385
385
|
return raw === '1' || raw === 'true';
|
|
386
386
|
};
|
|
387
|
+
const isTraceDashboardAutoMountEnabled = () => {
|
|
388
|
+
const raw = readEnvString('TRACE_AUTO_MOUNT').trim().toLowerCase();
|
|
389
|
+
return raw === '1' || raw === 'true';
|
|
390
|
+
};
|
|
391
|
+
const resolveTraceDashboardBasePath = () => {
|
|
392
|
+
const raw = readEnvString('TRACE_BASE_PATH').trim();
|
|
393
|
+
if (raw === '')
|
|
394
|
+
return '/trace';
|
|
395
|
+
return raw.startsWith('/') ? raw : `/${raw}`;
|
|
396
|
+
};
|
|
397
|
+
const resolveTraceDashboardMiddleware = () => {
|
|
398
|
+
return readEnvString('TRACE_MIDDLEWARE')
|
|
399
|
+
.split(',')
|
|
400
|
+
.map((value) => value.trim())
|
|
401
|
+
.filter(isNonEmptyString);
|
|
402
|
+
};
|
|
387
403
|
const isSystemTracePluginRequested = () => {
|
|
388
404
|
const globalTracePluginState = globalThis;
|
|
389
405
|
return globalTracePluginState.__zintrust_system_trace_plugin_requested__ === true;
|
|
390
406
|
};
|
|
391
|
-
const initializeSystemTrace = async () => {
|
|
407
|
+
const initializeSystemTrace = async (router) => {
|
|
392
408
|
if (!isSystemTracePluginRequested()) {
|
|
393
409
|
Logger.debug('System Trace plugin is not enabled in zintrust.plugins.*. Skipping init.');
|
|
394
410
|
return;
|
|
@@ -397,13 +413,31 @@ const initializeSystemTrace = async () => {
|
|
|
397
413
|
return;
|
|
398
414
|
const traceModule = (await tryImportOptional('@runtime/plugins/trace-runtime')) ??
|
|
399
415
|
(await loadLocalSystemTraceModule());
|
|
400
|
-
if (traceModule === undefined
|
|
416
|
+
if (traceModule === undefined) {
|
|
401
417
|
Logger.debug('System Trace is enabled but the optional package is unavailable.');
|
|
402
418
|
return;
|
|
403
419
|
}
|
|
404
420
|
try {
|
|
405
421
|
await traceModule.ensureSystemTraceRegistered();
|
|
406
|
-
|
|
422
|
+
if (traceModule.isAvailable?.() === false) {
|
|
423
|
+
Logger.debug('System Trace is enabled but the optional package is unavailable.');
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
if (!isTraceDashboardAutoMountEnabled()) {
|
|
427
|
+
Logger.info('System Trace runtime activated. Set TRACE_AUTO_MOUNT=true or register dashboard routes manually if needed.');
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
if (typeof traceModule.registerTraceDashboard !== 'function') {
|
|
431
|
+
Logger.warn('System Trace auto-mount requested but the optional package does not expose registerTraceDashboard.');
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
const basePath = resolveTraceDashboardBasePath();
|
|
435
|
+
const middleware = resolveTraceDashboardMiddleware();
|
|
436
|
+
traceModule.registerTraceDashboard(router, {
|
|
437
|
+
basePath,
|
|
438
|
+
...(middleware.length > 0 ? { middleware } : {}),
|
|
439
|
+
});
|
|
440
|
+
Logger.info(`System Trace dashboard auto-mounted at ${basePath}.`);
|
|
407
441
|
}
|
|
408
442
|
catch (error) {
|
|
409
443
|
Logger.warn('Failed to initialize System Trace runtime', error);
|
|
@@ -474,7 +508,7 @@ export const createLifecycle = (params) => {
|
|
|
474
508
|
await initializeArtifactDirectories(params.resolvedBasePath);
|
|
475
509
|
await registerMasterRoutes(params.resolvedBasePath, params.router);
|
|
476
510
|
initializeSockets(params.router);
|
|
477
|
-
await initializeSystemTrace();
|
|
511
|
+
await initializeSystemTrace(params.router);
|
|
478
512
|
if (Cloudflare.getWorkersEnv() === null && appConfig.dockerWorker === false) {
|
|
479
513
|
await initializeWorkers(params.router);
|
|
480
514
|
await initializeQueueMonitor(params.router);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TraceCommands.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/TraceCommands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAsBrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"TraceCommands.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/TraceCommands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAsBrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgqBzC,eAAO,MAAM,aAAa;mCACK,YAAY;mCAQZ,YAAY;oCAQX,YAAY;qCAQX,YAAY;;cAhCzB,MAAM;oBAAc,MAAM,OAAO;;;cAAjC,MAAM;oBAAc,MAAM,OAAO;;;cAAjC,MAAM;oBAAc,MAAM,OAAO;;;cAAjC,MAAM;oBAAc,MAAM,OAAO;;EAmDnD,CAAC"}
|
|
@@ -16,20 +16,40 @@ import { Database } from '../../orm/Database.js';
|
|
|
16
16
|
import { DatabaseAdapterRegistry } from '../../orm/DatabaseAdapterRegistry.js';
|
|
17
17
|
const loadTraceModule = async () => {
|
|
18
18
|
try {
|
|
19
|
-
return (await import('
|
|
19
|
+
return (await import('@zintrust/trace'));
|
|
20
20
|
}
|
|
21
21
|
catch (error) {
|
|
22
22
|
Logger.error('Failed to load optional package "@zintrust/trace"', error);
|
|
23
23
|
throw ErrorFactory.createCliError('Package "@zintrust/trace" is not installed. Add it to your project first.');
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
|
-
const
|
|
26
|
+
const addD1DatabaseOptions = (command) => {
|
|
27
27
|
command
|
|
28
|
-
.option('--hours <number>', 'Remove entries older than N hours (default: from config)', '')
|
|
29
28
|
.option('--local', 'D1 only: run against local D1 database')
|
|
30
29
|
.option('--remote', 'D1 only: run against remote D1 database')
|
|
31
|
-
.option('--database <name>', 'D1 only: Wrangler D1 database binding name')
|
|
30
|
+
.option('--database <name>', 'D1 only: Wrangler D1 database binding name');
|
|
31
|
+
};
|
|
32
|
+
const createTraceCommand = (config) => {
|
|
33
|
+
const command = BaseCommand.create({
|
|
34
|
+
name: config.name,
|
|
35
|
+
description: config.description,
|
|
36
|
+
addOptions: config.addOptions,
|
|
37
|
+
execute: async (options) => config.execute(options, command),
|
|
38
|
+
});
|
|
39
|
+
return command;
|
|
40
|
+
};
|
|
41
|
+
const resolveNamedTraceConnection = (name) => {
|
|
42
|
+
const connections = databaseConfig.connections;
|
|
43
|
+
return {
|
|
44
|
+
name,
|
|
45
|
+
config: connections[name] ?? databaseConfig.getConnection(),
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
const addPruneOptions = (command) => {
|
|
49
|
+
command
|
|
50
|
+
.option('--hours <number>', 'Remove entries older than N hours (default: from config)', '')
|
|
32
51
|
.option('--keep-exceptions', 'Keep exception entries regardless of age', false);
|
|
52
|
+
addD1DatabaseOptions(command);
|
|
33
53
|
};
|
|
34
54
|
const addMigrateOptions = (command) => {
|
|
35
55
|
command
|
|
@@ -41,10 +61,8 @@ const addMigrateOptions = (command) => {
|
|
|
41
61
|
.option('--force', 'Skip production confirmation (allow unsafe operations in production)')
|
|
42
62
|
.option('--all', 'Run migrations for all configured database connections')
|
|
43
63
|
.option('--connection <name>', 'Use a specific database connection for trace migrations')
|
|
44
|
-
.option('--local', 'D1 only: run against local D1 database')
|
|
45
|
-
.option('--remote', 'D1 only: run against remote D1 database')
|
|
46
|
-
.option('--database <name>', 'D1 only: Wrangler D1 database binding name')
|
|
47
64
|
.option('--no-interactive', 'Disable interactive prompts (useful for CI/CD)');
|
|
65
|
+
addD1DatabaseOptions(command);
|
|
48
66
|
};
|
|
49
67
|
const resolveDashboardBasePath = () => {
|
|
50
68
|
const raw = readEnvString('TRACE_BASE_PATH').trim();
|
|
@@ -456,20 +474,10 @@ const executeMigrateTrace = async (options, cmd) => {
|
|
|
456
474
|
}
|
|
457
475
|
}
|
|
458
476
|
else if (isNonEmptyString(options['connection'])) {
|
|
459
|
-
|
|
460
|
-
const connections = databaseConfig.connections;
|
|
461
|
-
targets.push({
|
|
462
|
-
name: selected,
|
|
463
|
-
config: connections[selected] ?? databaseConfig.getConnection(),
|
|
464
|
-
});
|
|
477
|
+
targets.push(resolveNamedTraceConnection(String(options['connection']).trim()));
|
|
465
478
|
}
|
|
466
479
|
else {
|
|
467
|
-
|
|
468
|
-
const connections = databaseConfig.connections;
|
|
469
|
-
targets.push({
|
|
470
|
-
name: selected,
|
|
471
|
-
config: connections[selected] ?? databaseConfig.getConnection(),
|
|
472
|
-
});
|
|
480
|
+
targets.push(resolveNamedTraceConnection(readEnvString('TRACE_DB_CONNECTION').trim() || 'default'));
|
|
473
481
|
}
|
|
474
482
|
let sequence = Promise.resolve();
|
|
475
483
|
for (const { name, config } of targets) {
|
|
@@ -489,46 +497,30 @@ const createProvider = (name, getCommand) => {
|
|
|
489
497
|
});
|
|
490
498
|
};
|
|
491
499
|
export const TraceCommands = Object.freeze({
|
|
492
|
-
createTracePruneCommand: () =>
|
|
500
|
+
createTracePruneCommand: () => createTraceCommand({
|
|
493
501
|
name: 'trace:prune',
|
|
494
502
|
description: 'Prune old entries from the trace storage',
|
|
495
503
|
addOptions: addPruneOptions,
|
|
496
|
-
execute: executePrune,
|
|
504
|
+
execute: async (options) => executePrune(options),
|
|
497
505
|
}),
|
|
498
|
-
createTraceClearCommand: () =>
|
|
506
|
+
createTraceClearCommand: () => createTraceCommand({
|
|
499
507
|
name: 'trace:clear',
|
|
500
508
|
description: 'Clear all entries from the trace storage',
|
|
501
|
-
addOptions:
|
|
502
|
-
command
|
|
503
|
-
.option('--local', 'D1 only: run against local D1 database')
|
|
504
|
-
.option('--remote', 'D1 only: run against remote D1 database')
|
|
505
|
-
.option('--database <name>', 'D1 only: Wrangler D1 database binding name');
|
|
506
|
-
},
|
|
509
|
+
addOptions: addD1DatabaseOptions,
|
|
507
510
|
execute: async (options) => executeClear(options),
|
|
508
511
|
}),
|
|
509
|
-
createTraceStatusCommand: () => {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
return cmd;
|
|
522
|
-
},
|
|
523
|
-
createTraceMigrateCommand: () => {
|
|
524
|
-
const cmd = BaseCommand.create({
|
|
525
|
-
name: 'migrate:trace',
|
|
526
|
-
description: 'Run trace package migrations',
|
|
527
|
-
addOptions: addMigrateOptions,
|
|
528
|
-
execute: async (options) => executeMigrateTrace(options, cmd),
|
|
529
|
-
});
|
|
530
|
-
return cmd;
|
|
531
|
-
},
|
|
512
|
+
createTraceStatusCommand: () => createTraceCommand({
|
|
513
|
+
name: 'trace:status',
|
|
514
|
+
description: 'Show trace storage stats and dashboard location',
|
|
515
|
+
addOptions: addD1DatabaseOptions,
|
|
516
|
+
execute: executeStatus,
|
|
517
|
+
}),
|
|
518
|
+
createTraceMigrateCommand: () => createTraceCommand({
|
|
519
|
+
name: 'migrate:trace',
|
|
520
|
+
description: 'Run trace package migrations',
|
|
521
|
+
addOptions: addMigrateOptions,
|
|
522
|
+
execute: executeMigrateTrace,
|
|
523
|
+
}),
|
|
532
524
|
createTracePruneProvider: () => createProvider('trace:prune', TraceCommands.createTracePruneCommand),
|
|
533
525
|
createTraceClearProvider: () => createProvider('trace:clear', TraceCommands.createTraceClearCommand),
|
|
534
526
|
createTraceStatusProvider: () => createProvider('trace:status', TraceCommands.createTraceStatusCommand),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KvLogger.d.ts","sourceRoot":"","sources":["../../../../src/config/logging/KvLogger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;
|
|
1
|
+
{"version":3,"file":"KvLogger.d.ts","sourceRoot":"","sources":["../../../../src/config/logging/KvLogger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAiKF,eAAO,MAAM,QAAQ;mBACE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;EAa/C,CAAC;AAEH,eAAe,QAAQ,CAAC"}
|
|
@@ -46,6 +46,7 @@ const buildKey = (timestampIso) => {
|
|
|
46
46
|
let buffer = [];
|
|
47
47
|
let flushTimer;
|
|
48
48
|
let flushPromise;
|
|
49
|
+
let resolveScheduledFlush;
|
|
49
50
|
const scheduleFlush = async () => {
|
|
50
51
|
if (flushPromise !== undefined)
|
|
51
52
|
return flushPromise;
|
|
@@ -57,6 +58,7 @@ const scheduleFlush = async () => {
|
|
|
57
58
|
await flushNow();
|
|
58
59
|
}
|
|
59
60
|
finally {
|
|
61
|
+
resolveScheduledFlush = undefined;
|
|
60
62
|
resolve(undefined);
|
|
61
63
|
}
|
|
62
64
|
};
|
|
@@ -65,6 +67,7 @@ const scheduleFlush = async () => {
|
|
|
65
67
|
void run();
|
|
66
68
|
return;
|
|
67
69
|
}
|
|
70
|
+
resolveScheduledFlush = resolve;
|
|
68
71
|
flushTimer = globalThis.setTimeout(() => {
|
|
69
72
|
flushTimer = undefined;
|
|
70
73
|
void run();
|
|
@@ -122,6 +125,20 @@ const flushSoon = async () => {
|
|
|
122
125
|
});
|
|
123
126
|
return flushPromise;
|
|
124
127
|
};
|
|
128
|
+
const flushImmediately = async () => {
|
|
129
|
+
const pendingResolve = resolveScheduledFlush;
|
|
130
|
+
if (flushTimer !== undefined) {
|
|
131
|
+
globalThis.clearTimeout(flushTimer);
|
|
132
|
+
flushTimer = undefined;
|
|
133
|
+
resolveScheduledFlush = undefined;
|
|
134
|
+
flushPromise = undefined;
|
|
135
|
+
}
|
|
136
|
+
const immediatePromise = flushSoon();
|
|
137
|
+
if (pendingResolve !== undefined) {
|
|
138
|
+
void immediatePromise.finally(() => pendingResolve());
|
|
139
|
+
}
|
|
140
|
+
return immediatePromise;
|
|
141
|
+
};
|
|
125
142
|
export const KvLogger = Object.freeze({
|
|
126
143
|
async enqueue(event) {
|
|
127
144
|
if (!isEnabled())
|
|
@@ -130,12 +147,7 @@ export const KvLogger = Object.freeze({
|
|
|
130
147
|
// Basic size guard: flush if it gets too large
|
|
131
148
|
const maxBatch = 100;
|
|
132
149
|
if (buffer.length >= maxBatch) {
|
|
133
|
-
|
|
134
|
-
if (flushTimer !== undefined) {
|
|
135
|
-
globalThis.clearTimeout(flushTimer);
|
|
136
|
-
flushTimer = undefined;
|
|
137
|
-
}
|
|
138
|
-
return flushSoon();
|
|
150
|
+
return flushImmediately();
|
|
139
151
|
}
|
|
140
152
|
return scheduleFlush();
|
|
141
153
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../../src/functions/cloudflare.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../../src/functions/cloudflare.ts"],"names":[],"mappings":";mBAyPuB,OAAO,QAAQ,OAAO,QAAQ,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;;AADhF,wBAoDE;AAGF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2B;gBAExC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO;IAKlC,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;CAkBjD"}
|
|
@@ -25,6 +25,10 @@ const startupConfigModules = Object.freeze([
|
|
|
25
25
|
file: StartupConfigFile.Mail,
|
|
26
26
|
serviceModuleId: '@service-runtime-config/' + 'mail.ts',
|
|
27
27
|
},
|
|
28
|
+
{
|
|
29
|
+
file: StartupConfigFile.Trace,
|
|
30
|
+
serviceModuleId: '@service-runtime-config/' + 'trace.ts',
|
|
31
|
+
},
|
|
28
32
|
{
|
|
29
33
|
file: StartupConfigFile.Middleware,
|
|
30
34
|
serviceModuleId: '@service-runtime-config/' + 'middleware.ts',
|
|
@@ -58,6 +62,9 @@ const importRootDatabaseModule = async () => {
|
|
|
58
62
|
const importRootMailModule = async () => {
|
|
59
63
|
return (await import('@runtime-config/' + 'mail.ts').catch(() => ({})));
|
|
60
64
|
};
|
|
65
|
+
const importRootTraceModule = async () => {
|
|
66
|
+
return (await import('@runtime-config/' + 'trace.ts').catch(() => ({})));
|
|
67
|
+
};
|
|
61
68
|
const importRootMiddlewareModule = async () => {
|
|
62
69
|
return (await import('@runtime-config/' + 'middleware.ts').catch(() => ({})));
|
|
63
70
|
};
|
|
@@ -78,6 +85,7 @@ const rootStartupImporters = Object.freeze({
|
|
|
78
85
|
[StartupConfigFile.Cache]: importRootCacheModule,
|
|
79
86
|
[StartupConfigFile.Database]: importRootDatabaseModule,
|
|
80
87
|
[StartupConfigFile.Mail]: importRootMailModule,
|
|
88
|
+
[StartupConfigFile.Trace]: importRootTraceModule,
|
|
81
89
|
[StartupConfigFile.Middleware]: importRootMiddlewareModule,
|
|
82
90
|
[StartupConfigFile.Notification]: importRootNotificationModule,
|
|
83
91
|
[StartupConfigFile.Queue]: importRootQueueModule,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequestContext.d.ts","sourceRoot":"","sources":["../../../src/http/RequestContext.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"RequestContext.d.ts","sourceRoot":"","sources":["../../../src/http/RequestContext.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAqGD,eAAO,MAAM,cAAc;QACf,CAAC,WAAW,eAAe,YAAY,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;eAKpD,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;YAK7C,eAAe,GAAG,SAAS;gBAIvB,QAAQ,GAAG,eAAe;gBAoC1B,QAAQ,WAAW,eAAe,GAAG,IAAI;aAS5C,QAAQ,GAAG,eAAe,GAAG,SAAS;oBAM/B,eAAe,UAAU,MAAM,GAAG,eAAe;mBASlD,QAAQ,UAAU,MAAM,GAAG,SAAS,GAAG,IAAI;qBAIzC,QAAQ,YAAY,MAAM,GAAG,SAAS,GAAG,IAAI;oBAI9C,QAAQ,WAAW,MAAM,GAAG,SAAS,GAAG,IAAI;EAG5D,CAAC;AAEH,eAAe,cAAc,CAAC"}
|
|
@@ -77,11 +77,9 @@ const setContextField = (req, field, value) => {
|
|
|
77
77
|
ctx[field] = value;
|
|
78
78
|
}
|
|
79
79
|
};
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return storage;
|
|
84
|
-
})();
|
|
80
|
+
const resolvedStorage = await resolveStorage();
|
|
81
|
+
syncStorage = resolvedStorage;
|
|
82
|
+
const STORAGE_PROMISE = Promise.resolve(resolvedStorage);
|
|
85
83
|
export const RequestContext = Object.freeze({
|
|
86
84
|
async run(context, callback) {
|
|
87
85
|
const storage = await STORAGE_PROMISE;
|
|
@@ -101,7 +99,8 @@ export const RequestContext = Object.freeze({
|
|
|
101
99
|
const traceId = extractTraceIdFromTraceparent(getHeaderString(req, 'traceparent')) ??
|
|
102
100
|
getHeaderString(req, 'x-trace-id') ??
|
|
103
101
|
getTraceIdFromMicroserviceTraceContext(req) ??
|
|
104
|
-
getOptionalContextString(req, 'traceId')
|
|
102
|
+
getOptionalContextString(req, 'traceId') ??
|
|
103
|
+
requestId;
|
|
105
104
|
const userId = getOptionalContextString(req, 'userId');
|
|
106
105
|
const tenantId = getOptionalContextString(req, 'tenantId');
|
|
107
106
|
const ctx = {
|
package/src/index.d.ts
CHANGED
|
@@ -99,6 +99,7 @@ export { Xss } from './security/Xss';
|
|
|
99
99
|
export { XssProtection } from './security/XssProtection';
|
|
100
100
|
export { ErrorFactory } from './exceptions/ZintrustError';
|
|
101
101
|
export { detectCloudflareWorkers, detectRuntimePlatform, RUNTIME_PLATFORM, RuntimeServices, type RuntimeCrypto, type RuntimeEnvReader, type RuntimeFs, type RuntimePlatform, type RuntimeServices as RuntimeServicesType, type RuntimeTimers, } from './runtime/RuntimeServices';
|
|
102
|
+
export { StartupConfigFile, StartupConfigFileRegistry } from './runtime/StartupConfigFileRegistry';
|
|
102
103
|
export { SystemTraceBridge } from './trace/SystemTraceBridge';
|
|
103
104
|
export { EventDispatcher } from './events/EventDispatcher';
|
|
104
105
|
export type { EventListener, EventMap, IEventDispatcher } from './events/EventDispatcher';
|