@nlabs/metropolisjs 1.0.7 → 1.1.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.
@@ -1,27 +1,33 @@
1
1
  /**
2
2
  * Example: Using the Factory Pattern in MetropolisJS
3
- *
3
+ *
4
4
  * This file demonstrates how to use the new consolidated action factory
5
5
  * instead of individual createXxxActions functions.
6
6
  */
7
7
 
8
- import type { FluxFramework } from '@nlabs/arkhamjs';
9
- import { createAction, createActions, createAllActions } from '../src/utils/actionFactory';
8
+ import {createAction, createActions, createAllActions} from '../src/utils/actionFactory.js';
9
+
10
+ import type {FluxFramework} from '@nlabs/arkhamjs';
11
+ import type {PostType} from '../src/adapters/postAdapter/postAdapter.js';
12
+ import type {User} from '../src/adapters/userAdapter/userAdapter.js';
13
+
14
+ const getErrorMessage = (error: unknown): string => (
15
+ error instanceof Error ? error.message : 'An unknown error occurred'
16
+ );
10
17
 
11
18
  // Example 1: Basic Usage
12
19
  export const basicUsage = (flux: FluxFramework) => {
13
20
  // 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;
21
+ const userActions = createAction('user', flux);
22
+ const postActions = createAction('post', flux);
17
23
 
18
24
  // Use actions normally
19
25
  const addUser = async () => {
20
- const user = await userActions.add({
21
- username: 'john_doe',
26
+ const user = await userActions.addUser({
22
27
  email: 'john@example.com',
23
28
  firstName: 'John',
24
- lastName: 'Doe'
29
+ lastName: 'Doe',
30
+ username: 'john_doe'
25
31
  });
26
32
  return user;
27
33
  };
@@ -40,20 +46,21 @@ export const basicUsage = (flux: FluxFramework) => {
40
46
  // Example 2: Custom Adapter with Business Logic
41
47
  export const customAdapterUsage = (flux: FluxFramework) => {
42
48
  // Custom user adapter that adds business logic
43
- const businessUserAdapter = (input: unknown, options?: any) => {
44
- const user = input as any;
45
-
49
+ const businessUserAdapter = (input: unknown): User => {
50
+ const user = input as User;
51
+ const email = user.email || '';
52
+
46
53
  // Business validation
47
- if (user.email && !user.email.includes('@company.com')) {
54
+ if(email && !email.includes('@company.com')) {
48
55
  throw new Error('Only company emails are allowed');
49
56
  }
50
-
57
+
51
58
  // Add computed fields
52
59
  return {
53
60
  ...user,
61
+ department: email.split('@')[0]?.split('.')[1] || 'general',
54
62
  fullName: `${user.firstName || ''} ${user.lastName || ''}`.trim(),
55
- isAdmin: user.userAccess >= 3,
56
- department: user.email?.split('@')[0]?.split('.')[1] || 'general'
63
+ isAdmin: (user.userAccess || 0) >= 3
57
64
  };
58
65
  };
59
66
 
@@ -61,8 +68,8 @@ export const customAdapterUsage = (flux: FluxFramework) => {
61
68
  const userActions = createAction('user', flux, {
62
69
  userAdapter: businessUserAdapter,
63
70
  userAdapterOptions: {
64
- strict: true,
65
- environment: 'production'
71
+ environment: 'production',
72
+ strict: true
66
73
  }
67
74
  });
68
75
 
@@ -71,73 +78,72 @@ export const customAdapterUsage = (flux: FluxFramework) => {
71
78
 
72
79
  // Example 3: Runtime Adapter Updates
73
80
  export const runtimeUpdates = (flux: FluxFramework) => {
74
- const userActions = createAction('user', flux) as any;
81
+ const userActions = createAction('user', flux);
75
82
 
76
83
  // Update adapter at runtime
77
84
  const updateToStrictMode = () => {
78
85
  userActions.updateUserAdapterOptions({
79
- strict: true,
80
- environment: 'production'
86
+ environment: 'production',
87
+ strict: true
81
88
  });
82
89
  };
83
90
 
84
91
  // Add custom validation at runtime
85
92
  const addCustomValidation = () => {
86
- userActions.updateUserAdapter((input, options) => {
87
- const user = input as any;
88
-
93
+ userActions.updateUserAdapter((input) => {
94
+ const user = input as User;
95
+
89
96
  // Additional runtime validation
90
- if (user.age && user.age < 18) {
97
+ if(user.age && user.age < 18) {
91
98
  throw new Error('User must be 18 or older');
92
99
  }
93
-
100
+
94
101
  return user;
95
102
  });
96
103
  };
97
104
 
98
- return {updateToStrictMode, addCustomValidation, userActions};
105
+ return {addCustomValidation, updateToStrictMode, userActions};
99
106
  };
100
107
 
101
108
  // Example 4: Testing with Mock Adapters
102
109
  export const testingExample = (flux: FluxFramework) => {
103
110
  // Mock adapter for testing
104
- const mockUserAdapter = Object.assign((input: unknown) => {
105
- mockUserAdapter.calls.push(input);
111
+ const calls: unknown[] = [];
112
+ const mockUserAdapter = (input: unknown) => {
113
+ calls.push(input);
106
114
  return {
107
115
  ...(input as Record<string, unknown>),
108
116
  id: 'mock-user-id',
109
- validated: true,
110
- timestamp: new Date().toISOString()
117
+ timestamp: new Date().toISOString(),
118
+ validated: true
111
119
  };
112
- }, {
113
- calls: [] as unknown[]
114
- });
120
+ };
115
121
 
116
122
  const userActions = createAction('user', flux, {
117
123
  userAdapter: mockUserAdapter
118
- }) as any;
124
+ });
119
125
 
120
126
  // Test that adapter was called
121
127
  const testUserCreation = async () => {
122
- const user = await userActions.add({
123
- username: 'test_user',
124
- email: 'test@example.com'
128
+ const user = await userActions.addUser({
129
+ email: 'test@example.com',
130
+ username: 'test_user'
125
131
  });
126
132
 
127
- if(mockUserAdapter.calls.length === 0 || user.id !== 'mock-user-id' || user.validated !== true) {
133
+ if(calls.length === 0 || user.id !== 'mock-user-id' || user.validated !== true) {
128
134
  throw new Error('Mock adapter validation failed');
129
135
  }
130
136
  };
131
137
 
132
- return {userActions, testUserCreation};
138
+ return {testUserCreation, userActions};
133
139
  };
134
140
 
135
141
  // Example 5: Multiple Adapters with Different Configurations
136
142
  export const multipleAdapters = (flux: FluxFramework) => {
137
143
  // User adapter with strict validation
138
144
  const strictUserAdapter = (input: unknown) => {
139
- const user = input as any;
140
- if (!user.username || !user.email) {
145
+ const user = input as User;
146
+ if(!user.username || !user.email) {
141
147
  throw new Error('Username and email are required');
142
148
  }
143
149
  return user;
@@ -145,8 +151,8 @@ export const multipleAdapters = (flux: FluxFramework) => {
145
151
 
146
152
  // Post adapter with content validation
147
153
  const contentPostAdapter = (input: unknown) => {
148
- const post = input as any;
149
- if (post.content && post.content.length > 1000) {
154
+ const post = input as PostType;
155
+ if(post.content && post.content.length > 1000) {
150
156
  throw new Error('Post content too long');
151
157
  }
152
158
  return post;
@@ -156,44 +162,44 @@ export const multipleAdapters = (flux: FluxFramework) => {
156
162
  const userActions = createAction('user', flux, {
157
163
  userAdapter: strictUserAdapter,
158
164
  userAdapterOptions: {strict: true}
159
- }) as any;
165
+ });
160
166
 
161
167
  const postActions = createAction('post', flux, {
162
168
  postAdapter: contentPostAdapter,
163
169
  postAdapterOptions: {environment: 'development'}
164
- }) as any;
170
+ });
165
171
 
166
- return {userActions, postActions};
172
+ return {postActions, userActions};
167
173
  };
168
174
 
169
175
  // Example 6: Error Handling
170
176
  export const errorHandling = (flux: FluxFramework) => {
171
177
  const userActions = createAction('user', flux, {
172
178
  userAdapterOptions: {
173
- strict: true,
174
179
  customValidation: (input) => {
175
- const user = input as any;
176
-
180
+ const user = input as User;
181
+
177
182
  // Custom error handling
178
- if (user.username && user.username.length < 3) {
183
+ if(user.username && user.username.length < 3) {
179
184
  throw new Error('Username must be at least 3 characters');
180
185
  }
181
-
182
- if (user.email && !user.email.includes('@')) {
186
+
187
+ if(user.email && !user.email.includes('@')) {
183
188
  throw new Error('Invalid email format');
184
189
  }
185
-
190
+
186
191
  return user;
187
- }
192
+ },
193
+ strict: true
188
194
  }
189
- }) as any;
195
+ });
190
196
 
191
- const createUserWithErrorHandling = async (userData: any) => {
197
+ const createUserWithErrorHandling = async (userData: Partial<User>) => {
192
198
  try {
193
- const user = await userActions.add(userData);
199
+ const user = await userActions.addUser(userData);
194
200
  return {success: true, user};
195
- } catch (error) {
196
- return {success: false, error: error.message};
201
+ } catch(error) {
202
+ return {error: getErrorMessage(error), success: false};
197
203
  }
198
204
  };
199
205
 
@@ -204,45 +210,46 @@ export const errorHandling = (flux: FluxFramework) => {
204
210
  export const multipleActionsExample = (flux: FluxFramework) => {
205
211
  // Create multiple actions at once
206
212
  const actions = createActions(['user', 'post', 'message'], flux, {
207
- user: {
208
- userAdapterOptions: { strict: true }
209
- },
210
213
  post: {
211
- postAdapter: (input: any) => {
212
- if (input.content && input.content.length > 1000) {
214
+ postAdapter: (input: unknown) => {
215
+ const post = input as PostType;
216
+ if(post.content && post.content.length > 1000) {
213
217
  throw new Error('Post content too long');
214
218
  }
215
- return input;
219
+ return post;
216
220
  }
221
+ },
222
+ user: {
223
+ userAdapterOptions: {strict: true}
217
224
  }
218
225
  });
219
226
 
220
- const createUserAndPost = async (userData: any, postData: any) => {
221
- const user = await actions.user.add(userData);
227
+ const createUserAndPost = async (userData: Partial<User>, postData: Partial<PostType>) => {
228
+ const user = await actions.user.addUser(userData);
222
229
  const post = await actions.post.add({
223
230
  ...postData,
224
231
  userId: user.userId
225
232
  });
226
- return { user, post };
233
+ return {post, user};
227
234
  };
228
235
 
229
- return { actions, createUserAndPost };
236
+ return {actions, createUserAndPost};
230
237
  };
231
238
 
232
239
  // Example 8: All Actions Creation
233
240
  export const allActionsExample = (flux: FluxFramework) => {
234
241
  // Create all available actions
235
242
  const allActions = createAllActions(flux, {
236
- user: { userAdapterOptions: { strict: true } },
237
- post: { postAdapterOptions: { environment: 'production' } },
238
- image: { imageAdapterOptions: { allowPartial: true } }
243
+ image: {imageAdapterOptions: {allowPartial: true}},
244
+ post: {postAdapterOptions: {environment: 'production'}},
245
+ user: {userAdapterOptions: {strict: true}}
239
246
  });
240
247
 
241
248
  const comprehensiveWorkflow = async () => {
242
249
  // Create user
243
- const user = await allActions.user.add({
244
- username: 'jane_doe',
245
- email: 'jane@example.com'
250
+ const user = await allActions.user.addUser({
251
+ email: 'jane@example.com',
252
+ username: 'jane_doe'
246
253
  });
247
254
 
248
255
  // Create post
@@ -263,8 +270,8 @@ export const allActionsExample = (flux: FluxFramework) => {
263
270
  recipientId: user.userId
264
271
  });
265
272
 
266
- return { user, post, image };
273
+ return {image, post, user};
267
274
  };
268
275
 
269
- return { allActions, comprehensiveWorkflow };
276
+ return {allActions, comprehensiveWorkflow};
270
277
  };
@@ -2,13 +2,15 @@
2
2
  * Example of handling signup errors in MetropolisJS
3
3
  */
4
4
  import {FluxFramework} from '@nlabs/arkhamjs';
5
- import type {userActions} from '../src/actions/userActions/userActions';
6
- import {USER_CONSTANTS} from '../src/stores/userStore';
7
- import {createAction} from '../src/utils/actionFactory';
5
+
6
+ import {USER_CONSTANTS} from '../src/stores/userStore.js';
7
+ import {createAction} from '../src/utils/actionFactory.js';
8
+
9
+ import type {UserActions} from '../src/actions/userActions/userActions.js';
8
10
 
9
11
  // Create a flux instance and user actions
10
12
  const flux = new FluxFramework();
11
- const userActions = createAction('user', flux) as unknown as userActions;
13
+ const userActions = createAction('user', flux) as unknown as UserActions;
12
14
 
13
15
  /**
14
16
  * Example 1: Basic error handling with try/catch
@@ -18,9 +20,9 @@ const handleAddWithTryCatch = async (userData: any) => {
18
20
  const user = await userActions.addUser(userData);
19
21
  console.log('Add successful:', user);
20
22
  return {success: true, user};
21
- } catch (error) {
23
+ } catch(error) {
22
24
  console.error('Add failed:', error.message);
23
- return {success: false, error: error.message};
25
+ return {error: error.message, success: false};
24
26
  }
25
27
  };
26
28
 
@@ -31,25 +33,25 @@ const handleSignUpWithFlux = async (userData: any) => {
31
33
  // Set up a listener for signup success
32
34
  const onSignUpSuccess = (payload: any) => {
33
35
  console.log('Signup successful:', payload.user);
34
- flux.removeListener(USER_CONSTANTS.SIGN_UP_SUCCESS, onSignUpSuccess);
35
- flux.removeListener(USER_CONSTANTS.SIGN_UP_ERROR, onSignUpError);
36
+ flux.off(USER_CONSTANTS.SIGN_UP_SUCCESS, onSignUpSuccess);
37
+ flux.off(USER_CONSTANTS.SIGN_UP_ERROR, onSignUpError);
36
38
  };
37
39
 
38
40
  // Set up a listener for signup error
39
41
  const onSignUpError = (payload: any) => {
40
42
  console.error('Signup failed:', payload.error.message);
41
- flux.removeListener(USER_CONSTANTS.SIGN_UP_SUCCESS, onSignUpSuccess);
42
- flux.removeListener(USER_CONSTANTS.SIGN_UP_ERROR, onSignUpError);
43
+ flux.off(USER_CONSTANTS.SIGN_UP_SUCCESS, onSignUpSuccess);
44
+ flux.off(USER_CONSTANTS.SIGN_UP_ERROR, onSignUpError);
43
45
  };
44
46
 
45
47
  // Add listeners
46
- flux.addListener(USER_CONSTANTS.SIGN_UP_SUCCESS, onSignUpSuccess);
47
- flux.addListener(USER_CONSTANTS.SIGN_UP_ERROR, onSignUpError);
48
+ flux.on(USER_CONSTANTS.SIGN_UP_SUCCESS, onSignUpSuccess);
49
+ flux.on(USER_CONSTANTS.SIGN_UP_ERROR, onSignUpError);
48
50
 
49
51
  // Attempt signup
50
52
  try {
51
53
  await userActions.signUp(userData);
52
- } catch (error) {
54
+ } catch(error) {
53
55
  // Error is already handled by the flux listener
54
56
  // This catch is just to prevent the error from propagating
55
57
  }
@@ -62,39 +64,38 @@ const handleSignUpWithValidation = async (userData: any) => {
62
64
  // Perform custom validation
63
65
  const errors: string[] = [];
64
66
 
65
- if (!userData.email || !userData.email.includes('@')) {
67
+ if(!userData.email || !userData.email.includes('@')) {
66
68
  errors.push('Invalid email format');
67
69
  }
68
70
 
69
- if (!userData.password || userData.password.length < 8) {
71
+ if(!userData.password || userData.password.length < 8) {
70
72
  errors.push('Password must be at least 8 characters');
71
73
  }
72
74
 
73
- if (!userData.username || userData.username.length < 3) {
75
+ if(!userData.username || userData.username.length < 3) {
74
76
  errors.push('Username must be at least 3 characters');
75
77
  }
76
78
 
77
79
  // If validation fails, return errors
78
- if (errors.length > 0) {
79
- return {success: false, errors};
80
+ if(errors.length > 0) {
81
+ return {errors, success: false};
80
82
  }
81
83
 
82
84
  // If validation passes, attempt signup
83
85
  try {
84
86
  const user = await userActions.signUp(userData);
85
87
  return {success: true, user};
86
- } catch (error) {
88
+ } catch(error) {
87
89
  // Handle specific error types
88
- if (error.message.includes('already exists')) {
89
- return {success: false, errors: ['Username or email already in use']};
90
+ if(error.message.includes('already exists')) {
91
+ return {errors: ['Username or email already in use'], success: false};
90
92
  }
91
93
 
92
- return {success: false, errors: [error.message]};
94
+ return {errors: [error.message], success: false};
93
95
  }
94
96
  };
95
97
 
96
98
  // Export examples
97
99
  export {
98
- handleSignUpWithFlux, handleSignUpWithTryCatch, handleSignUpWithValidation
100
+ handleAddWithTryCatch, handleSignUpWithFlux, handleSignUpWithValidation
99
101
  };
100
-