@open-mercato/core 0.6.8-develop.7029.1.a1bb3363af → 0.6.8-develop.7031.1.005201cd70

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 (236) hide show
  1. package/dist/modules/api_keys/backend/api-keys/page.js +3 -1
  2. package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
  3. package/dist/modules/attachments/components/AttachmentLibrary.js +2 -0
  4. package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
  5. package/dist/modules/audit_logs/backend/audit-logs/page.js +6 -0
  6. package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
  7. package/dist/modules/auth/backend/roles/page.js +3 -1
  8. package/dist/modules/auth/backend/roles/page.js.map +2 -2
  9. package/dist/modules/auth/backend/users/page.js +2 -1
  10. package/dist/modules/auth/backend/users/page.js.map +2 -2
  11. package/dist/modules/business_rules/backend/logs/page.js +3 -1
  12. package/dist/modules/business_rules/backend/logs/page.js.map +2 -2
  13. package/dist/modules/business_rules/backend/rules/page.js +3 -1
  14. package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
  15. package/dist/modules/business_rules/backend/sets/page.js +3 -1
  16. package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
  17. package/dist/modules/catalog/ai-agents.js +1 -1
  18. package/dist/modules/catalog/ai-agents.js.map +1 -1
  19. package/dist/modules/catalog/ai-tools/merchandising-pack.js +2 -2
  20. package/dist/modules/catalog/ai-tools/merchandising-pack.js.map +2 -2
  21. package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js +5 -2
  22. package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js.map +2 -2
  23. package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -0
  24. package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
  25. package/dist/modules/catalog/components/products/ProductsDataTable.js +7 -1
  26. package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
  27. package/dist/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.js +2 -0
  28. package/dist/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.js.map +2 -2
  29. package/dist/modules/communication_channels/backend/communication_channels/channels/page.js +3 -0
  30. package/dist/modules/communication_channels/backend/communication_channels/channels/page.js.map +2 -2
  31. package/dist/modules/configs/lib/system-status.js +9 -0
  32. package/dist/modules/configs/lib/system-status.js.map +2 -2
  33. package/dist/modules/currencies/backend/currencies/page.js +3 -1
  34. package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
  35. package/dist/modules/currencies/backend/exchange-rates/page.js +3 -1
  36. package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
  37. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +3 -1
  38. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
  39. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +3 -1
  40. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
  41. package/dist/modules/customers/ai-tools/companies-pack.js +4 -1
  42. package/dist/modules/customers/ai-tools/companies-pack.js.map +2 -2
  43. package/dist/modules/customers/ai-tools/deals-pack.js +4 -1
  44. package/dist/modules/customers/ai-tools/deals-pack.js.map +2 -2
  45. package/dist/modules/customers/ai-tools/people-pack.js +4 -1
  46. package/dist/modules/customers/ai-tools/people-pack.js.map +2 -2
  47. package/dist/modules/customers/api/deals/map/route.js +2 -1
  48. package/dist/modules/customers/api/deals/map/route.js.map +2 -2
  49. package/dist/modules/customers/backend/customers/companies/page.js +3 -1
  50. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  51. package/dist/modules/customers/backend/customers/deals/page.js +5 -2
  52. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  53. package/dist/modules/customers/backend/customers/people/page.js +3 -1
  54. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  55. package/dist/modules/customers/components/CustomerTodosTable.js +1 -0
  56. package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
  57. package/dist/modules/data_sync/backend/data-sync/page.js +3 -1
  58. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  59. package/dist/modules/devices/backend/devices/page.js +3 -1
  60. package/dist/modules/devices/backend/devices/page.js.map +2 -2
  61. package/dist/modules/directory/backend/directory/organizations/page.js +2 -1
  62. package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
  63. package/dist/modules/directory/backend/directory/tenants/page.js +2 -1
  64. package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
  65. package/dist/modules/entities/api/records.js +4 -2
  66. package/dist/modules/entities/api/records.js.map +2 -2
  67. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +3 -1
  68. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  69. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js +3 -0
  70. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js.map +2 -2
  71. package/dist/modules/eudr/backend/eudr/plots/page.js +3 -0
  72. package/dist/modules/eudr/backend/eudr/plots/page.js.map +2 -2
  73. package/dist/modules/eudr/backend/eudr/product-mappings/page.js +3 -0
  74. package/dist/modules/eudr/backend/eudr/product-mappings/page.js.map +2 -2
  75. package/dist/modules/eudr/backend/eudr/risk-assessments/page.js +3 -0
  76. package/dist/modules/eudr/backend/eudr/risk-assessments/page.js.map +2 -2
  77. package/dist/modules/eudr/backend/eudr/statements/page.js +3 -0
  78. package/dist/modules/eudr/backend/eudr/statements/page.js.map +2 -2
  79. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +1 -0
  80. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
  81. package/dist/modules/feature_toggles/components/OverridesTable.js +1 -0
  82. package/dist/modules/feature_toggles/components/OverridesTable.js.map +2 -2
  83. package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js +3 -0
  84. package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js.map +2 -2
  85. package/dist/modules/inbox_ops/backend/inbox-ops/page.js +3 -0
  86. package/dist/modules/inbox_ops/backend/inbox-ops/page.js.map +2 -2
  87. package/dist/modules/messages/components/MessagesInboxPageClient.js +4 -1
  88. package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
  89. package/dist/modules/payment_gateways/backend/payment-gateways/page.js +3 -1
  90. package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +2 -2
  91. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +3 -0
  92. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  93. package/dist/modules/push_notifications/backend/push_notifications/page.js +3 -1
  94. package/dist/modules/push_notifications/backend/push_notifications/page.js.map +2 -2
  95. package/dist/modules/query_index/lib/engine.js +108 -48
  96. package/dist/modules/query_index/lib/engine.js.map +2 -2
  97. package/dist/modules/resources/backend/resources/resource-types/page.js +3 -1
  98. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  99. package/dist/modules/resources/backend/resources/resources/page.js +3 -1
  100. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  101. package/dist/modules/sales/backend/sales/channels/offers/page.js +3 -0
  102. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  103. package/dist/modules/sales/backend/sales/channels/page.js +3 -0
  104. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  105. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +3 -0
  106. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
  107. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +4 -0
  108. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  109. package/dist/modules/staff/backend/staff/leave-requests/page.js +3 -0
  110. package/dist/modules/staff/backend/staff/leave-requests/page.js.map +2 -2
  111. package/dist/modules/staff/backend/staff/my-leave-requests/page.js +3 -0
  112. package/dist/modules/staff/backend/staff/my-leave-requests/page.js.map +2 -2
  113. package/dist/modules/staff/backend/staff/team-members/page.js +3 -0
  114. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  115. package/dist/modules/staff/backend/staff/team-roles/page.js +3 -0
  116. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  117. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +3 -0
  118. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  119. package/dist/modules/staff/backend/staff/teams/page.js +3 -0
  120. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  121. package/dist/modules/staff/backend/staff/timesheets/projects/page.js +3 -0
  122. package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
  123. package/dist/modules/warranty_claims/backend/page.js +3 -0
  124. package/dist/modules/warranty_claims/backend/page.js.map +2 -2
  125. package/dist/modules/warranty_claims/backend/warranty_claims/registrations/page.js +3 -0
  126. package/dist/modules/warranty_claims/backend/warranty_claims/registrations/page.js.map +2 -2
  127. package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.js +3 -0
  128. package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.js.map +2 -2
  129. package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.js +3 -0
  130. package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.js.map +2 -2
  131. package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js +3 -0
  132. package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js.map +2 -2
  133. package/dist/modules/wms/commands/inventory-actions.js +3 -0
  134. package/dist/modules/wms/commands/inventory-actions.js.map +2 -2
  135. package/dist/modules/wms/components/backend/WmsConfigurationPage.js +4 -0
  136. package/dist/modules/wms/components/backend/WmsConfigurationPage.js.map +2 -2
  137. package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js +1 -0
  138. package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js.map +2 -2
  139. package/dist/modules/wms/components/backend/WmsLotsListPage.js +1 -0
  140. package/dist/modules/wms/components/backend/WmsLotsListPage.js.map +2 -2
  141. package/dist/modules/wms/components/backend/inventoryMutationLoaders.js +27 -20
  142. package/dist/modules/wms/components/backend/inventoryMutationLoaders.js.map +2 -2
  143. package/dist/modules/workflows/backend/definitions/page.js +3 -1
  144. package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
  145. package/dist/modules/workflows/backend/events/page.js +3 -1
  146. package/dist/modules/workflows/backend/events/page.js.map +2 -2
  147. package/dist/modules/workflows/backend/instances/page.js +3 -1
  148. package/dist/modules/workflows/backend/instances/page.js.map +2 -2
  149. package/dist/modules/workflows/backend/tasks/page.js +3 -1
  150. package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
  151. package/package.json +7 -7
  152. package/src/modules/api_keys/backend/api-keys/page.tsx +4 -1
  153. package/src/modules/attachments/components/AttachmentLibrary.tsx +3 -0
  154. package/src/modules/audit_logs/backend/audit-logs/page.tsx +8 -0
  155. package/src/modules/auth/backend/roles/page.tsx +4 -2
  156. package/src/modules/auth/backend/users/page.tsx +3 -2
  157. package/src/modules/business_rules/backend/logs/page.tsx +4 -1
  158. package/src/modules/business_rules/backend/rules/page.tsx +4 -1
  159. package/src/modules/business_rules/backend/sets/page.tsx +4 -1
  160. package/src/modules/catalog/ai-agents.ts +1 -1
  161. package/src/modules/catalog/ai-tools/merchandising-pack.ts +2 -2
  162. package/src/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.tsx +12 -5
  163. package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +3 -0
  164. package/src/modules/catalog/components/products/ProductsDataTable.tsx +7 -0
  165. package/src/modules/catalog/i18n/de.json +1 -0
  166. package/src/modules/catalog/i18n/en.json +1 -0
  167. package/src/modules/catalog/i18n/es.json +1 -0
  168. package/src/modules/catalog/i18n/ko.json +1 -0
  169. package/src/modules/catalog/i18n/pl.json +1 -0
  170. package/src/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.tsx +4 -0
  171. package/src/modules/communication_channels/backend/communication_channels/channels/page.tsx +4 -0
  172. package/src/modules/configs/i18n/de.json +2 -0
  173. package/src/modules/configs/i18n/en.json +2 -0
  174. package/src/modules/configs/i18n/es.json +2 -0
  175. package/src/modules/configs/i18n/ko.json +2 -0
  176. package/src/modules/configs/i18n/pl.json +2 -0
  177. package/src/modules/configs/lib/system-status.ts +9 -0
  178. package/src/modules/currencies/backend/currencies/page.tsx +4 -1
  179. package/src/modules/currencies/backend/exchange-rates/page.tsx +4 -1
  180. package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +4 -1
  181. package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +4 -1
  182. package/src/modules/customers/ai-tools/companies-pack.ts +4 -1
  183. package/src/modules/customers/ai-tools/deals-pack.ts +4 -1
  184. package/src/modules/customers/ai-tools/people-pack.ts +4 -1
  185. package/src/modules/customers/api/deals/map/route.ts +1 -0
  186. package/src/modules/customers/backend/customers/companies/page.tsx +4 -1
  187. package/src/modules/customers/backend/customers/deals/page.tsx +8 -2
  188. package/src/modules/customers/backend/customers/people/page.tsx +4 -1
  189. package/src/modules/customers/components/CustomerTodosTable.tsx +2 -0
  190. package/src/modules/data_sync/backend/data-sync/page.tsx +4 -1
  191. package/src/modules/devices/backend/devices/page.tsx +4 -1
  192. package/src/modules/directory/backend/directory/organizations/page.tsx +3 -1
  193. package/src/modules/directory/backend/directory/tenants/page.tsx +3 -1
  194. package/src/modules/entities/api/records.ts +2 -0
  195. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +4 -1
  196. package/src/modules/eudr/backend/eudr/evidence-submissions/page.tsx +4 -0
  197. package/src/modules/eudr/backend/eudr/plots/page.tsx +4 -0
  198. package/src/modules/eudr/backend/eudr/product-mappings/page.tsx +4 -0
  199. package/src/modules/eudr/backend/eudr/risk-assessments/page.tsx +4 -0
  200. package/src/modules/eudr/backend/eudr/statements/page.tsx +4 -0
  201. package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +2 -1
  202. package/src/modules/feature_toggles/components/OverridesTable.tsx +2 -1
  203. package/src/modules/inbox_ops/backend/inbox-ops/log/page.tsx +4 -0
  204. package/src/modules/inbox_ops/backend/inbox-ops/page.tsx +4 -0
  205. package/src/modules/messages/components/MessagesInboxPageClient.tsx +4 -0
  206. package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +4 -1
  207. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +4 -0
  208. package/src/modules/push_notifications/backend/push_notifications/page.tsx +4 -1
  209. package/src/modules/query_index/lib/engine.ts +156 -53
  210. package/src/modules/resources/backend/resources/resource-types/page.tsx +4 -1
  211. package/src/modules/resources/backend/resources/resources/page.tsx +4 -1
  212. package/src/modules/sales/backend/sales/channels/offers/page.tsx +4 -0
  213. package/src/modules/sales/backend/sales/channels/page.tsx +4 -0
  214. package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +4 -0
  215. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +5 -0
  216. package/src/modules/staff/backend/staff/leave-requests/page.tsx +4 -0
  217. package/src/modules/staff/backend/staff/my-leave-requests/page.tsx +4 -0
  218. package/src/modules/staff/backend/staff/team-members/page.tsx +6 -0
  219. package/src/modules/staff/backend/staff/team-roles/page.tsx +4 -0
  220. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +4 -0
  221. package/src/modules/staff/backend/staff/teams/page.tsx +4 -0
  222. package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +4 -0
  223. package/src/modules/warranty_claims/backend/page.tsx +4 -0
  224. package/src/modules/warranty_claims/backend/warranty_claims/registrations/page.tsx +4 -0
  225. package/src/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.tsx +4 -0
  226. package/src/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.tsx +4 -0
  227. package/src/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.tsx +4 -0
  228. package/src/modules/wms/commands/inventory-actions.ts +3 -0
  229. package/src/modules/wms/components/backend/WmsConfigurationPage.tsx +5 -0
  230. package/src/modules/wms/components/backend/WmsInventoryConsolePage.tsx +2 -0
  231. package/src/modules/wms/components/backend/WmsLotsListPage.tsx +2 -0
  232. package/src/modules/wms/components/backend/inventoryMutationLoaders.ts +36 -20
  233. package/src/modules/workflows/backend/definitions/page.tsx +4 -1
  234. package/src/modules/workflows/backend/events/page.tsx +4 -1
  235. package/src/modules/workflows/backend/instances/page.tsx +4 -1
  236. package/src/modules/workflows/backend/tasks/page.tsx +4 -1
