pray-cli 1.6.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 (374) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +69 -0
  4. package/SECURITY.md +28 -0
  5. package/bin/pray.js +5 -0
  6. package/dist/archive/praypkg.d.ts +6 -0
  7. package/dist/archive/praypkg.d.ts.map +1 -0
  8. package/dist/archive/praypkg.js +67 -0
  9. package/dist/archive/praypkg.js.map +1 -0
  10. package/dist/auth/login.d.ts +11 -0
  11. package/dist/auth/login.d.ts.map +1 -0
  12. package/dist/auth/login.js +84 -0
  13. package/dist/auth/login.js.map +1 -0
  14. package/dist/auth/passkey.d.ts +3 -0
  15. package/dist/auth/passkey.d.ts.map +1 -0
  16. package/dist/auth/passkey.js +48 -0
  17. package/dist/auth/passkey.js.map +1 -0
  18. package/dist/auth/session.d.ts +11 -0
  19. package/dist/auth/session.d.ts.map +1 -0
  20. package/dist/auth/session.js +38 -0
  21. package/dist/auth/session.js.map +1 -0
  22. package/dist/auth/ssh-agent.d.ts +3 -0
  23. package/dist/auth/ssh-agent.d.ts.map +1 -0
  24. package/dist/auth/ssh-agent.js +135 -0
  25. package/dist/auth/ssh-agent.js.map +1 -0
  26. package/dist/cli/commands/distribution.d.ts +5 -0
  27. package/dist/cli/commands/distribution.d.ts.map +1 -0
  28. package/dist/cli/commands/distribution.js +134 -0
  29. package/dist/cli/commands/distribution.js.map +1 -0
  30. package/dist/cli/commands/init.d.ts +3 -0
  31. package/dist/cli/commands/init.d.ts.map +1 -0
  32. package/dist/cli/commands/init.js +44 -0
  33. package/dist/cli/commands/init.js.map +1 -0
  34. package/dist/cli/commands/inspect.d.ts +7 -0
  35. package/dist/cli/commands/inspect.d.ts.map +1 -0
  36. package/dist/cli/commands/inspect.js +98 -0
  37. package/dist/cli/commands/inspect.js.map +1 -0
  38. package/dist/cli/commands/packages.d.ts +4 -0
  39. package/dist/cli/commands/packages.d.ts.map +1 -0
  40. package/dist/cli/commands/packages.js +62 -0
  41. package/dist/cli/commands/packages.js.map +1 -0
  42. package/dist/cli/commands/plan.d.ts +2 -0
  43. package/dist/cli/commands/plan.d.ts.map +1 -0
  44. package/dist/cli/commands/plan.js +55 -0
  45. package/dist/cli/commands/plan.js.map +1 -0
  46. package/dist/cli/commands/update-core.d.ts +16 -0
  47. package/dist/cli/commands/update-core.d.ts.map +1 -0
  48. package/dist/cli/commands/update-core.js +108 -0
  49. package/dist/cli/commands/update-core.js.map +1 -0
  50. package/dist/cli/commands/update-latest.d.ts +2 -0
  51. package/dist/cli/commands/update-latest.d.ts.map +1 -0
  52. package/dist/cli/commands/update-latest.js +68 -0
  53. package/dist/cli/commands/update-latest.js.map +1 -0
  54. package/dist/cli/commands/update-report.d.ts +23 -0
  55. package/dist/cli/commands/update-report.d.ts.map +1 -0
  56. package/dist/cli/commands/update-report.js +113 -0
  57. package/dist/cli/commands/update-report.js.map +1 -0
  58. package/dist/cli/commands/update.d.ts +11 -0
  59. package/dist/cli/commands/update.d.ts.map +1 -0
  60. package/dist/cli/commands/update.js +65 -0
  61. package/dist/cli/commands/update.js.map +1 -0
  62. package/dist/cli/commands/workspace.d.ts +3 -0
  63. package/dist/cli/commands/workspace.d.ts.map +1 -0
  64. package/dist/cli/commands/workspace.js +63 -0
  65. package/dist/cli/commands/workspace.js.map +1 -0
  66. package/dist/cli/help.d.ts +6 -0
  67. package/dist/cli/help.d.ts.map +1 -0
  68. package/dist/cli/help.js +164 -0
  69. package/dist/cli/help.js.map +1 -0
  70. package/dist/cli/invocation.d.ts +10 -0
  71. package/dist/cli/invocation.d.ts.map +1 -0
  72. package/dist/cli/invocation.js +127 -0
  73. package/dist/cli/invocation.js.map +1 -0
  74. package/dist/cli/main.d.ts +2 -0
  75. package/dist/cli/main.d.ts.map +1 -0
  76. package/dist/cli/main.js +199 -0
  77. package/dist/cli/main.js.map +1 -0
  78. package/dist/cli/materialize.d.ts +10 -0
  79. package/dist/cli/materialize.d.ts.map +1 -0
  80. package/dist/cli/materialize.js +59 -0
  81. package/dist/cli/materialize.js.map +1 -0
  82. package/dist/cli/suggest.d.ts +4 -0
  83. package/dist/cli/suggest.d.ts.map +1 -0
  84. package/dist/cli/suggest.js +88 -0
  85. package/dist/cli/suggest.js.map +1 -0
  86. package/dist/cli/upgrade.d.ts +2 -0
  87. package/dist/cli/upgrade.d.ts.map +1 -0
  88. package/dist/cli/upgrade.js +15 -0
  89. package/dist/cli/upgrade.js.map +1 -0
  90. package/dist/confess/index.d.ts +11 -0
  91. package/dist/confess/index.d.ts.map +1 -0
  92. package/dist/confess/index.js +51 -0
  93. package/dist/confess/index.js.map +1 -0
  94. package/dist/constraint.d.ts +8 -0
  95. package/dist/constraint.d.ts.map +1 -0
  96. package/dist/constraint.js +97 -0
  97. package/dist/constraint.js.map +1 -0
  98. package/dist/domain/types.d.ts +8 -0
  99. package/dist/domain/types.d.ts.map +1 -0
  100. package/dist/domain/types.js +2 -0
  101. package/dist/domain/types.js.map +1 -0
  102. package/dist/environment.d.ts +8 -0
  103. package/dist/environment.d.ts.map +1 -0
  104. package/dist/environment.js +42 -0
  105. package/dist/environment.js.map +1 -0
  106. package/dist/errors.d.ts +18 -0
  107. package/dist/errors.d.ts.map +1 -0
  108. package/dist/errors.js +67 -0
  109. package/dist/errors.js.map +1 -0
  110. package/dist/git/sources.d.ts +14 -0
  111. package/dist/git/sources.d.ts.map +1 -0
  112. package/dist/git/sources.js +225 -0
  113. package/dist/git/sources.js.map +1 -0
  114. package/dist/hashing.d.ts +7 -0
  115. package/dist/hashing.d.ts.map +1 -0
  116. package/dist/hashing.js +43 -0
  117. package/dist/hashing.js.map +1 -0
  118. package/dist/http/client.d.ts +9 -0
  119. package/dist/http/client.d.ts.map +1 -0
  120. package/dist/http/client.js +51 -0
  121. package/dist/http/client.js.map +1 -0
  122. package/dist/index.d.ts +25 -0
  123. package/dist/index.d.ts.map +1 -0
  124. package/dist/index.js +19 -0
  125. package/dist/index.js.map +1 -0
  126. package/dist/literal/call-parser.d.ts +12 -0
  127. package/dist/literal/call-parser.d.ts.map +1 -0
  128. package/dist/literal/call-parser.js +75 -0
  129. package/dist/literal/call-parser.js.map +1 -0
  130. package/dist/literal/lines.d.ts +3 -0
  131. package/dist/literal/lines.d.ts.map +1 -0
  132. package/dist/literal/lines.js +34 -0
  133. package/dist/literal/lines.js.map +1 -0
  134. package/dist/literal/parser.d.ts +5 -0
  135. package/dist/literal/parser.d.ts.map +1 -0
  136. package/dist/literal/parser.js +269 -0
  137. package/dist/literal/parser.js.map +1 -0
  138. package/dist/literal/split.d.ts +4 -0
  139. package/dist/literal/split.d.ts.map +1 -0
  140. package/dist/literal/split.js +110 -0
  141. package/dist/literal/split.js.map +1 -0
  142. package/dist/literal/statement-surface.d.ts +11 -0
  143. package/dist/literal/statement-surface.d.ts.map +1 -0
  144. package/dist/literal/statement-surface.js +320 -0
  145. package/dist/literal/statement-surface.js.map +1 -0
  146. package/dist/literal/statements.d.ts +8 -0
  147. package/dist/literal/statements.d.ts.map +1 -0
  148. package/dist/literal/statements.js +49 -0
  149. package/dist/literal/statements.js.map +1 -0
  150. package/dist/literal/types.d.ts +27 -0
  151. package/dist/literal/types.d.ts.map +1 -0
  152. package/dist/literal/types.js +19 -0
  153. package/dist/literal/types.js.map +1 -0
  154. package/dist/lockfile/index.d.ts +24 -0
  155. package/dist/lockfile/index.d.ts.map +1 -0
  156. package/dist/lockfile/index.js +100 -0
  157. package/dist/lockfile/index.js.map +1 -0
  158. package/dist/lockfile/parse.d.ts +3 -0
  159. package/dist/lockfile/parse.d.ts.map +1 -0
  160. package/dist/lockfile/parse.js +94 -0
  161. package/dist/lockfile/parse.js.map +1 -0
  162. package/dist/lockfile/paths.d.ts +8 -0
  163. package/dist/lockfile/paths.d.ts.map +1 -0
  164. package/dist/lockfile/paths.js +66 -0
  165. package/dist/lockfile/paths.js.map +1 -0
  166. package/dist/lockfile/serialize.d.ts +3 -0
  167. package/dist/lockfile/serialize.d.ts.map +1 -0
  168. package/dist/lockfile/serialize.js +118 -0
  169. package/dist/lockfile/serialize.js.map +1 -0
  170. package/dist/lockfile/types.d.ts +49 -0
  171. package/dist/lockfile/types.d.ts.map +1 -0
  172. package/dist/lockfile/types.js +16 -0
  173. package/dist/lockfile/types.js.map +1 -0
  174. package/dist/manifest/deprecation.d.ts +7 -0
  175. package/dist/manifest/deprecation.d.ts.map +1 -0
  176. package/dist/manifest/deprecation.js +35 -0
  177. package/dist/manifest/deprecation.js.map +1 -0
  178. package/dist/manifest/destination.d.ts +19 -0
  179. package/dist/manifest/destination.d.ts.map +1 -0
  180. package/dist/manifest/destination.js +179 -0
  181. package/dist/manifest/destination.js.map +1 -0
  182. package/dist/manifest/edit.d.ts +9 -0
  183. package/dist/manifest/edit.d.ts.map +1 -0
  184. package/dist/manifest/edit.js +56 -0
  185. package/dist/manifest/edit.js.map +1 -0
  186. package/dist/manifest/format-manifest.d.ts +14 -0
  187. package/dist/manifest/format-manifest.d.ts.map +1 -0
  188. package/dist/manifest/format-manifest.js +274 -0
  189. package/dist/manifest/format-manifest.js.map +1 -0
  190. package/dist/manifest/format-serialize.d.ts +4 -0
  191. package/dist/manifest/format-serialize.d.ts.map +1 -0
  192. package/dist/manifest/format-serialize.js +172 -0
  193. package/dist/manifest/format-serialize.js.map +1 -0
  194. package/dist/manifest/index.d.ts +10 -0
  195. package/dist/manifest/index.d.ts.map +1 -0
  196. package/dist/manifest/index.js +33 -0
  197. package/dist/manifest/index.js.map +1 -0
  198. package/dist/manifest/package-declaration.d.ts +4 -0
  199. package/dist/manifest/package-declaration.d.ts.map +1 -0
  200. package/dist/manifest/package-declaration.js +80 -0
  201. package/dist/manifest/package-declaration.js.map +1 -0
  202. package/dist/manifest/parse-statements.d.ts +15 -0
  203. package/dist/manifest/parse-statements.d.ts.map +1 -0
  204. package/dist/manifest/parse-statements.js +216 -0
  205. package/dist/manifest/parse-statements.js.map +1 -0
  206. package/dist/manifest/parser.d.ts +3 -0
  207. package/dist/manifest/parser.d.ts.map +1 -0
  208. package/dist/manifest/parser.js +382 -0
  209. package/dist/manifest/parser.js.map +1 -0
  210. package/dist/manifest/types.d.ts +78 -0
  211. package/dist/manifest/types.d.ts.map +1 -0
  212. package/dist/manifest/types.js +84 -0
  213. package/dist/manifest/types.js.map +1 -0
  214. package/dist/package-spec/discovery.d.ts +2 -0
  215. package/dist/package-spec/discovery.d.ts.map +1 -0
  216. package/dist/package-spec/discovery.js +21 -0
  217. package/dist/package-spec/discovery.js.map +1 -0
  218. package/dist/package-spec/index.d.ts +5 -0
  219. package/dist/package-spec/index.d.ts.map +1 -0
  220. package/dist/package-spec/index.js +5 -0
  221. package/dist/package-spec/index.js.map +1 -0
  222. package/dist/package-spec/parse-maps.d.ts +8 -0
  223. package/dist/package-spec/parse-maps.d.ts.map +1 -0
  224. package/dist/package-spec/parse-maps.js +127 -0
  225. package/dist/package-spec/parse-maps.js.map +1 -0
  226. package/dist/package-spec/parser.d.ts +3 -0
  227. package/dist/package-spec/parser.d.ts.map +1 -0
  228. package/dist/package-spec/parser.js +111 -0
  229. package/dist/package-spec/parser.js.map +1 -0
  230. package/dist/package-spec/tree-hash.d.ts +4 -0
  231. package/dist/package-spec/tree-hash.d.ts.map +1 -0
  232. package/dist/package-spec/tree-hash.js +29 -0
  233. package/dist/package-spec/tree-hash.js.map +1 -0
  234. package/dist/package-spec/types.d.ts +44 -0
  235. package/dist/package-spec/types.d.ts.map +1 -0
  236. package/dist/package-spec/types.js +12 -0
  237. package/dist/package-spec/types.js.map +1 -0
  238. package/dist/project-context/dotenv.d.ts +3 -0
  239. package/dist/project-context/dotenv.d.ts.map +1 -0
  240. package/dist/project-context/dotenv.js +49 -0
  241. package/dist/project-context/dotenv.js.map +1 -0
  242. package/dist/project-context/index.d.ts +10 -0
  243. package/dist/project-context/index.d.ts.map +1 -0
  244. package/dist/project-context/index.js +62 -0
  245. package/dist/project-context/index.js.map +1 -0
  246. package/dist/project-context/runtime.d.ts +4 -0
  247. package/dist/project-context/runtime.d.ts.map +1 -0
  248. package/dist/project-context/runtime.js +8 -0
  249. package/dist/project-context/runtime.js.map +1 -0
  250. package/dist/project-context/types.d.ts +11 -0
  251. package/dist/project-context/types.d.ts.map +1 -0
  252. package/dist/project-context/types.js +2 -0
  253. package/dist/project-context/types.js.map +1 -0
  254. package/dist/publish/index.d.ts +6 -0
  255. package/dist/publish/index.d.ts.map +1 -0
  256. package/dist/publish/index.js +133 -0
  257. package/dist/publish/index.js.map +1 -0
  258. package/dist/registry/index.d.ts +17 -0
  259. package/dist/registry/index.d.ts.map +1 -0
  260. package/dist/registry/index.js +223 -0
  261. package/dist/registry/index.js.map +1 -0
  262. package/dist/registry/types.d.ts +27 -0
  263. package/dist/registry/types.d.ts.map +1 -0
  264. package/dist/registry/types.js +2 -0
  265. package/dist/registry/types.js.map +1 -0
  266. package/dist/render/content-builder.d.ts +9 -0
  267. package/dist/render/content-builder.d.ts.map +1 -0
  268. package/dist/render/content-builder.js +31 -0
  269. package/dist/render/content-builder.js.map +1 -0
  270. package/dist/render/header.d.ts +4 -0
  271. package/dist/render/header.d.ts.map +1 -0
  272. package/dist/render/header.js +15 -0
  273. package/dist/render/header.js.map +1 -0
  274. package/dist/render/legacy.d.ts +5 -0
  275. package/dist/render/legacy.d.ts.map +1 -0
  276. package/dist/render/legacy.js +53 -0
  277. package/dist/render/legacy.js.map +1 -0
  278. package/dist/render/managed-export.d.ts +7 -0
  279. package/dist/render/managed-export.d.ts.map +1 -0
  280. package/dist/render/managed-export.js +33 -0
  281. package/dist/render/managed-export.js.map +1 -0
  282. package/dist/render/project.d.ts +8 -0
  283. package/dist/render/project.d.ts.map +1 -0
  284. package/dist/render/project.js +35 -0
  285. package/dist/render/project.js.map +1 -0
  286. package/dist/render/provisioned.d.ts +9 -0
  287. package/dist/render/provisioned.d.ts.map +1 -0
  288. package/dist/render/provisioned.js +191 -0
  289. package/dist/render/provisioned.js.map +1 -0
  290. package/dist/render/scoped.d.ts +5 -0
  291. package/dist/render/scoped.d.ts.map +1 -0
  292. package/dist/render/scoped.js +50 -0
  293. package/dist/render/scoped.js.map +1 -0
  294. package/dist/render/types.d.ts +7 -0
  295. package/dist/render/types.d.ts.map +1 -0
  296. package/dist/render/types.js +2 -0
  297. package/dist/render/types.js.map +1 -0
  298. package/dist/resolve/context.d.ts +11 -0
  299. package/dist/resolve/context.d.ts.map +1 -0
  300. package/dist/resolve/context.js +16 -0
  301. package/dist/resolve/context.js.map +1 -0
  302. package/dist/resolve/package-root.d.ts +13 -0
  303. package/dist/resolve/package-root.d.ts.map +1 -0
  304. package/dist/resolve/package-root.js +86 -0
  305. package/dist/resolve/package-root.js.map +1 -0
  306. package/dist/resolve/project.d.ts +8 -0
  307. package/dist/resolve/project.d.ts.map +1 -0
  308. package/dist/resolve/project.js +261 -0
  309. package/dist/resolve/project.js.map +1 -0
  310. package/dist/resolve/types.d.ts +36 -0
  311. package/dist/resolve/types.d.ts.map +1 -0
  312. package/dist/resolve/types.js +2 -0
  313. package/dist/resolve/types.js.map +1 -0
  314. package/dist/serve/index.d.ts +7 -0
  315. package/dist/serve/index.d.ts.map +1 -0
  316. package/dist/serve/index.js +88 -0
  317. package/dist/serve/index.js.map +1 -0
  318. package/dist/substitute.d.ts +3 -0
  319. package/dist/substitute.d.ts.map +1 -0
  320. package/dist/substitute.js +38 -0
  321. package/dist/substitute.js.map +1 -0
  322. package/dist/sync/index.d.ts +6 -0
  323. package/dist/sync/index.d.ts.map +1 -0
  324. package/dist/sync/index.js +74 -0
  325. package/dist/sync/index.js.map +1 -0
  326. package/dist/terminal.d.ts +4 -0
  327. package/dist/terminal.d.ts.map +1 -0
  328. package/dist/terminal.js +26 -0
  329. package/dist/terminal.js.map +1 -0
  330. package/dist/tree/index.d.ts +4 -0
  331. package/dist/tree/index.d.ts.map +1 -0
  332. package/dist/tree/index.js +40 -0
  333. package/dist/tree/index.js.map +1 -0
  334. package/dist/trust/import-registry.d.ts +6 -0
  335. package/dist/trust/import-registry.d.ts.map +1 -0
  336. package/dist/trust/import-registry.js +65 -0
  337. package/dist/trust/import-registry.js.map +1 -0
  338. package/dist/trust/import-repo.d.ts +2 -0
  339. package/dist/trust/import-repo.d.ts.map +1 -0
  340. package/dist/trust/import-repo.js +50 -0
  341. package/dist/trust/import-repo.js.map +1 -0
  342. package/dist/trust/index.d.ts +11 -0
  343. package/dist/trust/index.d.ts.map +1 -0
  344. package/dist/trust/index.js +148 -0
  345. package/dist/trust/index.js.map +1 -0
  346. package/dist/trust/parse.d.ts +3 -0
  347. package/dist/trust/parse.d.ts.map +1 -0
  348. package/dist/trust/parse.js +43 -0
  349. package/dist/trust/parse.js.map +1 -0
  350. package/dist/trust/policy-helpers.d.ts +8 -0
  351. package/dist/trust/policy-helpers.d.ts.map +1 -0
  352. package/dist/trust/policy-helpers.js +36 -0
  353. package/dist/trust/policy-helpers.js.map +1 -0
  354. package/dist/trust/store.d.ts +7 -0
  355. package/dist/trust/store.d.ts.map +1 -0
  356. package/dist/trust/store.js +40 -0
  357. package/dist/trust/store.js.map +1 -0
  358. package/dist/trust/types.d.ts +13 -0
  359. package/dist/trust/types.d.ts.map +1 -0
  360. package/dist/trust/types.js +2 -0
  361. package/dist/trust/types.js.map +1 -0
  362. package/dist/validation.d.ts +8 -0
  363. package/dist/validation.d.ts.map +1 -0
  364. package/dist/validation.js +41 -0
  365. package/dist/validation.js.map +1 -0
  366. package/dist/vendor/index.d.ts +4 -0
  367. package/dist/vendor/index.d.ts.map +1 -0
  368. package/dist/vendor/index.js +31 -0
  369. package/dist/vendor/index.js.map +1 -0
  370. package/dist/verify/project.d.ts +14 -0
  371. package/dist/verify/project.d.ts.map +1 -0
  372. package/dist/verify/project.js +240 -0
  373. package/dist/verify/project.js.map +1 -0
  374. package/package.json +75 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,50 @@
