@platformatic/sql-mapper 0.36.0 → 0.37.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.
@@ -0,0 +1,36 @@
1
+ 'use strict'
2
+
3
+ const { tableName } = require('./utils')
4
+ const { Sorter } = require('@hapi/topo')
5
+
6
+ function buildCleanUp (db, sql, logger, entities) {
7
+ return async function cleanUp () {
8
+ logger.trace('cleaning up')
9
+ await db.tx(async tx => {
10
+ const topo = new Sorter()
11
+ const lookup = new Map()
12
+
13
+ for (const entity of Object.values(entities)) {
14
+ /* istanbul ignore next */
15
+ const relations = entity.relations.map(relation => {
16
+ // there is a name clash here with tables with the
17
+ // same name in different schemas
18
+ return relation.foreign_table_name
19
+ })
20
+ lookup.set(entity.table, entity)
21
+
22
+ const name = entity.table
23
+
24
+ topo.add(name, { before: relations, group: name })
25
+ }
26
+
27
+ for (const name of topo.nodes) {
28
+ const entity = lookup.get(name)
29
+ const toDelete = tableName(sql, entity.table, entity.schema)
30
+ await tx.query(sql`DELETE FROM ${toDelete}`)
31
+ }
32
+ })
33
+ }
34
+ }
35
+
36
+ module.exports = buildCleanUp
package/mapper.d.ts CHANGED
@@ -331,6 +331,11 @@ export interface SQLMapperPluginInterface {
331
331
  * Adds hooks to the entity.
332
332
  */
333
333
  addEntityHooks<EntityFields>(entityName: string, hooks: EntityHooks<EntityFields>): any
334
+
335
+ /**
336
+ * Clean up all the data in all entities
337
+ */
338
+ cleanUpAllEntities(): Promise<void>
334
339
  }
335
340
 
336
341
  // Extend the PlatformaticApp interface,
@@ -353,6 +358,10 @@ declare module '@platformatic/types' {
353
358
  * Adds hooks to the entity.
354
359
  */
355
360
  addEntityHooks<EntityFields>(entityName: string, hooks: EntityHooks<EntityFields>): any
361
+ /**
362
+ * Clean up all the data in all entities
363
+ */
364
+ cleanUpAllEntities(): Promise<void>
356
365
  }
357
366
  }
358
367
 
package/mapper.js CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const buildEntity = require('./lib/entity')
4
+ const buildCleanUp = require('./lib/clean-up')
4
5
  const queriesFactory = require('./lib/queries')
5
6
  const fp = require('fastify-plugin')
6
7
  const { areSchemasSupported } = require('./lib/utils')
