@goplusvn/core 0.1.0 → 0.1.1

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 (369) hide show
  1. package/package.json +2 -1
  2. package/src/assets/erp_wallpaper.png +0 -0
  3. package/src/assets/goeat_logo.png +0 -0
  4. package/src/audit/audit-manager.ts +139 -0
  5. package/src/audit/index.ts +11 -0
  6. package/src/audit/memory-audit-logger.ts +86 -0
  7. package/src/audit/types.ts +50 -0
  8. package/src/auth/auth-service.ts +97 -0
  9. package/src/auth/index.ts +266 -0
  10. package/src/code-generation/index.ts +69 -0
  11. package/src/configs/auth-routes.ts +17 -0
  12. package/src/configs/crud.ts +136 -0
  13. package/src/configs/data/navigations.ts +781 -0
  14. package/src/configs/data/oauth-links.ts +10 -0
  15. package/src/configs/entities/material-categories.config.ts +125 -0
  16. package/src/configs/i18n.ts +12 -0
  17. package/src/configs/index.ts +26 -0
  18. package/src/configs/status.ts +25 -0
  19. package/src/configs/themes.ts +100 -0
  20. package/src/crud/components/crud-bulk-actions.tsx +91 -0
  21. package/src/crud/components/crud-card-view.tsx +241 -0
  22. package/src/crud/components/crud-context.tsx +122 -0
  23. package/src/crud/components/crud-delete-dialog.tsx +145 -0
  24. package/src/crud/components/crud-dialog.tsx +406 -0
  25. package/src/crud/components/crud-empty-state.tsx +104 -0
  26. package/src/crud/components/crud-export-button.tsx +170 -0
  27. package/src/crud/components/crud-field-renderer.tsx +653 -0
  28. package/src/crud/components/crud-filter-chips.tsx +102 -0
  29. package/src/crud/components/crud-filters/checkbox-filter.tsx +97 -0
  30. package/src/crud/components/crud-filters/datetime-filter.tsx +83 -0
  31. package/src/crud/components/crud-filters/filter-builder.tsx +66 -0
  32. package/src/crud/components/crud-filters/index.tsx +76 -0
  33. package/src/crud/components/crud-filters/radio-filter.tsx +86 -0
  34. package/src/crud/components/crud-filters/select-filter.tsx +141 -0
  35. package/src/crud/components/crud-filters/text-filter.tsx +86 -0
  36. package/src/crud/components/crud-form.tsx +642 -0
  37. package/src/crud/components/crud-import-dialog.tsx +440 -0
  38. package/src/crud/components/crud-infinite-scroll.tsx +116 -0
  39. package/src/crud/components/crud-page.tsx +1017 -0
  40. package/src/crud/components/crud-provider.tsx +277 -0
  41. package/src/crud/components/crud-row-actions.tsx +189 -0
  42. package/src/crud/components/crud-search.tsx +82 -0
  43. package/src/crud/components/crud-sheet.tsx +336 -0
  44. package/src/crud/components/crud-table-skeleton.tsx +26 -0
  45. package/src/crud/components/crud-table-toolbar.tsx +91 -0
  46. package/src/crud/components/crud-table.tsx +352 -0
  47. package/src/crud/components/crud-virtual-table.tsx +55 -0
  48. package/src/crud/components/index.tsx +20 -0
  49. package/src/crud/crud-filters/checkbox-filter.tsx +87 -0
  50. package/src/crud/crud-filters/datetime-filter.tsx +82 -0
  51. package/src/crud/crud-filters/filter-builder.tsx +64 -0
  52. package/src/crud/crud-filters/index.tsx +78 -0
  53. package/src/crud/crud-filters/radio-filter.tsx +79 -0
  54. package/src/crud/crud-filters/select-filter.tsx +148 -0
  55. package/src/crud/crud-filters/text-filter.tsx +81 -0
  56. package/src/crud/index.ts +43 -0
  57. package/src/crud/lib/crud-service.test.ts +334 -0
  58. package/src/crud/lib/crud-service.ts +358 -0
  59. package/src/crud/lib/crud-utils.test.ts +354 -0
  60. package/src/crud/lib/crud-utils.ts +299 -0
  61. package/src/crud/lib/crud-validator.ts +247 -0
  62. package/src/crud/lib/data-loader.ts +234 -0
  63. package/src/crud/lib/field-calculator.ts +241 -0
  64. package/src/crud/lib/field-formatter.ts +240 -0
  65. package/src/crud/lib/import-export-service.test.ts +290 -0
  66. package/src/crud/lib/import-export-service.ts +352 -0
  67. package/src/crud/lib/import-server-utils.ts +109 -0
  68. package/src/crud/lib/lazy-loader.ts +241 -0
  69. package/src/crud/lib/parse-filters.ts +85 -0
  70. package/src/crud/lib/permissions.ts +52 -0
  71. package/src/crud/lib/serialize-config.ts +60 -0
  72. package/src/crud/lib/stream-loader.ts +145 -0
  73. package/src/crud/lib/translate-config.ts +335 -0
  74. package/src/crud/lib/types.ts +11 -0
  75. package/src/crud/pages/entity-crud-page.tsx +144 -0
  76. package/src/crud/server.ts +8 -0
  77. package/src/home/constants.tsx +142 -0
  78. package/src/home/feature-showcase.tsx +171 -0
  79. package/src/home/home-page.tsx +191 -0
  80. package/src/home/hooks/index.ts +1 -0
  81. package/src/home/hooks/useWidgetPreferences.ts +167 -0
  82. package/src/home/index.ts +33 -0
  83. package/src/home/quick-access-dialog.tsx +271 -0
  84. package/src/home/quick-access-menu.tsx +267 -0
  85. package/src/home/types.ts +140 -0
  86. package/src/home/welcome-card.tsx +92 -0
  87. package/src/home/widget-container.tsx +258 -0
  88. package/src/home/widgets/base-widget.tsx +200 -0
  89. package/src/home/widgets/customers-widget.tsx +74 -0
  90. package/src/home/widgets/index.ts +6 -0
  91. package/src/home/widgets/orders-widget.tsx +87 -0
  92. package/src/home/widgets/revenue-widget.tsx +71 -0
  93. package/src/home/widgets/stock-widget.tsx +109 -0
  94. package/src/hooks/index.tsx +598 -0
  95. package/src/hooks/use-tenant.test.tsx +30 -0
  96. package/src/hooks/use-tenant.ts +5 -0
  97. package/src/index.ts +17 -0
  98. package/src/infrastructure/__tests__/architecture-verification.spec.ts +103 -0
  99. package/src/infrastructure/api-service.ts +317 -0
  100. package/src/infrastructure/cache/cache-manager.ts +107 -0
  101. package/src/infrastructure/cache/cache.ts +120 -0
  102. package/src/infrastructure/cache/index.ts +8 -0
  103. package/src/infrastructure/cache/types.ts +48 -0
  104. package/src/infrastructure/cron/cron-manager.ts +239 -0
  105. package/src/infrastructure/cron/index.ts +6 -0
  106. package/src/infrastructure/cron/types.ts +41 -0
  107. package/src/infrastructure/event-bus/event-bus.ts +145 -0
  108. package/src/infrastructure/event-bus/index.ts +2 -0
  109. package/src/infrastructure/event-bus/types.ts +22 -0
  110. package/src/infrastructure/index.ts +32 -0
  111. package/src/infrastructure/lock/decorators.ts +67 -0
  112. package/src/infrastructure/lock/index.ts +2 -0
  113. package/src/infrastructure/lock/lock-manager.ts +33 -0
  114. package/src/infrastructure/logger/index.ts +2 -0
  115. package/src/infrastructure/logger/logger.ts +96 -0
  116. package/src/infrastructure/logger/types.ts +25 -0
  117. package/src/layout/index.tsx +185 -0
  118. package/src/navigation/index.ts +91 -0
  119. package/src/notification/index.ts +14 -0
  120. package/src/notification/notification-service.ts +120 -0
  121. package/src/notification/storage/in-memory.ts +56 -0
  122. package/src/notification/storage/index.ts +1 -0
  123. package/src/notification/types.ts +51 -0
  124. package/src/organization/branch-service.ts +299 -0
  125. package/src/organization/branches.config.ts +154 -0
  126. package/src/organization/index.ts +5 -0
  127. package/src/plugin/apps-registry.ts +97 -0
  128. package/src/plugin/index.ts +5 -0
  129. package/src/plugin/types.ts +41 -0
  130. package/src/providers/index.tsx +109 -0
  131. package/src/providers/tenant-provider.tsx +45 -0
  132. package/src/rbac/components/roles/role-card.tsx +158 -0
  133. package/src/rbac/components/roles/role-stats-cards.tsx +29 -0
  134. package/src/rbac/components/roles/role-toolbar.tsx +123 -0
  135. package/src/rbac/hooks/use-role-operations.ts +159 -0
  136. package/src/rbac/hooks/use-roles-data.ts +59 -0
  137. package/src/rbac/index.ts +297 -0
  138. package/src/rbac/lib/permission-helpers.ts +63 -0
  139. package/src/rbac/pages/action-list-page.tsx +25 -0
  140. package/src/rbac/pages/resource-list-page.tsx +25 -0
  141. package/src/rbac/pages/role-list-page.tsx +378 -0
  142. package/src/rbac/permission-service.ts +140 -0
  143. package/src/rbac/permissions.ts +135 -0
  144. package/src/rbac/resource-service.ts +115 -0
  145. package/src/rbac/resource-validator.ts +119 -0
  146. package/src/rbac/role-service.ts +165 -0
  147. package/src/rbac/server.ts +16 -0
  148. package/src/rbac/types.ts +38 -0
  149. package/src/schemas/action.schema.ts +66 -0
  150. package/src/schemas/branch.schema.ts +52 -0
  151. package/src/schemas/coming-soon-schema.ts +9 -0
  152. package/src/schemas/company.schema.ts +44 -0
  153. package/src/schemas/forgot-passward-schema.ts +9 -0
  154. package/src/schemas/index.ts +30 -0
  155. package/src/schemas/material-category.schema.ts +43 -0
  156. package/src/schemas/material-pricing.schema.ts +74 -0
  157. package/src/schemas/material.schema.ts +76 -0
  158. package/src/schemas/materials.ts +52 -0
  159. package/src/schemas/new-passward-schema.ts +15 -0
  160. package/src/schemas/partner-company.schema.ts +149 -0
  161. package/src/schemas/register-schema.ts +36 -0
  162. package/src/schemas/resource.schema.ts +133 -0
  163. package/src/schemas/role.schema.ts +11 -0
  164. package/src/schemas/sign-in-schema.ts +24 -0
  165. package/src/schemas/supplier-pricing.schema.ts +15 -0
  166. package/src/schemas/supplier.schema.ts +120 -0
  167. package/src/schemas/system-category-group.schema.ts +67 -0
  168. package/src/schemas/system-category.schema.ts +77 -0
  169. package/src/schemas/system-config.schema.ts +118 -0
  170. package/src/schemas/uom.schema.ts +75 -0
  171. package/src/schemas/user-supplier.schema.ts +179 -0
  172. package/src/schemas/user.schema.ts +18 -0
  173. package/src/schemas/verify-email-schema.ts +9 -0
  174. package/src/schemas/warehouse.schema.ts +49 -0
  175. package/src/system/components/categories/category-list.tsx +529 -0
  176. package/src/system/components/categories/category-manager.tsx +89 -0
  177. package/src/system/components/categories/group-sidebar.tsx +308 -0
  178. package/src/system/components/settings/setting-dialogs.tsx +197 -0
  179. package/src/system/components/settings/setting-field.tsx +291 -0
  180. package/src/system/components/settings/setting-form-dialog.tsx +308 -0
  181. package/src/system/components/settings/settings-groups.ts +80 -0
  182. package/src/system/components/settings/settings-search.tsx +71 -0
  183. package/src/system/components/settings/settings-section.tsx +74 -0
  184. package/src/system/components/settings/settings-sidebar.tsx +81 -0
  185. package/src/system/constants.ts +3 -0
  186. package/src/system/index.ts +150 -0
  187. package/src/system/job-manager.ts +176 -0
  188. package/src/system/pages/components/categories/category-list.tsx +537 -0
  189. package/src/system/pages/components/categories/category-manager.tsx +90 -0
  190. package/src/system/pages/components/categories/group-sidebar.tsx +311 -0
  191. package/src/system/pages/components/settings/sales-rules-settings.tsx +222 -0
  192. package/src/system/pages/components/settings/setting-dialogs.tsx +197 -0
  193. package/src/system/pages/components/settings/setting-field.tsx +292 -0
  194. package/src/system/pages/components/settings/setting-form-dialog.tsx +308 -0
  195. package/src/system/pages/components/settings/settings-groups.ts +87 -0
  196. package/src/system/pages/components/settings/settings-page.tsx +372 -0
  197. package/src/system/pages/components/settings/settings-search.tsx +71 -0
  198. package/src/system/pages/components/settings/settings-section.tsx +74 -0
  199. package/src/system/pages/components/settings/settings-sidebar.tsx +81 -0
  200. package/src/system/pages/components/settings/system-settings.tsx +244 -0
  201. package/src/system/pages/system-category-page.tsx +15 -0
  202. package/src/system/pages/system-settings-page.tsx +380 -0
  203. package/src/system/schemas/system-category-group.schema.ts +46 -0
  204. package/src/system/schemas/system-category.schema.ts +56 -0
  205. package/src/system/services/settings-service.ts +127 -0
  206. package/src/system/services/system-category-service.ts +63 -0
  207. package/src/system/types.ts +45 -0
  208. package/src/types/index.ts +703 -0
  209. package/src/ui/auth/auth-layout.tsx +135 -0
  210. package/src/ui/auth/forgot-password-form.tsx +98 -0
  211. package/src/ui/auth/index.tsx +7 -0
  212. package/src/ui/auth/new-password-form.tsx +107 -0
  213. package/src/ui/auth/oauth-links.tsx +30 -0
  214. package/src/ui/auth/register-form.tsx +202 -0
  215. package/src/ui/auth/sign-in-form.tsx +238 -0
  216. package/src/ui/auth/verify-email-form.tsx +104 -0
  217. package/src/ui/crud/index.tsx +10 -0
  218. package/src/ui/data-display/accordion.tsx +65 -0
  219. package/src/ui/data-display/aspect-ratio.tsx +11 -0
  220. package/src/ui/data-display/avatar.tsx +163 -0
  221. package/src/ui/data-display/bento-grid.tsx +77 -0
  222. package/src/ui/data-display/carousel.tsx +249 -0
  223. package/src/ui/data-display/chart.tsx +363 -0
  224. package/src/ui/data-display/code-block-highlight.tsx +54 -0
  225. package/src/ui/data-display/collapsible.tsx +42 -0
  226. package/src/ui/data-display/compact-stat-bar.tsx +149 -0
  227. package/src/ui/data-display/data-table/data-table-context.tsx +255 -0
  228. package/src/ui/data-display/data-table/data-table-empty-state.tsx +133 -0
  229. package/src/ui/data-display/data-table/data-table-skeleton.tsx +145 -0
  230. package/src/ui/data-display/data-table/data-table-toolbar.tsx +353 -0
  231. package/src/ui/data-display/data-table/data-table.tsx +597 -0
  232. package/src/ui/data-display/data-table/index.ts +44 -0
  233. package/src/ui/data-display/data-table-column-header.tsx +75 -0
  234. package/src/ui/data-display/data-table-pagination.tsx +130 -0
  235. package/src/ui/data-display/data-table-view-options.tsx +59 -0
  236. package/src/ui/data-display/formatted-number-input.tsx +210 -0
  237. package/src/ui/data-display/highlight.tsx +20 -0
  238. package/src/ui/data-display/hover-card.tsx +48 -0
  239. package/src/ui/data-display/index.tsx +50 -0
  240. package/src/ui/data-display/iphone-15-pro.tsx +114 -0
  241. package/src/ui/data-display/kanban/index.ts +4 -0
  242. package/src/ui/data-display/kanban/kanban-board.tsx +192 -0
  243. package/src/ui/data-display/kanban/kanban-column.tsx +74 -0
  244. package/src/ui/data-display/kanban/kanban-item.tsx +50 -0
  245. package/src/ui/data-display/kanban/kanban-types.ts +21 -0
  246. package/src/ui/data-display/kpi-card.tsx +68 -0
  247. package/src/ui/data-display/media-grid.tsx +110 -0
  248. package/src/ui/data-display/safari.tsx +175 -0
  249. package/src/ui/data-display/show-more-text.tsx +55 -0
  250. package/src/ui/data-display/tabs.tsx +68 -0
  251. package/src/ui/data-display/timeline.tsx +256 -0
  252. package/src/ui/feedback/alert.tsx +60 -0
  253. package/src/ui/feedback/context-menu.tsx +245 -0
  254. package/src/ui/feedback/drawer.tsx +132 -0
  255. package/src/ui/feedback/error-dialog.tsx +273 -0
  256. package/src/ui/feedback/index.tsx +183 -0
  257. package/src/ui/feedback/progress.tsx +32 -0
  258. package/src/ui/feedback/sheet.tsx +148 -0
  259. package/src/ui/feedback/sonner.tsx +36 -0
  260. package/src/ui/forms/command.tsx +157 -0
  261. package/src/ui/forms/date-picker.tsx +73 -0
  262. package/src/ui/forms/date-range-picker.tsx +76 -0
  263. package/src/ui/forms/date-time-picker.tsx +109 -0
  264. package/src/ui/forms/editor/editor-menu-bar.tsx +394 -0
  265. package/src/ui/forms/editor/index.tsx +130 -0
  266. package/src/ui/forms/editor/multi-select-example.tsx +1234 -0
  267. package/src/ui/forms/emoji-picker.tsx +109 -0
  268. package/src/ui/forms/file-dropzone.tsx +169 -0
  269. package/src/ui/forms/file-thumbnail.tsx +29 -0
  270. package/src/ui/forms/index.tsx +201 -0
  271. package/src/ui/forms/input-file.tsx +99 -0
  272. package/src/ui/forms/input-group.tsx +46 -0
  273. package/src/ui/forms/input-otp.tsx +81 -0
  274. package/src/ui/forms/input-phone.tsx +172 -0
  275. package/src/ui/forms/input-spin.tsx +116 -0
  276. package/src/ui/forms/input-tags.tsx +219 -0
  277. package/src/ui/forms/input-time.tsx +42 -0
  278. package/src/ui/forms/multi-select.tsx +629 -0
  279. package/src/ui/forms/multiple-date-picker.tsx +74 -0
  280. package/src/ui/forms/radio-group.tsx +42 -0
  281. package/src/ui/forms/rating.tsx +158 -0
  282. package/src/ui/forms/time-picker.tsx +57 -0
  283. package/src/ui/index.tsx +17 -0
  284. package/src/ui/layout/animated-list.tsx +77 -0
  285. package/src/ui/layout/animated-sidebar.tsx +294 -0
  286. package/src/ui/layout/command-menu.tsx +355 -0
  287. package/src/ui/layout/customizer.tsx +324 -0
  288. package/src/ui/layout/footer.tsx +43 -0
  289. package/src/ui/layout/full-screen-toggle.tsx +52 -0
  290. package/src/ui/layout/header-breadcrumb.tsx +77 -0
  291. package/src/ui/layout/horizontal-layout-header.tsx +83 -0
  292. package/src/ui/layout/horizontal-layout.tsx +50 -0
  293. package/src/ui/layout/index.tsx +25 -0
  294. package/src/ui/layout/language-dropdown.tsx +103 -0
  295. package/src/ui/layout/logo.tsx +63 -0
  296. package/src/ui/layout/main-layout.tsx +57 -0
  297. package/src/ui/layout/mode-dropdown.tsx +58 -0
  298. package/src/ui/layout/notification-dropdown.tsx +127 -0
  299. package/src/ui/layout/page-tabs.tsx +306 -0
  300. package/src/ui/layout/route-cache.tsx +214 -0
  301. package/src/ui/layout/sidebar-group-icon-menu.tsx +195 -0
  302. package/src/ui/layout/sidebar.tsx +279 -0
  303. package/src/ui/layout/tab-content-cache.tsx +201 -0
  304. package/src/ui/layout/tab-navigation-provider.tsx +536 -0
  305. package/src/ui/layout/toggle-mobile-sidebar.tsx +33 -0
  306. package/src/ui/layout/top-bar-header-menubar.tsx +412 -0
  307. package/src/ui/layout/user-dropdown.tsx +188 -0
  308. package/src/ui/layout/vertical-layout-header.tsx +65 -0
  309. package/src/ui/layout/vertical-layout.tsx +47 -0
  310. package/src/ui/management/audit-log-page.tsx +209 -0
  311. package/src/ui/management/cache-management.tsx +349 -0
  312. package/src/ui/management/index.ts +3 -0
  313. package/src/ui/management/job-management.tsx +308 -0
  314. package/src/ui/pages/not-found.tsx +30 -0
  315. package/src/ui/primitives/badge.tsx +66 -0
  316. package/src/ui/primitives/breadcrumb.tsx +103 -0
  317. package/src/ui/primitives/button.tsx +129 -0
  318. package/src/ui/primitives/calendar.tsx +74 -0
  319. package/src/ui/primitives/card.tsx +86 -0
  320. package/src/ui/primitives/checkbox.tsx +31 -0
  321. package/src/ui/primitives/client.ts +30 -0
  322. package/src/ui/primitives/combobox.tsx +290 -0
  323. package/src/ui/primitives/dialog.tsx +121 -0
  324. package/src/ui/primitives/dropdown-menu.tsx +239 -0
  325. package/src/ui/primitives/dynamic-icon.tsx +24 -0
  326. package/src/ui/primitives/index.tsx +134 -0
  327. package/src/ui/primitives/input-number.tsx +131 -0
  328. package/src/ui/primitives/input.tsx +22 -0
  329. package/src/ui/primitives/keyboard.tsx +23 -0
  330. package/src/ui/primitives/label.tsx +24 -0
  331. package/src/ui/primitives/menubar.tsx +262 -0
  332. package/src/ui/primitives/navigation-menu.tsx +157 -0
  333. package/src/ui/primitives/pagination.tsx +118 -0
  334. package/src/ui/primitives/popover.tsx +56 -0
  335. package/src/ui/primitives/prefetch-link.tsx +60 -0
  336. package/src/ui/primitives/resizable.tsx +59 -0
  337. package/src/ui/primitives/scroll-area.tsx +63 -0
  338. package/src/ui/primitives/select.tsx +172 -0
  339. package/src/ui/primitives/separator.tsx +51 -0
  340. package/src/ui/primitives/sidebar.tsx +844 -0
  341. package/src/ui/primitives/slider.tsx +27 -0
  342. package/src/ui/primitives/status-badge.tsx +47 -0
  343. package/src/ui/primitives/sticky-layout.tsx +50 -0
  344. package/src/ui/primitives/switch.tsx +29 -0
  345. package/src/ui/primitives/table.tsx +116 -0
  346. package/src/ui/primitives/tabs.tsx +55 -0
  347. package/src/ui/primitives/toggle-group.tsx +70 -0
  348. package/src/ui/primitives/toggle.tsx +47 -0
  349. package/src/ui/primitives/tooltip.tsx +59 -0
  350. package/src/user/components/dangerous-zone.tsx +34 -0
  351. package/src/user/components/delete-account-form.tsx +40 -0
  352. package/src/user/components/index.ts +4 -0
  353. package/src/user/components/profile-info-form.tsx +390 -0
  354. package/src/user/components/profile-info.tsx +32 -0
  355. package/src/user/components/unified-profile-dialog.tsx +1019 -0
  356. package/src/user/components/user-stats.tsx +27 -0
  357. package/src/user/components/user-toolbar.tsx +137 -0
  358. package/src/user/components/users-card-view.tsx +253 -0
  359. package/src/user/index.ts +11 -0
  360. package/src/user/pages/user-list-page.tsx +234 -0
  361. package/src/user/pages/users-client-page.tsx +385 -0
  362. package/src/user/profile-page.tsx +19 -0
  363. package/src/user/schemas.ts +68 -0
  364. package/src/user/types.ts +34 -0
  365. package/src/user/user-service.ts +538 -0
  366. package/src/utils/index.ts +906 -0
  367. package/src/workflow/activity-timeline.tsx +412 -0
  368. package/src/workflow/approval-workflow.tsx +31 -0
  369. package/src/workflow/index.ts +2 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@goplusvn/core",
