@aphexcms/cms-core 9.4.0 → 9.5.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 (403) hide show
  1. package/dist/admin/block-previews.svelte.d.ts +46 -0
  2. package/dist/admin/block-previews.svelte.d.ts.map +1 -0
  3. package/dist/admin/block-previews.svelte.js +26 -0
  4. package/dist/admin/field-components.svelte.d.ts +16 -0
  5. package/dist/admin/field-components.svelte.d.ts.map +1 -0
  6. package/dist/admin/field-components.svelte.js +18 -0
  7. package/dist/admin/nav.svelte.d.ts +34 -0
  8. package/dist/admin/nav.svelte.d.ts.map +1 -0
  9. package/dist/admin/nav.svelte.js +78 -0
  10. package/dist/admin/slots.svelte.d.ts +50 -0
  11. package/dist/admin/slots.svelte.d.ts.map +1 -0
  12. package/dist/admin/slots.svelte.js +67 -0
  13. package/dist/admin/types.d.ts +7 -0
  14. package/dist/admin/types.d.ts.map +1 -0
  15. package/dist/admin/types.js +1 -0
  16. package/dist/api/schemas/api-keys.d.ts +4 -37
  17. package/dist/api/schemas/api-keys.d.ts.map +1 -1
  18. package/dist/api/schemas/api-keys.js +5 -2
  19. package/dist/api/schemas/assets.d.ts +4 -0
  20. package/dist/api/schemas/assets.d.ts.map +1 -1
  21. package/dist/api/schemas/assets.js +3 -0
  22. package/dist/api/schemas/plugin-settings.d.ts +6 -0
  23. package/dist/api/schemas/plugin-settings.d.ts.map +1 -0
  24. package/dist/api/schemas/plugin-settings.js +8 -0
  25. package/dist/api/schemas/roles.d.ts +7 -56
  26. package/dist/api/schemas/roles.d.ts.map +1 -1
  27. package/dist/api/schemas/roles.js +11 -6
  28. package/dist/api/schemas/user.d.ts +2 -1
  29. package/dist/api/schemas/user.d.ts.map +1 -1
  30. package/dist/api/schemas/user.js +7 -2
  31. package/dist/app-augment.d.ts +11 -0
  32. package/dist/app-augment.d.ts.map +1 -1
  33. package/dist/app.d.ts +2 -0
  34. package/dist/auth/provider.d.ts +3 -0
  35. package/dist/auth/provider.d.ts.map +1 -1
  36. package/dist/cli/generate-types.d.ts +1 -4
  37. package/dist/cli/generate-types.d.ts.map +1 -1
  38. package/dist/cli/generate-types.js +99 -65
  39. package/dist/cli/generate-types.js.map +1 -1
  40. package/dist/cli/index.js +3 -3
  41. package/dist/cli/index.js.map +1 -1
  42. package/dist/client/index.d.ts +6 -0
  43. package/dist/client/index.d.ts.map +1 -1
  44. package/dist/client/index.js +9 -0
  45. package/dist/components/AdminApp.svelte +259 -113
  46. package/dist/components/AdminApp.svelte.d.ts +18 -2
  47. package/dist/components/AdminApp.svelte.d.ts.map +1 -1
  48. package/dist/components/admin/AdminSlot.svelte +18 -0
  49. package/dist/components/admin/AdminSlot.svelte.d.ts +12 -0
  50. package/dist/components/admin/AdminSlot.svelte.d.ts.map +1 -0
  51. package/dist/components/admin/DocumentEditor.svelte +646 -385
  52. package/dist/components/admin/DocumentEditor.svelte.d.ts +13 -0
  53. package/dist/components/admin/DocumentEditor.svelte.d.ts.map +1 -1
  54. package/dist/components/admin/MediaBrowser.svelte +13 -3
  55. package/dist/components/admin/MediaBrowser.svelte.d.ts.map +1 -1
  56. package/dist/components/admin/PluginSettingsPanel.svelte +231 -0
  57. package/dist/components/admin/PluginSettingsPanel.svelte.d.ts +8 -0
  58. package/dist/components/admin/PluginSettingsPanel.svelte.d.ts.map +1 -0
  59. package/dist/components/admin/SchemaField.svelte +76 -95
  60. package/dist/components/admin/SchemaField.svelte.d.ts +7 -0
  61. package/dist/components/admin/SchemaField.svelte.d.ts.map +1 -1
  62. package/dist/components/admin/fields/ArrayField.svelte +24 -2
  63. package/dist/components/admin/fields/ArrayField.svelte.d.ts.map +1 -1
  64. package/dist/components/admin/fields/FieldInput.svelte +109 -0
  65. package/dist/components/admin/fields/FieldInput.svelte.d.ts +17 -0
  66. package/dist/components/admin/fields/FieldInput.svelte.d.ts.map +1 -0
  67. package/dist/components/admin/fields/richtext/PortableTextImageView.svelte +5 -12
  68. package/dist/components/admin/fields/richtext/PortableTextImageView.svelte.d.ts +2 -9
  69. package/dist/components/admin/fields/richtext/PortableTextImageView.svelte.d.ts.map +1 -1
  70. package/dist/components/admin/fields/richtext/PortableTextObjectView.svelte +18 -17
  71. package/dist/components/admin/fields/richtext/PortableTextObjectView.svelte.d.ts +2 -9
  72. package/dist/components/admin/fields/richtext/PortableTextObjectView.svelte.d.ts.map +1 -1
  73. package/dist/components/admin/fields/richtext/RichtextField.svelte +55 -2
  74. package/dist/components/admin/fields/richtext/RichtextField.svelte.d.ts.map +1 -1
  75. package/dist/components/admin/fields/richtext/portable-text-object-node.d.ts +7 -0
  76. package/dist/components/admin/fields/richtext/portable-text-object-node.d.ts.map +1 -1
  77. package/dist/components/admin/fields/richtext/portable-text-object-node.js +4 -2
  78. package/dist/components/admin/fields/richtext/svelte-node-view.d.ts +16 -1
  79. package/dist/components/admin/fields/richtext/svelte-node-view.d.ts.map +1 -1
  80. package/dist/components/admin/fields/richtext/svelte-node-view.js +20 -1
  81. package/dist/components/layout/OrganizationSwitcher.svelte +31 -10
  82. package/dist/components/layout/OrganizationSwitcher.svelte.d.ts.map +1 -1
  83. package/dist/components/layout/Sidebar.svelte +49 -11
  84. package/dist/components/layout/Sidebar.svelte.d.ts +5 -1
  85. package/dist/components/layout/Sidebar.svelte.d.ts.map +1 -1
  86. package/dist/components/layout/sidebar/AppSidebar.svelte +66 -3
  87. package/dist/components/layout/sidebar/AppSidebar.svelte.d.ts +5 -0
  88. package/dist/components/layout/sidebar/AppSidebar.svelte.d.ts.map +1 -1
  89. package/dist/components/layout/sidebar/NavMain.svelte +3 -2
  90. package/dist/components/layout/sidebar/NavMain.svelte.d.ts +4 -3
  91. package/dist/components/layout/sidebar/NavMain.svelte.d.ts.map +1 -1
  92. package/dist/components/layout/sidebar/NavUser.svelte +5 -1
  93. package/dist/config.d.ts.map +1 -1
  94. package/dist/config.js +11 -0
  95. package/dist/db/interfaces/asset.d.ts +1 -0
  96. package/dist/db/interfaces/asset.d.ts.map +1 -1
  97. package/dist/db/interfaces/index.d.ts +3 -1
  98. package/dist/db/interfaces/index.d.ts.map +1 -1
  99. package/dist/db/interfaces/plugin-settings.d.ts +23 -0
  100. package/dist/db/interfaces/plugin-settings.d.ts.map +1 -0
  101. package/dist/db/interfaces/plugin-settings.js +13 -0
  102. package/dist/db/interfaces/role.d.ts +14 -5
  103. package/dist/db/interfaces/role.d.ts.map +1 -1
  104. package/dist/engine.d.ts +28 -0
  105. package/dist/engine.d.ts.map +1 -1
  106. package/dist/engine.js +44 -0
  107. package/dist/hooks.d.ts +6 -0
  108. package/dist/hooks.d.ts.map +1 -1
  109. package/dist/hooks.js +59 -2
  110. package/dist/index.d.ts +2 -0
  111. package/dist/index.d.ts.map +1 -1
  112. package/dist/index.js +5 -0
  113. package/dist/lib/admin/block-previews.svelte.d.ts +46 -0
  114. package/dist/lib/admin/block-previews.svelte.d.ts.map +1 -0
  115. package/dist/lib/admin/block-previews.svelte.js +27 -0
  116. package/dist/lib/admin/block-previews.svelte.js.map +1 -0
  117. package/dist/lib/admin/field-components.svelte.d.ts +16 -0
  118. package/dist/lib/admin/field-components.svelte.d.ts.map +1 -0
  119. package/dist/lib/admin/field-components.svelte.js +19 -0
  120. package/dist/lib/admin/field-components.svelte.js.map +1 -0
  121. package/dist/lib/admin/nav.svelte.d.ts +34 -0
  122. package/dist/lib/admin/nav.svelte.d.ts.map +1 -0
  123. package/dist/lib/admin/nav.svelte.js +79 -0
  124. package/dist/lib/admin/nav.svelte.js.map +1 -0
  125. package/dist/lib/admin/slots.svelte.d.ts +50 -0
  126. package/dist/lib/admin/slots.svelte.d.ts.map +1 -0
  127. package/dist/lib/admin/slots.svelte.js +68 -0
  128. package/dist/lib/admin/slots.svelte.js.map +1 -0
  129. package/dist/lib/admin/types.d.ts +7 -0
  130. package/dist/lib/admin/types.d.ts.map +1 -0
  131. package/dist/lib/admin/types.js +2 -0
  132. package/dist/lib/admin/types.js.map +1 -0
  133. package/dist/lib/api/schemas/api-keys.d.ts +4 -37
  134. package/dist/lib/api/schemas/api-keys.d.ts.map +1 -1
  135. package/dist/lib/api/schemas/api-keys.js +5 -2
  136. package/dist/lib/api/schemas/api-keys.js.map +1 -1
  137. package/dist/lib/api/schemas/assets.d.ts +4 -0
  138. package/dist/lib/api/schemas/assets.d.ts.map +1 -1
  139. package/dist/lib/api/schemas/assets.js +3 -0
  140. package/dist/lib/api/schemas/assets.js.map +1 -1
  141. package/dist/lib/api/schemas/plugin-settings.d.ts +6 -0
  142. package/dist/lib/api/schemas/plugin-settings.d.ts.map +1 -0
  143. package/dist/lib/api/schemas/plugin-settings.js +9 -0
  144. package/dist/lib/api/schemas/plugin-settings.js.map +1 -0
  145. package/dist/lib/api/schemas/roles.d.ts +7 -56
  146. package/dist/lib/api/schemas/roles.d.ts.map +1 -1
  147. package/dist/lib/api/schemas/roles.js +11 -6
  148. package/dist/lib/api/schemas/roles.js.map +1 -1
  149. package/dist/lib/api/schemas/user.d.ts +2 -1
  150. package/dist/lib/api/schemas/user.d.ts.map +1 -1
  151. package/dist/lib/api/schemas/user.js +7 -2
  152. package/dist/lib/api/schemas/user.js.map +1 -1
  153. package/dist/lib/app-augment.d.ts +11 -0
  154. package/dist/lib/app-augment.d.ts.map +1 -1
  155. package/dist/lib/auth/provider.d.ts +3 -0
  156. package/dist/lib/auth/provider.d.ts.map +1 -1
  157. package/dist/lib/client/index.d.ts +6 -0
  158. package/dist/lib/client/index.d.ts.map +1 -1
  159. package/dist/lib/client/index.js +9 -0
  160. package/dist/lib/client/index.js.map +1 -1
  161. package/dist/lib/components/admin/fields/richtext/portable-text-object-node.d.ts +7 -0
  162. package/dist/lib/components/admin/fields/richtext/portable-text-object-node.d.ts.map +1 -1
  163. package/dist/lib/components/admin/fields/richtext/portable-text-object-node.js +4 -2
  164. package/dist/lib/components/admin/fields/richtext/portable-text-object-node.js.map +1 -1
  165. package/dist/lib/components/admin/fields/richtext/svelte-node-view.d.ts +16 -1
  166. package/dist/lib/components/admin/fields/richtext/svelte-node-view.d.ts.map +1 -1
  167. package/dist/lib/components/admin/fields/richtext/svelte-node-view.js +20 -1
  168. package/dist/lib/components/admin/fields/richtext/svelte-node-view.js.map +1 -1
  169. package/dist/lib/config.d.ts.map +1 -1
  170. package/dist/lib/config.js +11 -0
  171. package/dist/lib/config.js.map +1 -1
  172. package/dist/lib/db/interfaces/asset.d.ts +1 -0
  173. package/dist/lib/db/interfaces/asset.d.ts.map +1 -1
  174. package/dist/lib/db/interfaces/index.d.ts +3 -1
  175. package/dist/lib/db/interfaces/index.d.ts.map +1 -1
  176. package/dist/lib/db/interfaces/plugin-settings.d.ts +23 -0
  177. package/dist/lib/db/interfaces/plugin-settings.d.ts.map +1 -0
  178. package/dist/lib/db/interfaces/plugin-settings.js +14 -0
  179. package/dist/lib/db/interfaces/plugin-settings.js.map +1 -0
  180. package/dist/lib/db/interfaces/role.d.ts +14 -5
  181. package/dist/lib/db/interfaces/role.d.ts.map +1 -1
  182. package/dist/lib/engine.d.ts +28 -0
  183. package/dist/lib/engine.d.ts.map +1 -1
  184. package/dist/lib/engine.js +44 -0
  185. package/dist/lib/engine.js.map +1 -1
  186. package/dist/lib/hooks.d.ts +6 -0
  187. package/dist/lib/hooks.d.ts.map +1 -1
  188. package/dist/lib/hooks.js +59 -2
  189. package/dist/lib/hooks.js.map +1 -1
  190. package/dist/lib/index.d.ts +2 -0
  191. package/dist/lib/index.d.ts.map +1 -1
  192. package/dist/lib/index.js +5 -0
  193. package/dist/lib/index.js.map +1 -1
  194. package/dist/lib/local-api/collection-api.d.ts.map +1 -1
  195. package/dist/lib/local-api/collection-api.js +4 -2
  196. package/dist/lib/local-api/collection-api.js.map +1 -1
  197. package/dist/lib/local-api/types.d.ts +8 -0
  198. package/dist/lib/local-api/types.d.ts.map +1 -1
  199. package/dist/lib/mcp/tools.d.ts.map +1 -1
  200. package/dist/lib/mcp/tools.js +68 -0
  201. package/dist/lib/mcp/tools.js.map +1 -1
  202. package/dist/lib/permissions-context.svelte.d.ts +7 -4
  203. package/dist/lib/permissions-context.svelte.d.ts.map +1 -1
  204. package/dist/lib/permissions-context.svelte.js.map +1 -1
  205. package/dist/lib/plugins/index.d.ts +3 -0
  206. package/dist/lib/plugins/index.d.ts.map +1 -0
  207. package/dist/lib/plugins/index.js +3 -0
  208. package/dist/lib/plugins/index.js.map +1 -0
  209. package/dist/lib/plugins/resolver.d.ts +49 -0
  210. package/dist/lib/plugins/resolver.d.ts.map +1 -0
  211. package/dist/lib/plugins/resolver.js +66 -0
  212. package/dist/lib/plugins/resolver.js.map +1 -0
  213. package/dist/lib/plugins/types.d.ts +233 -0
  214. package/dist/lib/plugins/types.d.ts.map +1 -0
  215. package/dist/lib/plugins/types.js +9 -0
  216. package/dist/lib/plugins/types.js.map +1 -0
  217. package/dist/lib/schema-utils/desugar.d.ts +27 -0
  218. package/dist/lib/schema-utils/desugar.d.ts.map +1 -0
  219. package/dist/lib/schema-utils/desugar.js +102 -0
  220. package/dist/lib/schema-utils/desugar.js.map +1 -0
  221. package/dist/lib/schema-utils/index.d.ts +2 -0
  222. package/dist/lib/schema-utils/index.d.ts.map +1 -1
  223. package/dist/lib/schema-utils/index.js +2 -0
  224. package/dist/lib/schema-utils/index.js.map +1 -1
  225. package/dist/lib/schema-utils/settings.d.ts +17 -0
  226. package/dist/lib/schema-utils/settings.d.ts.map +1 -0
  227. package/dist/lib/schema-utils/settings.js +23 -0
  228. package/dist/lib/schema-utils/settings.js.map +1 -0
  229. package/dist/lib/schema-utils/validator.d.ts.map +1 -1
  230. package/dist/lib/schema-utils/validator.js +11 -0
  231. package/dist/lib/schema-utils/validator.js.map +1 -1
  232. package/dist/lib/security/secret-crypto.d.ts +18 -0
  233. package/dist/lib/security/secret-crypto.d.ts.map +1 -0
  234. package/dist/lib/security/secret-crypto.js +71 -0
  235. package/dist/lib/security/secret-crypto.js.map +1 -0
  236. package/dist/lib/server/api/index.d.ts.map +1 -1
  237. package/dist/lib/server/api/index.js +3 -0
  238. package/dist/lib/server/api/index.js.map +1 -1
  239. package/dist/lib/server/api/routes/assets.d.ts.map +1 -1
  240. package/dist/lib/server/api/routes/assets.js +8 -2
  241. package/dist/lib/server/api/routes/assets.js.map +1 -1
  242. package/dist/lib/server/api/routes/organizations.d.ts.map +1 -1
  243. package/dist/lib/server/api/routes/organizations.js +4 -1
  244. package/dist/lib/server/api/routes/organizations.js.map +1 -1
  245. package/dist/lib/server/api/routes/plugin-settings.d.ts +4 -0
  246. package/dist/lib/server/api/routes/plugin-settings.d.ts.map +1 -0
  247. package/dist/lib/server/api/routes/plugin-settings.js +109 -0
  248. package/dist/lib/server/api/routes/plugin-settings.js.map +1 -0
  249. package/dist/lib/server/api/routes/roles.d.ts.map +1 -1
  250. package/dist/lib/server/api/routes/roles.js +37 -0
  251. package/dist/lib/server/api/routes/roles.js.map +1 -1
  252. package/dist/lib/server/api/routes/user.d.ts.map +1 -1
  253. package/dist/lib/server/api/routes/user.js +14 -3
  254. package/dist/lib/server/api/routes/user.js.map +1 -1
  255. package/dist/lib/services/asset-service.d.ts +1 -0
  256. package/dist/lib/services/asset-service.d.ts.map +1 -1
  257. package/dist/lib/services/asset-service.js.map +1 -1
  258. package/dist/lib/services/index.d.ts +2 -0
  259. package/dist/lib/services/index.d.ts.map +1 -1
  260. package/dist/lib/services/index.js +1 -0
  261. package/dist/lib/services/index.js.map +1 -1
  262. package/dist/lib/services/plugin-settings-service.d.ts +76 -0
  263. package/dist/lib/services/plugin-settings-service.d.ts.map +1 -0
  264. package/dist/lib/services/plugin-settings-service.js +236 -0
  265. package/dist/lib/services/plugin-settings-service.js.map +1 -0
  266. package/dist/lib/services/roles-service.d.ts +2 -2
  267. package/dist/lib/services/roles-service.d.ts.map +1 -1
  268. package/dist/lib/services/roles-service.js.map +1 -1
  269. package/dist/lib/theme/css.d.ts +30 -0
  270. package/dist/lib/theme/css.d.ts.map +1 -0
  271. package/dist/lib/theme/css.js +54 -0
  272. package/dist/lib/theme/css.js.map +1 -0
  273. package/dist/lib/theme/derive.d.ts +27 -0
  274. package/dist/lib/theme/derive.d.ts.map +1 -0
  275. package/dist/lib/theme/derive.js +108 -0
  276. package/dist/lib/theme/derive.js.map +1 -0
  277. package/dist/lib/theme/index.d.ts +5 -0
  278. package/dist/lib/theme/index.d.ts.map +1 -0
  279. package/dist/lib/theme/index.js +5 -0
  280. package/dist/lib/theme/index.js.map +1 -0
  281. package/dist/lib/theme/schemes.d.ts +60 -0
  282. package/dist/lib/theme/schemes.d.ts.map +1 -0
  283. package/dist/lib/theme/schemes.js +150 -0
  284. package/dist/lib/theme/schemes.js.map +1 -0
  285. package/dist/lib/theme/tokens.d.ts +57 -0
  286. package/dist/lib/theme/tokens.d.ts.map +1 -0
  287. package/dist/lib/theme/tokens.js +11 -0
  288. package/dist/lib/theme/tokens.js.map +1 -0
  289. package/dist/lib/types/auth.d.ts +10 -10
  290. package/dist/lib/types/auth.d.ts.map +1 -1
  291. package/dist/lib/types/capabilities.d.ts +50 -9
  292. package/dist/lib/types/capabilities.d.ts.map +1 -1
  293. package/dist/lib/types/capabilities.js +147 -5
  294. package/dist/lib/types/capabilities.js.map +1 -1
  295. package/dist/lib/types/config.d.ts +30 -1
  296. package/dist/lib/types/config.d.ts.map +1 -1
  297. package/dist/lib/types/schemas.d.ts +90 -2
  298. package/dist/lib/types/schemas.d.ts.map +1 -1
  299. package/dist/lib/types/schemas.js.map +1 -1
  300. package/dist/lib/types/sidebar.d.ts +3 -1
  301. package/dist/lib/types/sidebar.d.ts.map +1 -1
  302. package/dist/lib/utils/index.d.ts +1 -0
  303. package/dist/lib/utils/index.d.ts.map +1 -1
  304. package/dist/lib/utils/index.js +1 -0
  305. package/dist/lib/utils/index.js.map +1 -1
  306. package/dist/lib/utils/preview.d.ts +16 -5
  307. package/dist/lib/utils/preview.d.ts.map +1 -1
  308. package/dist/lib/utils/preview.js +7 -2
  309. package/dist/lib/utils/preview.js.map +1 -1
  310. package/dist/lib/vite/index.d.ts +7 -0
  311. package/dist/lib/vite/index.d.ts.map +1 -1
  312. package/dist/lib/vite/index.js +37 -6
  313. package/dist/lib/vite/index.js.map +1 -1
  314. package/dist/local-api/collection-api.d.ts.map +1 -1
  315. package/dist/local-api/collection-api.js +4 -2
  316. package/dist/local-api/types.d.ts +8 -0
  317. package/dist/local-api/types.d.ts.map +1 -1
  318. package/dist/mcp/tools.d.ts.map +1 -1
  319. package/dist/mcp/tools.js +68 -0
  320. package/dist/permissions-context.svelte.d.ts +7 -4
  321. package/dist/permissions-context.svelte.d.ts.map +1 -1
  322. package/dist/plugins/index.d.ts +3 -0
  323. package/dist/plugins/index.d.ts.map +1 -0
  324. package/dist/plugins/index.js +2 -0
  325. package/dist/plugins/resolver.d.ts +49 -0
  326. package/dist/plugins/resolver.d.ts.map +1 -0
  327. package/dist/plugins/resolver.js +65 -0
  328. package/dist/plugins/types.d.ts +233 -0
  329. package/dist/plugins/types.d.ts.map +1 -0
  330. package/dist/plugins/types.js +8 -0
  331. package/dist/schema-utils/desugar.d.ts +27 -0
  332. package/dist/schema-utils/desugar.d.ts.map +1 -0
  333. package/dist/schema-utils/desugar.js +101 -0
  334. package/dist/schema-utils/index.d.ts +2 -0
  335. package/dist/schema-utils/index.d.ts.map +1 -1
  336. package/dist/schema-utils/index.js +2 -0
  337. package/dist/schema-utils/settings.d.ts +17 -0
  338. package/dist/schema-utils/settings.d.ts.map +1 -0
  339. package/dist/schema-utils/settings.js +22 -0
  340. package/dist/schema-utils/validator.d.ts.map +1 -1
  341. package/dist/schema-utils/validator.js +11 -0
  342. package/dist/security/secret-crypto.d.ts +18 -0
  343. package/dist/security/secret-crypto.d.ts.map +1 -0
  344. package/dist/security/secret-crypto.js +70 -0
  345. package/dist/server/api/index.d.ts.map +1 -1
  346. package/dist/server/api/index.js +3 -0
  347. package/dist/server/api/routes/assets.d.ts.map +1 -1
  348. package/dist/server/api/routes/assets.js +8 -2
  349. package/dist/server/api/routes/organizations.d.ts.map +1 -1
  350. package/dist/server/api/routes/organizations.js +4 -1
  351. package/dist/server/api/routes/plugin-settings.d.ts +4 -0
  352. package/dist/server/api/routes/plugin-settings.d.ts.map +1 -0
  353. package/dist/server/api/routes/plugin-settings.js +108 -0
  354. package/dist/server/api/routes/roles.d.ts.map +1 -1
  355. package/dist/server/api/routes/roles.js +37 -0
  356. package/dist/server/api/routes/user.d.ts.map +1 -1
  357. package/dist/server/api/routes/user.js +14 -3
  358. package/dist/services/asset-service.d.ts +1 -0
  359. package/dist/services/asset-service.d.ts.map +1 -1
  360. package/dist/services/index.d.ts +2 -0
  361. package/dist/services/index.d.ts.map +1 -1
  362. package/dist/services/index.js +1 -0
  363. package/dist/services/plugin-settings-service.d.ts +76 -0
  364. package/dist/services/plugin-settings-service.d.ts.map +1 -0
  365. package/dist/services/plugin-settings-service.js +235 -0
  366. package/dist/services/roles-service.d.ts +2 -2
  367. package/dist/services/roles-service.d.ts.map +1 -1
  368. package/dist/theme/css.d.ts +30 -0
  369. package/dist/theme/css.d.ts.map +1 -0
  370. package/dist/theme/css.js +53 -0
  371. package/dist/theme/derive.d.ts +27 -0
  372. package/dist/theme/derive.d.ts.map +1 -0
  373. package/dist/theme/derive.js +107 -0
  374. package/dist/theme/index.d.ts +5 -0
  375. package/dist/theme/index.d.ts.map +1 -0
  376. package/dist/theme/index.js +4 -0
  377. package/dist/theme/schemes.d.ts +60 -0
  378. package/dist/theme/schemes.d.ts.map +1 -0
  379. package/dist/theme/schemes.js +149 -0
  380. package/dist/theme/tokens.d.ts +57 -0
  381. package/dist/theme/tokens.d.ts.map +1 -0
  382. package/dist/theme/tokens.js +10 -0
  383. package/dist/types/auth.d.ts +10 -10
  384. package/dist/types/auth.d.ts.map +1 -1
  385. package/dist/types/capabilities.d.ts +50 -9
  386. package/dist/types/capabilities.d.ts.map +1 -1
  387. package/dist/types/capabilities.js +147 -5
  388. package/dist/types/config.d.ts +30 -1
  389. package/dist/types/config.d.ts.map +1 -1
  390. package/dist/types/schemas.d.ts +90 -2
  391. package/dist/types/schemas.d.ts.map +1 -1
  392. package/dist/types/sidebar.d.ts +3 -1
  393. package/dist/types/sidebar.d.ts.map +1 -1
  394. package/dist/utils/index.d.ts +1 -0
  395. package/dist/utils/index.d.ts.map +1 -1
  396. package/dist/utils/index.js +1 -0
  397. package/dist/utils/preview.d.ts +16 -5
  398. package/dist/utils/preview.d.ts.map +1 -1
  399. package/dist/utils/preview.js +7 -2
  400. package/dist/vite/index.d.ts +7 -0
  401. package/dist/vite/index.d.ts.map +1 -1
  402. package/dist/vite/index.js +37 -6
  403. package/package.json +6 -4
