@carlonicora/nextjs-jsonapi 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (278) hide show
  1. package/dist/{ApiResponseInterface-DDI7QQPR.d.ts → ApiResponseInterface-DMwITHYP.d.mts} +11 -2
  2. package/dist/{ApiResponseInterface-BHN5D9r5.d.mts → ApiResponseInterface-DWgIAXI-.d.ts} +11 -2
  3. package/dist/AuthComponent-hxOPs9o8.d.mts +11 -0
  4. package/dist/AuthComponent-hxOPs9o8.d.ts +11 -0
  5. package/dist/{BlockNoteEditor-G6AK2NWA.js → BlockNoteEditor-IJASTIUZ.js} +16 -23
  6. package/dist/BlockNoteEditor-IJASTIUZ.js.map +1 -0
  7. package/dist/{BlockNoteEditor-AIEEQM6A.mjs → BlockNoteEditor-M6TUP3NT.mjs} +8 -15
  8. package/dist/BlockNoteEditor-M6TUP3NT.mjs.map +1 -0
  9. package/dist/JsonApiRequest-2OM5NDAW.js +24 -0
  10. package/dist/JsonApiRequest-2OM5NDAW.js.map +1 -0
  11. package/dist/{JsonApiRequest-6UR7DIAR.mjs → JsonApiRequest-SYZ6FGCA.mjs} +2 -3
  12. package/dist/{chunk-2K3Q24UF.js → chunk-3ZPK4QOB.js} +24 -14
  13. package/dist/chunk-3ZPK4QOB.js.map +1 -0
  14. package/dist/{chunk-VET55IZO.js → chunk-4L7OWJ2P.js} +10290 -7537
  15. package/dist/chunk-4L7OWJ2P.js.map +1 -0
  16. package/dist/chunk-4U5CJA44.mjs +3435 -0
  17. package/dist/chunk-4U5CJA44.mjs.map +1 -0
  18. package/dist/chunk-AGWQ75PQ.js +142 -0
  19. package/dist/chunk-AGWQ75PQ.js.map +1 -0
  20. package/dist/{chunk-PMXG5WBC.js → chunk-CKS6SVUK.js} +160 -24
  21. package/dist/chunk-CKS6SVUK.js.map +1 -0
  22. package/dist/{chunk-YF5XQZDR.mjs → chunk-F5UNXZ3J.mjs} +1 -1
  23. package/dist/chunk-F5UNXZ3J.mjs.map +1 -0
  24. package/dist/chunk-IGOWVLJH.mjs +142 -0
  25. package/dist/chunk-IGOWVLJH.mjs.map +1 -0
  26. package/dist/{chunk-HR4H2FP7.mjs → chunk-KJ4ETLJB.mjs} +24 -14
  27. package/dist/chunk-KJ4ETLJB.mjs.map +1 -0
  28. package/dist/{chunk-IKBA4AHN.mjs → chunk-SAL7XW2G.mjs} +143 -7
  29. package/dist/chunk-SAL7XW2G.mjs.map +1 -0
  30. package/dist/chunk-TW4QRJ7D.mjs +12085 -0
  31. package/dist/chunk-TW4QRJ7D.mjs.map +1 -0
  32. package/dist/chunk-U4NADAHN.js +3435 -0
  33. package/dist/chunk-U4NADAHN.js.map +1 -0
  34. package/dist/{chunk-EFJEWLRL.js → chunk-YUO55Q5A.js} +1 -1
  35. package/dist/chunk-YUO55Q5A.js.map +1 -0
  36. package/dist/client/index.d.mts +161 -11
  37. package/dist/client/index.d.ts +161 -11
  38. package/dist/client/index.js +71 -11
  39. package/dist/client/index.js.map +1 -1
  40. package/dist/client/index.mjs +70 -10
  41. package/dist/components/index.d.mts +763 -11
  42. package/dist/components/index.d.ts +763 -11
  43. package/dist/components/index.js +462 -11
  44. package/dist/components/index.js.map +1 -1
  45. package/dist/components/index.mjs +463 -12
  46. package/dist/config-BdCV25CE.d.mts +69 -0
  47. package/dist/config-C9dt1QiR.d.ts +69 -0
  48. package/dist/content.fields-Ck5lkQ5d.d.mts +47 -0
  49. package/dist/content.fields-Ck5lkQ5d.d.ts +47 -0
  50. package/dist/{content.interface-CR2aBeAW.d.ts → content.interface-B6qP_ABq.d.mts} +2 -3
  51. package/dist/{content.interface-FpLfsaRm.d.mts → content.interface-DHAFLasV.d.ts} +2 -3
  52. package/dist/contexts/index.d.mts +13 -6
  53. package/dist/contexts/index.d.ts +13 -6
  54. package/dist/contexts/index.js +7 -11
  55. package/dist/contexts/index.js.map +1 -1
  56. package/dist/contexts/index.mjs +6 -10
  57. package/dist/core/index.d.mts +575 -8
  58. package/dist/core/index.d.ts +575 -8
  59. package/dist/core/index.js +131 -3
  60. package/dist/core/index.js.map +1 -1
  61. package/dist/core/index.mjs +132 -4
  62. package/dist/index.d.mts +95 -71
  63. package/dist/index.d.ts +95 -71
  64. package/dist/index.js +113 -7
  65. package/dist/index.js.map +1 -1
  66. package/dist/index.mjs +135 -29
  67. package/dist/notification.interface-agcMYCkg.d.mts +228 -0
  68. package/dist/notification.interface-agcMYCkg.d.ts +228 -0
  69. package/dist/request-GBLBPYFM.js +8 -0
  70. package/dist/request-GBLBPYFM.js.map +1 -0
  71. package/dist/request-XABCMU25.mjs +8 -0
  72. package/dist/s3.service-DYnmymEd.d.mts +350 -0
  73. package/dist/s3.service-DyXjKTqr.d.ts +350 -0
  74. package/dist/server/index.d.mts +69 -4
  75. package/dist/server/index.d.ts +69 -4
  76. package/dist/server/index.js +211 -5
  77. package/dist/server/index.js.map +1 -1
  78. package/dist/server/index.mjs +211 -5
  79. package/dist/server/index.mjs.map +1 -1
  80. package/dist/token-2UWQJY5T.js +8 -0
  81. package/dist/token-2UWQJY5T.js.map +1 -0
  82. package/dist/token-EOK3N45S.mjs +8 -0
  83. package/dist/{useSocket-L-An7_Mr.d.mts → useSocket-91s8M4Xd.d.mts} +1 -1
  84. package/dist/{useSocket-BV6yMdWS.d.ts → useSocket-DSR7vaXj.d.ts} +1 -1
  85. package/package.json +12 -52
  86. package/src/client/JsonApiClient.ts +248 -0
  87. package/src/client/config.ts +78 -0
  88. package/src/client/index.ts +6 -1
  89. package/src/components/containers/TabsContainer.tsx +1 -1
  90. package/src/components/editors/BlockNoteEditor.tsx +3 -1
  91. package/src/components/index.ts +4 -0
  92. package/src/components/navigations/Breadcrumb.tsx +1 -1
  93. package/src/components/navigations/Header.tsx +2 -2
  94. package/src/contexts/CommonContext.tsx +1 -1
  95. package/src/contexts/SocketContext.tsx +1 -1
  96. package/src/contexts/index.ts +3 -0
  97. package/src/core/abstracts/ClientAbstractService.ts +255 -0
  98. package/src/core/abstracts/ServerAbstractService.ts +180 -0
  99. package/src/core/abstracts/index.ts +2 -0
  100. package/src/core/index.ts +35 -3
  101. package/src/discord/config.ts +15 -0
  102. package/src/discord/index.ts +1 -0
  103. package/src/features/auth/components/details/LandingComponent.tsx +2 -2
  104. package/src/features/auth/components/forms/AcceptInvitation.tsx +1 -1
  105. package/src/features/auth/components/forms/ActivateAccount.tsx +1 -1
  106. package/src/features/auth/components/forms/Cookies.tsx +2 -1
  107. package/src/features/auth/components/forms/ForgotPassword.tsx +1 -1
  108. package/src/features/auth/components/forms/Login.tsx +1 -1
  109. package/src/features/auth/components/forms/Logout.tsx +1 -1
  110. package/src/features/auth/components/forms/RefreshUser.tsx +2 -1
  111. package/src/features/auth/components/forms/Register.tsx +1 -1
  112. package/src/features/auth/components/forms/ResetPassword.tsx +1 -1
  113. package/src/features/auth/data/auth.service.ts +1 -1
  114. package/src/features/auth/utils/AuthCookies.ts +1 -1
  115. package/src/features/company/components/forms/CompanyConfigurationEditor.tsx +4 -2
  116. package/src/features/company/components/forms/CompanyDeleter.tsx +2 -1
  117. package/src/features/company/components/forms/CompanyEditor.tsx +6 -3
  118. package/src/features/company/components/forms/CompanyLicense.tsx +4 -2
  119. package/src/features/company/components/lists/CompaniesList.tsx +2 -1
  120. package/src/features/content/components/lists/ContentsListById.tsx +2 -1
  121. package/src/features/content/components/lists/RelevantContentsList.tsx +2 -1
  122. package/src/features/notification/components/lists/NotificationsList.tsx +2 -1
  123. package/src/features/notification/contexts/NotificationContext.tsx +2 -1
  124. package/src/features/role/components/forms/RemoveUserFromRole.tsx +4 -2
  125. package/src/features/role/components/forms/UserRoleAdd.tsx +2 -1
  126. package/src/features/role/components/lists/RolesList.tsx +2 -1
  127. package/src/features/role/components/lists/UserRolesList.tsx +2 -1
  128. package/src/features/user/components/forms/RoleUserAdd.tsx +4 -2
  129. package/src/features/user/components/forms/UserDeleter.tsx +2 -1
  130. package/src/features/user/components/forms/UserEditor.tsx +6 -3
  131. package/src/features/user/components/forms/UserMultiSelect.tsx +2 -1
  132. package/src/features/user/components/forms/UserReactivator.tsx +2 -1
  133. package/src/features/user/components/forms/UserResentInvitationEmail.tsx +2 -1
  134. package/src/features/user/components/forms/UserSelector.tsx +2 -1
  135. package/src/features/user/components/lists/AdminUsersList.tsx +2 -1
  136. package/src/features/user/components/lists/CompanyUsersList.tsx +2 -1
  137. package/src/features/user/components/lists/RelevantUsersList.tsx +2 -1
  138. package/src/features/user/components/lists/RoleUsersList.tsx +2 -1
  139. package/src/features/user/components/lists/UsersListByContentIds.tsx +2 -1
  140. package/src/features/user/hooks/useUserSearch.ts +2 -1
  141. package/src/hooks/useDataListRetriever.ts +4 -4
  142. package/src/hooks/usePageTracker.ts +1 -1
  143. package/src/hooks/usePushNotifications.ts +3 -2
  144. package/src/hooks/useSocket.ts +1 -1
  145. package/src/index.ts +7 -2
  146. package/src/roles/config.ts +0 -15
  147. package/src/roles/index.ts +1 -9
  148. package/src/server/JsonApiServer.ts +249 -0
  149. package/src/server/cache.ts +1 -1
  150. package/src/server/index.ts +13 -0
  151. package/src/server/request.ts +32 -18
  152. package/src/server/token.ts +1 -1
  153. package/dist/AbstractService-BsY6W3Ej.d.mts +0 -109
  154. package/dist/AbstractService-wLid8dB0.d.ts +0 -109
  155. package/dist/ApiData-DPKNfY-9.d.mts +0 -10
  156. package/dist/ApiData-DPKNfY-9.d.ts +0 -10
  157. package/dist/ApiDataInterface-DPP8s46n.d.mts +0 -21
  158. package/dist/ApiDataInterface-DPP8s46n.d.ts +0 -21
  159. package/dist/AuthComponent-B_Ps2Vb9.d.ts +0 -78
  160. package/dist/AuthComponent-CxnGgvoh.d.mts +0 -78
  161. package/dist/BlockNoteEditor-AIEEQM6A.mjs.map +0 -1
  162. package/dist/BlockNoteEditor-G6AK2NWA.js.map +0 -1
  163. package/dist/JsonApiRequest-UJ7FGIVI.js +0 -25
  164. package/dist/JsonApiRequest-UJ7FGIVI.js.map +0 -1
  165. package/dist/atoms/index.d.mts +0 -12
  166. package/dist/atoms/index.d.ts +0 -12
  167. package/dist/atoms/index.js +0 -9
  168. package/dist/atoms/index.js.map +0 -1
  169. package/dist/atoms/index.mjs +0 -9
  170. package/dist/chunk-2K3Q24UF.js.map +0 -1
  171. package/dist/chunk-32HM6MDD.js +0 -98
  172. package/dist/chunk-32HM6MDD.js.map +0 -1
  173. package/dist/chunk-3FBCC4G3.js +0 -8
  174. package/dist/chunk-3FBCC4G3.js.map +0 -1
  175. package/dist/chunk-3UELCPIN.js +0 -46
  176. package/dist/chunk-3UELCPIN.js.map +0 -1
  177. package/dist/chunk-5IET37O4.js +0 -4210
  178. package/dist/chunk-5IET37O4.js.map +0 -1
  179. package/dist/chunk-AGAJMJ4T.js +0 -147
  180. package/dist/chunk-AGAJMJ4T.js.map +0 -1
  181. package/dist/chunk-AYHKQWHH.js +0 -68
  182. package/dist/chunk-AYHKQWHH.js.map +0 -1
  183. package/dist/chunk-DEYKTLA3.js +0 -1131
  184. package/dist/chunk-DEYKTLA3.js.map +0 -1
  185. package/dist/chunk-EFJEWLRL.js.map +0 -1
  186. package/dist/chunk-FMBQZAIP.mjs +0 -490
  187. package/dist/chunk-FMBQZAIP.mjs.map +0 -1
  188. package/dist/chunk-HAG77QBV.mjs +0 -98
  189. package/dist/chunk-HAG77QBV.mjs.map +0 -1
  190. package/dist/chunk-HR4H2FP7.mjs.map +0 -1
  191. package/dist/chunk-IKBA4AHN.mjs.map +0 -1
  192. package/dist/chunk-J7YDGYSW.mjs +0 -9332
  193. package/dist/chunk-J7YDGYSW.mjs.map +0 -1
  194. package/dist/chunk-JGFWIT2E.mjs +0 -1131
  195. package/dist/chunk-JGFWIT2E.mjs.map +0 -1
  196. package/dist/chunk-P2F54I7Q.mjs +0 -4210
  197. package/dist/chunk-P2F54I7Q.mjs.map +0 -1
  198. package/dist/chunk-PMXG5WBC.js.map +0 -1
  199. package/dist/chunk-Q2N6SQYW.mjs +0 -8
  200. package/dist/chunk-Q2N6SQYW.mjs.map +0 -1
  201. package/dist/chunk-Q4FXESVT.js +0 -490
  202. package/dist/chunk-Q4FXESVT.js.map +0 -1
  203. package/dist/chunk-RBIVEH2K.mjs +0 -147
  204. package/dist/chunk-RBIVEH2K.mjs.map +0 -1
  205. package/dist/chunk-SM63SZCP.mjs +0 -68
  206. package/dist/chunk-SM63SZCP.mjs.map +0 -1
  207. package/dist/chunk-SZZYEG3P.mjs +0 -46
  208. package/dist/chunk-SZZYEG3P.mjs.map +0 -1
  209. package/dist/chunk-VET55IZO.js.map +0 -1
  210. package/dist/chunk-YF5XQZDR.mjs.map +0 -1
  211. package/dist/config-BmnK65TD.d.mts +0 -35
  212. package/dist/config-BmnK65TD.d.ts +0 -35
  213. package/dist/config-DQeAo9Kf.d.mts +0 -49
  214. package/dist/config-DQeAo9Kf.d.ts +0 -49
  215. package/dist/content.fields-cHPdM8GJ.d.mts +0 -27
  216. package/dist/content.fields-cHPdM8GJ.d.ts +0 -27
  217. package/dist/d3.link.interface-ClC4Irqp.d.mts +0 -21
  218. package/dist/d3.link.interface-ClC4Irqp.d.ts +0 -21
  219. package/dist/features/index.d.mts +0 -477
  220. package/dist/features/index.d.ts +0 -477
  221. package/dist/features/index.js +0 -108
  222. package/dist/features/index.js.map +0 -1
  223. package/dist/features/index.mjs +0 -108
  224. package/dist/hooks/index.d.mts +0 -69
  225. package/dist/hooks/index.d.ts +0 -69
  226. package/dist/hooks/index.js +0 -55
  227. package/dist/hooks/index.js.map +0 -1
  228. package/dist/hooks/index.mjs +0 -55
  229. package/dist/hooks/index.mjs.map +0 -1
  230. package/dist/interfaces/index.d.mts +0 -4
  231. package/dist/interfaces/index.d.ts +0 -4
  232. package/dist/interfaces/index.js +0 -2
  233. package/dist/interfaces/index.js.map +0 -1
  234. package/dist/interfaces/index.mjs +0 -2
  235. package/dist/interfaces/index.mjs.map +0 -1
  236. package/dist/notification.interface-B2BrLoDA.d.mts +0 -14
  237. package/dist/notification.interface-DlZLnAfg.d.ts +0 -14
  238. package/dist/permissions/index.d.mts +0 -41
  239. package/dist/permissions/index.d.ts +0 -41
  240. package/dist/permissions/index.js +0 -14
  241. package/dist/permissions/index.js.map +0 -1
  242. package/dist/permissions/index.mjs +0 -14
  243. package/dist/permissions/index.mjs.map +0 -1
  244. package/dist/request-7FE3LJLV.mjs +0 -9
  245. package/dist/request-7FE3LJLV.mjs.map +0 -1
  246. package/dist/request-QFS7NEIE.js +0 -9
  247. package/dist/request-QFS7NEIE.js.map +0 -1
  248. package/dist/roles/index.d.mts +0 -39
  249. package/dist/roles/index.d.ts +0 -39
  250. package/dist/roles/index.js +0 -18
  251. package/dist/roles/index.js.map +0 -1
  252. package/dist/roles/index.mjs +0 -18
  253. package/dist/roles/index.mjs.map +0 -1
  254. package/dist/shadcnui/index.d.mts +0 -698
  255. package/dist/shadcnui/index.d.ts +0 -698
  256. package/dist/shadcnui/index.js +0 -468
  257. package/dist/shadcnui/index.js.map +0 -1
  258. package/dist/shadcnui/index.mjs +0 -467
  259. package/dist/shadcnui/index.mjs.map +0 -1
  260. package/dist/token-IJSPOMW6.mjs +0 -9
  261. package/dist/token-IJSPOMW6.mjs.map +0 -1
  262. package/dist/token-UYE7CV6X.js +0 -9
  263. package/dist/token-UYE7CV6X.js.map +0 -1
  264. package/dist/types-B2QRyqyK.d.ts +0 -39
  265. package/dist/types-CgvNmxTd.d.mts +0 -39
  266. package/dist/types-t2PyXhDu.d.mts +0 -116
  267. package/dist/types-t2PyXhDu.d.ts +0 -116
  268. package/dist/user.interface-CooB1R79.d.mts +0 -85
  269. package/dist/user.interface-KnIT9pVY.d.ts +0 -85
  270. package/dist/utils/index.d.mts +0 -224
  271. package/dist/utils/index.d.ts +0 -224
  272. package/dist/utils/index.js +0 -46
  273. package/dist/utils/index.js.map +0 -1
  274. package/dist/utils/index.mjs +0 -46
  275. package/dist/utils/index.mjs.map +0 -1
  276. /package/dist/{JsonApiRequest-6UR7DIAR.mjs.map → JsonApiRequest-SYZ6FGCA.mjs.map} +0 -0
  277. /package/dist/{atoms/index.mjs.map → request-XABCMU25.mjs.map} +0 -0
  278. /package/dist/{features/index.mjs.map → token-EOK3N45S.mjs.map} +0 -0
