@effect-app/infra 2.50.0 → 2.52.0

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.
@@ -149,12 +149,17 @@ export type RefinePathValue<T, P extends Path<T>, X extends string | number | bo
149
149
  : never
150
150
  /* dprint-ignore-end */
151
151
 
152
+ export type EraseNeverContainingUnionElements<T> = T extends any ? {
153
+ [K in keyof T]: IsNever<T[K]> extends true ? true : false
154
+ } extends infer $NC ? true extends $NC[keyof $NC] ? never : T
155
+ : never : never
156
+
152
157
  export type RefineFieldPathValue<
153
158
  TFieldValues extends FieldValues,
154
159
  TFieldPath extends FieldPath<TFieldValues>,
155
160
  X extends string | number | boolean | null | bigint,
156
161
  Exclde extends boolean = false
157
- > = RefinePathValue<TFieldValues, TFieldPath, X, Exclde>
162
+ > = EraseNeverContainingUnionElements<RefinePathValue<TFieldValues, TFieldPath, X, Exclde>>
158
163
 
159
164
  export namespace RefinePathValueTests {
160
165
  type test1 = RefineFieldPathValue<{ a: { b: "tag1"; v1: string } | { b: "tag2"; v2: number } }, "a.b", "tag1">
@@ -207,6 +212,22 @@ export namespace RefinePathValueTests {
207
212
  true
208
213
  >
209
214
  expectTypeOf<test6E>().toEqualTypeOf<{ a: { b: "tag1"; v1: string } }>()
215
+
216
+ type test10 = RefineFieldPathValue<
217
+ | { nested: { a: string; _tag: "a" } | { b: number; _tag: "b" }; _tag: "ab" }
218
+ | { nested: { b: number; _tag: "b" } | { c: boolean; _tag: "c" }; _tag: "bc" },
219
+ "nested._tag",
220
+ "a",
221
+ false
222
+ >
223
+
224
+ expectTypeOf<test10>().toEqualTypeOf<{
225
+ nested: {
226
+ a: string
227
+ _tag: "a"
228
+ }
229
+ _tag: "ab"
230
+ }>()
210
231
  }
211
232
 
212
233
  export namespace SetFieldPathValueTests {
@@ -448,7 +448,7 @@ export type RefineWithLiteral<
448
448
  Exclde extends boolean = false
449
449
  > =
450
450
  // refine only if the value is a primitive
451
- V extends string | number | boolean | null | bigint
451
+ [V] extends [string | number | boolean | null | bigint]
452
452
  ? RefineFieldPathValue<TFieldValues, TFieldName, V, Exclde>
453
453
  : TFieldValues
454
454
  /* dprint-ignore-end */
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { Redacted } from "effect-app"
2
+ import { Effect, Layer, Redacted } from "effect-app"
3
3
  import { CosmosStoreLayer } from "./Cosmos.js"
4
4
  import { DiskStoreLayer } from "./Disk.js"
5
5
  import { MemoryStoreLive } from "./Memory.js"
@@ -7,23 +7,27 @@ import { MemoryStoreLive } from "./Memory.js"
7
7
  import type { StorageConfig } from "./service.js"
8
8
 
9
9
  export function StoreMakerLayer(cfg: StorageConfig) {
10
- const storageUrl = Redacted.value(cfg.url)
11
- if (storageUrl.startsWith("mem://")) {
12
- console.log("Using in memory store")
13
- return MemoryStoreLive
14
- }
15
- if (storageUrl.startsWith("disk://")) {
16
- const dir = storageUrl.replace("disk://", "")
17
- console.log("Using disk store at " + dir)
18
- return DiskStoreLayer(cfg, dir)
19
- }
20
- // if (storageUrl.startsWith("redis://")) {
21
- // console.log("Using Redis store")
22
- // return RedisStoreLayer(cfg)
23
- // }
10
+ return Effect
11
+ .sync(() => {
12
+ const storageUrl = Redacted.value(cfg.url)
13
+ if (storageUrl.startsWith("mem://")) {
14
+ console.log("Using in memory store")
15
+ return MemoryStoreLive
16
+ }
17
+ if (storageUrl.startsWith("disk://")) {
18
+ const dir = storageUrl.replace("disk://", "")
19
+ console.log("Using disk store at " + dir)
20
+ return DiskStoreLayer(cfg, dir)
21
+ }
22
+ // if (storageUrl.startsWith("redis://")) {
23
+ // console.log("Using Redis store")
24
+ // return RedisStoreLayer(cfg)
25
+ // }
24
26
 
25
- console.log("Using Cosmos DB store")
26
- return CosmosStoreLayer(cfg)
27
+ console.log("Using Cosmos DB store")
28
+ return CosmosStoreLayer(cfg)
29
+ })
30
+ .pipe(Layer.unwrapEffect)
27
31
  }
28
32
 
29
33
  export * from "./service.js"
@@ -928,3 +928,133 @@ it("distribution over union", () =>
928
928
  >()
929
929
  })
930
930
  .pipe(Effect.provide(MemoryStoreLive), setupRequestContextFromCurrent(), Effect.runPromise))