1
+ # CHANGELOG
2
+
3
+ ## Unreleased
4
+
5
+ ## 1.6.0 (2026-07-29)
6
+
7
+ - Add `login` with passkey and ssh-agent modes; persist sessions in `.pray/session.json`.
8
+ - Add `upgrade` via `npm install -g pray-cli@latest`.
9
+ - Honor `update --major|--latest|--dry-run|--json`, `plan --remote`, and `outdated --remote`.
10
+ - Implement `trust import-repo` and `trust import-registry` for local and http(s) sources.
11
+
12
+ ## 1.5.2 (2026-07-29)
13
+
14
+ - Put the Prayfile positioning line into the npm package description for registry search.
15
+
16
+ ## 1.5.1 (2026-07-29)
17
+
18
+ - Sync `PACKAGE_VERSION` with the package version and add `prepublishOnly` build for npm publish.
19
+ - Rework package description and README opener to match Prayfile positioning.
20
+
21
+ ## 1.5.0 (2026-07-27)
22
+
23
+ - Accept Gemfile-like Ruby surface sugar for Prayfile statements: `{…}` blocks, top-level `;`, and optional call parentheses.
24
+ - Add parser coverage for symbol maps and surface forms alongside substitute tests.
25
+ - Exercise the shared `testdata/shared` Prayfile corpus alongside Rust and Ruby.
26
+
27
+ ## 1.3.0 (2026-07-26)
28
+
29
+ - Add destination DSL parsing: `compose`, `tree`, and `file:` blocks in `Prayfile` for scoped rendering and exact file bindings, matching `pray-core`.
30
+ - Add role-based export selection (`fragment`, `folder`, `file`) so packages without an explicit `export:` resolve unambiguous exports automatically.
31
+ - Add `format`/`fmt` command to rewrite a legacy `Prayfile` into the recommended destination DSL and normalize marker comments in rendered lockfile outputs.
32
+ - Emit `pray` as the canonical package declaration keyword when formatting or editing manifests, while still accepting `use`, `include`, `agent`, and `package` on read for backward compatibility.
33
+
34
+ ## 1.1.0 (2026-07-14)
35
+
36
+ - Add environment-aware rendering with `group` blocks and `--env` or `PRAY_ENV`.
37
+ - Add global `--path` and `--file-path` flags with `PRAY_PATH`, `PRAY_FILE_PATH`, and project `.env` support.
38
+ - Record the selected environment in `Prayfile.lock`.
39
+ - Improve CLI help with grouped commands, per-command help, and suggestions for unknown commands.
40
+ - Add `--no-input` to skip interactive prompts.
41
+ - Honor `PRAY_NO_COLOR` and `NO_COLOR` for plain terminal output.
42
+ - Refresh git distribution caches on install when a locked revision is missing locally.
43
+
44
+ ## 1.0.0 (2026-07-13)
45
+
46
+ - Initial npm release of `pray-cli`.
47
+ - Resolve local path packages and git distribution sources.
48
+ - Publish to local distribution roots and serve over HTTP.
49
+ - Install, update, render, verify, and drift workflows with `Prayfile.lock`.
50
+ - Git distribution integration tests for install, locked revision, and update.
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 pray contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # pray-cli
2
+
3
+ TypeScript `pray` CLI and library for [Prayfile](https://pray.kisko.dev): a package manager for the language placed before inference.
4
+
5
+ Resolve, lock, render, verify, publish, and serve shared instructions, policies, templates, and related input as versioned packages. The installed executable is `pray`.
6
+
7
+ **Website:** [pray.kisko.dev](https://pray.kisko.dev)
8
+
9
+ **Maintainer:** Andrei Makarov ([contact@kiskolabs.com](mailto:contact@kiskolabs.com))
10
+
11
+ **Repository:** [kiskolabs/pray](https://github.com/kiskolabs/pray)
12
+
13
+ **Community docs:** [CHANGELOG.md](CHANGELOG.md) · [LICENSE.md](LICENSE.md) · [SECURITY.md](SECURITY.md)
14
+
15
+ ## Install
16
+
17
+ ```sh
18
+ npm install -g pray-cli
19
+ ```
20
+
21
+ Or run without installing:
22
+
23
+ ```sh
24
+ npx pray-cli install
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ From a project with a `Prayfile`:
30
+
31
+ ```sh
32
+ pray manifest
33
+ pray install
34
+ pray verify --strict
35
+ pray drift
36
+ pray publish --root ./prayers
37
+ pray serve --root ./prayers --port 7429
38
+ ```
39
+
40
+ ## Commands
41
+
42
+ - `manifest`, `init`, `prayer init`, `repo init`
43
+ - `add`, `remove`, `update`, `unlock`
44
+ - `install`, `apply`, `plan`, `render`, `verify`, `drift`, `format`
45
+ - `package`, `publish`, `serve`, `sync`, `vendor`, `clean`, `tree`
46
+ - `list`, `outdated`, `explain`
47
+ - `trust`, `confess`, `login`, `upgrade`
48
+
49
+ ## Development
50
+
51
+ ```sh
52
+ cd npmjs/pray-cli
53
+ npm install
54
+ npm test
55
+ npm run build
56
+ node bin/pray.js version
57
+ ```
58
+
59
+ ## Requirements
60
+
61
+ - Node.js 20+
62
+ - `git` for git sources
63
+ - `zstd` and `tar` for `.praypkg` archives
64
+
65
+ ## Status
66
+
67
+ Registry HTTP(S), git sources, local publish/serve/sync, vendor/tree, login (passkey and ssh-agent), upgrade, update/plan/outdated remote flags, and trust import paths are implemented. SSH registry (`pray+ssh://`) and `serve --stdio` remain planned.
68
+
69
+ See `SPEC.md` in the repository root for the normative specification.
package/SECURITY.md ADDED
@@ -0,0 +1,28 @@
1
+ # SECURITY
2
+
3
+ ## Reporting a Vulnerability
4
+
5
+ Do NOT open a public GitHub issue for security vulnerabilities.
6
+
7
+ Email security details to: security@kiskolabs.com
8
+
9
+ Include: description, steps to reproduce, potential impact, and suggested fix (if available).
10
+
11
+ ### Response Timeline
12
+
13
+ - We will acknowledge receipt of your report
14
+ - We will provide an initial assessment
15
+ - We will keep you informed of our progress and resolution timeline
16
+
17
+ ### Disclosure Policy
18
+
19
+ - We will work with you to understand and resolve the issue
20
+ - We will credit you for the discovery (unless you prefer to remain anonymous)
21
+ - We will publish a security advisory after the vulnerability is patched
22
+ - We will coordinate public disclosure with you
23
+
24
+ ## Automation Security
25
+
26
+ * Context Isolation: It is strictly forbidden to include production credentials, API keys, or Personally Identifiable Information (PII) in prompts sent to third-party LLMs or automation services.
27
+
28
+ * Supply Chain: All automated dependencies must be verified.
package/bin/pray.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import { runCli } from "../dist/cli/main.js";
3
+
4
+ const exitCode = await runCli(process.argv.slice(2));
5
+ process.exit(exitCode);
@@ -0,0 +1,6 @@
1
+ import type { ResolvedPackage } from "../resolve/types.js";
2
+ export declare function buildPackageArchiveBytes(packageEntry: ResolvedPackage): Buffer;
3
+ export declare function unpackPraypkg(artifactBytes: Buffer, outputDirectory: string): void;
4
+ export declare function packageArchivePath(packageName: string, version: string): string;
5
+ export declare function writePackageArchive(packageEntry: ResolvedPackage, outputPath: string): void;
6
+ //# sourceMappingURL=praypkg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"praypkg.d.ts","sourceRoot":"","sources":["../../src/archive/praypkg.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,eAAe,GAC5B,MAAM,CAuBR;AAED,wBAAgB,aAAa,CAC3B,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,GACtB,IAAI,CASN;AAED,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,MAAM,CAGR;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,eAAe,EAC7B,UAAU,EAAE,MAAM,GACjB,IAAI,CAIN"}
@@ -0,0 +1,67 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { copyFileSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { basename, dirname, join, resolve } from "node:path";
5
+ import { PrayError } from "../errors.js";
6
+ import { findPrayspecFile } from "../package-spec/index.js";
7
+ export function buildPackageArchiveBytes(packageEntry) {
8
+ const prayspecPath = findPrayspecFile(packageEntry.root);
9
+ const staging = mkdtempSync(join(tmpdir(), "pray-package-"));
10
+ try {
11
+ writeFileSync(join(staging, "metadata.json"), packageMetadataJson(packageEntry), "utf8");
12
+ writeFileSync(join(staging, basename(prayspecPath)), readFileSync(prayspecPath));
13
+ for (const file of packageEntry.spec.files) {
14
+ const destination = join(staging, file);
15
+ mkdirSync(dirname(destination), { recursive: true });
16
+ copyFileSync(join(packageEntry.root, file), destination);
17
+ }
18
+ const tarBytes = runCommand("tar", ["-cf", "-", "-C", staging, "."]);
19
+ return runCommand("zstd", ["-q", "-c"], tarBytes);
20
+ }
21
+ finally {
22
+ rmSync(staging, { recursive: true, force: true });
23
+ }
24
+ }
25
+ export function unpackPraypkg(artifactBytes, outputDirectory) {
26
+ mkdirSync(outputDirectory, { recursive: true });
27
+ const tarBytes = runCommand("zstd", ["-d", "-q", "-c"], artifactBytes);
28
+ const result = spawnSync("tar", ["-xf", "-", "-C", outputDirectory], {
29
+ input: tarBytes,
30
+ });
31
+ if (result.status !== 0) {
32
+ throw PrayError.integrity("failed to unpack package archive");
33
+ }
34
+ }
35
+ export function packageArchivePath(packageName, version) {
36
+ const slug = packageName.replaceAll("/", "-");
37
+ return join(".pray", "packages", `${slug}-${version}.praypkg`);
38
+ }
39
+ export function writePackageArchive(packageEntry, outputPath) {
40
+ const bytes = buildPackageArchiveBytes(packageEntry);
41
+ mkdirSync(dirname(resolve(outputPath)), { recursive: true });
42
+ writeFileSync(outputPath, bytes);
43
+ }
44
+ function packageMetadataJson(packageEntry) {
45
+ return JSON.stringify({
46
+ name: packageEntry.spec.name,
47
+ version: packageEntry.spec.version,
48
+ tree_hash: packageEntry.treeHash,
49
+ exports: packageEntry.selectedExports,
50
+ });
51
+ }
52
+ function runCommand(program, argumentsList, input) {
53
+ const result = spawnSync(program, argumentsList, {
54
+ input,
55
+ encoding: "buffer",
56
+ maxBuffer: 64 * 1024 * 1024,
57
+ });
58
+ if (result.error?.code === "ENOENT") {
59
+ throw PrayError.unsupported(`${program} is required to build or unpack package archives`);
60
+ }
61
+ if (result.status !== 0) {
62
+ const message = result.stderr?.toString("utf8").trim();
63
+ throw PrayError.integrity(message.length > 0 ? message : `${program} failed`);
64
+ }
65
+ return result.stdout;
66
+ }
67
+ //# sourceMappingURL=praypkg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"praypkg.js","sourceRoot":"","sources":["../../src/archive/praypkg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EACL,YAAY,EACZ,SAAS,EACT,WAAW,EACX,YAAY,EACZ,MAAM,EACN,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAG5D,MAAM,UAAU,wBAAwB,CACtC,YAA6B;IAE7B,MAAM,YAAY,GAAG,gBAAgB,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAC7D,IAAI,CAAC;QACH,aAAa,CACX,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,EAC9B,mBAAmB,CAAC,YAAY,CAAC,EACjC,MAAM,CACP,CAAC;QACF,aAAa,CACX,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC,EACrC,YAAY,CAAC,YAAY,CAAC,CAC3B,CAAC;QACF,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACxC,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,CAAC;QAC3D,CAAC;QACD,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QACrE,OAAO,UAAU,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC;IACpD,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,aAAqB,EACrB,eAAuB;IAEvB,SAAS,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,eAAe,CAAC,EAAE;QACnE,KAAK,EAAE,QAAQ;KAChB,CAAC,CAAC;IACH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,SAAS,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAC;IAChE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,WAAmB,EACnB,OAAe;IAEf,MAAM,IAAI,GAAG,WAAW,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,IAAI,OAAO,UAAU,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,YAA6B,EAC7B,UAAkB;IAElB,MAAM,KAAK,GAAG,wBAAwB,CAAC,YAAY,CAAC,CAAC;IACrD,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,aAAa,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,mBAAmB,CAAC,YAA6B;IACxD,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,IAAI;QAC5B,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,OAAO;QAClC,SAAS,EAAE,YAAY,CAAC,QAAQ;QAChC,OAAO,EAAE,YAAY,CAAC,eAAe;KACtC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,UAAU,CACjB,OAAe,EACf,aAAuB,EACvB,KAAc;IAEd,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,aAAa,EAAE;QAC/C,KAAK;QACL,QAAQ,EAAE,QAAQ;QAClB,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;KAC5B,CAAC,CAAC;IACH,IAAK,MAAM,CAAC,KAA2C,EAAE,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC3E,MAAM,SAAS,CAAC,WAAW,CACzB,GAAG,OAAO,kDAAkD,CAC7D,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QACvD,MAAM,SAAS,CAAC,SAAS,CACvB,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,SAAS,CACnD,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,MAAgB,CAAC;AACjC,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface LoginOptions {
2
+ servers: string[];
3
+ email: string;
4
+ credentialId?: string;
5
+ passkeyKey?: string;
6
+ publicKey?: string;
7
+ sshAgent: boolean;
8
+ }
9
+ export declare function parseLoginArguments(argumentsList: string[]): LoginOptions;
10
+ export declare function runLoginCommand(argumentsList: string[], sessionRoot: string): Promise<void>;
11
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/auth/login.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,YAAY,CAwEzE;AAED,wBAAsB,eAAe,CACnC,aAAa,EAAE,MAAM,EAAE,EACvB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAoBf"}
@@ -0,0 +1,84 @@
1
+ import { PrayError } from "../errors.js";
2
+ import { loginWithPasskey } from "./passkey.js";
3
+ import { loginWithSshAgent } from "./ssh-agent.js";
4
+ export function parseLoginArguments(argumentsList) {
5
+ const servers = [];
6
+ let email;
7
+ let credentialId;
8
+ let passkeyKey;
9
+ let publicKey;
10
+ let sshAgent = false;
11
+ for (let index = 0; index < argumentsList.length; index += 1) {
12
+ const argument = argumentsList[index];
13
+ const next = () => {
14
+ const value = argumentsList[index + 1];
15
+ if (!value) {
16
+ throw PrayError.unsupported(`login requires a value after ${argument}`);
17
+ }
18
+ index += 1;
19
+ return value;
20
+ };
21
+ switch (argument) {
22
+ case "--server":
23
+ servers.push(next());
24
+ break;
25
+ case "--email":
26
+ email = next();
27
+ break;
28
+ case "--credential-id":
29
+ credentialId = next();
30
+ break;
31
+ case "--passkey-key":
32
+ passkeyKey = next();
33
+ break;
34
+ case "--public-key":
35
+ publicKey = next();
36
+ break;
37
+ case "--ssh-agent":
38
+ sshAgent = true;
39
+ break;
40
+ default:
41
+ if (argument.startsWith("--")) {
42
+ throw PrayError.unsupported(`unknown login flag: ${argument}`);
43
+ }
44
+ throw PrayError.unsupported(`unexpected login argument: ${argument}`);
45
+ }
46
+ }
47
+ if (servers.length === 0) {
48
+ throw PrayError.unsupported("login requires at least one --server URL");
49
+ }
50
+ if (!email) {
51
+ throw PrayError.unsupported("login requires --email ADDRESS");
52
+ }
53
+ const passkeyMode = passkeyKey !== undefined;
54
+ if (passkeyMode === sshAgent || (!passkeyMode && !publicKey && !sshAgent)) {
55
+ throw PrayError.unsupported("login requires exactly one authentication mode");
56
+ }
57
+ if (passkeyMode && !credentialId) {
58
+ throw PrayError.unsupported("passkey login requires --credential-id");
59
+ }
60
+ if (sshAgent && !publicKey) {
61
+ throw PrayError.unsupported("ssh-agent login requires --public-key");
62
+ }
63
+ return {
64
+ servers,
65
+ email,
66
+ credentialId,
67
+ passkeyKey,
68
+ publicKey,
69
+ sshAgent,
70
+ };
71
+ }
72
+ export async function runLoginCommand(argumentsList, sessionRoot) {
73
+ const options = parseLoginArguments(argumentsList);
74
+ for (const server of options.servers) {
75
+ const session = options.passkeyKey
76
+ ? await loginWithPasskey(server, options.credentialId, options.passkeyKey, sessionRoot)
77
+ : await loginWithSshAgent(server, options.publicKey, sessionRoot);
78
+ if (session.email !== options.email) {
79
+ throw PrayError.resolution(`login completed for ${session.email} but ${options.email} was requested`);
80
+ }
81
+ process.stdout.write(`logged in as ${session.email} via ${session.kind} on ${server}\n`);
82
+ }
83
+ }
84
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/auth/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAWnD,MAAM,UAAU,mBAAmB,CAAC,aAAuB;IACzD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,KAAyB,CAAC;IAC9B,IAAI,YAAgC,CAAC;IACrC,IAAI,UAA8B,CAAC;IACnC,IAAI,SAA6B,CAAC;IAClC,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,aAAa,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC7D,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,CAAE,CAAC;QACvC,MAAM,IAAI,GAAG,GAAW,EAAE;YACxB,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YACvC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,SAAS,CAAC,WAAW,CAAC,gCAAgC,QAAQ,EAAE,CAAC,CAAC;YAC1E,CAAC;YACD,KAAK,IAAI,CAAC,CAAC;YACX,OAAO,KAAK,CAAC;QACf,CAAC,CAAC;QACF,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,UAAU;gBACb,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;gBACrB,MAAM;YACR,KAAK,SAAS;gBACZ,KAAK,GAAG,IAAI,EAAE,CAAC;gBACf,MAAM;YACR,KAAK,iBAAiB;gBACpB,YAAY,GAAG,IAAI,EAAE,CAAC;gBACtB,MAAM;YACR,KAAK,eAAe;gBAClB,UAAU,GAAG,IAAI,EAAE,CAAC;gBACpB,MAAM;YACR,KAAK,cAAc;gBACjB,SAAS,GAAG,IAAI,EAAE,CAAC;gBACnB,MAAM;YACR,KAAK,aAAa;gBAChB,QAAQ,GAAG,IAAI,CAAC;gBAChB,MAAM;YACR;gBACE,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC9B,MAAM,SAAS,CAAC,WAAW,CAAC,uBAAuB,QAAQ,EAAE,CAAC,CAAC;gBACjE,CAAC;gBACD,MAAM,SAAS,CAAC,WAAW,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,SAAS,CAAC,WAAW,CAAC,0CAA0C,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,SAAS,CAAC,WAAW,CAAC,gCAAgC,CAAC,CAAC;IAChE,CAAC;IACD,MAAM,WAAW,GAAG,UAAU,KAAK,SAAS,CAAC;IAC7C,IAAI,WAAW,KAAK,QAAQ,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,SAAS,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1E,MAAM,SAAS,CAAC,WAAW,CACzB,gDAAgD,CACjD,CAAC;IACJ,CAAC;IACD,IAAI,WAAW,IAAI,CAAC,YAAY,EAAE,CAAC;QACjC,MAAM,SAAS,CAAC,WAAW,CAAC,wCAAwC,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,QAAQ,IAAI,CAAC,SAAS,EAAE,CAAC;QAC3B,MAAM,SAAS,CAAC,WAAW,CAAC,uCAAuC,CAAC,CAAC;IACvE,CAAC;IAED,OAAO;QACL,OAAO;QACP,KAAK;QACL,YAAY;QACZ,UAAU;QACV,SAAS;QACT,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,aAAuB,EACvB,WAAmB;IAEnB,MAAM,OAAO,GAAG,mBAAmB,CAAC,aAAa,CAAC,CAAC;IACnD,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU;YAChC,CAAC,CAAC,MAAM,gBAAgB,CACpB,MAAM,EACN,OAAO,CAAC,YAAa,EACrB,OAAO,CAAC,UAAU,EAClB,WAAW,CACZ;YACH,CAAC,CAAC,MAAM,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,SAAU,EAAE,WAAW,CAAC,CAAC;QACrE,IAAI,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;YACpC,MAAM,SAAS,CAAC,UAAU,CACxB,uBAAuB,OAAO,CAAC,KAAK,QAAQ,OAAO,CAAC,KAAK,gBAAgB,CAC1E,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,gBAAgB,OAAO,CAAC,KAAK,QAAQ,OAAO,CAAC,IAAI,OAAO,MAAM,IAAI,CACnE,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type SessionFile } from "./session.js";
2
+ export declare function loginWithPasskey(serverUrl: string, credentialId: string, privateKeyPath: string, sessionRoot: string): Promise<SessionFile>;
3
+ //# sourceMappingURL=passkey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passkey.d.ts","sourceRoot":"","sources":["../../src/auth/passkey.ts"],"names":[],"mappings":"AAIA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAYhE,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,WAAW,CAAC,CA8BtB"}
@@ -0,0 +1,48 @@
1
+ import { createPrivateKey, sign } from "node:crypto";
2
+ import { readFileSync } from "node:fs";
3
+ import { PrayError } from "../errors.js";
4
+ import { httpPostJson, joinUrl } from "../http/client.js";
5
+ import { persistSession } from "./session.js";
6
+ export async function loginWithPasskey(serverUrl, credentialId, privateKeyPath, sessionRoot) {
7
+ const base = trimTrailingSlash(serverUrl);
8
+ const challenge = await postJson(joinUrl(base, "v1/auth/passkeys/challenge"), { credential_id: credentialId });
9
+ const privateKeyBytes = readFileSync(privateKeyPath);
10
+ if (privateKeyBytes.length !== 32) {
11
+ throw PrayError.unsupported("passkey private key must be 32 raw bytes");
12
+ }
13
+ const privateKey = ed25519PrivateKeyFromSeed(privateKeyBytes);
14
+ const signature = sign(null, Buffer.from(challenge.challenge, "utf8"), privateKey).toString("base64");
15
+ const response = await postJson(joinUrl(base, "v1/auth/passkeys/login"), {
16
+ credential_id: credentialId,
17
+ challenge_id: challenge.challenge_id,
18
+ signature,
19
+ });
20
+ return persistSession(sessionRoot, {
21
+ server_url: serverUrl,
22
+ email: response.email,
23
+ token: response.token,
24
+ kind: "passkey",
25
+ });
26
+ }
27
+ function ed25519PrivateKeyFromSeed(seed) {
28
+ const prefix = Buffer.from("302e020100300506032b657004220420", "hex");
29
+ return createPrivateKey({
30
+ key: Buffer.concat([prefix, seed]),
31
+ format: "der",
32
+ type: "pkcs8",
33
+ });
34
+ }
35
+ async function postJson(url, body) {
36
+ const responseBody = await httpPostJson(url, "application/json", JSON.stringify(body));
37
+ try {
38
+ return JSON.parse(responseBody.toString("utf8"));
39
+ }
40
+ catch (error) {
41
+ const message = error instanceof Error ? error.message : String(error);
42
+ throw PrayError.parse("auth response", message);
43
+ }
44
+ }
45
+ function trimTrailingSlash(value) {
46
+ return value.replace(/\/+$/, "");
47
+ }
48
+ //# sourceMappingURL=passkey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passkey.js","sourceRoot":"","sources":["../../src/auth/passkey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAoB,MAAM,cAAc,CAAC;AAYhE,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAiB,EACjB,YAAoB,EACpB,cAAsB,EACtB,WAAmB;IAEnB,MAAM,IAAI,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,MAAM,QAAQ,CAC9B,OAAO,CAAC,IAAI,EAAE,4BAA4B,CAAC,EAC3C,EAAE,aAAa,EAAE,YAAY,EAAE,CAChC,CAAC;IACF,MAAM,eAAe,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC;IACrD,IAAI,eAAe,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAClC,MAAM,SAAS,CAAC,WAAW,CAAC,0CAA0C,CAAC,CAAC;IAC1E,CAAC;IACD,MAAM,UAAU,GAAG,yBAAyB,CAAC,eAAe,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,IAAI,CACpB,IAAI,EACJ,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,EACxC,UAAU,CACX,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrB,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAC7B,OAAO,CAAC,IAAI,EAAE,wBAAwB,CAAC,EACvC;QACE,aAAa,EAAE,YAAY;QAC3B,YAAY,EAAE,SAAS,CAAC,YAAY;QACpC,SAAS;KACV,CACF,CAAC;IACF,OAAO,cAAc,CAAC,WAAW,EAAE;QACjC,UAAU,EAAE,SAAS;QACrB,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,IAAI,EAAE,SAAS;KAChB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,yBAAyB,CAAC,IAAY;IAC7C,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;IACtE,OAAO,gBAAgB,CAAC;QACtB,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAClC,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,OAAO;KACd,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,QAAQ,CAAI,GAAW,EAAE,IAAa;IACnD,MAAM,YAAY,GAAG,MAAM,YAAY,CACrC,GAAG,EACH,kBAAkB,EAClB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CACrB,CAAC;IACF,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAM,CAAC;IACxD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,SAAS,CAAC,KAAK,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa;IACtC,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface SessionFile {
2
+ server_url: string;
3
+ email: string;
4
+ token: string;
5
+ kind: string;
6
+ signer_fingerprint?: string;
7
+ }
8
+ export declare function sessionFilePath(root: string): string;
9
+ export declare function persistSession(root: string, session: SessionFile): SessionFile;
10
+ export declare function loadSessions(path: string): SessionFile[] | undefined;
11
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/auth/session.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAQD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,WAAW,GACnB,WAAW,CAgBb;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,GAAG,SAAS,CAcpE"}
@@ -0,0 +1,38 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { PrayError } from "../errors.js";
4
+ export function sessionFilePath(root) {
5
+ return join(root, ".pray", "session.json");
6
+ }
7
+ export function persistSession(root, session) {
8
+ const path = sessionFilePath(root);
9
+ mkdirSync(join(path, ".."), { recursive: true });
10
+ const sessions = loadSessions(path) ?? [];
11
+ const existingIndex = sessions.findIndex((entry) => entry.server_url === session.server_url);
12
+ if (existingIndex >= 0) {
13
+ sessions[existingIndex] = session;
14
+ }
15
+ else {
16
+ sessions.push(session);
17
+ }
18
+ const document = sessions.length === 1 ? sessions[0] : { sessions };
19
+ writeFileSync(path, `${JSON.stringify(document, null, 2)}\n`, "utf8");
20
+ return session;
21
+ }
22
+ export function loadSessions(path) {
23
+ if (!existsSync(path)) {
24
+ return undefined;
25
+ }
26
+ try {
27
+ const document = JSON.parse(readFileSync(path, "utf8"));
28
+ if ("sessions" in document && Array.isArray(document.sessions)) {
29
+ return document.sessions;
30
+ }
31
+ return [document];
32
+ }
33
+ catch (error) {
34
+ const message = error instanceof Error ? error.message : String(error);
35
+ throw PrayError.parse("session file", message);
36
+ }
37
+ }
38
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/auth/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAgBzC,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,IAAY,EACZ,OAAoB;IAEpB,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACnC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC1C,MAAM,aAAa,GAAG,QAAQ,CAAC,SAAS,CACtC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,KAAK,OAAO,CAAC,UAAU,CACnD,CAAC;IACF,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;QACvB,QAAQ,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IACD,MAAM,QAAQ,GACZ,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;IACtD,aAAa,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACtE,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAoB,CAAC;QAC3E,IAAI,UAAU,IAAI,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/D,OAAO,QAAQ,CAAC,QAAQ,CAAC;QAC3B,CAAC;QACD,OAAO,CAAC,QAAuB,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,SAAS,CAAC,KAAK,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type SessionFile } from "./session.js";
2
+ export declare function loginWithSshAgent(serverUrl: string, publicKeyPath: string, sessionRoot: string): Promise<SessionFile>;
3
+ //# sourceMappingURL=ssh-agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-agent.d.ts","sourceRoot":"","sources":["../../src/auth/ssh-agent.ts"],"names":[],"mappings":"AAIA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAahE,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,WAAW,CAAC,CA0BtB"}
@@ -0,0 +1,135 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { connect } from "node:net";
3
+ import { PrayError } from "../errors.js";
4
+ import { httpPostJson, joinUrl } from "../http/client.js";
5
+ import { persistSession } from "./session.js";
6
+ export async function loginWithSshAgent(serverUrl, publicKeyPath, sessionRoot) {
7
+ const publicKey = readFileSync(publicKeyPath, "utf8").trim();
8
+ const base = trimTrailingSlash(serverUrl);
9
+ const challenge = await postJson(joinUrl(base, "v1/auth/ssh-keys/challenge"), { public_key: publicKey });
10
+ const signature = await sshAgentSign(publicKey, Buffer.from(challenge.challenge, "utf8"));
11
+ const response = await postJson(joinUrl(base, "v1/auth/ssh-keys/login"), {
12
+ public_key: publicKey,
13
+ challenge_id: challenge.challenge_id,
14
+ signature,
15
+ });
16
+ return persistSession(sessionRoot, {
17
+ server_url: serverUrl,
18
+ email: response.email,
19
+ token: response.token,
20
+ kind: "ssh_key",
21
+ signer_fingerprint: challenge.fingerprint,
22
+ });
23
+ }
24
+ async function sshAgentSign(publicKey, message) {
25
+ const agentSocket = process.env.SSH_AUTH_SOCK;
26
+ if (!agentSocket) {
27
+ throw PrayError.unsupported("SSH_AUTH_SOCK is not set");
28
+ }
29
+ const rawKeyBytes = parseSshEd25519PublicKey(publicKey);
30
+ const publicKeyBlob = Buffer.concat([
31
+ sshString(Buffer.from("ssh-ed25519")),
32
+ sshString(rawKeyBytes),
33
+ ]);
34
+ const payload = Buffer.concat([
35
+ sshString(publicKeyBlob),
36
+ sshString(message),
37
+ Buffer.from([0, 0, 0, 0]),
38
+ ]);
39
+ const response = await agentRequest(agentSocket, 13, payload);
40
+ if (response.messageType !== 14) {
41
+ throw PrayError.resolution(`ssh agent returned unexpected message type: ${response.messageType}`);
42
+ }
43
+ const signatureBlob = readSshString(response.payload, 0).value;
44
+ return parseSshSignatureBlob(signatureBlob);
45
+ }
46
+ function parseSshEd25519PublicKey(publicKey) {
47
+ const fields = publicKey.split(/\s+/);
48
+ const algorithm = fields[0];
49
+ const keyValue = fields[1];
50
+ if (!algorithm || !keyValue) {
51
+ throw PrayError.unsupported("public key must include an algorithm and key");
52
+ }
53
+ if (algorithm !== "ssh-ed25519") {
54
+ throw PrayError.unsupported(`unsupported public key algorithm: ${algorithm}`);
55
+ }
56
+ const blob = Buffer.from(keyValue, "base64");
57
+ const algorithmField = readSshString(blob, 0);
58
+ if (algorithmField.value.toString("utf8") !== "ssh-ed25519") {
59
+ throw PrayError.parse("public key", "ed25519 public key blob must start with ssh-ed25519");
60
+ }
61
+ const keyBytes = readSshString(blob, algorithmField.nextOffset).value;
62
+ if (keyBytes.length !== 32) {
63
+ throw PrayError.parse("public key", "ed25519 public key must be 32 bytes");
64
+ }
65
+ return keyBytes;
66
+ }
67
+ function parseSshSignatureBlob(signatureBlob) {
68
+ const algorithm = readSshString(signatureBlob, 0);
69
+ if (algorithm.value.toString("utf8") !== "ssh-ed25519") {
70
+ throw PrayError.unsupported(`unsupported ssh signature algorithm: ${algorithm.value.toString("utf8")}`);
71
+ }
72
+ const signature = readSshString(signatureBlob, algorithm.nextOffset).value;
73
+ return signature.toString("base64");
74
+ }
75
+ function agentRequest(socketPath, messageType, payload) {
76
+ return new Promise((resolve, reject) => {
77
+ const socket = connect(socketPath);
78
+ const chunks = [];
79
+ socket.on("error", (error) => reject(error));
80
+ socket.on("data", (chunk) => chunks.push(chunk));
81
+ socket.on("end", () => {
82
+ try {
83
+ resolve(parseAgentResponse(Buffer.concat(chunks)));
84
+ }
85
+ catch (error) {
86
+ reject(error);
87
+ }
88
+ });
89
+ const body = Buffer.concat([Buffer.from([messageType]), payload]);
90
+ const frame = Buffer.alloc(4 + body.length);
91
+ frame.writeUInt32BE(body.length, 0);
92
+ body.copy(frame, 4);
93
+ socket.end(frame);
94
+ });
95
+ }
96
+ function parseAgentResponse(buffer) {
97
+ if (buffer.length < 5) {
98
+ throw PrayError.resolution("empty ssh agent response");
99
+ }
100
+ const length = buffer.readUInt32BE(0);
101
+ const body = buffer.subarray(4, 4 + length);
102
+ return { messageType: body[0], payload: body.subarray(1) };
103
+ }
104
+ function sshString(bytes) {
105
+ const buffer = Buffer.alloc(4 + bytes.length);
106
+ buffer.writeUInt32BE(bytes.length, 0);
107
+ bytes.copy(buffer, 4);
108
+ return buffer;
109
+ }
110
+ function readSshString(buffer, offset) {
111
+ if (buffer.length < offset + 4) {
112
+ throw PrayError.resolution("truncated ssh field");
113
+ }
114
+ const length = buffer.readUInt32BE(offset);
115
+ const start = offset + 4;
116
+ const end = start + length;
117
+ if (buffer.length < end) {
118
+ throw PrayError.resolution("truncated ssh agent response");
119
+ }
120
+ return { value: buffer.subarray(start, end), nextOffset: end };
121
+ }
122
+ async function postJson(url, body) {
123
+ const responseBody = await httpPostJson(url, "application/json", JSON.stringify(body));
124
+ try {
125
+ return JSON.parse(responseBody.toString("utf8"));
126
+ }
127
+ catch (error) {
128
+ const message = error instanceof Error ? error.message : String(error);
129
+ throw PrayError.parse("auth response", message);
130
+ }
131
+ }
132
+ function trimTrailingSlash(value) {
133
+ return value.replace(/\/+$/, "");
134
+ }
135
+ //# sourceMappingURL=ssh-agent.js.map