@sarj/eslint-plugin 2.3.1 → 2.3.2

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
@@ -2235,7 +2235,15 @@ var PURE_CONSTRUCTORS = /* @__PURE__ */ new Set([
2235
2235
  "Object",
2236
2236
  "Headers",
2237
2237
  "URLSearchParams",
2238
- "FormData"
2238
+ "FormData",
2239
+ "TextEncoder",
2240
+ "TextDecoder",
2241
+ "Blob",
2242
+ "ReadableStream",
2243
+ "WritableStream",
2244
+ "TransformStream",
2245
+ "Response",
2246
+ "AbortController"
2239
2247
  ]);
2240
2248
  function isNode3(value) {
2241
2249
  return typeof value === "object" && value !== null && typeof value.type === "string";
@@ -2425,7 +2433,49 @@ var INNOCUOUS_WORDS = /* @__PURE__ */ new Set([
2425
2433
  "invalid",
2426
2434
  "exists",
2427
2435
  "type",
2428
- "types"
2436
+ "types",
2437
+ "name",
2438
+ "names",
2439
+ "label",
2440
+ "labels",
2441
+ "title",
2442
+ "expiry",
2443
+ "expiration",
2444
+ "expires",
2445
+ "ttl",
2446
+ "version",
2447
+ "versions",
2448
+ "policy",
2449
+ "rotation",
2450
+ "arn",
2451
+ "path",
2452
+ "paths",
2453
+ "issuer",
2454
+ "audience",
2455
+ "strength",
2456
+ "manager",
2457
+ "service",
2458
+ "services",
2459
+ "repository",
2460
+ "provider",
2461
+ "providers",
2462
+ "store",
2463
+ "factory",
2464
+ "handler",
2465
+ "controller",
2466
+ "bucket",
2467
+ "url",
2468
+ "uri",
2469
+ "endpoint",
2470
+ "endpoints",
2471
+ "scope",
2472
+ "scopes",
2473
+ "event",
2474
+ "events",
2475
+ "format",
2476
+ "at",
2477
+ "len",
2478
+ "length"
2429
2479
  ]);
2430
2480
  var REDACTION_RE = /prefix|suffix|redact|mask|hash|hint|_len|length/i;
2431
2481
  var WHOLE_TOKEN_REDACTION_MARKERS = /* @__PURE__ */ new Set(["tag"]);
@@ -2500,6 +2550,12 @@ function isLoggerExpr(expr) {
2500
2550
  return false;
2501
2551
  }
2502
2552
  }
