@platformatic/sql-graphql 0.10.0 → 0.11.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/index.js +15 -1
- package/package.json +4 -4
- package/test/created_updated_at.test.js +517 -0
- package/test/helper.js +15 -0
- package/test/inserted_updated_at.test.js +17 -1
- package/test/schema-error.test.js +51 -0
package/index.js
CHANGED
|
@@ -118,7 +118,21 @@ async function mapperToGraphql (app, opts) {
|
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
let sdl =
|
|
121
|
+
let sdl = ''
|
|
122
|
+
try {
|
|
123
|
+
sdl = graphql.printSchema(new graphql.GraphQLSchema({ query, mutation, subscription }))
|
|
124
|
+
} catch (error) {
|
|
125
|
+
// The next lines are excluded from test coverage:
|
|
126
|
+
// it's quite hard to test the following lines for all of the DB types
|
|
127
|
+
/* istanbul ignore next */
|
|
128
|
+
app.log.debug({ query, mutation, subscription }, 'GraphQL input schema')
|
|
129
|
+
/* istanbul ignore next */
|
|
130
|
+
const newError = new Error('Error printing the GraphQL schema')
|
|
131
|
+
/* istanbul ignore next */
|
|
132
|
+
newError.cause = error
|
|
133
|
+
/* istanbul ignore next */
|
|
134
|
+
throw newError
|
|
135
|
+
}
|
|
122
136
|
|
|
123
137
|
if (opts.federationMetadata) {
|
|
124
138
|
for (const replacement of federationReplacements) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/sql-graphql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Map SQL dbs to GraphQL",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -14,14 +14,14 @@
|
|
|
14
14
|
},
|
|
15
15
|
"homepage": "https://github.com/platformatic/platformatic#readme",
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"@platformatic/sql-events": "0.10.0",
|
|
18
|
-
"@platformatic/sql-mapper": "0.10.0",
|
|
19
17
|
"fastify": "^4.6.0",
|
|
20
18
|
"snazzy": "^9.0.0",
|
|
21
19
|
"standard": "^17.0.0",
|
|
22
20
|
"tap": "^16.0.0",
|
|
23
21
|
"tsd": "^0.25.0",
|
|
24
|
-
"ws": "^8.9.0"
|
|
22
|
+
"ws": "^8.9.0",
|
|
23
|
+
"@platformatic/sql-events": "0.11.0",
|
|
24
|
+
"@platformatic/sql-mapper": "0.11.0"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"camelcase": "^6.0.0",
|
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('tap')
|
|
4
|
+
const sqlGraphQL = require('..')
|
|
5
|
+
const sqlMapper = require('@platformatic/sql-mapper')
|
|
6
|
+
const fastify = require('fastify')
|
|
7
|
+
const { clear, connInfo, isSQLite, isMysql } = require('./helper')
|
|
8
|
+
const { setTimeout } = require('timers/promises')
|
|
9
|
+
|
|
10
|
+
async function createBasicPages (db, sql) {
|
|
11
|
+
if (isSQLite) {
|
|
12
|
+
await db.query(sql`CREATE TABLE pages (
|
|
13
|
+
id INTEGER PRIMARY KEY,
|
|
14
|
+
title VARCHAR(42),
|
|
15
|
+
created_at TIMESTAMP,
|
|
16
|
+
updated_at TIMESTAMP
|
|
17
|
+
);`)
|
|
18
|
+
} else if (isMysql) {
|
|
19
|
+
await db.query(sql`CREATE TABLE pages (
|
|
20
|
+
id SERIAL PRIMARY KEY,
|
|
21
|
+
title VARCHAR(42),
|
|
22
|
+
created_at TIMESTAMP NULL DEFAULT NULL,
|
|
23
|
+
updated_at TIMESTAMP NULL DEFAULT NULL
|
|
24
|
+
);`)
|
|
25
|
+
} else {
|
|
26
|
+
await db.query(sql`CREATE TABLE pages (
|
|
27
|
+
id SERIAL PRIMARY KEY,
|
|
28
|
+
title VARCHAR(42),
|
|
29
|
+
created_at TIMESTAMP,
|
|
30
|
+
updated_at TIMESTAMP
|
|
31
|
+
);`)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
test('created_at updated_at happy path', async ({ pass, teardown, same, equal, not, comment }) => {
|
|
36
|
+
const app = fastify()
|
|
37
|
+
app.register(sqlMapper, {
|
|
38
|
+
...connInfo,
|
|
39
|
+
async onDatabaseLoad (db, sql) {
|
|
40
|
+
pass('onDatabaseLoad called')
|
|
41
|
+
|
|
42
|
+
await clear(db, sql)
|
|
43
|
+
await createBasicPages(db, sql)
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
app.register(sqlGraphQL)
|
|
47
|
+
teardown(app.close.bind(app))
|
|
48
|
+
|
|
49
|
+
await app.ready()
|
|
50
|
+
|
|
51
|
+
let original
|
|
52
|
+
|
|
53
|
+
{
|
|
54
|
+
const res = await app.inject({
|
|
55
|
+
method: 'POST',
|
|
56
|
+
url: '/graphql',
|
|
57
|
+
body: {
|
|
58
|
+
query: `
|
|
59
|
+
mutation {
|
|
60
|
+
savePage(input: { title: "Hello" }) {
|
|
61
|
+
id
|
|
62
|
+
title
|
|
63
|
+
createdAt
|
|
64
|
+
updatedAt
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
`
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
equal(res.statusCode, 200, 'savePage status code')
|
|
71
|
+
const data = res.json().data
|
|
72
|
+
not(data.savePage.createdAt, null, 'createdAt')
|
|
73
|
+
not(data.savePage.updatedAt, null, 'updatedAt')
|
|
74
|
+
comment(`createdAt: ${data.savePage.createdAt}`)
|
|
75
|
+
comment(`updatedAt: ${data.savePage.updatedAt}`)
|
|
76
|
+
original = data.savePage
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
{
|
|
80
|
+
const res = await app.inject({
|
|
81
|
+
method: 'POST',
|
|
82
|
+
url: '/graphql',
|
|
83
|
+
body: {
|
|
84
|
+
query: `
|
|
85
|
+
query {
|
|
86
|
+
getPageById(id: 1) {
|
|
87
|
+
id
|
|
88
|
+
title
|
|
89
|
+
createdAt
|
|
90
|
+
updatedAt
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
`
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
equal(res.statusCode, 200, 'pages status code')
|
|
97
|
+
const data = res.json().data
|
|
98
|
+
equal(data.getPageById.createdAt, original.createdAt, 'createdAt')
|
|
99
|
+
equal(data.getPageById.updatedAt, original.updatedAt, 'updatedAt')
|
|
100
|
+
comment(`createdAt: ${data.getPageById.createdAt}`)
|
|
101
|
+
comment(`updatedAt: ${data.getPageById.updatedAt}`)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
await setTimeout(1000) // await 1s
|
|
105
|
+
|
|
106
|
+
let updated
|
|
107
|
+
{
|
|
108
|
+
const res = await app.inject({
|
|
109
|
+
method: 'POST',
|
|
110
|
+
url: '/graphql',
|
|
111
|
+
body: {
|
|
112
|
+
query: `
|
|
113
|
+
mutation {
|
|
114
|
+
savePage(input: { id: 1, title: "Hello World" }) {
|
|
115
|
+
id
|
|
116
|
+
title
|
|
117
|
+
createdAt
|
|
118
|
+
updatedAt
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
`
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
const data = res.json().data
|
|
125
|
+
equal(data.savePage.createdAt, original.createdAt, 'createdAt')
|
|
126
|
+
not(data.savePage.updatedAt, original.updatedAt, 'updatedAt')
|
|
127
|
+
updated = data.savePage
|
|
128
|
+
comment(`createdAt: ${data.savePage.createdAt}`)
|
|
129
|
+
comment(`updatedAt: ${data.savePage.updatedAt}`)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
{
|
|
133
|
+
const res = await app.inject({
|
|
134
|
+
method: 'POST',
|
|
135
|
+
url: '/graphql',
|
|
136
|
+
body: {
|
|
137
|
+
query: `
|
|
138
|
+
query {
|
|
139
|
+
getPageById(id: 1) {
|
|
140
|
+
id
|
|
141
|
+
title
|
|
142
|
+
createdAt
|
|
143
|
+
updatedAt
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
`
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
equal(res.statusCode, 200, 'pages status code')
|
|
150
|
+
const data = res.json().data
|
|
151
|
+
equal(data.getPageById.createdAt, updated.createdAt, 'createdAt')
|
|
152
|
+
equal(data.getPageById.updatedAt, updated.updatedAt, 'updatedAt')
|
|
153
|
+
comment(`createdAt: ${data.getPageById.createdAt}`)
|
|
154
|
+
comment(`updatedAt: ${data.getPageById.updatedAt}`)
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
test('cannot set created_at', async ({ pass, teardown, same, equal, not, comment }) => {
|
|
159
|
+
const app = fastify()
|
|
160
|
+
app.register(sqlMapper, {
|
|
161
|
+
...connInfo,
|
|
162
|
+
async onDatabaseLoad (db, sql) {
|
|
163
|
+
pass('onDatabaseLoad called')
|
|
164
|
+
|
|
165
|
+
await clear(db, sql)
|
|
166
|
+
await createBasicPages(db, sql)
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
app.register(sqlGraphQL)
|
|
170
|
+
teardown(app.close.bind(app))
|
|
171
|
+
|
|
172
|
+
await app.ready()
|
|
173
|
+
|
|
174
|
+
{
|
|
175
|
+
const res = await app.inject({
|
|
176
|
+
method: 'POST',
|
|
177
|
+
url: '/graphql',
|
|
178
|
+
body: {
|
|
179
|
+
query: `
|
|
180
|
+
mutation {
|
|
181
|
+
savePage(input: { title: "Hello", createdAt: "${new Date().toISOString()}" }) {
|
|
182
|
+
id
|
|
183
|
+
title
|
|
184
|
+
createdAt
|
|
185
|
+
updatedAt
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
`
|
|
189
|
+
}
|
|
190
|
+
})
|
|
191
|
+
equal(res.statusCode, 400, 'savePage status code')
|
|
192
|
+
const data = res.json()
|
|
193
|
+
equal(data.errors[0].message, 'Field "createdAt" is not defined by type "PageInput".')
|
|
194
|
+
}
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
test('cannot set updated_at', async ({ pass, teardown, same, equal, not, comment }) => {
|
|
198
|
+
const app = fastify()
|
|
199
|
+
app.register(sqlMapper, {
|
|
200
|
+
...connInfo,
|
|
201
|
+
async onDatabaseLoad (db, sql) {
|
|
202
|
+
pass('onDatabaseLoad called')
|
|
203
|
+
|
|
204
|
+
await clear(db, sql)
|
|
205
|
+
await createBasicPages(db, sql)
|
|
206
|
+
}
|
|
207
|
+
})
|
|
208
|
+
app.register(sqlGraphQL)
|
|
209
|
+
teardown(app.close.bind(app))
|
|
210
|
+
|
|
211
|
+
await app.ready()
|
|
212
|
+
|
|
213
|
+
{
|
|
214
|
+
const res = await app.inject({
|
|
215
|
+
method: 'POST',
|
|
216
|
+
url: '/graphql',
|
|
217
|
+
body: {
|
|
218
|
+
query: `
|
|
219
|
+
mutation {
|
|
220
|
+
savePage(input: { title: "Hello" }) {
|
|
221
|
+
id
|
|
222
|
+
title
|
|
223
|
+
createdAt
|
|
224
|
+
updatedAt
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
`
|
|
228
|
+
}
|
|
229
|
+
})
|
|
230
|
+
equal(res.statusCode, 200, 'savePage status code')
|
|
231
|
+
const data = res.json().data
|
|
232
|
+
not(data.savePage.createdAt, null, 'createdAt')
|
|
233
|
+
not(data.savePage.updatedAt, null, 'updatedAt')
|
|
234
|
+
comment(`createdAt: ${data.savePage.createdAt}`)
|
|
235
|
+
comment(`updatedAt: ${data.savePage.updatedAt}`)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
{
|
|
239
|
+
const res = await app.inject({
|
|
240
|
+
method: 'POST',
|
|
241
|
+
url: '/graphql',
|
|
242
|
+
body: {
|
|
243
|
+
query: `
|
|
244
|
+
mutation {
|
|
245
|
+
savePage(input: { id: 1, title: "Hello World", updatedAt: "${new Date().toISOString()}" }) {
|
|
246
|
+
id
|
|
247
|
+
title
|
|
248
|
+
createdAt
|
|
249
|
+
updatedAt
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
`
|
|
253
|
+
}
|
|
254
|
+
})
|
|
255
|
+
equal(res.statusCode, 400, 'savePage status code')
|
|
256
|
+
const data = res.json()
|
|
257
|
+
equal(data.errors[0].message, 'Field "updatedAt" is not defined by type "PageInput".')
|
|
258
|
+
}
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
test('do not assign created_at updated_at', async ({ pass, teardown, same, equal, not, comment }) => {
|
|
262
|
+
const app = fastify()
|
|
263
|
+
app.register(sqlMapper, {
|
|
264
|
+
...connInfo,
|
|
265
|
+
autoTimestamp: false,
|
|
266
|
+
async onDatabaseLoad (db, sql) {
|
|
267
|
+
pass('onDatabaseLoad called')
|
|
268
|
+
|
|
269
|
+
await clear(db, sql)
|
|
270
|
+
await createBasicPages(db, sql)
|
|
271
|
+
}
|
|
272
|
+
})
|
|
273
|
+
app.register(sqlGraphQL)
|
|
274
|
+
teardown(app.close.bind(app))
|
|
275
|
+
|
|
276
|
+
await app.ready()
|
|
277
|
+
|
|
278
|
+
{
|
|
279
|
+
const res = await app.inject({
|
|
280
|
+
method: 'POST',
|
|
281
|
+
url: '/graphql',
|
|
282
|
+
body: {
|
|
283
|
+
query: `
|
|
284
|
+
mutation {
|
|
285
|
+
savePage(input: { title: "Hello" }) {
|
|
286
|
+
id
|
|
287
|
+
title
|
|
288
|
+
createdAt
|
|
289
|
+
updatedAt
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
`
|
|
293
|
+
}
|
|
294
|
+
})
|
|
295
|
+
equal(res.statusCode, 200, 'savePage status code')
|
|
296
|
+
const data = res.json().data
|
|
297
|
+
equal(data.savePage.createdAt, null, 'createdAt')
|
|
298
|
+
equal(data.savePage.updatedAt, null, 'updatedAt')
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
{
|
|
302
|
+
const res = await app.inject({
|
|
303
|
+
method: 'POST',
|
|
304
|
+
url: '/graphql',
|
|
305
|
+
body: {
|
|
306
|
+
query: `
|
|
307
|
+
query {
|
|
308
|
+
getPageById(id: 1) {
|
|
309
|
+
id
|
|
310
|
+
title
|
|
311
|
+
createdAt
|
|
312
|
+
updatedAt
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
`
|
|
316
|
+
}
|
|
317
|
+
})
|
|
318
|
+
equal(res.statusCode, 200, 'pages status code')
|
|
319
|
+
const data = res.json().data
|
|
320
|
+
equal(data.getPageById.createdAt, null, 'createdAt')
|
|
321
|
+
equal(data.getPageById.updatedAt, null, 'updatedAt')
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
{
|
|
325
|
+
const res = await app.inject({
|
|
326
|
+
method: 'POST',
|
|
327
|
+
url: '/graphql',
|
|
328
|
+
body: {
|
|
329
|
+
query: `
|
|
330
|
+
mutation {
|
|
331
|
+
savePage(input: { id: 1, title: "Hello World" }) {
|
|
332
|
+
id
|
|
333
|
+
title
|
|
334
|
+
createdAt
|
|
335
|
+
updatedAt
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
`
|
|
339
|
+
}
|
|
340
|
+
})
|
|
341
|
+
const data = res.json().data
|
|
342
|
+
equal(data.savePage.createdAt, null, 'createdAt')
|
|
343
|
+
equal(data.savePage.updatedAt, null, 'updatedAt')
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
{
|
|
347
|
+
const res = await app.inject({
|
|
348
|
+
method: 'POST',
|
|
349
|
+
url: '/graphql',
|
|
350
|
+
body: {
|
|
351
|
+
query: `
|
|
352
|
+
query {
|
|
353
|
+
getPageById(id: 1) {
|
|
354
|
+
id
|
|
355
|
+
title
|
|
356
|
+
createdAt
|
|
357
|
+
updatedAt
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
`
|
|
361
|
+
}
|
|
362
|
+
})
|
|
363
|
+
equal(res.statusCode, 200, 'pages status code')
|
|
364
|
+
const data = res.json().data
|
|
365
|
+
equal(data.getPageById.createdAt, null, 'createdAt')
|
|
366
|
+
equal(data.getPageById.updatedAt, null, 'updatedAt')
|
|
367
|
+
}
|
|
368
|
+
})
|
|
369
|
+
|
|
370
|
+
test('bulk insert adds created_at updated_at', async ({ pass, teardown, same, equal, not, comment }) => {
|
|
371
|
+
const app = fastify()
|
|
372
|
+
app.register(sqlMapper, {
|
|
373
|
+
...connInfo,
|
|
374
|
+
async onDatabaseLoad (db, sql) {
|
|
375
|
+
pass('onDatabaseLoad called')
|
|
376
|
+
|
|
377
|
+
await clear(db, sql)
|
|
378
|
+
await createBasicPages(db, sql)
|
|
379
|
+
}
|
|
380
|
+
})
|
|
381
|
+
app.register(sqlGraphQL)
|
|
382
|
+
teardown(app.close.bind(app))
|
|
383
|
+
|
|
384
|
+
await app.ready()
|
|
385
|
+
|
|
386
|
+
{
|
|
387
|
+
const res = await app.inject({
|
|
388
|
+
method: 'POST',
|
|
389
|
+
url: '/graphql',
|
|
390
|
+
body: {
|
|
391
|
+
query: `
|
|
392
|
+
mutation {
|
|
393
|
+
savePage(input: { title: "Hello" }) {
|
|
394
|
+
id
|
|
395
|
+
title
|
|
396
|
+
createdAt
|
|
397
|
+
updatedAt
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
`
|
|
401
|
+
}
|
|
402
|
+
})
|
|
403
|
+
equal(res.statusCode, 200, 'savePage status code')
|
|
404
|
+
const data = res.json().data
|
|
405
|
+
not(data.savePage.createdAt, null, 'createdAt')
|
|
406
|
+
not(data.savePage.updatedAt, null, 'updatedAt')
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
{
|
|
410
|
+
const res = await app.inject({
|
|
411
|
+
method: 'POST',
|
|
412
|
+
url: '/graphql',
|
|
413
|
+
body: {
|
|
414
|
+
query: `
|
|
415
|
+
mutation batch($inputs : [PageInput]!) {
|
|
416
|
+
insertPages (inputs: $inputs) {
|
|
417
|
+
id
|
|
418
|
+
title
|
|
419
|
+
createdAt
|
|
420
|
+
updatedAt
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
`,
|
|
424
|
+
variables: {
|
|
425
|
+
inputs: [
|
|
426
|
+
{ title: 'Page 1' },
|
|
427
|
+
{ title: 'Page 2' },
|
|
428
|
+
{ title: 'Page 3' }
|
|
429
|
+
]
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
})
|
|
433
|
+
equal(res.statusCode, 200, 'savePage status code')
|
|
434
|
+
const pages = res.json().data.insertPages
|
|
435
|
+
for (const page of pages) {
|
|
436
|
+
not(page.createdAt, null, 'createdAt')
|
|
437
|
+
not(page.updatedAt, null, 'updatedAt')
|
|
438
|
+
equal(page.createdAt, page.updatedAt, 'createdAt === updatedAt')
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
{
|
|
443
|
+
const res = await app.inject({
|
|
444
|
+
method: 'POST',
|
|
445
|
+
url: '/graphql',
|
|
446
|
+
body: {
|
|
447
|
+
query: `
|
|
448
|
+
query {
|
|
449
|
+
pages {
|
|
450
|
+
id
|
|
451
|
+
title
|
|
452
|
+
createdAt
|
|
453
|
+
updatedAt
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
`
|
|
457
|
+
}
|
|
458
|
+
})
|
|
459
|
+
equal(res.statusCode, 200, 'pages status code')
|
|
460
|
+
const pages = res.json().data.pages
|
|
461
|
+
for (const page of pages) {
|
|
462
|
+
not(page.createdAt, null, 'createdAt')
|
|
463
|
+
not(page.updatedAt, null, 'updatedAt')
|
|
464
|
+
equal(page.createdAt, page.updatedAt, 'createdAt === updatedAt')
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
test('bulk insert with autoTimestamp=false do not had created_at updated_at', async ({ pass, teardown, same, equal, not, comment }) => {
|
|
470
|
+
const app = fastify()
|
|
471
|
+
app.register(sqlMapper, {
|
|
472
|
+
...connInfo,
|
|
473
|
+
autoTimestamp: false,
|
|
474
|
+
async onDatabaseLoad (db, sql) {
|
|
475
|
+
pass('onDatabaseLoad called')
|
|
476
|
+
|
|
477
|
+
await clear(db, sql)
|
|
478
|
+
await createBasicPages(db, sql)
|
|
479
|
+
}
|
|
480
|
+
})
|
|
481
|
+
app.register(sqlGraphQL)
|
|
482
|
+
teardown(app.close.bind(app))
|
|
483
|
+
|
|
484
|
+
await app.ready()
|
|
485
|
+
|
|
486
|
+
{
|
|
487
|
+
const res = await app.inject({
|
|
488
|
+
method: 'POST',
|
|
489
|
+
url: '/graphql',
|
|
490
|
+
body: {
|
|
491
|
+
query: `
|
|
492
|
+
mutation batch($inputs : [PageInput]!) {
|
|
493
|
+
insertPages (inputs: $inputs) {
|
|
494
|
+
id
|
|
495
|
+
title
|
|
496
|
+
createdAt
|
|
497
|
+
updatedAt
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
`,
|
|
501
|
+
variables: {
|
|
502
|
+
inputs: [
|
|
503
|
+
{ title: 'Page 1' },
|
|
504
|
+
{ title: 'Page 2' },
|
|
505
|
+
{ title: 'Page 3' }
|
|
506
|
+
]
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
})
|
|
510
|
+
equal(res.statusCode, 200, 'savePage status code')
|
|
511
|
+
const pages = res.json().data.insertPages
|
|
512
|
+
for (const page of pages) {
|
|
513
|
+
equal(page.createdAt, null, 'createdAt')
|
|
514
|
+
equal(page.updatedAt, null, 'updatedAt')
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
})
|
package/test/helper.js
CHANGED
|
@@ -96,4 +96,19 @@ module.exports.clear = async function (db, sql) {
|
|
|
96
96
|
await db.query(sql`DROP Type simple_enum`)
|
|
97
97
|
} catch (err) {
|
|
98
98
|
}
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
await db.query(sql`DROP TABLE "myschema"."mytable"`)
|
|
102
|
+
} catch (err) {
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
await db.query(sql`DROP TABLE "myschema"."template"`)
|
|
107
|
+
} catch (err) {
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
await db.query(sql`DROP SCHEMA "myschema"`)
|
|
112
|
+
} catch (err) {
|
|
113
|
+
}
|
|
99
114
|
}
|
|
@@ -36,6 +36,10 @@ test('inserted_at updated_at happy path', async ({ pass, teardown, same, equal,
|
|
|
36
36
|
const app = fastify()
|
|
37
37
|
app.register(sqlMapper, {
|
|
38
38
|
...connInfo,
|
|
39
|
+
autoTimestamp: {
|
|
40
|
+
createdAt: 'inserted_at',
|
|
41
|
+
updatedAt: 'updated_at'
|
|
42
|
+
},
|
|
39
43
|
async onDatabaseLoad (db, sql) {
|
|
40
44
|
pass('onDatabaseLoad called')
|
|
41
45
|
|
|
@@ -159,6 +163,10 @@ test('cannot set inserted_at', async ({ pass, teardown, same, equal, not, commen
|
|
|
159
163
|
const app = fastify()
|
|
160
164
|
app.register(sqlMapper, {
|
|
161
165
|
...connInfo,
|
|
166
|
+
autoTimestamp: {
|
|
167
|
+
createdAt: 'inserted_at',
|
|
168
|
+
updatedAt: 'updated_at'
|
|
169
|
+
},
|
|
162
170
|
async onDatabaseLoad (db, sql) {
|
|
163
171
|
pass('onDatabaseLoad called')
|
|
164
172
|
|
|
@@ -198,6 +206,10 @@ test('cannot set updated_at', async ({ pass, teardown, same, equal, not, comment
|
|
|
198
206
|
const app = fastify()
|
|
199
207
|
app.register(sqlMapper, {
|
|
200
208
|
...connInfo,
|
|
209
|
+
autoTimestamp: {
|
|
210
|
+
createdAt: 'inserted_at',
|
|
211
|
+
updatedAt: 'updated_at'
|
|
212
|
+
},
|
|
201
213
|
async onDatabaseLoad (db, sql) {
|
|
202
214
|
pass('onDatabaseLoad called')
|
|
203
215
|
|
|
@@ -371,6 +383,10 @@ test('bulk insert adds inserted_at updated_at', async ({ pass, teardown, same, e
|
|
|
371
383
|
const app = fastify()
|
|
372
384
|
app.register(sqlMapper, {
|
|
373
385
|
...connInfo,
|
|
386
|
+
autoTimestamp: {
|
|
387
|
+
createdAt: 'inserted_at',
|
|
388
|
+
updatedAt: 'updated_at'
|
|
389
|
+
},
|
|
374
390
|
async onDatabaseLoad (db, sql) {
|
|
375
391
|
pass('onDatabaseLoad called')
|
|
376
392
|
|
|
@@ -466,7 +482,7 @@ test('bulk insert adds inserted_at updated_at', async ({ pass, teardown, same, e
|
|
|
466
482
|
}
|
|
467
483
|
})
|
|
468
484
|
|
|
469
|
-
test('bulk insert with autoTimestamp=false do not
|
|
485
|
+
test('bulk insert with autoTimestamp=false do not had inserted_at updated_at', async ({ pass, teardown, same, equal, not, comment }) => {
|
|
470
486
|
const app = fastify()
|
|
471
487
|
app.register(sqlMapper, {
|
|
472
488
|
...connInfo,
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('tap')
|
|
4
|
+
const sqlGraphQL = require('..')
|
|
5
|
+
const sqlMapper = require('@platformatic/sql-mapper')
|
|
6
|
+
const fastify = require('fastify')
|
|
7
|
+
const { clear, connInfo, isPg } = require('./helper')
|
|
8
|
+
|
|
9
|
+
const connInfoWithSchema = {
|
|
10
|
+
...connInfo,
|
|
11
|
+
schema: ['public', 'myschema']
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
test('should catch GraphQL print schema errors', { skip: !isPg }, async ({ pass, teardown, same }) => {
|
|
15
|
+
const app = fastify()
|
|
16
|
+
app.register(sqlMapper, {
|
|
17
|
+
...connInfoWithSchema,
|
|
18
|
+
async onDatabaseLoad (db, sql) {
|
|
19
|
+
pass('onDatabaseLoad called')
|
|
20
|
+
|
|
21
|
+
await clear(db, sql)
|
|
22
|
+
|
|
23
|
+
await db.query(sql`
|
|
24
|
+
CREATE SCHEMA IF NOT EXISTS "myschema";
|
|
25
|
+
|
|
26
|
+
CREATE TABLE IF NOT EXISTS "myschema"."template" (
|
|
27
|
+
"id" uuid NOT NULL,
|
|
28
|
+
PRIMARY KEY ("id")
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
CREATE TABLE IF NOT EXISTS "myschema"."mytable" (
|
|
32
|
+
"id" int4 NOT NULL,
|
|
33
|
+
"template_id" uuid,
|
|
34
|
+
CONSTRAINT "mytable_template" FOREIGN KEY ("template_id") REFERENCES "myschema"."template"("id"),
|
|
35
|
+
PRIMARY KEY ("id")
|
|
36
|
+
);`)
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
app.register(sqlGraphQL)
|
|
41
|
+
teardown(app.close.bind(app))
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
await app.ready()
|
|
45
|
+
same(true, false, 'We check that this line never runs, since we should catch the previous error')
|
|
46
|
+
} catch (error) {
|
|
47
|
+
same(error.name, 'Error')
|
|
48
|
+
same(error.message, 'Error printing the GraphQL schema')
|
|
49
|
+
same(error.cause, new Error('MyschemaTemplate.mytable field config must be an object.'))
|
|
50
|
+
}
|
|
51
|
+
})
|