@nlabs/metropolisjs 0.1.2 → 0.3.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 (329) hide show
  1. package/.github/copilot-instructions.md +167 -0
  2. package/AGENTS.md +13 -0
  3. package/CHANGELOG.md +112 -0
  4. package/GRAPHQL_VALIDATION_RESULTS.md +158 -0
  5. package/PERMISSION_GRAPHQL_INTEGRATION.md +293 -0
  6. package/PERMISSION_IMPLEMENTATION_SUMMARY.md +243 -0
  7. package/README.md +1123 -112
  8. package/SIGNIN_GRAPHQL_VALIDATION.md +125 -0
  9. package/VAULT_GRAPHQL_API_FINDINGS.md +312 -0
  10. package/docs/ACTIONS.md +63 -0
  11. package/docs/COLLECTIONS.md +1038 -0
  12. package/docs/CONNECTIONS.md +1367 -0
  13. package/docs/CRUD_INTEGRATION.md +702 -0
  14. package/examples/connections-usage.tsx +909 -0
  15. package/examples/content-actions-usage.ts +144 -0
  16. package/examples/crud-usage.tsx +847 -0
  17. package/examples/extensibility-usage.tsx +889 -0
  18. package/examples/i18n-import-examples.ts +86 -0
  19. package/examples/i18n-namespace-usage.ts +118 -0
  20. package/examples/i18next-singleton-demo.ts +187 -0
  21. package/examples/permission-system-usage.tsx +415 -0
  22. package/examples/project-details.tsx +397 -0
  23. package/examples/shared-i18n-usage.tsx +203 -0
  24. package/examples/signup-error-handling.ts +100 -0
  25. package/examples/translation-types.ts +86 -0
  26. package/examples/translation-usage.tsx +336 -0
  27. package/index.js +1 -0
  28. package/jest.config.mjs +28 -0
  29. package/lex.config.mjs +11 -2
  30. package/lib/__tests__/e2e/helpers/testGraphQLServer.d.ts +22 -0
  31. package/lib/__tests__/e2e/helpers/testGraphQLServer.d.ts.map +1 -0
  32. package/lib/__tests__/e2e/helpers/testGraphQLServer.js +197 -0
  33. package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.d.ts +3 -0
  34. package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.d.ts.map +1 -0
  35. package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.js +52 -0
  36. package/lib/actions/appActions/appActions.d.ts +29 -0
  37. package/lib/actions/appActions/appActions.d.ts.map +1 -0
  38. package/lib/actions/appActions/appActions.js +159 -0
  39. package/lib/actions/connectionActions/connectionActions.d.ts +19 -0
  40. package/lib/actions/connectionActions/connectionActions.d.ts.map +1 -0
  41. package/lib/actions/connectionActions/connectionActions.js +131 -0
  42. package/lib/actions/contentActions/contentActions.d.ts +34 -0
  43. package/lib/actions/contentActions/contentActions.d.ts.map +1 -0
  44. package/lib/actions/contentActions/contentActions.js +314 -0
  45. package/lib/actions/conversationActions/conversationActions.d.ts +30 -0
  46. package/lib/actions/conversationActions/conversationActions.d.ts.map +1 -0
  47. package/lib/actions/conversationActions/conversationActions.js +225 -0
  48. package/lib/actions/eventActions/eventActions.d.ts +27 -7
  49. package/lib/actions/eventActions/eventActions.d.ts.map +1 -0
  50. package/lib/actions/eventActions/eventActions.js +436 -2
  51. package/lib/actions/groupActions/groupActions.d.ts +30 -0
  52. package/lib/actions/groupActions/groupActions.d.ts.map +1 -0
  53. package/lib/actions/groupActions/groupActions.js +229 -0
  54. package/lib/actions/imageActions/imageActions.d.ts +16 -10
  55. package/lib/actions/imageActions/imageActions.d.ts.map +1 -0
  56. package/lib/actions/imageActions/imageActions.js +593 -2
  57. package/lib/actions/index.d.ts +21 -9
  58. package/lib/actions/index.d.ts.map +1 -0
  59. package/lib/actions/index.js +22 -2
  60. package/lib/actions/locationActions/locationActions.d.ts +11 -9
  61. package/lib/actions/locationActions/locationActions.d.ts.map +1 -0
  62. package/lib/actions/locationActions/locationActions.js +388 -2
  63. package/lib/actions/messageActions/messageActions.d.ts +16 -32
  64. package/lib/actions/messageActions/messageActions.d.ts.map +1 -0
  65. package/lib/actions/messageActions/messageActions.js +235 -2
  66. package/lib/actions/permissionActions/permissionActions.d.ts +34 -0
  67. package/lib/actions/permissionActions/permissionActions.d.ts.map +1 -0
  68. package/lib/actions/permissionActions/permissionActions.js +330 -0
  69. package/lib/actions/personaActions/personaActions.d.ts +65 -0
  70. package/lib/actions/personaActions/personaActions.d.ts.map +1 -0
  71. package/lib/actions/personaActions/personaActions.js +572 -0
  72. package/lib/actions/postActions/postActions.d.ts +12 -32
  73. package/lib/actions/postActions/postActions.d.ts.map +1 -0
  74. package/lib/actions/postActions/postActions.js +447 -2
  75. package/lib/actions/reactionActions/reactionActions.d.ts +13 -27
  76. package/lib/actions/reactionActions/reactionActions.d.ts.map +1 -0
  77. package/lib/actions/reactionActions/reactionActions.js +413 -2
  78. package/lib/actions/sseActions/sseActions.d.ts +1 -0
  79. package/lib/actions/sseActions/sseActions.d.ts.map +1 -0
  80. package/lib/actions/sseActions/sseActions.js +148 -2
  81. package/lib/actions/subscriptionActions/subscriptionActions.d.ts +24 -0
  82. package/lib/actions/subscriptionActions/subscriptionActions.d.ts.map +1 -0
  83. package/lib/actions/subscriptionActions/subscriptionActions.js +329 -0
  84. package/lib/actions/tagActions/tagActions.d.ts +13 -31
  85. package/lib/actions/tagActions/tagActions.d.ts.map +1 -0
  86. package/lib/actions/tagActions/tagActions.js +347 -2
  87. package/lib/actions/translationActions/translationActions.d.ts +38 -0
  88. package/lib/actions/translationActions/translationActions.d.ts.map +1 -0
  89. package/lib/actions/translationActions/translationActions.js +189 -0
  90. package/lib/actions/userActions/userActions.d.ts +44 -95
  91. package/lib/actions/userActions/userActions.d.ts.map +1 -0
  92. package/lib/actions/userActions/userActions.js +870 -2
  93. package/lib/actions/videoActions/videoActions.d.ts +41 -0
  94. package/lib/actions/videoActions/videoActions.d.ts.map +1 -0
  95. package/lib/actions/videoActions/videoActions.js +532 -0
  96. package/lib/actions/websocketActions/websocketActions.d.ts +20 -21
  97. package/lib/actions/websocketActions/websocketActions.d.ts.map +1 -0
  98. package/lib/actions/websocketActions/websocketActions.js +377 -2
  99. package/lib/adapters/appAdapter/appAdapter.d.ts +8 -0
  100. package/lib/adapters/appAdapter/appAdapter.d.ts.map +1 -0
  101. package/lib/adapters/appAdapter/appAdapter.js +90 -0
  102. package/lib/adapters/arangoAdapter/arangoAdapter.d.ts +3 -2
  103. package/lib/adapters/arangoAdapter/arangoAdapter.d.ts.map +1 -0
  104. package/lib/adapters/arangoAdapter/arangoAdapter.js +75 -2
  105. package/lib/adapters/contentAdapter/contentAdapter.d.ts +3 -2
  106. package/lib/adapters/contentAdapter/contentAdapter.d.ts.map +1 -0
  107. package/lib/adapters/contentAdapter/contentAdapter.js +107 -2
  108. package/lib/adapters/conversationAdapter/conversationAdapter.d.ts +3 -2
  109. package/lib/adapters/conversationAdapter/conversationAdapter.d.ts.map +1 -0
  110. package/lib/adapters/conversationAdapter/conversationAdapter.js +75 -2
  111. package/lib/adapters/eventAdapter/eventAdapter.d.ts +5 -2
  112. package/lib/adapters/eventAdapter/eventAdapter.d.ts.map +1 -0
  113. package/lib/adapters/eventAdapter/eventAdapter.js +162 -2
  114. package/lib/adapters/fileAdapter/fileAdapter.d.ts +3 -2
  115. package/lib/adapters/fileAdapter/fileAdapter.d.ts.map +1 -0
  116. package/lib/adapters/fileAdapter/fileAdapter.js +118 -2
  117. package/lib/adapters/groupAdapter/groupAdapter.d.ts +28 -0
  118. package/lib/adapters/groupAdapter/groupAdapter.d.ts.map +1 -0
  119. package/lib/adapters/groupAdapter/groupAdapter.js +66 -0
  120. package/lib/adapters/imageAdapter/imageAdapter.d.ts +9 -2
  121. package/lib/adapters/imageAdapter/imageAdapter.d.ts.map +1 -0
  122. package/lib/adapters/imageAdapter/imageAdapter.js +134 -2
  123. package/lib/adapters/index.d.ts +34 -16
  124. package/lib/adapters/index.d.ts.map +1 -0
  125. package/lib/adapters/index.js +19 -2
  126. package/lib/adapters/locationAdapter/locationAdapter.d.ts +3 -2
  127. package/lib/adapters/locationAdapter/locationAdapter.d.ts.map +1 -0
  128. package/lib/adapters/locationAdapter/locationAdapter.js +95 -2
  129. package/lib/adapters/messageAdapter/messageAdapter.d.ts +23 -19
  130. package/lib/adapters/messageAdapter/messageAdapter.d.ts.map +1 -0
  131. package/lib/adapters/messageAdapter/messageAdapter.js +82 -2
  132. package/lib/adapters/permissionAdapter/permissionAdapter.d.ts +41 -0
  133. package/lib/adapters/permissionAdapter/permissionAdapter.d.ts.map +1 -0
  134. package/lib/adapters/permissionAdapter/permissionAdapter.js +120 -0
  135. package/lib/adapters/personaAdapter/personaAdapter.d.ts +28 -2
  136. package/lib/adapters/personaAdapter/personaAdapter.d.ts.map +1 -0
  137. package/lib/adapters/personaAdapter/personaAdapter.js +161 -2
  138. package/lib/adapters/postAdapter/postAdapter.d.ts +3 -2
  139. package/lib/adapters/postAdapter/postAdapter.d.ts.map +1 -0
  140. package/lib/adapters/postAdapter/postAdapter.js +115 -2
  141. package/lib/adapters/reactionAdapter/reactionAdapter.d.ts +5 -2
  142. package/lib/adapters/reactionAdapter/reactionAdapter.d.ts.map +1 -0
  143. package/lib/adapters/reactionAdapter/reactionAdapter.js +81 -2
  144. package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts +3 -2
  145. package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts.map +1 -0
  146. package/lib/adapters/reaktorAdapter/reaktorAdapter.js +58 -2
  147. package/lib/adapters/sessionAdapter/sessionAdapter.d.ts +3 -2
  148. package/lib/adapters/sessionAdapter/sessionAdapter.d.ts.map +1 -0
  149. package/lib/adapters/sessionAdapter/sessionAdapter.js +80 -2
  150. package/lib/adapters/tagAdapter/tagAdapter.d.ts +3 -2
  151. package/lib/adapters/tagAdapter/tagAdapter.d.ts.map +1 -0
  152. package/lib/adapters/tagAdapter/tagAdapter.js +98 -2
  153. package/lib/adapters/translationAdapter/translationAdapter.d.ts +21 -0
  154. package/lib/adapters/translationAdapter/translationAdapter.d.ts.map +1 -0
  155. package/lib/adapters/translationAdapter/translationAdapter.js +55 -0
  156. package/lib/adapters/userAdapter/userAdapter.d.ts +18 -6
  157. package/lib/adapters/userAdapter/userAdapter.d.ts.map +1 -0
  158. package/lib/adapters/userAdapter/userAdapter.js +302 -2
  159. package/lib/adapters/videoAdapter/videoAdapter.d.ts +8 -0
  160. package/lib/adapters/videoAdapter/videoAdapter.d.ts.map +1 -0
  161. package/lib/adapters/videoAdapter/videoAdapter.js +194 -0
  162. package/lib/config/index.d.ts +19 -6
  163. package/lib/config/index.d.ts.map +1 -0
  164. package/lib/config/index.js +97 -2
  165. package/lib/constants/Collections.d.ts +44 -0
  166. package/lib/constants/Collections.d.ts.map +1 -0
  167. package/lib/constants/Collections.js +40 -0
  168. package/lib/constants/MetropolisConstants.d.ts +1 -0
  169. package/lib/constants/MetropolisConstants.d.ts.map +1 -0
  170. package/lib/constants/MetropolisConstants.js +15 -2
  171. package/lib/graphql/message.d.ts +1 -0
  172. package/lib/graphql/message.d.ts.map +1 -0
  173. package/lib/graphql/message.js +6 -4
  174. package/lib/graphql/notification.d.ts +1 -0
  175. package/lib/graphql/notification.d.ts.map +1 -0
  176. package/lib/graphql/notification.js +6 -4
  177. package/lib/graphql/session.d.ts +1 -0
  178. package/lib/graphql/session.d.ts.map +1 -0
  179. package/lib/graphql/session.js +4 -3
  180. package/lib/index.d.ts +45 -22
  181. package/lib/index.d.ts.map +1 -0
  182. package/lib/index.js +248 -2
  183. package/lib/stores/appStore.d.ts +1 -0
  184. package/lib/stores/appStore.d.ts.map +1 -0
  185. package/lib/stores/appStore.js +23 -2
  186. package/lib/stores/contentStore.d.ts +36 -0
  187. package/lib/stores/contentStore.d.ts.map +1 -0
  188. package/lib/stores/contentStore.js +139 -0
  189. package/lib/stores/conversationStore.d.ts +38 -0
  190. package/lib/stores/conversationStore.d.ts.map +1 -0
  191. package/lib/stores/conversationStore.js +117 -0
  192. package/lib/stores/eventStore.d.ts +4 -1
  193. package/lib/stores/eventStore.d.ts.map +1 -0
  194. package/lib/stores/eventStore.js +47 -2
  195. package/lib/stores/groupStore.d.ts +37 -0
  196. package/lib/stores/groupStore.d.ts.map +1 -0
  197. package/lib/stores/groupStore.js +68 -0
  198. package/lib/stores/imageStore.d.ts +6 -1
  199. package/lib/stores/imageStore.d.ts.map +1 -0
  200. package/lib/stores/imageStore.js +53 -2
  201. package/lib/stores/index.d.ts +20 -11
  202. package/lib/stores/index.d.ts.map +1 -0
  203. package/lib/stores/index.js +24 -2
  204. package/lib/stores/locationStore.d.ts +2 -1
  205. package/lib/stores/locationStore.d.ts.map +1 -0
  206. package/lib/stores/locationStore.js +42 -2
  207. package/lib/stores/messageStore.d.ts +19 -4
  208. package/lib/stores/messageStore.d.ts.map +1 -0
  209. package/lib/stores/messageStore.js +137 -2
  210. package/lib/stores/notificationStore.d.ts +33 -0
  211. package/lib/stores/notificationStore.d.ts.map +1 -0
  212. package/lib/stores/notificationStore.js +55 -0
  213. package/lib/stores/permissionStore.d.ts +37 -0
  214. package/lib/stores/permissionStore.d.ts.map +1 -0
  215. package/lib/stores/permissionStore.js +117 -0
  216. package/lib/stores/personaStore.d.ts +26 -0
  217. package/lib/stores/personaStore.d.ts.map +1 -0
  218. package/lib/stores/personaStore.js +118 -0
  219. package/lib/stores/postStore.d.ts +2 -1
  220. package/lib/stores/postStore.d.ts.map +1 -0
  221. package/lib/stores/postStore.js +53 -2
  222. package/lib/stores/reactionStore.d.ts +1 -0
  223. package/lib/stores/reactionStore.d.ts.map +1 -0
  224. package/lib/stores/reactionStore.js +28 -2
  225. package/lib/stores/subscriptionStore.d.ts +41 -0
  226. package/lib/stores/subscriptionStore.d.ts.map +1 -0
  227. package/lib/stores/subscriptionStore.js +85 -0
  228. package/lib/stores/tagStore.d.ts +8 -5
  229. package/lib/stores/tagStore.d.ts.map +1 -0
  230. package/lib/stores/tagStore.js +87 -2
  231. package/lib/stores/translationStore.d.ts +42 -0
  232. package/lib/stores/translationStore.d.ts.map +1 -0
  233. package/lib/stores/translationStore.js +122 -0
  234. package/lib/stores/userStore.d.ts +5 -4
  235. package/lib/stores/userStore.d.ts.map +1 -0
  236. package/lib/stores/userStore.js +319 -2
  237. package/lib/stores/videoStore.d.ts +39 -0
  238. package/lib/stores/videoStore.d.ts.map +1 -0
  239. package/lib/stores/videoStore.js +132 -0
  240. package/lib/stores/websocketStore.d.ts +1 -0
  241. package/lib/stores/websocketStore.d.ts.map +1 -0
  242. package/lib/stores/websocketStore.js +51 -2
  243. package/lib/types/apps.types.d.ts +17 -0
  244. package/lib/types/apps.types.d.ts.map +1 -0
  245. package/lib/types/apps.types.js +6 -0
  246. package/lib/types/common.types.d.ts +31 -0
  247. package/lib/types/common.types.d.ts.map +1 -0
  248. package/lib/types/common.types.js +6 -0
  249. package/lib/types/conversations.types.d.ts +17 -0
  250. package/lib/types/conversations.types.d.ts.map +1 -0
  251. package/lib/types/conversations.types.js +6 -0
  252. package/lib/types/edges.types.d.ts +38 -0
  253. package/lib/types/edges.types.d.ts.map +1 -0
  254. package/lib/types/edges.types.js +6 -0
  255. package/lib/types/groups.types.d.ts +19 -0
  256. package/lib/types/groups.types.d.ts.map +1 -0
  257. package/lib/types/groups.types.js +6 -0
  258. package/lib/types/index.d.ts +12 -0
  259. package/lib/types/index.d.ts.map +1 -0
  260. package/lib/types/index.js +12 -0
  261. package/lib/types/subscriptions.types.d.ts +32 -0
  262. package/lib/types/subscriptions.types.d.ts.map +1 -0
  263. package/lib/types/subscriptions.types.js +6 -0
  264. package/lib/types/videos.types.d.ts +61 -0
  265. package/lib/types/videos.types.d.ts.map +1 -0
  266. package/lib/types/videos.types.js +6 -0
  267. package/lib/utils/MetropolisProvider.d.ts +39 -15
  268. package/lib/utils/MetropolisProvider.d.ts.map +1 -0
  269. package/lib/utils/MetropolisProvider.js +31 -2
  270. package/lib/utils/actionFactory.d.ts +21 -19
  271. package/lib/utils/actionFactory.d.ts.map +1 -0
  272. package/lib/utils/actionFactory.js +95 -2
  273. package/lib/utils/api.d.ts +5 -4
  274. package/lib/utils/api.d.ts.map +1 -0
  275. package/lib/utils/api.js +252 -6
  276. package/lib/utils/app.d.ts +1 -0
  277. package/lib/utils/app.d.ts.map +1 -0
  278. package/lib/utils/app.js +15 -2
  279. package/lib/utils/baseActionFactory.d.ts +5 -23
  280. package/lib/utils/baseActionFactory.d.ts.map +1 -0
  281. package/lib/utils/baseActionFactory.js +72 -2
  282. package/lib/utils/configUtils.d.ts +11 -0
  283. package/lib/utils/configUtils.d.ts.map +1 -0
  284. package/lib/utils/configUtils.js +20 -0
  285. package/lib/utils/dateUtils.d.ts +1 -0
  286. package/lib/utils/dateUtils.d.ts.map +1 -0
  287. package/lib/utils/dateUtils.js +11 -2
  288. package/lib/utils/file.d.ts +3 -1
  289. package/lib/utils/file.d.ts.map +1 -0
  290. package/lib/utils/file.js +156 -2
  291. package/lib/utils/i18n.d.ts +7 -0
  292. package/lib/utils/i18n.d.ts.map +1 -0
  293. package/lib/utils/i18n.js +96 -0
  294. package/lib/utils/index.d.ts +20 -0
  295. package/lib/utils/index.d.ts.map +1 -0
  296. package/lib/utils/index.js +26 -0
  297. package/lib/utils/location.d.ts +4 -3
  298. package/lib/utils/location.d.ts.map +1 -0
  299. package/lib/utils/location.js +82 -2
  300. package/lib/utils/permissionUtils.d.ts +22 -0
  301. package/lib/utils/permissionUtils.d.ts.map +1 -0
  302. package/lib/utils/permissionUtils.js +72 -0
  303. package/lib/utils/requestCache.d.ts +8 -0
  304. package/lib/utils/requestCache.d.ts.map +1 -0
  305. package/lib/utils/requestCache.js +53 -0
  306. package/lib/utils/session.d.ts +14 -0
  307. package/lib/utils/session.d.ts.map +1 -0
  308. package/lib/utils/session.js +107 -0
  309. package/lib/utils/useConversationTyping.d.ts +26 -0
  310. package/lib/utils/useConversationTyping.d.ts.map +1 -0
  311. package/lib/utils/useConversationTyping.js +117 -0
  312. package/lib/utils/useMetropolis.d.ts +67 -12
  313. package/lib/utils/useMetropolis.d.ts.map +1 -0
  314. package/lib/utils/useMetropolis.js +311 -2
  315. package/lib/utils/useTranslations.d.ts +16 -0
  316. package/lib/utils/useTranslations.d.ts.map +1 -0
  317. package/lib/utils/useTranslations.js +105 -0
  318. package/lib/utils/validatorFactory.d.ts +3 -2
  319. package/lib/utils/validatorFactory.d.ts.map +1 -0
  320. package/lib/utils/validatorFactory.js +95 -2
  321. package/package.json +58 -17
  322. package/temp_signin.ts +73 -0
  323. package/lib/actions/profileActions/profileActions.d.ts +0 -50
  324. package/lib/actions/profileActions/profileActions.js +0 -2
  325. package/lib/adapters/profileAdapter/profileAdapter.d.ts +0 -32
  326. package/lib/adapters/profileAdapter/profileAdapter.js +0 -2
  327. package/lib/stores/profileStore.d.ts +0 -24
  328. package/lib/stores/profileStore.js +0 -2
  329. /package/{FACTORY_PATTERN_GUIDE.md → factoryPatternGuide.md} +0 -0
