@savvy-web/lint-staged 0.4.5 → 0.5.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/376.js +102 -6
- package/biome/silk.jsonc +1 -1
- package/index.d.ts +2 -1
- package/package.json +117 -117
package/376.js
CHANGED
|
@@ -961,8 +961,44 @@ class TypeScript {
|
|
|
961
961
|
};
|
|
962
962
|
}
|
|
963
963
|
}
|
|
964
|
+
const SCHEMA_URL_PREFIX = "https://biomejs.dev/schemas/";
|
|
965
|
+
const SCHEMA_URL_SUFFIX = "/schema.json";
|
|
966
|
+
const BIOME_GLOB_PATTERN = "**/biome.{json,jsonc}";
|
|
967
|
+
const BIOME_EXCLUDE_DIRS = [
|
|
968
|
+
"node_modules",
|
|
969
|
+
"dist",
|
|
970
|
+
".turbo",
|
|
971
|
+
".git",
|
|
972
|
+
".rslib"
|
|
973
|
+
];
|
|
974
|
+
function extractSemver(versionRange) {
|
|
975
|
+
return versionRange.replace(/^[^\d]*/, "");
|
|
976
|
+
}
|
|
977
|
+
function buildSchemaUrl(version) {
|
|
978
|
+
return `${SCHEMA_URL_PREFIX}${version}${SCHEMA_URL_SUFFIX}`;
|
|
979
|
+
}
|
|
980
|
+
function getBiomePeerVersion() {
|
|
981
|
+
const raw = "2.4.5";
|
|
982
|
+
if (!raw) return;
|
|
983
|
+
return extractSemver(raw);
|
|
984
|
+
}
|
|
985
|
+
function getExpectedSchemaUrl() {
|
|
986
|
+
const version = getBiomePeerVersion();
|
|
987
|
+
if (!version) return;
|
|
988
|
+
return buildSchemaUrl(version);
|
|
989
|
+
}
|
|
990
|
+
function findBiomeConfigs() {
|
|
991
|
+
return Effect.tryPromise(async ()=>{
|
|
992
|
+
const { glob } = await import("node:fs/promises");
|
|
993
|
+
const paths = [];
|
|
994
|
+
for await (const entry of glob(BIOME_GLOB_PATTERN, {
|
|
995
|
+
exclude: (name)=>BIOME_EXCLUDE_DIRS.includes(name)
|
|
996
|
+
}))paths.push(entry);
|
|
997
|
+
return paths;
|
|
998
|
+
});
|
|
999
|
+
}
|
|
964
1000
|
const MARKDOWNLINT_TEMPLATE = {
|
|
965
|
-
$schema: "https://raw.githubusercontent.com/DavidAnson/markdownlint-cli2/v0.
|
|
1001
|
+
$schema: "https://raw.githubusercontent.com/DavidAnson/markdownlint-cli2/v0.21.0/schema/markdownlint-cli2-config-schema.json",
|
|
966
1002
|
globs: [
|
|
967
1003
|
"**/*.{md,mdx}"
|
|
968
1004
|
],
|
|
@@ -1058,10 +1094,11 @@ const MARKDOWNLINT_TEMPLATE = {
|
|
|
1058
1094
|
},
|
|
1059
1095
|
"changeset-heading-hierarchy": false,
|
|
1060
1096
|
"changeset-required-sections": false,
|
|
1061
|
-
"changeset-content-structure": false
|
|
1097
|
+
"changeset-content-structure": false,
|
|
1098
|
+
"changeset-uncategorized-content": false
|
|
1062
1099
|
}
|
|
1063
1100
|
};
|
|
1064
|
-
const MARKDOWNLINT_SCHEMA = "https://raw.githubusercontent.com/DavidAnson/markdownlint-cli2/v0.
|
|
1101
|
+
const MARKDOWNLINT_SCHEMA = "https://raw.githubusercontent.com/DavidAnson/markdownlint-cli2/v0.21.0/schema/markdownlint-cli2-config-schema.json";
|
|
1065
1102
|
const MARKDOWNLINT_CONFIG = {
|
|
1066
1103
|
default: true,
|
|
1067
1104
|
MD001: true,
|
|
@@ -1139,7 +1176,8 @@ const MARKDOWNLINT_CONFIG = {
|
|
|
1139
1176
|
},
|
|
1140
1177
|
"changeset-heading-hierarchy": false,
|
|
1141
1178
|
"changeset-required-sections": false,
|
|
1142
|
-
"changeset-content-structure": false
|
|
1179
|
+
"changeset-content-structure": false,
|
|
1180
|
+
"changeset-uncategorized-content": false
|
|
1143
1181
|
};
|
|
1144
1182
|
const CHECK_MARK = "\u2713";
|
|
1145
1183
|
const WARNING = "\u26A0";
|
|
@@ -1306,6 +1344,31 @@ function writeMarkdownlintConfig(fs, preset, force) {
|
|
|
1306
1344
|
} else yield* Effect.log(`${CHECK_MARK} ${MARKDOWNLINT_CONFIG_PATH}: up-to-date`);
|
|
1307
1345
|
});
|
|
1308
1346
|
}
|
|
1347
|
+
function syncBiomeSchemas(fs) {
|
|
1348
|
+
return Effect.gen(function*() {
|
|
1349
|
+
const expectedUrl = getExpectedSchemaUrl();
|
|
1350
|
+
if (!expectedUrl) return;
|
|
1351
|
+
const configs = yield* findBiomeConfigs();
|
|
1352
|
+
for (const configPath of configs){
|
|
1353
|
+
const content = yield* fs.readFileString(configPath);
|
|
1354
|
+
const parsed = parse(content);
|
|
1355
|
+
if ("string" != typeof parsed.$schema) continue;
|
|
1356
|
+
if (!parsed.$schema.startsWith(SCHEMA_URL_PREFIX)) continue;
|
|
1357
|
+
if (parsed.$schema === expectedUrl) {
|
|
1358
|
+
yield* Effect.log(`${CHECK_MARK} ${configPath}: biome $schema up-to-date`);
|
|
1359
|
+
continue;
|
|
1360
|
+
}
|
|
1361
|
+
const edits = modify(content, [
|
|
1362
|
+
"$schema"
|
|
1363
|
+
], expectedUrl, {
|
|
1364
|
+
formattingOptions: JSONC_FORMAT
|
|
1365
|
+
});
|
|
1366
|
+
const updated = applyEdits(content, edits);
|
|
1367
|
+
yield* fs.writeFileString(configPath, updated);
|
|
1368
|
+
yield* Effect.log(`${CHECK_MARK} Updated $schema in ${configPath}`);
|
|
1369
|
+
}
|
|
1370
|
+
});
|
|
1371
|
+
}
|
|
1309
1372
|
const forceOption = Options.boolean("force").pipe(Options.withAlias("f"), Options.withDescription("Overwrite entire hook file (not just managed section)"), Options.withDefault(false));
|
|
1310
1373
|
const configOption = Options.text("config").pipe(Options.withAlias("c"), Options.withDescription("Relative path for the lint-staged config file (from repo root)"), Options.withDefault(DEFAULT_CONFIG_PATH));
|
|
1311
1374
|
const presetOption = Options.choice("preset", [
|
|
@@ -1356,6 +1419,7 @@ const initCommand = Command.make("init", {
|
|
|
1356
1419
|
yield* writeHook(fs, POST_MERGE_HOOK_PATH, shellContent, "Post-merge hook with savvy-lint managed section", force);
|
|
1357
1420
|
}
|
|
1358
1421
|
if (presetIncludesMarkdown(preset)) yield* writeMarkdownlintConfig(fs, preset, force);
|
|
1422
|
+
yield* syncBiomeSchemas(fs);
|
|
1359
1423
|
const configExists = yield* fs.exists(config);
|
|
1360
1424
|
if (configExists && !force) yield* Effect.log(`${WARNING} ${config} already exists (use --force to overwrite)`);
|
|
1361
1425
|
else {
|
|
@@ -1447,6 +1511,33 @@ function checkMarkdownlintConfig(content) {
|
|
|
1447
1511
|
isUpToDate: schemaMatches && configMatches
|
|
1448
1512
|
};
|
|
1449
1513
|
}
|
|
1514
|
+
function checkBiomeSchemas(fs) {
|
|
1515
|
+
return Effect.gen(function*() {
|
|
1516
|
+
const expectedUrl = getExpectedSchemaUrl();
|
|
1517
|
+
const statuses = [];
|
|
1518
|
+
if (!expectedUrl) return {
|
|
1519
|
+
statuses,
|
|
1520
|
+
warnings: []
|
|
1521
|
+
};
|
|
1522
|
+
const configs = yield* findBiomeConfigs();
|
|
1523
|
+
const warnings = [];
|
|
1524
|
+
for (const configPath of configs){
|
|
1525
|
+
const content = yield* fs.readFileString(configPath);
|
|
1526
|
+
const parsed = parse(content);
|
|
1527
|
+
if ("string" != typeof parsed.$schema || !parsed.$schema.startsWith(SCHEMA_URL_PREFIX)) continue;
|
|
1528
|
+
const matches = parsed.$schema === expectedUrl;
|
|
1529
|
+
statuses.push({
|
|
1530
|
+
path: configPath,
|
|
1531
|
+
matches
|
|
1532
|
+
});
|
|
1533
|
+
if (!matches) warnings.push(`${check_WARNING} ${configPath}: biome $schema is outdated.\n Run 'savvy-lint init' to update it.`);
|
|
1534
|
+
}
|
|
1535
|
+
return {
|
|
1536
|
+
statuses,
|
|
1537
|
+
warnings
|
|
1538
|
+
};
|
|
1539
|
+
});
|
|
1540
|
+
}
|
|
1450
1541
|
const quietOption = Options.boolean("quiet").pipe(Options.withAlias("q"), Options.withDescription("Only output warnings (for postinstall usage)"), Options.withDefault(false));
|
|
1451
1542
|
const checkCommand = Command.make("check", {
|
|
1452
1543
|
quiet: quietOption
|
|
@@ -1499,6 +1590,8 @@ const checkCommand = Command.make("check", {
|
|
|
1499
1590
|
if (status.found && status.needsUpdate) warnings.push(`${check_WARNING} Your ${hookPath} managed section is outdated.\n Run 'savvy-lint init' to update it (preserves your custom hooks).`);
|
|
1500
1591
|
}
|
|
1501
1592
|
}
|
|
1593
|
+
const biomeSchemaStatus = yield* checkBiomeSchemas(fs);
|
|
1594
|
+
warnings.push(...biomeSchemaStatus.warnings);
|
|
1502
1595
|
const hasMarkdownlintConfig = yield* fs.exists(MARKDOWNLINT_CONFIG_PATH);
|
|
1503
1596
|
let markdownlintStatus = {
|
|
1504
1597
|
exists: false,
|
|
@@ -1555,10 +1648,13 @@ const checkCommand = Command.make("check", {
|
|
|
1555
1648
|
yield* Effect.log(` ${check_WARNING} ${MARKDOWNLINT_CONFIG_PATH}: ${issues.join(", ")} differ from template`);
|
|
1556
1649
|
}
|
|
1557
1650
|
else yield* Effect.log(` ${BULLET} ${MARKDOWNLINT_CONFIG_PATH}: not found`);
|
|
1651
|
+
for (const status of biomeSchemaStatus.statuses)if (status.matches) yield* Effect.log(` ${check_CHECK_MARK} ${status.path}: biome $schema up-to-date`);
|
|
1652
|
+
else yield* Effect.log(` ${check_WARNING} ${status.path}: biome $schema outdated (run 'savvy-lint init' to update)`);
|
|
1558
1653
|
yield* Effect.log("");
|
|
1559
1654
|
const hasShellHookIssues = shellHookStatuses.some((s)=>s.found && s.needsUpdate);
|
|
1560
1655
|
const hasMarkdownlintIssues = hasMarkdownlintConfig && !markdownlintStatus.isUpToDate;
|
|
1561
|
-
const
|
|
1656
|
+
const hasBiomeSchemaIssues = biomeSchemaStatus.statuses.some((s)=>!s.matches);
|
|
1657
|
+
const hasIssues = !foundConfig || !hasHuskyHook || !managedStatus.found || managedStatus.needsUpdate || hasShellHookIssues || hasMarkdownlintIssues || hasBiomeSchemaIssues;
|
|
1562
1658
|
if (hasIssues) yield* Effect.log(`${check_WARNING} Some issues found. Run 'savvy-lint init' to fix.`);
|
|
1563
1659
|
else yield* Effect.log(`${check_CHECK_MARK} Lint-staged is configured correctly.`);
|
|
1564
1660
|
})).pipe(Command.withDescription("Check current lint-staged configuration and tool availability"));
|
|
@@ -1738,7 +1834,7 @@ const rootCommand = Command.make("savvy-lint").pipe(Command.withSubcommands([
|
|
|
1738
1834
|
]));
|
|
1739
1835
|
const cli = Command.run(rootCommand, {
|
|
1740
1836
|
name: "savvy-lint",
|
|
1741
|
-
version: "0.
|
|
1837
|
+
version: "0.5.0"
|
|
1742
1838
|
});
|
|
1743
1839
|
function runCli() {
|
|
1744
1840
|
const main = Effect.suspend(()=>cli(process.argv)).pipe(Effect.provide(NodeContext.layer));
|
package/biome/silk.jsonc
CHANGED
package/index.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ import { FileSystem } from '@effect/platform';
|
|
|
24
24
|
import { FileSystem as FileSystem_2 } from '@effect/platform/FileSystem';
|
|
25
25
|
import { Option } from 'effect/Option';
|
|
26
26
|
import { PlatformError } from '@effect/platform/Error';
|
|
27
|
+
import { UnknownException } from 'effect/Cause';
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* Base options shared by all handlers.
|
|
@@ -143,7 +144,7 @@ export declare interface BiomeOptions extends BaseHandlerOptions {
|
|
|
143
144
|
* Validates the current lint-staged setup and displays detected settings.
|
|
144
145
|
* With --quiet flag, only outputs warnings (for postinstall usage).
|
|
145
146
|
*/
|
|
146
|
-
export declare const checkCommand: Command_2.Command<"check", FileSystem.FileSystem, PlatformError, {
|
|
147
|
+
export declare const checkCommand: Command_2.Command<"check", FileSystem.FileSystem, UnknownException | PlatformError, {
|
|
147
148
|
readonly quiet: boolean;
|
|
148
149
|
}>;
|
|
149
150
|
|
package/package.json
CHANGED
|
@@ -1,118 +1,118 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
2
|
+
"name": "@savvy-web/lint-staged",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Composable, configurable lint-staged handlers for pre-commit hooks. Provides reusable handlers for Biome, Markdown, YAML, TypeScript, and more.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"lint-staged",
|
|
8
|
+
"pre-commit",
|
|
9
|
+
"hooks",
|
|
10
|
+
"biome",
|
|
11
|
+
"markdown",
|
|
12
|
+
"yaml",
|
|
13
|
+
"typescript",
|
|
14
|
+
"formatting",
|
|
15
|
+
"linting"
|
|
16
|
+
],
|
|
17
|
+
"homepage": "https://github.com/savvy-web/lint-staged#readme",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/savvy-web/lint-staged/issues"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/savvy-web/lint-staged.git"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"author": {
|
|
27
|
+
"name": "C. Spencer Beggs",
|
|
28
|
+
"email": "spencer@savvyweb.systems",
|
|
29
|
+
"url": "https://savvyweb.systems"
|
|
30
|
+
},
|
|
31
|
+
"type": "module",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./index.d.ts",
|
|
35
|
+
"import": "./index.js"
|
|
36
|
+
},
|
|
37
|
+
"./biome/silk.jsonc": "./biome/silk.jsonc"
|
|
38
|
+
},
|
|
39
|
+
"bin": {
|
|
40
|
+
"savvy-lint": "./bin/savvy-lint.js"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@effect/cli": "^0.73.2",
|
|
44
|
+
"@effect/platform": "^0.94.5",
|
|
45
|
+
"@effect/platform-node": "^0.104.1",
|
|
46
|
+
"@typescript-eslint/parser": "^8.56.1",
|
|
47
|
+
"cosmiconfig": "^9.0.1",
|
|
48
|
+
"effect": "^3.19.16",
|
|
49
|
+
"eslint": "^10.0.2",
|
|
50
|
+
"eslint-plugin-tsdoc": "^0.5.2",
|
|
51
|
+
"jsonc-parser": "^3.3.1",
|
|
52
|
+
"prettier": "^3.8.1",
|
|
53
|
+
"sort-package-json": "^3.6.1",
|
|
54
|
+
"workspace-tools": "^0.41.0",
|
|
55
|
+
"yaml": "^2.8.2",
|
|
56
|
+
"yaml-lint": "^1.7.0"
|
|
57
|
+
},
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"@biomejs/biome": "2.4.5",
|
|
60
|
+
"@types/node": "^25.2.0",
|
|
61
|
+
"@typescript/native-preview": "^7.0.0-dev.20260124.1",
|
|
62
|
+
"husky": "^9.1.0",
|
|
63
|
+
"lint-staged": "^16.3.2",
|
|
64
|
+
"markdownlint-cli2": "^0.21.0",
|
|
65
|
+
"markdownlint-cli2-formatter-codequality": "^0.0.7",
|
|
66
|
+
"turbo": "^2.8.13",
|
|
67
|
+
"typescript": "^5.9.3"
|
|
68
|
+
},
|
|
69
|
+
"peerDependenciesMeta": {
|
|
70
|
+
"@biomejs/biome": {
|
|
71
|
+
"optional": true
|
|
72
|
+
},
|
|
73
|
+
"@types/node": {
|
|
74
|
+
"optional": false
|
|
75
|
+
},
|
|
76
|
+
"@typescript/native-preview": {
|
|
77
|
+
"optional": false
|
|
78
|
+
},
|
|
79
|
+
"husky": {
|
|
80
|
+
"optional": false
|
|
81
|
+
},
|
|
82
|
+
"lint-staged": {
|
|
83
|
+
"optional": false
|
|
84
|
+
},
|
|
85
|
+
"markdownlint-cli2": {
|
|
86
|
+
"optional": false
|
|
87
|
+
},
|
|
88
|
+
"markdownlint-cli2-formatter-codequality": {
|
|
89
|
+
"optional": false
|
|
90
|
+
},
|
|
91
|
+
"turbo": {
|
|
92
|
+
"optional": false
|
|
93
|
+
},
|
|
94
|
+
"typescript": {
|
|
95
|
+
"optional": false
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"engines": {
|
|
99
|
+
"node": ">=24.0.0"
|
|
100
|
+
},
|
|
101
|
+
"scripts": {
|
|
102
|
+
"postinstall": "savvy-lint check --quiet || true"
|
|
103
|
+
},
|
|
104
|
+
"files": [
|
|
105
|
+
"!lint-staged.api.json",
|
|
106
|
+
"!tsconfig.json",
|
|
107
|
+
"!tsdoc.json",
|
|
108
|
+
"376.js",
|
|
109
|
+
"LICENSE",
|
|
110
|
+
"README.md",
|
|
111
|
+
"bin/savvy-lint.js",
|
|
112
|
+
"biome/silk.jsonc",
|
|
113
|
+
"index.d.ts",
|
|
114
|
+
"index.js",
|
|
115
|
+
"package.json",
|
|
116
|
+
"tsdoc-metadata.json"
|
|
117
|
+
]
|
|
118
|
+
}
|