@platformatic/sql-mapper 0.7.0 → 0.9.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/test/helper.js CHANGED
@@ -21,6 +21,7 @@ if (!process.env.DB || process.env.DB === 'postgresql') {
21
21
  connInfo.connectionString = 'mysql://root@127.0.0.1:3308/graph'
22
22
  connInfo.poolSize = 10
23
23
  module.exports.isMysql = true
24
+ module.exports.isMysql8 = true
24
25
  } else if (process.env.DB === 'sqlite') {
25
26
  connInfo.connectionString = 'sqlite://:memory:'
26
27
  module.exports.isSQLite = true
@@ -29,6 +30,11 @@ if (!process.env.DB || process.env.DB === 'postgresql') {
29
30
  module.exports.connInfo = connInfo
30
31
 
31
32
  module.exports.clear = async function (db, sql) {
33
+ try {
34
+ await db.query(sql`DROP TABLE editors`)
35
+ } catch {
36
+ }
37
+
32
38
  try {
33
39
  await db.query(sql`DROP TABLE pages`)
34
40
  } catch (err) {
@@ -68,4 +74,19 @@ module.exports.clear = async function (db, sql) {
68
74
  await db.query(sql`DROP TYPE pagetype`)
69
75
  } catch {
70
76
  }
77
+
78
+ try {
79
+ await db.query(sql`DROP TABLE test1.pages`)
80
+ } catch (err) {
81
+ }
82
+
83
+ try {
84
+ await db.query(sql`DROP TABLE test2.users`)
85
+ } catch (err) {
86
+ }
87
+
88
+ try {
89
+ await db.query(sql`DROP TABLE test2.pages`)
90
+ } catch (err) {
91
+ }
71
92
  }
@@ -6,7 +6,8 @@ const fastify = require('fastify')
6
6
 
7
7
  const fakeLogger = {
8
8
  trace: () => {},
9
- error: () => {}
9
+ error: () => {},
10
+ warn: () => {}
10
11
  }
11
12
 
12
13
  test('should throw if no connection string is provided', async ({ equal }) => {
@@ -193,96 +194,19 @@ test('missing connectionString', async ({ rejects }) => {
193
194
  await rejects(app.ready(), /connectionString/)
194
195
  })
195
196
 
196
- test('[pg] throws if no primary key', { skip: !isPg }, async ({ pass, teardown, equal }) => {
197
+ test('throw if no primary keys', async ({ rejects, teardown }) => {
197
198
  async function onDatabaseLoad (db, sql) {
198
199
  await clear(db, sql)
199
- teardown(() => db.dispose())
200
-
201
- await db.query(sql`CREATE TABLE IF NOT EXISTS pages (
202
- id SERIAL,
203
- title VARCHAR(255) NOT NULL
204
- );`)
205
- }
206
- try {
207
- await connect({
208
- connectionString: connInfo.connectionString,
209
- log: fakeLogger,
210
- onDatabaseLoad,
211
- ignore: {},
212
- hooks: {}
213
- })
214
- } catch (err) {
215
- equal(err.message, 'Cannot find primary key for Page entity')
216
- }
217
- })
218
-
219
- test('[mysql] throws if no primary key', { skip: !isMysql }, async ({ pass, teardown, equal }) => {
220
- async function onDatabaseLoad (db, sql) {
221
- await clear(db, sql)
222
- teardown(() => db.dispose())
223
200
 
224
201
  await db.query(sql`CREATE TABLE pages (
225
- id SERIAL,
226
202
  title VARCHAR(255) NOT NULL
227
203
  );`)
228
204
  }
229
- try {
230
- await connect({
231
- connectionString: connInfo.connectionString,
232
- log: fakeLogger,
233
- onDatabaseLoad,
234
- ignore: {},
235
- hooks: {}
236
- })
237
- } catch (err) {
238
- equal(err.message, 'Cannot find primary key for Page entity')
239
- }
240
- })
241
-
242
- test('[sqlite] throws if primary key is not defined', { skip: !isSQLite }, async ({ pass, teardown, equal }) => {
243
- async function onDatabaseLoad (db, sql) {
244
- await clear(db, sql)
245
-
246
- await db.query(sql`CREATE TABLE pages(
247
- id INTEGER NOT NULL,
248
- title TEXT NOT NULL
249
- );
250
- `)
251
- }
252
- try {
253
- await connect({
254
- connectionString: connInfo.connectionString,
255
- log: fakeLogger,
256
- onDatabaseLoad,
257
- ignore: {},
258
- hooks: {}
259
- })
260
- } catch (err) {
261
- equal(err.message, 'Cannot find primary key for Page entity')
262
- }
263
- })
264
-
265
- test('[sqlite] throws with multiple primary keys', { skip: !isSQLite }, async ({ pass, teardown, equal }) => {
266
- async function onDatabaseLoad (db, sql) {
267
- await clear(db, sql)
268
-
269
- await db.query(sql`CREATE TABLE pages(
270
- id INTEGER NOT NULL,
271
- author_id INTEGER NOT NULL,
272
- title TEXT NOT NULL,
273
- PRIMARY KEY (id, author_id)
274
- );
275
- `)
276
- }
277
- try {
278
- await connect({
279
- connectionString: connInfo.connectionString,
280
- log: fakeLogger,
281
- onDatabaseLoad,
282
- ignore: {},
283
- hooks: {}
284
- })
285
- } catch (err) {
286
- equal(err.message, 'Table pages has 2 primary keys')
287
- }
205
+ await rejects(connect({
206
+ connectionString: connInfo.connectionString,
207
+ log: fakeLogger,
208
+ onDatabaseLoad,
209
+ ignore: {},
210
+ hooks: {}
211
+ }))
288
212
  })
@@ -0,0 +1,320 @@
1
+ const { test } = require('tap')
2
+ const { connect } = require('..')
3
+
4
+ const { connInfo, isSQLite, isMysql, isMysql8, isPg, clear } = require('./helper')
5
+
6
+ const fakeLogger = {
7
+ trace: () => {},
8
+ error: () => {}
9
+ }
10
+
11
+ test('uses tables from different schemas', { skip: isSQLite }, async ({ pass, teardown, equal }) => {
12
+ async function onDatabaseLoad (db, sql) {
13
+ await clear(db, sql)
14
+ teardown(() => db.dispose())
15
+
16
+ await db.query(sql`CREATE SCHEMA IF NOT EXISTS test1;`)
17
+ if (isMysql || isMysql8) {
18
+ await db.query(sql`CREATE TABLE IF NOT EXISTS \`test1\`.\`pages\` (
19
+ id SERIAL PRIMARY KEY,
20
+ title VARCHAR(255) NOT NULL
21
+ );`)
22
+ } else {
23
+ await db.query(sql`CREATE TABLE IF NOT EXISTS "test1"."pages" (
24
+ id SERIAL PRIMARY KEY,
25
+ title VARCHAR(255) NOT NULL
26
+ );`)
27
+ }
28
+
29
+ await db.query(sql`CREATE SCHEMA IF NOT EXISTS test2;`)
30
+
31
+ if (isMysql || isMysql8) {
32
+ await db.query(sql`CREATE TABLE IF NOT EXISTS \`test2\`.\`users\` (
33
+ id SERIAL PRIMARY KEY,
34
+ username VARCHAR(255) NOT NULL
35
+ );`)
36
+ } else {
37
+ await db.query(sql`CREATE TABLE IF NOT EXISTS "test2"."users" (
38
+ id SERIAL PRIMARY KEY,
39
+ username VARCHAR(255) NOT NULL
40
+ );`)
41
+ }
42
+ }
43
+ const mapper = await connect({
44
+ connectionString: connInfo.connectionString,
45
+ log: fakeLogger,
46
+ onDatabaseLoad,
47
+ ignore: {},
48
+ hooks: {},
49
+ schema: ['test1', 'test2']
50
+ })
51
+ const pageEntity = mapper.entities.test1Page
52
+ equal(pageEntity.name, 'Test1Page')
53
+ equal(pageEntity.singularName, 'test1Page')
54
+ equal(pageEntity.pluralName, 'test1Pages')
55
+ equal(pageEntity.schema, 'test1')
56
+ const userEntity = mapper.entities.test2User
57
+ equal(userEntity.name, 'Test2User')
58
+ equal(userEntity.singularName, 'test2User')
59
+ equal(userEntity.pluralName, 'test2Users')
60
+ equal(userEntity.schema, 'test2')
61
+ pass()
62
+ })
63
+
64
+ test('find enums correctly using schemas', { skip: isSQLite }, async ({ pass, teardown, equal }) => {
65
+ async function onDatabaseLoad (db, sql) {
66
+ await clear(db, sql)
67
+ teardown(() => db.dispose())
68
+
69
+ await db.query(sql`CREATE SCHEMA IF NOT EXISTS test1;`)
70
+ if (isMysql || isMysql8) {
71
+ await db.query(sql`
72
+ CREATE TABLE IF NOT EXISTS \`test1\`.\`pages\` (
73
+ id SERIAL PRIMARY KEY,
74
+ title VARCHAR(255) NOT NULL,
75
+ type ENUM ('blank', 'non-blank')
76
+ );`)
77
+ } else if (isPg) {
78
+ await db.query(sql`
79
+ CREATE TYPE pagetype as enum ('blank', 'non-blank');
80
+ CREATE TABLE IF NOT EXISTS "test1"."pages" (
81
+ id SERIAL PRIMARY KEY,
82
+ title VARCHAR(255) NOT NULL,
83
+ type pagetype
84
+ );`)
85
+ } else {
86
+ await db.query(sql`CREATE TABLE IF NOT EXISTS "test1"."pages" (
87
+ id SERIAL PRIMARY KEY,
88
+ title VARCHAR(255) NOT NULL,
89
+ type ENUM ('blank', 'non-blank')
90
+ );`)
91
+ }
92
+ }
93
+ const mapper = await connect({
94
+ connectionString: connInfo.connectionString,
95
+ log: fakeLogger,
96
+ onDatabaseLoad,
97
+ ignore: {},
98
+ hooks: {},
99
+ schema: ['test1']
100
+ })
101
+ const pageEntity = mapper.entities.test1Page
102
+ equal(pageEntity.name, 'Test1Page')
103
+ equal(pageEntity.singularName, 'test1Page')
104
+ equal(pageEntity.pluralName, 'test1Pages')
105
+ pass()
106
+ })
107
+
108
+ test('if schema is empty array, should not load entities from tables in explicit schema', { skip: isSQLite }, async ({ pass, teardown, equal }) => {
109
+ async function onDatabaseLoad (db, sql) {
110
+ await clear(db, sql)
111
+ teardown(() => db.dispose())
112
+
113
+ await db.query(sql`CREATE SCHEMA IF NOT EXISTS test1;`)
114
+ if (isMysql || isMysql8) {
115
+ await db.query(sql`CREATE TABLE IF NOT EXISTS \`test1\`.\`pages\` (
116
+ id SERIAL PRIMARY KEY,
117
+ title VARCHAR(255) NOT NULL
118
+ );`)
119
+ } else {
120
+ await db.query(sql`CREATE TABLE IF NOT EXISTS "test1"."pages" (
121
+ id SERIAL PRIMARY KEY,
122
+ title VARCHAR(255) NOT NULL
123
+ );`)
124
+ }
125
+
126
+ await db.query(sql`CREATE SCHEMA IF NOT EXISTS test2;`)
127
+
128
+ if (isMysql || isMysql8) {
129
+ await db.query(sql`CREATE TABLE IF NOT EXISTS \`test2\`.\`users\` (
130
+ id SERIAL PRIMARY KEY,
131
+ username VARCHAR(255) NOT NULL
132
+ );`)
133
+ } else {
134
+ await db.query(sql`CREATE TABLE IF NOT EXISTS "test2"."users" (
135
+ id SERIAL PRIMARY KEY,
136
+ username VARCHAR(255) NOT NULL
137
+ );`)
138
+ }
139
+ }
140
+ const mapper = await connect({
141
+ connectionString: connInfo.connectionString,
142
+ log: fakeLogger,
143
+ onDatabaseLoad,
144
+ ignore: {},
145
+ hooks: {},
146
+ schema: []
147
+ })
148
+
149
+ equal(Object.keys(mapper.entities).length, 0)
150
+ pass()
151
+ })
152
+
153
+ test('[pg] if schema is empty array, should find entities only in default \'public\' schema', { skip: !isPg }, async ({ pass, teardown, equal }) => {
154
+ async function onDatabaseLoad (db, sql) {
155
+ await clear(db, sql)
156
+ teardown(() => db.dispose())
157
+
158
+ await db.query(sql`CREATE TABLE IF NOT EXISTS pages (
159
+ id SERIAL PRIMARY KEY,
160
+ title VARCHAR(255) NOT NULL
161
+ );`)
162
+
163
+ await db.query(sql`CREATE SCHEMA IF NOT EXISTS test2;`)
164
+ await db.query(sql`CREATE TABLE IF NOT EXISTS "test2"."users" (
165
+ id SERIAL PRIMARY KEY,
166
+ username VARCHAR(255) NOT NULL
167
+ );`)
168
+ }
169
+ const mapper = await connect({
170
+ connectionString: connInfo.connectionString,
171
+ log: fakeLogger,
172
+ onDatabaseLoad,
173
+ ignore: {},
174
+ hooks: {},
175
+ schema: []
176
+ })
177
+
178
+ equal(Object.keys(mapper.entities).length, 1)
179
+ const pageEntity = mapper.entities.page
180
+ equal(pageEntity.name, 'Page')
181
+ equal(pageEntity.singularName, 'page')
182
+ equal(pageEntity.pluralName, 'pages')
183
+ equal(pageEntity.schema, 'public')
184
+ pass()
185
+ })
186
+
187
+ test('[sqlite] if sqllite, ignores schema information', { skip: !isSQLite }, async ({ pass, teardown, equal }) => {
188
+ async function onDatabaseLoad (db, sql) {
189
+ await clear(db, sql)
190
+ teardown(() => db.dispose())
191
+ await db.query(sql`CREATE TABLE "pages" (
192
+ "id" INTEGER PRIMARY KEY,
193
+ "title" TEXT NOT NULL
194
+ );`)
195
+ }
196
+ const mapper = await connect({
197
+ connectionString: connInfo.connectionString,
198
+ log: fakeLogger,
199
+ onDatabaseLoad,
200
+ ignore: {},
201
+ hooks: {},
202
+ schema: ['ignored', 'also_ignored']
203
+ })
204
+
205
+ equal(Object.keys(mapper.entities).length, 1)
206
+ const pageEntity = mapper.entities.page
207
+ equal(pageEntity.name, 'Page')
208
+ equal(pageEntity.singularName, 'page')
209
+ equal(pageEntity.pluralName, 'pages')
210
+ equal(pageEntity.schema, null)
211
+ pass()
212
+ })
213
+
214
+ test('addEntityHooks in entities with schema', { skip: isSQLite }, async ({ pass, teardown, same, equal, plan, fail, throws, end }) => {
215
+ async function onDatabaseLoad (db, sql) {
216
+ await clear(db, sql)
217
+ teardown(() => db.dispose())
218
+
219
+ await db.query(sql`CREATE SCHEMA IF NOT EXISTS test1;`)
220
+ if (isMysql || isMysql8) {
221
+ await db.query(sql`CREATE TABLE IF NOT EXISTS \`test1\`.\`pages\` (
222
+ id SERIAL PRIMARY KEY,
223
+ title VARCHAR(255) NOT NULL
224
+ );`)
225
+ } else {
226
+ await db.query(sql`CREATE TABLE IF NOT EXISTS "test1"."pages" (
227
+ id SERIAL PRIMARY KEY,
228
+ title VARCHAR(255) NOT NULL
229
+ );`)
230
+ }
231
+ }
232
+
233
+ const mapper = await connect({
234
+ ...connInfo,
235
+ log: fakeLogger,
236
+ onDatabaseLoad,
237
+ schema: ['test1']
238
+ })
239
+
240
+ throws(() => mapper.addEntityHooks('user', {}), 'Cannot find entity user')
241
+
242
+ mapper.addEntityHooks('test1Page', {
243
+ noKey () {
244
+ fail('noKey should never be called')
245
+ },
246
+ async save (original, { input, ctx, fields }) {
247
+ pass('save called')
248
+
249
+ if (!input.id) {
250
+ same(input, {
251
+ title: 'Hello'
252
+ })
253
+
254
+ return original({
255
+ input: {
256
+ title: 'Hello from hook'
257
+ },
258
+ fields
259
+ })
260
+ } else {
261
+ same(input, {
262
+ id: 1,
263
+ title: 'Hello World'
264
+ })
265
+
266
+ return original({
267
+ input: {
268
+ id: 1,
269
+ title: 'Hello from hook 2'
270
+ },
271
+ fields
272
+ })
273
+ }
274
+ },
275
+ async find (original, args) {
276
+ pass('find called')
277
+
278
+ same(args.where, {
279
+ id: {
280
+ eq: '1'
281
+ }
282
+ })
283
+ args.where = {
284
+ id: {
285
+ eq: '2'
286
+ }
287
+ }
288
+ same(args.fields, ['id', 'title'])
289
+ return original(args)
290
+ },
291
+ async insert (original, args) {
292
+ pass('insert called')
293
+
294
+ same(args.inputs, [{
295
+ title: 'hello'
296
+ }, {
297
+ title: 'world'
298
+ }])
299
+ same(args.fields, ['id', 'title'])
300
+ return original(args)
301
+ }
302
+ })
303
+
304
+ const entity = mapper.entities.test1Page
305
+
306
+ same(await entity.save({ input: { title: 'Hello' } }), {
307
+ id: 1,
308
+ title: 'Hello from hook'
309
+ })
310
+
311
+ same(await entity.find({ where: { id: { eq: 1 } }, fields: ['id', 'title'] }), [])
312
+
313
+ same(await entity.save({ input: { id: 1, title: 'Hello World' } }), {
314
+ id: 1,
315
+ title: 'Hello from hook 2'
316
+ })
317
+
318
+ await entity.insert({ inputs: [{ title: 'hello' }, { title: 'world' }], fields: ['id', 'title'] })
319
+ end()
320
+ })