effect-app 4.0.0-beta.265 → 4.0.0-beta.267
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 +18 -0
- package/dist/Model/Repository/Registry.d.ts +5 -4
- package/dist/Model/Repository/Registry.d.ts.map +1 -1
- package/dist/Model/Repository/Registry.js +1 -1
- package/dist/Model/Repository/ext.d.ts +3 -3
- package/dist/Model/Repository/legacy.d.ts +6 -6
- package/dist/Model/Repository/legacy.d.ts.map +1 -1
- package/dist/Model/Repository/service.d.ts +30 -30
- package/dist/Model/Repository/service.d.ts.map +1 -1
- package/dist/Model/filter/types/path/eager.d.ts +35 -8
- package/dist/Model/filter/types/path/eager.d.ts.map +1 -1
- package/dist/Model/filter/types/path/eager.js +7 -1
- package/dist/Model/query/new-kid-interpreter.d.ts +4 -4
- package/dist/Store.d.ts +11 -11
- package/dist/Store.d.ts.map +1 -1
- package/dist/client/errors.d.ts +35 -4
- package/dist/client/errors.d.ts.map +1 -1
- package/dist/client/errors.js +32 -2
- package/package.json +1 -1
- package/src/Model/Repository/Registry.ts +3 -2
- package/src/Model/Repository/legacy.ts +5 -5
- package/src/Model/Repository/service.ts +39 -29
- package/src/Model/filter/types/path/eager.ts +38 -8
- package/src/Store.ts +10 -10
- package/src/client/errors.ts +41 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import type * as Scope from "effect/Scope"
|
|
3
|
-
import type { InvalidStateError, NotFoundError, OptimisticConcurrencyException } from "../../client/errors.js"
|
|
3
|
+
import type { DatabaseError, InvalidStateError, NotFoundError, OptimisticConcurrencyException } from "../../client/errors.js"
|
|
4
4
|
import type * as Effect from "../../Effect.js"
|
|
5
5
|
import type * as Option from "../../Option.js"
|
|
6
6
|
import type * as S from "../../Schema.js"
|
|
@@ -49,32 +49,32 @@ export interface Repository<
|
|
|
49
49
|
> {
|
|
50
50
|
readonly itemType: ItemType
|
|
51
51
|
readonly idKey: IdKey
|
|
52
|
-
readonly find: (id: T[IdKey]) => Effect.Effect<Option.Option<T>,
|
|
53
|
-
readonly all: Effect.Effect<T[],
|
|
52
|
+
readonly find: (id: T[IdKey]) => Effect.Effect<Option.Option<T>, DatabaseError, RSchema>
|
|
53
|
+
readonly all: Effect.Effect<T[], DatabaseError, RSchema>
|
|
54
54
|
readonly saveAndPublish: (
|
|
55
55
|
items: Iterable<T>,
|
|
56
56
|
events?: Iterable<Evt>
|
|
57
|
-
) => Effect.Effect<void, InvalidStateError | OptimisticConcurrencyException, RSchema | RPublish>
|
|
57
|
+
) => Effect.Effect<void, InvalidStateError | OptimisticConcurrencyException | DatabaseError, RSchema | RPublish>
|
|
58
58
|
readonly changeFeed: ChangeFeed<T>
|
|
59
59
|
readonly removeAndPublish: (
|
|
60
60
|
items: Iterable<T>,
|
|
61
61
|
events?: Iterable<Evt>
|
|
62
|
-
) => Effect.Effect<void,
|
|
62
|
+
) => Effect.Effect<void, DatabaseError, RSchema | RPublish>
|
|
63
63
|
|
|
64
64
|
readonly removeById: (
|
|
65
65
|
idOrIds: T[IdKey] | ReadonlyArray<T[IdKey]>
|
|
66
|
-
) => Effect.Effect<void,
|
|
66
|
+
) => Effect.Effect<void, DatabaseError, RSchema>
|
|
67
67
|
|
|
68
68
|
readonly queryRaw: <T, Out, R>(
|
|
69
69
|
schema: S.Codec<T, Out, R>,
|
|
70
70
|
raw: RawQuery<Encoded, Out>
|
|
71
|
-
) => Effect.Effect<readonly T[], S.SchemaError, R>
|
|
71
|
+
) => Effect.Effect<readonly T[], S.SchemaError | DatabaseError, R>
|
|
72
72
|
|
|
73
73
|
/**
|
|
74
74
|
* Explicitly seed a namespace. Primary is seeded eagerly on initialization.
|
|
75
75
|
* Non-primary namespaces must be seeded explicitly before use.
|
|
76
76
|
*/
|
|
77
|
-
readonly seedNamespace: (namespace: string) => Effect.Effect<void>
|
|
77
|
+
readonly seedNamespace: (namespace: string) => Effect.Effect<void, DatabaseError>
|
|
78
78
|
|
|
79
79
|
readonly query: {
|
|
80
80
|
// ending with projection
|
|
@@ -91,7 +91,8 @@ export interface Repository<
|
|
|
91
91
|
): Effect.Effect<
|
|
92
92
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
93
93
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
94
|
-
| (TType extends "count" ? never : S.SchemaError)
|
|
94
|
+
| (TType extends "count" ? never : S.SchemaError)
|
|
95
|
+
| DatabaseError,
|
|
95
96
|
Exclude<R, RProvided> | RSchema
|
|
96
97
|
>
|
|
97
98
|
<
|
|
@@ -111,7 +112,8 @@ export interface Repository<
|
|
|
111
112
|
): Effect.Effect<
|
|
112
113
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
113
114
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
114
|
-
| (TType extends "count" ? never : S.SchemaError)
|
|
115
|
+
| (TType extends "count" ? never : S.SchemaError)
|
|
116
|
+
| DatabaseError,
|
|
115
117
|
Exclude<R, RProvided> | RSchema
|
|
116
118
|
>
|
|
117
119
|
<
|
|
@@ -133,7 +135,8 @@ export interface Repository<
|
|
|
133
135
|
): Effect.Effect<
|
|
134
136
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
135
137
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
136
|
-
| (TType extends "count" ? never : S.SchemaError)
|
|
138
|
+
| (TType extends "count" ? never : S.SchemaError)
|
|
139
|
+
| DatabaseError,
|
|
137
140
|
Exclude<R, RProvided> | RSchema
|
|
138
141
|
>
|
|
139
142
|
<
|
|
@@ -157,7 +160,8 @@ export interface Repository<
|
|
|
157
160
|
): Effect.Effect<
|
|
158
161
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
159
162
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
160
|
-
| (TType extends "count" ? never : S.SchemaError)
|
|
163
|
+
| (TType extends "count" ? never : S.SchemaError)
|
|
164
|
+
| DatabaseError,
|
|
161
165
|
Exclude<R, RProvided> | RSchema
|
|
162
166
|
>
|
|
163
167
|
<
|
|
@@ -183,7 +187,8 @@ export interface Repository<
|
|
|
183
187
|
): Effect.Effect<
|
|
184
188
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
185
189
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
186
|
-
| (TType extends "count" ? never : S.SchemaError)
|
|
190
|
+
| (TType extends "count" ? never : S.SchemaError)
|
|
191
|
+
| DatabaseError,
|
|
187
192
|
Exclude<R, RProvided> | RSchema
|
|
188
193
|
>
|
|
189
194
|
<
|
|
@@ -209,7 +214,8 @@ export interface Repository<
|
|
|
209
214
|
): Effect.Effect<
|
|
210
215
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
211
216
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
212
|
-
| (TType extends "count" ? never : S.SchemaError)
|
|
217
|
+
| (TType extends "count" ? never : S.SchemaError)
|
|
218
|
+
| DatabaseError,
|
|
213
219
|
Exclude<R, RProvided> | RSchema
|
|
214
220
|
>
|
|
215
221
|
<
|
|
@@ -237,7 +243,8 @@ export interface Repository<
|
|
|
237
243
|
): Effect.Effect<
|
|
238
244
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
239
245
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
240
|
-
| (TType extends "count" ? never : S.SchemaError)
|
|
246
|
+
| (TType extends "count" ? never : S.SchemaError)
|
|
247
|
+
| DatabaseError,
|
|
241
248
|
Exclude<R, RProvided> | RSchema
|
|
242
249
|
>
|
|
243
250
|
<
|
|
@@ -267,7 +274,8 @@ export interface Repository<
|
|
|
267
274
|
): Effect.Effect<
|
|
268
275
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
269
276
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
270
|
-
| (TType extends "count" ? never : S.SchemaError)
|
|
277
|
+
| (TType extends "count" ? never : S.SchemaError)
|
|
278
|
+
| DatabaseError,
|
|
271
279
|
Exclude<R, RProvided> | RSchema
|
|
272
280
|
>
|
|
273
281
|
<
|
|
@@ -299,7 +307,8 @@ export interface Repository<
|
|
|
299
307
|
): Effect.Effect<
|
|
300
308
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
301
309
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
302
|
-
| (TType extends "count" ? never : S.SchemaError)
|
|
310
|
+
| (TType extends "count" ? never : S.SchemaError)
|
|
311
|
+
| DatabaseError,
|
|
303
312
|
Exclude<R, RProvided> | RSchema
|
|
304
313
|
>
|
|
305
314
|
<
|
|
@@ -333,7 +342,8 @@ export interface Repository<
|
|
|
333
342
|
): Effect.Effect<
|
|
334
343
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
335
344
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
336
|
-
| (TType extends "count" ? never : S.SchemaError)
|
|
345
|
+
| (TType extends "count" ? never : S.SchemaError)
|
|
346
|
+
| DatabaseError,
|
|
337
347
|
Exclude<R, RProvided> | RSchema
|
|
338
348
|
>
|
|
339
349
|
|
|
@@ -347,7 +357,7 @@ export interface Repository<
|
|
|
347
357
|
q: (initial: Query<Encoded>) => QAll<Encoded, EncodedRefined, RefineTHelper<T, EncodedRefined>, R, TType, E>
|
|
348
358
|
): Effect.Effect<
|
|
349
359
|
TType extends "many" ? DistributeQueryIfExclusiveOnArray<E, T, EncodedRefined> : RefineTHelper<T, EncodedRefined>,
|
|
350
|
-
TType extends "many" ? never : NotFoundError<ItemType
|
|
360
|
+
(TType extends "many" ? never : NotFoundError<ItemType>) | DatabaseError,
|
|
351
361
|
Exclude<R, RProvided> | RSchema
|
|
352
362
|
>
|
|
353
363
|
<
|
|
@@ -363,7 +373,7 @@ export interface Repository<
|
|
|
363
373
|
) => QAll<Encoded, EncodedRefined, RefineTHelper<T, EncodedRefined>, R, TType, E>
|
|
364
374
|
): Effect.Effect<
|
|
365
375
|
TType extends "many" ? DistributeQueryIfExclusiveOnArray<E, T, EncodedRefined> : RefineTHelper<T, EncodedRefined>,
|
|
366
|
-
TType extends "many" ? never : NotFoundError<ItemType
|
|
376
|
+
(TType extends "many" ? never : NotFoundError<ItemType>) | DatabaseError,
|
|
367
377
|
Exclude<R, RProvided> | RSchema
|
|
368
378
|
>
|
|
369
379
|
<
|
|
@@ -383,7 +393,7 @@ export interface Repository<
|
|
|
383
393
|
) => QAll<Encoded, EncodedRefined, RefineTHelper<T, EncodedRefined>, R, TType, E>
|
|
384
394
|
): Effect.Effect<
|
|
385
395
|
TType extends "many" ? DistributeQueryIfExclusiveOnArray<E, T, EncodedRefined> : RefineTHelper<T, EncodedRefined>,
|
|
386
|
-
TType extends "many" ? never : NotFoundError<ItemType
|
|
396
|
+
(TType extends "many" ? never : NotFoundError<ItemType>) | DatabaseError,
|
|
387
397
|
Exclude<R, RProvided> | RSchema
|
|
388
398
|
>
|
|
389
399
|
<
|
|
@@ -403,7 +413,7 @@ export interface Repository<
|
|
|
403
413
|
) => QAll<Encoded, EncodedRefined, RefineTHelper<T, EncodedRefined>, R, TType, E>
|
|
404
414
|
): Effect.Effect<
|
|
405
415
|
TType extends "many" ? DistributeQueryIfExclusiveOnArray<E, T, EncodedRefined> : RefineTHelper<T, EncodedRefined>,
|
|
406
|
-
TType extends "many" ? never : NotFoundError<ItemType
|
|
416
|
+
(TType extends "many" ? never : NotFoundError<ItemType>) | DatabaseError,
|
|
407
417
|
Exclude<R, RProvided> | RSchema
|
|
408
418
|
>
|
|
409
419
|
<
|
|
@@ -425,7 +435,7 @@ export interface Repository<
|
|
|
425
435
|
) => QAll<Encoded, EncodedRefined, RefineTHelper<T, EncodedRefined>, R, TType, E>
|
|
426
436
|
): Effect.Effect<
|
|
427
437
|
TType extends "many" ? DistributeQueryIfExclusiveOnArray<E, T, EncodedRefined> : RefineTHelper<T, EncodedRefined>,
|
|
428
|
-
TType extends "many" ? never : NotFoundError<ItemType
|
|
438
|
+
(TType extends "many" ? never : NotFoundError<ItemType>) | DatabaseError,
|
|
429
439
|
Exclude<R, RProvided> | RSchema
|
|
430
440
|
>
|
|
431
441
|
<
|
|
@@ -449,7 +459,7 @@ export interface Repository<
|
|
|
449
459
|
) => QAll<Encoded, EncodedRefined, RefineTHelper<T, EncodedRefined>, R, TType, E>
|
|
450
460
|
): Effect.Effect<
|
|
451
461
|
TType extends "many" ? DistributeQueryIfExclusiveOnArray<E, T, EncodedRefined> : RefineTHelper<T, EncodedRefined>,
|
|
452
|
-
TType extends "many" ? never : NotFoundError<ItemType
|
|
462
|
+
(TType extends "many" ? never : NotFoundError<ItemType>) | DatabaseError,
|
|
453
463
|
Exclude<R, RProvided> | RSchema
|
|
454
464
|
>
|
|
455
465
|
<
|
|
@@ -475,7 +485,7 @@ export interface Repository<
|
|
|
475
485
|
) => QAll<Encoded, EncodedRefined, RefineTHelper<T, EncodedRefined>, R, TType, E>
|
|
476
486
|
): Effect.Effect<
|
|
477
487
|
TType extends "many" ? DistributeQueryIfExclusiveOnArray<E, T, EncodedRefined> : RefineTHelper<T, EncodedRefined>,
|
|
478
|
-
TType extends "many" ? never : NotFoundError<ItemType
|
|
488
|
+
(TType extends "many" ? never : NotFoundError<ItemType>) | DatabaseError,
|
|
479
489
|
Exclude<R, RProvided> | RSchema
|
|
480
490
|
>
|
|
481
491
|
<
|
|
@@ -504,7 +514,7 @@ export interface Repository<
|
|
|
504
514
|
): Effect.Effect<
|
|
505
515
|
TType extends "many" ? DistributeQueryIfExclusiveOnArray<E, T, EncodedRefined>
|
|
506
516
|
: RefineTHelper<T, EncodedRefined>,
|
|
507
|
-
TType extends "many" ? never : NotFoundError<ItemType
|
|
517
|
+
(TType extends "many" ? never : NotFoundError<ItemType>) | DatabaseError,
|
|
508
518
|
Exclude<R, RProvided> | RSchema
|
|
509
519
|
>
|
|
510
520
|
<
|
|
@@ -535,7 +545,7 @@ export interface Repository<
|
|
|
535
545
|
): Effect.Effect<
|
|
536
546
|
TType extends "many" ? DistributeQueryIfExclusiveOnArray<E, T, EncodedRefined>
|
|
537
547
|
: RefineTHelper<T, EncodedRefined>,
|
|
538
|
-
TType extends "many" ? never : NotFoundError<ItemType
|
|
548
|
+
(TType extends "many" ? never : NotFoundError<ItemType>) | DatabaseError,
|
|
539
549
|
Exclude<R, RProvided> | RSchema
|
|
540
550
|
>
|
|
541
551
|
<
|
|
@@ -568,7 +578,7 @@ export interface Repository<
|
|
|
568
578
|
): Effect.Effect<
|
|
569
579
|
TType extends "many" ? DistributeQueryIfExclusiveOnArray<E, T, EncodedRefined>
|
|
570
580
|
: RefineTHelper<T, EncodedRefined>,
|
|
571
|
-
TType extends "many" ? never : NotFoundError<ItemType
|
|
581
|
+
(TType extends "many" ? never : NotFoundError<ItemType>) | DatabaseError,
|
|
572
582
|
Exclude<R, RProvided> | RSchema
|
|
573
583
|
>
|
|
574
584
|
}
|
|
@@ -585,7 +595,7 @@ export interface Repository<
|
|
|
585
595
|
percentage?: number
|
|
586
596
|
/** optional maximum number of items to sample */
|
|
587
597
|
maxItems?: number
|
|
588
|
-
}) => Effect.Effect<ValidationResult,
|
|
598
|
+
}) => Effect.Effect<ValidationResult, DatabaseError, RSchema>
|
|
589
599
|
}
|
|
590
600
|
|
|
591
601
|
type DistributeQueryIfExclusiveOnArray<Exclusive extends boolean, T, EncodedRefined> = [Exclusive] extends [true]
|
|
@@ -7,27 +7,36 @@ import type { ArrayKey, IsTuple, TupleKeys } from "./common.js"
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Helper type for recursively constructing paths through a type.
|
|
10
|
-
*
|
|
10
|
+
* `Seen` carries the set of object types already entered on this branch so
|
|
11
|
+
* recursion terminates on self-referential types (see {@link Path}).
|
|
11
12
|
*/
|
|
12
|
-
type PathImpl<K extends string | number, V> = V extends
|
|
13
|
+
type PathImpl<K extends string | number, V, Seen> = V extends
|
|
13
14
|
| Primitive
|
|
14
15
|
| BrowserNativeObject ? `${K}`
|
|
15
|
-
|
|
16
|
+
// Stop before re-entering a type already on this branch. Recursive types
|
|
17
|
+
// (notably `Json`, the encoded form of `Schema.Defect()`:
|
|
18
|
+
// `JsonObject = { [x: string]: Json }`) would otherwise descend forever and
|
|
19
|
+
// blow past TS's instantiation limit => TS2589. The key itself stays a valid
|
|
20
|
+
// leaf path; only the unbounded descent is cut.
|
|
21
|
+
: [V] extends [Seen] ? `${K}`
|
|
22
|
+
: `${K}` | `${K}.${Path<V, Seen | V>}`
|
|
16
23
|
|
|
17
24
|
/**
|
|
18
25
|
* Type which eagerly collects all paths through a type
|
|
19
|
-
* @typeParam T
|
|
26
|
+
* @typeParam T - type which should be introspected
|
|
27
|
+
* @typeParam Seen - object types already entered on this recursion branch;
|
|
28
|
+
* used to terminate on self-referential types
|
|
20
29
|
* @example
|
|
21
30
|
* ```
|
|
22
31
|
* Path<{foo: {bar: string}}> = 'foo' | 'foo.bar'
|
|
23
32
|
* ```
|
|
24
33
|
*/
|
|
25
|
-
export type Path<T> = T extends ReadonlyArray<infer V> ? IsTuple<T> extends true ? {
|
|
26
|
-
[K in TupleKeys<T>]-?: PathImpl<K & string, T[K]> | "length"
|
|
34
|
+
export type Path<T, Seen = never> = T extends ReadonlyArray<infer V> ? IsTuple<T> extends true ? {
|
|
35
|
+
[K in TupleKeys<T>]-?: PathImpl<K & string, T[K], Seen> | "length"
|
|
27
36
|
}[TupleKeys<T>]
|
|
28
|
-
: PathImpl<ArrayKey, V> | "length"
|
|
37
|
+
: PathImpl<ArrayKey, V, Seen | T> | "length"
|
|
29
38
|
: {
|
|
30
|
-
[K in keyof T]-?: PathImpl<K & string, T[K]>
|
|
39
|
+
[K in keyof T]-?: PathImpl<K & string, T[K], Seen | T>
|
|
31
40
|
}[keyof T]
|
|
32
41
|
|
|
33
42
|
/**
|
|
@@ -35,6 +44,27 @@ export type Path<T> = T extends ReadonlyArray<infer V> ? IsTuple<T> extends true
|
|
|
35
44
|
*/
|
|
36
45
|
export type FieldPath<TFieldValues extends FieldValues> = Path<TFieldValues>
|
|
37
46
|
|
|
47
|
+
export namespace PathRecursionTests {
|
|
48
|
+
// Regression: self-referential types must terminate instead of blowing past
|
|
49
|
+
// TS's instantiation limit (TS2589). `JsonLike` mirrors effect's `Json` — the
|
|
50
|
+
// encoded form of `Schema.Defect()` — whose `{ [x: string]: Json }` index
|
|
51
|
+
// signature previously made `Path` recurse forever. These aliases failing to
|
|
52
|
+
// compile (rather than resolving to a string union) signals the regression.
|
|
53
|
+
type JsonLike =
|
|
54
|
+
| string
|
|
55
|
+
| number
|
|
56
|
+
| boolean
|
|
57
|
+
| null
|
|
58
|
+
| ReadonlyArray<JsonLike>
|
|
59
|
+
| { readonly [x: string]: JsonLike }
|
|
60
|
+
export type _RawDefect = Path<{ id: string; raw: JsonLike }>
|
|
61
|
+
export type _NestedDefect = Path<{ a: { b: { error: { raw: JsonLike } } } }>
|
|
62
|
+
export type _ArrayOfDefect = Path<{ items: ReadonlyArray<{ raw: JsonLike }> }>
|
|
63
|
+
// finite paths are still produced
|
|
64
|
+
expectTypeOf<"id">().toExtend<_RawDefect>()
|
|
65
|
+
expectTypeOf<"raw">().toExtend<_RawDefect>()
|
|
66
|
+
}
|
|
67
|
+
|
|
38
68
|
/**
|
|
39
69
|
* Type to evaluate the type which the given path points to.
|
|
40
70
|
* @typeParam T - deeply nested type which is indexed by the path
|
package/src/Store.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as Data from "effect/Data"
|
|
|
3
3
|
import type * as Redacted from "effect/Redacted"
|
|
4
4
|
import * as Semaphore from "effect/Semaphore"
|
|
5
5
|
import type { NonEmptyReadonlyArray } from "./Array.js"
|
|
6
|
-
import type { OptimisticConcurrencyException } from "./client/errors.js"
|
|
6
|
+
import type { DatabaseError, OptimisticConcurrencyException } from "./client/errors.js"
|
|
7
7
|
import * as Context from "./Context.js"
|
|
8
8
|
import * as Effect from "./Effect.js"
|
|
9
9
|
import * as Layer from "./Layer.js"
|
|
@@ -99,30 +99,30 @@ export interface FilterArgs<Encoded extends FieldValues, U extends keyof Encoded
|
|
|
99
99
|
|
|
100
100
|
export type FilterFunc<Encoded extends FieldValues> = <U extends keyof Encoded = never>(
|
|
101
101
|
args: FilterArgs<Encoded, U>
|
|
102
|
-
) => Effect.Effect<(U extends undefined ? Encoded : Pick<Encoded, U>)[]>
|
|
102
|
+
) => Effect.Effect<(U extends undefined ? Encoded : Pick<Encoded, U>)[], DatabaseError>
|
|
103
103
|
|
|
104
104
|
export interface Store<
|
|
105
105
|
IdKey extends keyof Encoded,
|
|
106
106
|
Encoded extends FieldValues,
|
|
107
107
|
PM extends PersistenceModelType<Encoded> = PersistenceModelType<Encoded>
|
|
108
108
|
> {
|
|
109
|
-
all: Effect.Effect<PM[]>
|
|
109
|
+
all: Effect.Effect<PM[], DatabaseError>
|
|
110
110
|
filter: FilterFunc<Encoded>
|
|
111
|
-
find: (id: Encoded[IdKey]) => Effect.Effect<Option.Option<PM
|
|
112
|
-
set: (e: PM) => Effect.Effect<PM, OptimisticConcurrencyException>
|
|
111
|
+
find: (id: Encoded[IdKey]) => Effect.Effect<Option.Option<PM>, DatabaseError>
|
|
112
|
+
set: (e: PM) => Effect.Effect<PM, OptimisticConcurrencyException | DatabaseError>
|
|
113
113
|
batchSet: (
|
|
114
114
|
items: NonEmptyReadonlyArray<PM>
|
|
115
|
-
) => Effect.Effect<NonEmptyReadonlyArray<PM>, OptimisticConcurrencyException>
|
|
115
|
+
) => Effect.Effect<NonEmptyReadonlyArray<PM>, OptimisticConcurrencyException | DatabaseError>
|
|
116
116
|
bulkSet: (
|
|
117
117
|
items: NonEmptyReadonlyArray<PM>
|
|
118
|
-
) => Effect.Effect<NonEmptyReadonlyArray<PM>, OptimisticConcurrencyException>
|
|
119
|
-
batchRemove: (ids: NonEmptyReadonlyArray<Encoded[IdKey]>, partitionKey?: string) => Effect.Effect<void>
|
|
120
|
-
queryRaw: <Out>(query: RawQuery<Encoded, Out>) => Effect.Effect<readonly Out[]>
|
|
118
|
+
) => Effect.Effect<NonEmptyReadonlyArray<PM>, OptimisticConcurrencyException | DatabaseError>
|
|
119
|
+
batchRemove: (ids: NonEmptyReadonlyArray<Encoded[IdKey]>, partitionKey?: string) => Effect.Effect<void, DatabaseError>
|
|
120
|
+
queryRaw: <Out>(query: RawQuery<Encoded, Out>) => Effect.Effect<readonly Out[], DatabaseError>
|
|
121
121
|
/**
|
|
122
122
|
* Explicitly seed a namespace. Primary is seeded eagerly on initialization.
|
|
123
123
|
* Non-primary namespaces must be seeded explicitly before use.
|
|
124
124
|
*/
|
|
125
|
-
seedNamespace: (namespace: string) => Effect.Effect<void>
|
|
125
|
+
seedNamespace: (namespace: string) => Effect.Effect<void, DatabaseError>
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
export class StoreMaker extends Context.Opaque<StoreMaker, {
|
package/src/client/errors.ts
CHANGED
|
@@ -157,6 +157,45 @@ export class OptimisticConcurrencyException extends TaggedErrorClass<OptimisticC
|
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
/**
|
|
161
|
+
* Raised by a store adapter when a database operation fails for an
|
|
162
|
+
* infrastructure reason (request timeout, throttle, 5xx, dropped socket, or any
|
|
163
|
+
* non-conflict error). Distinct from `OptimisticConcurrencyException`, which is
|
|
164
|
+
* an expected etag conflict.
|
|
165
|
+
*
|
|
166
|
+
* `transient` is set by the adapter for failures worth retrying (timeout /
|
|
167
|
+
* throttle / 5xx / network). `cause` is the underlying adapter error, carried
|
|
168
|
+
* through a `Defect` schema so it serializes (an `Error` encodes to
|
|
169
|
+
* `{ name, message, cause }`) instead of breaking JSON encoding of the channel.
|
|
170
|
+
*
|
|
171
|
+
* Treated by the api/client/FE machinery like an unexpected (500-class) error.
|
|
172
|
+
*/
|
|
173
|
+
export class DatabaseError extends TaggedErrorClass<DatabaseError>()(
|
|
174
|
+
"DatabaseError",
|
|
175
|
+
{
|
|
176
|
+
message: S.String,
|
|
177
|
+
transient: S.Boolean,
|
|
178
|
+
cause: S.optional(S.Defect())
|
|
179
|
+
}
|
|
180
|
+
) {
|
|
181
|
+
constructor(
|
|
182
|
+
args: { message?: string; transient?: boolean; cause?: unknown },
|
|
183
|
+
disableValidation?: boolean
|
|
184
|
+
) {
|
|
185
|
+
super(
|
|
186
|
+
{
|
|
187
|
+
message: args.message ?? "Database operation failed",
|
|
188
|
+
transient: args.transient ?? false,
|
|
189
|
+
cause: args.cause
|
|
190
|
+
},
|
|
191
|
+
disableValidation as any
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
override toString() {
|
|
195
|
+
return `DatabaseError: ${this.message}`
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
160
199
|
const MutationOnlyErrors = [
|
|
161
200
|
InvalidStateError,
|
|
162
201
|
OptimisticConcurrencyException
|
|
@@ -168,7 +207,8 @@ const GeneralErrors = [
|
|
|
168
207
|
LoginError,
|
|
169
208
|
UnauthorizedError,
|
|
170
209
|
ValidationError,
|
|
171
|
-
ServiceUnavailableError
|
|
210
|
+
ServiceUnavailableError,
|
|
211
|
+
DatabaseError
|
|
172
212
|
] as const
|
|
173
213
|
|
|
174
214
|
export const SupportedErrors = S.Union([
|