ts-builds 1.1.0 ā 1.2.2
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.
- package/README.md +103 -217
- package/dist/cli.js +296 -16
- package/package.json +20 -12
package/README.md
CHANGED
|
@@ -1,148 +1,148 @@
|
|
|
1
1
|
# ts-builds
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/ts-builds)
|
|
4
|
+
[](https://github.com/jordanburke/ts-builds/actions/workflows/node.js.yml)
|
|
4
5
|
|
|
5
|
-
Shared TypeScript
|
|
6
|
+
Shared TypeScript build tooling. Bundles ESLint, Prettier, Vitest, TypeScript and provides a CLI for running standardized commands across projects.
|
|
6
7
|
|
|
7
|
-
##
|
|
8
|
+
## Quick Start
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
### New Project
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- **`.prettierignore`** - Files to ignore from formatting
|
|
15
|
-
|
|
16
|
-
### Extendable Configs (Can Be Customized)
|
|
12
|
+
```bash
|
|
13
|
+
mkdir my-library && cd my-library
|
|
14
|
+
pnpm init
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
- **`tsconfig.base.json`** - TypeScript compiler base settings
|
|
21
|
-
- **`tsdown.config.base.ts`** - Build configuration for tsdown
|
|
22
|
-
- **`package-scripts.json`** - Standardized npm scripts reference
|
|
16
|
+
# Install (bundles all tooling)
|
|
17
|
+
pnpm add -D ts-builds tsdown
|
|
23
18
|
|
|
24
|
-
|
|
19
|
+
# Initialize
|
|
20
|
+
npx ts-builds init # Creates .npmrc with hoist patterns
|
|
21
|
+
npx ts-builds config # Creates ts-builds.config.json
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
# Create source files
|
|
24
|
+
mkdir src test
|
|
25
|
+
echo 'export const hello = () => "Hello!"' > src/index.ts
|
|
28
26
|
|
|
29
|
-
#
|
|
30
|
-
|
|
27
|
+
# Validate
|
|
28
|
+
npx ts-builds validate
|
|
31
29
|
```
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
### Initialize Project
|
|
31
|
+
### Existing Project
|
|
36
32
|
|
|
37
33
|
```bash
|
|
38
|
-
|
|
39
|
-
# or
|
|
40
|
-
npx ts-builds init
|
|
41
|
-
```
|
|
34
|
+
pnpm add -D ts-builds tsdown
|
|
42
35
|
|
|
43
|
-
|
|
36
|
+
npx ts-builds init # Creates .npmrc
|
|
37
|
+
npx ts-builds config # Creates config file
|
|
38
|
+
npx ts-builds cleanup # Remove redundant dependencies
|
|
44
39
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
npx ts-builds help
|
|
40
|
+
npx ts-builds validate
|
|
49
41
|
```
|
|
50
42
|
|
|
51
|
-
|
|
43
|
+
## CLI Commands
|
|
44
|
+
|
|
45
|
+
### Setup Commands
|
|
52
46
|
|
|
53
47
|
```bash
|
|
54
|
-
npx ts-builds
|
|
48
|
+
npx ts-builds init # Create .npmrc with hoist patterns
|
|
49
|
+
npx ts-builds config # Create ts-builds.config.json
|
|
50
|
+
npx ts-builds config --force # Overwrite existing config
|
|
51
|
+
npx ts-builds info # Show bundled packages
|
|
52
|
+
npx ts-builds cleanup # Remove redundant dependencies
|
|
53
|
+
npx ts-builds help # Show all commands
|
|
55
54
|
```
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
### Remove Redundant Dependencies
|
|
56
|
+
### Script Commands
|
|
60
57
|
|
|
61
58
|
```bash
|
|
62
|
-
npx ts-builds
|
|
63
|
-
#
|
|
64
|
-
npx ts-builds
|
|
59
|
+
npx ts-builds validate # Run full validation chain
|
|
60
|
+
npx ts-builds format # Format with Prettier
|
|
61
|
+
npx ts-builds format:check # Check formatting only
|
|
62
|
+
npx ts-builds lint # Lint with ESLint (--fix)
|
|
63
|
+
npx ts-builds lint:check # Check lint only
|
|
64
|
+
npx ts-builds typecheck # TypeScript type checking
|
|
65
|
+
npx ts-builds test # Run tests once
|
|
66
|
+
npx ts-builds test:watch # Watch mode
|
|
67
|
+
npx ts-builds test:coverage # With coverage
|
|
68
|
+
npx ts-builds build # Production build
|
|
69
|
+
npx ts-builds dev # Watch mode build
|
|
65
70
|
```
|
|
66
71
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
### Minimal Installation
|
|
72
|
+
## Package.json Scripts
|
|
70
73
|
|
|
71
|
-
|
|
74
|
+
Add these to delegate all commands to ts-builds:
|
|
72
75
|
|
|
73
76
|
```json
|
|
74
77
|
{
|
|
75
|
-
"
|
|
76
|
-
"ts-builds
|
|
77
|
-
"
|
|
78
|
+
"scripts": {
|
|
79
|
+
"validate": "ts-builds validate",
|
|
80
|
+
"format": "ts-builds format",
|
|
81
|
+
"format:check": "ts-builds format:check",
|
|
82
|
+
"lint": "ts-builds lint",
|
|
83
|
+
"lint:check": "ts-builds lint:check",
|
|
84
|
+
"typecheck": "ts-builds typecheck",
|
|
85
|
+
"test": "ts-builds test",
|
|
86
|
+
"test:watch": "ts-builds test:watch",
|
|
87
|
+
"build": "ts-builds build",
|
|
88
|
+
"dev": "ts-builds dev",
|
|
89
|
+
"prepublishOnly": "pnpm validate"
|
|
78
90
|
}
|
|
79
91
|
}
|
|
80
92
|
```
|
|
81
93
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
```bash
|
|
85
|
-
# Build first, then test
|
|
86
|
-
pnpm build
|
|
87
|
-
node dist/cli.js help
|
|
88
|
-
|
|
89
|
-
# Or link globally
|
|
90
|
-
pnpm link --global
|
|
91
|
-
ts-builds help
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## š Usage
|
|
94
|
+
## Configuration
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
Create `ts-builds.config.json` to customize behavior:
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
### Basic
|
|
99
99
|
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"srcDir": "./src",
|
|
103
|
+
"validateChain": ["format", "lint", "typecheck", "test", "build"]
|
|
104
|
+
}
|
|
103
105
|
```
|
|
104
106
|
|
|
105
|
-
|
|
107
|
+
### Advanced (Monorepos, Custom Commands)
|
|
106
108
|
|
|
107
109
|
```json
|
|
108
110
|
{
|
|
109
|
-
"
|
|
111
|
+
"srcDir": "./src",
|
|
112
|
+
"commands": {
|
|
113
|
+
"compile": "tsc",
|
|
114
|
+
"docs:validate": "pnpm docs:build && pnpm docs:check",
|
|
115
|
+
"landing:validate": { "run": "pnpm validate", "cwd": "./landing" }
|
|
116
|
+
},
|
|
117
|
+
"chains": {
|
|
118
|
+
"validate": ["validate:core", "validate:landing"],
|
|
119
|
+
"validate:core": ["format", "lint", "compile", "test", "docs:validate", "build"],
|
|
120
|
+
"validate:landing": ["landing:validate"]
|
|
121
|
+
}
|
|
110
122
|
}
|
|
111
123
|
```
|
|
112
124
|
|
|
113
|
-
|
|
125
|
+
Run named chains:
|
|
114
126
|
|
|
115
|
-
|
|
127
|
+
```bash
|
|
128
|
+
npx ts-builds validate:core
|
|
129
|
+
npx ts-builds validate:landing
|
|
130
|
+
```
|
|
116
131
|
|
|
117
|
-
|
|
118
|
-
// eslint.config.mjs
|
|
119
|
-
import baseConfig from "ts-builds/eslint"
|
|
132
|
+
## Extendable Configs
|
|
120
133
|
|
|
121
|
-
|
|
122
|
-
```
|
|
134
|
+
ts-builds exports base configurations you can extend:
|
|
123
135
|
|
|
124
|
-
|
|
136
|
+
### ESLint
|
|
125
137
|
|
|
126
138
|
```javascript
|
|
127
139
|
// eslint.config.mjs
|
|
128
140
|
import baseConfig from "ts-builds/eslint"
|
|
129
141
|
|
|
130
|
-
export default [
|
|
131
|
-
...baseConfig,
|
|
132
|
-
{
|
|
133
|
-
// React-specific rules
|
|
134
|
-
files: ["**/*.tsx"],
|
|
135
|
-
rules: {
|
|
136
|
-
"react/jsx-uses-react": "error",
|
|
137
|
-
"react-hooks/rules-of-hooks": "error",
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
]
|
|
142
|
+
export default [...baseConfig]
|
|
141
143
|
```
|
|
142
144
|
|
|
143
|
-
### Vitest
|
|
144
|
-
|
|
145
|
-
**Basic usage:**
|
|
145
|
+
### Vitest
|
|
146
146
|
|
|
147
147
|
```typescript
|
|
148
148
|
// vitest.config.ts
|
|
@@ -152,25 +152,7 @@ import baseConfig from "ts-builds/vitest"
|
|
|
152
152
|
export default defineConfig(baseConfig)
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
```typescript
|
|
158
|
-
// vitest.config.ts
|
|
159
|
-
import { defineConfig } from "vitest/config"
|
|
160
|
-
import baseConfig from "ts-builds/vitest"
|
|
161
|
-
|
|
162
|
-
export default defineConfig({
|
|
163
|
-
...baseConfig,
|
|
164
|
-
test: {
|
|
165
|
-
...baseConfig.test,
|
|
166
|
-
setupFiles: ["./test/setup.ts"], // Add custom setup
|
|
167
|
-
},
|
|
168
|
-
})
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### TypeScript (Extendable)
|
|
172
|
-
|
|
173
|
-
**Basic usage:**
|
|
155
|
+
### TypeScript
|
|
174
156
|
|
|
175
157
|
```json
|
|
176
158
|
{
|
|
@@ -181,22 +163,7 @@ export default defineConfig({
|
|
|
181
163
|
}
|
|
182
164
|
```
|
|
183
165
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
```json
|
|
187
|
-
{
|
|
188
|
-
"extends": "ts-builds/tsconfig",
|
|
189
|
-
"compilerOptions": {
|
|
190
|
-
"outDir": "./dist",
|
|
191
|
-
"jsx": "react-jsx",
|
|
192
|
-
"lib": ["ES2020", "DOM"]
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
### Tsdown (Extendable)
|
|
198
|
-
|
|
199
|
-
**Basic usage:**
|
|
166
|
+
### tsdown
|
|
200
167
|
|
|
201
168
|
```typescript
|
|
202
169
|
// tsdown.config.ts
|
|
@@ -205,106 +172,25 @@ import baseConfig from "ts-builds/tsdown"
|
|
|
205
172
|
export default baseConfig
|
|
206
173
|
```
|
|
207
174
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
```typescript
|
|
211
|
-
// tsdown.config.ts
|
|
212
|
-
import baseConfig from "ts-builds/tsdown"
|
|
213
|
-
import type { UserConfig } from "tsdown"
|
|
214
|
-
|
|
215
|
-
export default {
|
|
216
|
-
...baseConfig,
|
|
217
|
-
entry: ["src/index.ts", "src/cli.ts"], // Multiple entry points
|
|
218
|
-
} satisfies UserConfig
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
### Package Scripts (Reference Only)
|
|
222
|
-
|
|
223
|
-
The `package-scripts.json` file contains standardized npm scripts. Copy the relevant scripts to your `package.json`:
|
|
175
|
+
### Prettier
|
|
224
176
|
|
|
225
177
|
```json
|
|
226
178
|
{
|
|
227
|
-
"
|
|
228
|
-
"validate": "pnpm format && pnpm lint && pnpm test && pnpm build",
|
|
229
|
-
"format": "prettier --write .",
|
|
230
|
-
"format:check": "prettier --check .",
|
|
231
|
-
"lint": "eslint ./src --fix",
|
|
232
|
-
"lint:check": "eslint ./src",
|
|
233
|
-
"test": "vitest run",
|
|
234
|
-
"test:watch": "vitest",
|
|
235
|
-
"test:coverage": "vitest run --coverage",
|
|
236
|
-
"test:ui": "vitest --ui",
|
|
237
|
-
"build": "rimraf dist && cross-env NODE_ENV=production tsdown",
|
|
238
|
-
"build:watch": "tsdown --watch",
|
|
239
|
-
"dev": "tsdown --watch",
|
|
240
|
-
"prepublishOnly": "pnpm validate",
|
|
241
|
-
"ts-types": "tsc"
|
|
242
|
-
}
|
|
179
|
+
"prettier": "ts-builds/prettier"
|
|
243
180
|
}
|
|
244
181
|
```
|
|
245
182
|
|
|
246
|
-
##
|
|
247
|
-
|
|
248
|
-
When configs are updated in this package, update your template:
|
|
249
|
-
|
|
250
|
-
```bash
|
|
251
|
-
# Update to latest version
|
|
252
|
-
pnpm update ts-builds
|
|
253
|
-
|
|
254
|
-
# Re-copy locked files (Prettier)
|
|
255
|
-
cp node_modules/ts-builds/.prettierrc .
|
|
256
|
-
cp node_modules/ts-builds/.prettierignore .
|
|
257
|
-
|
|
258
|
-
# Test that everything still works
|
|
259
|
-
pnpm validate
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
## šÆ Design Philosophy
|
|
263
|
-
|
|
264
|
-
### Locked vs Extendable
|
|
265
|
-
|
|
266
|
-
**Locked files** ensure consistency across all templates:
|
|
267
|
-
|
|
268
|
-
- **Prettier** - Code formatting should be identical everywhere
|
|
269
|
-
- Prevents formatting debates and merge conflicts
|
|
270
|
-
|
|
271
|
-
**Extendable files** allow variant-specific customization:
|
|
272
|
-
|
|
273
|
-
- **ESLint** - Different variants need different rules (React, Node.js, etc.)
|
|
274
|
-
- **Vitest** - Some variants need custom test setup
|
|
275
|
-
- **TypeScript** - Browser vs Node targets, JSX support, etc.
|
|
276
|
-
- **Build configs** - Different entry points, output formats
|
|
277
|
-
|
|
278
|
-
### Semantic Versioning
|
|
279
|
-
|
|
280
|
-
This package follows semver:
|
|
281
|
-
|
|
282
|
-
- **Patch** (1.0.x) - Bug fixes in configs
|
|
283
|
-
- **Minor** (1.x.0) - New configs added, backward compatible
|
|
284
|
-
- **Major** (x.0.0) - Breaking changes to existing configs
|
|
285
|
-
|
|
286
|
-
## š Available Template Variants
|
|
287
|
-
|
|
288
|
-
Templates using these configs:
|
|
289
|
-
|
|
290
|
-
- **[typescript-library-template](https://github.com/jordanburke/typescript-library-template)** - Base template (tsdown)
|
|
291
|
-
- **typescript-library-template-vite** - Vite-based variant (coming soon)
|
|
292
|
-
- **typescript-library-template-react** - React library variant (coming soon)
|
|
293
|
-
|
|
294
|
-
## š¤ Contributing
|
|
295
|
-
|
|
296
|
-
Found a bug or want to improve the configs?
|
|
297
|
-
|
|
298
|
-
1. Fork this repository
|
|
299
|
-
2. Make your changes
|
|
300
|
-
3. Test in a template project
|
|
301
|
-
4. Submit a PR with explanation
|
|
183
|
+
## Bundled Packages
|
|
302
184
|
|
|
303
|
-
|
|
185
|
+
Run `npx ts-builds info` to see all bundled packages. You don't need to install:
|
|
304
186
|
|
|
305
|
-
|
|
187
|
+
- eslint, prettier, typescript, vitest
|
|
188
|
+
- @typescript-eslint/eslint-plugin, @typescript-eslint/parser
|
|
189
|
+
- eslint-config-prettier, eslint-plugin-prettier, eslint-plugin-import
|
|
190
|
+
- @vitest/coverage-v8, @vitest/ui
|
|
191
|
+
- cross-env, rimraf, ts-node
|
|
192
|
+
- And more...
|
|
306
193
|
|
|
307
|
-
##
|
|
194
|
+
## License
|
|
308
195
|
|
|
309
|
-
|
|
310
|
-
- [package-scripts.json](./package-scripts.json) - Script reference documentation
|
|
196
|
+
MIT
|
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,72 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
2
3
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
4
|
import { join } from "node:path";
|
|
4
5
|
import { createInterface } from "node:readline";
|
|
5
6
|
|
|
6
7
|
//#region src/cli.ts
|
|
7
8
|
const targetDir = process.cwd();
|
|
9
|
+
const defaultChains = { validate: [
|
|
10
|
+
"format",
|
|
11
|
+
"lint",
|
|
12
|
+
"typecheck",
|
|
13
|
+
"test",
|
|
14
|
+
"build"
|
|
15
|
+
] };
|
|
16
|
+
function loadConfig() {
|
|
17
|
+
const configPath = join(targetDir, "ts-builds.config.json");
|
|
18
|
+
let userConfig = {};
|
|
19
|
+
if (existsSync(configPath)) try {
|
|
20
|
+
userConfig = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
21
|
+
} catch {
|
|
22
|
+
console.error("Warning: Failed to parse ts-builds.config.json, using defaults");
|
|
23
|
+
}
|
|
24
|
+
const commands = {};
|
|
25
|
+
if (userConfig.commands) for (const [name, cmd] of Object.entries(userConfig.commands)) commands[name] = typeof cmd === "string" ? { run: cmd } : cmd;
|
|
26
|
+
const chains = { ...defaultChains };
|
|
27
|
+
if (userConfig.validateChain) chains.validate = userConfig.validateChain;
|
|
28
|
+
if (userConfig.chains) Object.assign(chains, userConfig.chains);
|
|
29
|
+
return {
|
|
30
|
+
srcDir: userConfig.srcDir ?? "./src",
|
|
31
|
+
testDir: userConfig.testDir ?? "./test",
|
|
32
|
+
commands,
|
|
33
|
+
chains
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function runCommand(command$1, args, options = {}) {
|
|
37
|
+
const cwd = options.cwd ? join(targetDir, options.cwd) : targetDir;
|
|
38
|
+
return new Promise((resolve) => {
|
|
39
|
+
const child = spawn(command$1, args, {
|
|
40
|
+
cwd,
|
|
41
|
+
stdio: "inherit",
|
|
42
|
+
shell: true
|
|
43
|
+
});
|
|
44
|
+
child.on("close", (code) => {
|
|
45
|
+
resolve(code ?? 1);
|
|
46
|
+
});
|
|
47
|
+
child.on("error", (err) => {
|
|
48
|
+
console.error(`Failed to run ${command$1}: ${err.message}`);
|
|
49
|
+
resolve(1);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function runShellCommand(shellCmd, options = {}) {
|
|
54
|
+
const cwd = options.cwd ? join(targetDir, options.cwd) : targetDir;
|
|
55
|
+
return new Promise((resolve) => {
|
|
56
|
+
const child = spawn(shellCmd, {
|
|
57
|
+
cwd,
|
|
58
|
+
stdio: "inherit",
|
|
59
|
+
shell: true
|
|
60
|
+
});
|
|
61
|
+
child.on("close", (code) => {
|
|
62
|
+
resolve(code ?? 1);
|
|
63
|
+
});
|
|
64
|
+
child.on("error", (err) => {
|
|
65
|
+
console.error(`Failed to run: ${err.message}`);
|
|
66
|
+
resolve(1);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
8
70
|
const bundledPackages = [
|
|
9
71
|
"@eslint/eslintrc",
|
|
10
72
|
"@eslint/js",
|
|
@@ -50,31 +112,72 @@ function ensureNpmrcHoistPatterns() {
|
|
|
50
112
|
}
|
|
51
113
|
function showHelp() {
|
|
52
114
|
console.log(`
|
|
53
|
-
ts-builds - Shared TypeScript
|
|
115
|
+
ts-builds - Shared TypeScript build tooling
|
|
54
116
|
|
|
55
117
|
USAGE:
|
|
56
118
|
npx ts-builds [command]
|
|
57
119
|
|
|
58
|
-
COMMANDS:
|
|
59
|
-
init Initialize project with
|
|
120
|
+
SETUP COMMANDS:
|
|
121
|
+
init Initialize project with .npmrc hoist patterns (default)
|
|
122
|
+
config Create ts-builds.config.json (use --force to overwrite)
|
|
60
123
|
info Show bundled packages you don't need to install
|
|
61
124
|
cleanup Remove redundant dependencies from package.json
|
|
62
125
|
help Show this help message
|
|
63
126
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
127
|
+
SCRIPT COMMANDS:
|
|
128
|
+
validate Run full validation chain (configurable)
|
|
129
|
+
format Format code with Prettier (--write)
|
|
130
|
+
format:check Check formatting without writing
|
|
131
|
+
lint Lint and fix with ESLint
|
|
132
|
+
lint:check Check lint without fixing
|
|
133
|
+
typecheck Run TypeScript type checking (tsc --noEmit)
|
|
134
|
+
test Run tests once (vitest run)
|
|
135
|
+
test:watch Run tests in watch mode
|
|
136
|
+
test:coverage Run tests with coverage
|
|
137
|
+
test:ui Launch Vitest UI
|
|
138
|
+
build Production build (rimraf dist && tsdown)
|
|
139
|
+
build:watch Watch mode build
|
|
140
|
+
dev Alias for build:watch
|
|
68
141
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
tooling as dependencies. You only need to install:
|
|
142
|
+
CONFIGURATION:
|
|
143
|
+
Create ts-builds.config.json in your project root:
|
|
72
144
|
|
|
73
|
-
|
|
74
|
-
|
|
145
|
+
Basic:
|
|
146
|
+
{
|
|
147
|
+
"srcDir": "./src",
|
|
148
|
+
"validateChain": ["format", "lint", "typecheck", "test", "build"]
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
Advanced (monorepo with custom commands):
|
|
152
|
+
{
|
|
153
|
+
"srcDir": "./src",
|
|
154
|
+
"commands": {
|
|
155
|
+
"docs:validate": "pnpm docs:build && pnpm docs:check",
|
|
156
|
+
"landing:validate": { "run": "pnpm validate", "cwd": "./landing" }
|
|
157
|
+
},
|
|
158
|
+
"chains": {
|
|
159
|
+
"validate": ["validate:core", "validate:landing"],
|
|
160
|
+
"validate:core": ["format", "lint", "compile", "test", "docs:validate", "build"],
|
|
161
|
+
"validate:landing": ["landing:validate"]
|
|
162
|
+
}
|
|
163
|
+
}
|
|
75
164
|
|
|
76
|
-
|
|
77
|
-
|
|
165
|
+
USAGE IN PACKAGE.JSON:
|
|
166
|
+
{
|
|
167
|
+
"scripts": {
|
|
168
|
+
"validate": "ts-builds validate",
|
|
169
|
+
"validate:core": "ts-builds validate:core",
|
|
170
|
+
"format": "ts-builds format",
|
|
171
|
+
"lint": "ts-builds lint",
|
|
172
|
+
"test": "ts-builds test",
|
|
173
|
+
"build": "ts-builds build"
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
EXAMPLES:
|
|
178
|
+
npx ts-builds validate # Run default validation chain
|
|
179
|
+
npx ts-builds validate:core # Run named chain
|
|
180
|
+
npx ts-builds lint # Run single command
|
|
78
181
|
`);
|
|
79
182
|
}
|
|
80
183
|
function showInfo() {
|
|
@@ -151,10 +254,133 @@ function init() {
|
|
|
151
254
|
ensureNpmrcHoistPatterns();
|
|
152
255
|
console.log("\nDone! Your project is configured to hoist CLI binaries from peer dependencies.");
|
|
153
256
|
console.log("\nNext steps:");
|
|
257
|
+
console.log(" - Run 'npx ts-builds config' to create a config file");
|
|
154
258
|
console.log(" - Run 'npx ts-builds info' to see bundled packages");
|
|
155
259
|
console.log(" - Run 'npx ts-builds cleanup' to remove redundant deps");
|
|
156
260
|
}
|
|
157
|
-
|
|
261
|
+
function createConfig(force = false) {
|
|
262
|
+
const configPath = join(targetDir, "ts-builds.config.json");
|
|
263
|
+
if (existsSync(configPath) && !force) {
|
|
264
|
+
console.log("ts-builds.config.json already exists.");
|
|
265
|
+
console.log("Use 'ts-builds config --force' to overwrite.");
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
writeFileSync(configPath, JSON.stringify({
|
|
269
|
+
srcDir: "./src",
|
|
270
|
+
validateChain: [
|
|
271
|
+
"format",
|
|
272
|
+
"lint",
|
|
273
|
+
"typecheck",
|
|
274
|
+
"test",
|
|
275
|
+
"build"
|
|
276
|
+
]
|
|
277
|
+
}, null, 2) + "\n");
|
|
278
|
+
console.log("ā Created ts-builds.config.json");
|
|
279
|
+
console.log(`
|
|
280
|
+
Configuration options:
|
|
281
|
+
srcDir Source directory for linting (default: "./src")
|
|
282
|
+
testDir Test directory (default: "./test")
|
|
283
|
+
validateChain Commands to run for validate (default shown above)
|
|
284
|
+
commands Custom commands: { "name": "shell command" }
|
|
285
|
+
chains Named chains: { "validate:fast": ["format", "lint"] }
|
|
286
|
+
|
|
287
|
+
Example with custom commands:
|
|
288
|
+
{
|
|
289
|
+
"srcDir": "./src",
|
|
290
|
+
"commands": {
|
|
291
|
+
"docs": "pnpm docs:build",
|
|
292
|
+
"subproject": { "run": "pnpm validate", "cwd": "./packages/sub" }
|
|
293
|
+
},
|
|
294
|
+
"chains": {
|
|
295
|
+
"validate": ["format", "lint", "test", "build"],
|
|
296
|
+
"validate:full": ["format", "lint", "typecheck", "test", "docs", "build"]
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
`);
|
|
300
|
+
}
|
|
301
|
+
async function runFormat(check = false) {
|
|
302
|
+
return runCommand("prettier", check ? ["--check", "."] : ["--write", "."]);
|
|
303
|
+
}
|
|
304
|
+
async function runLint(check = false) {
|
|
305
|
+
const config = loadConfig();
|
|
306
|
+
return runCommand("eslint", check ? [config.srcDir] : ["--fix", config.srcDir]);
|
|
307
|
+
}
|
|
308
|
+
async function runTypecheck() {
|
|
309
|
+
return runCommand("tsc", ["--noEmit"]);
|
|
310
|
+
}
|
|
311
|
+
async function runTest(mode = "run") {
|
|
312
|
+
switch (mode) {
|
|
313
|
+
case "watch": return runCommand("vitest", []);
|
|
314
|
+
case "coverage": return runCommand("vitest", ["run", "--coverage"]);
|
|
315
|
+
case "ui": return runCommand("vitest", ["--ui"]);
|
|
316
|
+
default: return runCommand("vitest", ["run"]);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
async function runBuild(watch = false) {
|
|
320
|
+
if (watch) return runCommand("tsdown", ["--watch"]);
|
|
321
|
+
const cleanCode = await runCommand("rimraf", ["dist"]);
|
|
322
|
+
if (cleanCode !== 0) return cleanCode;
|
|
323
|
+
return runCommand("cross-env", ["NODE_ENV=production", "tsdown"]);
|
|
324
|
+
}
|
|
325
|
+
function getBuiltinCommands(config) {
|
|
326
|
+
return {
|
|
327
|
+
format: { run: "prettier --write ." },
|
|
328
|
+
"format:check": { run: "prettier --check ." },
|
|
329
|
+
lint: { run: `eslint --fix ${config.srcDir}` },
|
|
330
|
+
"lint:check": { run: `eslint ${config.srcDir}` },
|
|
331
|
+
typecheck: { run: "tsc --noEmit" },
|
|
332
|
+
"ts-types": { run: "tsc --noEmit" },
|
|
333
|
+
test: { run: "vitest run" },
|
|
334
|
+
"test:watch": { run: "vitest" },
|
|
335
|
+
"test:coverage": { run: "vitest run --coverage" },
|
|
336
|
+
"test:ui": { run: "vitest --ui" },
|
|
337
|
+
build: { run: "rimraf dist && cross-env NODE_ENV=production tsdown" },
|
|
338
|
+
"build:watch": { run: "tsdown --watch" },
|
|
339
|
+
dev: { run: "tsdown --watch" },
|
|
340
|
+
compile: { run: "tsc" }
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
async function runChain(chainName, config, visited = /* @__PURE__ */ new Set()) {
|
|
344
|
+
if (visited.has(chainName)) {
|
|
345
|
+
console.error(`Circular chain reference detected: ${chainName}`);
|
|
346
|
+
return 1;
|
|
347
|
+
}
|
|
348
|
+
visited.add(chainName);
|
|
349
|
+
const chain = config.chains[chainName];
|
|
350
|
+
if (!chain) {
|
|
351
|
+
console.error(`Unknown chain: ${chainName}`);
|
|
352
|
+
return 1;
|
|
353
|
+
}
|
|
354
|
+
const builtins = getBuiltinCommands(config);
|
|
355
|
+
console.log(`\nš Running chain: ${chainName} [${chain.join(" ā ")}]`);
|
|
356
|
+
for (const step of chain) {
|
|
357
|
+
if (config.chains[step]) {
|
|
358
|
+
const code$1 = await runChain(step, config, visited);
|
|
359
|
+
if (code$1 !== 0) return code$1;
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
const cmdDef = config.commands[step] ?? builtins[step];
|
|
363
|
+
if (!cmdDef) {
|
|
364
|
+
console.error(`Unknown command or chain: ${step}`);
|
|
365
|
+
return 1;
|
|
366
|
+
}
|
|
367
|
+
const cwdLabel = cmdDef.cwd ? ` (in ${cmdDef.cwd})` : "";
|
|
368
|
+
console.log(`\nā¶ Running ${step}...${cwdLabel}`);
|
|
369
|
+
const code = await runShellCommand(cmdDef.run, { cwd: cmdDef.cwd });
|
|
370
|
+
if (code !== 0) {
|
|
371
|
+
console.error(`\nā ${step} failed with exit code ${code}`);
|
|
372
|
+
return code;
|
|
373
|
+
}
|
|
374
|
+
console.log(`ā ${step} complete`);
|
|
375
|
+
}
|
|
376
|
+
return 0;
|
|
377
|
+
}
|
|
378
|
+
async function runValidate(chainName = "validate") {
|
|
379
|
+
return runChain(chainName, loadConfig());
|
|
380
|
+
}
|
|
381
|
+
const command = process.argv[2] || "init";
|
|
382
|
+
const subCommand = process.argv[3];
|
|
383
|
+
switch (command) {
|
|
158
384
|
case "help":
|
|
159
385
|
case "--help":
|
|
160
386
|
case "-h":
|
|
@@ -168,10 +394,64 @@ switch (process.argv[2] || "init") {
|
|
|
168
394
|
case "--cleanup":
|
|
169
395
|
await cleanup();
|
|
170
396
|
break;
|
|
397
|
+
case "format":
|
|
398
|
+
process.exit(await runFormat(subCommand === "check"));
|
|
399
|
+
break;
|
|
400
|
+
case "format:check":
|
|
401
|
+
process.exit(await runFormat(true));
|
|
402
|
+
break;
|
|
403
|
+
case "lint":
|
|
404
|
+
process.exit(await runLint(subCommand === "check"));
|
|
405
|
+
break;
|
|
406
|
+
case "lint:check":
|
|
407
|
+
process.exit(await runLint(true));
|
|
408
|
+
break;
|
|
409
|
+
case "typecheck":
|
|
410
|
+
case "ts-types":
|
|
411
|
+
process.exit(await runTypecheck());
|
|
412
|
+
break;
|
|
413
|
+
case "test":
|
|
414
|
+
process.exit(await runTest(subCommand));
|
|
415
|
+
break;
|
|
416
|
+
case "test:watch":
|
|
417
|
+
process.exit(await runTest("watch"));
|
|
418
|
+
break;
|
|
419
|
+
case "test:coverage":
|
|
420
|
+
process.exit(await runTest("coverage"));
|
|
421
|
+
break;
|
|
422
|
+
case "test:ui":
|
|
423
|
+
process.exit(await runTest("ui"));
|
|
424
|
+
break;
|
|
425
|
+
case "build":
|
|
426
|
+
process.exit(await runBuild(subCommand === "watch"));
|
|
427
|
+
break;
|
|
428
|
+
case "build:watch":
|
|
429
|
+
case "dev":
|
|
430
|
+
process.exit(await runBuild(true));
|
|
431
|
+
break;
|
|
432
|
+
case "validate":
|
|
433
|
+
process.exit(await runValidate());
|
|
434
|
+
break;
|
|
171
435
|
case "init":
|
|
172
|
-
default:
|
|
173
436
|
init();
|
|
174
437
|
break;
|
|
438
|
+
case "config":
|
|
439
|
+
createConfig(process.argv.includes("--force") || process.argv.includes("-f"));
|
|
440
|
+
break;
|
|
441
|
+
default: {
|
|
442
|
+
const config = loadConfig();
|
|
443
|
+
if (config.chains[command]) process.exit(await runValidate(command));
|
|
444
|
+
else if (config.commands[command]) {
|
|
445
|
+
const cmdDef = config.commands[command];
|
|
446
|
+
const code = await runShellCommand(cmdDef.run, { cwd: cmdDef.cwd });
|
|
447
|
+
process.exit(code);
|
|
448
|
+
} else {
|
|
449
|
+
console.error(`Unknown command: ${command}`);
|
|
450
|
+
console.log("Run 'ts-builds help' for usage information.");
|
|
451
|
+
process.exit(1);
|
|
452
|
+
}
|
|
453
|
+
break;
|
|
454
|
+
}
|
|
175
455
|
}
|
|
176
456
|
|
|
177
457
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-builds",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Shared TypeScript configuration files for library templates. Provides standardized ESLint, Prettier, Vitest, TypeScript, and build configs.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
"homepage": "https://github.com/jordanburke/ts-builds",
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|
|
21
|
-
"url": "https://github.com/jordanburke/ts-builds"
|
|
21
|
+
"url": "git+https://github.com/jordanburke/ts-builds.git"
|
|
22
22
|
},
|
|
23
23
|
"main": "./prettier-config.js",
|
|
24
24
|
"bin": {
|
|
25
|
-
"ts-builds": "
|
|
25
|
+
"ts-builds": "dist/cli.js"
|
|
26
26
|
},
|
|
27
27
|
"exports": {
|
|
28
28
|
".": "./prettier-config.js",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"@eslint/eslintrc": "^3.3.3",
|
|
51
51
|
"@eslint/js": "^9.39.1",
|
|
52
52
|
"@types/node": "^22.19.1",
|
|
53
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
54
|
-
"@typescript-eslint/parser": "^8.
|
|
53
|
+
"@typescript-eslint/eslint-plugin": "^8.49.0",
|
|
54
|
+
"@typescript-eslint/parser": "^8.49.0",
|
|
55
55
|
"@vitest/coverage-v8": "^4.0.15",
|
|
56
56
|
"@vitest/ui": "^4.0.15",
|
|
57
57
|
"cross-env": "^10.1.0",
|
|
@@ -79,11 +79,19 @@
|
|
|
79
79
|
}
|
|
80
80
|
},
|
|
81
81
|
"scripts": {
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
82
|
+
"bootstrap": "rimraf dist && tsdown",
|
|
83
|
+
"validate": "node dist/cli.js validate",
|
|
84
|
+
"validate:bootstrap": "pnpm bootstrap && pnpm validate",
|
|
85
|
+
"format": "node dist/cli.js format",
|
|
86
|
+
"format:check": "node dist/cli.js format:check",
|
|
87
|
+
"lint": "node dist/cli.js lint",
|
|
88
|
+
"lint:check": "node dist/cli.js lint:check",
|
|
89
|
+
"typecheck": "node dist/cli.js typecheck",
|
|
90
|
+
"test": "node dist/cli.js test",
|
|
86
91
|
"test:watch": "vitest",
|
|
87
|
-
"
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
"build": "node dist/cli.js build",
|
|
93
|
+
"dev": "node dist/cli.js dev",
|
|
94
|
+
"prepublishOnly": "pnpm validate:bootstrap"
|
|
95
|
+
},
|
|
96
|
+
"packageManager": "pnpm@10.24.0+sha512.01ff8ae71b4419903b65c60fb2dc9d34cf8bb6e06d03bde112ef38f7a34d6904c424ba66bea5cdcf12890230bf39f9580473140ed9c946fef328b6e5238a345a"
|
|
97
|
+
}
|