@teamkeel/functions-runtime 0.434.1 → 0.435.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.
- package/dist/index.cjs +220 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -1
- package/dist/index.d.ts +51 -1
- package/dist/index.js +220 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1560,6 +1560,221 @@ var QueryBuilder = class _QueryBuilder {
|
|
|
1560
1560
|
return rows.map((x) => transformRichDataTypes(camelCaseObject(x)));
|
|
1561
1561
|
});
|
|
1562
1562
|
}
|
|
1563
|
+
/**
|
|
1564
|
+
* Execute query with pagination support.
|
|
1565
|
+
* Returns results along with pageInfo metadata.
|
|
1566
|
+
* @param {Object} params - Pagination parameters
|
|
1567
|
+
* @param {number} [params.first] - Number of items for cursor pagination (forward)
|
|
1568
|
+
* @param {string} [params.after] - Cursor for forward pagination
|
|
1569
|
+
* @param {number} [params.last] - Number of items for cursor pagination (backward)
|
|
1570
|
+
* @param {string} [params.before] - Cursor for backward pagination
|
|
1571
|
+
* @param {number} [params.limit] - Page size for offset pagination
|
|
1572
|
+
* @param {number} [params.offset] - Offset for offset pagination
|
|
1573
|
+
* @param {Object} [params.orderBy] - Ordering specification
|
|
1574
|
+
* @returns {Promise<{results: any[], pageInfo: Object}>}
|
|
1575
|
+
*/
|
|
1576
|
+
async findManyWithPageInfo(params = {}) {
|
|
1577
|
+
const name = spanNameForModelAPI(
|
|
1578
|
+
this._modelName,
|
|
1579
|
+
"findManyWithPageInfo"
|
|
1580
|
+
);
|
|
1581
|
+
const db = useDatabase();
|
|
1582
|
+
return withSpan(name, async (span) => {
|
|
1583
|
+
const context6 = new QueryContext([this._tableName], this._tableConfigMap);
|
|
1584
|
+
const isOffsetPagination = params.limit != null && params.limit > 0;
|
|
1585
|
+
const isBackward = params.last != null && params.last > 0;
|
|
1586
|
+
const DEFAULT_PAGE_SIZE = 50;
|
|
1587
|
+
let limit;
|
|
1588
|
+
if (isOffsetPagination) {
|
|
1589
|
+
limit = params.limit;
|
|
1590
|
+
} else if (isBackward) {
|
|
1591
|
+
limit = params.last;
|
|
1592
|
+
} else {
|
|
1593
|
+
limit = params.first ?? DEFAULT_PAGE_SIZE;
|
|
1594
|
+
}
|
|
1595
|
+
const countQuery = db.selectFrom((qb) => this._db.as(this._tableName)).select(db.fn.countAll().as("total"));
|
|
1596
|
+
const countResult = await countQuery.executeTakeFirst();
|
|
1597
|
+
const totalCount = Number(countResult?.total ?? 0);
|
|
1598
|
+
let builder = db.selectFrom((qb) => this._db.as(this._tableName)).selectAll();
|
|
1599
|
+
let normalizedOrderBy = null;
|
|
1600
|
+
if (params.orderBy) {
|
|
1601
|
+
if (Array.isArray(params.orderBy)) {
|
|
1602
|
+
normalizedOrderBy = {};
|
|
1603
|
+
for (const item of params.orderBy) {
|
|
1604
|
+
for (const [key, dir] of Object.entries(item)) {
|
|
1605
|
+
normalizedOrderBy[key] = dir;
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
} else {
|
|
1609
|
+
normalizedOrderBy = params.orderBy;
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
const orderByFields = [];
|
|
1613
|
+
const hasCustomOrderBy = normalizedOrderBy !== null && Object.keys(normalizedOrderBy).length > 0;
|
|
1614
|
+
if (hasCustomOrderBy) {
|
|
1615
|
+
for (const [key, dir] of Object.entries(normalizedOrderBy)) {
|
|
1616
|
+
orderByFields.push({
|
|
1617
|
+
field: key,
|
|
1618
|
+
direction: String(dir).toLowerCase()
|
|
1619
|
+
});
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
orderByFields.push({ field: "id", direction: "asc" });
|
|
1623
|
+
if (hasCustomOrderBy) {
|
|
1624
|
+
const effectiveOrderBy = isBackward ? Object.fromEntries(
|
|
1625
|
+
Object.entries(normalizedOrderBy).map(([key, dir]) => [
|
|
1626
|
+
key,
|
|
1627
|
+
String(dir).toLowerCase() === "asc" ? "desc" : "asc"
|
|
1628
|
+
])
|
|
1629
|
+
) : normalizedOrderBy;
|
|
1630
|
+
builder = applyOrderBy(
|
|
1631
|
+
context6,
|
|
1632
|
+
builder,
|
|
1633
|
+
this._tableName,
|
|
1634
|
+
effectiveOrderBy
|
|
1635
|
+
);
|
|
1636
|
+
const idDirection = isBackward ? "desc" : "asc";
|
|
1637
|
+
builder = builder.orderBy(`${this._tableName}.id`, idDirection);
|
|
1638
|
+
} else {
|
|
1639
|
+
const direction = isBackward ? "desc" : "asc";
|
|
1640
|
+
builder = builder.orderBy(`${this._tableName}.id`, direction);
|
|
1641
|
+
}
|
|
1642
|
+
const cursor = isBackward ? params.before : params.after;
|
|
1643
|
+
if (cursor) {
|
|
1644
|
+
const primaryField = orderByFields[0];
|
|
1645
|
+
const primaryFieldCol = (0, import_change_case.snakeCase)(primaryField.field);
|
|
1646
|
+
const cursorLookup = await db.selectFrom((qb) => this._db.as(this._tableName)).select([primaryFieldCol, "id"]).where(`${this._tableName}.id`, "=", cursor).limit(1).executeTakeFirst();
|
|
1647
|
+
if (cursorLookup) {
|
|
1648
|
+
const primaryValue = cursorLookup[primaryFieldCol];
|
|
1649
|
+
const cursorId = cursorLookup.id;
|
|
1650
|
+
let primaryOp;
|
|
1651
|
+
if (primaryField.direction === "asc") {
|
|
1652
|
+
primaryOp = isBackward ? "<" : ">";
|
|
1653
|
+
} else {
|
|
1654
|
+
primaryOp = isBackward ? ">" : "<";
|
|
1655
|
+
}
|
|
1656
|
+
const idOp = isBackward ? "<" : ">";
|
|
1657
|
+
if (primaryValue === null) {
|
|
1658
|
+
if (primaryOp === ">") {
|
|
1659
|
+
builder = builder.where(
|
|
1660
|
+
(eb) => eb.or([
|
|
1661
|
+
eb(`${this._tableName}.${primaryFieldCol}`, "is not", null),
|
|
1662
|
+
eb.and([
|
|
1663
|
+
eb(`${this._tableName}.${primaryFieldCol}`, "is", null),
|
|
1664
|
+
eb(`${this._tableName}.id`, idOp, cursorId)
|
|
1665
|
+
])
|
|
1666
|
+
])
|
|
1667
|
+
);
|
|
1668
|
+
} else {
|
|
1669
|
+
builder = builder.where(
|
|
1670
|
+
(eb) => eb.and([
|
|
1671
|
+
eb(`${this._tableName}.${primaryFieldCol}`, "is", null),
|
|
1672
|
+
eb(`${this._tableName}.id`, idOp, cursorId)
|
|
1673
|
+
])
|
|
1674
|
+
);
|
|
1675
|
+
}
|
|
1676
|
+
} else {
|
|
1677
|
+
builder = builder.where(
|
|
1678
|
+
(eb) => eb.or([
|
|
1679
|
+
eb(
|
|
1680
|
+
`${this._tableName}.${primaryFieldCol}`,
|
|
1681
|
+
primaryOp,
|
|
1682
|
+
primaryValue
|
|
1683
|
+
),
|
|
1684
|
+
eb.and([
|
|
1685
|
+
eb(
|
|
1686
|
+
`${this._tableName}.${primaryFieldCol}`,
|
|
1687
|
+
"=",
|
|
1688
|
+
primaryValue
|
|
1689
|
+
),
|
|
1690
|
+
eb(`${this._tableName}.id`, idOp, cursorId)
|
|
1691
|
+
])
|
|
1692
|
+
])
|
|
1693
|
+
);
|
|
1694
|
+
}
|
|
1695
|
+
} else {
|
|
1696
|
+
builder = builder.where(
|
|
1697
|
+
`${this._tableName}.id`,
|
|
1698
|
+
"=",
|
|
1699
|
+
"___NONEXISTENT_ID___"
|
|
1700
|
+
);
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
if (limit != null) {
|
|
1704
|
+
builder = applyLimit(context6, builder, limit);
|
|
1705
|
+
}
|
|
1706
|
+
if (isOffsetPagination && params.offset) {
|
|
1707
|
+
builder = applyOffset(context6, builder, params.offset);
|
|
1708
|
+
}
|
|
1709
|
+
span.setAttribute("sql", builder.compile().sql);
|
|
1710
|
+
let rows = await builder.execute();
|
|
1711
|
+
if (isBackward) {
|
|
1712
|
+
rows = rows.reverse();
|
|
1713
|
+
}
|
|
1714
|
+
const results = rows.map(
|
|
1715
|
+
(x) => transformRichDataTypes(camelCaseObject(x))
|
|
1716
|
+
);
|
|
1717
|
+
let hasNextPage = false;
|
|
1718
|
+
if (isOffsetPagination) {
|
|
1719
|
+
hasNextPage = totalCount > (params.offset || 0) + limit;
|
|
1720
|
+
} else if (limit != null && results.length === limit && results.length > 0) {
|
|
1721
|
+
const lastResult = results[results.length - 1];
|
|
1722
|
+
const primaryField = orderByFields[0];
|
|
1723
|
+
const primaryFieldCol = (0, import_change_case.snakeCase)(primaryField.field);
|
|
1724
|
+
const primaryValue = lastResult[primaryField.field];
|
|
1725
|
+
const lastId = lastResult.id;
|
|
1726
|
+
const primaryOp = primaryField.direction === "asc" ? ">" : "<";
|
|
1727
|
+
let nextCheckQuery = db.selectFrom((qb) => this._db.as(this._tableName)).select("id").limit(1);
|
|
1728
|
+
if (primaryValue === null) {
|
|
1729
|
+
if (primaryOp === ">") {
|
|
1730
|
+
nextCheckQuery = nextCheckQuery.where(
|
|
1731
|
+
(eb) => eb.or([
|
|
1732
|
+
eb(`${this._tableName}.${primaryFieldCol}`, "is not", null),
|
|
1733
|
+
eb.and([
|
|
1734
|
+
eb(`${this._tableName}.${primaryFieldCol}`, "is", null),
|
|
1735
|
+
eb(`${this._tableName}.id`, ">", lastId)
|
|
1736
|
+
])
|
|
1737
|
+
])
|
|
1738
|
+
);
|
|
1739
|
+
} else {
|
|
1740
|
+
nextCheckQuery = nextCheckQuery.where(
|
|
1741
|
+
(eb) => eb.and([
|
|
1742
|
+
eb(`${this._tableName}.${primaryFieldCol}`, "is", null),
|
|
1743
|
+
eb(`${this._tableName}.id`, ">", lastId)
|
|
1744
|
+
])
|
|
1745
|
+
);
|
|
1746
|
+
}
|
|
1747
|
+
} else {
|
|
1748
|
+
nextCheckQuery = nextCheckQuery.where(
|
|
1749
|
+
(eb) => eb.or([
|
|
1750
|
+
eb(
|
|
1751
|
+
`${this._tableName}.${primaryFieldCol}`,
|
|
1752
|
+
primaryOp,
|
|
1753
|
+
primaryValue
|
|
1754
|
+
),
|
|
1755
|
+
eb.and([
|
|
1756
|
+
eb(`${this._tableName}.${primaryFieldCol}`, "=", primaryValue),
|
|
1757
|
+
eb(`${this._tableName}.id`, ">", lastId)
|
|
1758
|
+
])
|
|
1759
|
+
])
|
|
1760
|
+
);
|
|
1761
|
+
}
|
|
1762
|
+
const nextRecord = await nextCheckQuery.executeTakeFirst();
|
|
1763
|
+
hasNextPage = nextRecord != null;
|
|
1764
|
+
}
|
|
1765
|
+
const pageInfo = {
|
|
1766
|
+
count: results.length,
|
|
1767
|
+
totalCount,
|
|
1768
|
+
hasNextPage,
|
|
1769
|
+
startCursor: results.length > 0 ? results[0].id : "",
|
|
1770
|
+
endCursor: results.length > 0 ? results[results.length - 1].id : ""
|
|
1771
|
+
};
|
|
1772
|
+
if (isOffsetPagination && limit > 0) {
|
|
1773
|
+
pageInfo.pageNumber = 1 + Math.floor((params.offset || 0) / limit);
|
|
1774
|
+
}
|
|
1775
|
+
return { results, pageInfo };
|
|
1776
|
+
});
|
|
1777
|
+
}
|
|
1563
1778
|
};
|
|
1564
1779
|
|
|
1565
1780
|
// src/ModelAPI.js
|
|
@@ -2571,7 +2786,11 @@ function tryExecuteFunction({ request, db, permitted, permissionFns, actionType,
|
|
|
2571
2786
|
if (fnResult != null) {
|
|
2572
2787
|
switch (actionType) {
|
|
2573
2788
|
case PROTO_ACTION_TYPES.LIST:
|
|
2574
|
-
|
|
2789
|
+
if (Array.isArray(fnResult)) {
|
|
2790
|
+
rowsForPermissions = fnResult;
|
|
2791
|
+
} else if (fnResult.results != null && Array.isArray(fnResult.results)) {
|
|
2792
|
+
rowsForPermissions = fnResult.results;
|
|
2793
|
+
}
|
|
2575
2794
|
break;
|
|
2576
2795
|
case PROTO_ACTION_TYPES.DELETE:
|
|
2577
2796
|
rowsForPermissions = [{ id: fnResult }];
|