@jcbuisson/express-x 1.0.16 → 1.0.18
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/package.json +1 -1
- package/src/index.mjs +92 -76
package/package.json
CHANGED
package/src/index.mjs
CHANGED
|
@@ -5,7 +5,10 @@ import { Server } from "socket.io"
|
|
|
5
5
|
/*
|
|
6
6
|
* Enhance `app` express application with Feathers-like services
|
|
7
7
|
*/
|
|
8
|
-
function expressX(app, options={
|
|
8
|
+
function expressX(app, options={}) {
|
|
9
|
+
|
|
10
|
+
if (options.debug === undefined) options.debug = true
|
|
11
|
+
if (options.ws === undefined) options.ws = { ws_prefix: "expressx" }
|
|
9
12
|
|
|
10
13
|
const services = {}
|
|
11
14
|
const connections = {}
|
|
@@ -140,7 +143,7 @@ function expressX(app, options={ debug: true }) {
|
|
|
140
143
|
/*
|
|
141
144
|
* add an HTTP REST endpoint at `path`, based on `service`
|
|
142
145
|
*/
|
|
143
|
-
function
|
|
146
|
+
function addHttpRest(path, service) {
|
|
144
147
|
const context = {
|
|
145
148
|
app,
|
|
146
149
|
http: { name: service.name }
|
|
@@ -180,94 +183,107 @@ function expressX(app, options={ debug: true }) {
|
|
|
180
183
|
}
|
|
181
184
|
|
|
182
185
|
/*
|
|
183
|
-
*
|
|
184
|
-
|
|
186
|
+
* Create HTTP server
|
|
187
|
+
*/
|
|
185
188
|
const server = new http.Server(app)
|
|
186
|
-
const io = new Server(server)
|
|
187
|
-
|
|
188
|
-
io.on('connection', function(socket) {
|
|
189
|
-
if (options.debug) console.log('Client connected to the WebSocket')
|
|
190
|
-
const connection = {
|
|
191
|
-
id: lastConnectionId++,
|
|
192
|
-
socket,
|
|
193
|
-
channelNames: new Set(),
|
|
194
|
-
}
|
|
195
|
-
// store connection in cache
|
|
196
|
-
connections[connection.id] = connection
|
|
197
|
-
if (options.debug) console.log('active connections', Object.keys(connections))
|
|
198
|
-
|
|
199
|
-
// emit 'connection' event for app (expressjs extends EventEmitter)
|
|
200
|
-
app.emit('connection', connection)
|
|
201
|
-
|
|
202
|
-
// send 'connected' event to client
|
|
203
|
-
socket.emit('connected', connection.id)
|
|
204
|
-
|
|
205
|
-
socket.on('disconnect', () => {
|
|
206
|
-
if (options.debug) console.log('Client disconnected', connection.id)
|
|
207
|
-
delete connections[connection.id]
|
|
208
|
-
})
|
|
209
|
-
|
|
210
189
|
|
|
190
|
+
if (options.ws) {
|
|
211
191
|
/*
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if (
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
192
|
+
* Add websocket transport
|
|
193
|
+
*/
|
|
194
|
+
const io = new Server(server)
|
|
195
|
+
|
|
196
|
+
io.on('connection', function(socket) {
|
|
197
|
+
if (options.debug) console.log('Client connected to the WebSocket')
|
|
198
|
+
const connection = {
|
|
199
|
+
id: lastConnectionId++,
|
|
200
|
+
socket,
|
|
201
|
+
channelNames: new Set(),
|
|
202
|
+
}
|
|
203
|
+
// store connection in cache
|
|
204
|
+
connections[connection.id] = connection
|
|
205
|
+
if (options.debug) console.log('active connections', Object.keys(connections))
|
|
206
|
+
|
|
207
|
+
// emit 'connection' event for app (expressjs extends EventEmitter)
|
|
208
|
+
app.emit('connection', connection)
|
|
209
|
+
|
|
210
|
+
// send 'connected' event to client
|
|
211
|
+
socket.emit('connected', connection.id)
|
|
212
|
+
|
|
213
|
+
socket.on('disconnect', () => {
|
|
214
|
+
if (options.debug) console.log('Client disconnected', connection.id)
|
|
215
|
+
delete connections[connection.id]
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
/*
|
|
220
|
+
* Handle websocket client request
|
|
221
|
+
* Emit in return a 'client-response' message
|
|
222
|
+
*/
|
|
223
|
+
socket.on('client-request', async ({ uid, name, action, args }) => {
|
|
224
|
+
if (options.debug) console.log("client-request", uid, name, action, args)
|
|
225
|
+
if (name in services) {
|
|
226
|
+
const service = services[name]
|
|
227
|
+
try {
|
|
228
|
+
const serviceMethod = service['__' + action]
|
|
229
|
+
if (serviceMethod) {
|
|
230
|
+
const context = {
|
|
231
|
+
app,
|
|
232
|
+
ws: { connection, name, action, args },
|
|
233
|
+
}
|
|
227
234
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
235
|
+
try {
|
|
236
|
+
const result = await serviceMethod(context, ...args)
|
|
237
|
+
socket.emit('client-response', {
|
|
238
|
+
uid,
|
|
239
|
+
result,
|
|
240
|
+
})
|
|
241
|
+
// pub/sub: send event on associated channels
|
|
242
|
+
const publishFunc = service.publishCallback
|
|
243
|
+
if (publishFunc) {
|
|
244
|
+
const channelNames = await publishFunc(result, app)
|
|
245
|
+
if (options.debug) console.log('publish channels', name, action, channelNames)
|
|
246
|
+
for (const channelName of channelNames) {
|
|
247
|
+
if (options.debug) console.log('service-event', name, action, channelName)
|
|
248
|
+
const connectionList = Object.values(connections).filter(cnx => cnx.channelNames.has(channelName))
|
|
249
|
+
for (const connection of connectionList) {
|
|
250
|
+
if (options.debug) console.log('emit to', connection.id, name, action, result)
|
|
251
|
+
connection.socket.emit('service-event', {
|
|
252
|
+
name,
|
|
253
|
+
action,
|
|
254
|
+
result,
|
|
255
|
+
})
|
|
256
|
+
}
|
|
257
|
+
}
|
|
247
258
|
}
|
|
259
|
+
} catch(callErr) {
|
|
260
|
+
console.log('callErr', callErr)
|
|
261
|
+
io.emit('client-response', {
|
|
262
|
+
uid,
|
|
263
|
+
error: callErr.toString(),
|
|
264
|
+
})
|
|
248
265
|
}
|
|
266
|
+
} else {
|
|
267
|
+
io.emit('client-response', {
|
|
268
|
+
uid,
|
|
269
|
+
error: `there is no method named '${action}' for service '${name}'`,
|
|
270
|
+
})
|
|
249
271
|
}
|
|
250
|
-
}
|
|
272
|
+
} catch(error) {
|
|
251
273
|
io.emit('client-response', {
|
|
252
274
|
uid,
|
|
253
|
-
error
|
|
275
|
+
error,
|
|
254
276
|
})
|
|
255
277
|
}
|
|
256
|
-
}
|
|
278
|
+
} else {
|
|
257
279
|
io.emit('client-response', {
|
|
258
280
|
uid,
|
|
259
|
-
error
|
|
281
|
+
error: `there is no service named '${name}'`,
|
|
260
282
|
})
|
|
261
283
|
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
error: `there is no service named '${name}'`,
|
|
266
|
-
})
|
|
267
|
-
}
|
|
268
|
-
})
|
|
269
|
-
|
|
270
|
-
})
|
|
284
|
+
})
|
|
285
|
+
})
|
|
286
|
+
}
|
|
271
287
|
|
|
272
288
|
function joinChannel(channelName, connection) {
|
|
273
289
|
connection.channelNames.add(channelName)
|
|
@@ -284,7 +300,7 @@ function expressX(app, options={ debug: true }) {
|
|
|
284
300
|
createService,
|
|
285
301
|
service,
|
|
286
302
|
configure,
|
|
287
|
-
|
|
303
|
+
addHttpRest,
|
|
288
304
|
server,
|
|
289
305
|
joinChannel,
|
|
290
306
|
leaveChannel,
|