@effect-app/infra 2.6.0 → 2.7.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.
- package/CHANGELOG.md +12 -0
- package/_cjs/services/Repository/legacy.cjs +38 -1
- package/_cjs/services/Repository/legacy.cjs.map +1 -1
- package/_cjs/services/RepositoryBase.cjs.map +1 -1
- package/_cjs/services/Store/service.cjs.map +1 -1
- package/_cjs/services/query/dsl.cjs +10 -11
- package/_cjs/services/query/dsl.cjs.map +1 -1
- package/_cjs/services/query/new-kid-interpreter.cjs +1 -0
- package/_cjs/services/query/new-kid-interpreter.cjs.map +1 -1
- package/dist/services/Operations.d.ts +3 -3
- package/dist/services/Repository/legacy.d.ts +73 -23
- package/dist/services/Repository/legacy.d.ts.map +1 -1
- package/dist/services/Repository/legacy.js +26 -2
- package/dist/services/Repository/service.d.ts +10 -4
- package/dist/services/Repository/service.d.ts.map +1 -1
- package/dist/services/RepositoryBase.d.ts +2 -2
- package/dist/services/RepositoryBase.d.ts.map +1 -1
- package/dist/services/RepositoryBase.js +1 -1
- package/dist/services/Store/service.d.ts +6 -5
- package/dist/services/Store/service.d.ts.map +1 -1
- package/dist/services/Store/service.js +1 -1
- package/dist/services/query/dsl.d.ts +116 -58
- package/dist/services/query/dsl.d.ts.map +1 -1
- package/dist/services/query/dsl.js +12 -13
- package/dist/services/query/new-kid-interpreter.d.ts +2 -1
- package/dist/services/query/new-kid-interpreter.d.ts.map +1 -1
- package/dist/services/query/new-kid-interpreter.js +2 -1
- package/examples/query.ts +37 -11
- package/package.json +1 -1
- package/src/services/Repository/legacy.ts +179 -3
- package/src/services/Repository/service.ts +20 -12
- package/src/services/RepositoryBase.ts +4 -2
- package/src/services/Store/service.ts +6 -3
- package/src/services/query/dsl.ts +742 -315
- package/src/services/query/new-kid-interpreter.ts +10 -3
- package/test/dist/query.test.d.ts.map +1 -1
- package/test/query.test.ts +245 -11
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
3
3
|
import type { NonEmptyReadonlyArray, Option, ParseResult, S } from "effect-app"
|
|
4
4
|
import { Context, Effect, Layer } from "effect-app"
|
|
5
|
-
import type { NotFoundError, OptimisticConcurrencyException } from "effect-app/client"
|
|
5
|
+
import type { InvalidStateError, NotFoundError, OptimisticConcurrencyException } from "effect-app/client"
|
|
6
|
+
import type { FixEnv, PureEnv } from "effect-app/Pure"
|
|
7
|
+
import type { NonNegativeInt } from "effect-app/Schema"
|
|
8
|
+
import type { FieldValues } from "../../filter/types.js"
|
|
6
9
|
import * as Q from "../query.js"
|
|
7
10
|
import type { Repos } from "../RepositoryBase.js"
|
|
8
11
|
import { makeRepoInternal } from "../RepositoryBase.js"
|
|
9
12
|
import type { StoreConfig, StoreMaker } from "../Store.js"
|
|
10
13
|
import { type ExtendedRepository, extendRepo } from "./ext.js"
|
|
11
|
-
import type { Repository } from "./service.js"
|
|
14
|
+
import type { RefineTHelper, Repository } from "./service.js"
|
|
12
15
|
|
|
13
16
|
const names = new Map<string, number>()
|
|
14
17
|
const registerName = (name: string) => {
|
|
@@ -23,6 +26,177 @@ const registerName = (name: string) => {
|
|
|
23
26
|
}
|
|
24
27
|
}
|
|
25
28
|
|
|
29
|
+
/**
|
|
30
|
+
* @deprecated
|
|
31
|
+
*/
|
|
32
|
+
export interface RepoFunctions<T, Encoded extends { id: string }, Evt, ItemType, IdKey extends keyof T, Service> {
|
|
33
|
+
itemType: ItemType
|
|
34
|
+
T: T
|
|
35
|
+
all: Effect<readonly T[], never, Service>
|
|
36
|
+
find: (id: T[IdKey]) => Effect<Option<T>, never, Service>
|
|
37
|
+
removeById: (id: T[IdKey]) => Effect<void, NotFoundError<ItemType>, Service>
|
|
38
|
+
saveAndPublish: (
|
|
39
|
+
items: Iterable<T>,
|
|
40
|
+
events?: Iterable<Evt>
|
|
41
|
+
) => Effect<void, InvalidStateError | OptimisticConcurrencyException, Service>
|
|
42
|
+
removeAndPublish: (
|
|
43
|
+
items: Iterable<T>,
|
|
44
|
+
events?: Iterable<Evt>
|
|
45
|
+
) => Effect<void, never, Service>
|
|
46
|
+
save: (...items: T[]) => Effect<void, InvalidStateError | OptimisticConcurrencyException, Service>
|
|
47
|
+
get: (id: T[IdKey]) => Effect<T, NotFoundError<ItemType>, Service>
|
|
48
|
+
queryAndSavePure: {
|
|
49
|
+
<A, E2, R2, T2 extends T>(
|
|
50
|
+
q: (
|
|
51
|
+
q: Q.Query<Encoded>
|
|
52
|
+
) => Q.QueryEnd<Encoded, "one">,
|
|
53
|
+
pure: Effect<A, E2, FixEnv<R2, Evt, T, T2>>
|
|
54
|
+
): Effect.Effect<
|
|
55
|
+
A,
|
|
56
|
+
InvalidStateError | OptimisticConcurrencyException | NotFoundError<ItemType> | E2,
|
|
57
|
+
| Service
|
|
58
|
+
| Exclude<R2, {
|
|
59
|
+
env: PureEnv<Evt, T, T2>
|
|
60
|
+
}>
|
|
61
|
+
>
|
|
62
|
+
<A, E2, R2, T2 extends T>(
|
|
63
|
+
q: (
|
|
64
|
+
q: Q.Query<Encoded>
|
|
65
|
+
) =>
|
|
66
|
+
| Q.Query<Encoded>
|
|
67
|
+
| Q.QueryWhere<Encoded>
|
|
68
|
+
| Q.QueryEnd<Encoded, "many">,
|
|
69
|
+
pure: Effect<A, E2, FixEnv<R2, Evt, readonly T[], readonly T2[]>>
|
|
70
|
+
): Effect.Effect<
|
|
71
|
+
A,
|
|
72
|
+
InvalidStateError | OptimisticConcurrencyException | E2,
|
|
73
|
+
| Service
|
|
74
|
+
| Exclude<R2, {
|
|
75
|
+
env: PureEnv<Evt, readonly T[], readonly T2[]>
|
|
76
|
+
}>
|
|
77
|
+
>
|
|
78
|
+
<A, E2, R2, T2 extends T>(
|
|
79
|
+
q: (
|
|
80
|
+
q: Q.Query<Encoded>
|
|
81
|
+
) =>
|
|
82
|
+
| Q.Query<Encoded>
|
|
83
|
+
| Q.QueryWhere<Encoded>
|
|
84
|
+
| Q.QueryEnd<Encoded, "many">,
|
|
85
|
+
pure: Effect<A, E2, FixEnv<R2, Evt, readonly T[], readonly T2[]>>,
|
|
86
|
+
batch: "batched" | number
|
|
87
|
+
): Effect.Effect<
|
|
88
|
+
A[],
|
|
89
|
+
InvalidStateError | OptimisticConcurrencyException | E2,
|
|
90
|
+
| Service
|
|
91
|
+
| Exclude<R2, {
|
|
92
|
+
env: PureEnv<Evt, readonly T[], readonly T2[]>
|
|
93
|
+
}>
|
|
94
|
+
>
|
|
95
|
+
}
|
|
96
|
+
readonly query: {
|
|
97
|
+
<A, R, From extends FieldValues, TType extends "one" | "many" | "count" = "many">(
|
|
98
|
+
q: (
|
|
99
|
+
initial: Q.Query<Encoded>
|
|
100
|
+
) => Q.QueryProjection<Encoded extends From ? From : never, A, R, TType>
|
|
101
|
+
): Effect.Effect<
|
|
102
|
+
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
103
|
+
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
104
|
+
| (TType extends "count" ? never : S.ParseResult.ParseError),
|
|
105
|
+
R | Service
|
|
106
|
+
>
|
|
107
|
+
<
|
|
108
|
+
R = never,
|
|
109
|
+
TType extends "one" | "many" = "many",
|
|
110
|
+
EncodedRefined extends Encoded = Encoded
|
|
111
|
+
>(
|
|
112
|
+
q: (
|
|
113
|
+
initial: Q.Query<Encoded>
|
|
114
|
+
) => Q.QAll<Encoded, EncodedRefined, RefineTHelper<T, EncodedRefined>, R, TType>
|
|
115
|
+
): Effect.Effect<
|
|
116
|
+
TType extends "many" ? readonly RefineTHelper<T, EncodedRefined>[] : RefineTHelper<T, EncodedRefined>,
|
|
117
|
+
TType extends "many" ? never : NotFoundError<ItemType>,
|
|
118
|
+
R | Service
|
|
119
|
+
>
|
|
120
|
+
}
|
|
121
|
+
byIdAndSaveWithPure: {
|
|
122
|
+
<R, A, E, S2 extends T>(
|
|
123
|
+
id: T[IdKey],
|
|
124
|
+
pure: Effect<A, E, FixEnv<R, Evt, T, S2>>
|
|
125
|
+
): Effect<
|
|
126
|
+
A,
|
|
127
|
+
InvalidStateError | OptimisticConcurrencyException | E | NotFoundError<ItemType>,
|
|
128
|
+
| Service
|
|
129
|
+
| Exclude<R, {
|
|
130
|
+
env: PureEnv<Evt, T, S2>
|
|
131
|
+
}>
|
|
132
|
+
>
|
|
133
|
+
}
|
|
134
|
+
saveManyWithPure: {
|
|
135
|
+
<R, A, E, S1 extends T, S2 extends T>(
|
|
136
|
+
items: Iterable<S1>,
|
|
137
|
+
pure: Effect<A, E, FixEnv<R, Evt, readonly S1[], readonly S2[]>>
|
|
138
|
+
): Effect.Effect<
|
|
139
|
+
A,
|
|
140
|
+
InvalidStateError | OptimisticConcurrencyException | E,
|
|
141
|
+
Exclude<R, {
|
|
142
|
+
env: PureEnv<Evt, readonly S1[], readonly S2[]>
|
|
143
|
+
}>
|
|
144
|
+
>
|
|
145
|
+
<R, A, E, S1 extends T, S2 extends T>(
|
|
146
|
+
items: Iterable<S1>,
|
|
147
|
+
pure: Effect<A, E, FixEnv<R, Evt, readonly S1[], readonly S2[]>>,
|
|
148
|
+
batch: "batched" | number
|
|
149
|
+
): Effect.Effect<
|
|
150
|
+
A[],
|
|
151
|
+
InvalidStateError | OptimisticConcurrencyException | E,
|
|
152
|
+
Exclude<R, {
|
|
153
|
+
env: PureEnv<Evt, readonly S1[], readonly S2[]>
|
|
154
|
+
}>
|
|
155
|
+
>
|
|
156
|
+
}
|
|
157
|
+
/** @experimental */
|
|
158
|
+
mapped: MM<Service, Encoded>
|
|
159
|
+
use: <X>(
|
|
160
|
+
body: (_: Service) => X
|
|
161
|
+
) => X extends Effect<infer A, infer E, infer R> ? Effect<A, E, R | Service> : Effect<X, never, Service>
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* @deprecated
|
|
166
|
+
*/
|
|
167
|
+
const makeRepoFunctions = (tag: any, itemType: any) => {
|
|
168
|
+
const { all } = Effect.serviceConstants(tag) as any
|
|
169
|
+
const {
|
|
170
|
+
byIdAndSaveWithPure,
|
|
171
|
+
find,
|
|
172
|
+
get,
|
|
173
|
+
query,
|
|
174
|
+
queryAndSavePure,
|
|
175
|
+
removeAndPublish,
|
|
176
|
+
removeById,
|
|
177
|
+
save,
|
|
178
|
+
saveAndPublish,
|
|
179
|
+
saveManyWithPure
|
|
180
|
+
} = Effect.serviceFunctions(tag) as any
|
|
181
|
+
const mapped = (s: any) => Effect.map(tag, (_: any) => _.mapped(s))
|
|
182
|
+
return {
|
|
183
|
+
itemType,
|
|
184
|
+
all,
|
|
185
|
+
byIdAndSaveWithPure,
|
|
186
|
+
find,
|
|
187
|
+
removeById,
|
|
188
|
+
saveAndPublish,
|
|
189
|
+
removeAndPublish,
|
|
190
|
+
save,
|
|
191
|
+
get,
|
|
192
|
+
query,
|
|
193
|
+
mapped,
|
|
194
|
+
queryAndSavePure,
|
|
195
|
+
saveManyWithPure,
|
|
196
|
+
use: (body: any) => Effect.andThen(tag, body)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
26
200
|
/** @deprecated use makeRepo/extendRepo */
|
|
27
201
|
export class RepositoryBase<
|
|
28
202
|
T,
|
|
@@ -132,6 +306,7 @@ export const RepositoryDefaultImpl2 = <Service, Evt = never>() => {
|
|
|
132
306
|
impl: Repository<T, Encoded, Evt, ItemType, IdKey, R> & Ext
|
|
133
307
|
) => RepositoryBase<T, Encoded, Evt, ItemType, Ext, IdKey, R>)
|
|
134
308
|
& Context.Tag<Service, Service>
|
|
309
|
+
& RepoFunctions<T, Encoded, Evt, ItemType, IdKey, Service>
|
|
135
310
|
& {
|
|
136
311
|
Default: Layer.Layer<
|
|
137
312
|
Service,
|
|
@@ -207,6 +382,7 @@ export const RepositoryDefaultImpl2 = <Service, Evt = never>() => {
|
|
|
207
382
|
impl: Repository<T, Encoded, Evt, ItemType, "id", R> & Ext
|
|
208
383
|
) => RepositoryBase<T, Encoded, Evt, ItemType, Ext, "id", R>)
|
|
209
384
|
& Context.Tag<Service, Service>
|
|
385
|
+
& RepoFunctions<T, Encoded, Evt, ItemType, "id", Service>
|
|
210
386
|
& {
|
|
211
387
|
Default: Layer.Layer<
|
|
212
388
|
Service,
|
|
@@ -327,7 +503,7 @@ export const RepositoryDefaultImpl2 = <Service, Evt = never>() => {
|
|
|
327
503
|
Error.stackTraceLimit = limit
|
|
328
504
|
// TODO: actual class name or expect a string identifier - careful with overlapping between modules
|
|
329
505
|
return Context.assignTag<Service>(registerName(itemType + "Repo"), creationError)(
|
|
330
|
-
Cls
|
|
506
|
+
Object.assign(Cls, makeRepoFunctions(Cls, itemType))
|
|
331
507
|
) as any // impl is missing, but its marked protected
|
|
332
508
|
}
|
|
333
509
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Effect, Option, PubSub } from "effect-app"
|
|
1
|
+
import type { Effect, Option, PubSub, S } from "effect-app"
|
|
3
2
|
import type { InvalidStateError, NotFoundError, OptimisticConcurrencyException } from "effect-app/client"
|
|
4
3
|
import type { NonNegativeInt } from "effect-app/Schema/numbers"
|
|
5
4
|
import type { FieldValues } from "../../filter/types.js"
|
|
@@ -32,24 +31,33 @@ export interface Repository<
|
|
|
32
31
|
) => Effect<void, never, R>
|
|
33
32
|
|
|
34
33
|
readonly query: {
|
|
35
|
-
<A, R,
|
|
34
|
+
<A, R, From extends FieldValues, TType extends "one" | "many" | "count" = "many">(
|
|
36
35
|
q: (
|
|
37
36
|
initial: Query<Encoded>
|
|
38
|
-
) => QueryProjection<Encoded extends
|
|
37
|
+
) => QueryProjection<Encoded extends From ? From : never, A, R, TType>
|
|
39
38
|
): Effect.Effect<
|
|
40
39
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
41
40
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
42
|
-
| (TType extends "count" ? never : ParseResult.ParseError),
|
|
41
|
+
| (TType extends "count" ? never : S.ParseResult.ParseError),
|
|
42
|
+
R
|
|
43
|
+
>
|
|
44
|
+
<
|
|
45
|
+
R = never,
|
|
46
|
+
TType extends "one" | "many" = "many",
|
|
47
|
+
EncodedRefined extends Encoded = Encoded
|
|
48
|
+
>(
|
|
49
|
+
q: (initial: Query<Encoded>) => QAll<Encoded, EncodedRefined, RefineTHelper<T, EncodedRefined>, R, TType>
|
|
50
|
+
): Effect.Effect<
|
|
51
|
+
TType extends "many" ? readonly RefineTHelper<T, EncodedRefined>[] : RefineTHelper<T, EncodedRefined>,
|
|
52
|
+
TType extends "many" ? never : NotFoundError<ItemType>,
|
|
43
53
|
R
|
|
44
54
|
>
|
|
45
|
-
<R = never, TType extends "one" | "many" = "many">(
|
|
46
|
-
q: (initial: Query<Encoded>) => QAll<Encoded, T, R, TType>
|
|
47
|
-
): Effect.Effect<TType extends "many" ? readonly T[] : T, TType extends "many" ? never : NotFoundError<ItemType>, R>
|
|
48
|
-
// <R = never>(q: QAll<Encoded, T, R>): Effect.Effect<readonly T[], never, R>
|
|
49
|
-
// <A, R, Encoded2 extends FieldValues>(
|
|
50
|
-
// q: QueryProjection<Encoded extends Encoded2 ? Encoded2 : never, A, R>
|
|
51
|
-
// ): Effect.Effect<readonly A[], S.ParseResult.ParseError, R>
|
|
52
55
|
}
|
|
53
56
|
/** @deprecated use query */
|
|
54
57
|
readonly mapped: Mapped<Encoded>
|
|
55
58
|
}
|
|
59
|
+
|
|
60
|
+
export type RefineTHelper<T, EncodedRefined> = EncodedRefined extends { _tag: any }
|
|
61
|
+
? T extends { _tag: any } ? Extract<T, { _tag: EncodedRefined["_tag"] }>
|
|
62
|
+
: T
|
|
63
|
+
: T
|
|
@@ -258,8 +258,10 @@ export function makeRepoInternal<
|
|
|
258
258
|
<A, R, From extends FieldValues>(
|
|
259
259
|
q: QueryProjection<Encoded extends From ? From : never, A, R>
|
|
260
260
|
): Effect.Effect<readonly A[], S.ParseResult.ParseError, R>
|
|
261
|
-
<A, R
|
|
262
|
-
|
|
261
|
+
<A, R, EncodedRefined extends Encoded = Encoded>(
|
|
262
|
+
q: QAll<NoInfer<Encoded>, NoInfer<EncodedRefined>, A, R>
|
|
263
|
+
): Effect.Effect<readonly A[], never, R>
|
|
264
|
+
} = (<A, R, EncodedRefined extends Encoded = Encoded>(q: QAll<Encoded, EncodedRefined, A, R>) => {
|
|
263
265
|
const a = Q.toFilter(q)
|
|
264
266
|
const eff = a.mode === "project"
|
|
265
267
|
? filter(a)
|
|
@@ -3,6 +3,8 @@ import type { UniqueKey } from "@azure/cosmos"
|
|
|
3
3
|
import { Context, Effect } from "effect-app"
|
|
4
4
|
import type { NonEmptyReadonlyArray, Option, Secret } from "effect-app"
|
|
5
5
|
import type { OptimisticConcurrencyException } from "../../errors.js"
|
|
6
|
+
import type { FieldValues } from "../../filter/types.js"
|
|
7
|
+
import type { FieldPath } from "../../filter/types/path/index.js"
|
|
6
8
|
import type { FilterResult } from "./filterApi/query.js"
|
|
7
9
|
|
|
8
10
|
export type StoreConfig<E> = {
|
|
@@ -34,15 +36,16 @@ export type Where =
|
|
|
34
36
|
|
|
35
37
|
export type Filter = readonly FilterResult[]
|
|
36
38
|
|
|
37
|
-
export interface O<
|
|
38
|
-
key:
|
|
39
|
+
export interface O<TFieldValues extends FieldValues> {
|
|
40
|
+
key: FieldPath<TFieldValues>
|
|
39
41
|
direction: "ASC" | "DESC"
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
export interface FilterArgs<Encoded extends { id: string }, U extends keyof Encoded = never> {
|
|
45
|
+
t: Encoded
|
|
43
46
|
filter?: Filter | undefined
|
|
44
47
|
select?: NonEmptyReadonlyArray<U> | undefined
|
|
45
|
-
order?: NonEmptyReadonlyArray<O<Encoded
|
|
48
|
+
order?: NonEmptyReadonlyArray<O<NoInfer<Encoded>>>
|
|
46
49
|
limit?: number | undefined
|
|
47
50
|
skip?: number | undefined
|
|
48
51
|
}
|