@fictjs/eslint-plugin 0.0.13 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  default: () => index_default,
24
+ noComputedPropsKey: () => no_computed_props_key_default,
24
25
  noDirectMutation: () => no_direct_mutation_default,
25
26
  noEmptyEffect: () => no_empty_effect_default,
26
27
  noInlineFunctions: () => no_inline_functions_default,
@@ -29,13 +30,49 @@ __export(index_exports, {
29
30
  noStateDestructureWrite: () => no_state_destructure_write_default,
30
31
  noStateInLoop: () => no_state_in_loop_default,
31
32
  noStateOutsideComponent: () => no_state_outside_component_default,
33
+ noThirdPartyPropsSpread: () => no_third_party_props_spread_default,
34
+ noUnsafePropsSpread: () => no_unsafe_props_spread_default,
35
+ noUnsupportedPropsDestructure: () => no_unsupported_props_destructure_default,
32
36
  requireComponentReturn: () => require_component_return_default,
33
37
  requireListKey: () => require_list_key_default
34
38
  });
35
39
  module.exports = __toCommonJS(index_exports);
36
40
 
37
- // src/rules/no-direct-mutation.ts
41
+ // src/rules/no-computed-props-key.ts
38
42
  var rule = {
43
+ meta: {
44
+ type: "suggestion",
45
+ docs: {
46
+ description: "Disallow computed keys in JSX props object spreads",
47
+ recommended: true
48
+ },
49
+ messages: {
50
+ computedKey: "Computed props key may break fine-grained reactivity; use explicit props."
51
+ },
52
+ schema: []
53
+ },
54
+ create(context) {
55
+ return {
56
+ JSXSpreadAttribute(node) {
57
+ const expr = node.argument;
58
+ if (!expr || expr.type !== "ObjectExpression") return;
59
+ for (const prop of expr.properties ?? []) {
60
+ if (prop.type === "Property" && prop.computed) {
61
+ context.report({
62
+ node: prop,
63
+ messageId: "computedKey"
64
+ });
65
+ return;
66
+ }
67
+ }
68
+ }
69
+ };
70
+ }
71
+ };
72
+ var no_computed_props_key_default = rule;
73
+
74
+ // src/rules/no-direct-mutation.ts
75
+ var rule2 = {
39
76
  meta: {
40
77
  type: "suggestion",
41
78
  docs: {
@@ -87,10 +124,10 @@ function isDeepAccess(node) {
87
124
  }
88
125
  return depth > 1;
89
126
  }
90
- var no_direct_mutation_default = rule;
127
+ var no_direct_mutation_default = rule2;
91
128
 
92
129
  // src/rules/no-empty-effect.ts
93
- var rule2 = {
130
+ var rule3 = {
94
131
  meta: {
95
132
  type: "suggestion",
96
133
  docs: {
@@ -215,10 +252,10 @@ var rule2 = {
215
252
  };
216
253
  }
217
254
  };
218
- var no_empty_effect_default = rule2;
255
+ var no_empty_effect_default = rule3;
219
256
 
220
257
  // src/rules/no-inline-functions.ts
221
- var rule3 = {
258
+ var rule4 = {
222
259
  meta: {
223
260
  type: "suggestion",
224
261
  docs: {
@@ -268,10 +305,10 @@ var rule3 = {
268
305
  };
269
306
  }
270
307
  };
271
- var no_inline_functions_default = rule3;
308
+ var no_inline_functions_default = rule4;
272
309
 
273
310
  // src/rules/no-memo-side-effects.ts
274
- var rule4 = {
311
+ var rule5 = {
275
312
  meta: {
276
313
  type: "problem",
277
314
  docs: {
@@ -331,10 +368,10 @@ var rule4 = {
331
368
  };
332
369
  }
333
370
  };
334
- var no_memo_side_effects_default = rule4;
371
+ var no_memo_side_effects_default = rule5;
335
372
 
336
373
  // src/rules/no-nested-components.ts
337
- var rule5 = {
374
+ var rule6 = {
338
375
  meta: {
339
376
  type: "problem",
340
377
  docs: {
@@ -425,66 +462,7 @@ var rule5 = {
425
462
  };
426
463
  }
427
464
  };
428
- var no_nested_components_default = rule5;
429
-
430
- // src/rules/no-state-in-loop.ts
431
- var rule6 = {
432
- meta: {
433
- type: "problem",
434
- docs: {
435
- description: "Disallow $state declarations inside loops",
436
- recommended: true
437
- },
438
- messages: {
439
- noStateInLoop: "$state should not be declared inside a loop. Move it outside the loop."
440
- },
441
- schema: []
442
- },
443
- create(context) {
444
- let loopDepth = 0;
445
- return {
446
- ForStatement() {
447
- loopDepth++;
448
- },
449
- "ForStatement:exit"() {
450
- loopDepth--;
451
- },
452
- ForInStatement() {
453
- loopDepth++;
454
- },
455
- "ForInStatement:exit"() {
456
- loopDepth--;
457
- },
458
- ForOfStatement() {
459
- loopDepth++;
460
- },
461
- "ForOfStatement:exit"() {
462
- loopDepth--;
463
- },
464
- WhileStatement() {
465
- loopDepth++;
466
- },
467
- "WhileStatement:exit"() {
468
- loopDepth--;
469
- },
470
- DoWhileStatement() {
471
- loopDepth++;
472
- },
473
- "DoWhileStatement:exit"() {
474
- loopDepth--;
475
- },
476
- CallExpression(node) {
477
- if (loopDepth > 0 && node.callee.type === "Identifier" && node.callee.name === "$state") {
478
- context.report({
479
- node,
480
- messageId: "noStateInLoop"
481
- });
482
- }
483
- }
484
- };
485
- }
486
- };
487
- var no_state_in_loop_default = rule6;
465
+ var no_nested_components_default = rule6;
488
466
 
489
467
  // src/rules/no-state-destructure-write.ts
490
468
  var rule7 = {
@@ -576,6 +554,65 @@ var rule7 = {
576
554
  };
577
555
  var no_state_destructure_write_default = rule7;
578
556
 
557
+ // src/rules/no-state-in-loop.ts
558
+ var rule8 = {
559
+ meta: {
560
+ type: "problem",
561
+ docs: {
562
+ description: "Disallow $state declarations inside loops",
563
+ recommended: true
564
+ },
565
+ messages: {
566
+ noStateInLoop: "$state should not be declared inside a loop. Move it outside the loop."
567
+ },
568
+ schema: []
569
+ },
570
+ create(context) {
571
+ let loopDepth = 0;
572
+ return {
573
+ ForStatement() {
574
+ loopDepth++;
575
+ },
576
+ "ForStatement:exit"() {
577
+ loopDepth--;
578
+ },
579
+ ForInStatement() {
580
+ loopDepth++;
581
+ },
582
+ "ForInStatement:exit"() {
583
+ loopDepth--;
584
+ },
585
+ ForOfStatement() {
586
+ loopDepth++;
587
+ },
588
+ "ForOfStatement:exit"() {
589
+ loopDepth--;
590
+ },
591
+ WhileStatement() {
592
+ loopDepth++;
593
+ },
594
+ "WhileStatement:exit"() {
595
+ loopDepth--;
596
+ },
597
+ DoWhileStatement() {
598
+ loopDepth++;
599
+ },
600
+ "DoWhileStatement:exit"() {
601
+ loopDepth--;
602
+ },
603
+ CallExpression(node) {
604
+ if (loopDepth > 0 && node.callee.type === "Identifier" && node.callee.name === "$state") {
605
+ context.report({
606
+ node,
607
+ messageId: "noStateInLoop"
608
+ });
609
+ }
610
+ }
611
+ };
612
+ }
613
+ };
614
+ var no_state_in_loop_default = rule8;
615
+
579
616
  // src/rules/no-state-outside-component.ts
580
617
  var isUpperCaseName = (name) => !!name && /^[A-Z]/.test(name);
581
618
  var isHookName = (name) => !!name && /^use[A-Z]/.test(name);
@@ -637,7 +674,13 @@ var isInConditional = (ancestors) => ancestors.some(
637
674
  "LogicalExpression"
638
675
  ].includes(ancestor.type)
639
676
  );
640
- var rule8 = {
677
+ var isDirectStateDeclaration = (node, ancestors) => {
678
+ const parent = ancestors[ancestors.length - 1];
679
+ if (!parent || parent.type !== "VariableDeclarator") return false;
680
+ if (parent.init !== node) return false;
681
+ return parent.id?.type === "Identifier";
682
+ };
683
+ var rule9 = {
641
684
  meta: {
642
685
  type: "problem",
643
686
  docs: {
@@ -647,7 +690,8 @@ var rule8 = {
647
690
  messages: {
648
691
  moduleScope: "$state must be declared inside a component or hook function body (not at module scope).",
649
692
  componentOnly: "$state should only be used inside a component function (PascalCase or JSX-returning) or a hook (useX).",
650
- topLevel: "$state must be at the top level of the component or hook body (not inside conditionals or nested functions)."
693
+ topLevel: "$state must be at the top level of the component or hook body (not inside conditionals or nested functions).",
694
+ declarationOnly: "$state() must be assigned directly to a variable (e.g. let count = $state(0))."
651
695
  },
652
696
  schema: []
653
697
  },
@@ -656,6 +700,10 @@ var rule8 = {
656
700
  CallExpression(node) {
657
701
  if (node.callee.type !== "Identifier" || node.callee.name !== "$state") return;
658
702
  const ancestors = context.sourceCode.getAncestors(node);
703
+ if (!isDirectStateDeclaration(node, ancestors)) {
704
+ context.report({ node, messageId: "declarationOnly" });
705
+ return;
706
+ }
659
707
  const functionAncestors = ancestors.filter(
660
708
  (ancestor) => ["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"].includes(
661
709
  ancestor.type
@@ -681,10 +729,358 @@ var rule8 = {
681
729
  };
682
730
  }
683
731
  };
684
- var no_state_outside_component_default = rule8;
732
+ var no_state_outside_component_default = rule9;
733
+
734
+ // src/rules/no-third-party-props-spread.ts
735
+ var rule10 = {
736
+ meta: {
737
+ type: "suggestion",
738
+ docs: {
739
+ description: "Warn on third-party object spreads in JSX props",
740
+ recommended: true
741
+ },
742
+ messages: {
743
+ thirdPartySpread: "Spreading third-party objects into props may hide reactive changes; prefer explicit props or map fields."
744
+ },
745
+ schema: [
746
+ {
747
+ type: "object",
748
+ properties: {
749
+ includeCallExpressions: {
750
+ type: "boolean",
751
+ description: "Also warn when JSX spread comes from a third-party call expression."
752
+ },
753
+ allow: {
754
+ type: "array",
755
+ items: { type: "string" },
756
+ description: "Module specifiers to treat as internal."
757
+ },
758
+ internalPrefixes: {
759
+ type: "array",
760
+ items: { type: "string" },
761
+ description: 'Import path prefixes to treat as internal (e.g. "@/", "~/" ).'
762
+ }
763
+ },
764
+ additionalProperties: false
765
+ }
766
+ ]
767
+ },
768
+ create(context) {
769
+ const options = context.options[0] || {};
770
+ const allow = new Set(options.allow ?? []);
771
+ const internalPrefixes = options.internalPrefixes ?? [];
772
+ const includeCallExpressions = options.includeCallExpressions === true;
773
+ const thirdPartyImports = /* @__PURE__ */ new Set();
774
+ const isThirdPartySource = (source) => {
775
+ if (allow.has(source)) return false;
776
+ if (source.startsWith(".") || source.startsWith("/")) return false;
777
+ if (internalPrefixes.some((prefix) => source.startsWith(prefix))) return false;
778
+ return true;
779
+ };
780
+ const isComponentName = (name) => {
781
+ if (name.type === "JSXIdentifier") {
782
+ return /^[A-Z]/.test(name.name);
783
+ }
784
+ if (name.type === "JSXMemberExpression") {
785
+ return true;
786
+ }
787
+ return false;
788
+ };
789
+ const unwrapExpression = (expr) => {
790
+ let current = expr;
791
+ while (current) {
792
+ if (current.type === "ChainExpression") {
793
+ current = current.expression;
794
+ continue;
795
+ }
796
+ if (current.type === "TSAsExpression" || current.type === "TSTypeAssertion" || current.type === "TSNonNullExpression") {
797
+ current = current.expression;
798
+ continue;
799
+ }
800
+ break;
801
+ }
802
+ return current;
803
+ };
804
+ const getRootIdentifierName = (expr) => {
805
+ let current = unwrapExpression(expr);
806
+ while (current) {
807
+ if (current.type === "Identifier") return current.name;
808
+ if (current.type === "MemberExpression" || current.type === "OptionalMemberExpression") {
809
+ current = unwrapExpression(current.object);
810
+ continue;
811
+ }
812
+ if (includeCallExpressions && (current.type === "CallExpression" || current.type === "OptionalCallExpression")) {
813
+ current = unwrapExpression(current.callee);
814
+ continue;
815
+ }
816
+ return null;
817
+ }
818
+ return null;
819
+ };
820
+ return {
821
+ ImportDeclaration(node) {
822
+ if (!node.source?.value || typeof node.source.value !== "string") return;
823
+ if (!isThirdPartySource(node.source.value)) return;
824
+ for (const spec of node.specifiers ?? []) {
825
+ if (spec.local?.name) {
826
+ thirdPartyImports.add(spec.local.name);
827
+ }
828
+ }
829
+ },
830
+ JSXOpeningElement(node) {
831
+ if (!isComponentName(node.name)) return;
832
+ for (const attr of node.attributes ?? []) {
833
+ if (attr.type !== "JSXSpreadAttribute") continue;
834
+ const expr = attr.argument;
835
+ if (!expr) continue;
836
+ if (expr.type === "CallExpression" && expr.callee?.type === "Identifier" && expr.callee.name === "mergeProps") {
837
+ continue;
838
+ }
839
+ const root = getRootIdentifierName(expr);
840
+ if (root && thirdPartyImports.has(root)) {
841
+ context.report({
842
+ node: attr,
843
+ messageId: "thirdPartySpread"
844
+ });
845
+ }
846
+ }
847
+ }
848
+ };
849
+ }
850
+ };
851
+ var no_third_party_props_spread_default = rule10;
852
+
853
+ // src/rules/no-unsafe-props-spread.ts
854
+ var rule11 = {
855
+ meta: {
856
+ type: "suggestion",
857
+ docs: {
858
+ description: "Warn on JSX spread sources that are too dynamic to keep props reactive",
859
+ recommended: true
860
+ },
861
+ messages: {
862
+ unsafeSpread: "JSX spread source is too dynamic to keep props reactive. Consider passing explicit props or using mergeProps(() => source)."
863
+ },
864
+ schema: [
865
+ {
866
+ type: "object",
867
+ properties: {
868
+ accessorNames: {
869
+ type: "array",
870
+ items: { type: "string" },
871
+ description: "Identifier names to treat as accessor functions."
872
+ },
873
+ accessorModules: {
874
+ type: "array",
875
+ items: { type: "string" },
876
+ description: "Module specifiers whose imports are accessor functions."
877
+ }
878
+ },
879
+ additionalProperties: false
880
+ }
881
+ ]
882
+ },
883
+ create(context) {
884
+ const options = context.options[0] || {};
885
+ const accessorVars = new Set(options.accessorNames ?? []);
886
+ const accessorModules = new Set(options.accessorModules ?? []);
887
+ const isComponentName = (name) => {
888
+ if (name.type === "JSXIdentifier") {
889
+ return /^[A-Z]/.test(name.name);
890
+ }
891
+ if (name.type === "JSXMemberExpression") {
892
+ return true;
893
+ }
894
+ return false;
895
+ };
896
+ const recordAccessorVar = (node) => {
897
+ if (!node.init || node.id?.type !== "Identifier") return;
898
+ if (node.init.type !== "CallExpression") return;
899
+ if (node.init.callee?.type !== "Identifier") return;
900
+ const callee = node.init.callee.name;
901
+ if (callee === "$state" || callee === "$memo" || callee === "prop") {
902
+ accessorVars.add(node.id.name);
903
+ }
904
+ };
905
+ const isSafeAccessorExpr = (expr) => {
906
+ if (expr.type === "Identifier") return true;
907
+ if (expr.type === "CallExpression" && expr.callee?.type === "Identifier" && expr.arguments.length === 0 && accessorVars.has(expr.callee.name)) {
908
+ return true;
909
+ }
910
+ return false;
911
+ };
912
+ const isObviouslyDynamic = (expr) => expr.type === "ConditionalExpression" || expr.type === "LogicalExpression" || expr.type === "SequenceExpression" || expr.type === "AssignmentExpression" || expr.type === "UpdateExpression" || expr.type === "AwaitExpression" || expr.type === "NewExpression" || expr.type === "YieldExpression";
913
+ const hasUnsafeObjectLiteral = (obj) => {
914
+ for (const prop of obj.properties ?? []) {
915
+ if (prop.type === "SpreadElement") return true;
916
+ if (prop.type === "Property") {
917
+ if (prop.computed) return true;
918
+ if (prop.kind === "get" || prop.kind === "set") return true;
919
+ }
920
+ }
921
+ return false;
922
+ };
923
+ const shouldWarnForSpreadExpr = (expr) => {
924
+ if (isSafeAccessorExpr(expr)) return false;
925
+ if (expr.type === "CallExpression" && expr.callee?.type === "Identifier" && expr.callee.name === "mergeProps") {
926
+ return false;
927
+ }
928
+ if (expr.type === "ObjectExpression") {
929
+ return hasUnsafeObjectLiteral(expr);
930
+ }
931
+ if (isObviouslyDynamic(expr)) return true;
932
+ if (expr.type === "CallExpression") return true;
933
+ if (expr.type === "MemberExpression") return true;
934
+ return false;
935
+ };
936
+ return {
937
+ ImportDeclaration(node) {
938
+ if (!node.source?.value || typeof node.source.value !== "string") return;
939
+ if (!accessorModules.has(node.source.value)) return;
940
+ for (const spec of node.specifiers ?? []) {
941
+ if (spec.local?.name) {
942
+ accessorVars.add(spec.local.name);
943
+ }
944
+ }
945
+ },
946
+ VariableDeclarator: recordAccessorVar,
947
+ JSXOpeningElement(node) {
948
+ if (!isComponentName(node.name)) return;
949
+ for (const attr of node.attributes ?? []) {
950
+ if (attr.type !== "JSXSpreadAttribute") continue;
951
+ const expr = attr.argument;
952
+ if (!expr) continue;
953
+ if (shouldWarnForSpreadExpr(expr)) {
954
+ context.report({
955
+ node: attr,
956
+ messageId: "unsafeSpread"
957
+ });
958
+ }
959
+ }
960
+ }
961
+ };
962
+ }
963
+ };
964
+ var no_unsafe_props_spread_default = rule11;
965
+
966
+ // src/rules/no-unsupported-props-destructure.ts
967
+ var rule12 = {
968
+ meta: {
969
+ type: "suggestion",
970
+ docs: {
971
+ description: "Warn on unsupported props destructuring patterns in components",
972
+ recommended: true
973
+ },
974
+ messages: {
975
+ computedKey: "Computed property in props pattern cannot be made reactive.",
976
+ arrayRest: "Array rest in props destructuring falls back to non-reactive binding.",
977
+ nestedRest: "Nested props rest destructuring falls back to non-reactive binding; access props directly or use prop.",
978
+ nonFirstParam: "Props destructuring is only supported in the first parameter.",
979
+ fallback: "Props destructuring falls back to non-reactive binding."
980
+ },
981
+ schema: []
982
+ },
983
+ create(context) {
984
+ const isComponentName = (name) => /^[A-Z]/.test(name);
985
+ const getPropsPattern = (fnNode) => {
986
+ const params = fnNode?.params ?? [];
987
+ const first = params[0];
988
+ if (params.length > 1) {
989
+ params.slice(1).forEach((param) => {
990
+ if (!param) return;
991
+ const target = param.type === "AssignmentPattern" ? param.left : param;
992
+ if (target?.type === "ObjectPattern" || target?.type === "ArrayPattern") {
993
+ context.report({
994
+ node: target,
995
+ messageId: "nonFirstParam"
996
+ });
997
+ }
998
+ });
999
+ }
1000
+ if (!first) return null;
1001
+ if (first.type === "ObjectPattern") return first;
1002
+ if (first.type === "AssignmentPattern" && first.left?.type === "ObjectPattern") {
1003
+ return first.left;
1004
+ }
1005
+ if (first.type === "ArrayPattern") {
1006
+ context.report({
1007
+ node: first,
1008
+ messageId: "fallback"
1009
+ });
1010
+ return null;
1011
+ }
1012
+ return null;
1013
+ };
1014
+ const reportOnce = (node, messageId) => {
1015
+ context.report({
1016
+ node,
1017
+ messageId
1018
+ });
1019
+ };
1020
+ const walkPattern = (pattern, depth) => {
1021
+ if (!pattern) return;
1022
+ if (pattern.type === "ObjectPattern") {
1023
+ for (const prop of pattern.properties ?? []) {
1024
+ if (prop.type === "RestElement") {
1025
+ if (depth > 0) {
1026
+ reportOnce(prop, "nestedRest");
1027
+ }
1028
+ continue;
1029
+ }
1030
+ if (prop.type !== "Property") {
1031
+ reportOnce(prop, "fallback");
1032
+ continue;
1033
+ }
1034
+ if (prop.computed) {
1035
+ reportOnce(prop, "computedKey");
1036
+ continue;
1037
+ }
1038
+ const value = prop.value;
1039
+ if (value.type === "Identifier") {
1040
+ continue;
1041
+ }
1042
+ if (value.type === "AssignmentPattern" && value.left?.type === "Identifier") {
1043
+ continue;
1044
+ }
1045
+ if (value.type === "ObjectPattern") {
1046
+ walkPattern(value, depth + 1);
1047
+ continue;
1048
+ }
1049
+ if (value.type === "ArrayPattern") {
1050
+ const hasRest = (value.elements ?? []).some((el) => el?.type === "RestElement");
1051
+ reportOnce(value, hasRest ? "arrayRest" : "fallback");
1052
+ continue;
1053
+ }
1054
+ reportOnce(value, "fallback");
1055
+ }
1056
+ return;
1057
+ }
1058
+ if (pattern.type === "ArrayPattern") {
1059
+ reportOnce(pattern, "fallback");
1060
+ }
1061
+ };
1062
+ return {
1063
+ FunctionDeclaration(node) {
1064
+ if (!node.id?.name || !isComponentName(node.id.name)) return;
1065
+ const pattern = getPropsPattern(node);
1066
+ if (pattern) walkPattern(pattern, 0);
1067
+ },
1068
+ VariableDeclarator(node) {
1069
+ if (!node.id || node.id.type !== "Identifier" || !isComponentName(node.id.name)) return;
1070
+ if (!node.init) return;
1071
+ if (node.init.type !== "ArrowFunctionExpression" && node.init.type !== "FunctionExpression") {
1072
+ return;
1073
+ }
1074
+ const pattern = getPropsPattern(node.init);
1075
+ if (pattern) walkPattern(pattern, 0);
1076
+ }
1077
+ };
1078
+ }
1079
+ };
1080
+ var no_unsupported_props_destructure_default = rule12;
685
1081
 
686
1082
  // src/rules/require-component-return.ts
687
- var rule9 = {
1083
+ var rule13 = {
688
1084
  meta: {
689
1085
  type: "problem",
690
1086
  docs: {
@@ -772,10 +1168,10 @@ var rule9 = {
772
1168
  };
773
1169
  }
774
1170
  };
775
- var require_component_return_default = rule9;
1171
+ var require_component_return_default = rule13;
776
1172
 
777
1173
  // src/rules/require-list-key.ts
778
- var rule10 = {
1174
+ var rule14 = {
779
1175
  meta: {
780
1176
  type: "problem",
781
1177
  docs: {
@@ -866,7 +1262,7 @@ var rule10 = {
866
1262
  };
867
1263
  }
868
1264
  };
869
- var require_list_key_default = rule10;
1265
+ var require_list_key_default = rule14;
870
1266
 
871
1267
  // src/index.ts
872
1268
  var plugin = {
@@ -878,10 +1274,14 @@ var plugin = {
878
1274
  "no-state-in-loop": no_state_in_loop_default,
879
1275
  "no-direct-mutation": no_direct_mutation_default,
880
1276
  "no-empty-effect": no_empty_effect_default,
1277
+ "no-computed-props-key": no_computed_props_key_default,
881
1278
  "no-inline-functions": no_inline_functions_default,
882
1279
  "no-state-destructure-write": no_state_destructure_write_default,
883
1280
  "no-state-outside-component": no_state_outside_component_default,
884
1281
  "no-nested-components": no_nested_components_default,
1282
+ "no-third-party-props-spread": no_third_party_props_spread_default,
1283
+ "no-unsafe-props-spread": no_unsafe_props_spread_default,
1284
+ "no-unsupported-props-destructure": no_unsupported_props_destructure_default,
885
1285
  "require-list-key": require_list_key_default,
886
1286
  "no-memo-side-effects": no_memo_side_effects_default,
887
1287
  "require-component-return": require_component_return_default
@@ -894,12 +1294,16 @@ var plugin = {
894
1294
  "fict/no-direct-mutation": "warn",
895
1295
  "fict/no-empty-effect": "warn",
896
1296
  // FICT-E001
1297
+ "fict/no-computed-props-key": "warn",
897
1298
  "fict/no-inline-functions": "warn",
898
1299
  // FICT-X003
899
1300
  "fict/no-state-destructure-write": "error",
900
1301
  "fict/no-state-outside-component": "error",
901
1302
  "fict/no-nested-components": "error",
902
1303
  // FICT-C003
1304
+ "fict/no-third-party-props-spread": "warn",
1305
+ "fict/no-unsafe-props-spread": "warn",
1306
+ "fict/no-unsupported-props-destructure": "warn",
903
1307
  "fict/require-list-key": "error",
904
1308
  // FICT-J002
905
1309
  "fict/no-memo-side-effects": "warn",
@@ -913,6 +1317,7 @@ var plugin = {
913
1317
  var index_default = plugin;
914
1318
  // Annotate the CommonJS export names for ESM import in node:
915
1319
  0 && (module.exports = {
1320
+ noComputedPropsKey,
916
1321
  noDirectMutation,
917
1322
  noEmptyEffect,
918
1323
  noInlineFunctions,
@@ -921,6 +1326,9 @@ var index_default = plugin;
921
1326
  noStateDestructureWrite,
922
1327
  noStateInLoop,
923
1328
  noStateOutsideComponent,
1329
+ noThirdPartyPropsSpread,
1330
+ noUnsafePropsSpread,
1331
+ noUnsupportedPropsDestructure,
924
1332
  requireComponentReturn,
925
1333
  requireListKey
926
1334
  });