@gaganref/confect-server 0.0.0-stage → 10.3.1-fork.10

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 (367) hide show
  1. package/CHANGELOG.md +2119 -0
  2. package/LICENSE +7 -0
  3. package/README.md +16 -2
  4. package/dist/ActionCtx.d.ts +10 -0
  5. package/dist/ActionCtx.d.ts.map +1 -0
  6. package/dist/ActionCtx.js +18 -0
  7. package/dist/ActionCtx.js.map +1 -0
  8. package/dist/ActionRunner.d.ts +16 -0
  9. package/dist/ActionRunner.d.ts.map +1 -0
  10. package/dist/ActionRunner.js +18 -0
  11. package/dist/ActionRunner.js.map +1 -0
  12. package/dist/AiGatewayDecisionClient.d.ts +20 -0
  13. package/dist/AiGatewayDecisionClient.d.ts.map +1 -0
  14. package/dist/AiGatewayDecisionClient.js +31 -0
  15. package/dist/AiGatewayDecisionClient.js.map +1 -0
  16. package/dist/AiGatewayDecisionModel.d.ts +24 -0
  17. package/dist/AiGatewayDecisionModel.d.ts.map +1 -0
  18. package/dist/AiGatewayDecisionModel.js +27 -0
  19. package/dist/AiGatewayDecisionModel.js.map +1 -0
  20. package/dist/AiGatewayLanguageClient.d.ts +21 -0
  21. package/dist/AiGatewayLanguageClient.d.ts.map +1 -0
  22. package/dist/AiGatewayLanguageClient.js +32 -0
  23. package/dist/AiGatewayLanguageClient.js.map +1 -0
  24. package/dist/AiGatewayLanguageModel.d.ts +95 -0
  25. package/dist/AiGatewayLanguageModel.d.ts.map +1 -0
  26. package/dist/AiGatewayLanguageModel.js +42 -0
  27. package/dist/AiGatewayLanguageModel.js.map +1 -0
  28. package/dist/Auth.d.ts +20 -0
  29. package/dist/Auth.d.ts.map +1 -0
  30. package/dist/Auth.js +31 -0
  31. package/dist/Auth.js.map +1 -0
  32. package/dist/BlobNotFoundError.d.ts +9 -0
  33. package/dist/BlobNotFoundError.d.ts.map +1 -0
  34. package/dist/BlobNotFoundError.js +13 -0
  35. package/dist/BlobNotFoundError.js.map +1 -0
  36. package/dist/Callback.d.ts +31 -0
  37. package/dist/Callback.d.ts.map +1 -0
  38. package/dist/Callback.js +182 -0
  39. package/dist/Callback.js.map +1 -0
  40. package/dist/ComponentCtx.d.ts +71 -0
  41. package/dist/ComponentCtx.d.ts.map +1 -0
  42. package/dist/ComponentCtx.js +0 -0
  43. package/dist/ConvexConfigProvider.d.ts +21 -0
  44. package/dist/ConvexConfigProvider.d.ts.map +1 -0
  45. package/dist/ConvexConfigProvider.js +36 -0
  46. package/dist/ConvexConfigProvider.js.map +1 -0
  47. package/dist/ConvexFunctionDefinitions.d.ts +25 -0
  48. package/dist/ConvexFunctionDefinitions.d.ts.map +1 -0
  49. package/dist/ConvexFunctionDefinitions.js +25 -0
  50. package/dist/ConvexFunctionDefinitions.js.map +1 -0
  51. package/dist/ConvexLogger.d.ts +17 -0
  52. package/dist/ConvexLogger.d.ts.map +1 -0
  53. package/dist/ConvexLogger.js +33 -0
  54. package/dist/ConvexLogger.js.map +1 -0
  55. package/dist/CronJob.d.ts +14 -0
  56. package/dist/CronJob.d.ts.map +1 -0
  57. package/dist/CronJob.js +22 -0
  58. package/dist/CronJob.js.map +1 -0
  59. package/dist/CronJobs.d.ts +22 -0
  60. package/dist/CronJobs.d.ts.map +1 -0
  61. package/dist/CronJobs.js +83 -0
  62. package/dist/CronJobs.js.map +1 -0
  63. package/dist/DataModel.d.ts +28 -0
  64. package/dist/DataModel.d.ts.map +1 -0
  65. package/dist/DataModel.js +7 -0
  66. package/dist/DataModel.js.map +1 -0
  67. package/dist/DatabaseReader.d.ts +26 -0
  68. package/dist/DatabaseReader.d.ts.map +1 -0
  69. package/dist/DatabaseReader.js +33 -0
  70. package/dist/DatabaseReader.js.map +1 -0
  71. package/dist/DatabaseSchema.d.ts +67 -0
  72. package/dist/DatabaseSchema.d.ts.map +1 -0
  73. package/dist/DatabaseSchema.js +61 -0
  74. package/dist/DatabaseSchema.js.map +1 -0
  75. package/dist/DatabaseWriter.d.ts +44 -0
  76. package/dist/DatabaseWriter.d.ts.map +1 -0
  77. package/dist/DatabaseWriter.js +47 -0
  78. package/dist/DatabaseWriter.js.map +1 -0
  79. package/dist/Document.d.ts +37 -0
  80. package/dist/Document.d.ts.map +1 -0
  81. package/dist/Document.js +54 -0
  82. package/dist/Document.js.map +1 -0
  83. package/dist/ExecutionMetadata.d.ts +13 -0
  84. package/dist/ExecutionMetadata.d.ts.map +1 -0
  85. package/dist/ExecutionMetadata.js +19 -0
  86. package/dist/ExecutionMetadata.js.map +1 -0
  87. package/dist/FunctionImpl.d.ts +39 -0
  88. package/dist/FunctionImpl.d.ts.map +1 -0
  89. package/dist/FunctionImpl.js +46 -0
  90. package/dist/FunctionImpl.js.map +1 -0
  91. package/dist/FunctionRegistryItem.d.ts +36 -0
  92. package/dist/FunctionRegistryItem.d.ts.map +1 -0
  93. package/dist/FunctionRegistryItem.js +34 -0
  94. package/dist/FunctionRegistryItem.js.map +1 -0
  95. package/dist/GroupImpl.d.ts +77 -0
  96. package/dist/GroupImpl.d.ts.map +1 -0
  97. package/dist/GroupImpl.js +81 -0
  98. package/dist/GroupImpl.js.map +1 -0
  99. package/dist/GroupRegistry.d.ts +8 -0
  100. package/dist/GroupRegistry.d.ts.map +1 -0
  101. package/dist/GroupRegistry.js +26 -0
  102. package/dist/GroupRegistry.js.map +1 -0
  103. package/dist/Handler.d.ts +47 -0
  104. package/dist/Handler.d.ts.map +1 -0
  105. package/dist/Handler.js +7 -0
  106. package/dist/Handler.js.map +1 -0
  107. package/dist/HttpRouter.d.ts +80 -0
  108. package/dist/HttpRouter.d.ts.map +1 -0
  109. package/dist/HttpRouter.js +195 -0
  110. package/dist/HttpRouter.js.map +1 -0
  111. package/dist/MiddlewareImpl.d.ts +79 -0
  112. package/dist/MiddlewareImpl.d.ts.map +1 -0
  113. package/dist/MiddlewareImpl.js +58 -0
  114. package/dist/MiddlewareImpl.js.map +1 -0
  115. package/dist/MiddlewareRegistryItem.d.ts +12 -0
  116. package/dist/MiddlewareRegistryItem.d.ts.map +1 -0
  117. package/dist/MiddlewareRegistryItem.js +15 -0
  118. package/dist/MiddlewareRegistryItem.js.map +1 -0
  119. package/dist/MutationCtx.d.ts +10 -0
  120. package/dist/MutationCtx.d.ts.map +1 -0
  121. package/dist/MutationCtx.js +18 -0
  122. package/dist/MutationCtx.js.map +1 -0
  123. package/dist/MutationRunner.d.ts +27 -0
  124. package/dist/MutationRunner.d.ts.map +1 -0
  125. package/dist/MutationRunner.js +28 -0
  126. package/dist/MutationRunner.js.map +1 -0
  127. package/dist/MutationTransactionContext.d.ts +17 -0
  128. package/dist/MutationTransactionContext.d.ts.map +1 -0
  129. package/dist/MutationTransactionContext.js +20 -0
  130. package/dist/MutationTransactionContext.js.map +1 -0
  131. package/dist/OrderedQuery.d.ts +32 -0
  132. package/dist/OrderedQuery.d.ts.map +1 -0
  133. package/dist/OrderedQuery.js +36 -0
  134. package/dist/OrderedQuery.js.map +1 -0
  135. package/dist/QueryCtx.d.ts +10 -0
  136. package/dist/QueryCtx.d.ts.map +1 -0
  137. package/dist/QueryCtx.js +18 -0
  138. package/dist/QueryCtx.js.map +1 -0
  139. package/dist/QueryInitializer.d.ts +75 -0
  140. package/dist/QueryInitializer.d.ts.map +1 -0
  141. package/dist/QueryInitializer.js +105 -0
  142. package/dist/QueryInitializer.js.map +1 -0
  143. package/dist/QueryRunner.d.ts +46 -0
  144. package/dist/QueryRunner.d.ts.map +1 -0
  145. package/dist/QueryRunner.js +30 -0
  146. package/dist/QueryRunner.js.map +1 -0
  147. package/dist/QueryStream.d.ts +678 -0
  148. package/dist/QueryStream.d.ts.map +1 -0
  149. package/dist/QueryStream.js +943 -0
  150. package/dist/QueryStream.js.map +1 -0
  151. package/dist/QueryStreamCursor.d.ts +39 -0
  152. package/dist/QueryStreamCursor.d.ts.map +1 -0
  153. package/dist/QueryStreamCursor.js +52 -0
  154. package/dist/QueryStreamCursor.js.map +1 -0
  155. package/dist/QueryStreamIndexPrefix.d.ts +48 -0
  156. package/dist/QueryStreamIndexPrefix.d.ts.map +1 -0
  157. package/dist/QueryStreamIndexPrefix.js +38 -0
  158. package/dist/QueryStreamIndexPrefix.js.map +1 -0
  159. package/dist/QueryStreamIndexRange.d.ts +193 -0
  160. package/dist/QueryStreamIndexRange.d.ts.map +1 -0
  161. package/dist/QueryStreamIndexRange.js +241 -0
  162. package/dist/QueryStreamIndexRange.js.map +1 -0
  163. package/dist/QueryStreamKey.d.ts +64 -0
  164. package/dist/QueryStreamKey.d.ts.map +1 -0
  165. package/dist/QueryStreamKey.js +69 -0
  166. package/dist/QueryStreamKey.js.map +1 -0
  167. package/dist/QueryStreamKeyBounds.d.ts +136 -0
  168. package/dist/QueryStreamKeyBounds.d.ts.map +1 -0
  169. package/dist/QueryStreamKeyBounds.js +208 -0
  170. package/dist/QueryStreamKeyBounds.js.map +1 -0
  171. package/dist/QueryStreamKeyLabels.d.ts +27 -0
  172. package/dist/QueryStreamKeyLabels.d.ts.map +1 -0
  173. package/dist/QueryStreamKeyLabels.js +22 -0
  174. package/dist/QueryStreamKeyLabels.js.map +1 -0
  175. package/dist/QueryStreamKeyLayout.d.ts +179 -0
  176. package/dist/QueryStreamKeyLayout.d.ts.map +1 -0
  177. package/dist/QueryStreamKeyLayout.js +167 -0
  178. package/dist/QueryStreamKeyLayout.js.map +1 -0
  179. package/dist/QueryStreamKeyValues.d.ts +40 -0
  180. package/dist/QueryStreamKeyValues.d.ts.map +1 -0
  181. package/dist/QueryStreamKeyValues.js +57 -0
  182. package/dist/QueryStreamKeyValues.js.map +1 -0
  183. package/dist/QueryStreamOrderDirection.d.ts +24 -0
  184. package/dist/QueryStreamOrderDirection.d.ts.map +1 -0
  185. package/dist/QueryStreamOrderDirection.js +11 -0
  186. package/dist/QueryStreamOrderDirection.js.map +1 -0
  187. package/dist/QueryStreamPagination.d.ts +264 -0
  188. package/dist/QueryStreamPagination.d.ts.map +1 -0
  189. package/dist/QueryStreamPagination.js +172 -0
  190. package/dist/QueryStreamPagination.js.map +1 -0
  191. package/dist/QueryStreamReadBudget.d.ts +63 -0
  192. package/dist/QueryStreamReadBudget.d.ts.map +1 -0
  193. package/dist/QueryStreamReadBudget.js +81 -0
  194. package/dist/QueryStreamReadBudget.js.map +1 -0
  195. package/dist/QueryTransactionContext.d.ts +16 -0
  196. package/dist/QueryTransactionContext.d.ts.map +1 -0
  197. package/dist/QueryTransactionContext.js +17 -0
  198. package/dist/QueryTransactionContext.js.map +1 -0
  199. package/dist/RegisteredConvexFunction.d.ts +359 -0
  200. package/dist/RegisteredConvexFunction.d.ts.map +1 -0
  201. package/dist/RegisteredConvexFunction.js +154 -0
  202. package/dist/RegisteredConvexFunction.js.map +1 -0
  203. package/dist/RegisteredFunction.d.ts +143 -0
  204. package/dist/RegisteredFunction.d.ts.map +1 -0
  205. package/dist/RegisteredFunction.js +125 -0
  206. package/dist/RegisteredFunction.js.map +1 -0
  207. package/dist/RegisteredFunctions.d.ts +57 -0
  208. package/dist/RegisteredFunctions.d.ts.map +1 -0
  209. package/dist/RegisteredFunctions.js +32 -0
  210. package/dist/RegisteredFunctions.js.map +1 -0
  211. package/dist/RegisteredNodeFunction.d.ts +11 -0
  212. package/dist/RegisteredNodeFunction.d.ts.map +1 -0
  213. package/dist/RegisteredNodeFunction.js +45 -0
  214. package/dist/RegisteredNodeFunction.js.map +1 -0
  215. package/dist/Registry.d.ts +12 -0
  216. package/dist/Registry.d.ts.map +1 -0
  217. package/dist/Registry.js +17 -0
  218. package/dist/Registry.js.map +1 -0
  219. package/dist/RegistryItems.d.ts +21 -0
  220. package/dist/RegistryItems.d.ts.map +1 -0
  221. package/dist/RegistryItems.js +27 -0
  222. package/dist/RegistryItems.js.map +1 -0
  223. package/dist/RequestMetadata.d.ts +12 -0
  224. package/dist/RequestMetadata.d.ts.map +1 -0
  225. package/dist/RequestMetadata.js +16 -0
  226. package/dist/RequestMetadata.js.map +1 -0
  227. package/dist/ResolvedMiddleware.d.ts +24 -0
  228. package/dist/ResolvedMiddleware.d.ts.map +1 -0
  229. package/dist/ResolvedMiddleware.js +34 -0
  230. package/dist/ResolvedMiddleware.js.map +1 -0
  231. package/dist/Scheduler.d.ts +31 -0
  232. package/dist/Scheduler.d.ts.map +1 -0
  233. package/dist/Scheduler.js +35 -0
  234. package/dist/Scheduler.js.map +1 -0
  235. package/dist/Storage.d.ts +22 -0
  236. package/dist/Storage.d.ts.map +1 -0
  237. package/dist/Storage.js +27 -0
  238. package/dist/Storage.js.map +1 -0
  239. package/dist/StorageActionWriter.d.ts +35 -0
  240. package/dist/StorageActionWriter.d.ts.map +1 -0
  241. package/dist/StorageActionWriter.js +24 -0
  242. package/dist/StorageActionWriter.js.map +1 -0
  243. package/dist/StorageReader.d.ts +26 -0
  244. package/dist/StorageReader.d.ts.map +1 -0
  245. package/dist/StorageReader.js +22 -0
  246. package/dist/StorageReader.js.map +1 -0
  247. package/dist/StorageWriter.d.ts +29 -0
  248. package/dist/StorageWriter.d.ts.map +1 -0
  249. package/dist/StorageWriter.js +24 -0
  250. package/dist/StorageWriter.js.map +1 -0
  251. package/dist/Table.d.ts +274 -0
  252. package/dist/Table.d.ts.map +1 -0
  253. package/dist/Table.js +70 -0
  254. package/dist/Table.js.map +1 -0
  255. package/dist/TableInfo.d.ts +44 -0
  256. package/dist/TableInfo.d.ts.map +1 -0
  257. package/dist/TableInfo.js +7 -0
  258. package/dist/TableInfo.js.map +1 -0
  259. package/dist/TransactionMetadata.d.ts +12 -0
  260. package/dist/TransactionMetadata.d.ts.map +1 -0
  261. package/dist/TransactionMetadata.js +16 -0
  262. package/dist/TransactionMetadata.js.map +1 -0
  263. package/dist/VectorSearch.d.ts +23 -0
  264. package/dist/VectorSearch.d.ts.map +1 -0
  265. package/dist/VectorSearch.js +17 -0
  266. package/dist/VectorSearch.js.map +1 -0
  267. package/dist/_virtual/_rolldown/runtime.js +13 -0
  268. package/dist/index.d.ts +88 -0
  269. package/dist/index.d.ts.map +1 -0
  270. package/dist/index.js +61 -0
  271. package/dist/internal/AiGatewayDecisionClient.d.ts +7 -0
  272. package/dist/internal/AiGatewayDecisionClient.d.ts.map +1 -0
  273. package/dist/internal/AiGatewayDecisionClient.js +19 -0
  274. package/dist/internal/AiGatewayDecisionClient.js.map +1 -0
  275. package/dist/internal/AiGatewayLanguageClient.d.ts +7 -0
  276. package/dist/internal/AiGatewayLanguageClient.d.ts.map +1 -0
  277. package/dist/internal/AiGatewayLanguageClient.js +19 -0
  278. package/dist/internal/AiGatewayLanguageClient.js.map +1 -0
  279. package/dist/internal/AiGatewayServiceToken.d.ts +46 -0
  280. package/dist/internal/AiGatewayServiceToken.d.ts.map +1 -0
  281. package/dist/internal/AiGatewayServiceToken.js +62 -0
  282. package/dist/internal/AiGatewayServiceToken.js.map +1 -0
  283. package/dist/internal/constants.d.ts +2 -0
  284. package/dist/internal/constants.d.ts.map +1 -0
  285. package/dist/internal/constants.js +6 -0
  286. package/dist/internal/constants.js.map +1 -0
  287. package/dist/internal/utils.d.ts +13 -0
  288. package/dist/internal/utils.d.ts.map +1 -0
  289. package/dist/internal/utils.js +50 -0
  290. package/dist/internal/utils.js.map +1 -0
  291. package/dist/node.d.ts +2 -0
  292. package/dist/node.d.ts.map +1 -0
  293. package/dist/node.js +1 -0
  294. package/package.json +68 -3
  295. package/src/ActionCtx.ts +45 -0
  296. package/src/ActionRunner.ts +36 -0
  297. package/src/AiGatewayDecisionClient.ts +40 -0
  298. package/src/AiGatewayDecisionModel.ts +46 -0
  299. package/src/AiGatewayLanguageClient.ts +41 -0
  300. package/src/AiGatewayLanguageModel.ts +61 -0
  301. package/src/Auth.ts +51 -0
  302. package/src/BlobNotFoundError.ts +12 -0
  303. package/src/Callback.ts +313 -0
  304. package/src/ComponentCtx.ts +192 -0
  305. package/src/ConvexConfigProvider.ts +39 -0
  306. package/src/ConvexFunctionDefinitions.ts +91 -0
  307. package/src/ConvexLogger.ts +43 -0
  308. package/src/CronJob.ts +42 -0
  309. package/src/CronJobs.ts +165 -0
  310. package/src/DataModel.ts +81 -0
  311. package/src/DatabaseReader.ts +118 -0
  312. package/src/DatabaseSchema.ts +139 -0
  313. package/src/DatabaseWriter.ts +232 -0
  314. package/src/Document.ts +146 -0
  315. package/src/ExecutionMetadata.ts +26 -0
  316. package/src/FunctionImpl.ts +96 -0
  317. package/src/FunctionRegistryItem.ts +85 -0
  318. package/src/GroupImpl.ts +167 -0
  319. package/src/GroupRegistry.ts +41 -0
  320. package/src/Handler.ts +191 -0
  321. package/src/HttpRouter.ts +388 -0
  322. package/src/MiddlewareImpl.ts +247 -0
  323. package/src/MiddlewareRegistryItem.ts +21 -0
  324. package/src/MutationCtx.ts +45 -0
  325. package/src/MutationRunner.ts +66 -0
  326. package/src/MutationTransactionContext.ts +48 -0
  327. package/src/OrderedQuery.ts +136 -0
  328. package/src/QueryCtx.ts +45 -0
  329. package/src/QueryInitializer.ts +537 -0
  330. package/src/QueryRunner.ts +91 -0
  331. package/src/QueryStream.ts +2476 -0
  332. package/src/QueryStreamCursor.ts +99 -0
  333. package/src/QueryStreamIndexPrefix.ts +79 -0
  334. package/src/QueryStreamIndexRange.ts +489 -0
  335. package/src/QueryStreamKey.ts +118 -0
  336. package/src/QueryStreamKeyBounds.ts +395 -0
  337. package/src/QueryStreamKeyLabels.ts +56 -0
  338. package/src/QueryStreamKeyLayout.ts +382 -0
  339. package/src/QueryStreamKeyValues.ts +112 -0
  340. package/src/QueryStreamOrderDirection.ts +29 -0
  341. package/src/QueryStreamPagination.ts +357 -0
  342. package/src/QueryStreamReadBudget.ts +167 -0
  343. package/src/QueryTransactionContext.ts +37 -0
  344. package/src/RegisteredConvexFunction.ts +415 -0
  345. package/src/RegisteredFunction.ts +391 -0
  346. package/src/RegisteredFunctions.ts +88 -0
  347. package/src/RegisteredNodeFunction.ts +120 -0
  348. package/src/Registry.ts +17 -0
  349. package/src/RegistryItems.ts +40 -0
  350. package/src/RequestMetadata.ts +20 -0
  351. package/src/ResolvedMiddleware.ts +70 -0
  352. package/src/Scheduler.ts +85 -0
  353. package/src/Storage.ts +37 -0
  354. package/src/StorageActionWriter.ts +59 -0
  355. package/src/StorageReader.ts +59 -0
  356. package/src/StorageWriter.ts +58 -0
  357. package/src/Table.ts +156 -0
  358. package/src/TableInfo.ts +106 -0
  359. package/src/TransactionMetadata.ts +20 -0
  360. package/src/VectorSearch.ts +75 -0
  361. package/src/index.ts +87 -0
  362. package/src/internal/AiGatewayDecisionClient.ts +16 -0
  363. package/src/internal/AiGatewayLanguageClient.ts +16 -0
  364. package/src/internal/AiGatewayServiceToken.ts +129 -0
  365. package/src/internal/constants.ts +1 -0
  366. package/src/internal/utils.ts +89 -0
  367. package/src/node.ts +1 -0
