@nlabs/metropolisjs 0.1.1 → 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 (326) 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 +1343 -0
  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/factory-pattern-usage.ts +283 -0
  19. package/examples/i18n-import-examples.ts +86 -0
  20. package/examples/i18n-namespace-usage.ts +118 -0
  21. package/examples/i18next-singleton-demo.ts +187 -0
  22. package/examples/permission-system-usage.tsx +415 -0
  23. package/examples/project-details.tsx +397 -0
  24. package/examples/shared-i18n-usage.tsx +203 -0
  25. package/examples/signup-error-handling.ts +100 -0
  26. package/examples/translation-types.ts +86 -0
  27. package/examples/translation-usage.tsx +336 -0
  28. package/factoryPatternGuide.md +244 -0
  29. package/index.js +1 -0
  30. package/jest.config.mjs +28 -0
  31. package/lex.config.mjs +26 -0
  32. package/lib/__tests__/e2e/helpers/testGraphQLServer.d.ts +22 -0
  33. package/lib/__tests__/e2e/helpers/testGraphQLServer.d.ts.map +1 -0
  34. package/lib/__tests__/e2e/helpers/testGraphQLServer.js +197 -0
  35. package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.d.ts +3 -0
  36. package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.d.ts.map +1 -0
  37. package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.js +52 -0
  38. package/lib/actions/appActions/appActions.d.ts +29 -0
  39. package/lib/actions/appActions/appActions.d.ts.map +1 -0
  40. package/lib/actions/appActions/appActions.js +159 -0
  41. package/lib/actions/connectionActions/connectionActions.d.ts +19 -0
  42. package/lib/actions/connectionActions/connectionActions.d.ts.map +1 -0
  43. package/lib/actions/connectionActions/connectionActions.js +131 -0
  44. package/lib/actions/contentActions/contentActions.d.ts +34 -0
  45. package/lib/actions/contentActions/contentActions.d.ts.map +1 -0
  46. package/lib/actions/contentActions/contentActions.js +314 -0
  47. package/lib/actions/conversationActions/conversationActions.d.ts +30 -0
  48. package/lib/actions/conversationActions/conversationActions.d.ts.map +1 -0
  49. package/lib/actions/conversationActions/conversationActions.js +225 -0
  50. package/lib/actions/eventActions/eventActions.d.ts +65 -0
  51. package/lib/actions/eventActions/eventActions.d.ts.map +1 -0
  52. package/lib/actions/eventActions/eventActions.js +436 -0
  53. package/lib/actions/groupActions/groupActions.d.ts +30 -0
  54. package/lib/actions/groupActions/groupActions.d.ts.map +1 -0
  55. package/lib/actions/groupActions/groupActions.js +229 -0
  56. package/lib/actions/imageActions/imageActions.d.ts +62 -0
  57. package/lib/actions/imageActions/imageActions.d.ts.map +1 -0
  58. package/lib/actions/imageActions/imageActions.js +593 -0
  59. package/lib/actions/index.d.ts +21 -0
  60. package/lib/actions/index.d.ts.map +1 -0
  61. package/lib/actions/index.js +22 -0
  62. package/lib/actions/locationActions/locationActions.d.ts +60 -0
  63. package/lib/actions/locationActions/locationActions.d.ts.map +1 -0
  64. package/lib/actions/locationActions/locationActions.js +388 -0
  65. package/lib/actions/messageActions/messageActions.d.ts +38 -0
  66. package/lib/actions/messageActions/messageActions.d.ts.map +1 -0
  67. package/lib/actions/messageActions/messageActions.js +235 -0
  68. package/lib/actions/permissionActions/permissionActions.d.ts +34 -0
  69. package/lib/actions/permissionActions/permissionActions.d.ts.map +1 -0
  70. package/lib/actions/permissionActions/permissionActions.js +330 -0
  71. package/lib/actions/personaActions/personaActions.d.ts +65 -0
  72. package/lib/actions/personaActions/personaActions.d.ts.map +1 -0
  73. package/lib/actions/personaActions/personaActions.js +572 -0
  74. package/lib/actions/postActions/postActions.d.ts +36 -0
  75. package/lib/actions/postActions/postActions.d.ts.map +1 -0
  76. package/lib/actions/postActions/postActions.js +447 -0
  77. package/lib/actions/reactionActions/reactionActions.d.ts +38 -0
  78. package/lib/actions/reactionActions/reactionActions.d.ts.map +1 -0
  79. package/lib/actions/reactionActions/reactionActions.js +413 -0
  80. package/lib/actions/sseActions/sseActions.d.ts +38 -0
  81. package/lib/actions/sseActions/sseActions.d.ts.map +1 -0
  82. package/lib/actions/sseActions/sseActions.js +148 -0
  83. package/lib/actions/subscriptionActions/subscriptionActions.d.ts +24 -0
  84. package/lib/actions/subscriptionActions/subscriptionActions.d.ts.map +1 -0
  85. package/lib/actions/subscriptionActions/subscriptionActions.js +329 -0
  86. package/lib/actions/tagActions/tagActions.d.ts +37 -0
  87. package/lib/actions/tagActions/tagActions.d.ts.map +1 -0
  88. package/lib/actions/tagActions/tagActions.js +347 -0
  89. package/lib/actions/translationActions/translationActions.d.ts +38 -0
  90. package/lib/actions/translationActions/translationActions.d.ts.map +1 -0
  91. package/lib/actions/translationActions/translationActions.js +189 -0
  92. package/lib/actions/userActions/userActions.d.ts +78 -0
  93. package/lib/actions/userActions/userActions.d.ts.map +1 -0
  94. package/lib/actions/userActions/userActions.js +844 -0
  95. package/lib/actions/videoActions/videoActions.d.ts +41 -0
  96. package/lib/actions/videoActions/videoActions.d.ts.map +1 -0
  97. package/lib/actions/videoActions/videoActions.js +532 -0
  98. package/lib/actions/websocketActions/websocketActions.d.ts +30 -0
  99. package/lib/actions/websocketActions/websocketActions.d.ts.map +1 -0
  100. package/lib/actions/websocketActions/websocketActions.js +377 -0
  101. package/lib/adapters/appAdapter/appAdapter.d.ts +8 -0
  102. package/lib/adapters/appAdapter/appAdapter.d.ts.map +1 -0
  103. package/lib/adapters/appAdapter/appAdapter.js +90 -0
  104. package/lib/adapters/arangoAdapter/arangoAdapter.d.ts +21 -0
  105. package/lib/adapters/arangoAdapter/arangoAdapter.d.ts.map +1 -0
  106. package/lib/adapters/arangoAdapter/arangoAdapter.js +75 -0
  107. package/lib/adapters/contentAdapter/contentAdapter.d.ts +32 -0
  108. package/lib/adapters/contentAdapter/contentAdapter.d.ts.map +1 -0
  109. package/lib/adapters/contentAdapter/contentAdapter.js +107 -0
  110. package/lib/adapters/conversationAdapter/conversationAdapter.d.ts +24 -0
  111. package/lib/adapters/conversationAdapter/conversationAdapter.d.ts.map +1 -0
  112. package/lib/adapters/conversationAdapter/conversationAdapter.js +75 -0
  113. package/lib/adapters/eventAdapter/eventAdapter.d.ts +46 -0
  114. package/lib/adapters/eventAdapter/eventAdapter.d.ts.map +1 -0
  115. package/lib/adapters/eventAdapter/eventAdapter.js +162 -0
  116. package/lib/adapters/fileAdapter/fileAdapter.d.ts +30 -0
  117. package/lib/adapters/fileAdapter/fileAdapter.d.ts.map +1 -0
  118. package/lib/adapters/fileAdapter/fileAdapter.js +118 -0
  119. package/lib/adapters/groupAdapter/groupAdapter.d.ts +28 -0
  120. package/lib/adapters/groupAdapter/groupAdapter.d.ts.map +1 -0
  121. package/lib/adapters/groupAdapter/groupAdapter.js +66 -0
  122. package/lib/adapters/imageAdapter/imageAdapter.d.ts +38 -0
  123. package/lib/adapters/imageAdapter/imageAdapter.d.ts.map +1 -0
  124. package/lib/adapters/imageAdapter/imageAdapter.js +134 -0
  125. package/lib/adapters/index.d.ts +34 -0
  126. package/lib/adapters/index.d.ts.map +1 -0
  127. package/lib/adapters/index.js +19 -0
  128. package/lib/adapters/locationAdapter/locationAdapter.d.ts +28 -0
  129. package/lib/adapters/locationAdapter/locationAdapter.d.ts.map +1 -0
  130. package/lib/adapters/locationAdapter/locationAdapter.js +95 -0
  131. package/lib/adapters/messageAdapter/messageAdapter.d.ts +31 -0
  132. package/lib/adapters/messageAdapter/messageAdapter.d.ts.map +1 -0
  133. package/lib/adapters/messageAdapter/messageAdapter.js +82 -0
  134. package/lib/adapters/permissionAdapter/permissionAdapter.d.ts +41 -0
  135. package/lib/adapters/permissionAdapter/permissionAdapter.d.ts.map +1 -0
  136. package/lib/adapters/permissionAdapter/permissionAdapter.js +120 -0
  137. package/lib/adapters/personaAdapter/personaAdapter.d.ts +44 -0
  138. package/lib/adapters/personaAdapter/personaAdapter.d.ts.map +1 -0
  139. package/lib/adapters/personaAdapter/personaAdapter.js +161 -0
  140. package/lib/adapters/postAdapter/postAdapter.d.ts +33 -0
  141. package/lib/adapters/postAdapter/postAdapter.d.ts.map +1 -0
  142. package/lib/adapters/postAdapter/postAdapter.js +115 -0
  143. package/lib/adapters/reactionAdapter/reactionAdapter.d.ts +23 -0
  144. package/lib/adapters/reactionAdapter/reactionAdapter.d.ts.map +1 -0
  145. package/lib/adapters/reactionAdapter/reactionAdapter.js +81 -0
  146. package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts +17 -0
  147. package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts.map +1 -0
  148. package/lib/adapters/reaktorAdapter/reaktorAdapter.js +58 -0
  149. package/lib/adapters/sessionAdapter/sessionAdapter.d.ts +24 -0
  150. package/lib/adapters/sessionAdapter/sessionAdapter.d.ts.map +1 -0
  151. package/lib/adapters/sessionAdapter/sessionAdapter.js +80 -0
  152. package/lib/adapters/tagAdapter/tagAdapter.d.ts +21 -0
  153. package/lib/adapters/tagAdapter/tagAdapter.d.ts.map +1 -0
  154. package/lib/adapters/tagAdapter/tagAdapter.js +98 -0
  155. package/lib/adapters/translationAdapter/translationAdapter.d.ts +21 -0
  156. package/lib/adapters/translationAdapter/translationAdapter.d.ts.map +1 -0
  157. package/lib/adapters/translationAdapter/translationAdapter.js +55 -0
  158. package/lib/adapters/userAdapter/userAdapter.d.ts +67 -0
  159. package/lib/adapters/userAdapter/userAdapter.d.ts.map +1 -0
  160. package/lib/adapters/userAdapter/userAdapter.js +302 -0
  161. package/lib/adapters/videoAdapter/videoAdapter.d.ts +8 -0
  162. package/lib/adapters/videoAdapter/videoAdapter.d.ts.map +1 -0
  163. package/lib/adapters/videoAdapter/videoAdapter.js +194 -0
  164. package/lib/config/index.d.ts +44 -0
  165. package/lib/config/index.d.ts.map +1 -0
  166. package/lib/config/index.js +97 -0
  167. package/lib/constants/Collections.d.ts +44 -0
  168. package/lib/constants/Collections.d.ts.map +1 -0
  169. package/lib/constants/Collections.js +40 -0
  170. package/lib/constants/MetropolisConstants.d.ts +15 -0
  171. package/lib/constants/MetropolisConstants.d.ts.map +1 -0
  172. package/lib/constants/MetropolisConstants.js +15 -0
  173. package/lib/graphql/message.d.ts +3 -0
  174. package/lib/graphql/message.d.ts.map +1 -0
  175. package/lib/graphql/message.js +20 -0
  176. package/lib/graphql/notification.d.ts +3 -0
  177. package/lib/graphql/notification.d.ts.map +1 -0
  178. package/lib/graphql/notification.js +20 -0
  179. package/lib/graphql/session.d.ts +2 -0
  180. package/lib/graphql/session.d.ts.map +1 -0
  181. package/lib/graphql/session.js +17 -0
  182. package/lib/index.d.ts +52 -0
  183. package/lib/index.d.ts.map +1 -0
  184. package/lib/index.js +248 -0
  185. package/lib/stores/appStore.d.ts +23 -0
  186. package/lib/stores/appStore.d.ts.map +1 -0
  187. package/lib/stores/appStore.js +23 -0
  188. package/lib/stores/contentStore.d.ts +36 -0
  189. package/lib/stores/contentStore.d.ts.map +1 -0
  190. package/lib/stores/contentStore.js +139 -0
  191. package/lib/stores/conversationStore.d.ts +38 -0
  192. package/lib/stores/conversationStore.d.ts.map +1 -0
  193. package/lib/stores/conversationStore.js +117 -0
  194. package/lib/stores/eventStore.d.ts +37 -0
  195. package/lib/stores/eventStore.d.ts.map +1 -0
  196. package/lib/stores/eventStore.js +47 -0
  197. package/lib/stores/groupStore.d.ts +37 -0
  198. package/lib/stores/groupStore.d.ts.map +1 -0
  199. package/lib/stores/groupStore.js +68 -0
  200. package/lib/stores/imageStore.d.ts +40 -0
  201. package/lib/stores/imageStore.d.ts.map +1 -0
  202. package/lib/stores/imageStore.js +53 -0
  203. package/lib/stores/index.d.ts +24 -0
  204. package/lib/stores/index.d.ts.map +1 -0
  205. package/lib/stores/index.js +24 -0
  206. package/lib/stores/locationStore.d.ts +34 -0
  207. package/lib/stores/locationStore.d.ts.map +1 -0
  208. package/lib/stores/locationStore.js +42 -0
  209. package/lib/stores/messageStore.d.ts +51 -0
  210. package/lib/stores/messageStore.d.ts.map +1 -0
  211. package/lib/stores/messageStore.js +137 -0
  212. package/lib/stores/notificationStore.d.ts +33 -0
  213. package/lib/stores/notificationStore.d.ts.map +1 -0
  214. package/lib/stores/notificationStore.js +55 -0
  215. package/lib/stores/permissionStore.d.ts +37 -0
  216. package/lib/stores/permissionStore.d.ts.map +1 -0
  217. package/lib/stores/permissionStore.js +117 -0
  218. package/lib/stores/personaStore.d.ts +26 -0
  219. package/lib/stores/personaStore.d.ts.map +1 -0
  220. package/lib/stores/personaStore.js +118 -0
  221. package/lib/stores/postStore.d.ts +34 -0
  222. package/lib/stores/postStore.d.ts.map +1 -0
  223. package/lib/stores/postStore.js +53 -0
  224. package/lib/stores/reactionStore.d.ts +25 -0
  225. package/lib/stores/reactionStore.d.ts.map +1 -0
  226. package/lib/stores/reactionStore.js +28 -0
  227. package/lib/stores/subscriptionStore.d.ts +41 -0
  228. package/lib/stores/subscriptionStore.d.ts.map +1 -0
  229. package/lib/stores/subscriptionStore.js +85 -0
  230. package/lib/stores/tagStore.d.ts +34 -0
  231. package/lib/stores/tagStore.d.ts.map +1 -0
  232. package/lib/stores/tagStore.js +87 -0
  233. package/lib/stores/translationStore.d.ts +42 -0
  234. package/lib/stores/translationStore.d.ts.map +1 -0
  235. package/lib/stores/translationStore.js +122 -0
  236. package/lib/stores/userStore.d.ts +74 -0
  237. package/lib/stores/userStore.d.ts.map +1 -0
  238. package/lib/stores/userStore.js +319 -0
  239. package/lib/stores/videoStore.d.ts +39 -0
  240. package/lib/stores/videoStore.d.ts.map +1 -0
  241. package/lib/stores/videoStore.js +132 -0
  242. package/lib/stores/websocketStore.d.ts +24 -0
  243. package/lib/stores/websocketStore.d.ts.map +1 -0
  244. package/lib/stores/websocketStore.js +51 -0
  245. package/lib/types/apps.types.d.ts +17 -0
  246. package/lib/types/apps.types.d.ts.map +1 -0
  247. package/lib/types/apps.types.js +6 -0
  248. package/lib/types/common.types.d.ts +31 -0
  249. package/lib/types/common.types.d.ts.map +1 -0
  250. package/lib/types/common.types.js +6 -0
  251. package/lib/types/conversations.types.d.ts +17 -0
  252. package/lib/types/conversations.types.d.ts.map +1 -0
  253. package/lib/types/conversations.types.js +6 -0
  254. package/lib/types/edges.types.d.ts +38 -0
  255. package/lib/types/edges.types.d.ts.map +1 -0
  256. package/lib/types/edges.types.js +6 -0
  257. package/lib/types/groups.types.d.ts +19 -0
  258. package/lib/types/groups.types.d.ts.map +1 -0
  259. package/lib/types/groups.types.js +6 -0
  260. package/lib/types/index.d.ts +12 -0
  261. package/lib/types/index.d.ts.map +1 -0
  262. package/lib/types/index.js +12 -0
  263. package/lib/types/subscriptions.types.d.ts +32 -0
  264. package/lib/types/subscriptions.types.d.ts.map +1 -0
  265. package/lib/types/subscriptions.types.js +6 -0
  266. package/lib/types/videos.types.d.ts +61 -0
  267. package/lib/types/videos.types.d.ts.map +1 -0
  268. package/lib/types/videos.types.js +6 -0
  269. package/lib/utils/MetropolisProvider.d.ts +58 -0
  270. package/lib/utils/MetropolisProvider.d.ts.map +1 -0
  271. package/lib/utils/MetropolisProvider.js +31 -0
  272. package/lib/utils/actionFactory.d.ts +24 -0
  273. package/lib/utils/actionFactory.d.ts.map +1 -0
  274. package/lib/utils/actionFactory.js +95 -0
  275. package/lib/utils/api.d.ts +44 -0
  276. package/lib/utils/api.d.ts.map +1 -0
  277. package/lib/utils/api.js +253 -0
  278. package/lib/utils/app.d.ts +7 -0
  279. package/lib/utils/app.d.ts.map +1 -0
  280. package/lib/utils/app.js +15 -0
  281. package/lib/utils/baseActionFactory.d.ts +16 -0
  282. package/lib/utils/baseActionFactory.d.ts.map +1 -0
  283. package/lib/utils/baseActionFactory.js +72 -0
  284. package/lib/utils/configUtils.d.ts +11 -0
  285. package/lib/utils/configUtils.d.ts.map +1 -0
  286. package/lib/utils/configUtils.js +20 -0
  287. package/lib/utils/dateUtils.d.ts +3 -0
  288. package/lib/utils/dateUtils.d.ts.map +1 -0
  289. package/lib/utils/dateUtils.js +11 -0
  290. package/lib/utils/file.d.ts +3 -0
  291. package/lib/utils/file.d.ts.map +1 -0
  292. package/lib/utils/file.js +156 -0
  293. package/lib/utils/i18n.d.ts +7 -0
  294. package/lib/utils/i18n.d.ts.map +1 -0
  295. package/lib/utils/i18n.js +96 -0
  296. package/lib/utils/index.d.ts +20 -0
  297. package/lib/utils/index.d.ts.map +1 -0
  298. package/lib/utils/index.js +26 -0
  299. package/lib/utils/location.d.ts +10 -0
  300. package/lib/utils/location.d.ts.map +1 -0
  301. package/lib/utils/location.js +82 -0
  302. package/lib/utils/permissionUtils.d.ts +22 -0
  303. package/lib/utils/permissionUtils.d.ts.map +1 -0
  304. package/lib/utils/permissionUtils.js +72 -0
  305. package/lib/utils/requestCache.d.ts +8 -0
  306. package/lib/utils/requestCache.d.ts.map +1 -0
  307. package/lib/utils/requestCache.js +53 -0
  308. package/lib/utils/session.d.ts +14 -0
  309. package/lib/utils/session.d.ts.map +1 -0
  310. package/lib/utils/session.js +107 -0
  311. package/lib/utils/useConversationTyping.d.ts +26 -0
  312. package/lib/utils/useConversationTyping.d.ts.map +1 -0
  313. package/lib/utils/useConversationTyping.js +117 -0
  314. package/lib/utils/useMetropolis.d.ts +67 -0
  315. package/lib/utils/useMetropolis.d.ts.map +1 -0
  316. package/lib/utils/useMetropolis.js +311 -0
  317. package/lib/utils/useTranslations.d.ts +16 -0
  318. package/lib/utils/useTranslations.d.ts.map +1 -0
  319. package/lib/utils/useTranslations.js +105 -0
  320. package/lib/utils/validatorFactory.d.ts +49 -0
  321. package/lib/utils/validatorFactory.d.ts.map +1 -0
  322. package/lib/utils/validatorFactory.js +95 -0
  323. package/package.json +75 -28
  324. package/temp_signin.ts +73 -0
  325. package/tsconfig.lint.json +25 -0
  326. package/tsconfig.test.json +14 -0
