@platformatic/sql-mapper 0.45.1 → 0.46.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.js +9 -0
- package/mapper.js +13 -0
- package/package.json +3 -2
- package/test/ignore.test.js +187 -0
- package/test/types/mapper.test-d.ts +0 -1
package/lib/entity.js
CHANGED
|
@@ -8,6 +8,7 @@ const {
|
|
|
8
8
|
sanitizeLimit
|
|
9
9
|
} = require('./utils')
|
|
10
10
|
const { singularize } = require('inflected')
|
|
11
|
+
const { findNearestString } = require('@platformatic/utils')
|
|
11
12
|
const errors = require('./errors')
|
|
12
13
|
|
|
13
14
|
function lowerCaseFirst (str) {
|
|
@@ -369,6 +370,14 @@ function createMapper (defaultDb, sql, log, table, fields, primaryKeys, relation
|
|
|
369
370
|
}
|
|
370
371
|
|
|
371
372
|
function buildEntity (db, sql, log, table, queries, autoTimestamp, schema, useSchemaInName, ignore, limitConfig, schemaList, columns, constraintsList) {
|
|
373
|
+
const columnsNames = columns.map(c => c.column_name)
|
|
374
|
+
for (const ignoredColumn of Object.keys(ignore)) {
|
|
375
|
+
if (!columnsNames.includes(ignoredColumn)) {
|
|
376
|
+
const nearestColumn = findNearestString(columnsNames, ignoredColumn)
|
|
377
|
+
log.warn(`Ignored column "${ignoredColumn}" not found. Did you mean "${nearestColumn}"?`)
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
372
381
|
// Compute the columns
|
|
373
382
|
columns = columns.filter((c) => !ignore[c.column_name])
|
|
374
383
|
const fields = columns.reduce((acc, column) => {
|
package/mapper.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { findNearestString } = require('@platformatic/utils')
|
|
3
4
|
const buildEntity = require('./lib/entity')
|
|
4
5
|
const buildCleanUp = require('./lib/clean-up')
|
|
5
6
|
const queriesFactory = require('./lib/queries')
|
|
@@ -158,6 +159,18 @@ async function connect ({ connectionString, log, onDatabaseLoad, poolSize, ignor
|
|
|
158
159
|
}
|
|
159
160
|
}
|
|
160
161
|
|
|
162
|
+
const schemaTables = dbschema.map(table => table.table)
|
|
163
|
+
for (const ignoredTable of Object.keys(ignore)) {
|
|
164
|
+
if (!schemaTables.includes(ignoredTable)) {
|
|
165
|
+
const nearestTable = findNearestString(schemaTables, ignoredTable)
|
|
166
|
+
let warningMessage = `Ignored table "${ignoredTable}" not found.`
|
|
167
|
+
if (nearestTable) {
|
|
168
|
+
warningMessage += ` Did you mean "${nearestTable}"?`
|
|
169
|
+
}
|
|
170
|
+
log.warn(warningMessage)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
161
174
|
for (const { table, schema, columns, constraints } of dbschema) {
|
|
162
175
|
// The following line is a safety net when developing this module,
|
|
163
176
|
// it should never happen.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/sql-mapper",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.46.1",
|
|
4
4
|
"description": "A data mapper utility for SQL databases",
|
|
5
5
|
"main": "mapper.js",
|
|
6
6
|
"types": "mapper.d.ts",
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
"@matteo.collina/sqlite-pool": "^0.3.0",
|
|
31
31
|
"camelcase": "^6.3.0",
|
|
32
32
|
"fastify-plugin": "^4.5.0",
|
|
33
|
-
"inflected": "^2.1.0"
|
|
33
|
+
"inflected": "^2.1.0",
|
|
34
|
+
"@platformatic/utils": "0.46.1"
|
|
34
35
|
},
|
|
35
36
|
"tsd": {
|
|
36
37
|
"directory": "test/types"
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('tap')
|
|
4
|
+
const { connect } = require('..')
|
|
5
|
+
const { clear, connInfo, isSQLite } = require('./helper')
|
|
6
|
+
|
|
7
|
+
const fakeLogger = {
|
|
8
|
+
trace: () => {},
|
|
9
|
+
error: () => {},
|
|
10
|
+
warn: () => {}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function createBasicPages (db, sql) {
|
|
14
|
+
if (isSQLite) {
|
|
15
|
+
await db.query(sql`CREATE TABLE pages (
|
|
16
|
+
id INTEGER PRIMARY KEY,
|
|
17
|
+
title VARCHAR(42)
|
|
18
|
+
);`)
|
|
19
|
+
await db.query(sql`CREATE TABLE categories (
|
|
20
|
+
id INTEGER PRIMARY KEY,
|
|
21
|
+
name VARCHAR(42)
|
|
22
|
+
);`)
|
|
23
|
+
} else {
|
|
24
|
+
await db.query(sql`CREATE TABLE pages (
|
|
25
|
+
id SERIAL PRIMARY KEY,
|
|
26
|
+
title VARCHAR(42)
|
|
27
|
+
);`)
|
|
28
|
+
await db.query(sql`CREATE TABLE categories (
|
|
29
|
+
id SERIAL PRIMARY KEY,
|
|
30
|
+
name VARCHAR(42)
|
|
31
|
+
);`)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
test('ignore a table', async ({ pass, teardown, equal }) => {
|
|
36
|
+
async function onDatabaseLoad (db, sql) {
|
|
37
|
+
pass('onDatabaseLoad called')
|
|
38
|
+
teardown(() => db.dispose())
|
|
39
|
+
|
|
40
|
+
await clear(db, sql)
|
|
41
|
+
await createBasicPages(db, sql)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const mapper = await connect({
|
|
45
|
+
...connInfo,
|
|
46
|
+
log: fakeLogger,
|
|
47
|
+
onDatabaseLoad,
|
|
48
|
+
ignore: {
|
|
49
|
+
categories: true
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
const pageEntity = mapper.entities.page
|
|
54
|
+
equal(pageEntity.name, 'Page')
|
|
55
|
+
|
|
56
|
+
const categoryEntity = mapper.entities.category
|
|
57
|
+
equal(categoryEntity, undefined, 'category entity is ignored')
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('show a warning if there is no ignored table', async ({ plan, pass, teardown, equal }) => {
|
|
61
|
+
plan(4)
|
|
62
|
+
|
|
63
|
+
async function onDatabaseLoad (db, sql) {
|
|
64
|
+
pass('onDatabaseLoad called')
|
|
65
|
+
teardown(() => db.dispose())
|
|
66
|
+
|
|
67
|
+
await clear(db, sql)
|
|
68
|
+
await createBasicPages(db, sql)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const logger = {
|
|
72
|
+
trace: () => {},
|
|
73
|
+
error: () => {},
|
|
74
|
+
warn: (msg) => {
|
|
75
|
+
equal(msg, 'Ignored table "missing_table_pages" not found. Did you mean "pages"?')
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const mapper = await connect({
|
|
80
|
+
...connInfo,
|
|
81
|
+
log: logger,
|
|
82
|
+
onDatabaseLoad,
|
|
83
|
+
ignore: {
|
|
84
|
+
missing_table_pages: true
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
const pageEntity = mapper.entities.page
|
|
89
|
+
equal(pageEntity.name, 'Page')
|
|
90
|
+
|
|
91
|
+
const categoryEntity = mapper.entities.category
|
|
92
|
+
equal(categoryEntity.name, 'Category')
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
test('show a warning if the database is empty', async ({ plan, pass, teardown, equal }) => {
|
|
96
|
+
// plan(4)
|
|
97
|
+
|
|
98
|
+
async function onDatabaseLoad (db, sql) {
|
|
99
|
+
pass('onDatabaseLoad called')
|
|
100
|
+
teardown(() => db.dispose())
|
|
101
|
+
|
|
102
|
+
await clear(db, sql)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const logger = {
|
|
106
|
+
trace: () => {},
|
|
107
|
+
error: () => {},
|
|
108
|
+
warn: (msg) => {
|
|
109
|
+
equal(msg, 'Ignored table "missing_table_pages" not found.')
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
await connect({
|
|
114
|
+
...connInfo,
|
|
115
|
+
log: logger,
|
|
116
|
+
onDatabaseLoad,
|
|
117
|
+
ignore: {
|
|
118
|
+
missing_table_pages: true
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
test('ignore a column', async ({ pass, teardown, equal }) => {
|
|
124
|
+
async function onDatabaseLoad (db, sql) {
|
|
125
|
+
pass('onDatabaseLoad called')
|
|
126
|
+
teardown(() => db.dispose())
|
|
127
|
+
|
|
128
|
+
await clear(db, sql)
|
|
129
|
+
await createBasicPages(db, sql)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const mapper = await connect({
|
|
133
|
+
...connInfo,
|
|
134
|
+
log: fakeLogger,
|
|
135
|
+
onDatabaseLoad,
|
|
136
|
+
ignore: {
|
|
137
|
+
categories: {
|
|
138
|
+
name: true
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
const pageEntity = mapper.entities.page
|
|
144
|
+
equal(pageEntity.name, 'Page')
|
|
145
|
+
|
|
146
|
+
const categoryEntity = mapper.entities.category
|
|
147
|
+
equal(categoryEntity.name, 'Category')
|
|
148
|
+
equal(categoryEntity.fields.id.camelcase, 'id')
|
|
149
|
+
equal(categoryEntity.fields.name, undefined, 'name column is ignored')
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
test('shows a warning if there is no ignored column', async ({ plan, pass, teardown, equal }) => {
|
|
153
|
+
plan(4)
|
|
154
|
+
|
|
155
|
+
async function onDatabaseLoad (db, sql) {
|
|
156
|
+
pass('onDatabaseLoad called')
|
|
157
|
+
teardown(() => db.dispose())
|
|
158
|
+
|
|
159
|
+
await clear(db, sql)
|
|
160
|
+
await createBasicPages(db, sql)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const logger = {
|
|
164
|
+
trace: () => {},
|
|
165
|
+
error: () => {},
|
|
166
|
+
warn: (msg) => {
|
|
167
|
+
equal(msg, 'Ignored column "missing_column_name" not found. Did you mean "name"?')
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const mapper = await connect({
|
|
172
|
+
...connInfo,
|
|
173
|
+
log: logger,
|
|
174
|
+
onDatabaseLoad,
|
|
175
|
+
ignore: {
|
|
176
|
+
categories: {
|
|
177
|
+
missing_column_name: true
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
const pageEntity = mapper.entities.page
|
|
183
|
+
equal(pageEntity.name, 'Page')
|
|
184
|
+
|
|
185
|
+
const categoryEntity = mapper.entities.category
|
|
186
|
+
equal(categoryEntity.name, 'Category')
|
|
187
|
+
})
|
|
@@ -136,4 +136,3 @@ expectType<ErrorWithTwoParams>(errors.ParamLimitNotAllowedError)
|
|
|
136
136
|
expectType<ErrorWithOneParam>(errors.ParamLimitMustBeNotNegativeError)
|
|
137
137
|
expectType<ErrorWithOneParam>(errors.MissingValueForPrimaryKeyError)
|
|
138
138
|
expectType<ErrorWithNoParams>(errors.SQLiteOnlySupportsAutoIncrementOnOneColumnError)
|
|
139
|
-
|