@williamthorsen/tsconfig 0.4.0 → 0.6.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.
@@ -1,6 +1,6 @@
1
1
  /** @noformat — @generated. Do not edit. Compiled by rdy. */
2
2
  /* eslint-disable */
3
- export const __readyupVersion = "0.25.0";
3
+ export const __readyupVersion = "0.33.0";
4
4
 
5
5
 
6
6
  // .readyup/kits/default.ts
@@ -76,7 +76,7 @@ import { isDeepStrictEqual } from "node:util";
76
76
  function findRedundantOptions(entries, baseIndex) {
77
77
  const baseOptions = entries[baseIndex]?.compilerOptions;
78
78
  if (baseOptions === void 0) return [];
79
- const exempt = dependencyDeclaredKeys(entries, baseIndex);
79
+ const exempt = collectDependencyDeclaredKeys(entries, baseIndex);
80
80
  const redundant = [];
81
81
  for (const entry of entries.slice(0, baseIndex)) {
82
82
  if (!isConsumerOwnedConfig(entry.path)) continue;
@@ -87,7 +87,7 @@ function findRedundantOptions(entries, baseIndex) {
87
87
  }
88
88
  return redundant;
89
89
  }
90
- function dependencyDeclaredKeys(entries, baseIndex) {
90
+ function collectDependencyDeclaredKeys(entries, baseIndex) {
91
91
  const keys = /* @__PURE__ */ new Set();
92
92
  for (const [index, entry] of entries.entries()) {
93
93
  if (index === baseIndex || isConsumerOwnedConfig(entry.path)) continue;
@@ -107,7 +107,7 @@ function classifyNodeEsYear(major, esYearForMajor) {
107
107
  const lowestEsYear = esYearForMajor(lowestKnown);
108
108
  return lowestEsYear === void 0 ? { kind: "unknown" } : { esYear: lowestEsYear, kind: "under" };
109
109
  }
110
- function lowestNodeMajor(floors) {
110
+ function findLowestNodeMajor(floors) {
111
111
  const majors = floors.flatMap((floor) => {
112
112
  const major = readNodeMajor(floor);
113
113
  return major === void 0 ? [] : [major];
@@ -175,9 +175,6 @@ var default_default = defineRdyKit({
175
175
  }
176
176
  ]
177
177
  });
178
- function adoptedTsconfigs() {
179
- return classifyAdoptions().filter((adoption) => adoption.kind === "adopted");
180
- }
181
178
  function classifyAdoptions() {
182
179
  cache.adoptions ??= findTsconfigs().map((path) => classifyTsconfig(path));
183
180
  return cache.adoptions;
@@ -188,28 +185,14 @@ function classifyTsconfig(path) {
188
185
  const classification = classifyChain(chain);
189
186
  return classification.kind === "adopted" ? { baseIndex: classification.baseIndex, chain, kind: "adopted", path } : { kind: classification.kind, path };
190
187
  }
191
- function declaredNodeFloors() {
192
- const engineFloors = tsconfigSearchDirs().flatMap((dir) => {
193
- const manifest = readJsonFile(dirPath(dir, "package.json"));
194
- if (manifest === void 0) return [];
195
- const floor = readEnginesNodeFloor(manifest);
196
- return floor.kind === "found" ? [floor.floor] : [];
197
- });
198
- if (engineFloors.length > 0) return engineFloors;
199
- const toolVersionsFloor = readToolVersionsNode();
200
- return toolVersionsFloor === void 0 ? [] : [toolVersionsFloor];
201
- }
202
188
  function dedupe(values) {
203
189
  return [...new Set(values)];
204
190
  }
205
- function dirPath(dir, basename) {
206
- return dir === "." ? basename : `${dir}/${basename}`;
207
- }
208
191
  function everyEsYearMatchesTheBase() {
209
192
  const baseEsYear = readBaseEsYear();
210
193
  if (baseEsYear === void 0) return true;
211
194
  const offenders = [];
212
- for (const adoption of adoptedTsconfigs()) {
195
+ for (const adoption of listAdoptedTsconfigs()) {
213
196
  for (const entry of adoption.chain.entries.slice(0, adoption.baseIndex)) {
214
197
  if (!isConsumerOwnedConfig(entry.path)) continue;
215
198
  const declared = readDeclaredEsYear(entry.compilerOptions);
@@ -226,8 +209,8 @@ function everyTsconfigAdoptsTheBase() {
226
209
  const accountable = classifyAdoptions().filter((adoption) => adoption.kind !== "external-base");
227
210
  const adopted = accountable.filter((adoption) => adoption.kind === "adopted");
228
211
  const progress = { type: "fraction", passedCount: adopted.length, count: accountable.length };
229
- const uninstalled = pathsOfKind(accountable, "uninstalled");
230
- const unadopted = pathsOfKind(accountable, "unadopted");
212
+ const uninstalled = listPathsOfKind(accountable, "uninstalled");
213
+ const unadopted = listPathsOfKind(accountable, "unadopted");
231
214
  if (uninstalled.length === 0 && unadopted.length === 0) return { ok: true, progress };
232
215
  const details = [
233
216
  uninstalled.length > 0 ? `${PACKAGE_NAME} is named but not installed in: ${uninstalled.join(", ")}` : void 0,
@@ -236,7 +219,7 @@ function everyTsconfigAdoptsTheBase() {
236
219
  return { ok: false, detail: details.join("; "), progress };
237
220
  }
238
221
  function findTsconfigs() {
239
- return tsconfigSearchDirs().map((dir) => dirPath(dir, "tsconfig.json")).filter((path) => fileExists(path));
222
+ return listTsconfigSearchDirs().map((dir) => resolveDirPath(dir, "tsconfig.json")).filter((path) => fileExists(path));
240
223
  }
241
224
  function judgeNodeFloor() {
242
225
  const baseEsYear = readBaseEsYear();
@@ -255,12 +238,32 @@ function judgeNodeFloor() {
255
238
  kind: "fail"
256
239
  };
257
240
  }
241
+ function listAdoptedTsconfigs() {
242
+ return classifyAdoptions().filter((adoption) => adoption.kind === "adopted");
243
+ }
244
+ function listDeclaredNodeFloors() {
245
+ const engineFloors = listTsconfigSearchDirs().flatMap((dir) => {
246
+ const manifest = readJsonFile(resolveDirPath(dir, "package.json"));
247
+ if (manifest === void 0) return [];
248
+ const floor = readEnginesNodeFloor(manifest);
249
+ return floor.kind === "found" ? [floor.floor] : [];
250
+ });
251
+ if (engineFloors.length > 0) return engineFloors;
252
+ const toolVersionsFloor = readToolVersionsNode();
253
+ return toolVersionsFloor === void 0 ? [] : [toolVersionsFloor];
254
+ }
255
+ function listPathsOfKind(classified, kind) {
256
+ return classified.filter((adoption) => adoption.kind === kind).map((adoption) => adoption.path);
257
+ }
258
+ function listTsconfigSearchDirs() {
259
+ return discoverWorkspaces().map((workspace) => workspace.dir);
260
+ }
258
261
  function nodeFloorSupportsBaseEsYear() {
259
262
  const verdict = judgeNodeFloor();
260
263
  return verdict.kind === "skip" ? true : { ok: verdict.kind === "pass", detail: verdict.detail };
261
264
  }
262
265
  function noRedundantOptions() {
263
- const offenders = adoptedTsconfigs().flatMap(
266
+ const offenders = listAdoptedTsconfigs().flatMap(
264
267
  (adoption) => findRedundantOptions(adoption.chain.entries, adoption.baseIndex).map(
265
268
  (redundant) => `${redundant.path} (${redundant.key})`
266
269
  )
@@ -268,11 +271,8 @@ function noRedundantOptions() {
268
271
  if (offenders.length === 0) return true;
269
272
  return { ok: false, detail: `the base already supplies: ${dedupe(offenders).join(", ")}` };
270
273
  }
271
- function pathsOfKind(classified, kind) {
272
- return classified.filter((adoption) => adoption.kind === kind).map((adoption) => adoption.path);
273
- }
274
274
  function readBaseEsYear() {
275
- for (const adoption of adoptedTsconfigs()) {
275
+ for (const adoption of listAdoptedTsconfigs()) {
276
276
  const baseOptions = adoption.chain.entries[adoption.baseIndex]?.compilerOptions;
277
277
  const esYear = baseOptions === void 0 ? void 0 : readDeclaredEsYear(baseOptions);
278
278
  if (esYear !== void 0) return esYear;
@@ -284,9 +284,12 @@ function readChain(path) {
284
284
  return cache.chains.get(path);
285
285
  }
286
286
  function readNodeEsYear() {
287
- const major = lowestNodeMajor(declaredNodeFloors());
287
+ const major = findLowestNodeMajor(listDeclaredNodeFloors());
288
288
  return major === void 0 ? void 0 : classifyNodeEsYear(major, esYearForNodeMajor);
289
289
  }
290
+ function resolveDirPath(dir, basename) {
291
+ return dir === "." ? basename : `${dir}/${basename}`;
292
+ }
290
293
  function skipUnlessBaseEsYearKnown() {
291
294
  return readBaseEsYear() === void 0 ? NO_BASE_ES_YEAR : false;
292
295
  }
@@ -299,10 +302,6 @@ function skipUnlessSomeTsconfigIsAccountable() {
299
302
  if (classified.length === 0) return "no workspace tsconfig was found";
300
303
  return classified.some((adoption) => adoption.kind !== "external-base") ? false : "every workspace tsconfig extends a base belonging to another package";
301
304
  }
302
- function tsconfigSearchDirs() {
303
- cache.searchDirs ??= [.../* @__PURE__ */ new Set([".", ...discoverWorkspaces().map((workspace) => workspace.dir)])];
304
- return cache.searchDirs;
305
- }
306
305
  export {
307
306
  default_default as default
308
307
  };
@@ -7,12 +7,45 @@
7
7
  "alignment"
8
8
  ],
9
9
  "description": "Adoption and alignment checks for a project consuming @williamthorsen/tsconfig",
10
+ "esbuildVersion": "0.28.2",
11
+ "inputs": [
12
+ {
13
+ "hash": "8988b5dc",
14
+ "kind": "module",
15
+ "path": "kits/default.ts"
16
+ },
17
+ {
18
+ "hash": "7e083072",
19
+ "kind": "module",
20
+ "path": "../src/readiness/base-chain.ts"
21
+ },
22
+ {
23
+ "hash": "86555b6e",
24
+ "kind": "module",
25
+ "path": "../src/readiness/classifyChain.ts"
26
+ },
27
+ {
28
+ "hash": "723d4694",
29
+ "kind": "module",
30
+ "path": "../src/readiness/es-year.ts"
31
+ },
32
+ {
33
+ "hash": "acd6ba2b",
34
+ "kind": "module",
35
+ "path": "../src/readiness/findRedundantOptions.ts"
36
+ },
37
+ {
38
+ "hash": "31b0fbf5",
39
+ "kind": "module",
40
+ "path": "../src/readiness/node-floor.ts"
41
+ }
42
+ ],
10
43
  "name": "default",
11
44
  "path": "kits/default.js",
12
- "readyupVersion": "0.25.0",
45
+ "readyupVersion": "0.33.0",
13
46
  "source": "kits/default.ts",
14
- "sourceHash": "4d0a555c",
15
- "targetHash": "4c59a48d"
47
+ "sourceHash": "8988b5dc",
48
+ "targetHash": "eac2f4f5"
16
49
  }
17
50
  ]
18
51
  }
package/README.md CHANGED
@@ -3,13 +3,17 @@
3
3
  Shared TypeScript base config for Node-only projects. Inlines the settings of [`@tsconfig/strictest`](https://www.npmjs.com/package/@tsconfig/strictest) and adds the Node and build options it leaves out, so a consuming repo declares only what is genuinely its own.
4
4
 
5
5
  <!-- section:release-notes -->
6
- ## Release notes — v0.4.0 (2026-08-09)
6
+ ## Release notes — v0.6.0 (2026-08-26)
7
7
 
8
8
  ### 🎉 Features
9
9
 
10
- - Add a bundled readyup kit that checks tsconfig adoption and alignment (#152)
10
+ - 🚨 **Breaking:** Declare readyup as an optional peer of both kit-shipping packages (#179)
11
11
 
12
- Adds a readiness check to `@williamthorsen/tsconfig` that reports, package by package, whether a repo has adopted the base config and stayed aligned with it. A package that extends a framework's own base is reported as having opted out. The Node floor is the only finding that fails the check; the rest is advisory. The check is run with `pnpm exec rdy run --from npm:@williamthorsen/tsconfig`.
12
+ Declares `readyup` as an optional peer dependency of `@williamthorsen/tsconfig` and `@williamthorsen/eslint-config-typescript`, with a `>=0.33.0` floor. Both packages ship readiness kits that run against the consumer's own readyup, and below 0.33.0 that readyup omits the repo root from a monorepo's workspace list, so the kits check every member package and leave the root unchecked.
13
+
14
+ Both kits now take readyup's workspace list directly, dropping the root literal each carried to compensate for the older behavior.
15
+
16
+ Migration: A consumer running `rdy` against either kit upgrades `readyup` to 0.33.0 or later.
13
17
  <!-- /section:release-notes -->
14
18
 
15
19
  ## Installation
@@ -98,6 +102,8 @@ export default defineRdyConfig({
98
102
  });
99
103
  ```
100
104
 
105
+ The kit needs readyup 0.33.0 or later, declared as an optional peer. Below that, readyup does not report the repo root among a monorepo's workspaces, so the kit checks every member package and leaves the root unchecked.
106
+
101
107
  The kit walks each workspace tsconfig's `extends` chain and reports four things:
102
108
 
103
109
  - **Adoption**: a tsconfig reaching neither this base nor a framework base. A tsconfig naming this base through a specifier that does not resolve is reported separately, as declared but not installed.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@williamthorsen/tsconfig",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Shared TypeScript base config for Node-only projects",
5
5
  "keywords": [
6
6
  "tsconfig",
@@ -17,6 +17,7 @@
17
17
  },
18
18
  "license": "ISC",
19
19
  "author": "William Thorsen <william@thorsen.dev> (https://github.com/williamthorsen)",
20
+ "sideEffects": false,
20
21
  "type": "module",
21
22
  "exports": {
22
23
  "./package.json": "./package.json",
@@ -29,8 +30,16 @@
29
30
  ],
30
31
  "devDependencies": {
31
32
  "@tsconfig/strictest": "2.0.8",
32
- "esbuild": "0.28.1",
33
- "readyup": "0.25.0"
33
+ "esbuild": "0.28.2",
34
+ "readyup": "0.33.0"
35
+ },
36
+ "peerDependencies": {
37
+ "readyup": ">=0.33.0"
38
+ },
39
+ "peerDependenciesMeta": {
40
+ "readyup": {
41
+ "optional": true
42
+ }
34
43
  },
35
44
  "engines": {
36
45
  "node": ">=24"
@@ -31,7 +31,7 @@
31
31
  // Without this, `lib` follows `target` into the `.full` variant, admitting DOM globals.
32
32
  // `ESNext.Disposable` carries the explicit-resource-management declarations; no numbered lib has them.
33
33
  "lib": ["ES2025", "ESNext.Disposable"],
34
- // Default is `ES2022` with `Bundler` resolution — wrong for published Node packages.
34
+ // Default is `ES2022` with `Bundler` resolution: wrong for published Node packages.
35
35
  "module": "NodeNext",
36
36
  // Files with no import or export would otherwise be scripts sharing global scope.
37
37
  "moduleDetection": "force",