effect 4.0.0-beta.24 → 4.0.0-beta.26

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 (121) hide show
  1. package/dist/Config.js +4 -4
  2. package/dist/Config.js.map +1 -1
  3. package/dist/Effect.d.ts +21 -14
  4. package/dist/Effect.d.ts.map +1 -1
  5. package/dist/Effect.js +2 -1
  6. package/dist/Effect.js.map +1 -1
  7. package/dist/Runtime.d.ts +66 -0
  8. package/dist/Runtime.d.ts.map +1 -1
  9. package/dist/Runtime.js +72 -5
  10. package/dist/Runtime.js.map +1 -1
  11. package/dist/Schema.d.ts +15 -32
  12. package/dist/Schema.d.ts.map +1 -1
  13. package/dist/Schema.js +9 -17
  14. package/dist/Schema.js.map +1 -1
  15. package/dist/SchemaAST.js +91 -2
  16. package/dist/SchemaAST.js.map +1 -1
  17. package/dist/SchemaGetter.d.ts +3 -3
  18. package/dist/SchemaRepresentation.d.ts.map +1 -1
  19. package/dist/SchemaRepresentation.js +12 -8
  20. package/dist/SchemaRepresentation.js.map +1 -1
  21. package/dist/Stdio.d.ts +10 -2
  22. package/dist/Stdio.d.ts.map +1 -1
  23. package/dist/Stdio.js +18 -0
  24. package/dist/Stdio.js.map +1 -1
  25. package/dist/internal/effect.js.map +1 -1
  26. package/dist/internal/schema/representation.js +7 -3
  27. package/dist/internal/schema/representation.js.map +1 -1
  28. package/dist/internal/schema/to-codec.js +7 -10
  29. package/dist/internal/schema/to-codec.js.map +1 -1
  30. package/dist/testing/TestClock.d.ts +2 -2
  31. package/dist/unstable/ai/AiError.d.ts +6 -3
  32. package/dist/unstable/ai/AiError.d.ts.map +1 -1
  33. package/dist/unstable/ai/AiError.js +8 -4
  34. package/dist/unstable/ai/AiError.js.map +1 -1
  35. package/dist/unstable/ai/LanguageModel.js +7 -5
  36. package/dist/unstable/ai/LanguageModel.js.map +1 -1
  37. package/dist/unstable/cli/CliError.d.ts +19 -52
  38. package/dist/unstable/cli/CliError.d.ts.map +1 -1
  39. package/dist/unstable/cli/CliError.js +21 -53
  40. package/dist/unstable/cli/CliError.js.map +1 -1
  41. package/dist/unstable/cli/Command.d.ts +117 -62
  42. package/dist/unstable/cli/Command.d.ts.map +1 -1
  43. package/dist/unstable/cli/Command.js +95 -32
  44. package/dist/unstable/cli/Command.js.map +1 -1
  45. package/dist/unstable/cli/GlobalFlag.d.ts +1 -1
  46. package/dist/unstable/cli/GlobalFlag.d.ts.map +1 -1
  47. package/dist/unstable/cli/internal/command.d.ts +27 -10
  48. package/dist/unstable/cli/internal/command.d.ts.map +1 -1
  49. package/dist/unstable/cli/internal/command.js +40 -23
  50. package/dist/unstable/cli/internal/command.js.map +1 -1
  51. package/dist/unstable/cli/internal/config.js +42 -0
  52. package/dist/unstable/cli/internal/config.js.map +1 -1
  53. package/dist/unstable/cli/internal/help.d.ts +4 -4
  54. package/dist/unstable/cli/internal/help.d.ts.map +1 -1
  55. package/dist/unstable/cli/internal/help.js +25 -7
  56. package/dist/unstable/cli/internal/help.js.map +1 -1
  57. package/dist/unstable/cli/internal/parser.js +26 -6
  58. package/dist/unstable/cli/internal/parser.js.map +1 -1
  59. package/dist/unstable/http/HttpClient.d.ts.map +1 -1
  60. package/dist/unstable/http/HttpClient.js +18 -10
  61. package/dist/unstable/http/HttpClient.js.map +1 -1
  62. package/dist/unstable/httpapi/HttpApiBuilder.d.ts.map +1 -1
  63. package/dist/unstable/httpapi/HttpApiBuilder.js +1 -7
  64. package/dist/unstable/httpapi/HttpApiBuilder.js.map +1 -1
  65. package/dist/unstable/httpapi/HttpApiClient.d.ts +6 -6
  66. package/dist/unstable/httpapi/HttpApiClient.d.ts.map +1 -1
  67. package/dist/unstable/httpapi/HttpApiClient.js.map +1 -1
  68. package/dist/unstable/httpapi/HttpApiEndpoint.d.ts +10 -10
  69. package/dist/unstable/httpapi/HttpApiEndpoint.d.ts.map +1 -1
  70. package/dist/unstable/httpapi/HttpApiEndpoint.js +2 -2
  71. package/dist/unstable/httpapi/HttpApiEndpoint.js.map +1 -1
  72. package/dist/unstable/httpapi/HttpApiError.d.ts +6 -15
  73. package/dist/unstable/httpapi/HttpApiError.d.ts.map +1 -1
  74. package/dist/unstable/httpapi/HttpApiError.js +16 -21
  75. package/dist/unstable/httpapi/HttpApiError.js.map +1 -1
  76. package/dist/unstable/reactivity/Atom.d.ts +56 -0
  77. package/dist/unstable/reactivity/Atom.d.ts.map +1 -1
  78. package/dist/unstable/reactivity/Atom.js +66 -0
  79. package/dist/unstable/reactivity/Atom.js.map +1 -1
  80. package/dist/unstable/reactivity/AtomHttpApi.d.ts +2 -2
  81. package/dist/unstable/reactivity/AtomHttpApi.d.ts.map +1 -1
  82. package/dist/unstable/rpc/RpcServer.d.ts +5 -2
  83. package/dist/unstable/rpc/RpcServer.d.ts.map +1 -1
  84. package/dist/unstable/rpc/RpcServer.js.map +1 -1
  85. package/dist/unstable/sql/SqlResolver.d.ts.map +1 -1
  86. package/dist/unstable/sql/SqlResolver.js +15 -6
  87. package/dist/unstable/sql/SqlResolver.js.map +1 -1
  88. package/dist/unstable/sql/SqlSchema.d.ts +2 -2
  89. package/dist/unstable/sql/SqlSchema.d.ts.map +1 -1
  90. package/dist/unstable/sql/SqlSchema.js.map +1 -1
  91. package/package.json +1 -1
  92. package/src/Config.ts +4 -4
  93. package/src/Effect.ts +30 -10
  94. package/src/Runtime.ts +95 -5
  95. package/src/Schema.ts +20 -52
  96. package/src/SchemaAST.ts +127 -2
  97. package/src/SchemaGetter.ts +3 -3
  98. package/src/SchemaRepresentation.ts +12 -8
  99. package/src/Stdio.ts +21 -2
  100. package/src/internal/effect.ts +2 -1
  101. package/src/internal/schema/representation.ts +8 -4
  102. package/src/internal/schema/to-codec.ts +7 -17
  103. package/src/unstable/ai/AiError.ts +8 -4
  104. package/src/unstable/ai/LanguageModel.ts +8 -5
  105. package/src/unstable/cli/CliError.ts +43 -55
  106. package/src/unstable/cli/Command.ts +348 -180
  107. package/src/unstable/cli/GlobalFlag.ts +1 -1
  108. package/src/unstable/cli/internal/command.ts +62 -32
  109. package/src/unstable/cli/internal/config.ts +49 -0
  110. package/src/unstable/cli/internal/help.ts +41 -16
  111. package/src/unstable/cli/internal/parser.ts +36 -10
  112. package/src/unstable/http/HttpClient.ts +28 -13
  113. package/src/unstable/httpapi/HttpApiBuilder.ts +1 -7
  114. package/src/unstable/httpapi/HttpApiClient.ts +6 -6
  115. package/src/unstable/httpapi/HttpApiEndpoint.ts +4 -4
  116. package/src/unstable/httpapi/HttpApiError.ts +23 -21
  117. package/src/unstable/reactivity/Atom.ts +132 -0
  118. package/src/unstable/reactivity/AtomHttpApi.ts +2 -2
  119. package/src/unstable/rpc/RpcServer.ts +5 -0
  120. package/src/unstable/sql/SqlResolver.ts +15 -5
  121. package/src/unstable/sql/SqlSchema.ts +2 -2
