effect 4.1.0 → 4.1.2

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 (445) hide show
  1. package/README.md +30 -0
  2. package/THIRD_PARTY_NOTICES.md +62 -0
  3. package/ai-docs/package.json +2 -2
  4. package/dist/BigDecimal.d.ts +139 -7
  5. package/dist/BigDecimal.d.ts.map +1 -1
  6. package/dist/BigDecimal.js +83 -14
  7. package/dist/BigDecimal.js.map +1 -1
  8. package/dist/ByteSize.d.ts.map +1 -1
  9. package/dist/ByteSize.js +27 -14
  10. package/dist/ByteSize.js.map +1 -1
  11. package/dist/Equal.d.ts +2 -2
  12. package/dist/Equal.d.ts.map +1 -1
  13. package/dist/Equal.js +3 -3
  14. package/dist/Equal.js.map +1 -1
  15. package/dist/Hash.d.ts +3 -2
  16. package/dist/Hash.d.ts.map +1 -1
  17. package/dist/Hash.js +5 -4
  18. package/dist/Hash.js.map +1 -1
  19. package/dist/Iterable.d.ts.map +1 -1
  20. package/dist/Iterable.js +38 -32
  21. package/dist/Iterable.js.map +1 -1
  22. package/dist/JsonSchema.d.ts.map +1 -1
  23. package/dist/JsonSchema.js +27 -6
  24. package/dist/JsonSchema.js.map +1 -1
  25. package/dist/MutableRef.d.ts.map +1 -1
  26. package/dist/MutableRef.js +0 -7
  27. package/dist/MutableRef.js.map +1 -1
  28. package/dist/Path.d.ts.map +1 -1
  29. package/dist/Path.js +5 -1
  30. package/dist/Path.js.map +1 -1
  31. package/dist/Pool.d.ts.map +1 -1
  32. package/dist/Pool.js +2 -1
  33. package/dist/Pool.js.map +1 -1
  34. package/dist/Ref.d.ts.map +1 -1
  35. package/dist/Ref.js +0 -8
  36. package/dist/Ref.js.map +1 -1
  37. package/dist/Schedule.d.ts.map +1 -1
  38. package/dist/Schedule.js +8 -3
  39. package/dist/Schedule.js.map +1 -1
  40. package/dist/Schema.d.ts +2 -1
  41. package/dist/Schema.d.ts.map +1 -1
  42. package/dist/Schema.js +2 -1
  43. package/dist/Schema.js.map +1 -1
  44. package/dist/SchemaRepresentation.d.ts +4 -2
  45. package/dist/SchemaRepresentation.d.ts.map +1 -1
  46. package/dist/SchemaRepresentation.js +4 -2
  47. package/dist/SchemaRepresentation.js.map +1 -1
  48. package/dist/SchemaTransformation.d.ts +2 -2
  49. package/dist/SchemaTransformation.js +2 -2
  50. package/dist/Stream.d.ts.map +1 -1
  51. package/dist/Stream.js +6 -5
  52. package/dist/Stream.js.map +1 -1
  53. package/dist/ai/McpClient.d.ts +171 -19
  54. package/dist/ai/McpClient.d.ts.map +1 -1
  55. package/dist/ai/McpClient.js +277 -66
  56. package/dist/ai/McpClient.js.map +1 -1
  57. package/dist/ai/McpSchema.d.ts +108 -0
  58. package/dist/ai/McpSchema.d.ts.map +1 -1
  59. package/dist/ai/McpSchema.js +99 -0
  60. package/dist/ai/McpSchema.js.map +1 -1
  61. package/dist/ai/McpServer.d.ts +120 -6
  62. package/dist/ai/McpServer.d.ts.map +1 -1
  63. package/dist/ai/McpServer.js +258 -49
  64. package/dist/ai/McpServer.js.map +1 -1
  65. package/dist/ai/Prompt.d.ts.map +1 -1
  66. package/dist/ai/Prompt.js +20 -11
  67. package/dist/ai/Prompt.js.map +1 -1
  68. package/dist/ai/Tool.d.ts.map +1 -1
  69. package/dist/ai/Tool.js +5 -7
  70. package/dist/ai/Tool.js.map +1 -1
  71. package/dist/ai/internal/mcpCore.js +72 -3
  72. package/dist/ai/internal/mcpCore.js.map +1 -1
  73. package/dist/ai/internal/mcpProtocol/v2024_11_05.js +3 -1
  74. package/dist/ai/internal/mcpProtocol/v2024_11_05.js.map +1 -1
  75. package/dist/ai/internal/mcpProtocol/v2025_03_26.js +3 -1
  76. package/dist/ai/internal/mcpProtocol/v2025_03_26.js.map +1 -1
  77. package/dist/ai/internal/mcpProtocol/v2025_06_18.js +3 -1
  78. package/dist/ai/internal/mcpProtocol/v2025_06_18.js.map +1 -1
  79. package/dist/ai/internal/mcpProtocol/v2025_11_25.js +3 -1
  80. package/dist/ai/internal/mcpProtocol/v2025_11_25.js.map +1 -1
  81. package/dist/ai/internal/mcpProtocol/v2026_07_28.js +44 -8
  82. package/dist/ai/internal/mcpProtocol/v2026_07_28.js.map +1 -1
  83. package/dist/ai/internal/mcpProtocol.js +12 -0
  84. package/dist/ai/internal/mcpProtocol.js.map +1 -1
  85. package/dist/ai/internal/mcpRuntime.js +3 -3
  86. package/dist/ai/internal/mcpRuntime.js.map +1 -1
  87. package/dist/ai/internal/mcpSkills.d.ts +2 -0
  88. package/dist/ai/internal/mcpSkills.d.ts.map +1 -0
  89. package/dist/ai/internal/mcpSkills.js +428 -0
  90. package/dist/ai/internal/mcpSkills.js.map +1 -0
  91. package/dist/ai/internal/structured-output.js +11 -2
  92. package/dist/ai/internal/structured-output.js.map +1 -1
  93. package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
  94. package/dist/cluster/ClusterWorkflowEngine.js +30 -11
  95. package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
  96. package/dist/cluster/Entity.d.ts +26 -0
  97. package/dist/cluster/Entity.d.ts.map +1 -1
  98. package/dist/cluster/Entity.js.map +1 -1
  99. package/dist/cluster/MessageStorage.d.ts +6 -6
  100. package/dist/cluster/MessageStorage.d.ts.map +1 -1
  101. package/dist/cluster/MessageStorage.js +1 -3
  102. package/dist/cluster/MessageStorage.js.map +1 -1
  103. package/dist/cluster/Reply.d.ts +1 -1
  104. package/dist/cluster/Reply.d.ts.map +1 -1
  105. package/dist/cluster/Reply.js.map +1 -1
  106. package/dist/cluster/Runners.d.ts.map +1 -1
  107. package/dist/cluster/Runners.js +13 -2
  108. package/dist/cluster/Runners.js.map +1 -1
  109. package/dist/cluster/Sharding.d.ts +13 -0
  110. package/dist/cluster/Sharding.d.ts.map +1 -1
  111. package/dist/cluster/Sharding.js +4 -1
  112. package/dist/cluster/Sharding.js.map +1 -1
  113. package/dist/cluster/internal/clusterAbandon.d.ts.map +1 -1
  114. package/dist/cluster/internal/clusterAbandon.js +6 -4
  115. package/dist/cluster/internal/clusterAbandon.js.map +1 -1
  116. package/dist/cluster/internal/entityManager.js +63 -11
  117. package/dist/cluster/internal/entityManager.js.map +1 -1
  118. package/dist/cluster/internal/transactionNotifications.d.ts +5 -0
  119. package/dist/cluster/internal/transactionNotifications.d.ts.map +1 -0
  120. package/dist/cluster/internal/transactionNotifications.js +5 -0
  121. package/dist/cluster/internal/transactionNotifications.js.map +1 -0
  122. package/dist/crypto/Aead.d.ts +2 -1
  123. package/dist/crypto/Aead.d.ts.map +1 -1
  124. package/dist/crypto/Aead.js +2 -2
  125. package/dist/crypto/Aead.js.map +1 -1
  126. package/dist/crypto/Cipher.d.ts +2 -1
  127. package/dist/crypto/Cipher.d.ts.map +1 -1
  128. package/dist/crypto/Cipher.js +2 -2
  129. package/dist/crypto/Cipher.js.map +1 -1
  130. package/dist/crypto/KeyAgreement.d.ts +3 -2
  131. package/dist/crypto/KeyAgreement.d.ts.map +1 -1
  132. package/dist/crypto/KeyAgreement.js +2 -2
  133. package/dist/crypto/KeyAgreement.js.map +1 -1
  134. package/dist/crypto/KeyFormat.d.ts +33 -1
  135. package/dist/crypto/KeyFormat.d.ts.map +1 -1
  136. package/dist/crypto/KeyFormat.js.map +1 -1
  137. package/dist/crypto/KeyWrap.d.ts +4 -3
  138. package/dist/crypto/KeyWrap.d.ts.map +1 -1
  139. package/dist/crypto/KeyWrap.js +2 -2
  140. package/dist/crypto/KeyWrap.js.map +1 -1
  141. package/dist/crypto/Mac.d.ts +2 -1
  142. package/dist/crypto/Mac.d.ts.map +1 -1
  143. package/dist/crypto/Mac.js +2 -2
  144. package/dist/crypto/Mac.js.map +1 -1
  145. package/dist/crypto/Signature.d.ts +3 -2
  146. package/dist/crypto/Signature.d.ts.map +1 -1
  147. package/dist/crypto/Signature.js +2 -2
  148. package/dist/crypto/Signature.js.map +1 -1
  149. package/dist/crypto/WebCrypto.d.ts +19 -0
  150. package/dist/crypto/WebCrypto.d.ts.map +1 -1
  151. package/dist/crypto/WebCrypto.js.map +1 -1
  152. package/dist/crypto/internal/asymmetric.js.map +1 -1
  153. package/dist/crypto/internal/key.js +3 -2
  154. package/dist/crypto/internal/key.js.map +1 -1
  155. package/dist/encoding/Base64Url.d.ts.map +1 -1
  156. package/dist/encoding/Base64Url.js +26 -3
  157. package/dist/encoding/Base64Url.js.map +1 -1
  158. package/dist/encoding/Json5.d.ts +44 -0
  159. package/dist/encoding/Json5.d.ts.map +1 -0
  160. package/dist/encoding/Json5.js +56 -0
  161. package/dist/encoding/Json5.js.map +1 -0
  162. package/dist/encoding/Jsonc.d.ts +47 -0
  163. package/dist/encoding/Jsonc.d.ts.map +1 -0
  164. package/dist/encoding/Jsonc.js +120 -0
  165. package/dist/encoding/Jsonc.js.map +1 -0
  166. package/dist/encoding/Ndjson.d.ts +5 -4
  167. package/dist/encoding/Ndjson.d.ts.map +1 -1
  168. package/dist/encoding/Ndjson.js +6 -5
  169. package/dist/encoding/Ndjson.js.map +1 -1
  170. package/dist/encoding/SchemaBinary.d.ts +94 -0
  171. package/dist/encoding/SchemaBinary.d.ts.map +1 -1
  172. package/dist/encoding/SchemaBinary.js +219 -6
  173. package/dist/encoding/SchemaBinary.js.map +1 -1
  174. package/dist/encoding/Sse.d.ts +3 -1
  175. package/dist/encoding/Sse.d.ts.map +1 -1
  176. package/dist/encoding/Sse.js +5 -3
  177. package/dist/encoding/Sse.js.map +1 -1
  178. package/dist/encoding/index.d.ts +10 -0
  179. package/dist/encoding/index.d.ts.map +1 -1
  180. package/dist/encoding/index.js +10 -0
  181. package/dist/encoding/index.js.map +1 -1
  182. package/dist/eventlog/EventLog.d.ts +7 -0
  183. package/dist/eventlog/EventLog.d.ts.map +1 -1
  184. package/dist/eventlog/EventLog.js +7 -0
  185. package/dist/eventlog/EventLog.js.map +1 -1
  186. package/dist/eventlog/EventLogServer.d.ts +7 -1
  187. package/dist/eventlog/EventLogServer.d.ts.map +1 -1
  188. package/dist/eventlog/EventLogServer.js +55 -24
  189. package/dist/eventlog/EventLogServer.js.map +1 -1
  190. package/dist/eventlog/EventLogServerEncrypted.d.ts +10 -0
  191. package/dist/eventlog/EventLogServerEncrypted.d.ts.map +1 -1
  192. package/dist/eventlog/EventLogServerEncrypted.js.map +1 -1
  193. package/dist/eventlog/EventLogServerUnencrypted.d.ts +17 -0
  194. package/dist/eventlog/EventLogServerUnencrypted.d.ts.map +1 -1
  195. package/dist/eventlog/EventLogServerUnencrypted.js +14 -2
  196. package/dist/eventlog/EventLogServerUnencrypted.js.map +1 -1
  197. package/dist/eventlog/EventLogSessionAuth.d.ts +21 -0
  198. package/dist/eventlog/EventLogSessionAuth.d.ts.map +1 -1
  199. package/dist/eventlog/EventLogSessionAuth.js +22 -0
  200. package/dist/eventlog/EventLogSessionAuth.js.map +1 -1
  201. package/dist/graphql/GraphQLClient.d.ts +3 -1
  202. package/dist/graphql/GraphQLClient.d.ts.map +1 -1
  203. package/dist/graphql/GraphQLClient.js.map +1 -1
  204. package/dist/graphql/GraphQLClientError.d.ts +14 -9
  205. package/dist/graphql/GraphQLClientError.d.ts.map +1 -1
  206. package/dist/graphql/GraphQLClientError.js +14 -21
  207. package/dist/graphql/GraphQLClientError.js.map +1 -1
  208. package/dist/graphql/GraphQLProtocol.d.ts +12 -3
  209. package/dist/graphql/GraphQLProtocol.d.ts.map +1 -1
  210. package/dist/graphql/GraphQLProtocol.js +4 -1
  211. package/dist/graphql/GraphQLProtocol.js.map +1 -1
  212. package/dist/http/HttpClient.d.ts +204 -16
  213. package/dist/http/HttpClient.d.ts.map +1 -1
  214. package/dist/http/HttpClient.js +93 -13
  215. package/dist/http/HttpClient.js.map +1 -1
  216. package/dist/http/HttpServerRequest.d.ts.map +1 -1
  217. package/dist/http/HttpServerRequest.js +38 -22
  218. package/dist/http/HttpServerRequest.js.map +1 -1
  219. package/dist/http/internal/mimeTypes.d.ts +4 -1
  220. package/dist/http/internal/mimeTypes.d.ts.map +1 -1
  221. package/dist/http/internal/mimeTypes.js +4 -1
  222. package/dist/http/internal/mimeTypes.js.map +1 -1
  223. package/dist/http-api/HttpApiSchema.js +1 -1
  224. package/dist/http-api/HttpApiSchema.js.map +1 -1
  225. package/dist/internal/dateTime.js +66 -27
  226. package/dist/internal/dateTime.js.map +1 -1
  227. package/dist/internal/effect.js +10 -0
  228. package/dist/internal/effect.js.map +1 -1
  229. package/dist/internal/glob.js +234 -56
  230. package/dist/internal/glob.js.map +1 -1
  231. package/dist/internal/graphql.js +21 -7
  232. package/dist/internal/graphql.js.map +1 -1
  233. package/dist/internal/graphqlHeaders.d.ts +7 -0
  234. package/dist/internal/graphqlHeaders.d.ts.map +1 -1
  235. package/dist/internal/graphqlHeaders.js +11 -0
  236. package/dist/internal/graphqlHeaders.js.map +1 -1
  237. package/dist/internal/jsonParser.d.ts +5 -0
  238. package/dist/internal/jsonParser.d.ts.map +1 -0
  239. package/dist/internal/jsonParser.js +280 -0
  240. package/dist/internal/jsonParser.js.map +1 -0
  241. package/dist/internal/persistence.js +8 -1
  242. package/dist/internal/persistence.js.map +1 -1
  243. package/dist/internal/request.js +29 -42
  244. package/dist/internal/request.js.map +1 -1
  245. package/dist/internal/schema/fromJsonSchemaDocument.js +7 -8
  246. package/dist/internal/schema/fromJsonSchemaDocument.js.map +1 -1
  247. package/dist/internal/sql.js +16 -0
  248. package/dist/internal/sql.js.map +1 -1
  249. package/dist/internal/version.js +1 -1
  250. package/dist/jose/JoseError.d.ts +285 -0
  251. package/dist/jose/JoseError.d.ts.map +1 -0
  252. package/dist/jose/JoseError.js +269 -0
  253. package/dist/jose/JoseError.js.map +1 -0
  254. package/dist/jose/Jwe.d.ts +128 -0
  255. package/dist/jose/Jwe.d.ts.map +1 -0
  256. package/dist/jose/Jwe.js +134 -0
  257. package/dist/jose/Jwe.js.map +1 -0
  258. package/dist/jose/Jwk.d.ts +597 -0
  259. package/dist/jose/Jwk.d.ts.map +1 -0
  260. package/dist/jose/Jwk.js +503 -0
  261. package/dist/jose/Jwk.js.map +1 -0
  262. package/dist/jose/Jwks.d.ts +236 -0
  263. package/dist/jose/Jwks.d.ts.map +1 -0
  264. package/dist/jose/Jwks.js +306 -0
  265. package/dist/jose/Jwks.js.map +1 -0
  266. package/dist/jose/Jws.d.ts +177 -0
  267. package/dist/jose/Jws.d.ts.map +1 -0
  268. package/dist/jose/Jws.js +183 -0
  269. package/dist/jose/Jws.js.map +1 -0
  270. package/dist/jose/Jwt.d.ts +270 -0
  271. package/dist/jose/Jwt.d.ts.map +1 -0
  272. package/dist/jose/Jwt.js +293 -0
  273. package/dist/jose/Jwt.js.map +1 -0
  274. package/dist/jose/index.d.ts +51 -0
  275. package/dist/jose/index.d.ts.map +1 -0
  276. package/dist/jose/index.js +52 -0
  277. package/dist/jose/index.js.map +1 -0
  278. package/dist/jose/internal/compact.d.ts +2 -0
  279. package/dist/jose/internal/compact.d.ts.map +1 -0
  280. package/dist/jose/internal/compact.js +179 -0
  281. package/dist/jose/internal/compact.js.map +1 -0
  282. package/dist/net/Host.d.ts.map +1 -1
  283. package/dist/net/Host.js +5 -10
  284. package/dist/net/Host.js.map +1 -1
  285. package/dist/observability/OtlpExporter.d.ts +4 -0
  286. package/dist/observability/OtlpExporter.d.ts.map +1 -1
  287. package/dist/observability/OtlpExporter.js +40 -12
  288. package/dist/observability/OtlpExporter.js.map +1 -1
  289. package/dist/observability/OtlpSerialization.d.ts +1 -1
  290. package/dist/observability/OtlpSerialization.d.ts.map +1 -1
  291. package/dist/observability/OtlpSerialization.js +10 -4
  292. package/dist/observability/OtlpSerialization.js.map +1 -1
  293. package/dist/observability/internal/otlpProtobuf.js +3 -3
  294. package/dist/observability/internal/otlpProtobuf.js.map +1 -1
  295. package/dist/observability/internal/protobuf.js +6 -0
  296. package/dist/observability/internal/protobuf.js.map +1 -1
  297. package/dist/persistence/CircuitBreaker.d.ts +98 -38
  298. package/dist/persistence/CircuitBreaker.d.ts.map +1 -1
  299. package/dist/persistence/CircuitBreaker.js +67 -29
  300. package/dist/persistence/CircuitBreaker.js.map +1 -1
  301. package/dist/persistence/RateLimiter.d.ts +15 -0
  302. package/dist/persistence/RateLimiter.d.ts.map +1 -1
  303. package/dist/persistence/RateLimiter.js +76 -16
  304. package/dist/persistence/RateLimiter.js.map +1 -1
  305. package/dist/persistence/index.d.ts +1 -1
  306. package/dist/persistence/index.js +1 -1
  307. package/dist/reactivity/AtomRegistry.js +17 -7
  308. package/dist/reactivity/AtomRegistry.js.map +1 -1
  309. package/dist/rpc/Rpc.d.ts +1 -1
  310. package/dist/rpc/Rpc.d.ts.map +1 -1
  311. package/dist/rpc/Rpc.js.map +1 -1
  312. package/dist/rpc/RpcClient.d.ts +14 -2
  313. package/dist/rpc/RpcClient.d.ts.map +1 -1
  314. package/dist/rpc/RpcClient.js +38 -21
  315. package/dist/rpc/RpcClient.js.map +1 -1
  316. package/dist/rpc/RpcMessage.d.ts +3 -2
  317. package/dist/rpc/RpcMessage.d.ts.map +1 -1
  318. package/dist/rpc/RpcMessage.js.map +1 -1
  319. package/dist/rpc/RpcServer.d.ts.map +1 -1
  320. package/dist/rpc/RpcServer.js +10 -1
  321. package/dist/rpc/RpcServer.js.map +1 -1
  322. package/dist/sql/Migrator.d.ts +9 -1
  323. package/dist/sql/Migrator.d.ts.map +1 -1
  324. package/dist/sql/Migrator.js +18 -6
  325. package/dist/sql/Migrator.js.map +1 -1
  326. package/dist/sql/SqlClient.d.ts +46 -3
  327. package/dist/sql/SqlClient.d.ts.map +1 -1
  328. package/dist/sql/SqlClient.js +40 -15
  329. package/dist/sql/SqlClient.js.map +1 -1
  330. package/dist/sql/Statement.d.ts +46 -3
  331. package/dist/sql/Statement.d.ts.map +1 -1
  332. package/dist/sql/Statement.js +32 -26
  333. package/dist/sql/Statement.js.map +1 -1
  334. package/dist/workflow/Workflow.d.ts +4 -0
  335. package/dist/workflow/Workflow.d.ts.map +1 -1
  336. package/dist/workflow/Workflow.js.map +1 -1
  337. package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
  338. package/dist/workflow/WorkflowEngine.js +5 -0
  339. package/dist/workflow/WorkflowEngine.js.map +1 -1
  340. package/package.json +7 -3
  341. package/src/BigDecimal.ts +170 -16
  342. package/src/ByteSize.ts +29 -14
  343. package/src/Equal.ts +3 -3
  344. package/src/Hash.ts +5 -4
  345. package/src/Iterable.ts +28 -19
  346. package/src/JsonSchema.ts +45 -7
  347. package/src/MutableRef.ts +1 -8
  348. package/src/Path.ts +6 -1
  349. package/src/Pool.ts +2 -1
  350. package/src/Ref.ts +0 -8
  351. package/src/Schedule.ts +8 -6
  352. package/src/Schema.ts +3 -2
  353. package/src/SchemaRepresentation.ts +4 -2
  354. package/src/SchemaTransformation.ts +2 -2
  355. package/src/Stream.ts +6 -5
  356. package/src/ai/McpClient.ts +488 -91
  357. package/src/ai/McpSchema.ts +119 -0
  358. package/src/ai/McpServer.ts +302 -56
  359. package/src/ai/Prompt.ts +16 -11
  360. package/src/ai/Tool.ts +5 -10
  361. package/src/ai/internal/mcpCore.ts +165 -12
  362. package/src/ai/internal/mcpProtocol/v2024_11_05.ts +3 -1
  363. package/src/ai/internal/mcpProtocol/v2025_03_26.ts +3 -1
  364. package/src/ai/internal/mcpProtocol/v2025_06_18.ts +3 -1
  365. package/src/ai/internal/mcpProtocol/v2025_11_25.ts +3 -1
  366. package/src/ai/internal/mcpProtocol/v2026_07_28.ts +42 -9
  367. package/src/ai/internal/mcpProtocol.ts +15 -0
  368. package/src/ai/internal/mcpRuntime.ts +6 -3
  369. package/src/ai/internal/mcpSkills.ts +480 -0
  370. package/src/ai/internal/structured-output.ts +10 -4
  371. package/src/cluster/ClusterWorkflowEngine.ts +48 -33
  372. package/src/cluster/Entity.ts +52 -0
  373. package/src/cluster/MessageStorage.ts +3 -6
  374. package/src/cluster/Reply.ts +1 -1
  375. package/src/cluster/Runners.ts +16 -2
  376. package/src/cluster/Sharding.ts +17 -1
  377. package/src/cluster/internal/clusterAbandon.ts +7 -7
  378. package/src/cluster/internal/entityManager.ts +89 -15
  379. package/src/cluster/internal/transactionNotifications.ts +7 -0
  380. package/src/crypto/Aead.ts +3 -3
  381. package/src/crypto/Cipher.ts +3 -3
  382. package/src/crypto/KeyAgreement.ts +4 -4
  383. package/src/crypto/KeyFormat.ts +30 -1
  384. package/src/crypto/KeyWrap.ts +6 -6
  385. package/src/crypto/Mac.ts +3 -3
  386. package/src/crypto/Signature.ts +4 -4
  387. package/src/crypto/WebCrypto.ts +20 -0
  388. package/src/crypto/internal/asymmetric.ts +2 -1
  389. package/src/crypto/internal/key.ts +12 -5
  390. package/src/encoding/Base64Url.ts +27 -3
  391. package/src/encoding/Json5.ts +59 -0
  392. package/src/encoding/Jsonc.ts +126 -0
  393. package/src/encoding/Ndjson.ts +6 -5
  394. package/src/encoding/SchemaBinary.ts +228 -7
  395. package/src/encoding/Sse.ts +5 -3
  396. package/src/encoding/index.ts +12 -0
  397. package/src/eventlog/EventLog.ts +7 -0
  398. package/src/eventlog/EventLogServer.ts +67 -24
  399. package/src/eventlog/EventLogServerEncrypted.ts +5 -0
  400. package/src/eventlog/EventLogServerUnencrypted.ts +19 -2
  401. package/src/eventlog/EventLogSessionAuth.ts +26 -0
  402. package/src/graphql/GraphQLClient.ts +3 -1
  403. package/src/graphql/GraphQLClientError.ts +15 -22
  404. package/src/graphql/GraphQLProtocol.ts +12 -3
  405. package/src/http/HttpClient.ts +244 -33
  406. package/src/http/HttpServerRequest.ts +61 -23
  407. package/src/http/internal/mimeTypes.ts +4 -1
  408. package/src/http-api/HttpApiSchema.ts +1 -1
  409. package/src/internal/dateTime.ts +80 -27
  410. package/src/internal/effect.ts +6 -0
  411. package/src/internal/glob.ts +279 -63
  412. package/src/internal/graphql.ts +27 -9
  413. package/src/internal/graphqlHeaders.ts +13 -0
  414. package/src/internal/jsonParser.ts +307 -0
  415. package/src/internal/persistence.ts +9 -1
  416. package/src/internal/request.ts +51 -58
  417. package/src/internal/schema/fromJsonSchemaDocument.ts +11 -10
  418. package/src/internal/sql.ts +25 -0
  419. package/src/internal/version.ts +1 -1
  420. package/src/jose/JoseError.ts +329 -0
  421. package/src/jose/Jwe.ts +196 -0
  422. package/src/jose/Jwk.ts +777 -0
  423. package/src/jose/Jwks.ts +418 -0
  424. package/src/jose/Jws.ts +312 -0
  425. package/src/jose/Jwt.ts +493 -0
  426. package/src/jose/index.ts +58 -0
  427. package/src/jose/internal/compact.ts +195 -0
  428. package/src/net/Host.ts +5 -10
  429. package/src/observability/OtlpExporter.ts +42 -18
  430. package/src/observability/OtlpSerialization.ts +13 -5
  431. package/src/observability/internal/otlpProtobuf.ts +6 -6
  432. package/src/observability/internal/protobuf.ts +10 -0
  433. package/src/persistence/CircuitBreaker.ts +113 -48
  434. package/src/persistence/RateLimiter.ts +97 -19
  435. package/src/persistence/index.ts +1 -1
  436. package/src/reactivity/AtomRegistry.ts +19 -8
  437. package/src/rpc/Rpc.ts +3 -1
  438. package/src/rpc/RpcClient.ts +44 -24
  439. package/src/rpc/RpcMessage.ts +3 -2
  440. package/src/rpc/RpcServer.ts +12 -1
  441. package/src/sql/Migrator.ts +35 -18
  442. package/src/sql/SqlClient.ts +91 -22
  443. package/src/sql/Statement.ts +60 -35
  444. package/src/workflow/Workflow.ts +4 -0
  445. package/src/workflow/WorkflowEngine.ts +5 -0
