@platformatic/sql-mapper 3.71.1-alpha.0 → 4.0.0-alpha.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.
Files changed (3) hide show
  1. package/index.d.ts +81 -20
  2. package/lib/entity.js +63 -32
  3. package/package.json +4 -4
package/index.d.ts CHANGED
@@ -220,44 +220,88 @@ interface Count {
220
220
  }
221
221
 
222
222
  interface Insert<EntityFields> {
223
+ (options: {
224
+ /**
225
+ * Entity to insert.
226
+ */
227
+ input: EntityFields,
228
+ /**
229
+ * List of fields to be returned for the object.
230
+ */
231
+ fields?: string[],
232
+ /**
233
+ * If present, the entity participates in transaction.
234
+ */
235
+ tx?: Database,
236
+ /**
237
+ * Passing this to all sql-mapper functions allows authorization rules
238
+ * and other hooks to be applied to database queries.
239
+ */
240
+ ctx?: PlatformaticContext
241
+ }): Promise<Partial<EntityFields>>
242
+ }
243
+
244
+ interface InsertMany<EntityFields> {
223
245
  (options: {
224
246
  /**
225
247
  * Entities to insert.
226
248
  */
227
249
  inputs: EntityFields[],
228
250
  /**
229
- * List of fields to be returned for each object
251
+ * List of fields to be returned for each object.
230
252
  */
231
253
  fields?: string[],
232
254
  /**
233
- * If present, the entity participates in transaction
255
+ * If present, the entities participate in transaction.
234
256
  */
235
257
  tx?: Database,
236
258
  /**
237
- * Passing this to all sql-mapper functions allow to apply
238
- * authorization rules to the database queries (amongst other things).
259
+ * Passing this to all sql-mapper functions allows authorization rules
260
+ * and other hooks to be applied to database queries.
239
261
  */
240
262
  ctx?: PlatformaticContext
241
263
  }): Promise<Partial<EntityFields>[]>
242
264
  }
243
265
 
