metacoding 1.2.1 → 1.3.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.
@@ -0,0 +1,500 @@
1
+ ---
2
+ description: 'Modern JavaScript coding standards and best practices for browser and Node.js environments'
3
+ applyTo: 'src/**/*.{js,mjs}'
4
+ ---
5
+
6
+ # Modern JavaScript Development Guidelines
7
+
8
+ ## Language and Framework Preferences
9
+
10
+ - **Primary Language:** Modern JavaScript (ES6+/ES2020+)
11
+ - **Code Style:** Follow project's ESLint/Prettier configuration
12
+ - **Target Compatibility:** Node.js 18+, modern browsers (ES2020+)
13
+ - **Module System:** ES modules (import/export) preferred over CommonJS
14
+
15
+ ## Core JavaScript Principles
16
+
17
+ - **Modern Syntax:** Use ES6+ features (arrow functions, destructuring, async/await)
18
+ - **Immutability:** Prefer immutable patterns and functional programming concepts
19
+ - **Async Programming:** Use async/await for asynchronous operations, avoid callback hell
20
+ - **Error Handling:** Implement comprehensive error handling with try/catch blocks
21
+ - **Performance:** Consider performance implications of operations and memory usage
22
+
23
+ ## Naming Conventions
24
+
25
+ - **Files:** Use kebab-case for file names (e.g., `user-service.js`, `api-client.js`)
26
+ - **Classes:** PascalCase (e.g., `UserService`, `ApiClient`)
27
+ - **Functions/Methods:** camelCase (e.g., `getUserById`, `validateInput`)
28
+ - **Variables:** camelCase (e.g., `userId`, `isValid`, `userProfile`)
29
+ - **Constants:** SCREAMING_SNAKE_CASE (e.g., `MAX_RETRY_ATTEMPTS`, `API_BASE_URL`)
30
+ - **Private Methods:** Prefix with underscore (e.g., `_validateData`, `_handleError`)
31
+
32
+ ## Modern JavaScript Best Practices
33
+
34
+ ### ES6+ Features and Patterns
35
+
36
+ ```javascript
37
+ // ✅ Good: Use const/let instead of var
38
+ const API_URL = 'https://api.example.com';
39
+ let userCount = 0;
40
+
41
+ // ✅ Good: Arrow functions for concise syntax
42
+ const users = data.map((user) => user.name);
43
+ const filteredUsers = users.filter((user) => user.active);
44
+
45
+ // ✅ Good: Destructuring assignment
46
+ const {
47
+ name,
48
+ email,
49
+ address: { city },
50
+ } = user;
51
+ const [first, second, ...rest] = items;
52
+
53
+ // ✅ Good: Template literals
54
+ const message = `Welcome ${user.name}, you have ${count} notifications`;
55
+
56
+ // ✅ Good: Spread operator
57
+ const newUser = { ...existingUser, status: 'active' };
58
+ const mergedArray = [...array1, ...array2];
59
+ ```
60
+
61
+ ### Async/Await Patterns
62
+
63
+ ```javascript
64
+ // ✅ Good: Async/await with proper error handling
65
+ async function fetchUserData(userId) {
66
+ try {
67
+ const response = await fetch(`/api/users/${userId}`);
68
+ if (!response.ok) {
69
+ throw new Error(`HTTP error! status: ${response.status}`);
70
+ }
71
+ const userData = await response.json();
72
+ return userData;
73
+ } catch (error) {
74
+ console.error('Failed to fetch user data:', error);
75
+ throw error; // Re-throw to allow caller to handle
76
+ }
77
+ }
78
+
79
+ // ✅ Good: Promise.all for concurrent operations
80
+ async function fetchMultipleUsers(userIds) {
81
+ try {
82
+ const userPromises = userIds.map((id) => fetchUserData(id));
83
+ const users = await Promise.all(userPromises);
84
+ return users;
85
+ } catch (error) {
86
+ console.error('Failed to fetch multiple users:', error);
87
+ throw error;
88
+ }
89
+ }
90
+ ```
91
+
92
+ ### Functional Programming Patterns
93
+
94
+ ```javascript
95
+ // ✅ Good: Pure functions
96
+ const calculateTotal = (items) =>
97
+ items.reduce((total, item) => total + item.price, 0);
98
+
99
+ // ✅ Good: Higher-order functions
100
+ const withRetry =
101
+ (fn, maxAttempts = 3) =>
102
+ async (...args) => {
103
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
104
+ try {
105
+ return await fn(...args);
106
+ } catch (error) {
107
+ if (attempt === maxAttempts) throw error;
108
+ await new Promise((resolve) => setTimeout(resolve, 1000 * attempt));
109
+ }
110
+ }
111
+ };
112
+
113
+ // ✅ Good: Composition and chaining
114
+ const processUsers = (users) =>
115
+ users
116
+ .filter((user) => user.active)
117
+ .map((user) => ({
118
+ ...user,
119
+ displayName: `${user.firstName} ${user.lastName}`,
120
+ }))
121
+ .sort((a, b) => a.displayName.localeCompare(b.displayName));
122
+ ```
123
+
124
+ ## Browser-Specific Development
125
+
126
+ ### DOM Manipulation Best Practices
127
+
128
+ ```javascript
129
+ // ✅ Good: Modern DOM querying
130
+ const userElement = document.querySelector('[data-user-id="123"]');
131
+ const allButtons = document.querySelectorAll('.btn');
132
+
133
+ // ✅ Good: Event delegation
134
+ document.addEventListener('click', (event) => {
135
+ if (event.target.matches('.btn-submit')) {
136
+ handleSubmit(event);
137
+ }
138
+ });
139
+
140
+ // ✅ Good: Modern event handling
141
+ const button = document.getElementById('submit-btn');
142
+ button.addEventListener('click', async (event) => {
143
+ event.preventDefault();
144
+ await handleFormSubmission();
145
+ });
146
+ ```
147
+
148
+ ### Web APIs and Browser Features
149
+
150
+ ```javascript
151
+ // ✅ Good: Fetch API with error handling
152
+ async function apiRequest(url, options = {}) {
153
+ const config = {
154
+ headers: {
155
+ 'Content-Type': 'application/json',
156
+ },
157
+ ...options,
158
+ };
159
+
160
+ try {
161
+ const response = await fetch(url, config);
162
+ if (!response.ok) {
163
+ throw new Error(`API request failed: ${response.status}`);
164
+ }
165
+ return await response.json();
166
+ } catch (error) {
167
+ console.error('API request error:', error);
168
+ throw error;
169
+ }
170
+ }
171
+
172
+ // ✅ Good: Local storage with error handling
173
+ function saveToStorage(key, data) {
174
+ try {
175
+ localStorage.setItem(key, JSON.stringify(data));
176
+ } catch (error) {
177
+ console.error('Failed to save to localStorage:', error);
178
+ }
179
+ }
180
+
181
+ function loadFromStorage(key) {
182
+ try {
183
+ const data = localStorage.getItem(key);
184
+ return data ? JSON.parse(data) : null;
185
+ } catch (error) {
186
+ console.error('Failed to load from localStorage:', error);
187
+ return null;
188
+ }
189
+ }
190
+ ```
191
+
192
+ ## Node.js-Specific Development
193
+
194
+ ### Module Patterns
195
+
196
+ ```javascript
197
+ // ✅ Good: ES module exports
198
+ export const config = {
199
+ port: process.env.PORT || 3000,
200
+ dbUrl: process.env.DATABASE_URL,
201
+ };
202
+
203
+ export class UserService {
204
+ constructor(database) {
205
+ this.db = database;
206
+ }
207
+
208
+ async findById(id) {
209
+ return await this.db.users.findById(id);
210
+ }
211
+ }
212
+
213
+ export default UserService;
214
+
215
+ // ✅ Good: Named imports
216
+ import { config } from './config.js';
217
+ import UserService from './user-service.js';
218
+ ```
219
+
220
+ ### File System and Path Operations
221
+
222
+ ```javascript
223
+ import { promises as fs } from 'fs';
224
+ import path from 'path';
225
+ import { fileURLToPath } from 'url';
226
+
227
+ // ✅ Good: ES module __dirname equivalent
228
+ const __filename = fileURLToPath(import.meta.url);
229
+ const __dirname = path.dirname(__filename);
230
+
231
+ // ✅ Good: Async file operations
232
+ async function readConfigFile(filename) {
233
+ try {
234
+ const configPath = path.join(__dirname, 'config', filename);
235
+ const data = await fs.readFile(configPath, 'utf8');
236
+ return JSON.parse(data);
237
+ } catch (error) {
238
+ console.error(`Failed to read config file ${filename}:`, error);
239
+ return null;
240
+ }
241
+ }
242
+ ```
243
+
244
+ ## Error Handling Patterns
245
+
246
+ ### Comprehensive Error Management
247
+
248
+ ```javascript
249
+ // ✅ Good: Custom error classes
250
+ class ValidationError extends Error {
251
+ constructor(message, field) {
252
+ super(message);
253
+ this.name = 'ValidationError';
254
+ this.field = field;
255
+ }
256
+ }
257
+
258
+ class ApiError extends Error {
259
+ constructor(message, statusCode, originalError) {
260
+ super(message);
261
+ this.name = 'ApiError';
262
+ this.statusCode = statusCode;
263
+ this.originalError = originalError;
264
+ }
265
+ }
266
+
267
+ // ✅ Good: Error boundary patterns
268
+ async function withErrorHandling(operation, context = '') {
269
+ try {
270
+ return await operation();
271
+ } catch (error) {
272
+ console.error(`Error in ${context}:`, error);
273
+
274
+ // Re-throw known errors
275
+ if (error instanceof ValidationError || error instanceof ApiError) {
276
+ throw error;
277
+ }
278
+
279
+ // Wrap unknown errors
280
+ throw new Error(`Unexpected error in ${context}: ${error.message}`);
281
+ }
282
+ }
283
+ ```
284
+
285
+ ## Security Best Practices
286
+
287
+ ### Input Validation and Sanitization
288
+
289
+ ```javascript
290
+ // ✅ Good: Input validation
291
+ function validateEmail(email) {
292
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
293
+ return emailRegex.test(email);
294
+ }
295
+
296
+ function sanitizeInput(input) {
297
+ if (typeof input !== 'string') return '';
298
+ return input.trim().replace(/[<>]/g, '');
299
+ }
300
+
301
+ // ✅ Good: Data validation with schema
302
+ function validateUserData(userData) {
303
+ const errors = [];
304
+
305
+ if (!userData.name || typeof userData.name !== 'string') {
306
+ errors.push('Name is required and must be a string');
307
+ }
308
+
309
+ if (!validateEmail(userData.email)) {
310
+ errors.push('Valid email address is required');
311
+ }
312
+
313
+ if (errors.length > 0) {
314
+ throw new ValidationError('Validation failed', errors);
315
+ }
316
+
317
+ return {
318
+ name: sanitizeInput(userData.name),
319
+ email: userData.email.toLowerCase(),
320
+ };
321
+ }
322
+ ```
323
+
324
+ ## Performance Optimization
325
+
326
+ ### Efficient Data Operations
327
+
328
+ ```javascript
329
+ // ✅ Good: Efficient array operations
330
+ const processLargeDataset = (items) => {
331
+ // Use for...of for better performance with large arrays
332
+ const results = [];
333
+ for (const item of items) {
334
+ if (item.active) {
335
+ results.push(transformItem(item));
336
+ }
337
+ }
338
+ return results;
339
+ };
340
+
341
+ // ✅ Good: Debouncing for performance
342
+ function debounce(func, wait) {
343
+ let timeout;
344
+ return function executedFunction(...args) {
345
+ const later = () => {
346
+ clearTimeout(timeout);
347
+ func.apply(this, args);
348
+ };
349
+ clearTimeout(timeout);
350
+ timeout = setTimeout(later, wait);
351
+ };
352
+ }
353
+
354
+ // ✅ Good: Memoization for expensive operations
355
+ function memoize(fn) {
356
+ const cache = new Map();
357
+ return function memoized(...args) {
358
+ const key = JSON.stringify(args);
359
+ if (cache.has(key)) {
360
+ return cache.get(key);
361
+ }
362
+ const result = fn.apply(this, args);
363
+ cache.set(key, result);
364
+ return result;
365
+ };
366
+ }
367
+ ```
368
+
369
+ ## Build Tools and Development Workflow
370
+
371
+ ### Package.json Best Practices
372
+
373
+ ```javascript
374
+ // ✅ Good: Well-structured package.json scripts
375
+ {
376
+ "scripts": {
377
+ "dev": "vite",
378
+ "build": "vite build",
379
+ "preview": "vite preview",
380
+ "test": "jest",
381
+ "test:watch": "jest --watch",
382
+ "test:coverage": "jest --coverage",
383
+ "lint": "eslint src/**/*.js",
384
+ "lint:fix": "eslint src/**/*.js --fix",
385
+ "format": "prettier --write src/**/*.js"
386
+ }
387
+ }
388
+ ```
389
+
390
+ ### Environment Configuration
391
+
392
+ ```javascript
393
+ // ✅ Good: Environment configuration
394
+ const config = {
395
+ development: {
396
+ apiUrl: 'http://localhost:3000/api',
397
+ debug: true,
398
+ },
399
+ production: {
400
+ apiUrl: 'https://api.production.com',
401
+ debug: false,
402
+ },
403
+ test: {
404
+ apiUrl: 'http://localhost:3001/api',
405
+ debug: false,
406
+ },
407
+ };
408
+
409
+ export default config[process.env.NODE_ENV || 'development'];
410
+ ```
411
+
412
+ ## Anti-Patterns to Avoid
413
+
414
+ ### Common JavaScript Pitfalls
415
+
416
+ ```javascript
417
+ // ❌ Bad: Callback hell
418
+ getData(function (a) {
419
+ getMoreData(a, function (b) {
420
+ getEvenMoreData(b, function (c) {
421
+ // Nested callbacks are hard to maintain
422
+ });
423
+ });
424
+ });
425
+
426
+ // ❌ Bad: Modifying function parameters
427
+ function updateUser(user) {
428
+ user.lastUpdated = new Date(); // Mutates input parameter
429
+ return user;
430
+ }
431
+
432
+ // ❌ Bad: Using var and global variables
433
+ var globalCounter = 0; // Avoid var and globals
434
+ function incrementCounter() {
435
+ globalCounter++; // Side effects are hard to track
436
+ }
437
+
438
+ // ❌ Bad: Not handling promise rejections
439
+ fetch('/api/data'); // Unhandled promise
440
+
441
+ // ❌ Bad: Mixing async patterns
442
+ async function mixedPatterns() {
443
+ const data = await fetch('/api/data');
444
+ data.then((result) => {
445
+ // Don't mix async/await with .then()
446
+ console.log(result);
447
+ });
448
+ }
449
+ ```
450
+
451
+ ## Documentation Standards
452
+
453
+ ### JSDoc Documentation
454
+
455
+ ```javascript
456
+ /**
457
+ * Calculates the total price including tax
458
+ * @param {number} basePrice - The base price before tax
459
+ * @param {number} taxRate - The tax rate as a decimal (e.g., 0.08 for 8%)
460
+ * @returns {number} The total price including tax
461
+ * @throws {Error} When basePrice or taxRate is negative
462
+ * @example
463
+ * const total = calculateTotalPrice(100, 0.08); // Returns 108
464
+ */
465
+ function calculateTotalPrice(basePrice, taxRate) {
466
+ if (basePrice < 0 || taxRate < 0) {
467
+ throw new Error('Price and tax rate must be non-negative');
468
+ }
469
+ return basePrice * (1 + taxRate);
470
+ }
471
+
472
+ /**
473
+ * User service for managing user data
474
+ * @class
475
+ */
476
+ class UserService {
477
+ /**
478
+ * Creates a new UserService instance
479
+ * @param {Object} database - Database connection instance
480
+ */
481
+ constructor(database) {
482
+ this.db = database;
483
+ }
484
+
485
+ /**
486
+ * Retrieves a user by ID
487
+ * @param {string} userId - The unique user identifier
488
+ * @returns {Promise<Object|null>} User object or null if not found
489
+ * @async
490
+ */
491
+ async getUserById(userId) {
492
+ try {
493
+ return await this.db.users.findById(userId);
494
+ } catch (error) {
495
+ console.error(`Failed to fetch user ${userId}:`, error);
496
+ return null;
497
+ }
498
+ }
499
+ }
500
+ ```