@orizm/cli 2.2.7 → 3.0.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 (320) hide show
  1. package/README.md +111 -4
  2. package/dist/array-update-CMFUoQEe.mjs +41 -0
  3. package/dist/array-update-CMFUoQEe.mjs.map +1 -0
  4. package/dist/array-update-Dch4e9tI.cjs +58 -0
  5. package/dist/array-update-Dch4e9tI.cjs.map +1 -0
  6. package/dist/auth-BGW072BP.mjs +18 -0
  7. package/dist/auth-BGW072BP.mjs.map +1 -0
  8. package/dist/auth-CNbONZuf.cjs +18 -0
  9. package/dist/auth-CNbONZuf.cjs.map +1 -0
  10. package/dist/bucket-6d3VNt1D.mjs +17 -0
  11. package/dist/bucket-6d3VNt1D.mjs.map +1 -0
  12. package/dist/bucket-DjbHz9_A.cjs +17 -0
  13. package/dist/bucket-DjbHz9_A.cjs.map +1 -0
  14. package/dist/cli/main.cjs +231 -0
  15. package/dist/cli/main.cjs.map +1 -0
  16. package/dist/cli/main.d.cts +1 -0
  17. package/dist/cli/main.d.mts +1 -0
  18. package/dist/cli/main.mjs +196 -0
  19. package/dist/cli/main.mjs.map +1 -0
  20. package/dist/cms-BJnovGYT.mjs +172 -0
  21. package/dist/cms-BJnovGYT.mjs.map +1 -0
  22. package/dist/cms-Cnx-lDGu.cjs +172 -0
  23. package/dist/cms-Cnx-lDGu.cjs.map +1 -0
  24. package/dist/codegen-BF5b-u46.cjs +17 -0
  25. package/dist/codegen-BF5b-u46.cjs.map +1 -0
  26. package/dist/codegen-DZOB4ttR.mjs +17 -0
  27. package/dist/codegen-DZOB4ttR.mjs.map +1 -0
  28. package/dist/config/index.cjs +49 -96
  29. package/dist/config/index.cjs.map +1 -1
  30. package/dist/config/index.d.cts +1 -53
  31. package/dist/config/{index.d.ts → index.d.mts} +29 -27
  32. package/dist/config/index.d.mts.map +1 -0
  33. package/dist/config/index.mjs +59 -0
  34. package/dist/config/index.mjs.map +1 -0
  35. package/dist/config-loader-BEgS869e.mjs +65 -0
  36. package/dist/config-loader-BEgS869e.mjs.map +1 -0
  37. package/dist/config-loader-D8x32gEU.cjs +78 -0
  38. package/dist/config-loader-D8x32gEU.cjs.map +1 -0
  39. package/dist/confirm-delete-B9o73U7B.cjs +19 -0
  40. package/dist/confirm-delete-B9o73U7B.cjs.map +1 -0
  41. package/dist/confirm-delete-CsWkW69-.mjs +14 -0
  42. package/dist/confirm-delete-CsWkW69-.mjs.map +1 -0
  43. package/dist/consumer-BBsH8b1j.cjs +18 -0
  44. package/dist/consumer-BBsH8b1j.cjs.map +1 -0
  45. package/dist/consumer-DqyRfpsl.mjs +18 -0
  46. package/dist/consumer-DqyRfpsl.mjs.map +1 -0
  47. package/dist/consumer-OF6Z_eTP.cjs +95 -0
  48. package/dist/consumer-OF6Z_eTP.cjs.map +1 -0
  49. package/dist/consumer-pU2HyiyA.mjs +95 -0
  50. package/dist/consumer-pU2HyiyA.mjs.map +1 -0
  51. package/dist/content-BsoRmjis.mjs +20 -0
  52. package/dist/content-BsoRmjis.mjs.map +1 -0
  53. package/dist/content-Y-2Y0cyn.cjs +20 -0
  54. package/dist/content-Y-2Y0cyn.cjs.map +1 -0
  55. package/dist/create--1NYduI_.cjs +58 -0
  56. package/dist/create--1NYduI_.cjs.map +1 -0
  57. package/dist/create-B-PAOor6.mjs +66 -0
  58. package/dist/create-B-PAOor6.mjs.map +1 -0
  59. package/dist/create-BNYWcyuQ.cjs +66 -0
  60. package/dist/create-BNYWcyuQ.cjs.map +1 -0
  61. package/dist/create-B_gsZCL-.cjs +54 -0
  62. package/dist/create-B_gsZCL-.cjs.map +1 -0
  63. package/dist/create-BqlxdhcR.mjs +81 -0
  64. package/dist/create-BqlxdhcR.mjs.map +1 -0
  65. package/dist/create-CC814ixh.mjs +66 -0
  66. package/dist/create-CC814ixh.mjs.map +1 -0
  67. package/dist/create-CkFBiEDH.mjs +58 -0
  68. package/dist/create-CkFBiEDH.mjs.map +1 -0
  69. package/dist/create-CykRHseR.cjs +81 -0
  70. package/dist/create-CykRHseR.cjs.map +1 -0
  71. package/dist/create-RLyp_dl6.mjs +54 -0
  72. package/dist/create-RLyp_dl6.mjs.map +1 -0
  73. package/dist/create-Z-z3LXNW.cjs +66 -0
  74. package/dist/create-Z-z3LXNW.cjs.map +1 -0
  75. package/dist/delete-8yZ3j0vX.cjs +59 -0
  76. package/dist/delete-8yZ3j0vX.cjs.map +1 -0
  77. package/dist/delete-BOUObrDw.mjs +48 -0
  78. package/dist/delete-BOUObrDw.mjs.map +1 -0
  79. package/dist/delete-BSLIXrAh.mjs +59 -0
  80. package/dist/delete-BSLIXrAh.mjs.map +1 -0
  81. package/dist/delete-BenBNL2p.mjs +56 -0
  82. package/dist/delete-BenBNL2p.mjs.map +1 -0
  83. package/dist/delete-Bx2oNROv.cjs +56 -0
  84. package/dist/delete-Bx2oNROv.cjs.map +1 -0
  85. package/dist/delete-CCTiCYIL.cjs +51 -0
  86. package/dist/delete-CCTiCYIL.cjs.map +1 -0
  87. package/dist/delete-CGW0VMK6.cjs +56 -0
  88. package/dist/delete-CGW0VMK6.cjs.map +1 -0
  89. package/dist/delete-CIYY59v_.cjs +48 -0
  90. package/dist/delete-CIYY59v_.cjs.map +1 -0
  91. package/dist/delete-CSSd0gmt.mjs +56 -0
  92. package/dist/delete-CSSd0gmt.mjs.map +1 -0
  93. package/dist/delete-CSs5Czlo.mjs +59 -0
  94. package/dist/delete-CSs5Czlo.mjs.map +1 -0
  95. package/dist/delete-CrOVRvMo.cjs +56 -0
  96. package/dist/delete-CrOVRvMo.cjs.map +1 -0
  97. package/dist/delete-DehKYCXh.mjs +56 -0
  98. package/dist/delete-DehKYCXh.mjs.map +1 -0
  99. package/dist/delete-DhSU-Lx2.mjs +51 -0
  100. package/dist/delete-DhSU-Lx2.mjs.map +1 -0
  101. package/dist/delete-DozSxZQ7.cjs +59 -0
  102. package/dist/delete-DozSxZQ7.cjs.map +1 -0
  103. package/dist/detail-8CXNIhKw.cjs +16 -0
  104. package/dist/detail-8CXNIhKw.cjs.map +1 -0
  105. package/dist/detail-DN5jCQ4N.mjs +10 -0
  106. package/dist/detail-DN5jCQ4N.mjs.map +1 -0
  107. package/dist/download-oFGzg30E.mjs +68 -0
  108. package/dist/download-oFGzg30E.mjs.map +1 -0
  109. package/dist/download-ogGbb3FU.cjs +68 -0
  110. package/dist/download-ogGbb3FU.cjs.map +1 -0
  111. package/dist/erd-lKC5NB2l.cjs +124 -0
  112. package/dist/erd-lKC5NB2l.cjs.map +1 -0
  113. package/dist/erd-zDoF6I_y.mjs +123 -0
  114. package/dist/erd-zDoF6I_y.mjs.map +1 -0
  115. package/dist/get-BBOKSXkh.cjs +48 -0
  116. package/dist/get-BBOKSXkh.cjs.map +1 -0
  117. package/dist/get-BHniACk5.cjs +57 -0
  118. package/dist/get-BHniACk5.cjs.map +1 -0
  119. package/dist/get-BtmzDaVn.mjs +47 -0
  120. package/dist/get-BtmzDaVn.mjs.map +1 -0
  121. package/dist/get-CVV3h6HR.cjs +47 -0
  122. package/dist/get-CVV3h6HR.cjs.map +1 -0
  123. package/dist/get-CgEgETQa.mjs +52 -0
  124. package/dist/get-CgEgETQa.mjs.map +1 -0
  125. package/dist/get-DB80UNSR.mjs +47 -0
  126. package/dist/get-DB80UNSR.mjs.map +1 -0
  127. package/dist/get-DBxhbN1G.mjs +57 -0
  128. package/dist/get-DBxhbN1G.mjs.map +1 -0
  129. package/dist/get-DDB89cOs.mjs +48 -0
  130. package/dist/get-DDB89cOs.mjs.map +1 -0
  131. package/dist/get-DPGx1zU4.mjs +56 -0
  132. package/dist/get-DPGx1zU4.mjs.map +1 -0
  133. package/dist/get-IOU__2RP.cjs +52 -0
  134. package/dist/get-IOU__2RP.cjs.map +1 -0
  135. package/dist/get-KdWfYINc.cjs +47 -0
  136. package/dist/get-KdWfYINc.cjs.map +1 -0
  137. package/dist/get-jwXRlIBJ.cjs +57 -0
  138. package/dist/get-jwXRlIBJ.cjs.map +1 -0
  139. package/dist/group-roles-BEEzLxPX.mjs +36 -0
  140. package/dist/group-roles-BEEzLxPX.mjs.map +1 -0
  141. package/dist/group-roles-Bl_mEodO.cjs +59 -0
  142. package/dist/group-roles-Bl_mEodO.cjs.map +1 -0
  143. package/dist/invite-DsOCKGTJ.mjs +66 -0
  144. package/dist/invite-DsOCKGTJ.mjs.map +1 -0
  145. package/dist/invite-Dts9uNQL.cjs +66 -0
  146. package/dist/invite-Dts9uNQL.cjs.map +1 -0
  147. package/dist/key-BogfSiz_.mjs +17 -0
  148. package/dist/key-BogfSiz_.mjs.map +1 -0
  149. package/dist/key-Czwiu2pW.cjs +17 -0
  150. package/dist/key-Czwiu2pW.cjs.map +1 -0
  151. package/dist/link-BluFyxEL.mjs +42 -0
  152. package/dist/link-BluFyxEL.mjs.map +1 -0
  153. package/dist/link-DYu1Vjlw.cjs +42 -0
  154. package/dist/link-DYu1Vjlw.cjs.map +1 -0
  155. package/dist/list-2BpPj4Z0.cjs +40 -0
  156. package/dist/list-2BpPj4Z0.cjs.map +1 -0
  157. package/dist/list-57TUfNFd.mjs +48 -0
  158. package/dist/list-57TUfNFd.mjs.map +1 -0
  159. package/dist/list-60NcDr0q.cjs +81 -0
  160. package/dist/list-60NcDr0q.cjs.map +1 -0
  161. package/dist/list-BRh59EqI.cjs +35 -0
  162. package/dist/list-BRh59EqI.cjs.map +1 -0
  163. package/dist/list-BwfpuhmJ.cjs +37 -0
  164. package/dist/list-BwfpuhmJ.cjs.map +1 -0
  165. package/dist/list-CJuefq_I.cjs +82 -0
  166. package/dist/list-CJuefq_I.cjs.map +1 -0
  167. package/dist/list-CYE9Exi3.cjs +72 -0
  168. package/dist/list-CYE9Exi3.cjs.map +1 -0
  169. package/dist/list-CbvEh7eA.mjs +35 -0
  170. package/dist/list-CbvEh7eA.mjs.map +1 -0
  171. package/dist/list-CfIeReBx.mjs +82 -0
  172. package/dist/list-CfIeReBx.mjs.map +1 -0
  173. package/dist/list-CxHDoXjv.mjs +81 -0
  174. package/dist/list-CxHDoXjv.mjs.map +1 -0
  175. package/dist/list-D0-QrWmn.cjs +51 -0
  176. package/dist/list-D0-QrWmn.cjs.map +1 -0
  177. package/dist/list-D24J_Qbm.mjs +49 -0
  178. package/dist/list-D24J_Qbm.mjs.map +1 -0
  179. package/dist/list-D5PSDMWw.mjs +51 -0
  180. package/dist/list-D5PSDMWw.mjs.map +1 -0
  181. package/dist/list-DRKF2uKW.cjs +95 -0
  182. package/dist/list-DRKF2uKW.cjs.map +1 -0
  183. package/dist/list-DdJ05juK.mjs +72 -0
  184. package/dist/list-DdJ05juK.mjs.map +1 -0
  185. package/dist/list-DlJssPwy.cjs +48 -0
  186. package/dist/list-DlJssPwy.cjs.map +1 -0
  187. package/dist/list-V3W6hvOa.cjs +49 -0
  188. package/dist/list-V3W6hvOa.cjs.map +1 -0
  189. package/dist/list-rAn3uOA7.mjs +37 -0
  190. package/dist/list-rAn3uOA7.mjs.map +1 -0
  191. package/dist/list-syVDGkVR.mjs +40 -0
  192. package/dist/list-syVDGkVR.mjs.map +1 -0
  193. package/dist/list-yQZLzkC7.mjs +95 -0
  194. package/dist/list-yQZLzkC7.mjs.map +1 -0
  195. package/dist/login-2XcHd4wn.cjs +212 -0
  196. package/dist/login-2XcHd4wn.cjs.map +1 -0
  197. package/dist/login-FE_dbWMo.mjs +211 -0
  198. package/dist/login-FE_dbWMo.mjs.map +1 -0
  199. package/dist/logout-BDbWrGBm.mjs +35 -0
  200. package/dist/logout-BDbWrGBm.mjs.map +1 -0
  201. package/dist/logout-DC5TMJ5_.cjs +35 -0
  202. package/dist/logout-DC5TMJ5_.cjs.map +1 -0
  203. package/dist/management-BaN1Nynl.mjs +19 -0
  204. package/dist/management-BaN1Nynl.mjs.map +1 -0
  205. package/dist/management-DHXxdCra.cjs +19 -0
  206. package/dist/management-DHXxdCra.cjs.map +1 -0
  207. package/dist/mask-B1qD73jb.mjs +22 -0
  208. package/dist/mask-B1qD73jb.mjs.map +1 -0
  209. package/dist/mask-CqYLib9p.cjs +40 -0
  210. package/dist/mask-CqYLib9p.cjs.map +1 -0
  211. package/dist/oauth-client-CdD0evAV.cjs +170 -0
  212. package/dist/oauth-client-CdD0evAV.cjs.map +1 -0
  213. package/dist/oauth-client-QHuDa4fW.mjs +139 -0
  214. package/dist/oauth-client-QHuDa4fW.mjs.map +1 -0
  215. package/dist/object-BfUf8Y6w.mjs +20 -0
  216. package/dist/object-BfUf8Y6w.mjs.map +1 -0
  217. package/dist/object-DT7UEW9G.cjs +20 -0
  218. package/dist/object-DT7UEW9G.cjs.map +1 -0
  219. package/dist/org-C4cVovOM.cjs +14 -0
  220. package/dist/org-C4cVovOM.cjs.map +1 -0
  221. package/dist/org-CPhTRTks.mjs +14 -0
  222. package/dist/org-CPhTRTks.mjs.map +1 -0
  223. package/dist/org-context-Bewx2NEW.cjs +30 -0
  224. package/dist/org-context-Bewx2NEW.cjs.map +1 -0
  225. package/dist/org-context-D0dwWC2M.mjs +25 -0
  226. package/dist/org-context-D0dwWC2M.mjs.map +1 -0
  227. package/dist/parse-BeO2IwfI.cjs +229 -0
  228. package/dist/parse-BeO2IwfI.cjs.map +1 -0
  229. package/dist/parse-CA5fBB3x.mjs +150 -0
  230. package/dist/parse-CA5fBB3x.mjs.map +1 -0
  231. package/dist/project-CNr9xMny.cjs +20 -0
  232. package/dist/project-CNr9xMny.cjs.map +1 -0
  233. package/dist/project-DFoHcXi5.mjs +20 -0
  234. package/dist/project-DFoHcXi5.mjs.map +1 -0
  235. package/dist/project-name-CEoM-OL4.cjs +18 -0
  236. package/dist/project-name-CEoM-OL4.cjs.map +1 -0
  237. package/dist/project-name-DNMejnzZ.mjs +12 -0
  238. package/dist/project-name-DNMejnzZ.mjs.map +1 -0
  239. package/dist/project-user-9D7Ey_Fu.mjs +20 -0
  240. package/dist/project-user-9D7Ey_Fu.mjs.map +1 -0
  241. package/dist/project-user-DTPFjyfZ.cjs +20 -0
  242. package/dist/project-user-DTPFjyfZ.cjs.map +1 -0
  243. package/dist/push-0u6PDz4E.cjs +166 -0
  244. package/dist/push-0u6PDz4E.cjs.map +1 -0
  245. package/dist/push-D7co0keA.mjs +166 -0
  246. package/dist/push-D7co0keA.mjs.map +1 -0
  247. package/dist/run-codegen-Ceeosw5x.cjs +272 -0
  248. package/dist/run-codegen-Ceeosw5x.cjs.map +1 -0
  249. package/dist/run-codegen-DgaFaIQ1.mjs +190 -0
  250. package/dist/run-codegen-DgaFaIQ1.mjs.map +1 -0
  251. package/dist/run-with-context-CVhmzAFZ.mjs +876 -0
  252. package/dist/run-with-context-CVhmzAFZ.mjs.map +1 -0
  253. package/dist/run-with-context-DJNnEigg.cjs +943 -0
  254. package/dist/run-with-context-DJNnEigg.cjs.map +1 -0
  255. package/dist/schema-DDzrgjkT.mjs +20 -0
  256. package/dist/schema-DDzrgjkT.mjs.map +1 -0
  257. package/dist/schema-DdhyEh81.cjs +20 -0
  258. package/dist/schema-DdhyEh81.cjs.map +1 -0
  259. package/dist/shared-CZZimGxc.mjs +35 -0
  260. package/dist/shared-CZZimGxc.mjs.map +1 -0
  261. package/dist/shared-DHRPzzKl.cjs +59 -0
  262. package/dist/shared-DHRPzzKl.cjs.map +1 -0
  263. package/dist/status-Dq_NJE71.cjs +49 -0
  264. package/dist/status-Dq_NJE71.cjs.map +1 -0
  265. package/dist/status-fWqXzV0P.mjs +49 -0
  266. package/dist/status-fWqXzV0P.mjs.map +1 -0
  267. package/dist/table-C74eOSh8.cjs +27 -0
  268. package/dist/table-C74eOSh8.cjs.map +1 -0
  269. package/dist/table-MHEfbnWO.mjs +20 -0
  270. package/dist/table-MHEfbnWO.mjs.map +1 -0
  271. package/dist/table-event-C16cp9nq.mjs +72 -0
  272. package/dist/table-event-C16cp9nq.mjs.map +1 -0
  273. package/dist/table-event-D7PPuS7E.cjs +101 -0
  274. package/dist/table-event-D7PPuS7E.cjs.map +1 -0
  275. package/dist/token-store--9GYVL7N.cjs +139 -0
  276. package/dist/token-store--9GYVL7N.cjs.map +1 -0
  277. package/dist/token-store-reCGF86F.mjs +124 -0
  278. package/dist/token-store-reCGF86F.mjs.map +1 -0
  279. package/dist/update-8e3u4jKa.mjs +109 -0
  280. package/dist/update-8e3u4jKa.mjs.map +1 -0
  281. package/dist/update-CDLviRuu.cjs +73 -0
  282. package/dist/update-CDLviRuu.cjs.map +1 -0
  283. package/dist/update-CSiOfiPL.mjs +117 -0
  284. package/dist/update-CSiOfiPL.mjs.map +1 -0
  285. package/dist/update-CjbcI8Qc.mjs +61 -0
  286. package/dist/update-CjbcI8Qc.mjs.map +1 -0
  287. package/dist/update-Cktd0zXA.cjs +109 -0
  288. package/dist/update-Cktd0zXA.cjs.map +1 -0
  289. package/dist/update-D-X32BVW.cjs +117 -0
  290. package/dist/update-D-X32BVW.cjs.map +1 -0
  291. package/dist/update-DfYV_TQb.mjs +171 -0
  292. package/dist/update-DfYV_TQb.mjs.map +1 -0
  293. package/dist/update-OWC5K8Ne.cjs +61 -0
  294. package/dist/update-OWC5K8Ne.cjs.map +1 -0
  295. package/dist/update-ap5Qv1Yl.cjs +171 -0
  296. package/dist/update-ap5Qv1Yl.cjs.map +1 -0
  297. package/dist/update-yscrx6WQ.mjs +73 -0
  298. package/dist/update-yscrx6WQ.mjs.map +1 -0
  299. package/dist/upload-C43ZXxyb.cjs +95 -0
  300. package/dist/upload-C43ZXxyb.cjs.map +1 -0
  301. package/dist/upload-DGgJ1TQk.mjs +94 -0
  302. package/dist/upload-DGgJ1TQk.mjs.map +1 -0
  303. package/dist/validate-BpxZ8LTl.cjs +31 -0
  304. package/dist/validate-BpxZ8LTl.cjs.map +1 -0
  305. package/dist/validate-Ca0CRo16.mjs +31 -0
  306. package/dist/validate-Ca0CRo16.mjs.map +1 -0
  307. package/dist/webhook-3zs6Ulxd.mjs +20 -0
  308. package/dist/webhook-3zs6Ulxd.mjs.map +1 -0
  309. package/dist/webhook-BsygMMf-.cjs +20 -0
  310. package/dist/webhook-BsygMMf-.cjs.map +1 -0
  311. package/package.json +27 -16
  312. package/bin/index.js +0 -3
  313. package/dist/cli.cjs +0 -1978
  314. package/dist/cli.cjs.map +0 -1
  315. package/dist/cli.d.cts +0 -2
  316. package/dist/cli.d.ts +0 -2
  317. package/dist/cli.js +0 -1954
  318. package/dist/cli.js.map +0 -1
  319. package/dist/config/index.js +0 -81
  320. package/dist/config/index.js.map +0 -1