package/README.md CHANGED
@@ -11,38 +11,38 @@
11
11
 
12
12
  MetropolisJS is the bridge that connects your frontend dreams to backend reality. Built on the powerful combination of **Reaktor** (backend services) and **ArkhamJS** (frontend data store), MetropolisJS provides a seamless, real-time integration layer that handles everything from user authentication to real-time messaging and notifications.
13
13
 
14
- ## 🚀 Why MetropolisJS?
14
+ ## Why MetropolisJS?
15
15
 
16
- ### **Seamless Integration**
16
+ ### **Seamless Integration**
17
17
 
18
18
  Connect your React frontend to Reaktor-powered backend services with zero configuration headaches. MetropolisJS handles all the complex data flow, state management, and real-time communication.
19
19
 
20
- ### 🔄 **Real-Time Everything**
20
+ ### **Real-Time Everything**
21
21
 
22
22
  Built-in WebSocket and Server-Sent Events (SSE) support for instant messaging, live notifications, and real-time data synchronization. Your users will never miss a beat.
23
23
 
24
- ### 🛡️ **Type-Safe & Reliable**
24
+ ### **Type-Safe & Reliable**
25
25
 
26
26
  Full TypeScript support with comprehensive type definitions. Catch errors at compile time, not runtime.
27
27
 
