@zintrust/core 0.4.63 → 0.4.65
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/DebuggerCommands.js +1 -1
- package/src/cli/commands/MigrateCommand.js +1 -1
- package/src/debugger/SystemDebuggerBridge.js +1 -1
- package/src/functions/cloudflare.d.ts +1 -1
- package/src/functions/cloudflare.js +1 -1
- package/src/index.js +3 -3
- package/src/runtime/PluginAutoImports.d.ts.map +1 -1
- package/src/runtime/PluginAutoImports.js +28 -5
- package/src/runtime/WorkersModule.d.ts +2 -2
- package/src/runtime/plugins/system-debugger-runtime.js +1 -1
- package/src/tools/broadcast/Broadcast.d.ts +7 -1
- package/src/tools/broadcast/Broadcast.d.ts.map +1 -1
- package/src/tools/broadcast/Broadcast.js +300 -25
- package/src/zintrust.plugins.d.ts +3 -7
- package/src/zintrust.plugins.d.ts.map +1 -1
- package/src/zintrust.plugins.js +3 -9
- package/src/zintrust.plugins.wg.d.ts +0 -1
- package/src/zintrust.plugins.wg.d.ts.map +1 -1
- package/src/zintrust.plugins.wg.js +0 -3
- package/src/zintrust.comon.d.ts +0 -11
- package/src/zintrust.comon.d.ts.map +0 -1
- package/src/zintrust.comon.js +0 -17
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@ import { Database } from '../../orm/Database.js';
|
|
|
16
16
|
import { DatabaseAdapterRegistry } from '../../orm/DatabaseAdapterRegistry.js';
|
|
17
17
|
const loadDebuggerModule = async () => {
|
|
18
18
|
try {
|
|
19
|
-
return (await import('
|
|
19
|
+
return (await import('@zintrust/system-debugger'));
|
|
20
20
|
}
|
|
21
21
|
catch (error) {
|
|
22
22
|
Logger.error('Failed to load optional package "@zintrust/system-debugger"', error);
|
|
@@ -215,7 +215,7 @@ const warnIfAdapterMissing = (cmd, conn) => {
|
|
|
215
215
|
if (conn.driver === 'mysql' && DatabaseAdapterRegistry.get('mysql') === undefined) {
|
|
216
216
|
cmd.warn('MySQL adapter is not installed/registered; migrations may not hit a real MySQL DB.');
|
|
217
217
|
cmd.warn('Install via `zin plugin install adapter:mysql` (or `zin add db:mysql`).');
|
|
218
|
-
cmd.debug('[debug] Expected a side-effect import in src/zintrust.plugins.ts like: import "
|
|
218
|
+
cmd.debug('[debug] Expected a side-effect import in src/zintrust.plugins.ts like: import "@zintrust/db-mysql/register";');
|
|
219
219
|
}
|
|
220
220
|
if (conn.driver === 'postgresql' && DatabaseAdapterRegistry.get('postgresql') === undefined) {
|
|
221
221
|
cmd.warn('PostgreSQL adapter is not installed/registered; migrations may not hit a real PostgreSQL DB.');
|
|
@@ -2,5 +2,5 @@ declare const _default: {
|
|
|
2
2
|
fetch(request: Request, _env: unknown, _ctx: unknown): Promise<Response>;
|
|
3
3
|
};
|
|
4
4
|
export default _default;
|
|
5
|
-
export { ZintrustSocketHub } from '
|
|
5
|
+
export { ZintrustSocketHub } from '@zintrust/socket';
|
|
6
6
|
//# sourceMappingURL=cloudflare.d.ts.map
|
package/src/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @zintrust/core v0.4.
|
|
2
|
+
* @zintrust/core v0.4.65
|
|
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-05T16:19:42.578Z
|
|
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-05T16:19:42.544Z'; // 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":"PluginAutoImports.d.ts","sourceRoot":"","sources":["../../../src/runtime/PluginAutoImports.ts"],"names":[],"mappings":"AAKA,OAAO,EAAmB,KAAK,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEzF,KAAK,YAAY,GACb;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAChC;IACE,EAAE,EAAE,KAAK,CAAC;IACV,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,WAAW,GAAG,eAAe,CAAC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;
|
|
1
|
+
{"version":3,"file":"PluginAutoImports.d.ts","sourceRoot":"","sources":["../../../src/runtime/PluginAutoImports.ts"],"names":[],"mappings":"AAKA,OAAO,EAAmB,KAAK,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEzF,KAAK,YAAY,GACb;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAChC;IACE,EAAE,EAAE,KAAK,CAAC;IACV,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,WAAW,GAAG,eAAe,CAAC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AA4ON,eAAO,MAAM,iBAAiB;uCACY,uBAAuB,GAAY,OAAO,CAAC,YAAY,CAAC;IAkBhG;;;;;;OAMG;mCACkC,OAAO,CAAC,YAAY,CAAC;qCAkEnB,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;EAavE,CAAC"}
|
|
@@ -4,6 +4,16 @@ import { existsSync, readFile } from '../node-singletons/fs.js';
|
|
|
4
4
|
import * as path from '../node-singletons/path.js';
|
|
5
5
|
import { pathToFileURL } from '../node-singletons/url.js';
|
|
6
6
|
import { OfficialPlugins } from './OfficialPlugins.js';
|
|
7
|
+
const formatImportSummary = (summary, total) => {
|
|
8
|
+
const details = [`Loaded ${summary.loaded}/${total} official plugin imports`];
|
|
9
|
+
if (summary.missingSpecifiers.length > 0) {
|
|
10
|
+
details.push(`missing: ${summary.missingSpecifiers.join(', ')}`);
|
|
11
|
+
}
|
|
12
|
+
if (summary.failedSpecifiers.length > 0) {
|
|
13
|
+
details.push(`failed: ${summary.failedSpecifiers.join(', ')}`);
|
|
14
|
+
}
|
|
15
|
+
return details.join(' | ');
|
|
16
|
+
};
|
|
7
17
|
const getProjectCwd = () => process.cwd();
|
|
8
18
|
const getProjectRootEnv = () => readEnvString('ZINTRUST_PROJECT_ROOT');
|
|
9
19
|
const resolveProjectRoot = () => {
|
|
@@ -163,14 +173,27 @@ const importSpecifiers = async (specifiers) => {
|
|
|
163
173
|
summary.failed += 1;
|
|
164
174
|
return summary;
|
|
165
175
|
}
|
|
166
|
-
if (result.value.status === 'loaded')
|
|
176
|
+
if (result.value.status === 'loaded') {
|
|
167
177
|
summary.loaded += 1;
|
|
168
|
-
|
|
178
|
+
summary.loadedSpecifiers.push(result.value.specifier);
|
|
179
|
+
}
|
|
180
|
+
else if (result.value.status === 'missing') {
|
|
169
181
|
summary.missing += 1;
|
|
170
|
-
|
|
182
|
+
summary.missingSpecifiers.push(result.value.specifier);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
171
185
|
summary.failed += 1;
|
|
186
|
+
summary.failedSpecifiers.push(result.value.specifier);
|
|
187
|
+
}
|
|
172
188
|
return summary;
|
|
173
|
-
}, {
|
|
189
|
+
}, {
|
|
190
|
+
loaded: 0,
|
|
191
|
+
missing: 0,
|
|
192
|
+
failed: 0,
|
|
193
|
+
loadedSpecifiers: [],
|
|
194
|
+
missingSpecifiers: [],
|
|
195
|
+
failedSpecifiers: [],
|
|
196
|
+
});
|
|
174
197
|
};
|
|
175
198
|
export const PluginAutoImports = Object.freeze({
|
|
176
199
|
async tryImportRuntimeAutoImports(mode = 'base') {
|
|
@@ -183,7 +206,7 @@ export const PluginAutoImports = Object.freeze({
|
|
|
183
206
|
ok: false,
|
|
184
207
|
loadedPath: `official:${mode}`,
|
|
185
208
|
reason: 'import-failed',
|
|
186
|
-
errorMessage:
|
|
209
|
+
errorMessage: formatImportSummary(summary, specifiers.length),
|
|
187
210
|
};
|
|
188
211
|
},
|
|
189
212
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
type WorkersModule = typeof import('
|
|
2
|
-
type QueueMonitorModule = typeof import('
|
|
1
|
+
type WorkersModule = typeof import('@zintrust/workers');
|
|
2
|
+
type QueueMonitorModule = typeof import('@zintrust/queue-monitor');
|
|
3
3
|
export declare const loadWorkersModule: (options?: {
|
|
4
4
|
allowWhenDisabled?: boolean;
|
|
5
5
|
}) => Promise<WorkersModule>;
|
|
@@ -5,7 +5,7 @@ const fallbackDebuggerStorage = Object.freeze({
|
|
|
5
5
|
resolveStorage: (_db) => undefined,
|
|
6
6
|
});
|
|
7
7
|
const fallbackRegisterDebuggerRoutes = (_router, _storage, _options) => undefined;
|
|
8
|
-
const systemDebuggerModule = await import('
|
|
8
|
+
const systemDebuggerModule = await import('@zintrust/system-debugger')
|
|
9
9
|
.then((module) => module)
|
|
10
10
|
.catch(() => undefined);
|
|
11
11
|
export const isAvailable = () => systemDebuggerModule !== undefined;
|
|
@@ -4,10 +4,14 @@ type Broadcaster = Readonly<{
|
|
|
4
4
|
send: (channel: string, event: string, data: unknown) => Promise<unknown>;
|
|
5
5
|
publish: (input: BroadcastPublishInput) => Promise<BroadcastPublishResult>;
|
|
6
6
|
}>;
|
|
7
|
+
type BroadcastChannelScope = 'public' | 'private' | 'presence' | 'persistent';
|
|
7
8
|
type BroadcastDeliveryMode = 'auto' | 'socket' | 'driver';
|
|
9
|
+
type BroadcastTransport = 'internal-http' | 'socket' | 'driver';
|
|
8
10
|
export type BroadcastPublishInput = Readonly<{
|
|
9
11
|
channel?: string;
|
|
10
12
|
channels?: readonly string[];
|
|
13
|
+
scope?: BroadcastChannelScope;
|
|
14
|
+
channelScope?: BroadcastChannelScope;
|
|
11
15
|
event?: string;
|
|
12
16
|
name?: string;
|
|
13
17
|
data?: unknown;
|
|
@@ -19,12 +23,14 @@ export type BroadcastPublishInput = Readonly<{
|
|
|
19
23
|
}>;
|
|
20
24
|
export type BroadcastPublishResult = Readonly<{
|
|
21
25
|
ok: true;
|
|
22
|
-
transport:
|
|
26
|
+
transport: BroadcastTransport;
|
|
23
27
|
channels: readonly string[];
|
|
24
28
|
event: string;
|
|
25
29
|
deliveries?: number;
|
|
26
30
|
driver?: KnownBroadcastDriverConfig['driver'];
|
|
27
31
|
broadcaster?: string;
|
|
32
|
+
endpoint?: string;
|
|
33
|
+
attemptedTransports?: readonly BroadcastTransport[];
|
|
28
34
|
result?: unknown;
|
|
29
35
|
results?: readonly unknown[];
|
|
30
36
|
}>;
|
|
@@ -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":"AAQA,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;AAaH,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;AA8jBH,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"}
|
|
@@ -1,10 +1,231 @@
|
|
|
1
|
-
import { isArray, isNonEmptyString } from '../../helper/index.js';
|
|
1
|
+
import { isArray, isNonEmptyString, isObject } from '../../helper/index.js';
|
|
2
2
|
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
6
|
import broadcastConfig from '../../config/broadcast.js';
|
|
7
|
+
import { Env } from '../../config/env.js';
|
|
8
|
+
import { Logger } from '../../config/logger.js';
|
|
7
9
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
10
|
+
const BROADCAST_CHANNEL_SCOPES = new Set([
|
|
11
|
+
'public',
|
|
12
|
+
'private',
|
|
13
|
+
'presence',
|
|
14
|
+
'persistent',
|
|
15
|
+
]);
|
|
16
|
+
const INTERNAL_SOCKET_SECRET_HEADER = 'x-zintrust-socket-secret';
|
|
17
|
+
const pickFirstNonEmpty = (...values) => {
|
|
18
|
+
for (const value of values) {
|
|
19
|
+
if (value.trim() !== '') {
|
|
20
|
+
return value.trim();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return '';
|
|
24
|
+
};
|
|
25
|
+
const normalizeChannelScope = (value) => {
|
|
26
|
+
if (!isNonEmptyString(value)) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
const normalized = value.trim().toLowerCase();
|
|
30
|
+
if (BROADCAST_CHANNEL_SCOPES.has(normalized)) {
|
|
31
|
+
return normalized;
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
};
|
|
35
|
+
const getQualifiedChannelScope = (channel) => {
|
|
36
|
+
if (channel.startsWith('private-'))
|
|
37
|
+
return 'private';
|
|
38
|
+
if (channel.startsWith('presence-'))
|
|
39
|
+
return 'presence';
|
|
40
|
+
if (channel.startsWith('persistent-'))
|
|
41
|
+
return 'persistent';
|
|
42
|
+
return undefined;
|
|
43
|
+
};
|
|
44
|
+
const applyChannelScope = (channel, scope) => {
|
|
45
|
+
const normalizedChannel = channel.trim();
|
|
46
|
+
const existingScope = getQualifiedChannelScope(normalizedChannel);
|
|
47
|
+
if (existingScope !== undefined) {
|
|
48
|
+
if (scope !== undefined && scope !== existingScope) {
|
|
49
|
+
throw ErrorFactory.createValidationError(`Broadcast channel scope ${scope} conflicts with fully-qualified channel ${normalizedChannel}.`);
|
|
50
|
+
}
|
|
51
|
+
return normalizedChannel;
|
|
52
|
+
}
|
|
53
|
+
if (scope === undefined || scope === 'public') {
|
|
54
|
+
return normalizedChannel;
|
|
55
|
+
}
|
|
56
|
+
return `${scope}-${normalizedChannel}`;
|
|
57
|
+
};
|
|
58
|
+
const normalizeChannels = (input) => {
|
|
59
|
+
const scope = normalizeChannelScope(input.channelScope ?? input.scope);
|
|
60
|
+
if (isArray(input.channels)) {
|
|
61
|
+
return input.channels
|
|
62
|
+
.filter(isNonEmptyString)
|
|
63
|
+
.map((channel) => applyChannelScope(channel, scope));
|
|
64
|
+
}
|
|
65
|
+
if (isNonEmptyString(input.channel)) {
|
|
66
|
+
return [applyChannelScope(input.channel, scope)];
|
|
67
|
+
}
|
|
68
|
+
return [];
|
|
69
|
+
};
|
|
70
|
+
const appendUnique = (values, nextValue) => {
|
|
71
|
+
if (nextValue !== '' && !values.includes(nextValue)) {
|
|
72
|
+
values.push(nextValue);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const toAbsoluteBaseUrl = (value) => {
|
|
76
|
+
const trimmed = value.trim();
|
|
77
|
+
if (trimmed === '' || trimmed.startsWith('/')) {
|
|
78
|
+
return '';
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
return new URL(trimmed).toString();
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
try {
|
|
85
|
+
return new URL(`http://${trimmed}`).toString();
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return '';
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const getLoopbackAlternativeBaseUrl = (value) => {
|
|
93
|
+
try {
|
|
94
|
+
const parsed = new URL(value);
|
|
95
|
+
if (parsed.hostname === '127.0.0.1') {
|
|
96
|
+
parsed.hostname = 'localhost';
|
|
97
|
+
return parsed.toString();
|
|
98
|
+
}
|
|
99
|
+
if (parsed.hostname === 'localhost' ||
|
|
100
|
+
parsed.hostname === '[::1]' ||
|
|
101
|
+
parsed.hostname === '::1') {
|
|
102
|
+
parsed.hostname = '127.0.0.1';
|
|
103
|
+
return parsed.toString();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return '';
|
|
108
|
+
}
|
|
109
|
+
return '';
|
|
110
|
+
};
|
|
111
|
+
const getInternalPublishConfig = () => {
|
|
112
|
+
const baseUrls = [];
|
|
113
|
+
appendUnique(baseUrls, toAbsoluteBaseUrl(Env.get('BROADCAST_INTERNAL_URL', '')));
|
|
114
|
+
appendUnique(baseUrls, toAbsoluteBaseUrl(Env.get('APP_URL', '')));
|
|
115
|
+
appendUnique(baseUrls, toAbsoluteBaseUrl(Env.get('BASE_URL', Env.BASE_URL ?? '')));
|
|
116
|
+
const resolvedBaseUrls = [];
|
|
117
|
+
for (const baseUrl of baseUrls) {
|
|
118
|
+
appendUnique(resolvedBaseUrls, baseUrl);
|
|
119
|
+
appendUnique(resolvedBaseUrls, getLoopbackAlternativeBaseUrl(baseUrl));
|
|
120
|
+
}
|
|
121
|
+
const appId = pickFirstNonEmpty(Env.get('PUSHER_APP_ID', ''), Env.get('BROADCAST_APP_ID', '')) || 'internal';
|
|
122
|
+
const secret = pickFirstNonEmpty(Env.get('BROADCAST_SECRET', ''), Env.get('PUSHER_APP_SECRET', ''), Env.get('BROADCAST_APP_SECRET', ''));
|
|
123
|
+
return Object.freeze({
|
|
124
|
+
endpoints: resolvedBaseUrls.map((baseUrl) => new URL(`/apps/${encodeURIComponent(appId)}/events`, baseUrl).toString()),
|
|
125
|
+
appId,
|
|
126
|
+
secret,
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
const parseJsonResponseSafe = async (response) => {
|
|
130
|
+
const raw = await response.text();
|
|
131
|
+
if (raw.trim() === '') {
|
|
132
|
+
return {};
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
return JSON.parse(raw);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return { raw };
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
const getDeliveries = (payload) => {
|
|
142
|
+
if (!isObject(payload)) {
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
const deliveries = payload['deliveries'];
|
|
146
|
+
return typeof deliveries === 'number' && Number.isFinite(deliveries) ? deliveries : undefined;
|
|
147
|
+
};
|
|
148
|
+
const describeError = (error) => {
|
|
149
|
+
if (error instanceof Error) {
|
|
150
|
+
return {
|
|
151
|
+
name: error.name,
|
|
152
|
+
message: error.message,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
return String(error);
|
|
156
|
+
};
|
|
157
|
+
const logTransportFallback = (transport, details) => {
|
|
158
|
+
Logger.warn('Broadcast publish transport failed; falling back.', {
|
|
159
|
+
transport,
|
|
160
|
+
...details,
|
|
161
|
+
});
|
|
162
|
+
};
|
|
163
|
+
const requestInternalPublishEndpoint = async (endpoint, secret, payload) => {
|
|
164
|
+
try {
|
|
165
|
+
const response = await globalThis.fetch(endpoint, {
|
|
166
|
+
method: 'POST',
|
|
167
|
+
headers: {
|
|
168
|
+
'content-type': 'application/json',
|
|
169
|
+
...(secret === ''
|
|
170
|
+
? {}
|
|
171
|
+
: {
|
|
172
|
+
[INTERNAL_SOCKET_SECRET_HEADER]: secret,
|
|
173
|
+
authorization: `Bearer ${secret}`,
|
|
174
|
+
}),
|
|
175
|
+
},
|
|
176
|
+
body: JSON.stringify(payload),
|
|
177
|
+
});
|
|
178
|
+
const responseBody = await parseJsonResponseSafe(response);
|
|
179
|
+
if (!response.ok) {
|
|
180
|
+
const error = ErrorFactory.createTryCatchError(`Internal socket publish request failed (${response.status})`, {
|
|
181
|
+
status: response.status,
|
|
182
|
+
endpoint,
|
|
183
|
+
body: responseBody,
|
|
184
|
+
});
|
|
185
|
+
logTransportFallback('internal-http', {
|
|
186
|
+
endpoint,
|
|
187
|
+
status: response.status,
|
|
188
|
+
body: responseBody,
|
|
189
|
+
});
|
|
190
|
+
return { result: null, error };
|
|
191
|
+
}
|
|
192
|
+
const resolvedChannels = isObject(responseBody) && isArray(responseBody['channels'])
|
|
193
|
+
? responseBody['channels'].filter(isNonEmptyString).map((channel) => channel.trim())
|
|
194
|
+
: payload.channels;
|
|
195
|
+
const resolvedEvent = isObject(responseBody) && isNonEmptyString(responseBody['event'])
|
|
196
|
+
? responseBody['event'].trim()
|
|
197
|
+
: payload.event;
|
|
198
|
+
return {
|
|
199
|
+
result: {
|
|
200
|
+
ok: true,
|
|
201
|
+
transport: 'internal-http',
|
|
202
|
+
channels: resolvedChannels,
|
|
203
|
+
event: resolvedEvent,
|
|
204
|
+
deliveries: getDeliveries(responseBody),
|
|
205
|
+
endpoint,
|
|
206
|
+
result: responseBody,
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
logTransportFallback('internal-http', {
|
|
212
|
+
endpoint,
|
|
213
|
+
error: describeError(error),
|
|
214
|
+
});
|
|
215
|
+
return { result: null, error };
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
const tryInternalPublishEndpoints = async (endpoints, secret, payload, index = 0, lastError) => {
|
|
219
|
+
const endpoint = endpoints[index];
|
|
220
|
+
if (endpoint === undefined) {
|
|
221
|
+
return { result: null, error: lastError };
|
|
222
|
+
}
|
|
223
|
+
const attempt = await requestInternalPublishEndpoint(endpoint, secret, payload);
|
|
224
|
+
if (attempt.result !== null) {
|
|
225
|
+
return attempt;
|
|
226
|
+
}
|
|
227
|
+
return tryInternalPublishEndpoints(endpoints, secret, payload, index + 1, attempt.error ?? lastError);
|
|
228
|
+
};
|
|
8
229
|
const resolveBroadcasterConfig = async (name) => {
|
|
9
230
|
const selection = (name ?? broadcastConfig.getDriverName()).toString().trim().toLowerCase();
|
|
10
231
|
try {
|
|
@@ -59,15 +280,7 @@ const normalizePublishInput = (input) => {
|
|
|
59
280
|
else if (isNonEmptyString(input.name)) {
|
|
60
281
|
event = input.name.trim();
|
|
61
282
|
}
|
|
62
|
-
const channels = (
|
|
63
|
-
if (isArray(input.channels)) {
|
|
64
|
-
return input.channels.filter(isNonEmptyString).map((channel) => channel.trim());
|
|
65
|
-
}
|
|
66
|
-
if (isNonEmptyString(input.channel)) {
|
|
67
|
-
return [input.channel.trim()];
|
|
68
|
-
}
|
|
69
|
-
return [];
|
|
70
|
-
})();
|
|
283
|
+
const channels = normalizeChannels(input);
|
|
71
284
|
if (event === '' || channels.length === 0) {
|
|
72
285
|
throw ErrorFactory.createValidationError('Broadcast.publish requires event/name and channel/channels.');
|
|
73
286
|
}
|
|
@@ -82,12 +295,32 @@ const normalizePublishInput = (input) => {
|
|
|
82
295
|
...(input.user === undefined ? {} : { user: input.user }),
|
|
83
296
|
};
|
|
84
297
|
};
|
|
298
|
+
/**
|
|
299
|
+
* Error codes from publishSocketEventFromServer that represent policy/auth failures.
|
|
300
|
+
* These must not be swallowed in auto delivery mode — the socket publish policy must
|
|
301
|
+
* be respected even when a driver fallback is available.
|
|
302
|
+
*/
|
|
303
|
+
const NON_TRANSIENT_SOCKET_ERROR_CODES = new Set([
|
|
304
|
+
'FORBIDDEN',
|
|
305
|
+
'UNAUTHORIZED',
|
|
306
|
+
'VALIDATION_ERROR',
|
|
307
|
+
'SECURITY_ERROR',
|
|
308
|
+
'SANITIZER_ERROR',
|
|
309
|
+
]);
|
|
310
|
+
/**
|
|
311
|
+
* Returns true for authorization/validation/policy errors from the socket module.
|
|
312
|
+
* Returns false for "socket unavailable" errors (module missing, disabled, connection
|
|
313
|
+
* failure, config) which are safe to fall back from.
|
|
314
|
+
*/
|
|
315
|
+
const isNonTransientSocketError = (error) => {
|
|
316
|
+
if (!(error instanceof Error))
|
|
317
|
+
return false;
|
|
318
|
+
const code = error.code;
|
|
319
|
+
return typeof code === 'string' && NON_TRANSIENT_SOCKET_ERROR_CODES.has(code);
|
|
320
|
+
};
|
|
85
321
|
const tryPublishViaSocket = async (input) => {
|
|
86
322
|
try {
|
|
87
|
-
const socketModule = await import('
|
|
88
|
-
if (socketModule.socketRuntime.isEnabled() !== true) {
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
323
|
+
const socketModule = (await import('@zintrust/socket'));
|
|
91
324
|
const socketResult = await socketModule.publishSocketEventFromServer({
|
|
92
325
|
channels: input.channels,
|
|
93
326
|
event: input.event,
|
|
@@ -97,20 +330,38 @@ const tryPublishViaSocket = async (input) => {
|
|
|
97
330
|
user: input.user,
|
|
98
331
|
});
|
|
99
332
|
return {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
333
|
+
result: {
|
|
334
|
+
ok: true,
|
|
335
|
+
transport: 'socket',
|
|
336
|
+
channels: socketResult.channels,
|
|
337
|
+
event: socketResult.event,
|
|
338
|
+
deliveries: socketResult.deliveries,
|
|
339
|
+
result: socketResult,
|
|
340
|
+
},
|
|
106
341
|
};
|
|
107
342
|
}
|
|
108
343
|
catch (error) {
|
|
109
|
-
|
|
344
|
+
// For authorization/validation/policy errors, rethrow even in auto delivery mode
|
|
345
|
+
// to prevent bypassing socket publish policy via driver fallback.
|
|
346
|
+
// Only allow fallback for "socket unavailable" cases (module missing, disabled, connection issues).
|
|
347
|
+
if (isNonTransientSocketError(error)) {
|
|
110
348
|
throw error;
|
|
111
349
|
}
|
|
112
|
-
return null;
|
|
350
|
+
return { result: null, error };
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
const tryPublishViaInternalHttp = async (input) => {
|
|
354
|
+
const config = getInternalPublishConfig();
|
|
355
|
+
if (config.endpoints.length === 0 || typeof globalThis.fetch !== 'function') {
|
|
356
|
+
return { result: null };
|
|
113
357
|
}
|
|
358
|
+
const payload = {
|
|
359
|
+
channels: input.channels,
|
|
360
|
+
event: input.event,
|
|
361
|
+
data: input.data,
|
|
362
|
+
...(input.socketId === undefined ? {} : { socket_id: input.socketId }),
|
|
363
|
+
};
|
|
364
|
+
return tryInternalPublishEndpoints(config.endpoints, config.secret, payload);
|
|
114
365
|
};
|
|
115
366
|
const publishWithConfig = async (config, broadcasterName, input) => {
|
|
116
367
|
const results = await Promise.all(input.channels.map(async (channel) => sendWithConfig(config, channel, input.event, input.data)));
|
|
@@ -126,17 +377,41 @@ const publishWithConfig = async (config, broadcasterName, input) => {
|
|
|
126
377
|
};
|
|
127
378
|
const publishInternal = async (input) => {
|
|
128
379
|
const normalized = normalizePublishInput(input);
|
|
380
|
+
const attemptedTransports = [];
|
|
381
|
+
let lastTransportError;
|
|
129
382
|
if (normalized.delivery !== 'driver') {
|
|
383
|
+
attemptedTransports.push('internal-http');
|
|
384
|
+
const internalHttpResult = await tryPublishViaInternalHttp(normalized);
|
|
385
|
+
if (internalHttpResult.result !== null) {
|
|
386
|
+
return { ...internalHttpResult.result, attemptedTransports };
|
|
387
|
+
}
|
|
388
|
+
if (internalHttpResult.error !== undefined) {
|
|
389
|
+
lastTransportError = internalHttpResult.error;
|
|
390
|
+
}
|
|
391
|
+
attemptedTransports.push('socket');
|
|
130
392
|
const socketResult = await tryPublishViaSocket(normalized);
|
|
131
|
-
if (socketResult !== null) {
|
|
132
|
-
return socketResult;
|
|
393
|
+
if (socketResult.result !== null) {
|
|
394
|
+
return { ...socketResult.result, attemptedTransports };
|
|
395
|
+
}
|
|
396
|
+
if (socketResult.error !== undefined) {
|
|
397
|
+
lastTransportError = socketResult.error;
|
|
398
|
+
logTransportFallback('socket', {
|
|
399
|
+
error: describeError(socketResult.error),
|
|
400
|
+
});
|
|
133
401
|
}
|
|
134
402
|
}
|
|
135
403
|
if (normalized.delivery === 'socket') {
|
|
404
|
+
if (lastTransportError instanceof Error) {
|
|
405
|
+
throw lastTransportError;
|
|
406
|
+
}
|
|
136
407
|
throw ErrorFactory.createConfigError('Socket publish delivery is not available.');
|
|
137
408
|
}
|
|
409
|
+
attemptedTransports.push('driver');
|
|
138
410
|
const config = await resolveBroadcasterConfig(normalized.broadcaster);
|
|
139
|
-
return
|
|
411
|
+
return {
|
|
412
|
+
...(await publishWithConfig(config, normalized.broadcaster, normalized)),
|
|
413
|
+
attemptedTransports,
|
|
414
|
+
};
|
|
140
415
|
};
|
|
141
416
|
const publishLaterInternal = async (input, options = {}) => {
|
|
142
417
|
const normalized = normalizePublishInput(input);
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* side-effect imports (e.g. `@zintrust/db-sqlite/register`) that register
|
|
6
|
-
* optional adapters/drivers into core registries.
|
|
7
|
-
*
|
|
2
|
+
* Auto-generated fallback module.
|
|
3
|
+
* This file is created by scripts/ensure-worker-plugins.mjs when missing.
|
|
4
|
+
* It allows optional runtime plugin imports to resolve in CI/scaffolded setups.
|
|
8
5
|
*/
|
|
9
|
-
export type {};
|
|
10
6
|
export declare const __zintrustGeneratedPluginStub = "zintrust.plugins.ts";
|
|
11
7
|
declare const _default: {};
|
|
12
8
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zintrust.plugins.d.ts","sourceRoot":"","sources":["../../src/zintrust.plugins.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"zintrust.plugins.d.ts","sourceRoot":"","sources":["../../src/zintrust.plugins.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,6BAA6B,wBAAwB,CAAC;;AACnE,wBAAkB"}
|
package/src/zintrust.plugins.js
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* side-effect imports (e.g. `@zintrust/db-sqlite/register`) that register
|
|
6
|
-
* optional adapters/drivers into core registries.
|
|
7
|
-
*
|
|
2
|
+
* Auto-generated fallback module.
|
|
3
|
+
* This file is created by scripts/ensure-worker-plugins.mjs when missing.
|
|
4
|
+
* It allows optional runtime plugin imports to resolve in CI/scaffolded setups.
|
|
8
5
|
*/
|
|
9
|
-
import * as SystemDebuggerRuntime from './runtime/plugins/system-debugger-runtime.js';
|
|
10
|
-
globalThis.__zintrust_system_debugger_plugin_requested__ = true;
|
|
11
|
-
globalThis.__zintrust_system_debugger_runtime__ = SystemDebuggerRuntime;
|
|
12
6
|
export const __zintrustGeneratedPluginStub = 'zintrust.plugins.ts';
|
|
13
7
|
export default {};
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* This file is created by scripts/ensure-worker-plugins.mjs when missing.
|
|
4
4
|
* It allows optional runtime plugin imports to resolve in CI/scaffolded setups.
|
|
5
5
|
*/
|
|
6
|
-
export type {};
|
|
7
6
|
export declare const __zintrustGeneratedPluginStub = "zintrust.plugins.wg.ts";
|
|
8
7
|
declare const _default: {};
|
|
9
8
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zintrust.plugins.wg.d.ts","sourceRoot":"","sources":["../../src/zintrust.plugins.wg.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"zintrust.plugins.wg.d.ts","sourceRoot":"","sources":["../../src/zintrust.plugins.wg.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,6BAA6B,2BAA2B,CAAC;;AACtE,wBAAkB"}
|
|
@@ -3,8 +3,5 @@
|
|
|
3
3
|
* This file is created by scripts/ensure-worker-plugins.mjs when missing.
|
|
4
4
|
* It allows optional runtime plugin imports to resolve in CI/scaffolded setups.
|
|
5
5
|
*/
|
|
6
|
-
import * as SystemDebuggerRuntime from './runtime/plugins/system-debugger-runtime.js';
|
|
7
|
-
globalThis.__zintrust_system_debugger_plugin_requested__ = true;
|
|
8
|
-
globalThis.__zintrust_system_debugger_runtime__ = SystemDebuggerRuntime;
|
|
9
6
|
export const __zintrustGeneratedPluginStub = 'zintrust.plugins.wg.ts';
|
|
10
7
|
export default {};
|
package/src/zintrust.comon.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import '../packages/db-d1/src/register.js';
|
|
2
|
-
import '../packages/db-mysql/src/register.js';
|
|
3
|
-
import '../packages/db-postgres/src/register.js';
|
|
4
|
-
import '../packages/db-sqlite/src/register.js';
|
|
5
|
-
import '../packages/db-sqlserver/src/register.js';
|
|
6
|
-
import '../packages/mail-sendgrid/src/register.js';
|
|
7
|
-
import '../packages/mail-smtp/src/register.js';
|
|
8
|
-
import '../packages/queue-monitor/src/index.js';
|
|
9
|
-
import '../packages/queue-redis/src/register.js';
|
|
10
|
-
import '../packages/workers/src/register.js';
|
|
11
|
-
//# sourceMappingURL=zintrust.comon.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"zintrust.comon.d.ts","sourceRoot":"","sources":["../../src/zintrust.comon.ts"],"names":[],"mappings":"AAQA,OAAO,mCAAmC,CAAC;AAC3C,OAAO,sCAAsC,CAAC;AAC9C,OAAO,yCAAyC,CAAC;AACjD,OAAO,uCAAuC,CAAC;AAC/C,OAAO,0CAA0C,CAAC;AAClD,OAAO,2CAA2C,CAAC;AACnD,OAAO,uCAAuC,CAAC;AAC/C,OAAO,wCAAwC,CAAC;AAChD,OAAO,yCAAyC,CAAC;AACjD,OAAO,qCAAqC,CAAC"}
|
package/src/zintrust.comon.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-restricted-imports */
|
|
2
|
-
// /**
|
|
3
|
-
// * ZinTrust comon plugin auto-imports
|
|
4
|
-
// *
|
|
5
|
-
// * This file is managed by `zin plugin install` and contains side-effect
|
|
6
|
-
// * imports that register optional adapters/drivers into core registries.
|
|
7
|
-
// */
|
|
8
|
-
import '../packages/db-d1/src/register.js';
|
|
9
|
-
import '../packages/db-mysql/src/register.js';
|
|
10
|
-
import '../packages/db-postgres/src/register.js';
|
|
11
|
-
import '../packages/db-sqlite/src/register.js';
|
|
12
|
-
import '../packages/db-sqlserver/src/register.js';
|
|
13
|
-
import '../packages/mail-sendgrid/src/register.js';
|
|
14
|
-
import '../packages/mail-smtp/src/register.js';
|
|
15
|
-
import '@zintrust/queue-monitor';
|
|
16
|
-
import '../packages/queue-redis/src/register.js';
|
|
17
|
-
import '../packages/workers/src/register.js';
|