@platformatic/sql-graphql 0.0.23

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.
Files changed (54) hide show
  1. package/.nyc_output/0681b2b7-587a-40f2-8242-257bc4c72456.json +1 -0
  2. package/.nyc_output/191054d4-6a1e-4a1b-87bb-f801ed78a223.json +1 -0
  3. package/.nyc_output/22ead0f6-e5a6-4647-a2ea-db2f42498081.json +1 -0
  4. package/.nyc_output/4e847e26-05cd-4063-9277-48aff86d6822.json +1 -0
  5. package/.nyc_output/5acfd416-02d1-497b-8dbd-69c0af167c62.json +1 -0
  6. package/.nyc_output/5ec04f76-9bcb-475d-b79e-f9304cc0026c.json +1 -0
  7. package/.nyc_output/5f3bb47a-0d2d-440a-a466-8ffa9ab3efaa.json +1 -0
  8. package/.nyc_output/71c2bd84-9a72-4e86-83c6-d587ce525fe4.json +1 -0
  9. package/.nyc_output/74cc1dab-7479-48e7-80b0-c97351d8856e.json +1 -0
  10. package/.nyc_output/9f5d12ba-bc3d-461c-a0e2-2a95d2020c19.json +1 -0
  11. package/.nyc_output/ac343b71-6f76-421c-a287-46d19bb48f89.json +1 -0
  12. package/.nyc_output/c1c0eecb-63a0-4258-81b6-50e7488bd67c.json +1 -0
  13. package/.nyc_output/c201a1cd-3105-4d18-bbbb-8d7fa674d439.json +1 -0
  14. package/.nyc_output/d6da0270-e9ed-41e2-bbf3-9262d1df683c.json +1 -0
  15. package/.nyc_output/processinfo/0681b2b7-587a-40f2-8242-257bc4c72456.json +1 -0
  16. package/.nyc_output/processinfo/191054d4-6a1e-4a1b-87bb-f801ed78a223.json +1 -0
  17. package/.nyc_output/processinfo/22ead0f6-e5a6-4647-a2ea-db2f42498081.json +1 -0
  18. package/.nyc_output/processinfo/4e847e26-05cd-4063-9277-48aff86d6822.json +1 -0
  19. package/.nyc_output/processinfo/5acfd416-02d1-497b-8dbd-69c0af167c62.json +1 -0
  20. package/.nyc_output/processinfo/5ec04f76-9bcb-475d-b79e-f9304cc0026c.json +1 -0
  21. package/.nyc_output/processinfo/5f3bb47a-0d2d-440a-a466-8ffa9ab3efaa.json +1 -0
  22. package/.nyc_output/processinfo/71c2bd84-9a72-4e86-83c6-d587ce525fe4.json +1 -0
  23. package/.nyc_output/processinfo/74cc1dab-7479-48e7-80b0-c97351d8856e.json +1 -0
  24. package/.nyc_output/processinfo/9f5d12ba-bc3d-461c-a0e2-2a95d2020c19.json +1 -0
  25. package/.nyc_output/processinfo/ac343b71-6f76-421c-a287-46d19bb48f89.json +1 -0
  26. package/.nyc_output/processinfo/c1c0eecb-63a0-4258-81b6-50e7488bd67c.json +1 -0
  27. package/.nyc_output/processinfo/c201a1cd-3105-4d18-bbbb-8d7fa674d439.json +1 -0
  28. package/.nyc_output/processinfo/d6da0270-e9ed-41e2-bbf3-9262d1df683c.json +1 -0
  29. package/.nyc_output/processinfo/index.json +1 -0
  30. package/.taprc +1 -0
  31. package/LICENSE +201 -0
  32. package/NOTICE +13 -0
  33. package/README.md +13 -0
  34. package/index.d.ts +40 -0
  35. package/index.js +117 -0
  36. package/lib/entity-to-type.js +248 -0
  37. package/lib/relationship.js +67 -0
  38. package/lib/utils.js +77 -0
  39. package/package.json +44 -0
  40. package/test/datatypes.test.js +708 -0
  41. package/test/federation.test.js +312 -0
  42. package/test/helper.js +70 -0
  43. package/test/hooks.test.js +660 -0
  44. package/test/ignore.test.js +117 -0
  45. package/test/insert.test.js +181 -0
  46. package/test/inserted_updated_at.test.js +517 -0
  47. package/test/nested.test.js +862 -0
  48. package/test/no-modification-of-entity.test.js +113 -0
  49. package/test/order_by.test.js +397 -0
  50. package/test/relations.test.js +60 -0
  51. package/test/simple.test.js +708 -0
  52. package/test/sqlite.test.js +276 -0
  53. package/test/types/index.test-d.ts +33 -0
  54. package/test/where.test.js +814 -0
