oxlint-plugin-arch 0.12.5 → 0.12.6

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
@@ -1,3 +1,6 @@
1
+ import { createRequire } from "node:module";
2
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
+
1
4
  // src/index.ts
2
5
  import { eslintCompatPlugin } from "@oxlint/plugins";
3
6
 
@@ -3358,9 +3361,684 @@ var copyDashes = defineRule27({
3358
3361
  }
3359
3362
  });
3360
3363
 
3361
- // src/rules/files/files-components-only.ts
3364
+ // src/rules/effect/effect-layer-file.ts
3362
3365
  import { defineRule as defineRule28 } from "@oxlint/plugins";
3363
3366
 
3367
+ // src/utils/effect.utils.ts
3368
+ var effectBuilders = ["Effect.gen", "Effect.fn", "Effect.fnUntraced"];
3369
+ function effectIsBuilder(node, builders) {
3370
+ const value = node ? astUnwrap(node) : undefined;
3371
+ if (value?.type !== "CallExpression") {
3372
+ return false;
3373
+ }
3374
+ const callee = value.callee.type === "CallExpression" ? value.callee.callee : value.callee;
3375
+ return builders.has(astDottedName(callee) ?? "");
3376
+ }
3377
+ function effectGenerator(node, builders) {
3378
+ const value = node ? astUnwrap(node) : undefined;
3379
+ return effectIsBuilder(value, builders) ? value.arguments.find((argument) => argument.type === "FunctionExpression") : undefined;
3380
+ }
3381
+ function effectMatches(node, patterns) {
3382
+ if (!node || node.type === "Super") {
3383
+ return false;
3384
+ }
3385
+ const value = astUnwrap(node);
3386
+ const target = value.type === "CallExpression" ? value.callee : value;
3387
+ const name = astDottedName(target);
3388
+ if (name !== undefined && optionsPatternsTest(patterns, name)) {
3389
+ return true;
3390
+ }
3391
+ return value.type === "CallExpression" && target.type === "MemberExpression" && astMemberName(target) === "pipe" && effectMatches(target.object, patterns);
3392
+ }
3393
+
3394
+ // src/rules/effect/effect-layer-file.ts
3395
+ var effectLayerFileDefaultLayers = ["^Layer\\.", "^HttpRouter\\.add(?:All)?$", "(?:^|\\.)layer[^.]*$"];
3396
+ var effectLayerFileDefaultServices = ["(?:^|\\.)of$", "^Context\\."];
3397
+ var effectLayerFileDefaultConstructors = [
3398
+ "Layer.effect",
3399
+ "Layer.effectContext",
3400
+ "Layer.effectDiscard",
3401
+ "Layer.scoped",
3402
+ "Layer.scopedContext",
3403
+ "Layer.scopedDiscard",
3404
+ "Layer.sync",
3405
+ "Layer.unwrap"
3406
+ ];
3407
+ var effectLayerFile = defineRule28({
3408
+ meta: {
3409
+ type: "problem",
3410
+ schema: [
3411
+ {
3412
+ type: "object",
3413
+ additionalProperties: false,
3414
+ properties: {
3415
+ layer: { type: "string" },
3416
+ make: { type: "string" },
3417
+ prefix: { type: "string" },
3418
+ builders: { type: "array", items: { type: "string" } },
3419
+ layers: optionsPatternSchema,
3420
+ services: optionsPatternSchema,
3421
+ constructors: { type: "array", items: { type: "string" } }
3422
+ }
3423
+ }
3424
+ ],
3425
+ messages: {
3426
+ missing: "A layer file exports `{{layer}}`.",
3427
+ notLayer: "`{{layer}}` is built with Layer: a Layer call, a Layer pipe, or a function returning one.",
3428
+ builderName: "The Effect that builds the service is named `{{make}}`, one per layer file.",
3429
+ moduleMethod: "Only `{{make}}` is an Effect at module level; move this into `{{make}}`, or into a utils file if two files use it.",
3430
+ moduleHelper: "A layer file holds only `{{make}}`, {{prefix}}<Role> layers and `{{layer}}`; move this into `{{make}}`, or into a utils file if two files use it.",
3431
+ localLayer: "A Layer other than `{{layer}}` is named {{prefix}}<Role> and is not exported.",
3432
+ makeReturn: "`{{make}}` returns the service through its tag (Tag.of({ … })), a Context, or a Layer.",
3433
+ inlineBuilder: "Build this layer from `{{make}}`, not an inline Effect: Layer.effect(Tag, {{make}}). One built layer per file."
3434
+ }
3435
+ },
3436
+ createOnce(context) {
3437
+ let layer = "layer";
3438
+ let make = "make";
3439
+ let prefix = "layer";
3440
+ let builders = new Set(effectBuilders);
3441
+ let layers = [];
3442
+ let services = [];
3443
+ let constructors = new Set(effectLayerFileDefaultConstructors);
3444
+ const returned = (node) => {
3445
+ const value = node ? astUnwrap(node) : node;
3446
+ if (!value || !astIsInlineFunction(value)) {
3447
+ return value;
3448
+ }
3449
+ return value.body?.type === "BlockStatement" ? returned(value.body.body.findLast((statement) => statement.type === "ReturnStatement")?.argument) : returned(value.body);
3450
+ };
3451
+ return {
3452
+ before() {
3453
+ const options = optionsFirst(context, {});
3454
+ layer = options.layer ?? "layer";
3455
+ make = options.make ?? "make";
3456
+ prefix = options.prefix ?? "layer";
3457
+ builders = new Set(options.builders ?? effectBuilders);
3458
+ constructors = new Set(options.constructors ?? effectLayerFileDefaultConstructors);
3459
+ layers = optionsPatterns(options.layers ?? effectLayerFileDefaultLayers);
3460
+ services = [...optionsPatterns(options.services ?? effectLayerFileDefaultServices), ...layers];
3461
+ },
3462
+ Program(program) {
3463
+ const data = { layer, make, prefix };
3464
+ const declarators = program.body.flatMap((statement) => {
3465
+ const declaration = astDeclaration(statement);
3466
+ const exported = statement.type === "ExportNamedDeclaration";
3467
+ return declaration?.type === "VariableDeclaration" ? declaration.declarations.map((node) => ({ exported, node, name: node.id.type === "Identifier" ? node.id.name : "" })) : [];
3468
+ });
3469
+ const exportedLayer = declarators.find(({ exported, name }) => exported && name === layer);
3470
+ if (!exportedLayer) {
3471
+ context.report({
3472
+ node: program,
3473
+ messageId: "missing",
3474
+ data
3475
+ });
3476
+ } else if (!effectMatches(returned(exportedLayer.node.init), layers)) {
3477
+ context.report({
3478
+ node: exportedLayer.node,
3479
+ messageId: "notLayer",
3480
+ data
3481
+ });
3482
+ }
3483
+ const wired = new Set;
3484
+ const wiring = declarators.filter((item) => item === exportedLayer || effectMatches(item.node.init, layers));
3485
+ astVisit(wiring.map(({ node }) => node.init), [], (call) => {
3486
+ if (call.type !== "CallExpression" || !optionsPatternsTest(layers, astDottedName(call.callee) ?? "")) {
3487
+ return;
3488
+ }
3489
+ for (const argument of call.arguments) {
3490
+ const target = argument.type === "CallExpression" ? argument.callee : argument;
3491
+ if (target.type === "Identifier") {
3492
+ wired.add(target.name);
3493
+ }
3494
+ }
3495
+ });
3496
+ const locals = declarators.filter(({ exported }) => !exported);
3497
+ const effects = locals.filter(({ node }) => effectIsBuilder(node.init, builders));
3498
+ const builder = effects.find(({ name }) => name === make) ?? effects.find(({ name }) => wired.has(name));
3499
+ if (builder && builder.name !== make) {
3500
+ context.report({
3501
+ node: builder.node,
3502
+ messageId: "builderName",
3503
+ data
3504
+ });
3505
+ }
3506
+ for (const { node, name, exported } of declarators) {
3507
+ const isLayer = effectMatches(node.init, layers);
3508
+ const isEffect = effectIsBuilder(node.init, builders);
3509
+ if (!exported && isEffect && name !== builder?.name) {
3510
+ context.report({
3511
+ node,
3512
+ messageId: "moduleMethod",
3513
+ data
3514
+ });
3515
+ }
3516
+ if (!exported && !isEffect && !isLayer && name !== make) {
3517
+ context.report({
3518
+ node,
3519
+ messageId: "moduleHelper",
3520
+ data
3521
+ });
3522
+ }
3523
+ if (isLayer && name !== layer && (exported || !name.startsWith(prefix) || !/^[A-Z]\w*$/.test(name.slice(prefix.length)))) {
3524
+ context.report({
3525
+ node,
3526
+ messageId: "localLayer",
3527
+ data
3528
+ });
3529
+ }
3530
+ }
3531
+ for (const statement of program.body) {
3532
+ if (statement.type === "FunctionDeclaration") {
3533
+ context.report({
3534
+ node: statement,
3535
+ messageId: "moduleHelper",
3536
+ data
3537
+ });
3538
+ }
3539
+ }
3540
+ const generator = builder?.name === make ? effectGenerator(builder.node.init, builders) : undefined;
3541
+ for (const statement of generator?.body?.body ?? []) {
3542
+ if (statement.type === "ReturnStatement" && !effectMatches(statement.argument, services)) {
3543
+ context.report({
3544
+ node: statement,
3545
+ messageId: "makeReturn",
3546
+ data
3547
+ });
3548
+ }
3549
+ }
3550
+ },
3551
+ CallExpression(node) {
3552
+ if (!constructors.has(astDottedName(node.callee) ?? "")) {
3553
+ return;
3554
+ }
3555
+ for (const argument of node.arguments) {
3556
+ if (argument.type !== "SpreadElement" && (astIsInlineFunction(astUnwrap(argument)) || effectIsBuilder(argument, builders))) {
3557
+ context.report({
3558
+ node: argument,
3559
+ messageId: "inlineBuilder",
3560
+ data: { layer, make, prefix }
3561
+ });
3562
+ }
3563
+ }
3564
+ }
3565
+ };
3566
+ }
3567
+ });
3568
+
3569
+ // src/rules/effect/effect-layers.ts
3570
+ import { defineRule as defineRule29 } from "@oxlint/plugins";
3571
+ var effectLayersDefaultMerge = ["Layer.mergeAll"];
3572
+ var effectLayersDefaultProvide = ["Effect.provide", "Layer.provide", "Layer.provideMerge"];
3573
+ var effectLayersDefaultMin = 2;
3574
+ var effectLayersGroupSchema = {
3575
+ type: "object",
3576
+ additionalProperties: false,
3577
+ properties: {
3578
+ callees: { type: "array", items: { type: "string" } },
3579
+ min: { type: "integer", minimum: 1 }
3580
+ }
3581
+ };
3582
+ var effectLayers = defineRule29({
3583
+ meta: {
3584
+ type: "layout",
3585
+ fixable: "whitespace",
3586
+ schema: [
3587
+ {
3588
+ type: "object",
3589
+ additionalProperties: false,
3590
+ properties: {
3591
+ merge: effectLayersGroupSchema,
3592
+ provide: effectLayersGroupSchema,
3593
+ indent: sourceIndentSchema
3594
+ }
3595
+ }
3596
+ ],
3597
+ messages: {
3598
+ merge: "Put every layer in this merge on its own line.",
3599
+ provide: "Put every layer in this array on its own line."
3600
+ }
3601
+ },
3602
+ createOnce(context) {
3603
+ let merge = new Set(effectLayersDefaultMerge);
3604
+ let provide = new Set(effectLayersDefaultProvide);
3605
+ let mergeMin = effectLayersDefaultMin;
3606
+ let provideMin = effectLayersDefaultMin;
3607
+ let indentUnit = sourceIndentUnit();
3608
+ const check = (node) => {
3609
+ const source = context.sourceCode;
3610
+ const call = node.type === "CallExpression";
3611
+ const items = call ? node.arguments : node.elements;
3612
+ const present = items.filter((item) => item !== null);
3613
+ const open = call ? source.getTokenAfter(node.typeArguments ?? node.callee) : source.getFirstToken(node);
3614
+ const close = source.getLastToken(node);
3615
+ if (open?.value !== (call ? "(" : "[") || close === null || present.length < (call ? mergeMin : provideMin)) {
3616
+ return;
3617
+ }
3618
+ const packed = [open, ...present].some((item, index) => item.loc.end.line === (present.at(index) ?? close).loc.start.line);
3619
+ if (!packed) {
3620
+ return;
3621
+ }
3622
+ const text = source.text;
3623
+ const newline = sourceNewline(text);
3624
+ const base = sourceLineIndent(text, open.range[0]);
3625
+ const gaps = sourceItemGaps(open.range[1], present, close.range[0]);
3626
+ context.report({
3627
+ node,
3628
+ messageId: call ? "merge" : "provide",
3629
+ fix: (fixer) => {
3630
+ if (present.length !== items.length) {
3631
+ return null;
3632
+ }
3633
+ return sourceRespace(fixer, text, gaps, (_, end) => `${newline}${base}${end ? "" : indentUnit}`);
3634
+ }
3635
+ });
3636
+ };
3637
+ return {
3638
+ before() {
3639
+ const options = optionsFirst(context, {});
3640
+ merge = new Set(options.merge?.callees ?? effectLayersDefaultMerge);
3641
+ provide = new Set(options.provide?.callees ?? effectLayersDefaultProvide);
3642
+ mergeMin = options.merge?.min ?? effectLayersDefaultMin;
3643
+ provideMin = options.provide?.min ?? effectLayersDefaultMin;
3644
+ indentUnit = sourceIndentUnit(options.indent);
3645
+ },
3646
+ CallExpression(node) {
3647
+ const name = astDottedName(node.callee);
3648
+ if (name !== undefined && merge.has(name)) {
3649
+ check(node);
3650
+ }
3651
+ if (name !== undefined && provide.has(name)) {
3652
+ for (const argument of node.arguments) {
3653
+ if (argument.type === "ArrayExpression") {
3654
+ check(argument);
3655
+ }
3656
+ }
3657
+ }
3658
+ }
3659
+ };
3660
+ }
3661
+ });
3662
+
3663
+ // src/rules/effect/effect-merge-pipe.ts
3664
+ import { defineRule as defineRule30 } from "@oxlint/plugins";
3665
+ var effectMergePipeDefaultMerge = ["Layer.mergeAll"];
3666
+ var effectMergePipeDefaultPipe = ["pipe", "Function.pipe"];
3667
+ var effectMergePipeDefaultMethods = ["pipe"];
3668
+ var effectMergePipe = defineRule30({
3669
+ meta: {
3670
+ type: "layout",
3671
+ schema: [
3672
+ {
3673
+ type: "object",
3674
+ additionalProperties: false,
3675
+ properties: {
3676
+ merge: { type: "array", items: { type: "string" } },
3677
+ pipe: { type: "array", items: { type: "string" } },
3678
+ methods: { type: "array", items: { type: "string" } }
3679
+ }
3680
+ }
3681
+ ],
3682
+ messages: {
3683
+ piped: "A merge that spans lines is never piped. Name it first, then pipe the name."
3684
+ }
3685
+ },
3686
+ createOnce(context) {
3687
+ let merge = new Set(effectMergePipeDefaultMerge);
3688
+ let pipe = new Set(effectMergePipeDefaultPipe);
3689
+ let methods = new Set(effectMergePipeDefaultMethods);
3690
+ const isMultilineMerge = (node) => node?.type === "CallExpression" && merge.has(astDottedName(node.callee) ?? "") && !astIsOneLine(node);
3691
+ return {
3692
+ before() {
3693
+ const options = optionsFirst(context, {});
3694
+ merge = new Set(options.merge ?? effectMergePipeDefaultMerge);
3695
+ pipe = new Set(options.pipe ?? effectMergePipeDefaultPipe);
3696
+ methods = new Set(options.methods ?? effectMergePipeDefaultMethods);
3697
+ },
3698
+ CallExpression(node) {
3699
+ const callee = node.callee;
3700
+ const first = node.arguments.at(0);
3701
+ if (callee.type === "MemberExpression" && methods.has(astMemberName(callee) ?? "") && isMultilineMerge(callee.object)) {
3702
+ context.report({ node: callee.property, messageId: "piped" });
3703
+ }
3704
+ if (pipe.has(astDottedName(callee) ?? "") && first !== undefined && isMultilineMerge(first)) {
3705
+ context.report({ node: first, messageId: "piped" });
3706
+ }
3707
+ }
3708
+ };
3709
+ }
3710
+ });
3711
+
3712
+ // src/rules/effect/effect-schema-first.ts
3713
+ import { defineRule as defineRule31 } from "@oxlint/plugins";
3714
+ var effectSchemaFirstDefaultRuntime = [
3715
+ "Effect",
3716
+ "Layer",
3717
+ "Stream",
3718
+ "Context",
3719
+ "Scope",
3720
+ "Kysely",
3721
+ "React",
3722
+ "Fiber",
3723
+ "Queue",
3724
+ "PubSub",
3725
+ "Ref",
3726
+ "Deferred",
3727
+ "ManagedRuntime",
3728
+ "Sink",
3729
+ "Channel",
3730
+ "Request",
3731
+ "Response",
3732
+ "Headers",
3733
+ "ReadableStream",
3734
+ "WritableStream",
3735
+ "Blob",
3736
+ "File",
3737
+ "AbortSignal",
3738
+ "WebSocket",
3739
+ "Socket",
3740
+ "Worker",
3741
+ "Uint8Array",
3742
+ "ArrayBuffer",
3743
+ "globalThis"
3744
+ ];
3745
+ var effectSchemaFirstSections = {
3746
+ values: ["VariableDeclaration", "ClassDeclaration"],
3747
+ interfaces: ["TSInterfaceDeclaration"],
3748
+ modules: ["TSModuleDeclaration"],
3749
+ aliases: ["TSTypeAliasDeclaration"]
3750
+ };
3751
+ var effectSchemaFirstLabels = {
3752
+ values: "Schemas and values",
3753
+ interfaces: "interfaces",
3754
+ modules: "`declare module`",
3755
+ aliases: "type aliases"
3756
+ };
3757
+ var effectSchemaFirstDefaultOrder = ["values", ["interfaces", "modules"], "aliases"];
3758
+ var effectSchemaFirstSectionSchema = { type: "string", enum: ["values", "interfaces", "modules", "aliases"] };
3759
+ function effectSchemaFirstTypeName(node) {
3760
+ if (node.type === "TSQualifiedName") {
3761
+ const left = effectSchemaFirstTypeName(node.left);
3762
+ return left === undefined ? undefined : `${left}.${node.right.name}`;
3763
+ }
3764
+ return astDottedName(node);
3765
+ }
3766
+ function effectSchemaFirstReference(node) {
3767
+ if (node.type === "TSTypeReference") {
3768
+ return effectSchemaFirstTypeName(node.typeName);
3769
+ }
3770
+ if (node.type === "TSTypeQuery") {
3771
+ return effectSchemaFirstTypeName(node.exprName);
3772
+ }
3773
+ return node.type === "TSInterfaceHeritage" ? astDottedName(node.expression) : undefined;
3774
+ }
3775
+ var effectSchemaFirst = defineRule31({
3776
+ meta: {
3777
+ type: "suggestion",
3778
+ schema: [
3779
+ {
3780
+ type: "object",
3781
+ additionalProperties: false,
3782
+ properties: {
3783
+ member: { type: "string" },
3784
+ keep: optionsPatternSchema,
3785
+ runtime: { type: "array", items: { type: "string" } },
3786
+ rows: {
3787
+ type: "object",
3788
+ additionalProperties: false,
3789
+ properties: { types: { type: "array", items: { type: "string" } }, suffix: { type: "string" } }
3790
+ },
3791
+ order: {
3792
+ type: "array",
3793
+ items: { anyOf: [effectSchemaFirstSectionSchema, { type: "array", items: effectSchemaFirstSectionSchema, minItems: 1 }] }
3794
+ },
3795
+ derived: {
3796
+ type: "object",
3797
+ additionalProperties: false,
3798
+ properties: { first: { type: "boolean" }, sorted: { type: "boolean" } }
3799
+ }
3800
+ }
3801
+ }
3802
+ ],
3803
+ messages: {
3804
+ order: "Order a types file as {{order}}.",
3805
+ schemaType: "Add `export type {{name}} = typeof {{name}}.{{member}}` to the final type block.",
3806
+ typeOrder: "Move {{name}}: the type block lists the `typeof` aliases first, in Schema order, then the other aliases.",
3807
+ dataInterface: "Every field of {{name}} fits a Schema: make it a Schema and derive its type.",
3808
+ rowItem: "{{name}} is built from a database row: make it a Schema; only a `…{{suffix}}` alias may read the row type."
3809
+ }
3810
+ },
3811
+ createOnce(context) {
3812
+ let member = "Type";
3813
+ let keep = [];
3814
+ let runtime = new Set(effectSchemaFirstDefaultRuntime);
3815
+ let rows;
3816
+ let suffix = "Record";
3817
+ let ranks = new Map;
3818
+ let orderText = "";
3819
+ let derivedFirst = true;
3820
+ let derivedSorted = true;
3821
+ const derives = (alias) => {
3822
+ const annotation = alias.typeAnnotation;
3823
+ const name = annotation.type === "TSTypeQuery" ? annotation.exprName : undefined;
3824
+ return name?.type === "TSQualifiedName" && name.left.type === "Identifier" && name.left.name === alias.id.name && name.right.name === member;
3825
+ };
3826
+ const refers = (node, names) => astSome(node, (child) => {
3827
+ if (child.type === "TSFunctionType" || child.type === "TSConstructorType" || child.type === "TSMethodSignature") {
3828
+ return true;
3829
+ }
3830
+ return (effectSchemaFirstReference(child)?.split(".") ?? []).some((name) => names.has(name));
3831
+ });
3832
+ const readsRow = (node) => astSome(node, (child) => Boolean(rows?.has(effectSchemaFirstReference(child) ?? "")));
3833
+ const checkOrder = (program) => {
3834
+ let highest = 0;
3835
+ for (const statement of program.body) {
3836
+ const rank = ranks.get(astDeclaration(statement)?.type ?? "") ?? 0;
3837
+ if (rank > 0 && rank < highest) {
3838
+ context.report({
3839
+ node: statement,
3840
+ messageId: "order",
3841
+ data: { order: orderText }
3842
+ });
3843
+ }
3844
+ highest = Math.max(highest, rank);
3845
+ }
3846
+ };
3847
+ const keptNames = (program, aliases, interfaces) => {
3848
+ const kept = new Set(aliases.filter((alias) => refers(alias.typeAnnotation, runtime)).map((alias) => alias.id.name));
3849
+ for (const statement of program.body) {
3850
+ if (statement.type === "ImportDeclaration" && statement.source.value.startsWith(".")) {
3851
+ for (const specifier of statement.specifiers) {
3852
+ if (statement.importKind === "type" || specifier.type === "ImportSpecifier" && specifier.importKind === "type") {
3853
+ kept.add(specifier.local.name);
3854
+ }
3855
+ }
3856
+ }
3857
+ }
3858
+ const names = new Set([...runtime, ...kept]);
3859
+ let grew = true;
3860
+ while (grew) {
3861
+ grew = false;
3862
+ for (const node of interfaces) {
3863
+ const stays = node.body.body.length === 0 || Boolean(node.typeParameters) || optionsPatternsTest(keep, node.id.name) || refers(node, names);
3864
+ if (!kept.has(node.id.name) && stays) {
3865
+ names.add(node.id.name);
3866
+ kept.add(node.id.name);
3867
+ grew = true;
3868
+ }
3869
+ }
3870
+ }
3871
+ return kept;
3872
+ };
3873
+ return {
3874
+ before() {
3875
+ const options = optionsFirst(context, {});
3876
+ member = options.member ?? "Type";
3877
+ keep = optionsPatterns(options.keep);
3878
+ runtime = new Set(options.runtime ?? effectSchemaFirstDefaultRuntime);
3879
+ rows = options.rows ? new Set(options.rows.types ?? ["Kysely.Selectable"]) : undefined;
3880
+ suffix = options.rows?.suffix ?? "Record";
3881
+ const order = (options.order ?? effectSchemaFirstDefaultOrder).map((group) => [group].flat());
3882
+ ranks = new Map(order.flatMap((group, index) => group.flatMap((section) => effectSchemaFirstSections[section].map((type) => [type, index + 1]))));
3883
+ orderText = order.map((group) => group.map((section) => effectSchemaFirstLabels[section]).join(" and ")).join(", then ");
3884
+ derivedFirst = options.derived?.first ?? true;
3885
+ derivedSorted = options.derived?.sorted ?? true;
3886
+ },
3887
+ Program(program) {
3888
+ checkOrder(program);
3889
+ const declarations = program.body.flatMap((statement) => astDeclaration(statement) ?? []);
3890
+ const aliases = declarations.filter((node) => node.type === "TSTypeAliasDeclaration");
3891
+ const interfaces = declarations.filter((node) => node.type === "TSInterfaceDeclaration");
3892
+ const schemas = declarations.flatMap((node) => node.type === "VariableDeclaration" ? node.declarations : []).map(({ id }) => id.type === "Identifier" ? id.name : "");
3893
+ const exported = program.body.flatMap((statement) => statement.type === "ExportNamedDeclaration" && statement.declaration ? [statement.declaration] : []);
3894
+ const typed = new Set(exported.flatMap((node) => node.type === "TSTypeAliasDeclaration" && derives(node) ? [node.id.name] : []));
3895
+ for (const node of exported.flatMap((declaration) => declaration.type === "VariableDeclaration" ? declaration.declarations : [])) {
3896
+ const isSchema = node.init?.type === "CallExpression" || node.init?.type === "MemberExpression";
3897
+ if (isSchema && node.id.type === "Identifier" && !typed.has(node.id.name)) {
3898
+ context.report({
3899
+ node,
3900
+ messageId: "schemaType",
3901
+ data: { name: node.id.name, member }
3902
+ });
3903
+ }
3904
+ }
3905
+ let order = -1;
3906
+ let other = false;
3907
+ for (const alias of aliases) {
3908
+ if (!derives(alias)) {
3909
+ other = true;
3910
+ continue;
3911
+ }
3912
+ const index = schemas.indexOf(alias.id.name);
3913
+ if (derivedFirst && other || derivedSorted && index < order) {
3914
+ context.report({
3915
+ node: alias,
3916
+ messageId: "typeOrder",
3917
+ data: { name: alias.id.name }
3918
+ });
3919
+ }
3920
+ order = Math.max(order, index);
3921
+ }
3922
+ const kept = keptNames(program, aliases, interfaces);
3923
+ for (const node of interfaces) {
3924
+ if (!kept.has(node.id.name)) {
3925
+ context.report({
3926
+ node,
3927
+ messageId: "dataInterface",
3928
+ data: { name: node.id.name }
3929
+ });
3930
+ }
3931
+ }
3932
+ for (const node of rows ? declarations : []) {
3933
+ const fromRow = node.type === "TSTypeAliasDeclaration" && !node.id.name.endsWith(suffix) && readsRow(node.typeAnnotation) || node.type === "TSInterfaceDeclaration" && node.extends.some(readsRow);
3934
+ if (fromRow) {
3935
+ context.report({
3936
+ node,
3937
+ messageId: "rowItem",
3938
+ data: { name: node.id.name, suffix }
3939
+ });
3940
+ }
3941
+ }
3942
+ }
3943
+ };
3944
+ }
3945
+ });
3946
+
3947
+ // src/rules/effect/effect-values-first.ts
3948
+ import { defineRule as defineRule32 } from "@oxlint/plugins";
3949
+ var effectValuesFirstDefaultPinned = [
3950
+ "^Layer\\.",
3951
+ "^Context\\.",
3952
+ "^HttpRouter\\.add(?:All)?$",
3953
+ "(?:^|\\.)of$",
3954
+ "(?:^|\\.)layer[^.]*$",
3955
+ "^Schema\\.(?:asserts|decode\\w*|encode\\w*|is|isSchema|isSchemaError|resolveAnnotations)$"
3956
+ ];
3957
+ var effectValuesFirst = defineRule32({
3958
+ meta: {
3959
+ type: "suggestion",
3960
+ schema: [
3961
+ {
3962
+ type: "object",
3963
+ additionalProperties: false,
3964
+ properties: {
3965
+ builders: { type: "array", items: { type: "string" } },
3966
+ pinned: optionsPatternSchema
3967
+ }
3968
+ }
3969
+ ],
3970
+ messages: {
3971
+ value: "`{{name}}` is a value declared after `{{after}}`: declare values first, then helpers and methods."
3972
+ }
3973
+ },
3974
+ createOnce(context) {
3975
+ let builders = new Set(effectBuilders);
3976
+ let pinned = [];
3977
+ const check = (statements) => {
3978
+ const tied = new Set;
3979
+ let first;
3980
+ let barrier = false;
3981
+ for (const statement of statements) {
3982
+ const declaration = astDeclaration(statement);
3983
+ if (declaration?.type === "FunctionDeclaration" && declaration.id) {
3984
+ tied.add(declaration.id.name);
3985
+ first ??= declaration.id.name;
3986
+ continue;
3987
+ }
3988
+ if (declaration?.type !== "VariableDeclaration") {
3989
+ barrier ||= statement.type === "ExpressionStatement" && first !== undefined;
3990
+ continue;
3991
+ }
3992
+ for (const declarator of declaration.declarations) {
3993
+ const init = declarator.init;
3994
+ const names = astBindings(declarator.id).map((binding) => binding.name);
3995
+ const helper = Boolean(init && (astIsInlineFunction(astUnwrap(init)) || effectIsBuilder(init, builders)));
3996
+ const kept = helper || effectMatches(init, pinned) || astSome(init, (node) => node.type === "Identifier" && tied.has(node.name));
3997
+ if (first !== undefined && !kept && !barrier) {
3998
+ context.report({
3999
+ node: declarator,
4000
+ messageId: "value",
4001
+ data: { name: names.join(", "), after: first }
4002
+ });
4003
+ }
4004
+ if (kept) {
4005
+ names.forEach((name) => tied.add(name));
4006
+ }
4007
+ barrier ||= kept && first !== undefined && astSome(init, (node) => node.type === "YieldExpression");
4008
+ first ??= helper ? names.join(", ") : undefined;
4009
+ }
4010
+ }
4011
+ };
4012
+ const body = (init) => {
4013
+ const value = init ? astUnwrap(init) : null;
4014
+ const target = value && astIsInlineFunction(value) ? value : effectGenerator(value, builders);
4015
+ return target?.body?.type === "BlockStatement" ? target.body.body : [];
4016
+ };
4017
+ return {
4018
+ before() {
4019
+ const options = optionsFirst(context, {});
4020
+ builders = new Set(options.builders ?? effectBuilders);
4021
+ pinned = optionsPatterns(options.pinned ?? effectValuesFirstDefaultPinned);
4022
+ },
4023
+ Program(program) {
4024
+ check(program.body);
4025
+ for (const statement of program.body) {
4026
+ const declaration = astDeclaration(statement);
4027
+ if (declaration?.type === "FunctionDeclaration") {
4028
+ check(declaration.body?.body ?? []);
4029
+ }
4030
+ if (declaration?.type === "VariableDeclaration") {
4031
+ declaration.declarations.forEach((declarator) => check(body(declarator.init)));
4032
+ }
4033
+ }
4034
+ }
4035
+ };
4036
+ }
4037
+ });
4038
+
4039
+ // src/rules/files/files-components-only.ts
4040
+ import { defineRule as defineRule33 } from "@oxlint/plugins";
4041
+
3364
4042
  // src/utils/react.utils.ts
