@sarj/eslint-plugin 16.4.4 → 16.4.5

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.
@@ -15,6 +15,11 @@ interface ExampleFile {
15
15
  }
16
16
  /** A reviewed example. It remains private unless `public: true` is explicit. */
17
17
  interface RuleExample {
18
+ readonly ruleOptions?: readonly unknown[];
19
+ readonly installedDependencies?: readonly {
20
+ readonly module: string;
21
+ readonly version: string;
22
+ }[];
18
23
  readonly id: string;
19
24
  readonly scenarioId?: string;
20
25
  readonly title: string;
@@ -15,6 +15,11 @@ interface ExampleFile {
15
15
  }
16
16
  /** A reviewed example. It remains private unless `public: true` is explicit. */
17
17
  interface RuleExample {
18
+ readonly ruleOptions?: readonly unknown[];
19
+ readonly installedDependencies?: readonly {
20
+ readonly module: string;
21
+ readonly version: string;
22
+ }[];
18
23
  readonly id: string;
19
24
  readonly scenarioId?: string;
20
25
  readonly title: string;
package/dist/index.cjs CHANGED
@@ -112,7 +112,7 @@ ${missing.join("\n")}`);
112
112
  });
113
113
  }
114
114
  function publicExample(example) {
115
- return {
115
+ const copy = {
116
116
  id: example.id,
117
117
  scenarioId: example.scenarioId ?? "primary",
118
118
  title: example.title,
@@ -122,6 +122,9 @@ function publicExample(example) {
122
122
  expectedCount: example.expectedCount,
123
123
  fixedFiles: (example.fixedFiles ?? []).map(publicFile)
124
124
  };
125
+ if (example.ruleOptions !== void 0) copy.ruleOptions = example.ruleOptions;
126
+ if (example.installedDependencies !== void 0) copy.installedDependencies = example.installedDependencies.map(({ module: module2, version }) => ({ module: module2, version }));
127
+ return copy;
125
128
  }
126
129
  function publicFile(file) {
127
130
  return { path: file.path, source: file.source };
@@ -9687,8 +9690,8 @@ var NO_RESTRICTED_LIBRARY_LOAD_DOCUMENTATION = {
9687
9690
  category: "architecture",
9688
9691
  limitations: ["Only literal dynamic imports, unshadowed CommonJS loads/resolution calls, and runtime TypeScript import-equals declarations are checked; erased type imports are excluded. A configured restriction list is required."],
9689
9692
  examples: [
9690
- { id: "static-import", title: "Static imports remain the static-import rule's responsibility", outcome: "no-match", files: [{ path: "src/client.ts", source: "import axios from 'axios';" }], focusPath: "src/client.ts", expectedCount: 0, public: true },
9691
- { id: "runtime-load", title: "Do not load a restricted library at runtime", outcome: "match", files: [{ path: "src/client.ts", source: "const client = require('axios');" }], focusPath: "src/client.ts", expectedCount: 1, public: true }
9693
+ { id: "static-import", title: "Static imports remain the static-import rule's responsibility", outcome: "no-match", files: [{ path: "src/client.ts", source: "import axios from 'axios';" }], focusPath: "src/client.ts", expectedCount: 0, public: true, ruleOptions: [{ libraries: [{ id: "LIB101", module: "axios", replacement: "Ky" }] }] },
9694
+ { id: "runtime-load", title: "Do not load a restricted library at runtime", outcome: "match", files: [{ path: "src/client.ts", source: "const client = require('axios');" }], focusPath: "src/client.ts", expectedCount: 1, public: true, ruleOptions: [{ libraries: [{ id: "LIB101", module: "axios", replacement: "Ky" }] }] }
9692
9695
  ]
9693
9696
  };
9694
9697
  function staticModule(node) {
@@ -11832,8 +11835,8 @@ var NO_STORAGE_IN_STATELESS_MODULES_DOCUMENTATION = {
11832
11835
  category: "architecture",
11833
11836
  limitations: ["This opt-in architectural policy requires configured module paths and storage method names. Overloaded `put` requires storage-like receiver evidence; `prepare` requires SQL-shaped literal text or a conventional database receiver for dynamic text. These syntax heuristics do not prove database provenance or identify the system of record."],
11834
11837
  examples: [
11835
- { id: "system-of-record", title: "Read from the system of record", outcome: "no-match", files: [{ path: "src/engineer-digest/post.ts", source: "const issues = await linear.listIssues();" }], focusPath: "src/engineer-digest/post.ts", expectedCount: 0, public: true },
11836
- { id: "private-storage", title: "Do not write private state in a stateless module", outcome: "match", files: [{ path: "src/engineer-digest/post.ts", source: "export {}; await kv.put('digest:last', timestamp);" }], focusPath: "src/engineer-digest/post.ts", expectedCount: 1, public: true }
11838
+ { id: "system-of-record", title: "Read from the system of record", outcome: "no-match", files: [{ path: "src/engineer-digest/post.ts", source: "const issues = await linear.listIssues();" }], focusPath: "src/engineer-digest/post.ts", expectedCount: 0, public: true, ruleOptions: [{ modules: ["[\\\\/]engineer-digest[\\\\/]"] }] },
11839
+ { id: "private-storage", title: "Do not write private state in a stateless module", outcome: "match", files: [{ path: "src/engineer-digest/post.ts", source: "export {}; await kv.put('digest:last', timestamp);" }], focusPath: "src/engineer-digest/post.ts", expectedCount: 1, public: true, ruleOptions: [{ modules: ["[\\\\/]engineer-digest[\\\\/]"] }] }
11837
11840
  ]
11838
11841
  };
11839
11842
  function compile2(patterns) {
@@ -20993,7 +20996,8 @@ var PREFER_ZOD_PARSE_OUTPUT_TYPE_DOCUMENTATION = {
20993
20996
  ],
20994
20997
  focusPath: "src/row.ts",
20995
20998
  expectedCount: 0,
20996
- public: true
20999
+ public: true,
21000
+ installedDependencies: [{ module: "zod", version: "4.6.5" }]
20997
21001
  },
20998
21002
  {
20999
21003
  id: "hand-written-parsed-return",
@@ -21011,7 +21015,8 @@ var PREFER_ZOD_PARSE_OUTPUT_TYPE_DOCUMENTATION = {
21011
21015
  ],
21012
21016
  focusPath: "src/row.ts",
21013
21017
  expectedCount: 1,
21014
- public: true
21018
+ public: true,
21019
+ installedDependencies: [{ module: "zod", version: "4.6.5" }]
21015
21020
  }
21016
21021
  ]
21017
21022
  };
@@ -24284,7 +24289,7 @@ var RULES = {
24284
24289
  };
24285
24290
  var meta = {
24286
24291
  name: "@sarj/eslint-plugin",
24287
- version: "16.4.4"
24292
+ version: "16.4.5"
24288
24293
  };
24289
24294
  var APPLICATION_ONLY_RULES = [];
24290
24295
  var LIBRARY_IMPORT_POLICY = ["error", {
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { D as DocumentedRule } from './_docs-XCw_6XV9.cjs';
2
- export { p as publicDocumentation } from './_docs-XCw_6XV9.cjs';
1
+ import { D as DocumentedRule } from './_docs-B9LZ5Out.cjs';
2
+ export { p as publicDocumentation } from './_docs-B9LZ5Out.cjs';
3
3
  import '@typescript-eslint/utils';
4
4
 
5
5
  /** @fileoverview _retired-rules — burned rule names and their migration action. */
@@ -314,7 +314,7 @@ declare const RECOMMENDED_RULES: {
314
314
  }];
315
315
  readonly "no-restricted-imports": readonly ["error", {
316
316
  readonly paths: {
317
- name: "request" | "node-fetch" | "cross-fetch" | "isomorphic-fetch" | "axios" | "moment" | "dayjs" | "lodash" | "lodash-es" | "underscore" | "classnames" | "joi" | "yup" | "superstruct" | "io-ts" | "runtypes" | "jsonwebtoken" | "express" | "koa" | "jest" | "mocha" | "sinon" | "commander" | "yargs" | "bluebird" | "rimraf" | "fs-extra" | "abort-controller" | "querystring" | "dotenv" | "chalk" | "faker" | "node-sass" | "tslint";
317
+ name: "axios" | "request" | "node-fetch" | "cross-fetch" | "isomorphic-fetch" | "moment" | "dayjs" | "lodash" | "lodash-es" | "underscore" | "classnames" | "joi" | "yup" | "superstruct" | "io-ts" | "runtypes" | "jsonwebtoken" | "express" | "koa" | "jest" | "mocha" | "sinon" | "commander" | "yargs" | "bluebird" | "rimraf" | "fs-extra" | "abort-controller" | "querystring" | "dotenv" | "chalk" | "faker" | "node-sass" | "tslint";
318
318
  message: "Use the platform-native fetch API; review errors, timeouts, retries, and response parsing during migration." | "Standards standardizes date utilities on date-fns; migration is not API-compatible." | "Standards standardizes collection utilities on Remeda and native APIs." | "Use clsx for conditional class-name composition." | "Standards standardizes runtime validation on Zod; schemas are not drop-in compatible." | "Use jose; review key formats and async signing and verification APIs." | "Standards standardizes servers on Hono; Node deployments also need @hono/node-server." | "Standards standardizes tests on Vitest; review globals, timers, mocks, and environment setup." | "Use Vitest spies, mocks, and fake timers instead of Sinon." | "Standards standardizes command-line interfaces on citty." | "Use native Promise, adding p-limit or p-map only for the extensions actually needed." | "Prefer node:fs/promises; verify recursive removal, copy, path, and error semantics." | "Node 22 provides global AbortController." | "Use URLSearchParams and explicitly review repeated keys, escaping, arrays, and object coercion." | "Standards standardizes environment loading on @dotenvx/dotenvx." | "Use picocolors for terminal colors." | "The original faker package is abandoned; use @faker-js/faker." | "node-sass is end-of-life; use Dart Sass." | "TSLint is deprecated; use ESLint with typescript-eslint.";
319
319
  }[];
320
320
  readonly patterns: {
@@ -626,7 +626,7 @@ declare const STRICT_RULES: {
626
626
  }];
627
627
  readonly "no-restricted-imports": readonly ["error", {
628
628
  readonly paths: {
629
- name: "request" | "node-fetch" | "cross-fetch" | "isomorphic-fetch" | "axios" | "moment" | "dayjs" | "lodash" | "lodash-es" | "underscore" | "classnames" | "joi" | "yup" | "superstruct" | "io-ts" | "runtypes" | "jsonwebtoken" | "express" | "koa" | "jest" | "mocha" | "sinon" | "commander" | "yargs" | "bluebird" | "rimraf" | "fs-extra" | "abort-controller" | "querystring" | "dotenv" | "chalk" | "faker" | "node-sass" | "tslint";
629
+ name: "axios" | "request" | "node-fetch" | "cross-fetch" | "isomorphic-fetch" | "moment" | "dayjs" | "lodash" | "lodash-es" | "underscore" | "classnames" | "joi" | "yup" | "superstruct" | "io-ts" | "runtypes" | "jsonwebtoken" | "express" | "koa" | "jest" | "mocha" | "sinon" | "commander" | "yargs" | "bluebird" | "rimraf" | "fs-extra" | "abort-controller" | "querystring" | "dotenv" | "chalk" | "faker" | "node-sass" | "tslint";
630
630
  message: "Use the platform-native fetch API; review errors, timeouts, retries, and response parsing during migration." | "Standards standardizes date utilities on date-fns; migration is not API-compatible." | "Standards standardizes collection utilities on Remeda and native APIs." | "Use clsx for conditional class-name composition." | "Standards standardizes runtime validation on Zod; schemas are not drop-in compatible." | "Use jose; review key formats and async signing and verification APIs." | "Standards standardizes servers on Hono; Node deployments also need @hono/node-server." | "Standards standardizes tests on Vitest; review globals, timers, mocks, and environment setup." | "Use Vitest spies, mocks, and fake timers instead of Sinon." | "Standards standardizes command-line interfaces on citty." | "Use native Promise, adding p-limit or p-map only for the extensions actually needed." | "Prefer node:fs/promises; verify recursive removal, copy, path, and error semantics." | "Node 22 provides global AbortController." | "Use URLSearchParams and explicitly review repeated keys, escaping, arrays, and object coercion." | "Standards standardizes environment loading on @dotenvx/dotenvx." | "Use picocolors for terminal colors." | "The original faker package is abandoned; use @faker-js/faker." | "node-sass is end-of-life; use Dart Sass." | "TSLint is deprecated; use ESLint with typescript-eslint.";
631
631
  }[];
632
632
  readonly patterns: {
@@ -927,7 +927,7 @@ type FlatPreset = {
927
927
  declare const PLUGIN: {
928
928
  readonly meta: {
929
929
  readonly name: "@sarj/eslint-plugin";
930
- readonly version: "16.4.4";
930
+ readonly version: "16.4.5";
931
931
  };
932
932
  readonly rules: {
933
933
  readonly "require-explicit-contract-implementation": DocumentedRule<readonly [], "declareActualContract">;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { D as DocumentedRule } from './_docs-XCw_6XV9.js';
2
- export { p as publicDocumentation } from './_docs-XCw_6XV9.js';
1
+ import { D as DocumentedRule } from './_docs-B9LZ5Out.js';
2
+ export { p as publicDocumentation } from './_docs-B9LZ5Out.js';
3
3
  import '@typescript-eslint/utils';
4
4
 
5
5
  /** @fileoverview _retired-rules — burned rule names and their migration action. */
@@ -314,7 +314,7 @@ declare const RECOMMENDED_RULES: {
314
314
  }];
315
315
  readonly "no-restricted-imports": readonly ["error", {
316
316
  readonly paths: {
317
- name: "request" | "node-fetch" | "cross-fetch" | "isomorphic-fetch" | "axios" | "moment" | "dayjs" | "lodash" | "lodash-es" | "underscore" | "classnames" | "joi" | "yup" | "superstruct" | "io-ts" | "runtypes" | "jsonwebtoken" | "express" | "koa" | "jest" | "mocha" | "sinon" | "commander" | "yargs" | "bluebird" | "rimraf" | "fs-extra" | "abort-controller" | "querystring" | "dotenv" | "chalk" | "faker" | "node-sass" | "tslint";
317
+ name: "axios" | "request" | "node-fetch" | "cross-fetch" | "isomorphic-fetch" | "moment" | "dayjs" | "lodash" | "lodash-es" | "underscore" | "classnames" | "joi" | "yup" | "superstruct" | "io-ts" | "runtypes" | "jsonwebtoken" | "express" | "koa" | "jest" | "mocha" | "sinon" | "commander" | "yargs" | "bluebird" | "rimraf" | "fs-extra" | "abort-controller" | "querystring" | "dotenv" | "chalk" | "faker" | "node-sass" | "tslint";
318
318
  message: "Use the platform-native fetch API; review errors, timeouts, retries, and response parsing during migration." | "Standards standardizes date utilities on date-fns; migration is not API-compatible." | "Standards standardizes collection utilities on Remeda and native APIs." | "Use clsx for conditional class-name composition." | "Standards standardizes runtime validation on Zod; schemas are not drop-in compatible." | "Use jose; review key formats and async signing and verification APIs." | "Standards standardizes servers on Hono; Node deployments also need @hono/node-server." | "Standards standardizes tests on Vitest; review globals, timers, mocks, and environment setup." | "Use Vitest spies, mocks, and fake timers instead of Sinon." | "Standards standardizes command-line interfaces on citty." | "Use native Promise, adding p-limit or p-map only for the extensions actually needed." | "Prefer node:fs/promises; verify recursive removal, copy, path, and error semantics." | "Node 22 provides global AbortController." | "Use URLSearchParams and explicitly review repeated keys, escaping, arrays, and object coercion." | "Standards standardizes environment loading on @dotenvx/dotenvx." | "Use picocolors for terminal colors." | "The original faker package is abandoned; use @faker-js/faker." | "node-sass is end-of-life; use Dart Sass." | "TSLint is deprecated; use ESLint with typescript-eslint.";
319
319
  }[];
320
320
  readonly patterns: {
@@ -626,7 +626,7 @@ declare const STRICT_RULES: {
626
626
  }];
627
627
  readonly "no-restricted-imports": readonly ["error", {
628
628
  readonly paths: {
629
- name: "request" | "node-fetch" | "cross-fetch" | "isomorphic-fetch" | "axios" | "moment" | "dayjs" | "lodash" | "lodash-es" | "underscore" | "classnames" | "joi" | "yup" | "superstruct" | "io-ts" | "runtypes" | "jsonwebtoken" | "express" | "koa" | "jest" | "mocha" | "sinon" | "commander" | "yargs" | "bluebird" | "rimraf" | "fs-extra" | "abort-controller" | "querystring" | "dotenv" | "chalk" | "faker" | "node-sass" | "tslint";
629
+ name: "axios" | "request" | "node-fetch" | "cross-fetch" | "isomorphic-fetch" | "moment" | "dayjs" | "lodash" | "lodash-es" | "underscore" | "classnames" | "joi" | "yup" | "superstruct" | "io-ts" | "runtypes" | "jsonwebtoken" | "express" | "koa" | "jest" | "mocha" | "sinon" | "commander" | "yargs" | "bluebird" | "rimraf" | "fs-extra" | "abort-controller" | "querystring" | "dotenv" | "chalk" | "faker" | "node-sass" | "tslint";
630
630
  message: "Use the platform-native fetch API; review errors, timeouts, retries, and response parsing during migration." | "Standards standardizes date utilities on date-fns; migration is not API-compatible." | "Standards standardizes collection utilities on Remeda and native APIs." | "Use clsx for conditional class-name composition." | "Standards standardizes runtime validation on Zod; schemas are not drop-in compatible." | "Use jose; review key formats and async signing and verification APIs." | "Standards standardizes servers on Hono; Node deployments also need @hono/node-server." | "Standards standardizes tests on Vitest; review globals, timers, mocks, and environment setup." | "Use Vitest spies, mocks, and fake timers instead of Sinon." | "Standards standardizes command-line interfaces on citty." | "Use native Promise, adding p-limit or p-map only for the extensions actually needed." | "Prefer node:fs/promises; verify recursive removal, copy, path, and error semantics." | "Node 22 provides global AbortController." | "Use URLSearchParams and explicitly review repeated keys, escaping, arrays, and object coercion." | "Standards standardizes environment loading on @dotenvx/dotenvx." | "Use picocolors for terminal colors." | "The original faker package is abandoned; use @faker-js/faker." | "node-sass is end-of-life; use Dart Sass." | "TSLint is deprecated; use ESLint with typescript-eslint.";
631
631
  }[];
632
632
  readonly patterns: {
@@ -927,7 +927,7 @@ type FlatPreset = {
927
927
  declare const PLUGIN: {
928
928
  readonly meta: {
929
929
  readonly name: "@sarj/eslint-plugin";
930
- readonly version: "16.4.4";
930
+ readonly version: "16.4.5";
931
931
  };
932
932
  readonly rules: {
933
933
  readonly "require-explicit-contract-implementation": DocumentedRule<readonly [], "declareActualContract">;
package/dist/index.js CHANGED
@@ -61,7 +61,7 @@ ${missing.join("\n")}`);
61
61
  });
