@jini-ai/admin 0.3.10 → 0.4.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 (399) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +71 -37
  3. package/dist/agent-plugins/adapters/http.d.ts +7 -0
  4. package/dist/agent-plugins/adapters/http.js +15 -0
  5. package/dist/agent-plugins/adapters/memory.d.ts +8 -0
  6. package/dist/agent-plugins/adapters/memory.js +25 -0
  7. package/dist/agent-plugins/agent-plugins.module.d.ts +51 -0
  8. package/dist/agent-plugins/agent-plugins.module.js +6 -0
  9. package/dist/agent-plugins/conformance/agent-plugins-api.conformance.d.ts +12 -0
  10. package/dist/agent-plugins/conformance/agent-plugins-api.conformance.js +47 -0
  11. package/dist/agent-plugins/controllers/agent-plugin-files.controller.d.ts +20 -0
  12. package/dist/agent-plugins/controllers/agent-plugin-files.controller.js +43 -0
  13. package/dist/agent-plugins/controllers/agent-plugins.controller.d.ts +25 -0
  14. package/dist/agent-plugins/controllers/agent-plugins.controller.js +91 -0
  15. package/dist/agent-plugins/index.d.ts +9 -0
  16. package/dist/agent-plugins/index.js +9 -0
  17. package/dist/agent-plugins/messages.en.d.ts +23 -0
  18. package/dist/agent-plugins/messages.en.js +14 -0
  19. package/dist/agent-plugins/models.d.ts +57 -0
  20. package/dist/agent-plugins/models.js +2 -0
  21. package/dist/agent-plugins/package-file-tree.d.ts +111 -0
  22. package/dist/agent-plugins/package-file-tree.js +188 -0
  23. package/dist/agent-plugins/ports.d.ts +18 -0
  24. package/dist/agent-plugins/ports.js +3 -0
  25. package/dist/agent-plugins/react/components/AgentPluginFileContent.d.ts +5 -0
  26. package/dist/agent-plugins/react/components/AgentPluginFileContent.js +9 -0
  27. package/dist/agent-plugins/react/components/AgentPluginFileTree.d.ts +9 -0
  28. package/dist/agent-plugins/react/components/AgentPluginFileTree.js +7 -0
  29. package/dist/agent-plugins/react/components/AgentPluginInspector.d.ts +3 -0
  30. package/dist/agent-plugins/react/components/AgentPluginInspector.js +11 -0
  31. package/dist/agent-plugins/react/components/AgentPluginListPanel.d.ts +6 -0
  32. package/dist/agent-plugins/react/components/AgentPluginListPanel.js +10 -0
  33. package/dist/agent-plugins/react/components/AgentPluginRow.d.ts +5 -0
  34. package/dist/agent-plugins/react/components/AgentPluginRow.js +8 -0
  35. package/dist/agent-plugins/react/hooks/AgentPluginInspector.hooks.d.ts +90 -0
  36. package/dist/agent-plugins/react/hooks/AgentPluginInspector.hooks.js +74 -0
  37. package/dist/agent-plugins/react/hooks/AgentPluginPanel.hooks.d.ts +67 -0
  38. package/dist/agent-plugins/react/hooks/AgentPluginPanel.hooks.js +50 -0
  39. package/dist/agent-plugins/react/hooks/AgentPluginRow.hooks.d.ts +55 -0
  40. package/dist/agent-plugins/react/hooks/AgentPluginRow.hooks.js +6 -0
  41. package/dist/agent-plugins/react/hooks/AgentPluginsPage.hooks.d.ts +64 -0
  42. package/dist/agent-plugins/react/hooks/AgentPluginsPage.hooks.js +39 -0
  43. package/dist/agent-plugins/react/hooks/AgentPluginsPorts.hooks.d.ts +7 -0
  44. package/dist/agent-plugins/react/hooks/AgentPluginsPorts.hooks.js +10 -0
  45. package/dist/agent-plugins/react/hooks/MarketplaceTab.hooks.d.ts +6 -0
  46. package/dist/agent-plugins/react/hooks/MarketplaceTab.hooks.js +3 -0
  47. package/dist/agent-plugins/react/index.d.ts +245 -0
  48. package/dist/agent-plugins/react/index.js +13 -0
  49. package/dist/agent-plugins/react/pages/AgentPluginsPage.d.ts +4 -0
  50. package/dist/agent-plugins/react/pages/AgentPluginsPage.js +12 -0
  51. package/dist/agent-plugins/react/tabs/DownloadedTab.d.ts +4 -0
  52. package/dist/agent-plugins/react/tabs/DownloadedTab.js +5 -0
  53. package/dist/agent-plugins/react/tabs/InstalledTab.d.ts +4 -0
  54. package/dist/agent-plugins/react/tabs/InstalledTab.js +5 -0
  55. package/dist/agent-plugins/react/tabs/MarketplaceTab.d.ts +4 -0
  56. package/dist/agent-plugins/react/tabs/MarketplaceTab.js +10 -0
  57. package/dist/agent-plugins/rules.d.ts +33 -0
  58. package/dist/agent-plugins/rules.js +51 -0
  59. package/dist/browser/index.d.ts +1 -0
  60. package/dist/browser/index.js +1 -0
  61. package/dist/browser/navigation.d.ts +19 -4
  62. package/dist/browser/navigation.js +8 -8
  63. package/dist/browser/shell-navigation.d.ts +12 -0
  64. package/dist/browser/shell-navigation.js +16 -0
  65. package/dist/contracts/credential-management.d.ts +8 -0
  66. package/dist/contracts/credential-management.js +3 -0
  67. package/dist/contracts/media-picker.d.ts +17 -0
  68. package/dist/contracts/media-picker.js +5 -0
  69. package/dist/contracts/playground-render-target.d.ts +18 -0
  70. package/dist/contracts/playground-render-target.js +3 -0
  71. package/dist/core/entities/rules.d.ts +138 -0
  72. package/dist/core/entities/rules.js +344 -0
  73. package/dist/core/gated/types.d.ts +8 -4
  74. package/dist/core/index.d.ts +4 -0
  75. package/dist/core/index.js +1 -0
  76. package/dist/core/manifest/rules.d.ts +24 -6
  77. package/dist/core/manifest/rules.js +12 -11
  78. package/dist/core/module/controller-store.d.ts +22 -0
  79. package/dist/core/module/controller-store.js +32 -0
  80. package/dist/core/module/create-admin.d.ts +41 -0
  81. package/dist/core/module/create-admin.js +187 -0
  82. package/dist/core/module/define-admin-module.d.ts +4 -0
  83. package/dist/core/module/define-admin-module.js +5 -0
  84. package/dist/core/module/index.d.ts +7 -0
  85. package/dist/core/module/index.js +4 -0
  86. package/dist/core/module/token.d.ts +19 -0
  87. package/dist/core/module/token.js +4 -0
  88. package/dist/core/module/types.d.ts +79 -0
  89. package/dist/core/module/types.js +2 -0
  90. package/dist/core/permissions/rules.d.ts +4 -1
  91. package/dist/core/permissions/rules.js +1 -1
  92. package/dist/core/ports/analytics.d.ts +1 -1
  93. package/dist/core/ports/auth.d.ts +2 -2
  94. package/dist/core/ports/comments.d.ts +9 -6
  95. package/dist/core/ports/database.d.ts +13 -10
  96. package/dist/core/ports/entities.d.ts +302 -0
  97. package/dist/core/ports/entities.js +47 -0
  98. package/dist/core/ports/forms.d.ts +19 -7
  99. package/dist/core/ports/identity.d.ts +42 -17
  100. package/dist/core/ports/index.d.ts +2 -0
  101. package/dist/core/ports/integrations.d.ts +9 -4
  102. package/dist/core/ports/media.d.ts +16 -7
  103. package/dist/core/ports/members.d.ts +7 -3
  104. package/dist/core/ports/menus.d.ts +43 -0
  105. package/dist/core/ports/menus.js +43 -0
  106. package/dist/core/ports/plugins.d.ts +3 -2
  107. package/dist/core/ports/recovery.d.ts +10 -6
  108. package/dist/core/ports/redirects.d.ts +17 -7
  109. package/dist/core/ports/seo.d.ts +12 -6
  110. package/dist/core/ports/shell.d.ts +41 -0
  111. package/dist/core/ports/shell.js +2 -0
  112. package/dist/core/ports/workspace.d.ts +3 -3
  113. package/dist/core/routing/rules.d.ts +17 -4
  114. package/dist/core/routing/rules.js +4 -4
  115. package/dist/core/transport/errors.d.ts +13 -4
  116. package/dist/core/transport/errors.js +4 -4
  117. package/dist/core/transport/http.d.ts +26 -16
  118. package/dist/core/transport/http.js +59 -21
  119. package/dist/core/transport/types.d.ts +26 -14
  120. package/dist/core/transport/types.js +9 -7
  121. package/dist/media/adapters/http.d.ts +27 -0
  122. package/dist/media/adapters/http.js +44 -0
  123. package/dist/media/adapters/memory.d.ts +11 -0
  124. package/dist/media/adapters/memory.js +139 -0
  125. package/dist/media/conformance/media-api.conformance.d.ts +7 -0
  126. package/dist/media/conformance/media-api.conformance.js +69 -0
  127. package/dist/media/controllers/edit-media.controller.d.ts +24 -0
  128. package/dist/media/controllers/edit-media.controller.js +69 -0
  129. package/dist/media/controllers/library.controller.d.ts +47 -0
  130. package/dist/media/controllers/library.controller.js +173 -0
  131. package/dist/media/controllers/providers.controller.d.ts +30 -0
  132. package/dist/media/controllers/providers.controller.js +76 -0
  133. package/dist/media/html-attributes.d.ts +82 -0
  134. package/dist/media/html-attributes.js +204 -0
  135. package/dist/media/index.d.ts +12 -0
  136. package/dist/media/index.js +9 -0
  137. package/dist/media/media.module.d.ts +83 -0
  138. package/dist/media/media.module.js +43 -0
  139. package/dist/media/messages.en.d.ts +24 -0
  140. package/dist/media/messages.en.js +24 -0
  141. package/dist/media/models.d.ts +72 -0
  142. package/dist/media/models.js +2 -0
  143. package/dist/media/ports.d.ts +75 -0
  144. package/dist/media/ports.js +7 -0
  145. package/dist/media/react/components/EditMediaPanel.d.ts +3 -0
  146. package/dist/media/react/components/EditMediaPanel.js +10 -0
  147. package/dist/media/react/components/MediaCard.d.ts +5 -0
  148. package/dist/media/react/components/MediaCard.js +17 -0
  149. package/dist/media/react/components/MediaDialog.d.ts +3 -0
  150. package/dist/media/react/components/MediaDialog.js +8 -0
  151. package/dist/media/react/components/MediaGrid.d.ts +4 -0
  152. package/dist/media/react/components/MediaGrid.js +8 -0
  153. package/dist/media/react/components/MediaIcons.d.ts +14 -0
  154. package/dist/media/react/components/MediaIcons.js +39 -0
  155. package/dist/media/react/components/MediaLightbox.d.ts +5 -0
  156. package/dist/media/react/components/MediaLightbox.js +12 -0
  157. package/dist/media/react/components/MediaPicker.d.ts +3 -0
  158. package/dist/media/react/components/MediaPicker.js +10 -0
  159. package/dist/media/react/components/MediaPurgeDialog.d.ts +4 -0
  160. package/dist/media/react/components/MediaPurgeDialog.js +9 -0
  161. package/dist/media/react/components/UploadButton.d.ts +3 -0
  162. package/dist/media/react/components/UploadButton.js +8 -0
  163. package/dist/media/react/hooks/EditMediaPanel.hooks.d.ts +84 -0
  164. package/dist/media/react/hooks/EditMediaPanel.hooks.js +105 -0
  165. package/dist/media/react/hooks/LibraryTab.hooks.d.ts +103 -0
  166. package/dist/media/react/hooks/LibraryTab.hooks.js +164 -0
  167. package/dist/media/react/hooks/MediaCard.hooks.d.ts +79 -0
  168. package/dist/media/react/hooks/MediaCard.hooks.js +63 -0
  169. package/dist/media/react/hooks/MediaDialog.hooks.d.ts +10 -0
  170. package/dist/media/react/hooks/MediaDialog.hooks.js +20 -0
  171. package/dist/media/react/hooks/MediaGrid.hooks.d.ts +28 -0
  172. package/dist/media/react/hooks/MediaGrid.hooks.js +6 -0
  173. package/dist/media/react/hooks/MediaLightbox.hooks.d.ts +27 -0
  174. package/dist/media/react/hooks/MediaLightbox.hooks.js +64 -0
  175. package/dist/media/react/hooks/MediaPage.hooks.d.ts +68 -0
  176. package/dist/media/react/hooks/MediaPage.hooks.js +68 -0
  177. package/dist/media/react/hooks/MediaPicker.hooks.d.ts +26 -0
  178. package/dist/media/react/hooks/MediaPicker.hooks.js +25 -0
  179. package/dist/media/react/hooks/MediaPorts.hooks.d.ts +9 -0
  180. package/dist/media/react/hooks/MediaPorts.hooks.js +10 -0
  181. package/dist/media/react/hooks/MediaPurgeDialog.hooks.d.ts +22 -0
  182. package/dist/media/react/hooks/MediaPurgeDialog.hooks.js +6 -0
  183. package/dist/media/react/hooks/ProvidersTab.hooks.d.ts +55 -0
  184. package/dist/media/react/hooks/ProvidersTab.hooks.js +124 -0
  185. package/dist/media/react/hooks/UploadButton.hooks.d.ts +48 -0
  186. package/dist/media/react/hooks/UploadButton.hooks.js +118 -0
  187. package/dist/media/react/index.d.ts +373 -0
  188. package/dist/media/react/index.js +73 -0
  189. package/dist/media/react/pages/MediaPage.d.ts +4 -0
  190. package/dist/media/react/pages/MediaPage.js +9 -0
  191. package/dist/media/react/tabs/LibraryTab.d.ts +4 -0
  192. package/dist/media/react/tabs/LibraryTab.js +14 -0
  193. package/dist/media/react/tabs/ProvidersTab.d.ts +4 -0
  194. package/dist/media/react/tabs/ProvidersTab.js +10 -0
  195. package/dist/media/rules.d.ts +80 -0
  196. package/dist/media/rules.js +127 -0
  197. package/dist/media/styles.d.ts +4 -0
  198. package/dist/media/styles.js +5 -0
  199. package/dist/playground/adapters/http.d.ts +8 -0
  200. package/dist/playground/adapters/http.js +4 -0
  201. package/dist/playground/adapters/memory.d.ts +10 -0
  202. package/dist/playground/adapters/memory.js +30 -0
  203. package/dist/playground/conformance/playground-api.conformance.d.ts +6 -0
  204. package/dist/playground/conformance/playground-api.conformance.js +37 -0
  205. package/dist/playground/controllers/playground.controller.d.ts +16 -0
  206. package/dist/playground/controllers/playground.controller.js +21 -0
  207. package/dist/playground/index.d.ts +7 -0
  208. package/dist/playground/index.js +5 -0
  209. package/dist/playground/messages.en.d.ts +9 -0
  210. package/dist/playground/messages.en.js +2 -0
  211. package/dist/playground/models.d.ts +4 -0
  212. package/dist/playground/models.js +2 -0
  213. package/dist/playground/playground.module.d.ts +31 -0
  214. package/dist/playground/playground.module.js +5 -0
  215. package/dist/playground/ports.d.ts +5 -0
  216. package/dist/playground/ports.js +2 -0
  217. package/dist/playground/react/components/Canvas.d.ts +3 -0
  218. package/dist/playground/react/components/Canvas.js +9 -0
  219. package/dist/playground/react/hooks/Canvas.hooks.d.ts +7 -0
  220. package/dist/playground/react/hooks/Canvas.hooks.js +18 -0
  221. package/dist/playground/react/hooks/PlaygroundPage.hooks.d.ts +8 -0
  222. package/dist/playground/react/hooks/PlaygroundPage.hooks.js +2 -0
  223. package/dist/playground/react/hooks/PlaygroundPorts.hooks.d.ts +4 -0
  224. package/dist/playground/react/hooks/PlaygroundPorts.hooks.js +6 -0
  225. package/dist/playground/react/index.d.ts +136 -0
  226. package/dist/playground/react/index.js +10 -0
  227. package/dist/playground/react/pages/PlaygroundPage.d.ts +4 -0
  228. package/dist/playground/react/pages/PlaygroundPage.js +11 -0
  229. package/dist/playground/react/tabs/CanvasTab.d.ts +4 -0
  230. package/dist/playground/react/tabs/CanvasTab.js +5 -0
  231. package/dist/playground/rules.d.ts +4 -0
  232. package/dist/playground/rules.js +2 -0
  233. package/dist/react/OverlayHost.d.ts +3 -0
  234. package/dist/react/OverlayHost.hooks.d.ts +9 -0
  235. package/dist/react/OverlayHost.hooks.js +9 -0
  236. package/dist/react/OverlayHost.js +7 -0
  237. package/dist/react/bind-react.d.ts +46 -0
  238. package/dist/react/bind-react.js +28 -0
  239. package/dist/react/components/ConfirmButton/ConfirmButton.hooks.d.ts +7 -1
  240. package/dist/react/components/ConfirmButton/ConfirmButton.hooks.js +2 -2
  241. package/dist/react/components/ConfirmButton/ConfirmButton.js +1 -1
  242. package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.d.ts +17 -3
  243. package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.js +3 -3
  244. package/dist/react/components/ConfirmDialog/ConfirmDialog.js +5 -5
  245. package/dist/react/components/InteractiveHtmlEditor/InteractiveHtmlEditor.d.ts +6 -2
  246. package/dist/react/components/InteractiveHtmlEditor/InteractiveHtmlEditor.js +7 -8
  247. package/dist/react/components/RowMenu/RowMenu.d.ts +5 -1
  248. package/dist/react/components/RowMenu/RowMenu.hooks.d.ts +8 -2
  249. package/dist/react/components/RowMenu/RowMenu.hooks.js +4 -4
  250. package/dist/react/components/RowMenu/RowMenu.js +6 -6
  251. package/dist/react/components/Sidebar.d.ts +1 -1
  252. package/dist/react/components/Sidebar.js +103 -7
  253. package/dist/react/entities/EntityCell.d.ts +10 -0
  254. package/dist/react/entities/EntityCell.js +18 -0
  255. package/dist/react/entities/EntityDetail.d.ts +3 -0
  256. package/dist/react/entities/EntityDetail.js +21 -0
  257. package/dist/react/entities/EntityEdit.d.ts +13 -0
  258. package/dist/react/entities/EntityEdit.js +45 -0
  259. package/dist/react/entities/EntityField.d.ts +20 -0
  260. package/dist/react/entities/EntityField.js +31 -0
  261. package/dist/react/entities/EntityIndex.d.ts +3 -0
  262. package/dist/react/entities/EntityIndex.js +10 -0
  263. package/dist/react/entities/EntityList.d.ts +7 -0
  264. package/dist/react/entities/EntityList.js +52 -0
  265. package/dist/react/entities/contribution.d.ts +26 -0
  266. package/dist/react/entities/contribution.js +78 -0
  267. package/dist/react/entities/index.d.ts +10 -0
  268. package/dist/react/entities/index.js +7 -0
  269. package/dist/react/entities/rules.d.ts +179 -0
  270. package/dist/react/entities/rules.js +224 -0
  271. package/dist/react/entities/types.d.ts +45 -0
  272. package/dist/react/entities/types.js +5 -0
  273. package/dist/react/entities/use-entity-edit.d.ts +35 -0
  274. package/dist/react/entities/use-entity-edit.js +98 -0
  275. package/dist/react/entities/use-entity-read.d.ts +22 -0
  276. package/dist/react/entities/use-entity-read.js +27 -0
  277. package/dist/react/hooks/use-nav-sections.d.ts +12 -3
  278. package/dist/react/hooks/use-nav-sections.js +14 -14
  279. package/dist/react/hooks/use-sidebar-rail.d.ts +7 -1
  280. package/dist/react/hooks/use-sidebar-rail.js +11 -11
  281. package/dist/react/index.d.ts +3 -1
  282. package/dist/react/index.js +5 -2
  283. package/dist/react/kit/Kit.hooks.d.ts +13 -0
  284. package/dist/react/kit/Kit.hooks.js +10 -0
  285. package/dist/react/kit/Native.hooks.d.ts +38 -0
  286. package/dist/react/kit/Native.hooks.js +65 -0
  287. package/dist/react/kit/index.d.ts +12 -0
  288. package/dist/react/kit/index.js +21 -0
  289. package/dist/react/kit/native.d.ts +3 -0
  290. package/dist/react/kit/native.js +21 -0
  291. package/dist/react/kit/types.d.ts +40 -0
  292. package/dist/react/kit/types.js +2 -0
  293. package/dist/react/overlay.d.ts +36 -0
  294. package/dist/react/overlay.js +35 -0
  295. package/dist/react/overlays.d.ts +38 -0
  296. package/dist/react/overlays.js +46 -0
  297. package/dist/react/shell/AdminShell.d.ts +9 -0
  298. package/dist/react/shell/AdminShell.hooks.d.ts +15 -0
  299. package/dist/react/shell/AdminShell.hooks.js +27 -0
  300. package/dist/react/shell/AdminShell.js +46 -0
  301. package/dist/react/shell/index.d.ts +7 -0
  302. package/dist/react/shell/index.js +5 -0
  303. package/dist/react/shell/model.d.ts +25 -0
  304. package/dist/react/shell/model.js +29 -0
  305. package/dist/react/shell/theme-ports.d.ts +28 -0
  306. package/dist/react/shell/theme-ports.js +2 -0
  307. package/dist/react/shell/types.d.ts +99 -0
  308. package/dist/react/shell/types.js +2 -0
  309. package/dist/react/shell/use-admin-shell-session.d.ts +13 -0
  310. package/dist/react/shell/use-admin-shell-session.js +81 -0
  311. package/dist/react/shell/use-admin-theme.d.ts +16 -0
  312. package/dist/react/shell/use-admin-theme.js +57 -0
  313. package/dist/react/types.d.ts +6 -4
  314. package/dist/react/types.js +2 -2
  315. package/dist/react/use-controller.d.ts +16 -0
  316. package/dist/react/use-controller.js +18 -0
  317. package/dist/security/adapters/http.d.ts +16 -0
  318. package/dist/security/adapters/http.js +94 -0
  319. package/dist/security/adapters/memory.d.ts +15 -0
  320. package/dist/security/adapters/memory.js +60 -0
  321. package/dist/security/conformance/security-api.conformance.d.ts +10 -0
  322. package/dist/security/conformance/security-api.conformance.js +48 -0
  323. package/dist/security/controllers/access-tokens.controller.d.ts +44 -0
  324. package/dist/security/controllers/access-tokens.controller.js +112 -0
  325. package/dist/security/controllers/other-credentials.controller.d.ts +30 -0
  326. package/dist/security/controllers/other-credentials.controller.js +74 -0
  327. package/dist/security/controllers/root-key.controller.d.ts +35 -0
  328. package/dist/security/controllers/root-key.controller.js +90 -0
  329. package/dist/security/index.d.ts +9 -0
  330. package/dist/security/index.js +9 -0
  331. package/dist/security/messages.en.d.ts +12 -0
  332. package/dist/security/messages.en.js +2 -0
  333. package/dist/security/models.d.ts +112 -0
  334. package/dist/security/models.js +2 -0
  335. package/dist/security/ports.d.ts +58 -0
  336. package/dist/security/ports.js +5 -0
  337. package/dist/security/react/components/CredentialEditor.d.ts +3 -0
  338. package/dist/security/react/components/CredentialEditor.js +8 -0
  339. package/dist/security/react/hooks/AccessTokensTab.hooks.d.ts +94 -0
  340. package/dist/security/react/hooks/AccessTokensTab.hooks.js +36 -0
  341. package/dist/security/react/hooks/CredentialEditor.hooks.d.ts +49 -0
  342. package/dist/security/react/hooks/CredentialEditor.hooks.js +14 -0
  343. package/dist/security/react/hooks/RootKeyTab.hooks.d.ts +29 -0
  344. package/dist/security/react/hooks/RootKeyTab.hooks.js +19 -0
  345. package/dist/security/react/hooks/SecurityPage.hooks.d.ts +17 -0
  346. package/dist/security/react/hooks/SecurityPage.hooks.js +12 -0
  347. package/dist/security/react/hooks/SecurityPorts.hooks.d.ts +9 -0
  348. package/dist/security/react/hooks/SecurityPorts.hooks.js +6 -0
  349. package/dist/security/react/index.d.ts +215 -0
  350. package/dist/security/react/index.js +10 -0
  351. package/dist/security/react/pages/SecurityPage.d.ts +4 -0
  352. package/dist/security/react/pages/SecurityPage.js +10 -0
  353. package/dist/security/react/tabs/AccessTokensTab.d.ts +4 -0
  354. package/dist/security/react/tabs/AccessTokensTab.js +10 -0
  355. package/dist/security/react/tabs/RootKeyTab.d.ts +4 -0
  356. package/dist/security/react/tabs/RootKeyTab.js +9 -0
  357. package/dist/security/rules.d.ts +57 -0
  358. package/dist/security/rules.js +63 -0
  359. package/dist/security/security.module.d.ts +45 -0
  360. package/dist/security/security.module.js +5 -0
  361. package/dist/source-control/adapters/http.d.ts +6 -0
  362. package/dist/source-control/adapters/http.js +13 -0
  363. package/dist/source-control/adapters/memory.d.ts +9 -0
  364. package/dist/source-control/adapters/memory.js +35 -0
  365. package/dist/source-control/conformance/source-control-api.conformance.d.ts +10 -0
  366. package/dist/source-control/conformance/source-control-api.conformance.js +48 -0
  367. package/dist/source-control/controllers/source-control.controller.d.ts +26 -0
  368. package/dist/source-control/controllers/source-control.controller.js +70 -0
  369. package/dist/source-control/index.d.ts +8 -0
  370. package/dist/source-control/index.js +6 -0
  371. package/dist/source-control/messages.en.d.ts +11 -0
  372. package/dist/source-control/messages.en.js +2 -0
  373. package/dist/source-control/models.d.ts +70 -0
  374. package/dist/source-control/models.js +2 -0
  375. package/dist/source-control/ports.d.ts +23 -0
  376. package/dist/source-control/ports.js +3 -0
  377. package/dist/source-control/react/components/SourceControlCredentialFields.d.ts +5 -0
  378. package/dist/source-control/react/components/SourceControlCredentialFields.js +8 -0
  379. package/dist/source-control/react/components/SourceControlProviderRow.d.ts +5 -0
  380. package/dist/source-control/react/components/SourceControlProviderRow.js +7 -0
  381. package/dist/source-control/react/hooks/ProvidersTab.hooks.d.ts +45 -0
  382. package/dist/source-control/react/hooks/ProvidersTab.hooks.js +20 -0
  383. package/dist/source-control/react/hooks/SourceControlCredentialFields.hooks.d.ts +43 -0
  384. package/dist/source-control/react/hooks/SourceControlCredentialFields.hooks.js +9 -0
  385. package/dist/source-control/react/hooks/SourceControlPage.hooks.d.ts +17 -0
  386. package/dist/source-control/react/hooks/SourceControlPage.hooks.js +5 -0
  387. package/dist/source-control/react/hooks/SourceControlPorts.hooks.d.ts +9 -0
  388. package/dist/source-control/react/hooks/SourceControlPorts.hooks.js +6 -0
  389. package/dist/source-control/react/index.d.ts +156 -0
  390. package/dist/source-control/react/index.js +10 -0
  391. package/dist/source-control/react/pages/SourceControlPage.d.ts +4 -0
  392. package/dist/source-control/react/pages/SourceControlPage.js +11 -0
  393. package/dist/source-control/react/tabs/ProvidersTab.d.ts +4 -0
  394. package/dist/source-control/react/tabs/ProvidersTab.js +10 -0
  395. package/dist/source-control/rules.d.ts +32 -0
  396. package/dist/source-control/rules.js +35 -0
  397. package/dist/source-control/source-control.module.d.ts +36 -0
  398. package/dist/source-control/source-control.module.js +6 -0
  399. package/package.json +207 -4
