@effect-app/infra 0.235.1 → 1.0.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 (54) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/_cjs/api/routing/defaultErrorHandler.cjs +2 -2
  3. package/_cjs/api/routing/defaultErrorHandler.cjs.map +1 -1
  4. package/_cjs/rateLimit.cjs +3 -3
  5. package/_cjs/rateLimit.cjs.map +1 -1
  6. package/_cjs/services/Emailer/Sendgrid.cjs +2 -2
  7. package/_cjs/services/Emailer/Sendgrid.cjs.map +1 -1
  8. package/_cjs/services/Operations.cjs +1 -1
  9. package/_cjs/services/Operations.cjs.map +1 -1
  10. package/_cjs/services/Repository/ext.cjs +1 -1
  11. package/_cjs/services/Repository/ext.cjs.map +1 -1
  12. package/_cjs/services/RepositoryBase.cjs +10 -10
  13. package/_cjs/services/RepositoryBase.cjs.map +1 -1
  14. package/_cjs/services/Store/Cosmos/query.cjs +2 -2
  15. package/_cjs/services/Store/Cosmos/query.cjs.map +1 -1
  16. package/_cjs/services/Store/Cosmos.cjs +1 -1
  17. package/_cjs/services/Store/Cosmos.cjs.map +1 -1
  18. package/_cjs/services/Store/Memory.cjs +6 -6
  19. package/_cjs/services/Store/Memory.cjs.map +1 -1
  20. package/_cjs/services/Store/codeFilter.cjs +1 -1
  21. package/_cjs/services/Store/codeFilter.cjs.map +1 -1
  22. package/_cjs/services/Store/filterApi/query.cjs +1 -1
  23. package/_cjs/services/Store/filterApi/query.cjs.map +1 -1
  24. package/dist/api/routing/defaultErrorHandler.js +2 -2
  25. package/dist/api/routing/match.d.ts +1 -1
  26. package/dist/rateLimit.d.ts.map +1 -1
  27. package/dist/rateLimit.js +6 -6
  28. package/dist/services/Emailer/Sendgrid.js +3 -3
  29. package/dist/services/Operations.js +1 -1
  30. package/dist/services/Repository/ext.d.ts.map +1 -1
  31. package/dist/services/Repository/ext.js +3 -3
  32. package/dist/services/RepositoryBase.d.ts.map +1 -1
  33. package/dist/services/RepositoryBase.js +11 -11
  34. package/dist/services/Store/Cosmos/query.d.ts.map +1 -1
  35. package/dist/services/Store/Cosmos/query.js +4 -4
  36. package/dist/services/Store/Cosmos.d.ts.map +1 -1
  37. package/dist/services/Store/Cosmos.js +3 -3
  38. package/dist/services/Store/Memory.d.ts.map +1 -1
  39. package/dist/services/Store/Memory.js +8 -8
  40. package/dist/services/Store/codeFilter.js +3 -3
  41. package/dist/services/Store/filterApi/query.js +3 -3
  42. package/package.json +8 -8
  43. package/src/api/routing/defaultErrorHandler.ts +2 -2
  44. package/src/rateLimit.ts +5 -5
  45. package/src/services/Emailer/Sendgrid.ts +2 -2
  46. package/src/services/Operations.ts +1 -1
  47. package/src/services/Repository/ext.ts +2 -2
  48. package/src/services/RepositoryBase.ts +12 -13
  49. package/src/services/Store/Cosmos/query.ts +3 -3
  50. package/src/services/Store/Cosmos.ts +2 -2
  51. package/src/services/Store/Memory.ts +8 -8
  52. package/src/services/Store/Redis.ts.bak +1 -1
  53. package/src/services/Store/codeFilter.ts +2 -2
  54. package/src/services/Store/filterApi/query.ts +2 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-app/infra",
3
- "version": "0.235.1",
3
+ "version": "1.0.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -18,10 +18,10 @@
18
18
  "proper-lockfile": "^4.1.2",
