@simpill/utils 1.0.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.
Files changed (46) hide show
  1. package/CONTRIBUTING.md +787 -0
  2. package/README.md +186 -0
  3. package/__tests__/README.md +32 -0
  4. package/__tests__/e2e/all-packages-resolve.e2e.test.ts +40 -0
  5. package/__tests__/integration/env-and-async.integration.test.ts +12 -0
  6. package/__tests__/integration/errors-and-uuid.integration.test.ts +14 -0
  7. package/__tests__/integration/object-and-array.integration.test.ts +15 -0
  8. package/__tests__/unit/@simpill/_resolver/resolve-packages.unit.test.ts +47 -0
  9. package/__tests__/unit/@simpill/array.utils/array.utils.unit.test.ts +11 -0
  10. package/__tests__/unit/@simpill/async.utils/async.utils.unit.test.ts +12 -0
  11. package/__tests__/unit/@simpill/cache.utils/cache.utils.unit.test.ts +21 -0
  12. package/__tests__/unit/@simpill/env.utils/env.utils.unit.test.ts +13 -0
  13. package/__tests__/unit/@simpill/errors.utils/errors.utils.unit.test.ts +13 -0
  14. package/__tests__/unit/@simpill/object.utils/object.utils.unit.test.ts +11 -0
  15. package/__tests__/unit/@simpill/patterns.utils/patterns.utils.unit.test.ts +23 -0
  16. package/__tests__/unit/@simpill/string.utils/string.utils.unit.test.ts +11 -0
  17. package/__tests__/unit/@simpill/time.utils/time.utils.unit.test.ts +12 -0
  18. package/__tests__/unit/@simpill/uuid.utils/uuid.utils.unit.test.ts +12 -0
  19. package/docs/PUBLISHING_AND_PACKAGES.md +258 -0
  20. package/docs/template/.env.sample +0 -0
  21. package/docs/template/README.md +0 -0
  22. package/docs/template/TEMPLATE.md +1040 -0
  23. package/docs/template/assets/logo-banner.svg +20 -0
  24. package/docs/template/package.json +14 -0
  25. package/index.ts +89 -0
  26. package/package.json +87 -0
  27. package/scripts/README.md +57 -0
  28. package/scripts/github/github-set-all-topics.js +120 -0
  29. package/scripts/github/github-set-repo-topics.sh +33 -0
  30. package/scripts/github/github-set-repos-public.sh +71 -0
  31. package/scripts/lib/package-topics.js +57 -0
  32. package/scripts/lib/publish-order.js +140 -0
  33. package/scripts/lib/sync-repo-links.js +75 -0
  34. package/scripts/monorepo/install-hooks.sh +64 -0
  35. package/scripts/monorepo/monorepo-clean.sh +7 -0
  36. package/scripts/monorepo/monorepo-sync-deps.js +81 -0
  37. package/scripts/monorepo/monorepo-verify-deps.js +37 -0
  38. package/scripts/monorepo/use-local-utils-at-root.js +49 -0
  39. package/scripts/publish/publish-all.sh +152 -0
  40. package/scripts/utils/utils-fix-repo-metadata.js +61 -0
  41. package/scripts/utils/utils-prepare-all.sh +107 -0
  42. package/scripts/utils/utils-set-npm-keywords.js +132 -0
  43. package/scripts/utils/utils-update-readme-badges.js +83 -0
  44. package/scripts/utils/utils-use-local-deps.js +43 -0
  45. package/scripts/utils/utils-verify-all.sh +45 -0
  46. package/tsconfig.json +14 -0