package/dist/mcp/tools.js CHANGED
@@ -10,6 +10,7 @@
10
10
  import { z } from 'zod';
11
11
  import { VALID_FIELD_TYPES, RESERVED_FIELDS, validateSchemaReferences } from '../schema-utils/validator.js';
12
12
  import { validateDocumentData } from '../field-validation/utils.js';
13
+ import { validateFile } from '../utils/mime-detect.js';
13
14
  import { fieldWriteShape } from '../../cli/generate-types.js';
14
15
  import { DEFAULT_BLOCK_STYLES, DEFAULT_BLOCK_DECORATORS, DEFAULT_BLOCK_LISTS } from '../components/admin/fields/richtext/block-defaults.js';
15
16
  const ok = (data) => ({
@@ -499,6 +500,73 @@ export function buildContentTools({ aphexCMS, context }) {
499
500
  return fail(`List assets failed: ${err instanceof Error ? err.message : String(err)}`);
500
501
  }
501
502
  }
503
+ },
504
+ {
505
+ name: 'upload_asset',
506
+ description: 'Upload an image or file from base64 data and get back a ready-to-reference value. ' +
507
+ 'The response includes `imageValue` and `fileValue` — drop the matching one straight ' +
508
+ 'into a document field (e.g. a blog post `coverImage`, an author `avatar`, or an inline ' +
509
+ '`image` block) via update_document. File type is verified from the actual bytes, not the ' +
510
+ 'declared name.',
511
+ inputSchema: {
512
+ data: z.string().min(1).describe('Base64-encoded file contents (no data: URI prefix).'),
513
+ filename: z
514
+ .string()
515
+ .min(1)
516
+ .describe('Original filename, e.g. "cover.png". Its extension helps typing.'),
517
+ mimeType: z
518
+ .string()
519
+ .optional()
520
+ .describe('Declared MIME type. Optional — the bytes are sniffed regardless.'),
521
+ alt: z.string().optional().describe('Default alt text, shared across every placement.'),
522
+ title: z.string().optional(),
523
+ description: z.string().optional()
524
+ },
525
+ handler: async (args) => {
526
+ const base64 = asString(args, 'data');
527
+ const filename = asString(args, 'filename');
528
+ if (!base64)
529
+ return fail("'data' (base64 file contents) is required.");
530
+ if (!filename)
531
+ return fail("'filename' is required.");
532
+ let buffer;
533
+ try {
534
+ buffer = Buffer.from(base64, 'base64');
535
+ }
536
+ catch {
537
+ return fail("'data' is not valid base64.");
538
+ }
539
+ if (buffer.length === 0)
540
+ return fail("'data' decoded to zero bytes.");
541
+ const declaredMime = asString(args, 'mimeType') ?? '';
542
+ const validation = validateFile(buffer, filename, declaredMime);
543
+ if (!validation.valid) {
544
+ return fail(`Upload rejected: ${validation.error ?? 'file failed validation.'}`);
545
+ }
546
+ const mimeType = validation.detectedMimeType || declaredMime || 'application/octet-stream';
547
+ try {
548
+ const asset = await assetService.uploadAsset(orgId, {
549
+ buffer,
550
+ originalFilename: filename,
551
+ mimeType,
552
+ size: buffer.length,
553
+ alt: asString(args, 'alt') ?? undefined,
554
+ title: asString(args, 'title') ?? undefined,
555
+ description: asString(args, 'description') ?? undefined,
556
+ createdBy: context.user?.id
557
+ });
558
+ const ref = { _type: 'reference', _ref: asset.id };
559
+ return ok({
560
+ asset,
561
+ // Referenceable field values — use the one matching the target field's type.
562
+ imageValue: { _type: 'image', asset: ref },
563
+ fileValue: { _type: 'file', asset: ref }
564
+ });
565
+ }
566
+ catch (err) {
567
+ return fail(`Upload failed: ${err instanceof Error ? err.message : String(err)}`);
568
+ }
569
+ }
502
570
  }