62
62
  }
63
63
  function publicExample(example) {
64
- return {
64
+ const copy = {
65
65
  id: example.id,
66
66
  scenarioId: example.scenarioId ?? "primary",
67
67
  title: example.title,
@@ -71,6 +71,9 @@ function publicExample(example) {
71
71
  expectedCount: example.expectedCount,
72
72
  fixedFiles: (example.fixedFiles ?? []).map(publicFile)
73
73
  };
74
+ if (example.ruleOptions !== void 0) copy.ruleOptions = example.ruleOptions;
75
+ if (example.installedDependencies !== void 0) copy.installedDependencies = example.installedDependencies.map(({ module, version }) => ({ module, version }));
76
+ return copy;
74
77
  }
75
78
  function publicFile(file) {
76
79
  return { path: file.path, source: file.source };
@@ -9671,8 +9674,8 @@ var NO_RESTRICTED_LIBRARY_LOAD_DOCUMENTATION = {
9671
9674
  category: "architecture",
9672
9675
  limitations: ["Only literal dynamic imports, unshadowed CommonJS loads/resolution calls, and runtime TypeScript import-equals declarations are checked; erased type imports are excluded. A configured restriction list is required."],
9673
9676
  examples: [
9674
- { id: "static-import", title: "Static imports remain the static-import rule's responsibility", outcome: "no-match", files: [{ path: "src/client.ts", source: "import axios from 'axios';" }], focusPath: "src/client.ts", expectedCount: 0, public: true },
9675
- { id: "runtime-load", title: "Do not load a restricted library at runtime", outcome: "match", files: [{ path: "src/client.ts", source: "const client = require('axios');" }], focusPath: "src/client.ts", expectedCount: 1, public: true }
9677
+ { id: "static-import", title: "Static imports remain the static-import rule's responsibility", outcome: "no-match", files: [{ path: "src/client.ts", source: "import axios from 'axios';" }], focusPath: "src/client.ts", expectedCount: 0, public: true, ruleOptions: [{ libraries: [{ id: "LIB101", module: "axios", replacement: "Ky" }] }] },
9678
+ { id: "runtime-load", title: "Do not load a restricted library at runtime", outcome: "match", files: [{ path: "src/client.ts", source: "const client = require('axios');" }], focusPath: "src/client.ts", expectedCount: 1, public: true, ruleOptions: [{ libraries: [{ id: "LIB101", module: "axios", replacement: "Ky" }] }] }
9676
9679
  ]
9677
9680
  };
9678
9681
  function staticModule(node) {
@@ -11816,8 +11819,8 @@ var NO_STORAGE_IN_STATELESS_MODULES_DOCUMENTATION = {
11816
11819
  category: "architecture",
11817
11820
  limitations: ["This opt-in architectural policy requires configured module paths and storage method names. Overloaded `put` requires storage-like receiver evidence; `prepare` requires SQL-shaped literal text or a conventional database receiver for dynamic text. These syntax heuristics do not prove database provenance or identify the system of record."],
11818
11821
  examples: [
11819
- { id: "system-of-record", title: "Read from the system of record", outcome: "no-match", files: [{ path: "src/engineer-digest/post.ts", source: "const issues = await linear.listIssues();" }], focusPath: "src/engineer-digest/post.ts", expectedCount: 0, public: true },
11820
- { id: "private-storage", title: "Do not write private state in a stateless module", outcome: "match", files: [{ path: "src/engineer-digest/post.ts", source: "export {}; await kv.put('digest:last', timestamp);" }], focusPath: "src/engineer-digest/post.ts", expectedCount: 1, public: true }
11822
+ { id: "system-of-record", title: "Read from the system of record", outcome: "no-match", files: [{ path: "src/engineer-digest/post.ts", source: "const issues = await linear.listIssues();" }], focusPath: "src/engineer-digest/post.ts", expectedCount: 0, public: true, ruleOptions: [{ modules: ["[\\\\/]engineer-digest[\\\\/]"] }] },
11823
+ { id: "private-storage", title: "Do not write private state in a stateless module", outcome: "match", files: [{ path: "src/engineer-digest/post.ts", source: "export {}; await kv.put('digest:last', timestamp);" }], focusPath: "src/engineer-digest/post.ts", expectedCount: 1, public: true, ruleOptions: [{ modules: ["[\\\\/]engineer-digest[\\\\/]"] }] }
11821
11824
  ]
11822
11825
  };
11823
11826
  function compile2(patterns) {
@@ -21008,7 +21011,8 @@ var PREFER_ZOD_PARSE_OUTPUT_TYPE_DOCUMENTATION = {
21008
21011
  ],
21009
21012
  focusPath: "src/row.ts",
21010
21013
  expectedCount: 0,
21011
- public: true
21014
+ public: true,
21015
+ installedDependencies: [{ module: "zod", version: "4.6.5" }]
21012
21016
  },
21013
21017
  {
21014
21018
  id: "hand-written-parsed-return",
@@ -21026,7 +21030,8 @@ var PREFER_ZOD_PARSE_OUTPUT_TYPE_DOCUMENTATION = {
21026
21030
  ],
21027
21031
  focusPath: "src/row.ts",
21028
21032
  expectedCount: 1,
21029
- public: true
21033
+ public: true,
21034
+ installedDependencies: [{ module: "zod", version: "4.6.5" }]
21030
21035
  }
21031
21036
  ]
21032
21037
  };
@@ -24308,7 +24313,7 @@ var RULES = {
24308
24313
  };
24309
24314
  var meta = {
24310
24315
  name: "@sarj/eslint-plugin",
24311
- version: "16.4.4"
24316
+ version: "16.4.5"
24312
24317
  };
24313
24318
  var APPLICATION_ONLY_RULES = [];
24314
24319
  var LIBRARY_IMPORT_POLICY = ["error", {
@@ -38,7 +38,7 @@ var import_node_os = require("os");
38
38
  var import_node_path = require("path");
39
39
  var parser = __toESM(require("@typescript-eslint/parser"), 1);
40
40
  var import_eslint = require("eslint");
41
- async function verifyRuleExamples(rule) {
41
+ async function verifyRuleExamples(rule, setup = {}) {
42
42
  const spec = rule.documentation;
43
43
  if (spec === void 0 || !spec.publicExamples.some((item) => item.outcome === "match") || !spec.publicExamples.some((item) => item.outcome === "no-match")) {
44
44
  throw new Error("rule requires documented public matching and non-matching examples");
@@ -51,6 +51,15 @@ async function verifyRuleExamples(rule) {
51
51
  await (0, import_promises.mkdir)((0, import_node_path.dirname)(path), { recursive: true });
52
52
  await (0, import_promises.writeFile)(path, file.source);
53
53
  }
54
+ for (const dependency of example.installedDependencies ?? []) {
55
+ if (setup.installedDependencyRoot === void 0) throw new Error(`${example.id}: explicit installed dependency root is required`);
56
+ const packageFile = fixturePath((0, import_node_path.resolve)(setup.installedDependencyRoot), `node_modules/${dependency.module}/package.json`);
57
+ const metadata = JSON.parse(await (0, import_promises.readFile)(packageFile, "utf8"));
58
+ if (typeof metadata !== "object" || metadata === null || !("name" in metadata) || !("version" in metadata) || metadata.name !== dependency.module || metadata.version !== dependency.version) throw new Error(`${example.id}: installed dependency identity/version mismatch for ${dependency.module}`);
59
+ const destination = fixturePath(root, `node_modules/${dependency.module}`);
60
+ await (0, import_promises.mkdir)((0, import_node_path.dirname)(destination), { recursive: true });
61
+ await (0, import_promises.symlink)((0, import_node_path.dirname)(packageFile), destination, process.platform === "win32" ? "junction" : "dir");
62
+ }
54
63
  const tsconfig = (0, import_node_path.join)(root, "tsconfig.json");
55
64
  if (!example.files.some((file) => file.path === "tsconfig.json")) {
56
65
  await (0, import_promises.writeFile)(tsconfig, JSON.stringify({ compilerOptions: {
@@ -68,10 +77,11 @@ async function verifyRuleExamples(rule) {
68
77
  files: ["**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs}"],
69
78
  languageOptions: { parser, parserOptions: { project: tsconfig, tsconfigRootDir: root } },
70
79
  plugins: { "@sarj": { rules: { [spec.ruleId]: rule } } },
71
- rules: { [ruleId]: ["error", ...rule.defaultOptions ?? []] }
80
+ rules: { [ruleId]: ["error", ...example.ruleOptions ?? rule.defaultOptions ?? []] }
72
81
  };
73
82
  await verifyExample(new import_eslint.Linter({ cwd: root }), config, example, root, ruleId);
74
83
  } finally {
84
+ parser.clearCaches();
75
85
  await (0, import_promises.rm)(root, { recursive: true, force: true });
76
86
  }
77
87
  }
@@ -1,7 +1,9 @@
1
- import { D as DocumentedRule } from './_docs-XCw_6XV9.cjs';
1
+ import { D as DocumentedRule } from './_docs-B9LZ5Out.cjs';
2
2
  import '@typescript-eslint/utils';
3
3
 
4
4
  /** Execute all authored examples, including private regressions, in isolated projects. */
5
- declare function verifyRuleExamples<Options extends readonly unknown[], MessageIds extends string>(rule: DocumentedRule<Options, MessageIds>): Promise<number>;
5
+ declare function verifyRuleExamples<Options extends readonly unknown[], MessageIds extends string>(rule: DocumentedRule<Options, MessageIds>, setup?: {
6
+ readonly installedDependencyRoot?: string;
7
+ }): Promise<number>;
6
8
 
7
9
  export { verifyRuleExamples };
@@ -1,7 +1,9 @@
1
- import { D as DocumentedRule } from './_docs-XCw_6XV9.js';
1
+ import { D as DocumentedRule } from './_docs-B9LZ5Out.js';
2
2
  import '@typescript-eslint/utils';
3
3
 
4
4
  /** Execute all authored examples, including private regressions, in isolated projects. */
5
- declare function verifyRuleExamples<Options extends readonly unknown[], MessageIds extends string>(rule: DocumentedRule<Options, MessageIds>): Promise<number>;
5
+ declare function verifyRuleExamples<Options extends readonly unknown[], MessageIds extends string>(rule: DocumentedRule<Options, MessageIds>, setup?: {
6
+ readonly installedDependencyRoot?: string;
7
+ }): Promise<number>;
6
8
 
7
9
  export { verifyRuleExamples };
@@ -1,10 +1,10 @@
1
1
  // src/verify-rule-examples.ts
2
- import { mkdtemp, mkdir, rm, writeFile } from "fs/promises";
2
+ import { mkdtemp, mkdir, rm, writeFile, readFile, symlink } from "fs/promises";
3
3
  import { tmpdir } from "os";
4
4
  import { dirname, join, resolve, sep } from "path";
5
5
  import * as parser from "@typescript-eslint/parser";
6
6
  import { Linter } from "eslint";
7
- async function verifyRuleExamples(rule) {
7
+ async function verifyRuleExamples(rule, setup = {}) {
8
8
  const spec = rule.documentation;
9
9
  if (spec === void 0 || !spec.publicExamples.some((item) => item.outcome === "match") || !spec.publicExamples.some((item) => item.outcome === "no-match")) {
10
10
  throw new Error("rule requires documented public matching and non-matching examples");
@@ -17,6 +17,15 @@ async function verifyRuleExamples(rule) {
17
17
  await mkdir(dirname(path), { recursive: true });
18
18
  await writeFile(path, file.source);
19
19
  }
20
+ for (const dependency of example.installedDependencies ?? []) {
21
+ if (setup.installedDependencyRoot === void 0) throw new Error(`${example.id}: explicit installed dependency root is required`);
22
+ const packageFile = fixturePath(resolve(setup.installedDependencyRoot), `node_modules/${dependency.module}/package.json`);
23
+ const metadata = JSON.parse(await readFile(packageFile, "utf8"));
24
+ if (typeof metadata !== "object" || metadata === null || !("name" in metadata) || !("version" in metadata) || metadata.name !== dependency.module || metadata.version !== dependency.version) throw new Error(`${example.id}: installed dependency identity/version mismatch for ${dependency.module}`);
25
+ const destination = fixturePath(root, `node_modules/${dependency.module}`);
26
+ await mkdir(dirname(destination), { recursive: true });
27
+ await symlink(dirname(packageFile), destination, process.platform === "win32" ? "junction" : "dir");
28
+ }
20
29
  const tsconfig = join(root, "tsconfig.json");
21
30
  if (!example.files.some((file) => file.path === "tsconfig.json")) {
22
31
  await writeFile(tsconfig, JSON.stringify({ compilerOptions: {
@@ -34,10 +43,11 @@ async function verifyRuleExamples(rule) {
34
43
  files: ["**/*.{ts,tsx,js,jsx,mts,cts,mjs,cjs}"],
35
44
  languageOptions: { parser, parserOptions: { project: tsconfig, tsconfigRootDir: root } },
36
45
  plugins: { "@sarj": { rules: { [spec.ruleId]: rule } } },
37
- rules: { [ruleId]: ["error", ...rule.defaultOptions ?? []] }
46
+ rules: { [ruleId]: ["error", ...example.ruleOptions ?? rule.defaultOptions ?? []] }
38
47
  };
39
48
  await verifyExample(new Linter({ cwd: root }), config, example, root, ruleId);
40
49
  } finally {
50
+ parser.clearCaches();
41
51
  await rm(root, { recursive: true, force: true });
42
52
  }
43
53
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sarj/eslint-plugin",
3
- "version": "16.4.4",
3
+ "version": "16.4.5",
4
4
  "packageManager": "npm@12.1.0",
5
5
  "description": "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
6
6
  "type": "module",