@fluojs/websockets 1.0.8 → 2.0.0
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/README.ko.md +19 -6
- package/README.md +19 -6
- package/dist/bun/bun-service.d.ts +3 -1
- package/dist/bun/bun-service.d.ts.map +1 -1
- package/dist/bun/bun-service.js +75 -26
- package/dist/bun/bun-types.d.ts +5 -3
- package/dist/bun/bun-types.d.ts.map +1 -1
- package/dist/bun.d.ts +2 -1
- package/dist/bun.d.ts.map +1 -1
- package/dist/bun.js +2 -1
- package/dist/cloudflare-workers/cloudflare-workers-service.d.ts +4 -0
- package/dist/cloudflare-workers/cloudflare-workers-service.d.ts.map +1 -1
- package/dist/cloudflare-workers/cloudflare-workers-service.js +89 -20
- package/dist/cloudflare-workers/cloudflare-workers-types.d.ts +2 -2
- package/dist/cloudflare-workers/cloudflare-workers-types.d.ts.map +1 -1
- package/dist/cloudflare-workers.d.ts +2 -1
- package/dist/cloudflare-workers.d.ts.map +1 -1
- package/dist/cloudflare-workers.js +2 -1
- package/dist/decorators.d.ts +2 -2
- package/dist/decorators.d.ts.map +1 -1
- package/dist/decorators.js +4 -4
- package/dist/deno/deno-service.d.ts +4 -0
- package/dist/deno/deno-service.d.ts.map +1 -1
- package/dist/deno/deno-service.js +85 -16
- package/dist/deno/deno-types.d.ts +2 -2
- package/dist/deno/deno-types.d.ts.map +1 -1
- package/dist/deno.d.ts +2 -1
- package/dist/deno.d.ts.map +1 -1
- package/dist/deno.js +2 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/internal/shared.d.ts +6 -3
- package/dist/internal/shared.d.ts.map +1 -1
- package/dist/internal/shared.js +26 -6
- package/dist/internal.d.ts +7 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +6 -0
- package/dist/node/node-service.d.ts +3 -2
- package/dist/node/node-service.d.ts.map +1 -1
- package/dist/node/node-service.js +21 -5
- package/dist/node/node-types.d.ts +2 -2
- package/dist/node/node-types.d.ts.map +1 -1
- package/dist/node.d.ts +1 -0
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +2 -1
- package/dist/types.d.ts +26 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +21 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/internal/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,KAAK,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,KAAK,EAAE,SAAS,EAAY,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,uCAAuC,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGzE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/internal/shared.ts"],"names":[],"mappings":"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"}
|
package/dist/internal/shared.js
CHANGED
|
@@ -179,27 +179,46 @@ export async function resolveGatewayInstance(runtimeContainer, descriptor, logge
|
|
|
179
179
|
* @param socket The socket.
|
|
180
180
|
* @param request The request.
|
|
181
181
|
* @param data The data.
|
|
182
|
+
* @param socketId Stable connection identity passed to message handlers.
|
|
183
|
+
* @param replyMode Optional policy for serializing valid handler return envelopes.
|
|
184
|
+
* @param sendReply Runtime-owned reply sender that reports terminal send failures.
|
|
182
185
|
* @param logger The logger.
|
|
183
186
|
* @param loggerContext The logger context.
|
|
184
|
-
* @returns
|
|
187
|
+
* @returns `terminal` when reply delivery failed; otherwise `completed`.
|
|
185
188
|
*/
|
|
186
|
-
export async function dispatchGatewayMessage(resolved, socket, request, data, logger, loggerContext) {
|
|
189
|
+
export async function dispatchGatewayMessage(resolved, socket, request, data, socketId, replyMode, sendReply, logger, loggerContext) {
|
|
187
190
|
const parsed = parseIncomingMessage(data);
|
|
188
191
|
for (const {
|
|
189
192
|
descriptor,
|
|
190
193
|
instance
|
|
191
194
|
} of resolved) {
|
|
192
195
|
for (const handler of descriptor.wildcardMessageHandlers) {
|
|
193
|
-
await invokeGatewayMethod(instance, descriptor, handler, [parsed.payload, socket, request], logger, loggerContext);
|
|
196
|
+
const result = await invokeGatewayMethod(instance, descriptor, handler, [parsed.payload, socket, request, socketId], logger, loggerContext);
|
|
197
|
+
if (!sendHandlerReply(result, replyMode, sendReply)) {
|
|
198
|
+
return 'terminal';
|
|
199
|
+
}
|
|
194
200
|
}
|
|
195
201
|
if (parsed.event === undefined) {
|
|
196
202
|
continue;
|
|
197
203
|
}
|
|
198
204
|
const eventHandlers = descriptor.messageHandlersByEvent.get(parsed.event) ?? [];
|
|
199
205
|
for (const handler of eventHandlers) {
|
|
200
|
-
await invokeGatewayMethod(instance, descriptor, handler, [parsed.payload, socket, request], logger, loggerContext);
|
|
206
|
+
const result = await invokeGatewayMethod(instance, descriptor, handler, [parsed.payload, socket, request, socketId], logger, loggerContext);
|
|
207
|
+
if (!sendHandlerReply(result, replyMode, sendReply)) {
|
|
208
|
+
return 'terminal';
|
|
209
|
+
}
|
|
201
210
|
}
|
|
202
211
|
}
|
|
212
|
+
return 'completed';
|
|
213
|
+
}
|
|
214
|
+
function sendHandlerReply(result, replyMode, sendReply) {
|
|
215
|
+
if (replyMode !== 'event-envelope' || !isWebSocketEventEnvelope(result)) {
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
return sendReply(JSON.stringify(result));
|
|
219
|
+
}
|
|
220
|
+
function isWebSocketEventEnvelope(value) {
|
|
221
|
+
return typeof value === 'object' && value !== null && 'event' in value && typeof value.event === 'string';
|
|
203
222
|
}
|
|
204
223
|
|
|
205
224
|
/**
|
|
@@ -244,12 +263,13 @@ async function invokeGatewayMethod(instance, descriptor, handler, args, logger,
|
|
|
244
263
|
const value = instance[handler.methodKey];
|
|
245
264
|
if (typeof value !== 'function') {
|
|
246
265
|
logger.warn(`WebSocket gateway handler ${descriptor.targetName}.${handler.methodName} is not callable and was skipped.`, loggerContext);
|
|
247
|
-
return;
|
|
266
|
+
return undefined;
|
|
248
267
|
}
|
|
249
268
|
try {
|
|
250
|
-
await Promise.resolve(value.call(instance, ...args));
|
|
269
|
+
return await Promise.resolve(value.call(instance, ...args));
|
|
251
270
|
} catch (error) {
|
|
252
271
|
logger.error(`WebSocket gateway handler ${descriptor.targetName}.${handler.methodName} failed.`, error, loggerContext);
|
|
272
|
+
return undefined;
|
|
253
273
|
}
|
|
254
274
|
}
|
|
255
275
|
function discoveryCandidates(compiledModules) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-internal gateway discovery and dispatch primitives shared by protocol adapters.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export { discoverGatewayDescriptors, resolveGatewayInstance, type ResolvedGatewayInstance, } from './internal/shared.js';
|
|
7
|
+
//# sourceMappingURL=internal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,EACtB,KAAK,uBAAuB,GAC7B,MAAM,sBAAsB,CAAC"}
|
package/dist/internal.js
ADDED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Container } from '@fluojs/di';
|
|
2
|
-
import type { ApplicationLogger, CompiledModule, OnApplicationBootstrap, OnApplicationShutdown, OnModuleDestroy } from '@fluojs/runtime';
|
|
3
2
|
import type { HttpApplicationAdapter } from '@fluojs/http';
|
|
3
|
+
import type { ApplicationLogger, CompiledModule, OnApplicationBootstrap, OnApplicationShutdown, OnModuleDestroy } from '@fluojs/runtime';
|
|
4
4
|
import type { WebSocketRoomService } from '../types.js';
|
|
5
5
|
import { NodeWebSocketGatewayLifecycleService } from './node-service-token.js';
|
|
6
6
|
import type { WebSocketModuleOptions } from './node-types.js';
|
|
@@ -105,7 +105,8 @@ export declare class NodeWebSocketGatewayLifecycleServiceImplementation extends
|
|
|
105
105
|
private closeGatewayAttachment;
|
|
106
106
|
private clearConnectionTrackingState;
|
|
107
107
|
/**
|
|
108
|
-
* Adds one socket to an in-memory room membership set.
|
|
108
|
+
* Adds one currently open, runtime-registered socket to an in-memory room membership set.
|
|
109
|
+
* Unknown or already closed socket identifiers are ignored.
|
|
109
110
|
*
|
|
110
111
|
* @param socketId Socket identifier to add.
|
|
111
112
|
* @param room Room identifier to join.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-service.d.ts","sourceRoot":"","sources":["../../src/node/node-service.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"node-service.d.ts","sourceRoot":"","sources":["../../src/node/node-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@ import { createServer as createHttpServer } from 'node:http';
|
|
|
9
9
|
import { Inject } from '@fluojs/core';
|
|
10
10
|
import { APPLICATION_LOGGER, COMPILED_MODULES, HTTP_APPLICATION_ADAPTER, RUNTIME_CONTAINER } from '@fluojs/runtime/internal';
|
|
11
11
|
import { WebSocket, WebSocketServer } from 'ws';
|
|
12
|
-
import { dispatchGatewayDisconnect, dispatchGatewayMessage,
|
|
12
|
+
import { discoverGatewayDescriptors, dispatchGatewayDisconnect, dispatchGatewayMessage, isFinitePositiveInteger, normalizeGatewayPath, resolveGatewayInstance, runGatewayHandlers } from '../internal/shared.js';
|
|
13
13
|
import { WEBSOCKET_OPTIONS_INTERNAL } from '../options-token.internal.js';
|
|
14
14
|
import { NodeWebSocketGatewayLifecycleService } from './node-service-token.js';
|
|
15
15
|
function resolveHttpStatusText(status) {
|
|
@@ -329,6 +329,14 @@ class NodeWebSocketGatewayLifecycleServiceImplementation extends NodeWebSocketGa
|
|
|
329
329
|
rejectUpgradeRequestWithStatus(socket, rejection);
|
|
330
330
|
return;
|
|
331
331
|
}
|
|
332
|
+
if (this.isShuttingDown) {
|
|
333
|
+
this.releaseUpgradeReservation();
|
|
334
|
+
rejectUpgradeRequestWithStatus(socket, {
|
|
335
|
+
body: 'WebSocket server is shutting down.',
|
|
336
|
+
status: 503
|
|
337
|
+
});
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
332
340
|
try {
|
|
333
341
|
attachment.server.handleUpgrade(request, socket, head, websocket => {
|
|
334
342
|
attachment.server.emit('connection', websocket, request);
|
|
@@ -485,12 +493,15 @@ class NodeWebSocketGatewayLifecycleServiceImplementation extends NodeWebSocketGa
|
|
|
485
493
|
if (nextMessage === undefined) {
|
|
486
494
|
continue;
|
|
487
495
|
}
|
|
488
|
-
await this.handleMessage(state.resolved, socket, request, nextMessage);
|
|
496
|
+
await this.handleMessage(state.resolved, socket, request, nextMessage, state.socketId);
|
|
489
497
|
}
|
|
490
498
|
this.clearQueuedMessages(state);
|
|
491
499
|
}
|
|
492
|
-
async handleMessage(resolved, socket, request, data) {
|
|
493
|
-
await dispatchGatewayMessage(resolved, socket, request, data, this.
|
|
500
|
+
async handleMessage(resolved, socket, request, data, socketId) {
|
|
501
|
+
await dispatchGatewayMessage(resolved, socket, request, data, socketId, this.moduleOptions.replies?.mode, message => {
|
|
502
|
+
socket.send(message);
|
|
503
|
+
return true;
|
|
504
|
+
}, this.logger, 'WebSocketGatewayLifecycleService');
|
|
494
505
|
}
|
|
495
506
|
enqueueDisconnectDispatch(state, socket, disconnectEvent) {
|
|
496
507
|
state.handlerQueue = state.handlerQueue.then(async () => {
|
|
@@ -928,12 +939,17 @@ class NodeWebSocketGatewayLifecycleServiceImplementation extends NodeWebSocketGa
|
|
|
928
939
|
}
|
|
929
940
|
|
|
930
941
|
/**
|
|
931
|
-
* Adds one socket to an in-memory room membership set.
|
|
942
|
+
* Adds one currently open, runtime-registered socket to an in-memory room membership set.
|
|
943
|
+
* Unknown or already closed socket identifiers are ignored.
|
|
932
944
|
*
|
|
933
945
|
* @param socketId Socket identifier to add.
|
|
934
946
|
* @param room Room identifier to join.
|
|
935
947
|
*/
|
|
936
948
|
joinRoom(socketId, room) {
|
|
949
|
+
const socket = this.socketRegistry.get(socketId);
|
|
950
|
+
if (!socket || socket.readyState !== WebSocket.OPEN) {
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
937
953
|
let rooms = this.socketRooms.get(socketId);
|
|
938
954
|
if (!rooms) {
|
|
939
955
|
rooms = new Set();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { IncomingMessage } from 'node:http';
|
|
2
2
|
import type { WebSocket } from 'ws';
|
|
3
|
-
import type { WebSocketModuleOptions as SharedWebSocketModuleOptions,
|
|
3
|
+
import type { WebSocketModuleOptions as SharedWebSocketModuleOptions, WebSocketUpgradeGuard as SharedWebSocketUpgradeGuard, WebSocketUpgradeContext, WebSocketUpgradeRejection } from '../types.js';
|
|
4
4
|
/**
|
|
5
5
|
* Strongly typed message handler signature for the Node websocket runtime.
|
|
6
6
|
*/
|
|
7
|
-
export type TypedOnMessageHandler<TEvents extends Record<string, unknown>, K extends keyof TEvents> = (
|
|
7
|
+
export type TypedOnMessageHandler<TEvents extends Record<string, unknown>, K extends keyof TEvents> = import('../types.js').TypedOnMessageHandler<TEvents, K, WebSocket, IncomingMessage>;
|
|
8
8
|
/**
|
|
9
9
|
* Request and socket context passed to Node websocket gateway handlers.
|
|
10
10
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-types.d.ts","sourceRoot":"","sources":["../../src/node/node-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAEpC,OAAO,KAAK,EACV,sBAAsB,IAAI,4BAA4B,EACtD,
|
|
1
|
+
{"version":3,"file":"node-types.d.ts","sourceRoot":"","sources":["../../src/node/node-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAEpC,OAAO,KAAK,EACV,sBAAsB,IAAI,4BAA4B,EACtD,qBAAqB,IAAI,2BAA2B,EACpD,uBAAuB,EACvB,yBAAyB,EAC1B,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,MAAM,MAAM,qBAAqB,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,MAAM,OAAO,IAAI,OAAO,aAAa,EAAE,qBAAqB,CAC/I,OAAO,EACP,CAAC,EACD,SAAS,EACT,eAAe,CAChB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,eAAe,CAAC;IACzB,MAAM,EAAE,SAAS,CAAC;CACnB;AAED,YAAY,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,2BAA2B,CAAC,eAAe,CAAC,CAAC;AAEjF;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,4BAA4B,CAAC,eAAe,CAAC,CAAC"}
|
package/dist/node.d.ts
CHANGED
package/dist/node.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,YAAY,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/node.js
CHANGED
package/dist/types.d.ts
CHANGED
|
@@ -3,6 +3,19 @@ import type { MetadataPropertyKey, Token } from '@fluojs/core';
|
|
|
3
3
|
* Event-name-to-payload map used to type `@OnMessage(...)` handlers.
|
|
4
4
|
*/
|
|
5
5
|
export type WebSocketEventMap = Record<string, unknown>;
|
|
6
|
+
/**
|
|
7
|
+
* Event envelope that a message handler can return when event-envelope replies are enabled.
|
|
8
|
+
*/
|
|
9
|
+
export interface WebSocketEventEnvelope {
|
|
10
|
+
/** Reply payload sent as the envelope `data` field. */
|
|
11
|
+
data?: unknown;
|
|
12
|
+
/** Reply event name sent as the envelope `event` field. */
|
|
13
|
+
event: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Opt-in policy for processing message handler return values.
|
|
17
|
+
*/
|
|
18
|
+
export type WebSocketReplyMode = 'event-envelope';
|
|
6
19
|
/**
|
|
7
20
|
* Runtime-neutral message handler signature resolved from one {@link WebSocketEventMap} entry.
|
|
8
21
|
*
|
|
@@ -10,8 +23,13 @@ export type WebSocketEventMap = Record<string, unknown>;
|
|
|
10
23
|
* @typeParam K Event key handled by this callback.
|
|
11
24
|
* @typeParam TSocket Socket shape surfaced by the selected runtime subpath.
|
|
12
25
|
* @typeParam TRequest Request shape surfaced by the selected runtime subpath.
|
|
26
|
+
* @param payload Parsed payload for the decorated event.
|
|
27
|
+
* @param socket Accepted runtime socket.
|
|
28
|
+
* @param request Upgrade request associated with the connection.
|
|
29
|
+
* @param socketId Stable connection identity used by room operations.
|
|
30
|
+
* @returns An optional event envelope. Returns are ignored unless `replies.mode` is `event-envelope`.
|
|
13
31
|
*/
|
|
14
|
-
export type TypedOnMessageHandler<TEvents extends WebSocketEventMap, K extends keyof TEvents, TSocket = unknown, TRequest = Request> = (payload: TEvents[K], socket: TSocket, request: TRequest) => void |
|
|
32
|
+
export type TypedOnMessageHandler<TEvents extends WebSocketEventMap, K extends keyof TEvents, TSocket = unknown, TRequest = Request> = (payload: TEvents[K], socket: TSocket, request: TRequest, socketId: string) => Promise<WebSocketEventEnvelope | void> | WebSocketEventEnvelope | void;
|
|
15
33
|
/**
|
|
16
34
|
* Dedicated listener configuration for runtimes that can host a standalone WebSocket server.
|
|
17
35
|
*/
|
|
@@ -131,7 +149,8 @@ export type WebSocketUpgradeGuard<TRequest = Request> = (request: TRequest, cont
|
|
|
131
149
|
*/
|
|
132
150
|
export interface WebSocketRoomService {
|
|
133
151
|
/**
|
|
134
|
-
* Adds one socket to a room.
|
|
152
|
+
* Adds one currently open, runtime-registered socket to a room.
|
|
153
|
+
* Unknown or already closed socket identifiers are ignored.
|
|
135
154
|
*
|
|
136
155
|
* @param socketId Socket identifier to add.
|
|
137
156
|
* @param room Room identifier to join.
|
|
@@ -191,6 +210,11 @@ export interface WebSocketModuleOptions<TRequest = Request> {
|
|
|
191
210
|
intervalMs?: number;
|
|
192
211
|
timeoutMs?: number;
|
|
193
212
|
};
|
|
213
|
+
/** Opt-in processing for message handler return values. Returns are ignored when omitted. */
|
|
214
|
+
replies?: {
|
|
215
|
+
/** Sends valid `{ event, data? }` handler returns through the accepted socket. */
|
|
216
|
+
mode: WebSocketReplyMode;
|
|
217
|
+
};
|
|
194
218
|
shutdown?: {
|
|
195
219
|
timeoutMs?: number;
|
|
196
220
|
};
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAExD
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"realtime",
|
|
10
10
|
"upgrade"
|
|
11
11
|
],
|
|
12
|
-
"version": "
|
|
12
|
+
"version": "2.0.0",
|
|
13
13
|
"private": false,
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"repository": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"directory": "packages/websockets"
|
|
19
19
|
},
|
|
20
20
|
"engines": {
|
|
21
|
-
"node": ">=
|
|
21
|
+
"node": ">=24.0.0 <27"
|
|
22
22
|
},
|
|
23
23
|
"publishConfig": {
|
|
24
24
|
"access": "public"
|
|
@@ -44,6 +44,10 @@
|
|
|
44
44
|
"./node": {
|
|
45
45
|
"types": "./dist/node.d.ts",
|
|
46
46
|
"import": "./dist/node.js"
|
|
47
|
+
},
|
|
48
|
+
"./internal": {
|
|
49
|
+
"types": "./dist/internal.d.ts",
|
|
50
|
+
"import": "./dist/internal.js"
|
|
47
51
|
}
|
|
48
52
|
},
|
|
49
53
|
"main": "./dist/index.js",
|
|
@@ -61,6 +65,9 @@
|
|
|
61
65
|
],
|
|
62
66
|
"node": [
|
|
63
67
|
"./dist/node.d.ts"
|
|
68
|
+
],
|
|
69
|
+
"internal": [
|
|
70
|
+
"./dist/internal.d.ts"
|
|
64
71
|
]
|
|
65
72
|
}
|
|
66
73
|
},
|
|
@@ -68,20 +75,21 @@
|
|
|
68
75
|
"dist"
|
|
69
76
|
],
|
|
70
77
|
"dependencies": {
|
|
71
|
-
"ws": "^8.
|
|
72
|
-
"@fluojs/core": "^
|
|
73
|
-
"@fluojs/
|
|
74
|
-
"@fluojs/runtime": "^
|
|
75
|
-
"@fluojs/
|
|
78
|
+
"ws": "^8.21.0",
|
|
79
|
+
"@fluojs/core": "^2.0.0",
|
|
80
|
+
"@fluojs/di": "^3.0.0",
|
|
81
|
+
"@fluojs/runtime": "^3.0.0",
|
|
82
|
+
"@fluojs/http": "^3.0.0"
|
|
76
83
|
},
|
|
77
84
|
"devDependencies": {
|
|
78
85
|
"@types/ws": "^8.18.1",
|
|
79
|
-
"vitest": "^
|
|
80
|
-
"@fluojs/platform-
|
|
81
|
-
"@fluojs/platform-
|
|
82
|
-
"@fluojs/platform-express": "^
|
|
83
|
-
"@fluojs/platform-fastify": "^
|
|
84
|
-
"@fluojs/
|
|
86
|
+
"vitest": "^4.1.11",
|
|
87
|
+
"@fluojs/platform-bun": "^3.0.0",
|
|
88
|
+
"@fluojs/platform-cloudflare-workers": "^2.0.0",
|
|
89
|
+
"@fluojs/platform-express": "^2.0.0",
|
|
90
|
+
"@fluojs/platform-fastify": "^2.0.0",
|
|
91
|
+
"@fluojs/platform-nodejs": "^2.0.0",
|
|
92
|
+
"@fluojs/testing": "^3.0.0"
|
|
85
93
|
},
|
|
86
94
|
"scripts": {
|
|
87
95
|
"prebuild": "node ../../tooling/scripts/clean-dist.mjs",
|