@@ -0,0 +1,78 @@
1
+ "use client";
2
+
3
+ import { ModuleWithPermissions } from "../permissions/types";
4
+
5
+ // Config storage for client-side contexts
6
+ let _clientConfig: {
7
+ apiUrl: string;
8
+ appUrl?: string;
9
+ trackablePages?: ModuleWithPermissions[];
10
+ bootstrapper?: () => void;
11
+ additionalHeaders?: Record<string, string>;
12
+ } | null = null;
13
+
14
+ /**
15
+ * Configure the JSON:API client. This is the main configuration function.
16
+ * This is typically called during app initialization.
17
+ */
18
+ export function configureJsonApi(config: {
19
+ apiUrl: string;
20
+ appUrl?: string;
21
+ trackablePages?: ModuleWithPermissions[];
22
+ bootstrapper?: () => void;
23
+ additionalHeaders?: Record<string, string>;
24
+ }): void {
25
+ _clientConfig = config;
26
+ // Call bootstrapper immediately to register all modules
27
+ if (config.bootstrapper) {
28
+ config.bootstrapper();
29
+ }
30
+ }
31
+
32
+ /**
33
+ * Configure the client config. This is typically called during app initialization.
34
+ * @deprecated Use configureJsonApi instead
35
+ */
36
+ export function configureClientConfig(config: {
37
+ apiUrl: string;
38
+ appUrl?: string;
39
+ trackablePages?: ModuleWithPermissions[];
40
+ }): void {
41
+ _clientConfig = config;
42
+ }
43
+
44
+ /**
45
+ * Get the configured API URL.
46
+ */
47
+ export function getApiUrl(): string {
48
+ if (_clientConfig?.apiUrl) {
49
+ return _clientConfig.apiUrl;
50
+ }
51
+ if (typeof process !== "undefined" && process.env?.NEXT_PUBLIC_API_URL) {
52
+ return process.env.NEXT_PUBLIC_API_URL;
53
+ }
54
+ return "";
55
+ }
56
+
57
+ /**
58
+ * Get the configured app URL.
59
+ */
60
+ export function getAppUrl(): string {
61
+ if (_clientConfig?.appUrl) {
62
+ return _clientConfig.appUrl;
63
+ }
64
+ if (typeof process !== "undefined" && process.env?.NEXT_PUBLIC_APP_URL) {
65
+ return process.env.NEXT_PUBLIC_APP_URL;
66
+ }
67
+ if (typeof window !== "undefined") {
68
+ return window.location.origin;
69
+ }
70
+ return "";
71
+ }
72
+
73
+ /**
74
+ * Get the configured trackable pages.
75
+ */
76
+ export function getTrackablePages(): ModuleWithPermissions[] {
77
+ return _clientConfig?.trackablePages ?? [];
78
+ }
@@ -3,12 +3,17 @@
3
3
  // Context and Provider
