@jcbuisson/express-x 1.0.3 → 1.0.5
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 +2 -3
- package/src/{expressX.js → index.js} +80 -77
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jcbuisson/express-x",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "",
|
|
5
|
-
"main": "src/
|
|
5
|
+
"main": "src/index.js",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git@gitlab.com:buisson31/express-x.git"
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"@prisma/client": "^4.10.1",
|
|
18
18
|
"config": "^3.3.9",
|
|
19
19
|
"express": "^4.18.2",
|
|
20
|
-
"jsonwebtoken": "^9.0.0",
|
|
21
20
|
"socket.io": "^4.6.0"
|
|
22
21
|
},
|
|
23
22
|
"devDependencies": {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const { PrismaClient } = require('@prisma/client')
|
|
2
|
+
import http from 'http'
|
|
3
|
+
import { Server } from "socket.io"
|
|
4
|
+
import { PrismaClient } from '@prisma/client'
|
|
6
5
|
|
|
7
6
|
/*
|
|
8
7
|
* Enhance `app` express application with Feathers-like services
|
|
@@ -19,44 +18,39 @@ function expressX(app) {
|
|
|
19
18
|
/*
|
|
20
19
|
* create a service `name` based on Prisma table `entity`
|
|
21
20
|
*/
|
|
22
|
-
function createDatabaseService(
|
|
23
|
-
return createService({
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
},
|
|
49
|
-
}),
|
|
50
|
-
|
|
51
|
-
find: (options) => prisma[entity].findMany(options),
|
|
52
|
-
}
|
|
21
|
+
function createDatabaseService(name, { entity=name, client='prisma' }) {
|
|
22
|
+
return createService(name, {
|
|
23
|
+
create: (data) => prisma[entity].create({
|
|
24
|
+
data,
|
|
25
|
+
}),
|
|
26
|
+
|
|
27
|
+
get: (id) => prisma[entity].findUnique({
|
|
28
|
+
where: {
|
|
29
|
+
id,
|
|
30
|
+
},
|
|
31
|
+
}),
|
|
32
|
+
|
|
33
|
+
patch: (id, data) => prisma[entity].update({
|
|
34
|
+
where: {
|
|
35
|
+
id,
|
|
36
|
+
},
|
|
37
|
+
data,
|
|
38
|
+
}),
|
|
39
|
+
|
|
40
|
+
remove: (id, data) => prisma[entity].delete({
|
|
41
|
+
where: {
|
|
42
|
+
id,
|
|
43
|
+
},
|
|
44
|
+
}),
|
|
45
|
+
|
|
46
|
+
find: (options) => prisma[entity].findMany(options),
|
|
53
47
|
})
|
|
54
48
|
}
|
|
55
49
|
|
|
56
50
|
/*
|
|
57
51
|
* create a service `name` with given `methods`
|
|
58
52
|
*/
|
|
59
|
-
function createService(
|
|
53
|
+
function createService(name, methods) {
|
|
60
54
|
const service = { name }
|
|
61
55
|
|
|
62
56
|
for (const methodName in methods) {
|
|
@@ -64,7 +58,7 @@ function expressX(app) {
|
|
|
64
58
|
|
|
65
59
|
// `context` is the context of execution (transport type, connection, app)
|
|
66
60
|
// `args` is the list of arguments of the method
|
|
67
|
-
service[methodName] = async (context, ...args) => {
|
|
61
|
+
service['__' + methodName] = async (context, ...args) => {
|
|
68
62
|
context.args = args
|
|
69
63
|
|
|
70
64
|
// if a hook or the method throws an error, it will be caught by `socket.on('client-request'`
|
|
@@ -89,11 +83,11 @@ function expressX(app) {
|
|
|
89
83
|
}
|
|
90
84
|
return result
|
|
91
85
|
}
|
|
92
|
-
}
|
|
93
86
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
87
|
+
// hooked version of method: `create`, etc., to be called from backend with no context
|
|
88
|
+
service[methodName] = method
|
|
89
|
+
|
|
90
|
+
// un-hooked version of method: `_create`, etc., to be called from backend with no context
|
|
97
91
|
service['_' + methodName] = method
|
|
98
92
|
}
|
|
99
93
|
|
|
@@ -112,8 +106,9 @@ function expressX(app) {
|
|
|
112
106
|
return service
|
|
113
107
|
}
|
|
114
108
|
|
|
115
|
-
//
|
|
109
|
+
// `app.service(name)` starts here!
|
|
116
110
|
function service(name) {
|
|
111
|
+
// get service from `services` cache
|
|
117
112
|
if (name in services) return services[name]
|
|
118
113
|
throw Error(`there is no service named '${name}'`)
|
|
119
114
|
}
|
|
@@ -133,27 +128,27 @@ function expressX(app) {
|
|
|
133
128
|
}
|
|
134
129
|
|
|
135
130
|
app.post(path, async (req, res) => {
|
|
136
|
-
const value = await service.
|
|
131
|
+
const value = await service.__create(context, req.body)
|
|
137
132
|
res.json(value)
|
|
138
133
|
})
|
|
139
134
|
|
|
140
135
|
app.get(path, async (req, res) => {
|
|
141
|
-
const values = await service.
|
|
136
|
+
const values = await service.__find(context, req.body)
|
|
142
137
|
res.json(values)
|
|
143
138
|
})
|
|
144
139
|
|
|
145
140
|
app.get(`${path}/:id`, async (req, res) => {
|
|
146
|
-
const value = await service.
|
|
141
|
+
const value = await service.__get(context, parseInt(req.params.id))
|
|
147
142
|
res.json(value)
|
|
148
143
|
})
|
|
149
144
|
|
|
150
145
|
app.patch(`${path}/:id`, async (req, res) => {
|
|
151
|
-
const value = await service.
|
|
146
|
+
const value = await service.__patch(context, parseInt(req.params.id), req.body)
|
|
152
147
|
res.json(value)
|
|
153
148
|
})
|
|
154
149
|
|
|
155
150
|
app.delete(`${path}/:id`, async (req, res) => {
|
|
156
|
-
const value = await service.
|
|
151
|
+
const value = await service.__remove(context, parseInt(req.params.id))
|
|
157
152
|
res.json(value)
|
|
158
153
|
})
|
|
159
154
|
}
|
|
@@ -162,7 +157,7 @@ function expressX(app) {
|
|
|
162
157
|
* Add websocket transport for services
|
|
163
158
|
*/
|
|
164
159
|
const server = new http.Server(app)
|
|
165
|
-
const io = new
|
|
160
|
+
const io = new Server(server)
|
|
166
161
|
|
|
167
162
|
io.on('connection', function(socket) {
|
|
168
163
|
console.log('Client connected to the WebSocket')
|
|
@@ -195,36 +190,44 @@ function expressX(app) {
|
|
|
195
190
|
if (name in services) {
|
|
196
191
|
const service = services[name]
|
|
197
192
|
try {
|
|
198
|
-
const serviceMethod = service[action]
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
console.log('
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
193
|
+
const serviceMethod = service['__' + action]
|
|
194
|
+
if (serviceMethod) {
|
|
195
|
+
const context = {
|
|
196
|
+
app,
|
|
197
|
+
transport: 'ws',
|
|
198
|
+
connection,
|
|
199
|
+
name,
|
|
200
|
+
action,
|
|
201
|
+
}
|
|
202
|
+
const result = await serviceMethod(context, ...args)
|
|
203
|
+
|
|
204
|
+
io.emit('client-response', {
|
|
205
|
+
uid,
|
|
206
|
+
result,
|
|
207
|
+
})
|
|
208
|
+
// pub/sub: send event on associated channels
|
|
209
|
+
const publishFunc = service.publishCallback
|
|
210
|
+
if (publishFunc) {
|
|
211
|
+
const channelNames = await publishFunc(result, app)
|
|
212
|
+
console.log('publish channels', name, action, channelNames)
|
|
213
|
+
for (const channelName of channelNames) {
|
|
214
|
+
console.log('service-event', name, action, channelName)
|
|
215
|
+
const connectionList = Object.values(connections).filter(cnx => cnx.channelNames.has(channelName))
|
|
216
|
+
for (const connection of connectionList) {
|
|
217
|
+
console.log('emit to', connection.id)
|
|
218
|
+
connection.socket.emit('service-event', {
|
|
219
|
+
name,
|
|
220
|
+
action,
|
|
221
|
+
result,
|
|
222
|
+
})
|
|
223
|
+
}
|
|
226
224
|
}
|
|
227
225
|
}
|
|
226
|
+
} else {
|
|
227
|
+
io.emit('client-response', {
|
|
228
|
+
uid,
|
|
229
|
+
error: `there is no method named '${action}' for service '${name}'`,
|
|
230
|
+
})
|
|
228
231
|
}
|
|
229
232
|
} catch(error) {
|
|
230
233
|
io.emit('client-response', {
|
|
@@ -264,4 +267,4 @@ function expressX(app) {
|
|
|
264
267
|
return app
|
|
265
268
|
}
|
|
266
269
|
|
|
267
|
-
|
|
270
|
+
export default expressX
|