@zintrust/core 0.4.63 → 0.4.64

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zintrust/core",
3
- "version": "0.4.63",
3
+ "version": "0.4.64",
4
4
  "description": "Production-grade TypeScript backend framework for JavaScript",
5
5
  "homepage": "https://zintrust.com",
6
6
  "repository": {
@@ -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('../../../packages/system-debugger/src/index.js'));
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);
@@ -2,7 +2,7 @@ let cachedModule;
2
2
  let loadPromise = null;
3
3
  const importSystemDebugger = async () => {
4
4
  try {
5
- return (await import('../../packages/system-debugger/src/index.js'));
5
+ return (await import('@zintrust/system-debugger'));
6
6
  }
7
7
  catch {
8
8
  return null;
@@ -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 '../../packages/socket/src/index.js';
5
+ export { ZintrustSocketHub } from '@zintrust/socket';
6
6
  //# sourceMappingURL=cloudflare.d.ts.map
@@ -215,4 +215,4 @@ export default {
215
215
  }
216
216
  },
217
217
  };
218
- export { ZintrustSocketHub } from '../../packages/socket/src/index.js';
218
+ export { ZintrustSocketHub } from '@zintrust/socket';
package/src/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @zintrust/core v0.4.63
2
+ * @zintrust/core v0.4.64
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-05T13:11:49.141Z
8
+ * Built: 2026-04-05T14:53:27.033Z
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-05T13:11:49.107Z'; // Replaced during build
24
+ export const ZINTRUST_BUILD_DATE = '2026-04-05T14:53:26.999Z'; // 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;AA6MN,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"}
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
- else if (result.value.status === 'missing')
178
+ summary.loadedSpecifiers.push(result.value.specifier);
179
+ }
180
+ else if (result.value.status === 'missing') {
169
181
  summary.missing += 1;
170
- else
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
- }, { loaded: 0, missing: 0, failed: 0 });
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: `Loaded ${summary.loaded}/${specifiers.length} official plugin imports`,
209
+ errorMessage: formatImportSummary(summary, specifiers.length),
187
210
  };
188
211
  },
