@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.
- 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 +1123 -112
- 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/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/index.js +1 -0
- package/jest.config.mjs +28 -0
- package/lex.config.mjs +11 -2
- 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 +27 -7
- package/lib/actions/eventActions/eventActions.d.ts.map +1 -0
- package/lib/actions/eventActions/eventActions.js +436 -2
- 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 +16 -10
- package/lib/actions/imageActions/imageActions.d.ts.map +1 -0
- package/lib/actions/imageActions/imageActions.js +593 -2
- package/lib/actions/index.d.ts +21 -9
- package/lib/actions/index.d.ts.map +1 -0
- package/lib/actions/index.js +22 -2
- package/lib/actions/locationActions/locationActions.d.ts +11 -9
- package/lib/actions/locationActions/locationActions.d.ts.map +1 -0
- package/lib/actions/locationActions/locationActions.js +388 -2
- package/lib/actions/messageActions/messageActions.d.ts +16 -32
- package/lib/actions/messageActions/messageActions.d.ts.map +1 -0
- package/lib/actions/messageActions/messageActions.js +235 -2
- 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 +12 -32
- package/lib/actions/postActions/postActions.d.ts.map +1 -0
- package/lib/actions/postActions/postActions.js +447 -2
- package/lib/actions/reactionActions/reactionActions.d.ts +13 -27
- package/lib/actions/reactionActions/reactionActions.d.ts.map +1 -0
- package/lib/actions/reactionActions/reactionActions.js +413 -2
- package/lib/actions/sseActions/sseActions.d.ts +1 -0
- package/lib/actions/sseActions/sseActions.d.ts.map +1 -0
- package/lib/actions/sseActions/sseActions.js +148 -2
- 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 +13 -31
- package/lib/actions/tagActions/tagActions.d.ts.map +1 -0
- package/lib/actions/tagActions/tagActions.js +347 -2
- 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 +42 -95
- package/lib/actions/userActions/userActions.d.ts.map +1 -0
- package/lib/actions/userActions/userActions.js +844 -2
- 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 +20 -21
- package/lib/actions/websocketActions/websocketActions.d.ts.map +1 -0
- package/lib/actions/websocketActions/websocketActions.js +377 -2
- 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 +3 -2
- package/lib/adapters/arangoAdapter/arangoAdapter.d.ts.map +1 -0
- package/lib/adapters/arangoAdapter/arangoAdapter.js +75 -2
- package/lib/adapters/contentAdapter/contentAdapter.d.ts +3 -2
- package/lib/adapters/contentAdapter/contentAdapter.d.ts.map +1 -0
- package/lib/adapters/contentAdapter/contentAdapter.js +107 -2
- package/lib/adapters/conversationAdapter/conversationAdapter.d.ts +3 -2
- package/lib/adapters/conversationAdapter/conversationAdapter.d.ts.map +1 -0
- package/lib/adapters/conversationAdapter/conversationAdapter.js +75 -2
- package/lib/adapters/eventAdapter/eventAdapter.d.ts +5 -2
- package/lib/adapters/eventAdapter/eventAdapter.d.ts.map +1 -0
- package/lib/adapters/eventAdapter/eventAdapter.js +162 -2
- package/lib/adapters/fileAdapter/fileAdapter.d.ts +3 -2
- package/lib/adapters/fileAdapter/fileAdapter.d.ts.map +1 -0
- package/lib/adapters/fileAdapter/fileAdapter.js +118 -2
- 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 +9 -2
- package/lib/adapters/imageAdapter/imageAdapter.d.ts.map +1 -0
- package/lib/adapters/imageAdapter/imageAdapter.js +134 -2
- package/lib/adapters/index.d.ts +34 -16
- package/lib/adapters/index.d.ts.map +1 -0
- package/lib/adapters/index.js +19 -2
- package/lib/adapters/locationAdapter/locationAdapter.d.ts +3 -2
- package/lib/adapters/locationAdapter/locationAdapter.d.ts.map +1 -0
- package/lib/adapters/locationAdapter/locationAdapter.js +95 -2
- package/lib/adapters/messageAdapter/messageAdapter.d.ts +23 -19
- package/lib/adapters/messageAdapter/messageAdapter.d.ts.map +1 -0
- package/lib/adapters/messageAdapter/messageAdapter.js +82 -2
- 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 +28 -2
- package/lib/adapters/personaAdapter/personaAdapter.d.ts.map +1 -0
- package/lib/adapters/personaAdapter/personaAdapter.js +161 -2
- package/lib/adapters/postAdapter/postAdapter.d.ts +3 -2
- package/lib/adapters/postAdapter/postAdapter.d.ts.map +1 -0
- package/lib/adapters/postAdapter/postAdapter.js +115 -2
- package/lib/adapters/reactionAdapter/reactionAdapter.d.ts +5 -2
- package/lib/adapters/reactionAdapter/reactionAdapter.d.ts.map +1 -0
- package/lib/adapters/reactionAdapter/reactionAdapter.js +81 -2
- package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts +3 -2
- package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts.map +1 -0
- package/lib/adapters/reaktorAdapter/reaktorAdapter.js +58 -2
- package/lib/adapters/sessionAdapter/sessionAdapter.d.ts +3 -2
- package/lib/adapters/sessionAdapter/sessionAdapter.d.ts.map +1 -0
- package/lib/adapters/sessionAdapter/sessionAdapter.js +80 -2
- package/lib/adapters/tagAdapter/tagAdapter.d.ts +3 -2
- package/lib/adapters/tagAdapter/tagAdapter.d.ts.map +1 -0
- package/lib/adapters/tagAdapter/tagAdapter.js +98 -2
- 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 +18 -6
- package/lib/adapters/userAdapter/userAdapter.d.ts.map +1 -0
- package/lib/adapters/userAdapter/userAdapter.js +302 -2
- 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 +19 -6
- package/lib/config/index.d.ts.map +1 -0
- package/lib/config/index.js +97 -2
- 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 +1 -0
- package/lib/constants/MetropolisConstants.d.ts.map +1 -0
- package/lib/constants/MetropolisConstants.js +15 -2
- package/lib/graphql/message.d.ts +1 -0
- package/lib/graphql/message.d.ts.map +1 -0
- package/lib/graphql/message.js +6 -4
- package/lib/graphql/notification.d.ts +1 -0
- package/lib/graphql/notification.d.ts.map +1 -0
- package/lib/graphql/notification.js +6 -4
- package/lib/graphql/session.d.ts +1 -0
- package/lib/graphql/session.d.ts.map +1 -0
- package/lib/graphql/session.js +4 -3
- package/lib/index.d.ts +45 -22
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +248 -2
- package/lib/stores/appStore.d.ts +1 -0
- package/lib/stores/appStore.d.ts.map +1 -0
- package/lib/stores/appStore.js +23 -2
- 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 +4 -1
- package/lib/stores/eventStore.d.ts.map +1 -0
- package/lib/stores/eventStore.js +47 -2
- 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 +6 -1
- package/lib/stores/imageStore.d.ts.map +1 -0
- package/lib/stores/imageStore.js +53 -2
- package/lib/stores/index.d.ts +20 -11
- package/lib/stores/index.d.ts.map +1 -0
- package/lib/stores/index.js +24 -2
- package/lib/stores/locationStore.d.ts +2 -1
- package/lib/stores/locationStore.d.ts.map +1 -0
- package/lib/stores/locationStore.js +42 -2
- package/lib/stores/messageStore.d.ts +19 -4
- package/lib/stores/messageStore.d.ts.map +1 -0
- package/lib/stores/messageStore.js +137 -2
- 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 +2 -1
- package/lib/stores/postStore.d.ts.map +1 -0
- package/lib/stores/postStore.js +53 -2
- package/lib/stores/reactionStore.d.ts +1 -0
- package/lib/stores/reactionStore.d.ts.map +1 -0
- package/lib/stores/reactionStore.js +28 -2
- 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 +8 -5
- package/lib/stores/tagStore.d.ts.map +1 -0
- package/lib/stores/tagStore.js +87 -2
- 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 +5 -4
- package/lib/stores/userStore.d.ts.map +1 -0
- package/lib/stores/userStore.js +319 -2
- 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 +1 -0
- package/lib/stores/websocketStore.d.ts.map +1 -0
- package/lib/stores/websocketStore.js +51 -2
- 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 +39 -15
- package/lib/utils/MetropolisProvider.d.ts.map +1 -0
- package/lib/utils/MetropolisProvider.js +31 -2
- package/lib/utils/actionFactory.d.ts +21 -19
- package/lib/utils/actionFactory.d.ts.map +1 -0
- package/lib/utils/actionFactory.js +95 -2
- package/lib/utils/api.d.ts +5 -4
- package/lib/utils/api.d.ts.map +1 -0
- package/lib/utils/api.js +252 -6
- package/lib/utils/app.d.ts +1 -0
- package/lib/utils/app.d.ts.map +1 -0
- package/lib/utils/app.js +15 -2
- package/lib/utils/baseActionFactory.d.ts +5 -23
- package/lib/utils/baseActionFactory.d.ts.map +1 -0
- package/lib/utils/baseActionFactory.js +72 -2
- 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 +1 -0
- package/lib/utils/dateUtils.d.ts.map +1 -0
- package/lib/utils/dateUtils.js +11 -2
- package/lib/utils/file.d.ts +3 -1
- package/lib/utils/file.d.ts.map +1 -0
- package/lib/utils/file.js +156 -2
- 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 +4 -3
- package/lib/utils/location.d.ts.map +1 -0
- package/lib/utils/location.js +82 -2
- 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 -12
- package/lib/utils/useMetropolis.d.ts.map +1 -0
- package/lib/utils/useMetropolis.js +311 -2
- 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 +3 -2
- package/lib/utils/validatorFactory.d.ts.map +1 -0
- package/lib/utils/validatorFactory.js +95 -2
- package/package.json +58 -17
- package/temp_signin.ts +73 -0
- package/lib/actions/profileActions/profileActions.d.ts +0 -50
- package/lib/actions/profileActions/profileActions.js +0 -2
- package/lib/adapters/profileAdapter/profileAdapter.d.ts +0 -32
- package/lib/adapters/profileAdapter/profileAdapter.js +0 -2
- package/lib/stores/profileStore.d.ts +0 -24
- package/lib/stores/profileStore.js +0 -2
- /package/{FACTORY_PATTERN_GUIDE.md → factoryPatternGuide.md} +0 -0
|
@@ -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
|
+
// Define the types directly to avoid JSX compilation issues
|
|
7
|
+
type SimpleTranslations = Record<string, string>;
|
|
8
|
+
|
|
9
|
+
interface ComplexTranslation {
|
|
10
|
+
readonly value: string;
|
|
11
|
+
readonly locale: string;
|
|
12
|
+
readonly namespace?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type ComplexTranslations = Record<string, ComplexTranslation>;
|
|
16
|
+
|
|
17
|
+
// Test simple translations type
|
|
18
|
+
const simpleTranslations: SimpleTranslations = {
|
|
19
|
+
'welcome': 'Welcome to MetropolisJS!',
|
|
20
|
+
'hello': 'Hello {{name}}!',
|
|
21
|
+
'goodbye': 'Goodbye'
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// Test complex translations type
|
|
25
|
+
const complexTranslations: ComplexTranslations = {
|
|
26
|
+
'welcome:en': {
|
|
27
|
+
value: 'Welcome to MetropolisJS!',
|
|
28
|
+
locale: 'en',
|
|
29
|
+
namespace: 'common'
|
|
30
|
+
},
|
|
31
|
+
'hello:en': {
|
|
32
|
+
value: 'Hello {{name}}!',
|
|
33
|
+
locale: 'en',
|
|
34
|
+
namespace: 'common'
|
|
35
|
+
},
|
|
36
|
+
'save:en': {
|
|
37
|
+
value: 'Save',
|
|
38
|
+
locale: 'en',
|
|
39
|
+
namespace: 'buttons'
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Test individual complex translation type
|
|
44
|
+
const singleTranslation: ComplexTranslation = {
|
|
45
|
+
value: 'Test translation',
|
|
46
|
+
locale: 'en',
|
|
47
|
+
namespace: 'test'
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Function to demonstrate type safety
|
|
51
|
+
function processTranslations(translations: SimpleTranslations | ComplexTranslations): void {
|
|
52
|
+
if (Object.keys(translations).length === 0) {
|
|
53
|
+
console.log('No translations provided');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const firstKey = Object.keys(translations)[0];
|
|
58
|
+
const firstValue = translations[firstKey];
|
|
59
|
+
|
|
60
|
+
if (typeof firstValue === 'string') {
|
|
61
|
+
// TypeScript knows this is SimpleTranslations
|
|
62
|
+
console.log('Processing simple translations');
|
|
63
|
+
Object.entries(translations as SimpleTranslations).forEach(([key, value]) => {
|
|
64
|
+
console.log(`${key}: ${value}`);
|
|
65
|
+
});
|
|
66
|
+
} else if (typeof firstValue === 'object' && firstValue !== null && 'value' in firstValue) {
|
|
67
|
+
// TypeScript knows this is ComplexTranslations
|
|
68
|
+
console.log('Processing complex translations');
|
|
69
|
+
Object.entries(translations as ComplexTranslations).forEach(([key, translation]) => {
|
|
70
|
+
console.log(`${key}: ${translation.value} (${translation.locale}${translation.namespace ? `, ${translation.namespace}` : ''})`);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Test the function with both types
|
|
76
|
+
console.log('Testing simple translations:');
|
|
77
|
+
processTranslations(simpleTranslations);
|
|
78
|
+
|
|
79
|
+
console.log('\nTesting complex translations:');
|
|
80
|
+
processTranslations(complexTranslations);
|
|
81
|
+
|
|
82
|
+
console.log('\nType test completed successfully!');
|
|
83
|
+
|
|
84
|
+
// Export for use in other files
|
|
85
|
+
export { complexTranslations, processTranslations, simpleTranslations, singleTranslation };
|
|
86
|
+
export type { ComplexTranslation, ComplexTranslations, SimpleTranslations };
|
|
@@ -0,0 +1,336 @@
|
|
|
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
|
+
import React from 'react';
|
|
7
|
+
import { ComplexTranslations, Metropolis, SimpleTranslations } from '../src/index';
|
|
8
|
+
import { i18n } from '../src/utils/i18n';
|
|
9
|
+
|
|
10
|
+
// Example translations object with simple key-value pairs
|
|
11
|
+
const simpleTranslations: SimpleTranslations = {
|
|
12
|
+
'welcome': 'Welcome to MetropolisJS!',
|
|
13
|
+
'hello': 'Hello {{name}}!',
|
|
14
|
+
'goodbye': 'Goodbye',
|
|
15
|
+
'loading': 'Loading...',
|
|
16
|
+
'error': 'An error occurred',
|
|
17
|
+
'success': 'Operation completed successfully',
|
|
18
|
+
'cancel': 'Cancel',
|
|
19
|
+
'save': 'Save',
|
|
20
|
+
'delete': 'Delete',
|
|
21
|
+
'edit': 'Edit',
|
|
22
|
+
'create': 'Create',
|
|
23
|
+
'update': 'Update',
|
|
24
|
+
'search': 'Search',
|
|
25
|
+
'filter': 'Filter',
|
|
26
|
+
'sort': 'Sort',
|
|
27
|
+
'refresh': 'Refresh',
|
|
28
|
+
'back': 'Back',
|
|
29
|
+
'next': 'Next',
|
|
30
|
+
'previous': 'Previous',
|
|
31
|
+
'submit': 'Submit',
|
|
32
|
+
'reset': 'Reset',
|
|
33
|
+
'confirm': 'Confirm',
|
|
34
|
+
'yes': 'Yes',
|
|
35
|
+
'no': 'No',
|
|
36
|
+
'ok': 'OK',
|
|
37
|
+
'close': 'Close',
|
|
38
|
+
'open': 'Open',
|
|
39
|
+
'show': 'Show',
|
|
40
|
+
'hide': 'Hide',
|
|
41
|
+
'expand': 'Expand',
|
|
42
|
+
'collapse': 'Collapse',
|
|
43
|
+
'minimize': 'Minimize',
|
|
44
|
+
'maximize': 'Maximize',
|
|
45
|
+
'fullscreen': 'Fullscreen',
|
|
46
|
+
'settings': 'Settings',
|
|
47
|
+
'profile': 'Profile',
|
|
48
|
+
'account': 'Account',
|
|
49
|
+
'logout': 'Logout',
|
|
50
|
+
'login': 'Login',
|
|
51
|
+
'register': 'Register',
|
|
52
|
+
'forgot_password': 'Forgot Password?',
|
|
53
|
+
'remember_me': 'Remember Me',
|
|
54
|
+
'email': 'Email',
|
|
55
|
+
'password': 'Password',
|
|
56
|
+
'username': 'Username',
|
|
57
|
+
'first_name': 'First Name',
|
|
58
|
+
'last_name': 'Last Name',
|
|
59
|
+
'phone': 'Phone',
|
|
60
|
+
'address': 'Address',
|
|
61
|
+
'city': 'City',
|
|
62
|
+
'state': 'State',
|
|
63
|
+
'country': 'Country',
|
|
64
|
+
'zip_code': 'ZIP Code',
|
|
65
|
+
'birth_date': 'Birth Date',
|
|
66
|
+
'gender': 'Gender',
|
|
67
|
+
'male': 'Male',
|
|
68
|
+
'female': 'Female',
|
|
69
|
+
'other': 'Other',
|
|
70
|
+
'prefer_not_to_say': 'Prefer not to say'
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// Example complex translations with locale and namespace support
|
|
74
|
+
const complexTranslations: ComplexTranslations = {
|
|
75
|
+
'welcome:en': {
|
|
76
|
+
value: 'Welcome to MetropolisJS!',
|
|
77
|
+
locale: 'en',
|
|
78
|
+
namespace: 'common'
|
|
79
|
+
},
|
|
80
|
+
'hello:en': {
|
|
81
|
+
value: 'Hello {{name}}!',
|
|
82
|
+
locale: 'en',
|
|
83
|
+
namespace: 'common'
|
|
84
|
+
},
|
|
85
|
+
'save:en': {
|
|
86
|
+
value: 'Save',
|
|
87
|
+
locale: 'en',
|
|
88
|
+
namespace: 'buttons'
|
|
89
|
+
},
|
|
90
|
+
'cancel:en': {
|
|
91
|
+
value: 'Cancel',
|
|
92
|
+
locale: 'en',
|
|
93
|
+
namespace: 'buttons'
|
|
94
|
+
},
|
|
95
|
+
'welcome:es': {
|
|
96
|
+
value: '¡Bienvenido a MetropolisJS!',
|
|
97
|
+
locale: 'es',
|
|
98
|
+
namespace: 'common'
|
|
99
|
+
},
|
|
100
|
+
'hello:es': {
|
|
101
|
+
value: '¡Hola {{name}}!',
|
|
102
|
+
locale: 'es',
|
|
103
|
+
namespace: 'common'
|
|
104
|
+
},
|
|
105
|
+
'save:es': {
|
|
106
|
+
value: 'Guardar',
|
|
107
|
+
locale: 'es',
|
|
108
|
+
namespace: 'buttons'
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
// Example React component using Metropolis with simple translations
|
|
113
|
+
const SimpleTranslationApp: React.FC = () => {
|
|
114
|
+
return (
|
|
115
|
+
<Metropolis
|
|
116
|
+
translations={simpleTranslations}
|
|
117
|
+
config={{
|
|
118
|
+
development: {
|
|
119
|
+
app: {
|
|
120
|
+
api: {
|
|
121
|
+
url: 'https://api.example.com'
|
|
122
|
+
},
|
|
123
|
+
urls: {
|
|
124
|
+
websocket: 'wss://ws.example.com'
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}}
|
|
129
|
+
>
|
|
130
|
+
<div>
|
|
131
|
+
<h1>{i18n('welcome')}</h1>
|
|
132
|
+
<p>{i18n('hello', {name: 'John'})}</p>
|
|
133
|
+
<button>{i18n('save')}</button>
|
|
134
|
+
<button>{i18n('cancel')}</button>
|
|
135
|
+
<p>{i18n('loading')}</p>
|
|
136
|
+
</div>
|
|
137
|
+
</Metropolis>
|
|
138
|
+
);
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// Example React component using Metropolis with complex translations
|
|
142
|
+
const ComplexTranslationApp: React.FC = () => {
|
|
143
|
+
return (
|
|
144
|
+
<Metropolis
|
|
145
|
+
translations={complexTranslations}
|
|
146
|
+
config={{
|
|
147
|
+
development: {
|
|
148
|
+
app: {
|
|
149
|
+
api: {
|
|
150
|
+
url: 'https://api.example.com'
|
|
151
|
+
},
|
|
152
|
+
urls: {
|
|
153
|
+
websocket: 'wss://ws.example.com'
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}}
|
|
158
|
+
>
|
|
159
|
+
<div>
|
|
160
|
+
<h1>{i18n('welcome', {}, 'en', 'common')}</h1>
|
|
161
|
+
<p>{i18n('hello', {name: 'John'}, 'en', 'common')}</p>
|
|
162
|
+
<button>{i18n('save', {}, 'en', 'buttons')}</button>
|
|
163
|
+
<button>{i18n('cancel', {}, 'en', 'buttons')}</button>
|
|
164
|
+
<p>{i18n('loading')}</p>
|
|
165
|
+
</div>
|
|
166
|
+
</Metropolis>
|
|
167
|
+
);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// Example of using translations in a component
|
|
171
|
+
const UserProfile: React.FC = () => {
|
|
172
|
+
const [isLoading, setIsLoading] = React.useState(false);
|
|
173
|
+
const [user, setUser] = React.useState({name: 'John Doe'});
|
|
174
|
+
|
|
175
|
+
return (
|
|
176
|
+
<div>
|
|
177
|
+
<h2>{i18n('profile')}</h2>
|
|
178
|
+
{isLoading ? (
|
|
179
|
+
<p>{i18n('loading')}</p>
|
|
180
|
+
) : (
|
|
181
|
+
<div>
|
|
182
|
+
<p>{i18n('hello', {name: user.name})}</p>
|
|
183
|
+
<button>{i18n('edit')}</button>
|
|
184
|
+
<button>{i18n('delete')}</button>
|
|
185
|
+
</div>
|
|
186
|
+
)}
|
|
187
|
+
</div>
|
|
188
|
+
);
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
// Example of a form component with translations
|
|
192
|
+
const LoginForm: React.FC = () => {
|
|
193
|
+
const [formData, setFormData] = React.useState({
|
|
194
|
+
email: '',
|
|
195
|
+
password: '',
|
|
196
|
+
rememberMe: false
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const handleSubmit = (e: React.FormEvent) => {
|
|
200
|
+
e.preventDefault();
|
|
201
|
+
// Handle form submission
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
return (
|
|
205
|
+
<form onSubmit={handleSubmit}>
|
|
206
|
+
<h2>{i18n('login')}</h2>
|
|
207
|
+
|
|
208
|
+
<div>
|
|
209
|
+
<label htmlFor="email">{i18n('email')}:</label>
|
|
210
|
+
<input
|
|
211
|
+
id="email"
|
|
212
|
+
type="email"
|
|
213
|
+
value={formData.email}
|
|
214
|
+
onChange={(e) => setFormData({...formData, email: e.target.value})}
|
|
215
|
+
required
|
|
216
|
+
/>
|
|
217
|
+
</div>
|
|
218
|
+
|
|
219
|
+
<div>
|
|
220
|
+
<label htmlFor="password">{i18n('password')}:</label>
|
|
221
|
+
<input
|
|
222
|
+
id="password"
|
|
223
|
+
type="password"
|
|
224
|
+
value={formData.password}
|
|
225
|
+
onChange={(e) => setFormData({...formData, password: e.target.value})}
|
|
226
|
+
required
|
|
227
|
+
/>
|
|
228
|
+
</div>
|
|
229
|
+
|
|
230
|
+
<div>
|
|
231
|
+
<label>
|
|
232
|
+
<input
|
|
233
|
+
type="checkbox"
|
|
234
|
+
checked={formData.rememberMe}
|
|
235
|
+
onChange={(e) => setFormData({...formData, rememberMe: e.target.checked})}
|
|
236
|
+
/>
|
|
237
|
+
{i18n('remember_me')}
|
|
238
|
+
</label>
|
|
239
|
+
</div>
|
|
240
|
+
|
|
241
|
+
<div>
|
|
242
|
+
<button type="submit">{i18n('login')}</button>
|
|
243
|
+
<button type="button">{i18n('cancel')}</button>
|
|
244
|
+
</div>
|
|
245
|
+
|
|
246
|
+
<div>
|
|
247
|
+
<a href="#forgot-password">{i18n('forgot_password')}</a>
|
|
248
|
+
</div>
|
|
249
|
+
</form>
|
|
250
|
+
);
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
// Example of a multilingual app that can switch between simple and complex translations
|
|
254
|
+
const MultilingualApp: React.FC = () => {
|
|
255
|
+
const [useComplexTranslations, setUseComplexTranslations] = React.useState(false);
|
|
256
|
+
const [currentLocale, setCurrentLocale] = React.useState<'en' | 'es'>('en');
|
|
257
|
+
|
|
258
|
+
const selectedTranslations = useComplexTranslations ? complexTranslations : simpleTranslations;
|
|
259
|
+
|
|
260
|
+
return (
|
|
261
|
+
<Metropolis
|
|
262
|
+
translations={selectedTranslations}
|
|
263
|
+
config={{
|
|
264
|
+
development: {
|
|
265
|
+
app: {
|
|
266
|
+
api: {
|
|
267
|
+
url: 'https://api.example.com'
|
|
268
|
+
},
|
|
269
|
+
urls: {
|
|
270
|
+
websocket: 'wss://ws.example.com'
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}}
|
|
275
|
+
>
|
|
276
|
+
<div>
|
|
277
|
+
<div style={{marginBottom: '20px'}}>
|
|
278
|
+
<label>
|
|
279
|
+
<input
|
|
280
|
+
type="checkbox"
|
|
281
|
+
checked={useComplexTranslations}
|
|
282
|
+
onChange={(e) => setUseComplexTranslations(e.target.checked)}
|
|
283
|
+
/>
|
|
284
|
+
Use Complex Translations
|
|
285
|
+
</label>
|
|
286
|
+
|
|
287
|
+
{useComplexTranslations && (
|
|
288
|
+
<div style={{marginLeft: '20px'}}>
|
|
289
|
+
<label>
|
|
290
|
+
Locale:
|
|
291
|
+
<select value={currentLocale} onChange={(e) => setCurrentLocale(e.target.value as 'en' | 'es')}>
|
|
292
|
+
<option value="en">English</option>
|
|
293
|
+
<option value="es">Español</option>
|
|
294
|
+
</select>
|
|
295
|
+
</label>
|
|
296
|
+
</div>
|
|
297
|
+
)}
|
|
298
|
+
</div>
|
|
299
|
+
|
|
300
|
+
<h1>
|
|
301
|
+
{useComplexTranslations
|
|
302
|
+
? i18n('welcome', {}, currentLocale, 'common')
|
|
303
|
+
: i18n('welcome')
|
|
304
|
+
}
|
|
305
|
+
</h1>
|
|
306
|
+
|
|
307
|
+
<p>
|
|
308
|
+
{useComplexTranslations
|
|
309
|
+
? i18n('hello', {name: 'World'}, currentLocale, 'common')
|
|
310
|
+
: i18n('hello', {name: 'World'})
|
|
311
|
+
}
|
|
312
|
+
</p>
|
|
313
|
+
|
|
314
|
+
<div>
|
|
315
|
+
<button>
|
|
316
|
+
{useComplexTranslations
|
|
317
|
+
? i18n('save', {}, currentLocale, 'buttons')
|
|
318
|
+
: i18n('save')
|
|
319
|
+
}
|
|
320
|
+
</button>
|
|
321
|
+
<button>
|
|
322
|
+
{useComplexTranslations
|
|
323
|
+
? i18n('cancel', {}, currentLocale, 'buttons')
|
|
324
|
+
: i18n('cancel')
|
|
325
|
+
}
|
|
326
|
+
</button>
|
|
327
|
+
</div>
|
|
328
|
+
|
|
329
|
+
<UserProfile />
|
|
330
|
+
<LoginForm />
|
|
331
|
+
</div>
|
|
332
|
+
</Metropolis>
|
|
333
|
+
);
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
export default MultilingualApp;
|
package/index.js
CHANGED
package/jest.config.mjs
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Jest configuration for MetropolisJS tests.
|
|
3
|
+
* Pulls the default Lex Jest config (which includes TS/Babel transforms)
|
|
4
|
+
* and overlays the project-specific settings from lex.config.mjs.
|
|
5
|
+
*/
|
|
6
|
+
import lexConfig from './lex.config.mjs';
|
|
7
|
+
import baseConfig from './node_modules/@nlabs/lex/jest.config.mjs';
|
|
8
|
+
|
|
9
|
+
const projectJest = lexConfig?.jest || {};
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
...baseConfig,
|
|
13
|
+
...projectJest,
|
|
14
|
+
testPathIgnorePatterns: [
|
|
15
|
+
'lib/__tests__/e2e/helpers/testGraphQLServer.d.ts',
|
|
16
|
+
'lib/__tests__/e2e/helpers/testGraphQLServerSimple.d.ts'
|
|
17
|
+
],
|
|
18
|
+
transformIgnorePatterns: [
|
|
19
|
+
'/node_modules/(?!(?:@nlabs/utils|@nlabs/rip-hunter)/)'
|
|
20
|
+
],
|
|
21
|
+
moduleNameMapper: {
|
|
22
|
+
...baseConfig.moduleNameMapper,
|
|
23
|
+
...projectJest.moduleNameMapper
|
|
24
|
+
},
|
|
25
|
+
transform: {
|
|
26
|
+
...baseConfig.transform
|
|
27
|
+
}
|
|
28
|
+
};
|
package/lex.config.mjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import {Config} from '@nlabs/lex';
|
|
2
|
+
|
|
3
|
+
export default Config.create({
|
|
2
4
|
ai: {
|
|
3
5
|
maxTokens: 4000,
|
|
4
6
|
model: 'cursor-code',
|
|
@@ -6,12 +8,19 @@ export default {
|
|
|
6
8
|
temperature: 0.1
|
|
7
9
|
},
|
|
8
10
|
entryJS: 'app.tsx',
|
|
11
|
+
esbuild: {
|
|
12
|
+
minify: process.env.NODE_ENV === 'production'
|
|
13
|
+
},
|
|
9
14
|
gitUrl: 'https://github.com/nitrogenlabs/metropolisjs',
|
|
10
15
|
jest: {
|
|
16
|
+
extensionsToTreatAsEsm: ['.ts', '.tsx'],
|
|
17
|
+
moduleNameMapper: {
|
|
18
|
+
'^@nlabs/(.*)$': '<rootDir>/node_modules/@nlabs/$1'
|
|
19
|
+
},
|
|
11
20
|
testEnvironment: 'jsdom'
|
|
12
21
|
},
|
|
13
22
|
outputPath: 'lib',
|
|
14
23
|
targetEnvironment: 'web',
|
|
15
24
|
useESM: true,
|
|
16
25
|
useTypescript: true
|
|
17
|
-
};
|
|
26
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const MOCK_USER: {
|
|
2
|
+
userId: string;
|
|
3
|
+
username: string;
|
|
4
|
+
email: string;
|
|
5
|
+
password: string;
|
|
6
|
+
};
|
|
7
|
+
export declare const MOCK_SESSION: {
|
|
8
|
+
token: string;
|
|
9
|
+
expires: number;
|
|
10
|
+
issued: number;
|
|
11
|
+
userId: string;
|
|
12
|
+
username: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Start test GraphQL server
|
|
16
|
+
*/
|
|
17
|
+
export declare const startTestServer: (port?: number) => Promise<unknown>;
|
|
18
|
+
/**
|
|
19
|
+
* Stop test server
|
|
20
|
+
*/
|
|
21
|
+
export declare const stopTestServer: (server: any) => Promise<unknown>;
|
|
22
|
+
//# sourceMappingURL=testGraphQLServer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testGraphQLServer.d.ts","sourceRoot":"","sources":["../../../../src/__tests__/e2e/helpers/testGraphQLServer.ts"],"names":[],"mappings":"AA8CA,eAAO,MAAM,SAAS;;;;;CAKrB,CAAC;AAEF,eAAO,MAAM,YAAY;;;;;;CAMxB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,GAAU,aAAW,qBA6HhD,CAAC;AAUF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,WAAM,qBAIpC,CAAC"}
|