superacli 1.1.22 → 1.1.26

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 (257) hide show
  1. package/.beads/.br_history/{issues.20260427_104638_898729442.jsonl → issues.20260427_114912_061702372.jsonl} +65 -65
  2. package/.beads/.br_history/{issues.20260427_104638_209211116.jsonl → issues.20260427_115013_063113906.jsonl} +66 -66
  3. package/.beads/.br_history/{issues.20260427_104637_752744777.jsonl → issues.20260427_115114_208497343.jsonl} +67 -67
  4. package/.beads/.br_history/{issues.20260427_104615_669652069.jsonl → issues.20260427_115215_176080241.jsonl} +68 -68
  5. package/.beads/.br_history/issues.20260427_115316_481573328.jsonl +261 -0
  6. package/.beads/.br_history/issues.20260427_115335_866978652.jsonl +261 -0
  7. package/.beads/.br_history/issues.20260427_115436_866087391.jsonl +261 -0
  8. package/.beads/.br_history/issues.20260427_115538_016094860.jsonl +261 -0
  9. package/.beads/.br_history/issues.20260427_115638_932947449.jsonl +261 -0
  10. package/.beads/.br_history/issues.20260427_115739_982932603.jsonl +261 -0
  11. package/.beads/.br_history/issues.20260427_115840_963681039.jsonl +261 -0
  12. package/.beads/.br_history/issues.20260427_115941_912431509.jsonl +261 -0
  13. package/.beads/.br_history/issues.20260427_120043_043356448.jsonl +261 -0
  14. package/.beads/.br_history/issues.20260427_120144_955596968.jsonl +261 -0
  15. package/.beads/.br_history/issues.20260427_120246_060733977.jsonl +261 -0
  16. package/.beads/.br_history/issues.20260427_120307_717985017.jsonl +261 -0
  17. package/.beads/.br_history/issues.20260427_120408_871846736.jsonl +261 -0
  18. package/.beads/.br_history/issues.20260427_121003_963750732.jsonl +261 -0
  19. package/.beads/.br_history/issues.20260427_121006_018509431.jsonl +261 -0
  20. package/.beads/.br_history/issues.20260427_121019_617062931.jsonl +261 -0
  21. package/.beads/.br_history/issues.20260427_121021_689536311.jsonl +261 -0
  22. package/.beads/.br_history/issues.20260428_172005_240631447.jsonl +261 -0
  23. package/.beads/.br_history/issues.20260430_073641_144807989.jsonl +262 -0
  24. package/.beads/.br_history/issues.20260430_073642_807075699.jsonl +263 -0
  25. package/.beads/.br_history/issues.20260430_073645_625754223.jsonl +264 -0
  26. package/.beads/.br_history/issues.20260430_090639_154646058.jsonl +265 -0
  27. package/.beads/.br_history/issues.20260430_090640_350560318.jsonl +266 -0
  28. package/.beads/.br_history/issues.20260430_090641_509319001.jsonl +267 -0
  29. package/.beads/.br_history/issues.20260430_095140_396749398.jsonl +268 -0
  30. package/.beads/.br_history/issues.20260501_230041_334056077.jsonl +269 -0
  31. package/.beads/.br_recovery/beads.db-wal.20260427_121006_010373120.rebuild-failed +0 -0
  32. package/.beads/.br_recovery/beads.db.20260427_121006_010373120.rebuild-failed +0 -0
  33. package/.beads/beads.db.corrupted +0 -0
  34. package/.beads/issues.jsonl +46 -37
  35. package/.supercli/adapters/test-cli-adapter.js +19 -0
  36. package/cli/adapters/mcp.js +89 -3
  37. package/cli/adapters/openapi.js +71 -2
  38. package/cli/config.js +69 -1
  39. package/cli/daemon.js +349 -0
  40. package/cli/plugins-manager.js +41 -1
  41. package/cli/server-command.js +174 -4
  42. package/cli/supercli.js +35 -15
  43. package/docs/changelog-2026-04.html +6 -0
  44. package/docs/index.html +95 -8
  45. package/docs/plugins.html +30 -0
  46. package/docs/server.md +80 -0
  47. package/graphify-out/GRAPH_REPORT.md +140 -128
  48. package/graphify-out/cache/036077d325d5aa25fc6ad7f01ca32721b02e3f981231f67fb22f59380063572b.json +1 -0
  49. package/graphify-out/cache/11938479cfbdb8e52bf5f0f3c132d56204245ebb19aefe89bb0394feb36dbd5e.json +1 -0
  50. package/graphify-out/cache/141362b25039dee7a4959ef475befea0a25671aae66f3d14917e711e597ffbf6.json +1 -0
  51. package/graphify-out/cache/362adb1b6b483f56d09feaf652f4122366e568aaede752f48383b76d61f5d9d6.json +1 -0
  52. package/graphify-out/cache/42bc8f64d69d2cd9ecf64e92e38f89f7ea479f69c947de5984919e2fd5a716ee.json +1 -0
  53. package/graphify-out/cache/4b5cffce31d9193b7d0a8f15e8a41c66f6733a6490ebaeff2c8ca19701c72c0e.json +1 -0
  54. package/graphify-out/cache/5262fb95a8855fc90efbfff767eb3aacca82c4da5799605a969554580a255404.json +1 -0
  55. package/graphify-out/cache/5ef4e31750d9e7bc4ff4a7b535f247d9ab5ab9627d72e20794779ec4be424c66.json +1 -0
  56. package/graphify-out/cache/68e2b11c95ede4f05b88d001040008cb3ac72d7bd27f351497c87e128fb3b221.json +1 -0
  57. package/graphify-out/cache/6d5023ecffa52382d31152c8c06e86e286789228a3d4f7fde72087f3eafa11bc.json +1 -0
  58. package/graphify-out/cache/6e5776e123142a78f50fa0bfd5ae2d289282051a9b392ae507de7aa9017f95d4.json +1 -0
  59. package/graphify-out/cache/75982dc60fa7353600ca48a3b33f5ba497eea9d5743daac6e61e9cf4f64774be.json +1 -0
  60. package/graphify-out/cache/7796066b51d3a99071debdfb5f40c854400b5bf3aa7c1e83dd6ae88eddca0370.json +1 -0
  61. package/graphify-out/cache/8308aa47b396b929d5b896051ca91422afdde4861108d6f18f5094901093df79.json +1 -0
  62. package/graphify-out/cache/8ccd3b557a1ea98005fba84433f160ccd4a951fbdb6a4c9b7d7ba894f905b06b.json +1 -0
  63. package/graphify-out/cache/90ab53b8f1f3306e7c3a1f92ec628717ea90f4e684db764f7d7aa8e884fe2cae.json +1 -0
  64. package/graphify-out/cache/9832101a7622924f58b9e7d7752b41518049447171f7955e4c50dfd386574e12.json +1 -0
  65. package/graphify-out/cache/9fa6604cc820f3857c55c753ca0024788e4cbb61c4e12ba7ce0e4a1ce4ee0655.json +1 -0
  66. package/graphify-out/cache/a1e24a07beede2876e688cdb6c14e2d24abb22064862a6420cac321efabd3efd.json +1 -0
  67. package/graphify-out/cache/a418312f2805259c33007a18b36b6ae3b6a4da376ccae6006a3b9999262495db.json +1 -0
  68. package/graphify-out/cache/a6d9c029bd31a99b67357291305e27b01c5ef388925f7f2a6e985fec4efa8024.json +1 -0
  69. package/graphify-out/cache/a6ed52b709dd79f98adf72c483e8dfb6098203d7327470b82feb5e11390a5cf4.json +1 -0
  70. package/graphify-out/cache/b045ae4443d972ee8f47b91a0d61c984a190195b38ae1d331430b4c51c43acfd.json +1 -0
  71. package/graphify-out/cache/b849fb88344c2f88f3d22e42b67516e071c7d1e65f77f4ca23f25af6edfca3b3.json +1 -0
  72. package/graphify-out/cache/bc514f4074f89d2f7e7834670602e50bba0f24b8cd8c9d21ff4d361d3fd4d558.json +1 -0
  73. package/graphify-out/cache/be3fc87936f9f24d2d4f4b22b9d2a16f33f538cef1a181663120e23ecf16b81a.json +1 -0
  74. package/graphify-out/cache/c5a4822edbe3a95a56f9f943eed1567e5a5c913d59b1fa3df4ad54ffd9b02697.json +1 -0
  75. package/graphify-out/cache/cf411f1ddde50ee97c1c501f59ed7985bcdc022134574816bcce37ac20848e64.json +1 -0
  76. package/graphify-out/cache/d88625b5813742ca941ce8155cb77afb02425632002f621aca34f217440a392d.json +1 -0
  77. package/graphify-out/cache/da97fdc8af2a3306c292921110f84648bba2b0e85d27473b460b0e8a862ff225.json +1 -0
  78. package/graphify-out/cache/e88de9f1ae117f26fd217c3717eff7e525a284cc942b5f4d26ef2c4d65db59bd.json +1 -0
  79. package/graphify-out/cache/ebf6bd96ef2d8d396389ac7199e6ba818ee2d0c5dfc131fab7cdece9fb710f11.json +1 -0
  80. package/graphify-out/cache/f2a302550a6fe0649d36b8ef0b04b77673bca9f115732af8ae89751944dc9cc6.json +1 -0
  81. package/graphify-out/cache/f9ee11f4395cb41b6f6900079cb7e94297c89b1b0b4798398d2f7a2e244c683b.json +1 -0
  82. package/graphify-out/cache/fb46bd3ef530273918fc8915842453f21b418d536653d3b705b75b417255c246.json +1 -0
  83. package/graphify-out/cache/fcfdab94fe91af1f21fcefdba5a96674b9a16bb768288f3573fe68765163c765.json +1 -0
  84. package/graphify-out/graph.json +2420 -1157
  85. package/package.json +1 -1
  86. package/plugins/bluebuild/install-guidance.json +11 -0
  87. package/plugins/bluebuild/meta.json +5 -0
  88. package/plugins/bluebuild/plugin.json +99 -0
  89. package/plugins/bluebuild/skills/quickstart/SKILL.md +47 -0
  90. package/plugins/cargo-public-api/install-guidance.json +11 -0
  91. package/plugins/cargo-public-api/meta.json +5 -0
  92. package/plugins/cargo-public-api/plugin.json +88 -0
  93. package/plugins/cargo-public-api/skills/quickstart/SKILL.md +51 -0
  94. package/plugins/context-mode/plugin.json +10 -0
  95. package/plugins/context-mode/scripts/post-install.js +1 -1
  96. package/plugins/csview/install-guidance.json +11 -0
  97. package/plugins/csview/meta.json +5 -0
  98. package/plugins/csview/plugin.json +67 -0
  99. package/plugins/csview/skills/quickstart/SKILL.md +51 -0
  100. package/plugins/cymbal/install-guidance.json +11 -0
  101. package/plugins/cymbal/meta.json +5 -0
  102. package/plugins/cymbal/plugin.json +121 -0
  103. package/plugins/cymbal/skills/quickstart/SKILL.md +54 -0
  104. package/plugins/difftastic/install-guidance.json +11 -0
  105. package/plugins/difftastic/meta.json +5 -0
  106. package/plugins/difftastic/plugin.json +87 -0
  107. package/plugins/difftastic/skills/quickstart/SKILL.md +53 -0
  108. package/plugins/dlm/install-guidance.json +11 -0
  109. package/plugins/dlm/meta.json +5 -0
  110. package/plugins/dlm/plugin.json +85 -0
  111. package/plugins/dlm/skills/quickstart/SKILL.md +49 -0
  112. package/plugins/dofigen/install-guidance.json +11 -0
  113. package/plugins/dofigen/meta.json +5 -0
  114. package/plugins/dofigen/plugin.json +84 -0
  115. package/plugins/dofigen/skills/quickstart/SKILL.md +50 -0
  116. package/plugins/example-server-resources/meta.json +11 -0
  117. package/plugins/example-server-resources/plugin.json +46 -0
  118. package/plugins/http-nu/install-guidance.json +11 -0
  119. package/plugins/http-nu/meta.json +5 -0
  120. package/plugins/http-nu/plugin.json +84 -0
  121. package/plugins/http-nu/skills/quickstart/SKILL.md +52 -0
  122. package/plugins/hwatch/install-guidance.json +11 -0
  123. package/plugins/hwatch/meta.json +5 -0
  124. package/plugins/hwatch/plugin.json +100 -0
  125. package/plugins/hwatch/skills/quickstart/SKILL.md +54 -0
  126. package/plugins/hyperfine/install-guidance.json +3 -3
  127. package/plugins/hyperfine/meta.json +2 -2
  128. package/plugins/hyperfine/plugin.json +39 -16
  129. package/plugins/hyperfine/skills/quickstart/SKILL.md +33 -61
  130. package/plugins/json5/install-guidance.json +12 -0
  131. package/plugins/json5/meta.json +5 -0
  132. package/plugins/json5/plugin.json +88 -0
  133. package/plugins/json5/skills/quickstart/SKILL.md +55 -0
  134. package/plugins/mdsf/install-guidance.json +11 -0
  135. package/plugins/mdsf/meta.json +5 -0
  136. package/plugins/mdsf/plugin.json +101 -0
  137. package/plugins/mdsf/skills/quickstart/SKILL.md +55 -0
  138. package/plugins/oha/install-guidance.json +11 -0
  139. package/plugins/oha/meta.json +5 -0
  140. package/plugins/oha/plugin.json +67 -0
  141. package/plugins/oha/skills/quickstart/SKILL.md +44 -0
  142. package/plugins/pv-migrate/install-guidance.json +11 -0
  143. package/plugins/pv-migrate/meta.json +5 -0
  144. package/plugins/pv-migrate/plugin.json +102 -0
  145. package/plugins/pv-migrate/skills/quickstart/SKILL.md +58 -0
  146. package/plugins/rash/install-guidance.json +11 -0
  147. package/plugins/rash/meta.json +5 -0
  148. package/plugins/rash/plugin.json +85 -0
  149. package/plugins/rash/skills/quickstart/SKILL.md +46 -0
  150. package/plugins/rsonpath/install-guidance.json +11 -0
  151. package/plugins/rsonpath/meta.json +5 -0
  152. package/plugins/rsonpath/plugin.json +87 -0
  153. package/plugins/rsonpath/skills/quickstart/SKILL.md +44 -0
  154. package/plugins/rsql/install-guidance.json +11 -0
  155. package/plugins/rsql/meta.json +5 -0
  156. package/plugins/rsql/plugin.json +84 -0
  157. package/plugins/rsql/skills/quickstart/SKILL.md +52 -0
  158. package/plugins/temporal/install-guidance.json +11 -0
  159. package/plugins/temporal/meta.json +5 -0
  160. package/plugins/temporal/plugin.json +95 -0
  161. package/plugins/temporal/skills/quickstart/SKILL.md +49 -0
  162. package/plugins/tkn/install-guidance.json +11 -0
  163. package/plugins/tkn/meta.json +5 -0
  164. package/plugins/tkn/plugin.json +98 -0
  165. package/plugins/tkn/skills/quickstart/SKILL.md +50 -0
  166. package/plugins/toml2json/install-guidance.json +11 -0
  167. package/plugins/toml2json/meta.json +5 -0
  168. package/plugins/toml2json/plugin.json +85 -0
  169. package/plugins/toml2json/skills/quickstart/SKILL.md +47 -0
  170. package/plugins/worktrunk/install-guidance.json +11 -0
  171. package/plugins/worktrunk/meta.json +5 -0
  172. package/plugins/worktrunk/plugin.json +116 -0
  173. package/plugins/worktrunk/skills/quickstart/SKILL.md +62 -0
  174. package/server/app.js +46 -13
  175. package/server/middleware/auth.js +70 -0
  176. package/server/routes/adapters.js +3 -11
  177. package/server/routes/clients.js +46 -0
  178. package/server/routes/docs.js +10 -0
  179. package/server/routes/jobs.js +3 -2
  180. package/server/routes/mcp.js +1 -0
  181. package/server/routes/plugins.js +109 -26
  182. package/server/routes/settings.js +93 -0
  183. package/server/routes/specs.js +8 -3
  184. package/server/services/adaptersService.js +1 -0
  185. package/server/services/pluginResourceService.js +262 -0
  186. package/server/services/pluginsService.js +24 -0
  187. package/server/uploads/superbackend-openapi.json +47 -0
  188. package/server/uploads/test-auth-openapi.json +74 -0
  189. package/server/uploads/test-auth-spec.json +36 -0
  190. package/server/views/adapters.ejs +1 -0
  191. package/server/views/api-keys.ejs +147 -0
  192. package/server/views/clients.ejs +82 -0
  193. package/server/views/docs.ejs +7 -0
  194. package/server/views/jobs.ejs +26 -2
  195. package/server/views/layout.ejs +35 -21
  196. package/server/views/mcp.ejs +278 -21
  197. package/server/views/partials/head.ejs +4 -0
  198. package/server/views/plugins.ejs +33 -32
  199. package/server/views/settings.ejs +99 -0
  200. package/server/views/specs.ejs +217 -22
  201. package/.beads/.br_history/issues.20260427_103259_082222986.jsonl +0 -261
  202. package/.beads/.br_history/issues.20260427_103400_358332602.jsonl +0 -261
  203. package/.beads/.br_history/issues.20260427_103419_681839669.jsonl +0 -261
  204. package/.beads/.br_history/issues.20260427_103522_226669683.jsonl +0 -261
  205. package/.beads/.br_history/issues.20260427_103623_568379011.jsonl +0 -261
  206. package/.beads/.br_history/issues.20260427_103724_772051154.jsonl +0 -261
  207. package/.beads/.br_history/issues.20260427_103825_935228905.jsonl +0 -261
  208. package/.beads/.br_history/issues.20260427_103927_159626780.jsonl +0 -261
  209. package/.beads/.br_history/issues.20260427_104028_436388960.jsonl +0 -261
  210. package/.beads/.br_history/issues.20260427_104129_670562810.jsonl +0 -261
  211. package/.beads/.br_history/issues.20260427_104230_885162615.jsonl +0 -261
  212. package/.beads/.br_history/issues.20260427_104332_071213892.jsonl +0 -261
  213. package/.beads/.br_history/issues.20260427_104349_051129644.jsonl +0 -261
  214. package/.beads/.br_history/issues.20260427_104450_358444507.jsonl +0 -261
  215. package/.beads/.br_history/issues.20260427_104555_654123963.jsonl +0 -261
  216. package/.beads/.br_history/issues.20260427_104559_805009051.jsonl +0 -261
  217. package/.beads/.br_history/issues.20260427_104600_255068030.jsonl +0 -261
  218. package/.beads/.br_history/issues.20260427_104600_717042012.jsonl +0 -261
  219. package/.beads/.br_history/issues.20260427_104601_215845416.jsonl +0 -261
  220. package/.beads/.br_history/issues.20260427_104601_899140331.jsonl +0 -261
  221. package/.beads/.br_history/issues.20260427_104606_172300551.jsonl +0 -261
  222. package/.beads/.br_history/issues.20260427_104606_658098709.jsonl +0 -261
  223. package/.beads/.br_history/issues.20260427_104607_085798670.jsonl +0 -261
  224. package/.beads/.br_history/issues.20260427_104607_627598880.jsonl +0 -261
  225. package/.beads/.br_history/issues.20260427_104608_071298223.jsonl +0 -261
  226. package/.beads/.br_history/issues.20260427_104615_198124329.jsonl +0 -261
  227. package/scripts/post-tweet-issues.js +0 -161
  228. /package/.beads/.br_history/{issues.20260427_103259_082222986.jsonl.meta.json → issues.20260427_114912_061702372.jsonl.meta.json} +0 -0
  229. /package/.beads/.br_history/{issues.20260427_103400_358332602.jsonl.meta.json → issues.20260427_115013_063113906.jsonl.meta.json} +0 -0
  230. /package/.beads/.br_history/{issues.20260427_103419_681839669.jsonl.meta.json → issues.20260427_115114_208497343.jsonl.meta.json} +0 -0
  231. /package/.beads/.br_history/{issues.20260427_103522_226669683.jsonl.meta.json → issues.20260427_115215_176080241.jsonl.meta.json} +0 -0
  232. /package/.beads/.br_history/{issues.20260427_103623_568379011.jsonl.meta.json → issues.20260427_115316_481573328.jsonl.meta.json} +0 -0
  233. /package/.beads/.br_history/{issues.20260427_103724_772051154.jsonl.meta.json → issues.20260427_115335_866978652.jsonl.meta.json} +0 -0
  234. /package/.beads/.br_history/{issues.20260427_103825_935228905.jsonl.meta.json → issues.20260427_115436_866087391.jsonl.meta.json} +0 -0
  235. /package/.beads/.br_history/{issues.20260427_103927_159626780.jsonl.meta.json → issues.20260427_115538_016094860.jsonl.meta.json} +0 -0
  236. /package/.beads/.br_history/{issues.20260427_104028_436388960.jsonl.meta.json → issues.20260427_115638_932947449.jsonl.meta.json} +0 -0
  237. /package/.beads/.br_history/{issues.20260427_104129_670562810.jsonl.meta.json → issues.20260427_115739_982932603.jsonl.meta.json} +0 -0
  238. /package/.beads/.br_history/{issues.20260427_104230_885162615.jsonl.meta.json → issues.20260427_115840_963681039.jsonl.meta.json} +0 -0
  239. /package/.beads/.br_history/{issues.20260427_104332_071213892.jsonl.meta.json → issues.20260427_115941_912431509.jsonl.meta.json} +0 -0
  240. /package/.beads/.br_history/{issues.20260427_104349_051129644.jsonl.meta.json → issues.20260427_120043_043356448.jsonl.meta.json} +0 -0
  241. /package/.beads/.br_history/{issues.20260427_104450_358444507.jsonl.meta.json → issues.20260427_120144_955596968.jsonl.meta.json} +0 -0
  242. /package/.beads/.br_history/{issues.20260427_104555_654123963.jsonl.meta.json → issues.20260427_120246_060733977.jsonl.meta.json} +0 -0
  243. /package/.beads/.br_history/{issues.20260427_104559_805009051.jsonl.meta.json → issues.20260427_120307_717985017.jsonl.meta.json} +0 -0
  244. /package/.beads/.br_history/{issues.20260427_104600_255068030.jsonl.meta.json → issues.20260427_120408_871846736.jsonl.meta.json} +0 -0
  245. /package/.beads/.br_history/{issues.20260427_104600_717042012.jsonl.meta.json → issues.20260427_121003_963750732.jsonl.meta.json} +0 -0
  246. /package/.beads/.br_history/{issues.20260427_104601_215845416.jsonl.meta.json → issues.20260427_121006_018509431.jsonl.meta.json} +0 -0
  247. /package/.beads/.br_history/{issues.20260427_104601_899140331.jsonl.meta.json → issues.20260427_121019_617062931.jsonl.meta.json} +0 -0
  248. /package/.beads/.br_history/{issues.20260427_104606_172300551.jsonl.meta.json → issues.20260427_121021_689536311.jsonl.meta.json} +0 -0
  249. /package/.beads/.br_history/{issues.20260427_104606_658098709.jsonl.meta.json → issues.20260428_172005_240631447.jsonl.meta.json} +0 -0
  250. /package/.beads/.br_history/{issues.20260427_104607_085798670.jsonl.meta.json → issues.20260430_073641_144807989.jsonl.meta.json} +0 -0
  251. /package/.beads/.br_history/{issues.20260427_104607_627598880.jsonl.meta.json → issues.20260430_073642_807075699.jsonl.meta.json} +0 -0
  252. /package/.beads/.br_history/{issues.20260427_104608_071298223.jsonl.meta.json → issues.20260430_073645_625754223.jsonl.meta.json} +0 -0
  253. /package/.beads/.br_history/{issues.20260427_104615_198124329.jsonl.meta.json → issues.20260430_090639_154646058.jsonl.meta.json} +0 -0
  254. /package/.beads/.br_history/{issues.20260427_104615_669652069.jsonl.meta.json → issues.20260430_090640_350560318.jsonl.meta.json} +0 -0
  255. /package/.beads/.br_history/{issues.20260427_104637_752744777.jsonl.meta.json → issues.20260430_090641_509319001.jsonl.meta.json} +0 -0
  256. /package/.beads/.br_history/{issues.20260427_104638_209211116.jsonl.meta.json → issues.20260430_095140_396749398.jsonl.meta.json} +0 -0
  257. /package/.beads/.br_history/{issues.20260427_104638_898729442.jsonl.meta.json → issues.20260501_230041_334056077.jsonl.meta.json} +0 -0
