@zenstackhq/orm 3.5.0 → 3.5.2

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 CHANGED
@@ -1698,13 +1698,53 @@ var LateralJoinDialectBase = class extends BaseCrudDialect {
1698
1698
  qb = qb.select((eb) => {
1699
1699
  const objArgs = this.buildRelationObjectArgs(relationModel, relationModelAlias, eb, payload, parentResultName);
1700
1700
  if (relationFieldDef.array) {
1701
- return this.buildArrayAgg(this.buildJsonObject(objArgs)).as("$data");
1701
+ const orderBy = this.buildRelationOrderByExpressions(relationModel, relationModelAlias, payload);
1702
+ return this.buildArrayAgg(this.buildJsonObject(objArgs), orderBy).as("$data");
1702
1703
  } else {
1703
1704
  return this.buildJsonObject(objArgs).as("$data");
1704
1705
  }
1705
1706
  });
1706
1707
  return qb;
1707
1708
  }
1709
+ /**
1710
+ * Extracts scalar `orderBy` clauses from the relation payload and maps them to
1711
+ * the array-aggregation ordering format.
1712
+ *
1713
+ * For to-many relations aggregated into a JSON array (via lateral joins), this
1714
+ * lets us preserve a stable ordering by passing `{ expr, sort, nulls? }` into
1715
+ * the dialect's `buildArrayAgg` implementation.
1716
+ */
1717
+ buildRelationOrderByExpressions(model, modelAlias, payload) {
1718
+ if (payload === true || !payload.orderBy) {
1719
+ return void 0;
1720
+ }
1721
+ const items = [];
1722
+ for (const orderBy of ensureArray(payload.orderBy)) {
1723
+ for (const [field, value] of Object.entries(orderBy)) {
1724
+ if (!value || requireField(this.schema, model, field).relation) {
1725
+ continue;
1726
+ }
1727
+ const expr = this.fieldRef(model, field, modelAlias);
1728
+ let sort = typeof value === "string" ? value : value.sort;
1729
+ if (payload.take !== void 0 && payload.take < 0) {
1730
+ sort = this.negateSort(sort, true);
1731
+ }
1732
+ if (typeof value === "string") {
1733
+ items.push({
1734
+ expr,
1735
+ sort
1736
+ });
1737
+ } else {
1738
+ items.push({
1739
+ expr,
1740
+ sort,
1741
+ nulls: value.nulls
1742
+ });
1743
+ }
1744
+ }
1745
+ }
1746
+ return items.length > 0 ? items : void 0;
1747
+ }
1708
1748
  buildRelationObjectArgs(relationModel, relationModelAlias, eb, payload, parentResultName) {
1709
1749
  const relationModelDef = requireModel(this.schema, relationModel);
1710
1750
  const objArgs = {};
@@ -1890,7 +1930,7 @@ var MySqlCrudDialect = class extends LateralJoinDialectBase {
1890
1930
  buildExistsExpression(innerQuery) {
1891
1931
  return this.eb.exists(this.eb.selectFrom(innerQuery.as("$exists_sub")).select(this.eb.lit(1).as("_")));
1892
1932
  }
1893
- buildArrayAgg(arg) {
1933
+ buildArrayAgg(arg, _orderBy) {
1894
1934
  return this.eb.fn.coalesce(import_kysely3.sql`JSON_ARRAYAGG(${arg})`, import_kysely3.sql`JSON_ARRAY()`);
1895
1935
  }
1896
1936
  buildSkipTake(query, skip, take) {
@@ -2202,8 +2242,16 @@ var PostgresCrudDialect = class _PostgresCrudDialect extends LateralJoinDialectB
2202
2242
  }
2203
2243
  // #endregion
2204
2244
  // #region other overrides
2205
- buildArrayAgg(arg) {
2206
- return this.eb.fn.coalesce(import_kysely4.sql`jsonb_agg(${arg})`, import_kysely4.sql`'[]'::jsonb`);
2245
+ buildArrayAgg(arg, orderBy) {
2246
+ if (!orderBy || orderBy.length === 0) {
2247
+ return this.eb.fn.coalesce(import_kysely4.sql`jsonb_agg(${arg})`, import_kysely4.sql`'[]'::jsonb`);
2248
+ }
2249
+ const orderBySql = import_kysely4.sql.join(orderBy.map(({ expr, sort, nulls }) => {
2250
+ const dir = import_kysely4.sql.raw(sort.toUpperCase());
2251
+ const nullsSql = nulls ? import_kysely4.sql` NULLS ${import_kysely4.sql.raw(nulls.toUpperCase())}` : import_kysely4.sql``;
2252
+ return import_kysely4.sql`${expr} ${dir}${nullsSql}`;
2253
+ }), import_kysely4.sql.raw(", "));
2254
+ return this.eb.fn.coalesce(import_kysely4.sql`jsonb_agg(${arg} ORDER BY ${orderBySql})`, import_kysely4.sql`'[]'::jsonb`);
2207
2255
  }
2208
2256
  buildSkipTake(query, skip, take) {
2209
2257
  if (take !== void 0) {