@sarj/eslint-plugin 16.35.1 → 16.36.1

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/dist/index.cjs CHANGED
@@ -159,7 +159,9 @@ function nativeSpec(config, documentation) {
159
159
  throw new TypeError("rule references must use https");
160
160
  }
161
161
  const examples = [...documentation.examples ?? []];
162
- examples.forEach(validateExample);
162
+ const messageIds = Object.keys(meta2.messages).sort();
163
+ const knownMessages = new Set(messageIds);
164
+ examples.forEach((example) => validateExample(example, knownMessages));
163
165
  assertUnique(examples.map((example) => example.id), "rule example IDs");
164
166
  const publicExamples = examples.filter((example) => example.public === true);
165
167
  const scenarios = new Set(publicExamples.map((example) => example.scenarioId ?? "primary"));
@@ -170,7 +172,6 @@ function nativeSpec(config, documentation) {
170
172
  throw new TypeError(`published example scenario ${scenario} must contain both matching and non-matching cases exactly once`);
171
173
  }
172
174
  }
173
- const messageIds = Object.keys(meta2.messages).sort();
174
175
  const schema = optionsSchema(meta2.schema);
175
176
  const spec = {
176
177
  engine: "eslint",
@@ -206,7 +207,7 @@ function optionsSchema(value) {
206
207
  function isObject(value) {
207
208
  return value !== null && typeof value === "object";
208
209
  }
209
- function validateExample(example) {
210
+ function validateExample(example, messageIds) {
210
211
  if (!KEBAB_CASE.test(example.id)) {
211
212
  throw new TypeError("example ID must be lowercase kebab-case");
212
213
  }
@@ -241,6 +242,58 @@ function validateExample(example) {
241
242
  throw new TypeError("example focus path must name one example file");
242
243
  }
243
244
  assertUnique((example.fixedFiles ?? []).map((file) => file.path), "fixed example file paths");
245
+ if (example.expectedDiagnostics !== void 0) {
246
+ validateExpectedDiagnostics(example.expectedDiagnostics, example, messageIds);
247
+ }
248
+ }
249
+ function validateExpectedDiagnostics(value, example, messageIds) {
250
+ if (!Array.isArray(value) || value.length !== example.expectedCount) {
251
+ throw new TypeError(`${example.id}: expectedDiagnostics must be an array matching expectedCount`);
252
+ }
253
+ const diagnostics = value;
254
+ for (const diagnostic of diagnostics) {
255
+ validateExpectedDiagnostic(diagnostic, example.id, messageIds);
256
+ }
257
+ }
258
+ function validateExpectedDiagnostic(value, exampleId, messageIds) {
259
+ if (!isObject(value) || !("messageId" in value) || typeof value.messageId !== "string" || !messageIds.has(value.messageId) || !("message" in value) || typeof value.message !== "string" || !("location" in value) || !("automaticFix" in value) || typeof value.automaticFix !== "boolean" || !("suggestions" in value) || !Array.isArray(value.suggestions)) {
260
+ throw new TypeError(`${exampleId}: invalid expected diagnostic identity, message or delivery`);
261
+ }
262
+ assertFields(value, ["messageId", "message", "location", "automaticFix", "suggestions"], exampleId);
263
+ validateExpectedLocation(value.location, exampleId);
264
+ const suggestions = value.suggestions;
265
+ for (const suggestion of suggestions) {
266
+ validateExpectedSuggestion(suggestion, exampleId, messageIds);
267
+ }
268
+ }
269
+ function validateExpectedSuggestion(value, exampleId, messageIds) {
270
+ if (!isObject(value) || !("messageId" in value) || typeof value.messageId !== "string" || !messageIds.has(value.messageId) || !("output" in value) || typeof value.output !== "string") {
271
+ throw new TypeError(`${exampleId}: invalid expected suggestion identity or output`);
272
+ }
273
+ assertFields(value, ["messageId", "output"], exampleId);
274
+ }
275
+ function validateExpectedLocation(value, exampleId) {
276
+ if (!isObject(value) || !("line" in value) || !positiveCoordinate(value.line) || !("column" in value) || !positiveCoordinate(value.column)) {
277
+ throw new TypeError(`${exampleId}: expected diagnostic location requires positive integer coordinates`);
278
+ }
279
+ if (!("end" in value)) {
280
+ assertFields(value, ["line", "column"], exampleId);
281
+ return;
282
+ }
283
+ if (!isObject(value.end) || !("line" in value.end) || !positiveCoordinate(value.end.line) || !("column" in value.end) || !positiveCoordinate(value.end.column) || value.end.line < value.line || value.end.line === value.line && value.end.column < value.column) {
284
+ throw new TypeError(`${exampleId}: expected diagnostic end point must be complete and ordered`);
285
+ }
286
+ assertFields(value.end, ["line", "column"], exampleId);
287
+ assertFields(value, ["line", "column", "end"], exampleId);
288
+ }
289
+ function positiveCoordinate(value) {
290
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
291
+ }
292
+ function assertFields(value, expected, exampleId) {
293
+ const fields2 = Object.keys(value);
294
+ if (fields2.length !== expected.length || fields2.some((field) => !expected.includes(field))) {
295
+ throw new TypeError(`${exampleId}: unexpected or missing diagnostic expectation fields`);
296
+ }
244
297
  }
245
298
  function assertSafeRelativePath(path, label) {
246
299
  if (path.length === 0 || path.startsWith("/") || path.startsWith("\\") || /^[A-Za-z]:[\\/]/u.test(path) || path.split(/[\\/]/u).includes("..")) {
@@ -2898,6 +2951,7 @@ function sourceFacts(source, analysis) {
2898
2951
  if (reflectiveMember(node, analysis)) unsafe = true;
2899
2952
  const value = identity(node, analysis);
2900
2953
  if (value === "incomplete" || value === "dynamic" || protectedIdentity(value) && !containedUse(node)) unsafe = true;
2954
+ if (unsafe) break;
2901
2955
  }
2902
2956
  return { unsafe, imports, jsx };
2903
2957
  }
@@ -3900,7 +3954,7 @@ function isSearchParamReceiver(call, services) {
3900
3954
  // package.json
3901
3955
  var package_default = {
3902
3956
  name: "@sarj/eslint-plugin",
3903
- version: "16.35.1",
3957
+ version: "16.36.1",
3904
3958
  packageManager: "npm@12.2.1",
3905
3959
  description: "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
3906
3960
  type: "module",
@@ -17906,7 +17960,23 @@ var NO_RESTRICTED_LIBRARY_LOAD_DOCUMENTATION = {
17906
17960
  examples: [
17907
17961
  { id: "configured-replacement", title: "Use the configured library replacement", outcome: "no-match", files: [{ path: "src/client.ts", source: "import ky from 'ky'; const client = ky;" }], focusPath: "src/client.ts", expectedCount: 0, public: true, ruleOptions: [{ libraries: [{ id: "LIB101", module: "axios", replacement: "Ky" }] }] },
17908
17962
  { 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" }] }] },
17909
- { id: "static-import-owned-upstream", title: "Leave static restrictions to the owning import rule", outcome: "no-match", files: [{ path: "src/client.ts", source: "import axios from 'axios';" }], focusPath: "src/client.ts", expectedCount: 0, ruleOptions: [{ libraries: [{ id: "LIB101", module: "axios", replacement: "Ky" }] }] }
17963
+ { id: "static-import-owned-upstream", title: "Leave static restrictions to the owning import rule", outcome: "no-match", files: [{ path: "src/client.ts", source: "import axios from 'axios';" }], focusPath: "src/client.ts", expectedCount: 0, ruleOptions: [{ libraries: [{ id: "LIB101", module: "axios", replacement: "Ky" }] }] },
17964
+ {
17965
+ id: "checked-runtime-load",
17966
+ title: "Identify the exact restricted runtime argument",
17967
+ outcome: "match",
17968
+ files: [{ path: "src/client.ts", source: "const client = require('axios');" }],
17969
+ focusPath: "src/client.ts",
17970
+ expectedCount: 1,
17971
+ ruleOptions: [{ libraries: [{ id: "LIB101", module: "axios", replacement: "Ky" }] }],
17972
+ expectedDiagnostics: [{
17973
+ messageId: "restrictedLibraryLoad",
17974
+ message: "LIB101: Replace this runtime dependency reference to axios with Ky.",
17975
+ location: { line: 1, column: 24, end: { line: 1, column: 31 } },
17976
+ automaticFix: false,
17977
+ suggestions: []
17978
+ }]
17979
+ }
17910
17980
  ]
17911
17981
  };
17912
17982
  function staticModule(node) {
@@ -27266,6 +27336,16 @@ var PREFER_NATIVE_RANDOM_UUID_DOCUMENTATION = {
27266
27336
  ],
27267
27337
  focusPath: "src/ids.ts",
27268
27338
  expectedCount: 1,
27339
+ expectedDiagnostics: [{
27340
+ messageId: "preferNative",
27341
+ message: "Where supported by the deployment runtime, prefer native `globalThis.crypto.randomUUID()` over the `uuid` package for UUID v4.",
27342
+ location: { line: 1, column: 175, end: { line: 1, column: 179 } },
27343
+ automaticFix: true,
27344
+ suggestions: [{
27345
+ messageId: "replaceWithNative",
27346
+ output: "import { v4, NIL } from 'uuid'; const nativeUuid = crypto.randomUUID.bind(crypto); function nativeId(): string { return nativeUuid(); } function packageId(): string { return globalThis.crypto.randomUUID(); } export function ids(): string[] { return [nativeId(), packageId(), NIL]; }"
27347
+ }]
27348
+ }],
27269
27349
  fixedFiles: [
27270
27350
  {
27271
27351
  path: "src/ids.ts",
@@ -27273,6 +27353,24 @@ var PREFER_NATIVE_RANDOM_UUID_DOCUMENTATION = {
27273
27353
  }
27274
27354
  ],
27275
27355
  public: false
27356
+ },
27357
+ {
27358
+ id: "uuid-v4-suggestion-only",
27359
+ title: "Keep the unproven native replacement as a suggestion",
27360
+ outcome: "match",
27361
+ files: [{ path: "src/id.ts", source: "import { v4 } from 'uuid'; const id = v4();" }],
27362
+ focusPath: "src/id.ts",
27363
+ expectedCount: 1,
27364
+ expectedDiagnostics: [{
27365
+ messageId: "preferNative",
27366
+ message: "Where supported by the deployment runtime, prefer native `globalThis.crypto.randomUUID()` over the `uuid` package for UUID v4.",
27367
+ location: { line: 1, column: 39, end: { line: 1, column: 43 } },
27368
+ automaticFix: false,
27369
+ suggestions: [{
27370
+ messageId: "replaceWithNative",
27371
+ output: "import { v4 } from 'uuid'; const id = globalThis.crypto.randomUUID();"
27372
+ }]
27373
+ }]
27276
27374
  }
27277
27375
  ]
27278
27376
  };
@@ -28321,7 +28419,35 @@ var PREFER_NULLISH_FILTER_PREDICATE_DOCUMENTATION = {
28321
28419
  files: [{ path: "src/autofix-example.ts", source: "const present = [{ id: 'kept' }, null].filter(Boolean);" }],
28322
28420
  fixedFiles: [{ path: "src/autofix-example.ts", source: "const present = [{ id: 'kept' }, null].filter((value) => value !== null && value !== undefined);" }],
28323
28421
  focusPath: "src/autofix-example.ts",
28324
- expectedCount: 1
28422
+ expectedCount: 1,
28423
+ expectedDiagnostics: [{
28424
+ messageId: "preferNullishPredicate",
28425
+ message: "This built-in array contains only nullish or provably truthy values, so `filter(Boolean)` preserves runtime values but loses nullish narrowing. Use an explicit nullish predicate.",
28426
+ location: { line: 1, column: 47, end: { line: 1, column: 54 } },
28427
+ automaticFix: true,
28428
+ suggestions: [{
28429
+ messageId: "replaceBoolean",
28430
+ output: "const present = [{ id: 'kept' }, null].filter((value) => value !== null && value !== undefined);"
28431
+ }]
28432
+ }]
28433
+ },
28434
+ {
28435
+ id: "nonfresh-suggestion-only",
28436
+ title: "Suggest a nullish predicate without assuming a fresh receiver",
28437
+ outcome: "match",
28438
+ files: [{ path: "src/users.ts", source: "declare const users: readonly ({ id: string } | null)[];\nconst present = users.filter(Boolean);" }],
28439
+ focusPath: "src/users.ts",
28440
+ expectedCount: 1,
28441
+ expectedDiagnostics: [{
28442
+ messageId: "preferNullishPredicate",
28443
+ message: "This built-in array contains only nullish or provably truthy values, so `filter(Boolean)` preserves runtime values but loses nullish narrowing. Use an explicit nullish predicate.",
28444
+ location: { line: 2, column: 30, end: { line: 2, column: 37 } },
28445
+ automaticFix: false,
28446
+ suggestions: [{
28447
+ messageId: "replaceBoolean",
28448
+ output: "declare const users: readonly ({ id: string } | null)[];\nconst present = users.filter((value) => value !== null && value !== undefined);"
28449
+ }]
28450
+ }]
28325
28451
  }
28326
28452
  ]
28327
28453
  };
@@ -35864,335 +35990,214 @@ var LIBRARY_IMPORT_POLICY = ["error", {
35864
35990
  paths: LIBRARY_POLICY.map(({ module: module2, note }) => ({ name: module2, message: note })),
35865
35991
  patterns: LIBRARY_POLICY.map(({ module: module2, note }) => ({ group: [`${module2}/*`], message: note }))
35866
35992
  }];
35867
- var ADVISORY_RULES = [
35868
- "@sarj/excessive-commentary",
35869
- "@sarj/no-bespoke-api-case-conversion",
35870
- "@sarj/no-boolean-selector-parameter",
35871
- "@sarj/no-cors-wildcard-with-credentials",
35872
- "@sarj/no-credential-in-browser-storage",
35873
- "@sarj/no-discarded-validation-result",
35874
- "@sarj/no-exception-text-in-5xx-response",
35875
- "@sarj/no-excess-jsx-props",
35876
- "@sarj/no-generic-json-parser",
35877
- "@sarj/no-mutating-container-transform",
35878
- "@sarj/no-mutating-input-with-result",
35879
- "@sarj/no-negative-only-http-status-assertion",
35880
- "@sarj/no-numeric-search-param-coercion",
35881
- "@sarj/no-redundant-consumer-union",
35882
- "@sarj/no-redundant-local-alias",
35883
- "@sarj/no-restated-comment",
35884
- "@sarj/no-restated-jsdoc",
35885
- "@sarj/no-return-disposed-resource",
35886
- "@sarj/no-test-comments",
35887
- "@sarj/prefer-dependency-interface",
35888
- "@sarj/prefer-discriminated-union",
35889
- "@sarj/prefer-millisecond-control-duration-schema",
35890
- "@sarj/prefer-minimal-parameter-contract",
35891
- "@sarj/prefer-module-level-refined-schema",
35892
- "@sarj/prefer-native-fetch-in-server-actions",
35893
- "@sarj/prefer-node-crypto-hash",
35894
- "@sarj/prefer-node-fs-promises",
35895
- "@sarj/prefer-shared-zod-enum",
35896
- "@sarj/prefer-test-fixture-reuse",
35897
- "@sarj/prefer-whole-object-assertion",
35898
- "@sarj/prefer-zod-parse-output-type",
35899
- "@sarj/production-derived-test-cases",
35900
- "@sarj/require-constrained-schema-integer",
35901
- "@sarj/require-jwt-lifetime",
35902
- "@sarj/require-sql-access-class"
35903
- ];
35904
- var RECOMMENDED_RULES = {
35905
- "@sarj/no-excess-jsx-props": "warn",
35906
- "@sarj/no-redundant-consumer-union": "warn",
35907
- "@sarj/prefer-minimal-parameter-contract": "warn",
35908
- "@sarj/named-child-schema-type": "error",
35909
- "@sarj/no-conditional-empty-object-spread": "error",
35910
- "@sarj/prefer-typed-reflection": "error",
35911
- "@sarj/no-broad-return-type": "error",
35912
- "@sarj/no-reduce-accumulator-copy": "error",
35913
- "@sarj/no-known-value-widening": "error",
35914
- "@sarj/no-invalid-typed-mutation": "error",
35915
- "@sarj/no-contradictory-type-predicate": "error",
35916
- "@sarj/no-partial-type-predicate": "error",
35917
- "@sarj/no-boolean-selector-parameter": "warn",
35918
- "@sarj/no-invalid-zod-custom-parse": "error",
35919
- "@sarj/no-contradictory-overload-return": "error",
35920
- "@sarj/require-button-accessible-name": "error",
35921
- "@sarj/require-camelcase-properties": "error",
35922
- "@sarj/require-svg-accessible-name": "error",
35923
- "@sarj/prefer-logical-tailwind-utilities": ["error", { enabled: false }],
35924
- "@sarj/no-unlocalized-toast": ["error", { enabled: false }],
35925
- "@sarj/no-unlocalized-jsx-attributes": ["error", { enabled: false }],
35926
- "@sarj/no-unlocalized-jsx-text": ["error", { enabled: false }],
35927
- "no-restricted-imports": LIBRARY_IMPORT_POLICY,
35928
- "@sarj/no-restricted-library-load": ["error", { libraries: LIBRARY_POLICY }],
35929
- "@sarj/no-redundant-local-alias": "warn",
35930
- "@sarj/prefer-test-fixture-reuse": "warn",
35931
- "@sarj/no-negative-only-http-status-assertion": "warn",
35932
- "@sarj/no-mutating-input-with-result": "warn",
35933
- "@sarj/no-return-disposed-resource": "warn",
35934
- "@sarj/no-discarded-validation-result": "warn",
35935
- "@sarj/require-jwt-lifetime": "warn",
35936
- "@sarj/prefer-dependency-interface": "warn",
35937
- "@sarj/no-generic-json-parser": "warn",
35938
- "@sarj/require-constrained-schema-integer": "warn",
35939
- "@sarj/production-derived-test-cases": "warn",
35940
- "@sarj/no-test-comments": "warn",
35941
- "@sarj/no-mutating-container-transform": "warn",
35942
- "@sarj/prefer-native-random-uuid": "error",
35943
- "@sarj/prefer-shadcn-primitives": "error",
35944
- "@sarj/excessive-commentary": "warn",
35945
- "@sarj/no-excessive-cognitive-complexity": "error",
35946
- "@sarj/interface-contract-members-private": "error",
35947
- "@sarj/iac-source-coupled-test": "error",
35948
- "@sarj/duplicate-test-body": "error",
35949
- "@sarj/enforce-file-structure": "error",
35950
- "@sarj/no-client-side-data-fetching": "error",
35951
- "@sarj/no-comment-cruft": "error",
35952
- "@sarj/no-cors-wildcard-with-credentials": "warn",
35953
- "@sarj/no-dynamic-sql": "error",
35954
- "@sarj/no-fat-try-blocks": ["error", { max: 5 }],
35955
- "@sarj/no-hand-rolled-sleep": "error",
35956
- "@sarj/no-hand-rolled-spinner": "error",
35957
- "@sarj/no-insecure-random-id": "error",
35958
- "@sarj/no-exception-text-in-5xx-response": "warn",
35959
- "@sarj/no-json-stringify-error": "error",
35960
- "@sarj/no-impossible-zod-literal-bounds": "error",
35961
- "@sarj/no-in-operator-on-built-in-collections": "error",
35962
- "@sarj/no-log-only-catch": "error",
35963
- "@sarj/no-bare-return-from-test-catch": "error",
35964
- "@sarj/no-bespoke-api-case-conversion": "warn",
35965
- "@sarj/no-detached-global-fetch": "error",
35966
- "@sarj/no-json-stringify-object-equality": "error",
35967
- "@sarj/no-dangerously-allow-svg": "error",
35968
- "@sarj/no-credential-in-browser-storage": "warn",
35969
- "@sarj/no-numeric-search-param-coercion": "warn",
35970
- "@sarj/prefer-native-fetch-in-server-actions": "warn",
35971
- "@sarj/no-duplicate-lifecycle-refresh-listeners": "error",
35972
- "@sarj/no-long-comment": "error",
35973
- "@sarj/no-vague-suppression-description": "error",
35974
- "@sarj/no-generic-single-export-module": "error",
35975
- "@sarj/no-offset-pagination": "error",
35976
- "@sarj/no-positional-tuple-return": "error",
35977
- "@sarj/no-production-browser-source-maps": "error",
35978
- "@sarj/no-repeated-string-literal": "error",
35979
- "@sarj/no-redundant-optional-array-default": "error",
35980
- "@sarj/no-router-refresh-polling": "error",
35981
- "@sarj/no-restated-comment": "warn",
35982
- "@sarj/no-restated-jsdoc": "warn",
35983
- "@sarj/no-secret-in-log": "error",
35984
- "@sarj/no-server-env-in-client-component": "error",
35985
- "@sarj/no-select-star": "error",
35986
- "@sarj/no-sentinel-return-on-catch": "error",
35987
- "@sarj/no-silent-promise-catch": "error",
35988
- "@sarj/no-sleep-in-test-body": "error",
35989
- "@sarj/no-string-concat-in-loop": "error",
35990
- "@sarj/no-tautological-expect": "error",
35991
- "@sarj/no-duplicate-test-case": "error",
35992
- "@sarj/no-typed-doc-sections": "error",
35993
- "@sarj/no-trailing-value-narration": "error",
35994
- "@sarj/no-declaration-comment-wall": "error",
35995
- "@sarj/no-union-in-comment": "error",
35996
- "@sarj/no-type-member-comment-wall": "error",
35997
- "@sarj/no-unnecessary-use-client": "error",
35998
- "@sarj/no-unsafe-mock-casting": "error",
35999
- "@sarj/no-unsafe-test-double-cast": "error",
36000
- "@sarj/no-first-party-module-mock": "error",
36001
- "@sarj/no-zod-native-enum": "error",
36002
- "@sarj/test-loops-over-literal-cases": "error",
36003
- "@sarj/prefer-constant-time-secret-compare": "error",
36004
- "@sarj/prefer-ecmascript-private-members": "error",
36005
- "@sarj/prefer-discriminated-union": "warn",
36006
- "@sarj/prefer-input-group-search": "error",
36007
- "@sarj/prefer-millisecond-control-duration-schema": "warn",
36008
- "@sarj/prefer-immutable-module-constant": "error",
36009
- "@sarj/prefer-module-level-constant": "error",
36010
- "@sarj/prefer-module-level-schema": "error",
36011
- "@sarj/prefer-module-level-refined-schema": "warn",
36012
- "@sarj/prefer-multi-value-zod-literal": ["error", { zodMajorVersion: 4 }],
36013
- "@sarj/prefer-named-callback-domain": "error",
36014
- "@sarj/prefer-nominal-id-types": "error",
36015
- "@sarj/prefer-named-complex-return-type": "error",
36016
- "@sarj/prefer-node-crypto-hash": "warn",
36017
- "@sarj/prefer-node-fs-promises": "warn",
36018
- "@sarj/prefer-non-nullable-collection": "error",
36019
- "@sarj/prefer-nullish-filter-predicate": "error",
36020
- "@sarj/prefer-await-in-async-return": "error",
36021
- "@sarj/prefer-schema-for-api-payload": "error",
36022
- "@sarj/prefer-shared-zod-enum": "warn",
36023
- "@sarj/prefer-switch-for-repeated-equality": "error",
36024
- "@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
36025
- "@sarj/prefer-server-actions": "error",
36026
- "@sarj/prefer-whole-object-assertion": "warn",
36027
- "@sarj/repeated-static-call-cases": "error",
36028
- "@sarj/prefer-zod-infer": "error",
36029
- "@sarj/prefer-zod-parse-output-type": "warn",
36030
- "@sarj/require-assert-never": "error",
36031
- "@sarj/require-fetch-timeout": "error",
36032
- "@sarj/require-explicit-contract-implementation": "error",
36033
- "@sarj/require-explicit-service-contract": "error",
36034
- "@sarj/require-interface-for-exported-class": "error",
36035
- "@sarj/require-port-for-service": "error",
36036
- "@sarj/require-sql-access-class": "warn",
36037
- "@sarj/require-static-next-matcher": "error",
36038
- "@sarj/require-use-form-default-values": "error",
36039
- "@sarj/require-use-server-in-actions-file": "error",
36040
- "@sarj/require-zod-form-validation": "error",
36041
- "@sarj/store-insert-requires-on-conflict": "error",
36042
- "@sarj/stepdown": "error",
36043
- "@sarj/source-coupled-test": "error",
36044
- "@sarj/sole-export-matches-filename": "error",
36045
- "@sarj/test-phase-label-comment": "error",
36046
- "@sarj/require-pascal-case-zod-schema-name": "error"
36047
- };
36048
- var STRICT_RULES = {
36049
- "@sarj/no-discarded-validation-result": "warn",
36050
- "@sarj/no-generic-json-parser": "warn",
36051
- "@sarj/no-mutating-container-transform": "warn",
36052
- "@sarj/no-mutating-input-with-result": "warn",
36053
- "@sarj/no-negative-only-http-status-assertion": "warn",
36054
- "@sarj/no-redundant-local-alias": "warn",
36055
- "@sarj/no-return-disposed-resource": "warn",
36056
- "@sarj/no-test-comments": "warn",
36057
- "@sarj/prefer-dependency-interface": "warn",
36058
- "@sarj/prefer-test-fixture-reuse": "warn",
36059
- "@sarj/production-derived-test-cases": "warn",
36060
- "@sarj/require-constrained-schema-integer": "warn",
36061
- "@sarj/require-jwt-lifetime": "warn",
36062
- "@sarj/no-excess-jsx-props": "warn",
36063
- "@sarj/no-redundant-consumer-union": "warn",
36064
- "@sarj/prefer-minimal-parameter-contract": "warn",
36065
- "@sarj/named-child-schema-type": "error",
36066
- "@sarj/no-conditional-empty-object-spread": "error",
36067
- "@sarj/prefer-typed-reflection": "error",
36068
- "@sarj/no-broad-return-type": "error",
36069
- "@sarj/no-reduce-accumulator-copy": "error",
36070
- "@sarj/no-known-value-widening": "error",
36071
- "@sarj/no-invalid-typed-mutation": "error",
36072
- "@sarj/no-contradictory-type-predicate": "error",
36073
- "@sarj/no-partial-type-predicate": "error",
36074
- "@sarj/no-boolean-selector-parameter": "warn",
36075
- "@sarj/no-invalid-zod-custom-parse": "error",
36076
- "@sarj/no-contradictory-overload-return": "error",
36077
- "@sarj/require-button-accessible-name": "error",
36078
- "@sarj/require-camelcase-properties": "error",
36079
- "@sarj/require-svg-accessible-name": "error",
36080
- "@sarj/prefer-logical-tailwind-utilities": ["error", { enabled: false }],
36081
- "@sarj/no-unlocalized-toast": ["error", { enabled: false }],
36082
- "@sarj/no-unlocalized-jsx-attributes": ["error", { enabled: false }],
36083
- "@sarj/no-unlocalized-jsx-text": ["error", { enabled: false }],
36084
- "no-restricted-imports": LIBRARY_IMPORT_POLICY,
36085
- "@sarj/no-restricted-library-load": ["error", { libraries: LIBRARY_POLICY }],
36086
- "@sarj/prefer-native-random-uuid": "error",
36087
- "@sarj/prefer-shadcn-primitives": "error",
36088
- "@sarj/excessive-commentary": "warn",
36089
- "@sarj/no-excessive-cognitive-complexity": "error",
36090
- "@sarj/interface-contract-members-private": "error",
36091
- "@sarj/iac-source-coupled-test": "error",
36092
- "@sarj/duplicate-test-body": "error",
36093
- "@sarj/enforce-file-structure": "error",
36094
- "@sarj/no-client-side-data-fetching": "error",
36095
- "@sarj/no-comment-cruft": "error",
36096
- "@sarj/no-cors-wildcard-with-credentials": "warn",
36097
- "@sarj/no-dynamic-sql": "error",
36098
- "@sarj/no-enum": "error",
36099
- "@sarj/no-fat-try-blocks": ["error", { max: 5 }],
36100
- "@sarj/no-hand-rolled-sleep": "error",
36101
- "@sarj/no-hand-rolled-spinner": "error",
36102
- "@sarj/no-insecure-random-id": "error",
36103
- "@sarj/no-exception-text-in-5xx-response": "warn",
36104
- "@sarj/no-json-stringify-error": "error",
36105
- "@sarj/no-impossible-zod-literal-bounds": "error",
36106
- "@sarj/no-in-operator-on-built-in-collections": "error",
36107
- "@sarj/no-log-only-catch": "error",
36108
- "@sarj/no-bare-return-from-test-catch": "error",
36109
- "@sarj/no-bespoke-api-case-conversion": "warn",
36110
- "@sarj/no-detached-global-fetch": "error",
36111
- "@sarj/no-json-stringify-object-equality": "error",
36112
- "@sarj/no-dangerously-allow-svg": "error",
36113
- "@sarj/no-credential-in-browser-storage": "warn",
36114
- "@sarj/no-numeric-search-param-coercion": "warn",
36115
- "@sarj/prefer-native-fetch-in-server-actions": "warn",
36116
- "@sarj/no-duplicate-lifecycle-refresh-listeners": "error",
36117
- "@sarj/no-long-comment": "error",
36118
- "@sarj/no-vague-suppression-description": "error",
36119
- "@sarj/no-generic-single-export-module": "error",
36120
- "@sarj/no-offset-pagination": "error",
36121
- "@sarj/no-positional-tuple-return": "error",
36122
- "@sarj/no-production-browser-source-maps": "error",
36123
- "@sarj/no-raw-env": "error",
36124
- "@sarj/no-raw-fetch-outside-clients": "error",
36125
- "@sarj/no-repeated-string-literal": "error",
36126
- "@sarj/no-redundant-optional-array-default": "error",
36127
- "@sarj/no-router-refresh-polling": "error",
36128
- "@sarj/no-restated-comment": "warn",
36129
- "@sarj/no-restated-jsdoc": "warn",
36130
- "@sarj/no-secret-in-log": "error",
36131
- "@sarj/no-server-env-in-client-component": "error",
36132
- "@sarj/no-select-star": "error",
36133
- "@sarj/no-sentinel-return-on-catch": "error",
36134
- "@sarj/no-silent-promise-catch": "error",
36135
- "@sarj/no-sleep-in-test-body": "error",
36136
- "@sarj/no-storage-in-stateless-modules": "error",
36137
- "@sarj/no-string-concat-in-loop": "error",
36138
- "@sarj/no-tautological-expect": "error",
36139
- "@sarj/no-duplicate-test-case": "error",
36140
- "@sarj/no-typed-doc-sections": "error",
36141
- "@sarj/no-trailing-value-narration": "error",
36142
- "@sarj/no-declaration-comment-wall": "error",
36143
- "@sarj/no-union-in-comment": "error",
36144
- "@sarj/no-type-member-comment-wall": "error",
36145
- "@sarj/no-unnecessary-use-client": "error",
36146
- "@sarj/no-unsafe-mock-casting": "error",
36147
- "@sarj/no-unsafe-test-double-cast": "error",
36148
- "@sarj/no-first-party-module-mock": "error",
36149
- "@sarj/no-zod-native-enum": "error",
36150
- "@sarj/test-loops-over-literal-cases": "error",
36151
- "@sarj/prefer-constant-time-secret-compare": "error",
36152
- "@sarj/prefer-ecmascript-private-members": "error",
36153
- "@sarj/prefer-discriminated-union": "warn",
36154
- "@sarj/prefer-input-group-search": "error",
36155
- "@sarj/prefer-millisecond-control-duration-schema": "warn",
36156
- "@sarj/prefer-immutable-module-constant": "error",
36157
- "@sarj/prefer-module-level-constant": "error",
36158
- "@sarj/prefer-module-level-schema": "error",
36159
- "@sarj/prefer-module-level-refined-schema": "warn",
36160
- "@sarj/prefer-multi-value-zod-literal": ["error", { zodMajorVersion: 4 }],
36161
- "@sarj/prefer-named-callback-domain": "error",
36162
- "@sarj/prefer-nominal-id-types": "error",
36163
- "@sarj/prefer-named-complex-return-type": "error",
36164
- "@sarj/prefer-node-crypto-hash": "warn",
36165
- "@sarj/prefer-node-fs-promises": "warn",
36166
- "@sarj/prefer-non-nullable-collection": "error",
36167
- "@sarj/prefer-nullish-filter-predicate": "error",
36168
- "@sarj/prefer-await-in-async-return": "error",
36169
- "@sarj/prefer-schema-for-api-payload": "error",
36170
- "@sarj/prefer-shared-zod-enum": "warn",
36171
- "@sarj/prefer-switch-for-repeated-equality": "error",
36172
- "@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
36173
- "@sarj/prefer-server-actions": "error",
36174
- "@sarj/prefer-whole-object-assertion": "warn",
36175
- "@sarj/repeated-static-call-cases": "error",
36176
- "@sarj/prefer-zod-infer": "error",
36177
- "@sarj/prefer-zod-parse-output-type": "warn",
36178
- "@sarj/require-assert-never": "error",
36179
- "@sarj/require-fetch-timeout": "error",
36180
- "@sarj/require-explicit-contract-implementation": "error",
36181
- "@sarj/require-explicit-service-contract": "error",
36182
- "@sarj/require-interface-for-exported-class": "error",
36183
- "@sarj/require-port-for-service": "error",
36184
- "@sarj/require-sql-access-class": "warn",
36185
- "@sarj/require-static-next-matcher": "error",
36186
- "@sarj/require-use-form-default-values": "error",
36187
- "@sarj/require-use-server-in-actions-file": "error",
36188
- "@sarj/require-zod-form-validation": "error",
36189
- "@sarj/store-insert-requires-on-conflict": "error",
36190
- "@sarj/stepdown": "error",
36191
- "@sarj/source-coupled-test": "error",
36192
- "@sarj/sole-export-matches-filename": "error",
36193
- "@sarj/test-phase-label-comment": "error",
36194
- "@sarj/require-pascal-case-zod-schema-name": "error"
35993
+ var RULE_POLICY = {
35994
+ "@sarj/no-excess-jsx-props": ["warn", "both"],
35995
+ "@sarj/no-redundant-consumer-union": ["warn", "both"],
35996
+ "@sarj/prefer-minimal-parameter-contract": ["warn", "both"],
35997
+ "@sarj/named-child-schema-type": ["error", "both"],
35998
+ "@sarj/no-conditional-empty-object-spread": ["error", "both"],
35999
+ "@sarj/prefer-typed-reflection": ["error", "both"],
36000
+ "@sarj/no-broad-return-type": ["error", "both"],
36001
+ "@sarj/no-reduce-accumulator-copy": ["error", "both"],
36002
+ "@sarj/no-known-value-widening": ["error", "both"],
36003
+ "@sarj/no-invalid-typed-mutation": ["error", "both"],
36004
+ "@sarj/no-contradictory-type-predicate": ["error", "both"],
36005
+ "@sarj/no-partial-type-predicate": ["error", "both"],
36006
+ "@sarj/no-boolean-selector-parameter": ["warn", "both"],
36007
+ "@sarj/no-invalid-zod-custom-parse": ["error", "both"],
36008
+ "@sarj/no-contradictory-overload-return": ["error", "both"],
36009
+ "@sarj/require-button-accessible-name": ["error", "both"],
36010
+ "@sarj/require-camelcase-properties": ["error", "both"],
36011
+ "@sarj/require-svg-accessible-name": ["error", "both"],
36012
+ "@sarj/prefer-logical-tailwind-utilities": [
36013
+ "error",
36014
+ "both",
36015
+ () => [{ enabled: false }]
36016
+ ],
36017
+ "@sarj/no-unlocalized-toast": [
36018
+ "error",
36019
+ "both",
36020
+ () => [{ enabled: false }]
36021
+ ],
36022
+ "@sarj/no-unlocalized-jsx-attributes": [
36023
+ "error",
36024
+ "both",
36025
+ () => [{ enabled: false }]
36026
+ ],
36027
+ "@sarj/no-unlocalized-jsx-text": [
36028
+ "error",
36029
+ "both",
36030
+ () => [{ enabled: false }]
36031
+ ],
36032
+ "no-restricted-imports": ["shared", "both", LIBRARY_IMPORT_POLICY],
36033
+ "@sarj/no-restricted-library-load": [
36034
+ "error",
36035
+ "both",
36036
+ () => [{ libraries: LIBRARY_POLICY }]
36037
+ ],
36038
+ "@sarj/no-redundant-local-alias": ["warn", "both", "strict-order", 5],
36039
+ "@sarj/prefer-test-fixture-reuse": ["warn", "both", "strict-order", 9],
36040
+ "@sarj/no-negative-only-http-status-assertion": ["warn", "both", "strict-order", 4],
36041
+ "@sarj/no-mutating-input-with-result": ["warn", "both", "strict-order", 3],
36042
+ "@sarj/no-return-disposed-resource": ["warn", "both", "strict-order", 6],
36043
+ "@sarj/no-discarded-validation-result": ["warn", "both", "strict-order", 0],
36044
+ "@sarj/require-jwt-lifetime": ["warn", "both", "strict-order", 12],
36045
+ "@sarj/prefer-dependency-interface": ["warn", "both", "strict-order", 8],
36046
+ "@sarj/no-generic-json-parser": ["warn", "both", "strict-order", 1],
36047
+ "@sarj/require-constrained-schema-integer": ["warn", "both", "strict-order", 11],
36048
+ "@sarj/production-derived-test-cases": ["warn", "both", "strict-order", 10],
36049
+ "@sarj/no-test-comments": ["warn", "both", "strict-order", 7],
36050
+ "@sarj/no-mutating-container-transform": ["warn", "both", "strict-order", 2],
36051
+ "@sarj/prefer-native-random-uuid": ["error", "both"],
36052
+ "@sarj/prefer-shadcn-primitives": ["error", "both"],
36053
+ "@sarj/excessive-commentary": ["warn", "both"],
36054
+ "@sarj/no-excessive-cognitive-complexity": ["error", "both"],
36055
+ "@sarj/interface-contract-members-private": ["error", "both"],
36056
+ "@sarj/iac-source-coupled-test": ["error", "both"],
36057
+ "@sarj/duplicate-test-body": ["error", "both"],
36058
+ "@sarj/enforce-file-structure": ["error", "both"],
36059
+ "@sarj/no-client-side-data-fetching": ["error", "both"],
36060
+ "@sarj/no-comment-cruft": ["error", "both"],
36061
+ "@sarj/no-cors-wildcard-with-credentials": ["warn", "both"],
36062
+ "@sarj/no-dynamic-sql": ["error", "both"],
36063
+ "@sarj/no-enum": ["error", "strict"],
36064
+ "@sarj/no-fat-try-blocks": [
36065
+ "error",
36066
+ "both",
36067
+ () => [{ max: 5 }]
36068
+ ],
36069
+ "@sarj/no-hand-rolled-sleep": ["error", "both"],
36070
+ "@sarj/no-hand-rolled-spinner": ["error", "both"],
36071
+ "@sarj/no-insecure-random-id": ["error", "both"],
36072
+ "@sarj/no-exception-text-in-5xx-response": ["warn", "both"],
36073
+ "@sarj/no-json-stringify-error": ["error", "both"],
36074
+ "@sarj/no-impossible-zod-literal-bounds": ["error", "both"],
36075
+ "@sarj/no-in-operator-on-built-in-collections": ["error", "both"],
36076
+ "@sarj/no-log-only-catch": ["error", "both"],
36077
+ "@sarj/no-bare-return-from-test-catch": ["error", "both"],
36078
+ "@sarj/no-bespoke-api-case-conversion": ["warn", "both"],
36079
+ "@sarj/no-detached-global-fetch": ["error", "both"],
36080
+ "@sarj/no-json-stringify-object-equality": ["error", "both"],
36081
+ "@sarj/no-dangerously-allow-svg": ["error", "both"],
36082
+ "@sarj/no-credential-in-browser-storage": ["warn", "both"],
36083
+ "@sarj/no-numeric-search-param-coercion": ["warn", "both"],
36084
+ "@sarj/prefer-native-fetch-in-server-actions": ["warn", "both"],
36085
+ "@sarj/no-duplicate-lifecycle-refresh-listeners": ["error", "both"],
36086
+ "@sarj/no-long-comment": ["error", "both"],
36087
+ "@sarj/no-vague-suppression-description": ["error", "both"],
36088
+ "@sarj/no-generic-single-export-module": ["error", "both"],
36089
+ "@sarj/no-offset-pagination": ["error", "both"],
36090
+ "@sarj/no-positional-tuple-return": ["error", "both"],
36091
+ "@sarj/no-production-browser-source-maps": ["error", "both"],
36092
+ "@sarj/no-raw-env": ["error", "strict"],
36093
+ "@sarj/no-raw-fetch-outside-clients": ["error", "strict"],
36094
+ "@sarj/no-repeated-string-literal": ["error", "both"],
36095
+ "@sarj/no-redundant-optional-array-default": ["error", "both"],
36096
+ "@sarj/no-router-refresh-polling": ["error", "both"],
36097
+ "@sarj/no-restated-comment": ["warn", "both"],
36098
+ "@sarj/no-restated-jsdoc": ["warn", "both"],
36099
+ "@sarj/no-secret-in-log": ["error", "both"],
36100
+ "@sarj/no-server-env-in-client-component": ["error", "both"],
36101
+ "@sarj/no-select-star": ["error", "both"],
36102
+ "@sarj/no-sentinel-return-on-catch": ["error", "both"],
36103
+ "@sarj/no-silent-promise-catch": ["error", "both"],
36104
+ "@sarj/no-sleep-in-test-body": ["error", "both"],
36105
+ "@sarj/no-storage-in-stateless-modules": ["error", "strict"],
36106
+ "@sarj/no-string-concat-in-loop": ["error", "both"],
36107
+ "@sarj/no-tautological-expect": ["error", "both"],
36108
+ "@sarj/no-duplicate-test-case": ["error", "both"],
36109
+ "@sarj/no-typed-doc-sections": ["error", "both"],
36110
+ "@sarj/no-trailing-value-narration": ["error", "both"],
36111
+ "@sarj/no-declaration-comment-wall": ["error", "both"],
36112
+ "@sarj/no-union-in-comment": ["error", "both"],
36113
+ "@sarj/no-type-member-comment-wall": ["error", "both"],
36114
+ "@sarj/no-unnecessary-use-client": ["error", "both"],
36115
+ "@sarj/no-unsafe-mock-casting": ["error", "both"],
36116
+ "@sarj/no-unsafe-test-double-cast": ["error", "both"],
36117
+ "@sarj/no-first-party-module-mock": ["error", "both"],
36118
+ "@sarj/no-zod-native-enum": ["error", "both"],
36119
+ "@sarj/test-loops-over-literal-cases": ["error", "both"],
36120
+ "@sarj/prefer-constant-time-secret-compare": ["error", "both"],
36121
+ "@sarj/prefer-ecmascript-private-members": ["error", "both"],
36122
+ "@sarj/prefer-discriminated-union": ["warn", "both"],
36123
+ "@sarj/prefer-input-group-search": ["error", "both"],
36124
+ "@sarj/prefer-millisecond-control-duration-schema": ["warn", "both"],
36125
+ "@sarj/prefer-immutable-module-constant": ["error", "both"],
36126
+ "@sarj/prefer-module-level-constant": ["error", "both"],
36127
+ "@sarj/prefer-module-level-schema": ["error", "both"],
36128
+ "@sarj/prefer-module-level-refined-schema": ["warn", "both"],
36129
+ "@sarj/prefer-multi-value-zod-literal": [
36130
+ "error",
36131
+ "both",
36132
+ () => [{ zodMajorVersion: 4 }]
36133
+ ],
36134
+ "@sarj/prefer-named-callback-domain": ["error", "both"],
36135
+ "@sarj/prefer-nominal-id-types": ["error", "both"],
36136
+ "@sarj/prefer-named-complex-return-type": ["error", "both"],
36137
+ "@sarj/prefer-node-crypto-hash": ["warn", "both"],
36138
+ "@sarj/prefer-node-fs-promises": ["warn", "both"],
36139
+ "@sarj/prefer-non-nullable-collection": ["error", "both"],
36140
+ "@sarj/prefer-nullish-filter-predicate": ["error", "both"],
36141
+ "@sarj/prefer-await-in-async-return": ["error", "both"],
36142
+ "@sarj/prefer-schema-for-api-payload": ["error", "both"],
36143
+ "@sarj/prefer-shared-zod-enum": ["warn", "both"],
36144
+ "@sarj/prefer-switch-for-repeated-equality": ["error", "both"],
36145
+ "@sarj/prefer-semantic-colors": [
36146
+ "error",
36147
+ "both",
36148
+ () => [{ requireSemanticTokens: true }]
36149
+ ],
36150
+ "@sarj/prefer-server-actions": ["error", "both"],
36151
+ "@sarj/prefer-whole-object-assertion": ["warn", "both"],
36152
+ "@sarj/repeated-static-call-cases": ["error", "both"],
36153
+ "@sarj/prefer-zod-infer": ["error", "both"],
36154
+ "@sarj/prefer-zod-parse-output-type": ["warn", "both"],
36155
+ "@sarj/require-assert-never": ["error", "both"],
36156
+ "@sarj/require-fetch-timeout": ["error", "both"],
36157
+ "@sarj/require-explicit-contract-implementation": ["error", "both"],
36158
+ "@sarj/require-explicit-service-contract": ["error", "both"],
36159
+ "@sarj/require-interface-for-exported-class": ["error", "both"],
36160
+ "@sarj/require-port-for-service": ["error", "both"],
36161
+ "@sarj/require-sql-access-class": ["warn", "both"],
36162
+ "@sarj/require-static-next-matcher": ["error", "both"],
36163
+ "@sarj/require-use-form-default-values": ["error", "both"],
36164
+ "@sarj/require-use-server-in-actions-file": ["error", "both"],
36165
+ "@sarj/require-zod-form-validation": ["error", "both"],
36166
+ "@sarj/store-insert-requires-on-conflict": ["error", "both"],
36167
+ "@sarj/stepdown": ["error", "both"],
36168
+ "@sarj/source-coupled-test": ["error", "both"],
36169
+ "@sarj/sole-export-matches-filename": ["error", "both"],
36170
+ "@sarj/test-phase-label-comment": ["error", "both"],
36171
+ "@sarj/require-pascal-case-zod-schema-name": ["error", "both"]
36195
36172
  };
36173
+ var ADVISORY_RULES = Object.keys(RULE_POLICY).filter(isAdvisoryRuleName).toSorted();
36174
+ var RECOMMENDED_RULES = presetRules("recommended");
36175
+ var STRICT_RULES = presetRules("strict");
36176
+ function isAdvisoryRuleName(name) {
36177
+ return isPolicyName(name) && RULE_POLICY[name][0] === "warn";
36178
+ }
36179
+ function isPolicyName(name) {
36180
+ return Object.hasOwn(RULE_POLICY, name);
36181
+ }
36182
+ function presetRules(preset) {
36183
+ const rows = Object.entries(RULE_POLICY).filter(([, row]) => preset === "strict" || row[1] === "both");
36184
+ if (preset === "strict") rows.sort((left, right) => strictOrder(left[1]) - strictOrder(right[1]));
36185
+ const entries = rows.map(([name, row]) => [name, policySetting(row)]);
36186
+ const result = Object.fromEntries(entries);
36187
+ const names = Object.keys(result);
36188
+ if (names.length !== entries.length || names.some((name, index) => name !== entries[index]?.[0])) {
36189
+ throw new Error("Preset projection changed its closed policy key order.");
36190
+ }
36191
+ return result;
36192
+ }
36193
+ function strictOrder(row) {
36194
+ return row.length === 4 ? row[3] : Number.MAX_SAFE_INTEGER;
36195
+ }
36196
+ function policySetting(row) {
36197
+ if (row[0] === "shared") return row[2];
36198
+ if (row.length !== 3) return row[0];
36199
+ return [row[0], ...row[2]()];
36200
+ }
36196
36201
  var PLUGIN = {
36197
36202
  meta,
36198
36203
  rules: RULES,