19
19
  "pure-rand": "6.1.0",
20
20
  "redlock": "^4.2.0",
21
- "effect-app": "0.203.1",
22
- "@effect-app/core": "0.170.0",
23
- "@effect-app/schema": "0.221.1",
24
- "@effect-app/infra-adapters": "0.155.1"
21
+ "@effect-app/core": "1.0.0",
22
+ "effect-app": "1.0.0",
23
+ "@effect-app/schema": "1.0.0",
24
+ "@effect-app/infra-adapters": "1.0.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@babel/cli": "^7.24.1",
@@ -42,9 +42,9 @@
42
42
  },
43
43
  "peerDependencies": {
44
44
  "express": "^4.19.2",
45
- "@effect/platform": "^0.48.28",
46
- "@effect/schema": "^0.65.0",
47
- "effect": "^2.4.19"
45
+ "@effect/platform": "^0.49.0",
46
+ "@effect/schema": "^0.66.0",
47
+ "effect": "^3.0.0"
48
48
  },
49
49
  "typesVersions": {
50
50
  "*": {
@@ -38,7 +38,7 @@ export function defaultBasicErrorHandler<R>(
38
38
  const sendError = (code: number) => (body: unknown) =>
39
39
  Effect.sync(() => setBody(res, HttpBody.unsafeJson(body)).pipe(setStatus(code)))
40
40
  return r2.pipe(
41
- Effect.tapErrorCause((cause) => Cause.isFailure(cause) ? logRequestError(cause) : Effect.unit),
41
+ Effect.tapErrorCause((cause) => Cause.isFailure(cause) ? logRequestError(cause) : Effect.void),
42
42
  Effect.catchTag("ValidationError", (err) => sendError(400)(err.errors)),
43
43
  Effect
44
44
  // final catch all; expecting never so that unhandled known errors will show up
@@ -75,7 +75,7 @@ export function defaultErrorHandler<R>(
75
75
  )
76
76
  return r3
77
77
  .pipe(
78
- Effect.tapErrorCause((cause) => Cause.isFailure(cause) ? logRequestError(cause) : Effect.unit),
78
+ Effect.tapErrorCause((cause) => Cause.isFailure(cause) ? logRequestError(cause) : Effect.void),
79
79
  Effect
80
80
  .catchTags({
81
81
  "JWTError": (err) =>
package/src/rateLimit.ts CHANGED
@@ -25,7 +25,7 @@
25
25
 
26
26
  import type { Semaphore } from "@effect-app/core/Effect"
27
27
  import type { Duration, NonEmptyArray } from "effect-app"
28
- import { Effect, ReadonlyArray } from "effect-app"
28
+ import { Array, Effect } from "effect-app"
29
29
 
30
30
  /**
31
31
  * Executes the specified effect, acquiring the specified number of permits
@@ -63,7 +63,7 @@ export function batchPar<R, E, A, R2, E2, A2, T>(
63
63
  ) {
64
64
  return (items: Iterable<T>) =>
65
65
  Effect.forEach(
66
- ReadonlyArray.chunk_(items, n),
66
+ Array.chunk_(items, n),
67
67
  (_, i) =>
68
68
  Effect
69
69
  .forEach(_, (_, j) => forEachItem(_, j, i), { concurrency: "inherit" })
@@ -83,7 +83,7 @@ export function batch<R, E, A, R2, E2, A2, T>(
83
83
  ) {
84
84
  return (items: Iterable<T>) =>
85
85
  Effect.forEach(
86
- ReadonlyArray.chunk_(items, n),
86
+ Array.chunk_(items, n),
87
87
  (_, i) =>
88
88
  Effect
89
89
  .forEach(_, (_, j) => forEachItem(_, j, i), { concurrency: "inherit" })
@@ -125,10 +125,10 @@ export function naiveRateLimit(
125
125
  forEachBatch: (a: A[]) => Effect<A2, E2, R2>
126
126
  ) =>
127
127
  Effect.forEach(
128
- ReadonlyArray.chunk_(items, n),
128
+ Array.chunk_(items, n),
129
129
  (batch, i) =>
130
130
  ((i === 0)
131
- ? Effect.unit
131
+ ? Effect.void
132
132
  : Effect.sleep(d))
133
133
  .pipe(Effect.zipRight(
134
134
  Effect
@@ -1,7 +1,7 @@
1
1
  import { dropUndefinedT } from "@effect-app/core/utils"
2
2
  import type { EmailData } from "@sendgrid/helpers/classes/email-address.js"
3
3
  import sgMail from "@sendgrid/mail"
4
- import { Effect, Equivalence, ReadonlyArray, Secret } from "effect-app"
4
+ import { Array, Effect, Equivalence, Secret } from "effect-app"
5
5
  import { inspect } from "util"
6
6
  import { Emailer } from "./service.js"
7
7
  import type { EmailMsg, EmailMsgOptionalFrom, SendgridConfig } from "./service.js"
@@ -106,7 +106,7 @@ const eq = Equivalence.mapInput(
106
106
  // https://stackoverflow.com/a/53603076/11595834
107
107
  function renderFakeIfTest(addr: EmailData | EmailData[], makeId: () => number) {
108
108
  return Array.isArray(addr)
109
- ? ReadonlyArray.dedupeWith(
109
+ ? Array.dedupeWith(
110
110
  addr
111
111
  .map((x) => (isTestAddress(x) ? renderFake(x, makeId) : x)),
112
112
  eq
@@ -106,7 +106,7 @@ export class Operations extends Context.TagMakeId("effect-app/Operations", make)
106
106
  Effect
107
107
  .flatMap((_) => {
108
108
  if (Exit.isSuccess(_)) {
109
- return Effect.unit
109
+ return Effect.void
110
110
  } else {
111
111
  return reportAppError(_.cause)
112
112
  }
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  // Update = Must return updated items
3
3
  // Modify = Must `set` updated items, and can return anything.
4
- import { Effect, ReadonlyArray } from "effect-app"
4
+ import { Array, Effect } from "effect-app"
5
5
  import type { NonEmptyArray } from "effect-app"
6
6
  import { type FixEnv, runTerm } from "effect-app/Pure"
7
7
  import { NotFoundError } from "../../errors.js"
@@ -166,7 +166,7 @@ export function saveManyWithPureBatched_<
166
166
  batchSize = 100
167
167
  ) {
168
168
  return Effect.forEach(
169
- ReadonlyArray.chunk_(items, batchSize),
169
+ Array.chunk_(items, batchSize),
170
170
  (batch) =>
171
171
  saveAllWithEffectInt(
172
172
  self,
@@ -24,6 +24,7 @@ import type { ParseResult, Schema } from "@effect-app/schema"
24
24
  import { NonNegativeInt } from "@effect-app/schema"
25
25
  import type { NonEmptyArray, NonEmptyReadonlyArray } from "effect-app"
26
26
  import {
27
+ Array,
27
28
  Chunk,
28
29
  Context,
29
30
  Effect,
@@ -32,7 +33,6 @@ import {
32
33
  Option,
33
34
  pipe,
34
35
  PubSub,
35
- ReadonlyArray,
36
36
  Request,
37
37
  RequestResolver,
38
38
  S,
@@ -40,7 +40,6 @@ import {
40
40
  } from "effect-app"
41
41
  import { runTerm } from "effect-app/Pure"
42
42
  import type { FixEnv, PureEnv } from "effect-app/Pure"
43
- import type { NoInfer } from "effect/Types"
44
43
  import { type InvalidStateError, NotFoundError, type OptimisticConcurrencyException } from "../errors.js"
45
44
  import type { FieldValues } from "../filter/types.js"
46
45
  import { make as makeQuery } from "./query.js"
@@ -239,8 +238,8 @@ export class RepositoryBaseC3<
239
238
  Effect.andThen((_) =>
240
239
  Array.isArray(_)
241
240
  ? batch === undefined
242
- ? saveManyWithPure_(this, _, pure as any)
243
- : saveManyWithPureBatched_(this, _, pure as any, batch === "batched" ? 100 : batch)
241
+ ? saveManyWithPure_(this, _ as readonly T[], pure as any)
242
+ : saveManyWithPureBatched_(this, _ as readonly T[], pure as any, batch === "batched" ? 100 : batch)
244
243
  : saveWithPure_(this, _ as any, pure as any)
245
244
  )
246
245
  ) as any
@@ -278,7 +277,7 @@ export class RepositoryBaseC3<
278
277
  } = (items, pure, batch?: "batched" | number) =>
279
278
  batch
280
279
  ? Effect.forEach(
281
- ReadonlyArray.chunk_(items, batch === "batched" ? 100 : batch),
280
+ Array.chunk_(items, batch === "batched" ? 100 : batch),
282
281
  (batch) =>
283
282
  saveAllWithEffectInt(
284
283
  this,
@@ -392,7 +391,7 @@ export function makeRepo<
392
391
  const pubCfg = yield* $(Effect.context<R2>())
393
392
  const pub = "publishEvents" in args
394
393
  ? flow(args.publishEvents, Effect.provide(pubCfg))
395
- : () => Effect.unit
394
+ : () => Effect.void
396
395
  const changeFeed = yield* $(PubSub.unbounded<[T[], "save" | "remove"]>())
397
396
 
398
397
  const allE = cms
@@ -466,10 +465,10 @@ export function makeRepo<
466
465
  ret.forEach((_) => set(_.id, _._etag))
467
466
  })
468
467
  )
469
- .pipe(Effect.asUnit)
468
+ .pipe(Effect.asVoid)
470
469
 
471
470
  const saveAll = (a: Iterable<T>) =>
472
- encodeMany(Array.from(a))
471
+ encodeMany(Array.fromIterable(a))
473
472
  .pipe(
474
473
  Effect.orDie,
475
474
  Effect.andThen(saveAllE)
@@ -485,7 +484,7 @@ export function makeRepo<
485
484
  // TODO: for full consistency the events should be stored within the same database transaction, and then picked up.
486
485
  (_) => Effect.flatMapOption(_, pub),
487
486
  Effect.andThen(changeFeed.publish([Chunk.toArray(it), "save"])),
488
- Effect.asUnit
487
+ Effect.asVoid
489
488
  )
490
489
  })
491
490
  .pipe(Effect.withSpan("saveAndPublish"))
@@ -533,7 +532,7 @@ export function makeRepo<
533
532
  .filter(args)
534
533
  .pipe(Effect.tap((items) =>
535
534
  args.select
536
- ? Effect.unit
535
+ ? Effect.void
537
536
  : Effect.map(cms, ({ set }) => items.forEach((_) => set((_ as Encoded).id, (_ as PM)._etag)))
538
537
  ))
539
538
 
@@ -555,7 +554,7 @@ export function makeRepo<
555
554
  .pipe(
556
555
  Effect.flatMap(flow(
557
556
  S.decode(S.Array(a.schema)),
558
- Effect.map(ReadonlyArray.getSomes),
557
+ Effect.map(Array.getSomes),
559
558
  Effect.provide(rctx)
560
559
  ))
561
560
  )
@@ -574,7 +573,7 @@ export function makeRepo<
574
573
  ? Effect.andThen(
575
574
  eff,
576
575
  flow(
577
- ReadonlyArray.head,
576
+ Array.head,
578
577
  Effect.mapError(() => new NotFoundError({ id: "query", /* TODO */ type: name }))
579
578
  )
580
579
  )
@@ -1051,7 +1050,7 @@ export const makeRequest = <
1051
1050
  Effect.forEach(requests, (r) =>
1052
1051
  Request.complete(
1053
1052
  r,
1054
- ReadonlyArray
1053
+ Array
1055
1054
  .findFirst(items, (_) => _.id === r.id)
1056
1055
  .pipe(Option.match({
1057
1056
  onNone: () => Exit.fail(new NotFoundError({ type: repo.itemType, id: r.id })),
@@ -1,4 +1,4 @@
1
- import { Effect, Equivalence, pipe, ReadonlyArray } from "effect-app"
1
+ import { Array, Effect, Equivalence, pipe } from "effect-app"
2
2
  import type { NonEmptyReadonlyArray } from "effect-app"
3
3
  import { assertUnreachable } from "effect-app/utils"
4
4
  import type { FilterR, FilterResult } from "../filterApi/query.js"
@@ -100,7 +100,7 @@ export function buildWhereCosmosQuery3(
100
100
  let s = ""
101
101
  let l = 0
102
102
  const printN = (n: number) => {
103
- return n === 0 ? "" : ReadonlyArray.range(1, n).map(() => " ").join("")
103
+ return n === 0 ? "" : Array.range(1, n).map(() => " ").join("")
104
104
  }
105
105
  for (const e of state) {
106
106
  switch (e.t) {
@@ -175,7 +175,7 @@ export function buildWhereCosmosQuery3(
175
175
  .filter((_) => _.path.includes(".-1."))
176
176
  .map((_) => _.path.split(".-1.")[0])
177
177
  .map((_) => `JOIN ${_} IN f.${_}`),
178
- ReadonlyArray.dedupeWith(Equivalence.string)
178
+ Array.dedupeWith(Equivalence.string)
179
179
  )
180
180
  .join("\n")
181
181
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { toNonEmptyArray } from "@effect-app/core/Array"
4
4
  import { CosmosClient, CosmosClientLayer } from "@effect-app/infra-adapters/cosmos-client"
5
- import { Chunk, Duration, Effect, Layer, Option, pipe, ReadonlyArray, Secret, Struct } from "effect-app"
5
+ import { Array, Chunk, Duration, Effect, Layer, Option, pipe, Secret, Struct } from "effect-app"
6
6
  import type { NonEmptyReadonlyArray } from "effect-app"
7
7
  import { dropUndefinedT } from "effect-app/utils"
8
8
  import { OptimisticConcurrencyException } from "../../errors.js"
@@ -75,7 +75,7 @@ function makeCosmosStore({ prefix }: StorageConfig) {
75
75
  })
76
76
  ] as const
77
77
  )
78
- const batches = Chunk.toReadonlyArray(ReadonlyArray.chunk_(b, config?.maxBulkSize ?? 10))
78
+ const batches = Chunk.toReadonlyArray(Array.chunk_(b, config?.maxBulkSize ?? 10))
79
79
 
80
80
  const batchResult = yield* $(
81
81
  Effect.forEach(
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
 
3
- import { Effect, FiberRef, flow, Option, Order, pipe, ReadonlyArray, Ref, Struct } from "effect-app"
3
+ import { Array, Effect, FiberRef, flow, Option, Order, pipe, Ref, Struct } from "effect-app"
4
4
  import type { NonEmptyArray, NonEmptyReadonlyArray } from "effect-app"
5
5
  import { get } from "effect-app/utils"
6
6
  import type { RequestContext } from "../../RequestContext.js"
@@ -30,24 +30,24 @@ export function memFilter<T extends { id: string }, U extends keyof T = never>(f
30
30
  })
31
31
  ))
32
32
  if (Option.isSome(ords)) {
33
- c = ReadonlyArray.sortBy(...ords.value)(c)
33
+ c = Array.sortBy(...ords.value)(c)
34
34
  }
35
35
  if (!skip && limit === 1) {
36
36
  return select(
37
- ReadonlyArray.findFirst(c, f.filter ? codeFilter(f.filter) : (_) => Option.some(_)).pipe(
38
- Option.map(ReadonlyArray.make),
37
+ Array.findFirst(c, f.filter ? codeFilter(f.filter) : (_) => Option.some(_)).pipe(
38
+ Option.map(Array.make),
39
39
  Option.getOrElse(
40
40
  () => []
41
41
  )
42
42
  )
43
43
  )
44
44
  }
45
- let r = f.filter ? ReadonlyArray.filterMap(c, codeFilter(f.filter)) : c
45
+ let r = f.filter ? Array.filterMap(c, codeFilter(f.filter)) : c
46
46
  if (skip) {
47
- r = ReadonlyArray.drop(r, skip)
47
+ r = Array.drop(r, skip)
48
48
  }
49
49
  if (limit !== undefined) {
50
- r = ReadonlyArray.take(r, limit)
50
+ r = Array.take(r, limit)
51
51
  }
52
52
 
53
53
  return select(r)
@@ -96,7 +96,7 @@ export function makeMemoryStoreInt<Id extends string, Encoded extends { id: Id }
96
96
  const withPermit = sem.withPermits(1)
97
97
  const values = Effect.map(Ref.get(store), (s) => s.values())
98
98
 
99
- const all = Effect.map(values, ReadonlyArray.fromIterable)
99
+ const all = Effect.map(values, Array.fromIterable)
100
100
 
101
101
  const batchSet = (items: NonEmptyReadonlyArray<PM>) =>
102
102
  Effect
@@ -43,7 +43,7 @@ function makeRedisStore({ prefix }: StorageConfig) {
43
43
  const withPermit = sem.withPermits(1)
44
44
 
45
45
  const asMap = get.map((x) => new Map(x.map((x) => [x.id, x] as const)))
46
- const all = get.map(ReadonlyArray.fromIterable)
46
+ const all = get.map(Array.fromIterable)
47
47
  const batchSet = (items: NonEmptyReadonlyArray<PM>) =>
48
48
  Effect
49
49
  .forEach(items, (e) => s.find(e.id).flatMap((current) => updateETag(e, current)))
@@ -1,4 +1,4 @@
1
- import { ReadonlyArray } from "effect-app"
1
+ import { Array } from "effect-app"
2
2
  import { assertUnreachable, get } from "effect-app/utils"
3
3
  import type { FilterR, FilterResult } from "./filterApi/query.js"
4
4
  import { compare, greaterThan, greaterThanExclusive, lowerThan, lowerThanExclusive } from "./utils.js"
@@ -58,7 +58,7 @@ export const codeFilter3_ = <E>(state: readonly FilterResult[], sut: E, statemen
58
58
  let s = ""
59
59
  let l = 0
60
60
  const printN = (n: number) => {
61
- return n === 0 ? "" : ReadonlyArray.range(1, n).map(() => " ").join("")
61
+ return n === 0 ? "" : Array.range(1, n).map(() => " ").join("")
62
62
  }
63
63
  // TODO: path str updates
64
64
 
@@ -1,4 +1,4 @@
1
- import { ReadonlyArray } from "effect-app"
1
+ import { Array } from "effect-app"
2
2
  import type { FieldValues } from "../../../filter/types.js"
3
3
  import type { FieldPath, FieldPathValue } from "../../../filter/types/path/eager.js"
4
4
  import type { Filter, Ops } from "./proxy.js"
@@ -40,7 +40,7 @@ export const print = (state: readonly FilterResult[]) => {
40
40
  let s = ""
41
41
  let l = 0
42
42
  const printN = (n: number) => {
43
- return n === 0 ? "" : ReadonlyArray.range(1, n).map(() => " ").join("")
43
+ return n === 0 ? "" : Array.range(1, n).map(() => " ").join("")
44
44
  }
45
45
  for (const e of state) {
46
46
  switch (e.t) {