@@ -13,23 +13,25 @@
13
13
  * factory over it — makes both work:
14
14
  *
15
15
  * ```ts
16
- * const transport = createHttpTransport({ baseUrl: '/api/admin/v1' });
16
+ * const transport = createHttpTransport({ baseUrl: '/api/admin/v1', fetch: ({ url }, init) => fetch(url, init) });
17
17
  *
18
- * const client = createAdminClient(transport, {
19
- * identity: createIdentityRoutes, // shipped by @jini-ai/admin
20
- * media: createMediaRoutes, // shipped by @jini-ai/admin
18
+ * const client = createAdminClient({ transport, groups: {
19
+ * identity: createHostIdentityRoutes, // host implementation of AdminIdentityPort
20
+ * media: createHostMediaRoutes, // host implementation of AdminMediaPort
21
21
  * posts: createHostPostRoutes, // the host's own, same signature
22
22
  * widgets: createHostWidgetRoutes, // the host's own
23
- * });
23
+ * } });
24
24
  *
25
- * await client.identity.listUsers(); // Jini's
26
- * await client.posts.list(); // the host's
25
+ * await client.identity.listUsers({}); // host adapter over Jini's port contract
26
+ * await client.posts.list({}); // the host's own port
27
27
  * ```
28
28
  *