503
571
  ];
504
572
  }
@@ -8,12 +8,15 @@ export interface PermissionsContext {
8
8
  * such as field-level access lists.
9
9
  */
10
10
  readonly role: string | null;
11
- /** True if the session has the named capability. */
12
- can(cap: Capability): boolean;
11
+ /**
12
+ * True if the session has the named capability. Accepts core `Capability` ids
13
+ * (with autocomplete) or any plugin-declared capability string.
14
+ */
15
+ can(cap: Capability | (string & {})): boolean;
13
16
  /** True if the session has at least one of the capabilities. */
14
- canAny(...caps: Capability[]): boolean;
17
+ canAny(...caps: (Capability | (string & {}))[]): boolean;
15
18
  /** True if the session has every one of the capabilities. */
16
- canAll(...caps: Capability[]): boolean;
19
+ canAll(...caps: (Capability | (string & {}))[]): boolean;
17
20
  }
18
21
  /**
19
22
  * Publish a capability context to descendants.
@@ -1 +1 @@
1
- {"version":3,"file":"permissions-context.svelte.d.ts","sourceRoot":"","sources":["../src/lib/permissions-context.svelte.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIvD,MAAM,WAAW,kBAAkB;IAClC,0CAA0C;IAC1C,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,oDAAoD;IACpD,GAAG,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC;IAC9B,gEAAgE;IAChE,MAAM,CAAC,GAAG,IAAI,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IACvC,6DAA6D;IAC7D,MAAM,CAAC,GAAG,IAAI,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;CACvC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACpC,eAAe,EAAE,MAAM,SAAS,MAAM,EAAE,EACxC,OAAO,GAAE,MAAM,MAAM,GAAG,IAAiB,GACvC,kBAAkB,CAsBpB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,IAAI,kBAAkB,CAKnD"}
1
+ {"version":3,"file":"permissions-context.svelte.d.ts","sourceRoot":"","sources":["../src/lib/permissions-context.svelte.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIvD,MAAM,WAAW,kBAAkB;IAClC,0CAA0C;IAC1C,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;;;OAGG;IACH,GAAG,CAAC,GAAG,EAAE,UAAU,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC;IAC9C,gEAAgE;IAChE,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,UAAU,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC;IACzD,6DAA6D;IAC7D,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,UAAU,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC;CACzD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACpC,eAAe,EAAE,MAAM,SAAS,MAAM,EAAE,EACxC,OAAO,GAAE,MAAM,MAAM,GAAG,IAAiB,GACvC,kBAAkB,CAsBpB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,IAAI,kBAAkB,CAKnD"}
@@ -0,0 +1,3 @@
1
+ export * from './types.js';
2
+ export * from './resolver.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/plugins/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './types.js';
2
+ export * from './resolver.js';
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Part resolver — indexes a plugin list by extension point and answers the
3
+ * queries core needs (schemas to merge, routes to mount, document actions for a
4
+ * given type, a field component for an `input` key). Built once at boot from
5
+ * `config.plugins` and exposed on the engine so both server and admin consult the
6
+ * same resolved model. Validates duplicate part ids up front — no silent overrides.
7
+ */
8
+ import type { AdminToolPart, CMSPlugin, DocumentActionPart, FieldComponentPart, PartKind, PluginPart, ServerRoutePart, SettingsPart } from './types.js';
9
+ import type { SchemaType } from '../types/schemas.js';
10
+ import { type CapabilityDefinition } from '../types/capabilities.js';
11
+ type PartOf<K extends PartKind> = Extract<PluginPart, {
12
+ implements: K;
13
+ }>;
14
+ export interface PartResolver {
15
+ readonly plugins: CMSPlugin[];
16
+ /** All parts implementing a given extension point, typed to that part kind. */
17
+ getParts<K extends PartKind>(kind: K): PartOf<K>[];
18
+ /** Flattened schema contributions, ready to merge into `schemaTypes`. */
19
+ schemaTypes(): SchemaType[];
20
+ /** Apply every `aphex/schema/transform` part, in order, to a schema list. */
21
+ applySchemaTransforms(schemas: SchemaType[]): SchemaType[];
22
+ /** Server-route parts to mount under `/api`. */
23
+ serverRoutes(): ServerRoutePart[];
24
+ /** Deduplicated capability id strings declared by plugins. */
25
+ capabilities(): string[];
26
+ /** The full capability catalog — built-in definitions plus plugin-declared ones,
27
+ * deduped by id. This is the registry the roles UI renders. */
28
+ capabilityCatalog(): CapabilityDefinition[];
29
+ /** Document actions applicable to a document type, capability- and order-filtered. */
30
+ documentActions(args: {
31
+ schemaName: string;
32
+ capabilities?: string[];
33
+ overrideAccess?: boolean;
34
+ }): DocumentActionPart[];
35
+ /** Admin tools, capability- and order-filtered. */
36
+ adminTools(args?: {
37
+ capabilities?: string[];
38
+ overrideAccess?: boolean;
39
+ }): AdminToolPart[];
40
+ /** The field component registered for a given `input` key, if any. */
41
+ fieldComponent(input: string): FieldComponentPart | undefined;
42
+ /** All plugin settings declarations, in registration order. */
43
+ settingsDeclarations(): SettingsPart[];
44
+ /** The settings declaration for a given plugin id, if any. */
45
+ settingsDeclaration(pluginId: string): SettingsPart | undefined;
46
+ }
47
+ export declare function createPartResolver(plugins?: CMSPlugin[]): PartResolver;
48
+ export {};
49
+ //# sourceMappingURL=resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/lib/plugins/resolver.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EACX,aAAa,EACb,SAAS,EACT,kBAAkB,EAClB,kBAAkB,EAClB,QAAQ,EACR,UAAU,EACV,eAAe,EACf,YAAY,EACZ,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAGN,KAAK,oBAAoB,EACzB,MAAM,uBAAuB,CAAC;AAE/B,KAAK,MAAM,CAAC,CAAC,SAAS,QAAQ,IAAI,OAAO,CAAC,UAAU,EAAE;IAAE,UAAU,EAAE,CAAC,CAAA;CAAE,CAAC,CAAC;AAEzE,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC;IAC9B,+EAA+E;IAC/E,QAAQ,CAAC,CAAC,SAAS,QAAQ,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACnD,yEAAyE;IACzE,WAAW,IAAI,UAAU,EAAE,CAAC;IAC5B,6EAA6E;IAC7E,qBAAqB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAAC;IAC3D,gDAAgD;IAChD,YAAY,IAAI,eAAe,EAAE,CAAC;IAClC,8DAA8D;IAC9D,YAAY,IAAI,MAAM,EAAE,CAAC;IACzB;oEACgE;IAChE,iBAAiB,IAAI,oBAAoB,EAAE,CAAC;IAC5C,sFAAsF;IACtF,eAAe,CAAC,IAAI,EAAE;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,cAAc,CAAC,EAAE,OAAO,CAAC;KACzB,GAAG,kBAAkB,EAAE,CAAC;IACzB,mDAAmD;IACnD,UAAU,CAAC,IAAI,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,aAAa,EAAE,CAAC;IAC1F,sEAAsE;IACtE,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAAC;IAC9D,+DAA+D;IAC/D,oBAAoB,IAAI,YAAY,EAAE,CAAC;IACvC,8DAA8D;IAC9D,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;CAChE;AAED,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,SAAS,EAAO,GAAG,YAAY,CAgF1E"}
@@ -0,0 +1,65 @@
1
+ import { defineCapability, mergeCapabilityCatalog } from '../types/capabilities.js';
2
+ export function createPartResolver(plugins = []) {
3
+ const allParts = plugins.flatMap((p) => p.parts ?? []);
4
+ // Duplicate-id validation, per extension point. Parts without an id (schema,
5
+ // capabilities, field-component) are exempt.
6
+ const seen = new Map();
7
+ for (const part of allParts) {
8
+ if ('id' in part && typeof part.id === 'string') {
9
+ const bucket = seen.get(part.implements) ?? new Set();
10
+ if (bucket.has(part.id)) {
11
+ throw new Error(`Duplicate plugin part id "${part.id}" for ${part.implements}. ` +
12
+ `Part ids must be unique per extension point.`);
13
+ }
14
+ bucket.add(part.id);
15
+ seen.set(part.implements, bucket);
16
+ }
17
+ }
18
+ // Settings parts key on `pluginId` (not `id`), so guard their uniqueness separately —
19
+ // two declarations for one plugin would fight over the same storage row.
20
+ const settingsIds = new Set();
21
+ for (const part of allParts) {
22
+ if (part.implements !== 'aphex/settings')
23
+ continue;
24
+ if (settingsIds.has(part.pluginId)) {
25
+ throw new Error(`Duplicate plugin settings declaration for "${part.pluginId}". ` +
26
+ `Each plugin may declare settings once.`);
27
+ }
28
+ settingsIds.add(part.pluginId);
29
+ }
30
+ const getParts = (kind) => allParts.filter((p) => p.implements === kind);
31
+ const hasCaps = (required, caps, overrideAccess) => overrideAccess || !required || required.length === 0 || required.every((c) => caps.includes(c));
32
+ return {
33
+ plugins,
34
+ getParts,
35
+ schemaTypes: () => getParts('aphex/schema').flatMap((p) => p.schemas),
36
+ applySchemaTransforms: (schemas) => getParts('aphex/schema/transform').reduce((acc, part) => part.transform(acc), schemas),
37
+ serverRoutes: () => getParts('aphex/server/route'),
38
+ capabilities: () => {
39
+ const set = new Set();
40
+ for (const p of getParts('aphex/capabilities'))
41
+ for (const c of p.capabilities)
42
+ set.add(typeof c === 'string' ? c : c.id);
43
+ return [...set];
44
+ },
45
+ capabilityCatalog: () => {
46
+ // Normalize each plugin-declared capability (bare id or full definition),
47
+ // then merge with the built-in catalog — first definition of an id wins.
48
+ const pluginDefs = [];
49
+ for (const p of getParts('aphex/capabilities'))
50
+ for (const c of p.capabilities)
51
+ pluginDefs.push(typeof c === 'string' ? defineCapability(c) : c);
52
+ return mergeCapabilityCatalog(pluginDefs);
53
+ },
54
+ documentActions: ({ schemaName, capabilities = [], overrideAccess = false }) => getParts('aphex/document/action')
55
+ .filter((a) => !a.appliesTo || a.appliesTo.includes(schemaName))
56
+ .filter((a) => hasCaps(a.requiredCapabilities, capabilities, overrideAccess))
57
+ .sort((a, b) => (a.order ?? 0) - (b.order ?? 0)),
58
+ adminTools: ({ capabilities = [], overrideAccess = false } = {}) => getParts('aphex/admin/tool')
59
+ .filter((t) => hasCaps(t.requiredCapabilities, capabilities, overrideAccess))
60
+ .sort((a, b) => (a.order ?? 0) - (b.order ?? 0)),
61
+ fieldComponent: (input) => getParts('aphex/field/component').find((f) => f.input === input),
62
+ settingsDeclarations: () => getParts('aphex/settings'),
63
+ settingsDeclaration: (pluginId) => getParts('aphex/settings').find((s) => s.pluginId === pluginId)
64
+ };
65
+ }
@@ -0,0 +1,233 @@
1
+ /**
2
+ * Plugin type system — the public authoring surface.
3
+ *
4
+ * A plugin is a manifest of typed "parts", each implementing a named extension
5
+ * point. The kinds are split into two planes (see PLUGIN_SYSTEM_PLAN.md §Constraint):
6
+ *
7
+ * - SERVER / serializable plane — schemas, server routes, capabilities. Collected
8
+ * by the engine at boot; safe to reason about without loading any component.
9
+ * - COMPONENT plane — document actions, admin tools, field components. These carry
10
+ * Svelte components and are only ever imported into admin module code, never
11
+ * passed through SvelteKit `load` (load data must stay serializable).
12
+ *
13
+ * All imports here are type-only, so this module is safe on both planes.
14
+ */
15
+ import type { Component } from 'svelte';
16
+ import type { Context, Hono } from 'hono';
17
+ import type { AphexEnv } from '../server/api/index.js';
18
+ import type { Field, SettingsField, SchemaType } from '../types/schemas.js';
19
+ import type { AdminArea } from '../admin/types.js';
20
+ import type { CapabilityDefinition } from '../types/capabilities.js';
21
+ /** Known extension points. Plugins may also register custom string kinds. */
22
+ export type PartKind = 'aphex/schema' | 'aphex/schema/transform' | 'aphex/server/route' | 'aphex/capabilities' | 'aphex/settings' | 'aphex/document/action' | 'aphex/admin/tool' | 'aphex/field/component';
23
+ /** Contributes content schemas, merged into the app's `schemaTypes`. */
24
+ export interface SchemaPart {
25
+ implements: 'aphex/schema';
26
+ schemas: SchemaType[];
27
+ }
28
+ /**
29
+ * Transforms the resolved schema list — decorate existing types, not just add new
30
+ * ones (e.g. inject an SEO field group into a set of collections). Runs after all
31
+ * `aphex/schema` parts merge, on both the server engine and the admin, so the
32
+ * transform must be pure and deterministic. This is what lets a plugin "enable"
33
+ * itself on chosen document types the way Payload's `collections: [...]` does.
34
+ */
35
+ export interface SchemaTransformPart {
36
+ implements: 'aphex/schema/transform';
37
+ transform: (schemas: SchemaType[]) => SchemaType[];
38
+ }
39
+ /**
40
+ * Contributes an HTTP endpoint under `/api`. `path: '/bookings'` + `method: 'POST'`
41
+ * becomes `POST /api/bookings`. The handler gets the same Hono context as built-ins
42
+ * (`c.var.aphexCMS`, `c.var.auth`).
43
+ */
44
+ export interface ServerRoutePart {
45
+ implements: 'aphex/server/route';
46
+ /** Unique across all plugins — collisions are a startup error. */
47
+ id: string;
48
+ method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
49
+ path: string;
50
+ handler: (c: Context<AphexEnv>) => Response | Promise<Response>;
51
+ /**
52
+ * Who may call this route. Mandatory and with no default: a plugin route is an
53
+ * ordinary internet-facing endpoint, and "I forgot" must not be spellable as
54
+ * "anyone may call this". Say which of the three you mean:
55
+ *
56
+ * - `['forms.export']` — must be authenticated AND hold every listed capability.
57
+ * The usual answer. The CMS gates the route before the handler runs (401 with no
58
+ * session/api-key, 403 when capabilities are missing), so the check can't be
59
+ * forgotten in the handler.
60
+ * - `[]` — must be authenticated, but any role will do. Use when membership of the
61
+ * organization is itself the authorization.
62
+ * - `'public'` — no gate; anyone on the internet can call it. For webhook receivers
63
+ * and the like, where the handler does its own verification (a signature, a shared
64
+ * secret). Opting out is deliberate and greppable.
65
+ */
66
+ requiredCapabilities: string[] | 'public';
67
+ }
68
+ /**
69
+ * Declares custom capabilities this plugin introduces — surfaced (and assignable) in
70
+ * the roles UI. Pass `defineCapability(id, { title, description, group })` for full
71
+ * metadata, or a bare id string (labelled from its last segment). Merged with the
72
+ * built-in catalog by the part resolver (`capabilityCatalog()`); a plugin can't
73
+ * redefine a core capability.
74
+ */
75
+ export interface CapabilitiesPart {
76
+ implements: 'aphex/capabilities';
77
+ capabilities: (string | CapabilityDefinition)[];
78
+ }
79
+ /**
80
+ * Declares a plugin's **settings surface** — configuration a user edits in the
81
+ * admin UI (connection details, toggles, and — in phase 2 — secrets), stored
82
+ * per-`(organization, plugin)` and injected back into the plugin's server code.
83
+ *
84
+ * This is CONFIG, not content: settings are deliberately NOT content schema types.
85
+ * They never enter document lists, draft/published perspectives, versioning, the
86
+ * content REST/GraphQL API, MCP tools, or generated types. Only the field *renderer*
87
+ * is reused (the same UI that draws a document field), never the type registry,
88
+ * content storage, or content API. See references/plugin-settings-and-secrets-scope.md.
89
+ *
90
+ * Declaration only, like every other serializable part — the host owns rendering,
91
+ * storage, encryption, gating, and injection. A plugin only says what its settings
92
+ * look like.
93
+ */
94
+ export interface SettingsPart {
95
+ implements: 'aphex/settings';
96
+ /**
97
+ * Which plugin these settings belong to — the storage key alongside the org.
98
+ * Use the plugin's package name (e.g. `@aphexcms/forms`) so it's stable and unique.
99
+ */
100
+ pluginId: string;
101
+ /** Human label for the settings section in the admin UI. */
102
+ title: string;
103
+ /** Optional one-line description shown under the title. */
104
+ description?: string;
105
+ /**
106
+ * The settings fields. `SettingsField` is a deliberately narrow subset — `string`,
107
+ * `text`, `number`, `boolean`, plus the settings-only `secret` (write-only,
108
+ * encrypted at rest) — so every declared field is one the panel really renders and
109
+ * the service really validates. No content-schema features (references, portable
110
+ * text, assets) and no custom `input` widgets. Values are type-checked against
111
+ * these declarations on save.
112
+ */
113
+ fields: SettingsField[];
114
+ /**
115
+ * Capabilities required to view/edit this settings section. Defaults to the
116
+ * built-in `plugin.settings.manage` when omitted — set a narrower capability to
117
+ * gate a specific plugin's settings more tightly.
118
+ */
119
+ requiredCapabilities?: string[];
120
+ }
121
+ /**
122
+ * A minimal, stable context handed to a document-action component. Deliberately
123
+ * decoupled from editor internals — actions get exactly this and nothing more, so
124
+ * the editor can be refactored without breaking plugins.
125
+ */
126
+ export interface DocumentActionProps {
127
+ /** Null while the document is new and unsaved. */
128
+ documentId: string | null;
129
+ schema: SchemaType;
130
+ /** The live edited draft data. */
131
+ data: Record<string, unknown>;
132
+ status: 'new' | 'draft' | 'published' | 'unpublished';
133
+ /** Shallow-merge a patch into the document's data. */
134
+ updateData: (patch: Record<string, unknown>) => void;
135
+ save: () => Promise<void>;
136
+ publish: () => Promise<void>;
137
+ }
138
+ /** Adds a button/action to the document editor toolbar. */
139
+ export interface DocumentActionPart {
140
+ implements: 'aphex/document/action';
141
+ /** Unique across all plugins. */
142
+ id: string;
143
+ title: string;
144
+ icon?: Component;
145
+ component: Component<{
146
+ action: DocumentActionProps;
147
+ }>;
148
+ /** Document type names this applies to. Omit for all types. */
149
+ appliesTo?: string[];
150
+ requiredCapabilities?: string[];
151
+ order?: number;
152
+ }
153
+ /**
154
+ * The stable context handed to an admin-tool component — enough to read the
155
+ * environment, gate on capabilities, and navigate, without touching AdminApp
156
+ * internals. For document data, tools use the REST client (session-authenticated).
157
+ */
158
+ export interface AdminToolProps {
159
+ organizationId: string | null;
160
+ capabilities: readonly string[];
161
+ role: string | null;
162
+ /** True if the session has the capability (privileged roles bypass). */
163
+ can: (capability: string) => boolean;
164
+ /** All content schemas (read-only), for listing document types etc. */
165
+ schemas: SchemaType[];
166
+ /** Switch the active admin area/tab (e.g. back to `'structure'`). */
167
+ navigate: (area: AdminArea) => void;
168
+ /** Open a document in the editor. */
169
+ openDocument: (documentType: string, documentId: string) => void;
170
+ }
171
+ /** Adds a top-level admin section (its own tool). */
172
+ export interface AdminToolPart {
173
+ implements: 'aphex/admin/tool';
174
+ /** Unique across all plugins; also the tool's route key. */
175
+ id: string;
176
+ title: string;
177
+ icon?: Component;
178
+ component: Component<{
179
+ tool: AdminToolProps;
180
+ }>;
181
+ requiredCapabilities?: string[];
182
+ order?: number;
183
+ /**
184
+ * Where the tool's trigger renders. `'tab'` (default) puts it in the top tab
185
+ * strip alongside Content/Media/Vision; `'sidebar'` puts it in the left sidebar
186
+ * nav instead — better once several plugins are installed and the tab strip
187
+ * would overflow. Either way the tool opens the same `plugin:<id>` area.
188
+ */
189
+ placement?: 'tab' | 'sidebar';
190
+ }
191
+ /**
192
+ * The stable props a field-input widget receives — the same shape the built-in
193
+ * field renderers use, so a plugin widget is a drop-in replacement.
194
+ */
195
+ export interface FieldComponentProps {
196
+ field: Field;
197
+ value: unknown;
198
+ onUpdate: (value: unknown) => void;
199
+ readonly?: boolean;
200
+ /** Validation-state CSS classes to spread onto the control (optional). */
201
+ validationClasses?: string;
202
+ /** The whole document's data — for widgets that read sibling fields (e.g. an SEO preview). */
203
+ documentData?: Record<string, unknown>;
204
+ /** The document's type name (e.g. `'author'`) — for widgets that vary by type. */
205
+ schemaType?: string;
206
+ }
207
+ /**
208
+ * Provides a custom input widget, selected by a field's `input` key in the schema
209
+ * (e.g. `{ type: 'string', input: 'color' }`).
210
+ */
211
+ export interface FieldComponentPart {
212
+ implements: 'aphex/field/component';
213
+ /** Matched against a field's `input` property. */
214
+ input: string;
215
+ component: Component<FieldComponentProps>;
216
+ }
217
+ export type PluginPart = SchemaPart | SchemaTransformPart | ServerRoutePart | CapabilitiesPart | SettingsPart | DocumentActionPart | AdminToolPart | FieldComponentPart;
218
+ /** A plugin manifest. Returned by `definePlugin`. */
219
+ export interface CMSPlugin {
220
+ /** Package-style name, e.g. `@acme/aphex-plugin-seo`. Used in error messages. */
221
+ name: string;
222
+ version?: string;
223
+ parts?: PluginPart[];
224
+ }
225
+ /** Registration hook available to server-route parts (kept for the api-mount seam). */
226
+ export type RegisterRoutes = (app: Hono<AphexEnv>) => void;
227
+ /**
228
+ * Identity helper that pins the `CMSPlugin` type for authoring. Kept a pure
229
+ * pass-through so bundlers can tree-shake unused plugins; validation (duplicate
230
+ * ids/names) happens in the part resolver at boot, where it can see all plugins.
231
+ */
232
+ export declare function definePlugin(plugin: CMSPlugin): CMSPlugin;
233
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/plugins/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Identity helper that pins the `CMSPlugin` type for authoring. Kept a pure
3
+ * pass-through so bundlers can tree-shake unused plugins; validation (duplicate
4
+ * ids/names) happens in the part resolver at boot, where it can see all plugins.
5
+ */
6
+ export function definePlugin(plugin) {
7
+ return plugin;
8
+ }
@@ -0,0 +1,27 @@
1
+ import type { Field, SchemaType } from '../types/schemas.js';
2
+ export interface DesugarOptions {
3
+ /** The authored `type` keyword to replace, e.g. `'color'`. */
4
+ type: string;
5
+ /**
6
+ * Build the replacement from the authored field. Own the *shape* only — `type`,
7
+ * `fields`, and the default `input`/`inputOptions`. Anything you copy off the
8
+ * authored field here is redundant: it is layered back on afterwards.
9
+ */
10
+ build: (authored: Field) => Field;
11
+ /**
12
+ * Keys that exist only on the sugar type and must not survive onto the expanded
13
+ * field (e.g. color's `alpha`, which becomes `inputOptions.alpha`). Everything
14
+ * else the author wrote is preserved.
15
+ */
16
+ sugarKeys?: readonly string[];
17
+ }
18
+ /**
19
+ * Desugar every `{ type: <options.type> }` field across a schema list, recursing into
20
+ * nested objects and array members, preserving everything the author declared.
21
+ *
22
+ * Intended as the body of an `aphex/schema/transform` part, so it runs identically in
23
+ * the engine, the admin, and the type generator — nothing downstream ever sees the
24
+ * sugar keyword.
25
+ */
26
+ export declare function desugarFieldType(schemas: SchemaType[], options: DesugarOptions): SchemaType[];
27
+ //# sourceMappingURL=desugar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"desugar.d.ts","sourceRoot":"","sources":["../../src/lib/schema-utils/desugar.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAiB,MAAM,kBAAkB,CAAC;AAEzE,MAAM,WAAW,cAAc;IAC9B,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,KAAK,EAAE,CAAC,QAAQ,EAAE,KAAK,KAAK,KAAK,CAAC;IAClC;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B;AA6ED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,cAAc,GAAG,UAAU,EAAE,CAM7F"}
@@ -0,0 +1,101 @@
1
+ // schema-utils/desugar.ts
2
+ //
3
+ // Shared machinery for `aphex/schema/transform` parts that desugar a custom field
4
+ // keyword into a real field — e.g. `{ type: 'color' }` → the color `object`, or
5
+ // `{ type: 'seo' }` → the SEO `object`.
6
+ //
7
+ // Every such transform has the same two jobs, and the second is easy to get wrong:
8
+ //
9
+ // 1. Walk the whole schema list — fields, nested object fields, and array members.
10
+ // 2. Replace the sugar field WITHOUT losing what the author wrote on it.
11
+ //
12
+ // Hand-rolled transforms tended to rebuild the field from a hand-picked subset
13
+ // (`name`/`title`/`description`/`group`), which silently dropped `access` — turning a
14
+ // restricted field unrestricted — along with `validation` and every group after the
15
+ // first. Preservation is the default here so a plugin author can't forget it: the
16
+ // builder supplies only the shape, and the authored field is layered back on top.
17
+ /**
18
+ * Layer the authored field back over the built one.
19
+ *
20
+ * The builder owns structure (`type`, `fields`); the author owns intent (`group`,
21
+ * `validation`, `access`, and any property added to BaseField later — hence a
22
+ * spread rather than an allowlist, which would silently go stale).
23
+ */
24
+ function preserveAuthored(authored, built, sugarKeys) {
25
+ const rest = { ...authored };
26
+ delete rest.type;
27
+ for (const key of sugarKeys)
28
+ delete rest[key];
29
+ const builtRecord = built;
30
+ const merged = {
31
+ ...builtRecord,
32
+ ...rest,
33
+ // Re-assert what the desugaring defines: the author wrote `type: 'color'`,
34
+ // not the object it expands to.
35
+ type: builtRecord.type,
36
+ // An author who explicitly asked for a different widget still wins; otherwise
37
+ // the builder's widget is the whole point of the field type.
38
+ input: rest.input ?? builtRecord.input,
39
+ // Merged, not replaced: the builder derives options from the sugar keys
40
+ // (color's `alpha` → `inputOptions.alpha`), so letting an authored
41
+ // `inputOptions` win wholesale would silently drop them. Authored keys still
42
+ // win individually.
43
+ inputOptions: mergeInputOptions(builtRecord.inputOptions, rest.inputOptions)
44
+ };
45
+ if ('fields' in builtRecord)
46
+ merged.fields = builtRecord.fields;
47
+ return merged;
48
+ }
49
+ /** Combine the builder's derived widget options with any the author declared. */
50
+ function mergeInputOptions(built, authored) {
51
+ const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
52
+ if (!isRecord(built))
53
+ return isRecord(authored) ? authored : undefined;
54
+ if (!isRecord(authored))
55
+ return built;
56
+ return { ...built, ...authored };
57
+ }
58
+ function expandFields(fields, options) {
59
+ const sugarKeys = options.sugarKeys ?? [];
60
+ return fields.map((field) => {
61
+ if (field.type === options.type) {
62
+ return preserveAuthored(field, options.build(field), sugarKeys);
63
+ }
64
+ if (field.type === 'object' && Array.isArray(field.fields)) {
65
+ return { ...field, fields: expandFields(field.fields, options) };
66
+ }
67
+ if (field.type === 'array' && Array.isArray(field.of)) {
68
+ return { ...field, of: field.of.map((member) => expandMember(member, options)) };
69
+ }
70
+ return field;
71
+ });
72
+ }
73
+ /** Array `of` members are `TypeReference`s, not `Field`s — expand them the same way. */
74
+ function expandMember(member, options) {
75
+ if (member.type === options.type) {
76
+ // A member names a *type*, so `name` is often absent — but builders take a
77
+ // named field. Fall back to the sugar keyword so the expansion keeps its
78
+ // identity (`{ of: [{ type: 'color' }] }` stays a recognisable color member
79
+ // instead of becoming an anonymous object).
80
+ const authored = { ...member, name: member.name ?? options.type };
81
+ const built = options.build(authored);
82
+ return preserveAuthored(authored, built, options.sugarKeys ?? []);
83
+ }
84
+ if (Array.isArray(member.fields)) {
85
+ return { ...member, fields: expandFields(member.fields, options) };
86
+ }
87
+ return member;
88
+ }
89
+ /**
90
+ * Desugar every `{ type: <options.type> }` field across a schema list, recursing into
91
+ * nested objects and array members, preserving everything the author declared.
92
+ *
93
+ * Intended as the body of an `aphex/schema/transform` part, so it runs identically in
94
+ * the engine, the admin, and the type generator — nothing downstream ever sees the
95
+ * sugar keyword.
96
+ */
97
+ export function desugarFieldType(schemas, options) {
98
+ return schemas.map((schema) => 'fields' in schema && Array.isArray(schema.fields)
99
+ ? { ...schema, fields: expandFields(schema.fields, options) }
100
+ : schema);
101
+ }
@@ -1,4 +1,6 @@
1
1
  export * from './cleanup.js';
2
+ export * from './desugar.js';
3
+ export * from './settings.js';
2
4
  export * from './utils.js';
3
5
  export * from './validator.js';
4
6
  export * from './singleton.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/schema-utils/index.ts"],"names":[],"mappings":"AACA,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/schema-utils/index.ts"],"names":[],"mappings":"AACA,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC"}
@@ -1,5 +1,7 @@
1
1
  // Schema utilities - all schema-related helper functions
2
2
  export * from './cleanup.js';
3
+ export * from './desugar.js';
4
+ export * from './settings.js';
3
5
  export * from './utils.js';
4
6
  export * from './validator.js';
5
7
  export * from './singleton.js';