@platformatic/sql-mapper 0.45.0 → 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 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.45.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
+ })
@@ -89,7 +89,7 @@ expectType<SQLMapperPluginInterface<Entities>>(await connect<Entities>({
89
89
 
90
90
  const instance: FastifyInstance = fastify()
91
91
  instance.register(plugin, { connectionString: '', autoTimestamp: true })
92
- instance.register((instance) => {
92
+ instance.register((instance) => {
93
93
  expectType<SQLMapperPluginInterface<Entities>>(instance.platformatic)
94
94
 
95
95
  instance.platformatic.addEntityHooks<EntityFields>('something', {
@@ -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
-