@gaganref/confect-server 0.0.0-stage → 10.3.1-fork.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.
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,357 @@
1
+ import * as Chunk from "effect/Chunk";
2
+ import * as Data from "effect/Data";
3
+ import * as Match from "effect/Match";
4
+ import * as Option from "effect/Option";
5
+ import * as Result from "effect/Result";
6
+ import * as Schema from "effect/Schema";
7
+ import type * as QueryStreamKey from "./QueryStreamKey";
8
+ import * as QueryStreamKeyValues from "./QueryStreamKeyValues";
9
+
10
+ const PageSize = Schema.Natural.pipe(
11
+ Schema.brand("~@confect/server/QueryStreamPagination/PageSize"),
12
+ );
13
+ type PageSize = typeof PageSize.Type;
14
+
15
+ /**
16
+ * @experimental
17
+ */
18
+ export class InvalidPageSizeError extends Data.TaggedError(
19
+ "InvalidPageSizeError",
20
+ )<{
21
+ readonly numItems: number;
22
+ }> {
23
+ override get message(): string {
24
+ return `QueryStream.paginate: numItems must be a nonnegative integer (received ${this.numItems})`;
25
+ }
26
+ }
27
+
28
+ /**
29
+ * @experimental
30
+ */
31
+ export class EmptyInitialPageError extends Data.TaggedError(
32
+ "EmptyInitialPageError",
33
+ ) {
34
+ override get message(): string {
35
+ return "QueryStream.paginate: numItems of 0 with a null cursor is not supported";
36
+ }
37
+ }
38
+
39
+ /**
40
+ * @experimental
41
+ */
42
+ export type Range = Data.TaggedEnum<{
43
+ Unpinned: {};
44
+ ThroughKey: { readonly key: QueryStreamKey.Complete };
45
+ ThroughEnd: {};
46
+ }>;
47
+ /**
48
+ * @experimental
49
+ */
50
+ export const Range = Data.taggedEnum<Range>();
51
+
52
+ /**
53
+ * @experimental
54
+ */
55
+ export type Start = Data.TaggedEnum<{
56
+ Beginning: {};
57
+ After: {
58
+ readonly key: QueryStreamKey.Complete;
59
+ readonly cursor: string;
60
+ };
61
+ }>;
62
+ /**
63
+ * @experimental
64
+ */
65
+ export const Start = Data.taggedEnum<Start>();
66
+
67
+ /**
68
+ * @experimental
69
+ */
70
+ export interface ScanRequest {
71
+ readonly numItems: PageSize;
72
+ readonly after: Option.Option<QueryStreamKey.Complete>;
73
+ readonly range: Range;
74
+ }
75
+
76
+ /**
77
+ * @experimental
78
+ */
79
+ export type Request = Data.TaggedEnum<{
80
+ Unchanged: { readonly cursor: string };
81
+ Scan: ScanRequest;
82
+ }>;
83
+ const Request = Data.taggedEnum<Request>();
84
+
85
+ /**
86
+ * @experimental
87
+ */
88
+ export const parseRequest = (
89
+ numItems: number,
90
+ start: Start,
91
+ range: Range,
92
+ ): Result.Result<Request, InvalidPageSizeError | EmptyInitialPageError> =>
93
+ Result.flatMap(
94
+ Schema.decodeResult(PageSize)(numItems).pipe(
95
+ Result.mapError(() => new InvalidPageSizeError({ numItems })),
96
+ ),
97
+ (size): Result.Result<Request, EmptyInitialPageError> =>
98
+ size === 0
99
+ ? Start.$match(start, {
100
+ Beginning: () => Result.fail(new EmptyInitialPageError()),
101
+ After: ({ cursor }) =>
102
+ Result.succeed(Request.Unchanged({ cursor })),
103
+ })
104
+ : Result.succeed(
105
+ Request.Scan({
106
+ numItems: size,
107
+ after: Start.$match(start, {
108
+ Beginning: () => Option.none(),
109
+ After: ({ key }) => Option.some(key),
110
+ }),
111
+ range,
112
+ }),
113
+ ),
114
+ );
115
+
116
+ /**
117
+ * A nonempty scan, including filtered markers.
118
+ */
119
+ type Progress = Chunk.NonEmptyChunk<QueryStreamKey.Complete>;
120
+ const append = (
121
+ progress: Option.Option<Progress>,
122
+ key: QueryStreamKey.Complete,
123
+ ): Progress =>
124
+ Option.match(progress, {
125
+ onNone: () => Chunk.of(key),
126
+ onSome: (keys) => Chunk.append(keys, key),
127
+ });
128
+ const midpoint = (progress: Progress): QueryStreamKey.Complete =>
129
+ Option.getOrElse(
130
+ Chunk.get(progress, Math.floor((Chunk.size(progress) - 1) / 2)),
131
+ () => Chunk.headNonEmpty(progress),
132
+ );
133
+
134
+ interface Stopped<Doc> {
135
+ readonly page: Chunk.Chunk<Doc>;
136
+ readonly progress: Progress;
137
+ }
138
+
139
+ /**
140
+ * @experimental
141
+ */
142
+ export type QueryStreamPagination<Doc> = Data.TaggedEnum<{
143
+ Reading: {
144
+ readonly page: Chunk.Chunk<Doc>;
145
+ readonly progress: Option.Option<Progress>;
146
+ };
147
+ ItemLimit: Stopped<Doc>;
148
+ ReadLimit: Stopped<Doc>;
149
+ }>;
150
+ interface PaginationDefinition extends Data.TaggedEnum.WithGenerics<1> {
151
+ readonly taggedEnum: QueryStreamPagination<this["A"]>;
152
+ }
153
+ const QueryStreamPagination = Data.taggedEnum<PaginationDefinition>();
154
+
155
+ /**
156
+ * @experimental
157
+ */
158
+ export const initial = <Doc>(): QueryStreamPagination<Doc> =>
159
+ QueryStreamPagination.Reading({
160
+ page: Chunk.empty<Doc>(),
161
+ progress: Option.none(),
162
+ });
163
+
164
+ /**
165
+ * @experimental
166
+ */
167
+ export const record = <Doc>(
168
+ request: ScanRequest,
169
+ self: QueryStreamPagination<Doc>,
170
+ doc: Option.Option<Doc>,
171
+ key: QueryStreamKey.Complete,
172
+ readLimit: boolean,
173
+ ): QueryStreamPagination<Doc> =>
174
+ Match.value(self).pipe(
175
+ Match.tagsExhaustive({
176
+ Reading: (reading) => {
177
+ const progress = append(reading.progress, key);
178
+ const page = Option.match(doc, {
179
+ onNone: () => reading.page,
180
+ onSome: (value) => Chunk.append(reading.page, value),
181
+ });
182
+ const continueReading = () =>
183
+ QueryStreamPagination.Reading({
184
+ page,
185
+ progress: Option.some(progress),
186
+ });
187
+ return readLimit
188
+ ? QueryStreamPagination.ReadLimit({ page, progress })
189
+ : Range.$match(request.range, {
190
+ Unpinned: () =>
191
+ Chunk.size(page) >= request.numItems
192
+ ? QueryStreamPagination.ItemLimit({ page, progress })
193
+ : continueReading(),
194
+ ThroughKey: continueReading,
195
+ ThroughEnd: continueReading,
196
+ });
197
+ },
198
+ ItemLimit: () => self,
199
+ ReadLimit: () => self,
200
+ }),
201
+ );
202
+
203
+ /**
204
+ * @experimental
205
+ */
206
+ export type Continuation = Data.TaggedEnum<{
207
+ End: {};
208
+ Key: { readonly key: QueryStreamKey.Complete };
209
+ }>;
210
+ const Continuation = Data.taggedEnum<Continuation>();
211
+
212
+ interface Split<Doc> {
213
+ readonly page: ReadonlyArray<Doc>;
214
+ readonly continuation: Continuation;
215
+ readonly splitKey: QueryStreamKey.Complete;
216
+ }
217
+
218
+ /**
219
+ * @experimental
220
+ */
221
+ export type Outcome<Doc> = Data.TaggedEnum<{
222
+ Done: { readonly page: ReadonlyArray<Doc> };
223
+ Continue: {
224
+ readonly page: ReadonlyArray<Doc>;
225
+ readonly key: QueryStreamKey.Complete;
226
+ };
227
+ SplitRequired: Split<Doc>;
228
+ SplitRecommended: Split<Doc>;
229
+ }>;
230
+
231
+ /**
232
+ * @experimental
233
+ */
234
+ export class UnsafePageBoundaryError extends Data.TaggedError(
235
+ "UnsafePageBoundaryError",
236
+ )<{
237
+ readonly reason: "NoProgress" | "NoInteriorSplit";
238
+ }> {
239
+ override get message(): string {
240
+ return Match.value(this.reason).pipe(
241
+ Match.when(
242
+ "NoProgress",
243
+ () => "The read budget stopped the page before any key was scanned",
244
+ ),
245
+ Match.when(
246
+ "NoInteriorSplit",
247
+ () => "The read budget stopped the page without an interior split key",
248
+ ),
249
+ Match.exhaustive,
250
+ );
251
+ }
252
+ }
253
+
254
+ const SOFT_MAX_SCAN_LENGTH = 16000;
255
+
256
+ /**
257
+ * Decide the page result without reading a stream or serializing a cursor.
258
+ *
259
+ * @experimental
260
+ */
261
+ export const finish = <Doc>(
262
+ request: ScanRequest,
263
+ self: QueryStreamPagination<Doc>,
264
+ upstreamStopped: boolean,
265
+ ): Result.Result<Outcome<Doc>, UnsafePageBoundaryError> => {
266
+ const page = Chunk.toArray(self.page);
267
+ const stopped = (
268
+ progress: Option.Option<Progress>,
269
+ readLimit: boolean,
270
+ ): Result.Result<Outcome<Doc>, UnsafePageBoundaryError> =>
271
+ Result.flatMap(
272
+ Result.fromOption(
273
+ progress,
274
+ () => new UnsafePageBoundaryError({ reason: "NoProgress" }),
275
+ ),
276
+ (scanned): Result.Result<Outcome<Doc>, UnsafePageBoundaryError> => {
277
+ const splitKey = midpoint(scanned);
278
+ const atEnd = Range.$match(request.range, {
279
+ Unpinned: () => false,
280
+ ThroughEnd: () => false,
281
+ ThroughKey: ({ key }) =>
282
+ QueryStreamKeyValues.Order("asc")(splitKey.values, key.values) ===
283
+ 0,
284
+ });
285
+ if (readLimit && atEnd) {
286
+ return Result.fail(
287
+ new UnsafePageBoundaryError({ reason: "NoInteriorSplit" }),
288
+ );
289
+ }
290
+ const key = Chunk.lastNonEmpty(scanned);
291
+ if (readLimit)
292
+ return Result.succeed({
293
+ _tag: "SplitRequired",
294
+ page,
295
+ continuation: Continuation.Key({ key }),
296
+ splitKey,
297
+ });
298
+ return Result.succeed(
299
+ Chunk.size(scanned) >= SOFT_MAX_SCAN_LENGTH
300
+ ? {
301
+ _tag: "SplitRecommended",
302
+ page,
303
+ continuation: Continuation.Key({ key }),
304
+ splitKey,
305
+ }
306
+ : { _tag: "Continue", page, key },
307
+ );
308
+ },
309
+ );
310
+ const exhausted = (progress: Option.Option<Progress>): Outcome<Doc> => {
311
+ const finishRange = (
312
+ continuation: Continuation,
313
+ pinned: boolean,
314
+ ): Outcome<Doc> => {
315
+ const split = Option.filter(
316
+ progress,
317
+ (scanned) =>
318
+ pinned &&
319
+ (Chunk.size(scanned) >= SOFT_MAX_SCAN_LENGTH ||
320
+ page.length > request.numItems + 1),
321
+ );
322
+ return Option.match(split, {
323
+ onSome: (scanned): Outcome<Doc> => ({
324
+ _tag: "SplitRecommended",
325
+ page,
326
+ continuation,
327
+ splitKey: midpoint(scanned),
328
+ }),
329
+ onNone: () =>
330
+ Continuation.$match(continuation, {
331
+ End: (): Outcome<Doc> => ({ _tag: "Done", page }),
332
+ Key: ({ key }): Outcome<Doc> => ({
333
+ _tag: "Continue",
334
+ page,
335
+ key,
336
+ }),
337
+ }),
338
+ });
339
+ };
340
+ return Range.$match(request.range, {
341
+ Unpinned: () => finishRange(Continuation.End(), false),
342
+ ThroughEnd: () => finishRange(Continuation.End(), true),
343
+ ThroughKey: ({ key }) => finishRange(Continuation.Key({ key }), true),
344
+ });
345
+ };
346
+ return Match.value(self).pipe(
347
+ Match.tagsExhaustive({
348
+ Reading: ({ progress }) =>
349
+ upstreamStopped
350
+ ? stopped(progress, true)
351
+ : Result.succeed(exhausted(progress)),
352
+ ItemLimit: ({ progress }) =>
353
+ stopped(Option.some(progress), upstreamStopped),
354
+ ReadLimit: ({ progress }) => stopped(Option.some(progress), true),
355
+ }),
356
+ );
357
+ };
@@ -0,0 +1,167 @@
1
+ import type { GenericDocument } from "convex/server";
2
+ import { getDocumentSize } from "convex/values";
3
+ import * as Array from "effect/Array";
4
+ import * as Cause from "effect/Cause";
5
+ import * as Context from "effect/Context";
6
+ import * as Data from "effect/Data";
7
+ import * as Effect from "effect/Effect";
8
+ import * as Option from "effect/Option";
9
+ import type * as Pull from "effect/Pull";
10
+ import * as Schema from "effect/Schema";
11
+ import * as Stream from "effect/Stream";
12
+ import * as SynchronizedRef from "effect/SynchronizedRef";
13
+ import * as Tuple from "effect/Tuple";
14
+
15
+ /**
16
+ * @experimental
17
+ */
18
+ export interface QueryStreamReadBudget {
19
+ readonly isUnlimited: Effect.Effect<boolean>;
20
+ readonly isStopped: Effect.Effect<boolean>;
21
+ readonly isExhausted: Effect.Effect<boolean>;
22
+ readonly getReadCounts: Effect.Effect<ReadCounts>;
23
+ /**
24
+ * Returns a stream that records reads against this budget and stops
25
+ * requesting further batches once exhausted. Apply directly to the document
26
+ * source before buffering, filtering, or combining its output.
27
+ */
28
+ readonly accountFor: (
29
+ encodedDocuments: Stream.Stream<unknown>,
30
+ ) => Stream.Stream<unknown>;
31
+ }
32
+
33
+ const ReadLimit = Schema.Natural.pipe(
34
+ Schema.brand("~@confect/server/QueryStreamReadBudget/ReadLimit"),
35
+ );
36
+
37
+ /**
38
+ * @experimental
39
+ */
40
+ export const Limits = Schema.Struct({
41
+ maximumRowsRead: Schema.OptionFromOptionalKey(ReadLimit),
42
+ maximumBytesRead: Schema.OptionFromOptionalKey(ReadLimit),
43
+ });
44
+ /**
45
+ * @experimental
46
+ */
47
+ export type Limits = typeof Limits.Type;
48
+
49
+ /**
50
+ * @experimental
51
+ */
52
+ export class InvalidReadLimitError extends Data.TaggedError(
53
+ "InvalidReadLimitError",
54
+ )<{
55
+ readonly cause: Schema.SchemaError;
56
+ }> {
57
+ override get message(): string {
58
+ return `Invalid read limits: ${this.cause.message}`;
59
+ }
60
+ }
61
+
62
+ /**
63
+ * @experimental
64
+ */
65
+ export interface ReadCounts {
66
+ readonly rowsRead: number;
67
+ readonly bytesRead: number;
68
+ }
69
+
70
+ type State = Data.TaggedEnum<{
71
+ Active: ReadCounts;
72
+ Stopped: ReadCounts;
73
+ }>;
74
+
75
+ const State = Data.taggedEnum<State>();
76
+
77
+ /**
78
+ * @experimental
79
+ */
80
+ export const QueryStreamReadBudget = Context.Service<QueryStreamReadBudget>(
81
+ "@confect/server/QueryStreamReadBudget",
82
+ );
83
+
84
+ const isExhausted = (state: State, limits: Limits): boolean =>
85
+ State.$match(state, {
86
+ Stopped: () => true,
87
+ Active: ({ rowsRead, bytesRead }) =>
88
+ Option.exists(limits.maximumRowsRead, (limit) => rowsRead >= limit) ||
89
+ Option.exists(limits.maximumBytesRead, (limit) => bytesRead >= limit),
90
+ });
91
+
92
+ const readCounts = ({ rowsRead, bytesRead }: ReadCounts): ReadCounts => ({
93
+ rowsRead,
94
+ bytesRead,
95
+ });
96
+
97
+ const record = (
98
+ counts: ReadCounts,
99
+ documents: Array.NonEmptyReadonlyArray<unknown>,
100
+ ): ReadCounts => ({
101
+ rowsRead: counts.rowsRead + documents.length,
102
+ bytesRead: Array.reduce(
103
+ documents,
104
+ counts.bytesRead,
105
+ (bytes, document) => bytes + getDocumentSize(document as GenericDocument),
106
+ ),
107
+ });
108
+
109
+ /**
110
+ * @experimental
111
+ */
112
+ export const make = Effect.fnUntraced(function* (
113
+ limits: Limits,
114
+ ): Effect.fn.Return<QueryStreamReadBudget> {
115
+ const unlimited =
116
+ Option.isNone(limits.maximumRowsRead) &&
117
+ Option.isNone(limits.maximumBytesRead);
118
+ const stateRef = yield* SynchronizedRef.make<State>(
119
+ State.Active({ rowsRead: 0, bytesRead: 0 }),
120
+ );
121
+ const accountForPull: (
122
+ pull: Pull.Pull<Array.NonEmptyReadonlyArray<unknown>>,
123
+ ) => Pull.Pull<Array.NonEmptyReadonlyArray<unknown>> = unlimited
124
+ ? (pull) =>
125
+ Effect.uninterruptibleMask((restore) =>
126
+ Effect.tap(restore(pull), (documents) =>
127
+ SynchronizedRef.update(stateRef, (state) =>
128
+ State.Active(record(state, documents)),
129
+ ),
130
+ ),
131
+ )
132
+ : (pull) =>
133
+ SynchronizedRef.modifyEffect(stateRef, (state) =>
134
+ Effect.gen(function* () {
135
+ if (isExhausted(state, limits)) {
136
+ return Tuple.make(
137
+ Option.none(),
138
+ State.Stopped(readCounts(state)),
139
+ );
140
+ }
141
+ const documents = yield* pull;
142
+ return Tuple.make(
143
+ Option.some(documents),
144
+ State.Active(record(state, documents)),
145
+ );
146
+ }),
147
+ ).pipe(
148
+ Effect.flatMap(
149
+ Option.match({
150
+ onNone: () => Cause.done(),
151
+ onSome: Effect.succeed,
152
+ }),
153
+ ),
154
+ );
155
+ return QueryStreamReadBudget.of({
156
+ isUnlimited: Effect.succeed(unlimited),
157
+ isStopped: Effect.map(SynchronizedRef.get(stateRef), State.$is("Stopped")),
158
+ isExhausted: Effect.map(SynchronizedRef.get(stateRef), (state) =>
159
+ isExhausted(state, limits),
160
+ ),
161
+ getReadCounts: Effect.map(SynchronizedRef.get(stateRef), readCounts),
162
+ accountFor: (encodedDocuments) =>
163
+ Stream.transformPull(encodedDocuments, (pull) =>
164
+ Effect.succeed(accountForPull(pull)),
165
+ ).pipe(Stream.scoped),
166
+ });
167
+ });
@@ -0,0 +1,37 @@
1
+ import * as Ref from "@confect/core/Ref";
2
+ import type {
3
+ GenericDataModel,
4
+ GenericQueryCtx,
5
+ TransactionLimits,
6
+ } from "convex/server";
7
+ import * as Context from "effect/Context";
8
+ import * as Effect from "effect/Effect";
9
+ import * as Layer from "effect/Layer";
10
+
11
+ export type { TransactionLimits } from "convex/server";
12
+
13
+ export interface Options {
14
+ readonly transactionLimits?: TransactionLimits;
15
+ }
16
+
17
+ const make = (ctx: Pick<GenericQueryCtx<GenericDataModel>, "runQuery">) => ({
18
+ runQuery: Effect.fn("QueryTransactionContext.runQuery")(
19
+ <Query extends Ref.AnyQuery>(
20
+ query: Query,
21
+ args: Ref.Args<Query>,
22
+ options: Options,
23
+ ) =>
24
+ Ref.runWithCodec(query, args, (ref, encodedArgs) =>
25
+ ctx.runQuery(ref, encodedArgs, options),
26
+ ),
27
+ ),
28
+ });
29
+
30
+ export class QueryTransactionContext extends Context.Service<
31
+ QueryTransactionContext,
32
+ ReturnType<typeof make>
33
+ >()("@confect/server/QueryTransactionContext") {}
34
+
35
+ export const layer = (
36
+ ctx: Pick<GenericQueryCtx<GenericDataModel>, "runQuery">,
37
+ ) => Layer.succeed(QueryTransactionContext, make(ctx));