@hed-hog/core 0.0.349 → 0.0.351

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 (350) hide show
  1. package/dist/access-log/access-log.controller.d.ts +16 -0
  2. package/dist/access-log/access-log.controller.d.ts.map +1 -0
  3. package/dist/access-log/access-log.controller.js +44 -0
  4. package/dist/access-log/access-log.controller.js.map +1 -0
  5. package/dist/access-log/access-log.interceptor.d.ts +9 -0
  6. package/dist/access-log/access-log.interceptor.d.ts.map +1 -0
  7. package/dist/access-log/access-log.interceptor.js +46 -0
  8. package/dist/access-log/access-log.interceptor.js.map +1 -0
  9. package/dist/access-log/access-log.module.d.ts +3 -0
  10. package/dist/access-log/access-log.module.d.ts.map +1 -0
  11. package/dist/access-log/access-log.module.js +29 -0
  12. package/dist/access-log/access-log.module.js.map +1 -0
  13. package/dist/access-log/access-log.service.d.ts +47 -0
  14. package/dist/access-log/access-log.service.d.ts.map +1 -0
  15. package/dist/access-log/access-log.service.js +113 -0
  16. package/dist/access-log/access-log.service.js.map +1 -0
  17. package/dist/access-log/dto/query-access-log.dto.d.ts +8 -0
  18. package/dist/access-log/dto/query-access-log.dto.d.ts.map +1 -0
  19. package/dist/access-log/dto/query-access-log.dto.js +42 -0
  20. package/dist/access-log/dto/query-access-log.dto.js.map +1 -0
  21. package/dist/auth/auth.controller.d.ts +12 -12
  22. package/dist/auth/auth.service.d.ts +27 -27
  23. package/dist/auth/auth.service.d.ts.map +1 -1
  24. package/dist/auth/auth.service.js +0 -4
  25. package/dist/auth/auth.service.js.map +1 -1
  26. package/dist/challenge/challenge.service.d.ts +2 -2
  27. package/dist/challenge/challenge.service.d.ts.map +1 -1
  28. package/dist/challenge/challenge.service.js +0 -1
  29. package/dist/challenge/challenge.service.js.map +1 -1
  30. package/dist/core/system.module.d.ts.map +1 -1
  31. package/dist/core/system.module.js +1 -0
  32. package/dist/core/system.module.js.map +1 -1
  33. package/dist/core.module.d.ts.map +1 -1
  34. package/dist/core.module.js +15 -0
  35. package/dist/core.module.js.map +1 -1
  36. package/dist/dashboard/dashboard-user/dashboard-user.controller.d.ts +3 -3
  37. package/dist/dashboard/dashboard-user/dashboard-user.service.d.ts +3 -3
  38. package/dist/dashboard/dashboard.module.d.ts.map +1 -1
  39. package/dist/dashboard/dashboard.module.js +4 -1
  40. package/dist/dashboard/dashboard.module.js.map +1 -1
  41. package/dist/file/file.controller.js +0 -1
  42. package/dist/file/file.controller.js.map +1 -1
  43. package/dist/file/file.service.d.ts +65 -0
  44. package/dist/file/file.service.d.ts.map +1 -1
  45. package/dist/file/file.service.js +151 -3
  46. package/dist/file/file.service.js.map +1 -1
  47. package/dist/file/provider/abstract.provider.d.ts +8 -0
  48. package/dist/file/provider/abstract.provider.d.ts.map +1 -1
  49. package/dist/file/provider/abstract.provider.js.map +1 -1
  50. package/dist/file/provider/azure.provider.d.ts +4 -0
  51. package/dist/file/provider/azure.provider.d.ts.map +1 -1
  52. package/dist/file/provider/azure.provider.js +14 -0
  53. package/dist/file/provider/azure.provider.js.map +1 -1
  54. package/dist/file/provider/gcs.provider.d.ts +4 -0
  55. package/dist/file/provider/gcs.provider.d.ts.map +1 -1
  56. package/dist/file/provider/gcs.provider.js +14 -0
  57. package/dist/file/provider/gcs.provider.js.map +1 -1
  58. package/dist/file/provider/local.provider.d.ts +4 -0
  59. package/dist/file/provider/local.provider.d.ts.map +1 -1
  60. package/dist/file/provider/local.provider.js +19 -0
  61. package/dist/file/provider/local.provider.js.map +1 -1
  62. package/dist/file/provider/provider.factory.d.ts.map +1 -1
  63. package/dist/file/provider/provider.factory.js +3 -0
  64. package/dist/file/provider/provider.factory.js.map +1 -1
  65. package/dist/file/provider/s3.provider.d.ts +4 -0
  66. package/dist/file/provider/s3.provider.d.ts.map +1 -1
  67. package/dist/file/provider/s3.provider.js +17 -0
  68. package/dist/file/provider/s3.provider.js.map +1 -1
  69. package/dist/index.d.ts +3 -0
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +4 -0
  72. package/dist/index.js.map +1 -1
  73. package/dist/mcp/guards/mcp-auth.guard.d.ts +6 -1
  74. package/dist/mcp/guards/mcp-auth.guard.d.ts.map +1 -1
  75. package/dist/mcp/guards/mcp-auth.guard.js +29 -2
  76. package/dist/mcp/guards/mcp-auth.guard.js.map +1 -1
  77. package/dist/mcp/mcp-api-key.controller.d.ts +32 -0
  78. package/dist/mcp/mcp-api-key.controller.d.ts.map +1 -0
  79. package/dist/mcp/mcp-api-key.controller.js +64 -0
  80. package/dist/mcp/mcp-api-key.controller.js.map +1 -0
  81. package/dist/mcp/mcp-api-key.service.d.ts +27 -0
  82. package/dist/mcp/mcp-api-key.service.d.ts.map +1 -0
  83. package/dist/mcp/mcp-api-key.service.js +74 -0
  84. package/dist/mcp/mcp-api-key.service.js.map +1 -0
  85. package/dist/mcp/mcp-audit.service.d.ts +3 -1
  86. package/dist/mcp/mcp-audit.service.d.ts.map +1 -1
  87. package/dist/mcp/mcp-audit.service.js +14 -2
  88. package/dist/mcp/mcp-audit.service.js.map +1 -1
  89. package/dist/mcp/mcp-registry.service.d.ts +1 -2
  90. package/dist/mcp/mcp-registry.service.d.ts.map +1 -1
  91. package/dist/mcp/mcp-registry.service.js +6 -2
  92. package/dist/mcp/mcp-registry.service.js.map +1 -1
  93. package/dist/mcp/mcp.controller.d.ts +3 -1
  94. package/dist/mcp/mcp.controller.d.ts.map +1 -1
  95. package/dist/mcp/mcp.controller.js +10 -2
  96. package/dist/mcp/mcp.controller.js.map +1 -1
  97. package/dist/mcp/mcp.module.d.ts.map +1 -1
  98. package/dist/mcp/mcp.module.js +80 -1
  99. package/dist/mcp/mcp.module.js.map +1 -1
  100. package/dist/mcp/tools/core-ai.mcp-tools.d.ts +45 -0
  101. package/dist/mcp/tools/core-ai.mcp-tools.d.ts.map +1 -0
  102. package/dist/mcp/tools/core-ai.mcp-tools.js +214 -0
  103. package/dist/mcp/tools/core-ai.mcp-tools.js.map +1 -0
  104. package/dist/mcp/tools/core-dashboard-items.mcp-tools.d.ts +21 -0
  105. package/dist/mcp/tools/core-dashboard-items.mcp-tools.d.ts.map +1 -0
  106. package/dist/mcp/tools/core-dashboard-items.mcp-tools.js +89 -0
  107. package/dist/mcp/tools/core-dashboard-items.mcp-tools.js.map +1 -0
  108. package/dist/mcp/tools/core-dashboard.mcp-tools.d.ts +29 -0
  109. package/dist/mcp/tools/core-dashboard.mcp-tools.d.ts.map +1 -0
  110. package/dist/mcp/tools/core-dashboard.mcp-tools.js +149 -0
  111. package/dist/mcp/tools/core-dashboard.mcp-tools.js.map +1 -0
  112. package/dist/mcp/tools/core-event-webhooks.mcp-tools.d.ts +30 -0
  113. package/dist/mcp/tools/core-event-webhooks.mcp-tools.d.ts.map +1 -0
  114. package/dist/mcp/tools/core-event-webhooks.mcp-tools.js +185 -0
  115. package/dist/mcp/tools/core-event-webhooks.mcp-tools.js.map +1 -0
  116. package/dist/mcp/tools/core-files.mcp-tools.d.ts +26 -0
  117. package/dist/mcp/tools/core-files.mcp-tools.d.ts.map +1 -0
  118. package/dist/mcp/tools/core-files.mcp-tools.js +140 -0
  119. package/dist/mcp/tools/core-files.mcp-tools.js.map +1 -0
  120. package/dist/mcp/tools/core-integration-events.mcp-tools.d.ts +26 -0
  121. package/dist/mcp/tools/core-integration-events.mcp-tools.d.ts.map +1 -0
  122. package/dist/mcp/tools/core-integration-events.mcp-tools.js +168 -0
  123. package/dist/mcp/tools/core-integration-events.mcp-tools.js.map +1 -0
  124. package/dist/mcp/tools/core-mail-profile.mcp-tools.d.ts +32 -0
  125. package/dist/mcp/tools/core-mail-profile.mcp-tools.d.ts.map +1 -0
  126. package/dist/mcp/tools/core-mail-profile.mcp-tools.js +178 -0
  127. package/dist/mcp/tools/core-mail-profile.mcp-tools.js.map +1 -0
  128. package/dist/mcp/tools/core-mail-sent.mcp-tools.d.ts +14 -0
  129. package/dist/mcp/tools/core-mail-sent.mcp-tools.d.ts.map +1 -0
  130. package/dist/mcp/tools/core-mail-sent.mcp-tools.js +106 -0
  131. package/dist/mcp/tools/core-mail-sent.mcp-tools.js.map +1 -0
  132. package/dist/mcp/tools/core-mail.mcp-tools.d.ts +36 -0
  133. package/dist/mcp/tools/core-mail.mcp-tools.d.ts.map +1 -0
  134. package/dist/mcp/tools/core-mail.mcp-tools.js +184 -0
  135. package/dist/mcp/tools/core-mail.mcp-tools.js.map +1 -0
  136. package/dist/mcp/tools/core-mcp-chat.mcp-tools.d.ts +21 -0
  137. package/dist/mcp/tools/core-mcp-chat.mcp-tools.d.ts.map +1 -0
  138. package/dist/mcp/tools/core-mcp-chat.mcp-tools.js +118 -0
  139. package/dist/mcp/tools/core-mcp-chat.mcp-tools.js.map +1 -0
  140. package/dist/mcp/tools/core-menus.mcp-tools.d.ts +40 -0
  141. package/dist/mcp/tools/core-menus.mcp-tools.d.ts.map +1 -0
  142. package/dist/mcp/tools/core-menus.mcp-tools.js +268 -0
  143. package/dist/mcp/tools/core-menus.mcp-tools.js.map +1 -0
  144. package/dist/mcp/tools/core-notifications.mcp-tools.d.ts +31 -0
  145. package/dist/mcp/tools/core-notifications.mcp-tools.d.ts.map +1 -0
  146. package/dist/mcp/tools/core-notifications.mcp-tools.js +178 -0
  147. package/dist/mcp/tools/core-notifications.mcp-tools.js.map +1 -0
  148. package/dist/mcp/tools/core-profile.mcp-tools.d.ts +20 -0
  149. package/dist/mcp/tools/core-profile.mcp-tools.d.ts.map +1 -0
  150. package/dist/mcp/tools/core-profile.mcp-tools.js +111 -0
  151. package/dist/mcp/tools/core-profile.mcp-tools.js.map +1 -0
  152. package/dist/mcp/tools/core-roles.mcp-tools.d.ts +70 -0
  153. package/dist/mcp/tools/core-roles.mcp-tools.d.ts.map +1 -0
  154. package/dist/mcp/tools/core-roles.mcp-tools.js +355 -0
  155. package/dist/mcp/tools/core-roles.mcp-tools.js.map +1 -0
  156. package/dist/mcp/tools/core-routes.mcp-tools.d.ts +52 -0
  157. package/dist/mcp/tools/core-routes.mcp-tools.d.ts.map +1 -0
  158. package/dist/mcp/tools/core-routes.mcp-tools.js +254 -0
  159. package/dist/mcp/tools/core-routes.mcp-tools.js.map +1 -0
  160. package/dist/mcp/tools/core-screens.mcp-tools.d.ts +47 -0
  161. package/dist/mcp/tools/core-screens.mcp-tools.d.ts.map +1 -0
  162. package/dist/mcp/tools/core-screens.mcp-tools.js +250 -0
  163. package/dist/mcp/tools/core-screens.mcp-tools.js.map +1 -0
  164. package/dist/mcp/tools/core-sessions.mcp-tools.d.ts +20 -0
  165. package/dist/mcp/tools/core-sessions.mcp-tools.d.ts.map +1 -0
  166. package/dist/mcp/tools/core-sessions.mcp-tools.js +128 -0
  167. package/dist/mcp/tools/core-sessions.mcp-tools.js.map +1 -0
  168. package/dist/mcp/tools/core-settings.mcp-tools.d.ts +25 -0
  169. package/dist/mcp/tools/core-settings.mcp-tools.d.ts.map +1 -1
  170. package/dist/mcp/tools/core-settings.mcp-tools.js +138 -0
  171. package/dist/mcp/tools/core-settings.mcp-tools.js.map +1 -1
  172. package/dist/mcp/tools/core-system.mcp-tools.d.ts +8 -0
  173. package/dist/mcp/tools/core-system.mcp-tools.d.ts.map +1 -0
  174. package/dist/mcp/tools/core-system.mcp-tools.js +40 -0
  175. package/dist/mcp/tools/core-system.mcp-tools.js.map +1 -0
  176. package/dist/mcp/tools/core-webhooks.mcp-tools.d.ts +46 -0
  177. package/dist/mcp/tools/core-webhooks.mcp-tools.d.ts.map +1 -0
  178. package/dist/mcp/tools/core-webhooks.mcp-tools.js +266 -0
  179. package/dist/mcp/tools/core-webhooks.mcp-tools.js.map +1 -0
  180. package/dist/mcp-chat/mcp-chat.controller.d.ts +5 -1
  181. package/dist/mcp-chat/mcp-chat.controller.d.ts.map +1 -1
  182. package/dist/mcp-chat/mcp-chat.controller.js +46 -0
  183. package/dist/mcp-chat/mcp-chat.controller.js.map +1 -1
  184. package/dist/mcp-chat/mcp-chat.service.d.ts +31 -3
  185. package/dist/mcp-chat/mcp-chat.service.d.ts.map +1 -1
  186. package/dist/mcp-chat/mcp-chat.service.js +776 -38
  187. package/dist/mcp-chat/mcp-chat.service.js.map +1 -1
  188. package/dist/notification/dto/create-notification.dto.d.ts +26 -0
  189. package/dist/notification/dto/create-notification.dto.d.ts.map +1 -0
  190. package/dist/notification/dto/create-notification.dto.js +86 -0
  191. package/dist/notification/dto/create-notification.dto.js.map +1 -0
  192. package/dist/notification/dto/update-progress.dto.d.ts +6 -0
  193. package/dist/notification/dto/update-progress.dto.d.ts.map +1 -0
  194. package/dist/notification/dto/update-progress.dto.js +33 -0
  195. package/dist/notification/dto/update-progress.dto.js.map +1 -0
  196. package/dist/notification/notification.controller.d.ts +112 -0
  197. package/dist/notification/notification.controller.d.ts.map +1 -0
  198. package/dist/notification/notification.controller.js +130 -0
  199. package/dist/notification/notification.controller.js.map +1 -0
  200. package/dist/notification/notification.module.d.ts +3 -0
  201. package/dist/notification/notification.module.d.ts.map +1 -0
  202. package/dist/notification/notification.module.js +29 -0
  203. package/dist/notification/notification.module.js.map +1 -0
  204. package/dist/notification/notification.service.d.ts +112 -0
  205. package/dist/notification/notification.service.d.ts.map +1 -0
  206. package/dist/notification/notification.service.js +269 -0
  207. package/dist/notification/notification.service.js.map +1 -0
  208. package/dist/pdf/pdf.service.js +1 -1
  209. package/dist/pdf/pdf.service.js.map +1 -1
  210. package/dist/profile/profile.controller.d.ts +4 -4
  211. package/dist/profile/profile.controller.js +0 -1
  212. package/dist/profile/profile.controller.js.map +1 -1
  213. package/dist/profile/profile.module.d.ts.map +1 -1
  214. package/dist/profile/profile.module.js +1 -0
  215. package/dist/profile/profile.module.js.map +1 -1
  216. package/dist/profile/profile.service.d.ts +4 -4
  217. package/dist/session/session.controller.d.ts +3 -3
  218. package/dist/session/session.service.d.ts +9 -9
  219. package/dist/setting/dto/update-setting-list.dto.d.ts +9 -0
  220. package/dist/setting/dto/update-setting-list.dto.d.ts.map +1 -0
  221. package/dist/setting/dto/update-setting-list.dto.js +44 -0
  222. package/dist/setting/dto/update-setting-list.dto.js.map +1 -0
  223. package/dist/setting/setting.controller.d.ts +20 -1
  224. package/dist/setting/setting.controller.d.ts.map +1 -1
  225. package/dist/setting/setting.controller.js +12 -0
  226. package/dist/setting/setting.controller.js.map +1 -1
  227. package/dist/setting/setting.service.d.ts +20 -1
  228. package/dist/setting/setting.service.d.ts.map +1 -1
  229. package/dist/setting/setting.service.js +80 -4
  230. package/dist/setting/setting.service.js.map +1 -1
  231. package/dist/task/task.service.d.ts +13 -0
  232. package/dist/task/task.service.d.ts.map +1 -1
  233. package/dist/task/task.service.js +85 -0
  234. package/dist/task/task.service.js.map +1 -1
  235. package/dist/token/token.service.d.ts.map +1 -1
  236. package/dist/token/token.service.js +0 -1
  237. package/dist/token/token.service.js.map +1 -1
  238. package/dist/user/user.controller.d.ts +11 -11
  239. package/dist/user/user.service.d.ts +27 -27
  240. package/dist/webhook-integration/dto/webhook-action.dto.d.ts +22 -0
  241. package/dist/webhook-integration/dto/webhook-action.dto.d.ts.map +1 -0
  242. package/dist/webhook-integration/dto/webhook-action.dto.js +120 -0
  243. package/dist/webhook-integration/dto/webhook-action.dto.js.map +1 -0
  244. package/dist/webhook-integration/webhook-integration.controller.d.ts +7 -5
  245. package/dist/webhook-integration/webhook-integration.controller.d.ts.map +1 -1
  246. package/dist/webhook-integration/webhook-integration.controller.js +18 -5
  247. package/dist/webhook-integration/webhook-integration.controller.js.map +1 -1
  248. package/dist/webhook-integration/webhook-integration.service.d.ts +18 -5
  249. package/dist/webhook-integration/webhook-integration.service.d.ts.map +1 -1
  250. package/dist/webhook-integration/webhook-integration.service.js +342 -59
  251. package/dist/webhook-integration/webhook-integration.service.js.map +1 -1
  252. package/dist/webhook-integration/webhook-utils.d.ts +1 -0
  253. package/dist/webhook-integration/webhook-utils.d.ts.map +1 -1
  254. package/dist/webhook-integration/webhook-utils.js +38 -0
  255. package/dist/webhook-integration/webhook-utils.js.map +1 -1
  256. package/hedhog/data/menu.yaml +63 -4
  257. package/hedhog/data/route.yaml +1437 -0
  258. package/hedhog/data/setting_group.yaml +112 -0
  259. package/hedhog/data/setting_subgroup.yaml +32 -0
  260. package/hedhog/frontend/app/access-log/page.tsx.ejs +772 -0
  261. package/hedhog/frontend/app/account/components/mcp-tokens.tsx.ejs +285 -0
  262. package/hedhog/frontend/app/account/layout.tsx.ejs +32 -55
  263. package/hedhog/frontend/app/account/mcp-tokens/page.tsx.ejs +5 -0
  264. package/hedhog/frontend/app/ai_agent/page.tsx.ejs +10 -3
  265. package/hedhog/frontend/app/dashboard/dashboard-home-tabs.tsx.ejs +33 -13
  266. package/hedhog/frontend/app/dashboard/management/tabs/components-tab.tsx.ejs +12 -5
  267. package/hedhog/frontend/app/dashboard/management/tabs/dashboards-tab.tsx.ejs +12 -5
  268. package/hedhog/frontend/app/integrations-webhooks/page.tsx.ejs +3559 -1835
  269. package/hedhog/frontend/app/mcp_chat/chat-components.tsx.ejs +633 -0
  270. package/hedhog/frontend/app/mcp_chat/chat-types.ts.ejs +16 -0
  271. package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +583 -384
  272. package/hedhog/frontend/app/menu/page.tsx.ejs +9 -3
  273. package/hedhog/frontend/app/roles/page.tsx.ejs +18 -6
  274. package/hedhog/frontend/app/routes/page.tsx.ejs +9 -3
  275. package/hedhog/frontend/app/setting-list/page.tsx.ejs +822 -0
  276. package/hedhog/frontend/app/users/page.tsx.ejs +445 -203
  277. package/hedhog/frontend/app/users/user-access-sheet.tsx.ejs +310 -304
  278. package/hedhog/frontend/app/users/user-sheet.tsx.ejs +41 -44
  279. package/hedhog/frontend/messages/en.json +343 -3
  280. package/hedhog/frontend/messages/pt.json +343 -3
  281. package/hedhog/table/access_log.yaml +31 -0
  282. package/hedhog/table/mcp_api_key.yaml +30 -0
  283. package/hedhog/table/notification.yaml +72 -0
  284. package/hedhog/table/webhook_action_log.yaml +49 -0
  285. package/package.json +5 -4
  286. package/src/access-log/access-log.controller.ts +29 -0
  287. package/src/access-log/access-log.interceptor.ts +38 -0
  288. package/src/access-log/access-log.module.ts +16 -0
  289. package/src/access-log/access-log.service.ts +129 -0
  290. package/src/access-log/dto/query-access-log.dto.ts +23 -0
  291. package/src/auth/auth.service.ts +0 -7
  292. package/src/challenge/challenge.service.ts +0 -2
  293. package/src/core/system.module.ts +1 -0
  294. package/src/core.module.ts +15 -0
  295. package/src/dashboard/dashboard.module.ts +4 -1
  296. package/src/file/file.controller.ts +14 -14
  297. package/src/file/file.service.ts +198 -4
  298. package/src/file/provider/abstract.provider.ts +10 -0
  299. package/src/file/provider/azure.provider.ts +24 -0
  300. package/src/file/provider/gcs.provider.ts +20 -0
  301. package/src/file/provider/local.provider.ts +30 -2
  302. package/src/file/provider/provider.factory.ts +3 -0
  303. package/src/file/provider/s3.provider.ts +22 -0
  304. package/src/index.ts +5 -0
  305. package/src/mcp/guards/mcp-auth.guard.ts +64 -32
  306. package/src/mcp/mcp-api-key.controller.ts +42 -0
  307. package/src/mcp/mcp-api-key.service.ts +66 -0
  308. package/src/mcp/mcp-audit.service.ts +47 -36
  309. package/src/mcp/mcp-registry.service.ts +75 -69
  310. package/src/mcp/mcp.controller.ts +40 -30
  311. package/src/mcp/mcp.module.ts +115 -36
  312. package/src/mcp/tools/core-ai.mcp-tools.ts +156 -0
  313. package/src/mcp/tools/core-dashboard-items.mcp-tools.ts +63 -0
  314. package/src/mcp/tools/core-dashboard.mcp-tools.ts +103 -0
  315. package/src/mcp/tools/core-event-webhooks.mcp-tools.ts +134 -0
  316. package/src/mcp/tools/core-files.mcp-tools.ts +105 -0
  317. package/src/mcp/tools/core-integration-events.mcp-tools.ts +118 -0
  318. package/src/mcp/tools/core-mail-profile.mcp-tools.ts +128 -0
  319. package/src/mcp/tools/core-mail-sent.mcp-tools.ts +76 -0
  320. package/src/mcp/tools/core-mail.mcp-tools.ts +130 -0
  321. package/src/mcp/tools/core-mcp-chat.mcp-tools.ts +81 -0
  322. package/src/mcp/tools/core-menus.mcp-tools.ts +197 -0
  323. package/src/mcp/tools/core-notifications.mcp-tools.ts +128 -0
  324. package/src/mcp/tools/core-profile.mcp-tools.ts +74 -0
  325. package/src/mcp/tools/core-roles.mcp-tools.ts +288 -0
  326. package/src/mcp/tools/core-routes.mcp-tools.ts +196 -0
  327. package/src/mcp/tools/core-screens.mcp-tools.ts +186 -0
  328. package/src/mcp/tools/core-sessions.mcp-tools.ts +97 -0
  329. package/src/mcp/tools/core-settings.mcp-tools.ts +171 -53
  330. package/src/mcp/tools/core-system.mcp-tools.ts +19 -0
  331. package/src/mcp/tools/core-webhooks.mcp-tools.ts +199 -0
  332. package/src/mcp-chat/mcp-chat.controller.ts +113 -60
  333. package/src/mcp-chat/mcp-chat.service.ts +1343 -332
  334. package/src/notification/dto/create-notification.dto.ts +71 -0
  335. package/src/notification/dto/update-progress.dto.ts +16 -0
  336. package/src/notification/notification.controller.ts +83 -0
  337. package/src/notification/notification.module.ts +16 -0
  338. package/src/notification/notification.service.ts +324 -0
  339. package/src/pdf/pdf.service.ts +1 -1
  340. package/src/profile/profile.controller.ts +1 -1
  341. package/src/profile/profile.module.ts +1 -0
  342. package/src/setting/dto/update-setting-list.dto.ts +32 -0
  343. package/src/setting/setting.controller.ts +9 -0
  344. package/src/setting/setting.service.ts +99 -11
  345. package/src/task/task.service.ts +103 -0
  346. package/src/token/token.service.ts +0 -2
  347. package/src/webhook-integration/dto/webhook-action.dto.ts +96 -0
  348. package/src/webhook-integration/webhook-integration.controller.ts +124 -103
  349. package/src/webhook-integration/webhook-integration.service.ts +1137 -735
  350. package/src/webhook-integration/webhook-utils.ts +136 -79
