@homeflare/alchemy 0.43.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (612) hide show
  1. package/README.md +10 -1
  2. package/dist/caddy/index.js +35 -1
  3. package/dist/caddy/index.js.map +3 -3
  4. package/dist/launchd/index.js +35 -1
  5. package/dist/launchd/index.js.map +3 -3
  6. package/dist/linux/index.js +35 -1
  7. package/dist/linux/index.js.map +3 -3
  8. package/dist/litellm/access-group-form.d.ts +26 -0
  9. package/dist/litellm/access-group-form.d.ts.map +1 -0
  10. package/dist/litellm/access-group-operations.d.ts +37 -0
  11. package/dist/litellm/access-group-operations.d.ts.map +1 -0
  12. package/dist/litellm/access-group-types.d.ts +49 -0
  13. package/dist/litellm/access-group-types.d.ts.map +1 -0
  14. package/dist/litellm/access-group.d.ts +55 -0
  15. package/dist/litellm/access-group.d.ts.map +1 -0
  16. package/dist/litellm/credential-errors.d.ts +131 -0
  17. package/dist/litellm/credential-errors.d.ts.map +1 -0
  18. package/dist/litellm/credential-form.d.ts +79 -0
  19. package/dist/litellm/credential-form.d.ts.map +1 -0
  20. package/dist/litellm/credential-operations.d.ts +84 -0
  21. package/dist/litellm/credential-operations.d.ts.map +1 -0
  22. package/dist/litellm/credential-rewrite.d.ts +6 -0
  23. package/dist/litellm/credential-rewrite.d.ts.map +1 -0
  24. package/dist/litellm/credential-types.d.ts +87 -0
  25. package/dist/litellm/credential-types.d.ts.map +1 -0
  26. package/dist/litellm/credential-values.d.ts +53 -0
  27. package/dist/litellm/credential-values.d.ts.map +1 -0
  28. package/dist/litellm/credential.d.ts +83 -0
  29. package/dist/litellm/credential.d.ts.map +1 -0
  30. package/dist/litellm/fake-access-group-litellm.d.ts +34 -0
  31. package/dist/litellm/fake-access-group-litellm.d.ts.map +1 -0
  32. package/dist/litellm/fake-credential-litellm.d.ts +54 -0
  33. package/dist/litellm/fake-credential-litellm.d.ts.map +1 -0
  34. package/dist/litellm/fake-keys.d.ts +53 -0
  35. package/dist/litellm/fake-keys.d.ts.map +1 -0
  36. package/dist/litellm/fake-litellm.d.ts +4 -1
  37. package/dist/litellm/fake-litellm.d.ts.map +1 -1
  38. package/dist/litellm/fake-mcp-litellm.d.ts +67 -0
  39. package/dist/litellm/fake-mcp-litellm.d.ts.map +1 -0
  40. package/dist/litellm/fake-model-litellm-post-update.d.ts +49 -0
  41. package/dist/litellm/fake-model-litellm-post-update.d.ts.map +1 -0
  42. package/dist/litellm/fake-model-litellm.d.ts +48 -0
  43. package/dist/litellm/fake-model-litellm.d.ts.map +1 -0
  44. package/dist/litellm/fake-policy-attachment-litellm.d.ts +33 -0
  45. package/dist/litellm/fake-policy-attachment-litellm.d.ts.map +1 -0
  46. package/dist/litellm/fake-policy-litellm.d.ts +32 -0
  47. package/dist/litellm/fake-policy-litellm.d.ts.map +1 -0
  48. package/dist/litellm/fake-registry-base.d.ts +42 -0
  49. package/dist/litellm/fake-registry-base.d.ts.map +1 -0
  50. package/dist/litellm/fake-stack.d.ts +8 -1
  51. package/dist/litellm/fake-stack.d.ts.map +1 -1
  52. package/dist/litellm/fake-team-litellm.d.ts +47 -0
  53. package/dist/litellm/fake-team-litellm.d.ts.map +1 -0
  54. package/dist/litellm/fake-tool-litellm.d.ts +28 -0
  55. package/dist/litellm/fake-tool-litellm.d.ts.map +1 -0
  56. package/dist/litellm/fake-toolset-litellm.d.ts +29 -0
  57. package/dist/litellm/fake-toolset-litellm.d.ts.map +1 -0
  58. package/dist/litellm/index.d.ts +18 -0
  59. package/dist/litellm/index.d.ts.map +1 -1
  60. package/dist/litellm/index.js +3078 -2
  61. package/dist/litellm/index.js.map +65 -4
  62. package/dist/litellm/key-errors.d.ts +169 -0
  63. package/dist/litellm/key-errors.d.ts.map +1 -0
  64. package/dist/litellm/key-form.d.ts +119 -0
  65. package/dist/litellm/key-form.d.ts.map +1 -0
  66. package/dist/litellm/key-harness.d.ts +41 -0
  67. package/dist/litellm/key-harness.d.ts.map +1 -0
  68. package/dist/litellm/key-metadata-errors.d.ts +30 -0
  69. package/dist/litellm/key-metadata-errors.d.ts.map +1 -0
  70. package/dist/litellm/key-metadata.d.ts +22 -0
  71. package/dist/litellm/key-metadata.d.ts.map +1 -0
  72. package/dist/litellm/key-operations.d.ts +63 -0
  73. package/dist/litellm/key-operations.d.ts.map +1 -0
  74. package/dist/litellm/key-secret.d.ts +33 -0
  75. package/dist/litellm/key-secret.d.ts.map +1 -0
  76. package/dist/litellm/key.d.ts +78 -0
  77. package/dist/litellm/key.d.ts.map +1 -0
  78. package/dist/litellm/mcp-server-credential.d.ts +50 -0
  79. package/dist/litellm/mcp-server-credential.d.ts.map +1 -0
  80. package/dist/litellm/mcp-server-errors.d.ts +101 -0
  81. package/dist/litellm/mcp-server-errors.d.ts.map +1 -0
  82. package/dist/litellm/mcp-server-form.d.ts +56 -0
  83. package/dist/litellm/mcp-server-form.d.ts.map +1 -0
  84. package/dist/litellm/mcp-server-locate.d.ts +26 -0
  85. package/dist/litellm/mcp-server-locate.d.ts.map +1 -0
  86. package/dist/litellm/mcp-server-operations.d.ts +63 -0
  87. package/dist/litellm/mcp-server-operations.d.ts.map +1 -0
  88. package/dist/litellm/mcp-server-shadow.d.ts +24 -0
  89. package/dist/litellm/mcp-server-shadow.d.ts.map +1 -0
  90. package/dist/litellm/mcp-server-types.d.ts +118 -0
  91. package/dist/litellm/mcp-server-types.d.ts.map +1 -0
  92. package/dist/litellm/mcp-server-url.d.ts +11 -0
  93. package/dist/litellm/mcp-server-url.d.ts.map +1 -0
  94. package/dist/litellm/mcp-server.d.ts +95 -0
  95. package/dist/litellm/mcp-server.d.ts.map +1 -0
  96. package/dist/litellm/model-claim.d.ts +24 -0
  97. package/dist/litellm/model-claim.d.ts.map +1 -0
  98. package/dist/litellm/model-credential.d.ts +12 -0
  99. package/dist/litellm/model-credential.d.ts.map +1 -0
  100. package/dist/litellm/model-errors.d.ts +119 -0
  101. package/dist/litellm/model-errors.d.ts.map +1 -0
  102. package/dist/litellm/model-form.d.ts +78 -0
  103. package/dist/litellm/model-form.d.ts.map +1 -0
  104. package/dist/litellm/model-locate.d.ts +13 -0
  105. package/dist/litellm/model-locate.d.ts.map +1 -0
  106. package/dist/litellm/model-operations.d.ts +59 -0
  107. package/dist/litellm/model-operations.d.ts.map +1 -0
  108. package/dist/litellm/model-types.d.ts +91 -0
  109. package/dist/litellm/model-types.d.ts.map +1 -0
  110. package/dist/litellm/model.d.ts +88 -0
  111. package/dist/litellm/model.d.ts.map +1 -0
  112. package/dist/litellm/policy-attachment-form.d.ts +19 -0
  113. package/dist/litellm/policy-attachment-form.d.ts.map +1 -0
  114. package/dist/litellm/policy-attachment-operations.d.ts +31 -0
  115. package/dist/litellm/policy-attachment-operations.d.ts.map +1 -0
  116. package/dist/litellm/policy-attachment-types.d.ts +48 -0
  117. package/dist/litellm/policy-attachment-types.d.ts.map +1 -0
  118. package/dist/litellm/policy-attachment.d.ts +61 -0
  119. package/dist/litellm/policy-attachment.d.ts.map +1 -0
  120. package/dist/litellm/policy-form.d.ts +22 -0
  121. package/dist/litellm/policy-form.d.ts.map +1 -0
  122. package/dist/litellm/policy-operations.d.ts +42 -0
  123. package/dist/litellm/policy-operations.d.ts.map +1 -0
  124. package/dist/litellm/policy-types.d.ts +57 -0
  125. package/dist/litellm/policy-types.d.ts.map +1 -0
  126. package/dist/litellm/policy.d.ts +65 -0
  127. package/dist/litellm/policy.d.ts.map +1 -0
  128. package/dist/litellm/providers.d.ts +1 -1
  129. package/dist/litellm/providers.d.ts.map +1 -1
  130. package/dist/litellm/registry-errors.d.ts +62 -0
  131. package/dist/litellm/registry-errors.d.ts.map +1 -0
  132. package/dist/litellm/registry-support.d.ts +42 -0
  133. package/dist/litellm/registry-support.d.ts.map +1 -0
  134. package/dist/litellm/team-form.d.ts +26 -0
  135. package/dist/litellm/team-form.d.ts.map +1 -0
  136. package/dist/litellm/team-members.d.ts +10 -0
  137. package/dist/litellm/team-members.d.ts.map +1 -0
  138. package/dist/litellm/team-operations.d.ts +38 -0
  139. package/dist/litellm/team-operations.d.ts.map +1 -0
  140. package/dist/litellm/team-permission.d.ts +35 -0
  141. package/dist/litellm/team-permission.d.ts.map +1 -0
  142. package/dist/litellm/team-types.d.ts +101 -0
  143. package/dist/litellm/team-types.d.ts.map +1 -0
  144. package/dist/litellm/team.d.ts +67 -0
  145. package/dist/litellm/team.d.ts.map +1 -0
  146. package/dist/litellm/tool-policy-form.d.ts +21 -0
  147. package/dist/litellm/tool-policy-form.d.ts.map +1 -0
  148. package/dist/litellm/tool-policy-operations.d.ts +30 -0
  149. package/dist/litellm/tool-policy-operations.d.ts.map +1 -0
  150. package/dist/litellm/tool-policy-types.d.ts +46 -0
  151. package/dist/litellm/tool-policy-types.d.ts.map +1 -0
  152. package/dist/litellm/tool-policy.d.ts +62 -0
  153. package/dist/litellm/tool-policy.d.ts.map +1 -0
  154. package/dist/litellm/toolset-form.d.ts +20 -0
  155. package/dist/litellm/toolset-form.d.ts.map +1 -0
  156. package/dist/litellm/toolset-operations.d.ts +39 -0
  157. package/dist/litellm/toolset-operations.d.ts.map +1 -0
  158. package/dist/litellm/toolset-types.d.ts +46 -0
  159. package/dist/litellm/toolset-types.d.ts.map +1 -0
  160. package/dist/litellm/toolset.d.ts +55 -0
  161. package/dist/litellm/toolset.d.ts.map +1 -0
  162. package/dist/openbao/index.js +35 -1
  163. package/dist/openbao/index.js.map +3 -3
  164. package/dist/ownership/rows.d.ts +11 -0
  165. package/dist/ownership/rows.d.ts.map +1 -1
  166. package/dist/postgres/connection.d.ts +14 -2
  167. package/dist/postgres/connection.d.ts.map +1 -1
  168. package/dist/postgres/database-sql.d.ts +27 -8
  169. package/dist/postgres/database-sql.d.ts.map +1 -1
  170. package/dist/postgres/fake-grants-parse.d.ts +37 -0
  171. package/dist/postgres/fake-grants-parse.d.ts.map +1 -0
  172. package/dist/postgres/fake-grants-read.d.ts +61 -0
  173. package/dist/postgres/fake-grants-read.d.ts.map +1 -0
  174. package/dist/postgres/fake-grants-sql.d.ts +46 -0
  175. package/dist/postgres/fake-grants-sql.d.ts.map +1 -0
  176. package/dist/postgres/fake-grants-write.d.ts +29 -0
  177. package/dist/postgres/fake-grants-write.d.ts.map +1 -0
  178. package/dist/postgres/fake-role-sql.d.ts +41 -0
  179. package/dist/postgres/fake-role-sql.d.ts.map +1 -0
  180. package/dist/postgres/fake-schema-sql.d.ts +42 -0
  181. package/dist/postgres/fake-schema-sql.d.ts.map +1 -0
  182. package/dist/postgres/fake-sql-parse.d.ts +23 -0
  183. package/dist/postgres/fake-sql-parse.d.ts.map +1 -0
  184. package/dist/postgres/fake-sql-quote.d.ts +12 -0
  185. package/dist/postgres/fake-sql-quote.d.ts.map +1 -0
  186. package/dist/postgres/fake-sql.d.ts +42 -0
  187. package/dist/postgres/fake-sql.d.ts.map +1 -1
  188. package/dist/postgres/grants-attrs.d.ts +115 -0
  189. package/dist/postgres/grants-attrs.d.ts.map +1 -0
  190. package/dist/postgres/grants-declare.d.ts +88 -0
  191. package/dist/postgres/grants-declare.d.ts.map +1 -0
  192. package/dist/postgres/grants-diff.d.ts +25 -0
  193. package/dist/postgres/grants-diff.d.ts.map +1 -0
  194. package/dist/postgres/grants-errors.d.ts +137 -0
  195. package/dist/postgres/grants-errors.d.ts.map +1 -0
  196. package/dist/postgres/grants-existence.d.ts +14 -0
  197. package/dist/postgres/grants-existence.d.ts.map +1 -0
  198. package/dist/postgres/grants-ops.d.ts +65 -0
  199. package/dist/postgres/grants-ops.d.ts.map +1 -0
  200. package/dist/postgres/grants-ownership.d.ts +18 -0
  201. package/dist/postgres/grants-ownership.d.ts.map +1 -0
  202. package/dist/postgres/grants-plan-restore.d.ts +22 -0
  203. package/dist/postgres/grants-plan-restore.d.ts.map +1 -0
  204. package/dist/postgres/grants-plan.d.ts +65 -0
  205. package/dist/postgres/grants-plan.d.ts.map +1 -0
  206. package/dist/postgres/grants-read-defaults.d.ts +17 -0
  207. package/dist/postgres/grants-read-defaults.d.ts.map +1 -0
  208. package/dist/postgres/grants-read.d.ts +77 -0
  209. package/dist/postgres/grants-read.d.ts.map +1 -0
  210. package/dist/postgres/grants-refuse.d.ts +25 -0
  211. package/dist/postgres/grants-refuse.d.ts.map +1 -0
  212. package/dist/postgres/grants-sql.d.ts +42 -0
  213. package/dist/postgres/grants-sql.d.ts.map +1 -0
  214. package/dist/postgres/grants-words.d.ts +29 -0
  215. package/dist/postgres/grants-words.d.ts.map +1 -0
  216. package/dist/postgres/grants.d.ts +37 -0
  217. package/dist/postgres/grants.d.ts.map +1 -0
  218. package/dist/postgres/index.d.ts +31 -6
  219. package/dist/postgres/index.d.ts.map +1 -1
  220. package/dist/postgres/index.js +1998 -37
  221. package/dist/postgres/index.js.map +46 -7
  222. package/dist/postgres/installed-classifier.d.ts +13 -0
  223. package/dist/postgres/installed-classifier.d.ts.map +1 -0
  224. package/dist/postgres/providers.d.ts +16 -8
  225. package/dist/postgres/providers.d.ts.map +1 -1
  226. package/dist/postgres/psql-executor.d.ts +4 -0
  227. package/dist/postgres/psql-executor.d.ts.map +1 -1
  228. package/dist/postgres/role-attrs.d.ts +112 -0
  229. package/dist/postgres/role-attrs.d.ts.map +1 -0
  230. package/dist/postgres/role-diff.d.ts +22 -0
  231. package/dist/postgres/role-diff.d.ts.map +1 -0
  232. package/dist/postgres/role-errors.d.ts +132 -0
  233. package/dist/postgres/role-errors.d.ts.map +1 -0
  234. package/dist/postgres/role-membership-sql.d.ts +78 -0
  235. package/dist/postgres/role-membership-sql.d.ts.map +1 -0
  236. package/dist/postgres/role-provider.d.ts +11 -0
  237. package/dist/postgres/role-provider.d.ts.map +1 -0
  238. package/dist/postgres/role-scram.d.ts +8 -0
  239. package/dist/postgres/role-scram.d.ts.map +1 -0
  240. package/dist/postgres/role-secrets.d.ts +38 -0
  241. package/dist/postgres/role-secrets.d.ts.map +1 -0
  242. package/dist/postgres/role-sql.d.ts +68 -0
  243. package/dist/postgres/role-sql.d.ts.map +1 -0
  244. package/dist/postgres/role.d.ts +57 -0
  245. package/dist/postgres/role.d.ts.map +1 -0
  246. package/dist/postgres/schema-assert.d.ts +50 -0
  247. package/dist/postgres/schema-assert.d.ts.map +1 -0
  248. package/dist/postgres/schema-attrs.d.ts +51 -0
  249. package/dist/postgres/schema-attrs.d.ts.map +1 -0
  250. package/dist/postgres/schema-delete.d.ts +28 -0
  251. package/dist/postgres/schema-delete.d.ts.map +1 -0
  252. package/dist/postgres/schema-diff.d.ts +14 -0
  253. package/dist/postgres/schema-diff.d.ts.map +1 -0
  254. package/dist/postgres/schema-errors.d.ts +139 -0
  255. package/dist/postgres/schema-errors.d.ts.map +1 -0
  256. package/dist/postgres/schema-identity.d.ts +8 -0
  257. package/dist/postgres/schema-identity.d.ts.map +1 -0
  258. package/dist/postgres/schema-reconcile.d.ts +12 -0
  259. package/dist/postgres/schema-reconcile.d.ts.map +1 -0
  260. package/dist/postgres/schema-sql.d.ts +45 -0
  261. package/dist/postgres/schema-sql.d.ts.map +1 -0
  262. package/dist/postgres/schema-test-kit.d.ts +67 -0
  263. package/dist/postgres/schema-test-kit.d.ts.map +1 -0
  264. package/dist/postgres/schema.d.ts +54 -0
  265. package/dist/postgres/schema.d.ts.map +1 -0
  266. package/dist/proxmox/index.js +35 -1
  267. package/dist/proxmox/index.js.map +3 -3
  268. package/dist/release/fake-engine.d.ts +10 -0
  269. package/dist/release/fake-engine.d.ts.map +1 -1
  270. package/dist/release/index.js +35 -1
  271. package/dist/release/index.js.map +3 -3
  272. package/dist/valkey/acl-attrs.d.ts +94 -0
  273. package/dist/valkey/acl-attrs.d.ts.map +1 -0
  274. package/dist/valkey/acl-compare.d.ts +28 -0
  275. package/dist/valkey/acl-compare.d.ts.map +1 -0
  276. package/dist/valkey/acl-connection.d.ts +6 -0
  277. package/dist/valkey/acl-connection.d.ts.map +1 -0
  278. package/dist/valkey/acl-form.d.ts +62 -0
  279. package/dist/valkey/acl-form.d.ts.map +1 -0
  280. package/dist/valkey/acl-managed.d.ts +4 -0
  281. package/dist/valkey/acl-managed.d.ts.map +1 -0
  282. package/dist/valkey/acl-ops.d.ts +37 -0
  283. package/dist/valkey/acl-ops.d.ts.map +1 -0
  284. package/dist/valkey/acl-profiles.d.ts +53 -0
  285. package/dist/valkey/acl-profiles.d.ts.map +1 -0
  286. package/dist/valkey/acl-reconcile.d.ts +26 -0
  287. package/dist/valkey/acl-reconcile.d.ts.map +1 -0
  288. package/dist/valkey/acl.d.ts +24 -0
  289. package/dist/valkey/acl.d.ts.map +1 -0
  290. package/dist/valkey/connection-service.d.ts +22 -0
  291. package/dist/valkey/connection-service.d.ts.map +1 -0
  292. package/dist/valkey/connection.d.ts +59 -0
  293. package/dist/valkey/connection.d.ts.map +1 -0
  294. package/dist/valkey/errors.d.ts +165 -0
  295. package/dist/valkey/errors.d.ts.map +1 -0
  296. package/dist/valkey/fake-acl.d.ts +29 -0
  297. package/dist/valkey/fake-acl.d.ts.map +1 -0
  298. package/dist/valkey/fake-valkey.d.ts +35 -0
  299. package/dist/valkey/fake-valkey.d.ts.map +1 -0
  300. package/dist/valkey/handler-test-fixture.d.ts +20 -0
  301. package/dist/valkey/handler-test-fixture.d.ts.map +1 -0
  302. package/dist/valkey/index.d.ts +18 -0
  303. package/dist/valkey/index.d.ts.map +1 -0
  304. package/dist/valkey/index.js +964 -0
  305. package/dist/valkey/index.js.map +27 -0
  306. package/dist/valkey/instance-attrs.d.ts +46 -0
  307. package/dist/valkey/instance-attrs.d.ts.map +1 -0
  308. package/dist/valkey/instance-form.d.ts +22 -0
  309. package/dist/valkey/instance-form.d.ts.map +1 -0
  310. package/dist/valkey/instance.d.ts +48 -0
  311. package/dist/valkey/instance.d.ts.map +1 -0
  312. package/dist/valkey/provider-socket-fixture.d.ts +8 -0
  313. package/dist/valkey/provider-socket-fixture.d.ts.map +1 -0
  314. package/dist/valkey/providers.d.ts +16 -0
  315. package/dist/valkey/providers.d.ts.map +1 -0
  316. package/dist/valkey/resp.d.ts +38 -0
  317. package/dist/valkey/resp.d.ts.map +1 -0
  318. package/dist/valkey/transport-error.d.ts +36 -0
  319. package/dist/valkey/transport-error.d.ts.map +1 -0
  320. package/dist/valkey/transport.d.ts +50 -0
  321. package/dist/valkey/transport.d.ts.map +1 -0
  322. package/docs/litellm-access-group.md +105 -0
  323. package/docs/litellm-credential.md +60 -0
  324. package/docs/litellm-key-metadata.md +56 -0
  325. package/docs/litellm-key.md +194 -0
  326. package/docs/litellm-mcp.md +187 -0
  327. package/docs/litellm-model.md +111 -0
  328. package/docs/litellm-policy-attachment.md +86 -0
  329. package/docs/litellm-policy.md +103 -0
  330. package/docs/litellm-team.md +117 -0
  331. package/docs/litellm-tool-policy.md +90 -0
  332. package/docs/litellm-toolset.md +92 -0
  333. package/docs/litellm.md +16 -9
  334. package/docs/peers.md +15 -6
  335. package/docs/postgres-grants-example.md +55 -0
  336. package/docs/postgres-grants.md +157 -0
  337. package/docs/postgres-role.md +126 -0
  338. package/docs/postgres-schema.md +139 -0
  339. package/docs/postgres.md +20 -3
  340. package/docs/valkey-transport.md +29 -0
  341. package/docs/valkey.md +187 -0
  342. package/package.json +6 -2
  343. package/src/ceph/ceph-argv.test.ts +1 -1
  344. package/src/launchd/sudo-allowlist.test.ts +2 -2
  345. package/src/linux/sudo-allowlist.test.ts +3 -3
  346. package/src/linux/sudo-runner.test.ts +2 -2
  347. package/src/litellm/access-group-form.ts +105 -0
  348. package/src/litellm/access-group-operations.ts +92 -0
  349. package/src/litellm/access-group-types.ts +49 -0
  350. package/src/litellm/access-group.test.ts +197 -0
  351. package/src/litellm/access-group.ts +151 -0
  352. package/src/litellm/credential-errors.ts +183 -0
  353. package/src/litellm/credential-form.test.ts +151 -0
  354. package/src/litellm/credential-form.ts +211 -0
  355. package/src/litellm/credential-guards.test.ts +241 -0
  356. package/src/litellm/credential-operations.ts +208 -0
  357. package/src/litellm/credential-recovery.test.ts +93 -0
  358. package/src/litellm/credential-rewrite.test.ts +164 -0
  359. package/src/litellm/credential-rewrite.ts +50 -0
  360. package/src/litellm/credential-types.ts +117 -0
  361. package/src/litellm/credential-values.ts +94 -0
  362. package/src/litellm/credential.test.ts +218 -0
  363. package/src/litellm/credential.ts +227 -0
  364. package/src/litellm/fake-access-group-litellm.ts +127 -0
  365. package/src/litellm/fake-credential-litellm.ts +216 -0
  366. package/src/litellm/fake-keys.ts +190 -0
  367. package/src/litellm/fake-litellm.ts +19 -9
  368. package/src/litellm/fake-mcp-litellm.ts +214 -0
  369. package/src/litellm/fake-model-litellm-post-update.ts +103 -0
  370. package/src/litellm/fake-model-litellm.ts +233 -0
  371. package/src/litellm/fake-policy-attachment-litellm.ts +97 -0
  372. package/src/litellm/fake-policy-litellm.ts +186 -0
  373. package/src/litellm/fake-registry-base.ts +69 -0
  374. package/src/litellm/fake-stack.ts +17 -1
  375. package/src/litellm/fake-team-litellm.ts +229 -0
  376. package/src/litellm/fake-tool-litellm.ts +88 -0
  377. package/src/litellm/fake-toolset-litellm.ts +110 -0
  378. package/src/litellm/index.ts +140 -0
  379. package/src/litellm/key-delete.test.ts +212 -0
  380. package/src/litellm/key-errors.ts +241 -0
  381. package/src/litellm/key-form.ts +200 -0
  382. package/src/litellm/key-harness.ts +121 -0
  383. package/src/litellm/key-metadata-errors.ts +49 -0
  384. package/src/litellm/key-metadata.test.ts +156 -0
  385. package/src/litellm/key-metadata.ts +74 -0
  386. package/src/litellm/key-operations.ts +184 -0
  387. package/src/litellm/key-rotation.test.ts +110 -0
  388. package/src/litellm/key-scope.test.ts +135 -0
  389. package/src/litellm/key-secret.test.ts +248 -0
  390. package/src/litellm/key-secret.ts +137 -0
  391. package/src/litellm/key-transport.test.ts +166 -0
  392. package/src/litellm/key.test.ts +231 -0
  393. package/src/litellm/key.ts +213 -0
  394. package/src/litellm/mcp-server-adopt.test.ts +86 -0
  395. package/src/litellm/mcp-server-alias.test.ts +184 -0
  396. package/src/litellm/mcp-server-credential.ts +85 -0
  397. package/src/litellm/mcp-server-errors.ts +141 -0
  398. package/src/litellm/mcp-server-exports.test.ts +15 -0
  399. package/src/litellm/mcp-server-form.test.ts +241 -0
  400. package/src/litellm/mcp-server-form.ts +233 -0
  401. package/src/litellm/mcp-server-handlers.test.ts +150 -0
  402. package/src/litellm/mcp-server-locate.ts +66 -0
  403. package/src/litellm/mcp-server-operations.ts +111 -0
  404. package/src/litellm/mcp-server-registry.test.ts +146 -0
  405. package/src/litellm/mcp-server-retype.test.ts +114 -0
  406. package/src/litellm/mcp-server-shadow.test.ts +91 -0
  407. package/src/litellm/mcp-server-shadow.ts +45 -0
  408. package/src/litellm/mcp-server-tools.test.ts +85 -0
  409. package/src/litellm/mcp-server-types.ts +143 -0
  410. package/src/litellm/mcp-server-url.ts +66 -0
  411. package/src/litellm/mcp-server.test.ts +213 -0
  412. package/src/litellm/mcp-server.ts +225 -0
  413. package/src/litellm/model-claim.ts +69 -0
  414. package/src/litellm/model-credential.ts +45 -0
  415. package/src/litellm/model-errors.ts +168 -0
  416. package/src/litellm/model-foreign-row.test.ts +173 -0
  417. package/src/litellm/model-form.test.ts +228 -0
  418. package/src/litellm/model-form.ts +223 -0
  419. package/src/litellm/model-locate.test.ts +128 -0
  420. package/src/litellm/model-locate.ts +67 -0
  421. package/src/litellm/model-operations.test.ts +93 -0
  422. package/src/litellm/model-operations.ts +146 -0
  423. package/src/litellm/model-params-preserve.test.ts +119 -0
  424. package/src/litellm/model-recovery.test.ts +57 -0
  425. package/src/litellm/model-types.ts +112 -0
  426. package/src/litellm/model.test.ts +222 -0
  427. package/src/litellm/model.ts +237 -0
  428. package/src/litellm/policy-attachment-form.ts +103 -0
  429. package/src/litellm/policy-attachment-operations.ts +74 -0
  430. package/src/litellm/policy-attachment-types.ts +48 -0
  431. package/src/litellm/policy-attachment.test.ts +198 -0
  432. package/src/litellm/policy-attachment.ts +178 -0
  433. package/src/litellm/policy-form.ts +122 -0
  434. package/src/litellm/policy-operations.ts +112 -0
  435. package/src/litellm/policy-types.ts +58 -0
  436. package/src/litellm/policy.test.ts +214 -0
  437. package/src/litellm/policy.ts +146 -0
  438. package/src/litellm/providers.ts +24 -3
  439. package/src/litellm/registry-errors.ts +88 -0
  440. package/src/litellm/registry-exports.test.ts +66 -0
  441. package/src/litellm/registry-support.ts +109 -0
  442. package/src/litellm/team-form.ts +140 -0
  443. package/src/litellm/team-members.test.ts +150 -0
  444. package/src/litellm/team-members.ts +58 -0
  445. package/src/litellm/team-operations.ts +90 -0
  446. package/src/litellm/team-permission.ts +159 -0
  447. package/src/litellm/team-read.test.ts +89 -0
  448. package/src/litellm/team-types.ts +106 -0
  449. package/src/litellm/team.test.ts +206 -0
  450. package/src/litellm/team.ts +159 -0
  451. package/src/litellm/tool-policy-form.ts +94 -0
  452. package/src/litellm/tool-policy-operations.ts +58 -0
  453. package/src/litellm/tool-policy-types.ts +48 -0
  454. package/src/litellm/tool-policy.test.ts +172 -0
  455. package/src/litellm/tool-policy.ts +125 -0
  456. package/src/litellm/toolset-form.ts +104 -0
  457. package/src/litellm/toolset-operations.ts +90 -0
  458. package/src/litellm/toolset-types.ts +47 -0
  459. package/src/litellm/toolset.test.ts +198 -0
  460. package/src/litellm/toolset.ts +151 -0
  461. package/src/ownership/ownership.test.ts +33 -1
  462. package/src/ownership/rows.ts +53 -0
  463. package/src/postgres/connection.ts +42 -7
  464. package/src/postgres/database-bigint-serialization.test.ts +1 -0
  465. package/src/postgres/database-refusals.test.ts +2 -2
  466. package/src/postgres/database-sql.ts +36 -9
  467. package/src/postgres/fake-grants-parse.ts +189 -0
  468. package/src/postgres/fake-grants-read.ts +250 -0
  469. package/src/postgres/fake-grants-sql.ts +207 -0
  470. package/src/postgres/fake-grants-write.ts +90 -0
  471. package/src/postgres/fake-role-sql.ts +240 -0
  472. package/src/postgres/fake-schema-semantics.test.ts +36 -0
  473. package/src/postgres/fake-schema-sql.ts +146 -0
  474. package/src/postgres/fake-sql-parse.ts +86 -0
  475. package/src/postgres/fake-sql-quote.ts +36 -0
  476. package/src/postgres/fake-sql.ts +166 -46
  477. package/src/postgres/fixtures/pg-REL_18_6-acl.h.txt +147 -0
  478. package/src/postgres/fixtures/pg-REL_18_6-aclexplode-func.txt +31 -0
  479. package/src/postgres/fixtures/pg-REL_18_6-alter-default-privileges-synopsis.txt +82 -0
  480. package/src/postgres/fixtures/pg-REL_18_6-alter_role.sgml.txt +44 -0
  481. package/src/postgres/fixtures/pg-REL_18_6-create_role.sgml.txt +26 -0
  482. package/src/postgres/fixtures/pg-REL_18_6-grant-synopsis.txt +95 -0
  483. package/src/postgres/fixtures/pg-REL_18_6-pg_attribute.h.txt +24 -0
  484. package/src/postgres/fixtures/pg-REL_18_6-pg_auth_members.h.txt +62 -0
  485. package/src/postgres/fixtures/pg-REL_18_6-pg_authid.h.txt +70 -0
  486. package/src/postgres/fixtures/pg-REL_18_6-pg_class.h.txt +33 -0
  487. package/src/postgres/fixtures/pg-REL_18_6-pg_default_acl.h.txt +81 -0
  488. package/src/postgres/fixtures/pg-REL_18_6-pg_namespace.h.txt +28 -0
  489. package/src/postgres/fixtures/pg-REL_18_6-revoke-synopsis.txt +124 -0
  490. package/src/postgres/grants-acl.test.ts +61 -0
  491. package/src/postgres/grants-attrs.ts +185 -0
  492. package/src/postgres/grants-database.test.ts +158 -0
  493. package/src/postgres/grants-declare.ts +172 -0
  494. package/src/postgres/grants-delete-proof.test.ts +154 -0
  495. package/src/postgres/grants-diff.ts +101 -0
  496. package/src/postgres/grants-errors.ts +215 -0
  497. package/src/postgres/grants-existence-guards.test.ts +113 -0
  498. package/src/postgres/grants-existence.ts +101 -0
  499. package/src/postgres/grants-lifecycle-guards.test.ts +208 -0
  500. package/src/postgres/grants-lifecycle-repair.test.ts +208 -0
  501. package/src/postgres/grants-lifecycle.test.ts +181 -0
  502. package/src/postgres/grants-ops.ts +229 -0
  503. package/src/postgres/grants-owner-revoke.test.ts +121 -0
  504. package/src/postgres/grants-ownership.ts +49 -0
  505. package/src/postgres/grants-plan-collateral.test.ts +202 -0
  506. package/src/postgres/grants-plan-diff.test.ts +204 -0
  507. package/src/postgres/grants-plan-restore.ts +43 -0
  508. package/src/postgres/grants-plan-revocations.test.ts +69 -0
  509. package/src/postgres/grants-plan.test.ts +148 -0
  510. package/src/postgres/grants-plan.ts +245 -0
  511. package/src/postgres/grants-provenance.test.ts +134 -0
  512. package/src/postgres/grants-psql-lifecycle.test.ts +105 -0
  513. package/src/postgres/grants-read-absent.test.ts +91 -0
  514. package/src/postgres/grants-read-defaults.ts +51 -0
  515. package/src/postgres/grants-read.ts +250 -0
  516. package/src/postgres/grants-refusals.test.ts +136 -0
  517. package/src/postgres/grants-refuse.ts +119 -0
  518. package/src/postgres/grants-relkind-wire.test.ts +111 -0
  519. package/src/postgres/grants-repair-plan.test.ts +201 -0
  520. package/src/postgres/grants-sql.test.ts +128 -0
  521. package/src/postgres/grants-sql.ts +144 -0
  522. package/src/postgres/grants-words.ts +34 -0
  523. package/src/postgres/grants.ts +110 -0
  524. package/src/postgres/index.ts +129 -5
  525. package/src/postgres/installed-classifier.ts +36 -0
  526. package/src/postgres/providers.ts +33 -9
  527. package/src/postgres/psql-executor-escaping.test.ts +67 -0
  528. package/src/postgres/psql-executor.test.ts +63 -2
  529. package/src/postgres/psql-executor.ts +74 -34
  530. package/src/postgres/role-adopt.test.ts +98 -0
  531. package/src/postgres/role-attrs.ts +137 -0
  532. package/src/postgres/role-diff.ts +93 -0
  533. package/src/postgres/role-errors.ts +206 -0
  534. package/src/postgres/role-guard.test.ts +60 -0
  535. package/src/postgres/role-identity.test.ts +197 -0
  536. package/src/postgres/role-lifecycle.test.ts +228 -0
  537. package/src/postgres/role-membership-options.test.ts +73 -0
  538. package/src/postgres/role-membership-repair.test.ts +153 -0
  539. package/src/postgres/role-membership-sql.ts +223 -0
  540. package/src/postgres/role-password-ascii.test.ts +53 -0
  541. package/src/postgres/role-password-transports.test.ts +123 -0
  542. package/src/postgres/role-password.test.ts +158 -0
  543. package/src/postgres/role-privilege.test.ts +107 -0
  544. package/src/postgres/role-provenance.test.ts +200 -0
  545. package/src/postgres/role-provider.ts +105 -0
  546. package/src/postgres/role-refusals.test.ts +225 -0
  547. package/src/postgres/role-scram.test.ts +38 -0
  548. package/src/postgres/role-scram.ts +40 -0
  549. package/src/postgres/role-secrets.ts +61 -0
  550. package/src/postgres/role-sql.ts +213 -0
  551. package/src/postgres/role-valid-until.test.ts +68 -0
  552. package/src/postgres/role.ts +226 -0
  553. package/src/postgres/schema-assert.ts +139 -0
  554. package/src/postgres/schema-attrs.ts +71 -0
  555. package/src/postgres/schema-delete-proofs.test.ts +192 -0
  556. package/src/postgres/schema-delete.ts +96 -0
  557. package/src/postgres/schema-diff.ts +44 -0
  558. package/src/postgres/schema-drop-2bp01.test.ts +146 -0
  559. package/src/postgres/schema-errors.ts +209 -0
  560. package/src/postgres/schema-handlers.test.ts +193 -0
  561. package/src/postgres/schema-identity.ts +39 -0
  562. package/src/postgres/schema-lifecycle.test.ts +246 -0
  563. package/src/postgres/schema-race.test.ts +70 -0
  564. package/src/postgres/schema-reconcile.ts +100 -0
  565. package/src/postgres/schema-refusals.test.ts +144 -0
  566. package/src/postgres/schema-socket.test.ts +162 -0
  567. package/src/postgres/schema-sql.ts +130 -0
  568. package/src/postgres/schema-takeover.test.ts +149 -0
  569. package/src/postgres/schema-test-kit.ts +85 -0
  570. package/src/postgres/schema.ts +130 -0
  571. package/src/release/binary-alias.test.ts +3 -3
  572. package/src/release/binary-claims.test.ts +3 -3
  573. package/src/release/binary-directory-umask.test.ts +65 -0
  574. package/src/release/fake-engine.ts +15 -0
  575. package/src/valkey/acl-attrs.ts +98 -0
  576. package/src/valkey/acl-compare.ts +57 -0
  577. package/src/valkey/acl-connection.ts +13 -0
  578. package/src/valkey/acl-delete.test.ts +127 -0
  579. package/src/valkey/acl-form.ts +239 -0
  580. package/src/valkey/acl-managed.ts +13 -0
  581. package/src/valkey/acl-ops.ts +122 -0
  582. package/src/valkey/acl-ownership.test.ts +118 -0
  583. package/src/valkey/acl-prefix.test.ts +38 -0
  584. package/src/valkey/acl-profiles.ts +81 -0
  585. package/src/valkey/acl-reconcile.ts +180 -0
  586. package/src/valkey/acl-reserved.test.ts +69 -0
  587. package/src/valkey/acl-revocation.test.ts +94 -0
  588. package/src/valkey/acl-seat-prefix.test.ts +111 -0
  589. package/src/valkey/acl-validation.test.ts +54 -0
  590. package/src/valkey/acl.test.ts +215 -0
  591. package/src/valkey/acl.ts +169 -0
  592. package/src/valkey/connection-service.ts +46 -0
  593. package/src/valkey/connection.ts +180 -0
  594. package/src/valkey/errors.ts +239 -0
  595. package/src/valkey/fake-acl.ts +128 -0
  596. package/src/valkey/fake-valkey.ts +224 -0
  597. package/src/valkey/handler-test-fixture.ts +43 -0
  598. package/src/valkey/handlers.test.ts +205 -0
  599. package/src/valkey/index.ts +54 -0
  600. package/src/valkey/instance-attrs.ts +48 -0
  601. package/src/valkey/instance-form.ts +104 -0
  602. package/src/valkey/instance.test.ts +108 -0
  603. package/src/valkey/instance.ts +160 -0
  604. package/src/valkey/provider-socket-fixture.ts +71 -0
  605. package/src/valkey/providers.test.ts +129 -0
  606. package/src/valkey/providers.ts +21 -0
  607. package/src/valkey/resp.ts +212 -0
  608. package/src/valkey/transport-bounds.test.ts +150 -0
  609. package/src/valkey/transport-error.ts +37 -0
  610. package/src/valkey/transport.test.ts +158 -0
  611. package/src/valkey/transport.ts +109 -0
  612. package/src/valkey/upstream-bounds.test.ts +14 -0
