@nlabs/metropolisjs 0.1.2 → 0.2.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 +42 -95
  91. package/lib/actions/userActions/userActions.d.ts.map +1 -0
  92. package/lib/actions/userActions/userActions.js +844 -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
@@ -0,0 +1,415 @@
1
+ /**
2
+ * Permission System Usage Examples for MetropolisJS
3
+ *
4
+ * This file demonstrates how to use the 5-level RBAC permission system
5
+ * with various patterns and use cases.
6
+ */
7
+
8
+ import React, { useEffect } from 'react';
9
+ import {
10
+ usePermissionActions,
11
+ usePermissions,
12
+ PermissionGuard,
13
+ PermissionLevel
14
+ } from '@nlabs/metropolisjs';
15
+ import type { Permission } from '@nlabs/metropolisjs';
16
+
17
+ // =============================================================================
18
+ // Example 1: Basic Permission Level Checking
19
+ // =============================================================================
20
+
21
+ export const BasicPermissionExample = () => {
22
+ const { userLevel, isAdmin, isModerator, isUser } = usePermissions();
23
+
24
+ return (
25
+ <div>
26
+ <h2>Your Permission Level: {userLevel}</h2>
27
+ <ul>
28
+ <li>Is User: {isUser ? 'Yes' : 'No'}</li>
29
+ <li>Is Moderator: {isModerator ? 'Yes' : 'No'}</li>
30
+ <li>Is Admin: {isAdmin ? 'Yes' : 'No'}</li>
31
+ </ul>
32
+ </div>
33
+ );
34
+ };
35
+
36
+ // =============================================================================
37
+ // Example 2: Using Permission Guard Component
38
+ // =============================================================================
39
+
40
+ export const PermissionGuardExample = () => {
41
+ return (
42
+ <div>
43
+ <h1>Welcome to the App</h1>
44
+
45
+ <PermissionGuard
46
+ requiredLevel={PermissionLevel.USER}
47
+ fallback={<p>Please log in to view content</p>}
48
+ >
49
+ <p>You can see this content as a logged-in user</p>
50
+ </PermissionGuard>
51
+
52
+ <PermissionGuard
53
+ requiredLevel={PermissionLevel.MODERATOR}
54
+ fallback={<p>Moderator access required</p>}
55
+ >
56
+ <button>Moderate Content</button>
57
+ </PermissionGuard>
58
+
59
+ <PermissionGuard
60
+ requiredLevel={PermissionLevel.ADMIN}
61
+ fallback={null}
62
+ >
63
+ <button>Admin Settings</button>
64
+ </PermissionGuard>
65
+ </div>
66
+ );
67
+ };
68
+
69
+ // =============================================================================
70
+ // Example 3: Creating and Managing Permissions
71
+ // =============================================================================
72
+
73
+ export const ManagePermissionsExample = () => {
74
+ const permissionActions = usePermissionActions();
75
+ const { isAdmin } = usePermissions();
76
+
77
+ const grantUserPermission = async (userId: string) => {
78
+ if (!isAdmin) {
79
+ console.error('Only admins can grant permissions');
80
+ return;
81
+ }
82
+
83
+ try {
84
+ const permission = await permissionActions.add({
85
+ userId,
86
+ name: 'Moderator Role',
87
+ level: PermissionLevel.MODERATOR,
88
+ resource: 'posts',
89
+ description: 'Can moderate posts and comments'
90
+ });
91
+ console.log('Permission granted:', permission);
92
+ } catch (error) {
93
+ console.error('Failed to grant permission:', error);
94
+ }
95
+ };
96
+
97
+ const revokePermission = async (permissionId: string) => {
98
+ try {
99
+ await permissionActions.remove(permissionId);
100
+ console.log('Permission revoked');
101
+ } catch (error) {
102
+ console.error('Failed to revoke permission:', error);
103
+ }
104
+ };
105
+
106
+ return (
107
+ <div>
108
+ <h2>Permission Management</h2>
109
+ <button onClick={() => grantUserPermission('user123')}>
110
+ Grant Moderator Permission
111
+ </button>
112
+ </div>
113
+ );
114
+ };
115
+
116
+ // =============================================================================
117
+ // Example 4: Resource-Specific Permissions
118
+ // =============================================================================
119
+
120
+ export const ResourcePermissionsExample = () => {
121
+ const { checkResource } = usePermissions();
122
+
123
+ const canEditPosts = checkResource('posts', PermissionLevel.MODERATOR);
124
+ const canDeleteUsers = checkResource('users', PermissionLevel.ADMIN);
125
+ const canViewReports = checkResource('reports', PermissionLevel.MODERATOR);
126
+
127
+ return (
128
+ <div>
129
+ <h2>Resource Permissions</h2>
130
+ <ul>
131
+ <li>Can Edit Posts: {canEditPosts ? 'Yes' : 'No'}</li>
132
+ <li>Can Delete Users: {canDeleteUsers ? 'Yes' : 'No'}</li>
133
+ <li>Can View Reports: {canViewReports ? 'Yes' : 'No'}</li>
134
+ </ul>
135
+
136
+ <PermissionGuard
137
+ requiredLevel={PermissionLevel.MODERATOR}
138
+ resource="posts"
139
+ fallback={<p>You cannot edit posts</p>}
140
+ >
141
+ <button>Edit Post</button>
142
+ </PermissionGuard>
143
+ </div>
144
+ );
145
+ };
146
+
147
+ // =============================================================================
148
+ // Example 5: Listing User Permissions
149
+ // =============================================================================
150
+
151
+ export const UserPermissionsListExample = () => {
152
+ const permissionActions = usePermissionActions();
153
+ const [permissions, setPermissions] = React.useState<Permission[]>([]);
154
+
155
+ useEffect(() => {
156
+ const loadPermissions = async () => {
157
+ try {
158
+ const userId = 'current-user-id'; // Get from session
159
+ const userPermissions = await permissionActions.listByUser(userId);
160
+ setPermissions(userPermissions);
161
+ } catch (error) {
162
+ console.error('Failed to load permissions:', error);
163
+ }
164
+ };
165
+
166
+ loadPermissions();
167
+ }, [permissionActions]);
168
+
169
+ return (
170
+ <div>
171
+ <h2>My Permissions</h2>
172
+ <ul>
173
+ {permissions.map((permission) => (
174
+ <li key={permission.permissionId}>
175
+ <strong>{permission.name}</strong> - Level: {permission.level}
176
+ {permission.resource && ` (Resource: ${permission.resource})`}
177
+ {permission.description && <p>{permission.description}</p>}
178
+ </li>
179
+ ))}
180
+ </ul>
181
+ </div>
182
+ );
183
+ };
184
+
185
+ // =============================================================================
186
+ // Example 6: Permission Checking in API Calls
187
+ // =============================================================================
188
+
189
+ export const ProtectedAPICallExample = () => {
190
+ const { hasPermission } = usePermissions();
191
+ const permissionActions = usePermissionActions();
192
+
193
+ const deletePost = async (postId: string) => {
194
+ // Check permission before making API call
195
+ if (!hasPermission(PermissionLevel.MODERATOR)) {
196
+ alert('You do not have permission to delete posts');
197
+ return;
198
+ }
199
+
200
+ try {
201
+ // Make API call to delete post
202
+ console.log('Deleting post:', postId);
203
+ } catch (error) {
204
+ console.error('Failed to delete post:', error);
205
+ }
206
+ };
207
+
208
+ const checkUserPermission = async (userId: string, resource: string) => {
209
+ try {
210
+ const hasAccess = await permissionActions.check(
211
+ userId,
212
+ resource,
213
+ PermissionLevel.MODERATOR
214
+ );
215
+ console.log('User has access:', hasAccess);
216
+ return hasAccess;
217
+ } catch (error) {
218
+ console.error('Permission check failed:', error);
219
+ return false;
220
+ }
221
+ };
222
+
223
+ return (
224
+ <div>
225
+ <button onClick={() => deletePost('post123')}>Delete Post</button>
226
+ <button onClick={() => checkUserPermission('user123', 'posts')}>
227
+ Check User Permission
228
+ </button>
229
+ </div>
230
+ );
231
+ };
232
+
233
+ // =============================================================================
234
+ // Example 7: Permission Levels Overview
235
+ // =============================================================================
236
+
237
+ export const PermissionLevelsReference = () => {
238
+ return (
239
+ <div>
240
+ <h2>Permission Levels (RBAC)</h2>
241
+ <table>
242
+ <thead>
243
+ <tr>
244
+ <th>Level</th>
245
+ <th>Name</th>
246
+ <th>Value</th>
247
+ <th>Description</th>
248
+ </tr>
249
+ </thead>
250
+ <tbody>
251
+ <tr>
252
+ <td>0</td>
253
+ <td>Guest</td>
254
+ <td>PermissionLevel.GUEST</td>
255
+ <td>Unauthenticated users, limited read access</td>
256
+ </tr>
257
+ <tr>
258
+ <td>1</td>
259
+ <td>User</td>
260
+ <td>PermissionLevel.USER</td>
261
+ <td>Authenticated users, can create and edit own content</td>
262
+ </tr>
263
+ <tr>
264
+ <td>2</td>
265
+ <td>Moderator</td>
266
+ <td>PermissionLevel.MODERATOR</td>
267
+ <td>Can moderate content, manage users</td>
268
+ </tr>
269
+ <tr>
270
+ <td>3</td>
271
+ <td>Admin</td>
272
+ <td>PermissionLevel.ADMIN</td>
273
+ <td>Full access to application features</td>
274
+ </tr>
275
+ <tr>
276
+ <td>4</td>
277
+ <td>Super Admin</td>
278
+ <td>PermissionLevel.SUPER_ADMIN</td>
279
+ <td>Complete system access, can manage admins</td>
280
+ </tr>
281
+ </tbody>
282
+ </table>
283
+ </div>
284
+ );
285
+ };
286
+
287
+ // =============================================================================
288
+ // Example 8: Conditional Rendering Based on Permissions
289
+ // =============================================================================
290
+
291
+ export const ConditionalRenderingExample = () => {
292
+ const { userLevel, isAdmin, isModerator, isUser } = usePermissions();
293
+
294
+ return (
295
+ <div>
296
+ <h1>Dashboard</h1>
297
+
298
+ {isUser && (
299
+ <section>
300
+ <h2>My Content</h2>
301
+ <p>Create and manage your posts</p>
302
+ </section>
303
+ )}
304
+
305
+ {isModerator && (
306
+ <section>
307
+ <h2>Moderation Tools</h2>
308
+ <button>Review Flagged Content</button>
309
+ <button>Ban User</button>
310
+ </section>
311
+ )}
312
+
313
+ {isAdmin && (
314
+ <section>
315
+ <h2>Admin Panel</h2>
316
+ <button>User Management</button>
317
+ <button>System Settings</button>
318
+ <button>Analytics</button>
319
+ </section>
320
+ )}
321
+
322
+ {userLevel >= PermissionLevel.SUPER_ADMIN && (
323
+ <section>
324
+ <h2>Super Admin</h2>
325
+ <button>Manage Admins</button>
326
+ <button>System Configuration</button>
327
+ </section>
328
+ )}
329
+ </div>
330
+ );
331
+ };
332
+
333
+ // =============================================================================
334
+ // Example 9: Using with Metropolis Component
335
+ // =============================================================================
336
+
337
+ export const MetropolisConfigExample = () => {
338
+ return `
339
+ import { Metropolis, PermissionLevel } from '@nlabs/metropolisjs';
340
+
341
+ const App = () => {
342
+ return (
343
+ <Metropolis config={{
344
+ development: {
345
+ environment: 'development',
346
+ app: {
347
+ api: {
348
+ url: 'http://localhost:3000/app',
349
+ public: 'http://localhost:3000/public'
350
+ }
351
+ }
352
+ }
353
+ }}>
354
+ <YourApp />
355
+ </Metropolis>
356
+ );
357
+ };
358
+
359
+ const YourApp = () => {
360
+ const { isAdmin } = usePermissions();
361
+ const permissionActions = usePermissionActions();
362
+
363
+ // Use permissions throughout your app
364
+ return (
365
+ <div>
366
+ {isAdmin && <AdminPanel />}
367
+ <ContentArea />
368
+ </div>
369
+ );
370
+ };
371
+ `;
372
+ };
373
+
374
+ // =============================================================================
375
+ // Example 10: Testing Permissions
376
+ // =============================================================================
377
+
378
+ export const testPermissionSystem = () => {
379
+ return `
380
+ import { renderHook } from '@testing-library/react';
381
+ import { Metropolis, usePermissions, PermissionLevel } from '@nlabs/metropolisjs';
382
+
383
+ describe('Permission System', () => {
384
+ it('should check user permissions correctly', () => {
385
+ const wrapper = ({ children }) => (
386
+ <Metropolis config={{...}}>
387
+ {children}
388
+ </Metropolis>
389
+ );
390
+
391
+ const { result } = renderHook(() => usePermissions(), { wrapper });
392
+
393
+ expect(result.current.userLevel).toBe(1); // User level
394
+ expect(result.current.isUser).toBe(true);
395
+ expect(result.current.isAdmin).toBe(false);
396
+ });
397
+
398
+ it('should use PermissionGuard correctly', () => {
399
+ const { container } = render(
400
+ <Metropolis config={{...}}>
401
+ <PermissionGuard
402
+ requiredLevel={PermissionLevel.ADMIN}
403
+ fallback={<div>No access</div>}
404
+ >
405
+ <div>Admin content</div>
406
+ </PermissionGuard>
407
+ </Metropolis>
408
+ );
409
+
410
+ // Assert based on current user level
411
+ expect(container.textContent).toContain('No access');
412
+ });
413
+ });
414
+ `;
415
+ };