@@ -0,0 +1,283 @@
1
+ /**
2
+ * Example: Using the Factory Pattern in MetropolisJS
3
+ *
4
+ * This file demonstrates how to use the new consolidated action factory
5
+ * instead of individual createXxxActions functions.
6
+ */
7
+
8
+ import type { FluxFramework } from '@nlabs/arkhamjs';
9
+ import { createAction, createActions, createAllActions } from '../src/utils/actionFactory';
10
+
11
+ // Example 1: Basic Usage
12
+ export const basicUsage = (flux: FluxFramework) => {
13
+ // Create actions using consolidated factory functions
14
+ const userActions = createAction('user', flux) as any;
15
+ const postActions = createAction('post', flux) as any;
16
+ const eventActions = createAction('event', flux) as any;
17
+
18
+ // Use actions normally
19
+ const addUser = async () => {
20
+ const user = await userActions.add({
21
+ username: 'john_doe',
22
+ email: 'john@example.com',
23
+ firstName: 'John',
24
+ lastName: 'Doe'
25
+ });
26
+ return user;
27
+ };
28
+
29
+ const createPost = async () => {
30
+ const post = await postActions.add({
31
+ content: 'Hello, world!',
32
+ name: 'My First Post'
33
+ });
34
+ return post;
35
+ };
36
+
37
+ return {addUser, createPost};
38
+ };
39
+
40
+ // Example 2: Custom Adapter with Business Logic
41
+ export const customAdapterUsage = (flux: FluxFramework) => {
42
+ // Custom user adapter that adds business logic
43
+ const businessUserAdapter = (input: unknown, options?: any) => {
44
+ const user = input as any;
45
+
46
+ // Business validation
47
+ if (user.email && !user.email.includes('@company.com')) {
48
+ throw new Error('Only company emails are allowed');
49
+ }
50
+
51
+ // Add computed fields
52
+ return {
53
+ ...user,
54
+ fullName: `${user.firstName || ''} ${user.lastName || ''}`.trim(),
55
+ isAdmin: user.userAccess >= 3,
56
+ department: user.email?.split('@')[0]?.split('.')[1] || 'general'
57
+ };
58
+ };
59
+
60
+ // Create actions with custom adapter
61
+ const userActions = createAction('user', flux, {
62
+ userAdapter: businessUserAdapter,
63
+ userAdapterOptions: {
64
+ strict: true,
65
+ environment: 'production'
66
+ }
67
+ });
68
+
69
+ return userActions;
70
+ };
71
+
72
+ // Example 3: Runtime Adapter Updates
73
+ export const runtimeUpdates = (flux: FluxFramework) => {
74
+ const userActions = createAction('user', flux) as any;
75
+
76
+ // Update adapter at runtime
77
+ const updateToStrictMode = () => {
78
+ userActions.updateUserAdapterOptions({
79
+ strict: true,
80
+ environment: 'production'
81
+ });
82
+ };
83
+
84
+ // Add custom validation at runtime
85
+ const addCustomValidation = () => {
86
+ userActions.updateUserAdapter((input, options) => {
87
+ const user = input as any;
88
+
89
+ // Additional runtime validation
90
+ if (user.age && user.age < 18) {
91
+ throw new Error('User must be 18 or older');
92
+ }
93
+
94
+ return user;
95
+ });
96
+ };
97
+
98
+ return {updateToStrictMode, addCustomValidation, userActions};
99
+ };
100
+
101
+ // Example 4: Testing with Mock Adapters
102
+ export const testingExample = (flux: FluxFramework) => {
103
+ // Mock adapter for testing
104
+ const mockUserAdapter = jest.fn((input: unknown) => ({
105
+ ...(input as Record<string, unknown>),
106
+ id: 'mock-user-id',
107
+ validated: true,
108
+ timestamp: new Date().toISOString()
109
+ }));
110
+
111
+ const userActions = createAction('user', flux, {
112
+ userAdapter: mockUserAdapter
113
+ }) as any;
114
+
115
+ // Test that adapter was called
116
+ const testUserCreation = async () => {
117
+ const user = await userActions.add({
118
+ username: 'test_user',
119
+ email: 'test@example.com'
120
+ });
121
+
122
+ expect(mockUserAdapter).toHaveBeenCalled();
123
+ expect(user.id).toBe('mock-user-id');
124
+ expect(user.validated).toBe(true);
125
+ };
126
+
127
+ return {userActions, testUserCreation};
128
+ };
129
+
130
+ // Example 5: Multiple Adapters with Different Configurations
131
+ export const multipleAdapters = (flux: FluxFramework) => {
132
+ // User adapter with strict validation
133
+ const strictUserAdapter = (input: unknown) => {
134
+ const user = input as any;
135
+ if (!user.username || !user.email) {
136
+ throw new Error('Username and email are required');
137
+ }
138
+ return user;
139
+ };
140
+
141
+ // Post adapter with content validation
142
+ const contentPostAdapter = (input: unknown) => {
143
+ const post = input as any;
144
+ if (post.content && post.content.length > 1000) {
145
+ throw new Error('Post content too long');
146
+ }
147
+ return post;
148
+ };
149
+
150
+ // Create actions with different adapters
151
+ const userActions = createAction('user', flux, {
152
+ userAdapter: strictUserAdapter,
153
+ userAdapterOptions: {strict: true}
154
+ }) as any;
155
+
156
+ const postActions = createAction('post', flux, {
157
+ postAdapter: contentPostAdapter,
158
+ postAdapterOptions: {environment: 'development'}
159
+ }) as any;
160
+
161
+ return {userActions, postActions};
162
+ };
163
+
164
+ // Example 6: Error Handling
165
+ export const errorHandling = (flux: FluxFramework) => {
166
+ const userActions = createAction('user', flux, {
167
+ userAdapterOptions: {
168
+ strict: true,
169
+ customValidation: (input) => {
170
+ const user = input as any;
171
+
172
+ // Custom error handling
173
+ if (user.username && user.username.length < 3) {
174
+ throw new Error('Username must be at least 3 characters');
175
+ }
176
+
177
+ if (user.email && !user.email.includes('@')) {
178
+ throw new Error('Invalid email format');
179
+ }
180
+
181
+ return user;
182
+ }
183
+ }
184
+ }) as any;
185
+
186
+ const createUserWithErrorHandling = async (userData: any) => {
187
+ try {
188
+ const user = await userActions.add(userData);
189
+ return {success: true, user};
190
+ } catch (error) {
191
+ return {success: false, error: error.message};
192
+ }
193
+ };
194
+
195
+ return {createUserWithErrorHandling};
196
+ };
197
+
198
+ // Example 7: Multiple Actions Creation
199
+ export const multipleActionsExample = (flux: FluxFramework) => {
200
+ // Create multiple actions at once
201
+ const actions = createActions(['user', 'post', 'message'], flux, {
202
+ user: {
203
+ userAdapterOptions: { strict: true }
204
+ },
205
+ post: {
206
+ postAdapter: (input: any) => {
207
+ if (input.content && input.content.length > 1000) {
208
+ throw new Error('Post content too long');
209
+ }
210
+ return input;
211
+ }
212
+ }
213
+ });
214
+
215
+ const createUserAndPost = async (userData: any, postData: any) => {
216
+ const user = await actions.user.add(userData);
217
+ const post = await actions.post.add({
218
+ ...postData,
219
+ userId: user.userId
220
+ });
221
+ return { user, post };
222
+ };
223
+
224
+ return { actions, createUserAndPost };
225
+ };
226
+
227
+ // Example 8: All Actions Creation
228
+ export const allActionsExample = (flux: FluxFramework) => {
229
+ // Create all available actions
230
+ const allActions = createAllActions(flux, {
231
+ user: { userAdapterOptions: { strict: true } },
232
+ post: { postAdapterOptions: { environment: 'production' } },
233
+ image: { imageAdapterOptions: { allowPartial: true } }
234
+ });
235
+
236
+ const comprehensiveWorkflow = async () => {
237
+ // Create user
238
+ const user = await allActions.user.add({
239
+ username: 'jane_doe',
240
+ email: 'jane@example.com'
241
+ });
242
+
243
+ // Create post
244
+ const post = await allActions.post.add({
245
+ content: 'Hello world!',
246
+ name: 'My Post'
247
+ });
248
+
249
+ // Upload image
250
+ const image = await allActions.image.add({
251
+ base64: 'data:image/jpeg;base64,...',
252
+ description: 'Profile picture'
253
+ });
254
+
255
+ // Send message
256
+ await allActions.message.sendMessage({
257
+ content: 'Welcome!',
258
+ recipientId: user.userId
259
+ });
260
+
261
+ return { user, post, image };
262
+ };
263
+
264
+ return { allActions, comprehensiveWorkflow };
265
+ };
266
+
267
+ // Example 9: Migration from Old Pattern
268
+ export const migrationExample = (flux: FluxFramework) => {
269
+ // New way (recommended)
270
+ const userActions = createAction('user', flux) as any;
271
+ const postActions = createAction('post', flux) as any;
272
+ const eventActions = createAction('event', flux) as any;
273
+
274
+ const createUser = async (userData: any) => {
275
+ return await userActions.add(userData);
276
+ };
277
+
278
+ const createPost = async (postData: any) => {
279
+ return await postActions.add(postData);
280
+ };
281
+
282
+ return { createUser, createPost };
283
+ };
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Copyright (c) 2025-Present, Nitrogen Labs, Inc.
3
+ * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4
+ */
5
+
6
+ // This file demonstrates different ways to import i18next functions
7
+ // for consistency across MetropolisJS and GothamJS
8
+
9
+ // Method 1: Direct import (original i18next way)
10
+ import { t } from 'i18next';
11
+
12
+ // Method 2: Aliased import for consistency (recommended)
13
+ import { t as i18n } from 'i18next';
14
+
15
+ // Method 3: Multiple imports with aliases
16
+ import { t as translate } from 'i18next';
17
+
18
+ // Example usage showing the difference:
19
+
20
+ // Using the original 't' function
21
+ const originalWay = () => {
22
+ const welcome = t('welcome');
23
+ const greeting = t('hello_user', {name: 'John'});
24
+ return {welcome, greeting};
25
+ };
26
+
27
+ // Using the aliased 'i18n' function (same as MetropolisJS)
28
+ const consistentWay = () => {
29
+ const welcome = i18n('welcome');
30
+ const greeting = i18n('hello_user', {name: 'John'});
31
+ return {welcome, greeting};
32
+ };
33
+
34
+ // Using the 'translate' alias
35
+ const alternativeWay = () => {
36
+ const welcome = translate('welcome');
37
+ const greeting = translate('hello_user', {name: 'John'});
38
+ return {welcome, greeting};
39
+ };
40
+
41
+ // Real-world example: GothamJS component
42
+ const GothamJSComponent = () => {
43
+ // In GothamJS, you would use:
44
+ // import {t as i18n} from 'i18next';
45
+
46
+ // This gives you the same function name as MetropolisJS
47
+ const title = i18n('gotham_title');
48
+ const description = i18n('gotham_description');
49
+ const buttonText = i18n('gotham_button');
50
+
51
+ return {
52
+ title,
53
+ description,
54
+ buttonText
55
+ };
56
+ };
57
+
58
+ // MetropolisJS component (for comparison)
59
+ const MetropolisJSComponent = () => {
60
+ // In MetropolisJS, you would use:
61
+ // import {i18n} from './utils/i18n';
62
+ // (which internally uses i18next)
63
+
64
+ const title = i18n('metropolis_title');
65
+ const description = i18n('metropolis_description');
66
+ const buttonText = i18n('metropolis_button');
67
+
68
+ return {
69
+ title,
70
+ description,
71
+ buttonText
72
+ };
73
+ };
74
+
75
+ // Benefits of using {t as i18n}:
76
+ const benefits = {
77
+ consistency: 'Same function name across libraries',
78
+ familiarity: 'Developers know what i18n() does',
79
+ maintainability: 'Easier to switch between libraries',
80
+ clarity: 'Clear that it\'s for internationalization'
81
+ };
82
+
83
+ export {
84
+ alternativeWay, benefits, consistentWay, GothamJSComponent,
85
+ MetropolisJSComponent, originalWay
86
+ };
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Copyright (c) 2025-Present, Nitrogen Labs, Inc.
3
+ * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4
+ */
5
+ import { i18n, initI18n, updateI18nResources } from '../src/utils/i18n';
6
+
7
+ const translations = {
8
+ 'welcome:en': {
9
+ key: 'welcome',
10
+ locale: 'en',
11
+ value: 'Welcome {{name}}!',
12
+ namespace: 'common'
13
+ },
14
+ 'save:en': {
15
+ key: 'save',
16
+ locale: 'en',
17
+ value: 'Save',
18
+ namespace: 'buttons'
19
+ },
20
+ 'cancel:en': {
21
+ key: 'cancel',
22
+ locale: 'en',
23
+ value: 'Cancel',
24
+ namespace: 'buttons'
25
+ },
26
+ 'login:en': {
27
+ key: 'login',
28
+ locale: 'en',
29
+ value: 'Login to your account',
30
+ namespace: 'auth'
31
+ },
32
+ 'welcome:es': {
33
+ key: 'welcome',
34
+ locale: 'es',
35
+ value: '”Bienvenido {{name}}!',
36
+ namespace: 'common'
37
+ },
38
+ 'save:es': {
39
+ key: 'save',
40
+ locale: 'es',
41
+ value: 'Guardar',
42
+ namespace: 'buttons'
43
+ }
44
+ };
45
+
46
+ const initializeTranslations = () => {
47
+ initI18n(translations);
48
+ console.log('i18n initialized with namespaces');
49
+ };
50
+
51
+ const demonstrateNamespaceUsage = () => {
52
+ console.log('\n=== Namespace Usage Examples ===');
53
+
54
+ console.log('Default namespace (translations):');
55
+ console.log(i18n('welcome', {name: 'World'}));
56
+ console.log(i18n('welcome', {name: 'World'}, 'en'));
57
+
58
+ console.log('\nCommon namespace:');
59
+ console.log(i18n('welcome', {name: 'World'}, 'en', 'common'));
60
+ console.log(i18n('welcome', {name: 'Mundo'}, 'es', 'common'));
61
+
62
+ console.log('\nButtons namespace:');
63
+ console.log(i18n('save', {}, 'en', 'buttons'));
64
+ console.log(i18n('cancel', {}, 'en', 'buttons'));
65
+ console.log(i18n('save', {}, 'es', 'buttons'));
66
+
67
+ console.log('\nAuth namespace:');
68
+ console.log(i18n('login', {}, 'en', 'auth'));
69
+ };
70
+
71
+ const demonstrateDynamicUpdates = () => {
72
+ console.log('\n=== Dynamic Updates ===');
73
+
74
+ const newTranslations = {
75
+ 'delete:en': {
76
+ key: 'delete',
77
+ locale: 'en',
78
+ value: 'Delete',
79
+ namespace: 'buttons'
80
+ },
81
+ 'edit:en': {
82
+ key: 'edit',
83
+ locale: 'en',
84
+ value: 'Edit {{item}}',
85
+ namespace: 'actions'
86
+ }
87
+ };
88
+
89
+ updateI18nResources(newTranslations);
90
+
91
+ console.log('New button translation:');
92
+ console.log(i18n('delete', {}, 'en', 'buttons'));
93
+
94
+ console.log('New action translation:');
95
+ console.log(i18n('edit', {item: 'profile'}, 'en', 'actions'));
96
+ };
97
+
98
+ const demonstrateFallbacks = () => {
99
+ console.log('\n=== Fallback Behavior ===');
100
+
101
+ console.log('Missing key (returns key):');
102
+ console.log(i18n('missing-key', {}, 'en', 'common'));
103
+
104
+ console.log('Missing namespace (uses default):');
105
+ console.log(i18n('welcome', {name: 'World'}, 'en', 'missing-ns'));
106
+
107
+ console.log('Missing language (uses fallback):');
108
+ console.log(i18n('welcome', {name: 'World'}, 'fr', 'common'));
109
+ };
110
+
111
+ const runExamples = () => {
112
+ initializeTranslations();
113
+ demonstrateNamespaceUsage();
114
+ demonstrateDynamicUpdates();
115
+ demonstrateFallbacks();
116
+ };
117
+
118
+ export { demonstrateNamespaceUsage, initializeTranslations, runExamples };
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Copyright (c) 2025-Present, Nitrogen Labs, Inc.
3
+ * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4
+ */
5
+
6
+ // This file demonstrates how i18next works as a singleton
7
+ // and how GothamJS can share the same instance as MetropolisJS
8
+
9
+ import { changeLanguage, init, t } from 'i18next';
10
+
11
+ // Step 1: MetropolisJS initializes i18next (this happens in Metropolis component)
12
+ const initializeMetropolisI18n = () => {
13
+ console.log('šŸ”µ MetropolisJS: Initializing i18next...');
14
+
15
+ init({
16
+ resources: {
17
+ en: {
18
+ translations: {
19
+ 'welcome': 'Welcome to MetropolisJS!',
20
+ 'save': 'Save',
21
+ 'cancel': 'Cancel',
22
+ 'shared_text': 'This text is shared between libraries',
23
+ 'hello_user': 'Hello {{name}}!'
24
+ }
25
+ },
26
+ es: {
27
+ translations: {
28
+ 'welcome': '”Bienvenido a MetropolisJS!',
29
+ 'save': 'Guardar',
30
+ 'cancel': 'Cancelar',
31
+ 'shared_text': 'Este texto se comparte entre bibliotecas',
32
+ 'hello_user': '”Hola {{name}}!'
33
+ }
34
+ }
35
+ },
36
+ lng: 'en',
37
+ fallbackLng: 'en',
38
+ interpolation: {
39
+ escapeValue: false
40
+ }
41
+ });
42
+
43
+ console.log('šŸ”µ MetropolisJS: i18next initialized successfully');
44
+ };
45
+
46
+ // Step 2: GothamJS can use the same i18next instance
47
+ const gothamJSComponent = () => {
48
+ console.log('🟢 GothamJS: Using the same i18next instance');
49
+
50
+ // GothamJS can import {t as i18n} from 'i18next' for consistency
51
+ // This gives the same function name as MetropolisJS uses
52
+ // import {t as i18n} from 'i18next';
53
+
54
+ const gothamTitle = t('gotham_title', 'GothamJS Component'); // with fallback
55
+ const sharedText = t('shared_text'); // uses the same translation
56
+ const helloUser = t('hello_user', {name: 'Gotham User'}); // with interpolation
57
+
58
+ console.log('🟢 GothamJS translations:', {
59
+ gothamTitle,
60
+ sharedText,
61
+ helloUser
62
+ });
63
+
64
+ return {
65
+ title: gothamTitle,
66
+ description: sharedText,
67
+ greeting: helloUser
68
+ };
69
+ };
70
+
71
+ // Step 3: Demonstrate language switching affects both libraries
72
+ const demonstrateLanguageSwitching = async () => {
73
+ console.log('\nšŸŒ Demonstrating language switching...');
74
+
75
+ // Both MetropolisJS and GothamJS will see this change
76
+ await changeLanguage('es');
77
+
78
+ console.log('šŸ”„ Language changed to Spanish');
79
+
80
+ // MetropolisJS component
81
+ const metropolisText = t('welcome');
82
+ console.log('šŸ”µ MetropolisJS (Spanish):', metropolisText);
83
+
84
+ // GothamJS component - automatically uses Spanish now
85
+ const gothamText = t('shared_text');
86
+ console.log('🟢 GothamJS (Spanish):', gothamText);
87
+
88
+ // Switch back to English
89
+ await changeLanguage('en');
90
+ console.log('šŸ”„ Language changed back to English');
91
+
92
+ console.log('šŸ”µ MetropolisJS (English):', t('welcome'));
93
+ console.log('🟢 GothamJS (English):', t('shared_text'));
94
+ };
95
+
96
+ // Step 4: Show how namespaces work across libraries
97
+ const demonstrateNamespaces = () => {
98
+ console.log('\nšŸ“š Demonstrating namespaces...');
99
+
100
+ // MetropolisJS might use 'metropolis' namespace
101
+ const metropolisText = t('dashboard_title', {ns: 'metropolis'});
102
+
103
+ // GothamJS might use 'gotham' namespace
104
+ const gothamText = t('widget_title', {ns: 'gotham'});
105
+
106
+ // Both can use 'common' namespace for shared translations
107
+ const commonText = t('shared_button', {ns: 'common'});
108
+
109
+ console.log('šŸ”µ MetropolisJS namespace:', metropolisText);
110
+ console.log('🟢 GothamJS namespace:', gothamText);
111
+ console.log('🟔 Common namespace:', commonText);
112
+ };
113
+
114
+ // Step 5: Real-world usage example
115
+ const realWorldExample = () => {
116
+ console.log('\nšŸ—ļø Real-world usage example:');
117
+
118
+ // In a real React app:
119
+
120
+ // MetropolisJS component
121
+ const MetropolisComponent = () => {
122
+ // This would be in a MetropolisJS component
123
+ const title = t('dashboard_title');
124
+ const saveButton = t('save');
125
+
126
+ console.log('šŸ”µ MetropolisJS component:', {title, saveButton});
127
+
128
+ return {title, saveButton};
129
+ };
130
+
131
+ // GothamJS component
132
+ const GothamComponent = () => {
133
+ // This would be in a GothamJS component
134
+ // import {t} from 'i18next'; // Same i18next instance!
135
+
136
+ const widgetTitle = t('widget_title');
137
+ const sharedButton = t('shared_button');
138
+
139
+ console.log('🟢 GothamJS component:', {widgetTitle, sharedButton});
140
+
141
+ return {widgetTitle, sharedButton};
142
+ };
143
+
144
+ const metropolis = MetropolisComponent();
145
+ const gotham = GothamComponent();
146
+
147
+ console.log('āœ… Both components use the same i18next instance!');
148
+ console.log('āœ… Language changes affect both components!');
149
+ console.log('āœ… Namespaces keep translations organized!');
150
+
151
+ return {metropolis, gotham};
152
+ };
153
+
154
+ // Run the demonstration
155
+ const runDemo = () => {
156
+ console.log('šŸš€ i18next Singleton Demonstration');
157
+ console.log('=====================================\n');
158
+
159
+ // Initialize i18next (MetropolisJS does this)
160
+ initializeMetropolisI18n();
161
+
162
+ // GothamJS uses the same instance
163
+ const gothamResult = gothamJSComponent();
164
+
165
+ // Demonstrate language switching
166
+ demonstrateLanguageSwitching();
167
+
168
+ // Demonstrate namespaces
169
+ demonstrateNamespaces();
170
+
171
+ // Real-world example
172
+ const realWorld = realWorldExample();
173
+
174
+ console.log('\nāœ… Demonstration complete!');
175
+ console.log('āœ… GothamJS can fully share i18next with MetropolisJS');
176
+ console.log('āœ… Both libraries benefit from the same translation system');
177
+
178
+ return {
179
+ gothamResult,
180
+ realWorld
181
+ };
182
+ };
183
+
184
+ export {
185
+ demonstrateLanguageSwitching,
186
+ demonstrateNamespaces, gothamJSComponent, initializeMetropolisI18n, realWorldExample, runDemo
187
+ };