28
- ### 🎯 **Developer Experience First**
28
+ ### **Developer Experience First**
29
29
 
30
30
  Clean, intuitive APIs that make complex operations feel simple. Focus on building features, not boilerplate.
31
31
 
32
- ## 🎯 What Can You Build?
33
-
32
+ ## What Can You Build?
34
33
  MetropolisJS powers applications that need:
35
34
 
36
- - **🔐 User Authentication & Authorization**
37
- - **💬 Real-Time Messaging Systems**
38
- - **🔔 Live Notifications**
39
- - **📱 Social Media Features** (posts, reactions, tags)
40
- - **📍 Location-Based Services**
41
- - **🖼️ Media Management** (images, files)
42
- - **📅 Event Management**
43
- - **👥 User Connections & Relationships**
35
+ - **User Authentication & Authorization**
36
+ - **Role-Based Access Control (RBAC)** with 5-level permission system
37
+ - **Real-Time Messaging Systems**
38
+ - **Live Notifications**
39
+ - **Social Media Features** (posts, reactions, tags)
40
+ - **Location-Based Services**
41
+ - **Media Management** (images, files)
42
+ - **Event Management**
43
+ - **User Connections & Relationships**
44
44
 
45
- ## 🛠️ Quick Start
45
+ ## Quick Start
46
46
 
47
47
  ### Installation
48
48
 
@@ -53,15 +53,20 @@ npm install @nlabs/metropolisjs @nlabs/arkhamjs @nlabs/arkhamjs-utils-react
53
53
  ### Basic Setup
54
54
 
55
55
  ```tsx
56
- import React from 'react';
57
- import {Metropolis} from '@nlabs/metropolisjs';
58
- import {useMetropolis} from '@nlabs/metropolisjs';
56
+ import {Metropolis, useUserActions, useMessageActions, useWebsocketActions} from '@nlabs/metropolisjs';
59
57
 
60
58
  const App = () => {
61
59
  return (
62
60
  <Metropolis config={{
63
- environment: 'development',
64
- // Your configuration here
61
+ development: {
62
+ environment: 'development',
63
+ app: {
64
+ api: {
65
+ url: 'http://localhost:3000/app',
66
+ public: 'http://localhost:3000/public'
67
+ }
68
+ }
69
+ }
65
70
  }}>
66
71
  <YourApp />
67
72
  </Metropolis>
@@ -69,18 +74,255 @@ const App = () => {
69
74
  };
70
75
 
71
76
  const YourApp = () => {
72
- const {userActions, messageActions, websocketActions} = useMetropolis();
77
+ // Use specialized hooks for better performance
78
+ const userActions = useUserActions();
79
+ const messageActions = useMessageActions();
80
+ const websocketActions = useWebsocketActions();
73
81
 
74
82
  // Start building amazing features!
75
83
  return <div>Your app content</div>;
76
84
  };
77
85
  ```
78
86
 