@@ -0,0 +1,101 @@
1
+ const require_parse = require('./parse-BeO2IwfI.cjs');
2
+ let _praha_byethrow = require("@praha/byethrow");
3
+
4
+ //#region src/cli/commands/webhook/table-event.ts
5
+ const VALID_EVENTS = [
6
+ "content.create",
7
+ "content.update",
8
+ "content.delete"
9
+ ];
10
+ function parseTableEvents(flag, value) {
11
+ if (value === void 0) return _praha_byethrow.Result.succeed(void 0);
12
+ const items = require_parse.parseRepeatableFlag(flag, value);
13
+ if (_praha_byethrow.Result.isFailure(items)) return items;
14
+ const tableEvents = [];
15
+ for (const item of items.value) {
16
+ const pair = require_parse.splitColonPair(flag, item, "<table>:<event>");
17
+ if (_praha_byethrow.Result.isFailure(pair)) return pair;
18
+ const [tableName, event] = pair.value;
19
+ const matched = VALID_EVENTS.find((candidate) => candidate === event);
20
+ if (matched === void 0) return _praha_byethrow.Result.fail({ message: `Invalid --${flag} value: ${item}. Valid events: ${VALID_EVENTS.join(", ")}.` });
21
+ const existing = tableEvents.find((entry) => entry.tableName === tableName);
22
+ if (existing === void 0) tableEvents.push({
23
+ tableName,
24
+ events: [matched]
25
+ });
26
+ else if (!existing.events.includes(matched)) existing.events.push(matched);
27
+ }
28
+ return _praha_byethrow.Result.succeed(tableEvents);
29
+ }
30
+ function addTableEvents(current, additions) {
31
+ const merged = current.map((entry) => ({
32
+ tableName: entry.tableName,
33
+ events: [...entry.events]
34
+ }));
35
+ for (const addition of additions) {
36
+ const existing = merged.find((entry) => entry.tableName === addition.tableName);
37
+ if (existing === void 0) {
38
+ merged.push({
39
+ tableName: addition.tableName,
40
+ events: [...addition.events]
41
+ });
42
+ continue;
43
+ }
44
+ for (const event of addition.events) if (!existing.events.includes(event)) existing.events.push(event);
45
+ }
46
+ return merged;
47
+ }
48
+ function removeTableEvents(current, removals) {
49
+ return current.map((entry) => {
50
+ const removal = removals.find((candidate) => candidate.tableName === entry.tableName);
51
+ if (removal === void 0) return entry;
52
+ return {
53
+ tableName: entry.tableName,
54
+ events: entry.events.filter((event) => !removal.events.includes(event))
55
+ };
56
+ }).filter((entry) => entry.events.length > 0);
57
+ }
58
+ function missingTableEventRemovals(current, removals) {
59
+ const missing = [];
60
+ for (const removal of removals) {
61
+ const entry = current.find((candidate) => candidate.tableName === removal.tableName);
62
+ for (const event of removal.events) if (entry === void 0 || !entry.events.includes(event)) missing.push(`${removal.tableName}:${event}`);
63
+ }
64
+ return missing;
65
+ }
66
+ function formatTableEvents(tableEvents) {
67
+ return tableEvents.map((entry) => `${entry.tableName}:${entry.events.join("|")}`).join(", ");
68
+ }
69
+
70
+ //#endregion
71
+ Object.defineProperty(exports, 'addTableEvents', {
72
+ enumerable: true,
73
+ get: function () {
74
+ return addTableEvents;
75
+ }
76
+ });
77
+ Object.defineProperty(exports, 'formatTableEvents', {
78
+ enumerable: true,
79
+ get: function () {
80
+ return formatTableEvents;
81
+ }
82
+ });
83
+ Object.defineProperty(exports, 'missingTableEventRemovals', {
84
+ enumerable: true,
85
+ get: function () {
86
+ return missingTableEventRemovals;
87
+ }
88
+ });
89
+ Object.defineProperty(exports, 'parseTableEvents', {
90
+ enumerable: true,
91
+ get: function () {
92
+ return parseTableEvents;
93
+ }
94
+ });
95
+ Object.defineProperty(exports, 'removeTableEvents', {
96
+ enumerable: true,
97
+ get: function () {
98
+ return removeTableEvents;
99
+ }
100
+ });
101
+ //# sourceMappingURL=table-event-D7PPuS7E.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-event-D7PPuS7E.cjs","names":["Result","parseRepeatableFlag","splitColonPair"],"sources":["../src/cli/commands/webhook/table-event.ts"],"sourcesContent":["import { Result } from \"@praha/byethrow\";\nimport type { CommandFailure } from \"../define-command.js\";\nimport { parseRepeatableFlag, splitColonPair } from \"../parse.js\";\n\nexport type WebhookEventType =\n | \"content.create\"\n | \"content.update\"\n | \"content.delete\";\n\nexport type TableEvent = { tableName: string; events: WebhookEventType[] };\n\nconst VALID_EVENTS: WebhookEventType[] = [\n \"content.create\",\n \"content.update\",\n \"content.delete\",\n];\n\n// CLI は <table>:<event> を 1 件ずつ受けるが、API の tableEvents は\n// { tableName, events[] } の形なので、同一テーブルを 1 エントリに集約する。\nexport function parseTableEvents(\n flag: string,\n value: unknown,\n): Result.Result<TableEvent[] | undefined, CommandFailure> {\n if (value === undefined) return Result.succeed(undefined);\n\n const items = parseRepeatableFlag(flag, value);\n if (Result.isFailure(items)) return items;\n\n const tableEvents: TableEvent[] = [];\n for (const item of items.value) {\n const pair = splitColonPair(flag, item, \"<table>:<event>\");\n if (Result.isFailure(pair)) return pair;\n\n const [tableName, event] = pair.value;\n const matched = VALID_EVENTS.find((candidate) => candidate === event);\n if (matched === undefined) {\n return Result.fail({\n message: `Invalid --${flag} value: ${item}. Valid events: ${VALID_EVENTS.join(\", \")}.`,\n });\n }\n\n const existing = tableEvents.find((entry) => entry.tableName === tableName);\n if (existing === undefined) {\n tableEvents.push({ tableName, events: [matched] });\n } else if (!existing.events.includes(matched)) {\n existing.events.push(matched);\n }\n }\n return Result.succeed(tableEvents);\n}\n\nexport function addTableEvents(\n current: TableEvent[],\n additions: TableEvent[],\n): TableEvent[] {\n const merged = current.map((entry) => ({\n tableName: entry.tableName,\n events: [...entry.events],\n }));\n for (const addition of additions) {\n const existing = merged.find(\n (entry) => entry.tableName === addition.tableName,\n );\n if (existing === undefined) {\n merged.push({\n tableName: addition.tableName,\n events: [...addition.events],\n });\n continue;\n }\n for (const event of addition.events) {\n if (!existing.events.includes(event)) existing.events.push(event);\n }\n }\n return merged;\n}\n\nexport function removeTableEvents(\n current: TableEvent[],\n removals: TableEvent[],\n): TableEvent[] {\n return current\n .map((entry) => {\n const removal = removals.find(\n (candidate) => candidate.tableName === entry.tableName,\n );\n if (removal === undefined) return entry;\n return {\n tableName: entry.tableName,\n events: entry.events.filter((event) => !removal.events.includes(event)),\n };\n })\n .filter((entry) => entry.events.length > 0);\n}\n\n// remove 指定のうち現在の購読に存在しないものを \"table:event\" 形式で列挙する。\nexport function missingTableEventRemovals(\n current: TableEvent[],\n removals: TableEvent[],\n): string[] {\n const missing: string[] = [];\n for (const removal of removals) {\n const entry = current.find(\n (candidate) => candidate.tableName === removal.tableName,\n );\n for (const event of removal.events) {\n if (entry === undefined || !entry.events.includes(event)) {\n missing.push(`${removal.tableName}:${event}`);\n }\n }\n }\n return missing;\n}\n\nexport function formatTableEvents(tableEvents: TableEvent[]): string {\n return tableEvents\n .map((entry) => `${entry.tableName}:${entry.events.join(\"|\")}`)\n .join(\", \");\n}\n"],"mappings":";;;;AAWA,MAAM,eAAmC;CACvC;CACA;CACA;AACF;AAIA,SAAgB,iBACd,MACA,OACyD;CACzD,IAAI,UAAU,QAAW,OAAOA,uBAAO,QAAQ,MAAS;CAExD,MAAM,QAAQC,kCAAoB,MAAM,KAAK;CAC7C,IAAID,uBAAO,UAAU,KAAK,GAAG,OAAO;CAEpC,MAAM,cAA4B,CAAC;CACnC,KAAK,MAAM,QAAQ,MAAM,OAAO;EAC9B,MAAM,OAAOE,6BAAe,MAAM,MAAM,iBAAiB;EACzD,IAAIF,uBAAO,UAAU,IAAI,GAAG,OAAO;EAEnC,MAAM,CAAC,WAAW,SAAS,KAAK;EAChC,MAAM,UAAU,aAAa,MAAM,cAAc,cAAc,KAAK;EACpE,IAAI,YAAY,QACd,OAAOA,uBAAO,KAAK,EACjB,SAAS,aAAa,KAAK,UAAU,KAAK,kBAAkB,aAAa,KAAK,IAAI,EAAE,GACtF,CAAC;EAGH,MAAM,WAAW,YAAY,MAAM,UAAU,MAAM,cAAc,SAAS;EAC1E,IAAI,aAAa,QACf,YAAY,KAAK;GAAE;GAAW,QAAQ,CAAC,OAAO;EAAE,CAAC;OAC5C,IAAI,CAAC,SAAS,OAAO,SAAS,OAAO,GAC1C,SAAS,OAAO,KAAK,OAAO;CAEhC;CACA,OAAOA,uBAAO,QAAQ,WAAW;AACnC;AAEA,SAAgB,eACd,SACA,WACc;CACd,MAAM,SAAS,QAAQ,KAAK,WAAW;EACrC,WAAW,MAAM;EACjB,QAAQ,CAAC,GAAG,MAAM,MAAM;CAC1B,EAAE;CACF,KAAK,MAAM,YAAY,WAAW;EAChC,MAAM,WAAW,OAAO,MACrB,UAAU,MAAM,cAAc,SAAS,SAC1C;EACA,IAAI,aAAa,QAAW;GAC1B,OAAO,KAAK;IACV,WAAW,SAAS;IACpB,QAAQ,CAAC,GAAG,SAAS,MAAM;GAC7B,CAAC;GACD;EACF;EACA,KAAK,MAAM,SAAS,SAAS,QAC3B,IAAI,CAAC,SAAS,OAAO,SAAS,KAAK,GAAG,SAAS,OAAO,KAAK,KAAK;CAEpE;CACA,OAAO;AACT;AAEA,SAAgB,kBACd,SACA,UACc;CACd,OAAO,QACJ,KAAK,UAAU;EACd,MAAM,UAAU,SAAS,MACtB,cAAc,UAAU,cAAc,MAAM,SAC/C;EACA,IAAI,YAAY,QAAW,OAAO;EAClC,OAAO;GACL,WAAW,MAAM;GACjB,QAAQ,MAAM,OAAO,QAAQ,UAAU,CAAC,QAAQ,OAAO,SAAS,KAAK,CAAC;EACxE;CACF,CAAC,CAAC,CACD,QAAQ,UAAU,MAAM,OAAO,SAAS,CAAC;AAC9C;AAGA,SAAgB,0BACd,SACA,UACU;CACV,MAAM,UAAoB,CAAC;CAC3B,KAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,QAAQ,QAAQ,MACnB,cAAc,UAAU,cAAc,QAAQ,SACjD;EACA,KAAK,MAAM,SAAS,QAAQ,QAC1B,IAAI,UAAU,UAAa,CAAC,MAAM,OAAO,SAAS,KAAK,GACrD,QAAQ,KAAK,GAAG,QAAQ,UAAU,GAAG,OAAO;CAGlD;CACA,OAAO;AACT;AAEA,SAAgB,kBAAkB,aAAmC;CACnE,OAAO,YACJ,KAAK,UAAU,GAAG,MAAM,UAAU,GAAG,MAAM,OAAO,KAAK,GAAG,GAAG,CAAC,CAC9D,KAAK,IAAI;AACd"}
@@ -0,0 +1,139 @@
1
+ const require_cli_main = require('./cli/main.cjs');
2
+ let _praha_byethrow = require("@praha/byethrow");
3
+ let valibot = require("valibot");
4
+ valibot = require_cli_main.__toESM(valibot, 1);
5
+ let node_fs_promises = require("node:fs/promises");
6
+ let node_os = require("node:os");
7
+ node_os = require_cli_main.__toESM(node_os, 1);
8
+ let node_path = require("node:path");
9
+ node_path = require_cli_main.__toESM(node_path, 1);
10
+
11
+ //#region src/cli/env.ts
12
+ const DEFAULT_BASE_URL = "https://app.orizm.com";
13
+ const trimmedUrl = valibot.pipe(valibot.string(), valibot.url(), valibot.transform((value) => value.replace(/\/+$/, "")));
14
+ const nonEmpty = valibot.pipe(valibot.string(), valibot.nonEmpty());
15
+ const EnvSchema = valibot.object({
16
+ ORIZM_BASE_URL: valibot.optional(trimmedUrl, DEFAULT_BASE_URL),
17
+ ORIZM_OAUTH_ISSUER_URL: valibot.optional(trimmedUrl),
18
+ ORIZM_API_KEY: valibot.optional(nonEmpty),
19
+ ORIZM_PROJECT: valibot.optional(nonEmpty)
20
+ });
21
+ function normalize(raw) {
22
+ if (raw === void 0) return void 0;
23
+ const trimmed = raw.trim();
24
+ return trimmed === "" ? void 0 : trimmed;
25
+ }
26
+ function resolveEnv(source = process.env) {
27
+ const parsed = valibot.safeParse(EnvSchema, {
28
+ ORIZM_BASE_URL: normalize(source.ORIZM_BASE_URL),
29
+ ORIZM_OAUTH_ISSUER_URL: normalize(source.ORIZM_OAUTH_ISSUER_URL),
30
+ ORIZM_API_KEY: normalize(source.ORIZM_API_KEY),
31
+ ORIZM_PROJECT: normalize(source.ORIZM_PROJECT)
32
+ });
33
+ if (!parsed.success) return _praha_byethrow.Result.fail({
34
+ type: "invalid_env",
35
+ issues: parsed.issues
36
+ });
37
+ const { ORIZM_BASE_URL, ORIZM_OAUTH_ISSUER_URL, ORIZM_API_KEY, ORIZM_PROJECT } = parsed.output;
38
+ return _praha_byethrow.Result.succeed({
39
+ baseUrl: ORIZM_BASE_URL,
40
+ issuerUrl: ORIZM_OAUTH_ISSUER_URL ?? ORIZM_BASE_URL,
41
+ apiKey: ORIZM_API_KEY,
42
+ project: ORIZM_PROJECT
43
+ });
44
+ }
45
+
46
+ //#endregion
47
+ //#region src/cli/auth/token-store.ts
48
+ const TokenEntrySchema = valibot.object({
49
+ accessToken: valibot.string(),
50
+ refreshToken: valibot.string(),
51
+ idToken: valibot.string(),
52
+ expiresAt: valibot.string(),
53
+ scope: valibot.string(),
54
+ subject: valibot.string(),
55
+ profile: valibot.object({
56
+ name: valibot.optional(valibot.string()),
57
+ email: valibot.optional(valibot.string())
58
+ })
59
+ });
60
+ const AuthFileSchema = valibot.object({ issuers: valibot.record(valibot.string(), TokenEntrySchema) });
61
+ var FileTokenStore = class {
62
+ #dir;
63
+ #file;
64
+ constructor(dir = defaultAuthDir()) {
65
+ this.#dir = dir;
66
+ this.#file = node_path.default.join(dir, "auth.json");
67
+ }
68
+ async get(issuer) {
69
+ return (await this.#read()).issuers[issuer];
70
+ }
71
+ async set(issuer, entry) {
72
+ const file = await this.#read();
73
+ file.issuers[issuer] = entry;
74
+ await this.#write(file);
75
+ }
76
+ async remove(issuer) {
77
+ const file = await this.#read();
78
+ if (file.issuers[issuer] === void 0) return;
79
+ file.issuers = Object.fromEntries(Object.entries(file.issuers).filter(([key]) => key !== issuer));
80
+ await this.#write(file);
81
+ }
82
+ async #read() {
83
+ const raw = await (0, node_fs_promises.readFile)(this.#file, "utf-8").catch((error) => {
84
+ if (error.code === "ENOENT") return void 0;
85
+ throw error;
86
+ });
87
+ if (raw === void 0) return { issuers: {} };
88
+ const parsed = valibot.safeParse(AuthFileSchema, safeJsonParse(raw));
89
+ if (!parsed.success) throw new Error(`Malformed auth file: ${this.#file}`);
90
+ return parsed.output;
91
+ }
92
+ async #write(file) {
93
+ await (0, node_fs_promises.mkdir)(this.#dir, {
94
+ recursive: true,
95
+ mode: 448
96
+ });
97
+ const temp = node_path.default.join(this.#dir, `auth.json.${globalThis.crypto.randomUUID()}.tmp`);
98
+ await (0, node_fs_promises.writeFile)(temp, JSON.stringify(file, null, 2), {
99
+ encoding: "utf-8",
100
+ mode: 384
101
+ });
102
+ if (process.platform !== "win32") await (0, node_fs_promises.chmod)(temp, 384);
103
+ await (0, node_fs_promises.rename)(temp, this.#file).catch(async (error) => {
104
+ await (0, node_fs_promises.rm)(temp, { force: true });
105
+ throw error;
106
+ });
107
+ }
108
+ };
109
+ function defaultAuthDir() {
110
+ if (process.platform === "win32") {
111
+ const appData = process.env.APPDATA ?? node_path.default.join(node_os.default.homedir(), "AppData", "Roaming");
112
+ return node_path.default.join(appData, "orizm");
113
+ }
114
+ const xdg = process.env.XDG_CONFIG_HOME;
115
+ const base = xdg != null && xdg !== "" ? xdg : node_path.default.join(node_os.default.homedir(), ".config");
116
+ return node_path.default.join(base, "orizm");
117
+ }
118
+ function safeJsonParse(raw) {
119
+ try {
120
+ return JSON.parse(raw);
121
+ } catch {
122
+ return;
123
+ }
124
+ }
125
+
126
+ //#endregion
127
+ Object.defineProperty(exports, 'FileTokenStore', {
128
+ enumerable: true,
129
+ get: function () {
130
+ return FileTokenStore;
131
+ }
132
+ });
133
+ Object.defineProperty(exports, 'resolveEnv', {
134
+ enumerable: true,
135
+ get: function () {
136
+ return resolveEnv;
137
+ }
138
+ });
139
+ //# sourceMappingURL=token-store--9GYVL7N.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store--9GYVL7N.cjs","names":["v","Result","v","#dir","#file","path","#read","#write","os"],"sources":["../src/cli/env.ts","../src/cli/auth/token-store.ts"],"sourcesContent":["import * as v from \"valibot\";\nimport { Result } from \"@praha/byethrow\";\n\nexport const DEFAULT_BASE_URL = \"https://app.orizm.com\";\n\nexport type ResolvedEnv = {\n baseUrl: string;\n // OAuth2 issuer。ローカルで Hydra が別ポートのときだけ ORIZM_OAUTH_ISSUER_URL で上書きし、\n // 省略時は baseUrl と同じ。トークンストアの namespace キーともこの値で一致させる。\n issuerUrl: string;\n apiKey: string | undefined;\n project: string | undefined;\n};\n\nexport type EnvError = { type: \"invalid_env\"; issues: v.BaseIssue<unknown>[] };\n\nconst trimmedUrl = v.pipe(\n v.string(),\n v.url(),\n // 末尾スラッシュの有無で issuer namespace キーがブレないよう正規化する。\n v.transform((value) => value.replace(/\\/+$/, \"\")),\n);\n\nconst nonEmpty = v.pipe(v.string(), v.nonEmpty());\n\nconst EnvSchema = v.object({\n ORIZM_BASE_URL: v.optional(trimmedUrl, DEFAULT_BASE_URL),\n ORIZM_OAUTH_ISSUER_URL: v.optional(trimmedUrl),\n ORIZM_API_KEY: v.optional(nonEmpty),\n ORIZM_PROJECT: v.optional(nonEmpty),\n});\n\n// 空文字 / 空白のみの環境変数は未設定と同じ扱いにする(v.optional のデフォルト適用を働かせる)。\nfunction normalize(raw: string | undefined): string | undefined {\n if (raw === undefined) return undefined;\n const trimmed = raw.trim();\n return trimmed === \"\" ? undefined : trimmed;\n}\n\nexport function resolveEnv(\n source: NodeJS.ProcessEnv = process.env,\n): Result.Result<ResolvedEnv, EnvError> {\n const parsed = v.safeParse(EnvSchema, {\n ORIZM_BASE_URL: normalize(source.ORIZM_BASE_URL),\n ORIZM_OAUTH_ISSUER_URL: normalize(source.ORIZM_OAUTH_ISSUER_URL),\n ORIZM_API_KEY: normalize(source.ORIZM_API_KEY),\n ORIZM_PROJECT: normalize(source.ORIZM_PROJECT),\n });\n\n if (!parsed.success) {\n return Result.fail({ type: \"invalid_env\", issues: parsed.issues });\n }\n\n const {\n ORIZM_BASE_URL,\n ORIZM_OAUTH_ISSUER_URL,\n ORIZM_API_KEY,\n ORIZM_PROJECT,\n } = parsed.output;\n\n return Result.succeed({\n baseUrl: ORIZM_BASE_URL,\n issuerUrl: ORIZM_OAUTH_ISSUER_URL ?? ORIZM_BASE_URL,\n apiKey: ORIZM_API_KEY,\n project: ORIZM_PROJECT,\n });\n}\n","import {\n mkdir,\n readFile,\n rename,\n rm,\n writeFile,\n chmod,\n} from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport * as v from \"valibot\";\n\nconst TokenEntrySchema = v.object({\n accessToken: v.string(),\n refreshToken: v.string(),\n idToken: v.string(),\n // ISO8601。リフレッシュ要否の判定(残り 60 秒以下)に使う。\n expiresAt: v.string(),\n scope: v.string(),\n subject: v.string(),\n profile: v.object({\n name: v.optional(v.string()),\n email: v.optional(v.string()),\n }),\n});\n\nconst AuthFileSchema = v.object({\n issuers: v.record(v.string(), TokenEntrySchema),\n});\n\nexport type TokenEntry = v.InferOutput<typeof TokenEntrySchema>;\ntype AuthFile = v.InferOutput<typeof AuthFileSchema>;\n\nexport type TokenStore = {\n get(issuer: string): Promise<TokenEntry | undefined>;\n set(issuer: string, entry: TokenEntry): Promise<void>;\n remove(issuer: string): Promise<void>;\n};\n\n// 実装が 1 つでも、後で OS keychain など別の保管先に差し替えられるよう interface に寄せておく。\nexport class FileTokenStore implements TokenStore {\n readonly #dir: string;\n readonly #file: string;\n\n constructor(dir: string = defaultAuthDir()) {\n this.#dir = dir;\n this.#file = path.join(dir, \"auth.json\");\n }\n\n async get(issuer: string): Promise<TokenEntry | undefined> {\n const file = await this.#read();\n return file.issuers[issuer];\n }\n\n async set(issuer: string, entry: TokenEntry): Promise<void> {\n const file = await this.#read();\n file.issuers[issuer] = entry;\n await this.#write(file);\n }\n\n async remove(issuer: string): Promise<void> {\n const file = await this.#read();\n if (file.issuers[issuer] === undefined) return;\n file.issuers = Object.fromEntries(\n Object.entries(file.issuers).filter(([key]) => key !== issuer),\n );\n await this.#write(file);\n }\n\n async #read(): Promise<AuthFile> {\n const raw = await readFile(this.#file, \"utf-8\").catch(\n (error: NodeJS.ErrnoException) => {\n if (error.code === \"ENOENT\") return undefined;\n throw error;\n },\n );\n if (raw === undefined) return { issuers: {} };\n\n const parsed = v.safeParse(AuthFileSchema, safeJsonParse(raw));\n if (!parsed.success) {\n throw new Error(`Malformed auth file: ${this.#file}`);\n }\n return parsed.output;\n }\n\n // Refresh Token rotation の途中でクラッシュしても token を失わないよう、\n // 一時ファイルへ書いてから rename で差し替える。\n async #write(file: AuthFile): Promise<void> {\n await mkdir(this.#dir, { recursive: true, mode: 0o700 });\n const temp = path.join(\n this.#dir,\n `auth.json.${globalThis.crypto.randomUUID()}.tmp`,\n );\n await writeFile(temp, JSON.stringify(file, null, 2), {\n encoding: \"utf-8\",\n mode: 0o600,\n });\n if (process.platform !== \"win32\") {\n // umask の影響を受けないよう作成後に明示設定する。Windows は OS 既定 ACL に委ねる。\n await chmod(temp, 0o600);\n }\n await rename(temp, this.#file).catch(async (error: unknown) => {\n await rm(temp, { force: true });\n throw error;\n });\n }\n}\n\nexport function defaultAuthDir(): string {\n if (process.platform === \"win32\") {\n const appData =\n process.env.APPDATA ?? path.join(os.homedir(), \"AppData\", \"Roaming\");\n return path.join(appData, \"orizm\");\n }\n const xdg = process.env.XDG_CONFIG_HOME;\n const base =\n xdg != null && xdg !== \"\" ? xdg : path.join(os.homedir(), \".config\");\n return path.join(base, \"orizm\");\n}\n\nfunction safeJsonParse(raw: string): unknown {\n try {\n return JSON.parse(raw);\n } catch {\n return undefined;\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ import { Result } from "@praha/byethrow";
2
+ import * as v from "valibot";
3
+ import { chmod, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+
7
+ //#region src/cli/env.ts
8
+ const DEFAULT_BASE_URL = "https://app.orizm.com";
9
+ const trimmedUrl = v.pipe(v.string(), v.url(), v.transform((value) => value.replace(/\/+$/, "")));
10
+ const nonEmpty = v.pipe(v.string(), v.nonEmpty());
11
+ const EnvSchema = v.object({
12
+ ORIZM_BASE_URL: v.optional(trimmedUrl, DEFAULT_BASE_URL),
13
+ ORIZM_OAUTH_ISSUER_URL: v.optional(trimmedUrl),
14
+ ORIZM_API_KEY: v.optional(nonEmpty),
15
+ ORIZM_PROJECT: v.optional(nonEmpty)
16
+ });
17
+ function normalize(raw) {
18
+ if (raw === void 0) return void 0;
19
+ const trimmed = raw.trim();
20
+ return trimmed === "" ? void 0 : trimmed;
21
+ }
22
+ function resolveEnv(source = process.env) {
23
+ const parsed = v.safeParse(EnvSchema, {
24
+ ORIZM_BASE_URL: normalize(source.ORIZM_BASE_URL),
25
+ ORIZM_OAUTH_ISSUER_URL: normalize(source.ORIZM_OAUTH_ISSUER_URL),
26
+ ORIZM_API_KEY: normalize(source.ORIZM_API_KEY),
27
+ ORIZM_PROJECT: normalize(source.ORIZM_PROJECT)
28
+ });
29
+ if (!parsed.success) return Result.fail({
30
+ type: "invalid_env",
31
+ issues: parsed.issues
32
+ });
33
+ const { ORIZM_BASE_URL, ORIZM_OAUTH_ISSUER_URL, ORIZM_API_KEY, ORIZM_PROJECT } = parsed.output;
34
+ return Result.succeed({
35
+ baseUrl: ORIZM_BASE_URL,
36
+ issuerUrl: ORIZM_OAUTH_ISSUER_URL ?? ORIZM_BASE_URL,
37
+ apiKey: ORIZM_API_KEY,
38
+ project: ORIZM_PROJECT
39
+ });
40
+ }
41
+
42
+ //#endregion
43
+ //#region src/cli/auth/token-store.ts
44
+ const TokenEntrySchema = v.object({
45
+ accessToken: v.string(),
46
+ refreshToken: v.string(),
47
+ idToken: v.string(),
48
+ expiresAt: v.string(),
49
+ scope: v.string(),
50
+ subject: v.string(),
51
+ profile: v.object({
52
+ name: v.optional(v.string()),
53
+ email: v.optional(v.string())
54
+ })
55
+ });
56
+ const AuthFileSchema = v.object({ issuers: v.record(v.string(), TokenEntrySchema) });
57
+ var FileTokenStore = class {
58
+ #dir;
59
+ #file;
60
+ constructor(dir = defaultAuthDir()) {
61
+ this.#dir = dir;
62
+ this.#file = path.join(dir, "auth.json");
63
+ }
64
+ async get(issuer) {
65
+ return (await this.#read()).issuers[issuer];
66
+ }
67
+ async set(issuer, entry) {
68
+ const file = await this.#read();
69
+ file.issuers[issuer] = entry;
70
+ await this.#write(file);
71
+ }
72
+ async remove(issuer) {
73
+ const file = await this.#read();
74
+ if (file.issuers[issuer] === void 0) return;
75
+ file.issuers = Object.fromEntries(Object.entries(file.issuers).filter(([key]) => key !== issuer));
76
+ await this.#write(file);
77
+ }
78
+ async #read() {
79
+ const raw = await readFile(this.#file, "utf-8").catch((error) => {
80
+ if (error.code === "ENOENT") return void 0;
81
+ throw error;
82
+ });
83
+ if (raw === void 0) return { issuers: {} };
84
+ const parsed = v.safeParse(AuthFileSchema, safeJsonParse(raw));
85
+ if (!parsed.success) throw new Error(`Malformed auth file: ${this.#file}`);
86
+ return parsed.output;
87
+ }
88
+ async #write(file) {
89
+ await mkdir(this.#dir, {
90
+ recursive: true,
91
+ mode: 448
92
+ });
93
+ const temp = path.join(this.#dir, `auth.json.${globalThis.crypto.randomUUID()}.tmp`);
94
+ await writeFile(temp, JSON.stringify(file, null, 2), {
95
+ encoding: "utf-8",
96
+ mode: 384
97
+ });
98
+ if (process.platform !== "win32") await chmod(temp, 384);
99
+ await rename(temp, this.#file).catch(async (error) => {
100
+ await rm(temp, { force: true });
101
+ throw error;
102
+ });
103
+ }
104
+ };
105
+ function defaultAuthDir() {
106
+ if (process.platform === "win32") {
107
+ const appData = process.env.APPDATA ?? path.join(os.homedir(), "AppData", "Roaming");
108
+ return path.join(appData, "orizm");
109
+ }
110
+ const xdg = process.env.XDG_CONFIG_HOME;
111
+ const base = xdg != null && xdg !== "" ? xdg : path.join(os.homedir(), ".config");
112
+ return path.join(base, "orizm");
113
+ }
114
+ function safeJsonParse(raw) {
115
+ try {
116
+ return JSON.parse(raw);
117
+ } catch {
118
+ return;
119
+ }
120
+ }
121
+
122
+ //#endregion
123
+ export { resolveEnv as n, FileTokenStore as t };
124
+ //# sourceMappingURL=token-store-reCGF86F.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store-reCGF86F.mjs","names":["#dir","#file","#read","#write"],"sources":["../src/cli/env.ts","../src/cli/auth/token-store.ts"],"sourcesContent":["import * as v from \"valibot\";\nimport { Result } from \"@praha/byethrow\";\n\nexport const DEFAULT_BASE_URL = \"https://app.orizm.com\";\n\nexport type ResolvedEnv = {\n baseUrl: string;\n // OAuth2 issuer。ローカルで Hydra が別ポートのときだけ ORIZM_OAUTH_ISSUER_URL で上書きし、\n // 省略時は baseUrl と同じ。トークンストアの namespace キーともこの値で一致させる。\n issuerUrl: string;\n apiKey: string | undefined;\n project: string | undefined;\n};\n\nexport type EnvError = { type: \"invalid_env\"; issues: v.BaseIssue<unknown>[] };\n\nconst trimmedUrl = v.pipe(\n v.string(),\n v.url(),\n // 末尾スラッシュの有無で issuer namespace キーがブレないよう正規化する。\n v.transform((value) => value.replace(/\\/+$/, \"\")),\n);\n\nconst nonEmpty = v.pipe(v.string(), v.nonEmpty());\n\nconst EnvSchema = v.object({\n ORIZM_BASE_URL: v.optional(trimmedUrl, DEFAULT_BASE_URL),\n ORIZM_OAUTH_ISSUER_URL: v.optional(trimmedUrl),\n ORIZM_API_KEY: v.optional(nonEmpty),\n ORIZM_PROJECT: v.optional(nonEmpty),\n});\n\n// 空文字 / 空白のみの環境変数は未設定と同じ扱いにする(v.optional のデフォルト適用を働かせる)。\nfunction normalize(raw: string | undefined): string | undefined {\n if (raw === undefined) return undefined;\n const trimmed = raw.trim();\n return trimmed === \"\" ? undefined : trimmed;\n}\n\nexport function resolveEnv(\n source: NodeJS.ProcessEnv = process.env,\n): Result.Result<ResolvedEnv, EnvError> {\n const parsed = v.safeParse(EnvSchema, {\n ORIZM_BASE_URL: normalize(source.ORIZM_BASE_URL),\n ORIZM_OAUTH_ISSUER_URL: normalize(source.ORIZM_OAUTH_ISSUER_URL),\n ORIZM_API_KEY: normalize(source.ORIZM_API_KEY),\n ORIZM_PROJECT: normalize(source.ORIZM_PROJECT),\n });\n\n if (!parsed.success) {\n return Result.fail({ type: \"invalid_env\", issues: parsed.issues });\n }\n\n const {\n ORIZM_BASE_URL,\n ORIZM_OAUTH_ISSUER_URL,\n ORIZM_API_KEY,\n ORIZM_PROJECT,\n } = parsed.output;\n\n return Result.succeed({\n baseUrl: ORIZM_BASE_URL,\n issuerUrl: ORIZM_OAUTH_ISSUER_URL ?? ORIZM_BASE_URL,\n apiKey: ORIZM_API_KEY,\n project: ORIZM_PROJECT,\n });\n}\n","import {\n mkdir,\n readFile,\n rename,\n rm,\n writeFile,\n chmod,\n} from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport * as v from \"valibot\";\n\nconst TokenEntrySchema = v.object({\n accessToken: v.string(),\n refreshToken: v.string(),\n idToken: v.string(),\n // ISO8601。リフレッシュ要否の判定(残り 60 秒以下)に使う。\n expiresAt: v.string(),\n scope: v.string(),\n subject: v.string(),\n profile: v.object({\n name: v.optional(v.string()),\n email: v.optional(v.string()),\n }),\n});\n\nconst AuthFileSchema = v.object({\n issuers: v.record(v.string(), TokenEntrySchema),\n});\n\nexport type TokenEntry = v.InferOutput<typeof TokenEntrySchema>;\ntype AuthFile = v.InferOutput<typeof AuthFileSchema>;\n\nexport type TokenStore = {\n get(issuer: string): Promise<TokenEntry | undefined>;\n set(issuer: string, entry: TokenEntry): Promise<void>;\n remove(issuer: string): Promise<void>;\n};\n\n// 実装が 1 つでも、後で OS keychain など別の保管先に差し替えられるよう interface に寄せておく。\nexport class FileTokenStore implements TokenStore {\n readonly #dir: string;\n readonly #file: string;\n\n constructor(dir: string = defaultAuthDir()) {\n this.#dir = dir;\n this.#file = path.join(dir, \"auth.json\");\n }\n\n async get(issuer: string): Promise<TokenEntry | undefined> {\n const file = await this.#read();\n return file.issuers[issuer];\n }\n\n async set(issuer: string, entry: TokenEntry): Promise<void> {\n const file = await this.#read();\n file.issuers[issuer] = entry;\n await this.#write(file);\n }\n\n async remove(issuer: string): Promise<void> {\n const file = await this.#read();\n if (file.issuers[issuer] === undefined) return;\n file.issuers = Object.fromEntries(\n Object.entries(file.issuers).filter(([key]) => key !== issuer),\n );\n await this.#write(file);\n }\n\n async #read(): Promise<AuthFile> {\n const raw = await readFile(this.#file, \"utf-8\").catch(\n (error: NodeJS.ErrnoException) => {\n if (error.code === \"ENOENT\") return undefined;\n throw error;\n },\n );\n if (raw === undefined) return { issuers: {} };\n\n const parsed = v.safeParse(AuthFileSchema, safeJsonParse(raw));\n if (!parsed.success) {\n throw new Error(`Malformed auth file: ${this.#file}`);\n }\n return parsed.output;\n }\n\n // Refresh Token rotation の途中でクラッシュしても token を失わないよう、\n // 一時ファイルへ書いてから rename で差し替える。\n async #write(file: AuthFile): Promise<void> {\n await mkdir(this.#dir, { recursive: true, mode: 0o700 });\n const temp = path.join(\n this.#dir,\n `auth.json.${globalThis.crypto.randomUUID()}.tmp`,\n );\n await writeFile(temp, JSON.stringify(file, null, 2), {\n encoding: \"utf-8\",\n mode: 0o600,\n });\n if (process.platform !== \"win32\") {\n // umask の影響を受けないよう作成後に明示設定する。Windows は OS 既定 ACL に委ねる。\n await chmod(temp, 0o600);\n }\n await rename(temp, this.#file).catch(async (error: unknown) => {\n await rm(temp, { force: true });\n throw error;\n });\n }\n}\n\nexport function defaultAuthDir(): string {\n if (process.platform === \"win32\") {\n const appData =\n process.env.APPDATA ?? path.join(os.homedir(), \"AppData\", \"Roaming\");\n return path.join(appData, \"orizm\");\n }\n const xdg = process.env.XDG_CONFIG_HOME;\n const base =\n xdg != null && xdg !== \"\" ? xdg : path.join(os.homedir(), \".config\");\n return path.join(base, \"orizm\");\n}\n\nfunction safeJsonParse(raw: string): unknown {\n try {\n return JSON.parse(raw);\n } catch {\n return undefined;\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ import { t as defineCommand } from "./cli/main.mjs";
2
+ import { r as contextArgs } from "./shared-CZZimGxc.mjs";
3
+ import { a as apiErrorFailure, n as runWithContext, u as toResult } from "./run-with-context-CVhmzAFZ.mjs";
4
+ import { t as renderDetail } from "./detail-DN5jCQ4N.mjs";
5
+ import { f as parseRepeatableFlag, t as collectRepeatableFlag } from "./parse-CA5fBB3x.mjs";
6
+ import { r as resolveArrayUpdate } from "./array-update-CMFUoQEe.mjs";
7
+ import { i as warnMissingGroupRemovals, n as formatGroupRoles, r as parseGroupRoles, t as applyGroupRoleEdits } from "./group-roles-BEEzLxPX.mjs";
8
+ import { Result } from "@praha/byethrow";
9
+
10
+ //#region src/cli/commands/project-user/update.ts
11
+ async function projectUserUpdateHandler(ctx, options) {
12
+ if (options.name === void 0 && options.groupRoles === void 0) return Result.fail({ message: "Nothing to update. Pass --name or a --group-role option." });
13
+ let groupRoles;
14
+ if (options.groupRoles?.mode === "edit") {
15
+ const current = toResult(await ctx.client.GET("/projects/{projectName}/users/{userId}", { params: { path: {
16
+ projectName: ctx.projectName,
17
+ userId: options.userId
18
+ } } }));
19
+ if (Result.isFailure(current)) return apiErrorFailure(current.error);
20
+ warnMissingGroupRemovals(current.value.groupRoles, options.groupRoles.remove);
21
+ groupRoles = applyGroupRoleEdits(current.value.groupRoles, options.groupRoles);
22
+ } else if (options.groupRoles !== void 0) groupRoles = options.groupRoles.items;
23
+ const body = {
24
+ ...options.name !== void 0 ? { name: options.name } : {},
25
+ ...groupRoles !== void 0 ? { groupRoles } : {}
26
+ };
27
+ const updated = toResult(await ctx.client.PUT("/projects/{projectName}/users/{userId}", {
28
+ params: { path: {
29
+ projectName: ctx.projectName,
30
+ userId: options.userId
31
+ } },
32
+ body
33
+ }));
34
+ if (Result.isFailure(updated)) return apiErrorFailure(updated.error);
35
+ const value = updated.value;
36
+ return Result.succeed({
37
+ json: value,
38
+ text: () => renderDetail([
39
+ ["Updated", value.id],
40
+ ["Name", value.name],
41
+ ["Email", value.email],
42
+ ["Group roles", formatGroupRoles(value.groupRoles)]
43
+ ])
44
+ });
45
+ }
46
+ const updateArgs = {
47
+ ...contextArgs,
48
+ "user-id": {
49
+ type: "positional",
50
+ required: true,
51
+ description: "Project user ID"
52
+ },
53
+ name: {
54
+ type: "string",
55
+ description: "New display name"
56
+ },
57
+ "group-role": {
58
+ type: "string",
59
+ description: "Replace all RBAC assignments with <group>:<role>; repeatable"
60
+ },
61
+ "add-group-role": {
62
+ type: "string",
63
+ description: "Add an RBAC assignment as <group>:<role>; repeatable"
64
+ },
65
+ "remove-group-role": {
66
+ type: "string",
67
+ description: "Remove an RBAC assignment by group name; repeatable"
68
+ },
69
+ "clear-group-roles": {
70
+ type: "boolean",
71
+ description: "Remove all RBAC assignments",
72
+ default: false
73
+ }
74
+ };
75
+ var update_default = defineCommand({
76
+ meta: {
77
+ name: "update",
78
+ description: "Update a project user's name or group roles"
79
+ },
80
+ args: updateArgs,
81
+ run: async ({ args, rawArgs }) => {
82
+ const replace = parseGroupRoles("group-role", collectRepeatableFlag(rawArgs, "group-role"));
83
+ if (Result.isFailure(replace)) return replace;
84
+ const added = parseGroupRoles("add-group-role", collectRepeatableFlag(rawArgs, "add-group-role"));
85
+ if (Result.isFailure(added)) return added;
86
+ const removeValues = collectRepeatableFlag(rawArgs, "remove-group-role");
87
+ const removed = removeValues === void 0 ? Result.succeed(void 0) : parseRepeatableFlag("remove-group-role", removeValues);
88
+ if (Result.isFailure(removed)) return removed;
89
+ const groupRoles = resolveArrayUpdate({
90
+ replaceFlag: "group-role",
91
+ clearFlag: "clear-group-roles",
92
+ editFlags: "--add-group-role / --remove-group-role",
93
+ replace: replace.value,
94
+ add: added.value,
95
+ remove: removed.value,
96
+ clear: args["clear-group-roles"] === true
97
+ });
98
+ if (Result.isFailure(groupRoles)) return groupRoles;
99
+ return runWithContext(args, (ctx) => projectUserUpdateHandler(ctx, {
100
+ userId: args["user-id"],
101
+ name: typeof args.name === "string" ? args.name : void 0,
102
+ groupRoles: groupRoles.value
103
+ }));
104
+ }
105
+ });
106
+
107
+ //#endregion
108
+ export { update_default as default };
109
+ //# sourceMappingURL=update-8e3u4jKa.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-8e3u4jKa.mjs","names":[],"sources":["../src/cli/commands/project-user/update.ts"],"sourcesContent":["import type { ArgsDef } from \"citty\";\nimport { Result } from \"@praha/byethrow\";\nimport {\n defineCommand,\n type CommandFailure,\n type CommandOutput,\n} from \"../define-command.js\";\nimport { contextArgs } from \"../shared.js\";\nimport { runWithContext, type CommandContext } from \"../run-with-context.js\";\nimport { apiErrorFailure } from \"../api-errors.js\";\nimport { toResult } from \"../../api/errors.js\";\nimport { renderDetail } from \"../../ui/detail.js\";\nimport { collectRepeatableFlag, parseRepeatableFlag } from \"../parse.js\";\nimport { resolveArrayUpdate, type ArrayUpdate } from \"../array-update.js\";\nimport {\n applyGroupRoleEdits,\n formatGroupRoles,\n warnMissingGroupRemovals,\n parseGroupRoles,\n type GroupRole,\n} from \"../group-roles.js\";\n\nexport async function projectUserUpdateHandler(\n ctx: CommandContext,\n options: {\n userId: string;\n name?: string;\n groupRoles: ArrayUpdate<GroupRole, string>;\n },\n): Promise<Result.Result<CommandOutput | undefined, CommandFailure>> {\n if (options.name === undefined && options.groupRoles === undefined) {\n return Result.fail({\n message: \"Nothing to update. Pass --name or a --group-role option.\",\n });\n }\n\n // API は groupRoles の全置換しか受けないため、要素単位の編集は現状を取得してから組み立てる\n let groupRoles: GroupRole[] | undefined;\n if (options.groupRoles?.mode === \"edit\") {\n const current = toResult(\n await ctx.client.GET(\"/projects/{projectName}/users/{userId}\", {\n params: {\n path: { projectName: ctx.projectName, userId: options.userId },\n },\n }),\n );\n if (Result.isFailure(current)) return apiErrorFailure(current.error);\n warnMissingGroupRemovals(\n current.value.groupRoles,\n options.groupRoles.remove,\n );\n groupRoles = applyGroupRoleEdits(\n current.value.groupRoles,\n options.groupRoles,\n );\n } else if (options.groupRoles !== undefined) {\n groupRoles = options.groupRoles.items;\n }\n\n const body = {\n ...(options.name !== undefined ? { name: options.name } : {}),\n ...(groupRoles !== undefined ? { groupRoles } : {}),\n };\n\n const updated = toResult(\n await ctx.client.PUT(\"/projects/{projectName}/users/{userId}\", {\n params: {\n path: { projectName: ctx.projectName, userId: options.userId },\n },\n body,\n }),\n );\n if (Result.isFailure(updated)) return apiErrorFailure(updated.error);\n\n const value = updated.value;\n return Result.succeed({\n json: value,\n text: () =>\n renderDetail([\n [\"Updated\", value.id],\n [\"Name\", value.name],\n [\"Email\", value.email],\n [\"Group roles\", formatGroupRoles(value.groupRoles)],\n ]),\n });\n}\n\nconst updateArgs = {\n ...contextArgs,\n \"user-id\": {\n type: \"positional\",\n required: true,\n description: \"Project user ID\",\n },\n name: {\n type: \"string\",\n description: \"New display name\",\n },\n \"group-role\": {\n type: \"string\",\n description: \"Replace all RBAC assignments with <group>:<role>; repeatable\",\n },\n \"add-group-role\": {\n type: \"string\",\n description: \"Add an RBAC assignment as <group>:<role>; repeatable\",\n },\n \"remove-group-role\": {\n type: \"string\",\n description: \"Remove an RBAC assignment by group name; repeatable\",\n },\n \"clear-group-roles\": {\n type: \"boolean\",\n description: \"Remove all RBAC assignments\",\n default: false,\n },\n} satisfies ArgsDef;\n\nexport default defineCommand({\n meta: {\n name: \"update\",\n description: \"Update a project user's name or group roles\",\n },\n args: updateArgs,\n run: async ({ args, rawArgs }) => {\n const replace = parseGroupRoles(\n \"group-role\",\n collectRepeatableFlag(rawArgs, \"group-role\"),\n );\n if (Result.isFailure(replace)) return replace;\n const added = parseGroupRoles(\n \"add-group-role\",\n collectRepeatableFlag(rawArgs, \"add-group-role\"),\n );\n if (Result.isFailure(added)) return added;\n const removeValues = collectRepeatableFlag(rawArgs, \"remove-group-role\");\n const removed =\n removeValues === undefined\n ? Result.succeed(undefined)\n : parseRepeatableFlag(\"remove-group-role\", removeValues);\n if (Result.isFailure(removed)) return removed;\n const groupRoles = resolveArrayUpdate({\n replaceFlag: \"group-role\",\n clearFlag: \"clear-group-roles\",\n editFlags: \"--add-group-role / --remove-group-role\",\n replace: replace.value,\n add: added.value,\n remove: removed.value,\n clear: args[\"clear-group-roles\"] === true,\n });\n if (Result.isFailure(groupRoles)) return groupRoles;\n\n return runWithContext(args, (ctx) =>\n projectUserUpdateHandler(ctx, {\n userId: args[\"user-id\"],\n name: typeof args.name === \"string\" ? args.name : undefined,\n groupRoles: groupRoles.value,\n }),\n );\n },\n});\n"],"mappings":";;;;;;;;;;AAsBA,eAAsB,yBACpB,KACA,SAKmE;CACnE,IAAI,QAAQ,SAAS,UAAa,QAAQ,eAAe,QACvD,OAAO,OAAO,KAAK,EACjB,SAAS,2DACX,CAAC;CAIH,IAAI;CACJ,IAAI,QAAQ,YAAY,SAAS,QAAQ;EACvC,MAAM,UAAU,SACd,MAAM,IAAI,OAAO,IAAI,0CAA0C,EAC7D,QAAQ,EACN,MAAM;GAAE,aAAa,IAAI;GAAa,QAAQ,QAAQ;EAAO,EAC/D,EACF,CAAC,CACH;EACA,IAAI,OAAO,UAAU,OAAO,GAAG,OAAO,gBAAgB,QAAQ,KAAK;EACnE,yBACE,QAAQ,MAAM,YACd,QAAQ,WAAW,MACrB;EACA,aAAa,oBACX,QAAQ,MAAM,YACd,QAAQ,UACV;CACF,OAAO,IAAI,QAAQ,eAAe,QAChC,aAAa,QAAQ,WAAW;CAGlC,MAAM,OAAO;EACX,GAAI,QAAQ,SAAS,SAAY,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;EAC3D,GAAI,eAAe,SAAY,EAAE,WAAW,IAAI,CAAC;CACnD;CAEA,MAAM,UAAU,SACd,MAAM,IAAI,OAAO,IAAI,0CAA0C;EAC7D,QAAQ,EACN,MAAM;GAAE,aAAa,IAAI;GAAa,QAAQ,QAAQ;EAAO,EAC/D;EACA;CACF,CAAC,CACH;CACA,IAAI,OAAO,UAAU,OAAO,GAAG,OAAO,gBAAgB,QAAQ,KAAK;CAEnE,MAAM,QAAQ,QAAQ;CACtB,OAAO,OAAO,QAAQ;EACpB,MAAM;EACN,YACE,aAAa;GACX,CAAC,WAAW,MAAM,EAAE;GACpB,CAAC,QAAQ,MAAM,IAAI;GACnB,CAAC,SAAS,MAAM,KAAK;GACrB,CAAC,eAAe,iBAAiB,MAAM,UAAU,CAAC;EACpD,CAAC;CACL,CAAC;AACH;AAEA,MAAM,aAAa;CACjB,GAAG;CACH,WAAW;EACT,MAAM;EACN,UAAU;EACV,aAAa;CACf;CACA,MAAM;EACJ,MAAM;EACN,aAAa;CACf;CACA,cAAc;EACZ,MAAM;EACN,aAAa;CACf;CACA,kBAAkB;EAChB,MAAM;EACN,aAAa;CACf;CACA,qBAAqB;EACnB,MAAM;EACN,aAAa;CACf;CACA,qBAAqB;EACnB,MAAM;EACN,aAAa;EACb,SAAS;CACX;AACF;AAEA,qBAAe,cAAc;CAC3B,MAAM;EACJ,MAAM;EACN,aAAa;CACf;CACA,MAAM;CACN,KAAK,OAAO,EAAE,MAAM,cAAc;EAChC,MAAM,UAAU,gBACd,cACA,sBAAsB,SAAS,YAAY,CAC7C;EACA,IAAI,OAAO,UAAU,OAAO,GAAG,OAAO;EACtC,MAAM,QAAQ,gBACZ,kBACA,sBAAsB,SAAS,gBAAgB,CACjD;EACA,IAAI,OAAO,UAAU,KAAK,GAAG,OAAO;EACpC,MAAM,eAAe,sBAAsB,SAAS,mBAAmB;EACvE,MAAM,UACJ,iBAAiB,SACb,OAAO,QAAQ,MAAS,IACxB,oBAAoB,qBAAqB,YAAY;EAC3D,IAAI,OAAO,UAAU,OAAO,GAAG,OAAO;EACtC,MAAM,aAAa,mBAAmB;GACpC,aAAa;GACb,WAAW;GACX,WAAW;GACX,SAAS,QAAQ;GACjB,KAAK,MAAM;GACX,QAAQ,QAAQ;GAChB,OAAO,KAAK,yBAAyB;EACvC,CAAC;EACD,IAAI,OAAO,UAAU,UAAU,GAAG,OAAO;EAEzC,OAAO,eAAe,OAAO,QAC3B,yBAAyB,KAAK;GAC5B,QAAQ,KAAK;GACb,MAAM,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;GAClD,YAAY,WAAW;EACzB,CAAC,CACH;CACF;AACF,CAAC"}
@@ -0,0 +1,73 @@
1
+ const require_cli_main = require('./cli/main.cjs');
2
+ const require_shared = require('./shared-DHRPzzKl.cjs');
3
+ const require_run_with_context = require('./run-with-context-DJNnEigg.cjs');
4
+ const require_detail = require('./detail-8CXNIhKw.cjs');
5
+ const require_parse = require('./parse-BeO2IwfI.cjs');
6
+ const require_project_name = require('./project-name-CEoM-OL4.cjs');
7
+ let _praha_byethrow = require("@praha/byethrow");
8
+
9
+ //#region src/cli/commands/project/update.ts
10
+ async function projectUpdateHandler(ctx, options) {
11
+ const body = {
12
+ ...options.displayName !== void 0 ? { displayName: options.displayName } : {},
13
+ ...options.cmsUrl !== void 0 ? { cmsUrl: options.cmsUrl } : {},
14
+ ...options.deletionProtected !== void 0 ? { isDeletionProtected: options.deletionProtected } : {}
15
+ };
16
+ if (Object.keys(body).length === 0) return _praha_byethrow.Result.fail({ message: "Nothing to update. Pass --display-name, --cms-url, or --deletion-protected." });
17
+ const updated = require_run_with_context.toResult(await ctx.client.PUT("/projects/{projectName}", {
18
+ params: { path: { projectName: ctx.projectName } },
19
+ body
20
+ }));
21
+ if (_praha_byethrow.Result.isFailure(updated)) return require_run_with_context.apiErrorFailure(updated.error);
22
+ const value = updated.value;
23
+ return _praha_byethrow.Result.succeed({
24
+ json: value,
25
+ text: () => require_detail.renderDetail([
26
+ ["Updated", value.name],
27
+ ["Display name", value.displayName],
28
+ ["CMS URL", value.cmsUrl ?? "-"],
29
+ ["Deletion protected", String(value.isDeletionProtected)]
30
+ ])
31
+ });
32
+ }
33
+ const updateArgs = {
34
+ ...require_shared.contextArgs,
35
+ name: {
36
+ type: "positional",
37
+ required: false,
38
+ description: "Project name (defaults to the current project context)"
39
+ },
40
+ "display-name": {
41
+ type: "string",
42
+ description: "New display name"
43
+ },
44
+ "cms-url": {
45
+ type: "string",
46
+ description: "New CMS URL"
47
+ },
48
+ "deletion-protected": {
49
+ type: "string",
50
+ description: "Set deletion protection (true/false)",
51
+ valueHint: "true|false"
52
+ }
53
+ };
54
+ var update_default = require_cli_main.defineCommand({
55
+ meta: {
56
+ name: "update",
57
+ description: "Update a project's settings"
58
+ },
59
+ args: updateArgs,
60
+ run: async ({ args }) => {
61
+ const deletionProtected = require_parse.parseBooleanFlag("deletion-protected", args["deletion-protected"]);
62
+ if (_praha_byethrow.Result.isFailure(deletionProtected)) return deletionProtected;
63
+ return require_run_with_context.runWithContext(require_project_name.projectNameOverride(args), (ctx) => projectUpdateHandler(ctx, {
64
+ displayName: typeof args["display-name"] === "string" ? args["display-name"] : void 0,
65
+ cmsUrl: typeof args["cms-url"] === "string" ? args["cms-url"] : void 0,
66
+ deletionProtected: deletionProtected.value
67
+ }));
68
+ }
69
+ });
70
+
71
+ //#endregion
72
+ exports.default = update_default;
73
+ //# sourceMappingURL=update-CDLviRuu.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-CDLviRuu.cjs","names":["Result","toResult","apiErrorFailure","renderDetail","contextArgs","defineCommand","parseBooleanFlag","runWithContext","projectNameOverride"],"sources":["../src/cli/commands/project/update.ts"],"sourcesContent":["import type { ArgsDef } from \"citty\";\nimport { Result } from \"@praha/byethrow\";\nimport type { components } from \"@orizm/internal-shared/api-clients/dev-v2\";\nimport {\n defineCommand,\n type CommandFailure,\n type CommandOutput,\n} from \"../define-command.js\";\nimport { contextArgs } from \"../shared.js\";\nimport { runWithContext, type CommandContext } from \"../run-with-context.js\";\nimport { apiErrorFailure } from \"../api-errors.js\";\nimport { toResult } from \"../../api/errors.js\";\nimport { renderDetail } from \"../../ui/detail.js\";\nimport { parseBooleanFlag } from \"../parse.js\";\nimport { projectNameOverride } from \"./project-name.js\";\n\nexport async function projectUpdateHandler(\n ctx: CommandContext,\n options: {\n displayName?: string;\n cmsUrl?: string;\n deletionProtected?: boolean;\n },\n): Promise<Result.Result<CommandOutput | undefined, CommandFailure>> {\n const body: components[\"schemas\"][\"UpdateProjectRequest\"] = {\n ...(options.displayName !== undefined\n ? { displayName: options.displayName }\n : {}),\n ...(options.cmsUrl !== undefined ? { cmsUrl: options.cmsUrl } : {}),\n ...(options.deletionProtected !== undefined\n ? { isDeletionProtected: options.deletionProtected }\n : {}),\n };\n\n if (Object.keys(body).length === 0) {\n return Result.fail({\n message:\n \"Nothing to update. Pass --display-name, --cms-url, or --deletion-protected.\",\n });\n }\n\n const updated = toResult(\n await ctx.client.PUT(\"/projects/{projectName}\", {\n params: { path: { projectName: ctx.projectName } },\n body,\n }),\n );\n if (Result.isFailure(updated)) return apiErrorFailure(updated.error);\n\n const value = updated.value;\n return Result.succeed({\n json: value,\n text: () =>\n renderDetail([\n [\"Updated\", value.name],\n [\"Display name\", value.displayName],\n [\"CMS URL\", value.cmsUrl ?? \"-\"],\n [\"Deletion protected\", String(value.isDeletionProtected)],\n ]),\n });\n}\n\nconst updateArgs = {\n ...contextArgs,\n name: {\n type: \"positional\",\n required: false,\n description: \"Project name (defaults to the current project context)\",\n },\n \"display-name\": {\n type: \"string\",\n description: \"New display name\",\n },\n \"cms-url\": {\n type: \"string\",\n description: \"New CMS URL\",\n },\n // 「未指定 = 変更しない」「true / false = その値へ変更」の 3 状態を扱うため、\n // bare 指定が true になる boolean フラグではなく、値を明示させる文字列で受ける。\n \"deletion-protected\": {\n type: \"string\",\n description: \"Set deletion protection (true/false)\",\n valueHint: \"true|false\",\n },\n} satisfies ArgsDef;\n\nexport default defineCommand({\n meta: {\n name: \"update\",\n description: \"Update a project's settings\",\n },\n args: updateArgs,\n run: async ({ args }) => {\n const deletionProtected = parseBooleanFlag(\n \"deletion-protected\",\n args[\"deletion-protected\"],\n );\n if (Result.isFailure(deletionProtected)) return deletionProtected;\n\n return runWithContext(projectNameOverride(args), (ctx) =>\n projectUpdateHandler(ctx, {\n displayName:\n typeof args[\"display-name\"] === \"string\"\n ? args[\"display-name\"]\n : undefined,\n cmsUrl:\n typeof args[\"cms-url\"] === \"string\" ? args[\"cms-url\"] : undefined,\n deletionProtected: deletionProtected.value,\n }),\n );\n },\n});\n"],"mappings":";;;;;;;;;AAgBA,eAAsB,qBACpB,KACA,SAKmE;CACnE,MAAM,OAAsD;EAC1D,GAAI,QAAQ,gBAAgB,SACxB,EAAE,aAAa,QAAQ,YAAY,IACnC,CAAC;EACL,GAAI,QAAQ,WAAW,SAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;EACjE,GAAI,QAAQ,sBAAsB,SAC9B,EAAE,qBAAqB,QAAQ,kBAAkB,IACjD,CAAC;CACP;CAEA,IAAI,OAAO,KAAK,IAAI,CAAC,CAAC,WAAW,GAC/B,OAAOA,uBAAO,KAAK,EACjB,SACE,8EACJ,CAAC;CAGH,MAAM,UAAUC,kCACd,MAAM,IAAI,OAAO,IAAI,2BAA2B;EAC9C,QAAQ,EAAE,MAAM,EAAE,aAAa,IAAI,YAAY,EAAE;EACjD;CACF,CAAC,CACH;CACA,IAAID,uBAAO,UAAU,OAAO,GAAG,OAAOE,yCAAgB,QAAQ,KAAK;CAEnE,MAAM,QAAQ,QAAQ;CACtB,OAAOF,uBAAO,QAAQ;EACpB,MAAM;EACN,YACEG,4BAAa;GACX,CAAC,WAAW,MAAM,IAAI;GACtB,CAAC,gBAAgB,MAAM,WAAW;GAClC,CAAC,WAAW,MAAM,UAAU,GAAG;GAC/B,CAAC,sBAAsB,OAAO,MAAM,mBAAmB,CAAC;EAC1D,CAAC;CACL,CAAC;AACH;AAEA,MAAM,aAAa;CACjB,GAAGC;CACH,MAAM;EACJ,MAAM;EACN,UAAU;EACV,aAAa;CACf;CACA,gBAAgB;EACd,MAAM;EACN,aAAa;CACf;CACA,WAAW;EACT,MAAM;EACN,aAAa;CACf;CAGA,sBAAsB;EACpB,MAAM;EACN,aAAa;EACb,WAAW;CACb;AACF;AAEA,qBAAeC,+BAAc;CAC3B,MAAM;EACJ,MAAM;EACN,aAAa;CACf;CACA,MAAM;CACN,KAAK,OAAO,EAAE,WAAW;EACvB,MAAM,oBAAoBC,+BACxB,sBACA,KAAK,qBACP;EACA,IAAIN,uBAAO,UAAU,iBAAiB,GAAG,OAAO;EAEhD,OAAOO,wCAAeC,yCAAoB,IAAI,IAAI,QAChD,qBAAqB,KAAK;GACxB,aACE,OAAO,KAAK,oBAAoB,WAC5B,KAAK,kBACL;GACN,QACE,OAAO,KAAK,eAAe,WAAW,KAAK,aAAa;GAC1D,mBAAmB,kBAAkB;EACvC,CAAC,CACH;CACF;AACF,CAAC"}