@platformatic/sql-mapper 0.15.1 → 0.17.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.
@@ -124,33 +124,40 @@ async function insertOne (db, sql, table, schema, input, primaryKeys, fieldsToRe
124
124
  if (fieldsToRetrieve.length === 0) {
125
125
  await db.query(insertRawQuery)
126
126
  return {}
127
+ } else if (typeof db.tx === 'function') {
128
+ return db.tx(handleAutoIncrement)
127
129
  } else {
128
- return db.tx(async (transaction) => {
129
- await transaction.query(insertRawQuery)
130
+ // TODO add a log at trace level if we do this
131
+ // There are not nested transactions in SQLite, so we can just run the query
132
+ // because we are already in a transaction.
133
+ return handleAutoIncrement(db)
134
+ }
135
+
136
+ async function handleAutoIncrement (transaction) {
137
+ await transaction.query(insertRawQuery)
130
138
 
131
- let selectInsertedRawQuery = null
132
- if (hasAutoIncrementPK) {
133
- selectInsertedRawQuery = sql`
139
+ let selectInsertedRawQuery = null
140
+ if (hasAutoIncrementPK) {
141
+ selectInsertedRawQuery = sql`
134
142
  SELECT ${sql.join(fieldsToRetrieve, sql`, `)}
135
143
  FROM ${sql.ident(table)}
136
144
  WHERE _rowid_ = last_insert_rowid()
137
145
  `
138
- } else {
139
- const where = []
140
- for (const [key, value] of Object.entries(primaryKeyValues)) {
141
- where.push(sql`${sql.ident(key)} = ${sql.value(value)}`)
142
- }
146
+ } else {
147
+ const where = []
148
+ for (const [key, value] of Object.entries(primaryKeyValues)) {
149
+ where.push(sql`${sql.ident(key)} = ${sql.value(value)}`)
150
+ }
143
151
 
144
- selectInsertedRawQuery = sql`
152
+ selectInsertedRawQuery = sql`
145
153
  SELECT ${sql.join(fieldsToRetrieve, sql`, `)}
146
154
  FROM ${sql.ident(table)}
147
155
  WHERE ${sql.join(where, sql` AND `)}
148
156
  `
149
- }
157
+ }
150
158
 
151
- const [insertedRaw] = await transaction.query(selectInsertedRawQuery)
152
- return insertedRaw
153
- })
159
+ const [insertedRaw] = await transaction.query(selectInsertedRawQuery)
160
+ return insertedRaw
154
161
  }
155
162
  }
156
163
 
package/mapper.js CHANGED
@@ -172,6 +172,15 @@ async function sqlMapper (app, opts) {
172
172
  // TODO this would need to be refactored as other plugins
173
173
  // would need to use this same namespace
174
174
  app.decorate('platformatic', mapper)
175
+
176
+ app.decorateRequest('platformaticContext', null)
177
+ app.addHook('onRequest', function (req, reply, done) {
178
+ req.platformaticContext = {
179
+ app: this, // uses the encapsulated fastify instance of the route
180
+ reply
181
+ }
182
+ done()
183
+ })
175
184
  }
176
185
 
177
186
  module.exports = fp(sqlMapper)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/sql-mapper",
3
- "version": "0.15.1",
3
+ "version": "0.17.0",
4
4
  "description": "A data mapper utility for SQL databases",
5
5
  "main": "mapper.js",
6
6
  "repository": {
@@ -14,19 +14,19 @@
14
14
  },
15
15
  "homepage": "https://github.com/platformatic/platformatic#readme",
16
16
  "devDependencies": {
17
- "fastify": "^4.10.2",
17
+ "fastify": "^4.13.0",
18
18
  "snazzy": "^9.0.0",
19
19
  "standard": "^17.0.0",
20
- "tap": "^16.3.2",
21
- "tsd": "^0.25.0"
20
+ "tap": "^16.3.4",
21
+ "tsd": "^0.26.0"
22
22
  },
23
23
  "dependencies": {
24
24
  "@databases/mysql": "^5.2.1",
25
25
  "@databases/pg": "^5.4.1",
26
- "@databases/sql": "^3.2.0",
26
+ "@databases/sql": "^3.3.0",
27
27
  "@databases/sqlite": "^4.0.2",
28
28
  "camelcase": "^6.3.0",
29
- "fastify-plugin": "^4.4.0",
29
+ "fastify-plugin": "^4.5.0",
30
30
  "inflected": "^2.1.0"
31
31
  },
32
32
  "tsd": {
@@ -971,3 +971,37 @@ test('stored and virtual generated columns should return for pg', { skip: (isPg
971
971
  }
972
972
  }), [{ id: 2, test: 8, testStored: 16, testVirtual: 32 }])
973
973
  })
974
+
975
+ test('nested transactions', async ({ equal, same, teardown, rejects }) => {
976
+ async function onDatabaseLoad (db, sql) {
977
+ await clear(db, sql)
978
+ teardown(() => db.dispose())
979
+ if (isSQLite) {
980
+ await db.query(sql`CREATE TABLE pages (
981
+ id INTEGER PRIMARY KEY,
982
+ the_title VARCHAR(42)
983
+ );`)
984
+ } else {
985
+ await db.query(sql`CREATE TABLE pages (
986
+ id SERIAL PRIMARY KEY,
987
+ the_title VARCHAR(255)
988
+ );`)
989
+ }
990
+ }
991
+ const mapper = await connect({
992
+ connectionString: connInfo.connectionString,
993
+ log: fakeLogger,
994
+ onDatabaseLoad,
995
+ ignore: {},
996
+ hooks: {}
997
+ })
998
+
999
+ await mapper.db.tx(async (tx) => {
1000
+ const insertResult = await mapper.entities.page.save({
1001
+ input: {},
1002
+ fields: ['id', 'theTitle'],
1003
+ tx
1004
+ })
1005
+ same(insertResult, { id: '1', theTitle: null })
1006
+ })
1007
+ })
@@ -193,3 +193,31 @@ test('missing connectionString', async ({ rejects }) => {
193
193
 
194
194
  await rejects(app.ready(), /connectionString/)
195
195
  })
196
+
197
+ test('platformaticContext', async ({ plan, equal, teardown }) => {
198
+ plan(3)
199
+ async function onDatabaseLoad (db, sql) {
200
+ teardown(async () => await clear(db, sql))
201
+
202
+ await db.query(sql`CREATE TABLE IF NOT EXISTS pages (
203
+ id SERIAL PRIMARY KEY,
204
+ title VARCHAR(255) NOT NULL
205
+ );`)
206
+ }
207
+ const app = fastify()
208
+ teardown(() => app.close())
209
+ app.register(plugin, {
210
+ connectionString: connInfo.connectionString,
211
+ onDatabaseLoad
212
+ })
213
+
214
+ app.get('/', function (req, reply) {
215
+ const ctx = req.platformaticContext
216
+ equal(app, ctx.app)
217
+ equal(reply, ctx.reply)
218
+ return 'hello world'
219
+ })
220
+
221
+ const res = await app.inject('/')
222
+ equal(res.statusCode, 200)
223
+ })