@jcbuisson/express-x 1.4.0 → 1.4.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jcbuisson/express-x",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "src/index.mjs",
package/src/server.mjs CHANGED
@@ -14,10 +14,17 @@ export function expressX(prisma, options = {}) {
14
14
  if (options.ws === undefined) options.ws = { ws_prefix: "expressx" }
15
15
 
16
16
  const services = {}
17
- const connections = {}
18
17
 
18
+ app.connections = {}
19
19
  let lastConnectionId = 1
20
20
 
21
+ app.printCnx = (label) => {
22
+ console.log(label)
23
+ for (const id in app.connections) {
24
+ console.log(`CNX ${id}, data ${JSON.stringify(app.connections[id].data)}`)
25
+ }
26
+ }
27
+
21
28
  // logging function - a winston logger must be configured first
22
29
  app.log = (severity, message) => {
23
30
  const logger = app.get('logger')
@@ -62,18 +69,21 @@ export function expressX(prisma, options = {}) {
62
69
  const beforeMethodHooks = service?.hooks?.before && service.hooks.before[methodName] || []
63
70
  const beforeAllHooks = service?.hooks?.before?.all || []
64
71
  for (const hook of [...beforeMethodHooks, ...beforeAllHooks]) {
65
- context = await hook({ ...context, args })
72
+ // context = await hook(context)
73
+ await hook(context)
66
74
  }
67
75
 
68
76
  // call method
69
77
  const result = await method(...context.args)
70
- app.log('debug', 'result ' + JSON.stringify(result))
78
+ // put result into context
79
+ context.result = result
71
80
 
72
81
  // call 'after' hooks
73
82
  const afterMethodHooks = service?.hooks?.after && service.hooks.after[methodName] || []
74
83
  const afterAllHooks = service?.hooks?.after?.all || []
75
84
  for (const hook of [...afterMethodHooks, ...afterAllHooks]) {
76
- context = await hook({ ...context, result })
85
+ // context = await hook(context)
86
+ await hook(context)
77
87
  }
78
88
  return result
79
89
  }
@@ -117,7 +127,8 @@ export function expressX(prisma, options = {}) {
117
127
  async function addHttpRest(path, service) {
118
128
  const context = {
119
129
  app,
120
- http: { name: service.name }
130
+ transport: 'http',
131
+ params: { name: service.name }
121
132
  }
122
133
 
123
134
  // introspect schema and return a map: field name => prisma type
@@ -133,7 +144,7 @@ export function expressX(prisma, options = {}) {
133
144
 
134
145
  app.post(path, async (req, res) => {
135
146
  app.log('verbose', `http request POST ${req.url}`)
136
- context.http.req = req
147
+ context.params.req = req
137
148
  try {
138
149
  const value = await service.__create(context, { data: req.body })
139
150
  publish(service, 'create', value)
@@ -146,7 +157,7 @@ export function expressX(prisma, options = {}) {
146
157
 
147
158
  app.get(path, async (req, res) => {
148
159
  app.log('verbose', `http request GET ${req.url}`)
149
- context.http.req = req
160
+ context.params.req = req
150
161
  const query = { ...req.query }
151
162
  try {
152
163
  // the values in `req.query` are all strings, but Prisma need proper types
@@ -182,7 +193,7 @@ export function expressX(prisma, options = {}) {
182
193
 
183
194
  app.get(`${path}/:id`, async (req, res) => {
184
195
  app.log('verbose', `http request GET ${req.url}`)
185
- context.http.req = req
196
+ context.params.req = req
186
197
  try {
187
198
  const value = await service.__findUnique(context, {
188
199
  where: {
@@ -199,7 +210,7 @@ export function expressX(prisma, options = {}) {
199
210
 
200
211
  app.patch(`${path}/:id`, async (req, res) => {
201
212
  app.log('verbose', `http request PATCH ${req.url}`)
202
- context.http.req = req
213
+ context.params.req = req
203
214
  try {
204
215
  const value = await service.__update(context, {
205
216
  where: {
@@ -217,7 +228,7 @@ export function expressX(prisma, options = {}) {
217
228
 
218
229
  app.delete(`${path}/:id`, async (req, res) => {
219
230
  app.log('verbose', `http request DELETE ${req.url}`)
220
- context.http.req = req
231
+ context.params.req = req
221
232
  try {
222
233
  const value = await service.__delete(context, {
223
234
  where: {
@@ -252,11 +263,13 @@ export function expressX(prisma, options = {}) {
252
263
  id: lastConnectionId++,
253
264
  socket,
254
265
  channelNames: new Set(),
255
- data: {},
266
+ data: {
267
+ a: 123
268
+ },
256
269
  }
257
270
  // store connection in cache
258
- connections[connection.id] = connection
259
- app.log('verbose', `active connection ids: ${Object.keys(connections)}`)
271
+ app.connections[connection.id] = connection
272
+ app.log('verbose', `Connection ids: ${Object.keys(app.connections)}`)
260
273
 
261
274
  // emit 'connection' event for app (expressjs extends EventEmitter)
262
275
  app.emit('connection', connection)
@@ -267,15 +280,22 @@ export function expressX(prisma, options = {}) {
267
280
  socket.on('disconnect', () => {
268
281
  app.log('verbose', `Client disconnected ${connection.id}`)
269
282
 
270
- // TODO: wait for 1mn before cleaning (a reconnection will use this data)
271
- // delete connections[connection.id]
283
+ // remove connection record after 1mn (leaves time in case of connection transfer)
284
+ setTimeout(() => {
285
+ app.log('verbose', `Delete connection ${connection.id}`)
286
+ delete app.connections[connection.id]
287
+ }, 60 * 1000)
272
288
  })
273
289
 
274
- // handle connection data transfer caused by a disconnection (page reload, network issue, etc.)
290
+
291
+ // handle connection data transfer caused by a disconnection/reconnection (page reload, network issue, etc.)
275
292
  socket.on('cnx-transfer', async ({ from, to }) => {
276
293
  app.log('verbose', `cnx-transfer from ${from} to ${to}`)
277
- connections[to] = connections[from]
278
- delete connections[from]
294
+ if (!app.connections[from]) return
295
+ app.connections[to] = app.connections[from]
296
+ app.connections[to].socket = socket
297
+ delete app.connections[from]
298
+ // app.printCnx('AFTER TRANSFER')
279
299
  })
280
300
 
281
301
 
@@ -292,11 +312,13 @@ export function expressX(prisma, options = {}) {
292
312
  if (serviceMethod) {
293
313
  const context = {
294
314
  app,
295
- ws: { connection, name, action, args },
315
+ transport: 'ws',
316
+ params: { connection, name, action, args },
296
317
  }
297
318
 
298
319
  try {
299
320
  const result = await serviceMethod(context, ...args)
321
+ app.log('verbose', `client-response ${uid} ${JSON.stringify(result)}`)
300
322
  socket.emit('client-response', {
301
323
  uid,
302
324
  result,
@@ -304,7 +326,7 @@ export function expressX(prisma, options = {}) {
304
326
  // pub/sub: send event on associated channels
305
327
  publish(service, action, result)
306
328
  } catch(err) {
307
- app.log('error', err)
329
+ app.log('error', err.toString())
308
330
  io.emit('client-response', {
309
331
  uid,
310
332
  error: err.toString(),
@@ -340,7 +362,7 @@ export function expressX(prisma, options = {}) {
340
362
  app.log('verbose', `publish channels ${service.name} ${action} ${channelNames}`)
341
363
  for (const channelName of channelNames) {
342
364
  app.log('verbose', `service-event ${service.name} ${action} ${channelName}`)
343
- const connectionList = Object.values(connections).filter(cnx => cnx.channelNames.has(channelName))
365
+ const connectionList = Object.values(app.connections).filter(cnx => cnx.channelNames.has(channelName))
344
366
  for (const connection of connectionList) {
345
367
  app.log('verbose', `emit to ${connection.id} ${service.name} ${action} ${result}`)
346
368
  connection.socket.emit('service-event', {
@@ -8,7 +8,7 @@ import { PrismaClient } from '@prisma/client'
8
8
  import { describe, it, before, after, beforeEach, afterEach } from 'node:test'
9
9
  import { strict as assert } from 'node:assert'
10
10
 
11
- import { expressX, expressXClient } from '../src/index.mjs'
11
+ import { expressX } from '../src/index.mjs'
12
12
 
13
13
  const prisma = new PrismaClient({
14
14
  datasources: {
@@ -144,41 +144,3 @@ describe('HTTP/REST API', () => {
144
144
  app.server.close()
145
145
  })
146
146
  })
147
-
148
-
149
- // test compatibility with client API
150
- describe('Client API', () => {
151
-
152
- let clientApp, socket
153
-
154
- before(async () => {
155
- await new Promise((resolve) => {
156
- app.server.listen(8008, () => {
157
- console.log(`App listening at http://localhost:8008`)
158
- resolve()
159
- })
160
- })
161
-
162
- socket = io('http://localhost:8008', { transports: ["websocket"] })
163
- clientApp = expressXClient(socket)
164
- })
165
-
166
- after(async () => {
167
- app.server.close()
168
- })
169
-
170
- it("can create a user", async () => {
171
- const user = await clientApp.service('User').create({
172
- data: {
173
- name: "chris",
174
- email: 'chris@mail.fr'
175
- },
176
- })
177
- assert(user.name === 'chris')
178
- })
179
-
180
- after(async () => {
181
- await socket.close()
182
- await app.server.close()
183
- })
184
- })