|
|
@@ -0,0 +1,251 @@ |
|
|
This is typescript environment setup guide for LLM and humans |
|
|
|
|
|
## Baseline |
|
|
|
|
|
Always setup baseline settings |
|
|
|
|
|
- pnpm |
|
|
- typescript |
|
|
- vitest |
|
|
|
|
|
```bash |
|
|
pnpm init --init-type module |
|
|
pnpm add typescript vitest @vitest/coverage-v8 @types/node -D |
|
|
echo "{}" > .vscode/settings.json |
|
|
echo "node_modules\ntmp" > .gitignore |
|
|
mkdir -p src |
|
|
|
|
|
# git |
|
|
git init |
|
|
git add . |
|
|
git commit -m "init" |
|
|
``` |
|
|
|
|
|
package.json |
|
|
|
|
|
```json |
|
|
{ |
|
|
"private": true, |
|
|
"type": "module", |
|
|
"scripts": { |
|
|
"typecheck": "tsc --noEmit", |
|
|
"test": "vitest run", |
|
|
"test:cov": "vitest run --coverage" |
|
|
}, |
|
|
"license": "MIT", |
|
|
"devDependencies": { |
|
|
"@types/node": "^24.0.0", |
|
|
"@vitest/coverage-v8": "3.2.3", |
|
|
"jiti": "^2.4.2", |
|
|
"typescript": "^5.8.3", |
|
|
"vitest": "^3.2.3" |
|
|
}, |
|
|
"pnpm": { |
|
|
"onlyBuiltDependencies": ["esbuild"] |
|
|
} |
|
|
} |
|
|
``` |
|
|
|
|
|
tsconfig.json |
|
|
|
|
|
```json |
|
|
{ |
|
|
"compilerOptions": { |
|
|
"target": "esnext", |
|
|
"module": "esnext", |
|
|
"moduleResolution": "bundler", |
|
|
"noEmit": true, |
|
|
"esModuleInterop": true, |
|
|
"allowImportingTsExtensions": true, |
|
|
"forceConsistentCasingInFileNames": true, |
|
|
"strict": true, |
|
|
"skipLibCheck": true, |
|
|
"types": ["vitest/importMeta"] |
|
|
} |
|
|
} |
|
|
``` |
|
|
|
|
|
or `pnpm tsc --init --module esnext --moduleResolution Bundler --target esnext --noEmit` |
|
|
|
|
|
vitest.config.ts |
|
|
|
|
|
```ts |
|
|
import { defineConfig } from "vitest/config"; |
|
|
export default defineConfig({ |
|
|
test: { |
|
|
includeSource: ["src/**/*.{ts}"], |
|
|
include: ["src/**/*.{test,spec}.{ts,tsx}"], |
|
|
}, |
|
|
}); |
|
|
``` |
|
|
|
|
|
Entrypoint: src/index.ts |
|
|
|
|
|
```ts |
|
|
/** |
|
|
* explation of this module |
|
|
*/ |
|
|
export {}; |
|
|
if (import.meta.vitest) { |
|
|
const { test, expect } = import.meta.vitest; |
|
|
test("init", () => { |
|
|
expect(true).toBe(true); |
|
|
}); |
|
|
} |
|
|
``` |
|
|
|
|
|
.github/workflows/ci.yaml |
|
|
|
|
|
```yaml |
|
|
name: CI |
|
|
on: |
|
|
push: |
|
|
branches: [main] |
|
|
pull_request: |
|
|
branches: [main] |
|
|
jobs: |
|
|
test: |
|
|
runs-on: ubuntu-latest |
|
|
steps: |
|
|
- uses: actions/checkout@v4 |
|
|
- name: Install pnpm |
|
|
uses: pnpm/action-setup@v4 |
|
|
with: |
|
|
version: 10 |
|
|
- uses: actions/setup-node@v4 |
|
|
with: |
|
|
node-version: 24 |
|
|
cache: "pnpm" |
|
|
- run: pnpm install --frozen-lockfile |
|
|
- run: pnpm test |
|
|
- run: pnpm typecheck |
|
|
``` |
|
|
|
|
|
## Optional: eslint |
|
|
|
|
|
Ask to user: `Do you want to use eslint?` |
|
|
|
|
|
```bash |
|
|
pnpm add -d @eslint/js eslint typescript-eslint |
|
|
``` |
|
|
|
|
|
package.json |
|
|
|
|
|
```json |
|
|
{ |
|
|
"scripts": { |
|
|
"lint": "eslint . --quiet", |
|
|
"lint:warn": "eslint .", |
|
|
"lint:fix": "eslint . --fix" |
|
|
} |
|
|
} |
|
|
``` |
|
|
|
|
|
eslint.config.ts |
|
|
|
|
|
```ts |
|
|
import eslint from "@eslint/js"; |
|
|
import tseslint from "typescript-eslint"; |
|
|
export default tseslint.config( |
|
|
eslint.configs.recommended, |
|
|
...tseslint.configs.recommendedTypeCheckedOnly, |
|
|
{ |
|
|
languageOptions: { |
|
|
parserOptions: { |
|
|
projectService: true, |
|
|
tsconfigRootDir: import.meta.dirname, |
|
|
}, |
|
|
}, |
|
|
}, |
|
|
{ |
|
|
// base rules |
|
|
rules: { |
|
|
"@typescript-eslint/no-redeclare": "error", |
|
|
"@typescript-eslint/prefer-ts-expect-error": "error", |
|
|
"@typescript-eslint/no-floating-promises": "error", |
|
|
"@typescript-eslint/only-throw-error": "error", |
|
|
"no-throw-literal": "off", |
|
|
}, |
|
|
}, |
|
|
{ |
|
|
// warning for refactoring |
|
|
rules: { |
|
|
"@typescript-eslint/no-empty-interface": "warn", |
|
|
"@typescript-eslint/no-empty-object-type": "warn", |
|
|
"@typescript-eslint/no-empty-function": "warn", |
|
|
"@typescript-eslint/no-explicit-any": "warn", |
|
|
"@typescript-eslint/no-deprecated": "warn", |
|
|
"@typescript-eslint/await-thenable": "warn", |
|
|
"@typescript-eslint/require-await": "warn", |
|
|
"@typescript-eslint/consistent-type-imports": [ |
|
|
"warn", |
|
|
{ |
|
|
prefer: "type-imports", |
|
|
disallowTypeAnnotations: false, |
|
|
fixStyle: "inline-type-imports", |
|
|
}, |
|
|
], |
|
|
"@typescript-eslint/ban-ts-comment": [ |
|
|
"warn", |
|
|
{ |
|
|
"ts-ignore": true, |
|
|
"ts-expect-error": "allow-with-description", |
|
|
}, |
|
|
], |
|
|
"prefer-const": "warn", |
|
|
complexity: ["warn", { max: 7 }], |
|
|
"no-console": "warn", |
|
|
}, |
|
|
}, |
|
|
{ |
|
|
// allow console in examples |
|
|
files: ["examples/*.ts"], |
|
|
rules: { |
|
|
"no-console": "off", |
|
|
}, |
|
|
} |
|
|
); |
|
|
``` |
|
|
|
|
|
## Optional: PROMPT |
|
|
|
|
|
CLAUDE.md |
|
|
|
|
|
```markdown |
|
|
## Coding Rules |
|
|
|
|
|
- File covention: `src/<snake_case>.ts` |
|
|
- Add test `src/*.test.ts` for `src/*.ts` |
|
|
- Use function and function scope instead of class |
|
|
- Add `.ts` extensions to import. eg. `import {} from "./x.ts"` for deno compatibility. |
|
|
- Never disable any lint rules without explicit user approval |
|
|
``` |
|
|
|
|
|
.claude/settings.json |
|
|
|
|
|
```json |
|
|
{ |
|
|
"permissions": { |
|
|
"allow": ["Bash(pnpm test)", "Bash(ls:*)", "Bash(grep:*)"], |
|
|
"deny": [] |
|
|
} |
|
|
} |
|
|
``` |
|
|
|
|
|
.mcp.json |
|
|
|
|
|
``` |
|
|
{} |
|
|
``` |
|
|
|
|
|
## Optional: neverthrow |
|
|
|
|
|
```bash |
|
|
pnpm add neverthrow -D |
|
|
``` |
|
|
|
|
|
Additional prompt |
|
|
|
|
|
``` |
|
|
Never throw exception in our project. Instead of throw, use neverthrow |
|
|
``` |