@sylphx/lens-pusher 1.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.
@@ -0,0 +1,122 @@
1
+ /**
2
+ * @sylphx/lens-pusher
3
+ *
4
+ * Pusher Channels integration for Lens real-time subscriptions.
5
+ * For serverless deployments where WebSocket connections aren't persistent.
6
+ *
7
+ * Flow:
8
+ * 1. Server uses HTTP adapter for requests
9
+ * 2. Clients subscribe to Pusher channels directly (using pusher-js)
10
+ * 3. Server publishes updates to Pusher (via pusher server SDK)
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * // Client-side (pusher-js)
15
+ * import Pusher from 'pusher-js';
16
+ * import { createPusherSubscription } from '@sylphx/lens-pusher';
17
+ *
18
+ * const pusher = new Pusher('your-key', { cluster: 'us2' });
19
+ *
20
+ * const unsubscribe = createPusherSubscription(pusher, 'entity:User:123', (data) => {
21
+ * console.log('User updated:', data);
22
+ * });
23
+ *
24
+ * // Server-side (pusher)
25
+ * import Pusher from 'pusher';
26
+ * import { createPusherBroadcaster } from '@sylphx/lens-pusher';
27
+ *
28
+ * const pusher = new Pusher({
29
+ * appId: process.env.PUSHER_APP_ID,
30
+ * key: process.env.PUSHER_KEY,
31
+ * secret: process.env.PUSHER_SECRET,
32
+ * cluster: process.env.PUSHER_CLUSTER,
33
+ * });
34
+ *
35
+ * const broadcast = createPusherBroadcaster(pusher);
36
+ * await broadcast('entity:User:123', { id: '123', name: 'Updated' });
37
+ * ```
38
+ */
39
+ /**
40
+ * Pusher transport configuration.
41
+ */
42
+ interface PusherTransportOptions {
43
+ /** Pusher app ID */
44
+ appId: string;
45
+ /** Pusher key */
46
+ key: string;
47
+ /** Pusher secret */
48
+ secret: string;
49
+ /** Pusher cluster (e.g., 'us2', 'eu', 'ap1') */
50
+ cluster: string;
51
+ /** Use TLS (default: true) */
52
+ useTLS?: boolean;
53
+ /** Channel prefix (default: 'lens-') */
54
+ channelPrefix?: string;
55
+ /** Debug logging */
56
+ debug?: boolean;
57
+ }
58
+ /**
59
+ * Pusher client interface (pusher-js).
60
+ * Matches the pusher-js client API.
61
+ */
62
+ interface PusherClientLike {
63
+ subscribe(channelName: string): {
64
+ bind(eventName: string, callback: (data: unknown) => void): void;
65
+ unbind(eventName: string, callback: (data: unknown) => void): void;
66
+ };
67
+ unsubscribe(channelName: string): void;
68
+ }
69
+ /**
70
+ * Pusher server interface (pusher).
71
+ * Matches the pusher server SDK API.
72
+ */
73
+ interface PusherServerLike {
74
+ trigger(channel: string | string[], event: string, data: unknown): Promise<unknown>;
75
+ }
76
+ /**
77
+ * Create a subscription to a Lens channel via Pusher (client-side).
78
+ *
79
+ * @param pusher - Pusher client instance (from pusher-js)
80
+ * @param channel - Channel name (e.g., 'entity:User:123')
81
+ * @param onMessage - Callback for incoming messages
82
+ * @param channelPrefix - Channel prefix (default: 'lens-')
83
+ * @returns Unsubscribe function
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * import Pusher from 'pusher-js';
88
+ * import { createPusherSubscription } from '@sylphx/lens-pusher';
89
+ *
90
+ * const pusher = new Pusher('your-key', { cluster: 'us2' });
91
+ *
92
+ * const unsubscribe = createPusherSubscription(pusher, 'entity:User:123', (data) => {
93
+ * console.log('User updated:', data);
94
+ * });
95
+ * ```
96
+ */
97
+ declare function createPusherSubscription(pusher: PusherClientLike, channel: string, onMessage: (data: unknown) => void, channelPrefix?: string): () => void;
98
+ /**
99
+ * Create a broadcaster for publishing Lens updates via Pusher (server-side).
100
+ *
101
+ * @param pusher - Pusher server instance (from pusher)
102
+ * @param channelPrefix - Channel prefix (default: 'lens-')
103
+ * @returns Broadcast function
104
+ *
105
+ * @example
106
+ * ```typescript
107
+ * import Pusher from 'pusher';
108
+ * import { createPusherBroadcaster } from '@sylphx/lens-pusher';
109
+ *
110
+ * const pusher = new Pusher({
111
+ * appId: process.env.PUSHER_APP_ID,
112
+ * key: process.env.PUSHER_KEY,
113
+ * secret: process.env.PUSHER_SECRET,
114
+ * cluster: process.env.PUSHER_CLUSTER,
115
+ * });
116
+ *
117
+ * const broadcast = createPusherBroadcaster(pusher);
118
+ * await broadcast('entity:User:123', { id: '123', name: 'Updated' });
119
+ * ```
120
+ */
121
+ declare function createPusherBroadcaster(pusher: PusherServerLike, channelPrefix?: string): (channel: string, data: unknown) => Promise<void>;
122
+ export { createPusherSubscription, createPusherBroadcaster, PusherTransportOptions, PusherServerLike, PusherClientLike as PusherLike, PusherClientLike };
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ // src/index.ts
2
+ function createPusherSubscription(pusher, channel, onMessage, channelPrefix = "lens-") {
3
+ const pusherChannel = `${channelPrefix}${channel}`;
4
+ const subscription = pusher.subscribe(pusherChannel);
5
+ subscription.bind("update", onMessage);
6
+ return () => {
7
+ subscription.unbind("update", onMessage);
8
+ pusher.unsubscribe(pusherChannel);
9
+ };
10
+ }
11
+ function createPusherBroadcaster(pusher, channelPrefix = "lens-") {
12
+ return async (channel, data) => {
13
+ const pusherChannel = `${channelPrefix}${channel}`;
14
+ await pusher.trigger(pusherChannel, "update", data);
15
+ };
16
+ }
17
+ export {
18
+ createPusherSubscription,
19
+ createPusherBroadcaster
20
+ };
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@sylphx/lens-pusher",
3
+ "version": "1.0.0",
4
+ "description": "Pusher Channels integration for Lens real-time subscriptions",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "bunup",
16
+ "typecheck": "tsc --noEmit",
17
+ "test": "echo 'no tests yet'",
18
+ "prepack": "[ -d dist ] || bun run build"
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "src"
23
+ ],
24
+ "keywords": [
25
+ "lens",
26
+ "pusher",
27
+ "realtime",
28
+ "serverless",
29
+ "websocket"
30
+ ],
31
+ "author": "SylphxAI",
32
+ "license": "MIT",
33
+ "peerDependencies": {
34
+ "pusher": ">=5.0.0",
35
+ "pusher-js": ">=8.0.0"
36
+ },
37
+ "peerDependenciesMeta": {
38
+ "pusher": {
39
+ "optional": true
40
+ },
41
+ "pusher-js": {
42
+ "optional": true
43
+ }
44
+ },
45
+ "devDependencies": {
46
+ "pusher": "^5.2.0",
47
+ "pusher-js": "^8.4.0",
48
+ "typescript": "^5.9.3"
49
+ }
50
+ }
package/src/index.ts ADDED
@@ -0,0 +1,152 @@
1
+ /**
2
+ * @sylphx/lens-pusher
3
+ *
4
+ * Pusher Channels integration for Lens real-time subscriptions.
5
+ * For serverless deployments where WebSocket connections aren't persistent.
6
+ *
7
+ * Flow:
8
+ * 1. Server uses HTTP adapter for requests
9
+ * 2. Clients subscribe to Pusher channels directly (using pusher-js)
10
+ * 3. Server publishes updates to Pusher (via pusher server SDK)
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * // Client-side (pusher-js)
15
+ * import Pusher from 'pusher-js';
16
+ * import { createPusherSubscription } from '@sylphx/lens-pusher';
17
+ *
18
+ * const pusher = new Pusher('your-key', { cluster: 'us2' });
19
+ *
20
+ * const unsubscribe = createPusherSubscription(pusher, 'entity:User:123', (data) => {
21
+ * console.log('User updated:', data);
22
+ * });
23
+ *
24
+ * // Server-side (pusher)
25
+ * import Pusher from 'pusher';
26
+ * import { createPusherBroadcaster } from '@sylphx/lens-pusher';
27
+ *
28
+ * const pusher = new Pusher({
29
+ * appId: process.env.PUSHER_APP_ID,
30
+ * key: process.env.PUSHER_KEY,
31
+ * secret: process.env.PUSHER_SECRET,
32
+ * cluster: process.env.PUSHER_CLUSTER,
33
+ * });
34
+ *
35
+ * const broadcast = createPusherBroadcaster(pusher);
36
+ * await broadcast('entity:User:123', { id: '123', name: 'Updated' });
37
+ * ```
38
+ */
39
+
40
+ /**
41
+ * Pusher transport configuration.
42
+ */
43
+ export interface PusherTransportOptions {
44
+ /** Pusher app ID */
45
+ appId: string;
46
+ /** Pusher key */
47
+ key: string;
48
+ /** Pusher secret */
49
+ secret: string;
50
+ /** Pusher cluster (e.g., 'us2', 'eu', 'ap1') */
51
+ cluster: string;
52
+ /** Use TLS (default: true) */
53
+ useTLS?: boolean;
54
+ /** Channel prefix (default: 'lens-') */
55
+ channelPrefix?: string;
56
+ /** Debug logging */
57
+ debug?: boolean;
58
+ }
59
+
60
+ /**
61
+ * Pusher client interface (pusher-js).
62
+ * Matches the pusher-js client API.
63
+ */
64
+ export interface PusherClientLike {
65
+ subscribe(channelName: string): {
66
+ bind(eventName: string, callback: (data: unknown) => void): void;
67
+ unbind(eventName: string, callback: (data: unknown) => void): void;
68
+ };
69
+ unsubscribe(channelName: string): void;
70
+ }
71
+
72
+ /**
73
+ * Pusher server interface (pusher).
74
+ * Matches the pusher server SDK API.
75
+ */
76
+ export interface PusherServerLike {
77
+ trigger(channel: string | string[], event: string, data: unknown): Promise<unknown>;
78
+ }
79
+
80
+ /**
81
+ * Create a subscription to a Lens channel via Pusher (client-side).
82
+ *
83
+ * @param pusher - Pusher client instance (from pusher-js)
84
+ * @param channel - Channel name (e.g., 'entity:User:123')
85
+ * @param onMessage - Callback for incoming messages
86
+ * @param channelPrefix - Channel prefix (default: 'lens-')
87
+ * @returns Unsubscribe function
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * import Pusher from 'pusher-js';
92
+ * import { createPusherSubscription } from '@sylphx/lens-pusher';
93
+ *
94
+ * const pusher = new Pusher('your-key', { cluster: 'us2' });
95
+ *
96
+ * const unsubscribe = createPusherSubscription(pusher, 'entity:User:123', (data) => {
97
+ * console.log('User updated:', data);
98
+ * });
99
+ * ```
100
+ */
101
+ export function createPusherSubscription(
102
+ pusher: PusherClientLike,
103
+ channel: string,
104
+ onMessage: (data: unknown) => void,
105
+ channelPrefix = "lens-",
106
+ ): () => void {
107
+ const pusherChannel = `${channelPrefix}${channel}`;
108
+ const subscription = pusher.subscribe(pusherChannel);
109
+
110
+ subscription.bind("update", onMessage);
111
+
112
+ return () => {
113
+ subscription.unbind("update", onMessage);
114
+ pusher.unsubscribe(pusherChannel);
115
+ };
116
+ }
117
+
118
+ /**
119
+ * Create a broadcaster for publishing Lens updates via Pusher (server-side).
120
+ *
121
+ * @param pusher - Pusher server instance (from pusher)
122
+ * @param channelPrefix - Channel prefix (default: 'lens-')
123
+ * @returns Broadcast function
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * import Pusher from 'pusher';
128
+ * import { createPusherBroadcaster } from '@sylphx/lens-pusher';
129
+ *
130
+ * const pusher = new Pusher({
131
+ * appId: process.env.PUSHER_APP_ID,
132
+ * key: process.env.PUSHER_KEY,
133
+ * secret: process.env.PUSHER_SECRET,
134
+ * cluster: process.env.PUSHER_CLUSTER,
135
+ * });
136
+ *
137
+ * const broadcast = createPusherBroadcaster(pusher);
138
+ * await broadcast('entity:User:123', { id: '123', name: 'Updated' });
139
+ * ```
140
+ */
141
+ export function createPusherBroadcaster(
142
+ pusher: PusherServerLike,
143
+ channelPrefix = "lens-",
144
+ ): (channel: string, data: unknown) => Promise<void> {
145
+ return async (channel: string, data: unknown) => {
146
+ const pusherChannel = `${channelPrefix}${channel}`;
147
+ await pusher.trigger(pusherChannel, "update", data);
148
+ };
149
+ }
150
+
151
+ // Legacy export for backwards compatibility
152
+ export type { PusherClientLike as PusherLike };