@nlabs/metropolisjs 0.1.1 → 0.1.2
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/FACTORY_PATTERN_GUIDE.md +244 -0
- package/README.md +332 -0
- package/examples/factory-pattern-usage.ts +283 -0
- package/lex.config.mjs +17 -0
- package/lib/actions/eventActions/eventActions.d.ts +45 -0
- package/lib/actions/eventActions/eventActions.js +2 -0
- package/lib/actions/imageActions/imageActions.d.ts +56 -0
- package/lib/actions/imageActions/imageActions.js +2 -0
- package/lib/actions/index.d.ts +9 -0
- package/lib/actions/index.js +2 -0
- package/lib/actions/locationActions/locationActions.d.ts +58 -0
- package/lib/actions/locationActions/locationActions.js +2 -0
- package/lib/actions/messageActions/messageActions.d.ts +54 -0
- package/lib/actions/messageActions/messageActions.js +2 -0
- package/lib/actions/postActions/postActions.d.ts +56 -0
- package/lib/actions/postActions/postActions.js +2 -0
- package/lib/actions/profileActions/profileActions.d.ts +50 -0
- package/lib/actions/profileActions/profileActions.js +2 -0
- package/lib/actions/reactionActions/reactionActions.d.ts +52 -0
- package/lib/actions/reactionActions/reactionActions.js +2 -0
- package/lib/actions/sseActions/sseActions.d.ts +37 -0
- package/lib/actions/sseActions/sseActions.js +2 -0
- package/lib/actions/tagActions/tagActions.d.ts +55 -0
- package/lib/actions/tagActions/tagActions.js +2 -0
- package/lib/actions/userActions/userActions.d.ts +131 -0
- package/lib/actions/userActions/userActions.js +2 -0
- package/lib/actions/websocketActions/websocketActions.d.ts +31 -0
- package/lib/actions/websocketActions/websocketActions.js +2 -0
- package/lib/adapters/arangoAdapter/arangoAdapter.d.ts +20 -0
- package/lib/adapters/arangoAdapter/arangoAdapter.js +2 -0
- package/lib/adapters/contentAdapter/contentAdapter.d.ts +31 -0
- package/lib/adapters/contentAdapter/contentAdapter.js +2 -0
- package/lib/adapters/conversationAdapter/conversationAdapter.d.ts +23 -0
- package/lib/adapters/conversationAdapter/conversationAdapter.js +2 -0
- package/lib/adapters/eventAdapter/eventAdapter.d.ts +43 -0
- package/lib/adapters/eventAdapter/eventAdapter.js +2 -0
- package/lib/adapters/fileAdapter/fileAdapter.d.ts +29 -0
- package/lib/adapters/fileAdapter/fileAdapter.js +2 -0
- package/lib/adapters/imageAdapter/imageAdapter.d.ts +31 -0
- package/lib/adapters/imageAdapter/imageAdapter.js +2 -0
- package/lib/adapters/index.d.ts +16 -0
- package/lib/adapters/index.js +2 -0
- package/lib/adapters/locationAdapter/locationAdapter.d.ts +27 -0
- package/lib/adapters/locationAdapter/locationAdapter.js +2 -0
- package/lib/adapters/messageAdapter/messageAdapter.d.ts +27 -0
- package/lib/adapters/messageAdapter/messageAdapter.js +2 -0
- package/lib/adapters/personaAdapter/personaAdapter.d.ts +18 -0
- package/lib/adapters/personaAdapter/personaAdapter.js +2 -0
- package/lib/adapters/postAdapter/postAdapter.d.ts +32 -0
- package/lib/adapters/postAdapter/postAdapter.js +2 -0
- package/lib/adapters/profileAdapter/profileAdapter.d.ts +32 -0
- package/lib/adapters/profileAdapter/profileAdapter.js +2 -0
- package/lib/adapters/reactionAdapter/reactionAdapter.d.ts +20 -0
- package/lib/adapters/reactionAdapter/reactionAdapter.js +2 -0
- package/lib/adapters/reaktorAdapter/reaktorAdapter.d.ts +16 -0
- package/lib/adapters/reaktorAdapter/reaktorAdapter.js +2 -0
- package/lib/adapters/sessionAdapter/sessionAdapter.d.ts +23 -0
- package/lib/adapters/sessionAdapter/sessionAdapter.js +2 -0
- package/lib/adapters/tagAdapter/tagAdapter.d.ts +20 -0
- package/lib/adapters/tagAdapter/tagAdapter.js +2 -0
- package/lib/adapters/userAdapter/userAdapter.d.ts +55 -0
- package/lib/adapters/userAdapter/userAdapter.js +2 -0
- package/lib/config/index.d.ts +31 -0
- package/lib/config/index.js +2 -0
- package/lib/constants/MetropolisConstants.d.ts +14 -0
- package/lib/constants/MetropolisConstants.js +2 -0
- package/lib/graphql/message.d.ts +2 -0
- package/lib/graphql/message.js +18 -0
- package/lib/graphql/notification.d.ts +2 -0
- package/lib/graphql/notification.js +18 -0
- package/lib/graphql/session.d.ts +1 -0
- package/lib/graphql/session.js +16 -0
- package/lib/index.d.ts +29 -0
- package/lib/index.js +2 -0
- package/lib/stores/appStore.d.ts +22 -0
- package/lib/stores/appStore.js +2 -0
- package/lib/stores/eventStore.d.ts +34 -0
- package/lib/stores/eventStore.js +2 -0
- package/lib/stores/imageStore.d.ts +35 -0
- package/lib/stores/imageStore.js +2 -0
- package/lib/stores/index.d.ts +15 -0
- package/lib/stores/index.js +2 -0
- package/lib/stores/locationStore.d.ts +33 -0
- package/lib/stores/locationStore.js +2 -0
- package/lib/stores/messageStore.d.ts +36 -0
- package/lib/stores/messageStore.js +2 -0
- package/lib/stores/postStore.d.ts +33 -0
- package/lib/stores/postStore.js +2 -0
- package/lib/stores/profileStore.d.ts +24 -0
- package/lib/stores/profileStore.js +2 -0
- package/lib/stores/reactionStore.d.ts +24 -0
- package/lib/stores/reactionStore.js +2 -0
- package/lib/stores/tagStore.d.ts +31 -0
- package/lib/stores/tagStore.js +2 -0
- package/lib/stores/userStore.d.ts +73 -0
- package/lib/stores/userStore.js +2 -0
- package/lib/stores/websocketStore.d.ts +23 -0
- package/lib/stores/websocketStore.js +2 -0
- package/lib/utils/MetropolisProvider.d.ts +34 -0
- package/lib/utils/MetropolisProvider.js +2 -0
- package/lib/utils/actionFactory.d.ts +22 -0
- package/lib/utils/actionFactory.js +2 -0
- package/lib/utils/api.d.ts +43 -0
- package/lib/utils/api.js +7 -0
- package/lib/utils/app.d.ts +6 -0
- package/lib/utils/app.js +2 -0
- package/lib/utils/baseActionFactory.d.ts +34 -0
- package/lib/utils/baseActionFactory.js +2 -0
- package/lib/utils/dateUtils.d.ts +2 -0
- package/lib/utils/dateUtils.js +2 -0
- package/lib/utils/file.d.ts +1 -0
- package/lib/utils/file.js +2 -0
- package/lib/utils/location.d.ts +9 -0
- package/lib/utils/location.js +2 -0
- package/lib/utils/useMetropolis.d.ts +12 -0
- package/lib/utils/useMetropolis.js +2 -0
- package/lib/utils/validatorFactory.d.ts +48 -0
- package/lib/utils/validatorFactory.js +2 -0
- package/package.json +33 -27
- package/tsconfig.lint.json +25 -0
- package/tsconfig.test.json +14 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# MetropolisJS Factory Pattern Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
MetropolisJS has been refactored to use a **factory function pattern** for actions instead of class-based approaches. This provides better functional programming practices, improved testability, and enhanced flexibility through dependency injection.
|
|
6
|
+
|
|
7
|
+
## Key Benefits
|
|
8
|
+
|
|
9
|
+
1. **Functional Programming**: Pure functions instead of classes with side effects
|
|
10
|
+
2. **Better Testability**: Easier to mock and test individual functions
|
|
11
|
+
3. **Composability**: Actions can be easily combined and extended
|
|
12
|
+
4. **Dependency Injection**: Custom adapters can be injected and merged with defaults
|
|
13
|
+
5. **Backward Compatibility**: Legacy class wrappers maintain existing API compatibility
|
|
14
|
+
|
|
15
|
+
## Basic Usage
|
|
16
|
+
|
|
17
|
+
### Before (Class-based)
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import {userActions} from '../actions/userActions';
|
|
21
|
+
|
|
22
|
+
const userActions = new userActions(flux);
|
|
23
|
+
const user = await userActions.add(userData);
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### After (Factory Pattern)
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import {createUserActions} from '../actions/userActions';
|
|
30
|
+
|
|
31
|
+
const userActions = createUserActions(flux);
|
|
32
|
+
const user = await userActions.add(userData);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Advanced Usage with Custom Adapters
|
|
36
|
+
|
|
37
|
+
### Custom Validation Adapter
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
// Custom adapter that extends default behavior
|
|
41
|
+
const customUserAdapter = (input: unknown, options?: UserAdapterOptions) => {
|
|
42
|
+
// input is already validated by default adapter
|
|
43
|
+
const user = input as any;
|
|
44
|
+
|
|
45
|
+
// Add business-specific validation
|
|
46
|
+
if (user.email && !user.email.includes('@company.com')) {
|
|
47
|
+
throw new Error('Only company emails allowed');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Add computed fields
|
|
51
|
+
return {
|
|
52
|
+
...user,
|
|
53
|
+
fullName: `${user.firstName || ''} ${user.lastName || ''}`.trim(),
|
|
54
|
+
isAdmin: user.userAccess >= 3
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const userActions = createUserActions(flux, {
|
|
59
|
+
userAdapter: customUserAdapter
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Configuration-based Adapters
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
const userActions = createUserActions(flux, {
|
|
67
|
+
userAdapterOptions: {
|
|
68
|
+
strict: true,
|
|
69
|
+
environment: 'production',
|
|
70
|
+
customValidation: (input) => {
|
|
71
|
+
// Additional validation logic
|
|
72
|
+
return input;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Runtime Adapter Updates
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
const userActions = createUserActions(flux);
|
|
82
|
+
|
|
83
|
+
// Update adapter at runtime
|
|
84
|
+
userActions.updateUserAdapter(customUserAdapter);
|
|
85
|
+
|
|
86
|
+
// Update options at runtime
|
|
87
|
+
userActions.updateUserAdapterOptions({
|
|
88
|
+
strict: true,
|
|
89
|
+
environment: 'production'
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Available Actions
|
|
94
|
+
|
|
95
|
+
All action files now export factory functions:
|
|
96
|
+
|
|
97
|
+
- `createUserActions(flux, options?)` - User management
|
|
98
|
+
- `createPostActions(flux, options?)` - Post management
|
|
99
|
+
- `createEventActions(flux, options?)` - Event management
|
|
100
|
+
- `createMessageActions(flux, options?)` - Messaging
|
|
101
|
+
- `createImageActions(flux, options?)` - Image handling
|
|
102
|
+
- `createLocationActions(flux, options?)` - Location services
|
|
103
|
+
- `createReactionActions(flux, options?)` - Reactions
|
|
104
|
+
- `createTagActions(flux, options?)` - Tag management
|
|
105
|
+
- `createWebsocketActions(flux)` - WebSocket connections
|
|
106
|
+
|
|
107
|
+
## Adapter Options Interface
|
|
108
|
+
|
|
109
|
+
All adapters support the same options interface:
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
interface AdapterOptions {
|
|
113
|
+
strict?: boolean; // Enable strict validation
|
|
114
|
+
allowPartial?: boolean; // Allow partial data
|
|
115
|
+
environment?: 'development' | 'production' | 'test';
|
|
116
|
+
customValidation?: (input: unknown) => unknown;
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Migration Guide
|
|
121
|
+
|
|
122
|
+
### Step 1: Update Imports
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
// Old
|
|
126
|
+
import {userActions} from '../actions/userActions';
|
|
127
|
+
|
|
128
|
+
// New
|
|
129
|
+
import {createUserActions} from '../actions/userActions';
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Step 2: Update Instantiation
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
// Old
|
|
136
|
+
const userActions = new userActions(flux, customAdapter);
|
|
137
|
+
|
|
138
|
+
// New
|
|
139
|
+
const userActions = createUserActions(flux, {
|
|
140
|
+
userAdapter: customAdapter
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Step 3: Update useMetropolis Hook
|
|
145
|
+
|
|
146
|
+
The `useMetropolis` hook has been updated to use the factory pattern:
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
// Old
|
|
150
|
+
return useMemo(() => ({
|
|
151
|
+
userActions: new userActions(flux, UserAdapter),
|
|
152
|
+
postActions: new PostActions(flux, PostAdapter),
|
|
153
|
+
// ...
|
|
154
|
+
}), [flux, UserAdapter, PostAdapter]);
|
|
155
|
+
|
|
156
|
+
// New
|
|
157
|
+
return useMemo(() => ({
|
|
158
|
+
userActions: createUserActions(flux, {
|
|
159
|
+
userAdapter: UserAdapter
|
|
160
|
+
}),
|
|
161
|
+
postActions: createPostActions(flux, {
|
|
162
|
+
postAdapter: PostAdapter
|
|
163
|
+
}),
|
|
164
|
+
// ...
|
|
165
|
+
}), [flux, UserAdapter, PostAdapter]);
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Backward Compatibility
|
|
169
|
+
|
|
170
|
+
Legacy class wrappers are provided for backward compatibility:
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
// Still works
|
|
174
|
+
import {userActionsClass} from '../actions/userActions';
|
|
175
|
+
const userActions = new userActionsClass(flux, options);
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Testing Examples
|
|
179
|
+
|
|
180
|
+
### Unit Testing Actions
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
import {createUserActions} from '../actions/userActions';
|
|
184
|
+
|
|
185
|
+
describe('userActions', () => {
|
|
186
|
+
let flux: FluxFramework;
|
|
187
|
+
let userActions: userActions;
|
|
188
|
+
|
|
189
|
+
beforeEach(() => {
|
|
190
|
+
flux = createMockFlux();
|
|
191
|
+
userActions = createUserActions(flux);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('should add user with validation', async () => {
|
|
195
|
+
const userData = {username: 'test', email: 'test@example.com'};
|
|
196
|
+
const result = await userActions.add(userData);
|
|
197
|
+
expect(result).toBeDefined();
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Testing with Custom Adapters
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
const mockAdapter = jest.fn((input) => ({
|
|
206
|
+
...input,
|
|
207
|
+
validated: true
|
|
208
|
+
}));
|
|
209
|
+
|
|
210
|
+
const userActions = createUserActions(flux, {
|
|
211
|
+
userAdapter: mockAdapter
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
expect(mockAdapter).toHaveBeenCalled();
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Best Practices
|
|
218
|
+
|
|
219
|
+
1. **Use Factory Functions**: Prefer `createXxxActions()` over class constructors
|
|
220
|
+
2. **Leverage Adapter Injection**: Use custom adapters for business logic
|
|
221
|
+
3. **Runtime Updates**: Use update methods for dynamic behavior changes
|
|
222
|
+
4. **Type Safety**: Always use TypeScript interfaces for better type checking
|
|
223
|
+
5. **Error Handling**: Custom adapters should throw meaningful errors
|
|
224
|
+
|
|
225
|
+
## Performance Considerations
|
|
226
|
+
|
|
227
|
+
- Factory functions are lightweight and create minimal overhead
|
|
228
|
+
- Adapter validation is only performed when needed
|
|
229
|
+
- Options are merged efficiently without deep cloning
|
|
230
|
+
- Legacy wrappers have minimal performance impact
|
|
231
|
+
|
|
232
|
+
## Future Enhancements
|
|
233
|
+
|
|
234
|
+
The factory pattern enables future enhancements:
|
|
235
|
+
|
|
236
|
+
- **Middleware Support**: Chain multiple adapters
|
|
237
|
+
- **Plugin System**: Load adapters dynamically
|
|
238
|
+
- **Caching**: Cache validated results
|
|
239
|
+
- **Async Adapters**: Support async validation logic
|
|
240
|
+
- **Schema Evolution**: Handle multiple adapter versions
|
|
241
|
+
|
|
242
|
+
## Conclusion
|
|
243
|
+
|
|
244
|
+
The factory pattern provides a more functional, testable, and flexible approach to action management in MetropolisJS. While maintaining backward compatibility, it opens up new possibilities for customization and extension.
|
package/README.md
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
# MetropolisJS: Seamless Frontend-Backend Integration Framework
|
|
2
|
+
|
|
3
|
+
> **The Ultimate Frontend Integration Library for Modern Web Applications**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@nlabs/metropolisjs)
|
|
6
|
+
[](https://www.npmjs.com/package/@nlabs/metropolisjs)
|
|
7
|
+
[](https://github.com/nitrogenlabs/metropolisjs/issues)
|
|
8
|
+
[](https://github.com/ellerbrock/typescript-badges/)
|
|
9
|
+
[](http://opensource.org/licenses/MIT)
|
|
10
|
+
[](https://discord.gg/Ttgev58)
|
|
11
|
+
|
|
12
|
+
MetropolisJS is the bridge that connects your frontend dreams to backend reality. Built on the powerful combination of **Reaktor** (backend services) and **ArkhamJS** (frontend data store), MetropolisJS provides a seamless, real-time integration layer that handles everything from user authentication to real-time messaging and notifications.
|
|
13
|
+
|
|
14
|
+
## 🚀 Why MetropolisJS?
|
|
15
|
+
|
|
16
|
+
### ✨ **Seamless Integration**
|
|
17
|
+
|
|
18
|
+
Connect your React frontend to Reaktor-powered backend services with zero configuration headaches. MetropolisJS handles all the complex data flow, state management, and real-time communication.
|
|
19
|
+
|
|
20
|
+
### 🔄 **Real-Time Everything**
|
|
21
|
+
|
|
22
|
+
Built-in WebSocket and Server-Sent Events (SSE) support for instant messaging, live notifications, and real-time data synchronization. Your users will never miss a beat.
|
|
23
|
+
|
|
24
|
+
### 🛡️ **Type-Safe & Reliable**
|
|
25
|
+
|
|
26
|
+
Full TypeScript support with comprehensive type definitions. Catch errors at compile time, not runtime.
|
|
27
|
+
|
|
28
|
+
### 🎯 **Developer Experience First**
|
|
29
|
+
|
|
30
|
+
Clean, intuitive APIs that make complex operations feel simple. Focus on building features, not boilerplate.
|
|
31
|
+
|
|
32
|
+
## 🎯 What Can You Build?
|
|
33
|
+
|
|
34
|
+
MetropolisJS powers applications that need:
|
|
35
|
+
|
|
36
|
+
- **🔐 User Authentication & Authorization**
|
|
37
|
+
- **💬 Real-Time Messaging Systems**
|
|
38
|
+
- **🔔 Live Notifications**
|
|
39
|
+
- **📱 Social Media Features** (posts, reactions, tags)
|
|
40
|
+
- **📍 Location-Based Services**
|
|
41
|
+
- **🖼️ Media Management** (images, files)
|
|
42
|
+
- **📅 Event Management**
|
|
43
|
+
- **👥 User Connections & Relationships**
|
|
44
|
+
|
|
45
|
+
## 🛠️ Quick Start
|
|
46
|
+
|
|
47
|
+
### Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npm install @nlabs/metropolisjs @nlabs/arkhamjs @nlabs/arkhamjs-utils-react
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Basic Setup
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
import React from 'react';
|
|
57
|
+
import {Metropolis} from '@nlabs/metropolisjs';
|
|
58
|
+
import {useMetropolis} from '@nlabs/metropolisjs';
|
|
59
|
+
|
|
60
|
+
const App = () => {
|
|
61
|
+
return (
|
|
62
|
+
<Metropolis config={{
|
|
63
|
+
environment: 'development',
|
|
64
|
+
// Your configuration here
|
|
65
|
+
}}>
|
|
66
|
+
<YourApp />
|
|
67
|
+
</Metropolis>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const YourApp = () => {
|
|
72
|
+
const {userActions, messageActions, websocketActions} = useMetropolis();
|
|
73
|
+
|
|
74
|
+
// Start building amazing features!
|
|
75
|
+
return <div>Your app content</div>;
|
|
76
|
+
};
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### User Authentication Example
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
const LoginForm = () => {
|
|
83
|
+
const {userActions} = useMetropolis();
|
|
84
|
+
const [username, setUsername] = useState('');
|
|
85
|
+
const [password, setPassword] = useState('');
|
|
86
|
+
|
|
87
|
+
const handleLogin = async () => {
|
|
88
|
+
try {
|
|
89
|
+
const session = await userActions.signIn(username, password);
|
|
90
|
+
console.log('User logged in successfully!', session);
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error('Login failed:', error);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<form onSubmit={handleLogin}>
|
|
98
|
+
<input
|
|
99
|
+
value={username}
|
|
100
|
+
onChange={(e) => setUsername(e.target.value)}
|
|
101
|
+
placeholder="Username"
|
|
102
|
+
/>
|
|
103
|
+
<input
|
|
104
|
+
type="password"
|
|
105
|
+
value={password}
|
|
106
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
107
|
+
placeholder="Password"
|
|
108
|
+
/>
|
|
109
|
+
<button type="submit">Sign In</button>
|
|
110
|
+
</form>
|
|
111
|
+
);
|
|
112
|
+
};
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Real-Time Messaging
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
const ChatComponent = () => {
|
|
119
|
+
const {messageActions, websocketActions} = useMetropolis();
|
|
120
|
+
const [messages, setMessages] = useState([]);
|
|
121
|
+
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
// Initialize WebSocket connection
|
|
124
|
+
websocketActions.wsInit();
|
|
125
|
+
|
|
126
|
+
// Load existing messages
|
|
127
|
+
messageActions.list().then(setMessages);
|
|
128
|
+
}, []);
|
|
129
|
+
|
|
130
|
+
const sendMessage = async (content) => {
|
|
131
|
+
await messageActions.add({ content });
|
|
132
|
+
// Message automatically appears in real-time for all connected users!
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<div>
|
|
137
|
+
{messages.map(message => (
|
|
138
|
+
<div key={message.messageId}>{message.content}</div>
|
|
139
|
+
))}
|
|
140
|
+
<button onClick={() => sendMessage('Hello World!')}>
|
|
141
|
+
Send Message
|
|
142
|
+
</button>
|
|
143
|
+
</div>
|
|
144
|
+
);
|
|
145
|
+
};
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## 🏗️ Architecture
|
|
149
|
+
|
|
150
|
+
MetropolisJS is built on a powerful three-layer architecture:
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
154
|
+
│ React App │ │ MetropolisJS │ │ Reaktor │
|
|
155
|
+
│ │◄──►│ │◄──►│ Backend │
|
|
156
|
+
│ UI Layer │ │ Integration │ │ Services │
|
|
157
|
+
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
158
|
+
│
|
|
159
|
+
▼
|
|
160
|
+
┌─────────────────┐
|
|
161
|
+
│ ArkhamJS │
|
|
162
|
+
│ Data Store │
|
|
163
|
+
│ │
|
|
164
|
+
└─────────────────┘
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### 🔧 Core Components
|
|
168
|
+
|
|
169
|
+
- **Actions**: Handle all API interactions and business logic
|
|
170
|
+
- **Adapters**: Transform data between frontend and backend formats
|
|
171
|
+
- **Stores**: Manage application state with ArkhamJS
|
|
172
|
+
- **WebSocket Actions**: Handle real-time communication
|
|
173
|
+
- **Configuration**: Flexible setup for any environment
|
|
174
|
+
|
|
175
|
+
## 📚 Available Actions
|
|
176
|
+
|
|
177
|
+
MetropolisJS provides comprehensive action classes for all your needs:
|
|
178
|
+
|
|
179
|
+
- **userActions**: Authentication, profiles, user management
|
|
180
|
+
- **messageActions**: Real-time messaging and conversations
|
|
181
|
+
- **postActions**: Social media posts and content
|
|
182
|
+
- **reactionActions**: Likes, reactions, and interactions
|
|
183
|
+
- **tagActions**: Content categorization and discovery
|
|
184
|
+
- **eventActions**: Event management and scheduling
|
|
185
|
+
- **imageActions**: Media upload and management
|
|
186
|
+
- **locationActions**: Geolocation and location-based features
|
|
187
|
+
- **websocketActions**: Real-time communication setup
|
|
188
|
+
|
|
189
|
+
## 🔌 Adapters
|
|
190
|
+
|
|
191
|
+
Customize data transformation with powerful adapters:
|
|
192
|
+
|
|
193
|
+
- **userAdapter**: User profiles and authentication data
|
|
194
|
+
- **messageAdapter**: Chat and messaging data
|
|
195
|
+
- **postAdapter**: Social media content
|
|
196
|
+
- **eventAdapter**: Event and scheduling data
|
|
197
|
+
- **imageAdapter**: Media and file data
|
|
198
|
+
- **locationAdapter**: Geolocation data
|
|
199
|
+
- **tagAdapter**: Categorization data
|
|
200
|
+
- **reactionAdapter**: User interaction data
|
|
201
|
+
|
|
202
|
+
## ⚡ Real-Time Features
|
|
203
|
+
|
|
204
|
+
### WebSocket Integration
|
|
205
|
+
|
|
206
|
+
```tsx
|
|
207
|
+
const {websocketActions} = useMetropolis();
|
|
208
|
+
|
|
209
|
+
// Initialize real-time connections
|
|
210
|
+
websocketActions.wsInit();
|
|
211
|
+
|
|
212
|
+
// Messages, notifications, and data updates
|
|
213
|
+
// are automatically synchronized across all clients
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Server-Sent Events
|
|
217
|
+
|
|
218
|
+
Built-in SSE support for lightweight real-time updates without the overhead of WebSocket connections.
|
|
219
|
+
|
|
220
|
+
## 🎨 Customization
|
|
221
|
+
|
|
222
|
+
### Custom Adapters
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
class CustomUserAdapter extends User {
|
|
226
|
+
// Override methods to customize data transformation
|
|
227
|
+
toJson() {
|
|
228
|
+
const data = super.toJson();
|
|
229
|
+
return {
|
|
230
|
+
...data,
|
|
231
|
+
displayName: `${data.firstName} ${data.lastName}`,
|
|
232
|
+
customField: 'custom value'
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Use custom adapter
|
|
238
|
+
const {userActions} = useMetropolis({
|
|
239
|
+
adapters: {
|
|
240
|
+
User: CustomUserAdapter
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Configuration
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
const config = {
|
|
249
|
+
environment: 'production',
|
|
250
|
+
app: {
|
|
251
|
+
session: {
|
|
252
|
+
maxMinutes: 1440, // 24 hours
|
|
253
|
+
minMinutes: 15
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
isAuth: () => {
|
|
257
|
+
// Custom authentication logic
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## 🚀 Performance Features
|
|
264
|
+
|
|
265
|
+
- **Debounced API calls** to prevent excessive requests
|
|
266
|
+
- **Intelligent caching** with ArkhamJS
|
|
267
|
+
- **Optimistic updates** for instant UI feedback
|
|
268
|
+
- **Connection pooling** for WebSocket efficiency
|
|
269
|
+
- **Lazy loading** support for large datasets
|
|
270
|
+
|
|
271
|
+
## 🔒 Security
|
|
272
|
+
|
|
273
|
+
- **Automatic token refresh** for seamless sessions
|
|
274
|
+
- **Secure WebSocket connections** with authentication
|
|
275
|
+
- **Input validation** and sanitization
|
|
276
|
+
- **CSRF protection** built-in
|
|
277
|
+
- **Session management** with configurable timeouts
|
|
278
|
+
|
|
279
|
+
## 📦 Installation & Setup
|
|
280
|
+
|
|
281
|
+
### Prerequisites
|
|
282
|
+
|
|
283
|
+
- Node.js 16+
|
|
284
|
+
- React 18+
|
|
285
|
+
- TypeScript 4.5+
|
|
286
|
+
|
|
287
|
+
### Full Installation
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
# Install MetropolisJS and dependencies
|
|
291
|
+
npm install @nlabs/metropolisjs @nlabs/arkhamjs @nlabs/arkhamjs-utils-react
|
|
292
|
+
|
|
293
|
+
# For development
|
|
294
|
+
npm install --save-dev @types/react @types/node
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Environment Setup
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
# Set your environment variables
|
|
301
|
+
export NODE_ENV=development
|
|
302
|
+
export REAKTOR_API_URL=your-reaktor-backend-url
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## 🤝 Contributing
|
|
306
|
+
|
|
307
|
+
We love contributions! Here's how you can help:
|
|
308
|
+
|
|
309
|
+
1. **Fork** the repository
|
|
310
|
+
2. **Create** a feature branch (`git checkout -b feature/amazing-feature`)
|
|
311
|
+
3. **Commit** your changes (`git commit -m 'Add amazing feature'`)
|
|
312
|
+
4. **Push** to the branch (`git push origin feature/amazing-feature`)
|
|
313
|
+
5. **Open** a Pull Request
|
|
314
|
+
|
|
315
|
+
## 📄 License
|
|
316
|
+
|
|
317
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
318
|
+
|
|
319
|
+
## 🆘 Support
|
|
320
|
+
|
|
321
|
+
- **Documentation**: [Coming Soon]
|
|
322
|
+
- **Issues**: [GitHub Issues](https://github.com/nitrogenlabs/metropolisjs/issues)
|
|
323
|
+
- **Discussions**: [GitHub Discussions](https://github.com/nitrogenlabs/metropolisjs/discussions)
|
|
324
|
+
- **Email**: <giraldo@nitrogenlabs.com>
|
|
325
|
+
|
|
326
|
+
## 🏢 About Nitrogen Labs
|
|
327
|
+
|
|
328
|
+
MetropolisJS is proudly developed by [Nitrogen Labs](http://nitrogenlabs.com), a team passionate about building powerful, developer-friendly tools that make web development faster, more reliable, and more enjoyable.
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
**Ready to build the future?** Start with MetropolisJS today and experience the power of seamless frontend-backend integration! 🚀
|