2553
+ function isRawSecretValue(prop) {
2554
+ if (prop.shorthand) {
2555
+ return true;
2556
+ }
2557
+ return prop.value.type === "Identifier" || prop.value.type === "MemberExpression";
2558
+ }
2503
2559
  function propertyKeyName2(prop) {
2504
2560
  if (prop.computed) {
2505
2561
  return null;
@@ -2554,7 +2610,7 @@ var no_secret_in_log_default = import_utils24.ESLintUtils.RuleCreator(
2554
2610
  continue;
2555
2611
  }
2556
2612
  const keyName2 = propertyKeyName2(prop);
2557
- if (keyName2 !== null && isSecretKeyword(keyName2)) {
2613
+ if (keyName2 !== null && isSecretKeyword(keyName2) && isRawSecretValue(prop)) {
2558
2614
  context.report({
2559
2615
  node: prop,
2560
2616
  messageId: "noSecretInLog",
@@ -2587,6 +2643,10 @@ var CHOICE_TOKENS = /* @__PURE__ */ new Set([
2587
2643
  ]);
2588
2644
  var LOWER_TOKEN_RE = /^[a-z][a-z0-9_-]{0,30}$/;
2589
2645
  var MIN_CLUSTER_SIZE = 2;
2646
+ var BOOLEANISH = /* @__PURE__ */ new Set(["true", "false"]);
2647
+ function isEnumToken(lit) {
2648
+ return LOWER_TOKEN_RE.test(lit) && lit.length >= 2 && !BOOLEANISH.has(lit);
2649
+ }
2590
2650
  var IGNORE_PATTERNS = [
2591
2651
  /[\\/]generated[\\/]/,
2592
2652
  /\.gen\.tsx?$/,
@@ -2616,14 +2676,89 @@ function keyName(key) {
2616
2676
  }
2617
2677
  return null;
2618
2678
  }
2679
+ function isStringLiteralMember(t) {
2680
+ return t.type === import_utils25.AST_NODE_TYPES.TSLiteralType && t.literal.type === import_utils25.AST_NODE_TYPES.Literal && typeof t.literal.value === "string";
2681
+ }
2619
2682
  function isStringLiteralUnion(node) {
2620
2683
  if (node?.type !== import_utils25.AST_NODE_TYPES.TSUnionType) {
2621
2684
  return false;
2622
2685
  }
2623
- const stringMembers = node.types.filter(
2624
- (t) => t.type === import_utils25.AST_NODE_TYPES.TSLiteralType && t.literal.type === import_utils25.AST_NODE_TYPES.Literal && typeof t.literal.value === "string"
2625
- );
2626
- return stringMembers.length >= MIN_CLUSTER_SIZE;
2686
+ return node.types.filter(isStringLiteralMember).length >= MIN_CLUSTER_SIZE;
2687
+ }
2688
+ function isLikelyClosedUnion(node) {
2689
+ return node?.type === import_utils25.AST_NODE_TYPES.TSUnionType && node.types.some(isStringLiteralMember);
2690
+ }
2691
+ function unionMemberNames(typeNode, out) {
2692
+ if (typeNode === void 0) {
2693
+ return;
2694
+ }
2695
+ if (typeNode.type === import_utils25.AST_NODE_TYPES.TSIntersectionType || typeNode.type === import_utils25.AST_NODE_TYPES.TSUnionType) {
2696
+ for (const t of typeNode.types) {
2697
+ unionMemberNames(t, out);
2698
+ }
2699
+ return;
2700
+ }
2701
+ if (typeNode.type !== import_utils25.AST_NODE_TYPES.TSTypeLiteral) {
2702
+ return;
2703
+ }
2704
+ for (const member of typeNode.members) {
2705
+ if (member.type === import_utils25.AST_NODE_TYPES.TSPropertySignature && isLikelyClosedUnion(member.typeAnnotation?.typeAnnotation)) {
2706
+ const propName2 = keyName(member.key);
2707
+ if (propName2 !== null) {
2708
+ out.add(propName2);
2709
+ }
2710
+ }
2711
+ }
2712
+ }
2713
+ function bindingName(node) {
2714
+ const id = node.type === import_utils25.AST_NODE_TYPES.AssignmentPattern ? node.left : node;
2715
+ return id.type === import_utils25.AST_NODE_TYPES.Identifier ? id.name : null;
2716
+ }
2717
+ function addUnionRefsFromBinding(param, out) {
2718
+ const binding = param.type === import_utils25.AST_NODE_TYPES.AssignmentPattern ? param.left : param;
2719
+ if (binding.type === import_utils25.AST_NODE_TYPES.ObjectPattern) {
2720
+ const members = /* @__PURE__ */ new Set();
2721
+ unionMemberNames(binding.typeAnnotation?.typeAnnotation, members);
2722
+ if (members.size === 0) {
2723
+ return;
2724
+ }
2725
+ for (const prop of binding.properties) {
2726
+ if (prop.type !== import_utils25.AST_NODE_TYPES.Property) {
2727
+ continue;
2728
+ }
2729
+ const propKey = keyName(prop.key);
2730
+ const local = bindingName(prop.value);
2731
+ if (propKey !== null && local !== null && members.has(propKey)) {
2732
+ out.add(local);
2733
+ }
2734
+ }
2735
+ return;
2736
+ }
2737
+ if (binding.type !== import_utils25.AST_NODE_TYPES.Identifier) {
2738
+ return;
2739
+ }
2740
+ const typeNode = binding.typeAnnotation?.typeAnnotation;
2741
+ if (isLikelyClosedUnion(typeNode)) {
2742
+ out.add(binding.name);
2743
+ return;
2744
+ }
2745
+ if (typeNode?.type === import_utils25.AST_NODE_TYPES.TSTypeLiteral) {
2746
+ for (const member of typeNode.members) {
2747
+ if (member.type === import_utils25.AST_NODE_TYPES.TSPropertySignature && isLikelyClosedUnion(member.typeAnnotation?.typeAnnotation)) {
2748
+ const propName2 = keyName(member.key);
2749
+ if (propName2 !== null) {
2750
+ out.add(`${binding.name}.${propName2}`);
2751
+ }
2752
+ }
2753
+ }
2754
+ }
2755
+ }
2756
+ function unionRefsFromParams(fn) {
2757
+ const out = /* @__PURE__ */ new Set();
2758
+ for (const param of fn.params) {
2759
+ addUnionRefsFromBinding(param, out);
2760
+ }
2761
+ return out;
2627
2762
  }
2628
2763
  function refKey(node) {
2629
2764
  if (node.type === import_utils25.AST_NODE_TYPES.Identifier) {
@@ -2670,16 +2805,25 @@ var prefer_string_literal_union_default = import_utils25.ESLintUtils.RuleCreator
2670
2805
  const validClusters = [];
2671
2806
  const bareChoiceProps = [];
2672
2807
  const containersWithUnion = /* @__PURE__ */ new Set();
2673
- function pushScope() {
2674
- scopeStack.push(/* @__PURE__ */ new Map());
2808
+ function pushScope(fn) {
2809
+ scopeStack.push({
2810
+ clusters: /* @__PURE__ */ new Map(),
2811
+ unionRefs: unionRefsFromParams(fn)
2812
+ });
2813
+ }
2814
+ function isUnionTypedRef(key, current) {
2815
+ if (current.has(key)) {
2816
+ return true;
2817
+ }
2818
+ return scopeStack.some((s) => s.unionRefs.has(key));
2675
2819
  }
2676
2820
  function popScope() {
2677
- const clusters = scopeStack.pop();
2678
- if (clusters === void 0) {
2821
+ const scope = scopeStack.pop();
2822
+ if (scope === void 0) {
2679
2823
  return;
2680
2824
  }
2681
- for (const entry of clusters.values()) {
2682
- if (entry.allTokens && entry.literals.size >= MIN_CLUSTER_SIZE) {
2825
+ for (const [key, entry] of scope.clusters) {
2826
+ if (entry.allTokens && entry.literals.size >= MIN_CLUSTER_SIZE && !isUnionTypedRef(key, scope.unionRefs)) {
2683
2827
  validClusters.push(entry.node);
2684
2828
  }
2685
2829
  }
@@ -2689,10 +2833,10 @@ var prefer_string_literal_union_default = import_utils25.ESLintUtils.RuleCreator
2689
2833
  if (scope === void 0) {
2690
2834
  return;
2691
2835
  }
2692
- const allTokens = literals.every((lit) => LOWER_TOKEN_RE.test(lit));
2693
- const existing = scope.get(key);
2836
+ const allTokens = literals.every((lit) => isEnumToken(lit));
2837
+ const existing = scope.clusters.get(key);
2694
2838
  if (existing === void 0) {
2695
- scope.set(key, {
2839
+ scope.clusters.set(key, {
2696
2840
  node,
2697
2841
  literals: new Set(literals),
2698
2842
  allTokens
@@ -2725,6 +2869,15 @@ var prefer_string_literal_union_default = import_utils25.ESLintUtils.RuleCreator
2725
2869
  "FunctionExpression:exit": popScope,
2726
2870
  ArrowFunctionExpression: pushScope,
2727
2871
  "ArrowFunctionExpression:exit": popScope,
2872
+ VariableDeclarator(node) {
2873
+ const scope = scopeStack[scopeStack.length - 1];
2874
+ if (scope === void 0 || node.id.type !== import_utils25.AST_NODE_TYPES.Identifier) {
2875
+ return;
2876
+ }
2877
+ if (isLikelyClosedUnion(node.id.typeAnnotation?.typeAnnotation)) {
2878
+ scope.unionRefs.add(node.id.name);
2879
+ }
2880
+ },
2728
2881
  BinaryExpression(node) {
2729
2882
  if (node.operator !== "===" && node.operator !== "!==" && node.operator !== "==" && node.operator !== "!=") {
2730
2883
  return;
@@ -2980,7 +3133,7 @@ var rules = {
2980
3133
  var plugin = {
2981
3134
  meta: {
2982
3135
  name: "@sarj/eslint-plugin",
2983
- version: "2.3.1"
3136
+ version: "2.3.2"
2984
3137
  },
2985
3138
  rules,
2986
3139
  configs: {