@platformatic/sql-mapper 0.36.0 → 0.37.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/clean-up.js +36 -0
- package/mapper.d.ts +9 -0
- package/mapper.js +2 -0
- package/package.json +3 -2
- package/test/helper.js +10 -0
- package/test/mapper.test.js +88 -0
- package/test/types/mapper.test-d.ts +3 -0
package/lib/clean-up.js
ADDED
|
@@ -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.
|
|
3
|
+
"version": "0.37.1",
|
|
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.
|
|
33
|
+
"@platformatic/types": "0.37.1"
|
|
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 {
|
package/test/mapper.test.js
CHANGED
|
@@ -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
|
|