@randajan/koa-io-session 1.0.0 → 2.2.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.
@@ -29,122 +29,128 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  // src/index.js
30
30
  var index_exports = {};
31
31
  __export(index_exports, {
32
+ SessionBridge: () => SessionBridge,
32
33
  SessionStore: () => SessionStore,
33
- attachSession: () => attachSession,
34
+ bridgeSession: () => bridgeSession,
34
35
  default: () => index_default,
35
36
  generateUid: () => generateUid
36
37
  });
37
38
  module.exports = __toCommonJS(index_exports);
38
39
 
39
- // src/attachSession.js
40
+ // src/class/SessionBridge.js
41
+ var import_events2 = require("events");
40
42
  var import_http = require("http");
41
- var import_koa_session = __toESM(require("koa-session"), 1);
42
- var import_props3 = require("@randajan/props");
43
+ var import_props4 = require("@randajan/props");
43
44
 
44
45
  // src/tools.js
45
46
  var import_crypto = __toESM(require("crypto"), 1);
46
47
  var generateUid = (len = 16) => import_crypto.default.randomBytes(len).toString("base64url").slice(0, len);
47
- var isObject = (value) => !!value && typeof value === "object";
48
-
49
- // src/SessionStore.js
50
- var import_props = require("@randajan/props");
51
- var import_events = require("events");
52
- var wrapStore = (store) => {
53
- return {
54
- get: store.get.bind(store),
55
- set: store.set.bind(store),
56
- destroy: store.destroy.bind(store),
57
- touch: store.touch.bind(store)
58
- };
59
- };
60
- var formatState = (session2, maxAge, prevTTL, defaultTTL) => {
61
- const ttl = maxAge ?? prevTTL ?? defaultTTL;
62
- const expiresAt = Date.now() + ttl;
63
- return { session: session2, expiresAt, ttl };
48
+ var is = (type, any) => typeof any === type;
49
+ var valid = (type, any, req = false, msg = "argument") => {
50
+ if (any == null) {
51
+ if (!req) {
52
+ return;
53
+ }
54
+ throw new Error(`${msg} require typeof '${type}'`);
55
+ }
56
+ if (is(type, any)) {
57
+ return any;
58
+ }
59
+ throw new Error(`${msg} is not typeof '${type}'`);
64
60
  };
65
- var SessionStore = class extends Map {
66
- constructor(defaultTTL = 864e5, eventEmitterOpt = {}) {
67
- super();
68
- (0, import_props.solid)(this, "defaultTTL", defaultTTL);
69
- (0, import_props.solid)(this, "event", new import_events.EventEmitter(eventEmitterOpt));
61
+ var validRange = (min, max, any, req = false, msg = "argument") => {
62
+ const num = valid("number", any, req, msg);
63
+ if (num == null) {
64
+ return;
70
65
  }
71
- on(eventName, callback) {
72
- return this.event.on(eventName, callback);
66
+ if (num < min) {
67
+ throw new Error(`${msg} must be greater than ${min}`);
73
68
  }
74
- get(sid) {
75
- const d = super.get(sid);
76
- if (!d) {
77
- return;
78
- }
79
- if (Date.now() < d.expiresAt) {
80
- return d.session;
81
- }
82
- this.delete(sid);
69
+ if (num > max) {
70
+ throw new Error(`${msg} must be less than ${max}`);
83
71
  }
84
- touch(sid, maxAge) {
85
- const { defaultTTL } = this;
86
- const d = super.get(sid);
87
- if (!d) {
88
- return false;
89
- }
90
- super.set(sid, formatState(d.session, maxAge, d.ttl, defaultTTL));
91
- this.event.emit("touch", this, sid);
92
- return true;
72
+ return num;
73
+ };
74
+ var validInterval = (any, req = false, msg = "argument") => {
75
+ return validRange(10, 2147483647, any, req, msg);
76
+ };
77
+ var validObject = (any, req = false, msg = "argument") => {
78
+ const obj = valid("object", any, req, msg);
79
+ if (obj == null) {
80
+ return;
93
81
  }
94
- set(sid, session2, maxAge) {
95
- const { defaultTTL } = this;
96
- const d = super.get(sid);
97
- if (session2 == null) {
98
- return !d || this.destroy(sid);
99
- }
100
- super.set(sid, formatState(session2, maxAge, d?.ttl, defaultTTL));
101
- this.event.emit("set", this, sid, !d);
102
- return true;
82
+ if (!Array.isArray(obj)) {
83
+ return obj;
103
84
  }
104
- delete(sid) {
105
- return this.destroy(sid);
85
+ throw new Error(`${msg} must be object, not array`);
86
+ };
87
+ var validStore = (store) => {
88
+ const missing = [];
89
+ if (!is("function", store?.get)) {
90
+ missing.push("get()");
106
91
  }
107
- destroy(sid) {
108
- if (this.has(sid)) {
109
- super.delete(sid);
110
- this.event.emit("destroy", this, sid);
111
- }
112
- return true;
92
+ if (!is("function", store?.set)) {
93
+ missing.push("set()");
113
94
  }
114
- cleanup() {
115
- const now = Date.now();
116
- let cleared = 0;
117
- for (const [sid, d] of this.entries()) {
118
- if (now < d.expiresAt) {
119
- continue;
120
- }
121
- if (this.destroy(sid)) {
122
- cleared++;
123
- }
124
- }
125
- if (cleared) {
126
- this.event.emit("cleanup", this, cleared);
127
- }
128
- return cleared;
95
+ if (!is("function", store?.destroy)) {
96
+ missing.push("destroy()");
129
97
  }
130
- autoCleanup(interval) {
131
- const { defaultTTL } = this;
132
- if (!interval) {
133
- interval = defaultTTL / 10;
134
- }
135
- const tid = setInterval(() => {
136
- this.cleanup();
137
- }, interval);
138
- return (_) => clearInterval(tid);
98
+ if (!is("function", store?.on)) {
99
+ missing.push("on()");
100
+ }
101
+ if (missing.length) {
102
+ throw new TypeError(`store is missing required API: ${missing.join(", ")}`);
139
103
  }
104
+ return store;
105
+ };
106
+
107
+ // src/httpSession.js
108
+ var import_koa_session = __toESM(require("koa-session"), 1);
109
+
110
+ // src/wrappers.js
111
+ var wrapStore = (store) => {
112
+ return {
113
+ get: store.get.bind(store),
114
+ set: store.set.bind(store),
115
+ destroy: store.destroy.bind(store)
116
+ };
117
+ };
118
+ var wrapExternalKey = (opt, onSet) => {
119
+ const { externalKey: base, key, signed } = opt;
120
+ const get = base?.get ? (ctx) => base.get(ctx) : (ctx) => ctx.cookies.get(key, { signed });
121
+ const setRaw = base?.set ? (ctx, sid) => base.set(ctx, sid) : (ctx, sid) => ctx.cookies.set(key, sid, opt);
122
+ const set = typeof onSet != "function" ? setRaw : (ctx, sid) => {
123
+ setRaw(ctx, sid);
124
+ onSet(ctx, sid);
125
+ };
126
+ return { get, set };
127
+ };
128
+
129
+ // src/httpSession.js
130
+ var createKoaSession = (opt, app, onSet) => {
131
+ const store = wrapStore(opt.store);
132
+ const externalKey = wrapExternalKey(opt, onSet);
133
+ const koaSession = (0, import_koa_session.default)({ ...opt, store, externalKey }, app);
134
+ return [koaSession, externalKey];
135
+ };
136
+ var createClientCookie = (opt) => {
137
+ const { key, maxAge, signed, path, secure, sameSite, httpOnly } = opt;
138
+ return wrapExternalKey({
139
+ key,
140
+ signed,
141
+ maxAge,
142
+ path: path ?? "/",
143
+ secure,
144
+ sameSite,
145
+ httpOnly: httpOnly ?? true,
146
+ overwrite: true
147
+ });
140
148
  };
141
149
 
142
150
  // src/socketSession.js
143
- var import_props2 = require("@randajan/props");
144
- var import_queue = require("@randajan/queue");
151
+ var import_props = require("@randajan/props");
145
152
  var sidLocks = /* @__PURE__ */ new Map();
146
- var touchQueues = /* @__PURE__ */ new Map();
147
- var createSessionCtx = (sessionId, session2, socket) => (0, import_props2.solids)({ session: session2 }, { sessionId, socket });
153
+ var createSessionCtx = (sessionId, session2, socket) => (0, import_props.solids)({ session: session2 }, { sessionId, socket });
148
154
  var createSessionHash = (session2) => {
149
155
  try {
150
156
  return JSON.stringify(session2 ?? null);
@@ -179,150 +185,305 @@ var withLock = async (task, socket, ...args) => {
179
185
  }
180
186
  }
181
187
  };
182
- var getTouchQueue = (sid, store) => {
183
- const existing = touchQueues.get(sid);
184
- if (existing) {
185
- return existing;
186
- }
187
- const queue = (0, import_queue.createQueue)(async (touchMaxAge) => {
188
- try {
189
- await store.touch(sid, touchMaxAge);
190
- } catch {
191
- }
192
- if (!queue.isPending) {
193
- touchQueues.delete(sid);
194
- }
195
- }, { pass: "last", softMs: 1e3, hardMs: 5e3 });
196
- touchQueues.set(sid, queue);
197
- return queue;
198
- };
199
- var scheduleTouch = (sid, store, maxAge) => {
200
- if (typeof store?.touch !== "function") {
201
- return;
188
+ var applyOnMissing = (onMissing) => {
189
+ if (onMissing instanceof Error) {
190
+ throw onMissing;
202
191
  }
203
- const queue = getTouchQueue(sid, store);
204
- queue(maxAge);
205
- };
206
- var clearTouchQueue = (sid) => {
207
- const queue = touchQueues.get(sid);
208
- if (!queue) {
209
- return false;
210
- }
211
- queue.flush();
212
- touchQueues.delete(sid);
213
- return true;
192
+ if (is("function", onMissing)) {
193
+ return onMissing();
194
+ }
195
+ return onMissing;
214
196
  };
215
- var runSessionHandler = async (socket, handler, opt = {}) => {
197
+ var runSessionHandler = async (socket, handler, store, onMissing) => {
216
198
  const sid = socket.sessionId;
217
- const { store, maxAge } = opt;
218
199
  const current = await store.get(sid);
219
- if (!isObject(current)) {
220
- throw new Error("Session not found");
200
+ if (!current) {
201
+ return applyOnMissing(onMissing);
221
202
  }
222
203
  const session2 = current;
223
204
  const sessionCtx = createSessionCtx(sid, session2, socket);
224
205
  const originalHash = createSessionHash(sessionCtx.session);
225
206
  const result = await handler(sessionCtx, socket);
226
207
  if (sessionCtx.session == null) {
227
- clearTouchQueue(sid);
228
208
  await store.destroy(sid);
229
209
  return result;
230
210
  }
231
- if (!isObject(sessionCtx.session)) {
232
- throw new TypeError("sessionCtx.session must be an object or null");
233
- }
211
+ sessionCtx.session = validObject(sessionCtx.session, false, "session");
234
212
  if (isSessionHashChanged(originalHash, sessionCtx.session)) {
235
- clearTouchQueue(sid);
236
- await store.set(sid, sessionCtx.session, maxAge);
237
- } else {
238
- scheduleTouch(sid, store, maxAge);
213
+ await store.set(sid, sessionCtx.session);
239
214
  }
240
215
  return result;
241
216
  };
242
- var applySessionHandler = async (socket, handler, opt = {}) => {
217
+ var applySessionHandler = async (socket, handler, store, onMissing) => {
243
218
  if (typeof handler !== "function") {
244
219
  throw new TypeError("socket.withSession(handler) requires a function");
245
220
  }
246
221
  if (!socket.sessionId) {
247
- throw new Error("Missing session id");
222
+ return applyOnMissing(onMissing);
248
223
  }
249
- return withLock(runSessionHandler, socket, handler, opt);
224
+ return withLock(runSessionHandler, socket, handler, store, onMissing);
250
225
  };
251
226
 
252
- // src/attachSession.js
253
- var validateStore = (store) => {
254
- const missing = [];
255
- if (typeof store?.get !== "function") {
256
- missing.push("get()");
227
+ // src/class/SessionStore.js
228
+ var import_props2 = require("@randajan/props");
229
+ var import_events = require("events");
230
+
231
+ // src/const.js
232
+ var ms = {
233
+ s: (v = 1) => v * 1e3,
234
+ m: (v = 1) => ms.s(v * 60),
235
+ h: (v = 1) => ms.m(v * 60),
236
+ d: (v = 1) => ms.h(v * 24),
237
+ w: (v = 1) => ms.d(v * 7),
238
+ M: (v = 1) => ms.d(v * 30),
239
+ y: (v = 1) => ms.d(v * 365)
240
+ };
241
+ var _customOptKeys = /* @__PURE__ */ new Set([
242
+ "store",
243
+ "autoCleanup",
244
+ "autoCleanupMs",
245
+ "clientKey",
246
+ "clientMaxAge",
247
+ "clientAlwaysRoll"
248
+ ]);
249
+
250
+ // src/class/SessionStore.js
251
+ var formatState = (session2, maxAge, prevTTL, maxAgeDefault) => {
252
+ const ttl = maxAge ?? prevTTL ?? maxAgeDefault;
253
+ const expiresAt = Date.now() + ttl;
254
+ return { session: session2, expiresAt, ttl };
255
+ };
256
+ var SessionStore = class extends Map {
257
+ constructor(opt = {}) {
258
+ super();
259
+ const maxAge = validRange(ms.s(), ms.y(), opt.maxAge, false, "maxAge") ?? ms.M();
260
+ const autoCleanup = valid("boolean", opt.autoCleanup, false, "autoCleanup") ?? true;
261
+ const autoCleanupMs = validInterval(opt.autoCleanupMs, false, "autoCleanupMs") ?? Math.max(ms.s(), Math.min(ms.h(), maxAge / 10));
262
+ (0, import_props2.solid)(this, "maxAge", maxAge);
263
+ (0, import_props2.solid)(this, "event", new import_events.EventEmitter());
264
+ if (!autoCleanup) {
265
+ return;
266
+ }
267
+ setInterval((_) => this.cleanup(), autoCleanupMs);
257
268
  }
258
- if (typeof store?.set !== "function") {
259
- missing.push("set()");
269
+ on(eventName, callback) {
270
+ return this.event.on(eventName, callback);
260
271
  }
261
- if (typeof store?.destroy !== "function") {
262
- missing.push("destroy()");
272
+ get(sid) {
273
+ const d = super.get(sid);
274
+ if (!d) {
275
+ return;
276
+ }
277
+ if (Date.now() < d.expiresAt) {
278
+ return d.session;
279
+ }
280
+ this.delete(sid);
263
281
  }
264
- if (typeof store?.touch !== "function") {
265
- missing.push("touch()");
282
+ set(sid, session2, maxAge) {
283
+ const d = super.get(sid);
284
+ if (session2 == null) {
285
+ return !d || this.destroy(sid);
286
+ }
287
+ super.set(sid, formatState(session2, maxAge, d?.ttl, this.maxAge));
288
+ this.event.emit("set", this, sid, !d);
289
+ return true;
266
290
  }
267
- if (typeof store?.on !== "function") {
268
- missing.push("on()");
291
+ delete(sid) {
292
+ return this.destroy(sid);
269
293
  }
270
- if (missing.length) {
271
- throw new TypeError(`attachSession options.store is missing required API: ${missing.join(", ")}`);
294
+ destroy(sid) {
295
+ if (this.has(sid)) {
296
+ super.delete(sid);
297
+ this.event.emit("destroy", this, sid);
298
+ }
299
+ return true;
300
+ }
301
+ cleanup() {
302
+ const now = Date.now();
303
+ let cleared = 0;
304
+ for (const [sid, d] of this.entries()) {
305
+ if (now < d.expiresAt) {
306
+ continue;
307
+ }
308
+ if (this.destroy(sid)) {
309
+ cleared++;
310
+ }
311
+ }
312
+ if (cleared) {
313
+ this.event.emit("cleanup", this, cleared);
314
+ }
315
+ return cleared;
272
316
  }
273
317
  };
274
- var attachSession = (app, io, opt = {}) => {
275
- opt.signed = "signed" in opt ? !!opt.signed : true;
276
- if (!app.keys) {
277
- app.keys = Array(6).fill().map(() => generateUid(12));
278
- }
279
- if (!opt.key) {
280
- opt.key = generateUid(12);
281
- }
282
- if (!opt.maxAge) {
283
- opt.maxAge = 864e5;
284
- }
285
- const { key, signed, externalKey } = opt;
286
- const store = opt.store || new SessionStore(opt.maxAge);
287
- validateStore(store);
288
- opt.store = wrapStore(store);
289
- const getSID = externalKey ? (ctx) => externalKey.get(ctx) : (ctx) => ctx.cookies.get(key, { signed });
290
- const koaSession = (0, import_koa_session.default)(opt, app);
291
- app.use(koaSession);
292
- app.use(async (ctx, next) => {
293
- (0, import_props3.solid)(ctx, "sessionId", getSID(ctx));
294
- await next();
295
- });
296
- io.use(async (socket, next) => {
297
- const req = socket.request;
298
- const res = req.res ?? socket.response ?? new import_http.ServerResponse(req);
299
- const ctx = app.createContext(req, res);
300
- await koaSession(ctx, async () => {
318
+
319
+ // src/formatOptions.js
320
+ var pickKoaOpt = (rawOpt) => {
321
+ const koaOpt = {};
322
+ for (const key in rawOpt) {
323
+ if (_customOptKeys.has(key)) {
324
+ continue;
325
+ }
326
+ koaOpt[key] = rawOpt[key];
327
+ }
328
+ koaOpt.key = valid("string", koaOpt.key, false, "key") ?? generateUid(12);
329
+ koaOpt.maxAge = validRange(ms.s(), ms.y(), koaOpt.maxAge, false, "maxAge") ?? ms.M();
330
+ koaOpt.signed = valid("boolean", koaOpt.signed, false, "signed") ?? true;
331
+ koaOpt.store = validStore(rawOpt.store || new SessionStore(rawOpt));
332
+ return koaOpt;
333
+ };
334
+ var formatOptions = (opt = {}) => {
335
+ opt = validObject(opt, true, "options");
336
+ const koaOpt = pickKoaOpt(opt);
337
+ const clientKey = valid("string", opt.clientKey) ?? `${koaOpt.key}.cid`;
338
+ const clientMaxAge = validInterval(opt.clientMaxAge, false, "clientMaxAge") ?? ms.y();
339
+ const clientAlwaysRoll = valid("boolean", opt.clientAlwaysRoll, false, "clientAlwaysRoll") ?? true;
340
+ const clientOpt = { ...koaOpt, key: clientKey, maxAge: clientMaxAge };
341
+ return {
342
+ koaOpt,
343
+ clientOpt,
344
+ clientAlwaysRoll
345
+ };
346
+ };
347
+
348
+ // src/class/Bridge.js
349
+ var import_props3 = require("@randajan/props");
350
+ var Bridge = class {
351
+ constructor(opt = {}) {
352
+ const { onSet, onDelete } = opt;
353
+ (0, import_props3.solids)(this, {
354
+ onSet,
355
+ onDelete,
356
+ s2c: /* @__PURE__ */ new Map(),
357
+ c2s: /* @__PURE__ */ new Map()
301
358
  });
302
- (0, import_props3.solid)(socket, "sessionId", getSID(ctx));
303
- (0, import_props3.solid)(socket, "withSession", async (handler) => {
304
- return applySessionHandler(socket, handler, opt);
305
- }, false);
306
- await next();
307
- });
308
- io.on("connection", (socket) => {
309
- const sid = socket.sessionId;
310
- if (sid) {
311
- socket.join(`sessionId:${sid}`);
359
+ }
360
+ set(cid, sid) {
361
+ if (!cid || !sid) {
362
+ return false;
312
363
  }
313
- });
314
- store.on("destroy", (_store, sid) => {
364
+ const byCid = this.deleteByCid(cid, sid);
365
+ const bySid = this.deleteBySid(sid, cid);
366
+ if (!byCid && !bySid) {
367
+ return false;
368
+ }
369
+ this.c2s.set(cid, sid);
370
+ this.s2c.set(sid, cid);
371
+ this.onSet({ clientId: cid, sessionId: sid });
372
+ return true;
373
+ }
374
+ getByCid(cid) {
375
+ return this.c2s.get(cid);
376
+ }
377
+ getBySid(sid) {
378
+ return this.s2c.get(sid);
379
+ }
380
+ deleteBySid(sid, skipIf) {
381
+ const cid = this.getBySid(sid);
382
+ if (!cid) {
383
+ return true;
384
+ }
385
+ if (skipIf && cid == skipIf) {
386
+ return false;
387
+ }
388
+ this.s2c.delete(sid);
389
+ this.c2s.delete(cid);
390
+ this.onDelete({ clientId: cid, sessionId: sid });
391
+ return true;
392
+ }
393
+ deleteByCid(cid, skipIf) {
394
+ const sid = this.getByCid(cid);
315
395
  if (!sid) {
316
- return;
396
+ return true;
317
397
  }
318
- clearTouchQueue(sid);
319
- const room = io.in(`sessionId:${sid}`);
320
- room.emit("session:destroy");
321
- setTimeout((_) => room.disconnectSockets(true), 200);
322
- });
323
- return store;
398
+ if (skipIf && sid == skipIf) {
399
+ return false;
400
+ }
401
+ this.c2s.delete(cid);
402
+ this.s2c.delete(sid);
403
+ this.onDelete({ clientId: cid, sessionId: sid });
404
+ return true;
405
+ }
406
+ };
407
+
408
+ // src/class/SessionBridge.js
409
+ var SessionBridge = class extends import_events2.EventEmitter {
410
+ constructor(app, io, opt = {}) {
411
+ super();
412
+ if (!app.keys) {
413
+ app.keys = Array(6).fill().map(() => generateUid(12));
414
+ }
415
+ const o = formatOptions(opt);
416
+ const { store } = o.koaOpt;
417
+ const brg = new Bridge({
418
+ onSet: (pair) => this.emit("sessionStart", pair),
419
+ onDelete: (pair) => this.emit("sessionEnd", pair)
420
+ });
421
+ const cc = createClientCookie(o.clientOpt);
422
+ const [koaSession, sc] = createKoaSession(o.koaOpt, app, (ctx, sid) => {
423
+ const cid = cc.get(ctx);
424
+ brg.set(cid, sid);
425
+ });
426
+ const regenerateSid = async (ctx, cid, reqSid) => {
427
+ if (cid == null || reqSid == null) {
428
+ return;
429
+ }
430
+ const brgSid = brg.getByCid(cid);
431
+ if (brgSid == reqSid) {
432
+ return;
433
+ } else if (brgSid) {
434
+ sc.set(ctx, brgSid);
435
+ return;
436
+ }
437
+ if (brg.getBySid(reqSid)) {
438
+ return;
439
+ }
440
+ if (!await store.get(reqSid)) {
441
+ return;
442
+ }
443
+ brg.set(cid, reqSid);
444
+ };
445
+ app.use(koaSession);
446
+ app.use(async (ctx, next) => {
447
+ let cid = cc.get(ctx);
448
+ const sid = sc.get(ctx);
449
+ if (!cid) {
450
+ cc.set(ctx, cid = generateUid(24));
451
+ } else if (o.clientAlwaysRoll) {
452
+ cc.set(ctx, cid);
453
+ }
454
+ await regenerateSid(ctx, cid, sid);
455
+ (0, import_props4.solid)(ctx, "clientId", cid);
456
+ (0, import_props4.virtual)(ctx, "sessionId", (_) => brg.getByCid(cid));
457
+ await next();
458
+ });
459
+ io.use(async (socket, next) => {
460
+ const req = socket.request;
461
+ const res = req.res ?? socket.response ?? new import_http.ServerResponse(req);
462
+ const ctx = app.createContext(req, res);
463
+ await koaSession(ctx, async () => {
464
+ });
465
+ const cid = cc.get(ctx);
466
+ const sid = sc.get(ctx);
467
+ await regenerateSid(ctx, cid, sid);
468
+ (0, import_props4.solid)(socket, "clientId", cid);
469
+ (0, import_props4.virtual)(socket, "sessionId", (_) => brg.getByCid(cid));
470
+ (0, import_props4.solid)(socket, "withSession", async function(handler, onMissing) {
471
+ const onm = arguments.length > 1 ? onMissing : new Error("Session missing");
472
+ return applySessionHandler(socket, handler, store, onm);
473
+ }, false);
474
+ await next();
475
+ });
476
+ store.on("destroy", (_store, sid) => {
477
+ if (!sid) {
478
+ return;
479
+ }
480
+ brg.deleteBySid(sid);
481
+ });
482
+ (0, import_props4.solid)(this, "store", store);
483
+ }
324
484
  };
325
485
 
326
486
  // src/index.js
327
- var index_default = attachSession;
487
+ var bridgeSession = (app, io, opt = {}) => new SessionBridge(app, io, opt);
488
+ var index_default = bridgeSession;
328
489
  //# sourceMappingURL=index.js.map