@zintrust/core 2.7.1 → 2.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +15 -12
- package/src/cache/drivers/KVDriver.d.ts.map +1 -1
- package/src/cache/drivers/KVDriver.js +2 -3
- package/src/health/RuntimeHealthProbes.js +2 -2
- package/src/http/middleware/FileUploadMiddleware.d.ts.map +1 -1
- package/src/http/middleware/FileUploadMiddleware.js +23 -1
- package/src/index.js +3 -3
- package/src/orm/QueryBuilder.d.ts.map +1 -1
- package/src/orm/QueryBuilder.js +22 -3
- package/src/tools/broadcast/Broadcast.d.ts.map +1 -1
- package/src/tools/broadcast/Broadcast.js +55 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zintrust/core",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.3",
|
|
4
4
|
"description": "Production-grade TypeScript backend framework for JavaScript",
|
|
5
5
|
"homepage": "https://zintrust.com",
|
|
6
6
|
"repository": {
|
|
@@ -213,16 +213,16 @@
|
|
|
213
213
|
"./package.json": "./package.json"
|
|
214
214
|
},
|
|
215
215
|
"dependencies": {
|
|
216
|
-
"@cloudflare/containers": "^0.3.
|
|
216
|
+
"@cloudflare/containers": "^0.3.7",
|
|
217
217
|
"bcryptjs": "^3.0.3",
|
|
218
|
-
"bullmq": "^5.
|
|
218
|
+
"bullmq": "^5.79.0",
|
|
219
219
|
"chalk": "^5.6.2",
|
|
220
220
|
"commander": "^15.0.0",
|
|
221
221
|
"inquirer": "^14.0.1",
|
|
222
|
-
"ioredis": "^5.11.
|
|
222
|
+
"ioredis": "^5.11.1",
|
|
223
223
|
"jsonwebtoken": "^9.0.3",
|
|
224
|
-
"mysql2": "^3.22.
|
|
225
|
-
"pg": "^8.
|
|
224
|
+
"mysql2": "^3.22.5",
|
|
225
|
+
"pg": "^8.22.0",
|
|
226
226
|
"redis": "^6.0.0",
|
|
227
227
|
"tsx": "^4.22.4"
|
|
228
228
|
},
|
|
@@ -234,18 +234,21 @@
|
|
|
234
234
|
"node-forge": "^1.4.0",
|
|
235
235
|
"fast-uri": "3.1.2",
|
|
236
236
|
"fast-xml-parser": "5.8.0",
|
|
237
|
-
"
|
|
237
|
+
"@babel/core": "^7.29.7",
|
|
238
|
+
"protobufjs": "7.6.4",
|
|
238
239
|
"picomatch": "^4.0.4",
|
|
239
240
|
"cross-spawn": "^7.0.5",
|
|
240
241
|
"glob": "^11.1.0",
|
|
241
242
|
"minimatch": "^10.2.2",
|
|
242
243
|
"rollup": "^4.59.0",
|
|
243
|
-
"vite": "^8.0.
|
|
244
|
+
"vite": "^8.0.16",
|
|
244
245
|
"flatted": "^3.4.2",
|
|
245
246
|
"uuid": "14.0.0",
|
|
246
|
-
"ioredis": "^5.11.
|
|
247
|
+
"ioredis": "^5.11.1",
|
|
247
248
|
"axios": "^1.16.1",
|
|
248
|
-
"
|
|
249
|
+
"form-data": "^4.0.6",
|
|
250
|
+
"js-yaml": "^4.2.0",
|
|
251
|
+
"tmp": "^0.2.7",
|
|
249
252
|
"sonarqube-scanner": {
|
|
250
253
|
"axios": "^1.16.1"
|
|
251
254
|
},
|
|
@@ -256,7 +259,7 @@
|
|
|
256
259
|
"undici": "^6.24.0"
|
|
257
260
|
},
|
|
258
261
|
"miniflare": {
|
|
259
|
-
"undici": "^7.
|
|
262
|
+
"undici": "^7.28.0"
|
|
260
263
|
},
|
|
261
264
|
"http-proxy-agent": "7.0.2",
|
|
262
265
|
"retry-request": "8.0.2",
|
|
@@ -265,7 +268,7 @@
|
|
|
265
268
|
"braces": "^3.0.3",
|
|
266
269
|
"lodash": "^4.17.21",
|
|
267
270
|
"semver": "^7.6.3",
|
|
268
|
-
"ws": "^8.
|
|
271
|
+
"ws": "^8.21.0",
|
|
269
272
|
"micromatch": "^4.0.8",
|
|
270
273
|
"brace-expansion": "^5.0.6",
|
|
271
274
|
"esbuild": "0.28.1",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KVDriver.d.ts","sourceRoot":"","sources":["../../../../src/cache/drivers/KVDriver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"KVDriver.d.ts","sourceRoot":"","sources":["../../../../src/cache/drivers/KVDriver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AA0DtD;;GAEG;AACH,eAAO,MAAM,QAAQ;kBArDF,WAAW;EAuD5B,CAAC"}
|
|
@@ -9,8 +9,7 @@ import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
|
9
9
|
* Create a new KV driver instance
|
|
10
10
|
*/
|
|
11
11
|
const create = () => {
|
|
12
|
-
|
|
13
|
-
const kv = Cloudflare.getKVBinding('CACHE');
|
|
12
|
+
const kv = Cloudflare.getKVBinding();
|
|
14
13
|
return {
|
|
15
14
|
async get(key) {
|
|
16
15
|
if (kv === null)
|
|
@@ -20,7 +19,7 @@ const create = () => {
|
|
|
20
19
|
},
|
|
21
20
|
async set(key, value, ttl) {
|
|
22
21
|
if (kv === null) {
|
|
23
|
-
Logger.warn('KV binding
|
|
22
|
+
Logger.warn('Configured KV binding not found. Cache set ignored.');
|
|
24
23
|
return;
|
|
25
24
|
}
|
|
26
25
|
const options = {};
|
|
@@ -40,9 +40,9 @@ const pingKvCache = async (timeoutMs = 2000) => {
|
|
|
40
40
|
if (driver !== 'kv')
|
|
41
41
|
return null;
|
|
42
42
|
const start = Date.now();
|
|
43
|
-
const kv = Cloudflare.getKVBinding(
|
|
43
|
+
const kv = Cloudflare.getKVBinding();
|
|
44
44
|
if (kv === null) {
|
|
45
|
-
throw ErrorFactory.createConfigError('KV binding
|
|
45
|
+
throw ErrorFactory.createConfigError('Configured KV binding not found');
|
|
46
46
|
}
|
|
47
47
|
const key = `__runtime_health__:kv:${Date.now()}`;
|
|
48
48
|
await withTimeout('runtime.cache.kv.ping', timeoutMs, async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileUploadMiddleware.d.ts","sourceRoot":"","sources":["../../../../src/http/middleware/FileUploadMiddleware.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"FileUploadMiddleware.d.ts","sourceRoot":"","sources":["../../../../src/http/middleware/FileUploadMiddleware.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAqJ9D;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAsDlC,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|
|
@@ -49,7 +49,29 @@ const isPipeable = (req) => {
|
|
|
49
49
|
* e.g. `doc[reg_cer]` -> `doc.reg_cer`, `doc[reg_cer][file]` -> `doc.reg_cer.file`.
|
|
50
50
|
* Empty brackets (`files[]`) collapse to the base name (`files`).
|
|
51
51
|
*/
|
|
52
|
-
const toDottedName = (name) =>
|
|
52
|
+
const toDottedName = (name) => {
|
|
53
|
+
let result = '';
|
|
54
|
+
let cursor = 0;
|
|
55
|
+
while (cursor < name.length) {
|
|
56
|
+
const openBracket = name.indexOf('[', cursor);
|
|
57
|
+
if (openBracket === -1) {
|
|
58
|
+
result += name.slice(cursor);
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
result += name.slice(cursor, openBracket);
|
|
62
|
+
const closeBracket = name.indexOf(']', openBracket + 1);
|
|
63
|
+
if (closeBracket === -1) {
|
|
64
|
+
result += name.slice(openBracket);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
const inner = name.slice(openBracket + 1, closeBracket);
|
|
68
|
+
if (inner !== '') {
|
|
69
|
+
result += `.${inner}`;
|
|
70
|
+
}
|
|
71
|
+
cursor = closeBracket + 1;
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
};
|
|
53
75
|
/**
|
|
54
76
|
* Add dotted-notation aliases for any bracket-notation keys, without removing
|
|
55
77
|
* the original field names. Existing keys are never overwritten.
|
package/src/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @zintrust/core v2.7.
|
|
2
|
+
* @zintrust/core v2.7.3
|
|
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-06-
|
|
8
|
+
* Built: 2026-06-20T09:43:35.633Z
|
|
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-06-
|
|
24
|
+
export const ZINTRUST_BUILD_DATE = '2026-06-20T09:43:35.558Z'; // 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":"QueryBuilder.d.ts","sourceRoot":"","sources":["../../../src/orm/QueryBuilder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGtE,OAAO,KAAK,EAAE,SAAS,EAAY,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAGzC,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,aAAa,CAAC,EAAE,qBAAqB,CAAC;CACvC;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAUD;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;CAC7C;AAED,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;AAE5D,MAAM,WAAW,mBAAmB;IAClC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,aAAa,KAAK,aAAa,CAAC;AAC5E,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAEvE,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC;IACvD,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;IACnD,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,aAAa,CAAC;IAClG,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,aAAa,CAAC;IAC3E,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,aAAa,CAAC;IAC1E,UAAU,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,GAAG,aAAa,CAAC;IACzE,YAAY,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,GAAG,aAAa,CAAC;IAC3E,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,aAAa,CAAC;IAChG,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,aAAa,CAAC;IAClG,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC;IACzC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC;IAC1D,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC;IAC7D,WAAW,IAAI,aAAa,CAAC;IAC7B,WAAW,IAAI,aAAa,CAAC;IAC7B,cAAc,IAAI,aAAa,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,aAAa,CAAC;IAC/C,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,aAAa,CAAC;IACnD,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,aAAa,CAAC;IACnE,aAAa,IAAI,aAAa,CAAC;IAC/B,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC;IACpC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC;IACrC,eAAe,IAAI,WAAW,EAAE,CAAC;IACjC,gBAAgB,IAAI,MAAM,EAAE,CAAC;IAC7B,QAAQ,IAAI,MAAM,CAAC;IACnB,QAAQ,IAAI,MAAM,GAAG,SAAS,CAAC;IAC/B,SAAS,IAAI,MAAM,GAAG,SAAS,CAAC;IAChC,UAAU,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,KAAK,GAAG,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACxE,QAAQ,IAAI,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,eAAe,IAAI,OAAO,CAAC;IAC3B,KAAK,IAAI,MAAM,CAAC;IAChB,aAAa,IAAI,OAAO,EAAE,CAAC;IAC3B,KAAK,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC9B,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC7C,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IACvB,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IACvB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAE/F,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,oBAAoB,GAAG,aAAa,CAAC;IAC7D,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAAC;IAC3C,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1F,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7D,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAChG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;
|
|
1
|
+
{"version":3,"file":"QueryBuilder.d.ts","sourceRoot":"","sources":["../../../src/orm/QueryBuilder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGtE,OAAO,KAAK,EAAE,SAAS,EAAY,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAGzC,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,aAAa,CAAC,EAAE,qBAAqB,CAAC;CACvC;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAUD;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;CAC7C;AAED,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;AAE5D,MAAM,WAAW,mBAAmB;IAClC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,aAAa,KAAK,aAAa,CAAC;AAC5E,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAEvE,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC;IACvD,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC;IACnD,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,aAAa,CAAC;IAClG,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,aAAa,CAAC;IAC3E,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,aAAa,CAAC;IAC1E,UAAU,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,GAAG,aAAa,CAAC;IACzE,YAAY,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,GAAG,aAAa,CAAC;IAC3E,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,aAAa,CAAC;IAChG,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,aAAa,CAAC;IAClG,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC;IACzC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC;IAC1D,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC;IAC7D,WAAW,IAAI,aAAa,CAAC;IAC7B,WAAW,IAAI,aAAa,CAAC;IAC7B,cAAc,IAAI,aAAa,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,aAAa,CAAC;IAC/C,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,aAAa,CAAC;IACnD,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,aAAa,CAAC;IACnE,aAAa,IAAI,aAAa,CAAC;IAC/B,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC;IACpC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC;IACrC,eAAe,IAAI,WAAW,EAAE,CAAC;IACjC,gBAAgB,IAAI,MAAM,EAAE,CAAC;IAC7B,QAAQ,IAAI,MAAM,CAAC;IACnB,QAAQ,IAAI,MAAM,GAAG,SAAS,CAAC;IAC/B,SAAS,IAAI,MAAM,GAAG,SAAS,CAAC;IAChC,UAAU,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,KAAK,GAAG,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACxE,QAAQ,IAAI,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,eAAe,IAAI,OAAO,CAAC;IAC3B,KAAK,IAAI,MAAM,CAAC;IAChB,aAAa,IAAI,OAAO,EAAE,CAAC;IAC3B,KAAK,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC9B,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC7C,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IACvB,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IACvB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAE/F,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,oBAAoB,GAAG,aAAa,CAAC;IAC7D,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAAC;IAC3C,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1F,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7D,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAChG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAqvDD;;;;;GAKG;AACH,eAAO,MAAM,YAAY;IACvB;;OAEG;sBAEU,MAAM,GAAG,SAAS,OACxB,SAAS,YACL,mBAAmB,GAC3B,aAAa;IA+BhB;;;;;OAKG;aACY,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;EAIxC,CAAC"}
|
package/src/orm/QueryBuilder.js
CHANGED
|
@@ -382,14 +382,30 @@ const buildLimitOffsetClause = (limit, offset) => {
|
|
|
382
382
|
}
|
|
383
383
|
return sql;
|
|
384
384
|
};
|
|
385
|
+
// Matches `left OP right` where both sides are identifier paths (e.g.
|
|
386
|
+
// `users.id = profiles.user_id`). Operator alternation lists the two-char
|
|
387
|
+
// operators before their single-char prefixes so `<=`/`>=`/`<>` win the match.
|
|
388
|
+
const JOIN_CONDITION = /^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\s*(=|!=|<>|<=|>=|<|>)\s*([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)$/;
|
|
389
|
+
const buildJoinClause = (joins, dialect) => joins
|
|
390
|
+
.map(({ table, on, type }) => {
|
|
391
|
+
assertSafeIdentifierPath(table, 'join table');
|
|
392
|
+
const match = JOIN_CONDITION.exec(on.trim());
|
|
393
|
+
if (!match) {
|
|
394
|
+
throw ErrorFactory.createDatabaseError('Unsafe SQL join condition');
|
|
395
|
+
}
|
|
396
|
+
const [, left, op, right] = match;
|
|
397
|
+
return ` ${type} JOIN ${escapeIdentifier(table, dialect)} ON ${escapeIdentifier(left, dialect)} ${op} ${escapeIdentifier(right, dialect)}`;
|
|
398
|
+
})
|
|
399
|
+
.join('');
|
|
385
400
|
const buildSelectQuery = (state) => {
|
|
386
401
|
if (state.tableName.length > 0) {
|
|
387
402
|
assertSafeIdentifierPath(state.tableName, 'table name');
|
|
388
403
|
}
|
|
389
404
|
const columns = buildSelectClause(state.selectColumns, state.dialect);
|
|
390
405
|
const fromClause = state.tableName.length > 0 ? ` FROM ${escapeIdentifier(state.tableName, state.dialect)}` : '';
|
|
406
|
+
const joinClause = buildJoinClause(state.joins, state.dialect);
|
|
391
407
|
const where = compileWhere(getEffectiveWhereConditions(state), state.dialect);
|
|
392
|
-
const sql = `SELECT ${columns}${fromClause}${where.sql}${buildOrderByClause(state.orderByClauses, state.randomOrder, state.dialect)}${buildLimitOffsetClause(state.limitValue, state.offsetValue)}`;
|
|
408
|
+
const sql = `SELECT ${columns}${fromClause}${joinClause}${where.sql}${buildOrderByClause(state.orderByClauses, state.randomOrder, state.dialect)}${buildLimitOffsetClause(state.limitValue, state.offsetValue)}`;
|
|
393
409
|
return { sql, parameters: where.parameters };
|
|
394
410
|
};
|
|
395
411
|
const buildCountQuery = (state) => {
|
|
@@ -706,10 +722,13 @@ function attachSoftDeleteMethods(builder, state) {
|
|
|
706
722
|
}
|
|
707
723
|
function attachJoinOrderPagingMethods(builder, state) {
|
|
708
724
|
builder.join = (tableJoin, on) => {
|
|
709
|
-
state.joins.push({ table: tableJoin, on });
|
|
725
|
+
state.joins.push({ table: tableJoin, on, type: 'INNER' });
|
|
726
|
+
return builder;
|
|
727
|
+
};
|
|
728
|
+
builder.leftJoin = (tableJoin, on) => {
|
|
729
|
+
state.joins.push({ table: tableJoin, on, type: 'LEFT' });
|
|
710
730
|
return builder;
|
|
711
731
|
};
|
|
712
|
-
builder.leftJoin = (tableJoin, on) => builder.join(tableJoin, on);
|
|
713
732
|
builder.orderBy = (column, direction = 'ASC') => {
|
|
714
733
|
applyOrderByClause(state, column, direction);
|
|
715
734
|
return builder;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Broadcast.d.ts","sourceRoot":"","sources":["../../../../src/tools/broadcast/Broadcast.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Broadcast.d.ts","sourceRoot":"","sources":["../../../../src/tools/broadcast/Broadcast.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,KAAK,WAAW,GAAG,QAAQ,CAAC;IAC1B,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1E,OAAO,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;CAC5E,CAAC,CAAC;AAEH,KAAK,qBAAqB,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,YAAY,CAAC;AAC9E,KAAK,qBAAqB,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAC1D,KAAK,kBAAkB,GAAG,eAAe,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAShE,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,KAAK,CAAC,EAAE,qBAAqB,CAAC;IAC9B,YAAY,CAAC,EAAE,qBAAqB,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC,CAAC;AA0BH,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C,EAAE,EAAE,IAAI,CAAC;IACT,SAAS,EAAE,kBAAkB,CAAC;IAC9B,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,0BAA0B,CAAC,QAAQ,CAAC,CAAC;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACpD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;CAC9B,CAAC,CAAC;AAs3BH,eAAO,MAAM,SAAS;mBACC,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC;kBAIxD,MAAM,SAAS,MAAM,QAAQ,OAAO;0BAU5B,MAAM,SAAS,MAAM,QAAQ,OAAO;wBAKvD,qBAAqB,YACnB;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;4BAO1C,MAAM,SACR,MAAM,QACP,OAAO,YACJ;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;qBAKpC,MAAM;8BAES,qBAAqB;kCAEjB,MAAM,SAAS,MAAM,QAAQ,OAAO;;uBAKrD,MAAM,GAAG,WAAW;EAmBvC,CAAC;AAEH,eAAe,SAAS,CAAC"}
|
|
@@ -3,6 +3,7 @@ import { InMemoryDriver } from './drivers/InMemory.js';
|
|
|
3
3
|
import { PusherDriver } from './drivers/Pusher.js';
|
|
4
4
|
import { RedisDriver } from './drivers/Redis.js';
|
|
5
5
|
import { RedisHttpsDriver } from './drivers/RedisHttps.js';
|
|
6
|
+
import { delay } from '../../common/index.js';
|
|
6
7
|
import broadcastConfig from '../../config/broadcast.js';
|
|
7
8
|
import { Env } from '../../config/env.js';
|
|
8
9
|
import { Logger } from '../../config/logger.js';
|
|
@@ -15,6 +16,25 @@ const BROADCAST_CHANNEL_SCOPES = new Set([
|
|
|
15
16
|
]);
|
|
16
17
|
const INTERNAL_SOCKET_SECRET_HEADER = 'x-zintrust-socket-secret';
|
|
17
18
|
const DEFAULT_BROADCAST_EVENTS_PATH_TEMPLATE = '/apps/{appId}/events';
|
|
19
|
+
// A POST that returns one of these never completed at the application origin, so
|
|
20
|
+
// re-sending it cannot duplicate a delivered event. 520-524 are the edge->origin
|
|
21
|
+
// (e.g. Cloudflare) statuses: a 522 means the edge could not connect to the origin,
|
|
22
|
+
// not that the broadcast was processed. Genuine application responses (2xx and 4xx
|
|
23
|
+
// such as 401/403/422) reached the origin and are never retried.
|
|
24
|
+
const TRANSIENT_PUBLISH_STATUSES = new Set([
|
|
25
|
+
408, 425, 429, 500, 502, 503, 504, 520, 521, 522, 523, 524,
|
|
26
|
+
]);
|
|
27
|
+
const resolveInternalPublishRetryConfig = () => ({
|
|
28
|
+
maxAttempts: Math.max(1, Env.getInt('BROADCAST_INTERNAL_PUBLISH_RETRIES', 3)),
|
|
29
|
+
baseDelayMs: Math.max(0, Env.getInt('BROADCAST_INTERNAL_PUBLISH_RETRY_BASE_MS', 200)),
|
|
30
|
+
});
|
|
31
|
+
// exponential backoff + full jitter
|
|
32
|
+
const computeRetryDelayMs = (baseDelayMs, attempt) => {
|
|
33
|
+
const exponential = baseDelayMs * Math.pow(2, attempt - 1);
|
|
34
|
+
const num = Math.random(); // NOSONAR
|
|
35
|
+
const jitter = baseDelayMs === 0 ? 0 : Math.floor(num * baseDelayMs);
|
|
36
|
+
return exponential + jitter;
|
|
37
|
+
};
|
|
18
38
|
const pickFirstNonEmpty = (...values) => {
|
|
19
39
|
for (const value of values) {
|
|
20
40
|
if (value.trim() !== '') {
|
|
@@ -224,7 +244,7 @@ const logTransportFallback = (transport, details) => {
|
|
|
224
244
|
...details,
|
|
225
245
|
});
|
|
226
246
|
};
|
|
227
|
-
const
|
|
247
|
+
const attemptInternalPublishEndpoint = async (endpoint, secret, payload) => {
|
|
228
248
|
try {
|
|
229
249
|
const response = await tracedFetch(endpoint, {
|
|
230
250
|
method: 'POST',
|
|
@@ -251,7 +271,12 @@ const requestInternalPublishEndpoint = async (endpoint, secret, payload) => {
|
|
|
251
271
|
status: response.status,
|
|
252
272
|
body: responseBody,
|
|
253
273
|
});
|
|
254
|
-
return {
|
|
274
|
+
return {
|
|
275
|
+
result: null,
|
|
276
|
+
error,
|
|
277
|
+
status: response.status,
|
|
278
|
+
transient: TRANSIENT_PUBLISH_STATUSES.has(response.status),
|
|
279
|
+
};
|
|
255
280
|
}
|
|
256
281
|
const resolvedChannels = isObject(responseBody) && isArray(responseBody['channels'])
|
|
257
282
|
? responseBody['channels'].filter(isNonEmptyString).map((channel) => channel.trim())
|
|
@@ -276,8 +301,34 @@ const requestInternalPublishEndpoint = async (endpoint, secret, payload) => {
|
|
|
276
301
|
endpoint,
|
|
277
302
|
error: describeError(error),
|
|
278
303
|
});
|
|
279
|
-
|
|
280
|
-
|
|
304
|
+
// A thrown error means the POST never completed at the application origin, so
|
|
305
|
+
// it is safe to retry.
|
|
306
|
+
return { result: null, error, transient: true };
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
const requestInternalPublishEndpoint = async (endpoint, secret, payload, attempt = 1, retryConfig) => {
|
|
310
|
+
const { maxAttempts, baseDelayMs } = retryConfig ?? resolveInternalPublishRetryConfig();
|
|
311
|
+
const result = await attemptInternalPublishEndpoint(endpoint, secret, payload);
|
|
312
|
+
if (result.result !== null) {
|
|
313
|
+
return result;
|
|
314
|
+
}
|
|
315
|
+
// Non-transient failures (application 4xx, etc.) reached the origin; do not retry.
|
|
316
|
+
if (result.transient !== true || attempt >= maxAttempts) {
|
|
317
|
+
return result;
|
|
318
|
+
}
|
|
319
|
+
const delayMs = computeRetryDelayMs(baseDelayMs, attempt);
|
|
320
|
+
Logger.warn('Broadcast internal publish retrying transient failure.', {
|
|
321
|
+
endpoint,
|
|
322
|
+
attempt,
|
|
323
|
+
maxAttempts,
|
|
324
|
+
delayMs,
|
|
325
|
+
status: result.status,
|
|
326
|
+
});
|
|
327
|
+
await delay(delayMs);
|
|
328
|
+
return requestInternalPublishEndpoint(endpoint, secret, payload, attempt + 1, {
|
|
329
|
+
maxAttempts,
|
|
330
|
+
baseDelayMs,
|
|
331
|
+
});
|
|
281
332
|
};
|
|
282
333
|
const tryInternalPublishEndpoints = async (endpoints, secret, payload, index = 0, lastError) => {
|
|
283
334
|
const endpoint = endpoints[index];
|