@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.
- package/CHANGELOG.md +2119 -0
- package/LICENSE +7 -0
- package/README.md +16 -2
- package/dist/ActionCtx.d.ts +10 -0
- package/dist/ActionCtx.d.ts.map +1 -0
- package/dist/ActionCtx.js +18 -0
- package/dist/ActionCtx.js.map +1 -0
- package/dist/ActionRunner.d.ts +16 -0
- package/dist/ActionRunner.d.ts.map +1 -0
- package/dist/ActionRunner.js +18 -0
- package/dist/ActionRunner.js.map +1 -0
- package/dist/AiGatewayDecisionClient.d.ts +20 -0
- package/dist/AiGatewayDecisionClient.d.ts.map +1 -0
- package/dist/AiGatewayDecisionClient.js +31 -0
- package/dist/AiGatewayDecisionClient.js.map +1 -0
- package/dist/AiGatewayDecisionModel.d.ts +24 -0
- package/dist/AiGatewayDecisionModel.d.ts.map +1 -0
- package/dist/AiGatewayDecisionModel.js +27 -0
- package/dist/AiGatewayDecisionModel.js.map +1 -0
- package/dist/AiGatewayLanguageClient.d.ts +21 -0
- package/dist/AiGatewayLanguageClient.d.ts.map +1 -0
- package/dist/AiGatewayLanguageClient.js +32 -0
- package/dist/AiGatewayLanguageClient.js.map +1 -0
- package/dist/AiGatewayLanguageModel.d.ts +95 -0
- package/dist/AiGatewayLanguageModel.d.ts.map +1 -0
- package/dist/AiGatewayLanguageModel.js +42 -0
- package/dist/AiGatewayLanguageModel.js.map +1 -0
- package/dist/Auth.d.ts +20 -0
- package/dist/Auth.d.ts.map +1 -0
- package/dist/Auth.js +31 -0
- package/dist/Auth.js.map +1 -0
- package/dist/BlobNotFoundError.d.ts +9 -0
- package/dist/BlobNotFoundError.d.ts.map +1 -0
- package/dist/BlobNotFoundError.js +13 -0
- package/dist/BlobNotFoundError.js.map +1 -0
- package/dist/Callback.d.ts +31 -0
- package/dist/Callback.d.ts.map +1 -0
- package/dist/Callback.js +182 -0
- package/dist/Callback.js.map +1 -0
- package/dist/ComponentCtx.d.ts +71 -0
- package/dist/ComponentCtx.d.ts.map +1 -0
- package/dist/ComponentCtx.js +0 -0
- package/dist/ConvexConfigProvider.d.ts +21 -0
- package/dist/ConvexConfigProvider.d.ts.map +1 -0
- package/dist/ConvexConfigProvider.js +36 -0
- package/dist/ConvexConfigProvider.js.map +1 -0
- package/dist/ConvexFunctionDefinitions.d.ts +25 -0
- package/dist/ConvexFunctionDefinitions.d.ts.map +1 -0
- package/dist/ConvexFunctionDefinitions.js +25 -0
- package/dist/ConvexFunctionDefinitions.js.map +1 -0
- package/dist/ConvexLogger.d.ts +17 -0
- package/dist/ConvexLogger.d.ts.map +1 -0
- package/dist/ConvexLogger.js +33 -0
- package/dist/ConvexLogger.js.map +1 -0
- package/dist/CronJob.d.ts +14 -0
- package/dist/CronJob.d.ts.map +1 -0
- package/dist/CronJob.js +22 -0
- package/dist/CronJob.js.map +1 -0
- package/dist/CronJobs.d.ts +22 -0
- package/dist/CronJobs.d.ts.map +1 -0
- package/dist/CronJobs.js +83 -0
- package/dist/CronJobs.js.map +1 -0
- package/dist/DataModel.d.ts +28 -0
- package/dist/DataModel.d.ts.map +1 -0
- package/dist/DataModel.js +7 -0
- package/dist/DataModel.js.map +1 -0
- package/dist/DatabaseReader.d.ts +26 -0
- package/dist/DatabaseReader.d.ts.map +1 -0
- package/dist/DatabaseReader.js +33 -0
- package/dist/DatabaseReader.js.map +1 -0
- package/dist/DatabaseSchema.d.ts +67 -0
- package/dist/DatabaseSchema.d.ts.map +1 -0
- package/dist/DatabaseSchema.js +61 -0
- package/dist/DatabaseSchema.js.map +1 -0
- package/dist/DatabaseWriter.d.ts +44 -0
- package/dist/DatabaseWriter.d.ts.map +1 -0
- package/dist/DatabaseWriter.js +47 -0
- package/dist/DatabaseWriter.js.map +1 -0
- package/dist/Document.d.ts +37 -0
- package/dist/Document.d.ts.map +1 -0
- package/dist/Document.js +54 -0
- package/dist/Document.js.map +1 -0
- package/dist/ExecutionMetadata.d.ts +13 -0
- package/dist/ExecutionMetadata.d.ts.map +1 -0
- package/dist/ExecutionMetadata.js +19 -0
- package/dist/ExecutionMetadata.js.map +1 -0
- package/dist/FunctionImpl.d.ts +39 -0
- package/dist/FunctionImpl.d.ts.map +1 -0
- package/dist/FunctionImpl.js +46 -0
- package/dist/FunctionImpl.js.map +1 -0
- package/dist/FunctionRegistryItem.d.ts +36 -0
- package/dist/FunctionRegistryItem.d.ts.map +1 -0
- package/dist/FunctionRegistryItem.js +34 -0
- package/dist/FunctionRegistryItem.js.map +1 -0
- package/dist/GroupImpl.d.ts +77 -0
- package/dist/GroupImpl.d.ts.map +1 -0
- package/dist/GroupImpl.js +81 -0
- package/dist/GroupImpl.js.map +1 -0
- package/dist/GroupRegistry.d.ts +8 -0
- package/dist/GroupRegistry.d.ts.map +1 -0
- package/dist/GroupRegistry.js +26 -0
- package/dist/GroupRegistry.js.map +1 -0
- package/dist/Handler.d.ts +47 -0
- package/dist/Handler.d.ts.map +1 -0
- package/dist/Handler.js +7 -0
- package/dist/Handler.js.map +1 -0
- package/dist/HttpRouter.d.ts +80 -0
- package/dist/HttpRouter.d.ts.map +1 -0
- package/dist/HttpRouter.js +195 -0
- package/dist/HttpRouter.js.map +1 -0
- package/dist/MiddlewareImpl.d.ts +79 -0
- package/dist/MiddlewareImpl.d.ts.map +1 -0
- package/dist/MiddlewareImpl.js +58 -0
- package/dist/MiddlewareImpl.js.map +1 -0
- package/dist/MiddlewareRegistryItem.d.ts +12 -0
- package/dist/MiddlewareRegistryItem.d.ts.map +1 -0
- package/dist/MiddlewareRegistryItem.js +15 -0
- package/dist/MiddlewareRegistryItem.js.map +1 -0
- package/dist/MutationCtx.d.ts +10 -0
- package/dist/MutationCtx.d.ts.map +1 -0
- package/dist/MutationCtx.js +18 -0
- package/dist/MutationCtx.js.map +1 -0
- package/dist/MutationRunner.d.ts +27 -0
- package/dist/MutationRunner.d.ts.map +1 -0
- package/dist/MutationRunner.js +28 -0
- package/dist/MutationRunner.js.map +1 -0
- package/dist/MutationTransactionContext.d.ts +17 -0
- package/dist/MutationTransactionContext.d.ts.map +1 -0
- package/dist/MutationTransactionContext.js +20 -0
- package/dist/MutationTransactionContext.js.map +1 -0
- package/dist/OrderedQuery.d.ts +32 -0
- package/dist/OrderedQuery.d.ts.map +1 -0
- package/dist/OrderedQuery.js +36 -0
- package/dist/OrderedQuery.js.map +1 -0
- package/dist/QueryCtx.d.ts +10 -0
- package/dist/QueryCtx.d.ts.map +1 -0
- package/dist/QueryCtx.js +18 -0
- package/dist/QueryCtx.js.map +1 -0
- package/dist/QueryInitializer.d.ts +75 -0
- package/dist/QueryInitializer.d.ts.map +1 -0
- package/dist/QueryInitializer.js +105 -0
- package/dist/QueryInitializer.js.map +1 -0
- package/dist/QueryRunner.d.ts +46 -0
- package/dist/QueryRunner.d.ts.map +1 -0
- package/dist/QueryRunner.js +30 -0
- package/dist/QueryRunner.js.map +1 -0
- package/dist/QueryStream.d.ts +678 -0
- package/dist/QueryStream.d.ts.map +1 -0
- package/dist/QueryStream.js +943 -0
- package/dist/QueryStream.js.map +1 -0
- package/dist/QueryStreamCursor.d.ts +39 -0
- package/dist/QueryStreamCursor.d.ts.map +1 -0
- package/dist/QueryStreamCursor.js +52 -0
- package/dist/QueryStreamCursor.js.map +1 -0
- package/dist/QueryStreamIndexPrefix.d.ts +48 -0
- package/dist/QueryStreamIndexPrefix.d.ts.map +1 -0
- package/dist/QueryStreamIndexPrefix.js +38 -0
- package/dist/QueryStreamIndexPrefix.js.map +1 -0
- package/dist/QueryStreamIndexRange.d.ts +193 -0
- package/dist/QueryStreamIndexRange.d.ts.map +1 -0
- package/dist/QueryStreamIndexRange.js +241 -0
- package/dist/QueryStreamIndexRange.js.map +1 -0
- package/dist/QueryStreamKey.d.ts +64 -0
- package/dist/QueryStreamKey.d.ts.map +1 -0
- package/dist/QueryStreamKey.js +69 -0
- package/dist/QueryStreamKey.js.map +1 -0
- package/dist/QueryStreamKeyBounds.d.ts +136 -0
- package/dist/QueryStreamKeyBounds.d.ts.map +1 -0
- package/dist/QueryStreamKeyBounds.js +208 -0
- package/dist/QueryStreamKeyBounds.js.map +1 -0
- package/dist/QueryStreamKeyLabels.d.ts +27 -0
- package/dist/QueryStreamKeyLabels.d.ts.map +1 -0
- package/dist/QueryStreamKeyLabels.js +22 -0
- package/dist/QueryStreamKeyLabels.js.map +1 -0
- package/dist/QueryStreamKeyLayout.d.ts +179 -0
- package/dist/QueryStreamKeyLayout.d.ts.map +1 -0
- package/dist/QueryStreamKeyLayout.js +167 -0
- package/dist/QueryStreamKeyLayout.js.map +1 -0
- package/dist/QueryStreamKeyValues.d.ts +40 -0
- package/dist/QueryStreamKeyValues.d.ts.map +1 -0
- package/dist/QueryStreamKeyValues.js +57 -0
- package/dist/QueryStreamKeyValues.js.map +1 -0
- package/dist/QueryStreamOrderDirection.d.ts +24 -0
- package/dist/QueryStreamOrderDirection.d.ts.map +1 -0
- package/dist/QueryStreamOrderDirection.js +11 -0
- package/dist/QueryStreamOrderDirection.js.map +1 -0
- package/dist/QueryStreamPagination.d.ts +264 -0
- package/dist/QueryStreamPagination.d.ts.map +1 -0
- package/dist/QueryStreamPagination.js +172 -0
- package/dist/QueryStreamPagination.js.map +1 -0
- package/dist/QueryStreamReadBudget.d.ts +63 -0
- package/dist/QueryStreamReadBudget.d.ts.map +1 -0
- package/dist/QueryStreamReadBudget.js +81 -0
- package/dist/QueryStreamReadBudget.js.map +1 -0
- package/dist/QueryTransactionContext.d.ts +16 -0
- package/dist/QueryTransactionContext.d.ts.map +1 -0
- package/dist/QueryTransactionContext.js +17 -0
- package/dist/QueryTransactionContext.js.map +1 -0
- package/dist/RegisteredConvexFunction.d.ts +359 -0
- package/dist/RegisteredConvexFunction.d.ts.map +1 -0
- package/dist/RegisteredConvexFunction.js +154 -0
- package/dist/RegisteredConvexFunction.js.map +1 -0
- package/dist/RegisteredFunction.d.ts +143 -0
- package/dist/RegisteredFunction.d.ts.map +1 -0
- package/dist/RegisteredFunction.js +125 -0
- package/dist/RegisteredFunction.js.map +1 -0
- package/dist/RegisteredFunctions.d.ts +57 -0
- package/dist/RegisteredFunctions.d.ts.map +1 -0
- package/dist/RegisteredFunctions.js +32 -0
- package/dist/RegisteredFunctions.js.map +1 -0
- package/dist/RegisteredNodeFunction.d.ts +11 -0
- package/dist/RegisteredNodeFunction.d.ts.map +1 -0
- package/dist/RegisteredNodeFunction.js +45 -0
- package/dist/RegisteredNodeFunction.js.map +1 -0
- package/dist/Registry.d.ts +12 -0
- package/dist/Registry.d.ts.map +1 -0
- package/dist/Registry.js +17 -0
- package/dist/Registry.js.map +1 -0
- package/dist/RegistryItems.d.ts +21 -0
- package/dist/RegistryItems.d.ts.map +1 -0
- package/dist/RegistryItems.js +27 -0
- package/dist/RegistryItems.js.map +1 -0
- package/dist/RequestMetadata.d.ts +12 -0
- package/dist/RequestMetadata.d.ts.map +1 -0
- package/dist/RequestMetadata.js +16 -0
- package/dist/RequestMetadata.js.map +1 -0
- package/dist/ResolvedMiddleware.d.ts +24 -0
- package/dist/ResolvedMiddleware.d.ts.map +1 -0
- package/dist/ResolvedMiddleware.js +34 -0
- package/dist/ResolvedMiddleware.js.map +1 -0
- package/dist/Scheduler.d.ts +31 -0
- package/dist/Scheduler.d.ts.map +1 -0
- package/dist/Scheduler.js +35 -0
- package/dist/Scheduler.js.map +1 -0
- package/dist/Storage.d.ts +22 -0
- package/dist/Storage.d.ts.map +1 -0
- package/dist/Storage.js +27 -0
- package/dist/Storage.js.map +1 -0
- package/dist/StorageActionWriter.d.ts +35 -0
- package/dist/StorageActionWriter.d.ts.map +1 -0
- package/dist/StorageActionWriter.js +24 -0
- package/dist/StorageActionWriter.js.map +1 -0
- package/dist/StorageReader.d.ts +26 -0
- package/dist/StorageReader.d.ts.map +1 -0
- package/dist/StorageReader.js +22 -0
- package/dist/StorageReader.js.map +1 -0
- package/dist/StorageWriter.d.ts +29 -0
- package/dist/StorageWriter.d.ts.map +1 -0
- package/dist/StorageWriter.js +24 -0
- package/dist/StorageWriter.js.map +1 -0
- package/dist/Table.d.ts +274 -0
- package/dist/Table.d.ts.map +1 -0
- package/dist/Table.js +70 -0
- package/dist/Table.js.map +1 -0
- package/dist/TableInfo.d.ts +44 -0
- package/dist/TableInfo.d.ts.map +1 -0
- package/dist/TableInfo.js +7 -0
- package/dist/TableInfo.js.map +1 -0
- package/dist/TransactionMetadata.d.ts +12 -0
- package/dist/TransactionMetadata.d.ts.map +1 -0
- package/dist/TransactionMetadata.js +16 -0
- package/dist/TransactionMetadata.js.map +1 -0
- package/dist/VectorSearch.d.ts +23 -0
- package/dist/VectorSearch.d.ts.map +1 -0
- package/dist/VectorSearch.js +17 -0
- package/dist/VectorSearch.js.map +1 -0
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/index.d.ts +88 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +61 -0
- package/dist/internal/AiGatewayDecisionClient.d.ts +7 -0
- package/dist/internal/AiGatewayDecisionClient.d.ts.map +1 -0
- package/dist/internal/AiGatewayDecisionClient.js +19 -0
- package/dist/internal/AiGatewayDecisionClient.js.map +1 -0
- package/dist/internal/AiGatewayLanguageClient.d.ts +7 -0
- package/dist/internal/AiGatewayLanguageClient.d.ts.map +1 -0
- package/dist/internal/AiGatewayLanguageClient.js +19 -0
- package/dist/internal/AiGatewayLanguageClient.js.map +1 -0
- package/dist/internal/AiGatewayServiceToken.d.ts +46 -0
- package/dist/internal/AiGatewayServiceToken.d.ts.map +1 -0
- package/dist/internal/AiGatewayServiceToken.js +62 -0
- package/dist/internal/AiGatewayServiceToken.js.map +1 -0
- package/dist/internal/constants.d.ts +2 -0
- package/dist/internal/constants.d.ts.map +1 -0
- package/dist/internal/constants.js +6 -0
- package/dist/internal/constants.js.map +1 -0
- package/dist/internal/utils.d.ts +13 -0
- package/dist/internal/utils.d.ts.map +1 -0
- package/dist/internal/utils.js +50 -0
- package/dist/internal/utils.js.map +1 -0
- package/dist/node.d.ts +2 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +1 -0
- package/package.json +68 -3
- package/src/ActionCtx.ts +45 -0
- package/src/ActionRunner.ts +36 -0
- package/src/AiGatewayDecisionClient.ts +40 -0
- package/src/AiGatewayDecisionModel.ts +46 -0
- package/src/AiGatewayLanguageClient.ts +41 -0
- package/src/AiGatewayLanguageModel.ts +61 -0
- package/src/Auth.ts +51 -0
- package/src/BlobNotFoundError.ts +12 -0
- package/src/Callback.ts +313 -0
- package/src/ComponentCtx.ts +192 -0
- package/src/ConvexConfigProvider.ts +39 -0
- package/src/ConvexFunctionDefinitions.ts +91 -0
- package/src/ConvexLogger.ts +43 -0
- package/src/CronJob.ts +42 -0
- package/src/CronJobs.ts +165 -0
- package/src/DataModel.ts +81 -0
- package/src/DatabaseReader.ts +118 -0
- package/src/DatabaseSchema.ts +139 -0
- package/src/DatabaseWriter.ts +232 -0
- package/src/Document.ts +146 -0
- package/src/ExecutionMetadata.ts +26 -0
- package/src/FunctionImpl.ts +96 -0
- package/src/FunctionRegistryItem.ts +85 -0
- package/src/GroupImpl.ts +167 -0
- package/src/GroupRegistry.ts +41 -0
- package/src/Handler.ts +191 -0
- package/src/HttpRouter.ts +388 -0
- package/src/MiddlewareImpl.ts +247 -0
- package/src/MiddlewareRegistryItem.ts +21 -0
- package/src/MutationCtx.ts +45 -0
- package/src/MutationRunner.ts +66 -0
- package/src/MutationTransactionContext.ts +48 -0
- package/src/OrderedQuery.ts +136 -0
- package/src/QueryCtx.ts +45 -0
- package/src/QueryInitializer.ts +537 -0
- package/src/QueryRunner.ts +91 -0
- package/src/QueryStream.ts +2476 -0
- package/src/QueryStreamCursor.ts +99 -0
- package/src/QueryStreamIndexPrefix.ts +79 -0
- package/src/QueryStreamIndexRange.ts +489 -0
- package/src/QueryStreamKey.ts +118 -0
- package/src/QueryStreamKeyBounds.ts +395 -0
- package/src/QueryStreamKeyLabels.ts +56 -0
- package/src/QueryStreamKeyLayout.ts +382 -0
- package/src/QueryStreamKeyValues.ts +112 -0
- package/src/QueryStreamOrderDirection.ts +29 -0
- package/src/QueryStreamPagination.ts +357 -0
- package/src/QueryStreamReadBudget.ts +167 -0
- package/src/QueryTransactionContext.ts +37 -0
- package/src/RegisteredConvexFunction.ts +415 -0
- package/src/RegisteredFunction.ts +391 -0
- package/src/RegisteredFunctions.ts +88 -0
- package/src/RegisteredNodeFunction.ts +120 -0
- package/src/Registry.ts +17 -0
- package/src/RegistryItems.ts +40 -0
- package/src/RequestMetadata.ts +20 -0
- package/src/ResolvedMiddleware.ts +70 -0
- package/src/Scheduler.ts +85 -0
- package/src/Storage.ts +37 -0
- package/src/StorageActionWriter.ts +59 -0
- package/src/StorageReader.ts +59 -0
- package/src/StorageWriter.ts +58 -0
- package/src/Table.ts +156 -0
- package/src/TableInfo.ts +106 -0
- package/src/TransactionMetadata.ts +20 -0
- package/src/VectorSearch.ts +75 -0
- package/src/index.ts +87 -0
- package/src/internal/AiGatewayDecisionClient.ts +16 -0
- package/src/internal/AiGatewayLanguageClient.ts +16 -0
- package/src/internal/AiGatewayServiceToken.ts +129 -0
- package/src/internal/constants.ts +1 -0
- package/src/internal/utils.ts +89 -0
- 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.js";
|
|
8
|
+
import * as QueryStreamKeyValues from "./QueryStreamKeyValues.js";
|
|
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));
|