@gaganref/confect-server 10.3.1-fork.4 → 10.3.1-fork.41

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 (279) hide show
  1. package/dist/ActionCall.d.ts +30 -0
  2. package/dist/ActionCall.d.ts.map +1 -0
  3. package/dist/ActionCall.js +41 -0
  4. package/dist/ActionCall.js.map +1 -0
  5. package/dist/ActionCtx.d.ts +1 -1
  6. package/dist/ActionCtx.d.ts.map +1 -1
  7. package/dist/ActionCtx.js.map +1 -1
  8. package/dist/ActionRunner.js +2 -2
  9. package/dist/AiGatewayDecisionClient.d.ts +2 -2
  10. package/dist/AiGatewayDecisionClient.d.ts.map +1 -1
  11. package/dist/AiGatewayDecisionClient.js +1 -1
  12. package/dist/AiGatewayDecisionClient.js.map +1 -1
  13. package/dist/AiGatewayLanguageClient.d.ts +2 -2
  14. package/dist/AiGatewayLanguageClient.d.ts.map +1 -1
  15. package/dist/AiGatewayLanguageClient.js +1 -1
  16. package/dist/AiGatewayLanguageClient.js.map +1 -1
  17. package/dist/Auth.d.ts +14 -2
  18. package/dist/Auth.d.ts.map +1 -1
  19. package/dist/Auth.js +13 -3
  20. package/dist/Auth.js.map +1 -1
  21. package/dist/Callback.js +3 -3
  22. package/dist/ComponentCtx.d.ts +1 -1
  23. package/dist/ComponentCtx.d.ts.map +1 -1
  24. package/dist/ConvexConfigProvider.js +2 -2
  25. package/dist/ConvexFunctionDefinitions.d.ts +4 -4
  26. package/dist/ConvexFunctionDefinitions.d.ts.map +1 -1
  27. package/dist/ConvexFunctionDefinitions.js +4 -4
  28. package/dist/ConvexFunctionDefinitions.js.map +1 -1
  29. package/dist/ConvexLogger.js +1 -1
  30. package/dist/CronJobs.d.ts +1 -1
  31. package/dist/CronJobs.d.ts.map +1 -1
  32. package/dist/CronJobs.js +6 -6
  33. package/dist/CronJobs.js.map +1 -1
  34. package/dist/DataModel.d.ts +3 -3
  35. package/dist/DataModel.d.ts.map +1 -1
  36. package/dist/DataModel.js.map +1 -1
  37. package/dist/DatabaseReader.d.ts +4 -4
  38. package/dist/DatabaseReader.d.ts.map +1 -1
  39. package/dist/DatabaseReader.js.map +1 -1
  40. package/dist/DatabaseSchema.d.ts +1 -1
  41. package/dist/DatabaseSchema.d.ts.map +1 -1
  42. package/dist/DatabaseSchema.js +2 -2
  43. package/dist/DatabaseSchema.js.map +1 -1
  44. package/dist/DatabaseWriter.d.ts +41 -7
  45. package/dist/DatabaseWriter.d.ts.map +1 -1
  46. package/dist/DatabaseWriter.js +55 -8
  47. package/dist/DatabaseWriter.js.map +1 -1
  48. package/dist/Document.d.ts +4 -4
  49. package/dist/Document.d.ts.map +1 -1
  50. package/dist/Document.js.map +1 -1
  51. package/dist/ExecutionMetadata.js +1 -1
  52. package/dist/FunctionImpl.d.ts +2 -2
  53. package/dist/FunctionImpl.d.ts.map +1 -1
  54. package/dist/FunctionImpl.js +2 -2
  55. package/dist/FunctionImpl.js.map +1 -1
  56. package/dist/FunctionRegistryItem.d.ts +1 -1
  57. package/dist/FunctionRegistryItem.d.ts.map +1 -1
  58. package/dist/FunctionRegistryItem.js +1 -1
  59. package/dist/FunctionRegistryItem.js.map +1 -1
  60. package/dist/GroupImpl.d.ts +24 -5
  61. package/dist/GroupImpl.d.ts.map +1 -1
  62. package/dist/GroupImpl.js +21 -22
  63. package/dist/GroupImpl.js.map +1 -1
  64. package/dist/GroupRegistry.d.ts +3 -2
  65. package/dist/GroupRegistry.d.ts.map +1 -1
  66. package/dist/GroupRegistry.js +10 -3
  67. package/dist/GroupRegistry.js.map +1 -1
  68. package/dist/Handler.d.ts +31 -27
  69. package/dist/Handler.d.ts.map +1 -1
  70. package/dist/Handler.js.map +1 -1
  71. package/dist/HttpRouter.d.ts +15 -13
  72. package/dist/HttpRouter.d.ts.map +1 -1
  73. package/dist/HttpRouter.js +16 -7
  74. package/dist/HttpRouter.js.map +1 -1
  75. package/dist/MiddlewareImpl.d.ts +14 -14
  76. package/dist/MiddlewareImpl.d.ts.map +1 -1
  77. package/dist/MiddlewareImpl.js +1 -1
  78. package/dist/MiddlewareImpl.js.map +1 -1
  79. package/dist/MutationCtx.d.ts +1 -1
  80. package/dist/MutationCtx.d.ts.map +1 -1
  81. package/dist/MutationCtx.js.map +1 -1
  82. package/dist/MutationRunner.d.ts +1 -1
  83. package/dist/MutationRunner.d.ts.map +1 -1
  84. package/dist/MutationRunner.js +2 -2
  85. package/dist/MutationRunner.js.map +1 -1
  86. package/dist/MutationTransactionContext.d.ts +2 -2
  87. package/dist/MutationTransactionContext.d.ts.map +1 -1
  88. package/dist/MutationTransactionContext.js +2 -2
  89. package/dist/MutationTransactionContext.js.map +1 -1
  90. package/dist/OfficialComponent.d.ts +50 -0
  91. package/dist/OfficialComponent.d.ts.map +1 -0
  92. package/dist/OfficialComponent.js +70 -0
  93. package/dist/OfficialComponent.js.map +1 -0
  94. package/dist/OrderedQuery.d.ts +4 -4
  95. package/dist/OrderedQuery.d.ts.map +1 -1
  96. package/dist/OrderedQuery.js.map +1 -1
  97. package/dist/QueryCtx.d.ts +1 -1
  98. package/dist/QueryCtx.d.ts.map +1 -1
  99. package/dist/QueryCtx.js.map +1 -1
  100. package/dist/QueryInitializer.d.ts +10 -10
  101. package/dist/QueryInitializer.d.ts.map +1 -1
  102. package/dist/QueryInitializer.js +2 -2
  103. package/dist/QueryInitializer.js.map +1 -1
  104. package/dist/QueryRunner.d.ts +2 -2
  105. package/dist/QueryRunner.d.ts.map +1 -1
  106. package/dist/QueryRunner.js +2 -2
  107. package/dist/QueryRunner.js.map +1 -1
  108. package/dist/QueryStream.d.ts +131 -23
  109. package/dist/QueryStream.d.ts.map +1 -1
  110. package/dist/QueryStream.js +142 -40
  111. package/dist/QueryStream.js.map +1 -1
  112. package/dist/QueryStreamCursor.d.ts +2 -2
  113. package/dist/QueryStreamCursor.d.ts.map +1 -1
  114. package/dist/QueryStreamCursor.js +1 -1
  115. package/dist/QueryStreamCursor.js.map +1 -1
  116. package/dist/QueryStreamIndexPrefix.d.ts +2 -2
  117. package/dist/QueryStreamIndexPrefix.d.ts.map +1 -1
  118. package/dist/QueryStreamIndexPrefix.js +1 -1
  119. package/dist/QueryStreamIndexPrefix.js.map +1 -1
  120. package/dist/QueryStreamIndexRange.d.ts +4 -4
  121. package/dist/QueryStreamIndexRange.d.ts.map +1 -1
  122. package/dist/QueryStreamIndexRange.js +2 -2
  123. package/dist/QueryStreamIndexRange.js.map +1 -1
  124. package/dist/QueryStreamKey.d.ts +2 -2
  125. package/dist/QueryStreamKey.d.ts.map +1 -1
  126. package/dist/QueryStreamKey.js +1 -1
  127. package/dist/QueryStreamKey.js.map +1 -1
  128. package/dist/QueryStreamKeyBounds.d.ts +3 -3
  129. package/dist/QueryStreamKeyBounds.d.ts.map +1 -1
  130. package/dist/QueryStreamKeyBounds.js +2 -2
  131. package/dist/QueryStreamKeyBounds.js.map +1 -1
  132. package/dist/QueryStreamKeyLayout.d.ts +1 -1
  133. package/dist/QueryStreamKeyLayout.d.ts.map +1 -1
  134. package/dist/QueryStreamKeyLayout.js +2 -2
  135. package/dist/QueryStreamKeyLayout.js.map +1 -1
  136. package/dist/QueryStreamKeyValues.d.ts +1 -1
  137. package/dist/QueryStreamKeyValues.d.ts.map +1 -1
  138. package/dist/QueryStreamKeyValues.js +1 -1
  139. package/dist/QueryStreamKeyValues.js.map +1 -1
  140. package/dist/QueryStreamPagination.d.ts +1 -1
  141. package/dist/QueryStreamPagination.d.ts.map +1 -1
  142. package/dist/QueryStreamPagination.js +1 -1
  143. package/dist/QueryStreamPagination.js.map +1 -1
  144. package/dist/QueryStreamReadBudget.d.ts +3 -2
  145. package/dist/QueryStreamReadBudget.d.ts.map +1 -1
  146. package/dist/QueryStreamReadBudget.js +7 -4
  147. package/dist/QueryStreamReadBudget.js.map +1 -1
  148. package/dist/QueryTransactionContext.js +2 -2
  149. package/dist/RegisteredConvexFunction.d.ts +27 -24
  150. package/dist/RegisteredConvexFunction.d.ts.map +1 -1
  151. package/dist/RegisteredConvexFunction.js +39 -26
  152. package/dist/RegisteredConvexFunction.js.map +1 -1
  153. package/dist/RegisteredFunction.d.ts +51 -47
  154. package/dist/RegisteredFunction.d.ts.map +1 -1
  155. package/dist/RegisteredFunction.js +126 -37
  156. package/dist/RegisteredFunction.js.map +1 -1
  157. package/dist/RegisteredFunctions.d.ts +3 -3
  158. package/dist/RegisteredFunctions.d.ts.map +1 -1
  159. package/dist/RegisteredFunctions.js.map +1 -1
  160. package/dist/RegisteredNodeFunction.d.ts +7 -7
  161. package/dist/RegisteredNodeFunction.d.ts.map +1 -1
  162. package/dist/RegisteredNodeFunction.js +8 -6
  163. package/dist/RegisteredNodeFunction.js.map +1 -1
  164. package/dist/Registry.d.ts +1 -1
  165. package/dist/Registry.d.ts.map +1 -1
  166. package/dist/Registry.js.map +1 -1
  167. package/dist/RegistryItems.d.ts +7 -0
  168. package/dist/RegistryItems.d.ts.map +1 -1
  169. package/dist/RegistryItems.js +8 -3
  170. package/dist/RegistryItems.js.map +1 -1
  171. package/dist/RequestMetadata.js +1 -1
  172. package/dist/ResolvedMiddleware.d.ts +2 -2
  173. package/dist/ResolvedMiddleware.d.ts.map +1 -1
  174. package/dist/ResolvedMiddleware.js.map +1 -1
  175. package/dist/Scheduler.js +2 -2
  176. package/dist/Storage.d.ts +6 -6
  177. package/dist/Storage.d.ts.map +1 -1
  178. package/dist/Storage.js +1 -1
  179. package/dist/Storage.js.map +1 -1
  180. package/dist/StorageActionWriter.d.ts +1 -1
  181. package/dist/StorageActionWriter.d.ts.map +1 -1
  182. package/dist/StorageActionWriter.js +1 -1
  183. package/dist/StorageActionWriter.js.map +1 -1
  184. package/dist/StorageReader.d.ts +1 -1
  185. package/dist/StorageReader.d.ts.map +1 -1
  186. package/dist/StorageReader.js +1 -1
  187. package/dist/StorageReader.js.map +1 -1
  188. package/dist/StorageWriter.d.ts +1 -1
  189. package/dist/StorageWriter.d.ts.map +1 -1
  190. package/dist/StorageWriter.js +1 -1
  191. package/dist/StorageWriter.js.map +1 -1
  192. package/dist/TableInfo.d.ts +2 -2
  193. package/dist/TableInfo.d.ts.map +1 -1
  194. package/dist/TableInfo.js.map +1 -1
  195. package/dist/TransactionMetadata.js +1 -1
  196. package/dist/VectorSearch.d.ts +1 -1
  197. package/dist/VectorSearch.d.ts.map +1 -1
  198. package/dist/VectorSearch.js +1 -1
  199. package/dist/VectorSearch.js.map +1 -1
  200. package/dist/index.d.ts +62 -60
  201. package/dist/index.d.ts.map +1 -1
  202. package/dist/index.js +20 -18
  203. package/dist/internal/AiGatewayDecisionClient.d.ts +1 -1
  204. package/dist/internal/AiGatewayDecisionClient.d.ts.map +1 -1
  205. package/dist/internal/AiGatewayDecisionClient.js +1 -1
  206. package/dist/internal/AiGatewayDecisionClient.js.map +1 -1
  207. package/dist/internal/AiGatewayLanguageClient.d.ts +1 -1
  208. package/dist/internal/AiGatewayLanguageClient.d.ts.map +1 -1
  209. package/dist/internal/AiGatewayLanguageClient.js +1 -1
  210. package/dist/internal/AiGatewayLanguageClient.js.map +1 -1
  211. package/dist/internal/AiGatewayServiceToken.js +1 -1
  212. package/dist/internal/DocumentPatch.d.ts +16 -0
  213. package/dist/internal/DocumentPatch.d.ts.map +1 -0
  214. package/dist/internal/DocumentPatch.js +36 -0
  215. package/dist/internal/DocumentPatch.js.map +1 -0
  216. package/dist/internal/observability.d.ts +5 -0
  217. package/dist/internal/observability.d.ts.map +1 -0
  218. package/dist/internal/observability.js +21 -0
  219. package/dist/internal/observability.js.map +1 -0
  220. package/dist/node.d.ts +1 -1
  221. package/dist/node.d.ts.map +1 -1
  222. package/package.json +5 -5
  223. package/src/ActionCall.ts +82 -0
  224. package/src/ActionCtx.ts +1 -1
  225. package/src/AiGatewayDecisionClient.ts +3 -3
  226. package/src/AiGatewayLanguageClient.ts +3 -3
  227. package/src/Auth.ts +24 -2
  228. package/src/ComponentCtx.ts +1 -1
  229. package/src/ConvexFunctionDefinitions.ts +10 -9
  230. package/src/CronJobs.ts +1 -1
  231. package/src/DataModel.ts +3 -3
  232. package/src/DatabaseReader.ts +4 -4
  233. package/src/DatabaseSchema.ts +1 -1
  234. package/src/DatabaseWriter.ts +189 -31
  235. package/src/Document.ts +4 -4
  236. package/src/FunctionImpl.ts +5 -5
  237. package/src/FunctionRegistryItem.ts +1 -1
  238. package/src/GroupImpl.ts +66 -13
  239. package/src/GroupRegistry.ts +11 -7
  240. package/src/Handler.ts +44 -28
  241. package/src/HttpRouter.ts +71 -21
  242. package/src/MiddlewareImpl.ts +17 -17
  243. package/src/MutationCtx.ts +1 -1
  244. package/src/MutationRunner.ts +1 -1
  245. package/src/MutationTransactionContext.ts +2 -2
  246. package/src/OfficialComponent.ts +151 -0
  247. package/src/OrderedQuery.ts +4 -4
  248. package/src/QueryCtx.ts +1 -1
  249. package/src/QueryInitializer.ts +9 -9
  250. package/src/QueryRunner.ts +2 -2
  251. package/src/QueryStream.ts +406 -76
  252. package/src/QueryStreamCursor.ts +3 -3
  253. package/src/QueryStreamIndexPrefix.ts +2 -2
  254. package/src/QueryStreamIndexRange.ts +4 -4
  255. package/src/QueryStreamKey.ts +2 -2
  256. package/src/QueryStreamKeyBounds.ts +3 -3
  257. package/src/QueryStreamKeyLayout.ts +1 -1
  258. package/src/QueryStreamKeyValues.ts +1 -1
  259. package/src/QueryStreamPagination.ts +2 -2
  260. package/src/QueryStreamReadBudget.ts +19 -6
  261. package/src/RegisteredConvexFunction.ts +38 -21
  262. package/src/RegisteredFunction.ts +209 -60
  263. package/src/RegisteredFunctions.ts +4 -4
  264. package/src/RegisteredNodeFunction.ts +15 -9
  265. package/src/Registry.ts +1 -1
  266. package/src/RegistryItems.ts +33 -2
  267. package/src/ResolvedMiddleware.ts +2 -2
  268. package/src/Storage.ts +3 -3
  269. package/src/StorageActionWriter.ts +1 -1
  270. package/src/StorageReader.ts +1 -1
  271. package/src/StorageWriter.ts +1 -1
  272. package/src/TableInfo.ts +2 -2
  273. package/src/VectorSearch.ts +1 -1
  274. package/src/index.ts +62 -60
  275. package/src/internal/AiGatewayDecisionClient.ts +2 -2
  276. package/src/internal/AiGatewayLanguageClient.ts +2 -2
  277. package/src/internal/DocumentPatch.ts +87 -0
  278. package/src/internal/observability.ts +27 -0
  279. package/src/node.ts +1 -1
