@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.
- package/.github/copilot-instructions.md +167 -0
- package/AGENTS.md +13 -0
- package/CHANGELOG.md +112 -0
- package/GRAPHQL_VALIDATION_RESULTS.md +158 -0
- package/PERMISSION_GRAPHQL_INTEGRATION.md +293 -0
- package/PERMISSION_IMPLEMENTATION_SUMMARY.md +243 -0
- package/README.md +1343 -0
- package/SIGNIN_GRAPHQL_VALIDATION.md +125 -0
- package/VAULT_GRAPHQL_API_FINDINGS.md +312 -0
- package/docs/ACTIONS.md +63 -0
- package/docs/COLLECTIONS.md +1038 -0
- package/docs/CONNECTIONS.md +1367 -0
- package/docs/CRUD_INTEGRATION.md +702 -0
- package/examples/connections-usage.tsx +909 -0
- package/examples/content-actions-usage.ts +144 -0
- package/examples/crud-usage.tsx +847 -0
- package/examples/extensibility-usage.tsx +889 -0
- package/examples/factory-pattern-usage.ts +283 -0
- package/examples/i18n-import-examples.ts +86 -0
- package/examples/i18n-namespace-usage.ts +118 -0
- package/examples/i18next-singleton-demo.ts +187 -0
- package/examples/permission-system-usage.tsx +415 -0
- package/examples/project-details.tsx +397 -0
- package/examples/shared-i18n-usage.tsx +203 -0
- package/examples/signup-error-handling.ts +100 -0
- package/examples/translation-types.ts +86 -0
- package/examples/translation-usage.tsx +336 -0
- package/factoryPatternGuide.md +244 -0
- package/index.js +1 -0
- package/jest.config.mjs +28 -0
- package/lex.config.mjs +26 -0
- package/lib/__tests__/e2e/helpers/testGraphQLServer.d.ts +22 -0
- package/lib/__tests__/e2e/helpers/testGraphQLServer.d.ts.map +1 -0
- package/lib/__tests__/e2e/helpers/testGraphQLServer.js +197 -0
- package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.d.ts +3 -0
- package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.d.ts.map +1 -0
- package/lib/__tests__/e2e/helpers/testGraphQLServerSimple.js +52 -0
- package/lib/actions/appActions/appActions.d.ts +29 -0
- package/lib/actions/appActions/appActions.d.ts.map +1 -0
- package/lib/actions/appActions/appActions.js +159 -0
- package/lib/actions/connectionActions/connectionActions.d.ts +19 -0
- package/lib/actions/connectionActions/connectionActions.d.ts.map +1 -0
- package/lib/actions/connectionActions/connectionActions.js +131 -0
- package/lib/actions/contentActions/contentActions.d.ts +34 -0
- package/lib/actions/contentActions/contentActions.d.ts.map +1 -0
- package/lib/actions/contentActions/contentActions.js +314 -0
- package/lib/actions/conversationActions/conversationActions.d.ts +30 -0
- package/lib/actions/conversationActions/conversationActions.d.ts.map +1 -0
- package/lib/actions/conversationActions/conversationActions.js +225 -0
- package/lib/actions/eventActions/eventActions.d.ts +65 -0
- package/lib/actions/eventActions/eventActions.d.ts.map +1 -0
- package/lib/actions/eventActions/eventActions.js +436 -0
- package/lib/actions/groupActions/groupActions.d.ts +30 -0
- package/lib/actions/groupActions/groupActions.d.ts.map +1 -0
- package/lib/actions/groupActions/groupActions.js +229 -0
- package/lib/actions/imageActions/imageActions.d.ts +62 -0
- package/lib/actions/imageActions/imageActions.d.ts.map +1 -0
- package/lib/actions/imageActions/imageActions.js +593 -0
- package/lib/actions/index.d.ts +21 -0
- package/lib/actions/index.d.ts.map +1 -0
- package/lib/actions/index.js +22 -0
- package/lib/actions/locationActions/locationActions.d.ts +60 -0
- package/lib/actions/locationActions/locationActions.d.ts.map +1 -0
- package/lib/actions/locationActions/locationActions.js +388 -0
- package/lib/actions/messageActions/messageActions.d.ts +38 -0
- package/lib/actions/messageActions/messageActions.d.ts.map +1 -0
- package/lib/actions/messageActions/messageActions.js +235 -0
- package/lib/actions/permissionActions/permissionActions.d.ts +34 -0
- package/lib/actions/permissionActions/permissionActions.d.ts.map +1 -0
- package/lib/actions/permissionActions/permissionActions.js +330 -0
- package/lib/actions/personaActions/personaActions.d.ts +65 -0
- package/lib/actions/personaActions/personaActions.d.ts.map +1 -0
- package/lib/actions/personaActions/personaActions.js +572 -0
- package/lib/actions/postActions/postActions.d.ts +36 -0
- package/lib/actions/postActions/postActions.d.ts.map +1 -0
- package/lib/actions/postActions/postActions.js +447 -0
- package/lib/actions/reactionActions/reactionActions.d.ts +38 -0
- package/lib/actions/reactionActions/reactionActions.d.ts.map +1 -0
- package/lib/actions/reactionActions/reactionActions.js +413 -0
- package/lib/actions/sseActions/sseActions.d.ts +38 -0
- package/lib/actions/sseActions/sseActions.d.ts.map +1 -0
- package/lib/actions/sseActions/sseActions.js +148 -0
- package/lib/actions/subscriptionActions/subscriptionActions.d.ts +24 -0
- package/lib/actions/subscriptionActions/subscriptionActions.d.ts.map +1 -0
- package/lib/actions/subscriptionActions/subscriptionActions.js +329 -0
- package/lib/actions/tagActions/tagActions.d.ts +37 -0
- package/lib/actions/tagActions/tagActions.d.ts.map +1 -0
- package/lib/actions/tagActions/tagActions.js +347 -0
- package/lib/actions/translationActions/translationActions.d.ts +38 -0
- package/lib/actions/translationActions/translationActions.d.ts.map +1 -0
- package/lib/actions/translationActions/translationActions.js +189 -0
- package/lib/actions/userActions/userActions.d.ts +78 -0
- package/lib/actions/userActions/userActions.d.ts.map +1 -0
- package/lib/actions/userActions/userActions.js +844 -0
- package/lib/actions/videoActions/videoActions.d.ts +41 -0
- package/lib/actions/videoActions/videoActions.d.ts.map +1 -0
- package/lib/actions/videoActions/videoActions.js +532 -0
- package/lib/actions/websocketActions/websocketActions.d.ts +30 -0
- package/lib/actions/websocketActions/websocketActions.d.ts.map +1 -0
- package/lib/actions/websocketActions/websocketActions.js +377 -0
- package/lib/adapters/appAdapter/appAdapter.d.ts +8 -0
- package/lib/adapters/appAdapter/appAdapter.d.ts.map +1 -0
- package/lib/adapters/appAdapter/appAdapter.js +90 -0
- package/lib/adapters/arangoAdapter/arangoAdapter.d.ts +21 -0
- package/lib/adapters/arangoAdapter/arangoAdapter.d.ts.map +1 -0
- package/lib/adapters/arangoAdapter/arangoAdapter.js +75 -0
- package/lib/adapters/contentAdapter/contentAdapter.d.ts +32 -0
- package/lib/adapters/contentAdapter/contentAdapter.d.ts.map +1 -0
- package/lib/adapters/contentAdapter/contentAdapter.js +107 -0
- package/lib/adapters/conversationAdapter/conversationAdapter.d.ts +24 -0
- package/lib/adapters/conversationAdapter/conversationAdapter.d.ts.map +1 -0
- package/lib/adapters/conversationAdapter/conversationAdapter.js +75 -0
- package/lib/adapters/eventAdapter/eventAdapter.d.ts +46 -0
- package/lib/adapters/eventAdapter/eventAdapter.d.ts.map +1 -0
- package/lib/adapters/eventAdapter/eventAdapter.js +162 -0
- package/lib/adapters/fileAdapter/fileAdapter.d.ts +30 -0
- package/lib/adapters/fileAdapter/fileAdapter.d.ts.map +1 -0
- package/lib/adapters/fileAdapter/fileAdapter.js +118 -0
- package/lib/adapters/groupAdapter/groupAdapter.d.ts +28 -0
- package/lib/adapters/groupAdapter/groupAdapter.d.ts.map +1 -0
- package/lib/adapters/groupAdapter/groupAdapter.js +66 -0
- package/lib/adapters/imageAdapter/imageAdapter.d.ts +38 -0
- package/lib/adapters/imageAdapter/imageAdapter.d.ts.map +1 -0
- package/lib/adapters/imageAdapter/imageAdapter.js +134 -0
- package/lib/adapters/index.d.ts +34 -0
- package/lib/adapters/index.d.ts.map +1 -0
- package/lib/adapters/index.js +19 -0
- package/lib/adapters/locationAdapter/locationAdapter.d.ts +28 -0
- package/lib/adapters/locationAdapter/locationAdapter.d.ts.map +1 -0
- package/lib/adapters/locationAdapter/locationAdapter.js +95 -0
- package/lib/adapters/messageAdapter/messageAdapter.d.ts +31 -0
- package/lib/adapters/messageAdapter/messageAdapter.d.ts.map +1 -0
- package/lib/adapters/messageAdapter/messageAdapter.js +82 -0
- package/lib/adapters/permissionAdapter/permissionAdapter.d.ts +41 -0
- package/lib/adapters/permissionAdapter/permissionAdapter.d.ts.map +1 -0
- package/lib/adapters/permissionAdapter/permissionAdapter.js +120 -0
- package/lib/adapters/personaAdapter/personaAdapter.d.ts +44 -0
- package/lib/adapters/personaAdapter/personaAdapter.d.ts.map +1 -0
- package/lib/adapters/personaAdapter/personaAdapter.js +161 -0
- package/lib/adapters/postAdapter/postAdapter.d.ts +33 -0
- package/lib/adapters/postAdapter/postAdapter.d.ts.map +1 -0
- package/lib/adapters/postAdapter/postAdapter.js +115 -0
- package/lib/adapters/reactionAdapter/reactionAdapter.d.ts +23 -0
- package/lib/adapters/reactionAdapter/reactionAdapter.d.ts.map +1 -0
- package/lib/adapters/reactionAdapter/reactionAdapter.js +81 -0
- package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts +17 -0
- package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts.map +1 -0
- package/lib/adapters/reaktorAdapter/reaktorAdapter.js +58 -0
- package/lib/adapters/sessionAdapter/sessionAdapter.d.ts +24 -0
- package/lib/adapters/sessionAdapter/sessionAdapter.d.ts.map +1 -0
- package/lib/adapters/sessionAdapter/sessionAdapter.js +80 -0
- package/lib/adapters/tagAdapter/tagAdapter.d.ts +21 -0
- package/lib/adapters/tagAdapter/tagAdapter.d.ts.map +1 -0
- package/lib/adapters/tagAdapter/tagAdapter.js +98 -0
- package/lib/adapters/translationAdapter/translationAdapter.d.ts +21 -0
- package/lib/adapters/translationAdapter/translationAdapter.d.ts.map +1 -0
- package/lib/adapters/translationAdapter/translationAdapter.js +55 -0
- package/lib/adapters/userAdapter/userAdapter.d.ts +67 -0
- package/lib/adapters/userAdapter/userAdapter.d.ts.map +1 -0
- package/lib/adapters/userAdapter/userAdapter.js +302 -0
- package/lib/adapters/videoAdapter/videoAdapter.d.ts +8 -0
- package/lib/adapters/videoAdapter/videoAdapter.d.ts.map +1 -0
- package/lib/adapters/videoAdapter/videoAdapter.js +194 -0
- package/lib/config/index.d.ts +44 -0
- package/lib/config/index.d.ts.map +1 -0
- package/lib/config/index.js +97 -0
- package/lib/constants/Collections.d.ts +44 -0
- package/lib/constants/Collections.d.ts.map +1 -0
- package/lib/constants/Collections.js +40 -0
- package/lib/constants/MetropolisConstants.d.ts +15 -0
- package/lib/constants/MetropolisConstants.d.ts.map +1 -0
- package/lib/constants/MetropolisConstants.js +15 -0
- package/lib/graphql/message.d.ts +3 -0
- package/lib/graphql/message.d.ts.map +1 -0
- package/lib/graphql/message.js +20 -0
- package/lib/graphql/notification.d.ts +3 -0
- package/lib/graphql/notification.d.ts.map +1 -0
- package/lib/graphql/notification.js +20 -0
- package/lib/graphql/session.d.ts +2 -0
- package/lib/graphql/session.d.ts.map +1 -0
- package/lib/graphql/session.js +17 -0
- package/lib/index.d.ts +52 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +248 -0
- package/lib/stores/appStore.d.ts +23 -0
- package/lib/stores/appStore.d.ts.map +1 -0
- package/lib/stores/appStore.js +23 -0
- package/lib/stores/contentStore.d.ts +36 -0
- package/lib/stores/contentStore.d.ts.map +1 -0
- package/lib/stores/contentStore.js +139 -0
- package/lib/stores/conversationStore.d.ts +38 -0
- package/lib/stores/conversationStore.d.ts.map +1 -0
- package/lib/stores/conversationStore.js +117 -0
- package/lib/stores/eventStore.d.ts +37 -0
- package/lib/stores/eventStore.d.ts.map +1 -0
- package/lib/stores/eventStore.js +47 -0
- package/lib/stores/groupStore.d.ts +37 -0
- package/lib/stores/groupStore.d.ts.map +1 -0
- package/lib/stores/groupStore.js +68 -0
- package/lib/stores/imageStore.d.ts +40 -0
- package/lib/stores/imageStore.d.ts.map +1 -0
- package/lib/stores/imageStore.js +53 -0
- package/lib/stores/index.d.ts +24 -0
- package/lib/stores/index.d.ts.map +1 -0
- package/lib/stores/index.js +24 -0
- package/lib/stores/locationStore.d.ts +34 -0
- package/lib/stores/locationStore.d.ts.map +1 -0
- package/lib/stores/locationStore.js +42 -0
- package/lib/stores/messageStore.d.ts +51 -0
- package/lib/stores/messageStore.d.ts.map +1 -0
- package/lib/stores/messageStore.js +137 -0
- package/lib/stores/notificationStore.d.ts +33 -0
- package/lib/stores/notificationStore.d.ts.map +1 -0
- package/lib/stores/notificationStore.js +55 -0
- package/lib/stores/permissionStore.d.ts +37 -0
- package/lib/stores/permissionStore.d.ts.map +1 -0
- package/lib/stores/permissionStore.js +117 -0
- package/lib/stores/personaStore.d.ts +26 -0
- package/lib/stores/personaStore.d.ts.map +1 -0
- package/lib/stores/personaStore.js +118 -0
- package/lib/stores/postStore.d.ts +34 -0
- package/lib/stores/postStore.d.ts.map +1 -0
- package/lib/stores/postStore.js +53 -0
- package/lib/stores/reactionStore.d.ts +25 -0
- package/lib/stores/reactionStore.d.ts.map +1 -0
- package/lib/stores/reactionStore.js +28 -0
- package/lib/stores/subscriptionStore.d.ts +41 -0
- package/lib/stores/subscriptionStore.d.ts.map +1 -0
- package/lib/stores/subscriptionStore.js +85 -0
- package/lib/stores/tagStore.d.ts +34 -0
- package/lib/stores/tagStore.d.ts.map +1 -0
- package/lib/stores/tagStore.js +87 -0
- package/lib/stores/translationStore.d.ts +42 -0
- package/lib/stores/translationStore.d.ts.map +1 -0
- package/lib/stores/translationStore.js +122 -0
- package/lib/stores/userStore.d.ts +74 -0
- package/lib/stores/userStore.d.ts.map +1 -0
- package/lib/stores/userStore.js +319 -0
- package/lib/stores/videoStore.d.ts +39 -0
- package/lib/stores/videoStore.d.ts.map +1 -0
- package/lib/stores/videoStore.js +132 -0
- package/lib/stores/websocketStore.d.ts +24 -0
- package/lib/stores/websocketStore.d.ts.map +1 -0
- package/lib/stores/websocketStore.js +51 -0
- package/lib/types/apps.types.d.ts +17 -0
- package/lib/types/apps.types.d.ts.map +1 -0
- package/lib/types/apps.types.js +6 -0
- package/lib/types/common.types.d.ts +31 -0
- package/lib/types/common.types.d.ts.map +1 -0
- package/lib/types/common.types.js +6 -0
- package/lib/types/conversations.types.d.ts +17 -0
- package/lib/types/conversations.types.d.ts.map +1 -0
- package/lib/types/conversations.types.js +6 -0
- package/lib/types/edges.types.d.ts +38 -0
- package/lib/types/edges.types.d.ts.map +1 -0
- package/lib/types/edges.types.js +6 -0
- package/lib/types/groups.types.d.ts +19 -0
- package/lib/types/groups.types.d.ts.map +1 -0
- package/lib/types/groups.types.js +6 -0
- package/lib/types/index.d.ts +12 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +12 -0
- package/lib/types/subscriptions.types.d.ts +32 -0
- package/lib/types/subscriptions.types.d.ts.map +1 -0
- package/lib/types/subscriptions.types.js +6 -0
- package/lib/types/videos.types.d.ts +61 -0
- package/lib/types/videos.types.d.ts.map +1 -0
- package/lib/types/videos.types.js +6 -0
- package/lib/utils/MetropolisProvider.d.ts +58 -0
- package/lib/utils/MetropolisProvider.d.ts.map +1 -0
- package/lib/utils/MetropolisProvider.js +31 -0
- package/lib/utils/actionFactory.d.ts +24 -0
- package/lib/utils/actionFactory.d.ts.map +1 -0
- package/lib/utils/actionFactory.js +95 -0
- package/lib/utils/api.d.ts +44 -0
- package/lib/utils/api.d.ts.map +1 -0
- package/lib/utils/api.js +253 -0
- package/lib/utils/app.d.ts +7 -0
- package/lib/utils/app.d.ts.map +1 -0
- package/lib/utils/app.js +15 -0
- package/lib/utils/baseActionFactory.d.ts +16 -0
- package/lib/utils/baseActionFactory.d.ts.map +1 -0
- package/lib/utils/baseActionFactory.js +72 -0
- package/lib/utils/configUtils.d.ts +11 -0
- package/lib/utils/configUtils.d.ts.map +1 -0
- package/lib/utils/configUtils.js +20 -0
- package/lib/utils/dateUtils.d.ts +3 -0
- package/lib/utils/dateUtils.d.ts.map +1 -0
- package/lib/utils/dateUtils.js +11 -0
- package/lib/utils/file.d.ts +3 -0
- package/lib/utils/file.d.ts.map +1 -0
- package/lib/utils/file.js +156 -0
- package/lib/utils/i18n.d.ts +7 -0
- package/lib/utils/i18n.d.ts.map +1 -0
- package/lib/utils/i18n.js +96 -0
- package/lib/utils/index.d.ts +20 -0
- package/lib/utils/index.d.ts.map +1 -0
- package/lib/utils/index.js +26 -0
- package/lib/utils/location.d.ts +10 -0
- package/lib/utils/location.d.ts.map +1 -0
- package/lib/utils/location.js +82 -0
- package/lib/utils/permissionUtils.d.ts +22 -0
- package/lib/utils/permissionUtils.d.ts.map +1 -0
- package/lib/utils/permissionUtils.js +72 -0
- package/lib/utils/requestCache.d.ts +8 -0
- package/lib/utils/requestCache.d.ts.map +1 -0
- package/lib/utils/requestCache.js +53 -0
- package/lib/utils/session.d.ts +14 -0
- package/lib/utils/session.d.ts.map +1 -0
- package/lib/utils/session.js +107 -0
- package/lib/utils/useConversationTyping.d.ts +26 -0
- package/lib/utils/useConversationTyping.d.ts.map +1 -0
- package/lib/utils/useConversationTyping.js +117 -0
- package/lib/utils/useMetropolis.d.ts +67 -0
- package/lib/utils/useMetropolis.d.ts.map +1 -0
- package/lib/utils/useMetropolis.js +311 -0
- package/lib/utils/useTranslations.d.ts +16 -0
- package/lib/utils/useTranslations.d.ts.map +1 -0
- package/lib/utils/useTranslations.js +105 -0
- package/lib/utils/validatorFactory.d.ts +49 -0
- package/lib/utils/validatorFactory.d.ts.map +1 -0
- package/lib/utils/validatorFactory.js +95 -0
- package/package.json +75 -28
- package/temp_signin.ts +73 -0
- package/tsconfig.lint.json +25 -0
- 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
|
+
};
|