oxlint-plugin-arch 0.13.1 → 0.13.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.js CHANGED
@@ -53,6 +53,9 @@ function optionsAssertMockingApis(patterns) {
53
53
  function optionsEscape(value) {
54
54
  return value.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
55
55
  }
56
+ function optionsWildcards(names) {
57
+ return [names ?? []].flat().map((name) => new RegExp(`^${name.split("*").map(optionsEscape).join(".*")}$`));
58
+ }
56
59
 
57
60
  // src/utils/ast.utils.ts
58
61
  var astSkippedKeys = new Set(["parent", "type", "start", "end", "range", "loc", "tokens", "comments"]);
@@ -458,7 +461,8 @@ var namingStemSchemaProperties = {
458
461
  roles: { type: "array", items: { type: "string" } },
459
462
  separators: { type: "array", items: { type: "string" } },
460
463
  normalize: { type: "string", enum: ["remove-separators", "none"] },
461
- singularize: { type: "string", enum: ["none", "trailing-s"] }
464
+ singularize: { type: "string", enum: ["none", "trailing-s"] },
465
+ prefix: { type: "array", items: { type: "string", enum: ["file", "folder", "parent"] }, minItems: 1 }
462
466
  };
463
467
  function namingBasename(filePath) {
464
468
  return posix.basename(filePath.replaceAll("\\", "/"));
@@ -485,17 +489,73 @@ function namingFileStem(basename, mode = "before-first-dot", trailingRoles = [],
485
489
  }
486
490
  return stem;
487
491
  }
492
+ function namingSingular(value) {
493
+ const parts = value.split(/[-_]+/).filter(Boolean);
494
+ const last = parts.at(-1) ?? "";
495
+ return last.endsWith("s") && last.length > 1 ? [...parts.slice(0, -1), last.slice(0, -1)].join("-") : value;
496
+ }
497
+ function namingFolders(filename) {
498
+ return filename.replaceAll("\\", "/").split("/").slice(0, -1).toReversed();
499
+ }
488
500
  function namingFilePrefixesFor(filename, options) {
489
501
  const basename = namingBasename(filename).replace(/\.(tsx?|jsx?)$/, "");
490
- const stem = namingFileStem(basename, options.stem, options.roles, options.separators);
502
+ const [folder = "", parent = ""] = namingFolders(filename);
491
503
  const normalize = options.normalize ?? "remove-separators";
492
- const prefixes = [namingNormalized(stem, normalize)];
493
- const parts = stem.split(/[-_]+/).filter(Boolean);
494
- const last = parts.at(-1) ?? "";
495
- if (options.singularize === "trailing-s" && last.endsWith("s") && last.length > 1) {
496
- prefixes.push(namingNormalized([...parts.slice(0, -1), last.slice(0, -1)].join("-"), normalize));
504
+ const sources = { file: namingFileStem(basename, options.stem, options.roles, options.separators), folder, parent };
505
+ const prefixes = (options.prefix ?? ["file"]).flatMap((source) => {
506
+ const stem = sources[source];
507
+ return options.singularize === "trailing-s" ? [stem, namingSingular(stem)] : [stem];
508
+ });
509
+ return [...new Set(prefixes.map((stem) => namingNormalized(stem, normalize)).filter(Boolean))];
510
+ }
511
+ function namingTemplatePattern(template, placeholder = "[a-z0-9-]+") {
512
+ const seen = new Set;
513
+ const source = template.split(/(\{[^{}]+\})/).map((part) => {
514
+ const name = /^\{[^{}]+\}$/.test(part) ? part.slice(1, -1) : undefined;
515
+ if (name === undefined) {
516
+ return part.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
517
+ }
518
+ const again = seen.has(name);
519
+ seen.add(name);
520
+ return again ? `\\k<${name}>` : `(?<${name}>${placeholder})`;
521
+ }).join("");
522
+ try {
523
+ return new RegExp(`^${source}$`);
524
+ } catch {
525
+ return null;
497
526
  }
498
- return [...new Set(prefixes.filter(Boolean))];
527
+ }
528
+ function namingCaptures(filename, options = {}) {
529
+ const path = filename.replaceAll("\\", "/");
530
+ const file = namingBasename(path).replace(/\.(tsx?|jsx?)$/, "");
531
+ const [folder = "", parent = ""] = namingFolders(path);
532
+ const stem = namingFileStem(file, options.stem === "folder" ? undefined : options.stem, options.roles, options.separators);
533
+ const read = options.stem === "folder" ? folder : stem;
534
+ const last = read.split(/[-_]+/).at(-1) ?? "";
535
+ const domain = options.singularize === "trailing-s" && last.length > 1 && last.endsWith("s") ? read.slice(0, -1) : read;
536
+ const builtIn = { file, stem, folder, parent, domain };
537
+ if (options.file === undefined) {
538
+ return builtIn;
539
+ }
540
+ const depth = options.file.split("/").length;
541
+ const match = namingTemplatePattern(options.file, options.placeholder)?.exec(path.split("/").slice(-depth).join("/"));
542
+ return match ? { ...builtIn, ...match.groups } : null;
543
+ }
544
+ function namingExpand(template, captures, camelCase, escape = (value) => value) {
545
+ return template.replaceAll(/\{([A-Za-z][A-Za-z0-9]*)\}/g, (placeholder, key) => {
546
+ const name = key.toLowerCase();
547
+ if (!Object.hasOwn(captures, name)) {
548
+ return placeholder;
549
+ }
550
+ const value = captures[name];
551
+ if (key.length > 1 && key === key.toUpperCase()) {
552
+ return escape(value.split(/[-_\s.]+/).filter(Boolean).join("_").toUpperCase());
553
+ }
554
+ if (/^[A-Z]/.test(key)) {
555
+ return escape(namingPascalCase(value));
556
+ }
557
+ return escape(camelCase ? namingCamelCase(value) : value);
558
+ });
499
559
  }
500
560
  function namingHasFilePrefix(name, prefixes, normalize) {
501
561
  const comparable = normalize === "none" ? name : name.replaceAll("_", "").toLowerCase();
@@ -1123,7 +1183,17 @@ var boundariesDeny = defineRule6({
1123
1183
  additionalProperties: false,
1124
1184
  properties: {
1125
1185
  imports: { type: "object", additionalProperties: { type: "string" } },
1126
- calls: { type: "object", additionalProperties: { type: "string" } }
1186
+ calls: { type: "object", additionalProperties: { type: "string" } },
1187
+ only: {
1188
+ type: "array",
1189
+ items: {
1190
+ type: "object",
1191
+ additionalProperties: false,
1192
+ properties: { imports: optionsPatternSchema, calls: optionsPatternSchema, in: optionsPatternSchema, message: { type: "string" } },
1193
+ required: ["in"],
1194
+ anyOf: [{ required: ["imports"] }, { required: ["calls"] }]
1195
+ }
1196
+ }
1127
1197
  }
1128
1198
  }
1129
1199
  ],
@@ -1148,8 +1218,17 @@ var boundariesDeny = defineRule6({
1148
1218
  return {
1149
1219
  before() {
1150
1220
  const options = optionsFirst(context, {});
1151
- imports = Object.entries(options.imports ?? {}).map(([pattern, message]) => [optionsGlob(pattern), message && ` ${message}`]);
1152
- calls = new Map(Object.entries(options.calls ?? {}).map(([name, message]) => [name, message && ` ${message}`]));
1221
+ const filename = context.filename.replaceAll("\\", "/");
1222
+ const elsewhere = (options.only ?? []).filter((entry) => ![entry.in].flat().some((place) => optionsGlob(`**/${place}{,/**}`).test(filename)));
1223
+ const owned = (entry) => ` ${entry.message ?? `Only ${[entry.in].flat().join(", ")} may use it.`}`;
1224
+ imports = [
1225
+ ...Object.entries(options.imports ?? {}).map(([pattern, message]) => [optionsGlob(pattern), message && ` ${message}`]),
1226
+ ...elsewhere.flatMap((entry) => [entry.imports ?? []].flat().map((pattern) => [optionsGlob(pattern), owned(entry)]))
1227
+ ];
1228
+ calls = new Map([
1229
+ ...elsewhere.flatMap((entry) => [entry.calls ?? []].flat().map((name) => [name, owned(entry)])),
1230
+ ...Object.entries(options.calls ?? {}).map(([name, message]) => [name, message && ` ${message}`])
1231
+ ]);
1153
1232
  if (imports.length === 0 && calls.size === 0) {
1154
1233
  return false;
1155
1234
  }
@@ -2432,9 +2511,85 @@ var codeInline = defineRule16({
2432
2511
  }
2433
2512
  });
2434
2513
 
2435
- // src/rules/code/code-justified-call.ts
2514
+ // src/rules/code/code-inside.ts
2436
2515
  import { defineRule as defineRule17 } from "@oxlint/plugins";
2437
- var codeJustifiedCall = defineRule17({
2516
+ function codeInsideOwners(node) {
2517
+ const parent = node.parent;
2518
+ if (!parent) {
2519
+ return [];
2520
+ }
2521
+ const callback = node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
2522
+ const owner = callback && astIsCall(parent) && parent.arguments.some((item) => item === node) ? astDottedName(parent.callee) : undefined;
2523
+ return [...owner === undefined ? [] : [owner], ...codeInsideOwners(parent)];
2524
+ }
2525
+ var codeInside = defineRule17({
2526
+ meta: {
2527
+ type: "problem",
2528
+ schema: [
2529
+ {
2530
+ type: "object",
2531
+ additionalProperties: false,
2532
+ properties: {
2533
+ inside: {
2534
+ type: "array",
2535
+ items: {
2536
+ type: "object",
2537
+ additionalProperties: false,
2538
+ properties: {
2539
+ callee: optionsPatternSchema,
2540
+ calls: { type: "object", additionalProperties: { type: "string" } }
2541
+ },
2542
+ required: ["callee", "calls"]
2543
+ }
2544
+ }
2545
+ },
2546
+ required: ["inside"]
2547
+ }
2548
+ ],
2549
+ messages: {
2550
+ inside: "Do not call '{{name}}' inside {{owner}}.{{message}}"
2551
+ }
2552
+ },
2553
+ createOnce(context) {
2554
+ let entries = [];
2555
+ return {
2556
+ before() {
2557
+ entries = optionsFirst(context, { inside: [] }).inside.map((entry) => ({
2558
+ callees: optionsWildcards(entry.callee),
2559
+ calls: Object.entries(entry.calls).map(([name, message]) => [optionsWildcards(name)[0], message && ` ${message}`])
2560
+ }));
2561
+ if (entries.length === 0) {
2562
+ return false;
2563
+ }
2564
+ },
2565
+ CallExpression(node) {
2566
+ const name = astDottedName(node.callee);
2567
+ if (name === undefined) {
2568
+ return;
2569
+ }
2570
+ const banned = entries.flatMap(({ callees, calls }) => calls.flatMap(([pattern, message]) => pattern.test(name) ? [{ callees, message }] : []));
2571
+ if (banned.length === 0) {
2572
+ return;
2573
+ }
2574
+ const owners = codeInsideOwners(node);
2575
+ for (const { callees, message } of banned) {
2576
+ const owner = owners.find((item) => optionsPatternsTest(callees, item));
2577
+ if (owner !== undefined) {
2578
+ context.report({
2579
+ node: node.callee,
2580
+ messageId: "inside",
2581
+ data: { name, owner, message }
2582
+ });
2583
+ }
2584
+ }
2585
+ }
2586
+ };
2587
+ }
2588
+ });
2589
+
2590
+ // src/rules/code/code-justified-call.ts
2591
+ import { defineRule as defineRule18 } from "@oxlint/plugins";
2592
+ var codeJustifiedCall = defineRule18({
2438
2593
  meta: {
2439
2594
  type: "problem",
2440
2595
  schema: [
@@ -2488,8 +2643,8 @@ var codeJustifiedCall = defineRule17({
2488
2643
  });
2489
2644
 
2490
2645
  // src/rules/code/code-literal-in.ts
2491
- import { defineRule as defineRule18 } from "@oxlint/plugins";
2492
- var codeLiteralIn = defineRule18({
2646
+ import { defineRule as defineRule19 } from "@oxlint/plugins";
2647
+ var codeLiteralIn = defineRule19({
2493
2648
  meta: {
2494
2649
  type: "suggestion",
2495
2650
  schema: [
@@ -2530,7 +2685,7 @@ var codeLiteralIn = defineRule18({
2530
2685
  });
2531
2686
 
2532
2687
  // src/rules/code/code-mutable-state.ts
2533
- import { defineRule as defineRule19 } from "@oxlint/plugins";
2688
+ import { defineRule as defineRule20 } from "@oxlint/plugins";
2534
2689
  var functionScopes = new Set([
2535
2690
  "FunctionDeclaration",
2536
2691
  "FunctionExpression",
@@ -2547,7 +2702,7 @@ function hasAncestor(node, test) {
2547
2702
  }
2548
2703
  return false;
2549
2704
  }
2550
- var codeMutableState = defineRule19({
2705
+ var codeMutableState = defineRule20({
2551
2706
  meta: {
2552
2707
  type: "problem",
2553
2708
  schema: [
@@ -2605,7 +2760,7 @@ var codeMutableState = defineRule19({
2605
2760
  });
2606
2761
 
2607
2762
  // src/rules/code/code-object-params.ts
2608
- import { defineRule as defineRule20 } from "@oxlint/plugins";
2763
+ import { defineRule as defineRule21 } from "@oxlint/plugins";
2609
2764
  function isObjectParam(node) {
2610
2765
  if (node.type === "ObjectPattern") {
2611
2766
  return true;
@@ -2619,7 +2774,7 @@ function isObjectParam(node) {
2619
2774
  const annotation = node.typeAnnotation?.typeAnnotation;
2620
2775
  return !annotation || annotation.type === "TSTypeReference" || annotation.type === "TSTypeLiteral" || annotation.type === "TSIntersectionType";
2621
2776
  }
2622
- var codeObjectParams = defineRule20({
2777
+ var codeObjectParams = defineRule21({
2623
2778
  meta: {
2624
2779
  type: "problem",
2625
2780
  schema: [
@@ -2668,8 +2823,8 @@ var codeObjectParams = defineRule20({
2668
2823
  });
2669
2824
 
2670
2825
  // src/rules/code/code-paired-call.ts
2671
- import { defineRule as defineRule21 } from "@oxlint/plugins";
2672
- var codePairedCall = defineRule21({
2826
+ import { defineRule as defineRule22 } from "@oxlint/plugins";
2827
+ var codePairedCall = defineRule22({
2673
2828
  meta: {
2674
2829
  type: "problem",
2675
2830
  schema: [
@@ -2736,7 +2891,7 @@ var codePairedCall = defineRule21({
2736
2891
  });
2737
2892
 
2738
2893
  // src/rules/code/code-promise-mutation.ts
2739
- import { defineRule as defineRule22 } from "@oxlint/plugins";
2894
+ import { defineRule as defineRule23 } from "@oxlint/plugins";
2740
2895
  function mutationBinding(node) {
2741
2896
  if (node.type === "Identifier") {
2742
2897
  return node;
@@ -2765,7 +2920,7 @@ function mutationBindings(node) {
2765
2920
  const binding = mutationBinding(node);
2766
2921
  return binding ? [binding] : [];
2767
2922
  }
2768
- var codePromiseMutation = defineRule22({
2923
+ var codePromiseMutation = defineRule23({
2769
2924
  meta: {
2770
2925
  type: "problem",
2771
2926
  schema: [
@@ -2858,8 +3013,8 @@ var codePromiseMutation = defineRule22({
2858
3013
  var codeSwitch = astSelectorRule("SwitchStatement", "Avoid switch statements.");
2859
3014
 
2860
3015
  // src/rules/code/code-traced.ts
2861
- import { defineRule as defineRule23 } from "@oxlint/plugins";
2862
- var codeTraced = defineRule23({
3016
+ import { defineRule as defineRule24 } from "@oxlint/plugins";
3017
+ var codeTraced = defineRule24({
2863
3018
  meta: {
2864
3019
  type: "problem",
2865
3020
  schema: [
@@ -2946,7 +3101,7 @@ var codeTraced = defineRule23({
2946
3101
  });
2947
3102
 
2948
3103
  // src/rules/code/code-trivial-functions.ts
2949
- import { defineRule as defineRule24 } from "@oxlint/plugins";
3104
+ import { defineRule as defineRule25 } from "@oxlint/plugins";
2950
3105
  var codeTrivialFunctionsBanned = [
2951
3106
  "isRecord",
2952
3107
  "isPlainObject",
@@ -3104,7 +3259,7 @@ function codeTrivialFunctionsDefaults(program) {
3104
3259
  }
3105
3260
  return starts;
3106
3261
  }
3107
- var codeTrivialFunctions = defineRule24({
3262
+ var codeTrivialFunctions = defineRule25({
3108
3263
  meta: {
3109
3264
  type: "problem",
3110
3265
  schema: [
@@ -3246,8 +3401,8 @@ var codeTrivialFunctions = defineRule24({
3246
3401
  });
3247
3402
 
3248
3403
  // src/rules/code/code-yield-argument.ts
3249
- import { defineRule as defineRule25 } from "@oxlint/plugins";
3250
- var codeYieldArgument = defineRule25({
3404
+ import { defineRule as defineRule26 } from "@oxlint/plugins";
3405
+ var codeYieldArgument = defineRule26({
3251
3406
  meta: {
3252
3407
  type: "suggestion",
3253
3408
  messages: {
@@ -3269,7 +3424,7 @@ var codeYieldArgument = defineRule25({
3269
3424
  });
3270
3425
 
3271
3426
  // src/rules/comments/comments-code.ts
3272
- import { defineRule as defineRule26 } from "@oxlint/plugins";
3427
+ import { defineRule as defineRule27 } from "@oxlint/plugins";
3273
3428
  var commentsLineGap = /^[\t \r\n\u2028\u2029]*$/;
3274
3429
  var commentsLineTerminator = /\r\n|[\n\r\u2028\u2029]/;
3275
3430
  var commentsUnicodeTerminator = /[\u2028\u2029]/;
@@ -3320,7 +3475,7 @@ function commentsFollowsOpeningBrace(text, offset) {
3320
3475
  }
3321
3476
  return false;
3322
3477
  }
3323
- var commentsCode = defineRule26({
3478
+ var commentsCode = defineRule27({
3324
3479
  meta: {
3325
3480
  type: "suggestion",
3326
3481
  fixable: "code",
@@ -3523,9 +3678,9 @@ var commentsCode = defineRule26({
3523
3678
  });
3524
3679
 
3525
3680
  // src/rules/comments/comments-directives.ts
3526
- import { defineRule as defineRule27 } from "@oxlint/plugins";
3681
+ import { defineRule as defineRule28 } from "@oxlint/plugins";
3527
3682
  var directive = /^\s*(?:oxlint|eslint)-disable(?:-next-line|-line)?\b(.*)$/s;
3528
- var commentsDirectives = defineRule27({
3683
+ var commentsDirectives = defineRule28({
3529
3684
  meta: {
3530
3685
  type: "problem",
3531
3686
  schema: [],
@@ -3553,9 +3708,9 @@ var commentsDirectives = defineRule27({
3553
3708
  });
3554
3709
 
3555
3710
  // src/rules/copy/copy-dashes.ts
3556
- import { defineRule as defineRule28 } from "@oxlint/plugins";
3711
+ import { defineRule as defineRule29 } from "@oxlint/plugins";
3557
3712
  var copyDashesMessage = "Use a comma, colon, period or parentheses instead.";
3558
- var copyDashes = defineRule28({
3713
+ var copyDashes = defineRule29({
3559
3714
  meta: {
3560
3715
  type: "suggestion",
3561
3716
  schema: [
@@ -3611,7 +3766,7 @@ var copyDashes = defineRule28({
3611
3766
  });
3612
3767
 
3613
3768
  // src/rules/effect/effect-layer-file.ts
3614
- import { defineRule as defineRule29 } from "@oxlint/plugins";
3769
+ import { defineRule as defineRule30 } from "@oxlint/plugins";
3615
3770
 
3616
3771
  // src/utils/effect.utils.ts
3617
3772
  var effectBuilders = ["Effect.gen", "Effect.fn", "Effect.fnUntraced"];
@@ -3653,7 +3808,7 @@ var effectLayerFileDefaultConstructors = [
3653
3808
  "Layer.sync",
3654
3809
  "Layer.unwrap"
3655
3810
  ];
3656
- var effectLayerFile = defineRule29({
3811
+ var effectLayerFile = defineRule30({
3657
3812
  meta: {
3658
3813
  type: "problem",
3659
3814
  schema: [
@@ -3819,8 +3974,138 @@ var effectLayerFile = defineRule29({
3819
3974
  }
3820
3975
  });
3821
3976
 
3977
+ // src/rules/effect/effect-layer-keys.ts
3978
+ import { defineRule as defineRule31 } from "@oxlint/plugins";
3979
+ import { readFileSync } from "node:fs";
3980
+ var effectLayerKeysPairs = new Map([["{", "}"], ["(", ")"], ["[", "]"], ["<", ">"]]);
3981
+ function effectLayerKeysDeclared(text, declaration) {
3982
+ const code = text.replaceAll(/\/\*[\s\S]*?\*\/|\/\/[^\n]*|'(?:[^'\\\n]|\\.)*'|"(?:[^"\\\n]|\\.)*"/g, " ");
3983
+ const start = code.indexOf(`${declaration}<`);
3984
+ const open = start === -1 ? -1 : code.indexOf("{", start);
3985
+ if (open === -1) {
3986
+ return null;
3987
+ }
3988
+ const paths = [];
3989
+ const frames = [{ open: "{", members: 0 }];
3990
+ const key = /\s*(?:readonly\s+)?([A-Za-z_$][\w$]*)\??\s*(?=[:(<])/y;
3991
+ let fresh = true;
3992
+ for (let index = open + 1;index < code.length && frames.length > 0; index += 1) {
3993
+ const char = code[index];
3994
+ const members = frames.every((frame) => frame.open === "{");
3995
+ key.lastIndex = index;
3996
+ const match = fresh && members ? key.exec(code) : null;
3997
+ if (match) {
3998
+ const rest = code.slice(key.lastIndex).replace(/^:\s*/, "");
3999
+ const path = [...frames.flatMap((frame) => frame.key ?? []), match[1]].join(".");
4000
+ const parent = frames.at(-1);
4001
+ if (parent) {
4002
+ parent.members += 1;
4003
+ }
4004
+ if (rest.startsWith("{")) {
4005
+ frames.push({
4006
+ open: "{",
4007
+ key: match[1],
4008
+ members: 0
4009
+ });
4010
+ index = code.length - rest.length;
4011
+ } else {
4012
+ paths.push(path);
4013
+ fresh = false;
4014
+ index = key.lastIndex - 1;
4015
+ }
4016
+ continue;
4017
+ }
4018
+ if (effectLayerKeysPairs.has(char)) {
4019
+ frames.push({ open: char, members: 0 });
4020
+ } else if (char === effectLayerKeysPairs.get(frames.at(-1)?.open ?? "") && !(char === ">" && code[index - 1] === "=")) {
4021
+ const closed = frames.pop();
4022
+ if (closed?.key !== undefined && closed.members === 0) {
4023
+ paths.push([...frames.flatMap((frame) => frame.key ?? []), closed.key].join("."));
4024
+ }
4025
+ }
4026
+ fresh = members && (char === "{" || char === ";" || char === "," || char === "}" || fresh && /\s/.test(char));
4027
+ }
4028
+ return paths;
4029
+ }
4030
+ function effectLayerKeysBound(object, path) {
4031
+ return object.properties.flatMap((property) => {
4032
+ const key = declarationsPropertyName(property);
4033
+ if (property.type !== "Property" || key === undefined) {
4034
+ return [];
4035
+ }
4036
+ return property.value.type === "ObjectExpression" ? effectLayerKeysBound(property.value, [...path, key]) : [[[...path, key].join("."), property]];
4037
+ });
4038
+ }
4039
+ var effectLayerKeys = defineRule31({
4040
+ meta: {
4041
+ type: "problem",
4042
+ schema: [
4043
+ {
4044
+ type: "object",
4045
+ additionalProperties: false,
4046
+ properties: {
4047
+ service: { type: "string", minLength: 1 },
4048
+ callees: { type: "array", items: { type: "string" }, minItems: 1 },
4049
+ declaration: { type: "string", minLength: 1 }
4050
+ },
4051
+ required: ["service"]
4052
+ }
4053
+ ],
4054
+ messages: {
4055
+ extra: "'{{path}}' is not a method of the service declared in {{file}}.",
4056
+ missing: "The service in {{file}} declares {{paths}}, which this layer does not bind."
4057
+ }
4058
+ },
4059
+ createOnce(context) {
4060
+ let declared = null;
4061
+ let callees = [];
4062
+ let file = "";
4063
+ return {
4064
+ before() {
4065
+ const options = optionsFirst(context, { service: "" });
4066
+ file = namingExpand(options.service, namingCaptures(context.filename) ?? {}, false);
4067
+ callees = optionsWildcards(options.callees ?? ["*.of", "*.bind"]);
4068
+ try {
4069
+ declared = effectLayerKeysDeclared(readFileSync(file, "utf8"), options.declaration ?? "Context.Service");
4070
+ } catch {
4071
+ declared = null;
4072
+ }
4073
+ if (!declared) {
4074
+ return false;
4075
+ }
4076
+ },
4077
+ CallExpression(node) {
4078
+ const first = node.arguments.at(0);
4079
+ if (!declared || first?.type !== "ObjectExpression" || !optionsPatternsTest(callees, astDottedName(node.callee) ?? "")) {
4080
+ return;
4081
+ }
4082
+ const bound = effectLayerKeysBound(first, []);
4083
+ const names = new Set(bound.map(([path]) => path));
4084
+ const short = file.split("/").slice(-2).join("/");
4085
+ const missing = declared.filter((path) => !names.has(path) && !bound.some(([name]) => name.startsWith(`${path}.`)));
4086
+ for (const [path, property] of bound) {
4087
+ if (!declared.some((name) => name === path || path.startsWith(`${name}.`))) {
4088
+ context.report({
4089
+ node: property,
4090
+ messageId: "extra",
4091
+ data: { path, file: short }
4092
+ });
4093
+ }
4094
+ }
4095
+ if (missing.length > 0) {
4096
+ context.report({
4097
+ node: first,
4098
+ messageId: "missing",
4099
+ data: { paths: missing.map((path) => `'${path}'`).join(", "), file: short }
4100
+ });
4101
+ }
4102
+ }
4103
+ };
4104
+ }
4105
+ });
4106
+
3822
4107
  // src/rules/effect/effect-layers.ts
3823
- import { defineRule as defineRule30 } from "@oxlint/plugins";
4108
+ import { defineRule as defineRule32 } from "@oxlint/plugins";
3824
4109
  var effectLayersDefaultMerge = ["Layer.mergeAll"];
3825
4110
  var effectLayersDefaultProvide = ["Effect.provide", "Layer.provide", "Layer.provideMerge"];
3826
4111
  var effectLayersDefaultMin = 2;
@@ -3832,7 +4117,7 @@ var effectLayersGroupSchema = {
3832
4117
  min: { type: "integer", minimum: 1 }
3833
4118
  }
3834
4119
  };
3835
- var effectLayers = defineRule30({
4120
+ var effectLayers = defineRule32({
3836
4121
  meta: {
3837
4122
  type: "layout",
3838
4123
  fixable: "whitespace",
@@ -3914,11 +4199,11 @@ var effectLayers = defineRule30({
3914
4199
  });
3915
4200
 
3916
4201
  // src/rules/effect/effect-merge-pipe.ts
3917
- import { defineRule as defineRule31 } from "@oxlint/plugins";
4202
+ import { defineRule as defineRule33 } from "@oxlint/plugins";
3918
4203
  var effectMergePipeDefaultMerge = ["Layer.mergeAll"];
3919
4204
  var effectMergePipeDefaultPipe = ["pipe", "Function.pipe"];
3920
4205
  var effectMergePipeDefaultMethods = ["pipe"];
3921
- var effectMergePipe = defineRule31({
4206
+ var effectMergePipe = defineRule33({
3922
4207
  meta: {
3923
4208
  type: "layout",
3924
4209
  schema: [
@@ -3963,7 +4248,7 @@ var effectMergePipe = defineRule31({
3963
4248
  });
3964
4249
 
3965
4250
  // src/rules/effect/effect-schema-first.ts
3966
- import { defineRule as defineRule32 } from "@oxlint/plugins";
4251
+ import { defineRule as defineRule34 } from "@oxlint/plugins";
3967
4252
  var effectSchemaFirstDefaultRuntime = [
3968
4253
  "Effect",
3969
4254
  "Layer",
@@ -4025,7 +4310,7 @@ function effectSchemaFirstReference(node) {
4025
4310
  }
4026
4311
  return node.type === "TSInterfaceHeritage" ? astDottedName(node.expression) : undefined;
4027
4312
  }
4028
- var effectSchemaFirst = defineRule32({
4313
+ var effectSchemaFirst = defineRule34({
4029
4314
  meta: {
4030
4315
  type: "suggestion",
4031
4316
  schema: [
@@ -4035,6 +4320,7 @@ var effectSchemaFirst = defineRule32({
4035
4320
  properties: {
4036
4321
  member: { type: "string" },
4037
4322
  keep: optionsPatternSchema,
4323
+ allow: optionsPatternSchema,
4038
4324
  runtime: { type: "array", items: { type: "string" } },
4039
4325
  rows: {
4040
4326
  type: "object",
@@ -4064,6 +4350,7 @@ var effectSchemaFirst = defineRule32({
4064
4350
  createOnce(context) {
4065
4351
  let member = "Type";
4066
4352
  let keep = [];
4353
+ let allow = [];
4067
4354
  let runtime = new Set(effectSchemaFirstDefaultRuntime);
4068
4355
  let rows;
4069
4356
  let suffix = "Record";
@@ -4128,6 +4415,7 @@ var effectSchemaFirst = defineRule32({
4128
4415
  const options = optionsFirst(context, {});
4129
4416
  member = options.member ?? "Type";
4130
4417
  keep = optionsPatterns(options.keep);
4418
+ allow = optionsPatterns(options.allow);
4131
4419
  runtime = new Set(options.runtime ?? effectSchemaFirstDefaultRuntime);
4132
4420
  rows = options.rows ? new Set(options.rows.types ?? ["Kysely.Selectable"]) : undefined;
4133
4421
  suffix = options.rows?.suffix ?? "Record";
@@ -4147,7 +4435,7 @@ var effectSchemaFirst = defineRule32({
4147
4435
  const typed = new Set(exported.flatMap((node) => node.type === "TSTypeAliasDeclaration" && derives(node) ? [node.id.name] : []));
4148
4436
  for (const node of exported.flatMap((declaration) => declaration.type === "VariableDeclaration" ? declaration.declarations : [])) {
4149
4437
  const isSchema = node.init?.type === "CallExpression" || node.init?.type === "MemberExpression";
4150
- if (isSchema && node.id.type === "Identifier" && !typed.has(node.id.name)) {
4438
+ if (isSchema && node.id.type === "Identifier" && !typed.has(node.id.name) && !optionsPatternsTest(allow, node.id.name)) {
4151
4439
  context.report({
4152
4440
  node,
4153
4441
  messageId: "schemaType",
@@ -4197,8 +4485,104 @@ var effectSchemaFirst = defineRule32({
4197
4485
  }
4198
4486
  });
4199
4487
 
4488
+ // src/rules/effect/effect-service-params.ts
4489
+ import { defineRule as defineRule35 } from "@oxlint/plugins";
4490
+ function effectServiceParamsKey(member) {
4491
+ if (member.type !== "TSPropertySignature" && member.type !== "TSMethodSignature" || member.computed) {
4492
+ return;
4493
+ }
4494
+ return member.key.type === "Identifier" ? member.key.name : undefined;
4495
+ }
4496
+ function effectServiceParamsTypeName(name) {
4497
+ if (name.type === "TSQualifiedName") {
4498
+ return `${effectServiceParamsTypeName(name.left)}.${name.right.name}`;
4499
+ }
4500
+ return name.type === "Identifier" ? name.name : "this";
4501
+ }
4502
+ var effectServiceParams = defineRule35({
4503
+ meta: {
4504
+ type: "problem",
4505
+ schema: [
4506
+ {
4507
+ type: "object",
4508
+ additionalProperties: false,
4509
+ properties: {
4510
+ name: optionsPatternSchema,
4511
+ allow: optionsPatternSchema,
4512
+ declaration: { type: "string", minLength: 1 }
4513
+ }
4514
+ }
4515
+ ],
4516
+ messages: {
4517
+ name: "'{{path}}' takes '{{type}}'; a service method takes a params type that matches {{pattern}}.",
4518
+ inline: "'{{path}}' takes an unnamed type; a service method takes a params type that matches {{pattern}}."
4519
+ }
4520
+ },
4521
+ createOnce(context) {
4522
+ let options = {};
4523
+ let captures = {};
4524
+ let allowed = [];
4525
+ function checkParams(params, keys) {
4526
+ const first = params.at(0);
4527
+ const annotation = first && "typeAnnotation" in first ? first.typeAnnotation?.typeAnnotation : undefined;
4528
+ if (!first || !annotation) {
4529
+ return;
4530
+ }
4531
+ const values = { ...captures, path: keys.join("-"), key: keys.at(-1) ?? "" };
4532
+ const sources = [options.name ?? "^{Folder}\\w*Params$"].flat().map((source) => namingExpand(source, values, true, optionsEscape));
4533
+ const data = { path: keys.join("."), pattern: optionsPatternLabel(sources) };
4534
+ if (annotation.type !== "TSTypeReference") {
4535
+ context.report({
4536
+ node: first,
4537
+ messageId: "inline",
4538
+ data
4539
+ });
4540
+ return;
4541
+ }
4542
+ const type = effectServiceParamsTypeName(annotation.typeName);
4543
+ const last = type.split(".").at(-1) ?? type;
4544
+ if (!optionsPatternsTest(allowed, type) && !optionsPatternsTest(optionsPatterns(sources), last)) {
4545
+ context.report({
4546
+ node: first,
4547
+ messageId: "name",
4548
+ data: { ...data, type }
4549
+ });
4550
+ }
4551
+ }
4552
+ function check(literal, path) {
4553
+ for (const member of literal.members) {
4554
+ const key = effectServiceParamsKey(member);
4555
+ const type = member.type === "TSPropertySignature" ? member.typeAnnotation?.typeAnnotation : undefined;
4556
+ if (key === undefined) {
4557
+ continue;
4558
+ }
4559
+ if (member.type === "TSMethodSignature") {
4560
+ checkParams(member.params, [...path, key]);
4561
+ } else if (type?.type === "TSFunctionType") {
4562
+ checkParams(type.params, [...path, key]);
4563
+ } else if (type?.type === "TSTypeLiteral") {
4564
+ check(type, [...path, key]);
4565
+ }
4566
+ }
4567
+ }
4568
+ return {
4569
+ before() {
4570
+ options = optionsFirst(context, {});
4571
+ captures = namingCaptures(context.filename) ?? {};
4572
+ allowed = optionsPatterns(options.allow);
4573
+ },
4574
+ TSTypeLiteral(node) {
4575
+ const call = node.parent.type === "TSTypeParameterInstantiation" ? node.parent.parent : undefined;
4576
+ if (call?.type === "CallExpression" && astDottedName(call.callee) === (options.declaration ?? "Context.Service")) {
4577
+ check(node, []);
4578
+ }
4579
+ }
4580
+ };
4581
+ }
4582
+ });
4583
+
4200
4584
  // src/rules/effect/effect-values-first.ts
4201
- import { defineRule as defineRule33 } from "@oxlint/plugins";
4585
+ import { defineRule as defineRule36 } from "@oxlint/plugins";
4202
4586
  var effectValuesFirstDefaultPinned = [
4203
4587
  "^Layer\\.",
4204
4588
  "^Context\\.",
@@ -4207,7 +4591,7 @@ var effectValuesFirstDefaultPinned = [
4207
4591
  "(?:^|\\.)layer[^.]*$",
4208
4592
  "^Schema\\.(?:asserts|decode\\w*|encode\\w*|is|isSchema|isSchemaError|resolveAnnotations)$"
4209
4593
  ];
4210
- var effectValuesFirst = defineRule33({
4594
+ var effectValuesFirst = defineRule36({
4211
4595
  meta: {
4212
4596
  type: "suggestion",
4213
4597
  schema: [
@@ -4289,32 +4673,116 @@ var effectValuesFirst = defineRule33({
4289
4673
  }
4290
4674
  });
4291
4675
 
4292
- // src/rules/files/files-components-only.ts
4293
- import { defineRule as defineRule34 } from "@oxlint/plugins";
4294
-
4295
- // src/utils/react.utils.ts
4296
- function reactReturnsOutput(program, node) {
4297
- const expressions = astReturnExpressions(node);
4298
- if (expressions.some((expression) => astContainsJsx(expression) || expression.type === "Literal" && expression.value === null)) {
4299
- return true;
4300
- }
4301
- const returned = new Set(expressions.flatMap((expression) => expression.type === "Identifier" ? [expression.name] : []));
4302
- const propsWithChildren = new Set(program.body.flatMap((statement) => statement.type === "ImportDeclaration" && statement.source.value === "react" ? statement.specifiers.flatMap((specifier) => specifier.type === "ImportSpecifier" && astModuleName(specifier.imported) === "PropsWithChildren" ? [specifier.local.name] : []) : []));
4303
- return node.params.some((param) => {
4304
- const returnsProp = param.type === "ObjectPattern" && param.properties.some((property) => property.type === "Property" && property.value.type === "Identifier" && returned.has(property.value.name));
4305
- if (!returnsProp) {
4306
- return false;
4676
+ // src/rules/effect/effect-yield-name.ts
4677
+ import { defineRule as defineRule37 } from "@oxlint/plugins";
4678
+ var effectYieldName = defineRule37({
4679
+ meta: {
4680
+ type: "suggestion",
4681
+ schema: [
4682
+ {
4683
+ type: "object",
4684
+ additionalProperties: false,
4685
+ properties: {
4686
+ names: { type: "object", additionalProperties: optionsPatternSchema },
4687
+ allow: optionsPatternSchema
4688
+ }
4689
+ }
4690
+ ],
4691
+ messages: {
4692
+ name: "Name this '{{expected}}', not '{{actual}}': it holds {{source}}."
4307
4693
  }
4308
- let found = false;
4309
- astVisit(param.typeAnnotation, [], (candidate) => {
4310
- if (candidate.type === "TSTypeReference" && candidate.typeName.type === "Identifier" && propsWithChildren.has(candidate.typeName.name)) {
4311
- found = true;
4694
+ },
4695
+ createOnce(context) {
4696
+ return {
4697
+ VariableDeclarator(node) {
4698
+ const { id, init } = node;
4699
+ if (id.type !== "Identifier" || init?.type !== "YieldExpression" || !init.delegate || init.argument?.type !== "MemberExpression") {
4700
+ return;
4701
+ }
4702
+ const service = astMemberName(init.argument);
4703
+ const source = astDottedName(init.argument);
4704
+ if (!service || !source || !/^[A-Z]/.test(service)) {
4705
+ return;
4706
+ }
4707
+ const options = optionsFirst(context, {});
4708
+ const named = options.names?.[source] ?? options.names?.[`*.${service}`];
4709
+ const expected = named === undefined ? [`${service.charAt(0).toLowerCase()}${service.slice(1)}`] : [named].flat();
4710
+ if (!expected.includes(id.name) && !optionsPatternsTest(optionsPatterns(options.allow), id.name)) {
4711
+ context.report({
4712
+ node: id,
4713
+ messageId: "name",
4714
+ data: { expected: expected.join(" or "), actual: id.name, source }
4715
+ });
4716
+ }
4312
4717
  }
4313
- });
4314
- return found;
4315
- });
4316
- }
4317
- function reactIsComponentValue(program, initializer) {
4718
+ };
4719
+ }
4720
+ });
4721
+
4722
+ // src/rules/effect/effect-yields-first.ts
4723
+ import { defineRule as defineRule38 } from "@oxlint/plugins";
4724
+ function effectYieldsFirstService(statement) {
4725
+ const init = statement.type === "VariableDeclaration" && statement.declarations.length === 1 ? statement.declarations[0].init : null;
4726
+ const argument = init?.type === "YieldExpression" && init.delegate ? init.argument : null;
4727
+ return argument?.type === "MemberExpression" && /^[A-Z]/.test(astMemberName(argument) ?? "") ? astDottedName(argument) : undefined;
4728
+ }
4729
+ var effectYieldsFirst = defineRule38({
4730
+ meta: {
4731
+ type: "suggestion",
4732
+ messages: {
4733
+ first: "Yield {{source}} with the other dependencies, at the top of the function."
4734
+ }
4735
+ },
4736
+ createOnce(context) {
4737
+ return {
4738
+ FunctionExpression(node) {
4739
+ if (!node.generator || !node.body) {
4740
+ return;
4741
+ }
4742
+ let started = false;
4743
+ for (const statement of node.body.body) {
4744
+ const source = effectYieldsFirstService(statement);
4745
+ if (source === undefined) {
4746
+ started = true;
4747
+ } else if (started) {
4748
+ context.report({
4749
+ node: statement,
4750
+ messageId: "first",
4751
+ data: { source }
4752
+ });
4753
+ }
4754
+ }
4755
+ }
4756
+ };
4757
+ }
4758
+ });
4759
+
4760
+ // src/rules/files/files-components-only.ts
4761
+ import { defineRule as defineRule39 } from "@oxlint/plugins";
4762
+
4763
+ // src/utils/react.utils.ts
4764
+ function reactReturnsOutput(program, node) {
4765
+ const expressions = astReturnExpressions(node);
4766
+ if (expressions.some((expression) => astContainsJsx(expression) || expression.type === "Literal" && expression.value === null)) {
4767
+ return true;
4768
+ }
4769
+ const returned = new Set(expressions.flatMap((expression) => expression.type === "Identifier" ? [expression.name] : []));
4770
+ const propsWithChildren = new Set(program.body.flatMap((statement) => statement.type === "ImportDeclaration" && statement.source.value === "react" ? statement.specifiers.flatMap((specifier) => specifier.type === "ImportSpecifier" && astModuleName(specifier.imported) === "PropsWithChildren" ? [specifier.local.name] : []) : []));
4771
+ return node.params.some((param) => {
4772
+ const returnsProp = param.type === "ObjectPattern" && param.properties.some((property) => property.type === "Property" && property.value.type === "Identifier" && returned.has(property.value.name));
4773
+ if (!returnsProp) {
4774
+ return false;
4775
+ }
4776
+ let found = false;
4777
+ astVisit(param.typeAnnotation, [], (candidate) => {
4778
+ if (candidate.type === "TSTypeReference" && candidate.typeName.type === "Identifier" && propsWithChildren.has(candidate.typeName.name)) {
4779
+ found = true;
4780
+ }
4781
+ });
4782
+ return found;
4783
+ });
4784
+ }
4785
+ function reactIsComponentValue(program, initializer) {
4318
4786
  if (!initializer) {
4319
4787
  return false;
4320
4788
  }
@@ -4362,7 +4830,7 @@ function reactIsComponent(program, candidate) {
4362
4830
  function componentName(basename2) {
4363
4831
  return basename2.replace(/\.(tsx?|jsx?)$/, "").replaceAll(/(?:^[-.]*|[-.]+)(.?)/g, (_, char) => char.toUpperCase());
4364
4832
  }
4365
- var filesComponentsOnly = defineRule34({
4833
+ var filesComponentsOnly = defineRule39({
4366
4834
  meta: {
4367
4835
  type: "problem",
4368
4836
  schema: [
@@ -4450,7 +4918,7 @@ var filesComponentsOnly = defineRule34({
4450
4918
  });
4451
4919
 
4452
4920
  // src/rules/files/files-constants-only.ts
4453
- import { defineRule as defineRule35 } from "@oxlint/plugins";
4921
+ import { defineRule as defineRule40 } from "@oxlint/plugins";
4454
4922
  function unwrap(expression) {
4455
4923
  if (expression.type === "ParenthesizedExpression" || expression.type === "TSAsExpression" || expression.type === "TSSatisfiesExpression" || expression.type === "TSTypeAssertion" || expression.type === "TSNonNullExpression" || expression.type === "TSInstantiationExpression") {
4456
4924
  return unwrap(expression.expression);
@@ -4505,7 +4973,7 @@ function collectBindings(program) {
4505
4973
  }
4506
4974
  return bindings;
4507
4975
  }
4508
- var filesConstantsOnly = defineRule35({
4976
+ var filesConstantsOnly = defineRule40({
4509
4977
  meta: {
4510
4978
  type: "problem",
4511
4979
  schema: [
@@ -4604,7 +5072,7 @@ var filesConstantsOnly = defineRule35({
4604
5072
  });
4605
5073
 
4606
5074
  // src/rules/files/files-domain-constants.ts
4607
- import { defineRule as defineRule36 } from "@oxlint/plugins";
5075
+ import { defineRule as defineRule41 } from "@oxlint/plugins";
4608
5076
  import { basename as basename2, dirname as dirname2 } from "node:path";
4609
5077
  function isData(expression) {
4610
5078
  const value = astUnwrap(expression);
@@ -4622,7 +5090,7 @@ function isData(expression) {
4622
5090
  }
4623
5091
  return value.type === "NewExpression" && value.callee.type === "Identifier" && ["Map", "Set"].includes(value.callee.name) && value.arguments[0]?.type === "ArrayExpression" && value.arguments[0].elements.length > 0;
4624
5092
  }
4625
- var filesDomainConstants = defineRule36({
5093
+ var filesDomainConstants = defineRule41({
4626
5094
  meta: {
4627
5095
  type: "problem",
4628
5096
  schema: [
@@ -4687,9 +5155,8 @@ var filesDomainConstants = defineRule36({
4687
5155
  });
4688
5156
 
4689
5157
  // src/rules/files/files-exports.ts
4690
- import { defineRule as defineRule37 } from "@oxlint/plugins";
4691
- import { posix as posix2 } from "node:path";
4692
- var filesExports = defineRule37({
5158
+ import { defineRule as defineRule42 } from "@oxlint/plugins";
5159
+ var filesExports = defineRule42({
4693
5160
  meta: {
4694
5161
  type: "problem",
4695
5162
  schema: [
@@ -4705,6 +5172,8 @@ var filesExports = defineRule37({
4705
5172
  separators: { type: "array", items: { type: "string" } },
4706
5173
  types: { type: "boolean" },
4707
5174
  factory: { type: "string" },
5175
+ file: { type: "string" },
5176
+ placeholder: { type: "string" },
4708
5177
  scope: { type: "string", enum: ["exports", "declarations"] }
4709
5178
  },
4710
5179
  anyOf: [{ required: ["names"] }, { required: ["patterns"] }, { required: ["factory"] }]
@@ -4743,16 +5212,12 @@ var filesExports = defineRule37({
4743
5212
  if (options.names === undefined && options.patterns === undefined) {
4744
5213
  return;
4745
5214
  }
4746
- const read = options.stem === "folder" ? namingBasename(posix2.dirname(context.filename.replaceAll("\\", "/"))) : namingFileStem(basename3, options.stem, options.roles, options.separators);
4747
- const last = read.split(/[-_]+/).at(-1) ?? "";
4748
- const domain = options.singularize === "trailing-s" && last.length > 1 && last.endsWith("s") ? read.slice(0, -1) : read;
4749
- const pascalDomain = namingPascalCase(domain);
4750
- const camelDomain = namingCamelCase(domain);
4751
- const allowed = (options.names ?? []).map((template) => template.replaceAll("{Domain}", pascalDomain).replaceAll("{domain}", camelDomain));
4752
- const patterns = (options.patterns ?? []).map((template) => {
4753
- const source = template.replaceAll("{Domain}", optionsEscape(pascalDomain)).replaceAll("{domain}", optionsEscape(camelDomain));
4754
- return new RegExp(`^(?:${source})$`);
4755
- });
5215
+ const captures = namingCaptures(context.filename, options);
5216
+ if (!captures) {
5217
+ return;
5218
+ }
5219
+ const allowed = (options.names ?? []).map((template) => namingExpand(template, captures, true));
5220
+ const patterns = (options.patterns ?? []).map((template) => new RegExp(`^(?:${namingExpand(template, captures, true, optionsEscape)})$`));
4756
5221
  const allowedLabel = [...allowed, ...patterns.map((pattern) => pattern.toString())].join(", ");
4757
5222
  for (const binding of exportsCollect(program)) {
4758
5223
  if (options.types && binding.typeOnly) {
@@ -4773,12 +5238,12 @@ var filesExports = defineRule37({
4773
5238
  });
4774
5239
 
4775
5240
  // src/rules/files/files-externals.ts
4776
- import { defineRule as defineRule38 } from "@oxlint/plugins";
4777
- import { existsSync as existsSync2, readFileSync } from "node:fs";
5241
+ import { defineRule as defineRule43 } from "@oxlint/plugins";
5242
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
4778
5243
  import { builtinModules as builtinModules2 } from "node:module";
4779
5244
  import { dirname as dirname3, join as join2 } from "node:path";
4780
5245
  var filesExternalsConfigs = "^(?:vite|next)\\.config\\.[cm]?[jt]s$";
4781
- var filesExternals = defineRule38({
5246
+ var filesExternals = defineRule43({
4782
5247
  meta: {
4783
5248
  type: "problem",
4784
5249
  schema: [
@@ -4804,7 +5269,7 @@ var filesExternals = defineRule38({
4804
5269
  }
4805
5270
  let dependencies;
4806
5271
  try {
4807
- const manifest = JSON.parse(readFileSync(join2(folder, "package.json"), "utf8"));
5272
+ const manifest = JSON.parse(readFileSync2(join2(folder, "package.json"), "utf8"));
4808
5273
  dependencies = [...Object.keys(manifest.dependencies ?? {}), ...Object.keys(manifest.optionalDependencies ?? {})];
4809
5274
  } catch {
4810
5275
  return;
@@ -4871,7 +5336,7 @@ var filesExternals = defineRule38({
4871
5336
  });
4872
5337
 
4873
5338
  // src/rules/files/files-factory-keys.ts
4874
- import { defineRule as defineRule39 } from "@oxlint/plugins";
5339
+ import { defineRule as defineRule44 } from "@oxlint/plugins";
4875
5340
  function returnedObject(expression) {
4876
5341
  if (expression?.type === "TSAsExpression" || expression?.type === "TSSatisfiesExpression" || expression?.type === "TSTypeAssertion" || expression?.type === "TSNonNullExpression") {
4877
5342
  return returnedObject(expression.expression);
@@ -4882,7 +5347,7 @@ function compileKeys(pattern, keys, requireKeys) {
4882
5347
  const allowedList = keys.concat(requireKeys.filter((key) => !keys.includes(key)));
4883
5348
  return { patterns: optionsPatternsWithEmpty(pattern), allowed: new Set(allowedList), allowedList, required: requireKeys };
4884
5349
  }
4885
- var filesFactoryKeys = defineRule39({
5350
+ var filesFactoryKeys = defineRule44({
4886
5351
  meta: {
4887
5352
  type: "problem",
4888
5353
  schema: [
@@ -5000,8 +5465,8 @@ var filesFactoryKeys = defineRule39({
5000
5465
  });
5001
5466
 
5002
5467
  // src/rules/files/files-helpers.ts
5003
- import { defineRule as defineRule40 } from "@oxlint/plugins";
5004
- var filesHelpers = defineRule40({
5468
+ import { defineRule as defineRule45 } from "@oxlint/plugins";
5469
+ var filesHelpers = defineRule45({
5005
5470
  meta: {
5006
5471
  type: "problem",
5007
5472
  schema: [
@@ -5049,8 +5514,8 @@ var filesHelpers = defineRule40({
5049
5514
  });
5050
5515
 
5051
5516
  // src/rules/files/files-no-functions.ts
5052
- import { defineRule as defineRule41 } from "@oxlint/plugins";
5053
- var filesNoFunctions = defineRule41({
5517
+ import { defineRule as defineRule46 } from "@oxlint/plugins";
5518
+ var filesNoFunctions = defineRule46({
5054
5519
  meta: {
5055
5520
  type: "problem",
5056
5521
  schema: [
@@ -5104,8 +5569,8 @@ var filesNoFunctions = defineRule41({
5104
5569
  });
5105
5570
 
5106
5571
  // src/rules/files/files-restricted.ts
5107
- import { defineRule as defineRule42 } from "@oxlint/plugins";
5108
- var filesRestricted = defineRule42({
5572
+ import { defineRule as defineRule47 } from "@oxlint/plugins";
5573
+ var filesRestricted = defineRule47({
5109
5574
  meta: {
5110
5575
  type: "problem",
5111
5576
  schema: [
@@ -5137,7 +5602,7 @@ var filesRestricted = defineRule42({
5137
5602
  });
5138
5603
 
5139
5604
  // src/rules/files/files-route.ts
5140
- import { defineRule as defineRule43 } from "@oxlint/plugins";
5605
+ import { defineRule as defineRule48 } from "@oxlint/plugins";
5141
5606
  function inspectAdapter(context, item, bannedHooks, banIntrinsicJsx) {
5142
5607
  astVisit(item.node.body, [item.node], (node) => {
5143
5608
  if (banIntrinsicJsx && node.type === "JSXOpeningElement" && node.name.type === "JSXIdentifier" && /^[a-z]/.test(node.name.name)) {
@@ -5157,7 +5622,7 @@ function inspectAdapter(context, item, bannedHooks, banIntrinsicJsx) {
5157
5622
  }
5158
5623
  });
5159
5624
  }
5160
- var filesRoute = defineRule43({
5625
+ var filesRoute = defineRule48({
5161
5626
  meta: {
5162
5627
  type: "problem",
5163
5628
  schema: [
@@ -5226,8 +5691,247 @@ var filesRoute = defineRule43({
5226
5691
  }
5227
5692
  });
5228
5693
 
5694
+ // src/rules/files/files-siblings.ts
5695
+ import { defineRule as defineRule49 } from "@oxlint/plugins";
5696
+ import { existsSync as existsSync3 } from "node:fs";
5697
+ import { dirname as dirname4, join as join3 } from "node:path";
5698
+ var filesSiblings = defineRule49({
5699
+ meta: {
5700
+ type: "problem",
5701
+ schema: [
5702
+ {
5703
+ type: "object",
5704
+ additionalProperties: false,
5705
+ properties: {
5706
+ require: optionsPatternSchema,
5707
+ message: { type: "string" }
5708
+ },
5709
+ required: ["require"]
5710
+ }
5711
+ ],
5712
+ messages: {
5713
+ missing: "This file needs '{{file}}' beside it.{{message}}"
5714
+ }
5715
+ },
5716
+ createOnce(context) {
5717
+ return {
5718
+ Program(program) {
5719
+ const options = optionsFirst(context, { require: [] });
5720
+ const captures = namingCaptures(context.filename) ?? {};
5721
+ for (const template of [options.require].flat()) {
5722
+ const file = namingExpand(template, captures, false);
5723
+ if (!existsSync3(join3(dirname4(context.filename), file))) {
5724
+ context.report({
5725
+ node: program,
5726
+ messageId: "missing",
5727
+ data: { file, message: options.message ? ` ${options.message}` : "" }
5728
+ });
5729
+ }
5730
+ }
5731
+ }
5732
+ };
5733
+ }
5734
+ });
5735
+
5736
+ // src/rules/files/files-top-level.ts
5737
+ import { defineRule as defineRule50 } from "@oxlint/plugins";
5738
+ var filesTopLevelKinds = [
5739
+ "import",
5740
+ "export",
5741
+ "reexport",
5742
+ "default",
5743
+ "type",
5744
+ "interface",
5745
+ "enum",
5746
+ "class",
5747
+ "namespace",
5748
+ "const",
5749
+ "let",
5750
+ "var",
5751
+ "function",
5752
+ "function-const",
5753
+ "call",
5754
+ "statement"
5755
+ ];
5756
+ var filesTopLevelDeclared = new Map([
5757
+ ["FunctionDeclaration", "function"],
5758
+ ["TSDeclareFunction", "function"],
5759
+ ["ClassDeclaration", "class"],
5760
+ ["TSTypeAliasDeclaration", "type"],
5761
+ ["TSInterfaceDeclaration", "interface"],
5762
+ ["TSEnumDeclaration", "enum"],
5763
+ ["TSModuleDeclaration", "namespace"]
5764
+ ]);
5765
+ var filesTopLevelEntries = {
5766
+ type: "array",
5767
+ items: {
5768
+ anyOf: [
5769
+ { type: "string" },
5770
+ {
5771
+ type: "object",
5772
+ additionalProperties: false,
5773
+ properties: {
5774
+ kind: { anyOf: [{ type: "string", enum: [...filesTopLevelKinds] }, { type: "array", items: { type: "string", enum: [...filesTopLevelKinds] }, minItems: 1 }] },
5775
+ names: optionsPatternSchema,
5776
+ from: optionsPatternSchema,
5777
+ exported: { type: "boolean" },
5778
+ message: { type: "string" }
5779
+ },
5780
+ required: ["kind"]
5781
+ }
5782
+ ]
5783
+ }
5784
+ };
5785
+ var filesTopLevelValues = new Map([
5786
+ ["Literal", "<literal>"],
5787
+ ["TemplateLiteral", "<literal>"],
5788
+ ["ObjectExpression", "<object>"],
5789
+ ["ArrayExpression", "<array>"],
5790
+ ["FunctionExpression", "<function>"],
5791
+ ["ArrowFunctionExpression", "<function>"]
5792
+ ]);
5793
+ function filesTopLevelHead(node) {
5794
+ if (!node) {
5795
+ return "<none>";
5796
+ }
5797
+ if (node.type === "AwaitExpression") {
5798
+ return filesTopLevelHead(node.argument);
5799
+ }
5800
+ if (node.type === "ParenthesizedExpression" || node.type === "TSAsExpression" || node.type === "TSSatisfiesExpression" || node.type === "TSTypeAssertion" || node.type === "TSNonNullExpression" || node.type === "ChainExpression") {
5801
+ return filesTopLevelHead(node.expression);
5802
+ }
5803
+ if (node.type === "CallExpression" || node.type === "NewExpression") {
5804
+ return filesTopLevelHead(node.callee);
5805
+ }
5806
+ if (node.type === "TaggedTemplateExpression") {
5807
+ return filesTopLevelHead(node.tag);
5808
+ }
5809
+ if (node.type === "MemberExpression") {
5810
+ return astDottedName(node) ?? filesTopLevelHead(node.object);
5811
+ }
5812
+ return node.type === "Identifier" ? node.name : filesTopLevelValues.get(node.type) ?? "<other>";
5813
+ }
5814
+ function filesTopLevelItems(statement) {
5815
+ const item = (kind, name, node2, from = "", exported2 = false) => ({ kind, name, from, exported: exported2, node: node2 });
5816
+ if (statement.type === "ExpressionStatement" && statement.directive) {
5817
+ return [];
5818
+ }
5819
+ if (statement.type === "ImportDeclaration") {
5820
+ return [item("import", statement.source.value, statement)];
5821
+ }
5822
+ if (statement.type === "ExportAllDeclaration") {
5823
+ return [item("reexport", statement.source.value, statement, "", true)];
5824
+ }
5825
+ if (statement.type === "ExportNamedDeclaration" && !statement.declaration) {
5826
+ const kind = statement.source ? "reexport" : "export";
5827
+ const names = statement.specifiers.map((specifier) => item(kind, astModuleName(specifier.exported), specifier, statement.source?.value ?? "", true));
5828
+ return names.length > 0 ? names : [item(kind, "", statement, statement.source?.value ?? "", true)];
5829
+ }
5830
+ const exported = statement.type === "ExportNamedDeclaration" || statement.type === "ExportDefaultDeclaration";
5831
+ const node = exported ? statement.declaration : statement;
5832
+ if (!node) {
5833
+ return [];
5834
+ }
5835
+ if (node.type === "VariableDeclaration") {
5836
+ return node.declarations.flatMap((declarator) => {
5837
+ const variable = node.kind === "using" || node.kind === "await using" ? "statement" : node.kind;
5838
+ const kind = declarationsIsFunctionValue(declarator.init) ? "function-const" : variable;
5839
+ return astBindings(declarator.id).map((binding) => item(kind, binding.name, declarator, filesTopLevelHead(declarator.init), exported));
5840
+ });
5841
+ }
5842
+ const declared = filesTopLevelDeclared.get(node.type);
5843
+ if (declared) {
5844
+ const id = "id" in node ? node.id : null;
5845
+ return [item(declared, id && "name" in id ? id.name : "", node, "", exported)];
5846
+ }
5847
+ if (statement.type === "ExportDefaultDeclaration") {
5848
+ return [item("default", filesTopLevelHead(node), statement, filesTopLevelHead(node), true)];
5849
+ }
5850
+ if (statement.type === "ExpressionStatement") {
5851
+ const expression = astUnwrap(statement.expression);
5852
+ if (expression.type === "CallExpression" || expression.type === "TaggedTemplateExpression") {
5853
+ return [item("call", filesTopLevelHead(expression), statement)];
5854
+ }
5855
+ }
5856
+ return [item("statement", statement.type, statement)];
5857
+ }
5858
+ var filesTopLevel = defineRule50({
5859
+ meta: {
5860
+ type: "problem",
5861
+ schema: [
5862
+ {
5863
+ type: "object",
5864
+ additionalProperties: false,
5865
+ properties: {
5866
+ allow: filesTopLevelEntries,
5867
+ deny: filesTopLevelEntries,
5868
+ message: { type: "string" },
5869
+ stem: { type: "string", enum: [...namingStemModes, "folder"] },
5870
+ singularize: { type: "string", enum: ["none", "trailing-s"] },
5871
+ roles: { type: "array", items: { type: "string" } },
5872
+ separators: { type: "array", items: { type: "string" } },
5873
+ file: { type: "string" },
5874
+ placeholder: { type: "string" }
5875
+ },
5876
+ anyOf: [{ required: ["allow"] }, { required: ["deny"] }]
5877
+ }
5878
+ ],
5879
+ messages: {
5880
+ denied: "Top-level {{what}} is not allowed in this file.{{message}}",
5881
+ unlisted: "Top-level {{what}} is not allowed in this file; allowed: {{allowed}}.{{message}}"
5882
+ }
5883
+ },
5884
+ createOnce(context) {
5885
+ return {
5886
+ Program(program) {
5887
+ const options = optionsFirst(context, {});
5888
+ const captures = namingCaptures(context.filename, options);
5889
+ if (!captures) {
5890
+ return;
5891
+ }
5892
+ const patterns = (pattern) => pattern === undefined ? null : optionsPatterns([pattern].flat().map((source) => namingExpand(source, captures, true, optionsEscape)));
5893
+ const matcher = (entry) => {
5894
+ if (typeof entry !== "string") {
5895
+ return { kinds: [entry.kind].flat(), names: patterns(entry.names), from: patterns(entry.from), exported: entry.exported, message: entry.message ?? "" };
5896
+ }
5897
+ const kind = filesTopLevelKinds.find((name) => name === entry);
5898
+ return kind ? { kinds: [kind], names: null, from: null, message: "" } : { kinds: ["call"], names: optionsWildcards(entry), from: null, message: "" };
5899
+ };
5900
+ const matches = (item) => (entry) => entry.kinds.includes(item.kind) && (entry.names === null || optionsPatternsTest(entry.names, item.name)) && (entry.from === null || optionsPatternsTest(entry.from, item.from)) && (entry.exported === undefined || entry.exported === item.exported);
5901
+ const allow = options.allow?.map(matcher);
5902
+ const deny = (options.deny ?? []).map(matcher);
5903
+ const label = (entry) => [
5904
+ entry.exported === undefined ? [] : [entry.exported ? "exported" : "unexported"],
5905
+ [entry.kind].flat().join("/"),
5906
+ entry.names === undefined ? [] : ["named", [entry.names].flat().join(" | ")],
5907
+ entry.from === undefined ? [] : ["from", [entry.from].flat().join(" | ")]
5908
+ ].flat().join(" ");
5909
+ const allowed = (options.allow ?? []).map((entry) => typeof entry === "string" ? entry : label(entry)).join(", ");
5910
+ const hint = options.message ? ` ${options.message}` : "";
5911
+ for (const item of program.body.flatMap(filesTopLevelItems)) {
5912
+ const what = item.name && item.kind !== "statement" ? `${item.kind} '${item.name}'` : item.kind;
5913
+ const denied = deny.find(matches(item));
5914
+ if (denied) {
5915
+ context.report({
5916
+ node: item.node,
5917
+ messageId: "denied",
5918
+ data: { what, message: denied.message ? ` ${denied.message}` : hint }
5919
+ });
5920
+ } else if (allow && !allow.some(matches(item))) {
5921
+ context.report({
5922
+ node: item.node,
5923
+ messageId: "unlisted",
5924
+ data: { what, allowed, message: hint }
5925
+ });
5926
+ }
5927
+ }
5928
+ }
5929
+ };
5930
+ }
5931
+ });
5932
+
5229
5933
  // src/rules/files/files-types-only.ts
5230
- import { defineRule as defineRule44 } from "@oxlint/plugins";
5934
+ import { defineRule as defineRule51 } from "@oxlint/plugins";
5231
5935
  function runtimeImportLocalNames(statement) {
5232
5936
  return statement.specifiers.flatMap((specifier) => specifier.type !== "ImportSpecifier" || specifier.importKind !== "type" ? [specifier.local.name] : []);
5233
5937
  }
@@ -5396,7 +6100,7 @@ function runtimeKind(node) {
5396
6100
  }
5397
6101
  return node.type === "FunctionDeclaration" ? "function" : "variable";
5398
6102
  }
5399
- var filesTypesOnly = defineRule44({
6103
+ var filesTypesOnly = defineRule51({
5400
6104
  meta: {
5401
6105
  type: "problem",
5402
6106
  schema: [
@@ -5504,8 +6208,8 @@ var filesTypesOnly = defineRule44({
5504
6208
  });
5505
6209
 
5506
6210
  // src/rules/layout/layout-arrow-body.ts
5507
- import { defineRule as defineRule45 } from "@oxlint/plugins";
5508
- var layoutArrowBody = defineRule45({
6211
+ import { defineRule as defineRule52 } from "@oxlint/plugins";
6212
+ var layoutArrowBody = defineRule52({
5509
6213
  meta: {
5510
6214
  type: "layout",
5511
6215
  fixable: "whitespace",
@@ -5557,12 +6261,12 @@ var layoutArrowBody = defineRule45({
5557
6261
  });
5558
6262
 
5559
6263
  // src/rules/layout/layout-call-arguments.ts
5560
- import { defineRule as defineRule46 } from "@oxlint/plugins";
6264
+ import { defineRule as defineRule53 } from "@oxlint/plugins";
5561
6265
  function layoutCallArgumentsHuggable(node) {
5562
6266
  return astIsInlineFunction(node) || node.type === "ObjectExpression" || node.type === "ArrayExpression" || astIsCall(node) && node.arguments.length === 1 && (node.callee.type !== "MemberExpression" || astIsOneLine(node.callee)) && node.arguments.every(layoutCallArgumentsHuggable);
5563
6267
  }
5564
6268
  var layoutCallArgumentsMax = { type: "integer", minimum: 1 };
5565
- var layoutCallArguments = defineRule46({
6269
+ var layoutCallArguments = defineRule53({
5566
6270
  meta: {
5567
6271
  type: "layout",
5568
6272
  fixable: "whitespace",
@@ -5708,7 +6412,7 @@ var layoutCallArguments = defineRule46({
5708
6412
  fix: (fixer) => sourceRespace(fixer, text, gaps, (_, end) => `${newline}${end ? base : inner}`)
5709
6413
  });
5710
6414
  };
5711
- const join3 = (node, items, open, close) => {
6415
+ const join4 = (node, items, open, close) => {
5712
6416
  const source = context.sourceCode;
5713
6417
  const text = source.text;
5714
6418
  const first = items.at(0);
@@ -5737,7 +6441,7 @@ var layoutCallArguments = defineRule46({
5737
6441
  hug(node, options.hug.max);
5738
6442
  }
5739
6443
  if (options.join && !(options.join.keep ?? []).includes(source.getText(node.callee)) && !(isPipe(node) && (node.arguments.length > 1 || options.pipe)) && astCallDepth(node) <= (options.join.nesting ?? Number.POSITIVE_INFINITY)) {
5740
- join3(node, node.arguments, source.getTokenAfter(node.typeArguments ?? node.callee), source.getLastToken(node));
6444
+ join4(node, node.arguments, source.getTokenAfter(node.typeArguments ?? node.callee), source.getLastToken(node));
5741
6445
  }
5742
6446
  };
5743
6447
  const parameters = (node) => {
@@ -5747,7 +6451,7 @@ var layoutCallArguments = defineRule46({
5747
6451
  if (!options.join || !first || !last) {
5748
6452
  return;
5749
6453
  }
5750
- join3(node, node.params, source.getTokenBefore(first, { filter: (token) => token.value === "(" }), source.getTokenAfter(last, { filter: (token) => token.value === ")" }));
6454
+ join4(node, node.params, source.getTokenBefore(first, { filter: (token) => token.value === "(" }), source.getTokenAfter(last, { filter: (token) => token.value === ")" }));
5751
6455
  };
5752
6456
  return {
5753
6457
  before() {
@@ -5768,12 +6472,12 @@ var layoutCallArguments = defineRule46({
5768
6472
  });
5769
6473
 
5770
6474
  // src/rules/layout/layout-call-array.ts
5771
- import { defineRule as defineRule47 } from "@oxlint/plugins";
6475
+ import { defineRule as defineRule54 } from "@oxlint/plugins";
5772
6476
  var layoutCallArrayDefaultCallees = ["Promise.all", "Promise.allSettled"];
5773
6477
  function layoutCallArrayRoot(node) {
5774
6478
  return node.type === "MemberExpression" ? layoutCallArrayRoot(node.object) : node;
5775
6479
  }
5776
- var layoutCallArray = defineRule47({
6480
+ var layoutCallArray = defineRule54({
5777
6481
  meta: {
5778
6482
  type: "layout",
5779
6483
  fixable: "whitespace",
@@ -5889,7 +6593,7 @@ var layoutCallArray = defineRule47({
5889
6593
  });
5890
6594
 
5891
6595
  // src/rules/layout/layout-call-depth.ts
5892
- import { defineRule as defineRule48 } from "@oxlint/plugins";
6596
+ import { defineRule as defineRule55 } from "@oxlint/plugins";
5893
6597
  function layoutCallDepthOuter(node, callbacks) {
5894
6598
  const parent = node.parent;
5895
6599
  if (!parent || !callbacks && (parent.type === "ArrowFunctionExpression" || parent.type === "FunctionExpression")) {
@@ -5904,7 +6608,7 @@ function layoutCallDepthOuter(node, callbacks) {
5904
6608
  }
5905
6609
  return astIsCall(parent) && parent.arguments.some((argument) => argument === node) ? parent : layoutCallDepthOuter(parent, callbacks);
5906
6610
  }
5907
- var layoutCallDepth = defineRule48({
6611
+ var layoutCallDepth = defineRule55({
5908
6612
  meta: {
5909
6613
  type: "layout",
5910
6614
  schema: [
@@ -5946,8 +6650,8 @@ var layoutCallDepth = defineRule48({
5946
6650
  });
5947
6651
 
5948
6652
  // src/rules/layout/layout-chain.ts
5949
- import { defineRule as defineRule49 } from "@oxlint/plugins";
5950
- var layoutChain = defineRule49({
6653
+ import { defineRule as defineRule56 } from "@oxlint/plugins";
6654
+ var layoutChain = defineRule56({
5951
6655
  meta: {
5952
6656
  type: "layout",
5953
6657
  fixable: "whitespace",
@@ -6066,8 +6770,8 @@ var layoutChain = defineRule49({
6066
6770
  });
6067
6771
 
6068
6772
  // src/rules/layout/layout-items.ts
6069
- import { defineRule as defineRule50 } from "@oxlint/plugins";
6070
- var layoutItems = defineRule50({
6773
+ import { defineRule as defineRule57 } from "@oxlint/plugins";
6774
+ var layoutItems = defineRule57({
6071
6775
  meta: {
6072
6776
  type: "layout",
6073
6777
  fixable: "whitespace",
@@ -6122,8 +6826,8 @@ var layoutItems = defineRule50({
6122
6826
  });
6123
6827
 
6124
6828
  // src/rules/layout/layout-jsx-attributes.ts
6125
- import { defineRule as defineRule51 } from "@oxlint/plugins";
6126
- var layoutJsxAttributes = defineRule51({
6829
+ import { defineRule as defineRule58 } from "@oxlint/plugins";
6830
+ var layoutJsxAttributes = defineRule58({
6127
6831
  meta: {
6128
6832
  type: "layout",
6129
6833
  fixable: "whitespace",
@@ -6211,8 +6915,8 @@ var layoutJsxAttributes = defineRule51({
6211
6915
  });
6212
6916
 
6213
6917
  // src/rules/layout/layout-key-value.ts
6214
- import { defineRule as defineRule52 } from "@oxlint/plugins";
6215
- var layoutKeyValue = defineRule52({
6918
+ import { defineRule as defineRule59 } from "@oxlint/plugins";
6919
+ var layoutKeyValue = defineRule59({
6216
6920
  meta: {
6217
6921
  type: "layout",
6218
6922
  fixable: "whitespace",
@@ -6248,7 +6952,7 @@ var layoutKeyValue = defineRule52({
6248
6952
  });
6249
6953
 
6250
6954
  // src/rules/layout/layout-object.ts
6251
- import { defineRule as defineRule53 } from "@oxlint/plugins";
6955
+ import { defineRule as defineRule60 } from "@oxlint/plugins";
6252
6956
  function layoutObjectIsWhitespace(text) {
6253
6957
  return /^[\t\n\r\f ]*$/.test(text);
6254
6958
  }
@@ -6256,7 +6960,7 @@ function layoutObjectIsFlat(property) {
6256
6960
  const value = property.type === "SpreadElement" ? property.argument : property.value;
6257
6961
  return astIsOneLine(property) && (property.type === "SpreadElement" || !property.method && property.kind === "init") && value.type !== "ObjectExpression" && value.type !== "ArrayExpression" && !astIsInlineFunction(value);
6258
6962
  }
6259
- var layoutObject = defineRule53({
6963
+ var layoutObject = defineRule60({
6260
6964
  meta: {
6261
6965
  type: "layout",
6262
6966
  fixable: "whitespace",
@@ -6301,7 +7005,7 @@ var layoutObject = defineRule53({
6301
7005
  let indentUnit = sourceIndentUnit();
6302
7006
  let newline = `
6303
7007
  `;
6304
- let join3;
7008
+ let join4;
6305
7009
  let params = false;
6306
7010
  let nested = false;
6307
7011
  let siblings = false;
@@ -6359,7 +7063,7 @@ var layoutObject = defineRule53({
6359
7063
  }
6360
7064
  function joinBlocked(node, call) {
6361
7065
  const callee = call && astIsCall(call) ? astDottedName(call.callee) : undefined;
6362
- const kept = callee !== undefined && (join3?.keep ?? []).some((name) => callee === name || callee.endsWith(`.${name}`));
7066
+ const kept = callee !== undefined && (join4?.keep ?? []).some((name) => callee === name || callee.endsWith(`.${name}`));
6363
7067
  return kept || keptByInner(node) || splitSiblings(node) > 1 || node.properties.length === 0 || !node.properties.every(layoutObjectIsFlat) || context.sourceCode.getCommentsInside(node).length > 0;
6364
7068
  }
6365
7069
  function reportSplit(node, properties, open, close, messageId) {
@@ -6422,7 +7126,7 @@ var layoutObject = defineRule53({
6422
7126
  scope = options.scope ?? "call-args";
6423
7127
  indentUnit = sourceIndentUnit(options.indent);
6424
7128
  newline = sourceNewline(context.sourceCode.text);
6425
- join3 = options.join;
7129
+ join4 = options.join;
6426
7130
  params = options.params ?? false;
6427
7131
  nested = options.nested ?? false;
6428
7132
  siblings = options.siblings ?? false;
@@ -6447,7 +7151,7 @@ var layoutObject = defineRule53({
6447
7151
  return;
6448
7152
  }
6449
7153
  const split = full || holds;
6450
- if (split ? !astIsOneLine(node) : !join3 || astIsOneLine(node)) {
7154
+ if (split ? !astIsOneLine(node) : !join4 || astIsOneLine(node)) {
6451
7155
  return;
6452
7156
  }
6453
7157
  const call = (parent.type === "CallExpression" || parent.type === "NewExpression") && parent.arguments.includes(node) ? parent : undefined;
@@ -6461,7 +7165,7 @@ var layoutObject = defineRule53({
6461
7165
  const gaps = sourceItemGaps(node.range[0] + 1, properties, node.range[1] - 1);
6462
7166
  const comma = text.slice(...gaps.at(-1) ?? [0, 0]).includes(",") ? "," : "";
6463
7167
  const joined = ` ${properties.map((property) => source.getText(property)).join(", ")}${comma} `;
6464
- if (sourceJoinedWidth(text, node.range[0] + 1, joined, node.range[1] - 1) > (join3?.max ?? 0)) {
7168
+ if (sourceJoinedWidth(text, node.range[0] + 1, joined, node.range[1] - 1) > (join4?.max ?? 0)) {
6465
7169
  return;
6466
7170
  }
6467
7171
  context.report({
@@ -6480,7 +7184,7 @@ var layoutObject = defineRule53({
6480
7184
  });
6481
7185
 
6482
7186
  // src/rules/layout/layout-padding.ts
6483
- import { defineRule as defineRule54 } from "@oxlint/plugins";
7187
+ import { defineRule as defineRule61 } from "@oxlint/plugins";
6484
7188
  var layoutPaddingControl = new Set([
6485
7189
  "IfStatement",
6486
7190
  "ForStatement",
@@ -6509,7 +7213,7 @@ function layoutPaddingKind(node) {
6509
7213
  function layoutPaddingIsMultilineVariable(node, kind) {
6510
7214
  return kind === "variable" && node.loc.start.line !== node.loc.end.line;
6511
7215
  }
6512
- var layoutPadding = defineRule54({
7216
+ var layoutPadding = defineRule61({
6513
7217
  meta: {
6514
7218
  type: "layout",
6515
7219
  fixable: "whitespace",
@@ -6598,8 +7302,8 @@ var layoutPadding = defineRule54({
6598
7302
  });
6599
7303
 
6600
7304
  // src/rules/layout/layout-pipe.ts
6601
- import { defineRule as defineRule55 } from "@oxlint/plugins";
6602
- var layoutPipe = defineRule55({
7305
+ import { defineRule as defineRule62 } from "@oxlint/plugins";
7306
+ var layoutPipe = defineRule62({
6603
7307
  meta: {
6604
7308
  type: "layout",
6605
7309
  schema: [{ type: "object", additionalProperties: false, properties: { methods: { type: "array", items: { type: "string" } } } }],
@@ -6640,7 +7344,7 @@ var layoutPipe = defineRule55({
6640
7344
  });
6641
7345
 
6642
7346
  // src/rules/layout/layout-ternary.ts
6643
- import { defineRule as defineRule56 } from "@oxlint/plugins";
7347
+ import { defineRule as defineRule63 } from "@oxlint/plugins";
6644
7348
  function layoutTernaryLines(node) {
6645
7349
  return node.loc.end.line - node.loc.start.line + 1;
6646
7350
  }
@@ -6648,7 +7352,7 @@ function layoutTernaryBreak(between, operator, newline) {
6648
7352
  const at = between.indexOf(operator);
6649
7353
  return `${between.slice(0, at).trimEnd()}${newline}${operator} ${between.slice(at + 1).trimStart()}`;
6650
7354
  }
6651
- var layoutTernary = defineRule56({
7355
+ var layoutTernary = defineRule63({
6652
7356
  meta: {
6653
7357
  type: "layout",
6654
7358
  fixable: "whitespace",
@@ -6764,8 +7468,8 @@ var layoutTernary = defineRule56({
6764
7468
  });
6765
7469
 
6766
7470
  // src/rules/layout/layout-type-arguments.ts
6767
- import { defineRule as defineRule57 } from "@oxlint/plugins";
6768
- var layoutTypeArguments = defineRule57({
7471
+ import { defineRule as defineRule64 } from "@oxlint/plugins";
7472
+ var layoutTypeArguments = defineRule64({
6769
7473
  meta: {
6770
7474
  type: "layout",
6771
7475
  fixable: "code",
@@ -6824,13 +7528,14 @@ var layoutTypeArguments = defineRule57({
6824
7528
  });
6825
7529
 
6826
7530
  // src/rules/naming/naming-declarations.ts
6827
- import { defineRule as defineRule58 } from "@oxlint/plugins";
7531
+ import { defineRule as defineRule65 } from "@oxlint/plugins";
6828
7532
  var namingDeclarationsKinds = ["function", "const", "let", "var", "class", "type", "interface", "enum"];
6829
- var namingDeclarations = defineRule58({
7533
+ var namingDeclarations = defineRule65({
6830
7534
  meta: {
6831
7535
  type: "problem",
6832
- schema: [
6833
- {
7536
+ schema: {
7537
+ type: "array",
7538
+ items: {
6834
7539
  type: "object",
6835
7540
  additionalProperties: false,
6836
7541
  properties: {
@@ -6841,56 +7546,61 @@ var namingDeclarations = defineRule58({
6841
7546
  allow: optionsPatternSchema
6842
7547
  }
6843
7548
  }
6844
- ],
7549
+ },
6845
7550
  messages: {
6846
7551
  prefix: "'{{name}}' must start with file prefix '{{prefix}}'.",
6847
7552
  pattern: "'{{name}}' must match {{pattern}}."
6848
7553
  }
6849
7554
  },
6850
7555
  createOnce(context) {
6851
- let options = {};
6852
- let kinds = null;
6853
- let allowed = [];
6854
- let expected = [];
6855
- let prefixes = [];
6856
- let label = "";
7556
+ let checks = [];
6857
7557
  function check(node) {
6858
7558
  const declarator = node.type === "VariableDeclarator";
6859
7559
  const kind = declarationsKindOf(node, declarator ? [node.parent] : []);
6860
7560
  const name = declarationsIdName(node);
6861
7561
  const loop = declarator ? node.parent.parent : null;
6862
7562
  const loopHeader = loop?.type === "ForStatement" ? loop.init === node.parent : (loop?.type === "ForInStatement" || loop?.type === "ForOfStatement") && loop.left === node.parent;
6863
- if (!kind || !name || loopHeader || kinds && !kinds.has(kind) || optionsPatternsTest(allowed, name)) {
7563
+ if (!kind || !name || loopHeader) {
6864
7564
  return;
6865
7565
  }
6866
- if (expected.length > 0) {
6867
- if (optionsPatternsTest(expected, name)) {
6868
- return;
7566
+ for (const { kinds, allowed, expected, prefixes, label, normalize } of checks) {
7567
+ if (kinds && !kinds.has(kind) || optionsPatternsTest(allowed, name)) {
7568
+ continue;
7569
+ }
7570
+ if (expected.length > 0) {
7571
+ if (!optionsPatternsTest(expected, name)) {
7572
+ context.report({
7573
+ node,
7574
+ messageId: "pattern",
7575
+ data: { name, pattern: label }
7576
+ });
7577
+ }
7578
+ continue;
7579
+ }
7580
+ if (!namingHasFilePrefix(name, prefixes, normalize)) {
7581
+ context.report({
7582
+ node,
7583
+ messageId: "prefix",
7584
+ data: { name, prefix: prefixes.join(" or ") }
7585
+ });
6869
7586
  }
6870
- context.report({
6871
- node,
6872
- messageId: "pattern",
6873
- data: { name, pattern: label }
6874
- });
6875
- return;
6876
- }
6877
- if (namingHasFilePrefix(name, prefixes, options.normalize)) {
6878
- return;
6879
7587
  }
6880
- context.report({
6881
- node,
6882
- messageId: "prefix",
6883
- data: { name, prefix: prefixes.join(" or ") }
6884
- });
6885
7588
  }
6886
7589
  return {
6887
7590
  before() {
6888
- options = optionsFirst(context, { stem: "before-first-dot", normalize: "remove-separators" });
6889
- kinds = options.kinds?.length ? new Set(options.kinds) : null;
6890
- allowed = optionsPatterns(options.allow);
6891
- expected = optionsPatterns(options.pattern, options.flags);
6892
- label = optionsPatternLabel(options.pattern);
6893
- prefixes = namingFilePrefixesFor(context.filename, options);
7591
+ const given = optionsAll(context);
7592
+ const captures = namingCaptures(context.filename) ?? {};
7593
+ checks = (given.length > 0 ? given : [{}]).map((options) => {
7594
+ const sources = options.pattern === undefined ? [] : [options.pattern].flat().map((source) => namingExpand(source, captures, true, optionsEscape));
7595
+ return {
7596
+ kinds: options.kinds?.length ? new Set(options.kinds) : null,
7597
+ allowed: optionsPatterns(options.allow),
7598
+ expected: optionsPatterns(sources, options.flags),
7599
+ prefixes: namingFilePrefixesFor(context.filename, options),
7600
+ label: optionsPatternLabel(sources),
7601
+ normalize: options.normalize
7602
+ };
7603
+ });
6894
7604
  },
6895
7605
  FunctionDeclaration: check,
6896
7606
  ClassDeclaration: check,
@@ -6903,33 +7613,14 @@ var namingDeclarations = defineRule58({
6903
7613
  });
6904
7614
 
6905
7615
  // src/rules/naming/naming-exports.ts
6906
- import { defineRule as defineRule59 } from "@oxlint/plugins";
7616
+ import { defineRule as defineRule66 } from "@oxlint/plugins";
6907
7617
  var namingExportsScopeProperties = {
6908
7618
  scope: { type: "string", enum: ["exports", "functions", "declarations"] },
6909
7619
  types: { type: "boolean" },
6910
7620
  services: { type: "boolean" },
6911
7621
  allow: optionsPatternSchema
6912
7622
  };
6913
- function matchTemplate(basename3, template, placeholder = "[a-z0-9-]+") {
6914
- let pattern = "";
6915
- let index = 0;
6916
- while (index < template.length) {
6917
- const char = template[index];
6918
- if (char === "{") {
6919
- const end = template.indexOf("}", index);
6920
- if (end === -1) {
6921
- return null;
6922
- }
6923
- pattern += `(?<${template.slice(index + 1, end)}>${placeholder})`;
6924
- index = end + 1;
6925
- continue;
6926
- }
6927
- pattern += /[.+^${}()|[\]\\]/.test(char) ? `\\${char}` : char;
6928
- index += 1;
6929
- }
6930
- return new RegExp(`^${pattern}$`).exec(basename3)?.groups ?? null;
6931
- }
6932
- var namingExports = defineRule59({
7623
+ var namingExports = defineRule66({
6933
7624
  meta: {
6934
7625
  type: "problem",
6935
7626
  schema: {
@@ -6959,7 +7650,7 @@ var namingExports = defineRule59({
6959
7650
  mode: { type: "string", enum: ["template"] },
6960
7651
  ...namingExportsScopeProperties,
6961
7652
  file: { type: "string" },
6962
- export: { type: "string" },
7653
+ export: optionsPatternSchema,
6963
7654
  match: { type: "string", enum: ["all", "some"] },
6964
7655
  placeholder: { type: "string" },
6965
7656
  camelCase: { type: "boolean" }
@@ -6986,23 +7677,15 @@ var namingExports = defineRule59({
6986
7677
  const allowed = optionsPatterns(options.allow);
6987
7678
  if (options.mode === "template") {
6988
7679
  const file = namingBasename(context.filename);
6989
- const groups = matchTemplate(file, options.file, options.placeholder);
6990
- if (!groups) {
7680
+ const captures2 = namingCaptures(context.filename, { file: options.file, placeholder: options.placeholder });
7681
+ if (!captures2) {
6991
7682
  continue;
6992
7683
  }
6993
- const expected2 = options.export.replaceAll(/\{([^}]+)\}/g, (placeholder, key) => {
6994
- const group = groups[key.toLowerCase()];
6995
- if (!group) {
6996
- return placeholder;
6997
- }
6998
- if (/^[A-Z]/.test(key)) {
6999
- return namingPascalCase(group);
7000
- }
7001
- return options.camelCase ? namingCamelCase(group) : group;
7002
- });
7684
+ const names2 = [options.export].flat().map((template) => namingExpand(template, captures2, options.camelCase ?? false));
7685
+ const expected2 = names2.join(" or ");
7003
7686
  const functions = (scope === "exports" ? exportsFunctions(program, true) : declarationsFunctions(program)).filter(({ name }) => !optionsPatternsTest(allowed, name));
7004
7687
  if (options.match === "some") {
7005
- if (functions.some((item) => item.name === expected2)) {
7688
+ if (functions.some((item) => names2.includes(item.name))) {
7006
7689
  continue;
7007
7690
  }
7008
7691
  const first = functions.at(0);
@@ -7014,7 +7697,7 @@ var namingExports = defineRule59({
7014
7697
  continue;
7015
7698
  }
7016
7699
  for (const item of functions) {
7017
- if (item.name !== expected2) {
7700
+ if (!names2.includes(item.name)) {
7018
7701
  context.report({
7019
7702
  node: item.node,
7020
7703
  messageId: "mismatch",
@@ -7036,7 +7719,9 @@ var namingExports = defineRule59({
7036
7719
  names.push(...declarationsPublicServiceMethods(program));
7037
7720
  }
7038
7721
  const prefixes = options.mode === "pattern" ? [] : namingFilePrefixesFor(context.filename, options);
7039
- const expected = options.mode === "pattern" ? optionsPatternsWithEmpty(options.pattern, options.flags) : [];
7722
+ const captures = namingCaptures(context.filename) ?? {};
7723
+ const sources = options.mode === "pattern" ? [options.pattern].flat().map((source) => namingExpand(source, captures, true, optionsEscape)) : [];
7724
+ const expected = optionsPatternsWithEmpty(sources, options.mode === "pattern" ? options.flags : undefined);
7040
7725
  for (const item of declarationsUnique(names)) {
7041
7726
  if (optionsPatternsTest(allowed, item.name)) {
7042
7727
  continue;
@@ -7046,7 +7731,7 @@ var namingExports = defineRule59({
7046
7731
  context.report({
7047
7732
  node: item.node,
7048
7733
  messageId: "pattern",
7049
- data: { name: item.name, pattern: optionsPatternLabel(options.pattern) }
7734
+ data: { name: item.name, pattern: optionsPatternLabel(sources) }
7050
7735
  });
7051
7736
  }
7052
7737
  continue;
@@ -7066,10 +7751,10 @@ var namingExports = defineRule59({
7066
7751
  });
7067
7752
 
7068
7753
  // src/rules/naming/naming-file.ts
7069
- import { defineRule as defineRule60 } from "@oxlint/plugins";
7754
+ import { defineRule as defineRule67 } from "@oxlint/plugins";
7070
7755
  import { readdirSync as readdirSync2 } from "node:fs";
7071
- import { dirname as dirname4 } from "node:path";
7072
- var namingFile = defineRule60({
7756
+ import { dirname as dirname5 } from "node:path";
7757
+ var namingFile = defineRule67({
7073
7758
  meta: {
7074
7759
  type: "problem",
7075
7760
  schema: {
@@ -7081,9 +7766,12 @@ var namingFile = defineRule60({
7081
7766
  pattern: optionsPatternSchema,
7082
7767
  message: { type: "string" },
7083
7768
  flags: { type: "string" },
7084
- unique: { type: "string", minLength: 1 }
7769
+ unique: { type: "string", minLength: 1 },
7770
+ template: optionsPatternSchema,
7771
+ placeholder: { type: "string" }
7085
7772
  },
7086
- required: ["pattern", "message"]
7773
+ required: ["message"],
7774
+ anyOf: [{ required: ["pattern"] }, { required: ["template"] }]
7087
7775
  }
7088
7776
  },
7089
7777
  messages: {
@@ -7096,9 +7784,12 @@ var namingFile = defineRule60({
7096
7784
  Program(program) {
7097
7785
  const basename3 = namingBasename(context.filename);
7098
7786
  let siblings;
7099
- for (const { pattern, message, flags, unique } of optionsAll(context)) {
7787
+ for (const { pattern, message, flags, unique, template, placeholder } of optionsAll(context)) {
7100
7788
  const patterns = optionsPatternsWithEmpty(pattern, flags);
7101
- if (!optionsPatternsTest(patterns, basename3)) {
7789
+ const path = context.filename.replaceAll("\\", "/").split("/");
7790
+ const templates = [template ?? []].flat();
7791
+ const fits = templates.some((item) => namingTemplatePattern(item, placeholder)?.test(path.slice(-item.split("/").length).join("/")));
7792
+ if (pattern !== undefined && !optionsPatternsTest(patterns, basename3) || templates.length > 0 && !fits) {
7102
7793
  context.report({
7103
7794
  node: program,
7104
7795
  messageId: "mismatch",
@@ -7119,7 +7810,7 @@ var namingFile = defineRule60({
7119
7810
  }
7120
7811
  if (!siblings) {
7121
7812
  try {
7122
- siblings = readdirSync2(dirname4(context.filename), { withFileTypes: true }).flatMap((entry) => entry.isFile() ? [entry.name] : []);
7813
+ siblings = readdirSync2(dirname5(context.filename), { withFileTypes: true }).flatMap((entry) => entry.isFile() ? [entry.name] : []);
7123
7814
  } catch {
7124
7815
  siblings = [];
7125
7816
  }
@@ -7139,9 +7830,9 @@ var namingFile = defineRule60({
7139
7830
  });
7140
7831
 
7141
7832
  // src/rules/naming/naming-folder.ts
7142
- import { defineRule as defineRule61 } from "@oxlint/plugins";
7143
- import { posix as posix3 } from "node:path";
7144
- var namingFolder = defineRule61({
7833
+ import { defineRule as defineRule68 } from "@oxlint/plugins";
7834
+ import { posix as posix2 } from "node:path";
7835
+ var namingFolder = defineRule68({
7145
7836
  meta: {
7146
7837
  type: "problem",
7147
7838
  schema: [
@@ -7164,7 +7855,7 @@ var namingFolder = defineRule61({
7164
7855
  return {
7165
7856
  Program(program) {
7166
7857
  const { singularize = "trailing-s", separators = ["-"], after, prefixes: stripPrefixes = [] } = optionsFirst(context, {});
7167
- const all = posix3.dirname(context.filename.replaceAll("\\", "/")).split("/").filter((part) => part && part !== ".");
7858
+ const all = posix2.dirname(context.filename.replaceAll("\\", "/")).split("/").filter((part) => part && part !== ".");
7168
7859
  const parent = [all.at(-1) ?? ""];
7169
7860
  let folders = after ? undefined : parent;
7170
7861
  const marker = (after ?? "").split("/").filter(Boolean);
@@ -7205,9 +7896,451 @@ var namingFolder = defineRule61({
7205
7896
  }
7206
7897
  });
7207
7898
 
7899
+ // src/rules/naming/naming-imports.ts
7900
+ import { defineRule as defineRule69 } from "@oxlint/plugins";
7901
+ var namingImports = defineRule69({
7902
+ meta: {
7903
+ type: "problem",
7904
+ schema: [
7905
+ {
7906
+ type: "object",
7907
+ additionalProperties: false,
7908
+ properties: {
7909
+ imports: {
7910
+ type: "array",
7911
+ items: {
7912
+ type: "object",
7913
+ additionalProperties: false,
7914
+ properties: {
7915
+ source: { type: "string" },
7916
+ name: optionsPatternSchema,
7917
+ namespace: { type: "boolean" },
7918
+ placeholder: { type: "string" }
7919
+ },
7920
+ required: ["source", "name"]
7921
+ }
7922
+ }
7923
+ },
7924
+ required: ["imports"]
7925
+ }
7926
+ ],
7927
+ messages: {
7928
+ name: "Import '{{source}}' as '{{expected}}', not '{{actual}}'.",
7929
+ namespace: "Import '{{source}}' as a namespace: import * as {{expected}}."
7930
+ }
7931
+ },
7932
+ createOnce(context) {
7933
+ let entries = [];
7934
+ return {
7935
+ before() {
7936
+ entries = optionsFirst(context, { imports: [] }).imports.flatMap((entry) => {
7937
+ const pattern = namingTemplatePattern(entry.source, entry.placeholder ?? "[^/]+");
7938
+ return pattern ? [{ pattern, names: [entry.name].flat(), namespace: entry.namespace !== false }] : [];
7939
+ });
7940
+ if (entries.length === 0) {
7941
+ return false;
7942
+ }
7943
+ },
7944
+ ImportDeclaration(node) {
7945
+ const source = node.source.value;
7946
+ for (const entry of entries) {
7947
+ const match = entry.pattern.exec(source);
7948
+ if (!match) {
7949
+ continue;
7950
+ }
7951
+ const names = entry.names.map((template) => namingExpand(template, { ...match.groups }, true));
7952
+ const expected = names.join(" or ");
7953
+ for (const specifier of node.specifiers) {
7954
+ if (specifier.type !== "ImportNamespaceSpecifier" && entry.namespace) {
7955
+ context.report({
7956
+ node: specifier,
7957
+ messageId: "namespace",
7958
+ data: { source, expected }
7959
+ });
7960
+ } else if (specifier.type !== "ImportSpecifier" && !names.includes(specifier.local.name)) {
7961
+ context.report({
7962
+ node: specifier,
7963
+ messageId: "name",
7964
+ data: { source, expected, actual: specifier.local.name }
7965
+ });
7966
+ }
7967
+ }
7968
+ return;
7969
+ }
7970
+ }
7971
+ };
7972
+ }
7973
+ });
7974
+
7975
+ // src/rules/naming/naming-keys.ts
7976
+ import { defineRule as defineRule70 } from "@oxlint/plugins";
7977
+ function namingKeysNames(value) {
7978
+ const dotted = astDottedName(value);
7979
+ return dotted === undefined ? [] : [...new Set([dotted.split(".").at(-1) ?? dotted, dotted.split(".")[0]])];
7980
+ }
7981
+ function namingKeysSingular(key, options) {
7982
+ return options.singularize === "trailing-s" && key.length > 1 && key.endsWith("s") ? [key, key.slice(0, -1)] : [key];
7983
+ }
7984
+ function namingKeysSources(options, captures, keys) {
7985
+ const last = keys.at(-1) ?? "";
7986
+ return [options.name ?? []].flat().flatMap((source) => namingKeysSingular(last, options).map((key) => {
7987
+ const values = { ...captures, path: keys.join("-"), key };
7988
+ return namingExpand(source, values, true, optionsEscape);
7989
+ }));
7990
+ }
7991
+ function namingKeysFunction(value) {
7992
+ if (astIsInlineFunction(value)) {
7993
+ return value;
7994
+ }
7995
+ return value.type === "CallExpression" ? value.arguments.find(astIsInlineFunction) ?? namingKeysFunction(value.callee) : undefined;
7996
+ }
7997
+ function namingKeysYielded(node) {
7998
+ let found;
7999
+ astSome(node, (candidate) => {
8000
+ const call = candidate.type === "YieldExpression" && candidate.delegate && candidate.argument ? astUnwrap(candidate.argument) : undefined;
8001
+ found ??= call?.type === "CallExpression" ? call : undefined;
8002
+ return found !== undefined;
8003
+ });
8004
+ return found;
8005
+ }
8006
+ function namingKeysAssigned(fn, returned) {
8007
+ let found;
8008
+ astSome(fn.body, (candidate) => {
8009
+ const local = candidate.type === "VariableDeclarator" && candidate.id.type === "Identifier" && candidate.init ? candidate.id.name : undefined;
8010
+ const used = local !== undefined && astSome(returned, (node) => node.type === "Identifier" && node.name === local);
8011
+ found ??= used && candidate.type === "VariableDeclarator" && candidate.init ? namingKeysYielded(candidate.init) : undefined;
8012
+ return found !== undefined;
8013
+ });
8014
+ return found;
8015
+ }
8016
+ function namingKeysCalled(fn) {
8017
+ const returned = astReturnExpressions(fn).at(-1);
8018
+ if (!returned) {
8019
+ return;
8020
+ }
8021
+ const plain = astUnwrap(returned);
8022
+ const direct = !fn.generator && plain.type === "CallExpression" ? plain : undefined;
8023
+ const call = namingKeysYielded(returned) ?? namingKeysAssigned(fn, returned) ?? direct;
8024
+ return call ? astDottedName(call.callee) : undefined;
8025
+ }
8026
+ var namingKeys = defineRule70({
8027
+ meta: {
8028
+ type: "problem",
8029
+ schema: [
8030
+ {
8031
+ type: "object",
8032
+ additionalProperties: false,
8033
+ properties: {
8034
+ callees: { type: "array", items: { type: "string" }, minItems: 1 },
8035
+ exports: optionsPatternSchema,
8036
+ name: optionsPatternSchema,
8037
+ keys: optionsPatternSchema,
8038
+ inline: { type: "boolean" },
8039
+ delegate: { type: "boolean" },
8040
+ allow: optionsPatternSchema,
8041
+ singularize: { type: "string", enum: ["none", "trailing-s"] }
8042
+ },
8043
+ anyOf: [{ required: ["callees"] }, { required: ["exports"] }]
8044
+ }
8045
+ ],
8046
+ messages: {
8047
+ name: "'{{name}}' under key '{{path}}' must match {{pattern}}.",
8048
+ key: "Key '{{key}}' in '{{path}}' must match {{pattern}}.",
8049
+ inline: "Bind a named function under '{{path}}', not an inline one.",
8050
+ delegate: "'{{path}}' must return a call to '{{path}}' on its service, not '{{called}}'."
8051
+ }
8052
+ },
8053
+ createOnce(context) {
8054
+ let options = {};
8055
+ let captures = {};
8056
+ let callees = [];
8057
+ let exported = [];
8058
+ let allowed = [];
8059
+ let keyPatterns = [];
8060
+ function checkValue(value, keys) {
8061
+ const path = keys.join(".");
8062
+ const fn = namingKeysFunction(value);
8063
+ const names = namingKeysNames(value);
8064
+ const sources = namingKeysSources(options, captures, keys);
8065
+ const called = options.delegate && fn ? namingKeysCalled(fn) : undefined;
8066
+ if (fn && astIsInlineFunction(value) && options.inline === false) {
8067
+ context.report({
8068
+ node: value,
8069
+ messageId: "inline",
8070
+ data: { path }
8071
+ });
8072
+ }
8073
+ if (called !== undefined && called.split(".").slice(1).join(".") !== path) {
8074
+ context.report({
8075
+ node: value,
8076
+ messageId: "delegate",
8077
+ data: { path, called }
8078
+ });
8079
+ }
8080
+ if (sources.length > 0 && names.length > 0 && !names.some((name) => optionsPatternsTest(optionsPatterns(sources), name))) {
8081
+ context.report({
8082
+ node: value,
8083
+ messageId: "name",
8084
+ data: { name: names[0], path, pattern: optionsPatternLabel(sources) }
8085
+ });
8086
+ }
8087
+ }
8088
+ function check(object, path) {
8089
+ for (const property of object.properties) {
8090
+ const key = declarationsPropertyName(property);
8091
+ const keys = key === undefined ? path : [...path, key];
8092
+ if (property.type !== "Property" || key === undefined || optionsPatternsTest(allowed, keys.join("."))) {
8093
+ continue;
8094
+ }
8095
+ if (keyPatterns.length > 0 && !optionsPatternsTest(keyPatterns, key)) {
8096
+ context.report({
8097
+ node: property.key,
8098
+ messageId: "key",
8099
+ data: { key, path: keys.join("."), pattern: optionsPatternLabel(options.keys) }
8100
+ });
8101
+ }
8102
+ if (property.value.type === "ObjectExpression") {
8103
+ check(property.value, keys);
8104
+ } else {
8105
+ checkValue(property.value, keys);
8106
+ }
8107
+ }
8108
+ }
8109
+ return {
8110
+ before() {
8111
+ options = optionsFirst(context, {});
8112
+ captures = namingCaptures(context.filename) ?? {};
8113
+ callees = optionsWildcards(options.callees);
8114
+ exported = optionsPatterns(options.exports);
8115
+ allowed = optionsPatterns(options.allow);
8116
+ keyPatterns = optionsPatterns(options.keys);
8117
+ if (callees.length === 0 && exported.length === 0) {
8118
+ return false;
8119
+ }
8120
+ },
8121
+ CallExpression(node) {
8122
+ const first = node.arguments.at(0);
8123
+ if (first?.type === "ObjectExpression" && optionsPatternsTest(callees, astDottedName(node.callee) ?? "")) {
8124
+ check(first, []);
8125
+ }
8126
+ },
8127
+ VariableDeclarator(node) {
8128
+ const statement = node.parent.parent;
8129
+ const top = statement?.type === "ExportNamedDeclaration" && statement.parent.type === "Program";
8130
+ const value = node.init ? astUnwrap(node.init) : null;
8131
+ if (top && node.id.type === "Identifier" && value?.type === "ObjectExpression" && optionsPatternsTest(exported, node.id.name)) {
8132
+ check(value, []);
8133
+ }
8134
+ }
8135
+ };
8136
+ }
8137
+ });
8138
+
8139
+ // src/rules/naming/naming-labels.ts
8140
+ import { defineRule as defineRule71 } from "@oxlint/plugins";
8141
+ function namingLabelsRoot(node) {
8142
+ return node.type === "CallExpression" ? namingLabelsRoot(node.callee) : astDottedName(node);
8143
+ }
8144
+ function namingLabelsBinding(node, within) {
8145
+ const parent = node.parent;
8146
+ if (!parent) {
8147
+ return;
8148
+ }
8149
+ if (parent.type === "VariableDeclarator" && parent.init === node) {
8150
+ return parent.id.type === "Identifier" ? parent.id.name : undefined;
8151
+ }
8152
+ if ((parent.type === "ClassDeclaration" || parent.type === "ClassExpression") && parent.superClass === node) {
8153
+ return parent.id?.name;
8154
+ }
8155
+ if (parent.type === "CallExpression" && parent.callee === node || parent.type === "MemberExpression" && parent.object === node) {
8156
+ return namingLabelsBinding(parent, within);
8157
+ }
8158
+ const owner = parent.type === "CallExpression" && parent.callee.type === "MemberExpression" ? astDottedName(parent.callee) : undefined;
8159
+ return owner !== undefined && optionsPatternsTest(within, owner) ? owner.split(".").at(-2) : undefined;
8160
+ }
8161
+ function namingLabelsTarget(first, property) {
8162
+ if (property === undefined) {
8163
+ return first;
8164
+ }
8165
+ const held = first.type === "ObjectExpression" ? first.properties.find((item) => declarationsPropertyName(item) === property) : undefined;
8166
+ return held?.type === "Property" ? held.value : undefined;
8167
+ }
8168
+ function namingLabelsPlain(text, loose) {
8169
+ return loose ? text.replaceAll(/[._\-/\s]/g, "").toLowerCase() : text;
8170
+ }
8171
+ function namingLabelsExpected({ entry, drop }, captures, binding) {
8172
+ const name = drop.reduce((text, pattern) => text.replace(pattern, ""), binding);
8173
+ return [entry.name ?? []].flat().map((template) => namingExpand(template, { ...captures, name }, false));
8174
+ }
8175
+ var namingLabels = defineRule71({
8176
+ meta: {
8177
+ type: "problem",
8178
+ schema: [
8179
+ {
8180
+ type: "object",
8181
+ additionalProperties: false,
8182
+ properties: {
8183
+ labels: {
8184
+ type: "array",
8185
+ items: {
8186
+ type: "object",
8187
+ additionalProperties: false,
8188
+ properties: {
8189
+ callee: optionsPatternSchema,
8190
+ property: { type: "string" },
8191
+ name: optionsPatternSchema,
8192
+ pattern: optionsPatternSchema,
8193
+ drop: optionsPatternSchema,
8194
+ loose: { type: "boolean" },
8195
+ within: optionsPatternSchema
8196
+ },
8197
+ required: ["callee"],
8198
+ anyOf: [{ required: ["name"] }, { required: ["pattern"] }]
8199
+ }
8200
+ }
8201
+ },
8202
+ required: ["labels"]
8203
+ }
8204
+ ],
8205
+ messages: {
8206
+ name: "'{{label}}' must be '{{expected}}', after the name '{{name}}'.",
8207
+ pattern: "'{{label}}' must match {{pattern}}."
8208
+ }
8209
+ },
8210
+ createOnce(context) {
8211
+ let entries = [];
8212
+ let captures = {};
8213
+ return {
8214
+ before() {
8215
+ const paths = namingCaptures(context.filename) ?? {};
8216
+ captures = paths;
8217
+ entries = optionsFirst(context, { labels: [] }).labels.map((entry) => ({
8218
+ callees: optionsWildcards(entry.callee),
8219
+ entry,
8220
+ drop: optionsPatterns(entry.drop),
8221
+ within: optionsWildcards(entry.within),
8222
+ patterns: [entry.pattern ?? []].flat().map((source) => namingExpand(source, paths, true, optionsEscape))
8223
+ }));
8224
+ if (entries.length === 0) {
8225
+ return false;
8226
+ }
8227
+ },
8228
+ CallExpression(node) {
8229
+ const root = namingLabelsRoot(node.callee);
8230
+ const first = node.arguments.at(0);
8231
+ if (root === undefined || !first) {
8232
+ return;
8233
+ }
8234
+ for (const compiled of entries) {
8235
+ const target = optionsPatternsTest(compiled.callees, root) ? namingLabelsTarget(first, compiled.entry.property) : undefined;
8236
+ const label = target ? astStaticString(target) : undefined;
8237
+ if (!target || label === undefined) {
8238
+ continue;
8239
+ }
8240
+ if (compiled.patterns.length > 0 && !optionsPatternsTest(optionsPatterns(compiled.patterns), label)) {
8241
+ context.report({
8242
+ node: target,
8243
+ messageId: "pattern",
8244
+ data: { label, pattern: optionsPatternLabel(compiled.patterns) }
8245
+ });
8246
+ }
8247
+ const binding = namingLabelsBinding(node, compiled.within);
8248
+ const expected = binding === undefined ? [] : namingLabelsExpected(compiled, captures, binding);
8249
+ const plain = expected.map((item) => namingLabelsPlain(item, compiled.entry.loose));
8250
+ if (binding !== undefined && expected.length > 0 && !plain.includes(namingLabelsPlain(label, compiled.entry.loose))) {
8251
+ context.report({
8252
+ node: target,
8253
+ messageId: "name",
8254
+ data: { label, expected: expected.join(" or "), name: binding }
8255
+ });
8256
+ }
8257
+ }
8258
+ }
8259
+ };
8260
+ }
8261
+ });
8262
+
8263
+ // src/rules/naming/naming-pairs.ts
8264
+ import { defineRule as defineRule72 } from "@oxlint/plugins";
8265
+ function namingPairsArguments(node, found) {
8266
+ if (node.type === "MemberExpression") {
8267
+ return namingPairsArguments(node.object, found);
8268
+ }
8269
+ if (node.type !== "CallExpression") {
8270
+ return found;
8271
+ }
8272
+ const method = node.callee.type === "MemberExpression" ? astMemberName(node.callee) : undefined;
8273
+ const first = node.arguments.at(0);
8274
+ if (method !== undefined && first && !found.has(method)) {
8275
+ found.set(method, first);
8276
+ }
8277
+ return namingPairsArguments(node.callee, found);
8278
+ }
8279
+ var namingPairs = defineRule72({
8280
+ meta: {
8281
+ type: "problem",
8282
+ schema: [
8283
+ {
8284
+ type: "object",
8285
+ additionalProperties: false,
8286
+ properties: {
8287
+ pairs: {
8288
+ type: "array",
8289
+ items: {
8290
+ type: "object",
8291
+ additionalProperties: false,
8292
+ properties: {
8293
+ methods: { type: "array", items: { type: "string" }, minItems: 2, maxItems: 2 },
8294
+ strip: optionsPatternSchema,
8295
+ allow: optionsPatternSchema
8296
+ },
8297
+ required: ["methods"]
8298
+ }
8299
+ }
8300
+ },
8301
+ required: ["pairs"]
8302
+ }
8303
+ ],
8304
+ messages: {
8305
+ pair: "'{{second}}' in .{{secondMethod}}() must share its name with '{{first}}' in .{{firstMethod}}()."
8306
+ }
8307
+ },
8308
+ createOnce(context) {
8309
+ return {
8310
+ CallExpression(node) {
8311
+ const parent = node.parent;
8312
+ const chained = parent.type === "MemberExpression" && parent.object === node || parent.type === "CallExpression" && parent.callee === node;
8313
+ const { pairs } = optionsFirst(context, { pairs: [] });
8314
+ if (chained || pairs.length === 0) {
8315
+ return;
8316
+ }
8317
+ const found = namingPairsArguments(node, new Map);
8318
+ for (const { methods: [firstMethod, secondMethod], strip, allow } of pairs) {
8319
+ const firstNode = found.get(firstMethod);
8320
+ const secondNode = found.get(secondMethod);
8321
+ const first = firstNode ? astDottedName(firstNode)?.split(".").at(-1) : undefined;
8322
+ const second = secondNode ? astDottedName(secondNode)?.split(".").at(-1) : undefined;
8323
+ const skipped = optionsPatterns(allow);
8324
+ const stem = (name) => optionsPatterns(strip).reduce((text, pattern) => text.replace(pattern, ""), name);
8325
+ if (!secondNode || first === undefined || second === undefined || optionsPatternsTest(skipped, first) || optionsPatternsTest(skipped, second)) {
8326
+ continue;
8327
+ }
8328
+ if (stem(first) !== stem(second)) {
8329
+ context.report({
8330
+ node: secondNode,
8331
+ messageId: "pair",
8332
+ data: { first, second, firstMethod, secondMethod }
8333
+ });
8334
+ }
8335
+ }
8336
+ }
8337
+ };
8338
+ }
8339
+ });
8340
+
7208
8341
  // src/rules/naming/naming-types.ts
7209
- import { defineRule as defineRule62 } from "@oxlint/plugins";
7210
- var namingTypes = defineRule62({
8342
+ import { defineRule as defineRule73 } from "@oxlint/plugins";
8343
+ var namingTypes = defineRule73({
7211
8344
  meta: {
7212
8345
  type: "problem",
7213
8346
  schema: [{ type: "object", additionalProperties: false, properties: { pattern: optionsPatternSchema, message: { type: "string" } } }],
@@ -7236,8 +8369,8 @@ var namingTypes = defineRule62({
7236
8369
  });
7237
8370
 
7238
8371
  // src/rules/react/react-dynamic-classes.ts
7239
- import { defineRule as defineRule63 } from "@oxlint/plugins";
7240
- var reactDynamicClasses = defineRule63({
8372
+ import { defineRule as defineRule74 } from "@oxlint/plugins";
8373
+ var reactDynamicClasses = defineRule74({
7241
8374
  meta: {
7242
8375
  type: "problem",
7243
8376
  schema: [
@@ -7277,8 +8410,8 @@ var reactDynamicClasses = defineRule63({
7277
8410
  });
7278
8411
 
7279
8412
  // src/rules/react/react-empty-effect.ts
7280
- import { defineRule as defineRule64 } from "@oxlint/plugins";
7281
- var reactEmptyEffect = defineRule64({
8413
+ import { defineRule as defineRule75 } from "@oxlint/plugins";
8414
+ var reactEmptyEffect = defineRule75({
7282
8415
  meta: {
7283
8416
  type: "problem",
7284
8417
  schema: [
@@ -7318,8 +8451,8 @@ var reactEmptyEffect = defineRule64({
7318
8451
  });
7319
8452
 
7320
8453
  // src/rules/react/react-memo.ts
7321
- import { defineRule as defineRule65 } from "@oxlint/plugins";
7322
- var reactMemo = defineRule65({
8454
+ import { defineRule as defineRule76 } from "@oxlint/plugins";
8455
+ var reactMemo = defineRule76({
7323
8456
  meta: {
7324
8457
  type: "problem",
7325
8458
  schema: [
@@ -7381,7 +8514,7 @@ var reactMemo = defineRule65({
7381
8514
  });
7382
8515
 
7383
8516
  // src/rules/react/react-props.ts
7384
- import { defineRule as defineRule66 } from "@oxlint/plugins";
8517
+ import { defineRule as defineRule77 } from "@oxlint/plugins";
7385
8518
  function reactPropsTarget(node) {
7386
8519
  if (node?.type === "FunctionDeclaration" || node?.type === "FunctionExpression" || node?.type === "ArrowFunctionExpression") {
7387
8520
  return { fn: node };
@@ -7408,7 +8541,7 @@ function reactIsPassThrough(type) {
7408
8541
  const argument = type.typeArguments?.params.length === 1 ? type.typeArguments.params[0] : undefined;
7409
8542
  return name.type === "Identifier" && name.name === "ComponentProps" && (argument?.type === "TSTypeQuery" || argument?.type === "TSLiteralType" && argument.literal.type === "Literal" && typeof argument.literal.value === "string");
7410
8543
  }
7411
- var reactProps = defineRule66({
8544
+ var reactProps = defineRule77({
7412
8545
  meta: {
7413
8546
  type: "problem",
7414
8547
  schema: [
@@ -7507,8 +8640,8 @@ var reactProps = defineRule66({
7507
8640
  });
7508
8641
 
7509
8642
  // src/rules/react/react-query-props.ts
7510
- import { defineRule as defineRule67 } from "@oxlint/plugins";
7511
- var reactQueryProps = defineRule67({
8643
+ import { defineRule as defineRule78 } from "@oxlint/plugins";
8644
+ var reactQueryProps = defineRule78({
7512
8645
  meta: {
7513
8646
  type: "problem",
7514
8647
  schema: [
@@ -7589,7 +8722,7 @@ var reactQueryProps = defineRule67({
7589
8722
  });
7590
8723
 
7591
8724
  // src/rules/schemas/schemas-inline.ts
7592
- import { defineRule as defineRule68 } from "@oxlint/plugins";
8725
+ import { defineRule as defineRule79 } from "@oxlint/plugins";
7593
8726
 
7594
8727
  // src/utils/schemas.utils.ts
7595
8728
  var schemasElementOptionsSchema = {
@@ -7625,7 +8758,7 @@ function schemasIsAllowedElement(node, allowScalars, namespaces, structuralMetho
7625
8758
  }
7626
8759
 
7627
8760
  // src/rules/schemas/schemas-inline.ts
7628
- var schemasInline = defineRule68({
8761
+ var schemasInline = defineRule79({
7629
8762
  meta: {
7630
8763
  type: "problem",
7631
8764
  schema: [schemasElementOptionsSchema],
@@ -7674,11 +8807,11 @@ var schemasInline = defineRule68({
7674
8807
  });
7675
8808
 
7676
8809
  // src/rules/schemas/schemas-local.ts
7677
- import { defineRule as defineRule69 } from "@oxlint/plugins";
8810
+ import { defineRule as defineRule80 } from "@oxlint/plugins";
7678
8811
  var schemasLocalImportMessage = "Do not import runtime schema constructors from {{source}}; import a named schema instead.";
7679
8812
  var schemasLocalConstructionMessage = "Do not construct schemas locally; import a named schema instead.";
7680
8813
  var schemasLocalCalls = ["config", "prettifyError", "treeifyError", "flattenError", "formatError"];
7681
- var schemasLocal = defineRule69({
8814
+ var schemasLocal = defineRule80({
7682
8815
  meta: {
7683
8816
  type: "problem",
7684
8817
  schema: [
@@ -7827,8 +8960,8 @@ var schemasLocal = defineRule69({
7827
8960
  });
7828
8961
 
7829
8962
  // src/rules/schemas/schemas-rederive.ts
7830
- import { defineRule as defineRule70 } from "@oxlint/plugins";
7831
- var schemasRederive = defineRule70({
8963
+ import { defineRule as defineRule81 } from "@oxlint/plugins";
8964
+ var schemasRederive = defineRule81({
7832
8965
  meta: {
7833
8966
  type: "problem",
7834
8967
  schema: [
@@ -7874,7 +9007,7 @@ var schemasRederive = defineRule70({
7874
9007
  });
7875
9008
 
7876
9009
  // src/rules/schemas/schemas-single-use.ts
7877
- import { defineRule as defineRule71 } from "@oxlint/plugins";
9010
+ import { defineRule as defineRule82 } from "@oxlint/plugins";
7878
9011
  function isScalarSchema(node, namespaces, structuralMethods) {
7879
9012
  if (node.type !== "CallExpression" || node.callee.type !== "MemberExpression") {
7880
9013
  return false;
@@ -7888,7 +9021,7 @@ function isScalarSchema(node, namespaces, structuralMethods) {
7888
9021
  }
7889
9022
  return node.callee.object.type === "CallExpression" && isScalarSchema(node.callee.object, namespaces, structuralMethods);
7890
9023
  }
7891
- var schemasSingleUse = defineRule71({
9024
+ var schemasSingleUse = defineRule82({
7892
9025
  meta: {
7893
9026
  type: "suggestion",
7894
9027
  schema: [schemasElementOptionsSchema],
@@ -7964,7 +9097,7 @@ var schemasSingleUse = defineRule71({
7964
9097
  });
7965
9098
 
7966
9099
  // src/rules/tests/tests-assertions.ts
7967
- import { defineRule as defineRule72 } from "@oxlint/plugins";
9100
+ import { defineRule as defineRule83 } from "@oxlint/plugins";
7968
9101
  var testsAssertionsModifiers = new Set(["for", "each", "concurrent", "sequential", "only", "skip"]);
7969
9102
  var testsAssertionsFunctions = [
7970
9103
  "expect",
@@ -8154,7 +9287,7 @@ function isAssertedTest(registration, sourceCode, state) {
8154
9287
  }
8155
9288
  return rows.length > 0 && rows.every((row) => hasAssertion(callback, row.bindings, new Set, state));
8156
9289
  }
8157
- var testsAssertions = defineRule72({
9290
+ var testsAssertions = defineRule83({
8158
9291
  meta: {
8159
9292
  type: "problem",
8160
9293
  schema: [
@@ -8280,8 +9413,8 @@ var testsAssertions = defineRule72({
8280
9413
  });
8281
9414
 
8282
9415
  // src/rules/tests/tests-concurrent-db.ts
8283
- import { defineRule as defineRule73 } from "@oxlint/plugins";
8284
- var testsConcurrentDb = defineRule73({
9416
+ import { defineRule as defineRule84 } from "@oxlint/plugins";
9417
+ var testsConcurrentDb = defineRule84({
8285
9418
  meta: {
8286
9419
  type: "problem",
8287
9420
  schema: [
@@ -8337,7 +9470,7 @@ var testsConcurrentDb = defineRule73({
8337
9470
  });
8338
9471
 
8339
9472
  // src/rules/tests/tests-modifiers.ts
8340
- import { defineRule as defineRule74 } from "@oxlint/plugins";
9473
+ import { defineRule as defineRule85 } from "@oxlint/plugins";
8341
9474
  var testsModifiersNames = ["test", "it", "describe", "suite"];
8342
9475
  var testsModifiersPackages = new Set(["vitest", "bun:test", "@playwright/test", "@jest/globals"]);
8343
9476
  var testsModifiersBanned = ["only", "skip", "todo"];
@@ -8356,7 +9489,7 @@ function modifierName(node) {
8356
9489
  const property = astMemberName(node);
8357
9490
  return object && property ? `${object}.${property}` : undefined;
8358
9491
  }
8359
- var testsModifiers = defineRule74({
9492
+ var testsModifiers = defineRule85({
8360
9493
  meta: {
8361
9494
  type: "problem",
8362
9495
  schema: [
@@ -8410,9 +9543,9 @@ var testsModifiers = defineRule74({
8410
9543
  });
8411
9544
 
8412
9545
  // src/rules/tests/tests-titles.ts
8413
- import { defineRule as defineRule75 } from "@oxlint/plugins";
9546
+ import { defineRule as defineRule86 } from "@oxlint/plugins";
8414
9547
  var testsTitlesModifiers = ["only", "skip", "concurrent", "sequential", "todo", "each", "for"];
8415
- var testsTitles = defineRule75({
9548
+ var testsTitles = defineRule86({
8416
9549
  meta: {
8417
9550
  type: "suggestion",
8418
9551
  schema: [
@@ -8490,11 +9623,11 @@ var testsTitles = defineRule75({
8490
9623
  });
8491
9624
 
8492
9625
  // src/rules/types/types-declarations.ts
8493
- import { defineRule as defineRule76 } from "@oxlint/plugins";
9626
+ import { defineRule as defineRule87 } from "@oxlint/plugins";
8494
9627
  function isValuePattern(source) {
8495
9628
  return /^\^?=/.test(source);
8496
9629
  }
8497
- var typesDeclarations = defineRule76({
9630
+ var typesDeclarations = defineRule87({
8498
9631
  meta: {
8499
9632
  type: "problem",
8500
9633
  schema: [
@@ -8545,8 +9678,8 @@ var typesDeclarations = defineRule76({
8545
9678
  });
8546
9679
 
8547
9680
  // src/rules/types/types-duplicate.ts
8548
- import { defineRule as defineRule77 } from "@oxlint/plugins";
8549
- var typesDuplicate = defineRule77({
9681
+ import { defineRule as defineRule88 } from "@oxlint/plugins";
9682
+ var typesDuplicate = defineRule88({
8550
9683
  meta: {
8551
9684
  type: "suggestion",
8552
9685
  schema: [
@@ -8610,7 +9743,7 @@ var typesDuplicate = defineRule77({
8610
9743
  });
8611
9744
 
8612
9745
  // src/rules/types/types-imported-alias.ts
8613
- import { defineRule as defineRule78 } from "@oxlint/plugins";
9746
+ import { defineRule as defineRule89 } from "@oxlint/plugins";
8614
9747
  function importedAliasTarget(declaration, imports) {
8615
9748
  if (declaration?.type !== "TSTypeAliasDeclaration") {
8616
9749
  return;
@@ -8622,7 +9755,7 @@ function importedAliasTarget(declaration, imports) {
8622
9755
  const { name } = type.typeName;
8623
9756
  return imports.has(name) && !declaration.typeParameters?.params.some((parameter) => parameter.name.name === name) ? name : undefined;
8624
9757
  }
8625
- var typesImportedAlias = defineRule78({
9758
+ var typesImportedAlias = defineRule89({
8626
9759
  meta: {
8627
9760
  type: "problem",
8628
9761
  schema: [],
@@ -8684,7 +9817,7 @@ var typesImportedAlias = defineRule78({
8684
9817
  });
8685
9818
 
8686
9819
  // src/rules/types/types-inline.ts
8687
- import { defineRule as defineRule79 } from "@oxlint/plugins";
9820
+ import { defineRule as defineRule90 } from "@oxlint/plugins";
8688
9821
  function parameterAnnotation(parameter) {
8689
9822
  if (parameter.type === "TSParameterProperty") {
8690
9823
  return parameterAnnotation(parameter.parameter);
@@ -8694,7 +9827,7 @@ function parameterAnnotation(parameter) {
8694
9827
  }
8695
9828
  return parameter.typeAnnotation;
8696
9829
  }
8697
- var typesInline = defineRule79({
9830
+ var typesInline = defineRule90({
8698
9831
  meta: {
8699
9832
  type: "problem",
8700
9833
  schema: [
@@ -8806,8 +9939,8 @@ var typesInline = defineRule79({
8806
9939
  });
8807
9940
 
8808
9941
  // src/rules/types/types-local-alias.ts
8809
- import { defineRule as defineRule80 } from "@oxlint/plugins";
8810
- var typesLocalAlias = defineRule80({
9942
+ import { defineRule as defineRule91 } from "@oxlint/plugins";
9943
+ var typesLocalAlias = defineRule91({
8811
9944
  meta: {
8812
9945
  type: "problem",
8813
9946
  schema: [{ type: "object", additionalProperties: false, properties: { allow: optionsPatternSchema, message: { type: "string" } } }],
@@ -8836,8 +9969,8 @@ var typesLocalAlias = defineRule80({
8836
9969
  });
8837
9970
 
8838
9971
  // src/rules/types/types-namespace-import.ts
8839
- import { defineRule as defineRule81 } from "@oxlint/plugins";
8840
- var typesNamespaceImport = defineRule81({
9972
+ import { defineRule as defineRule92 } from "@oxlint/plugins";
9973
+ var typesNamespaceImport = defineRule92({
8841
9974
  meta: {
8842
9975
  type: "suggestion",
8843
9976
  schema: [
@@ -8879,8 +10012,8 @@ var typesNamespaceImport = defineRule81({
8879
10012
  });
8880
10013
 
8881
10014
  // src/rules/types/types-service.ts
8882
- import { defineRule as defineRule82 } from "@oxlint/plugins";
8883
- var typesService = defineRule82({
10015
+ import { defineRule as defineRule93 } from "@oxlint/plugins";
10016
+ var typesService = defineRule93({
8884
10017
  meta: {
8885
10018
  type: "problem",
8886
10019
  schema: [
@@ -8930,12 +10063,12 @@ var typesService = defineRule82({
8930
10063
  });
8931
10064
 
8932
10065
  // src/rules/types/types-unknown.ts
8933
- import { defineRule as defineRule83 } from "@oxlint/plugins";
10066
+ import { defineRule as defineRule94 } from "@oxlint/plugins";
8934
10067
  function isCatchName(node) {
8935
10068
  const key = "key" in node && !(("computed" in node) && node.computed) ? node.key : undefined;
8936
10069
  return key?.type === "Identifier" && key.name === "catch";
8937
10070
  }
8938
- var typesUnknown = defineRule83({
10071
+ var typesUnknown = defineRule94({
8939
10072
  meta: { type: "problem", schema: [], messages: { forbidden: "Use an owned domain type rather than unknown." } },
8940
10073
  createOnce(context) {
8941
10074
  return {
@@ -8978,6 +10111,7 @@ var src_default = eslintCompatPlugin({
8978
10111
  "code-double-negation": codeDoubleNegation,
8979
10112
  "code-function-nesting": codeFunctionNesting,
8980
10113
  "code-inline": codeInline,
10114
+ "code-inside": codeInside,
8981
10115
  "code-justified-call": codeJustifiedCall,
8982
10116
  "code-literal-in": codeLiteralIn,
8983
10117
  "code-mutable-state": codeMutableState,
@@ -8992,10 +10126,14 @@ var src_default = eslintCompatPlugin({
8992
10126
  "comments-directives": commentsDirectives,
8993
10127
  "copy-dashes": copyDashes,
8994
10128
  "effect-layer-file": effectLayerFile,
10129
+ "effect-layer-keys": effectLayerKeys,
8995
10130
  "effect-layers": effectLayers,
8996
10131
  "effect-merge-pipe": effectMergePipe,
8997
10132
  "effect-schema-first": effectSchemaFirst,
10133
+ "effect-service-params": effectServiceParams,
8998
10134
  "effect-values-first": effectValuesFirst,
10135
+ "effect-yield-name": effectYieldName,
10136
+ "effect-yields-first": effectYieldsFirst,
8999
10137
  "files-components-only": filesComponentsOnly,
9000
10138
  "files-constants-only": filesConstantsOnly,
9001
10139
  "files-domain-constants": filesDomainConstants,
@@ -9006,6 +10144,8 @@ var src_default = eslintCompatPlugin({
9006
10144
  "files-no-functions": filesNoFunctions,
9007
10145
  "files-restricted": filesRestricted,
9008
10146
  "files-route": filesRoute,
10147
+ "files-siblings": filesSiblings,
10148
+ "files-top-level": filesTopLevel,
9009
10149
  "files-types-only": filesTypesOnly,
9010
10150
  "layout-arrow-body": layoutArrowBody,
9011
10151
  "layout-call-arguments": layoutCallArguments,
@@ -9024,6 +10164,10 @@ var src_default = eslintCompatPlugin({
9024
10164
  "naming-exports": namingExports,
9025
10165
  "naming-file": namingFile,
9026
10166
  "naming-folder": namingFolder,
10167
+ "naming-imports": namingImports,
10168
+ "naming-keys": namingKeys,
10169
+ "naming-labels": namingLabels,
10170
+ "naming-pairs": namingPairs,
9027
10171
  "naming-types": namingTypes,
9028
10172
  "react-dynamic-classes": reactDynamicClasses,
9029
10173
  "react-empty-effect": reactEmptyEffect,