@@ -15,7 +15,7 @@ import * as HttpRouter from "../http/HttpRouter.ts"
15
15
  import type { HttpServerRequest } from "../http/HttpServerRequest.ts"
16
16
  import type { HttpServerResponse } from "../http/HttpServerResponse.ts"
17
17
  import type * as Multipart from "../http/Multipart.ts"
18
- import { HttpApiSchemaError } from "./HttpApiError.ts"
18
+ import { BadRequestFromSchemaError, type BadRequestNoContent } from "./HttpApiError.ts"
19
19
  import type * as HttpApiGroup from "./HttpApiGroup.ts"
20
20
  import type * as HttpApiMiddleware from "./HttpApiMiddleware.ts"
21
21
  import * as HttpApiSchema from "./HttpApiSchema.ts"
@@ -53,7 +53,7 @@ export interface HttpApiEndpoint<
53
53
  out Payload extends Schema.Top = never,
54
54
  out Headers extends Schema.Top = never,
55
55
  out Success extends Schema.Top = typeof HttpApiSchema.NoContent,
56
- out Error extends Schema.Top = typeof HttpApiSchemaError,
56
+ out Error extends Schema.Top = typeof BadRequestNoContent,
57
57
  in out Middleware = never,
58
58
  out MiddlewareR = never
