forge-sql-orm 2.0.20 → 2.0.21
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/README.md +49 -0
- package/dist/ForgeSQLORM.js +11 -0
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +11 -0
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/utils/sqlUtils.d.ts +2 -0
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/package.json +10 -10
- package/src/utils/sqlUtils.ts +11 -0
package/README.md
CHANGED
|
@@ -465,6 +465,20 @@ await forgeSQL.crud().insert(Users, [
|
|
|
465
465
|
],
|
|
466
466
|
true
|
|
467
467
|
);
|
|
468
|
+
|
|
469
|
+
// Insert with sequence (nextVal)
|
|
470
|
+
import { nextVal } from "forge-sql-orm";
|
|
471
|
+
|
|
472
|
+
const user = {
|
|
473
|
+
id: nextVal('user_id_seq'),
|
|
474
|
+
name: "user test",
|
|
475
|
+
organization_id: 1
|
|
476
|
+
};
|
|
477
|
+
const id = await forgeSQL.modify().insert(appUser, [user]);
|
|
478
|
+
|
|
479
|
+
// The generated SQL will be:
|
|
480
|
+
// INSERT INTO app_user (id, name, organization_id)
|
|
481
|
+
// VALUES (NEXTVAL(user_id_seq), ?, ?) -- params: ["user test", 1]
|
|
468
482
|
```
|
|
469
483
|
|
|
470
484
|
### Update Operations
|
|
@@ -494,6 +508,41 @@ await forgeSQL.crud().updateFields(
|
|
|
494
508
|
await forgeSQL.crud().deleteById(1, Users);
|
|
495
509
|
```
|
|
496
510
|
|
|
511
|
+
## SQL Utilities
|
|
512
|
+
|
|
513
|
+
### formatLimitOffset
|
|
514
|
+
|
|
515
|
+
The `formatLimitOffset` utility function is used to safely insert numeric values directly into SQL queries for LIMIT and OFFSET clauses. This is necessary because Atlassian Forge SQL doesn't support parameterized queries for these clauses.
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
import { formatLimitOffset } from "forge-sql-orm";
|
|
519
|
+
|
|
520
|
+
// Example usage in a query
|
|
521
|
+
const result = await forgeSQL
|
|
522
|
+
.select()
|
|
523
|
+
.from(orderItem)
|
|
524
|
+
.orderBy(asc(orderItem.createdAt))
|
|
525
|
+
.limit(formatLimitOffset(10))
|
|
526
|
+
.offset(formatLimitOffset(350000));
|
|
527
|
+
|
|
528
|
+
// The generated SQL will be:
|
|
529
|
+
// SELECT * FROM order_item
|
|
530
|
+
// ORDER BY created_at ASC
|
|
531
|
+
// LIMIT 10
|
|
532
|
+
// OFFSET 350000
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
**Important Notes:**
|
|
536
|
+
- The function performs type checking to prevent SQL injection
|
|
537
|
+
- It throws an error if the input is not a valid number
|
|
538
|
+
- Use this function instead of direct parameter binding for LIMIT and OFFSET clauses
|
|
539
|
+
- The function is specifically designed to work with Atlassian Forge SQL's limitations
|
|
540
|
+
|
|
541
|
+
**Security Considerations:**
|
|
542
|
+
- The function includes validation to ensure the input is a valid number
|
|
543
|
+
- This prevents SQL injection by ensuring only numeric values are inserted
|
|
544
|
+
- Always use this function instead of string concatenation for LIMIT and OFFSET values
|
|
545
|
+
|
|
497
546
|
## Optimistic Locking
|
|
498
547
|
|
|
499
548
|
Optimistic locking is a concurrency control mechanism that prevents data conflicts when multiple transactions attempt to update the same record concurrently. Instead of using locks, this technique relies on a version field in your entity models.
|
package/dist/ForgeSQLORM.js
CHANGED
|
@@ -269,6 +269,15 @@ function processNullBranches(obj) {
|
|
|
269
269
|
}
|
|
270
270
|
return allNull ? null : result;
|
|
271
271
|
}
|
|
272
|
+
function formatLimitOffset(limitOrOffset) {
|
|
273
|
+
if (typeof limitOrOffset !== "number" || isNaN(limitOrOffset)) {
|
|
274
|
+
throw new Error("limitOrOffset must be a valid number");
|
|
275
|
+
}
|
|
276
|
+
return drizzleOrm.sql.raw(`${limitOrOffset}`);
|
|
277
|
+
}
|
|
278
|
+
function nextVal(sequenceName) {
|
|
279
|
+
return drizzleOrm.sql`SELECT NEXT VALUE FOR ${sequenceName} AS id`;
|
|
280
|
+
}
|
|
272
281
|
class ForgeSQLCrudOperations {
|
|
273
282
|
forgeOperations;
|
|
274
283
|
options;
|
|
@@ -1338,6 +1347,7 @@ exports.forgeDriver = forgeDriver;
|
|
|
1338
1347
|
exports.forgeSystemTables = forgeSystemTables;
|
|
1339
1348
|
exports.forgeTimeString = forgeTimeString;
|
|
1340
1349
|
exports.forgeTimestampString = forgeTimestampString;
|
|
1350
|
+
exports.formatLimitOffset = formatLimitOffset;
|
|
1341
1351
|
exports.generateDropTableStatements = generateDropTableStatements;
|
|
1342
1352
|
exports.getHttpResponse = getHttpResponse;
|
|
1343
1353
|
exports.getPrimaryKeys = getPrimaryKeys;
|
|
@@ -1346,6 +1356,7 @@ exports.getTables = getTables;
|
|
|
1346
1356
|
exports.mapSelectAllFieldsToAlias = mapSelectAllFieldsToAlias;
|
|
1347
1357
|
exports.mapSelectFieldsWithAlias = mapSelectFieldsWithAlias;
|
|
1348
1358
|
exports.migrations = migrations;
|
|
1359
|
+
exports.nextVal = nextVal;
|
|
1349
1360
|
exports.parseDateTime = parseDateTime;
|
|
1350
1361
|
exports.patchDbWithSelectAliased = patchDbWithSelectAliased;
|
|
1351
1362
|
//# sourceMappingURL=ForgeSQLORM.js.map
|