@jini-ai/cms 0.1.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 (527) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +84 -0
  3. package/dist/content-types/agent-tools.d.ts +65 -0
  4. package/dist/content-types/agent-tools.d.ts.map +1 -0
  5. package/dist/content-types/agent-tools.js +172 -0
  6. package/dist/content-types/agent-tools.js.map +1 -0
  7. package/dist/content-types/cleanup.d.ts +118 -0
  8. package/dist/content-types/cleanup.d.ts.map +1 -0
  9. package/dist/content-types/cleanup.js +65 -0
  10. package/dist/content-types/cleanup.js.map +1 -0
  11. package/dist/content-types/errors.d.ts +90 -0
  12. package/dist/content-types/errors.d.ts.map +1 -0
  13. package/dist/content-types/errors.js +119 -0
  14. package/dist/content-types/errors.js.map +1 -0
  15. package/dist/content-types/field-defs.d.ts +25 -0
  16. package/dist/content-types/field-defs.d.ts.map +1 -0
  17. package/dist/content-types/field-defs.js +155 -0
  18. package/dist/content-types/field-defs.js.map +1 -0
  19. package/dist/content-types/index-provisioning.d.ts +94 -0
  20. package/dist/content-types/index-provisioning.d.ts.map +1 -0
  21. package/dist/content-types/index-provisioning.js +133 -0
  22. package/dist/content-types/index-provisioning.js.map +1 -0
  23. package/dist/content-types/index.d.ts +63 -0
  24. package/dist/content-types/index.d.ts.map +1 -0
  25. package/dist/content-types/index.js +36 -0
  26. package/dist/content-types/index.js.map +1 -0
  27. package/dist/content-types/lifecycle-dispatch.d.ts +38 -0
  28. package/dist/content-types/lifecycle-dispatch.d.ts.map +1 -0
  29. package/dist/content-types/lifecycle-dispatch.js +28 -0
  30. package/dist/content-types/lifecycle-dispatch.js.map +1 -0
  31. package/dist/content-types/lifecycle.d.ts +104 -0
  32. package/dist/content-types/lifecycle.d.ts.map +1 -0
  33. package/dist/content-types/lifecycle.js +143 -0
  34. package/dist/content-types/lifecycle.js.map +1 -0
  35. package/dist/content-types/list.d.ts +44 -0
  36. package/dist/content-types/list.d.ts.map +1 -0
  37. package/dist/content-types/list.js +13 -0
  38. package/dist/content-types/list.js.map +1 -0
  39. package/dist/content-types/repo.memory.d.ts +72 -0
  40. package/dist/content-types/repo.memory.d.ts.map +1 -0
  41. package/dist/content-types/repo.memory.js +71 -0
  42. package/dist/content-types/repo.memory.js.map +1 -0
  43. package/dist/content-types/tool-registrations.d.ts +65 -0
  44. package/dist/content-types/tool-registrations.d.ts.map +1 -0
  45. package/dist/content-types/tool-registrations.js +180 -0
  46. package/dist/content-types/tool-registrations.js.map +1 -0
  47. package/dist/content-types/types.d.ts +78 -0
  48. package/dist/content-types/types.d.ts.map +1 -0
  49. package/dist/content-types/types.js +32 -0
  50. package/dist/content-types/types.js.map +1 -0
  51. package/dist/content-types/write-service.d.ts +141 -0
  52. package/dist/content-types/write-service.d.ts.map +1 -0
  53. package/dist/content-types/write-service.js +180 -0
  54. package/dist/content-types/write-service.js.map +1 -0
  55. package/dist/core/commands/change-set.d.ts +98 -0
  56. package/dist/core/commands/change-set.d.ts.map +1 -0
  57. package/dist/core/commands/change-set.js +2 -0
  58. package/dist/core/commands/change-set.js.map +1 -0
  59. package/dist/core/commands/command.d.ts +168 -0
  60. package/dist/core/commands/command.d.ts.map +1 -0
  61. package/dist/core/commands/command.js +173 -0
  62. package/dist/core/commands/command.js.map +1 -0
  63. package/dist/core/index.d.ts +45 -0
  64. package/dist/core/index.d.ts.map +1 -0
  65. package/dist/core/index.js +43 -0
  66. package/dist/core/index.js.map +1 -0
  67. package/dist/core/ports.d.ts +139 -0
  68. package/dist/core/ports.d.ts.map +1 -0
  69. package/dist/core/ports.js +2 -0
  70. package/dist/core/ports.js.map +1 -0
  71. package/dist/core/tools/registration-kit.d.ts +308 -0
  72. package/dist/core/tools/registration-kit.d.ts.map +1 -0
  73. package/dist/core/tools/registration-kit.js +381 -0
  74. package/dist/core/tools/registration-kit.js.map +1 -0
  75. package/dist/entries/agent-tools.d.ts +78 -0
  76. package/dist/entries/agent-tools.d.ts.map +1 -0
  77. package/dist/entries/agent-tools.js +158 -0
  78. package/dist/entries/agent-tools.js.map +1 -0
  79. package/dist/entries/errors.d.ts +43 -0
  80. package/dist/entries/errors.d.ts.map +1 -0
  81. package/dist/entries/errors.js +59 -0
  82. package/dist/entries/errors.js.map +1 -0
  83. package/dist/entries/field-validation.d.ts +70 -0
  84. package/dist/entries/field-validation.d.ts.map +1 -0
  85. package/dist/entries/field-validation.js +87 -0
  86. package/dist/entries/field-validation.js.map +1 -0
  87. package/dist/entries/index.d.ts +55 -0
  88. package/dist/entries/index.d.ts.map +1 -0
  89. package/dist/entries/index.js +38 -0
  90. package/dist/entries/index.js.map +1 -0
  91. package/dist/entries/lifecycle-dispatch.d.ts +15 -0
  92. package/dist/entries/lifecycle-dispatch.d.ts.map +1 -0
  93. package/dist/entries/lifecycle-dispatch.js +16 -0
  94. package/dist/entries/lifecycle-dispatch.js.map +1 -0
  95. package/dist/entries/list.d.ts +47 -0
  96. package/dist/entries/list.d.ts.map +1 -0
  97. package/dist/entries/list.js +12 -0
  98. package/dist/entries/list.js.map +1 -0
  99. package/dist/entries/repo.memory.d.ts +64 -0
  100. package/dist/entries/repo.memory.d.ts.map +1 -0
  101. package/dist/entries/repo.memory.js +73 -0
  102. package/dist/entries/repo.memory.js.map +1 -0
  103. package/dist/entries/tool-registrations.d.ts +52 -0
  104. package/dist/entries/tool-registrations.d.ts.map +1 -0
  105. package/dist/entries/tool-registrations.js +141 -0
  106. package/dist/entries/tool-registrations.js.map +1 -0
  107. package/dist/entries/types.d.ts +55 -0
  108. package/dist/entries/types.d.ts.map +1 -0
  109. package/dist/entries/types.js +2 -0
  110. package/dist/entries/types.js.map +1 -0
  111. package/dist/entries/write-service.d.ts +202 -0
  112. package/dist/entries/write-service.d.ts.map +1 -0
  113. package/dist/entries/write-service.js +204 -0
  114. package/dist/entries/write-service.js.map +1 -0
  115. package/dist/identity/admin-crud-service.d.ts +252 -0
  116. package/dist/identity/admin-crud-service.d.ts.map +1 -0
  117. package/dist/identity/admin-crud-service.js +437 -0
  118. package/dist/identity/admin-crud-service.js.map +1 -0
  119. package/dist/identity/agent-tool-input.d.ts +58 -0
  120. package/dist/identity/agent-tool-input.d.ts.map +1 -0
  121. package/dist/identity/agent-tool-input.js +126 -0
  122. package/dist/identity/agent-tool-input.js.map +1 -0
  123. package/dist/identity/agent-tools.d.ts +101 -0
  124. package/dist/identity/agent-tools.d.ts.map +1 -0
  125. package/dist/identity/agent-tools.js +290 -0
  126. package/dist/identity/agent-tools.js.map +1 -0
  127. package/dist/identity/auth-service.d.ts +87 -0
  128. package/dist/identity/auth-service.d.ts.map +1 -0
  129. package/dist/identity/auth-service.js +141 -0
  130. package/dist/identity/auth-service.js.map +1 -0
  131. package/dist/identity/authorize.d.ts +90 -0
  132. package/dist/identity/authorize.d.ts.map +1 -0
  133. package/dist/identity/authorize.js +94 -0
  134. package/dist/identity/authorize.js.map +1 -0
  135. package/dist/identity/grant-service.d.ts +198 -0
  136. package/dist/identity/grant-service.d.ts.map +1 -0
  137. package/dist/identity/grant-service.js +361 -0
  138. package/dist/identity/grant-service.js.map +1 -0
  139. package/dist/identity/hasher.d.ts +39 -0
  140. package/dist/identity/hasher.d.ts.map +1 -0
  141. package/dist/identity/hasher.js +39 -0
  142. package/dist/identity/hasher.js.map +1 -0
  143. package/dist/identity/index.d.ts +59 -0
  144. package/dist/identity/index.d.ts.map +1 -0
  145. package/dist/identity/index.js +51 -0
  146. package/dist/identity/index.js.map +1 -0
  147. package/dist/identity/password-policy.d.ts +58 -0
  148. package/dist/identity/password-policy.d.ts.map +1 -0
  149. package/dist/identity/password-policy.js +67 -0
  150. package/dist/identity/password-policy.js.map +1 -0
  151. package/dist/identity/permission-migrations.d.ts +86 -0
  152. package/dist/identity/permission-migrations.d.ts.map +1 -0
  153. package/dist/identity/permission-migrations.js +67 -0
  154. package/dist/identity/permission-migrations.js.map +1 -0
  155. package/dist/identity/permissions.d.ts +35 -0
  156. package/dist/identity/permissions.d.ts.map +1 -0
  157. package/dist/identity/permissions.js +603 -0
  158. package/dist/identity/permissions.js.map +1 -0
  159. package/dist/identity/ports.d.ts +201 -0
  160. package/dist/identity/ports.d.ts.map +1 -0
  161. package/dist/identity/ports.js +2 -0
  162. package/dist/identity/ports.js.map +1 -0
  163. package/dist/identity/repo.memory.d.ts +164 -0
  164. package/dist/identity/repo.memory.d.ts.map +1 -0
  165. package/dist/identity/repo.memory.js +224 -0
  166. package/dist/identity/repo.memory.js.map +1 -0
  167. package/dist/identity/seed.d.ts +42 -0
  168. package/dist/identity/seed.d.ts.map +1 -0
  169. package/dist/identity/seed.js +277 -0
  170. package/dist/identity/seed.js.map +1 -0
  171. package/dist/identity/tool-registrations.d.ts +50 -0
  172. package/dist/identity/tool-registrations.d.ts.map +1 -0
  173. package/dist/identity/tool-registrations.js +419 -0
  174. package/dist/identity/tool-registrations.js.map +1 -0
  175. package/dist/identity/types.d.ts +185 -0
  176. package/dist/identity/types.d.ts.map +1 -0
  177. package/dist/identity/types.js +64 -0
  178. package/dist/identity/types.js.map +1 -0
  179. package/dist/identity/username.d.ts +12 -0
  180. package/dist/identity/username.d.ts.map +1 -0
  181. package/dist/identity/username.js +14 -0
  182. package/dist/identity/username.js.map +1 -0
  183. package/dist/media/agent-tools.d.ts +66 -0
  184. package/dist/media/agent-tools.d.ts.map +1 -0
  185. package/dist/media/agent-tools.js +131 -0
  186. package/dist/media/agent-tools.js.map +1 -0
  187. package/dist/media/blob-gc-lock.d.ts +37 -0
  188. package/dist/media/blob-gc-lock.d.ts.map +1 -0
  189. package/dist/media/blob-gc-lock.js +55 -0
  190. package/dist/media/blob-gc-lock.js.map +1 -0
  191. package/dist/media/blob-gc.d.ts +246 -0
  192. package/dist/media/blob-gc.d.ts.map +1 -0
  193. package/dist/media/blob-gc.js +254 -0
  194. package/dist/media/blob-gc.js.map +1 -0
  195. package/dist/media/blob-key.d.ts +28 -0
  196. package/dist/media/blob-key.d.ts.map +1 -0
  197. package/dist/media/blob-key.js +11 -0
  198. package/dist/media/blob-key.js.map +1 -0
  199. package/dist/media/blob-store.fs.d.ts +23 -0
  200. package/dist/media/blob-store.fs.d.ts.map +1 -0
  201. package/dist/media/blob-store.fs.js +48 -0
  202. package/dist/media/blob-store.fs.js.map +1 -0
  203. package/dist/media/blob-store.memory.d.ts +22 -0
  204. package/dist/media/blob-store.memory.d.ts.map +1 -0
  205. package/dist/media/blob-store.memory.js +23 -0
  206. package/dist/media/blob-store.memory.js.map +1 -0
  207. package/dist/media/content-type-sniffer.d.ts +49 -0
  208. package/dist/media/content-type-sniffer.d.ts.map +1 -0
  209. package/dist/media/content-type-sniffer.js +141 -0
  210. package/dist/media/content-type-sniffer.js.map +1 -0
  211. package/dist/media/image-transformer.d.ts +45 -0
  212. package/dist/media/image-transformer.d.ts.map +1 -0
  213. package/dist/media/image-transformer.js +23 -0
  214. package/dist/media/image-transformer.js.map +1 -0
  215. package/dist/media/image-transformer.sharp.d.ts +26 -0
  216. package/dist/media/image-transformer.sharp.d.ts.map +1 -0
  217. package/dist/media/image-transformer.sharp.js +91 -0
  218. package/dist/media/image-transformer.sharp.js.map +1 -0
  219. package/dist/media/index.d.ts +43 -0
  220. package/dist/media/index.d.ts.map +1 -0
  221. package/dist/media/index.js +31 -0
  222. package/dist/media/index.js.map +1 -0
  223. package/dist/media/media-service.d.ts +244 -0
  224. package/dist/media/media-service.d.ts.map +1 -0
  225. package/dist/media/media-service.js +345 -0
  226. package/dist/media/media-service.js.map +1 -0
  227. package/dist/media/ports.d.ts +142 -0
  228. package/dist/media/ports.d.ts.map +1 -0
  229. package/dist/media/ports.js +2 -0
  230. package/dist/media/ports.js.map +1 -0
  231. package/dist/media/rendition-service.d.ts +66 -0
  232. package/dist/media/rendition-service.d.ts.map +1 -0
  233. package/dist/media/rendition-service.js +135 -0
  234. package/dist/media/rendition-service.js.map +1 -0
  235. package/dist/media/repo.memory.d.ts +107 -0
  236. package/dist/media/repo.memory.d.ts.map +1 -0
  237. package/dist/media/repo.memory.js +131 -0
  238. package/dist/media/repo.memory.js.map +1 -0
  239. package/dist/media/tool-registrations.d.ts +42 -0
  240. package/dist/media/tool-registrations.d.ts.map +1 -0
  241. package/dist/media/tool-registrations.js +121 -0
  242. package/dist/media/tool-registrations.js.map +1 -0
  243. package/dist/media/transform-lock.d.ts +36 -0
  244. package/dist/media/transform-lock.d.ts.map +1 -0
  245. package/dist/media/transform-lock.js +50 -0
  246. package/dist/media/transform-lock.js.map +1 -0
  247. package/dist/media/transform-registry.d.ts +103 -0
  248. package/dist/media/transform-registry.d.ts.map +1 -0
  249. package/dist/media/transform-registry.js +87 -0
  250. package/dist/media/transform-registry.js.map +1 -0
  251. package/dist/media/transform-types.d.ts +82 -0
  252. package/dist/media/transform-types.d.ts.map +1 -0
  253. package/dist/media/transform-types.js +47 -0
  254. package/dist/media/transform-types.js.map +1 -0
  255. package/dist/media/types.d.ts +150 -0
  256. package/dist/media/types.d.ts.map +1 -0
  257. package/dist/media/types.js +26 -0
  258. package/dist/media/types.js.map +1 -0
  259. package/dist/navigation/agent-tools.d.ts +90 -0
  260. package/dist/navigation/agent-tools.d.ts.map +1 -0
  261. package/dist/navigation/agent-tools.js +225 -0
  262. package/dist/navigation/agent-tools.js.map +1 -0
  263. package/dist/navigation/contracts.d.ts +98 -0
  264. package/dist/navigation/contracts.d.ts.map +1 -0
  265. package/dist/navigation/contracts.js +70 -0
  266. package/dist/navigation/contracts.js.map +1 -0
  267. package/dist/navigation/index.d.ts +39 -0
  268. package/dist/navigation/index.d.ts.map +1 -0
  269. package/dist/navigation/index.js +30 -0
  270. package/dist/navigation/index.js.map +1 -0
  271. package/dist/navigation/menu-service.d.ts +256 -0
  272. package/dist/navigation/menu-service.d.ts.map +1 -0
  273. package/dist/navigation/menu-service.js +382 -0
  274. package/dist/navigation/menu-service.js.map +1 -0
  275. package/dist/navigation/ports.d.ts +147 -0
  276. package/dist/navigation/ports.d.ts.map +1 -0
  277. package/dist/navigation/ports.js +2 -0
  278. package/dist/navigation/ports.js.map +1 -0
  279. package/dist/navigation/read-model.d.ts +11 -0
  280. package/dist/navigation/read-model.d.ts.map +1 -0
  281. package/dist/navigation/read-model.js +27 -0
  282. package/dist/navigation/read-model.js.map +1 -0
  283. package/dist/navigation/reconcile.d.ts +57 -0
  284. package/dist/navigation/reconcile.d.ts.map +1 -0
  285. package/dist/navigation/reconcile.js +33 -0
  286. package/dist/navigation/reconcile.js.map +1 -0
  287. package/dist/navigation/repo.memory.d.ts +137 -0
  288. package/dist/navigation/repo.memory.d.ts.map +1 -0
  289. package/dist/navigation/repo.memory.js +95 -0
  290. package/dist/navigation/repo.memory.js.map +1 -0
  291. package/dist/navigation/resolver.d.ts +110 -0
  292. package/dist/navigation/resolver.d.ts.map +1 -0
  293. package/dist/navigation/resolver.js +131 -0
  294. package/dist/navigation/resolver.js.map +1 -0
  295. package/dist/navigation/tool-registrations.d.ts +43 -0
  296. package/dist/navigation/tool-registrations.d.ts.map +1 -0
  297. package/dist/navigation/tool-registrations.js +126 -0
  298. package/dist/navigation/tool-registrations.js.map +1 -0
  299. package/dist/navigation/types.d.ts +207 -0
  300. package/dist/navigation/types.d.ts.map +1 -0
  301. package/dist/navigation/types.js +14 -0
  302. package/dist/navigation/types.js.map +1 -0
  303. package/dist/presentation/index.d.ts +15 -0
  304. package/dist/presentation/index.d.ts.map +1 -0
  305. package/dist/presentation/index.js +15 -0
  306. package/dist/presentation/index.js.map +1 -0
  307. package/dist/presentation/presentation.d.ts +72 -0
  308. package/dist/presentation/presentation.d.ts.map +1 -0
  309. package/dist/presentation/presentation.js +51 -0
  310. package/dist/presentation/presentation.js.map +1 -0
  311. package/dist/presentation/repo.memory.d.ts +9 -0
  312. package/dist/presentation/repo.memory.d.ts.map +1 -0
  313. package/dist/presentation/repo.memory.js +21 -0
  314. package/dist/presentation/repo.memory.js.map +1 -0
  315. package/dist/server/index.d.ts +28 -0
  316. package/dist/server/index.d.ts.map +1 -0
  317. package/dist/server/index.js +28 -0
  318. package/dist/server/index.js.map +1 -0
  319. package/dist/settings/agent-tools.d.ts +83 -0
  320. package/dist/settings/agent-tools.d.ts.map +1 -0
  321. package/dist/settings/agent-tools.js +200 -0
  322. package/dist/settings/agent-tools.js.map +1 -0
  323. package/dist/settings/agent-writable-preferences.d.ts +67 -0
  324. package/dist/settings/agent-writable-preferences.d.ts.map +1 -0
  325. package/dist/settings/agent-writable-preferences.js +144 -0
  326. package/dist/settings/agent-writable-preferences.js.map +1 -0
  327. package/dist/settings/change-feed.d.ts +74 -0
  328. package/dist/settings/change-feed.d.ts.map +1 -0
  329. package/dist/settings/change-feed.js +61 -0
  330. package/dist/settings/change-feed.js.map +1 -0
  331. package/dist/settings/definitions-dispatch.d.ts +51 -0
  332. package/dist/settings/definitions-dispatch.d.ts.map +1 -0
  333. package/dist/settings/definitions-dispatch.js +86 -0
  334. package/dist/settings/definitions-dispatch.js.map +1 -0
  335. package/dist/settings/dictionaries/index.d.ts +45 -0
  336. package/dist/settings/dictionaries/index.d.ts.map +1 -0
  337. package/dist/settings/dictionaries/index.js +69 -0
  338. package/dist/settings/dictionaries/index.js.map +1 -0
  339. package/dist/settings/dictionaries/settings-dialog.ar.d.ts +3 -0
  340. package/dist/settings/dictionaries/settings-dialog.ar.d.ts.map +1 -0
  341. package/dist/settings/dictionaries/settings-dialog.ar.js +28 -0
  342. package/dist/settings/dictionaries/settings-dialog.ar.js.map +1 -0
  343. package/dist/settings/dictionaries/settings-dialog.bn.d.ts +3 -0
  344. package/dist/settings/dictionaries/settings-dialog.bn.d.ts.map +1 -0
  345. package/dist/settings/dictionaries/settings-dialog.bn.js +28 -0
  346. package/dist/settings/dictionaries/settings-dialog.bn.js.map +1 -0
  347. package/dist/settings/dictionaries/settings-dialog.de.d.ts +3 -0
  348. package/dist/settings/dictionaries/settings-dialog.de.d.ts.map +1 -0
  349. package/dist/settings/dictionaries/settings-dialog.de.js +28 -0
  350. package/dist/settings/dictionaries/settings-dialog.de.js.map +1 -0
  351. package/dist/settings/dictionaries/settings-dialog.es.d.ts +3 -0
  352. package/dist/settings/dictionaries/settings-dialog.es.d.ts.map +1 -0
  353. package/dist/settings/dictionaries/settings-dialog.es.js +28 -0
  354. package/dist/settings/dictionaries/settings-dialog.es.js.map +1 -0
  355. package/dist/settings/dictionaries/settings-dialog.fa.d.ts +3 -0
  356. package/dist/settings/dictionaries/settings-dialog.fa.d.ts.map +1 -0
  357. package/dist/settings/dictionaries/settings-dialog.fa.js +28 -0
  358. package/dist/settings/dictionaries/settings-dialog.fa.js.map +1 -0
  359. package/dist/settings/dictionaries/settings-dialog.fr.d.ts +3 -0
  360. package/dist/settings/dictionaries/settings-dialog.fr.d.ts.map +1 -0
  361. package/dist/settings/dictionaries/settings-dialog.fr.js +28 -0
  362. package/dist/settings/dictionaries/settings-dialog.fr.js.map +1 -0
  363. package/dist/settings/dictionaries/settings-dialog.hi.d.ts +3 -0
  364. package/dist/settings/dictionaries/settings-dialog.hi.d.ts.map +1 -0
  365. package/dist/settings/dictionaries/settings-dialog.hi.js +28 -0
  366. package/dist/settings/dictionaries/settings-dialog.hi.js.map +1 -0
  367. package/dist/settings/dictionaries/settings-dialog.hu.d.ts +3 -0
  368. package/dist/settings/dictionaries/settings-dialog.hu.d.ts.map +1 -0
  369. package/dist/settings/dictionaries/settings-dialog.hu.js +28 -0
  370. package/dist/settings/dictionaries/settings-dialog.hu.js.map +1 -0
  371. package/dist/settings/dictionaries/settings-dialog.id.d.ts +3 -0
  372. package/dist/settings/dictionaries/settings-dialog.id.d.ts.map +1 -0
  373. package/dist/settings/dictionaries/settings-dialog.id.js +28 -0
  374. package/dist/settings/dictionaries/settings-dialog.id.js.map +1 -0
  375. package/dist/settings/dictionaries/settings-dialog.it.d.ts +3 -0
  376. package/dist/settings/dictionaries/settings-dialog.it.d.ts.map +1 -0
  377. package/dist/settings/dictionaries/settings-dialog.it.js +28 -0
  378. package/dist/settings/dictionaries/settings-dialog.it.js.map +1 -0
  379. package/dist/settings/dictionaries/settings-dialog.ja.d.ts +3 -0
  380. package/dist/settings/dictionaries/settings-dialog.ja.d.ts.map +1 -0
  381. package/dist/settings/dictionaries/settings-dialog.ja.js +28 -0
  382. package/dist/settings/dictionaries/settings-dialog.ja.js.map +1 -0
  383. package/dist/settings/dictionaries/settings-dialog.ko.d.ts +3 -0
  384. package/dist/settings/dictionaries/settings-dialog.ko.d.ts.map +1 -0
  385. package/dist/settings/dictionaries/settings-dialog.ko.js +28 -0
  386. package/dist/settings/dictionaries/settings-dialog.ko.js.map +1 -0
  387. package/dist/settings/dictionaries/settings-dialog.pl.d.ts +3 -0
  388. package/dist/settings/dictionaries/settings-dialog.pl.d.ts.map +1 -0
  389. package/dist/settings/dictionaries/settings-dialog.pl.js +28 -0
  390. package/dist/settings/dictionaries/settings-dialog.pl.js.map +1 -0
  391. package/dist/settings/dictionaries/settings-dialog.pt-BR.d.ts +3 -0
  392. package/dist/settings/dictionaries/settings-dialog.pt-BR.d.ts.map +1 -0
  393. package/dist/settings/dictionaries/settings-dialog.pt-BR.js +28 -0
  394. package/dist/settings/dictionaries/settings-dialog.pt-BR.js.map +1 -0
  395. package/dist/settings/dictionaries/settings-dialog.ru.d.ts +3 -0
  396. package/dist/settings/dictionaries/settings-dialog.ru.d.ts.map +1 -0
  397. package/dist/settings/dictionaries/settings-dialog.ru.js +28 -0
  398. package/dist/settings/dictionaries/settings-dialog.ru.js.map +1 -0
  399. package/dist/settings/dictionaries/settings-dialog.th.d.ts +3 -0
  400. package/dist/settings/dictionaries/settings-dialog.th.d.ts.map +1 -0
  401. package/dist/settings/dictionaries/settings-dialog.th.js +28 -0
  402. package/dist/settings/dictionaries/settings-dialog.th.js.map +1 -0
  403. package/dist/settings/dictionaries/settings-dialog.tr.d.ts +3 -0
  404. package/dist/settings/dictionaries/settings-dialog.tr.d.ts.map +1 -0
  405. package/dist/settings/dictionaries/settings-dialog.tr.js +28 -0
  406. package/dist/settings/dictionaries/settings-dialog.tr.js.map +1 -0
  407. package/dist/settings/dictionaries/settings-dialog.uk.d.ts +3 -0
  408. package/dist/settings/dictionaries/settings-dialog.uk.d.ts.map +1 -0
  409. package/dist/settings/dictionaries/settings-dialog.uk.js +28 -0
  410. package/dist/settings/dictionaries/settings-dialog.uk.js.map +1 -0
  411. package/dist/settings/dictionaries/settings-dialog.ur.d.ts +3 -0
  412. package/dist/settings/dictionaries/settings-dialog.ur.d.ts.map +1 -0
  413. package/dist/settings/dictionaries/settings-dialog.ur.js +28 -0
  414. package/dist/settings/dictionaries/settings-dialog.ur.js.map +1 -0
  415. package/dist/settings/dictionaries/settings-dialog.zh-CN.d.ts +3 -0
  416. package/dist/settings/dictionaries/settings-dialog.zh-CN.d.ts.map +1 -0
  417. package/dist/settings/dictionaries/settings-dialog.zh-CN.js +28 -0
  418. package/dist/settings/dictionaries/settings-dialog.zh-CN.js.map +1 -0
  419. package/dist/settings/dictionaries/settings-dialog.zh-TW.d.ts +3 -0
  420. package/dist/settings/dictionaries/settings-dialog.zh-TW.d.ts.map +1 -0
  421. package/dist/settings/dictionaries/settings-dialog.zh-TW.js +28 -0
  422. package/dist/settings/dictionaries/settings-dialog.zh-TW.js.map +1 -0
  423. package/dist/settings/ensure-definitions.d.ts +88 -0
  424. package/dist/settings/ensure-definitions.d.ts.map +1 -0
  425. package/dist/settings/ensure-definitions.js +91 -0
  426. package/dist/settings/ensure-definitions.js.map +1 -0
  427. package/dist/settings/errors.d.ts +36 -0
  428. package/dist/settings/errors.d.ts.map +1 -0
  429. package/dist/settings/errors.js +40 -0
  430. package/dist/settings/errors.js.map +1 -0
  431. package/dist/settings/index.d.ts +37 -0
  432. package/dist/settings/index.d.ts.map +1 -0
  433. package/dist/settings/index.js +36 -0
  434. package/dist/settings/index.js.map +1 -0
  435. package/dist/settings/ports.d.ts +117 -0
  436. package/dist/settings/ports.d.ts.map +1 -0
  437. package/dist/settings/ports.js +2 -0
  438. package/dist/settings/ports.js.map +1 -0
  439. package/dist/settings/purge-service.d.ts +53 -0
  440. package/dist/settings/purge-service.d.ts.map +1 -0
  441. package/dist/settings/purge-service.js +105 -0
  442. package/dist/settings/purge-service.js.map +1 -0
  443. package/dist/settings/repo.memory.d.ts +119 -0
  444. package/dist/settings/repo.memory.d.ts.map +1 -0
  445. package/dist/settings/repo.memory.js +199 -0
  446. package/dist/settings/repo.memory.js.map +1 -0
  447. package/dist/settings/settings.d.ts +124 -0
  448. package/dist/settings/settings.d.ts.map +1 -0
  449. package/dist/settings/settings.js +238 -0
  450. package/dist/settings/settings.js.map +1 -0
  451. package/dist/settings/tool-registrations.d.ts +56 -0
  452. package/dist/settings/tool-registrations.d.ts.map +1 -0
  453. package/dist/settings/tool-registrations.js +240 -0
  454. package/dist/settings/tool-registrations.js.map +1 -0
  455. package/dist/settings/types.d.ts +125 -0
  456. package/dist/settings/types.d.ts.map +1 -0
  457. package/dist/settings/types.js +3 -0
  458. package/dist/settings/types.js.map +1 -0
  459. package/dist/settings/ui-tab-definitions.d.ts +41 -0
  460. package/dist/settings/ui-tab-definitions.d.ts.map +1 -0
  461. package/dist/settings/ui-tab-definitions.js +148 -0
  462. package/dist/settings/ui-tab-definitions.js.map +1 -0
  463. package/dist/settings/write-service.d.ts +314 -0
  464. package/dist/settings/write-service.d.ts.map +1 -0
  465. package/dist/settings/write-service.js +677 -0
  466. package/dist/settings/write-service.js.map +1 -0
  467. package/dist/taxonomy/agent-tools.d.ts +76 -0
  468. package/dist/taxonomy/agent-tools.d.ts.map +1 -0
  469. package/dist/taxonomy/agent-tools.js +178 -0
  470. package/dist/taxonomy/agent-tools.js.map +1 -0
  471. package/dist/taxonomy/content-lookup.d.ts +45 -0
  472. package/dist/taxonomy/content-lookup.d.ts.map +1 -0
  473. package/dist/taxonomy/content-lookup.js +9 -0
  474. package/dist/taxonomy/content-lookup.js.map +1 -0
  475. package/dist/taxonomy/index.d.ts +38 -0
  476. package/dist/taxonomy/index.d.ts.map +1 -0
  477. package/dist/taxonomy/index.js +38 -0
  478. package/dist/taxonomy/index.js.map +1 -0
  479. package/dist/taxonomy/list.d.ts +39 -0
  480. package/dist/taxonomy/list.d.ts.map +1 -0
  481. package/dist/taxonomy/list.js +19 -0
  482. package/dist/taxonomy/list.js.map +1 -0
  483. package/dist/taxonomy/merge-term.d.ts +94 -0
  484. package/dist/taxonomy/merge-term.d.ts.map +1 -0
  485. package/dist/taxonomy/merge-term.js +65 -0
  486. package/dist/taxonomy/merge-term.js.map +1 -0
  487. package/dist/taxonomy/repo.memory.d.ts +160 -0
  488. package/dist/taxonomy/repo.memory.d.ts.map +1 -0
  489. package/dist/taxonomy/repo.memory.js +171 -0
  490. package/dist/taxonomy/repo.memory.js.map +1 -0
  491. package/dist/taxonomy/validation-chain.d.ts +114 -0
  492. package/dist/taxonomy/validation-chain.d.ts.map +1 -0
  493. package/dist/taxonomy/validation-chain.js +152 -0
  494. package/dist/taxonomy/validation-chain.js.map +1 -0
  495. package/dist/taxonomy/write-service.d.ts +387 -0
  496. package/dist/taxonomy/write-service.d.ts.map +1 -0
  497. package/dist/taxonomy/write-service.js +350 -0
  498. package/dist/taxonomy/write-service.js.map +1 -0
  499. package/dist/workspace/agent-tools.d.ts +67 -0
  500. package/dist/workspace/agent-tools.d.ts.map +1 -0
  501. package/dist/workspace/agent-tools.js +103 -0
  502. package/dist/workspace/agent-tools.js.map +1 -0
  503. package/dist/workspace/create.d.ts +116 -0
  504. package/dist/workspace/create.d.ts.map +1 -0
  505. package/dist/workspace/create.js +69 -0
  506. package/dist/workspace/create.js.map +1 -0
  507. package/dist/workspace/delete.d.ts +50 -0
  508. package/dist/workspace/delete.d.ts.map +1 -0
  509. package/dist/workspace/delete.js +24 -0
  510. package/dist/workspace/delete.js.map +1 -0
  511. package/dist/workspace/index.d.ts +27 -0
  512. package/dist/workspace/index.d.ts.map +1 -0
  513. package/dist/workspace/index.js +27 -0
  514. package/dist/workspace/index.js.map +1 -0
  515. package/dist/workspace/repo.memory.d.ts +34 -0
  516. package/dist/workspace/repo.memory.d.ts.map +1 -0
  517. package/dist/workspace/repo.memory.js +50 -0
  518. package/dist/workspace/repo.memory.js.map +1 -0
  519. package/dist/workspace/tool-registrations.d.ts +38 -0
  520. package/dist/workspace/tool-registrations.d.ts.map +1 -0
  521. package/dist/workspace/tool-registrations.js +71 -0
  522. package/dist/workspace/tool-registrations.js.map +1 -0
  523. package/dist/workspace/update.d.ts +52 -0
  524. package/dist/workspace/update.d.ts.map +1 -0
  525. package/dist/workspace/update.js +41 -0
  526. package/dist/workspace/update.js.map +1 -0
  527. package/package.json +149 -0
