@sarj/eslint-plugin 2.4.1 → 2.5.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.d.cts CHANGED
@@ -72,6 +72,9 @@ declare const rules: {
72
72
  "no-secret-in-log": _typescript_eslint_utils_ts_eslint.RuleModule<"noSecretInLog", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
73
73
  name: string;
74
74
  };
75
+ "no-unsafe-cast": _typescript_eslint_utils_ts_eslint.RuleModule<"asAny" | "doubleCast", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
76
+ name: string;
77
+ };
75
78
  "prefer-string-literal-union": _typescript_eslint_utils_ts_eslint.RuleModule<"bareChoiceField" | "comparisonCluster", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
76
79
  name: string;
77
80
  };
@@ -156,6 +159,9 @@ declare const plugin: {
156
159
  "no-secret-in-log": _typescript_eslint_utils_ts_eslint.RuleModule<"noSecretInLog", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
157
160
  name: string;
158
161
  };
162
+ "no-unsafe-cast": _typescript_eslint_utils_ts_eslint.RuleModule<"asAny" | "doubleCast", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
163
+ name: string;
164
+ };
159
165
  "prefer-string-literal-union": _typescript_eslint_utils_ts_eslint.RuleModule<"bareChoiceField" | "comparisonCluster", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
160
166
  name: string;
161
167
  };
@@ -187,6 +193,7 @@ declare const plugin: {
187
193
  "@sarj/no-fat-try-blocks": string;
188
194
  "@sarj/no-cors-wildcard-with-credentials": string;
189
195
  "@sarj/no-secret-in-log": string;
196
+ "@sarj/no-unsafe-cast": string;
190
197
  "@sarj/single-public-export": string;
191
198
  "@sarj/prefer-string-literal-union": string;
192
199
  };
@@ -217,6 +224,7 @@ declare const plugin: {
217
224
  "@sarj/no-fat-try-blocks": string;
218
225
  "@sarj/no-cors-wildcard-with-credentials": string;
219
226
  "@sarj/no-secret-in-log": string;
227
+ "@sarj/no-unsafe-cast": string;
220
228
  "@sarj/single-public-export": string;
221
229
  "@sarj/prefer-string-literal-union": string;
222
230
  };
package/dist/index.d.ts CHANGED
@@ -72,6 +72,9 @@ declare const rules: {
72
72
  "no-secret-in-log": _typescript_eslint_utils_ts_eslint.RuleModule<"noSecretInLog", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
73
73
  name: string;
74
74
  };
75
+ "no-unsafe-cast": _typescript_eslint_utils_ts_eslint.RuleModule<"asAny" | "doubleCast", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
76
+ name: string;
77
+ };
75
78
  "prefer-string-literal-union": _typescript_eslint_utils_ts_eslint.RuleModule<"bareChoiceField" | "comparisonCluster", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
76
79
  name: string;
77
80
  };
@@ -156,6 +159,9 @@ declare const plugin: {
156
159
  "no-secret-in-log": _typescript_eslint_utils_ts_eslint.RuleModule<"noSecretInLog", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
157
160
  name: string;
158
161
  };
162
+ "no-unsafe-cast": _typescript_eslint_utils_ts_eslint.RuleModule<"asAny" | "doubleCast", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
163
+ name: string;
164
+ };
159
165
  "prefer-string-literal-union": _typescript_eslint_utils_ts_eslint.RuleModule<"bareChoiceField" | "comparisonCluster", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
160
166
  name: string;
161
167
  };
@@ -187,6 +193,7 @@ declare const plugin: {
187
193
  "@sarj/no-fat-try-blocks": string;
188
194
  "@sarj/no-cors-wildcard-with-credentials": string;
189
195
  "@sarj/no-secret-in-log": string;
196
+ "@sarj/no-unsafe-cast": string;
190
197
  "@sarj/single-public-export": string;
191
198
  "@sarj/prefer-string-literal-union": string;
192
199
  };