@@ -10,6 +10,10 @@ const {
10
10
  removeServerPlugin,
11
11
  getPluginArchiveBuffer,
12
12
  } = require("../services/pluginsService")
13
+ const { getStorage } = require("../storage/adapter")
14
+ const { registerPluginResources, unregisterPluginResources } = require("../services/pluginResourceService")
15
+ const { bumpVersion } = require("../services/configService")
16
+ const { requireAuth } = require("../middleware/auth")
13
17
 
14
18
  const router = Router()
15
19
 
@@ -147,7 +151,7 @@ async function parseMultipartFormData(req) {
147
151
  }
148
152
  }
149
153
 
150
- router.get("/", async (req, res) => {
154
+ router.get("/", requireAuth, async (req, res) => {
151
155
  try {
152
156
  const plugins = await listServerPlugins()
153
157
  const settings = await getSettings()
@@ -160,25 +164,7 @@ router.get("/", async (req, res) => {
160
164
  }
161
165
  })
162
166
 
163
- router.get("/settings", async (req, res) => {
164
- try {
165
- const settings = await getSettings()
166
- res.json(settings)
167
- } catch (err) {
168
- handleError(res, err)
169
- }
170
- })
171
-
172
- router.put("/settings", async (req, res) => {
173
- try {
174
- const settings = await updateSettings(req.body || {})
175
- res.json({ ok: true, settings })
176
- } catch (err) {
177
- handleError(res, err)
178
- }
179
- })
180
-
181
- router.post("/", async (req, res) => {
167
+ router.post("/", requireAuth, async (req, res) => {
182
168
  try {
183
169
  const sourceType = String((req.body && req.body.source_type) || "json").trim().toLowerCase()
184
170
  const plugin = sourceType === "zip"
@@ -190,7 +176,7 @@ router.post("/", async (req, res) => {
190
176
  }
191
177
  })
192
178
 
193
- router.post("/upload", async (req, res) => {
179
+ router.post("/upload", requireAuth, async (req, res) => {
194
180
  try {
195
181
  const contentType = String(req.headers["content-type"] || "")
196
182
  const payload = contentType.includes("multipart/form-data")
@@ -203,7 +189,7 @@ router.post("/upload", async (req, res) => {
203
189
  }
204
190
  })
205
191
 
206
- router.get("/:name", async (req, res) => {
192
+ router.get("/:name", requireAuth, async (req, res) => {
207
193
  try {
208
194
  const plugin = await getServerPlugin(req.params.name)
209
195
  if (!plugin) {
@@ -215,7 +201,7 @@ router.get("/:name", async (req, res) => {
215
201
  }
216
202
  })
217
203
 
218
- router.patch("/:name", async (req, res) => {
204
+ router.patch("/:name", requireAuth, async (req, res) => {
219
205
  try {
220
206
  const plugin = await updatePluginMetadata(req.params.name, req.body || {})
221
207
  res.json({ ok: true, plugin })
@@ -224,7 +210,7 @@ router.patch("/:name", async (req, res) => {
224
210
  }
225
211
  })
226
212
 
227
- router.delete("/:name", async (req, res) => {
213
+ router.delete("/:name", requireAuth, async (req, res) => {
228
214
  try {
229
215
  const removed = await removeServerPlugin(req.params.name)
230
216
  res.json({ ok: true, removed })
@@ -233,7 +219,7 @@ router.delete("/:name", async (req, res) => {
233
219
  }
234
220
  })
235
221
 
236
- router.get("/:name/manifest", async (req, res) => {
222
+ router.get("/:name/manifest", requireAuth, async (req, res) => {
237
223
  try {
238
224
  const plugin = await getServerPlugin(req.params.name)
239
225
  if (!plugin) {
@@ -245,7 +231,7 @@ router.get("/:name/manifest", async (req, res) => {
245
231
  }
246
232
  })
247
233
 
248
- router.get("/:name/archive", async (req, res) => {
234
+ router.get("/:name/archive", requireAuth, async (req, res) => {
249
235
  try {
250
236
  const archive = await getPluginArchiveBuffer(req.params.name)
251
237
  if (!archive) {
@@ -259,4 +245,101 @@ router.get("/:name/archive", async (req, res) => {
259
245
  }
260
246
  })
261
247
 
248
+ router.post("/client-resources", requireAuth, async (req, res) => {
249
+ try {
250
+ const storage = getStorage()
251
+ const { client_id, plugins } = req.body || {}
252
+
253
+ if (!Array.isArray(plugins)) {
254
+ return res.status(400).json({ error: "plugins must be an array", type: "invalid_argument" })
255
+ }
256
+
257
+ if (!client_id || typeof client_id !== "string") {
258
+ return res.status(400).json({ error: "client_id is required", type: "invalid_argument" })
259
+ }
260
+
261
+ // Update client last_seen
262
+ await storage.set(`client:${client_id}`, {
263
+ client_id: client_id,
264
+ last_seen: new Date(),
265
+ plugin_count: plugins.length
266
+ })
267
+
268
+ // Remove existing cli resources from this specific client only
269
+ const allMcpKeys = await storage.listKeys("mcp:")
270
+ const allSpecKeys = await storage.listKeys("spec:")
271
+ const clientMcpKeys = allMcpKeys.filter(k => k.startsWith(`mcp:cli:${client_id}:`))
272
+ const clientSpecKeys = allSpecKeys.filter(k => k.startsWith(`spec:cli:${client_id}:`))
273
+
274
+ // Remove this client's existing resources
275
+ for (const key of clientMcpKeys) {
276
+ await storage.delete(key)
277
+ }
278
+ for (const key of clientSpecKeys) {
279
+ await storage.delete(key)
280
+ }
281
+
282
+ // Store plugin metadata and register resources
283
+ const results = { synced: plugins.length, registered_mcp: 0, registered_specs: 0, errors: [] }
284
+
285
+ for (const plugin of plugins) {
286
+ if (!plugin.name || !plugin.server_resources) continue
287
+
288
+ try {
289
+ // Store plugin metadata with client_id
290
+ await storage.set(`plugin_client:${client_id}:${plugin.name}`, {
291
+ name: plugin.name,
292
+ server_resources: plugin.server_resources,
293
+ client_id: client_id,
294
+ synced_at: new Date()
295
+ })
296
+
297
+ // Register resources with client_id in key
298
+ const regResults = await registerPluginResources(plugin.name, plugin.server_resources, "cli", client_id)
299
+ results.registered_mcp += regResults.mcp.length
300
+ results.registered_specs += regResults.specs.length
301
+ results.errors.push(...regResults.errors)
302
+ } catch (err) {
303
+ results.errors.push(`Failed to sync plugin ${plugin.name}: ${err.message}`)
304
+ }
305
+ }
306
+
307
+ await bumpVersion()
308
+ res.json({ ok: true, ...results })
309
+ } catch (err) {
310
+ handleError(res, err)
311
+ }
312
+ })
313
+
314
+ // List clients endpoint
315
+ router.get("/clients", async (req, res) => {
316
+ try {
317
+ const storage = getStorage()
318
+ const clientKeys = await storage.listKeys("client:")
319
+ const clients = []
320
+
321
+ for (const key of clientKeys) {
322
+ try {
323
+ const client = await storage.get(key)
324
+ if (client && client.client_id) {
325
+ clients.push(client)
326
+ }
327
+ } catch (err) {
328
+ // Skip if client read fails
329
+ }
330
+ }
331
+
332
+ // Sort by last_seen descending
333
+ clients.sort((a, b) => new Date(b.last_seen) - new Date(a.last_seen))
334
+
335
+ if (req.query.format !== "json" && req.accepts("html") && !req.xhr && !req.headers["x-requested-with"]) {
336
+ return res.render("clients", { clients })
337
+ }
338
+
339
+ res.json({ clients })
340
+ } catch (err) {
341
+ handleError(res, err)
342
+ }
343
+ })
344
+
262
345
  module.exports = router
@@ -0,0 +1,93 @@
1
+ const { Router } = require("express");
2
+ const { getSettings, updateSettings } = require("../services/pluginsService");
3
+
4
+ const router = Router();
5
+
6
+ // Helper function to handle errors
7
+ function handleError(res, err) {
8
+ console.error(err);
9
+ const status = err.status || 500;
10
+ const error = err.error || { code: 500, type: "internal_error", message: err.message || "Internal server error" };
11
+ res.status(status).json({ error });
12
+ }
13
+
14
+ // GET /settings - Render settings view
15
+ router.get("/settings", async (req, res) => {
16
+ try {
17
+ const settings = await getSettings()
18
+ if (req.query.format !== "json" && req.accepts("html") && !req.xhr && !req.headers["x-requested-with"]) {
19
+ return res.render("settings", { settings })
20
+ }
21
+ res.json(settings)
22
+ } catch (err) {
23
+ handleError(res, err)
24
+ }
25
+ })
26
+
27
+ // PUT /settings - Update settings
28
+ router.put("/settings", async (req, res) => {
29
+ try {
30
+ const settings = await updateSettings(req.body || {})
31
+ res.json({ ok: true, settings })
32
+ } catch (err) {
33
+ handleError(res, err)
34
+ }
35
+ })
36
+
37
+ // GET /api-keys - Render API keys view
38
+ router.get("/api-keys", async (req, res) => {
39
+ try {
40
+ const settings = await getSettings()
41
+ if (req.query.format !== "json" && req.accepts("html") && !req.xhr && !req.headers["x-requested-with"]) {
42
+ return res.render("api-keys", { settings })
43
+ }
44
+ res.json({ api_keys: settings.api_keys || [] })
45
+ } catch (err) {
46
+ handleError(res, err)
47
+ }
48
+ })
49
+
50
+ // POST /api-keys - Create API key
51
+ router.post("/api-keys", async (req, res) => {
52
+ try {
53
+ const { name } = req.body || {}
54
+ if (!name || typeof name !== "string") {
55
+ return res.status(400).json({ error: "name is required", type: "invalid_argument" })
56
+ }
57
+
58
+ const settings = await getSettings()
59
+ const crypto = require("crypto")
60
+ const key = crypto.randomBytes(32).toString("hex")
61
+
62
+ const newApiKey = {
63
+ name: String(name).trim(),
64
+ key,
65
+ created_at: new Date().toISOString()
66
+ }
67
+
68
+ const apiKeys = Array.isArray(settings.api_keys) ? settings.api_keys : []
69
+ apiKeys.push(newApiKey)
70
+
71
+ await updateSettings({ api_keys: apiKeys })
72
+ res.status(201).json(newApiKey)
73
+ } catch (err) {
74
+ handleError(res, err)
75
+ }
76
+ })
77
+
78
+ // DELETE /api-keys/:key - Delete API key
79
+ router.delete("/api-keys/:key", async (req, res) => {
80
+ try {
81
+ const keyToDelete = req.params.key
82
+ const settings = await getSettings()
83
+ const apiKeys = Array.isArray(settings.api_keys) ? settings.api_keys : []
84
+ const filtered = apiKeys.filter(k => k.key !== keyToDelete)
85
+
86
+ await updateSettings({ api_keys: filtered })
87
+ res.json({ ok: true })
88
+ } catch (err) {
89
+ handleError(res, err)
90
+ }
91
+ })
92
+
93
+ module.exports = router;
@@ -28,9 +28,12 @@ router.get("/", async (req, res) => {
28
28
  router.post("/", async (req, res) => {
29
29
  try {
30
30
  const storage = getStorage()
31
- const { name, url, auth } = req.body
31
+ const { name, url, auth, pluginSource } = req.body
32
32
  const key = `spec:${name}`
33
- const doc = { _id: key, name, url, auth: auth || "none", createdAt: new Date() }
33
+ // Support both simple string auth and object auth
34
+ const authValue = auth || "none"
35
+ const doc = { _id: key, name, url, auth: authValue, createdAt: new Date() }
36
+ if (typeof pluginSource === "string") doc.pluginSource = pluginSource
34
37
  await storage.set(key, doc)
35
38
  await bumpVersion()
36
39
  if (req.headers["content-type"]?.includes("urlencoded")) {
@@ -54,7 +57,9 @@ router.put("/:id", async (req, res) => {
54
57
  await storage.delete(id)
55
58
  }
56
59
 
57
- const doc = { _id: newKey, name, url, auth: auth || "none" }
60
+ // Support both simple string auth and object auth
61
+ const authValue = auth || "none"
62
+ const doc = { _id: newKey, name, url, auth: authValue }
58
63
  await storage.set(newKey, doc)
59
64
  await bumpVersion()
60
65
  res.json({ ok: true })
@@ -65,6 +65,7 @@ async function listAdapters() {
65
65
  const records = await Promise.all(keys.map(k => storage.get(k)))
66
66
  return records
67
67
  .filter(Boolean)
68
+ .filter(record => record.name) // Filter out records without name (e.g., package records)
68
69
  .sort((a, b) => String(a.name || "").localeCompare(String(b.name || "")))
69
70
  .map(toPublicAdapter)
70
71
  }
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Plugin Resource Service
3
+ * Handles registration and cleanup of server resources (MCP/OpenAPI) from plugins
4
+ */
5
+ const { getStorage } = require("../storage/adapter")
6
+
7
+ async function registerPluginResources(pluginName, serverResources, origin = "cli", clientId = null) {
8
+ const storage = getStorage()
9
+ const results = { mcp: [], specs: [], errors: [] }
10
+
11
+ try {
12
+ // Register MCP resources
13
+ if (serverResources.mcp && Array.isArray(serverResources.mcp)) {
14
+ for (const mcpResource of serverResources.mcp) {
15
+ try {
16
+ if (!mcpResource.name || (!mcpResource.url && !mcpResource.command)) {
17
+ results.errors.push(`Invalid MCP resource: missing name or url/command`)
18
+ continue
19
+ }
20
+
21
+ // Build key with client_id if origin is cli
22
+ const key = origin === "cli" && clientId
23
+ ? `mcp:${origin}:${clientId}:${pluginName}:${mcpResource.name}`
24
+ : `mcp:${origin}:${pluginName}:${mcpResource.name}`
25
+
26
+ const doc = {
27
+ _id: key,
28
+ name: key,
29
+ displayName: mcpResource.name,
30
+ pluginSource: pluginName,
31
+ origin: origin,
32
+ clientId: clientId || null,
33
+ createdAt: new Date()
34
+ }
35
+
36
+ // Copy MCP properties
37
+ if (mcpResource.url) doc.url = mcpResource.url
38
+ if (mcpResource.command) doc.command = mcpResource.command
39
+ if (mcpResource.args) doc.args = mcpResource.args
40
+ if (mcpResource.headers) doc.headers = mcpResource.headers
41
+ if (mcpResource.env) doc.env = mcpResource.env
42
+ if (mcpResource.timeout_ms) doc.timeout_ms = mcpResource.timeout_ms
43
+ if (mcpResource.stateful) doc.stateful = true
44
+
45
+ await storage.set(key, doc)
46
+ results.mcp.push(key)
47
+ } catch (err) {
48
+ results.errors.push(`Failed to register MCP ${mcpResource.name}: ${err.message}`)
49
+ }
50
+ }
51
+ }
52
+
53
+ // Register OpenAPI spec resources
54
+ if (serverResources.specs && Array.isArray(serverResources.specs)) {
55
+ for (const specResource of serverResources.specs) {
56
+ try {
57
+ if (!specResource.name || !specResource.url) {
58
+ results.errors.push(`Invalid spec resource: missing name or url`)
59
+ continue
60
+ }
61
+
62
+ // Build key with client_id if origin is cli
63
+ const key = origin === "cli" && clientId
64
+ ? `spec:${origin}:${clientId}:${pluginName}:${specResource.name}`
65
+ : `spec:${origin}:${pluginName}:${specResource.name}`
66
+
67
+ const doc = {
68
+ _id: key,
69
+ name: key,
70
+ displayName: specResource.name,
71
+ url: specResource.url,
72
+ auth: specResource.auth || "none",
73
+ pluginSource: pluginName,
74
+ origin: origin,
75
+ clientId: clientId || null,
76
+ createdAt: new Date()
77
+ }
78
+
79
+ await storage.set(key, doc)
80
+ results.specs.push(key)
81
+ } catch (err) {
82
+ results.errors.push(`Failed to register spec ${specResource.name}: ${err.message}`)
83
+ }
84
+ }
85
+ }
86
+ } catch (err) {
87
+ results.errors.push(`Resource registration failed: ${err.message}`)
88
+ }
89
+
90
+ return results
91
+ }
92
+
93
+ async function unregisterPluginResources(pluginName, origin = "cli") {
94
+ const storage = getStorage()
95
+ const results = { mcp: [], specs: [], errors: [] }
96
+
97
+ try {
98
+ // Remove MCP resources by origin prefix
99
+ const allMcpKeys = await storage.listKeys("mcp:")
100
+ const targetMcpKeys = allMcpKeys.filter(k => k.startsWith(`mcp:${origin}:${pluginName}:`))
101
+ for (const key of targetMcpKeys) {
102
+ try {
103
+ await storage.delete(key)
104
+ results.mcp.push(key)
105
+ } catch (err) {
106
+ results.errors.push(`Failed to remove MCP ${key}: ${err.message}`)
107
+ }
108
+ }
109
+
110
+ // Remove spec resources by origin prefix
111
+ const allSpecKeys = await storage.listKeys("spec:")
112
+ const targetSpecKeys = allSpecKeys.filter(k => k.startsWith(`spec:${origin}:${pluginName}:`))
113
+ for (const key of targetSpecKeys) {
114
+ try {
115
+ await storage.delete(key)
116
+ results.specs.push(key)
117
+ } catch (err) {
118
+ results.errors.push(`Failed to remove spec ${key}: ${err.message}`)
119
+ }
120
+ }
121
+ } catch (err) {
122
+ results.errors.push(`Resource cleanup failed: ${err.message}`)
123
+ }
124
+
125
+ return results
126
+ }
127
+
128
+ async function registerAllPluginResources() {
129
+ const storage = getStorage()
130
+ const results = { plugins: {}, totalErrors: 0, registeredMcp: 0, registeredSpecs: 0 }
131
+
132
+ // Register resources from client plugins (plugin_client:{client-id}:*)
133
+ const clientPluginKeys = await storage.listKeys("plugin_client:")
134
+ for (const key of clientPluginKeys) {
135
+ try {
136
+ const plugin = await storage.get(key)
137
+ if (plugin && plugin.server_resources && plugin.client_id) {
138
+ const pluginResults = await registerPluginResources(plugin.name, plugin.server_resources, "cli", plugin.client_id)
139
+ results.plugins[plugin.name] = pluginResults
140
+ results.totalErrors += pluginResults.errors.length
141
+ results.registeredMcp += pluginResults.mcp.length
142
+ results.registeredSpecs += pluginResults.specs.length
143
+ }
144
+ } catch (err) {
145
+ results.totalErrors++
146
+ }
147
+ }
148
+
149
+ // Register resources from server plugins (plugin_server:*)
150
+ const serverPluginKeys = await storage.listKeys("plugin_server:")
151
+ for (const key of serverPluginKeys) {
152
+ try {
153
+ const plugin = await storage.get(key)
154
+ if (plugin && plugin.manifest && plugin.manifest.server_resources) {
155
+ const pluginResults = await registerPluginResources(plugin.name, plugin.manifest.server_resources, "server")
156
+ results.plugins[plugin.name] = pluginResults
157
+ results.totalErrors += pluginResults.errors.length
158
+ results.registeredMcp += pluginResults.mcp.length
159
+ results.registeredSpecs += pluginResults.specs.length
160
+ }
161
+ } catch (err) {
162
+ results.totalErrors++
163
+ }
164
+ }
165
+
166
+ return results
167
+ }
168
+
169
+ async function syncPluginResources() {
170
+ const storage = getStorage()
171
+
172
+ // Get all currently registered plugin resources
173
+ const allMcpKeys = await storage.listKeys("mcp:")
174
+ const allSpecKeys = await storage.listKeys("spec:")
175
+
176
+ // Filter for plugin resources (contain origin prefix)
177
+ const pluginMcpKeys = allMcpKeys.filter(k => k.split(':').length > 2)
178
+ const pluginSpecKeys = allSpecKeys.filter(k => k.split(':').length > 2)
179
+
180
+ // Build set of expected resources from server storage (plugin_client:* and plugin_server:*)
181
+ const expectedMcpKeys = new Set()
182
+ const expectedSpecKeys = new Set()
183
+
184
+ const clientPluginKeys = await storage.listKeys("plugin_client:")
185
+ const serverPluginKeys = await storage.listKeys("plugin_server:")
186
+
187
+ // Read client plugins
188
+ for (const key of clientPluginKeys) {
189
+ try {
190
+ const plugin = await storage.get(key)
191
+ if (plugin && plugin.server_resources && plugin.client_id) {
192
+ if (plugin.server_resources.mcp) {
193
+ for (const mcp of plugin.server_resources.mcp) {
194
+ expectedMcpKeys.add(`mcp:cli:${plugin.client_id}:${plugin.name}:${mcp.name}`)
195
+ }
196
+ }
197
+ if (plugin.server_resources.specs) {
198
+ for (const spec of plugin.server_resources.specs) {
199
+ expectedSpecKeys.add(`spec:cli:${plugin.client_id}:${plugin.name}:${spec.name}`)
200
+ }
201
+ }
202
+ }
203
+ } catch (err) {
204
+ // Skip if plugin read fails
205
+ }
206
+ }
207
+
208
+ // Read server plugins
209
+ for (const key of serverPluginKeys) {
210
+ try {
211
+ const plugin = await storage.get(key)
212
+ if (plugin && plugin.manifest && plugin.manifest.server_resources) {
213
+ if (plugin.manifest.server_resources.mcp) {
214
+ for (const mcp of plugin.manifest.server_resources.mcp) {
215
+ expectedMcpKeys.add(`mcp:server:${plugin.name}:${mcp.name}`)
216
+ }
217
+ }
218
+ if (plugin.manifest.server_resources.specs) {
219
+ for (const spec of plugin.manifest.server_resources.specs) {
220
+ expectedSpecKeys.add(`spec:server:${plugin.name}:${spec.name}`)
221
+ }
222
+ }
223
+ }
224
+ } catch (err) {
225
+ // Skip if plugin read fails
226
+ }
227
+ }
228
+
229
+ // Remove orphaned resources (no longer in any installed plugin)
230
+ const cleanupResults = { removedMcp: [], removedSpecs: [], errors: [] }
231
+
232
+ for (const key of pluginMcpKeys) {
233
+ if (!expectedMcpKeys.has(key)) {
234
+ try {
235
+ await storage.delete(key)
236
+ cleanupResults.removedMcp.push(key)
237
+ } catch (err) {
238
+ cleanupResults.errors.push(`Failed to remove orphaned MCP ${key}: ${err.message}`)
239
+ }
240
+ }
241
+ }
242
+
243
+ for (const key of pluginSpecKeys) {
244
+ if (!expectedSpecKeys.has(key)) {
245
+ try {
246
+ await storage.delete(key)
247
+ cleanupResults.removedSpecs.push(key)
248
+ } catch (err) {
249
+ cleanupResults.errors.push(`Failed to remove orphaned spec ${key}: ${err.message}`)
250
+ }
251
+ }
252
+ }
253
+
254
+ return cleanupResults
255
+ }
256
+
257
+ module.exports = {
258
+ registerPluginResources,
259
+ unregisterPluginResources,
260
+ registerAllPluginResources,
261
+ syncPluginResources
262
+ }
@@ -1,6 +1,7 @@
1
1
  const crypto = require("crypto")
2
2
  const { getStorage } = require("../storage/adapter")
3
3
  const { bumpVersion } = require("./configService")
4
+ const { registerPluginResources, unregisterPluginResources } = require("./pluginResourceService")
4
5
 
5
6
  const PLUGIN_PREFIX = "plugin_server:"
6
7
  const SETTINGS_KEY = "settings:plugins"
@@ -18,6 +19,8 @@ function defaultSettings() {
18
19
  max_zip_mb: 10,
19
20
  default_hooks_policy: "deny",
20
21
  admin_mode_enabled: false,
22
+ public_access: true,
23
+ api_keys: [],
21
24
  }
22
25
  }
23
26
 
@@ -119,6 +122,15 @@ async function updateSettings(patch = {}) {
119
122
  if (patch.admin_mode_enabled !== undefined) {
120
123
  next.admin_mode_enabled = patch.admin_mode_enabled === true || patch.admin_mode_enabled === "true"
121
124
  }
125
+ if (patch.public_access !== undefined) {
126
+ next.public_access = patch.public_access === true || patch.public_access === "true"
127
+ }
128
+ if (patch.api_keys !== undefined) {
129
+ if (!Array.isArray(patch.api_keys)) {
130
+ throw invalid("api_keys must be an array")
131
+ }
132
+ next.api_keys = patch.api_keys
133
+ }
122
134
  const storage = getStorage()
123
135
  await storage.set(SETTINGS_KEY, next)
124
136
  return next
@@ -194,6 +206,12 @@ async function upsertJsonPlugin(payload) {
194
206
  }
195
207
  const storage = getStorage()
196
208
  await storage.set(pluginKey(common.name), next)
209
+
210
+ // Register server resources if present
211
+ if (manifest.server_resources) {
212
+ await registerPluginResources(common.name, manifest.server_resources, "server")
213
+ }
214
+
197
215
  await bumpVersion()
198
216
  return toPublicPlugin(next)
199
217
  }
@@ -233,6 +251,12 @@ async function upsertZipPlugin(payload) {
233
251
  }
234
252
  const storage = getStorage()
235
253
  await storage.set(pluginKey(common.name), next)
254
+
255
+ // Register server resources if present
256
+ if (manifest.server_resources) {
257
+ await registerPluginResources(common.name, manifest.server_resources, "server")
258
+ }
259
+
236
260
  await bumpVersion()
237
261
  return toPublicPlugin(next)
238
262
  }
@@ -0,0 +1,47 @@
1
+ {
2
+ "openapi": "3.0.0",
3
+ "info": {
4
+ "title": "Superbackend API",
5
+ "version": "1.0.0"
6
+ },
7
+ "servers": [
8
+ {
9
+ "url": "https://superbackend.coolify.intrane.fr"
10
+ }
11
+ ],
12
+ "paths": {
13
+ "/health": {
14
+ "get": {
15
+ "operationId": "getHealth",
16
+ "summary": "Health check endpoint",
17
+ "description": "Returns the health status of the backend service",
18
+ "responses": {
19
+ "200": {
20
+ "description": "Health status",
21
+ "content": {
22
+ "application/json": {
23
+ "schema": {
24
+ "type": "object",
25
+ "properties": {
26
+ "status": {
27
+ "type": "string",
28
+ "example": "ok"
29
+ },
30
+ "mode": {
31
+ "type": "string",
32
+ "example": "middleware"
33
+ },
34
+ "database": {
35
+ "type": "string",
36
+ "example": "connected"
37
+ }
38
+ }
39
+ }
40
+ }
41
+ }
42
+ }
43
+ }
44
+ }
45
+ }
46
+ }
47
+ }