indusagi-coding-agent 0.1.28 → 0.1.30

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.
Files changed (147) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/LICENSE.md +22 -0
  3. package/README.md +2 -0
  4. package/dist/core/messages.d.ts +1 -76
  5. package/dist/core/messages.d.ts.map +1 -1
  6. package/dist/core/messages.js +1 -122
  7. package/dist/core/messages.js.map +1 -1
  8. package/dist/core/session-manager.d.ts +1 -447
  9. package/dist/core/session-manager.d.ts.map +1 -1
  10. package/dist/core/session-manager.js +1 -1203
  11. package/dist/core/session-manager.js.map +1 -1
  12. package/package.json +2 -2
  13. package/docs/COMPLETE-GUIDE.md +0 -300
  14. package/docs/COMPREHENSIVE-CLI-SUMMARY.md +0 -900
  15. package/docs/MODES-ARCHITECTURE.md +0 -565
  16. package/docs/PRINT-MODE-GUIDE.md +0 -456
  17. package/docs/README.md +0 -78
  18. package/docs/RPC-GUIDE.md +0 -705
  19. package/docs/UTILS-IMPLEMENTATION-SUMMARY.md +0 -647
  20. package/docs/UTILS-MODULE-OVERVIEW.md +0 -1480
  21. package/docs/UTILS-QA-CHECKLIST.md +0 -1061
  22. package/docs/UTILS-USAGE-GUIDE.md +0 -1419
  23. package/docs/compaction.md +0 -390
  24. package/docs/custom-provider.md +0 -538
  25. package/docs/development.md +0 -69
  26. package/docs/extensions.md +0 -1733
  27. package/docs/hooks.md +0 -378
  28. package/docs/images/doom-extension.png +0 -0
  29. package/docs/images/interactive-mode.png +0 -0
  30. package/docs/images/tree-view.png +0 -0
  31. package/docs/json.md +0 -79
  32. package/docs/keybindings.md +0 -162
  33. package/docs/models.md +0 -193
  34. package/docs/packages.md +0 -163
  35. package/docs/prompt-templates.md +0 -67
  36. package/docs/providers.md +0 -147
  37. package/docs/rpc.md +0 -1048
  38. package/docs/sdk.md +0 -969
  39. package/docs/session.md +0 -412
  40. package/docs/settings.md +0 -219
  41. package/docs/shell-aliases.md +0 -13
  42. package/docs/skills.md +0 -226
  43. package/docs/subagents.md +0 -225
  44. package/docs/terminal-setup.md +0 -65
  45. package/docs/themes.md +0 -295
  46. package/docs/tree.md +0 -219
  47. package/docs/tui.md +0 -887
  48. package/docs/web-tools.md +0 -304
  49. package/docs/windows.md +0 -17
  50. package/examples/README.md +0 -25
  51. package/examples/extensions/README.md +0 -192
  52. package/examples/extensions/antigravity-image-gen.ts +0 -414
  53. package/examples/extensions/auto-commit-on-exit.ts +0 -49
  54. package/examples/extensions/bookmark.ts +0 -50
  55. package/examples/extensions/claude-rules.ts +0 -86
  56. package/examples/extensions/confirm-destructive.ts +0 -59
  57. package/examples/extensions/custom-compaction.ts +0 -115
  58. package/examples/extensions/custom-footer.ts +0 -65
  59. package/examples/extensions/custom-header.ts +0 -73
  60. package/examples/extensions/custom-provider-anthropic/index.ts +0 -605
  61. package/examples/extensions/custom-provider-anthropic/package-lock.json +0 -24
  62. package/examples/extensions/custom-provider-anthropic/package.json +0 -19
  63. package/examples/extensions/custom-provider-gitlab-duo/index.ts +0 -350
  64. package/examples/extensions/custom-provider-gitlab-duo/package.json +0 -16
  65. package/examples/extensions/custom-provider-gitlab-duo/test.ts +0 -83
  66. package/examples/extensions/dirty-repo-guard.ts +0 -56
  67. package/examples/extensions/doom-overlay/README.md +0 -46
  68. package/examples/extensions/doom-overlay/doom/build/doom.js +0 -21
  69. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  70. package/examples/extensions/doom-overlay/doom/build.sh +0 -152
  71. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +0 -72
  72. package/examples/extensions/doom-overlay/doom-component.ts +0 -133
  73. package/examples/extensions/doom-overlay/doom-engine.ts +0 -173
  74. package/examples/extensions/doom-overlay/doom-keys.ts +0 -105
  75. package/examples/extensions/doom-overlay/index.ts +0 -74
  76. package/examples/extensions/doom-overlay/wad-finder.ts +0 -51
  77. package/examples/extensions/event-bus.ts +0 -43
  78. package/examples/extensions/file-trigger.ts +0 -41
  79. package/examples/extensions/git-checkpoint.ts +0 -53
  80. package/examples/extensions/handoff.ts +0 -151
  81. package/examples/extensions/hello.ts +0 -25
  82. package/examples/extensions/inline-bash.ts +0 -94
  83. package/examples/extensions/input-transform.ts +0 -43
  84. package/examples/extensions/interactive-shell.ts +0 -196
  85. package/examples/extensions/mac-system-theme.ts +0 -47
  86. package/examples/extensions/message-renderer.ts +0 -60
  87. package/examples/extensions/modal-editor.ts +0 -86
  88. package/examples/extensions/model-status.ts +0 -31
  89. package/examples/extensions/notify.ts +0 -25
  90. package/examples/extensions/overlay-qa-tests.ts +0 -882
  91. package/examples/extensions/overlay-test.ts +0 -151
  92. package/examples/extensions/permission-gate.ts +0 -34
  93. package/examples/extensions/pirate.ts +0 -47
  94. package/examples/extensions/plan-mode/README.md +0 -65
  95. package/examples/extensions/plan-mode/index.ts +0 -341
  96. package/examples/extensions/plan-mode/utils.ts +0 -168
  97. package/examples/extensions/preset.ts +0 -399
  98. package/examples/extensions/protected-paths.ts +0 -30
  99. package/examples/extensions/qna.ts +0 -120
  100. package/examples/extensions/question.ts +0 -265
  101. package/examples/extensions/questionnaire.ts +0 -428
  102. package/examples/extensions/rainbow-editor.ts +0 -88
  103. package/examples/extensions/sandbox/index.ts +0 -318
  104. package/examples/extensions/sandbox/package-lock.json +0 -92
  105. package/examples/extensions/sandbox/package.json +0 -19
  106. package/examples/extensions/send-user-message.ts +0 -97
  107. package/examples/extensions/session-name.ts +0 -27
  108. package/examples/extensions/shutdown-command.ts +0 -63
  109. package/examples/extensions/snake.ts +0 -344
  110. package/examples/extensions/space-invaders.ts +0 -561
  111. package/examples/extensions/ssh.ts +0 -220
  112. package/examples/extensions/status-line.ts +0 -40
  113. package/examples/extensions/subagent/README.md +0 -172
  114. package/examples/extensions/subagent/agents/planner.md +0 -37
  115. package/examples/extensions/subagent/agents/reviewer.md +0 -35
  116. package/examples/extensions/subagent/agents/scout.md +0 -50
  117. package/examples/extensions/subagent/agents/worker.md +0 -24
  118. package/examples/extensions/subagent/agents.ts +0 -127
  119. package/examples/extensions/subagent/index.ts +0 -964
  120. package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
  121. package/examples/extensions/subagent/prompts/implement.md +0 -10
  122. package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
  123. package/examples/extensions/summarize.ts +0 -196
  124. package/examples/extensions/timed-confirm.ts +0 -70
  125. package/examples/extensions/todo.ts +0 -300
  126. package/examples/extensions/tool-override.ts +0 -144
  127. package/examples/extensions/tools.ts +0 -147
  128. package/examples/extensions/trigger-compact.ts +0 -40
  129. package/examples/extensions/truncated-tool.ts +0 -193
  130. package/examples/extensions/widget-placement.ts +0 -17
  131. package/examples/extensions/with-deps/index.ts +0 -36
  132. package/examples/extensions/with-deps/package-lock.json +0 -31
  133. package/examples/extensions/with-deps/package.json +0 -22
  134. package/examples/sdk/01-minimal.ts +0 -22
  135. package/examples/sdk/02-custom-model.ts +0 -50
  136. package/examples/sdk/03-custom-prompt.ts +0 -55
  137. package/examples/sdk/04-skills.ts +0 -46
  138. package/examples/sdk/05-tools.ts +0 -56
  139. package/examples/sdk/06-extensions.ts +0 -88
  140. package/examples/sdk/07-context-files.ts +0 -40
  141. package/examples/sdk/08-prompt-templates.ts +0 -47
  142. package/examples/sdk/09-api-keys-and-oauth.ts +0 -48
  143. package/examples/sdk/10-settings.ts +0 -38
  144. package/examples/sdk/11-sessions.ts +0 -48
  145. package/examples/sdk/12-full-control.ts +0 -82
  146. package/examples/sdk/13-codex-oauth.ts +0 -37
  147. package/examples/sdk/README.md +0 -144
