@sarj/eslint-plugin 16.4.5 → 16.4.7
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 +94 -50
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +94 -50
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -262,6 +262,7 @@ function deepFreeze(value) {
|
|
|
262
262
|
}
|
|
263
263
|
|
|
264
264
|
// src/rules/_paths.ts
|
|
265
|
+
var LINE_TERMINATOR_RE = /[\n\r\u2028\u2029]/u;
|
|
265
266
|
var SCRIPT_FILE_RE = /(?:^|[\\/])scripts[\\/]|\.mjs$/;
|
|
266
267
|
var STORY_FILE_RE = /\.stories\.[cm]?[jt]sx?$/i;
|
|
267
268
|
var STORY_TREE_RE = /(^|\/)stories(?:[_-][^/]*)?\//i;
|
|
@@ -311,8 +312,8 @@ function leadingCommentBodies(sourceText) {
|
|
|
311
312
|
const bodies = [];
|
|
312
313
|
let index = 0;
|
|
313
314
|
if (sourceText.startsWith("#!")) {
|
|
314
|
-
const shebangEnd = sourceText
|
|
315
|
-
index = shebangEnd ===
|
|
315
|
+
const shebangEnd = commentLineEnd(sourceText, 2);
|
|
316
|
+
index = shebangEnd === sourceText.length ? sourceText.length : shebangEnd + 1;
|
|
316
317
|
}
|
|
317
318
|
while (index < sourceText.length) {
|
|
318
319
|
while (/\s/u.test(sourceText[index] ?? "")) index++;
|
|
@@ -326,7 +327,7 @@ function leadingCommentBodies(sourceText) {
|
|
|
326
327
|
const end = sourceText.indexOf("*/", index + 2);
|
|
327
328
|
if (end === -1) break;
|
|
328
329
|
bodies.push(
|
|
329
|
-
...sourceText.slice(index + 2, end).split(
|
|
330
|
+
...sourceText.slice(index + 2, end).split(LINE_TERMINATOR_RE).map((line) => line.replace(/^\s*\*?\s?/u, "").trim()).filter((line) => line.length > 0)
|
|
330
331
|
);
|
|
331
332
|
index = end + 2;
|
|
332
333
|
continue;
|
|
@@ -345,8 +346,8 @@ function isScriptFile(filename) {
|
|
|
345
346
|
return SCRIPT_FILE_RE.test(filename);
|
|
346
347
|
}
|
|
347
348
|
function commentLineEnd(sourceText, start) {
|
|
348
|
-
const end = sourceText.
|
|
349
|
-
return end === -1 ? sourceText.length : end;
|
|
349
|
+
const end = sourceText.slice(start).search(LINE_TERMINATOR_RE);
|
|
350
|
+
return end === -1 ? sourceText.length : start + end;
|
|
350
351
|
}
|
|
351
352
|
|
|
352
353
|
// src/rules/require-explicit-contract-implementation.ts
|
|
@@ -5473,7 +5474,9 @@ var NO_ENUM_DOCUMENTATION = {
|
|
|
5473
5474
|
focusPath: "src/status.ts",
|
|
5474
5475
|
expectedCount: 1,
|
|
5475
5476
|
public: true
|
|
5476
|
-
}
|
|
5477
|
+
},
|
|
5478
|
+
{ id: "authored-after-comment", scenarioId: "native-header-boundary", title: "Keep executable authored code in scope", outcome: "match", files: [{ path: "src/status.ts", source: '// ordinary header\u2028const marker="auto-generated file"; enum Mode {Start} console.log(Mode.Start, marker);' }], focusPath: "src/status.ts", expectedCount: 1, public: true },
|
|
5479
|
+
{ id: "generated-header", scenarioId: "native-header-boundary", title: "Respect a native generated banner", outcome: "no-match", files: [{ path: "src/status.ts", source: '// auto-generated file\u2028const marker="auto-generated file"; enum Mode {Start} console.log(Mode.Start, marker);' }], focusPath: "src/status.ts", expectedCount: 0, public: true }
|
|
5477
5480
|
]
|
|
5478
5481
|
};
|
|
5479
5482
|
function matchesAnyPattern(filename, patterns) {
|
|
@@ -6833,7 +6836,9 @@ var NO_JSON_STRINGIFY_ERROR_DOCUMENTATION = {
|
|
|
6833
6836
|
limitations: ["The rule uses stable local catch bindings and unshadowed built-in constructors, not runtime type information. Custom replacers are left to their serializer contract; a catch value is not guaranteed to be an Error."],
|
|
6834
6837
|
examples: [
|
|
6835
6838
|
{ id: "explicit-error-message", title: "Narrow an unknown catch value before selecting fields", outcome: "no-match", files: [{ path: "src/report.ts", source: "try { f(); } catch (err) { JSON.stringify({ error: err instanceof Error ? err.message : String(err) }); }" }], focusPath: "src/report.ts", expectedCount: 0, public: true },
|
|
6836
|
-
{ id: "stringified-error", title: "Do not stringify an Error object", outcome: "match", files: [{ path: "src/report.ts", source: "try { f(); } catch (err) { JSON.stringify({ error: err }); }" }], focusPath: "src/report.ts", expectedCount: 1, public: true }
|
|
6839
|
+
{ id: "stringified-error", title: "Do not stringify an Error object", outcome: "match", files: [{ path: "src/report.ts", source: "try { f(); } catch (err) { JSON.stringify({ error: err }); }" }], focusPath: "src/report.ts", expectedCount: 1, public: true },
|
|
6840
|
+
{ id: "shadowed-error-binding", scenarioId: "binding-provenance", title: "Keep native binding provenance", outcome: "match", files: [{ path: "src/error.ts", source: 'function probe(){try{throw {id:1};}catch(err){if(err instanceof Error)return err.message;{const err=new Error("lost");return JSON.stringify(err);}}}\nconsole.log(probe());' }], focusPath: "src/error.ts", expectedCount: 1, public: true },
|
|
6841
|
+
{ id: "escaped-fallback-binding", scenarioId: "binding-provenance", title: "Keep native binding provenance", outcome: "no-match", files: [{ path: "src/error.ts", source: "function probe(){try{throw {id:1};}catch(err){if(err instanceof Error)return err.message;return JSON.stringify(\\u0065rr);}}\nconsole.log(probe());" }], focusPath: "src/error.ts", expectedCount: 0, public: true }
|
|
6837
6842
|
]
|
|
6838
6843
|
};
|
|
6839
6844
|
var SAFE_STRING_PROPS = /* @__PURE__ */ new Set(["message", "stack", "name"]);
|
|
@@ -6863,25 +6868,25 @@ var BUILTIN_ERROR_CONSTRUCTORS = /* @__PURE__ */ new Set([
|
|
|
6863
6868
|
"TypeError",
|
|
6864
6869
|
"URIError"
|
|
6865
6870
|
]);
|
|
6866
|
-
function identifierIsProvenError(identifier,
|
|
6867
|
-
const variable = import_utils41.ASTUtils.findVariable(
|
|
6871
|
+
function identifierIsProvenError(identifier, sourceCode) {
|
|
6872
|
+
const variable = import_utils41.ASTUtils.findVariable(sourceCode.getScope(identifier), identifier.name);
|
|
6868
6873
|
if (variable === null || variable.defs.length !== 1 || variable.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
6869
6874
|
const definition = variable.defs[0];
|
|
6870
6875
|
if (definition?.type === "CatchClause") return true;
|
|
6871
6876
|
if (definition?.type !== "Variable") return false;
|
|
6872
6877
|
const initializer = definition.node.init;
|
|
6873
|
-
return initializer?.type === "NewExpression" && initializer.callee.type === "Identifier" && BUILTIN_ERROR_CONSTRUCTORS.has(initializer.callee.name) && isGlobalIdentifier(initializer.callee.name,
|
|
6878
|
+
return initializer?.type === "NewExpression" && initializer.callee.type === "Identifier" && BUILTIN_ERROR_CONSTRUCTORS.has(initializer.callee.name) && isGlobalIdentifier(initializer.callee.name, sourceCode.getScope(initializer.callee));
|
|
6874
6879
|
}
|
|
6875
6880
|
function isGlobalIdentifier(name, scope) {
|
|
6876
6881
|
const binding = import_utils41.ASTUtils.findVariable(scope, name);
|
|
6877
6882
|
return binding === null || binding.defs.length === 0;
|
|
6878
6883
|
}
|
|
6879
|
-
function positiveErrorSubject(test) {
|
|
6880
|
-
return instanceofErrorSubject(test) ?? typeGuardSubject(test);
|
|
6884
|
+
function positiveErrorSubject(test, sourceCode) {
|
|
6885
|
+
return instanceofErrorSubject(test, sourceCode) ?? typeGuardSubject(test);
|
|
6881
6886
|
}
|
|
6882
6887
|
var TYPE_GUARD_PATTERN = /^(is|has)[A-Z]/;
|
|
6883
|
-
function instanceofErrorSubject(test) {
|
|
6884
|
-
if (test.type === "BinaryExpression" && test.operator === "instanceof" && test.right.type === "Identifier" && test.right.name === "Error") {
|
|
6888
|
+
function instanceofErrorSubject(test, sourceCode) {
|
|
6889
|
+
if (test.type === "BinaryExpression" && test.operator === "instanceof" && test.right.type === "Identifier" && test.right.name === "Error" && isGlobalIdentifier("Error", sourceCode.getScope(test.right))) {
|
|
6885
6890
|
return test.left;
|
|
6886
6891
|
}
|
|
6887
6892
|
return null;
|
|
@@ -6895,36 +6900,34 @@ function typeGuardSubject(test) {
|
|
|
6895
6900
|
return null;
|
|
6896
6901
|
}
|
|
6897
6902
|
function isNarrowedByEarlyReturn(node, argExpr, sourceCode) {
|
|
6898
|
-
const argText = sourceCode.getText(argExpr);
|
|
6899
6903
|
let current = node.parent;
|
|
6900
6904
|
while (current) {
|
|
6901
6905
|
if (current.type === "BlockStatement" || current.type === "Program") {
|
|
6902
|
-
if (hasEarlierErrorGuard(current.body, node,
|
|
6906
|
+
if (hasEarlierErrorGuard(current.body, node, argExpr, sourceCode)) return true;
|
|
6903
6907
|
}
|
|
6904
6908
|
current = current.parent;
|
|
6905
6909
|
}
|
|
6906
6910
|
return false;
|
|
6907
6911
|
}
|
|
6908
6912
|
function isGuardedByInstanceofError(node, argExpr, sourceCode) {
|
|
6909
|
-
const
|
|
6910
|
-
const sameSubject = (subject) => sourceCode.getText(subject) === argText;
|
|
6913
|
+
const sameSubject = (subject) => sameSubjectBinding(subject, argExpr, sourceCode);
|
|
6911
6914
|
let current = node.parent;
|
|
6912
6915
|
while (current) {
|
|
6913
6916
|
if (current.type === "ConditionalExpression") {
|
|
6914
|
-
const subject = positiveErrorSubject(current.test);
|
|
6917
|
+
const subject = positiveErrorSubject(current.test, sourceCode);
|
|
6915
6918
|
if (subject && sameSubject(subject) && nodeWithin(node, current.alternate)) {
|
|
6916
6919
|
return true;
|
|
6917
6920
|
}
|
|
6918
|
-
const negated = negatedInstanceofErrorSubject(current.test);
|
|
6921
|
+
const negated = negatedInstanceofErrorSubject(current.test, sourceCode);
|
|
6919
6922
|
if (negated && sameSubject(negated) && nodeWithin(node, current.consequent)) {
|
|
6920
6923
|
return true;
|
|
6921
6924
|
}
|
|
6922
6925
|
} else if (current.type === "IfStatement") {
|
|
6923
|
-
const subject = positiveErrorSubject(current.test);
|
|
6926
|
+
const subject = positiveErrorSubject(current.test, sourceCode);
|
|
6924
6927
|
if (subject && sameSubject(subject) && nodeWithin(node, current.alternate)) {
|
|
6925
6928
|
return true;
|
|
6926
6929
|
}
|
|
6927
|
-
const negated = negatedInstanceofErrorSubject(current.test);
|
|
6930
|
+
const negated = negatedInstanceofErrorSubject(current.test, sourceCode);
|
|
6928
6931
|
if (negated && sameSubject(negated) && nodeWithin(node, current.consequent)) {
|
|
6929
6932
|
return true;
|
|
6930
6933
|
}
|
|
@@ -6933,12 +6936,21 @@ function isGuardedByInstanceofError(node, argExpr, sourceCode) {
|
|
|
6933
6936
|
}
|
|
6934
6937
|
return false;
|
|
6935
6938
|
}
|
|
6936
|
-
function negatedInstanceofErrorSubject(test) {
|
|
6939
|
+
function negatedInstanceofErrorSubject(test, sourceCode) {
|
|
6937
6940
|
if (test.type === "UnaryExpression" && test.operator === "!") {
|
|
6938
|
-
return positiveErrorSubject(test.argument);
|
|
6941
|
+
return positiveErrorSubject(test.argument, sourceCode);
|
|
6939
6942
|
}
|
|
6940
6943
|
return null;
|
|
6941
6944
|
}
|
|
6945
|
+
function sameSubjectBinding(subject, value, sourceCode) {
|
|
6946
|
+
const left = unwrapExpression(subject);
|
|
6947
|
+
const right = unwrapExpression(value);
|
|
6948
|
+
if (left.type === "Identifier" && right.type === "Identifier") {
|
|
6949
|
+
const binding = import_utils41.ASTUtils.findVariable(sourceCode.getScope(left), left.name);
|
|
6950
|
+
return binding !== null && binding === import_utils41.ASTUtils.findVariable(sourceCode.getScope(right), right.name);
|
|
6951
|
+
}
|
|
6952
|
+
return sourceCode.getText(subject) === sourceCode.getText(value);
|
|
6953
|
+
}
|
|
6942
6954
|
function nodeWithin(node, container) {
|
|
6943
6955
|
return container !== null && node.range[0] >= container.range[0] && node.range[1] <= container.range[1];
|
|
6944
6956
|
}
|
|
@@ -6966,21 +6978,21 @@ function directLiteralValues(argument) {
|
|
|
6966
6978
|
}
|
|
6967
6979
|
return argument.type === "SpreadElement" ? [] : [argument];
|
|
6968
6980
|
}
|
|
6969
|
-
function expressionSuggestsError(expression,
|
|
6981
|
+
function expressionSuggestsError(expression, sourceCode) {
|
|
6970
6982
|
expression = unwrapExpression(expression);
|
|
6971
6983
|
const unwrappedExpressionCallee = expression.type === "CallExpression" || expression.type === "NewExpression" ? unwrapExpression(expression.callee) : null;
|
|
6972
6984
|
if (expression.type === "Identifier") {
|
|
6973
|
-
return identifierIsProvenError(expression,
|
|
6985
|
+
return identifierIsProvenError(expression, sourceCode);
|
|
6974
6986
|
}
|
|
6975
6987
|
if (expression.type === "NewExpression" && unwrappedExpressionCallee?.type === "Identifier") {
|
|
6976
|
-
return BUILTIN_ERROR_CONSTRUCTORS.has(unwrappedExpressionCallee.name) && isGlobalIdentifier(unwrappedExpressionCallee.name,
|
|
6988
|
+
return BUILTIN_ERROR_CONSTRUCTORS.has(unwrappedExpressionCallee.name) && isGlobalIdentifier(unwrappedExpressionCallee.name, sourceCode.getScope(unwrappedExpressionCallee));
|
|
6977
6989
|
}
|
|
6978
|
-
return expression.type === "MemberExpression" && memberSuggestsError(expression,
|
|
6990
|
+
return expression.type === "MemberExpression" && memberSuggestsError(expression, sourceCode);
|
|
6979
6991
|
}
|
|
6980
|
-
function memberSuggestsError(member,
|
|
6992
|
+
function memberSuggestsError(member, sourceCode) {
|
|
6981
6993
|
const propName2 = import_utils41.ASTUtils.getPropertyName(member);
|
|
6982
6994
|
const base = member.object;
|
|
6983
|
-
const baseSuggestsError = base.type === "Identifier" && identifierIsProvenError(base,
|
|
6995
|
+
const baseSuggestsError = base.type === "Identifier" && identifierIsProvenError(base, sourceCode);
|
|
6984
6996
|
if (baseSuggestsError) {
|
|
6985
6997
|
if (propName2 === null) {
|
|
6986
6998
|
return true;
|
|
@@ -7020,7 +7032,7 @@ var no_json_stringify_error_default = createRule({
|
|
|
7020
7032
|
const replacer = node.arguments[1] === void 0 ? void 0 : unwrapExpression(node.arguments[1]);
|
|
7021
7033
|
if (replacer !== void 0 && !(replacer.type === "Literal" && replacer.value === null) && !(replacer.type === "Identifier" && replacer.name === "undefined" && isGlobalIdentifier("undefined", scope))) return;
|
|
7022
7034
|
const unsafeValue = directLiteralValues(firstArg).find(
|
|
7023
|
-
(value) => expressionSuggestsError(value,
|
|
7035
|
+
(value) => expressionSuggestsError(value, context.sourceCode) && !isGuardedByInstanceofError(node, value, context.sourceCode) && !isNarrowedByEarlyReturn(node, value, context.sourceCode)
|
|
7024
7036
|
);
|
|
7025
7037
|
if (unsafeValue === void 0) {
|
|
7026
7038
|
return;
|
|
@@ -7033,14 +7045,14 @@ var no_json_stringify_error_default = createRule({
|
|
|
7033
7045
|
};
|
|
7034
7046
|
}
|
|
7035
7047
|
});
|
|
7036
|
-
function hasEarlierErrorGuard(statements, node,
|
|
7048
|
+
function hasEarlierErrorGuard(statements, node, argExpr, sourceCode) {
|
|
7037
7049
|
for (const stmt of statements) {
|
|
7038
7050
|
if (stmt.range[0] >= node.range[0]) {
|
|
7039
7051
|
break;
|
|
7040
7052
|
}
|
|
7041
7053
|
if (stmt.type === "IfStatement" && stmt.alternate === null && branchTerminates(stmt.consequent)) {
|
|
7042
|
-
const subject = positiveErrorSubject(stmt.test);
|
|
7043
|
-
if (subject &&
|
|
7054
|
+
const subject = positiveErrorSubject(stmt.test, sourceCode);
|
|
7055
|
+
if (subject && sameSubjectBinding(subject, argExpr, sourceCode)) {
|
|
7044
7056
|
return true;
|
|
7045
7057
|
}
|
|
7046
7058
|
}
|
|
@@ -7196,7 +7208,7 @@ var import_utils43 = require("@typescript-eslint/utils");
|
|
|
7196
7208
|
// src/rules/_zod.ts
|
|
7197
7209
|
var ZOD_SCHEMA_NAME_RE = /Schema$|^Z[A-Z]/;
|
|
7198
7210
|
function isZodModule(source) {
|
|
7199
|
-
return
|
|
7211
|
+
return source === "zod" || source.startsWith("zod/");
|
|
7200
7212
|
}
|
|
7201
7213
|
|
|
7202
7214
|
// src/rules/no-impossible-zod-literal-bounds.ts
|
|
@@ -7583,6 +7595,7 @@ var NO_REDUNDANT_OPTIONAL_ARRAY_DEFAULT_DOCUMENTATION = {
|
|
|
7583
7595
|
autofix: "safe",
|
|
7584
7596
|
limitations: [
|
|
7585
7597
|
"Only syntactically local Zod array chains with adjacent `.optional().default(...)` calls are checked.",
|
|
7598
|
+
"Imports must name the official zod package or its subpaths; relative modules and unproven npm aliases are excluded.",
|
|
7586
7599
|
"String, scalar, tuple, set, record, aliased, composed, and dynamically constructed schemas are excluded.",
|
|
7587
7600
|
"The reversed `.default(...).optional()` order is preserved because its outer optional can return undefined instead of the default.",
|
|
7588
7601
|
"Defaults must be literal arrays or synchronous functions returning one literal array; dynamic or undefined fallbacks are excluded because Zod 3 reparses the fallback.",
|
|
@@ -7623,6 +7636,30 @@ var NO_REDUNDANT_OPTIONAL_ARRAY_DEFAULT_DOCUMENTATION = {
|
|
|
7623
7636
|
focusPath: "src/schema.ts",
|
|
7624
7637
|
expectedCount: 1,
|
|
7625
7638
|
public: true
|
|
7639
|
+
},
|
|
7640
|
+
{
|
|
7641
|
+
id: "unrelated-relative-builder",
|
|
7642
|
+
title: "Preserve an unrelated builder in a directory named zod",
|
|
7643
|
+
outcome: "no-match",
|
|
7644
|
+
files: [
|
|
7645
|
+
{ path: "src/my-zod/index.ts", source: 'export const z = { string: () => "string", array: (_element: string) => ({ optional: () => ({ default: (value: readonly string[]) => ({ value, optional: true }) }), default: (value: readonly string[]) => ({ value, optional: false }) }) };' },
|
|
7646
|
+
{ path: "src/schema.ts", source: 'import { z } from "./my-zod/index.js"; export const Items = z.array(z.string()).optional().default([]);' }
|
|
7647
|
+
],
|
|
7648
|
+
focusPath: "src/schema.ts",
|
|
7649
|
+
expectedCount: 0,
|
|
7650
|
+
public: true,
|
|
7651
|
+
scenarioId: "module-identity"
|
|
7652
|
+
},
|
|
7653
|
+
{
|
|
7654
|
+
id: "official-zod-subpath-array",
|
|
7655
|
+
title: "Official Zod subpath constructors retain the safe fix",
|
|
7656
|
+
outcome: "match",
|
|
7657
|
+
files: [{ path: "src/schema.ts", source: 'import { array, string } from "zod/v4"; const Items = array(string()).optional().default([]);' }],
|
|
7658
|
+
fixedFiles: [{ path: "src/schema.ts", source: 'import { array, string } from "zod/v4"; const Items = array(string()).default([]);' }],
|
|
7659
|
+
focusPath: "src/schema.ts",
|
|
7660
|
+
expectedCount: 1,
|
|
7661
|
+
public: true,
|
|
7662
|
+
scenarioId: "module-identity"
|
|
7626
7663
|
}
|
|
7627
7664
|
]
|
|
7628
7665
|
};
|
|
@@ -8815,11 +8852,12 @@ var NO_OFFSET_PAGINATION_DOCUMENTATION = {
|
|
|
8815
8852
|
limitations: ["A SELECT/FROM query shape or adjacent LIMIT/OFFSET fragment is required. Isolated OFFSET fragments and test files are excluded; this lexical context does not prove a database execution sink. Performance and concurrent-write behavior depend on indexes, ordering, isolation, and dialect; bounded pages and random page access can justify OFFSET."],
|
|
8816
8853
|
examples: [
|
|
8817
8854
|
{ id: "keyset-pagination", title: "Page from a stable cursor", outcome: "no-match", files: [{ path: "src/runs.ts", source: "db.prepare(`SELECT id FROM runs WHERE id > ? ORDER BY id LIMIT ?`).all();" }], focusPath: "src/runs.ts", expectedCount: 0, public: true },
|
|
8818
|
-
{ id: "offset-pagination", title: "Do not page by offset", outcome: "match", files: [{ path: "src/runs.ts", source: "db.query(`SELECT id FROM runs ORDER BY id LIMIT ? OFFSET ?`);" }], focusPath: "src/runs.ts", expectedCount: 1, public: true }
|
|
8855
|
+
{ id: "offset-pagination", title: "Do not page by offset", outcome: "match", files: [{ path: "src/runs.ts", source: "db.query(`SELECT id FROM runs ORDER BY id LIMIT ? OFFSET ?`);" }], focusPath: "src/runs.ts", expectedCount: 1, public: true },
|
|
8856
|
+
{ id: "decoded-query", scenarioId: "native-decoded-sql", title: "Inspect native-decoded query text", outcome: "match", files: [{ path: "src/page.ts", source: 'db.query("SELECT id FROM runs ORDER BY id LIMIT 1 OFF\\u0053ET 1");' }], focusPath: "src/page.ts", expectedCount: 1, public: true },
|
|
8857
|
+
{ id: "decoded-comment-data", scenarioId: "native-decoded-sql", title: "Ignore native-decoded comment data", outcome: "no-match", files: [{ path: "src/page.ts", source: 'db.query("SELECT id FROM runs /* OFF\\x53ET 1 */");' }], focusPath: "src/page.ts", expectedCount: 0, public: true }
|
|
8819
8858
|
]
|
|
8820
8859
|
};
|
|
8821
8860
|
var OFFSET_PAGINATION = /\bOFFSET\s+(?:%s|%\(\w+\)s|\?\d*|:\w+|@\w+|\$\d+|\d+)/i;
|
|
8822
|
-
var OFFSET_GATE = /offset/i;
|
|
8823
8861
|
var PAGINATION_CONTEXT = /\bSELECT\b[\s\S]*\bFROM\b[\s\S]*\bOFFSET\b|\bLIMIT\s+(?:%s|%\(\w+\)s|\?\d*|:\w+|@\w+|\$\d+|\d+)\s+OFFSET\b/i;
|
|
8824
8862
|
var no_offset_pagination_default = createRule({
|
|
8825
8863
|
name: "no-offset-pagination",
|
|
@@ -8836,7 +8874,7 @@ var no_offset_pagination_default = createRule({
|
|
|
8836
8874
|
},
|
|
8837
8875
|
defaultOptions: [],
|
|
8838
8876
|
create(context) {
|
|
8839
|
-
if (isTestFile(context.filename)
|
|
8877
|
+
if (isTestFile(context.filename)) {
|
|
8840
8878
|
return {};
|
|
8841
8879
|
}
|
|
8842
8880
|
return createSqlListener((sql, node) => {
|
|
@@ -10953,7 +10991,9 @@ var NO_SELECT_STAR_DOCUMENTATION = {
|
|
|
10953
10991
|
limitations: ["Only statically visible embedded SQL is checked; quoted strings (including PostgreSQL dollar strings), comments, function arguments such as COUNT(*), and stars inside EXISTS are excluded. This is a bounded lexical scan, not a complete SQL parser."],
|
|
10954
10992
|
examples: [
|
|
10955
10993
|
{ id: "explicit-projection", title: "Select the required columns", outcome: "no-match", files: [{ path: "src/runs.ts", source: "db.prepare(`SELECT id, status FROM runs`).all();" }], focusPath: "src/runs.ts", expectedCount: 0, public: true },
|
|
10956
|
-
{ id: "wildcard-projection", title: "Do not select every column", outcome: "match", files: [{ path: "src/runs.ts", source: "db.prepare(`SELECT * FROM runs`).all();" }], focusPath: "src/runs.ts", expectedCount: 1, public: true }
|
|
10994
|
+
{ id: "wildcard-projection", title: "Do not select every column", outcome: "match", files: [{ path: "src/runs.ts", source: "db.prepare(`SELECT * FROM runs`).all();" }], focusPath: "src/runs.ts", expectedCount: 1, public: true },
|
|
10995
|
+
{ id: "decoded-query", scenarioId: "native-decoded-sql", title: "Inspect native-decoded query text", outcome: "match", files: [{ path: "src/page.ts", source: 'db.query("SEL\\u0045CT * FROM runs");' }], focusPath: "src/page.ts", expectedCount: 1, public: true },
|
|
10996
|
+
{ id: "decoded-comment-data", scenarioId: "native-decoded-sql", title: "Ignore native-decoded comment data", outcome: "no-match", files: [{ path: "src/page.ts", source: 'db.query("SEL\\x45CT id FROM runs /* SELECT * FROM runs */");' }], focusPath: "src/page.ts", expectedCount: 0, public: true }
|
|
10957
10997
|
]
|
|
10958
10998
|
};
|
|
10959
10999
|
var QUERY_SHAPE = /\bSELECT\b[\s\S]*?\bFROM\b/i;
|
|
@@ -10961,7 +11001,6 @@ var SELECT_KEYWORD = /\bSELECT\b/gi;
|
|
|
10961
11001
|
var FROM_KEYWORD = /^FROM\b/i;
|
|
10962
11002
|
var EXISTS_BEFORE = /\bEXISTS\s*\(\s*$/i;
|
|
10963
11003
|
var QUALIFIED_PREFIX = /\w\.$/;
|
|
10964
|
-
var SELECT_GATE = /select/i;
|
|
10965
11004
|
function hasRealSelectStar(sql) {
|
|
10966
11005
|
const selects = [...sql.matchAll(SELECT_KEYWORD)].map((m) => m.index);
|
|
10967
11006
|
for (let pos = 0; pos < sql.length; pos++) {
|
|
@@ -11010,7 +11049,7 @@ var no_select_star_default = createRule({
|
|
|
11010
11049
|
},
|
|
11011
11050
|
defaultOptions: [],
|
|
11012
11051
|
create(context) {
|
|
11013
|
-
if (isTestFile(context.filename)
|
|
11052
|
+
if (isTestFile(context.filename)) {
|
|
11014
11053
|
return {};
|
|
11015
11054
|
}
|
|
11016
11055
|
return createSqlListener((sql, node) => {
|
|
@@ -18934,16 +18973,20 @@ var PREFER_SWITCH_FOR_REPEATED_EQUALITY_DOCUMENTATION = {
|
|
|
18934
18973
|
],
|
|
18935
18974
|
examples: [
|
|
18936
18975
|
{ id: "switch-dispatch", title: "Make finite dispatch explicit", outcome: "no-match", files: [{ path: "src/render.ts", source: "switch (kind) { case 'a': return a(); case 'b': return b(); case 'c': return c(); default: return fallback(); }" }], focusPath: "src/render.ts", expectedCount: 0, public: true },
|
|
18937
|
-
{ id: "repeated-equality", title: "Avoid repeating the discriminant", outcome: "match", files: [{ path: "src/render.ts", source: "if (kind === 'a') return a(); else if (kind === 'b') return b(); else if (kind === 'c') return c();" }], focusPath: "src/render.ts", expectedCount: 1, public: true }
|
|
18976
|
+
{ id: "repeated-equality", title: "Avoid repeating the discriminant", outcome: "match", files: [{ path: "src/render.ts", source: "if (kind === 'a') return a(); else if (kind === 'b') return b(); else if (kind === 'c') return c();" }], focusPath: "src/render.ts", expectedCount: 1, public: true },
|
|
18977
|
+
{ id: "escaped-middle", scenarioId: "native-discriminant", title: "Use native identifier identity", outcome: "match", files: [{ path: "src/dispatch.ts", source: `function probe(kind){if(kind==='a')return 1;else if(\\u006bind==='b')return 2;else if(kind==='c')return 3;return 0;}
|
|
18978
|
+
console.log(JSON.stringify(["a","b","c","d"].map(probe)));` }], focusPath: "src/dispatch.ts", expectedCount: 1, public: true },
|
|
18979
|
+
{ id: "different-discriminants", scenarioId: "native-discriminant", title: "Use native identifier identity", outcome: "no-match", files: [{ path: "src/dispatch.ts", source: `function probe(kind){const other="other";if(kind==='a')return 1;else if(other==='b')return 2;else if(kind==='c')return 3;return 0;}
|
|
18980
|
+
console.log(JSON.stringify(["a","b","c","d"].map(probe)));` }], focusPath: "src/dispatch.ts", expectedCount: 0, public: true }
|
|
18938
18981
|
]
|
|
18939
18982
|
};
|
|
18940
|
-
function
|
|
18983
|
+
function discriminantName(test) {
|
|
18941
18984
|
if (test.type !== import_utils110.AST_NODE_TYPES.BinaryExpression || test.operator !== "===") return null;
|
|
18942
18985
|
const leftIsCase = isCaseValue(test.left);
|
|
18943
18986
|
const rightIsCase = isCaseValue(test.right);
|
|
18944
18987
|
if (leftIsCase === rightIsCase) return null;
|
|
18945
18988
|
const discriminant = leftIsCase ? test.right : test.left;
|
|
18946
|
-
return discriminant.type === import_utils110.AST_NODE_TYPES.Identifier ?
|
|
18989
|
+
return discriminant.type === import_utils110.AST_NODE_TYPES.Identifier ? discriminant.name : null;
|
|
18947
18990
|
}
|
|
18948
18991
|
function isCaseValue(node) {
|
|
18949
18992
|
if (node.type === import_utils110.AST_NODE_TYPES.Literal) return true;
|
|
@@ -18967,12 +19010,12 @@ var prefer_switch_for_repeated_equality_default = createRule({
|
|
|
18967
19010
|
return {
|
|
18968
19011
|
IfStatement(node) {
|
|
18969
19012
|
if (node.parent.type === import_utils110.AST_NODE_TYPES.IfStatement && node.parent.alternate === node) return;
|
|
18970
|
-
const first =
|
|
19013
|
+
const first = discriminantName(node.test);
|
|
18971
19014
|
if (first === null) return;
|
|
18972
19015
|
let count = 1;
|
|
18973
19016
|
let current = node.alternate;
|
|
18974
19017
|
while (current?.type === import_utils110.AST_NODE_TYPES.IfStatement) {
|
|
18975
|
-
if (
|
|
19018
|
+
if (discriminantName(current.test) !== first) return;
|
|
18976
19019
|
count += 1;
|
|
18977
19020
|
current = current.alternate;
|
|
18978
19021
|
}
|
|
@@ -22700,7 +22743,9 @@ var STORE_INSERT_REQUIRES_ON_CONFLICT_DOCUMENTATION = {
|
|
|
22700
22743
|
limitations: ["Only the nearest statically named callable is considered; top-level inserts and anonymous callbacks are excluded. Recognized conflict syntax does not prove idempotence or concurrency safety: WHERE NOT EXISTS can race, and INSERT OR REPLACE can delete an existing row. Review unique constraints and dialect semantics manually."],
|
|
22701
22744
|
examples: [
|
|
22702
22745
|
{ id: "conflict-safe-insert", title: "Review the conflict policy for a replayed insert", outcome: "no-match", files: [{ path: "src/store.ts", source: "function seed() { db.prepare(`INSERT INTO runs (id) VALUES (?) ON CONFLICT(id) DO NOTHING`).run(); }" }], focusPath: "src/store.ts", expectedCount: 0, public: true },
|
|
22703
|
-
{ id: "bare-insert", title: "Review a bare insert in a replay-named callable", outcome: "match", files: [{ path: "src/store.ts", source: "function seed() { db.prepare(`INSERT INTO runs (id) VALUES (?)`).run(); }" }], focusPath: "src/store.ts", expectedCount: 1, public: true }
|
|
22746
|
+
{ id: "bare-insert", title: "Review a bare insert in a replay-named callable", outcome: "match", files: [{ path: "src/store.ts", source: "function seed() { db.prepare(`INSERT INTO runs (id) VALUES (?)`).run(); }" }], focusPath: "src/store.ts", expectedCount: 1, public: true },
|
|
22747
|
+
{ id: "decoded-query", scenarioId: "native-decoded-sql", title: "Inspect native-decoded query text", outcome: "match", files: [{ path: "src/page.ts", source: `function seed(){db.query("INS\\u0045RT INTO runs(id,note) VALUES(4,'new')");}` }], focusPath: "src/page.ts", expectedCount: 1, public: true },
|
|
22748
|
+
{ id: "decoded-comment-data", scenarioId: "native-decoded-sql", title: "Ignore native-decoded comment data", outcome: "no-match", files: [{ path: "src/page.ts", source: `function seed(){db.query("SELECT id FROM runs /* INS\\x45RT INTO runs(id,note) VALUES(4,'new') */");}` }], focusPath: "src/page.ts", expectedCount: 0, public: true }
|
|
22704
22749
|
]
|
|
22705
22750
|
};
|
|
22706
22751
|
var INSERT_WRITE = /\bINSERT\s+(?:OR\s+\w+\s+)?INTO\s+[\w."'`?$:@-]+\s*(?:\([^)]*\)\s*)?(?:VALUES|SELECT|DEFAULT\s+VALUES)\b/i;
|
|
@@ -22720,7 +22765,6 @@ function owningCallableName(node) {
|
|
|
22720
22765
|
}
|
|
22721
22766
|
return null;
|
|
22722
22767
|
}
|
|
22723
|
-
var INSERT_GATE = /insert/i;
|
|
22724
22768
|
var store_insert_requires_on_conflict_default = createRule({
|
|
22725
22769
|
name: "store-insert-requires-on-conflict",
|
|
22726
22770
|
documentation: STORE_INSERT_REQUIRES_ON_CONFLICT_DOCUMENTATION,
|
|
@@ -22736,7 +22780,7 @@ var store_insert_requires_on_conflict_default = createRule({
|
|
|
22736
22780
|
},
|
|
22737
22781
|
defaultOptions: [],
|
|
22738
22782
|
create(context) {
|
|
22739
|
-
if (isTestFile(context.filename)
|
|
22783
|
+
if (isTestFile(context.filename)) {
|
|
22740
22784
|
return {};
|
|
22741
22785
|
}
|
|
22742
22786
|
return createSqlListener((sql, node) => {
|
|
@@ -24289,7 +24333,7 @@ var RULES = {
|
|
|
24289
24333
|
};
|
|
24290
24334
|
var meta = {
|
|
24291
24335
|
name: "@sarj/eslint-plugin",
|
|
24292
|
-
version: "16.4.
|
|
24336
|
+
version: "16.4.7"
|
|
24293
24337
|
};
|
|
24294
24338
|
var APPLICATION_ONLY_RULES = [];
|
|
24295
24339
|
var LIBRARY_IMPORT_POLICY = ["error", {
|
package/dist/index.d.cts
CHANGED
|
@@ -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.
|
|
930
|
+
readonly version: "16.4.7";
|
|
931
931
|
};
|
|
932
932
|
readonly rules: {
|
|
933
933
|
readonly "require-explicit-contract-implementation": DocumentedRule<readonly [], "declareActualContract">;
|
package/dist/index.d.ts
CHANGED
|
@@ -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.
|
|
930
|
+
readonly version: "16.4.7";
|
|
931
931
|
};
|
|
932
932
|
readonly rules: {
|
|
933
933
|
readonly "require-explicit-contract-implementation": DocumentedRule<readonly [], "declareActualContract">;
|
package/dist/index.js
CHANGED
|
@@ -211,6 +211,7 @@ function deepFreeze(value) {
|
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
// src/rules/_paths.ts
|
|
214
|
+
var LINE_TERMINATOR_RE = /[\n\r\u2028\u2029]/u;
|
|
214
215
|
var SCRIPT_FILE_RE = /(?:^|[\\/])scripts[\\/]|\.mjs$/;
|
|
215
216
|
var STORY_FILE_RE = /\.stories\.[cm]?[jt]sx?$/i;
|
|
216
217
|
var STORY_TREE_RE = /(^|\/)stories(?:[_-][^/]*)?\//i;
|
|
@@ -260,8 +261,8 @@ function leadingCommentBodies(sourceText) {
|
|
|
260
261
|
const bodies = [];
|
|
261
262
|
let index = 0;
|
|
262
263
|
if (sourceText.startsWith("#!")) {
|
|
263
|
-
const shebangEnd = sourceText
|
|
264
|
-
index = shebangEnd ===
|
|
264
|
+
const shebangEnd = commentLineEnd(sourceText, 2);
|
|
265
|
+
index = shebangEnd === sourceText.length ? sourceText.length : shebangEnd + 1;
|
|
265
266
|
}
|
|
266
267
|
while (index < sourceText.length) {
|
|
267
268
|
while (/\s/u.test(sourceText[index] ?? "")) index++;
|
|
@@ -275,7 +276,7 @@ function leadingCommentBodies(sourceText) {
|
|
|
275
276
|
const end = sourceText.indexOf("*/", index + 2);
|
|
276
277
|
if (end === -1) break;
|
|
277
278
|
bodies.push(
|
|
278
|
-
...sourceText.slice(index + 2, end).split(
|
|
279
|
+
...sourceText.slice(index + 2, end).split(LINE_TERMINATOR_RE).map((line) => line.replace(/^\s*\*?\s?/u, "").trim()).filter((line) => line.length > 0)
|
|
279
280
|
);
|
|
280
281
|
index = end + 2;
|
|
281
282
|
continue;
|
|
@@ -294,8 +295,8 @@ function isScriptFile(filename) {
|
|
|
294
295
|
return SCRIPT_FILE_RE.test(filename);
|
|
295
296
|
}
|
|
296
297
|
function commentLineEnd(sourceText, start) {
|
|
297
|
-
const end = sourceText.
|
|
298
|
-
return end === -1 ? sourceText.length : end;
|
|
298
|
+
const end = sourceText.slice(start).search(LINE_TERMINATOR_RE);
|
|
299
|
+
return end === -1 ? sourceText.length : start + end;
|
|
299
300
|
}
|
|
300
301
|
|
|
301
302
|
// src/rules/require-explicit-contract-implementation.ts
|
|
@@ -5437,7 +5438,9 @@ var NO_ENUM_DOCUMENTATION = {
|
|
|
5437
5438
|
focusPath: "src/status.ts",
|
|
5438
5439
|
expectedCount: 1,
|
|
5439
5440
|
public: true
|
|
5440
|
-
}
|
|
5441
|
+
},
|
|
5442
|
+
{ id: "authored-after-comment", scenarioId: "native-header-boundary", title: "Keep executable authored code in scope", outcome: "match", files: [{ path: "src/status.ts", source: '// ordinary header\u2028const marker="auto-generated file"; enum Mode {Start} console.log(Mode.Start, marker);' }], focusPath: "src/status.ts", expectedCount: 1, public: true },
|
|
5443
|
+
{ id: "generated-header", scenarioId: "native-header-boundary", title: "Respect a native generated banner", outcome: "no-match", files: [{ path: "src/status.ts", source: '// auto-generated file\u2028const marker="auto-generated file"; enum Mode {Start} console.log(Mode.Start, marker);' }], focusPath: "src/status.ts", expectedCount: 0, public: true }
|
|
5441
5444
|
]
|
|
5442
5445
|
};
|
|
5443
5446
|
function matchesAnyPattern(filename, patterns) {
|
|
@@ -6800,7 +6803,9 @@ var NO_JSON_STRINGIFY_ERROR_DOCUMENTATION = {
|
|
|
6800
6803
|
limitations: ["The rule uses stable local catch bindings and unshadowed built-in constructors, not runtime type information. Custom replacers are left to their serializer contract; a catch value is not guaranteed to be an Error."],
|
|
6801
6804
|
examples: [
|
|
6802
6805
|
{ id: "explicit-error-message", title: "Narrow an unknown catch value before selecting fields", outcome: "no-match", files: [{ path: "src/report.ts", source: "try { f(); } catch (err) { JSON.stringify({ error: err instanceof Error ? err.message : String(err) }); }" }], focusPath: "src/report.ts", expectedCount: 0, public: true },
|
|
6803
|
-
{ id: "stringified-error", title: "Do not stringify an Error object", outcome: "match", files: [{ path: "src/report.ts", source: "try { f(); } catch (err) { JSON.stringify({ error: err }); }" }], focusPath: "src/report.ts", expectedCount: 1, public: true }
|
|
6806
|
+
{ id: "stringified-error", title: "Do not stringify an Error object", outcome: "match", files: [{ path: "src/report.ts", source: "try { f(); } catch (err) { JSON.stringify({ error: err }); }" }], focusPath: "src/report.ts", expectedCount: 1, public: true },
|
|
6807
|
+
{ id: "shadowed-error-binding", scenarioId: "binding-provenance", title: "Keep native binding provenance", outcome: "match", files: [{ path: "src/error.ts", source: 'function probe(){try{throw {id:1};}catch(err){if(err instanceof Error)return err.message;{const err=new Error("lost");return JSON.stringify(err);}}}\nconsole.log(probe());' }], focusPath: "src/error.ts", expectedCount: 1, public: true },
|
|
6808
|
+
{ id: "escaped-fallback-binding", scenarioId: "binding-provenance", title: "Keep native binding provenance", outcome: "no-match", files: [{ path: "src/error.ts", source: "function probe(){try{throw {id:1};}catch(err){if(err instanceof Error)return err.message;return JSON.stringify(\\u0065rr);}}\nconsole.log(probe());" }], focusPath: "src/error.ts", expectedCount: 0, public: true }
|
|
6804
6809
|
]
|
|
6805
6810
|
};
|
|
6806
6811
|
var SAFE_STRING_PROPS = /* @__PURE__ */ new Set(["message", "stack", "name"]);
|
|
@@ -6830,25 +6835,25 @@ var BUILTIN_ERROR_CONSTRUCTORS = /* @__PURE__ */ new Set([
|
|
|
6830
6835
|
"TypeError",
|
|
6831
6836
|
"URIError"
|
|
6832
6837
|
]);
|
|
6833
|
-
function identifierIsProvenError(identifier,
|
|
6834
|
-
const variable = ASTUtils14.findVariable(
|
|
6838
|
+
function identifierIsProvenError(identifier, sourceCode) {
|
|
6839
|
+
const variable = ASTUtils14.findVariable(sourceCode.getScope(identifier), identifier.name);
|
|
6835
6840
|
if (variable === null || variable.defs.length !== 1 || variable.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
6836
6841
|
const definition = variable.defs[0];
|
|
6837
6842
|
if (definition?.type === "CatchClause") return true;
|
|
6838
6843
|
if (definition?.type !== "Variable") return false;
|
|
6839
6844
|
const initializer = definition.node.init;
|
|
6840
|
-
return initializer?.type === "NewExpression" && initializer.callee.type === "Identifier" && BUILTIN_ERROR_CONSTRUCTORS.has(initializer.callee.name) && isGlobalIdentifier(initializer.callee.name,
|
|
6845
|
+
return initializer?.type === "NewExpression" && initializer.callee.type === "Identifier" && BUILTIN_ERROR_CONSTRUCTORS.has(initializer.callee.name) && isGlobalIdentifier(initializer.callee.name, sourceCode.getScope(initializer.callee));
|
|
6841
6846
|
}
|
|
6842
6847
|
function isGlobalIdentifier(name, scope) {
|
|
6843
6848
|
const binding = ASTUtils14.findVariable(scope, name);
|
|
6844
6849
|
return binding === null || binding.defs.length === 0;
|
|
6845
6850
|
}
|
|
6846
|
-
function positiveErrorSubject(test) {
|
|
6847
|
-
return instanceofErrorSubject(test) ?? typeGuardSubject(test);
|
|
6851
|
+
function positiveErrorSubject(test, sourceCode) {
|
|
6852
|
+
return instanceofErrorSubject(test, sourceCode) ?? typeGuardSubject(test);
|
|
6848
6853
|
}
|
|
6849
6854
|
var TYPE_GUARD_PATTERN = /^(is|has)[A-Z]/;
|
|
6850
|
-
function instanceofErrorSubject(test) {
|
|
6851
|
-
if (test.type === "BinaryExpression" && test.operator === "instanceof" && test.right.type === "Identifier" && test.right.name === "Error") {
|
|
6855
|
+
function instanceofErrorSubject(test, sourceCode) {
|
|
6856
|
+
if (test.type === "BinaryExpression" && test.operator === "instanceof" && test.right.type === "Identifier" && test.right.name === "Error" && isGlobalIdentifier("Error", sourceCode.getScope(test.right))) {
|
|
6852
6857
|
return test.left;
|
|
6853
6858
|
}
|
|
6854
6859
|
return null;
|
|
@@ -6862,36 +6867,34 @@ function typeGuardSubject(test) {
|
|
|
6862
6867
|
return null;
|
|
6863
6868
|
}
|
|
6864
6869
|
function isNarrowedByEarlyReturn(node, argExpr, sourceCode) {
|
|
6865
|
-
const argText = sourceCode.getText(argExpr);
|
|
6866
6870
|
let current = node.parent;
|
|
6867
6871
|
while (current) {
|
|
6868
6872
|
if (current.type === "BlockStatement" || current.type === "Program") {
|
|
6869
|
-
if (hasEarlierErrorGuard(current.body, node,
|
|
6873
|
+
if (hasEarlierErrorGuard(current.body, node, argExpr, sourceCode)) return true;
|
|
6870
6874
|
}
|
|
6871
6875
|
current = current.parent;
|
|
6872
6876
|
}
|
|
6873
6877
|
return false;
|
|
6874
6878
|
}
|
|
6875
6879
|
function isGuardedByInstanceofError(node, argExpr, sourceCode) {
|
|
6876
|
-
const
|
|
6877
|
-
const sameSubject = (subject) => sourceCode.getText(subject) === argText;
|
|
6880
|
+
const sameSubject = (subject) => sameSubjectBinding(subject, argExpr, sourceCode);
|
|
6878
6881
|
let current = node.parent;
|
|
6879
6882
|
while (current) {
|
|
6880
6883
|
if (current.type === "ConditionalExpression") {
|
|
6881
|
-
const subject = positiveErrorSubject(current.test);
|
|
6884
|
+
const subject = positiveErrorSubject(current.test, sourceCode);
|
|
6882
6885
|
if (subject && sameSubject(subject) && nodeWithin(node, current.alternate)) {
|
|
6883
6886
|
return true;
|
|
6884
6887
|
}
|
|
6885
|
-
const negated = negatedInstanceofErrorSubject(current.test);
|
|
6888
|
+
const negated = negatedInstanceofErrorSubject(current.test, sourceCode);
|
|
6886
6889
|
if (negated && sameSubject(negated) && nodeWithin(node, current.consequent)) {
|
|
6887
6890
|
return true;
|
|
6888
6891
|
}
|
|
6889
6892
|
} else if (current.type === "IfStatement") {
|
|
6890
|
-
const subject = positiveErrorSubject(current.test);
|
|
6893
|
+
const subject = positiveErrorSubject(current.test, sourceCode);
|
|
6891
6894
|
if (subject && sameSubject(subject) && nodeWithin(node, current.alternate)) {
|
|
6892
6895
|
return true;
|
|
6893
6896
|
}
|
|
6894
|
-
const negated = negatedInstanceofErrorSubject(current.test);
|
|
6897
|
+
const negated = negatedInstanceofErrorSubject(current.test, sourceCode);
|
|
6895
6898
|
if (negated && sameSubject(negated) && nodeWithin(node, current.consequent)) {
|
|
6896
6899
|
return true;
|
|
6897
6900
|
}
|
|
@@ -6900,12 +6903,21 @@ function isGuardedByInstanceofError(node, argExpr, sourceCode) {
|
|
|
6900
6903
|
}
|
|
6901
6904
|
return false;
|
|
6902
6905
|
}
|
|
6903
|
-
function negatedInstanceofErrorSubject(test) {
|
|
6906
|
+
function negatedInstanceofErrorSubject(test, sourceCode) {
|
|
6904
6907
|
if (test.type === "UnaryExpression" && test.operator === "!") {
|
|
6905
|
-
return positiveErrorSubject(test.argument);
|
|
6908
|
+
return positiveErrorSubject(test.argument, sourceCode);
|
|
6906
6909
|
}
|
|
6907
6910
|
return null;
|
|
6908
6911
|
}
|
|
6912
|
+
function sameSubjectBinding(subject, value, sourceCode) {
|
|
6913
|
+
const left = unwrapExpression(subject);
|
|
6914
|
+
const right = unwrapExpression(value);
|
|
6915
|
+
if (left.type === "Identifier" && right.type === "Identifier") {
|
|
6916
|
+
const binding = ASTUtils14.findVariable(sourceCode.getScope(left), left.name);
|
|
6917
|
+
return binding !== null && binding === ASTUtils14.findVariable(sourceCode.getScope(right), right.name);
|
|
6918
|
+
}
|
|
6919
|
+
return sourceCode.getText(subject) === sourceCode.getText(value);
|
|
6920
|
+
}
|
|
6909
6921
|
function nodeWithin(node, container) {
|
|
6910
6922
|
return container !== null && node.range[0] >= container.range[0] && node.range[1] <= container.range[1];
|
|
6911
6923
|
}
|
|
@@ -6933,21 +6945,21 @@ function directLiteralValues(argument) {
|
|
|
6933
6945
|
}
|
|
6934
6946
|
return argument.type === "SpreadElement" ? [] : [argument];
|
|
6935
6947
|
}
|
|
6936
|
-
function expressionSuggestsError(expression,
|
|
6948
|
+
function expressionSuggestsError(expression, sourceCode) {
|
|
6937
6949
|
expression = unwrapExpression(expression);
|
|
6938
6950
|
const unwrappedExpressionCallee = expression.type === "CallExpression" || expression.type === "NewExpression" ? unwrapExpression(expression.callee) : null;
|
|
6939
6951
|
if (expression.type === "Identifier") {
|
|
6940
|
-
return identifierIsProvenError(expression,
|
|
6952
|
+
return identifierIsProvenError(expression, sourceCode);
|
|
6941
6953
|
}
|
|
6942
6954
|
if (expression.type === "NewExpression" && unwrappedExpressionCallee?.type === "Identifier") {
|
|
6943
|
-
return BUILTIN_ERROR_CONSTRUCTORS.has(unwrappedExpressionCallee.name) && isGlobalIdentifier(unwrappedExpressionCallee.name,
|
|
6955
|
+
return BUILTIN_ERROR_CONSTRUCTORS.has(unwrappedExpressionCallee.name) && isGlobalIdentifier(unwrappedExpressionCallee.name, sourceCode.getScope(unwrappedExpressionCallee));
|
|
6944
6956
|
}
|
|
6945
|
-
return expression.type === "MemberExpression" && memberSuggestsError(expression,
|
|
6957
|
+
return expression.type === "MemberExpression" && memberSuggestsError(expression, sourceCode);
|
|
6946
6958
|
}
|
|
6947
|
-
function memberSuggestsError(member,
|
|
6959
|
+
function memberSuggestsError(member, sourceCode) {
|
|
6948
6960
|
const propName2 = ASTUtils14.getPropertyName(member);
|
|
6949
6961
|
const base = member.object;
|
|
6950
|
-
const baseSuggestsError = base.type === "Identifier" && identifierIsProvenError(base,
|
|
6962
|
+
const baseSuggestsError = base.type === "Identifier" && identifierIsProvenError(base, sourceCode);
|
|
6951
6963
|
if (baseSuggestsError) {
|
|
6952
6964
|
if (propName2 === null) {
|
|
6953
6965
|
return true;
|
|
@@ -6987,7 +6999,7 @@ var no_json_stringify_error_default = createRule({
|
|
|
6987
6999
|
const replacer = node.arguments[1] === void 0 ? void 0 : unwrapExpression(node.arguments[1]);
|
|
6988
7000
|
if (replacer !== void 0 && !(replacer.type === "Literal" && replacer.value === null) && !(replacer.type === "Identifier" && replacer.name === "undefined" && isGlobalIdentifier("undefined", scope))) return;
|
|
6989
7001
|
const unsafeValue = directLiteralValues(firstArg).find(
|
|
6990
|
-
(value) => expressionSuggestsError(value,
|
|
7002
|
+
(value) => expressionSuggestsError(value, context.sourceCode) && !isGuardedByInstanceofError(node, value, context.sourceCode) && !isNarrowedByEarlyReturn(node, value, context.sourceCode)
|
|
6991
7003
|
);
|
|
6992
7004
|
if (unsafeValue === void 0) {
|
|
6993
7005
|
return;
|
|
@@ -7000,14 +7012,14 @@ var no_json_stringify_error_default = createRule({
|
|
|
7000
7012
|
};
|
|
7001
7013
|
}
|
|
7002
7014
|
});
|
|
7003
|
-
function hasEarlierErrorGuard(statements, node,
|
|
7015
|
+
function hasEarlierErrorGuard(statements, node, argExpr, sourceCode) {
|
|
7004
7016
|
for (const stmt of statements) {
|
|
7005
7017
|
if (stmt.range[0] >= node.range[0]) {
|
|
7006
7018
|
break;
|
|
7007
7019
|
}
|
|
7008
7020
|
if (stmt.type === "IfStatement" && stmt.alternate === null && branchTerminates(stmt.consequent)) {
|
|
7009
|
-
const subject = positiveErrorSubject(stmt.test);
|
|
7010
|
-
if (subject &&
|
|
7021
|
+
const subject = positiveErrorSubject(stmt.test, sourceCode);
|
|
7022
|
+
if (subject && sameSubjectBinding(subject, argExpr, sourceCode)) {
|
|
7011
7023
|
return true;
|
|
7012
7024
|
}
|
|
7013
7025
|
}
|
|
@@ -7170,7 +7182,7 @@ import {
|
|
|
7170
7182
|
// src/rules/_zod.ts
|
|
7171
7183
|
var ZOD_SCHEMA_NAME_RE = /Schema$|^Z[A-Z]/;
|
|
7172
7184
|
function isZodModule(source) {
|
|
7173
|
-
return
|
|
7185
|
+
return source === "zod" || source.startsWith("zod/");
|
|
7174
7186
|
}
|
|
7175
7187
|
|
|
7176
7188
|
// src/rules/no-impossible-zod-literal-bounds.ts
|
|
@@ -7562,6 +7574,7 @@ var NO_REDUNDANT_OPTIONAL_ARRAY_DEFAULT_DOCUMENTATION = {
|
|
|
7562
7574
|
autofix: "safe",
|
|
7563
7575
|
limitations: [
|
|
7564
7576
|
"Only syntactically local Zod array chains with adjacent `.optional().default(...)` calls are checked.",
|
|
7577
|
+
"Imports must name the official zod package or its subpaths; relative modules and unproven npm aliases are excluded.",
|
|
7565
7578
|
"String, scalar, tuple, set, record, aliased, composed, and dynamically constructed schemas are excluded.",
|
|
7566
7579
|
"The reversed `.default(...).optional()` order is preserved because its outer optional can return undefined instead of the default.",
|
|
7567
7580
|
"Defaults must be literal arrays or synchronous functions returning one literal array; dynamic or undefined fallbacks are excluded because Zod 3 reparses the fallback.",
|
|
@@ -7602,6 +7615,30 @@ var NO_REDUNDANT_OPTIONAL_ARRAY_DEFAULT_DOCUMENTATION = {
|
|
|
7602
7615
|
focusPath: "src/schema.ts",
|
|
7603
7616
|
expectedCount: 1,
|
|
7604
7617
|
public: true
|
|
7618
|
+
},
|
|
7619
|
+
{
|
|
7620
|
+
id: "unrelated-relative-builder",
|
|
7621
|
+
title: "Preserve an unrelated builder in a directory named zod",
|
|
7622
|
+
outcome: "no-match",
|
|
7623
|
+
files: [
|
|
7624
|
+
{ path: "src/my-zod/index.ts", source: 'export const z = { string: () => "string", array: (_element: string) => ({ optional: () => ({ default: (value: readonly string[]) => ({ value, optional: true }) }), default: (value: readonly string[]) => ({ value, optional: false }) }) };' },
|
|
7625
|
+
{ path: "src/schema.ts", source: 'import { z } from "./my-zod/index.js"; export const Items = z.array(z.string()).optional().default([]);' }
|
|
7626
|
+
],
|
|
7627
|
+
focusPath: "src/schema.ts",
|
|
7628
|
+
expectedCount: 0,
|
|
7629
|
+
public: true,
|
|
7630
|
+
scenarioId: "module-identity"
|
|
7631
|
+
},
|
|
7632
|
+
{
|
|
7633
|
+
id: "official-zod-subpath-array",
|
|
7634
|
+
title: "Official Zod subpath constructors retain the safe fix",
|
|
7635
|
+
outcome: "match",
|
|
7636
|
+
files: [{ path: "src/schema.ts", source: 'import { array, string } from "zod/v4"; const Items = array(string()).optional().default([]);' }],
|
|
7637
|
+
fixedFiles: [{ path: "src/schema.ts", source: 'import { array, string } from "zod/v4"; const Items = array(string()).default([]);' }],
|
|
7638
|
+
focusPath: "src/schema.ts",
|
|
7639
|
+
expectedCount: 1,
|
|
7640
|
+
public: true,
|
|
7641
|
+
scenarioId: "module-identity"
|
|
7605
7642
|
}
|
|
7606
7643
|
]
|
|
7607
7644
|
};
|
|
@@ -8799,11 +8836,12 @@ var NO_OFFSET_PAGINATION_DOCUMENTATION = {
|
|
|
8799
8836
|
limitations: ["A SELECT/FROM query shape or adjacent LIMIT/OFFSET fragment is required. Isolated OFFSET fragments and test files are excluded; this lexical context does not prove a database execution sink. Performance and concurrent-write behavior depend on indexes, ordering, isolation, and dialect; bounded pages and random page access can justify OFFSET."],
|
|
8800
8837
|
examples: [
|
|
8801
8838
|
{ id: "keyset-pagination", title: "Page from a stable cursor", outcome: "no-match", files: [{ path: "src/runs.ts", source: "db.prepare(`SELECT id FROM runs WHERE id > ? ORDER BY id LIMIT ?`).all();" }], focusPath: "src/runs.ts", expectedCount: 0, public: true },
|
|
8802
|
-
{ id: "offset-pagination", title: "Do not page by offset", outcome: "match", files: [{ path: "src/runs.ts", source: "db.query(`SELECT id FROM runs ORDER BY id LIMIT ? OFFSET ?`);" }], focusPath: "src/runs.ts", expectedCount: 1, public: true }
|
|
8839
|
+
{ id: "offset-pagination", title: "Do not page by offset", outcome: "match", files: [{ path: "src/runs.ts", source: "db.query(`SELECT id FROM runs ORDER BY id LIMIT ? OFFSET ?`);" }], focusPath: "src/runs.ts", expectedCount: 1, public: true },
|
|
8840
|
+
{ id: "decoded-query", scenarioId: "native-decoded-sql", title: "Inspect native-decoded query text", outcome: "match", files: [{ path: "src/page.ts", source: 'db.query("SELECT id FROM runs ORDER BY id LIMIT 1 OFF\\u0053ET 1");' }], focusPath: "src/page.ts", expectedCount: 1, public: true },
|
|
8841
|
+
{ id: "decoded-comment-data", scenarioId: "native-decoded-sql", title: "Ignore native-decoded comment data", outcome: "no-match", files: [{ path: "src/page.ts", source: 'db.query("SELECT id FROM runs /* OFF\\x53ET 1 */");' }], focusPath: "src/page.ts", expectedCount: 0, public: true }
|
|
8803
8842
|
]
|
|
8804
8843
|
};
|
|
8805
8844
|
var OFFSET_PAGINATION = /\bOFFSET\s+(?:%s|%\(\w+\)s|\?\d*|:\w+|@\w+|\$\d+|\d+)/i;
|
|
8806
|
-
var OFFSET_GATE = /offset/i;
|
|
8807
8845
|
var PAGINATION_CONTEXT = /\bSELECT\b[\s\S]*\bFROM\b[\s\S]*\bOFFSET\b|\bLIMIT\s+(?:%s|%\(\w+\)s|\?\d*|:\w+|@\w+|\$\d+|\d+)\s+OFFSET\b/i;
|
|
8808
8846
|
var no_offset_pagination_default = createRule({
|
|
8809
8847
|
name: "no-offset-pagination",
|
|
@@ -8820,7 +8858,7 @@ var no_offset_pagination_default = createRule({
|
|
|
8820
8858
|
},
|
|
8821
8859
|
defaultOptions: [],
|
|
8822
8860
|
create(context) {
|
|
8823
|
-
if (isTestFile(context.filename)
|
|
8861
|
+
if (isTestFile(context.filename)) {
|
|
8824
8862
|
return {};
|
|
8825
8863
|
}
|
|
8826
8864
|
return createSqlListener((sql, node) => {
|
|
@@ -10937,7 +10975,9 @@ var NO_SELECT_STAR_DOCUMENTATION = {
|
|
|
10937
10975
|
limitations: ["Only statically visible embedded SQL is checked; quoted strings (including PostgreSQL dollar strings), comments, function arguments such as COUNT(*), and stars inside EXISTS are excluded. This is a bounded lexical scan, not a complete SQL parser."],
|
|
10938
10976
|
examples: [
|
|
10939
10977
|
{ id: "explicit-projection", title: "Select the required columns", outcome: "no-match", files: [{ path: "src/runs.ts", source: "db.prepare(`SELECT id, status FROM runs`).all();" }], focusPath: "src/runs.ts", expectedCount: 0, public: true },
|
|
10940
|
-
{ id: "wildcard-projection", title: "Do not select every column", outcome: "match", files: [{ path: "src/runs.ts", source: "db.prepare(`SELECT * FROM runs`).all();" }], focusPath: "src/runs.ts", expectedCount: 1, public: true }
|
|
10978
|
+
{ id: "wildcard-projection", title: "Do not select every column", outcome: "match", files: [{ path: "src/runs.ts", source: "db.prepare(`SELECT * FROM runs`).all();" }], focusPath: "src/runs.ts", expectedCount: 1, public: true },
|
|
10979
|
+
{ id: "decoded-query", scenarioId: "native-decoded-sql", title: "Inspect native-decoded query text", outcome: "match", files: [{ path: "src/page.ts", source: 'db.query("SEL\\u0045CT * FROM runs");' }], focusPath: "src/page.ts", expectedCount: 1, public: true },
|
|
10980
|
+
{ id: "decoded-comment-data", scenarioId: "native-decoded-sql", title: "Ignore native-decoded comment data", outcome: "no-match", files: [{ path: "src/page.ts", source: 'db.query("SEL\\x45CT id FROM runs /* SELECT * FROM runs */");' }], focusPath: "src/page.ts", expectedCount: 0, public: true }
|
|
10941
10981
|
]
|
|
10942
10982
|
};
|
|
10943
10983
|
var QUERY_SHAPE = /\bSELECT\b[\s\S]*?\bFROM\b/i;
|
|
@@ -10945,7 +10985,6 @@ var SELECT_KEYWORD = /\bSELECT\b/gi;
|
|
|
10945
10985
|
var FROM_KEYWORD = /^FROM\b/i;
|
|
10946
10986
|
var EXISTS_BEFORE = /\bEXISTS\s*\(\s*$/i;
|
|
10947
10987
|
var QUALIFIED_PREFIX = /\w\.$/;
|
|
10948
|
-
var SELECT_GATE = /select/i;
|
|
10949
10988
|
function hasRealSelectStar(sql) {
|
|
10950
10989
|
const selects = [...sql.matchAll(SELECT_KEYWORD)].map((m) => m.index);
|
|
10951
10990
|
for (let pos = 0; pos < sql.length; pos++) {
|
|
@@ -10994,7 +11033,7 @@ var no_select_star_default = createRule({
|
|
|
10994
11033
|
},
|
|
10995
11034
|
defaultOptions: [],
|
|
10996
11035
|
create(context) {
|
|
10997
|
-
if (isTestFile(context.filename)
|
|
11036
|
+
if (isTestFile(context.filename)) {
|
|
10998
11037
|
return {};
|
|
10999
11038
|
}
|
|
11000
11039
|
return createSqlListener((sql, node) => {
|
|
@@ -18945,16 +18984,20 @@ var PREFER_SWITCH_FOR_REPEATED_EQUALITY_DOCUMENTATION = {
|
|
|
18945
18984
|
],
|
|
18946
18985
|
examples: [
|
|
18947
18986
|
{ id: "switch-dispatch", title: "Make finite dispatch explicit", outcome: "no-match", files: [{ path: "src/render.ts", source: "switch (kind) { case 'a': return a(); case 'b': return b(); case 'c': return c(); default: return fallback(); }" }], focusPath: "src/render.ts", expectedCount: 0, public: true },
|
|
18948
|
-
{ id: "repeated-equality", title: "Avoid repeating the discriminant", outcome: "match", files: [{ path: "src/render.ts", source: "if (kind === 'a') return a(); else if (kind === 'b') return b(); else if (kind === 'c') return c();" }], focusPath: "src/render.ts", expectedCount: 1, public: true }
|
|
18987
|
+
{ id: "repeated-equality", title: "Avoid repeating the discriminant", outcome: "match", files: [{ path: "src/render.ts", source: "if (kind === 'a') return a(); else if (kind === 'b') return b(); else if (kind === 'c') return c();" }], focusPath: "src/render.ts", expectedCount: 1, public: true },
|
|
18988
|
+
{ id: "escaped-middle", scenarioId: "native-discriminant", title: "Use native identifier identity", outcome: "match", files: [{ path: "src/dispatch.ts", source: `function probe(kind){if(kind==='a')return 1;else if(\\u006bind==='b')return 2;else if(kind==='c')return 3;return 0;}
|
|
18989
|
+
console.log(JSON.stringify(["a","b","c","d"].map(probe)));` }], focusPath: "src/dispatch.ts", expectedCount: 1, public: true },
|
|
18990
|
+
{ id: "different-discriminants", scenarioId: "native-discriminant", title: "Use native identifier identity", outcome: "no-match", files: [{ path: "src/dispatch.ts", source: `function probe(kind){const other="other";if(kind==='a')return 1;else if(other==='b')return 2;else if(kind==='c')return 3;return 0;}
|
|
18991
|
+
console.log(JSON.stringify(["a","b","c","d"].map(probe)));` }], focusPath: "src/dispatch.ts", expectedCount: 0, public: true }
|
|
18949
18992
|
]
|
|
18950
18993
|
};
|
|
18951
|
-
function
|
|
18994
|
+
function discriminantName(test) {
|
|
18952
18995
|
if (test.type !== AST_NODE_TYPES95.BinaryExpression || test.operator !== "===") return null;
|
|
18953
18996
|
const leftIsCase = isCaseValue(test.left);
|
|
18954
18997
|
const rightIsCase = isCaseValue(test.right);
|
|
18955
18998
|
if (leftIsCase === rightIsCase) return null;
|
|
18956
18999
|
const discriminant = leftIsCase ? test.right : test.left;
|
|
18957
|
-
return discriminant.type === AST_NODE_TYPES95.Identifier ?
|
|
19000
|
+
return discriminant.type === AST_NODE_TYPES95.Identifier ? discriminant.name : null;
|
|
18958
19001
|
}
|
|
18959
19002
|
function isCaseValue(node) {
|
|
18960
19003
|
if (node.type === AST_NODE_TYPES95.Literal) return true;
|
|
@@ -18978,12 +19021,12 @@ var prefer_switch_for_repeated_equality_default = createRule({
|
|
|
18978
19021
|
return {
|
|
18979
19022
|
IfStatement(node) {
|
|
18980
19023
|
if (node.parent.type === AST_NODE_TYPES95.IfStatement && node.parent.alternate === node) return;
|
|
18981
|
-
const first =
|
|
19024
|
+
const first = discriminantName(node.test);
|
|
18982
19025
|
if (first === null) return;
|
|
18983
19026
|
let count = 1;
|
|
18984
19027
|
let current = node.alternate;
|
|
18985
19028
|
while (current?.type === AST_NODE_TYPES95.IfStatement) {
|
|
18986
|
-
if (
|
|
19029
|
+
if (discriminantName(current.test) !== first) return;
|
|
18987
19030
|
count += 1;
|
|
18988
19031
|
current = current.alternate;
|
|
18989
19032
|
}
|
|
@@ -22721,7 +22764,9 @@ var STORE_INSERT_REQUIRES_ON_CONFLICT_DOCUMENTATION = {
|
|
|
22721
22764
|
limitations: ["Only the nearest statically named callable is considered; top-level inserts and anonymous callbacks are excluded. Recognized conflict syntax does not prove idempotence or concurrency safety: WHERE NOT EXISTS can race, and INSERT OR REPLACE can delete an existing row. Review unique constraints and dialect semantics manually."],
|
|
22722
22765
|
examples: [
|
|
22723
22766
|
{ id: "conflict-safe-insert", title: "Review the conflict policy for a replayed insert", outcome: "no-match", files: [{ path: "src/store.ts", source: "function seed() { db.prepare(`INSERT INTO runs (id) VALUES (?) ON CONFLICT(id) DO NOTHING`).run(); }" }], focusPath: "src/store.ts", expectedCount: 0, public: true },
|
|
22724
|
-
{ id: "bare-insert", title: "Review a bare insert in a replay-named callable", outcome: "match", files: [{ path: "src/store.ts", source: "function seed() { db.prepare(`INSERT INTO runs (id) VALUES (?)`).run(); }" }], focusPath: "src/store.ts", expectedCount: 1, public: true }
|
|
22767
|
+
{ id: "bare-insert", title: "Review a bare insert in a replay-named callable", outcome: "match", files: [{ path: "src/store.ts", source: "function seed() { db.prepare(`INSERT INTO runs (id) VALUES (?)`).run(); }" }], focusPath: "src/store.ts", expectedCount: 1, public: true },
|
|
22768
|
+
{ id: "decoded-query", scenarioId: "native-decoded-sql", title: "Inspect native-decoded query text", outcome: "match", files: [{ path: "src/page.ts", source: `function seed(){db.query("INS\\u0045RT INTO runs(id,note) VALUES(4,'new')");}` }], focusPath: "src/page.ts", expectedCount: 1, public: true },
|
|
22769
|
+
{ id: "decoded-comment-data", scenarioId: "native-decoded-sql", title: "Ignore native-decoded comment data", outcome: "no-match", files: [{ path: "src/page.ts", source: `function seed(){db.query("SELECT id FROM runs /* INS\\x45RT INTO runs(id,note) VALUES(4,'new') */");}` }], focusPath: "src/page.ts", expectedCount: 0, public: true }
|
|
22725
22770
|
]
|
|
22726
22771
|
};
|
|
22727
22772
|
var INSERT_WRITE = /\bINSERT\s+(?:OR\s+\w+\s+)?INTO\s+[\w."'`?$:@-]+\s*(?:\([^)]*\)\s*)?(?:VALUES|SELECT|DEFAULT\s+VALUES)\b/i;
|
|
@@ -22741,7 +22786,6 @@ function owningCallableName(node) {
|
|
|
22741
22786
|
}
|
|
22742
22787
|
return null;
|
|
22743
22788
|
}
|
|
22744
|
-
var INSERT_GATE = /insert/i;
|
|
22745
22789
|
var store_insert_requires_on_conflict_default = createRule({
|
|
22746
22790
|
name: "store-insert-requires-on-conflict",
|
|
22747
22791
|
documentation: STORE_INSERT_REQUIRES_ON_CONFLICT_DOCUMENTATION,
|
|
@@ -22757,7 +22801,7 @@ var store_insert_requires_on_conflict_default = createRule({
|
|
|
22757
22801
|
},
|
|
22758
22802
|
defaultOptions: [],
|
|
22759
22803
|
create(context) {
|
|
22760
|
-
if (isTestFile(context.filename)
|
|
22804
|
+
if (isTestFile(context.filename)) {
|
|
22761
22805
|
return {};
|
|
22762
22806
|
}
|
|
22763
22807
|
return createSqlListener((sql, node) => {
|
|
@@ -24313,7 +24357,7 @@ var RULES = {
|
|
|
24313
24357
|
};
|
|
24314
24358
|
var meta = {
|
|
24315
24359
|
name: "@sarj/eslint-plugin",
|
|
24316
|
-
version: "16.4.
|
|
24360
|
+
version: "16.4.7"
|
|
24317
24361
|
};
|
|
24318
24362
|
var APPLICATION_ONLY_RULES = [];
|
|
24319
24363
|
var LIBRARY_IMPORT_POLICY = ["error", {
|