@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.
Files changed (308) hide show
  1. package/CHANGELOG.md +1514 -0
  2. package/_check.sh +1 -1
  3. package/dist/CUPS.d.ts +15 -7
  4. package/dist/CUPS.d.ts.map +1 -1
  5. package/dist/CUPS.js +10 -12
  6. package/dist/Emailer/Sendgrid.d.ts +14 -14
  7. package/dist/Emailer/Sendgrid.d.ts.map +1 -1
  8. package/dist/Emailer/Sendgrid.js +16 -15
  9. package/dist/Emailer/fake.d.ts +1 -1
  10. package/dist/Emailer/service.d.ts +11 -5
  11. package/dist/Emailer/service.d.ts.map +1 -1
  12. package/dist/Emailer/service.js +3 -3
  13. package/dist/Emailer.d.ts +1 -1
  14. package/dist/MainFiberSet.d.ts +9 -9
  15. package/dist/MainFiberSet.d.ts.map +1 -1
  16. package/dist/MainFiberSet.js +3 -3
  17. package/dist/Model/Repository/Registry.d.ts +20 -0
  18. package/dist/Model/Repository/Registry.d.ts.map +1 -0
  19. package/dist/Model/Repository/Registry.js +17 -0
  20. package/dist/Model/Repository/ext.d.ts +33 -15
  21. package/dist/Model/Repository/ext.d.ts.map +1 -1
  22. package/dist/Model/Repository/ext.js +54 -2
  23. package/dist/Model/Repository/internal/internal.d.ts +6 -6
  24. package/dist/Model/Repository/internal/internal.d.ts.map +1 -1
  25. package/dist/Model/Repository/internal/internal.js +43 -32
  26. package/dist/Model/Repository/legacy.d.ts +1 -1
  27. package/dist/Model/Repository/makeRepo.d.ts +7 -6
  28. package/dist/Model/Repository/makeRepo.d.ts.map +1 -1
  29. package/dist/Model/Repository/makeRepo.js +5 -1
  30. package/dist/Model/Repository/service.d.ts +28 -23
  31. package/dist/Model/Repository/service.d.ts.map +1 -1
  32. package/dist/Model/Repository/validation.d.ts +142 -17
  33. package/dist/Model/Repository/validation.d.ts.map +1 -1
  34. package/dist/Model/Repository/validation.js +5 -5
  35. package/dist/Model/Repository.d.ts +2 -1
  36. package/dist/Model/Repository.d.ts.map +1 -1
  37. package/dist/Model/Repository.js +2 -1
  38. package/dist/Model/dsl.d.ts +4 -4
  39. package/dist/Model/dsl.d.ts.map +1 -1
  40. package/dist/Model/filter/filterApi.d.ts +5 -5
  41. package/dist/Model/filter/filterApi.d.ts.map +1 -1
  42. package/dist/Model/filter/types/errors.d.ts +1 -1
  43. package/dist/Model/filter/types/fields.d.ts +1 -1
  44. package/dist/Model/filter/types/path/common.d.ts +1 -1
  45. package/dist/Model/filter/types/path/eager.d.ts +1 -1
  46. package/dist/Model/filter/types/path/eager.d.ts.map +1 -1
  47. package/dist/Model/filter/types/path/eager.js +1 -1
  48. package/dist/Model/filter/types/path/index.d.ts +1 -1
  49. package/dist/Model/filter/types/utils.d.ts +1 -1
  50. package/dist/Model/filter/types/validator.d.ts +1 -1
  51. package/dist/Model/filter/types.d.ts +1 -1
  52. package/dist/Model/query/dsl.d.ts +25 -25
  53. package/dist/Model/query/dsl.d.ts.map +1 -1
  54. package/dist/Model/query/new-kid-interpreter.d.ts +6 -6
  55. package/dist/Model/query/new-kid-interpreter.d.ts.map +1 -1
  56. package/dist/Model/query/new-kid-interpreter.js +3 -3
  57. package/dist/Model/query.d.ts +1 -1
  58. package/dist/Model.d.ts +2 -1
  59. package/dist/Model.d.ts.map +1 -1
  60. package/dist/Model.js +2 -1
  61. package/dist/QueueMaker/SQLQueue.d.ts +6 -8
  62. package/dist/QueueMaker/SQLQueue.d.ts.map +1 -1
  63. package/dist/QueueMaker/SQLQueue.js +106 -115
  64. package/dist/QueueMaker/errors.d.ts +2 -2
  65. package/dist/QueueMaker/errors.d.ts.map +1 -1
  66. package/dist/QueueMaker/memQueue.d.ts +7 -4
  67. package/dist/QueueMaker/memQueue.d.ts.map +1 -1
  68. package/dist/QueueMaker/memQueue.js +52 -62
  69. package/dist/QueueMaker/sbqueue.d.ts +6 -3
  70. package/dist/QueueMaker/sbqueue.d.ts.map +1 -1
  71. package/dist/QueueMaker/sbqueue.js +39 -53
  72. package/dist/QueueMaker/service.d.ts +1 -1
  73. package/dist/RequestContext.d.ts +117 -31
  74. package/dist/RequestContext.d.ts.map +1 -1
  75. package/dist/RequestContext.js +7 -8
  76. package/dist/RequestFiberSet.d.ts +7 -7
  77. package/dist/RequestFiberSet.d.ts.map +1 -1
  78. package/dist/RequestFiberSet.js +5 -5
  79. package/dist/Store/ContextMapContainer.d.ts +20 -4
  80. package/dist/Store/ContextMapContainer.d.ts.map +1 -1
  81. package/dist/Store/ContextMapContainer.js +13 -3
  82. package/dist/Store/Cosmos/query.d.ts +1 -1
  83. package/dist/Store/Cosmos/query.d.ts.map +1 -1
  84. package/dist/Store/Cosmos/query.js +10 -12
  85. package/dist/Store/Cosmos.d.ts +1 -1
  86. package/dist/Store/Cosmos.d.ts.map +1 -1
  87. package/dist/Store/Cosmos.js +318 -240
  88. package/dist/Store/Disk.d.ts +2 -2
  89. package/dist/Store/Disk.d.ts.map +1 -1
  90. package/dist/Store/Disk.js +25 -22
  91. package/dist/Store/Memory.d.ts +4 -4
  92. package/dist/Store/Memory.d.ts.map +1 -1
  93. package/dist/Store/Memory.js +27 -22
  94. package/dist/Store/SQL/Pg.d.ts +4 -0
  95. package/dist/Store/SQL/Pg.d.ts.map +1 -0
  96. package/dist/Store/SQL/Pg.js +189 -0
  97. package/dist/Store/SQL/query.d.ts +38 -0
  98. package/dist/Store/SQL/query.d.ts.map +1 -0
  99. package/dist/Store/SQL/query.js +367 -0
  100. package/dist/Store/SQL.d.ts +20 -0
  101. package/dist/Store/SQL.d.ts.map +1 -0
  102. package/dist/Store/SQL.js +381 -0
  103. package/dist/Store/codeFilter.d.ts +1 -1
  104. package/dist/Store/codeFilter.d.ts.map +1 -1
  105. package/dist/Store/codeFilter.js +2 -1
  106. package/dist/Store/index.d.ts +5 -2
  107. package/dist/Store/index.d.ts.map +1 -1
  108. package/dist/Store/index.js +15 -3
  109. package/dist/Store/service.d.ts +18 -7
  110. package/dist/Store/service.d.ts.map +1 -1
  111. package/dist/Store/service.js +24 -6
  112. package/dist/Store/utils.d.ts +1 -1
  113. package/dist/Store/utils.d.ts.map +1 -1
  114. package/dist/Store/utils.js +3 -4
  115. package/dist/Store.d.ts +1 -1
  116. package/dist/adapters/SQL/Model.d.ts +30 -47
  117. package/dist/adapters/SQL/Model.d.ts.map +1 -1
  118. package/dist/adapters/SQL/Model.js +22 -14
  119. package/dist/adapters/SQL.d.ts +1 -1
  120. package/dist/adapters/ServiceBus.d.ts +11 -11
  121. package/dist/adapters/ServiceBus.d.ts.map +1 -1
  122. package/dist/adapters/ServiceBus.js +15 -17
  123. package/dist/adapters/cosmos-client.d.ts +3 -3
  124. package/dist/adapters/cosmos-client.d.ts.map +1 -1
  125. package/dist/adapters/cosmos-client.js +3 -3
  126. package/dist/adapters/index.d.ts +8 -2
  127. package/dist/adapters/index.d.ts.map +1 -1
  128. package/dist/adapters/index.js +8 -2
  129. package/dist/adapters/logger.d.ts +2 -2
  130. package/dist/adapters/logger.d.ts.map +1 -1
  131. package/dist/adapters/memQueue.d.ts +3 -3
  132. package/dist/adapters/memQueue.d.ts.map +1 -1
  133. package/dist/adapters/memQueue.js +3 -3
  134. package/dist/adapters/mongo-client.d.ts +3 -3
  135. package/dist/adapters/mongo-client.d.ts.map +1 -1
  136. package/dist/adapters/mongo-client.js +3 -3
  137. package/dist/adapters/redis-client.d.ts +4 -4
  138. package/dist/adapters/redis-client.d.ts.map +1 -1
  139. package/dist/adapters/redis-client.js +3 -3
  140. package/dist/api/ContextProvider.d.ts +8 -8
  141. package/dist/api/ContextProvider.d.ts.map +1 -1
  142. package/dist/api/ContextProvider.js +6 -6
  143. package/dist/api/codec.d.ts +1 -1
  144. package/dist/api/internal/RequestContextMiddleware.d.ts +2 -2
  145. package/dist/api/internal/RequestContextMiddleware.d.ts.map +1 -1
  146. package/dist/api/internal/RequestContextMiddleware.js +2 -2
  147. package/dist/api/internal/auth.d.ts +45 -7
  148. package/dist/api/internal/auth.d.ts.map +1 -1
  149. package/dist/api/internal/auth.js +160 -29
  150. package/dist/api/internal/events.d.ts +3 -3
  151. package/dist/api/internal/events.d.ts.map +1 -1
  152. package/dist/api/internal/events.js +12 -8
  153. package/dist/api/internal/health.d.ts +1 -1
  154. package/dist/api/layerUtils.d.ts +6 -6
  155. package/dist/api/layerUtils.d.ts.map +1 -1
  156. package/dist/api/layerUtils.js +5 -5
  157. package/dist/api/middlewares.d.ts +1 -1
  158. package/dist/api/reportError.d.ts +1 -1
  159. package/dist/api/routing/middleware/RouterMiddleware.d.ts +4 -4
  160. package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -1
  161. package/dist/api/routing/middleware/middleware.d.ts +50 -4
  162. package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
  163. package/dist/api/routing/middleware/middleware.js +79 -17
  164. package/dist/api/routing/middleware.d.ts +1 -2
  165. package/dist/api/routing/middleware.d.ts.map +1 -1
  166. package/dist/api/routing/middleware.js +1 -2
  167. package/dist/api/routing/schema/jwt.d.ts +2 -2
  168. package/dist/api/routing/schema/jwt.d.ts.map +1 -1
  169. package/dist/api/routing/schema/jwt.js +1 -1
  170. package/dist/api/routing/tsort.d.ts +1 -1
  171. package/dist/api/routing/tsort.d.ts.map +1 -1
  172. package/dist/api/routing/utils.d.ts +3 -3
  173. package/dist/api/routing/utils.d.ts.map +1 -1
  174. package/dist/api/routing.d.ts +32 -35
  175. package/dist/api/routing.d.ts.map +1 -1
  176. package/dist/api/routing.js +84 -36
  177. package/dist/api/setupRequest.d.ts +8 -5
  178. package/dist/api/setupRequest.d.ts.map +1 -1
  179. package/dist/api/setupRequest.js +14 -9
  180. package/dist/api/util.d.ts +1 -1
  181. package/dist/arbs.d.ts +1 -1
  182. package/dist/arbs.d.ts.map +1 -1
  183. package/dist/arbs.js +5 -3
  184. package/dist/errorReporter.d.ts +5 -5
  185. package/dist/errorReporter.d.ts.map +1 -1
  186. package/dist/errorReporter.js +20 -25
  187. package/dist/errors.d.ts +1 -1
  188. package/dist/fileUtil.d.ts +1 -1
  189. package/dist/fileUtil.d.ts.map +1 -1
  190. package/dist/fileUtil.js +3 -2
  191. package/dist/index.d.ts +1 -1
  192. package/dist/logger/jsonLogger.d.ts +1 -1
  193. package/dist/logger/logFmtLogger.d.ts +1 -1
  194. package/dist/logger/shared.d.ts +1 -1
  195. package/dist/logger/shared.js +2 -2
  196. package/dist/logger.d.ts +1 -1
  197. package/dist/logger.d.ts.map +1 -1
  198. package/dist/rateLimit.d.ts +9 -3
  199. package/dist/rateLimit.d.ts.map +1 -1
  200. package/dist/rateLimit.js +5 -11
  201. package/dist/test.d.ts +2 -2
  202. package/dist/test.d.ts.map +1 -1
  203. package/dist/test.js +1 -1
  204. package/dist/vitest.d.ts +1 -1
  205. package/examples/query.ts +39 -35
  206. package/package.json +41 -37
  207. package/src/CUPS.ts +9 -11
  208. package/src/Emailer/Sendgrid.ts +18 -15
  209. package/src/Emailer/service.ts +9 -3
  210. package/src/MainFiberSet.ts +5 -6
  211. package/src/Model/Repository/Registry.ts +33 -0
  212. package/src/Model/Repository/ext.ts +96 -10
  213. package/src/Model/Repository/internal/internal.ts +97 -88
  214. package/src/Model/Repository/makeRepo.ts +12 -10
  215. package/src/Model/Repository/service.ts +31 -22
  216. package/src/Model/Repository/validation.ts +4 -4
  217. package/src/Model/Repository.ts +1 -0
  218. package/src/Model/dsl.ts +3 -3
  219. package/src/Model/filter/types/path/eager.ts +1 -2
  220. package/src/Model/query/dsl.ts +18 -18
  221. package/src/Model/query/new-kid-interpreter.ts +2 -2
  222. package/src/Model.ts +1 -0
  223. package/src/QueueMaker/SQLQueue.ts +123 -154
  224. package/src/QueueMaker/memQueue.ts +85 -107
  225. package/src/QueueMaker/sbqueue.ts +54 -81
  226. package/src/RequestContext.ts +8 -10
  227. package/src/RequestFiberSet.ts +4 -4
  228. package/src/Store/ContextMapContainer.ts +41 -2
  229. package/src/Store/Cosmos/query.ts +16 -20
  230. package/src/Store/Cosmos.ts +452 -342
  231. package/src/Store/Disk.ts +52 -49
  232. package/src/Store/Memory.ts +55 -51
  233. package/src/Store/SQL/Pg.ts +318 -0
  234. package/src/Store/SQL/query.ts +409 -0
  235. package/src/Store/SQL.ts +668 -0
  236. package/src/Store/codeFilter.ts +1 -0
  237. package/src/Store/index.ts +17 -2
  238. package/src/Store/service.ts +32 -8
  239. package/src/Store/utils.ts +23 -22
  240. package/src/adapters/SQL/Model.ts +83 -72
  241. package/src/adapters/ServiceBus.ts +114 -118
  242. package/src/adapters/cosmos-client.ts +2 -2
  243. package/src/adapters/index.ts +7 -0
  244. package/src/adapters/memQueue.ts +2 -2
  245. package/src/adapters/mongo-client.ts +2 -2
  246. package/src/adapters/redis-client.ts +2 -2
  247. package/src/api/ContextProvider.ts +12 -13
  248. package/src/api/internal/RequestContextMiddleware.ts +1 -1
  249. package/src/api/internal/auth.ts +246 -44
  250. package/src/api/internal/events.ts +15 -10
  251. package/src/api/layerUtils.ts +8 -8
  252. package/src/api/routing/middleware/RouterMiddleware.ts +4 -4
  253. package/src/api/routing/middleware/middleware.ts +112 -15
  254. package/src/api/routing/middleware.ts +0 -2
  255. package/src/api/routing/schema/jwt.ts +2 -3
  256. package/src/api/routing.ts +153 -79
  257. package/src/api/setupRequest.ts +30 -10
  258. package/src/arbs.ts +4 -2
  259. package/src/errorReporter.ts +63 -75
  260. package/src/fileUtil.ts +2 -1
  261. package/src/logger/shared.ts +1 -1
  262. package/src/rateLimit.ts +30 -22
  263. package/src/test.ts +1 -1
  264. package/test/auth.test.ts +101 -0
  265. package/test/contextProvider.test.ts +11 -11
  266. package/test/controller.test.ts +27 -21
  267. package/test/dist/auth.test.d.ts.map +1 -0
  268. package/test/dist/contextProvider.test.d.ts.map +1 -1
  269. package/test/dist/controller.test.d.ts.map +1 -1
  270. package/test/dist/fixtures.d.ts +26 -12
  271. package/test/dist/fixtures.d.ts.map +1 -1
  272. package/test/dist/fixtures.js +12 -10
  273. package/test/dist/query.test.d.ts.map +1 -1
  274. package/test/dist/rawQuery.test.d.ts.map +1 -1
  275. package/test/dist/repository-ext.test.d.ts.map +1 -0
  276. package/test/dist/requires.test.d.ts.map +1 -1
  277. package/test/dist/router-generator.test.d.ts.map +1 -0
  278. package/test/dist/routing-interruptibility.test.d.ts.map +1 -0
  279. package/test/dist/rpc-e2e-invalidation.test.d.ts.map +1 -0
  280. package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
  281. package/test/dist/rpc-stream-fullstack.test.d.ts.map +1 -0
  282. package/test/dist/sql-store.test.d.ts.map +1 -0
  283. package/test/fixtures.ts +11 -9
  284. package/test/query.test.ts +216 -36
  285. package/test/rawQuery.test.ts +23 -19
  286. package/test/repository-ext.test.ts +60 -0
  287. package/test/requires.test.ts +6 -6
  288. package/test/router-generator.test.ts +180 -0
  289. package/test/routing-interruptibility.test.ts +63 -0
  290. package/test/rpc-e2e-invalidation.test.ts +507 -0
  291. package/test/rpc-multi-middleware.test.ts +79 -10
  292. package/test/rpc-stream-fullstack.test.ts +325 -0
  293. package/test/sql-store.test.ts +1064 -0
  294. package/test/validateSample.test.ts +15 -12
  295. package/tsconfig.examples.json +1 -1
  296. package/tsconfig.json +0 -1
  297. package/tsconfig.json.bak +2 -2
  298. package/tsconfig.src.json +35 -35
  299. package/tsconfig.test.json +2 -2
  300. package/dist/Operations.d.ts +0 -55
  301. package/dist/Operations.d.ts.map +0 -1
  302. package/dist/Operations.js +0 -102
  303. package/dist/OperationsRepo.d.ts +0 -41
  304. package/dist/OperationsRepo.d.ts.map +0 -1
  305. package/dist/OperationsRepo.js +0 -14
  306. package/eslint.config.mjs +0 -24
  307. package/src/Operations.ts +0 -235
  308. package/src/OperationsRepo.ts +0 -16