87
+ ### Using Actions
88
+
89
+ MetropolisJS provides multiple ways to access actions:
90
+
91
+ ```tsx
92
+ // Option 1: Specialized hooks (recommended - best performance)
93
+ const userActions = useUserActions();
94
+ const postActions = usePostActions();
95
+
96
+ // Option 2: Selective creation
97
+ const {userActions, postActions} = useMetropolis(['user', 'post']);
98
+
99
+ // Option 3: All actions (default behavior)
100
+ const {userActions, postActions, messageActions} = useMetropolis();
101
+ ```
102
+
103
+ ## Configuration
104
+
105
+ The `Metropolis` component accepts three main props: `config`, `adapters`, and `translations`. Here's how to configure each:
106
+
107
+ ### Configuration Object
108
+
109
+ The `config` prop accepts a `MetropolisConfiguration` object that supports environment-specific settings:
110
+
111
+ ```tsx
112
+ <Metropolis
113
+ config={{
114
+ // Environment-specific configurations
115
+ development: {
116
+ environment: 'development',
117
+ app: {
118
+ api: {
119
+ url: 'http://localhost:3000/app',
120
+ public: 'http://localhost:3000/public',
121
+ uploadImage: 'http://localhost:3000/upload'
122
+ },
123
+ urls: {
124
+ websocket: 'ws://localhost:3000'
125
+ },
126
+ session: {
127
+ maxMinutes: 1440, // 24 hours
128
+ minMinutes: 15
129
+ },
130
+ name: 'My App',
131
+ version: '1.0.0'
132
+ },
133
+ isAuth: () => {
134
+ // Custom authentication check
135
+ const session = flux.getState('user.session', {});
136
+ return !!session.userActive;
137
+ }
138
+ },
139
+ production: {
140
+ environment: 'production',
141
+ app: {
142
+ api: {
143
+ url: 'https://api.example.com/app',
144
+ public: 'https://api.example.com/public',
145
+ uploadImage: 'https://api.example.com/upload'
146
+ },
147
+ urls: {
148
+ websocket: 'wss://api.example.com'
149
+ },
150
+ session: {
151
+ maxMinutes: 2880, // 48 hours
152
+ minMinutes: 30
153
+ }
154
+ }
155
+ }
156
+ }}
157
+ >
158
+ <YourApp />
159
+ </Metropolis>
160
+ ```
161
+
162
+ #### Configuration Options
163
+
164
+ **Environment Configuration** (`MetropolisEnvironmentConfiguration`):
165
+ - `environment`: `'development' | 'production' | 'test' | 'local'` - Current environment
166
+ - `app`: Application-specific configuration
167
+ - `api`: API endpoint configuration
168
+ - `url`: Main API endpoint
169
+ - `public`: Public API endpoint
170
+ - `uploadImage`: Image upload endpoint
171
+ - `urls`: Additional URL configurations
172
+ - `websocket`: WebSocket server URL
173
+ - `session`: Session management settings
174
+ - `maxMinutes`: Maximum session duration in minutes
175
+ - `minMinutes`: Minimum session duration in minutes
176
+ - `name`: Application name
177
+ - `version`: Application version
178
+ - `isAuth`: Function that returns a boolean indicating if the user is authenticated
179
+ - `adapters`: Custom adapters (can also be passed as a separate prop)
180
+
181
+ ### Custom Adapters
182
+
183
+ Pass custom adapters to override default data transformation behavior:
184
+
185
+ ```tsx
186
+ import {parseUser, parseMessage} from '@nlabs/metropolisjs';
187
+
188
+ <Metropolis
189
+ adapters={{
190
+ User: parseUser,
191
+ Message: parseMessage,
192
+ // Add other custom adapters as needed
193
+ Content: customContentAdapter,
194
+ Event: customEventAdapter,
195
+ Image: customImageAdapter,
196
+ Location: customLocationAdapter,
197
+ Post: customPostAdapter,
198
+ Persona: customPersonaAdapter,
199
+ Reaction: customReactionAdapter,
200
+ Tag: customTagAdapter,
201
+ Translation: customTranslationAdapter
202
+ }}
203
+ >
204
+ <YourApp />
205
+ </Metropolis>
206
+ ```
207
+
208
+ ### Translations
209
+
210
+ MetropolisJS supports both simple and complex translation formats:
211
+
212
+ #### Simple Translations
213
+
214
+ ```tsx
215
+ <Metropolis
216
+ translations={{
217
+ 'welcome': 'Welcome to MetropolisJS!',
218
+ 'save': 'Save',
219
+ 'cancel': 'Cancel',
220
+ 'hello_user': 'Hello {{name}}!',
221
+ 'items_count': 'You have {{count}} items'
222
+ }}
223
+ >
224
+ <YourApp />
225
+ </Metropolis>
226
+ ```
227
+
228
+ #### Complex Translations (with locale and namespace)
229
+
230
+ ```tsx
231
+ <Metropolis
232
+ translations={{
233
+ 'welcome': {
234
+ value: 'Welcome to MetropolisJS!',
235
+ locale: 'en',
236
+ namespace: 'common'
237
+ },
238
+ 'save': {
239
+ value: 'Save',
240
+ locale: 'en',
241
+ namespace: 'actions'
242
+ }
243
+ }}
244
+ >
245
+ <YourApp />
246
+ </Metropolis>
247
+ ```
248
+
249
+ ### Complete Configuration Example
250
+
251
+ ```tsx
252
+ import {Metropolis} from '@nlabs/metropolisjs';
253
+ import {parseUser, parseMessage} from '@nlabs/metropolisjs';
254
+
255
+ const App = () => {
256
+ return (
257
+ <Metropolis
258
+ config={{
259
+ development: {
260
+ environment: 'development',
261
+ app: {
262
+ api: {
263
+ url: 'http://localhost:3000/app',
264
+ public: 'http://localhost:3000/public'
265
+ },
266
+ urls: {
267
+ websocket: 'ws://localhost:3000'
268
+ },
269
+ session: {
270
+ maxMinutes: 1440,
271
+ minMinutes: 15
272
+ }
273
+ },
274
+ isAuth: () => {
275
+ // Your custom auth logic
276
+ return true;
277
+ }
278
+ },
279
+ production: {
280
+ environment: 'production',
281
+ app: {
282
+ api: {
283
+ url: 'https://api.example.com/app',
284
+ public: 'https://api.example.com/public'
285
+ },
286
+ urls: {
287
+ websocket: 'wss://api.example.com'
288
+ }
289
+ }
290
+ }
291
+ }}
292
+ adapters={{
293
+ User: parseUser,
294
+ Message: parseMessage
295
+ }}
296
+ translations={{
297
+ 'welcome': 'Welcome!',
298
+ 'save': 'Save',
299
+ 'cancel': 'Cancel'
300
+ }}
301
+ >
302
+ <YourApp />
303
+ </Metropolis>
304
+ );
305
+ };
306
+ ```
307
+
308
+ ### Environment Detection
309
+
310
+ MetropolisJS automatically detects the environment based on:
311
+
312
+ 1. The `environment` property in your config
313
+ 2. `process.env.stage` (if set)
314
+ 3. `process.env.NODE_ENV` (fallback)
315
+ 4. Defaults to `'local'` if none are set
316
+
317
+ The configuration system will merge environment-specific settings with default values, allowing you to override only what you need.
318
+
79
319
  ### User Authentication Example
80
320
 
81
321
  ```tsx
322
+ import {useUserActions} from '@nlabs/metropolisjs';
323
+
82
324
  const LoginForm = () => {
83
- const {userActions} = useMetropolis();
325
+ const userActions = useUserActions(); // Specialized hook - only creates user actions
84
326
  const [username, setUsername] = useState('');
85
327
  const [password, setPassword] = useState('');
86
328
 
@@ -115,8 +357,11 @@ const LoginForm = () => {
115
357
  ### Real-Time Messaging
116
358
 
117
359
  ```tsx
