propro-utils 1.5.64 → 1.5.66

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.
@@ -102,7 +102,10 @@ async function createDefaultFolders(folderSchema, accountId) {
102
102
 
103
103
  const debugLog = (area, message, data = null) => {
104
104
  const timestamp = new Date().toISOString();
105
- console.log(`[${timestamp}] [${area}] ${message}`, data ? data : '');
105
+ console.log(
106
+ `[${timestamp}] [${area}] ${message}`,
107
+ data ? JSON.stringify(data, null, 2) : ''
108
+ );
106
109
  };
107
110
 
108
111
  const DEFAULT_THEME = {
@@ -113,142 +116,275 @@ const DEFAULT_THEME = {
113
116
  name: 'Default Theme',
114
117
  };
115
118
 
119
+ const timeoutPromise = (promise, timeout, name) => {
120
+ return Promise.race([
121
+ promise,
122
+ new Promise((_, reject) =>
123
+ setTimeout(
124
+ () =>
125
+ reject(new Error(`${name} operation timed out after ${timeout}ms`)),
126
+ timeout
127
+ )
128
+ ),
129
+ ]);
130
+ };
131
+
116
132
  const checkIfUserExists = async accountId => {
133
+ const startTime = Date.now();
117
134
  try {
135
+ if (!accountId) {
136
+ throw new Error('AccountId is required');
137
+ }
118
138
  debugLog('init', `Starting user check for accountId: ${accountId}`);
119
139
 
120
- // Parallel service initialization
121
- const [userSchema, userStyleSchema, folderSchema, Theme] =
122
- await Promise.all([
123
- ServiceManager.getService('UserSchema'),
124
- ServiceManager.getService('UserStyleSchema'),
125
- ServiceManager.getService('FolderSchema'),
126
- ServiceManager.getService('Theme'),
127
- ]);
128
-
129
- debugLog('services', 'All services initialized');
130
-
131
- // Find user and theme in parallel
132
- const [user, existingTheme] = await Promise.all([
133
- userSchema.findOne({ accountId }).populate('userGlobalStyles'),
134
- Theme.findOne({
135
- name: 'Default Theme',
136
- accountId,
137
- }),
138
- ]);
139
-
140
- debugLog('query', 'Initial queries complete', {
141
- userFound: !!user,
142
- themeFound: !!existingTheme,
143
- });
140
+ // Initialize services with timeout and individual error handling
141
+ let services;
142
+ try {
143
+ debugLog('services', 'Initializing services...');
144
144
 
145
- // Create or use existing theme
146
- const defaultTheme =
147
- existingTheme ||
148
- (await Theme.create({
149
- ...DEFAULT_THEME,
150
- id: uuidv4(),
151
- accountId,
152
- }));
145
+ // Wrap each service request in a proper Promise chain
146
+ const serviceRequests = [
147
+ Promise.resolve(ServiceManager.getService('UserSchema')).then(
148
+ service => service,
149
+ error => {
150
+ throw new Error(`Failed to get UserSchema: ${error.message}`);
151
+ }
152
+ ),
153
+ Promise.resolve(ServiceManager.getService('UserStyleSchema')).then(
154
+ service => service,
155
+ error => {
156
+ throw new Error(`Failed to get UserStyleSchema: ${error.message}`);
157
+ }
158
+ ),
159
+ Promise.resolve(ServiceManager.getService('FolderSchema')).then(
160
+ service => service,
161
+ error => {
162
+ throw new Error(`Failed to get FolderSchema: ${error.message}`);
163
+ }
164
+ ),
165
+ Promise.resolve(ServiceManager.getService('Theme')).then(
166
+ service => service,
167
+ error => {
168
+ throw new Error(`Failed to get Theme: ${error.message}`);
169
+ }
170
+ ),
171
+ ];
153
172
 
154
- debugLog('theme', 'Theme ready', { themeId: defaultTheme._id });
173
+ services = await timeoutPromise(
174
+ Promise.all(serviceRequests),
175
+ 5000,
176
+ 'Service initialization'
177
+ );
155
178
 
156
- if (user) {
157
- debugLog('user', 'Existing user found, updating if needed');
179
+ debugLog('services', 'Services initialized successfully', {
180
+ serviceCount: services.length,
181
+ initTime: Date.now() - startTime,
182
+ });
183
+ } catch (error) {
184
+ debugLog('error', 'Service initialization failed', {
185
+ error: error.message,
186
+ });
187
+ throw error;
188
+ }
158
189
 
159
- const updates = [];
190
+ const [userSchema, userStyleSchema, folderSchema, Theme] = services;
160
191
 
161
- // Collect necessary updates
162
- if (!user.theme) {
163
- user.theme = defaultTheme._id;
164
- updates.push('theme');
165
- }
192
+ // Find user and theme with timeout
193
+ let user, existingTheme;
194
+ try {
195
+ debugLog('query', 'Starting user and theme queries');
196
+ [user, existingTheme] = await timeoutPromise(
197
+ Promise.all([
198
+ userSchema
199
+ .findOne({ accountId })
200
+ .populate('userGlobalStyles')
201
+ .exec()
202
+ .catch(e => {
203
+ throw new Error(`Failed to find user: ${e.message}`);
204
+ }),
205
+ Theme.findOne({
206
+ name: 'Default Theme',
207
+ accountId,
208
+ })
209
+ .exec()
210
+ .catch(e => {
211
+ throw new Error(`Failed to find theme: ${e.message}`);
212
+ }),
213
+ ]),
214
+ 5000,
215
+ 'Initial queries'
216
+ );
166
217
 
167
- if (!user.userGlobalStyles) {
168
- user.userGlobalStyles = await createUserGlobalStyles(
169
- userStyleSchema,
170
- accountId
218
+ debugLog('query', 'Queries completed', {
219
+ userFound: !!user,
220
+ themeFound: !!existingTheme,
221
+ queryTime: Date.now() - startTime,
222
+ });
223
+ } catch (error) {
224
+ debugLog('error', 'Query operations failed', { error: error.message });
225
+ throw error;
226
+ }
227
+
228
+ // Create or use existing theme
229
+ let defaultTheme;
230
+ try {
231
+ if (!existingTheme) {
232
+ debugLog('theme', 'Creating new theme');
233
+ defaultTheme = await timeoutPromise(
234
+ Theme.create({
235
+ ...DEFAULT_THEME,
236
+ id: uuidv4(),
237
+ accountId,
238
+ }),
239
+ 5000,
240
+ 'Theme creation'
171
241
  );
172
- updates.push('userGlobalStyles');
173
- } else if (user.userGlobalStyles.styleShortcuts.length === 0) {
174
- user.userGlobalStyles.styleShortcuts = defaultUserGlobalStyleShortcuts;
175
- await user.userGlobalStyles.save();
242
+ debugLog('theme', 'New theme created', { themeId: defaultTheme._id });
243
+ } else {
244
+ defaultTheme = existingTheme;
245
+ debugLog('theme', 'Using existing theme', {
246
+ themeId: defaultTheme._id,
247
+ });
176
248
  }
249
+ } catch (error) {
250
+ debugLog('error', 'Theme operation failed', { error: error.message });
251
+ throw error;
252
+ }
177
253
 
178
- // Check folders only if needed
179
- const userFolders = await folderSchema.find(
180
- { user_id: user.id },
181
- { name: 1 }
182
- );
183
- const userFolderNames = new Set(userFolders.map(f => f.name));
184
- const foldersToCreate = defaultFolders.filter(
185
- f => !userFolderNames.has(f.name)
186
- );
254
+ if (user) {
255
+ debugLog('user', 'Processing existing user');
256
+ const updates = [];
257
+
258
+ try {
259
+ // Theme update if needed
260
+ if (!user.theme) {
261
+ debugLog('update', 'Adding theme to user');
262
+ user.theme = defaultTheme._id;
263
+ updates.push('theme');
264
+ }
265
+
266
+ // Global styles update if needed
267
+ if (!user.userGlobalStyles) {
268
+ debugLog('update', 'Creating user global styles');
269
+ user.userGlobalStyles = await timeoutPromise(
270
+ createUserGlobalStyles(userStyleSchema, accountId),
271
+ 5000,
272
+ 'Global styles creation'
273
+ );
274
+ updates.push('userGlobalStyles');
275
+ } else if (user.userGlobalStyles.styleShortcuts.length === 0) {
276
+ debugLog('update', 'Updating empty style shortcuts');
277
+ user.userGlobalStyles.styleShortcuts =
278
+ defaultUserGlobalStyleShortcuts;
279
+ await timeoutPromise(
280
+ user.userGlobalStyles.save(),
281
+ 5000,
282
+ 'Style shortcuts update'
283
+ );
284
+ }
187
285
 
188
- if (foldersToCreate.length > 0) {
189
- debugLog(
190
- 'folders',
191
- `Creating ${foldersToCreate.length} missing folders`
286
+ // Folder checks
287
+ debugLog('folders', 'Checking user folders');
288
+ const userFolders = await timeoutPromise(
289
+ folderSchema.find({ user_id: user.id }, { name: 1 }),
290
+ 5000,
291
+ 'Folder query'
192
292
  );
193
- await Promise.all(
194
- foldersToCreate.map(folder =>
195
- folderSchema.create({
196
- ...folder,
197
- user_id: user.id,
198
- })
199
- )
293
+
294
+ const userFolderNames = new Set(userFolders.map(f => f.name));
295
+ const foldersToCreate = defaultFolders.filter(
296
+ f => !userFolderNames.has(f.name)
200
297
  );
201
- }
202
298
 
203
- // Save user only if there were updates
204
- if (updates.length > 0) {
205
- debugLog('update', `Saving user updates: ${updates.join(', ')}`);
206
- await user.save();
299
+ if (foldersToCreate.length > 0) {
300
+ debugLog('folders', 'Creating missing folders', {
301
+ count: foldersToCreate.length,
302
+ });
303
+ await timeoutPromise(
304
+ Promise.all(
305
+ foldersToCreate.map(folder =>
306
+ folderSchema.create({
307
+ ...folder,
308
+ user_id: user.id,
309
+ })
310
+ )
311
+ ),
312
+ 5000,
313
+ 'Folder creation'
314
+ );
315
+ }
316
+
317
+ // Save user if there were updates
318
+ if (updates.length > 0) {
319
+ debugLog('update', 'Saving user updates', { updates });
320
+ await timeoutPromise(user.save(), 5000, 'User save');
321
+ }
322
+ } catch (error) {
323
+ debugLog('error', 'User update operations failed', {
324
+ error: error.message,
325
+ });
326
+ throw error;
207
327
  }
208
328
 
209
- debugLog('complete', 'Existing user processed successfully');
329
+ debugLog('complete', 'Existing user processed', {
330
+ userId: user.id,
331
+ totalTime: Date.now() - startTime,
332
+ });
210
333
  return user;
211
334
  }
212
335
 
213
- debugLog('create', 'Creating new user');
336
+ // Create new user
337
+ try {
338
+ debugLog('create', 'Creating new user');
339
+ const userGlobalStyles = await timeoutPromise(
340
+ createUserGlobalStyles(userStyleSchema, accountId),
341
+ 5000,
342
+ 'Global styles creation'
343
+ );
214
344
 
215
- // Create new user with all required relations
216
- const userGlobalStyles = await createUserGlobalStyles(
217
- userStyleSchema,
218
- accountId
219
- );
345
+ const newUserId = uuidv4();
220
346
 
221
- const [newUser, newFolders] = await Promise.all([
222
- userSchema.create({
223
- accountId,
224
- id: uuidv4(),
225
- verified: false,
226
- userGlobalStyles: userGlobalStyles._id,
227
- theme: defaultTheme._id,
228
- }),
229
- createDefaultFolders(folderSchema, uuidv4()), // Pass the new user ID
230
- ]);
231
-
232
- newUser.folders = newFolders.map(folder => folder._id);
233
- await newUser.save();
234
-
235
- debugLog('complete', 'New user created successfully', {
236
- userId: newUser.id,
237
- });
238
- return newUser;
347
+ const [newUser, newFolders] = await timeoutPromise(
348
+ Promise.all([
349
+ userSchema.create({
350
+ accountId,
351
+ id: newUserId,
352
+ verified: false,
353
+ userGlobalStyles: userGlobalStyles._id,
354
+ theme: defaultTheme._id,
355
+ }),
356
+ createDefaultFolders(folderSchema, newUserId),
357
+ ]),
358
+ 5000,
359
+ 'User and folders creation'
360
+ );
361
+
362
+ newUser.folders = newFolders.map(folder => folder._id);
363
+ await timeoutPromise(newUser.save(), 5000, 'New user save');
364
+
365
+ debugLog('complete', 'New user created', {
366
+ userId: newUser.id,
367
+ totalTime: Date.now() - startTime,
368
+ });
369
+ return newUser;
370
+ } catch (error) {
371
+ debugLog('error', 'User creation failed', { error: error.message });
372
+ throw error;
373
+ }
239
374
  } catch (error) {
375
+ const totalTime = Date.now() - startTime;
240
376
  debugLog('error', 'Operation failed', {
241
377
  error: error.message,
242
378
  stack: error.stack,
379
+ totalTime,
243
380
  });
244
381
 
245
- // Throw error with original cause and context
246
- throw new Error('Failed to get or create user', {
382
+ throw new Error(`Failed to get or create user: ${error.message}`, {
247
383
  cause: error,
248
- accountId,
249
384
  });
250
385
  }
251
386
  };
387
+
252
388
  module.exports = {
253
389
  getAccountProfile,
254
390
  checkIfUserExists,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "propro-utils",
3
- "version": "1.5.64",
3
+ "version": "1.5.66",
4
4
  "description": "Auth middleware for propro-auth",
5
5
  "main": "src/index.js",
6
6
  "scripts": {