3365
4043
  function reactReturnsOutput(program, node) {
3366
4044
  const expressions = astReturnExpressions(node);
@@ -3431,7 +4109,7 @@ function reactIsComponent(program, candidate) {
3431
4109
  function componentName(basename2) {
3432
4110
  return basename2.replace(/\.(tsx?|jsx?)$/, "").replaceAll(/(?:^[-.]*|[-.]+)(.?)/g, (_, char) => char.toUpperCase());
3433
4111
  }
3434
- var filesComponentsOnly = defineRule28({
4112
+ var filesComponentsOnly = defineRule33({
3435
4113
  meta: {
3436
4114
  type: "problem",
3437
4115
  schema: [
@@ -3519,7 +4197,7 @@ var filesComponentsOnly = defineRule28({
3519
4197
  });
3520
4198
 
3521
4199
  // src/rules/files/files-constants-only.ts
3522
- import { defineRule as defineRule29 } from "@oxlint/plugins";
4200
+ import { defineRule as defineRule34 } from "@oxlint/plugins";
3523
4201
  function unwrap(expression) {
3524
4202
  if (expression.type === "ParenthesizedExpression" || expression.type === "TSAsExpression" || expression.type === "TSSatisfiesExpression" || expression.type === "TSTypeAssertion" || expression.type === "TSNonNullExpression" || expression.type === "TSInstantiationExpression") {
3525
4203
  return unwrap(expression.expression);
@@ -3574,7 +4252,7 @@ function collectBindings(program) {
3574
4252
  }
3575
4253
  return bindings;
3576
4254
  }
3577
- var filesConstantsOnly = defineRule29({
4255
+ var filesConstantsOnly = defineRule34({
3578
4256
  meta: {
3579
4257
  type: "problem",
3580
4258
  schema: [
@@ -3673,7 +4351,7 @@ var filesConstantsOnly = defineRule29({
3673
4351
  });
3674
4352
 
3675
4353
  // src/rules/files/files-domain-constants.ts
3676
- import { defineRule as defineRule30 } from "@oxlint/plugins";
4354
+ import { defineRule as defineRule35 } from "@oxlint/plugins";
3677
4355
  import { basename as basename2, dirname as dirname2 } from "node:path";
3678
4356
  function isData(expression) {
3679
4357
  const value = astUnwrap(expression);
@@ -3691,7 +4369,7 @@ function isData(expression) {
3691
4369
  }
3692
4370
  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;
3693
4371
  }
3694
- var filesDomainConstants = defineRule30({
4372
+ var filesDomainConstants = defineRule35({
3695
4373
  meta: {
3696
4374
  type: "problem",
3697
4375
  schema: [
@@ -3756,11 +4434,11 @@ var filesDomainConstants = defineRule30({
3756
4434
  });
3757
4435
 
3758
4436
  // src/rules/files/files-exports.ts
3759
- import { defineRule as defineRule31 } from "@oxlint/plugins";
4437
+ import { defineRule as defineRule36 } from "@oxlint/plugins";
3760
4438
  function escapeRegExp(value) {
3761
4439
  return value.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
3762
4440
  }
3763
- var filesExports = defineRule31({
4441
+ var filesExports = defineRule36({
3764
4442
  meta: {
3765
4443
  type: "problem",
3766
4444
  schema: [
@@ -3841,12 +4519,12 @@ var filesExports = defineRule31({
3841
4519
  });
3842
4520
 
3843
4521
  // src/rules/files/files-externals.ts
3844
- import { defineRule as defineRule32 } from "@oxlint/plugins";
4522
+ import { defineRule as defineRule37 } from "@oxlint/plugins";
3845
4523
  import { existsSync as existsSync2, readFileSync } from "node:fs";
3846
4524
  import { builtinModules as builtinModules2 } from "node:module";
3847
4525
  import { dirname as dirname3, join as join2 } from "node:path";
3848
4526
  var filesExternalsConfigs = "^(?:vite|next)\\.config\\.[cm]?[jt]s$";
3849
- var filesExternals = defineRule32({
4527
+ var filesExternals = defineRule37({
3850
4528
  meta: {
3851
4529
  type: "problem",
3852
4530
  schema: [
@@ -3939,7 +4617,7 @@ var filesExternals = defineRule32({
3939
4617
  });
3940
4618
 
3941
4619
  // src/rules/files/files-factory-keys.ts
3942
- import { defineRule as defineRule33 } from "@oxlint/plugins";
4620
+ import { defineRule as defineRule38 } from "@oxlint/plugins";
3943
4621
  function returnedObject(expression) {
3944
4622
  if (expression?.type === "TSAsExpression" || expression?.type === "TSSatisfiesExpression" || expression?.type === "TSTypeAssertion" || expression?.type === "TSNonNullExpression") {
3945
4623
  return returnedObject(expression.expression);
@@ -3950,7 +4628,7 @@ function compileKeys(pattern, keys, requireKeys) {
3950
4628
  const allowedList = keys.concat(requireKeys.filter((key) => !keys.includes(key)));
3951
4629
  return { patterns: optionsPatternsWithEmpty(pattern), allowed: new Set(allowedList), allowedList, required: requireKeys };
3952
4630
  }
3953
- var filesFactoryKeys = defineRule33({
4631
+ var filesFactoryKeys = defineRule38({
3954
4632
  meta: {
3955
4633
  type: "problem",
3956
4634
  schema: [
@@ -4068,8 +4746,8 @@ var filesFactoryKeys = defineRule33({
4068
4746
  });
4069
4747
 
4070
4748
  // src/rules/files/files-helpers.ts
4071
- import { defineRule as defineRule34 } from "@oxlint/plugins";
4072
- var filesHelpers = defineRule34({
4749
+ import { defineRule as defineRule39 } from "@oxlint/plugins";
4750
+ var filesHelpers = defineRule39({
4073
4751
  meta: {
4074
4752
  type: "problem",
4075
4753
  schema: [
@@ -4117,8 +4795,8 @@ var filesHelpers = defineRule34({
4117
4795
  });
4118
4796
 
4119
4797
  // src/rules/files/files-no-functions.ts
4120
- import { defineRule as defineRule35 } from "@oxlint/plugins";
4121
- var filesNoFunctions = defineRule35({
4798
+ import { defineRule as defineRule40 } from "@oxlint/plugins";
4799
+ var filesNoFunctions = defineRule40({
4122
4800
  meta: {
4123
4801
  type: "problem",
4124
4802
  schema: [
@@ -4172,8 +4850,8 @@ var filesNoFunctions = defineRule35({
4172
4850
  });
4173
4851
 
4174
4852
  // src/rules/files/files-restricted.ts
4175
- import { defineRule as defineRule36 } from "@oxlint/plugins";
4176
- var filesRestricted = defineRule36({
4853
+ import { defineRule as defineRule41 } from "@oxlint/plugins";
4854
+ var filesRestricted = defineRule41({
4177
4855
  meta: {
4178
4856
  type: "problem",
4179
4857
  schema: [
@@ -4205,7 +4883,7 @@ var filesRestricted = defineRule36({
4205
4883
  });
4206
4884
 
4207
4885
  // src/rules/files/files-route.ts
4208
- import { defineRule as defineRule37 } from "@oxlint/plugins";
4886
+ import { defineRule as defineRule42 } from "@oxlint/plugins";
4209
4887
  function inspectAdapter(context, item, bannedHooks, banIntrinsicJsx) {
4210
4888
  astVisit(item.node.body, [item.node], (node) => {
4211
4889
  if (banIntrinsicJsx && node.type === "JSXOpeningElement" && node.name.type === "JSXIdentifier" && /^[a-z]/.test(node.name.name)) {
@@ -4225,7 +4903,7 @@ function inspectAdapter(context, item, bannedHooks, banIntrinsicJsx) {
4225
4903
  }
4226
4904
  });
4227
4905
  }
4228
- var filesRoute = defineRule37({
4906
+ var filesRoute = defineRule42({
4229
4907
  meta: {
4230
4908
  type: "problem",
4231
4909
  schema: [
@@ -4295,7 +4973,7 @@ var filesRoute = defineRule37({
4295
4973
  });
4296
4974
 
4297
4975
  // src/rules/files/files-types-only.ts
4298
- import { defineRule as defineRule38 } from "@oxlint/plugins";
4976
+ import { defineRule as defineRule43 } from "@oxlint/plugins";
4299
4977
  function runtimeImportLocalNames(statement) {
4300
4978
  return statement.specifiers.flatMap((specifier) => specifier.type !== "ImportSpecifier" || specifier.importKind !== "type" ? [specifier.local.name] : []);
4301
4979
  }
@@ -4464,7 +5142,7 @@ function runtimeKind(node) {
4464
5142
  }
4465
5143
  return node.type === "FunctionDeclaration" ? "function" : "variable";
4466
5144
  }
4467
- var filesTypesOnly = defineRule38({
5145
+ var filesTypesOnly = defineRule43({
4468
5146
  meta: {
4469
5147
  type: "problem",
4470
5148
  schema: [
@@ -4572,8 +5250,8 @@ var filesTypesOnly = defineRule38({
4572
5250
  });
4573
5251
 
4574
5252
  // src/rules/layout/layout-arrow-body.ts
4575
- import { defineRule as defineRule39 } from "@oxlint/plugins";
4576
- var layoutArrowBody = defineRule39({
5253
+ import { defineRule as defineRule44 } from "@oxlint/plugins";
5254
+ var layoutArrowBody = defineRule44({
4577
5255
  meta: {
4578
5256
  type: "layout",
4579
5257
  fixable: "whitespace",
@@ -4625,12 +5303,12 @@ var layoutArrowBody = defineRule39({
4625
5303
  });
4626
5304
 
4627
5305
  // src/rules/layout/layout-call-arguments.ts
4628
- import { defineRule as defineRule40 } from "@oxlint/plugins";
5306
+ import { defineRule as defineRule45 } from "@oxlint/plugins";
4629
5307
  function layoutCallArgumentsHuggable(node) {
4630
5308
  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);
4631
5309
  }
4632
5310
  var layoutCallArgumentsMax = { type: "integer", minimum: 1 };
4633
- var layoutCallArguments = defineRule40({
5311
+ var layoutCallArguments = defineRule45({
4634
5312
  meta: {
4635
5313
  type: "layout",
4636
5314
  fixable: "whitespace",
@@ -4812,12 +5490,12 @@ var layoutCallArguments = defineRule40({
4812
5490
  });
4813
5491
 
4814
5492
  // src/rules/layout/layout-call-array.ts
4815
- import { defineRule as defineRule41 } from "@oxlint/plugins";
5493
+ import { defineRule as defineRule46 } from "@oxlint/plugins";
4816
5494
  var layoutCallArrayDefaultCallees = ["Promise.all", "Promise.allSettled"];
4817
5495
  function layoutCallArrayRoot(node) {
4818
5496
  return node.type === "MemberExpression" ? layoutCallArrayRoot(node.object) : node;
4819
5497
  }
4820
- var layoutCallArray = defineRule41({
5498
+ var layoutCallArray = defineRule46({
4821
5499
  meta: {
4822
5500
  type: "layout",
4823
5501
  fixable: "whitespace",
@@ -4933,7 +5611,7 @@ var layoutCallArray = defineRule41({
4933
5611
  });
4934
5612
 
4935
5613
  // src/rules/layout/layout-call-depth.ts
4936
- import { defineRule as defineRule42 } from "@oxlint/plugins";
5614
+ import { defineRule as defineRule47 } from "@oxlint/plugins";
4937
5615
  function layoutCallDepthOuter(node) {
4938
5616
  const parent = node.parent;
4939
5617
  if (!parent || parent.type === "ArrowFunctionExpression" || parent.type === "FunctionExpression" || parent.type.endsWith("Statement")) {
@@ -4941,7 +5619,7 @@ function layoutCallDepthOuter(node) {
4941
5619
  }
4942
5620
  return astIsCall(parent) && parent.arguments.some((argument) => argument === node) ? parent : layoutCallDepthOuter(parent);
4943
5621
  }
4944
- var layoutCallDepth = defineRule42({
5622
+ var layoutCallDepth = defineRule47({
4945
5623
  meta: {
4946
5624
  type: "layout",
4947
5625
  schema: [
@@ -4980,8 +5658,8 @@ var layoutCallDepth = defineRule42({
4980
5658
  });
4981
5659
 
4982
5660
  // src/rules/layout/layout-chain.ts
4983
- import { defineRule as defineRule43 } from "@oxlint/plugins";
4984
- var layoutChain = defineRule43({
5661
+ import { defineRule as defineRule48 } from "@oxlint/plugins";
5662
+ var layoutChain = defineRule48({
4985
5663
  meta: {
4986
5664
  type: "layout",
4987
5665
  fixable: "whitespace",
@@ -5100,8 +5778,8 @@ var layoutChain = defineRule43({
5100
5778
  });
5101
5779
 
5102
5780
  // src/rules/layout/layout-items.ts
5103
- import { defineRule as defineRule44 } from "@oxlint/plugins";
5104
- var layoutItems = defineRule44({
5781
+ import { defineRule as defineRule49 } from "@oxlint/plugins";
5782
+ var layoutItems = defineRule49({
5105
5783
  meta: {
5106
5784
  type: "layout",
5107
5785
  fixable: "whitespace",
@@ -5156,8 +5834,8 @@ var layoutItems = defineRule44({
5156
5834
  });
5157
5835
 
5158
5836
  // src/rules/layout/layout-jsx-attributes.ts
5159
- import { defineRule as defineRule45 } from "@oxlint/plugins";
5160
- var layoutJsxAttributes = defineRule45({
5837
+ import { defineRule as defineRule50 } from "@oxlint/plugins";
5838
+ var layoutJsxAttributes = defineRule50({
5161
5839
  meta: {
5162
5840
  type: "layout",
5163
5841
  fixable: "whitespace",
@@ -5245,8 +5923,8 @@ var layoutJsxAttributes = defineRule45({
5245
5923
  });
5246
5924
 
5247
5925
  // src/rules/layout/layout-key-value.ts
5248
- import { defineRule as defineRule46 } from "@oxlint/plugins";
5249
- var layoutKeyValue = defineRule46({
5926
+ import { defineRule as defineRule51 } from "@oxlint/plugins";
5927
+ var layoutKeyValue = defineRule51({
5250
5928
  meta: {
5251
5929
  type: "layout",
5252
5930
  fixable: "whitespace",
@@ -5282,7 +5960,7 @@ var layoutKeyValue = defineRule46({
5282
5960
  });
5283
5961
 
5284
5962
  // src/rules/layout/layout-object.ts
5285
- import { defineRule as defineRule47 } from "@oxlint/plugins";
5963
+ import { defineRule as defineRule52 } from "@oxlint/plugins";
5286
5964
  function layoutObjectIsWhitespace(text) {
5287
5965
  return /^[\t\n\r\f ]*$/.test(text);
5288
5966
  }
@@ -5290,7 +5968,7 @@ function layoutObjectIsFlat(property) {
5290
5968
  const value = property.type === "SpreadElement" ? property.argument : property.value;
5291
5969
  return astIsOneLine(property) && (property.type === "SpreadElement" || !property.method && property.kind === "init") && value.type !== "ObjectExpression" && value.type !== "ArrayExpression" && !astIsInlineFunction(value);
5292
5970
  }
5293
- var layoutObject = defineRule47({
5971
+ var layoutObject = defineRule52({
5294
5972
  meta: {
5295
5973
  type: "layout",
5296
5974
  fixable: "whitespace",
@@ -5407,7 +6085,7 @@ var layoutObject = defineRule47({
5407
6085
  });
5408
6086
 
5409
6087
  // src/rules/layout/layout-padding.ts
5410
- import { defineRule as defineRule48 } from "@oxlint/plugins";
6088
+ import { defineRule as defineRule53 } from "@oxlint/plugins";
5411
6089
  var layoutPaddingControl = new Set([
5412
6090
  "IfStatement",
5413
6091
  "ForStatement",
@@ -5436,7 +6114,7 @@ function layoutPaddingKind(node) {
5436
6114
  function layoutPaddingIsMultilineVariable(node, kind) {
5437
6115
  return kind === "variable" && node.loc.start.line !== node.loc.end.line;
5438
6116
  }
5439
- var layoutPadding = defineRule48({
6117
+ var layoutPadding = defineRule53({
5440
6118
  meta: {
5441
6119
  type: "layout",
5442
6120
  fixable: "whitespace",
@@ -5525,8 +6203,8 @@ var layoutPadding = defineRule48({
5525
6203
  });
5526
6204
 
5527
6205
  // src/rules/layout/layout-pipe.ts
5528
- import { defineRule as defineRule49 } from "@oxlint/plugins";
5529
- var layoutPipe = defineRule49({
6206
+ import { defineRule as defineRule54 } from "@oxlint/plugins";
6207
+ var layoutPipe = defineRule54({
5530
6208
  meta: {
5531
6209
  type: "layout",
5532
6210
  messages: {
@@ -5557,7 +6235,7 @@ var layoutPipe = defineRule49({
5557
6235
  });
5558
6236
 
5559
6237
  // src/rules/layout/layout-ternary.ts
5560
- import { defineRule as defineRule50 } from "@oxlint/plugins";
6238
+ import { defineRule as defineRule55 } from "@oxlint/plugins";
5561
6239
  function layoutTernaryLines(node) {
5562
6240
  return node.loc.end.line - node.loc.start.line + 1;
5563
6241
  }
@@ -5565,7 +6243,7 @@ function layoutTernaryBreak(between, operator, newline) {
5565
6243
  const at = between.indexOf(operator);
5566
6244
  return `${between.slice(0, at).trimEnd()}${newline}${operator} ${between.slice(at + 1).trimStart()}`;
5567
6245
  }
5568
- var layoutTernary = defineRule50({
6246
+ var layoutTernary = defineRule55({
5569
6247
  meta: {
5570
6248
  type: "layout",
5571
6249
  fixable: "whitespace",
@@ -5681,9 +6359,9 @@ var layoutTernary = defineRule50({
5681
6359
  });
5682
6360
 
5683
6361
  // src/rules/naming/naming-declarations.ts
5684
- import { defineRule as defineRule51 } from "@oxlint/plugins";
6362
+ import { defineRule as defineRule56 } from "@oxlint/plugins";
5685
6363
  var namingDeclarationsKinds = ["function", "const", "let", "var", "class", "type", "interface", "enum"];
5686
- var namingDeclarations = defineRule51({
6364
+ var namingDeclarations = defineRule56({
5687
6365
  meta: {
5688
6366
  type: "problem",
5689
6367
  schema: [
@@ -5760,7 +6438,7 @@ var namingDeclarations = defineRule51({
5760
6438
  });
5761
6439
 
5762
6440
  // src/rules/naming/naming-exports.ts
5763
- import { defineRule as defineRule52 } from "@oxlint/plugins";
6441
+ import { defineRule as defineRule57 } from "@oxlint/plugins";
5764
6442
  var namingExportsScopeProperties = {
5765
6443
  scope: { type: "string", enum: ["exports", "functions", "declarations"] },
5766
6444
  types: { type: "boolean" },
@@ -5786,7 +6464,7 @@ function matchTemplate(basename3, template, placeholder = "[a-z0-9-]+") {
5786
6464
  }
5787
6465
  return new RegExp(`^${pattern}$`).exec(basename3)?.groups ?? null;
5788
6466
  }
5789
- var namingExports = defineRule52({
6467
+ var namingExports = defineRule57({
5790
6468
  meta: {
5791
6469
  type: "problem",
5792
6470
  schema: {
@@ -5923,10 +6601,10 @@ var namingExports = defineRule52({
5923
6601
  });
5924
6602
 
5925
6603
  // src/rules/naming/naming-file.ts
5926
- import { defineRule as defineRule53 } from "@oxlint/plugins";
6604
+ import { defineRule as defineRule58 } from "@oxlint/plugins";
5927
6605
  import { readdirSync as readdirSync2 } from "node:fs";
5928
6606
  import { dirname as dirname4 } from "node:path";
5929
- var namingFile = defineRule53({
6607
+ var namingFile = defineRule58({
5930
6608
  meta: {
5931
6609
  type: "problem",
5932
6610
  schema: {
@@ -5996,9 +6674,9 @@ var namingFile = defineRule53({
5996
6674
  });
5997
6675
 
5998
6676
  // src/rules/naming/naming-folder.ts
5999
- import { defineRule as defineRule54 } from "@oxlint/plugins";
6677
+ import { defineRule as defineRule59 } from "@oxlint/plugins";
6000
6678
  import { posix as posix2 } from "node:path";
6001
- var namingFolder = defineRule54({
6679
+ var namingFolder = defineRule59({
6002
6680
  meta: {
6003
6681
  type: "problem",
6004
6682
  schema: [
@@ -6072,9 +6750,9 @@ var reactDynamicClasses = astSelectorRule(':matches(JSXAttribute[name.name="clas
6072
6750
  var reactEmptyEffect = astSelectorRule(':matches(CallExpression[callee.name=/^use(Layout)?Effect$/], CallExpression[callee.object.name="React"][callee.property.name=/^use(Layout)?Effect$/]) > :matches(ArrowFunctionExpression, FunctionExpression) > BlockStatement[body.length=0]', "Remove the empty effect.");
6073
6751
 
6074
6752
  // src/rules/react/react-memo.ts
6075
- import { defineRule as defineRule55 } from "@oxlint/plugins";
6753
+ import { defineRule as defineRule60 } from "@oxlint/plugins";
6076
6754
  var reactMemoNames = ["memo", "useMemo", "useCallback"];
6077
- var reactMemo = defineRule55({
6755
+ var reactMemo = defineRule60({
6078
6756
  meta: {
6079
6757
  type: "problem",
6080
6758
  schema: [],
@@ -6109,7 +6787,7 @@ var reactMemo = defineRule55({
6109
6787
  });
6110
6788
 
6111
6789
  // src/rules/react/react-props.ts
6112
- import { defineRule as defineRule56 } from "@oxlint/plugins";
6790
+ import { defineRule as defineRule61 } from "@oxlint/plugins";
6113
6791
  function reactPropsTarget(node) {
6114
6792
  if (node?.type === "FunctionDeclaration" || node?.type === "FunctionExpression" || node?.type === "ArrowFunctionExpression") {
6115
6793
  return { fn: node };
@@ -6136,7 +6814,7 @@ function reactIsPassThrough(type) {
6136
6814
  const argument = type.typeArguments?.params.length === 1 ? type.typeArguments.params[0] : undefined;
6137
6815
  return name.type === "Identifier" && name.name === "ComponentProps" && (argument?.type === "TSTypeQuery" || argument?.type === "TSLiteralType" && argument.literal.type === "Literal" && typeof argument.literal.value === "string");
6138
6816
  }
6139
- var reactProps = defineRule56({
6817
+ var reactProps = defineRule61({
6140
6818
  meta: {
6141
6819
  type: "problem",
6142
6820
  schema: [
@@ -6235,7 +6913,7 @@ var reactProps = defineRule56({
6235
6913
  });
6236
6914
 
6237
6915
  // src/rules/schemas/schemas-inline.ts
6238
- import { defineRule as defineRule57 } from "@oxlint/plugins";
6916
+ import { defineRule as defineRule62 } from "@oxlint/plugins";
6239
6917
 
6240
6918
  // src/utils/schemas.utils.ts
6241
6919
  var schemasElementOptionsSchema = {
@@ -6271,7 +6949,7 @@ function schemasIsAllowedElement(node, allowScalars, namespaces, structuralMetho
6271
6949
  }
6272
6950
 
6273
6951
  // src/rules/schemas/schemas-inline.ts
6274
- var schemasInline = defineRule57({
6952
+ var schemasInline = defineRule62({
6275
6953
  meta: {
6276
6954
  type: "problem",
6277
6955
  schema: [schemasElementOptionsSchema],
@@ -6320,11 +6998,11 @@ var schemasInline = defineRule57({
6320
6998
  });
6321
6999
 
6322
7000
  // src/rules/schemas/schemas-local.ts
6323
- import { defineRule as defineRule58 } from "@oxlint/plugins";
7001
+ import { defineRule as defineRule63 } from "@oxlint/plugins";
6324
7002
  var schemasLocalImportMessage = "Do not import runtime schema constructors from {{source}}; import a named schema instead.";
6325
7003
  var schemasLocalConstructionMessage = "Do not construct schemas locally; import a named schema instead.";
6326
7004
  var schemasLocalCalls = ["config", "prettifyError", "treeifyError", "flattenError", "formatError"];
6327
- var schemasLocal = defineRule58({
7005
+ var schemasLocal = defineRule63({
6328
7006
  meta: {
6329
7007
  type: "problem",
6330
7008
  schema: [
@@ -6337,6 +7015,8 @@ var schemasLocal = defineRule58({
6337
7015
  calls: { type: "array", items: { type: "string" } },
6338
7016
  allow: { type: "array", items: { type: "string" } },
6339
7017
  patterns: { type: "array", items: { type: "string" } },
7018
+ imports: { type: "boolean" },
7019
+ values: { type: "boolean" },
6340
7020
  message: { type: "string" },
6341
7021
  importMessage: { type: "string" },
6342
7022
  constructionMessage: { type: "string" }
@@ -6356,6 +7036,32 @@ var schemasLocal = defineRule58({
6356
7036
  let pending = [];
6357
7037
  let importMessage = schemasLocalImportMessage;
6358
7038
  let constructionMessage = schemasLocalConstructionMessage;
7039
+ let imports = true;
7040
+ let values = false;
7041
+ let inline = new Set;
7042
+ function isInline(node) {
7043
+ if (inline.size === 0) {
7044
+ return false;
7045
+ }
7046
+ for (let parent = node.parent;parent; parent = parent.parent) {
7047
+ if (inline.has(parent)) {
7048
+ return true;
7049
+ }
7050
+ }
7051
+ return false;
7052
+ }
7053
+ function readsLocal(node) {
7054
+ const scope = context.sourceCode.getScope(node);
7055
+ return astSome(node, (child) => {
7056
+ if (child.type !== "Identifier") {
7057
+ return false;
7058
+ }
7059
+ const parent = child.parent;
7060
+ const named = parent.type === "MemberExpression" && parent.property === child && !parent.computed || parent.type === "Property" && parent.key === child && !parent.computed && !parent.shorthand;
7061
+ const type = named ? undefined : boundariesDeclaredVariable(scope, child.name)?.scope.type;
7062
+ return type !== undefined && type !== "module" && type !== "global";
7063
+ });
7064
+ }
6359
7065
  function isAllowedCall(node, member) {
6360
7066
  return member?.type === "MemberExpression" && member.object === node && !member.computed && member.property.type === "Identifier" && calls.has(member.property.name) && member.parent.type === "CallExpression" && member.parent.callee === member;
6361
7067
  }
@@ -6363,6 +7069,9 @@ var schemasLocal = defineRule58({
6363
7069
  return packages.has(source) || [...packages].some((name) => source.startsWith(`${name}/`));
6364
7070
  }
6365
7071
  function reportRuntimeImport(node, source) {
7072
+ if (!imports) {
7073
+ return;
7074
+ }
6366
7075
  context.report({
6367
7076
  node,
6368
7077
  messageId: "runtimeImport",
@@ -6387,6 +7096,9 @@ var schemasLocal = defineRule58({
6387
7096
  pending = [];
6388
7097
  importMessage = options.importMessage ?? options.message ?? schemasLocalImportMessage;
6389
7098
  constructionMessage = options.constructionMessage ?? options.message ?? schemasLocalConstructionMessage;
7099
+ imports = options.imports ?? true;
7100
+ values = options.values ?? false;
7101
+ inline = new Set;
6390
7102
  if ((options.allow ?? []).some((suffix) => filename.endsWith(suffix)) || (options.patterns ?? []).some((pattern) => new RegExp(pattern).test(filename))) {
6391
7103
  return false;
6392
7104
  }
@@ -6409,7 +7121,7 @@ var schemasLocal = defineRule58({
6409
7121
  pending.push({ node, locals });
6410
7122
  },
6411
7123
  "Program:exit"() {
6412
- const runtime = pending.filter(({ node, locals }) => context.sourceCode.getDeclaredVariables(node).filter((variable) => locals.includes(variable.name)).some((variable) => variable.references.length === 0 || variable.references.some((reference) => !isAllowedCall(reference.identifier, reference.identifier.parent))));
7124
+ const runtime = pending.filter(({ node, locals }) => context.sourceCode.getDeclaredVariables(node).filter((variable) => locals.includes(variable.name)).some((variable) => variable.references.length === 0 || variable.references.some((reference) => !isAllowedCall(reference.identifier, reference.identifier.parent) && !isInline(reference.identifier))));
6413
7125
  for (const { node } of runtime) {
6414
7126
  reportRuntimeImport(node, node.source.value);
6415
7127
  }
@@ -6424,6 +7136,10 @@ var schemasLocal = defineRule58({
6424
7136
  if (root.type !== "Identifier" || !constructors.has(root.name) || node.callee.type === "MemberExpression" && node.callee.object === root && isAllowedCall(root, root.parent)) {
6425
7137
  return;
6426
7138
  }
7139
+ if (values && (isInline(node) || readsLocal(node))) {
7140
+ inline.add(node);
7141
+ return;
7142
+ }
6427
7143
  context.report({
6428
7144
  node,
6429
7145
  messageId: "construction",
@@ -6435,8 +7151,8 @@ var schemasLocal = defineRule58({
6435
7151
  });
6436
7152
 
6437
7153
  // src/rules/schemas/schemas-rederive.ts
6438
- import { defineRule as defineRule59 } from "@oxlint/plugins";
6439
- var schemasRederive = defineRule59({
7154
+ import { defineRule as defineRule64 } from "@oxlint/plugins";
7155
+ var schemasRederive = defineRule64({
6440
7156
  meta: {
6441
7157
  type: "problem",
6442
7158
  schema: [
@@ -6482,7 +7198,7 @@ var schemasRederive = defineRule59({
6482
7198
  });
6483
7199
 
6484
7200
  // src/rules/schemas/schemas-single-use.ts
6485
- import { defineRule as defineRule60 } from "@oxlint/plugins";
7201
+ import { defineRule as defineRule65 } from "@oxlint/plugins";
6486
7202
  function isScalarSchema(node, namespaces, structuralMethods) {
6487
7203
  if (node.type !== "CallExpression" || node.callee.type !== "MemberExpression") {
6488
7204
  return false;
@@ -6496,7 +7212,7 @@ function isScalarSchema(node, namespaces, structuralMethods) {
6496
7212
  }
6497
7213
  return node.callee.object.type === "CallExpression" && isScalarSchema(node.callee.object, namespaces, structuralMethods);
6498
7214
  }
6499
- var schemasSingleUse = defineRule60({
7215
+ var schemasSingleUse = defineRule65({
6500
7216
  meta: {
6501
7217
  type: "suggestion",
6502
7218
  schema: [schemasElementOptionsSchema],
@@ -6572,7 +7288,7 @@ var schemasSingleUse = defineRule60({
6572
7288
  });
6573
7289
 
6574
7290
  // src/rules/tests/tests-assertions.ts
6575
- import { defineRule as defineRule61 } from "@oxlint/plugins";
7291
+ import { defineRule as defineRule66 } from "@oxlint/plugins";
6576
7292
  var testsAssertionsModifiers = new Set(["for", "each", "concurrent", "sequential", "only", "skip"]);
6577
7293
  var testsAssertionsFunctions = [
6578
7294
  "expect",
@@ -6762,7 +7478,7 @@ function isAssertedTest(registration, sourceCode, state) {
6762
7478
  }
6763
7479
  return rows.length > 0 && rows.every((row) => hasAssertion(callback, row.bindings, new Set, state));
6764
7480
  }
6765
- var testsAssertions = defineRule61({
7481
+ var testsAssertions = defineRule66({
6766
7482
  meta: {
6767
7483
  type: "problem",
6768
7484
  schema: [
@@ -6888,8 +7604,8 @@ var testsAssertions = defineRule61({
6888
7604
  });
6889
7605
 
6890
7606
  // src/rules/tests/tests-concurrent-db.ts
6891
- import { defineRule as defineRule62 } from "@oxlint/plugins";
6892
- var testsConcurrentDb = defineRule62({
7607
+ import { defineRule as defineRule67 } from "@oxlint/plugins";
7608
+ var testsConcurrentDb = defineRule67({
6893
7609
  meta: {
6894
7610
  type: "problem",
6895
7611
  schema: [
@@ -6945,7 +7661,7 @@ var testsConcurrentDb = defineRule62({
6945
7661
  });
6946
7662
 
6947
7663
  // src/rules/tests/tests-modifiers.ts
6948
- import { defineRule as defineRule63 } from "@oxlint/plugins";
7664
+ import { defineRule as defineRule68 } from "@oxlint/plugins";
6949
7665
  var testsModifiersNames = ["test", "it", "describe", "suite"];
6950
7666
  var testsModifiersPackages = new Set(["vitest", "bun:test", "@playwright/test", "@jest/globals"]);
6951
7667
  var testsModifiersBanned = ["only", "skip", "todo"];
@@ -6964,7 +7680,7 @@ function modifierName(node) {
6964
7680
  const property = astMemberName(node);
6965
7681
  return object && property ? `${object}.${property}` : undefined;
6966
7682
  }
6967
- var testsModifiers = defineRule63({
7683
+ var testsModifiers = defineRule68({
6968
7684
  meta: {
6969
7685
  type: "problem",
6970
7686
  schema: [
@@ -7018,9 +7734,9 @@ var testsModifiers = defineRule63({
7018
7734
  });
7019
7735
 
7020
7736
  // src/rules/tests/tests-titles.ts
7021
- import { defineRule as defineRule64 } from "@oxlint/plugins";
7737
+ import { defineRule as defineRule69 } from "@oxlint/plugins";
7022
7738
  var testsTitlesModifiers = ["only", "skip", "concurrent", "sequential", "todo", "each", "for"];
7023
- var testsTitles = defineRule64({
7739
+ var testsTitles = defineRule69({
7024
7740
  meta: {
7025
7741
  type: "suggestion",
7026
7742
  schema: [
@@ -7098,11 +7814,11 @@ var testsTitles = defineRule64({
7098
7814
  });
7099
7815
 
7100
7816
  // src/rules/types/types-declarations.ts
7101
- import { defineRule as defineRule65 } from "@oxlint/plugins";
7817
+ import { defineRule as defineRule70 } from "@oxlint/plugins";
7102
7818
  function isValuePattern(source) {
7103
7819
  return /^\^?=/.test(source);
7104
7820
  }
7105
- var typesDeclarations = defineRule65({
7821
+ var typesDeclarations = defineRule70({
7106
7822
  meta: {
7107
7823
  type: "problem",
7108
7824
  schema: [
@@ -7144,8 +7860,73 @@ var typesDeclarations = defineRule65({
7144
7860
  }
7145
7861
  });
7146
7862
 
7863
+ // src/rules/types/types-duplicate.ts
7864
+ import { defineRule as defineRule71 } from "@oxlint/plugins";
7865
+ var typesDuplicate = defineRule71({
7866
+ meta: {
7867
+ type: "suggestion",
7868
+ schema: [
7869
+ {
7870
+ type: "object",
7871
+ additionalProperties: false,
7872
+ properties: {
7873
+ structs: { type: "array", items: { type: "string" } },
7874
+ min: { type: "integer", minimum: 1 }
7875
+ }
7876
+ }
7877
+ ],
7878
+ messages: { duplicate: "{{name}} has the same members as {{first}}; use {{first}}, or derive one from the other." }
7879
+ },
7880
+ createOnce(context) {
7881
+ let structs = new Set(["Schema.Struct"]);
7882
+ let min = 2;
7883
+ let seen = new Map;
7884
+ const check = (node, name, kind, members) => {
7885
+ if (members.length < min) {
7886
+ return;
7887
+ }
7888
+ const signature = members.map((item) => context.sourceCode.getText(item).replaceAll(/\breadonly\s+/g, "").replaceAll(/\s+/g, "").replace(/[;,]$/, "")).sort().join(";");
7889
+ const key = `${kind}:${signature}`;
7890
+ const first = seen.get(key);
7891
+ if (first === undefined) {
7892
+ seen.set(key, name);
7893
+ return;
7894
+ }
7895
+ context.report({
7896
+ node,
7897
+ messageId: "duplicate",
7898
+ data: { name, first }
7899
+ });
7900
+ };
7901
+ return {
7902
+ before() {
7903
+ const options = optionsFirst(context, {});
7904
+ structs = new Set(options.structs ?? ["Schema.Struct"]);
7905
+ min = options.min ?? 2;
7906
+ seen = new Map;
7907
+ },
7908
+ TSInterfaceDeclaration(node) {
7909
+ const heritage = node.extends.map((item) => context.sourceCode.getText(item)).join(",");
7910
+ check(node, node.id.name, `type:${heritage}`, node.body.body);
7911
+ },
7912
+ TSTypeAliasDeclaration(node) {
7913
+ if (node.typeAnnotation.type === "TSTypeLiteral") {
7914
+ check(node, node.id.name, "type:", node.typeAnnotation.members);
7915
+ }
7916
+ },
7917
+ VariableDeclarator(node) {
7918
+ const init = node.init ? astUnwrap(node.init) : undefined;
7919
+ const fields = init?.type === "CallExpression" && structs.has(astDottedName(init.callee) ?? "") ? init.arguments[0] : undefined;
7920
+ if (fields?.type === "ObjectExpression" && node.id.type === "Identifier") {
7921
+ check(node, node.id.name, "struct", fields.properties);
7922
+ }
7923
+ }
7924
+ };
7925
+ }
7926
+ });
7927
+
7147
7928
  // src/rules/types/types-imported-alias.ts
7148
- import { defineRule as defineRule66 } from "@oxlint/plugins";
7929
+ import { defineRule as defineRule72 } from "@oxlint/plugins";
7149
7930
  function importedAliasTarget(declaration, imports) {
7150
7931
  if (declaration?.type !== "TSTypeAliasDeclaration") {
7151
7932
  return;
@@ -7157,7 +7938,7 @@ function importedAliasTarget(declaration, imports) {
7157
7938
  const { name } = type.typeName;
7158
7939
  return imports.has(name) && !declaration.typeParameters?.params.some((parameter) => parameter.name.name === name) ? name : undefined;
7159
7940
  }
7160
- var typesImportedAlias = defineRule66({
7941
+ var typesImportedAlias = defineRule72({
7161
7942
  meta: {
7162
7943
  type: "problem",
7163
7944
  schema: [],
@@ -7219,7 +8000,7 @@ var typesImportedAlias = defineRule66({
7219
8000
  });
7220
8001
 
7221
8002
  // src/rules/types/types-inline.ts
7222
- import { defineRule as defineRule67 } from "@oxlint/plugins";
8003
+ import { defineRule as defineRule73 } from "@oxlint/plugins";
7223
8004
  function parameterAnnotation(parameter) {
7224
8005
  if (parameter.type === "TSParameterProperty") {
7225
8006
  return parameterAnnotation(parameter.parameter);
@@ -7229,7 +8010,7 @@ function parameterAnnotation(parameter) {
7229
8010
  }
7230
8011
  return parameter.typeAnnotation;
7231
8012
  }
7232
- var typesInline = defineRule67({
8013
+ var typesInline = defineRule73({
7233
8014
  meta: {
7234
8015
  type: "problem",
7235
8016
  schema: [
@@ -7305,8 +8086,8 @@ var typesInline = defineRule67({
7305
8086
  var typesLocalAlias = astSelectorRule("TSTypeAliasDeclaration", "Local component/hook contracts use interfaces named for their owner. Derived or reusable aliases belong in domain types; do not substitute an empty interface.");
7306
8087
 
7307
8088
  // src/rules/types/types-namespace-import.ts
7308
- import { defineRule as defineRule68 } from "@oxlint/plugins";
7309
- var typesNamespaceImport = defineRule68({
8089
+ import { defineRule as defineRule74 } from "@oxlint/plugins";
8090
+ var typesNamespaceImport = defineRule74({
7310
8091
  meta: {
7311
8092
  type: "suggestion",
7312
8093
  schema: [
@@ -7348,8 +8129,8 @@ var typesNamespaceImport = defineRule68({
7348
8129
  });
7349
8130
 
7350
8131
  // src/rules/types/types-service.ts
7351
- import { defineRule as defineRule69 } from "@oxlint/plugins";
7352
- var typesService = defineRule69({
8132
+ import { defineRule as defineRule75 } from "@oxlint/plugins";
8133
+ var typesService = defineRule75({
7353
8134
  meta: {
7354
8135
  type: "problem",
7355
8136
  schema: [
@@ -7399,12 +8180,12 @@ var typesService = defineRule69({
7399
8180
  });
7400
8181
 
7401
8182
  // src/rules/types/types-unknown.ts
7402
- import { defineRule as defineRule70 } from "@oxlint/plugins";
8183
+ import { defineRule as defineRule76 } from "@oxlint/plugins";
7403
8184
  function isCatchName(node) {
7404
8185
  const key = "key" in node && !(("computed" in node) && node.computed) ? node.key : undefined;
7405
8186
  return key?.type === "Identifier" && key.name === "catch";
7406
8187
  }
7407
- var typesUnknown = defineRule70({
8188
+ var typesUnknown = defineRule76({
7408
8189
  meta: { type: "problem", schema: [], messages: { forbidden: "Use an owned domain type rather than unknown." } },
7409
8190
  createOnce(context) {
7410
8191
  return {
@@ -7459,6 +8240,11 @@ var src_default = eslintCompatPlugin({
7459
8240
  "comments-code": commentsCode,
7460
8241
  "comments-directives": commentsDirectives,
7461
8242
  "copy-dashes": copyDashes,
8243
+ "effect-layer-file": effectLayerFile,
8244
+ "effect-layers": effectLayers,
8245
+ "effect-merge-pipe": effectMergePipe,
8246
+ "effect-schema-first": effectSchemaFirst,
8247
+ "effect-values-first": effectValuesFirst,
7462
8248
  "files-components-only": filesComponentsOnly,
7463
8249
  "files-constants-only": filesConstantsOnly,
7464
8250
  "files-domain-constants": filesDomainConstants,
@@ -7500,6 +8286,7 @@ var src_default = eslintCompatPlugin({
7500
8286
  "tests-modifiers": testsModifiers,
7501
8287
  "tests-titles": testsTitles,
7502
8288
  "types-declarations": typesDeclarations,
8289
+ "types-duplicate": typesDuplicate,
7503
8290
  "types-imported-alias": typesImportedAlias,
7504
8291
  "types-inline": typesInline,
7505
8292
  "types-local-alias": typesLocalAlias,