@uploadista/event-emitter-websocket 0.0.3 → 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/.turbo/turbo-build.log +19 -2
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +32 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +31 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -0
- package/package.json +5 -4
- package/tsdown.config.ts +11 -0
- package/dist/test-generic.d.ts +0 -36
- package/dist/test-generic.d.ts.map +0 -1
- package/dist/test-generic.js +0 -12
- package/dist/websocket-event-emitter.d.ts +0 -7
- package/dist/websocket-event-emitter.d.ts.map +0 -1
- package/dist/websocket-event-emitter.js +0 -57
- package/dist/websocket-manager.d.ts +0 -27
- package/dist/websocket-manager.d.ts.map +0 -1
- package/dist/websocket-manager.js +0 -97
- package/dist/websocket-server.d.ts +0 -10
- package/dist/websocket-server.d.ts.map +0 -1
- package/dist/websocket-server.js +0 -56
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
> @uploadista/event-emitter-websocket@0.0.
|
|
4
|
-
>
|
|
3
|
+
> @uploadista/event-emitter-websocket@0.0.3 build /Users/denislaboureyras/Documents/uploadista/dev/uploadista-workspace/uploadista-sdk/packages/event-emitters/websocket
|
|
4
|
+
> tsdown
|
|
5
5
|
|
|
6
|
+
[34mℹ[39m tsdown [2mv0.15.9[22m powered by rolldown [2mv1.0.0-beta.44[22m
|
|
7
|
+
[34mℹ[39m Using tsdown config: [4m/Users/denislaboureyras/Documents/uploadista/dev/uploadista-workspace/uploadista-sdk/packages/event-emitters/websocket/tsdown.config.ts[24m
|
|
8
|
+
[34mℹ[39m entry: [34msrc/index.ts[39m
|
|
9
|
+
[34mℹ[39m tsconfig: [34mtsconfig.json[39m
|
|
10
|
+
[34mℹ[39m Build start
|
|
11
|
+
[34mℹ[39m Cleaning 7 files
|
|
12
|
+
[34mℹ[39m [33m[CJS][39m [2mdist/[22m[1mindex.cjs[22m [2m2.67 kB[22m [2m│ gzip: 1.17 kB[22m
|
|
13
|
+
[34mℹ[39m [33m[CJS][39m 1 files, total: 2.67 kB
|
|
14
|
+
[34mℹ[39m [34m[ESM][39m [2mdist/[22m[1mindex.js[22m [2m2.11 kB[22m [2m│ gzip: 0.94 kB[22m
|
|
15
|
+
[34mℹ[39m [34m[ESM][39m [2mdist/[22mindex.js.map [2m9.61 kB[22m [2m│ gzip: 2.72 kB[22m
|
|
16
|
+
[34mℹ[39m [34m[ESM][39m [2mdist/[22mindex.d.ts.map [2m1.38 kB[22m [2m│ gzip: 0.50 kB[22m
|
|
17
|
+
[34mℹ[39m [34m[ESM][39m [2mdist/[22m[32m[1mindex.d.ts[22m[39m [2m2.10 kB[22m [2m│ gzip: 0.54 kB[22m
|
|
18
|
+
[34mℹ[39m [34m[ESM][39m 4 files, total: 15.19 kB
|
|
19
|
+
[34mℹ[39m [33m[CJS][39m [2mdist/[22mindex.d.cts.map [2m1.38 kB[22m [2m│ gzip: 0.50 kB[22m
|
|
20
|
+
[34mℹ[39m [33m[CJS][39m [2mdist/[22m[32m[1mindex.d.cts[22m[39m [2m2.10 kB[22m [2m│ gzip: 0.54 kB[22m
|
|
21
|
+
[34mℹ[39m [33m[CJS][39m 2 files, total: 3.47 kB
|
|
22
|
+
[32m✔[39m Build complete in [32m9685ms[39m
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`@uploadista/core/errors`);c=s(c);let l=require(`@uploadista/core/types`);l=s(l);let u=require(`effect`);u=s(u);const d=u.Effect.gen(function*(){let e=yield*l.EventBroadcasterService,t=new Map,n=new Map,r=(e,r)=>{let i=n.get(e);if(i)for(let e of i){let n=t.get(e);if(n&&n.readyState===1)try{n.send(r)}catch(t){console.warn(`Failed to send message to connection ${e}:`,t),s(e)}else s(e)}};yield*e.subscribe(`uploadista:events`,e=>{try{let{eventKey:t,message:n}=JSON.parse(e);r(t,n)}catch(e){console.warn(`Failed to parse broadcast message:`,e)}}).pipe(u.Effect.catchAll(e=>(console.error(`Failed to subscribe to broadcast events:`,e),u.Effect.void)));let i=e=>t.get(e)||null,a=()=>t,o=(e,n)=>{t.set(e,n)},s=e=>{t.delete(e);for(let[t,r]of n.entries())r.delete(e),r.size===0&&n.delete(t)};return{getConnection:i,getConnections:a,addConnection:o,removeConnection:s,subscribeToEvents:(e,t)=>{n.has(e)||n.set(e,new Set),n.get(e)?.add(t)},unsubscribeFromEvents:(e,t)=>{let r=n.get(e);r&&(r.delete(t),r.size===0&&n.delete(e))},emitToEvents:(t,n)=>{u.Effect.runPromise(e.publish(`uploadista:events`,JSON.stringify({eventKey:t,message:n}))).catch(e=>{console.error(`Failed to publish event to broadcaster:`,e)})}}});var f=class extends u.Context.Tag(`BaseWebSocketManagerService`)(){};const p=u.Layer.effect(f,d);function m(e){return{emit:(t,n)=>u.Effect.try({try:()=>{e.emitToEvents(t,n)},catch:e=>c.UploadistaError.fromCode(`UNKNOWN_ERROR`,{cause:e})}),subscribe:(t,n)=>u.Effect.try({try:()=>{e.addConnection(n.id,n),e.subscribeToEvents(t,n.id),n.send(JSON.stringify({type:`subscribed`,payload:{eventKey:t},timestamp:new Date().toISOString()}))},catch:e=>c.UploadistaError.fromCode(`UNKNOWN_ERROR`,{cause:e})}),unsubscribe:t=>u.Effect.try({try:()=>{let n=e.getConnections();for(let[r]of n)e.unsubscribeFromEvents(t,r)},catch:e=>c.UploadistaError.fromCode(`UNKNOWN_ERROR`,{cause:e})})}}const h=u.Effect.gen(function*(){return m(yield*f)}),g=e=>u.Layer.effect(l.BaseEventEmitterService,h).pipe(u.Layer.provide(p),u.Layer.provide(e));exports.WebSocketManagerService=f,exports.makeBaseEventEmitter=h,exports.makeWebSocketManager=d,exports.webSocketEventEmitter=g,exports.webSocketManager=p;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { BaseEventEmitter, BaseEventEmitterService, EventBroadcasterService, WebSocketConnection } from "@uploadista/core/types";
|
|
2
|
+
import { Context, Effect, Layer } from "effect";
|
|
3
|
+
|
|
4
|
+
//#region src/websocket-manager.d.ts
|
|
5
|
+
interface WebSocketManager {
|
|
6
|
+
readonly getConnection: (key: string) => WebSocketConnection | null;
|
|
7
|
+
readonly getConnections: () => Map<string, WebSocketConnection>;
|
|
8
|
+
readonly addConnection: (key: string, connection: WebSocketConnection) => void;
|
|
9
|
+
readonly removeConnection: (key: string) => void;
|
|
10
|
+
readonly subscribeToEvents: (eventKey: string, connectionId: string) => void;
|
|
11
|
+
readonly unsubscribeFromEvents: (eventKey: string, connectionId: string) => void;
|
|
12
|
+
readonly emitToEvents: (eventKey: string, event: string) => void;
|
|
13
|
+
}
|
|
14
|
+
declare const makeWebSocketManager: Effect.Effect<{
|
|
15
|
+
getConnection: (key: string) => WebSocketConnection | null;
|
|
16
|
+
getConnections: () => Map<string, WebSocketConnection>;
|
|
17
|
+
addConnection: (key: string, connection: WebSocketConnection) => void;
|
|
18
|
+
removeConnection: (key: string) => void;
|
|
19
|
+
subscribeToEvents: (eventKey: string, connectionId: string) => void;
|
|
20
|
+
unsubscribeFromEvents: (eventKey: string, connectionId: string) => void;
|
|
21
|
+
emitToEvents: (eventKey: string, message: string) => void;
|
|
22
|
+
}, never, EventBroadcasterService>;
|
|
23
|
+
declare const WebSocketManagerService_base: Context.TagClass<WebSocketManagerService, "BaseWebSocketManagerService", WebSocketManager>;
|
|
24
|
+
declare class WebSocketManagerService extends WebSocketManagerService_base {}
|
|
25
|
+
declare const webSocketManager: Layer.Layer<WebSocketManagerService, never, EventBroadcasterService>;
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/websocket-event-emitter.d.ts
|
|
28
|
+
declare const makeBaseEventEmitter: Effect.Effect<BaseEventEmitter, never, WebSocketManagerService>;
|
|
29
|
+
declare const webSocketEventEmitter: (eventBroadcaster: Layer.Layer<EventBroadcasterService>) => Layer.Layer<BaseEventEmitterService, never, never>;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { type WebSocketManager, WebSocketManagerService, makeBaseEventEmitter, makeWebSocketManager, webSocketEventEmitter, webSocketManager };
|
|
32
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/websocket-manager.ts","../src/websocket-event-emitter.ts"],"sourcesContent":[],"mappings":";;;;UAKiB,gBAAA;EAAA,SAAA,aAAgB,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GACU,mBADV,GAAA,IAAA;EACU,SAAA,cAAA,EAAA,GAAA,GACV,GADU,CAAA,MAAA,EACE,mBADF,CAAA;EACE,SAAA,aAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,UAAA,EAG7B,mBAH6B,EAAA,GAAA,IAAA;EAAZ,SAAA,gBAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAGjB,SAAA,iBAAA,EAAA,CAAA,QAAA,EAAA,MAAA,EAAA,YAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAmB,SAAA,qBAAA,EAAA,CAAA,QAAA,EAAA,MAAA,EAAA,YAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAWtB,SAAA,YAAA,EAiHX,CAAA,QAAA,EAAA,MAAA,EAAA,KAAA,EAAA,MAAA,EAAA,GAAA,IAAA;;AA/DuC,cAlD5B,oBAkD4B,EAlDR,MAAA,CAAA,MAkDQ,CAAA;EAAZ,aAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAJU,mBAIV,GAAA,IAAA;EAMb,cAAA,EAAA,GAAA,GANa,GAMb,CAAA,MAAA,EANyB,mBAMzB,CAAA;2CAAA;EAxDiB,gBAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAA,iBAAA,EAAA,CAAA,QAAA,EAAA,MAAA,EAAA,YAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAiH9B,qBAAA,EAAA,CAAA,QAAA,EAAA,MAAA,EAAA,YAAA,EAAA,MAAA,EAAA,GAAA,IAAA;;;cAAA;cAGU,uBAAA,SAAgC,4BAAA;AAKhC,cAAA,gBAGZ,EAH4B,KAAA,CAAA,KAG5B,CAH4B,uBAG5B,EAAA,KAAA,EAH4B,uBAG5B,CAAA;;;AA5IgB,cCkEJ,oBDlEoB,ECkEA,MAAA,CAAA,MDlEA,CCkEA,gBDlEA,EAAA,KAAA,ECkEA,uBDlEA,CAAA;AACU,cCsE9B,qBDtE8B,EAAA,CAAA,gBAAA,ECuEvB,KAAA,CAAM,KDvEiB,CCuEX,uBDvEW,CAAA,EAAA,GCuEa,KAAA,CAAA,KDvEb,CCuEa,uBDvEb,EAAA,KAAA,EAAA,KAAA,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { BaseEventEmitter, BaseEventEmitterService, EventBroadcasterService, WebSocketConnection } from "@uploadista/core/types";
|
|
2
|
+
import { Context, Effect, Layer } from "effect";
|
|
3
|
+
|
|
4
|
+
//#region src/websocket-manager.d.ts
|
|
5
|
+
interface WebSocketManager {
|
|
6
|
+
readonly getConnection: (key: string) => WebSocketConnection | null;
|
|
7
|
+
readonly getConnections: () => Map<string, WebSocketConnection>;
|
|
8
|
+
readonly addConnection: (key: string, connection: WebSocketConnection) => void;
|
|
9
|
+
readonly removeConnection: (key: string) => void;
|
|
10
|
+
readonly subscribeToEvents: (eventKey: string, connectionId: string) => void;
|
|
11
|
+
readonly unsubscribeFromEvents: (eventKey: string, connectionId: string) => void;
|
|
12
|
+
readonly emitToEvents: (eventKey: string, event: string) => void;
|
|
13
|
+
}
|
|
14
|
+
declare const makeWebSocketManager: Effect.Effect<{
|
|
15
|
+
getConnection: (key: string) => WebSocketConnection | null;
|
|
16
|
+
getConnections: () => Map<string, WebSocketConnection>;
|
|
17
|
+
addConnection: (key: string, connection: WebSocketConnection) => void;
|
|
18
|
+
removeConnection: (key: string) => void;
|
|
19
|
+
subscribeToEvents: (eventKey: string, connectionId: string) => void;
|
|
20
|
+
unsubscribeFromEvents: (eventKey: string, connectionId: string) => void;
|
|
21
|
+
emitToEvents: (eventKey: string, message: string) => void;
|
|
22
|
+
}, never, EventBroadcasterService>;
|
|
23
|
+
declare const WebSocketManagerService_base: Context.TagClass<WebSocketManagerService, "BaseWebSocketManagerService", WebSocketManager>;
|
|
24
|
+
declare class WebSocketManagerService extends WebSocketManagerService_base {}
|
|
25
|
+
declare const webSocketManager: Layer.Layer<WebSocketManagerService, never, EventBroadcasterService>;
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/websocket-event-emitter.d.ts
|
|
28
|
+
declare const makeBaseEventEmitter: Effect.Effect<BaseEventEmitter, never, WebSocketManagerService>;
|
|
29
|
+
declare const webSocketEventEmitter: (eventBroadcaster: Layer.Layer<EventBroadcasterService>) => Layer.Layer<BaseEventEmitterService, never, never>;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { type WebSocketManager, WebSocketManagerService, makeBaseEventEmitter, makeWebSocketManager, webSocketEventEmitter, webSocketManager };
|
|
3
32
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/websocket-manager.ts","../src/websocket-event-emitter.ts"],"sourcesContent":[],"mappings":";;;;UAKiB,gBAAA;EAAA,SAAA,aAAgB,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GACU,mBADV,GAAA,IAAA;EACU,SAAA,cAAA,EAAA,GAAA,GACV,GADU,CAAA,MAAA,EACE,mBADF,CAAA;EACE,SAAA,aAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,UAAA,EAG7B,mBAH6B,EAAA,GAAA,IAAA;EAAZ,SAAA,gBAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAGjB,SAAA,iBAAA,EAAA,CAAA,QAAA,EAAA,MAAA,EAAA,YAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAmB,SAAA,qBAAA,EAAA,CAAA,QAAA,EAAA,MAAA,EAAA,YAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAWtB,SAAA,YAAA,EAiHX,CAAA,QAAA,EAAA,MAAA,EAAA,KAAA,EAAA,MAAA,EAAA,GAAA,IAAA;;AA/DuC,cAlD5B,oBAkD4B,EAlDR,MAAA,CAAA,MAkDQ,CAAA;EAAZ,aAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAJU,mBAIV,GAAA,IAAA;EAMb,cAAA,EAAA,GAAA,GANa,GAMb,CAAA,MAAA,EANyB,mBAMzB,CAAA;2CAAA;EAxDiB,gBAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAA,iBAAA,EAAA,CAAA,QAAA,EAAA,MAAA,EAAA,YAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAiH9B,qBAAA,EAAA,CAAA,QAAA,EAAA,MAAA,EAAA,YAAA,EAAA,MAAA,EAAA,GAAA,IAAA;;;cAAA;cAGU,uBAAA,SAAgC,4BAAA;AAKhC,cAAA,gBAGZ,EAH4B,KAAA,CAAA,KAG5B,CAH4B,uBAG5B,EAAA,KAAA,EAH4B,uBAG5B,CAAA;;;AA5IgB,cCkEJ,oBDlEoB,ECkEA,MAAA,CAAA,MDlEA,CCkEA,gBDlEA,EAAA,KAAA,ECkEA,uBDlEA,CAAA;AACU,cCsE9B,qBDtE8B,EAAA,CAAA,gBAAA,ECuEvB,KAAA,CAAM,KDvEiB,CCuEX,uBDvEW,CAAA,EAAA,GCuEa,KAAA,CAAA,KDvEb,CCuEa,uBDvEb,EAAA,KAAA,EAAA,KAAA,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import{UploadistaError as e}from"@uploadista/core/errors";import{BaseEventEmitterService as t,EventBroadcasterService as n}from"@uploadista/core/types";import{Context as r,Effect as i,Layer as a}from"effect";const o=i.gen(function*(){let e=yield*n,t=new Map,r=new Map,a=(e,n)=>{let i=r.get(e);if(i)for(let e of i){let r=t.get(e);if(r&&r.readyState===1)try{r.send(n)}catch(t){console.warn(`Failed to send message to connection ${e}:`,t),l(e)}else l(e)}};yield*e.subscribe(`uploadista:events`,e=>{try{let{eventKey:t,message:n}=JSON.parse(e);a(t,n)}catch(e){console.warn(`Failed to parse broadcast message:`,e)}}).pipe(i.catchAll(e=>(console.error(`Failed to subscribe to broadcast events:`,e),i.void)));let o=e=>t.get(e)||null,s=()=>t,c=(e,n)=>{t.set(e,n)},l=e=>{t.delete(e);for(let[t,n]of r.entries())n.delete(e),n.size===0&&r.delete(t)};return{getConnection:o,getConnections:s,addConnection:c,removeConnection:l,subscribeToEvents:(e,t)=>{r.has(e)||r.set(e,new Set),r.get(e)?.add(t)},unsubscribeFromEvents:(e,t)=>{let n=r.get(e);n&&(n.delete(t),n.size===0&&r.delete(e))},emitToEvents:(t,n)=>{i.runPromise(e.publish(`uploadista:events`,JSON.stringify({eventKey:t,message:n}))).catch(e=>{console.error(`Failed to publish event to broadcaster:`,e)})}}});var s=class extends r.Tag(`BaseWebSocketManagerService`)(){};const c=a.effect(s,o);function l(t){return{emit:(n,r)=>i.try({try:()=>{t.emitToEvents(n,r)},catch:t=>e.fromCode(`UNKNOWN_ERROR`,{cause:t})}),subscribe:(n,r)=>i.try({try:()=>{t.addConnection(r.id,r),t.subscribeToEvents(n,r.id),r.send(JSON.stringify({type:`subscribed`,payload:{eventKey:n},timestamp:new Date().toISOString()}))},catch:t=>e.fromCode(`UNKNOWN_ERROR`,{cause:t})}),unsubscribe:n=>i.try({try:()=>{let e=t.getConnections();for(let[r]of e)t.unsubscribeFromEvents(n,r)},catch:t=>e.fromCode(`UNKNOWN_ERROR`,{cause:t})})}}const u=i.gen(function*(){return l(yield*s)}),d=e=>a.effect(t,u).pipe(a.provide(c),a.provide(e));export{s as WebSocketManagerService,u as makeBaseEventEmitter,o as makeWebSocketManager,d as webSocketEventEmitter,c as webSocketManager};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["webSocketManager"],"sources":["../src/websocket-manager.ts","../src/websocket-event-emitter.ts"],"sourcesContent":["import type { WebSocketConnection } from \"@uploadista/core/types\";\nimport { EventBroadcasterService } from \"@uploadista/core/types\";\nimport { Context, Effect, Layer } from \"effect\";\n\n// Base untyped WebSocketManager - works with raw string messages\nexport interface WebSocketManager {\n readonly getConnection: (key: string) => WebSocketConnection | null;\n readonly getConnections: () => Map<string, WebSocketConnection>;\n readonly addConnection: (\n key: string,\n connection: WebSocketConnection,\n ) => void;\n readonly removeConnection: (key: string) => void;\n readonly subscribeToEvents: (eventKey: string, connectionId: string) => void;\n readonly unsubscribeFromEvents: (\n eventKey: string,\n connectionId: string,\n ) => void;\n readonly emitToEvents: (eventKey: string, event: string) => void;\n}\n\nexport const makeWebSocketManager = Effect.gen(function* () {\n const broadcaster = yield* EventBroadcasterService;\n\n const connections = new Map<string, WebSocketConnection>();\n const subscriptions = new Map<string, Set<string>>(); // eventKey -> Set<connectionId>\n\n // Helper to send messages to local connections for a given eventKey\n const emitToLocalConnections = (eventKey: string, message: string): void => {\n const connectionIds = subscriptions.get(eventKey);\n if (!connectionIds) return;\n\n for (const connectionId of connectionIds) {\n const connection = connections.get(connectionId);\n if (connection && connection.readyState === 1) {\n try {\n connection.send(message);\n } catch (error) {\n console.warn(\n `Failed to send message to connection ${connectionId}:`,\n error,\n );\n removeConnection(connectionId);\n }\n } else {\n removeConnection(connectionId);\n }\n }\n };\n\n // Subscribe to broadcast events from other instances\n yield* broadcaster\n .subscribe(\"uploadista:events\", (broadcastMessage) => {\n try {\n const { eventKey, message } = JSON.parse(broadcastMessage);\n emitToLocalConnections(eventKey, message);\n } catch (error) {\n console.warn(\"Failed to parse broadcast message:\", error);\n }\n })\n .pipe(\n Effect.catchAll((error) => {\n console.error(\"Failed to subscribe to broadcast events:\", error);\n return Effect.void;\n }),\n );\n\n const getConnection = (key: string): WebSocketConnection | null => {\n return connections.get(key) || null;\n };\n\n const getConnections = (): Map<string, WebSocketConnection> => {\n return connections;\n };\n\n const addConnection = (\n key: string,\n connection: WebSocketConnection,\n ): void => {\n connections.set(key, connection);\n };\n\n const removeConnection = (key: string): void => {\n connections.delete(key);\n // Clean up subscriptions\n for (const [eventKey, connectionIds] of subscriptions.entries()) {\n connectionIds.delete(key);\n if (connectionIds.size === 0) {\n subscriptions.delete(eventKey);\n }\n }\n };\n\n const subscribeToEvents = (eventKey: string, connectionId: string): void => {\n if (!subscriptions.has(eventKey)) {\n subscriptions.set(eventKey, new Set());\n }\n subscriptions.get(eventKey)?.add(connectionId);\n };\n\n const unsubscribeFromEvents = (\n eventKey: string,\n connectionId: string,\n ): void => {\n const connectionIds = subscriptions.get(eventKey);\n if (connectionIds) {\n connectionIds.delete(connectionId);\n if (connectionIds.size === 0) {\n subscriptions.delete(eventKey);\n }\n }\n };\n\n const emitToEvents = (eventKey: string, message: string): void => {\n // Publish to broadcaster so all instances (including this one) receive it\n Effect.runPromise(\n broadcaster.publish(\n \"uploadista:events\",\n JSON.stringify({ eventKey, message }),\n ),\n ).catch((error) => {\n console.error(\"Failed to publish event to broadcaster:\", error);\n });\n };\n\n return {\n getConnection,\n getConnections,\n addConnection,\n removeConnection,\n subscribeToEvents,\n unsubscribeFromEvents,\n emitToEvents,\n };\n});\n\n// Context tags\nexport class WebSocketManagerService extends Context.Tag(\n \"BaseWebSocketManagerService\",\n)<WebSocketManagerService, WebSocketManager>() {}\n\n// Base layer\nexport const webSocketManager = Layer.effect(\n WebSocketManagerService,\n makeWebSocketManager,\n);\n","import { UploadistaError } from \"@uploadista/core/errors\";\nimport type {\n WebSocketConnection,\n WebSocketMessage,\n} from \"@uploadista/core/types\";\nimport {\n type BaseEventEmitter,\n BaseEventEmitterService,\n type EventBroadcasterService,\n} from \"@uploadista/core/types\";\nimport { Effect, Layer } from \"effect\";\nimport {\n type WebSocketManager,\n WebSocketManagerService,\n webSocketManager,\n} from \"./websocket-manager\";\n\nexport function webSocketBaseEventEmitter(\n webSocketManager: WebSocketManager,\n): BaseEventEmitter {\n return {\n emit: (eventKey: string, message: string) => {\n return Effect.try({\n try: () => {\n webSocketManager.emitToEvents(eventKey, message);\n },\n catch: (cause) => {\n return UploadistaError.fromCode(\"UNKNOWN_ERROR\", { cause });\n },\n });\n },\n subscribe: (eventKey: string, connection: WebSocketConnection) => {\n return Effect.try({\n try: () => {\n webSocketManager.addConnection(connection.id, connection);\n webSocketManager.subscribeToEvents(eventKey, connection.id);\n\n // Send confirmation message\n connection.send(\n JSON.stringify({\n type: \"subscribed\",\n payload: { eventKey },\n timestamp: new Date().toISOString(),\n } satisfies WebSocketMessage),\n );\n },\n catch: (cause) => {\n return UploadistaError.fromCode(\"UNKNOWN_ERROR\", { cause });\n },\n });\n },\n unsubscribe: (eventKey: string) => {\n return Effect.try({\n try: () => {\n // Note: We need connectionId for proper cleanup, but the interface only provides eventKey\n // For now, we'll remove all connections for this eventKey\n // This could be improved by tracking connection mapping\n const connections = webSocketManager.getConnections();\n for (const [connectionId] of connections) {\n webSocketManager.unsubscribeFromEvents(eventKey, connectionId);\n }\n },\n catch: (cause) => {\n return UploadistaError.fromCode(\"UNKNOWN_ERROR\", { cause });\n },\n });\n },\n };\n}\n\n// Effect-based implementation using webSocketManagerService\nexport const makeBaseEventEmitter = Effect.gen(function* () {\n const webSocketManager = yield* WebSocketManagerService;\n return webSocketBaseEventEmitter(webSocketManager);\n});\n\nexport const webSocketEventEmitter = (\n eventBroadcaster: Layer.Layer<EventBroadcasterService>,\n) =>\n Layer.effect(BaseEventEmitterService, makeBaseEventEmitter).pipe(\n Layer.provide(webSocketManager),\n Layer.provide(eventBroadcaster),\n );\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uploadista/event-emitter-websocket",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.4",
|
|
5
5
|
"description": "WebSocket event emitter for Uploadista",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Uploadista",
|
|
@@ -14,13 +14,14 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"effect": "3.18.4",
|
|
17
|
-
"@uploadista/core": "0.0.
|
|
17
|
+
"@uploadista/core": "0.0.4"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"
|
|
20
|
+
"tsdown": "0.15.9",
|
|
21
|
+
"@uploadista/typescript-config": "0.0.4"
|
|
21
22
|
},
|
|
22
23
|
"scripts": {
|
|
23
|
-
"build": "
|
|
24
|
+
"build": "tsdown",
|
|
24
25
|
"format": "biome format --write ./src",
|
|
25
26
|
"lint": "biome lint --write ./src",
|
|
26
27
|
"check": "biome check --write ./src"
|
package/tsdown.config.ts
ADDED
package/dist/test-generic.d.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
declare const uploadEventEmitter: import("@uploadista/core").EventEmitter<{
|
|
2
|
-
type: import("@uploadista/core").UploadEventType.UPLOAD_STARTED | import("@uploadista/core").UploadEventType.UPLOAD_COMPLETE;
|
|
3
|
-
data: {
|
|
4
|
-
id: string;
|
|
5
|
-
offset: number;
|
|
6
|
-
storage: {
|
|
7
|
-
id: string;
|
|
8
|
-
type: string;
|
|
9
|
-
path?: string | undefined;
|
|
10
|
-
uploadId?: string | undefined;
|
|
11
|
-
bucket?: string | undefined;
|
|
12
|
-
};
|
|
13
|
-
size?: number | undefined;
|
|
14
|
-
metadata?: Record<string, string> | undefined;
|
|
15
|
-
creationDate?: string | undefined;
|
|
16
|
-
url?: string | undefined;
|
|
17
|
-
sizeIsDeferred?: boolean | undefined;
|
|
18
|
-
};
|
|
19
|
-
} | {
|
|
20
|
-
type: import("@uploadista/core").UploadEventType.UPLOAD_PROGRESS;
|
|
21
|
-
data: {
|
|
22
|
-
id: string;
|
|
23
|
-
progress: number;
|
|
24
|
-
total: number;
|
|
25
|
-
};
|
|
26
|
-
} | {
|
|
27
|
-
type: import("@uploadista/core").UploadEventType.UPLOAD_FAILED;
|
|
28
|
-
data: {
|
|
29
|
-
id: string;
|
|
30
|
-
error: string;
|
|
31
|
-
};
|
|
32
|
-
}>;
|
|
33
|
-
declare const flowEventEmitter: import("@uploadista/core").EventEmitter<FlowEvent>;
|
|
34
|
-
declare const combinedEventEmitter: import("@uploadista/core").EventEmitter<any>;
|
|
35
|
-
export { uploadEventEmitter, flowEventEmitter, combinedEventEmitter };
|
|
36
|
-
//# sourceMappingURL=test-generic.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"test-generic.d.ts","sourceRoot":"","sources":["../src/test-generic.ts"],"names":[],"mappings":"AAUA,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EACgC,CAAC;AACzD,QAAA,MAAM,gBAAgB,oDAAqD,CAAC;AAC5E,QAAA,MAAM,oBAAoB,8CAER,CAAC;AAGnB,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,CAAC"}
|
package/dist/test-generic.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { webSocketEventEmitterStore } from "./websocket-event-emitter";
|
|
2
|
-
import { createWebSocketManager } from "./websocket-manager";
|
|
3
|
-
// Test that we can create websocket managers for both event types
|
|
4
|
-
const uploadManager = createWebSocketManager();
|
|
5
|
-
const flowManager = createWebSocketManager();
|
|
6
|
-
const combinedManager = createWebSocketManager();
|
|
7
|
-
// Test that we can create event emitters for both types
|
|
8
|
-
const uploadEventEmitter = webSocketEventEmitterStore(uploadManager);
|
|
9
|
-
const flowEventEmitter = webSocketEventEmitterStore(flowManager);
|
|
10
|
-
const combinedEventEmitter = webSocketEventEmitterStore(combinedManager);
|
|
11
|
-
// This file just tests compilation - no runtime code needed
|
|
12
|
-
export { uploadEventEmitter, flowEventEmitter, combinedEventEmitter };
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { type BaseEventEmitter, BaseEventEmitterService, type EventBroadcasterService } from "@uploadista/core/types";
|
|
2
|
-
import { Effect, Layer } from "effect";
|
|
3
|
-
import { type WebSocketManager, WebSocketManagerService } from "./websocket-manager";
|
|
4
|
-
export declare function webSocketBaseEventEmitter(webSocketManager: WebSocketManager): BaseEventEmitter;
|
|
5
|
-
export declare const makeBaseEventEmitter: Effect.Effect<BaseEventEmitter, never, WebSocketManagerService>;
|
|
6
|
-
export declare const webSocketEventEmitter: (eventBroadcaster: Layer.Layer<EventBroadcasterService>) => Layer.Layer<BaseEventEmitterService, never, never>;
|
|
7
|
-
//# sourceMappingURL=websocket-event-emitter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-event-emitter.d.ts","sourceRoot":"","sources":["../src/websocket-event-emitter.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,KAAK,gBAAgB,EACrB,uBAAuB,EACvB,KAAK,uBAAuB,EAC7B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EACL,KAAK,gBAAgB,EACrB,uBAAuB,EAExB,MAAM,qBAAqB,CAAC;AAE7B,wBAAgB,yBAAyB,CACvC,gBAAgB,EAAE,gBAAgB,GACjC,gBAAgB,CAiDlB;AAGD,eAAO,MAAM,oBAAoB,iEAG/B,CAAC;AAEH,eAAO,MAAM,qBAAqB,GAChC,kBAAkB,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,uDAKrD,CAAC"}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { UploadistaError } from "@uploadista/core/errors";
|
|
2
|
-
import { BaseEventEmitterService, } from "@uploadista/core/types";
|
|
3
|
-
import { Effect, Layer } from "effect";
|
|
4
|
-
import { WebSocketManagerService, webSocketManager, } from "./websocket-manager";
|
|
5
|
-
export function webSocketBaseEventEmitter(webSocketManager) {
|
|
6
|
-
return {
|
|
7
|
-
emit: (eventKey, message) => {
|
|
8
|
-
return Effect.try({
|
|
9
|
-
try: () => {
|
|
10
|
-
webSocketManager.emitToEvents(eventKey, message);
|
|
11
|
-
},
|
|
12
|
-
catch: (cause) => {
|
|
13
|
-
return UploadistaError.fromCode("UNKNOWN_ERROR", { cause });
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
|
-
},
|
|
17
|
-
subscribe: (eventKey, connection) => {
|
|
18
|
-
return Effect.try({
|
|
19
|
-
try: () => {
|
|
20
|
-
webSocketManager.addConnection(connection.id, connection);
|
|
21
|
-
webSocketManager.subscribeToEvents(eventKey, connection.id);
|
|
22
|
-
// Send confirmation message
|
|
23
|
-
connection.send(JSON.stringify({
|
|
24
|
-
type: "subscribed",
|
|
25
|
-
payload: { eventKey },
|
|
26
|
-
timestamp: new Date().toISOString(),
|
|
27
|
-
}));
|
|
28
|
-
},
|
|
29
|
-
catch: (cause) => {
|
|
30
|
-
return UploadistaError.fromCode("UNKNOWN_ERROR", { cause });
|
|
31
|
-
},
|
|
32
|
-
});
|
|
33
|
-
},
|
|
34
|
-
unsubscribe: (eventKey) => {
|
|
35
|
-
return Effect.try({
|
|
36
|
-
try: () => {
|
|
37
|
-
// Note: We need connectionId for proper cleanup, but the interface only provides eventKey
|
|
38
|
-
// For now, we'll remove all connections for this eventKey
|
|
39
|
-
// This could be improved by tracking connection mapping
|
|
40
|
-
const connections = webSocketManager.getConnections();
|
|
41
|
-
for (const [connectionId] of connections) {
|
|
42
|
-
webSocketManager.unsubscribeFromEvents(eventKey, connectionId);
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
catch: (cause) => {
|
|
46
|
-
return UploadistaError.fromCode("UNKNOWN_ERROR", { cause });
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
// Effect-based implementation using webSocketManagerService
|
|
53
|
-
export const makeBaseEventEmitter = Effect.gen(function* () {
|
|
54
|
-
const webSocketManager = yield* WebSocketManagerService;
|
|
55
|
-
return webSocketBaseEventEmitter(webSocketManager);
|
|
56
|
-
});
|
|
57
|
-
export const webSocketEventEmitter = (eventBroadcaster) => Layer.effect(BaseEventEmitterService, makeBaseEventEmitter).pipe(Layer.provide(webSocketManager), Layer.provide(eventBroadcaster));
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { WebSocketConnection } from "@uploadista/core/types";
|
|
2
|
-
import { EventBroadcasterService } from "@uploadista/core/types";
|
|
3
|
-
import { Context, Effect, Layer } from "effect";
|
|
4
|
-
export interface WebSocketManager {
|
|
5
|
-
readonly getConnection: (key: string) => WebSocketConnection | null;
|
|
6
|
-
readonly getConnections: () => Map<string, WebSocketConnection>;
|
|
7
|
-
readonly addConnection: (key: string, connection: WebSocketConnection) => void;
|
|
8
|
-
readonly removeConnection: (key: string) => void;
|
|
9
|
-
readonly subscribeToEvents: (eventKey: string, connectionId: string) => void;
|
|
10
|
-
readonly unsubscribeFromEvents: (eventKey: string, connectionId: string) => void;
|
|
11
|
-
readonly emitToEvents: (eventKey: string, event: string) => void;
|
|
12
|
-
}
|
|
13
|
-
export declare const makeWebSocketManager: Effect.Effect<{
|
|
14
|
-
getConnection: (key: string) => WebSocketConnection | null;
|
|
15
|
-
getConnections: () => Map<string, WebSocketConnection>;
|
|
16
|
-
addConnection: (key: string, connection: WebSocketConnection) => void;
|
|
17
|
-
removeConnection: (key: string) => void;
|
|
18
|
-
subscribeToEvents: (eventKey: string, connectionId: string) => void;
|
|
19
|
-
unsubscribeFromEvents: (eventKey: string, connectionId: string) => void;
|
|
20
|
-
emitToEvents: (eventKey: string, message: string) => void;
|
|
21
|
-
}, never, EventBroadcasterService>;
|
|
22
|
-
declare const WebSocketManagerService_base: Context.TagClass<WebSocketManagerService, "BaseWebSocketManagerService", WebSocketManager>;
|
|
23
|
-
export declare class WebSocketManagerService extends WebSocketManagerService_base {
|
|
24
|
-
}
|
|
25
|
-
export declare const webSocketManager: Layer.Layer<WebSocketManagerService, never, EventBroadcasterService>;
|
|
26
|
-
export {};
|
|
27
|
-
//# sourceMappingURL=websocket-manager.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-manager.d.ts","sourceRoot":"","sources":["../src/websocket-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAGhD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,mBAAmB,GAAG,IAAI,CAAC;IACpE,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAChE,QAAQ,CAAC,aAAa,EAAE,CACtB,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,mBAAmB,KAC5B,IAAI,CAAC;IACV,QAAQ,CAAC,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,QAAQ,CAAC,iBAAiB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7E,QAAQ,CAAC,qBAAqB,EAAE,CAC9B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,KACjB,IAAI,CAAC;IACV,QAAQ,CAAC,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAClE;AAED,eAAO,MAAM,oBAAoB;yBA8CH,MAAM,KAAG,mBAAmB,GAAG,IAAI;0BAIpC,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC;yBAKpD,MAAM,cACC,mBAAmB,KAC9B,IAAI;4BAIwB,MAAM,KAAG,IAAI;kCAWP,MAAM,gBAAgB,MAAM,KAAG,IAAI;sCAQ5D,MAAM,gBACF,MAAM,KACnB,IAAI;6BAUyB,MAAM,WAAW,MAAM,KAAG,IAAI;kCAqB9D,CAAC;;AAGH,qBAAa,uBAAwB,SAAQ,4BAEC;CAAG;AAGjD,eAAO,MAAM,gBAAgB,sEAG5B,CAAC"}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { EventBroadcasterService } from "@uploadista/core/types";
|
|
2
|
-
import { Context, Effect, Layer } from "effect";
|
|
3
|
-
export const makeWebSocketManager = Effect.gen(function* () {
|
|
4
|
-
const broadcaster = yield* EventBroadcasterService;
|
|
5
|
-
const connections = new Map();
|
|
6
|
-
const subscriptions = new Map(); // eventKey -> Set<connectionId>
|
|
7
|
-
// Helper to send messages to local connections for a given eventKey
|
|
8
|
-
const emitToLocalConnections = (eventKey, message) => {
|
|
9
|
-
const connectionIds = subscriptions.get(eventKey);
|
|
10
|
-
if (!connectionIds)
|
|
11
|
-
return;
|
|
12
|
-
for (const connectionId of connectionIds) {
|
|
13
|
-
const connection = connections.get(connectionId);
|
|
14
|
-
if (connection && connection.readyState === 1) {
|
|
15
|
-
try {
|
|
16
|
-
connection.send(message);
|
|
17
|
-
}
|
|
18
|
-
catch (error) {
|
|
19
|
-
console.warn(`Failed to send message to connection ${connectionId}:`, error);
|
|
20
|
-
removeConnection(connectionId);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
removeConnection(connectionId);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
// Subscribe to broadcast events from other instances
|
|
29
|
-
yield* broadcaster
|
|
30
|
-
.subscribe("uploadista:events", (broadcastMessage) => {
|
|
31
|
-
try {
|
|
32
|
-
const { eventKey, message } = JSON.parse(broadcastMessage);
|
|
33
|
-
emitToLocalConnections(eventKey, message);
|
|
34
|
-
}
|
|
35
|
-
catch (error) {
|
|
36
|
-
console.warn("Failed to parse broadcast message:", error);
|
|
37
|
-
}
|
|
38
|
-
})
|
|
39
|
-
.pipe(Effect.catchAll((error) => {
|
|
40
|
-
console.error("Failed to subscribe to broadcast events:", error);
|
|
41
|
-
return Effect.void;
|
|
42
|
-
}));
|
|
43
|
-
const getConnection = (key) => {
|
|
44
|
-
return connections.get(key) || null;
|
|
45
|
-
};
|
|
46
|
-
const getConnections = () => {
|
|
47
|
-
return connections;
|
|
48
|
-
};
|
|
49
|
-
const addConnection = (key, connection) => {
|
|
50
|
-
connections.set(key, connection);
|
|
51
|
-
};
|
|
52
|
-
const removeConnection = (key) => {
|
|
53
|
-
connections.delete(key);
|
|
54
|
-
// Clean up subscriptions
|
|
55
|
-
for (const [eventKey, connectionIds] of subscriptions.entries()) {
|
|
56
|
-
connectionIds.delete(key);
|
|
57
|
-
if (connectionIds.size === 0) {
|
|
58
|
-
subscriptions.delete(eventKey);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
const subscribeToEvents = (eventKey, connectionId) => {
|
|
63
|
-
if (!subscriptions.has(eventKey)) {
|
|
64
|
-
subscriptions.set(eventKey, new Set());
|
|
65
|
-
}
|
|
66
|
-
subscriptions.get(eventKey)?.add(connectionId);
|
|
67
|
-
};
|
|
68
|
-
const unsubscribeFromEvents = (eventKey, connectionId) => {
|
|
69
|
-
const connectionIds = subscriptions.get(eventKey);
|
|
70
|
-
if (connectionIds) {
|
|
71
|
-
connectionIds.delete(connectionId);
|
|
72
|
-
if (connectionIds.size === 0) {
|
|
73
|
-
subscriptions.delete(eventKey);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
const emitToEvents = (eventKey, message) => {
|
|
78
|
-
// Publish to broadcaster so all instances (including this one) receive it
|
|
79
|
-
Effect.runPromise(broadcaster.publish("uploadista:events", JSON.stringify({ eventKey, message }))).catch((error) => {
|
|
80
|
-
console.error("Failed to publish event to broadcaster:", error);
|
|
81
|
-
});
|
|
82
|
-
};
|
|
83
|
-
return {
|
|
84
|
-
getConnection,
|
|
85
|
-
getConnections,
|
|
86
|
-
addConnection,
|
|
87
|
-
removeConnection,
|
|
88
|
-
subscribeToEvents,
|
|
89
|
-
unsubscribeFromEvents,
|
|
90
|
-
emitToEvents,
|
|
91
|
-
};
|
|
92
|
-
});
|
|
93
|
-
// Context tags
|
|
94
|
-
export class WebSocketManagerService extends Context.Tag("BaseWebSocketManagerService")() {
|
|
95
|
-
}
|
|
96
|
-
// Base layer
|
|
97
|
-
export const webSocketManager = Layer.effect(WebSocketManagerService, makeWebSocketManager);
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Context, Effect, Layer } from "effect";
|
|
2
|
-
export interface WebSocketServer {
|
|
3
|
-
handleConnection(key: string, websocket: WebSocket): Effect.Effect<void, never>;
|
|
4
|
-
broadcastEvent(event: unknown): Effect.Effect<void, never>;
|
|
5
|
-
getConnectionCount(): number;
|
|
6
|
-
}
|
|
7
|
-
export declare function webSocketServer(): WebSocketServer;
|
|
8
|
-
export declare const WebSocketServer: Context.Tag<WebSocketServer, WebSocketServer>;
|
|
9
|
-
export declare const WebSocketServerLayer: Layer.Layer<WebSocketServer, never, never>;
|
|
10
|
-
//# sourceMappingURL=websocket-server.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-server.d.ts","sourceRoot":"","sources":["../src/websocket-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAGhD,MAAM,WAAW,eAAe;IAC9B,gBAAgB,CACd,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,SAAS,GACnB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC9B,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC3D,kBAAkB,IAAI,MAAM,CAAC;CAC9B;AAED,wBAAgB,eAAe,IAAI,eAAe,CAgEjD;AAED,eAAO,MAAM,eAAe,+CAC4B,CAAC;AAEzD,eAAO,MAAM,oBAAoB,4CAGhC,CAAC"}
|
package/dist/websocket-server.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { Context, Effect, Layer } from "effect";
|
|
2
|
-
import { createWebSocketManager } from "./websocket-event-emitter";
|
|
3
|
-
export function webSocketServer() {
|
|
4
|
-
const webSocketManager = createWebSocketManager();
|
|
5
|
-
const handleConnection = (key, websocket) => {
|
|
6
|
-
return Effect.sync(() => {
|
|
7
|
-
const connection = {
|
|
8
|
-
id: key,
|
|
9
|
-
send: (data) => websocket.send(data),
|
|
10
|
-
close: (code, reason) => websocket.close(code, reason),
|
|
11
|
-
readyState: websocket.readyState,
|
|
12
|
-
};
|
|
13
|
-
webSocketManager.addConnection(key, connection);
|
|
14
|
-
websocket.addEventListener("close", () => {
|
|
15
|
-
webSocketManager.removeConnection(key);
|
|
16
|
-
});
|
|
17
|
-
websocket.addEventListener("error", () => {
|
|
18
|
-
webSocketManager.removeConnection(key);
|
|
19
|
-
});
|
|
20
|
-
// Send a welcome message
|
|
21
|
-
websocket.send(JSON.stringify({
|
|
22
|
-
type: "connection",
|
|
23
|
-
message: "WebSocket connection established",
|
|
24
|
-
key,
|
|
25
|
-
}));
|
|
26
|
-
});
|
|
27
|
-
};
|
|
28
|
-
const broadcastEvent = (event) => {
|
|
29
|
-
return Effect.sync(() => {
|
|
30
|
-
// Since we removed the generic broadcast method, we can use emitToUpload for specific upload events
|
|
31
|
-
// Or add a generic broadcast method if needed
|
|
32
|
-
const connections = webSocketManager.getConnections();
|
|
33
|
-
const message = JSON.stringify(event);
|
|
34
|
-
for (const [_key, connection] of connections) {
|
|
35
|
-
if (connection.readyState === 1) {
|
|
36
|
-
try {
|
|
37
|
-
connection.send(message);
|
|
38
|
-
}
|
|
39
|
-
catch (error) {
|
|
40
|
-
console.warn(`Failed to send broadcast message:`, error);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
};
|
|
46
|
-
const getConnectionCount = () => {
|
|
47
|
-
return webSocketManager.getConnections().size ?? 0;
|
|
48
|
-
};
|
|
49
|
-
return {
|
|
50
|
-
handleConnection,
|
|
51
|
-
broadcastEvent,
|
|
52
|
-
getConnectionCount,
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
export const WebSocketServer = Context.GenericTag("WebSocketServer");
|
|
56
|
-
export const WebSocketServerLayer = Layer.effect(WebSocketServer, Effect.succeed(webSocketServer()));
|