@@ -0,0 +1,964 @@
1
+ // src/valkey/acl.ts
2
+ import { Resource } from "alchemy";
3
+ import { Unowned } from "alchemy/AdoptPolicy";
4
+ import { isResolved } from "alchemy/Diff";
5
+ import * as Provider from "alchemy/Provider";
6
+ import * as Effect9 from "effect/Effect";
7
+
8
+ // src/valkey/acl-form.ts
9
+ import { sha256 } from "alchemy/Util/sha256";
10
+ import * as Effect from "effect/Effect";
11
+
12
+ // src/valkey/acl-profiles.ts
13
+ var SEAT_COMMANDS = "+@read +@write +@string +@hash +@list +@set +@sortedset +@stream +@pubsub +@connection " + "+@transaction -@dangerous -@admin -keys -flushall -flushdb -monitor -acl -config " + "-shutdown -debug";
14
+ var DENY = "-scan -randomkey -dbsize -pubsub";
15
+ var MONITOR_COMMANDS = "-@all +ping +client|setname +info +command|info +commandlog|len +config|get " + "+latency|latest +latency|histogram +slowlog|get +slowlog|len";
16
+ var SEAT_RULES = [...SEAT_COMMANDS.split(" "), ...DENY.split(" ")];
17
+ var SERVICE_RULES = ["+@all", "-@dangerous", ...DENY.split(" ")];
18
+ var MONITOR_RULES = MONITOR_COMMANDS.split(" ");
19
+ var profileRules = (profile) => profile === "seat" ? SEAT_RULES : profile === "service" ? SERVICE_RULES : MONITOR_RULES;
20
+ var effectiveKeyPrefix = (user) => user.profile === "monitor" ? "" : user.profile === "seat" ? user.keyPrefix ?? `${user.name}:*` : user.keyPrefix ?? "*";
21
+ var declaredKeyPatterns = (user) => {
22
+ const prefix = effectiveKeyPrefix(user);
23
+ return prefix === "" ? [] : [`~${prefix}`];
24
+ };
25
+ var declaredChannels = (user) => {
26
+ if (user.profile === "monitor")
27
+ return [];
28
+ const prefix = effectiveKeyPrefix(user);
29
+ return (user.channelPatterns ?? [prefix]).map((pattern) => `&${pattern}`);
30
+ };
31
+
32
+ // src/valkey/errors.ts
33
+ import * as Data from "effect/Data";
34
+
35
+ class ValkeyInstanceDrift extends Data.TaggedError("ValkeyInstanceDrift") {
36
+ get message() {
37
+ return `Valkey.Instance "${this.instance}": ${this.prop} is declared as ` + `${JSON.stringify(this.declared)} but the live instance has ${JSON.stringify(this.live)}. ` + "Update the declaration to match the live value, or change it by hand and re-plan.";
38
+ }
39
+ }
40
+
41
+ class ValkeyInstanceUnreachable extends Data.TaggedError("ValkeyInstanceUnreachable") {
42
+ get message() {
43
+ return `Valkey.Instance "${this.instance}" at ${this.host === undefined ? "" : `${this.host}:`}` + `${String(this.port)}: could not verify the instance. Check that the Quadlet container is ` + "running and the ACL/password is correct.";
44
+ }
45
+ }
46
+
47
+ class ValkeyAclParseError extends Data.TaggedError("ValkeyAclParseError") {
48
+ get message() {
49
+ return "Valkey.AclFile: cannot parse an ACL LIST line. The line is withheld from this message " + "because it can carry a password hash.";
50
+ }
51
+ }
52
+
53
+ class ValkeyAclPasswordMissing extends Data.TaggedError("ValkeyAclPasswordMissing") {
54
+ get message() {
55
+ return `Valkey.AclFile "${this.instance}": ACL user "${this.user}" references environment ` + `variable ${this.variable}, which is missing or empty at call time.`;
56
+ }
57
+ }
58
+
59
+ class ValkeyAuthPasswordMissing extends Data.TaggedError("ValkeyAuthPasswordMissing") {
60
+ get message() {
61
+ const who = this.username === undefined ? "" : ` as "${this.username}"`;
62
+ return `Valkey connection${who}: password environment variable ${this.variable} is missing or ` + "empty at call time. Render the secret into the deploying process environment and re-plan.";
63
+ }
64
+ }
65
+
66
+ class ValkeyAclReadbackFailed extends Data.TaggedError("ValkeyAclReadbackFailed") {
67
+ get message() {
68
+ return `Valkey.AclFile "${this.instance}": ACL reconciliation for "${this.user}" reported success, ` + "but readback contradicts the declared rules or removal. Re-plan.";
69
+ }
70
+ }
71
+
72
+ class ValkeyAclSeatKeyPrefix extends Data.TaggedError("ValkeyAclSeatKeyPrefix") {
73
+ get message() {
74
+ return `Valkey.AclFile "${this.instance}": ACL user "${this.user}" declares key prefix ` + `"${this.keyPrefix}". A seat user is limited to "${this.user}:*"; a user that owns ` + 'every key on the instance declares profile "service".';
75
+ }
76
+ }
77
+
78
+ class ValkeyAclReservedUser extends Data.TaggedError("ValkeyAclReservedUser") {
79
+ get message() {
80
+ return `Valkey.AclFile "${this.instance}": refusing to manage ACL user "${this.user}". ` + "That name is `default` or the connection username. ACL SETUSER reset would replace the " + "credential this kit authenticates with, and the next ACL LIST would answer NOPERM.";
81
+ }
82
+ }
83
+
84
+ class ValkeyAclUserNameMismatch extends Data.TaggedError("ValkeyAclUserNameMismatch") {
85
+ get message() {
86
+ return `Valkey.AclFile "${this.instance}": ACL user "${this.user}" was found keyed under ` + `"${this.recordKey}". This family keys every user by its own name; re-plan or fix the ` + "ACL by hand on the instance.";
87
+ }
88
+ }
89
+
90
+ class ValkeyAclMonitorKeyPrefix extends Data.TaggedError("ValkeyAclMonitorKeyPrefix") {
91
+ get message() {
92
+ return `Valkey.AclFile "${this.instance}": ACL user "${this.user}" declares profile "monitor" ` + `with key prefix "${this.keyPrefix}". The monitor profile is key-less (resetkeys); omit ` + "the keyPrefix.";
93
+ }
94
+ }
95
+
96
+ class ValkeyAclNameGlob extends Data.TaggedError("ValkeyAclNameGlob") {
97
+ get message() {
98
+ return `Valkey.AclFile "${this.instance}": ACL user "${this.user}" contains glob characters ` + `(${this.chars}). A name is interpolated into key and channel patterns, so a glob would ` + "widen the isolation the profile fixes. Use a glob-free name.";
99
+ }
100
+ }
101
+
102
+ class ValkeyAclFileRendered extends Data.TaggedError("ValkeyAclFileRendered") {
103
+ get message() {
104
+ return `Valkey.AclFile "${this.instance}": the instance loads its ACL from "${this.path}" ` + "(CONFIG GET aclfile), so the file — not this family — is the source of truth. The kit " + "speaks RESP only and can neither write that file nor survive the renderer that owns it; " + "a runtime ACL SETUSER there is reverted on the next render or restart. Declare the users " + "in the rendering template. Adoption also reconciles and is refused. ACL reads require " + "ACL LIST permission, which CT100 rendered users do not have.";
105
+ }
106
+ }
107
+
108
+ class ValkeyAclChannelPatterns extends Data.TaggedError("ValkeyAclChannelPatterns") {
109
+ get message() {
110
+ return `Valkey.AclFile "${this.instance}": invalid channel patterns for "${this.user}". ` + "Seats require <name>:*; monitors require no channels.";
111
+ }
112
+ }
113
+
114
+ // src/secrets/write-only.ts
115
+ import { Buffer as Buffer2 } from "node:buffer";
116
+ import { randomBytes, scryptSync, timingSafeEqual } from "node:crypto";
117
+ var resolveAll = (refs, env = process.env) => {
118
+ const values = {};
119
+ const missing = [];
120
+ for (const [key, ref] of Object.entries(refs)) {
121
+ const value = env[ref.fromEnv];
122
+ if (value === undefined || value === "")
123
+ missing.push(ref.fromEnv);
124
+ else
125
+ values[key] = value;
126
+ }
127
+ return { missing: [...new Set(missing)].sort(), values };
128
+ };
129
+ var COST = { N: 16384, maxmem: 64 * 1024 * 1024, p: 1, r: 8 };
130
+ var PREFIX = "scrypt";
131
+ var canonical = (values) => JSON.stringify(Object.keys(values).sort().map((key) => [key, values[key]]));
132
+ var digest = (salt, values) => scryptSync(canonical(values), salt, 32, COST);
133
+ var seal = (values, salt) => {
134
+ if (Object.keys(values).length === 0)
135
+ return "";
136
+ const bytes = salt === undefined ? randomBytes(16) : Buffer2.from(salt, "utf8");
137
+ return `${PREFIX}:${bytes.toString("base64url")}:${digest(bytes, values).toString("base64url")}`;
138
+ };
139
+ var sealMatches = (sealed, values) => {
140
+ if (sealed === "")
141
+ return Object.keys(values).length === 0;
142
+ const [prefix, salt, stored, extra] = sealed.split(":");
143
+ if (prefix !== PREFIX || salt === undefined || stored === undefined || extra !== undefined) {
144
+ return false;
145
+ }
146
+ const expected = Buffer2.from(stored, "base64url");
147
+ const actual = digest(Buffer2.from(salt, "base64url"), values);
148
+ return expected.length === actual.length && timingSafeEqual(expected, actual);
149
+ };
150
+
151
+ // src/valkey/acl-compare.ts
152
+ var sameSet = (a, b) => {
153
+ if (a.length !== b.length)
154
+ return false;
155
+ const sa = new Set(a);
156
+ const sb = new Set(b);
157
+ if (sa.size !== sb.size)
158
+ return false;
159
+ for (const x of sa)
160
+ if (!sb.has(x))
161
+ return false;
162
+ return true;
163
+ };
164
+ var inferProfile = (rules) => {
165
+ const normalised = rules.filter((rule) => rule !== "-@all");
166
+ if (sameSet(normalised, SEAT_RULES))
167
+ return "seat";
168
+ if (sameSet(normalised, SERVICE_RULES))
169
+ return "service";
170
+ if (sameSet(rules, MONITOR_RULES))
171
+ return "monitor";
172
+ return "unrecognized";
173
+ };
174
+ var matchesDeclared = (live, user) => live.name === user.name && live.on && !live.nopass && live.hasPassword && sameSet(live.keyPatterns, declaredKeyPatterns(user)) && sameSet(live.channelPatterns, declaredChannels(user)) && inferProfile(live.rules) === user.profile;
175
+
176
+ // src/valkey/acl-form.ts
177
+ var NAME_GLOB = /[*?[\]\\]/;
178
+ var passwordToken = (password) => Effect.map(sha256(password), (hash) => `#${hash}`);
179
+ var buildSetUserArgs = (user, password) => Effect.map(passwordToken(password), (token) => [
180
+ "ACL",
181
+ "SETUSER",
182
+ user.name,
183
+ "reset",
184
+ "on",
185
+ token,
186
+ "resetchannels",
187
+ ...declaredChannels(user),
188
+ ...declaredKeyPatterns(user),
189
+ ...profileRules(user.profile)
190
+ ]);
191
+ var MARKER_TOKENS = new Set(["resetchannels", "resetkeys", "resetpass", "reseton", "resetoff"]);
192
+ var parseAclLine = (line) => {
193
+ const parts = line.split(" ");
194
+ if (parts[0] !== "user" || parts[1] === undefined || parts[1] === "") {
195
+ throw new ValkeyAclParseError;
196
+ }
197
+ const on = parts[2] === "on";
198
+ const nopass = parts.includes("nopass");
199
+ const keyPatterns = [];
200
+ const channelPatterns = [];
201
+ const rules = [];
202
+ let hasPassword = false;
203
+ for (const part of parts.slice(2)) {
204
+ if (part.startsWith("~"))
205
+ keyPatterns.push(part);
206
+ else if (part.startsWith("&"))
207
+ channelPatterns.push(part);
208
+ else if (part.startsWith(">") || part.startsWith("<") || part.startsWith("#"))
209
+ hasPassword = true;
210
+ else if (part.startsWith("+") || part.startsWith("-"))
211
+ rules.push(part);
212
+ else if (MARKER_TOKENS.has(part))
213
+ continue;
214
+ }
215
+ return { name: parts[1], on, nopass, hasPassword, keyPatterns, channelPatterns, rules };
216
+ };
217
+ var seatKeyPrefixEscapes = (user) => user.profile === "seat" && (user.keyPrefix ?? `${user.name}:*`) !== `${user.name}:*`;
218
+ var refusalBeforeWrite = (instance, users, self) => {
219
+ for (const [key, user] of Object.entries(users)) {
220
+ if (user.name !== key) {
221
+ return new ValkeyAclUserNameMismatch({ instance, recordKey: key, user: user.name });
222
+ }
223
+ if (user.name === "default" || user.name === self) {
224
+ return new ValkeyAclReservedUser({ instance, user: user.name });
225
+ }
226
+ const glob = NAME_GLOB.exec(user.name);
227
+ if (glob !== null) {
228
+ return new ValkeyAclNameGlob({ instance, user: user.name, chars: glob[0] });
229
+ }
230
+ if (seatKeyPrefixEscapes(user)) {
231
+ return new ValkeyAclSeatKeyPrefix({
232
+ instance,
233
+ user: user.name,
234
+ keyPrefix: user.keyPrefix ?? `${user.name}:*`
235
+ });
236
+ }
237
+ if (user.channelPatterns !== undefined && (user.profile === "monitor" && user.channelPatterns.length > 0 || user.profile === "seat" && (user.channelPatterns.length !== 1 || user.channelPatterns[0] !== `${user.name}:*`)))
238
+ return new ValkeyAclChannelPatterns({ instance, user: user.name });
239
+ if (user.profile === "monitor" && user.keyPrefix !== undefined) {
240
+ return new ValkeyAclMonitorKeyPrefix({
241
+ instance,
242
+ user: user.name,
243
+ keyPrefix: user.keyPrefix
244
+ });
245
+ }
246
+ }
247
+ return;
248
+ };
249
+ var passwordState = (sealed, value) => {
250
+ if (value === undefined)
251
+ return "unknown";
252
+ if (sealed === "")
253
+ return "stale";
254
+ return sealMatches(sealed, { password: value }) ? "match" : "stale";
255
+ };
256
+ var planAclUsers = (declared, live, exclusive = false, managed = []) => {
257
+ const create = [];
258
+ const update = [];
259
+ const undeclared = [];
260
+ for (const [name, user] of Object.entries(declared)) {
261
+ const liveUser = live[name];
262
+ if (liveUser === undefined)
263
+ create.push(user);
264
+ else if (!matchesDeclared(liveUser, user))
265
+ update.push(user);
266
+ }
267
+ for (const name of Object.keys(live)) {
268
+ if (declared[name] === undefined)
269
+ undeclared.push(name);
270
+ }
271
+ return {
272
+ create,
273
+ update,
274
+ remove: exclusive ? undeclared : undeclared.filter((name) => managed.includes(name)),
275
+ undeclared
276
+ };
277
+ };
278
+ var buildDelUserArgs = (users) => [
279
+ "ACL",
280
+ "DELUSER",
281
+ ...users
282
+ ];
283
+
284
+ // src/valkey/acl-connection.ts
285
+ import * as Effect3 from "effect/Effect";
286
+
287
+ // src/valkey/connection-service.ts
288
+ import * as Context from "effect/Context";
289
+ import * as Data2 from "effect/Data";
290
+ import * as Effect2 from "effect/Effect";
291
+ import * as Layer from "effect/Layer";
292
+ import * as Option from "effect/Option";
293
+
294
+ class ValkeyConnectionMissing extends Data2.TaggedError("ValkeyConnectionMissing") {
295
+ get message() {
296
+ return `Valkey connection for "${this.instance}" is missing; configure that instance in valkeyProviders.`;
297
+ }
298
+ }
299
+
300
+ class ValkeyConnection extends Context.Service()("Valkey.Connection") {
301
+ }
302
+ var connectionService = (instance) => instance === undefined ? ValkeyConnection : Context.Service(`Valkey.Connection:${instance}`);
303
+ var valkeyConnection = (config) => Layer.succeed(connectionService(config.instance), Effect2.succeed(config));
304
+ var resolveValkeyConnection = (instance) => Effect2.gen(function* () {
305
+ const service = yield* Effect2.serviceOption(connectionService(instance));
306
+ if (Option.isNone(service)) {
307
+ return yield* Effect2.fail(new ValkeyConnectionMissing({ instance: instance ?? "<unnamed>" }));
308
+ }
309
+ return yield* service.value;
310
+ });
311
+
312
+ // src/valkey/acl-connection.ts
313
+ var aclUnreachable = (instance) => (_error) => Effect3.gen(function* () {
314
+ const config = yield* resolveValkeyConnection(instance);
315
+ return yield* Effect3.fail(new ValkeyInstanceUnreachable({ instance, host: config.host, port: config.port }));
316
+ });
317
+
318
+ // src/valkey/acl-managed.ts
319
+ var managedUserNames = (stored, previous) => stored?.managedUsers ?? (previous === undefined ? Object.keys(stored?.users ?? {}).filter((name) => stored?.users[name]?.passwordSeal !== "") : Object.keys(previous.users));
320
+
321
+ // src/valkey/acl-ops.ts
322
+ import * as Effect6 from "effect/Effect";
323
+
324
+ // src/valkey/transport.ts
325
+ import * as Effect5 from "effect/Effect";
326
+
327
+ // src/valkey/resp.ts
328
+ import * as Effect4 from "effect/Effect";
329
+
330
+ // src/valkey/transport-error.ts
331
+ import * as Data3 from "effect/Data";
332
+
333
+ class ValkeyServerError extends Data3.TaggedError("ValkeyServerError") {
334
+ get message() {
335
+ return this.detail;
336
+ }
337
+ }
338
+
339
+ class ValkeySocketError extends Data3.TaggedError("ValkeySocketError") {
340
+ get message() {
341
+ return this.reason;
342
+ }
343
+ }
344
+
345
+ // src/valkey/resp.ts
346
+ var MAX_BULK_BYTES = 1048576;
347
+ var MAX_ARRAY_ITEMS = 1e4;
348
+ var CRLF = `\r
349
+ `;
350
+ var boundedCount = (raw, cap) => {
351
+ if (!/^(?:-1|\d+)$/.test(raw))
352
+ return;
353
+ const n = Number(raw);
354
+ if (!Number.isSafeInteger(n) || n > cap)
355
+ return;
356
+ return n;
357
+ };
358
+ var readUntil = (socket, state, inFlight, timeoutMs, done) => Effect4.tryPromise({
359
+ try: (signal) => new Promise((resolve, reject) => {
360
+ let settled = false;
361
+ const wait = {};
362
+ const finish = (fn) => {
363
+ if (settled)
364
+ return;
365
+ settled = true;
366
+ if (wait.timer !== undefined)
367
+ clearTimeout(wait.timer);
368
+ if (wait.onData !== undefined)
369
+ socket.off("data", wait.onData);
370
+ if (wait.onEnd !== undefined)
371
+ socket.off("end", wait.onEnd);
372
+ signal.removeEventListener("abort", onAbort);
373
+ if (inFlight.fail === failRead)
374
+ inFlight.fail = null;
375
+ fn();
376
+ };
377
+ const failRead = (reason) => {
378
+ finish(() => reject(new ValkeySocketError({ reason })));
379
+ };
380
+ const onAbort = () => failRead("read interrupted");
381
+ const settle = (parsed) => {
382
+ state.buf = state.buf.subarray(parsed.drop);
383
+ finish(() => resolve(parsed.value));
384
+ };
385
+ const immediate = done(state.buf);
386
+ if (immediate !== undefined) {
387
+ settle(immediate);
388
+ return;
389
+ }
390
+ if (socket.readableEnded || socket.destroyed) {
391
+ failRead("socket closed mid-reply");
392
+ return;
393
+ }
394
+ wait.onData = (chunk) => {
395
+ state.buf = Buffer.concat([state.buf, chunk]);
396
+ if (state.buf.length > MAX_BULK_BYTES + 64) {
397
+ failRead(`reply exceeded ${String(MAX_BULK_BYTES)} bytes`);
398
+ return;
399
+ }
400
+ const parsed = done(state.buf);
401
+ if (parsed === undefined)
402
+ return;
403
+ settle(parsed);
404
+ };
405
+ wait.onEnd = () => failRead("socket closed mid-reply");
406
+ wait.timer = setTimeout(() => failRead("socket timed out"), timeoutMs);
407
+ inFlight.fail = failRead;
408
+ signal.addEventListener("abort", onAbort);
409
+ socket.on("data", wait.onData);
410
+ socket.on("end", wait.onEnd);
411
+ }),
412
+ catch: (cause) => cause instanceof ValkeySocketError ? cause : new ValkeySocketError({ reason: String(cause) })
413
+ });
414
+ var readReply = (socket, state, command, inFlight, timeoutMs) => {
415
+ const readLine = () => readUntil(socket, state, inFlight, timeoutMs, (buffer) => {
416
+ const nl = buffer.indexOf(CRLF);
417
+ return nl === -1 ? undefined : { value: buffer.subarray(0, nl).toString("utf8"), drop: nl + 2 };
418
+ });
419
+ const readBytes = (n) => Effect4.gen(function* () {
420
+ if (state.taken + n > MAX_BULK_BYTES) {
421
+ return yield* Effect4.fail(new ValkeySocketError({
422
+ reason: `reply exceeded ${String(MAX_BULK_BYTES)} bytes`
423
+ }));
424
+ }
425
+ state.taken += n;
426
+ return yield* readUntil(socket, state, inFlight, timeoutMs, (buffer) => buffer.length < n + 2 ? undefined : { value: buffer.subarray(0, n).toString("utf8"), drop: n + 2 });
427
+ });
428
+ return Effect4.gen(function* () {
429
+ const line = yield* readLine();
430
+ const prefix = line[0];
431
+ if (prefix === "+")
432
+ return { kind: "bulk", value: line.slice(1) };
433
+ if (prefix === "-") {
434
+ return yield* Effect4.fail(new ValkeyServerError({ detail: line.slice(1) }));
435
+ }
436
+ if (prefix === "$") {
437
+ const n = boundedCount(line.slice(1), MAX_BULK_BYTES);
438
+ if (n === undefined) {
439
+ return yield* Effect4.fail(new ValkeySocketError({
440
+ reason: `bulk length ${line.slice(1)} exceeds ${String(MAX_BULK_BYTES)}`
441
+ }));
442
+ }
443
+ if (n === -1)
444
+ return { kind: "bulk", value: null };
445
+ return { kind: "bulk", value: yield* readBytes(n) };
446
+ }
447
+ if (prefix === "*") {
448
+ const n = boundedCount(line.slice(1), MAX_ARRAY_ITEMS);
449
+ if (n === undefined) {
450
+ return yield* Effect4.fail(new ValkeySocketError({
451
+ reason: `array length ${line.slice(1)} exceeds ${String(MAX_ARRAY_ITEMS)}`
452
+ }));
453
+ }
454
+ if (n === -1)
455
+ return { kind: "array", values: [] };
456
+ const values = [];
457
+ for (let i = 0;i < n; i += 1) {
458
+ const item = yield* readReply(socket, state, command, inFlight, timeoutMs);
459
+ if (item.kind !== "bulk") {
460
+ return yield* Effect4.fail(new ValkeyServerError({
461
+ detail: `nested array inside the reply to ${command}: this family reads only flat arrays`
462
+ }));
463
+ }
464
+ values.push(item.value);
465
+ }
466
+ return { kind: "array", values };
467
+ }
468
+ if (prefix === ":")
469
+ return { kind: "bulk", value: line.slice(1) };
470
+ return yield* Effect4.fail(new ValkeyServerError({ detail: `unexpected RESP prefix ${prefix}` }));
471
+ });
472
+ };
473
+
474
+ // src/valkey/transport.ts
475
+ var DEFAULT_SOCKET_TIMEOUT_MS = 1e4;
476
+ var CRLF2 = `\r
477
+ `;
478
+ var encodeArgs = (args) => `*${args.length}${CRLF2}${args.map((a) => `$${Buffer.byteLength(a)}${CRLF2}${a}`).join(CRLF2)}${CRLF2}`;
479
+ var makeSocketExecutor = (socket, timeoutMs = DEFAULT_SOCKET_TIMEOUT_MS) => {
480
+ const inFlight = { fail: null };
481
+ let socketFailure;
482
+ const onError = (error) => {
483
+ socketFailure = error.message;
484
+ inFlight.fail?.(error.message);
485
+ };
486
+ socket.on("error", onError);
487
+ return {
488
+ send: (args) => {
489
+ if (socketFailure !== undefined || socket.destroyed) {
490
+ return Effect5.fail(new ValkeySocketError({ reason: socketFailure ?? "socket closed" }));
491
+ }
492
+ const state = { buf: Buffer.alloc(0), taken: 0 };
493
+ const command = args[0] ?? "command";
494
+ try {
495
+ socket.write(encodeArgs(args));
496
+ } catch (cause) {
497
+ return Effect5.fail(new ValkeySocketError({
498
+ reason: cause instanceof Error ? cause.message : String(cause)
499
+ }));
500
+ }
501
+ if (socketFailure !== undefined || socket.destroyed) {
502
+ return Effect5.fail(new ValkeySocketError({ reason: socketFailure ?? "socket closed" }));
503
+ }
504
+ return readReply(socket, state, command, inFlight, timeoutMs);
505
+ }
506
+ };
507
+ };
508
+ var arrayPairs = (values) => {
509
+ const out = new Map;
510
+ for (let i = 0;i + 1 < values.length; i += 2) {
511
+ out.set(values[i] ?? "", values[i + 1] ?? null);
512
+ }
513
+ return out;
514
+ };
515
+
516
+ // src/valkey/acl-ops.ts
517
+ var readParsedUsers = (executor, self) => Effect6.gen(function* () {
518
+ const reply = yield* executor.send(["ACL", "LIST"]);
519
+ if (reply.kind === "error") {
520
+ return yield* Effect6.fail(new ValkeyServerError({ detail: reply.message }));
521
+ }
522
+ if (reply.kind !== "array") {
523
+ return yield* Effect6.fail(new ValkeyServerError({ detail: "ACL LIST did not answer an array" }));
524
+ }
525
+ const users = {};
526
+ for (const line of reply.values) {
527
+ if (line === null)
528
+ continue;
529
+ const parsed = yield* Effect6.try({
530
+ try: () => parseAclLine(line),
531
+ catch: () => new ValkeyAclParseError
532
+ });
533
+ if (parsed.name === "default" || parsed.name === self)
534
+ continue;
535
+ users[parsed.name] = parsed;
536
+ }
537
+ return users;
538
+ });
539
+ var toUserAttributes = (line) => ({
540
+ name: line.name,
541
+ keyPrefix: line.keyPatterns[0]?.slice(1) ?? "",
542
+ extraKeyPatterns: line.keyPatterns.slice(1).map((pattern) => pattern.slice(1)),
543
+ channelPatterns: [...line.channelPatterns],
544
+ profile: inferProfile(line.rules),
545
+ on: line.on,
546
+ nopass: line.nopass,
547
+ hasPassword: line.hasPassword,
548
+ passwordSeal: ""
549
+ });
550
+ var toAttributes = (instance, parsed) => {
551
+ const users = {};
552
+ for (const [name, line] of Object.entries(parsed)) {
553
+ users[name] = toUserAttributes(line);
554
+ }
555
+ return { instance, users };
556
+ };
557
+ var readWithExecutor = (executor, instance, self) => Effect6.map(readParsedUsers(executor, self), (parsed) => toAttributes(instance, parsed));
558
+ var readAclFileConfig = (executor) => Effect6.gen(function* () {
559
+ const reply = yield* executor.send(["CONFIG", "GET", "aclfile"]);
560
+ if (reply.kind === "error") {
561
+ return yield* Effect6.fail(new ValkeyServerError({ detail: reply.message }));
562
+ }
563
+ if (reply.kind !== "array") {
564
+ return yield* Effect6.fail(new ValkeyServerError({ detail: "CONFIG GET aclfile did not answer an array" }));
565
+ }
566
+ const path = arrayPairs(reply.values).get("aclfile");
567
+ if (path === undefined || path === null)
568
+ return yield* Effect6.fail(new ValkeyServerError({ detail: "CONFIG GET aclfile omitted aclfile" }));
569
+ return path;
570
+ });
571
+
572
+ // src/valkey/acl-reconcile.ts
573
+ import * as Effect7 from "effect/Effect";
574
+ var reconcileWithExecutor = (executor, props, stored, env = process.env, self, previous) => Effect7.gen(function* () {
575
+ const aclfile = yield* readAclFileConfig(executor);
576
+ if (aclfile !== "") {
577
+ return yield* Effect7.fail(new ValkeyAclFileRendered({ instance: props.instance, path: aclfile }));
578
+ }
579
+ const refused = refusalBeforeWrite(props.instance, props.users, self);
580
+ if (refused !== undefined)
581
+ return yield* Effect7.fail(refused);
582
+ const refs = {};
583
+ for (const [name, user] of Object.entries(props.users))
584
+ refs[name] = user.password;
585
+ const { values } = resolveAll(refs, env);
586
+ const live = yield* readParsedUsers(executor, self);
587
+ const { create, update, remove, undeclared } = planAclUsers(props.users, live, props.exclusive, managedUserNames(stored, previous));
588
+ for (const name of undeclared) {
589
+ yield* Effect7.logWarning(`Valkey.AclFile "${props.instance}": live ACL user "${name}" is not declared; ${remove.includes(name) ? "it is scheduled for deletion (previously managed or exclusive: true)." : "it was left alone (exclusive: false)."}`);
590
+ }
591
+ const rotate = Object.entries(props.users).filter(([name, user]) => {
592
+ const liveUser = live[name];
593
+ const sealed = stored?.users[name]?.passwordSeal ?? "";
594
+ return liveUser !== undefined && matchesDeclared(liveUser, user) && passwordState(sealed, values[name]) === "stale";
595
+ }).map(([, user]) => user);
596
+ const writes = [...create, ...update, ...rotate];
597
+ const writeList = [];
598
+ for (const user of writes) {
599
+ const password = values[user.name];
600
+ if (password === undefined) {
601
+ return yield* Effect7.fail(new ValkeyAclPasswordMissing({
602
+ instance: props.instance,
603
+ user: user.name,
604
+ variable: user.password.fromEnv
605
+ }));
606
+ }
607
+ writeList.push({ user, password });
608
+ }
609
+ for (const { user, password } of writeList) {
610
+ const reply = yield* executor.send(yield* buildSetUserArgs(user, password));
611
+ if (reply.kind === "error") {
612
+ return yield* Effect7.fail(new ValkeyServerError({ detail: reply.message }));
613
+ }
614
+ }
615
+ if (remove.length > 0) {
616
+ const reply = yield* executor.send(buildDelUserArgs(remove));
617
+ if (reply.kind === "error") {
618
+ return yield* Effect7.fail(new ValkeyServerError({ detail: reply.message }));
619
+ }
620
+ }
621
+ const after = yield* readParsedUsers(executor, self);
622
+ for (const [name, user] of Object.entries(props.users)) {
623
+ const parsed = after[name];
624
+ if (parsed === undefined || !matchesDeclared(parsed, user)) {
625
+ return yield* Effect7.fail(new ValkeyAclReadbackFailed({ instance: props.instance, user: name }));
626
+ }
627
+ }
628
+ if (props.exclusive || remove.length > 0) {
629
+ for (const name of Object.keys(after)) {
630
+ if (props.users[name] === undefined && (props.exclusive || remove.includes(name))) {
631
+ return yield* Effect7.fail(new ValkeyAclReadbackFailed({ instance: props.instance, user: name }));
632
+ }
633
+ }
634
+ }
635
+ const seals = {};
636
+ for (const name of Object.keys(props.users)) {
637
+ seals[name] = stored?.users[name]?.passwordSeal ?? "";
638
+ }
639
+ for (const { user, password } of writeList)
640
+ seals[user.name] = seal({ password });
641
+ const users = {};
642
+ for (const [name, parsed] of Object.entries(after)) {
643
+ users[name] = { ...toUserAttributes(parsed), passwordSeal: seals[name] ?? "" };
644
+ }
645
+ return { instance: props.instance, users, managedUsers: Object.keys(props.users).sort() };
646
+ });
647
+
648
+ // src/valkey/connection.ts
649
+ import * as Effect8 from "effect/Effect";
650
+ import { connect } from "node:net";
651
+ var openSocket = (host, port, timeoutMs) => Effect8.tryPromise({
652
+ try: (signal) => new Promise((resolve, reject) => {
653
+ const socket = connect({ host, port });
654
+ let settled = false;
655
+ const onConnect = () => {
656
+ if (settled)
657
+ return;
658
+ settled = true;
659
+ socket.off("error", onError);
660
+ socket.off("timeout", onTimeout);
661
+ signal.removeEventListener("abort", onAbort);
662
+ clearTimeout(timer);
663
+ socket.setTimeout(0);
664
+ resolve(socket);
665
+ };
666
+ const onError = (error) => {
667
+ if (settled)
668
+ return;
669
+ settled = true;
670
+ socket.off("connect", onConnect);
671
+ socket.off("timeout", onTimeout);
672
+ signal.removeEventListener("abort", onAbort);
673
+ clearTimeout(timer);
674
+ socket.destroy();
675
+ reject(new ValkeySocketError({ reason: error.message }));
676
+ };
677
+ const onTimeout = () => onError(new Error("connect timed out"));
678
+ const onAbort = () => onError(new Error("connect interrupted"));
679
+ const timer = setTimeout(onTimeout, timeoutMs);
680
+ timer.unref();
681
+ socket.setTimeout(timeoutMs);
682
+ signal.addEventListener("abort", onAbort);
683
+ socket.once("connect", onConnect);
684
+ socket.once("error", onError);
685
+ socket.once("timeout", onTimeout);
686
+ }),
687
+ catch: (cause) => cause instanceof ValkeySocketError ? cause : new ValkeySocketError({ reason: String(cause) })
688
+ });
689
+ var auth = (executor, config, env) => {
690
+ if (!("password" in config))
691
+ return Effect8.void;
692
+ const { username, password } = config;
693
+ return Effect8.gen(function* () {
694
+ const { values, missing } = resolveAll({ password }, env);
695
+ const value = values.password;
696
+ if (missing.length > 0 || value === undefined) {
697
+ return yield* Effect8.fail(new ValkeyAuthPasswordMissing({ username, variable: password.fromEnv }));
698
+ }
699
+ const reply = yield* executor.send(username === undefined ? ["AUTH", value] : ["AUTH", username, value]);
700
+ if (reply.kind === "error")
701
+ return yield* Effect8.fail(new ValkeyServerError({ detail: "Valkey AUTH was refused" }));
702
+ });
703
+ };
704
+ var withValkey = (build, instance) => Effect8.gen(function* () {
705
+ const config = yield* resolveValkeyConnection(instance);
706
+ const timeoutMs = config.timeoutMs ?? DEFAULT_SOCKET_TIMEOUT_MS;
707
+ const socket = yield* openSocket(config.host, config.port, timeoutMs);
708
+ const executor = makeSocketExecutor(socket, timeoutMs);
709
+ socket.setTimeout(timeoutMs);
710
+ const onIdle = () => {
711
+ socket.destroy(new Error("socket timed out"));
712
+ };
713
+ socket.on("timeout", onIdle);
714
+ return yield* Effect8.ensuring(Effect8.gen(function* () {
715
+ yield* auth(executor, config, process.env);
716
+ return yield* build(executor, config);
717
+ }), Effect8.sync(() => {
718
+ socket.setTimeout(0);
719
+ socket.off("timeout", onIdle);
720
+ socket.destroy();
721
+ }));
722
+ });
723
+
724
+ // src/valkey/acl.ts
725
+ var ValkeyAclFile = Resource("Valkey.AclFile", {
726
+ defaultRemovalPolicy: "retain"
727
+ });
728
+ var isValkeyAclFile = (value) => (typeof value === "object" || typeof value === "function") && value !== null && value.Type === "Valkey.AclFile";
729
+ var makeValkeyAclFileHandlers = (connect2 = withValkey) => ValkeyAclFile.Provider.of({
730
+ list: () => Effect9.succeed([]),
731
+ nuke: { skip: true },
732
+ read: ({ output, olds }) => Effect9.gen(function* () {
733
+ const props = output ?? olds;
734
+ const live = yield* connect2((ex, config) => readWithExecutor(ex, props.instance, config.username), props.instance).pipe(Effect9.catchTag("ValkeySocketError", aclUnreachable(props.instance)));
735
+ if (output === undefined)
736
+ return Unowned(live);
737
+ const users = {};
738
+ for (const [name, user] of Object.entries(live.users)) {
739
+ users[name] = { ...user, passwordSeal: output.users[name]?.passwordSeal ?? "" };
740
+ }
741
+ return { instance: live.instance, users, managedUsers: managedUserNames(output, olds) };
742
+ }),
743
+ diff: ({ news, output, olds }) => Effect9.gen(function* () {
744
+ if (!isResolved(news))
745
+ return;
746
+ const refused = refusalBeforeWrite(news.instance, news.users);
747
+ if (refused !== undefined)
748
+ return yield* Effect9.fail(refused);
749
+ if (output === undefined)
750
+ return;
751
+ const declared = Object.keys(news.users).sort();
752
+ if (!sameSet(declared, [...managedUserNames(output, olds)]))
753
+ return { action: "update" };
754
+ const liveNames = Object.keys(output.users).sort();
755
+ if (news.exclusive && declared.length !== liveNames.length)
756
+ return { action: "update" };
757
+ for (const [name, user] of Object.entries(news.users)) {
758
+ const live = output.users[name];
759
+ if (live === undefined || live.keyPrefix !== effectiveKeyPrefix(user) || live.extraKeyPatterns.length > 0 || !sameSet(live.channelPatterns, [...declaredChannels(user)]) || live.profile !== user.profile || !live.on || live.nopass || !live.hasPassword) {
760
+ return { action: "update" };
761
+ }
762
+ const { values } = resolveAll({ password: user.password });
763
+ if (passwordState(live.passwordSeal, values.password) === "stale") {
764
+ return { action: "update" };
765
+ }
766
+ }
767
+ return { action: "noop" };
768
+ }),
769
+ reconcile: ({ news, output, olds }) => connect2((ex, config) => reconcileWithExecutor(ex, news, output, process.env, config.username, olds), news.instance).pipe(Effect9.catchTag("ValkeySocketError", aclUnreachable(news.instance))),
770
+ delete: ({ olds, output }) => connect2((ex, config) => Effect9.gen(function* () {
771
+ const aclfile = yield* readAclFileConfig(ex);
772
+ if (aclfile !== "") {
773
+ return yield* Effect9.fail(new ValkeyAclFileRendered({ instance: olds.instance, path: aclfile }));
774
+ }
775
+ const live = yield* readParsedUsers(ex, config.username);
776
+ const targets = managedUserNames(output, olds).filter((name) => live[name] !== undefined);
777
+ if (targets.length === 0)
778
+ return;
779
+ const reply = yield* ex.send(buildDelUserArgs(targets));
780
+ if (reply.kind === "error") {
781
+ return yield* Effect9.fail(new ValkeyServerError({ detail: reply.message }));
782
+ }
783
+ return;
784
+ }), olds.instance).pipe(Effect9.catchTag("ValkeySocketError", aclUnreachable(olds.instance)))
785
+ });
786
+ var valkeyAclFileHandlers = makeValkeyAclFileHandlers();
787
+ var ValkeyAclFileProvider = () => Provider.succeed(ValkeyAclFile, valkeyAclFileHandlers);
788
+ // src/valkey/instance.ts
789
+ import { Resource as Resource2 } from "alchemy";
790
+ import { Unowned as Unowned2 } from "alchemy/AdoptPolicy";
791
+ import { isResolved as isResolved2 } from "alchemy/Diff";
792
+ import * as Provider2 from "alchemy/Provider";
793
+ import * as Data4 from "effect/Data";
794
+ import * as Effect10 from "effect/Effect";
795
+
796
+ // src/valkey/instance-form.ts
797
+ var parseInfo = (value) => {
798
+ const fallback = "0.0.0";
799
+ if (value === null)
800
+ return { version: fallback, port: 0 };
801
+ const match = /valkey_version:([0-9a-zA-Z._-]+)/.exec(value);
802
+ const port = /tcp_port:([0-9]+)/.exec(value);
803
+ return {
804
+ version: match?.[1] ?? fallback,
805
+ port: port?.[1] === undefined ? 0 : Number(port[1])
806
+ };
807
+ };
808
+ var MEMORY_UNITS = {
809
+ "": 1n,
810
+ b: 1n,
811
+ k: 1000n,
812
+ kb: 1024n,
813
+ m: 1000000n,
814
+ mb: 1024n * 1024n,
815
+ g: 1000000000n,
816
+ gb: 1024n * 1024n * 1024n
817
+ };
818
+ var memoryBytes = (value) => {
819
+ if (value.startsWith("-"))
820
+ return;
821
+ const match = /^(\d+)([a-z]*)$/i.exec(value);
822
+ if (match === null)
823
+ return;
824
+ const digits = match[1];
825
+ const unit = (match[2] ?? "").toLowerCase();
826
+ const mul = MEMORY_UNITS[unit];
827
+ if (digits === undefined || mul === undefined)
828
+ return;
829
+ return BigInt(digits) * mul;
830
+ };
831
+ var sameMemory = (declared, live) => {
832
+ const left = memoryBytes(declared);
833
+ const right = memoryBytes(live);
834
+ return left !== undefined && right !== undefined && left === right;
835
+ };
836
+ var defaultedConfig = (raw) => ({
837
+ maxmemory: raw.maxmemory ?? "0",
838
+ maxmemoryPolicy: raw.maxmemoryPolicy ?? "noeviction",
839
+ appendonly: raw.appendonly ?? "no"
840
+ });
841
+ var buildAttributes = (props, info, config) => ({
842
+ name: props.name,
843
+ port: info.port,
844
+ version: info.version,
845
+ ...defaultedConfig(config)
846
+ });
847
+ var firstDrift = (props, live) => {
848
+ const checks = [
849
+ ["port", props.port, live.port],
850
+ ["maxmemory", props.maxmemory, live.maxmemory],
851
+ ["maxmemoryPolicy", props.maxmemoryPolicy, live.maxmemoryPolicy],
852
+ ["appendonly", props.appendonly, live.appendonly]
853
+ ];
854
+ for (const [prop, declared, liveValue] of checks) {
855
+ if (declared === undefined)
856
+ continue;
857
+ if (prop === "maxmemory" && typeof declared === "string" && typeof liveValue === "string" && sameMemory(declared, liveValue)) {
858
+ continue;
859
+ }
860
+ if (declared !== liveValue)
861
+ return { prop, declared, live: liveValue };
862
+ }
863
+ return;
864
+ };
865
+
866
+ // src/valkey/instance.ts
867
+ var ValkeyInstance = Resource2("Valkey.Instance", {
868
+ defaultRemovalPolicy: "retain"
869
+ });
870
+ var isValkeyInstance = (value) => (typeof value === "object" || typeof value === "function") && value !== null && value.Type === "Valkey.Instance";
871
+
872
+ class ValkeyInstanceDeleteRefused extends Data4.TaggedError("ValkeyInstanceDeleteRefused") {
873
+ get message() {
874
+ return `Valkey.Instance "${this.instance}": delete is refused. This provider never stops a ` + "running Valkey server. Stop it by hand on the host if you mean to remove it, then remove " + "the declaration.";
875
+ }
876
+ }
877
+ var readWithExecutor2 = (executor, props) => Effect10.gen(function* () {
878
+ const infoReply = yield* executor.send(["INFO"]);
879
+ if (infoReply.kind === "error") {
880
+ return yield* Effect10.fail(new ValkeyServerError({ detail: infoReply.message }));
881
+ }
882
+ const info = parseInfo(infoReply.kind === "bulk" ? infoReply.value : null);
883
+ const configReply = yield* executor.send([
884
+ "CONFIG",
885
+ "GET",
886
+ "maxmemory",
887
+ "maxmemory-policy",
888
+ "appendonly"
889
+ ]);
890
+ if (configReply.kind === "error") {
891
+ return yield* Effect10.fail(new ValkeyServerError({ detail: configReply.message }));
892
+ }
893
+ const pairs = configReply.kind === "array" ? arrayPairs(configReply.values) : new Map;
894
+ return buildAttributes(props, info, {
895
+ maxmemory: pairs.get("maxmemory") ?? undefined,
896
+ maxmemoryPolicy: pairs.get("maxmemory-policy") ?? undefined,
897
+ appendonly: pairs.get("appendonly") ?? undefined
898
+ });
899
+ });
900
+ var makeValkeyInstanceHandlers = (connect2 = withValkey) => ValkeyInstance.Provider.of({
901
+ list: () => Effect10.succeed([]),
902
+ nuke: { skip: true },
903
+ read: ({ output, olds }) => Effect10.gen(function* () {
904
+ const props = output ?? olds;
905
+ return yield* connect2((ex) => Effect10.map(readWithExecutor2(ex, { name: props.name, port: props.port }), Unowned2), props.name);
906
+ }),
907
+ diff: ({ news, output }) => Effect10.sync(() => {
908
+ if (!isResolved2(news))
909
+ return;
910
+ if (output === undefined)
911
+ return;
912
+ const drift = firstDrift(news, output);
913
+ return drift !== undefined ? { action: "update" } : { action: "noop" };
914
+ }),
915
+ reconcile: ({ news }) => Effect10.gen(function* () {
916
+ const live = yield* connect2((ex) => readWithExecutor2(ex, { name: news.name, port: news.port }), news.name);
917
+ const drift = firstDrift(news, live);
918
+ if (drift !== undefined) {
919
+ return yield* Effect10.fail(new ValkeyInstanceDrift({
920
+ instance: news.name,
921
+ prop: drift.prop,
922
+ declared: drift.declared,
923
+ live: drift.live
924
+ }));
925
+ }
926
+ return live;
927
+ }),
928
+ delete: ({ olds }) => Effect10.fail(new ValkeyInstanceDeleteRefused({ instance: olds.name }))
929
+ });
930
+ var valkeyInstanceHandlers = makeValkeyInstanceHandlers();
931
+ var ValkeyInstanceProvider = () => Provider2.succeed(ValkeyInstance, valkeyInstanceHandlers);
932
+ // src/valkey/providers.ts
933
+ import * as Layer2 from "effect/Layer";
934
+ var valkeyProviders = (config) => Layer2.mergeAll(ValkeyInstanceProvider(), ValkeyAclFileProvider()).pipe(Layer2.provideMerge(valkeyConnection(config)));
935
+ export {
936
+ ValkeyAclChannelPatterns,
937
+ ValkeyAclFile,
938
+ ValkeyAclFileProvider,
939
+ ValkeyAclFileRendered,
940
+ ValkeyAclMonitorKeyPrefix,
941
+ ValkeyAclNameGlob,
942
+ ValkeyAclParseError,
943
+ ValkeyAclPasswordMissing,
944
+ ValkeyAclReadbackFailed,
945
+ ValkeyAclReservedUser,
946
+ ValkeyAclSeatKeyPrefix,
947
+ ValkeyAclUserNameMismatch,
948
+ ValkeyAuthPasswordMissing,
949
+ ValkeyConnection,
950
+ ValkeyConnectionMissing,
951
+ ValkeyInstance,
952
+ ValkeyInstanceDeleteRefused,
953
+ ValkeyInstanceDrift,
954
+ ValkeyInstanceProvider,
955
+ ValkeyInstanceUnreachable,
956
+ isValkeyAclFile,
957
+ isValkeyInstance,
958
+ valkeyConnection,
959
+ valkeyProviders,
960
+ withValkey
961
+ };
962
+
963
+ //# debugId=AD3AB456863A1F6E64756E2164756E21
964
+ //# sourceMappingURL=index.js.map