@orizm/cli 3.1.0 → 3.3.0-beta.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 (379) hide show
  1. package/README.md +27 -1
  2. package/dist/agent-Kf8iuW2I.mjs +14 -0
  3. package/dist/agent-Kf8iuW2I.mjs.map +1 -0
  4. package/dist/agent-UZZtdOZS.cjs +14 -0
  5. package/dist/agent-UZZtdOZS.cjs.map +1 -0
  6. package/dist/auth-BnXPHgBU.cjs +18 -0
  7. package/dist/{auth-CNbONZuf.cjs.map → auth-BnXPHgBU.cjs.map} +1 -1
  8. package/dist/{auth-BGW072BP.mjs → auth-DHVtM0sF.mjs} +4 -4
  9. package/dist/{auth-BGW072BP.mjs.map → auth-DHVtM0sF.mjs.map} +1 -1
  10. package/dist/{bucket-mg5QQORh.cjs → bucket-CFaYmimY.cjs} +3 -3
  11. package/dist/{bucket-mg5QQORh.cjs.map → bucket-CFaYmimY.cjs.map} +1 -1
  12. package/dist/{bucket-DqW-WEYb.mjs → bucket-D-lu1xgZ.mjs} +3 -3
  13. package/dist/{bucket-DqW-WEYb.mjs.map → bucket-D-lu1xgZ.mjs.map} +1 -1
  14. package/dist/cli/main.cjs +14 -12
  15. package/dist/cli/main.cjs.map +1 -1
  16. package/dist/cli/main.mjs +14 -13
  17. package/dist/cli/main.mjs.map +1 -1
  18. package/dist/{cms-BJnovGYT.mjs → cms-8XZhxwsM.mjs} +8 -5
  19. package/dist/cms-8XZhxwsM.mjs.map +1 -0
  20. package/dist/{cms-Cnx-lDGu.cjs → cms-C4zEtppZ.cjs} +8 -5
  21. package/dist/cms-C4zEtppZ.cjs.map +1 -0
  22. package/dist/{codegen-BF5b-u46.cjs → codegen-Cypg4O3L.cjs} +3 -3
  23. package/dist/{codegen-BF5b-u46.cjs.map → codegen-Cypg4O3L.cjs.map} +1 -1
  24. package/dist/{codegen-DZOB4ttR.mjs → codegen-Dnjv7zfm.mjs} +3 -3
  25. package/dist/{codegen-DZOB4ttR.mjs.map → codegen-Dnjv7zfm.mjs.map} +1 -1
  26. package/dist/config/index.cjs +4 -2
  27. package/dist/config/index.cjs.map +1 -1
  28. package/dist/config/index.d.mts +8 -1
  29. package/dist/config/index.d.mts.map +1 -1
  30. package/dist/config/index.mjs +4 -2
  31. package/dist/config/index.mjs.map +1 -1
  32. package/dist/{config-loader-D8x32gEU.cjs → config-loader-CZfANHBf.cjs} +2 -2
  33. package/dist/config-loader-CZfANHBf.cjs.map +1 -0
  34. package/dist/{config-loader-BEgS869e.mjs → config-loader-CtbZOGjc.mjs} +3 -3
  35. package/dist/config-loader-CtbZOGjc.mjs.map +1 -0
  36. package/dist/{confirm-delete-B9o73U7B.cjs → confirm-delete-BX8bJrXZ.cjs} +3 -3
  37. package/dist/{confirm-delete-B9o73U7B.cjs.map → confirm-delete-BX8bJrXZ.cjs.map} +1 -1
  38. package/dist/{confirm-delete-CsWkW69-.mjs → confirm-delete-CcKLYuCB.mjs} +2 -2
  39. package/dist/{confirm-delete-CsWkW69-.mjs.map → confirm-delete-CcKLYuCB.mjs.map} +1 -1
  40. package/dist/{consumer-C4WiGHWG.mjs → consumer-BAM3E_68.mjs} +4 -4
  41. package/dist/{consumer-C4WiGHWG.mjs.map → consumer-BAM3E_68.mjs.map} +1 -1
  42. package/dist/{consumer-OF6Z_eTP.cjs → consumer-BSgriLn0.cjs} +4 -4
  43. package/dist/consumer-BSgriLn0.cjs.map +1 -0
  44. package/dist/consumer-D-Y6KJ8a.cjs +18 -0
  45. package/dist/{consumer-l-8wUK8E.cjs.map → consumer-D-Y6KJ8a.cjs.map} +1 -1
  46. package/dist/{consumer-pU2HyiyA.mjs → consumer-s8LnLw4e.mjs} +4 -4
  47. package/dist/consumer-s8LnLw4e.mjs.map +1 -0
  48. package/dist/content-ClRuLcGq.cjs +20 -0
  49. package/dist/{content-DMjSwor1.cjs.map → content-ClRuLcGq.cjs.map} +1 -1
  50. package/dist/content-DWnYo6ad.mjs +20 -0
  51. package/dist/{content-BOb6NC8M.mjs.map → content-DWnYo6ad.mjs.map} +1 -1
  52. package/dist/{create-DJY71sp9.cjs → create-B3d4CDel.cjs} +2 -2
  53. package/dist/{create-DJY71sp9.cjs.map → create-B3d4CDel.cjs.map} +1 -1
  54. package/dist/{create-CC814ixh.mjs → create-BD6iS4n6.mjs} +2 -2
  55. package/dist/{create-CC814ixh.mjs.map → create-BD6iS4n6.mjs.map} +1 -1
  56. package/dist/{create-B-PAOor6.mjs → create-BGV3F44O.mjs} +3 -3
  57. package/dist/{create-B-PAOor6.mjs.map → create-BGV3F44O.mjs.map} +1 -1
  58. package/dist/{create-Z-z3LXNW.cjs → create-BYDbsUvw.cjs} +3 -3
  59. package/dist/{create-Z-z3LXNW.cjs.map → create-BYDbsUvw.cjs.map} +1 -1
  60. package/dist/{create-Belwettw.mjs → create-BtuS23L3.mjs} +2 -2
  61. package/dist/{create-Belwettw.mjs.map → create-BtuS23L3.mjs.map} +1 -1
  62. package/dist/{create-CCsn7yp5.cjs → create-CNDCTpi0.cjs} +3 -3
  63. package/dist/{create-CCsn7yp5.cjs.map → create-CNDCTpi0.cjs.map} +1 -1
  64. package/dist/{create-BNYWcyuQ.cjs → create-DzRMGpm_.cjs} +2 -2
  65. package/dist/{create-BNYWcyuQ.cjs.map → create-DzRMGpm_.cjs.map} +1 -1
  66. package/dist/{create-B1ZBOqcV.mjs → create-fweRd0UB.mjs} +2 -2
  67. package/dist/{create-B1ZBOqcV.mjs.map → create-fweRd0UB.mjs.map} +1 -1
  68. package/dist/{create-D5suBd3J.mjs → create-m5fNBqQE.mjs} +3 -3
  69. package/dist/{create-D5suBd3J.mjs.map → create-m5fNBqQE.mjs.map} +1 -1
  70. package/dist/{create-CmOriwGo.cjs → create-tWGEtI3t.cjs} +2 -2
  71. package/dist/{create-CmOriwGo.cjs.map → create-tWGEtI3t.cjs.map} +1 -1
  72. package/dist/{delete-DhSU-Lx2.mjs → delete-B8VlzzCj.mjs} +3 -3
  73. package/dist/{delete-DhSU-Lx2.mjs.map → delete-B8VlzzCj.mjs.map} +1 -1
  74. package/dist/{delete-DVrafka1.cjs → delete-B9j8c8ln.cjs} +3 -3
  75. package/dist/{delete-DVrafka1.cjs.map → delete-B9j8c8ln.cjs.map} +1 -1
  76. package/dist/{delete-ZIifaG0i.mjs → delete-BhJK-8vE.mjs} +3 -3
  77. package/dist/{delete-ZIifaG0i.mjs.map → delete-BhJK-8vE.mjs.map} +1 -1
  78. package/dist/{delete-YYh_0khQ.mjs → delete-Bi6UhAhS.mjs} +3 -3
  79. package/dist/{delete-YYh_0khQ.mjs.map → delete-Bi6UhAhS.mjs.map} +1 -1
  80. package/dist/{delete-CCTiCYIL.cjs → delete-C_oxZa_p.cjs} +3 -3
  81. package/dist/{delete-CCTiCYIL.cjs.map → delete-C_oxZa_p.cjs.map} +1 -1
  82. package/dist/{delete-CSs5Czlo.mjs → delete-Ci7cq3mU.mjs} +3 -3
  83. package/dist/{delete-CSs5Czlo.mjs.map → delete-Ci7cq3mU.mjs.map} +1 -1
  84. package/dist/{delete-XWJRhBFs.mjs → delete-CiWkGnog.mjs} +3 -3
  85. package/dist/{delete-XWJRhBFs.mjs.map → delete-CiWkGnog.mjs.map} +1 -1
  86. package/dist/{delete-DozSxZQ7.cjs → delete-Cmk80aqF.cjs} +3 -3
  87. package/dist/{delete-DozSxZQ7.cjs.map → delete-Cmk80aqF.cjs.map} +1 -1
  88. package/dist/{delete-8yZ3j0vX.cjs → delete-CvtvB2Cr.cjs} +3 -3
  89. package/dist/{delete-8yZ3j0vX.cjs.map → delete-CvtvB2Cr.cjs.map} +1 -1
  90. package/dist/{delete-CIYY59v_.cjs → delete-DG825UwK.cjs} +4 -3
  91. package/dist/{delete-CIYY59v_.cjs.map → delete-DG825UwK.cjs.map} +1 -1
  92. package/dist/{delete-WpMIIvjj.cjs → delete-DGrSMqOt.cjs} +3 -3
  93. package/dist/{delete-WpMIIvjj.cjs.map → delete-DGrSMqOt.cjs.map} +1 -1
  94. package/dist/{delete-BOUObrDw.mjs → delete-Datr3Kqq.mjs} +3 -2
  95. package/dist/{delete-BOUObrDw.mjs.map → delete-Datr3Kqq.mjs.map} +1 -1
  96. package/dist/{delete-D4r1ve4v.cjs → delete-TTF4pIKw.cjs} +3 -3
  97. package/dist/{delete-D4r1ve4v.cjs.map → delete-TTF4pIKw.cjs.map} +1 -1
  98. package/dist/{delete-BSLIXrAh.mjs → delete-X8iVsETw.mjs} +3 -3
  99. package/dist/{delete-BSLIXrAh.mjs.map → delete-X8iVsETw.mjs.map} +1 -1
  100. package/dist/docs/features/cli/authentication.md +93 -0
  101. package/dist/docs/features/cli/commands/agent.md +49 -0
  102. package/dist/docs/features/cli/commands/auth.md +36 -0
  103. package/dist/docs/features/cli/commands/bucket.md +120 -0
  104. package/dist/docs/features/cli/commands/codegen.md +51 -0
  105. package/dist/docs/features/cli/commands/content.md +117 -0
  106. package/dist/docs/features/cli/commands/key.md +155 -0
  107. package/dist/docs/features/cli/commands/link.md +21 -0
  108. package/dist/docs/features/cli/commands/org.md +18 -0
  109. package/dist/docs/features/cli/commands/project-user.md +108 -0
  110. package/dist/docs/features/cli/commands/project.md +106 -0
  111. package/dist/docs/features/cli/commands/schema.md +108 -0
  112. package/dist/docs/features/cli/commands/webhook.md +110 -0
  113. package/dist/docs/features/cli/commands.md +110 -0
  114. package/dist/docs/features/cli/configuration.md +70 -0
  115. package/dist/docs/features/cli/output.md +53 -0
  116. package/dist/docs/features/cli/project-linking.md +58 -0
  117. package/dist/docs/features/cli/quickstart.md +83 -0
  118. package/dist/docs/features/cli.md +56 -0
  119. package/dist/docs/features/cms-sdk/account.md +122 -0
  120. package/dist/docs/features/cms-sdk/auth.md +122 -0
  121. package/dist/docs/features/cms-sdk/bucket.md +113 -0
  122. package/dist/docs/features/cms-sdk/cli.md +104 -0
  123. package/dist/docs/features/cms-sdk/fetch-contents.md +608 -0
  124. package/dist/docs/features/cms-sdk/install.md +98 -0
  125. package/dist/docs/features/cms-sdk/management-user.md +244 -0
  126. package/dist/docs/features/cms-sdk/migrate-to-v2.md +152 -0
  127. package/dist/docs/features/cms-sdk/mutation-contents.md +190 -0
  128. package/dist/docs/features/console/audit-logs.md +55 -0
  129. package/dist/docs/features/console/bucket.md +70 -0
  130. package/dist/docs/features/console/create-project.md +103 -0
  131. package/dist/docs/features/console/generate-api-key.md +103 -0
  132. package/dist/docs/features/console/invite-project-users.md +70 -0
  133. package/dist/docs/features/console/management-tables.md +131 -0
  134. package/dist/docs/features/console/organization-member-management.md +78 -0
  135. package/dist/docs/features/console/schema-history.md +29 -0
  136. package/dist/docs/features/console.md +15 -0
  137. package/dist/docs/features/consumer-sdk/cli.md +60 -0
  138. package/dist/docs/features/consumer-sdk/fetch-contents.md +603 -0
  139. package/dist/docs/features/consumer-sdk/install.md +90 -0
  140. package/dist/docs/features/consumer-sdk/migrate-to-v2.md +43 -0
  141. package/dist/docs/features/design-editor/about.md +36 -0
  142. package/dist/docs/features/design-editor/getting-started.md +244 -0
  143. package/dist/docs/features/design-editor/install.md +17 -0
  144. package/dist/docs/features/design-editor/prop-editor.md +83 -0
  145. package/dist/docs/features/design-editor/schema.md +279 -0
  146. package/dist/docs/features/dictionary.md +265 -0
  147. package/dist/docs/features/draft.md +241 -0
  148. package/dist/docs/features/form/about.md +83 -0
  149. package/dist/docs/features/form/editor.md +410 -0
  150. package/dist/docs/features/form/submission.md +94 -0
  151. package/dist/docs/features/full-text-search.md +114 -0
  152. package/dist/docs/features/history.md +152 -0
  153. package/dist/docs/features/schema/about.md +215 -0
  154. package/dist/docs/features/schema/authority.md +456 -0
  155. package/dist/docs/features/schema/bucket.md +142 -0
  156. package/dist/docs/features/schema/database.md +419 -0
  157. package/dist/docs/features/schema/table-module.md +140 -0
  158. package/dist/docs/features/webhook/revalidate-nextjs.md +185 -0
  159. package/dist/docs/features/webhook.md +295 -0
  160. package/dist/docs/get-started/add-model-starter.md +124 -0
  161. package/dist/docs/get-started/get-started-with-starter.md +218 -0
  162. package/dist/docs/index.md +89 -0
  163. package/dist/docs/introduction.md +140 -0
  164. package/dist/docs/manifest.json +6 -0
  165. package/dist/docs/resources/cli-migration-guide.md +82 -0
  166. package/dist/docs/resources/cli-v2-to-v3-migration-guide.md +138 -0
  167. package/dist/docs/resources/deploy-to-vercel.md +62 -0
  168. package/dist/docs/resources/limits.md +24 -0
  169. package/dist/docs/resources/private-registry.md +23 -0
  170. package/dist/docs/resources/status.md +22 -0
  171. package/dist/docs/resources/user-model.md +38 -0
  172. package/dist/{download-ogGbb3FU.cjs → download-BkzmfQXD.cjs} +2 -2
  173. package/dist/{download-ogGbb3FU.cjs.map → download-BkzmfQXD.cjs.map} +1 -1
  174. package/dist/{download-oFGzg30E.mjs → download-Dx1oyrMg.mjs} +2 -2
  175. package/dist/{download-oFGzg30E.mjs.map → download-Dx1oyrMg.mjs.map} +1 -1
  176. package/dist/{erd-zDoF6I_y.mjs → erd-BihhEfZ_.mjs} +3 -3
  177. package/dist/{erd-zDoF6I_y.mjs.map → erd-BihhEfZ_.mjs.map} +1 -1
  178. package/dist/{erd-lKC5NB2l.cjs → erd-DmnB1v2c.cjs} +3 -3
  179. package/dist/{erd-lKC5NB2l.cjs.map → erd-DmnB1v2c.cjs.map} +1 -1
  180. package/dist/{get-CgEgETQa.mjs → get-1TtxSEoT.mjs} +2 -2
  181. package/dist/{get-CgEgETQa.mjs.map → get-1TtxSEoT.mjs.map} +1 -1
  182. package/dist/{get-DjRyK0hJ.cjs → get-B5S1GfjR.cjs} +2 -2
  183. package/dist/{get-DjRyK0hJ.cjs.map → get-B5S1GfjR.cjs.map} +1 -1
  184. package/dist/{get-DDB89cOs.mjs → get-BLDHE_Zl.mjs} +2 -2
  185. package/dist/{get-DDB89cOs.mjs.map → get-BLDHE_Zl.mjs.map} +1 -1
  186. package/dist/{get-KdWfYINc.cjs → get-C5OH05Ka.cjs} +2 -2
  187. package/dist/{get-KdWfYINc.cjs.map → get-C5OH05Ka.cjs.map} +1 -1
  188. package/dist/{get-DwtzBjGV.cjs → get-CKZPn669.cjs} +2 -2
  189. package/dist/{get-DwtzBjGV.cjs.map → get-CKZPn669.cjs.map} +1 -1
  190. package/dist/{get-IOU__2RP.cjs → get-CdDZkUXV.cjs} +2 -2
  191. package/dist/{get-IOU__2RP.cjs.map → get-CdDZkUXV.cjs.map} +1 -1
  192. package/dist/{get-DB80UNSR.mjs → get-Cw4Dw5NG.mjs} +2 -2
  193. package/dist/{get-DB80UNSR.mjs.map → get-Cw4Dw5NG.mjs.map} +1 -1
  194. package/dist/{get-C7dKoSIc.mjs → get-Dy3AD4il.mjs} +2 -2
  195. package/dist/{get-C7dKoSIc.mjs.map → get-Dy3AD4il.mjs.map} +1 -1
  196. package/dist/{get-BBOKSXkh.cjs → get-PVsUGHBR.cjs} +2 -2
  197. package/dist/{get-BBOKSXkh.cjs.map → get-PVsUGHBR.cjs.map} +1 -1
  198. package/dist/{get-B6vBaq_D.mjs → get-Vo3yr12d.mjs} +2 -2
  199. package/dist/{get-B6vBaq_D.mjs.map → get-Vo3yr12d.mjs.map} +1 -1
  200. package/dist/{get-jwXRlIBJ.cjs → get-jaN2o0XY.cjs} +2 -2
  201. package/dist/{get-jwXRlIBJ.cjs.map → get-jaN2o0XY.cjs.map} +1 -1
  202. package/dist/{get-DBxhbN1G.mjs → get-qOKYAc46.mjs} +2 -2
  203. package/dist/{get-DBxhbN1G.mjs.map → get-qOKYAc46.mjs.map} +1 -1
  204. package/dist/init-BpKpTQ0z.mjs +425 -0
  205. package/dist/init-BpKpTQ0z.mjs.map +1 -0
  206. package/dist/init-BrZCChEG.cjs +427 -0
  207. package/dist/init-BrZCChEG.cjs.map +1 -0
  208. package/dist/{invite-DPygtCoO.cjs → invite-Tw3SMV0Q.cjs} +2 -2
  209. package/dist/{invite-DPygtCoO.cjs.map → invite-Tw3SMV0Q.cjs.map} +1 -1
  210. package/dist/{invite-D66DSMvq.mjs → invite-vzajkU2u.mjs} +2 -2
  211. package/dist/{invite-D66DSMvq.mjs.map → invite-vzajkU2u.mjs.map} +1 -1
  212. package/dist/{key-C71Ffll9.mjs → key-CyVxu3Uk.mjs} +3 -3
  213. package/dist/{key-C71Ffll9.mjs.map → key-CyVxu3Uk.mjs.map} +1 -1
  214. package/dist/{key-DQr7qRL2.cjs → key-tRYRqYNo.cjs} +3 -3
  215. package/dist/{key-DQr7qRL2.cjs.map → key-tRYRqYNo.cjs.map} +1 -1
  216. package/dist/{link-BluFyxEL.mjs → link-Bd55x5Zf.mjs} +2 -2
  217. package/dist/{link-BluFyxEL.mjs.map → link-Bd55x5Zf.mjs.map} +1 -1
  218. package/dist/{link-DYu1Vjlw.cjs → link-Cz7MX02S.cjs} +2 -2
  219. package/dist/{link-DYu1Vjlw.cjs.map → link-Cz7MX02S.cjs.map} +1 -1
  220. package/dist/{list-D5PSDMWw.mjs → list-2otVufvs.mjs} +3 -3
  221. package/dist/{list-D5PSDMWw.mjs.map → list-2otVufvs.mjs.map} +1 -1
  222. package/dist/{list-sQk00GV5.mjs → list-BMnBuZMr.mjs} +2 -2
  223. package/dist/{list-sQk00GV5.mjs.map → list-BMnBuZMr.mjs.map} +1 -1
  224. package/dist/{list-BwfpuhmJ.cjs → list-Bo8IMFd0.cjs} +2 -2
  225. package/dist/{list-BwfpuhmJ.cjs.map → list-Bo8IMFd0.cjs.map} +1 -1
  226. package/dist/{list-B0N4-Q-5.mjs → list-BtgAAUKm.mjs} +2 -2
  227. package/dist/{list-B0N4-Q-5.mjs.map → list-BtgAAUKm.mjs.map} +1 -1
  228. package/dist/{list-vbMaOiza.mjs → list-C0lq-gBZ.mjs} +2 -2
  229. package/dist/{list-vbMaOiza.mjs.map → list-C0lq-gBZ.mjs.map} +1 -1
  230. package/dist/{list-BsYYq9wT.mjs → list-CGZ3iT6J.mjs} +2 -2
  231. package/dist/{list-BsYYq9wT.mjs.map → list-CGZ3iT6J.mjs.map} +1 -1
  232. package/dist/{list-CFwW0G9f.cjs → list-CMWXO4nB.cjs} +2 -2
  233. package/dist/{list-CFwW0G9f.cjs.map → list-CMWXO4nB.cjs.map} +1 -1
  234. package/dist/{list-rAn3uOA7.mjs → list-Ccaec0cs.mjs} +2 -2
  235. package/dist/{list-rAn3uOA7.mjs.map → list-Ccaec0cs.mjs.map} +1 -1
  236. package/dist/{list-CU42ERNY.cjs → list-Cp_mHwbN.cjs} +2 -2
  237. package/dist/{list-CU42ERNY.cjs.map → list-Cp_mHwbN.cjs.map} +1 -1
  238. package/dist/{list-D0-QrWmn.cjs → list-Cs7kbAAi.cjs} +3 -3
  239. package/dist/{list-D0-QrWmn.cjs.map → list-Cs7kbAAi.cjs.map} +1 -1
  240. package/dist/{list-DlJssPwy.cjs → list-D5IaYurn.cjs} +2 -2
  241. package/dist/{list-DlJssPwy.cjs.map → list-D5IaYurn.cjs.map} +1 -1
  242. package/dist/{list-CbvEh7eA.mjs → list-DcIBInNA.mjs} +2 -2
  243. package/dist/{list-CbvEh7eA.mjs.map → list-DcIBInNA.mjs.map} +1 -1
  244. package/dist/{list-BzLraBnA.cjs → list-Dd3veD9Z.cjs} +2 -2
  245. package/dist/{list-BzLraBnA.cjs.map → list-Dd3veD9Z.cjs.map} +1 -1
  246. package/dist/{list-DexBclfb.cjs → list-DdVKKaDN.cjs} +2 -2
  247. package/dist/{list-DexBclfb.cjs.map → list-DdVKKaDN.cjs.map} +1 -1
  248. package/dist/{list-Br6Cmi9S.cjs → list-E1sjTZLe.cjs} +2 -2
  249. package/dist/{list-Br6Cmi9S.cjs.map → list-E1sjTZLe.cjs.map} +1 -1
  250. package/dist/{list-BRh59EqI.cjs → list-KI-7REC_.cjs} +2 -2
  251. package/dist/{list-BRh59EqI.cjs.map → list-KI-7REC_.cjs.map} +1 -1
  252. package/dist/{list-ocfd7631.mjs → list-MWD4huKP.mjs} +2 -2
  253. package/dist/{list-ocfd7631.mjs.map → list-MWD4huKP.mjs.map} +1 -1
  254. package/dist/{list-57TUfNFd.mjs → list-Pf5aAoaN.mjs} +2 -2
  255. package/dist/{list-57TUfNFd.mjs.map → list-Pf5aAoaN.mjs.map} +1 -1
  256. package/dist/{list-BHvURTWd.cjs → list-fG4zo8zz.cjs} +2 -2
  257. package/dist/{list-BHvURTWd.cjs.map → list-fG4zo8zz.cjs.map} +1 -1
  258. package/dist/{list-DrZYlidZ.mjs → list-r2UPz1zW.mjs} +2 -2
  259. package/dist/{list-DrZYlidZ.mjs.map → list-r2UPz1zW.mjs.map} +1 -1
  260. package/dist/{login-FE_dbWMo.mjs → login-Dq2L3bI7.mjs} +2 -2
  261. package/dist/{login-FE_dbWMo.mjs.map → login-Dq2L3bI7.mjs.map} +1 -1
  262. package/dist/{login-2XcHd4wn.cjs → login-M1IF2MdC.cjs} +2 -2
  263. package/dist/{login-2XcHd4wn.cjs.map → login-M1IF2MdC.cjs.map} +1 -1
  264. package/dist/{logout-DC5TMJ5_.cjs → logout-BCSfFgPz.cjs} +2 -2
  265. package/dist/{logout-DC5TMJ5_.cjs.map → logout-BCSfFgPz.cjs.map} +1 -1
  266. package/dist/{logout-BDbWrGBm.mjs → logout-DFzQCQKe.mjs} +2 -2
  267. package/dist/{logout-BDbWrGBm.mjs.map → logout-DFzQCQKe.mjs.map} +1 -1
  268. package/dist/management-C1p-Hm2Z.cjs +19 -0
  269. package/dist/{management-BGYcZB4c.cjs.map → management-C1p-Hm2Z.cjs.map} +1 -1
  270. package/dist/{management-DDACMgbU.mjs → management-h4yE09a6.mjs} +5 -5
  271. package/dist/{management-DDACMgbU.mjs.map → management-h4yE09a6.mjs.map} +1 -1
  272. package/dist/object-CZDLoc9L.cjs +20 -0
  273. package/dist/{object-DVqidsEc.cjs.map → object-CZDLoc9L.cjs.map} +1 -1
  274. package/dist/object-CqMsEkh9.mjs +20 -0
  275. package/dist/{object-qdBdEghr.mjs.map → object-CqMsEkh9.mjs.map} +1 -1
  276. package/dist/{org-CPhTRTks.mjs → org-Co-rjfr-.mjs} +2 -2
  277. package/dist/{org-CPhTRTks.mjs.map → org-Co-rjfr-.mjs.map} +1 -1
  278. package/dist/{org-C4cVovOM.cjs → org-Drj3VqIm.cjs} +2 -2
  279. package/dist/{org-C4cVovOM.cjs.map → org-Drj3VqIm.cjs.map} +1 -1
  280. package/dist/{org-context-Bewx2NEW.cjs → org-context-DKFnPH_o.cjs} +2 -2
  281. package/dist/{org-context-Bewx2NEW.cjs.map → org-context-DKFnPH_o.cjs.map} +1 -1
  282. package/dist/{org-context-D0dwWC2M.mjs → org-context-Df5McOiK.mjs} +2 -2
  283. package/dist/{org-context-D0dwWC2M.mjs.map → org-context-Df5McOiK.mjs.map} +1 -1
  284. package/dist/project-C7qWFjMV.mjs +20 -0
  285. package/dist/{project-CaXD3QBs.mjs.map → project-C7qWFjMV.mjs.map} +1 -1
  286. package/dist/project-Dm7nr5NV.cjs +20 -0
  287. package/dist/{project-BX7zvWB1.cjs.map → project-Dm7nr5NV.cjs.map} +1 -1
  288. package/dist/project-user-D9h_QBc0.mjs +20 -0
  289. package/dist/{project-user-Cp7i6orv.mjs.map → project-user-D9h_QBc0.mjs.map} +1 -1
  290. package/dist/project-user-wLFnHFwB.cjs +20 -0
  291. package/dist/{project-user-Dm0qR-sh.cjs.map → project-user-wLFnHFwB.cjs.map} +1 -1
  292. package/dist/prompt-C-XNDSNE.cjs +42 -0
  293. package/dist/prompt-C-XNDSNE.cjs.map +1 -0
  294. package/dist/prompt-Dr2Rkxun.mjs +25 -0
  295. package/dist/prompt-Dr2Rkxun.mjs.map +1 -0
  296. package/dist/{push-0u6PDz4E.cjs → push-BggkrD0g.cjs} +31 -12
  297. package/dist/push-BggkrD0g.cjs.map +1 -0
  298. package/dist/{push-D7co0keA.mjs → push-xWnD9oov.mjs} +30 -11
  299. package/dist/push-xWnD9oov.mjs.map +1 -0
  300. package/dist/{run-codegen-Ceeosw5x.cjs → run-codegen-B-90rvjk.cjs} +4 -4
  301. package/dist/run-codegen-B-90rvjk.cjs.map +1 -0
  302. package/dist/{run-codegen-DgaFaIQ1.mjs → run-codegen-CrO08jJT.mjs} +4 -4
  303. package/dist/run-codegen-CrO08jJT.mjs.map +1 -0
  304. package/dist/{run-with-context-CVhmzAFZ.mjs → run-with-context-B4DyI8Wo.mjs} +6 -26
  305. package/dist/run-with-context-B4DyI8Wo.mjs.map +1 -0
  306. package/dist/{run-with-context-DJNnEigg.cjs → run-with-context-D8pSrqD_.cjs} +7 -39
  307. package/dist/run-with-context-D8pSrqD_.cjs.map +1 -0
  308. package/dist/schema-CUVTXrHk.cjs +20 -0
  309. package/dist/{schema-B3iRqvYK.cjs.map → schema-CUVTXrHk.cjs.map} +1 -1
  310. package/dist/schema-DlUWHV_t.mjs +20 -0
  311. package/dist/{schema-exG250MU.mjs.map → schema-DlUWHV_t.mjs.map} +1 -1
  312. package/dist/{status-Dq_NJE71.cjs → status-CqPJTxeK.cjs} +2 -2
  313. package/dist/{status-Dq_NJE71.cjs.map → status-CqPJTxeK.cjs.map} +1 -1
  314. package/dist/{status-fWqXzV0P.mjs → status-D7nOW3R3.mjs} +2 -2
  315. package/dist/{status-fWqXzV0P.mjs.map → status-D7nOW3R3.mjs.map} +1 -1
  316. package/dist/{token-store--9GYVL7N.cjs → token-store-BgWGhqq0.cjs} +3 -3
  317. package/dist/{token-store--9GYVL7N.cjs.map → token-store-BgWGhqq0.cjs.map} +1 -1
  318. package/dist/{token-store-reCGF86F.mjs → token-store-C2r7cFA-.mjs} +2 -2
  319. package/dist/{token-store-reCGF86F.mjs.map → token-store-C2r7cFA-.mjs.map} +1 -1
  320. package/dist/{update-B4lv4dAz.mjs → update-8-sHFvNB.mjs} +2 -2
  321. package/dist/{update-B4lv4dAz.mjs.map → update-8-sHFvNB.mjs.map} +1 -1
  322. package/dist/{update-Dyo4vuZs.mjs → update-B5hKKw0K.mjs} +3 -3
  323. package/dist/{update-Dyo4vuZs.mjs.map → update-B5hKKw0K.mjs.map} +1 -1
  324. package/dist/{update-Do9HHWzs.cjs → update-BVaqURWE.cjs} +2 -2
  325. package/dist/{update-Do9HHWzs.cjs.map → update-BVaqURWE.cjs.map} +1 -1
  326. package/dist/{update-DRnN1kiu.cjs → update-BlUwNhLA.cjs} +2 -2
  327. package/dist/{update-DRnN1kiu.cjs.map → update-BlUwNhLA.cjs.map} +1 -1
  328. package/dist/{update-Cx_2GkQj.cjs → update-BqhLwuP7.cjs} +2 -2
  329. package/dist/{update-Cx_2GkQj.cjs.map → update-BqhLwuP7.cjs.map} +1 -1
  330. package/dist/{update-mEmULIau.mjs → update-DaYjh5VN.mjs} +2 -2
  331. package/dist/{update-mEmULIau.mjs.map → update-DaYjh5VN.mjs.map} +1 -1
  332. package/dist/{update-CJgEmSWJ.cjs → update-DcTzR54Z.cjs} +3 -3
  333. package/dist/{update-CJgEmSWJ.cjs.map → update-DcTzR54Z.cjs.map} +1 -1
  334. package/dist/{update-CIH6sSVk.cjs → update-Dne7g_0s.cjs} +2 -2
  335. package/dist/{update-CIH6sSVk.cjs.map → update-Dne7g_0s.cjs.map} +1 -1
  336. package/dist/{update-CQ4n4Xuf.mjs → update-Dy1BOnTB.mjs} +2 -2
  337. package/dist/{update-CQ4n4Xuf.mjs.map → update-Dy1BOnTB.mjs.map} +1 -1
  338. package/dist/{update-rzij1b_o.mjs → update-slz_X0mG.mjs} +2 -2
  339. package/dist/{update-rzij1b_o.mjs.map → update-slz_X0mG.mjs.map} +1 -1
  340. package/dist/{upload-DGgJ1TQk.mjs → upload-CDtzV9Wx.mjs} +3 -3
  341. package/dist/{upload-DGgJ1TQk.mjs.map → upload-CDtzV9Wx.mjs.map} +1 -1
  342. package/dist/{upload-C43ZXxyb.cjs → upload-DIln1QDA.cjs} +3 -3
  343. package/dist/{upload-C43ZXxyb.cjs.map → upload-DIln1QDA.cjs.map} +1 -1
  344. package/dist/{validate-BpxZ8LTl.cjs → validate-BH8jqdqq.cjs} +2 -2
  345. package/dist/{validate-BpxZ8LTl.cjs.map → validate-BH8jqdqq.cjs.map} +1 -1
  346. package/dist/{validate-Ca0CRo16.mjs → validate-COS4bfr0.mjs} +2 -2
  347. package/dist/{validate-Ca0CRo16.mjs.map → validate-COS4bfr0.mjs.map} +1 -1
  348. package/dist/webhook-BT3cHrq5.mjs +20 -0
  349. package/dist/{webhook-CpZ1-Ho5.mjs.map → webhook-BT3cHrq5.mjs.map} +1 -1
  350. package/dist/webhook-CQeuAqec.cjs +20 -0
  351. package/dist/{webhook-CbL4QaR5.cjs.map → webhook-CQeuAqec.cjs.map} +1 -1
  352. package/package.json +10 -9
  353. package/dist/auth-CNbONZuf.cjs +0 -18
  354. package/dist/cms-BJnovGYT.mjs.map +0 -1
  355. package/dist/cms-Cnx-lDGu.cjs.map +0 -1
  356. package/dist/config-loader-BEgS869e.mjs.map +0 -1
  357. package/dist/config-loader-D8x32gEU.cjs.map +0 -1
  358. package/dist/consumer-OF6Z_eTP.cjs.map +0 -1
  359. package/dist/consumer-l-8wUK8E.cjs +0 -18
  360. package/dist/consumer-pU2HyiyA.mjs.map +0 -1
  361. package/dist/content-BOb6NC8M.mjs +0 -20
  362. package/dist/content-DMjSwor1.cjs +0 -20
  363. package/dist/management-BGYcZB4c.cjs +0 -19
  364. package/dist/object-DVqidsEc.cjs +0 -20
  365. package/dist/object-qdBdEghr.mjs +0 -20
  366. package/dist/project-BX7zvWB1.cjs +0 -20
  367. package/dist/project-CaXD3QBs.mjs +0 -20
  368. package/dist/project-user-Cp7i6orv.mjs +0 -20
  369. package/dist/project-user-Dm0qR-sh.cjs +0 -20
  370. package/dist/push-0u6PDz4E.cjs.map +0 -1
  371. package/dist/push-D7co0keA.mjs.map +0 -1
  372. package/dist/run-codegen-Ceeosw5x.cjs.map +0 -1
  373. package/dist/run-codegen-DgaFaIQ1.mjs.map +0 -1
  374. package/dist/run-with-context-CVhmzAFZ.mjs.map +0 -1
  375. package/dist/run-with-context-DJNnEigg.cjs.map +0 -1
  376. package/dist/schema-B3iRqvYK.cjs +0 -20
  377. package/dist/schema-exG250MU.mjs +0 -20
  378. package/dist/webhook-CbL4QaR5.cjs +0 -20
  379. package/dist/webhook-CpZ1-Ho5.mjs +0 -20