@@ -1,1419 +0,0 @@
1
- # Utils Module Usage Guide
2
-
3
- **Version**: 1.0.0
4
- **Last Updated**: February 2024
5
- **Contains**: 40+ Real-World Examples
6
-
7
- ---
8
-
9
- ## Table of Contents
10
-
11
- 1. [Array Utilities Usage](#array-utilities-usage)
12
- 2. [Error Handling Patterns](#error-handling-patterns)
13
- 3. [Logging Usage Examples](#logging-usage-examples)
14
- 4. [File Operations Workflows](#file-operations-workflows)
15
- 5. [String & Date Formatting](#string--date-formatting)
16
- 6. [JSON Processing](#json-processing)
17
- 7. [Image Processing](#image-processing)
18
- 8. [Git Operations](#git-operations)
19
- 9. [Data Transformation Pipelines](#data-transformation-pipelines)
20
- 10. [Integration Patterns](#integration-patterns)
21
- 11. [Performance Optimization](#performance-optimization)
22
- 12. [Dependency Management](#dependency-management)
23
- 13. [Debugging Techniques](#debugging-techniques)
24
- 14. [Common Gotchas](#common-gotchas)
25
-
26
- ---
27
-
28
- ## Array Utilities Usage
29
-
30
- ### 1. Grouping and Categorizing Data
31
-
32
- ```typescript
33
- import { groupBy, partition, unique } from './utils/array';
34
-
35
- // Example 1: Group users by role
36
- const users = [
37
- { id: 1, name: 'Alice', role: 'admin' },
38
- { id: 2, name: 'Bob', role: 'user' },
39
- { id: 3, name: 'Charlie', role: 'admin' },
40
- { id: 4, name: 'Diana', role: 'user' }
41
- ];
42
-
43
- const grouped = groupBy(users, user => user.role);
44
- // Result:
45
- // {
46
- // admin: [{ id: 1, ... }, { id: 3, ... }],
47
- // user: [{ id: 2, ... }, { id: 4, ... }]
48
- // }
49
-
50
- // Use case: Create permission groups
51
- const permissions = {
52
- admin: ['read', 'write', 'delete'],
53
- user: ['read']
54
- };
55
-
56
- for (const [role, members] of Object.entries(grouped)) {
57
- applyPermissions(members, permissions[role]);
58
- }
59
- ```
60
-
61
- ### 2. Partitioning Arrays
62
-
63
- ```typescript
64
- import { partition, unique } from './utils/array';
65
-
66
- // Example 2: Separate active and inactive users
67
- const [activeUsers, inactiveUsers] = partition(
68
- users,
69
- user => user.isActive
70
- );
71
-
72
- // Example 3: Separate even and odd numbers
73
- const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
74
- const [even, odd] = partition(numbers, n => n % 2 === 0);
75
- // even: [2, 4, 6, 8]
76
- // odd: [1, 3, 5, 7, 9]
77
-
78
- // Practical: Split data for parallel processing
79
- const [largeOrders, smallOrders] = partition(
80
- orders,
81
- order => order.total > 1000
82
- );
83
-
84
- processLargeOrdersWithPriority(largeOrders);
85
- processSmallOrdersInBatch(smallOrders);
86
- ```
87
-
88
- ### 3. Deduplication and Unique Values
89
-
90
- ```typescript
91
- import { unique } from './utils/array';
92
-
93
- // Example 1: Remove duplicate IDs while preserving order
94
- const records = [
95
- { id: 1, name: 'A' },
96
- { id: 2, name: 'B' },
97
- { id: 1, name: 'A' }, // duplicate
98
- { id: 3, name: 'C' }
99
- ];
100
-
101
- const unique_ = unique(records, r => r.id);
102
- // Result: [{ id: 1 }, { id: 2 }, { id: 3 }]
103
-
104
- // Example 2: Get unique tags from multiple arrays
105
- const tags1 = ['javascript', 'react', 'node'];
106
- const tags2 = ['react', 'typescript', 'node'];
107
-
108
- const allTags = unique([...tags1, ...tags2]);
109
- // Result: ['javascript', 'react', 'node', 'typescript']
110
- ```
111
-
112
- ### 4. Flattening Nested Arrays
113
-
114
- ```typescript
115
- import { flatten, chunk } from './utils/array';
116
-
117
- // Example 1: Flatten directory structure
118
- const fileStructure = [
119
- 'README.md',
120
- ['src/',
121
- ['utils.ts', 'index.ts'],
122
- ['tests/', ['utils.test.ts']]
123
- ],
124
- 'package.json'
125
- ];
126
-
127
- const allFiles = flatten(fileStructure);
128
- // Result: ['README.md', 'src/', 'utils.ts', 'index.ts', 'tests/', 'utils.test.ts', 'package.json']
129
-
130
- // Example 2: Flatten with depth limit
131
- const result = flatten(fileStructure, 2);
132
- // Only flattens 2 levels deep
133
- ```
134
-
135
- ### 5. Chunking for Batch Processing
136
-
137
- ```typescript
138
- import { chunk } from './utils/array';
139
-
140
- // Example 1: Process large arrays in batches
141
- const data = Array.from({ length: 1000 }, (_, i) => i);
142
- const batchSize = 100;
143
-
144
- for (const batch of chunk(data, batchSize)) {
145
- await processBatch(batch);
146
- // Prevents memory issues with large datasets
147
- }
148
-
149
- // Example 2: Create pagination
150
- const itemsPerPage = 20;
151
- const allItems = [...items];
152
- const pages = chunk(allItems, itemsPerPage);
153
-
154
- pages.forEach((page, index) => {
155
- renderPage(page, index + 1); // Page numbers start at 1
156
- });
157
- ```
158
-
159
- ### 6. Sorting Custom Objects
160
-
161
- ```typescript
162
- import { sortBy } from './utils/array';
163
-
164
- // Example: Sort users by age, then by name
165
- const users = [
166
- { name: 'Charlie', age: 30 },
167
- { name: 'Alice', age: 25 },
168
- { name: 'Bob', age: 25 }
169
- ];
170
-
171
- const sorted = sortBy(users, (a, b) => {
172
- if (a.age !== b.age) return a.age - b.age;
173
- return a.name.localeCompare(b.name);
174
- });
175
-
176
- // Result:
177
- // [
178
- // { name: 'Alice', age: 25 },
179
- // { name: 'Bob', age: 25 },
180
- // { name: 'Charlie', age: 30 }
181
- // ]
182
- ```
183
-
184
- ### 7. Set Operations
185
-
186
- ```typescript
187
- import { union, intersection, difference } from './utils/array';
188
-
189
- // Example: Compare user permissions
190
- const adminPermissions = ['read', 'write', 'delete', 'admin'];
191
- const userPermissions = ['read', 'write'];
192
- const guestPermissions = ['read'];
193
-
194
- // All unique permissions
195
- const allPermissions = union(adminPermissions, userPermissions, guestPermissions);
196
-
197
- // Common permissions across all groups
198
- const commonPermissions = intersection(adminPermissions, userPermissions, guestPermissions);
199
- // Result: ['read']
200
-
201
- // Exclusive admin permissions
202
- const adminOnly = difference(adminPermissions, userPermissions, guestPermissions);
203
- // Result: ['delete', 'admin']
204
- ```
205
-
206
- ### 8. Finding Min/Max and Aggregations
207
-
208
- ```typescript
209
- import { minBy, maxBy, sum, average } from './utils/array';
210
-
211
- // Example: Sales analytics
212
- const sales = [
213
- { product: 'A', amount: 1500 },
214
- { product: 'B', amount: 2300 },
215
- { product: 'C', amount: 800 }
216
- ];
217
-
218
- const bestProduct = maxBy(sales, s => s.amount);
219
- const worstProduct = minBy(sales, s => s.amount);
220
- const totalSales = sum(sales, s => s.amount);
221
- const avgSale = average(sales, s => s.amount);
222
-
223
- console.log(`Best: ${bestProduct.product} ($${bestProduct.amount})`);
224
- console.log(`Worst: ${worstProduct.product} ($${worstProduct.amount})`);
225
- console.log(`Total: $${totalSales}`);
226
- console.log(`Average: $${avgSale.toFixed(2)}`);
227
- ```
228
-
229
- ### 9. Zipping Arrays Together
230
-
231
- ```typescript
232
- import { zip, unzip } from './utils/array';
233
-
234
- // Example 1: Combine related arrays
235
- const names = ['Alice', 'Bob', 'Charlie'];
236
- const ages = [25, 30, 35];
237
- const cities = ['NYC', 'LA', 'Chicago'];
238
-
239
- const combined = zip(names, ages, cities);
240
- // Result: [
241
- // ['Alice', 25, 'NYC'],
242
- // ['Bob', 30, 'LA'],
243
- // ['Charlie', 35, 'Chicago']
244
- // ]
245
-
246
- // Example 2: Create objects from zipped data
247
- const people = combined.map(([name, age, city]) => ({
248
- name, age, city
249
- }));
250
-
251
- // Example 3: Unzip to separate arrays
252
- const [unzippedNames, unzippedAges, unzippedCities] = unzip(combined);
253
- ```
254
-
255
- ### 10. Sampling and Shuffling
256
-
257
- ```typescript
258
- import { shuffle, sample, sampleSize } from './utils/array';
259
-
260
- // Example 1: Random selection
261
- const questions = [/* 100 questions */];
262
- const quiz = sampleSize(questions, 10); // Select 10 random questions
263
-
264
- // Example 2: Shuffle for randomization
265
- const shuffledCards = shuffle(deck); // Shuffle deck for card game
266
-
267
- // Example 3: Pick single random item
268
- const randomUser = sample(users);
269
- ```
270
-
271
- ---
272
-
273
- ## Error Handling Patterns
274
-
275
- ### 1. Basic Error Formatting
276
-
277
- ```typescript
278
- import { formatErrorForUser, ErrorCode } from './utils/error-handler';
279
-
280
- // Pattern 1: Standard error handling
281
- async function loadConfig() {
282
- try {
283
- const content = await fs.readFile('./config.json', 'utf-8');
284
- return JSON.parse(content);
285
- } catch (error) {
286
- const formatted = formatErrorForUser(error);
287
- console.error(`Error: ${formatted.message}`);
288
- console.error('Try this:', formatted.suggestions[0]);
289
- throw formatted.originalError;
290
- }
291
- }
292
- ```
293
-
294
- ### 2. API Error Response
295
-
296
- ```typescript
297
- import { formatErrorForUser } from './utils/error-handler';
298
-
299
- // Express error middleware
300
- app.use((err, req, res, next) => {
301
- const formatted = formatErrorForUser(err);
302
-
303
- // Log internally
304
- internalLogger.error(formatted.technicalDetails);
305
-
306
- // Return user-friendly response
307
- res.status(500).json({
308
- success: false,
309
- error: formatted.message,
310
- code: formatted.code,
311
- suggestions: formatted.suggestions
312
- });
313
- });
314
- ```
315
-
316
- ### 3. Promise Error Wrapper
317
-
318
- ```typescript
319
- import { handlePromise } from './utils/error-handler';
320
-
321
- async function fetchUserData(userId) {
322
- const [user, error] = await handlePromise(
323
- fetch(`/api/users/${userId}`).then(r => r.json())
324
- );
325
-
326
- if (error) {
327
- return {
328
- success: false,
329
- error: formatErrorForUser(error).message
330
- };
331
- }
332
-
333
- return { success: true, data: user };
334
- }
335
- ```
336
-
337
- ### 4. Retry with Exponential Backoff
338
-
339
- ```typescript
340
- import { retryWithBackoff, formatErrorForUser } from './utils/error-handler';
341
-
342
- // Resilient database connection
343
- async function connectWithRetry() {
344
- try {
345
- return await retryWithBackoff(
346
- async () => {
347
- const conn = await db.connect();
348
- console.log('Connected successfully');
349
- return conn;
350
- },
351
- 5, // Max 5 attempts
352
- 1000 // Start with 1s delay, doubles each attempt
353
- );
354
- } catch (error) {
355
- const formatted = formatErrorForUser(error, { code: 'NETWORK' });
356
- console.error(formatted.message);
357
- // Fallback strategy
358
- return await createOfflineCache();
359
- }
360
- }
361
- ```
362
-
363
- ### 5. Error Categorization
364
-
365
- ```typescript
366
- import { categorizeError, getRecoverySuggestions } from './utils/error-handler';
367
-
368
- function handleError(error) {
369
- const errorType = categorizeError(error);
370
- const suggestions = getRecoverySuggestions(error);
371
-
372
- switch (errorType) {
373
- case 'TypeError':
374
- showTypeErrorUI(suggestions);
375
- break;
376
- case 'ReferenceError':
377
- showReferenceErrorUI(suggestions);
378
- break;
379
- case 'SyntaxError':
380
- showSyntaxErrorUI(suggestions);
381
- break;
382
- default:
383
- showGenericErrorUI(suggestions);
384
- }
385
- }
386
- ```
387
-
388
- ### 6. Sanitized Error Messages
389
-
390
- ```typescript
391
- import { sanitizeErrorMessage, extractErrorMessage } from './utils/error-handler';
392
-
393
- // Before sending to client
394
- const rawError = error.message;
395
- // Raw: "Error reading /home/user/secret.key: EACCES"
396
-
397
- const safe = sanitizeErrorMessage(rawError);
398
- // Safe: "Error reading file: Permission denied"
399
-
400
- // Send to client
401
- res.json({ error: safe });
402
-
403
- // But log the technical details internally
404
- internalLog.error(rawError);
405
- ```
406
-
407
- ---
408
-
409
- ## Logging Usage Examples
410
-
411
- ### 1. Basic Module Logging
412
-
413
- ```typescript
414
- import { createLogger, setLogLevel } from './utils/logger';
415
-
416
- // Create logger for module
417
- const log = createLogger('UserService');
418
-
419
- // Set global log level
420
- setLogLevel('debug');
421
-
422
- // Use in functions
423
- export async function getUser(id: string) {
424
- log.debug('Fetching user', { userId: id });
425
-
426
- try {
427
- const user = await db.users.findById(id);
428
- log.info('User fetched successfully', { userId: id, name: user.name });
429
- return user;
430
- } catch (error) {
431
- log.error('Failed to fetch user', { userId: id, error: String(error) });
432
- throw error;
433
- }
434
- }
435
- ```
436
-
437
- ### 2. Performance Monitoring
438
-
439
- ```typescript
440
- const log = createLogger('Database');
441
-
442
- async function complexQuery() {
443
- const timer = log.time('complex-query');
444
-
445
- try {
446
- const result = await db.query(`
447
- SELECT u.*, c.count FROM users u
448
- LEFT JOIN (SELECT userId, count(*) as count FROM orders GROUP BY userId) c
449
- ON u.id = c.userId
450
- WHERE u.status = 'active'
451
- `);
452
-
453
- timer(); // Automatically logs: "complex-query: 234.50ms"
454
- return result;
455
- } catch (error) {
456
- timer(); // Still logs timing even on error
457
- log.error('Query failed', { error: String(error) });
458
- throw error;
459
- }
460
- }
461
- ```
462
-
463
- ### 3. Scoped Logging with Context
464
-
465
- ```typescript
466
- import { createScopedLogger } from './utils/logger';
467
-
468
- // In request handler
469
- app.post('/api/users', async (req, res) => {
470
- const requestId = generateRequestId();
471
- const requestLog = createScopedLogger(log, `req-${requestId}`, {
472
- method: 'POST',
473
- path: '/api/users',
474
- ip: req.ip
475
- });
476
-
477
- requestLog.info('Processing request');
478
-
479
- try {
480
- const user = await createUser(req.body);
481
- requestLog.info('User created', { userId: user.id });
482
- res.json(user);
483
- } catch (error) {
484
- requestLog.error('User creation failed', { error: String(error) });
485
- res.status(400).json({ error: 'Failed to create user' });
486
- }
487
- });
488
- ```
489
-
490
- ### 4. Batch Logging
491
-
492
- ```typescript
493
- import { logBatch } from './utils/logger';
494
-
495
- async function processBatch(items) {
496
- const log = createLogger('BatchProcessor');
497
- const results = [];
498
-
499
- for (const item of items) {
500
- try {
501
- const result = await processItem(item);
502
- results.push(`Processed: ${item.id}`);
503
- } catch (error) {
504
- results.push(`Failed: ${item.id}`);
505
- }
506
- }
507
-
508
- // Log all results as group
509
- logBatch('Batch Processing Complete', results, log);
510
- }
511
- ```
512
-
513
- ### 5. Performance Monitor
514
-
515
- ```typescript
516
- import { createPerformanceMonitor } from './utils/logger';
517
-
518
- const log = createLogger('API');
519
- const monitor = createPerformanceMonitor(log, 200); // 200ms threshold
520
-
521
- // Any operation over 200ms triggers warning instead of debug
522
- await monitor('user-lookup', async () => {
523
- return await db.users.find({ active: true });
524
- });
525
-
526
- // Result: "user-lookup completed { duration: 245.30ms }"
527
- // Log level: WARN (because 245ms > 200ms threshold)
528
- ```
529
-
530
- ---
531
-
532
- ## File Operations Workflows
533
-
534
- ### 1. Safe File Reading with Validation
535
-
536
- ```typescript
537
- import {
538
- readFile,
539
- exists,
540
- getSize,
541
- formatErrorForUser
542
- } from './utils/file-operations';
543
- import { parseJSON } from './utils/json-formatter';
544
-
545
- async function loadConfig(path: string) {
546
- try {
547
- // Check existence first
548
- if (!await exists(path)) {
549
- console.log('Config not found, creating default...');
550
- return getDefaultConfig();
551
- }
552
-
553
- // Check file size to prevent memory issues
554
- const size = await getSize(path);
555
- if (size > 1000000) { // 1MB limit
556
- throw new Error('Config file too large');
557
- }
558
-
559
- // Read and parse
560
- const content = await readFile(path);
561
- const [config, error] = parseJSON(content);
562
-
563
- if (error) {
564
- throw new Error(`Invalid JSON: ${error.message}`);
565
- }
566
-
567
- return config;
568
- } catch (error) {
569
- const formatted = formatErrorForUser(error);
570
- console.error(formatted.message);
571
- return getDefaultConfig();
572
- }
573
- }
574
- ```
575
-
576
- ### 2. Batch File Processing
577
-
578
- ```typescript
579
- import {
580
- batchProcessFiles,
581
- readFile,
582
- writeFile,
583
- createLogger
584
- } from './utils/file-operations';
585
-
586
- const log = createLogger('FileProcessor');
587
-
588
- async function convertFilesToUTF8() {
589
- let converted = 0;
590
-
591
- const count = await batchProcessFiles(
592
- './data',
593
- async (filePath) => {
594
- const content = await readFile(filePath, { encoding: 'latin1' });
595
- const utf8Content = Buffer.from(content, 'latin1').toString('utf-8');
596
- await writeFile(filePath, utf8Content);
597
- converted++;
598
- log.debug('Converted', { file: filePath });
599
- },
600
- { extension: '.txt', recursive: true }
601
- );
602
-
603
- log.info('Conversion complete', { processed: converted, total: count });
604
- }
605
- ```
606
-
607
- ### 3. Safe File Deletion with Backup
608
-
609
- ```typescript
610
- import { deleteFile, exists } from './utils/file-operations';
611
-
612
- async function safeDelete(filePath: string) {
613
- try {
614
- if (!await exists(filePath)) {
615
- throw new Error('File not found');
616
- }
617
-
618
- const backupPath = await deleteFile(filePath, true);
619
- console.log(`Deleted: ${filePath}`);
620
- console.log(`Backup: ${backupPath}`);
621
-
622
- return { success: true, backup: backupPath };
623
- } catch (error) {
624
- console.error('Failed to delete:', error.message);
625
- return { success: false };
626
- }
627
- }
628
- ```
629
-
630
- ### 4. Directory Listing and Filtering
631
-
632
- ```typescript
633
- import { listFiles, isFile, isDirectory } from './utils/file-operations';
634
-
635
- async function analyzeProjectStructure() {
636
- // Get all TypeScript files
637
- const tsFiles = await listFiles('./src', {
638
- extension: '.ts',
639
- recursive: true,
640
- filesOnly: true
641
- });
642
-
643
- // Get all test files
644
- const testFiles = await listFiles('./src', {
645
- extension: '.test.ts',
646
- recursive: true
647
- });
648
-
649
- // Get all directories
650
- const dirs = await listFiles('./src', {
651
- recursive: true,
652
- filesOnly: false
653
- });
654
-
655
- console.log(`Found ${tsFiles.length} TypeScript files`);
656
- console.log(`Found ${testFiles.length} test files`);
657
- console.log(`Found ${dirs.length} directories`);
658
- }
659
- ```
660
-
661
- ### 5. File Metadata and Integrity
662
-
663
- ```typescript
664
- import { getMetadata, copyFile } from './utils/file-operations';
665
-
666
- async function backupWithVerification() {
667
- const original = './important.json';
668
- const backup = './important.json.backup';
669
-
670
- // Get hash before copying
671
- const originalMeta = await getMetadata(original, true);
672
- console.log(`Original hash: ${originalMeta.hash}`);
673
-
674
- // Copy with verification
675
- await copyFile(original, backup, true);
676
-
677
- // Verify copy
678
- const backupMeta = await getMetadata(backup, true);
679
- if (originalMeta.hash === backupMeta.hash) {
680
- console.log('Backup verified - files are identical');
681
- } else {
682
- console.error('Backup verification failed - files differ!');
683
- }
684
- }
685
- ```
686
-
687
- ### 6. Line-by-Line Processing
688
-
689
- ```typescript
690
- import { readLinesSync, appendFile } from './utils/file-operations';
691
-
692
- async function processLogFile() {
693
- let errorCount = 0;
694
- let warningCount = 0;
695
-
696
- await readLinesSync('./app.log', (line, index) => {
697
- if (line.includes('[ERROR]')) {
698
- errorCount++;
699
- console.log(`Line ${index}: ${line}`);
700
- } else if (line.includes('[WARN]')) {
701
- warningCount++;
702
- }
703
- });
704
-
705
- // Write summary
706
- await appendFile('./summary.log',
707
- `Errors: ${errorCount}, Warnings: ${warningCount}\n`);
708
- }
709
- ```
710
-
711
- ---
712
-
713
- ## String & Date Formatting
714
-
715
- ### 1. String Case Conversions
716
-
717
- ```typescript
718
- import {
719
- capitalize,
720
- toCamelCase,
721
- toSnakeCase,
722
- toKebabCase
723
- } from './utils/string-formatter';
724
-
725
- const text = 'hello world';
726
-
727
- console.log(capitalize(text)); // 'Hello world'
728
- console.log(toCamelCase('hello-world-example')); // 'helloWorldExample'
729
- console.log(toSnakeCase('helloWorld')); // 'hello_world'
730
- console.log(toKebabCase('HelloWorld')); // 'hello-world'
731
-
732
- // Practical: URL slug generation
733
- const title = 'Hello World Example!';
734
- const slug = toKebabCase(title.toLowerCase());
735
- // Result: 'hello-world-example'
736
- ```
737
-
738
- ### 2. Date Formatting and Manipulation
739
-
740
- ```typescript
741
- import {
742
- formatDate,
743
- addDays,
744
- getDuration,
745
- getWeekNumber
746
- } from './utils/date-formatter';
747
-
748
- // Example 1: Format dates for display
749
- const now = new Date();
750
- console.log(formatDate(now, 'yyyy-MM-dd')); // '2024-02-15'
751
- console.log(formatDate(now, 'yyyy-MM-dd HH:mm')); // '2024-02-15 14:30'
752
- console.log(formatDate(now, 'MMMM d, yyyy')); // 'February 15, 2024'
753
-
754
- // Example 2: Date arithmetic
755
- const deadline = addDays(now, 7);
756
- console.log(`Deadline: ${formatDate(deadline, 'yyyy-MM-dd')}`);
757
-
758
- // Example 3: Duration calculation
759
- const start = new Date('2024-02-01');
760
- const end = new Date('2024-02-15');
761
- const duration = getDuration(start, end);
762
- console.log(`Duration: ${duration.days} days, ${duration.hours} hours`);
763
-
764
- // Example 4: Week number for reporting
765
- const weekNum = getWeekNumber(now);
766
- console.log(`Current week: ${weekNum}`);
767
- ```
768
-
769
- ---
770
-
771
- ## JSON Processing
772
-
773
- ### 1. Safe JSON Parsing
774
-
775
- ```typescript
776
- import { parseJSON, validateJSON } from './utils/json-formatter';
777
-
778
- // Example: API response handling
779
- async function handleApiResponse(response) {
780
- const text = await response.text();
781
-
782
- // Validate first
783
- const isValid = validateJSON(text);
784
- if (!isValid) {
785
- console.error('Invalid JSON response');
786
- return null;
787
- }
788
-
789
- // Safe parse
790
- const [data, error] = parseJSON(text);
791
- if (error) {
792
- console.error('Parse error:', error.message);
793
- return null;
794
- }
795
-
796
- return data;
797
- }
798
- ```
799
-
800
- ### 2. Flatten/Unflatten for APIs
801
-
802
- ```typescript
803
- import { flattenJSON, unflattenJSON } from './utils/json-formatter';
804
-
805
- // Flatten for form submission
806
- const user = {
807
- name: 'John',
808
- address: {
809
- street: '123 Main St',
810
- city: 'New York',
811
- zip: {
812
- code: '10001'
813
- }
814
- }
815
- };
816
-
817
- const flat = flattenJSON(user);
818
- // Result:
819
- // {
820
- // 'name': 'John',
821
- // 'address.street': '123 Main St',
822
- // 'address.city': 'New York',
823
- // 'address.zip.code': '10001'
824
- // }
825
-
826
- // Send form data...
827
-
828
- // Unflatten for storage
829
- const restored = unflattenJSON(flat);
830
- // Result: Same as original user object
831
- ```
832
-
833
- ### 3. JSON Merging
834
-
835
- ```typescript
836
- import { mergeJSON } from './utils/json-formatter';
837
-
838
- // Merge configuration files
839
- const baseConfig = {
840
- port: 3000,
841
- timeout: 30000,
842
- features: { auth: true, logging: true }
843
- };
844
-
845
- const envConfig = {
846
- port: 8080,
847
- features: { cache: true }
848
- };
849
-
850
- const merged = mergeJSON(baseConfig, envConfig);
851
- // Result:
852
- // {
853
- // port: 8080, // Overridden
854
- // timeout: 30000, // From base
855
- // features: { auth: true, logging: true, cache: true } // Deep merged
856
- // }
857
- ```
858
-
859
- ---
860
-
861
- ## Image Processing
862
-
863
- ### 1. Image Resizing Workflow
864
-
865
- ```typescript
866
- import {
867
- resizeImage,
868
- getImageDimensions,
869
- createLogger
870
- } from './utils/image-operations';
871
-
872
- const log = createLogger('ImageResize');
873
-
874
- async function optimizeImage(inputPath, outputPath) {
875
- try {
876
- // Get original dimensions
877
- const dims = await getImageDimensions(inputPath);
878
- log.info('Original dimensions', dims);
879
-
880
- // Resize to fit in 1920x1080
881
- const resized = await resizeImage(inputPath, {
882
- width: 1920,
883
- height: 1080,
884
- fit: 'inside'
885
- });
886
-
887
- log.info('Image resized', { path: outputPath });
888
- return resized;
889
- } catch (error) {
890
- log.error('Resize failed', { error: String(error) });
891
- throw error;
892
- }
893
- }
894
- ```
895
-
896
- ### 2. Image Format Conversion
897
-
898
- ```typescript
899
- import {
900
- convertFormat,
901
- detectFormat
902
- } from './utils/image-operations';
903
-
904
- async function convertToWebP(inputPath, outputPath) {
905
- // Detect original format
906
- const format = detectFormat(inputPath);
907
- console.log(`Original format: ${format}`);
908
-
909
- // Convert to WebP with compression
910
- const result = await convertFormat(inputPath, 'webp', {
911
- quality: 0.8
912
- });
913
-
914
- // Save result
915
- const fs = require('fs').promises;
916
- await fs.writeFile(outputPath, result);
917
- console.log(`Converted to WebP: ${outputPath}`);
918
- }
919
- ```
920
-
921
- ### 3. Batch Image Processing
922
-
923
- ```typescript
924
- import {
925
- resizeImage,
926
- batchProcessFiles
927
- } from './utils/file-operations';
928
-
929
- async function createThumbnails() {
930
- let created = 0;
931
-
932
- const count = await batchProcessFiles(
933
- './images',
934
- async (imagePath) => {
935
- const outputPath = imagePath.replace('.', '_thumb.');
936
- await resizeImage(imagePath, outputPath, {
937
- width: 200,
938
- height: 200,
939
- fit: 'cover'
940
- });
941
- created++;
942
- },
943
- { extension: '.jpg', recursive: true }
944
- );
945
-
946
- console.log(`Created ${created} thumbnails out of ${count} images`);
947
- }
948
- ```
949
-
950
- ---
951
-
952
- ## Git Operations
953
-
954
- ### 1. Repository Status Check
955
-
956
- ```typescript
957
- import {
958
- checkIsRepository,
959
- getGitStatus,
960
- getCurrentBranch,
961
- createLogger
962
- } from './utils/git';
963
-
964
- const log = createLogger('Git');
965
-
966
- async function checkRepoStatus() {
967
- try {
968
- if (!await checkIsRepository()) {
969
- log.error('Not a git repository');
970
- return;
971
- }
972
-
973
- const branch = await getCurrentBranch();
974
- const status = await getGitStatus();
975
-
976
- log.info('Repository status', {
977
- branch,
978
- modified: status.modified.length,
979
- untracked: status.untracked.length,
980
- staged: status.staged.length
981
- });
982
-
983
- if (status.modified.length > 0) {
984
- log.warn('Uncommitted changes:', status.modified);
985
- }
986
- } catch (error) {
987
- log.error('Failed to check status', { error: String(error) });
988
- }
989
- }
990
- ```
991
-
992
- ### 2. Commit History Analysis
993
-
994
- ```typescript
995
- import { getCommitHistory, formatDate } from './utils/git';
996
-
997
- async function analyzeCommits() {
998
- const commits = await getCommitHistory(50);
999
-
1000
- // Group by author
1001
- const byAuthor = {};
1002
- for (const commit of commits) {
1003
- if (!byAuthor[commit.author]) {
1004
- byAuthor[commit.author] = [];
1005
- }
1006
- byAuthor[commit.author].push(commit);
1007
- }
1008
-
1009
- // Show statistics
1010
- for (const [author, commits] of Object.entries(byAuthor)) {
1011
- console.log(`${author}: ${commits.length} commits`);
1012
- }
1013
- }
1014
- ```
1015
-
1016
- ---
1017
-
1018
- ## Data Transformation Pipelines
1019
-
1020
- ### 1. Multi-Step Transformation
1021
-
1022
- ```typescript
1023
- import { transform } from './utils/data-transformer';
1024
-
1025
- async function processUserData(users) {
1026
- const result = await transform(users)
1027
- .pipe(filter(u => u.status === 'active'))
1028
- .pipe(map(u => ({
1029
- ...u,
1030
- email: u.email.toLowerCase(),
1031
- joinedYear: new Date(u.joinDate).getFullYear()
1032
- })))
1033
- .pipe(sortBy((a, b) => b.joinedYear - a.joinedYear))
1034
- .pipe(chunk(10))
1035
- .execute();
1036
-
1037
- return result; // Array of arrays, grouped by year
1038
- }
1039
- ```
1040
-
1041
- ### 2. Parallel Processing
1042
-
1043
- ```typescript
1044
- async function processLargeDataset(items) {
1045
- const result = await transform(items)
1046
- .pipe(parallel(async (item) => {
1047
- return await expensiveOperation(item);
1048
- }, 4)) // Process 4 items in parallel
1049
- .execute();
1050
-
1051
- return result;
1052
- }
1053
- ```
1054
-
1055
- ---
1056
-
1057
- ## Integration Patterns
1058
-
1059
- ### 1. Complete API Handler
1060
-
1061
- ```typescript
1062
- import {
1063
- createLogger,
1064
- formatErrorForUser,
1065
- retryWithBackoff,
1066
- handlePromise
1067
- } from './utils';
1068
-
1069
- const log = createLogger('API');
1070
-
1071
- app.get('/api/data/:id', async (req, res) => {
1072
- const requestLog = createScopedLogger(log, `req-${req.id}`, {
1073
- path: req.path,
1074
- method: req.method
1075
- });
1076
-
1077
- requestLog.info('Request started');
1078
- const timer = requestLog.time('total');
1079
-
1080
- try {
1081
- // Fetch with retries
1082
- const [data, error] = await handlePromise(
1083
- retryWithBackoff(
1084
- () => fetchFromDatabase(req.params.id),
1085
- 3,
1086
- 1000
1087
- )
1088
- );
1089
-
1090
- if (error) {
1091
- const formatted = formatErrorForUser(error);
1092
- requestLog.error('Database error', { error: formatted.code });
1093
- return res.status(500).json({
1094
- error: formatted.message,
1095
- code: formatted.code
1096
- });
1097
- }
1098
-
1099
- requestLog.info('Data retrieved', { size: JSON.stringify(data).length });
1100
- timer();
1101
- res.json(data);
1102
- } catch (error) {
1103
- const formatted = formatErrorForUser(error);
1104
- requestLog.error('Unexpected error', { error: formatted.message });
1105
- timer();
1106
- res.status(500).json({ error: 'Internal server error' });
1107
- }
1108
- });
1109
- ```
1110
-
1111
- ### 2. CLI Command Implementation
1112
-
1113
- ```typescript
1114
- import {
1115
- createLogger,
1116
- readFile,
1117
- writeFile,
1118
- formatErrorForUser
1119
- } from './utils';
1120
-
1121
- async function processCommand(input, output) {
1122
- const log = createLogger('CLI');
1123
-
1124
- try {
1125
- log.info('Starting process', { input, output });
1126
-
1127
- const timer = log.time('process');
1128
-
1129
- // Read input
1130
- const content = await readFile(input);
1131
- log.debug('File read', { size: content.length });
1132
-
1133
- // Process
1134
- const processed = await processContent(content);
1135
- log.debug('Content processed', { resultSize: processed.length });
1136
-
1137
- // Write output
1138
- await writeFile(output, processed, { createDirs: true });
1139
- log.info('Process complete', { output });
1140
-
1141
- timer();
1142
- } catch (error) {
1143
- const formatted = formatErrorForUser(error);
1144
- log.error(formatted.message);
1145
- console.error(`Error: ${formatted.message}`);
1146
- process.exit(1);
1147
- }
1148
- }
1149
- ```
1150
-
1151
- ---
1152
-
1153
- ## Performance Optimization
1154
-
1155
- ### 1. Batch Operations
1156
-
1157
- ```typescript
1158
- // BAD: Individual operations
1159
- for (const file of files) {
1160
- const content = await readFile(file);
1161
- const processed = processContent(content);
1162
- await writeFile(file, processed);
1163
- }
1164
-
1165
- // GOOD: Batch processing
1166
- const count = await batchProcessFiles(
1167
- dir,
1168
- async (file) => {
1169
- const content = await readFile(file);
1170
- const processed = processContent(content);
1171
- await writeFile(file, processed);
1172
- }
1173
- );
1174
- ```
1175
-
1176
- ### 2. Efficient Array Handling
1177
-
1178
- ```typescript
1179
- // BAD: Multiple iterations
1180
- const active = data.filter(x => x.isActive);
1181
- const mapped = active.map(x => transform(x));
1182
- const sorted = mapped.sort((a, b) => a.id - b.id);
1183
-
1184
- // GOOD: Single pipeline
1185
- const result = await transform(data)
1186
- .pipe(filter(x => x.isActive))
1187
- .pipe(map(x => transform(x)))
1188
- .pipe(sortBy((a, b) => a.id - b.id))
1189
- .execute();
1190
- ```
1191
-
1192
- ---
1193
-
1194
- ## Dependency Management
1195
-
1196
- ### 1. Import Organization
1197
-
1198
- ```typescript
1199
- // Organize imports by category
1200
-
1201
- // Node.js modules
1202
- import * as path from 'path';
1203
- import { promises as fs } from 'fs';
1204
-
1205
- // Utilities
1206
- import {
1207
- readFile,
1208
- writeFile,
1209
- listFiles,
1210
- formatErrorForUser
1211
- } from './utils/file-operations';
1212
-
1213
- import {
1214
- createLogger,
1215
- setLogLevel
1216
- } from './utils/logger';
1217
-
1218
- import {
1219
- groupBy,
1220
- unique,
1221
- chunk
1222
- } from './utils/array';
1223
-
1224
- // Application code
1225
- import { processData } from './processor';
1226
- ```
1227
-
1228
- ### 2. Avoiding Circular Dependencies
1229
-
1230
- ```typescript
1231
- // BAD: Direct circular dependency
1232
- // file-a.ts
1233
- import { funcB } from './file-b';
1234
- export const funcA = () => funcB();
1235
-
1236
- // file-b.ts
1237
- import { funcA } from './file-a';
1238
- export const funcB = () => funcA();
1239
-
1240
- // GOOD: Use shared interface
1241
- // types.ts
1242
- export interface Processor {
1243
- process(data: any): any;
1244
- }
1245
-
1246
- // file-a.ts
1247
- import type { Processor } from './types';
1248
- export class ProcessorA implements Processor {
1249
- process(data) { /* ... */ }
1250
- }
1251
-
1252
- // file-b.ts
1253
- import type { Processor } from './types';
1254
- export class ProcessorB implements Processor {
1255
- process(data) { /* ... */ }
1256
- }
1257
- ```
1258
-
1259
- ---
1260
-
1261
- ## Debugging Techniques
1262
-
1263
- ### 1. Structured Logging for Debugging
1264
-
1265
- ```typescript
1266
- const log = createLogger('MyModule');
1267
- setLogLevel('debug'); // Enable debug messages
1268
-
1269
- // Example: Track variable changes
1270
- const value = initialValue;
1271
- log.debug('Initial value', { value });
1272
-
1273
- // Process
1274
- const processed = await process(value);
1275
- log.debug('After processing', { value: processed });
1276
-
1277
- // Conditional debugging
1278
- if (getLogLevel() <= LogLevel.DEBUG) {
1279
- log.debug('Expensive operation', {
1280
- ...hugeObject,
1281
- timestamp: Date.now()
1282
- });
1283
- }
1284
- ```
1285
-
1286
- ### 2. Error Context for Debugging
1287
-
1288
- ```typescript
1289
- try {
1290
- const result = await operation();
1291
- } catch (error) {
1292
- const formatted = formatErrorForUser(error);
1293
-
1294
- // Log full context
1295
- internalLog.error('Operation failed', {
1296
- operation: 'fetchUserData',
1297
- input: userId,
1298
- stack: formatted.technicalDetails,
1299
- timestamp: new Date().toISOString()
1300
- });
1301
-
1302
- // Show user-friendly message
1303
- showError(formatted.message);
1304
- }
1305
- ```
1306
-
1307
- ---
1308
-
1309
- ## Common Gotchas
1310
-
1311
- ### 1. Array Modification
1312
-
1313
- ```typescript
1314
- // Gotcha: Modifying original array
1315
- const original = [1, 2, 3];
1316
- const sorted = sortBy(original, (a, b) => b - a);
1317
-
1318
- // safe - sortBy returns new array
1319
- console.log(original); // [1, 2, 3] - unchanged
1320
- console.log(sorted); // [3, 2, 1] - new array
1321
-
1322
- // But this modifies original:
1323
- const mapped = original.map(x => x * 2);
1324
- original[0] = 999; // Changes affect mapped? No, primitives are safe.
1325
- ```
1326
-
1327
- ### 2. Async Gotchas
1328
-
1329
- ```typescript
1330
- // Gotcha: Forgetting await
1331
- const file = readFile('file.txt'); // Returns Promise!
1332
- const content = file; // This is a Promise, not string
1333
-
1334
- // Correct:
1335
- const content = await readFile('file.txt');
1336
-
1337
- // Gotcha: Promise.all vs sequential
1338
- // Sequential (slow)
1339
- const file1 = await readFile('f1.txt');
1340
- const file2 = await readFile('f2.txt');
1341
-
1342
- // Parallel (fast)
1343
- const [file1, file2] = await Promise.all([
1344
- readFile('f1.txt'),
1345
- readFile('f2.txt')
1346
- ]);
1347
- ```
1348
-
1349
- ### 3. Logging Level Gotcha
1350
-
1351
- ```typescript
1352
- // Gotcha: Debug log always evaluates expression
1353
- log.debug('User: ' + JSON.stringify(hugeObject)); // String created even if debug disabled!
1354
-
1355
- // Better:
1356
- if (getLogLevel() <= LogLevel.DEBUG) {
1357
- log.debug('User', hugeObject); // Only if debug is enabled
1358
- }
1359
-
1360
- // Or use lazy evaluation (if supported)
1361
- log.debug(() => `User: ${JSON.stringify(hugeObject)}`);
1362
- ```
1363
-
1364
- ### 4. File Path Gotcha
1365
-
1366
- ```typescript
1367
- // Gotcha: Relative paths from wrong directory
1368
- const content = await readFile('./data.json');
1369
- // Works when run from project root
1370
- // Fails when run from subdirectory!
1371
-
1372
- // Better:
1373
- const content = await readFile(
1374
- path.resolve(__dirname, '../../data.json')
1375
- );
1376
- // Or
1377
- const content = await readFile(
1378
- validatePath('./data.json')
1379
- );
1380
- ```
1381
-
1382
- ### 5. Error Message Gotcha
1383
-
1384
- ```typescript
1385
- // Gotcha: Showing sensitive information
1386
- catch (error) {
1387
- console.error(error.message);
1388
- // Client sees: "/home/user/app/config/db.ts line 42"
1389
- }
1390
-
1391
- // Correct:
1392
- catch (error) {
1393
- const safe = sanitizeErrorMessage(error.message);
1394
- console.error(safe);
1395
- // Client sees: "Database connection failed"
1396
- }
1397
- ```
1398
-
1399
- ---
1400
-
1401
- ## Best Practices Summary
1402
-
1403
- 1. **Always handle errors**: Use formatErrorForUser for user-facing errors
1404
- 2. **Use appropriate log levels**: Don't log everything at INFO
1405
- 3. **Batch file operations**: Process multiple files together
1406
- 4. **Validate inputs**: Use type guards and path validators
1407
- 5. **Create new arrays**: Functions like sortBy return new arrays
1408
- 6. **Use pipelines**: Chain transformations with transform()
1409
- 7. **Scope loggers**: Create scoped loggers with context for requests
1410
- 8. **Check before deleting**: Verify file exists before operations
1411
- 9. **Sanitize errors**: Always sanitize before showing to users
1412
- 10. **Test edge cases**: Handle empty arrays, null values, etc.
1413
-
1414
- ---
1415
-
1416
- **Last Updated**: February 2024
1417
- **Maintained By**: Indusagi Core Team
1418
- **License**: MIT
1419
-