@zintrust/socket 0.4.59 → 0.4.63
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/dist/build-manifest.json +9 -9
- package/dist/index.d.ts +17 -2
- package/dist/index.js +82 -10
- package/package.json +2 -2
package/dist/build-manifest.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zintrust/socket",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"buildDate": "2026-04-
|
|
3
|
+
"version": "0.4.63",
|
|
4
|
+
"buildDate": "2026-04-05T13:13:05.363Z",
|
|
5
5
|
"buildEnvironment": {
|
|
6
6
|
"node": "v22.22.1",
|
|
7
7
|
"platform": "darwin",
|
|
8
8
|
"arch": "arm64"
|
|
9
9
|
},
|
|
10
10
|
"git": {
|
|
11
|
-
"commit": "
|
|
11
|
+
"commit": "533afc24",
|
|
12
12
|
"branch": "release"
|
|
13
13
|
},
|
|
14
14
|
"package": {
|
|
@@ -22,16 +22,16 @@
|
|
|
22
22
|
},
|
|
23
23
|
"files": {
|
|
24
24
|
"build-manifest.json": {
|
|
25
|
-
"size":
|
|
26
|
-
"sha256": "
|
|
25
|
+
"size": 1086,
|
|
26
|
+
"sha256": "a55e096a80190637fe7d56c36e53865451f623c88ceb5ccb7b9124e4a14335bb"
|
|
27
27
|
},
|
|
28
28
|
"index.d.ts": {
|
|
29
|
-
"size":
|
|
30
|
-
"sha256": "
|
|
29
|
+
"size": 1393,
|
|
30
|
+
"sha256": "c3b8e8d96234c34a42f08dd14fadab504cb6f2bd76c15bce5fb23e5acde4941f"
|
|
31
31
|
},
|
|
32
32
|
"index.js": {
|
|
33
|
-
"size":
|
|
34
|
-
"sha256": "
|
|
33
|
+
"size": 38284,
|
|
34
|
+
"sha256": "cf683327a9a0d2ba1b349cc059c2113c76e36e130b56e613932fdccd5c4f435f"
|
|
35
35
|
},
|
|
36
36
|
"register.d.ts": {
|
|
37
37
|
"size": 16,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
|
-
import { type IRouter, type SocketRouteRegistrar } from '@zintrust/core';
|
|
1
|
+
import { type IRequest, type IRouter, type SocketRouteRegistrar } from '@zintrust/core';
|
|
2
|
+
type ServerSideSocketPublishInput = Readonly<{
|
|
3
|
+
channels: readonly string[];
|
|
4
|
+
event: string;
|
|
5
|
+
data: unknown;
|
|
6
|
+
socketId?: string;
|
|
7
|
+
request?: IRequest;
|
|
8
|
+
user?: unknown;
|
|
9
|
+
}>;
|
|
10
|
+
declare const publishSocketEventFromServer: (input: ServerSideSocketPublishInput) => Promise<{
|
|
11
|
+
ok: true;
|
|
12
|
+
transport: "node" | "cloudflare";
|
|
13
|
+
channels: readonly string[];
|
|
14
|
+
event: string;
|
|
15
|
+
deliveries: number;
|
|
16
|
+
}>;
|
|
2
17
|
declare const socketRuntime: any;
|
|
3
18
|
declare const registerSocketRoutes: (router: IRouter) => void;
|
|
4
19
|
declare const socketRouteRegistrar: SocketRouteRegistrar;
|
|
@@ -16,5 +31,5 @@ export declare class ZintrustSocketHub {
|
|
|
16
31
|
private handlePublishRequest;
|
|
17
32
|
}
|
|
18
33
|
export declare const publishSocketEvent: (channels: string[], event: string, data: unknown, excludeSocketId?: string) => number;
|
|
19
|
-
export { registerSocketRoutes, socketRouteRegistrar, socketRuntime };
|
|
34
|
+
export { publishSocketEventFromServer, registerSocketRoutes, socketRouteRegistrar, socketRuntime };
|
|
20
35
|
export default SocketPackage;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { broadcastConfig, Cloudflare, ErrorFactory, isArray, isNonEmptyString, Logger, middlewareConfig, Router, SocketFeature, } from '@zintrust/core';
|
|
2
2
|
const encoder = new TextEncoder();
|
|
3
3
|
const websocketGuid = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
|
|
4
4
|
const socketHubBindingName = 'ZT_SOCKET_HUB';
|
|
@@ -46,7 +46,11 @@ const normalizeSocketPath = (value) => {
|
|
|
46
46
|
if (trimmed === '' || trimmed === '/')
|
|
47
47
|
return '/app';
|
|
48
48
|
const normalized = trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
|
|
49
|
-
|
|
49
|
+
let end = normalized.length;
|
|
50
|
+
while (end > 1 && normalized[end - 1] === '/') {
|
|
51
|
+
end -= 1;
|
|
52
|
+
}
|
|
53
|
+
return end === normalized.length ? normalized : normalized.slice(0, end);
|
|
50
54
|
};
|
|
51
55
|
const pickFirstNonEmpty = (...values) => {
|
|
52
56
|
for (const value of values) {
|
|
@@ -491,7 +495,7 @@ const shouldUseCloudflareHub = (settings) => {
|
|
|
491
495
|
};
|
|
492
496
|
const parseJsonResponse = async (response) => {
|
|
493
497
|
try {
|
|
494
|
-
return
|
|
498
|
+
return await response.clone().json();
|
|
495
499
|
}
|
|
496
500
|
catch {
|
|
497
501
|
try {
|
|
@@ -658,6 +662,76 @@ const normalizePublishDecisionPayload = (payload, decision) => {
|
|
|
658
662
|
})(),
|
|
659
663
|
};
|
|
660
664
|
};
|
|
665
|
+
const createServerSidePublishRequest = (input) => {
|
|
666
|
+
return {
|
|
667
|
+
getBody: () => null,
|
|
668
|
+
getHeader: () => undefined,
|
|
669
|
+
getParam: () => undefined,
|
|
670
|
+
user: input.user ?? null,
|
|
671
|
+
};
|
|
672
|
+
};
|
|
673
|
+
const getResponseDeliveries = (payload) => {
|
|
674
|
+
if (typeof payload !== 'object' || payload === null) {
|
|
675
|
+
return 0;
|
|
676
|
+
}
|
|
677
|
+
const deliveries = payload.deliveries;
|
|
678
|
+
return typeof deliveries === 'number' && Number.isFinite(deliveries) ? deliveries : 0;
|
|
679
|
+
};
|
|
680
|
+
const publishSocketEventFromServer = async (input) => {
|
|
681
|
+
const settings = getSocketRuntimeSettings(Cloudflare.getWorkersEnv());
|
|
682
|
+
if (!settings.enabled || settings.appKey.trim() === '') {
|
|
683
|
+
throw ErrorFactory.createConfigError('Socket runtime is not enabled.');
|
|
684
|
+
}
|
|
685
|
+
const request = input.request ?? createServerSidePublishRequest(input);
|
|
686
|
+
const payload = {
|
|
687
|
+
channels: input.channels.map((channel) => channel.trim()),
|
|
688
|
+
event: input.event.trim(),
|
|
689
|
+
data: input.data ?? {},
|
|
690
|
+
...(isNonEmptyString(input.socketId) ? { socket_id: input.socketId.trim() } : {}),
|
|
691
|
+
};
|
|
692
|
+
const publishPolicy = resolveSocketPublishPolicy();
|
|
693
|
+
const decision = await publishPolicy.authorize(request, {
|
|
694
|
+
appId: settings.appId,
|
|
695
|
+
channels: payload.channels,
|
|
696
|
+
event: payload.event,
|
|
697
|
+
data: payload.data,
|
|
698
|
+
socketId: payload.socket_id,
|
|
699
|
+
user: input.user ?? request.user ?? null,
|
|
700
|
+
});
|
|
701
|
+
if (decision.allowed !== true) {
|
|
702
|
+
throw ErrorFactory.createForbiddenError(decision.message ?? 'Forbidden', {
|
|
703
|
+
statusCode: decision.statusCode ?? 403,
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
const allowedPayload = normalizePublishDecisionPayload(payload, decision);
|
|
707
|
+
if (allowedPayload === null) {
|
|
708
|
+
throw ErrorFactory.createValidationError('Socket publish policy must return a non-empty event and channels.');
|
|
709
|
+
}
|
|
710
|
+
if (shouldUseCloudflareHub(settings)) {
|
|
711
|
+
const response = await forwardPublishToHub(settings, allowedPayload, Cloudflare.getWorkersEnv());
|
|
712
|
+
const responseBody = await parseJsonResponse(response);
|
|
713
|
+
if (!response.ok) {
|
|
714
|
+
throw ErrorFactory.createTryCatchError(`Socket publish request failed (${response.status})`, {
|
|
715
|
+
status: response.status,
|
|
716
|
+
body: responseBody,
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
return {
|
|
720
|
+
ok: true,
|
|
721
|
+
transport: 'cloudflare',
|
|
722
|
+
channels: allowedPayload.channels,
|
|
723
|
+
event: allowedPayload.event,
|
|
724
|
+
deliveries: getResponseDeliveries(responseBody),
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
return {
|
|
728
|
+
ok: true,
|
|
729
|
+
transport: 'node',
|
|
730
|
+
channels: allowedPayload.channels,
|
|
731
|
+
event: allowedPayload.event,
|
|
732
|
+
deliveries: publishToChannels(getNodeSocketState(), allowedPayload.channels, allowedPayload.event, allowedPayload.data, allowedPayload.socket_id),
|
|
733
|
+
};
|
|
734
|
+
};
|
|
661
735
|
const forwardPublishToHub = async (settings, payload, envSource) => {
|
|
662
736
|
const stub = getSocketHubStub(settings, envSource);
|
|
663
737
|
if (stub === null) {
|
|
@@ -839,15 +913,13 @@ const publishEvent = async (req, res) => {
|
|
|
839
913
|
const registerSocketRoutes = (router) => {
|
|
840
914
|
const settings = getSocketRuntimeSettings();
|
|
841
915
|
const allowAuthRouteOverride = isSocketAuthRouteOverrideEnabled();
|
|
916
|
+
const hasExistingAuthRoute = routeExists(router, 'POST', '/broadcasting/auth');
|
|
842
917
|
assertReservedSocketRouteAvailable(router, 'GET', `${settings.path}/:appKey`);
|
|
843
|
-
assertReservedSocketRouteAvailable(router, 'POST', '/broadcasting/auth', {
|
|
844
|
-
allowOverride: true,
|
|
845
|
-
});
|
|
846
918
|
assertReservedSocketRouteAvailable(router, 'POST', '/apps/:appId/events');
|
|
847
919
|
Router.get(router, `${settings.path}/:appKey`, respondUpgradeRequired);
|
|
848
|
-
if (
|
|
849
|
-
if (!
|
|
850
|
-
Logger.
|
|
920
|
+
if (hasExistingAuthRoute) {
|
|
921
|
+
if (!allowAuthRouteOverride) {
|
|
922
|
+
Logger.info('Detected existing application-owned POST /broadcasting/auth route; preserving it while sockets are enabled.');
|
|
851
923
|
}
|
|
852
924
|
}
|
|
853
925
|
else {
|
|
@@ -926,5 +998,5 @@ export class ZintrustSocketHub {
|
|
|
926
998
|
export const publishSocketEvent = (channels, event, data, excludeSocketId) => {
|
|
927
999
|
return publishToChannels(getNodeSocketState(), channels, event, data, excludeSocketId);
|
|
928
1000
|
};
|
|
929
|
-
export { registerSocketRoutes, socketRouteRegistrar, socketRuntime };
|
|
1001
|
+
export { publishSocketEventFromServer, registerSocketRoutes, socketRouteRegistrar, socketRuntime };
|
|
930
1002
|
export default SocketPackage;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zintrust/socket",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.63",
|
|
4
4
|
"description": "Unified socket runtime for ZinTrust.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"node": ">=20.0.0"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"@zintrust/core": "^0.4.
|
|
26
|
+
"@zintrust/core": "^0.4.63"
|
|
27
27
|
},
|
|
28
28
|
"publishConfig": {
|
|
29
29
|
"access": "public"
|