@platformatic/sql-graphql 0.12.1 → 0.13.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/lib/entity-to-type.js +11 -5
- package/lib/relationship.js +1 -1
- package/package.json +3 -3
- package/test/enum.test.js +125 -0
- package/test/helper.js +20 -0
- package/test/schema.test.js +111 -1
package/lib/entity-to-type.js
CHANGED
|
@@ -49,13 +49,19 @@ function constructGraph (app, entity, opts, ignore) {
|
|
|
49
49
|
// sqlite doesn't support enums
|
|
50
50
|
/* istanbul ignore next */
|
|
51
51
|
if (field.enum) {
|
|
52
|
-
const enumValues = field.enum.reduce((acc, enumValue) => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
const enumValues = field.enum.reduce((acc, enumValue, index) => {
|
|
53
|
+
let key = enumValue.replace(/[^\w\s]/g, '_')
|
|
54
|
+
|
|
55
|
+
const keyStartsWithLetterOrUnderscore = !!key.match(/^[_a-zA-Z]/g)
|
|
56
|
+
if (!keyStartsWithLetterOrUnderscore) {
|
|
57
|
+
key = `_${key}`
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (key.startsWith('__')) {
|
|
61
|
+
key = key.replace('__', `enum${++index}`)
|
|
56
62
|
}
|
|
57
63
|
|
|
58
|
-
acc[
|
|
64
|
+
acc[key] = { value: enumValue }
|
|
59
65
|
return acc
|
|
60
66
|
}, {})
|
|
61
67
|
try {
|
package/lib/relationship.js
CHANGED
|
@@ -23,7 +23,7 @@ module.exports = function establishRelations (app, relations, resolvers, loaders
|
|
|
23
23
|
|
|
24
24
|
const current = entitiesTypeMap[entityName]
|
|
25
25
|
const foreign = entitiesTypeMap[foreignEntityName]
|
|
26
|
-
assert(foreign !== undefined, `No foreign table named "${foreign_table_name}" was found ${enhanceAssertLogMsg}`)
|
|
26
|
+
assert(foreign !== undefined, `No foreign table named "${foreign_table_name}" was found ${enhanceAssertLogMsg}. Relation: ${JSON.stringify(relation, null, 2)}`)
|
|
27
27
|
|
|
28
28
|
// current to foreign, we skip this if the foreign table has a composite primary key
|
|
29
29
|
// TODO implement support for this case
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/sql-graphql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.1",
|
|
4
4
|
"description": "Map SQL dbs to GraphQL",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"tap": "^16.3.2",
|
|
21
21
|
"tsd": "^0.25.0",
|
|
22
22
|
"ws": "^8.11.0",
|
|
23
|
-
"@platformatic/sql-events": "0.
|
|
24
|
-
"@platformatic/sql-mapper": "0.
|
|
23
|
+
"@platformatic/sql-events": "0.13.1",
|
|
24
|
+
"@platformatic/sql-mapper": "0.13.1"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"camelcase": "^6.3.0",
|
package/test/enum.test.js
CHANGED
|
@@ -98,3 +98,128 @@ test('should not fail if tables have duplicate enum names', { skip: isSQLite },
|
|
|
98
98
|
same(true, false, 'Previous call should never fail')
|
|
99
99
|
}
|
|
100
100
|
})
|
|
101
|
+
|
|
102
|
+
test('should not fail if tables have enum with special characters', { skip: isSQLite }, async ({ pass, teardown, same, equal }) => {
|
|
103
|
+
const app = fastify()
|
|
104
|
+
app.register(sqlMapper, {
|
|
105
|
+
...connInfo,
|
|
106
|
+
async onDatabaseLoad (db, sql) {
|
|
107
|
+
pass('onDatabaseLoad called')
|
|
108
|
+
|
|
109
|
+
await clear(db, sql)
|
|
110
|
+
|
|
111
|
+
if (isPg) {
|
|
112
|
+
await db.query(sql`
|
|
113
|
+
CREATE TYPE custom_enum AS ENUM('.', ',');
|
|
114
|
+
|
|
115
|
+
CREATE TABLE enum_tests (
|
|
116
|
+
id INTEGER NOT NULL,
|
|
117
|
+
test_enum custom_enum,
|
|
118
|
+
PRIMARY KEY (id)
|
|
119
|
+
);
|
|
120
|
+
`)
|
|
121
|
+
} else {
|
|
122
|
+
await db.query(sql`
|
|
123
|
+
CREATE TABLE enum_tests (
|
|
124
|
+
id INTEGER NOT NULL,
|
|
125
|
+
test_enum ENUM ('.', ',') DEFAULT NULL,
|
|
126
|
+
PRIMARY KEY (id)
|
|
127
|
+
);
|
|
128
|
+
`)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
app.register(sqlGraphQL)
|
|
134
|
+
teardown(app.close.bind(app))
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
await app.ready()
|
|
138
|
+
same(true, true, 'custom_enum have special chars, but app does not throws')
|
|
139
|
+
} catch (err) {
|
|
140
|
+
console.log(err)
|
|
141
|
+
same(true, false, 'Previous call should never fail')
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
{
|
|
145
|
+
const res = await app.inject({
|
|
146
|
+
method: 'POST',
|
|
147
|
+
url: '/graphql',
|
|
148
|
+
body: {
|
|
149
|
+
query: `
|
|
150
|
+
mutation ($input: EnumTestInput!) {
|
|
151
|
+
saveEnumTest(input: $input) {
|
|
152
|
+
id
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
`,
|
|
156
|
+
variables: { input: { id: 1 } }
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
equal(res.statusCode, 200)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
{
|
|
163
|
+
const res = await app.inject({
|
|
164
|
+
method: 'POST',
|
|
165
|
+
url: '/graphql',
|
|
166
|
+
body: {
|
|
167
|
+
query: `
|
|
168
|
+
mutation ($input: EnumTestInput!) {
|
|
169
|
+
saveEnumTest(input: $input) {
|
|
170
|
+
id
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
`,
|
|
174
|
+
variables: { input: { id: 2 } }
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
equal(res.statusCode, 200)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
{
|
|
181
|
+
const res = await app.inject({
|
|
182
|
+
method: 'POST',
|
|
183
|
+
url: '/graphql',
|
|
184
|
+
body: {
|
|
185
|
+
query: `
|
|
186
|
+
query { enumTests { id } }
|
|
187
|
+
`
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
equal(res.statusCode, 200)
|
|
191
|
+
same(res.json(), { data: { enumTests: [{ id: 1 }, { id: 2 }] } })
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
{
|
|
195
|
+
const res = await app.inject({
|
|
196
|
+
method: 'POST',
|
|
197
|
+
url: '/graphql',
|
|
198
|
+
body: {
|
|
199
|
+
query: `
|
|
200
|
+
mutation ($input: EnumTestWhereArgumentsid!) {
|
|
201
|
+
deleteEnumTests(where: {id: $input}) {
|
|
202
|
+
id
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
`,
|
|
206
|
+
variables: { input: { eq: 1 } }
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
equal(res.statusCode, 200)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
{
|
|
213
|
+
const res = await app.inject({
|
|
214
|
+
method: 'POST',
|
|
215
|
+
url: '/graphql',
|
|
216
|
+
body: {
|
|
217
|
+
query: `
|
|
218
|
+
query { enumTests { id } }
|
|
219
|
+
`
|
|
220
|
+
}
|
|
221
|
+
})
|
|
222
|
+
equal(res.statusCode, 200)
|
|
223
|
+
same(res.json(), { data: { enumTests: [{ id: 2 }] } })
|
|
224
|
+
}
|
|
225
|
+
})
|
package/test/helper.js
CHANGED
|
@@ -127,6 +127,16 @@ module.exports.clear = async function (db, sql) {
|
|
|
127
127
|
} catch (err) {
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
try {
|
|
131
|
+
await db.query(sql`DROP TABLE test4.books`)
|
|
132
|
+
} catch (err) {
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
await db.query(sql`DROP TABLE test3.authors`)
|
|
137
|
+
} catch (err) {
|
|
138
|
+
}
|
|
139
|
+
|
|
130
140
|
try {
|
|
131
141
|
await db.query(sql`DROP TABLE test2.books`)
|
|
132
142
|
} catch (err) {
|
|
@@ -137,6 +147,16 @@ module.exports.clear = async function (db, sql) {
|
|
|
137
147
|
} catch (err) {
|
|
138
148
|
}
|
|
139
149
|
|
|
150
|
+
try {
|
|
151
|
+
await db.query(sql`DROP SCHEMA test4`)
|
|
152
|
+
} catch (err) {
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
await db.query(sql`DROP SCHEMA test3`)
|
|
157
|
+
} catch (err) {
|
|
158
|
+
}
|
|
159
|
+
|
|
140
160
|
try {
|
|
141
161
|
await db.query(sql`DROP SCHEMA test2`)
|
|
142
162
|
} catch (err) {
|
package/test/schema.test.js
CHANGED
|
@@ -4,7 +4,7 @@ const { test } = require('tap')
|
|
|
4
4
|
const sqlGraphQL = require('..')
|
|
5
5
|
const sqlMapper = require('@platformatic/sql-mapper')
|
|
6
6
|
const fastify = require('fastify')
|
|
7
|
-
const { isSQLite, connInfo, isMysql, clear } = require('./helper')
|
|
7
|
+
const { isSQLite, isPg, connInfo, isMysql, clear } = require('./helper')
|
|
8
8
|
|
|
9
9
|
test('should handle relationships with different schemas', { skip: isSQLite }, async ({ pass, teardown, same, equal }) => {
|
|
10
10
|
const app = fastify()
|
|
@@ -165,3 +165,113 @@ test('should handle relationships with different schemas', { skip: isSQLite }, a
|
|
|
165
165
|
}, 'query authors response')
|
|
166
166
|
}
|
|
167
167
|
})
|
|
168
|
+
|
|
169
|
+
test('should not throw if all of the schema with contraint references are loaded on the config', { skip: !isPg }, async ({ pass, teardown, same }) => {
|
|
170
|
+
const app = fastify()
|
|
171
|
+
app.register(sqlMapper, {
|
|
172
|
+
...connInfo,
|
|
173
|
+
schema: ['test1', 'test2', 'test3', 'test4'],
|
|
174
|
+
async onDatabaseLoad (db, sql) {
|
|
175
|
+
pass('onDatabaseLoad called')
|
|
176
|
+
|
|
177
|
+
await clear(db, sql)
|
|
178
|
+
|
|
179
|
+
await db.query(sql`CREATE SCHEMA IF NOT EXISTS test1;`)
|
|
180
|
+
await db.query(sql`CREATE SCHEMA IF NOT EXISTS test2;`)
|
|
181
|
+
await db.query(sql`CREATE SCHEMA IF NOT EXISTS test3;`)
|
|
182
|
+
await db.query(sql`CREATE SCHEMA IF NOT EXISTS test4;`)
|
|
183
|
+
await db.query(sql`
|
|
184
|
+
CREATE TABLE test1.authors (
|
|
185
|
+
id INTEGER PRIMARY KEY,
|
|
186
|
+
name VARCHAR(42)
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
CREATE TABLE test2.books (
|
|
190
|
+
id INTEGER PRIMARY KEY,
|
|
191
|
+
title VARCHAR(42),
|
|
192
|
+
author_id INTEGER
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
CREATE TABLE test3.authors (
|
|
196
|
+
id INTEGER PRIMARY KEY,
|
|
197
|
+
name VARCHAR(42)
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
CREATE TABLE test4.books (
|
|
201
|
+
id INTEGER PRIMARY KEY,
|
|
202
|
+
title VARCHAR(42),
|
|
203
|
+
author_id INTEGER
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
ALTER TABLE ONLY test2.books
|
|
207
|
+
ADD CONSTRAINT authors_fkey FOREIGN KEY (author_id) REFERENCES test1.authors(id);
|
|
208
|
+
|
|
209
|
+
ALTER TABLE ONLY test4.books
|
|
210
|
+
ADD CONSTRAINT authors_fkey FOREIGN KEY (author_id) REFERENCES test3.authors(id);
|
|
211
|
+
`)
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
app.register(sqlGraphQL)
|
|
215
|
+
teardown(app.close.bind(app))
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
await app.ready()
|
|
219
|
+
} catch (error) {
|
|
220
|
+
same(true, false, 'app should not throw')
|
|
221
|
+
}
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
test('should not throw if some of the schema with contraint references are not passed to the config', { skip: !isPg }, async ({ pass, teardown, same }) => {
|
|
225
|
+
const app = fastify()
|
|
226
|
+
app.register(sqlMapper, {
|
|
227
|
+
...connInfo,
|
|
228
|
+
schema: ['test1', 'test2'],
|
|
229
|
+
async onDatabaseLoad (db, sql) {
|
|
230
|
+
pass('onDatabaseLoad called')
|
|
231
|
+
|
|
232
|
+
await clear(db, sql)
|
|
233
|
+
|
|
234
|
+
await db.query(sql`CREATE SCHEMA IF NOT EXISTS test1;`)
|
|
235
|
+
await db.query(sql`CREATE SCHEMA IF NOT EXISTS test2;`)
|
|
236
|
+
await db.query(sql`CREATE SCHEMA IF NOT EXISTS test3;`)
|
|
237
|
+
await db.query(sql`CREATE SCHEMA IF NOT EXISTS test4;`)
|
|
238
|
+
await db.query(sql`
|
|
239
|
+
CREATE TABLE test1.authors (
|
|
240
|
+
id INTEGER PRIMARY KEY,
|
|
241
|
+
name VARCHAR(42)
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
CREATE TABLE test2.books (
|
|
245
|
+
id INTEGER PRIMARY KEY,
|
|
246
|
+
title VARCHAR(42),
|
|
247
|
+
author_id INTEGER
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
CREATE TABLE test3.authors (
|
|
251
|
+
id INTEGER PRIMARY KEY,
|
|
252
|
+
name VARCHAR(42)
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
CREATE TABLE test4.books (
|
|
256
|
+
id INTEGER PRIMARY KEY,
|
|
257
|
+
title VARCHAR(42),
|
|
258
|
+
author_id INTEGER
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
ALTER TABLE ONLY test2.books
|
|
262
|
+
ADD CONSTRAINT authors_fkey FOREIGN KEY (author_id) REFERENCES test1.authors(id);
|
|
263
|
+
|
|
264
|
+
ALTER TABLE ONLY test4.books
|
|
265
|
+
ADD CONSTRAINT authors_fkey FOREIGN KEY (author_id) REFERENCES test3.authors(id);
|
|
266
|
+
`)
|
|
267
|
+
}
|
|
268
|
+
})
|
|
269
|
+
app.register(sqlGraphQL)
|
|
270
|
+
teardown(app.close.bind(app))
|
|
271
|
+
|
|
272
|
+
try {
|
|
273
|
+
await app.ready()
|
|
274
|
+
} catch (error) {
|
|
275
|
+
same(true, false, 'we expect the app to not throw')
|
|
276
|
+
}
|
|
277
|
+
})
|