189
212
  /**
@@ -1,5 +1,5 @@
1
- type WorkersModule = typeof import('../../packages/workers/src/index.js');
2
- type QueueMonitorModule = typeof import('../../packages/queue-monitor/src/index.js');
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('../../../packages/system-debugger/src/index.js')
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: 'socket' | 'driver';
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":"AAMA,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,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE1D,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,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,QAAQ,GAAG,QAAQ,CAAC;IAC/B,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,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;CAC9B,CAAC,CAAC;AAsMH,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
+ {"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;AAEhE,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;AAqiBH,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,228 @@
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 INTERNAL_SOCKET_SECRET_HEADER = 'x-zintrust-socket-secret';
11
+ const pickFirstNonEmpty = (...values) => {
12
+ for (const value of values) {
13
+ if (value.trim() !== '') {
14
+ return value.trim();
15
+ }
16
+ }
17
+ return '';
18
+ };
19
+ const normalizeChannelScope = (value) => {
20
+ if (!isNonEmptyString(value)) {
21
+ return undefined;
22
+ }
23
+ const normalized = value.trim().toLowerCase();
24
+ if (normalized === 'public' ||
25
+ normalized === 'private' ||
26
+ normalized === 'presence' ||
27
+ normalized === 'persistent') {
28
+ return normalized;
29
+ }
30
+ return undefined;
31
+ };
32
+ const getQualifiedChannelScope = (channel) => {
33
+ if (channel.startsWith('private-'))
34
+ return 'private';
35
+ if (channel.startsWith('presence-'))
36
+ return 'presence';
37
+ if (channel.startsWith('persistent-'))
38
+ return 'persistent';
39
+ return undefined;
40
+ };
41
+ const applyChannelScope = (channel, scope) => {
42
+ const normalizedChannel = channel.trim();
43
+ const existingScope = getQualifiedChannelScope(normalizedChannel);
44
+ if (existingScope !== undefined) {
45
+ if (scope !== undefined && scope !== existingScope) {
46
+ throw ErrorFactory.createValidationError(`Broadcast channel scope ${scope} conflicts with fully-qualified channel ${normalizedChannel}.`);
47
+ }
48
+ return normalizedChannel;
49
+ }
50
+ if (scope === undefined || scope === 'public') {
51
+ return normalizedChannel;
52
+ }
53
+ return `${scope}-${normalizedChannel}`;
54
+ };
55
+ const normalizeChannels = (input) => {
56
+ const scope = normalizeChannelScope(input.channelScope ?? input.scope);
57
+ if (isArray(input.channels)) {
58
+ return input.channels
59
+ .filter(isNonEmptyString)
60
+ .map((channel) => applyChannelScope(channel, scope));
61
+ }
62
+ if (isNonEmptyString(input.channel)) {
63
+ return [applyChannelScope(input.channel, scope)];
64
+ }
65
+ return [];
66
+ };
67
+ const appendUnique = (values, nextValue) => {
68
+ if (nextValue !== '' && !values.includes(nextValue)) {
69
+ values.push(nextValue);
70
+ }
71
+ };
72
+ const toAbsoluteBaseUrl = (value) => {
73
+ const trimmed = value.trim();
74
+ if (trimmed === '' || trimmed.startsWith('/')) {
75
+ return '';
76
+ }
77
+ try {
78
+ return new URL(trimmed).toString();
79
+ }
80
+ catch {
81
+ try {
82
+ return new URL(`http://${trimmed}`).toString();
83
+ }
84
+ catch {
85
+ return '';
86
+ }
87
+ }
88
+ };
89
+ const getLoopbackAlternativeBaseUrl = (value) => {
90
+ try {
91
+ const parsed = new URL(value);
92
+ if (parsed.hostname === '127.0.0.1') {
93
+ parsed.hostname = 'localhost';
94
+ return parsed.toString();
95
+ }
96
+ if (parsed.hostname === 'localhost' ||
97
+ parsed.hostname === '[::1]' ||
98
+ parsed.hostname === '::1') {
99
+ parsed.hostname = '127.0.0.1';
100
+ return parsed.toString();
101
+ }
102
+ }
103
+ catch {
104
+ return '';
105
+ }
106
+ return '';
107
+ };
108
+ const getInternalPublishConfig = () => {
109
+ const baseUrls = [];
110
+ appendUnique(baseUrls, toAbsoluteBaseUrl(Env.get('BROADCAST_INTERNAL_URL', '')));
111
+ appendUnique(baseUrls, toAbsoluteBaseUrl(Env.get('APP_URL', '')));
112
+ appendUnique(baseUrls, toAbsoluteBaseUrl(Env.get('BASE_URL', Env.BASE_URL ?? '')));
113
+ const resolvedBaseUrls = [];
114
+ for (const baseUrl of baseUrls) {
115
+ appendUnique(resolvedBaseUrls, baseUrl);
116
+ appendUnique(resolvedBaseUrls, getLoopbackAlternativeBaseUrl(baseUrl));
117
+ }
118
+ const appId = pickFirstNonEmpty(Env.get('PUSHER_APP_ID', ''), Env.get('BROADCAST_APP_ID', '')) || 'internal';
119
+ const secret = pickFirstNonEmpty(Env.get('BROADCAST_SECRET', ''), Env.get('PUSHER_APP_SECRET', ''), Env.get('BROADCAST_APP_SECRET', ''));
120
+ return Object.freeze({
121
+ endpoints: resolvedBaseUrls.map((baseUrl) => new URL(`/apps/${encodeURIComponent(appId)}/events`, baseUrl).toString()),
122
+ appId,
123
+ secret,
124
+ });
125
+ };
126
+ const parseJsonResponseSafe = async (response) => {
127
+ const raw = await response.text();
128
+ if (raw.trim() === '') {
129
+ return {};
130
+ }
131
+ try {
132
+ return JSON.parse(raw);
133
+ }
134
+ catch {
135
+ return { raw };
136
+ }
137
+ };
138
+ const getDeliveries = (payload) => {
139
+ if (!isObject(payload)) {
140
+ return undefined;
141
+ }
142
+ const deliveries = payload['deliveries'];
143
+ return typeof deliveries === 'number' && Number.isFinite(deliveries) ? deliveries : undefined;
144
+ };
145
+ const describeError = (error) => {
146
+ if (error instanceof Error) {
147
+ return {
148
+ name: error.name,
149
+ message: error.message,
150
+ };
151
+ }
152
+ return String(error);
153
+ };
154
+ const logTransportFallback = (transport, details) => {
155
+ Logger.warn('Broadcast publish transport failed; falling back.', {
156
+ transport,
157
+ ...details,
158
+ });
159
+ };
160
+ const requestInternalPublishEndpoint = async (endpoint, secret, payload) => {
161
+ try {
162
+ const response = await globalThis.fetch(endpoint, {
163
+ method: 'POST',
164
+ headers: {
165
+ 'content-type': 'application/json',
166
+ ...(secret === ''
167
+ ? {}
168
+ : {
169
+ [INTERNAL_SOCKET_SECRET_HEADER]: secret,
170
+ authorization: `Bearer ${secret}`,
171
+ }),
172
+ },
173
+ body: JSON.stringify(payload),
174
+ });
175
+ const responseBody = await parseJsonResponseSafe(response);
176
+ if (!response.ok) {
177
+ const error = ErrorFactory.createTryCatchError(`Internal socket publish request failed (${response.status})`, {
178
+ status: response.status,
179
+ endpoint,
180
+ body: responseBody,
181
+ });
182
+ logTransportFallback('internal-http', {
183
+ endpoint,
184
+ status: response.status,
185
+ body: responseBody,
186
+ });
187
+ return { result: null, error };
188
+ }
189
+ const resolvedChannels = isObject(responseBody) && isArray(responseBody['channels'])
190
+ ? responseBody['channels'].filter(isNonEmptyString).map((channel) => channel.trim())
191
+ : payload.channels;
192
+ const resolvedEvent = isObject(responseBody) && isNonEmptyString(responseBody['event'])
193
+ ? responseBody['event'].trim()
194
+ : payload.event;
195
+ return {
196
+ result: {
197
+ ok: true,
198
+ transport: 'internal-http',
199
+ channels: resolvedChannels,
200
+ event: resolvedEvent,
201
+ deliveries: getDeliveries(responseBody),
202
+ endpoint,
203
+ result: responseBody,
204
+ },
205
+ };
206
+ }
207
+ catch (error) {
208
+ logTransportFallback('internal-http', {
209
+ endpoint,
210
+ error: describeError(error),
211
+ });
212
+ return { result: null, error };
213
+ }
214
+ };
215
+ const tryInternalPublishEndpoints = async (endpoints, secret, payload, index = 0, lastError) => {
216
+ const endpoint = endpoints[index];
217
+ if (endpoint === undefined) {
218
+ return { result: null, error: lastError };
219
+ }
220
+ const attempt = await requestInternalPublishEndpoint(endpoint, secret, payload);
221
+ if (attempt.result !== null) {
222
+ return attempt;
223
+ }
224
+ return tryInternalPublishEndpoints(endpoints, secret, payload, index + 1, attempt.error ?? lastError);
225
+ };
8
226
  const resolveBroadcasterConfig = async (name) => {
9
227
  const selection = (name ?? broadcastConfig.getDriverName()).toString().trim().toLowerCase();
10
228
  try {
@@ -59,15 +277,7 @@ const normalizePublishInput = (input) => {
59
277
  else if (isNonEmptyString(input.name)) {
60
278
  event = input.name.trim();
61
279
  }
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
- })();
280
+ const channels = normalizeChannels(input);
71
281
  if (event === '' || channels.length === 0) {
72
282
  throw ErrorFactory.createValidationError('Broadcast.publish requires event/name and channel/channels.');
73
283
  }
@@ -84,10 +294,7 @@ const normalizePublishInput = (input) => {
84
294
  };
85
295
  const tryPublishViaSocket = async (input) => {
86
296
  try {
87
- const socketModule = await import('../../../packages/socket/src/index.js');
88
- if (socketModule.socketRuntime.isEnabled() !== true) {
89
- return null;
90
- }
297
+ const socketModule = (await import('@zintrust/socket'));
91
298
  const socketResult = await socketModule.publishSocketEventFromServer({
92
299
  channels: input.channels,
93
300
  event: input.event,
@@ -97,20 +304,32 @@ const tryPublishViaSocket = async (input) => {
97
304
  user: input.user,
98
305
  });
99
306
  return {
100
- ok: true,
101
- transport: 'socket',
102
- channels: socketResult.channels,
103
- event: socketResult.event,
104
- deliveries: socketResult.deliveries,
105
- result: socketResult,
307
+ result: {
308
+ ok: true,
309
+ transport: 'socket',
310
+ channels: socketResult.channels,
311
+ event: socketResult.event,
312
+ deliveries: socketResult.deliveries,
313
+ result: socketResult,
314
+ },
106
315
  };
107
316
  }
108
317
  catch (error) {
109
- if (input.delivery === 'socket') {
110
- throw error;
111
- }
112
- return null;
318
+ return { result: null, error };
319
+ }
320
+ };
321
+ const tryPublishViaInternalHttp = async (input) => {
322
+ const config = getInternalPublishConfig();
323
+ if (config.endpoints.length === 0 || typeof globalThis.fetch !== 'function') {
324
+ return { result: null };
113
325
  }
326
+ const payload = {
327
+ channels: input.channels,
328
+ event: input.event,
329
+ data: input.data,
330
+ ...(input.socketId === undefined ? {} : { socket_id: input.socketId }),
331
+ };
332
+ return tryInternalPublishEndpoints(config.endpoints, config.secret, payload);
114
333
  };
115
334
  const publishWithConfig = async (config, broadcasterName, input) => {
116
335
  const results = await Promise.all(input.channels.map(async (channel) => sendWithConfig(config, channel, input.event, input.data)));
@@ -126,17 +345,41 @@ const publishWithConfig = async (config, broadcasterName, input) => {
126
345
  };
127
346
  const publishInternal = async (input) => {
128
347
  const normalized = normalizePublishInput(input);
348
+ const attemptedTransports = [];
349
+ let lastTransportError;
129
350
  if (normalized.delivery !== 'driver') {
351
+ attemptedTransports.push('internal-http');
352
+ const internalHttpResult = await tryPublishViaInternalHttp(normalized);
353
+ if (internalHttpResult.result !== null) {
354
+ return { ...internalHttpResult.result, attemptedTransports };
355
+ }
356
+ if (internalHttpResult.error !== undefined) {
357
+ lastTransportError = internalHttpResult.error;
358
+ }
359
+ attemptedTransports.push('socket');
130
360
  const socketResult = await tryPublishViaSocket(normalized);
131
- if (socketResult !== null) {
132
- return socketResult;
361
+ if (socketResult.result !== null) {
362
+ return { ...socketResult.result, attemptedTransports };
363
+ }
364
+ if (socketResult.error !== undefined) {
365
+ lastTransportError = socketResult.error;
366
+ logTransportFallback('socket', {
367
+ error: describeError(socketResult.error),
368
+ });
133
369
  }
134
370
  }
135
371
  if (normalized.delivery === 'socket') {
372
+ if (lastTransportError instanceof Error) {
373
+ throw lastTransportError;
374
+ }
136
375
  throw ErrorFactory.createConfigError('Socket publish delivery is not available.');
137
376
  }
377
+ attemptedTransports.push('driver');
138
378
  const config = await resolveBroadcasterConfig(normalized.broadcaster);
139
- return publishWithConfig(config, normalized.broadcaster, normalized);
379
+ return {
380
+ ...(await publishWithConfig(config, normalized.broadcaster, normalized)),
381
+ attemptedTransports,
382
+ };
140
383
  };
141
384
  const publishLaterInternal = async (input, options = {}) => {
142
385
  const normalized = normalizePublishInput(input);
@@ -5,7 +5,7 @@ import '../packages/db-sqlite/src/register.js';
5
5
  import '../packages/db-sqlserver/src/register.js';
6
6
  import '../packages/mail-sendgrid/src/register.js';
7
7
  import '../packages/mail-smtp/src/register.js';
8
- import '../packages/queue-monitor/src/index.js';
8
+ import '@zintrust/queue-monitor';
9
9
  import '../packages/queue-redis/src/register.js';
10
10
  import '../packages/workers/src/register.js';
11
11
  //# sourceMappingURL=zintrust.comon.d.ts.map