@@ -1,12 +1,12 @@
1
1
  import * as Array from "effect/Array";
2
2
  import * as Effect from "effect/Effect";
3
- import * as QueryStreamKey from "./QueryStreamKey";
3
+ import * as QueryStreamKey from "./QueryStreamKey.js";
4
4
  import * as SchemaIssue from "effect/SchemaIssue";
5
5
  import * as Match from "effect/Match";
6
6
  import * as Schema from "effect/Schema";
7
7
  import * as SchemaGetter from "effect/SchemaGetter";
8
- import * as QueryStreamKeyLayout from "./QueryStreamKeyLayout";
9
- import * as QueryStreamKeyValues from "./QueryStreamKeyValues";
8
+ import * as QueryStreamKeyLayout from "./QueryStreamKeyLayout.js";
9
+ import * as QueryStreamKeyValues from "./QueryStreamKeyValues.js";
10
10
 
11
11
  // Serialized labels are a cursor boundary representation. They include every
12
12
  // runtime position but do not preserve implicitness.
@@ -1,8 +1,8 @@
1
1
  import * as Array from "effect/Array";
2
2
  import * as Data from "effect/Data";
3
3
  import * as Result from "effect/Result";
4
- import type * as QueryStreamKey from "./QueryStreamKey";
5
- import type * as QueryStreamKeyValues from "./QueryStreamKeyValues";
4
+ import type * as QueryStreamKey from "./QueryStreamKey.js";
5
+ import type * as QueryStreamKeyValues from "./QueryStreamKeyValues.js";
6
6
 
