@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.
- 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,118 @@
|
|
|
1
|
+
import * as Data from "effect/Data";
|
|
2
|
+
import * as Predicate from "effect/Predicate";
|
|
3
|
+
import * as Result from "effect/Result";
|
|
4
|
+
import * as QueryStreamKeyLayout from "./QueryStreamKeyLayout";
|
|
5
|
+
import type * as QueryStreamKeyValues from "./QueryStreamKeyValues";
|
|
6
|
+
|
|
7
|
+
const TypeId = "~@confect/server/QueryStreamKey";
|
|
8
|
+
|
|
9
|
+
interface Payload {
|
|
10
|
+
readonly [TypeId]: typeof TypeId;
|
|
11
|
+
readonly layout: QueryStreamKeyLayout.QueryStreamKeyLayout;
|
|
12
|
+
readonly values: QueryStreamKeyValues.QueryStreamKeyValues;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @experimental
|
|
17
|
+
*/
|
|
18
|
+
export type QueryStreamKey = Data.TaggedEnum<{
|
|
19
|
+
Complete: Payload;
|
|
20
|
+
Prefix: Payload;
|
|
21
|
+
}>;
|
|
22
|
+
const QueryStreamKey = Data.taggedEnum<QueryStreamKey>();
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @experimental
|
|
26
|
+
*/
|
|
27
|
+
export type Complete = Data.TaggedEnum.Value<QueryStreamKey, "Complete">;
|
|
28
|
+
/**
|
|
29
|
+
* @experimental
|
|
30
|
+
*/
|
|
31
|
+
export type Prefix = Data.TaggedEnum.Value<QueryStreamKey, "Prefix">;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @experimental
|
|
35
|
+
*/
|
|
36
|
+
export class KeyWidthMismatchError extends Data.TaggedError(
|
|
37
|
+
"KeyWidthMismatchError",
|
|
38
|
+
)<{
|
|
39
|
+
readonly kind: "complete" | "prefix";
|
|
40
|
+
readonly width: number;
|
|
41
|
+
readonly actual: number;
|
|
42
|
+
}> {
|
|
43
|
+
override get message(): string {
|
|
44
|
+
return `Invalid ${this.kind} key width (${this.actual}); expected ${this.kind === "complete" ? "exactly" : "at most"} ${this.width}`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @experimental
|
|
50
|
+
*/
|
|
51
|
+
export const complete = (
|
|
52
|
+
layout: QueryStreamKeyLayout.QueryStreamKeyLayout,
|
|
53
|
+
values: QueryStreamKeyValues.QueryStreamKeyValues,
|
|
54
|
+
): Result.Result<Complete, KeyWidthMismatchError> => {
|
|
55
|
+
const width = QueryStreamKeyLayout.runtimeWidth(layout);
|
|
56
|
+
return values.length === width
|
|
57
|
+
? Result.succeed(
|
|
58
|
+
QueryStreamKey.Complete({ [TypeId]: TypeId, layout, values }),
|
|
59
|
+
)
|
|
60
|
+
: Result.fail(
|
|
61
|
+
new KeyWidthMismatchError({
|
|
62
|
+
kind: "complete",
|
|
63
|
+
width,
|
|
64
|
+
actual: values.length,
|
|
65
|
+
}),
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @experimental
|
|
71
|
+
*/
|
|
72
|
+
export const prefix = (
|
|
73
|
+
layout: QueryStreamKeyLayout.QueryStreamKeyLayout,
|
|
74
|
+
values: QueryStreamKeyValues.QueryStreamKeyValues,
|
|
75
|
+
): Result.Result<Prefix, KeyWidthMismatchError> => {
|
|
76
|
+
const width = QueryStreamKeyLayout.runtimeWidth(layout);
|
|
77
|
+
return values.length <= width
|
|
78
|
+
? Result.succeed(
|
|
79
|
+
QueryStreamKey.Prefix({ [TypeId]: TypeId, layout, values }),
|
|
80
|
+
)
|
|
81
|
+
: Result.fail(
|
|
82
|
+
new KeyWidthMismatchError({
|
|
83
|
+
kind: "prefix",
|
|
84
|
+
width,
|
|
85
|
+
actual: values.length,
|
|
86
|
+
}),
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// A complete key already satisfies the prefix width guarantee.
|
|
91
|
+
/**
|
|
92
|
+
* @experimental
|
|
93
|
+
*/
|
|
94
|
+
export const toPrefix = (self: Complete): Prefix =>
|
|
95
|
+
QueryStreamKey.Prefix({
|
|
96
|
+
[TypeId]: TypeId,
|
|
97
|
+
layout: self.layout,
|
|
98
|
+
values: self.values,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @experimental
|
|
103
|
+
*/
|
|
104
|
+
export const values = (
|
|
105
|
+
self: QueryStreamKey,
|
|
106
|
+
): QueryStreamKeyValues.QueryStreamKeyValues => self.values;
|
|
107
|
+
/**
|
|
108
|
+
* @experimental
|
|
109
|
+
*/
|
|
110
|
+
export const layout = (
|
|
111
|
+
self: QueryStreamKey,
|
|
112
|
+
): QueryStreamKeyLayout.QueryStreamKeyLayout => self.layout;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @experimental
|
|
116
|
+
*/
|
|
117
|
+
export const isComplete = (value: unknown): value is Complete =>
|
|
118
|
+
Predicate.hasProperty(value, TypeId) && QueryStreamKey.$is("Complete")(value);
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import * as Array from "effect/Array";
|
|
2
|
+
import * as Data from "effect/Data";
|
|
3
|
+
import * as Option from "effect/Option";
|
|
4
|
+
import * as Order from "effect/Order";
|
|
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";
|
|
9
|
+
|
|
10
|
+
// A bound's key may be a *prefix* of the full key: bounding by `["a"]` means
|
|
11
|
+
// bounding by the whole family of keys that start with `"a"`. To compare
|
|
12
|
+
// bounds and keys uniformly, each is modelled as a "cut"—a position
|
|
13
|
+
// *between* keys: the `predecessor` cut of a prefix sits just before every
|
|
14
|
+
// key extending it, the `successor` cut just after, and an `exact` cut is a
|
|
15
|
+
// full key itself. (This is `convex-helpers`' `compareKeys` model.)
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* One side of a range: a (possibly prefix) key and whether it's included.
|
|
19
|
+
*
|
|
20
|
+
* @experimental
|
|
21
|
+
*/
|
|
22
|
+
export interface KeyBound {
|
|
23
|
+
readonly keyValues: QueryStreamKeyValues.QueryStreamKeyValues;
|
|
24
|
+
readonly inclusive: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Bounds over a stream's key, in _ascending key space_ (`narrow` converts from
|
|
29
|
+
* stream space, where `desc` reverses which end is which).
|
|
30
|
+
*
|
|
31
|
+
* @experimental
|
|
32
|
+
*/
|
|
33
|
+
export interface KeyBounds {
|
|
34
|
+
readonly lower: Option.Option<KeyBound>;
|
|
35
|
+
readonly upper: Option.Option<KeyBound>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Bounds in _full index-key space_: `eq`-pinned values appear as a shared
|
|
40
|
+
* prefix of both keys (`fromBounds` re-derives them as `eq` constraints). An
|
|
41
|
+
* empty key bounds nothing.
|
|
42
|
+
*
|
|
43
|
+
* @experimental
|
|
44
|
+
*/
|
|
45
|
+
export interface IndexBounds {
|
|
46
|
+
readonly lower: KeyBound;
|
|
47
|
+
readonly upper: KeyBound;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
type KeyCut = Data.TaggedEnum<{
|
|
51
|
+
Predecessor: {
|
|
52
|
+
readonly keyValues: QueryStreamKeyValues.QueryStreamKeyValues;
|
|
53
|
+
};
|
|
54
|
+
Exact: { readonly key: QueryStreamKey.Complete };
|
|
55
|
+
Successor: { readonly keyValues: QueryStreamKeyValues.QueryStreamKeyValues };
|
|
56
|
+
}>;
|
|
57
|
+
const KeyCut = Data.taggedEnum<KeyCut>();
|
|
58
|
+
|
|
59
|
+
const cutRank = KeyCut.$match({
|
|
60
|
+
Predecessor: () => 0,
|
|
61
|
+
Exact: () => 1,
|
|
62
|
+
Successor: () => 2,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const cutKeyValues = KeyCut.$match({
|
|
66
|
+
Predecessor: ({ keyValues }) => keyValues,
|
|
67
|
+
Exact: ({ key }) => QueryStreamKey.values(key),
|
|
68
|
+
Successor: ({ keyValues }) => keyValues,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const KeyCutOrder: Order.Order<KeyCut> = Order.make((self, that) => {
|
|
72
|
+
const selfKeyValues = cutKeyValues(self);
|
|
73
|
+
const thatKeyValues = cutKeyValues(that);
|
|
74
|
+
const minLength = Math.min(selfKeyValues.length, thatKeyValues.length);
|
|
75
|
+
const prefixOrdering = QueryStreamKeyValues.Order("asc")(
|
|
76
|
+
Array.take(selfKeyValues, minLength),
|
|
77
|
+
Array.take(thatKeyValues, minLength),
|
|
78
|
+
);
|
|
79
|
+
if (prefixOrdering !== 0) {
|
|
80
|
+
return prefixOrdering;
|
|
81
|
+
}
|
|
82
|
+
if (selfKeyValues.length === thatKeyValues.length) {
|
|
83
|
+
return Order.Number(cutRank(self), cutRank(that));
|
|
84
|
+
}
|
|
85
|
+
// One key is a proper prefix of the other. The shorter cut sits just
|
|
86
|
+
// before (`predecessor`) or just after (`successor`) *every* key
|
|
87
|
+
// extending its prefix—the longer one included. (`exact` cuts are
|
|
88
|
+
// always full keys, so an `exact` cut is never the shorter one here.)
|
|
89
|
+
const selfIsShorter = selfKeyValues.length < thatKeyValues.length;
|
|
90
|
+
const shorter = selfIsShorter ? self : that;
|
|
91
|
+
const shorterOrdering = KeyCut.$match(shorter, {
|
|
92
|
+
Predecessor: () => -1 as const,
|
|
93
|
+
Exact: () => 1 as const,
|
|
94
|
+
Successor: () => 1 as const,
|
|
95
|
+
});
|
|
96
|
+
return selfIsShorter ? shorterOrdering : (-shorterOrdering as -1 | 1);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const lowerCut = (bound: KeyBound): KeyCut =>
|
|
100
|
+
bound.inclusive
|
|
101
|
+
? KeyCut.Predecessor({ keyValues: bound.keyValues })
|
|
102
|
+
: KeyCut.Successor({ keyValues: bound.keyValues });
|
|
103
|
+
|
|
104
|
+
const upperCut = (bound: KeyBound): KeyCut =>
|
|
105
|
+
bound.inclusive
|
|
106
|
+
? KeyCut.Successor({ keyValues: bound.keyValues })
|
|
107
|
+
: KeyCut.Predecessor({ keyValues: bound.keyValues });
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The stricter (later) of two lower bounds.
|
|
111
|
+
*
|
|
112
|
+
* @experimental
|
|
113
|
+
*/
|
|
114
|
+
export const tightestLower = (self: KeyBound, that: KeyBound): KeyBound =>
|
|
115
|
+
Order.isGreaterThan(KeyCutOrder)(lowerCut(that), lowerCut(self))
|
|
116
|
+
? that
|
|
117
|
+
: self;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* The stricter (earlier) of two upper bounds.
|
|
121
|
+
*
|
|
122
|
+
* @experimental
|
|
123
|
+
*/
|
|
124
|
+
export const tightestUpper = (self: KeyBound, that: KeyBound): KeyBound =>
|
|
125
|
+
Order.isLessThan(KeyCutOrder)(upperCut(that), upperCut(self)) ? that : self;
|
|
126
|
+
|
|
127
|
+
const combineKeyBound = (
|
|
128
|
+
self: Option.Option<ParsedBound>,
|
|
129
|
+
that: Option.Option<ParsedBound>,
|
|
130
|
+
combine: (self: ParsedBound, that: ParsedBound) => ParsedBound,
|
|
131
|
+
): Option.Option<ParsedBound> =>
|
|
132
|
+
Option.match(self, {
|
|
133
|
+
onNone: () => that,
|
|
134
|
+
onSome: (first) =>
|
|
135
|
+
Option.some(
|
|
136
|
+
Option.match(that, {
|
|
137
|
+
onNone: () => first,
|
|
138
|
+
onSome: (second) => combine(first, second),
|
|
139
|
+
}),
|
|
140
|
+
),
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* @experimental
|
|
145
|
+
*/
|
|
146
|
+
export const intersect = (
|
|
147
|
+
self: ParsedBounds,
|
|
148
|
+
that: ParsedBounds,
|
|
149
|
+
): Result.Result<ParsedBounds, QueryStreamKeyLayout.KeyLayoutMismatchError> =>
|
|
150
|
+
Result.map(forLayout(self.keyLayout, that), () =>
|
|
151
|
+
make(self.keyLayout, {
|
|
152
|
+
lower: combineKeyBound(self.lower, that.lower, tighterLower),
|
|
153
|
+
upper: combineKeyBound(self.upper, that.upper, tighterUpper),
|
|
154
|
+
}),
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* @experimental
|
|
159
|
+
*/
|
|
160
|
+
export const isEmpty = (indexBounds: IndexBounds): boolean =>
|
|
161
|
+
KeyCutOrder(lowerCut(indexBounds.lower), upperCut(indexBounds.upper)) >= 0;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* @experimental
|
|
165
|
+
*/
|
|
166
|
+
export const intersectIndexBounds = (
|
|
167
|
+
self: IndexBounds,
|
|
168
|
+
that: IndexBounds,
|
|
169
|
+
): IndexBounds => ({
|
|
170
|
+
lower: tightestLower(self.lower, that.lower),
|
|
171
|
+
upper: tightestUpper(self.upper, that.upper),
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Whether a compatible key sits after the lower bound (always, when unbounded).
|
|
176
|
+
*
|
|
177
|
+
* @experimental
|
|
178
|
+
*/
|
|
179
|
+
export const admittedByLower =
|
|
180
|
+
(parsedBounds: ParsedBounds) =>
|
|
181
|
+
(
|
|
182
|
+
key: QueryStreamKey.Complete,
|
|
183
|
+
): Result.Result<boolean, QueryStreamKeyLayout.KeyLayoutMismatchError> =>
|
|
184
|
+
Result.gen(function* () {
|
|
185
|
+
yield* QueryStreamKeyLayout.validateEquivalence(
|
|
186
|
+
parsedBounds.keyLayout,
|
|
187
|
+
key.layout,
|
|
188
|
+
);
|
|
189
|
+
return Option.match(parsedBounds.lower, {
|
|
190
|
+
onNone: () => true,
|
|
191
|
+
onSome: (bound) =>
|
|
192
|
+
KeyCutOrder(KeyCut.Exact({ key }), lowerCut(rawBound(bound))) > 0,
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Whether a compatible key sits before the upper bound (always, when
|
|
198
|
+
* unbounded).
|
|
199
|
+
*
|
|
200
|
+
* @experimental
|
|
201
|
+
*/
|
|
202
|
+
export const admittedByUpper =
|
|
203
|
+
(parsedBounds: ParsedBounds) =>
|
|
204
|
+
(
|
|
205
|
+
key: QueryStreamKey.Complete,
|
|
206
|
+
): Result.Result<boolean, QueryStreamKeyLayout.KeyLayoutMismatchError> =>
|
|
207
|
+
Result.gen(function* () {
|
|
208
|
+
yield* QueryStreamKeyLayout.validateEquivalence(
|
|
209
|
+
parsedBounds.keyLayout,
|
|
210
|
+
key.layout,
|
|
211
|
+
);
|
|
212
|
+
return Option.match(parsedBounds.upper, {
|
|
213
|
+
onNone: () => true,
|
|
214
|
+
onSome: (bound) =>
|
|
215
|
+
KeyCutOrder(KeyCut.Exact({ key }), upperCut(rawBound(bound))) < 0,
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* At least one endpoint in stream order. Omit the other to leave that side
|
|
221
|
+
* unbounded.
|
|
222
|
+
*
|
|
223
|
+
* @experimental
|
|
224
|
+
*/
|
|
225
|
+
export type NarrowBounds =
|
|
226
|
+
| {
|
|
227
|
+
readonly start: KeyBound;
|
|
228
|
+
readonly end?: KeyBound | undefined;
|
|
229
|
+
}
|
|
230
|
+
| {
|
|
231
|
+
readonly start?: KeyBound | undefined;
|
|
232
|
+
readonly end: KeyBound;
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* @experimental
|
|
237
|
+
*/
|
|
238
|
+
export interface ParsedBound {
|
|
239
|
+
readonly key: QueryStreamKey.Prefix;
|
|
240
|
+
readonly inclusive: boolean;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Endpoints validated against a stream layout. Operations that preserve the
|
|
244
|
+
// key space retain these values; coordinate changes construct new endpoints.
|
|
245
|
+
const TypeId = "~@confect/server/QueryStreamKeyBounds";
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* @experimental
|
|
249
|
+
*/
|
|
250
|
+
export interface ParsedBounds {
|
|
251
|
+
readonly [TypeId]: typeof TypeId;
|
|
252
|
+
readonly keyLayout: QueryStreamKeyLayout.QueryStreamKeyLayout;
|
|
253
|
+
readonly lower: Option.Option<ParsedBound>;
|
|
254
|
+
readonly upper: Option.Option<ParsedBound>;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const make = (
|
|
258
|
+
keyLayout: QueryStreamKeyLayout.QueryStreamKeyLayout,
|
|
259
|
+
endpoints: Pick<ParsedBounds, "lower" | "upper">,
|
|
260
|
+
): ParsedBounds => ({
|
|
261
|
+
[TypeId]: TypeId,
|
|
262
|
+
keyLayout,
|
|
263
|
+
lower: endpoints.lower,
|
|
264
|
+
upper: endpoints.upper,
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* @experimental
|
|
269
|
+
*/
|
|
270
|
+
export const unbounded = (
|
|
271
|
+
keyLayout: QueryStreamKeyLayout.QueryStreamKeyLayout,
|
|
272
|
+
): ParsedBounds =>
|
|
273
|
+
make(keyLayout, { lower: Option.none(), upper: Option.none() });
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* @experimental
|
|
277
|
+
*/
|
|
278
|
+
export const forLayout = (
|
|
279
|
+
keyLayout: QueryStreamKeyLayout.QueryStreamKeyLayout,
|
|
280
|
+
parsedBounds: ParsedBounds,
|
|
281
|
+
): Result.Result<ParsedBounds, QueryStreamKeyLayout.KeyLayoutMismatchError> =>
|
|
282
|
+
Result.gen(function* () {
|
|
283
|
+
yield* QueryStreamKeyLayout.validateEquivalence(
|
|
284
|
+
keyLayout,
|
|
285
|
+
parsedBounds.keyLayout,
|
|
286
|
+
);
|
|
287
|
+
return parsedBounds;
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// Combining existing parsed endpoints still needs a shared layout, including
|
|
291
|
+
// when one or both endpoints are absent.
|
|
292
|
+
/**
|
|
293
|
+
* @experimental
|
|
294
|
+
*/
|
|
295
|
+
export const fromParsed = (
|
|
296
|
+
keyLayout: QueryStreamKeyLayout.QueryStreamKeyLayout,
|
|
297
|
+
endpoints: Pick<ParsedBounds, "lower" | "upper">,
|
|
298
|
+
): Result.Result<ParsedBounds, QueryStreamKeyLayout.KeyLayoutMismatchError> => {
|
|
299
|
+
const validateEndpoint = (endpoint: Option.Option<ParsedBound>) =>
|
|
300
|
+
Option.match(endpoint, {
|
|
301
|
+
onNone: () => Result.succeed(undefined),
|
|
302
|
+
onSome: ({ key }) =>
|
|
303
|
+
QueryStreamKeyLayout.validateEquivalence(keyLayout, key.layout),
|
|
304
|
+
});
|
|
305
|
+
return Result.gen(function* () {
|
|
306
|
+
yield* validateEndpoint(endpoints.lower);
|
|
307
|
+
yield* validateEndpoint(endpoints.upper);
|
|
308
|
+
return make(keyLayout, endpoints);
|
|
309
|
+
});
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
const rawBound = (bound: ParsedBound): KeyBound => ({
|
|
313
|
+
keyValues: QueryStreamKey.values(bound.key),
|
|
314
|
+
inclusive: bound.inclusive,
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
// Select existing endpoints so intersection retains their parsed keys.
|
|
318
|
+
const tighterLower = (self: ParsedBound, that: ParsedBound): ParsedBound =>
|
|
319
|
+
KeyCutOrder(lowerCut(rawBound(that)), lowerCut(rawBound(self))) > 0
|
|
320
|
+
? that
|
|
321
|
+
: self;
|
|
322
|
+
|
|
323
|
+
const tighterUpper = (self: ParsedBound, that: ParsedBound): ParsedBound =>
|
|
324
|
+
KeyCutOrder(upperCut(rawBound(that)), upperCut(rawBound(self))) < 0
|
|
325
|
+
? that
|
|
326
|
+
: self;
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* @experimental
|
|
330
|
+
*/
|
|
331
|
+
export const tightestParsedLower = (
|
|
332
|
+
self: ParsedBound,
|
|
333
|
+
that: ParsedBound,
|
|
334
|
+
): Result.Result<ParsedBound, QueryStreamKeyLayout.KeyLayoutMismatchError> =>
|
|
335
|
+
Result.gen(function* () {
|
|
336
|
+
yield* QueryStreamKeyLayout.validateEquivalence(
|
|
337
|
+
self.key.layout,
|
|
338
|
+
that.key.layout,
|
|
339
|
+
);
|
|
340
|
+
return tighterLower(self, that);
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* @experimental
|
|
345
|
+
*/
|
|
346
|
+
export const tightestParsedUpper = (
|
|
347
|
+
self: ParsedBound,
|
|
348
|
+
that: ParsedBound,
|
|
349
|
+
): Result.Result<ParsedBound, QueryStreamKeyLayout.KeyLayoutMismatchError> =>
|
|
350
|
+
Result.gen(function* () {
|
|
351
|
+
yield* QueryStreamKeyLayout.validateEquivalence(
|
|
352
|
+
self.key.layout,
|
|
353
|
+
that.key.layout,
|
|
354
|
+
);
|
|
355
|
+
return tighterUpper(self, that);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* @experimental
|
|
360
|
+
*/
|
|
361
|
+
export const parseBound = (
|
|
362
|
+
keyLayout: QueryStreamKeyLayout.QueryStreamKeyLayout,
|
|
363
|
+
{ keyValues, inclusive }: KeyBound,
|
|
364
|
+
): Result.Result<ParsedBound, QueryStreamKey.KeyWidthMismatchError> =>
|
|
365
|
+
Result.map(QueryStreamKey.prefix(keyLayout, keyValues), (key) => ({
|
|
366
|
+
key,
|
|
367
|
+
inclusive,
|
|
368
|
+
}));
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* @experimental
|
|
372
|
+
*/
|
|
373
|
+
export const parse = (
|
|
374
|
+
keyLayout: QueryStreamKeyLayout.QueryStreamKeyLayout,
|
|
375
|
+
keyBounds: KeyBounds,
|
|
376
|
+
): Result.Result<ParsedBounds, QueryStreamKey.KeyWidthMismatchError> => {
|
|
377
|
+
const endpoint = (bound: Option.Option<KeyBound>) =>
|
|
378
|
+
Option.match(bound, {
|
|
379
|
+
onNone: () => Result.succeed(Option.none<ParsedBound>()),
|
|
380
|
+
onSome: (value) => Result.map(parseBound(keyLayout, value), Option.some),
|
|
381
|
+
});
|
|
382
|
+
return Result.gen(function* () {
|
|
383
|
+
const lower = yield* endpoint(keyBounds.lower);
|
|
384
|
+
const upper = yield* endpoint(keyBounds.upper);
|
|
385
|
+
return make(keyLayout, { lower, upper });
|
|
386
|
+
});
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* @experimental
|
|
391
|
+
*/
|
|
392
|
+
export const toBounds = (parsedBounds: ParsedBounds): KeyBounds => ({
|
|
393
|
+
lower: Option.map(parsedBounds.lower, rawBound),
|
|
394
|
+
upper: Option.map(parsedBounds.upper, rawBound),
|
|
395
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as Brand from "effect/Brand";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Ordered names for the visible components of a stream's ordering key. Names
|
|
5
|
+
* may repeat, and the sequence may be empty. They are aliases, not document
|
|
6
|
+
* field paths; implicit ID positions have no visible label.
|
|
7
|
+
*
|
|
8
|
+
* @experimental
|
|
9
|
+
*/
|
|
10
|
+
export type QueryStreamKeyLabels<
|
|
11
|
+
Names extends ReadonlyArray<string> = ReadonlyArray<string>,
|
|
12
|
+
> = Readonly<Names> & Brand.Brand<"@confect/server/QueryStreamKeyLabels">;
|
|
13
|
+
|
|
14
|
+
// Tuple operations must use the underlying names: spreading a branded tuple
|
|
15
|
+
// directly can widen its fixed positions into an array of element unions.
|
|
16
|
+
// Defer extraction and concatenation until both label types are known to avoid
|
|
17
|
+
// expanding unresolved tuple types while checking generic stream operations.
|
|
18
|
+
/**
|
|
19
|
+
* @experimental
|
|
20
|
+
*/
|
|
21
|
+
export type Concat<
|
|
22
|
+
LeftKeyLabels extends QueryStreamKeyLabels,
|
|
23
|
+
RightKeyLabels extends QueryStreamKeyLabels,
|
|
24
|
+
> =
|
|
25
|
+
LeftKeyLabels extends QueryStreamKeyLabels<infer LeftNames>
|
|
26
|
+
? RightKeyLabels extends QueryStreamKeyLabels<infer RightNames>
|
|
27
|
+
? QueryStreamKeyLabels<readonly [...LeftNames, ...RightNames]>
|
|
28
|
+
: never
|
|
29
|
+
: never;
|
|
30
|
+
|
|
31
|
+
const LabelsBrand = Brand.nominal<QueryStreamKeyLabels>();
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Mark a tuple of names as labels without changing its runtime representation.
|
|
35
|
+
*
|
|
36
|
+
* @experimental
|
|
37
|
+
*/
|
|
38
|
+
export function make<const Names extends ReadonlyArray<string>>(
|
|
39
|
+
names: Names,
|
|
40
|
+
): QueryStreamKeyLabels<Names>;
|
|
41
|
+
export function make(names: ReadonlyArray<string>): QueryStreamKeyLabels {
|
|
42
|
+
return LabelsBrand(names);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Check whether the labels start with the given prefix, including order and
|
|
47
|
+
* multiplicity. The empty prefix always matches.
|
|
48
|
+
*
|
|
49
|
+
* @experimental
|
|
50
|
+
*/
|
|
51
|
+
export const hasPrefix = (
|
|
52
|
+
self: QueryStreamKeyLabels,
|
|
53
|
+
prefixKeyLabels: QueryStreamKeyLabels,
|
|
54
|
+
): boolean =>
|
|
55
|
+
prefixKeyLabels.length <= self.length &&
|
|
56
|
+
prefixKeyLabels.every((label, index) => label === self[index]);
|