@sarj/eslint-plugin 2.3.0 → 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.d.cts CHANGED
@@ -72,9 +72,6 @@ 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-template-literal-in-log": _typescript_eslint_utils_ts_eslint.RuleModule<"noTemplateLiteralInLog", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
76
- name: string;
77
- };
78
75
  "prefer-string-literal-union": _typescript_eslint_utils_ts_eslint.RuleModule<"bareChoiceField" | "comparisonCluster", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
79
76
  name: string;
80
77
  };
@@ -159,9 +156,6 @@ declare const plugin: {
159
156
  "no-secret-in-log": _typescript_eslint_utils_ts_eslint.RuleModule<"noSecretInLog", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
160
157
  name: string;
161
158
  };
162
- "no-template-literal-in-log": _typescript_eslint_utils_ts_eslint.RuleModule<"noTemplateLiteralInLog", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
163
- name: string;
164
- };
165
159
  "prefer-string-literal-union": _typescript_eslint_utils_ts_eslint.RuleModule<"bareChoiceField" | "comparisonCluster", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
166
160
  name: string;
167
161
  };
@@ -192,7 +186,6 @@ declare const plugin: {
192
186
  "@sarj/prefer-semantic-colors": string;
193
187
  "@sarj/no-fat-try-blocks": string;
194
188
  "@sarj/no-cors-wildcard-with-credentials": string;
195
- "@sarj/no-template-literal-in-log": string;
196
189
  "@sarj/no-secret-in-log": string;
197
190
  "@sarj/single-public-export": string;
198
191
  "@sarj/prefer-string-literal-union": string;
@@ -223,7 +216,6 @@ declare const plugin: {
223
216
  "@sarj/prefer-semantic-colors": string;
224
217
  "@sarj/no-fat-try-blocks": string;
225
218
  "@sarj/no-cors-wildcard-with-credentials": string;
226
- "@sarj/no-template-literal-in-log": string;
227
219
  "@sarj/no-secret-in-log": string;
228
220
  "@sarj/single-public-export": string;
229
221
  "@sarj/prefer-string-literal-union": string;
package/dist/index.d.ts CHANGED
@@ -72,9 +72,6 @@ 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-template-literal-in-log": _typescript_eslint_utils_ts_eslint.RuleModule<"noTemplateLiteralInLog", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
76
- name: string;
77
- };
78
75
  "prefer-string-literal-union": _typescript_eslint_utils_ts_eslint.RuleModule<"bareChoiceField" | "comparisonCluster", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
79
76
  name: string;
80
77
  };
@@ -159,9 +156,6 @@ declare const plugin: {
159
156
  "no-secret-in-log": _typescript_eslint_utils_ts_eslint.RuleModule<"noSecretInLog", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
160
157
  name: string;
161
158
  };
162
- "no-template-literal-in-log": _typescript_eslint_utils_ts_eslint.RuleModule<"noTemplateLiteralInLog", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
163
- name: string;
164
- };
165
159
  "prefer-string-literal-union": _typescript_eslint_utils_ts_eslint.RuleModule<"bareChoiceField" | "comparisonCluster", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
166
160
  name: string;
167
161
  };
