@jcbuisson/express-x 1.3.4 → 1.3.6
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 +3 -8
- package/src/common-hooks.mjs +1 -1
- package/src/server.mjs +16 -29
- package/test/index.test.js +46 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jcbuisson/express-x",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.6",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.mjs",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"license": "MIT",
|
|
13
13
|
"private": false,
|
|
14
14
|
"scripts": {
|
|
15
|
-
"test": "
|
|
15
|
+
"test": "node --test",
|
|
16
16
|
"generate": "npx prisma generate",
|
|
17
17
|
"migrate": "npx prisma migrate dev --name init"
|
|
18
18
|
},
|
|
@@ -21,14 +21,9 @@
|
|
|
21
21
|
"@jcbuisson/express-x-client": "^1.0.10",
|
|
22
22
|
"@prisma/client": "^4.10.1",
|
|
23
23
|
"axios": "^1.4.0",
|
|
24
|
-
"
|
|
24
|
+
"bcryptjs": "^2.4.3",
|
|
25
25
|
"config": "^3.3.9",
|
|
26
|
-
"esm": "^3.2.25",
|
|
27
26
|
"express": "^4.18.2",
|
|
28
27
|
"socket.io": "^4.6.0"
|
|
29
|
-
},
|
|
30
|
-
"devDependencies": {
|
|
31
|
-
"chai": "^4.3.7",
|
|
32
|
-
"mocha": "^10.2.0"
|
|
33
28
|
}
|
|
34
29
|
}
|
package/src/common-hooks.mjs
CHANGED
package/src/server.mjs
CHANGED
|
@@ -75,7 +75,7 @@ export function expressX(options = {}) {
|
|
|
75
75
|
// call method
|
|
76
76
|
const result = await method(...context.args)
|
|
77
77
|
app.log('debug', `result ${result}`)
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
// call 'after' hooks
|
|
80
80
|
const afterMethodHooks = service?.hooks?.after && service.hooks.after[methodName] || []
|
|
81
81
|
const afterAllHooks = service?.hooks?.after?.all || []
|
|
@@ -127,27 +127,14 @@ export function expressX(options = {}) {
|
|
|
127
127
|
http: { name: service.name }
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
// introspect
|
|
131
|
-
async function
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
fieldTypes[column.name] = column.type.toLowerCase()
|
|
139
|
-
})
|
|
140
|
-
} else if (service.prisma._activeProvider === 'postgresql') {
|
|
141
|
-
const fieldInfo = await service.prisma.$queryRawUnsafe(`
|
|
142
|
-
SELECT column_name, data_type
|
|
143
|
-
FROM information_schema.columns
|
|
144
|
-
WHERE table_name = '${service.entity}';
|
|
145
|
-
`)
|
|
146
|
-
fieldInfo.forEach(column => {
|
|
147
|
-
fieldTypes[column.column_name] = column.data_type
|
|
148
|
-
})
|
|
149
|
-
}
|
|
150
|
-
return fieldTypes
|
|
130
|
+
// introspect schema
|
|
131
|
+
async function getTypesMap() {
|
|
132
|
+
const dmmf = await service.prisma._getDmmf()
|
|
133
|
+
const fieldDescriptions = dmmf.modelMap[service.name].fields
|
|
134
|
+
return fieldDescriptions.reduce((accu, descr) => {
|
|
135
|
+
accu[descr.name] = descr.type
|
|
136
|
+
return accu
|
|
137
|
+
}, {})
|
|
151
138
|
}
|
|
152
139
|
|
|
153
140
|
|
|
@@ -172,23 +159,23 @@ export function expressX(options = {}) {
|
|
|
172
159
|
// the values in `req.query` are all strings, but Prisma need proper types
|
|
173
160
|
// we need to introspect column types and do the proper transtyping
|
|
174
161
|
for (const fieldName in query) {
|
|
175
|
-
|
|
176
|
-
const fieldType =
|
|
162
|
+
const typesDict = await getTypesMap()
|
|
163
|
+
const fieldType = typesDict[fieldName]
|
|
177
164
|
|
|
178
|
-
if (fieldType === '
|
|
165
|
+
if (fieldType === 'Int') {
|
|
179
166
|
query[fieldName] = parseInt(query[fieldName])
|
|
180
|
-
} else if (fieldType === '
|
|
167
|
+
} else if (fieldType === 'Float') {
|
|
181
168
|
query[fieldName] = parseFloat(query[fieldName])
|
|
182
|
-
} else if (fieldType === '
|
|
169
|
+
} else if (fieldType === 'Boolean') {
|
|
183
170
|
query[fieldName] = (query[fieldName] === 't') ? true : false
|
|
184
|
-
} else if (fieldType === '
|
|
171
|
+
} else if (fieldType === 'String') {
|
|
185
172
|
query[fieldName] = query[fieldName]
|
|
186
173
|
} else {
|
|
187
174
|
// ?
|
|
188
175
|
query[fieldName] = query[fieldName]
|
|
189
176
|
}
|
|
190
177
|
}
|
|
191
|
-
|
|
178
|
+
// call __findMany
|
|
192
179
|
const values = await service.__findMany(context, {
|
|
193
180
|
where: query,
|
|
194
181
|
})
|
package/test/index.test.js
CHANGED
|
@@ -4,7 +4,9 @@ import axios from 'axios'
|
|
|
4
4
|
import io from 'socket.io-client'
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
import { assert } from 'chai'
|
|
7
|
+
// import { assert } from 'chai'
|
|
8
|
+
import { describe, it, before, after, beforeEach, afterEach } from 'node:test'
|
|
9
|
+
import { strict as assert } from 'node:assert'
|
|
8
10
|
|
|
9
11
|
import { expressX, expressXClient } from '../src/index.mjs'
|
|
10
12
|
|
|
@@ -12,13 +14,18 @@ import { expressX, expressXClient } from '../src/index.mjs'
|
|
|
12
14
|
// `app` is a regular express application, enhanced with services and real-time features
|
|
13
15
|
const app = expressX()
|
|
14
16
|
|
|
15
|
-
app.createDatabaseService('User')
|
|
16
|
-
app.createDatabaseService('Post')
|
|
17
|
-
|
|
18
17
|
|
|
19
18
|
|
|
20
19
|
describe('ExpressX API (no running server)', () => {
|
|
21
20
|
|
|
21
|
+
before(async () => {
|
|
22
|
+
app.createDatabaseService('User')
|
|
23
|
+
app.createDatabaseService('Post')
|
|
24
|
+
|
|
25
|
+
await app.service('User').deleteMany()
|
|
26
|
+
await app.service('Post').deleteMany()
|
|
27
|
+
})
|
|
28
|
+
|
|
22
29
|
it("can delete all users", async () => {
|
|
23
30
|
const res = await app.service('User').deleteMany()
|
|
24
31
|
console.log('res delete', res)
|
|
@@ -61,24 +68,41 @@ describe('HTTP/REST API', () => {
|
|
|
61
68
|
|
|
62
69
|
let chris
|
|
63
70
|
|
|
64
|
-
before(() => {
|
|
71
|
+
before(async () => {
|
|
72
|
+
console.log("before")
|
|
65
73
|
// add body parsers for http requests
|
|
66
74
|
app.use(bodyParser.json())
|
|
67
75
|
app.use(bodyParser.urlencoded({ extended: false }))
|
|
68
76
|
|
|
77
|
+
app.createDatabaseService('User')
|
|
78
|
+
app.createDatabaseService('Post')
|
|
79
|
+
|
|
80
|
+
await app.service('User').deleteMany()
|
|
81
|
+
await app.service('Post').deleteMany()
|
|
82
|
+
|
|
69
83
|
// add http/rest endpoints
|
|
70
84
|
app.addHttpRest('/api/user', app.service('User'))
|
|
71
85
|
app.addHttpRest('/api/post', app.service('Post'))
|
|
72
86
|
|
|
73
|
-
|
|
87
|
+
await new Promise((resolve) => {
|
|
88
|
+
app.server.listen(8008, () => {
|
|
89
|
+
console.log(`App listening at http://localhost:8008`)
|
|
90
|
+
resolve()
|
|
91
|
+
})
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
after(() => {
|
|
96
|
+
console.log("after")
|
|
97
|
+
app.server.close()
|
|
74
98
|
})
|
|
75
99
|
|
|
76
100
|
it("can create a user", async () => {
|
|
77
101
|
const res = await axios.post('http://localhost:8008/api/user', {
|
|
78
|
-
name: "
|
|
79
|
-
email: '
|
|
102
|
+
name: "chris",
|
|
103
|
+
email: 'chris@mail.fr'
|
|
80
104
|
})
|
|
81
|
-
assert(res?.data?.name === '
|
|
105
|
+
assert(res?.data?.name === 'chris')
|
|
82
106
|
})
|
|
83
107
|
|
|
84
108
|
it("can find users", async () => {
|
|
@@ -110,23 +134,32 @@ describe('HTTP/REST API', () => {
|
|
|
110
134
|
})
|
|
111
135
|
|
|
112
136
|
after(async () => {
|
|
113
|
-
|
|
137
|
+
app.server.close()
|
|
114
138
|
})
|
|
115
139
|
})
|
|
116
140
|
|
|
117
141
|
|
|
118
|
-
// test compatibility with
|
|
142
|
+
// test compatibility with client API
|
|
119
143
|
describe('Client API', () => {
|
|
120
144
|
|
|
121
145
|
let clientApp, socket
|
|
122
146
|
|
|
123
|
-
before(() => {
|
|
124
|
-
|
|
147
|
+
before(async () => {
|
|
148
|
+
await new Promise((resolve) => {
|
|
149
|
+
app.server.listen(8008, () => {
|
|
150
|
+
console.log(`App listening at http://localhost:8008`)
|
|
151
|
+
resolve()
|
|
152
|
+
})
|
|
153
|
+
})
|
|
125
154
|
|
|
126
155
|
socket = io('http://localhost:8008', { transports: ["websocket"] })
|
|
127
156
|
clientApp = expressXClient(socket)
|
|
128
157
|
})
|
|
129
158
|
|
|
159
|
+
after(async () => {
|
|
160
|
+
app.server.close()
|
|
161
|
+
})
|
|
162
|
+
|
|
130
163
|
it("can create a user", async () => {
|
|
131
164
|
const user = await clientApp.service('User').create({
|
|
132
165
|
data: {
|