@@ -0,0 +1,382 @@
1
+ import { NAV_DOC_TYPE, } from "./types.js";
2
+ // ---------------------------------------------------------------------------
3
+ // Outbox event publication — each mutating function below
4
+ // enqueues its matching NAVIGATION_EVENTS entry after its repo write(s)
5
+ // succeed, never on a rejection path. Mirrors the host's proven
6
+ // `outbox.enqueue()` call shape.
7
+ // ---------------------------------------------------------------------------
8
+ /**
9
+ * `payload` is typed as a plain `Record<string, unknown>` (not the specific
10
+ * `NavMenuChangedPayload`/`NavLocationChangedPayload` shape) so the result
11
+ * assigns directly to `OutboxPort.enqueue`'s `DomainEvent` parameter (whose
12
+ * default payload type is `Record<string, unknown>`) without a cast — every
13
+ * call site below still passes a fresh object literal matching one of those
14
+ * two contract shapes exactly (`contracts.ts`), just not nominally typed here.
15
+ */
16
+ function buildEvent(required) {
17
+ return {
18
+ id: required.idGen.newId(),
19
+ name: required.name,
20
+ occurredAt: required.clock.nowIso(),
21
+ aggregateId: required.aggregateId,
22
+ workspaceId: required.workspaceId,
23
+ payload: required.payload,
24
+ };
25
+ }
26
+ // ---------------------------------------------------------------------------
27
+ // Typed errors
28
+ // ---------------------------------------------------------------------------
29
+ export class MenuNotFoundError extends Error {
30
+ }
31
+ export class MenuValidationError extends Error {
32
+ }
33
+ export class MenuConflictError extends Error {
34
+ }
35
+ /**
36
+ * The 409-style purge rejection: hard delete is blocked while the menu is
37
+ * still bound to at least one theme location (deletion ladder).
38
+ * Carries the offending location keys so a caller can render "unassign these
39
+ * first" without a second lookup.
40
+ */
41
+ export class MenuLocationBoundError extends MenuConflictError {
42
+ boundLocations;
43
+ constructor(message, boundLocations) {
44
+ super(message);
45
+ this.boundLocations = boundLocations;
46
+ }
47
+ }
48
+ // ---------------------------------------------------------------------------
49
+ // Tree validation (total/bounded amendment)
50
+ // ---------------------------------------------------------------------------
51
+ /** Default max nesting depth (root = depth 1). Configurable. */
52
+ export const DEFAULT_MAX_TREE_DEPTH = 5;
53
+ /** Default max total item count across the whole tree. */
54
+ export const DEFAULT_MAX_ITEM_COUNT = 500;
55
+ const VALID_TARGET_KINDS = new Set(["entryRef", "termRef", "url", "route"]);
56
+ /** Named deferred seams — recognized, rejected until their resolver ships. */
57
+ const RESERVED_TARGET_KINDS = new Set(["dynamicQuery", "content"]);
58
+ const URL_SCHEME_DENYLIST = ["javascript:", "data:", "vbscript:"];
59
+ /**
60
+ * Validates a candidate item tree and returns a defensively-cloned copy.
61
+ *
62
+ * Checks (total/bounded validation + target integrity):
63
+ * - every node has a non-empty `id`, unique across the whole tree (id
64
+ * stability is a caller responsibility — see `updateMenuTree` doc for the
65
+ * simplification this build accepts);
66
+ * - nesting depth stays within `maxDepth`;
67
+ * - total item count stays within `maxItemCount`;
68
+ * - every target's `kind` is one of the four v1 kinds — reserved kinds
69
+ * (`dynamicQuery`, `content`) are rejected with a clear "not yet" error
70
+ * rather than silently accepted;
71
+ * - `url` targets reject a scheme denylist (`javascript:`, `data:`, `vbscript:`).
72
+ *
73
+ * @complexity O(n) over total node count for one full walk; no per-node
74
+ * backtracking. Space is O(n) for the cloned tree plus O(n) for the id set.
75
+ * @overallScore 100
76
+ */
77
+ export function validateAndCloneTree(items, limits = {}) {
78
+ const maxDepth = limits.maxDepth ?? DEFAULT_MAX_TREE_DEPTH;
79
+ const maxItemCount = limits.maxItemCount ?? DEFAULT_MAX_ITEM_COUNT;
80
+ const seenIds = new Set();
81
+ let count = 0;
82
+ function walk(nodes, depth) {
83
+ if (depth > maxDepth) {
84
+ throw new MenuValidationError(`menu tree exceeds max nesting depth of ${maxDepth}`);
85
+ }
86
+ return nodes.map((node) => {
87
+ count += 1;
88
+ if (count > maxItemCount) {
89
+ throw new MenuValidationError(`menu tree exceeds max item count of ${maxItemCount}`);
90
+ }
91
+ if (!node.id || !node.id.trim()) {
92
+ throw new MenuValidationError("every menu item requires a non-empty id");
93
+ }
94
+ if (seenIds.has(node.id)) {
95
+ throw new MenuValidationError(`duplicate item id '${node.id}' in menu tree`);
96
+ }
97
+ seenIds.add(node.id);
98
+ validateTarget(node.target);
99
+ const children = node.children ? walk(node.children, depth + 1) : undefined;
100
+ return { ...node, children };
101
+ });
102
+ }
103
+ return walk(items, 1);
104
+ }
105
+ function validateTarget(target) {
106
+ const kind = target.kind;
107
+ if (RESERVED_TARGET_KINDS.has(kind)) {
108
+ throw new MenuValidationError(`target kind '${kind}' is a reserved seam and is not supported yet`);
109
+ }
110
+ if (!VALID_TARGET_KINDS.has(kind)) {
111
+ throw new MenuValidationError(`unknown target kind '${kind}'`);
112
+ }
113
+ if (kind === "url") {
114
+ const href = target.href.trim().toLowerCase();
115
+ if (URL_SCHEME_DENYLIST.some((scheme) => href.startsWith(scheme))) {
116
+ throw new MenuValidationError(`url target uses a disallowed scheme: '${target.href}'`);
117
+ }
118
+ }
119
+ }
120
+ function assertValidTitleAndSlug(title, slug) {
121
+ if (!title)
122
+ throw new MenuValidationError("title is required");
123
+ if (!slug.match(/^[a-z0-9-]+$/)) {
124
+ throw new MenuValidationError("slug must use lowercase letters, numbers, and dashes");
125
+ }
126
+ }
127
+ /**
128
+ * Creates a new `menu` entry in `published` status with no location
129
+ * assignments. Rejects a duplicate slug within the workspace.
130
+ *
131
+ * Was `draft` originally (mirroring `posts`), changed 2026-08-09 on explicit product direction: a
132
+ * menu has no separate review/approval workflow the way a post does, and `resolveForLocation`
133
+ * (`resolver.ts`) never actually branched on `status` — the field only ever gated the trash/purge
134
+ * lifecycle. Landing a new menu in `draft` produced a status label at odds with its real behavior
135
+ * (already fully live wherever it gets bound to a location) rather than gating anything real, so
136
+ * the default now matches the actual behavior instead of implying a workflow that doesn't exist.
137
+ *
138
+ * @complexity O(n) in the initial tree size for validation; O(m) in existing
139
+ * menu count for the slug-uniqueness scan (repo-dependent).
140
+ * @overallScore 100
141
+ */
142
+ export async function createMenu(required, optional = {}) {
143
+ const { deps, input } = required;
144
+ const title = input.title.trim();
145
+ const slug = input.slug.trim().toLowerCase();
146
+ assertValidTitleAndSlug(title, slug);
147
+ const duplicate = await deps.repo.findBySlug({ workspaceId: input.workspaceId, slug });
148
+ if (duplicate)
149
+ throw new MenuConflictError(`slug '${slug}' already exists`);
150
+ const items = validateAndCloneTree(input.items ?? [], optional.limits);
151
+ const menu = {
152
+ id: deps.idGen.newId(),
153
+ workspaceId: input.workspaceId,
154
+ slug,
155
+ title,
156
+ status: "published",
157
+ doc: { type: NAV_DOC_TYPE, version: 1, items },
158
+ locations: [],
159
+ updatedAt: deps.clock.nowIso(),
160
+ version: 1,
161
+ };
162
+ await deps.repo.save(menu);
163
+ await deps.outbox.enqueue(buildEvent({
164
+ idGen: deps.idGen,
165
+ clock: deps.clock,
166
+ name: "navigation.menu.created",
167
+ workspaceId: menu.workspaceId,
168
+ aggregateId: menu.id,
169
+ payload: { menuId: menu.id, slug: menu.slug },
170
+ }));
171
+ return { menu };
172
+ }
173
+ /**
174
+ * Replaces a menu's whole item tree, guarded by optimistic concurrency on the
175
+ * entry `version` (matches the host's `updatePost` pattern).
176
+ *
177
+ * Id-stability note ("an update may not renumber surviving items"):
178
+ * this build enforces only that ids are present and unique within the
179
+ * submitted tree (`validateAndCloneTree`). Detecting whether a *specific*
180
+ * surviving node kept its original id would require diffing against the
181
+ * previous tree and is deferred — a caller-discipline requirement for now,
182
+ * not a runtime-enforced invariant.
183
+ *
184
+ * @complexity O(n) in the new tree size for validation; O(1) additional repo
185
+ * calls (one read, at most one slug-uniqueness read, one write).
186
+ * @overallScore 90
187
+ * @findings Medium: id-stability across edits (ids not renumbered on survive)
188
+ * is documented but not runtime-enforced — see doc comment above. Deferred
189
+ * pending a tree-diff mechanism; would need the previous tree's id set passed
190
+ * in to check "no id vanished and reappeared elsewhere," which is more than
191
+ * this slice's scope calls for.
192
+ */
193
+ export async function updateMenuTree(required, optional = {}) {
194
+ const { deps, input } = required;
195
+ const existing = await deps.repo.findById({ workspaceId: input.workspaceId, id: input.id });
196
+ if (!existing)
197
+ throw new MenuNotFoundError(`menu '${input.id}' was not found`);
198
+ if (existing.version !== input.expectedVersion) {
199
+ throw new MenuConflictError(`menu '${input.id}' was modified concurrently (expected version ${input.expectedVersion}, found ${existing.version})`);
200
+ }
201
+ const title = (input.title ?? existing.title).trim();
202
+ const slug = (input.slug ?? existing.slug).trim().toLowerCase();
203
+ assertValidTitleAndSlug(title, slug);
204
+ if (slug !== existing.slug) {
205
+ const duplicate = await deps.repo.findBySlug({ workspaceId: input.workspaceId, slug });
206
+ if (duplicate && duplicate.id !== existing.id) {
207
+ throw new MenuConflictError(`slug '${slug}' already exists`);
208
+ }
209
+ }
210
+ const items = validateAndCloneTree(input.items, optional.limits);
211
+ const menu = {
212
+ ...existing,
213
+ title,
214
+ slug,
215
+ doc: { type: NAV_DOC_TYPE, version: existing.doc.version, items },
216
+ updatedAt: deps.clock.nowIso(),
217
+ version: existing.version + 1,
218
+ };
219
+ await deps.repo.save(menu);
220
+ await deps.outbox.enqueue(buildEvent({
221
+ idGen: deps.idGen,
222
+ clock: deps.clock,
223
+ name: "navigation.menu.updated",
224
+ workspaceId: menu.workspaceId,
225
+ aggregateId: menu.id,
226
+ payload: { menuId: menu.id, slug: menu.slug },
227
+ }));
228
+ return { menu };
229
+ }
230
+ /**
231
+ * Assigns a menu to a theme location. This writes two
232
+ * representations that must stay in lockstep:
233
+ * 1. the menu's own `locations` field (source of truth, revisioned), and
234
+ * 2. the derived `nav_location_bindings` row (uniqueness index).
235
+ *
236
+ * If the location was already bound to a *different* menu, that menu is
237
+ * **reassigned away** (last-writer-wins, the chosen
238
+ * default) and its `locations` field is updated to drop the key — recorded as
239
+ * its own revision-worthy write.
240
+ *
241
+ * Atomicity note: these writes are
242
+ * logically ONE transaction — the binding-index write is a second in-tx
243
+ * participant alongside a slug-change-capture slot in the host's routing
244
+ * layer. Neither real cross-write transactions nor that routing layer exist
245
+ * as running code yet anywhere this library has shipped, so this function
246
+ * performs the writes sequentially with no rollback if a later step throws.
247
+ * This is an accepted, documented gap pending the command gateway's
248
+ * transaction machinery — do not copy this sequencing pattern into code that
249
+ * has real transactions available.
250
+ *
251
+ * @complexity O(1) repo calls (bounded: at most two menu reads/writes plus one
252
+ * binding upsert), independent of workspace size.
253
+ * @overallScore 90
254
+ * @findings Medium: no rollback across the two writes (menu save, then
255
+ * binding upsert) if the second fails, leaving the derived index stale until
256
+ * a rebuild. Acceptable because the index is declared rebuildable-by-definition;
257
+ * flagged as tech debt for when transactions
258
+ * exist.
259
+ */
260
+ export async function assignLocation(required, _optional = {}) {
261
+ const { deps, input } = required;
262
+ const menu = await deps.repo.findById({ workspaceId: input.workspaceId, id: input.menuId });
263
+ if (!menu)
264
+ throw new MenuNotFoundError(`menu '${input.menuId}' was not found`);
265
+ const now = deps.clock.nowIso();
266
+ const existingBinding = await deps.bindingRepo.findByLocation({
267
+ workspaceId: input.workspaceId,
268
+ locationKey: input.locationKey,
269
+ });
270
+ let displacedMenu = null;
271
+ if (existingBinding && existingBinding.menuId !== input.menuId) {
272
+ const displaced = await deps.repo.findById({
273
+ workspaceId: input.workspaceId,
274
+ id: existingBinding.menuId,
275
+ });
276
+ if (displaced) {
277
+ const updatedDisplaced = {
278
+ ...displaced,
279
+ locations: displaced.locations.filter((key) => key !== input.locationKey),
280
+ updatedAt: now,
281
+ version: displaced.version + 1,
282
+ };
283
+ await deps.repo.save(updatedDisplaced);
284
+ displacedMenu = updatedDisplaced;
285
+ }
286
+ }
287
+ const updatedMenu = {
288
+ ...menu,
289
+ locations: menu.locations.includes(input.locationKey)
290
+ ? menu.locations
291
+ : [...menu.locations, input.locationKey],
292
+ updatedAt: now,
293
+ version: menu.version + 1,
294
+ };
295
+ await deps.repo.save(updatedMenu);
296
+ const binding = await deps.bindingRepo.upsert({
297
+ workspaceId: input.workspaceId,
298
+ locationKey: input.locationKey,
299
+ menuId: input.menuId,
300
+ boundAt: now,
301
+ });
302
+ if (displacedMenu) {
303
+ await deps.outbox.enqueue(buildEvent({
304
+ idGen: deps.idGen,
305
+ clock: deps.clock,
306
+ name: "navigation.location.unassigned",
307
+ workspaceId: input.workspaceId,
308
+ aggregateId: displacedMenu.id,
309
+ payload: { locationKey: input.locationKey, menuId: displacedMenu.id },
310
+ }));
311
+ }
312
+ await deps.outbox.enqueue(buildEvent({
313
+ idGen: deps.idGen,
314
+ clock: deps.clock,
315
+ name: "navigation.location.assigned",
316
+ workspaceId: input.workspaceId,
317
+ aggregateId: input.menuId,
318
+ payload: { locationKey: input.locationKey, menuId: input.menuId },
319
+ }));
320
+ return { menu: updatedMenu, binding, displacedMenu };
321
+ }
322
+ /**
323
+ * Deletion ladder (mirrors the media library's):
324
+ * 1. First call on a non-trashed menu **soft-deletes** it (`status: 'trash'`,
325
+ * revisioned) and returns — no purge yet.
326
+ * 2. A second call on an already-trashed menu attempts the **hard purge**. If
327
+ * the menu is still bound to any location, purge is rejected with
328
+ * `MenuLocationBoundError` (409-style) listing the bound keys, unless
329
+ * `force` is set — permission-gating that error behind
330
+ * `navigation.delete.force` is the caller's (gateway's) job, not this
331
+ * function's; this function only enforces the *shape* of the guard.
332
+ * 3. On a successful purge, the menu row and all of its location bindings are
333
+ * removed.
334
+ *
335
+ * @complexity O(1) repo calls; O(k) bindings scanned where k = locations this
336
+ * menu holds (small, bounded by registered locations).
337
+ * @overallScore 100
338
+ */
339
+ export async function deleteMenu(required, _optional = {}) {
340
+ const { deps, input } = required;
341
+ const existing = await deps.repo.findById({ workspaceId: input.workspaceId, id: input.id });
342
+ if (!existing)
343
+ throw new MenuNotFoundError(`menu '${input.id}' was not found`);
344
+ if (existing.status !== "trash") {
345
+ const trashed = {
346
+ ...existing,
347
+ status: "trash",
348
+ updatedAt: deps.clock.nowIso(),
349
+ version: existing.version + 1,
350
+ };
351
+ await deps.repo.save(trashed);
352
+ await deps.outbox.enqueue(buildEvent({
353
+ idGen: deps.idGen,
354
+ clock: deps.clock,
355
+ name: "navigation.menu.updated",
356
+ workspaceId: trashed.workspaceId,
357
+ aggregateId: trashed.id,
358
+ payload: { menuId: trashed.id, slug: trashed.slug },
359
+ }));
360
+ return { menu: trashed, purged: false };
361
+ }
362
+ const bindings = await deps.bindingRepo.listByMenu({
363
+ workspaceId: input.workspaceId,
364
+ menuId: input.id,
365
+ });
366
+ if (bindings.length > 0 && !input.force) {
367
+ const boundLocations = bindings.map((row) => row.locationKey);
368
+ throw new MenuLocationBoundError(`menu '${input.id}' is still bound to location(s): ${boundLocations.join(", ")} — unassign before purging, or use force`, boundLocations);
369
+ }
370
+ await deps.repo.remove({ workspaceId: input.workspaceId, id: input.id });
371
+ await deps.bindingRepo.removeByMenu({ workspaceId: input.workspaceId, menuId: input.id });
372
+ await deps.outbox.enqueue(buildEvent({
373
+ idGen: deps.idGen,
374
+ clock: deps.clock,
375
+ name: "navigation.menu.deleted",
376
+ workspaceId: existing.workspaceId,
377
+ aggregateId: existing.id,
378
+ payload: { menuId: existing.id, slug: existing.slug },
379
+ }));
380
+ return { menu: null, purged: true };
381
+ }
382
+ //# sourceMappingURL=menu-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu-service.js","sourceRoot":"","sources":["../../src/navigation/menu-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * @file Ports + typed-call contracts for the `navigation` library.
3
+ *
4
+ * The rule-of-two applied honestly to navigation:
5
+ *
6
+ * - **`NavLocationBindingRepoPort` IS a port.** It persists the derived
7
+ * `nav_location_bindings` index and has two real adapters, one built now:
8
+ * in-memory (dev/tests) + SQLite (persistent, host-supplied) — the same shape
9
+ * every other repo in this library already follows.
10
+ *
11
+ * - **Menus themselves add NO new persistence port.** A menu is a generic
12
+ * entry; it rides the existing entries repo (in-memory + SQLite), which
13
+ * already passes rule-of-two. Inventing a `MenuRepoPort` would be a second
14
+ * store for data that already has one.
15
+ *
16
+ * - **`NavTargetResolver` is NOT a port — it is one evaluator.** Resolving a
17
+ * target ref to an href/label is ordinary core code over routing + entries +
18
+ * taxonomy (typed calls). There is exactly one production
19
+ * implementation, so — following the identity library's self-application of the rule-of-two to
20
+ * `authorize()` ("no PolicyPort; one evaluator") — it stays a plain typed-call
21
+ * contract, refactored into a port only if a second real resolver appears.
22
+ *
23
+ * INTERFACES ONLY. No feature logic lives here.
24
+ */
25
+ import type { ISODateTime, UUID } from "../core/ports.js";
26
+ import type { NavLocationBindingRow, NavLocationDescriptor, NavLocationKey, NavMenuDoc, NavMenuEntry, ResolvedNav } from "./types.js";
27
+ /**
28
+ * Persistence for the derived `nav_location_bindings` index. Writes happen only inside the same transaction as the menu-entry
29
+ * mutation that changed `locations` (single write chokepoint); this
30
+ * port is the storage seam, not a second write path. `rebuildForWorkspace`
31
+ * exists because the index is **rebuildable by definition** —
32
+ * a full rescan of menu entries can always reconstruct it.
33
+ */
34
+ export interface NavLocationBindingRepoPort {
35
+ /** The menu currently bound to a location, if any. */
36
+ findByLocation(required: {
37
+ workspaceId: UUID;
38
+ locationKey: NavLocationKey;
39
+ }): Promise<NavLocationBindingRow | null>;
40
+ /** All locations a given menu currently fills. */
41
+ listByMenu(required: {
42
+ workspaceId: UUID;
43
+ menuId: UUID;
44
+ }): Promise<NavLocationBindingRow[]>;
45
+ /** Every binding in the workspace (admin overview + render prefetch). */
46
+ listByWorkspace(required: {
47
+ workspaceId: UUID;
48
+ }): Promise<NavLocationBindingRow[]>;
49
+ /**
50
+ * Assign a location to a menu. Honors `UNIQUE (workspace_id, location_key)` —
51
+ * claiming a location already bound elsewhere **reassigns** it (last writer
52
+ * wins) and the caller records the displaced menu's revision through the
53
+ * chokepoint. Returns the row that now holds the binding.
54
+ */
55
+ upsert(required: {
56
+ workspaceId: UUID;
57
+ locationKey: NavLocationKey;
58
+ menuId: UUID;
59
+ boundAt: ISODateTime;
60
+ }): Promise<NavLocationBindingRow>;
61
+ /** Remove a single location binding (unassign). */
62
+ remove(required: {
63
+ workspaceId: UUID;
64
+ locationKey: NavLocationKey;
65
+ }): Promise<void>;
66
+ /** Drop every binding for a menu (menu purge). */
67
+ removeByMenu(required: {
68
+ workspaceId: UUID;
69
+ menuId: UUID;
70
+ }): Promise<void>;
71
+ /**
72
+ * Rebuild the whole workspace's index from the authoritative menu entries.
73
+ * The index is derived + rebuildable, so this is always safe.
74
+ */
75
+ rebuildForWorkspace(required: {
76
+ workspaceId: UUID;
77
+ bindings: readonly NavLocationBindingRow[];
78
+ }): Promise<void>;
79
+ }
80
+ /** Context needed to compute hrefs + active-state during resolution. */
81
+ export interface NavResolveContext {
82
+ readonly workspaceId: UUID;
83
+ /**
84
+ * The current request route/path, used to compute `isCurrent`/`isActive`.
85
+ * Absent for non-request resolution (e.g. an AI preview).
86
+ */
87
+ readonly currentPath?: string | undefined;
88
+ }
89
+ /**
90
+ * Resolves a stored `NavMenuDoc` into a render-ready `ResolvedNav` — targets to
91
+ * hrefs, labels filled from targets, active-state computed, unavailable targets
92
+ * flagged. One production evaluator (routing + entries + taxonomy typed calls),
93
+ * so this is a contract, not a port (see file header). The theme receives only
94
+ * the resolved data.
95
+ */
96
+ export interface NavTargetResolver {
97
+ resolve(required: {
98
+ context: NavResolveContext;
99
+ menuId: UUID;
100
+ locationKey: NavLocationKey;
101
+ title: string;
102
+ doc: NavMenuDoc;
103
+ }): Promise<ResolvedNav>;
104
+ }
105
+ /**
106
+ * The navigation library's public read surface over the entries repo, exposed as
107
+ * typed calls so callers (theme renderer, routing, AI tools) never
108
+ * reach into storage. Reuses the entries repo underneath — adds no new port.
109
+ */
110
+ export interface NavMenuReadModel {
111
+ /** Load a menu entry as the typed navigation projection. */
112
+ getMenu(required: {
113
+ workspaceId: UUID;
114
+ menuId: UUID;
115
+ }): Promise<NavMenuEntry | null>;
116
+ getMenuBySlug(required: {
117
+ workspaceId: UUID;
118
+ slug: string;
119
+ }): Promise<NavMenuEntry | null>;
120
+ listMenus(required: {
121
+ workspaceId: UUID;
122
+ }): Promise<NavMenuEntry[]>;
123
+ /**
124
+ * Resolve the menu bound to a theme location, already rendered to
125
+ * `ResolvedNav`. Returns `null` when the location has no menu. This is the one
126
+ * call the theme renderer makes.
127
+ */
128
+ resolveForLocation(required: {
129
+ context: NavResolveContext;
130
+ locationKey: NavLocationKey;
131
+ }): Promise<ResolvedNav | null>;
132
+ }
133
+ /**
134
+ * Registry of theme/plugin-declared locations (populated by the
135
+ * `navigation.locations.register` hook). Read-only lookup; the
136
+ * writable side is the hook, not this contract.
137
+ */
138
+ export interface NavLocationRegistry {
139
+ list(required: {
140
+ workspaceId: UUID;
141
+ }): NavLocationDescriptor[];
142
+ get(required: {
143
+ workspaceId: UUID;
144
+ key: NavLocationKey;
145
+ }): NavLocationDescriptor | null;
146
+ }
147
+ //# sourceMappingURL=ports.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../src/navigation/ports.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ports.js","sourceRoot":"","sources":["../../src/navigation/ports.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import type { NavLocationBindingRepoPort, NavMenuReadModel } from "./ports.js";
2
+ import type { MenuRepoPort } from "./repo.memory.js";
3
+ import { type ResolveTargetHrefFn } from "./resolver.js";
4
+ export interface NavMenuReadModelDeps {
5
+ menuRepo: MenuRepoPort;
6
+ bindingRepo: NavLocationBindingRepoPort;
7
+ /** Overridable for tests / once a host's routing library lands; defaults to the honest placeholder documented above. */
8
+ resolveTargetHref?: ResolveTargetHrefFn | undefined;
9
+ }
10
+ export declare function createNavMenuReadModel(deps: NavMenuReadModelDeps): NavMenuReadModel;
11
+ //# sourceMappingURL=read-model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-model.d.ts","sourceRoot":"","sources":["../../src/navigation/read-model.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,0BAA0B,EAAE,gBAAgB,EAAqB,MAAM,YAAY,CAAC;AAClG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAsB,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAG7E,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,YAAY,CAAC;IACvB,WAAW,EAAE,0BAA0B,CAAC;IACxC,wHAAwH;IACxH,iBAAiB,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;CACrD;AAID,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,gBAAgB,CA2BnF"}
@@ -0,0 +1,27 @@
1
+ import { resolveForLocation } from "./resolver.js";
2
+ const DEFAULT_RESOLVE_TARGET_HREF = async () => null;
3
+ export function createNavMenuReadModel(deps) {
4
+ const resolveTargetHref = deps.resolveTargetHref ?? DEFAULT_RESOLVE_TARGET_HREF;
5
+ return {
6
+ async getMenu(required) {
7
+ return deps.menuRepo.findById({ workspaceId: required.workspaceId, id: required.menuId });
8
+ },
9
+ async getMenuBySlug(required) {
10
+ return deps.menuRepo.findBySlug(required);
11
+ },
12
+ async listMenus(required) {
13
+ return deps.menuRepo.list(required);
14
+ },
15
+ async resolveForLocation(required) {
16
+ return resolveForLocation({
17
+ deps: { menuRepo: deps.menuRepo, bindingRepo: deps.bindingRepo, resolveTargetHref },
18
+ input: {
19
+ workspaceId: required.context.workspaceId,
20
+ locationKey: required.locationKey,
21
+ currentPath: required.context.currentPath,
22
+ },
23
+ });
24
+ },
25
+ };
26
+ }
27
+ //# sourceMappingURL=read-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-model.js","sourceRoot":"","sources":["../../src/navigation/read-model.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,kBAAkB,EAA4B,MAAM,eAAe,CAAC;AAU7E,MAAM,2BAA2B,GAAwB,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC;AAE1E,MAAM,UAAU,sBAAsB,CAAC,IAA0B;IAC/D,MAAM,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,IAAI,2BAA2B,CAAC;IAEhF,OAAO;QACL,KAAK,CAAC,OAAO,CAAC,QAA6C;YACzD,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,EAAE,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5F,CAAC;QAED,KAAK,CAAC,aAAa,CAAC,QAA6C;YAC/D,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC;QAED,KAAK,CAAC,SAAS,CAAC,QAA+B;YAC7C,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtC,CAAC;QAED,KAAK,CAAC,kBAAkB,CAAC,QAAqE;YAC5F,OAAO,kBAAkB,CAAC;gBACxB,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,iBAAiB,EAAE;gBACnF,KAAK,EAAE;oBACL,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,WAAW;oBACzC,WAAW,EAAE,QAAQ,CAAC,WAAW;oBACjC,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,WAAW;iBAC1C;aACF,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}