@effect-app/infra 0.48.0 → 0.49.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 (163) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/_cjs/_ext/Array.cjs.map +1 -1
  3. package/_cjs/api/defaultErrorHandler.cjs.map +1 -1
  4. package/_cjs/api/express/makeJsonSchema.cjs +2 -2
  5. package/_cjs/api/express/makeJsonSchema.cjs.map +1 -1
  6. package/_cjs/api/express/schema/jwt.cjs.map +1 -1
  7. package/_cjs/api/express/schema/requestHandler.cjs.map +1 -1
  8. package/_cjs/api/express/schema/routing.cjs.map +1 -1
  9. package/_cjs/api/reportError.cjs.map +1 -1
  10. package/_cjs/api/routing.cjs.map +1 -1
  11. package/_cjs/api/setupRequest.cjs.map +1 -1
  12. package/_cjs/api/writeDocs.cjs.map +1 -1
  13. package/_cjs/rateLimit.cjs.map +1 -1
  14. package/_cjs/services/Emailer/Sendgrid.cjs.map +1 -1
  15. package/_cjs/services/Emailer/fake.cjs.map +1 -1
  16. package/_cjs/services/Operations/live.cjs.map +1 -1
  17. package/_cjs/services/Operations/service.cjs.map +1 -1
  18. package/_cjs/services/QueueMaker/errors.cjs.map +1 -1
  19. package/_cjs/services/QueueMaker/memQueue.cjs.map +1 -1
  20. package/_cjs/services/QueueMaker/sbqueue.cjs.map +1 -1
  21. package/_cjs/services/Repository.cjs +8 -8
  22. package/_cjs/services/Repository.cjs.map +1 -1
  23. package/_cjs/services/RepositoryBase.cjs +13 -13
  24. package/_cjs/services/RepositoryBase.cjs.map +1 -1
  25. package/_cjs/services/RequestContextContainer.cjs.map +1 -1
  26. package/_cjs/services/Store/Cosmos.cjs +9 -9
  27. package/_cjs/services/Store/Cosmos.cjs.map +1 -1
  28. package/_cjs/services/Store/Cosmos.test.cjs.map +1 -1
  29. package/_cjs/services/Store/Disk.cjs.map +1 -1
  30. package/_cjs/services/Store/Memory.cjs +42 -42
  31. package/_cjs/services/Store/Memory.cjs.map +1 -1
  32. package/_cjs/services/Store/Redis.cjs +13 -13
  33. package/_cjs/services/Store/Redis.cjs.map +1 -1
  34. package/_cjs/services/Store/codeFilter.test.cjs.map +1 -1
  35. package/_cjs/services/Store/index.cjs.map +1 -1
  36. package/_cjs/services/Store/service.cjs.map +1 -1
  37. package/_cjs/services/Store/utils.cjs +2 -3
  38. package/_cjs/services/Store/utils.cjs.map +1 -1
  39. package/_cjs/services/simpledb/cosmosdb.cjs +12 -4
  40. package/_cjs/services/simpledb/cosmosdb.cjs.map +1 -1
  41. package/_cjs/services/simpledb/diskdb.cjs.map +1 -1
  42. package/_cjs/services/simpledb/memdb.cjs.map +1 -1
  43. package/_cjs/services/simpledb/mongodb.cjs +15 -5
  44. package/_cjs/services/simpledb/mongodb.cjs.map +1 -1
  45. package/_cjs/services/simpledb/redisdb.cjs +13 -7
  46. package/_cjs/services/simpledb/redisdb.cjs.map +1 -1
  47. package/_cjs/services/simpledb/simpledb.cjs.map +1 -1
  48. package/_src/_ext/Array.ts +3 -2
  49. package/_src/api/defaultErrorHandler.ts +14 -12
  50. package/_src/api/express/makeJsonSchema.ts +6 -5
  51. package/_src/api/express/schema/jwt.ts +1 -1
  52. package/_src/api/express/schema/requestHandler.ts +112 -100
  53. package/_src/api/express/schema/routing.ts +61 -55
  54. package/_src/api/reportError.ts +16 -12
  55. package/_src/api/routing.ts +157 -135
  56. package/_src/api/setupRequest.ts +3 -1
  57. package/_src/api/writeDocs.ts +4 -3
  58. package/_src/rateLimit.ts +21 -14
  59. package/_src/services/Emailer/Sendgrid.ts +11 -10
  60. package/_src/services/Emailer/fake.ts +2 -1
  61. package/_src/services/Operations/live.ts +18 -12
  62. package/_src/services/Operations/service.ts +26 -17
  63. package/_src/services/QueueMaker/errors.ts +7 -6
  64. package/_src/services/QueueMaker/memQueue.ts +13 -11
  65. package/_src/services/QueueMaker/sbqueue.ts +16 -14
  66. package/_src/services/Repository.ts +53 -51
  67. package/_src/services/RepositoryBase.ts +33 -28
  68. package/_src/services/RequestContextContainer.ts +4 -3
  69. package/_src/services/Store/Cosmos.test.ts +31 -29
  70. package/_src/services/Store/Cosmos.ts +203 -180
  71. package/_src/services/Store/Disk.ts +19 -18
  72. package/_src/services/Store/Memory.ts +37 -32
  73. package/_src/services/Store/Redis.ts +31 -27
  74. package/_src/services/Store/codeFilter.test.ts +26 -16
  75. package/_src/services/Store/index.ts +26 -24
  76. package/_src/services/Store/service.ts +5 -5
  77. package/_src/services/Store/utils.ts +27 -24
  78. package/_src/services/simpledb/cosmosdb.ts +61 -51
  79. package/_src/services/simpledb/diskdb.ts +38 -31
  80. package/_src/services/simpledb/memdb.ts +25 -21
  81. package/_src/services/simpledb/mongodb.ts +40 -35
  82. package/_src/services/simpledb/redisdb.ts +66 -55
  83. package/_src/services/simpledb/simpledb.ts +32 -30
  84. package/dist/_ext/Array.d.ts.map +1 -1
  85. package/dist/_ext/Array.js +2 -2
  86. package/dist/api/defaultErrorHandler.d.ts.map +1 -1
  87. package/dist/api/defaultErrorHandler.js +5 -5
  88. package/dist/api/express/makeJsonSchema.d.ts +0 -1
  89. package/dist/api/express/makeJsonSchema.d.ts.map +1 -1
  90. package/dist/api/express/makeJsonSchema.js +4 -4
  91. package/dist/api/express/schema/jwt.js +2 -2
  92. package/dist/api/express/schema/requestHandler.d.ts.map +1 -1
  93. package/dist/api/express/schema/requestHandler.js +17 -17
  94. package/dist/api/express/schema/routing.d.ts.map +1 -1
  95. package/dist/api/express/schema/routing.js +13 -11
  96. package/dist/api/reportError.d.ts.map +1 -1
  97. package/dist/api/reportError.js +6 -6
  98. package/dist/api/routing.d.ts.map +1 -1
  99. package/dist/api/routing.js +29 -25
  100. package/dist/api/setupRequest.d.ts.map +1 -1
  101. package/dist/api/setupRequest.js +2 -2
  102. package/dist/api/writeDocs.d.ts.map +1 -1
  103. package/dist/api/writeDocs.js +5 -4
  104. package/dist/rateLimit.d.ts +4 -4
  105. package/dist/rateLimit.d.ts.map +1 -1
  106. package/dist/rateLimit.js +5 -4
  107. package/dist/services/Emailer/Sendgrid.d.ts.map +1 -1
  108. package/dist/services/Emailer/Sendgrid.js +9 -9
  109. package/dist/services/Emailer/fake.d.ts.map +1 -1
  110. package/dist/services/Emailer/fake.js +1 -1
  111. package/dist/services/Operations/live.d.ts.map +1 -1
  112. package/dist/services/Operations/live.js +11 -8
  113. package/dist/services/Operations/service.d.ts.map +1 -1
  114. package/dist/services/Operations/service.js +10 -4
  115. package/dist/services/QueueMaker/errors.d.ts.map +1 -1
  116. package/dist/services/QueueMaker/errors.js +5 -5
  117. package/dist/services/QueueMaker/memQueue.d.ts +1 -1
  118. package/dist/services/QueueMaker/memQueue.d.ts.map +1 -1
  119. package/dist/services/QueueMaker/memQueue.js +5 -4
  120. package/dist/services/QueueMaker/sbqueue.d.ts.map +1 -1
  121. package/dist/services/QueueMaker/sbqueue.js +5 -5
  122. package/dist/services/Repository.d.ts +34 -35
  123. package/dist/services/Repository.d.ts.map +1 -1
  124. package/dist/services/Repository.js +16 -16
  125. package/dist/services/RepositoryBase.d.ts +4 -4
  126. package/dist/services/RepositoryBase.d.ts.map +1 -1
  127. package/dist/services/RepositoryBase.js +25 -22
  128. package/dist/services/RequestContextContainer.d.ts.map +1 -1
  129. package/dist/services/RequestContextContainer.js +3 -3
  130. package/dist/services/Store/Cosmos.d.ts +3 -3
  131. package/dist/services/Store/Cosmos.d.ts.map +1 -1
  132. package/dist/services/Store/Cosmos.js +53 -39
  133. package/dist/services/Store/Disk.d.ts.map +1 -1
  134. package/dist/services/Store/Disk.js +18 -18
  135. package/dist/services/Store/Memory.d.ts +2 -3
  136. package/dist/services/Store/Memory.d.ts.map +1 -1
  137. package/dist/services/Store/Memory.js +44 -44
  138. package/dist/services/Store/Redis.d.ts +4 -4
  139. package/dist/services/Store/Redis.d.ts.map +1 -1
  140. package/dist/services/Store/Redis.js +19 -17
  141. package/dist/services/Store/index.d.ts.map +1 -1
  142. package/dist/services/Store/index.js +4 -4
  143. package/dist/services/Store/service.d.ts +4 -5
  144. package/dist/services/Store/service.d.ts.map +1 -1
  145. package/dist/services/Store/service.js +3 -3
  146. package/dist/services/Store/utils.d.ts +2 -2
  147. package/dist/services/Store/utils.d.ts.map +1 -1
  148. package/dist/services/Store/utils.js +16 -14
  149. package/dist/services/simpledb/cosmosdb.d.ts.map +1 -1
  150. package/dist/services/simpledb/cosmosdb.js +16 -12
  151. package/dist/services/simpledb/diskdb.d.ts.map +1 -1
  152. package/dist/services/simpledb/diskdb.js +15 -15
  153. package/dist/services/simpledb/memdb.d.ts.map +1 -1
  154. package/dist/services/simpledb/memdb.js +6 -6
  155. package/dist/services/simpledb/mongodb.d.ts +5 -5
  156. package/dist/services/simpledb/mongodb.d.ts.map +1 -1
  157. package/dist/services/simpledb/mongodb.js +9 -9
  158. package/dist/services/simpledb/redisdb.d.ts +4 -4
  159. package/dist/services/simpledb/redisdb.d.ts.map +1 -1
  160. package/dist/services/simpledb/redisdb.js +18 -18
  161. package/dist/services/simpledb/simpledb.d.ts.map +1 -1
  162. package/dist/services/simpledb/simpledb.js +9 -9
  163. package/package.json +7 -7