7
7
  const TypeId = "~@confect/server/QueryStreamIndexPrefix";
8
8
 
@@ -11,10 +11,10 @@ import * as Match from "effect/Match";
11
11
  import * as Option from "effect/Option";
12
12
  import * as Result from "effect/Result";
13
13
  import type * as Types from "effect/Types";
14
- import * as QueryStreamIndexPrefix from "./QueryStreamIndexPrefix";
15
- import * as QueryStreamKeyBounds from "./QueryStreamKeyBounds";
16
- import * as QueryStreamKeyValues from "./QueryStreamKeyValues";
17
- import type * as QueryStreamOrderDirection from "./QueryStreamOrderDirection";
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
18
 
19
19
  type Head<FieldPaths extends ReadonlyArray<string>> =
20
20
  FieldPaths extends readonly [infer H extends string, ...ReadonlyArray<string>]
@@ -1,8 +1,8 @@
1
1
  import * as Data from "effect/Data";
2
2
  import * as Predicate from "effect/Predicate";
3
3
  import * as Result from "effect/Result";
4
- import * as QueryStreamKeyLayout from "./QueryStreamKeyLayout";
5
- import type * as QueryStreamKeyValues from "./QueryStreamKeyValues";
4
+ import * as QueryStreamKeyLayout from "./QueryStreamKeyLayout.js";
5
+ import type * as QueryStreamKeyValues from "./QueryStreamKeyValues.js";
6
6
 