@@ -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(cfg: StorageConfig) {
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"
@@ -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, ServiceMap } from "effect-app"
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
- * currently only supported in disk/memory. CosmosDB is TODO.
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 ServiceMap.Opaque<StoreMaker, {
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
- // parserEnv
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 ServiceMap.Opaque<ContextMap>()("effect-app/ContextMap", { make: makeMap }) {
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<string>
205
+ url: Redacted.Redacted
182
206
  prefix: string
183
207
  dbName: string
184
208
  }
@@ -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
- (type: string) =>
17
- <IdKey extends keyof E, E extends PersistenceModelType<{}>>(e: E, idKey: IdKey, current: Option.Option<E>) =>
18
- Effect.gen(function*() {
19
- if (e._etag) {
20
- if (Option.isNone(current)) {
21
- return yield* new OptimisticConcurrencyException({
22
- type,
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: current.value[idKey] as string,
34
- current: current.value._etag,
25
+ id: e[idKey] as string,
26
+ current: "",
35
27
  found: e._etag,
36
- code: 412
28
+ code: 409
37
29
  })
38
30
  }
39
- const newE = makeETag(e)
40
- return newE
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
- extends
195
- VariantSchema.Field<{
196
- readonly select: S
197
- readonly insert: S
198
- readonly update: S
199
- readonly json: S
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
- extends
550
- VariantSchema.Field<{
551
- readonly select: Schema.fromJsonString<S>
552
- readonly insert: Schema.fromJsonString<S>
553
- readonly update: Schema.fromJsonString<S>
554
- readonly json: S
555
- readonly jsonCreate: S
556
- readonly jsonUpdate: S
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.ordered({
829
- Request: Model.insert,
830
- Result: Model,
831
- execute: (request: any) =>
832
- sql.onDialectOrElse({
833
- mysql: () =>
834
- Effect.forEach(request, (request: any) =>
835
- sql`insert into ${sql(options.tableName)} ${sql.insert(request)};
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
- .unprepared
838
- .pipe(
839
- Effect.map(([, results]) => results![0] as any)
840
- ), { concurrency: 10 }),
841
- orElse: () => sql`insert into ${sql(options.tableName)} ${sql.insert(request).returning("*")}`
842
- })
843
- }).pipe(
844
- RequestResolver.setDelay(options.window),
845
- setMaxBatchSize,
846
- RequestResolver.withSpan(`${options.spanPrefix}.insertResolver`)
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.void({
864
- Request: Model.insert,
865
- execute: (request: any) => sql`insert into ${sql(options.tableName)} ${sql.insert(request)}`
866
- }).pipe(
867
- RequestResolver.setDelay(options.window),
868
- setMaxBatchSize,
869
- RequestResolver.withSpan(`${options.spanPrefix}.insertVoidResolver`)
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.findById({
882
- Id: idSchema,
883
- Result: Model,
884
- ResultId(request: any) {
885
- return request[idColumn]
886
- },
887
- execute: (ids: any) => sql`select * from ${sql(options.tableName)} where ${sql.in(idColumn, ids)}`
888
- }).pipe(
889
- RequestResolver.setDelay(options.window),
890
- setMaxBatchSize,
891
- RequestResolver.withSpan(`${options.spanPrefix}.findByIdResolver`)
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.void({
908
- Request: idSchema,
909
- execute: (ids: any) => sql`delete from ${sql(options.tableName)} where ${sql.in(idColumn, ids)}`
910
- }).pipe(
911
- RequestResolver.setDelay(options.window),
912
- setMaxBatchSize,
913
- RequestResolver.withSpan(`${options.spanPrefix}.deleteResolver`)
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"]