@@ -19,9 +19,9 @@ function makeDiskStoreInt<Id extends string, PM extends PersistenceModelType<Id>
19
19
  const fsStore = {
20
20
  get: fu
21
21
  .readTextFile(file)
22
- .map(x => JSON.parse(x) as PM[])
22
+ .map((x) => JSON.parse(x) as PM[])
23
23
  .orDie,
24
- setRaw: (v: Iterable<PM>) => JSON.stringify([...v], undefined, 2)["|>"](json => fu.writeTextFile(file, json))
24
+ setRaw: (v: Iterable<PM>) => JSON.stringify([...v], undefined, 2)["|>"]((json) => fu.writeTextFile(file, json))
25
25
  }
26
26
 
27
27
  const store = yield* $(
@@ -42,19 +42,19 @@ function makeDiskStoreInt<Id extends string, PM extends PersistenceModelType<Id>
42
42
  ...store,
43
43
  batchSet: flow(
44
44
  store.batchSet,
45
- t => t.tap(() => flushToDisk.tapErrorCause(err => Effect(console.error(err))).forkDaemon)
45
+ (t) => t.tap(() => flushToDisk.tapErrorCause((err) => Effect(console.error(err))).forkDaemon)
46
46
  ),
47
47
  bulkSet: flow(
48
48
  store.bulkSet,
49
- t => t.tap(() => flushToDisk.tapErrorCause(err => Effect(console.error(err))).forkDaemon)
49
+ (t) => t.tap(() => flushToDisk.tapErrorCause((err) => Effect(console.error(err))).forkDaemon)
50
50
  ),
51
51
  set: flow(
52
52
  store.set,
53
- t => t.tap(() => flushToDisk.tapErrorCause(err => Effect(console.error(err))).forkDaemon)
53
+ (t) => t.tap(() => flushToDisk.tapErrorCause((err) => Effect(console.error(err))).forkDaemon)
54
54
  ),
55
55
  remove: flow(
56
56
  store.remove,
57
- t => t.tap(() => flushToDisk.tapErrorCause(err => Effect(console.error(err))).forkDaemon)
57
+ (t) => t.tap(() => flushToDisk.tapErrorCause((err) => Effect(console.error(err))).forkDaemon)
58
58
  )
59
59
  } satisfies Store<PM, Id>