59
59
  > extends Pipeable {
@@ -179,7 +179,7 @@ export function getErrorSchemas(endpoint: AnyWithProps): [Schema.Top, ...Array<S
179
179
  schemas.add(key.error)
180
180
  }
181
181
  }
182
- return Arr.append(Array.from(schemas), HttpApiSchemaError)
182
+ return Arr.append(Array.from(schemas), BadRequestFromSchemaError)
183
183
  }
184
184
 
185
185
  /**
@@ -936,7 +936,7 @@ export const make = <Method extends HttpMethod>(method: Method) =>
936
936
  : Payload,
937
937
  Headers extends Schema.Struct.Fields ? Schema.Struct<Headers> : Headers,
938
938
  Success extends ReadonlyArray<Schema.Top> ? Success[number] : Success,
939
- (Error extends ReadonlyArray<Schema.Top> ? Error[number] : Error) | typeof HttpApiSchemaError
939
+ (Error extends ReadonlyArray<Schema.Top> ? Error[number] : Error) | typeof BadRequestNoContent
940
940
  > => {
941
941
  return makeProto({
942
942
  name,
@@ -2,30 +2,11 @@
2
2
  * @since 4.0.0
3
3
  */
4
4
  import * as ErrorReporter from "../../ErrorReporter.ts"
5
+ import { identity } from "../../Function.ts"
5
6
  import * as Schema from "../../Schema.ts"
7
+ import * as Transformation from "../../SchemaTransformation.ts"
6
8
  import * as HttpApiSchema from "./HttpApiSchema.ts"
7
9
 