29
29
  * Both halves share one auth policy, one error class, one place to add retries or tracing. A host
30
30
  * adding a route is a factory plus one line in the map — it never edits a Jini file, and it never
31
31
  * grows a second `fetch` wrapper with its own subtly different error handling, which is exactly
32
32
  * how `api.ts` reached 1,548 lines.
33
+ * This package ships port contracts and the assembler, not backend route factories;
34
+ * the host supplies each factory and may share it with other hosts without changing this seam.
33
35
  *
34
36
  * ## Why `AdminTransport` is an interface and not just a function
35
37
  *
@@ -51,25 +53,35 @@ export interface AdminTransport {
51
53
  * @param path Route-group-relative path, always starting with `/` (`/users`, `/media/abc`).
52
54
  * The base is the transport's concern — a route group that embeds a base is not portable to
53
55
  * a host that mounts the admin API somewhere else.
54
- * @param init Standard `RequestInit`. A transport that is not HTTP-backed may ignore fields it
55
- * cannot honour, but must respect `method` and `body`.
56
+ * @param init Standard `RequestInit` plus an optional success observer. A transport that is not
57
+ * HTTP-backed may ignore fields it cannot honour, but must respect `method` and `body`.
56
58
  * @throws {AdminApiError} on any non-success response.
57
59
  */
58
- request<T>(path: string, init?: RequestInit): Promise<T>;
60
+ request<T>(requiredArgs: {
61
+ readonly path: string;
62
+ }, optionalArgs?: RequestInit & {
63
+ /** Called only on success with the response metadata, after parsing and before resolving.
64
+ * Reading ETag here lets route adapters send If-Match without duplicating transport logic. */
65
+ readonly onOk?: (args: {
66
+ readonly response: Response;
67
+ }) => void;
68
+ }): Promise<T>;
59
69
  }
