dialogue-ts 0.0.2 → 0.0.4
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/src/index.cjs +160 -69
- package/dist/src/index.cjs.map +1 -1
- package/dist/src/index.d.cts +60 -2
- package/dist/src/index.d.ts +60 -2
- package/dist/src/index.js +158 -69
- package/dist/src/index.js.map +1 -1
- package/package.json +4 -2
package/dist/src/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
|
-
import { Result } from 'slang-ts';
|
|
3
2
|
import { Socket, Server } from 'socket.io';
|
|
3
|
+
import { Result } from 'slang-ts';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -247,6 +247,14 @@ interface DialogueConfig {
|
|
|
247
247
|
logger?: Logger;
|
|
248
248
|
/** CORS configuration. Defaults to allowing all origins in development. */
|
|
249
249
|
cors?: CorsConfig | boolean;
|
|
250
|
+
/**
|
|
251
|
+
* Runtime to use for the HTTP server and Socket.IO engine.
|
|
252
|
+
* - "bun": Uses Bun.serve() with @socket.io/bun-engine
|
|
253
|
+
* - "node": Uses Node.js http.createServer() with Socket.IO's built-in engine
|
|
254
|
+
*
|
|
255
|
+
* Auto-detected if not specified (checks for Bun globals, falls back to Node).
|
|
256
|
+
*/
|
|
257
|
+
runtime?: "bun" | "node";
|
|
250
258
|
}
|
|
251
259
|
/**
|
|
252
260
|
* Message envelope - the shape of all messages sent between clients and server.
|
|
@@ -436,6 +444,56 @@ interface RoomManager {
|
|
|
436
444
|
removeParticipant(roomId: string, clientId: string): void;
|
|
437
445
|
}
|
|
438
446
|
|
|
447
|
+
/** Supported runtime environments */
|
|
448
|
+
type Runtime = "bun" | "node";
|
|
449
|
+
/**
|
|
450
|
+
* Runtime adapter interface that abstracts the HTTP server and Socket.IO engine
|
|
451
|
+
* binding for different JavaScript runtimes (Bun, Node.js).
|
|
452
|
+
*
|
|
453
|
+
* Each adapter handles:
|
|
454
|
+
* - Binding the Socket.IO engine to the IO server
|
|
455
|
+
* - Starting/stopping the HTTP server with Hono routing and Socket.IO transport
|
|
456
|
+
*/
|
|
457
|
+
interface RuntimeAdapter {
|
|
458
|
+
/** The runtime this adapter targets */
|
|
459
|
+
readonly runtime: Runtime;
|
|
460
|
+
/**
|
|
461
|
+
* Bind the Socket.IO server to the runtime-specific engine.
|
|
462
|
+
* For Bun: uses @socket.io/bun-engine
|
|
463
|
+
* For Node: uses Socket.IO's built-in engine.io (attached to http.Server)
|
|
464
|
+
*/
|
|
465
|
+
bind(io: Server): void;
|
|
466
|
+
/**
|
|
467
|
+
* Start the HTTP server on the given port, routing both Hono app
|
|
468
|
+
* requests and Socket.IO transport (polling + websocket).
|
|
469
|
+
*/
|
|
470
|
+
start(options: RuntimeStartOptions): Promise<void>;
|
|
471
|
+
/** Stop the HTTP server and clean up resources */
|
|
472
|
+
stop(): Promise<void>;
|
|
473
|
+
}
|
|
474
|
+
/** Options passed to RuntimeAdapter.start() */
|
|
475
|
+
interface RuntimeStartOptions {
|
|
476
|
+
port: number;
|
|
477
|
+
app: Hono;
|
|
478
|
+
io: Server;
|
|
479
|
+
corsConfig: CorsConfig | boolean | undefined;
|
|
480
|
+
logger: Logger;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Detects the current JavaScript runtime by checking for Bun globals.
|
|
485
|
+
* Falls back to "node" if Bun is not detected.
|
|
486
|
+
*/
|
|
487
|
+
declare function detectRuntime(): Runtime;
|
|
488
|
+
/**
|
|
489
|
+
* Creates the appropriate runtime adapter based on the specified runtime.
|
|
490
|
+
* Uses auto-detection if no runtime is specified.
|
|
491
|
+
*
|
|
492
|
+
* @param runtime - Explicit runtime choice, or auto-detected if omitted
|
|
493
|
+
* @returns A RuntimeAdapter for the target runtime
|
|
494
|
+
*/
|
|
495
|
+
declare function createRuntimeAdapter(runtime?: Runtime): RuntimeAdapter;
|
|
496
|
+
|
|
439
497
|
/**
|
|
440
498
|
* Creates a Dialogue instance from configuration.
|
|
441
499
|
* This is the main entry point for the library.
|
|
@@ -661,4 +719,4 @@ interface RateLimiter {
|
|
|
661
719
|
*/
|
|
662
720
|
declare function createRateLimiter(config: RateLimiterConfig): RateLimiter;
|
|
663
721
|
|
|
664
|
-
export { type AuthData, type AuthenticateResult, type ConnectedClient, type CorsConfig, type Dialogue, type DialogueConfig, type DialogueContext, type EventDefinition, type EventHistoryConfig, type EventMessage, type HistoryManager, type HistoryManagerConfig, type HooksConfig, type JwtClaims, type LogEntry, type Logger, type RateLimiter, type RateLimiterConfig, type Room, type RoomConfig, type RoomManager, createDefaultLogger, createDialogue, createHistoryManager, createRateLimiter, createSilentLogger, defineEvent, getEventByName, isEventAllowed, validateEventData };
|
|
722
|
+
export { type AuthData, type AuthenticateResult, type ConnectedClient, type CorsConfig, type Dialogue, type DialogueConfig, type DialogueContext, type EventDefinition, type EventHistoryConfig, type EventMessage, type HistoryManager, type HistoryManagerConfig, type HooksConfig, type JwtClaims, type LogEntry, type Logger, type RateLimiter, type RateLimiterConfig, type Room, type RoomConfig, type RoomManager, type Runtime, type RuntimeAdapter, type RuntimeStartOptions, createDefaultLogger, createDialogue, createHistoryManager, createRateLimiter, createRuntimeAdapter, createSilentLogger, defineEvent, detectRuntime, getEventByName, isEventAllowed, validateEventData };
|
package/dist/src/index.js
CHANGED
|
@@ -1,3 +1,149 @@
|
|
|
1
|
+
// src/adapters/bun-adapter.ts
|
|
2
|
+
import { Server as BunEngine } from "@socket.io/bun-engine";
|
|
3
|
+
function addCorsHeaders(response, request, corsConfig) {
|
|
4
|
+
const origin = request.headers.get("Origin");
|
|
5
|
+
if (!origin) {
|
|
6
|
+
return response;
|
|
7
|
+
}
|
|
8
|
+
const headers = new Headers(response.headers);
|
|
9
|
+
if (corsConfig === void 0 || corsConfig === true) {
|
|
10
|
+
headers.set("Access-Control-Allow-Origin", origin);
|
|
11
|
+
headers.set("Access-Control-Allow-Credentials", "true");
|
|
12
|
+
} else if (corsConfig === false) {
|
|
13
|
+
return response;
|
|
14
|
+
} else {
|
|
15
|
+
const allowedOrigin = corsConfig.origin;
|
|
16
|
+
if (allowedOrigin === true) {
|
|
17
|
+
headers.set("Access-Control-Allow-Origin", origin);
|
|
18
|
+
} else if (typeof allowedOrigin === "string" && allowedOrigin === origin) {
|
|
19
|
+
headers.set("Access-Control-Allow-Origin", origin);
|
|
20
|
+
} else if (Array.isArray(allowedOrigin) && allowedOrigin.includes(origin)) {
|
|
21
|
+
headers.set("Access-Control-Allow-Origin", origin);
|
|
22
|
+
}
|
|
23
|
+
if (corsConfig.credentials !== false) {
|
|
24
|
+
headers.set("Access-Control-Allow-Credentials", "true");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
headers.set("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
28
|
+
headers.set("Access-Control-Allow-Headers", "Content-Type");
|
|
29
|
+
return new Response(response.body, {
|
|
30
|
+
status: response.status,
|
|
31
|
+
statusText: response.statusText,
|
|
32
|
+
headers
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function createBunAdapter() {
|
|
36
|
+
const engine = new BunEngine();
|
|
37
|
+
let bunServer = null;
|
|
38
|
+
return {
|
|
39
|
+
runtime: "bun",
|
|
40
|
+
bind(io) {
|
|
41
|
+
io.bind(engine);
|
|
42
|
+
},
|
|
43
|
+
start({
|
|
44
|
+
port,
|
|
45
|
+
app,
|
|
46
|
+
corsConfig,
|
|
47
|
+
logger
|
|
48
|
+
}) {
|
|
49
|
+
const { websocket } = engine.handler();
|
|
50
|
+
bunServer = Bun.serve({
|
|
51
|
+
port,
|
|
52
|
+
idleTimeout: 30,
|
|
53
|
+
async fetch(req, server) {
|
|
54
|
+
const url = new URL(req.url);
|
|
55
|
+
if (url.pathname.startsWith("/socket.io")) {
|
|
56
|
+
if (req.method === "OPTIONS") {
|
|
57
|
+
return addCorsHeaders(
|
|
58
|
+
new Response(null, { status: 204 }),
|
|
59
|
+
req,
|
|
60
|
+
corsConfig
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
const response = await engine.handleRequest(req, server);
|
|
64
|
+
return addCorsHeaders(response, req, corsConfig);
|
|
65
|
+
}
|
|
66
|
+
return app.fetch(req);
|
|
67
|
+
},
|
|
68
|
+
websocket
|
|
69
|
+
});
|
|
70
|
+
logger.info({
|
|
71
|
+
message: `Server running on http://localhost:${port} (bun)`,
|
|
72
|
+
atFunction: "bunAdapter.start",
|
|
73
|
+
data: { port, runtime: "bun" }
|
|
74
|
+
});
|
|
75
|
+
return Promise.resolve();
|
|
76
|
+
},
|
|
77
|
+
stop() {
|
|
78
|
+
if (bunServer) {
|
|
79
|
+
bunServer.stop();
|
|
80
|
+
bunServer = null;
|
|
81
|
+
}
|
|
82
|
+
return Promise.resolve();
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// src/adapters/node-adapter.ts
|
|
88
|
+
import { createServer } from "http";
|
|
89
|
+
import { getRequestListener } from "@hono/node-server";
|
|
90
|
+
function createNodeAdapter() {
|
|
91
|
+
let httpServer = null;
|
|
92
|
+
let socketIoServer = null;
|
|
93
|
+
return {
|
|
94
|
+
runtime: "node",
|
|
95
|
+
bind(io) {
|
|
96
|
+
socketIoServer = io;
|
|
97
|
+
},
|
|
98
|
+
start({ port, app, io, logger }) {
|
|
99
|
+
const requestListener = getRequestListener(app.fetch);
|
|
100
|
+
httpServer = createServer(requestListener);
|
|
101
|
+
io.attach(httpServer);
|
|
102
|
+
return new Promise((resolve) => {
|
|
103
|
+
httpServer?.listen(port, () => {
|
|
104
|
+
logger.info({
|
|
105
|
+
message: `Server running on http://localhost:${port} (node)`,
|
|
106
|
+
atFunction: "nodeAdapter.start",
|
|
107
|
+
data: { port, runtime: "node" }
|
|
108
|
+
});
|
|
109
|
+
resolve();
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
},
|
|
113
|
+
stop() {
|
|
114
|
+
return new Promise((resolve) => {
|
|
115
|
+
if (socketIoServer) {
|
|
116
|
+
socketIoServer = null;
|
|
117
|
+
}
|
|
118
|
+
if (httpServer) {
|
|
119
|
+
httpServer.close(() => {
|
|
120
|
+
httpServer = null;
|
|
121
|
+
resolve();
|
|
122
|
+
});
|
|
123
|
+
} else {
|
|
124
|
+
resolve();
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/adapters/index.ts
|
|
132
|
+
function detectRuntime() {
|
|
133
|
+
if (typeof globalThis.Bun !== "undefined") {
|
|
134
|
+
return "bun";
|
|
135
|
+
}
|
|
136
|
+
return "node";
|
|
137
|
+
}
|
|
138
|
+
function createRuntimeAdapter(runtime) {
|
|
139
|
+
const resolved = runtime ?? detectRuntime();
|
|
140
|
+
const adapters = {
|
|
141
|
+
bun: createBunAdapter,
|
|
142
|
+
node: createNodeAdapter
|
|
143
|
+
};
|
|
144
|
+
return adapters[resolved]();
|
|
145
|
+
}
|
|
146
|
+
|
|
1
147
|
// src/create-dialogue.ts
|
|
2
148
|
import { Hono } from "hono";
|
|
3
149
|
import { Err as Err3 } from "slang-ts";
|
|
@@ -125,7 +271,6 @@ function createSilentLogger() {
|
|
|
125
271
|
}
|
|
126
272
|
|
|
127
273
|
// src/server.ts
|
|
128
|
-
import { Server as BunEngine } from "@socket.io/bun-engine";
|
|
129
274
|
import { cors as honoCors } from "hono/cors";
|
|
130
275
|
import { Server } from "socket.io";
|
|
131
276
|
|
|
@@ -717,38 +862,6 @@ function buildHonoCorsOptions(cors) {
|
|
|
717
862
|
credentials: cors.credentials ?? true
|
|
718
863
|
};
|
|
719
864
|
}
|
|
720
|
-
function addCorsHeaders(response, request, corsConfig) {
|
|
721
|
-
const origin = request.headers.get("Origin");
|
|
722
|
-
if (!origin) {
|
|
723
|
-
return response;
|
|
724
|
-
}
|
|
725
|
-
const headers = new Headers(response.headers);
|
|
726
|
-
if (corsConfig === void 0 || corsConfig === true) {
|
|
727
|
-
headers.set("Access-Control-Allow-Origin", origin);
|
|
728
|
-
headers.set("Access-Control-Allow-Credentials", "true");
|
|
729
|
-
} else if (corsConfig === false) {
|
|
730
|
-
return response;
|
|
731
|
-
} else {
|
|
732
|
-
const allowedOrigin = corsConfig.origin;
|
|
733
|
-
if (allowedOrigin === true) {
|
|
734
|
-
headers.set("Access-Control-Allow-Origin", origin);
|
|
735
|
-
} else if (typeof allowedOrigin === "string" && allowedOrigin === origin) {
|
|
736
|
-
headers.set("Access-Control-Allow-Origin", origin);
|
|
737
|
-
} else if (Array.isArray(allowedOrigin) && allowedOrigin.includes(origin)) {
|
|
738
|
-
headers.set("Access-Control-Allow-Origin", origin);
|
|
739
|
-
}
|
|
740
|
-
if (corsConfig.credentials !== false) {
|
|
741
|
-
headers.set("Access-Control-Allow-Credentials", "true");
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
headers.set("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
745
|
-
headers.set("Access-Control-Allow-Headers", "Content-Type");
|
|
746
|
-
return new Response(response.body, {
|
|
747
|
-
status: response.status,
|
|
748
|
-
statusText: response.statusText,
|
|
749
|
-
headers
|
|
750
|
-
});
|
|
751
|
-
}
|
|
752
865
|
function sendHistoryOnJoin(socket, roomId, roomConfig, historyManager) {
|
|
753
866
|
if (!(roomConfig?.syncHistoryOnJoin && historyManager)) {
|
|
754
867
|
return;
|
|
@@ -777,7 +890,7 @@ function createDialogueContext(io, connectedClients, roomManager) {
|
|
|
777
890
|
rooms: roomsRecord
|
|
778
891
|
};
|
|
779
892
|
}
|
|
780
|
-
function setupServer(app, config, historyManager) {
|
|
893
|
+
function setupServer(app, config, adapter, historyManager) {
|
|
781
894
|
const logger = config.logger ?? createDefaultLogger();
|
|
782
895
|
const hooks = config.hooks;
|
|
783
896
|
const connectedClients = /* @__PURE__ */ new Map();
|
|
@@ -786,8 +899,7 @@ function setupServer(app, config, historyManager) {
|
|
|
786
899
|
const honoCorsOptions = buildHonoCorsOptions(config.cors);
|
|
787
900
|
app.use("*", honoCors(honoCorsOptions));
|
|
788
901
|
const io = new Server({ cors: corsOptions });
|
|
789
|
-
|
|
790
|
-
io.bind(engine);
|
|
902
|
+
adapter.bind(io);
|
|
791
903
|
const getContextForHooks = () => {
|
|
792
904
|
return createDialogueContext(io, connectedClients, roomManager);
|
|
793
905
|
};
|
|
@@ -1168,46 +1280,20 @@ function setupServer(app, config, historyManager) {
|
|
|
1168
1280
|
}
|
|
1169
1281
|
});
|
|
1170
1282
|
});
|
|
1171
|
-
const { websocket } = engine.handler();
|
|
1172
1283
|
const port = config.port ?? 3e3;
|
|
1173
|
-
let bunServer = null;
|
|
1174
1284
|
return {
|
|
1175
1285
|
io,
|
|
1176
|
-
engine,
|
|
1177
1286
|
roomManager,
|
|
1178
1287
|
start() {
|
|
1179
|
-
|
|
1288
|
+
return adapter.start({
|
|
1180
1289
|
port,
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
if (req.method === "OPTIONS") {
|
|
1186
|
-
return addCorsHeaders(
|
|
1187
|
-
new Response(null, { status: 204 }),
|
|
1188
|
-
req,
|
|
1189
|
-
config.cors
|
|
1190
|
-
);
|
|
1191
|
-
}
|
|
1192
|
-
const response = await engine.handleRequest(req, server);
|
|
1193
|
-
return addCorsHeaders(response, req, config.cors);
|
|
1194
|
-
}
|
|
1195
|
-
return app.fetch(req);
|
|
1196
|
-
},
|
|
1197
|
-
websocket
|
|
1198
|
-
});
|
|
1199
|
-
logger.info({
|
|
1200
|
-
message: `Server running on http://localhost:${port}`,
|
|
1201
|
-
atFunction: "setupServer.start",
|
|
1202
|
-
data: { port }
|
|
1290
|
+
app,
|
|
1291
|
+
io,
|
|
1292
|
+
corsConfig: config.cors,
|
|
1293
|
+
logger
|
|
1203
1294
|
});
|
|
1204
|
-
return Promise.resolve();
|
|
1205
1295
|
},
|
|
1206
1296
|
stop() {
|
|
1207
|
-
if (bunServer) {
|
|
1208
|
-
bunServer.stop();
|
|
1209
|
-
bunServer = null;
|
|
1210
|
-
}
|
|
1211
1297
|
for (const client of connectedClients.values()) {
|
|
1212
1298
|
client.disconnect();
|
|
1213
1299
|
}
|
|
@@ -1219,7 +1305,7 @@ function setupServer(app, config, historyManager) {
|
|
|
1219
1305
|
atFunction: "setupServer.stop",
|
|
1220
1306
|
data: null
|
|
1221
1307
|
});
|
|
1222
|
-
return
|
|
1308
|
+
return adapter.stop();
|
|
1223
1309
|
},
|
|
1224
1310
|
/**
|
|
1225
1311
|
* Gets a connected client by socket ID
|
|
@@ -1283,6 +1369,7 @@ function createDialogue(config) {
|
|
|
1283
1369
|
onCleanup: config.hooks?.events?.onCleanup,
|
|
1284
1370
|
onLoad: config.hooks?.events?.onLoad
|
|
1285
1371
|
});
|
|
1372
|
+
const adapter = createRuntimeAdapter(config.runtime);
|
|
1286
1373
|
const {
|
|
1287
1374
|
io,
|
|
1288
1375
|
roomManager,
|
|
@@ -1293,7 +1380,7 @@ function createDialogue(config) {
|
|
|
1293
1380
|
getClientsByUserId,
|
|
1294
1381
|
getClientRooms: getClientRoomIds,
|
|
1295
1382
|
isUserInRoom
|
|
1296
|
-
} = setupServer(app, config, historyManager);
|
|
1383
|
+
} = setupServer(app, config, adapter, historyManager);
|
|
1297
1384
|
const dialogue = {
|
|
1298
1385
|
app,
|
|
1299
1386
|
io,
|
|
@@ -1402,8 +1489,10 @@ export {
|
|
|
1402
1489
|
createDialogue,
|
|
1403
1490
|
createHistoryManager,
|
|
1404
1491
|
createRateLimiter,
|
|
1492
|
+
createRuntimeAdapter,
|
|
1405
1493
|
createSilentLogger,
|
|
1406
1494
|
defineEvent,
|
|
1495
|
+
detectRuntime,
|
|
1407
1496
|
getEventByName,
|
|
1408
1497
|
isEventAllowed,
|
|
1409
1498
|
validateEventData
|