@@ -192,7 +186,6 @@ declare const plugin: {
192
186
  "@sarj/prefer-semantic-colors": string;
193
187
  "@sarj/no-fat-try-blocks": string;
194
188
  "@sarj/no-cors-wildcard-with-credentials": string;
195
- "@sarj/no-template-literal-in-log": string;
196
189
  "@sarj/no-secret-in-log": string;
197
190
  "@sarj/single-public-export": string;
198
191
  "@sarj/prefer-string-literal-union": string;
@@ -223,7 +216,6 @@ declare const plugin: {
223
216
  "@sarj/prefer-semantic-colors": string;
224
217
  "@sarj/no-fat-try-blocks": string;
225
218
  "@sarj/no-cors-wildcard-with-credentials": string;
226
- "@sarj/no-template-literal-in-log": string;
227
219
  "@sarj/no-secret-in-log": string;
228
220
  "@sarj/single-public-export": string;
229
221
  "@sarj/prefer-string-literal-union": string;
package/dist/index.js CHANGED
@@ -2223,7 +2223,15 @@ var PURE_CONSTRUCTORS = /* @__PURE__ */ new Set([
2223
2223
  "Object",
2224
2224
  "Headers",
2225
2225
  "URLSearchParams",
2226
- "FormData"
2226
+ "FormData",
2227
+ "TextEncoder",
2228
+ "TextDecoder",
2229
+ "Blob",
2230
+ "ReadableStream",
2231
+ "WritableStream",
2232
+ "TransformStream",
2233
+ "Response",
2234
+ "AbortController"
2227
2235
  ]);
2228
2236
  function isNode3(value) {
2229
2237
  return typeof value === "object" && value !== null && typeof value.type === "string";
@@ -2413,7 +2421,49 @@ var INNOCUOUS_WORDS = /* @__PURE__ */ new Set([
2413
2421
  "invalid",
2414
2422
  "exists",
2415
2423
  "type",
2416
- "types"
2424
+ "types",
2425
+ "name",
2426
+ "names",
2427
+ "label",
2428
+ "labels",
2429
+ "title",
2430
+ "expiry",
2431
+ "expiration",
2432
+ "expires",
2433
+ "ttl",
2434
+ "version",
2435
+ "versions",
2436
+ "policy",
2437
+ "rotation",
2438
+ "arn",
2439
+ "path",
2440
+ "paths",
2441
+ "issuer",
2442
+ "audience",
2443
+ "strength",
2444
+ "manager",
2445
+ "service",
2446
+ "services",
2447
+ "repository",
2448
+ "provider",
2449
+ "providers",
2450
+ "store",
2451
+ "factory",
2452
+ "handler",
2453
+ "controller",
2454
+ "bucket",
2455
+ "url",
2456
+ "uri",
2457
+ "endpoint",
2458
+ "endpoints",
2459
+ "scope",
2460
+ "scopes",
2461
+ "event",
2462
+ "events",
2463
+ "format",
2464
+ "at",
2465
+ "len",
2466
+ "length"
2417
2467
  ]);
2418
2468
  var REDACTION_RE = /prefix|suffix|redact|mask|hash|hint|_len|length/i;
2419
2469
  var WHOLE_TOKEN_REDACTION_MARKERS = /* @__PURE__ */ new Set(["tag"]);
@@ -2488,6 +2538,12 @@ function isLoggerExpr(expr) {
2488
2538
  return false;
2489
2539
  }
2490
2540
  }
2541
+ function isRawSecretValue(prop) {
2542
+ if (prop.shorthand) {
2543
+ return true;
2544
+ }
2545
+ return prop.value.type === "Identifier" || prop.value.type === "MemberExpression";
2546
+ }
2491
2547
  function propertyKeyName2(prop) {
2492
2548
  if (prop.computed) {
2493
2549
  return null;
@@ -2542,7 +2598,7 @@ var no_secret_in_log_default = ESLintUtils23.RuleCreator(
2542
2598
  continue;
2543
2599
  }
2544
2600
  const keyName2 = propertyKeyName2(prop);
2545
- if (keyName2 !== null && isSecretKeyword(keyName2)) {
2601
+ if (keyName2 !== null && isSecretKeyword(keyName2) && isRawSecretValue(prop)) {
2546
2602
  context.report({
2547
2603
  node: prop,
2548
2604
  messageId: "noSecretInLog",
@@ -2557,120 +2613,9 @@ var no_secret_in_log_default = ESLintUtils23.RuleCreator(
2557
2613
  }
2558
2614
  });
2559
2615
 
2560
- // src/rules/no-template-literal-in-log.ts
2561
- import { ESLintUtils as ESLintUtils24 } from "@typescript-eslint/utils";
2562
- var LOG_METHODS2 = /* @__PURE__ */ new Set([
2563
- "debug",
2564
- "info",
2565
- "warn",
2566
- "warning",
2567
- "error",
2568
- "exception",
2569
- "critical",
2570
- "trace",
2571
- "log",
2572
- "fatal",
2573
- "success"
2574
- ]);
2575
- var LOGGER_NAMES2 = /* @__PURE__ */ new Set([
2576
- "console",
2577
- "logger",
2578
- "log",
2579
- "_log",
2580
- "_logger"
2581
- ]);
2582
- var LOGGER_FACTORIES2 = /* @__PURE__ */ new Set([
2583
- "getlogger",
2584
- "createlogger"
2585
- ]);
2586
- function looksLikeLogger(node) {
2587
- switch (node.type) {
2588
- case "Identifier": {
2589
- const name = node.name.toLowerCase();
2590
- return LOGGER_NAMES2.has(name) || LOGGER_FACTORIES2.has(name);
2591
- }
2592
- case "MemberExpression": {
2593
- if (!node.computed && node.property.type === "Identifier") {
2594
- const prop = node.property.name.toLowerCase();
2595
- if (LOGGER_NAMES2.has(prop) || LOGGER_FACTORIES2.has(prop)) {
2596
- return true;
2597
- }
2598
- }
2599
- return looksLikeLogger(node.object);
2600
- }
2601
- case "CallExpression":
2602
- return looksLikeLogger(node.callee);
2603
- default:
2604
- return false;
2605
- }
2606
- }
2607
- function findInterpolatingTemplate(node) {
2608
- if (node.type === "TemplateLiteral") {
2609
- return node.expressions.length > 0 ? node : null;
2610
- }
2611
- if (node.type === "BinaryExpression" && node.operator === "+") {
2612
- return findInterpolatingTemplate(node.left) ?? findInterpolatingTemplate(node.right);
2613
- }
2614
- return null;
2615
- }
2616
- function messageArg(node, method, receiver) {
2617
- const levelFirst = method === "log" && !isConsoleReceiver(receiver);
2618
- const arg = node.arguments[levelFirst ? 1 : 0];
2619
- if (arg === void 0 || arg.type === "SpreadElement") {
2620
- return null;
2621
- }
2622
- return arg;
2623
- }
2624
- function isConsoleReceiver(node) {
2625
- return node.type === "Identifier" && node.name === "console";
2626
- }
2627
- var no_template_literal_in_log_default = ESLintUtils24.RuleCreator(
2628
- (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
2629
- )({
2630
- name: "no-template-literal-in-log",
2631
- meta: {
2632
- type: "problem",
2633
- docs: {
2634
- description: "Disallow an interpolating template literal as a logging message \u2014 pass variables as structured fields so logs stay filterable and templates stay constant."
2635
- },
2636
- schema: [],
2637
- messages: {
2638
- noTemplateLiteralInLog: "Interpolating template literal as a logging message \u2014 pass variables as structured fields (logger.info('msg', { key })) instead."
2639
- }
2640
- },
2641
- defaultOptions: [],
2642
- create(context) {
2643
- return {
2644
- CallExpression(node) {
2645
- const callee = node.callee;
2646
- if (callee.type !== "MemberExpression" || callee.computed) {
2647
- return;
2648
- }
2649
- if (callee.property.type !== "Identifier") {
2650
- return;
2651
- }
2652
- const method = callee.property.name;
2653
- if (!LOG_METHODS2.has(method)) {
2654
- return;
2655
- }
2656
- if (!looksLikeLogger(callee.object)) {
2657
- return;
2658
- }
2659
- const arg = messageArg(node, method, callee.object);
2660
- if (arg === null) {
2661
- return;
2662
- }
2663
- if (findInterpolatingTemplate(arg) !== null) {
2664
- context.report({ node, messageId: "noTemplateLiteralInLog" });
2665
- }
2666
- }
2667
- };
2668
- }
2669
- });
2670
-
2671
2616
  // src/rules/prefer-string-literal-union.ts
2672
2617
  import {
2673
- ESLintUtils as ESLintUtils25,
2618
+ ESLintUtils as ESLintUtils24,
2674
2619
  AST_NODE_TYPES as AST_NODE_TYPES12
2675
2620
  } from "@typescript-eslint/utils";
2676
2621
  var CHOICE_TOKENS = /* @__PURE__ */ new Set([
@@ -2689,6 +2634,10 @@ var CHOICE_TOKENS = /* @__PURE__ */ new Set([
2689
2634
  ]);
2690
2635
  var LOWER_TOKEN_RE = /^[a-z][a-z0-9_-]{0,30}$/;
2691
2636
  var MIN_CLUSTER_SIZE = 2;
2637
+ var BOOLEANISH = /* @__PURE__ */ new Set(["true", "false"]);
2638
+ function isEnumToken(lit) {
2639
+ return LOWER_TOKEN_RE.test(lit) && lit.length >= 2 && !BOOLEANISH.has(lit);
2640
+ }
2692
2641
  var IGNORE_PATTERNS = [
2693
2642
  /[\\/]generated[\\/]/,
2694
2643
  /\.gen\.tsx?$/,
@@ -2718,14 +2667,89 @@ function keyName(key) {
2718
2667
  }
2719
2668
  return null;
2720
2669
  }
2670
+ function isStringLiteralMember(t) {
2671
+ return t.type === AST_NODE_TYPES12.TSLiteralType && t.literal.type === AST_NODE_TYPES12.Literal && typeof t.literal.value === "string";
2672
+ }
2721
2673
  function isStringLiteralUnion(node) {
2722
2674
  if (node?.type !== AST_NODE_TYPES12.TSUnionType) {
2723
2675
  return false;
2724
2676
  }
2725
- const stringMembers = node.types.filter(
2726
- (t) => t.type === AST_NODE_TYPES12.TSLiteralType && t.literal.type === AST_NODE_TYPES12.Literal && typeof t.literal.value === "string"
2727
- );
2728
- return stringMembers.length >= MIN_CLUSTER_SIZE;
2677
+ return node.types.filter(isStringLiteralMember).length >= MIN_CLUSTER_SIZE;
2678
+ }
2679
+ function isLikelyClosedUnion(node) {
2680
+ return node?.type === AST_NODE_TYPES12.TSUnionType && node.types.some(isStringLiteralMember);
2681
+ }
2682
+ function unionMemberNames(typeNode, out) {
2683
+ if (typeNode === void 0) {
2684
+ return;
2685
+ }
2686
+ if (typeNode.type === AST_NODE_TYPES12.TSIntersectionType || typeNode.type === AST_NODE_TYPES12.TSUnionType) {
2687
+ for (const t of typeNode.types) {
2688
+ unionMemberNames(t, out);
2689
+ }
2690
+ return;
2691
+ }
2692
+ if (typeNode.type !== AST_NODE_TYPES12.TSTypeLiteral) {
2693
+ return;
2694
+ }
2695
+ for (const member of typeNode.members) {
2696
+ if (member.type === AST_NODE_TYPES12.TSPropertySignature && isLikelyClosedUnion(member.typeAnnotation?.typeAnnotation)) {
2697
+ const propName2 = keyName(member.key);
2698
+ if (propName2 !== null) {
2699
+ out.add(propName2);
2700
+ }
2701
+ }
2702
+ }
2703
+ }
2704
+ function bindingName(node) {
2705
+ const id = node.type === AST_NODE_TYPES12.AssignmentPattern ? node.left : node;
2706
+ return id.type === AST_NODE_TYPES12.Identifier ? id.name : null;
2707
+ }
2708
+ function addUnionRefsFromBinding(param, out) {
2709
+ const binding = param.type === AST_NODE_TYPES12.AssignmentPattern ? param.left : param;
2710
+ if (binding.type === AST_NODE_TYPES12.ObjectPattern) {
2711
+ const members = /* @__PURE__ */ new Set();
2712
+ unionMemberNames(binding.typeAnnotation?.typeAnnotation, members);
2713
+ if (members.size === 0) {
2714
+ return;
2715
+ }
2716
+ for (const prop of binding.properties) {
2717
+ if (prop.type !== AST_NODE_TYPES12.Property) {
2718
+ continue;
2719
+ }
2720
+ const propKey = keyName(prop.key);
2721
+ const local = bindingName(prop.value);
2722
+ if (propKey !== null && local !== null && members.has(propKey)) {
2723
+ out.add(local);
2724
+ }
2725
+ }
2726
+ return;
2727
+ }
2728
+ if (binding.type !== AST_NODE_TYPES12.Identifier) {
2729
+ return;
2730
+ }
2731
+ const typeNode = binding.typeAnnotation?.typeAnnotation;
2732
+ if (isLikelyClosedUnion(typeNode)) {
2733
+ out.add(binding.name);
2734
+ return;
2735
+ }
2736
+ if (typeNode?.type === AST_NODE_TYPES12.TSTypeLiteral) {
2737
+ for (const member of typeNode.members) {
2738
+ if (member.type === AST_NODE_TYPES12.TSPropertySignature && isLikelyClosedUnion(member.typeAnnotation?.typeAnnotation)) {
2739
+ const propName2 = keyName(member.key);
2740
+ if (propName2 !== null) {
2741
+ out.add(`${binding.name}.${propName2}`);
2742
+ }
2743
+ }
2744
+ }
2745
+ }
2746
+ }
2747
+ function unionRefsFromParams(fn) {
2748
+ const out = /* @__PURE__ */ new Set();
2749
+ for (const param of fn.params) {
2750
+ addUnionRefsFromBinding(param, out);
2751
+ }
2752
+ return out;
2729
2753
  }
2730
2754
  function refKey(node) {
2731
2755
  if (node.type === AST_NODE_TYPES12.Identifier) {
@@ -2746,7 +2770,7 @@ function strLiteral(node) {
2746
2770
  }
2747
2771
  return null;
2748
2772
  }
2749
- var prefer_string_literal_union_default = ESLintUtils25.RuleCreator(
2773
+ var prefer_string_literal_union_default = ESLintUtils24.RuleCreator(
2750
2774
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2751
2775
  )({
2752
2776
  name: "prefer-string-literal-union",
@@ -2772,16 +2796,25 @@ var prefer_string_literal_union_default = ESLintUtils25.RuleCreator(
2772
2796
  const validClusters = [];
2773
2797
  const bareChoiceProps = [];
2774
2798
  const containersWithUnion = /* @__PURE__ */ new Set();
2775
- function pushScope() {
2776
- scopeStack.push(/* @__PURE__ */ new Map());
2799
+ function pushScope(fn) {
2800
+ scopeStack.push({
2801
+ clusters: /* @__PURE__ */ new Map(),
2802
+ unionRefs: unionRefsFromParams(fn)
2803
+ });
2804
+ }
2805
+ function isUnionTypedRef(key, current) {
2806
+ if (current.has(key)) {
2807
+ return true;
2808
+ }
2809
+ return scopeStack.some((s) => s.unionRefs.has(key));
2777
2810
  }
2778
2811
  function popScope() {
2779
- const clusters = scopeStack.pop();
2780
- if (clusters === void 0) {
2812
+ const scope = scopeStack.pop();
2813
+ if (scope === void 0) {
2781
2814
  return;
2782
2815
  }
2783
- for (const entry of clusters.values()) {
2784
- if (entry.allTokens && entry.literals.size >= MIN_CLUSTER_SIZE) {
2816
+ for (const [key, entry] of scope.clusters) {
2817
+ if (entry.allTokens && entry.literals.size >= MIN_CLUSTER_SIZE && !isUnionTypedRef(key, scope.unionRefs)) {
2785
2818
  validClusters.push(entry.node);
2786
2819
  }
2787
2820
  }
@@ -2791,10 +2824,10 @@ var prefer_string_literal_union_default = ESLintUtils25.RuleCreator(
2791
2824
  if (scope === void 0) {
2792
2825
  return;
2793
2826
  }
2794
- const allTokens = literals.every((lit) => LOWER_TOKEN_RE.test(lit));
2795
- const existing = scope.get(key);
2827
+ const allTokens = literals.every((lit) => isEnumToken(lit));
2828
+ const existing = scope.clusters.get(key);
2796
2829
  if (existing === void 0) {
2797
- scope.set(key, {
2830
+ scope.clusters.set(key, {
2798
2831
  node,
2799
2832
  literals: new Set(literals),
2800
2833
  allTokens
@@ -2827,6 +2860,15 @@ var prefer_string_literal_union_default = ESLintUtils25.RuleCreator(
2827
2860
  "FunctionExpression:exit": popScope,
2828
2861
  ArrowFunctionExpression: pushScope,
2829
2862
  "ArrowFunctionExpression:exit": popScope,
2863
+ VariableDeclarator(node) {
2864
+ const scope = scopeStack[scopeStack.length - 1];
2865
+ if (scope === void 0 || node.id.type !== AST_NODE_TYPES12.Identifier) {
2866
+ return;
2867
+ }
2868
+ if (isLikelyClosedUnion(node.id.typeAnnotation?.typeAnnotation)) {
2869
+ scope.unionRefs.add(node.id.name);
2870
+ }
2871
+ },
2830
2872
  BinaryExpression(node) {
2831
2873
  if (node.operator !== "===" && node.operator !== "!==" && node.operator !== "==" && node.operator !== "!=") {
2832
2874
  return;
@@ -2907,7 +2949,7 @@ var prefer_string_literal_union_default = ESLintUtils25.RuleCreator(
2907
2949
  });
2908
2950
 
2909
2951
  // src/rules/single-public-export.ts
2910
- import { ESLintUtils as ESLintUtils26, AST_NODE_TYPES as AST_NODE_TYPES13 } from "@typescript-eslint/utils";
2952
+ import { ESLintUtils as ESLintUtils25, AST_NODE_TYPES as AST_NODE_TYPES13 } from "@typescript-eslint/utils";
2911
2953
  var JUNK_DRAWER_STEMS = /* @__PURE__ */ new Set([
2912
2954
  "util",
2913
2955
  "utils",
@@ -3012,7 +3054,7 @@ var summarizeExports = (body) => {
3012
3054
  }
3013
3055
  return { names, hasReExport, candidate };
3014
3056
  };
3015
- var single_public_export_default = ESLintUtils26.RuleCreator(
3057
+ var single_public_export_default = ESLintUtils25.RuleCreator(
3016
3058
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
3017
3059
  )({
3018
3060
  name: "single-public-export",
@@ -3076,14 +3118,13 @@ var rules = {
3076
3118
  "no-cors-wildcard-with-credentials": no_cors_wildcard_with_credentials_default,
3077
3119
  "no-fat-try-blocks": no_fat_try_blocks_default,
3078
3120
  "no-secret-in-log": no_secret_in_log_default,
3079
- "no-template-literal-in-log": no_template_literal_in_log_default,
3080
3121
  "prefer-string-literal-union": prefer_string_literal_union_default,
3081
3122
  "single-public-export": single_public_export_default
3082
3123
  };
3083
3124
  var plugin = {
3084
3125
  meta: {
3085
3126
  name: "@sarj/eslint-plugin",
3086
- version: "2.3.0"
3127
+ version: "2.3.2"
3087
3128
  },
3088
3129
  rules,
3089
3130
  configs: {
@@ -3112,7 +3153,6 @@ var plugin = {
3112
3153
  // Ported from sarj-python-lint (SARJ), corpus-validated FP~0.
3113
3154
  "@sarj/no-fat-try-blocks": "warn",
3114
3155
  "@sarj/no-cors-wildcard-with-credentials": "warn",
3115
- "@sarj/no-template-literal-in-log": "warn",
3116
3156
  "@sarj/no-secret-in-log": "warn",
3117
3157
  "@sarj/single-public-export": "warn",
3118
3158
  "@sarj/prefer-string-literal-union": "warn"
@@ -3147,7 +3187,6 @@ var plugin = {
3147
3187
  // Ported from sarj-python-lint (SARJ), corpus-validated FP~0.
3148
3188
  "@sarj/no-fat-try-blocks": "error",
3149
3189
  "@sarj/no-cors-wildcard-with-credentials": "error",
3150
- "@sarj/no-template-literal-in-log": "error",
3151
3190
  "@sarj/no-secret-in-log": "error",
3152
3191
  "@sarj/single-public-export": "error",
3153
3192
  // High-volume/stylistic — warn until rollout proves FP rate.