@@ -172,6 +173,7 @@ async function connect ({ connectionString, log, onDatabaseLoad, poolSize = 10,
172
173
  db,
173
174
  sql,
174
175
  entities,
176
+ cleanUpAllEntities: buildCleanUp(db, sql, log, entities, queries),
175
177
  addEntityHooks,
176
178
  dbschema
177
179
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/sql-mapper",
3
- "version": "0.36.0",
3
+ "version": "0.37.0",
4
4
  "description": "A data mapper utility for SQL databases",
5
5
  "main": "mapper.js",
6
6
  "types": "mapper.d.ts",
@@ -25,11 +25,12 @@
25
25
  "@databases/mysql": "^6.0.0",
26
26
  "@databases/pg": "^5.4.1",
27
27
  "@databases/sql": "^3.3.0",
28
+ "@hapi/topo": "^6.0.2",
28
29
  "@matteo.collina/sqlite-pool": "^0.3.0",
29
30
  "camelcase": "^6.3.0",
30
31
  "fastify-plugin": "^4.5.0",
31
32
  "inflected": "^2.1.0",
32
- "@platformatic/types": "0.36.0"
33
+ "@platformatic/types": "0.37.0"
33
34
  },
34
35
  "tsd": {
35
36
  "directory": "test/types"
package/test/helper.js CHANGED
@@ -35,6 +35,11 @@ if (!process.env.DB || process.env.DB === 'postgresql') {
35
35
  module.exports.connInfo = connInfo
36
36
 
37
37
  module.exports.clear = async function (db, sql) {
38
+ try {
39
+ await db.query(sql`DROP TABLE graphs`)
40
+ } catch {
41
+ }
42
+
38
43
  try {
39
44
  await db.query(sql`DROP TABLE editors`)
40
45
  } catch {
@@ -45,6 +50,11 @@ module.exports.clear = async function (db, sql) {
45
50
  } catch (err) {
46
51
  }
47
52
 
53
+ try {
54
+ await db.query(sql`DROP TABLE comments`)
55
+ } catch (err) {
56
+ }
57
+
48
58
  try {
49
59
  await db.query(sql`DROP TABLE categories`)
50
60
  } catch {
@@ -235,3 +235,91 @@ test('platformatic decorator already present', async ({ teardown }) => {
235
235
  })
236
236
  await app.ready()
237
237
  })
238
+
239
+ test('clean up all tables', async ({ teardown, has, equal, same }) => {
240
+ async function onDatabaseLoad (db, sql) {
241
+ await clear(db, sql)
242
+ teardown(async () => await clear(db, sql))
243
+ teardown(() => db.dispose())
244
+
245
+ await db.query(sql`CREATE TABLE IF NOT EXISTS pages (
246
+ id SERIAL PRIMARY KEY,
247
+ title VARCHAR(255) NOT NULL
248
+ );`)
249
+ }
250
+ const mapper = await connect({
251
+ connectionString: connInfo.connectionString,
252
+ log: fakeLogger,
253
+ onDatabaseLoad
254
+ })
255
+
256
+ const res = await mapper.entities.page.save({ input: { title: 'hello' } })
257
+
258
+ same(await mapper.entities.page.find(), [res])
259
+
260
+ await mapper.cleanUpAllEntities()
261
+
262
+ const pages = await mapper.entities.page.find()
263
+ equal(pages.length, 0)
264
+ })
265
+
266
+ test('clean up all tables with foreign keys', async ({ teardown, has, equal, same }) => {
267
+ async function onDatabaseLoad (db, sql) {
268
+ await clear(db, sql)
269
+ teardown(async () => await clear(db, sql))
270
+ teardown(() => db.dispose())
271
+
272
+ if (db.isSQLite) {
273
+ await db.query(sql`CREATE TABLE IF NOT EXISTS pages (
274
+ id INTEGER PRIMARY KEY,
275
+ title VARCHAR(255) NOT NULL
276
+ );`)
277
+ await db.query(sql`CREATE TABLE IF NOT EXISTS comments (
278
+ id INTEGER PRIMARY KEY,
279
+ text VARCHAR(255) NOT NULL,
280
+ page_id INTEGER NOT NULL REFERENCES pages(id)
281
+ );`)
282
+ } else if (db.isPg) {
283
+ await db.query(sql`CREATE TABLE IF NOT EXISTS pages (
284
+ id SERIAL PRIMARY KEY,
285
+ title VARCHAR(255) NOT NULL
286
+ );`)
287
+ await db.query(sql`CREATE TABLE IF NOT EXISTS comments (
288
+ id SERIAL PRIMARY KEY,
289
+ text VARCHAR(255) NOT NULL,
290
+ page_id INTEGER NOT NULL REFERENCES pages(id)
291
+ );`)
292
+ } else {
293
+ await db.query(sql`CREATE TABLE IF NOT EXISTS pages (
294
+ id INTEGER PRIMARY KEY AUTO_INCREMENT,
295
+ title VARCHAR(255) NOT NULL
296
+ );`)
297
+ await db.query(sql`CREATE TABLE IF NOT EXISTS comments (
298
+ id INTEGER PRIMARY KEY AUTO_INCREMENT,
299
+ text VARCHAR(255) NOT NULL,
300
+ page_id INTEGER NOT NULL REFERENCES pages(id)
301
+ );`)
302
+ }
303
+ }
304
+ const mapper = await connect({
305
+ connectionString: connInfo.connectionString,
306
+ log: fakeLogger,
307
+ onDatabaseLoad
308
+ })
309
+
310
+ {
311
+ const p1 = await mapper.entities.page.save({ input: { title: 'hello' } })
312
+ same(await mapper.entities.page.find(), [p1])
313
+
314
+ const c1 = await mapper.entities.comment.save({ input: { text: 'foo', pageId: p1.id } })
315
+ same(await mapper.entities.comment.find(), [c1])
316
+ }
317
+
318
+ await mapper.cleanUpAllEntities()
319
+
320
+ const pages = await mapper.entities.page.find()
321
+ equal(pages.length, 0)
322
+
323
+ const comments = await mapper.entities.comment.find()
324
+ equal(comments.length, 0)
325
+ })
@@ -17,6 +17,8 @@ expectType<Database>(pluginOptions.db)
17
17
  expectType<SQL>(pluginOptions.sql)
18
18
  expectType<{ [entityName: string]: Entity }>(pluginOptions.entities)
19
19
 
20
+ expectType<Promise<void>>(pluginOptions.cleanUpAllEntities())
21
+
20
22
  interface EntityFields {
21
23
  id: number,
22
24
  name: string,
@@ -88,6 +90,7 @@ instance.register((instance) => {
88
90
  const ctx = request.platformaticContext
89
91
  expectType<FastifyInstance>(ctx.app)
90
92
  expectType<FastifyReply>(ctx.reply)
93
+ await instance.platformatic.cleanUpAllEntities()
91
94
  })
92
95
  })
93
96