3
3
  "description": "GoPlusVN Platform Kit - ERP kernel: layout, RBAC, CRUD, multi-tenant, system pages",
4
- "version": "0.1.0",
4
+ "version": "0.1.1",
5
5
  "private": false,
6
6
  "publishConfig": {
7
7
  "registry": "https://registry.npmjs.org",
@@ -13,6 +13,7 @@
13
13
  "sideEffects": false,
14
14
  "files": [
15
15
  "dist",
16
+ "src",
16
17
  "README.md",
17
18
  "CHANGELOG.md"
18
19
  ],
Binary file
Binary file
@@ -0,0 +1,139 @@
1
+ import type {
2
+ AuditLog,
3
+ AuditLogger,
4
+ AuditManagerOptions,
5
+ CreateAuditInput,
6
+ } from "./types";
7
+ import { createLogger } from "../infrastructure/logger";
8
+ import { MemoryAuditLogger } from "./memory-audit-logger";
9
+
10
+ const logger = createLogger("AuditManager");
11
+
12
+ /**
13
+ * Console-based audit logger (default)
14
+ * In production, replace with database or external service
15
+ */
16
+ class ConsoleAuditLogger implements AuditLogger {
17
+ async log(entry: AuditLog): Promise<void> {
18
+ logger.info(`AUDIT: ${entry.action} ${entry.resource}`, {
19
+ id: entry.id,
20
+ resourceId: entry.resourceId,
21
+ userId: entry.userId,
22
+ changes: entry.changes,
23
+ });
24
+ }
25
+ }
26
+
27
+ /**
28
+ * AuditManager - tracks actions for compliance and debugging
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * import { auditManager } from '@goerp/core/audit';
33
+ *
34
+ * // Log an action
35
+ * await auditManager.log({
36
+ * action: 'update',
37
+ * resource: 'purchase-order',
38
+ * resourceId: '123',
39
+ * userId: session.user.id,
40
+ * changes: { status: { old: 'pending', new: 'approved' } }
41
+ * });
42
+ * ```
43
+ */
44
+ class AuditManagerImpl {
45
+ private auditLogger: AuditLogger;
46
+ private registeredActions: Set<string>;
47
+
48
+ constructor(options: AuditManagerOptions = {}) {
49
+ this.auditLogger = options.logger || new MemoryAuditLogger();
50
+ this.registeredActions = new Set(
51
+ options.actions || ["create", "update", "delete", "login", "logout"],
52
+ );
53
+ }
54
+
55
+ /** Set custom audit logger */
56
+ setLogger(auditLogger: AuditLogger): void {
57
+ this.auditLogger = auditLogger;
58
+ }
59
+
60
+ /** Register action for automatic auditing */
61
+ registerAction(action: string): void {
62
+ this.registeredActions.add(action);
63
+ }
64
+
65
+ /** Check if action is registered for auditing */
66
+ isRegistered(action: string): boolean {
67
+ return this.registeredActions.has(action);
68
+ }
69
+
70
+ /** Log an audit entry */
71
+ async log(input: CreateAuditInput): Promise<void> {
72
+ const entry: AuditLog = {
73
+ id: crypto.randomUUID(),
74
+ ...input,
75
+ createdAt: new Date(),
76
+ };
77
+
78
+ try {
79
+ await this.auditLogger.log(entry);
80
+ } catch (error) {
81
+ logger.error("Failed to log audit entry", { error: String(error) });
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Get logs if the logger supports it (specifically MemoryAuditLogger)
87
+ */
88
+ getLogs(filter: any = {}): AuditLog[] {
89
+ if ("getLogs" in this.auditLogger) {
90
+ return (this.auditLogger as any).getLogs(filter);
91
+ }
92
+ return [];
93
+ }
94
+
95
+ /** Create middleware for automatic API route auditing */
96
+ middleware() {
97
+ return async (
98
+ ctx: {
99
+ action?: { actionName: string; resourceName: string };
100
+ state?: { currentUser?: { id: string }; currentRole?: string };
101
+ request?: { ip?: string; header?: Record<string, string> };
102
+ status?: number;
103
+ },
104
+ next: () => Promise<void>,
105
+ ): Promise<void> => {
106
+ const startTime = Date.now();
107
+ let error: Error | null = null;
108
+
109
+ try {
110
+ await next();
111
+ } catch (e) {
112
+ error = e as Error;
113
+ throw e;
114
+ } finally {
115
+ if (ctx.action && this.isRegistered(ctx.action.actionName)) {
116
+ await this.log({
117
+ action: ctx.action.actionName,
118
+ resource: ctx.action.resourceName,
119
+ userId: ctx.state?.currentUser?.id,
120
+ roleName: ctx.state?.currentRole,
121
+ ip: ctx.request?.ip,
122
+ userAgent: ctx.request?.header?.["user-agent"],
123
+ status: ctx.status || (error ? 500 : 200),
124
+ metadata: {
125
+ duration: Date.now() - startTime,
126
+ ...(error && { error: error.message }),
127
+ },
128
+ });
129
+ }
130
+ }
131
+ };
132
+ }
133
+ }
134
+
135
+ // Singleton instance
136
+ export const auditManager = new AuditManagerImpl();
137
+
138
+ // Export class for testing
139
+ export { AuditManagerImpl, ConsoleAuditLogger, MemoryAuditLogger };
@@ -0,0 +1,11 @@
1
+ export {
2
+ auditManager,
3
+ AuditManagerImpl,
4
+ ConsoleAuditLogger,
5
+ } from "./audit-manager";
6
+ export type {
7
+ AuditLog,
8
+ AuditLogger,
9
+ AuditManagerOptions,
10
+ CreateAuditInput,
11
+ } from "./types";
@@ -0,0 +1,86 @@
1
+ import type { AuditLog, AuditLogger } from "./types";
2
+
3
+ /**
4
+ * Filter options for retrieving audit logs
5
+ */
6
+ export interface AuditLogFilter {
7
+ fromDate?: Date;
8
+ toDate?: Date;
9
+ userId?: string;
10
+ action?: string;
11
+ resource?: string;
12
+ type?: "info" | "warning" | "error";
13
+ limit?: number;
14
+ offset?: number;
15
+ }
16
+
17
+ /**
18
+ * In-memory audit logger that supports retrieval
19
+ */
20
+ export class MemoryAuditLogger implements AuditLogger {
21
+ private logs: AuditLog[] = [];
22
+ private readonly maxLogs: number;
23
+
24
+ constructor(maxLogs = 1000) {
25
+ this.maxLogs = maxLogs;
26
+ }
27
+
28
+ async log(entry: AuditLog): Promise<void> {
29
+ // Add to beginning of array
30
+ this.logs.unshift(entry);
31
+
32
+ // Trim if exceeds max size
33
+ if (this.logs.length > this.maxLogs) {
34
+ this.logs = this.logs.slice(0, this.maxLogs);
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Get logs with filtering
40
+ */
41
+ getLogs(filter: AuditLogFilter = {}): AuditLog[] {
42
+ let filtered = this.logs;
43
+
44
+ if (filter.fromDate) {
45
+ filtered = filtered.filter((log) => log.createdAt >= filter.fromDate!);
46
+ }
47
+
48
+ if (filter.toDate) {
49
+ filtered = filtered.filter((log) => log.createdAt <= filter.toDate!);
50
+ }
51
+
52
+ if (filter.userId) {
53
+ filtered = filtered.filter((log) => log.userId === filter.userId);
54
+ }
55
+
56
+ if (filter.action) {
57
+ filtered = filtered.filter((log) => log.action === filter.action);
58
+ }
59
+
60
+ if (filter.resource) {
61
+ filtered = filtered.filter((log) => log.resource === filter.resource);
62
+ }
63
+
64
+ // "type" filter is a fuzzy mapping based on status code or action name for demo purposes
65
+ if (filter.type) {
66
+ filtered = filtered.filter((log) => {
67
+ if (filter.type === "error") return (log.status || 200) >= 400;
68
+ if (filter.type === "warning")
69
+ return (log.status || 200) >= 300 && (log.status || 200) < 400;
70
+ return (log.status || 200) < 300;
71
+ });
72
+ }
73
+
74
+ const offset = filter.offset || 0;
75
+ const limit = filter.limit || 50;
76
+
77
+ return filtered.slice(offset, offset + limit);
78
+ }
79
+
80
+ /**
81
+ * Clear all logs
82
+ */
83
+ clear(): void {
84
+ this.logs = [];
85
+ }
86
+ }
@@ -0,0 +1,50 @@
1
+ // Audit Types
2
+ export interface AuditLog {
3
+ id: string;
4
+ /** Action type: create, update, delete, login, logout, custom */
5
+ action: string;
6
+ /** Resource/entity name (e.g., 'purchase-order', 'user') */
7
+ resource: string;
8
+ /** Resource ID */
9
+ resourceId?: string;
10
+ /** User who performed the action */
11
+ userId?: string;
12
+ /** User's role at time of action */
13
+ roleName?: string;
14
+ /** Changes made (for update actions) */
15
+ changes?: Record<string, { old: unknown; new: unknown }>;
16
+ /** Additional metadata */
17
+ metadata?: Record<string, unknown>;
18
+ /** Request IP address */
19
+ ip?: string;
20
+ /** User agent */
21
+ userAgent?: string;
22
+ /** HTTP status code */
23
+ status?: number;
24
+ /** Timestamp */
25
+ createdAt: Date;
26
+ }
27
+
28
+ export interface CreateAuditInput {
29
+ action: string;
30
+ resource: string;
31
+ resourceId?: string;
32
+ userId?: string;
33
+ roleName?: string;
34
+ changes?: Record<string, { old: unknown; new: unknown }>;
35
+ metadata?: Record<string, unknown>;
36
+ ip?: string;
37
+ userAgent?: string;
38
+ status?: number;
39
+ }
40
+
41
+ export interface AuditLogger {
42
+ log(entry: AuditLog): Promise<void>;
43
+ }
44
+
45
+ export interface AuditManagerOptions {
46
+ /** Custom logger implementation */
47
+ logger?: AuditLogger;
48
+ /** Actions to automatically audit */
49
+ actions?: string[];
50
+ }
@@ -0,0 +1,97 @@
1
+ // Define the shape of the Prisma Client required by this service
2
+ export interface AuthPrismaClient {
3
+ user: any;
4
+ }
5
+
6
+ // Dynamic import bcryptjs to avoid Edge Runtime issues
7
+ export async function verifyPassword(
8
+ password: string,
9
+ hash: string,
10
+ ): Promise<boolean> {
11
+ try {
12
+ const bcrypt = await import("bcryptjs");
13
+ return bcrypt.compareSync(password, hash);
14
+ } catch (error) {
15
+ console.error("Error verifying password", error);
16
+ return false;
17
+ }
18
+ }
19
+
20
+ export interface AuthenticatedUser {
21
+ id: string;
22
+ email: string | null;
23
+ name: string;
24
+ avatar: string | null;
25
+ status: string;
26
+ }
27
+
28
+ export interface AuthError {
29
+ message: string;
30
+ email?: string;
31
+ }
32
+
33
+ /**
34
+ * Authenticate user with email and password
35
+ * Returns user data if successful, throws error if failed
36
+ */
37
+ export async function authenticateUser(
38
+ db: AuthPrismaClient,
39
+ email: string,
40
+ password: string,
41
+ ): Promise<AuthenticatedUser> {
42
+ try {
43
+ // Query user from database by email
44
+ const user = await db.user.findUnique({
45
+ where: { email: email.toLowerCase().trim() },
46
+ select: {
47
+ id: true,
48
+ email: true,
49
+ name: true,
50
+ avatar: true,
51
+ password: true,
52
+ isActive: true,
53
+ },
54
+ });
55
+
56
+ // Check if user exists
57
+ if (!user) {
58
+ throw new Error("Invalid email or password");
59
+ }
60
+
61
+ // Check if user account is suspended/inactive
62
+ if (!user.isActive) {
63
+ throw new Error("ACCOUNT_SUSPENDED");
64
+ }
65
+
66
+ // Verify password
67
+ if (!user.password) {
68
+ throw new Error("Invalid email or password");
69
+ }
70
+
71
+ const isPasswordValid = await verifyPassword(password, user.password);
72
+ if (!isPasswordValid) {
73
+ throw new Error("Invalid email or password");
74
+ }
75
+
76
+ // Update last login time
77
+ await db.user.update({
78
+ where: { id: user.id },
79
+ data: { lastLoginAt: new Date() },
80
+ });
81
+
82
+ // Return user data (without password)
83
+ return {
84
+ id: user.id,
85
+ name: user.name || "",
86
+ email: user.email,
87
+ avatar: user.avatar || null,
88
+ status: "ONLINE",
89
+ };
90
+ } catch (error) {
91
+ // Re-throw error with proper message
92
+ if (error instanceof Error) {
93
+ throw error;
94
+ }
95
+ throw new Error("Error signing in");
96
+ }
97
+ }
@@ -0,0 +1,266 @@
1
+ // @goerp/core/auth
2
+ // Authentication and RBAC utilities for GoERP
3
+
4
+ import type { Session } from "next-auth";
5
+
6
+ export * from "./auth-service";
7
+
8
+ // ============================================================================
9
+ // Types
10
+ // ============================================================================
11
+
12
+ export interface Permission {
13
+ resourceCode: string;
14
+ actionCode: string;
15
+ }
16
+
17
+ export interface ExtendedUser {
18
+ id: string;
19
+ name?: string | null;
20
+ email?: string | null;
21
+ image?: string | null;
22
+ roles?: string[];
23
+ permissions?: Permission[];
24
+ }
25
+
26
+ export interface UserSession {
27
+ user: ExtendedUser;
28
+ }
29
+
30
+ export interface CrudPermissionResult {
31
+ create: boolean;
32
+ view: boolean;
33
+ update: boolean;
34
+ delete: boolean;
35
+ export: boolean;
36
+ import: boolean;
37
+ approve: boolean;
38
+ reject: boolean;
39
+ }
40
+
41
+ // ============================================================================
42
+ // Constants
43
+ // ============================================================================
44
+
45
+ const ADMIN_ROLE_CODE = "admin";
46
+ const BYPASS_AUTH =
47
+ process.env.BYPASS_AUTH === "true" || process.env.BYPASS_AUTH === "1";
48
+
49
+ // Action code mapping
50
+ const ACTION_CODES: Record<string, string> = {
51
+ create: "create",
52
+ view: "view",
53
+ update: "update",
54
+ delete: "delete",
55
+ export: "export",
56
+ import: "import",
57
+ approve: "approve",
58
+ reject: "reject",
59
+ };
60
+
61
+ /**
62
+ * Get action code from action name
63
+ */
64
+ export function getActionCode(action: string): string {
65
+ return ACTION_CODES[action] || action;
66
+ }
67
+
68
+ // ============================================================================
69
+ // Permission Functions
70
+ // ============================================================================
71
+
72
+ /**
73
+ * Get all permissions from session
74
+ */
75
+ export function getUserPermissions(session: Session | null): Permission[] {
76
+ if (!session?.user) return [];
77
+ const user = session.user as ExtendedUser;
78
+
79
+ if (!user.permissions) {
80
+ return [];
81
+ }
82
+ return user.permissions;
83
+ }
84
+
85
+ /**
86
+ * Get CRUD permissions from session for a specific entity
87
+ */
88
+ export function getCrudPermissionsFromSession(
89
+ session: Session | null,
90
+ entity: string,
91
+ ): CrudPermissionResult {
92
+ // TEMPORARY: Return all permissions as true if bypass is enabled
93
+ if (BYPASS_AUTH) {
94
+ return {
95
+ create: true,
96
+ view: true,
97
+ update: true,
98
+ delete: true,
99
+ export: true,
100
+ import: true,
101
+ approve: true,
102
+ reject: true,
103
+ };
104
+ }
105
+
106
+ if (!session?.user) {
107
+ return {
108
+ create: false,
109
+ view: false,
110
+ update: false,
111
+ delete: false,
112
+ export: false,
113
+ import: false,
114
+ approve: false,
115
+ reject: false,
116
+ };
117
+ }
118
+
119
+ const user = session.user as ExtendedUser;
120
+
121
+ if (!user.id) {
122
+ return {
123
+ create: false,
124
+ view: false,
125
+ update: false,
126
+ delete: false,
127
+ export: false,
128
+ import: false,
129
+ approve: false,
130
+ reject: false,
131
+ };
132
+ }
133
+
134
+ // Check admin role first (fastest check)
135
+ const isAdmin =
136
+ user.roles?.includes(ADMIN_ROLE_CODE) ||
137
+ user.roles?.includes("SUPER_ADMIN");
138
+ if (isAdmin) {
139
+ return {
140
+ create: true,
141
+ view: true,
142
+ update: true,
143
+ delete: true,
144
+ export: true,
145
+ import: true,
146
+ approve: true,
147
+ reject: true,
148
+ };
149
+ }
150
+
151
+ // Pre-compute permission keys for fast lookup
152
+ const permissions = user.permissions || [];
153
+ const permissionKeys = new Set(
154
+ permissions.map((p) => `${p.resourceCode}:${p.actionCode}`),
155
+ );
156
+
157
+ const hasPermission = (action: string) => {
158
+ const key = `${entity}:${action}`;
159
+ return permissionKeys.has(key);
160
+ };
161
+
162
+ return {
163
+ create: hasPermission(getActionCode("create")),
164
+ view: hasPermission(getActionCode("view")),
165
+ update: hasPermission(getActionCode("update")),
166
+ delete: hasPermission(getActionCode("delete")),
167
+ export: hasPermission(getActionCode("export")),
168
+ import: hasPermission(getActionCode("import")),
169
+ approve: hasPermission(getActionCode("approve")),
170
+ reject: hasPermission(getActionCode("reject")),
171
+ };
172
+ }
173
+
174
+ /**
175
+ * Check if user has a specific permission
176
+ */
177
+ export function checkPermission(
178
+ session: Session | null,
179
+ resourceCode: string,
180
+ actionCode: string,
181
+ ): boolean {
182
+ if (BYPASS_AUTH) {
183
+ return true;
184
+ }
185
+
186
+ if (!session?.user) return false;
187
+ const user = session.user as ExtendedUser;
188
+
189
+ if (!user.permissions || user.permissions.length === 0) {
190
+ return false;
191
+ }
192
+
193
+ // Admin role bypass
194
+ if (
195
+ user.roles?.includes(ADMIN_ROLE_CODE) ||
196
+ user.roles?.includes("SUPER_ADMIN")
197
+ ) {
198
+ return true;
199
+ }
200
+
201
+ return user.permissions.some(
202
+ (p) => p.resourceCode === resourceCode && p.actionCode === actionCode,
203
+ );
204
+ }
205
+
206
+ /**
207
+ * Alias for checkPermission
208
+ */
209
+ export function hasPermission(
210
+ session: Session | null,
211
+ resourceCode: string,
212
+ actionCode: string,
213
+ ): boolean {
214
+ return checkPermission(session, resourceCode, actionCode);
215
+ }
216
+
217
+ /**
218
+ * Require permission - throw error if not authorized
219
+ */
220
+ export function requirePermission(
221
+ session: Session | null,
222
+ resourceCode: string,
223
+ actionCode: string,
224
+ ): void {
225
+ if (!checkPermission(session, resourceCode, actionCode)) {
226
+ throw new Error(
227
+ `Unauthorized: User does not have permission ${actionCode} on ${resourceCode}`,
228
+ );
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Check if user has a specific role
234
+ */
235
+ export function hasRole(session: Session | null, roleCode: string): boolean {
236
+ if (!session?.user) return false;
237
+ const user = session.user as ExtendedUser;
238
+
239
+ if (!user.roles) {
240
+ return false;
241
+ }
242
+ return user.roles.includes(roleCode);
243
+ }
244
+
245
+ /**
246
+ * Check if user has any of the specified roles
247
+ */
248
+ export function hasAnyRole(
249
+ session: Session | null,
250
+ roleCodes: string[],
251
+ ): boolean {
252
+ if (!session?.user) return false;
253
+ const user = session.user as ExtendedUser;
254
+
255
+ if (!user.roles) {
256
+ return false;
257
+ }
258
+ return roleCodes.some((role) => user.roles!.includes(role));
259
+ }
260
+
261
+ /**
262
+ * Check if user is admin
263
+ */
264
+ export function isAdmin(session: Session | null): boolean {
265
+ return hasRole(session, ADMIN_ROLE_CODE);
266
+ }