@zintrust/core 0.4.77 → 0.4.79
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/cli/commands/ProxyScaffoldUtils.d.ts +2 -0
- package/src/cli/commands/ProxyScaffoldUtils.d.ts.map +1 -1
- package/src/cli/commands/ProxyScaffoldUtils.js +147 -4
- package/src/cli/commands/WranglerProxyCommandUtils.d.ts.map +1 -1
- package/src/cli/commands/WranglerProxyCommandUtils.js +14 -2
- package/src/config/workers.d.ts.map +1 -1
- package/src/config/workers.js +52 -12
- package/src/index.js +3 -3
- package/src/middleware/ErrorHandlerMiddleware.d.ts.map +1 -1
- package/src/middleware/ErrorHandlerMiddleware.js +13 -1
- package/src/orm/migrations/MigrationStore.d.ts.map +1 -1
- package/src/orm/migrations/MigrationStore.js +63 -32
- package/src/proxy/d1/ZintrustD1Proxy.d.ts.map +1 -1
- package/src/proxy/d1/ZintrustD1Proxy.js +16 -9
- package/src/runtime/plugins/trace-runtime.d.ts +6 -1
- package/src/runtime/plugins/trace-runtime.d.ts.map +1 -1
- package/src/runtime/plugins/trace-runtime.js +4 -4
package/package.json
CHANGED
|
@@ -15,11 +15,13 @@ type EnsureWranglerConfigOptions<TValues, TOptions> = {
|
|
|
15
15
|
type EnsureWranglerConfigResult<TValues> = {
|
|
16
16
|
createdFile: boolean;
|
|
17
17
|
insertedEnv: boolean;
|
|
18
|
+
content: string;
|
|
18
19
|
values: TValues;
|
|
19
20
|
};
|
|
20
21
|
export declare const trimNonEmptyOption: (value: string | undefined) => string | undefined;
|
|
21
22
|
export declare const resolveConfigPath: (raw: string | undefined, fallback?: string) => string;
|
|
22
23
|
export declare const findQuotedValue: (content: string, key: string) => string | undefined;
|
|
24
|
+
export declare const renderProxyWranglerDevConfig: (content: string, envName: string) => string | undefined;
|
|
23
25
|
export declare const injectEnvBlock: (content: string, envName: string, block: string) => string;
|
|
24
26
|
export declare const renderDefaultWranglerConfig: (envBlock: string, compatibilityDate: string) => string;
|
|
25
27
|
export declare const ensureProxyEntrypoint: (options: EnsureProxyEntrypointOptions) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProxyScaffoldUtils.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/ProxyScaffoldUtils.ts"],"names":[],"mappings":"AAKA,KAAK,4BAA4B,GAAG;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,KAAK,2BAA2B,CAAC,OAAO,EAAE,QAAQ,IAAI;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,QAAQ,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,QAAQ,KAAK,OAAO,CAAC;IAC3E,cAAc,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC;IAC5C,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,KAAK,0BAA0B,CAAC,OAAO,IAAI;IACzC,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SAIvE,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,KAAK,MAAM,GAAG,SAAS,EAAE,iBAA2B,KAAG,MAExF,CAAC;AAmBF,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,EAAE,KAAK,MAAM,KAAG,MAAM,GAAG,SAQvE,CAAC;
|
|
1
|
+
{"version":3,"file":"ProxyScaffoldUtils.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/ProxyScaffoldUtils.ts"],"names":[],"mappings":"AAKA,KAAK,4BAA4B,GAAG;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,KAAK,2BAA2B,CAAC,OAAO,EAAE,QAAQ,IAAI;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,QAAQ,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,QAAQ,KAAK,OAAO,CAAC;IAC3E,cAAc,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC;IAC5C,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,KAAK,0BAA0B,CAAC,OAAO,IAAI;IACzC,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SAIvE,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,KAAK,MAAM,GAAG,SAAS,EAAE,iBAA2B,KAAG,MAExF,CAAC;AAmBF,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,EAAE,KAAK,MAAM,KAAG,MAAM,GAAG,SAQvE,CAAC;AAwKF,eAAO,MAAM,4BAA4B,GACvC,SAAS,MAAM,EACf,SAAS,MAAM,KACd,MAAM,GAAG,SAgBX,CAAC;AAQF,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,EAAE,SAAS,MAAM,EAAE,OAAO,MAAM,KAAG,MAuBhF,CAAC;AAEF,eAAO,MAAM,2BAA2B,GACtC,UAAU,MAAM,EAChB,mBAAmB,MAAM,KACxB,MAaF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,SAAS,4BAA4B,KACpC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAmB3C,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,OAAO,EAAE,QAAQ,EACpD,SAAS,2BAA2B,CAAC,OAAO,EAAE,QAAQ,CAAC,KACtD,0BAA0B,CAAC,OAAO,CAqBpC,CAAC"}
|
|
@@ -47,6 +47,148 @@ const findEnvObjectStart = (content) => {
|
|
|
47
47
|
return -1;
|
|
48
48
|
return valueStart;
|
|
49
49
|
};
|
|
50
|
+
const createJsonScanState = () => ({
|
|
51
|
+
inString: false,
|
|
52
|
+
isEscaped: false,
|
|
53
|
+
inLineComment: false,
|
|
54
|
+
inBlockComment: false,
|
|
55
|
+
});
|
|
56
|
+
const advanceWithinLineComment = (state, current) => {
|
|
57
|
+
if (!state.inLineComment)
|
|
58
|
+
return 0;
|
|
59
|
+
if (current === '\n')
|
|
60
|
+
state.inLineComment = false;
|
|
61
|
+
return 1;
|
|
62
|
+
};
|
|
63
|
+
const advanceWithinBlockComment = (state, current, next) => {
|
|
64
|
+
if (!state.inBlockComment)
|
|
65
|
+
return 0;
|
|
66
|
+
if (current === '*' && next === '/') {
|
|
67
|
+
state.inBlockComment = false;
|
|
68
|
+
return 2;
|
|
69
|
+
}
|
|
70
|
+
return 1;
|
|
71
|
+
};
|
|
72
|
+
const advanceWithinString = (state, current) => {
|
|
73
|
+
if (!state.inString)
|
|
74
|
+
return 0;
|
|
75
|
+
if (state.isEscaped) {
|
|
76
|
+
state.isEscaped = false;
|
|
77
|
+
}
|
|
78
|
+
else if (current === '\\') {
|
|
79
|
+
state.isEscaped = true;
|
|
80
|
+
}
|
|
81
|
+
else if (current === '"') {
|
|
82
|
+
state.inString = false;
|
|
83
|
+
}
|
|
84
|
+
return 1;
|
|
85
|
+
};
|
|
86
|
+
const startJsonScanContext = (state, current, next) => {
|
|
87
|
+
if (current === '/' && next === '/') {
|
|
88
|
+
state.inLineComment = true;
|
|
89
|
+
return 2;
|
|
90
|
+
}
|
|
91
|
+
if (current === '/' && next === '*') {
|
|
92
|
+
state.inBlockComment = true;
|
|
93
|
+
return 2;
|
|
94
|
+
}
|
|
95
|
+
if (current === '"') {
|
|
96
|
+
state.inString = true;
|
|
97
|
+
return 1;
|
|
98
|
+
}
|
|
99
|
+
return 0;
|
|
100
|
+
};
|
|
101
|
+
const advanceJsonScanState = (state, current, next) => {
|
|
102
|
+
return (advanceWithinLineComment(state, current) ||
|
|
103
|
+
advanceWithinBlockComment(state, current, next) ||
|
|
104
|
+
advanceWithinString(state, current) ||
|
|
105
|
+
startJsonScanContext(state, current, next));
|
|
106
|
+
};
|
|
107
|
+
const rewriteRelativeWranglerPaths = (content) => {
|
|
108
|
+
return content.replaceAll('": "./', '": "../../');
|
|
109
|
+
};
|
|
110
|
+
const findQuotedKeyFrom = (content, key, startIndex) => {
|
|
111
|
+
let cursor = Math.max(0, startIndex);
|
|
112
|
+
const state = createJsonScanState();
|
|
113
|
+
const candidate = `"${key}"`;
|
|
114
|
+
while (cursor < content.length) {
|
|
115
|
+
const current = content[cursor];
|
|
116
|
+
const next = content[cursor + 1];
|
|
117
|
+
if (!state.inString && !state.inLineComment && !state.inBlockComment) {
|
|
118
|
+
if (content.startsWith(candidate, cursor))
|
|
119
|
+
return cursor;
|
|
120
|
+
}
|
|
121
|
+
const advanced = advanceJsonScanState(state, current, next);
|
|
122
|
+
cursor += advanced > 0 ? advanced : 1;
|
|
123
|
+
}
|
|
124
|
+
return -1;
|
|
125
|
+
};
|
|
126
|
+
const findJsonKeyValueStartFrom = (content, key, startIndex) => {
|
|
127
|
+
const keyPosition = findQuotedKeyFrom(content, key, startIndex);
|
|
128
|
+
if (keyPosition < 0)
|
|
129
|
+
return -1;
|
|
130
|
+
let cursor = keyPosition + key.length + 2;
|
|
131
|
+
while (isJsonWhitespace(content[cursor]))
|
|
132
|
+
cursor += 1;
|
|
133
|
+
if (content[cursor] !== ':')
|
|
134
|
+
return -1;
|
|
135
|
+
cursor += 1;
|
|
136
|
+
while (isJsonWhitespace(content[cursor]))
|
|
137
|
+
cursor += 1;
|
|
138
|
+
return cursor;
|
|
139
|
+
};
|
|
140
|
+
const findMatchingObjectBrace = (content, objectStart) => {
|
|
141
|
+
let depth = 0;
|
|
142
|
+
const state = createJsonScanState();
|
|
143
|
+
for (let index = objectStart; index < content.length; index += 1) {
|
|
144
|
+
const current = content[index];
|
|
145
|
+
const next = content[index + 1];
|
|
146
|
+
if (!state.inString && !state.inLineComment && !state.inBlockComment) {
|
|
147
|
+
if (current === '{') {
|
|
148
|
+
depth += 1;
|
|
149
|
+
}
|
|
150
|
+
else if (current === '}') {
|
|
151
|
+
depth -= 1;
|
|
152
|
+
if (depth === 0)
|
|
153
|
+
return index;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const advanced = advanceJsonScanState(state, current, next);
|
|
157
|
+
if (advanced > 1)
|
|
158
|
+
index += advanced - 1;
|
|
159
|
+
}
|
|
160
|
+
return -1;
|
|
161
|
+
};
|
|
162
|
+
const extractObjectBlock = (content, key, startIndex = 0) => {
|
|
163
|
+
const valueStart = findJsonKeyValueStartFrom(content, key, startIndex);
|
|
164
|
+
if (valueStart < 0 || content[valueStart] !== '{')
|
|
165
|
+
return undefined;
|
|
166
|
+
const valueEnd = findMatchingObjectBrace(content, valueStart);
|
|
167
|
+
if (valueEnd < 0)
|
|
168
|
+
return undefined;
|
|
169
|
+
return content.slice(valueStart, valueEnd + 1);
|
|
170
|
+
};
|
|
171
|
+
const indentBlock = (content, spaces) => {
|
|
172
|
+
const prefix = ' '.repeat(spaces);
|
|
173
|
+
return content
|
|
174
|
+
.split('\n')
|
|
175
|
+
.map((line) => (line.trim().length === 0 ? line : `${prefix}${line}`))
|
|
176
|
+
.join('\n');
|
|
177
|
+
};
|
|
178
|
+
export const renderProxyWranglerDevConfig = (content, envName) => {
|
|
179
|
+
const envObjectStart = findEnvObjectStart(content);
|
|
180
|
+
if (envObjectStart < 0)
|
|
181
|
+
return undefined;
|
|
182
|
+
const envBlock = extractObjectBlock(content, envName, envObjectStart);
|
|
183
|
+
if (envBlock === undefined)
|
|
184
|
+
return undefined;
|
|
185
|
+
const aliasBlock = extractObjectBlock(content, 'alias');
|
|
186
|
+
const envBody = envBlock.slice(1, -1).trim();
|
|
187
|
+
if (envBody.length === 0)
|
|
188
|
+
return undefined;
|
|
189
|
+
const aliasLine = aliasBlock === undefined ? [] : [` "alias": ${aliasBlock},`];
|
|
190
|
+
return rewriteRelativeWranglerPaths(['{', ...aliasLine, indentBlock(envBody, 2), '}', ''].join('\n'));
|
|
191
|
+
};
|
|
50
192
|
const isObjectEffectivelyEmpty = (content, objectStart) => {
|
|
51
193
|
let cursor = objectStart + 1;
|
|
52
194
|
while (isJsonWhitespace(content[cursor]))
|
|
@@ -105,15 +247,16 @@ export const ensureProxyEntrypoint = (options) => {
|
|
|
105
247
|
export const ensureWranglerConfig = (options) => {
|
|
106
248
|
if (!existsSync(options.configPath)) {
|
|
107
249
|
const values = options.resolveValues(undefined, options.options);
|
|
108
|
-
|
|
109
|
-
|
|
250
|
+
const content = renderDefaultWranglerConfig(options.renderEnvBlock(values), options.compatibilityDate);
|
|
251
|
+
writeFileSync(options.configPath, content, 'utf-8');
|
|
252
|
+
return { createdFile: true, insertedEnv: true, content, values };
|
|
110
253
|
}
|
|
111
254
|
const content = readFileSync(options.configPath, 'utf-8');
|
|
112
255
|
const values = options.resolveValues(content, options.options);
|
|
113
256
|
const next = injectEnvBlock(content, options.envName, options.renderEnvBlock(values));
|
|
114
257
|
if (next !== content) {
|
|
115
258
|
writeFileSync(options.configPath, next, 'utf-8');
|
|
116
|
-
return { createdFile: false, insertedEnv: true, values };
|
|
259
|
+
return { createdFile: false, insertedEnv: true, content: next, values };
|
|
117
260
|
}
|
|
118
|
-
return { createdFile: false, insertedEnv: false, values };
|
|
261
|
+
return { createdFile: false, insertedEnv: false, content, values };
|
|
119
262
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WranglerProxyCommandUtils.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/WranglerProxyCommandUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"WranglerProxyCommandUtils.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/WranglerProxyCommandUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAarE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,MAAM,2BAA2B,GAAG,cAAc,GAAG;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,KAAK,+BAA+B,CAAC,OAAO,EAAE,QAAQ,SAAS,2BAA2B,IAAI;IAC5F,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,QAAQ,KAAK,OAAO,CAAC;IAC3E,cAAc,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC;IAC5C,mBAAmB,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CACjD,CAAC;AAEF,eAAO,MAAM,2BAA2B,GAAI,SAAS,OAAO,EAAE,eAAe,MAAM,KAAG,IAIrF,CAAC;AAEF,eAAO,MAAM,0BAA0B,GAAI,OAAO,EAAE,QAAQ,SAAS,2BAA2B,EAC9F,OAAO,+BAA+B,CAAC,OAAO,EAAE,QAAQ,CAAC,KACxD,YAuEF,CAAC"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { BaseCommand } from '../BaseCommand.js';
|
|
2
2
|
import { maybeRunProxyWatchMode, parseIntOption } from '../commands/ProxyCommandUtils.js';
|
|
3
|
-
import { ensureProxyEntrypoint, ensureWranglerConfig, resolveConfigPath, } from '../commands/ProxyScaffoldUtils.js';
|
|
3
|
+
import { ensureProxyEntrypoint, ensureWranglerConfig, renderProxyWranglerDevConfig, resolveConfigPath, } from '../commands/ProxyScaffoldUtils.js';
|
|
4
4
|
import { SpawnUtil } from '../utils/spawn.js';
|
|
5
5
|
import { Logger } from '../../config/logger.js';
|
|
6
|
+
import { mkdirSync, writeFileSync } from '../../node-singletons/fs.js';
|
|
6
7
|
import { join } from '../../node-singletons/path.js';
|
|
7
8
|
export const addWranglerProxyBaseOptions = (command, defaultConfig) => {
|
|
8
9
|
command.option('-c, --config <path>', 'Wrangler config file', defaultConfig);
|
|
@@ -45,7 +46,18 @@ export const createWranglerProxyCommand = (input) => {
|
|
|
45
46
|
Logger.info(`Added env.${input.envName} to ${configPath}.`);
|
|
46
47
|
}
|
|
47
48
|
input.afterConfigResolved?.(result.values);
|
|
48
|
-
const
|
|
49
|
+
const proxyConfigContent = renderProxyWranglerDevConfig(result.content, input.envName);
|
|
50
|
+
const proxyConfigDir = join(cwd, '.wrangler', 'tmp');
|
|
51
|
+
const proxyConfigPath = join(proxyConfigDir, `zin.proxy.${input.envName}.jsonc`);
|
|
52
|
+
if (proxyConfigContent !== undefined) {
|
|
53
|
+
mkdirSync(proxyConfigDir, { recursive: true });
|
|
54
|
+
writeFileSync(proxyConfigPath, proxyConfigContent, 'utf-8');
|
|
55
|
+
}
|
|
56
|
+
const args = [
|
|
57
|
+
'dev',
|
|
58
|
+
'--config',
|
|
59
|
+
proxyConfigContent === undefined ? configPath : proxyConfigPath,
|
|
60
|
+
];
|
|
49
61
|
if (port !== undefined) {
|
|
50
62
|
args.push('--port', String(port));
|
|
51
63
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workers.d.ts","sourceRoot":"","sources":["../../../src/config/workers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,8BAA8B,CAAC;AAItC,OAAO,KAAK,EACV,WAAW,EAIX,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAItB,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"workers.d.ts","sourceRoot":"","sources":["../../../src/config/workers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,8BAA8B,CAAC;AAItC,OAAO,KAAK,EACV,WAAW,EAIX,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAItB,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAgXnC,eAAO,MAAM,qBAAqB,GAChC,QAAQ,WAAW,EACnB,mBAAc,EACd,UAAU,qBAAqB,KAC9B,OA6CF,CAAC;AAEF,eAAO,MAAM,wBAAwB,QAAa,OAAO,CAAC,IAAI,CAmB7D,CAAC;AAgFF,QAAA,MAAM,mBAAmB,QAAO,mBA2D/B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAqBnE,eAAO,MAAM,aAAa,EAAE,aAY1B,CAAC"}
|
package/src/config/workers.js
CHANGED
|
@@ -28,6 +28,56 @@ const unregisterRedisConnection = (client) => {
|
|
|
28
28
|
registry.cachedConnections.delete(registryKey);
|
|
29
29
|
}
|
|
30
30
|
};
|
|
31
|
+
const awaitRedisQuitWithin = async (client, timeoutMs) => {
|
|
32
|
+
if (typeof client.quit !== 'function')
|
|
33
|
+
return true;
|
|
34
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
35
|
+
await client.quit();
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
let timeoutId;
|
|
39
|
+
try {
|
|
40
|
+
await Promise.race([
|
|
41
|
+
client.quit(),
|
|
42
|
+
new Promise((_, reject) => {
|
|
43
|
+
timeoutId = globalThis.setTimeout(() => {
|
|
44
|
+
reject(ErrorFactory.createGeneralError('Redis graceful shutdown timed out', { timeoutMs }));
|
|
45
|
+
}, timeoutMs);
|
|
46
|
+
}),
|
|
47
|
+
]);
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
if (timeoutId !== undefined) {
|
|
55
|
+
globalThis.clearTimeout(timeoutId);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const forceDisconnectRedisClient = (client, error) => {
|
|
60
|
+
if (error !== undefined) {
|
|
61
|
+
Logger.warn('Tracked Redis graceful shutdown failed, forcing disconnect', error);
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
client.disconnect();
|
|
65
|
+
}
|
|
66
|
+
catch (disconnectError) {
|
|
67
|
+
Logger.error('Tracked Redis forced disconnect failed', disconnectError);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
const shutdownTrackedRedisConnection = async (client, timeoutMs) => {
|
|
71
|
+
try {
|
|
72
|
+
const quitCompleted = await awaitRedisQuitWithin(client, timeoutMs);
|
|
73
|
+
if (!quitCompleted) {
|
|
74
|
+
forceDisconnectRedisClient(client, ErrorFactory.createGeneralError('Redis graceful shutdown timed out', { timeoutMs }));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
forceDisconnectRedisClient(client, error);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
31
81
|
const hasReusableRedisStatus = (client) => {
|
|
32
82
|
return client.status !== 'end' && client.status !== 'close';
|
|
33
83
|
};
|
|
@@ -263,6 +313,7 @@ export const createRedisConnection = (config, maxRetries = 3, options) => {
|
|
|
263
313
|
export const shutdownRedisConnections = async () => {
|
|
264
314
|
const registry = getRedisConnectionRegistry();
|
|
265
315
|
const trackedConnections = Array.from(registry.activeConnections);
|
|
316
|
+
const perConnectionTimeoutMs = 750;
|
|
266
317
|
if (trackedConnections.length === 0)
|
|
267
318
|
return;
|
|
268
319
|
registry.activeConnections.clear();
|
|
@@ -271,18 +322,7 @@ export const shutdownRedisConnections = async () => {
|
|
|
271
322
|
count: trackedConnections.length,
|
|
272
323
|
});
|
|
273
324
|
await Promise.allSettled(trackedConnections.map(async (client) => {
|
|
274
|
-
|
|
275
|
-
await client.quit();
|
|
276
|
-
}
|
|
277
|
-
catch (error) {
|
|
278
|
-
Logger.warn('Tracked Redis graceful shutdown failed, forcing disconnect', error);
|
|
279
|
-
try {
|
|
280
|
-
client.disconnect();
|
|
281
|
-
}
|
|
282
|
-
catch (disconnectError) {
|
|
283
|
-
Logger.error('Tracked Redis forced disconnect failed', disconnectError);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
325
|
+
await shutdownTrackedRedisConnection(client, perConnectionTimeoutMs);
|
|
286
326
|
}));
|
|
287
327
|
};
|
|
288
328
|
const createIntervalConfig = () => Env.SSE_SNAPSHOT_INTERVAL;
|
package/src/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @zintrust/core v0.4.
|
|
2
|
+
* @zintrust/core v0.4.79
|
|
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-08T11:45:55.486Z
|
|
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-08T11:45:55.451Z'; // 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":"ErrorHandlerMiddleware.d.ts","sourceRoot":"","sources":["../../../src/middleware/ErrorHandlerMiddleware.ts"],"names":[],"mappings":"AAOA,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,wCAAwC,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAG9D,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,0BAA0B,CAAC;CACxC;
|
|
1
|
+
{"version":3,"file":"ErrorHandlerMiddleware.d.ts","sourceRoot":"","sources":["../../../src/middleware/ErrorHandlerMiddleware.ts"],"names":[],"mappings":"AAOA,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,wCAAwC,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAG9D,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,0BAA0B,CAAC;CACxC;AA6CD,eAAO,MAAM,sBAAsB;qBACjB,mBAAmB,GAAQ,UAAU;EA8CrD,CAAC;AAEH,eAAe,sBAAsB,CAAC"}
|
|
@@ -5,6 +5,18 @@ import { ErrorResponse } from '../http/ErrorResponse.js';
|
|
|
5
5
|
import { RequestContext } from '../http/RequestContext.js';
|
|
6
6
|
import { respondWithMiddlewareFailure, } from './MiddlewareFailureResponder.js';
|
|
7
7
|
import { captureTraceException } from '../runtime/plugins/trace-runtime.js';
|
|
8
|
+
const resolveTraceExceptionContext = (req) => {
|
|
9
|
+
const requestContext = RequestContext.get(req);
|
|
10
|
+
const context = req.context ?? {};
|
|
11
|
+
const batchId = requestContext?.traceId ??
|
|
12
|
+
(typeof context['traceId'] === 'string' ? context['traceId'] : undefined);
|
|
13
|
+
const path = requestContext?.path ?? (typeof context['path'] === 'string' ? context['path'] : undefined);
|
|
14
|
+
const userId = requestContext?.userId ??
|
|
15
|
+
(typeof context['userId'] === 'string' ? context['userId'] : undefined);
|
|
16
|
+
if (batchId === undefined && path === undefined && userId === undefined)
|
|
17
|
+
return undefined;
|
|
18
|
+
return { batchId, path, userId };
|
|
19
|
+
};
|
|
8
20
|
const isWritableEnded = (res) => {
|
|
9
21
|
if (typeof res.getRaw !== 'function')
|
|
10
22
|
return false;
|
|
@@ -30,7 +42,7 @@ export const ErrorHandlerMiddleware = Object.freeze({
|
|
|
30
42
|
await next();
|
|
31
43
|
}
|
|
32
44
|
catch (error) {
|
|
33
|
-
captureTraceException(error);
|
|
45
|
+
captureTraceException(error, resolveTraceExceptionContext(req));
|
|
34
46
|
Logger.error('Unhandled request error:', error);
|
|
35
47
|
const requestId = RequestContext.get(req)?.requestId ?? req.context['requestId'];
|
|
36
48
|
const includeStack = Env.NODE_ENV !== 'production' && !shouldHideStackFromResponse(error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MigrationStore.d.ts","sourceRoot":"","sources":["../../../../src/orm/migrations/MigrationStore.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI/C,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"MigrationStore.d.ts","sourceRoot":"","sources":["../../../../src/orm/migrations/MigrationStore.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI/C,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AA6dhG,eAAO,MAAM,cAAc;oBACH,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;8BAKzC,SAAS,UACN,cAAc,YACZ,MAAM,GACd,OAAO,CAAC,MAAM,CAAC;sBA4BZ,SAAS,SACN,cAAc,WACZ,MAAM,GACd,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;sBAmDlC,SAAS,UACL;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,cAAc,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAC9E,OAAO,CAAC,IAAI,CAAC;mBA2DV,SAAS,UACL;QACN,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,cAAc,CAAC;QACtB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,qBAAqB,CAAC;QAC9B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC3B,GACA,OAAO,CAAC,IAAI,CAAC;kCAmDV,SAAS,UACL;QAAE,KAAK,EAAE,cAAc,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GACnE,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;8BA6C5C,SAAS,UACL;QAAE,KAAK,EAAE,cAAc,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GACjD,OAAO,CAAC,MAAM,EAAE,CAAC;qBA0Bd,SAAS,UACL;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,cAAc,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAC/D,OAAO,CAAC,IAAI,CAAC;EAmBhB,CAAC"}
|
|
@@ -32,7 +32,9 @@ const queryExists = async (db, sql, parameters) => {
|
|
|
32
32
|
const schemaHasTable = async (db, tableName) => {
|
|
33
33
|
const driver = db.getType();
|
|
34
34
|
if (driver === 'sqlite' || driver === 'd1' || driver === 'd1-remote') {
|
|
35
|
-
return queryExists(db, "SELECT 1 FROM sqlite_master WHERE type='table' AND name=? LIMIT 1", [
|
|
35
|
+
return queryExists(db, "SELECT 1 FROM sqlite_master WHERE type='table' AND name=? LIMIT 1", [
|
|
36
|
+
tableName,
|
|
37
|
+
]);
|
|
36
38
|
}
|
|
37
39
|
if (driver === 'postgresql') {
|
|
38
40
|
return queryExists(db, "SELECT 1 FROM information_schema.tables WHERE table_schema='public' AND table_name=? LIMIT 1", [tableName]);
|
|
@@ -87,41 +89,70 @@ const ensureTrackingTable = async (db) => {
|
|
|
87
89
|
await ensure();
|
|
88
90
|
clearTableLayoutCache(db);
|
|
89
91
|
};
|
|
92
|
+
const probeTableLayout = async (db) => {
|
|
93
|
+
const [hasTable, hasName, hasMigration, hasScope, hasService, hasStatus, hasAppliedAt, hasCreatedAt,] = await Promise.all([
|
|
94
|
+
schemaHasTable(db, 'migrations'),
|
|
95
|
+
schemaHasColumn(db, 'migrations', 'name'),
|
|
96
|
+
schemaHasColumn(db, 'migrations', 'migration'),
|
|
97
|
+
schemaHasColumn(db, 'migrations', 'scope'),
|
|
98
|
+
schemaHasColumn(db, 'migrations', 'service'),
|
|
99
|
+
schemaHasColumn(db, 'migrations', 'status'),
|
|
100
|
+
schemaHasColumn(db, 'migrations', 'applied_at'),
|
|
101
|
+
schemaHasColumn(db, 'migrations', 'created_at'),
|
|
102
|
+
]);
|
|
103
|
+
return {
|
|
104
|
+
hasAppliedAt,
|
|
105
|
+
hasCreatedAt,
|
|
106
|
+
hasMigration,
|
|
107
|
+
hasName,
|
|
108
|
+
hasScope,
|
|
109
|
+
hasService,
|
|
110
|
+
hasStatus,
|
|
111
|
+
hasTable,
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
const ensureProbeTableExists = async (db, probe, allowEnsure) => {
|
|
115
|
+
if (probe.hasTable || !allowEnsure)
|
|
116
|
+
return null;
|
|
117
|
+
await ensureTrackingTable(db);
|
|
118
|
+
return resolveTableLayout(db, false);
|
|
119
|
+
};
|
|
120
|
+
const assertProbeHasIdentityColumns = (probe) => {
|
|
121
|
+
if (probe.hasName || probe.hasMigration)
|
|
122
|
+
return;
|
|
123
|
+
throw ErrorFactory.createCliError('The migrations table is missing both `name` and `migration` columns. Update the tracking table before running migrations.');
|
|
124
|
+
};
|
|
125
|
+
const toTableLayout = (probe) => {
|
|
126
|
+
return {
|
|
127
|
+
hasAppliedAt: probe.hasAppliedAt,
|
|
128
|
+
hasCreatedAt: probe.hasCreatedAt,
|
|
129
|
+
hasMigration: probe.hasMigration,
|
|
130
|
+
hasName: probe.hasName,
|
|
131
|
+
hasScope: probe.hasScope,
|
|
132
|
+
hasService: probe.hasService,
|
|
133
|
+
hasStatus: probe.hasStatus,
|
|
134
|
+
requiresCompatibilityMode: probe.hasMigration ||
|
|
135
|
+
!probe.hasName ||
|
|
136
|
+
!probe.hasScope ||
|
|
137
|
+
!probe.hasService ||
|
|
138
|
+
!probe.hasStatus,
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
const loadTableLayout = async (db, allowEnsure) => {
|
|
142
|
+
if (typeof db.query !== 'function')
|
|
143
|
+
return DEFAULT_LAYOUT;
|
|
144
|
+
const probe = await probeTableLayout(db);
|
|
145
|
+
const ensuredLayout = await ensureProbeTableExists(db, probe, allowEnsure);
|
|
146
|
+
if (ensuredLayout !== null)
|
|
147
|
+
return ensuredLayout;
|
|
148
|
+
assertProbeHasIdentityColumns(probe);
|
|
149
|
+
return toTableLayout(probe);
|
|
150
|
+
};
|
|
90
151
|
const resolveTableLayout = async (db, allowEnsure = true) => {
|
|
91
152
|
const cached = tableLayoutCache.get(db);
|
|
92
153
|
if (cached !== undefined)
|
|
93
154
|
return cached;
|
|
94
|
-
const layoutPromise = (
|
|
95
|
-
if (typeof db.query !== 'function')
|
|
96
|
-
return DEFAULT_LAYOUT;
|
|
97
|
-
const [hasTable, hasName, hasMigration, hasScope, hasService, hasStatus, hasAppliedAt, hasCreatedAt] = await Promise.all([
|
|
98
|
-
schemaHasTable(db, 'migrations'),
|
|
99
|
-
schemaHasColumn(db, 'migrations', 'name'),
|
|
100
|
-
schemaHasColumn(db, 'migrations', 'migration'),
|
|
101
|
-
schemaHasColumn(db, 'migrations', 'scope'),
|
|
102
|
-
schemaHasColumn(db, 'migrations', 'service'),
|
|
103
|
-
schemaHasColumn(db, 'migrations', 'status'),
|
|
104
|
-
schemaHasColumn(db, 'migrations', 'applied_at'),
|
|
105
|
-
schemaHasColumn(db, 'migrations', 'created_at'),
|
|
106
|
-
]);
|
|
107
|
-
if (!hasTable && allowEnsure) {
|
|
108
|
-
await ensureTrackingTable(db);
|
|
109
|
-
return resolveTableLayout(db, false);
|
|
110
|
-
}
|
|
111
|
-
if (!hasName && !hasMigration) {
|
|
112
|
-
throw ErrorFactory.createCliError('The migrations table is missing both `name` and `migration` columns. Update the tracking table before running migrations.');
|
|
113
|
-
}
|
|
114
|
-
return {
|
|
115
|
-
hasAppliedAt,
|
|
116
|
-
hasCreatedAt,
|
|
117
|
-
hasMigration,
|
|
118
|
-
hasName,
|
|
119
|
-
hasScope,
|
|
120
|
-
hasService,
|
|
121
|
-
hasStatus,
|
|
122
|
-
requiresCompatibilityMode: hasMigration || !hasName || !hasScope || !hasService || !hasStatus,
|
|
123
|
-
};
|
|
124
|
-
})();
|
|
155
|
+
const layoutPromise = loadTableLayout(db, allowEnsure);
|
|
125
156
|
tableLayoutCache.set(db, layoutPromise);
|
|
126
157
|
return layoutPromise.catch((error) => {
|
|
127
158
|
if (tableLayoutCache.get(db) === layoutPromise) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ZintrustD1Proxy.d.ts","sourceRoot":"","sources":["../../../../src/proxy/d1/ZintrustD1Proxy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ZintrustD1Proxy.d.ts","sourceRoot":"","sources":["../../../../src/proxy/d1/ZintrustD1Proxy.ts"],"names":[],"mappings":"AASA,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;AAEjD,KAAK,qBAAqB,GAAG;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE;QACH,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QACtC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QACrE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;QAChE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;KAChG,CAAC;IACF,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrF,CAAC;AAEF,KAAK,WAAW,CAAC,CAAC,IAAI;IACpB,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;CACf,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,IAAI,EAAE,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK,mBAAmB,CAAC;IACpD,GAAG,EAAE,CAAC,CAAC,GAAG,OAAO,OAAO,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,KAAK,EAAE,CAAC,CAAC,GAAG,OAAO,OAAO,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5C,GAAG,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;CACjC,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,mBAAmB,CAAC;CAC/C,CAAC;AAEF,KAAK,KAAK,GAAG;IACX,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAyRF,eAAO,MAAM,eAAe;;;mBAGL,OAAO,OAAO,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC;EAqB5D,CAAC;AAEH,eAAe,eAAe,CAAC"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { Logger } from '../../config/logger.js';
|
|
2
|
-
import { isArray, isObject, isString } from '../../helper/index.js';
|
|
3
1
|
import { getEnvInt, json, normalizeBindingName, readAndVerifyJson, toErrorResponse, } from '../CloudflareProxyShared.js';
|
|
4
2
|
import { RequestValidator } from '../RequestValidator.js';
|
|
5
3
|
const DEFAULT_SIGNING_WINDOW_MS = 60_000;
|
|
6
4
|
const DEFAULT_MAX_BODY_BYTES = 128 * 1024;
|
|
7
5
|
const DEFAULT_MAX_SQL_BYTES = 32 * 1024;
|
|
8
6
|
const DEFAULT_MAX_PARAMS = 256;
|
|
7
|
+
const isRecord = (value) => typeof value === 'object' && value !== null;
|
|
8
|
+
const isString = (value) => typeof value === 'string';
|
|
9
|
+
const isArray = (value) => Array.isArray(value);
|
|
9
10
|
const isDebugEnabled = (env) => {
|
|
10
11
|
const raw = env.ZT_PROXY_DEBUG;
|
|
11
12
|
if (!isString(raw))
|
|
@@ -28,10 +29,16 @@ const safeErrorMessage = (error) => {
|
|
|
28
29
|
const logProxyError = (env, context, error) => {
|
|
29
30
|
if (!isDebugEnabled(env))
|
|
30
31
|
return;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
try {
|
|
33
|
+
// eslint-disable-next-line no-console
|
|
34
|
+
console.error('[ZintrustD1Proxy] error', {
|
|
35
|
+
...context,
|
|
36
|
+
message: safeErrorMessage(error).slice(0, 800),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// ignore logging failures in Workers proxy mode
|
|
41
|
+
}
|
|
35
42
|
};
|
|
36
43
|
const resolveD1Binding = (env) => {
|
|
37
44
|
const candidates = ['DB', 'zintrust_db', normalizeBindingName(env.D1_BINDING)].filter((value, index, values) => isString(value) && value.trim() !== '' && values.indexOf(value) === index);
|
|
@@ -50,7 +57,7 @@ const loadStatements = (env) => {
|
|
|
50
57
|
return null;
|
|
51
58
|
try {
|
|
52
59
|
const parsed = JSON.parse(raw);
|
|
53
|
-
if (!
|
|
60
|
+
if (!isRecord(parsed))
|
|
54
61
|
return null;
|
|
55
62
|
return parsed;
|
|
56
63
|
}
|
|
@@ -80,7 +87,7 @@ const toD1ExceptionResponse = (error) => {
|
|
|
80
87
|
return toErrorResponse(500, 'D1_ERROR', message);
|
|
81
88
|
};
|
|
82
89
|
const parseSqlPayload = (payload) => {
|
|
83
|
-
if (!
|
|
90
|
+
if (!isRecord(payload)) {
|
|
84
91
|
return { ok: false, response: toErrorResponse(400, 'VALIDATION_ERROR', 'Invalid body') };
|
|
85
92
|
}
|
|
86
93
|
const sql = payload['sql'];
|
|
@@ -181,7 +188,7 @@ const handleExec = async (request, env) => {
|
|
|
181
188
|
}
|
|
182
189
|
};
|
|
183
190
|
const parseStatementPayload = (payload) => {
|
|
184
|
-
if (!
|
|
191
|
+
if (!isRecord(payload)) {
|
|
185
192
|
return { ok: false, response: toErrorResponse(400, 'VALIDATION_ERROR', 'Invalid body') };
|
|
186
193
|
}
|
|
187
194
|
const statementId = payload['statementId'];
|
|
@@ -18,7 +18,12 @@ export declare const registerTraceRoutes: (router: unknown, storage: unknown, op
|
|
|
18
18
|
basePath?: string;
|
|
19
19
|
middleware?: ReadonlyArray<string>;
|
|
20
20
|
}) => void;
|
|
21
|
-
export declare const captureTraceException: (error: unknown
|
|
21
|
+
export declare const captureTraceException: (error: unknown, context?: {
|
|
22
|
+
batchId?: string;
|
|
23
|
+
hostname?: string;
|
|
24
|
+
path?: string;
|
|
25
|
+
userId?: string;
|
|
26
|
+
}) => void;
|
|
22
27
|
export declare const ensureSystemTraceRegistered: () => Promise<void>;
|
|
23
28
|
export {};
|
|
24
29
|
//# sourceMappingURL=trace-runtime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trace-runtime.d.ts","sourceRoot":"","sources":["../../../../src/runtime/plugins/trace-runtime.ts"],"names":[],"mappings":"AAAA,KAAK,cAAc,GAAG;IACpB,KAAK,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACxE,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,cAAc,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC;CACtC,CAAC;
|
|
1
|
+
{"version":3,"file":"trace-runtime.d.ts","sourceRoot":"","sources":["../../../../src/runtime/plugins/trace-runtime.ts"],"names":[],"mappings":"AAAA,KAAK,cAAc,GAAG;IACpB,KAAK,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACxE,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,cAAc,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC;CACtC,CAAC;AAwEF,eAAO,MAAM,WAAW,QAAO,OAA0C,CAAC;AAE1E,eAAO,MAAM,WAAW,EAAE,cAIxB,CAAC;AAEH,eAAO,MAAM,YAAY,EAAE,eAIzB,CAAC;AAEH,eAAO,MAAM,sBAAsB,GACjC,QAAQ,OAAO,EACf,UAAU;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE,KAClE,IAEF,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,OAAO,EACf,SAAS,OAAO,EAChB,UAAU;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE,KAClE,IAEF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,OAAO,OAAO,EACd,UAAU;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,KAChF,IASF,CAAC;AAEF,eAAO,MAAM,2BAA2B,QAAa,OAAO,CAAC,IAAI,CAIhE,CAAC"}
|
|
@@ -6,7 +6,7 @@ const fallbackTraceStorage = Object.freeze({
|
|
|
6
6
|
});
|
|
7
7
|
const fallbackRegisterTraceDashboard = (_router, _options) => undefined;
|
|
8
8
|
const fallbackRegisterTraceRoutes = (_router, _storage, _options) => undefined;
|
|
9
|
-
const fallbackCaptureTraceException = (_error) => undefined;
|
|
9
|
+
const fallbackCaptureTraceException = (_error, _context) => undefined;
|
|
10
10
|
let systemTraceModule;
|
|
11
11
|
let didAttemptSystemTraceLoad = false;
|
|
12
12
|
let pendingSystemTraceLoad;
|
|
@@ -46,13 +46,13 @@ export const registerTraceDashboard = (router, options) => {
|
|
|
46
46
|
export const registerTraceRoutes = (router, storage, options) => {
|
|
47
47
|
(systemTraceModule?.registerTraceRoutes ?? fallbackRegisterTraceRoutes)(router, storage, options);
|
|
48
48
|
};
|
|
49
|
-
export const captureTraceException = (error) => {
|
|
49
|
+
export const captureTraceException = (error, context) => {
|
|
50
50
|
if (systemTraceModule?.captureTraceException !== undefined) {
|
|
51
|
-
systemTraceModule.captureTraceException(error);
|
|
51
|
+
systemTraceModule.captureTraceException(error, context);
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
54
|
void loadSystemTraceModule().then((module) => {
|
|
55
|
-
(module?.captureTraceException ?? fallbackCaptureTraceException)(error);
|
|
55
|
+
(module?.captureTraceException ?? fallbackCaptureTraceException)(error, context);
|
|
56
56
|
});
|
|
57
57
|
};
|
|
58
58
|
export const ensureSystemTraceRegistered = async () => {
|