@@ -24,6 +24,7 @@ import { tokenizeText } from "@open-mercato/shared/lib/search/tokenize";
24
24
  import { runBeforeQueryPipeline, runAfterQueryPipeline } from "@open-mercato/shared/lib/query/query-extension-runner";
25
25
  import { warnOnCiphertextLikeFallback } from "@open-mercato/shared/lib/query/ciphertext-search-warning";
26
26
  import { resolveEncryptedSortFields, resolveEncryptedSortMaxRows, sortRowsInMemory } from "@open-mercato/shared/lib/query/encrypted-sort";
27
+ import { resolveListCountCap } from "@open-mercato/shared/lib/query/count-cap";
27
28
  import { mapWithConcurrency } from "@open-mercato/shared/lib/query/bounded-decrypt";
28
29
  import { createLogger } from "@open-mercato/shared/lib/logger";
29
30
  import { parseNumberWithDefault } from "@open-mercato/shared/lib/number";
@@ -799,6 +800,79 @@ class HybridQueryEngine {
799
800
  };
800
801
  const hasCustomFieldFilters = cfFilters.length > 0;
801
802
  const canOptimizeCount = !hasCustomFieldFilters && !hasNonBaseSearchSource;
803
+ const isRowsetDependentFilter = (filter) => {
804
+ const baseField = resolveBaseColumn(String(filter.field));
805
+ if (!baseField) return true;
806
+ if ((filter.op === "like" || filter.op === "ilike") && searchRuntime.enabled && typeof filter.value === "string" && hasNonBaseSearchSource) return true;
807
+ return false;
808
+ };
809
+ const rowsetRegularFilters = regularBaseFilters.filter((filter) => isRowsetDependentFilter(filter));
810
+ const outerRegularFilters = regularBaseFilters.filter((filter) => !isRowsetDependentFilter(filter));
811
+ const orGroupsRowsetDependent = orGroupCfFilters.length > 0 || orGroupFilters.some((filter) => isRowsetDependentFilter(filter));
812
+ const hasInnerTypedCfSource = preparedCfSources.some((source) => ((opts.customFieldSources ?? []).find((s) => s && (s.alias ?? void 0) === source.alias)?.join?.type ?? "left") === "inner");
813
+ const needsIndexRowset = hasCustomFieldFilters || rowsetRegularFilters.length > 0 || orGroupsRowsetDependent || hasInnerTypedCfSource;
814
+ const applyCountShape = async (q) => {
815
+ let next = applyBaseScope(q);
816
+ for (const filter of outerRegularFilters) {
817
+ const baseField = resolveBaseColumn(String(filter.field));
818
+ if (!baseField) continue;
819
+ next = this.applyColumnFilter(next, qualify(baseField), filter, {
820
+ ...searchRuntime,
821
+ entity,
822
+ field: String(filter.field),
823
+ recordIdColumn: qualify("id")
824
+ });
825
+ }
826
+ if (!orGroupsRowsetDependent) next = applyOrGroupedBaseFilters(next);
827
+ if (needsIndexRowset) {
828
+ let rowset = db.selectFrom(sql`(select 1)`.as("om_count_seed")).select(sql`1`.as("one"));
829
+ rowset = applyEntityIndexesJoin(rowset);
830
+ rowset = applyCustomFieldSourceJoins(rowset);
831
+ rowset = applyCfFilters(rowset);
832
+ for (const filter of rowsetRegularFilters) {
833
+ const baseField = resolveBaseColumn(String(filter.field));
834
+ if (!baseField) {
835
+ rowset = this.applyIndexDocFilterFromAlias(
836
+ rowset,
837
+ "ei",
838
+ entity,
839
+ String(filter.field),
840
+ filter.op,
841
+ filter.value,
842
+ qualify("id"),
843
+ searchRuntime
844
+ );
845
+ continue;
846
+ }
847
+ rowset = this.applyColumnFilter(rowset, qualify(baseField), filter, {
848
+ ...searchRuntime,
849
+ entity,
850
+ field: String(filter.field),
851
+ recordIdColumn: qualify("id")
852
+ });
853
+ }
854
+ if (orGroupsRowsetDependent) rowset = applyOrGroupedBaseFilters(rowset);
855
+ const capturedRowset = rowset;
856
+ next = next.where((eb) => eb.exists(capturedRowset));
857
+ }
858
+ next = await applyJoinFilters({
859
+ db,
860
+ baseTable,
861
+ builder: next,
862
+ joinMap,
863
+ joinFilters,
864
+ aliasTables,
865
+ qualifyBase: (column) => qualify(column),
866
+ applyAliasScope: async (target, alias) => applyAliasScopes(target, alias),
867
+ applyFilterOp: (target, column, op, value) => applyJoinFilterOpFn(target, column, op, value),
868
+ applyJoinFilterOp: async (target, filter, qualified, join) => {
869
+ const applied = await applyJoinSearchFilterOp(target, filter, qualified, join);
870
+ return { applied, builder: target };
871
+ },
872
+ columnExists: (tbl, column) => this.columnExists(tbl, column)
873
+ });
874
+ return next;
875
+ };
802
876
  const selectFieldSet = new Set(opts.fields && opts.fields.length ? opts.fields.map(String) : Array.from(columns.keys()));