@@ -0,0 +1,1040 @@
1
+ # Package Template
2
+
3
+ This template provides step-by-step instructions and all configuration files needed to create a new `@simpill` package.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ # Replace {name} with your package name (e.g., cache, http, logger)
9
+ export PKG_NAME="{name}"
10
+
11
+ # Run the setup commands
12
+ ./scripts/create-package.sh $PKG_NAME
13
+ ```
14
+
15
+ Or follow the manual steps below.
16
+
17
+ ---
18
+
19
+ ## Table of Contents
20
+
21
+ 1. [Step 1: Create Directory Structure](#step-1-create-directory-structure)
22
+ 2. [Step 2: Create Configuration Files](#step-2-create-configuration-files)
23
+ 3. [Step 3: Create Source Files](#step-3-create-source-files)
24
+ 4. [Step 4: Create Scripts](#step-4-create-scripts)
25
+ 5. [Step 5: Create Documentation](#step-5-create-documentation)
26
+ 6. [Step 6: Create CI/CD Workflows](#step-6-create-cicd-workflows)
27
+ 7. [Step 7: Initialize and Verify](#step-7-initialize-and-verify)
28
+ 8. [Checklist](#checklist)
29
+
30
+ ---
31
+
32
+ ## Step 1: Create Directory Structure
33
+
34
+ ```bash
35
+ # Replace {name} with your package name
36
+ PKG_NAME="{name}"
37
+
38
+ # Create all directories
39
+ mkdir -p ${PKG_NAME}.utils/{src/{client,server,shared},__tests__/{client,server,shared}/{unit,integration},scripts,examples/{basic,advanced,client,server}}
40
+ ```
41
+
42
+ Final structure:
43
+
44
+ ```
45
+ {name}.utils/
46
+ ├── __tests__/
47
+ │ ├── client/
48
+ │ │ ├── unit/
49
+ │ │ └── integration/
50
+ │ ├── server/
51
+ │ │ ├── unit/
52
+ │ │ └── integration/
53
+ │ └── shared/
54
+ │ └── unit/
55
+ ├── examples/
56
+ │ ├── basic/
57
+ │ ├── advanced/
58
+ │ ├── client/
59
+ │ └── server/
60
+ ├── scripts/
61
+ ├── src/
62
+ │ ├── client/
63
+ │ ├── server/
64
+ │ └── shared/
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Step 2: Create Configuration Files
70
+
71
+ ### package.json
72
+
73
+ ```json
74
+ {
75
+ "name": "@simpill/{name}.utils",
76
+ "version": "1.0.0",
77
+ "description": "Brief description of the package",
78
+ "repository": {
79
+ "type": "git",
80
+ "url": "https://github.com/SkinnnyJay/simpill-utils.git",
81
+ "directory": "{name}.utils"
82
+ },
83
+ "bugs": {
84
+ "url": "https://github.com/SkinnnyJay/simpill-utils/issues"
85
+ },
86
+ "homepage": "https://github.com/SkinnnyJay/simpill-utils/tree/main/utils/{name}.utils#readme",
87
+ "main": "dist/index.js",
88
+ "types": "dist/index.d.ts",
89
+ "exports": {
90
+ ".": {
91
+ "types": "./dist/index.d.ts",
92
+ "import": "./dist/index.js",
93
+ "require": "./dist/index.js"
94
+ },
95
+ "./client": {
96
+ "types": "./dist/client/index.d.ts",
97
+ "import": "./dist/client/index.js",
98
+ "require": "./dist/client/index.js"
99
+ },
100
+ "./server": {
101
+ "types": "./dist/server/index.d.ts",
102
+ "import": "./dist/server/index.js",
103
+ "require": "./dist/server/index.js"
104
+ },
105
+ "./shared": {
106
+ "types": "./dist/shared/index.d.ts",
107
+ "import": "./dist/shared/index.js",
108
+ "require": "./dist/shared/index.js"
109
+ }
110
+ },
111
+ "files": [
112
+ "dist",
113
+ "README.md"
114
+ ],
115
+ "scripts": {
116
+ "build": "tsc",
117
+ "prepublishOnly": "npm run build",
118
+ "test": "jest",
119
+ "test:watch": "jest --watch",
120
+ "test:coverage": "jest --coverage",
121
+ "lint": "biome lint .",
122
+ "lint:fix": "biome lint --write .",
123
+ "format": "biome format --write .",
124
+ "format:check": "biome format .",
125
+ "check": "biome check .",
126
+ "check:fix": "biome check --write .",
127
+ "verify": "./scripts/check.sh",
128
+ "prepare": "./scripts/install-hooks.sh"
129
+ },
130
+ "keywords": [
131
+ "typescript",
132
+ "type-safe",
133
+ "{relevant-keywords}"
134
+ ],
135
+ "author": "@SkinnnyJay",
136
+ "license": "ISC",
137
+ "sideEffects": false,
138
+ "devDependencies": {
139
+ "@biomejs/biome": "^2.3.11",
140
+ "@types/jest": "^30.0.0",
141
+ "@types/node": "^20.11.0",
142
+ "jest": "^30.2.0",
143
+ "ts-jest": "^29.4.6",
144
+ "typescript": "^5.3.3"
145
+ },
146
+ "peerDependencies": {
147
+ "typescript": ">=4.0.0"
148
+ },
149
+ "engines": {
150
+ "node": ">=16.0.0"
151
+ },
152
+ "dependencies": {}
153
+ }
154
+ ```
155
+
156
+ ### tsconfig.json
157
+
158
+ ```json
159
+ {
160
+ "compilerOptions": {
161
+ "target": "ES2020",
162
+ "module": "commonjs",
163
+ "lib": ["ES2020"],
164
+ "types": ["node", "jest"],
165
+ "declaration": true,
166
+ "declarationMap": true,
167
+ "sourceMap": true,
168
+ "outDir": "./dist",
169
+ "rootDir": "./src",
170
+ "strict": true,
171
+ "esModuleInterop": true,
172
+ "skipLibCheck": true,
173
+ "forceConsistentCasingInFileNames": true,
174
+ "resolveJsonModule": true,
175
+ "moduleResolution": "node"
176
+ },
177
+ "include": ["src/**/*"],
178
+ "exclude": ["node_modules", "dist", "__tests__"]
179
+ }
180
+ ```
181
+
182
+ ### jest.config.js
183
+
184
+ ```javascript
185
+ /** @type {import('jest').Config} */
186
+ module.exports = {
187
+ preset: "ts-jest",
188
+ testEnvironment: "node",
189
+ roots: ["<rootDir>/src", "<rootDir>/__tests__"],
190
+ testMatch: ["**/__tests__/**/*.test.ts", "**/?(*.)+(spec|test).ts"],
191
+ collectCoverageFrom: ["src/**/*.ts", "!src/**/*.d.ts", "!src/**/*.test.ts", "!src/**/*.spec.ts"],
192
+ coverageDirectory: "coverage",
193
+ coverageReporters: ["text", "lcov", "html"],
194
+ coverageThreshold: {
195
+ global: {
196
+ branches: 80,
197
+ functions: 80,
198
+ lines: 80,
199
+ statements: 80,
200
+ },
201
+ },
202
+ moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json"],
203
+ transform: {
204
+ "^.+\\.ts$": "ts-jest",
205
+ },
206
+ verbose: true,
207
+ clearMocks: true,
208
+ resetMocks: true,
209
+ restoreMocks: true,
210
+ };
211
+ ```
212
+
213
+ ### biome.json
214
+
215
+ ```json
216
+ {
217
+ "$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
218
+ "vcs": {
219
+ "enabled": true,
220
+ "clientKind": "git",
221
+ "useIgnoreFile": true
222
+ },
223
+ "files": {
224
+ "ignoreUnknown": false,
225
+ "includes": ["**", "!**/node_modules", "!**/dist", "!**/*.d.ts.map", "!**/*.js.map"]
226
+ },
227
+ "formatter": {
228
+ "enabled": true,
229
+ "indentStyle": "space",
230
+ "indentWidth": 2,
231
+ "lineEnding": "lf",
232
+ "lineWidth": 100,
233
+ "formatWithErrors": false
234
+ },
235
+ "assist": { "actions": { "source": { "organizeImports": "on" } } },
236
+ "linter": {
237
+ "enabled": true,
238
+ "rules": {
239
+ "recommended": true,
240
+ "complexity": {
241
+ "noBannedTypes": "error",
242
+ "noUselessTypeConstraint": "error"
243
+ },
244
+ "correctness": {
245
+ "noUnusedVariables": "error",
246
+ "useExhaustiveDependencies": "warn"
247
+ },
248
+ "style": {
249
+ "noParameterAssign": "error",
250
+ "useConst": "error",
251
+ "useTemplate": "error"
252
+ },
253
+ "suspicious": {
254
+ "noExplicitAny": "warn",
255
+ "noArrayIndexKey": "warn"
256
+ }
257
+ }
258
+ },
259
+ "javascript": {
260
+ "formatter": {
261
+ "quoteStyle": "double",
262
+ "jsxQuoteStyle": "double",
263
+ "quoteProperties": "asNeeded",
264
+ "trailingCommas": "es5",
265
+ "semicolons": "always",
266
+ "arrowParentheses": "always"
267
+ }
268
+ },
269
+ "overrides": [
270
+ {
271
+ "includes": ["**/*.test.ts", "**/*.spec.ts", "**/__tests__/**"],
272
+ "linter": {
273
+ "rules": {
274
+ "suspicious": {
275
+ "noExplicitAny": "off"
276
+ }
277
+ }
278
+ }
279
+ }
280
+ ]
281
+ }
282
+ ```
283
+
284
+ ### .gitignore
285
+
286
+ ```gitignore
287
+ # Cursor Ignore Configuration
288
+
289
+ # Version Control
290
+ .git/
291
+ .svn/
292
+ .hg/
293
+
294
+ # Build outputs
295
+ build/
296
+ dist/
297
+ out/
298
+ target/
299
+ *.exe
300
+ *.dll
301
+ *.so
302
+ *.dylib
303
+
304
+ # Dependencies
305
+ node_modules/
306
+ vendor/
307
+ .venv/
308
+ venv/
309
+ env/
310
+ __pycache__/
311
+ *.pyc
312
+
313
+ # IDE and Editor files
314
+ .idea/
315
+ .vscode/
316
+ *.swp
317
+ *.swo
318
+ *~
319
+ .DS_Store
320
+ Thumbs.db
321
+
322
+ # Logs and databases
323
+ *.log
324
+ logs/
325
+ log/
326
+ *.sqlite
327
+ *.db
328
+
329
+ # Cache and temporary files
330
+ .cache/
331
+ .temp/
332
+ tmp/
333
+ temp/
334
+ .cursor-history/
335
+
336
+ # Test coverage
337
+ coverage/
338
+ .coverage
339
+ htmlcov/
340
+
341
+ # Environment and secrets
342
+ .env
343
+ .env.local
344
+ *.pem
345
+ *.key
346
+ secrets/
347
+
348
+ # Documentation build
349
+ docs/_build/
350
+ site/
351
+
352
+ # Package files
353
+ *.tgz
354
+ *.tar.gz
355
+ *.zip
356
+ *.rar
357
+
358
+ # Lock files (use package-lock.json)
359
+ yarn.lock
360
+ pnpm-lock.yaml
361
+ ```
362
+
363
+ ### .npmignore
364
+
365
+ ```npmignore
366
+ # Source files
367
+ src/
368
+ __tests__/
369
+
370
+ # Configuration
371
+ tsconfig.json
372
+ .gitignore
373
+ .npmignore
374
+ biome.json
375
+ jest.config.js
376
+ Makefile
377
+ scripts/
378
+
379
+ # IDE
380
+ .vscode/
381
+ .idea/
382
+ *.swp
383
+ *.swo
384
+ .cursorrules
385
+ .cursorignore
386
+
387
+ # OS
388
+ .DS_Store
389
+ Thumbs.db
390
+
391
+ # Logs
392
+ *.log
393
+ npm-debug.log*
394
+
395
+ # Environment files
396
+ .env
397
+ .env.local
398
+ .env.*.local
399
+
400
+ # Testing
401
+ coverage/
402
+ .nyc_output/
403
+
404
+ # Documentation (keep README.md)
405
+ AGENTS.md
406
+ CLAUDE.md
407
+ CONTRIBUTING.md
408
+ examples/
409
+ ```
410
+
411
+ ---
412
+
413
+ ## Step 3: Create Source Files
414
+
415
+ ### src/index.ts (Main Entry Point)
416
+
417
+ ```typescript
418
+ /**
419
+ * {Name} Utilities
420
+ *
421
+ * Brief description of what this package provides.
422
+ *
423
+ * Import paths:
424
+ * - `@simpill/{name}.utils` - All exports (this file)
425
+ * - `@simpill/{name}.utils/client` - Edge-only utilities
426
+ * - `@simpill/{name}.utils/server` - Node.js-only utilities
427
+ * - `@simpill/{name}.utils/shared` - Shared utilities
428
+ */
429
+
430
+ // Client/Edge-compatible functions (no fs dependency)
431
+ export * from "./client";
432
+
433
+ // Server/Node.js utilities (requires fs)
434
+ export * from "./server";
435
+
436
+ // Shared utilities
437
+ export * from "./shared";
438
+ ```
439
+
440
+ ### src/client/index.ts
441
+
442
+ ```typescript
443
+ /**
444
+ * Client/Edge Runtime Utilities
445
+ *
446
+ * Lightweight, file-system-free utilities for edge environments.
447
+ * These functions work in Edge Runtime, browsers, and middleware.
448
+ */
449
+
450
+ // Export client-specific implementations
451
+ // export { functionName } from "./implementation-file";
452
+ ```
453
+
454
+ ### src/server/index.ts
455
+
456
+ ```typescript
457
+ /**
458
+ * Server/Node.js Utilities
459
+ *
460
+ * Full-featured utilities with Node.js API access.
461
+ * These utilities require Node.js and should not be used in edge/client environments.
462
+ */
463
+
464
+ // Export server-specific implementations
465
+ // export { ClassName, functionName } from "./implementation-file";
466
+ ```
467
+
468
+ ### src/shared/index.ts
469
+
470
+ ```typescript
471
+ /**
472
+ * Shared utilities for {name} handling.
473
+ * These are used by both client (edge) and server (node) implementations.
474
+ */
475
+
476
+ // Export shared constants, types, and pure functions
477
+ // export { CONSTANT_NAME, TypeName, helperFunction } from "./helpers";
478
+ ```
479
+
480
+ ### src/shared/constants.ts (Example)
481
+
482
+ ```typescript
483
+ /**
484
+ * Shared constants for {name}.utils
485
+ */
486
+
487
+ /** Log prefix for console messages */
488
+ export const LOG_PREFIX = "[{name}.utils]";
489
+
490
+ /** Default configuration values */
491
+ export const DEFAULTS = {
492
+ timeout: 5000,
493
+ retries: 3,
494
+ } as const;
495
+ ```
496
+
497
+ ### src/shared/errors.ts (Example)
498
+
499
+ ```typescript
500
+ /**
501
+ * Error classes for {name}.utils
502
+ */
503
+
504
+ /** Base error class for all {name}.utils errors */
505
+ export class {Name}Error extends Error {
506
+ constructor(message: string) {
507
+ super(message);
508
+ this.name = "{Name}Error";
509
+ }
510
+ }
511
+
512
+ /** Error thrown when validation fails */
513
+ export class {Name}ValidationError extends {Name}Error {
514
+ constructor(message: string) {
515
+ super(message);
516
+ this.name = "{Name}ValidationError";
517
+ }
518
+ }
519
+ ```
520
+
521
+ ---
522
+
523
+ ## Step 4: Create Scripts
524
+
525
+ ### scripts/check.sh
526
+
527
+ ```bash
528
+ #!/usr/bin/env bash
529
+ set -euo pipefail
530
+
531
+ cd "$(dirname "$0")/.."
532
+
533
+ echo "Running pre-push checks for {name}.utils"
534
+ echo "--------------------------------------"
535
+
536
+ echo "[1/5] Checking format..."
537
+ npm run format:check
538
+ echo "Format check passed."
539
+
540
+ echo "[2/5] Running linter..."
541
+ npm run lint
542
+ echo "Lint check passed."
543
+
544
+ echo "[3/5] Running type check..."
545
+ npx tsc --noEmit
546
+ echo "Type check passed."
547
+
548
+ echo "[4/5] Running tests..."
549
+ npm test
550
+ echo "Tests passed."
551
+
552
+ echo "[5/5] Verifying build..."
553
+ npm run build
554
+ echo "Build completed."
555
+
556
+ echo "--------------------------------------"
557
+ echo "All checks passed."
558
+ ```
559
+
560
+ ### scripts/install-hooks.sh
561
+
562
+ ```bash
563
+ #!/usr/bin/env bash
564
+ set -euo pipefail
565
+
566
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
567
+ PACKAGE_DIR="$(dirname "$SCRIPT_DIR")"
568
+ REPO_ROOT="$(cd "$PACKAGE_DIR/.." && pwd)"
569
+ HOOKS_DIR="$REPO_ROOT/.git/hooks"
570
+
571
+ if [ ! -d "$REPO_ROOT/.git" ]; then
572
+ echo "Not a git repository. Skipping hook installation."
573
+ exit 0
574
+ fi
575
+
576
+ mkdir -p "$HOOKS_DIR"
577
+
578
+ cat > "$HOOKS_DIR/pre-push" << 'EOF'
579
+ #!/usr/bin/env bash
580
+ set -euo pipefail
581
+
582
+ REPO_ROOT="$(git rev-parse --show-toplevel)"
583
+
584
+ if [ -x "$REPO_ROOT/{name}.utils/scripts/pre-push.sh" ]; then
585
+ "$REPO_ROOT/{name}.utils/scripts/pre-push.sh"
586
+ fi
587
+ EOF
588
+
589
+ chmod +x "$HOOKS_DIR/pre-push"
590
+
591
+ echo "Git hooks installed."
592
+ ```
593
+
594
+ ### scripts/pre-push.sh
595
+
596
+ ```bash
597
+ #!/usr/bin/env bash
598
+ set -euo pipefail
599
+
600
+ cd "$(dirname "$0")/.."
601
+ ./scripts/check.sh
602
+ ```
603
+
604
+ **Make scripts executable:**
605
+
606
+ ```bash
607
+ chmod +x ${PKG_NAME}.utils/scripts/*.sh
608
+ ```
609
+
610
+ ---
611
+
612
+ ## Step 5: Create Documentation
613
+
614
+ ### README.md
615
+
616
+ ```markdown
617
+ # @simpill/{name}.utils
618
+
619
+ Brief description of what this package does.
620
+
621
+ ## Installation
622
+
623
+ \`\`\`bash
624
+ npm install @simpill/{name}.utils
625
+ \`\`\`
626
+
627
+ ## Usage
628
+
629
+ ### Basic Usage
630
+
631
+ \`\`\`typescript
632
+ import { functionName } from "@simpill/{name}.utils";
633
+
634
+ // Example usage
635
+ const result = functionName();
636
+ \`\`\`
637
+
638
+ ### Client/Edge Runtime
639
+
640
+ \`\`\`typescript
641
+ import { clientFunction } from "@simpill/{name}.utils/client";
642
+
643
+ // Works in Edge Runtime, browsers, middleware
644
+ \`\`\`
645
+
646
+ ### Server/Node.js
647
+
648
+ \`\`\`typescript
649
+ import { ServerClass } from "@simpill/{name}.utils/server";
650
+
651
+ // Full Node.js features
652
+ \`\`\`
653
+
654
+ ## API Reference
655
+
656
+ ### Client Exports
657
+
658
+ | Export | Description |
659
+ |--------|-------------|
660
+ | `functionName` | Brief description |
661
+
662
+ ### Server Exports
663
+
664
+ | Export | Description |
665
+ |--------|-------------|
666
+ | `ClassName` | Brief description |
667
+
668
+ ### Shared Exports
669
+
670
+ | Export | Description |
671
+ |--------|-------------|
672
+ | `helperFunction` | Brief description |
673
+
674
+ ## License
675
+
676
+ ISC
677
+ ```
678
+
679
+ ### AGENTS.md
680
+
681
+ ```markdown
682
+ # Repository Guidelines
683
+
684
+ ## Project Structure & Module Organization
685
+ - `src/` contains TypeScript sources. Runtime-specific modules live in `src/client/` (Edge) and `src/server/` (Node), with shared helpers in `src/shared/`. Public exports are consolidated in `src/index.ts` and per-runtime `index.ts` files.
686
+ - `__tests__/` mirrors the runtime split (`client`, `server`, `shared`) with `unit/` and `integration/` suites.
687
+ - `examples/` holds usage samples; `dist/` is the compiled output generated by `tsc`.
688
+ - `scripts/` contains repo automation (checks and git hooks). `coverage/` is generated by Jest.
689
+
690
+ ## Build, Test, and Development Commands
691
+ - `npm run build`: compile TypeScript to `dist/`.
692
+ - `npm test`: run Jest once; `npm run test:watch` for watch mode.
693
+ - `npm run test:coverage`: generate coverage reports in `coverage/`.
694
+ - `npm run lint`, `npm run format`, `npm run check`: Biome linting/formatting.
695
+ - `npm run verify`: full pre-push suite (format check, lint, typecheck, tests, build).
696
+ - `npm run prepare`: install the git pre-push hook via `scripts/install-hooks.sh`.
697
+
698
+ ## Coding Style & Naming Conventions
699
+ - TypeScript is `strict` with a Node 16+ target; avoid widening types unnecessarily.
700
+ - Biome enforces 2-space indentation, double quotes, semicolons, trailing commas, and 100-char lines.
701
+ - File names use `kebab-case` with runtime hints when needed (e.g., `{name}.edge.ts`, `parse-helpers.ts`).
702
+ - Use `camelCase` for variables/functions and `PascalCase` for types/classes. Keep exports wired through the relevant `index.ts` barrel files.
703
+
704
+ ## Testing Guidelines
705
+ - Jest + `ts-jest` with tests under `__tests__/`.
706
+ - Naming convention: `*.unit.test.ts` and `*.integration.test.ts`.
707
+ - Add tests in the matching domain folder (`client`, `server`, `shared`).
708
+ - Maintain 80%+ coverage across branches, functions, lines, and statements.
709
+
710
+ ## Commit & Pull Request Guidelines
711
+ - Use Conventional Commits like `feat:`, `fix:`, or `chore:` with optional scopes (e.g., `feat(server): add parser`).
712
+ - PRs should summarize intent, list test commands run, and note any API changes.
713
+ - Update `README.md` or `examples/` when public behavior or exports change.
714
+ ```
715
+
716
+ ### CLAUDE.md
717
+
718
+ ```markdown
719
+ # CLAUDE.md
720
+
721
+ This file provides guidance to Claude Code when working with this package.
722
+
723
+ ## Package Overview
724
+
725
+ `@simpill/{name}.utils` provides [brief description].
726
+
727
+ ## Key Files
728
+
729
+ | File | Purpose |
730
+ |------|---------|
731
+ | `src/index.ts` | Main entry point, re-exports all |
732
+ | `src/client/index.ts` | Edge/browser exports |
733
+ | `src/server/index.ts` | Node.js exports |
734
+ | `src/shared/index.ts` | Shared utilities |
735
+
736
+ ## Quick Commands
737
+
738
+ \`\`\`bash
739
+ npm run build # Compile TypeScript
740
+ npm test # Run tests
741
+ npm run test:coverage # Tests with coverage
742
+ npm run check:fix # Fix lint + format
743
+ npm run verify # All pre-push checks
744
+ \`\`\`
745
+
746
+ ## Architecture
747
+
748
+ - **client/**: No `fs` module, works in Edge Runtime
749
+ - **server/**: Full Node.js access
750
+ - **shared/**: Pure functions, no runtime dependencies
751
+
752
+ ## Testing
753
+
754
+ Tests mirror the `src/` structure:
755
+ - `__tests__/client/unit/` - Client unit tests
756
+ - `__tests__/server/unit/` - Server unit tests
757
+ - `__tests__/shared/unit/` - Shared unit tests
758
+
759
+ Naming: `{feature}.unit.test.ts` or `{feature}.integration.test.ts`
760
+ ```
761
+
762
+ ---
763
+
764
+ ## Step 6: Create CI/CD Workflows
765
+
766
+ ### .github/workflows/{name}-utils-ci.yml
767
+
768
+ ```yaml
769
+ name: {name}.utils CI
770
+
771
+ on:
772
+ push:
773
+ branches:
774
+ - main
775
+ - develop
776
+ paths:
777
+ - "{name}.utils/**"
778
+ - ".github/workflows/{name}-utils-ci.yml"
779
+ pull_request:
780
+ branches:
781
+ - main
782
+ - develop
783
+ paths:
784
+ - "{name}.utils/**"
785
+ - ".github/workflows/{name}-utils-ci.yml"
786
+
787
+ defaults:
788
+ run:
789
+ working-directory: {name}.utils
790
+
791
+ jobs:
792
+ lint:
793
+ name: Lint & Format
794
+ runs-on: ubuntu-latest
795
+ steps:
796
+ - name: Checkout
797
+ uses: actions/checkout@v4
798
+
799
+ - name: Setup Node.js
800
+ uses: actions/setup-node@v4
801
+ with:
802
+ node-version: "20"
803
+ cache: "npm"
804
+ cache-dependency-path: {name}.utils/package-lock.json
805
+
806
+ - name: Install dependencies
807
+ run: npm ci
808
+
809
+ - name: Check formatting
810
+ run: npm run format:check
811
+
812
+ - name: Lint
813
+ run: npm run lint
814
+
815
+ test:
816
+ name: Test (Node ${{ matrix.node-version }})
817
+ runs-on: ubuntu-latest
818
+ strategy:
819
+ matrix:
820
+ node-version: ["18", "20", "22"]
821
+ steps:
822
+ - name: Checkout
823
+ uses: actions/checkout@v4
824
+
825
+ - name: Setup Node.js ${{ matrix.node-version }}
826
+ uses: actions/setup-node@v4
827
+ with:
828
+ node-version: ${{ matrix.node-version }}
829
+ cache: "npm"
830
+ cache-dependency-path: {name}.utils/package-lock.json
831
+
832
+ - name: Install dependencies
833
+ run: npm ci
834
+
835
+ - name: Run tests
836
+ run: npm test
837
+
838
+ coverage:
839
+ name: Coverage
840
+ runs-on: ubuntu-latest
841
+ steps:
842
+ - name: Checkout
843
+ uses: actions/checkout@v4
844
+
845
+ - name: Setup Node.js
846
+ uses: actions/setup-node@v4
847
+ with:
848
+ node-version: "20"
849
+ cache: "npm"
850
+ cache-dependency-path: {name}.utils/package-lock.json
851
+
852
+ - name: Install dependencies
853
+ run: npm ci
854
+
855
+ - name: Run tests with coverage
856
+ run: npm run test:coverage
857
+
858
+ - name: Upload coverage reports
859
+ uses: codecov/codecov-action@v4
860
+ with:
861
+ directory: {name}.utils/coverage
862
+ flags: {name}-utils
863
+ fail_ci_if_error: false
864
+ env:
865
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
866
+
867
+ build:
868
+ name: Build
869
+ runs-on: ubuntu-latest
870
+ steps:
871
+ - name: Checkout
872
+ uses: actions/checkout@v4
873
+
874
+ - name: Setup Node.js
875
+ uses: actions/setup-node@v4
876
+ with:
877
+ node-version: "20"
878
+ cache: "npm"
879
+ cache-dependency-path: {name}.utils/package-lock.json
880
+
881
+ - name: Install dependencies
882
+ run: npm ci
883
+
884
+ - name: Build
885
+ run: npm run build
886
+
887
+ - name: Verify dist output
888
+ run: |
889
+ test -f dist/index.js
890
+ test -f dist/index.d.ts
891
+ test -f dist/client/index.js
892
+ test -f dist/client/index.d.ts
893
+ test -f dist/server/index.js
894
+ test -f dist/server/index.d.ts
895
+ test -f dist/shared/index.js
896
+ test -f dist/shared/index.d.ts
897
+
898
+ typecheck:
899
+ name: Type Check
900
+ runs-on: ubuntu-latest
901
+ steps:
902
+ - name: Checkout
903
+ uses: actions/checkout@v4
904
+
905
+ - name: Setup Node.js
906
+ uses: actions/setup-node@v4
907
+ with:
908
+ node-version: "20"
909
+ cache: "npm"
910
+ cache-dependency-path: {name}.utils/package-lock.json
911
+
912
+ - name: Install dependencies
913
+ run: npm ci
914
+
915
+ - name: Type check
916
+ run: npx tsc --noEmit
917
+ ```
918
+
919
+ ---
920
+
921
+ ## Step 7: Initialize and Verify
922
+
923
+ ```bash
924
+ cd ${PKG_NAME}.utils
925
+
926
+ # Install dependencies
927
+ npm install
928
+
929
+ # Run all checks
930
+ npm run verify
931
+ ```
932
+
933
+ ---
934
+
935
+ ## Checklist
936
+
937
+ ### Initial Setup
938
+
939
+ - [ ] Create package directory: `{name}.utils/`
940
+ - [ ] Create `src/` directory structure (`client/`, `server/`, `shared/`)
941
+ - [ ] Create `__tests__/` directory structure (mirrors `src/`)
942
+ - [ ] Create `scripts/` directory with `check.sh`, `install-hooks.sh`, `pre-push.sh`
943
+ - [ ] Make scripts executable: `chmod +x scripts/*.sh`
944
+
945
+ ### Configuration Files
946
+
947
+ - [ ] `package.json` with correct name, exports, and scripts
948
+ - [ ] `tsconfig.json` with strict mode
949
+ - [ ] `jest.config.js` with coverage thresholds
950
+ - [ ] `biome.json` with standard rules
951
+ - [ ] `.gitignore`
952
+ - [ ] `.npmignore`
953
+
954
+ ### Documentation
955
+
956
+ - [ ] `README.md` with installation, usage, and API reference
957
+ - [ ] `AGENTS.md` with package-specific AI guidelines
958
+ - [ ] `CLAUDE.md` with Claude-specific instructions
959
+
960
+ ### Source Code
961
+
962
+ - [ ] `src/index.ts` main entry point
963
+ - [ ] `src/client/index.ts` client exports
964
+ - [ ] `src/server/index.ts` server exports
965
+ - [ ] `src/shared/index.ts` shared exports
966
+ - [ ] Implementation files in appropriate directories
967
+
968
+ ### Tests
969
+
970
+ - [ ] Unit tests for all public APIs
971
+ - [ ] Integration tests where applicable
972
+ - [ ] 80%+ coverage achieved
973
+ - [ ] All tests passing
974
+
975
+ ### CI/CD
976
+
977
+ - [ ] `.github/workflows/{name}-utils-ci.yml`
978
+
979
+ ### Final Verification
980
+
981
+ - [ ] `npm run verify` passes all checks
982
+ - [ ] `npm run build` produces valid output
983
+ - [ ] Package can be imported correctly
984
+ - [ ] Subpath exports work as expected
985
+
986
+ ---
987
+
988
+ ## Example Test File
989
+
990
+ ### \_\_tests\_\_/shared/unit/helpers.unit.test.ts
991
+
992
+ ```typescript
993
+ /**
994
+ * @file Helpers Unit Tests
995
+ * @description Tests for shared helper functions
996
+ */
997
+
998
+ describe("helperFunction", () => {
999
+ beforeEach(() => {
1000
+ // Setup
1001
+ });
1002
+
1003
+ afterEach(() => {
1004
+ // Cleanup
1005
+ });
1006
+
1007
+ describe("basic functionality", () => {
1008
+ it("should return expected result for valid input", () => {
1009
+ // Arrange
1010
+ const input = "test";
1011
+
1012
+ // Act
1013
+ const result = helperFunction(input);
1014
+
1015
+ // Assert
1016
+ expect(result).toBe("expected");
1017
+ });
1018
+
1019
+ it("should handle edge case: empty string", () => {
1020
+ expect(helperFunction("")).toBe("");
1021
+ });
1022
+
1023
+ it("should throw when input is invalid", () => {
1024
+ expect(() => {
1025
+ helperFunction(null as any);
1026
+ }).toThrow(ValidationError);
1027
+ });
1028
+ });
1029
+ });
1030
+ ```
1031
+
1032
+ ---
1033
+
1034
+ ## Notes
1035
+
1036
+ - Replace all `{name}` placeholders with your actual package name (lowercase)
1037
+ - Replace all `{Name}` placeholders with PascalCase version for class names
1038
+ - Add package-specific dependencies to `package.json` as needed
1039
+ - Update keywords in `package.json` to match your package's purpose
1040
+ - The `examples/` directory structure is optional but recommended