@zintrust/core 0.7.2 → 0.7.7
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/package.json +1 -1
- package/src/cache/drivers/KVRemoteDriver.d.ts.map +1 -1
- package/src/cache/drivers/KVRemoteDriver.js +24 -27
- package/src/cli/commands/schedule/ScheduleCliSupport.d.ts.map +1 -1
- package/src/cli/commands/schedule/ScheduleCliSupport.js +23 -7
- package/src/cli/scaffolding/ProjectScaffolder.d.ts.map +1 -1
- package/src/cli/scaffolding/ProjectScaffolder.js +45 -6
- package/src/cli/utils/spawn.d.ts.map +1 -1
- package/src/cli/utils/spawn.js +19 -13
- package/src/config/logger.d.ts +10 -12
- package/src/config/logger.d.ts.map +1 -1
- package/src/config/logger.js +6 -3
- package/src/index.js +3 -3
- package/src/proxy/ProxyServerUtils.d.ts.map +1 -1
- package/src/proxy/ProxyServerUtils.js +49 -12
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KVRemoteDriver.d.ts","sourceRoot":"","sources":["../../../../src/cache/drivers/KVRemoteDriver.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"KVRemoteDriver.d.ts","sourceRoot":"","sources":["../../../../src/cache/drivers/KVRemoteDriver.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AA6YtD,eAAO,MAAM,cAAc;kBAvEM,WAAW;EAyE1C,CAAC;AAEH,eAAe,cAAc,CAAC"}
|
|
@@ -206,6 +206,25 @@ const createCloudflareKvApiClient = (resolveNamespaceId) => {
|
|
|
206
206
|
};
|
|
207
207
|
return { getJson, putJson, deleteKey };
|
|
208
208
|
};
|
|
209
|
+
const logKvRemoteProxyFallback = (operation, error) => {
|
|
210
|
+
Logger.warn(`KV remote proxy ${operation} failed; falling back to Cloudflare KV API`, Logger.withTraceSkipContext({
|
|
211
|
+
error: error instanceof Error ? error.message : String(error),
|
|
212
|
+
}));
|
|
213
|
+
};
|
|
214
|
+
const clearKvRemoteDriver = async () => {
|
|
215
|
+
Logger.warn('KV remote clear() is not implemented.');
|
|
216
|
+
await Promise.resolve();
|
|
217
|
+
};
|
|
218
|
+
const createKvRemoteHas = (getJson) => {
|
|
219
|
+
return async function has(key) {
|
|
220
|
+
if (!hasCloudflareApiCreds())
|
|
221
|
+
return (await this.get(key)) !== null;
|
|
222
|
+
const settings = getSettings();
|
|
223
|
+
if (!hasProxySigningCreds(settings))
|
|
224
|
+
return (await getJson(key)) !== null;
|
|
225
|
+
return (await this.get(key)) !== null;
|
|
226
|
+
};
|
|
227
|
+
};
|
|
209
228
|
const createKvRemoteDriver = () => {
|
|
210
229
|
const resolveNamespaceId = createCloudflareNamespaceIdResolver();
|
|
211
230
|
const cf = createCloudflareKvApiClient(resolveNamespaceId);
|
|
@@ -226,11 +245,7 @@ const createKvRemoteDriver = () => {
|
|
|
226
245
|
catch (error) {
|
|
227
246
|
if (!hasCloudflareApiCreds())
|
|
228
247
|
throw error;
|
|
229
|
-
|
|
230
|
-
...Logger.withTraceSkipContext({
|
|
231
|
-
error: error instanceof Error ? error.message : String(error),
|
|
232
|
-
}),
|
|
233
|
-
});
|
|
248
|
+
logKvRemoteProxyFallback('GET', error);
|
|
234
249
|
return cf.getJson(key);
|
|
235
250
|
}
|
|
236
251
|
},
|
|
@@ -252,11 +267,7 @@ const createKvRemoteDriver = () => {
|
|
|
252
267
|
catch (error) {
|
|
253
268
|
if (!hasCloudflareApiCreds())
|
|
254
269
|
throw error;
|
|
255
|
-
|
|
256
|
-
...Logger.withTraceSkipContext({
|
|
257
|
-
error: error instanceof Error ? error.message : String(error),
|
|
258
|
-
}),
|
|
259
|
-
});
|
|
270
|
+
logKvRemoteProxyFallback('PUT', error);
|
|
260
271
|
await cf.putJson(key, value, ttl);
|
|
261
272
|
}
|
|
262
273
|
},
|
|
@@ -276,26 +287,12 @@ const createKvRemoteDriver = () => {
|
|
|
276
287
|
catch (error) {
|
|
277
288
|
if (!hasCloudflareApiCreds())
|
|
278
289
|
throw error;
|
|
279
|
-
|
|
280
|
-
...Logger.withTraceSkipContext({
|
|
281
|
-
error: error instanceof Error ? error.message : String(error),
|
|
282
|
-
}),
|
|
283
|
-
});
|
|
290
|
+
logKvRemoteProxyFallback('DELETE', error);
|
|
284
291
|
await cf.deleteKey(key);
|
|
285
292
|
}
|
|
286
293
|
},
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
await Promise.resolve();
|
|
290
|
-
},
|
|
291
|
-
async has(key) {
|
|
292
|
-
if (!hasCloudflareApiCreds())
|
|
293
|
-
return (await this.get(key)) !== null;
|
|
294
|
-
const settings = getSettings();
|
|
295
|
-
if (!hasProxySigningCreds(settings))
|
|
296
|
-
return (await cf.getJson(key)) !== null;
|
|
297
|
-
return (await this.get(key)) !== null;
|
|
298
|
-
},
|
|
294
|
+
clear: clearKvRemoteDriver,
|
|
295
|
+
has: createKvRemoteHas(cf.getJson),
|
|
299
296
|
};
|
|
300
297
|
};
|
|
301
298
|
export const KVRemoteDriver = Object.freeze({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScheduleCliSupport.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/schedule/ScheduleCliSupport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ScheduleCliSupport.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/schedule/ScheduleCliSupport.ts"],"names":[],"mappings":"AAyNA,eAAO,MAAM,kBAAkB;sCAzEc,OAAO,CAAC,OAAO,CAAC;mBA2EtC,OAAO,CAAC,IAAI,CAAC;gCA3BG,OAAO,CAAC,IAAI,CAAC;EAqClD,CAAC;AAEH,eAAe,kBAAkB,CAAC"}
|
|
@@ -33,16 +33,33 @@ const getProjectSourceCliEntry = (projectRoot) => {
|
|
|
33
33
|
}
|
|
34
34
|
return undefined;
|
|
35
35
|
};
|
|
36
|
-
const
|
|
36
|
+
const getCurrentCliScript = () => {
|
|
37
37
|
const script = String(process.argv[1] ?? '').trim();
|
|
38
38
|
if (script.length === 0)
|
|
39
|
-
return
|
|
39
|
+
return undefined;
|
|
40
40
|
const resolvedScript = path.resolve(script);
|
|
41
|
+
return existsSync(resolvedScript) ? resolvedScript : undefined;
|
|
42
|
+
};
|
|
43
|
+
const isRunningProjectSourceCli = (projectRoot) => {
|
|
44
|
+
const resolvedScript = getCurrentCliScript();
|
|
45
|
+
if (resolvedScript === undefined)
|
|
46
|
+
return false;
|
|
41
47
|
const sourceCliEntry = getProjectSourceCliEntry(projectRoot);
|
|
42
48
|
if (sourceCliEntry === undefined)
|
|
43
49
|
return false;
|
|
44
50
|
return resolvedScript === path.resolve(sourceCliEntry);
|
|
45
51
|
};
|
|
52
|
+
const getScheduleReentryScript = (projectRoot) => {
|
|
53
|
+
const sourceCliEntry = getProjectSourceCliEntry(projectRoot);
|
|
54
|
+
if (sourceCliEntry !== undefined) {
|
|
55
|
+
return path.relative(projectRoot, sourceCliEntry);
|
|
56
|
+
}
|
|
57
|
+
const currentCliScript = getCurrentCliScript();
|
|
58
|
+
if (currentCliScript === undefined)
|
|
59
|
+
return undefined;
|
|
60
|
+
const relativeCurrentScript = path.relative(projectRoot, currentCliScript);
|
|
61
|
+
return relativeCurrentScript.startsWith('..') ? currentCliScript : relativeCurrentScript;
|
|
62
|
+
};
|
|
46
63
|
const getExistingProjectSchedulePath = () => {
|
|
47
64
|
for (const loader of getProjectScheduleLoaders()) {
|
|
48
65
|
if (loader.exists())
|
|
@@ -108,14 +125,13 @@ const ensureProjectSourceContext = async () => {
|
|
|
108
125
|
if (isRunningProjectSourceCli(projectRoot)) {
|
|
109
126
|
return false;
|
|
110
127
|
}
|
|
111
|
-
const
|
|
112
|
-
if (
|
|
113
|
-
throw ErrorFactory.createCliError('Source schedules require a project CLI entrypoint at bin/zin.ts or bin/zintrust.ts');
|
|
128
|
+
const reentryScript = getScheduleReentryScript(projectRoot);
|
|
129
|
+
if (reentryScript === undefined) {
|
|
130
|
+
throw ErrorFactory.createCliError('Source schedules require either a project CLI entrypoint at bin/zin.ts or bin/zintrust.ts, or a resolvable current CLI script.');
|
|
114
131
|
}
|
|
115
|
-
const relativeSourceCliEntry = path.relative(projectRoot, sourceCliEntry);
|
|
116
132
|
const exitCode = await SpawnUtil.spawnAndWait({
|
|
117
133
|
command: 'tsx',
|
|
118
|
-
args: [
|
|
134
|
+
args: [reentryScript, ...process.argv.slice(2)],
|
|
119
135
|
cwd: projectRoot,
|
|
120
136
|
env: {
|
|
121
137
|
...process.env,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectScaffolder.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/ProjectScaffolder.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"ProjectScaffolder.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/ProjectScaffolder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAiBH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,cAAc,GAAG,sBAAsB,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAAC;IACtD,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,eAAe,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;IACpE,cAAc,IAAI,MAAM,CAAC;IACzB,sBAAsB,IAAI,OAAO,CAAC;IAClC,iBAAiB,IAAI,MAAM,CAAC;IAC5B,WAAW,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM,CAAC;IACtD,gBAAgB,IAAI,OAAO,CAAC;IAC5B,aAAa,IAAI,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;CAC3E;AAumBD,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAEhD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAsBrE;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG;IAChE,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAsBA;AAwJD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,GAAE,MAAsB,GAAG,kBAAkB,CAsB/F;AAED,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CAEhC;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;EAM5B,CAAC"}
|
|
@@ -7,6 +7,7 @@ import { EnvData } from '../scaffolding/env.js';
|
|
|
7
7
|
import { extractMajorMinorVersion, toCompatibleGovernanceVersion, } from '../scaffolding/ScaffoldingVersionUtils.js';
|
|
8
8
|
import { Logger } from '../../config/logger.js';
|
|
9
9
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
10
|
+
import { isNonEmptyString } from '../../helper/index.js';
|
|
10
11
|
import { randomBytes } from '../../node-singletons/crypto.js';
|
|
11
12
|
import fs from '../../node-singletons/fs.js';
|
|
12
13
|
import * as path from '../../node-singletons/path.js';
|
|
@@ -24,11 +25,38 @@ const readBundledGovernancePackage = () => {
|
|
|
24
25
|
const SAFE_PATH = '/usr/local/bin:/usr/bin:/bin';
|
|
25
26
|
const NPM_VIEW_TIMEOUT_MS = 1500;
|
|
26
27
|
const publishedVersionCache = new Map();
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
const SAFE_NPM_ENV_KEYS = Object.freeze([
|
|
29
|
+
'HOME',
|
|
30
|
+
'USERPROFILE',
|
|
31
|
+
'APPDATA',
|
|
32
|
+
'LOCALAPPDATA',
|
|
33
|
+
'npm_config_userconfig',
|
|
34
|
+
'npm_config_cache',
|
|
35
|
+
'NPM_CONFIG_CACHE',
|
|
36
|
+
'npm_config_registry',
|
|
37
|
+
'NPM_CONFIG_REGISTRY',
|
|
38
|
+
'HTTP_PROXY',
|
|
39
|
+
'HTTPS_PROXY',
|
|
40
|
+
'NO_PROXY',
|
|
41
|
+
'http_proxy',
|
|
42
|
+
'https_proxy',
|
|
43
|
+
'no_proxy',
|
|
44
|
+
'SSL_CERT_FILE',
|
|
45
|
+
'NODE_EXTRA_CA_CERTS',
|
|
46
|
+
]);
|
|
47
|
+
const createSafeNpmEnv = () => {
|
|
48
|
+
const env = {
|
|
49
|
+
NODE_ENV: process.env['NODE_ENV'] ?? 'development',
|
|
50
|
+
PATH: SAFE_PATH,
|
|
51
|
+
};
|
|
52
|
+
for (const key of SAFE_NPM_ENV_KEYS) {
|
|
53
|
+
const value = process.env[key];
|
|
54
|
+
if (isNonEmptyString(value)) {
|
|
55
|
+
env[key] = value;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return env;
|
|
59
|
+
};
|
|
32
60
|
const loadPublishedNpmVersion = (packageName) => {
|
|
33
61
|
if (publishedVersionCache.has(packageName)) {
|
|
34
62
|
return publishedVersionCache.get(packageName);
|
|
@@ -563,6 +591,14 @@ const createDirectoriesForState = (state) => {
|
|
|
563
591
|
const template = resolveTemplate(state.templateName);
|
|
564
592
|
return createDirectories(state.projectPath, template?.directories ?? []);
|
|
565
593
|
};
|
|
594
|
+
const canReuseExistingProjectPath = (projectPath) => {
|
|
595
|
+
try {
|
|
596
|
+
return fs.statSync(projectPath).isDirectory() && fs.readdirSync(projectPath).length === 0;
|
|
597
|
+
}
|
|
598
|
+
catch {
|
|
599
|
+
return false;
|
|
600
|
+
}
|
|
601
|
+
};
|
|
566
602
|
const createFilesForState = (state) => {
|
|
567
603
|
const template = resolveTemplate(state.templateName);
|
|
568
604
|
const variables = state.variables;
|
|
@@ -622,9 +658,12 @@ const scaffoldWithState = async (state, options
|
|
|
622
658
|
}
|
|
623
659
|
prepareContext(state, options);
|
|
624
660
|
if (fs.existsSync(state.projectPath)) {
|
|
625
|
-
if (options.overwrite === true) {
|
|
661
|
+
if (options.overwrite === true || options.force === true) {
|
|
626
662
|
fs.rmSync(state.projectPath, { recursive: true, force: true });
|
|
627
663
|
}
|
|
664
|
+
else if (canReuseExistingProjectPath(state.projectPath)) {
|
|
665
|
+
Logger.info(`Reusing empty project directory: ${state.projectPath}`);
|
|
666
|
+
}
|
|
628
667
|
else {
|
|
629
668
|
return {
|
|
630
669
|
success: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../../../src/cli/utils/spawn.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../../../src/cli/utils/spawn.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAiDD,eAAO,MAAM,SAAS;wBACM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;EAiF7D,CAAC"}
|
package/src/cli/utils/spawn.js
CHANGED
|
@@ -3,6 +3,7 @@ import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
|
3
3
|
import { spawn } from '../../node-singletons/child-process.js';
|
|
4
4
|
import { existsSync } from '../../node-singletons/fs.js';
|
|
5
5
|
import * as path from '../../node-singletons/path.js';
|
|
6
|
+
import { fileURLToPath } from '../../node-singletons/url.js';
|
|
6
7
|
const getExitCode = (exitCode, signal) => {
|
|
7
8
|
if (typeof exitCode === 'number')
|
|
8
9
|
return exitCode;
|
|
@@ -10,22 +11,28 @@ const getExitCode = (exitCode, signal) => {
|
|
|
10
11
|
return 0;
|
|
11
12
|
return 1;
|
|
12
13
|
};
|
|
14
|
+
const CURRENT_PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../..');
|
|
15
|
+
const buildBinCandidates = (binDir, command) => process.platform === 'win32'
|
|
16
|
+
? [
|
|
17
|
+
path.join(binDir, `${command}.cmd`),
|
|
18
|
+
path.join(binDir, `${command}.exe`),
|
|
19
|
+
path.join(binDir, `${command}.bat`),
|
|
20
|
+
path.join(binDir, command),
|
|
21
|
+
]
|
|
22
|
+
: [path.join(binDir, command)];
|
|
13
23
|
const resolveLocalBin = (command, cwd) => {
|
|
14
24
|
// If command is already a path, leave it alone.
|
|
15
25
|
if (command.includes('/') || command.includes('\\'))
|
|
16
26
|
return command;
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
for (const candidate of candidates) {
|
|
27
|
-
if (existsSync(candidate))
|
|
28
|
-
return candidate;
|
|
27
|
+
const binDirs = [
|
|
28
|
+
path.join(cwd, 'node_modules', '.bin'),
|
|
29
|
+
path.join(CURRENT_PACKAGE_ROOT, 'node_modules', '.bin'),
|
|
30
|
+
].filter((value, index, items) => items.indexOf(value) === index);
|
|
31
|
+
for (const binDir of binDirs) {
|
|
32
|
+
for (const candidate of buildBinCandidates(binDir, command)) {
|
|
33
|
+
if (existsSync(candidate))
|
|
34
|
+
return candidate;
|
|
35
|
+
}
|
|
29
36
|
}
|
|
30
37
|
return command;
|
|
31
38
|
};
|
|
@@ -34,7 +41,6 @@ const buildCommandNotFoundMessage = (command) => {
|
|
|
34
41
|
return [
|
|
35
42
|
"Error: 'tsx' not found on PATH.",
|
|
36
43
|
'Install it in the project with "npm install -D tsx".',
|
|
37
|
-
'If you want a machine-wide fallback, install it globally with "npm install -g tsx".',
|
|
38
44
|
].join(' ');
|
|
39
45
|
}
|
|
40
46
|
return `Error: '${command}' not found on PATH.`;
|
package/src/config/logger.d.ts
CHANGED
|
@@ -6,23 +6,21 @@ interface ILogger {
|
|
|
6
6
|
error(message: string, error?: unknown, category?: string): void;
|
|
7
7
|
fatal(message: string, error?: unknown, category?: string): void;
|
|
8
8
|
}
|
|
9
|
+
interface ILoggerNamespace extends ILogger {
|
|
10
|
+
cleanLogsOnce(): Promise<string[]>;
|
|
11
|
+
scope(scope: string): ILogger;
|
|
12
|
+
addSink(fn: LogSink): () => void;
|
|
13
|
+
withTraceSkipContext(context?: Record<string, unknown>): Record<string, unknown>;
|
|
14
|
+
shouldSkipTraceLogContext(context?: Record<string, unknown>): boolean;
|
|
15
|
+
}
|
|
9
16
|
/**
|
|
10
17
|
* External log sink. Receives every log line after the built-in sinks have fired.
|
|
11
18
|
* Return value is ignored; errors are swallowed to protect the caller.
|
|
12
19
|
*/
|
|
13
20
|
export type LogSink = (level: LogLevel, message: string, context?: Record<string, unknown>) => void;
|
|
21
|
+
export declare const withTraceSkipContext: (context?: Record<string, unknown>) => Record<string, unknown>;
|
|
22
|
+
export declare const shouldSkipTraceLogContext: (context?: Record<string, unknown>) => boolean;
|
|
14
23
|
export declare const cleanLogsOnce: () => Promise<string[]>;
|
|
15
|
-
export declare const Logger:
|
|
16
|
-
debug: (message: string, data?: unknown, category?: string) => void;
|
|
17
|
-
info: (message: string, data?: unknown, category?: string) => void;
|
|
18
|
-
warn: (message: string, data?: unknown, category?: string) => void;
|
|
19
|
-
error: (message: string, error?: unknown, category?: string) => void;
|
|
20
|
-
fatal: (message: string, error?: unknown, category?: string) => void;
|
|
21
|
-
cleanLogsOnce: () => Promise<string[]>;
|
|
22
|
-
scope: (scope: string) => ILogger;
|
|
23
|
-
addSink: (fn: LogSink) => (() => void);
|
|
24
|
-
withTraceSkipContext: (context?: Record<string, unknown>) => Record<string, unknown>;
|
|
25
|
-
shouldSkipTraceLogContext: (context?: Record<string, unknown>) => boolean;
|
|
26
|
-
}>;
|
|
24
|
+
export declare const Logger: ILoggerNamespace;
|
|
27
25
|
export default Logger;
|
|
28
26
|
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/config/logger.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,UAAU,OAAO;IACf,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClE;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/config/logger.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,UAAU,OAAO;IACf,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClE;AAED,UAAU,gBAAiB,SAAQ,OAAO;IACxC,aAAa,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACnC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,OAAO,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,IAAI,CAAC;IACjC,oBAAoB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjF,yBAAyB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;CACvE;AAkzBD;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;AAIpG,eAAO,MAAM,oBAAoB,GAC/B,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CASxB,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,OAE7E,CAAC;AAkCF,eAAO,MAAM,aAAa,QAAa,OAAO,CAAC,MAAM,EAAE,CAYtD,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,gBAWnB,CAAC;AAEH,eAAe,MAAM,CAAC"}
|
package/src/config/logger.js
CHANGED
|
@@ -741,13 +741,16 @@ const createLoggerScope = (scope) => {
|
|
|
741
741
|
};
|
|
742
742
|
};
|
|
743
743
|
const TRACE_SKIP_LOG_CONTEXT_KEY = '__zintrustSkipTraceLog';
|
|
744
|
-
const withTraceSkipContext = (context) => {
|
|
744
|
+
export const withTraceSkipContext = (context) => {
|
|
745
|
+
if (context === undefined) {
|
|
746
|
+
return { [TRACE_SKIP_LOG_CONTEXT_KEY]: true };
|
|
747
|
+
}
|
|
745
748
|
return {
|
|
746
|
-
...
|
|
749
|
+
...context,
|
|
747
750
|
[TRACE_SKIP_LOG_CONTEXT_KEY]: true,
|
|
748
751
|
};
|
|
749
752
|
};
|
|
750
|
-
const shouldSkipTraceLogContext = (context) => {
|
|
753
|
+
export const shouldSkipTraceLogContext = (context) => {
|
|
751
754
|
return context?.[TRACE_SKIP_LOG_CONTEXT_KEY] === true;
|
|
752
755
|
};
|
|
753
756
|
const loggerSinks = [];
|
package/src/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @zintrust/core v0.7.
|
|
2
|
+
* @zintrust/core v0.7.7
|
|
3
3
|
*
|
|
4
4
|
* ZinTrust Framework - Production-Grade TypeScript Backend
|
|
5
5
|
* Built for performance, type safety, and exceptional developer experience
|
|
6
6
|
*
|
|
7
7
|
* Build Information:
|
|
8
|
-
* Built: 2026-04-
|
|
8
|
+
* Built: 2026-04-19T15:28:44.954Z
|
|
9
9
|
* Node: >=20.0.0
|
|
10
10
|
* License: MIT
|
|
11
11
|
*
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* Available at runtime for debugging and health checks
|
|
22
22
|
*/
|
|
23
23
|
export const ZINTRUST_VERSION = '0.1.41';
|
|
24
|
-
export const ZINTRUST_BUILD_DATE = '2026-04-
|
|
24
|
+
export const ZINTRUST_BUILD_DATE = '2026-04-19T15:28:44.919Z'; // Replaced during build
|
|
25
25
|
export { Application } from './boot/Application.js';
|
|
26
26
|
export { AwsSigV4 } from './common/index.js';
|
|
27
27
|
export { SignedRequest } from './security/SignedRequest.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProxyServerUtils.d.ts","sourceRoot":"","sources":["../../../src/proxy/ProxyServerUtils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProxyServerUtils.d.ts","sourceRoot":"","sources":["../../../src/proxy/ProxyServerUtils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAI7D,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC,CAAC;AAuCH,eAAO,MAAM,iBAAiB,GAC5B,WAAW,kBAAkB,EAC7B,QAAQ,MAAM,EACd,WAAW;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,KACjE,eAUF,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,WAAW,kBAAkB,EAC7B,QAAQ,MAAM,KACb;IACD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;CAOtB,CAAC;AAEL,eAAO,MAAM,sBAAsB,GACjC,KAAK,eAAe,EACpB,MAAM,MAAM,EACZ,QAAQ;IAAE,OAAO,EAAE,kBAAkB,CAAA;CAAE,EACvC,aAAa,MAAM,KAClB,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAoCtE,CAAC"}
|
|
@@ -1,7 +1,42 @@
|
|
|
1
1
|
import { Env } from '../config/env.js';
|
|
2
2
|
import { Logger } from '../config/logger.js';
|
|
3
|
+
import { isNonEmptyString } from '../helper/index.js';
|
|
3
4
|
import { resolveProxySigningConfig } from './ProxySigningConfigResolver.js';
|
|
4
5
|
import { extractSigningHeaders, verifyProxySignatureIfNeeded } from './ProxySigningRequest.js';
|
|
6
|
+
const PROXY_DEBUG_ENV_BY_SERVICE = Object.freeze({
|
|
7
|
+
MySQLProxyServer: 'MYSQL_PROXY_DEBUG',
|
|
8
|
+
PostgresProxyServer: 'POSTGRES_PROXY_DEBUG',
|
|
9
|
+
RedisProxyServer: 'REDIS_PROXY_DEBUG',
|
|
10
|
+
SqlServerProxyServer: 'SQLSERVER_PROXY_DEBUG',
|
|
11
|
+
});
|
|
12
|
+
const parseProxyDebugValue = (raw) => {
|
|
13
|
+
const normalized = raw.trim().toLowerCase();
|
|
14
|
+
if (normalized === 'true' || normalized === '1' || normalized === 'yes')
|
|
15
|
+
return true;
|
|
16
|
+
if (normalized === 'false' || normalized === '0' || normalized === 'no')
|
|
17
|
+
return false;
|
|
18
|
+
return undefined;
|
|
19
|
+
};
|
|
20
|
+
const resolveProxyDebugEnabled = (serviceName) => {
|
|
21
|
+
const serviceEnvKey = PROXY_DEBUG_ENV_BY_SERVICE[serviceName];
|
|
22
|
+
const serviceRaw = serviceEnvKey ? Env.get(serviceEnvKey, '') : '';
|
|
23
|
+
if (isNonEmptyString(serviceRaw)) {
|
|
24
|
+
const parsed = parseProxyDebugValue(serviceRaw);
|
|
25
|
+
if (parsed !== undefined)
|
|
26
|
+
return parsed;
|
|
27
|
+
}
|
|
28
|
+
const sharedRaw = Env.get('ZT_PROXY_DEBUG', '');
|
|
29
|
+
if (isNonEmptyString(sharedRaw)) {
|
|
30
|
+
const parsed = parseProxyDebugValue(sharedRaw);
|
|
31
|
+
if (parsed !== undefined)
|
|
32
|
+
return parsed;
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
};
|
|
36
|
+
const withTraceSkipProxyContext = (context) => ({
|
|
37
|
+
...context,
|
|
38
|
+
__zintrustSkipTraceLog: true,
|
|
39
|
+
});
|
|
5
40
|
export const resolveBaseConfig = (overrides, prefix, defaults) => {
|
|
6
41
|
const host = overrides.host ?? Env.get(`${prefix}_PROXY_HOST`, Env.HOST ?? defaults?.host ?? '127.0.0.1');
|
|
7
42
|
const port = overrides.port ?? Env.getInt(`${prefix}_PROXY_PORT`, Env.PORT ?? defaults?.port ?? 3000);
|
|
@@ -18,22 +53,24 @@ export const resolveBaseSigningConfig = (overrides, prefix) => resolveProxySigni
|
|
|
18
53
|
export const verifyRequestSignature = async (req, body, config, serviceName) => {
|
|
19
54
|
const headers = extractSigningHeaders(req);
|
|
20
55
|
const hasAnySigningHeader = Object.values(headers).some((value) => typeof value === 'string' && value.trim() !== '');
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
56
|
+
if (resolveProxyDebugEnabled(serviceName)) {
|
|
57
|
+
Logger.debug(`[${serviceName}] Verifying request signature`, {
|
|
58
|
+
...withTraceSkipProxyContext({
|
|
59
|
+
path: req.url ?? '',
|
|
60
|
+
method: req.method ?? 'POST',
|
|
61
|
+
requireSigning: config.signing.require,
|
|
62
|
+
hasAnySigningHeader,
|
|
63
|
+
configuredKeyId: config.signing.keyId,
|
|
64
|
+
hasConfiguredSecret: config.signing.secret.trim() !== '',
|
|
65
|
+
bodyBytes: body.length,
|
|
66
|
+
}),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
32
69
|
const verified = await verifyProxySignatureIfNeeded(req, body, config.signing);
|
|
33
70
|
if (!verified.ok) {
|
|
34
71
|
const error = verified.error ?? { status: 401, message: 'Unauthorized' };
|
|
35
72
|
Logger.warn(`[${serviceName}] Signature verification failed`, {
|
|
36
|
-
...
|
|
73
|
+
...withTraceSkipProxyContext({
|
|
37
74
|
path: req.url ?? '',
|
|
38
75
|
method: req.method ?? 'POST',
|
|
39
76
|
status: error.status,
|