init: typescript esm boilerplate
This commit is contained in:
commit
6b522a0803
16 changed files with 3518 additions and 0 deletions
10
.dockerignore
Normal file
10
.dockerignore
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
.git
|
||||
.gitignore
|
||||
.husky
|
||||
node_modules
|
||||
dist
|
||||
*.md
|
||||
.env*
|
||||
!.env.example
|
||||
.vscode
|
||||
.omc
|
||||
9
.editorconfig
Normal file
9
.editorconfig
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
1
.env.example
Normal file
1
.env.example
Normal file
|
|
@ -0,0 +1 @@
|
|||
NODE_ENV=development
|
||||
39
.gitignore
vendored
Normal file
39
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
node_modules/
|
||||
dist/
|
||||
*.tsbuildinfo
|
||||
|
||||
*.log
|
||||
npm-debug.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
._*
|
||||
.directory
|
||||
|
||||
.cache
|
||||
.parcel-cache
|
||||
.next
|
||||
.nuxt
|
||||
out
|
||||
|
||||
coverage
|
||||
*.lcov
|
||||
.nyc_output
|
||||
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/extensions.json
|
||||
.history/
|
||||
*.vsix
|
||||
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
*.tgz
|
||||
|
||||
.omc/
|
||||
4
.tokeignore
Normal file
4
.tokeignore
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
pnpm-lock.yaml
|
||||
node_modules
|
||||
dist
|
||||
.omc
|
||||
34
.vscode/settings.json
vendored
Normal file
34
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"prettier.enable": false,
|
||||
"editor.formatOnSave": false,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.organizeImports": "never"
|
||||
},
|
||||
"eslint.rules.customizations": [
|
||||
{ "rule": "style/*", "severity": "off", "fixable": true },
|
||||
{ "rule": "format/*", "severity": "off", "fixable": true },
|
||||
{ "rule": "*-indent", "severity": "off", "fixable": true },
|
||||
{ "rule": "*-spacing", "severity": "off", "fixable": true },
|
||||
{ "rule": "*-spaces", "severity": "off", "fixable": true },
|
||||
{ "rule": "*-order", "severity": "off", "fixable": true },
|
||||
{ "rule": "*-dangle", "severity": "off", "fixable": true },
|
||||
{ "rule": "*-newline", "severity": "off", "fixable": true },
|
||||
{ "rule": "*quotes", "severity": "off", "fixable": true },
|
||||
{ "rule": "*semi", "severity": "off", "fixable": true }
|
||||
],
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"typescript",
|
||||
"typescriptreact",
|
||||
"html",
|
||||
"markdown",
|
||||
"json",
|
||||
"jsonc",
|
||||
"yaml",
|
||||
"toml",
|
||||
"css",
|
||||
"postcss"
|
||||
]
|
||||
}
|
||||
60
AGENTS.md
Normal file
60
AGENTS.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# Agents
|
||||
|
||||
## Project Overview
|
||||
|
||||
TypeScript ESM boilerplate. Runtime-only via `tsx`, no build step.
|
||||
|
||||
## Stack
|
||||
|
||||
- **Runtime**: Node 24+, tsx
|
||||
- **Package manager**: pnpm
|
||||
- **Linting**: @antfu/eslint-config v8 (eslint.config.mjs)
|
||||
- **Env**: env-var + native `loadEnvFile`
|
||||
- **Container**: Docker, node:24-alpine
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
src/
|
||||
├── index.ts # entrypoint
|
||||
└── shared/
|
||||
└── config.ts # env config
|
||||
```
|
||||
|
||||
## Preferred Folder Structure
|
||||
|
||||
```
|
||||
src/
|
||||
├── index.ts # entrypoint
|
||||
├── shared/ # cross-cutting concerns (config, types, utilities)
|
||||
└── lib/ # third-party wrappers, adapters
|
||||
```
|
||||
|
||||
Expand based on project type as needed. Keep `src/index.ts` as the single entrypoint.
|
||||
|
||||
## Conventions
|
||||
|
||||
- ESM only (`"type": "module"`)
|
||||
- Path alias `@/*` maps to `src/*` — imports must end with `.js` extension (nodenext resolution)
|
||||
- No build step — tsx runs TS directly in dev and prod
|
||||
- `cross-env` for cross-platform env vars in npm scripts
|
||||
- No useless comments
|
||||
- Split code into multiple files rather than monoliths
|
||||
|
||||
## Commands
|
||||
|
||||
- `pnpm dev` — watch mode
|
||||
- `pnpm start` — production run
|
||||
- `pnpm lint` — check
|
||||
- `pnpm lint:fix` — auto-fix
|
||||
|
||||
## Lint Rules
|
||||
|
||||
- `no-console: off` — console.log is allowed
|
||||
- `antfu/no-top-level-await: off`
|
||||
- Stylistic: 2-space indent, single quotes
|
||||
- JSON key ordering enforced (auto-fixed)
|
||||
|
||||
## Docker
|
||||
|
||||
Single-stage, no build. Copies source, installs prod deps, runs via `pnpm start`.
|
||||
3
CLAUDE.md
Normal file
3
CLAUDE.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Claude
|
||||
|
||||
Read [AGENTS.md](./AGENTS.md) for project context, conventions, and structure.
|
||||
11
Dockerfile
Normal file
11
Dockerfile
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
FROM node:24-alpine
|
||||
ENV PNPM_HOME="/pnpm"
|
||||
ENV PATH="$PNPM_HOME:$PATH"
|
||||
RUN corepack enable
|
||||
|
||||
COPY . /app
|
||||
WORKDIR /app
|
||||
|
||||
RUN pnpm install --prod --frozen-lockfile
|
||||
|
||||
CMD ["pnpm", "start"]
|
||||
14
eslint.config.mjs
Normal file
14
eslint.config.mjs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import antfu from '@antfu/eslint-config'
|
||||
|
||||
export default antfu({
|
||||
stylistic: {
|
||||
indent: 2,
|
||||
quotes: 'single',
|
||||
},
|
||||
typescript: true,
|
||||
ignores: ['.omc'],
|
||||
rules: {
|
||||
'no-console': 'off',
|
||||
'antfu/no-top-level-await': 'off',
|
||||
},
|
||||
})
|
||||
26
package.json
Normal file
26
package.json
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "boilerplate",
|
||||
"type": "module",
|
||||
"version": "0.1.0",
|
||||
"packageManager": "pnpm@10.13.1",
|
||||
"description": "typescript esm boilerplate",
|
||||
"engines": {
|
||||
"node": ">=24.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "tsx --watch src/index.ts",
|
||||
"start": "cross-env NODE_ENV=production tsx src/index.ts",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"cross-env": "^7.0.3",
|
||||
"env-var": "^7.5.0",
|
||||
"tsx": "^4.21.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^8.0.0",
|
||||
"@types/node": "^22.15.0",
|
||||
"eslint": "^9.27.0"
|
||||
}
|
||||
}
|
||||
3268
pnpm-lock.yaml
generated
Normal file
3268
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load diff
6
pnpm-workspace.yaml
Normal file
6
pnpm-workspace.yaml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
shellEmulator: true
|
||||
|
||||
trustPolicy: no-downgrade
|
||||
|
||||
onlyBuiltDependencies:
|
||||
- esbuild
|
||||
3
src/index.ts
Normal file
3
src/index.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import { config } from '@/shared/config.js'
|
||||
|
||||
console.log(`starting in ${config.mode} mode...`)
|
||||
10
src/shared/config.ts
Normal file
10
src/shared/config.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { existsSync } from 'node:fs'
|
||||
import { loadEnvFile } from 'node:process'
|
||||
import env from 'env-var'
|
||||
|
||||
if (existsSync('.env'))
|
||||
loadEnvFile('.env')
|
||||
|
||||
export const config = {
|
||||
mode: env.get('NODE_ENV').default('production').asString(),
|
||||
}
|
||||
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2024",
|
||||
"rootDir": "./src",
|
||||
"module": "nodenext",
|
||||
"moduleResolution": "nodenext",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"outDir": "./dist",
|
||||
"sourceMap": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue