payload-socket-plugin 1.1.0 → 1.1.2
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.md +33 -25
- package/dist/browser.d.ts +19 -0
- package/dist/browser.js +32 -0
- package/dist/index.d.ts +2 -1
- package/package.json +2 -6
- package/dist/mock.d.ts +0 -13
- package/dist/mock.js +0 -19
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Real-time event broadcasting plugin for Payload CMS using Socket.IO with Redis s
|
|
|
18
18
|
## Prerequisites
|
|
19
19
|
|
|
20
20
|
- **Node.js**: >= 20.0.0
|
|
21
|
-
- **Payload CMS**:
|
|
21
|
+
- **Payload CMS**: ^2.0.0 || ^3.0.0
|
|
22
22
|
- **Redis** (optional): Required for multi-instance deployments
|
|
23
23
|
|
|
24
24
|
## Installation
|
|
@@ -61,15 +61,17 @@ export default buildConfig({
|
|
|
61
61
|
},
|
|
62
62
|
path: "/socket.io",
|
|
63
63
|
},
|
|
64
|
-
includeCollections: ["
|
|
64
|
+
includeCollections: ["posts", "users"],
|
|
65
65
|
authorize: {
|
|
66
|
-
projects: async (user, event) => {
|
|
67
|
-
// Only allow project owner to receive events
|
|
68
|
-
return user.id === event.doc.user;
|
|
69
|
-
},
|
|
70
66
|
posts: async (user, event) => {
|
|
71
67
|
// Allow everyone to receive public post events
|
|
72
|
-
return
|
|
68
|
+
return (
|
|
69
|
+
event.doc.status === "published" || user.id === event.doc.author
|
|
70
|
+
);
|
|
71
|
+
},
|
|
72
|
+
users: async (user, event) => {
|
|
73
|
+
// Only allow user to receive their own events
|
|
74
|
+
return user.id === event.id;
|
|
73
75
|
},
|
|
74
76
|
},
|
|
75
77
|
}),
|
|
@@ -115,16 +117,16 @@ const socket = io("http://localhost:3000", {
|
|
|
115
117
|
});
|
|
116
118
|
|
|
117
119
|
// Subscribe to collection events
|
|
118
|
-
socket.emit("join-collection", "
|
|
120
|
+
socket.emit("join-collection", "posts");
|
|
119
121
|
|
|
120
122
|
// Listen for events
|
|
121
123
|
socket.on("payload:event", (event) => {
|
|
122
124
|
console.log("Event received:", event);
|
|
123
125
|
// {
|
|
124
126
|
// type: 'update',
|
|
125
|
-
// collection: '
|
|
127
|
+
// collection: 'posts',
|
|
126
128
|
// id: '123',
|
|
127
|
-
// doc: { ... },
|
|
129
|
+
// doc: { title: 'My Post', status: 'published', ... },
|
|
128
130
|
// user: { id: '456', email: 'user@example.com' },
|
|
129
131
|
// timestamp: '2024-01-01T00:00:00.000Z'
|
|
130
132
|
// }
|
|
@@ -153,28 +155,25 @@ Authorization handlers determine which users can receive events for specific doc
|
|
|
153
155
|
```typescript
|
|
154
156
|
import type { CollectionAuthorizationHandler } from "payload-socket-plugin";
|
|
155
157
|
|
|
156
|
-
const
|
|
157
|
-
user,
|
|
158
|
-
event
|
|
159
|
-
) => {
|
|
158
|
+
const authorizePost: CollectionAuthorizationHandler = async (user, event) => {
|
|
160
159
|
// Admin can see all events
|
|
161
160
|
if (user.role === "admin") {
|
|
162
161
|
return true;
|
|
163
162
|
}
|
|
164
163
|
|
|
165
|
-
// Check if user
|
|
166
|
-
const
|
|
167
|
-
collection: "
|
|
164
|
+
// Check if post is published or user is the author
|
|
165
|
+
const post = await payload.findByID({
|
|
166
|
+
collection: "posts",
|
|
168
167
|
id: event.id as string,
|
|
169
168
|
});
|
|
170
169
|
|
|
171
|
-
return user.id ===
|
|
170
|
+
return post.status === "published" || user.id === post.author;
|
|
172
171
|
};
|
|
173
172
|
|
|
174
173
|
// Use in plugin config
|
|
175
174
|
socketPlugin({
|
|
176
175
|
authorize: {
|
|
177
|
-
|
|
176
|
+
posts: authorizePost,
|
|
178
177
|
},
|
|
179
178
|
});
|
|
180
179
|
```
|
|
@@ -185,13 +184,13 @@ socketPlugin({
|
|
|
185
184
|
|
|
186
185
|
```typescript
|
|
187
186
|
// Subscribe to a single collection
|
|
188
|
-
socket.emit("join-collection", "
|
|
187
|
+
socket.emit("join-collection", "posts");
|
|
189
188
|
|
|
190
189
|
// Subscribe to multiple collections
|
|
191
|
-
socket.emit("subscribe", ["
|
|
190
|
+
socket.emit("subscribe", ["posts", "users", "media"]);
|
|
192
191
|
|
|
193
192
|
// Unsubscribe
|
|
194
|
-
socket.emit("unsubscribe", ["
|
|
193
|
+
socket.emit("unsubscribe", ["posts"]);
|
|
195
194
|
```
|
|
196
195
|
|
|
197
196
|
### Listening for Events
|
|
@@ -199,8 +198,8 @@ socket.emit("unsubscribe", ["projects"]);
|
|
|
199
198
|
```typescript
|
|
200
199
|
// Listen to specific collection events
|
|
201
200
|
socket.on("payload:event", (event) => {
|
|
202
|
-
if (event.collection === "
|
|
203
|
-
// Handle
|
|
201
|
+
if (event.collection === "posts" && event.type === "update") {
|
|
202
|
+
// Handle post update
|
|
204
203
|
}
|
|
205
204
|
});
|
|
206
205
|
|
|
@@ -346,6 +345,16 @@ socketPlugin({
|
|
|
346
345
|
4. Authorization handlers determine which users receive the event
|
|
347
346
|
5. Redis adapter ensures events sync across multiple server instances
|
|
348
347
|
|
|
348
|
+
## Browser Compatibility
|
|
349
|
+
|
|
350
|
+
This plugin includes automatic browser-safe mocking for the Payload admin panel. When bundled for the browser (e.g., in the Payload admin UI), the plugin automatically uses a mock implementation that:
|
|
351
|
+
|
|
352
|
+
- Returns the config unchanged (no Socket.IO server initialization)
|
|
353
|
+
- Provides no-op functions for `initSocketIO()` and `SocketIOManager` methods
|
|
354
|
+
- Prevents server-side dependencies (Socket.IO, Redis) from being bundled in the browser
|
|
355
|
+
|
|
356
|
+
This is handled automatically via the `"browser"` field in `package.json`, so you don't need to configure anything special. The Socket.IO server only runs on the server side.
|
|
357
|
+
|
|
349
358
|
## Environment Variables
|
|
350
359
|
|
|
351
360
|
```bash
|
|
@@ -428,7 +437,6 @@ import type {
|
|
|
428
437
|
|
|
429
438
|
## Known Limitations
|
|
430
439
|
|
|
431
|
-
- Only supports Payload CMS v2.x (v3.x support coming soon)
|
|
432
440
|
- Authorization handlers are called for each connected user on every event
|
|
433
441
|
- No built-in event replay or history mechanism
|
|
434
442
|
- Redis is required for multi-instance deployments
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Config } from "payload";
|
|
2
|
+
/**
|
|
3
|
+
* Browser-safe mock for the Socket.IO plugin
|
|
4
|
+
* This file is used when bundling for the browser (e.g., Payload admin panel)
|
|
5
|
+
* The actual Socket.IO server only runs on the server side
|
|
6
|
+
*/
|
|
7
|
+
export declare const socketPlugin: () => (config: Config) => Config;
|
|
8
|
+
/**
|
|
9
|
+
* Browser-safe mock for initSocketIO
|
|
10
|
+
* Does nothing in browser environment
|
|
11
|
+
*/
|
|
12
|
+
export declare const initSocketIO: (httpServer?: any) => Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Browser-safe mock for SocketIOManager
|
|
15
|
+
* Returns a minimal mock class in browser environment
|
|
16
|
+
*/
|
|
17
|
+
export declare class SocketIOManager {
|
|
18
|
+
constructor();
|
|
19
|
+
}
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SocketIOManager = exports.initSocketIO = exports.socketPlugin = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Browser-safe mock for the Socket.IO plugin
|
|
6
|
+
* This file is used when bundling for the browser (e.g., Payload admin panel)
|
|
7
|
+
* The actual Socket.IO server only runs on the server side
|
|
8
|
+
*/
|
|
9
|
+
const socketPlugin = () => (config) => {
|
|
10
|
+
// Return config unchanged - Socket.IO server is server-side only
|
|
11
|
+
return config;
|
|
12
|
+
};
|
|
13
|
+
exports.socketPlugin = socketPlugin;
|
|
14
|
+
/**
|
|
15
|
+
* Browser-safe mock for initSocketIO
|
|
16
|
+
* Does nothing in browser environment
|
|
17
|
+
*/
|
|
18
|
+
const initSocketIO = async (httpServer) => {
|
|
19
|
+
// No-op in browser
|
|
20
|
+
console.warn("initSocketIO called in browser environment - this is a no-op");
|
|
21
|
+
};
|
|
22
|
+
exports.initSocketIO = initSocketIO;
|
|
23
|
+
/**
|
|
24
|
+
* Browser-safe mock for SocketIOManager
|
|
25
|
+
* Returns a minimal mock class in browser environment
|
|
26
|
+
*/
|
|
27
|
+
class SocketIOManager {
|
|
28
|
+
constructor() {
|
|
29
|
+
// No-op in browser
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.SocketIOManager = SocketIOManager;
|
package/dist/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payload-socket-plugin",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "Real-time Socket.IO plugin for Payload CMS with Redis support",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
-
"browser": "dist/
|
|
7
|
+
"browser": "dist/browser.js",
|
|
8
8
|
"files": [
|
|
9
9
|
"dist",
|
|
10
10
|
"README.md"
|
|
@@ -30,9 +30,6 @@
|
|
|
30
30
|
"engines": {
|
|
31
31
|
"node": ">=20.0.0"
|
|
32
32
|
},
|
|
33
|
-
"peerDependencies": {
|
|
34
|
-
"payload": "^2.0.0"
|
|
35
|
-
},
|
|
36
33
|
"dependencies": {
|
|
37
34
|
"@socket.io/redis-adapter": "^8.0.0",
|
|
38
35
|
"ioredis": "^5.3.0",
|
|
@@ -42,7 +39,6 @@
|
|
|
42
39
|
"devDependencies": {
|
|
43
40
|
"@types/jsonwebtoken": "^9.0.0",
|
|
44
41
|
"@types/node": "^20.0.0",
|
|
45
|
-
"payload": "^2.0.0",
|
|
46
42
|
"typescript": "^5.0.0"
|
|
47
43
|
},
|
|
48
44
|
"repository": {
|
package/dist/mock.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mock module for socket plugin
|
|
3
|
-
* Used by webpack to prevent bundling server-side Socket.IO code in the admin panel
|
|
4
|
-
*
|
|
5
|
-
* This is aliased in payload.config.ts webpack configuration:
|
|
6
|
-
* [socketPluginPath]: socketPluginMockPath
|
|
7
|
-
*/
|
|
8
|
-
import { Config } from "payload/config";
|
|
9
|
-
/**
|
|
10
|
-
* Mock plugin that does nothing
|
|
11
|
-
* The real plugin is only used on the server side
|
|
12
|
-
*/
|
|
13
|
-
export declare const socketPlugin: () => (config: Config) => Config;
|
package/dist/mock.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Mock module for socket plugin
|
|
4
|
-
* Used by webpack to prevent bundling server-side Socket.IO code in the admin panel
|
|
5
|
-
*
|
|
6
|
-
* This is aliased in payload.config.ts webpack configuration:
|
|
7
|
-
* [socketPluginPath]: socketPluginMockPath
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.socketPlugin = void 0;
|
|
11
|
-
/**
|
|
12
|
-
* Mock plugin that does nothing
|
|
13
|
-
* The real plugin is only used on the server side
|
|
14
|
-
*/
|
|
15
|
-
const socketPlugin = () => (config) => {
|
|
16
|
-
// Return config unchanged - no Socket.IO in admin panel
|
|
17
|
-
return config;
|
|
18
|
-
};
|
|
19
|
-
exports.socketPlugin = socketPlugin;
|