7
7
  const TypeId = "~@confect/server/QueryStreamKey";
8
8
 
@@ -3,9 +3,9 @@ import * as Data from "effect/Data";
3
3
  import * as Option from "effect/Option";
4
4
  import * as Order from "effect/Order";
5
5
  import * as Result from "effect/Result";
6
- import * as QueryStreamKey from "./QueryStreamKey";
7
- import * as QueryStreamKeyLayout from "./QueryStreamKeyLayout";
8
- import * as QueryStreamKeyValues from "./QueryStreamKeyValues";
6
+ import * as QueryStreamKey from "./QueryStreamKey.js";
7
+ import * as QueryStreamKeyLayout from "./QueryStreamKeyLayout.js";
8
+ import * as QueryStreamKeyValues from "./QueryStreamKeyValues.js";
9
9
 
10
10
  // A bound's key may be a *prefix* of the full key: bounding by `["a"]` means
11
11
  // bounding by the whole family of keys that start with `"a"`. To compare
@@ -6,7 +6,7 @@ import * as Option from "effect/Option";
6
6
  import * as Result from "effect/Result";
7
7
  import type * as Types from "effect/Types";
8
8
 
9
- import * as QueryStreamKeyLabels from "./QueryStreamKeyLabels";
9
+ import * as QueryStreamKeyLabels from "./QueryStreamKeyLabels.js";
10
10
 
11
11
  /**
12
12
  * One runtime position of a stream key. Explicit IDs and their aliases are
@@ -12,7 +12,7 @@ import * as Result from "effect/Result";
12
12
  import * as Schema from "effect/Schema";
13
13
  import * as SchemaGetter from "effect/SchemaGetter";
14
14
  import * as SchemaIssue from "effect/SchemaIssue";
15
- import type * as QueryStreamOrderDirection from "./QueryStreamOrderDirection";
15
+ import type * as QueryStreamOrderDirection from "./QueryStreamOrderDirection.js";
16
16
 
17
17
  const UNDEFINED_SENTINEL = { $undefined: true } as const;
18
18
  const KeyValue = Schema.Json.pipe(
@@ -4,8 +4,8 @@ import * as Match from "effect/Match";
4
4
  import * as Option from "effect/Option";
5
5
  import * as Result from "effect/Result";
6
6
  import * as Schema from "effect/Schema";
7
- import type * as QueryStreamKey from "./QueryStreamKey";
8
- import * as QueryStreamKeyValues from "./QueryStreamKeyValues";
7
+ import type * as QueryStreamKey from "./QueryStreamKey.js";
8
+ import * as QueryStreamKeyValues from "./QueryStreamKeyValues.js";
9
9
 
10
10
  const PageSize = Schema.Natural.pipe(
11
11
  Schema.brand("~@confect/server/QueryStreamPagination/PageSize"),
@@ -22,8 +22,9 @@ export interface QueryStreamReadBudget {
22
22
  readonly getReadCounts: Effect.Effect<ReadCounts>;
23
23
  /**
24
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.
25
+ * requesting further batches once exhausted, except for one limit-boundary
26
+ * lookahead to detect completion. Apply directly to the document source
27
+ * before buffering, filtering, or combining its output.
27
28
  */
