payload-socket-plugin 1.1.5 → 2.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.
- package/README.md +135 -22
- package/dist/index.js +13 -13
- package/dist/initSocketIO.d.ts +7 -2
- package/dist/initSocketIO.js +12 -11
- package/dist/socketManager.d.ts +3 -1
- package/dist/socketManager.js +26 -19
- package/package.json +17 -3
package/README.md
CHANGED
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
Real-time event broadcasting plugin for Payload CMS using Socket.IO with Redis support for multi-instance deployments.
|
|
8
8
|
|
|
9
|
+
> **Version 2.0.0+** supports Payload CMS v3.72.0+
|
|
10
|
+
> For Payload v2, use [v1.x](https://github.com/beewhoo/payload-socket-plugin/tree/v1.1.5)
|
|
11
|
+
|
|
9
12
|
## Features
|
|
10
13
|
|
|
11
14
|
- ✅ **Real-time Events**: Broadcast collection changes (create, update, delete) to connected clients
|
|
@@ -18,17 +21,21 @@ Real-time event broadcasting plugin for Payload CMS using Socket.IO with Redis s
|
|
|
18
21
|
## Prerequisites
|
|
19
22
|
|
|
20
23
|
- **Node.js**: >= 20.0.0
|
|
21
|
-
- **Payload CMS**: ^
|
|
24
|
+
- **Payload CMS**: ^3.72.0 (for v2.x of this plugin)
|
|
22
25
|
- **Redis** (optional): Required for multi-instance deployments
|
|
23
26
|
|
|
24
27
|
## Installation
|
|
25
28
|
|
|
29
|
+
### For Payload v3 (Current)
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install payload-socket-plugin@^2.0.0
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### For Payload v2 (Legacy)
|
|
36
|
+
|
|
26
37
|
```bash
|
|
27
|
-
npm install payload-socket-plugin
|
|
28
|
-
# or
|
|
29
|
-
yarn add payload-socket-plugin
|
|
30
|
-
# or
|
|
31
|
-
pnpm add payload-socket-plugin
|
|
38
|
+
npm install payload-socket-plugin@^1.0.0
|
|
32
39
|
```
|
|
33
40
|
|
|
34
41
|
### Install Socket.IO Client (for frontend)
|
|
@@ -37,13 +44,13 @@ pnpm add payload-socket-plugin
|
|
|
37
44
|
npm install socket.io-client
|
|
38
45
|
```
|
|
39
46
|
|
|
40
|
-
## Quick Start
|
|
47
|
+
## Quick Start (Payload v3)
|
|
41
48
|
|
|
42
49
|
### 1. Configure the Plugin
|
|
43
50
|
|
|
44
51
|
```typescript
|
|
45
52
|
// payload.config.ts
|
|
46
|
-
import { buildConfig } from "payload
|
|
53
|
+
import { buildConfig } from "payload";
|
|
47
54
|
import { socketPlugin } from "payload-socket-plugin";
|
|
48
55
|
|
|
49
56
|
export default buildConfig({
|
|
@@ -79,29 +86,42 @@ export default buildConfig({
|
|
|
79
86
|
});
|
|
80
87
|
```
|
|
81
88
|
|
|
82
|
-
### 2. Initialize Socket.IO Server
|
|
89
|
+
### 2. Initialize Socket.IO Server (Next.js Custom Server)
|
|
83
90
|
|
|
84
91
|
```typescript
|
|
85
92
|
// server.ts
|
|
86
93
|
import express from "express";
|
|
87
|
-
import
|
|
94
|
+
import { createServer } from "http";
|
|
95
|
+
import next from "next";
|
|
96
|
+
import { getPayload } from "payload";
|
|
88
97
|
import { initSocketIO } from "payload-socket-plugin";
|
|
98
|
+
import config from "@payload-config";
|
|
89
99
|
|
|
90
|
-
const
|
|
100
|
+
const port = parseInt(process.env.PORT || "3000", 10);
|
|
101
|
+
const dev = process.env.NODE_ENV !== "production";
|
|
102
|
+
const app = next({ dev });
|
|
103
|
+
const handle = app.getRequestHandler();
|
|
91
104
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
secret: process.env.PAYLOAD_SECRET,
|
|
95
|
-
express: app,
|
|
96
|
-
});
|
|
105
|
+
app.prepare().then(async () => {
|
|
106
|
+
const server = express();
|
|
97
107
|
|
|
98
|
-
//
|
|
99
|
-
|
|
100
|
-
console.log("Server running on port 3000");
|
|
101
|
-
});
|
|
108
|
+
// Let Next.js handle all routes
|
|
109
|
+
server.all("*", (req, res) => handle(req, res));
|
|
102
110
|
|
|
103
|
-
//
|
|
104
|
-
|
|
111
|
+
// Create HTTP server
|
|
112
|
+
const httpServer = createServer(server);
|
|
113
|
+
|
|
114
|
+
// Get Payload instance
|
|
115
|
+
const payload = await getPayload({ config });
|
|
116
|
+
|
|
117
|
+
// Initialize Socket.IO with the payload instance
|
|
118
|
+
await initSocketIO(httpServer, payload);
|
|
119
|
+
|
|
120
|
+
// Start server
|
|
121
|
+
httpServer.listen(port, () => {
|
|
122
|
+
console.log(`Server listening on port ${port}`);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
105
125
|
```
|
|
106
126
|
|
|
107
127
|
### 3. Connect from Client
|
|
@@ -491,6 +511,99 @@ socketPlugin({
|
|
|
491
511
|
- No built-in event replay or history mechanism
|
|
492
512
|
- Redis is required for multi-instance deployments
|
|
493
513
|
|
|
514
|
+
## Migration Guide
|
|
515
|
+
|
|
516
|
+
### Migrating from v1.x (Payload v2) to v2.x (Payload v3)
|
|
517
|
+
|
|
518
|
+
Version 2.0.0 introduces breaking changes to support Payload CMS v3:
|
|
519
|
+
|
|
520
|
+
#### 1. Update Dependencies
|
|
521
|
+
|
|
522
|
+
```bash
|
|
523
|
+
npm install payload@^3.72.0 payload-socket-plugin@^2.0.0
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
#### 2. Update Import Paths
|
|
527
|
+
|
|
528
|
+
```typescript
|
|
529
|
+
// ❌ Old (v1.x)
|
|
530
|
+
import { buildConfig } from "payload/config";
|
|
531
|
+
|
|
532
|
+
// ✅ New (v2.x)
|
|
533
|
+
import { buildConfig } from "payload";
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
#### 3. Update Server Initialization
|
|
537
|
+
|
|
538
|
+
The `initSocketIO` function now requires the Payload instance as a parameter:
|
|
539
|
+
|
|
540
|
+
```typescript
|
|
541
|
+
// ❌ Old (v1.x)
|
|
542
|
+
import payload from "payload";
|
|
543
|
+
import { initSocketIO } from "payload-socket-plugin";
|
|
544
|
+
|
|
545
|
+
await payload.init({ secret, express: app });
|
|
546
|
+
const server = app.listen(3000);
|
|
547
|
+
await initSocketIO(server);
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
```typescript
|
|
551
|
+
// ✅ New (v2.x)
|
|
552
|
+
import { getPayload } from "payload";
|
|
553
|
+
import { initSocketIO } from "payload-socket-plugin";
|
|
554
|
+
import config from "@payload-config";
|
|
555
|
+
|
|
556
|
+
const payload = await getPayload({ config });
|
|
557
|
+
const httpServer = createServer(app);
|
|
558
|
+
await initSocketIO(httpServer, payload);
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
#### 4. Update Next.js Integration
|
|
562
|
+
|
|
563
|
+
Payload v3 uses Next.js by default. Update your server setup:
|
|
564
|
+
|
|
565
|
+
```typescript
|
|
566
|
+
// server.ts (Payload v3 with Next.js)
|
|
567
|
+
import express from "express";
|
|
568
|
+
import { createServer } from "http";
|
|
569
|
+
import next from "next";
|
|
570
|
+
import { getPayload } from "payload";
|
|
571
|
+
import { initSocketIO } from "payload-socket-plugin";
|
|
572
|
+
import config from "@payload-config";
|
|
573
|
+
|
|
574
|
+
const app = next({ dev: process.env.NODE_ENV !== "production" });
|
|
575
|
+
const handle = app.getRequestHandler();
|
|
576
|
+
|
|
577
|
+
app.prepare().then(async () => {
|
|
578
|
+
const server = express();
|
|
579
|
+
server.all("*", (req, res) => handle(req, res));
|
|
580
|
+
|
|
581
|
+
const httpServer = createServer(server);
|
|
582
|
+
const payload = await getPayload({ config });
|
|
583
|
+
|
|
584
|
+
await initSocketIO(httpServer, payload);
|
|
585
|
+
|
|
586
|
+
httpServer.listen(3000);
|
|
587
|
+
});
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
#### 5. Environment Variables
|
|
591
|
+
|
|
592
|
+
Make sure to set `SOCKET_ENABLED=true` in your `.env` file if you're using the `enabled` option:
|
|
593
|
+
|
|
594
|
+
```bash
|
|
595
|
+
# .env
|
|
596
|
+
SOCKET_ENABLED=true
|
|
597
|
+
REDIS_URL=redis://localhost:6379
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
#### Breaking Changes Summary
|
|
601
|
+
|
|
602
|
+
- **Minimum Payload version**: Now requires Payload v3.72.0+
|
|
603
|
+
- **`initSocketIO` signature**: Now requires `(httpServer, payloadInstance)` instead of just `(httpServer)`
|
|
604
|
+
- **Import paths**: Changed from `payload/config` to `payload`
|
|
605
|
+
- **Payload initialization**: Use `getPayload({ config })` instead of `payload.init()`
|
|
606
|
+
|
|
494
607
|
## Changelog
|
|
495
608
|
|
|
496
609
|
See [CHANGELOG.md](./CHANGELOG.md) for version history.
|
package/dist/index.js
CHANGED
|
@@ -53,6 +53,7 @@ const socketManager_1 = require("./socketManager");
|
|
|
53
53
|
*/
|
|
54
54
|
const socketPlugin = (pluginOptions = {}) => {
|
|
55
55
|
return (incomingConfig) => {
|
|
56
|
+
var _a;
|
|
56
57
|
// Default options
|
|
57
58
|
const options = {
|
|
58
59
|
enabled: true,
|
|
@@ -79,12 +80,13 @@ const socketPlugin = (pluginOptions = {}) => {
|
|
|
79
80
|
* Create event payload from hook arguments
|
|
80
81
|
*/
|
|
81
82
|
const createEventPayload = (type, collection, args) => {
|
|
83
|
+
var _a, _b;
|
|
82
84
|
return {
|
|
83
85
|
type,
|
|
84
86
|
collection,
|
|
85
|
-
id: args.doc
|
|
87
|
+
id: ((_a = args.doc) === null || _a === void 0 ? void 0 : _a.id) || args.id,
|
|
86
88
|
doc: type === "delete" ? undefined : args.doc,
|
|
87
|
-
user: args.req
|
|
89
|
+
user: ((_b = args.req) === null || _b === void 0 ? void 0 : _b.user)
|
|
88
90
|
? {
|
|
89
91
|
id: args.req.user.id,
|
|
90
92
|
email: args.req.user.email,
|
|
@@ -97,7 +99,8 @@ const socketPlugin = (pluginOptions = {}) => {
|
|
|
97
99
|
/**
|
|
98
100
|
* Add hooks to collections
|
|
99
101
|
*/
|
|
100
|
-
const collectionsWithHooks = incomingConfig.collections
|
|
102
|
+
const collectionsWithHooks = ((_a = incomingConfig.collections) === null || _a === void 0 ? void 0 : _a.map((collection) => {
|
|
103
|
+
var _a, _b;
|
|
101
104
|
// Skip if events should not be emitted for this collection
|
|
102
105
|
if (!shouldEmitForCollection(collection.slug)) {
|
|
103
106
|
return collection;
|
|
@@ -108,7 +111,7 @@ const socketPlugin = (pluginOptions = {}) => {
|
|
|
108
111
|
...collection.hooks,
|
|
109
112
|
// After change hook - only emit for updates
|
|
110
113
|
afterChange: [
|
|
111
|
-
...(collection.hooks
|
|
114
|
+
...(((_a = collection.hooks) === null || _a === void 0 ? void 0 : _a.afterChange) || []),
|
|
112
115
|
async (args) => {
|
|
113
116
|
try {
|
|
114
117
|
// Only emit events for updates, not creates
|
|
@@ -125,7 +128,7 @@ const socketPlugin = (pluginOptions = {}) => {
|
|
|
125
128
|
],
|
|
126
129
|
// After delete hook
|
|
127
130
|
afterDelete: [
|
|
128
|
-
...(collection.hooks
|
|
131
|
+
...(((_b = collection.hooks) === null || _b === void 0 ? void 0 : _b.afterDelete) || []),
|
|
129
132
|
async (args) => {
|
|
130
133
|
try {
|
|
131
134
|
const event = createEventPayload("delete", collection.slug, args);
|
|
@@ -138,7 +141,7 @@ const socketPlugin = (pluginOptions = {}) => {
|
|
|
138
141
|
],
|
|
139
142
|
},
|
|
140
143
|
};
|
|
141
|
-
}) || [];
|
|
144
|
+
})) || [];
|
|
142
145
|
/**
|
|
143
146
|
* Add onInit hook to initialize Socket.IO server
|
|
144
147
|
*/
|
|
@@ -147,13 +150,10 @@ const socketPlugin = (pluginOptions = {}) => {
|
|
|
147
150
|
if (incomingConfig.onInit) {
|
|
148
151
|
await incomingConfig.onInit(payload);
|
|
149
152
|
}
|
|
150
|
-
//
|
|
151
|
-
// The server
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
// The HTTP server will be initialized in server.ts using initSocketIO()
|
|
155
|
-
payload.__socketManager = socketManager;
|
|
156
|
-
}
|
|
153
|
+
// Store the socket manager for later initialization
|
|
154
|
+
// The HTTP server will be initialized in server.ts using initSocketIO()
|
|
155
|
+
// This works for both standard Payload server and custom Express servers
|
|
156
|
+
payload.__socketManager = socketManager;
|
|
157
157
|
};
|
|
158
158
|
return {
|
|
159
159
|
...incomingConfig,
|
package/dist/initSocketIO.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Server as HTTPServer } from "http";
|
|
2
|
+
import type { Payload } from "payload";
|
|
2
3
|
/**
|
|
3
4
|
* Initialize Socket.IO server with the HTTP server instance
|
|
4
5
|
* This should be called after the HTTP server is created
|
|
@@ -6,13 +7,17 @@ import { Server as HTTPServer } from "http";
|
|
|
6
7
|
* @example
|
|
7
8
|
* ```ts
|
|
8
9
|
* import { initSocketIO } from 'payload-socket-plugin';
|
|
10
|
+
* import { getPayload } from 'payload';
|
|
11
|
+
* import config from '@payload-config';
|
|
12
|
+
*
|
|
13
|
+
* const payload = await getPayload({ config });
|
|
9
14
|
*
|
|
10
15
|
* const server = app.listen(PORT, () => {
|
|
11
16
|
* console.log(`Server is running on port ${PORT}`);
|
|
12
17
|
* });
|
|
13
18
|
*
|
|
14
19
|
* // Initialize Socket.IO
|
|
15
|
-
* await initSocketIO(server);
|
|
20
|
+
* await initSocketIO(server, payload);
|
|
16
21
|
* ```
|
|
17
22
|
*/
|
|
18
|
-
export declare function initSocketIO(httpServer: HTTPServer): Promise<void>;
|
|
23
|
+
export declare function initSocketIO(httpServer: HTTPServer, payloadInstance: Payload): Promise<void>;
|
package/dist/initSocketIO.js
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.initSocketIO = initSocketIO;
|
|
7
|
-
const payload_1 = __importDefault(require("payload"));
|
|
8
4
|
/**
|
|
9
5
|
* Initialize Socket.IO server with the HTTP server instance
|
|
10
6
|
* This should be called after the HTTP server is created
|
|
@@ -12,29 +8,34 @@ const payload_1 = __importDefault(require("payload"));
|
|
|
12
8
|
* @example
|
|
13
9
|
* ```ts
|
|
14
10
|
* import { initSocketIO } from 'payload-socket-plugin';
|
|
11
|
+
* import { getPayload } from 'payload';
|
|
12
|
+
* import config from '@payload-config';
|
|
13
|
+
*
|
|
14
|
+
* const payload = await getPayload({ config });
|
|
15
15
|
*
|
|
16
16
|
* const server = app.listen(PORT, () => {
|
|
17
17
|
* console.log(`Server is running on port ${PORT}`);
|
|
18
18
|
* });
|
|
19
19
|
*
|
|
20
20
|
* // Initialize Socket.IO
|
|
21
|
-
* await initSocketIO(server);
|
|
21
|
+
* await initSocketIO(server, payload);
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
|
-
async function initSocketIO(httpServer) {
|
|
24
|
+
async function initSocketIO(httpServer, payloadInstance) {
|
|
25
25
|
try {
|
|
26
26
|
// Get the socket manager from payload instance
|
|
27
|
-
const socketManager =
|
|
27
|
+
const socketManager = payloadInstance
|
|
28
|
+
.__socketManager;
|
|
28
29
|
if (!socketManager) {
|
|
29
|
-
|
|
30
|
+
payloadInstance.logger.warn("Socket.IO manager not found. Make sure socketPlugin is configured.");
|
|
30
31
|
return;
|
|
31
32
|
}
|
|
32
33
|
// Initialize Socket.IO with the HTTP server
|
|
33
|
-
await socketManager.init(httpServer);
|
|
34
|
-
|
|
34
|
+
await socketManager.init(httpServer, payloadInstance);
|
|
35
|
+
payloadInstance.logger.info("Socket.IO initialized successfully");
|
|
35
36
|
}
|
|
36
37
|
catch (error) {
|
|
37
|
-
|
|
38
|
+
payloadInstance.logger.error("Failed to initialize Socket.IO:", error);
|
|
38
39
|
throw error;
|
|
39
40
|
}
|
|
40
41
|
}
|
package/dist/socketManager.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Server as SocketIOServer } from "socket.io";
|
|
2
2
|
import { Server as HTTPServer } from "http";
|
|
3
3
|
import { RealtimeEventsPluginOptions, RealtimeEventPayload } from "./types";
|
|
4
|
+
import type { Payload } from "payload";
|
|
4
5
|
/**
|
|
5
6
|
* Socket.IO Manager for handling real-time events with Redis adapter
|
|
6
7
|
* Supports multiple Payload instances for production environments
|
|
@@ -10,11 +11,12 @@ export declare class SocketIOManager {
|
|
|
10
11
|
private pubClient;
|
|
11
12
|
private subClient;
|
|
12
13
|
private options;
|
|
14
|
+
private payload;
|
|
13
15
|
constructor(options: RealtimeEventsPluginOptions);
|
|
14
16
|
/**
|
|
15
17
|
* Initialize Socket.IO server with Redis adapter
|
|
16
18
|
*/
|
|
17
|
-
init(server: HTTPServer): Promise<SocketIOServer>;
|
|
19
|
+
init(server: HTTPServer, payloadInstance: Payload): Promise<SocketIOServer>;
|
|
18
20
|
/**
|
|
19
21
|
* Setup Redis adapter for multi-instance synchronization
|
|
20
22
|
*/
|
package/dist/socketManager.js
CHANGED
|
@@ -8,7 +8,6 @@ const socket_io_1 = require("socket.io");
|
|
|
8
8
|
const redis_adapter_1 = require("@socket.io/redis-adapter");
|
|
9
9
|
const ioredis_1 = __importDefault(require("ioredis"));
|
|
10
10
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
11
|
-
const payload_1 = __importDefault(require("payload"));
|
|
12
11
|
/**
|
|
13
12
|
* Socket.IO Manager for handling real-time events with Redis adapter
|
|
14
13
|
* Supports multiple Payload instances for production environments
|
|
@@ -18,12 +17,14 @@ class SocketIOManager {
|
|
|
18
17
|
this.io = null;
|
|
19
18
|
this.pubClient = null;
|
|
20
19
|
this.subClient = null;
|
|
20
|
+
this.payload = null;
|
|
21
21
|
this.options = options;
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
24
|
* Initialize Socket.IO server with Redis adapter
|
|
25
25
|
*/
|
|
26
|
-
async init(server) {
|
|
26
|
+
async init(server, payloadInstance) {
|
|
27
|
+
this.payload = payloadInstance;
|
|
27
28
|
const { redis, socketIO = {} } = this.options;
|
|
28
29
|
// Create Socket.IO server
|
|
29
30
|
this.io = new socket_io_1.Server(server, {
|
|
@@ -42,16 +43,17 @@ class SocketIOManager {
|
|
|
42
43
|
this.setupAuthentication();
|
|
43
44
|
// Setup connection handlers
|
|
44
45
|
this.setupConnectionHandlers();
|
|
45
|
-
|
|
46
|
+
this.payload.logger.info("Socket.IO server initialized with real-time events plugin");
|
|
46
47
|
return this.io;
|
|
47
48
|
}
|
|
48
49
|
/**
|
|
49
50
|
* Setup Redis adapter for multi-instance synchronization
|
|
50
51
|
*/
|
|
51
52
|
async setupRedisAdapter() {
|
|
52
|
-
|
|
53
|
+
var _a;
|
|
54
|
+
const redisUrl = (_a = this.options.redis) === null || _a === void 0 ? void 0 : _a.url;
|
|
53
55
|
if (!redisUrl) {
|
|
54
|
-
|
|
56
|
+
this.payload.logger.warn("Redis URL not configured. Skipping Redis adapter setup. Set redis.url in plugin options.");
|
|
55
57
|
return;
|
|
56
58
|
}
|
|
57
59
|
try {
|
|
@@ -68,10 +70,10 @@ class SocketIOManager {
|
|
|
68
70
|
new Promise((resolve) => this.subClient.once("ready", resolve)),
|
|
69
71
|
]);
|
|
70
72
|
this.io.adapter((0, redis_adapter_1.createAdapter)(this.pubClient, this.subClient));
|
|
71
|
-
|
|
73
|
+
this.payload.logger.info("Redis adapter configured for Socket.IO multi-instance support");
|
|
72
74
|
}
|
|
73
75
|
catch (error) {
|
|
74
|
-
|
|
76
|
+
this.payload.logger.error("Failed to setup Redis adapter:", error);
|
|
75
77
|
throw error;
|
|
76
78
|
}
|
|
77
79
|
}
|
|
@@ -91,9 +93,9 @@ class SocketIOManager {
|
|
|
91
93
|
return next(new Error("Authentication token required"));
|
|
92
94
|
}
|
|
93
95
|
try {
|
|
94
|
-
const decoded = jsonwebtoken_1.default.verify(token,
|
|
96
|
+
const decoded = jsonwebtoken_1.default.verify(token, this.payload.secret);
|
|
95
97
|
// Fetch full user document from Payload
|
|
96
|
-
const userDoc = await
|
|
98
|
+
const userDoc = await this.payload.findByID({
|
|
97
99
|
collection: decoded.collection || "users",
|
|
98
100
|
id: decoded.id,
|
|
99
101
|
});
|
|
@@ -118,7 +120,7 @@ class SocketIOManager {
|
|
|
118
120
|
}
|
|
119
121
|
}
|
|
120
122
|
catch (error) {
|
|
121
|
-
|
|
123
|
+
this.payload.logger.error("Socket authentication error:", error);
|
|
122
124
|
next(new Error("Authentication failed"));
|
|
123
125
|
}
|
|
124
126
|
});
|
|
@@ -128,7 +130,8 @@ class SocketIOManager {
|
|
|
128
130
|
*/
|
|
129
131
|
setupConnectionHandlers() {
|
|
130
132
|
this.io.on("connection", async (socket) => {
|
|
131
|
-
|
|
133
|
+
var _a, _b;
|
|
134
|
+
this.payload.logger.info(`Client connected: ${socket.id}, User: ${((_a = socket.user) === null || _a === void 0 ? void 0 : _a.email) || ((_b = socket.user) === null || _b === void 0 ? void 0 : _b.id)}`);
|
|
132
135
|
// Allow clients to subscribe to specific collections
|
|
133
136
|
socket.on("subscribe", (collections) => {
|
|
134
137
|
const collectionList = Array.isArray(collections)
|
|
@@ -136,7 +139,7 @@ class SocketIOManager {
|
|
|
136
139
|
: [collections];
|
|
137
140
|
collectionList.forEach((collection) => {
|
|
138
141
|
socket.join(`collection:${collection}`);
|
|
139
|
-
|
|
142
|
+
this.payload.logger.info(`Client ${socket.id} subscribed to collection: ${collection}`);
|
|
140
143
|
});
|
|
141
144
|
});
|
|
142
145
|
// Allow clients to unsubscribe from collections
|
|
@@ -146,25 +149,27 @@ class SocketIOManager {
|
|
|
146
149
|
: [collections];
|
|
147
150
|
collectionList.forEach((collection) => {
|
|
148
151
|
socket.leave(`collection:${collection}`);
|
|
149
|
-
|
|
152
|
+
this.payload.logger.info(`Client ${socket.id} unsubscribed from collection: ${collection}`);
|
|
150
153
|
});
|
|
151
154
|
});
|
|
152
155
|
// Allow clients to join collection rooms (alias for subscribe)
|
|
153
156
|
socket.on("join-collection", (collection) => {
|
|
157
|
+
var _a;
|
|
154
158
|
const roomName = `collection:${collection}`;
|
|
155
159
|
socket.join(roomName);
|
|
156
|
-
|
|
160
|
+
this.payload.logger.info(`Client ${socket.id} (${(_a = socket.user) === null || _a === void 0 ? void 0 : _a.email}) joined collection room: ${roomName}`);
|
|
157
161
|
});
|
|
158
162
|
// Handle disconnection
|
|
159
163
|
socket.on("disconnect", () => {
|
|
160
|
-
|
|
164
|
+
var _a, _b;
|
|
165
|
+
this.payload.logger.info(`Client disconnected: ${socket.id}, User: ${((_a = socket.user) === null || _a === void 0 ? void 0 : _a.email) || ((_b = socket.user) === null || _b === void 0 ? void 0 : _b.id)}`);
|
|
161
166
|
});
|
|
162
167
|
if (this.options.onSocketConnection) {
|
|
163
168
|
try {
|
|
164
|
-
await this.options.onSocketConnection(socket, this.io,
|
|
169
|
+
await this.options.onSocketConnection(socket, this.io, this.payload);
|
|
165
170
|
}
|
|
166
171
|
catch (error) {
|
|
167
|
-
|
|
172
|
+
this.payload.logger.error(`Error in custom socket connection handler: ${error}`);
|
|
168
173
|
}
|
|
169
174
|
}
|
|
170
175
|
});
|
|
@@ -174,7 +179,7 @@ class SocketIOManager {
|
|
|
174
179
|
*/
|
|
175
180
|
async emitEvent(event) {
|
|
176
181
|
if (!this.io) {
|
|
177
|
-
|
|
182
|
+
this.payload.logger.warn("Socket.IO server not initialized, cannot emit event");
|
|
178
183
|
return;
|
|
179
184
|
}
|
|
180
185
|
const { authorize, shouldEmit, transformEvent } = this.options;
|
|
@@ -232,7 +237,9 @@ class SocketIOManager {
|
|
|
232
237
|
if (this.subClient) {
|
|
233
238
|
await this.subClient.quit();
|
|
234
239
|
}
|
|
235
|
-
|
|
240
|
+
if (this.payload) {
|
|
241
|
+
this.payload.logger.info("Socket.IO server closed");
|
|
242
|
+
}
|
|
236
243
|
}
|
|
237
244
|
}
|
|
238
245
|
exports.SocketIOManager = SocketIOManager;
|
package/package.json
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payload-socket-plugin",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Real-time Socket.IO plugin for Payload CMS with Redis support",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Real-time Socket.IO plugin for Payload CMS v3 with Redis support",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
-
"
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"require": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./browser": {
|
|
14
|
+
"import": "./dist/browser.js",
|
|
15
|
+
"require": "./dist/browser.js",
|
|
16
|
+
"types": "./dist/browser.d.ts"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
8
19
|
"files": [
|
|
9
20
|
"dist",
|
|
10
21
|
"README.md"
|
|
@@ -30,6 +41,9 @@
|
|
|
30
41
|
"engines": {
|
|
31
42
|
"node": ">=20.0.0"
|
|
32
43
|
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"payload": "^3.72.0"
|
|
46
|
+
},
|
|
33
47
|
"dependencies": {
|
|
34
48
|
"@socket.io/redis-adapter": "^8.0.0",
|
|
35
49
|
"ioredis": "^5.3.0",
|