8
- /**
9
- * @category errors
10
- * @since 4.0.0
11
- */
12
- export class HttpApiSchemaError extends Schema.ErrorClass<HttpApiSchemaError>("effect/HttpApiSchemaError")({
13
- _tag: Schema.tag("HttpApiSchemaError"),
14
- message: Schema.String
15
- }, {
16
- httpApiStatus: 400,
17
- description: "The request or response did not match the expected schema"
18
- }) {
19
- /**
20
- * @since 4.0.0
21
- */
22
- static fromSchemaError(error: Schema.SchemaError): HttpApiSchemaError {
23
- return new HttpApiSchemaError({ message: error.message })
24
- }
25
-
26
- override readonly [ErrorReporter.ignore] = true
27
- }
28
-
29
10
  /**
30
11
  * @category Built-in errors
31
12
  * @since 4.0.0
@@ -37,6 +18,7 @@ export class BadRequest extends Schema.ErrorClass<BadRequest>("effect/HttpApiErr
37
18
  httpApiStatus: 400
38
19
  }) {
39
20
  override readonly [ErrorReporter.ignore] = true
21
+ static readonly singleton = new BadRequest()
40
22
  }
41
23
 
42
24
  /**
@@ -47,6 +29,26 @@ export const BadRequestNoContent = BadRequest.pipe(HttpApiSchema.asNoContent({
47
29
  decode: () => new BadRequest({})
48
30
  }))
49
31
 
32
+ /**
33
+ * @category Built-in errors
34
+ * @since 4.0.0
35
+ */
36
+ export const BadRequestFromSchemaError = BadRequest.pipe(
37
+ Schema.decodeTo(
38
+ Schema.Union([Schema.declare(Schema.isSchemaError), BadRequest]),
39
+ Transformation.transform({
40
+ encode: (_) => BadRequest.singleton,
41
+ decode: identity
42
+ })
43
+ ),
44
+ HttpApiSchema.asNoContent({
45
+ decode: () => new BadRequest({})
46
+ })
47
+ ).annotate({
48
+ httpApiStatus: 400,
49
+ description: "BadRequest"
50
+ })
51
+
50
52
  /**
51
53
  * @category Built-in errors
52
54
  * @since 4.0.0
@@ -1750,6 +1750,138 @@ export const withRefresh: {
1750
1750
  }
1751
1751
  )
1752
1752
 
1753
+ /**
1754
+ * Adds stale-while-revalidate refresh behavior to an async result atom.
1755
+ *
1756
+ * Automatic revalidation during reads is skipped while the current value is
1757
+ * fresh within `staleTime`. Manual `refresh` calls remain forceful and always
1758
+ * forward to the wrapped atom.
1759
+ *
1760
+ * Use `revalidateOnMount` to control whether stale data should trigger a
1761
+ * background refresh on first mount. Use `revalidateOnFocus` to control
1762
+ * focus behavior. `true` respects `staleTime` and `"always"` forces refetch.
1763
+ *
1764
+ * @since 4.0.0
1765
+ * @category combinators
1766
+ */
1767
+ export const swr: {
1768
+ /**
1769
+ * Adds stale-while-revalidate refresh behavior to an async result atom.
1770
+ *
1771
+ * Automatic revalidation during reads is skipped while the current value is
1772
+ * fresh within `staleTime`. Manual `refresh` calls remain forceful and always
1773
+ * forward to the wrapped atom.
1774
+ *
1775
+ * Use `revalidateOnMount` to control whether stale data should trigger a
1776
+ * background refresh on first mount. Use `revalidateOnFocus` to control
1777
+ * focus behavior. `true` respects `staleTime` and `"always"` forces refetch.
1778
+ *
1779
+ * @since 4.0.0
1780
+ * @category combinators
1781
+ */
1782
+ (
1783
+ options: {
1784
+ readonly staleTime: Duration.Input
1785
+ readonly revalidateOnMount?: boolean | undefined
1786
+ readonly revalidateOnFocus?: boolean | "always" | undefined
1787
+ readonly focusSignal?: Atom<any> | undefined
1788
+ }
1789
+ ): <R extends Atom<AsyncResult.AsyncResult<any, any>>>(self: R) => WithoutSerializable<R>
1790
+ /**
1791
+ * Adds stale-while-revalidate refresh behavior to an async result atom.
1792
+ *
1793
+ * Automatic revalidation during reads is skipped while the current value is
1794
+ * fresh within `staleTime`. Manual `refresh` calls remain forceful and always
1795
+ * forward to the wrapped atom.
1796
+ *
1797
+ * Use `revalidateOnMount` to control whether stale data should trigger a
1798
+ * background refresh on first mount. Use `revalidateOnFocus` to control
1799
+ * focus behavior. `true` respects `staleTime` and `"always"` forces refetch.
1800
+ *
1801
+ * @since 4.0.0
1802
+ * @category combinators
1803
+ */
1804
+ <R extends Atom<AsyncResult.AsyncResult<any, any>>>(
1805
+ self: R,
1806
+ options: {
1807
+ readonly staleTime: Duration.Input
1808
+ readonly revalidateOnMount?: boolean | undefined
1809
+ readonly revalidateOnFocus?: boolean | "always" | undefined
1810
+ readonly focusSignal?: Atom<any> | undefined
1811
+ }
1812
+ ): WithoutSerializable<R>
1813
+ } = dual(
1814
+ 2,
1815
+ <A, E>(
1816
+ self: Atom<AsyncResult.AsyncResult<A, E>>,
1817
+ options: {
1818
+ readonly staleTime: Duration.Input
1819
+ readonly revalidateOnMount?: boolean | undefined
1820
+ readonly revalidateOnFocus?: boolean | "always" | undefined
1821
+ readonly focusSignal?: Atom<any> | undefined
1822
+ }
1823
+ ): Atom<AsyncResult.AsyncResult<A, E>> => {
1824
+ const staleTime = Duration.toMillis(Duration.fromInputUnsafe(options.staleTime))
1825
+ const refresh = self.refresh ?? function(f: <A>(atom: Atom<A>) => void) {
1826
+ f(self)
1827
+ }
1828
+ function read(get: Context) {
1829
+ const current = get.once(self)
1830
+ get.subscribe(self, (value) => {
1831
+ get.setSelf(value)
1832
+ })
1833
+ if (options.revalidateOnFocus && options.focusSignal) {
1834
+ get.once(options.focusSignal)
1835
+ get.subscribe(
1836
+ options.focusSignal,
1837
+ options.revalidateOnFocus === "always" ? () => get.refresh(self) : () => {
1838
+ const current = get.once(self)
1839
+ if (shouldRevalidateSWR(current, staleTime)) {
1840
+ get.refresh(self)
1841
+ }
1842
+ }
1843
+ )
1844
+ }
1845
+ const firstRead = Option.isNone(get.self<AsyncResult.AsyncResult<A, E>>())
1846
+ if (firstRead && options.revalidateOnMount === false) {
1847
+ return current
1848
+ }
1849
+ if (shouldRevalidateSWR(current, staleTime)) {
1850
+ get.refresh(self)
1851
+ }
1852
+ return current
1853
+ }
1854
+ return isWritable(self)
1855
+ ? writable(read, (ctx, value) => {
1856
+ ctx.set(self, value)
1857
+ }, refresh)
1858
+ : readable(read, refresh)
1859
+ }
1860
+ ) as any
1861
+
1862
+ const swrTimestamp = <A, E>(result: AsyncResult.AsyncResult<A, E>): Option.Option<number> => {
1863
+ if (result._tag === "Success") {
1864
+ return Option.some(result.timestamp)
1865
+ }
1866
+ if (result._tag === "Failure") {
1867
+ return Option.map(result.previousSuccess, (success) => success.timestamp)
1868
+ }
1869
+ return Option.none()
1870
+ }
1871
+
1872
+ const isFreshWithin = (timestamp: number, staleTime: number, now: number): boolean => now - timestamp < staleTime
1873
+
1874
+ const shouldRevalidateSWR = <A, E>(result: AsyncResult.AsyncResult<A, E>, staleTime: number): boolean => {
1875
+ if (result.waiting) {
1876
+ return false
1877
+ }
1878
+ const timestamp = Option.getOrUndefined(swrTimestamp(result))
1879
+ if (timestamp === undefined) {
1880
+ return result._tag !== "Initial"
1881
+ }
1882
+ return !isFreshWithin(timestamp, staleTime, Date.now())
1883
+ }
1884
+
1753
1885
  /**
1754
1886
  * @since 4.0.0
1755
1887
  * @category Optimistic
@@ -67,7 +67,7 @@ export interface AtomHttpApiClient<Self, Id extends string, Groups extends HttpA
67
67
  }
68
68
  >,
69
69
  WithResponse extends true ? [_Success["Type"], HttpClientResponse] : _Success["Type"],
70
- _Error | HttpClientError.HttpClientError | SchemaError
70
+ _Error["Type"] | HttpClientError.HttpClientError | SchemaError
71
71
  >
72
72
  : never
73
73
 
@@ -124,7 +124,7 @@ export interface AtomHttpApiClient<Self, Id extends string, Groups extends HttpA
124
124
  ] ? Atom.Atom<
125
125
  AsyncResult.AsyncResult<
126
126
  WithResponse extends true ? [_Success["Type"], HttpClientResponse] : _Success["Type"],
127
- _Error | HttpClientError.HttpClientError | SchemaError
127
+ _Error["Type"] | HttpClientError.HttpClientError | SchemaError
128
128
  >
129
129
  >
130
130
  : never
@@ -739,6 +739,7 @@ export const layerHttp = <Rpcs extends Rpc.Any>(options: {
739
739
  readonly spanPrefix?: string | undefined
740
740
  readonly spanAttributes?: Record<string, unknown> | undefined
741
741
  readonly concurrency?: number | "unbounded" | undefined
742
+ readonly disableFatalDefects?: boolean | undefined
742
743
  }): Layer.Layer<
743
744
  never,
744
745
  never,
@@ -1080,6 +1081,7 @@ export const toHttpEffect: <Rpcs extends Rpc.Any>(
1080
1081
  readonly disableTracing?: boolean | undefined
1081
1082
  readonly spanPrefix?: string | undefined
1082
1083
  readonly spanAttributes?: Record<string, unknown> | undefined
1084
+ readonly disableFatalDefects?: boolean | undefined
1083
1085
  } | undefined
1084
1086
  ) => Effect.Effect<
1085
1087
  Effect.Effect<HttpServerResponse.HttpServerResponse, never, Scope.Scope | HttpServerRequest.HttpServerRequest>,
@@ -1095,6 +1097,7 @@ export const toHttpEffect: <Rpcs extends Rpc.Any>(
1095
1097
  readonly disableTracing?: boolean | undefined
1096
1098
  readonly spanPrefix?: string | undefined
1097
1099
  readonly spanAttributes?: Record<string, unknown> | undefined
1100
+ readonly disableFatalDefects?: boolean | undefined
1098
1101
  }
1099
1102
  ) {
1100
1103
  const { httpEffect, protocol } = yield* makeProtocolWithHttpEffect
@@ -1116,6 +1119,7 @@ export const toHttpEffectWebsocket: <Rpcs extends Rpc.Any>(
1116
1119
  readonly disableTracing?: boolean | undefined
1117
1120
  readonly spanPrefix?: string | undefined
1118
1121
  readonly spanAttributes?: Record<string, unknown> | undefined
1122
+ readonly disableFatalDefects?: boolean | undefined
1119
1123
  } | undefined
1120
1124
  ) => Effect.Effect<
1121
1125
  Effect.Effect<HttpServerResponse.HttpServerResponse, never, Scope.Scope | HttpServerRequest.HttpServerRequest>,
@@ -1131,6 +1135,7 @@ export const toHttpEffectWebsocket: <Rpcs extends Rpc.Any>(
1131
1135
  readonly disableTracing?: boolean | undefined
1132
1136
  readonly spanPrefix?: string | undefined
1133
1137
  readonly spanAttributes?: Record<string, unknown> | undefined
1138
+ readonly disableFatalDefects?: boolean | undefined
1134
1139
  }
1135
1140
  ) {
1136
1141
  const { httpEffect, protocol } = yield* makeProtocolWithHttpEffectWebsocket
@@ -104,14 +104,14 @@ export const ordered = <Req extends Schema.Top, Res extends Schema.Top, _, E, R>
104
104
  >,
105
105
  SqlClient.TransactionConnection["Service"] | undefined
106
106
  >({
107
- key: (entry) => entry.services.mapUnsafe.get(SqlClient.TransactionConnection.key),
107
+ key: transactionKey,
108
108
  resolver: Effect.fnUntraced(function*(entries) {
109
109
  const inputs = yield* partitionRequests(entries, options.Request)
110
110
  const results = yield* options.execute(inputs as any).pipe(
111
111
  Effect.provideServices(entries[0].services)
112
112
  )
113
113
  if (results.length !== inputs.length) {
114
- return yield* Effect.fail(new ResultLengthMismatch({ expected: inputs.length, actual: results.length }))
114
+ return yield* new ResultLengthMismatch({ expected: inputs.length, actual: results.length })
115
115
  }
116
116
  const decodedResults = yield* decodeArray(results).pipe(
117
117
  Effect.provideServices(entries[0].services)
@@ -160,7 +160,7 @@ export const grouped = <Req extends Schema.Top, Res extends Schema.Top, K, Row,
160
160
  >,
161
161
  SqlClient.TransactionConnection["Service"] | undefined
162
162
  >({
163
- key: (entry) => entry.services.mapUnsafe.get(SqlClient.TransactionConnection.key),
163
+ key: transactionKey,
164
164
  resolver: Effect.fnUntraced(function*(entries) {
165
165
  const inputs = yield* partitionRequests(entries, options.Request)
166
166
  const resultMap = MutableHashMap.empty<K, Arr.NonEmptyArray<Res["Type"]>>()
@@ -226,7 +226,11 @@ export const findById = <Id extends Schema.Top, Res extends Schema.Top, Row, E,
226
226
  >,
227
227
  SqlClient.TransactionConnection["Service"] | undefined
228
228
  >({
229
- key: (entry) => entry.services.mapUnsafe.get(SqlClient.TransactionConnection.key),
229
+ key(entry) {
230
+ const conn = entry.services.mapUnsafe.get(SqlClient.TransactionConnection.key)
231
+ if (!conn) return undefined
232
+ return Equal.byReferenceUnsafe(conn)
233
+ },
230
234
  resolver: Effect.fnUntraced(function*(entries) {
231
235
  const [inputs, idMap] = yield* partitionRequestsById(entries, options.Id)
232
236
  const results = yield* options.execute(inputs as any).pipe(
@@ -279,7 +283,7 @@ const void_ = <Req extends Schema.Top, _, E, R>(
279
283
  >,
280
284
  SqlClient.TransactionConnection["Service"] | undefined
281
285
  >({
282
- key: (entry) => entry.services.mapUnsafe.get(SqlClient.TransactionConnection.key),
286
+ key: transactionKey,
283
287
  resolver: Effect.fnUntraced(function*(entries) {
284
288
  const inputs = yield* partitionRequests(entries, options.Request)
285
289
  yield* options.execute(inputs as any).pipe(
@@ -354,3 +358,9 @@ const partitionRequestsById = function*<In, A, E, R, InE>(
354
358
 
355
359
  return [inputs, byIdMap] as const
356
360
  }
361
+
362
+ function transactionKey<A>(entry: Request.Entry<A>): SqlClient.TransactionConnection["Service"] | undefined {
363
+ const conn = entry.services.mapUnsafe.get(SqlClient.TransactionConnection.key)
364
+ if (!conn) return undefined
365
+ return Equal.byReferenceUnsafe(conn)
366
+ }
@@ -23,7 +23,7 @@ export const findAll = <Req extends Schema.Top, Res extends Schema.Top, E, R>(
23
23
  const encodeRequest = Schema.encodeEffect(options.Request)
24
24
  const decode = Schema.decodeUnknownEffect(Schema.mutable(Schema.Array(options.Result)))
25
25
  return (
26
- request: Req["Encoded"]
26
+ request: Req["Type"]
27
27
  ): Effect.Effect<
28
28
  Array<Res["Type"]>,
29
29
  E | Schema.SchemaError,
@@ -46,7 +46,7 @@ export const findNonEmpty = <Req extends Schema.Top, Res extends Schema.Top, E,
46
46
  ) => {
47
47
  const find = findAll(options)
48
48
  return (
49
- request: Req["Encoded"]
49
+ request: Req["Type"]
50
50
  ): Effect.Effect<
51
51
  Arr.NonEmptyArray<Res["Type"]>,
52
52
  E | Schema.SchemaError | Cause.NoSuchElementError,