@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 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.20.0/schema/markdownlint-cli2-config-schema.json",
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.20.0/schema/markdownlint-cli2-config-schema.json";
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 hasIssues = !foundConfig || !hasHuskyHook || !managedStatus.found || managedStatus.needsUpdate || hasShellHookIssues || hasMarkdownlintIssues;
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.4.5"
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
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://biomejs.dev/schemas/2.4.1/schema.json",
2
+ "$schema": "https://biomejs.dev/schemas/2.4.5/schema.json",
3
3
  "assist": {
4
4
  "actions": {
5
5
  "source": {
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
- "name": "@savvy-web/lint-staged",
3
- "version": "0.4.5",
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.3",
45
- "@effect/platform-node": "^0.104.1",
46
- "@typescript-eslint/parser": "^8.54.0",
47
- "cosmiconfig": "^9.0.0",
48
- "effect": "^3.19.16",
49
- "eslint": "^9.39.2",
50
- "eslint-plugin-tsdoc": "^0.5.0",
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.1",
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.2.0",
64
- "markdownlint-cli2": "^0.21.0",
65
- "markdownlint-cli2-formatter-codequality": "^0.0.7",
66
- "turbo": "^2.8.0",
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
- }
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
+ }