Initial commit
This commit is contained in:
252
skills/typescript-standards/README.md
Normal file
252
skills/typescript-standards/README.md
Normal file
@@ -0,0 +1,252 @@
|
||||
# TypeScript Standards Skill
|
||||
|
||||
Claude Code skill for creating and standardizing TypeScript library projects.
|
||||
|
||||
## Overview
|
||||
|
||||
This skill provides comprehensive guidance for:
|
||||
|
||||
- Creating new TypeScript libraries from the typescript-library-template
|
||||
- Applying standardized tooling and scripts to existing projects
|
||||
- Configuring modern build tools (tsup, Vitest, ESLint, Prettier)
|
||||
- Setting up dual module format (CommonJS + ES modules)
|
||||
|
||||
## Skill Contents
|
||||
|
||||
```
|
||||
typescript-standards/
|
||||
├── SKILL.md # Main skill guide (loaded by Claude Code)
|
||||
└── references/
|
||||
├── template-setup.md # Complete guide for new projects
|
||||
├── standardization.md # Migration guide for existing projects
|
||||
└── tooling-reference.md # Configuration reference for all tools
|
||||
```
|
||||
|
||||
## When Claude Code Uses This Skill
|
||||
|
||||
The skill automatically activates when:
|
||||
|
||||
- Creating new TypeScript libraries or npm packages
|
||||
- Standardizing build scripts across TypeScript projects
|
||||
- Setting up or migrating to dual module format
|
||||
- Configuring tsup, Vitest, ESLint, or Prettier
|
||||
- Publishing packages to npm
|
||||
- Migrating from webpack, rollup, Jest, or other tools
|
||||
|
||||
## Installation
|
||||
|
||||
### For Use in Other Projects
|
||||
|
||||
```bash
|
||||
# Copy to Claude Code skills directory
|
||||
cp -r .claude/skills/typescript-standards ~/.claude/skills/
|
||||
|
||||
# Verify installation
|
||||
ls ~/.claude/skills/typescript-standards
|
||||
```
|
||||
|
||||
### For Marketplace Distribution
|
||||
|
||||
This skill is configured for marketplace distribution via `.claude-plugin/marketplace.json`.
|
||||
|
||||
## Key Features
|
||||
|
||||
### 1. Template Setup Guide
|
||||
|
||||
Complete walkthrough for creating new libraries:
|
||||
|
||||
- Clone and customize the template
|
||||
- Project configuration checklist
|
||||
- Development workflow
|
||||
- Publishing to npm
|
||||
- CI/CD setup
|
||||
|
||||
See: `references/template-setup.md`
|
||||
|
||||
### 2. Standardization Guide
|
||||
|
||||
Migrate existing projects to template standards:
|
||||
|
||||
- Step-by-step migration process
|
||||
- Tool-by-tool configuration updates
|
||||
- Test migration (Jest → Vitest)
|
||||
- Build migration (webpack/rollup → tsup)
|
||||
- Common issues and solutions
|
||||
|
||||
See: `references/standardization.md`
|
||||
|
||||
### 3. Tooling Reference
|
||||
|
||||
Comprehensive configuration reference:
|
||||
|
||||
- tsup - Build configuration with all options
|
||||
- Vitest - Testing configuration and patterns
|
||||
- ESLint - Flat config format with TypeScript
|
||||
- Prettier - Code formatting standards
|
||||
- TypeScript - Strict mode configuration
|
||||
|
||||
See: `references/tooling-reference.md`
|
||||
|
||||
## Standardized Commands
|
||||
|
||||
The skill teaches this consistent command pattern:
|
||||
|
||||
```bash
|
||||
# Main validation
|
||||
pnpm validate # Format → Lint → Test → Build
|
||||
|
||||
# Individual operations
|
||||
pnpm format # Write formatted code
|
||||
pnpm format:check # Validate formatting only
|
||||
pnpm lint # Fix ESLint issues
|
||||
pnpm lint:check # Check linting only
|
||||
pnpm test # Run tests
|
||||
pnpm test:watch # Watch mode
|
||||
pnpm test:coverage # With coverage
|
||||
pnpm build # Production build
|
||||
pnpm dev # Development watch
|
||||
```
|
||||
|
||||
## Core Principles
|
||||
|
||||
1. **Consistency** - Same commands work across all projects
|
||||
2. **Dual Format** - CommonJS + ES modules with TypeScript declarations
|
||||
3. **Type Safety** - Strict TypeScript with pragmatic exceptions
|
||||
4. **Modern Tooling** - Fast builds (tsup), fast tests (Vitest)
|
||||
5. **Quality Gates** - Single `validate` command ensures everything passes
|
||||
|
||||
## Example Usage
|
||||
|
||||
### Creating a New Library
|
||||
|
||||
```typescript
|
||||
// User: "Create a new TypeScript library for date utilities"
|
||||
// Claude Code (using this skill):
|
||||
// 1. Guides through cloning template
|
||||
// 2. Provides customization checklist
|
||||
// 3. Explains development workflow
|
||||
// 4. Assists with implementation
|
||||
// 5. Validates before publish
|
||||
```
|
||||
|
||||
### Standardizing Existing Project
|
||||
|
||||
```typescript
|
||||
// User: "Apply typescript-library-template standards to this project"
|
||||
// Claude Code (using this skill):
|
||||
// 1. Analyzes current setup
|
||||
// 2. Proposes migration plan
|
||||
// 3. Updates dependencies
|
||||
// 4. Copies configurations
|
||||
// 5. Migrates tests and build
|
||||
// 6. Validates everything works
|
||||
```
|
||||
|
||||
## Configuration Templates
|
||||
|
||||
The skill provides complete, working configurations for:
|
||||
|
||||
### tsup.config.ts
|
||||
|
||||
Environment-based builds with dual format output
|
||||
|
||||
### vitest.config.ts
|
||||
|
||||
Testing with coverage and multiple reporters
|
||||
|
||||
### eslint.config.mjs
|
||||
|
||||
Flat config with TypeScript, Prettier, and import sorting
|
||||
|
||||
### package.json
|
||||
|
||||
Standardized scripts and dual module exports
|
||||
|
||||
### tsconfig.json
|
||||
|
||||
Strict TypeScript with pragmatic defaults
|
||||
|
||||
## Validation Checklist
|
||||
|
||||
The skill ensures projects meet these standards:
|
||||
|
||||
- [ ] Dual module format (CJS + ESM + types)
|
||||
- [ ] Standardized scripts (`validate`, `format`, `lint`, etc.)
|
||||
- [ ] Modern build tool (tsup)
|
||||
- [ ] Modern test framework (Vitest)
|
||||
- [ ] Strict TypeScript configuration
|
||||
- [ ] ESLint + Prettier integration
|
||||
- [ ] Pre-publish validation (`prepublishOnly`)
|
||||
- [ ] Proper package.json exports
|
||||
- [ ] Documentation (CLAUDE.md, README.md)
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### Multiple Entry Points
|
||||
|
||||
The skill guides setting up subpath exports:
|
||||
|
||||
```json
|
||||
{
|
||||
"exports": {
|
||||
".": "./dist/index.js",
|
||||
"./utils": "./dist/utils.js"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Build Configurations
|
||||
|
||||
Adapting tsup for specific needs:
|
||||
|
||||
- Browser-compatible builds
|
||||
- Peer dependency handling
|
||||
- Custom minification
|
||||
- Code splitting
|
||||
|
||||
### Migration Patterns
|
||||
|
||||
Common migration scenarios:
|
||||
|
||||
- webpack → tsup
|
||||
- rollup → tsup
|
||||
- Jest → Vitest
|
||||
- TSLint → ESLint
|
||||
- Old ESLint configs → Flat config
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
The skill includes solutions for common issues:
|
||||
|
||||
- Module resolution errors
|
||||
- Test migration problems
|
||||
- Build configuration issues
|
||||
- Type generation failures
|
||||
- Dual format compatibility
|
||||
|
||||
## Resources
|
||||
|
||||
- **Template Repository**: https://github.com/jordanburke/typescript-library-template
|
||||
- **Example Implementation**: See the functype project for advanced usage
|
||||
- **Marketplace Distribution**: `.claude-plugin/marketplace.json`
|
||||
|
||||
## Contributing
|
||||
|
||||
To improve this skill:
|
||||
|
||||
1. Edit files in `.claude/skills/typescript-standards/`
|
||||
2. Test changes with Claude Code
|
||||
3. Update documentation as needed
|
||||
4. Commit changes to the repository
|
||||
|
||||
## Version History
|
||||
|
||||
- **1.0.0** - Initial release
|
||||
- Template setup guide
|
||||
- Standardization guide
|
||||
- Tooling reference
|
||||
- Marketplace configuration
|
||||
|
||||
## License
|
||||
|
||||
MIT - Same as the typescript-library-template repository
|
||||
371
skills/typescript-standards/SKILL.md
Normal file
371
skills/typescript-standards/SKILL.md
Normal file
@@ -0,0 +1,371 @@
|
||||
---
|
||||
name: typescript-standards
|
||||
description: Guide for creating TypeScript libraries using the typescript-library-template pattern and applying its standards to existing projects. Use when setting up new npm packages, standardizing build scripts, configuring tooling (tsup, Vitest, ESLint, Prettier), or applying dual module format patterns.
|
||||
---
|
||||
|
||||
# TypeScript Project Standards
|
||||
|
||||
## Overview
|
||||
|
||||
This skill helps you create professional TypeScript libraries using the typescript-library-template pattern and apply these standards to existing projects. It provides a modern, production-ready setup with dual module format support, comprehensive testing, and consistent code quality tooling.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Trigger this skill when:
|
||||
|
||||
- Creating a new TypeScript library or npm package
|
||||
- Standardizing build scripts across TypeScript projects
|
||||
- Setting up or migrating to dual module format (CommonJS + ES modules)
|
||||
- Configuring modern tooling (tsup, Vitest, ESLint, Prettier)
|
||||
- Applying consistent code quality standards
|
||||
- Publishing packages to npm
|
||||
- Migrating from older build tools (webpack, rollup, tsc alone)
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Scenario 1: Creating a New Project
|
||||
|
||||
```bash
|
||||
# Clone the template
|
||||
git clone https://github.com/jordanburke/typescript-library-template.git my-library
|
||||
cd my-library
|
||||
|
||||
# Remove template's git history
|
||||
rm -rf .git
|
||||
git init
|
||||
|
||||
# Install dependencies
|
||||
pnpm install
|
||||
|
||||
# Customize (see references/template-setup.md for checklist)
|
||||
# - Update package.json (name, description, repository)
|
||||
# - Update README.md
|
||||
# - Add your code to src/
|
||||
|
||||
# Validate everything works
|
||||
pnpm validate
|
||||
```
|
||||
|
||||
### Scenario 2: Applying Standards to Existing Project
|
||||
|
||||
See `references/standardization.md` for detailed migration guide. Quick version:
|
||||
|
||||
1. **Update scripts** in package.json to standardized pattern
|
||||
2. **Install tooling**: tsup, vitest, eslint, prettier
|
||||
3. **Copy configs**: tsup.config.ts, vitest.config.ts, eslint.config.mjs
|
||||
4. **Update build outputs**: Dual module format with proper exports
|
||||
5. **Run validation**: `pnpm validate`
|
||||
|
||||
## Core Standards
|
||||
|
||||
### Script Commands
|
||||
|
||||
The template follows a consistent command pattern:
|
||||
|
||||
**Main validation command:**
|
||||
|
||||
```bash
|
||||
pnpm validate # Format → Lint → Test → Build (use before commits)
|
||||
```
|
||||
|
||||
**Individual operations:**
|
||||
|
||||
```bash
|
||||
# Formatting
|
||||
pnpm format # Write formatted code
|
||||
pnpm format:check # Validate formatting only
|
||||
|
||||
# Linting
|
||||
pnpm lint # Fix ESLint issues
|
||||
pnpm lint:check # Check ESLint issues only
|
||||
|
||||
# Testing
|
||||
pnpm test # Run tests once
|
||||
pnpm test:watch # Watch mode
|
||||
pnpm test:coverage # With coverage report
|
||||
pnpm test:ui # Interactive UI
|
||||
|
||||
# Building
|
||||
pnpm build # Production build (dist/)
|
||||
pnpm dev # Development watch (lib/)
|
||||
pnpm ts-types # Type check only
|
||||
```
|
||||
|
||||
### Dual Module Format
|
||||
|
||||
The template supports both CommonJS and ES modules:
|
||||
|
||||
**package.json exports:**
|
||||
|
||||
```json
|
||||
{
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"require": "./dist/index.js",
|
||||
"import": "./dist/index.mjs"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Build outputs:**
|
||||
|
||||
- `lib/` - Development builds (NODE_ENV !== "production")
|
||||
- `dist/` - Production builds (NODE_ENV === "production")
|
||||
- Both directories published to npm
|
||||
|
||||
### Build Configuration (tsup)
|
||||
|
||||
Key features:
|
||||
|
||||
- Environment-based output (lib/ vs dist/)
|
||||
- Dual format (CJS + ESM)
|
||||
- TypeScript declarations for both formats
|
||||
- Source maps in development
|
||||
- Minification in production
|
||||
- Watch mode for development
|
||||
|
||||
### Testing (Vitest)
|
||||
|
||||
Configuration highlights:
|
||||
|
||||
- Node.js environment
|
||||
- v8 coverage provider
|
||||
- Multiple reporters (text, json, html)
|
||||
- Hot reload in watch mode
|
||||
- UI mode available
|
||||
|
||||
### Code Quality
|
||||
|
||||
**ESLint:**
|
||||
|
||||
- Flat config (eslint.config.mjs)
|
||||
- TypeScript support
|
||||
- Prettier integration
|
||||
- Import sorting with simple-import-sort
|
||||
- Strict type checking
|
||||
|
||||
**Prettier:**
|
||||
|
||||
- No semicolons
|
||||
- Trailing commas
|
||||
- Double quotes
|
||||
- 120 character width
|
||||
- 2 space tabs
|
||||
|
||||
**TypeScript:**
|
||||
|
||||
- Strict mode enabled
|
||||
- Pragmatic exceptions:
|
||||
- `noImplicitAny: false`
|
||||
- `strictPropertyInitialization: false`
|
||||
- ESNext target
|
||||
- Declaration files only (tsup handles transpilation)
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### Creating a New Library
|
||||
|
||||
1. **Clone and customize** (see references/template-setup.md)
|
||||
2. **Develop** with `pnpm dev` (watch mode)
|
||||
3. **Test** with `pnpm test:watch`
|
||||
4. **Validate** with `pnpm validate` before commits
|
||||
5. **Publish** with `npm publish` (prepublishOnly auto-validates)
|
||||
|
||||
### Standardizing an Existing Project
|
||||
|
||||
1. **Audit current setup** - identify gaps
|
||||
2. **Update package.json** - scripts and dependencies
|
||||
3. **Copy configurations** - tsup, vitest, eslint
|
||||
4. **Migrate build** - switch to tsup with dual format
|
||||
5. **Update exports** - proper dual module support
|
||||
6. **Test thoroughly** - ensure all builds work
|
||||
7. **Update documentation** - new commands and workflows
|
||||
|
||||
### Publishing to npm
|
||||
|
||||
The template includes safety checks:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"prepublishOnly": "pnpm validate"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This ensures every publish:
|
||||
|
||||
1. Formats code correctly
|
||||
2. Passes all linting
|
||||
3. Passes all tests
|
||||
4. Builds successfully
|
||||
|
||||
**Publishing workflow:**
|
||||
|
||||
```bash
|
||||
# Update version
|
||||
npm version patch # or minor, major
|
||||
|
||||
# Publish (prepublishOnly runs automatically)
|
||||
npm publish --access public
|
||||
```
|
||||
|
||||
## Architecture Patterns
|
||||
|
||||
### Environment-Based Builds
|
||||
|
||||
The tsup configuration (line 3 in tsup.config.ts) checks `NODE_ENV`:
|
||||
|
||||
```typescript
|
||||
const isDev = process.env.NODE_ENV !== "production"
|
||||
|
||||
export default defineConfig({
|
||||
outDir: isDev ? "lib" : "dist",
|
||||
minify: !isDev,
|
||||
sourcemap: isDev,
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
**Why two output directories?**
|
||||
|
||||
- `lib/` - Fast development builds, easier debugging
|
||||
- `dist/` - Optimized production builds, what npm gets
|
||||
|
||||
### File Organization
|
||||
|
||||
```
|
||||
project/
|
||||
├── src/
|
||||
│ ├── index.ts # Main entry point
|
||||
│ └── **/*.ts # All source files
|
||||
├── test/
|
||||
│ └── *.spec.ts # Vitest tests
|
||||
├── lib/ # Dev builds (gitignored)
|
||||
├── dist/ # Prod builds (gitignored)
|
||||
├── tsup.config.ts # Build config
|
||||
├── vitest.config.ts # Test config
|
||||
├── eslint.config.mjs # Lint config
|
||||
├── .prettierrc # Format config (optional)
|
||||
└── package.json # Scripts + exports
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Build Issues
|
||||
|
||||
**"Cannot find module" errors:**
|
||||
|
||||
- Check package.json exports match build outputs
|
||||
- Verify both .js and .mjs files exist in dist/
|
||||
- Ensure types field points to .d.ts file
|
||||
|
||||
**Watch mode not working:**
|
||||
|
||||
- Check tsup.config.ts has watch: true for dev
|
||||
- Verify NODE_ENV is not set to "production"
|
||||
|
||||
### Test Issues
|
||||
|
||||
**Tests not found:**
|
||||
|
||||
- Check vitest.config.ts includes correct pattern
|
||||
- Verify test files end in .spec.ts or .test.ts
|
||||
- Ensure test/ directory exists
|
||||
|
||||
**Coverage incomplete:**
|
||||
|
||||
- Check coverage.include in vitest.config.ts
|
||||
- Add exclude patterns for generated files
|
||||
|
||||
### Import Issues
|
||||
|
||||
**Dual module problems:**
|
||||
|
||||
- Verify package.json exports use correct paths
|
||||
- Check tsup generates both .js and .mjs
|
||||
- Test with both `require()` and `import`
|
||||
|
||||
**Type definitions missing:**
|
||||
|
||||
- Ensure tsup config has `dts: true`
|
||||
- Check .d.ts files generated in dist/
|
||||
- Verify types field in package.json
|
||||
|
||||
## Migration Checklist
|
||||
|
||||
When applying these standards to an existing project:
|
||||
|
||||
- [ ] Update package.json scripts to standardized pattern
|
||||
- [ ] Install required devDependencies (tsup, vitest, eslint, prettier)
|
||||
- [ ] Copy tsup.config.ts and adjust for your project
|
||||
- [ ] Copy vitest.config.ts and adjust test patterns
|
||||
- [ ] Copy eslint.config.mjs and adjust rules if needed
|
||||
- [ ] Add/update .prettierrc with standard config
|
||||
- [ ] Update tsconfig.json for strict mode
|
||||
- [ ] Update package.json exports for dual module format
|
||||
- [ ] Migrate tests to Vitest (if using different framework)
|
||||
- [ ] Update GitHub Actions to use `pnpm validate`
|
||||
- [ ] Update documentation (README, CLAUDE.md)
|
||||
- [ ] Test with `pnpm validate`
|
||||
- [ ] Verify published package works in both CJS and ESM projects
|
||||
|
||||
## Resources
|
||||
|
||||
### Reference Documents
|
||||
|
||||
- **references/template-setup.md** - Complete guide for using the template
|
||||
- **references/standardization.md** - Detailed migration guide for existing projects
|
||||
- **references/tooling-reference.md** - Configuration examples and patterns
|
||||
|
||||
### External Links
|
||||
|
||||
- **GitHub Template**: https://github.com/jordanburke/typescript-library-template
|
||||
- **tsup Documentation**: https://tsup.egoist.dev/
|
||||
- **Vitest Documentation**: https://vitest.dev/
|
||||
- **ESLint Flat Config**: https://eslint.org/docs/latest/use/configure/configuration-files
|
||||
|
||||
### Key Files to Reference
|
||||
|
||||
When working with this template, these files contain the canonical configurations:
|
||||
|
||||
- `tsup.config.ts` - Build configuration with environment logic
|
||||
- `vitest.config.ts` - Test configuration with coverage
|
||||
- `eslint.config.mjs` - Linting rules and TypeScript integration
|
||||
- `package.json` - Scripts, exports, and dependency versions
|
||||
- `STANDARDIZATION_GUIDE.md` - Migration instructions
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Development Workflow
|
||||
|
||||
1. **Always use `pnpm dev`** during development for fast rebuilds
|
||||
2. **Run `pnpm validate`** before committing changes
|
||||
3. **Use `pnpm test:watch`** while writing tests
|
||||
4. **Check `pnpm test:coverage`** to ensure adequate coverage
|
||||
|
||||
### Code Quality
|
||||
|
||||
1. **Enable strict TypeScript** - catches issues early
|
||||
2. **Fix linting issues** - don't disable rules without good reason
|
||||
3. **Write tests** - aim for high coverage on critical paths
|
||||
4. **Format consistently** - let Prettier handle style
|
||||
|
||||
### Publishing
|
||||
|
||||
1. **Test locally** - use `npm link` to test before publishing
|
||||
2. **Version semantically** - follow semver (major.minor.patch)
|
||||
3. **Update changelog** - document changes for users
|
||||
4. **Verify dual format** - test in both CJS and ESM projects
|
||||
|
||||
### Documentation
|
||||
|
||||
1. **Keep CLAUDE.md updated** - helps Claude Code assist you
|
||||
2. **Document commands** - clear examples for all scripts
|
||||
3. **Explain architecture** - help future maintainers
|
||||
4. **Link to references** - point to this skill for standards
|
||||
718
skills/typescript-standards/references/standardization.md
Normal file
718
skills/typescript-standards/references/standardization.md
Normal file
@@ -0,0 +1,718 @@
|
||||
# Project Standardization Guide
|
||||
|
||||
Complete guide for applying typescript-library-template standards to existing TypeScript projects.
|
||||
|
||||
## Overview
|
||||
|
||||
This guide helps you migrate existing TypeScript projects to use the standardized tooling, build configuration, and workflow from typescript-library-template.
|
||||
|
||||
## Pre-Migration Assessment
|
||||
|
||||
Before starting, analyze your current project:
|
||||
|
||||
### Current State Checklist
|
||||
|
||||
- [ ] What build tool are you using? (webpack, rollup, tsc, etc.)
|
||||
- [ ] What test framework? (Jest, Mocha, AVA, etc.)
|
||||
- [ ] Current linting setup? (ESLint with what config?)
|
||||
- [ ] Module format? (CJS only, ESM only, or dual?)
|
||||
- [ ] TypeScript configuration? (strict mode? target?)
|
||||
- [ ] Script command naming? (build vs compile, test vs spec?)
|
||||
|
||||
### Compatibility Check
|
||||
|
||||
This standardization works best for:
|
||||
|
||||
- ✅ TypeScript libraries or packages
|
||||
- ✅ Node.js modules (not browser-only apps)
|
||||
- ✅ Projects targeting dual module format
|
||||
- ✅ npm packages intended for publishing
|
||||
|
||||
May require adaptation for:
|
||||
|
||||
- ⚠️ React/Vue/Angular applications (keep framework tooling)
|
||||
- ⚠️ Browser-only libraries (may not need CJS)
|
||||
- ⚠️ Projects with complex webpack configs (evaluate if tsup can replace)
|
||||
- ⚠️ Monorepos (apply per package, not root)
|
||||
|
||||
## Migration Steps
|
||||
|
||||
### Step 1: Backup Current Project
|
||||
|
||||
```bash
|
||||
# Create a backup branch
|
||||
git checkout -b pre-standardization-backup
|
||||
|
||||
# Or create a full copy
|
||||
cp -r . ../project-backup
|
||||
```
|
||||
|
||||
### Step 2: Update package.json Scripts
|
||||
|
||||
Replace your existing scripts with the standardized pattern:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"validate": "pnpm format && pnpm lint && pnpm test && pnpm build",
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check .",
|
||||
"lint": "eslint ./src --fix",
|
||||
"lint:check": "eslint ./src",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
"test:ui": "vitest --ui",
|
||||
"build": "rimraf dist && cross-env NODE_ENV=production tsup",
|
||||
"build:watch": "tsup --watch",
|
||||
"dev": "tsup --watch",
|
||||
"prepublishOnly": "pnpm validate",
|
||||
"ts-types": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key changes:**
|
||||
|
||||
- `validate` as the main pre-checkin command
|
||||
- Clear separation: `format` vs `format:check`, `lint` vs `lint:check`
|
||||
- Vitest for testing (replaces Jest/Mocha)
|
||||
- tsup for building (replaces webpack/rollup/tsc)
|
||||
- `dev` for watch mode development
|
||||
|
||||
### Step 3: Update Dependencies
|
||||
|
||||
**Remove old dependencies:**
|
||||
|
||||
```bash
|
||||
# Build tools (if using these)
|
||||
pnpm remove webpack webpack-cli rollup @rollup/plugin-typescript
|
||||
|
||||
# Test frameworks (if using these)
|
||||
pnpm remove jest ts-jest @types/jest mocha chai
|
||||
|
||||
# Old linting (if using these)
|
||||
pnpm remove tslint
|
||||
```
|
||||
|
||||
**Install new dependencies:**
|
||||
|
||||
```bash
|
||||
# Build tool
|
||||
pnpm add -D tsup cross-env rimraf
|
||||
|
||||
# Testing
|
||||
pnpm add -D vitest @vitest/coverage-v8 @vitest/ui
|
||||
|
||||
# Linting and formatting
|
||||
pnpm add -D eslint @eslint/js @eslint/eslintrc
|
||||
pnpm add -D @typescript-eslint/parser @typescript-eslint/eslint-plugin
|
||||
pnpm add -D eslint-config-prettier eslint-plugin-prettier
|
||||
pnpm add -D eslint-plugin-simple-import-sort eslint-plugin-import
|
||||
pnpm add -D prettier
|
||||
|
||||
# TypeScript
|
||||
pnpm add -D typescript @types/node ts-node
|
||||
|
||||
# Utilities
|
||||
pnpm add -D globals
|
||||
```
|
||||
|
||||
### Step 4: Create tsup Configuration
|
||||
|
||||
Create `tsup.config.ts` in project root:
|
||||
|
||||
```typescript
|
||||
import { defineConfig } from "tsup"
|
||||
|
||||
const isDev = process.env.NODE_ENV !== "production"
|
||||
|
||||
export default defineConfig({
|
||||
entry: ["src/index.ts"],
|
||||
format: ["cjs", "esm"],
|
||||
dts: true,
|
||||
splitting: false,
|
||||
sourcemap: isDev,
|
||||
clean: true,
|
||||
outDir: isDev ? "lib" : "dist",
|
||||
minify: !isDev,
|
||||
treeshake: !isDev,
|
||||
})
|
||||
```
|
||||
|
||||
**Customize for your project:**
|
||||
|
||||
- **Multiple entry points**: `entry: ["src/index.ts", "src/utils.ts"]`
|
||||
- **Additional formats**: `format: ["cjs", "esm", "iife"]`
|
||||
- **External dependencies**: `external: ["peer-dependency-name"]`
|
||||
- **Bundle splitting**: `splitting: true` (for code splitting)
|
||||
|
||||
### Step 5: Create Vitest Configuration
|
||||
|
||||
Create `vitest.config.ts` in project root:
|
||||
|
||||
```typescript
|
||||
import { defineConfig } from "vitest/config"
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
environment: "node",
|
||||
coverage: {
|
||||
provider: "v8",
|
||||
reporter: ["text", "json", "html"],
|
||||
include: ["src/**/*.ts"],
|
||||
exclude: ["src/**/*.spec.ts", "src/**/*.test.ts", "**/*.d.ts", "**/node_modules/**"],
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
**Migrate tests:**
|
||||
|
||||
If migrating from Jest:
|
||||
|
||||
```typescript
|
||||
// Old Jest test
|
||||
import { describe, test, expect } from "@jest/globals"
|
||||
|
||||
test("example", () => {
|
||||
expect(true).toBe(true)
|
||||
})
|
||||
|
||||
// New Vitest test (very similar!)
|
||||
import { describe, it, expect } from "vitest"
|
||||
|
||||
it("example", () => {
|
||||
expect(true).toBe(true)
|
||||
})
|
||||
```
|
||||
|
||||
Most Jest tests work with minimal changes. Main differences:
|
||||
|
||||
- Import from `vitest` instead of `@jest/globals`
|
||||
- Use `it` instead of `test` (both work, but `it` is conventional)
|
||||
- Some advanced mocking APIs may differ
|
||||
|
||||
### Step 6: Create ESLint Configuration
|
||||
|
||||
Create `eslint.config.mjs` (flat config format):
|
||||
|
||||
```javascript
|
||||
import eslint from "@eslint/js"
|
||||
import tseslint from "@typescript-eslint/eslint-plugin"
|
||||
import tsparser from "@typescript-eslint/parser"
|
||||
import prettier from "eslint-plugin-prettier"
|
||||
import simpleImportSort from "eslint-plugin-simple-import-sort"
|
||||
import globals from "globals"
|
||||
|
||||
export default [
|
||||
{
|
||||
ignores: ["dist/**", "lib/**", "node_modules/**", "coverage/**"],
|
||||
},
|
||||
eslint.configs.recommended,
|
||||
{
|
||||
files: ["**/*.ts", "**/*.tsx"],
|
||||
languageOptions: {
|
||||
parser: tsparser,
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
},
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.es2021,
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
"@typescript-eslint": tseslint,
|
||||
prettier: prettier,
|
||||
"simple-import-sort": simpleImportSort,
|
||||
},
|
||||
rules: {
|
||||
"prettier/prettier": "error",
|
||||
"simple-import-sort/imports": "error",
|
||||
"simple-import-sort/exports": "error",
|
||||
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }],
|
||||
"@typescript-eslint/no-explicit-any": "warn",
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
### Step 7: Create Prettier Configuration
|
||||
|
||||
Create `.prettierrc` (or add to package.json):
|
||||
|
||||
```json
|
||||
{
|
||||
"semi": false,
|
||||
"trailingComma": "all",
|
||||
"singleQuote": false,
|
||||
"printWidth": 120,
|
||||
"tabWidth": 2,
|
||||
"endOfLine": "auto"
|
||||
}
|
||||
```
|
||||
|
||||
Or in package.json:
|
||||
|
||||
```json
|
||||
{
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
"trailingComma": "all",
|
||||
"singleQuote": false,
|
||||
"printWidth": 120,
|
||||
"tabWidth": 2,
|
||||
"endOfLine": "auto"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 8: Update TypeScript Configuration
|
||||
|
||||
Update `tsconfig.json` for strict mode:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"lib": ["ESNext"],
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": false,
|
||||
"strictPropertyInitialization": false,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "lib", "**/*.spec.ts", "**/*.test.ts"]
|
||||
}
|
||||
```
|
||||
|
||||
**Key settings:**
|
||||
|
||||
- `strict: true` - Enable all strict checks
|
||||
- `noImplicitAny: false` - Pragmatic: allow implicit any in some cases
|
||||
- `strictPropertyInitialization: false` - Easier constructor patterns
|
||||
- `target: "ESNext"` - Let tsup handle transpilation
|
||||
- `declaration: true` - Generate .d.ts files (though tsup handles this)
|
||||
|
||||
### Step 9: Update package.json Exports
|
||||
|
||||
Update your package.json for dual module format:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "your-package",
|
||||
"version": "1.0.0",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"require": "./dist/index.js",
|
||||
"import": "./dist/index.mjs"
|
||||
}
|
||||
},
|
||||
"files": ["lib", "dist"]
|
||||
}
|
||||
```
|
||||
|
||||
**For multiple entry points:**
|
||||
|
||||
```json
|
||||
{
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"require": "./dist/index.js",
|
||||
"import": "./dist/index.mjs"
|
||||
},
|
||||
"./utils": {
|
||||
"types": "./dist/utils.d.ts",
|
||||
"require": "./dist/utils.js",
|
||||
"import": "./dist/utils.mjs"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 10: Update .gitignore
|
||||
|
||||
Ensure these are ignored:
|
||||
|
||||
```
|
||||
# Build outputs
|
||||
dist/
|
||||
lib/
|
||||
|
||||
# Dependencies
|
||||
node_modules/
|
||||
|
||||
# Coverage
|
||||
coverage/
|
||||
.nyc_output/
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.local
|
||||
```
|
||||
|
||||
### Step 11: Test the Migration
|
||||
|
||||
```bash
|
||||
# Clean old builds
|
||||
rm -rf dist lib build out
|
||||
|
||||
# Install dependencies
|
||||
pnpm install
|
||||
|
||||
# Try the dev workflow
|
||||
pnpm dev
|
||||
|
||||
# In another terminal, run tests
|
||||
pnpm test:watch
|
||||
|
||||
# Run full validation
|
||||
pnpm validate
|
||||
```
|
||||
|
||||
**If validation passes**, migration is successful!
|
||||
|
||||
### Step 12: Update CI/CD Pipelines
|
||||
|
||||
Update GitHub Actions workflows:
|
||||
|
||||
**Before:**
|
||||
|
||||
```yaml
|
||||
- run: npm run build
|
||||
- run: npm run lint
|
||||
- run: npm run test
|
||||
```
|
||||
|
||||
**After:**
|
||||
|
||||
```yaml
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 10
|
||||
|
||||
- run: pnpm install
|
||||
- run: pnpm validate
|
||||
```
|
||||
|
||||
Simple and consistent!
|
||||
|
||||
### Step 13: Update Documentation
|
||||
|
||||
Update your project documentation:
|
||||
|
||||
**README.md:**
|
||||
|
||||
```markdown
|
||||
## Development
|
||||
|
||||
# Install dependencies
|
||||
|
||||
pnpm install
|
||||
|
||||
# Development mode (watch)
|
||||
|
||||
pnpm dev
|
||||
|
||||
# Run tests
|
||||
|
||||
pnpm test
|
||||
|
||||
# Validate before commit
|
||||
|
||||
pnpm validate
|
||||
```
|
||||
|
||||
**CLAUDE.md:**
|
||||
|
||||
Add standardized commands section (see template's CLAUDE.md).
|
||||
|
||||
## Migration Patterns
|
||||
|
||||
### From Webpack to tsup
|
||||
|
||||
**Old webpack.config.js:**
|
||||
|
||||
```javascript
|
||||
module.exports = {
|
||||
entry: "./src/index.ts",
|
||||
output: {
|
||||
filename: "bundle.js",
|
||||
library: "MyLib",
|
||||
libraryTarget: "umd",
|
||||
},
|
||||
module: {
|
||||
rules: [{ test: /\.ts$/, use: "ts-loader" }],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
**New tsup.config.ts:**
|
||||
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
entry: ["src/index.ts"],
|
||||
format: ["cjs", "esm"], // More modern than UMD
|
||||
dts: true,
|
||||
splitting: false,
|
||||
sourcemap: true,
|
||||
clean: true,
|
||||
})
|
||||
```
|
||||
|
||||
Benefits:
|
||||
|
||||
- ✅ Simpler configuration
|
||||
- ✅ Built-in TypeScript support
|
||||
- ✅ Automatic dual format
|
||||
- ✅ Much faster builds
|
||||
|
||||
### From Rollup to tsup
|
||||
|
||||
**Old rollup.config.js:**
|
||||
|
||||
```javascript
|
||||
import typescript from "@rollup/plugin-typescript"
|
||||
|
||||
export default {
|
||||
input: "src/index.ts",
|
||||
output: [
|
||||
{ file: "dist/index.js", format: "cjs" },
|
||||
{ file: "dist/index.esm.js", format: "es" },
|
||||
],
|
||||
plugins: [typescript()],
|
||||
}
|
||||
```
|
||||
|
||||
**New tsup.config.ts:**
|
||||
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
entry: ["src/index.ts"],
|
||||
format: ["cjs", "esm"],
|
||||
dts: true,
|
||||
})
|
||||
```
|
||||
|
||||
Same output, less config!
|
||||
|
||||
### From Jest to Vitest
|
||||
|
||||
**Old jest.config.js:**
|
||||
|
||||
```javascript
|
||||
module.exports = {
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "node",
|
||||
collectCoverageFrom: ["src/**/*.ts"],
|
||||
coveragePathIgnorePatterns: ["/node_modules/", "/test/"],
|
||||
}
|
||||
```
|
||||
|
||||
**New vitest.config.ts:**
|
||||
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
environment: "node",
|
||||
coverage: {
|
||||
provider: "v8",
|
||||
include: ["src/**/*.ts"],
|
||||
exclude: ["**/*.spec.ts", "**/*.test.ts"],
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
**Test migration:**
|
||||
|
||||
Most Jest tests work as-is! Just change imports:
|
||||
|
||||
```typescript
|
||||
// Change this:
|
||||
import { describe, test, expect } from "@jest/globals"
|
||||
|
||||
// To this:
|
||||
import { describe, it, expect } from "vitest"
|
||||
```
|
||||
|
||||
### From TSLint to ESLint
|
||||
|
||||
If you're still using TSLint (deprecated):
|
||||
|
||||
1. **Remove TSLint**: `pnpm remove tslint`
|
||||
2. **Install ESLint**: Follow Step 6 above
|
||||
3. **Migrate rules**: Most TSLint rules have ESLint equivalents
|
||||
4. **Run migration**: `npx tslint-to-eslint-config` (if needed)
|
||||
|
||||
## Common Issues and Solutions
|
||||
|
||||
### Issue: "Module not found" after migration
|
||||
|
||||
**Problem**: Import paths changed or external dependencies not configured.
|
||||
|
||||
**Solution**:
|
||||
|
||||
```typescript
|
||||
// tsup.config.ts
|
||||
export default defineConfig({
|
||||
external: ["peer-dependency-name"], // Don't bundle peer deps
|
||||
})
|
||||
```
|
||||
|
||||
### Issue: Tests not running
|
||||
|
||||
**Problem**: Test files not found or wrong pattern.
|
||||
|
||||
**Solution**: Check vitest.config.ts includes your test pattern:
|
||||
|
||||
```typescript
|
||||
test: {
|
||||
include: ['**/*.{test,spec}.{ts,tsx}'], // Adjust pattern
|
||||
}
|
||||
```
|
||||
|
||||
### Issue: Build outputs to wrong directory
|
||||
|
||||
**Problem**: Old build artifacts in different locations.
|
||||
|
||||
**Solution**:
|
||||
|
||||
```bash
|
||||
# Clean everything
|
||||
rm -rf dist lib build out .next .nuxt
|
||||
|
||||
# Rebuild
|
||||
pnpm build
|
||||
```
|
||||
|
||||
### Issue: Types not generated
|
||||
|
||||
**Problem**: TypeScript declaration files missing.
|
||||
|
||||
**Solution**: Ensure tsup.config.ts has `dts: true`:
|
||||
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
dts: true, // Generate .d.ts files
|
||||
})
|
||||
```
|
||||
|
||||
### Issue: Linting fails on valid code
|
||||
|
||||
**Problem**: ESLint rules too strict or misconfigured.
|
||||
|
||||
**Solution**: Adjust rules in eslint.config.mjs:
|
||||
|
||||
```javascript
|
||||
rules: {
|
||||
"@typescript-eslint/no-explicit-any": "warn", // Change from "error" to "warn"
|
||||
// Or disable specific rules:
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
}
|
||||
```
|
||||
|
||||
### Issue: Format conflicts between Prettier and ESLint
|
||||
|
||||
**Problem**: Competing formatting rules.
|
||||
|
||||
**Solution**: Ensure eslint-config-prettier is loaded:
|
||||
|
||||
```javascript
|
||||
import prettier from "eslint-config-prettier"
|
||||
|
||||
export default [
|
||||
// ... other configs
|
||||
prettier, // Must be last to override other rules
|
||||
]
|
||||
```
|
||||
|
||||
## Validation Checklist
|
||||
|
||||
After migration, verify:
|
||||
|
||||
- [ ] `pnpm install` completes without errors
|
||||
- [ ] `pnpm dev` builds successfully
|
||||
- [ ] `pnpm test` passes all tests
|
||||
- [ ] `pnpm lint` reports no errors
|
||||
- [ ] `pnpm format:check` shows code is formatted
|
||||
- [ ] `pnpm build` produces dist/ with .js, .mjs, and .d.ts files
|
||||
- [ ] `pnpm validate` passes completely
|
||||
- [ ] Old build artifacts removed
|
||||
- [ ] package.json exports configured correctly
|
||||
- [ ] CI/CD updated to use `pnpm validate`
|
||||
- [ ] Documentation updated with new commands
|
||||
|
||||
## Rollback Plan
|
||||
|
||||
If migration fails or causes issues:
|
||||
|
||||
```bash
|
||||
# Revert to backup
|
||||
git checkout pre-standardization-backup
|
||||
|
||||
# Or restore from copy
|
||||
rm -rf project-dir
|
||||
cp -r ../project-backup project-dir
|
||||
```
|
||||
|
||||
## Benefits After Migration
|
||||
|
||||
Once standardized, you gain:
|
||||
|
||||
1. **Consistency** - Same commands across all projects
|
||||
2. **Modern tooling** - Faster builds with tsup, better DX with Vitest
|
||||
3. **Dual format** - Automatic CommonJS and ES module support
|
||||
4. **Type safety** - Strict TypeScript configuration
|
||||
5. **Quality gates** - Single `validate` command ensures everything passes
|
||||
6. **CI/CD simplicity** - One command to rule them all
|
||||
7. **Documentation** - Clear, consistent developer experience
|
||||
|
||||
## Next Steps
|
||||
|
||||
After successful migration:
|
||||
|
||||
1. **Train your team** - Share new commands and workflow
|
||||
2. **Update CI/CD** - Simplify to `pnpm validate`
|
||||
3. **Publish new version** - If npm package, publish with new build
|
||||
4. **Monitor issues** - Watch for any compatibility problems
|
||||
5. **Iterate** - Adjust configuration as needed
|
||||
|
||||
## Resources
|
||||
|
||||
- **Template Repository**: https://github.com/jordanburke/typescript-library-template
|
||||
- **tsup Documentation**: https://tsup.egoist.dev/
|
||||
- **Vitest Migration**: https://vitest.dev/guide/migration.html
|
||||
- **ESLint Flat Config**: https://eslint.org/docs/latest/use/configure/configuration-files
|
||||
553
skills/typescript-standards/references/template-setup.md
Normal file
553
skills/typescript-standards/references/template-setup.md
Normal file
@@ -0,0 +1,553 @@
|
||||
# Template Setup Guide
|
||||
|
||||
Complete guide for creating a new TypeScript library using the typescript-library-template.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before starting, ensure you have:
|
||||
|
||||
- **Node.js**: ≥ 18.0.0
|
||||
- **pnpm**: Latest version (template uses 10.18.3+)
|
||||
- **Git**: For version control
|
||||
- **npm account**: For publishing (optional)
|
||||
|
||||
Check versions:
|
||||
|
||||
```bash
|
||||
node --version # Should be 18.0.0 or higher
|
||||
pnpm --version # Latest stable version
|
||||
git --version
|
||||
```
|
||||
|
||||
## Initial Setup
|
||||
|
||||
### Step 1: Clone the Template
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/jordanburke/typescript-library-template.git my-library-name
|
||||
|
||||
# Navigate to the directory
|
||||
cd my-library-name
|
||||
|
||||
# Remove the template's git history
|
||||
rm -rf .git
|
||||
|
||||
# Initialize your own repository
|
||||
git init
|
||||
```
|
||||
|
||||
### Step 2: Install Dependencies
|
||||
|
||||
```bash
|
||||
# Install all dependencies
|
||||
pnpm install
|
||||
|
||||
# Verify installation
|
||||
pnpm validate
|
||||
```
|
||||
|
||||
If `pnpm validate` succeeds, you have a working setup!
|
||||
|
||||
## Customization Checklist
|
||||
|
||||
### Update package.json
|
||||
|
||||
Replace template placeholders with your project details:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "your-library-name", // ← Change this
|
||||
"version": "1.0.0", // ← Start at 1.0.0 or 0.1.0
|
||||
"description": "Your library description", // ← Describe your library
|
||||
"keywords": [
|
||||
// ← Add relevant keywords
|
||||
"your",
|
||||
"keywords",
|
||||
"here"
|
||||
],
|
||||
"author": "your.email@example.com", // ← Your email
|
||||
"license": "MIT", // ← Choose license (MIT, Apache-2.0, etc.)
|
||||
"homepage": "https://github.com/yourname/your-library", // ← Your repo
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/yourname/your-library" // ← Your repo URL
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Important fields:**
|
||||
|
||||
- `name` - Must be unique on npm if publishing publicly
|
||||
- `version` - Start at 1.0.0 (stable) or 0.1.0 (experimental)
|
||||
- `description` - Shows up in npm search
|
||||
- `keywords` - Helps users find your package
|
||||
- `repository.url` - Links to source code
|
||||
|
||||
### Update README.md
|
||||
|
||||
Replace template content with your library information:
|
||||
|
||||
```markdown
|
||||
# Your Library Name
|
||||
|
||||
Brief description of what your library does.
|
||||
|
||||
## Installation
|
||||
|
||||
\`\`\`bash
|
||||
npm install your-library-name
|
||||
|
||||
# or
|
||||
|
||||
pnpm add your-library-name
|
||||
\`\`\`
|
||||
|
||||
## Usage
|
||||
|
||||
\`\`\`typescript
|
||||
import { YourFunction } from 'your-library-name'
|
||||
|
||||
// Example usage
|
||||
const result = YourFunction('example')
|
||||
\`\`\`
|
||||
|
||||
## API
|
||||
|
||||
Document your main functions and types here.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
```
|
||||
|
||||
### Update CLAUDE.md
|
||||
|
||||
Customize the Claude Code guidance for your project:
|
||||
|
||||
1. **Update project overview** - Describe what your library does
|
||||
2. **Add architecture notes** - Explain key design decisions
|
||||
3. **Document commands** - Keep the standard commands, add custom ones
|
||||
4. **Add development tips** - Project-specific guidance
|
||||
|
||||
Example:
|
||||
|
||||
```markdown
|
||||
# CLAUDE.md
|
||||
|
||||
## Project Overview
|
||||
|
||||
This is [your library name], a TypeScript library that [brief description].
|
||||
|
||||
## Architecture
|
||||
|
||||
- **Main module**: `src/index.ts` - exports all public APIs
|
||||
- **Core logic**: `src/core/` - [describe organization]
|
||||
- **Utilities**: `src/utils/` - [describe helpers]
|
||||
|
||||
## Development Commands
|
||||
|
||||
[Keep standard commands from template]
|
||||
|
||||
## Custom Workflows
|
||||
|
||||
[Add any project-specific workflows]
|
||||
```
|
||||
|
||||
### Optional: Update License
|
||||
|
||||
If not using MIT license:
|
||||
|
||||
1. Delete `LICENSE` file
|
||||
2. Create new license file for your chosen license
|
||||
3. Update `package.json` license field
|
||||
4. Update README.md license section
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Step 3: Write Your Code
|
||||
|
||||
```bash
|
||||
# Start development watch mode
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
This runs tsup in watch mode, rebuilding on every file change.
|
||||
|
||||
**File structure:**
|
||||
|
||||
```
|
||||
src/
|
||||
├── index.ts # Main entry point - export public API here
|
||||
├── core/ # Core functionality
|
||||
│ └── yourFeature.ts
|
||||
├── utils/ # Helper utilities
|
||||
│ └── helpers.ts
|
||||
└── types/ # Type definitions (if needed)
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
**Example src/index.ts:**
|
||||
|
||||
```typescript
|
||||
// Export your main functions and types
|
||||
export { yourFunction } from "./core/yourFeature"
|
||||
export { helperFunction } from "./utils/helpers"
|
||||
|
||||
// Export types
|
||||
export type { YourType } from "./types"
|
||||
```
|
||||
|
||||
### Step 4: Write Tests
|
||||
|
||||
```bash
|
||||
# Run tests in watch mode
|
||||
pnpm test:watch
|
||||
```
|
||||
|
||||
**Test file structure:**
|
||||
|
||||
```
|
||||
test/
|
||||
├── yourFeature.spec.ts
|
||||
└── helpers.spec.ts
|
||||
```
|
||||
|
||||
**Example test:**
|
||||
|
||||
```typescript
|
||||
import { describe, expect, it } from "vitest"
|
||||
import { yourFunction } from "../src/core/yourFeature"
|
||||
|
||||
describe("yourFunction", () => {
|
||||
it("should return expected result", () => {
|
||||
const result = yourFunction("input")
|
||||
expect(result).toBe("expected")
|
||||
})
|
||||
|
||||
it("should handle edge cases", () => {
|
||||
expect(() => yourFunction(null)).toThrow()
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Step 5: Validate Before Commit
|
||||
|
||||
```bash
|
||||
# Run full validation
|
||||
pnpm validate
|
||||
```
|
||||
|
||||
This runs:
|
||||
|
||||
1. Format code with Prettier
|
||||
2. Lint with ESLint
|
||||
3. Run all tests
|
||||
4. Build for production
|
||||
|
||||
**All must pass** before committing!
|
||||
|
||||
## Git Workflow
|
||||
|
||||
### Step 6: Initial Commit
|
||||
|
||||
```bash
|
||||
# Add all files
|
||||
git add .
|
||||
|
||||
# Create initial commit
|
||||
git commit -m "Initial commit from typescript-library-template"
|
||||
|
||||
# Create main branch (if needed)
|
||||
git branch -M main
|
||||
```
|
||||
|
||||
### Step 7: Connect to Remote Repository
|
||||
|
||||
```bash
|
||||
# Add remote (create repo on GitHub first)
|
||||
git remote add origin https://github.com/yourname/your-library.git
|
||||
|
||||
# Push initial commit
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
## Publishing to npm
|
||||
|
||||
### Step 8: Prepare for Publishing
|
||||
|
||||
**Create npm account** (if you don't have one):
|
||||
|
||||
```bash
|
||||
npm login
|
||||
```
|
||||
|
||||
**Verify package name is available:**
|
||||
|
||||
```bash
|
||||
npm view your-library-name
|
||||
# Should show "npm ERR! 404 Not Found" if available
|
||||
```
|
||||
|
||||
**Choose access level:**
|
||||
|
||||
- Public packages: Free, anyone can install
|
||||
- Private packages: Requires paid npm account
|
||||
|
||||
### Step 9: Publish
|
||||
|
||||
```bash
|
||||
# First publish (public package)
|
||||
npm publish --access public
|
||||
|
||||
# Subsequent publishes (after updates)
|
||||
npm publish
|
||||
```
|
||||
|
||||
The `prepublishOnly` hook automatically runs `pnpm validate`, ensuring:
|
||||
|
||||
- Code is formatted
|
||||
- Linting passes
|
||||
- Tests pass
|
||||
- Build succeeds
|
||||
|
||||
### Version Updates
|
||||
|
||||
Follow semantic versioning (semver):
|
||||
|
||||
```bash
|
||||
# Patch: bug fixes (1.0.0 → 1.0.1)
|
||||
npm version patch
|
||||
|
||||
# Minor: new features, backward compatible (1.0.0 → 1.1.0)
|
||||
npm version minor
|
||||
|
||||
# Major: breaking changes (1.0.0 → 2.0.0)
|
||||
npm version major
|
||||
```
|
||||
|
||||
After version bump:
|
||||
|
||||
```bash
|
||||
# Publish new version
|
||||
npm publish
|
||||
|
||||
# Push version tag to git
|
||||
git push --tags
|
||||
```
|
||||
|
||||
## Testing Your Published Package
|
||||
|
||||
Before announcing your package, test it works:
|
||||
|
||||
```bash
|
||||
# Create test directory outside your project
|
||||
mkdir /tmp/test-my-library
|
||||
cd /tmp/test-my-library
|
||||
|
||||
# Initialize package
|
||||
npm init -y
|
||||
|
||||
# Install your package
|
||||
npm install your-library-name
|
||||
|
||||
# Test CommonJS
|
||||
node -e "const lib = require('your-library-name'); console.log(lib)"
|
||||
|
||||
# Test ES modules (need package.json with "type": "module")
|
||||
node -e "import('your-library-name').then(console.log)"
|
||||
```
|
||||
|
||||
## Post-Setup Checklist
|
||||
|
||||
After completing setup, verify:
|
||||
|
||||
- [ ] package.json has correct name, version, description
|
||||
- [ ] package.json repository URL points to your repo
|
||||
- [ ] README.md describes your library
|
||||
- [ ] CLAUDE.md reflects your project
|
||||
- [ ] LICENSE file is correct
|
||||
- [ ] `pnpm validate` passes
|
||||
- [ ] Git repository initialized and pushed
|
||||
- [ ] First commit made
|
||||
- [ ] (Optional) Published to npm
|
||||
- [ ] (Optional) Tested published package works
|
||||
|
||||
## Continuous Integration Setup
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
Create `.github/workflows/ci.yml`:
|
||||
|
||||
```yaml
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "18"
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 10
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Run validation
|
||||
run: pnpm validate
|
||||
```
|
||||
|
||||
This runs your full validation on every push and pull request.
|
||||
|
||||
## Next Steps
|
||||
|
||||
Now that your library is set up:
|
||||
|
||||
1. **Develop features** - Add your core functionality
|
||||
2. **Write comprehensive tests** - Aim for high coverage
|
||||
3. **Document your API** - Keep README up to date
|
||||
4. **Set up CI** - Automate testing
|
||||
5. **Add badges** - Build status, coverage, npm version
|
||||
6. **Create examples** - Help users understand usage
|
||||
7. **Write changelog** - Document changes between versions
|
||||
|
||||
## Common Customizations
|
||||
|
||||
### Adding Dependencies
|
||||
|
||||
```bash
|
||||
# Production dependencies (users need these)
|
||||
pnpm add dependency-name
|
||||
|
||||
# Development dependencies (only for development)
|
||||
pnpm add -D dev-dependency-name
|
||||
```
|
||||
|
||||
### Adding Scripts
|
||||
|
||||
Add to package.json scripts:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"custom-script": "your command here"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Configuring TypeScript
|
||||
|
||||
Edit `tsconfig.json` for your needs. The template uses strict mode with pragmatic defaults.
|
||||
|
||||
### Customizing Build
|
||||
|
||||
Edit `tsup.config.ts` to:
|
||||
|
||||
- Add/remove formats (CJS, ESM, IIFE)
|
||||
- Configure minification
|
||||
- Add external dependencies
|
||||
- Customize output files
|
||||
|
||||
### Adding Subpath Exports
|
||||
|
||||
Support imports like `your-library/feature`:
|
||||
|
||||
**package.json:**
|
||||
|
||||
```json
|
||||
{
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"require": "./dist/index.js",
|
||||
"import": "./dist/index.mjs"
|
||||
},
|
||||
"./feature": {
|
||||
"types": "./dist/feature.d.ts",
|
||||
"require": "./dist/feature.js",
|
||||
"import": "./dist/feature.mjs"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**tsup.config.ts:**
|
||||
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
entry: {
|
||||
index: "src/index.ts",
|
||||
feature: "src/feature/index.ts", // Additional entry point
|
||||
},
|
||||
// ... rest of config
|
||||
})
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Command not found: pnpm"
|
||||
|
||||
Install pnpm:
|
||||
|
||||
```bash
|
||||
npm install -g pnpm
|
||||
```
|
||||
|
||||
### Validation fails after cloning
|
||||
|
||||
```bash
|
||||
# Clean install
|
||||
rm -rf node_modules pnpm-lock.yaml
|
||||
pnpm install
|
||||
pnpm validate
|
||||
```
|
||||
|
||||
### Tests failing
|
||||
|
||||
```bash
|
||||
# Run with verbose output
|
||||
pnpm test --reporter=verbose
|
||||
|
||||
# Check specific test
|
||||
pnpm vitest run test/specific.spec.ts
|
||||
```
|
||||
|
||||
### Build issues
|
||||
|
||||
```bash
|
||||
# Clean and rebuild
|
||||
rm -rf dist lib
|
||||
pnpm build
|
||||
```
|
||||
|
||||
### npm publish fails
|
||||
|
||||
Common issues:
|
||||
|
||||
- **Name taken**: Choose different package name
|
||||
- **Not logged in**: Run `npm login`
|
||||
- **Validation fails**: Fix issues, then try again
|
||||
- **No permission**: Check npm account and package scope
|
||||
|
||||
## Resources
|
||||
|
||||
- **Template Repository**: https://github.com/jordanburke/typescript-library-template
|
||||
- **npm Documentation**: https://docs.npmjs.com/
|
||||
- **tsup Documentation**: https://tsup.egoist.dev/
|
||||
- **Vitest Documentation**: https://vitest.dev/
|
||||
- **Semantic Versioning**: https://semver.org/
|
||||
834
skills/typescript-standards/references/tooling-reference.md
Normal file
834
skills/typescript-standards/references/tooling-reference.md
Normal file
@@ -0,0 +1,834 @@
|
||||
# Tooling Reference
|
||||
|
||||
Comprehensive reference for all tooling configurations used in the typescript-library-template.
|
||||
|
||||
## tsup Configuration
|
||||
|
||||
tsup is the build tool that handles TypeScript compilation, bundling, and dual module format generation.
|
||||
|
||||
### Basic Configuration
|
||||
|
||||
File: `tsup.config.ts`
|
||||
|
||||
```typescript
|
||||
import type { Options } from "tsup"
|
||||
|
||||
const env = process.env.NODE_ENV
|
||||
|
||||
export const tsup: Options = {
|
||||
splitting: true,
|
||||
sourcemap: true,
|
||||
clean: true,
|
||||
dts: true,
|
||||
format: ["cjs", "esm"],
|
||||
minify: env === "production",
|
||||
bundle: env === "production",
|
||||
skipNodeModulesBundle: true,
|
||||
watch: env === "development",
|
||||
target: "es2020",
|
||||
outDir: env === "production" ? "dist" : "lib",
|
||||
entry: ["src/index.ts", "src/**/*.ts"],
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration Options Explained
|
||||
|
||||
**entry** - Entry points for build:
|
||||
|
||||
```typescript
|
||||
// Single entry
|
||||
entry: ["src/index.ts"]
|
||||
|
||||
// Multiple entries
|
||||
entry: ["src/index.ts", "src/utils.ts"]
|
||||
|
||||
// Glob pattern (all TypeScript files)
|
||||
entry: ["src/**/*.ts"]
|
||||
```
|
||||
|
||||
**format** - Output module formats:
|
||||
|
||||
```typescript
|
||||
// Dual format (recommended for libraries)
|
||||
format: ["cjs", "esm"]
|
||||
|
||||
// Triple format (includes IIFE for browser)
|
||||
format: ["cjs", "esm", "iife"]
|
||||
|
||||
// Single format
|
||||
format: ["esm"]
|
||||
```
|
||||
|
||||
**dts** - TypeScript declaration files:
|
||||
|
||||
```typescript
|
||||
// Generate .d.ts files
|
||||
dts: true
|
||||
|
||||
// Generate with custom options
|
||||
dts: {
|
||||
resolve: true,
|
||||
entry: ["src/index.ts"],
|
||||
}
|
||||
```
|
||||
|
||||
**outDir** - Output directory:
|
||||
|
||||
```typescript
|
||||
// Environment-based (development vs production)
|
||||
outDir: env === "production" ? "dist" : "lib"
|
||||
|
||||
// Fixed directory
|
||||
outDir: "dist"
|
||||
```
|
||||
|
||||
**minify** - Code minification:
|
||||
|
||||
```typescript
|
||||
// Production only (recommended)
|
||||
minify: env === "production"
|
||||
|
||||
// Always minify
|
||||
minify: true
|
||||
|
||||
// Custom minifier
|
||||
minify: "terser"
|
||||
```
|
||||
|
||||
**sourcemap** - Source map generation:
|
||||
|
||||
```typescript
|
||||
// Development only (recommended)
|
||||
sourcemap: env !== "production"
|
||||
|
||||
// Always generate
|
||||
sourcemap: true
|
||||
|
||||
// Inline sourcemaps
|
||||
sourcemap: "inline"
|
||||
```
|
||||
|
||||
**bundle** - Bundle dependencies:
|
||||
|
||||
```typescript
|
||||
// Production only (recommended)
|
||||
bundle: env === "production"
|
||||
|
||||
// Never bundle (useful for libraries)
|
||||
bundle: false
|
||||
```
|
||||
|
||||
**external** - External dependencies (don't bundle):
|
||||
|
||||
```typescript
|
||||
// Exclude peer dependencies
|
||||
external: ["react", "react-dom"]
|
||||
|
||||
// Regex pattern
|
||||
external: [/^@myorg\//]
|
||||
```
|
||||
|
||||
**splitting** - Code splitting:
|
||||
|
||||
```typescript
|
||||
// Enable code splitting (for better tree-shaking)
|
||||
splitting: true
|
||||
|
||||
// Disable
|
||||
splitting: false
|
||||
```
|
||||
|
||||
**target** - JavaScript target:
|
||||
|
||||
```typescript
|
||||
// Modern Node.js
|
||||
target: "es2020"
|
||||
|
||||
// Latest features
|
||||
target: "esnext"
|
||||
|
||||
// Older compatibility
|
||||
target: "es2015"
|
||||
```
|
||||
|
||||
**watch** - Watch mode:
|
||||
|
||||
```typescript
|
||||
// Development mode only
|
||||
watch: env === "development"
|
||||
|
||||
// Always watch
|
||||
watch: true
|
||||
|
||||
// With options
|
||||
watch: {
|
||||
onRebuild(err) {
|
||||
if (err) console.error('Build failed:', err)
|
||||
else console.log('Build succeeded')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**clean** - Clean output directory:
|
||||
|
||||
```typescript
|
||||
// Always clean before build (recommended)
|
||||
clean: true
|
||||
|
||||
// Keep previous builds
|
||||
clean: false
|
||||
```
|
||||
|
||||
### Advanced Patterns
|
||||
|
||||
**Multiple Entry Points with Custom Names:**
|
||||
|
||||
```typescript
|
||||
export const tsup: Options = {
|
||||
entry: {
|
||||
index: "src/index.ts",
|
||||
utils: "src/utils/index.ts",
|
||||
types: "src/types/index.ts",
|
||||
},
|
||||
format: ["cjs", "esm"],
|
||||
dts: true,
|
||||
}
|
||||
```
|
||||
|
||||
This generates:
|
||||
|
||||
- `dist/index.js`, `dist/index.mjs`, `dist/index.d.ts`
|
||||
- `dist/utils.js`, `dist/utils.mjs`, `dist/utils.d.ts`
|
||||
- `dist/types.js`, `dist/types.mjs`, `dist/types.d.ts`
|
||||
|
||||
**Browser-Compatible Build:**
|
||||
|
||||
```typescript
|
||||
export const tsup: Options = {
|
||||
entry: ["src/index.ts"],
|
||||
format: ["esm", "iife"],
|
||||
globalName: "MyLib",
|
||||
platform: "browser",
|
||||
target: "es2015",
|
||||
dts: true,
|
||||
}
|
||||
```
|
||||
|
||||
**Library with Peer Dependencies:**
|
||||
|
||||
```typescript
|
||||
export const tsup: Options = {
|
||||
entry: ["src/index.ts"],
|
||||
format: ["cjs", "esm"],
|
||||
dts: true,
|
||||
external: ["react", "react-dom"], // Don't bundle peer deps
|
||||
skipNodeModulesBundle: true,
|
||||
}
|
||||
```
|
||||
|
||||
## Vitest Configuration
|
||||
|
||||
Vitest is the test runner - fast, modern alternative to Jest.
|
||||
|
||||
### Basic Configuration
|
||||
|
||||
File: `vitest.config.ts`
|
||||
|
||||
```typescript
|
||||
import { defineConfig } from "vitest/config"
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
environment: "node",
|
||||
include: ["**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
|
||||
coverage: {
|
||||
provider: "v8",
|
||||
reporter: ["text", "json", "html"],
|
||||
exclude: ["node_modules/", "dist/", "**/*.d.ts", "**/*.test.{js,ts}", "**/*.config.{js,ts}"],
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### Configuration Options Explained
|
||||
|
||||
**globals** - Global test functions:
|
||||
|
||||
```typescript
|
||||
// Enable globals (describe, it, expect available without import)
|
||||
globals: true
|
||||
|
||||
// Require explicit imports
|
||||
globals: false
|
||||
```
|
||||
|
||||
**environment** - Test environment:
|
||||
|
||||
```typescript
|
||||
// Node.js environment (for libraries)
|
||||
environment: "node"
|
||||
|
||||
// Browser-like environment (for browser code)
|
||||
environment: "jsdom"
|
||||
|
||||
// Happy DOM (faster alternative to jsdom)
|
||||
environment: "happy-dom"
|
||||
```
|
||||
|
||||
**include** - Test file patterns:
|
||||
|
||||
```typescript
|
||||
// All common test patterns (default)
|
||||
include: ["**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"]
|
||||
|
||||
// Only .spec.ts files
|
||||
include: ["**/*.spec.ts"]
|
||||
|
||||
// Custom directory
|
||||
include: ["test/**/*.test.ts"]
|
||||
```
|
||||
|
||||
**exclude** - Exclude patterns:
|
||||
|
||||
```typescript
|
||||
exclude: ["node_modules/", "dist/", ".idea/", ".git/", "**/*.d.ts"]
|
||||
```
|
||||
|
||||
**coverage.provider** - Coverage tool:
|
||||
|
||||
```typescript
|
||||
// v8 (faster, Node.js built-in)
|
||||
provider: "v8"
|
||||
|
||||
// istanbul (more accurate in some cases)
|
||||
provider: "istanbul"
|
||||
```
|
||||
|
||||
**coverage.reporter** - Coverage report formats:
|
||||
|
||||
```typescript
|
||||
// Multiple formats
|
||||
reporter: ["text", "json", "html"]
|
||||
|
||||
// Text only (for CI)
|
||||
reporter: ["text"]
|
||||
|
||||
// With lcov for tools like Codecov
|
||||
reporter: ["text", "lcov"]
|
||||
```
|
||||
|
||||
**coverage.include** - Files to cover:
|
||||
|
||||
```typescript
|
||||
include: ["src/**/*.ts"]
|
||||
```
|
||||
|
||||
**coverage.exclude** - Files to exclude from coverage:
|
||||
|
||||
```typescript
|
||||
exclude: ["node_modules/", "dist/", "**/*.d.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.config.ts"]
|
||||
```
|
||||
|
||||
**coverage.threshold** - Minimum coverage:
|
||||
|
||||
```typescript
|
||||
coverage: {
|
||||
threshold: {
|
||||
lines: 80,
|
||||
functions: 80,
|
||||
branches: 80,
|
||||
statements: 80,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Advanced Patterns
|
||||
|
||||
**Test Setup File:**
|
||||
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
setupFiles: ["./test/setup.ts"], // Runs before each test file
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Example `test/setup.ts`:
|
||||
|
||||
```typescript
|
||||
import { expect } from "vitest"
|
||||
|
||||
// Custom matchers or global setup
|
||||
beforeEach(() => {
|
||||
// Runs before each test
|
||||
})
|
||||
```
|
||||
|
||||
**Multiple Environments:**
|
||||
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
test: {
|
||||
environmentMatchGlobs: [
|
||||
["**/*.dom.test.ts", "jsdom"], // DOM tests use jsdom
|
||||
["**/*.node.test.ts", "node"], // Node tests use node
|
||||
],
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
**Watch Mode Options:**
|
||||
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
test: {
|
||||
watch: false, // Disable watch in CI
|
||||
poolOptions: {
|
||||
threads: {
|
||||
singleThread: true, // For debugging
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## ESLint Configuration
|
||||
|
||||
ESLint enforces code quality and style rules.
|
||||
|
||||
### Basic Configuration (Flat Config)
|
||||
|
||||
File: `eslint.config.mjs`
|
||||
|
||||
```javascript
|
||||
import path from "node:path"
|
||||
import { fileURLToPath } from "node:url"
|
||||
|
||||
import { FlatCompat } from "@eslint/eslintrc"
|
||||
import js from "@eslint/js"
|
||||
import typescriptEslint from "@typescript-eslint/eslint-plugin"
|
||||
import tsParser from "@typescript-eslint/parser"
|
||||
import prettier from "eslint-plugin-prettier"
|
||||
import simpleImportSort from "eslint-plugin-simple-import-sort"
|
||||
import globals from "globals"
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = path.dirname(__filename)
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: __dirname,
|
||||
recommendedConfig: js.configs.recommended,
|
||||
allConfig: js.configs.all,
|
||||
})
|
||||
|
||||
export default [
|
||||
{
|
||||
ignores: [
|
||||
"**/.gitignore",
|
||||
"**/.eslintignore",
|
||||
"**/node_modules",
|
||||
"**/.DS_Store",
|
||||
"**/dist",
|
||||
"**/lib",
|
||||
"**/coverage",
|
||||
],
|
||||
},
|
||||
...compat.extends("eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended"),
|
||||
{
|
||||
plugins: {
|
||||
"@typescript-eslint": typescriptEslint,
|
||||
"simple-import-sort": simpleImportSort,
|
||||
prettier,
|
||||
},
|
||||
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.es2021,
|
||||
},
|
||||
|
||||
parser: tsParser,
|
||||
ecmaVersion: 2020,
|
||||
sourceType: "module",
|
||||
},
|
||||
|
||||
rules: {
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{},
|
||||
{
|
||||
usePrettierrc: true,
|
||||
},
|
||||
],
|
||||
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"simple-import-sort/imports": "error",
|
||||
"simple-import-sort/exports": "error",
|
||||
},
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
### Key Configuration Sections
|
||||
|
||||
**ignores** - Files to ignore:
|
||||
|
||||
```javascript
|
||||
{
|
||||
ignores: ["**/node_modules", "**/dist", "**/lib", "**/coverage", "**/*.d.ts"]
|
||||
}
|
||||
```
|
||||
|
||||
**extends** - Base configurations:
|
||||
|
||||
```javascript
|
||||
...compat.extends(
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:prettier/recommended"
|
||||
)
|
||||
```
|
||||
|
||||
**plugins** - ESLint plugins:
|
||||
|
||||
```javascript
|
||||
plugins: {
|
||||
"@typescript-eslint": typescriptEslint,
|
||||
"simple-import-sort": simpleImportSort,
|
||||
"prettier": prettier
|
||||
}
|
||||
```
|
||||
|
||||
**languageOptions** - Parser and globals:
|
||||
|
||||
```javascript
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.es2021,
|
||||
},
|
||||
parser: tsParser,
|
||||
ecmaVersion: 2020,
|
||||
sourceType: "module"
|
||||
}
|
||||
```
|
||||
|
||||
**rules** - Custom rule configuration:
|
||||
|
||||
```javascript
|
||||
rules: {
|
||||
// Prettier integration
|
||||
"prettier/prettier": ["error", {}, { usePrettierrc: true }],
|
||||
|
||||
// TypeScript rules
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/no-explicit-any": "warn",
|
||||
|
||||
// Import sorting
|
||||
"simple-import-sort/imports": "error",
|
||||
"simple-import-sort/exports": "error"
|
||||
}
|
||||
```
|
||||
|
||||
### Common Rule Configurations
|
||||
|
||||
**Strict TypeScript:**
|
||||
|
||||
```javascript
|
||||
rules: {
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"@typescript-eslint/strict-boolean-expressions": "error",
|
||||
"@typescript-eslint/no-unused-vars": ["error", {
|
||||
argsIgnorePattern: "^_",
|
||||
varsIgnorePattern: "^_"
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
**Relaxed for Prototyping:**
|
||||
|
||||
```javascript
|
||||
rules: {
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-unused-vars": "warn",
|
||||
"@typescript-eslint/ban-ts-comment": "off"
|
||||
}
|
||||
```
|
||||
|
||||
## Prettier Configuration
|
||||
|
||||
Prettier handles code formatting automatically.
|
||||
|
||||
### Basic Configuration
|
||||
|
||||
File: `.prettierrc` or in `package.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"semi": false,
|
||||
"trailingComma": "all",
|
||||
"singleQuote": false,
|
||||
"printWidth": 120,
|
||||
"tabWidth": 2,
|
||||
"endOfLine": "auto"
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration Options
|
||||
|
||||
**semi** - Semicolons:
|
||||
|
||||
```json
|
||||
"semi": false // No semicolons (recommended)
|
||||
"semi": true // Always semicolons
|
||||
```
|
||||
|
||||
**trailingComma** - Trailing commas:
|
||||
|
||||
```json
|
||||
"trailingComma": "all" // Everywhere possible (recommended)
|
||||
"trailingComma": "es5" // ES5 valid locations only
|
||||
"trailingComma": "none" // No trailing commas
|
||||
```
|
||||
|
||||
**singleQuote** - Quote style:
|
||||
|
||||
```json
|
||||
"singleQuote": false // Double quotes (recommended)
|
||||
"singleQuote": true // Single quotes
|
||||
```
|
||||
|
||||
**printWidth** - Line width:
|
||||
|
||||
```json
|
||||
"printWidth": 120 // 120 characters (recommended)
|
||||
"printWidth": 80 // 80 characters (traditional)
|
||||
```
|
||||
|
||||
**tabWidth** - Indentation:
|
||||
|
||||
```json
|
||||
"tabWidth": 2 // 2 spaces (recommended)
|
||||
"tabWidth": 4 // 4 spaces
|
||||
```
|
||||
|
||||
**endOfLine** - Line endings:
|
||||
|
||||
```json
|
||||
"endOfLine": "auto" // Auto-detect (recommended)
|
||||
"endOfLine": "lf" // Unix (LF)
|
||||
"endOfLine": "crlf" // Windows (CRLF)
|
||||
```
|
||||
|
||||
### Ignore Files
|
||||
|
||||
Create `.prettierignore`:
|
||||
|
||||
```
|
||||
dist
|
||||
lib
|
||||
node_modules
|
||||
coverage
|
||||
*.min.js
|
||||
```
|
||||
|
||||
## TypeScript Configuration
|
||||
|
||||
TypeScript compiler configuration for strict type checking.
|
||||
|
||||
### Basic Configuration
|
||||
|
||||
File: `tsconfig.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"lib": ["ESNext"],
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": false,
|
||||
"strictPropertyInitialization": false,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "lib", "**/*.spec.ts", "**/*.test.ts"]
|
||||
}
|
||||
```
|
||||
|
||||
### Key Options Explained
|
||||
|
||||
**target** - JavaScript version:
|
||||
|
||||
```json
|
||||
"target": "ESNext" // Latest JS features
|
||||
"target": "ES2020" // Modern but stable
|
||||
"target": "ES2015" // Wider compatibility
|
||||
```
|
||||
|
||||
**module** - Module system:
|
||||
|
||||
```json
|
||||
"module": "ESNext" // For bundlers (recommended)
|
||||
"module": "CommonJS" // For Node.js
|
||||
"module": "NodeNext" // For modern Node.js
|
||||
```
|
||||
|
||||
**moduleResolution** - How modules are resolved:
|
||||
|
||||
```json
|
||||
"moduleResolution": "bundler" // For bundlers like tsup (recommended)
|
||||
"moduleResolution": "node" // Node.js style
|
||||
"moduleResolution": "nodenext" // Modern Node.js
|
||||
```
|
||||
|
||||
**strict** - Strict type checking:
|
||||
|
||||
```json
|
||||
"strict": true // Enable all strict checks (recommended)
|
||||
```
|
||||
|
||||
**noImplicitAny** - Implicit any errors:
|
||||
|
||||
```json
|
||||
"noImplicitAny": false // Pragmatic (allow some implicit any)
|
||||
"noImplicitAny": true // Strict (no implicit any)
|
||||
```
|
||||
|
||||
**strictPropertyInitialization** - Class property initialization:
|
||||
|
||||
```json
|
||||
"strictPropertyInitialization": false // More flexible (recommended)
|
||||
"strictPropertyInitialization": true // Strict initialization
|
||||
```
|
||||
|
||||
### Path Mapping
|
||||
|
||||
For absolute imports:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["src/*"],
|
||||
"@utils/*": ["src/utils/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Usage:
|
||||
|
||||
```typescript
|
||||
import { helper } from "@/utils/helper"
|
||||
import { MyClass } from "@utils/MyClass"
|
||||
```
|
||||
|
||||
## Integration Examples
|
||||
|
||||
### package.json Complete Example
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-library",
|
||||
"version": "1.0.0",
|
||||
"description": "My TypeScript library",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"require": "./dist/index.js",
|
||||
"import": "./dist/index.mjs"
|
||||
}
|
||||
},
|
||||
"files": ["dist", "lib"],
|
||||
"scripts": {
|
||||
"validate": "pnpm format && pnpm lint && pnpm test && pnpm build",
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check .",
|
||||
"lint": "eslint ./src --fix",
|
||||
"lint:check": "eslint ./src",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
"test:ui": "vitest --ui",
|
||||
"build": "rimraf dist && cross-env NODE_ENV=production tsup",
|
||||
"build:watch": "tsup --watch",
|
||||
"dev": "tsup --watch",
|
||||
"prepublishOnly": "pnpm validate",
|
||||
"ts-types": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Complete File Structure
|
||||
|
||||
```
|
||||
my-library/
|
||||
├── .claude/
|
||||
│ └── skills/
|
||||
│ └── typescript-standards/
|
||||
├── src/
|
||||
│ ├── index.ts
|
||||
│ └── utils/
|
||||
├── test/
|
||||
│ └── index.spec.ts
|
||||
├── .gitignore
|
||||
├── .prettierrc
|
||||
├── eslint.config.mjs
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
├── tsup.config.ts
|
||||
├── vitest.config.ts
|
||||
├── CLAUDE.md
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Build Issues
|
||||
|
||||
**Problem**: "Cannot find module"
|
||||
**Solution**: Check tsup external configuration or package.json exports
|
||||
|
||||
**Problem**: "Types not generated"
|
||||
**Solution**: Ensure `dts: true` in tsup.config.ts
|
||||
|
||||
### Test Issues
|
||||
|
||||
**Problem**: "Test files not found"
|
||||
**Solution**: Check vitest.config.ts include patterns
|
||||
|
||||
**Problem**: "Coverage incomplete"
|
||||
**Solution**: Review coverage.exclude and coverage.include in vitest.config.ts
|
||||
|
||||
### Linting Issues
|
||||
|
||||
**Problem**: "Parsing error"
|
||||
**Solution**: Ensure @typescript-eslint/parser is configured correctly
|
||||
|
||||
**Problem**: "Rule conflicts"
|
||||
**Solution**: Make sure eslint-config-prettier is last in extends
|
||||
|
||||
## Resources
|
||||
|
||||
- **tsup**: https://tsup.egoist.dev/
|
||||
- **Vitest**: https://vitest.dev/
|
||||
- **ESLint**: https://eslint.org/
|
||||
- **Prettier**: https://prettier.io/
|
||||
- **TypeScript**: https://www.typescriptlang.org/
|
||||
Reference in New Issue
Block a user