@sarj/eslint-plugin 3.0.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +23 -144
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -8
- package/dist/index.d.ts +0 -8
- package/dist/index.js +23 -144
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -7177,126 +7177,8 @@ var prefer_non_nullable_collection_default = import_utils51.ESLintUtils.RuleCrea
|
|
|
7177
7177
|
}
|
|
7178
7178
|
});
|
|
7179
7179
|
|
|
7180
|
-
// src/rules/primary-export-file-name.ts
|
|
7181
|
-
var import_utils52 = require("@typescript-eslint/utils");
|
|
7182
|
-
var CONVENTIONAL_BUCKET_EXPORTS = /* @__PURE__ */ new Set(["cn"]);
|
|
7183
|
-
var GENERIC_ENTRYPOINTS = /* @__PURE__ */ new Set(["main", "run", "cli", "setup", "teardown", "execute"]);
|
|
7184
|
-
var ACRONYM_OVERRIDES = [
|
|
7185
|
-
[/OAuth/g, "Oauth"],
|
|
7186
|
-
[/GraphQL/g, "Graphql"],
|
|
7187
|
-
[/gRPC/g, "Grpc"]
|
|
7188
|
-
];
|
|
7189
|
-
var CAMEL_BOUNDARY_RE = /(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/g;
|
|
7190
|
-
var basename = (filename) => filename.split(/[/\\]/).pop() ?? filename;
|
|
7191
|
-
var stemOf = (base) => base.replace(/\.(test|spec|config|d|stories)\.[cm]?[jt]sx?$/i, "").replace(/\.[cm]?[jt]sx?$/i, "");
|
|
7192
|
-
var kebabCase = (name) => {
|
|
7193
|
-
let normalized = name;
|
|
7194
|
-
for (const [pattern, replacement] of ACRONYM_OVERRIDES) {
|
|
7195
|
-
normalized = normalized.replace(pattern, replacement);
|
|
7196
|
-
}
|
|
7197
|
-
return normalized.replace(CAMEL_BOUNDARY_RE, "-").toLowerCase();
|
|
7198
|
-
};
|
|
7199
|
-
var isFunctionOrClass = (node) => node.type === import_utils52.AST_NODE_TYPES.ArrowFunctionExpression || node.type === import_utils52.AST_NODE_TYPES.FunctionExpression;
|
|
7200
|
-
var findPrimaryExport = (body) => {
|
|
7201
|
-
let exportCount = 0;
|
|
7202
|
-
let primaryCandidate = null;
|
|
7203
|
-
for (const statement of body) {
|
|
7204
|
-
if (statement.type === import_utils52.AST_NODE_TYPES.ExportAllDeclaration) {
|
|
7205
|
-
return null;
|
|
7206
|
-
}
|
|
7207
|
-
if (statement.type === import_utils52.AST_NODE_TYPES.ExportDefaultDeclaration) {
|
|
7208
|
-
exportCount += 1;
|
|
7209
|
-
const decl = statement.declaration;
|
|
7210
|
-
if ((decl.type === import_utils52.AST_NODE_TYPES.FunctionDeclaration || decl.type === import_utils52.AST_NODE_TYPES.ClassDeclaration) && decl.id !== null) {
|
|
7211
|
-
primaryCandidate = { name: decl.id.name, node: statement, isDefault: true };
|
|
7212
|
-
} else if (decl.type === import_utils52.AST_NODE_TYPES.Identifier) {
|
|
7213
|
-
primaryCandidate = { name: decl.name, node: statement, isDefault: true };
|
|
7214
|
-
}
|
|
7215
|
-
} else if (statement.type === import_utils52.AST_NODE_TYPES.ExportNamedDeclaration) {
|
|
7216
|
-
if (statement.source !== null) {
|
|
7217
|
-
return null;
|
|
7218
|
-
}
|
|
7219
|
-
const decl = statement.declaration;
|
|
7220
|
-
if (decl === null) {
|
|
7221
|
-
exportCount += statement.specifiers.length;
|
|
7222
|
-
if (statement.specifiers.length === 1 && primaryCandidate === null) {
|
|
7223
|
-
const spec = statement.specifiers[0];
|
|
7224
|
-
if (spec && spec.exported.type === import_utils52.AST_NODE_TYPES.Identifier) {
|
|
7225
|
-
primaryCandidate = { name: spec.exported.name, node: statement, isDefault: false };
|
|
7226
|
-
}
|
|
7227
|
-
}
|
|
7228
|
-
} else if (decl.type === import_utils52.AST_NODE_TYPES.FunctionDeclaration || decl.type === import_utils52.AST_NODE_TYPES.ClassDeclaration) {
|
|
7229
|
-
if (decl.id !== null) {
|
|
7230
|
-
exportCount += 1;
|
|
7231
|
-
if (primaryCandidate === null) {
|
|
7232
|
-
primaryCandidate = { name: decl.id.name, node: statement, isDefault: false };
|
|
7233
|
-
}
|
|
7234
|
-
}
|
|
7235
|
-
} else if (decl.type === import_utils52.AST_NODE_TYPES.VariableDeclaration) {
|
|
7236
|
-
for (const declarator of decl.declarations) {
|
|
7237
|
-
if (declarator.id.type === import_utils52.AST_NODE_TYPES.Identifier) {
|
|
7238
|
-
exportCount += 1;
|
|
7239
|
-
if (primaryCandidate === null && declarator.init && isFunctionOrClass(declarator.init)) {
|
|
7240
|
-
primaryCandidate = { name: declarator.id.name, node: statement, isDefault: false };
|
|
7241
|
-
}
|
|
7242
|
-
}
|
|
7243
|
-
}
|
|
7244
|
-
} else if (decl.type === import_utils52.AST_NODE_TYPES.TSTypeAliasDeclaration || decl.type === import_utils52.AST_NODE_TYPES.TSInterfaceDeclaration) {
|
|
7245
|
-
exportCount += 1;
|
|
7246
|
-
if (primaryCandidate === null) {
|
|
7247
|
-
primaryCandidate = { name: decl.id.name, node: statement, isDefault: false };
|
|
7248
|
-
}
|
|
7249
|
-
}
|
|
7250
|
-
}
|
|
7251
|
-
}
|
|
7252
|
-
if (primaryCandidate === null || exportCount > 2) {
|
|
7253
|
-
return null;
|
|
7254
|
-
}
|
|
7255
|
-
return { ...primaryCandidate, count: exportCount };
|
|
7256
|
-
};
|
|
7257
|
-
var primary_export_file_name_default = import_utils52.ESLintUtils.RuleCreator(
|
|
7258
|
-
(name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
|
|
7259
|
-
)({
|
|
7260
|
-
name: "primary-export-file-name",
|
|
7261
|
-
meta: {
|
|
7262
|
-
type: "suggestion",
|
|
7263
|
-
docs: {
|
|
7264
|
-
description: "Enforce semantic naming alignment: a file with a single primary export must be named after that export."
|
|
7265
|
-
},
|
|
7266
|
-
schema: [],
|
|
7267
|
-
messages: {
|
|
7268
|
-
primaryExportMismatch: "Module stem '{{stem}}' does not match its primary export '{{name}}' \u2014 rename the file to '{{expected}}{{ext}}' to describe its responsibility."
|
|
7269
|
-
}
|
|
7270
|
-
},
|
|
7271
|
-
defaultOptions: [],
|
|
7272
|
-
create(context) {
|
|
7273
|
-
const base = basename(context.filename);
|
|
7274
|
-
if (base.endsWith(".d.ts") || base.startsWith("index.") || base.startsWith("_")) return {};
|
|
7275
|
-
if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
7276
|
-
const stem3 = stemOf(base);
|
|
7277
|
-
if (stem3 === "page" || stem3 === "layout" || stem3 === "loading" || stem3 === "error" || stem3 === "not-found" || stem3 === "route" || stem3 === "__root" || stem3 === "config" || stem3 === "constants" || stem3 === "types" || stem3.startsWith("$") || stem3.startsWith("[")) {
|
|
7278
|
-
return {};
|
|
7279
|
-
}
|
|
7280
|
-
return {
|
|
7281
|
-
Program(node) {
|
|
7282
|
-
const primary = findPrimaryExport(node.body);
|
|
7283
|
-
if (primary === null) return;
|
|
7284
|
-
if (CONVENTIONAL_BUCKET_EXPORTS.has(primary.name) || GENERIC_ENTRYPOINTS.has(primary.name)) return;
|
|
7285
|
-
const expectedStem = kebabCase(primary.name);
|
|
7286
|
-
if (stem3 === expectedStem) return;
|
|
7287
|
-
const ext = base.endsWith(".tsx") ? ".tsx" : ".ts";
|
|
7288
|
-
context.report({
|
|
7289
|
-
node: primary.node,
|
|
7290
|
-
messageId: "primaryExportMismatch",
|
|
7291
|
-
data: { stem: stem3, name: primary.name, expected: expectedStem, ext }
|
|
7292
|
-
});
|
|
7293
|
-
}
|
|
7294
|
-
};
|
|
7295
|
-
}
|
|
7296
|
-
});
|
|
7297
|
-
|
|
7298
7180
|
// src/rules/no-implicit-attribute-access.ts
|
|
7299
|
-
var
|
|
7181
|
+
var import_utils52 = require("@typescript-eslint/utils");
|
|
7300
7182
|
var EXCLUDED_BASES = /* @__PURE__ */ new Set([
|
|
7301
7183
|
"environ",
|
|
7302
7184
|
"headers",
|
|
@@ -7312,15 +7194,15 @@ var EXCLUDED_BASES = /* @__PURE__ */ new Set([
|
|
|
7312
7194
|
"sessionStorage"
|
|
7313
7195
|
]);
|
|
7314
7196
|
function getBaseName(node) {
|
|
7315
|
-
if (node.type ===
|
|
7197
|
+
if (node.type === import_utils52.AST_NODE_TYPES.Identifier) {
|
|
7316
7198
|
return node.name;
|
|
7317
7199
|
}
|
|
7318
|
-
if (node.type ===
|
|
7200
|
+
if (node.type === import_utils52.AST_NODE_TYPES.MemberExpression && node.property.type === import_utils52.AST_NODE_TYPES.Identifier) {
|
|
7319
7201
|
return node.property.name;
|
|
7320
7202
|
}
|
|
7321
7203
|
return null;
|
|
7322
7204
|
}
|
|
7323
|
-
var no_implicit_attribute_access_default =
|
|
7205
|
+
var no_implicit_attribute_access_default = import_utils52.ESLintUtils.RuleCreator(
|
|
7324
7206
|
(name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
|
|
7325
7207
|
)({
|
|
7326
7208
|
name: "no-implicit-attribute-access",
|
|
@@ -7341,7 +7223,7 @@ var no_implicit_attribute_access_default = import_utils53.ESLintUtils.RuleCreato
|
|
|
7341
7223
|
if (!node.computed) {
|
|
7342
7224
|
return;
|
|
7343
7225
|
}
|
|
7344
|
-
if (node.property.type ===
|
|
7226
|
+
if (node.property.type === import_utils52.AST_NODE_TYPES.Literal && typeof node.property.value === "string") {
|
|
7345
7227
|
const baseName = getBaseName(node.object);
|
|
7346
7228
|
if (!baseName || !EXCLUDED_BASES.has(baseName)) {
|
|
7347
7229
|
context.report({
|
|
@@ -7354,11 +7236,11 @@ var no_implicit_attribute_access_default = import_utils53.ESLintUtils.RuleCreato
|
|
|
7354
7236
|
},
|
|
7355
7237
|
CallExpression(node) {
|
|
7356
7238
|
const callee = node.callee;
|
|
7357
|
-
if (callee.type ===
|
|
7358
|
-
const method = callee.property.type ===
|
|
7239
|
+
if (callee.type === import_utils52.AST_NODE_TYPES.MemberExpression) {
|
|
7240
|
+
const method = callee.property.type === import_utils52.AST_NODE_TYPES.Identifier ? callee.property.name : null;
|
|
7359
7241
|
if (method === "get") {
|
|
7360
7242
|
const arg = node.arguments[0];
|
|
7361
|
-
if (arg && arg.type ===
|
|
7243
|
+
if (arg && arg.type === import_utils52.AST_NODE_TYPES.Literal && typeof arg.value === "string") {
|
|
7362
7244
|
const baseName = getBaseName(callee.object);
|
|
7363
7245
|
if (!baseName || !EXCLUDED_BASES.has(baseName)) {
|
|
7364
7246
|
context.report({
|
|
@@ -7376,8 +7258,8 @@ var no_implicit_attribute_access_default = import_utils53.ESLintUtils.RuleCreato
|
|
|
7376
7258
|
});
|
|
7377
7259
|
|
|
7378
7260
|
// src/rules/strict-test-assertions.ts
|
|
7379
|
-
var
|
|
7380
|
-
var strict_test_assertions_default =
|
|
7261
|
+
var import_utils53 = require("@typescript-eslint/utils");
|
|
7262
|
+
var strict_test_assertions_default = import_utils53.ESLintUtils.RuleCreator.withoutDocs({
|
|
7381
7263
|
meta: {
|
|
7382
7264
|
type: "suggestion",
|
|
7383
7265
|
docs: {
|
|
@@ -7395,9 +7277,9 @@ var strict_test_assertions_default = import_utils54.ESLintUtils.RuleCreator.with
|
|
|
7395
7277
|
let currentObject = null;
|
|
7396
7278
|
let sequence = [];
|
|
7397
7279
|
function getExpectObject(expr) {
|
|
7398
|
-
if (expr.type ===
|
|
7280
|
+
if (expr.type === import_utils53.AST_NODE_TYPES.CallExpression && expr.callee.type === import_utils53.AST_NODE_TYPES.MemberExpression && expr.callee.object.type === import_utils53.AST_NODE_TYPES.CallExpression && expr.callee.object.callee.type === import_utils53.AST_NODE_TYPES.Identifier && expr.callee.object.callee.name === "expect" && expr.callee.object.arguments.length === 1) {
|
|
7399
7281
|
const arg = expr.callee.object.arguments.at(0);
|
|
7400
|
-
if (arg?.type ===
|
|
7282
|
+
if (arg?.type === import_utils53.AST_NODE_TYPES.MemberExpression) {
|
|
7401
7283
|
return arg.object;
|
|
7402
7284
|
}
|
|
7403
7285
|
}
|
|
@@ -7413,12 +7295,12 @@ var strict_test_assertions_default = import_utils54.ESLintUtils.RuleCreator.with
|
|
|
7413
7295
|
if (!currentObject) return null;
|
|
7414
7296
|
const objectText = context.sourceCode.getText(currentObject);
|
|
7415
7297
|
const props = sequence.map((stmt) => {
|
|
7416
|
-
if (stmt.expression.type !==
|
|
7298
|
+
if (stmt.expression.type !== import_utils53.AST_NODE_TYPES.CallExpression || stmt.expression.callee.type !== import_utils53.AST_NODE_TYPES.MemberExpression || stmt.expression.callee.object.type !== import_utils53.AST_NODE_TYPES.CallExpression) {
|
|
7417
7299
|
return null;
|
|
7418
7300
|
}
|
|
7419
7301
|
const actual = stmt.expression.callee.object.arguments.at(0);
|
|
7420
7302
|
const expected = stmt.expression.arguments.at(0);
|
|
7421
|
-
if (actual?.type ===
|
|
7303
|
+
if (actual?.type === import_utils53.AST_NODE_TYPES.MemberExpression && actual.property.type === import_utils53.AST_NODE_TYPES.Identifier && expected) {
|
|
7422
7304
|
const propName2 = actual.property.name;
|
|
7423
7305
|
const valText = context.sourceCode.getText(expected);
|
|
7424
7306
|
return `${propName2}: ${valText}`;
|
|
@@ -7436,7 +7318,7 @@ var strict_test_assertions_default = import_utils54.ESLintUtils.RuleCreator.with
|
|
|
7436
7318
|
}
|
|
7437
7319
|
}
|
|
7438
7320
|
for (const statement of body) {
|
|
7439
|
-
if (statement.type ===
|
|
7321
|
+
if (statement.type === import_utils53.AST_NODE_TYPES.ExpressionStatement) {
|
|
7440
7322
|
const obj = getExpectObject(statement.expression);
|
|
7441
7323
|
if (obj && currentObject && context.sourceCode.getText(obj) === context.sourceCode.getText(currentObject)) {
|
|
7442
7324
|
sequence.push(statement);
|
|
@@ -7470,8 +7352,8 @@ var strict_test_assertions_default = import_utils54.ESLintUtils.RuleCreator.with
|
|
|
7470
7352
|
});
|
|
7471
7353
|
|
|
7472
7354
|
// src/rules/no-async-callback-in-waitfor.ts
|
|
7473
|
-
var
|
|
7474
|
-
var no_async_callback_in_waitfor_default =
|
|
7355
|
+
var import_utils54 = require("@typescript-eslint/utils");
|
|
7356
|
+
var no_async_callback_in_waitfor_default = import_utils54.ESLintUtils.RuleCreator(
|
|
7475
7357
|
(name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
|
|
7476
7358
|
)({
|
|
7477
7359
|
name: "no-async-callback-in-waitfor",
|
|
@@ -7492,9 +7374,9 @@ var no_async_callback_in_waitfor_default = import_utils55.ESLintUtils.RuleCreato
|
|
|
7492
7374
|
}
|
|
7493
7375
|
return {
|
|
7494
7376
|
CallExpression(node) {
|
|
7495
|
-
if (node.callee.type ===
|
|
7377
|
+
if (node.callee.type === import_utils54.AST_NODE_TYPES.Identifier && node.callee.name === "waitFor") {
|
|
7496
7378
|
const callback = node.arguments[0];
|
|
7497
|
-
if (callback && (callback.type ===
|
|
7379
|
+
if (callback && (callback.type === import_utils54.AST_NODE_TYPES.ArrowFunctionExpression || callback.type === import_utils54.AST_NODE_TYPES.FunctionExpression) && callback.async) {
|
|
7498
7380
|
context.report({
|
|
7499
7381
|
node: callback,
|
|
7500
7382
|
messageId: "noAsyncCallbackInWaitFor"
|
|
@@ -7507,8 +7389,8 @@ var no_async_callback_in_waitfor_default = import_utils55.ESLintUtils.RuleCreato
|
|
|
7507
7389
|
});
|
|
7508
7390
|
|
|
7509
7391
|
// src/rules/prefer-setup-file-mocks.ts
|
|
7510
|
-
var
|
|
7511
|
-
var prefer_setup_file_mocks_default =
|
|
7392
|
+
var import_utils55 = require("@typescript-eslint/utils");
|
|
7393
|
+
var prefer_setup_file_mocks_default = import_utils55.ESLintUtils.RuleCreator(
|
|
7512
7394
|
(name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
|
|
7513
7395
|
)({
|
|
7514
7396
|
name: "prefer-setup-file-mocks",
|
|
@@ -7529,7 +7411,7 @@ var prefer_setup_file_mocks_default = import_utils56.ESLintUtils.RuleCreator(
|
|
|
7529
7411
|
}
|
|
7530
7412
|
return {
|
|
7531
7413
|
CallExpression(node) {
|
|
7532
|
-
if (node.callee.type ===
|
|
7414
|
+
if (node.callee.type === import_utils55.AST_NODE_TYPES.MemberExpression && node.callee.object.type === import_utils55.AST_NODE_TYPES.Identifier && (node.callee.object.name === "vi" || node.callee.object.name === "jest") && node.callee.property.type === import_utils55.AST_NODE_TYPES.Identifier && node.callee.property.name === "mock") {
|
|
7533
7415
|
context.report({
|
|
7534
7416
|
node,
|
|
7535
7417
|
messageId: "preferSetupFileMocks"
|
|
@@ -7567,7 +7449,6 @@ var rules = {
|
|
|
7567
7449
|
"no-unsafe-mock-casting": no_unsafe_mock_casting_default,
|
|
7568
7450
|
"prefer-string-literal-union": prefer_string_literal_union_default,
|
|
7569
7451
|
"prefer-zod-enum": prefer_zod_enum_default,
|
|
7570
|
-
"primary-export-file-name": primary_export_file_name_default,
|
|
7571
7452
|
"no-silent-promise-catch": no_silent_promise_catch_default,
|
|
7572
7453
|
"require-fetch-timeout": require_fetch_timeout_default,
|
|
7573
7454
|
"no-offset-pagination": no_offset_pagination_default,
|
|
@@ -7597,7 +7478,7 @@ var rules = {
|
|
|
7597
7478
|
var plugin = {
|
|
7598
7479
|
meta: {
|
|
7599
7480
|
name: "@sarj/eslint-plugin",
|
|
7600
|
-
version: "
|
|
7481
|
+
version: "4.0.0"
|
|
7601
7482
|
},
|
|
7602
7483
|
rules,
|
|
7603
7484
|
configs: {
|
|
@@ -7631,7 +7512,6 @@ var plugin = {
|
|
|
7631
7512
|
"@sarj/no-cors-wildcard-with-credentials": "warn",
|
|
7632
7513
|
"@sarj/no-secret-in-log": "warn",
|
|
7633
7514
|
"@sarj/no-unsafe-mock-casting": "warn",
|
|
7634
|
-
"@sarj/primary-export-file-name": "warn",
|
|
7635
7515
|
"@sarj/prefer-string-literal-union": "warn",
|
|
7636
7516
|
"@sarj/prefer-zod-enum": "warn",
|
|
7637
7517
|
// Mined from 2y of PR review feedback + 5-repo code-smell audit (2026-07).
|
|
@@ -7721,7 +7601,6 @@ var plugin = {
|
|
|
7721
7601
|
"@sarj/no-cors-wildcard-with-credentials": "error",
|
|
7722
7602
|
"@sarj/no-secret-in-log": "error",
|
|
7723
7603
|
"@sarj/no-unsafe-mock-casting": "error",
|
|
7724
|
-
"@sarj/primary-export-file-name": "error",
|
|
7725
7604
|
// Promoted to error 2026-07-25 — strict means strict (user directive).
|
|
7726
7605
|
"@sarj/prefer-string-literal-union": "error",
|
|
7727
7606
|
"@sarj/prefer-zod-enum": "error",
|