@effect-app/infra 0.223.2 → 0.225.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 +31 -0
- package/_cjs/_ext/Array.cjs +0 -8
- package/_cjs/_ext/Array.cjs.map +1 -1
- package/_cjs/api/routing/schema/jwt.cjs +6 -4
- package/_cjs/api/routing/schema/jwt.cjs.map +1 -1
- package/_cjs/services/Emailer/service.cjs +2 -2
- package/_cjs/services/Emailer/service.cjs.map +1 -1
- package/_cjs/services/Operations.cjs +1 -2
- package/_cjs/services/Operations.cjs.map +1 -1
- package/_cjs/services/RepositoryBase.cjs +2 -3
- package/_cjs/services/RepositoryBase.cjs.map +1 -1
- package/_cjs/services/RequestContextContainer.cjs +1 -2
- package/_cjs/services/RequestContextContainer.cjs.map +1 -1
- package/_cjs/services/Store/ContextMapContainer.cjs +4 -5
- package/_cjs/services/Store/ContextMapContainer.cjs.map +1 -1
- package/_cjs/services/Store/Cosmos.cjs +5 -5
- package/_cjs/services/Store/Cosmos.cjs.map +1 -1
- package/_cjs/services/Store/Memory.cjs +1 -1
- package/_cjs/services/Store/Memory.cjs.map +1 -1
- package/_cjs/services/Store/service.cjs +2 -3
- package/_cjs/services/Store/service.cjs.map +1 -1
- package/dist/_ext/Array.d.ts +0 -5
- package/dist/_ext/Array.d.ts.map +1 -1
- package/dist/_ext/Array.js +1 -8
- package/dist/api/routing/schema/jwt.d.ts.map +1 -1
- package/dist/api/routing/schema/jwt.js +6 -5
- package/dist/services/Emailer/service.d.ts +6 -6
- package/dist/services/Emailer/service.d.ts.map +1 -1
- package/dist/services/Emailer/service.js +3 -3
- package/dist/services/Operations.d.ts +7 -7
- package/dist/services/Operations.d.ts.map +1 -1
- package/dist/services/Operations.js +3 -4
- package/dist/services/QueueMaker/service.d.ts +2 -2
- package/dist/services/Repository/ext.d.ts +11 -11
- package/dist/services/RepositoryBase.d.ts +11 -11
- package/dist/services/RepositoryBase.d.ts.map +1 -1
- package/dist/services/RepositoryBase.js +4 -5
- package/dist/services/RequestContextContainer.d.ts +1 -1
- package/dist/services/RequestContextContainer.d.ts.map +1 -1
- package/dist/services/RequestContextContainer.js +2 -3
- package/dist/services/Store/ContextMapContainer.d.ts.map +1 -1
- package/dist/services/Store/ContextMapContainer.js +2 -3
- package/dist/services/Store/Cosmos.d.ts.map +1 -1
- package/dist/services/Store/Cosmos.js +8 -8
- package/dist/services/Store/Memory.d.ts.map +1 -1
- package/dist/services/Store/Memory.js +4 -4
- package/dist/services/Store/index.d.ts +1 -1
- package/dist/services/Store/index.d.ts.map +1 -1
- package/dist/services/Store/service.d.ts +14 -18
- package/dist/services/Store/service.d.ts.map +1 -1
- package/dist/services/Store/service.js +4 -5
- package/dist/services/query/new-kid-interpreter.d.ts +1 -1
- package/examples/query.ts +60 -0
- package/package.json +6 -6
- package/src/_ext/Array.ts +0 -14
- package/src/api/routing/schema/jwt.ts +2 -7
- package/src/services/Emailer/service.ts +2 -3
- package/src/services/Operations.ts +2 -3
- package/src/services/RepositoryBase.ts +4 -5
- package/src/services/RequestContextContainer.ts +1 -2
- package/src/services/Store/ContextMapContainer.ts +1 -2
- package/src/services/Store/Cosmos.ts +8 -8
- package/src/services/Store/Memory.ts +3 -3
- package/src/services/Store/service.ts +4 -5
- package/test/dist/query.test.d.ts.map +1 -1
- package/test/query.test.ts +11 -14
- package/tsconfig.examples.json +16 -0
- package/tsconfig.json.bak +3 -0
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { Effect } from "effect-app";
|
|
2
|
-
import { TagClassId, TagClassMakeId } from "effect-app/service";
|
|
1
|
+
import { Context, Effect } from "effect-app";
|
|
3
2
|
/**
|
|
4
3
|
* @tsplus type StoreMaker
|
|
5
4
|
* @tsplus companion StoreMaker.Ops
|
|
6
5
|
*/
|
|
7
|
-
export class StoreMaker extends
|
|
6
|
+
export class StoreMaker extends Context.TagId("effect-app/StoreMaker")() {
|
|
8
7
|
}
|
|
9
8
|
export const makeContextMap = () => {
|
|
10
9
|
const etags = new Map();
|
|
@@ -70,6 +69,6 @@ const makeMap = Effect.sync(() => makeContextMap());
|
|
|
70
69
|
* @tsplus type ContextMap
|
|
71
70
|
* @tsplus companion ContextMap.Ops
|
|
72
71
|
*/
|
|
73
|
-
export class ContextMap extends
|
|
72
|
+
export class ContextMap extends Context.TagMakeId("effect-app/ContextMap", makeMap)() {
|
|
74
73
|
}
|
|
75
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
74
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZXJ2aWNlcy9TdG9yZS9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sWUFBWSxDQUFBO0FBeUU1Qzs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sVUFBVyxTQUFRLE9BQU8sQ0FBQyxLQUFLLENBQUMsdUJBQXVCLENBQUMsRUFNbEU7Q0FDSDtBQUVELE1BQU0sQ0FBQyxNQUFNLGNBQWMsR0FBRyxHQUFHLEVBQUU7SUFDakMsTUFBTSxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUE7SUFDdkMsTUFBTSxPQUFPLEdBQUcsQ0FBQyxFQUFVLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUE7SUFDN0MsTUFBTSxPQUFPLEdBQUcsQ0FBQyxFQUFVLEVBQUUsSUFBd0IsRUFBRSxFQUFFO1FBQ3ZELElBQUksS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFBO0lBQzdELENBQUMsQ0FBQTtJQUVELCtCQUErQjtJQUMvQiwyQkFBMkI7SUFDM0IsZ0RBQWdEO0lBQ2hELE1BQU07SUFFTiwrQkFBK0I7SUFDL0IsMkJBQTJCO0lBQzNCLHNDQUFzQztJQUN0QyxNQUFNO0lBRU4sa0NBQWtDO0lBQ2xDLHdCQUF3QjtJQUN4QixvQ0FBb0M7SUFDcEMsU0FBUztJQUNULDJCQUEyQjtJQUMzQixjQUFjO0lBQ2QsSUFBSTtJQUVKLGlDQUFpQztJQUNqQyxvRkFBb0Y7SUFDcEYsb0lBQW9JO0lBQ3BJLGdCQUFnQjtJQUNoQixhQUFhO0lBQ2IsNEdBQTRHO0lBQzVHLHNDQUFzQztJQUN0QyxrRUFBa0U7SUFDbEUsdURBQXVEO0lBQ3ZELHNCQUFzQjtJQUN0QixzQkFBc0I7SUFDdEIsU0FBUztJQUNULHFDQUFxQztJQUNyQyx5Q0FBeUM7SUFDekMsaUJBQWlCO0lBQ2pCLDZCQUE2QjtJQUM3QixtQkFBbUI7SUFDbkIsK0NBQStDO0lBQy9DLHFCQUFxQjtJQUNyQixtQkFBbUI7SUFDbkIsMkNBQTJDO0lBQzNDLHlCQUF5QjtJQUN6QixzQkFBc0I7SUFDdEIsWUFBWTtJQUNaLGlCQUFpQjtJQUNqQix5Q0FBeUM7SUFDekMscURBQXFEO0lBQ3JELG9CQUFvQjtJQUNwQixVQUFVO0lBQ1YsUUFBUTtJQUNSLE1BQU07SUFDTixJQUFJO0lBRUosT0FBTztRQUNMLEdBQUcsRUFBRSxPQUFPO1FBQ1osR0FBRyxFQUFFLE9BQU87UUFDWixZQUFZO0tBQ2IsQ0FBQTtBQUNILENBQUMsQ0FBQTtBQUVELE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQTtBQUVuRDs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sVUFBVyxTQUFRLE9BQU8sQ0FBQyxTQUFTLENBQUMsdUJBQXVCLEVBQUUsT0FBTyxDQUFDLEVBQWM7Q0FDaEcifQ==
|
|
@@ -14,7 +14,7 @@ export declare const toFilter: <TFieldValues extends FieldValues, A, R>(q: QAll<
|
|
|
14
14
|
key: import("../../filter/types/path/eager.js").Path<TFieldValues>;
|
|
15
15
|
direction: "ASC" | "DESC";
|
|
16
16
|
}[]];
|
|
17
|
-
ttype: "
|
|
17
|
+
ttype: "many" | "one" | "count";
|
|
18
18
|
mode: "project" | "collect" | "transform";
|
|
19
19
|
filter: QueryBuilder<any>;
|
|
20
20
|
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { RepositoryDefaultImpl } from "@effect-app/infra/services/RepositoryBase"
|
|
2
|
+
import { Effect, flow, Layer, ManagedRuntime, S } from "effect-app"
|
|
3
|
+
import { and, or, order, page, project, where } from "../src/services/query.js"
|
|
4
|
+
import { ContextMapContainer } from "../src/services/Store/ContextMapContainer.js"
|
|
5
|
+
import { MemoryStoreLive } from "../src/services/Store/Memory.js"
|
|
6
|
+
|
|
7
|
+
const str = S.struct({ _tag: S.literal("string"), value: S.string })
|
|
8
|
+
const num = S.struct({ _tag: S.literal("number"), value: S.number })
|
|
9
|
+
const someUnion = S.union(str, num)
|
|
10
|
+
|
|
11
|
+
export class Something extends S.Class<Something>()({
|
|
12
|
+
id: S.StringId.withDefault,
|
|
13
|
+
displayName: S.NonEmptyString255,
|
|
14
|
+
n: S.Date.withDefault,
|
|
15
|
+
union: someUnion.pipe(S.withDefaultConstructor(() => ({ _tag: "string" as const, value: "hi" })))
|
|
16
|
+
}) {}
|
|
17
|
+
export declare namespace Something {
|
|
18
|
+
export interface Encoded extends S.Schema.Encoded<typeof Something> {}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const items = [
|
|
22
|
+
new Something({ displayName: S.NonEmptyString255("Verona"), n: new Date("2020-01-01T00:00:00Z") }),
|
|
23
|
+
new Something({ displayName: S.NonEmptyString255("Riley") }),
|
|
24
|
+
new Something({
|
|
25
|
+
displayName: S.NonEmptyString255("Riley"),
|
|
26
|
+
n: new Date("2020-01-01T00:00:00Z"),
|
|
27
|
+
union: { _tag: "number", value: 1 }
|
|
28
|
+
})
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
class SomethingRepo extends RepositoryDefaultImpl<SomethingRepo>()(
|
|
32
|
+
"Something",
|
|
33
|
+
Something
|
|
34
|
+
) {
|
|
35
|
+
static readonly Test = Layer
|
|
36
|
+
.effect(
|
|
37
|
+
SomethingRepo,
|
|
38
|
+
SomethingRepo.makeWith({ makeInitial: Effect.sync(() => items) }, (_) => new SomethingRepo(_))
|
|
39
|
+
)
|
|
40
|
+
.pipe(
|
|
41
|
+
Layer.provide(Layer.merge(MemoryStoreLive, ContextMapContainer.live))
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const program = Effect.gen(function*($) {
|
|
46
|
+
const r = yield* $(SomethingRepo.query(flow(
|
|
47
|
+
where("displayName", "Verona"),
|
|
48
|
+
or(
|
|
49
|
+
where("displayName", "Riley"),
|
|
50
|
+
and("n", "gt", "2021-01-01T00:00:00Z") // TODO: work with To type translation, so Date?
|
|
51
|
+
),
|
|
52
|
+
order("displayName"),
|
|
53
|
+
page({ take: 1 }),
|
|
54
|
+
project(S.struct(Something.pick("id", "displayName")))
|
|
55
|
+
)))
|
|
56
|
+
console.log("$$ result", r)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
const rt = ManagedRuntime.make(SomethingRepo.Test)
|
|
60
|
+
rt.runFork(program)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-app/infra",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.225.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
"proper-lockfile": "^4.1.2",
|
|
19
19
|
"pure-rand": "6.0.4",
|
|
20
20
|
"redlock": "^4.2.0",
|
|
21
|
-
"@effect-app/core": "0.
|
|
22
|
-
"@effect-app/
|
|
23
|
-
"@effect-app/
|
|
24
|
-
"
|
|
25
|
-
"effect-app": "0.
|
|
21
|
+
"@effect-app/core": "0.159.0",
|
|
22
|
+
"@effect-app/fluent-extensions": "0.153.0",
|
|
23
|
+
"@effect-app/infra-adapters": "0.146.0",
|
|
24
|
+
"effect-app": "0.192.0",
|
|
25
|
+
"@effect-app/schema": "0.211.1"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@babel/cli": "^7.23.9",
|
package/src/_ext/Array.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { Chunk, Effect, Equal } from "effect-app"
|
|
2
|
-
import type { ObjectOps } from "effect-app/utils"
|
|
3
|
-
import { inspect } from "util"
|
|
4
2
|
import { NotFoundError } from "../errors.js"
|
|
5
3
|
|
|
6
4
|
/**
|
|
@@ -22,15 +20,3 @@ export function getFirstById<A extends { id: unknown }, Type extends string>(
|
|
|
22
20
|
Effect.mapError(() => new NotFoundError<Type>({ type, id }))
|
|
23
21
|
)
|
|
24
22
|
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @tsplus fluent Object.Ops inspect
|
|
28
|
-
*/
|
|
29
|
-
export function RecordInspect<TT extends object>(
|
|
30
|
-
o: ObjectOps<TT>,
|
|
31
|
-
showHidden?: boolean | undefined,
|
|
32
|
-
depth?: number | null | undefined,
|
|
33
|
-
color?: boolean | undefined
|
|
34
|
-
) {
|
|
35
|
-
return inspect(o.subject, showHidden, depth, color)
|
|
36
|
-
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
3
|
/* eslint-disable @typescript-eslint/ban-types */
|
|
4
|
-
import type { ParseIssue } from "@effect/schema/ParseResult"
|
|
5
|
-
import type { Effect } from "effect-app"
|
|
6
4
|
import * as S from "effect-app/schema"
|
|
7
5
|
import { jwtDecode, type JwtDecodeOptions } from "jwt-decode"
|
|
8
6
|
|
|
@@ -11,16 +9,13 @@ export const parseJwt = <R, I, A>(
|
|
|
11
9
|
options?: JwtDecodeOptions | undefined
|
|
12
10
|
): S.Schema<A, string, R> =>
|
|
13
11
|
S
|
|
14
|
-
.
|
|
12
|
+
.transformToOrFail(
|
|
15
13
|
S.string,
|
|
16
14
|
S.unknown,
|
|
17
15
|
(s, __, ast) =>
|
|
18
16
|
S.ParseResult.try({
|
|
19
17
|
try: () => jwtDecode(s, options),
|
|
20
18
|
catch: (e: any) => new S.ParseResult.Type(ast, s, e?.message)
|
|
21
|
-
})
|
|
22
|
-
(_): Effect<string, ParseIssue> => {
|
|
23
|
-
throw new Error("not implemented")
|
|
24
|
-
}
|
|
19
|
+
})
|
|
25
20
|
)
|
|
26
21
|
.pipe(S.compose(schema, { strict: false }))
|
|
@@ -2,14 +2,13 @@ import type { Email, NonEmptyString255 } from "@effect-app/schema"
|
|
|
2
2
|
import type { MailContent, MailData } from "@sendgrid/helpers/classes/mail.js"
|
|
3
3
|
import type { ResponseError } from "@sendgrid/mail"
|
|
4
4
|
import type sgMail from "@sendgrid/mail"
|
|
5
|
-
import type
|
|
6
|
-
import { TagClassId } from "effect-app/service"
|
|
5
|
+
import { Context, type Effect, type NonEmptyReadonlyArray, type Secret } from "effect-app"
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* @tsplus type Emailer
|
|
10
9
|
* @tsplus companion Emailer.Ops
|
|
11
10
|
*/
|
|
12
|
-
export class Emailer extends
|
|
11
|
+
export class Emailer extends Context.TagId("effect-app/Emailer")<Emailer, {
|
|
13
12
|
sendMail: (msg: EmailMsgOptionalFrom) => Effect<void, Error | ResponseError>
|
|
14
13
|
}>() {}
|
|
15
14
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { StringId } from "@effect-app/schema"
|
|
2
|
-
import { Cause, copy, Duration, Effect, Exit, Layer, Option, S, Schedule } from "effect-app"
|
|
2
|
+
import { Cause, Context, copy, Duration, Effect, Exit, Layer, Option, S, Schedule } from "effect-app"
|
|
3
3
|
import type { OperationProgress } from "effect-app/Operations"
|
|
4
|
-
import { TagClassMakeId } from "effect-app/service"
|
|
5
4
|
import * as Scope from "effect/Scope"
|
|
6
5
|
import { forkDaemonReportRequestUnexpected } from "../api/reportError.js"
|
|
7
6
|
|
|
@@ -97,7 +96,7 @@ const make = Effect.sync(() => {
|
|
|
97
96
|
}
|
|
98
97
|
})
|
|
99
98
|
|
|
100
|
-
export class Operations extends
|
|
99
|
+
export class Operations extends Context.TagMakeId("effect-app/Operations", make)<Operations>() {
|
|
101
100
|
private static readonly CleanupLive = this
|
|
102
101
|
.use((_) =>
|
|
103
102
|
_.cleanup.pipe(
|
|
@@ -22,11 +22,10 @@ import { toNonEmptyArray } from "@effect-app/core/Array"
|
|
|
22
22
|
import { flatMapOption } from "@effect-app/core/Effect"
|
|
23
23
|
import type { ParseResult, Schema } from "@effect-app/schema"
|
|
24
24
|
import { NonNegativeInt } from "@effect-app/schema"
|
|
25
|
-
import type {
|
|
26
|
-
import { Chunk, Effect, flow, Option, pipe, PubSub, ReadonlyArray, S, Unify } from "effect-app"
|
|
25
|
+
import type { NonEmptyArray, NonEmptyReadonlyArray } from "effect-app"
|
|
26
|
+
import { Chunk, Context, Effect, flow, Option, pipe, PubSub, ReadonlyArray, S, Unify } from "effect-app"
|
|
27
27
|
import { runTerm } from "effect-app/Pure"
|
|
28
28
|
import type { FixEnv, PureEnv } from "effect-app/Pure"
|
|
29
|
-
import { assignTag } from "effect-app/service"
|
|
30
29
|
import type { NoInfer } from "effect/Types"
|
|
31
30
|
import { type InvalidStateError, NotFoundError, type OptimisticConcurrencyException } from "../errors.js"
|
|
32
31
|
import type { FieldValues } from "../filter/types.js"
|
|
@@ -946,7 +945,7 @@ export const RepositoryBaseImpl = <Service>() => {
|
|
|
946
945
|
Error.stackTraceLimit = 2
|
|
947
946
|
const creationError = new Error()
|
|
948
947
|
Error.stackTraceLimit = limit
|
|
949
|
-
return assignTag<Service>(undefined, creationError)(Object.assign(Cls, makeRepoFunctions(Cls))) as any
|
|
948
|
+
return Context.assignTag<Service>(undefined, creationError)(Object.assign(Cls, makeRepoFunctions(Cls))) as any
|
|
950
949
|
}
|
|
951
950
|
}
|
|
952
951
|
|
|
@@ -992,6 +991,6 @@ export const RepositoryDefaultImpl = <Service, Evt = never>() => {
|
|
|
992
991
|
Error.stackTraceLimit = 2
|
|
993
992
|
const creationError = new Error()
|
|
994
993
|
Error.stackTraceLimit = limit
|
|
995
|
-
return assignTag<Service>(undefined, creationError)(Object.assign(Cls, makeRepoFunctions(Cls))) as any // impl is missing, but its marked protected
|
|
994
|
+
return Context.assignTag<Service>(undefined, creationError)(Object.assign(Cls, makeRepoFunctions(Cls))) as any // impl is missing, but its marked protected
|
|
996
995
|
}
|
|
997
996
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { NonEmptyString255 } from "@effect-app/schema"
|
|
2
2
|
import { Context, Effect, FiberRef, Layer, Option } from "effect-app"
|
|
3
3
|
import { RequestId } from "effect-app/ids"
|
|
4
|
-
import { TagClassId } from "effect-app/service"
|
|
5
4
|
import { RequestContext } from "../RequestContext.js"
|
|
6
5
|
import { restoreFromRequestContext } from "./Store/Memory.js"
|
|
7
6
|
|
|
@@ -10,7 +9,7 @@ import { restoreFromRequestContext } from "./Store/Memory.js"
|
|
|
10
9
|
* @tsplus companion RequestContextContainer.Ops
|
|
11
10
|
*/
|
|
12
11
|
export abstract class RequestContextContainer
|
|
13
|
-
extends
|
|
12
|
+
extends Context.TagId("effect-app/RequestContextContainer")<RequestContextContainer, {
|
|
14
13
|
requestContext: Effect<RequestContext>
|
|
15
14
|
update: (f: (rc: RequestContext) => RequestContext) => Effect<RequestContext>
|
|
16
15
|
start: (f: RequestContext) => Effect<void>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Context, Effect, FiberRef, Layer, Option } from "effect-app"
|
|
2
|
-
import { TagClassId } from "effect-app/service"
|
|
3
2
|
import { ContextMap } from "./service.js"
|
|
4
3
|
|
|
5
4
|
// TODO: we have to create a new contextmap on every request.
|
|
@@ -11,7 +10,7 @@ import { ContextMap } from "./service.js"
|
|
|
11
10
|
/**
|
|
12
11
|
* @tsplus companion ContextMapContainer.Ops
|
|
13
12
|
*/
|
|
14
|
-
export abstract class ContextMapContainer extends
|
|
13
|
+
export abstract class ContextMapContainer extends Context.TagId("effect-app/ContextMapContainer")<ContextMapContainer, {
|
|
15
14
|
get: Effect<ContextMap>
|
|
16
15
|
start: Effect<void>
|
|
17
16
|
}>() {
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import { toNonEmptyArray } from "@effect-app/core/Array"
|
|
4
4
|
import { CosmosClient, CosmosClientLayer } from "@effect-app/infra-adapters/cosmos-client"
|
|
5
|
-
import { Chunk, Duration, Effect, Layer, Option, ReadonlyArray, Secret } from "effect-app"
|
|
5
|
+
import { Chunk, Duration, Effect, Layer, Option, pipe, ReadonlyArray, Secret, Struct } from "effect-app"
|
|
6
6
|
import type { NonEmptyReadonlyArray } from "effect-app"
|
|
7
|
-
import { dropUndefinedT
|
|
7
|
+
import { dropUndefinedT } from "effect-app/utils"
|
|
8
8
|
import { OptimisticConcurrencyException } from "../../errors.js"
|
|
9
9
|
import { buildWhereCosmosQuery3, logQuery } from "./Cosmos/query.js"
|
|
10
10
|
import { StoreMaker } from "./service.js"
|
|
@@ -18,7 +18,7 @@ function makeCosmosStore({ prefix }: StorageConfig) {
|
|
|
18
18
|
return Effect.gen(function*($) {
|
|
19
19
|
const { db } = yield* $(CosmosClient)
|
|
20
20
|
return {
|
|
21
|
-
make: <Id extends string, Encoded extends { id: Id }, R = never, E = never>(
|
|
21
|
+
make: <Id extends string, Encoded extends Record<string, any> & { id: Id }, R = never, E = never>(
|
|
22
22
|
name: string,
|
|
23
23
|
seed?: Effect<Iterable<Encoded>, E, R>,
|
|
24
24
|
config?: StoreConfig<Encoded>
|
|
@@ -56,7 +56,7 @@ function makeCosmosStore({ prefix }: StorageConfig) {
|
|
|
56
56
|
dropUndefinedT({
|
|
57
57
|
operationType: "Create" as const,
|
|
58
58
|
resourceBody: {
|
|
59
|
-
...omit(x, "_etag"),
|
|
59
|
+
...Struct.omit(x, "_etag"),
|
|
60
60
|
_partitionKey: config?.partitionValue(x)
|
|
61
61
|
},
|
|
62
62
|
partitionKey: config?.partitionValue(x)
|
|
@@ -66,7 +66,7 @@ function makeCosmosStore({ prefix }: StorageConfig) {
|
|
|
66
66
|
operationType: "Replace" as const,
|
|
67
67
|
id: x.id,
|
|
68
68
|
resourceBody: {
|
|
69
|
-
...omit(x, "_etag"),
|
|
69
|
+
...Struct.omit(x, "_etag"),
|
|
70
70
|
_partitionKey: config?.partitionValue(x)
|
|
71
71
|
},
|
|
72
72
|
ifMatch: eTag,
|
|
@@ -139,7 +139,7 @@ function makeCosmosStore({ prefix }: StorageConfig) {
|
|
|
139
139
|
onNone: () => ({
|
|
140
140
|
operationType: "Create" as const,
|
|
141
141
|
resourceBody: {
|
|
142
|
-
...omit(x, "_etag"),
|
|
142
|
+
...Struct.omit(x, "_etag"),
|
|
143
143
|
_partitionKey: config?.partitionValue(x)
|
|
144
144
|
}
|
|
145
145
|
}),
|
|
@@ -147,7 +147,7 @@ function makeCosmosStore({ prefix }: StorageConfig) {
|
|
|
147
147
|
operationType: "Replace" as const,
|
|
148
148
|
id: x.id,
|
|
149
149
|
resourceBody: {
|
|
150
|
-
...omit(x, "_etag"),
|
|
150
|
+
...Struct.omit(x, "_etag"),
|
|
151
151
|
_partitionKey: config?.partitionValue(x)
|
|
152
152
|
},
|
|
153
153
|
ifMatch: eTag
|
|
@@ -250,7 +250,7 @@ function makeCosmosStore({ prefix }: StorageConfig) {
|
|
|
250
250
|
.query<M>(q)
|
|
251
251
|
.fetchAll()
|
|
252
252
|
.then(({ resources }) =>
|
|
253
|
-
resources.map((_) => ({ ...
|
|
253
|
+
resources.map((_) => ({ ...pipe(defaultValues, Struct.pick(...f.select!)), ..._ }))
|
|
254
254
|
)
|
|
255
255
|
: container
|
|
256
256
|
.items
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
|
|
3
|
-
import { Effect, FiberRef, flow, Option, Order, pipe, ReadonlyArray, Ref } from "effect-app"
|
|
3
|
+
import { Effect, FiberRef, flow, Option, Order, pipe, ReadonlyArray, Ref, Struct } from "effect-app"
|
|
4
4
|
import type { NonEmptyArray, NonEmptyReadonlyArray } from "effect-app"
|
|
5
|
-
import { get
|
|
5
|
+
import { get } from "effect-app/utils"
|
|
6
6
|
import type { RequestContext } from "../../RequestContext.js"
|
|
7
7
|
import type { FilterArgs, PersistenceModelType, Store, StoreConfig } from "./service.js"
|
|
8
8
|
import { StoreMaker } from "./service.js"
|
|
@@ -11,7 +11,7 @@ import { codeFilter, makeUpdateETag } from "./utils.js"
|
|
|
11
11
|
export function memFilter<T extends { id: string }, U extends keyof T = never>(f: FilterArgs<T, U>) {
|
|
12
12
|
type M = U extends undefined ? T : Pick<T, U>
|
|
13
13
|
return ((c: T[]): M[] => {
|
|
14
|
-
const select = (r: T[]): M[] => (f.select ? r.map(
|
|
14
|
+
const select = (r: T[]): M[] => (f.select ? r.map(Struct.pick(...f.select)) : r) as any
|
|
15
15
|
const skip = f?.skip
|
|
16
16
|
const limit = f?.limit
|
|
17
17
|
const ords = Option.map(Option.fromNullable(f.order), (_) =>
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import type { UniqueKey } from "@azure/cosmos"
|
|
3
|
-
import { Effect } from "effect-app"
|
|
3
|
+
import { Context, Effect } from "effect-app"
|
|
4
4
|
import type { NonEmptyReadonlyArray, Option, Secret } from "effect-app"
|
|
5
|
-
import { TagClassId, TagClassMakeId } from "effect-app/service"
|
|
6
5
|
import type { OptimisticConcurrencyException } from "../../errors.js"
|
|
7
6
|
import type { FieldValues } from "../../filter/types.js"
|
|
8
7
|
import type { QueryBuilder } from "./filterApi/query.js"
|
|
@@ -78,7 +77,7 @@ export interface Store<
|
|
|
78
77
|
* @tsplus type StoreMaker
|
|
79
78
|
* @tsplus companion StoreMaker.Ops
|
|
80
79
|
*/
|
|
81
|
-
export class StoreMaker extends
|
|
80
|
+
export class StoreMaker extends Context.TagId("effect-app/StoreMaker")<StoreMaker, {
|
|
82
81
|
make: <Encoded extends { id: Id }, Id extends string, R = never, E = never>(
|
|
83
82
|
name: string,
|
|
84
83
|
seed?: Effect<Iterable<Encoded>, E, R>,
|
|
@@ -158,10 +157,10 @@ const makeMap = Effect.sync(() => makeContextMap())
|
|
|
158
157
|
* @tsplus type ContextMap
|
|
159
158
|
* @tsplus companion ContextMap.Ops
|
|
160
159
|
*/
|
|
161
|
-
export class ContextMap extends
|
|
160
|
+
export class ContextMap extends Context.TagMakeId("effect-app/ContextMap", makeMap)<ContextMap>() {
|
|
162
161
|
}
|
|
163
162
|
|
|
164
|
-
export type PersistenceModelType<Encoded> = Encoded & {
|
|
163
|
+
export type PersistenceModelType<Encoded extends Object> = Encoded & {
|
|
165
164
|
_etag?: string | undefined
|
|
166
165
|
}
|
|
167
166
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.test.d.ts","sourceRoot":"","sources":["../query.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAQ,KAAK,EAAgB,CAAC,
|
|
1
|
+
{"version":3,"file":"query.test.d.ts","sourceRoot":"","sources":["../query.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAQ,KAAK,EAAgB,CAAC,EAAU,MAAM,YAAY,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYlF,qBAAa,SAAU,SAAQ,cAK7B;CAAG;AACL,MAAM,CAAC,OAAO,WAAW,SAAS,CAAC;IACjC,UAAiB,OAAQ,SAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,SAAS,CAAC;KAAG;CACvE;;;;;;;;;;;;;;;;;;;;;;;;;AAGD,qBAAa,WAAY,SAAQ,gBAAgE;CAAG"}
|
package/test/query.test.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { Effect, flow, Layer, Option, pipe, S } from "effect-app"
|
|
2
|
-
import { TagClassMakeId } from "effect-app/service"
|
|
3
|
-
import { pick } from "effect-app/utils"
|
|
1
|
+
import { Context, Effect, flow, Layer, Option, pipe, S, Struct } from "effect-app"
|
|
4
2
|
import { inspect } from "util"
|
|
5
3
|
import { expect, it } from "vitest"
|
|
6
4
|
import { and, make, one, or, order, page, project, toFilter, where } from "../src/services/query.js"
|
|
@@ -23,7 +21,7 @@ export declare namespace Something {
|
|
|
23
21
|
}
|
|
24
22
|
|
|
25
23
|
const MakeSomeService = Effect.succeed({ a: 1 })
|
|
26
|
-
export class SomeService extends
|
|
24
|
+
export class SomeService extends Context.TagMakeId("SomeService", MakeSomeService)<SomeService>() {}
|
|
27
25
|
|
|
28
26
|
const q = make<Something.Encoded>()
|
|
29
27
|
.pipe( // provided automatically inside Repo.q2()
|
|
@@ -37,7 +35,7 @@ const q = make<Something.Encoded>()
|
|
|
37
35
|
project(
|
|
38
36
|
S.transformToOrFail(
|
|
39
37
|
S.struct({ id: S.StringId, displayName: S.string }), // for projection performance benefit, this should be limited to the fields interested, and leads to SELECT fields
|
|
40
|
-
S.struct(pick(Something.fields, "id", "displayName")),
|
|
38
|
+
S.struct(Struct.pick(Something.fields, "id", "displayName")),
|
|
41
39
|
(_) => Effect.andThen(SomeService, _)
|
|
42
40
|
)
|
|
43
41
|
)
|
|
@@ -87,7 +85,7 @@ it("works", () => {
|
|
|
87
85
|
|
|
88
86
|
const processed = memFilter(interpreted)(items.map((_) => S.encodeSync(Something)(_)))
|
|
89
87
|
|
|
90
|
-
expect(processed).toEqual(items.slice(0, 2).toReversed().map(
|
|
88
|
+
expect(processed).toEqual(items.slice(0, 2).toReversed().map(Struct.pick("id", "displayName")))
|
|
91
89
|
})
|
|
92
90
|
|
|
93
91
|
class SomethingRepo extends RepositoryDefaultImpl<SomethingRepo>()(
|
|
@@ -117,17 +115,16 @@ it("works with repo", () =>
|
|
|
117
115
|
order("displayName"),
|
|
118
116
|
page({ take: 10 }),
|
|
119
117
|
project(
|
|
120
|
-
S.
|
|
118
|
+
S.transformToOrFail(
|
|
121
119
|
S.struct({ displayName: S.string }), // for projection performance benefit, this should be limited to the fields interested, and leads to SELECT fields
|
|
122
|
-
S.struct(pick(Something.fields, "displayName")),
|
|
123
|
-
(_) => Effect.andThen(SomeService, _)
|
|
124
|
-
() => Effect.die(new Error("not implemented"))
|
|
120
|
+
S.struct(Struct.pick(Something.fields, "displayName")),
|
|
121
|
+
(_) => Effect.andThen(SomeService, _)
|
|
125
122
|
)
|
|
126
123
|
)
|
|
127
124
|
))
|
|
128
125
|
)
|
|
129
|
-
expect(q1).toEqual(items.slice(0, 2).toReversed().map(
|
|
130
|
-
expect(q2).toEqual(items.slice(0, 2).toReversed().map(
|
|
126
|
+
expect(q1).toEqual(items.slice(0, 2).toReversed().map(Struct.pick("id", "displayName")))
|
|
127
|
+
expect(q2).toEqual(items.slice(0, 2).toReversed().map(Struct.pick("displayName")))
|
|
131
128
|
})
|
|
132
129
|
.pipe(Effect.provide(Layer.mergeAll(SomethingRepo.Test, SomeService.toLayer())), Effect.runPromise))
|
|
133
130
|
|
|
@@ -145,7 +142,7 @@ it("collect", () =>
|
|
|
145
142
|
project(
|
|
146
143
|
S.transformTo(
|
|
147
144
|
// TODO: sample case with narrowing down a union?
|
|
148
|
-
S.encodedSchema(S.struct(pick(Something.fields, "displayName", "n"))), // for projection performance benefit, this should be limited to the fields interested, and leads to SELECT fields
|
|
145
|
+
S.encodedSchema(S.struct(Struct.pick(Something.fields, "displayName", "n"))), // for projection performance benefit, this should be limited to the fields interested, and leads to SELECT fields
|
|
149
146
|
S.typeSchema(S.option(S.string)),
|
|
150
147
|
(_) =>
|
|
151
148
|
_.displayName === "Riley" && _.n === "2020-01-01T00:00:00.000Z"
|
|
@@ -168,7 +165,7 @@ it("collect", () =>
|
|
|
168
165
|
project(
|
|
169
166
|
S.transformTo(
|
|
170
167
|
// TODO: sample case with narrowing down a union?
|
|
171
|
-
S.encodedSchema(S.struct(pick(Something.fields, "union"))), // for projection performance benefit, this should be limited to the fields interested, and leads to SELECT fields
|
|
168
|
+
S.encodedSchema(S.struct(Struct.pick(Something.fields, "union"))), // for projection performance benefit, this should be limited to the fields interested, and leads to SELECT fields
|
|
172
169
|
S.typeSchema(S.option(S.string)),
|
|
173
170
|
(_) =>
|
|
174
171
|
_.union._tag === "string"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"include": [
|
|
4
|
+
"examples"
|
|
5
|
+
],
|
|
6
|
+
"references": [
|
|
7
|
+
{
|
|
8
|
+
"path": "tsconfig.src.json"
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"compilerOptions": {
|
|
12
|
+
"tsBuildInfoFile": ".tsbuildinfo/examples.tsbuildinfo",
|
|
13
|
+
"rootDir": "examples",
|
|
14
|
+
"noEmit": true
|
|
15
|
+
}
|
|
16
|
+
}
|