@tofrankie/tsconfig 0.0.4 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## tsconfig@0.1.0 (2026-05-22)
4
+
5
+ ### Breaking Changes 🚨
6
+
7
+ - Redesign preset and naming system
8
+ - Added exports: `web.app.json`, `react.app.json`, `vue.app.json`, `node.app.json`, `node.lib.json`, `react.lib.json`, `vue.lib.json`, `vitest.web.json`, `vitest.node.json`, `strict.json`
9
+ - Removed exports: `dom.json`, `node.json`, `lib.json`, `strictest.json`, `vitest.json`, `react.vite.json`, `vue.vite.json`, `react.lib.vite.json`, `vue.lib.vite.json`, `node.lib.tsdown.json`
10
+
11
+ ### Features
12
+
13
+ - Added interactive CLI (`npx @tofrankie/tsconfig`) to scaffold `tsconfig` files
14
+
15
+ ## tsconfig@0.0.5 (2026-04-04)
16
+
17
+ - Update documentation
18
+
3
19
  ## tsconfig@0.0.4 (2026-03-31)
4
20
 
5
21
  - Update `node.lib.tsdown.json` preset: disable `declarationMap`
package/README.md CHANGED
@@ -2,97 +2,58 @@
2
2
 
3
3
  ![npm version](https://img.shields.io/npm/v/@tofrankie/tsconfig) ![node version](https://img.shields.io/node/v/@tofrankie/tsconfig) ![npm package license](https://img.shields.io/npm/l/@tofrankie/tsconfig) ![npm last update](https://img.shields.io/npm/last-update/@tofrankie/tsconfig)
4
4
 
5
- Shared [tsconfig](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) configuration.
5
+ Shared [TypeScript](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) configuration.
6
6
 
7
7
  > [!IMPORTANT]
8
- > Presets are not yet stable and may change.
8
+ > Before 1.0.0, releases may include breaking changes. Read the [CHANGELOG](CHANGELOG.md) before upgrading.
9
9
 
10
- ## Usage
10
+ ## Install
11
11
 
12
12
  ```bash
13
13
  $ pnpm add typescript @tofrankie/tsconfig -D
14
14
  ```
15
15
 
16
- Create a `tsconfig.json` in your project root:
16
+ Install additional dependencies based on your scenario:
17
17
 
18
- ```json
19
- {
20
- "extends": "@tofrankie/tsconfig/react.vite.json"
21
- // other options...
22
- }
23
- ```
24
-
25
- ## Presets
26
-
27
- Use `@tofrankie/tsconfig/<filename>` in `extends`. If the last column of the table is not `-`, also add those packages to this project's devDependencies.
28
-
29
- | Preset | Purpose (how to choose) | Extra dependencies |
30
- | ---------------------- | -------------------------------------------------------- | ----------------------- |
31
- | `strictest.json` | Strictest rules | - |
32
- | `strict.json` | Strict rules | - |
33
- | `dom.json` | Web App / DOM API | - |
34
- | `node.json` | Node scripts / services / CLI (`@tsconfig/node20`) | - |
35
- | `lib.json` | npm packages to publish (independent of runtime) | - |
36
- | `node.lib.json` | Node packages to publish | - |
37
- | `node.lib.tsdown.json` | Node libraries for tsdown (bundler resolution, `noEmit`) | - |
38
- | `react.json` | React App (bundler-agnostic) | - |
39
- | `react.vite.json` | React + Vite | `vite` |
40
- | `react.lib.json` | React component libraries to publish | - |
41
- | `react.lib.vite.json` | React component libraries developed with Vite | `vite` |
42
- | `vue.json` | Vue 3 App (bundler-agnostic) | - |
43
- | `vue.vite.json` | Vue 3 + Vite | `vite` |
44
- | `vue.lib.json` | Vue 3 component libraries to publish | - |
45
- | `vue.lib.vite.json` | Vue 3 component libraries developed with Vite | `vite` |
46
- | `vitest.json` | Testing with Vitest | `@types/node`, `vitest` |
47
-
48
- Dependency relationships between them: **[DEPENDENCY_GRAPH](./DEPENDENCY_GRAPH.md)**.
49
-
50
- ## Examples
51
-
52
- ### React + Vite
53
-
54
- `tsconfig.json`
18
+ - Node projects usually need: `@types/node`
19
+ - Vitest projects usually need: `vitest`, `@types/node`
20
+ - Vite projects usually need: `vite`
55
21
 
56
- ```json
57
- {
58
- "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }],
59
- "files": []
60
- }
61
- ```
22
+ ## Quick Start
62
23
 
63
- `tsconfig.app.json`
24
+ Choose one preset based on your project:
64
25
 
65
- ```json
66
- {
67
- "extends": "@tofrankie/tsconfig/react.vite.json",
68
- "compilerOptions": {
69
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo"
70
- },
71
- "include": ["src"]
72
- }
73
- ```
26
+ - `@tofrankie/tsconfig/web.app.json` - Web App (framework-agnostic)
27
+ - `@tofrankie/tsconfig/react.app.json` - React Web App
28
+ - `@tofrankie/tsconfig/react.lib.json` - React Library (npm package)
29
+ - `@tofrankie/tsconfig/vue.app.json` - Vue Web App
30
+ - `@tofrankie/tsconfig/vue.lib.json` - Vue Library (npm package)
31
+ - `@tofrankie/tsconfig/node.app.json` - Node Application/Script
32
+ - `@tofrankie/tsconfig/node.lib.json` - Node Library (npm package)
33
+ - `@tofrankie/tsconfig/vitest.web.json` - Vitest (Web)
34
+ - `@tofrankie/tsconfig/vitest.node.json` - Vitest (Node)
35
+ - `@tofrankie/tsconfig/strict.json` - Strict
74
36
 
75
- `tsconfig.node.json`
37
+ Then extend it from your `tsconfig.json`. For example, for a React web app:
76
38
 
77
- ```json
39
+ ```jsonc
78
40
  {
79
- "extends": "@tofrankie/tsconfig/node.json",
41
+ "extends": "@tofrankie/tsconfig/react.app.json",
80
42
  "compilerOptions": {
81
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo"
43
+ // your custom compiler options
44
+ // ...
82
45
  },
83
- "include": ["vite.config.ts"]
84
46
  }
85
47
  ```
86
48
 
87
- ## Acknowledgements
49
+ ## CLI
88
50
 
89
- Thanks to these referenced packages:
51
+ An interactive CLI is included to scaffold your `tsconfig` files quickly. After generation, adjust the output files to match your project needs.
90
52
 
91
- - `@tsconfig/node20`
92
- - `@tsconfig/strictest`
93
- - `@tsconfig/vite-react`
94
- - `@vue/tsconfig`
53
+ ```bash
54
+ $ npx @tofrankie/tsconfig
55
+ ```
95
56
 
96
57
  ## License
97
58
 
98
- MIT
59
+ MIT License © [Frankie](https://github.com/tofrankie)
package/dist/index.mjs ADDED
@@ -0,0 +1,330 @@
1
+ #!/usr/bin/env node
2
+ import { confirm, isCancel, outro, select } from "@clack/prompts";
3
+ import { Command } from "commander";
4
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
5
+ import { execaCommand } from "execa";
6
+ //#region src/cli/constants.ts
7
+ const STACKS = [
8
+ "react",
9
+ "vue",
10
+ "node",
11
+ "web"
12
+ ];
13
+ const SHAPES = ["app", "lib"];
14
+ const TEST_RUNNERS = [
15
+ "vitest",
16
+ "none",
17
+ "other"
18
+ ];
19
+ const BUNDLERS = [
20
+ "vite",
21
+ "rollup",
22
+ "tsdown",
23
+ "tsup",
24
+ "none",
25
+ "other"
26
+ ];
27
+ //#endregion
28
+ //#region src/cli/args/index.ts
29
+ function parseArgs(argv) {
30
+ const program = new Command("tsconfig");
31
+ const stackSet = new Set(STACKS);
32
+ const shapeSet = new Set(SHAPES);
33
+ const testSet = new Set(TEST_RUNNERS);
34
+ const bundlerSet = new Set(BUNDLERS);
35
+ function parseStack(value) {
36
+ if (!stackSet.has(value)) throw new Error(`Invalid --stack: ${value}`);
37
+ return value;
38
+ }
39
+ function parseShape(value) {
40
+ if (!shapeSet.has(value)) throw new Error(`Invalid --shape: ${value}`);
41
+ return value;
42
+ }
43
+ function parseTest(value) {
44
+ if (!testSet.has(value)) throw new Error(`Invalid --test: ${value}`);
45
+ return value;
46
+ }
47
+ function parseBundler(value) {
48
+ if (!bundlerSet.has(value)) throw new Error(`Invalid --bundler: ${value}`);
49
+ return value;
50
+ }
51
+ program.option("--stack <stack>", "react|vue|node|web", parseStack).option("--shape <shape>", "app|lib", parseShape).option("--test <test>", "vitest|none|other", parseTest).option("--bundler <bundler>", "vite|rollup|tsdown|tsup|none|other", parseBundler).option("--yes", "non-interactive mode").option("--install", "install dependencies").option("--force", "overwrite all existing files");
52
+ program.parse(argv);
53
+ return program.opts();
54
+ }
55
+ //#endregion
56
+ //#region src/cli/generate/merge-tsconfig.ts
57
+ function mergeTsconfig(base, options) {
58
+ const out = structuredClone(base);
59
+ if (!out.extends) return out;
60
+ out.compilerOptions ??= {};
61
+ if ([
62
+ "vite",
63
+ "rollup",
64
+ "tsdown",
65
+ "tsup"
66
+ ].includes(options.bundler)) out.compilerOptions.moduleResolution = "bundler";
67
+ else out.compilerOptions.moduleResolution = "nodenext";
68
+ const isAppEnv = out.extends.includes("react") || out.extends.includes("vue") || out.extends.includes("web");
69
+ if (options.bundler === "vite" && isAppEnv) {
70
+ const types = Array.isArray(out.compilerOptions.types) ? out.compilerOptions.types : [];
71
+ out.compilerOptions.types = Array.from(new Set([...types, "vite/client"]));
72
+ }
73
+ return out;
74
+ }
75
+ //#endregion
76
+ //#region src/cli/generate/write-with-confirm.ts
77
+ async function writeWithConfirm(file, content, options = {}) {
78
+ if (!existsSync(file) || options.force) {
79
+ writeFileSync(file, content);
80
+ return "written";
81
+ }
82
+ if (!await confirm({
83
+ message: `File ${file} exists, overwrite?`,
84
+ initialValue: false
85
+ })) return "skipped";
86
+ writeFileSync(file, content);
87
+ return "written";
88
+ }
89
+ //#endregion
90
+ //#region src/cli/generate/generate-files.ts
91
+ async function generateFiles(plan) {
92
+ const written = [];
93
+ const skipped = [];
94
+ for (const f of plan.files) {
95
+ const merged = mergeTsconfig(f.shape ? f.shape : { extends: f.extends }, { bundler: plan.bundler });
96
+ if (await writeWithConfirm(f.path, `${JSON.stringify(merged, null, 2)}\n`, { force: plan.force }) === "written") written.push(f.path);
97
+ else skipped.push(f.path);
98
+ }
99
+ return {
100
+ written,
101
+ skipped
102
+ };
103
+ }
104
+ //#endregion
105
+ //#region src/cli/install/choose-pm.ts
106
+ function choosePackageManager(cwd = process.cwd()) {
107
+ if (existsSync(`${cwd}/pnpm-lock.yaml`)) return "pnpm";
108
+ if (existsSync(`${cwd}/yarn.lock`)) return "yarn";
109
+ if (existsSync(`${cwd}/package-lock.json`)) return "npm";
110
+ if (existsSync(`${cwd}/bun.lockb`) || existsSync(`${cwd}/bun.lock`)) return "bun";
111
+ return "npm";
112
+ }
113
+ //#endregion
114
+ //#region src/cli/install/install-deps.ts
115
+ async function installDeps(plan) {
116
+ const pm = choosePackageManager();
117
+ if (plan.deps.length === 0) return;
118
+ await execaCommand(pm === "pnpm" ? `pnpm add -D ${plan.deps.join(" ")}` : pm === "yarn" ? `yarn add -D ${plan.deps.join(" ")}` : pm === "bun" ? `bun add -d ${plan.deps.join(" ")}` : `npm i -D ${plan.deps.join(" ")}`, { stdio: "inherit" });
119
+ }
120
+ //#endregion
121
+ //#region src/cli/plan/resolve-plan.ts
122
+ function resolvePlan(input) {
123
+ const preset = resolvePreset(input.stack, input.shape);
124
+ const testPreset = input.test === "vitest" ? input.stack === "node" ? "vitest.node.json" : "vitest.web.json" : void 0;
125
+ const files = [];
126
+ if (input.stack === "node") files.push({
127
+ path: "tsconfig.json",
128
+ extends: `@tofrankie/tsconfig/${preset}`
129
+ });
130
+ else {
131
+ const rootShape = {
132
+ files: [],
133
+ references: [{ path: "./tsconfig.app.json" }, { path: "./tsconfig.node.json" }]
134
+ };
135
+ if (testPreset) rootShape.references.push({ path: "./tsconfig.test.json" });
136
+ files.push({
137
+ path: "tsconfig.json",
138
+ shape: rootShape
139
+ }, {
140
+ path: "tsconfig.app.json",
141
+ extends: `@tofrankie/tsconfig/${preset}`
142
+ }, {
143
+ path: "tsconfig.node.json",
144
+ extends: "@tofrankie/tsconfig/node.app.json"
145
+ });
146
+ }
147
+ if (testPreset) files.push({
148
+ path: "tsconfig.test.json",
149
+ extends: `@tofrankie/tsconfig/${testPreset}`
150
+ });
151
+ const deps = ["typescript", "@tofrankie/tsconfig"];
152
+ if (input.test === "vitest") deps.push("vitest", "@types/node");
153
+ if (input.bundler === "vite") deps.push("vite");
154
+ return {
155
+ preset,
156
+ testPreset,
157
+ bundler: input.bundler,
158
+ files,
159
+ deps: Array.from(new Set(deps)),
160
+ force: input.force
161
+ };
162
+ }
163
+ function resolvePreset(stack, shape) {
164
+ if (stack === "react") return shape === "lib" ? "react.lib.json" : "react.app.json";
165
+ if (stack === "vue") return shape === "lib" ? "vue.lib.json" : "vue.app.json";
166
+ if (stack === "node") return shape === "lib" ? "node.lib.json" : "node.app.json";
167
+ return "web.app.json";
168
+ }
169
+ //#endregion
170
+ //#region src/cli/detect/detect-project.ts
171
+ function detectProject(cwd = process.cwd()) {
172
+ const pkgPath = `${cwd}/package.json`;
173
+ if (!existsSync(pkgPath)) return {
174
+ hasReact: false,
175
+ hasVue: false,
176
+ hasVite: false,
177
+ hasRollup: false,
178
+ hasTsdown: false,
179
+ hasTsup: false
180
+ };
181
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
182
+ const deps = {
183
+ ...pkg.dependencies ?? {},
184
+ ...pkg.devDependencies ?? {}
185
+ };
186
+ return {
187
+ hasReact: !!deps.react,
188
+ hasVue: !!deps.vue,
189
+ hasVite: !!deps.vite,
190
+ hasRollup: !!deps.rollup,
191
+ hasTsdown: !!deps.tsdown,
192
+ hasTsup: !!deps.tsup
193
+ };
194
+ }
195
+ //#endregion
196
+ //#region src/cli/prompts/index.ts
197
+ function asStack(value) {
198
+ return value;
199
+ }
200
+ function asShape(value) {
201
+ return value;
202
+ }
203
+ function asTestRunner(value) {
204
+ return value;
205
+ }
206
+ function asBundler(value) {
207
+ return value;
208
+ }
209
+ async function runPrompts(args) {
210
+ const detected = detectProject();
211
+ const detectedStack = args.stack ?? (detected.hasReact ? "react" : detected.hasVue ? "vue" : "node");
212
+ const detectedBundler = args.bundler ?? (detected.hasVite ? "vite" : detected.hasRollup ? "rollup" : detected.hasTsdown ? "tsdown" : detected.hasTsup ? "tsup" : "none");
213
+ if (args.yes) return {
214
+ stack: detectedStack,
215
+ shape: args.shape ?? "app",
216
+ test: args.test ?? "none",
217
+ bundler: detectedBundler,
218
+ yes: !!args.yes,
219
+ install: !!args.install,
220
+ force: !!args.force
221
+ };
222
+ const stack = args.stack ?? await select({
223
+ message: "Select stack",
224
+ options: [
225
+ {
226
+ value: "react",
227
+ label: "React"
228
+ },
229
+ {
230
+ value: "vue",
231
+ label: "Vue"
232
+ },
233
+ {
234
+ value: "node",
235
+ label: "Node"
236
+ },
237
+ {
238
+ value: "web",
239
+ label: "Web"
240
+ }
241
+ ],
242
+ initialValue: detectedStack
243
+ });
244
+ if (isCancel(stack)) process.exit(1);
245
+ const shape = args.shape ?? await select({
246
+ message: "Select shape",
247
+ options: [{
248
+ value: "app",
249
+ label: "App"
250
+ }, {
251
+ value: "lib",
252
+ label: "Lib"
253
+ }]
254
+ });
255
+ if (isCancel(shape)) process.exit(1);
256
+ const test = args.test ?? await select({
257
+ message: "Select test",
258
+ options: [
259
+ {
260
+ value: "vitest",
261
+ label: "Vitest"
262
+ },
263
+ {
264
+ value: "none",
265
+ label: "None"
266
+ },
267
+ {
268
+ value: "other",
269
+ label: "Other (same as none)"
270
+ }
271
+ ]
272
+ });
273
+ if (isCancel(test)) process.exit(1);
274
+ const bundler = args.bundler ?? await select({
275
+ message: "Select bundler",
276
+ options: [
277
+ {
278
+ value: "vite",
279
+ label: "Vite"
280
+ },
281
+ {
282
+ value: "rollup",
283
+ label: "Rollup"
284
+ },
285
+ {
286
+ value: "tsdown",
287
+ label: "Tsdown"
288
+ },
289
+ {
290
+ value: "tsup",
291
+ label: "Tsup"
292
+ },
293
+ {
294
+ value: "none",
295
+ label: "None"
296
+ },
297
+ {
298
+ value: "other",
299
+ label: "Other"
300
+ }
301
+ ],
302
+ initialValue: detectedBundler
303
+ });
304
+ if (isCancel(bundler)) process.exit(1);
305
+ const install = args.install ?? await confirm({
306
+ message: "Install required dependencies now?",
307
+ initialValue: true
308
+ });
309
+ if (isCancel(install)) process.exit(1);
310
+ return {
311
+ stack: asStack(stack),
312
+ shape: asShape(shape),
313
+ test: asTestRunner(test),
314
+ bundler: asBundler(bundler),
315
+ yes: !!args.yes,
316
+ install: !!install,
317
+ force: !!args.force
318
+ };
319
+ }
320
+ //#endregion
321
+ //#region src/cli/index.ts
322
+ async function main() {
323
+ const promptResult = await runPrompts(parseArgs(process.argv));
324
+ const plan = resolvePlan(promptResult);
325
+ const result = await generateFiles(plan);
326
+ if (promptResult.install) await installDeps(plan);
327
+ outro(`done: written ${result.written.length}, skipped ${result.skipped.length}`);
328
+ }
329
+ //#endregion
330
+ export { main };
@@ -1,22 +1,22 @@
1
1
  {
2
2
  "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2023"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
3
7
  "strict": true,
4
- "allowUnusedLabels": false,
5
8
  "allowUnreachableCode": false,
6
- "exactOptionalPropertyTypes": true,
9
+ "allowUnusedLabels": false,
10
+ "exactOptionalPropertyTypes": false,
7
11
  "noFallthroughCasesInSwitch": true,
8
12
  "noImplicitOverride": true,
9
13
  "noImplicitReturns": true,
10
- "noPropertyAccessFromIndexSignature": true,
11
- "noUncheckedIndexedAccess": true,
14
+ "noPropertyAccessFromIndexSignature": false,
15
+ "noUncheckedIndexedAccess": false,
12
16
  "noUnusedLocals": true,
13
17
  "noUnusedParameters": true,
14
-
15
- "isolatedModules": true,
16
-
17
18
  "esModuleInterop": true,
19
+ "isolatedModules": true,
18
20
  "skipLibCheck": true
19
- },
20
- "$schema": "https://www.schemastore.org/tsconfig",
21
- "_version": "2.0.0"
21
+ }
22
22
  }
package/node.lib.json CHANGED
@@ -1,3 +1,26 @@
1
1
  {
2
- "extends": ["./node.json", "./lib.json"]
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2023"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "strict": true,
8
+ "allowUnreachableCode": false,
9
+ "allowUnusedLabels": false,
10
+ "exactOptionalPropertyTypes": false,
11
+ "noFallthroughCasesInSwitch": true,
12
+ "noImplicitOverride": true,
13
+ "noImplicitReturns": true,
14
+ "noPropertyAccessFromIndexSignature": false,
15
+ "noUncheckedIndexedAccess": false,
16
+ "noUnusedLocals": true,
17
+ "noUnusedParameters": true,
18
+ "declaration": true,
19
+ "declarationMap": true,
20
+ "emitDeclarationOnly": true,
21
+ "noEmit": false,
22
+ "esModuleInterop": true,
23
+ "isolatedModules": true,
24
+ "skipLibCheck": true
25
+ }
3
26
  }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@tofrankie/tsconfig",
3
3
  "type": "module",
4
- "version": "0.0.4",
5
- "description": "Shared tsconfig configuration",
4
+ "version": "0.1.0",
5
+ "description": "Shared TypeScript configuration",
6
6
  "author": "Frankie <1426203851@qq.com>",
7
7
  "license": "MIT",
8
8
  "homepage": "https://github.com/tofrankie/config/tree/main/packages/tsconfig",
@@ -14,26 +14,32 @@
14
14
  "bugs": "https://github.com/tofrankie/config/issues",
15
15
  "keywords": [
16
16
  "tsconfig",
17
+ "typescript",
18
+ "typescript-config",
19
+ "node",
20
+ "react",
21
+ "tsdown",
22
+ "vite",
23
+ "vitest",
24
+ "vue",
17
25
  "tofrankie"
18
26
  ],
27
+ "bin": {
28
+ "tsconfig": "./dist/index.mjs"
29
+ },
19
30
  "files": [
20
31
  "CHANGELOG.md",
21
- "base",
22
- "dom.json",
23
- "lib.json",
24
- "node.json",
32
+ "dist",
33
+ "node.app.json",
25
34
  "node.lib.json",
26
- "node.lib.tsdown.json",
27
- "react.json",
35
+ "react.app.json",
28
36
  "react.lib.json",
29
- "react.lib.vite.json",
30
- "react.vite.json",
31
37
  "strict.json",
32
- "vitest.json",
33
- "vue.json",
38
+ "vitest.node.json",
39
+ "vitest.web.json",
40
+ "vue.app.json",
34
41
  "vue.lib.json",
35
- "vue.lib.vite.json",
36
- "vue.vite.json"
42
+ "web.app.json"
37
43
  ],
38
44
  "engines": {
39
45
  "node": "^20.0.0 || ^22.0.0 || ^24.0.0"
@@ -49,20 +55,33 @@
49
55
  "publishConfig": {
50
56
  "access": "public"
51
57
  },
58
+ "dependencies": {
59
+ "@clack/prompts": "^0.11.0",
60
+ "ansis": "^4.2.0",
61
+ "commander": "^14.0.2",
62
+ "execa": "^9.6.0",
63
+ "tsconfck": "^3.1.6"
64
+ },
52
65
  "devDependencies": {
53
66
  "@tsconfig/node20": "^20.1.9",
54
67
  "@tsconfig/strictest": "^2.0.8",
55
68
  "@tsconfig/vite-react": "^7.0.2",
56
69
  "@vue/tsconfig": "^0.9.0",
70
+ "eslint-plugin-jsonc": "^3.1.2",
57
71
  "jsonc-parser": "^3.3.1",
58
- "publint": "^0.3.18",
72
+ "publint": "^0.3.21",
59
73
  "tsx": "^4.21.0",
60
- "typescript": "^5.9.3",
61
- "vitest": "^4.1.2"
74
+ "typescript": "^5.9.3"
62
75
  },
63
76
  "scripts": {
64
- "build": "tsx ./scripts/build.ts",
65
- "test": "pnpm build && vitest run",
77
+ "build": "run-s build:tsconfig build:cli json:lint",
78
+ "build:tsconfig": "node ./scripts/build-tsconfig.ts",
79
+ "build:cli": "tsdown",
80
+ "typecheck": "tsc --noEmit",
81
+ "json:lint": "run-s json:sort json:sort json:sort json:format",
82
+ "json:sort": "eslint --fix --config ./eslint.json.js >/dev/null 2>&1 || true",
83
+ "json:format": "prettier ./**/*.json --write --log-level silent",
84
+ "test": "vitest run",
66
85
  "publint": "publint"
67
86
  }
68
87
  }
package/react.app.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "jsx": "react-jsx",
5
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "moduleResolution": "bundler",
8
+ "strict": true,
9
+ "allowUnreachableCode": false,
10
+ "allowUnusedLabels": false,
11
+ "exactOptionalPropertyTypes": false,
12
+ "noFallthroughCasesInSwitch": true,
13
+ "noImplicitOverride": true,
14
+ "noImplicitReturns": true,
15
+ "noPropertyAccessFromIndexSignature": false,
16
+ "noUncheckedIndexedAccess": false,
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "noEmit": true,
20
+ "esModuleInterop": true,
21
+ "isolatedModules": true,
22
+ "skipLibCheck": true
23
+ }
24
+ }
package/react.lib.json CHANGED
@@ -1,6 +1,27 @@
1
1
  {
2
- "extends": ["./dom.json", "./lib.json"],
3
2
  "compilerOptions": {
4
- "jsx": "react-jsx"
3
+ "target": "ES2022",
4
+ "jsx": "react-jsx",
5
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "moduleResolution": "bundler",
8
+ "strict": true,
9
+ "allowUnreachableCode": false,
10
+ "allowUnusedLabels": false,
11
+ "exactOptionalPropertyTypes": false,
12
+ "noFallthroughCasesInSwitch": true,
13
+ "noImplicitOverride": true,
14
+ "noImplicitReturns": true,
15
+ "noPropertyAccessFromIndexSignature": false,
16
+ "noUncheckedIndexedAccess": false,
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "declaration": true,
20
+ "declarationMap": true,
21
+ "emitDeclarationOnly": true,
22
+ "noEmit": false,
23
+ "esModuleInterop": true,
24
+ "isolatedModules": true,
25
+ "skipLibCheck": true
5
26
  }
6
27
  }
package/strict.json CHANGED
@@ -1,19 +1,18 @@
1
1
  {
2
- "extends": "./base/tsconfig/strictest/tsconfig.json",
3
2
  "compilerOptions": {
4
- // This option is part of the recommended tsconfig as of TS 5.9.
5
- // Commented out for now. It's hard to land in the current ecosystem.
6
- // Needs more consensus before moving forward.
3
+ "strict": true,
4
+ "allowUnreachableCode": false,
5
+ "allowUnusedLabels": false,
7
6
  "exactOptionalPropertyTypes": false,
8
-
9
- // See <https://www.semver-ts.org/formal-spec/5-compiler-considerations.html#strictness>
10
- // Part of the recommended tsconfig as of TS 5.9.
11
- // Flags starting with `no` are likely to have false positives,
12
- // So they are not suitable for existing codebases, but are recommended for new codebases,
13
- // as well as libraries that need to be more strict about their types.
14
- // See also <https://github.com/vuejs/tsconfig/issues/38#issuecomment-3524621112> for more discussion.
7
+ "noFallthroughCasesInSwitch": true,
8
+ "noImplicitOverride": true,
9
+ "noImplicitReturns": true,
10
+ "noPropertyAccessFromIndexSignature": false,
15
11
  "noUncheckedIndexedAccess": false,
16
-
17
- "noPropertyAccessFromIndexSignature": false
12
+ "noUnusedLocals": true,
13
+ "noUnusedParameters": true,
14
+ "esModuleInterop": true,
15
+ "isolatedModules": true,
16
+ "skipLibCheck": true
18
17
  }
19
18
  }
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2023"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "types": ["vitest/globals", "node"],
8
+ "strict": true,
9
+ "allowUnreachableCode": false,
10
+ "allowUnusedLabels": false,
11
+ "exactOptionalPropertyTypes": false,
12
+ "noFallthroughCasesInSwitch": true,
13
+ "noImplicitOverride": true,
14
+ "noImplicitReturns": true,
15
+ "noPropertyAccessFromIndexSignature": false,
16
+ "noUncheckedIndexedAccess": false,
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "noEmit": true,
20
+ "esModuleInterop": true,
21
+ "isolatedModules": true,
22
+ "skipLibCheck": true
23
+ }
24
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "jsx": "react-jsx",
5
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "moduleResolution": "bundler",
8
+ "types": ["vitest/globals", "node"],
9
+ "strict": true,
10
+ "allowUnreachableCode": false,
11
+ "allowUnusedLabels": false,
12
+ "exactOptionalPropertyTypes": false,
13
+ "noFallthroughCasesInSwitch": true,
14
+ "noImplicitOverride": true,
15
+ "noImplicitReturns": true,
16
+ "noPropertyAccessFromIndexSignature": false,
17
+ "noUncheckedIndexedAccess": false,
18
+ "noUnusedLocals": true,
19
+ "noUnusedParameters": true,
20
+ "noEmit": true,
21
+ "esModuleInterop": true,
22
+ "isolatedModules": true,
23
+ "skipLibCheck": true
24
+ }
25
+ }
package/vue.app.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "jsx": "preserve",
5
+ "jsxImportSource": "vue",
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "moduleDetection": "force",
8
+ "useDefineForClassFields": true,
9
+ "libReplacement": false,
10
+ "module": "ESNext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "types": [],
14
+ "allowImportingTsExtensions": true,
15
+ "strict": true,
16
+ "allowUnreachableCode": false,
17
+ "allowUnusedLabels": false,
18
+ "exactOptionalPropertyTypes": false,
19
+ "noFallthroughCasesInSwitch": true,
20
+ "noImplicitOverride": true,
21
+ "noImplicitReturns": true,
22
+ "noImplicitThis": true,
23
+ "noPropertyAccessFromIndexSignature": false,
24
+ "noUncheckedIndexedAccess": false,
25
+ "noUnusedLocals": true,
26
+ "noUnusedParameters": true,
27
+ "noEmit": true,
28
+ "esModuleInterop": true,
29
+ "forceConsistentCasingInFileNames": true,
30
+ "isolatedModules": true,
31
+ "verbatimModuleSyntax": true,
32
+ "skipLibCheck": true
33
+ }
34
+ }
package/vue.lib.json CHANGED
@@ -1,3 +1,37 @@
1
1
  {
2
- "extends": ["./dom.json", "./lib.json", "./base/vue/tsconfig/tsconfig.lib.json"]
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "jsx": "preserve",
5
+ "jsxImportSource": "vue",
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "moduleDetection": "force",
8
+ "useDefineForClassFields": true,
9
+ "libReplacement": false,
10
+ "module": "ESNext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "types": [],
14
+ "allowImportingTsExtensions": true,
15
+ "strict": true,
16
+ "allowUnreachableCode": false,
17
+ "allowUnusedLabels": false,
18
+ "exactOptionalPropertyTypes": false,
19
+ "noFallthroughCasesInSwitch": true,
20
+ "noImplicitOverride": true,
21
+ "noImplicitReturns": true,
22
+ "noImplicitThis": true,
23
+ "noPropertyAccessFromIndexSignature": false,
24
+ "noUncheckedIndexedAccess": true,
25
+ "noUnusedLocals": true,
26
+ "noUnusedParameters": true,
27
+ "declaration": true,
28
+ "declarationMap": true,
29
+ "emitDeclarationOnly": true,
30
+ "noEmit": false,
31
+ "esModuleInterop": true,
32
+ "forceConsistentCasingInFileNames": true,
33
+ "isolatedModules": true,
34
+ "verbatimModuleSyntax": true,
35
+ "skipLibCheck": false
36
+ }
3
37
  }
package/web.app.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "strict": true,
8
+ "allowUnreachableCode": false,
9
+ "allowUnusedLabels": false,
10
+ "exactOptionalPropertyTypes": false,
11
+ "noFallthroughCasesInSwitch": true,
12
+ "noImplicitOverride": true,
13
+ "noImplicitReturns": true,
14
+ "noPropertyAccessFromIndexSignature": false,
15
+ "noUncheckedIndexedAccess": false,
16
+ "noUnusedLocals": true,
17
+ "noUnusedParameters": true,
18
+ "noEmit": true,
19
+ "esModuleInterop": true,
20
+ "isolatedModules": true,
21
+ "skipLibCheck": true
22
+ }
23
+ }
@@ -1,15 +0,0 @@
1
- {
2
- "$schema": "https://www.schemastore.org/tsconfig",
3
- "_version": "20.1.0",
4
-
5
- "compilerOptions": {
6
- "lib": ["es2023"],
7
- "module": "nodenext",
8
- "target": "es2022",
9
-
10
- "strict": true,
11
- "esModuleInterop": true,
12
- "skipLibCheck": true,
13
- "moduleResolution": "node16"
14
- }
15
- }
@@ -1,29 +0,0 @@
1
- {
2
- "$schema": "https://www.schemastore.org/tsconfig",
3
- "_version": "7.0.0",
4
-
5
- "compilerOptions": {
6
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
7
- "target": "ES2022",
8
- "useDefineForClassFields": true,
9
- "lib": ["ES2022", "DOM", "DOM.Iterable"],
10
- "module": "ESNext",
11
- "skipLibCheck": true,
12
-
13
- /* Bundler mode */
14
- "moduleResolution": "bundler",
15
- "allowImportingTsExtensions": true,
16
- "verbatimModuleSyntax": true,
17
- "moduleDetection": "force",
18
- "noEmit": true,
19
- "jsx": "react-jsx",
20
-
21
- /* Linting */
22
- "strict": true,
23
- "noUnusedLocals": true,
24
- "noUnusedParameters": true,
25
- "erasableSyntaxOnly": true,
26
- "noFallthroughCasesInSwitch": true,
27
- "noUncheckedSideEffectImports": true
28
- }
29
- }
@@ -1,24 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "lib": [
5
- // Target ES2022 to align with Vite.
6
- // <https://vite.dev/config/build-options.html#build-target>
7
- // Support for newer versions of language built-ins are
8
- // left for the users to include, because that would require:
9
- // - either the project doesn't need to support older versions of browsers;
10
- // - or the project has properly included the necessary polyfills.
11
- "ES2022",
12
-
13
- "DOM",
14
- "DOM.Iterable"
15
-
16
- // No `ScriptHost` because Vue 3 dropped support for IE
17
- ],
18
-
19
- // Set to empty to avoid accidental inclusion of unwanted types,
20
- // e.g. the Node.js types that would pollute the global scope.
21
- // It's the default value in TS 6+, too.
22
- "types": []
23
- }
24
- }
@@ -1,65 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- // Most non-library projects don't need to emit declarations.
4
- // So we add this option by default to make the config more friendly to most users.
5
- "noEmit": true,
6
-
7
- // As long as you are using a build tool, we recommend you to author and ship in ES modules.
8
- // Even if you are targeting Node.js, because
9
- // - `CommonJS` is too outdated
10
- // - the ecosystem hasn't fully caught up with `Node16`/`NodeNext`
11
- // This recommendation includes environments like Vitest, Vite Config File, Vite SSR, etc.
12
- "module": "ESNext",
13
-
14
- // We expect users to use bundlers.
15
- // So here we enable some resolution features that are only available in bundlers.
16
- "moduleResolution": "bundler",
17
- "resolveJsonModule": true,
18
- "allowImportingTsExtensions": true,
19
- // Even files without `import` or `export` are treated as modules.
20
- // It helps to avoid mysterious errors such as `Cannot redeclare block-scoped variable 'name`.
21
- // https://www.totaltypescript.com/cannot-redeclare-block-scoped-variable#solution-3-your-module-isnt-a-module
22
- "moduleDetection": "force",
23
-
24
- // Required in Vue projects
25
- "jsx": "preserve",
26
- "jsxImportSource": "vue",
27
-
28
- // `"noImplicitThis": true` is part of `strict`
29
- // Added again here in case some users decide to disable `strict`.
30
- // This enables stricter inference for data properties on `this`.
31
- "noImplicitThis": true,
32
- // Strict mode is on by default in TS 6+
33
- "strict": true,
34
-
35
- // This option is part of the recommended tsconfig as of TS 5.9.
36
- // Commented out for now. It's hard to land in the current ecosystem.
37
- // Needs more consensus before moving forward.
38
- // "exactOptionalPropertyTypes": true,
39
-
40
- // <https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#verbatimmodulesyntax>
41
- // Any imports or exports without a type modifier are left around. This is important for `<script setup>`.
42
- // Anything that uses the type modifier is dropped entirely.
43
- "verbatimModuleSyntax": true,
44
-
45
- // A few notes:
46
- // - Vue 3 supports ES2016+
47
- // - For Vite, the actual compilation target is determined by the
48
- // `build.target` option in the Vite config.
49
- // So don't change the `target` field here. It has to be
50
- // at least `ES2020` for dynamic `import()`s and `import.meta` to work correctly.
51
- // - If you are not using Vite, feel free to overwrite the `target` field.
52
- "target": "ESNext",
53
- // For spec compliance.
54
- // `true` by default if the `target` is `ES2020` or higher.
55
- // Explicitly set it to `true` here in case some users want to overwrite the `target`.
56
- "useDefineForClassFields": true,
57
-
58
- // Recommended
59
- "esModuleInterop": true,
60
- "forceConsistentCasingInFileNames": true,
61
- "libReplacement": false,
62
- // See <https://github.com/vuejs/vue-cli/pull/5688>
63
- "skipLibCheck": true,
64
- }
65
- }
@@ -1,21 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- // Emit declaration files for the library.
4
- "noEmit": false,
5
- "declaration": true,
6
- "emitDeclarationOnly": true,
7
-
8
- // Libraries generally require more strict type accuracy.
9
- // For example, its types must be compatible with the Vue types.
10
- // So we don't want to skip the type checking of its dependencies.
11
- "skipLibCheck": false,
12
-
13
- // See <https://www.semver-ts.org/formal-spec/5-compiler-considerations.html#strictness>
14
- // Part of the recommended tsconfig as of TS 5.9.
15
- // Flags starting with `no` are likely to have false positives,
16
- // So they are not suitable for existing codebases, but are recommended for new codebases,
17
- // as well as libraries that need to be more strict about their types.
18
- // See also <https://github.com/vuejs/tsconfig/issues/38#issuecomment-3524621112> for more discussion.
19
- "noUncheckedIndexedAccess": true,
20
- }
21
- }
package/dom.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "./strict.json",
3
- "compilerOptions": {
4
- "lib": ["ES2022", "DOM", "DOM.Iterable"],
5
- "target": "ES2022",
6
- "module": "ESNext",
7
- "moduleResolution": "bundler"
8
- }
9
- }
package/lib.json DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "extends": "./strict.json",
3
- "compilerOptions": {
4
- "declaration": true,
5
- "declarationMap": true
6
- }
7
- }
package/node.json DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "extends": ["./strict.json", "./base/tsconfig/node20/tsconfig.json"]
3
- }
@@ -1,9 +0,0 @@
1
- {
2
- "extends": ["./node.json", "./lib.json"],
3
- "compilerOptions": {
4
- "noEmit": true,
5
- "declarationMap": false,
6
- "module": "ESNext",
7
- "moduleResolution": "bundler"
8
- }
9
- }
package/react.json DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "extends": "./dom.json",
3
- "compilerOptions": {
4
- "jsx": "react-jsx"
5
- }
6
- }
@@ -1,6 +0,0 @@
1
- {
2
- "extends": "./react.lib.json",
3
- "compilerOptions": {
4
- "types": ["vite/client"]
5
- }
6
- }
package/react.vite.json DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "extends": ["./react.json", "./base/tsconfig/vite-react/tsconfig.json"],
3
- "compilerOptions": {
4
- "noEmit": true,
5
- "types": ["vite/client"]
6
- }
7
- }
package/vitest.json DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "extends": "./node.json",
3
- "compilerOptions": {
4
- "types": ["node", "vitest/globals"],
5
- "noEmit": true
6
- }
7
- }
package/vue.json DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "extends": ["./dom.json", "./base/vue/tsconfig/tsconfig.dom.json"]
3
- }
package/vue.lib.vite.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "./vue.lib.json",
3
- "compilerOptions": {
4
- "noEmit": true,
5
- "types": ["vite/client"],
6
- "module": "ESNext",
7
- "moduleResolution": "bundler"
8
- }
9
- }
package/vue.vite.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "./vue.json",
3
- "compilerOptions": {
4
- "noEmit": true,
5
- "types": ["vite/client"],
6
- "module": "ESNext",
7
- "moduleResolution": "bundler"
8
- }
9
- }