@@ -16,8 +16,11 @@ import * as Context from "../Context.ts"
16
16
  import * as Duration from "../Duration.ts"
17
17
  import * as Effect from "../Effect.ts"
18
18
  import { flow, identity } from "../Function.ts"
19
+ import { escapeKeySegment } from "../internal/persistence.ts"
19
20
  import * as Layer from "../Layer.ts"
21
+ import * as Schedule from "../Schedule.ts"
20
22
  import * as Schema from "../Schema.ts"
23
+ import type * as Scope from "../Scope.ts"
21
24
  import * as Redis from "./Redis.ts"
22
25
 
23
26
  /**
@@ -85,6 +88,9 @@ export const RateLimiter: Context.Service<RateLimiter, RateLimiter> = Context.Se
85
88
  * The limiter supports fixed-window and token-bucket algorithms and either
86
89
  * fails or returns a delay when a limit is exceeded.
87
90
  *
91
+ * A nonpositive `limit` admits no positive token requests: fail mode rejects
92
+ * them and delay mode returns an infinite delay without touching the store.
93
+ *
88
94
  * @stability unstable
89
95
  * @category constructors
90
96
  * @since 4.0.0
@@ -106,10 +112,9 @@ export const make: Effect.Effect<
106
112
  const algorithm = options.algorithm ?? "fixed-window"
107
113
  const window = Duration.max(Duration.fromInputUnsafe(options.window), Duration.millis(1))
108
114
  const windowMillis = Duration.toMillis(window)
109
- const refillRate = Duration.divideUnsafe(window, options.limit)
110
- const refillRateMillis = Duration.toMillis(refillRate)
115
+ const exceeded = tokens > options.limit
111
116
 
112
- if (onExceeded === "fail" && tokens > options.limit) {
117
+ if (onExceeded === "fail" && exceeded) {
113
118
  return Effect.fail(
114
119
  new RateLimiterError({
115
120
  reason: new RateLimitExceeded({
@@ -122,6 +127,19 @@ export const make: Effect.Effect<
122
127
  )
123
128
  }
124
129
 
130
+ // A nonpositive limit never refills, so skip the store and its infinite refill rate.
131
+ if (options.limit <= 0) {
132
+ return Effect.succeed<ConsumeResult>({
133
+ delay: exceeded ? Duration.infinity : Duration.zero,
134
+ limit: options.limit,
135
+ remaining: options.limit - tokens,
136
+ resetAfter: exceeded ? Duration.infinity : Duration.zero
137
+ })
138
+ }
139
+
140
+ const refillRate = Duration.divideUnsafe(window, options.limit)
141
+ const refillRateMillis = Duration.toMillis(refillRate)
142
+
125
143
  if (algorithm === "fixed-window") {
126
144
  return Effect.flatMap(
127
145
  store.fixedWindow({
@@ -706,18 +724,25 @@ interface AdaptiveState {
706
724
  expiresAt: number
707
725
  }
708
726
 
727
+ const memoryStoreSweepInterval = Duration.minutes(1)
728
+
709
729
  /**
710
- * Provides a process-local in-memory `RateLimiterStore`.
730
+ * Creates a process-local `RateLimiterStore`. Every entry expires once its
731
+ * state is indistinguishable from a missing key, and a background sweep tied to
732
+ * the scope removes expired entries, so an idle store drains to empty.
711
733
  *
712
- * @stability unstable
713
- * @category layers
714
- * @since 4.0.0
734
+ * @internal
715
735
  */
