effect 4.0.0-beta.4 → 4.0.0-beta.6

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 (310) hide show
  1. package/dist/Cause.d.ts +1 -1
  2. package/dist/Cause.d.ts.map +1 -1
  3. package/dist/Channel.d.ts.map +1 -1
  4. package/dist/Channel.js +6 -4
  5. package/dist/Channel.js.map +1 -1
  6. package/dist/Config.d.ts +1 -1
  7. package/dist/Data.d.ts +3 -2
  8. package/dist/Data.d.ts.map +1 -1
  9. package/dist/Data.js +9 -8
  10. package/dist/Data.js.map +1 -1
  11. package/dist/Effect.d.ts +0 -226
  12. package/dist/Effect.d.ts.map +1 -1
  13. package/dist/Effect.js +0 -118
  14. package/dist/Effect.js.map +1 -1
  15. package/dist/Encoding.d.ts +194 -0
  16. package/dist/Encoding.d.ts.map +1 -0
  17. package/dist/Encoding.js +352 -0
  18. package/dist/Encoding.js.map +1 -0
  19. package/dist/Equal.js.map +1 -1
  20. package/dist/FileSystem.d.ts +1 -1
  21. package/dist/FileSystem.d.ts.map +1 -1
  22. package/dist/FileSystem.js +5 -5
  23. package/dist/FileSystem.js.map +1 -1
  24. package/dist/Filter.d.ts +30 -1
  25. package/dist/Filter.d.ts.map +1 -1
  26. package/dist/Filter.js +15 -0
  27. package/dist/Filter.js.map +1 -1
  28. package/dist/Formatter.js +1 -1
  29. package/dist/Formatter.js.map +1 -1
  30. package/dist/Graph.d.ts.map +1 -1
  31. package/dist/Graph.js +2 -2
  32. package/dist/Graph.js.map +1 -1
  33. package/dist/Latch.d.ts +109 -0
  34. package/dist/Latch.d.ts.map +1 -0
  35. package/dist/Latch.js +72 -0
  36. package/dist/Latch.js.map +1 -0
  37. package/dist/Pipeable.d.ts +17 -0
  38. package/dist/Pipeable.d.ts.map +1 -1
  39. package/dist/Pipeable.js +19 -1
  40. package/dist/Pipeable.js.map +1 -1
  41. package/dist/PlatformError.d.ts +8 -7
  42. package/dist/PlatformError.d.ts.map +1 -1
  43. package/dist/PlatformError.js +2 -2
  44. package/dist/PlatformError.js.map +1 -1
  45. package/dist/Pool.d.ts +5 -3
  46. package/dist/Pool.d.ts.map +1 -1
  47. package/dist/Pool.js +6 -4
  48. package/dist/Pool.js.map +1 -1
  49. package/dist/PubSub.d.ts +3 -2
  50. package/dist/PubSub.d.ts.map +1 -1
  51. package/dist/PubSub.js +3 -2
  52. package/dist/PubSub.js.map +1 -1
  53. package/dist/Request.d.ts +1 -1
  54. package/dist/Request.d.ts.map +1 -1
  55. package/dist/Request.js +2 -1
  56. package/dist/Request.js.map +1 -1
  57. package/dist/RequestResolver.d.ts +0 -20
  58. package/dist/RequestResolver.d.ts.map +1 -1
  59. package/dist/RequestResolver.js +0 -20
  60. package/dist/RequestResolver.js.map +1 -1
  61. package/dist/Schedule.d.ts +2 -2
  62. package/dist/Schedule.d.ts.map +1 -1
  63. package/dist/Schedule.js +30 -16
  64. package/dist/Schedule.js.map +1 -1
  65. package/dist/Schema.d.ts +192 -42
  66. package/dist/Schema.d.ts.map +1 -1
  67. package/dist/Schema.js +385 -71
  68. package/dist/Schema.js.map +1 -1
  69. package/dist/SchemaGetter.d.ts +2 -2
  70. package/dist/SchemaGetter.d.ts.map +1 -1
  71. package/dist/SchemaGetter.js +12 -14
  72. package/dist/SchemaGetter.js.map +1 -1
  73. package/dist/SchemaRepresentation.d.ts +44 -43
  74. package/dist/SchemaRepresentation.d.ts.map +1 -1
  75. package/dist/SchemaRepresentation.js +5 -2
  76. package/dist/SchemaRepresentation.js.map +1 -1
  77. package/dist/SchemaTransformation.d.ts +37 -0
  78. package/dist/SchemaTransformation.d.ts.map +1 -1
  79. package/dist/SchemaTransformation.js +80 -0
  80. package/dist/SchemaTransformation.js.map +1 -1
  81. package/dist/Semaphore.d.ts +211 -0
  82. package/dist/Semaphore.d.ts.map +1 -0
  83. package/dist/{PartitionedSemaphore.js → Semaphore.js} +97 -13
  84. package/dist/Semaphore.js.map +1 -0
  85. package/dist/Stream.d.ts.map +1 -1
  86. package/dist/Stream.js +9 -8
  87. package/dist/Stream.js.map +1 -1
  88. package/dist/Struct.d.ts +16 -0
  89. package/dist/Struct.d.ts.map +1 -1
  90. package/dist/Struct.js +22 -0
  91. package/dist/Struct.js.map +1 -1
  92. package/dist/SubscriptionRef.d.ts +2 -1
  93. package/dist/SubscriptionRef.d.ts.map +1 -1
  94. package/dist/SubscriptionRef.js +2 -1
  95. package/dist/SubscriptionRef.js.map +1 -1
  96. package/dist/SynchronizedRef.d.ts +2 -1
  97. package/dist/SynchronizedRef.d.ts.map +1 -1
  98. package/dist/SynchronizedRef.js +2 -1
  99. package/dist/SynchronizedRef.js.map +1 -1
  100. package/dist/Types.d.ts +14 -6
  101. package/dist/Types.d.ts.map +1 -1
  102. package/dist/index.d.ts +14 -5
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js +14 -5
  105. package/dist/index.js.map +1 -1
  106. package/dist/internal/core.js +11 -3
  107. package/dist/internal/core.js.map +1 -1
  108. package/dist/internal/effect.js.map +1 -1
  109. package/dist/internal/rcRef.js +2 -1
  110. package/dist/internal/rcRef.js.map +1 -1
  111. package/dist/testing/TestClock.d.ts +3 -2
  112. package/dist/testing/TestClock.d.ts.map +1 -1
  113. package/dist/testing/TestClock.js +5 -3
  114. package/dist/testing/TestClock.js.map +1 -1
  115. package/dist/unstable/ai/AiError.d.ts +39 -39
  116. package/dist/unstable/ai/Chat.d.ts.map +1 -1
  117. package/dist/unstable/ai/Chat.js +2 -1
  118. package/dist/unstable/ai/Chat.js.map +1 -1
  119. package/dist/unstable/ai/McpSchema.d.ts +51 -51
  120. package/dist/unstable/ai/Prompt.d.ts +20 -20
  121. package/dist/unstable/ai/Response.d.ts +25 -25
  122. package/dist/unstable/cli/CliError.d.ts +5 -5
  123. package/dist/unstable/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
  124. package/dist/unstable/cluster/ClusterWorkflowEngine.js +2 -1
  125. package/dist/unstable/cluster/ClusterWorkflowEngine.js.map +1 -1
  126. package/dist/unstable/cluster/Entity.d.ts +2 -1
  127. package/dist/unstable/cluster/Entity.d.ts.map +1 -1
  128. package/dist/unstable/cluster/Entity.js.map +1 -1
  129. package/dist/unstable/cluster/Envelope.d.ts +1 -1
  130. package/dist/unstable/cluster/K8sHttpClient.d.ts +1 -1
  131. package/dist/unstable/cluster/Message.d.ts +5 -5
  132. package/dist/unstable/cluster/MessageStorage.d.ts.map +1 -1
  133. package/dist/unstable/cluster/MessageStorage.js +2 -1
  134. package/dist/unstable/cluster/MessageStorage.js.map +1 -1
  135. package/dist/unstable/cluster/Reply.d.ts +3 -3
  136. package/dist/unstable/cluster/Runner.d.ts +1 -1
  137. package/dist/unstable/cluster/Runners.d.ts.map +1 -1
  138. package/dist/unstable/cluster/Runners.js +4 -3
  139. package/dist/unstable/cluster/Runners.js.map +1 -1
  140. package/dist/unstable/cluster/Sharding.d.ts.map +1 -1
  141. package/dist/unstable/cluster/Sharding.js +7 -5
  142. package/dist/unstable/cluster/Sharding.js.map +1 -1
  143. package/dist/unstable/cluster/internal/entityManager.js +4 -3
  144. package/dist/unstable/cluster/internal/entityManager.js.map +1 -1
  145. package/dist/unstable/cluster/internal/entityReaper.js +2 -1
  146. package/dist/unstable/cluster/internal/entityReaper.js.map +1 -1
  147. package/dist/unstable/cluster/internal/resourceRef.js +2 -1
  148. package/dist/unstable/cluster/internal/resourceRef.js.map +1 -1
  149. package/dist/unstable/devtools/DevToolsSchema.d.ts +36 -36
  150. package/dist/unstable/encoding/Sse.d.ts +1 -1
  151. package/dist/unstable/eventlog/EventJournal.d.ts +1 -1
  152. package/dist/unstable/eventlog/EventLog.d.ts.map +1 -1
  153. package/dist/unstable/eventlog/EventLog.js +2 -1
  154. package/dist/unstable/eventlog/EventLog.js.map +1 -1
  155. package/dist/unstable/eventlog/EventLogRemote.d.ts +5 -5
  156. package/dist/unstable/http/Cookies.d.ts +1 -1
  157. package/dist/unstable/http/HttpEffect.d.ts.map +1 -1
  158. package/dist/unstable/http/HttpEffect.js +18 -26
  159. package/dist/unstable/http/HttpEffect.js.map +1 -1
  160. package/dist/unstable/http/Multipart.d.ts +2 -2
  161. package/dist/unstable/http/UrlParams.d.ts +1 -1
  162. package/dist/unstable/httpapi/HttpApiBuilder.js +2 -2
  163. package/dist/unstable/httpapi/HttpApiBuilder.js.map +1 -1
  164. package/dist/unstable/httpapi/HttpApiScalar.d.ts +6 -0
  165. package/dist/unstable/httpapi/HttpApiScalar.d.ts.map +1 -1
  166. package/dist/unstable/httpapi/HttpApiScalar.js.map +1 -1
  167. package/dist/unstable/persistence/KeyValueStore.js +6 -6
  168. package/dist/unstable/persistence/KeyValueStore.js.map +1 -1
  169. package/dist/unstable/persistence/PersistedCache.d.ts +6 -5
  170. package/dist/unstable/persistence/PersistedCache.d.ts.map +1 -1
  171. package/dist/unstable/persistence/PersistedCache.js +2 -1
  172. package/dist/unstable/persistence/PersistedCache.js.map +1 -1
  173. package/dist/unstable/persistence/PersistedQueue.d.ts.map +1 -1
  174. package/dist/unstable/persistence/PersistedQueue.js +6 -5
  175. package/dist/unstable/persistence/PersistedQueue.js.map +1 -1
  176. package/dist/unstable/process/ChildProcessSpawner.d.ts +6 -0
  177. package/dist/unstable/process/ChildProcessSpawner.d.ts.map +1 -1
  178. package/dist/unstable/process/ChildProcessSpawner.js.map +1 -1
  179. package/dist/unstable/reactivity/Atom.d.ts.map +1 -1
  180. package/dist/unstable/reactivity/Atom.js +12 -9
  181. package/dist/unstable/reactivity/Atom.js.map +1 -1
  182. package/dist/unstable/reactivity/Hydration.d.ts +39 -0
  183. package/dist/unstable/reactivity/Hydration.d.ts.map +1 -0
  184. package/dist/unstable/reactivity/Hydration.js +76 -0
  185. package/dist/unstable/reactivity/Hydration.js.map +1 -0
  186. package/dist/unstable/reactivity/index.d.ts +4 -0
  187. package/dist/unstable/reactivity/index.d.ts.map +1 -1
  188. package/dist/unstable/reactivity/index.js +4 -0
  189. package/dist/unstable/reactivity/index.js.map +1 -1
  190. package/dist/unstable/rpc/RpcClient.d.ts.map +1 -1
  191. package/dist/unstable/rpc/RpcClient.js +3 -2
  192. package/dist/unstable/rpc/RpcClient.js.map +1 -1
  193. package/dist/unstable/rpc/RpcServer.d.ts.map +1 -1
  194. package/dist/unstable/rpc/RpcServer.js +5 -3
  195. package/dist/unstable/rpc/RpcServer.js.map +1 -1
  196. package/dist/unstable/rpc/Utils.d.ts.map +1 -1
  197. package/dist/unstable/rpc/Utils.js +2 -1
  198. package/dist/unstable/rpc/Utils.js.map +1 -1
  199. package/dist/unstable/socket/Socket.d.ts.map +1 -1
  200. package/dist/unstable/socket/Socket.js +3 -2
  201. package/dist/unstable/socket/Socket.js.map +1 -1
  202. package/dist/unstable/sql/Statement.js +0 -1
  203. package/dist/unstable/sql/Statement.js.map +1 -1
  204. package/dist/unstable/workers/Worker.d.ts.map +1 -1
  205. package/dist/unstable/workers/Worker.js +2 -1
  206. package/dist/unstable/workers/Worker.js.map +1 -1
  207. package/dist/unstable/workflow/DurableDeferred.js +2 -2
  208. package/dist/unstable/workflow/DurableDeferred.js.map +1 -1
  209. package/dist/unstable/workflow/Workflow.d.ts +1 -1
  210. package/dist/unstable/workflow/WorkflowEngine.d.ts +2 -1
  211. package/dist/unstable/workflow/WorkflowEngine.d.ts.map +1 -1
  212. package/dist/unstable/workflow/WorkflowEngine.js +2 -1
  213. package/dist/unstable/workflow/WorkflowEngine.js.map +1 -1
  214. package/package.json +1 -2
  215. package/src/Cause.ts +1 -1
  216. package/src/Channel.ts +6 -4
  217. package/src/Data.ts +10 -9
  218. package/src/Effect.ts +0 -246
  219. package/src/Encoding.ts +879 -0
  220. package/src/Equal.ts +2 -2
  221. package/src/FileSystem.ts +7 -8
  222. package/src/Filter.ts +48 -1
  223. package/src/Formatter.ts +1 -1
  224. package/src/Graph.ts +8 -5
  225. package/src/Latch.ts +112 -0
  226. package/src/Pipeable.ts +32 -1
  227. package/src/PlatformError.ts +5 -5
  228. package/src/Pool.ts +9 -7
  229. package/src/PubSub.ts +10 -9
  230. package/src/Request.ts +3 -2
  231. package/src/RequestResolver.ts +0 -20
  232. package/src/Schedule.ts +217 -115
  233. package/src/Schema.ts +567 -105
  234. package/src/SchemaGetter.ts +12 -14
  235. package/src/SchemaRepresentation.ts +5 -2
  236. package/src/SchemaTransformation.ts +104 -0
  237. package/src/Semaphore.ts +356 -0
  238. package/src/Stream.ts +9 -8
  239. package/src/Struct.ts +26 -0
  240. package/src/SubscriptionRef.ts +3 -2
  241. package/src/SynchronizedRef.ts +3 -2
  242. package/src/Types.ts +12 -2
  243. package/src/index.ts +17 -6
  244. package/src/internal/core.ts +10 -2
  245. package/src/internal/effect.ts +3 -2
  246. package/src/internal/rcRef.ts +2 -1
  247. package/src/testing/TestClock.ts +8 -6
  248. package/src/unstable/ai/AiError.ts +1 -1
  249. package/src/unstable/ai/Chat.ts +2 -1
  250. package/src/unstable/ai/Prompt.ts +20 -20
  251. package/src/unstable/ai/Response.ts +22 -22
  252. package/src/unstable/cluster/ClusterWorkflowEngine.ts +3 -2
  253. package/src/unstable/cluster/Entity.ts +2 -1
  254. package/src/unstable/cluster/Envelope.ts +1 -1
  255. package/src/unstable/cluster/MessageStorage.ts +2 -1
  256. package/src/unstable/cluster/Runners.ts +6 -5
  257. package/src/unstable/cluster/Sharding.ts +8 -6
  258. package/src/unstable/cluster/internal/entityManager.ts +6 -5
  259. package/src/unstable/cluster/internal/entityReaper.ts +2 -1
  260. package/src/unstable/cluster/internal/resourceRef.ts +2 -1
  261. package/src/unstable/eventlog/EventLog.ts +2 -1
  262. package/src/unstable/http/HttpEffect.ts +17 -25
  263. package/src/unstable/http/Multipart.ts +2 -2
  264. package/src/unstable/http/UrlParams.ts +1 -1
  265. package/src/unstable/httpapi/HttpApiBuilder.ts +2 -2
  266. package/src/unstable/httpapi/HttpApiScalar.ts +6 -0
  267. package/src/unstable/persistence/KeyValueStore.ts +6 -6
  268. package/src/unstable/persistence/PersistedCache.ts +20 -9
  269. package/src/unstable/persistence/PersistedQueue.ts +7 -6
  270. package/src/unstable/process/ChildProcessSpawner.ts +6 -0
  271. package/src/unstable/reactivity/Atom.ts +7 -5
  272. package/src/unstable/reactivity/Hydration.ts +112 -0
  273. package/src/unstable/reactivity/index.ts +5 -0
  274. package/src/unstable/rpc/RpcClient.ts +4 -3
  275. package/src/unstable/rpc/RpcServer.ts +6 -4
  276. package/src/unstable/rpc/Utils.ts +2 -1
  277. package/src/unstable/socket/Socket.ts +3 -2
  278. package/src/unstable/sql/Statement.ts +0 -1
  279. package/src/unstable/workers/Worker.ts +2 -1
  280. package/src/unstable/workflow/DurableDeferred.ts +2 -2
  281. package/src/unstable/workflow/WorkflowEngine.ts +3 -2
  282. package/dist/PartitionedSemaphore.d.ts +0 -52
  283. package/dist/PartitionedSemaphore.d.ts.map +0 -1
  284. package/dist/PartitionedSemaphore.js.map +0 -1
  285. package/dist/encoding/Base64.d.ts +0 -67
  286. package/dist/encoding/Base64.d.ts.map +0 -1
  287. package/dist/encoding/Base64.js +0 -146
  288. package/dist/encoding/Base64.js.map +0 -1
  289. package/dist/encoding/Base64Url.d.ts +0 -60
  290. package/dist/encoding/Base64Url.d.ts.map +0 -1
  291. package/dist/encoding/Base64Url.js +0 -89
  292. package/dist/encoding/Base64Url.js.map +0 -1
  293. package/dist/encoding/EncodingError.d.ts +0 -31
  294. package/dist/encoding/EncodingError.d.ts.map +0 -1
  295. package/dist/encoding/EncodingError.js +0 -22
  296. package/dist/encoding/EncodingError.js.map +0 -1
  297. package/dist/encoding/Hex.d.ts +0 -61
  298. package/dist/encoding/Hex.d.ts.map +0 -1
  299. package/dist/encoding/Hex.js +0 -115
  300. package/dist/encoding/Hex.js.map +0 -1
  301. package/dist/encoding/index.d.ts +0 -26
  302. package/dist/encoding/index.d.ts.map +0 -1
  303. package/dist/encoding/index.js +0 -27
  304. package/dist/encoding/index.js.map +0 -1
  305. package/src/PartitionedSemaphore.ts +0 -182
  306. package/src/encoding/Base64.ts +0 -366
  307. package/src/encoding/Base64Url.ts +0 -104
  308. package/src/encoding/EncodingError.ts +0 -35
  309. package/src/encoding/Hex.ts +0 -390
  310. package/src/encoding/index.ts +0 -31
