@effect-app/infra 3.10.0 → 4.0.0-beta.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.
Files changed (231) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/_check.sh +3 -0
  3. package/dist/CUPS.d.ts +22 -12
  4. package/dist/CUPS.d.ts.map +1 -1
  5. package/dist/CUPS.js +28 -29
  6. package/dist/Emailer/Sendgrid.js +13 -12
  7. package/dist/Emailer/service.d.ts +3 -13
  8. package/dist/Emailer/service.d.ts.map +1 -1
  9. package/dist/Emailer/service.js +3 -3
  10. package/dist/MainFiberSet.d.ts +18 -41
  11. package/dist/MainFiberSet.d.ts.map +1 -1
  12. package/dist/MainFiberSet.js +10 -10
  13. package/dist/Model/Repository/ext.d.ts.map +1 -1
  14. package/dist/Model/Repository/ext.js +13 -10
  15. package/dist/Model/Repository/internal/internal.d.ts +5 -5
  16. package/dist/Model/Repository/internal/internal.d.ts.map +1 -1
  17. package/dist/Model/Repository/internal/internal.js +52 -42
  18. package/dist/Model/Repository/legacy.d.ts +9 -9
  19. package/dist/Model/Repository/legacy.d.ts.map +1 -1
  20. package/dist/Model/Repository/makeRepo.d.ts +4 -4
  21. package/dist/Model/Repository/makeRepo.d.ts.map +1 -1
  22. package/dist/Model/Repository/makeRepo.js +1 -1
  23. package/dist/Model/Repository/service.d.ts +11 -11
  24. package/dist/Model/Repository/service.d.ts.map +1 -1
  25. package/dist/Model/Repository/validation.d.ts +17 -47
  26. package/dist/Model/Repository/validation.d.ts.map +1 -1
  27. package/dist/Model/Repository/validation.js +2 -2
  28. package/dist/Model/query/dsl.d.ts +22 -22
  29. package/dist/Model/query/dsl.d.ts.map +1 -1
  30. package/dist/Model/query/dsl.js +1 -1
  31. package/dist/Model/query/new-kid-interpreter.d.ts +1 -1
  32. package/dist/Model/query/new-kid-interpreter.js +7 -7
  33. package/dist/Operations.d.ts +22 -63
  34. package/dist/Operations.d.ts.map +1 -1
  35. package/dist/Operations.js +14 -14
  36. package/dist/OperationsRepo.d.ts +23 -7
  37. package/dist/OperationsRepo.d.ts.map +1 -1
  38. package/dist/OperationsRepo.js +4 -5
  39. package/dist/QueueMaker/SQLQueue.d.ts +6 -8
  40. package/dist/QueueMaker/SQLQueue.d.ts.map +1 -1
  41. package/dist/QueueMaker/SQLQueue.js +20 -24
  42. package/dist/QueueMaker/errors.js +1 -1
  43. package/dist/QueueMaker/memQueue.d.ts +2 -5
  44. package/dist/QueueMaker/memQueue.d.ts.map +1 -1
  45. package/dist/QueueMaker/memQueue.js +22 -26
  46. package/dist/QueueMaker/sbqueue.d.ts +2 -5
  47. package/dist/QueueMaker/sbqueue.d.ts.map +1 -1
  48. package/dist/QueueMaker/sbqueue.js +24 -28
  49. package/dist/RequestContext.d.ts +28 -41
  50. package/dist/RequestContext.d.ts.map +1 -1
  51. package/dist/RequestContext.js +4 -4
  52. package/dist/RequestFiberSet.d.ts +23 -50
  53. package/dist/RequestFiberSet.d.ts.map +1 -1
  54. package/dist/RequestFiberSet.js +14 -14
  55. package/dist/Store/ContextMapContainer.d.ts +4 -4
  56. package/dist/Store/ContextMapContainer.d.ts.map +1 -1
  57. package/dist/Store/ContextMapContainer.js +5 -5
  58. package/dist/Store/Cosmos.d.ts.map +1 -1
  59. package/dist/Store/Cosmos.js +21 -28
  60. package/dist/Store/Disk.d.ts.map +1 -1
  61. package/dist/Store/Disk.js +12 -16
  62. package/dist/Store/Memory.d.ts +2 -2
  63. package/dist/Store/Memory.d.ts.map +1 -1
  64. package/dist/Store/Memory.js +25 -33
  65. package/dist/Store/index.js +2 -2
  66. package/dist/Store/service.d.ts +9 -34
  67. package/dist/Store/service.d.ts.map +1 -1
  68. package/dist/Store/service.js +4 -4
  69. package/dist/Store/utils.d.ts.map +1 -1
  70. package/dist/Store/utils.js +10 -2
  71. package/dist/adapters/SQL/Model.d.ts +106 -162
  72. package/dist/adapters/SQL/Model.d.ts.map +1 -1
  73. package/dist/adapters/SQL/Model.js +92 -130
  74. package/dist/adapters/ServiceBus.d.ts +13 -44
  75. package/dist/adapters/ServiceBus.d.ts.map +1 -1
  76. package/dist/adapters/ServiceBus.js +13 -15
  77. package/dist/adapters/cosmos-client.d.ts +7 -3
  78. package/dist/adapters/cosmos-client.d.ts.map +1 -1
  79. package/dist/adapters/cosmos-client.js +5 -4
  80. package/dist/adapters/logger.d.ts +1 -1
  81. package/dist/adapters/logger.d.ts.map +1 -1
  82. package/dist/adapters/memQueue.d.ts +8 -21
  83. package/dist/adapters/memQueue.d.ts.map +1 -1
  84. package/dist/adapters/memQueue.js +4 -4
  85. package/dist/adapters/mongo-client.d.ts +6 -6
  86. package/dist/adapters/mongo-client.d.ts.map +1 -1
  87. package/dist/adapters/mongo-client.js +5 -4
  88. package/dist/adapters/redis-client.d.ts +14 -4
  89. package/dist/adapters/redis-client.d.ts.map +1 -1
  90. package/dist/adapters/redis-client.js +19 -18
  91. package/dist/api/ContextProvider.d.ts +10 -15
  92. package/dist/api/ContextProvider.d.ts.map +1 -1
  93. package/dist/api/ContextProvider.js +8 -8
  94. package/dist/api/codec.d.ts +1 -1
  95. package/dist/api/codec.d.ts.map +1 -1
  96. package/dist/api/codec.js +1 -1
  97. package/dist/api/internal/RequestContextMiddleware.d.ts +1 -1
  98. package/dist/api/internal/RequestContextMiddleware.d.ts.map +1 -1
  99. package/dist/api/internal/auth.d.ts +3 -3
  100. package/dist/api/internal/auth.d.ts.map +1 -1
  101. package/dist/api/internal/auth.js +8 -8
  102. package/dist/api/internal/events.d.ts +2 -2
  103. package/dist/api/internal/events.d.ts.map +1 -1
  104. package/dist/api/internal/events.js +9 -9
  105. package/dist/api/internal/health.d.ts +1 -1
  106. package/dist/api/internal/health.d.ts.map +1 -1
  107. package/dist/api/internal/health.js +2 -2
  108. package/dist/api/layerUtils.d.ts +14 -14
  109. package/dist/api/layerUtils.d.ts.map +1 -1
  110. package/dist/api/layerUtils.js +5 -5
  111. package/dist/api/middlewares.d.ts +0 -75
  112. package/dist/api/middlewares.d.ts.map +1 -1
  113. package/dist/api/middlewares.js +6 -51
  114. package/dist/api/reportError.js +4 -4
  115. package/dist/api/routing/middleware/RouterMiddleware.d.ts +4 -4
  116. package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -1
  117. package/dist/api/routing/middleware/middleware.d.ts +6 -7
  118. package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
  119. package/dist/api/routing/middleware/middleware.js +9 -13
  120. package/dist/api/routing/schema/jwt.d.ts +1 -1
  121. package/dist/api/routing/schema/jwt.d.ts.map +1 -1
  122. package/dist/api/routing/schema/jwt.js +5 -4
  123. package/dist/api/routing/utils.d.ts +2 -2
  124. package/dist/api/routing/utils.d.ts.map +1 -1
  125. package/dist/api/routing/utils.js +10 -8
  126. package/dist/api/routing.d.ts +39 -37
  127. package/dist/api/routing.d.ts.map +1 -1
  128. package/dist/api/routing.js +17 -21
  129. package/dist/api/setupRequest.d.ts +4 -6
  130. package/dist/api/setupRequest.d.ts.map +1 -1
  131. package/dist/api/setupRequest.js +10 -9
  132. package/dist/arbs.d.ts +3 -3
  133. package/dist/arbs.d.ts.map +1 -1
  134. package/dist/arbs.js +2 -2
  135. package/dist/errorReporter.d.ts +1 -1
  136. package/dist/errorReporter.d.ts.map +1 -1
  137. package/dist/errorReporter.js +12 -12
  138. package/dist/fileUtil.d.ts +6 -6
  139. package/dist/fileUtil.d.ts.map +1 -1
  140. package/dist/logger/jsonLogger.d.ts.map +1 -1
  141. package/dist/logger/jsonLogger.js +19 -18
  142. package/dist/logger/logFmtLogger.d.ts.map +1 -1
  143. package/dist/logger/logFmtLogger.js +11 -13
  144. package/dist/logger/shared.d.ts +2 -2
  145. package/dist/logger/shared.d.ts.map +1 -1
  146. package/dist/logger/shared.js +7 -9
  147. package/dist/logger.d.ts +1 -1
  148. package/dist/logger.d.ts.map +1 -1
  149. package/dist/rateLimit.d.ts +2 -2
  150. package/dist/rateLimit.d.ts.map +1 -1
  151. package/dist/rateLimit.js +5 -5
  152. package/dist/test.d.ts +2 -2
  153. package/dist/test.d.ts.map +1 -1
  154. package/dist/test.js +6 -24
  155. package/package.json +19 -22
  156. package/src/CUPS.ts +15 -14
  157. package/src/Emailer/Sendgrid.ts +15 -13
  158. package/src/Emailer/service.ts +3 -3
  159. package/src/MainFiberSet.ts +16 -12
  160. package/src/Model/Repository/ext.ts +18 -16
  161. package/src/Model/Repository/internal/internal.ts +80 -69
  162. package/src/Model/Repository/legacy.ts +9 -9
  163. package/src/Model/Repository/makeRepo.ts +5 -5
  164. package/src/Model/Repository/service.ts +12 -12
  165. package/src/Model/Repository/validation.ts +1 -1
  166. package/src/Model/query/dsl.ts +13 -13
  167. package/src/Model/query/new-kid-interpreter.ts +8 -8
  168. package/src/Operations.ts +17 -14
  169. package/src/OperationsRepo.ts +3 -4
  170. package/src/QueueMaker/SQLQueue.ts +86 -89
  171. package/src/QueueMaker/errors.ts +1 -1
  172. package/src/QueueMaker/memQueue.ts +90 -91
  173. package/src/QueueMaker/sbqueue.ts +90 -92
  174. package/src/RequestContext.ts +3 -3
  175. package/src/RequestFiberSet.ts +17 -15
  176. package/src/Store/ContextMapContainer.ts +4 -4
  177. package/src/Store/Cosmos.ts +20 -27
  178. package/src/Store/Disk.ts +13 -17
  179. package/src/Store/Memory.ts +28 -34
  180. package/src/Store/index.ts +1 -1
  181. package/src/Store/service.ts +4 -4
  182. package/src/Store/utils.ts +9 -5
  183. package/src/adapters/SQL/Model.ts +255 -268
  184. package/src/adapters/ServiceBus.ts +17 -20
  185. package/src/adapters/cosmos-client.ts +5 -5
  186. package/src/adapters/memQueue.ts +3 -3
  187. package/src/adapters/mongo-client.ts +5 -5
  188. package/src/adapters/redis-client.ts +25 -19
  189. package/src/api/ContextProvider.ts +24 -34
  190. package/src/api/codec.ts +1 -1
  191. package/src/api/internal/auth.ts +11 -13
  192. package/src/api/internal/events.ts +11 -11
  193. package/src/api/internal/health.ts +1 -1
  194. package/src/api/layerUtils.ts +20 -20
  195. package/src/api/middlewares.ts +0 -97
  196. package/src/api/reportError.ts +3 -3
  197. package/src/api/routing/middleware/RouterMiddleware.ts +5 -6
  198. package/src/api/routing/middleware/middleware.ts +13 -25
  199. package/src/api/routing/schema/jwt.ts +9 -7
  200. package/src/api/routing/utils.ts +12 -10
  201. package/src/api/routing.ts +77 -79
  202. package/src/api/setupRequest.ts +9 -8
  203. package/src/arbs.ts +3 -3
  204. package/src/errorReporter.ts +12 -12
  205. package/src/logger/jsonLogger.ts +18 -17
  206. package/src/logger/logFmtLogger.ts +10 -12
  207. package/src/logger/shared.ts +6 -8
  208. package/src/rateLimit.ts +7 -7
  209. package/src/test.ts +7 -29
  210. package/test/contextProvider.test.ts +77 -70
  211. package/test/controller.test.ts +51 -39
  212. package/test/dist/contextProvider.test.d.ts.map +1 -1
  213. package/test/dist/controller.test.d.ts.map +1 -1
  214. package/test/dist/fixtures.d.ts +33 -81
  215. package/test/dist/fixtures.d.ts.map +1 -1
  216. package/test/dist/fixtures.js +9 -8
  217. package/test/dist/query.test.d.ts.map +1 -1
  218. package/test/dist/rawQuery.test.d.ts.map +1 -1
  219. package/test/dist/requires.test.d.ts.map +1 -1
  220. package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
  221. package/test/fixtures.ts +9 -7
  222. package/test/query.test.ts +49 -41
  223. package/test/rawQuery.test.ts +44 -40
  224. package/test/requires.test.ts +40 -31
  225. package/test/rpc-multi-middleware.test.ts +13 -14
  226. package/test/validateSample.test.ts +2 -2
  227. package/tsconfig.json +1 -27
  228. package/dist/api/internal/middlewares.d.ts +0 -15
  229. package/dist/api/internal/middlewares.d.ts.map +0 -1
  230. package/dist/api/internal/middlewares.js +0 -168
  231. package/src/api/internal/middlewares.ts +0 -279
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
 