803
877
  if (requiresPlaintextSort) {
804
878
  for (const field of encryptedSortFields) selectFieldSet.add(field);
@@ -854,30 +928,11 @@ class HybridQueryEngine {
854
928
  const page = opts.page?.page ?? 1;
855
929
  const pageSize = opts.page?.pageSize ?? 20;
856
930
  const sqlDebugEnabled = this.isSqlDebugEnabled();
857
- let total;
858
- if (canOptimizeCount) {
859
- const optimizedRoot = db.selectFrom(`${baseTable} as b`);
860
- let countCore = applyBaseScope(optimizedRoot);
861
- countCore = applyRegularBaseFilters(countCore);
862
- countCore = applyOrGroupedBaseFilters(countCore);
863
- countCore = await applyJoinFilters({
864
- db,
865
- baseTable,
866
- builder: countCore,
867
- joinMap,
868
- joinFilters,
869
- aliasTables,
870
- qualifyBase: (column) => qualify(column),
871
- applyAliasScope: async (target, alias) => applyAliasScopes(target, alias),
872
- applyFilterOp: (target, column, op, value) => applyJoinFilterOpFn(target, column, op, value),
873
- applyJoinFilterOp: async (target, filter, qualified, join) => {
874
- const applied = await applyJoinSearchFilterOp(target, filter, qualified, join);
875
- return { applied, builder: target };
876
- },
877
- columnExists: (tbl, column) => this.columnExists(tbl, column)
878
- });
879
- const sub = countCore.select(sql.ref(qualify("id")).as("id")).groupBy(qualify("id")).as("sq");
880
- const countQuery = db.selectFrom(sub).select(sql`count(*)`.as("count"));
931
+ const countCap = resolveListCountCap();
932
+ const runBoundedCount = async (wasOptimizable) => {
933
+ const countRoot = db.selectFrom(`${baseTable} as b`);
934
+ const shape = await applyCountShape(countRoot);
935
+ const countQuery = countCap !== null ? db.selectFrom(shape.select(sql`1`.as("one")).limit(countCap + 1).as("om_count_probe")).select(sql`count(*)`.as("count")) : shape.select(sql`count(*)`.as("count"));
881
936
  if (debugEnabled && sqlDebugEnabled) {
882
937
  const compiled = countQuery.compile();
883
938
  this.debug("query:sql:count", { entity, sql: compiled.sql, bindings: compiled.parameters });
@@ -886,26 +941,18 @@ class HybridQueryEngine {
886
941
  "query:sql:count",
887
942
  entity,
888
943
  () => countQuery.executeTakeFirst(),
889
- { optimized: true },
944
+ { optimized: wasOptimizable },
890
945
  profiler
891
946
  );
892
- total = this.parseCount(countRow);
893
- } else {
894
- const countRoot = db.selectFrom(`${baseTable} as b`);
895
- const countBuilder = (await applyQueryShape(countRoot)).select(sql`count(distinct ${sql.ref(qualify("id"))})`.as("count"));
896
- if (debugEnabled && sqlDebugEnabled) {
897
- const compiled = countBuilder.compile();
898
- this.debug("query:sql:count", { entity, sql: compiled.sql, bindings: compiled.parameters });
947
+ const probed = this.parseCount(countRow);
948
+ if (countCap !== null && probed > countCap) {
949
+ return { total: countCap, warning: { entity, cap: countCap } };
899
950
  }
900
- const countRow = await this.captureSqlTiming(
901
- "query:sql:count",
902
- entity,
903
- () => countBuilder.executeTakeFirst(),
904
- { optimized: false },
905
- profiler
906
- );
907
- total = this.parseCount(countRow);
908
- }
951
+ return { total: probed };
952
+ };
953
+ const counted = await runBoundedCount(canOptimizeCount);
954
+ const total = counted.total;
955
+ const listCountCapWarning = counted.warning;
909
956
  const dekKeyCache = /* @__PURE__ */ new Map();
910
957
  const decryptRow = async (item) => {
911
958
  let next = item;
@@ -952,23 +999,25 @@ class HybridQueryEngine {
952
999
  const sortFieldNames = Array.from(/* @__PURE__ */ new Set(["id", ...scopeFieldNames, ...resolvedSorts.map((s) => String(s.field))]));
953
1000
  phase1 = applySelection(phase1, sortFieldNames);
954
1001
  if (cap !== null) {
955
- phase1 = phase1.limit(cap).orderBy(qualify("id"), "asc");
1002
+ phase1 = phase1.limit(cap + 1).orderBy(qualify("id"), "asc");
956
1003
  }
957
1004
  if (debugEnabled && sqlDebugEnabled) {
958
1005
  const compiled = phase1.compile();
959
1006
  this.debug("query:sql:data:phase1", { entity, sql: compiled.sql, bindings: compiled.parameters });
960
1007
  }
961
- const candidateRows = await this.captureSqlTiming(
1008
+ const candidateRowsRaw = await this.captureSqlTiming(
962
1009
  "query:sql:data:phase1",
963
1010
  entity,
964
1011
  () => phase1.execute(),
965
1012
  { phase: 1 },
966
1013
  profiler
967
1014
  );
1015
+ const sortTruncated = cap !== null && candidateRowsRaw.length > cap;
1016
+ const candidateRows = sortTruncated && cap !== null ? candidateRowsRaw.slice(0, cap) : candidateRowsRaw;
968
1017
  const decryptedCandidates = await mapWithConcurrency(candidateRows, DECRYPT_CONCURRENCY, decryptRow);
969
1018
  const orderedCandidates = sortRowsInMemory(decryptedCandidates, resolvedSorts);
970
1019
  const pageIds = orderedCandidates.slice((page - 1) * pageSize, page * pageSize).map((row) => row.id);
971
- if (cap !== null && total > cap) {
1020
+ if (sortTruncated && cap !== null) {
972
1021
  encryptedSortRowCapWarning = {
973
1022
  entity,
974
1023
  sortFields: resolvedSorts.map((s) => String(s.field)),
@@ -1020,10 +1069,11 @@ class HybridQueryEngine {
1020
1069
  if (debugEnabled) this.debug("query:complete", { entity, total, items: items.length });
1021
1070
  const typedItems = items;
1022
1071
  let result = { items: typedItems, page, pageSize, total };
1023
- if (partialIndexWarning || encryptedSortRowCapWarning) {
1072
+ if (partialIndexWarning || encryptedSortRowCapWarning || listCountCapWarning) {
1024
1073
  const meta = {};
1025
1074
  if (partialIndexWarning) meta.partialIndexWarning = partialIndexWarning;
1026
1075
  if (encryptedSortRowCapWarning) meta.encryptedSortRowCapWarning = encryptedSortRowCapWarning;
1076
+ if (listCountCapWarning) meta.listCountCapWarning = listCountCapWarning;
1027
1077
  result.meta = meta;
1028
1078
  }
1029
1079
  result = await applyAfterExtensions(result);
@@ -1645,16 +1695,26 @@ class HybridQueryEngine {
1645
1695
  };
1646
1696
  const page = opts.page?.page ?? 1;
1647
1697
  const pageSize = opts.page?.pageSize ?? 20;
1698
+ const countCap = resolveListCountCap();
1648
1699
  const root = db.selectFrom(`custom_entities_storage as ${alias}`);
1649
- const countQuery = applyScope(root).select(sql`count(distinct ${sql.ref(`${alias}.entity_id`)})`.as("count"));
1700
+ const countShape = applyScope(root);
1701
+ const countQuery = countCap !== null ? db.selectFrom(countShape.select(sql`1`.as("one")).limit(countCap + 1).as("om_count_probe")).select(sql`count(*)`.as("count")) : countShape.select(sql`count(*)`.as("count"));
1650
1702
  const countRow = await countQuery.executeTakeFirst();
1651
- const total = this.parseCount(countRow);
1703
+ const probed = this.parseCount(countRow);
1704
+ let total = probed;
1705
+ let listCountCapWarning;
1706
+ if (countCap !== null && probed > countCap) {
1707
+ total = countCap;
1708
+ listCountCapWarning = { entity, cap: countCap };
1709
+ }
1652
1710
  let dataQuery = applyScope(db.selectFrom(`custom_entities_storage as ${alias}`));
1653
1711
  dataQuery = applySelection(dataQuery);
1654
1712
  dataQuery = applySort(dataQuery);
1655
1713
  dataQuery = dataQuery.limit(pageSize).offset((page - 1) * pageSize);
1656
1714
  const items = await dataQuery.execute();
1657
- return { items, page, pageSize, total };
1715
+ const result = { items, page, pageSize, total };
1716
+ if (listCountCapWarning) result.meta = { listCountCapWarning };
1717
+ return result;
1658
1718
  }
1659
1719
  async tableExists(table) {
1660
1720
  const db = this.getDb();