@@ -0,0 +1,16 @@
1
+ import { PaginationModule } from '@hed-hog/api-pagination';
2
+ import { PrismaModule } from '@hed-hog/api-prisma';
3
+ import { forwardRef, Module } from '@nestjs/common';
4
+ import { AccessLogController } from './access-log.controller';
5
+ import { AccessLogService } from './access-log.service';
6
+
7
+ @Module({
8
+ imports: [
9
+ forwardRef(() => PrismaModule),
10
+ forwardRef(() => PaginationModule),
11
+ ],
12
+ controllers: [AccessLogController],
13
+ providers: [AccessLogService],
14
+ exports: [AccessLogService],
15
+ })
16
+ export class AccessLogModule {}
@@ -0,0 +1,129 @@
1
+ import { PageOrderDirection, PaginationService } from '@hed-hog/api-pagination';
2
+ import { Prisma, PrismaService } from '@hed-hog/api-prisma';
3
+ import { forwardRef, Inject, Injectable, Logger } from '@nestjs/common';
4
+
5
+ interface RecordHttpData {
6
+ userId?: number;
7
+ ip?: string;
8
+ userAgent?: string;
9
+ method: string;
10
+ path: string;
11
+ }
12
+
13
+ interface RecordMcpData {
14
+ userId?: number;
15
+ mcpTool: string;
16
+ mcpPrompt?: string;
17
+ }
18
+
19
+ type AccessLogListParams = {
20
+ page?: number;
21
+ pageSize?: number;
22
+ search?: string;
23
+ sortField?: string;
24
+ sortOrder?: PageOrderDirection;
25
+ fields?: string;
26
+ userId?: number;
27
+ userSearch?: string;
28
+ createdAtFrom?: string;
29
+ createdAtTo?: string;
30
+ type?: 'http' | 'mcp' | 'all';
31
+ };
32
+
33
+ @Injectable()
34
+ export class AccessLogService {
35
+ private readonly logger = new Logger(AccessLogService.name);
36
+
37
+ constructor(
38
+ @Inject(forwardRef(() => PrismaService))
39
+ private readonly prisma: PrismaService,
40
+ @Inject(forwardRef(() => PaginationService))
41
+ private readonly pagination: PaginationService,
42
+ ) {}
43
+
44
+ recordHttp(data: RecordHttpData): void {
45
+ this.prisma.access_log
46
+ .create({
47
+ data: {
48
+ user_id: data.userId ?? null,
49
+ ip: data.ip ?? null,
50
+ user_agent: data.userAgent ?? null,
51
+ method: data.method,
52
+ path: data.path,
53
+ },
54
+ })
55
+ .catch((e) => this.logger.warn(`Failed to persist HTTP access log: ${e.message}`));
56
+ }
57
+
58
+ recordMcp(data: RecordMcpData): void {
59
+ this.prisma.access_log
60
+ .create({
61
+ data: {
62
+ user_id: data.userId ?? null,
63
+ mcp_tool: data.mcpTool,
64
+ mcp_prompt: data.mcpPrompt ?? null,
65
+ },
66
+ })
67
+ .catch((e) => this.logger.warn(`Failed to persist MCP access log: ${e.message}`));
68
+ }
69
+
70
+ async list(params: AccessLogListParams) {
71
+ const where: Prisma.access_logWhereInput = {};
72
+
73
+ if (params.userId) {
74
+ where.user_id = params.userId;
75
+ }
76
+
77
+ if (params.userSearch) {
78
+ where.user = {
79
+ OR: [
80
+ { name: { contains: params.userSearch, mode: 'insensitive' } },
81
+ ],
82
+ };
83
+ }
84
+
85
+ if (params.createdAtFrom || params.createdAtTo) {
86
+ where.created_at = {};
87
+ if (params.createdAtFrom) {
88
+ where.created_at.gte = new Date(params.createdAtFrom);
89
+ }
90
+ if (params.createdAtTo) {
91
+ const to = new Date(params.createdAtTo);
92
+ to.setHours(23, 59, 59, 999);
93
+ where.created_at.lte = to;
94
+ }
95
+ }
96
+
97
+ if (params.type === 'http') {
98
+ where.method = { not: null };
99
+ } else if (params.type === 'mcp') {
100
+ where.mcp_tool = { not: null };
101
+ }
102
+
103
+ return this.pagination.paginate(this.prisma.access_log, {
104
+ ...params,
105
+ fields: params.fields ?? '',
106
+ }, {
107
+ where,
108
+ orderBy: { created_at: 'desc' },
109
+ include: {
110
+ user: { select: { id: true, name: true, photo_id: true } },
111
+ },
112
+ });
113
+ }
114
+
115
+ async clearOld(retentionDays: number, batchLimit: number): Promise<void> {
116
+ await this.prisma.$executeRaw`
117
+ WITH del AS (
118
+ SELECT id
119
+ FROM access_log
120
+ WHERE created_at < (now() - ${Prisma.sql`INTERVAL '${Prisma.raw(String(retentionDays))} days'`})
121
+ ORDER BY id
122
+ LIMIT ${batchLimit}
123
+ )
124
+ DELETE FROM access_log al
125
+ USING del
126
+ WHERE al.id = del.id
127
+ `;
128
+ }
129
+ }
@@ -0,0 +1,23 @@
1
+ import { IsIn, IsNumberString, IsOptional, IsString } from 'class-validator';
2
+
3
+ export class QueryAccessLogDto {
4
+ @IsOptional()
5
+ @IsNumberString()
6
+ userId?: string;
7
+
8
+ @IsOptional()
9
+ @IsString()
10
+ userSearch?: string;
11
+
12
+ @IsOptional()
13
+ @IsString()
14
+ createdAtFrom?: string;
15
+
16
+ @IsOptional()
17
+ @IsString()
18
+ createdAtTo?: string;
19
+
20
+ @IsOptional()
21
+ @IsIn(['http', 'mcp', 'all'])
22
+ type?: 'http' | 'mcp' | 'all';
23
+ }
@@ -82,8 +82,6 @@ export class AuthService {
82
82
 
83
83
  async requiresMfaForLogin(locale: string, email: string, user: any) {
84
84
 
85
- console.log('MFA required, setting up email MFA');
86
-
87
85
  const settings = await this.setting.getSettingValues([
88
86
  'require-mfa',
89
87
  'require-email-verification',
@@ -387,16 +385,11 @@ export class AuthService {
387
385
 
388
386
  if (!user) throw new BadRequestException(getLocaleText('accessDenied', locale, 'Access denied.'));
389
387
 
390
- console.debug({ user });
391
-
392
388
  const credentials = (user as unknown as User).user_credential?.filter((c) => c.type === 'password') || [];
393
389
 
394
- console.debug({ credentials });
395
-
396
390
  const identifier = user.user_identifier?.find((i) => i.type === 'email' && i.value === email);
397
391
 
398
392
  if (!(await this.security.validatePassword(locale, credentials, password))) {
399
- console.debug('Invalid password');
400
393
  throw new BadRequestException(getLocaleText('accessDenied', locale, 'Access denied.'));
401
394
  }
402
395
 
@@ -376,8 +376,6 @@ export class ChallengeService {
376
376
 
377
377
  async sendMfaCodeToMultipleEmails(locale: string, userId: number, emails: string[]) {
378
378
 
379
- console.log('Sending MFA codes to multiple emails:', emails);
380
-
381
379
  if (!emails || emails.length === 0) {
382
380
  return { success: true };
383
381
  }
@@ -13,5 +13,6 @@ import { SystemService } from './system.service';
13
13
  ],
14
14
  controllers: [SystemController],
15
15
  providers: [SystemService],
16
+ exports: [SystemService],
16
17
  })
17
18
  export class SystemModule { }
@@ -1,5 +1,8 @@
1
1
  import { LogInterceptor } from '@hed-hog/api';
2
2
  import { LocaleModule } from '@hed-hog/api-locale';
3
+ import { AccessLogInterceptor } from './access-log/access-log.interceptor';
4
+ import { AccessLogModule } from './access-log/access-log.module';
5
+ import { AccessLogService } from './access-log/access-log.service';
3
6
  import { MailModule as MailSendModule } from '@hed-hog/api-mail';
4
7
  import { PaginationModule } from '@hed-hog/api-pagination';
5
8
  import { PrismaModule, PrismaService } from '@hed-hog/api-prisma';
@@ -37,6 +40,7 @@ import { IsEmailWithSettingsConstraint } from './validators/is-email-with-settin
37
40
  import { IsPinCodeWithSettingConstraint } from './validators/is-pin-code-with-setting.validator';
38
41
  import { IsStrongPasswordWithSettingsConstraint } from './validators/is-strong-password-with-settings.validator';
39
42
  import { ValidatorServiceLocator } from './validators/service-locator';
43
+ import { NotificationModule } from './notification/notification.module';
40
44
  import { WebhookIntegrationModule } from './webhook-integration/webhook-integration.module';
41
45
 
42
46
  @Global()
@@ -73,6 +77,8 @@ import { WebhookIntegrationModule } from './webhook-integration/webhook-integrat
73
77
  forwardRef(() => McpModule),
74
78
  forwardRef(() => McpChatModule),
75
79
  forwardRef(() => PdfModule),
80
+ forwardRef(() => NotificationModule),
81
+ forwardRef(() => AccessLogModule),
76
82
  ],
77
83
  exports: [
78
84
  UserModule,
@@ -94,6 +100,8 @@ import { WebhookIntegrationModule } from './webhook-integration/webhook-integrat
94
100
  IsEmailWithSettingsConstraint,
95
101
  IsPinCodeWithSettingConstraint,
96
102
  PdfModule,
103
+ NotificationModule,
104
+ AccessLogModule,
97
105
  ],
98
106
  providers: [
99
107
  Reflector,
@@ -107,6 +115,13 @@ import { WebhookIntegrationModule } from './webhook-integration/webhook-integrat
107
115
  },
108
116
  inject: [Reflector, PrismaService],
109
117
  },
118
+ {
119
+ provide: APP_INTERCEPTOR,
120
+ useFactory: (accessLogService: AccessLogService) => {
121
+ return new AccessLogInterceptor(accessLogService);
122
+ },
123
+ inject: [AccessLogService],
124
+ },
110
125
  ]
111
126
  })