3
- import { Array, Chunk, Duration, Effect, Layer, type NonEmptyReadonlyArray, Option, pipe, Redacted, Struct } from "effect-app"
3
+ import { Array, Duration, Effect, Layer, type NonEmptyReadonlyArray, Option, pipe, Redacted, Struct } from "effect-app"
4
4
  import { toNonEmptyArray } from "effect-app/Array"
5
5
  import { dropUndefinedT, mutable } from "effect-app/utils"
6
6
  import { CosmosClient, CosmosClientLayer } from "../adapters/cosmos-client.js"
@@ -70,12 +70,12 @@ function makeCosmosStore({ prefix }: StorageConfig) {
70
70
  (x) =>
71
71
  [
72
72
  x,
73
- Option.match(Option.fromNullable(x._etag), {
73
+ Option.match(Option.fromNullishOr(x._etag), {
74
74
  onNone: () =>
75
75
  dropUndefinedT({
76
76
  operationType: "Create" as const,
77
77
  resourceBody: {
78
- ...Struct.omit(x, "_etag", idKey),
78
+ ...Struct.omit(x, ["_etag", idKey]),
79
79
  id: x[idKey],
80
80
  _partitionKey: config?.partitionValue(x)
81
81
  }
@@ -87,7 +87,7 @@ function makeCosmosStore({ prefix }: StorageConfig) {
87
87
  operationType: "Replace" as const,
88
88
  id: x[idKey],
89
89
  resourceBody: {
90
- ...Struct.omit(x, "_etag", idKey),
90
+ ...Struct.omit(x, ["_etag", idKey]),
91
91
  id: x[idKey],
92
92
  _partitionKey: config?.partitionValue(x)
93
93
  },
@@ -98,7 +98,7 @@ function makeCosmosStore({ prefix }: StorageConfig) {
98
98
  })
99
99
  ] as const
100
100
  )
101
- const batches = Chunk.toReadonlyArray(Array.chunk_(b, config?.maxBulkSize ?? 10))
101
+ const batches = Array.chunksOf(b, config?.maxBulkSize ?? 10)
102
102
 
103
103
  const batchResult = yield* Effect.forEach(
104
104
  batches
@@ -162,9 +162,8 @@ function makeCosmosStore({ prefix }: StorageConfig) {
162
162
  return batchResult.flat() as unknown as NonEmptyReadonlyArray<Encoded>
163
163
  })
164
164
  .pipe(Effect.withSpan("Cosmos.bulkSet [effect-app/infra/Store]", {
165
- captureStackTrace: false,
166
165
  attributes: { "repository.container_id": containerId, "repository.model_name": name }
167
- }))
166
+ }, { captureStackTrace: false }))
168
167
 
169
168
  const batchSet = (items: NonEmptyReadonlyArray<PM>) => {
170
169
  return Effect
@@ -173,11 +172,11 @@ function makeCosmosStore({ prefix }: StorageConfig) {
173
172
  (x) =>
174
173
  [
175
174
  x,
176
- Option.match(Option.fromNullable(x._etag), {
175
+ Option.match(Option.fromNullishOr(x._etag), {
177
176
  onNone: () => ({
178
177
  operationType: "Create" as const,
179
178
  resourceBody: {
180
- ...Struct.omit(x, "_etag", idKey),
179
+ ...Struct.omit(x, ["_etag", idKey]),
181
180
  id: x[idKey],
182
181
  _partitionKey: config?.partitionValue(x)
183
182
  }
@@ -188,7 +187,7 @@ function makeCosmosStore({ prefix }: StorageConfig) {
188
187
  operationType: "Replace" as const,
189
188
  id: x[idKey],
190
189
  resourceBody: {
191
- ...Struct.omit(x, "_etag", idKey),
190
+ ...Struct.omit(x, ["_etag", idKey]),
192
191
  id: x[idKey],
193
192
  _partitionKey: config?.partitionValue(x)
194
193
  },
@@ -228,9 +227,8 @@ function makeCosmosStore({ prefix }: StorageConfig) {
228
227
  })
229
228
  .pipe(Effect
230
229
  .withSpan("Cosmos.batchSet [effect-app/infra/Store]", {
231
- captureStackTrace: false,
232
230
  attributes: { "repository.container_id": containerId, "repository.model_name": name }
233
- }))
231
+ }, { captureStackTrace: false }))
234
232
  }
235
233
 
236
234
  const s: Store<IdKey, Encoded> = {
@@ -254,9 +252,8 @@ function makeCosmosStore({ prefix }: StorageConfig) {
254
252
  ),
255
253
  Effect
256
254
  .withSpan("Cosmos.queryRaw [effect-app/infra/Store]", {
257
- captureStackTrace: false,
258
255
  attributes: { "repository.container_id": containerId, "repository.model_name": name }
259
- })
256
+ }, { captureStackTrace: false })
260
257
  ),
261
258
  batchRemove: (ids, partitionKey?: string) =>
262
259
  Effect.promise(() =>
@@ -294,9 +291,8 @@ function makeCosmosStore({ prefix }: StorageConfig) {
294
291
  ),
295
292
  Effect
296
293
  .withSpan("Cosmos.all [effect-app/infra/Store]", {
297
- captureStackTrace: false,
298
294
  attributes: { "repository.container_id": containerId, "repository.model_name": name }
299
- })
295
+ }, { captureStackTrace: false })
300
296
  ),
301
297
  /**
302
298
  * May return duplicate results for "join_find", when matching more than once.
@@ -336,7 +332,7 @@ function makeCosmosStore({ prefix }: StorageConfig) {
336
332
  ({
337
333
  ...pipe(
338
334
  defaultValues,
339
- Struct.pick(...f.select!.filter((_) => typeof _ === "string"))
335
+ Struct.pick(f.select!.filter((_) => typeof _ === "string"))
340
336
  ),
341
337
  ...mapReverseId(_ as any)
342
338
  }) as any
@@ -354,9 +350,8 @@ function makeCosmosStore({ prefix }: StorageConfig) {
354
350
  )
355
351
  .pipe(
356
352
  Effect.withSpan("Cosmos.filter [effect-app/infra/Store]", {
357
- captureStackTrace: false,
358
353
  attributes: { "repository.container_id": containerId, "repository.model_name": name }
359
- })
354
+ }, { captureStackTrace: false })
360
355
  )
361
356
  },
362
357
  find: (id) =>
@@ -366,24 +361,23 @@ function makeCosmosStore({ prefix }: StorageConfig) {
366
361
  .item(id, config?.partitionValue({ [idKey]: id } as Encoded))
367
362
  .read<Encoded>()
368
363
  .then(({ resource }) =>
369
- Option.fromNullable(resource).pipe(Option.map((_) => ({ ...defaultValues, ...mapReverseId(_) })))
364
+ Option.fromNullishOr(resource).pipe(Option.map((_) => ({ ...defaultValues, ...mapReverseId(_) })))
370
365
  )
371
366
  )
372
367
  .pipe(Effect
373
368
  .withSpan("Cosmos.find [effect-app/infra/Store]", {
374
- captureStackTrace: false,
375
369
  attributes: {
376
370
  "repository.container_id": containerId,
377
371
  "repository.model_name": name,
378
372
  partitionValue: config?.partitionValue({ [idKey]: id } as Encoded),
379
373
  id
380
374
  }
381
- })),
375
+ }, { captureStackTrace: false })),
382
376
  set: (e) =>
383
377
  Option
384
378
  .match(
385
379
  Option
386
- .fromNullable(e._etag),
380
+ .fromNullishOr(e._etag),
387
381
  {
388
382
  onNone: () =>
389
383
  Effect.promise(() =>
@@ -410,7 +404,7 @@ function makeCosmosStore({ prefix }: StorageConfig) {
410
404
  Effect
411
405
  .flatMap((x) => {
412
406
  if (x.statusCode === 412 || x.statusCode === 404 || x.statusCode === 409) {
413
- return new OptimisticConcurrencyException({ type: name, id: e[idKey], code: x.statusCode })
407
+ return Effect.fail(new OptimisticConcurrencyException({ type: name, id: e[idKey], code: x.statusCode }))
414
408
  }
415
409
  if (x.statusCode > 299 || x.statusCode < 200) {
416
410
  return Effect.die(
@@ -426,13 +420,12 @@ function makeCosmosStore({ prefix }: StorageConfig) {
426
420
  }),
427
421
  Effect
428
422
  .withSpan("Cosmos.set [effect-app/infra/Store]", {
429
- captureStackTrace: false,
430
423
  attributes: {
431
424
  "repository.container_id": containerId,
432
425
  "repository.model_name": name,
433
426
  id: e[idKey]
434
427
  }
435
- })
428
+ }, { captureStackTrace: false })
436
429
  ),
437
430
  batchSet,
438
431
  bulkSet
@@ -443,7 +436,7 @@ function makeCosmosStore({ prefix }: StorageConfig) {
443
436
  container
444
437
  .item(importedMarkerId, importedMarkerId)
445
438
  .read<{ id: string }>()
446
- .then(({ resource }) => Option.fromNullable(resource))
439
+ .then(({ resource }) => Option.fromNullishOr(resource))
447
440
  )
448
441
 
449
442
  if (!Option.isSome(marker)) {
package/src/Store/Disk.ts CHANGED
@@ -3,7 +3,7 @@ import * as fu from "../fileUtil.js"
3
3
 
4
4
  import fs from "fs"
5
5
 
6
- import { Console, Effect, flow } from "effect-app"
6
+ import { Console, Effect, flow, Semaphore } from "effect-app"
7
7
  import type { FieldValues } from "../Model/filter/types.js"
8
8
  import { makeMemoryStoreInt, storeId } from "./Memory.js"
9
9
  import { type PersistenceModelType, type StorageConfig, type Store, type StoreConfig, StoreMaker } from "./service.js"
@@ -30,26 +30,24 @@ function makeDiskStoreInt<IdKey extends keyof Encoded, Encoded extends FieldValu
30
30
  get: fu
31
31
  .readTextFile(file)
32
32
  .pipe(
33
- Effect.withSpan("Disk.read.readFile [effect-app/infra/Store]", { captureStackTrace: false }),
33
+ Effect.withSpan("Disk.read.readFile [effect-app/infra/Store]", {}, { captureStackTrace: false }),
34
34
  Effect.flatMap((x) =>
35
35
  Effect.sync(() => JSON.parse(x) as PM[]).pipe(
36
- Effect.withSpan("Disk.read.parse [effect-app/infra/Store]", { captureStackTrace: false })
36
+ Effect.withSpan("Disk.read.parse [effect-app/infra/Store]", {}, { captureStackTrace: false })
37
37
  )
38
38
  ),
39
39
  Effect.orDie,
40
40
  Effect.withSpan("Disk.read [effect-app/infra/Store]", {
41
- captureStackTrace: false,
42
41
  attributes: { "disk.file": file }
43
- })
42
+ }, { captureStackTrace: false })
44
43
  ),
45
44
  setRaw: (v: Iterable<PM>) =>
46
45
  Effect
47
46
  .sync(() => JSON.stringify([...v], undefined, 2))
48
47
  .pipe(
49
48
  Effect.withSpan("Disk.stringify [effect-app/infra/Store]", {
50
- captureStackTrace: false,
51
49
  attributes: { "disk.file": file }
52
- }),
50
+ }, { captureStackTrace: false }),
53
51
  Effect
54
52
  .flatMap(
55
53
  (json) =>
@@ -57,15 +55,13 @@ function makeDiskStoreInt<IdKey extends keyof Encoded, Encoded extends FieldValu
57
55
  .writeTextFile(file, json)
58
56
  .pipe(Effect
59
57
  .withSpan("Disk.write.writeFile [effect-app/infra/Store]", {
60
- captureStackTrace: false,
61
58
  attributes: { "disk.file_size": json.length }
62
- }))
59
+ }, { captureStackTrace: false }))
63
60
  ),
64
61
  Effect
65
62
  .withSpan("Disk.write [effect-app/infra/Store]", {
66
- captureStackTrace: false,
67
63
  attributes: { "disk.file": file }
68
- })
64
+ }, { captureStackTrace: false })
69
65
  )
70
66
  }
71
67
 
@@ -95,14 +91,14 @@ function makeDiskStoreInt<IdKey extends keyof Encoded, Encoded extends FieldValu
95
91
  })
96
92
  )
97
93
 
98
- const sem = Effect.unsafeMakeSemaphore(1)
94
+ const sem = Semaphore.makeUnsafe(1)
99
95
  const withPermit = sem.withPermits(1)
100
96
  const flushToDisk = Effect.flatMap(store.all, fsStore.setRaw).pipe(withPermit)
101
97
  const flushToDiskInBackground = flushToDisk
102
98
  .pipe(
103
- Effect.tapErrorCause(Console.error),
99
+ Effect.tapCause(Console.error),
104
100
  Effect.uninterruptible,
105
- Effect.forkDaemon
101
+ Effect.forkDetach
106
102
  )
107
103
 
108
104
  return {
@@ -144,13 +140,13 @@ export function makeDiskStore({ prefix }: StorageConfig, dir: string) {
144
140
  config?: StoreConfig<Encoded>
145
141
  ) =>
146
142
  Effect.gen(function*() {
147
- const storesSem = Effect.unsafeMakeSemaphore(1)
143
+ const storesSem = Semaphore.makeUnsafe(1)
148
144
  const primary = yield* makeDiskStoreInt(prefix, idKey, "primary", dir, name, seed, config?.defaultValues)
149
145
  const stores = new Map<string, Store<IdKey, Encoded>>([["primary", primary]])
150
- const ctx = yield* Effect.context<R>()
146
+ const ctx = yield* Effect.services<R>()
151
147
  const getStore = !config?.allowNamespace
152
148
  ? Effect.succeed(primary)
153
- : storeId.pipe(Effect.flatMap((namespace) => {
149
+ : storeId.asEffect().pipe(Effect.flatMap((namespace) => {
154
150
  const store = stores.get(namespace)
155
151
  if (store) {
156
152
  return Effect.succeed(store)
@@ -1,11 +1,11 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
 
3
- import { Array, Context, Effect, Either, flow, type NonEmptyReadonlyArray, Option, Order, pipe, Ref, Struct } from "effect-app"
3
+ import { Array, Effect, flow, type NonEmptyReadonlyArray, Option, Order, pipe, Ref, Result, Semaphore, ServiceMap, Struct } from "effect-app"
4
4
  import { NonEmptyString255 } from "effect-app/Schema"
5
5
  import { get } from "effect-app/utils"
6
6
  import { InfraLogger } from "../logger.js"
7
7
  import type { FieldValues } from "../Model/filter/types.js"
8
- import { codeFilter } from "./codeFilter.js"
8
+ import { codeFilter, codeFilter3_ } from "./codeFilter.js"
9
9
  import { type FilterArgs, type PersistenceModelType, type Store, type StoreConfig, StoreMaker } from "./service.js"
10
10
  import { makeUpdateETag } from "./utils.js"
11
11
 
@@ -18,20 +18,20 @@ export function memFilter<T extends FieldValues, U extends keyof T = never>(f: F
18
18
  return r.map((i) => {
19
19
  const [keys, subKeys] = pipe(
20
20
  sel,
21
- Array.partitionMap((r) =>
22
- typeof r === "string" ? Either.left(String(r)) : Either.right(r as { key: string; subKeys: string[] })
21
+ Array.partition((r) =>
22
+ typeof r === "string" ? Result.fail(String(r)) : Result.succeed(r as { key: string; subKeys: string[] })
23
23
  )
24
24
  )
25
- const n = Struct.pick(i, ...keys)
25
+ const n = Struct.pick(i, keys)
26
26
  subKeys.forEach((subKey) => {
27
- n[subKey.key] = i[subKey.key]!.map(Struct.pick(...subKey.subKeys))
27
+ n[subKey.key] = i[subKey.key]!.map(Struct.pick(subKey.subKeys))
28
28
  })
29
29
  return n as M
30
30
  }) as any
31
31
  }
32
32
  const skip = f?.skip
33
33
  const limit = f?.limit
34
- const ords = Option.map(Option.fromNullable(f.order), (_) =>
34
+ const ords = Option.map(Option.fromNullishOr(f.order), (_) =>
35
35
  _.map((_) =>
36
36
  Order.make<T>((self, that) => {
37
37
  // TODO: inspect data types for the right comparison?
@@ -59,7 +59,7 @@ export function memFilter<T extends FieldValues, U extends keyof T = never>(f: F
59
59
  )
60
60
  )
61
61
  }
62
- let r = f.filter ? Array.filterMap(c, codeFilter(f.filter)) : c
62
+ let r = f.filter ? Array.filter(c, (x) => codeFilter3_(f.filter!, x)) : c
63
63
  if (skip) {
64
64
  r = Array.drop(r, skip)
65
65
  }
@@ -71,9 +71,9 @@ export function memFilter<T extends FieldValues, U extends keyof T = never>(f: F
71
71
  })
72
72
  }
73
73
 
74
- const defaultNs = NonEmptyString255("primary")
74
+ const defaultNs: NonEmptyString255 = NonEmptyString255("primary")
75
75
  export class storeId
76
- extends Context.Reference<storeId>()("StoreId", { defaultValue: (): NonEmptyString255 => defaultNs })
76
+ extends ServiceMap.Reference("StoreId", { defaultValue: (): NonEmptyString255 => defaultNs })
77
77
  {}
78
78
 
79
79
  function logQuery(f: FilterArgs<any, any>, defaultValues?: any) {
@@ -107,8 +107,8 @@ export function makeMemoryStoreInt<IdKey extends keyof Encoded, Encoded extends
107
107
  const defaultValues = _defaultValues ?? {}
108
108
 
109
109
  const items = new Map([...items_].map((_) => [_[idKey], { _etag: undefined, ...defaultValues, ..._ }] as const))
110
- const store = Ref.unsafeMake<ReadonlyMap<Encoded[IdKey], PM>>(items)
111
- const sem = Effect.unsafeMakeSemaphore(1)
110
+ const store = Ref.makeUnsafe<ReadonlyMap<Encoded[IdKey], PM>>(items)
111
+ const sem = Semaphore.makeUnsafe(1)
112
112
  const withPermit = sem.withPermits(1)
113
113
  const values = Effect.map(Ref.get(store), (s) => s.values())
114
114
 
@@ -159,31 +159,28 @@ export function makeMemoryStoreInt<IdKey extends keyof Encoded, Encoded extends
159
159
  // Effect.tap(() => logQuery(query, defaultValues)),
160
160
  Effect.map(query.memory),
161
161
  Effect.withSpan("Memory.queryRaw [effect-app/infra/Store]", {
162
- captureStackTrace: false,
163
162
  attributes: { "repository.model_name": modelName, "repository.namespace": namespace }
164
- })
163
+ }, { captureStackTrace: false })
165
164
  ),
166
165
 
167
166
  all: all.pipe(Effect.withSpan("Memory.all [effect-app/infra/Store]", {
168
- captureStackTrace: false,
169
167
  attributes: {
170
168
  modelName,
171
169
  namespace
172
170
  }
173
- })),
171
+ }, { captureStackTrace: false })),
174
172
  find: (id) =>
175
173
  Ref
176
174
  .get(store)
177
175
  .pipe(
178
- Effect.map((_) => Option.fromNullable(_.get(id))),
176
+ Effect.map((_) => Option.fromNullishOr(_.get(id))),
179
177
  Effect
180
178
  .withSpan("Memory.find [effect-app/infra/Store]", {
181
- captureStackTrace: false,
182
179
  attributes: {
183
180
  modelName,
184
181
  namespace
185
182
  }
186
- })
183
+ }, { captureStackTrace: false })
187
184
  ),
188
185
  filter: (f) =>
189
186
  all
@@ -191,9 +188,8 @@ export function makeMemoryStoreInt<IdKey extends keyof Encoded, Encoded extends
191
188
  Effect.tap(() => logQuery(f, defaultValues)),
192
189
  Effect.map(memFilter(f)),
193
190
  Effect.withSpan("Memory.filter [effect-app/infra/Store]", {
194
- captureStackTrace: false,
195
191
  attributes: { "repository.model_name": modelName, "repository.namespace": namespace }
196
- })
192
+ }, { captureStackTrace: false })
197
193
  ),
198
194
  set: (e) =>
199
195
  s
@@ -210,9 +206,8 @@ export function makeMemoryStoreInt<IdKey extends keyof Encoded, Encoded extends
210
206
  withPermit,
211
207
  Effect
212
208
  .withSpan("Memory.set [effect-app/infra/Store]", {
213
- captureStackTrace: false,
214
209
  attributes: { "repository.model_name": modelName, "repository.namespace": namespace }
215
- })
210
+ }, { captureStackTrace: false })
216
211
  ),
217
212
  batchRemove: (items: NonEmptyReadonlyArray<Encoded[IdKey]>) =>
218
213
  pipe(
@@ -220,13 +215,13 @@ export function makeMemoryStoreInt<IdKey extends keyof Encoded, Encoded extends
220
215
  .sync(() => items)
221
216
  // align with CosmosDB
222
217
  .pipe(
223
- Effect.filterOrDieMessage((_) => _.length <= 100, "BatchRemove: a batch may not exceed 100 items"),
218
+ Effect.filterOrFail((_) => _.length <= 100, () => "BatchRemove: a batch may not exceed 100 items"),
219
+ Effect.orDie,
224
220
  Effect.andThen(batchRemove),
225
221
  Effect
226
222
  .withSpan("Memory.batchRemove [effect-app/infra/Store]", {
227
- captureStackTrace: false,
228
223
  attributes: { "repository.model_name": modelName, "repository.namespace": namespace }
229
- })
224
+ }, { captureStackTrace: false })
230
225
  )
231
226
  ),
232
227
  batchSet: (items: readonly [PM, ...PM[]]) =>
@@ -235,22 +230,21 @@ export function makeMemoryStoreInt<IdKey extends keyof Encoded, Encoded extends
235
230
  .sync(() => items)
236
231
  // align with CosmosDB
237
232
  .pipe(
238
- Effect.filterOrDieMessage((_) => _.length <= 100, "BatchSet: a batch may not exceed 100 items"),
233
+ Effect.filterOrFail((_) => _.length <= 100, () => "BatchSet: a batch may not exceed 100 items"),
234
+ Effect.orDie,
239
235
  Effect.andThen(batchSet),
240
236
  Effect
241
237
  .withSpan("Memory.batchSet [effect-app/infra/Store]", {
242
- captureStackTrace: false,
243
238
  attributes: { "repository.model_name": modelName, "repository.namespace": namespace }
244
- })
239
+ }, { captureStackTrace: false })
245
240
  )
246
241
  ),
247
242
  bulkSet: flow(
248
243
  batchSet,
249
244
  (_) =>
250
245
  _.pipe(Effect.withSpan("Memory.bulkSet [effect-app/infra/Store]", {
251
- captureStackTrace: false,
252
246
  attributes: { "repository.model_name": modelName, "repository.namespace": namespace }
253
- }))
247
+ }, { captureStackTrace: false }))
254
248
  )
255
249
  }
256
250
  return s
@@ -265,7 +259,7 @@ export const makeMemoryStore = () => ({
265
259
  config?: StoreConfig<Encoded>
266
260
  ) =>
267
261
  Effect.gen(function*() {
268
- const storesSem = Effect.unsafeMakeSemaphore(1)
262
+ const storesSem = Semaphore.makeUnsafe(1)
269
263
  const primary = yield* makeMemoryStoreInt<IdKey, Encoded, R, E>(
270
264
  modelName,
271
265
  idKey,
@@ -273,11 +267,11 @@ export const makeMemoryStore = () => ({
273
267
  seed,
274
268
  config?.defaultValues
275
269
  )
276
- const ctx = yield* Effect.context<R>()
270
+ const ctx = yield* Effect.services<R>()
277
271
  const stores = new Map([["primary", primary]])
278
272
  const getStore = !config?.allowNamespace
279
273
  ? Effect.succeed(primary)
280
- : storeId.pipe(Effect.flatMap((namespace) => {
274
+ : storeId.asEffect().pipe(Effect.flatMap((namespace) => {
281
275
  const store = stores.get(namespace)
282
276
  if (store) {
283
277
  return Effect.succeed(store)
@@ -27,7 +27,7 @@ export function StoreMakerLayer(cfg: StorageConfig) {
27
27
  console.log("Using Cosmos DB store")
28
28
  return CosmosStoreLayer(cfg)
29
29
  })
30
- .pipe(Layer.unwrapEffect)
30
+ .pipe(Layer.unwrap)
31
31
  }
32
32
 
33
33
  export * from "./service.js"
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import type { UniqueKey } from "@azure/cosmos"
3
- import { Context, Effect, type NonEmptyReadonlyArray, type Option, type Redacted } from "effect-app"
3
+ import { Effect, type NonEmptyReadonlyArray, type Option, type Redacted, ServiceMap } from "effect-app"
4
4
  import type { OptimisticConcurrencyException } from "../errors.js"
5
5
  import type { FilterResult } from "../Model/filter/filterApi.js"
6
6
  import type { FieldValues } from "../Model/filter/types.js"
@@ -89,14 +89,14 @@ export interface Store<
89
89
  queryRaw: <Out>(query: RawQuery<Encoded, Out>) => Effect.Effect<readonly Out[]>
90
90
  }
91
91
 
92
- export class StoreMaker extends Context.TagId("effect-app/StoreMaker")<StoreMaker, {
92
+ export class StoreMaker extends ServiceMap.Opaque<StoreMaker, {
93
93
  make: <IdKey extends keyof Encoded, Encoded extends FieldValues, R = never, E = never>(
94
94
  name: string,
95
95
  idKey: IdKey,
96
96
  seed?: Effect.Effect<Iterable<Encoded>, E, R>,
97
97
  config?: StoreConfig<Encoded>
98
98
  ) => Effect.Effect<Store<IdKey, Encoded>, E, R>
99
- }>() {
99
+ }>()("effect-app/StoreMaker") {
100
100
  }
101
101
 
102
102
  export const makeContextMap = () => {
@@ -170,7 +170,7 @@ export const makeContextMap = () => {
170
170
 
171
171
  const makeMap = Effect.sync(() => makeContextMap())
172
172
 
173
- export class ContextMap extends Context.TagMakeId("effect-app/ContextMap", makeMap)<ContextMap>() {
173
+ export class ContextMap extends ServiceMap.Opaque<ContextMap>()("effect-app/ContextMap", { make: makeMap }) {
174
174
  }
175
175
 
176
176
  export type PersistenceModelType<Encoded extends object> = Encoded & {
@@ -17,11 +17,15 @@ export const makeUpdateETag =
17
17
  <IdKey extends keyof E, E extends PersistenceModelType<{}>>(e: E, idKey: IdKey, current: Option.Option<E>) =>
18
18
  Effect.gen(function*() {
19
19
  if (e._etag) {
20
- yield* Effect.mapError(
21
- current,
22
- () =>
23
- new OptimisticConcurrencyException({ type, id: e[idKey] as string, current: "", found: e._etag, code: 409 })
24
- )
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
+ }
25
29
  }
26
30
  if (Option.isSome(current) && current.value._etag !== e._etag) {
27
31
  return yield* new OptimisticConcurrencyException({