@inixiative/config 0.1.0 → 0.3.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/README.md +2 -1
- package/dist/cli.js +106 -14
- package/dist/tsup.js +3 -2
- package/lefthook/base.yml +8 -0
- package/package.json +5 -1
- package/versions.json +12 -7
package/README.md
CHANGED
|
@@ -12,6 +12,7 @@ Shared toolchain for the inixiative ecosystem: tsconfig/biome/tsup presets, a ve
|
|
|
12
12
|
| `@inixiative/config/biome/base.json` | formatter + linter core (single quotes, lineWidth 100, recommended + strictness block) |
|
|
13
13
|
| `@inixiative/config/biome/react.json` | overlay: hook dependency linting |
|
|
14
14
|
| `@inixiative/config/tsup` | `node(options)` / `react(options)` build presets |
|
|
15
|
+
| `@inixiative/config/lefthook/base.yml` | pre-commit hooks: typecheck + biome on staged files |
|
|
15
16
|
|
|
16
17
|
Adoption is three stub files plus the devDependency:
|
|
17
18
|
|
|
@@ -55,7 +56,7 @@ bunx @inixiative/config scan [root]
|
|
|
55
56
|
bunx @inixiative/config train [root]
|
|
56
57
|
```
|
|
57
58
|
|
|
58
|
-
`check` is read-only and exits non-zero on drift — run it in CI after a frozen-lockfile install. It verifies toolchain pins, `"latest"` ranges, `packageManager`/`.bun-version`, legacy `bun.lockb`, a committed (tracked, un-ignored) `bun.lock`, required scripts (`check`/`typecheck`/`lint`/`test`), stub `extends`, presence of this package, and for every ecosystem dependency that the declared range admits the blessed version and the lockfile actually resolves to it (the stale-lockfile class).
|
|
59
|
+
`check` is read-only and exits non-zero on drift — run it in CI after a frozen-lockfile install. It verifies toolchain pins, `"latest"` ranges, `packageManager`/`.bun-version`, legacy `bun.lockb`, a committed (tracked, un-ignored) `bun.lock`, required scripts (`check`/`typecheck`/`lint`/`test`), lefthook (dep + `lefthook.yml` extending the shared hooks + `prepare` script; git repos only), stub `extends`, presence of this package, and for every ecosystem dependency that the declared range admits the blessed version and the lockfile actually resolves to it (the stale-lockfile class).
|
|
59
60
|
|
|
60
61
|
`sync` applies every fix, re-locks via `bun install`, and runs `bun update` on stale ecosystem entries. It refuses to run on a dirty working tree without `--force`. The react preset is inferred from a `react` dependency; override with `--preset`. Missing scripts are filled with defaults; existing script bodies are never touched.
|
|
61
62
|
|
package/dist/cli.js
CHANGED
|
@@ -69,7 +69,7 @@ var tryParseJsonc = (text) => {
|
|
|
69
69
|
}
|
|
70
70
|
};
|
|
71
71
|
var parseRange = (range) => {
|
|
72
|
-
const match = range.match(/^(\^|~|>=)?\s*(\d+)\.(\d+)\.(\d+)
|
|
72
|
+
const match = range.match(/^(\^|~|>=)?\s*(\d+)\.(\d+)\.(\d+)$/);
|
|
73
73
|
if (!match) return null;
|
|
74
74
|
return {
|
|
75
75
|
op: match[1] ?? "=",
|
|
@@ -90,7 +90,9 @@ var admits = (range, version) => {
|
|
|
90
90
|
if (parts.some((p) => p === true)) return true;
|
|
91
91
|
return parts.includes(null) ? null : false;
|
|
92
92
|
}
|
|
93
|
-
const
|
|
93
|
+
const target = range.trim();
|
|
94
|
+
if (version.includes("-")) return target === version ? true : null;
|
|
95
|
+
const parsed = parseRange(target);
|
|
94
96
|
if (!parsed) return null;
|
|
95
97
|
const cmp = compare(version, parsed.version);
|
|
96
98
|
if (parsed.op === "=") return cmp === 0;
|
|
@@ -98,12 +100,22 @@ var admits = (range, version) => {
|
|
|
98
100
|
if (cmp < 0) return false;
|
|
99
101
|
const [major, minor] = parsed.version.split(".").map(Number);
|
|
100
102
|
const [vMajor, vMinor] = version.split(".").map(Number);
|
|
101
|
-
if (parsed.op === "^")
|
|
103
|
+
if (parsed.op === "^") {
|
|
104
|
+
if (major > 0) return vMajor === major;
|
|
105
|
+
if (minor > 0) return vMajor === 0 && vMinor === minor;
|
|
106
|
+
return cmp === 0;
|
|
107
|
+
}
|
|
102
108
|
return vMajor === major && vMinor === minor;
|
|
103
109
|
};
|
|
104
110
|
var lockedVersion = (lockText, name) => {
|
|
105
|
-
const
|
|
106
|
-
|
|
111
|
+
const lock = tryParseJsonc(lockText);
|
|
112
|
+
const packages = lock?.packages;
|
|
113
|
+
if (!packages || typeof packages !== "object") return null;
|
|
114
|
+
const entry = packages[name];
|
|
115
|
+
const spec = Array.isArray(entry) ? entry[0] : null;
|
|
116
|
+
if (typeof spec !== "string" || !spec.startsWith(`${name}@`)) return null;
|
|
117
|
+
const version = spec.slice(name.length + 1);
|
|
118
|
+
return /^\d/.test(version) ? version : null;
|
|
107
119
|
};
|
|
108
120
|
var topoOrder = (root, manifest2) => {
|
|
109
121
|
const repos = discoverRepos(root, manifest2).map((repo) => ({
|
|
@@ -273,15 +285,87 @@ function inspect(dir2, manifest2, presetOverride) {
|
|
|
273
285
|
level: "error",
|
|
274
286
|
message: "bun.lock missing \u2192 run bun install and commit the lockfile"
|
|
275
287
|
});
|
|
276
|
-
} else
|
|
288
|
+
} else {
|
|
289
|
+
const ignoreStatus = spawnSync("git", ["check-ignore", "-q", "bun.lock"], {
|
|
290
|
+
cwd: dir2
|
|
291
|
+
}).status;
|
|
292
|
+
if (ignoreStatus === 0) {
|
|
293
|
+
findings.push({
|
|
294
|
+
level: "error",
|
|
295
|
+
message: "bun.lock is gitignored \u2192 removing the ignore rule; commit the lockfile",
|
|
296
|
+
fix: () => {
|
|
297
|
+
const gitignorePath = join(dir2, ".gitignore");
|
|
298
|
+
if (!existsSync(gitignorePath)) return;
|
|
299
|
+
const kept = readFileSync(gitignorePath, "utf8").split("\n").filter((line) => !/^\s*bun\.lockb?\s*$/.test(line));
|
|
300
|
+
writeFileSync(gitignorePath, kept.join("\n"));
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
} else if (ignoreStatus === 1) {
|
|
304
|
+
const trackedStatus = spawnSync("git", ["ls-files", "--error-unmatch", "bun.lock"], {
|
|
305
|
+
cwd: dir2
|
|
306
|
+
}).status;
|
|
307
|
+
if (trackedStatus === 1) {
|
|
308
|
+
findings.push({
|
|
309
|
+
level: "error",
|
|
310
|
+
message: "bun.lock untracked \u2192 staging it; commit the lockfile",
|
|
311
|
+
fix: () => {
|
|
312
|
+
spawnSync("git", ["add", "bun.lock"], { cwd: dir2 });
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
} else if (trackedStatus !== 0) {
|
|
316
|
+
findings.push({
|
|
317
|
+
level: "warn",
|
|
318
|
+
message: "git ls-files failed \u2014 cannot verify the lockfile is tracked"
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
} else {
|
|
322
|
+
findings.push({
|
|
323
|
+
level: "warn",
|
|
324
|
+
message: "git check-ignore failed \u2014 cannot verify the lockfile is not ignored"
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
const lefthookPin = manifest2.toolchain.lefthook;
|
|
329
|
+
if (lefthookPin && !DEP_FIELDS.some((field) => pkg[field]?.lefthook)) {
|
|
277
330
|
findings.push({
|
|
278
331
|
level: "error",
|
|
279
|
-
message:
|
|
332
|
+
message: `lefthook missing \u2192 devDependency ${lefthookPin}`,
|
|
333
|
+
fix: () => {
|
|
334
|
+
pkg.devDependencies ??= {};
|
|
335
|
+
pkg.devDependencies.lefthook = lefthookPin;
|
|
336
|
+
touch();
|
|
337
|
+
}
|
|
280
338
|
});
|
|
281
|
-
}
|
|
339
|
+
}
|
|
340
|
+
const lefthookPath = join(dir2, "lefthook.yml");
|
|
341
|
+
const lefthookStub = "extends:\n - node_modules/@inixiative/config/lefthook/base.yml\n";
|
|
342
|
+
if (!existsSync(lefthookPath)) {
|
|
343
|
+
findings.push({
|
|
344
|
+
level: "error",
|
|
345
|
+
message: "lefthook.yml missing \u2192 stub extending @inixiative/config/lefthook/base.yml",
|
|
346
|
+
fix: () => writeFileSync(lefthookPath, lefthookStub)
|
|
347
|
+
});
|
|
348
|
+
} else if (!readFileSync(lefthookPath, "utf8").includes("lefthook/base.yml")) {
|
|
349
|
+
findings.push({
|
|
350
|
+
level: "error",
|
|
351
|
+
message: "lefthook.yml does not extend the shared hooks \u2192 replaced with extends stub (local hooks overwritten \u2014 review the diff)",
|
|
352
|
+
fix: () => writeFileSync(lefthookPath, lefthookStub)
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
if (!pkg.scripts?.prepare) {
|
|
282
356
|
findings.push({
|
|
283
357
|
level: "error",
|
|
284
|
-
message:
|
|
358
|
+
message: 'scripts.prepare missing \u2192 "lefthook install"',
|
|
359
|
+
fix: () => {
|
|
360
|
+
pkg.scripts ??= {};
|
|
361
|
+
pkg.scripts.prepare = "lefthook install";
|
|
362
|
+
touch();
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
} else if (!pkg.scripts.prepare.includes("lefthook")) {
|
|
366
|
+
findings.push({
|
|
367
|
+
level: "warn",
|
|
368
|
+
message: "scripts.prepare does not run lefthook install \u2014 hooks will not auto-install"
|
|
285
369
|
});
|
|
286
370
|
}
|
|
287
371
|
}
|
|
@@ -492,7 +576,8 @@ if (command === "train") {
|
|
|
492
576
|
bump.fix?.();
|
|
493
577
|
}
|
|
494
578
|
inspection.flush();
|
|
495
|
-
|
|
579
|
+
const bumped = bumps.length > 0;
|
|
580
|
+
const staleLock = inspection.findings.some((finding) => finding.kind === "stale-lock");
|
|
496
581
|
const remote = spawnSync2("npm", ["view", `${repo.name}@latest`, "version"], {
|
|
497
582
|
encoding: "utf8"
|
|
498
583
|
});
|
|
@@ -504,7 +589,7 @@ if (command === "train") {
|
|
|
504
589
|
skipped.push(repo.name);
|
|
505
590
|
continue;
|
|
506
591
|
}
|
|
507
|
-
if (
|
|
592
|
+
if (bumped || ahead || staleLock) {
|
|
508
593
|
const install = spawnSync2("bun", ["install"], { cwd: repo.dir, stdio: "inherit" });
|
|
509
594
|
if (install.status !== 0) {
|
|
510
595
|
console.error("\u2717 bun install failed \u2014 aborting train");
|
|
@@ -513,7 +598,6 @@ if (command === "train") {
|
|
|
513
598
|
const stale = inspect(repo.dir, manifest).findings.filter((finding) => finding.kind === "stale-lock" && finding.name).map((finding) => finding.name);
|
|
514
599
|
if (stale.length > 0) {
|
|
515
600
|
spawnSync2("bun", ["update", ...new Set(stale)], { cwd: repo.dir, stdio: "inherit" });
|
|
516
|
-
touched = true;
|
|
517
601
|
}
|
|
518
602
|
const check = spawnSync2("bun", ["run", "check"], { cwd: repo.dir, stdio: "inherit" });
|
|
519
603
|
if (check.status !== 0) {
|
|
@@ -521,7 +605,11 @@ if (command === "train") {
|
|
|
521
605
|
process.exit(1);
|
|
522
606
|
}
|
|
523
607
|
}
|
|
524
|
-
|
|
608
|
+
const mutated = spawnSync2("git", ["status", "--porcelain", "package.json", "bun.lock"], {
|
|
609
|
+
cwd: repo.dir,
|
|
610
|
+
encoding: "utf8"
|
|
611
|
+
});
|
|
612
|
+
if (mutated.status === 0 && mutated.stdout.trim().length > 0) {
|
|
525
613
|
spawnSync2("git", ["add", "package.json", "bun.lock"], { cwd: repo.dir });
|
|
526
614
|
const commit = spawnSync2(
|
|
527
615
|
"git",
|
|
@@ -584,4 +672,8 @@ if (!flags.has("--no-install")) {
|
|
|
584
672
|
}
|
|
585
673
|
}
|
|
586
674
|
var final = inspect(dir, manifest, presetFlag);
|
|
587
|
-
|
|
675
|
+
var remaining = final.findings.filter((finding) => finding.fix);
|
|
676
|
+
for (const finding of remaining) finding.fix?.();
|
|
677
|
+
final.flush();
|
|
678
|
+
var settled = remaining.length > 0 ? inspect(dir, manifest, presetFlag) : final;
|
|
679
|
+
process.exit(report(settled.findings) > 0 ? 1 : 0);
|
package/dist/tsup.js
CHANGED
|
@@ -8,12 +8,13 @@ var base = {
|
|
|
8
8
|
sourcemap: true,
|
|
9
9
|
clean: true
|
|
10
10
|
};
|
|
11
|
-
var
|
|
11
|
+
var withDts = (options) => options.dts === true ? { ...options, dts: base.dts } : options;
|
|
12
|
+
var node = (options = {}) => defineConfig({ ...base, ...withDts(options) });
|
|
12
13
|
var react = (options = {}) => {
|
|
13
14
|
const external = Array.isArray(options.external) ? options.external : [];
|
|
14
15
|
return defineConfig({
|
|
15
16
|
...base,
|
|
16
|
-
...options,
|
|
17
|
+
...withDts(options),
|
|
17
18
|
external: [.../* @__PURE__ */ new Set(["react", "react-dom", "react/jsx-runtime", ...external])]
|
|
18
19
|
});
|
|
19
20
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inixiative/config",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Shared toolchain for the inixiative ecosystem: tsconfig/biome/tsup presets, a version manifest (BOM), and a sync/check CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"dist",
|
|
20
20
|
"tsconfig",
|
|
21
21
|
"biome",
|
|
22
|
+
"lefthook",
|
|
22
23
|
"versions.json",
|
|
23
24
|
"README.md"
|
|
24
25
|
],
|
|
@@ -29,12 +30,14 @@
|
|
|
29
30
|
"./tsconfig/react.json": "./tsconfig/react.json",
|
|
30
31
|
"./biome/base.json": "./biome/base.json",
|
|
31
32
|
"./biome/react.json": "./biome/react.json",
|
|
33
|
+
"./lefthook/base.yml": "./lefthook/base.yml",
|
|
32
34
|
"./tsup": {
|
|
33
35
|
"types": "./dist/tsup.d.ts",
|
|
34
36
|
"import": "./dist/tsup.js"
|
|
35
37
|
}
|
|
36
38
|
},
|
|
37
39
|
"scripts": {
|
|
40
|
+
"prepare": "lefthook install",
|
|
38
41
|
"build": "tsup",
|
|
39
42
|
"test": "bun test",
|
|
40
43
|
"typecheck": "tsc --noEmit",
|
|
@@ -47,6 +50,7 @@
|
|
|
47
50
|
"devDependencies": {
|
|
48
51
|
"@biomejs/biome": "2.5.2",
|
|
49
52
|
"@types/bun": "1.3.14",
|
|
53
|
+
"lefthook": "2.1.9",
|
|
50
54
|
"tsup": "8.5.1",
|
|
51
55
|
"typescript": "6.0.3"
|
|
52
56
|
},
|
package/versions.json
CHANGED
|
@@ -4,15 +4,20 @@
|
|
|
4
4
|
"@biomejs/biome": "2.5.2",
|
|
5
5
|
"typescript": "6.0.3",
|
|
6
6
|
"tsup": "8.5.1",
|
|
7
|
-
"@types/bun": "1.3.14"
|
|
7
|
+
"@types/bun": "1.3.14",
|
|
8
|
+
"lefthook": "2.1.9"
|
|
8
9
|
},
|
|
9
|
-
"required": [
|
|
10
|
+
"required": [
|
|
11
|
+
"@biomejs/biome",
|
|
12
|
+
"typescript",
|
|
13
|
+
"@types/bun"
|
|
14
|
+
],
|
|
10
15
|
"ecosystem": {
|
|
11
|
-
"@inixiative/json-rules": "2.
|
|
12
|
-
"@inixiative/permissions": "0.3.
|
|
13
|
-
"@inixiative/transitions": "0.0
|
|
14
|
-
"@inixiative/rules-builder": "0.
|
|
16
|
+
"@inixiative/json-rules": "2.13.0",
|
|
17
|
+
"@inixiative/permissions": "0.3.2",
|
|
18
|
+
"@inixiative/transitions": "0.1.0",
|
|
19
|
+
"@inixiative/rules-builder": "0.14.0",
|
|
15
20
|
"@inixiative/prisma-map": "0.1.0",
|
|
16
|
-
"@inixiative/atlas": "0.1.
|
|
21
|
+
"@inixiative/atlas": "0.1.1"
|
|
17
22
|
}
|
|
18
23
|
}
|