@effect-app/infra 4.0.0-beta.2 → 4.0.0-beta.200
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 +1514 -0
- package/_check.sh +1 -1
- package/dist/CUPS.d.ts +15 -7
- package/dist/CUPS.d.ts.map +1 -1
- package/dist/CUPS.js +10 -12
- package/dist/Emailer/Sendgrid.d.ts +14 -14
- package/dist/Emailer/Sendgrid.d.ts.map +1 -1
- package/dist/Emailer/Sendgrid.js +16 -15
- package/dist/Emailer/fake.d.ts +1 -1
- package/dist/Emailer/service.d.ts +11 -5
- package/dist/Emailer/service.d.ts.map +1 -1
- package/dist/Emailer/service.js +3 -3
- package/dist/Emailer.d.ts +1 -1
- package/dist/MainFiberSet.d.ts +9 -9
- package/dist/MainFiberSet.d.ts.map +1 -1
- package/dist/MainFiberSet.js +3 -3
- package/dist/Model/Repository/Registry.d.ts +20 -0
- package/dist/Model/Repository/Registry.d.ts.map +1 -0
- package/dist/Model/Repository/Registry.js +17 -0
- package/dist/Model/Repository/ext.d.ts +33 -15
- package/dist/Model/Repository/ext.d.ts.map +1 -1
- package/dist/Model/Repository/ext.js +54 -2
- package/dist/Model/Repository/internal/internal.d.ts +6 -6
- package/dist/Model/Repository/internal/internal.d.ts.map +1 -1
- package/dist/Model/Repository/internal/internal.js +43 -32
- package/dist/Model/Repository/legacy.d.ts +1 -1
- package/dist/Model/Repository/makeRepo.d.ts +7 -6
- package/dist/Model/Repository/makeRepo.d.ts.map +1 -1
- package/dist/Model/Repository/makeRepo.js +5 -1
- package/dist/Model/Repository/service.d.ts +28 -23
- package/dist/Model/Repository/service.d.ts.map +1 -1
- package/dist/Model/Repository/validation.d.ts +142 -17
- package/dist/Model/Repository/validation.d.ts.map +1 -1
- package/dist/Model/Repository/validation.js +5 -5
- package/dist/Model/Repository.d.ts +2 -1
- package/dist/Model/Repository.d.ts.map +1 -1
- package/dist/Model/Repository.js +2 -1
- package/dist/Model/dsl.d.ts +4 -4
- package/dist/Model/dsl.d.ts.map +1 -1
- package/dist/Model/filter/filterApi.d.ts +5 -5
- package/dist/Model/filter/filterApi.d.ts.map +1 -1
- package/dist/Model/filter/types/errors.d.ts +1 -1
- package/dist/Model/filter/types/fields.d.ts +1 -1
- package/dist/Model/filter/types/path/common.d.ts +1 -1
- package/dist/Model/filter/types/path/eager.d.ts +1 -1
- package/dist/Model/filter/types/path/eager.d.ts.map +1 -1
- package/dist/Model/filter/types/path/eager.js +1 -1
- package/dist/Model/filter/types/path/index.d.ts +1 -1
- package/dist/Model/filter/types/utils.d.ts +1 -1
- package/dist/Model/filter/types/validator.d.ts +1 -1
- package/dist/Model/filter/types.d.ts +1 -1
- package/dist/Model/query/dsl.d.ts +25 -25
- package/dist/Model/query/dsl.d.ts.map +1 -1
- package/dist/Model/query/new-kid-interpreter.d.ts +6 -6
- package/dist/Model/query/new-kid-interpreter.d.ts.map +1 -1
- package/dist/Model/query/new-kid-interpreter.js +3 -3
- package/dist/Model/query.d.ts +1 -1
- package/dist/Model.d.ts +2 -1
- package/dist/Model.d.ts.map +1 -1
- package/dist/Model.js +2 -1
- package/dist/QueueMaker/SQLQueue.d.ts +6 -8
- package/dist/QueueMaker/SQLQueue.d.ts.map +1 -1
- package/dist/QueueMaker/SQLQueue.js +106 -115
- package/dist/QueueMaker/errors.d.ts +2 -2
- package/dist/QueueMaker/errors.d.ts.map +1 -1
- package/dist/QueueMaker/memQueue.d.ts +7 -4
- package/dist/QueueMaker/memQueue.d.ts.map +1 -1
- package/dist/QueueMaker/memQueue.js +52 -62
- package/dist/QueueMaker/sbqueue.d.ts +6 -3
- package/dist/QueueMaker/sbqueue.d.ts.map +1 -1
- package/dist/QueueMaker/sbqueue.js +39 -53
- package/dist/QueueMaker/service.d.ts +1 -1
- package/dist/RequestContext.d.ts +117 -31
- package/dist/RequestContext.d.ts.map +1 -1
- package/dist/RequestContext.js +7 -8
- package/dist/RequestFiberSet.d.ts +7 -7
- package/dist/RequestFiberSet.d.ts.map +1 -1
- package/dist/RequestFiberSet.js +5 -5
- package/dist/Store/ContextMapContainer.d.ts +20 -4
- package/dist/Store/ContextMapContainer.d.ts.map +1 -1
- package/dist/Store/ContextMapContainer.js +13 -3
- package/dist/Store/Cosmos/query.d.ts +1 -1
- package/dist/Store/Cosmos/query.d.ts.map +1 -1
- package/dist/Store/Cosmos/query.js +10 -12
- package/dist/Store/Cosmos.d.ts +1 -1
- package/dist/Store/Cosmos.d.ts.map +1 -1
- package/dist/Store/Cosmos.js +318 -240
- package/dist/Store/Disk.d.ts +2 -2
- package/dist/Store/Disk.d.ts.map +1 -1
- package/dist/Store/Disk.js +25 -22
- package/dist/Store/Memory.d.ts +4 -4
- package/dist/Store/Memory.d.ts.map +1 -1
- package/dist/Store/Memory.js +27 -22
- package/dist/Store/SQL/Pg.d.ts +4 -0
- package/dist/Store/SQL/Pg.d.ts.map +1 -0
- package/dist/Store/SQL/Pg.js +189 -0
- package/dist/Store/SQL/query.d.ts +38 -0
- package/dist/Store/SQL/query.d.ts.map +1 -0
- package/dist/Store/SQL/query.js +367 -0
- package/dist/Store/SQL.d.ts +20 -0
- package/dist/Store/SQL.d.ts.map +1 -0
- package/dist/Store/SQL.js +381 -0
- package/dist/Store/codeFilter.d.ts +1 -1
- package/dist/Store/codeFilter.d.ts.map +1 -1
- package/dist/Store/codeFilter.js +2 -1
- package/dist/Store/index.d.ts +5 -2
- package/dist/Store/index.d.ts.map +1 -1
- package/dist/Store/index.js +15 -3
- package/dist/Store/service.d.ts +18 -7
- package/dist/Store/service.d.ts.map +1 -1
- package/dist/Store/service.js +24 -6
- package/dist/Store/utils.d.ts +1 -1
- package/dist/Store/utils.d.ts.map +1 -1
- package/dist/Store/utils.js +3 -4
- package/dist/Store.d.ts +1 -1
- package/dist/adapters/SQL/Model.d.ts +30 -47
- package/dist/adapters/SQL/Model.d.ts.map +1 -1
- package/dist/adapters/SQL/Model.js +22 -14
- package/dist/adapters/SQL.d.ts +1 -1
- package/dist/adapters/ServiceBus.d.ts +11 -11
- package/dist/adapters/ServiceBus.d.ts.map +1 -1
- package/dist/adapters/ServiceBus.js +15 -17
- package/dist/adapters/cosmos-client.d.ts +3 -3
- package/dist/adapters/cosmos-client.d.ts.map +1 -1
- package/dist/adapters/cosmos-client.js +3 -3
- package/dist/adapters/index.d.ts +8 -2
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +8 -2
- package/dist/adapters/logger.d.ts +2 -2
- package/dist/adapters/logger.d.ts.map +1 -1
- package/dist/adapters/memQueue.d.ts +3 -3
- package/dist/adapters/memQueue.d.ts.map +1 -1
- package/dist/adapters/memQueue.js +3 -3
- package/dist/adapters/mongo-client.d.ts +3 -3
- package/dist/adapters/mongo-client.d.ts.map +1 -1
- package/dist/adapters/mongo-client.js +3 -3
- package/dist/adapters/redis-client.d.ts +4 -4
- package/dist/adapters/redis-client.d.ts.map +1 -1
- package/dist/adapters/redis-client.js +3 -3
- package/dist/api/ContextProvider.d.ts +8 -8
- package/dist/api/ContextProvider.d.ts.map +1 -1
- package/dist/api/ContextProvider.js +6 -6
- package/dist/api/codec.d.ts +1 -1
- package/dist/api/internal/RequestContextMiddleware.d.ts +2 -2
- package/dist/api/internal/RequestContextMiddleware.d.ts.map +1 -1
- package/dist/api/internal/RequestContextMiddleware.js +2 -2
- package/dist/api/internal/auth.d.ts +45 -7
- package/dist/api/internal/auth.d.ts.map +1 -1
- package/dist/api/internal/auth.js +160 -29
- package/dist/api/internal/events.d.ts +3 -3
- package/dist/api/internal/events.d.ts.map +1 -1
- package/dist/api/internal/events.js +12 -8
- package/dist/api/internal/health.d.ts +1 -1
- package/dist/api/layerUtils.d.ts +6 -6
- package/dist/api/layerUtils.d.ts.map +1 -1
- package/dist/api/layerUtils.js +5 -5
- package/dist/api/middlewares.d.ts +1 -1
- package/dist/api/reportError.d.ts +1 -1
- package/dist/api/routing/middleware/RouterMiddleware.d.ts +4 -4
- package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.d.ts +50 -4
- package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.js +79 -17
- package/dist/api/routing/middleware.d.ts +1 -2
- package/dist/api/routing/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware.js +1 -2
- package/dist/api/routing/schema/jwt.d.ts +2 -2
- package/dist/api/routing/schema/jwt.d.ts.map +1 -1
- package/dist/api/routing/schema/jwt.js +1 -1
- package/dist/api/routing/tsort.d.ts +1 -1
- package/dist/api/routing/tsort.d.ts.map +1 -1
- package/dist/api/routing/utils.d.ts +3 -3
- package/dist/api/routing/utils.d.ts.map +1 -1
- package/dist/api/routing.d.ts +32 -35
- package/dist/api/routing.d.ts.map +1 -1
- package/dist/api/routing.js +84 -36
- package/dist/api/setupRequest.d.ts +8 -5
- package/dist/api/setupRequest.d.ts.map +1 -1
- package/dist/api/setupRequest.js +14 -9
- package/dist/api/util.d.ts +1 -1
- package/dist/arbs.d.ts +1 -1
- package/dist/arbs.d.ts.map +1 -1
- package/dist/arbs.js +5 -3
- package/dist/errorReporter.d.ts +5 -5
- package/dist/errorReporter.d.ts.map +1 -1
- package/dist/errorReporter.js +20 -25
- package/dist/errors.d.ts +1 -1
- package/dist/fileUtil.d.ts +1 -1
- package/dist/fileUtil.d.ts.map +1 -1
- package/dist/fileUtil.js +3 -2
- package/dist/index.d.ts +1 -1
- package/dist/logger/jsonLogger.d.ts +1 -1
- package/dist/logger/logFmtLogger.d.ts +1 -1
- package/dist/logger/shared.d.ts +1 -1
- package/dist/logger/shared.js +2 -2
- package/dist/logger.d.ts +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/rateLimit.d.ts +9 -3
- package/dist/rateLimit.d.ts.map +1 -1
- package/dist/rateLimit.js +5 -11
- package/dist/test.d.ts +2 -2
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +1 -1
- package/dist/vitest.d.ts +1 -1
- package/examples/query.ts +39 -35
- package/package.json +41 -37
- package/src/CUPS.ts +9 -11
- package/src/Emailer/Sendgrid.ts +18 -15
- package/src/Emailer/service.ts +9 -3
- package/src/MainFiberSet.ts +5 -6
- package/src/Model/Repository/Registry.ts +33 -0
- package/src/Model/Repository/ext.ts +96 -10
- package/src/Model/Repository/internal/internal.ts +97 -88
- package/src/Model/Repository/makeRepo.ts +12 -10
- package/src/Model/Repository/service.ts +31 -22
- package/src/Model/Repository/validation.ts +4 -4
- package/src/Model/Repository.ts +1 -0
- package/src/Model/dsl.ts +3 -3
- package/src/Model/filter/types/path/eager.ts +1 -2
- package/src/Model/query/dsl.ts +18 -18
- package/src/Model/query/new-kid-interpreter.ts +2 -2
- package/src/Model.ts +1 -0
- package/src/QueueMaker/SQLQueue.ts +123 -154
- package/src/QueueMaker/memQueue.ts +85 -107
- package/src/QueueMaker/sbqueue.ts +54 -81
- package/src/RequestContext.ts +8 -10
- package/src/RequestFiberSet.ts +4 -4
- package/src/Store/ContextMapContainer.ts +41 -2
- package/src/Store/Cosmos/query.ts +16 -20
- package/src/Store/Cosmos.ts +452 -342
- package/src/Store/Disk.ts +52 -49
- package/src/Store/Memory.ts +55 -51
- package/src/Store/SQL/Pg.ts +318 -0
- package/src/Store/SQL/query.ts +409 -0
- package/src/Store/SQL.ts +668 -0
- package/src/Store/codeFilter.ts +1 -0
- package/src/Store/index.ts +17 -2
- package/src/Store/service.ts +32 -8
- package/src/Store/utils.ts +23 -22
- package/src/adapters/SQL/Model.ts +83 -72
- package/src/adapters/ServiceBus.ts +114 -118
- package/src/adapters/cosmos-client.ts +2 -2
- package/src/adapters/index.ts +7 -0
- package/src/adapters/memQueue.ts +2 -2
- package/src/adapters/mongo-client.ts +2 -2
- package/src/adapters/redis-client.ts +2 -2
- package/src/api/ContextProvider.ts +12 -13
- package/src/api/internal/RequestContextMiddleware.ts +1 -1
- package/src/api/internal/auth.ts +246 -44
- package/src/api/internal/events.ts +15 -10
- package/src/api/layerUtils.ts +8 -8
- package/src/api/routing/middleware/RouterMiddleware.ts +4 -4
- package/src/api/routing/middleware/middleware.ts +112 -15
- package/src/api/routing/middleware.ts +0 -2
- package/src/api/routing/schema/jwt.ts +2 -3
- package/src/api/routing.ts +153 -79
- package/src/api/setupRequest.ts +30 -10
- package/src/arbs.ts +4 -2
- package/src/errorReporter.ts +63 -75
- package/src/fileUtil.ts +2 -1
- package/src/logger/shared.ts +1 -1
- package/src/rateLimit.ts +30 -22
- package/src/test.ts +1 -1
- package/test/auth.test.ts +101 -0
- package/test/contextProvider.test.ts +11 -11
- package/test/controller.test.ts +27 -21
- package/test/dist/auth.test.d.ts.map +1 -0
- package/test/dist/contextProvider.test.d.ts.map +1 -1
- package/test/dist/controller.test.d.ts.map +1 -1
- package/test/dist/fixtures.d.ts +26 -12
- package/test/dist/fixtures.d.ts.map +1 -1
- package/test/dist/fixtures.js +12 -10
- package/test/dist/query.test.d.ts.map +1 -1
- package/test/dist/rawQuery.test.d.ts.map +1 -1
- package/test/dist/repository-ext.test.d.ts.map +1 -0
- package/test/dist/requires.test.d.ts.map +1 -1
- package/test/dist/router-generator.test.d.ts.map +1 -0
- package/test/dist/routing-interruptibility.test.d.ts.map +1 -0
- package/test/dist/rpc-e2e-invalidation.test.d.ts.map +1 -0
- package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
- package/test/dist/rpc-stream-fullstack.test.d.ts.map +1 -0
- package/test/dist/sql-store.test.d.ts.map +1 -0
- package/test/fixtures.ts +11 -9
- package/test/query.test.ts +216 -36
- package/test/rawQuery.test.ts +23 -19
- package/test/repository-ext.test.ts +60 -0
- package/test/requires.test.ts +6 -6
- package/test/router-generator.test.ts +180 -0
- package/test/routing-interruptibility.test.ts +63 -0
- package/test/rpc-e2e-invalidation.test.ts +507 -0
- package/test/rpc-multi-middleware.test.ts +79 -10
- package/test/rpc-stream-fullstack.test.ts +325 -0
- package/test/sql-store.test.ts +1064 -0
- package/test/validateSample.test.ts +15 -12
- package/tsconfig.examples.json +1 -1
- package/tsconfig.json +0 -1
- package/tsconfig.json.bak +2 -2
- package/tsconfig.src.json +35 -35
- package/tsconfig.test.json +2 -2
- package/dist/Operations.d.ts +0 -55
- package/dist/Operations.d.ts.map +0 -1
- package/dist/Operations.js +0 -102
- package/dist/OperationsRepo.d.ts +0 -41
- package/dist/OperationsRepo.d.ts.map +0 -1
- package/dist/OperationsRepo.js +0 -14
- package/eslint.config.mjs +0 -24
- package/src/Operations.ts +0 -235
- package/src/OperationsRepo.ts +0 -16
package/src/Store/index.ts
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import { Effect, Layer, Redacted } from "effect-app"
|
|
3
|
+
import type { SqlClient } from "effect/unstable/sql"
|
|
3
4
|
import { CosmosStoreLayer } from "./Cosmos.js"
|
|
4
5
|
import { DiskStoreLayer } from "./Disk.js"
|
|
5
6
|
import { MemoryStoreLive } from "./Memory.js"
|
|
6
7
|
// import { RedisStoreLayer } from "./Redis.js"
|
|
8
|
+
import { RepositoryRegistryLive } from "../Model.js"
|
|
7
9
|
import type { StorageConfig } from "./service.js"
|
|
10
|
+
import { SQLiteStoreLayer } from "./SQL.js"
|
|
11
|
+
import { PgStoreLayer } from "./SQL/Pg.js"
|
|
8
12
|
|
|
9
|
-
export function StoreMakerLayer(
|
|
13
|
+
export function StoreMakerLayer(
|
|
14
|
+
cfg: StorageConfig,
|
|
15
|
+
options?: { makeSqlClientLayer?: (namespace: string) => Layer.Layer<SqlClient.SqlClient> }
|
|
16
|
+
) {
|
|
10
17
|
return Effect
|
|
11
18
|
.sync(() => {
|
|
12
19
|
const storageUrl = Redacted.value(cfg.url)
|
|
@@ -19,6 +26,14 @@ export function StoreMakerLayer(cfg: StorageConfig) {
|
|
|
19
26
|
console.log("Using disk store at " + dir)
|
|
20
27
|
return DiskStoreLayer(cfg, dir)
|
|
21
28
|
}
|
|
29
|
+
if (storageUrl.startsWith("sqlite://")) {
|
|
30
|
+
console.log("Using SQLite store")
|
|
31
|
+
return SQLiteStoreLayer(cfg, options)
|
|
32
|
+
}
|
|
33
|
+
if (storageUrl.startsWith("pg://")) {
|
|
34
|
+
console.log("Using PostgreSQL store")
|
|
35
|
+
return PgStoreLayer(cfg)
|
|
36
|
+
}
|
|
22
37
|
// if (storageUrl.startsWith("redis://")) {
|
|
23
38
|
// console.log("Using Redis store")
|
|
24
39
|
// return RedisStoreLayer(cfg)
|
|
@@ -27,7 +42,7 @@ export function StoreMakerLayer(cfg: StorageConfig) {
|
|
|
27
42
|
console.log("Using Cosmos DB store")
|
|
28
43
|
return CosmosStoreLayer(cfg)
|
|
29
44
|
})
|
|
30
|
-
.pipe(Layer.unwrap)
|
|
45
|
+
.pipe(Layer.unwrap, Layer.merge(RepositoryRegistryLive))
|
|
31
46
|
}
|
|
32
47
|
|
|
33
48
|
export * from "./service.js"
|
package/src/Store/service.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import type { UniqueKey } from "@azure/cosmos"
|
|
3
|
-
import { Effect, type NonEmptyReadonlyArray, type Option, type Redacted
|
|
3
|
+
import { Context, Effect, type NonEmptyReadonlyArray, type Option, type Redacted } from "effect-app"
|
|
4
|
+
import * as Semaphore from "effect/Semaphore"
|
|
4
5
|
import type { OptimisticConcurrencyException } from "../errors.js"
|
|
5
6
|
import type { FilterResult } from "../Model/filter/filterApi.js"
|
|
6
7
|
import type { FieldValues } from "../Model/filter/types.js"
|
|
@@ -10,8 +11,8 @@ import { type RawQuery } from "../Model/query.js"
|
|
|
10
11
|
export interface StoreConfig<E> {
|
|
11
12
|
partitionValue: (e?: E) => string
|
|
12
13
|
/**
|
|
13
|
-
* Primarily used for testing, creating namespaces in the database to separate data e.g to run multiple tests in isolation within the same database
|
|
14
|
-
*
|
|
14
|
+
* Primarily used for testing, creating namespaces in the database to separate data e.g to run multiple tests in isolation within the same database.
|
|
15
|
+
* Memory/Disk use separate store instances per namespace. CosmosDB uses namespace-prefixed partition keys. SQL uses a `_namespace` column.
|
|
15
16
|
*/
|
|
16
17
|
allowNamespace?: (namespace: string) => boolean
|
|
17
18
|
/**
|
|
@@ -87,9 +88,14 @@ export interface Store<
|
|
|
87
88
|
) => Effect.Effect<NonEmptyReadonlyArray<PM>, OptimisticConcurrencyException>
|
|
88
89
|
batchRemove: (ids: NonEmptyReadonlyArray<Encoded[IdKey]>, partitionKey?: string) => Effect.Effect<void>
|
|
89
90
|
queryRaw: <Out>(query: RawQuery<Encoded, Out>) => Effect.Effect<readonly Out[]>
|
|
91
|
+
/**
|
|
92
|
+
* Explicitly seed a namespace. Primary is seeded eagerly on initialization.
|
|
93
|
+
* Non-primary namespaces must be seeded explicitly before use.
|
|
94
|
+
*/
|
|
95
|
+
seedNamespace: (namespace: string) => Effect.Effect<void>
|
|
90
96
|
}
|
|
91
97
|
|
|
92
|
-
export class StoreMaker extends
|
|
98
|
+
export class StoreMaker extends Context.Opaque<StoreMaker, {
|
|
93
99
|
make: <IdKey extends keyof Encoded, Encoded extends FieldValues, R = never, E = never>(
|
|
94
100
|
name: string,
|
|
95
101
|
idKey: IdKey,
|
|
@@ -161,16 +167,34 @@ export const makeContextMap = () => {
|
|
|
161
167
|
// }
|
|
162
168
|
// }
|
|
163
169
|
|
|
170
|
+
const store = new Map<symbol, unknown>()
|
|
171
|
+
const sem = Semaphore.makeUnsafe(1)
|
|
172
|
+
|
|
164
173
|
return {
|
|
165
174
|
get: getEtag,
|
|
166
|
-
set: setEtag
|
|
167
|
-
|
|
175
|
+
set: setEtag,
|
|
176
|
+
getOrCreateStore: <T>(key: symbol, make: () => T): T => {
|
|
177
|
+
let value = store.get(key) as T | undefined
|
|
178
|
+
if (value === undefined) {
|
|
179
|
+
value = make()
|
|
180
|
+
store.set(key, value)
|
|
181
|
+
}
|
|
182
|
+
return value
|
|
183
|
+
},
|
|
184
|
+
getOrCreateStoreEffect: <T, E, R>(key: symbol, make: Effect.Effect<T, E, R>): Effect.Effect<T, E, R> =>
|
|
185
|
+
sem.withPermits(1)(Effect.uninterruptible(Effect.gen(function*() {
|
|
186
|
+
const value = store.get(key) as T | undefined
|
|
187
|
+
if (value !== undefined) return value
|
|
188
|
+
const v = yield* make
|
|
189
|
+
store.set(key, v)
|
|
190
|
+
return v
|
|
191
|
+
})))
|
|
168
192
|
}
|
|
169
193
|
}
|
|
170
194
|
|
|
171
195
|
const makeMap = Effect.sync(() => makeContextMap())
|
|
172
196
|
|
|
173
|
-
export class ContextMap extends
|
|
197
|
+
export class ContextMap extends Context.Opaque<ContextMap>()("effect-app/ContextMap", { make: makeMap }) {
|
|
174
198
|
}
|
|
175
199
|
|
|
176
200
|
export type PersistenceModelType<Encoded extends object> = Encoded & {
|
|
@@ -178,7 +202,7 @@ export type PersistenceModelType<Encoded extends object> = Encoded & {
|
|
|
178
202
|
}
|
|
179
203
|
|
|
180
204
|
export interface StorageConfig {
|
|
181
|
-
url: Redacted.Redacted
|
|
205
|
+
url: Redacted.Redacted
|
|
182
206
|
prefix: string
|
|
183
207
|
dbName: string
|
|
184
208
|
}
|
package/src/Store/utils.ts
CHANGED
|
@@ -12,33 +12,34 @@ export const makeETag = <E extends PersistenceModelType<{}>>(
|
|
|
12
12
|
_etag: crypto.createHash("sha256").update(JSON.stringify(e)).digest("hex")
|
|
13
13
|
}) as any
|
|
14
14
|
|
|
15
|
-
export const makeUpdateETag =
|
|
16
|
-
(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
id: e[idKey] as string,
|
|
24
|
-
current: "",
|
|
25
|
-
found: e._etag,
|
|
26
|
-
code: 409
|
|
27
|
-
})
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
if (Option.isSome(current) && current.value._etag !== e._etag) {
|
|
15
|
+
export const makeUpdateETag = (type: string) =>
|
|
16
|
+
Effect.fnUntraced(function*<IdKey extends keyof E, E extends PersistenceModelType<{}>>(
|
|
17
|
+
e: E,
|
|
18
|
+
idKey: IdKey,
|
|
19
|
+
current: Option.Option<E>
|
|
20
|
+
) {
|
|
21
|
+
if (e._etag) {
|
|
22
|
+
if (Option.isNone(current)) {
|
|
31
23
|
return yield* new OptimisticConcurrencyException({
|
|
32
24
|
type,
|
|
33
|
-
id:
|
|
34
|
-
current:
|
|
25
|
+
id: e[idKey] as string,
|
|
26
|
+
current: "",
|
|
35
27
|
found: e._etag,
|
|
36
|
-
code:
|
|
28
|
+
code: 409
|
|
37
29
|
})
|
|
38
30
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
31
|
+
}
|
|
32
|
+
if (Option.isSome(current) && current.value._etag !== e._etag) {
|
|
33
|
+
return yield* new OptimisticConcurrencyException({
|
|
34
|
+
type,
|
|
35
|
+
id: current.value[idKey] as string,
|
|
36
|
+
current: current.value._etag,
|
|
37
|
+
found: e._etag,
|
|
38
|
+
code: 412
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
return makeETag(e)
|
|
42
|
+
})
|
|
42
43
|
|
|
43
44
|
export function lowercaseIfString<T>(val: T) {
|
|
44
45
|
if (typeof val === "string") {
|
|
@@ -7,10 +7,6 @@
|
|
|
7
7
|
/**
|
|
8
8
|
* @since 1.0.0
|
|
9
9
|
*/
|
|
10
|
-
import * as VariantSchema from "effect/unstable/schema/VariantSchema"
|
|
11
|
-
import { SqlClient } from "effect/unstable/sql/SqlClient"
|
|
12
|
-
import * as SqlResolver from "effect/unstable/sql/SqlResolver"
|
|
13
|
-
import * as SqlSchema from "effect/unstable/sql/SqlSchema"
|
|
14
10
|
import crypto from "crypto" // TODO
|
|
15
11
|
import type { Brand } from "effect/Brand"
|
|
16
12
|
import * as DateTime from "effect/DateTime"
|
|
@@ -24,6 +20,10 @@ import * as Schema from "effect/Schema"
|
|
|
24
20
|
import * as Getter from "effect/SchemaGetter"
|
|
25
21
|
import * as Transformation from "effect/SchemaTransformation"
|
|
26
22
|
import type { Scope } from "effect/Scope"
|
|
23
|
+
import * as VariantSchema from "effect/unstable/schema/VariantSchema"
|
|
24
|
+
import { SqlClient } from "effect/unstable/sql/SqlClient"
|
|
25
|
+
import * as SqlResolver from "effect/unstable/sql/SqlResolver"
|
|
26
|
+
import * as SqlSchema from "effect/unstable/sql/SqlSchema"
|
|
27
27
|
|
|
28
28
|
const {
|
|
29
29
|
Class,
|
|
@@ -190,14 +190,13 @@ export const Generated = <S extends Schema.Top>(
|
|
|
190
190
|
* @since 1.0.0
|
|
191
191
|
* @category generated
|
|
192
192
|
*/
|
|
193
|
-
export interface GeneratedByApp<S extends Schema.Top>
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}>
|
|
193
|
+
export interface GeneratedByApp<S extends Schema.Top> extends
|
|
194
|
+
VariantSchema.Field<{
|
|
195
|
+
readonly select: S
|
|
196
|
+
readonly insert: S
|
|
197
|
+
readonly update: S
|
|
198
|
+
readonly json: S
|
|
199
|
+
}>
|
|
201
200
|
{}
|
|
202
201
|
|
|
203
202
|
/**
|
|
@@ -303,8 +302,7 @@ export const FieldOption: <Field extends VariantSchema.Field<any> | Schema.Top>(
|
|
|
303
302
|
) => Field extends Schema.Top ? FieldOption<Field>
|
|
304
303
|
: Field extends VariantSchema.Field<infer S> ? VariantSchema.Field<
|
|
305
304
|
{
|
|
306
|
-
readonly [K in keyof S]: S[K] extends Schema.Top
|
|
307
|
-
? K extends VariantsDatabase ? Schema.OptionFromNullOr<S[K]>
|
|
305
|
+
readonly [K in keyof S]: S[K] extends Schema.Top ? K extends VariantsDatabase ? Schema.OptionFromNullOr<S[K]>
|
|
308
306
|
: optionalOption<S[K]>
|
|
309
307
|
: never
|
|
310
308
|
}
|
|
@@ -545,16 +543,21 @@ export const DateTimeUpdateFromNumber: DateTimeUpdateFromNumber = Field({
|
|
|
545
543
|
* @since 1.0.0
|
|
546
544
|
* @category json
|
|
547
545
|
*/
|
|
548
|
-
export interface JsonFromString<S extends Schema.Top>
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
546
|
+
export interface JsonFromString<S extends Schema.Top> extends
|
|
547
|
+
VariantSchema.Field<{
|
|
548
|
+
readonly select: Schema.fromJsonString<
|
|
549
|
+
Schema.Codec<S["Type"], Schema.Json, S["DecodingServices"], S["EncodingServices"]>
|
|
550
|
+
>
|
|
551
|
+
readonly insert: Schema.fromJsonString<
|
|
552
|
+
Schema.Codec<S["Type"], Schema.Json, S["DecodingServices"], S["EncodingServices"]>
|
|
553
|
+
>
|
|
554
|
+
readonly update: Schema.fromJsonString<
|
|
555
|
+
Schema.Codec<S["Type"], Schema.Json, S["DecodingServices"], S["EncodingServices"]>
|
|
556
|
+
>
|
|
557
|
+
readonly json: S
|
|
558
|
+
readonly jsonCreate: S
|
|
559
|
+
readonly jsonUpdate: S
|
|
560
|
+
}>
|
|
558
561
|
{}
|
|
559
562
|
|
|
560
563
|
/**
|
|
@@ -568,7 +571,7 @@ export interface JsonFromString<S extends Schema.Top>
|
|
|
568
571
|
export const JsonFromString = <S extends Schema.Top>(
|
|
569
572
|
schema: S
|
|
570
573
|
): JsonFromString<S> => {
|
|
571
|
-
const parsed = Schema.fromJsonString(schema)
|
|
574
|
+
const parsed = Schema.fromJsonString(Schema.toCodecJson(schema))
|
|
572
575
|
return Field({
|
|
573
576
|
select: parsed,
|
|
574
577
|
insert: parsed,
|
|
@@ -825,26 +828,28 @@ export const makeDataLoaders = <
|
|
|
825
828
|
const idColumn = options.idColumn as string
|
|
826
829
|
const setMaxBatchSize = options.maxBatchSize ? RequestResolver.batchN(options.maxBatchSize) : identity
|
|
827
830
|
|
|
828
|
-
const insertResolver = SqlResolver
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
831
|
+
const insertResolver = SqlResolver
|
|
832
|
+
.ordered({
|
|
833
|
+
Request: Model.insert,
|
|
834
|
+
Result: Model,
|
|
835
|
+
execute: (request: any) =>
|
|
836
|
+
sql.onDialectOrElse({
|
|
837
|
+
mysql: () =>
|
|
838
|
+
Effect.forEach(request, (request: any) =>
|
|
839
|
+
sql`insert into ${sql(options.tableName)} ${sql.insert(request)};
|
|
836
840
|
select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID();`
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
841
|
+
.unprepared
|
|
842
|
+
.pipe(
|
|
843
|
+
Effect.map(([, results]) => results![0] as any)
|
|
844
|
+
), { concurrency: 10 }),
|
|
845
|
+
orElse: () => sql`insert into ${sql(options.tableName)} ${sql.insert(request).returning("*")}`
|
|
846
|
+
})
|
|
847
|
+
})
|
|
848
|
+
.pipe(
|
|
849
|
+
RequestResolver.setDelay(options.window),
|
|
850
|
+
setMaxBatchSize,
|
|
851
|
+
RequestResolver.withSpan(`${options.spanPrefix}.insertResolver`)
|
|
852
|
+
)
|
|
848
853
|
const insertExecute = SqlResolver.request(insertResolver)
|
|
849
854
|
const insert = (
|
|
850
855
|
insert: S["insert"]["Type"]
|
|
@@ -860,14 +865,16 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID(
|
|
|
860
865
|
})
|
|
861
866
|
) as any
|
|
862
867
|
|
|
863
|
-
const insertVoidResolver = SqlResolver
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
868
|
+
const insertVoidResolver = SqlResolver
|
|
869
|
+
.void({
|
|
870
|
+
Request: Model.insert,
|
|
871
|
+
execute: (request: any) => sql`insert into ${sql(options.tableName)} ${sql.insert(request)}`
|
|
872
|
+
})
|
|
873
|
+
.pipe(
|
|
874
|
+
RequestResolver.setDelay(options.window),
|
|
875
|
+
setMaxBatchSize,
|
|
876
|
+
RequestResolver.withSpan(`${options.spanPrefix}.insertVoidResolver`)
|
|
877
|
+
)
|
|
871
878
|
const insertVoidExecute = SqlResolver.request(insertVoidResolver)
|
|
872
879
|
const insertVoid = (
|
|
873
880
|
insert: S["insert"]["Type"]
|
|
@@ -878,18 +885,20 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID(
|
|
|
878
885
|
})
|
|
879
886
|
) as any
|
|
880
887
|
|
|
881
|
-
const findByIdResolver = SqlResolver
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
888
|
+
const findByIdResolver = SqlResolver
|
|
889
|
+
.findById({
|
|
890
|
+
Id: idSchema,
|
|
891
|
+
Result: Model,
|
|
892
|
+
ResultId(request: any) {
|
|
893
|
+
return request[idColumn]
|
|
894
|
+
},
|
|
895
|
+
execute: (ids: any) => sql`select * from ${sql(options.tableName)} where ${sql.in(idColumn, ids)}`
|
|
896
|
+
})
|
|
897
|
+
.pipe(
|
|
898
|
+
RequestResolver.setDelay(options.window),
|
|
899
|
+
setMaxBatchSize,
|
|
900
|
+
RequestResolver.withSpan(`${options.spanPrefix}.findByIdResolver`)
|
|
901
|
+
)
|
|
893
902
|
const findByIdExecute = SqlResolver.request(findByIdResolver)
|
|
894
903
|
const findById = (
|
|
895
904
|
id: S["fields"][Id]["Type"]
|
|
@@ -904,14 +913,16 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID(
|
|
|
904
913
|
})
|
|
905
914
|
) as any
|
|
906
915
|
|
|
907
|
-
const deleteResolver = SqlResolver
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
916
|
+
const deleteResolver = SqlResolver
|
|
917
|
+
.void({
|
|
918
|
+
Request: idSchema,
|
|
919
|
+
execute: (ids: any) => sql`delete from ${sql(options.tableName)} where ${sql.in(idColumn, ids)}`
|
|
920
|
+
})
|
|
921
|
+
.pipe(
|
|
922
|
+
RequestResolver.setDelay(options.window),
|
|
923
|
+
setMaxBatchSize,
|
|
924
|
+
RequestResolver.withSpan(`${options.spanPrefix}.deleteResolver`)
|
|
925
|
+
)
|
|
915
926
|
const deleteExecute = SqlResolver.request(deleteResolver)
|
|
916
927
|
const delete_ = (
|
|
917
928
|
id: S["fields"][Id]["Type"]
|