@@ -86,11 +86,9 @@
86
86
  */
87
87
  import * as DateTime from "./DateTime.ts"
88
88
  import * as Effect from "./Effect.ts"
89
- import * as Base64 from "./encoding/Base64.ts"
90
- import * as Base64Url from "./encoding/Base64Url.ts"
91
- import * as Hex from "./encoding/Hex.ts"
89
+ import * as Encoding from "./Encoding.ts"
92
90
  import * as Option from "./Option.ts"
93
- import { Class } from "./Pipeable.ts"
91
+ import * as Pipeable from "./Pipeable.ts"
94
92
  import * as Predicate from "./Predicate.ts"
95
93
  import * as Result from "./Result.ts"
96
94
  import type * as Schema from "./Schema.ts"
@@ -136,7 +134,7 @@ import * as Str from "./String.ts"
136
134
  * @category model
137
135
  * @since 4.0.0
138
136
  */
139
- export class Getter<out T, in E, R = never> extends Class {
137
+ export class Getter<out T, in E, R = never> extends Pipeable.Class {
140
138
  readonly run: (
141
139
  input: Option.Option<E>,
142
140
  options: AST.ParseOptions
@@ -1218,7 +1216,7 @@ export function split<E extends string>(options?: {
1218
1216
  * @since 4.0.0
1219
1217
  */
1220
1218
  export function encodeBase64<E extends Uint8Array | string>(): Getter<string, E> {
1221
- return transform(Base64.encode)
1219
+ return transform(Encoding.encodeBase64)
1222
1220
  }
1223
1221
 
1224
1222
  /**
@@ -1244,7 +1242,7 @@ export function encodeBase64<E extends Uint8Array | string>(): Getter<string, E>
1244
1242
  * @since 4.0.0
1245
1243
  */
1246
1244
  export function encodeBase64Url<E extends Uint8Array | string>(): Getter<string, E> {
1247
- return transform(Base64Url.encode)
1245
+ return transform(Encoding.encodeBase64Url)
1248
1246
  }
1249
1247
 
1250
1248
  /**
@@ -1269,7 +1267,7 @@ export function encodeBase64Url<E extends Uint8Array | string>(): Getter<string,
1269
1267
  * @since 4.0.0
1270
1268
  */
1271
1269
  export function encodeHex<E extends Uint8Array | string>(): Getter<string, E> {
1272
- return transform(Hex.encode)
1270
+ return transform(Encoding.encodeHex)
1273
1271
  }
1274
1272
 
1275
1273
  /**
@@ -1297,7 +1295,7 @@ export function encodeHex<E extends Uint8Array | string>(): Getter<string, E> {
1297
1295
  export function decodeBase64<E extends string>(): Getter<Uint8Array, E> {
1298
1296
  return transformOrFail((input) =>
1299
1297
  Result.mapError(
1300
- Base64.decode(input),
1298
+ Encoding.decodeBase64(input),
1301
1299
  (e) => new Issue.InvalidValue(Option.some(input), { message: e.message })
1302
1300
  ).asEffect()
1303
1301
  )
@@ -1327,7 +1325,7 @@ export function decodeBase64<E extends string>(): Getter<Uint8Array, E> {
1327
1325
  */
1328
1326
  export function decodeBase64String<E extends string>(): Getter<string, E> {
1329
1327
  return transformOrFail((input) =>
1330
- Result.match(Base64.decodeString(input), {
1328
+ Result.match(Encoding.decodeBase64String(input), {
1331
1329
  onFailure: (e) => Effect.fail(new Issue.InvalidValue(Option.some(input), { message: e.message })),
1332
1330
  onSuccess: Effect.succeed
1333
1331
  })
@@ -1358,7 +1356,7 @@ export function decodeBase64String<E extends string>(): Getter<string, E> {
1358
1356
  */
1359
1357
  export function decodeBase64Url<E extends string>(): Getter<Uint8Array, E> {
1360
1358
  return transformOrFail((input) =>
1361
- Result.match(Base64Url.decode(input), {
1359
+ Result.match(Encoding.decodeBase64Url(input), {
1362
1360
  onFailure: (e) => Effect.fail(new Issue.InvalidValue(Option.some(input), { message: e.message })),
1363
1361
  onSuccess: Effect.succeed
1364
1362
  })
@@ -1389,7 +1387,7 @@ export function decodeBase64Url<E extends string>(): Getter<Uint8Array, E> {
1389
1387
  */
1390
1388
  export function decodeBase64UrlString<E extends string>(): Getter<string, E> {
1391
1389
  return transformOrFail((input) =>
1392
- Result.match(Base64Url.decodeString(input), {
1390
+ Result.match(Encoding.decodeBase64UrlString(input), {
1393
1391
  onFailure: (e) => Effect.fail(new Issue.InvalidValue(Option.some(input), { message: e.message })),
1394
1392
  onSuccess: Effect.succeed
1395
1393
  })
@@ -1420,7 +1418,7 @@ export function decodeBase64UrlString<E extends string>(): Getter<string, E> {
1420
1418
  */
1421
1419
  export function decodeHex<E extends string>(): Getter<Uint8Array, E> {
1422
1420
  return transformOrFail((input) =>
1423
- Result.match(Hex.decode(input), {
1421
+ Result.match(Encoding.decodeHex(input), {
1424
1422
  onFailure: (e) => Effect.fail(new Issue.InvalidValue(Option.some(input), { message: e.message })),
1425
1423
  onSuccess: Effect.succeed
1426
1424
  })
@@ -1451,7 +1449,7 @@ export function decodeHex<E extends string>(): Getter<Uint8Array, E> {
1451
1449
  */
1452
1450
  export function decodeHexString<E extends string>(): Getter<string, E> {
1453
1451
  return transformOrFail((input) =>
1454
- Result.match(Hex.decodeString(input), {
1452
+ Result.match(Encoding.decodeHexString(input), {
1455
1453
  onFailure: (e) => Effect.fail(new Issue.InvalidValue(Option.some(input), { message: e.message })),
1456
1454
  onSuccess: Effect.succeed
1457
1455
  })
@@ -1698,7 +1698,8 @@ export type Reviver<T> = (declaration: Declaration, recur: (representation: Repr
1698
1698
 
1699
1699
  /**
1700
1700
  * Default {@link Reviver} for {@link toSchema} that handles built-in Effect
1701
- * types (Option, Result, Redacted, Cause, Exit, ReadonlyMap, ReadonlySet,
1701
+ * types (Option, Result, Redacted, Cause, Exit, ReadonlyMap, HashMap,
1702
+ * ReadonlySet,
1702
1703
  * Date, Duration, URL, RegExp, etc.).
1703
1704
  *
1704
1705
  * - Pass as `options.reviver` to {@link toSchema} to reconstruct schemas that
@@ -1723,7 +1724,7 @@ export const toSchemaDefaultReviver: Reviver<Schema.Top> = (s, recur) => {
1723
1724
  case "effect/Redacted":
1724
1725
  return Schema.Redacted(typeParameters[0])
1725
1726
  case "effect/Cause/Failure":
1726
- return Schema.CauseFailure(typeParameters[0], typeParameters[1])
1727
+ return Schema.CauseReason(typeParameters[0], typeParameters[1])
1727
1728
  case "effect/Cause":
1728
1729
  return Schema.Cause(typeParameters[0], typeParameters[1])
1729
1730
  case "Error":
@@ -1732,6 +1733,8 @@ export const toSchemaDefaultReviver: Reviver<Schema.Top> = (s, recur) => {
1732
1733
  return Schema.Exit(typeParameters[0], typeParameters[1], typeParameters[2])
1733
1734
  case "ReadonlyMap":
1734
1735
  return Schema.ReadonlyMap(typeParameters[0], typeParameters[1])
1736
+ case "effect/HashMap":
1737
+ return Schema.HashMap(typeParameters[0], typeParameters[1])
1735
1738
  case "ReadonlySet":
1736
1739
  return Schema.ReadonlySet(typeParameters[0])
1737
1740
  case "RegExp":
@@ -82,6 +82,8 @@
82
82
  * @since 4.0.0
83
83
  */
84
84
 
85
+ import * as BigDecimal from "./BigDecimal.ts"
86
+ import * as DateTime from "./DateTime.ts"
85
87
  import * as Duration from "./Duration.ts"
86
88
  import * as Effect from "./Effect.ts"
87
89
  import * as Option from "./Option.ts"
@@ -1136,6 +1138,33 @@ export const urlFromString: Transformation<URL, string> = transformOrFail<URL, s
1136
1138
  encode: (url) => Effect.succeed(url.href)
1137
1139
  })
1138
1140
 
1141
+ /**
1142
+ * Decodes a `string` into a `BigDecimal` and encodes a `BigDecimal` back to
1143
+ * its string representation.
1144
+ *
1145
+ * When to use this:
1146
+ * - Parsing decimal number strings from APIs or user input.
1147
+ *
1148
+ * Behavior:
1149
+ * - Decode: calls `BigDecimal.fromString(s)`. Fails with `InvalidValue` if the
1150
+ * string is not a valid BigDecimal representation.
1151
+ * - Encode: returns `BigDecimal.format(bd)`.
1152
+ *
1153
+ * @since 4.0.0
1154
+ */
1155
+ export const bigDecimalFromString: Transformation<BigDecimal.BigDecimal, string> = transformOrFail<
1156
+ BigDecimal.BigDecimal,
1157
+ string
1158
+ >({
1159
+ decode: (s) => {
1160
+ const result = BigDecimal.fromString(s)
1161
+ return result === undefined
1162
+ ? Effect.fail(new Issue.InvalidValue(Option.some(s), { message: `Invalid BigDecimal string: ${s}` }))
1163
+ : Effect.succeed(result)
1164
+ },
1165
+ encode: (bd) => Effect.succeed(BigDecimal.format(bd))
1166
+ })
1167
+
1139
1168
  /**
1140
1169
  * Decodes a Base64-encoded `string` into a `Uint8Array` and encodes a
1141
1170
  * `Uint8Array` back to a Base64 string.
@@ -1264,3 +1293,78 @@ export const fromURLSearchParams = new Transformation<unknown, URLSearchParams>(
1264
1293
  Getter.decodeURLSearchParams(),
1265
1294
  Getter.encodeURLSearchParams()
1266
1295
  )
1296
+
1297
+ /**
1298
+ * @since 4.0.0
1299
+ */
1300
+ export const timeZoneOffsetFromNumber: Transformation<DateTime.TimeZone.Offset, number> = transform<
1301
+ DateTime.TimeZone.Offset,
1302
+ number
1303
+ >({
1304
+ decode: (n) => DateTime.zoneMakeOffset(n),
1305
+ encode: (tz) => tz.offset
1306
+ })
1307
+
1308
+ /**
1309
+ * @since 4.0.0
1310
+ */
1311
+ export const timeZoneNamedFromString: Transformation<DateTime.TimeZone.Named, string> = transformOrFail<
1312
+ DateTime.TimeZone.Named,
1313
+ string
1314
+ >({
1315
+ decode: (s) => {
1316
+ const result = DateTime.zoneMakeNamed(s)
1317
+ return result === undefined
1318
+ ? Effect.fail(new Issue.InvalidValue(Option.some(s), { message: `Invalid IANA time zone: ${s}` }))
1319
+ : Effect.succeed(result)
1320
+ },
1321
+ encode: (tz) => Effect.succeed(tz.id)
1322
+ })
1323
+
1324
+ /**
1325
+ * @since 4.0.0
1326
+ */
1327
+ export const timeZoneFromString: Transformation<DateTime.TimeZone, string> = transformOrFail<
1328
+ DateTime.TimeZone,
1329
+ string
1330
+ >({
1331
+ decode: (s) => {
1332
+ const result = DateTime.zoneFromString(s)
1333
+ return result === undefined
1334
+ ? Effect.fail(new Issue.InvalidValue(Option.some(s), { message: `Invalid time zone: ${s}` }))
1335
+ : Effect.succeed(result)
1336
+ },
1337
+ encode: (tz) => Effect.succeed(DateTime.zoneToString(tz))
1338
+ })
1339
+
1340
+ /**
1341
+ * @since 4.0.0
1342
+ */
1343
+ export const dateTimeUtcFromString: Transformation<DateTime.Utc, string> = transformOrFail<
1344
+ DateTime.Utc,
1345
+ string
1346
+ >({
1347
+ decode: (s) => {
1348
+ const result = DateTime.make(s)
1349
+ return result === undefined
1350
+ ? Effect.fail(new Issue.InvalidValue(Option.some(s), { message: "Invalid DateTime input" }))
1351
+ : Effect.succeed(DateTime.toUtc(result))
1352
+ },
1353
+ encode: (utc) => Effect.succeed(DateTime.formatIso(utc))
1354
+ })
1355
+
1356
+ /**
1357
+ * @since 4.0.0
1358
+ */
1359
+ export const dateTimeZonedFromString: Transformation<DateTime.Zoned, string> = transformOrFail<
1360
+ DateTime.Zoned,
1361
+ string
1362
+ >({
1363
+ decode: (s) => {
1364
+ const result = DateTime.makeZonedFromString(s)
1365
+ return result === undefined
1366
+ ? Effect.fail(new Issue.InvalidValue(Option.some(s), { message: `Invalid zoned DateTime string: ${s}` }))
1367
+ : Effect.succeed(result)
1368
+ },
1369
+ encode: (zoned) => Effect.succeed(DateTime.formatIsoZoned(zoned))
1370
+ })
@@ -0,0 +1,356 @@
1
+ /**
2
+ * @since 2.0.0
3
+ */
4
+ import * as Effect from "./Effect.ts"
5
+ import * as internal from "./internal/effect.ts"
6
+ import * as MutableHashMap from "./MutableHashMap.ts"
7
+ import * as Option from "./Option.ts"
8
+
9
+ /**
10
+ * @category models
11
+ * @since 2.0.0
12
+ * @example
13
+ * ```ts
14
+ * import { Effect, Semaphore } from "effect"
15
+ *
16
+ * // Create and use a semaphore for controlling concurrent access
17
+ * const program = Effect.gen(function*() {
18
+ * const semaphore = yield* Semaphore.make(2)
19
+ *
20
+ * return yield* semaphore.withPermits(1)(
21
+ * Effect.succeed("Resource accessed")
22
+ * )
23
+ * })
24
+ * ```
25
+ */
26
+ export interface Semaphore {
27
+ /**
28
+ * Adjusts the number of permits available in the semaphore.
29
+ */
30
+ resize(permits: number): Effect.Effect<void>
31
+
32
+ /**
33
+ * Runs an effect with the given number of permits and releases the permits
34
+ * when the effect completes.
35
+ *
36
+ * **Details**
37
+ *
38
+ * This function acquires the specified number of permits before executing
39
+ * the provided effect. Once the effect finishes, the permits are released.
40
+ * If insufficient permits are available, the function will wait until they
41
+ * are released by other tasks.
42
+ */
43
+ withPermits(permits: number): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
44
+
45
+ /**
46
+ * Runs an effect with the given number of permits and releases the permits
47
+ * when the effect completes.
48
+ *
49
+ * **Details**
50
+ *
51
+ * This function acquires the specified number of permits before executing
52
+ * the provided effect. Once the effect finishes, the permits are released.
53
+ * If insufficient permits are available, the function will wait until they
54
+ * are released by other tasks.
55
+ */
56
+ withPermit<A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R>
57
+
58
+ /**
59
+ * Runs an effect only if the specified number of permits are immediately
60
+ * available.
61
+ *
62
+ * **Details**
63
+ *
64
+ * This function attempts to acquire the specified number of permits. If they
65
+ * are available, it runs the effect and releases the permits after the effect
66
+ * completes. If permits are not available, the effect does not execute, and
67
+ * the result is `Option.none`.
68
+ */
69
+ withPermitsIfAvailable(
70
+ permits: number
71
+ ): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Option.Option<A>, E, R>
72
+
73
+ /**
74
+ * Acquires the specified number of permits and returns the resulting
75
+ * available permits, suspending the task if they are not yet available.
76
+ * Concurrent pending `take` calls are processed in a first-in, first-out manner.
77
+ */
78
+ take(permits: number): Effect.Effect<number>
79
+
80
+ /**
81
+ * Releases the specified number of permits and returns the resulting
82
+ * available permits.
83
+ */
84
+ release(permits: number): Effect.Effect<number>
85
+
86
+ /**
87
+ * Releases all permits held by this semaphore and returns the resulting available permits.
88
+ */
89
+ releaseAll: Effect.Effect<number>
90
+ }
91
+
92
+ /**
93
+ * Unsafely creates a new Semaphore.
94
+ *
95
+ * **Previously Known As**
96
+ *
97
+ * This API replaces the following from Effect 3.x:
98
+ *
99
+ * - `Effect.makeSemaphoreUnsafe`
100
+ *
101
+ * @example
102
+ * ```ts
103
+ * import { Effect, Semaphore } from "effect"
104
+ *
105
+ * const semaphore = Semaphore.makeUnsafe(3)
106
+ *
107
+ * const task = (id: number) =>
108
+ * semaphore.withPermits(1)(
109
+ * Effect.gen(function*() {
110
+ * yield* Effect.log(`Task ${id} started`)
111
+ * yield* Effect.sleep("1 second")
112
+ * yield* Effect.log(`Task ${id} completed`)
113
+ * })
114
+ * )
115
+ *
116
+ * // Only 3 tasks can run concurrently
117
+ * const program = Effect.all([
118
+ * task(1),
119
+ * task(2),
120
+ * task(3),
121
+ * task(4),
122
+ * task(5)
123
+ * ], { concurrency: "unbounded" })
124
+ * ```
125
+ *
126
+ * @since 2.0.0
127
+ * @category constructors
128
+ */
129
+ export const makeUnsafe: (permits: number) => Semaphore = internal.makeSemaphoreUnsafe
130
+
131
+ /**
132
+ * Creates a new Semaphore.
133
+ *
134
+ * **Previously Known As**
135
+ *
136
+ * This API replaces the following from Effect 3.x:
137
+ *
138
+ * - `Effect.makeSemaphore`
139
+ *
140
+ * @example
141
+ * ```ts
142
+ * import { Effect, Semaphore } from "effect"
143
+ *
144
+ * const program = Effect.gen(function*() {
145
+ * const semaphore = yield* Semaphore.make(2)
146
+ *
147
+ * const task = (id: number) =>
148
+ * semaphore.withPermits(1)(
149
+ * Effect.gen(function*() {
150
+ * yield* Effect.log(`Task ${id} acquired permit`)
151
+ * yield* Effect.sleep("1 second")
152
+ * yield* Effect.log(`Task ${id} releasing permit`)
153
+ * })
154
+ * )
155
+ *
156
+ * // Run 4 tasks, but only 2 can run concurrently
157
+ * yield* Effect.all([task(1), task(2), task(3), task(4)])
158
+ * })
159
+ * ```
160
+ *
161
+ * @since 2.0.0
162
+ * @category constructors
163
+ */
164
+ export const make: (permits: number) => Effect.Effect<Semaphore> = internal.makeSemaphore
165
+
166
+ // -----------------------------------------------------------------------------
167
+ // Partitioned
168
+ // -----------------------------------------------------------------------------
169
+
170
+ /**
171
+ * @since 3.19.4
172
+ * @category models
173
+ */
174
+ export const PartitionedTypeId: PartitionedTypeId = "~effect/PartitionedSemaphore"
175
+
176
+ /**
177
+ * @since 3.19.4
178
+ * @category models
179
+ */
180
+ export type PartitionedTypeId = "~effect/PartitionedSemaphore"
181
+
182
+ /**
183
+ * A `Partitioned` semaphore controls access to a shared permit pool while
184
+ * tracking waiters by partition key.
185
+ *
186
+ * Waiting permits are distributed across partitions in round-robin order.
187
+ *
188
+ * **Previously Known As**
189
+ *
190
+ * This API replaces the following from Effect 3.x:
191
+ *
192
+ * - `PartitionedSemaphore.PartitionedSemaphore`
193
+ *
194
+ * @since 3.19.4
195
+ * @category models
196
+ */
197
+ export interface Partitioned<in K> {
198
+ readonly [PartitionedTypeId]: PartitionedTypeId
199
+ readonly withPermits: (
200
+ key: K,
201
+ permits: number
202
+ ) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
203
+ }
204
+
205
+ /**
206
+ * Creates a `Partitioned` semaphore unsafely.
207
+ *
208
+ * **Previously Known As**
209
+ *
210
+ * This API replaces the following from Effect 3.x:
211
+ *
212
+ * - `PartitionedSemaphore.makeUnsafe`
213
+ *
214
+ * @since 3.19.4
215
+ * @category constructors
216
+ */
217
+ export const makePartitionedUnsafe = <K = unknown>(options: {
218
+ readonly permits: number
219
+ }): Partitioned<K> => {
220
+ const maxPermits = Math.max(0, options.permits)
221
+
222
+ if (!Number.isFinite(maxPermits)) {
223
+ return {
224
+ [PartitionedTypeId]: PartitionedTypeId,
225
+ withPermits: () => (effect) => effect
226
+ }
227
+ }
228
+
229
+ let totalPermits = maxPermits
230
+ let waitingPermits = 0
231
+
232
+ type Waiter = {
233
+ permits: number
234
+ readonly resume: () => void
235
+ }
236
+ const partitions = MutableHashMap.empty<K, Set<Waiter>>()
237
+
238
+ const take = (key: K, permits: number) =>
239
+ Effect.callback<void>((resume) => {
240
+ if (maxPermits < permits) {
241
+ resume(Effect.never)
242
+ return
243
+ }
244
+
245
+ if (totalPermits >= permits) {
246
+ totalPermits -= permits
247
+ resume(Effect.void)
248
+ return
249
+ }
250
+
251
+ const needed = permits - totalPermits
252
+ const taken = permits - needed
253
+ if (totalPermits > 0) {
254
+ totalPermits = 0
255
+ }
256
+ waitingPermits += needed
257
+
258
+ const waiters = Option.getOrElse(
259
+ MutableHashMap.get(partitions, key),
260
+ () => {
261
+ const set = new Set<Waiter>()
262
+ MutableHashMap.set(partitions, key, set)
263
+ return set
264
+ }
265
+ )
266
+
267
+ const entry: Waiter = {
268
+ permits: needed,
269
+ resume: () => {
270
+ cleanup()
271
+ resume(Effect.void)
272
+ }
273
+ }
274
+
275
+ const cleanup = () => {
276
+ waiters.delete(entry)
277
+ if (waiters.size === 0) {
278
+ MutableHashMap.remove(partitions, key)
279
+ }
280
+ }
281
+
282
+ waiters.add(entry)
283
+
284
+ return Effect.sync(() => {
285
+ cleanup()
286
+ waitingPermits -= entry.permits
287
+ if (taken > 0) {
288
+ releaseUnsafe(taken)
289
+ }
290
+ })
291
+ })
292
+
293
+ let iterator = partitions[Symbol.iterator]()
294
+
295
+ const releaseUnsafe = (permits: number): void => {
296
+ while (permits > 0) {
297
+ if (waitingPermits === 0) {
298
+ totalPermits += permits
299
+ return
300
+ }
301
+
302
+ let state = iterator.next()
303
+ if (state.done) {
304
+ iterator = partitions[Symbol.iterator]()
305
+ state = iterator.next()
306
+ if (state.done) {
307
+ return
308
+ }
309
+ }
310
+
311
+ const waiter = state.value[1].values().next().value
312
+ if (waiter === undefined) {
313
+ continue
314
+ }
315
+
316
+ waiter.permits -= 1
317
+ waitingPermits -= 1
318
+
319
+ if (waiter.permits === 0) {
320
+ waiter.resume()
321
+ }
322
+
323
+ permits -= 1
324
+ }
325
+ }
326
+
327
+ return {
328
+ [PartitionedTypeId]: PartitionedTypeId,
329
+ withPermits: (key, permits) => {
330
+ const takePermits = take(key, permits)
331
+ return (effect) =>
332
+ Effect.uninterruptibleMask((restore) =>
333
+ Effect.flatMap(
334
+ restore(takePermits),
335
+ () => Effect.ensuring(restore(effect), Effect.sync(() => releaseUnsafe(permits)))
336
+ )
337
+ )
338
+ }
339
+ }
340
+ }
341
+
342
+ /**
343
+ * Creates a `Partitioned` semaphore.
344
+ *
345
+ * **Previously Known As**
346
+ *
347
+ * This API replaces the following from Effect 3.x:
348
+ *
349
+ * - `PartitionedSemaphore.make`
350
+ *
351
+ * @since 3.19.4
352
+ * @category constructors
353
+ */
354
+ export const makePartitioned = <K = unknown>(options: {
355
+ readonly permits: number
356
+ }): Effect.Effect<Partitioned<K>> => Effect.sync(() => makePartitionedUnsafe<K>(options))
package/src/Stream.ts CHANGED
@@ -20,6 +20,7 @@ import * as internalExecutionPlan from "./internal/executionPlan.ts"
20
20
  import * as internal from "./internal/stream.ts"
21
21
  import { addSpanStackTrace } from "./internal/tracer.ts"
22
22
  import * as Iterable from "./Iterable.ts"
23
+ import * as Latch from "./Latch.ts"
23
24
  import type * as Layer from "./Layer.ts"
24
25
  import type { LogLevel } from "./LogLevel.ts"
25
26
  import * as MutableHashMap from "./MutableHashMap.ts"
@@ -2648,8 +2649,8 @@ export const tapSink: {
2648
2649
  transformPullBracket(
2649
2650
  self,
2650
2651
  Effect.fnUntraced(function*(pull, _, scope) {
2651
- const upstreamLatch = Effect.makeLatchUnsafe()
2652
- const sinkLatch = Effect.makeLatchUnsafe()
2652
+ const upstreamLatch = Latch.makeUnsafe()
2653
+ const sinkLatch = Latch.makeUnsafe()
2653
2654
  let chunk: Arr.NonEmptyReadonlyArray<A> | undefined = undefined
2654
2655
  let causeSink: Cause.Cause<E2> | undefined = undefined
2655
2656
  let sinkDone = false
@@ -5341,7 +5342,7 @@ export const zipLatestAll = <T extends ReadonlyArray<Stream<any, any, any>>>(
5341
5342
  fromChannel(Channel.suspend(() => {
5342
5343
  const latest: Array<any> = []
5343
5344
  const emitted = new Set<number>()
5344
- const readyLatch = Effect.makeLatchUnsafe()
5345
+ const readyLatch = Latch.makeUnsafe()
5345
5346
  return Channel.mergeAll(
5346
5347
  Channel.fromArray(
5347
5348
  streams.map((s, i) =>
@@ -12210,9 +12211,9 @@ export const debounce: {
12210
12211
  let lastArr: Arr.NonEmptyReadonlyArray<A> | undefined
12211
12212
  let cause: Cause.Cause<Cause.Done | E> | undefined
12212
12213
  let emitAtMs = Infinity
12213
- const pullLatch = Effect.makeLatchUnsafe()
12214
- const emitLatch = Effect.makeLatchUnsafe()
12215
- const endLatch = Effect.makeLatchUnsafe()
12214
+ const pullLatch = Latch.makeUnsafe()
12215
+ const emitLatch = Latch.makeUnsafe()
12216
+ const endLatch = Latch.makeUnsafe()
12216
12217
 
12217
12218
  yield* pull.pipe(
12218
12219
  pullLatch.whenOpen,
@@ -13537,7 +13538,7 @@ export const aggregateWithin: {
13537
13538
  fromChannel(Channel.fromTransformBracket(Effect.fnUntraced(function*(_upstream, _, scope) {
13538
13539
  const pull = yield* Channel.toPullScoped(self.channel, _)
13539
13540
 
13540
- const pullLatch = Effect.makeLatchUnsafe(false)
13541
+ const pullLatch = Latch.makeUnsafe(false)
13541
13542
  const scheduleStep = Symbol()
13542
13543
  const buffer = yield* Queue.make</**
13543
13544
  * Aggregates elements with a sink, emitting each result when the sink completes or the schedule triggers.
@@ -17747,7 +17748,7 @@ export const toReadableStreamWith = dual<
17747
17748
  ): ReadableStream<A> => {
17748
17749
  let currentResolve: (() => void) | undefined = undefined
17749
17750
  let fiber: Fiber.Fiber<void, E> | undefined = undefined
17750
- const latch = Effect.makeLatchUnsafe(false)
17751
+ const latch = Latch.makeUnsafe(false)
17751
17752
 
17752
17753
  return new ReadableStream<A>({
17753
17754
  start(controller) {
package/src/Struct.ts CHANGED
@@ -1513,3 +1513,29 @@ export function makeReducer<A>(
1513
1513
  }
1514
1514
  return Reducer.make(combine, initialValue)
1515
1515
  }
1516
+
1517
+ /**
1518
+ * Creates a record with the given keys and value.
1519
+ *
1520
+ * **Example** (Creating a record)
1521
+ *
1522
+ * ```ts
1523
+ * import { Struct } from "effect"
1524
+ *
1525
+ * const record = Struct.Record(["a", "b"], "value")
1526
+ * console.log(record) // { a: "value", b: "value" }
1527
+ * ```
1528
+ *
1529
+ * @category Constructors
1530
+ * @since 4.0.0
1531
+ */
1532
+ export function Record<const Keys extends ReadonlyArray<string | symbol>, Value>(
1533
+ keys: Keys,
1534
+ value: Value
1535
+ ): Record<Keys[number], Value> {
1536
+ const out: any = {}
1537
+ for (const key of keys) {
1538
+ out[key] = value
1539
+ }
1540
+ return out
1541
+ }