244
- interface Save<EntityFields> {
266
+ interface Update<EntityFields> {
245
267
  (options: {
246
268
  /**
247
- * Entity to save.
269
+ * Entity fields to update. All primary keys must be present.
270
+ */
271
+ input: Partial<EntityFields>,
272
+ /**
273
+ * List of fields to be returned for the object.
274
+ */
275
+ fields?: string[],
276
+ /**
277
+ * If present, the entity participates in transaction.
278
+ */
279
+ tx?: Database,
280
+ /**
281
+ * Passing this to all sql-mapper functions allows authorization rules
282
+ * and other hooks to be applied to database queries.
283
+ */
284
+ ctx?: PlatformaticContext
285
+ }): Promise<Partial<EntityFields> | null>
286
+ }
287
+
288
+ interface Upsert<EntityFields> {
289
+ (options: {
290
+ /**
291
+ * Entity to insert or update.
248
292
  */
249
293
  input: EntityFields,
250
294
  /**
251
- * List of fields to be returned for each object
295
+ * List of fields to be returned for the object.
252
296
  */
253
297
  fields?: string[],
254
298
  /**
255
- * If present, the entity participates in transaction
299
+ * If present, the entity participates in transaction.
256
300
  */
257
301
  tx?: Database,
258
302
  /**
259
- * Passing this to all sql-mapper functions allow to apply
260
- * authorization rules to the database queries (amongst other things).
303
+ * Passing this to all sql-mapper functions allows authorization rules
304
+ * and other hooks to be applied to database queries.
261
305
  */
262
306
  ctx?: PlatformaticContext
263
307
  }): Promise<Partial<EntityFields>>
@@ -361,13 +405,30 @@ export interface Entity<EntityFields = any> {
361
405
  */
362
406
  find: Find<EntityFields>,
363
407
  /**
364
- * Inserts entities to the database.
408
+ * Inserts an entity into the database.
365
409
  */
366
410
  insert: Insert<EntityFields>,
367
411
  /**
368
- * Saves entity to the database.
412
+ * Inserts multiple entities into the database.
413
+ */
414
+ insertMany: InsertMany<EntityFields>,
415
+ /**
416
+ * Updates an entity by its primary keys.
417
+ */
418
+ update: Update<EntityFields>,
419
+ /**
420
+ * Updates one or more entity rows in the database.
369
421
  */
370
- save: Save<EntityFields>,
422
+ updateMany: UpdateMany<EntityFields>,
423
+ /**
424
+ * Inserts or updates an entity.
425
+ */
426
+ upsert: Upsert<EntityFields>,
427
+ /**
428
+ * Inserts or updates an entity.
429
+ * @deprecated Use `upsert` instead.
430
+ */
431
+ save: Upsert<EntityFields>,
371
432
  /**
372
433
  * Deletes entities from the database.
373
434
  */
@@ -376,10 +437,6 @@ export interface Entity<EntityFields = any> {
376
437
  * Count the entities considering the where condition.
377
438
  */
378
439
  count: Count,
379
- /**
380
- * Update one or more entity rows from the database.
381
- */
382
- updateMany: UpdateMany<EntityFields>
383
440
  }
384
441
 
385
442
  type EntityHook<T extends (...args: any) => any> = (original: T, ...options: Parameters<T>) => ReturnType<T>
@@ -387,10 +444,14 @@ type EntityHook<T extends (...args: any) => any> = (original: T, ...options: Par
387
444
  export interface EntityHooks<EntityFields = any> {
388
445
  find?: EntityHook<Find<EntityFields>>,
389
446
  insert?: EntityHook<Insert<EntityFields>>,
390
- save?: EntityHook<Save<EntityFields>>,
447
+ insertMany?: EntityHook<InsertMany<EntityFields>>,
448
+ update?: EntityHook<Update<EntityFields>>,
449
+ updateMany?: EntityHook<UpdateMany<EntityFields>>,
450
+ upsert?: EntityHook<Upsert<EntityFields>>,
451
+ /** @deprecated Use the `upsert` hook instead. */
452
+ save?: EntityHook<Upsert<EntityFields>>,
391
453
  delete?: EntityHook<Delete<EntityFields>>,
392
- count?: EntityHook<Count>,
393
- updateMany?: EntityHook<UpdateMany<EntityFields>>
454
+ count?: EntityHook<Count>
394
455
  }
395
456
 
396
457
  interface BasePoolOptions {
package/lib/entity.js CHANGED
@@ -5,6 +5,7 @@ import { buildCursorCondition } from './cursor.js'
5
5
  import {
6
6
  InputNotProvidedError,
7
7
  InvalidPrimaryKeyTypeError,
8
+ MissingValueForPrimaryKeyError,
8
9
  MissingWhereClauseError,
9
10
  ParamNotAllowedError,
10
11
  UnknownFieldError,
@@ -146,50 +147,30 @@ function createMapper (
146
147
  return newOutput
147
148
  }
148
149
 
149
- async function save (args) {
150
- const db = getDB(args)
150
+ async function insert (args) {
151
151
  if (args.input === undefined) {
152
152
  throw new InputNotProvidedError()
153
153
  }
154
- // args.input is not array
154
+
155
+ const db = getDB(args)
155
156
  const fieldsToRetrieve = computeFields(args.fields).map(f => sql.ident(f))
156
157
  const input = fixInput(args.input)
157
158
 
158
- let hasPrimaryKeys = true
159
- for (const key of primaryKeys) {
160
- if (input[key] === undefined) {
161
- hasPrimaryKeys = false
162
- break
159
+ if (autoTimestamp) {
160
+ const now = new Date()
161
+ if (fields[autoTimestamp.createdAt]) {
162
+ input[autoTimestamp.createdAt] = now
163
163
  }
164
- }
165
-
166
- let now
167
- if (autoTimestamp && fields[autoTimestamp.updatedAt]) {
168
- now = new Date()
169
- input[autoTimestamp.updatedAt] = now
170
- }
171
- if (hasPrimaryKeys) {
172
- // update
173
- const res = await queries.updateOne(db, sql, table, schema, input, primaryKeys, fieldsToRetrieve)
174
- if (res) {
175
- return fixOutput(res)
164
+ if (fields[autoTimestamp.updatedAt]) {
165
+ input[autoTimestamp.updatedAt] = now
176
166
  }
177
- // If we are here, the record does not exist, so we create it
178
- // this is inefficient because it will do 2 queries.
179
- // TODO there is a way to do it in one query with DB specific syntax.
180
167
  }
181
168
 
182
- // insert
183
- if (autoTimestamp && fields[autoTimestamp.createdAt]) {
184
- /* istanbul ignore next */
185
- now = now || new Date()
186
- input[autoTimestamp.createdAt] = now
187
- }
188
169
  const res = await queries.insertOne(db, sql, table, schema, input, primaryKeysTypes, fieldsToRetrieve)
189
170
  return fixOutput(res)
190
171
  }
191
172
 
192
- async function insert (args) {
173
+ async function insertMany (args) {
193
174
  const db = getDB(args)
194
175
  const fieldsToRetrieve = computeFields(args.fields).map(f => sql.ident(f))
195
176
  const inputs = args.inputs
@@ -240,6 +221,53 @@ function createMapper (
240
221
  }
241
222
  }
242
223
 
224
+ async function update (args) {
225
+ if (args.input === undefined) {
226
+ throw new InputNotProvidedError()
227
+ }
228
+
229
+ const db = getDB(args)
230
+ const fieldsToRetrieve = computeFields(args.fields).map(f => sql.ident(f))
231
+ const input = fixInput(args.input)
232
+
233
+ for (const key of primaryKeys) {
234
+ if (input[key] === undefined) {
235
+ throw new MissingValueForPrimaryKeyError(key)
236
+ }
237
+ }
238
+
239
+ if (autoTimestamp && fields[autoTimestamp.updatedAt]) {
240
+ input[autoTimestamp.updatedAt] = new Date()
241
+ }
242
+
243
+ const res = await queries.updateOne(db, sql, table, schema, input, primaryKeys, fieldsToRetrieve)
244
+ return res ? fixOutput(res) : null
245
+ }
246
+
247
+ async function upsert (args) {
248
+ if (args.input === undefined) {
249
+ throw new InputNotProvidedError()
250
+ }
251
+
252
+ const input = fixInput(args.input)
253
+ let hasPrimaryKeys = true
254
+ for (const key of primaryKeys) {
255
+ if (input[key] === undefined) {
256
+ hasPrimaryKeys = false
257
+ break
258
+ }
259
+ }
260
+
261
+ if (hasPrimaryKeys) {
262
+ const updated = await entity.update(args)
263
+ if (updated) {
264
+ return updated
265
+ }
266
+ }
267
+
268
+ return entity.insert(args)
269
+ }
270
+
243
271
  async function updateMany (args) {
244
272
  if (args.input === undefined) {
245
273
  throw new InputNotProvidedError()
@@ -508,9 +536,12 @@ function createMapper (
508
536
 
509
537
  if (!isView) {
510
538
  entity.insert = insert
511
- entity.save = save
512
- entity.delete = _delete
539
+ entity.insertMany = insertMany
540
+ entity.update = update
513
541
  entity.updateMany = updateMany
542
+ entity.upsert = upsert
543
+ entity.save = upsert
544
+ entity.delete = _delete
514
545
  }
515
546
 
516
547
  return entity
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/sql-mapper",
3
- "version": "3.71.1-alpha.0",
3
+ "version": "4.0.0-alpha.1",
4
4
  "description": "A data mapper utility for SQL databases",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -35,11 +35,11 @@
35
35
  "camelcase": "^6.3.0",
36
36
  "fastify-plugin": "^6.0.0",
37
37
  "inflected": "^2.1.0",
38
- "@platformatic/foundation": "3.71.1-alpha.0",
39
- "@platformatic/telemetry": "3.71.1-alpha.0"
38
+ "@platformatic/foundation": "4.0.0-alpha.1",
39
+ "@platformatic/tracing": "4.0.0-alpha.1"
40
40
  },
41
41
  "engines": {
42
- "node": ">=22.19.0"
42
+ "node": ">=24.20.0"
43
43
  },
44
44
  "scripts": {
45
45
  "lint": "eslint",