4
4
  export * from "./context";
5
5
 
6
- // Hooks
6
+ // Client-side hooks
7
7
  export * from "./hooks";
8
8
 
9
9
  // Client-side request utilities
10
10
  export * from "./request";
11
11
  export * from "./token";
12
+ export * from "./JsonApiClient";
13
+ export * from "./config";
14
+
15
+ // All hooks (merged from /hooks entry point)
16
+ export * from "../hooks";
12
17
 
13
18
  // Table generator registration (must be in client-only context)
14
19
  import { useCompanyTableStructure } from "../features/company/hooks";
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { useCurrentUserContext } from "../../contexts";
4
- import { UserInterface } from "../../features";
4
+ import { UserInterface } from "../../features/user/data";
5
5
  import { Action, ModuleWithPermissions } from "../../permissions";
6
6
  import { ScrollArea, Tabs, TabsContent, TabsList, TabsTrigger } from "../../shadcnui";
7
7
  import { cn } from "../../utils";
@@ -8,7 +8,9 @@ import { CheckIcon, XIcon } from "lucide-react";
8
8
  import { useTranslations } from "next-intl";
9
9
  import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
10
10
  import { useCurrentUserContext } from "../../contexts";
11
- import { S3Interface, S3Service, UserInterface } from "../../features";
11
+ import { S3Interface } from "../../features/s3/data";
12
+ import { UserInterface } from "../../features/user/data";
13
+ import { S3Service } from "../../features/s3/data/s3.service";
12
14
  import { Button } from "../../shadcnui";