60
60
  })
@@ -79,7 +79,7 @@ export function makeDiskStore({ prefix }: StorageConfig, dir: string) {
79
79
  const storesSem = Semaphore.unsafeMake(1)
80
80
  const primary = yield* $(makeDiskStoreInt(prefix, "primary", dir, name, seed))
81
81
  const stores = new Map<string, Store<PM, Id>>([["primary", primary]])
82
- const getStore = !config?.allowNamespace ? Effect.succeed(primary) : storeId.get.flatMap(namespace => {
82
+ const getStore = !config?.allowNamespace ? Effect.succeed(primary) : storeId.get.flatMap((namespace) => {
83
83
  const store = stores.get(namespace)
84
84
  if (store) {
85
85
  return Effect.succeed(store)
@@ -91,7 +91,7 @@ export function makeDiskStore({ prefix }: StorageConfig, dir: string) {
91
91
  Effect.suspend(() => {
92
92
  const existing = stores.get(namespace)
93
93
  if (existing) return Effect(existing)
94
- return makeDiskStoreInt<Id, PM>(prefix, namespace, dir, name, seed).tap(store =>
94
+ return makeDiskStoreInt<Id, PM>(prefix, namespace, dir, name, seed).tap((store) =>
95
95
  Effect.sync(() => stores.set(namespace, store))
96
96
  )
97
97
  })
@@ -99,14 +99,14 @@ export function makeDiskStore({ prefix }: StorageConfig, dir: string) {
99
99
  })
100
100
 
101
101
  const s: Store<PM, Id> = {
102
- all: getStore.flatMap(_ => _.all),
103
- find: (...args) => getStore.flatMap(_ => _.find(...args)),
104
- filter: (...args) => getStore.flatMap(_ => _.filter(...args)),
105
- filterJoinSelect: (...args) => getStore.flatMap(_ => _.filterJoinSelect(...args)),
106
- set: (...args) => getStore.flatMap(_ => _.set(...args)),
107
- batchSet: (...args) => getStore.flatMap(_ => _.batchSet(...args)),
108
- bulkSet: (...args) => getStore.flatMap(_ => _.bulkSet(...args)),
109
- remove: (...args) => getStore.flatMap(_ => _.remove(...args))
102
+ all: getStore.flatMap((_) => _.all),
103
+ find: (...args) => getStore.flatMap((_) => _.find(...args)),
104
+ filter: (...args) => getStore.flatMap((_) => _.filter(...args)),
105
+ filterJoinSelect: (...args) => getStore.flatMap((_) => _.filterJoinSelect(...args)),
106
+ set: (...args) => getStore.flatMap((_) => _.set(...args)),
107
+ batchSet: (...args) => getStore.flatMap((_) => _.batchSet(...args)),
108
+ bulkSet: (...args) => getStore.flatMap((_) => _.bulkSet(...args)),
109
+ remove: (...args) => getStore.flatMap((_) => _.remove(...args))
110
110
  }
111
111
  return s
112
112
  })
@@ -115,7 +115,8 @@ export function makeDiskStore({ prefix }: StorageConfig, dir: string) {
115
115
  }
116
116
 
117
117
  export function DiskStoreLive(config: Config<StorageConfig>, dir: string) {
118
- return config.config
119
- .flatMap(_ => makeDiskStore(_, dir))
118
+ return config
119
+ .config
120
+ .flatMap((_) => makeDiskStore(_, dir))
120
121
  .toLayer(StoreMaker)
121
122
  }
@@ -6,11 +6,11 @@ import { StoreMaker } from "./service.js"
6
6
  import { codeFilter, codeFilterJoinSelect, makeETag, makeUpdateETag } from "./utils.js"
7
7
 
8
8
  export function memFilter<T extends { id: string }>(filter: Filter<T>, cursor?: { skip?: number; limit?: number }) {
9
- return ((c: Chunk<T>): Chunk<T> => {
9
+ return ((c: T[]): T[] => {
10
10
  const skip = cursor?.skip
11
11
  const limit = cursor?.limit
12
12
  if (!skip && limit === 1) {
13
- return c.findFirstMap(codeFilter(filter)).map(Chunk.make).getOrElse(() => Chunk.empty())
13
+ return c.findFirstMap(codeFilter(filter)).map(ReadonlyArray.make).getOrElse(() => [])
14
14
  }
15
15
  let r = c.filterMap(codeFilter(filter))
16
16
  if (skip) {
@@ -19,17 +19,18 @@ export function memFilter<T extends { id: string }>(filter: Filter<T>, cursor?:
19
19
  if (limit !== undefined) {
20
20
  r = r.take(limit)
21
21
  }
22
- return r.toChunk
22
+ return r
23
23
  })
24
24
  }
25
25
 
26
26
  export const storeId = FiberRef.unsafeMake("primary")
27
- export const restoreFromRequestContext = RequestContextContainer.get.flatMap(ctx =>
27
+ export const restoreFromRequestContext = RequestContextContainer.get.flatMap((ctx) =>
28
28
  storeId.set(ctx.namespace ?? "primary")
29
29
  )
30
30
 
31
31
  function logQuery(filter: any, cursor: any) {
32
- return Effect.logDebug("mem query")
32
+ return Effect
33
+ .logDebug("mem query")
33
34
  .apply(Effect.logAnnotates({
34
35
  query: JSON.stringify(filter, undefined, 2),
35
36
  cursor: JSON.stringify(
@@ -47,47 +48,51 @@ export function makeMemoryStoreInt<Id extends string, PM extends PersistenceMode
47
48
  return Effect.gen(function*($) {
48
49
  const updateETag = makeUpdateETag(name)
49
50
  const items_ = yield* $(seed ?? Effect([]))
50
- const items = new Map(items_.toChunk.map(_ => [_.id, _] as const))
51
+ const items = new Map(items_.toChunk.map((_) => [_.id, _] as const))
51
52
  const makeStore = (): ReadonlyMap<Id, PM> => new Map([...items.entries()].map(([id, e]) => [id, makeETag(e)]))
52
53
  const store = Ref.unsafeMake(makeStore())
53
54
  const sem = Semaphore.unsafeMake(1)
54
55
  const withPermit = sem.withPermits(1)
55
- const values = store.get.map(s => s.values())
56
- const all = values.map(Chunk.fromIterable)
56
+ const values = store.get.map((s) => s.values())
57
+ const all = values.map(ReadonlyArray.fromIterable)
57
58
  const batchSet = (items: NonEmptyReadonlyArray<PM>) =>
58
59
  items
59
- .forEachEffect(i => s.find(i.id).flatMap(current => updateETag(i, current)))
60
- .tap(items =>
61
- store.get
62
- .map(m => {
60
+ .forEachEffect((i) => s.find(i.id).flatMap((current) => updateETag(i, current)))
61
+ .tap((items) =>
62
+ store
63
+ .get
64
+ .map((m) => {
63
65
  const mut = m as Map<Id, PM>
64
- items.forEach(e => mut.set(e.id, e))
66
+ items.forEach((e) => mut.set(e.id, e))
65
67
  return mut
66
68
  })
67
- .flatMap(_ => store.set(_))
69
+ .flatMap((_) => store.set(_))
68
70
  )
69
- .map(_ => _.toReadonlyArray as NonEmptyReadonlyArray<PM>)
71
+ .map((_) => _ as NonEmptyArray<PM>)
70
72
  .apply(withPermit)
71
73
  const s: Store<PM, Id> = {
72
74
  all,
73
- find: id => store.get.map(_ => Option.fromNullable(_.get(id))),
75
+ find: (id) => store.get.map((_) => Option.fromNullable(_.get(id))),
74
76
  filter: (filter: Filter<PM>, cursor?: { skip?: number; limit?: number }) =>
75
77
  all
76
78
  .tap(() => logQuery(filter, cursor))
77
79
  .map(memFilter(filter, cursor)),
78
80
  filterJoinSelect: <T extends object>(filter: FilterJoinSelect) =>
79
- all.map(c => c.flatMap(codeFilterJoinSelect<PM, T>(filter))),
80
- set: e =>
81
+ all.map((c) => c.flatMap(codeFilterJoinSelect<PM, T>(filter))),
82
+ set: (e) =>
81
83
  s
82
84
  .find(e.id)
83
- .flatMap(current => updateETag(e, current))
84
- .tap(e => store.get.map(_ => new Map([..._, [e.id, e]])).flatMap(_ => store.set(_)))
85
+ .flatMap((current) => updateETag(e, current))
86
+ .tap((e) => store.get.map((_) => new Map([..._, [e.id, e]])).flatMap((_) => store.set(_)))
85
87
  .apply(withPermit),
86
88
  batchSet,
87
89
  bulkSet: batchSet,
88
90
  remove: (e: PM) =>
89
- store.get.map(_ => new Map([..._].filter(([_]) => _ !== e.id)))
90
- .flatMap(_ => store.set(_)).apply(withPermit)
91
+ store
92
+ .get
93
+ .map((_) => new Map([..._].filter(([_]) => _ !== e.id)))
94
+ .flatMap((_) => store.set(_))
95
+ .apply(withPermit)
91
96
  }
92
97
  return s
93
98
  })
@@ -103,7 +108,7 @@ export const makeMemoryStore = () => ({
103
108
  const storesSem = Semaphore.unsafeMake(1)
104
109
  const primary = yield* $(makeMemoryStoreInt<Id, PM>(name, seed))
105
110
  const stores = new Map([["primary", primary]])
106
- const getStore = !config?.allowNamespace ? Effect.succeed(primary) : storeId.get.flatMap(namespace => {
111
+ const getStore = !config?.allowNamespace ? Effect.succeed(primary) : storeId.get.flatMap((namespace) => {
107
112
  const store = stores.get(namespace)
108
113
  if (store) {
109
114
  return Effect.succeed(store)
@@ -114,18 +119,18 @@ export const makeMemoryStore = () => ({
114
119
  return storesSem.withPermits(1)(Effect.suspend(() => {
115
120
  const store = stores.get(namespace)
116
121
  if (store) return Effect(store)
117
- return makeMemoryStoreInt(name, seed).tap(store => Effect.sync(() => stores.set(namespace, store)))
122
+ return makeMemoryStoreInt(name, seed).tap((store) => Effect.sync(() => stores.set(namespace, store)))
118
123
  }))
119
124
  })
120
125
  const s: Store<PM, Id> = {
121
- all: getStore.flatMap(_ => _.all),
122
- find: (...args) => getStore.flatMap(_ => _.find(...args)),
123
- filter: (...args) => getStore.flatMap(_ => _.filter(...args)),
124
- filterJoinSelect: (...args) => getStore.flatMap(_ => _.filterJoinSelect(...args)),
125
- set: (...args) => getStore.flatMap(_ => _.set(...args)),
126
- batchSet: (...args) => getStore.flatMap(_ => _.batchSet(...args)),
127
- bulkSet: (...args) => getStore.flatMap(_ => _.bulkSet(...args)),
128
- remove: (...args) => getStore.flatMap(_ => _.remove(...args))
126
+ all: getStore.flatMap((_) => _.all),
127
+ find: (...args) => getStore.flatMap((_) => _.find(...args)),
128
+ filter: (...args) => getStore.flatMap((_) => _.filter(...args)),
129
+ filterJoinSelect: (...args) => getStore.flatMap((_) => _.filterJoinSelect(...args)),
130
+ set: (...args) => getStore.flatMap((_) => _.set(...args)),
131
+ batchSet: (...args) => getStore.flatMap((_) => _.batchSet(...args)),
132
+ bulkSet: (...args) => getStore.flatMap((_) => _.bulkSet(...args)),
133
+ remove: (...args) => getStore.flatMap((_) => _.remove(...args))
129
134
  }
130
135
  return s
131
136
  })
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import * as RedisClient from "@effect-app/infra-adapters/redis-client"
2
+ import { RedisClient } from "@effect-app/infra-adapters/redis-client"
3
3
  import { NotFoundError } from "../../errors.js"
4
4
  import { memFilter } from "./Memory.js"
5
5
 
@@ -9,7 +9,7 @@ import { codeFilterJoinSelect, makeETag, makeUpdateETag } from "./utils.js"
9
9
 
10
10
  export function makeRedisStore({ prefix }: StorageConfig) {
11
11
  return Effect.gen(function*($) {
12
- const redis = yield* $(RedisClient.RedisClient)
12
+ const redis = yield* $(RedisClient)
13
13
  return {
14
14
  make: <Id extends string, PM extends PersistenceModelType<Id>>(
15
15
  name: string,
@@ -20,65 +20,69 @@ export function makeRedisStore({ prefix }: StorageConfig) {
20
20
  const updateETag = makeUpdateETag(name)
21
21
  // Very naive implementation of course.
22
22
  const key = `${prefix}${name}`
23
- const current = yield* $(RedisClient.get(key).orDie.provideService(RedisClient.RedisClient, redis))
23
+ const current = yield* $(redis.get(key).orDie.provideService(RedisClient, redis))
24
24
  if (!current.isSome()) {
25
25
  const m = yield* $(seed ?? Effect([]))
26
26
  yield* $(
27
- RedisClient.set(key, JSON.stringify({ data: [...m].map(e => makeETag(e)) }))
27
+ redis
28
+ .set(key, JSON.stringify({ data: [...m].map((e) => makeETag(e)) }))
28
29
  .orDie
29
- .provideService(RedisClient.RedisClient, redis)
30
+ .provideService(RedisClient, redis)
30
31
  )
31
32
  }
32
- const get = RedisClient.get(key)
33
- .flatMap(x => x.encaseInEffect(() => new NotFoundError("data", "")))
33
+ const get = redis
34
+ .get(key)
35
+ .flatMap((x) => x.encaseInEffect(() => new NotFoundError("data", "")))
34
36
  .orDie
35
- .map(x => JSON.parse(x) as { data: readonly PM[] })
36
- .map(_ => _.data)
37
- .provideService(RedisClient.RedisClient, redis)
37
+ .map((x) => JSON.parse(x) as { data: readonly PM[] })
38
+ .map((_) => _.data)
39
+ .provideService(RedisClient, redis)
38
40
 
39
- const set = (i: ReadonlyMap<Id, PM>) => RedisClient.set(key, JSON.stringify({ data: [...i.values()] })).orDie
41
+ const set = (i: ReadonlyMap<Id, PM>) => redis.set(key, JSON.stringify({ data: [...i.values()] })).orDie
40
42
 
41
43
  const sem = Semaphore.unsafeMake(1)
42
44
  const withPermit = sem.withPermits(1)
43
45
 
44
- const asMap = get.map(x => new Map(x.map(x => [x.id, x] as const)))
45
- const all = get.map(Chunk.fromIterable)
46
+ const asMap = get.map((x) => new Map(x.map((x) => [x.id, x] as const)))
47
+ const all = get.map(ReadonlyArray.fromIterable)
46
48
  const batchSet = (items: NonEmptyReadonlyArray<PM>) =>
47
49
  items
48
- .forEachEffect(e => s.find(e.id).flatMap(current => updateETag(e, current)))
49
- .tap(items =>
50
+ .forEachEffect((e) => s.find(e.id).flatMap((current) => updateETag(e, current)))
51
+ .tap((items) =>
50
52
  asMap
51
- .map(m => {
53
+ .map((m) => {
52
54
  const mut = m
53
- items.forEach(e => mut.set(e.id, e))
55
+ items.forEach((e) => mut.set(e.id, e))
54
56
  return mut
55
57
  })
56
58
  .flatMap(set)
57
59
  )
58
- .map(_ => _.toReadonlyArray as NonEmptyReadonlyArray<PM>)
60
+ .map((_) => _ as NonEmptyArray<PM>)
59
61
  .apply(withPermit)
60
- .provideService(RedisClient.RedisClient, redis)
62
+ .provideService(RedisClient, redis)
61
63
  const s: Store<PM, Id> = {
62
64
  all,
63
65
  filter: (filter: Filter<PM>, cursor?: { skip?: number; limit?: number }) =>
64
66
  all.map(memFilter(filter, cursor)),
65
67
  filterJoinSelect: <T extends object>(filter: FilterJoinSelect) =>
66
- all.map(c => c.flatMap(codeFilterJoinSelect<PM, T>(filter))),
67
- find: id => asMap.map(_ => Option.fromNullable(_.get(id))),
68
- set: e =>
68
+ all.map((c) => c.flatMap(codeFilterJoinSelect<PM, T>(filter))),
69
+ find: (id) => asMap.map((_) => Option.fromNullable(_.get(id))),
70
+ set: (e) =>
69
71
  s
70
72
  .find(e.id)
71
- .flatMap(current => updateETag(e, current))
72
- .tap(e => asMap.map(_ => new Map([..._, [e.id, e]])).flatMap(set))
73
+ .flatMap((current) => updateETag(e, current))
74
+ .tap((e) => asMap.map((_) => new Map([..._, [e.id, e]])).flatMap(set))
73
75
  .apply(withPermit)
74
- .provideService(RedisClient.RedisClient, redis),
76
+ .provideService(RedisClient, redis),
75
77
  batchSet,
76
78
  bulkSet: batchSet,
77
79
  remove: (e: PM) =>
78
- asMap.map(_ => new Map([..._].filter(([_]) => _ !== e.id))).flatMap(set)
80
+ asMap
81
+ .map((_) => new Map([..._].filter(([_]) => _ !== e.id)))
82
+ .flatMap(set)
79
83
  .apply(withPermit)
80
84
  .provideService(
81
- RedisClient.RedisClient,
85
+ RedisClient,
82
86
  redis
83
87
  )
84
88
  }
@@ -20,7 +20,7 @@ export function somethingsWhere(
20
20
  ) => Where | [Where, ...Where[]],
21
21
  mode?: "or" | "and"
22
22
  ) {
23
- return makeSomethingFilter_(f => {
23
+ return makeSomethingFilter_((f) => {
24
24
  const m = makeWhere ? makeWhere(f) : []
25
25
  return ({
26
26
  mode,
@@ -44,37 +44,47 @@ type Something = {
44
44
 
45
45
  test("works", () => {
46
46
  expect(
47
- somethings.filterMap(codeFilter(
48
- somethingsWhere(_ => _("b", _ => "b2"))
49
- )).toArray
47
+ somethings
48
+ .filterMap(codeFilter(
49
+ somethingsWhere((_) => _("b", (_) => "b2"))
50
+ ))
51
+ .toArray
50
52
  )
51
53
  .toEqual([somethings[1]])
52
54
 
53
55
  expect(
54
- somethings.filterMap(codeFilter(
55
- somethingsWhere(_ => _("b", _ => "b"))
56
- )).toArray
56
+ somethings
57
+ .filterMap(codeFilter(
58
+ somethingsWhere((_) => _("b", (_) => "b"))
59
+ ))
60
+ .toArray
57
61
  )
58
62
  .toEqual([somethings[0]])
59
63
 
60
64
  expect(
61
- somethings.filterMap(codeFilter(
62
- somethingsWhere(_ => _("d.-1.a", _ => "a5"))
63
- )).toArray
65
+ somethings
66
+ .filterMap(codeFilter(
67
+ somethingsWhere((_) => _("d.-1.a", (_) => "a5"))
68
+ ))
69
+ .toArray
64
70
  )
65
71
  .toEqual([somethings[1]])
66
72
 
67
73
  expect(
68
- somethings.filterMap(codeFilter(
69
- somethingsWhere(_ => _("d.-1.a", _ => "a"))
70
- )).toArray
74
+ somethings
75
+ .filterMap(codeFilter(
76
+ somethingsWhere((_) => _("d.-1.a", (_) => "a"))
77
+ ))
78
+ .toArray
71
79
  )
72
80
  .toEqual([somethings[0]])
73
81
 
74
82
  expect(
75
- somethings.filterMap(codeFilter(
76
- somethingsWhere(_ => _("d.-1.a", _ => _.$isnt("a")))
77
- )).toArray
83
+ somethings
84
+ .filterMap(codeFilter(
85
+ somethingsWhere((_) => _("d.-1.a", (_) => _.$isnt("a")))
86
+ ))
87
+ .toArray
78
88
  )
79
89
  .toEqual([somethings[1]])
80
90
  })
@@ -14,32 +14,34 @@ import { StoreMaker } from "./service.js"
14
14
  * @tsplus static StoreMaker.Ops Live
15
15
  */
16
16
  export function StoreMakerLive(config: Config<StorageConfig>) {
17
- return config.config.flatMap(cfg => {
18
- const storageUrl = cfg.url.value
19
- if (storageUrl.startsWith("mem://")) {
20
- console.log("Using in memory store")
21
- return Effect(makeMemoryStore())
22
- }
23
- if (storageUrl.startsWith("disk://")) {
24
- const dir = storageUrl.replace("disk://", "")
25
- console.log("Using disk store at " + dir)
26
- return makeDiskStore(cfg, dir)
27
- }
28
- if (storageUrl.startsWith("redis://")) {
29
- console.log("Using Redis store")
30
- return RedisClient.makeRedisClient(makeRedis(storageUrl)).flatMap(client =>
31
- makeRedisStore(cfg).provideService(
32
- RedisClient.RedisClient,
33
- client
17
+ return config
18
+ .config
19
+ .flatMap((cfg) => {
20
+ const storageUrl = cfg.url.value
21
+ if (storageUrl.startsWith("mem://")) {
22
+ console.log("Using in memory store")
23
+ return Effect(makeMemoryStore())
24
+ }
25
+ if (storageUrl.startsWith("disk://")) {
26
+ const dir = storageUrl.replace("disk://", "")
27
+ console.log("Using disk store at " + dir)
28
+ return makeDiskStore(cfg, dir)
29
+ }
30
+ if (storageUrl.startsWith("redis://")) {
31
+ console.log("Using Redis store")
32
+ return RedisClient.makeRedisClient(makeRedis(storageUrl)).flatMap((client) =>
33
+ makeRedisStore(cfg).provideService(
34
+ RedisClient.RedisClient,
35
+ client
36
+ )
34
37
  )
35
- )
36
- }
38
+ }
37
39
 
38
- console.log("Using Cosmos DB store")
39
- return CosmosClient.makeCosmosClient(storageUrl, cfg.dbName).flatMap(client =>
40
- makeCosmosStore(cfg).provideService(CosmosClient.CosmosClient, client)
41
- )
42
- })
40
+ console.log("Using Cosmos DB store")
41
+ return CosmosClient.makeCosmosClient(storageUrl, cfg.dbName).flatMap((client) =>
42
+ makeCosmosStore(cfg).provideService(CosmosClient.CosmosClient, client)
43
+ )
44
+ })
43
45
  .toLayerScoped(StoreMaker)
44
46
  }
45
47
 
@@ -57,14 +57,14 @@ export type FilterJoinSelect = {
57
57
  }
58
58
 
59
59
  export interface Store<PM extends PersistenceModelType<Id>, Id extends string> {
60
- all: Effect<never, never, Chunk<PM>>
60
+ all: Effect<never, never, PM[]>
61
61
  filter: (
62
62
  filter: Filter<PM>,
63
63
  cursor?: { limit?: number; skip?: number }
64
- ) => Effect<never, never, Chunk<PM>>
64
+ ) => Effect<never, never, PM[]>
65
65
  filterJoinSelect: <T extends object>(
66
66
  filter: FilterJoinSelect
67
- ) => Effect<never, never, Chunk<T & { _rootId: string }>>
67
+ ) => Effect<never, never, (T & { _rootId: string })[]>
68
68
  find: (id: Id) => Effect<never, never, Option<PM>>
69
69
  set: (e: PM) => Effect<never, OptimisticConcurrencyException, PM>
70
70
  batchSet: (
@@ -124,8 +124,8 @@ export const makeMap = Effect.sync((): ContextMap => {
124
124
  // but of course removes confirming of validation rules (which may be okay for a database owned by the app, as we write safely)
125
125
  lax: false,
126
126
  cache: {
127
- getOrSetParser: p => parserCache.get(p) ?? setAndReturn(p, i => parserEnv.cache!.getOrSet(i, p)),
128
- getOrSetParsers: parsers => {
127
+ getOrSetParser: (p) => parserCache.get(p) ?? setAndReturn(p, (i) => parserEnv.cache!.getOrSet(i, p)),
128
+ getOrSetParsers: (parsers) => {
129
129
  return Object.entries(parsers).reduce((prev, [k, v]) => {
130
130
  prev[k] = parserEnv.cache!.getOrSetParser(v)
131
131
  return prev
@@ -50,20 +50,21 @@ export function codeFilter<E extends { id: string }, NE extends E>(filter: Filte
50
50
  ? Option(x as unknown as NE)
51
51
  : Option.none
52
52
  : filter.type === "join_find"
53
- ? filter.keys.some(k => {
53
+ ? filter.keys.some((k) => {
54
54
  const value = get(x, k) as Record<string, unknown>[]
55
55
  // we mimic the behavior of cosmosdb; if the shape in db does not match what we're looking for, we imagine false hit
56
56
  return (
57
- value &&
58
- value.some(v => compareCaseInsensitive(v[filter.valueKey], filter.value))
57
+ value
58
+ && value.some((v) => compareCaseInsensitive(v[filter.valueKey], filter.value))
59
59
  )
60
60
  })
61
61
  ? Option(x as unknown as NE)
62
62
  : Option.none
63
63
  // TODO: support mixed or/and
64
64
  : filter.mode === "or"
65
- ? filter.where
66
- .some(p =>
65
+ ? filter
66
+ .where
67
+ .some((p) =>
67
68
  p.t === "in"
68
69
  ? p.value.includes(get(x, p.key))
69
70
  : p.t === "not-in"
@@ -82,8 +83,9 @@ export function codeFilter<E extends { id: string }, NE extends E>(filter: Filte
82
83
  )
83
84
  ? Option(x as unknown as NE)
84
85
  : Option.none
85
- : filter.where
86
- .every(p =>
86
+ : filter
87
+ .where
88
+ .every((p) =>
87
89
  p.t === "in"
88
90
  ? p.value.includes(get(x, p.key))
89
91
  : p.t === "not-in"
@@ -100,12 +102,12 @@ export function codeFilter<E extends { id: string }, NE extends E>(filter: Filte
100
102
  ? p.key.includes(".-1.")
101
103
  ? (get(x, p.key.split(".-1.")[0]) as any[])
102
104
  // TODO: or vs and
103
- .every(_ => !compareCaseInsensitive(get(_, p.key.split(".-1.")[1]!), p.value))
105
+ .every((_) => !compareCaseInsensitive(get(_, p.key.split(".-1.")[1]!), p.value))
104
106
  : !compareCaseInsensitive(get(x, p.key), p.value)
105
107
  : p.key.includes(".-1.")
106
108
  ? (get(x, p.key.split(".-1.")[0]) as any[])
107
109
  // TODO: or vs and
108
- .some(_ => compareCaseInsensitive(get(_, p.key.split(".-1.")[1]!), p.value))
110
+ .some((_) => compareCaseInsensitive(get(_, p.key.split(".-1.")[1]!), p.value))
109
111
  : compareCaseInsensitive(get(x, p.key), p.value)
110
112
  )
111
113
  ? Option(x as unknown as NE)
@@ -116,22 +118,23 @@ export function codeFilterJoinSelect<E extends { id: string }, NE>(
116
118
  filter: FilterJoinSelect
117
119
  ) {
118
120
  return (x: E) =>
119
- filter.keys.filterMap(k => {
120
- const value = get(x, k)
121
- // we mimic the behavior of cosmosdb; if the shape in db does not match what we're looking for, we imagine false hit
122
- return value
123
- ? Option(
124
- (value as readonly NE[]).filterMap(v =>
125
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
126
- compareCaseInsensitive((v as any)[filter.valueKey], filter.value)
127
- ? Option({ ...v, _rootId: x.id })
128
- : Option.none
121
+ filter
122
+ .keys
123
+ .filterMap((k) => {
124
+ const value = get(x, k)
125
+ // we mimic the behavior of cosmosdb; if the shape in db does not match what we're looking for, we imagine false hit
126
+ return value
127
+ ? Option(
128
+ (value as readonly NE[]).filterMap((v) =>
129
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
130
+ compareCaseInsensitive((v as any)[filter.valueKey], filter.value)
131
+ ? Option({ ...v, _rootId: x.id })
132
+ : Option.none
133
+ )
129
134
  )
130
- )
131
- : Option.none
132
- })
133
- .flatMap(_ => _)
134
- .toChunk
135
+ : Option.none
136
+ })
137
+ .flatMap((_) => _)
135
138
  }
136
139
 
137
140
  function lowercaseIfString<T>(val: T) {