effect-app 4.0.0-beta.29 → 4.0.0-beta.291
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 +1397 -0
- package/dist/Array.d.ts +2 -1
- package/dist/Array.d.ts.map +1 -1
- package/dist/Array.js +4 -4
- package/dist/Chunk.d.ts.map +1 -1
- package/dist/Config/SecretURL.d.ts +3 -1
- package/dist/Config/SecretURL.d.ts.map +1 -1
- package/dist/Config/SecretURL.js +3 -6
- package/dist/Config/internal/configSecretURL.d.ts.map +1 -1
- package/dist/Config/internal/configSecretURL.js +2 -2
- package/dist/Config.d.ts +2 -0
- package/dist/Config.d.ts.map +1 -0
- package/dist/Config.js +8 -0
- package/dist/ConfigProvider.d.ts +2 -0
- package/dist/ConfigProvider.d.ts.map +1 -0
- package/dist/ConfigProvider.js +6 -0
- package/dist/{ServiceMap.d.ts → Context.d.ts} +18 -20
- package/dist/Context.d.ts.map +1 -0
- package/dist/Context.js +67 -0
- package/dist/DataDependencies.d.ts +388 -0
- package/dist/DataDependencies.d.ts.map +1 -0
- package/dist/DataDependencies.js +64 -0
- package/dist/Effect.d.ts +10 -9
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +5 -8
- package/dist/Emailer.d.ts +51 -0
- package/dist/Emailer.d.ts.map +1 -0
- package/dist/Emailer.js +7 -0
- package/dist/Function.d.ts.map +1 -1
- package/dist/Layer.d.ts +10 -6
- package/dist/Layer.d.ts.map +1 -1
- package/dist/Layer.js +3 -2
- package/dist/Model/Repository/Registry.d.ts +22 -0
- package/dist/Model/Repository/Registry.d.ts.map +1 -0
- package/dist/Model/Repository/Registry.js +18 -0
- package/dist/Model/Repository/ext.d.ts +60 -0
- package/dist/Model/Repository/ext.d.ts.map +1 -0
- package/dist/Model/Repository/ext.js +122 -0
- package/dist/Model/Repository/internal/internal.d.ts +63 -0
- package/dist/Model/Repository/internal/internal.d.ts.map +1 -0
- package/dist/Model/Repository/internal/internal.js +438 -0
- package/dist/Model/Repository/legacy.d.ts +21 -0
- package/dist/Model/Repository/legacy.d.ts.map +1 -0
- package/dist/Model/Repository/legacy.js +2 -0
- package/dist/Model/Repository/makeRepo.d.ts +54 -0
- package/dist/Model/Repository/makeRepo.d.ts.map +1 -0
- package/dist/Model/Repository/makeRepo.js +27 -0
- package/dist/Model/Repository/service.d.ts +121 -0
- package/dist/Model/Repository/service.d.ts.map +1 -0
- package/dist/Model/Repository/service.js +2 -0
- package/dist/Model/Repository/validation.d.ts +58 -0
- package/dist/Model/Repository/validation.d.ts.map +1 -0
- package/dist/Model/Repository/validation.js +32 -0
- package/dist/Model/Repository.d.ts +7 -0
- package/dist/Model/Repository.d.ts.map +1 -0
- package/dist/Model/Repository.js +7 -0
- package/dist/Model/dsl.d.ts +33 -0
- package/dist/Model/dsl.d.ts.map +1 -0
- package/dist/Model/dsl.js +43 -0
- package/dist/Model/filter/filterApi.d.ts +30 -0
- package/dist/Model/filter/filterApi.d.ts.map +1 -0
- package/dist/Model/filter/filterApi.js +2 -0
- package/dist/Model/filter/types/errors.d.ts +29 -0
- package/dist/Model/filter/types/errors.d.ts.map +1 -0
- package/dist/Model/filter/types/errors.js +2 -0
- package/dist/Model/filter/types/fields.d.ts +15 -0
- package/dist/Model/filter/types/fields.d.ts.map +1 -0
- package/dist/Model/filter/types/fields.js +2 -0
- package/dist/Model/filter/types/path/common.d.ts +316 -0
- package/dist/Model/filter/types/path/common.d.ts.map +1 -0
- package/dist/Model/filter/types/path/common.js +2 -0
- package/dist/Model/filter/types/path/eager.d.ts +94 -0
- package/dist/Model/filter/types/path/eager.d.ts.map +1 -0
- package/dist/Model/filter/types/path/eager.js +36 -0
- package/dist/Model/filter/types/path/index.d.ts +4 -0
- package/dist/Model/filter/types/path/index.d.ts.map +1 -0
- package/dist/Model/filter/types/path/index.js +3 -0
- package/dist/Model/filter/types/utils.d.ts +79 -0
- package/dist/Model/filter/types/utils.d.ts.map +1 -0
- package/dist/Model/filter/types/utils.js +2 -0
- package/dist/Model/filter/types/validator.d.ts +30 -0
- package/dist/Model/filter/types/validator.d.ts.map +1 -0
- package/dist/Model/filter/types/validator.js +2 -0
- package/dist/Model/filter/types.d.ts +5 -0
- package/dist/Model/filter/types.d.ts.map +1 -0
- package/dist/Model/filter/types.js +7 -0
- package/dist/Model/query/dsl.d.ts +506 -0
- package/dist/Model/query/dsl.d.ts.map +1 -0
- package/dist/Model/query/dsl.js +376 -0
- package/dist/Model/query/new-kid-interpreter.d.ts +136 -0
- package/dist/Model/query/new-kid-interpreter.d.ts.map +1 -0
- package/dist/Model/query/new-kid-interpreter.js +336 -0
- package/dist/Model/query.d.ts +15 -0
- package/dist/Model/query.d.ts.map +1 -0
- package/dist/Model/query.js +3 -0
- package/dist/Model.d.ts +5 -0
- package/dist/Model.d.ts.map +1 -0
- package/dist/Model.js +5 -0
- package/dist/NonEmptySet.d.ts +3 -1
- package/dist/NonEmptySet.d.ts.map +1 -1
- package/dist/NonEmptySet.js +2 -2
- package/dist/Option.d.ts +1 -0
- package/dist/Option.d.ts.map +1 -1
- package/dist/Option.js +3 -1
- package/dist/Pure.d.ts +7 -5
- package/dist/Pure.d.ts.map +1 -1
- package/dist/Pure.js +7 -4
- package/dist/QueueMaker.d.ts +11 -0
- package/dist/QueueMaker.d.ts.map +1 -0
- package/dist/QueueMaker.js +11 -0
- package/dist/RequestContext.d.ts +87 -0
- package/dist/RequestContext.d.ts.map +1 -0
- package/dist/RequestContext.js +45 -0
- package/dist/RequestScopedDependencies.d.ts +21 -0
- package/dist/RequestScopedDependencies.d.ts.map +1 -0
- package/dist/RequestScopedDependencies.js +16 -0
- package/dist/Schema/Class.d.ts +188 -19
- package/dist/Schema/Class.d.ts.map +1 -1
- package/dist/Schema/Class.js +260 -17
- package/dist/Schema/FastCheck.d.ts.map +1 -1
- package/dist/Schema/SchemaParser.d.ts +5 -0
- package/dist/Schema/SchemaParser.d.ts.map +1 -0
- package/dist/Schema/SchemaParser.js +6 -0
- package/dist/Schema/SpecialJsonSchema.d.ts +34 -0
- package/dist/Schema/SpecialJsonSchema.d.ts.map +1 -0
- package/dist/Schema/SpecialJsonSchema.js +118 -0
- package/dist/Schema/SpecialOpenApi.d.ts +32 -0
- package/dist/Schema/SpecialOpenApi.d.ts.map +1 -0
- package/dist/Schema/SpecialOpenApi.js +123 -0
- package/dist/Schema/brand.d.ts +4 -2
- package/dist/Schema/brand.d.ts.map +1 -1
- package/dist/Schema/brand.js +3 -1
- package/dist/Schema/email.d.ts.map +1 -1
- package/dist/Schema/email.js +7 -4
- package/dist/Schema/ext.d.ts +338 -55
- package/dist/Schema/ext.d.ts.map +1 -1
- package/dist/Schema/ext.js +358 -53
- package/dist/Schema/moreStrings.d.ts +82 -36
- package/dist/Schema/moreStrings.d.ts.map +1 -1
- package/dist/Schema/moreStrings.js +49 -42
- package/dist/Schema/numbers.d.ts +34 -21
- package/dist/Schema/numbers.d.ts.map +1 -1
- package/dist/Schema/numbers.js +55 -12
- package/dist/Schema/phoneNumber.d.ts.map +1 -1
- package/dist/Schema/phoneNumber.js +6 -3
- package/dist/Schema/schema.d.ts +1 -1
- package/dist/Schema/schema.d.ts.map +1 -1
- package/dist/Schema/schema.js +2 -2
- package/dist/Schema/strings.d.ts +18 -4
- package/dist/Schema/strings.d.ts.map +1 -1
- package/dist/Schema/strings.js +1 -5
- package/dist/Schema.d.ts +222 -8
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +191 -12
- package/dist/SchemaAST.d.ts +2 -0
- package/dist/SchemaAST.d.ts.map +1 -0
- package/dist/SchemaAST.js +2 -0
- package/dist/Set.d.ts +4 -1
- package/dist/Set.d.ts.map +1 -1
- package/dist/Set.js +3 -2
- package/dist/Store.d.ts +163 -0
- package/dist/Store.d.ts.map +1 -0
- package/dist/Store.js +113 -0
- package/dist/_ext/Array.d.ts +1 -1
- package/dist/_ext/Array.d.ts.map +1 -1
- package/dist/_ext/Array.js +4 -2
- package/dist/_ext/misc.d.ts +4 -1
- package/dist/_ext/misc.d.ts.map +1 -1
- package/dist/_ext/misc.js +4 -2
- package/dist/_ext/ord.ext.d.ts +2 -1
- package/dist/_ext/ord.ext.d.ts.map +1 -1
- package/dist/_ext/ord.ext.js +2 -2
- package/dist/builtin.d.ts +2 -14
- package/dist/builtin.d.ts.map +1 -1
- package/dist/builtin.js +1 -1
- package/dist/client/InvalidationKeys.d.ts +29 -0
- package/dist/client/InvalidationKeys.d.ts.map +1 -0
- package/dist/client/InvalidationKeys.js +33 -0
- package/dist/client/apiClientFactory.d.ts +19 -31
- package/dist/client/apiClientFactory.d.ts.map +1 -1
- package/dist/client/apiClientFactory.js +155 -35
- package/dist/client/clientFor.d.ts +54 -18
- package/dist/client/clientFor.d.ts.map +1 -1
- package/dist/client/clientFor.js +9 -1
- package/dist/client/errors.d.ts +82 -27
- package/dist/client/errors.d.ts.map +1 -1
- package/dist/client/errors.js +75 -19
- package/dist/client/makeClient.d.ts +492 -32
- package/dist/client/makeClient.d.ts.map +1 -1
- package/dist/client/makeClient.js +62 -28
- package/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +3 -1
- package/dist/faker.d.ts.map +1 -1
- package/dist/http/Request.d.ts +1 -1
- package/dist/http/Request.d.ts.map +1 -1
- package/dist/http/Request.js +2 -2
- package/dist/ids.d.ts +42 -14
- package/dist/ids.d.ts.map +1 -1
- package/dist/ids.js +30 -5
- package/dist/index.d.ts +6 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -8
- package/dist/middleware.d.ts +13 -7
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +14 -8
- package/dist/rpc/Invalidation.d.ts +3140 -0
- package/dist/rpc/Invalidation.d.ts.map +1 -0
- package/dist/rpc/Invalidation.js +178 -0
- package/dist/rpc/MiddlewareMaker.d.ts +11 -7
- package/dist/rpc/MiddlewareMaker.d.ts.map +1 -1
- package/dist/rpc/MiddlewareMaker.js +59 -38
- package/dist/rpc/RpcContextMap.d.ts +3 -3
- package/dist/rpc/RpcContextMap.d.ts.map +1 -1
- package/dist/rpc/RpcContextMap.js +4 -4
- package/dist/rpc/RpcMiddleware.d.ts +14 -10
- package/dist/rpc/RpcMiddleware.d.ts.map +1 -1
- package/dist/rpc/RpcMiddleware.js +1 -1
- package/dist/rpc.d.ts +1 -1
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +2 -2
- package/dist/runtime.d.ts +19 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +40 -0
- package/dist/setupRequest.d.ts +20 -0
- package/dist/setupRequest.d.ts.map +1 -0
- package/dist/setupRequest.js +72 -0
- package/dist/toast.d.ts +51 -0
- package/dist/toast.d.ts.map +1 -0
- package/dist/toast.js +34 -0
- package/dist/transform.d.ts +1 -1
- package/dist/transform.d.ts.map +1 -1
- package/dist/transform.js +4 -5
- package/dist/utils/effectify.d.ts +1 -1
- package/dist/utils/effectify.d.ts.map +1 -1
- package/dist/utils/effectify.js +2 -2
- package/dist/utils/extend.d.ts.map +1 -1
- package/dist/utils/gen.d.ts +4 -4
- package/dist/utils/gen.d.ts.map +1 -1
- package/dist/utils/logLevel.d.ts +2 -2
- package/dist/utils/logLevel.d.ts.map +1 -1
- package/dist/utils/logger.d.ts +4 -3
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +4 -4
- package/dist/utils.d.ts +34 -39
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +33 -37
- package/dist/validation/validators.d.ts.map +1 -1
- package/dist/validation.d.ts.map +1 -1
- package/dist/withToast.d.ts +30 -0
- package/dist/withToast.d.ts.map +1 -0
- package/dist/withToast.js +64 -0
- package/package.json +22 -251
- package/src/Array.ts +5 -5
- package/src/Chunk.ts +3 -3
- package/src/Config/SecretURL.ts +6 -3
- package/src/Config/internal/configSecretURL.ts +2 -2
- package/src/Config.ts +7 -0
- package/src/ConfigProvider.ts +5 -0
- package/src/{ServiceMap.ts → Context.ts} +56 -63
- package/src/DataDependencies.ts +114 -0
- package/src/Effect.ts +14 -16
- package/src/Emailer.ts +51 -0
- package/src/Inputify.type.ts +1 -1
- package/src/Layer.ts +11 -7
- package/src/Model/Repository/Registry.ts +35 -0
- package/src/Model/Repository/ext.ts +375 -0
- package/src/Model/Repository/internal/internal.ts +755 -0
- package/src/Model/Repository/legacy.ts +29 -0
- package/src/Model/Repository/makeRepo.ts +145 -0
- package/src/Model/Repository/service.ts +676 -0
- package/src/Model/Repository/validation.ts +31 -0
- package/src/Model/Repository.ts +6 -0
- package/src/Model/dsl.ts +129 -0
- package/src/Model/filter/filterApi.ts +60 -0
- package/src/Model/filter/types/errors.ts +47 -0
- package/src/Model/filter/types/fields.ts +50 -0
- package/src/Model/filter/types/path/common.ts +404 -0
- package/src/Model/filter/types/path/eager.ts +329 -0
- package/src/Model/filter/types/path/index.ts +4 -0
- package/src/Model/filter/types/utils.ts +128 -0
- package/src/Model/filter/types/validator.ts +46 -0
- package/src/Model/filter/types.ts +6 -0
- package/src/Model/query/dsl.ts +2781 -0
- package/src/Model/query/new-kid-interpreter.ts +484 -0
- package/src/Model/query.ts +13 -0
- package/src/Model.ts +4 -0
- package/src/NonEmptySet.ts +6 -4
- package/src/Option.ts +2 -0
- package/src/Pure.ts +10 -7
- package/src/QueueMaker.ts +11 -0
- package/src/RequestContext.ts +48 -0
- package/src/RequestScopedDependencies.ts +45 -0
- package/src/Schema/Class.ts +633 -59
- package/src/Schema/SchemaParser.ts +12 -0
- package/src/Schema/SpecialJsonSchema.ts +139 -0
- package/src/Schema/SpecialOpenApi.ts +130 -0
- package/src/Schema/brand.ts +22 -2
- package/src/Schema/email.ts +9 -4
- package/src/Schema/ext.ts +446 -91
- package/src/Schema/moreStrings.ts +147 -68
- package/src/Schema/numbers.ts +97 -28
- package/src/Schema/phoneNumber.ts +9 -5
- package/src/Schema/schema.ts +1 -1
- package/src/Schema/strings.ts +23 -14
- package/src/Schema.ts +397 -26
- package/src/SchemaAST.ts +1 -0
- package/src/Set.ts +6 -2
- package/src/Store.ts +273 -0
- package/src/_ext/Array.ts +4 -2
- package/src/_ext/misc.ts +4 -1
- package/src/_ext/ord.ext.ts +2 -1
- package/src/builtin-json.d.ts +24 -0
- package/src/builtin.ts +16 -21
- package/src/client/InvalidationKeys.ts +50 -0
- package/src/client/apiClientFactory.ts +299 -134
- package/src/client/clientFor.ts +107 -34
- package/src/client/errors.ts +100 -29
- package/src/client/makeClient.ts +586 -78
- package/src/client.ts +6 -4
- package/src/http/Request.ts +3 -3
- package/src/http.ts +1 -1
- package/src/ids.ts +33 -6
- package/src/index.ts +20 -23
- package/src/middleware.ts +13 -9
- package/src/rpc/Invalidation.ts +278 -0
- package/src/rpc/MiddlewareMaker.ts +88 -80
- package/src/rpc/README.md +2 -2
- package/src/rpc/RpcContextMap.ts +7 -6
- package/src/rpc/RpcMiddleware.ts +19 -13
- package/src/rpc.ts +4 -4
- package/src/runtime.ts +56 -0
- package/src/setupRequest.ts +138 -0
- package/src/toast.ts +54 -0
- package/src/transform.ts +4 -4
- package/src/utils/effectify.ts +1 -1
- package/src/utils/gen.ts +8 -8
- package/src/utils/logLevel.ts +1 -1
- package/src/utils/logger.ts +4 -3
- package/src/utils.ts +85 -158
- package/src/validation.ts +2 -2
- package/src/withToast.ts +133 -0
- package/test/dist/rpc.test.d.ts.map +1 -1
- package/test/dist/secretURL.test.d.ts.map +1 -0
- package/test/dist/special.test.d.ts.map +1 -0
- package/test/moreStrings.test.ts +1 -1
- package/test/rpc.test.ts +45 -6
- package/test/schema.test.ts +459 -30
- package/test/secretURL.test.ts +160 -0
- package/test/special.test.ts +1258 -0
- package/test/utils.test.ts +7 -7
- package/tsconfig.base.json +6 -5
- package/tsconfig.json +3 -1
- package/tsconfig.src.json +29 -29
- package/tsconfig.test.json +2 -2
- package/dist/Operations.d.ts +0 -123
- package/dist/Operations.d.ts.map +0 -1
- package/dist/Operations.js +0 -29
- package/dist/ServiceMap.d.ts.map +0 -1
- package/dist/ServiceMap.js +0 -91
- package/eslint.config.mjs +0 -26
- package/src/Operations.ts +0 -55
- package/tsconfig.json.bak +0 -12
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
3
|
+
import { identity, pipe } from "effect/Function"
|
|
4
|
+
import * as Match from "effect/Match"
|
|
5
|
+
import * as Array from "../../Array.ts"
|
|
6
|
+
import { toNonEmptyArray } from "../../Array.ts"
|
|
7
|
+
import * as Option from "../../Option.ts"
|
|
8
|
+
import * as S from "../../Schema.ts"
|
|
9
|
+
import * as SchemaAST from "../../SchemaAST.ts"
|
|
10
|
+
import { dropUndefinedT } from "../../utils.ts"
|
|
11
|
+
import type { FilterResult } from "../filter/filterApi.ts"
|
|
12
|
+
import type { FieldValues } from "../filter/types.ts"
|
|
13
|
+
import type { FieldPath } from "../filter/types/path/eager.ts"
|
|
14
|
+
import { make, type Q, type QAll } from "../query/dsl.ts"
|
|
15
|
+
|
|
16
|
+
export type AggregateIrExpression =
|
|
17
|
+
| { readonly _tag: "agg-count" }
|
|
18
|
+
| { readonly _tag: "agg-count-when"; readonly filter: readonly FilterResult[] }
|
|
19
|
+
| { readonly _tag: "agg-sum"; readonly field: string }
|
|
20
|
+
| { readonly _tag: "agg-min"; readonly field: string }
|
|
21
|
+
| { readonly _tag: "agg-max"; readonly field: string }
|
|
22
|
+
|
|
23
|
+
export type AggregateIrItem =
|
|
24
|
+
| AggregateIrExpression
|
|
25
|
+
| { readonly _tag: "agg-field"; readonly path: string }
|
|
26
|
+
|
|
27
|
+
export type ComputedProjectionMathIrExpression =
|
|
28
|
+
| {
|
|
29
|
+
readonly _tag: "field"
|
|
30
|
+
readonly field: string
|
|
31
|
+
}
|
|
32
|
+
| {
|
|
33
|
+
readonly _tag: "mul"
|
|
34
|
+
readonly left: ComputedProjectionMathIrExpression
|
|
35
|
+
readonly right: ComputedProjectionMathIrExpression
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type ComputedProjectionIrExpression =
|
|
39
|
+
| {
|
|
40
|
+
readonly _tag: "relation-count"
|
|
41
|
+
readonly path: string
|
|
42
|
+
readonly filter: readonly FilterResult[]
|
|
43
|
+
}
|
|
44
|
+
| {
|
|
45
|
+
readonly _tag: "relation-any"
|
|
46
|
+
readonly path: string
|
|
47
|
+
readonly filter: readonly FilterResult[]
|
|
48
|
+
}
|
|
49
|
+
| {
|
|
50
|
+
readonly _tag: "relation-every"
|
|
51
|
+
readonly path: string
|
|
52
|
+
readonly filter: readonly FilterResult[]
|
|
53
|
+
}
|
|
54
|
+
| {
|
|
55
|
+
readonly _tag: "relation-distinct-count"
|
|
56
|
+
readonly path: string
|
|
57
|
+
readonly field: string
|
|
58
|
+
readonly filter: readonly FilterResult[]
|
|
59
|
+
}
|
|
60
|
+
| {
|
|
61
|
+
readonly _tag: "relation-sum"
|
|
62
|
+
readonly path: string
|
|
63
|
+
readonly field: string
|
|
64
|
+
readonly filter: readonly FilterResult[]
|
|
65
|
+
}
|
|
66
|
+
| {
|
|
67
|
+
readonly _tag: "relation-sum-expr"
|
|
68
|
+
readonly path: string
|
|
69
|
+
readonly expression: ComputedProjectionMathIrExpression
|
|
70
|
+
readonly filter: readonly FilterResult[]
|
|
71
|
+
}
|
|
72
|
+
| {
|
|
73
|
+
readonly _tag: "relation-sum-expr-by"
|
|
74
|
+
readonly path: string
|
|
75
|
+
readonly expression: ComputedProjectionMathIrExpression
|
|
76
|
+
readonly unit: string
|
|
77
|
+
readonly filter: readonly FilterResult[]
|
|
78
|
+
}
|
|
79
|
+
| {
|
|
80
|
+
readonly _tag: "relation-sum-expr-normalized"
|
|
81
|
+
readonly path: string
|
|
82
|
+
readonly expression: ComputedProjectionMathIrExpression
|
|
83
|
+
readonly unit: string
|
|
84
|
+
readonly toBase: string
|
|
85
|
+
readonly factors: Readonly<Record<string, number>>
|
|
86
|
+
readonly filter: readonly FilterResult[]
|
|
87
|
+
}
|
|
88
|
+
| {
|
|
89
|
+
readonly _tag: "relation-collect"
|
|
90
|
+
readonly path: string
|
|
91
|
+
readonly field: string
|
|
92
|
+
readonly distinct: boolean
|
|
93
|
+
readonly filter: readonly FilterResult[]
|
|
94
|
+
}
|
|
95
|
+
| {
|
|
96
|
+
readonly _tag: "relation-collect-fields"
|
|
97
|
+
readonly path: string
|
|
98
|
+
readonly fields: readonly string[]
|
|
99
|
+
readonly distinct: boolean
|
|
100
|
+
readonly filter: readonly FilterResult[]
|
|
101
|
+
}
|
|
102
|
+
| {
|
|
103
|
+
readonly _tag: "relation-length"
|
|
104
|
+
readonly path: string
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
type Result<TFieldValues extends FieldValues, A = TFieldValues, R = never> = {
|
|
108
|
+
filter: FilterResult[]
|
|
109
|
+
schema: S.Codec<A, TFieldValues, R> | undefined
|
|
110
|
+
limit: number | undefined
|
|
111
|
+
skip: number | undefined
|
|
112
|
+
order: { key: FieldPath<TFieldValues>; direction: "ASC" | "DESC" }[]
|
|
113
|
+
ttype: "one" | "many" | "count" | undefined
|
|
114
|
+
mode: "collect" | "project" | "transform" | "aggregate" | undefined
|
|
115
|
+
computed: Record<string, ComputedProjectionIrExpression> | undefined
|
|
116
|
+
aggregateMap: Record<string, AggregateIrItem> | undefined
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const interpret = <
|
|
120
|
+
TFieldValues extends FieldValues,
|
|
121
|
+
TFieldValuesRefined extends TFieldValues = TFieldValues,
|
|
122
|
+
A = TFieldValues,
|
|
123
|
+
R = never
|
|
124
|
+
>(_: QAll<TFieldValues, TFieldValuesRefined, A, R>) => {
|
|
125
|
+
const a = _ as Q<TFieldValues>
|
|
126
|
+
|
|
127
|
+
const data: Result<TFieldValues, any, any> = {
|
|
128
|
+
filter: [],
|
|
129
|
+
schema: undefined,
|
|
130
|
+
limit: undefined,
|
|
131
|
+
skip: undefined,
|
|
132
|
+
order: [],
|
|
133
|
+
ttype: undefined,
|
|
134
|
+
mode: undefined,
|
|
135
|
+
computed: undefined,
|
|
136
|
+
aggregateMap: undefined
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const upd = (
|
|
140
|
+
v: Result<TFieldValues, any, any>
|
|
141
|
+
) => {
|
|
142
|
+
data.filter.push(...v.filter)
|
|
143
|
+
data.order.push(...v.order)
|
|
144
|
+
if (v.limit !== undefined) data.limit = v.limit
|
|
145
|
+
if (v.skip !== undefined) data.skip = v.skip
|
|
146
|
+
if (v.ttype !== undefined) data.ttype = v.ttype
|
|
147
|
+
if (v.schema !== undefined) data.schema = v.schema
|
|
148
|
+
if (v.mode !== undefined) data.mode = v.mode
|
|
149
|
+
if (v.computed !== undefined) data.computed = v.computed
|
|
150
|
+
if (v.aggregateMap !== undefined) data.aggregateMap = v.aggregateMap
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const applyPath = (path: string) => (_: FilterResult): FilterResult =>
|
|
154
|
+
_.t === "where" || _.t === "and" || _.t === "or"
|
|
155
|
+
? { ..._, path: `${path}.-1.${_.path}` }
|
|
156
|
+
: { ..._, result: _.result.map(applyPath(path)) }
|
|
157
|
+
|
|
158
|
+
pipe(
|
|
159
|
+
a,
|
|
160
|
+
Match.valueTags({
|
|
161
|
+
value: () => {
|
|
162
|
+
// data.filter.push(value)
|
|
163
|
+
},
|
|
164
|
+
where: ({ current, operation, relation, subPath }) => {
|
|
165
|
+
upd(interpret(current))
|
|
166
|
+
if (typeof operation === "function") {
|
|
167
|
+
data.filter.push(
|
|
168
|
+
{
|
|
169
|
+
t: "where-scope",
|
|
170
|
+
result: interpret(operation(make())).filter.map(subPath ? applyPath(subPath) : identity),
|
|
171
|
+
relation
|
|
172
|
+
}
|
|
173
|
+
)
|
|
174
|
+
} else {
|
|
175
|
+
data.filter.push(
|
|
176
|
+
{
|
|
177
|
+
t: "where",
|
|
178
|
+
path: operation[0],
|
|
179
|
+
op: operation.length === 2 ? "eq" : operation[1],
|
|
180
|
+
value: operation.length === 2 ? operation[1] : operation[2]
|
|
181
|
+
}
|
|
182
|
+
)
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
and: ({ current, operation, relation }) => {
|
|
186
|
+
upd(interpret(current))
|
|
187
|
+
if (typeof operation === "function") {
|
|
188
|
+
data.filter.push(
|
|
189
|
+
{ t: "and-scope", result: interpret(operation(make())).filter, relation }
|
|
190
|
+
)
|
|
191
|
+
} else {
|
|
192
|
+
data.filter.push(
|
|
193
|
+
{
|
|
194
|
+
t: "and",
|
|
195
|
+
path: operation[0],
|
|
196
|
+
op: operation.length === 2 ? "eq" : operation[1],
|
|
197
|
+
value: operation.length === 2 ? operation[1] : operation[2]
|
|
198
|
+
}
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
or: ({ current, operation, relation }) => {
|
|
203
|
+
upd(interpret(current))
|
|
204
|
+
if (typeof operation === "function") {
|
|
205
|
+
data.filter.push(
|
|
206
|
+
{ t: "or-scope", result: interpret(operation(make())).filter, relation }
|
|
207
|
+
)
|
|
208
|
+
} else {
|
|
209
|
+
data.filter.push(
|
|
210
|
+
{
|
|
211
|
+
t: "or",
|
|
212
|
+
path: operation[0],
|
|
213
|
+
op: operation.length === 2 ? "eq" : operation[1],
|
|
214
|
+
value: operation.length === 2 ? operation[1] : operation[2]
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
one: ({ current }) => {
|
|
220
|
+
upd(interpret(current))
|
|
221
|
+
data.limit = 1
|
|
222
|
+
data.ttype = "one"
|
|
223
|
+
},
|
|
224
|
+
count: ({ current }) => {
|
|
225
|
+
upd(interpret(current))
|
|
226
|
+
data.ttype = "count"
|
|
227
|
+
data.schema = S.Struct({ id: S.String }) as any
|
|
228
|
+
},
|
|
229
|
+
order: ({ current, direction, field }) => {
|
|
230
|
+
upd(interpret(current))
|
|
231
|
+
data.order.push({ key: field, direction })
|
|
232
|
+
},
|
|
233
|
+
page: (v) => {
|
|
234
|
+
upd(interpret(v.current))
|
|
235
|
+
data.limit = v.take
|
|
236
|
+
data.skip = v.skip
|
|
237
|
+
},
|
|
238
|
+
project: (v) => {
|
|
239
|
+
upd(interpret(v.current))
|
|
240
|
+
if (v.mode === "aggregate" && v.aggregateMap) {
|
|
241
|
+
data.schema = v.schema
|
|
242
|
+
data.mode = "aggregate"
|
|
243
|
+
data.aggregateMap = Object.fromEntries(
|
|
244
|
+
Object.entries(v.aggregateMap).map(([key, expression]) => {
|
|
245
|
+
switch (expression._tag) {
|
|
246
|
+
case "agg-field":
|
|
247
|
+
return [key, { _tag: "agg-field" as const, path: expression.path }]
|
|
248
|
+
case "agg-count":
|
|
249
|
+
return [key, { _tag: "agg-count" as const }]
|
|
250
|
+
case "agg-count-when": {
|
|
251
|
+
const filter = interpret(expression.operation(make())).filter
|
|
252
|
+
return [key, { _tag: "agg-count-when" as const, filter }]
|
|
253
|
+
}
|
|
254
|
+
case "agg-sum":
|
|
255
|
+
return [key, { _tag: "agg-sum" as const, field: expression.field }]
|
|
256
|
+
case "agg-min":
|
|
257
|
+
return [key, { _tag: "agg-min" as const, field: expression.field }]
|
|
258
|
+
case "agg-max":
|
|
259
|
+
return [key, { _tag: "agg-max" as const, field: expression.field }]
|
|
260
|
+
}
|
|
261
|
+
})
|
|
262
|
+
)
|
|
263
|
+
return
|
|
264
|
+
}
|
|
265
|
+
if (v.computed && v.mode === "transform") {
|
|
266
|
+
throw new Error("Computed projections require mode 'project' or 'collect', not 'transform'")
|
|
267
|
+
}
|
|
268
|
+
data.schema = v.schema
|
|
269
|
+
data.mode = v.computed
|
|
270
|
+
? v.mode === "collect" ? "collect" : "project"
|
|
271
|
+
: v.mode
|
|
272
|
+
data.computed = v.computed
|
|
273
|
+
? Object.fromEntries(
|
|
274
|
+
Object.entries(v.computed).map(([key, expression]) => {
|
|
275
|
+
const e = expression
|
|
276
|
+
const op = "operation" in e ? e.operation : undefined
|
|
277
|
+
const filter = op ? interpret(op(make())).filter.map(applyPath(e.path)) : []
|
|
278
|
+
switch (e._tag) {
|
|
279
|
+
case "relation-count":
|
|
280
|
+
case "relation-any":
|
|
281
|
+
case "relation-every":
|
|
282
|
+
return [key, { _tag: e._tag, path: e.path, filter } as ComputedProjectionIrExpression]
|
|
283
|
+
case "relation-distinct-count":
|
|
284
|
+
case "relation-sum":
|
|
285
|
+
return [
|
|
286
|
+
key,
|
|
287
|
+
{ _tag: e._tag, path: e.path, field: e.field, filter } as ComputedProjectionIrExpression
|
|
288
|
+
]
|
|
289
|
+
case "relation-sum-expr":
|
|
290
|
+
return [
|
|
291
|
+
key,
|
|
292
|
+
{ _tag: e._tag, path: e.path, expression: e.expression, filter } as ComputedProjectionIrExpression
|
|
293
|
+
]
|
|
294
|
+
case "relation-sum-expr-by":
|
|
295
|
+
return [
|
|
296
|
+
key,
|
|
297
|
+
{
|
|
298
|
+
_tag: e._tag,
|
|
299
|
+
path: e.path,
|
|
300
|
+
expression: e.expression,
|
|
301
|
+
unit: e.unit,
|
|
302
|
+
filter
|
|
303
|
+
} as ComputedProjectionIrExpression
|
|
304
|
+
]
|
|
305
|
+
case "relation-sum-expr-normalized":
|
|
306
|
+
return [
|
|
307
|
+
key,
|
|
308
|
+
{
|
|
309
|
+
_tag: e._tag,
|
|
310
|
+
path: e.path,
|
|
311
|
+
expression: e.expression,
|
|
312
|
+
unit: e.unit,
|
|
313
|
+
toBase: e.toBase,
|
|
314
|
+
factors: e.factors,
|
|
315
|
+
filter
|
|
316
|
+
} as ComputedProjectionIrExpression
|
|
317
|
+
]
|
|
318
|
+
case "relation-collect":
|
|
319
|
+
return [
|
|
320
|
+
key,
|
|
321
|
+
{
|
|
322
|
+
_tag: e._tag,
|
|
323
|
+
path: e.path,
|
|
324
|
+
field: e.field,
|
|
325
|
+
distinct: e.distinct,
|
|
326
|
+
filter
|
|
327
|
+
} as ComputedProjectionIrExpression
|
|
328
|
+
]
|
|
329
|
+
case "relation-collect-fields":
|
|
330
|
+
return [
|
|
331
|
+
key,
|
|
332
|
+
{
|
|
333
|
+
_tag: e._tag,
|
|
334
|
+
path: e.path,
|
|
335
|
+
fields: e.fields,
|
|
336
|
+
distinct: e.distinct,
|
|
337
|
+
filter
|
|
338
|
+
} as ComputedProjectionIrExpression
|
|
339
|
+
]
|
|
340
|
+
case "relation-length":
|
|
341
|
+
return [key, { _tag: e._tag, path: e.path } as ComputedProjectionIrExpression]
|
|
342
|
+
}
|
|
343
|
+
})
|
|
344
|
+
)
|
|
345
|
+
: undefined
|
|
346
|
+
}
|
|
347
|
+
})
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
return data
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const walkTransformation = (t: S.AST.AST): S.AST.AST => {
|
|
354
|
+
if (S.AST.isDeclaration(t) && t.typeParameters.length > 0) {
|
|
355
|
+
return walkTransformation(t.typeParameters[0]!)
|
|
356
|
+
}
|
|
357
|
+
return t
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export const toFilter = <
|
|
361
|
+
TFieldValues extends FieldValues,
|
|
362
|
+
A,
|
|
363
|
+
R,
|
|
364
|
+
TFieldValuesRefined extends TFieldValues = TFieldValues
|
|
365
|
+
>(
|
|
366
|
+
q: QAll<TFieldValues, TFieldValuesRefined, A, R>,
|
|
367
|
+
baseSchema?: S.Schema<unknown>
|
|
368
|
+
) => {
|
|
369
|
+
// TODO: Native interpreter for each db adapter, instead of the intermediate "new-kid" format
|
|
370
|
+
const a = interpret(q)
|
|
371
|
+
|
|
372
|
+
// Aggregate mode: build select entirely from aggregateMap (no schema-driven field list)
|
|
373
|
+
if (a.mode === "aggregate" && a.aggregateMap) {
|
|
374
|
+
const aggSelect = Object.entries(a.aggregateMap).map(([key, item]) => {
|
|
375
|
+
if (item._tag === "agg-field") {
|
|
376
|
+
return { key, path: item.path }
|
|
377
|
+
}
|
|
378
|
+
return { key, aggregate: item }
|
|
379
|
+
})
|
|
380
|
+
return dropUndefinedT({
|
|
381
|
+
t: null as unknown as TFieldValues,
|
|
382
|
+
limit: a.limit,
|
|
383
|
+
skip: a.skip,
|
|
384
|
+
select: Option.getOrUndefined(toNonEmptyArray(aggSelect)) as any,
|
|
385
|
+
schema: a.schema,
|
|
386
|
+
computed: undefined,
|
|
387
|
+
order: Option.getOrUndefined(toNonEmptyArray(a.order)),
|
|
388
|
+
ttype: a.ttype,
|
|
389
|
+
mode: "aggregate" as const,
|
|
390
|
+
filter: a.filter.length ? a.filter : undefined
|
|
391
|
+
})
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const schema = a.schema
|
|
395
|
+
let select: (keyof TFieldValues | { key: string; subKeys: string[] } | {
|
|
396
|
+
key: string
|
|
397
|
+
computed: ComputedProjectionIrExpression
|
|
398
|
+
})[] = []
|
|
399
|
+
// TODO: support more complex (nested) schemas?
|
|
400
|
+
if (schema) {
|
|
401
|
+
const t = walkTransformation(SchemaAST.toEncoded(schema.ast))
|
|
402
|
+
if (S.AST.isObjects(t)) {
|
|
403
|
+
select = t.propertySignatures.map((_) => _.name as string)
|
|
404
|
+
for (const prop of t.propertySignatures) {
|
|
405
|
+
if (S.AST.isArrays(prop.type)) {
|
|
406
|
+
// make sure we only select when there are actually type literals in the tuple...
|
|
407
|
+
// otherwise we might be dealing with strings etc.
|
|
408
|
+
// TODO; be more strict, can't support arrays with unions that have non TypeLiteral members etc..
|
|
409
|
+
const arraySelect = {
|
|
410
|
+
key: prop.name as string,
|
|
411
|
+
subKeys: Array.flatMap(
|
|
412
|
+
prop.type.rest,
|
|
413
|
+
(x) => {
|
|
414
|
+
const t = walkTransformation(x)
|
|
415
|
+
return S.AST.isObjects(t) ? t.propertySignatures.map((y) => y.name as string) : []
|
|
416
|
+
}
|
|
417
|
+
)
|
|
418
|
+
}
|
|
419
|
+
if (arraySelect.subKeys.length > 0) {
|
|
420
|
+
select.push(arraySelect)
|
|
421
|
+
// make sure we don't double select?
|
|
422
|
+
if (select.includes(prop.name as string)) {
|
|
423
|
+
select.splice(select.indexOf(prop.name as string), 1)
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
const computed = a.computed
|
|
431
|
+
const getSelectKey = (_: (typeof select)[number]) => {
|
|
432
|
+
if (typeof _ === "string") {
|
|
433
|
+
return _
|
|
434
|
+
}
|
|
435
|
+
if (typeof _ === "object" && _ !== null && "key" in _) {
|
|
436
|
+
return _.key
|
|
437
|
+
}
|
|
438
|
+
return String(_)
|
|
439
|
+
}
|
|
440
|
+
const schemaKeys = select.map(getSelectKey)
|
|
441
|
+
const nonEncodedSchemaKeys = (() => {
|
|
442
|
+
if (!baseSchema) {
|
|
443
|
+
return [] as string[]
|
|
444
|
+
}
|
|
445
|
+
const encoded = walkTransformation(SchemaAST.toEncoded(baseSchema.ast))
|
|
446
|
+
if (!S.AST.isObjects(encoded)) {
|
|
447
|
+
return [] as string[]
|
|
448
|
+
}
|
|
449
|
+
const encodedKeys = encoded.propertySignatures.map((_) => _.name as string)
|
|
450
|
+
return schemaKeys.filter((key) => !encodedKeys.includes(key))
|
|
451
|
+
})()
|
|
452
|
+
const missingComputedKeys = nonEncodedSchemaKeys.filter((key) => !(computed && key in computed))
|
|
453
|
+
|
|
454
|
+
if (Array.isArrayNonEmpty(missingComputedKeys)) {
|
|
455
|
+
throw new Error(`Missing computed projections for schema keys: ${missingComputedKeys.join(", ")}`)
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
if (computed) {
|
|
459
|
+
const computedKeys = Object.keys(computed)
|
|
460
|
+
const extraComputedKeys = computedKeys.filter((key) => !schemaKeys.includes(key))
|
|
461
|
+
if (Array.isArrayNonEmpty(extraComputedKeys)) {
|
|
462
|
+
throw new Error(`Computed projection keys must exist in projection schema: ${extraComputedKeys.join(", ")}`)
|
|
463
|
+
}
|
|
464
|
+
select = select.filter((_) => {
|
|
465
|
+
const key = getSelectKey(_)
|
|
466
|
+
return !(key in computed)
|
|
467
|
+
})
|
|
468
|
+
select.push(...Object.entries(computed).map(([key, expression]) => ({ key, computed: expression })))
|
|
469
|
+
}
|
|
470
|
+
return dropUndefinedT({
|
|
471
|
+
t: null as unknown as TFieldValues,
|
|
472
|
+
limit: a.limit,
|
|
473
|
+
skip: a.skip,
|
|
474
|
+
select: Option.getOrUndefined(toNonEmptyArray(select)),
|
|
475
|
+
schema,
|
|
476
|
+
computed,
|
|
477
|
+
order: Option.getOrUndefined(toNonEmptyArray(a.order)),
|
|
478
|
+
ttype: a.ttype,
|
|
479
|
+
mode: a.mode ?? "transform",
|
|
480
|
+
filter: a.filter.length
|
|
481
|
+
? a.filter
|
|
482
|
+
: undefined
|
|
483
|
+
})
|
|
484
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from "./query/dsl.ts"
|
|
2
|
+
export * from "./query/new-kid-interpreter.ts"
|
|
3
|
+
|
|
4
|
+
export interface RawQuery<Encoded, Out> {
|
|
5
|
+
cosmos: (vals: { name: string }) => {
|
|
6
|
+
query: string
|
|
7
|
+
parameters: {
|
|
8
|
+
name: string
|
|
9
|
+
value: any
|
|
10
|
+
}[]
|
|
11
|
+
}
|
|
12
|
+
memory: (t: readonly Encoded[]) => readonly Out[]
|
|
13
|
+
}
|
package/src/Model.ts
ADDED
package/src/NonEmptySet.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { type Equivalence, Option, type Order } from "effect"
|
|
2
1
|
import type { NonEmptyReadonlyArray } from "effect/Array"
|
|
3
|
-
import
|
|
4
|
-
import
|
|
2
|
+
import type * as Equivalence from "effect/Equivalence"
|
|
3
|
+
import * as Option from "effect/Option"
|
|
4
|
+
import type * as Order from "effect/Order"
|
|
5
|
+
import { flow, pipe } from "./Function.ts"
|
|
6
|
+
import { filter_, filterMap, filterMap_, fromArray as fromArrayOriginal, insert as insertOriginal, insert_ as insert_Original, map, map_, reduce, reduce_, remove, remove_, type Set, toArray as toArrayOriginal } from "./Set.ts"
|
|
5
7
|
|
|
6
8
|
export interface NonEmptyBrand {
|
|
7
9
|
readonly NonEmpty: unique symbol
|
|
@@ -87,4 +89,4 @@ export function fromSet<A>(set: Set<A>) {
|
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
// TODO
|
|
90
|
-
export * from "./Set.
|
|
92
|
+
export * from "./Set.ts"
|
package/src/Option.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
4
4
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
5
|
+
// eslint-disable-next-line import/no-unassigned-import
|
|
6
|
+
import "./builtin.ts"
|
|
5
7
|
import { getOrUndefined as value, type Some } from "effect/Option"
|
|
6
8
|
import * as Option from "effect/Option"
|
|
7
9
|
|
package/src/Pure.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import * as
|
|
2
|
+
import * as Chunk from "effect/Chunk"
|
|
3
|
+
import * as Effect from "effect/Effect"
|
|
4
|
+
import * as Layer from "effect/Layer"
|
|
5
|
+
import * as Result from "effect/Result"
|
|
6
|
+
import * as Context from "./Context.ts"
|
|
7
|
+
import { tuple } from "./Function.ts"
|
|
5
8
|
|
|
6
9
|
const S1 = Symbol()
|
|
7
10
|
const S2 = Symbol()
|
|
@@ -86,9 +89,9 @@ export function GMU<W, S, S2, GA, MR, ME>(modify: (i: GA) => Pure<W, S, S2, MR,
|
|
|
86
89
|
) => GMU_(get, modify, update)
|
|
87
90
|
}
|
|
88
91
|
|
|
89
|
-
const tagg =
|
|
92
|
+
const tagg = Context.Service<{ env: PureEnv<never, unknown, never> }>("PureEnv")
|
|
90
93
|
function castTag<W, S, S2>() {
|
|
91
|
-
return tagg as any as
|
|
94
|
+
return tagg as any as Context.Service<PureEnvEnv<W, S, S2>, PureEnvEnv<W, S, S2>>
|
|
92
95
|
}
|
|
93
96
|
|
|
94
97
|
export const ServiceTag = Symbol()
|
|
@@ -100,9 +103,9 @@ export abstract class PhantomTypeParameter<Identifier extends keyof any, Instant
|
|
|
100
103
|
}
|
|
101
104
|
}
|
|
102
105
|
|
|
103
|
-
export type ServiceShape<T extends
|
|
106
|
+
export type ServiceShape<T extends Context.ServiceClass.Shape<any, any>> = Omit<
|
|
104
107
|
T,
|
|
105
|
-
keyof
|
|
108
|
+
keyof Context.ServiceClass.Shape<any, any>
|
|
106
109
|
>
|
|
107
110
|
|
|
108
111
|
export abstract class ServiceTagged<ServiceKey> extends PhantomTypeParameter<string, ServiceKey> {}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { RequestContext } from "./RequestContext.ts"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Per-message context envelope (tenant/store id, request metadata) carried
|
|
5
|
+
* alongside message-schema payloads. Alias of {@link RequestContext}.
|
|
6
|
+
*
|
|
7
|
+
* All that remains of the former queue machinery (SB/SQLite/mem `QueueMaker`
|
|
8
|
+
* implementations and the `QueueBase` interface) after the move to cluster
|
|
9
|
+
* entities — the message schemas that embed it still reference this envelope.
|
|
10
|
+
*/
|
|
11
|
+
export const QueueMeta = RequestContext
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as Context from "./Context.ts"
|
|
2
|
+
import { UserProfileId } from "./ids.ts"
|
|
3
|
+
import * as S from "./Schema.ts"
|
|
4
|
+
import { NonEmptyString255 } from "./Schema.ts"
|
|
5
|
+
|
|
6
|
+
export const Locale = S.Literals(["en", "de"])
|
|
7
|
+
export type Locale = typeof Locale.Type
|
|
8
|
+
|
|
9
|
+
export class LocaleRef extends Context.Reference("Locale", { defaultValue: (): Locale => "en" }) {}
|
|
10
|
+
|
|
11
|
+
export class RequestContext extends S.Opaque<RequestContext>()(S.Struct({
|
|
12
|
+
span: S.Struct({
|
|
13
|
+
traceId: S.String,
|
|
14
|
+
spanId: S.String,
|
|
15
|
+
sampled: S.Boolean
|
|
16
|
+
}),
|
|
17
|
+
name: NonEmptyString255,
|
|
18
|
+
locale: Locale,
|
|
19
|
+
sourceId: S.optional(NonEmptyString255), // TODO?
|
|
20
|
+
namespace: NonEmptyString255,
|
|
21
|
+
/** @deprecated */
|
|
22
|
+
userProfile: S.optional(S.Struct({ sub: UserProfileId })) //
|
|
23
|
+
})) {
|
|
24
|
+
static toMonitoring(this: void, self: RequestContext) {
|
|
25
|
+
return {
|
|
26
|
+
operationName: self.name,
|
|
27
|
+
locale: self.locale
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const spanAttributes = (ctx: Pick<RequestContext, "locale" | "namespace"> & Partial<RequestContext>) => ({
|
|
33
|
+
"code.function.name": ctx.name,
|
|
34
|
+
"app.locale": ctx.locale,
|
|
35
|
+
"app.tenant.id": ctx.namespace,
|
|
36
|
+
...ctx.sourceId ? { "client.id": ctx.sourceId } : {},
|
|
37
|
+
...(ctx.userProfile?.sub
|
|
38
|
+
? {
|
|
39
|
+
"user.id": ctx
|
|
40
|
+
.userProfile
|
|
41
|
+
.sub,
|
|
42
|
+
"user.roles": "roles" in ctx
|
|
43
|
+
.userProfile
|
|
44
|
+
? ctx.userProfile.roles
|
|
45
|
+
: undefined
|
|
46
|
+
}
|
|
47
|
+
: {})
|
|
48
|
+
})
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as Data from "effect/Data"
|
|
2
|
+
import type * as Scope from "effect/Scope"
|
|
3
|
+
import * as Context from "./Context.ts"
|
|
4
|
+
import * as Effect from "./Effect.ts"
|
|
5
|
+
import * as Layer from "./Layer.ts"
|
|
6
|
+
|
|
7
|
+
export type Root = "root"
|
|
8
|
+
|
|
9
|
+
export class RequestScopedDependencyNotStartedError extends Data.TaggedError(
|
|
10
|
+
"RequestScopedDependencyNotStartedError"
|
|
11
|
+
)<{ readonly key: string }> {}
|
|
12
|
+
|
|
13
|
+
export interface RequestScopedDependency<Service, E = never, R = never> extends Context.Reference<Service | Root> {
|
|
14
|
+
readonly current: Effect.Effect<Service, RequestScopedDependencyNotStartedError>
|
|
15
|
+
readonly layer: Layer.Layer<never, E, R>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const access = <Service>(
|
|
19
|
+
dependency: Context.Reference<Service | Root>,
|
|
20
|
+
key: string
|
|
21
|
+
): Effect.Effect<Service, RequestScopedDependencyNotStartedError> =>
|
|
22
|
+
dependency.pipe(
|
|
23
|
+
Effect.filterOrFail((_): _ is Service => _ !== "root", () => new RequestScopedDependencyNotStartedError({ key }))
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
export const make = <Service, E = never, R = never>(
|
|
27
|
+
key: string,
|
|
28
|
+
service: Effect.Effect<Service, E, R>
|
|
29
|
+
): RequestScopedDependency<Service, E, Exclude<R, Scope.Scope>> => {
|
|
30
|
+
const dependency = Context.Reference<Service | Root>(key, { defaultValue: () => "root" })
|
|
31
|
+
return Object.assign(dependency, {
|
|
32
|
+
current: access(dependency, key),
|
|
33
|
+
layer: Layer.effect(dependency, service)
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const layer = <
|
|
38
|
+
Deps extends readonly [RequestScopedDependency<any, any, any>, ...Array<RequestScopedDependency<any, any, any>>]
|
|
39
|
+
>(
|
|
40
|
+
...dependencies: Deps
|
|
41
|
+
): Layer.Layer<
|
|
42
|
+
never,
|
|
43
|
+
{ [K in keyof Deps]: Deps[K] extends RequestScopedDependency<any, infer E, any> ? E : never }[number],
|
|
44
|
+
{ [K in keyof Deps]: Deps[K] extends RequestScopedDependency<any, any, infer R> ? R : never }[number]
|
|
45
|
+
> => dependencies.map((_) => _.layer).reduce((acc, l) => Layer.merge(acc, l)) as any
|