360
+ import {useMessageActions, useWebsocketActions} from '@nlabs/metropolisjs';
361
+
118
362
  const ChatComponent = () => {
119
- const {messageActions, websocketActions} = useMetropolis();
363
+ const messageActions = useMessageActions();
364
+ const websocketActions = useWebsocketActions();
120
365
  const [messages, setMessages] = useState([]);
121
366
 
122
367
  useEffect(() => {
@@ -145,9 +390,9 @@ const ChatComponent = () => {
145
390
  };
146
391
  ```
147
392
 
148
- ## 🏗️ Architecture
393
+ ## Architecture
149
394
 
150
- MetropolisJS is built on a powerful three-layer architecture:
395
+ MetropolisJS is built on a powerful three-layer architecture with modern React patterns:
151
396
 
152
397
  ```
153
398
  ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
@@ -155,126 +400,766 @@ MetropolisJS is built on a powerful three-layer architecture:
155
400
  │ │◄──►│ │◄──►│ Backend │
156
401
  │ UI Layer │ │ Integration │ │ Services │
157
402
  └─────────────────┘ └─────────────────┘ └─────────────────┘
158
-
159
-
160
- ┌─────────────────┐
161
- │ ArkhamJS │
162
- │ Data Store │
163
- │ │
164
- └─────────────────┘
403
+
404
+
405
+ ┌─────────────────┐
406
+ ArkhamJS │
407
+ Data Store │
408
+
409
+ └─────────────────┘
410
+
411
+
412
+ ┌─────────────────┐
413
+ │ React Context │
414
+ │ (Config/Flux) │
415
+ └─────────────────┘
165
416
  ```
166
417
 
167
- ### 🔧 Core Components
418
+ ### Core Components
168
419
 
169
- - **Actions**: Handle all API interactions and business logic
420
+ - **Actions**: Handle all API interactions and business logic (factory pattern)
170
421
  - **Adapters**: Transform data between frontend and backend formats
171
422
  - **Stores**: Manage application state with ArkhamJS
172
423
  - **WebSocket Actions**: Handle real-time communication
173
- - **Configuration**: Flexible setup for any environment
424
+ - **Configuration**: Context-based configuration (React best practices)
425
+ - **Hooks**: Specialized hooks for accessing actions and configuration
426
+
427
+ ### Modern Architecture Features
428
+
429
+ MetropolisJS follows React best practices:
430
+
431
+ - **Context-Based Configuration**: No global state, configuration through React Context
432
+ - **Factory Pattern**: Functional action creation with dependency injection
433
+ - **Selective Action Creation**: Only create actions you need for better performance
434
+ - **Type Safety**: Full TypeScript support with proper type inference
435
+ - **Specialized Hooks**: Individual hooks for each action type
436
+ - **Flux State Integration**: Configuration stored in flux state for non-React code access
437
+
438
+ ## Available Actions
439
+
440
+ MetropolisJS provides comprehensive actions for all your needs. Access them using specialized hooks or the main `useMetropolis()` hook:
441
+
442
+ ### Specialized Hooks (Recommended)
443
+
444
+ - `useUserActions()` - Authentication, personas, user management
445
+ - `useMessageActions()` - Real-time messaging and conversations
446
+ - `usePermissionActions()` - Permission and role management (RBAC)
447
+ - `usePostActions()` - Social media posts and content
448
+ - `useReactionActions()` - Likes, reactions, and interactions
449
+ - `useTagActions()` - Content categorization and discovery
450
+ - `useEventActions()` - Event management and scheduling
451
+ - `useImageActions()` - Media upload and management
452
+ - `useLocationActions()` - Geolocation and location-based features
453
+ - `useWebsocketActions()` - Real-time communication setup
454
+ - `useContentActions()` - Content management
455
+ - `usePersonaActions()` - Persona management
456
+ - `useTranslationActions()` - Translation management
457
+
458
+ ### Using Collection Actions
459
+
460
+ ```tsx
461
+ // Recommended: Use specialized hooks (only creates what you need)
462
+ const userActions = useUserActions();
463
+ const postActions = usePostActions();
464
+ const permissionActions = usePermissionActions();
465
+
466
+ // Alternative: Selective creation
467
+ const {userActions, postActions, permissionActions} = useMetropolis(['user', 'post', 'permission']);
468
+
469
+ // Alternative: All actions (creates all action types)
470
+ const {userActions, postActions, messageActions, permissionActions} = useMetropolis();
471
+ ```
472
+
473
+ ## Factory Pattern Guide
474
+
475
+ MetropolisJS has been refactored to use a **factory function pattern** for actions instead of class-based approaches. This provides better functional programming practices, improved testability, and enhanced flexibility through dependency injection.
476
+
477
+ ### Key Benefits
478
+
479
+ 1. **Functional Programming**: Pure functions instead of classes with side effects
480
+ 2. **Better Testability**: Easier to mock and test individual functions
481
+ 3. **Composability**: Actions can be easily combined and extended
482
+ 4. **Dependency Injection**: Custom adapters can be injected and merged with defaults
483
+ 5. **Backward Compatibility**: Legacy class wrappers maintain existing API compatibility
484
+
485
+ ### Basic Usage
486
+
487
+ #### Before (Class-based)
488
+
489
+ ```typescript
490
+ import {userActions} from '../actions/userActions';
491
+
492
+ const userActions = new userActions(flux);
493
+ const user = await userActions.add(userData);
494
+ ```
495
+
496
+ #### After (Factory Pattern)
497
+
498
+ ```typescript
499
+ import {createUserActions} from '../actions/userActions';
500
+
501
+ const userActions = createUserActions(flux);
502
+ const user = await userActions.add(userData);
503
+ ```
504
+
505
+ ### Advanced Usage with Custom Adapters
506
+
507
+ #### Custom Validation Adapter
508
+
509
+ ```typescript
510
+ // Custom adapter that extends default behavior
511
+ const customUserAdapter = (input: unknown, options?: UserAdapterOptions) => {
512
+ // input is already validated by default adapter
513
+ const user = input as any;
514
+
515
+ // Add business-specific validation
516
+ if (user.email && !user.email.includes('@company.com')) {
517
+ throw new Error('Only company emails allowed');
518
+ }
519
+
520
+ // Add computed fields
521
+ return {
522
+ ...user,
523
+ fullName: `${user.firstName || ''} ${user.lastName || ''}`.trim(),
524
+ isAdmin: user.userAccess >= 3
525
+ };
526
+ };
527
+
528
+ const userActions = createUserActions(flux, {
529
+ userAdapter: customUserAdapter
530
+ });
531
+ ```
532
+
533
+ #### Configuration-based Adapters
534
+
535
+ ```typescript
536
+ const userActions = createUserActions(flux, {
537
+ userAdapterOptions: {
538
+ strict: true,
539
+ environment: 'production',
540
+ customValidation: (input) => {
541
+ // Additional validation logic
542
+ return input;
543
+ }
544
+ }
545
+ });
546
+ ```
547
+
548
+ #### Runtime Adapter Updates
549
+
550
+ ```typescript
551
+ const userActions = createUserActions(flux);
552
+
553
+ // Update adapter at runtime
554
+ userActions.updateUserAdapter(customUserAdapter);
555
+
556
+ // Update options at runtime
557
+ userActions.updateUserAdapterOptions({
558
+ strict: true,
559
+ environment: 'production'
560
+ });
561
+ ```
562
+
563
+ ### Available Factory Functions
564
+
565
+ All action files now export factory functions:
566
+
567
+ - `createUserActions(flux, options?)` - User management
568
+ - `createPostActions(flux, options?)` - Post management
569
+ - `createEventActions(flux, options?)` - Event management
570
+ - `createMessageActions(flux, options?)` - Messaging
571
+ - `createImageActions(flux, options?)` - Image handling
572
+ - `createLocationActions(flux, options?)` - Location services
573
+ - `createReactionActions(flux, options?)` - Reactions
574
+ - `createTagActions(flux, options?)` - Tag management
575
+ - `createWebsocketActions(flux)` - WebSocket connections
576
+
577
+ ### Adapter Options Interface
578
+
579
+ All adapters support the same options interface:
580
+
581
+ ```typescript
582
+ interface AdapterOptions {
583
+ strict?: boolean; // Enable strict validation
584
+ allowPartial?: boolean; // Allow partial data
585
+ environment?: 'development' | 'production' | 'test';
586
+ customValidation?: (input: unknown) => unknown;
587
+ }
588
+ ```
589
+
590
+ ### Migration Guide
591
+
592
+ #### Step 1: Update Imports
593
+
594
+ ```typescript
595
+ // Old
596
+ import {userActions} from '../actions/userActions';
597
+
598
+ // New
599
+ import {createUserActions} from '../actions/userActions';
600
+ ```
601
+
602
+ #### Step 2: Update Instantiation
603
+
604
+ ```typescript
605
+ // Old
606
+ const userActions = new userActions(flux, customAdapter);
607
+
608
+ // New
609
+ const userActions = createUserActions(flux, {
610
+ userAdapter: customAdapter
611
+ });
612
+ ```
613
+
614
+ #### Step 3: Using Actions in Components
615
+
616
+ The recommended approach is to use specialized hooks:
617
+
618
+ ```typescript
619
+ // Recommended: Use specialized hooks
620
+ import {useUserActions, usePostActions} from '@nlabs/metropolisjs';
621
+
622
+ const MyComponent = () => {
623
+ const userActions = useUserActions();
624
+ const postActions = usePostActions();
625
+ // ...
626
+ };
627
+
628
+ // Alternative: Use useMetropolis with selective creation
629
+ import {useMetropolis} from '@nlabs/metropolisjs';
630
+
631
+ const MyComponent = () => {
632
+ const {userActions, postActions} = useMetropolis(['user', 'post']);
633
+ // ...
634
+ };
635
+ ```
636
+
637
+ ### Configuration Access
638
+
639
+ Access configuration using React hooks:
640
+
641
+ ```typescript
642
+ import {useMetropolisConfig} from '@nlabs/metropolisjs';
643
+
644
+ const MyComponent = () => {
645
+ const config = useMetropolisConfig();
646
+ const apiUrl = config.app?.api?.url;
647
+ // ...
648
+ };
649
+ ```
650
+
651
+ For non-React code (actions, utilities), use:
652
+
653
+ ```typescript
654
+ import {getConfigFromFlux} from '@nlabs/metropolisjs';
655
+
656
+ const config = getConfigFromFlux(flux);
657
+ const apiUrl = config.app?.api?.url || '';
658
+ ```
659
+
660
+ **Note:** The `Config` class has been removed. Use `useMetropolisConfig()` in React components or `getConfigFromFlux()` in non-React code.
661
+
662
+ ### Testing Examples
663
+
664
+ #### Unit Testing Actions
665
+
666
+ ```typescript
667
+ import {createUserActions} from '@nlabs/metropolisjs';
668
+
669
+ describe('userActions', () => {
670
+ let flux: FluxFramework;
671
+ let userActions: userActions;
672
+
673
+ beforeEach(() => {
674
+ flux = createMockFlux();
675
+ // Store config in flux state for actions to access
676
+ flux.setState('app.config', {
677
+ app: { api: { url: 'http://localhost:3000/app' } }
678
+ });
679
+ userActions = createUserActions(flux);
680
+ });
681
+
682
+ it('should add user with validation', async () => {
683
+ const userData = {username: 'test', email: 'test@example.com'};
684
+ const result = await userActions.add(userData);
685
+ expect(result).toBeDefined();
686
+ });
687
+ });
688
+ ```
689
+
690
+ #### Testing with Custom Adapters
691
+
692
+ ```typescript
693
+ const mockAdapter = jest.fn((input) => ({
694
+ ...input,
695
+ validated: true
696
+ }));
697
+
698
+ const userActions = createUserActions(flux, {
699
+ userAdapter: mockAdapter
700
+ });
701
+
702
+ expect(mockAdapter).toHaveBeenCalled();
703
+ ```
704
+
705
+ #### Testing React Components
706
+
707
+ ```typescript
708
+ import {renderHook} from '@testing-library/react';
709
+ import {Metropolis, useUserActions} from '@nlabs/metropolisjs';
710
+
711
+ describe('useUserActions', () => {
712
+ it('should return user actions', () => {
713
+ const wrapper = ({children}) => (
714
+ <Metropolis config={{development: {app: {api: {url: 'http://localhost'}}}}}>
715
+ {children}
716
+ </Metropolis>
717
+ );
718
+
719
+ const {result} = renderHook(() => useUserActions(), {wrapper});
720
+ expect(result.current).toBeDefined();
721
+ expect(result.current.add).toBeDefined();
722
+ });
723
+ });
724
+ ```
725
+
726
+ ### Best Practices
727
+
728
+ 1. **Use Specialized Hooks**: Prefer `useUserActions()` over `useMetropolis()` when you only need one action type
729
+ 2. **Selective Creation**: Use `useMetropolis(['user', 'post'])` when you need multiple specific actions
730
+ 3. **Context-Based Config**: Use `useMetropolisConfig()` for accessing configuration
731
+ 4. **Leverage Adapter Injection**: Pass custom adapters through the `Metropolis` component
732
+ 5. **Type Safety**: Always use TypeScript interfaces for better type checking
733
+ 6. **Error Handling**: Custom adapters should throw meaningful errors
734
+ 7. **Wrap Components**: Always wrap components using hooks with `<Metropolis>` provider
735
+
736
+ ### Removed APIs
174
737
 
175
- ## 📚 Available Actions
738
+ The following APIs have been removed:
176
739
 
177
- MetropolisJS provides comprehensive action classes for all your needs:
740
+ - `Config.get()` - Use `useMetropolisConfig()` in React components or `getConfigFromFlux(flux)` in non-React code
741
+ - `Config.set()` - Pass configuration to the `<Metropolis>` component instead
178
742
 
179
- - **userActions**: Authentication, profiles, user management
180
- - **messageActions**: Real-time messaging and conversations
181
- - **postActions**: Social media posts and content
182
- - **reactionActions**: Likes, reactions, and interactions
183
- - **tagActions**: Content categorization and discovery
184
- - **eventActions**: Event management and scheduling
185
- - **imageActions**: Media upload and management
186
- - **locationActions**: Geolocation and location-based features
187
- - **websocketActions**: Real-time communication setup
743
+ ### Performance Considerations
188
744
 
189
- ## 🔌 Adapters
745
+ - **Specialized hooks** only create the specific action type (best performance)
746
+ - **Selective creation** creates only requested actions
747
+ - Factory functions are lightweight and create minimal overhead
748
+ - Adapter validation is only performed when needed
749
+ - Options are merged efficiently without deep cloning
750
+ - Better tree-shaking opportunities with specialized hooks
190
751
 
191
- Customize data transformation with powerful adapters:
752
+ ## Adapters
192
753
 
193
- - **userAdapter**: User profiles and authentication data
194
- - **messageAdapter**: Chat and messaging data
195
- - **postAdapter**: Social media content
196
- - **eventAdapter**: Event and scheduling data
197
- - **imageAdapter**: Media and file data
198
- - **locationAdapter**: Geolocation data
199
- - **tagAdapter**: Categorization data
200
- - **reactionAdapter**: User interaction data
754
+ Customize data transformation with powerful adapters. Pass adapters to the `Metropolis` component:
201
755
 
202
- ## Real-Time Features
756
+ - **User**: User account and authentication data
757
+ - **Permission**: Permission and role data with RBAC support
758
+ - **Message**: Chat and messaging data
759
+ - **Post**: Social media content
760
+ - **Event**: Event and scheduling data
761
+ - **Image**: Media and file data
762
+ - **Location**: Geolocation data
763
+ - **Tag**: Categorization data
764
+ - **Reaction**: User interaction data
765
+ - **Content**: Content management
766
+ - **Persona**: Persona management
767
+ - **Translation**: Translation data
768
+
769
+ ## Real-Time Features
203
770
 
204
771
  ### WebSocket Integration
205
772
 
206
773
  ```tsx
207
- const {websocketActions} = useMetropolis();
774
+ import {useWebsocketActions} from '@nlabs/metropolisjs';
775
+
776
+ const MyComponent = () => {
777
+ const websocketActions = useWebsocketActions();
208
778
 
209
- // Initialize real-time connections
210
- websocketActions.wsInit();
779
+ useEffect(() => {
780
+ // Initialize real-time connections
781
+ websocketActions.wsInit();
782
+ }, []);
211
783
 
212
- // Messages, notifications, and data updates
213
- // are automatically synchronized across all clients
784
+ // Messages, notifications, and data updates
785
+ // are automatically synchronized across all clients
786
+ };
214
787
  ```
215
788
 
216
789
  ### Server-Sent Events
217
790
 
218
791
  Built-in SSE support for lightweight real-time updates without the overhead of WebSocket connections.
219
792
 
220
- ## 🎨 Customization
793
+ ## Customization
221
794
 
222
- ### Custom Adapters
795
+ ### Custom Data Adapters
796
+
797
+ You can customize data transformation by providing custom adapters. Adapters are functions that transform and validate data:
223
798
 
224
799
  ```tsx
225
- class CustomUserAdapter extends User {
226
- // Override methods to customize data transformation
227
- toJson() {
228
- const data = super.toJson();
229
- return {
230
- ...data,
231
- displayName: `${data.firstName} ${data.lastName}`,
232
- customField: 'custom value'
233
- };
234
- }
235
- }
800
+ // Custom adapter function
801
+ const customUserAdapter = (input: unknown, options?: UserAdapterOptions) => {
802
+ const user = input as any;
803
+
804
+ // Add custom transformation logic
805
+ return {
806
+ ...user,
807
+ displayName: `${user.firstName || ''} ${user.lastName || ''}`.trim(),
808
+ customField: 'custom value',
809
+ isVerified: user.email?.endsWith('@company.com')
810
+ };
811
+ };
236
812
 
237
- // Use custom adapter
238
- const {userActions} = useMetropolis({
239
- adapters: {
240
- User: CustomUserAdapter
241
- }
242
- });
813
+ // Pass adapters through the Metropolis component (recommended)
814
+ <Metropolis
815
+ adapters={{
816
+ User: customUserAdapter,
817
+ Message: customMessageAdapter
818
+ }}
819
+ >
820
+ <YourApp />
821
+ </Metropolis>
243
822
  ```
244
823
 
245
- ### Configuration
824
+ The adapters will be automatically used by all action hooks. For more details on the factory pattern and adapter customization, see the [Factory Pattern Guide](#-factory-pattern-guide) section above.
825
+
826
+ ### Accessing Configuration
246
827
 
247
828
  ```tsx
248
- const config = {
249
- environment: 'production',
250
- app: {
251
- session: {
252
- maxMinutes: 1440, // 24 hours
253
- minMinutes: 15
254
- }
255
- },
256
- isAuth: () => {
257
- // Custom authentication logic
258
- return true;
259
- }
829
+ import {useMetropolisConfig} from '@nlabs/metropolisjs';
830
+
831
+ const MyComponent = () => {
832
+ const config = useMetropolisConfig();
833
+ const apiUrl = config.app?.api?.url;
834
+ const websocketUrl = config.app?.urls?.websocket;
835
+
836
+ // Use configuration values
837
+ return <div>API: {apiUrl}</div>;
260
838
  };
261
839
  ```
262
840
 
263
- ## 🚀 Performance Features
841
+ **Note:** `useMetropolisConfig()` must be used within a component wrapped by `<Metropolis>`.
264
842
 
265
- - **Debounced API calls** to prevent excessive requests
266
- - **Intelligent caching** with ArkhamJS
267
- - **Optimistic updates** for instant UI feedback
268
- - **Connection pooling** for WebSocket efficiency
269
- - **Lazy loading** support for large datasets
843
+ ## Performance Features
270
844
 
271
- ## 🔒 Security
845
+ - **Selective Action Creation** - Only create actions you need with specialized hooks
846
+ - **Debounced API calls** - Prevent excessive requests
847
+ - **Intelligent caching** - With ArkhamJS
848
+ - **Optimistic updates** - Instant UI feedback
849
+ - **Connection pooling** - WebSocket efficiency
850
+ - **Lazy loading** - Support for large datasets
851
+ - **Tree-shaking friendly** - Better bundle optimization
852
+
853
+ ## Security
272
854
 
273
855
  - **Automatic token refresh** for seamless sessions
274
856
  - **Secure WebSocket connections** with authentication
275
857
  - **Input validation** and sanitization
276
858
  - **CSRF protection** built-in
277
859
  - **Session management** with configurable timeouts
860
+ - **5-Level RBAC permission system** for granular access control
861
+
862
+ ## Permission System (RBAC)
863
+
864
+ MetropolisJS includes a comprehensive 5-level Role-Based Access Control (RBAC) system that integrates seamlessly with the Reaktor backend. This system provides granular control over user permissions and access levels throughout your application.
865
+
866
+ ### Permission Levels
867
+
868
+ The system defines five hierarchical permission levels:
869
+
870
+ ```typescript
871
+ enum PermissionLevel {
872
+ GUEST = 0, // Unauthenticated users
873
+ USER = 1, // Authenticated users
874
+ MODERATOR = 2, // Content moderators
875
+ ADMIN = 3, // Application administrators
876
+ SUPER_ADMIN = 4 // System administrators
877
+ }
878
+ ```
879
+
880
+ | Level | Name | Value | Description |
881
+ |-------|------|-------|-------------|
882
+ | 0 | Guest | `PermissionLevel.GUEST` | Unauthenticated users with limited read access |
883
+ | 1 | User | `PermissionLevel.USER` | Authenticated users who can create and edit their own content |
884
+ | 2 | Moderator | `PermissionLevel.MODERATOR` | Can moderate content and manage users |
885
+ | 3 | Admin | `PermissionLevel.ADMIN` | Full access to application features |
886
+ | 4 | Super Admin | `PermissionLevel.SUPER_ADMIN` | Complete system access, can manage admins |
887
+
888
+ ### Using the Permission System
889
+
890
+ #### 1. Permission Hook
891
+
892
+ The `usePermissions()` hook provides comprehensive permission checking capabilities:
893
+
894
+ ```tsx
895
+ import { usePermissions, PermissionLevel } from '@nlabs/metropolisjs';
896
+
897
+ const MyComponent = () => {
898
+ const {
899
+ userLevel, // Current user's permission level
900
+ isGuest, // Boolean checks
901
+ isUser,
902
+ isModerator,
903
+ isAdmin,
904
+ isSuperAdmin,
905
+ hasPermission, // Function to check specific level
906
+ checkResource // Function to check resource-specific permissions
907
+ } = usePermissions();
908
+
909
+ return (
910
+ <div>
911
+ <p>Your level: {userLevel}</p>
912
+ {isAdmin && <button>Admin Panel</button>}
913
+ {hasPermission(PermissionLevel.MODERATOR) && (
914
+ <button>Moderate Content</button>
915
+ )}
916
+ </div>
917
+ );
918
+ };
919
+ ```
920
+
921
+ #### 2. Permission Guard Component
922
+
923
+ Conditionally render components based on permission requirements:
924
+
925
+ ```tsx
926
+ import { PermissionGuard, PermissionLevel } from '@nlabs/metropolisjs';
927
+
928
+ const ProtectedContent = () => {
929
+ return (
930
+ <>
931
+ <PermissionGuard
932
+ requiredLevel={PermissionLevel.USER}
933
+ fallback={<p>Please log in to view this content</p>}
934
+ >
935
+ <p>This content is visible to authenticated users</p>
936
+ </PermissionGuard>
937
+
938
+ <PermissionGuard
939
+ requiredLevel={PermissionLevel.ADMIN}
940
+ fallback={null} // Hides content completely
941
+ >
942
+ <button>Admin Settings</button>
943
+ </PermissionGuard>
944
+
945
+ <PermissionGuard
946
+ requiredLevel={PermissionLevel.MODERATOR}
947
+ resource="posts" // Resource-specific permission
948
+ fallback={<p>Moderator access required</p>}
949
+ >
950
+ <button>Moderate Posts</button>
951
+ </PermissionGuard>
952
+ </>
953
+ );
954
+ };
955
+ ```
956
+
957
+ #### 3. Managing Permissions with Actions
958
+
959
+ Use `usePermissionActions()` to manage permissions programmatically:
960
+
961
+ ```tsx
962
+ import { usePermissionActions, PermissionLevel } from '@nlabs/metropolisjs';
963
+
964
+ const PermissionManager = () => {
965
+ const permissionActions = usePermissionActions();
966
+
967
+ const grantModeratorRole = async (userId: string) => {
968
+ try {
969
+ const permission = await permissionActions.add({
970
+ userId,
971
+ name: 'Moderator Role',
972
+ level: PermissionLevel.MODERATOR,
973
+ resource: 'posts',
974
+ description: 'Can moderate posts and comments'
975
+ });
976
+ console.log('Permission granted:', permission);
977
+ } catch (error) {
978
+ console.error('Failed to grant permission:', error);
979
+ }
980
+ };
981
+
982
+ const checkUserAccess = async (userId: string) => {
983
+ const hasAccess = await permissionActions.check(
984
+ userId,
985
+ 'posts',
986
+ PermissionLevel.MODERATOR
987
+ );
988
+ return hasAccess;
989
+ };
990
+
991
+ const loadUserPermissions = async (userId: string) => {
992
+ const permissions = await permissionActions.listByUser(userId);
993
+ return permissions;
994
+ };
995
+
996
+ return (
997
+ <div>
998
+ <button onClick={() => grantModeratorRole('user123')}>
999
+ Grant Moderator Permission
1000
+ </button>
1001
+ </div>
1002
+ );
1003
+ };
1004
+ ```
1005
+
1006
+ #### 4. Resource-Specific Permissions
1007
+
1008
+ The permission system supports resource-specific access control:
1009
+
1010
+ ```tsx
1011
+ import { usePermissions, PermissionLevel } from '@nlabs/metropolisjs';
1012
+
1013
+ const ResourceProtectedComponent = () => {
1014
+ const { checkResource } = usePermissions();
1015
+
1016
+ const canEditPosts = checkResource('posts', PermissionLevel.MODERATOR);
1017
+ const canDeleteUsers = checkResource('users', PermissionLevel.ADMIN);
1018
+ const canViewReports = checkResource('reports', PermissionLevel.MODERATOR);
1019
+
1020
+ return (
1021
+ <div>
1022
+ {canEditPosts && <button>Edit Post</button>}
1023
+ {canDeleteUsers && <button>Delete User</button>}
1024
+ {canViewReports && <button>View Reports</button>}
1025
+ </div>
1026
+ );
1027
+ };
1028
+ ```
1029
+
1030
+ ### Backward Compatibility
1031
+
1032
+ The permission system is fully backward compatible with the existing `userAccess` field in the User model. The `userAccess` number (0-4) directly maps to the `PermissionLevel` enum values, ensuring seamless integration with existing code.
1033
+
1034
+ ### Available Permission Actions
1035
+
1036
+ The `usePermissionActions()` hook provides the following methods:
1037
+
1038
+ - **`add(permissionData)`** - Grant a new permission
1039
+ - **`check(userId, resource, requiredLevel)`** - Check if a user has access
1040
+ - **`itemById(permissionId)`** - Retrieve a specific permission
1041
+ - **`list(from?, to?)`** - List all permissions with pagination
1042
+ - **`listByUser(userId)`** - Get all permissions for a specific user
1043
+ - **`remove(permissionId)`** - Revoke a permission
1044
+ - **`update(permission)`** - Update an existing permission
1045
+
1046
+ ### Integration with Reaktor Backend
1047
+
1048
+ The permission system integrates with the Reaktor backend through GraphQL mutations and queries:
1049
+
1050
+ ```graphql
1051
+ # Grant permission
1052
+ mutation {
1053
+ permissions {
1054
+ add(permission: {
1055
+ userId: "user123"
1056
+ level: 2
1057
+ resource: "posts"
1058
+ name: "Moderator"
1059
+ }) {
1060
+ permissionId
1061
+ level
1062
+ resource
1063
+ }
1064
+ }
1065
+ }
1066
+
1067
+ # Check permission
1068
+ query {
1069
+ permissions {
1070
+ check(
1071
+ userId: "user123"
1072
+ resource: "posts"
1073
+ requiredLevel: 2
1074
+ )
1075
+ }
1076
+ }
1077
+
1078
+ # List user permissions
1079
+ query {
1080
+ permissions {
1081
+ listByUser(userId: "user123") {
1082
+ permissionId
1083
+ name
1084
+ level
1085
+ resource
1086
+ description
1087
+ }
1088
+ }
1089
+ }
1090
+ ```
1091
+
1092
+ ### Best Practices
1093
+
1094
+ 1. **Use Permission Guards for UI**: Wrap sensitive UI elements with `<PermissionGuard>` components
1095
+ 2. **Check Permissions in Actions**: Always verify permissions before executing sensitive operations
1096
+ 3. **Resource-Specific Permissions**: Use resource-based permissions for fine-grained control
1097
+ 4. **Leverage Boolean Helpers**: Use `isAdmin`, `isModerator`, etc. for cleaner code
1098
+ 5. **Test Permission Logic**: Write tests for permission checks to ensure security
1099
+ 6. **Document Required Levels**: Clearly document what permission level each feature requires
1100
+
1101
+ ### Example: Complete Permission Workflow
1102
+
1103
+ ```tsx
1104
+ import {
1105
+ Metropolis,
1106
+ usePermissions,
1107
+ usePermissionActions,
1108
+ PermissionGuard,
1109
+ PermissionLevel
1110
+ } from '@nlabs/metropolisjs';
1111
+
1112
+ const App = () => {
1113
+ return (
1114
+ <Metropolis config={{/* your config */}}>
1115
+ <Dashboard />
1116
+ </Metropolis>
1117
+ );
1118
+ };
1119
+
1120
+ const Dashboard = () => {
1121
+ const { isAdmin, isModerator, userLevel } = usePermissions();
1122
+ const permissionActions = usePermissionActions();
1123
+
1124
+ return (
1125
+ <div>
1126
+ <h1>Dashboard - Level: {userLevel}</h1>
1127
+
1128
+ {/* Everyone sees this */}
1129
+ <section>
1130
+ <h2>Public Content</h2>
1131
+ </section>
1132
+
1133
+ {/* Only authenticated users */}
1134
+ <PermissionGuard requiredLevel={PermissionLevel.USER}>
1135
+ <section>
1136
+ <h2>User Content</h2>
1137
+ <button>Create Post</button>
1138
+ </section>
1139
+ </PermissionGuard>
1140
+
1141
+ {/* Only moderators and above */}
1142
+ {isModerator && (
1143
+ <section>
1144
+ <h2>Moderation Tools</h2>
1145
+ <button>Review Content</button>
1146
+ </section>
1147
+ )}
1148
+
1149
+ {/* Only admins */}
1150
+ {isAdmin && (
1151
+ <section>
1152
+ <h2>Admin Panel</h2>
1153
+ <button>Manage Users</button>
1154
+ <button>System Settings</button>
1155
+ </section>
1156
+ )}
1157
+ </div>
1158
+ );
1159
+ };
1160
+ ```
1161
+
1162
+ For more detailed examples, see [`examples/permission-system-usage.tsx`](./examples/permission-system-usage.tsx).
278
1163
 
279
1164
  ## 📦 Installation & Setup
280
1165
 
@@ -296,13 +1181,15 @@ npm install --save-dev @types/react @types/node
296
1181
 
297
1182
  ### Environment Setup
298
1183
 
299
- ```bash
300
- # Set your environment variables
301
- export NODE_ENV=development
302
- export REAKTOR_API_URL=your-reaktor-backend-url
303
- ```
1184
+ MetropolisJS automatically detects the environment from:
304
1185
 
305
- ## 🤝 Contributing
1186
+ - `process.env.stage` (if set)
1187
+ - `process.env.NODE_ENV` (fallback)
1188
+ - Defaults to `'local'` if none are set
1189
+
1190
+ Configure your environment-specific settings in the `config` prop of the `Metropolis` component.
1191
+
1192
+ ## Contributing
306
1193
 
307
1194
  We love contributions! Here's how you can help:
308
1195
 
@@ -312,21 +1199,145 @@ We love contributions! Here's how you can help:
312
1199
  4. **Push** to the branch (`git push origin feature/amazing-feature`)
313
1200
  5. **Open** a Pull Request
314
1201
 
315
- ## 📄 License
1202
+ ## License
316
1203
 
317
1204
  This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
318
1205
 
319
- ## 🆘 Support
1206
+ ## Additional Documentation
1207
+
1208
+ - **[Factory Pattern Guide](./factoryPatternGuide.md)** - Detailed guide on using the factory pattern
1209
+ - **[Architecture Analysis](./ARCHITECTURE_ANALYSIS.md)** - Deep dive into the architecture
1210
+ - **[Changelog](./CHANGELOG.md)** - Complete list of changes and improvements
320
1211
 
321
- - **Documentation**: [Coming Soon]
1212
+ ## Support
1213
+
1214
+ - **Documentation**: See above for detailed guides
322
1215
  - **Issues**: [GitHub Issues](https://github.com/nitrogenlabs/metropolisjs/issues)
323
1216
  - **Discussions**: [GitHub Discussions](https://github.com/nitrogenlabs/metropolisjs/discussions)
324
1217
  - **Email**: <giraldo@nitrogenlabs.com>
325
1218
 
326
- ## 🏢 About Nitrogen Labs
1219
+ ## About Nitrogen Labs
327
1220
 
328
1221
  MetropolisJS is proudly developed by [Nitrogen Labs](http://nitrogenlabs.com), a team passionate about building powerful, developer-friendly tools that make web development faster, more reliable, and more enjoyable.
329
1222
 
330
1223
  ---
331
1224
 
332
1225
  **Ready to build the future?** Start with MetropolisJS today and experience the power of seamless frontend-backend integration! 🚀
1226
+
1227
+ ## CRUD Operations
1228
+
1229
+ MetropolisJS now provides comprehensive CRUD (Create, Read, Update, Delete) operations for all Reaktor collections:
1230
+
1231
+ ### Supported Collections
1232
+
1233
+ - **users** - User accounts and authentication data
1234
+ - **posts** - User posts and content
1235
+ - **groups** - Group entities and communities
1236
+ - **messages** - Direct messages
1237
+ - **conversations** - Conversation threads
1238
+ - **files** - File attachments
1239
+ - **images** - Image media
1240
+ - **videos** - Video media
1241
+ - **apps** - Application entities
1242
+ - **personas** - Extended user persona details
1243
+ - **tags** - Tag entities for categorization
1244
+
1245
+ ### Basic CRUD Example
1246
+
1247
+ ```tsx
1248
+ import {useFlux} from '@nlabs/arkhamjs-utils-react';
1249
+ import {createPostActions, createGroupActions} from '@nlabs/metropolisjs';
1250
+
1251
+ const MyComponent = () => {
1252
+ const flux = useFlux();
1253
+ const postActions = createPostActions(flux);
1254
+ const groupActions = createGroupActions(flux);
1255
+
1256
+ // Create
1257
+ const createPost = async () => {
1258
+ const post = await postActions.add({
1259
+ content: "Hello World",
1260
+ userId: "user123",
1261
+ name: "My First Post"
1262
+ });
1263
+ };
1264
+
1265
+ // Read
1266
+ const getPost = async (postId: string) => {
1267
+ const post = await postActions.itemById(postId);
1268
+ };
1269
+
1270
+ // Update
1271
+ const updatePost = async (postId: string) => {
1272
+ await postActions.update({
1273
+ postId,
1274
+ content: "Updated content"
1275
+ });
1276
+ };
1277
+
1278
+ // Delete
1279
+ const deletePost = async (postId: string) => {
1280
+ await postActions.delete(postId);
1281
+ };
1282
+
1283
+ // List with pagination
1284
+ const listPosts = async () => {
1285
+ const posts = await postActions.listByLatest(0, 10);
1286
+ };
1287
+ };
1288
+ ```
1289
+
1290
+ ### Relationship Management
1291
+
1292
+ Connect and manage relationships between collections:
1293
+
1294
+ ```tsx
1295
+ import {createConnectionActions, CONNECTION_TYPES} from '@nlabs/metropolisjs';
1296
+
1297
+ const connectionActions = createConnectionActions(flux);
1298
+
1299
+ // Add user to group
1300
+ await connectionActions.addConnection(
1301
+ 'users',
1302
+ userId,
1303
+ 'groups',
1304
+ groupId,
1305
+ CONNECTION_TYPES.MEMBER
1306
+ );
1307
+
1308
+ // Get all connections
1309
+ const connections = await connectionActions.getConnections('users', userId);
1310
+
1311
+ // Remove connection
1312
+ await connectionActions.removeConnection('users', userId, 'groups', groupId);
1313
+ ```
1314
+
1315
+ ### Extensible Fields
1316
+
1317
+ All CRUD operations support custom fields:
1318
+
1319
+ ```tsx
1320
+ const post = await postActions.add({
1321
+ content: "Hello",
1322
+ userId: "user123",
1323
+ // Custom fields
1324
+ customField1: "value",
1325
+ customField2: 42,
1326
+ metadata: {
1327
+ source: "mobile",
1328
+ version: "1.0"
1329
+ }
1330
+ });
1331
+ ```
1332
+
1333
+ ### Documentation
1334
+
1335
+ For comprehensive guides and examples, see:
1336
+
1337
+ - [CRUD Integration Guide](./docs/CRUD_INTEGRATION.md) - Complete guide to CRUD operations
1338
+ - [Actions Reference](./docs/ACTIONS.md) - Action families, hooks, creators, and method map
1339
+ - [Collections Reference](./docs/COLLECTIONS.md) - Detailed information about each collection
1340
+ - [Connections Guide](./docs/CONNECTIONS.md) - Managing relationships between collections
1341
+ - [CRUD Examples](./examples/crud-usage.tsx) - Practical code examples
1342
+ - [Connection Examples](./examples/connections-usage.tsx) - Relationship management examples
1343
+ - [Extensibility Examples](./examples/extensibility-usage.tsx) - Custom field examples