@@ -0,0 +1,99 @@
1
+ import * as Array from "effect/Array";
2
+ import * as Effect from "effect/Effect";
3
+ import * as QueryStreamKey from "./QueryStreamKey.js";
4
+ import * as SchemaIssue from "effect/SchemaIssue";
5
+ import * as Match from "effect/Match";
6
+ import * as Schema from "effect/Schema";
7
+ import * as SchemaGetter from "effect/SchemaGetter";
8
+ import * as QueryStreamKeyLayout from "./QueryStreamKeyLayout.js";
9
+ import * as QueryStreamKeyValues from "./QueryStreamKeyValues.js";
10
+
11
+ // Serialized labels are a cursor boundary representation. They include every
12
+ // runtime position but do not preserve implicitness.
13
+ const RuntimeLabels = Schema.Array(Schema.String);
14
+ const RuntimeLabelsEquivalence = Schema.toEquivalence(RuntimeLabels);
15
+ const positionRuntimeLabel = Match.type<QueryStreamKeyLayout.Position>().pipe(
16
+ Match.tagsExhaustive({
17
+ Visible: ({ label }) => label,
18
+ ImplicitId: () => "_id",
19
+ }),
20
+ );
21
+
22
+ /**
23
+ * @experimental
24
+ */
25
+ export const QueryStreamCursor = Schema.Struct({
26
+ runtimeLabels: RuntimeLabels,
27
+ keyValues: QueryStreamKeyValues.QueryStreamKeyValues,
28
+ }).check(
29
+ Schema.makeFilter(
30
+ (cursor) => cursor.keyValues.length === cursor.runtimeLabels.length,
31
+ { message: "key values and runtime labels must have the same length" },
32
+ ),
33
+ );
34
+
35
+ /**
36
+ * @experimental
37
+ */
38
+ export interface QueryStreamCursor extends Schema.Schema.Type<
39
+ typeof QueryStreamCursor
40
+ > {}
41
+
42
+ /**
43
+ * @experimental
44
+ */
45
+ export const END_CURSOR = "[]";
46
+
47
+ /**
48
+ * Bind cursor string encoding and decoding to a layout.
49
+ *
50
+ * @experimental
51
+ */
52
+ export const fromKeyLayout = (
53
+ keyLayout: QueryStreamKeyLayout.QueryStreamKeyLayout,
54
+ ) => {
55
+ const runtimeLabels = Array.map(
56
+ QueryStreamKeyLayout.positions(keyLayout),
57
+ positionRuntimeLabel,
58
+ );
59
+ return Schema.fromJsonString(QueryStreamCursor)
60
+ .check(
61
+ Schema.makeFilter(
62
+ (cursor) =>
63
+ RuntimeLabelsEquivalence(cursor.runtimeLabels, runtimeLabels),
64
+ { message: "Cursor runtime labels do not match the stream" },
65
+ ),
66
+ )
67
+ .pipe(
68
+ Schema.decodeTo(
69
+ Schema.declare(QueryStreamKey.isComplete).check(
70
+ Schema.makeFilter(
71
+ (key) => QueryStreamKeyLayout.Equivalence(key.layout, keyLayout),
72
+ { message: "Cursor key does not belong to the stream layout" },
73
+ ),
74
+ ),
75
+ {
76
+ decode: SchemaGetter.transformEffect((cursor, options) =>
77
+ Effect.fromResult(
78
+ QueryStreamKey.complete(keyLayout, cursor.keyValues),
79
+ ).pipe(
80
+ Effect.mapError(
81
+ (error) =>
82
+ new SchemaIssue.InvalidValue(
83
+ { message: error.message },
84
+ cursor.keyValues,
85
+ options,
86
+ ),
87
+ ),
88
+ ),
89
+ ),
90
+ encode: SchemaGetter.transformEffect((key) =>
91
+ QueryStreamCursor.makeEffect({
92
+ runtimeLabels,
93
+ keyValues: key.values,
94
+ }),
95
+ ),
96
+ },
97
+ ),
98
+ );
99
+ };
@@ -0,0 +1,79 @@
1
+ import * as Array from "effect/Array";
2
+ import * as Data from "effect/Data";
3
+ import * as Result from "effect/Result";
4
+ import type * as QueryStreamKey from "./QueryStreamKey.js";
5
+ import type * as QueryStreamKeyValues from "./QueryStreamKeyValues.js";
6
+
7
+ const TypeId = "~@confect/server/QueryStreamIndexPrefix";
8
+
9
+ /**
10
+ * @experimental
11
+ */
12
+ export type IndexEntries = ReadonlyArray<
13
+ readonly [string, QueryStreamKeyValues.QueryStreamKeyValues[number]]
14
+ >;
15
+
16
+ /**
17
+ * Index coordinates retain the field path belonging to each value.
18
+ *
19
+ * @experimental
20
+ */
21
+ export interface QueryStreamIndexPrefix {
22
+ readonly [TypeId]: IndexEntries;
23
+ }
24
+
25
+ /**
26
+ * @experimental
27
+ */
28
+ export class IndexPrefixWidthMismatchError extends Data.TaggedError(
29
+ "IndexPrefixWidthMismatchError",
30
+ )<{
31
+ readonly width: number;
32
+ readonly actual: number;
33
+ }> {
34
+ override get message(): string {
35
+ return `Invalid index prefix key width (${this.actual}); expected at most ${this.width}`;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * @experimental
41
+ */
42
+ export const make = (
43
+ fieldPaths: ReadonlyArray<string>,
44
+ keyValues: QueryStreamKeyValues.QueryStreamKeyValues,
45
+ ): Result.Result<QueryStreamIndexPrefix, IndexPrefixWidthMismatchError> =>
46
+ keyValues.length <= fieldPaths.length
47
+ ? Result.succeed({ [TypeId]: Array.zip(fieldPaths, keyValues) })
48
+ : Result.fail(
49
+ new IndexPrefixWidthMismatchError({
50
+ width: fieldPaths.length,
51
+ actual: keyValues.length,
52
+ }),
53
+ );
54
+
55
+ /**
56
+ * @experimental
57
+ */
58
+ export const entries = (self: QueryStreamIndexPrefix): IndexEntries =>
59
+ self[TypeId];
60
+
61
+ /**
62
+ * @experimental
63
+ */
64
+ export const keyValues = (
65
+ self: QueryStreamIndexPrefix,
66
+ ): QueryStreamKeyValues.QueryStreamKeyValues =>
67
+ Array.map(entries(self), ([, value]) => value);
68
+
69
+ /**
70
+ * Restore equality values when crossing into index coordinates.
71
+ *
72
+ * @experimental
73
+ */
74
+ export const fromStreamKey = (
75
+ fieldPaths: ReadonlyArray<string>,
76
+ equalityKeyValues: QueryStreamKeyValues.QueryStreamKeyValues,
77
+ self: QueryStreamKey.QueryStreamKey,
78
+ ): Result.Result<QueryStreamIndexPrefix, IndexPrefixWidthMismatchError> =>
79
+ make(fieldPaths, Array.appendAll(equalityKeyValues, self.values));
@@ -0,0 +1,489 @@
1
+ import type {
2
+ GenericDocument,
3
+ FieldTypeFromFieldPath,
4
+ IndexRange as ConvexIndexRange,
5
+ IndexRangeBuilder as ConvexIndexRangeBuilder,
6
+ } from "convex/server";
7
+ import * as Array from "effect/Array";
8
+ import * as Data from "effect/Data";
9
+ import { identity, pipe } from "effect/Function";
10
+ import * as Match from "effect/Match";
11
+ import * as Option from "effect/Option";
12
+ import * as Result from "effect/Result";
13
+ import type * as Types from "effect/Types";
14
+ import * as QueryStreamIndexPrefix from "./QueryStreamIndexPrefix.js";
15
+ import * as QueryStreamKeyBounds from "./QueryStreamKeyBounds.js";
16
+ import * as QueryStreamKeyValues from "./QueryStreamKeyValues.js";
17
+ import type * as QueryStreamOrderDirection from "./QueryStreamOrderDirection.js";
18
+
19
+ type Head<FieldPaths extends ReadonlyArray<string>> =
20
+ FieldPaths extends readonly [infer H extends string, ...ReadonlyArray<string>]
21
+ ? H
22
+ : never;
23
+
24
+ type Tail<FieldPaths extends ReadonlyArray<string>> =
25
+ FieldPaths extends readonly [
26
+ string,
27
+ ...infer Rest extends ReadonlyArray<string>,
28
+ ]
29
+ ? Rest
30
+ : ReadonlyArray<string>;
31
+
32
+ // The range builder mirrors Convex's `IndexRangeBuilder`, but *consumes* the
33
+ // index-field tuple at the type level as `eq` pins field paths. The remaining
34
+ // tuple supplies the initial visible ordering labels of the resulting stream.
35
+
36
+ const TypeId = "~@confect/server/QueryStreamIndexRange";
37
+
38
+ interface Equality {
39
+ readonly fieldPath: string;
40
+ readonly value: QueryStreamKeyValues.KeyValue;
41
+ }
42
+
43
+ interface Endpoint {
44
+ readonly value: QueryStreamKeyValues.KeyValue;
45
+ readonly inclusive: boolean;
46
+ }
47
+
48
+ type Interval = Data.TaggedEnum<{
49
+ Lower: { readonly lower: Endpoint };
50
+ Upper: { readonly upper: Endpoint };
51
+ Between: { readonly lower: Endpoint; readonly upper: Endpoint };
52
+ }>;
53
+ const Interval = Data.taggedEnum<Interval>();
54
+
55
+ interface Constraints {
56
+ readonly equalities: ReadonlyArray<Equality>;
57
+ readonly bounded: Option.Option<{
58
+ readonly fieldPath: string;
59
+ readonly interval: Interval;
60
+ }>;
61
+ }
62
+
63
+ /**
64
+ * The equality prefix followed by at most one bounded field.
65
+ *
66
+ * @experimental
67
+ */
68
+ export interface QueryStreamIndexRange<
69
+ out RemainingFieldPaths extends ReadonlyArray<string> = ReadonlyArray<string>,
70
+ > {
71
+ readonly [TypeId]: Constraints & {
72
+ readonly _Remaining: Types.Covariant<RemainingFieldPaths>;
73
+ };
74
+ }
75
+
76
+ /**
77
+ * @experimental
78
+ */
79
+ export type Remaining<IndexRange> =
80
+ IndexRange extends QueryStreamIndexRange<infer RemainingFieldPaths>
81
+ ? RemainingFieldPaths
82
+ : never;
83
+
84
+ /**
85
+ * A typed index-range builder. `eq` must target the next unpinned index field,
86
+ * and consumes it; `gt`/`gte`/`lt`/`lte` bound the next field without consuming
87
+ * it (bounded field paths still vary within the range).
88
+ *
89
+ * @experimental
90
+ */
91
+ export interface Builder<
92
+ ConvexDoc extends GenericDocument,
93
+ FieldPaths extends ReadonlyArray<string>,
94
+ > extends QueryStreamIndexRange<FieldPaths> {
95
+ readonly eq: (
96
+ fieldPath: Head<FieldPaths>,
97
+ value: FieldTypeFromFieldPath<ConvexDoc, Head<FieldPaths>>,
98
+ ) => Builder<ConvexDoc, Tail<FieldPaths>>;
99
+ readonly gt: (
100
+ fieldPath: Head<FieldPaths>,
101
+ value: FieldTypeFromFieldPath<ConvexDoc, Head<FieldPaths>>,
102
+ ) => LowerBoundedBuilder<ConvexDoc, FieldPaths>;
103
+ readonly gte: (
104
+ fieldPath: Head<FieldPaths>,
105
+ value: FieldTypeFromFieldPath<ConvexDoc, Head<FieldPaths>>,
106
+ ) => LowerBoundedBuilder<ConvexDoc, FieldPaths>;
107
+ readonly lt: (
108
+ fieldPath: Head<FieldPaths>,
109
+ value: FieldTypeFromFieldPath<ConvexDoc, Head<FieldPaths>>,
110
+ ) => QueryStreamIndexRange<FieldPaths>;
111
+ readonly lte: (
112
+ fieldPath: Head<FieldPaths>,
113
+ value: FieldTypeFromFieldPath<ConvexDoc, Head<FieldPaths>>,
114
+ ) => QueryStreamIndexRange<FieldPaths>;
115
+ }
116
+
117
+ /**
118
+ * After `gt`/`gte`, only an upper bound on the same field may follow.
119
+ *
120
+ * @experimental
121
+ */
122
+ export interface LowerBoundedBuilder<
123
+ ConvexDoc extends GenericDocument,
124
+ FieldPaths extends ReadonlyArray<string>,
125
+ > extends QueryStreamIndexRange<FieldPaths> {
126
+ readonly lt: (
127
+ fieldPath: Head<FieldPaths>,
128
+ value: FieldTypeFromFieldPath<ConvexDoc, Head<FieldPaths>>,
129
+ ) => QueryStreamIndexRange<FieldPaths>;
130
+ readonly lte: (
131
+ fieldPath: Head<FieldPaths>,
132
+ value: FieldTypeFromFieldPath<ConvexDoc, Head<FieldPaths>>,
133
+ ) => QueryStreamIndexRange<FieldPaths>;
134
+ }
135
+
136
+ const make = (constraints: Constraints): QueryStreamIndexRange => ({
137
+ [TypeId]: {
138
+ ...constraints,
139
+ _Remaining: identity as Types.Covariant<ReadonlyArray<string>>,
140
+ },
141
+ });
142
+
143
+ const makeBuilder = (
144
+ equalities: ReadonlyArray<Equality>,
145
+ ): Builder<GenericDocument, ReadonlyArray<string>> => {
146
+ const upper =
147
+ (inclusive: boolean) =>
148
+ (fieldPath: string, value: QueryStreamKeyValues.KeyValue) =>
149
+ make({
150
+ equalities,
151
+ bounded: Option.some({
152
+ fieldPath,
153
+ interval: Interval.Upper({ upper: { value, inclusive } }),
154
+ }),
155
+ });
156
+ const lower =
157
+ (inclusive: boolean) =>
158
+ (
159
+ fieldPath: string,
160
+ value: QueryStreamKeyValues.KeyValue,
161
+ ): LowerBoundedBuilder<GenericDocument, ReadonlyArray<string>> => {
162
+ const endpoint = { value, inclusive };
163
+ const finish =
164
+ (upperInclusive: boolean) =>
165
+ (_fieldPath: string, upperValue: QueryStreamKeyValues.KeyValue) =>
166
+ make({
167
+ equalities,
168
+ bounded: Option.some({
169
+ fieldPath,
170
+ interval: Interval.Between({
171
+ lower: endpoint,
172
+ upper: { value: upperValue, inclusive: upperInclusive },
173
+ }),
174
+ }),
175
+ });
176
+ return {
177
+ ...make({
178
+ equalities,
179
+ bounded: Option.some({
180
+ fieldPath,
181
+ interval: Interval.Lower({ lower: endpoint }),
182
+ }),
183
+ }),
184
+ lt: finish(false),
185
+ lte: finish(true),
186
+ };
187
+ };
188
+ return {
189
+ ...make({ equalities, bounded: Option.none() }),
190
+ eq: (fieldPath, value) =>
191
+ makeBuilder(Array.append(equalities, { fieldPath, value })),
192
+ gt: lower(false),
193
+ gte: lower(true),
194
+ lt: upper(false),
195
+ lte: upper(true),
196
+ };
197
+ };
198
+
199
+ /**
200
+ * The initial builder handed to a range callback.
201
+ *
202
+ * @experimental
203
+ */
204
+ export const builder = <
205
+ ConvexDoc extends GenericDocument,
206
+ FieldPaths extends ReadonlyArray<string>,
207
+ >(): Builder<ConvexDoc, FieldPaths> =>
208
+ makeBuilder([]) as unknown as Builder<ConvexDoc, FieldPaths>;
209
+
210
+ /**
211
+ * Number of index fields pinned by equality constraints.
212
+ *
213
+ * @experimental
214
+ */
215
+ export const equalityPrefixLength = (self: QueryStreamIndexRange): number =>
216
+ self[TypeId].equalities.length;
217
+
218
+ interface ConvexUpperBoundBuilder extends ConvexIndexRange {
219
+ readonly lt: (
220
+ fieldPath: string,
221
+ value: QueryStreamKeyValues.KeyValue,
222
+ ) => ConvexIndexRange;
223
+ readonly lte: (
224
+ fieldPath: string,
225
+ value: QueryStreamKeyValues.KeyValue,
226
+ ) => ConvexIndexRange;
227
+ }
228
+
229
+ interface ConvexRangeBuilder extends ConvexUpperBoundBuilder {
230
+ readonly eq: (
231
+ fieldPath: string,
232
+ value: QueryStreamKeyValues.KeyValue,
233
+ ) => ConvexRangeBuilder;
234
+ readonly gt: (
235
+ fieldPath: string,
236
+ value: QueryStreamKeyValues.KeyValue,
237
+ ) => ConvexUpperBoundBuilder;
238
+ readonly gte: (
239
+ fieldPath: string,
240
+ value: QueryStreamKeyValues.KeyValue,
241
+ ) => ConvexUpperBoundBuilder;
242
+ }
243
+
244
+ /**
245
+ * Apply one range to Convex's index-range builder.
246
+ *
247
+ * @experimental
248
+ */
249
+ export const apply = (
250
+ self: QueryStreamIndexRange,
251
+ q: ConvexIndexRangeBuilder<GenericDocument, string[]>,
252
+ ): ConvexIndexRange => {
253
+ const { equalities, bounded } = self[TypeId];
254
+ // Convex tracks equality progress through a static field tuple. These paths
255
+ // are runtime data; the range model owns their ordering. Its runtime builder
256
+ // supports further equality calls, even when the SDK type has lost the tuple.
257
+ const prefix = Array.reduce(
258
+ equalities,
259
+ q as ConvexRangeBuilder,
260
+ (target, { fieldPath, value }) => target.eq(fieldPath, value),
261
+ );
262
+ return Option.match(bounded, {
263
+ onNone: () => prefix,
264
+ onSome: ({ fieldPath, interval }) => {
265
+ const lower = (
266
+ target: ConvexRangeBuilder,
267
+ endpoint: Endpoint,
268
+ ): ConvexUpperBoundBuilder =>
269
+ target[endpoint.inclusive ? "gte" : "gt"](fieldPath, endpoint.value);
270
+ const upper = (
271
+ target: ConvexUpperBoundBuilder,
272
+ endpoint: Endpoint,
273
+ ): ConvexIndexRange =>
274
+ target[endpoint.inclusive ? "lte" : "lt"](fieldPath, endpoint.value);
275
+ return Interval.$match(interval, {
276
+ Lower: ({ lower: endpoint }) => lower(prefix, endpoint),
277
+ Upper: ({ upper: endpoint }) => upper(prefix, endpoint),
278
+ Between: (endpoints) =>
279
+ upper(lower(prefix, endpoints.lower), endpoints.upper),
280
+ });
281
+ },
282
+ });
283
+ };
284
+
285
+ // Convex index ranges have the shape `eq(f1) … eq(fn), gt/gte(fm)?,
286
+ // lt/lte(fm)?`—every field path pinned except the last, which may carry two
287
+ // inequalities. An arbitrary range between two index keys therefore
288
+ // decomposes into a *sequence* of Convex-expressible ranges (the port of
289
+ // `convex-helpers`' `splitRange`): e.g. `(1, 2, 3) < key <= (1, 3, 2)` over
290
+ // field paths `(f1, f2, f3)` becomes
291
+ //
292
+ // 1. eq(f1, 1), eq(f2, 2), gt(f3, 3)
293
+ // 2. eq(f1, 1), gt(f2, 2), lt(f2, 3)
294
+ // 3. eq(f1, 1), eq(f2, 3), lte(f3, 2)
295
+
296
+ type BoundTag = "gt" | "gte" | "lt" | "lte";
297
+
298
+ class TaggedBound extends Data.Class<{
299
+ readonly indexEntries: QueryStreamIndexPrefix.IndexEntries;
300
+ readonly tag: BoundTag;
301
+ }> {}
302
+
303
+ /**
304
+ * Dropping a bound's last entry bounds the remaining prefix exclusively.
305
+ */
306
+ const excludePrefix = (tag: BoundTag): BoundTag =>
307
+ Match.value(tag).pipe(
308
+ Match.whenOr("gt", "gte", () => "gt" as const),
309
+ Match.whenOr("lt", "lte", () => "lt" as const),
310
+ Match.exhaustive,
311
+ );
312
+
313
+ /**
314
+ * Peel a bound down to the single entry that feeds the middle range.
315
+ */
316
+ const peelBound = (
317
+ indexEntries: QueryStreamIndexPrefix.IndexEntries,
318
+ tag: BoundTag,
319
+ ): {
320
+ readonly peeled: ReadonlyArray<TaggedBound>;
321
+ readonly final: TaggedBound;
322
+ } =>
323
+ indexEntries.length <= 1
324
+ ? { peeled: [], final: new TaggedBound({ indexEntries, tag }) }
325
+ : pipe(
326
+ peelBound(Array.dropRight(indexEntries, 1), excludePrefix(tag)),
327
+ ({ final, peeled }) => ({
328
+ peeled: Array.prepend(peeled, new TaggedBound({ indexEntries, tag })),
329
+ final,
330
+ }),
331
+ );
332
+
333
+ /**
334
+ * Pin every entry but the last, which gets the bound tag.
335
+ */
336
+ const rangeFor = (
337
+ prefix: ReadonlyArray<Equality>,
338
+ indexEntries: QueryStreamIndexPrefix.IndexEntries,
339
+ tag: BoundTag,
340
+ ): QueryStreamIndexRange =>
341
+ Option.match(Array.last(indexEntries), {
342
+ onNone: () => make({ equalities: prefix, bounded: Option.none() }),
343
+ onSome: ([fieldPath, value]) =>
344
+ make({
345
+ equalities: Array.appendAll(
346
+ prefix,
347
+ Array.map(Array.dropRight(indexEntries, 1), ([path, pinned]) => ({
348
+ fieldPath: path,
349
+ value: pinned,
350
+ })),
351
+ ),
352
+ bounded: Option.some({
353
+ fieldPath,
354
+ interval:
355
+ tag === "gt" || tag === "gte"
356
+ ? Interval.Lower({ lower: { value, inclusive: tag === "gte" } })
357
+ : Interval.Upper({ upper: { value, inclusive: tag === "lte" } }),
358
+ }),
359
+ }),
360
+ });
361
+
362
+ /**
363
+ * Decompose the range between `indexBounds.lower` and `indexBounds.upper` (over
364
+ * the complete index `fieldPaths`, `_id` tiebreaker included) into a sequence
365
+ * of Convex-expressible ranges, ordered for the given direction.
366
+ *
367
+ * @experimental
368
+ */
369
+ export const fromBounds = (
370
+ fieldPaths: ReadonlyArray<string>,
371
+ orderDirection: QueryStreamOrderDirection.QueryStreamOrderDirection,
372
+ indexBounds: QueryStreamKeyBounds.IndexBounds,
373
+ ): Result.Result<
374
+ ReadonlyArray<QueryStreamIndexRange>,
375
+ QueryStreamIndexPrefix.IndexPrefixWidthMismatchError
376
+ > =>
377
+ Result.gen(function* () {
378
+ const lowerIndexEntries = QueryStreamIndexPrefix.entries(
379
+ yield* QueryStreamIndexPrefix.make(
380
+ fieldPaths,
381
+ indexBounds.lower.keyValues,
382
+ ),
383
+ );
384
+ const upperIndexEntries = QueryStreamIndexPrefix.entries(
385
+ yield* QueryStreamIndexPrefix.make(
386
+ fieldPaths,
387
+ indexBounds.upper.keyValues,
388
+ ),
389
+ );
390
+ // Equal cuts are an empty range too: e.g. lower exclusive at `k` and
391
+ // upper inclusive at `k`—the half-open (k, k]—both cut at
392
+ // successor(k).
393
+ if (QueryStreamKeyBounds.isEmpty(indexBounds)) {
394
+ return [];
395
+ }
396
+
397
+ const commonLength = pipe(
398
+ Array.zip(indexBounds.lower.keyValues, indexBounds.upper.keyValues),
399
+ Array.takeWhile(
400
+ ([lowerValue, upperValue]) =>
401
+ QueryStreamKeyValues.ValueOrder(lowerValue, upperValue) === 0,
402
+ ),
403
+ Array.length,
404
+ );
405
+ const equalities = pipe(
406
+ Array.take(lowerIndexEntries, commonLength),
407
+ Array.map(([fieldPath, value]) => ({ fieldPath, value })),
408
+ );
409
+
410
+ const lower = peelBound(
411
+ Array.drop(lowerIndexEntries, commonLength),
412
+ indexBounds.lower.inclusive ? "gte" : "gt",
413
+ );
414
+ const upper = peelBound(
415
+ Array.drop(upperIndexEntries, commonLength),
416
+ indexBounds.upper.inclusive ? "lte" : "lt",
417
+ );
418
+
419
+ const startIndexRanges = Array.map(lower.peeled, ({ indexEntries, tag }) =>
420
+ rangeFor(equalities, indexEntries, tag),
421
+ );
422
+ const endIndexRanges = Array.reverse(
423
+ Array.map(upper.peeled, ({ indexEntries, tag }) =>
424
+ rangeFor(equalities, indexEntries, tag),
425
+ ),
426
+ );
427
+
428
+ const { indexEntries: lowerFinalIndexEntries, tag: lowerFinalTag } =
429
+ lower.final;
430
+ const { indexEntries: upperFinalIndexEntries, tag: upperFinalTag } =
431
+ upper.final;
432
+ const middleIndexRange =
433
+ Array.isReadonlyArrayNonEmpty(lowerFinalIndexEntries) &&
434
+ Array.isReadonlyArrayNonEmpty(upperFinalIndexEntries)
435
+ ? make({
436
+ equalities,
437
+ bounded: Option.some({
438
+ fieldPath: Array.headNonEmpty(lowerFinalIndexEntries)[0],
439
+ interval: Interval.Between({
440
+ lower: {
441
+ value: Array.headNonEmpty(lowerFinalIndexEntries)[1],
442
+ inclusive: lowerFinalTag === "gte",
443
+ },
444
+ upper: {
445
+ value: Array.headNonEmpty(upperFinalIndexEntries)[1],
446
+ inclusive: upperFinalTag === "lte",
447
+ },
448
+ }),
449
+ }),
450
+ })
451
+ : Array.isReadonlyArrayNonEmpty(lowerFinalIndexEntries)
452
+ ? rangeFor(equalities, lowerFinalIndexEntries, lowerFinalTag)
453
+ : rangeFor(equalities, upperFinalIndexEntries, upperFinalTag);
454
+
455
+ const indexRanges = Array.appendAll(
456
+ Array.appendAll(startIndexRanges, Array.of(middleIndexRange)),
457
+ endIndexRanges,
458
+ );
459
+ return orderDirection === "desc" ? Array.reverse(indexRanges) : indexRanges;
460
+ });
461
+
462
+ /**
463
+ * Derive full-index bounds directly from the structural range.
464
+ *
465
+ * @experimental
466
+ */
467
+ export const toBounds = (
468
+ self: QueryStreamIndexRange,
469
+ ): QueryStreamKeyBounds.IndexBounds => {
470
+ const { equalities, bounded } = self[TypeId];
471
+ const keyValues = Array.map(equalities, (equality) => equality.value);
472
+ const unbounded = { keyValues, inclusive: true };
473
+ const endpoint = ({ value, inclusive }: Endpoint) => ({
474
+ keyValues: Array.append(keyValues, value),
475
+ inclusive,
476
+ });
477
+ return Option.match(bounded, {
478
+ onNone: () => ({ lower: unbounded, upper: unbounded }),
479
+ onSome: ({ interval }) =>
480
+ Interval.$match(interval, {
481
+ Lower: ({ lower }) => ({ lower: endpoint(lower), upper: unbounded }),
482
+ Upper: ({ upper }) => ({ lower: unbounded, upper: endpoint(upper) }),
483
+ Between: ({ lower, upper }) => ({
484
+ lower: endpoint(lower),
485
+ upper: endpoint(upper),
486
+ }),
487
+ }),
488
+ });
489
+ };