112
127
  export class CoreModule implements NestModule, OnModuleInit {
@@ -23,6 +23,9 @@ import { DashboardCrudModule } from './dashboard/dashboard.module';
23
23
  ],
24
24
  controllers: [],
25
25
  providers: [],
26
- exports: [],
26
+ exports: [
27
+ forwardRef(() => DashboardCrudModule),
28
+ forwardRef(() => DashboardItemModule),
29
+ ],
27
30
  })
28
31
  export class DashboardModule {}
@@ -2,19 +2,19 @@ import { Public, Role } from '@hed-hog/api';
2
2
  import { getLocaleText, Locale } from '@hed-hog/api-locale';
3
3
  import { Pagination } from '@hed-hog/api-pagination';
4
4
  import {
5
- Body,
6
- Controller,
7
- Delete,
8
- forwardRef,
9
- Get,
10
- Inject,
11
- Param,
12
- ParseIntPipe,
13
- Post,
14
- Put,
15
- Res,
16
- UploadedFile,
17
- UseInterceptors,
5
+ Body,
6
+ Controller,
7
+ Delete,
8
+ forwardRef,
9
+ Get,
10
+ Inject,
11
+ Param,
12
+ ParseIntPipe,
13
+ Post,
14
+ Put,
15
+ Res,
16
+ UploadedFile,
17
+ UseInterceptors,
18
18
  } from '@nestjs/common';
