@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 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 import_utils53 = require("@typescript-eslint/utils");
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 === import_utils53.AST_NODE_TYPES.Identifier) {
7197
+ if (node.type === import_utils52.AST_NODE_TYPES.Identifier) {
7316
7198
  return node.name;
7317
7199
  }
7318
- if (node.type === import_utils53.AST_NODE_TYPES.MemberExpression && node.property.type === import_utils53.AST_NODE_TYPES.Identifier) {
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 = import_utils53.ESLintUtils.RuleCreator(
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 === import_utils53.AST_NODE_TYPES.Literal && typeof node.property.value === "string") {
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 === import_utils53.AST_NODE_TYPES.MemberExpression) {
7358
- const method = callee.property.type === import_utils53.AST_NODE_TYPES.Identifier ? callee.property.name : null;
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 === import_utils53.AST_NODE_TYPES.Literal && typeof arg.value === "string") {
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 import_utils54 = require("@typescript-eslint/utils");
7380
- var strict_test_assertions_default = import_utils54.ESLintUtils.RuleCreator.withoutDocs({
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 === import_utils54.AST_NODE_TYPES.CallExpression && expr.callee.type === import_utils54.AST_NODE_TYPES.MemberExpression && expr.callee.object.type === import_utils54.AST_NODE_TYPES.CallExpression && expr.callee.object.callee.type === import_utils54.AST_NODE_TYPES.Identifier && expr.callee.object.callee.name === "expect" && expr.callee.object.arguments.length === 1) {
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 === import_utils54.AST_NODE_TYPES.MemberExpression) {
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 !== import_utils54.AST_NODE_TYPES.CallExpression || stmt.expression.callee.type !== import_utils54.AST_NODE_TYPES.MemberExpression || stmt.expression.callee.object.type !== import_utils54.AST_NODE_TYPES.CallExpression) {
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 === import_utils54.AST_NODE_TYPES.MemberExpression && actual.property.type === import_utils54.AST_NODE_TYPES.Identifier && expected) {
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 === import_utils54.AST_NODE_TYPES.ExpressionStatement) {
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 import_utils55 = require("@typescript-eslint/utils");
7474
- var no_async_callback_in_waitfor_default = import_utils55.ESLintUtils.RuleCreator(
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 === import_utils55.AST_NODE_TYPES.Identifier && node.callee.name === "waitFor") {
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 === import_utils55.AST_NODE_TYPES.ArrowFunctionExpression || callback.type === import_utils55.AST_NODE_TYPES.FunctionExpression) && callback.async) {
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 import_utils56 = require("@typescript-eslint/utils");
7511
- var prefer_setup_file_mocks_default = import_utils56.ESLintUtils.RuleCreator(
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 === import_utils56.AST_NODE_TYPES.MemberExpression && node.callee.object.type === import_utils56.AST_NODE_TYPES.Identifier && (node.callee.object.name === "vi" || node.callee.object.name === "jest") && node.callee.property.type === import_utils56.AST_NODE_TYPES.Identifier && node.callee.property.name === "mock") {
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: "3.0.0"
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",