@@ -0,0 +1,185 @@
1
+ <!-- source: docs/src/app/features/webhook/revalidate-nextjs/page.mdx -->
2
+
3
+ # Next.js でキャッシュを再検証する
4
+
5
+ Webhook と Next.js の `revalidateTag()` を組み合わせて、更新されたコンテンツのキャッシュだけを失効させる構成を説明します。
6
+
7
+ 時間ベースの再検証では、更新がなくても再取得が走り、逆に更新直後は次の再検証まで古い内容が表示されます。Webhook で失効させると、更新があったコンテンツだけを対象にできます。
8
+
9
+ このページは Next.js 16 の App Router を前提としています。
10
+
11
+ ## 仕組み
12
+
13
+ 1. 編集者が CMS でコンテンツを公開する
14
+ 2. Orizm が設定された URL に POST リクエストを送る
15
+ 3. Route Handler がペイロードから失効させるキャッシュタグを決定する
16
+ 4. `revalidateTag()` でそのタグを失効させる
17
+ 5. 次のリクエストで最新のコンテンツが取得される
18
+
19
+ ## キャッシュタグを設計する
20
+
21
+ 一覧ページ用の「テーブル単位のタグ」と、詳細ページ用の「コンテンツ単位のタグ」の2種類があれば、ほとんどのサイトで足ります。
22
+
23
+ ```ts copy filename="src/lib/revalidate-tag.ts"
24
+ import type { OrizmClient } from "@repo/orizm/consumer";
25
+
26
+ export function generateTag(
27
+ tableName: keyof OrizmClient["tables"],
28
+ resourceId?: string,
29
+ ): string {
30
+ return resourceId ? `${tableName}:${resourceId}` : tableName;
31
+ }
32
+ ```
33
+
34
+ テーブル名を `keyof OrizmClient["tables"]` で受け取ることで、存在しないテーブル名を渡すとコンパイルエラーになります。
35
+
36
+ ## コンテンツ取得にタグを付ける
37
+
38
+ Consumer SDK の各メソッドは最後の引数で `RequestInit` を受け取ります。ここで `next.tags` を指定すると、その取得結果にキャッシュタグが付きます。
39
+
40
+ ```ts copy filename="src/features/blog/get-blog-list.ts"
41
+ import { serverSideCmsClient } from "@/lib/orizm-client";
42
+ import { generateTag } from "@/lib/revalidate-tag";
43
+
44
+ export function getBlogList() {
45
+ return serverSideCmsClient.tables.blog.list(
46
+ { order: { publishedAt: "desc" } },
47
+ { next: { tags: [generateTag("blog")] } },
48
+ );
49
+ }
50
+ ```
51
+
52
+ 詳細ページにはコンテンツ単位のタグだけを付けます。失効させる側で必要なタグをまとめて渡すため、取得側は1つのタグで済みます。
53
+
54
+ ```ts copy filename="src/features/blog/detail/id/get-blog-single.ts"
55
+ import { serverSideCmsClient } from "@/lib/orizm-client";
56
+ import { generateTag } from "@/lib/revalidate-tag";
57
+
58
+ export function getBlogSingle(id: string) {
59
+ return serverSideCmsClient.tables.blog.get(
60
+ id,
61
+ { include: { category: true } },
62
+ { next: { tags: [generateTag("blog", id)] } },
63
+ );
64
+ }
65
+ ```
66
+
67
+ `RequestInit` の指定方法は [コンテンツの取得](../consumer-sdk/fetch-contents.md) を参照してください。
68
+
69
+ ## Route Handler を実装する
70
+
71
+ Webhook を受け取るエンドポイントを作ります。ペイロードの型 `WebhookPayload` は `orizm codegen consumer` が生成します。`table` をキーにした判別可能なユニオンなので、`switch` で分岐すると `content` の型がそのテーブルの型に絞られます。
72
+
73
+ 送信元の確認には [署名の検証](../webhook.md#署名の検証) を使います。`jwksUrl` に設定する値は後述の [エンドポイントを保護する](#エンドポイントを保護する) を参照してください。
74
+
75
+ ```ts copy filename="src/app/api/revalidate/route.ts"
76
+ import type { WebhookPayload } from "@repo/orizm/consumer";
77
+ import { createWebhookVerifier } from "@orizm/consumer-sdk/webhook";
78
+ import { revalidateTag } from "next/cache";
79
+ import { type NextRequest, NextResponse } from "next/server";
80
+ import { generateTag } from "@/lib/revalidate-tag";
81
+ import { env } from "@/env";
82
+
83
+ // リクエストごとに作り直すと JWKS のキャッシュが効かないため、モジュールスコープに置く
84
+ const verifier = createWebhookVerifier<WebhookPayload>({
85
+ jwksUrl: env.ORIZM_WEBHOOK_JWKS_URL,
86
+ // インスタンスが使い捨てられてもキャッシュが効くよう、JWKS の取得を Data Cache に載せる
87
+ fetchOptions: { next: { revalidate: 300 } },
88
+ });
89
+
90
+ export const POST = async (request: NextRequest): Promise<Response> => {
91
+ const result = await verifier.verifyRequest(request);
92
+
93
+ if (!result.valid) {
94
+ return NextResponse.json({ error: result.reason }, { status: 401 });
95
+ }
96
+
97
+ const revalidateTags = await getRevalidateTags(result.body);
98
+
99
+ for (const tag of revalidateTags) {
100
+ revalidateTag(tag, "max");
101
+ }
102
+
103
+ return NextResponse.json({ revalidated: revalidateTags });
104
+ };
105
+
106
+ const getRevalidateTags = async (
107
+ payload: WebhookPayload,
108
+ ): Promise<string[]> => {
109
+ switch (payload.table) {
110
+ case "blog": {
111
+ return [generateTag("blog"), generateTag("blog", payload.content.id)];
112
+ }
113
+ // ...
114
+ default: {
115
+ assertNever(payload);
116
+ }
117
+ }
118
+ };
119
+
120
+ function assertNever(x: never): never {
121
+ throw new Error(`Unexpected payload: ${JSON.stringify(x)}`);
122
+ }
123
+ ```
124
+
125
+ 実装時の注意は4点です。
126
+
127
+ - `verifyRequest` は署名検証のために body を読み切るため、呼び出したあとに `request.json()` を呼ぶことはできません。ペイロードは `result.body` から取得します
128
+ - JWKS が取得できないときは `WebhookJwksFetchError` が throw されます。捕捉せずに Next.js に 500 を返させれば、Orizm が再送します。ただし JWKS URL が 404 を返す場合は設定間違いなので、`reason` が `jwks-not-found` の検証失敗として返ります
129
+ - 配信は5秒でタイムアウトします。タグを組むために参照先を引く必要がある場合も、軽量な取得1回程度に留めてください
130
+ - 同じイベントが複数回届くことがあります。`revalidateTag()` は何度呼んでも問題ありませんが、それ以外の副作用を行う場合は重複実行を考慮してください
131
+
132
+ 配信の詳細は [配信の仕様](../webhook.md#配信の仕様) を参照してください。
133
+
134
+ ## エンドポイントを保護する
135
+
136
+ このエンドポイントは公開 URL に置くため、Orizm 以外からのリクエストを拒否する必要があります。Orizm はリクエストに Ed25519 署名を付与するため、[署名の検証](../webhook.md#署名の検証)で送信元を確認します。
137
+
138
+ 検証に使う JWKS の URL は、Orizm コンソールの Webhook 詳細画面に表示されます。
139
+
140
+ この URL が返すのは公開鍵だけなので、秘密の値として扱う必要はありません。ソースコードに直接書いても構いませんし、環境ごとに Webhook を分けていて URL が変わる場合は、環境変数にしておくと扱いやすくなります。
141
+
142
+ ```sh copy filename="apps/consumer/.env.local"
143
+ ORIZM_WEBHOOK_JWKS_URL=<コンソールに表示される JWKS URL>
144
+ ```
145
+
146
+ 署名の検証に失敗して401を返すと、その通知はリトライされずに失われます。設定を直したあとは、改めてコンテンツを更新して配信を発生させてください。
147
+
148
+ ## Orizm に Webhook を登録する
149
+
150
+ エンドポイントを用意したら、Orizm 側に通知先として登録します。開発者コンソールでの手順は [設定方法](../webhook.md#設定方法) を参照してください。
151
+
152
+ CLI からも登録できます。
153
+
154
+ ```sh copy
155
+ orizm webhook create --name "revalidate" \
156
+ --url https://example.com/api/revalidate \
157
+ --table-event blog:content.create \
158
+ --table-event blog:content.update \
159
+ --table-event blog:content.delete
160
+ ```
161
+
162
+ 購読するテーブルとイベントは、サイトの表示に使っているものだけに絞ります。どの編集操作でどのイベントが届くかは [編集操作とイベントの対応](../webhook.md#編集操作とイベントの対応) を参照してください。
163
+
164
+ あとからスキーマにテーブルを追加してサイトの表示に使う場合は、Table Events への追加も必要です。追加を忘れると、そのテーブルの更新は通知されません。
165
+
166
+ ## デプロイ時の注意
167
+
168
+ - **Basic 認証やアクセス制限から除外する。** Next.js 16 の `proxy.ts` (Next.js 15 以前の `middleware.ts`) で Basic 認証をかけている場合、`matcher` から `/api/revalidate` を除外してください
169
+ - **Vercel の Deployment Protection を確認する。** 保護が有効な環境では外部からの POST が拒否されます。保護をバイパスする設定を行うか、本番環境のみに Webhook を登録してください
170
+
171
+ ## うまく動かないとき
172
+
173
+ **再検証されない**
174
+
175
+ - 開発サーバーではキャッシュの挙動が本番と異なります。デプロイした環境で確認してください
176
+ - 取得側に `next.tags` を付け忘れていないか確認してください。タグが付いていないキャッシュは `revalidateTag()` の対象になりません
177
+ - Route Handler が返した `revalidated` に意図したタグが含まれているか、ログで確認してください
178
+ - `revalidateTag()` の第2引数に `"max"` を指定している場合、そのページが次に表示されるまで再取得は始まりません
179
+ - 予約公開・予約非公開を使っている場合、指定した時刻から最大1分ほど遅れて通知されます
180
+
181
+ **401が返る**
182
+
183
+ - `ORIZM_WEBHOOK_JWKS_URL` が、通知を受け取りたい Webhook の JWKS URL と一致しているか確認してください。JWKS は Webhook ごとに異なるため、別の Webhook の URL では検証に失敗します
184
+ - `verifyRequest` より先に `request.json()` などで body を読んでいないか確認してください
185
+ - Basic 認証やアクセス制限がエンドポイントに掛かっていないか確認してください
@@ -0,0 +1,295 @@
1
+ <!-- source: docs/src/app/features/webhook/page.mdx -->
2
+
3
+ # Webhook
4
+
5
+ Webhook機能を使用すると、コンテンツの作成、更新、削除が行われた際に、指定したURLに通知を送信できます。これにより、外部システムやサービスとの連携が可能です。
6
+
7
+ ## 機能
8
+
9
+ - コンテンツの作成、更新、削除を通知
10
+ - テーブルごとに通知するイベントを指定
11
+ - カスタムリクエストヘッダーに対応
12
+ - 配信失敗時の自動リトライ
13
+ - Ed25519 署名による送信元の検証
14
+
15
+ ## 設定方法
16
+
17
+ Orizmコンソールのプロジェクト設定からWebhookを設定できます。
18
+
19
+ コマンドラインから設定する場合は [webhook コマンド](./cli/commands/webhook.md) を参照してください。
20
+
21
+ ### プロジェクト設定を開く
22
+
23
+ ![プロジェクト設定を開く](./webhook-access-project-settings.png)
24
+
25
+ ### Webhook設定を開く
26
+
27
+ ![Webhook設定を開く](./webhook-access-webhooks.png)
28
+
29
+ ### Webhookの作成をクリック
30
+
31
+ ![Webhookの作成をクリック](./webhook-create-new.png)
32
+
33
+ ### Webhookの作成
34
+
35
+ ![Webhookの作成](./webhook-create.png)
36
+
37
+ | プロパティ名 | 概要 |
38
+ | ------------ | ------------------------------------------------- |
39
+ | Name | コンソール上の表示用です |
40
+ | URL | 指定したURLにPOSTリクエストでイベントを通知します |
41
+
42
+ ### テーブルとイベントを選択
43
+
44
+ Table Events で通知を受け取るテーブルとイベントを選択します。
45
+
46
+ - `Add Table Event` をクリックするとテーブルを追加します
47
+ - `Add All Tables` をクリックすると全てのテーブルを追加します
48
+
49
+ 特定のイベント通知が不要な場合は、チェックボックスを解除することで通知を無効にできます。
50
+
51
+ `Save` をクリックすると設定が保存されます。
52
+
53
+ ![テーブルとイベントを選択](./webhook-select-table-and-event.png)
54
+
55
+ ### カスタムリクエストヘッダー
56
+
57
+ Custom Request Headers で必要に応じて、HTTPリクエストに任意のヘッダーを追加できます。
58
+
59
+ ![カスタムHTTPヘッダー](./webhook-custom-headers.png)
60
+
61
+ ## サポートしているイベント
62
+
63
+ | イベント名 | 説明 |
64
+ | ---------------- | ---------------------------- |
65
+ | `content.create` | コンテンツが新規作成された時 |
66
+ | `content.update` | コンテンツが更新された時 |
67
+ | `content.delete` | コンテンツが削除された時 |
68
+
69
+ ### 編集操作とイベントの対応
70
+
71
+ 公開や非公開には専用のイベントがなく、いずれも`content.update`として通知されます。
72
+
73
+ | 編集操作 | 通知されるイベント | `old` |
74
+ | -------------------- | ------------------ | ----- |
75
+ | コンテンツの作成 | `content.create` | なし |
76
+ | コンテンツの更新 | `content.update` | あり |
77
+ | コンテンツの公開 | `content.update` | なし |
78
+ | コンテンツの非公開 | `content.update` | なし |
79
+ | コンテンツの削除 | `content.delete` | なし |
80
+ | 予約公開・予約非公開 | `content.update` | なし |
81
+
82
+ 予約公開・予約非公開は1分ごとに実行対象を確認するため、指定した時刻から最大1分ほど遅れて通知されます。
83
+
84
+ ## Webhookペイロード
85
+
86
+ Webhookがトリガーされると、指定したURLにPOSTリクエストで以下のようなJSON形式のデータが送信されます。
87
+
88
+ ```json
89
+ {
90
+ "event": "content.create",
91
+ "timestamp": "2025-01-01T00:00:00.000Z",
92
+ "project": "projectName",
93
+ "table": "tableName",
94
+ "content": {
95
+ "id": "xxxxxxxx"
96
+ ...
97
+ }
98
+ }
99
+ ```
100
+
101
+ ### event
102
+
103
+ トリガーされたイベントの名前です。[サポートしているイベント](#サポートしているイベント) のイベント名が入ります。
104
+
105
+ ### timestamp
106
+
107
+ イベントの発生時刻です。
108
+
109
+ ISO 8601形式で表現されます。(例: `2025-01-01T00:00:00.000Z`)
110
+
111
+ ### project
112
+
113
+ イベントが発生したプロジェクト名です。
114
+
115
+ ### table
116
+
117
+ イベントが発生したテーブル名です。
118
+
119
+ ### content
120
+
121
+ イベントが発生した際のコンテンツです。
122
+
123
+ ### old
124
+
125
+ イベントが発生した際の変更前のコンテンツです。
126
+
127
+ コンテンツの更新の場合のみ存在します。
128
+
129
+ ## 配信の仕様
130
+
131
+ | 項目 | 仕様 |
132
+ | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
133
+ | HTTPメソッド | `POST` |
134
+ | リクエストヘッダー | `Content-Type: application/json`、`User-Agent: superx-webhook`、[署名ヘッダー](#署名の検証)(`webhook-id`、`webhook-timestamp`、`webhook-signature`)、および設定したカスタムリクエストヘッダー |
135
+ | タイムアウト | 5秒 |
136
+ | 成功の判定 | ステータスコードが2xx |
137
+ | リトライする失敗 | タイムアウト、ネットワークエラー、5xxのレスポンス |
138
+ | リトライしない失敗 | 4xxのレスポンス |
139
+ | 試行回数 | 初回を含めて最大10回 |
140
+ | リトライの間隔 | 指数バックオフ(1秒から始まり、失敗するたびに倍になります) |
141
+
142
+ - 通知先が複数設定されている場合、宛先ごとに独立して配信とリトライを行います。失敗した宛先だけが再送されます
143
+ - リトライ中に設定を変更しても、進行中の配信には反映されません
144
+ - リトライが発生すると、あとに発生したイベントが先に届くことがあります。またタイムアウトしたリクエストが受信側では処理されていた場合、同じイベントが複数回届きます
145
+
146
+ 受信側は、同じイベントを複数回受け取っても問題のない実装にしてください。
147
+
148
+ ## 署名の検証
149
+
150
+ Orizm は Webhook の POST リクエストに [Standard Webhooks](https://www.standardwebhooks.com/) 準拠の Ed25519 署名を付与します。受信側で署名を検証すると、リクエストが自分の登録したその Webhook 設定に由来することを暗号学的に確認できます。
151
+
152
+ ### 署名ヘッダー
153
+
154
+ | ヘッダー | 説明 |
155
+ | ------------------- | ----------------------------------------------------------------------------------- |
156
+ | `webhook-id` | 配信ごとに一意な ID。リトライしても同じ値のため、受信側の冪等性キーとして使えます |
157
+ | `webhook-timestamp` | 送信試行時刻(Unix 秒)。リトライごとに新しい値になります |
158
+ | `webhook-signature` | `v1a,<base64>` 形式の署名。**スペース区切りで複数の署名が併記されることがあります** |
159
+
160
+ 署名ヘッダーはカスタムリクエストヘッダーでは上書きできません。
161
+
162
+ ### 公開鍵の取得
163
+
164
+ 検証に使う公開鍵は、Webhook ごとの JWKS エンドポイントで配布されます。URL は Orizm コンソールの Webhook 詳細画面に表示されます。
165
+
166
+ 鍵は自動的にローテーションされます。公開鍵をコードや設定ファイルにコピーして固定せず、必ず JWKS エンドポイントから取得してください。
167
+
168
+ - JWKS のレスポンスは 5 分〜24 時間を目安にキャッシュしてください
169
+ - 手持ちのどの鍵でも検証に失敗したときは、JWKS を再取得してから一度だけ再試行してください(鍵のローテーション直後に古いキャッシュを使っているケースに対応できます)。再取得には 30 秒程度の最短間隔を設けてください
170
+ - ローテーションの移行中は、新旧 2 つの鍵による 2 つの署名が届きます。**署名が 1 つである前提の実装は、ローテーションのたびに壊れます**
171
+
172
+ ### 検証の手順
173
+
174
+ 1. `webhook-timestamp` が現在時刻から許容窓(推奨 ±5 分)以内であることを確認します。超えていたら拒否します(リプレイ対策)
175
+ 2. `webhook-id`、`webhook-timestamp`、リクエストボディを `.` で連結した文字列 `{webhook-id}.{webhook-timestamp}.{body}` を署名対象とします
176
+ 3. `webhook-signature` をスペースで分割し、`v1a,` に続く base64 の署名のいずれかが、JWKS 内のいずれかの鍵で Ed25519 検証に通れば成功です
177
+
178
+ 署名は **JSON パース前の raw body** に対して行われます。パースした値を再シリアライズするとバイト列が一致しないことがあるため、必ず受信したそのままのボディ文字列で検証してください。
179
+
180
+ ### レスポンスコードの指針
181
+
182
+ | 状況 | 返すべきステータス |
183
+ | ---------------------------------------- | ------------------------------------------ |
184
+ | 署名の検証の結果、リクエストが不正 | `401`(Orizm は 4xx に対して再送しません) |
185
+ | JWKS URL が誤っているなど設定に起因する | `4xx`(再送しても解決しません) |
186
+ | JWKS が取得できないなどの一時障害 | `5xx`(Orizm が再送します) |
187
+
188
+ ### SDK で検証する
189
+
190
+ `@orizm/cms-sdk/webhook` または `@orizm/consumer-sdk/webhook` の `createWebhookVerifier` を使うと、JWKS の取得とキャッシュ、複数署名のパース、タイムスタンプの検証までをまとめて行えます。Web Crypto API と `fetch` だけで実装されているため、Cloudflare Workers や Vercel Edge などの Node.js 以外のランタイムでも動作します。
191
+
192
+ `verifyRequest` に受信した `Request` を渡すと、raw body の取り出しから検証、ペイロードのパースまでを行います。検証に成功した場合だけ `body` からペイロードを取得できます。ペイロードの型 `WebhookPayload` は `orizm codegen consumer` が生成します。
193
+
194
+ ```ts copy filename="src/app/api/webhook/route.ts"
195
+ import type { WebhookPayload } from "@repo/orizm/consumer";
196
+ import { createWebhookVerifier } from "@orizm/consumer-sdk/webhook";
197
+
198
+ // リクエストごとに作り直すと JWKS のキャッシュが効かないため、モジュールスコープに置く
199
+ const verifier = createWebhookVerifier<WebhookPayload>({
200
+ jwksUrl: "<コンソールに表示される JWKS URL>",
201
+ });
202
+
203
+ export const POST = async (request: Request): Promise<Response> => {
204
+ const result = await verifier.verifyRequest(request);
205
+
206
+ if (!result.valid) {
207
+ return Response.json({ error: result.reason }, { status: 401 });
208
+ }
209
+
210
+ // result.body は検証済みのペイロード
211
+ console.log(result.body.event, result.body.table);
212
+ return Response.json({ ok: true });
213
+ };
214
+ ```
215
+
216
+ `verifyRequest` は署名検証のために body を読み切るため、呼び出したあとに `request.json()` や `request.text()` を呼ぶことはできません。ペイロードは `result.body` から取得してください。
217
+
218
+ JWKS が取得できないときは `WebhookJwksFetchError` が throw されます。署名の真偽を判定できていない一時障害なので、そのまま throw させてフレームワークに 5xx を返させるのが適切です(Orizm が再送します)。捕捉して独自のレスポンスを返す場合も、401 ではなく 5xx を返してください。
219
+
220
+ ただし JWKS URL が 404 を返した場合は、URL の設定間違いであって再送では解決しないため、throw ではなく `reason` が `jwks-not-found` の検証失敗として返ります。`result.reason` をログに出しておくと、署名が不正だったのか URL の設定が誤っているのかを切り分けられます。
221
+
222
+ #### JWKS の取得をランタイムのキャッシュに載せる
223
+
224
+ verifier は取得した JWKS をメモリ上にキャッシュしますが、サーバーレス環境ではインスタンスが使い捨てられるためキャッシュが効かないことがあります。`fetchOptions` に渡した値は JWKS 取得の `fetch` にそのまま渡るので、Next.js の Data Cache などに載せられます。
225
+
226
+ ```ts copy filename="src/app/api/webhook/route.ts"
227
+ const verifier = createWebhookVerifier<WebhookPayload>({
228
+ jwksUrl: "<コンソールに表示される JWKS URL>",
229
+ fetchOptions: { next: { revalidate: 300 } },
230
+ });
231
+ ```
232
+
233
+ 鍵は自動ローテーションされるため、`cache: "force-cache"` や `next: { revalidate: false }` のような無期限キャッシュは指定しないでください。JWKS が更新されず、ローテーション後に検証が通らなくなります。
234
+
235
+ Express や素の `node:http` のように `Request` を組み立てられない環境では、raw body 文字列とヘッダーを渡す `verifyPayload` を使います。
236
+
237
+ ```ts copy filename="src/webhook.ts"
238
+ // express.raw({ type: "application/json" }) などで生のボディを受け取っておく
239
+ const result = await verifier.verifyPayload(
240
+ req.body.toString("utf8"),
241
+ req.headers,
242
+ );
243
+ ```
244
+
245
+ ### SDK を使わずに検証する
246
+
247
+ 依存を追加せず、Web Crypto API だけで検証する例です。
248
+
249
+ ```ts copy filename="verify-webhook.ts"
250
+ export async function verifyWebhook(
251
+ jwksUrl: string,
252
+ payload: string,
253
+ headers: Headers,
254
+ ): Promise<boolean> {
255
+ const id = headers.get("webhook-id");
256
+ const timestamp = headers.get("webhook-timestamp");
257
+ const signatureHeader = headers.get("webhook-signature");
258
+ if (id === null || timestamp === null || signatureHeader === null) {
259
+ return false;
260
+ }
261
+
262
+ // リプレイ対策: 許容窓 ±5 分
263
+ const skew = Math.abs(Date.now() / 1000 - Number(timestamp));
264
+ if (!Number.isFinite(skew) || skew > 300) {
265
+ return false;
266
+ }
267
+
268
+ // 実際には 5 分〜24 時間を目安にキャッシュする
269
+ const jwks = await fetch(jwksUrl).then((res) => res.json());
270
+ const publicKeys = await Promise.all(
271
+ jwks.keys.map((jwk) =>
272
+ crypto.subtle.importKey("jwk", jwk, "Ed25519", false, ["verify"]),
273
+ ),
274
+ );
275
+
276
+ const content = new TextEncoder().encode(`${id}.${timestamp}.${payload}`);
277
+ const signatures = signatureHeader
278
+ .split(" ")
279
+ .filter((entry) => entry.startsWith("v1a,"))
280
+ .map((entry) =>
281
+ Uint8Array.from(atob(entry.slice(4)), (char) => char.charCodeAt(0)),
282
+ );
283
+
284
+ for (const key of publicKeys) {
285
+ for (const signature of signatures) {
286
+ if (await crypto.subtle.verify("Ed25519", key, signature, content)) {
287
+ return true;
288
+ }
289
+ }
290
+ }
291
+ return false;
292
+ }
293
+ ```
294
+
295
+ 呼び出し側では、JSON パース前の raw body(例: Next.js の Route Handler では `await request.text()`、Express では `express.raw()` や `express.json({ verify })` で保持した生のボディ)を `payload` に渡してください。
@@ -0,0 +1,124 @@
1
+ <!-- source: docs/src/app/get-started/add-model-starter/page.mdx -->
2
+
3
+ # モデルを追加する
4
+
5
+ ## はじめに
6
+
7
+ このチュートリアルでは、 Orizm のスターターキットに新たなモデル Job(採用情報)を追加し、CMSで管理しつつ、公開サイトで表示するまでの流れを解説します。
8
+
9
+ スターターキットにはすでに固定ページ・お知らせ・ブログなどのモデルが含まれていますが、新たにJobモデルを追加することで、Orizmのテーブル機能を理解し、独自のデータ構造を組み込む方法を学びます。
10
+
11
+ ## モデルの定義
12
+
13
+ はじめに必要なカラムを設計します。ここではJobは以下のカラムを持つモデルとして定義します。
14
+
15
+ | カラム名 | 型 | 説明 |
16
+ | ------------- | -------- | ---------------- |
17
+ | `title` | `string` | 求人のタイトル |
18
+ | `description` | `string` | 求人の詳細情報 |
19
+ | `order` | `number` | 表示順を制御する |
20
+
21
+ ## モデルの作成
22
+
23
+ スターターキットのコードを編集してモデルを追加します。次のコードをコピーして `packages/orizm/orizm.config.ts` の `tables` プロパティに追加して保存します。
24
+
25
+ ```ts copy
26
+ // 採用情報テーブル
27
+ job: {
28
+ columns: {
29
+ // 職種
30
+ title: {
31
+ type: "string",
32
+ required: true,
33
+ },
34
+ // 業務内容
35
+ description: {
36
+ type: "string",
37
+ required: true,
38
+ },
39
+ // 掲載順
40
+ order: {
41
+ type: "number",
42
+ required: true,
43
+ },
44
+ },
45
+ }
46
+ ```
47
+
48
+ このスキーマを適用するために、次のコマンドを実行してデータベースを更新します。
49
+
50
+ ```sh
51
+ pnpm run orizm:push
52
+ ```
53
+
54
+ うまくいけば、Orizm console にテーブルが追加されていることが確認できます。
55
+
56
+ ![Job テーブル](./job-table.png)
57
+
58
+ また、テーブルを消したいときは、先ほど追加したTypeScriptのスキーマを削除し、再度 `orizm:push` を実行してください。本番プロジェクトでこのような破壊的変更を望まない場合、削除保護機能を使うことができます。
59
+
60
+ ## CMS での管理
61
+
62
+ CMSでこの新しいモデルを管理するページを追加していきます。
63
+
64
+ 以下に、大まかな変更箇所を示します。
65
+
66
+ ### packages/model にvalibotスキーマを追加する
67
+
68
+ スターターキットでは Valibot を使って型システムの補強やバリデーションを行っています。
69
+ Orizm のコード生成コマンドでは Valibotに依存しない型定義しか生成していないため、このレイヤーで型の補強しています。
70
+
71
+ ### packages/apps/cms に CRUDページを追加する
72
+
73
+ スターターキットにすでに存在するモデルを参考にして、新しいモデルのCRUDページを作成していきます。
74
+
75
+ #### Server Action の追加
76
+
77
+ スターターキットでは `src/**/actions.ts` というファイルに Server Action を定義しています。
78
+ ここでは、 Orizm CMS SDK を使ってリモートのOrizmプロジェクトと通信するコードが存在します。
79
+
80
+ #### コンポーネントの追加
81
+
82
+ スターターキットでは `src/features` というディレクトリに、モデル固有のコンポーネントを配置しています。
83
+ 例えば、作成フォーム、編集フォームといったコンポーネントがここに配置されます。
84
+ この階層のコンポーネントは、 CMS SDK を使ってデータを読み込んだり、前のステップで定義した Server Action を呼び出してデータを更新します。
85
+
86
+ #### ページの追加
87
+
88
+ スターターキットは App Router を使っています。 `src/app` ディレクトリにファイルを配置することで、ページのRoutingを定義できます。
89
+
90
+ ## 公開サイト(Consumer)に表示
91
+
92
+ スターターキットの公開サイト(Consumer) は `apps/consumer` ディレクトリにある Next.js アプリケーションです。
93
+
94
+ シンプルな例として、Jobモデルを一覧表示するには、以下のような `page.tsx` ファイルを作成し、appディレクトリに配置します。
95
+
96
+ ```tsx
97
+ import { serverSideCmsClient } from "@/lib/orizm-client";
98
+
99
+ export default async function Page() {
100
+ const res = await serverSideCmsClient.tables.job.list({
101
+ limit: 10,
102
+ order: { order: "asc" },
103
+ });
104
+ const jobs = res.contents;
105
+
106
+ return (
107
+ <div>
108
+ {jobs.map((job) => (
109
+ <div key={job.id}>
110
+ <h2>{job.title}</h2>
111
+ <p>{job.description}</p>
112
+ </div>
113
+ ))}
114
+ </div>
115
+ );
116
+ }
117
+ ```
118
+
119
+ スターターキットでは、CMSと同様に `src/features` ディレクトリにモデル固有のコンポーネントや通信ロジックをまとめて配置することで、コードの再利用性を高めています。
120
+
121
+ # まとめ
122
+
123
+ ここまでで、独自のモデルを定義して追加する際の大まかな流れを解説しました。
124
+ さらにカスタマイズする場合、Orizm のテーブル機能のリファレンスも参考にしてください。