716
- export const layerStoreMemory: Layer.Layer<
717
- RateLimiterStore
718
- > = Layer.sync(RateLimiterStore, () => {
736
+ export const makeMemoryStore: Effect.Effect<
737
+ {
738
+ readonly store: RateLimiterStore["Service"]
739
+ readonly size: number
740
+ },
741
+ never,
742
+ Scope.Scope
743
+ > = Effect.gen(function*() {
719
744
  const fixedCounters = new Map<string, { count: number; expiresAt: number }>()
720
- const tokenBuckets = new Map<string, { tokens: number; lastRefill: number }>()
745
+ const tokenBuckets = new Map<string, { tokens: number; lastRefill: number; expiresAt: number }>()
721
746
  const adaptiveStates = new Map<string, AdaptiveState>()
722
747
 
723
748
  const getAdaptiveState = (key: string, now: number): AdaptiveState | undefined => {
@@ -738,7 +763,7 @@ export const layerStoreMemory: Layer.Layer<
738
763
  const learnedExpiresAt = (now: number, learnedWindowMillis: number): number =>
739
764
  now + learnedWindowMillis + adaptiveStateTtlGraceMillis
740
765
 
741
- return RateLimiterStore.of({
766
+ const store = RateLimiterStore.of({
742
767
  fixedWindow: (options) =>
743
768
  Effect.clockWith((clock) =>
744
769
  Effect.sync(() => {
@@ -749,7 +774,7 @@ export const layerStoreMemory: Layer.Layer<
749
774
  counter = { count: 0, expiresAt: now }
750
775
  fixedCounters.set(options.key, counter)
751
776
  }
752
- if (options.limit && counter.count + options.tokens > options.limit) {
777
+ if (options.limit !== undefined && counter.count + options.tokens > options.limit) {
753
778
  return [counter.count + options.tokens, counter.expiresAt - now] as const
754
779
  }
755
780
  counter.count += options.tokens
@@ -763,8 +788,8 @@ export const layerStoreMemory: Layer.Layer<
763
788
  const refillRateMillis = Duration.toMillis(options.refillRate)
764
789
  const now = clock.currentTimeMillisUnsafe()
765
790
  let bucket = tokenBuckets.get(options.key)
766
- if (!bucket) {
767
- bucket = { tokens: options.limit, lastRefill: now }
791
+ if (!bucket || bucket.expiresAt <= now) {
792
+ bucket = { tokens: options.limit, lastRefill: now, expiresAt: now }
768
793
  tokenBuckets.set(options.key, bucket)
769
794
  }
770
795
  const tokensToAdd = Math.floor((now - bucket.lastRefill) / refillRateMillis)
@@ -780,6 +805,8 @@ export const layerStoreMemory: Layer.Layer<
780
805
  if (options.allowOverflow || newTokenCount >= 0) {
781
806
  bucket.tokens = newTokenCount
782
807
  }
808
+ // The bucket is indistinguishable from a fresh one once fully refilled
809
+ bucket.expiresAt = bucket.lastRefill + Math.ceil(options.limit - bucket.tokens) * refillRateMillis
783
810
  return [newTokenCount, Math.max(0, now - bucket.lastRefill)] as const
784
811
  })
785
812
  ),
@@ -924,12 +951,59 @@ export const layerStoreMemory: Layer.Layer<
924
951
  })
925
952
  )
926
953
  })
954
+
955
+ const sweep = Effect.clockWith((clock) =>
956
+ Effect.sync(() => {
957
+ const now = clock.currentTimeMillisUnsafe()
958
+ for (const map of [fixedCounters, tokenBuckets, adaptiveStates]) {
959
+ for (const [key, entry] of map) {
960
+ if (entry.expiresAt <= now) {
961
+ map.delete(key)
962
+ }
963
+ }
964
+ }
965
+ })
966
+ )
967
+ yield* sweep.pipe(
968
+ Effect.repeat(Schedule.spaced(memoryStoreSweepInterval)),
969
+ Effect.forkScoped
970
+ )
971
+
972
+ return {
973
+ store,
974
+ get size() {
975
+ return fixedCounters.size + tokenBuckets.size + adaptiveStates.size
976
+ }
977
+ }
927
978
  })
928
979
 
980
+ /**
981
+ * Provides a process-local in-memory `RateLimiterStore`.
982
+ *
983
+ * **Details**
984
+ *
985
+ * Entries expire once their state is indistinguishable from an unseen key, and
986
+ * a background sweep scoped to the layer removes expired entries periodically.
987
+ *
988
+ * @stability unstable
989
+ * @category layers
990
+ * @since 4.0.0
991
+ */
992
+ export const layerStoreMemory: Layer.Layer<
993
+ RateLimiterStore
994
+ > = Layer.effect(RateLimiterStore)(Effect.map(makeMemoryStore, (memory) => memory.store))
995
+
929
996
  /**
930
997
  * Creates a Redis-backed `RateLimiterStore` using Lua scripts and the
931
998
  * configured key prefix.
932
999
  *
1000
+ * **Details**
1001
+ *
1002
+ * State for a rate-limit key is stored under `<prefix><key>`, with
1003
+ * `<prefix><key>:refill` holding token-bucket refill times and
1004
+ * `<prefix><key>:adaptive` holding adaptive state. `%` and `:` in the key are
1005
+ * percent-encoded so different keys never share Redis state.
1006
+ *
933
1007
  * @stability unstable
934
1008
  * @category constructors
935
1009
  * @since 4.0.0
@@ -941,6 +1015,7 @@ export const makeStoreRedis = Effect.fnUntraced(function*(
941
1015
  ) {
942
1016
  const prefix = options?.prefix ?? "ratelimiter:"
943
1017
  const redis = yield* Redis.Redis
1018
+ const redisKey = (key: string) => `${prefix}${escapeKeySegment(key)}`
944
1019
 
945
1020
  const fixedWindow = redis.eval(fixedWindowScript)
946
1021
  const tokenBucket = redis.eval(tokenBucketScript)
@@ -949,7 +1024,7 @@ export const makeStoreRedis = Effect.fnUntraced(function*(
949
1024
 
950
1025
  return RateLimiterStore.of({
951
1026
  fixedWindow(options) {
952
- const key = `${prefix}${options.key}`
1027
+ const key = redisKey(options.key)
953
1028
  const refillMillis = Duration.toMillis(options.refillRate)
954
1029
  return Effect.mapError(
955
1030
  Effect.map(
@@ -966,7 +1041,7 @@ export const makeStoreRedis = Effect.fnUntraced(function*(
966
1041
  )
967
1042
  },
968
1043
  tokenBucket(options) {
969
- const key = `${prefix}${options.key}`
1044
+ const key = redisKey(options.key)
970
1045
  const lastRefillKey = `${key}:refill`
971
1046
  const refillMillis = Duration.toMillis(options.refillRate)
972
1047
  return Effect.clockWith((clock) =>
@@ -994,7 +1069,7 @@ export const makeStoreRedis = Effect.fnUntraced(function*(
994
1069
  )
995
1070
  },
996
1071
  adaptiveConsume(options) {
997
- const key = `${prefix}${options.key}:adaptive`
1072
+ const key = `${redisKey(options.key)}:adaptive`
998
1073
  return Effect.map(
999
1074
  Effect.mapError(
1000
1075
  adaptiveConsume(
@@ -1021,7 +1096,7 @@ export const makeStoreRedis = Effect.fnUntraced(function*(
1021
1096
  adaptiveFeedback(options) {
1022
1097
  if (options.status !== 429 || options.retryAfter === undefined) return Effect.void
1023
1098
  const retryAfterMillis = clampAdaptiveDurationMillis(Duration.toMillis(options.retryAfter))
1024
- const key = `${prefix}${options.key}:adaptive`
1099
+ const key = `${redisKey(options.key)}:adaptive`
1025
1100
  return Effect.asVoid(
1026
1101
  Effect.mapError(
1027
1102
  adaptiveFeedback(
@@ -1057,6 +1132,9 @@ local limit = tonumber(ARGV[3])
1057
1132
  local current = tonumber(redis.call("GET", key))
1058
1133
 
1059
1134
  if not current then
1135
+ if limit and tokens > limit then
1136
+ return { string.format("%.17g", tokens), 0 }
1137
+ end
1060
1138
  local nextpttl = math.max(1, math.ceil(refillms * tokens))
1061
1139
  redis.call("SET", key, tokens, "PX", nextpttl)
1062
1140
  return { string.format("%.17g", tokens), nextpttl }
@@ -7,7 +7,7 @@
7
7
 
8
8
  /**
9
9
  * @stability experimental
10
- * @since 4.0.6
10
+ * @since 4.0.7
11
11
  */
12
12
  export * as CircuitBreaker from "./CircuitBreaker.ts"
13
13
 
@@ -553,9 +553,15 @@ class RegistryImpl implements AtomRegistry {
553
553
  const node = this.ensureNode(atom)
554
554
  if (options?.immediate) {
555
555
  f(node.value())
556
- } else if (node.state === NodeState.stale) {
557
- // a listener hears the next change, which only reaches an up-to-date node
558
- node.value()
556
+ } else {
557
+ // build the node so the listener hears its next change. A failed build
558
+ // is left for the next read to report; an error raised after the value
559
+ // is committed has no later read to report it, so it is rethrown
560
+ try {
561
+ node.value()
562
+ } catch (error) {
563
+ if ((node.state & NodeFlags.waitingForValue) === 0) throw error
564
+ }
559
565
  }
560
566
  const remove = node.subscribe(function() {
561
567
  f(node._value)
@@ -842,11 +848,15 @@ class NodeImpl<A> {
842
848
  }
843
849
 
844
850
  build(): void {
845
- // a lifetime still attached to a node that needs a value belongs to a
846
- // build that failed, or to one that is running and is now superseded
847
- this.disposeLifetime()
848
- this.invalidatedDuringBuild = false
849
851
  const lifetime = makeLifetime(this)
852
+ // release a failed or superseded build; its finalizers run only once, so
853
+ // their failure is rethrown once this build commits
854
+ try {
855
+ this.disposeLifetime()
856
+ } catch (error) {
857
+ lifetime.failure = error
858
+ }
859
+ this.invalidatedDuringBuild = false
850
860
  this.lifetime = lifetime
851
861
  let value: A
852
862
  let read = false
@@ -1126,7 +1136,8 @@ interface Lifetime<A> extends Atom.AtomContext {
1126
1136
  readonly node: NodeImpl<A>
1127
1137
  // the parents read so far by the build; `undefined` once the build has returned
1128
1138
  reads: Set<NodeImpl<any>> | undefined
1129
- // a failure met while reading a parent that still produced its value
1139
+ // rethrown once the build commits: a failure from releasing the previous
1140
+ // lifetime, or from reading a parent that still produced its value
1130
1141
  failure: unknown
1131
1142
  finalizers: Array<() => void> | undefined
1132
1143
  disposed: boolean
package/src/rpc/Rpc.ts CHANGED
@@ -363,7 +363,9 @@ export type SuccessExit<R> = Success<R> extends infer T ? T extends Stream<infer
363
363
  * @category utility types
364
364
  * @since 4.0.0
365
365
  */
366
- export type SuccessChunk<R> = Success<R> extends Stream<infer _A, infer _E, infer _Env> ? _A : never
366
+ export type SuccessChunk<R> = R extends Any ?
367
+ SuccessSchema<R> extends RpcSchema.Stream<infer _A, infer _E> ? _A["Type"] : never
368
+ : never
367
369
 
368
370
  /**
369
371
  * Extracts the RPC error schema, including error schemas contributed by
@@ -113,7 +113,8 @@ export declare namespace RpcClient {
113
113
  * handler's result and error are not returned, but transport errors,
114
114
  * middleware errors and failures before the handler starts still fail the
115
115
  * call. Over HTTP and workers the call completes after the handler has
116
- * finished.
116
+ * finished. A protocol that only delivers requests acknowledges the call
117
+ * itself once it has delivered the request.
117
118
  */
118
119
  readonly discard?: Discard | undefined
119
120
  }
@@ -188,7 +189,8 @@ export declare namespace RpcClient {
188
189
  * handler's result and error are not returned, but transport errors,
189
190
  * middleware errors and failures before the handler starts still fail the
190
191
  * call. Over HTTP and workers the call completes after the handler has
191
- * finished.
192
+ * finished. A protocol that only delivers requests acknowledges the call
193
+ * itself once it has delivered the request.
192
194
  */
193
195
  readonly discard?: Discard | undefined
194
196
  }
@@ -418,19 +420,18 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any, E, const Flatten extend
418
420
  let fiber: Fiber.Fiber<any, any>
419
421
  return Effect.onInterrupt(
420
422
  Effect.callback<any, any>((resume) => {
421
- // the acknowledgement of a discarded call, held until its send has finished
422
- let ack: Exit.Exit<any, any> | undefined
423
+ let acked = false
423
424
  const entry: ClientEntry = {
424
425
  _tag: "Effect",
425
426
  rpc,
426
427
  context,
427
428
  resume(exit) {
428
- if (discard) {
429
- // Interrupting the send could cancel the call, as an HTTP
430
- // handler is scoped to its request, so the call completes
431
- // once the send has finished too.
432
- ack = exit._tag === "Success" ? Exit.void : exit
433
- if (fiber?.pollUnsafe()) resume(ack)
429
+ if (discard && exit._tag === "Success") {
430
+ // A successful acknowledgement waits for the send to finish, as
431
+ // interrupting the send could cancel the call: an HTTP handler
432
+ // is scoped to its request. Failures complete the call at once.
433
+ acked = true
434
+ if (fiber?.pollUnsafe()) resume(Exit.void)
434
435
  return
435
436
  }
436
437
  resume(exit)
@@ -450,8 +451,8 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any, E, const Flatten extend
450
451
  if (exit._tag === "Failure") {
451
452
  entries.delete(id)
452
453
  return resume(exit)
453
- } else if (ack) {
454
- return resume(ack)
454
+ } else if (acked) {
455
+ return resume(Exit.void)
455
456
  }
456
457
  })
457
458
  }),
@@ -604,8 +605,10 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any, E, const Flatten extend
604
605
  if (!entry || entry._tag !== "Queue") return Effect.void
605
606
  return Queue.offerAll(entry.queue, message.values).pipe(
606
607
  supportsAck
607
- ? Effect.flatMap(() =>
608
- options.onFromClient({
608
+ ? Effect.flatMap((dropped) =>
609
+ // values are dropped when the queue was shutdown by an interrupted
610
+ // consumer, so the server should not be asked for more
611
+ dropped.length > 0 ? Effect.void : options.onFromClient({
609
612
  message: { _tag: "Ack", requestId: message.requestId },
610
613
  context: entry.context
611
614
  })
@@ -831,8 +834,10 @@ export const make: <Rpcs extends Rpc.Any, const Flatten extends boolean = false>
831
834
  }
832
835
  case "ClientProtocolError": {
833
836
  const exit = Exit.fail(message.error)
834
- const requestIds = Array.from(entries.keys())
835
- entries.clear()
837
+ const requestIds = message.requestIds === undefined
838
+ ? Array.from(entries.keys())
839
+ : message.requestIds.map(RequestId).filter((requestId) => entries.has(requestId))
840
+ for (const requestId of requestIds) entries.delete(requestId)
836
841
  return Effect.forEach(
837
842
  requestIds,
838
843
  (requestId) => write({ _tag: "Exit", clientId: 0, requestId, exit: exit as any })
@@ -953,6 +958,16 @@ export const withHeaders: {
953
958
  * Use to provide the transport boundary for RPC clients over HTTP, WebSocket,
954
959
  * workers, sockets, or custom protocols.
955
960
  *
961
+ * **Details**
962
+ *
963
+ * A `Request` that `send` accepts stays pending until a reply names its id: an
964
+ * `Exit`, or a `ClientProtocolError` that lists it in `requestIds`. Until then
965
+ * the client keeps the request and the caller's context, unless the caller is
966
+ * interrupted, the client closes or the connection fails. A transport that
967
+ * only delivers requests, such as a message queue, writes a void `Exit` for a
968
+ * `discard` request once the request is delivered, and fails `send` with an
969
+ * `RpcClientError` for any other request.
970
+ *
956
971
  * @stability unstable
957
972
  * @category services
958
973
  * @since 4.0.0
@@ -1599,21 +1614,26 @@ export const makeProtocolWorker = (
1599
1614
  undefined
1600
1615
  }).pipe(
1601
1616
  Effect.tapCause((cause) => {
1617
+ const requestIdsByClient = new Map<number, Array<string | number>>()
1602
1618
  for (const [requestId, entry] of entries) {
1603
1619
  if (entry.worker !== backing) continue
1604
1620
  entries.delete(requestId)
1605
1621
  entry.latch.openUnsafe()
1622
+ const requestIds = requestIdsByClient.get(entry.clientId)
1623
+ if (requestIds) requestIds.push(requestId)
1624
+ else requestIdsByClient.set(entry.clientId, [requestId])
1606
1625
  }
1607
- const error = Cause.findError(cause)
1608
- return broadcast({
1609
- _tag: "ClientProtocolError",
1610
- error: new RpcClientError({
1611
- reason: Result.isSuccess(error) ? error.success.reason : new RpcClientDefect({
1612
- message: "Error in worker",
1613
- cause: Cause.squash(cause)
1614
- })
1626
+ const found = Cause.findError(cause)
1627
+ const error = new RpcClientError({
1628
+ reason: Result.isSuccess(found) ? found.success.reason : new RpcClientDefect({
1629
+ message: "Error in worker",
1630
+ cause: Cause.squash(cause)
1615
1631
  })
1616
1632
  })
1633
+ return Effect.forEach(
1634
+ requestIdsByClient,
1635
+ ([clientId, requestIds]) => writeResponse(clientId, { _tag: "ClientProtocolError", error, requestIds })
1636
+ )
1617
1637
  }),
1618
1638
  Effect.retry(Schedule.spaced(1000)),
1619
1639
  Effect.annotateLogs({
@@ -325,8 +325,8 @@ export interface ResponseExitEncoded {
325
325
  }
326
326
 
327
327
  /**
328
- * A server-to-client protocol message reporting a client protocol error to all
329
- * affected in-flight requests.
328
+ * A server-to-client protocol message failing in-flight requests with a client
329
+ * protocol error: those in `requestIds`, or all of them when it is omitted.
330
330
  *
331
331
  * @stability unstable
332
332
  * @category models
@@ -335,6 +335,7 @@ export interface ResponseExitEncoded {
335
335
  export interface ClientProtocolError {
336
336
  readonly _tag: "ClientProtocolError"
337
337
  readonly error: RpcClientError
338
+ readonly requestIds?: ReadonlyArray<string | number>
338
339
  }
339
340
 
340
341
  /**
@@ -902,6 +902,17 @@ export const make: <Rpcs extends Rpc.Any>(
902
902
  request: RequestEncoded,
903
903
  payload: unknown
904
904
  ) => {
905
+ // the headers come from the wire unvalidated, and malformed input makes
906
+ // `Headers.fromInput` throw
907
+ let headers: Headers.Headers
908
+ try {
909
+ headers = Headers.fromInput(request.headers)
910
+ } catch {
911
+ const reason = "Invalid request headers"
912
+ return request.isNotification === true
913
+ ? dropNotification(reason)
914
+ : sendRequestDefect(client, requestId, schemas.encodeExit, reason)
915
+ }
905
916
  // nothing is encoded for a notification, and only a reply would remove its schemas
906
917
  if (request.isNotification !== true) {
907
918
  client.schemas.set(
@@ -919,7 +930,7 @@ export const make: <Rpcs extends Rpc.Any>(
919
930
  const decoded = request as Types.Mutable<RequestEncoded>
920
931
  decoded.id = requestId
921
932
  decoded.payload = payload
922
- decoded.headers = Headers.fromInput(request.headers) as any
933
+ decoded.headers = headers as any
923
934
  return server.write(client.id, decoded as any)
924
935
  }
925
936
 
@@ -12,7 +12,7 @@
12
12
  import * as Arr from "../Array.ts"
13
13
  import * as Data from "../Data.ts"
14
14
  import * as Effect from "../Effect.ts"
15
- import { pipe } from "../Function.ts"
15
+ import { identity, pipe } from "../Function.ts"
16
16
  import * as Option from "../Option.ts"
17
17
  import * as Order from "../Order.ts"
18
18
  import * as Client from "./SqlClient.ts"
@@ -99,13 +99,22 @@ export class MigrationError extends Data.TaggedError("MigrationError")<{
99
99
  * migrations. ClickHouse runs without a transaction and records each migration
100
100
  * only after it succeeds.
101
101
  *
102
+ * **Details**
103
+ *
104
+ * `transformWrites` transforms only the effects that create the migrations
105
+ * table and insert into it, for clients such as ClickHouse that run row-less
106
+ * statements differently from queries. Reads of the migrations table and the
107
+ * migrations themselves are not transformed. It defaults to `identity`.
108
+ *
102
109
  * @stability unstable
103
110
  * @category constructors
104
111
  * @since 4.0.0
105
112
  */
106
113
  export const make = <RD = never>({
114
+ transformWrites = identity,
107
115
  dumpSchema = () => Effect.void
108
116
  }: {
117
+ transformWrites?: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
109
118
  dumpSchema?: (
110
119
  path: string,
111
120
  migrationsTable: string
@@ -123,7 +132,7 @@ export const make = <RD = never>({
123
132
  Effect.gen(function*() {
124
133
  const sql = yield* Client.SqlClient
125
134
 
126
- const ensureMigrationsTable = sql.onDialectOrElse({
135
+ const createMigrationsTable = transformWrites(sql.onDialectOrElse({
127
136
  mssql: () =>
128
137
  sql`IF OBJECT_ID(N'${sql.literal(table)}', N'U') IS NULL
129
138
  CREATE TABLE ${sql(table)} (
@@ -147,14 +156,25 @@ export const make = <RD = never>({
147
156
  ) ENGINE = MergeTree
148
157
  ORDER BY migration_id`,
149
158
  pg: () =>
150
- Effect.flatMap(
151
- migrationsTableExists(sql, table),
152
- (exists) =>
153
- exists ? Effect.void : Effect.asVoid(sql`CREATE TABLE ${sql(table)} (
159
+ sql`CREATE TABLE ${sql(table)} (
154
160
  migration_id integer primary key,
155
161
  created_at timestamp with time zone not null default now(),
156
162
  name text not null
157
- )`).pipe(
163
+ )`,
164
+ orElse: () =>
165
+ sql`CREATE TABLE IF NOT EXISTS ${sql(table)} (
166
+ migration_id integer PRIMARY KEY NOT NULL,
167
+ created_at datetime NOT NULL DEFAULT current_timestamp,
168
+ name VARCHAR(255) NOT NULL
169
+ )`
170
+ }))
171
+
172
+ const ensureMigrationsTable = sql.onDialectOrElse({
173
+ pg: () =>
174
+ Effect.flatMap(
175
+ migrationsTableExists(sql, table),
176
+ (exists) =>
177
+ exists ? Effect.void : Effect.asVoid(createMigrationsTable).pipe(
158
178
  Effect.catch((error) =>
159
179
  Effect.flatMap(
160
180
  migrationsTableExists(sql, table),
@@ -163,22 +183,19 @@ ORDER BY migration_id`,
163
183
  )
164
184
  )
165
185
  ),
166
- orElse: () =>
167
- sql`CREATE TABLE IF NOT EXISTS ${sql(table)} (
168
- migration_id integer PRIMARY KEY NOT NULL,
169
- created_at datetime NOT NULL DEFAULT current_timestamp,
170
- name VARCHAR(255) NOT NULL
171
- )`
186
+ orElse: () => createMigrationsTable
172
187
  })
173
188
 
174
189
  const insertMigrations = (
175
190
  rows: Arr.NonEmptyReadonlyArray<[id: number, name: string]>
176
191
  ) =>
177
- sql`INSERT INTO ${sql(table)} ${
178
- sql.insert(
179
- Arr.map(rows, ([migration_id, name]) => ({ migration_id, name }))
180
- )
181
- }`.withoutTransform
192
+ transformWrites(
193
+ sql`INSERT INTO ${sql(table)} ${
194
+ sql.insert(
195
+ Arr.map(rows, ([migration_id, name]) => ({ migration_id, name }))
196
+ )
197
+ }`.withoutTransform
198
+ )
182
199
 
183
200
  const latestMigration = Effect.map(
184
201
  sql<{ migration_id: number; name: string; created_at: Date }>`SELECT migration_id, name, created_at FROM ${