agentic-team-templates 0.9.2 → 0.10.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,448 @@
1
+ # JavaScript Expert Development Guide
2
+
3
+ Comprehensive guidelines for principal-level JavaScript engineering across all runtimes, frameworks, and paradigms.
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ This guide applies to:
10
+ - Node.js services, CLIs, and tooling
11
+ - React, Vue, Angular, Svelte, and other UI frameworks
12
+ - Vanilla JavaScript and Web APIs
13
+ - TypeScript (strict mode, always)
14
+ - Build tools, bundlers, and transpilers
15
+ - Testing at every level (unit, integration, E2E, performance)
16
+
17
+ ### Core Philosophy
18
+
19
+ JavaScript is the runtime. Know it deeply:
20
+ - The event loop is not optional knowledge — it's the foundation
21
+ - Prototypes, closures, and the module system are first principles
22
+ - The spec (ECMAScript) is the source of truth, not blog posts
23
+ - Every abstraction leaks — understand what's underneath
24
+
25
+ ### Key Principles
26
+
27
+ 1. **Language Mastery Over Framework Dependence** - Frameworks come and go, JS fundamentals are permanent
28
+ 2. **Type Safety Is Non-Negotiable** - TypeScript strict mode, always
29
+ 3. **Functional by Default** - Pure functions and composition, classes when lifecycle demands it
30
+ 4. **Performance Is a Feature** - Profile before optimizing, measure don't guess
31
+ 5. **Error Handling Is Control Flow** - Result types over thrown exceptions
32
+
33
+ ### Project Structure
34
+
35
+ ```
36
+ src/
37
+ ├── core/ # Pure business logic, zero dependencies
38
+ ├── adapters/ # External integrations (DB, HTTP, FS)
39
+ ├── services/ # Orchestration layer
40
+ ├── utils/ # Pure utility functions
41
+ ├── types/ # TypeScript type definitions
42
+ ├── __tests__/ # Test files
43
+ └── index.ts # Public API surface
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Language Deep Dive
49
+
50
+ ### The Event Loop
51
+
52
+ Understanding execution order is fundamental:
53
+
54
+ ```typescript
55
+ console.log('1 - sync');
56
+ setTimeout(() => console.log('2 - macrotask'), 0);
57
+ Promise.resolve().then(() => console.log('3 - microtask'));
58
+ queueMicrotask(() => console.log('4 - microtask'));
59
+ console.log('5 - sync');
60
+ // Output: 1, 5, 3, 4, 2
61
+ ```
62
+
63
+ ### Type Safety
64
+
65
+ ```typescript
66
+ // Discriminated unions over optional fields
67
+ type Result<T, E = Error> =
68
+ | { ok: true; value: T }
69
+ | { ok: false; error: E };
70
+
71
+ // Branded types for domain safety
72
+ type UserId = string & { readonly __brand: unique symbol };
73
+
74
+ // Const assertions and template literal types
75
+ const EVENTS = ['click', 'keydown', 'submit'] as const;
76
+ type EventName = (typeof EVENTS)[number];
77
+ ```
78
+
79
+ ### Functional Patterns
80
+
81
+ ```typescript
82
+ const pipe = <T>(...fns: Array<(arg: T) => T>) =>
83
+ (value: T): T => fns.reduce((acc, fn) => fn(acc), value);
84
+
85
+ const processUser = pipe(validateInput, normalizeEmail, hashPassword);
86
+ ```
87
+
88
+ ### Async Patterns
89
+
90
+ ```typescript
91
+ // Parallel independent operations
92
+ const [users, posts] = await Promise.all([fetchUsers(), fetchPosts()]);
93
+
94
+ // Race with timeout
95
+ const withTimeout = <T>(promise: Promise<T>, ms: number): Promise<T> =>
96
+ Promise.race([
97
+ promise,
98
+ new Promise<never>((_, reject) =>
99
+ setTimeout(() => reject(new Error(`Timeout after ${ms}ms`)), ms)
100
+ ),
101
+ ]);
102
+
103
+ // Async iteration for streams
104
+ async function* readChunks(stream: ReadableStream<Uint8Array>) {
105
+ const reader = stream.getReader();
106
+ try {
107
+ while (true) {
108
+ const { done, value } = await reader.read();
109
+ if (done) break;
110
+ yield value;
111
+ }
112
+ } finally {
113
+ reader.releaseLock();
114
+ }
115
+ }
116
+ ```
117
+
118
+ ### Generators and Lazy Evaluation
119
+
120
+ ```typescript
121
+ function* filter<T>(iterable: Iterable<T>, predicate: (item: T) => boolean) {
122
+ for (const item of iterable) {
123
+ if (predicate(item)) yield item;
124
+ }
125
+ }
126
+
127
+ function* take<T>(iterable: Iterable<T>, count: number) {
128
+ let i = 0;
129
+ for (const item of iterable) {
130
+ if (i++ >= count) break;
131
+ yield item;
132
+ }
133
+ }
134
+ ```
135
+
136
+ ### Error Handling
137
+
138
+ ```typescript
139
+ // Result types for expected failures
140
+ function parseConfig(raw: string): Result<Config> {
141
+ try {
142
+ const parsed = JSON.parse(raw);
143
+ const validated = ConfigSchema.safeParse(parsed);
144
+ if (!validated.success) {
145
+ return { ok: false, error: new ValidationError(validated.error) };
146
+ }
147
+ return { ok: true, value: validated.data };
148
+ } catch {
149
+ return { ok: false, error: new ParseError('Invalid JSON') };
150
+ }
151
+ }
152
+
153
+ // Reserve throw for invariant violations
154
+ function assertNonNull<T>(value: T | null | undefined, msg: string): asserts value is T {
155
+ if (value == null) throw new Error(`Invariant: ${msg}`);
156
+ }
157
+ ```
158
+
159
+ ---
160
+
161
+ ## Node.js Patterns
162
+
163
+ ### Graceful Shutdown
164
+
165
+ ```typescript
166
+ const shutdown = async (signal: string) => {
167
+ console.log(`Received ${signal}, shutting down...`);
168
+ server.close();
169
+ await db.disconnect();
170
+ process.exit(0);
171
+ };
172
+
173
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
174
+ process.on('SIGINT', () => shutdown('SIGINT'));
175
+ ```
176
+
177
+ ### Streams
178
+
179
+ ```typescript
180
+ import { pipeline } from 'node:stream/promises';
181
+
182
+ await pipeline(
183
+ createReadStream('input.log'),
184
+ new Transform({
185
+ transform(chunk, _encoding, callback) {
186
+ const filtered = chunk.toString()
187
+ .split('\n')
188
+ .filter((line: string) => line.includes('ERROR'))
189
+ .join('\n');
190
+ callback(null, filtered);
191
+ },
192
+ }),
193
+ createGzip(),
194
+ createWriteStream('errors.log.gz'),
195
+ );
196
+ ```
197
+
198
+ ### Worker Threads
199
+
200
+ ```typescript
201
+ import { Worker, isMainThread, parentPort, workerData } from 'node:worker_threads';
202
+
203
+ if (isMainThread) {
204
+ const runWorker = <T>(data: unknown): Promise<T> =>
205
+ new Promise((resolve, reject) => {
206
+ const worker = new Worker(new URL(import.meta.url), { workerData: data });
207
+ worker.on('message', resolve);
208
+ worker.on('error', reject);
209
+ });
210
+ } else {
211
+ const result = performExpensiveComputation(workerData);
212
+ parentPort!.postMessage(result);
213
+ }
214
+ ```
215
+
216
+ ### Configuration
217
+
218
+ ```typescript
219
+ import { z } from 'zod';
220
+
221
+ const EnvSchema = z.object({
222
+ NODE_ENV: z.enum(['development', 'production', 'test']),
223
+ PORT: z.coerce.number().int().positive().default(3000),
224
+ DATABASE_URL: z.string().url(),
225
+ });
226
+
227
+ export const env = EnvSchema.parse(process.env);
228
+ ```
229
+
230
+ ---
231
+
232
+ ## React Patterns
233
+
234
+ ### Server Components First (React 19+)
235
+
236
+ ```tsx
237
+ // Default: Server Component — no 'use client'
238
+ async function ProjectList() {
239
+ const projects = await db.projects.findMany();
240
+ return <ul>{projects.map(p => <ProjectCard key={p.id} project={p} />)}</ul>;
241
+ }
242
+
243
+ // Only add 'use client' when you need interactivity
244
+ 'use client';
245
+ function SearchInput({ onSearch }: { onSearch: (q: string) => void }) {
246
+ const [query, setQuery] = useState('');
247
+ return <input value={query} onChange={e => setQuery(e.target.value)} />;
248
+ }
249
+ ```
250
+
251
+ ### Composition Patterns
252
+
253
+ ```tsx
254
+ // Compound components
255
+ function Tabs({ children }: { children: React.ReactNode }) {
256
+ const [active, setActive] = useState(0);
257
+ return <TabsContext.Provider value={{ active, setActive }}>{children}</TabsContext.Provider>;
258
+ }
259
+ Tabs.List = function TabList({ children }) { ... };
260
+ Tabs.Panel = function TabPanel({ children, index }) { ... };
261
+ ```
262
+
263
+ ### State Management Hierarchy
264
+
265
+ 1. `useState` — local state
266
+ 2. `useReducer` — complex local state with actions
267
+ 3. Context — low-frequency shared state (theme, auth, locale)
268
+ 4. External store (Zustand, Jotai) — high-frequency shared state
269
+
270
+ ### Anti-Patterns
271
+
272
+ ```tsx
273
+ // Never: useEffect for derived state
274
+ const fullName = `${firstName} ${lastName}`; // Just compute it
275
+
276
+ // Never: index as key for dynamic lists
277
+ {items.map(item => <Item key={item.id} item={item} />)}
278
+
279
+ // Never: Object literals as default props
280
+ const EMPTY: readonly Item[] = [];
281
+ function List({ items = EMPTY }: { items?: readonly Item[] }) { ... }
282
+ ```
283
+
284
+ ---
285
+
286
+ ## Testing
287
+
288
+ ### Philosophy
289
+
290
+ - Tests are production code — same quality standards
291
+ - Test behavior and contracts, never implementation details
292
+ - Every bug fix starts with a failing test
293
+ - If it's hard to test, the design is wrong
294
+
295
+ ### Unit Tests
296
+
297
+ ```typescript
298
+ describe('clamp', () => {
299
+ it('returns value when within range', () => {
300
+ expect(clamp(5, 0, 10)).toBe(5);
301
+ });
302
+ it('returns min when value is below range', () => {
303
+ expect(clamp(-5, 0, 10)).toBe(0);
304
+ });
305
+ it('returns max when value is above range', () => {
306
+ expect(clamp(15, 0, 10)).toBe(10);
307
+ });
308
+ });
309
+ ```
310
+
311
+ ### Parameterized Tests
312
+
313
+ ```typescript
314
+ it.each([
315
+ ['Hello World', 'hello-world'],
316
+ [' spaces ', 'spaces'],
317
+ ['Special!@#Characters', 'specialcharacters'],
318
+ ])('converts "%s" to "%s"', (input, expected) => {
319
+ expect(slugify(input)).toBe(expected);
320
+ });
321
+ ```
322
+
323
+ ### Component Tests
324
+
325
+ ```tsx
326
+ import { render, screen } from '@testing-library/react';
327
+ import userEvent from '@testing-library/user-event';
328
+
329
+ it('adds a new todo when form is submitted', async () => {
330
+ const user = userEvent.setup();
331
+ render(<TodoList />);
332
+ await user.type(screen.getByRole('textbox', { name: /new todo/i }), 'Buy milk');
333
+ await user.click(screen.getByRole('button', { name: /add/i }));
334
+ expect(screen.getByText('Buy milk')).toBeInTheDocument();
335
+ });
336
+ ```
337
+
338
+ ### API Mocking with MSW
339
+
340
+ ```typescript
341
+ import { http, HttpResponse } from 'msw';
342
+ import { setupServer } from 'msw/node';
343
+
344
+ const server = setupServer(
345
+ http.get('/api/users/:id', ({ params }) => {
346
+ return HttpResponse.json({ id: params.id, name: 'Test User' });
347
+ }),
348
+ );
349
+
350
+ beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
351
+ afterEach(() => server.resetHandlers());
352
+ afterAll(() => server.close());
353
+ ```
354
+
355
+ ### E2E Tests
356
+
357
+ ```typescript
358
+ import { test, expect } from '@playwright/test';
359
+
360
+ test('login flow', async ({ page }) => {
361
+ await page.goto('/login');
362
+ await page.getByLabel('Email').fill('user@example.com');
363
+ await page.getByLabel('Password').fill('password');
364
+ await page.getByRole('button', { name: 'Sign in' }).click();
365
+ await expect(page).toHaveURL('/dashboard');
366
+ });
367
+ ```
368
+
369
+ ### Test Anti-Patterns
370
+
371
+ - Never test implementation details (internal state, class names)
372
+ - Never use `setTimeout` for waiting — use `waitFor` or `findBy`
373
+ - Never let tests depend on execution order
374
+ - Never ignore flaky tests — a flaky test is a bug
375
+
376
+ ---
377
+
378
+ ## Performance
379
+
380
+ ### Profiling First
381
+
382
+ ```typescript
383
+ performance.mark('operation-start');
384
+ doExpensiveWork();
385
+ performance.mark('operation-end');
386
+ performance.measure('operation', 'operation-start', 'operation-end');
387
+ ```
388
+
389
+ ### V8 Optimization
390
+
391
+ - Keep function argument shapes consistent (monomorphic)
392
+ - Initialize all object properties in the same order
393
+ - Use `Map`/`Set` for dynamic collections, plain objects for static shapes
394
+ - Use `TypedArray` for numeric data
395
+
396
+ ### Memory Management
397
+
398
+ - Use `AbortController` signals for event listener cleanup
399
+ - Use `WeakMap`/`WeakRef` for caches that shouldn't prevent GC
400
+ - Avoid closures that capture large scopes — extract only what's needed
401
+
402
+ ### Bundle Size
403
+
404
+ - Dynamic imports for code splitting
405
+ - Named exports for tree-shaking
406
+ - Prefer native APIs (`structuredClone`, `Intl`, `URL`, `crypto.randomUUID`)
407
+
408
+ ---
409
+
410
+ ## Tooling
411
+
412
+ ### TypeScript Config
413
+
414
+ ```jsonc
415
+ {
416
+ "compilerOptions": {
417
+ "strict": true,
418
+ "noUncheckedIndexedAccess": true,
419
+ "exactOptionalPropertyTypes": true,
420
+ "verbatimModuleSyntax": true,
421
+ "module": "ESNext",
422
+ "target": "ES2022"
423
+ }
424
+ }
425
+ ```
426
+
427
+ ### Dependency Hygiene
428
+
429
+ - Pin exact versions for applications
430
+ - Audit regularly (`npm audit`)
431
+ - Prefer zero-dependency packages
432
+ - Check bundle size before adding (`bundlephobia.com`)
433
+
434
+ ---
435
+
436
+ ## Definition of Done
437
+
438
+ A JavaScript feature is complete when:
439
+
440
+ - [ ] TypeScript strict mode passes with zero errors
441
+ - [ ] All code paths have explicit types (no `any`)
442
+ - [ ] Unit tests cover logic branches and edge cases
443
+ - [ ] Integration tests verify external boundaries
444
+ - [ ] Error cases are tested, not just happy paths
445
+ - [ ] No floating promises
446
+ - [ ] No memory leaks in long-running paths
447
+ - [ ] Bundle impact assessed (client-side code)
448
+ - [ ] Code reviewed and approved