19
19
  import { FileInterceptor } from '@nestjs/platform-express';
20
20
  import { Response } from 'express';
@@ -54,7 +54,7 @@ export class FileController {
54
54
 
55
55
  @Put('download/:id')
56
56
  async getTempURL(@Param('id', ParseIntPipe) id) {
57
- console.log('Generating temp URL for file ID:', id);
57
+
58
58
  return {
59
59
  url: await this.fileService.tempURL(
60
60
  (await this.fileService.get(id)).path,
@@ -10,6 +10,9 @@ import {
10
10
  OnModuleInit
11
11
  } from '@nestjs/common';
12
12
  import { JwtService } from '@nestjs/jwt';
13
+ import { createWriteStream, promises as fs } from 'fs';
14
+ import { basename, dirname } from 'path';
15
+ import { pipeline } from 'stream/promises';
13
16
  import { SettingService } from '../setting/setting.service';
14
17
  import { DeleteDTO } from './dto/delete.dto';
15
18
  import { AbstractProvider } from './provider/abstract.provider';
@@ -235,6 +238,113 @@ export class FileService implements OnModuleInit {
235
238
  return settings['storage'];
236
239
  }
237
240
 
241
+ private getProviderPath(storage: string, filepath: string) {
242
+ if (storage === EnumProvider.LOCAL) {
243
+ return filepath;
244
+ }
245
+
246
+ try {
247
+ return new URL(filepath).pathname;
248
+ } catch {
249
+ return filepath;
250
+ }
251
+ }
252
+
253
+ private mapStorageNotFoundError(error: any, fileId: number) {
254
+ const missingInStorage =
255
+ error?.name === 'NoSuchKey' ||
256
+ error?.Code === 'NoSuchKey' ||
257
+ error?.$metadata?.httpStatusCode === 404;
258
+
259
+ if (missingInStorage) {
260
+ throw new NotFoundException(`File not found in storage: ${fileId}`);
261
+ }
262
+
263
+ throw error;
264
+ }
265
+
266
+ async openReadStreamById(fileId: number) {
267
+ if (!fileId) {
268
+ throw new BadRequestException(`No file ID provided`);
269
+ }
270
+
271
+ const file = await this.prismaService.file.findUnique({
272
+ where: {
273
+ id: fileId,
274
+ },
275
+ include: {
276
+ file_mimetype: true,
277
+ },
278
+ });
279
+
280
+ if (!file) {
281
+ throw new NotFoundException(`File not found: ${fileId}`);
282
+ }
283
+
284
+ const storage = await this.getStorage();
285
+ const provider = await this.getProvider();
286
+ const providerPath = this.getProviderPath(storage, file.path);
287
+
288
+ let metadata: any;
289
+ try {
290
+ metadata = await provider.metaData(providerPath);
291
+ } catch {
292
+ metadata = undefined;
293
+ }
294
+
295
+ try {
296
+ const stream = await provider.readStream(providerPath);
297
+ return {
298
+ file,
299
+ stream,
300
+ size: file.size ?? this.getFileSizeFromMetadata(metadata),
301
+ };
302
+ } catch (error) {
303
+ this.mapStorageNotFoundError(error, fileId);
304
+ }
305
+ }
306
+
307
+ async downloadToPath(
308
+ fileId: number,
309
+ destinationPath: string,
310
+ options?: { maxBytes?: number },
311
+ ) {
312
+ if (!destinationPath) {
313
+ throw new BadRequestException(`No destination path provided`);
314
+ }
315
+
316
+ const { file, stream, size } = await this.openReadStreamById(fileId);
317
+
318
+ if (options?.maxBytes && size && size > options.maxBytes) {
319
+ throw new BadRequestException(
320
+ `File too large for streaming download: ${size} bytes (max ${options.maxBytes})`,
321
+ );
322
+ }
323
+
324
+ await fs.mkdir(dirname(destinationPath), { recursive: true });
325
+
326
+ try {
327
+ await pipeline(stream, createWriteStream(destinationPath));
328
+ const stats = await fs.stat(destinationPath);
329
+
330
+ if (options?.maxBytes && stats.size > options.maxBytes) {
331
+ await fs.unlink(destinationPath).catch(() => undefined);
332
+ throw new BadRequestException(
333
+ `File too large for streaming download: ${stats.size} bytes (max ${options.maxBytes})`,
334
+ );
335
+ }
336
+
337
+ return {
338
+ file,
339
+ path: destinationPath,
340
+ size: stats.size,
341
+ };
342
+ } catch (error) {
343
+ await fs.unlink(destinationPath).catch(() => undefined);
344
+ throw error;
345
+ }
346
+ }
347
+
238
348
  async getBuffer(fileId: number) {
239
349
 
240
350
  if (!fileId) {
@@ -258,8 +368,7 @@ export class FileService implements OnModuleInit {
258
368
 
259
369
  const provider = await this.getProvider();
260
370
 
261
- const providerPath =
262
- storage === EnumProvider.LOCAL ? file.path : new URL(file.path).pathname;
371
+ const providerPath = this.getProviderPath(storage, file.path);
263
372
 
264
373
  let providerBuffer: Buffer;
265
374
  try {
@@ -341,6 +450,89 @@ export class FileService implements OnModuleInit {
341
450
  return file;
342
451
  }
343
452
 
453
+ async uploadFromPath(
454
+ destination: string,
455
+ filePath: string,
456
+ metadata?: {
457
+ originalname?: string;
458
+ filename?: string;
459
+ mimetype?: string;
460
+ size?: number;
461
+ encoding?: string;
462
+ },
463
+ ) {
464
+ if (!filePath) {
465
+ throw new BadRequestException(`No file path provided`);
466
+ }
467
+
468
+ if (!destination) {
469
+ throw new BadRequestException(`No destination provided`);
470
+ }
471
+
472
+ const stats = await fs.stat(filePath).catch(() => null);
473
+ if (!stats || !stats.isFile()) {
474
+ throw new NotFoundException(`File path not found: ${filePath}`);
475
+ }
476
+
477
+ const size = metadata?.size ?? stats.size;
478
+ const mimetype = metadata?.mimetype ?? 'application/octet-stream';
479
+ const originalname = this.normalizeUploadedFilename(
480
+ metadata?.originalname ?? metadata?.filename ?? basename(filePath),
481
+ );
482
+
483
+ if (!(await this.acceptMimetypes(mimetype))) {
484
+ throw new BadRequestException(`Invalid file type: ${mimetype}`);
485
+ }
486
+
487
+ if (!(await this.maxFileSize(size))) {
488
+ throw new BadRequestException(`File too large: ${size} bytes`);
489
+ }
490
+
491
+ const provider = await this.getProvider();
492
+ const providerWithPathUpload = provider as AbstractProvider & {
493
+ uploadFromPath?: (
494
+ destination: string,
495
+ filePath: string,
496
+ options?: { filename?: string; mimetype?: string },
497
+ ) => Promise<string>;
498
+ };
499
+
500
+ let url: string;
501
+ if (typeof providerWithPathUpload.uploadFromPath === 'function') {
502
+ url = await providerWithPathUpload.uploadFromPath(destination, filePath, {
503
+ filename: originalname,
504
+ mimetype,
505
+ });
506
+ } else {
507
+ // Fallback explícito para providers legados sem suporte nativo por path.
508
+ const buffer = await fs.readFile(filePath);
509
+ url = await provider.upload(destination, {
510
+ fieldname: 'file',
511
+ originalname,
512
+ encoding: metadata?.encoding ?? '7bit',
513
+ mimetype,
514
+ size,
515
+ destination: '',
516
+ filename: originalname,
517
+ path: filePath,
518
+ buffer,
519
+ });
520
+ }
521
+
522
+ const file = await this.prismaService.file.create({
523
+ data: {
524
+ filename: originalname,
525
+ path: url,
526
+ provider_id: this.providerId,
527
+ location: destination,
528
+ mimetype_id: await this.getMimeType(mimetype),
529
+ size,
530
+ },
531
+ });
532
+
533
+ return file;
534
+ }
535
+
344
536
  async delete(locale:string,{ ids }: DeleteDTO) {
345
537
  const files = await this.prismaService.file.findMany({
346
538
  where: {
@@ -482,9 +674,11 @@ export class FileService implements OnModuleInit {
482
674
  );
483
675
  }
484
676
 
677
+ const storage = await this.getStorage();
485
678
  const provider = await this.getProvider();
486
- const metadata = await provider.metaData(file.path);
487
- const stream = await provider.readStream(file.path);
679
+ const providerPath = this.getProviderPath(storage, file.path);
680
+ const metadata = await provider.metaData(providerPath);
681
+ const stream = await provider.readStream(providerPath);
488
682
  const size = this.getFileSizeFromMetadata(metadata);
489
683
 
490
684
  return {
@@ -9,6 +9,11 @@ interface IProvider {
9
9
  mimetype?: string,
10
10
  ): Promise<any>;
11
11
  upload(destination: string, file: MulterFile): Promise<any>;
12
+ uploadFromPath(
13
+ destination: string,
14
+ filePath: string,
15
+ options?: { filename?: string; mimetype?: string },
16
+ ): Promise<any>;
12
17
  readStream(filepath: string): Promise<any>;
13
18
  delete(filepath: string): Promise<any>;
14
19
  metaData(filepath: string): Promise<any>;
@@ -25,6 +30,11 @@ export abstract class AbstractProvider implements IProvider {
25
30
  mimetype?: string,
26
31
  ): Promise<any>;
27
32
  abstract upload(destination: string, file: MulterFile): Promise<any>;
33
+ abstract uploadFromPath(
34
+ destination: string,
35
+ filePath: string,
36
+ options?: { filename?: string; mimetype?: string },
37
+ ): Promise<any>;
28
38
  abstract readStream(filepath: string): Promise<any>;
29
39
  abstract delete(filepath: string): Promise<any>;
30
40
  abstract metaData(filepath: string): Promise<any>;
@@ -5,6 +5,7 @@ import {
5
5
  StorageSharedKeyCredential,
6
6
  } from '@azure/storage-blob';
7
7
  import { BadRequestException } from '@nestjs/common';
8
+ import { basename } from 'path';
8
9
  import { AbstractProvider } from './abstract.provider';
9
10
 
10
11
  export class AzureProvider extends AbstractProvider {
@@ -92,6 +93,29 @@ export class AzureProvider extends AbstractProvider {
92
93
  return `https://${this.setting['storage-abs-container']}.azureedge.net/${filepath}`;
93
94
  }
94
95
 
96
+ async uploadFromPath(
97
+ destination: string,
98
+ filePath: string,
99
+ options?: { filename?: string; mimetype?: string },
100
+ ): Promise<any> {
101
+ const blobServiceClient = await this.getClient();
102
+ const containerClient = blobServiceClient.getContainerClient(
103
+ this.setting['storage-abs-container'],
104
+ );
105
+ const filepath = [destination, this.getFilename(options?.filename ?? basename(filePath))].join(
106
+ '/',
107
+ );
108
+ const blobClient = containerClient.getBlockBlobClient(filepath);
109
+
110
+ await blobClient.uploadFile(filePath, {
111
+ blobHTTPHeaders: options?.mimetype
112
+ ? { blobContentType: options.mimetype }
113
+ : undefined,
114
+ });
115
+
116
+ return `https://${this.setting['storage-abs-container']}.azureedge.net/${filepath}`;
117
+ }
118
+
95
119
  async delete(filepath: string): Promise<any> {
96
120
  const url = new URL(filepath);
97
121
 
@@ -1,5 +1,6 @@
1
1
  import { Storage } from '@google-cloud/storage';
2
2
  import { BadRequestException } from '@nestjs/common';
3
+ import { basename } from 'path';
3
4
  import { AbstractProvider } from './abstract.provider';
4
5
 
5
6
  export class GCSProvider extends AbstractProvider {
@@ -67,6 +68,25 @@ export class GCSProvider extends AbstractProvider {
67
68
  contentType: file.mimetype,
68
69
  });
69
70
  }
71
+
72
+ async uploadFromPath(
73
+ destination: string,
74
+ filePath: string,
75
+ options?: { filename?: string; mimetype?: string },
76
+ ): Promise<any> {
77
+ const storage = await this.getClient();
78
+ const bucket = storage.bucket(this.setting['storage-gcs-bucket']);
79
+ const objectPath = [destination.replace(/\/$/, ''), this.getFilename(options?.filename ?? basename(filePath))]
80
+ .filter(Boolean)
81
+ .join('/');
82
+
83
+ await bucket.upload(filePath, {
84
+ destination: objectPath,
85
+ contentType: options?.mimetype,
86
+ });
87
+
88
+ return objectPath;
89
+ }
70
90
  async readStream(filepath: string): Promise<any> {
71
91
  const storage = await this.getClient();
72
92
  const bucket = storage.bucket(this.setting['storage-gcs-bucket']);
@@ -1,9 +1,9 @@
1
1
  import { BadRequestException } from '@nestjs/common';
2
2
  import { JwtService } from '@nestjs/jwt';
3
3
  import { createReadStream, existsSync, promises as fs } from 'fs';
4
- import { mkdir, unlink, writeFile } from 'fs/promises';
4
+ import { copyFile, mkdir, stat, unlink, writeFile } from 'fs/promises';
5
5
  import * as path from 'path';
6
- import { join, sep } from 'path';
6
+ import { basename, join, sep } from 'path';
7
7
  import { Stream } from 'stream';
8
8
  import { AbstractProvider } from './abstract.provider';
9
9
 
@@ -99,6 +99,34 @@ export class LocalProvider extends AbstractProvider {
99
99
  return filePath;
100
100
  }
101
101
 
102
+ async uploadFromPath(
103
+ destination: string,
104
+ filePath: string,
105
+ options?: { filename?: string; mimetype?: string },
106
+ ): Promise<any> {
107
+ const sourcePath = this.resolveFilepath(filePath);
108
+ if (!existsSync(sourcePath)) {
109
+ throw new BadRequestException(`File not found: ${sourcePath}`);
110
+ }
111
+
112
+ const sourceStats = await stat(sourcePath);
113
+ if (!sourceStats.isFile()) {
114
+ throw new BadRequestException(`Invalid file path: ${sourcePath}`);
115
+ }
116
+
117
+ const storagePath = join(this.setting['storage-local-path'], destination);
118
+
119
+ if (!existsSync(storagePath)) {
120
+ await this.createFolderRecursive(storagePath);
121
+ }
122
+
123
+ const targetFilename = this.getFilename(options?.filename ?? basename(sourcePath));
124
+ const targetPath = join(storagePath, targetFilename);
125
+ await copyFile(sourcePath, targetPath);
126
+
127
+ return targetPath;
128
+ }
129
+
102
130
  async delete(filepath: string): Promise<any> {
103
131
  const fullPath = this.resolveFilepath(filepath);
104
132