60
70
  /**
61
71
  * A route group: turns a transport into a typed set of operations.
62
72
  *
63
- * Every port implementation in this package is one of these, and a host's own route groups use
64
- * the identical signature — that symmetry is what lets Jini-shipped and host-owned groups sit in
73
+ * Host implementations of this package's ports and a host's own route groups use
74
+ * the identical signature — that symmetry is what lets shared and host-owned groups sit in
65
75
  * the same client with no adapter between them.
66
76
  */
67
- export type AdminRouteGroupFactory<TPort> = (transport: AdminTransport) => TPort;
77
+ export type AdminRouteGroupFactory<TPort> = (requiredArgs: {
78
+ readonly transport: AdminTransport;
79
+ }) => TPort;
68
80
  /**
69
81
  * The assembled client: one object carrying every wired route group.
70
82
  *
71
83
  * `TGroups` is inferred from the factory map handed to `createAdminClient`, so a host's own
72
- * groups are as type-safe as the shipped ones with no declaration merging or module augmentation.
84
+ * groups are as type-safe as shared ones with no declaration merging or module augmentation.
73
85
  */
74
86
  export type AdminClient<TGroups extends Record<string, AdminRouteGroupFactory<unknown>>> = {
75
87
  readonly [K in keyof TGroups]: ReturnType<TGroups[K]>;
@@ -13,23 +13,25 @@
13
13
  * factory over it — makes both work:
14
14
  *
15
15
  * ```ts
16
- * const transport = createHttpTransport({ baseUrl: '/api/admin/v1' });
16
+ * const transport = createHttpTransport({ baseUrl: '/api/admin/v1', fetch: ({ url }, init) => fetch(url, init) });
17
17
  *
18
- * const client = createAdminClient(transport, {
19
- * identity: createIdentityRoutes, // shipped by @jini-ai/admin
20
- * media: createMediaRoutes, // shipped by @jini-ai/admin
18
+ * const client = createAdminClient({ transport, groups: {
19
+ * identity: createHostIdentityRoutes, // host implementation of AdminIdentityPort
20
+ * media: createHostMediaRoutes, // host implementation of AdminMediaPort
21
21
  * posts: createHostPostRoutes, // the host's own, same signature
22
22
  * widgets: createHostWidgetRoutes, // the host's own
23
- * });
23
+ * } });
24
24
  *
25
- * await client.identity.listUsers(); // Jini's
26
- * await client.posts.list(); // the host's
25
+ * await client.identity.listUsers({}); // host adapter over Jini's port contract
26
+ * await client.posts.list({}); // the host's own port
27
27
  * ```
28
28
  *
29
29
  * Both halves share one auth policy, one error class, one place to add retries or tracing. A host
30
30
  * adding a route is a factory plus one line in the map — it never edits a Jini file, and it never
31
31
  * grows a second `fetch` wrapper with its own subtly different error handling, which is exactly
32
32
  * how `api.ts` reached 1,548 lines.
33
+ * This package ships port contracts and the assembler, not backend route factories;
34
+ * the host supplies each factory and may share it with other hosts without changing this seam.
33
35
  *
34
36
  * ## Why `AdminTransport` is an interface and not just a function
35
37
  *
@@ -0,0 +1,27 @@
1
+ import type { MediaApiPort } from '../ports.js';
2
+ import type { MediaRequestOptions } from '../models.js';
3
+ /** Authentication, workspace addressing, transport retries and error decoding belong to the host.
4
+ * Retryable errors remain intact so the library can recover automatically after an outage.
5
+ * The adapter never reaches for global fetch, tokens or a hardcoded workspace. */
6
+ export interface MediaTransportPort {
7
+ request<T>(required: {
8
+ path: string;
9
+ method: 'GET' | 'POST' | 'PATCH' | 'DELETE';
10
+ body?: unknown;
11
+ }, optional?: MediaRequestOptions): Promise<T>;
12
+ url(required: {
13
+ path: string;
14
+ }, optional?: Record<string, never>): string;
15
+ }
16
+ export declare function createHttpMediaApi({ transport, basePath }: {
17
+ transport: MediaTransportPort;
18
+ basePath: string;
19
+ }, { replacePath, restorePath, }?: {
20
+ replacePath?: (required: {
21
+ id: string;
22
+ }, optional?: Record<string, never>) => string;
23
+ restorePath?: (required: {
24
+ id: string;
25
+ }, optional?: Record<string, never>) => string;
26
+ }): MediaApiPort;
27
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1,44 @@
1
+ import { queryMedia } from '../rules.js';
2
+ export function createHttpMediaApi({ transport, basePath }, { replacePath, restorePath, } = {}) {
3
+ const base = basePath.replace(/\/$/, '');
4
+ const path = (id) => `${base}/${encodeURIComponent(id)}`;
5
+ async function asset(method, target, body, options) {
6
+ options.signal?.throwIfAborted();
7
+ const response = await transport.request({ path: target, method, ...(body === undefined ? {} : { body }) }, options);
8
+ return response.media;
9
+ }
10
+ return {
11
+ replaceSupported: !!replacePath,
12
+ restoreSupported: !!restorePath,
13
+ async list(query, options = {}) {
14
+ options.signal?.throwIfAborted();
15
+ const response = await transport.request({ path: base, method: 'GET' }, options);
16
+ return queryMedia({ media: response.media, query });
17
+ },
18
+ upload(input, { signal, ...metadata } = {}) {
19
+ return asset('POST', base, { ...input, ...metadata }, signal ? { signal } : {});
20
+ },
21
+ update({ id, patch }, options = {}) {
22
+ return asset('PATCH', path(id), patch, options);
23
+ },
24
+ ...(replacePath ? { replace({ id, upload }, options = {}) {
25
+ return asset('POST', replacePath({ id }), upload, options);
26
+ } } : {}),
27
+ trash({ id }, options = {}) {
28
+ return asset('POST', `${path(id)}/trash`, undefined, options);
29
+ },
30
+ ...(restorePath ? { restore({ id }, options = {}) {
31
+ return asset('POST', restorePath({ id }), undefined, options);
32
+ } } : {}),
33
+ delete({ id }, options = {}) {
34
+ options.signal?.throwIfAborted();
35
+ return transport.request({ path: path(id), method: 'DELETE' }, options);
36
+ },
37
+ originalUrl({ id, version }, _optional = {}) {
38
+ // Replacement preserves the id; the refreshed version must identify its new bytes.
39
+ const revision = version === undefined ? '' : `?v=${encodeURIComponent(version)}`;
40
+ return transport.url({ path: `${path(id)}/original${revision}` });
41
+ },
42
+ };
43
+ }
44
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1,11 @@
1
+ import type { MediaApiPort, MediaProvidersPort } from '../ports.js';
2
+ import type { MediaAsset, MediaProvider } from '../models.js';
3
+ export declare function createMemoryMediaApi({ assets }: {
4
+ assets?: readonly MediaAsset[];
5
+ }, { now }?: {
6
+ now?: () => string;
7
+ }): MediaApiPort;
8
+ export declare function createMemoryMediaProviders({ providers }: {
9
+ providers?: readonly MediaProvider[];
10
+ }, _optional?: Record<string, never>): MediaProvidersPort;
11
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1,139 @@
1
+ import { queryMedia } from '../rules.js';
2
+ export function createMemoryMediaApi({ assets = [] }, { now = () => new Date().toISOString() } = {}) {
3
+ const items = new Map(assets.map((item) => [item.id, Object.freeze({ ...item })]));
4
+ let sequence = 0;
5
+ function check(options) {
6
+ options.signal?.throwIfAborted();
7
+ }
8
+ function get(id) {
9
+ const item = items.get(id);
10
+ if (!item)
11
+ throw new Error(`Media not found: ${id}`);
12
+ return item;
13
+ }
14
+ function put(item) {
15
+ const frozen = Object.freeze(item);
16
+ items.set(item.id, frozen);
17
+ return frozen;
18
+ }
19
+ function content(input) {
20
+ // The REAL server ignores the declared string and stores sniffContentType(bytes) instead.
21
+ // This fake has no bytes to sniff — its input is an opaque base64 string a test made up —
22
+ // so it echoes what the caller declared. Tests needing disagreement must seed assets directly.
23
+ return { byteSize: Math.max(0, Math.floor(input.dataBase64.length * 3 / 4) - (input.dataBase64.match(/=+$/)?.[0].length ?? 0)), contentType: input.contentType, sha256: `memory-content-${++sequence}` };
24
+ }
25
+ return {
26
+ replaceSupported: true,
27
+ restoreSupported: true,
28
+ async list(query, options = {}) {
29
+ check(options);
30
+ return Object.freeze(queryMedia({ media: [...items.values()], query }));
31
+ },
32
+ async upload(input, options = {}) {
33
+ check(options);
34
+ let id;
35
+ do {
36
+ id = `memory-${++sequence}`;
37
+ } while (items.has(id));
38
+ const timestamp = now();
39
+ return put({
40
+ id,
41
+ title: options.title ?? input.filename,
42
+ alt: options.alt ?? '',
43
+ caption: options.caption ?? '',
44
+ credit: options.credit ?? '',
45
+ slug: options.slug ?? id,
46
+ width: options.width ?? null,
47
+ height: options.height ?? null,
48
+ cssClass: options.cssClass ?? null,
49
+ htmlAttributes: options.htmlAttributes ?? null,
50
+ status: 'active',
51
+ publicUrl: null,
52
+ createdAt: timestamp,
53
+ updatedAt: timestamp,
54
+ version: 1,
55
+ ...content(input),
56
+ });
57
+ },
58
+ async update({ id, patch }, options = {}) {
59
+ check(options);
60
+ const previous = get(id);
61
+ const metadata = Object.fromEntries(Object.entries(patch).filter(([key, value]) => ['title', 'slug', 'alt', 'caption', 'credit', 'width', 'height', 'cssClass', 'htmlAttributes'].includes(key) && value !== undefined));
62
+ return put({ ...previous, ...metadata, version: previous.version + 1, updatedAt: now() });
63
+ },
64
+ async replace({ id, upload }, options = {}) {
65
+ check(options);
66
+ const previous = get(id);
67
+ if (previous.status !== 'active')
68
+ throw new Error('Cannot replace trashed media');
69
+ return put({
70
+ ...previous,
71
+ ...content(upload),
72
+ version: previous.version + 1,
73
+ updatedAt: now(),
74
+ });
75
+ },
76
+ async trash({ id }, options = {}) {
77
+ check(options);
78
+ const previous = get(id);
79
+ return put({
80
+ ...previous,
81
+ status: 'trashed',
82
+ publicUrl: null,
83
+ version: previous.version + 1,
84
+ updatedAt: now(),
85
+ });
86
+ },
87
+ async restore({ id }, options = {}) {
88
+ check(options);
89
+ const previous = get(id);
90
+ return put({ ...previous, status: 'active', version: previous.version + 1, updatedAt: now() });
91
+ },
92
+ async delete({ id }, options = {}) {
93
+ check(options);
94
+ if (get(id).status !== 'trashed')
95
+ throw new Error('Trash media before permanent deletion');
96
+ items.delete(id);
97
+ return { purged: true };
98
+ },
99
+ // Distinct memory:// scheme so a URL assertion fails if the consumer calls a real client.
100
+ originalUrl: ({ id }) => `memory://media-original/${encodeURIComponent(id)}`,
101
+ };
102
+ }
103
+ export function createMemoryMediaProviders({ providers = [] }, _optional = {}) {
104
+ const items = new Map(providers.map((item) => [item.id, Object.freeze({ ...item })]));
105
+ function write(id, configured) {
106
+ const previous = items.get(id);
107
+ if (!previous)
108
+ throw new Error('Unknown provider');
109
+ const next = Object.freeze({ ...previous, configured });
110
+ items.set(id, next);
111
+ return next;
112
+ }
113
+ return {
114
+ async list(_required, options = {}) {
115
+ options.signal?.throwIfAborted();
116
+ return Object.freeze([...items.values()]);
117
+ },
118
+ async saveSettings({ id, baseUrl, model }, options = {}) {
119
+ options.signal?.throwIfAborted();
120
+ const previous = items.get(id);
121
+ if (!previous)
122
+ throw new Error('Unknown provider');
123
+ const next = Object.freeze({ ...previous, baseUrl, model });
124
+ items.set(id, next);
125
+ return next;
126
+ },
127
+ async saveCredential({ id, credential }, options = {}) {
128
+ options.signal?.throwIfAborted();
129
+ if (!credential.trim())
130
+ throw new Error('Credential is required');
131
+ return write(id, true);
132
+ },
133
+ async removeCredential({ id }, options = {}) {
134
+ options.signal?.throwIfAborted();
135
+ return write(id, false);
136
+ },
137
+ };
138
+ }
139
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1,7 @@
1
+ import type { MediaApiPort } from '../ports.js';
2
+ /** Destructive checklist: run only against an isolated backend with no production data.
3
+ * Returns named checks and throws at the first failed contract. No test-framework dependency. */
4
+ export declare function runMediaApiConformance({ api }: {
5
+ api: MediaApiPort;
6
+ }, _optional?: Record<string, never>): Promise<readonly string[]>;
7
+ //# sourceMappingURL=media-api.conformance.d.ts.map
@@ -0,0 +1,69 @@
1
+ import { canReplaceMedia } from '../rules.js';
2
+ /** Destructive checklist: run only against an isolated backend with no production data.
3
+ * Returns named checks and throws at the first failed contract. No test-framework dependency. */
4
+ export async function runMediaApiConformance({ api }, _optional = {}) {
5
+ const checks = [];
6
+ function assert(condition, name) {
7
+ if (!condition)
8
+ throw new Error(`Media API conformance: ${name}`);
9
+ checks.push(name);
10
+ }
11
+ async function rejects(run, name) {
12
+ let rejected = false;
13
+ try {
14
+ await run();
15
+ }
16
+ catch {
17
+ rejected = true;
18
+ }
19
+ assert(rejected, name);
20
+ }
21
+ const input = {
22
+ filename: 'conformance.png',
23
+ contentType: 'image/png',
24
+ dataBase64: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+aT1sAAAAASUVORK5CYII=',
25
+ };
26
+ const created = await api.upload(input, { alt: 'initial alt' });
27
+ assert(created.id.length > 0 && created.status === 'active', 'upload creates an active asset');
28
+ try {
29
+ const before = await api.list({});
30
+ assert(before.some((item) => item.id === created.id), 'list contains upload');
31
+ const updated = await api.update({ id: created.id, patch: { title: 'renamed' } });
32
+ assert(updated.title === 'renamed' && updated.alt === 'initial alt', 'partial metadata patch preserves untouched fields');
33
+ assert(created.title === 'conformance.png', 'prior snapshots do not mutate');
34
+ const images = await api.list({ filter: 'images' });
35
+ assert(images.every((item) => item.contentType?.startsWith('image/')), 'image filter');
36
+ assert(typeof api.originalUrl({ id: created.id }) === 'string', 'original URL is synchronous');
37
+ await rejects(() => api.delete({ id: created.id }), 'active asset cannot be purged');
38
+ if (canReplaceMedia({ api })) {
39
+ const replaced = await api.replace({
40
+ id: created.id,
41
+ upload: { ...input, filename: 'replacement.png' },
42
+ });
43
+ assert(replaced.id === created.id &&
44
+ replaced.alt === updated.alt &&
45
+ replaced.title === updated.title, 'replace retains identity and metadata');
46
+ }
47
+ else {
48
+ assert(api.replace === undefined || api.replaceSupported === false, 'replacement is optional and unavailable');
49
+ }
50
+ const abort = new AbortController();
51
+ abort.abort();
52
+ await rejects(() => api.list({}, { signal: abort.signal }), 'aborted list rejects');
53
+ await rejects(() => api.update({ id: created.id, patch: { title: 'must not save' } }, { signal: abort.signal }), 'aborted write rejects');
54
+ assert((await api.list({})).find((item) => item.id === created.id)?.title === 'renamed', 'aborted write has no effects');
55
+ const trashed = await api.trash({ id: created.id });
56
+ assert(trashed.status === 'trashed', 'trash is a distinct state');
57
+ assert((await api.delete({ id: created.id })).purged, 'trashed asset can be purged');
58
+ assert(!(await api.list({})).some((item) => item.id === created.id), 'purge removes asset');
59
+ await rejects(() => api.update({ id: created.id, patch: {} }), 'missing asset rejects');
60
+ return Object.freeze(checks);
61
+ }
62
+ finally {
63
+ if ((await api.list({})).some((item) => item.id === created.id)) {
64
+ await api.trash({ id: created.id });
65
+ await api.delete({ id: created.id });
66
+ }
67
+ }
68
+ }
69
+ //# sourceMappingURL=media-api.conformance.js.map
@@ -0,0 +1,24 @@
1
+ import type { MediaApiPort } from '../ports.js';
2
+ import type { MediaAsset, MediaMetadataPatch, UploadInput } from '../models.js';
3
+ export declare function createEditMediaController({ api, item }: {
4
+ api: MediaApiPort;
5
+ item: MediaAsset;
6
+ }, _optional?: Record<string, never>): {
7
+ getSnapshot: () => Readonly<{
8
+ draft: MediaMetadataPatch;
9
+ saving: boolean;
10
+ error: string | null;
11
+ }>;
12
+ subscribe: ({ listener }: {
13
+ listener: () => void;
14
+ }) => () => void;
15
+ dispose: () => void;
16
+ setDraft({ patch }: {
17
+ patch: MediaMetadataPatch;
18
+ }, _optional?: Record<string, never>): void;
19
+ save(_required?: Record<string, never>, _optional?: Record<string, never>): Promise<boolean>;
20
+ replace({ upload }: {
21
+ upload: UploadInput;
22
+ }, _optional?: Record<string, never>): Promise<boolean>;
23
+ };
24
+ //# sourceMappingURL=edit-media.controller.d.ts.map
@@ -0,0 +1,69 @@
1
+ import { createControllerStore } from '../../core/module/controller-store.js';
2
+ import { diffMediaMetadata, canReplaceMedia } from '../rules.js';
3
+ export function createEditMediaController({ api, item }, _optional = {}) {
4
+ // Frozen at mount, exactly like draft's initializer — stays the value draft was seeded
5
+ // from even as the live list advances underneath it. Never diff against a drifting item.
6
+ let baseline = Object.freeze({ ...item });
7
+ const store = createControllerStore({
8
+ initial: {
9
+ draft: metadataDraft({ item }),
10
+ saving: false,
11
+ error: null,
12
+ },
13
+ });
14
+ async function perform(run) {
15
+ if (store.signal.aborted || store.getSnapshot().saving)
16
+ return false;
17
+ store.set({ patch: { saving: true, error: null } });
18
+ try {
19
+ const saved = await run();
20
+ if (store.signal.aborted)
21
+ return false;
22
+ baseline = saved;
23
+ store.set({
24
+ patch: {
25
+ draft: metadataDraft({ item: baseline }),
26
+ },
27
+ });
28
+ return true;
29
+ }
30
+ catch (error) {
31
+ store.set({
32
+ patch: { error: error instanceof Error ? error.message : 'Failed to save media metadata' },
33
+ });
34
+ return false;
35
+ }
36
+ finally {
37
+ store.set({ patch: { saving: false } });
38
+ }
39
+ }
40
+ return {
41
+ getSnapshot: store.getSnapshot,
42
+ subscribe: store.subscribe,
43
+ dispose: store.dispose,
44
+ setDraft({ patch }, _optional = {}) {
45
+ if (!store.getSnapshot().saving)
46
+ store.set({ patch: { draft: { ...store.getSnapshot().draft, ...patch } } });
47
+ },
48
+ async save(_required = {}, _optional = {}) {
49
+ const patch = diffMediaMetadata({ item: baseline, draft: store.getSnapshot().draft });
50
+ if (Object.keys(patch).length === 0)
51
+ return true;
52
+ return perform(() => api.update({ id: item.id, patch }, { signal: store.signal }));
53
+ },
54
+ async replace({ upload }, _optional = {}) {
55
+ if (!canReplaceMedia({ api })) {
56
+ store.set({ patch: { error: 'File replacement is unavailable' } });
57
+ return false;
58
+ }
59
+ return perform(() => api.replace({ id: item.id, upload }, { signal: store.signal }));
60
+ },
61
+ };
62
+ }
63
+ /** Do not invent CMS fields for hosts which omit them: undefined is an untouched field. */
64
+ function metadataDraft({ item }) {
65
+ return Object.fromEntries(Object.entries({ title: item.title, slug: item.slug, alt: item.alt,
66
+ caption: item.caption, credit: item.credit, width: item.width, height: item.height,
67
+ cssClass: item.cssClass, htmlAttributes: item.htmlAttributes }).filter(([, value]) => value !== undefined));
68
+ }
69
+ //# sourceMappingURL=edit-media.controller.js.map
@@ -0,0 +1,47 @@
1
+ import { countMediaTabs } from '../rules.js';
2
+ import type { MediaApiPort } from '../ports.js';
3
+ import type { MediaAsset, MediaQuery, UploadInput } from '../models.js';
4
+ export interface LibraryState {
5
+ readonly items: readonly MediaAsset[] | null;
6
+ readonly query: MediaQuery;
7
+ readonly loading: boolean;
8
+ readonly busy: boolean;
9
+ readonly pendingIds: readonly string[];
10
+ readonly error: string | null;
11
+ readonly pendingPurge: MediaAsset | null;
12
+ readonly hasUntyped: boolean;
13
+ readonly counts: ReturnType<typeof countMediaTabs> | null;
14
+ }
15
+ export declare function createLibraryController({ api }: {
16
+ api: MediaApiPort;
17
+ }, { query }?: {
18
+ query?: MediaQuery;
19
+ }): {
20
+ getSnapshot: () => Readonly<LibraryState>;
21
+ subscribe: ({ listener }: {
22
+ listener: () => void;
23
+ }) => () => void;
24
+ load: (_required?: Record<string, never>, _optional?: Record<string, never>) => Promise<void>;
25
+ setQuery({ query }: {
26
+ query: MediaQuery;
27
+ }, _optional?: Record<string, never>): Promise<void>;
28
+ upload({ input, alt }: {
29
+ input: UploadInput;
30
+ alt?: string;
31
+ }, _optional?: Record<string, never>): Promise<boolean>;
32
+ trash({ id }: {
33
+ id: string;
34
+ }, _optional?: Record<string, never>): Promise<boolean>;
35
+ restore({ id }: {
36
+ id: string;
37
+ }, _optional?: Record<string, never>): Promise<boolean>;
38
+ requestPurge({ item }: {
39
+ item: MediaAsset;
40
+ }, _optional?: Record<string, never>): void;
41
+ cancelPurge(_required?: Record<string, never>, _optional?: Record<string, never>): void;
42
+ confirmPurge({ confirmed }: {
43
+ confirmed: boolean;
44
+ }, _optional?: Record<string, never>): Promise<boolean>;
45
+ dispose(_required?: Record<string, never>, _optional?: Record<string, never>): void;
46
+ };
47
+ //# sourceMappingURL=library.controller.d.ts.map