@strapi-community/plugin-io 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.
- package/LICENSE +21 -0
- package/README.md +1308 -0
- package/dist/_chunks/MonitoringPage-DLZdTZpg.mjs +752 -0
- package/dist/_chunks/MonitoringPage-HxHK1nFr.js +754 -0
- package/dist/_chunks/SettingsPage-88RdJkLy.js +1411 -0
- package/dist/_chunks/SettingsPage-DBIu309c.mjs +1409 -0
- package/dist/_chunks/SocketStatsWidget--uGHcYvU.mjs +220 -0
- package/dist/_chunks/SocketStatsWidget-C1-1_VOB.js +222 -0
- package/dist/_chunks/de-BoFxKIL3.mjs +102 -0
- package/dist/_chunks/de-Crne_WJ-.js +102 -0
- package/dist/_chunks/en-B4_6Q0aQ.mjs +120 -0
- package/dist/_chunks/en-Bd2IKJzy.js +120 -0
- package/dist/_chunks/es-CCwv5Ulk.mjs +41 -0
- package/dist/_chunks/es-Xj8RgKuQ.js +41 -0
- package/dist/_chunks/fr-D_r96iuZ.js +41 -0
- package/dist/_chunks/fr-DtBI9vH_.mjs +41 -0
- package/dist/_chunks/index-BVQ20t1c.js +113 -0
- package/dist/_chunks/index-CEh8vkxY.mjs +411 -0
- package/dist/_chunks/index-DLXtrAtk.mjs +114 -0
- package/dist/_chunks/index-DkTxsEqL.js +428 -0
- package/dist/_chunks/pt-Bba2cd2e.js +41 -0
- package/dist/_chunks/pt-I9epJZpI.mjs +41 -0
- package/dist/admin/index.js +3 -0
- package/dist/admin/index.mjs +4 -0
- package/dist/server/index.js +30000 -0
- package/dist/server/index.mjs +29970 -0
- package/package.json +120 -0
- package/types.d.ts +362 -0
package/package.json
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/package",
|
|
3
|
+
"name": "@strapi-community/plugin-io",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "A plugin for Strapi CMS that provides the ability for Socket IO integration",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"strapi",
|
|
8
|
+
"strapi-plugin",
|
|
9
|
+
"plugin",
|
|
10
|
+
"strapi plugin",
|
|
11
|
+
"socket",
|
|
12
|
+
"socket io",
|
|
13
|
+
"io"
|
|
14
|
+
],
|
|
15
|
+
"type": "commonjs",
|
|
16
|
+
"exports": {
|
|
17
|
+
"./package.json": "./package.json",
|
|
18
|
+
"./strapi-admin": {
|
|
19
|
+
"source": "./admin/src/index.js",
|
|
20
|
+
"import": "./dist/admin/index.mjs",
|
|
21
|
+
"require": "./dist/admin/index.js",
|
|
22
|
+
"default": "./dist/admin/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./strapi-server": {
|
|
25
|
+
"source": "./server/index.js",
|
|
26
|
+
"import": "./dist/server/index.mjs",
|
|
27
|
+
"require": "./dist/server/index.js",
|
|
28
|
+
"default": "./dist/server/index.js"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"types.d.ts",
|
|
34
|
+
"README.md"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "strapi-plugin build",
|
|
38
|
+
"watch": "strapi-plugin watch",
|
|
39
|
+
"watch:link": "strapi-plugin watch:link",
|
|
40
|
+
"verify": "strapi-plugin verify",
|
|
41
|
+
"lint": "eslint . --fix",
|
|
42
|
+
"format": "prettier --write \"./**/*.{js,json,yml,md}\""
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"date-fns": "^3.6.0",
|
|
46
|
+
"socket.io": "^4.8.1",
|
|
47
|
+
"zod": "^3.24.1"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
51
|
+
"@semantic-release/commit-analyzer": "^13.0.0",
|
|
52
|
+
"@semantic-release/git": "^10.0.1",
|
|
53
|
+
"@semantic-release/github": "^11.0.2",
|
|
54
|
+
"@semantic-release/npm": "^12.0.1",
|
|
55
|
+
"@semantic-release/release-notes-generator": "^14.0.1",
|
|
56
|
+
"@strapi/design-system": "^2.0.2",
|
|
57
|
+
"@strapi/icons": "^2.0.2",
|
|
58
|
+
"@strapi/sdk-plugin": "^5.3.2",
|
|
59
|
+
"@strapi/strapi": "^5.33.0",
|
|
60
|
+
"eslint": "^8.57.1",
|
|
61
|
+
"eslint-config-prettier": "^9.1.2",
|
|
62
|
+
"prettier": "^3.7.4",
|
|
63
|
+
"react": "^18.3.1",
|
|
64
|
+
"react-dom": "^18.3.1",
|
|
65
|
+
"react-router-dom": "^6.30.2",
|
|
66
|
+
"semantic-release": "^24.2.3",
|
|
67
|
+
"styled-components": "^6.1.19"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"@strapi/design-system": "^2.0.0-rc.1",
|
|
71
|
+
"@strapi/icons": "^2.0.0-rc.1",
|
|
72
|
+
"@strapi/strapi": "^5.0.0",
|
|
73
|
+
"react": "^18.0.0",
|
|
74
|
+
"react-dom": "^18.0.0",
|
|
75
|
+
"react-router-dom": "^6.0.0",
|
|
76
|
+
"styled-components": "^6.0.0"
|
|
77
|
+
},
|
|
78
|
+
"peerDependenciesMeta": {
|
|
79
|
+
"@strapi/design-system": {
|
|
80
|
+
"optional": true
|
|
81
|
+
},
|
|
82
|
+
"@strapi/icons": {
|
|
83
|
+
"optional": true
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"strapi": {
|
|
87
|
+
"name": "io",
|
|
88
|
+
"displayName": "IO",
|
|
89
|
+
"description": "A plugin for Strapi CMS that provides the ability for Socket IO integration",
|
|
90
|
+
"kind": "plugin"
|
|
91
|
+
},
|
|
92
|
+
"engines": {
|
|
93
|
+
"node": ">=18.0.0 <=22.x.x",
|
|
94
|
+
"npm": ">=6.0.0"
|
|
95
|
+
},
|
|
96
|
+
"author": {
|
|
97
|
+
"name": "@ComfortablyCoding",
|
|
98
|
+
"url": "https://github.com/ComfortablyCoding"
|
|
99
|
+
},
|
|
100
|
+
"maintainers": [
|
|
101
|
+
{
|
|
102
|
+
"name": "@ComfortablyCoding",
|
|
103
|
+
"url": "https://github.com/ComfortablyCoding",
|
|
104
|
+
"lead": true
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"name": "@hrdunn",
|
|
108
|
+
"url": "https://github.com/hrdunn"
|
|
109
|
+
}
|
|
110
|
+
],
|
|
111
|
+
"homepage": "https://github.com/strapi-community/plugin-io#readme",
|
|
112
|
+
"repository": {
|
|
113
|
+
"type": "git",
|
|
114
|
+
"url": "https://github.com/strapi-community/plugin-io.git"
|
|
115
|
+
},
|
|
116
|
+
"bugs": {
|
|
117
|
+
"url": "https://github.com/strapi-community/plugin-io/issues"
|
|
118
|
+
},
|
|
119
|
+
"license": "MIT"
|
|
120
|
+
}
|
package/types.d.ts
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Server as SocketIOServer, Socket, Namespace } from 'socket.io';
|
|
3
|
+
import type { Core } from '@strapi/strapi';
|
|
4
|
+
|
|
5
|
+
declare module '@strapi/strapi' {
|
|
6
|
+
export interface Strapi {
|
|
7
|
+
/**
|
|
8
|
+
* Global Socket.IO instance with helper functions
|
|
9
|
+
* @example
|
|
10
|
+
* strapi.$io.server.emit('notification', data);
|
|
11
|
+
* strapi.$io.joinRoom(socketId, 'premium-users');
|
|
12
|
+
*/
|
|
13
|
+
$io: SocketIO;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Current plugin settings (read-only)
|
|
17
|
+
* @example
|
|
18
|
+
* const maxConnections = strapi.$ioSettings.connection.maxConnections;
|
|
19
|
+
*/
|
|
20
|
+
$ioSettings?: PluginSettings;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface SocketIOConfig {
|
|
25
|
+
events?: SocketEvent[];
|
|
26
|
+
hooks?: {
|
|
27
|
+
init?: (context: { strapi: Core.Strapi; $io: SocketIO }) => void | Promise<void>;
|
|
28
|
+
};
|
|
29
|
+
contentTypes?: Array<string | ContentTypeConfig>;
|
|
30
|
+
socket?: {
|
|
31
|
+
serverOptions?: any;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Additional sensitive field names to exclude from emitted data.
|
|
35
|
+
* These are added to the default list which includes:
|
|
36
|
+
* password, resetPasswordToken, confirmationToken, refreshToken,
|
|
37
|
+
* accessToken, secret, apiKey, privateKey, token, salt, hash
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* sensitiveFields: ['creditCard', 'ssn', 'socialSecurityNumber']
|
|
41
|
+
*/
|
|
42
|
+
sensitiveFields?: string[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface SocketEvent {
|
|
46
|
+
name: string;
|
|
47
|
+
handler: (
|
|
48
|
+
context: { strapi: Core.Strapi; io: SocketIO },
|
|
49
|
+
socket: Socket,
|
|
50
|
+
...args: any[]
|
|
51
|
+
) => void | Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Populate configuration for content type events.
|
|
56
|
+
* Supports multiple formats for flexibility.
|
|
57
|
+
*/
|
|
58
|
+
export type PopulateConfig =
|
|
59
|
+
| '*' // Populate all relations (1 level deep)
|
|
60
|
+
| true // Alias for '*'
|
|
61
|
+
| string[] // Specific relations: ['author', 'category']
|
|
62
|
+
| Record<string, any>; // Strapi populate syntax: { author: { fields: ['name'] } }
|
|
63
|
+
|
|
64
|
+
export interface ContentTypeConfig {
|
|
65
|
+
/** Content type UID (e.g., 'api::article.article') */
|
|
66
|
+
uid: string;
|
|
67
|
+
/** Actions to emit events for. Defaults to all: ['create', 'update', 'delete'] */
|
|
68
|
+
actions?: Array<'create' | 'update' | 'delete'>;
|
|
69
|
+
/**
|
|
70
|
+
* Populate relations when emitting events.
|
|
71
|
+
* When configured, the plugin will refetch the entity with populated relations
|
|
72
|
+
* after create/update operations before emitting the event.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* // Populate all relations
|
|
76
|
+
* populate: '*'
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* // Populate specific relations
|
|
80
|
+
* populate: ['author', 'category']
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* // Strapi populate syntax with field selection
|
|
84
|
+
* populate: {
|
|
85
|
+
* author: { fields: ['username', 'email'] },
|
|
86
|
+
* category: true
|
|
87
|
+
* }
|
|
88
|
+
*/
|
|
89
|
+
populate?: PopulateConfig;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface EmitOptions {
|
|
93
|
+
event: 'create' | 'update' | 'delete';
|
|
94
|
+
schema: any;
|
|
95
|
+
data: any;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface RawEmitOptions {
|
|
99
|
+
event: string;
|
|
100
|
+
data: any;
|
|
101
|
+
rooms?: string[];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface SocketIOMetrics {
|
|
105
|
+
totalEmits: number;
|
|
106
|
+
cachedLookups: number;
|
|
107
|
+
connectedSockets: number;
|
|
108
|
+
errors: number;
|
|
109
|
+
cacheSize: {
|
|
110
|
+
rooms: number;
|
|
111
|
+
abilities: number;
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export class SocketIO {
|
|
116
|
+
constructor(options?: any);
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Emit a content type event with sanitization and permission checking
|
|
120
|
+
*/
|
|
121
|
+
emit(options: EmitOptions): Promise<void>;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Emit a raw event to specified rooms
|
|
125
|
+
*/
|
|
126
|
+
raw(options: RawEmitOptions): Promise<void>;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Invalidate the internal cache
|
|
130
|
+
*/
|
|
131
|
+
invalidateCache(): void;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Get current metrics
|
|
135
|
+
*/
|
|
136
|
+
getMetrics(): SocketIOMetrics;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Get the underlying Socket.IO server instance
|
|
140
|
+
*/
|
|
141
|
+
readonly server: SocketIOServer;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* All configured namespaces
|
|
145
|
+
*/
|
|
146
|
+
namespaces?: Record<string, Namespace>;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Join socket to room
|
|
150
|
+
*/
|
|
151
|
+
joinRoom?(socketId: string, roomName: string): boolean;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Remove socket from room
|
|
155
|
+
*/
|
|
156
|
+
leaveRoom?(socketId: string, roomName: string): boolean;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get all sockets in room
|
|
160
|
+
*/
|
|
161
|
+
getSocketsInRoom?(roomName: string): Promise<Array<{ id: string; user: any }>>;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Send private message to specific socket
|
|
165
|
+
*/
|
|
166
|
+
sendPrivateMessage?(socketId: string, event: string, data: any): void;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Broadcast from socket to all others
|
|
170
|
+
*/
|
|
171
|
+
broadcast?(socketId: string, event: string, data: any): void;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Emit to namespace
|
|
175
|
+
*/
|
|
176
|
+
emitToNamespace?(namespace: string, event: string, data: any): void;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Force disconnect socket
|
|
180
|
+
*/
|
|
181
|
+
disconnectSocket?(socketId: string, reason?: string): boolean;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Subscribe a socket to a specific entity (server-side)
|
|
185
|
+
*/
|
|
186
|
+
subscribeToEntity?(socketId: string, uid: string, id: string | number): Promise<EntitySubscriptionResult>;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Unsubscribe a socket from a specific entity
|
|
190
|
+
*/
|
|
191
|
+
unsubscribeFromEntity?(socketId: string, uid: string, id: string | number): EntitySubscriptionResult;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Get all entity subscriptions for a socket
|
|
195
|
+
*/
|
|
196
|
+
getEntitySubscriptions?(socketId: string): EntitySubscriptionsResult;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Emit an event to all clients subscribed to a specific entity
|
|
200
|
+
*/
|
|
201
|
+
emitToEntity?(uid: string, id: string | number, event: string, data: any): void;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get all sockets subscribed to a specific entity
|
|
205
|
+
*/
|
|
206
|
+
getEntityRoomSockets?(uid: string, id: string | number): Promise<Array<{ id: string; user: any }>>;
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Cleanup and destroy the Socket.IO instance
|
|
210
|
+
*/
|
|
211
|
+
destroy(): Promise<void>;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export interface EntitySubscriptionResult {
|
|
215
|
+
success: boolean;
|
|
216
|
+
room?: string;
|
|
217
|
+
uid?: string;
|
|
218
|
+
id?: string | number;
|
|
219
|
+
error?: string;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export interface EntitySubscriptionsResult {
|
|
223
|
+
success: boolean;
|
|
224
|
+
subscriptions?: Array<{ uid: string; id: string; room: string }>;
|
|
225
|
+
error?: string;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Plugin Settings
|
|
230
|
+
*/
|
|
231
|
+
export interface PluginSettings {
|
|
232
|
+
enabled: boolean;
|
|
233
|
+
cors: { origins: string[] };
|
|
234
|
+
connection: {
|
|
235
|
+
maxConnections: number;
|
|
236
|
+
pingTimeout: number;
|
|
237
|
+
pingInterval: number;
|
|
238
|
+
connectionTimeout: number;
|
|
239
|
+
};
|
|
240
|
+
security: {
|
|
241
|
+
requireAuthentication: boolean;
|
|
242
|
+
rateLimiting: {
|
|
243
|
+
enabled: boolean;
|
|
244
|
+
maxEventsPerSecond: number;
|
|
245
|
+
};
|
|
246
|
+
ipWhitelist: string[];
|
|
247
|
+
ipBlacklist: string[];
|
|
248
|
+
};
|
|
249
|
+
events: {
|
|
250
|
+
customEventNames: boolean;
|
|
251
|
+
includeRelations: boolean;
|
|
252
|
+
excludeFields: string[];
|
|
253
|
+
onlyPublished: boolean;
|
|
254
|
+
};
|
|
255
|
+
rooms: {
|
|
256
|
+
autoJoinByRole: Record<string, string[]>;
|
|
257
|
+
enablePrivateRooms: boolean;
|
|
258
|
+
};
|
|
259
|
+
rolePermissions: Record<string, RolePermission>;
|
|
260
|
+
redis: {
|
|
261
|
+
enabled: boolean;
|
|
262
|
+
url: string;
|
|
263
|
+
};
|
|
264
|
+
namespaces: {
|
|
265
|
+
enabled: boolean;
|
|
266
|
+
list: Record<string, { requireAuth: boolean }>;
|
|
267
|
+
};
|
|
268
|
+
monitoring: {
|
|
269
|
+
enableConnectionLogging: boolean;
|
|
270
|
+
enableEventLogging: boolean;
|
|
271
|
+
maxEventLogSize: number;
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export interface RolePermission {
|
|
276
|
+
canConnect: boolean;
|
|
277
|
+
allowCredentials: boolean;
|
|
278
|
+
allowedMethods: string[];
|
|
279
|
+
contentTypes: Record<string, {
|
|
280
|
+
create: boolean;
|
|
281
|
+
update: boolean;
|
|
282
|
+
delete: boolean;
|
|
283
|
+
}>;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Settings Service
|
|
288
|
+
*/
|
|
289
|
+
export interface SettingsService {
|
|
290
|
+
getSettings(): Promise<PluginSettings>;
|
|
291
|
+
setSettings(newSettings: Partial<PluginSettings>): Promise<PluginSettings>;
|
|
292
|
+
getDefaultSettings(): PluginSettings;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Monitoring Service
|
|
297
|
+
*/
|
|
298
|
+
export interface MonitoringService {
|
|
299
|
+
getConnectionStats(): ConnectionStats;
|
|
300
|
+
getEventStats(): EventStats;
|
|
301
|
+
getEventLog(limit?: number): EventLogEntry[];
|
|
302
|
+
logEvent(eventType: string, data?: any): void;
|
|
303
|
+
resetStats(): void;
|
|
304
|
+
sendTestEvent(eventName?: string, data?: any): TestEventResult;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export interface ConnectionStats {
|
|
308
|
+
connected: number;
|
|
309
|
+
rooms: Array<{ name: string; members: number; isEntityRoom?: boolean }>;
|
|
310
|
+
sockets: Array<{
|
|
311
|
+
id: string;
|
|
312
|
+
connected: boolean;
|
|
313
|
+
rooms: string[];
|
|
314
|
+
entitySubscriptions?: Array<{ uid: string; id: string; room: string }>;
|
|
315
|
+
handshake: {
|
|
316
|
+
address: string;
|
|
317
|
+
time: string;
|
|
318
|
+
query: Record<string, string>;
|
|
319
|
+
};
|
|
320
|
+
user: any;
|
|
321
|
+
}>;
|
|
322
|
+
entitySubscriptions?: {
|
|
323
|
+
total: number;
|
|
324
|
+
byContentType: Record<string, number>;
|
|
325
|
+
rooms: string[];
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export interface EventStats {
|
|
330
|
+
totalEvents: number;
|
|
331
|
+
eventsByType: Record<string, number>;
|
|
332
|
+
lastReset: number;
|
|
333
|
+
eventsPerSecond: string | number;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export interface EventLogEntry {
|
|
337
|
+
timestamp: number;
|
|
338
|
+
type: string;
|
|
339
|
+
data: any;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export interface TestEventResult {
|
|
343
|
+
success: boolean;
|
|
344
|
+
eventName: string;
|
|
345
|
+
data: any;
|
|
346
|
+
recipients: number;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Extend Strapi plugin services
|
|
351
|
+
*/
|
|
352
|
+
declare module '@strapi/strapi' {
|
|
353
|
+
export interface PluginServices {
|
|
354
|
+
io?: {
|
|
355
|
+
settings: SettingsService;
|
|
356
|
+
monitoring: MonitoringService;
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
export default SocketIO;
|
|
362
|
+
|