28
29
  readonly accountFor: (
29
30
  encodedDocuments: Stream.Stream<unknown>,
@@ -133,10 +134,22 @@ export const make = Effect.fnUntraced(function* (
133
134
  SynchronizedRef.modifyEffect(stateRef, (state) =>
134
135
  Effect.gen(function* () {
135
136
  if (isExhausted(state, limits)) {
136
- return Tuple.make(
137
- Option.none(),
138
- State.Stopped(readCounts(state)),
139
- );
137
+ const canProbeEnd =
138
+ State.$is("Active")(state) &&
139
+ !Option.exists(
140
+ limits.maximumRowsRead,
141
+ (limit) => state.rowsRead > limit,
142
+ ) &&
143
+ !Option.exists(
144
+ limits.maximumBytesRead,
145
+ (limit) => state.bytesRead > limit,
146
+ );
147
+ // Iterators expose completion only through a pull. Count a
148
+ // lookahead row, but never publish it beyond either limit.
149
+ const counts = canProbeEnd
150
+ ? record(state, yield* pull)
151
+ : readCounts(state);
152
+ return Tuple.make(Option.none(), State.Stopped(counts));
140
153
  }
141
154
  const documents = yield* pull;
142
155
  return Tuple.make(
@@ -24,27 +24,27 @@ import * as Layer from "effect/Layer";
24
24
  import * as Match from "effect/Match";
25
25
  import * as Schema from "effect/Schema";
26
26
  import * as EffectScheduler from "effect/Scheduler";
27
- import * as Auth from "./Auth";
28
- import * as ConvexConfigProvider from "./ConvexConfigProvider";
29
- import * as DatabaseReader from "./DatabaseReader";
30
- import type * as DatabaseSchema from "./DatabaseSchema";
31
- import * as DatabaseWriter from "./DatabaseWriter";
32
- import type * as DataModel from "./DataModel";
33
- import * as ExecutionMetadata from "./ExecutionMetadata";
34
- import * as RequestMetadata from "./RequestMetadata";
35
- import * as TransactionMetadata from "./TransactionMetadata";
36
- import * as MutationCtx from "./MutationCtx";
37
- import * as MutationRunner from "./MutationRunner";
38
- import * as MutationTransactionContext from "./MutationTransactionContext";
39
- import * as QueryCtx from "./QueryCtx";
40
- import * as QueryRunner from "./QueryRunner";
41
- import * as QueryTransactionContext from "./QueryTransactionContext";
42
- import * as RegisteredFunction from "./RegisteredFunction";
43
- import type * as FunctionRegistryItem from "./FunctionRegistryItem";
44
- import type * as ResolvedMiddleware from "./ResolvedMiddleware";
45
- import * as Scheduler from "./Scheduler";
46
- import { StorageWriter } from "./StorageWriter";
47
- import type * as Handler from "./Handler";
27
+ import * as Auth from "./Auth.js";
28
+ import * as ConvexConfigProvider from "./ConvexConfigProvider.js";
29
+ import * as DatabaseReader from "./DatabaseReader.js";
30
+ import type * as DatabaseSchema from "./DatabaseSchema.js";
31
+ import * as DatabaseWriter from "./DatabaseWriter.js";
32
+ import type * as DataModel from "./DataModel.js";
33
+ import * as ExecutionMetadata from "./ExecutionMetadata.js";
34
+ import * as RequestMetadata from "./RequestMetadata.js";
35
+ import * as TransactionMetadata from "./TransactionMetadata.js";
36
+ import * as MutationCtx from "./MutationCtx.js";
37
+ import * as MutationRunner from "./MutationRunner.js";
38
+ import * as MutationTransactionContext from "./MutationTransactionContext.js";
39
+ import * as QueryCtx from "./QueryCtx.js";
40
+ import * as QueryRunner from "./QueryRunner.js";
41
+ import * as QueryTransactionContext from "./QueryTransactionContext.js";
42
+ import * as RegisteredFunction from "./RegisteredFunction.js";
43
+ import type * as FunctionRegistryItem from "./FunctionRegistryItem.js";
44
+ import type * as ResolvedMiddleware from "./ResolvedMiddleware.js";
45
+ import * as Scheduler from "./Scheduler.js";
46
+ import { StorageWriter } from "./StorageWriter.js";
47
+ import type * as Handler from "./Handler.js";
48
48
 
49
49
  export type Definition = Data.TaggedEnum<{
50
50
  PublicQuery: ReturnType<typeof queryFunction>;
@@ -61,12 +61,14 @@ export const prepare = (
61
61
  databaseSchema: DatabaseSchema.AnyWithProps,
62
62
  item: FunctionRegistryItem.ConfectFunctionRegistryItem,
63
63
  resolvedMiddlewares: ReadonlyArray<ResolvedMiddleware.ResolvedMiddleware> = [],
64
+ observability?: Layer.Layer<never>,
64
65
  ) =>
65
66
  Match.value(item.functionType).pipe(
66
67
  Match.when("query", () => {
67
68
  const definition = queryFunction({
68
69
  databaseSchema,
69
70
  name: item.name,
71
+ observability,
70
72
  functionVisibility: item.functionVisibility,
71
73
  args: item.args,
72
74
  returns: item.returns,
@@ -84,6 +86,7 @@ export const prepare = (
84
86
  const definition = mutationFunction({
85
87
  databaseSchema,
86
88
  name: item.name,
89
+ observability,
87
90
  functionVisibility: item.functionVisibility,
88
91
  args: item.args,
89
92
  returns: item.returns,
@@ -100,6 +103,7 @@ export const prepare = (
100
103
  Match.when("action", () => {
101
104
  const definition = convexActionFunction(databaseSchema, {
102
105
  name: item.name,
106
+ observability,
103
107
  functionVisibility: item.functionVisibility,
104
108
  args: item.args,
105
109
  returns: item.returns,
@@ -188,6 +192,7 @@ const queryFunction = <
188
192
  error,
189
193
  handler,
190
194
  resolvedMiddlewares,
195
+ observability,
191
196
  }: {
192
197
  databaseSchema: DatabaseSchema_;
193
198
  name: string;
@@ -199,6 +204,7 @@ const queryFunction = <
199
204
  a: Args,
200
205
  ) => Effect.Effect<Returns, E, Handler.QueryServices<DatabaseSchema_>>;
201
206
  resolvedMiddlewares: ReadonlyArray<ResolvedMiddleware.ResolvedMiddleware>;
207
+ observability?: Layer.Layer<never> | undefined;
202
208
  }) => ({
203
209
  args: compileArgsSchema(args, databaseSchema.target.scope),
204
210
  returns: compileReturnsSchema(returns, databaseSchema.target.scope),
@@ -258,6 +264,9 @@ const queryFunction = <
258
264
  RegisteredFunction.combineErrorSchemas(error, resolvedMiddlewares),
259
265
  {
260
266
  scheduler: new EffectScheduler.MixedScheduler("sync"),
267
+ invocation: Effect.promise(() => ctx.meta.getFunctionMetadata()),
268
+ clock: observability === undefined ? undefined : queryClock,
269
+ observability,
261
270
  },
262
271
  ),
263
272
  ),
@@ -274,6 +283,7 @@ export const mutationLayer = <Schema extends DatabaseSchema.AnyWithProps>(
274
283
  RequestMetadata.layer(ctx.meta),
275
284
  TransactionMetadata.layer(ctx.meta),
276
285
  Auth.layerForTarget<Schema["target"]>(schema.target, ctx.auth),
286
+ Auth.mutationLayer(ctx.auth),
277
287
  Scheduler.layer<DatabaseSchema.Scope<Schema>>(
278
288
  ctx.scheduler,
279
289
  schema.target.scope,
@@ -313,6 +323,7 @@ const mutationFunction = <
313
323
  error,
314
324
  handler,
315
325
  resolvedMiddlewares,
326
+ observability,
316
327
  }: {
317
328
  databaseSchema: DatabaseSchema_;
318
329
  name: string;
@@ -324,6 +335,7 @@ const mutationFunction = <
324
335
  a: Args,
325
336
  ) => Effect.Effect<Returns, E, MutationServices<DatabaseSchema_>>;
326
337
  resolvedMiddlewares: ReadonlyArray<ResolvedMiddleware.ResolvedMiddleware>;
338
+ observability?: Layer.Layer<never> | undefined;
327
339
  }) => ({
328
340
  args: compileArgsSchema(args, databaseSchema.target.scope),
329
341
  returns: compileReturnsSchema(returns, databaseSchema.target.scope),
@@ -360,6 +372,8 @@ const mutationFunction = <
360
372
  RegisteredFunction.combineErrorSchemas(error, resolvedMiddlewares),
361
373
  {
362
374
  scheduler: new EffectScheduler.MixedScheduler("sync"),
375
+ invocation: Effect.promise(() => ctx.meta.getFunctionMetadata()),
376
+ observability,
363
377
  },
364
378
  ),
365
379
  ),
@@ -382,6 +396,7 @@ const convexActionFunction = <
382
396
  error,
383
397
  handler,
384
398
  resolvedMiddlewares,
399
+ observability,
385
400
  }: {
386
401
  name: string;
387
402
  functionVisibility: FunctionVisibility;
@@ -396,6 +411,7 @@ const convexActionFunction = <
396
411
  RegisteredFunction.ActionServices<DatabaseSchema_>
397
412
  >;
398
413
  resolvedMiddlewares: ReadonlyArray<ResolvedMiddleware.ResolvedMiddleware>;
414
+ observability?: Layer.Layer<never> | undefined;
399
415
  },
400
416
  ) =>
401
417
  RegisteredFunction.actionFunctionBase({
@@ -407,6 +423,7 @@ const convexActionFunction = <
407
423
  error,
408
424
  handler,
409
425
  resolvedMiddlewares,
426
+ observability,
410
427
  createLayer: (ctx) =>
411
428
  Layer.mergeAll(
412
429
  RegisteredFunction.actionLayer(schema, ctx),
@@ -1,3 +1,5 @@
1
+ import * as ActionCallSpec from "@confect/core/ActionCall";
2
+ import * as ActionCall from "./ActionCall.js";
1
3
  import type { FunctionSpec, RuntimeAndFunctionType } from "@confect/core";
2
4
  import * as IdScope from "@confect/core/IdScope";
3
5
  import type * as FunctionProvenance from "@confect/core/FunctionProvenance";
@@ -9,6 +11,7 @@ import {
9
11
  import {
10
12
  type DefaultFunctionArgs,
11
13
  type FunctionVisibility,
14
+ type FunctionMetadata,
12
15
  type GenericActionCtx,
13
16
  type GenericDataModel,
14
17
  type StorageReader as ConvexStorageReader,
@@ -19,30 +22,41 @@ import {
19
22
  import type { Value } from "convex/values";
20
23
  import { ConvexError } from "convex/values";
21
24
  import { pipe } from "effect/Function";
25
+ import * as Clock from "effect/Clock";
26
+ import * as Cause from "effect/Cause";
22
27
  import * as Console from "effect/Console";
28
+ import * as Context from "effect/Context";
23
29
  import * as Effect from "effect/Effect";
30
+ import * as Exit from "effect/Exit";
24
31
  import * as Result from "effect/Result";
25
32
  import * as Layer from "effect/Layer";
26
33
  import * as Schema from "effect/Schema";
27
34
  import type * as EffectScheduler from "effect/Scheduler";
28
- import * as ActionCtx from "./ActionCtx";
29
- import * as ActionRunner from "./ActionRunner";
30
- import * as Auth from "./Auth";
31
- import * as ConvexLogger from "./ConvexLogger";
32
- import type * as DatabaseSchema from "./DatabaseSchema";
33
- import type * as DataModel from "./DataModel";
34
- import * as ExecutionMetadata from "./ExecutionMetadata";
35
- import * as RequestMetadata from "./RequestMetadata";
36
- import * as MutationRunner from "./MutationRunner";
37
- import * as QueryRunner from "./QueryRunner";
38
- import type * as ResolvedMiddleware from "./ResolvedMiddleware";
39
- import * as Scheduler from "./Scheduler";
40
- import * as Storage from "./Storage";
41
- import * as StorageActionWriter from "./StorageActionWriter";
42
- import type * as StorageReader from "./StorageReader";
43
- import * as StorageWriter from "./StorageWriter";
44
- import * as VectorSearch from "./VectorSearch";
45
- import type * as Handler from "./Handler";
35
+ import * as ActionCtx from "./ActionCtx.js";
36
+ import * as ActionRunner from "./ActionRunner.js";
37
+ import * as Auth from "./Auth.js";
38
+ import * as ConvexLogger from "./ConvexLogger.js";
39
+ import type * as DatabaseSchema from "./DatabaseSchema.js";
40
+ import type * as DataModel from "./DataModel.js";
41
+ import * as ExecutionMetadata from "./ExecutionMetadata.js";
42
+ import * as RequestMetadata from "./RequestMetadata.js";
43
+ import * as MutationRunner from "./MutationRunner.js";
44
+ import * as QueryRunner from "./QueryRunner.js";
45
+ import type * as ResolvedMiddleware from "./ResolvedMiddleware.js";
46
+ import * as Scheduler from "./Scheduler.js";
47
+ import * as Storage from "./Storage.js";
48
+ import * as StorageActionWriter from "./StorageActionWriter.js";
49
+ import type * as StorageReader from "./StorageReader.js";
50
+ import * as StorageWriter from "./StorageWriter.js";
51
+ import * as Tracer from "effect/Tracer";
52
+ import * as ObservabilityRuntime from "./internal/observability.js";
53
+ import * as VectorSearch from "./VectorSearch.js";
54
+ import type * as Handler from "./Handler.js";
55
+
56
+ export const Observability = Context.Reference<Layer.Layer<never> | undefined>(
57
+ "@confect/server/Observability",
58
+ { defaultValue: () => undefined },
59
+ );
46
60
 
47
61
  export type Any =
48
62
  | RegisteredQuery<FunctionVisibility, DefaultFunctionArgs, any>
@@ -183,67 +197,144 @@ export const combineErrorSchemas = (
183
197
  };
184
198
 
185
199
  /**
186
- * Run the `Effect` as a `Promise`. The error schema acts as an allowlist of
187
- * failures that may be surfaced to the client as a `ConvexError`:
200
+ * Run the `Effect` as a `Promise`. Inspect the complete `Exit` before encoding
201
+ * a declared error so a typed failure cannot hide a defect.
188
202
  *
189
- * - With a schema: typed errors are schema-encoded and wrapped in a
190
- * `ConvexError`, then thrown so Convex surfaces the data to the client.
191
- * `Effect.either` escapes the failure channel before `runPromise` so the
192
- * thrown `ConvexError` retains its `Symbol.for("ConvexError")` identity
193
- * instead of being wrapped in Effect's `FiberFailure`.
194
- * - Without a schema: every failure is converted to a defect via `Effect.orDie`,
195
- * so nothing—not even a `ConvexError` the handler placed in its error
196
- * channel—reaches the client as a `ConvexError`. The fiber dies and
197
- * `runPromise` rejects with a generic failure.
203
+ * Any `Die` reason takes the defect path. Without a `Die`, the first `Fail` in
204
+ * cause order is schema-encoded and thrown as a `ConvexError` outside the
205
+ * Effect runtime so Convex surfaces its data to the client. Other failures and
206
+ * interruptions alongside that `Fail` are ignored. Without an error schema, the
207
+ * selected failure is treated as a defect.
198
208
  *
199
- * Either way, a `ConvexError` _defect_—thrown imperatively rather than placed
200
- * in the error channel, e.g. the pagination protocol's `InvalidCursor` signal
201
- * from `QueryStream.paginate`—is rethrown bare so it retains its identity and
202
- * Convex serializes its `data` to the client, matching how a thrown
203
- * `ConvexError` behaves in a plain Convex handler.
209
+ * A lone `ConvexError` defect or a selected undeclared `ConvexError` failure is
210
+ * rethrown bare so it keeps Convex's meaning. Pagination and Workpool rely on
211
+ * its data for their control signals. Other causes with a `Die`, interrupt-only
212
+ * or empty causes, and error-encoding failures reject with a plain `Error`
213
+ * whose message renders the complete cause and whose `cause` holds it for
214
+ * server diagnostics.
204
215
  *
205
216
  * A `scheduler` in `runOptions` must be passed here as a run option rather than
206
217
  * provided via `Effect.provideService` inside `effect`: the run option lands in
207
218
  * the fiber's root context, while a service provided within `effect` pops
208
- * before the `orDie`/`catch`/`result` wrappers this function adds. The fiber's
209
- * op counter survives context pops, so a cooperative yield can fire inside
210
- * those wrappers—only a root-context scheduler covers them.
219
+ * before the exit/encoding wrappers this function adds. The fiber's op counter
220
+ * survives context pops, so a cooperative yield can fire inside those wrappers.
221
+ * Only a root-context scheduler covers them.
211
222
  */
212
223
  export const runHandlerPromise =
213
224
  (
214
225
  errorSchema: Schema.Codec<any, any> | undefined,
215
226
  runOptions?: {
216
227
  readonly scheduler?: EffectScheduler.Scheduler | undefined;
228
+ readonly clock?: Clock.Clock | undefined;
229
+ readonly invocation?: Effect.Effect<FunctionMetadata> | undefined;
230
+ readonly observability?: Layer.Layer<never> | undefined;
217
231
  },
218
232
  ) =>
219
233
  <A, E>(effect: Effect.Effect<A, E>): Promise<A> => {
220
- // A `ConvexError` defect escapes into the (escaped) failure channel so
221
- // the `throw` below rethrows it with its identity intact.
222
- const rethrowConvexErrorDefects = Effect.catchDefect(
223
- (defect: unknown): Effect.Effect<never, ConvexError<any>> =>
224
- defect instanceof ConvexError
225
- ? Effect.fail(defect)
226
- : Effect.die(defect),
234
+ const { observability, invocation, clock } = runOptions ?? {};
235
+ let encodedError: Exit.Exit<any, any> | undefined;
236
+ let undeclared: { readonly error: unknown } | undefined;
237
+ const observed = Effect.tapCause(effect, (cause) =>
238
+ Effect.gen(function* () {
239
+ const reason =
240
+ cause.reasons.find(Cause.isDieReason) ??
241
+ cause.reasons.find(Cause.isFailReason);
242
+ if (reason?._tag === "Fail" && errorSchema !== undefined) {
243
+ encodedError = yield* Effect.exit(
244
+ Schema.encodeEffect(errorSchema)(reason.error),
245
+ );
246
+ // An encoding failure is a defect, even when it dies with a ConvexError.
247
+ if (Exit.isFailure(encodedError)) {
248
+ const encoding = encodedError.cause;
249
+ return yield* Cause.squash(encoding) instanceof ConvexError
250
+ ? Effect.die(
251
+ new Error(Cause.pretty(encoding), { cause: encoding }),
252
+ )
253
+ : Effect.orDie(encodedError);
254
+ }
255
+ }
256
+ // With no error schema a failure is a defect, so the root span ends as one.
257
+ if (
258
+ reason?._tag === "Fail" &&
259
+ errorSchema === undefined &&
260
+ !(reason.error instanceof ConvexError)
261
+ ) {
262
+ undeclared = { error: reason.error };
263
+ return yield* Effect.die(reason.error);
264
+ }
265
+ }),
227
266
  );
228
-
229
- const withConvexError =
230
- errorSchema === undefined
231
- ? Effect.orDie(effect)
232
- : effect.pipe(
233
- Effect.catch((typedError) =>
234
- pipe(
235
- Schema.encodeEffect(errorSchema)(typedError),
236
- Effect.catchTag("SchemaError", Effect.die),
237
- Effect.andThen((encodedError) =>
238
- Effect.fail(new ConvexError(encodedError)),
267
+ const withConvexError: Effect.Effect<Result.Result<A, ConvexError<any>>> =
268
+ Effect.gen(function* () {
269
+ const exit = yield* Effect.exit(
270
+ observability === undefined || invocation === undefined
271
+ ? effect
272
+ : Effect.flatMap(invocation, ({ name, type, componentPath }) =>
273
+ Effect.useSpan(
274
+ name,
275
+ {
276
+ root: true,
277
+ attributes: { kind: type, componentPath },
278
+ },
279
+ (span) =>
280
+ Effect.provideService(observed, Tracer.ParentSpan, span),
239
281
  ),
240
282
  ),
241
- ),
283
+ );
284
+ if (Exit.isSuccess(exit)) {
285
+ return Result.succeed(exit.value);
286
+ }
287
+ if (undeclared !== undefined)
288
+ return yield* Effect.die(undeclared.error);
289
+
290
+ const cause =
291
+ encodedError !== undefined && Exit.isFailure(encodedError)
292
+ ? encodedError.cause
293
+ : exit.cause;
294
+ const reason =
295
+ cause.reasons.find(Cause.isDieReason) ??
296
+ cause.reasons.find(Cause.isFailReason);
297
+ if (
298
+ encodedError === undefined &&
299
+ reason?._tag === "Die" &&
300
+ cause.reasons.length === 1 &&
301
+ reason.defect instanceof ConvexError
302
+ ) {
303
+ return Result.fail(reason.defect);
304
+ }
305
+
306
+ if (reason?._tag === "Fail") {
307
+ if (errorSchema === undefined) {
308
+ if (reason.error instanceof ConvexError) {
309
+ return Result.fail(reason.error);
310
+ }
311
+ return yield* Effect.die(reason.error);
312
+ }
313
+ const encoded =
314
+ encodedError ??
315
+ (yield* Effect.exit(
316
+ Schema.encodeEffect(errorSchema)(reason.error),
317
+ ));
318
+ if (Exit.isSuccess(encoded)) {
319
+ return Result.fail(new ConvexError(encoded.value));
320
+ }
321
+ return yield* Effect.die(
322
+ new Error(Cause.pretty(encoded.cause), { cause: encoded.cause }),
242
323
  );
324
+ }
325
+ return yield* Effect.die(new Error(Cause.pretty(cause), { cause }));
326
+ });
243
327
  return Effect.runPromise(
244
- Effect.result(rethrowConvexErrorDefects(withConvexError)).pipe(
245
- Effect.provide(ConvexLogger.layer),
328
+ withConvexError.pipe(
329
+ Effect.provide(
330
+ observability === undefined
331
+ ? ConvexLogger.layer
332
+ : ObservabilityRuntime.memoized(observability),
333
+ ),
246
334
  Effect.provideService(Console.Console, globalThis.console),
335
+ clock === undefined
336
+ ? (self) => self
337
+ : Effect.provideService(Clock.Clock, clock),
247
338
  ),
248
339
  runOptions,
249
340
  ).then(
@@ -274,6 +365,7 @@ export const actionFunctionBase = <
274
365
  resolvedMiddlewares = [],
275
366
  createLayer,
276
367
  scope = IdScope.app,
368
+ observability,
277
369
  }: {
278
370
  name: string;
279
371
  functionVisibility: FunctionVisibility;
@@ -286,6 +378,7 @@ export const actionFunctionBase = <
286
378
  ctx: GenericActionCtx<DataModel.ToConvex<DataModel.FromSchema<Schema>>>,
287
379
  ) => Layer.Layer<R>;
288
380
  scope?: IdScope.IdScope;
381
+ observability?: Layer.Layer<never> | undefined;
289
382
  }) => ({
290
383
  args: compileArgsSchema(args, scope),
291
384
  returns: compileReturnsSchema(returns, scope),
@@ -299,6 +392,12 @@ export const actionFunctionBase = <
299
392
  Schema.decodeUnknownEffect(args),
300
393
  Effect.catchTag("SchemaError", Effect.die),
301
394
  );
395
+ const restricted = resolvedMiddlewares.some(
396
+ ({ middlewareSpec }) =>
397
+ middlewareSpec.key === ActionCallSpec.Middleware.key,
398
+ )
399
+ ? restrict(ctx)
400
+ : undefined;
302
401
  // oxlint-disable-next-line effecttsgo/any-unknown-in-error-context -- Middleware errors are intentionally erased here and validated by runHandlerPromise against the combined error schema below.
303
402
  const decodedReturns = yield* applyMiddleware(
304
403
  handler(decodedArgs),
@@ -309,13 +408,19 @@ export const actionFunctionBase = <
309
408
  functionVisibility,
310
409
  args: decodedArgs,
311
410
  },
312
- ).pipe(Effect.provide(createLayer(ctx)));
411
+ ).pipe(Effect.provide(createLayer(restricted?.ctx ?? ctx)));
412
+ if (restricted !== undefined) yield* restricted.check;
313
413
  return yield* pipe(
314
414
  decodedReturns,
315
415
  Schema.encodeEffect(returns),
316
416
  Effect.catchTag("SchemaError", Effect.die),
317
417
  );
318
- }).pipe(runHandlerPromise(combineErrorSchemas(error, resolvedMiddlewares))),
418
+ }).pipe(
419
+ runHandlerPromise(combineErrorSchemas(error, resolvedMiddlewares), {
420
+ invocation: Effect.promise(() => ctx.meta.getFunctionMetadata()),
421
+ observability,
422
+ }),
423
+ ),
319
424
  });
320
425
 
321
426
  export type ActionServices<
@@ -389,3 +494,47 @@ export const storageLayer = <Scope extends IdScope.IdScope>(
389
494
  Storage.layer(reader) as Layer.Layer<
390
495
  Storage.Storage | StorageReader.ForScope<Scope>
391
496
  >;
497
+
498
+ /**
499
+ * Shares one dispatch budget across the entire middleware chain.
500
+ */
501
+ const restrict = <Model extends GenericDataModel>(
502
+ ctx: GenericActionCtx<Model>,
503
+ ) => {
504
+ let dispatched = false;
505
+ const claim = () => {
506
+ if (dispatched) throw new ActionCall.ActionCallAlreadyUsed();
507
+ dispatched = true;
508
+ };
509
+ const restricted: GenericActionCtx<Model> = {
510
+ ...ctx,
511
+ scheduler: {
512
+ runAfter: () => {
513
+ throw new ActionCall.SchedulingNotAllowed();
514
+ },
515
+ runAt: () => {
516
+ throw new ActionCall.SchedulingNotAllowed();
517
+ },
518
+ cancel: () => {
519
+ throw new ActionCall.SchedulingNotAllowed();
520
+ },
521
+ },
522
+ runQuery: (...args) => {
523
+ claim();
524
+ return ctx.runQuery(...args);
525
+ },
526
+ runMutation: (...args) => {
527
+ claim();
528
+ return ctx.runMutation(...args);
529
+ },
530
+ runAction: () => {
531
+ throw new ActionCall.NestedActionNotAllowed();
532
+ },
533
+ };
534
+ return {
535
+ ctx: restricted,
536
+ check: Effect.suspend(() =>
537
+ dispatched ? Effect.void : Effect.die(new ActionCall.ActionCallNotUsed()),
538
+ ),
539
+ };
540
+ };