@@ -217,6 +224,7 @@ declare const plugin: {
217
224
  "@sarj/no-fat-try-blocks": string;
218
225
  "@sarj/no-cors-wildcard-with-credentials": string;
219
226
  "@sarj/no-secret-in-log": string;
227
+ "@sarj/no-unsafe-cast": string;
220
228
  "@sarj/single-public-export": string;
221
229
  "@sarj/prefer-string-literal-union": string;
222
230
  };
package/dist/index.js CHANGED
@@ -3230,10 +3230,56 @@ var no_secret_in_log_default = ESLintUtils23.RuleCreator(
3230
3230
  }
3231
3231
  });
3232
3232
 
3233
+ // src/rules/no-unsafe-cast.ts
3234
+ import { ESLintUtils as ESLintUtils24 } from "@typescript-eslint/utils";
3235
+ import { AST_NODE_TYPES as AST_NODE_TYPES13 } from "@typescript-eslint/utils";
3236
+ function isAnyAnnotation(node) {
3237
+ return node.type === AST_NODE_TYPES13.TSAnyKeyword;
3238
+ }
3239
+ function isConstAssertion(typeAnnotation) {
3240
+ return typeAnnotation.type === AST_NODE_TYPES13.TSTypeReference && typeAnnotation.typeName.type === AST_NODE_TYPES13.Identifier && typeAnnotation.typeName.name === "const";
3241
+ }
3242
+ var no_unsafe_cast_default = ESLintUtils24.RuleCreator(
3243
+ (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3244
+ )({
3245
+ name: "no-unsafe-cast",
3246
+ meta: {
3247
+ type: "problem",
3248
+ docs: {
3249
+ description: "Disallow `as any`/`<any>` casts and `as unknown as T` double-casts, which fully disable type checking."
3250
+ },
3251
+ schema: [],
3252
+ messages: {
3253
+ asAny: "`as any` disables type checking on this value. Narrow with a type guard, model the shape, or cast to a specific type instead.",
3254
+ doubleCast: "`as unknown as T` double-cast bypasses the compiler's structural check. Prefer a runtime validator (e.g. a zod schema) or an accurate type at the boundary."
3255
+ }
3256
+ },
3257
+ defaultOptions: [],
3258
+ create(context) {
3259
+ function checkAssertion(node) {
3260
+ if (isConstAssertion(node.typeAnnotation)) {
3261
+ return;
3262
+ }
3263
+ if (isAnyAnnotation(node.typeAnnotation)) {
3264
+ context.report({ node, messageId: "asAny" });
3265
+ return;
3266
+ }
3267
+ const inner = node.expression;
3268
+ if (inner.type === AST_NODE_TYPES13.TSAsExpression || inner.type === AST_NODE_TYPES13.TSTypeAssertion) {
3269
+ context.report({ node, messageId: "doubleCast" });
3270
+ }
3271
+ }
3272
+ return {
3273
+ TSAsExpression: checkAssertion,
3274
+ TSTypeAssertion: checkAssertion
3275
+ };
3276
+ }
3277
+ });
3278
+
3233
3279
  // src/rules/prefer-string-literal-union.ts
3234
3280
  import {
3235
- ESLintUtils as ESLintUtils24,
3236
- AST_NODE_TYPES as AST_NODE_TYPES13
3281
+ ESLintUtils as ESLintUtils25,
3282
+ AST_NODE_TYPES as AST_NODE_TYPES14
3237
3283
  } from "@typescript-eslint/utils";
3238
3284
  import * as ts from "typescript";
3239
3285
  var CHOICE_TOKENS = /* @__PURE__ */ new Set([
@@ -3277,19 +3323,19 @@ function isChoiceLikeName(name) {
3277
3323
  return CHOICE_TOKENS.has(lastWord(name));
3278
3324
  }
3279
3325
  function keyName(key) {
3280
- if (key.type === AST_NODE_TYPES13.Identifier) {
3326
+ if (key.type === AST_NODE_TYPES14.Identifier) {
3281
3327
  return key.name;
3282
3328
  }
3283
- if (key.type === AST_NODE_TYPES13.Literal && typeof key.value === "string") {
3329
+ if (key.type === AST_NODE_TYPES14.Literal && typeof key.value === "string") {
3284
3330
  return key.value;
3285
3331
  }
3286
3332
  return null;
3287
3333
  }
3288
3334
  function isStringLiteralMember(t) {
3289
- return t.type === AST_NODE_TYPES13.TSLiteralType && t.literal.type === AST_NODE_TYPES13.Literal && typeof t.literal.value === "string";
3335
+ return t.type === AST_NODE_TYPES14.TSLiteralType && t.literal.type === AST_NODE_TYPES14.Literal && typeof t.literal.value === "string";
3290
3336
  }
3291
3337
  function isStringLiteralUnion(node) {
3292
- if (node?.type !== AST_NODE_TYPES13.TSUnionType) {
3338
+ if (node?.type !== AST_NODE_TYPES14.TSUnionType) {
3293
3339
  return false;
3294
3340
  }
3295
3341
  return node.types.filter(isStringLiteralMember).length >= MIN_CLUSTER_SIZE;
@@ -3318,12 +3364,12 @@ function bindingSourceExpression(decl) {
3318
3364
  return ts.isForOfStatement(node) ? node.expression : node.initializer;
3319
3365
  }
3320
3366
  function refKey(node) {
3321
- if (node.type === AST_NODE_TYPES13.Identifier) {
3367
+ if (node.type === AST_NODE_TYPES14.Identifier) {
3322
3368
  return node.name;
3323
3369
  }
3324
- if (node.type === AST_NODE_TYPES13.MemberExpression && !node.computed) {
3370
+ if (node.type === AST_NODE_TYPES14.MemberExpression && !node.computed) {
3325
3371
  const inner = refKey(node.object);
3326
- if (inner === null || node.property.type !== AST_NODE_TYPES13.Identifier) {
3372
+ if (inner === null || node.property.type !== AST_NODE_TYPES14.Identifier) {
3327
3373
  return null;
3328
3374
  }
3329
3375
  return `${inner}.${node.property.name}`;
@@ -3331,12 +3377,12 @@ function refKey(node) {
3331
3377
  return null;
3332
3378
  }
3333
3379
  function strLiteral(node) {
3334
- if (node.type === AST_NODE_TYPES13.Literal && typeof node.value === "string") {
3380
+ if (node.type === AST_NODE_TYPES14.Literal && typeof node.value === "string") {
3335
3381
  return node.value;
3336
3382
  }
3337
3383
  return null;
3338
3384
  }
3339
- var prefer_string_literal_union_default = ESLintUtils24.RuleCreator(
3385
+ var prefer_string_literal_union_default = ESLintUtils25.RuleCreator(
3340
3386
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3341
3387
  )({
3342
3388
  name: "prefer-string-literal-union",
@@ -3360,7 +3406,7 @@ var prefer_string_literal_union_default = ESLintUtils24.RuleCreator(
3360
3406
  }
3361
3407
  let services;
3362
3408
  try {
3363
- services = ESLintUtils24.getParserServices(context);
3409
+ services = ESLintUtils25.getParserServices(context);
3364
3410
  } catch {
3365
3411
  services = null;
3366
3412
  }
@@ -3444,7 +3490,7 @@ var prefer_string_literal_union_default = ESLintUtils24.RuleCreator(
3444
3490
  containersWithUnion.add(container);
3445
3491
  return;
3446
3492
  }
3447
- if (typeNode?.type !== AST_NODE_TYPES13.TSStringKeyword) {
3493
+ if (typeNode?.type !== AST_NODE_TYPES14.TSStringKeyword) {
3448
3494
  return;
3449
3495
  }
3450
3496
  const name = keyName(key);
@@ -3532,10 +3578,10 @@ var prefer_string_literal_union_default = ESLintUtils24.RuleCreator(
3532
3578
  }
3533
3579
  };
3534
3580
  function refKeyText(node) {
3535
- if (node.type === AST_NODE_TYPES13.BinaryExpression) {
3581
+ if (node.type === AST_NODE_TYPES14.BinaryExpression) {
3536
3582
  return refKey(node.left) ?? refKey(node.right) ?? "value";
3537
3583
  }
3538
- if (node.type === AST_NODE_TYPES13.SwitchStatement) {
3584
+ if (node.type === AST_NODE_TYPES14.SwitchStatement) {
3539
3585
  return refKey(node.discriminant) ?? "value";
3540
3586
  }
3541
3587
  return "value";
@@ -3544,7 +3590,7 @@ var prefer_string_literal_union_default = ESLintUtils24.RuleCreator(
3544
3590
  });
3545
3591
 
3546
3592
  // src/rules/single-public-export.ts
3547
- import { ESLintUtils as ESLintUtils25, AST_NODE_TYPES as AST_NODE_TYPES14 } from "@typescript-eslint/utils";
3593
+ import { ESLintUtils as ESLintUtils26, AST_NODE_TYPES as AST_NODE_TYPES15 } from "@typescript-eslint/utils";
3548
3594
  var JUNK_DRAWER_STEMS = /* @__PURE__ */ new Set([
3549
3595
  "util",
3550
3596
  "utils",
@@ -3578,12 +3624,12 @@ var kebabCase2 = (name) => {
3578
3624
  }
3579
3625
  return normalized.replace(CAMEL_BOUNDARY_RE, "-").toLowerCase();
3580
3626
  };
3581
- var isFunctionExpression = (node) => node !== null && (node.type === AST_NODE_TYPES14.ArrowFunctionExpression || node.type === AST_NODE_TYPES14.FunctionExpression);
3627
+ var isFunctionExpression = (node) => node !== null && (node.type === AST_NODE_TYPES15.ArrowFunctionExpression || node.type === AST_NODE_TYPES15.FunctionExpression);
3582
3628
  var functionConstName = (decl) => {
3583
3629
  if (decl.declarations.length !== 1) return null;
3584
3630
  const [declarator] = decl.declarations;
3585
3631
  if (declarator === void 0) return null;
3586
- if (declarator.id.type !== AST_NODE_TYPES14.Identifier) return null;
3632
+ if (declarator.id.type !== AST_NODE_TYPES15.Identifier) return null;
3587
3633
  if (!isFunctionExpression(declarator.init)) return null;
3588
3634
  return declarator.id.name;
3589
3635
  };
@@ -3597,20 +3643,20 @@ var summarizeExports = (body) => {
3597
3643
  };
3598
3644
  for (const statement of body) {
3599
3645
  switch (statement.type) {
3600
- case AST_NODE_TYPES14.ExportAllDeclaration:
3646
+ case AST_NODE_TYPES15.ExportAllDeclaration:
3601
3647
  hasReExport = true;
3602
3648
  break;
3603
- case AST_NODE_TYPES14.ExportDefaultDeclaration: {
3649
+ case AST_NODE_TYPES15.ExportDefaultDeclaration: {
3604
3650
  names += 1;
3605
3651
  const decl = statement.declaration;
3606
- if (decl.type === AST_NODE_TYPES14.FunctionDeclaration && decl.id !== null) {
3652
+ if (decl.type === AST_NODE_TYPES15.FunctionDeclaration && decl.id !== null) {
3607
3653
  candidate = { name: decl.id.name, node: statement };
3608
- } else if (decl.type === AST_NODE_TYPES14.ClassDeclaration && decl.id !== null) {
3654
+ } else if (decl.type === AST_NODE_TYPES15.ClassDeclaration && decl.id !== null) {
3609
3655
  candidate = { name: decl.id.name, node: statement };
3610
3656
  }
3611
3657
  break;
3612
3658
  }
3613
- case AST_NODE_TYPES14.ExportNamedDeclaration: {
3659
+ case AST_NODE_TYPES15.ExportNamedDeclaration: {
3614
3660
  if (statement.source !== null) {
3615
3661
  hasReExport = true;
3616
3662
  break;
@@ -3621,15 +3667,15 @@ var summarizeExports = (body) => {
3621
3667
  break;
3622
3668
  }
3623
3669
  switch (decl.type) {
3624
- case AST_NODE_TYPES14.FunctionDeclaration:
3670
+ case AST_NODE_TYPES15.FunctionDeclaration:
3625
3671
  if (decl.id !== null) addCandidate(decl.id.name, statement);
3626
3672
  else names += 1;
3627
3673
  break;
3628
- case AST_NODE_TYPES14.ClassDeclaration:
3674
+ case AST_NODE_TYPES15.ClassDeclaration:
3629
3675
  if (decl.id !== null) addCandidate(decl.id.name, statement);
3630
3676
  else names += 1;
3631
3677
  break;
3632
- case AST_NODE_TYPES14.VariableDeclaration: {
3678
+ case AST_NODE_TYPES15.VariableDeclaration: {
3633
3679
  const fnName = functionConstName(decl);
3634
3680
  if (fnName !== null && decl.declarations.length === 1) {
3635
3681
  addCandidate(fnName, statement);
@@ -3649,7 +3695,7 @@ var summarizeExports = (body) => {
3649
3695
  }
3650
3696
  return { names, hasReExport, candidate };
3651
3697
  };
3652
- var single_public_export_default = ESLintUtils25.RuleCreator(
3698
+ var single_public_export_default = ESLintUtils26.RuleCreator(
3653
3699
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
3654
3700
  )({
3655
3701
  name: "single-public-export",
@@ -3713,13 +3759,14 @@ var rules = {
3713
3759
  "no-cors-wildcard-with-credentials": no_cors_wildcard_with_credentials_default,
3714
3760
  "no-fat-try-blocks": no_fat_try_blocks_default,
3715
3761
  "no-secret-in-log": no_secret_in_log_default,
3762
+ "no-unsafe-cast": no_unsafe_cast_default,
3716
3763
  "prefer-string-literal-union": prefer_string_literal_union_default,
3717
3764
  "single-public-export": single_public_export_default
3718
3765
  };
3719
3766
  var plugin = {
3720
3767
  meta: {
3721
3768
  name: "@sarj/eslint-plugin",
3722
- version: "2.4.1"
3769
+ version: "2.5.0"
3723
3770
  },
3724
3771
  rules,
3725
3772
  configs: {
@@ -3749,6 +3796,7 @@ var plugin = {
3749
3796
  "@sarj/no-fat-try-blocks": "warn",
3750
3797
  "@sarj/no-cors-wildcard-with-credentials": "warn",
3751
3798
  "@sarj/no-secret-in-log": "warn",
3799
+ "@sarj/no-unsafe-cast": "warn",
3752
3800
  "@sarj/single-public-export": "warn",
3753
3801
  "@sarj/prefer-string-literal-union": "warn"
3754
3802
  }
@@ -3783,6 +3831,7 @@ var plugin = {
3783
3831
  "@sarj/no-fat-try-blocks": "error",
3784
3832
  "@sarj/no-cors-wildcard-with-credentials": "error",
3785
3833
  "@sarj/no-secret-in-log": "error",
3834
+ "@sarj/no-unsafe-cast": "warn",
3786
3835
  "@sarj/single-public-export": "error",
3787
3836
  // High-volume/stylistic — warn until rollout proves FP rate.
3788
3837
  "@sarj/prefer-string-literal-union": "warn"