931
+
932
+ it("refine nested union", () =>
933
+ Effect
934
+ .gen(function*() {
935
+ class TestNested extends S.Class<TestNested>()({ id: S.String, nested: TestUnion }) {}
936
+
937
+ const repo = yield* makeRepo("test", TestNested, {})
938
+
939
+ const base = make<TestNested>()
940
+
941
+ const res_query = base.pipe(
942
+ where("nested._tag", Math.random() > 0.5 ? "animal" : "person")
943
+ )
944
+
945
+ expectTypeOf(res_query).toEqualTypeOf<
946
+ QueryWhere<TestNested, {
947
+ readonly id: string
948
+ readonly nested: {
949
+ readonly _tag: "person"
950
+ readonly id: string
951
+ readonly surname: string
952
+ } | {
953
+ readonly _tag: "animal"
954
+ readonly id: string
955
+ readonly surname: string
956
+ }
957
+ }, false>
958
+ >()
959
+
960
+ const res = yield* repo.query(
961
+ () => res_query
962
+ )
963
+
964
+ expectTypeOf(res).toEqualTypeOf<
965
+ readonly {
966
+ readonly id: string
967
+ readonly nested: Person | Animal
968
+ }[]
969
+ >()
970
+ })
971
+ .pipe(Effect.provide(MemoryStoreLive), setupRequestContextFromCurrent(), Effect.runPromise))
972
+
973
+ it("refine union with nested union", () =>
974
+ Effect
975
+ .gen(function*() {
976
+ class A extends S.TaggedClass<A>()("A", {
977
+ a: S.String
978
+ }) {}
979
+
980
+ class B extends S.TaggedClass<B>()("B", {
981
+ b: S.String
982
+ }) {}
983
+
984
+ class C extends S.TaggedClass<C>()("C", {
985
+ c: S.String
986
+ }) {}
987
+
988
+ class D extends S.TaggedClass<D>()("D", {
989
+ d: S.String
990
+ }) {}
991
+
992
+ class E extends S.TaggedClass<E>()("E", {
993
+ e: S.String
994
+ }) {}
995
+
996
+ class Container1 extends S.TaggedClass<Container1>()("Container1", {
997
+ id: S.String,
998
+ nested: S.Union(A, B, C)
999
+ }) {}
1000
+
1001
+ class Container2 extends S.TaggedClass<Container2>()("Container2", {
1002
+ id: S.String,
1003
+ nested: S.Union(B, C, D)
1004
+ }) {}
1005
+
1006
+ class Container3 extends S.TaggedClass<Container3>()("Container3", {
1007
+ id: S.String,
1008
+ nested: S.Union(C, D, E)
1009
+ }) {}
1010
+
1011
+ const Containers = S.Union(Container1, Container2, Container3)
1012
+ type Containers = typeof Containers.Type
1013
+
1014
+ const repo = yield* makeRepo("containers", Containers, {})
1015
+
1016
+ const base = make<Containers>()
1017
+
1018
+ const res_query = base.pipe(
1019
+ where("nested._tag", "D")
1020
+ )
1021
+
1022
+ expectTypeOf(res_query).toEqualTypeOf<
1023
+ QueryWhere<
1024
+ Containers,
1025
+ {
1026
+ readonly id: string
1027
+ readonly _tag: "Container2"
1028
+ readonly nested: {
1029
+ readonly _tag: "D"
1030
+ readonly d: string
1031
+ }
1032
+ } | {
1033
+ readonly id: string
1034
+ readonly _tag: "Container3"
1035
+ readonly nested: {
1036
+ readonly _tag: "D"
1037
+ readonly d: string
1038
+ }
1039
+ },
1040
+ false
1041
+ >
1042
+ >()
1043
+
1044
+ const res = yield* repo.query(
1045
+ () => res_query
1046
+ )
1047
+
1048
+ expectTypeOf(res).toEqualTypeOf<
1049
+ readonly ({
1050
+ readonly _tag: "Container2"
1051
+ readonly id: string
1052
+ readonly nested: D
1053
+ } | {
1054
+ readonly _tag: "Container3"
1055
+ readonly id: string
1056
+ readonly nested: D
1057
+ })[]
1058
+ >()
1059
+ })
1060
+ .pipe(Effect.provide(MemoryStoreLive), setupRequestContextFromCurrent(), Effect.runPromise))