13
15
  import { BlockNoteDiffUtil, BlockNoteWordDiffRendererUtil, cn } from "../../utils";
14
16
  import { errorToast } from "../errors";
@@ -8,6 +8,7 @@ export * from "./navigations";
8
8
  export * from "./pages";
9
9
  export * from "./tables";
10
10
 
11
+ // Feature components
11
12
  export * from "../features/auth/components";
12
13
  export * from "../features/company/components";
13
14
  export * from "../features/content/components";
@@ -15,3 +16,6 @@ export * from "../features/feature/components";
15
16
  export * from "../features/notification/components";
16
17
  export * from "../features/role/components";
17
18
  export * from "../features/user/components";
19
+
20
+ // shadcn/ui components (merged from /shadcnui entry point)
21
+ export * from "../shadcnui";
@@ -21,7 +21,7 @@ type BreadcrumbProps = { items: BreadcrumbItemData[] };
21
21
 
22
22
  const ITEMS_TO_DISPLAY = 3;
23
23
 
24
- export function Breadcrumb({ items }: BreadcrumbProps) {
24
+ export function BreadcrumbNavigation({ items }: BreadcrumbProps) {
25
25
  const generateUrl = usePageUrlGenerator();
26
26
  const t = useTranslations();
27
27
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { useSharedContext } from "../../contexts/SharedContext";
4
4
  import { SidebarTrigger } from "../../shadcnui";
5
- import { Breadcrumb } from "./Breadcrumb";
5
+ import { BreadcrumbNavigation } from "./Breadcrumb";
6
6
 
7
7
  type HeaderProps = {
8
8
  children?: React.ReactNode;
@@ -16,7 +16,7 @@ export function Header({ children }: HeaderProps) {
16
16
  <div className="bg-sidebar flex h-12 w-full flex-row items-center justify-between pl-2 pr-4">
17
17
  <SidebarTrigger aria-label="Toggle sidebar" />
18
18
  <div className="flex w-full flex-row items-center justify-start">
19
- <Breadcrumb items={breadcrumbs} />
19
+ <BreadcrumbNavigation items={breadcrumbs} />
20
20
  </div>
21
21
  <div className="flex w-64 flex-row items-center justify-end gap-x-4 whitespace-nowrap">
22
22
  {children ? children : null}
@@ -3,7 +3,7 @@
3
3
  import { useTranslations } from "next-intl";
4
4
 
5
5
  import { createContext, ReactNode, useContext } from "react";
6
- import { UserInterface } from "../features";
6
+ import { UserInterface } from "../features/user/data";
7
7
  import { useCurrentUserContext } from "../features/user/contexts";
8
8
  import { BreadcrumbItemData } from "../interfaces";
9
9
  import { SharedProvider } from "./SharedContext";
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import React, { createContext, useContext } from "react";
4
- import { NotificationInterface } from "../features";
4
+ import { NotificationInterface } from "../features/notification/data";
5
5
  import { useSocket } from "../hooks";
6
6
 
7
7
  interface SocketContextProps {
@@ -5,3 +5,6 @@ export * from "../features/user/contexts";
5
5
  export * from "./CommonContext";
6
6
  export * from "./SharedContext";
7
7
  export * from "./SocketContext";
8
+
9
+ // Jotai atoms (merged from /atoms entry point)
10
+ export * from "../atoms";
@@ -0,0 +1,255 @@
1
+ "use client";
2
+
3
+ import { ApiRequestDataTypeInterface } from "../interfaces/ApiRequestDataTypeInterface";
4
+ import { ApiResponseInterface } from "../interfaces/ApiResponseInterface";
5
+ import {
6
+ ClientJsonApiGet,
7
+ ClientJsonApiPost,
8
+ ClientJsonApiPut,
9
+ ClientJsonApiPatch,
10
+ ClientJsonApiDelete,
11
+ } from "../../client/JsonApiClient";
12
+ // Duplicated to avoid importing from AbstractService which pulls in server code
13
+ // These are exported so client services can import them from here instead of core
14
+ export enum ClientHttpMethod {
15
+ GET = "GET",
16
+ POST = "POST",
17
+ PUT = "PUT",
18
+ PATCH = "PATCH",
19
+ DELETE = "DELETE",
20
+ }
21
+
22
+ export interface ClientNextRef {
23
+ next?: string;
24
+ }
25
+
26
+ export interface ClientPreviousRef {
27
+ previous?: string;
28
+ }
29
+
30
+ export interface ClientSelfRef {
31
+ self?: string;
32
+ }
33
+
34
+ let globalErrorHandler: ((status: number, message: string) => void) | null = null;
35
+
36
+ /**
37
+ * Set a global error handler for API errors (client-side only).
38
+ * This handler will be called instead of throwing errors.
39
+ */
40
+ export function setClientGlobalErrorHandler(handler: (status: number, message: string) => void) {
41
+ globalErrorHandler = handler;
42
+ }
43
+
44
+ /**
45
+ * Get the current global error handler.
46
+ */
47
+ export function getClientGlobalErrorHandler(): ((status: number, message: string) => void) | null {
48
+ return globalErrorHandler;
49
+ }
50
+
51
+ /**
52
+ * Client-side abstract base class for services that interact with the JSON:API.
53
+ * Use this for client components.
54
+ */
55
+ export abstract class ClientAbstractService {
56
+ /**
57
+ * Extract locale from client-side URL pathname
58
+ * URL structure: /{locale}/route-path (e.g., /it/accounts)
59
+ * Fallback chain: URL locale → navigator.language → "en"
60
+ */
61
+ private static getClientLocale(): string {
62
+ if (typeof window === "undefined") {
63
+ return "en"; // Should not happen in client service
64
+ }
65
+
66
+ // Extract locale from URL pathname (first segment after leading slash)
67
+ const pathSegments = window.location.pathname.split("/").filter(Boolean);
68
+ const urlLocale = pathSegments[0];
69
+
70
+ // Validate against supported locales (currently only "en")
71
+ const supportedLocales = ["en"];
72
+ if (urlLocale && supportedLocales.includes(urlLocale)) {
73
+ return urlLocale;
74
+ }
75
+
76
+ // Fallback to navigator language
77
+ const navigatorLocale = navigator.language.split("-")[0];
78
+ if (navigatorLocale && supportedLocales.includes(navigatorLocale)) {
79
+ return navigatorLocale;
80
+ }
81
+
82
+ // Final fallback
83
+ return "en";
84
+ }
85
+
86
+ /**
87
+ * Fetch the next page of results.
88
+ */
89
+ static async next<T>(params: {
90
+ type: ApiRequestDataTypeInterface;
91
+ endpoint: string;
92
+ next?: ClientNextRef;
93
+ previous?: ClientPreviousRef;
94
+ self?: ClientSelfRef;
95
+ }): Promise<T> {
96
+ return await this.callApi<T>({
97
+ method: ClientHttpMethod.GET,
98
+ type: params.type,
99
+ endpoint: params.endpoint,
100
+ next: params.next,
101
+ previous: params.previous,
102
+ self: params.self,
103
+ });
104
+ }
105
+
106
+ /**
107
+ * Fetch the previous page of results.
108
+ */
109
+ static async previous<T>(params: {
110
+ type: ApiRequestDataTypeInterface;
111
+ endpoint: string;
112
+ next?: ClientNextRef;
113
+ previous?: ClientPreviousRef;
114
+ self?: ClientSelfRef;
115
+ }): Promise<T> {
116
+ return await this.callApi<T>({
117
+ method: ClientHttpMethod.GET,
118
+ type: params.type,
119
+ endpoint: params.endpoint,
120
+ next: params.next,
121
+ previous: params.previous,
122
+ self: params.self,
123
+ });
124
+ }
125
+
126
+ /**
127
+ * Make a client-side API call.
128
+ */
129
+ protected static async callApi<T>(params: {
130
+ type: ApiRequestDataTypeInterface;
131
+ method: ClientHttpMethod;
132
+ endpoint: string;
133
+ companyId?: string;
134
+ input?: any;
135
+ overridesJsonApiCreation?: boolean;
136
+ next?: ClientNextRef;
137
+ previous?: ClientPreviousRef;
138
+ self?: ClientSelfRef;
139
+ responseType?: ApiRequestDataTypeInterface;
140
+ files?: { [key: string]: File | Blob } | File | Blob;
141
+ }): Promise<T> {
142
+ let apiResponse: ApiResponseInterface;
143
+
144
+ // Client-side: extract locale from URL pathname
145
+ const language = this.getClientLocale();
146
+
147
+ switch (params.method) {
148
+ case ClientHttpMethod.GET:
149
+ apiResponse = await ClientJsonApiGet({
150
+ classKey: params.type,
151
+ endpoint: params.endpoint,
152
+ companyId: params.companyId,
153
+ language: language,
154
+ });
155
+ break;
156
+ case ClientHttpMethod.POST:
157
+ apiResponse = await ClientJsonApiPost({
158
+ classKey: params.type,
159
+ endpoint: params.endpoint,
160
+ companyId: params.companyId,
161
+ body: params.input,
162
+ overridesJsonApiCreation: params.overridesJsonApiCreation,
163
+ language: language,
164
+ responseType: params.responseType,
165
+ files: params.files,
166
+ });
167
+ break;
168
+ case ClientHttpMethod.PUT:
169
+ apiResponse = await ClientJsonApiPut({
170
+ classKey: params.type,
171
+ endpoint: params.endpoint,
172
+ companyId: params.companyId,
173
+ body: params.input,
174
+ language: language,
175
+ responseType: params.responseType,
176
+ files: params.files,
177
+ });
178
+ break;
179
+ case ClientHttpMethod.PATCH:
180
+ apiResponse = await ClientJsonApiPatch({
181
+ classKey: params.type,
182
+ endpoint: params.endpoint,
183
+ companyId: params.companyId,
184
+ body: params.input,
185
+ overridesJsonApiCreation: params.overridesJsonApiCreation,
186
+ language: language,
187
+ responseType: params.responseType,
188
+ files: params.files,
189
+ });
190
+ break;
191
+ case ClientHttpMethod.DELETE:
192
+ apiResponse = await ClientJsonApiDelete({
193
+ classKey: params.type,
194
+ endpoint: params.endpoint,
195
+ companyId: params.companyId,
196
+ language: language,
197
+ responseType: params.responseType,
198
+ });
199
+ break;
200
+ default:
201
+ throw new Error("Method not found");
202
+ }
203
+
204
+ if (!apiResponse.ok) {
205
+ if (globalErrorHandler) {
206
+ globalErrorHandler(apiResponse.response, apiResponse.error);
207
+ return undefined as any;
208
+ } else {
209
+ const error = new Error(`${apiResponse.response}:${apiResponse.error}`) as any;
210
+ error.status = apiResponse.response;
211
+ error.digest = `HTTP_${apiResponse.response}`;
212
+ throw error;
213
+ }
214
+ }
215
+
216
+ if (apiResponse.next && params.next) params.next.next = apiResponse.next;
217
+ if (apiResponse.prev && params.previous) params.previous.previous = apiResponse.prev;
218
+ if (apiResponse.self && params.self) params.self.self = apiResponse.self;
219
+
220
+ return apiResponse.data as T;
221
+ }
222
+
223
+ /**
224
+ * Get raw JSON:API response data without deserialization.
225
+ */
226
+ protected static async getRawData(params: {
227
+ type: ApiRequestDataTypeInterface;
228
+ method: ClientHttpMethod;
229
+ endpoint: string;
230
+ companyId?: string;
231
+ }): Promise<any> {
232
+ const language = this.getClientLocale();
233
+
234
+ const apiResponse: ApiResponseInterface = await ClientJsonApiGet({
235
+ classKey: params.type,
236
+ endpoint: params.endpoint,
237
+ companyId: params.companyId,
238
+ language: language,
239
+ });
240
+
241
+ if (!apiResponse.ok) {
242
+ if (globalErrorHandler) {
243
+ globalErrorHandler(apiResponse.response, apiResponse.error);
244
+ return undefined as any;
245
+ } else {
246
+ const error = new Error(`${apiResponse.response}:${apiResponse.error}`) as any;
247
+ error.status = apiResponse.response;
248
+ error.digest = `HTTP_${apiResponse.response}`;
249
+ throw error;
250
+ }
251
+ }
252
+
253
+ return apiResponse.raw;
254
+ }
255
+ }
@@ -0,0 +1,180 @@
1
+ // Server-only abstract service (NOT a server action - cannot be called from client components)
2
+
3
+ import { ApiRequestDataTypeInterface } from "../interfaces/ApiRequestDataTypeInterface";
4
+ import { ApiResponseInterface } from "../interfaces/ApiResponseInterface";
5
+ import {
6
+ ServerJsonApiGet,
7
+ ServerJsonApiPost,
8
+ ServerJsonApiPut,
9
+ ServerJsonApiPatch,
10
+ ServerJsonApiDelete,
11
+ } from "../../server/JsonApiServer";
12
+ import { HttpMethod, NextRef, PreviousRef, SelfRef } from "./AbstractService";
13
+
14
+ /**
15
+ * Server-side abstract base class for services that interact with the JSON:API.
16
+ * Use this for server components and server actions.
17
+ */
18
+ export abstract class ServerAbstractService {
19
+ /**
20
+ * Fetch the next page of results.
21
+ */
22
+ static async next<T>(params: {
23
+ type: ApiRequestDataTypeInterface;
24
+ endpoint: string;
25
+ next?: NextRef;
26
+ previous?: PreviousRef;
27
+ self?: SelfRef;
28
+ }): Promise<T> {
29
+ return await this.callApi<T>({
30
+ method: HttpMethod.GET,
31
+ type: params.type,
32
+ endpoint: params.endpoint,
33
+ next: params.next,
34
+ previous: params.previous,
35
+ self: params.self,
36
+ });
37
+ }
38
+
39
+ /**
40
+ * Fetch the previous page of results.
41
+ */
42
+ static async previous<T>(params: {
43
+ type: ApiRequestDataTypeInterface;
44
+ endpoint: string;
45
+ next?: NextRef;
46
+ previous?: PreviousRef;
47
+ self?: SelfRef;
48
+ }): Promise<T> {
49
+ return await this.callApi<T>({
50
+ method: HttpMethod.GET,
51
+ type: params.type,
52
+ endpoint: params.endpoint,
53
+ next: params.next,
54
+ previous: params.previous,
55
+ self: params.self,
56
+ });
57
+ }
58
+
59
+ /**
60
+ * Make a server-side API call.
61
+ */
62
+ protected static async callApi<T>(params: {
63
+ type: ApiRequestDataTypeInterface;
64
+ method: HttpMethod;
65
+ endpoint: string;
66
+ companyId?: string;
67
+ input?: any;
68
+ overridesJsonApiCreation?: boolean;
69
+ next?: NextRef;
70
+ previous?: PreviousRef;
71
+ self?: SelfRef;
72
+ responseType?: ApiRequestDataTypeInterface;
73
+ files?: { [key: string]: File | Blob } | File | Blob;
74
+ }): Promise<T> {
75
+ let apiResponse: ApiResponseInterface;
76
+
77
+ // Get language from next-intl server
78
+ const { getLocale } = await import("next-intl/server");
79
+ const language = (await getLocale()) ?? "en";
80
+
81
+ switch (params.method) {
82
+ case HttpMethod.GET:
83
+ apiResponse = await ServerJsonApiGet({
84
+ classKey: params.type,
85
+ endpoint: params.endpoint,
86
+ companyId: params.companyId,
87
+ language: language,
88
+ });
89
+ break;
90
+ case HttpMethod.POST:
91
+ apiResponse = await ServerJsonApiPost({
92
+ classKey: params.type,
93
+ endpoint: params.endpoint,
94
+ companyId: params.companyId,
95
+ body: params.input,
96
+ overridesJsonApiCreation: params.overridesJsonApiCreation,
97
+ language: language,
98
+ responseType: params.responseType,
99
+ files: params.files,
100
+ });
101
+ break;
102
+ case HttpMethod.PUT:
103
+ apiResponse = await ServerJsonApiPut({
104
+ classKey: params.type,
105
+ endpoint: params.endpoint,
106
+ companyId: params.companyId,
107
+ body: params.input,
108
+ language: language,
109
+ responseType: params.responseType,
110
+ files: params.files,
111
+ });
112
+ break;
113
+ case HttpMethod.PATCH:
114
+ apiResponse = await ServerJsonApiPatch({
115
+ classKey: params.type,
116
+ endpoint: params.endpoint,
117
+ companyId: params.companyId,
118
+ body: params.input,
119
+ overridesJsonApiCreation: params.overridesJsonApiCreation,
120
+ language: language,
121
+ responseType: params.responseType,
122
+ files: params.files,
123
+ });
124
+ break;
125
+ case HttpMethod.DELETE:
126
+ apiResponse = await ServerJsonApiDelete({
127
+ classKey: params.type,
128
+ endpoint: params.endpoint,
129
+ companyId: params.companyId,
130
+ language: language,
131
+ responseType: params.responseType,
132
+ });
133
+ break;
134
+ default:
135
+ throw new Error("Method not found");
136
+ }
137
+
138
+ if (!apiResponse.ok) {
139
+ const error = new Error(`${apiResponse.response}:${apiResponse.error}`) as any;
140
+ error.status = apiResponse.response;
141
+ error.digest = `HTTP_${apiResponse.response}`;
142
+ throw error;
143
+ }
144
+
145
+ if (apiResponse.next && params.next) params.next.next = apiResponse.next;
146
+ if (apiResponse.prev && params.previous) params.previous.previous = apiResponse.prev;
147
+ if (apiResponse.self && params.self) params.self.self = apiResponse.self;
148
+
149
+ return apiResponse.data as T;
150
+ }
151
+
152
+ /**
153
+ * Get raw JSON:API response data without deserialization.
154
+ */
155
+ protected static async getRawData(params: {
156
+ type: ApiRequestDataTypeInterface;
157
+ method: HttpMethod;
158
+ endpoint: string;
159
+ companyId?: string;
160
+ }): Promise<any> {
161
+ const { getLocale } = await import("next-intl/server");
162
+ const language = (await getLocale()) ?? "en";
163
+
164
+ const apiResponse: ApiResponseInterface = await ServerJsonApiGet({
165
+ classKey: params.type,
166
+ endpoint: params.endpoint,
167
+ companyId: params.companyId,
168
+ language: language,
169
+ });
170
+
171
+ if (!apiResponse.ok) {
172
+ const error = new Error(`${apiResponse.response}:${apiResponse.error}`) as any;
173
+ error.status = apiResponse.response;
174
+ error.digest = `HTTP_${apiResponse.response}`;
175
+ throw error;
176
+ }
177
+
178
+ return apiResponse.raw;
179
+ }
180
+ }
@@ -1,2 +1,4 @@
1
1
  export * from "./AbstractApiData";
2
+ // AbstractService is a base class needed by all services
2
3
  export * from "./AbstractService";
4
+ export * from "./ClientAbstractService";
package/src/core/index.ts CHANGED
@@ -1,7 +1,7 @@
1
- // Interfaces
1
+ // Core interfaces
2
2
  export * from "./interfaces";
3
3
 
4
- // Abstracts (will be added)
4
+ // Abstracts
5
5
  export * from "./abstracts";
6
6
 
7
7
  // Factories
@@ -16,5 +16,37 @@ export * from "./endpoint";
16
16
  // Field selectors
17
17
  export * from "./fields";
18
18
 
19
- // Utilities
19
+ // Core utilities
20
20
  export * from "./utils";
21
+
22
+ // Top-level interfaces (breadcrumb, d3)
23
+ export * from "../interfaces";
24
+
25
+ // Top-level utilities (cn, date-formatter, schemas, etc.)
26
+ export * from "../utils";
27
+
28
+ // Permissions
29
+ export * from "../permissions";
30
+
31
+ // Feature data classes, interfaces, and modules
32
+ export * from "../features/auth/data";
33
+ export * from "../features/auth/enums";
34
+ export * from "../features/auth/auth.module";
35
+ export * from "../features/company/data";
36
+ export * from "../features/company/company.module";
37
+ export * from "../features/content/data";
38
+ export * from "../features/content/content.module";
39
+ export * from "../features/feature/data";
40
+ export * from "../features/feature/feature.module";
41
+ export * from "../features/module";
42
+ export * from "../features/notification/data";
43
+ export * from "../features/notification/notification.module";
44
+ export * from "../features/push/data";
45
+ export * from "../features/push/push.module";
46
+ export * from "../features/role/data";
47
+ export * from "../features/role/role.module";
48
+ export * from "../features/s3";
49
+ export * from "../features/search";
50
+ export * from "../features/user/data";
51
+ export * from "../features/user/user.module";
52
+ export * from "../features/user/author.module";