@sarj/eslint-plugin 15.6.6 → 15.6.8
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 +301 -13
- package/dist/index.d.cts +8 -2
- package/dist/index.d.ts +8 -2
- package/dist/index.js +299 -12
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
advisoryRules: () => advisoryRules,
|
|
33
34
|
applicationOnlyRules: () => applicationOnlyRules,
|
|
34
35
|
default: () => index_default,
|
|
35
36
|
publicDocumentation: () => publicDocumentation,
|
|
@@ -474,7 +475,7 @@ var duplicateTestBodyDocumentation = {
|
|
|
474
475
|
outcome: "no-match",
|
|
475
476
|
files: [{
|
|
476
477
|
path: "src/user.test.ts",
|
|
477
|
-
source: "test.each(['a', 'b'])('
|
|
478
|
+
source: "test.each(['a', 'b'])('accepts %s', (value) => { const result = parse(value); expect(result.ok).toBe(true); expect(result.value).toBe(value); });"
|
|
478
479
|
}],
|
|
479
480
|
focusPath: "src/user.test.ts",
|
|
480
481
|
expectedCount: 0,
|
|
@@ -486,7 +487,7 @@ var duplicateTestBodyDocumentation = {
|
|
|
486
487
|
outcome: "match",
|
|
487
488
|
files: [{
|
|
488
489
|
path: "src/user.test.ts",
|
|
489
|
-
source: "test('accepts a', () => { const result = parse(
|
|
490
|
+
source: "test('accepts a', () => { const value = 'a'; const result = parse(value); expect(result.ok).toBe(true); expect(result.value).toBe(value); });\ntest('accepts b', () => { const value = 'b'; const result = parse(value); expect(result.ok).toBe(true); expect(result.value).toBe(value); });"
|
|
490
491
|
}],
|
|
491
492
|
focusPath: "src/user.test.ts",
|
|
492
493
|
expectedCount: 1,
|
|
@@ -14784,8 +14785,290 @@ var stepdown_default = createRule({
|
|
|
14784
14785
|
}
|
|
14785
14786
|
});
|
|
14786
14787
|
|
|
14787
|
-
// src/rules/
|
|
14788
|
+
// src/rules/source-coupled-test.ts
|
|
14788
14789
|
var import_utils70 = require("@typescript-eslint/utils");
|
|
14790
|
+
var SOURCE_SUFFIX_RE = /\.(?:bash|hcl|sh|tf|tfvars|ya?ml|py|[cm]?[jt]s)$/iu;
|
|
14791
|
+
var FS_MODULES = /* @__PURE__ */ new Set(["fs", "node:fs", "fs/promises", "node:fs/promises"]);
|
|
14792
|
+
var FS_READERS = /* @__PURE__ */ new Set(["readFile", "readFileSync"]);
|
|
14793
|
+
var TEXT_TRANSFORMS = /* @__PURE__ */ new Set([
|
|
14794
|
+
"slice",
|
|
14795
|
+
"substring",
|
|
14796
|
+
"substr",
|
|
14797
|
+
"toLowerCase",
|
|
14798
|
+
"toString",
|
|
14799
|
+
"toUpperCase",
|
|
14800
|
+
"trim",
|
|
14801
|
+
"trimEnd",
|
|
14802
|
+
"trimStart",
|
|
14803
|
+
"replace",
|
|
14804
|
+
"replaceAll"
|
|
14805
|
+
]);
|
|
14806
|
+
var TEXT_PREDICATES = /* @__PURE__ */ new Set(["endsWith", "includes", "indexOf", "lastIndexOf", "match", "matchAll", "search", "startsWith"]);
|
|
14807
|
+
var REGEXP_PREDICATES = /* @__PURE__ */ new Set(["exec", "test"]);
|
|
14808
|
+
var EXPECT_MATCHERS = /* @__PURE__ */ new Set([
|
|
14809
|
+
"toBe",
|
|
14810
|
+
"toBeFalsy",
|
|
14811
|
+
"toBeGreaterThan",
|
|
14812
|
+
"toBeGreaterThanOrEqual",
|
|
14813
|
+
"toBeLessThan",
|
|
14814
|
+
"toBeLessThanOrEqual",
|
|
14815
|
+
"toBeNull",
|
|
14816
|
+
"toBeTruthy",
|
|
14817
|
+
"toContain",
|
|
14818
|
+
"toEqual",
|
|
14819
|
+
"toHaveLength",
|
|
14820
|
+
"toMatch",
|
|
14821
|
+
"toMatchSnapshot",
|
|
14822
|
+
"toStrictEqual"
|
|
14823
|
+
]);
|
|
14824
|
+
var EXPECT_MODIFIERS = /* @__PURE__ */ new Set(["not", "rejects", "resolves"]);
|
|
14825
|
+
var ASSERT_MATCHERS = /* @__PURE__ */ new Set(["deepEqual", "doesNotMatch", "equal", "match", "notDeepEqual", "notEqual", "notStrictEqual", "ok", "strictEqual"]);
|
|
14826
|
+
var sourceCoupledTestDocumentation = {
|
|
14827
|
+
summary: "Disallow raw repository source text as a test oracle; parse or execute the artifact instead.",
|
|
14828
|
+
rationale: "Substring and regex checks can pass on comments or unreachable configuration and fail after behavior-preserving formatting changes.",
|
|
14829
|
+
remediation: "Parse the artifact, execute its validator, or assert on Terraform plan JSON or another runtime contract.",
|
|
14830
|
+
category: "testing",
|
|
14831
|
+
limitations: [
|
|
14832
|
+
"The rule follows lexical aliases, source-path collections, awaited reads, and common text operations; interprocedural flows remain unreported.",
|
|
14833
|
+
"When raw representation is genuinely the contract (for example a golden or compatibility sentinel), use an exact line suppression with the reason."
|
|
14834
|
+
],
|
|
14835
|
+
examples: [
|
|
14836
|
+
{
|
|
14837
|
+
id: "parsed-policy-contract",
|
|
14838
|
+
title: "Assert on parsed policy behavior",
|
|
14839
|
+
outcome: "no-match",
|
|
14840
|
+
files: [{ path: "src/policy.test.ts", source: "import { readFileSync } from 'node:fs'; test('policy', () => { const policy = JSON.parse(readFileSync('policy.json', 'utf8')); expect(validate(policy)).toEqual([]); });" }],
|
|
14841
|
+
focusPath: "src/policy.test.ts",
|
|
14842
|
+
expectedCount: 0,
|
|
14843
|
+
public: true
|
|
14844
|
+
},
|
|
14845
|
+
{
|
|
14846
|
+
id: "terraform-substring-contract",
|
|
14847
|
+
title: "Do not prove Terraform behavior with a regex",
|
|
14848
|
+
outcome: "match",
|
|
14849
|
+
files: [{ path: "src/policy.test.ts", source: "import { readFileSync } from 'node:fs'; test('policy', () => { const source = readFileSync('main.tf', 'utf8'); expect(source).toMatch(/prevent_destroy/); });" }],
|
|
14850
|
+
focusPath: "src/policy.test.ts",
|
|
14851
|
+
expectedCount: 1,
|
|
14852
|
+
public: true
|
|
14853
|
+
}
|
|
14854
|
+
]
|
|
14855
|
+
};
|
|
14856
|
+
function staticMemberName5(node) {
|
|
14857
|
+
if (!node.computed && node.property.type === import_utils70.AST_NODE_TYPES.Identifier) return node.property.name;
|
|
14858
|
+
if (node.computed && node.property.type === import_utils70.AST_NODE_TYPES.Literal && typeof node.property.value === "string") return node.property.value;
|
|
14859
|
+
return null;
|
|
14860
|
+
}
|
|
14861
|
+
function unwrap5(node) {
|
|
14862
|
+
if (node.type === import_utils70.AST_NODE_TYPES.AwaitExpression) return unwrap5(node.argument);
|
|
14863
|
+
if (node.type === import_utils70.AST_NODE_TYPES.ChainExpression) return unwrap5(node.expression);
|
|
14864
|
+
if (node.type === import_utils70.AST_NODE_TYPES.TSAsExpression || node.type === import_utils70.AST_NODE_TYPES.TSNonNullExpression || node.type === import_utils70.AST_NODE_TYPES.TSTypeAssertion) return unwrap5(node.expression);
|
|
14865
|
+
return node;
|
|
14866
|
+
}
|
|
14867
|
+
function stringValue(node) {
|
|
14868
|
+
const current = unwrap5(node);
|
|
14869
|
+
if (current.type === import_utils70.AST_NODE_TYPES.Literal && typeof current.value === "string") return current.value;
|
|
14870
|
+
if (current.type === import_utils70.AST_NODE_TYPES.TemplateLiteral && current.expressions.length === 0) return current.quasis[0]?.value.cooked ?? null;
|
|
14871
|
+
return null;
|
|
14872
|
+
}
|
|
14873
|
+
function importSource(node) {
|
|
14874
|
+
return typeof node.source.value === "string" ? node.source.value : null;
|
|
14875
|
+
}
|
|
14876
|
+
function requireSource(node) {
|
|
14877
|
+
const current = unwrap5(node);
|
|
14878
|
+
if (current.type !== import_utils70.AST_NODE_TYPES.CallExpression || current.callee.type !== import_utils70.AST_NODE_TYPES.Identifier || current.callee.name !== "require" || current.arguments.length !== 1 || current.arguments[0]?.type === import_utils70.AST_NODE_TYPES.SpreadElement) return null;
|
|
14879
|
+
return stringValue(current.arguments[0]);
|
|
14880
|
+
}
|
|
14881
|
+
function newScope() {
|
|
14882
|
+
return { collections: /* @__PURE__ */ new Set(), declared: /* @__PURE__ */ new Set(), fsObjects: /* @__PURE__ */ new Set(), fsReaders: /* @__PURE__ */ new Set(), paths: /* @__PURE__ */ new Set(), rawOrigins: /* @__PURE__ */ new Map() };
|
|
14883
|
+
}
|
|
14884
|
+
var source_coupled_test_default = createRule({
|
|
14885
|
+
name: "source-coupled-test",
|
|
14886
|
+
documentation: sourceCoupledTestDocumentation,
|
|
14887
|
+
meta: {
|
|
14888
|
+
type: "suggestion",
|
|
14889
|
+
docs: { description: sourceCoupledTestDocumentation.summary },
|
|
14890
|
+
schema: [],
|
|
14891
|
+
messages: { rawSourceOracle: "Raw repository source text is the oracle. Parse or execute the artifact so comments, formatting, and unreachable blocks cannot satisfy the contract." }
|
|
14892
|
+
},
|
|
14893
|
+
defaultOptions: [],
|
|
14894
|
+
create(context) {
|
|
14895
|
+
if (!isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
14896
|
+
const scopes = [newScope()];
|
|
14897
|
+
const reportedOrigins = /* @__PURE__ */ new Set();
|
|
14898
|
+
const currentScope = () => scopes.at(-1) ?? scopes[0];
|
|
14899
|
+
const visible = (kind, name) => {
|
|
14900
|
+
for (let index = scopes.length - 1; index >= 0; index--) {
|
|
14901
|
+
const scope = scopes[index];
|
|
14902
|
+
if (scope.declared.has(name)) return scope[kind].has(name);
|
|
14903
|
+
}
|
|
14904
|
+
return false;
|
|
14905
|
+
};
|
|
14906
|
+
const visibleRawOrigins = (name) => {
|
|
14907
|
+
for (let index = scopes.length - 1; index >= 0; index--) {
|
|
14908
|
+
const scope = scopes[index];
|
|
14909
|
+
if (scope.declared.has(name)) return scope.rawOrigins.get(name) ?? /* @__PURE__ */ new Set();
|
|
14910
|
+
}
|
|
14911
|
+
return /* @__PURE__ */ new Set();
|
|
14912
|
+
};
|
|
14913
|
+
const sourcePath = (node) => {
|
|
14914
|
+
const current = unwrap5(node);
|
|
14915
|
+
const value = stringValue(current);
|
|
14916
|
+
if (value !== null) return SOURCE_SUFFIX_RE.test(value);
|
|
14917
|
+
if (current.type === import_utils70.AST_NODE_TYPES.Identifier) return visible("paths", current.name);
|
|
14918
|
+
if (current.type === import_utils70.AST_NODE_TYPES.BinaryExpression && current.operator === "+") {
|
|
14919
|
+
return sourcePath(current.left) || sourcePath(current.right);
|
|
14920
|
+
}
|
|
14921
|
+
if (current.type === import_utils70.AST_NODE_TYPES.TemplateLiteral) return current.expressions.some(sourcePath);
|
|
14922
|
+
if (current.type === import_utils70.AST_NODE_TYPES.CallExpression || current.type === import_utils70.AST_NODE_TYPES.NewExpression) {
|
|
14923
|
+
return current.arguments.some((argument) => argument.type !== import_utils70.AST_NODE_TYPES.SpreadElement && sourcePath(argument));
|
|
14924
|
+
}
|
|
14925
|
+
if (current.type === import_utils70.AST_NODE_TYPES.MemberExpression) return sourcePath(current.object);
|
|
14926
|
+
return false;
|
|
14927
|
+
};
|
|
14928
|
+
const rawRead = (node) => {
|
|
14929
|
+
const current = unwrap5(node);
|
|
14930
|
+
if (current.type !== import_utils70.AST_NODE_TYPES.CallExpression || current.arguments.length === 0) return false;
|
|
14931
|
+
const callee = unwrap5(current.callee);
|
|
14932
|
+
if (callee.type === import_utils70.AST_NODE_TYPES.Identifier) {
|
|
14933
|
+
return visible("fsReaders", callee.name) && sourcePath(current.arguments[0]);
|
|
14934
|
+
}
|
|
14935
|
+
if (callee.type !== import_utils70.AST_NODE_TYPES.MemberExpression) return false;
|
|
14936
|
+
const name = staticMemberName5(callee);
|
|
14937
|
+
const object = unwrap5(callee.object);
|
|
14938
|
+
return name !== null && FS_READERS.has(name) && object.type === import_utils70.AST_NODE_TYPES.Identifier && visible("fsObjects", object.name) && sourcePath(current.arguments[0]);
|
|
14939
|
+
};
|
|
14940
|
+
const rawOrigins = (node) => {
|
|
14941
|
+
const current = unwrap5(node);
|
|
14942
|
+
if (current.type === import_utils70.AST_NODE_TYPES.Identifier) return visibleRawOrigins(current.name);
|
|
14943
|
+
if (rawRead(current)) return /* @__PURE__ */ new Set([`${current.range[0]}:${current.range[1]}`]);
|
|
14944
|
+
if (current.type === import_utils70.AST_NODE_TYPES.BinaryExpression && current.operator === "+") return /* @__PURE__ */ new Set([...rawOrigins(current.left), ...rawOrigins(current.right)]);
|
|
14945
|
+
if (current.type !== import_utils70.AST_NODE_TYPES.CallExpression) return /* @__PURE__ */ new Set();
|
|
14946
|
+
const callee = unwrap5(current.callee);
|
|
14947
|
+
if (callee.type !== import_utils70.AST_NODE_TYPES.MemberExpression) return /* @__PURE__ */ new Set();
|
|
14948
|
+
const name = staticMemberName5(callee);
|
|
14949
|
+
return name !== null && TEXT_TRANSFORMS.has(name) ? rawOrigins(callee.object) : /* @__PURE__ */ new Set();
|
|
14950
|
+
};
|
|
14951
|
+
const evidenceOrigins = (node) => {
|
|
14952
|
+
const current = unwrap5(node);
|
|
14953
|
+
const direct = rawOrigins(current);
|
|
14954
|
+
if (direct.size > 0) return direct;
|
|
14955
|
+
if (current.type === import_utils70.AST_NODE_TYPES.BinaryExpression || current.type === import_utils70.AST_NODE_TYPES.LogicalExpression) return /* @__PURE__ */ new Set([...evidenceOrigins(current.left), ...evidenceOrigins(current.right)]);
|
|
14956
|
+
if (current.type === import_utils70.AST_NODE_TYPES.UnaryExpression) return evidenceOrigins(current.argument);
|
|
14957
|
+
if (current.type !== import_utils70.AST_NODE_TYPES.CallExpression) return /* @__PURE__ */ new Set();
|
|
14958
|
+
const callee = unwrap5(current.callee);
|
|
14959
|
+
if (callee.type !== import_utils70.AST_NODE_TYPES.MemberExpression) return /* @__PURE__ */ new Set();
|
|
14960
|
+
const name = staticMemberName5(callee);
|
|
14961
|
+
if (name !== null && TEXT_PREDICATES.has(name)) return rawOrigins(callee.object);
|
|
14962
|
+
if (name !== null && REGEXP_PREDICATES.has(name)) return new Set(current.arguments.flatMap((argument) => argument.type === import_utils70.AST_NODE_TYPES.SpreadElement ? [] : [...rawOrigins(argument)]));
|
|
14963
|
+
return /* @__PURE__ */ new Set();
|
|
14964
|
+
};
|
|
14965
|
+
const rawAssertionOrigins = (node) => {
|
|
14966
|
+
const callee = unwrap5(node.callee);
|
|
14967
|
+
if (callee.type === import_utils70.AST_NODE_TYPES.Identifier && callee.name === "assert") {
|
|
14968
|
+
return new Set(node.arguments.flatMap((argument) => argument.type === import_utils70.AST_NODE_TYPES.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
14969
|
+
}
|
|
14970
|
+
if (callee.type !== import_utils70.AST_NODE_TYPES.MemberExpression) return /* @__PURE__ */ new Set();
|
|
14971
|
+
const matcher = staticMemberName5(callee);
|
|
14972
|
+
if (matcher === null) return /* @__PURE__ */ new Set();
|
|
14973
|
+
let receiver = unwrap5(callee.object);
|
|
14974
|
+
while (receiver.type === import_utils70.AST_NODE_TYPES.MemberExpression && EXPECT_MODIFIERS.has(staticMemberName5(receiver) ?? "")) receiver = unwrap5(receiver.object);
|
|
14975
|
+
if (receiver.type === import_utils70.AST_NODE_TYPES.CallExpression && receiver.callee.type === import_utils70.AST_NODE_TYPES.Identifier && receiver.callee.name === "expect") {
|
|
14976
|
+
if (!EXPECT_MATCHERS.has(matcher)) return /* @__PURE__ */ new Set();
|
|
14977
|
+
return new Set([...receiver.arguments, ...node.arguments].flatMap((argument) => argument.type === import_utils70.AST_NODE_TYPES.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
14978
|
+
}
|
|
14979
|
+
if (receiver.type !== import_utils70.AST_NODE_TYPES.Identifier || receiver.name !== "assert" || !ASSERT_MATCHERS.has(matcher)) return /* @__PURE__ */ new Set();
|
|
14980
|
+
return new Set(node.arguments.flatMap((argument) => argument.type === import_utils70.AST_NODE_TYPES.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
14981
|
+
};
|
|
14982
|
+
const declare = (name, state) => {
|
|
14983
|
+
const scope = currentScope();
|
|
14984
|
+
scope.declared.add(name);
|
|
14985
|
+
scope.collections.delete(name);
|
|
14986
|
+
scope.fsObjects.delete(name);
|
|
14987
|
+
scope.fsReaders.delete(name);
|
|
14988
|
+
scope.paths.delete(name);
|
|
14989
|
+
scope.rawOrigins.delete(name);
|
|
14990
|
+
if (state.collection === true) scope.collections.add(name);
|
|
14991
|
+
if (state.fsObject === true) scope.fsObjects.add(name);
|
|
14992
|
+
if (state.fsReader === true) scope.fsReaders.add(name);
|
|
14993
|
+
if (state.path === true) scope.paths.add(name);
|
|
14994
|
+
if (state.rawOrigins !== void 0 && state.rawOrigins.size > 0) {
|
|
14995
|
+
scope.rawOrigins.set(name, state.rawOrigins);
|
|
14996
|
+
}
|
|
14997
|
+
};
|
|
14998
|
+
const sourceCollection = (node) => {
|
|
14999
|
+
const current = unwrap5(node);
|
|
15000
|
+
return current.type === import_utils70.AST_NODE_TYPES.ArrayExpression && current.elements.length > 0 && current.elements.every((element) => element !== null && element.type !== import_utils70.AST_NODE_TYPES.SpreadElement && sourcePath(element));
|
|
15001
|
+
};
|
|
15002
|
+
const declaredNames2 = (node) => {
|
|
15003
|
+
const current = unwrap5(node);
|
|
15004
|
+
if (current.type === import_utils70.AST_NODE_TYPES.Identifier) return [current.name];
|
|
15005
|
+
if (current.type === import_utils70.AST_NODE_TYPES.AssignmentPattern) return declaredNames2(current.left);
|
|
15006
|
+
if (current.type === import_utils70.AST_NODE_TYPES.RestElement) return declaredNames2(current.argument);
|
|
15007
|
+
if (current.type === import_utils70.AST_NODE_TYPES.ArrayPattern) return current.elements.flatMap((element) => element === null ? [] : declaredNames2(element));
|
|
15008
|
+
if (current.type === import_utils70.AST_NODE_TYPES.ObjectPattern) return current.properties.flatMap((property) => property.type === import_utils70.AST_NODE_TYPES.RestElement ? declaredNames2(property.argument) : declaredNames2(property.value));
|
|
15009
|
+
return [];
|
|
15010
|
+
};
|
|
15011
|
+
const enterFunction = (node) => {
|
|
15012
|
+
scopes.push(newScope());
|
|
15013
|
+
for (const parameter of node.params) for (const name of declaredNames2(parameter)) declare(name, {});
|
|
15014
|
+
};
|
|
15015
|
+
const exitFunction = () => {
|
|
15016
|
+
scopes.pop();
|
|
15017
|
+
};
|
|
15018
|
+
return {
|
|
15019
|
+
ImportDeclaration(node) {
|
|
15020
|
+
const source = importSource(node);
|
|
15021
|
+
if (source === null || !FS_MODULES.has(source)) return;
|
|
15022
|
+
for (const specifier of node.specifiers) {
|
|
15023
|
+
if (specifier.type === import_utils70.AST_NODE_TYPES.ImportSpecifier) {
|
|
15024
|
+
const imported = specifier.imported.type === import_utils70.AST_NODE_TYPES.Identifier ? specifier.imported.name : String(specifier.imported.value);
|
|
15025
|
+
if (FS_READERS.has(imported)) declare(specifier.local.name, { fsReader: true });
|
|
15026
|
+
} else {
|
|
15027
|
+
declare(specifier.local.name, { fsObject: true });
|
|
15028
|
+
}
|
|
15029
|
+
}
|
|
15030
|
+
},
|
|
15031
|
+
":function": enterFunction,
|
|
15032
|
+
":function:exit": exitFunction,
|
|
15033
|
+
VariableDeclarator(node) {
|
|
15034
|
+
if (node.init === null) return;
|
|
15035
|
+
const required = requireSource(node.init);
|
|
15036
|
+
if (required !== null && FS_MODULES.has(required) && node.id.type === import_utils70.AST_NODE_TYPES.Identifier) {
|
|
15037
|
+
declare(node.id.name, { fsObject: true });
|
|
15038
|
+
return;
|
|
15039
|
+
}
|
|
15040
|
+
if (node.id.type === import_utils70.AST_NODE_TYPES.ObjectPattern && required !== null && FS_MODULES.has(required)) {
|
|
15041
|
+
for (const property of node.id.properties) {
|
|
15042
|
+
if (property.type !== import_utils70.AST_NODE_TYPES.Property || property.value.type !== import_utils70.AST_NODE_TYPES.Identifier) continue;
|
|
15043
|
+
const key = property.key.type === import_utils70.AST_NODE_TYPES.Identifier ? property.key.name : property.key.type === import_utils70.AST_NODE_TYPES.Literal ? String(property.key.value) : "";
|
|
15044
|
+
if (FS_READERS.has(key)) declare(property.value.name, { fsReader: true });
|
|
15045
|
+
}
|
|
15046
|
+
return;
|
|
15047
|
+
}
|
|
15048
|
+
if (node.id.type !== import_utils70.AST_NODE_TYPES.Identifier) return;
|
|
15049
|
+
declare(node.id.name, { collection: sourceCollection(node.init), path: sourcePath(node.init), rawOrigins: rawOrigins(node.init) });
|
|
15050
|
+
},
|
|
15051
|
+
AssignmentExpression(node) {
|
|
15052
|
+
if (node.left.type === import_utils70.AST_NODE_TYPES.Identifier) declare(node.left.name, { path: sourcePath(node.right), rawOrigins: rawOrigins(node.right) });
|
|
15053
|
+
},
|
|
15054
|
+
ForOfStatement(node) {
|
|
15055
|
+
const right = unwrap5(node.right);
|
|
15056
|
+
const collection = right.type === import_utils70.AST_NODE_TYPES.Identifier && visible("collections", right.name);
|
|
15057
|
+
const left = node.left.type === import_utils70.AST_NODE_TYPES.VariableDeclaration ? node.left.declarations[0]?.id : node.left;
|
|
15058
|
+
if (collection && left?.type === import_utils70.AST_NODE_TYPES.Identifier) declare(left.name, { path: true });
|
|
15059
|
+
},
|
|
15060
|
+
CallExpression(node) {
|
|
15061
|
+
const origins = rawAssertionOrigins(node);
|
|
15062
|
+
if (origins.size === 0 || [...origins].every((origin) => reportedOrigins.has(origin))) return;
|
|
15063
|
+
for (const origin of origins) reportedOrigins.add(origin);
|
|
15064
|
+
context.report({ node, messageId: "rawSourceOracle" });
|
|
15065
|
+
}
|
|
15066
|
+
};
|
|
15067
|
+
}
|
|
15068
|
+
});
|
|
15069
|
+
|
|
15070
|
+
// src/rules/zod-naming-convention.ts
|
|
15071
|
+
var import_utils71 = require("@typescript-eslint/utils");
|
|
14789
15072
|
var zodNamingConventionDocumentation = {
|
|
14790
15073
|
summary: "Enforce a consistent Zod schema naming convention \u2014 a `Z` prefix (`ZUser`) or a `Schema` suffix (`userSchema`); both are accepted by default.",
|
|
14791
15074
|
rationale: "A recognizable schema name distinguishes runtime validators from ordinary values at each use site.",
|
|
@@ -14826,18 +15109,18 @@ var NON_SCHEMA_TERMINALS = /* @__PURE__ */ new Set([
|
|
|
14826
15109
|
"prettifyError",
|
|
14827
15110
|
"treeifyError"
|
|
14828
15111
|
]);
|
|
14829
|
-
var terminalMethodName = (callee) => !callee.computed && callee.property.type ===
|
|
15112
|
+
var terminalMethodName = (callee) => !callee.computed && callee.property.type === import_utils71.AST_NODE_TYPES.Identifier ? callee.property.name : null;
|
|
14830
15113
|
var calleeChainRoot = (node) => {
|
|
14831
15114
|
let current = node;
|
|
14832
15115
|
for (; ; ) {
|
|
14833
|
-
if (current.type ===
|
|
15116
|
+
if (current.type === import_utils71.AST_NODE_TYPES.Identifier) {
|
|
14834
15117
|
return current;
|
|
14835
15118
|
}
|
|
14836
|
-
if (current.type ===
|
|
15119
|
+
if (current.type === import_utils71.AST_NODE_TYPES.MemberExpression) {
|
|
14837
15120
|
current = current.object;
|
|
14838
15121
|
continue;
|
|
14839
15122
|
}
|
|
14840
|
-
if (current.type ===
|
|
15123
|
+
if (current.type === import_utils71.AST_NODE_TYPES.CallExpression) {
|
|
14841
15124
|
current = current.callee;
|
|
14842
15125
|
continue;
|
|
14843
15126
|
}
|
|
@@ -14877,7 +15160,7 @@ var zod_naming_convention_default = createRule({
|
|
|
14877
15160
|
const acceptsSchemaWord = convention !== "prefix";
|
|
14878
15161
|
const zodBindings = /* @__PURE__ */ new Set();
|
|
14879
15162
|
function resolvedBinding(identifier) {
|
|
14880
|
-
return
|
|
15163
|
+
return import_utils71.ASTUtils.findVariable(
|
|
14881
15164
|
context.sourceCode.getScope(identifier),
|
|
14882
15165
|
identifier.name
|
|
14883
15166
|
);
|
|
@@ -14899,7 +15182,7 @@ var zod_naming_convention_default = createRule({
|
|
|
14899
15182
|
ImportDeclaration(node) {
|
|
14900
15183
|
if (!isZodModule(node.source.value)) return;
|
|
14901
15184
|
for (const specifier of node.specifiers) {
|
|
14902
|
-
if (specifier.type ===
|
|
15185
|
+
if (specifier.type === import_utils71.AST_NODE_TYPES.ImportNamespaceSpecifier || specifier.type === import_utils71.AST_NODE_TYPES.ImportDefaultSpecifier || specifier.type === import_utils71.AST_NODE_TYPES.ImportSpecifier && (specifier.imported.type === import_utils71.AST_NODE_TYPES.Identifier ? specifier.imported.name === "z" : specifier.imported.value === "z")) {
|
|
14903
15186
|
recordZodBinding(specifier.local);
|
|
14904
15187
|
}
|
|
14905
15188
|
}
|
|
@@ -14907,13 +15190,13 @@ var zod_naming_convention_default = createRule({
|
|
|
14907
15190
|
VariableDeclarator(node) {
|
|
14908
15191
|
const init = node.init;
|
|
14909
15192
|
if (init === null || init === void 0) return;
|
|
14910
|
-
if (init.type !==
|
|
15193
|
+
if (init.type !== import_utils71.AST_NODE_TYPES.CallExpression) return;
|
|
14911
15194
|
const callee = init.callee;
|
|
14912
|
-
if (callee.type !==
|
|
15195
|
+
if (callee.type !== import_utils71.AST_NODE_TYPES.MemberExpression) return;
|
|
14913
15196
|
if (!isZodChain(callee)) return;
|
|
14914
15197
|
const terminal = terminalMethodName(callee);
|
|
14915
15198
|
if (terminal !== null && NON_SCHEMA_TERMINALS.has(terminal)) return;
|
|
14916
|
-
if (node.id.type !==
|
|
15199
|
+
if (node.id.type !== import_utils71.AST_NODE_TYPES.Identifier) return;
|
|
14917
15200
|
if (test.test(node.id.name)) return;
|
|
14918
15201
|
if (acceptsSchemaWord && CONTAINS_SCHEMA_RE.test(node.id.name)) return;
|
|
14919
15202
|
context.report({
|
|
@@ -15070,17 +15353,19 @@ var rules = {
|
|
|
15070
15353
|
"require-zod-form-validation": require_zod_form_validation_default,
|
|
15071
15354
|
"store-insert-requires-on-conflict": store_insert_requires_on_conflict_default,
|
|
15072
15355
|
"stepdown": stepdown_default,
|
|
15356
|
+
"source-coupled-test": source_coupled_test_default,
|
|
15073
15357
|
"zod-naming-convention": zod_naming_convention_default
|
|
15074
15358
|
};
|
|
15075
15359
|
var meta = {
|
|
15076
15360
|
name: "@sarj/eslint-plugin",
|
|
15077
|
-
version: "15.6.
|
|
15361
|
+
version: "15.6.8"
|
|
15078
15362
|
};
|
|
15079
15363
|
var applicationOnlyRules = [
|
|
15080
15364
|
"no-restricted-library-load",
|
|
15081
15365
|
"prefer-native-random-uuid",
|
|
15082
15366
|
"prefer-shadcn-primitives"
|
|
15083
15367
|
];
|
|
15368
|
+
var advisoryRules = ["source-coupled-test"];
|
|
15084
15369
|
var recommendedRules = {
|
|
15085
15370
|
"@sarj/duplicate-test-body": "error",
|
|
15086
15371
|
"@sarj/enforce-file-structure": "error",
|
|
@@ -15138,6 +15423,7 @@ var recommendedRules = {
|
|
|
15138
15423
|
"@sarj/require-zod-form-validation": "error",
|
|
15139
15424
|
"@sarj/store-insert-requires-on-conflict": "error",
|
|
15140
15425
|
"@sarj/stepdown": "error",
|
|
15426
|
+
"@sarj/source-coupled-test": "warn",
|
|
15141
15427
|
"@sarj/zod-naming-convention": "error"
|
|
15142
15428
|
};
|
|
15143
15429
|
var strictRules = {
|
|
@@ -15201,6 +15487,7 @@ var strictRules = {
|
|
|
15201
15487
|
"@sarj/require-zod-form-validation": "error",
|
|
15202
15488
|
"@sarj/store-insert-requires-on-conflict": "error",
|
|
15203
15489
|
"@sarj/stepdown": "error",
|
|
15490
|
+
"@sarj/source-coupled-test": "warn",
|
|
15204
15491
|
"@sarj/zod-naming-convention": "error"
|
|
15205
15492
|
};
|
|
15206
15493
|
var plugin = {
|
|
@@ -15225,6 +15512,7 @@ var plugin = {
|
|
|
15225
15512
|
var index_default = plugin;
|
|
15226
15513
|
// Annotate the CommonJS export names for ESM import in node:
|
|
15227
15514
|
0 && (module.exports = {
|
|
15515
|
+
advisoryRules,
|
|
15228
15516
|
applicationOnlyRules,
|
|
15229
15517
|
publicDocumentation,
|
|
15230
15518
|
recommendedRules,
|
package/dist/index.d.cts
CHANGED
|
@@ -274,12 +274,15 @@ declare const rules: {
|
|
|
274
274
|
readonly "require-zod-form-validation": DocumentedRule<readonly [], "missingZodValidation">;
|
|
275
275
|
readonly "store-insert-requires-on-conflict": DocumentedRule<readonly [], "storeInsertRequiresOnConflict">;
|
|
276
276
|
readonly stepdown: DocumentedRule<[], "helperAboveOnlyCaller">;
|
|
277
|
+
readonly "source-coupled-test": DocumentedRule<readonly [], "rawSourceOracle">;
|
|
277
278
|
readonly "zod-naming-convention": DocumentedRule<readonly [{
|
|
278
279
|
convention?: "prefix" | "suffix" | "either";
|
|
279
280
|
}?], "zPrefix" | "schemaSuffix" | "zodSchemaName">;
|
|
280
281
|
};
|
|
281
282
|
/** Rules registered for application-profile configs but intentionally absent from general presets. */
|
|
282
283
|
declare const applicationOnlyRules: readonly ["no-restricted-library-load", "prefer-native-random-uuid", "prefer-shadcn-primitives"];
|
|
284
|
+
/** Calibrated rules that intentionally remain warnings until consumer-corpus precision is proven. */
|
|
285
|
+
declare const advisoryRules: readonly ["source-coupled-test"];
|
|
283
286
|
declare const recommendedRules: {
|
|
284
287
|
readonly "@sarj/duplicate-test-body": "error";
|
|
285
288
|
readonly "@sarj/enforce-file-structure": "error";
|
|
@@ -341,6 +344,7 @@ declare const recommendedRules: {
|
|
|
341
344
|
readonly "@sarj/require-zod-form-validation": "error";
|
|
342
345
|
readonly "@sarj/store-insert-requires-on-conflict": "error";
|
|
343
346
|
readonly "@sarj/stepdown": "error";
|
|
347
|
+
readonly "@sarj/source-coupled-test": "warn";
|
|
344
348
|
readonly "@sarj/zod-naming-convention": "error";
|
|
345
349
|
};
|
|
346
350
|
declare const strictRules: {
|
|
@@ -408,6 +412,7 @@ declare const strictRules: {
|
|
|
408
412
|
readonly "@sarj/require-zod-form-validation": "error";
|
|
409
413
|
readonly "@sarj/store-insert-requires-on-conflict": "error";
|
|
410
414
|
readonly "@sarj/stepdown": "error";
|
|
415
|
+
readonly "@sarj/source-coupled-test": "warn";
|
|
411
416
|
readonly "@sarj/zod-naming-convention": "error";
|
|
412
417
|
};
|
|
413
418
|
type FlatPreset = {
|
|
@@ -418,7 +423,7 @@ type FlatPreset = {
|
|
|
418
423
|
declare const plugin: {
|
|
419
424
|
readonly meta: {
|
|
420
425
|
readonly name: "@sarj/eslint-plugin";
|
|
421
|
-
readonly version: "15.6.
|
|
426
|
+
readonly version: "15.6.8";
|
|
422
427
|
};
|
|
423
428
|
readonly rules: {
|
|
424
429
|
readonly "duplicate-test-body": DocumentedRule<readonly [], "duplicateTestBody">;
|
|
@@ -507,6 +512,7 @@ declare const plugin: {
|
|
|
507
512
|
readonly "require-zod-form-validation": DocumentedRule<readonly [], "missingZodValidation">;
|
|
508
513
|
readonly "store-insert-requires-on-conflict": DocumentedRule<readonly [], "storeInsertRequiresOnConflict">;
|
|
509
514
|
readonly stepdown: DocumentedRule<[], "helperAboveOnlyCaller">;
|
|
515
|
+
readonly "source-coupled-test": DocumentedRule<readonly [], "rawSourceOracle">;
|
|
510
516
|
readonly "zod-naming-convention": DocumentedRule<readonly [{
|
|
511
517
|
convention?: "prefix" | "suffix" | "either";
|
|
512
518
|
}?], "zPrefix" | "schemaSuffix" | "zodSchemaName">;
|
|
@@ -518,4 +524,4 @@ declare const plugin: {
|
|
|
518
524
|
};
|
|
519
525
|
};
|
|
520
526
|
|
|
521
|
-
export { type RetiredRule, applicationOnlyRules, plugin as default, publicDocumentation, recommendedRules, renamedRules, retiredRules, rules, strictRules };
|
|
527
|
+
export { type RetiredRule, advisoryRules, applicationOnlyRules, plugin as default, publicDocumentation, recommendedRules, renamedRules, retiredRules, rules, strictRules };
|
package/dist/index.d.ts
CHANGED
|
@@ -274,12 +274,15 @@ declare const rules: {
|
|
|
274
274
|
readonly "require-zod-form-validation": DocumentedRule<readonly [], "missingZodValidation">;
|
|
275
275
|
readonly "store-insert-requires-on-conflict": DocumentedRule<readonly [], "storeInsertRequiresOnConflict">;
|
|
276
276
|
readonly stepdown: DocumentedRule<[], "helperAboveOnlyCaller">;
|
|
277
|
+
readonly "source-coupled-test": DocumentedRule<readonly [], "rawSourceOracle">;
|
|
277
278
|
readonly "zod-naming-convention": DocumentedRule<readonly [{
|
|
278
279
|
convention?: "prefix" | "suffix" | "either";
|
|
279
280
|
}?], "zPrefix" | "schemaSuffix" | "zodSchemaName">;
|
|
280
281
|
};
|
|
281
282
|
/** Rules registered for application-profile configs but intentionally absent from general presets. */
|
|
282
283
|
declare const applicationOnlyRules: readonly ["no-restricted-library-load", "prefer-native-random-uuid", "prefer-shadcn-primitives"];
|
|
284
|
+
/** Calibrated rules that intentionally remain warnings until consumer-corpus precision is proven. */
|
|
285
|
+
declare const advisoryRules: readonly ["source-coupled-test"];
|
|
283
286
|
declare const recommendedRules: {
|
|
284
287
|
readonly "@sarj/duplicate-test-body": "error";
|
|
285
288
|
readonly "@sarj/enforce-file-structure": "error";
|
|
@@ -341,6 +344,7 @@ declare const recommendedRules: {
|
|
|
341
344
|
readonly "@sarj/require-zod-form-validation": "error";
|
|
342
345
|
readonly "@sarj/store-insert-requires-on-conflict": "error";
|
|
343
346
|
readonly "@sarj/stepdown": "error";
|
|
347
|
+
readonly "@sarj/source-coupled-test": "warn";
|
|
344
348
|
readonly "@sarj/zod-naming-convention": "error";
|
|
345
349
|
};
|
|
346
350
|
declare const strictRules: {
|
|
@@ -408,6 +412,7 @@ declare const strictRules: {
|
|
|
408
412
|
readonly "@sarj/require-zod-form-validation": "error";
|
|
409
413
|
readonly "@sarj/store-insert-requires-on-conflict": "error";
|
|
410
414
|
readonly "@sarj/stepdown": "error";
|
|
415
|
+
readonly "@sarj/source-coupled-test": "warn";
|
|
411
416
|
readonly "@sarj/zod-naming-convention": "error";
|
|
412
417
|
};
|
|
413
418
|
type FlatPreset = {
|
|
@@ -418,7 +423,7 @@ type FlatPreset = {
|
|
|
418
423
|
declare const plugin: {
|
|
419
424
|
readonly meta: {
|
|
420
425
|
readonly name: "@sarj/eslint-plugin";
|
|
421
|
-
readonly version: "15.6.
|
|
426
|
+
readonly version: "15.6.8";
|
|
422
427
|
};
|
|
423
428
|
readonly rules: {
|
|
424
429
|
readonly "duplicate-test-body": DocumentedRule<readonly [], "duplicateTestBody">;
|
|
@@ -507,6 +512,7 @@ declare const plugin: {
|
|
|
507
512
|
readonly "require-zod-form-validation": DocumentedRule<readonly [], "missingZodValidation">;
|
|
508
513
|
readonly "store-insert-requires-on-conflict": DocumentedRule<readonly [], "storeInsertRequiresOnConflict">;
|
|
509
514
|
readonly stepdown: DocumentedRule<[], "helperAboveOnlyCaller">;
|
|
515
|
+
readonly "source-coupled-test": DocumentedRule<readonly [], "rawSourceOracle">;
|
|
510
516
|
readonly "zod-naming-convention": DocumentedRule<readonly [{
|
|
511
517
|
convention?: "prefix" | "suffix" | "either";
|
|
512
518
|
}?], "zPrefix" | "schemaSuffix" | "zodSchemaName">;
|
|
@@ -518,4 +524,4 @@ declare const plugin: {
|
|
|
518
524
|
};
|
|
519
525
|
};
|
|
520
526
|
|
|
521
|
-
export { type RetiredRule, applicationOnlyRules, plugin as default, publicDocumentation, recommendedRules, renamedRules, retiredRules, rules, strictRules };
|
|
527
|
+
export { type RetiredRule, advisoryRules, applicationOnlyRules, plugin as default, publicDocumentation, recommendedRules, renamedRules, retiredRules, rules, strictRules };
|
package/dist/index.js
CHANGED
|
@@ -431,7 +431,7 @@ var duplicateTestBodyDocumentation = {
|
|
|
431
431
|
outcome: "no-match",
|
|
432
432
|
files: [{
|
|
433
433
|
path: "src/user.test.ts",
|
|
434
|
-
source: "test.each(['a', 'b'])('
|
|
434
|
+
source: "test.each(['a', 'b'])('accepts %s', (value) => { const result = parse(value); expect(result.ok).toBe(true); expect(result.value).toBe(value); });"
|
|
435
435
|
}],
|
|
436
436
|
focusPath: "src/user.test.ts",
|
|
437
437
|
expectedCount: 0,
|
|
@@ -443,7 +443,7 @@ var duplicateTestBodyDocumentation = {
|
|
|
443
443
|
outcome: "match",
|
|
444
444
|
files: [{
|
|
445
445
|
path: "src/user.test.ts",
|
|
446
|
-
source: "test('accepts a', () => { const result = parse(
|
|
446
|
+
source: "test('accepts a', () => { const value = 'a'; const result = parse(value); expect(result.ok).toBe(true); expect(result.value).toBe(value); });\ntest('accepts b', () => { const value = 'b'; const result = parse(value); expect(result.ok).toBe(true); expect(result.value).toBe(value); });"
|
|
447
447
|
}],
|
|
448
448
|
focusPath: "src/user.test.ts",
|
|
449
449
|
expectedCount: 1,
|
|
@@ -14762,9 +14762,291 @@ var stepdown_default = createRule({
|
|
|
14762
14762
|
}
|
|
14763
14763
|
});
|
|
14764
14764
|
|
|
14765
|
+
// src/rules/source-coupled-test.ts
|
|
14766
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES56 } from "@typescript-eslint/utils";
|
|
14767
|
+
var SOURCE_SUFFIX_RE = /\.(?:bash|hcl|sh|tf|tfvars|ya?ml|py|[cm]?[jt]s)$/iu;
|
|
14768
|
+
var FS_MODULES = /* @__PURE__ */ new Set(["fs", "node:fs", "fs/promises", "node:fs/promises"]);
|
|
14769
|
+
var FS_READERS = /* @__PURE__ */ new Set(["readFile", "readFileSync"]);
|
|
14770
|
+
var TEXT_TRANSFORMS = /* @__PURE__ */ new Set([
|
|
14771
|
+
"slice",
|
|
14772
|
+
"substring",
|
|
14773
|
+
"substr",
|
|
14774
|
+
"toLowerCase",
|
|
14775
|
+
"toString",
|
|
14776
|
+
"toUpperCase",
|
|
14777
|
+
"trim",
|
|
14778
|
+
"trimEnd",
|
|
14779
|
+
"trimStart",
|
|
14780
|
+
"replace",
|
|
14781
|
+
"replaceAll"
|
|
14782
|
+
]);
|
|
14783
|
+
var TEXT_PREDICATES = /* @__PURE__ */ new Set(["endsWith", "includes", "indexOf", "lastIndexOf", "match", "matchAll", "search", "startsWith"]);
|
|
14784
|
+
var REGEXP_PREDICATES = /* @__PURE__ */ new Set(["exec", "test"]);
|
|
14785
|
+
var EXPECT_MATCHERS = /* @__PURE__ */ new Set([
|
|
14786
|
+
"toBe",
|
|
14787
|
+
"toBeFalsy",
|
|
14788
|
+
"toBeGreaterThan",
|
|
14789
|
+
"toBeGreaterThanOrEqual",
|
|
14790
|
+
"toBeLessThan",
|
|
14791
|
+
"toBeLessThanOrEqual",
|
|
14792
|
+
"toBeNull",
|
|
14793
|
+
"toBeTruthy",
|
|
14794
|
+
"toContain",
|
|
14795
|
+
"toEqual",
|
|
14796
|
+
"toHaveLength",
|
|
14797
|
+
"toMatch",
|
|
14798
|
+
"toMatchSnapshot",
|
|
14799
|
+
"toStrictEqual"
|
|
14800
|
+
]);
|
|
14801
|
+
var EXPECT_MODIFIERS = /* @__PURE__ */ new Set(["not", "rejects", "resolves"]);
|
|
14802
|
+
var ASSERT_MATCHERS = /* @__PURE__ */ new Set(["deepEqual", "doesNotMatch", "equal", "match", "notDeepEqual", "notEqual", "notStrictEqual", "ok", "strictEqual"]);
|
|
14803
|
+
var sourceCoupledTestDocumentation = {
|
|
14804
|
+
summary: "Disallow raw repository source text as a test oracle; parse or execute the artifact instead.",
|
|
14805
|
+
rationale: "Substring and regex checks can pass on comments or unreachable configuration and fail after behavior-preserving formatting changes.",
|
|
14806
|
+
remediation: "Parse the artifact, execute its validator, or assert on Terraform plan JSON or another runtime contract.",
|
|
14807
|
+
category: "testing",
|
|
14808
|
+
limitations: [
|
|
14809
|
+
"The rule follows lexical aliases, source-path collections, awaited reads, and common text operations; interprocedural flows remain unreported.",
|
|
14810
|
+
"When raw representation is genuinely the contract (for example a golden or compatibility sentinel), use an exact line suppression with the reason."
|
|
14811
|
+
],
|
|
14812
|
+
examples: [
|
|
14813
|
+
{
|
|
14814
|
+
id: "parsed-policy-contract",
|
|
14815
|
+
title: "Assert on parsed policy behavior",
|
|
14816
|
+
outcome: "no-match",
|
|
14817
|
+
files: [{ path: "src/policy.test.ts", source: "import { readFileSync } from 'node:fs'; test('policy', () => { const policy = JSON.parse(readFileSync('policy.json', 'utf8')); expect(validate(policy)).toEqual([]); });" }],
|
|
14818
|
+
focusPath: "src/policy.test.ts",
|
|
14819
|
+
expectedCount: 0,
|
|
14820
|
+
public: true
|
|
14821
|
+
},
|
|
14822
|
+
{
|
|
14823
|
+
id: "terraform-substring-contract",
|
|
14824
|
+
title: "Do not prove Terraform behavior with a regex",
|
|
14825
|
+
outcome: "match",
|
|
14826
|
+
files: [{ path: "src/policy.test.ts", source: "import { readFileSync } from 'node:fs'; test('policy', () => { const source = readFileSync('main.tf', 'utf8'); expect(source).toMatch(/prevent_destroy/); });" }],
|
|
14827
|
+
focusPath: "src/policy.test.ts",
|
|
14828
|
+
expectedCount: 1,
|
|
14829
|
+
public: true
|
|
14830
|
+
}
|
|
14831
|
+
]
|
|
14832
|
+
};
|
|
14833
|
+
function staticMemberName5(node) {
|
|
14834
|
+
if (!node.computed && node.property.type === AST_NODE_TYPES56.Identifier) return node.property.name;
|
|
14835
|
+
if (node.computed && node.property.type === AST_NODE_TYPES56.Literal && typeof node.property.value === "string") return node.property.value;
|
|
14836
|
+
return null;
|
|
14837
|
+
}
|
|
14838
|
+
function unwrap5(node) {
|
|
14839
|
+
if (node.type === AST_NODE_TYPES56.AwaitExpression) return unwrap5(node.argument);
|
|
14840
|
+
if (node.type === AST_NODE_TYPES56.ChainExpression) return unwrap5(node.expression);
|
|
14841
|
+
if (node.type === AST_NODE_TYPES56.TSAsExpression || node.type === AST_NODE_TYPES56.TSNonNullExpression || node.type === AST_NODE_TYPES56.TSTypeAssertion) return unwrap5(node.expression);
|
|
14842
|
+
return node;
|
|
14843
|
+
}
|
|
14844
|
+
function stringValue(node) {
|
|
14845
|
+
const current = unwrap5(node);
|
|
14846
|
+
if (current.type === AST_NODE_TYPES56.Literal && typeof current.value === "string") return current.value;
|
|
14847
|
+
if (current.type === AST_NODE_TYPES56.TemplateLiteral && current.expressions.length === 0) return current.quasis[0]?.value.cooked ?? null;
|
|
14848
|
+
return null;
|
|
14849
|
+
}
|
|
14850
|
+
function importSource(node) {
|
|
14851
|
+
return typeof node.source.value === "string" ? node.source.value : null;
|
|
14852
|
+
}
|
|
14853
|
+
function requireSource(node) {
|
|
14854
|
+
const current = unwrap5(node);
|
|
14855
|
+
if (current.type !== AST_NODE_TYPES56.CallExpression || current.callee.type !== AST_NODE_TYPES56.Identifier || current.callee.name !== "require" || current.arguments.length !== 1 || current.arguments[0]?.type === AST_NODE_TYPES56.SpreadElement) return null;
|
|
14856
|
+
return stringValue(current.arguments[0]);
|
|
14857
|
+
}
|
|
14858
|
+
function newScope() {
|
|
14859
|
+
return { collections: /* @__PURE__ */ new Set(), declared: /* @__PURE__ */ new Set(), fsObjects: /* @__PURE__ */ new Set(), fsReaders: /* @__PURE__ */ new Set(), paths: /* @__PURE__ */ new Set(), rawOrigins: /* @__PURE__ */ new Map() };
|
|
14860
|
+
}
|
|
14861
|
+
var source_coupled_test_default = createRule({
|
|
14862
|
+
name: "source-coupled-test",
|
|
14863
|
+
documentation: sourceCoupledTestDocumentation,
|
|
14864
|
+
meta: {
|
|
14865
|
+
type: "suggestion",
|
|
14866
|
+
docs: { description: sourceCoupledTestDocumentation.summary },
|
|
14867
|
+
schema: [],
|
|
14868
|
+
messages: { rawSourceOracle: "Raw repository source text is the oracle. Parse or execute the artifact so comments, formatting, and unreachable blocks cannot satisfy the contract." }
|
|
14869
|
+
},
|
|
14870
|
+
defaultOptions: [],
|
|
14871
|
+
create(context) {
|
|
14872
|
+
if (!isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
14873
|
+
const scopes = [newScope()];
|
|
14874
|
+
const reportedOrigins = /* @__PURE__ */ new Set();
|
|
14875
|
+
const currentScope = () => scopes.at(-1) ?? scopes[0];
|
|
14876
|
+
const visible = (kind, name) => {
|
|
14877
|
+
for (let index = scopes.length - 1; index >= 0; index--) {
|
|
14878
|
+
const scope = scopes[index];
|
|
14879
|
+
if (scope.declared.has(name)) return scope[kind].has(name);
|
|
14880
|
+
}
|
|
14881
|
+
return false;
|
|
14882
|
+
};
|
|
14883
|
+
const visibleRawOrigins = (name) => {
|
|
14884
|
+
for (let index = scopes.length - 1; index >= 0; index--) {
|
|
14885
|
+
const scope = scopes[index];
|
|
14886
|
+
if (scope.declared.has(name)) return scope.rawOrigins.get(name) ?? /* @__PURE__ */ new Set();
|
|
14887
|
+
}
|
|
14888
|
+
return /* @__PURE__ */ new Set();
|
|
14889
|
+
};
|
|
14890
|
+
const sourcePath = (node) => {
|
|
14891
|
+
const current = unwrap5(node);
|
|
14892
|
+
const value = stringValue(current);
|
|
14893
|
+
if (value !== null) return SOURCE_SUFFIX_RE.test(value);
|
|
14894
|
+
if (current.type === AST_NODE_TYPES56.Identifier) return visible("paths", current.name);
|
|
14895
|
+
if (current.type === AST_NODE_TYPES56.BinaryExpression && current.operator === "+") {
|
|
14896
|
+
return sourcePath(current.left) || sourcePath(current.right);
|
|
14897
|
+
}
|
|
14898
|
+
if (current.type === AST_NODE_TYPES56.TemplateLiteral) return current.expressions.some(sourcePath);
|
|
14899
|
+
if (current.type === AST_NODE_TYPES56.CallExpression || current.type === AST_NODE_TYPES56.NewExpression) {
|
|
14900
|
+
return current.arguments.some((argument) => argument.type !== AST_NODE_TYPES56.SpreadElement && sourcePath(argument));
|
|
14901
|
+
}
|
|
14902
|
+
if (current.type === AST_NODE_TYPES56.MemberExpression) return sourcePath(current.object);
|
|
14903
|
+
return false;
|
|
14904
|
+
};
|
|
14905
|
+
const rawRead = (node) => {
|
|
14906
|
+
const current = unwrap5(node);
|
|
14907
|
+
if (current.type !== AST_NODE_TYPES56.CallExpression || current.arguments.length === 0) return false;
|
|
14908
|
+
const callee = unwrap5(current.callee);
|
|
14909
|
+
if (callee.type === AST_NODE_TYPES56.Identifier) {
|
|
14910
|
+
return visible("fsReaders", callee.name) && sourcePath(current.arguments[0]);
|
|
14911
|
+
}
|
|
14912
|
+
if (callee.type !== AST_NODE_TYPES56.MemberExpression) return false;
|
|
14913
|
+
const name = staticMemberName5(callee);
|
|
14914
|
+
const object = unwrap5(callee.object);
|
|
14915
|
+
return name !== null && FS_READERS.has(name) && object.type === AST_NODE_TYPES56.Identifier && visible("fsObjects", object.name) && sourcePath(current.arguments[0]);
|
|
14916
|
+
};
|
|
14917
|
+
const rawOrigins = (node) => {
|
|
14918
|
+
const current = unwrap5(node);
|
|
14919
|
+
if (current.type === AST_NODE_TYPES56.Identifier) return visibleRawOrigins(current.name);
|
|
14920
|
+
if (rawRead(current)) return /* @__PURE__ */ new Set([`${current.range[0]}:${current.range[1]}`]);
|
|
14921
|
+
if (current.type === AST_NODE_TYPES56.BinaryExpression && current.operator === "+") return /* @__PURE__ */ new Set([...rawOrigins(current.left), ...rawOrigins(current.right)]);
|
|
14922
|
+
if (current.type !== AST_NODE_TYPES56.CallExpression) return /* @__PURE__ */ new Set();
|
|
14923
|
+
const callee = unwrap5(current.callee);
|
|
14924
|
+
if (callee.type !== AST_NODE_TYPES56.MemberExpression) return /* @__PURE__ */ new Set();
|
|
14925
|
+
const name = staticMemberName5(callee);
|
|
14926
|
+
return name !== null && TEXT_TRANSFORMS.has(name) ? rawOrigins(callee.object) : /* @__PURE__ */ new Set();
|
|
14927
|
+
};
|
|
14928
|
+
const evidenceOrigins = (node) => {
|
|
14929
|
+
const current = unwrap5(node);
|
|
14930
|
+
const direct = rawOrigins(current);
|
|
14931
|
+
if (direct.size > 0) return direct;
|
|
14932
|
+
if (current.type === AST_NODE_TYPES56.BinaryExpression || current.type === AST_NODE_TYPES56.LogicalExpression) return /* @__PURE__ */ new Set([...evidenceOrigins(current.left), ...evidenceOrigins(current.right)]);
|
|
14933
|
+
if (current.type === AST_NODE_TYPES56.UnaryExpression) return evidenceOrigins(current.argument);
|
|
14934
|
+
if (current.type !== AST_NODE_TYPES56.CallExpression) return /* @__PURE__ */ new Set();
|
|
14935
|
+
const callee = unwrap5(current.callee);
|
|
14936
|
+
if (callee.type !== AST_NODE_TYPES56.MemberExpression) return /* @__PURE__ */ new Set();
|
|
14937
|
+
const name = staticMemberName5(callee);
|
|
14938
|
+
if (name !== null && TEXT_PREDICATES.has(name)) return rawOrigins(callee.object);
|
|
14939
|
+
if (name !== null && REGEXP_PREDICATES.has(name)) return new Set(current.arguments.flatMap((argument) => argument.type === AST_NODE_TYPES56.SpreadElement ? [] : [...rawOrigins(argument)]));
|
|
14940
|
+
return /* @__PURE__ */ new Set();
|
|
14941
|
+
};
|
|
14942
|
+
const rawAssertionOrigins = (node) => {
|
|
14943
|
+
const callee = unwrap5(node.callee);
|
|
14944
|
+
if (callee.type === AST_NODE_TYPES56.Identifier && callee.name === "assert") {
|
|
14945
|
+
return new Set(node.arguments.flatMap((argument) => argument.type === AST_NODE_TYPES56.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
14946
|
+
}
|
|
14947
|
+
if (callee.type !== AST_NODE_TYPES56.MemberExpression) return /* @__PURE__ */ new Set();
|
|
14948
|
+
const matcher = staticMemberName5(callee);
|
|
14949
|
+
if (matcher === null) return /* @__PURE__ */ new Set();
|
|
14950
|
+
let receiver = unwrap5(callee.object);
|
|
14951
|
+
while (receiver.type === AST_NODE_TYPES56.MemberExpression && EXPECT_MODIFIERS.has(staticMemberName5(receiver) ?? "")) receiver = unwrap5(receiver.object);
|
|
14952
|
+
if (receiver.type === AST_NODE_TYPES56.CallExpression && receiver.callee.type === AST_NODE_TYPES56.Identifier && receiver.callee.name === "expect") {
|
|
14953
|
+
if (!EXPECT_MATCHERS.has(matcher)) return /* @__PURE__ */ new Set();
|
|
14954
|
+
return new Set([...receiver.arguments, ...node.arguments].flatMap((argument) => argument.type === AST_NODE_TYPES56.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
14955
|
+
}
|
|
14956
|
+
if (receiver.type !== AST_NODE_TYPES56.Identifier || receiver.name !== "assert" || !ASSERT_MATCHERS.has(matcher)) return /* @__PURE__ */ new Set();
|
|
14957
|
+
return new Set(node.arguments.flatMap((argument) => argument.type === AST_NODE_TYPES56.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
14958
|
+
};
|
|
14959
|
+
const declare = (name, state) => {
|
|
14960
|
+
const scope = currentScope();
|
|
14961
|
+
scope.declared.add(name);
|
|
14962
|
+
scope.collections.delete(name);
|
|
14963
|
+
scope.fsObjects.delete(name);
|
|
14964
|
+
scope.fsReaders.delete(name);
|
|
14965
|
+
scope.paths.delete(name);
|
|
14966
|
+
scope.rawOrigins.delete(name);
|
|
14967
|
+
if (state.collection === true) scope.collections.add(name);
|
|
14968
|
+
if (state.fsObject === true) scope.fsObjects.add(name);
|
|
14969
|
+
if (state.fsReader === true) scope.fsReaders.add(name);
|
|
14970
|
+
if (state.path === true) scope.paths.add(name);
|
|
14971
|
+
if (state.rawOrigins !== void 0 && state.rawOrigins.size > 0) {
|
|
14972
|
+
scope.rawOrigins.set(name, state.rawOrigins);
|
|
14973
|
+
}
|
|
14974
|
+
};
|
|
14975
|
+
const sourceCollection = (node) => {
|
|
14976
|
+
const current = unwrap5(node);
|
|
14977
|
+
return current.type === AST_NODE_TYPES56.ArrayExpression && current.elements.length > 0 && current.elements.every((element) => element !== null && element.type !== AST_NODE_TYPES56.SpreadElement && sourcePath(element));
|
|
14978
|
+
};
|
|
14979
|
+
const declaredNames2 = (node) => {
|
|
14980
|
+
const current = unwrap5(node);
|
|
14981
|
+
if (current.type === AST_NODE_TYPES56.Identifier) return [current.name];
|
|
14982
|
+
if (current.type === AST_NODE_TYPES56.AssignmentPattern) return declaredNames2(current.left);
|
|
14983
|
+
if (current.type === AST_NODE_TYPES56.RestElement) return declaredNames2(current.argument);
|
|
14984
|
+
if (current.type === AST_NODE_TYPES56.ArrayPattern) return current.elements.flatMap((element) => element === null ? [] : declaredNames2(element));
|
|
14985
|
+
if (current.type === AST_NODE_TYPES56.ObjectPattern) return current.properties.flatMap((property) => property.type === AST_NODE_TYPES56.RestElement ? declaredNames2(property.argument) : declaredNames2(property.value));
|
|
14986
|
+
return [];
|
|
14987
|
+
};
|
|
14988
|
+
const enterFunction = (node) => {
|
|
14989
|
+
scopes.push(newScope());
|
|
14990
|
+
for (const parameter of node.params) for (const name of declaredNames2(parameter)) declare(name, {});
|
|
14991
|
+
};
|
|
14992
|
+
const exitFunction = () => {
|
|
14993
|
+
scopes.pop();
|
|
14994
|
+
};
|
|
14995
|
+
return {
|
|
14996
|
+
ImportDeclaration(node) {
|
|
14997
|
+
const source = importSource(node);
|
|
14998
|
+
if (source === null || !FS_MODULES.has(source)) return;
|
|
14999
|
+
for (const specifier of node.specifiers) {
|
|
15000
|
+
if (specifier.type === AST_NODE_TYPES56.ImportSpecifier) {
|
|
15001
|
+
const imported = specifier.imported.type === AST_NODE_TYPES56.Identifier ? specifier.imported.name : String(specifier.imported.value);
|
|
15002
|
+
if (FS_READERS.has(imported)) declare(specifier.local.name, { fsReader: true });
|
|
15003
|
+
} else {
|
|
15004
|
+
declare(specifier.local.name, { fsObject: true });
|
|
15005
|
+
}
|
|
15006
|
+
}
|
|
15007
|
+
},
|
|
15008
|
+
":function": enterFunction,
|
|
15009
|
+
":function:exit": exitFunction,
|
|
15010
|
+
VariableDeclarator(node) {
|
|
15011
|
+
if (node.init === null) return;
|
|
15012
|
+
const required = requireSource(node.init);
|
|
15013
|
+
if (required !== null && FS_MODULES.has(required) && node.id.type === AST_NODE_TYPES56.Identifier) {
|
|
15014
|
+
declare(node.id.name, { fsObject: true });
|
|
15015
|
+
return;
|
|
15016
|
+
}
|
|
15017
|
+
if (node.id.type === AST_NODE_TYPES56.ObjectPattern && required !== null && FS_MODULES.has(required)) {
|
|
15018
|
+
for (const property of node.id.properties) {
|
|
15019
|
+
if (property.type !== AST_NODE_TYPES56.Property || property.value.type !== AST_NODE_TYPES56.Identifier) continue;
|
|
15020
|
+
const key = property.key.type === AST_NODE_TYPES56.Identifier ? property.key.name : property.key.type === AST_NODE_TYPES56.Literal ? String(property.key.value) : "";
|
|
15021
|
+
if (FS_READERS.has(key)) declare(property.value.name, { fsReader: true });
|
|
15022
|
+
}
|
|
15023
|
+
return;
|
|
15024
|
+
}
|
|
15025
|
+
if (node.id.type !== AST_NODE_TYPES56.Identifier) return;
|
|
15026
|
+
declare(node.id.name, { collection: sourceCollection(node.init), path: sourcePath(node.init), rawOrigins: rawOrigins(node.init) });
|
|
15027
|
+
},
|
|
15028
|
+
AssignmentExpression(node) {
|
|
15029
|
+
if (node.left.type === AST_NODE_TYPES56.Identifier) declare(node.left.name, { path: sourcePath(node.right), rawOrigins: rawOrigins(node.right) });
|
|
15030
|
+
},
|
|
15031
|
+
ForOfStatement(node) {
|
|
15032
|
+
const right = unwrap5(node.right);
|
|
15033
|
+
const collection = right.type === AST_NODE_TYPES56.Identifier && visible("collections", right.name);
|
|
15034
|
+
const left = node.left.type === AST_NODE_TYPES56.VariableDeclaration ? node.left.declarations[0]?.id : node.left;
|
|
15035
|
+
if (collection && left?.type === AST_NODE_TYPES56.Identifier) declare(left.name, { path: true });
|
|
15036
|
+
},
|
|
15037
|
+
CallExpression(node) {
|
|
15038
|
+
const origins = rawAssertionOrigins(node);
|
|
15039
|
+
if (origins.size === 0 || [...origins].every((origin) => reportedOrigins.has(origin))) return;
|
|
15040
|
+
for (const origin of origins) reportedOrigins.add(origin);
|
|
15041
|
+
context.report({ node, messageId: "rawSourceOracle" });
|
|
15042
|
+
}
|
|
15043
|
+
};
|
|
15044
|
+
}
|
|
15045
|
+
});
|
|
15046
|
+
|
|
14765
15047
|
// src/rules/zod-naming-convention.ts
|
|
14766
15048
|
import {
|
|
14767
|
-
AST_NODE_TYPES as
|
|
15049
|
+
AST_NODE_TYPES as AST_NODE_TYPES57,
|
|
14768
15050
|
ASTUtils as ASTUtils16
|
|
14769
15051
|
} from "@typescript-eslint/utils";
|
|
14770
15052
|
var zodNamingConventionDocumentation = {
|
|
@@ -14807,18 +15089,18 @@ var NON_SCHEMA_TERMINALS = /* @__PURE__ */ new Set([
|
|
|
14807
15089
|
"prettifyError",
|
|
14808
15090
|
"treeifyError"
|
|
14809
15091
|
]);
|
|
14810
|
-
var terminalMethodName = (callee) => !callee.computed && callee.property.type ===
|
|
15092
|
+
var terminalMethodName = (callee) => !callee.computed && callee.property.type === AST_NODE_TYPES57.Identifier ? callee.property.name : null;
|
|
14811
15093
|
var calleeChainRoot = (node) => {
|
|
14812
15094
|
let current = node;
|
|
14813
15095
|
for (; ; ) {
|
|
14814
|
-
if (current.type ===
|
|
15096
|
+
if (current.type === AST_NODE_TYPES57.Identifier) {
|
|
14815
15097
|
return current;
|
|
14816
15098
|
}
|
|
14817
|
-
if (current.type ===
|
|
15099
|
+
if (current.type === AST_NODE_TYPES57.MemberExpression) {
|
|
14818
15100
|
current = current.object;
|
|
14819
15101
|
continue;
|
|
14820
15102
|
}
|
|
14821
|
-
if (current.type ===
|
|
15103
|
+
if (current.type === AST_NODE_TYPES57.CallExpression) {
|
|
14822
15104
|
current = current.callee;
|
|
14823
15105
|
continue;
|
|
14824
15106
|
}
|
|
@@ -14880,7 +15162,7 @@ var zod_naming_convention_default = createRule({
|
|
|
14880
15162
|
ImportDeclaration(node) {
|
|
14881
15163
|
if (!isZodModule(node.source.value)) return;
|
|
14882
15164
|
for (const specifier of node.specifiers) {
|
|
14883
|
-
if (specifier.type ===
|
|
15165
|
+
if (specifier.type === AST_NODE_TYPES57.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES57.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES57.ImportSpecifier && (specifier.imported.type === AST_NODE_TYPES57.Identifier ? specifier.imported.name === "z" : specifier.imported.value === "z")) {
|
|
14884
15166
|
recordZodBinding(specifier.local);
|
|
14885
15167
|
}
|
|
14886
15168
|
}
|
|
@@ -14888,13 +15170,13 @@ var zod_naming_convention_default = createRule({
|
|
|
14888
15170
|
VariableDeclarator(node) {
|
|
14889
15171
|
const init = node.init;
|
|
14890
15172
|
if (init === null || init === void 0) return;
|
|
14891
|
-
if (init.type !==
|
|
15173
|
+
if (init.type !== AST_NODE_TYPES57.CallExpression) return;
|
|
14892
15174
|
const callee = init.callee;
|
|
14893
|
-
if (callee.type !==
|
|
15175
|
+
if (callee.type !== AST_NODE_TYPES57.MemberExpression) return;
|
|
14894
15176
|
if (!isZodChain(callee)) return;
|
|
14895
15177
|
const terminal = terminalMethodName(callee);
|
|
14896
15178
|
if (terminal !== null && NON_SCHEMA_TERMINALS.has(terminal)) return;
|
|
14897
|
-
if (node.id.type !==
|
|
15179
|
+
if (node.id.type !== AST_NODE_TYPES57.Identifier) return;
|
|
14898
15180
|
if (test.test(node.id.name)) return;
|
|
14899
15181
|
if (acceptsSchemaWord && CONTAINS_SCHEMA_RE.test(node.id.name)) return;
|
|
14900
15182
|
context.report({
|
|
@@ -15051,17 +15333,19 @@ var rules = {
|
|
|
15051
15333
|
"require-zod-form-validation": require_zod_form_validation_default,
|
|
15052
15334
|
"store-insert-requires-on-conflict": store_insert_requires_on_conflict_default,
|
|
15053
15335
|
"stepdown": stepdown_default,
|
|
15336
|
+
"source-coupled-test": source_coupled_test_default,
|
|
15054
15337
|
"zod-naming-convention": zod_naming_convention_default
|
|
15055
15338
|
};
|
|
15056
15339
|
var meta = {
|
|
15057
15340
|
name: "@sarj/eslint-plugin",
|
|
15058
|
-
version: "15.6.
|
|
15341
|
+
version: "15.6.8"
|
|
15059
15342
|
};
|
|
15060
15343
|
var applicationOnlyRules = [
|
|
15061
15344
|
"no-restricted-library-load",
|
|
15062
15345
|
"prefer-native-random-uuid",
|
|
15063
15346
|
"prefer-shadcn-primitives"
|
|
15064
15347
|
];
|
|
15348
|
+
var advisoryRules = ["source-coupled-test"];
|
|
15065
15349
|
var recommendedRules = {
|
|
15066
15350
|
"@sarj/duplicate-test-body": "error",
|
|
15067
15351
|
"@sarj/enforce-file-structure": "error",
|
|
@@ -15119,6 +15403,7 @@ var recommendedRules = {
|
|
|
15119
15403
|
"@sarj/require-zod-form-validation": "error",
|
|
15120
15404
|
"@sarj/store-insert-requires-on-conflict": "error",
|
|
15121
15405
|
"@sarj/stepdown": "error",
|
|
15406
|
+
"@sarj/source-coupled-test": "warn",
|
|
15122
15407
|
"@sarj/zod-naming-convention": "error"
|
|
15123
15408
|
};
|
|
15124
15409
|
var strictRules = {
|
|
@@ -15182,6 +15467,7 @@ var strictRules = {
|
|
|
15182
15467
|
"@sarj/require-zod-form-validation": "error",
|
|
15183
15468
|
"@sarj/store-insert-requires-on-conflict": "error",
|
|
15184
15469
|
"@sarj/stepdown": "error",
|
|
15470
|
+
"@sarj/source-coupled-test": "warn",
|
|
15185
15471
|
"@sarj/zod-naming-convention": "error"
|
|
15186
15472
|
};
|
|
15187
15473
|
var plugin = {
|
|
@@ -15205,6 +15491,7 @@ var plugin = {
|
|
|
15205
15491
|
};
|
|
15206
15492
|
var index_default = plugin;
|
|
15207
15493
|
export {
|
|
15494
|
+
advisoryRules,
|
|
15208
15495
|
applicationOnlyRules,
|
|
15209
15496
|
index_default as default,
|
|
15210
15497
|
publicDocumentation,
|