@@ -0,0 +1,312 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('tap')
4
+ const Fastify = require('fastify')
5
+ const mercurius = require('mercurius')
6
+ const sqlGraphQL = require('..')
7
+ const sqlMapper = require('@platformatic/sql-mapper')
8
+ const { clear, connInfo, isSQLite } = require('./helper')
9
+
10
+ async function createTestService (t, schema, resolvers = {}) {
11
+ const service = Fastify({ logger: { level: 'error' } })
12
+ service.register(mercurius, {
13
+ schema,
14
+ resolvers,
15
+ federationMetadata: true
16
+ })
17
+ await service.listen({ port: 0 })
18
+ return [service, service.server.address().port]
19
+ }
20
+
21
+ const categories = {
22
+ c1: {
23
+ id: 'c1',
24
+ name: 'Food'
25
+ },
26
+ c2: {
27
+ id: 'c2',
28
+ name: 'Places'
29
+ }
30
+ }
31
+
32
+ // This works because the database is reset between tests
33
+ const postCategory = {
34
+ 1: 'c1',
35
+ 2: 'c2',
36
+ 3: 'c1',
37
+ 4: 'c1'
38
+ }
39
+
40
+ const categoryPost = Object.keys(postCategory).reduce((acc, key) => {
41
+ acc[postCategory[key]] = acc[postCategory[key]] || []
42
+ acc[postCategory[key]].push(key)
43
+ return acc
44
+ }, {})
45
+
46
+ const posts = [{
47
+ title: 'Post 1',
48
+ longText: 'This is a long text 1'
49
+ }, {
50
+ title: 'Post 2',
51
+ longText: 'This is a long text 2'
52
+ }, {
53
+ title: 'Post 3',
54
+ longText: 'This is a long text 3'
55
+ }, {
56
+ title: 'Post 4',
57
+ longText: 'This is a long text 4'
58
+ }]
59
+
60
+ async function createTestGatewayServer (t, cacheOpts) {
61
+ const categoryServiceSchema = `
62
+ type Query @extends {
63
+ categories: [Category]
64
+ }
65
+
66
+ type Category @key(fields: "id") {
67
+ id: ID!
68
+ name: String
69
+ posts: [Post]
70
+ }
71
+
72
+ type Post @key(fields: "id") @extends {
73
+ id: ID! @external
74
+ category: Category
75
+ }
76
+ `
77
+ const categoryServiceResolvers = {
78
+ Query: {
79
+ categories: (root, args, context, info) => {
80
+ t.pass('Query.categories resolved')
81
+ return Object.values(categories)
82
+ }
83
+ },
84
+ Category: {
85
+ posts: (root, args, context, info) => {
86
+ t.pass('Category.posts resolved')
87
+ return categoryPost[root.id]
88
+ ? categoryPost[root.id].map(id => ({ id }))
89
+ : []
90
+ },
91
+ __resolveReference: (category, args, context, info) => {
92
+ t.pass('Category.__resolveReference')
93
+ return categories[category.id]
94
+ }
95
+ },
96
+ Post: {
97
+ category: (root, args, context, info) => {
98
+ t.pass('Post.category resolved')
99
+ return categories[postCategory[root.id]]
100
+ }
101
+ }
102
+ }
103
+ const [categoryService, categoryServicePort] = await createTestService(t, categoryServiceSchema, categoryServiceResolvers)
104
+
105
+ const postService = Fastify()
106
+ postService.register(sqlMapper, {
107
+ ...connInfo,
108
+ async onDatabaseLoad (db, sql) {
109
+ t.pass('onDatabaseLoad called')
110
+
111
+ await clear(db, sql)
112
+
113
+ if (isSQLite) {
114
+ await db.query(sql`CREATE TABLE posts (
115
+ id INTEGER PRIMARY KEY,
116
+ title VARCHAR(42),
117
+ long_text TEXT
118
+ );`)
119
+ } else {
120
+ await db.query(sql`CREATE TABLE posts (
121
+ id SERIAL PRIMARY KEY,
122
+ title VARCHAR(42),
123
+ long_text TEXT
124
+ );`)
125
+ }
126
+ }
127
+ })
128
+ postService.register(sqlGraphQL, {
129
+ federationMetadata: true
130
+ })
131
+ await postService.listen({ port: 0 })
132
+ const postServicePort = postService.server.address().port
133
+
134
+ await postService.inject({
135
+ method: 'POST',
136
+ url: '/graphql',
137
+ body: {
138
+ query: `
139
+ mutation batch($inputs : [PostInput]!) {
140
+ insertPosts(inputs: $inputs) {
141
+ id
142
+ title
143
+ }
144
+ }
145
+ `,
146
+ variables: {
147
+ inputs: posts
148
+ }
149
+ }
150
+ })
151
+
152
+ const gateway = Fastify()
153
+ t.teardown(async () => {
154
+ await gateway.close()
155
+ await categoryService.close()
156
+ await postService.close()
157
+ })
158
+ gateway.register(mercurius, {
159
+ gateway: {
160
+ services: [{
161
+ name: 'category',
162
+ url: `http://localhost:${categoryServicePort}/graphql`
163
+ }, {
164
+ name: 'post',
165
+ url: `http://localhost:${postServicePort}/graphql`
166
+ }]
167
+ }
168
+ })
169
+
170
+ return gateway
171
+ }
172
+
173
+ test('extendable', async (t) => {
174
+ const app = await createTestGatewayServer(t)
175
+
176
+ const query = `query {
177
+ categories {
178
+ id
179
+ name
180
+ posts {
181
+ id
182
+ title
183
+ longText
184
+ category {
185
+ id
186
+ name
187
+ }
188
+ }
189
+ }
190
+ posts {
191
+ id
192
+ title
193
+ category {
194
+ id
195
+ name
196
+ }
197
+ }
198
+ }`
199
+
200
+ const expected = {
201
+ data: {
202
+ categories: [
203
+ {
204
+ id: 'c1',
205
+ name: 'Food',
206
+ posts: [
207
+ {
208
+ id: '1',
209
+ title: 'Post 1',
210
+ longText: 'This is a long text 1',
211
+ category: {
212
+ id: 'c1',
213
+ name: 'Food'
214
+ }
215
+ },
216
+ {
217
+ id: '3',
218
+ title: 'Post 3',
219
+ longText: 'This is a long text 3',
220
+ category: {
221
+ id: 'c1',
222
+ name: 'Food'
223
+ }
224
+ },
225
+ {
226
+ id: '4',
227
+ title: 'Post 4',
228
+ longText: 'This is a long text 4',
229
+ category: {
230
+ id: 'c1',
231
+ name: 'Food'
232
+ }
233
+ }
234
+ ]
235
+ },
236
+ {
237
+ id: 'c2',
238
+ name: 'Places',
239
+ posts: [
240
+ {
241
+ id: '2',
242
+ title: 'Post 2',
243
+ longText: 'This is a long text 2',
244
+ category: {
245
+ id: 'c2',
246
+ name: 'Places'
247
+ }
248
+ }
249
+ ]
250
+ }
251
+ ],
252
+ posts: [
253
+ {
254
+ id: '1',
255
+ title: 'Post 1',
256
+ category: {
257
+ id: 'c1',
258
+ name: 'Food'
259
+ }
260
+ },
261
+ {
262
+ id: '2',
263
+ title: 'Post 2',
264
+ category: {
265
+ id: 'c2',
266
+ name: 'Places'
267
+ }
268
+ },
269
+ {
270
+ id: '3',
271
+ title: 'Post 3',
272
+ category: {
273
+ id: 'c1',
274
+ name: 'Food'
275
+ }
276
+ },
277
+ {
278
+ id: '4',
279
+ title: 'Post 4',
280
+ category: {
281
+ id: 'c1',
282
+ name: 'Food'
283
+ }
284
+ }
285
+ ]
286
+ }
287
+ }
288
+
289
+ t.comment('first request')
290
+
291
+ {
292
+ const res = await app.inject({
293
+ method: 'POST',
294
+ url: '/graphql',
295
+ body: { query }
296
+ })
297
+
298
+ t.same(res.json(), expected)
299
+ }
300
+
301
+ t.comment('second request')
302
+
303
+ {
304
+ const res = await app.inject({
305
+ method: 'POST',
306
+ url: '/graphql',
307
+ body: { query }
308
+ })
309
+
310
+ t.same(res.json(), expected)
311
+ }
312
+ })
package/test/helper.js ADDED
@@ -0,0 +1,70 @@
1
+ 'use strict'
2
+
3
+ // Needed to work with dates & postgresql
4
+ // See https://node-postgres.com/features/types/
5
+ process.env.TZ = 'UTC'
6
+
7
+ const connInfo = {}
8
+
9
+ if (!process.env.DB || process.env.DB === 'postgresql') {
10
+ connInfo.connectionString = 'postgres://postgres:postgres@127.0.0.1/postgres'
11
+ module.exports.isPg = true
12
+ } else if (process.env.DB === 'mariadb') {
13
+ connInfo.connectionString = 'mysql://root@127.0.0.1:3307/graph'
14
+ connInfo.poolSize = 10
15
+ module.exports.isMysql = true
16
+ } else if (process.env.DB === 'mysql') {
17
+ connInfo.connectionString = 'mysql://root@127.0.0.1/graph'
18
+ connInfo.poolSize = 10
19
+ module.exports.isMysql = true
20
+ } else if (process.env.DB === 'mysql8') {
21
+ connInfo.connectionString = 'mysql://root@127.0.0.1:3308/graph'
22
+ connInfo.poolSize = 10
23
+ module.exports.isMysql = true
24
+ } else if (process.env.DB === 'sqlite') {
25
+ connInfo.connectionString = 'sqlite://:memory:'
26
+ module.exports.isSQLite = true
27
+ }
28
+
29
+ module.exports.connInfo = connInfo
30
+
31
+ module.exports.clear = async function (db, sql) {
32
+ try {
33
+ await db.query(sql`DROP TABLE pages`)
34
+ } catch (err) {
35
+ }
36
+
37
+ try {
38
+ await db.query(sql`DROP TABLE categories`)
39
+ } catch {
40
+ }
41
+
42
+ try {
43
+ await db.query(sql`DROP TABLE posts`)
44
+ } catch {
45
+ }
46
+
47
+ try {
48
+ await db.query(sql`DROP TABLE simple_types`)
49
+ } catch {
50
+ }
51
+
52
+ try {
53
+ await db.query(sql`DROP TABLE owners`)
54
+ } catch {
55
+ }
56
+
57
+ try {
58
+ await db.query(sql`DROP TABLE users`)
59
+ } catch {
60
+ }
61
+
62
+ try {
63
+ await db.query(sql`DROP TABLE versions`)
64
+ } catch {
65
+ }
66
+ try {
67
+ await db.query(sql`DROP TABLE graphs`)
68
+ } catch {
69
+ }
70
+ }