@deslop/coding-standards 0.1.1082 → 0.1.1085

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/oxlint.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as prepend, $t as strictEqual, A as filter$1, Ar as isString, At as getOrUndefined, B as getSomes, Bt as zipWith, C as contains$1, Cr as isNullish$1, Ct as filter, D as empty, Dt as fromNullishOr, E as dedupeWith, Et as flatten$1, F as flatMap$1, Ft as match, Gn as NodeInspectSymbol, H as isArrayEmpty, I as flatten, It as none, K as join, Kr as pipeArguments, L as forEach, Lr as constVoid, Lt as orElse, M as findFirst, Mt as isSome, N as findFirstIndex, O as ensure, Or as isReadonlyObject, Ot as fromUndefinedOr, Pr as constFalse, Pt as map, Q as of, Rt as some, S as appendAll, St as exists, T as dedupe, Tt as flatMap, U as isArrayNonEmpty, Ur as pipe, V as head, Y as map$1, Z as matchRight, at as get$2, bt as all, c as make$3, cr as number, ct as remove, d as includes, f as match$1, ft as fromOption, g as trim, gr as isBoolean, h as startsWith, ir as symbol, it as fromEntries, j as filterMap, k as every, kr as isRegExp, kt as getOrElse, l as update, lr as optimize, lt as values, m as split, mr as hasProperty, nr as byReferenceUnsafe, nt as sort, o as toArray, or as combine, p as replaceAll, pr as symbol$1, q as last, r as make$2, rr as equals, rt as take, s as get$3, sr as hash, t as append$1, tt as some$1, u as Order, ur as string, w as containsWith, wr as isNumber, wt as firstSomeOf, x as append, xr as isNotNullish, xt as contains, y as TaggedError, z as get$1, zr as dual, zt as toArray$1 } from "./MutableList-BCF17jPH.mjs";
1
+ import { $ as last, $r as pipeArguments, A as dedupe, Ar as isNullish$1, At as filter, Cr as isBoolean, D as appendAll, Dr as isNotNull, Dt as all, E as append, F as every, Fr as isReadonlyObject, Ft as fromUndefinedOr, G as get$1, Gt as some, H as flatten, Ht as match, I as filter$1, Ir as isRegExp, It as getOrElse, J as isArrayEmpty, K as getSomes, Kr as dual, Kt as toArray$1, L as filterMap, Lr as isString, Lt as getOrUndefined, M as dropRight, Mt as flatMap, N as empty, Nt as flatten$1, O as contains, Or as isNotNullish, Ot as contains$1, P as ensure, Pt as fromNullishOr, Q as join, Qn as NodeInspectSymbol, R as findFirst, Rt as isNone, U as forEach, Ut as none, V as flatMap$1, Vr as constFalse, Vt as map, Wr as constVoid, Wt as orElse, Xr as pipe, Y as isArrayNonEmpty, Z as isReadonlyArrayNonEmpty, _ as startsWith, _r as string, at as prepend, br as symbol$1, c as make$3, ct as sort, d as Order, dr as symbol, dt as fromEntries, f as includes, ft as get$2, g as split, gr as optimize, gt as values, h as replaceAll, hr as number, ht as remove, it as of, j as dedupeWith, jr as isNumber, jt as firstSomeOf, k as containsWith, kt as exists, l as update, lr as byReferenceUnsafe, lt as take, m as replace, mr as hash, o as toArray, on as strictEqual, p as match$1, pr as combine, q as head, qt as zipWith, r as make$2, rt as matchRight, s as get$3, st as some$1, t as append$1, tt as map$1, u as match$2, ur as equals, ut as takeWhile, v as toUpperCase, w as TaggedError, x as parse, xr as hasProperty, y as trim, yt as fromOption, z as findFirstIndex, zt as isSome } from "./MutableList-NTBI6AHW.mjs";
2
2
  //#region ../../node_modules/.pnpm/effect@4.0.5/node_modules/effect/dist/internal/graph.js
3
3
  /** @internal */
4
4
  const TypeId = "~effect/Graph";
@@ -633,6 +633,28 @@ function defineConfig(config) {
633
633
  }
634
634
  //#endregion
635
635
  //#region src/rules/shared.ts
636
+ function inert(token) {
637
+ if (contains([
638
+ "Boolean",
639
+ "Identifier",
640
+ "Null",
641
+ "Numeric",
642
+ "String"
643
+ ], token.type)) return true;
644
+ if (token.type === "Keyword") return contains([
645
+ "const",
646
+ "new",
647
+ "return"
648
+ ], token.value);
649
+ return token.type === "Punctuator" && contains([
650
+ "(",
651
+ ",",
652
+ ":",
653
+ "=",
654
+ "[",
655
+ "{"
656
+ ], token.value);
657
+ }
636
658
  function variableFromScope(input) {
637
659
  if (input.scope === null) return none();
638
660
  const scope = input.scope;
@@ -690,7 +712,7 @@ function importedMember(input) {
690
712
  importedName: input.importedName,
691
713
  node: input.node.object,
692
714
  source: "effect"
693
- }) && (input.propertyName === void 0 || contains(memberName(input.node), input.propertyName));
715
+ }) && (input.propertyName === void 0 || contains$1(memberName(input.node), input.propertyName));
694
716
  }
695
717
  function matches(regExp) {
696
718
  return (text) => isSome(pipe(text, match$1(regExp)));
@@ -711,7 +733,7 @@ function isReactUseState(input) {
711
733
  node: input.node.callee,
712
734
  source: "react"
713
735
  });
714
- return input.node.callee.type === "MemberExpression" && contains(memberName(input.node.callee), "useState") && input.node.callee.object.type === "Identifier" && isNamespaceImport({
736
+ return input.node.callee.type === "MemberExpression" && contains$1(memberName(input.node.callee), "useState") && input.node.callee.object.type === "Identifier" && isNamespaceImport({
715
737
  context: input.context,
716
738
  node: input.node.callee.object,
717
739
  source: "react"
@@ -868,7 +890,7 @@ function schemaCycleNames(input) {
868
890
  const indices = fromEntries(map$1(names, (name) => [name, addNode(mutable, name)]));
869
891
  for (const edge of edges) for (const target of edge.targets) zipWith(get$2(indices, edge.name), get$2(indices, target), (source, sink) => addEdge(mutable, source, sink, "reads"));
870
892
  });
871
- return pipe(stronglyConnectedComponents(graph), map$1((component) => getSomes(map$1(component, (index) => getNode(graph, index)))), filter$1((component) => (component.length > 1 || some$1(edges, (edge) => contains$1(component, edge.name) && contains$1(edge.targets, edge.name))) && some$1(component, (name) => contains$1(seeds, name))), flatten);
893
+ return pipe(stronglyConnectedComponents(graph), map$1((component) => getSomes(map$1(component, (index) => getNode(graph, index)))), filter$1((component) => (component.length > 1 || some$1(edges, (edge) => contains(component, edge.name) && contains(edge.targets, edge.name))) && some$1(component, (name) => contains(seeds, name))), flatten);
872
894
  }
873
895
  function hasSingleStatementExpression(node) {
874
896
  if (node.body === null) return false;
@@ -890,9 +912,159 @@ function singleUseThunk(input) {
890
912
  })), exists((variable) => filter$1(variable.references, (reference) => reference.isRead()).length === 1));
891
913
  }
892
914
  //#endregion
915
+ //#region src/rules/explicit-effect-concurrency.ts
916
+ function statesConcurrency(node) {
917
+ if (node === void 0) return false;
918
+ if (node.type !== "ObjectExpression") return true;
919
+ return some$1(node.properties, (property) => property.type === "SpreadElement" || property.key.type === "Identifier" && property.key.name === "concurrency" || property.key.type === "Literal" && property.key.value === "concurrency");
920
+ }
921
+ function isFunction(node) {
922
+ return node?.type === "ArrowFunctionExpression" || node?.type === "FunctionExpression";
923
+ }
924
+ const explicitEffectConcurrency = defineRule({
925
+ create: (context) => ({ CallExpression: (node) => {
926
+ if (node.callee.type !== "MemberExpression" || !importedMember({
927
+ context,
928
+ importedName: "Effect",
929
+ node: node.callee
930
+ })) return;
931
+ const name = memberName(node.callee);
932
+ if (!exists(name, (method) => method === "all" || method === "forEach")) return;
933
+ const index = match$2(contains$1(name, "all") || isFunction(node.arguments[0]) || node.arguments[1]?.type === "ObjectExpression", {
934
+ onFalse: () => 2,
935
+ onTrue: () => 1
936
+ });
937
+ if (statesConcurrency(node.arguments[index])) return;
938
+ context.report({
939
+ message: "Choose the concurrency: {concurrency: 'unbounded'} for independent effects, {concurrency: 1} when order or a shared resource matters.",
940
+ node: node.callee
941
+ });
942
+ } }),
943
+ meta: { type: "problem" }
944
+ });
945
+ //#endregion
946
+ //#region src/rules/module-constant.ts
947
+ const isConstantName = matches(/^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$/u);
948
+ function literal(node) {
949
+ if (node.type === "Literal") return node.value !== null;
950
+ if (node.type === "TemplateLiteral") return isArrayEmpty(node.expressions);
951
+ if (node.type === "UnaryExpression") return node.operator === "-" && literal(node.argument);
952
+ if (node.type === "BinaryExpression") return literal(node.left) && literal(node.right);
953
+ if (node.type === "ArrayExpression") return every(node.elements, (element) => element !== null && element.type !== "SpreadElement" && literal(element));
954
+ if (node.type === "ObjectExpression") return every(node.properties, (property) => property.type === "Property" && !property.computed && property.kind === "init" && literal(property.value));
955
+ return pipe(typeWrapped(node), exists(literal));
956
+ }
957
+ function literalConstant(statement) {
958
+ if (statement.type !== "VariableDeclaration" || statement.kind !== "const" || statement.declarations.length !== 1) return none();
959
+ const [node] = statement.declarations;
960
+ if (node?.id.type !== "Identifier" || node.init === null || !literal(node.init)) return none();
961
+ return some({
962
+ id: node.id,
963
+ node
964
+ });
965
+ }
966
+ function renamed(input) {
967
+ if (input.reference.identifier.parent.type === "Property" && input.reference.identifier.parent.shorthand) return input.fixer.replaceText(input.reference.identifier, `${input.reference.identifier.name}: ${input.name}`);
968
+ return input.fixer.replaceText(input.reference.identifier, input.name);
969
+ }
970
+ function primitive(node) {
971
+ if (node.type === "Literal") return !hasProperty(node, "regex");
972
+ return contains([
973
+ "BinaryExpression",
974
+ "TemplateLiteral",
975
+ "UnaryExpression"
976
+ ], node.type) || pipe(typeWrapped(node), exists(primitive));
977
+ }
978
+ function check$2(input) {
979
+ if (input.found.id.typeAnnotation === null && input.found.node.init !== null && primitive(input.found.node.init) && filter$1(input.variable.references, (reference) => reference.isRead()).length === 1 && !pipe(input.context.sourceCode.getText(input.found.node), includes("\n"))) {
980
+ input.context.report({
981
+ message: "Inline this value at its only use.",
982
+ node: input.found.node
983
+ });
984
+ return;
985
+ }
986
+ if (!isConstantName(input.found.id.name)) {
987
+ const name = pipe(input.found.id.name, replaceAll(/(?<=[a-z0-9])(?=[A-Z])/gu, "_"), toUpperCase);
988
+ const taken = some$1([input.found.id, ...map$1(input.variable.references, (reference) => reference.identifier)], (node) => isSome(variableFromScope({
989
+ name,
990
+ scope: input.context.sourceCode.getScope(node)
991
+ })));
992
+ input.context.report({
993
+ fix: (fixer) => {
994
+ if (taken) return [];
995
+ return [fixer.replaceTextRange([input.found.id.range[0], input.found.id.range[0] + input.found.id.name.length], name), ...pipe(input.variable.references, filter$1((reference) => reference.identifier !== input.found.id), map$1((reference) => renamed({
996
+ fixer,
997
+ name,
998
+ reference
999
+ })))];
1000
+ },
1001
+ message: `Name this module constant ${name}.`,
1002
+ node: input.found.node
1003
+ });
1004
+ }
1005
+ if (!input.leading) input.context.report({
1006
+ message: "Declare this module constant directly under the imports.",
1007
+ node: input.found.node
1008
+ });
1009
+ }
1010
+ const moduleConstant = defineRule({
1011
+ create: (context) => ({ Program: (program) => {
1012
+ const leading = takeWhile(program.body, (statement) => statement.type === "ImportDeclaration" || isSome(literalConstant(statement)));
1013
+ for (const statement of program.body) pipe(literalConstant(statement), flatMap((found) => pipe(variableFromScope({
1014
+ name: found.id.name,
1015
+ scope: context.sourceCode.getScope(found.node)
1016
+ }), filter((variable) => !some$1(variable.references, (reference) => reference.identifier.parent.type === "ExportSpecifier")), map((variable) => ({
1017
+ found,
1018
+ variable
1019
+ })))), match({
1020
+ onNone: constVoid,
1021
+ onSome: (match) => check$2({
1022
+ ...match,
1023
+ context,
1024
+ leading: contains(leading, statement)
1025
+ })
1026
+ }));
1027
+ } }),
1028
+ meta: {
1029
+ fixable: "code",
1030
+ type: "suggestion"
1031
+ }
1032
+ });
1033
+ //#endregion
1034
+ //#region src/rules/motion-limits.ts
1035
+ function utility(token) {
1036
+ return pipe(token, split(":"), last, getOrElse(() => token), replace(/^!|!$/gu, ""));
1037
+ }
1038
+ function amount(token, pattern) {
1039
+ return pipe(utility(token), match$1(pattern), flatMap((match) => fromNullishOr(match[1])), map((value) => pipe(parse(value), getOrElse(() => 0))));
1040
+ }
1041
+ function violation(token) {
1042
+ if (exists(amount(token, /^duration-(\d+)$/u), (value) => value > 300)) return some("Keep a transition under 300 ms: duration-300 or less.");
1043
+ if (matches(/^zoom-(?:in|out)$/u)(utility(token)) || exists(amount(token, /^zoom-(?:in|out)-(\d+)$/u), (value) => value < 90)) return some("Enter from 0.9 scale or more: zoom-in-90 or zoom-in-95.");
1044
+ if (pipe(token, split(":"), dropRight(1), contains("starting")) && exists(amount(token, /^scale-(\d+)$/u), (value) => value < 90)) return some("Enter from 0.9 scale or more: starting:scale-90 or starting:scale-95.");
1045
+ return none();
1046
+ }
1047
+ function check$1(context, node, text) {
1048
+ pipe(split(text, /\s+/u), map$1(violation), getSomes, head, map((message) => context.report({
1049
+ message,
1050
+ node
1051
+ })));
1052
+ }
1053
+ const motionLimits = defineRule({
1054
+ create: (context) => ({
1055
+ Literal: (node) => {
1056
+ if (isString(node.value)) check$1(context, node, node.value);
1057
+ },
1058
+ TemplateElement: (node) => {
1059
+ check$1(context, node, node.value.raw);
1060
+ }
1061
+ }),
1062
+ meta: { type: "problem" }
1063
+ });
1064
+ //#endregion
893
1065
  //#region src/rules/no-array-wrap-ternary.ts
894
1066
  function testedValue(node) {
895
- if (node.type !== "CallExpression" || node.callee.type !== "MemberExpression" || node.callee.object.type !== "Identifier" || node.callee.object.name !== "Array" || !contains(memberName(node.callee), "isArray") || node.arguments.length !== 1) return none();
1067
+ if (node.type !== "CallExpression" || node.callee.type !== "MemberExpression" || node.callee.object.type !== "Identifier" || node.callee.object.name !== "Array" || !contains$1(memberName(node.callee), "isArray") || node.arguments.length !== 1) return none();
896
1068
  const argument = node.arguments[0];
897
1069
  if (argument?.type !== "Identifier" && argument?.type !== "MemberExpression") return none();
898
1070
  return some(argument);
@@ -937,6 +1109,63 @@ const noArrayWrapTernary = defineRule({
937
1109
  meta: { type: "problem" }
938
1110
  });
939
1111
  //#endregion
1112
+ //#region src/rules/no-barrel-module.ts
1113
+ const noBarrelModule = defineRule({
1114
+ create: (context) => ({
1115
+ ExportAllDeclaration: (node) => {
1116
+ context.report({
1117
+ message: "Import from the module that defines each name; never re-export a whole module.",
1118
+ node
1119
+ });
1120
+ },
1121
+ Program: (node) => {
1122
+ const statements = filter$1(node.body, (statement) => statement.type !== "ImportDeclaration");
1123
+ if (isArrayEmpty(statements) || !every(statements, (statement) => statement.type === "ExportNamedDeclaration" && statement.source !== null)) return;
1124
+ context.report({
1125
+ message: "Import from the defining modules instead of a file that only re-exports them.",
1126
+ node
1127
+ });
1128
+ }
1129
+ }),
1130
+ meta: { type: "problem" }
1131
+ });
1132
+ //#endregion
1133
+ //#region src/rules/no-compiler-opt-out.ts
1134
+ const noCompilerOptOut = defineRule({
1135
+ create: (context) => ({ ExpressionStatement: (node) => {
1136
+ if (node.directive !== "use no memo" && node.directive !== "use no forget") return;
1137
+ context.report({
1138
+ message: "Fix the code React Compiler rejects instead of opting the function out of compilation.",
1139
+ node
1140
+ });
1141
+ } }),
1142
+ meta: { type: "problem" }
1143
+ });
1144
+ //#endregion
1145
+ //#region src/rules/no-component-atom-allocation.ts
1146
+ const componentOrHook = matches(/^(?:[A-Z]|use[A-Z])/u);
1147
+ const readsOrWrites = matches(/^(?:is[A-Z]|get|set$|update$|modify$|refresh$|mount$|batch$|toStream)/u);
1148
+ function renderingFunction(node) {
1149
+ return pipe(fromNullishOr(node.parent), flatMap((parent) => {
1150
+ if ((parent.type === "FunctionDeclaration" || parent.type === "FunctionExpression" || parent.type === "ArrowFunctionExpression") && exists(bindingName(parent), componentOrHook)) return some(parent);
1151
+ return renderingFunction(parent);
1152
+ }));
1153
+ }
1154
+ const noComponentAtomAllocation = defineRule({
1155
+ create: (context) => ({ CallExpression: (node) => {
1156
+ if (node.callee.type !== "MemberExpression" || node.callee.object.type !== "Identifier" || node.callee.object.name !== "Atom" || !isImportBinding({
1157
+ context,
1158
+ node: node.callee.object,
1159
+ source: /reactivity|atom/u
1160
+ }) || exists(memberName(node.callee), readsOrWrites) || isNone(renderingFunction(node))) return;
1161
+ context.report({
1162
+ message: "Declare the atom at module level, or in Atom.family keyed by the prop; an atom made during render is a new atom on every render.",
1163
+ node
1164
+ });
1165
+ } }),
1166
+ meta: { type: "problem" }
1167
+ });
1168
+ //#endregion
940
1169
  //#region src/rules/no-constant-function.ts
941
1170
  function isConstantFunction(input) {
942
1171
  if (input.node.async || input.node.generator || isArrayNonEmpty(input.node.params) || isNotNullish(input.node.typeParameters)) return false;
@@ -986,7 +1215,7 @@ function isPipeCall(context, node) {
986
1215
  });
987
1216
  }
988
1217
  function enclosingPipes(context, node) {
989
- if (node.type === "Program" || contains$1([
1218
+ if (node.type === "Program" || contains([
990
1219
  "ArrowFunctionExpression",
991
1220
  "FunctionDeclaration",
992
1221
  "FunctionExpression"
@@ -1007,7 +1236,7 @@ const noDeepPipe = defineRule({
1007
1236
  //#endregion
1008
1237
  //#region src/rules/no-destructured-parameter.ts
1009
1238
  function namedTuple(input) {
1010
- if (contains$1(input.seen, input.node)) return false;
1239
+ if (contains(input.seen, input.node)) return false;
1011
1240
  if (input.node.type === "TSTupleType") return isArrayNonEmpty(input.node.elementTypes) && every(input.node.elementTypes, (element) => element.type === "TSNamedTupleMember");
1012
1241
  if (input.node.type === "TSParenthesizedType" || input.node.type === "TSTypeOperator" && input.node.operator === "readonly") return namedTuple({
1013
1242
  ...input,
@@ -1081,6 +1310,9 @@ const noDestructuredParameter = defineRule({
1081
1310
  });
1082
1311
  //#endregion
1083
1312
  //#region src/rules/no-discarded-failure.ts
1313
+ function logged(node) {
1314
+ return node.parent.type === "CallExpression" && node.parent.callee === node && some$1(node.parent.arguments, (argument) => argument.type === "ObjectExpression" && every(argument.properties, (property) => property.type === "Property") && some$1(argument.properties, (property) => !property.computed && (property.key.type === "Identifier" && property.key.name === "log" || property.key.type === "Literal" && property.key.value === "log") && property.value.type === "Literal" && (property.value.value === true || isString(property.value.value))));
1315
+ }
1084
1316
  const noDiscardedFailure = defineRule({
1085
1317
  create: (context) => ({ MemberExpression: (node) => {
1086
1318
  if (!importedMember({
@@ -1088,13 +1320,14 @@ const noDiscardedFailure = defineRule({
1088
1320
  importedName: "Effect",
1089
1321
  node
1090
1322
  })) return;
1091
- if (!exists(memberName(node), (name) => contains$1([
1323
+ if (!exists(memberName(node), (name) => contains([
1092
1324
  "ignore",
1093
1325
  "orDie",
1094
1326
  "orDieWith"
1095
1327
  ], name))) return;
1328
+ if (contains$1(memberName(node), "ignore") && logged(node)) return;
1096
1329
  context.report({
1097
- message: "Map the failure to the service's error; an expected failure is never ignored or turned into a defect.",
1330
+ message: "Map the failure to the service's error, or log best-effort work with Effect.ignore({log: 'Warn', message}); an expected failure is never dropped silently or turned into a defect.",
1098
1331
  node
1099
1332
  });
1100
1333
  } }),
@@ -1102,12 +1335,7 @@ const noDiscardedFailure = defineRule({
1102
1335
  });
1103
1336
  //#endregion
1104
1337
  //#region src/rules/no-double-nullish-check.ts
1105
- function nullishOperand(node) {
1106
- if (node.type === "Literal" && node.value === null) return some("null");
1107
- if (node.type === "Identifier" && node.name === "undefined") return some("undefined");
1108
- return none();
1109
- }
1110
- const variants = {
1338
+ const VARIANTS = {
1111
1339
  "&&": {
1112
1340
  comparison: "!==",
1113
1341
  message: "Use Predicate.isNotNullish."
@@ -1117,6 +1345,11 @@ const variants = {
1117
1345
  message: "Use Predicate.isNullish."
1118
1346
  }
1119
1347
  };
1348
+ function nullishOperand(node) {
1349
+ if (node.type === "Literal" && node.value === null) return some("null");
1350
+ if (node.type === "Identifier" && node.name === "undefined") return some("undefined");
1351
+ return none();
1352
+ }
1120
1353
  function operands(input) {
1121
1354
  if (input.node.type !== "LogicalExpression" || input.node.operator !== input.operator) return [input.node];
1122
1355
  return appendAll(operands({
@@ -1139,7 +1372,7 @@ const noDoubleNullishCheck = defineRule({
1139
1372
  create: (context) => ({ LogicalExpression: (node) => {
1140
1373
  if (node.operator === "??") return;
1141
1374
  if (node.parent.type === "LogicalExpression" && node.parent.operator === node.operator) return;
1142
- const variant = variants[node.operator];
1375
+ const variant = VARIANTS[node.operator];
1143
1376
  const checks = pipe(operands({
1144
1377
  node,
1145
1378
  operator: node.operator
@@ -1186,6 +1419,80 @@ const noEffectPropertyArrow = defineRule({
1186
1419
  meta: { type: "problem" }
1187
1420
  });
1188
1421
  //#endregion
1422
+ //#region src/rules/no-empty-recovery.ts
1423
+ function calleeOf(node) {
1424
+ if (node.type === "CallExpression" && node.callee.type !== "Super") return node.callee;
1425
+ return node;
1426
+ }
1427
+ function isEffectEmpty(input) {
1428
+ const member = calleeOf(input.node);
1429
+ return member.type === "MemberExpression" && member.object.type === "Identifier" && contains$1(memberName(member), "empty") && isImportBinding({
1430
+ context: input.context,
1431
+ node: member.object,
1432
+ source: "effect"
1433
+ });
1434
+ }
1435
+ function isEmptyValue(input) {
1436
+ if (isNullish$1(input.node)) return false;
1437
+ if (input.node.type === "Identifier") return input.node.name === "undefined";
1438
+ if (input.node.type === "Literal") return input.node.value === null || input.node.value === "";
1439
+ if (input.node.type === "ArrayExpression") return isArrayEmpty(input.node.elements);
1440
+ if (input.node.type === "ObjectExpression") return isArrayEmpty(input.node.properties);
1441
+ if (input.node.type === "TemplateLiteral") return isArrayEmpty(input.node.expressions) && every(input.node.quasis, (quasi) => quasi.value.raw === "");
1442
+ return isEffectEmpty({
1443
+ context: input.context,
1444
+ node: input.node
1445
+ });
1446
+ }
1447
+ function isEmptySuccess(input) {
1448
+ if (isNullish$1(input.node)) return false;
1449
+ if (importedMember({
1450
+ context: input.context,
1451
+ importedName: "Effect",
1452
+ node: input.node,
1453
+ propertyName: "void"
1454
+ })) return true;
1455
+ return input.node.type === "CallExpression" && input.node.callee.type !== "Super" && importedMember({
1456
+ context: input.context,
1457
+ importedName: "Effect",
1458
+ node: input.node.callee,
1459
+ propertyName: "succeed"
1460
+ }) && every(input.node.arguments, (argument) => argument.type !== "SpreadElement" && isEmptyValue({
1461
+ context: input.context,
1462
+ node: argument
1463
+ }));
1464
+ }
1465
+ function recoversEmpty(input) {
1466
+ if (input.name === "orElseSucceed") return isEmptyValue({
1467
+ context: input.context,
1468
+ node: input.node
1469
+ });
1470
+ return isEmptySuccess({
1471
+ context: input.context,
1472
+ node: input.node
1473
+ });
1474
+ }
1475
+ const noEmptyRecovery = defineRule({
1476
+ create: (context) => ({ CallExpression: (node) => {
1477
+ if (node.callee.type !== "MemberExpression" || !importedMember({
1478
+ context,
1479
+ importedName: "Effect",
1480
+ node: node.callee
1481
+ })) return;
1482
+ const name = pipe(memberName(node.callee), getOrElse(() => ""));
1483
+ if (!pipe(name, startsWith("catch")) && !pipe(name, startsWith("orElse"))) return;
1484
+ for (const argument of node.arguments) if ((argument.type === "ArrowFunctionExpression" || argument.type === "FunctionExpression") && recoversEmpty({
1485
+ context,
1486
+ name,
1487
+ node: returnedExpression(argument)
1488
+ })) context.report({
1489
+ message: "Let the failure flow, or map it to the service’s error; an empty value hides that the work failed.",
1490
+ node: argument
1491
+ });
1492
+ } }),
1493
+ meta: { type: "problem" }
1494
+ });
1495
+ //#endregion
1189
1496
  //#region src/rules/no-error-message-assertion.ts
1190
1497
  function receiverName(node) {
1191
1498
  if (node.type === "Identifier") return some(node.name);
@@ -1193,13 +1500,13 @@ function receiverName(node) {
1193
1500
  return memberName(node);
1194
1501
  }
1195
1502
  function isErrorMessage(node) {
1196
- return node?.type === "MemberExpression" && contains(memberName(node), "message") && exists(receiverName(node.object), matches(/^(?:e|err|error|failure|cause|exception)$|Error$/iu));
1503
+ return node?.type === "MemberExpression" && contains$1(memberName(node), "message") && exists(receiverName(node.object), matches(/^(?:e|err|error|failure|cause|exception)$|Error$/iu));
1197
1504
  }
1198
1505
  function expectsErrorMessage(node) {
1199
1506
  return node.type === "CallExpression" && node.callee.type === "Identifier" && node.callee.name === "expect" && isErrorMessage(node.arguments[0]);
1200
1507
  }
1201
1508
  function expectsMessage(node) {
1202
- if (node.object.type === "MemberExpression" && contains(memberName(node.object), "not")) return expectsErrorMessage(node.object.object);
1509
+ if (node.object.type === "MemberExpression" && contains$1(memberName(node.object), "not")) return expectsErrorMessage(node.object.object);
1203
1510
  return expectsErrorMessage(node.object);
1204
1511
  }
1205
1512
  function assertsMessage(node) {
@@ -1215,7 +1522,7 @@ const noErrorMessageAssertion = defineRule({
1215
1522
  });
1216
1523
  return;
1217
1524
  }
1218
- if (node.callee.type === "MemberExpression" && (node.arguments[0]?.type === "Literal" || node.arguments[0]?.type === "TemplateLiteral") && (exists(memberName(node.callee), (name) => contains$1(["toThrow", "toThrowError"], name)) || expectsMessage(node.callee))) context.report({
1525
+ if (node.callee.type === "MemberExpression" && (node.arguments[0]?.type === "Literal" || node.arguments[0]?.type === "TemplateLiteral") && (exists(memberName(node.callee), (name) => contains(["toThrow", "toThrowError"], name)) || expectsMessage(node.callee))) context.report({
1219
1526
  message: "Assert the failure, never its message wording.",
1220
1527
  node
1221
1528
  });
@@ -1241,7 +1548,7 @@ function hasUnusedSetter(input) {
1241
1548
  }
1242
1549
  function isFakeRefState(input) {
1243
1550
  if (!isReactUseState(input) || input.node.arguments[0]?.type !== "ArrowFunctionExpression" || input.node.arguments[0].body.type !== "ObjectExpression" || input.node.arguments[0].body.properties.length !== 1 || !hasUnusedSetter(input)) return false;
1244
- return some$1(input.node.arguments[0].body.properties, (property) => property.type === "Property" && contains(propertyName(property), "current") && property.value.type === "Literal" && property.value.value === null);
1551
+ return some$1(input.node.arguments[0].body.properties, (property) => property.type === "Property" && contains$1(propertyName(property), "current") && property.value.type === "Literal" && property.value.value === null);
1245
1552
  }
1246
1553
  const noFakeRefState = defineRule({
1247
1554
  create: (context) => ({ CallExpression: (node) => {
@@ -1256,6 +1563,49 @@ const noFakeRefState = defineRule({
1256
1563
  meta: { type: "problem" }
1257
1564
  });
1258
1565
  //#endregion
1566
+ //#region src/rules/no-floating-derived-type.ts
1567
+ function derived(node) {
1568
+ if (node.type === "TSIndexedAccessType") return derived(node.objectType);
1569
+ return node.type === "TSTypeReference" && node.typeName.type === "Identifier" && contains([
1570
+ "Awaited",
1571
+ "ConstructorParameters",
1572
+ "InstanceType",
1573
+ "Parameters",
1574
+ "ReturnType"
1575
+ ], node.typeName.name);
1576
+ }
1577
+ const noFloatingDerivedType = defineRule({
1578
+ create: (context) => ({ TSTypeAliasDeclaration: (node) => {
1579
+ const listed = some$1(context.sourceCode.ast.body, (statement) => statement.type === "ExportNamedDeclaration" && some$1(statement.specifiers, (specifier) => specifier.local.type === "Identifier" && specifier.local.name === node.id.name));
1580
+ if (node.parent.type === "ExportNamedDeclaration" || listed || !derived(node.typeAnnotation)) return;
1581
+ context.report({
1582
+ message: "Import the library's own type, or pass the value straight to the call that types it.",
1583
+ node
1584
+ });
1585
+ } }),
1586
+ meta: { type: "problem" }
1587
+ });
1588
+ //#endregion
1589
+ //#region src/rules/no-gradient.ts
1590
+ const GRADIENT = /(?:^|[\s:])bg-(?:linear|radial|conic|gradient)(?:-|$|\s)|gradient\(/u;
1591
+ function report$4(context, node) {
1592
+ context.report({
1593
+ message: "Use a flat theme color; gradients are never part of the design.",
1594
+ node
1595
+ });
1596
+ }
1597
+ const noGradient = defineRule({
1598
+ create: (context) => ({
1599
+ Literal: (node) => {
1600
+ if (isString(node.value) && GRADIENT.test(node.value)) report$4(context, node);
1601
+ },
1602
+ TemplateElement: (node) => {
1603
+ if (GRADIENT.test(node.value.raw)) report$4(context, node);
1604
+ }
1605
+ }),
1606
+ meta: { type: "problem" }
1607
+ });
1608
+ //#endregion
1259
1609
  //#region src/rules/no-hand-written-guard.ts
1260
1610
  function isSubject(input) {
1261
1611
  return input.node.type === "Identifier" && input.node.name === input.name;
@@ -1284,7 +1634,7 @@ function check(input) {
1284
1634
  if (input.node.type === "UnaryExpression" && input.node.operator === "!" && input.node.argument.type === "CallExpression" && input.node.argument.callee.type === "MemberExpression" && isSubject({
1285
1635
  name: "Array",
1286
1636
  node: input.node.argument.callee.object
1287
- }) && contains(memberName(input.node.argument.callee), "isArray") && input.node.argument.arguments.length === 1 && every(input.node.argument.arguments, (argument) => isSubject({
1637
+ }) && contains$1(memberName(input.node.argument.callee), "isArray") && input.node.argument.arguments.length === 1 && every(input.node.argument.arguments, (argument) => isSubject({
1288
1638
  name: input.name,
1289
1639
  node: argument
1290
1640
  }))) return some(["!Array.isArray"]);
@@ -1308,11 +1658,11 @@ function check(input) {
1308
1658
  subject: input.node.right
1309
1659
  })]), map(of));
1310
1660
  }
1311
- function report$2(input) {
1661
+ function report$3(input) {
1312
1662
  const predicate = input.node.returnType?.typeAnnotation;
1313
1663
  const returned = returnedExpression(input.node);
1314
1664
  if (predicate?.type !== "TSTypePredicate" || predicate.asserts || predicate.parameterName.type !== "Identifier" || isNullish$1(returned)) return;
1315
- const name = pipe(check({
1665
+ map(pipe(check({
1316
1666
  name: predicate.parameterName.name,
1317
1667
  node: returned
1318
1668
  }), map((checks) => pipe(checks, sort(Order), join(" && "))), flatMap((key) => get$2({
@@ -1337,8 +1687,7 @@ function report$2(input) {
1337
1687
  "typeof === string": "isString",
1338
1688
  "typeof === symbol": "isSymbol",
1339
1689
  "typeof === undefined": "isUndefined"
1340
- }, key)));
1341
- map(name, (guard) => {
1690
+ }, key))), (guard) => {
1342
1691
  input.context.report({
1343
1692
  message: `Use Predicate.${guard} instead of this hand-written type guard.`,
1344
1693
  node: input.node
@@ -1348,19 +1697,19 @@ function report$2(input) {
1348
1697
  const noHandWrittenGuard = defineRule({
1349
1698
  create: (context) => ({
1350
1699
  ArrowFunctionExpression: (node) => {
1351
- report$2({
1700
+ report$3({
1352
1701
  context,
1353
1702
  node
1354
1703
  });
1355
1704
  },
1356
1705
  FunctionDeclaration: (node) => {
1357
- report$2({
1706
+ report$3({
1358
1707
  context,
1359
1708
  node
1360
1709
  });
1361
1710
  },
1362
1711
  FunctionExpression: (node) => {
1363
- report$2({
1712
+ report$3({
1364
1713
  context,
1365
1714
  node
1366
1715
  });
@@ -1393,13 +1742,12 @@ const noLet = defineRule({
1393
1742
  });
1394
1743
  //#endregion
1395
1744
  //#region src/rules/no-multiline-comment.ts
1396
- const directive = /^\s*(?:eslint|oxlint|@effect-diagnostics|@ts-|\/\s*<reference|#region|#endregion)/u;
1397
1745
  function adjacentLines(pair) {
1398
1746
  return pair.first?.type === "Line" && pair.second?.type === "Line" && pair.second.loc.start.line === pair.first.loc.end.line + 1;
1399
1747
  }
1400
1748
  const noMultilineComment = defineRule({
1401
1749
  create: (context) => ({ Program: () => {
1402
- const comments = pipe(context.sourceCode.getAllComments(), filter$1((comment) => !directive.test(comment.value)));
1750
+ const comments = pipe(context.sourceCode.getAllComments(), filter$1((comment) => !matches(/^\s*(?:eslint|oxlint|@effect-diagnostics|@ts-|\/\s*<reference|#region|#endregion)/u)(comment.value)));
1403
1751
  pipe(comments, filter$1((comment, index) => adjacentLines({
1404
1752
  first: comment,
1405
1753
  second: comments[index + 1]
@@ -1415,22 +1763,32 @@ const noMultilineComment = defineRule({
1415
1763
  });
1416
1764
  //#endregion
1417
1765
  //#region src/rules/no-native-control.ts
1418
- const primitives = {
1766
+ const PRIMITIVES = {
1419
1767
  button: "Button",
1420
1768
  input: "Input",
1421
1769
  select: "Select",
1422
1770
  textarea: "Textarea"
1423
1771
  };
1424
- const controlStyle = /(?:^|:)(?:hover|focus|focus-visible|active):|(?:^|:)(?:rounded|shadow|ring)(?:-|$)|(?:^|:)p[blrtxy]?-(?!0$)|(?:^|:)bg-(?!transparent$)|(?:^|:)border(?:-[blrtxy])?$|(?:^|:)border-(?!0$|[blrtxy]-0$)/u;
1772
+ const CONTROL_STYLE = /(?:^|:)(?:hover|focus|focus-visible|active):|(?:^|:)(?:rounded|shadow|ring)(?:-|$)|(?:^|:)p[blrtxy]?-(?!0$)|(?:^|:)bg-(?!transparent$)|(?:^|:)border(?:-[blrtxy])?$|(?:^|:)border-(?!0$|[blrtxy]-0$)/u;
1773
+ function classStrings(node) {
1774
+ if (node.type === "Literal") return filter$1([node.value], isString);
1775
+ if (node.type === "TemplateLiteral") return map$1(node.quasis, (quasi) => quasi.value.raw);
1776
+ if (node.type === "JSXExpressionContainer") return classStrings(node.expression);
1777
+ if (node.type === "CallExpression") return flatMap$1(node.arguments, classStrings);
1778
+ if (node.type === "ConditionalExpression") return flatMap$1([node.consequent, node.alternate], classStrings);
1779
+ if (node.type === "LogicalExpression") return classStrings(node.right);
1780
+ if (node.type === "ArrayExpression") return flatMap$1(filter$1(node.elements, isNotNull), classStrings);
1781
+ return empty();
1782
+ }
1425
1783
  const noNativeControl = defineRule({
1426
1784
  create: (context) => ({ JSXOpeningElement: (node) => {
1427
1785
  if (node.name.type !== "JSXIdentifier") return;
1428
1786
  const name = node.name.name;
1429
- map(get$2(primitives, name), (primitive) => {
1430
- const styled = pipe(node.attributes, findFirst((attribute) => attribute.type === "JSXAttribute" && attribute.name.type === "JSXIdentifier" && attribute.name.name === "className"), flatMap((attribute) => {
1431
- if (attribute.type !== "JSXAttribute" || attribute.value?.type !== "Literal") return none();
1432
- return fromNullishOr(attribute.value.value);
1433
- }), exists((value) => some$1(split(value, /\s+/u), matches(controlStyle))));
1787
+ map(get$2(PRIMITIVES, name), (primitive) => {
1788
+ const styled = pipe(node.attributes, findFirst((attribute) => attribute.type === "JSXAttribute" && attribute.name.type === "JSXIdentifier" && attribute.name.name === "className"), map((attribute) => {
1789
+ if (attribute.type !== "JSXAttribute" || attribute.value === null) return empty();
1790
+ return classStrings(attribute.value);
1791
+ }), exists((values) => some$1(values, (value) => some$1(split(value, /\s+/u), matches(CONTROL_STYLE)))));
1434
1792
  if (name !== "select" && !styled) return;
1435
1793
  context.report({
1436
1794
  message: `Use the ${primitive} UI primitive instead of a styled native control.`,
@@ -1443,7 +1801,7 @@ const noNativeControl = defineRule({
1443
1801
  //#endregion
1444
1802
  //#region src/rules/no-native-emptiness-check.ts
1445
1803
  function emptinessPredicate(node) {
1446
- const comparesLength = node.left.type === "MemberExpression" && contains(memberName(node.left), "length") && node.right.type === "Literal" && node.right.value === 0;
1804
+ const comparesLength = node.left.type === "MemberExpression" && contains$1(memberName(node.left), "length") && node.right.type === "Literal" && node.right.value === 0;
1447
1805
  if (comparesLength && node.operator === "===") return some("Array.isArrayEmpty, Array.isReadonlyArrayEmpty, or String.isEmpty");
1448
1806
  if (comparesLength && node.operator === ">") return some("Array.isArrayNonEmpty, Array.isReadonlyArrayNonEmpty, or String.isNonEmpty");
1449
1807
  return none();
@@ -1461,7 +1819,7 @@ const noNativeEmptinessCheck = defineRule({
1461
1819
  });
1462
1820
  //#endregion
1463
1821
  //#region src/rules/no-native-method-call.ts
1464
- const nativeMethods = [
1822
+ const NATIVE_METHODS = [
1465
1823
  "at",
1466
1824
  "catch",
1467
1825
  "charAt",
@@ -1532,13 +1890,48 @@ function freshRegExpFlags(input) {
1532
1890
  if (flags.type !== "Literal" || !isString(flags.value)) return some(none());
1533
1891
  return some(some(flags.value));
1534
1892
  }
1893
+ function memberRoot(node) {
1894
+ if (node.type === "MemberExpression") return memberRoot(node.object);
1895
+ return node;
1896
+ }
1897
+ function chainRoot(node) {
1898
+ if (node.type === "MemberExpression") return chainRoot(node.object);
1899
+ if (node.type === "CallExpression" && node.callee.type !== "Super") return chainRoot(node.callee);
1900
+ if (node.type === "ParenthesizedExpression") return chainRoot(node.expression);
1901
+ return node;
1902
+ }
1903
+ function isYieldedService(node) {
1904
+ if (node?.type !== "YieldExpression" || !node.delegate || isNullish$1(node.argument)) return false;
1905
+ if (node.argument.type === "Identifier") return matches(/^[A-Z]/u)(node.argument.name);
1906
+ return node.argument.type === "MemberExpression" && exists(memberName(node.argument), (name) => matches(/^[A-Z]/u)(name));
1907
+ }
1908
+ const effectPackage = matches(/^(?:effect(?:\/|$)|@effect\/)/u);
1909
+ const localPath = matches(/^[.#~/]|^@\//u);
1910
+ function ownsMethod(input) {
1911
+ const root = chainRoot(input.receiver);
1912
+ const throughCall = root !== memberRoot(input.receiver);
1913
+ if (isYieldedService(root)) return true;
1914
+ if (root.type !== "Identifier") return false;
1915
+ if (root.name === "path") return !throughCall;
1916
+ return pipe(variableFor(input.context, root), filter((variable) => isReadonlyArrayNonEmpty(variable.defs)), match({
1917
+ onNone: () => !throughCall && matches(/^[A-Z]/u)(root.name) && !contains([
1918
+ "Object",
1919
+ "Promise",
1920
+ "RegExp"
1921
+ ], root.name),
1922
+ onSome: (variable) => some$1(variable.defs, (definition) => {
1923
+ if (definition.node.type === "VariableDeclarator") return !throughCall && isYieldedService(definition.node.init);
1924
+ if (definition.type !== "ImportBinding" || definition.parent?.type !== "ImportDeclaration") return false;
1925
+ return !localPath(definition.parent.source.value) && !(throughCall && effectPackage(definition.parent.source.value));
1926
+ })
1927
+ }));
1928
+ }
1535
1929
  const noNativeMethodCall = defineRule({
1536
1930
  create: (context) => ({ CallExpression: (node) => {
1537
- if (node.callee.type !== "MemberExpression" || node.callee.object.type === "Identifier" && (node.callee.object.name === "path" || isImportBinding({
1931
+ if (node.callee.type !== "MemberExpression" || ownsMethod({
1538
1932
  context,
1539
- node: node.callee.object,
1540
- source: /^(?:effect(?:\/|$)|@effect\/)/u
1541
- }))) return;
1933
+ receiver: node.callee.object
1934
+ })) return;
1542
1935
  const receiver = node.callee.object;
1543
1936
  const regExpFlags = freshRegExpFlags({
1544
1937
  context,
@@ -1551,29 +1944,19 @@ const noNativeMethodCall = defineRule({
1551
1944
  });
1552
1945
  return;
1553
1946
  }
1554
- pipe(memberName(node.callee), filter((name) => contains$1(nativeMethods, name)), filter((name) => !contains$1([
1947
+ pipe(memberName(node.callee), filter((name) => contains(NATIVE_METHODS, name)), filter((name) => !contains([
1555
1948
  "entries",
1556
1949
  "keys",
1557
1950
  "values"
1558
- ], name) || isArrayEmpty(node.arguments) || receiver.type === "Identifier" && receiver.name === "Object"), map((name) => {
1559
- context.report({
1560
- message: `Replace .${name}() on a native array, string, record, or Promise with its Effect Array, String, Record, or Effect function; a third-party API's own method stays, with an inline disable and its reason.`,
1561
- node: node.callee
1562
- });
1563
- }));
1951
+ ], name) || isArrayEmpty(node.arguments) || receiver.type === "Identifier" && receiver.name === "Object"), map((name) => context.report({
1952
+ message: `Replace .${name}() on a native array, string, record, or Promise with its Effect Array, String, Record, or Effect function; a third-party API's own method stays, with an inline disable and its reason.`,
1953
+ node: node.callee
1954
+ })));
1564
1955
  } }),
1565
1956
  meta: { type: "problem" }
1566
1957
  });
1567
1958
  //#endregion
1568
1959
  //#region src/rules/no-nullish-ternary.ts
1569
- const nullishPredicates = [
1570
- "isNotNull",
1571
- "isNotNullish",
1572
- "isNotUndefined",
1573
- "isNull",
1574
- "isNullish",
1575
- "isUndefined"
1576
- ];
1577
1960
  function isNullish(input) {
1578
1961
  if (input.node.type === "Literal") return input.node.value === null;
1579
1962
  return input.node.type === "Identifier" && input.node.name === "undefined";
@@ -1594,7 +1977,14 @@ function testsNullish(input) {
1594
1977
  context: input.context,
1595
1978
  importedName: "Predicate",
1596
1979
  node: input.node.callee
1597
- }) && exists(memberName(input.node.callee), (name) => contains$1(nullishPredicates, name));
1980
+ }) && exists(memberName(input.node.callee), (name) => contains([
1981
+ "isNotNull",
1982
+ "isNotNullish",
1983
+ "isNotUndefined",
1984
+ "isNull",
1985
+ "isNullish",
1986
+ "isUndefined"
1987
+ ], name));
1598
1988
  }
1599
1989
  const noNullishTernary = defineRule({
1600
1990
  create: (context) => ({ ConditionalExpression: (node) => {
@@ -1626,7 +2016,7 @@ function checks(input) {
1626
2016
  }) && input.test.arguments[0] !== void 0 && input.context.sourceCode.getText(input.test.arguments[0]) === input.subject;
1627
2017
  }
1628
2018
  function exits(node) {
1629
- return contains$1([
2019
+ return contains([
1630
2020
  "ContinueStatement",
1631
2021
  "ReturnStatement",
1632
2022
  "ThrowStatement"
@@ -1663,7 +2053,7 @@ function guarded(input) {
1663
2053
  }
1664
2054
  const noOptionValueAccess = defineRule({
1665
2055
  create: (context) => ({ MemberExpression: (node) => {
1666
- if (!contains(memberName(node), "value")) return;
2056
+ if (!contains$1(memberName(node), "value")) return;
1667
2057
  if (guarded({
1668
2058
  context,
1669
2059
  node,
@@ -1677,26 +2067,14 @@ const noOptionValueAccess = defineRule({
1677
2067
  });
1678
2068
  //#endregion
1679
2069
  //#region src/rules/no-property-alias.ts
1680
- const functions = [
2070
+ const FUNCTIONS = [
1681
2071
  "ArrowFunctionExpression",
1682
2072
  "FunctionDeclaration",
1683
2073
  "FunctionExpression"
1684
2074
  ];
1685
- const deferred = [
1686
- "ChainExpression",
1687
- "ConditionalExpression",
1688
- "DoWhileStatement",
1689
- "ForInStatement",
1690
- "ForOfStatement",
1691
- "ForStatement",
1692
- "IfStatement",
1693
- "LogicalExpression",
1694
- "SwitchStatement",
1695
- "WhileStatement"
1696
- ];
1697
2075
  function insideFunction(node) {
1698
2076
  if (isNullish$1(node.parent) || node.parent.type === "Program") return false;
1699
- if (contains$1(functions, node.parent.type)) return true;
2077
+ if (contains(FUNCTIONS, node.parent.type)) return true;
1700
2078
  return insideFunction(node.parent);
1701
2079
  }
1702
2080
  function sameRoot(input) {
@@ -1708,9 +2086,58 @@ function sameRoot(input) {
1708
2086
  scope: input.context.sourceCode.getScope(input.read)
1709
2087
  }));
1710
2088
  }
2089
+ function pathTop(node) {
2090
+ if (node.parent?.type === "MemberExpression" && node.parent.object === node && !node.parent.computed) return pathTop(node.parent);
2091
+ return node;
2092
+ }
2093
+ function tested(node) {
2094
+ if (isNullish$1(node.parent)) return false;
2095
+ if (node.parent.type === "LogicalExpression") return node.parent.left === node || tested(node.parent);
2096
+ if (contains([
2097
+ "ChainExpression",
2098
+ "TSAsExpression",
2099
+ "TSNonNullExpression"
2100
+ ], node.parent.type)) return tested(node.parent);
2101
+ return node.parent.type === "BinaryExpression" && contains([
2102
+ "!=",
2103
+ "!==",
2104
+ "==",
2105
+ "===",
2106
+ "in",
2107
+ "instanceof"
2108
+ ], node.parent.operator) || node.parent.type === "UnaryExpression" && contains(["!", "typeof"], node.parent.operator) || node.parent.type === "ConditionalExpression" && node.parent.test === node || node.parent.type === "IfStatement" && node.parent.test === node || node.parent.type === "SwitchStatement" && node.parent.discriminant === node || node.parent.type === "CallExpression" && node.parent.callee !== node && !(node.parent.parent.type === "CallExpression" && node.parent.parent.callee === node.parent) && (predicate(node.parent.callee) || tested(node.parent));
2109
+ }
2110
+ function predicate(callee) {
2111
+ if (callee.type === "CallExpression") return predicate(callee.callee);
2112
+ if (callee.type === "Identifier") return matches(/^(?:has|is)(?:[A-Z]|$)/u)(callee.name);
2113
+ return callee.type === "MemberExpression" && callee.property.type === "Identifier" && matches(/^(?:has|is)(?:[A-Z]|$)/u)(callee.property.name);
2114
+ }
2115
+ function deferred(input) {
2116
+ if (isNullish$1(input.node.parent) || input.node.parent === input.block) return false;
2117
+ const parent = input.node.parent;
2118
+ if (contains(FUNCTIONS, parent.type) && !(parent.parent?.type === "CallExpression" && some$1(parent.parent.arguments, (argument) => argument === parent))) return true;
2119
+ return deferred({
2120
+ ...input,
2121
+ node: parent
2122
+ });
2123
+ }
2124
+ function needsAlias(input) {
2125
+ if (input.declaration.parent.type !== "BlockStatement" || !contains(FUNCTIONS, input.declaration.parent.parent.type) || !pipe(input.declaration.parent.body, takeWhile((statement) => statement !== input.declaration), every((statement) => statement.type === "VariableDeclaration"))) return true;
2126
+ const block = input.declaration.parent;
2127
+ const paths = map$1(input.reads, (read) => ({
2128
+ callback: enclosed({
2129
+ block,
2130
+ node: read,
2131
+ types: FUNCTIONS
2132
+ }),
2133
+ node: pathTop(read),
2134
+ text: input.context.sourceCode.getText(pathTop(read))
2135
+ }));
2136
+ return some$1(paths, (checked) => tested(checked.node) && some$1(paths, (read) => read.callback && (read.text === checked.text || startsWith(`${checked.text}.`)(read.text))));
2137
+ }
1711
2138
  function enclosed(input) {
1712
2139
  if (isNullish$1(input.node.parent) || input.node.parent === input.block) return false;
1713
- if (contains$1(input.types, input.node.parent.type)) return true;
2140
+ if (contains(input.types, input.node.parent.type)) return true;
1714
2141
  return enclosed({
1715
2142
  ...input,
1716
2143
  node: input.node.parent
@@ -1729,42 +2156,31 @@ function written(node) {
1729
2156
  if (node.type === "UpdateExpression" || node.type === "UnaryExpression" && node.operator === "delete") return objectRoot(node.argument);
1730
2157
  return none();
1731
2158
  }
1732
- function inert(token) {
1733
- if (contains$1([
1734
- "Boolean",
1735
- "Identifier",
1736
- "Null",
1737
- "Numeric",
1738
- "String"
1739
- ], token.type)) return true;
1740
- if (token.type === "Keyword") return contains$1(["const", "return"], token.value);
1741
- return token.type === "Punctuator" && contains$1([
1742
- "(",
1743
- ",",
1744
- ":",
1745
- "=",
1746
- "[",
1747
- "{"
1748
- ], token.value);
1749
- }
1750
2159
  function replacement(input) {
1751
2160
  if (input.read.parent?.type === "Property" && input.read.parent.shorthand) return `${input.name}: ${input.text}`;
1752
2161
  return input.text;
1753
2162
  }
1754
- function report$1(input) {
2163
+ function report$2(input) {
1755
2164
  const reads = pipe(input.variable.references, filter$1((reference) => reference.isRead()), map$1((reference) => reference.identifier));
1756
2165
  const text = input.context.sourceCode.getText(input.init);
1757
2166
  pipe(rootName(input.init), filter((root) => isArrayNonEmpty(reads) && every(reads, (read) => {
1758
2167
  const used = outermost(read);
1759
- return read.parent.type !== "ExportSpecifier" && !enclosed({
2168
+ return read.parent.type !== "ExportSpecifier" && (!needsAlias({
2169
+ context: input.context,
2170
+ declaration: input.declaration,
2171
+ reads
2172
+ }) || !enclosed({
1760
2173
  block: input.declaration.parent,
1761
2174
  node: read,
1762
- types: functions
2175
+ types: FUNCTIONS
2176
+ })) && !deferred({
2177
+ block: input.declaration.parent,
2178
+ node: read
1763
2179
  }) && !(used.parent?.type === "CallExpression" && used.parent.callee === used) && !(used.parent?.type === "TaggedTemplateExpression" && used.parent.tag === used) && !some$1(input.writes, (write) => between({
1764
2180
  declaration: input.declaration,
1765
2181
  node: write,
1766
2182
  read
1767
- }) && contains(written(write), root)) && sameRoot({
2183
+ }) && contains$1(written(write), root)) && sameRoot({
1768
2184
  context: input.context,
1769
2185
  declarator: input.node,
1770
2186
  name: root,
@@ -1777,7 +2193,19 @@ function report$1(input) {
1777
2193
  if (reads.length !== 1 || some$1(reads, (read) => startsWith("JSX")(read.parent.type) || enclosed({
1778
2194
  block: input.declaration.parent,
1779
2195
  node: read,
1780
- types: deferred
2196
+ types: [
2197
+ ...FUNCTIONS,
2198
+ "ChainExpression",
2199
+ "ConditionalExpression",
2200
+ "DoWhileStatement",
2201
+ "ForInStatement",
2202
+ "ForOfStatement",
2203
+ "ForStatement",
2204
+ "IfStatement",
2205
+ "LogicalExpression",
2206
+ "SwitchStatement",
2207
+ "WhileStatement"
2208
+ ]
1781
2209
  }) || some$1(input.statements, (node) => between({
1782
2210
  declaration: input.declaration,
1783
2211
  node,
@@ -1810,7 +2238,7 @@ const noPropertyAlias = defineRule({
1810
2238
  scope: context.sourceCode.getScope(candidate.node)
1811
2239
  }), match({
1812
2240
  onNone: constVoid,
1813
- onSome: (variable) => report$1({
2241
+ onSome: (variable) => report$2({
1814
2242
  ...candidate,
1815
2243
  context,
1816
2244
  variable,
@@ -1823,6 +2251,19 @@ const noPropertyAlias = defineRule({
1823
2251
  },
1824
2252
  UpdateExpression: write,
1825
2253
  VariableDeclarator: (node) => {
2254
+ if (node.parent.type === "VariableDeclaration" && node.parent.parent.type === "ExportNamedDeclaration" && node.id.type === "Identifier" && node.init?.type === "MemberExpression") {
2255
+ const init = node.init;
2256
+ pipe(rootName(init), flatMap((root) => variableFromScope({
2257
+ name: root,
2258
+ scope: context.sourceCode.getScope(node)
2259
+ })), filter((variable) => every(variable.defs, (definition) => definition.type === "Variable")), match({
2260
+ onNone: constVoid,
2261
+ onSome: (variable) => context.report({
2262
+ message: `Export ${variable.name} and read ${context.sourceCode.getText(init)} where it is used.`,
2263
+ node
2264
+ })
2265
+ }));
2266
+ }
1826
2267
  if (node.parent.type === "VariableDeclaration" && node.parent.kind === "const" && node.parent.declarations.length === 1 && (node.parent.parent.type === "BlockStatement" || node.parent.parent.type === "StaticBlock") && node.id.type === "Identifier" && node.id.typeAnnotation === null && node.init?.type === "MemberExpression" && insideFunction(node.parent)) append$1(candidates, {
1827
2268
  declaration: node.parent,
1828
2269
  init: node.init,
@@ -1846,7 +2287,7 @@ function isTopLevelStatement(node) {
1846
2287
  }
1847
2288
  function insideCycleType(input) {
1848
2289
  if (input.node.type === "Program") return false;
1849
- if (input.node.type === "TSTypeAliasDeclaration" && isTopLevelStatement(input.node)) return contains$1(input.cycleNames, input.node.id.name);
2290
+ if (input.node.type === "TSTypeAliasDeclaration" && isTopLevelStatement(input.node)) return contains(input.cycleNames, input.node.id.name);
1850
2291
  return insideCycleType({
1851
2292
  cycleNames: input.cycleNames,
1852
2293
  node: input.node.parent
@@ -1887,7 +2328,7 @@ function shapeLiterals(input) {
1887
2328
  return pipe(typeDeclarations({
1888
2329
  context: input.context,
1889
2330
  name: input.type.typeName
1890
- }), filter$1((declaration) => declaration.type === "TSTypeAliasDeclaration"), filter$1((alias) => !contains$1(input.seen, alias)), flatMap$1((alias) => shapeLiterals({
2331
+ }), filter$1((declaration) => declaration.type === "TSTypeAliasDeclaration"), filter$1((alias) => !contains(input.seen, alias)), flatMap$1((alias) => shapeLiterals({
1891
2332
  ...input,
1892
2333
  seen: append(input.seen, alias),
1893
2334
  type: alias.typeAnnotation
@@ -2035,7 +2476,7 @@ function isReactUseRef(input) {
2035
2476
  node: input.node.callee,
2036
2477
  source: "react"
2037
2478
  });
2038
- return input.node.callee.type === "MemberExpression" && contains(memberName(input.node.callee), "useRef") && input.node.callee.object.type === "Identifier" && isNamespaceImport({
2479
+ return input.node.callee.type === "MemberExpression" && contains$1(memberName(input.node.callee), "useRef") && input.node.callee.object.type === "Identifier" && isNamespaceImport({
2039
2480
  context: input.context,
2040
2481
  node: input.node.callee.object,
2041
2482
  source: "react"
@@ -2110,7 +2551,7 @@ const shipped = [
2110
2551
  schema: "Natural"
2111
2552
  }
2112
2553
  ];
2113
- function schemaMember(input) {
2554
+ function schemaMember$1(input) {
2114
2555
  if (input.node.type !== "MemberExpression" || !importedMember({
2115
2556
  context: input.context,
2116
2557
  importedName: "Schema",
@@ -2120,16 +2561,16 @@ function schemaMember(input) {
2120
2561
  }
2121
2562
  function shippedSchema(input) {
2122
2563
  if (input.filter.type !== "CallExpression") return none();
2123
- const base = schemaMember({
2564
+ const base = schemaMember$1({
2124
2565
  context: input.context,
2125
2566
  node: input.base
2126
2567
  });
2127
- const check = schemaMember({
2568
+ const check = schemaMember$1({
2128
2569
  context: input.context,
2129
2570
  node: input.filter.callee
2130
2571
  });
2131
2572
  const [value, ...rest] = input.filter.arguments;
2132
- return pipe(shipped, findFirst((entry) => contains(base, entry.base) && contains(check, entry.check) && isArrayEmpty(rest) && match(fromUndefinedOr(entry.only), {
2573
+ return pipe(shipped, findFirst((entry) => contains$1(base, entry.base) && contains$1(check, entry.check) && isArrayEmpty(rest) && match(fromUndefinedOr(entry.only), {
2133
2574
  onNone: () => value === void 0,
2134
2575
  onSome: (only) => value?.type === "Literal" && value.value === only
2135
2576
  })), map((entry) => entry.schema));
@@ -2140,14 +2581,14 @@ function pipedBase(node) {
2140
2581
  if (node.parent.arguments[1] !== node) return none();
2141
2582
  return fromNullishOr(node.parent.arguments[0]);
2142
2583
  }
2143
- if (node.parent.callee.type !== "MemberExpression" || !contains(memberName(node.parent.callee), "pipe") || node.parent.arguments.length !== 1) return none();
2584
+ if (node.parent.callee.type !== "MemberExpression" || !contains$1(memberName(node.parent.callee), "pipe") || node.parent.arguments.length !== 1) return none();
2144
2585
  return some(node.parent.callee.object);
2145
2586
  }
2146
2587
  function reinventedSchema(input) {
2147
- if (input.node.callee.type !== "MemberExpression" || !contains(memberName(input.node.callee), "check")) return none();
2588
+ if (input.node.callee.type !== "MemberExpression" || !contains$1(memberName(input.node.callee), "check")) return none();
2148
2589
  const callee = input.node.callee;
2149
2590
  const [filter] = input.node.arguments;
2150
- if (isSome(schemaMember({
2591
+ if (isSome(schemaMember$1({
2151
2592
  context: input.context,
2152
2593
  node: callee
2153
2594
  }))) {
@@ -2267,7 +2708,7 @@ const noReturnType = defineRule({
2267
2708
  });
2268
2709
  //#endregion
2269
2710
  //#region src/rules/no-single-use-value.ts
2270
- const repeating = [
2711
+ const REPEATING = [
2271
2712
  "ArrowFunctionExpression",
2272
2713
  "DoWhileStatement",
2273
2714
  "ForInStatement",
@@ -2282,7 +2723,7 @@ function runsOnce(input) {
2282
2723
  ...input,
2283
2724
  node: input.node
2284
2725
  });
2285
- if (contains$1(repeating, input.node.type) || input.node.type === "IfStatement" || input.node.type === "ConditionalExpression" || input.node.type === "LogicalExpression" || input.node.type === "ChainExpression" || input.node.type === "SwitchStatement" || input.node.type === "TryStatement") return false;
2726
+ if (contains(REPEATING, input.node.type) || input.node.type === "IfStatement" || input.node.type === "ConditionalExpression" || input.node.type === "LogicalExpression" || input.node.type === "ChainExpression" || input.node.type === "SwitchStatement" || input.node.type === "TryStatement") return false;
2286
2727
  return climb({
2287
2728
  ...input,
2288
2729
  node: input.node
@@ -2306,7 +2747,7 @@ function insideConditional(input) {
2306
2747
  });
2307
2748
  }
2308
2749
  function candidate(node) {
2309
- return node.parent.type === "VariableDeclaration" && node.parent.kind === "const" && node.parent.declarations.length === 1 && node.parent.parent.type === "BlockStatement" && node.id.type === "Identifier" && node.id.typeAnnotation === null && node.init !== null && !contains$1(["ArrowFunctionExpression", "FunctionExpression"], node.init.type) && !(node.init.type === "MemberExpression" && isSome(rootName(node.init))) && !(node.init.type === "Literal" && !hasProperty(node.init, "regex")) && !(node.init.type === "TemplateLiteral" && isArrayEmpty(node.init.expressions));
2750
+ return node.parent.type === "VariableDeclaration" && node.parent.kind === "const" && node.parent.declarations.length === 1 && node.parent.parent.type === "BlockStatement" && node.id.type === "Identifier" && node.id.typeAnnotation === null && node.init !== null && !contains(["ArrowFunctionExpression", "FunctionExpression"], node.init.type) && !(node.init.type === "MemberExpression" && isSome(rootName(node.init))) && !(node.init.type === "Literal" && !hasProperty(node.init, "regex")) && !(node.init.type === "TemplateLiteral" && isArrayEmpty(node.init.expressions));
2310
2751
  }
2311
2752
  function unwrapped(node) {
2312
2753
  return pipe(typeWrapped(node), match({
@@ -2324,10 +2765,61 @@ function inlined(input) {
2324
2765
  if (input.read.range[0] === input.next.range[0]) return `;${value}`;
2325
2766
  return value;
2326
2767
  }
2327
- function report(input) {
2768
+ function executes(node) {
2769
+ if (contains([
2770
+ "AwaitExpression",
2771
+ "CallExpression",
2772
+ "MemberExpression",
2773
+ "NewExpression",
2774
+ "SpreadElement",
2775
+ "TaggedTemplateExpression",
2776
+ "YieldExpression"
2777
+ ], node.type)) return true;
2778
+ if (contains([
2779
+ "ArrowFunctionExpression",
2780
+ "FunctionDeclaration",
2781
+ "FunctionExpression"
2782
+ ], node.type)) return false;
2783
+ return some$1(childNodes(node), executes);
2784
+ }
2785
+ function suspends(node) {
2786
+ if (node.type === "YieldExpression" || node.type === "AwaitExpression") return true;
2787
+ if (contains([
2788
+ "ArrowFunctionExpression",
2789
+ "FunctionDeclaration",
2790
+ "FunctionExpression"
2791
+ ], node.type)) return false;
2792
+ return some$1(childNodes(node), suspends);
2793
+ }
2794
+ function surface(node) {
2795
+ if (contains([
2796
+ "ExpressionStatement",
2797
+ "ReturnStatement",
2798
+ "VariableDeclaration"
2799
+ ], node.type) || node.type === "ArrowFunctionExpression" && node.expression) return true;
2800
+ if (isNullish$1(node.parent) || !contains([
2801
+ "AwaitExpression",
2802
+ "JSXAttribute",
2803
+ "JSXElement",
2804
+ "JSXExpressionContainer",
2805
+ "JSXFragment",
2806
+ "JSXOpeningElement",
2807
+ "VariableDeclarator",
2808
+ "YieldExpression"
2809
+ ], node.type)) return false;
2810
+ return surface(node.parent);
2811
+ }
2812
+ function readable(input) {
2813
+ if (!pipe(input.context.sourceCode.getText(input.init), includes("\n"))) return true;
2814
+ const slot = outermost(input.read);
2815
+ if (isNullish$1(slot.parent) || suspends(input.init)) return false;
2816
+ if (slot.parent.type === "JSXExpressionContainer" || slot.parent.type === "ReturnStatement") return true;
2817
+ return isNotNullish(slot.parent.parent) && (slot.parent.type === "CallExpression" && slot.parent.callee !== slot || slot.parent.type === "ArrayExpression") && surface(slot.parent.parent);
2818
+ }
2819
+ function report$1(input) {
2328
2820
  const declaration = input.node.parent;
2329
2821
  const init = input.node.init;
2330
- if (declaration.type !== "VariableDeclaration" || declaration.parent.type !== "BlockStatement" || input.node.id.type !== "Identifier" || init === null || pipe(input.context.sourceCode.getText(init), includes("\n"))) return;
2822
+ if (declaration.type !== "VariableDeclaration" || declaration.parent.type !== "BlockStatement" || input.node.id.type !== "Identifier" || init === null) return;
2331
2823
  const statements = declaration.parent.body;
2332
2824
  const name = input.node.id.name;
2333
2825
  pipe(findFirstIndex(statements, (statement) => statement === declaration), flatMap((index) => get$1(statements, index + 1)), flatMap((next) => pipe(variableFromScope({
@@ -2336,6 +2828,10 @@ function report(input) {
2336
2828
  }), map((variable) => filter$1(variable.references, (reference) => reference.isRead())), filter((reads) => reads.length === 1), flatMap(head), map((reference) => reference.identifier), filter((read) => read.range[0] >= next.range[0] && read.range[1] <= next.range[1] && climb({
2337
2829
  node: read,
2338
2830
  statement: next
2831
+ }) && readable({
2832
+ context: input.context,
2833
+ init,
2834
+ read
2339
2835
  }) && !(init.type === "ConditionalExpression" && insideConditional({
2340
2836
  node: read,
2341
2837
  statement: next
@@ -2349,7 +2845,7 @@ function report(input) {
2349
2845
  if (!fixable({
2350
2846
  init,
2351
2847
  read: found.read
2352
- })) return [];
2848
+ }) || executes(init) && !every(input.context.sourceCode.getTokensBetween(declaration, found.read), inert)) return [];
2353
2849
  return [fixer.remove(declaration), fixer.replaceText(found.read, inlined({
2354
2850
  context: input.context,
2355
2851
  init,
@@ -2375,7 +2871,7 @@ const noSingleUseValue = defineRule({
2375
2871
  CallExpression: effect,
2376
2872
  NewExpression: effect,
2377
2873
  "Program:exit": () => {
2378
- for (const node of get$3(candidates)) report({
2874
+ for (const node of get$3(candidates)) report$1({
2379
2875
  context,
2380
2876
  effects: get$3(effects),
2381
2877
  node
@@ -2395,6 +2891,22 @@ const noSingleUseValue = defineRule({
2395
2891
  }
2396
2892
  });
2397
2893
  //#endregion
2894
+ //#region src/rules/no-stored-jsx.ts
2895
+ function element(node) {
2896
+ if (node.type === "JSXElement" || node.type === "JSXFragment") return true;
2897
+ return pipe(typeWrapped(node), exists(element));
2898
+ }
2899
+ const noStoredJsx = defineRule({
2900
+ create: (context) => ({ VariableDeclarator: (node) => {
2901
+ if (node.init === null || !element(node.init)) return;
2902
+ context.report({
2903
+ message: "Write the element where it renders, or make it a component when several places render it.",
2904
+ node
2905
+ });
2906
+ } }),
2907
+ meta: { type: "problem" }
2908
+ });
2909
+ //#endregion
2398
2910
  //#region src/rules/no-stored-schema-operation.ts
2399
2911
  function storedSchemaOperation(node) {
2400
2912
  return node.parent.type === "VariableDeclarator" && node.parent.init === node || node.parent.type === "Property" && node.parent.value === node || node.parent.type === "PropertyDefinition" && node.parent.value === node || node.parent.type === "ArrayExpression" || node.parent.type === "AssignmentExpression" && node.parent.right === node;
@@ -2458,7 +2970,7 @@ function detachable(input) {
2458
2970
  function forwardedChain(input) {
2459
2971
  const chain = callGroups(input.returned);
2460
2972
  function fixed(node) {
2461
- return node.type === "Literal" || exists(rootName(node), (root) => !contains$1(input.names, root));
2973
+ return node.type === "Literal" || exists(rootName(node), (root) => !contains(input.names, root));
2462
2974
  }
2463
2975
  return matchRight(chain.groups, {
2464
2976
  onEmpty: constFalse,
@@ -2532,7 +3044,7 @@ function exportedAlias(input) {
2532
3044
  return input.node.parent.type === "VariableDeclaration" && input.node.parent.kind === "const" && input.node.parent.parent.type === "ExportNamedDeclaration" && input.node.id.type === "Identifier" && input.node.init?.type === "Identifier" && pipe(variableFor(input.context, input.node.init), exists((variable) => some$1(variable.defs, (definition) => definition.type === "ImportBinding" || definition.type === "FunctionName" || definition.type === "ClassName" || definition.node.type === "VariableDeclarator" && definition.node.parent.type === "VariableDeclaration" && definition.node.parent.kind === "const")));
2533
3045
  }
2534
3046
  function singleUseLiteral(input) {
2535
- if (input.node.parent.type !== "VariableDeclaration" || input.node.parent.kind !== "const" || isExport(input.node.parent.parent) || input.node.id.type !== "Identifier" || input.node.id.typeAnnotation !== null || !(input.node.init?.type === "Literal" && !hasProperty(input.node.init, "regex") || input.node.init?.type === "TemplateLiteral" && isArrayEmpty(input.node.init.expressions))) return false;
3047
+ if (input.node.parent.type !== "VariableDeclaration" || input.node.parent.kind !== "const" || isExport(input.node.parent.parent) || input.node.parent.parent.type === "Program" || input.node.id.type !== "Identifier" || input.node.id.typeAnnotation !== null || !(input.node.init?.type === "Literal" && !hasProperty(input.node.init, "regex") || input.node.init?.type === "TemplateLiteral" && isArrayEmpty(input.node.init.expressions))) return false;
2536
3048
  return pipe(variableFromScope({
2537
3049
  name: input.node.id.name,
2538
3050
  scope: input.context.sourceCode.getScope(input.node)
@@ -2547,7 +3059,7 @@ function singleUseLayerPart(input) {
2547
3059
  }), map((variable) => filter$1(variable.references, (reference) => reference.isRead())), exists((reads) => {
2548
3060
  const consumer = reads[0]?.identifier.parent;
2549
3061
  if (reads.length !== 1 || consumer?.type !== "CallExpression") return false;
2550
- if (init.type === "MemberExpression") return contains(memberName(init), "layer") && (importedMember({
3062
+ if (init.type === "MemberExpression") return contains$1(memberName(init), "layer") && (importedMember({
2551
3063
  context: input.context,
2552
3064
  importedName: "Layer",
2553
3065
  node: consumer.callee
@@ -2660,6 +3172,45 @@ const noTrivialIndirection = defineRule({
2660
3172
  meta: { type: "problem" }
2661
3173
  });
2662
3174
  //#endregion
3175
+ //#region src/rules/no-type-from-value.ts
3176
+ function schemaMember(name) {
3177
+ return name.type === "TSQualifiedName" && contains([
3178
+ "Encoded",
3179
+ "Type",
3180
+ "cases",
3181
+ "fields",
3182
+ "literals",
3183
+ "members"
3184
+ ], name.right.name);
3185
+ }
3186
+ function valueQuery(node) {
3187
+ if (node.type === "TSParenthesizedType") return valueQuery(node.typeAnnotation);
3188
+ if (node.type === "TSIndexedAccessType") return valueQuery(node.objectType);
3189
+ return node.type === "TSTypeQuery" && (node.exprName.type === "Identifier" || node.exprName.type === "TSQualifiedName" && !schemaMember(node.exprName));
3190
+ }
3191
+ function nestedObject(node) {
3192
+ return node.parent?.type === "TSIndexedAccessType" && node.parent.objectType === node;
3193
+ }
3194
+ const noTypeFromValue = defineRule({
3195
+ create: (context) => {
3196
+ function report(node) {
3197
+ context.report({
3198
+ message: "Declare the closed set as a schema, such as Schema.Literals, and read its type with typeof X.Type.",
3199
+ node
3200
+ });
3201
+ }
3202
+ return {
3203
+ TSIndexedAccessType: (node) => {
3204
+ if (!nestedObject(node) && valueQuery(node.objectType)) report(node);
3205
+ },
3206
+ TSTypeOperator: (node) => {
3207
+ if (node.operator === "keyof" && !nestedObject(node) && valueQuery(node.typeAnnotation)) report(node);
3208
+ }
3209
+ };
3210
+ },
3211
+ meta: { type: "problem" }
3212
+ });
3213
+ //#endregion
2663
3214
  //#region src/rules/no-typeof.ts
2664
3215
  const noTypeof = defineRule({
2665
3216
  create: (context) => ({ UnaryExpression: (node) => {
@@ -2741,6 +3292,44 @@ const noUnvalidatedJsonDecode = defineRule({
2741
3292
  meta: { type: "problem" }
2742
3293
  });
2743
3294
  //#endregion
3295
+ //#region src/rules/preserve-error-cause.ts
3296
+ function constructedFields(node) {
3297
+ if (node?.type !== "CallExpression" && node?.type !== "NewExpression") return none();
3298
+ const constructs = node.type === "NewExpression" || node.callee.type === "MemberExpression" && contains$1(memberName(node.callee), "make");
3299
+ const fields = node.arguments[0];
3300
+ if (!constructs || fields?.type !== "ObjectExpression") return none();
3301
+ return some(fields);
3302
+ }
3303
+ function dropsCause(node) {
3304
+ if (node.type !== "ArrowFunctionExpression" && node.type !== "FunctionExpression" || isArrayEmpty(node.params)) return false;
3305
+ return exists(constructedFields(returnedExpression(node)), (fields) => every(fields.properties, (property) => property.type === "SpreadElement" || !(property.key.type === "Identifier" && property.key.name === "cause")));
3306
+ }
3307
+ function report(context, node) {
3308
+ context.report({
3309
+ message: "Keep the original failure as the new error’s cause: X.make({cause, message}).",
3310
+ node
3311
+ });
3312
+ }
3313
+ const preserveErrorCause = defineRule({
3314
+ create: (context) => ({ CallExpression: (node) => {
3315
+ if (node.callee.type !== "MemberExpression" || !importedMember({
3316
+ context,
3317
+ importedName: "Effect",
3318
+ node: node.callee
3319
+ })) return;
3320
+ const name = memberName(node.callee);
3321
+ if (contains$1(name, "mapError")) {
3322
+ forEach(filter$1(node.arguments, dropsCause), (callback) => report(context, callback));
3323
+ return;
3324
+ }
3325
+ if (!exists(name, (method) => method === "try" || method === "tryPromise")) return;
3326
+ const options = node.arguments[0];
3327
+ if (options?.type !== "ObjectExpression") return;
3328
+ for (const property of options.properties) if (property.type === "Property" && property.key.type === "Identifier" && property.key.name === "catch" && dropsCause(property.value)) report(context, property.value);
3329
+ } }),
3330
+ meta: { type: "problem" }
3331
+ });
3332
+ //#endregion
2744
3333
  //#region src/rules/schema-type-pair.ts
2745
3334
  function expressionRoot(node) {
2746
3335
  if (node.type === "MemberExpression") return expressionRoot(node.object);
@@ -2790,7 +3379,7 @@ function isSchemaDefinition(input) {
2790
3379
  context: input.context,
2791
3380
  importedName: "Schema",
2792
3381
  node: input.node.callee
2793
- }) && contains(memberName(input.node.callee), "make")) return false;
3382
+ }) && contains$1(memberName(input.node.callee), "make")) return false;
2794
3383
  if (!expressionUsesImport({
2795
3384
  context: input.context,
2796
3385
  importedName: "Schema",
@@ -2808,6 +3397,31 @@ function isSchemaDefinition(input) {
2808
3397
  function namedTypeAlias(input) {
2809
3398
  return pipe(input.typeStatement, flatMap(typeAlias), filter((declaration) => declaration.id.name === input.name));
2810
3399
  }
3400
+ function exportedNames(input) {
3401
+ return flatMap$1(input.program.body, (statement) => {
3402
+ if (statement.type !== "ExportNamedDeclaration" || statement.declaration !== null || statement.source !== null) return empty();
3403
+ return flatMap$1(statement.specifiers, (specifier) => {
3404
+ const typeOnly = statement.exportKind === "type" || specifier.exportKind === "type";
3405
+ if (specifier.local.type !== "Identifier" || typeOnly !== input.typeOnly) return empty();
3406
+ return [specifier.local.name];
3407
+ });
3408
+ });
3409
+ }
3410
+ function exportLists(program) {
3411
+ return {
3412
+ types: exportedNames({
3413
+ program,
3414
+ typeOnly: true
3415
+ }),
3416
+ values: exportedNames({
3417
+ program,
3418
+ typeOnly: false
3419
+ })
3420
+ };
3421
+ }
3422
+ function isExported(input) {
3423
+ return input.statement.type === "ExportNamedDeclaration" || contains(input.exports.values, input.name) || input.typeOnly && contains(input.exports.types, input.name);
3424
+ }
2811
3425
  function reportSchemaVariable(input) {
2812
3426
  if (input.variable.id.type !== "Identifier" || !matches(/^[A-Z]/u)(input.variable.id.name)) return;
2813
3427
  if (input.variable.init === null || !isSchemaDefinition({
@@ -2816,7 +3430,7 @@ function reportSchemaVariable(input) {
2816
3430
  })) return;
2817
3431
  const name = input.variable.id.name;
2818
3432
  const typeStatement = pipe(input.program.body, findFirstIndex((statement) => statement === input.statement), filter((index) => index > 0), flatMap((index) => get$1(input.program.body, index - 1)));
2819
- if (contains$1(input.cycleNames, name)) {
3433
+ if (contains(input.cycleNames, name)) {
2820
3434
  if (!pipe(namedTypeAlias({
2821
3435
  name,
2822
3436
  typeStatement
@@ -2843,6 +3457,20 @@ function reportSchemaVariable(input) {
2843
3457
  message: `Place \`type ${name} = typeof ${name}.Type\` immediately before this Schema.`,
2844
3458
  node: input.variable
2845
3459
  });
3460
+ else if (isExported({
3461
+ exports: input.exports,
3462
+ name,
3463
+ statement: input.statement,
3464
+ typeOnly: false
3465
+ }) !== exists(typeStatement, (statement) => isExported({
3466
+ exports: input.exports,
3467
+ name,
3468
+ statement,
3469
+ typeOnly: true
3470
+ }))) input.context.report({
3471
+ message: `Export both \`type ${name}\` and the \`${name}\` Schema, or neither.`,
3472
+ node: input.variable
3473
+ });
2846
3474
  if (input.variable.init.type === "TSSatisfiesExpression" && schemaSchemaType({
2847
3475
  context: input.context,
2848
3476
  node: input.variable.init.typeAnnotation
@@ -2864,11 +3492,13 @@ const schemaTypePair = defineRule({
2864
3492
  context,
2865
3493
  program
2866
3494
  });
3495
+ const exports = exportLists(program);
2867
3496
  for (const statement of program.body) {
2868
3497
  const declaration = statementDeclaration(statement);
2869
3498
  if (declaration?.type === "VariableDeclaration") for (const variable of declaration.declarations) reportSchemaVariable({
2870
3499
  context,
2871
3500
  cycleNames,
3501
+ exports,
2872
3502
  program,
2873
3503
  statement,
2874
3504
  variable
@@ -2879,7 +3509,7 @@ const schemaTypePair = defineRule({
2879
3509
  });
2880
3510
  //#endregion
2881
3511
  //#region src/oxlint.ts
2882
- const reactLegacyApis = [
3512
+ const REACT_LEGACY_APIS = [
2883
3513
  "Component",
2884
3514
  "PureComponent",
2885
3515
  "createRef",
@@ -2888,9 +3518,9 @@ const reactLegacyApis = [
2888
3518
  "useCallback",
2889
3519
  "useMemo"
2890
3520
  ];
2891
- const reactLegacyMessage = "Use React 19 function components with refs as props; React Compiler owns memoization.";
2892
- const mapMessage = "Use HashMap, or MutableHashMap for local mutation; for identity keys, wrap objects the code owns in Equal.byReferenceUnsafe, which marks them reference-compared globally.";
2893
- const reactHooks = [
3521
+ const REACT_LEGACY_MESSAGE = "Use React 19 function components with refs as props; React Compiler owns memoization.";
3522
+ const MAP_MESSAGE = "Use HashMap, or MutableHashMap for local mutation; for identity keys, wrap objects the code owns in Equal.byReferenceUnsafe, which marks them reference-compared globally.";
3523
+ const REACT_HOOKS = [
2894
3524
  "use",
2895
3525
  "useActionState",
2896
3526
  "useContext",
@@ -2909,8 +3539,8 @@ const reactHooks = [
2909
3539
  "useSyncExternalStore",
2910
3540
  "useTransition"
2911
3541
  ];
2912
- const runMessage = "Run the entry point with NodeRuntime.runMain, and Effects in React through atoms. A Promise that an external contract demands takes Effect.runPromise once, with an inline disable that names the contract.";
2913
- const runners = [
3542
+ const RUN_MESSAGE = "Run the entry point with NodeRuntime.runMain, and Effects in React through atoms. A Promise that an external contract demands takes Effect.runPromise once, with an inline disable that names the contract.";
3543
+ const RUNNERS = [
2914
3544
  "runCallback",
2915
3545
  "runCallbackWith",
2916
3546
  "runFork",
@@ -2924,7 +3554,7 @@ const runners = [
2924
3554
  "runSyncExitWith",
2925
3555
  "runSyncWith"
2926
3556
  ];
2927
- const setMessage = "Use HashSet, or MutableHashSet for local mutation; for identity keys, wrap objects the code owns in Equal.byReferenceUnsafe, which marks them reference-compared globally.";
3557
+ const SET_MESSAGE = "Use HashSet, or MutableHashSet for local mutation; for identity keys, wrap objects the code owns in Equal.byReferenceUnsafe, which marks them reference-compared globally.";
2928
3558
  const oxlint = defineConfig({
2929
3559
  categories: {
2930
3560
  correctness: "off",
@@ -2969,6 +3599,10 @@ const oxlint = defineConfig({
2969
3599
  ],
2970
3600
  rules: { "import/no-default-export": "off" }
2971
3601
  },
3602
+ {
3603
+ files: ["**/app.plugin.js"],
3604
+ rules: { "@deslop/coding-standards/no-barrel-module": "off" }
3605
+ },
2972
3606
  {
2973
3607
  files: ["**/components/ui/**"],
2974
3608
  rules: {
@@ -2981,7 +3615,9 @@ const oxlint = defineConfig({
2981
3615
  rules: {
2982
3616
  "@deslop/coding-standards/no-destructured-parameter": "off",
2983
3617
  "@deslop/coding-standards/no-native-control": "off",
2984
- "@deslop/coding-standards/no-renamed-import": "off"
3618
+ "@deslop/coding-standards/no-renamed-import": "off",
3619
+ "jsx-a11y/click-events-have-key-events": "off",
3620
+ "jsx-a11y/label-has-associated-control": "off"
2985
3621
  }
2986
3622
  },
2987
3623
  {
@@ -3008,19 +3644,29 @@ const oxlint = defineConfig({
3008
3644
  "typescript",
3009
3645
  "oxc",
3010
3646
  "import",
3647
+ "jsx-a11y",
3011
3648
  "react",
3012
3649
  "unicorn"
3013
3650
  ],
3014
3651
  rules: {
3652
+ "@deslop/coding-standards/explicit-effect-concurrency": "error",
3653
+ "@deslop/coding-standards/module-constant": "error",
3654
+ "@deslop/coding-standards/motion-limits": "error",
3015
3655
  "@deslop/coding-standards/no-array-wrap-ternary": "error",
3656
+ "@deslop/coding-standards/no-barrel-module": "error",
3657
+ "@deslop/coding-standards/no-compiler-opt-out": "error",
3658
+ "@deslop/coding-standards/no-component-atom-allocation": "error",
3016
3659
  "@deslop/coding-standards/no-constant-function": "error",
3017
3660
  "@deslop/coding-standards/no-deep-pipe": "error",
3018
3661
  "@deslop/coding-standards/no-destructured-parameter": "error",
3019
3662
  "@deslop/coding-standards/no-discarded-failure": "error",
3020
3663
  "@deslop/coding-standards/no-double-nullish-check": "error",
3021
3664
  "@deslop/coding-standards/no-effect-property-arrow": "error",
3665
+ "@deslop/coding-standards/no-empty-recovery": "error",
3022
3666
  "@deslop/coding-standards/no-error-message-assertion": "error",
3023
3667
  "@deslop/coding-standards/no-fake-ref-state": "error",
3668
+ "@deslop/coding-standards/no-floating-derived-type": "error",
3669
+ "@deslop/coding-standards/no-gradient": "error",
3024
3670
  "@deslop/coding-standards/no-hand-written-guard": "error",
3025
3671
  "@deslop/coding-standards/no-in-operator": "error",
3026
3672
  "@deslop/coding-standards/no-let": "error",
@@ -3039,13 +3685,16 @@ const oxlint = defineConfig({
3039
3685
  "@deslop/coding-standards/no-renamed-import": "error",
3040
3686
  "@deslop/coding-standards/no-return-type": "error",
3041
3687
  "@deslop/coding-standards/no-single-use-value": "error",
3688
+ "@deslop/coding-standards/no-stored-jsx": "error",
3042
3689
  "@deslop/coding-standards/no-stored-schema-operation": "error",
3043
3690
  "@deslop/coding-standards/no-switch-statement": "error",
3044
3691
  "@deslop/coding-standards/no-trivial-indirection": "error",
3692
+ "@deslop/coding-standards/no-type-from-value": "error",
3045
3693
  "@deslop/coding-standards/no-typeof": "error",
3046
3694
  "@deslop/coding-standards/no-undestructured-use-state": "error",
3047
3695
  "@deslop/coding-standards/no-unexplained-disable": "error",
3048
3696
  "@deslop/coding-standards/no-unvalidated-json-decode": "error",
3697
+ "@deslop/coding-standards/preserve-error-cause": "error",
3049
3698
  "@deslop/coding-standards/schema-type-pair": "error",
3050
3699
  "effecttsgo/abort-controller-in-effect": "error",
3051
3700
  "effecttsgo/crypto-random-uuid": "error",
@@ -3178,7 +3827,7 @@ const oxlint = defineConfig({
3178
3827
  "typescript/no-import-type-side-effects": "error",
3179
3828
  "typescript/no-inferrable-types": "error",
3180
3829
  "typescript/no-invalid-void-type": "error",
3181
- "typescript/no-misused-promises": ["error", { checksVoidReturn: false }],
3830
+ "typescript/no-misused-promises": ["error", { checksVoidReturn: { attributes: false } }],
3182
3831
  "typescript/no-misused-spread": "error",
3183
3832
  "typescript/no-namespace": ["error", { allowDeclarations: true }],
3184
3833
  "typescript/no-non-null-assertion": "error",
@@ -3210,6 +3859,7 @@ const oxlint = defineConfig({
3210
3859
  "typescript/restrict-plus-operands": "error",
3211
3860
  "typescript/restrict-template-expressions": "error",
3212
3861
  "typescript/strict-boolean-expressions": ["error", {
3862
+ allowNullableObject: false,
3213
3863
  allowNumber: false,
3214
3864
  allowString: false
3215
3865
  }],
@@ -3239,8 +3889,8 @@ const oxlint = defineConfig({
3239
3889
  "no-restricted-imports": ["error", {
3240
3890
  paths: [
3241
3891
  {
3242
- importNames: reactLegacyApis,
3243
- message: reactLegacyMessage,
3892
+ importNames: REACT_LEGACY_APIS,
3893
+ message: REACT_LEGACY_MESSAGE,
3244
3894
  name: "react"
3245
3895
  },
3246
3896
  {
@@ -3303,6 +3953,7 @@ const oxlint = defineConfig({
3303
3953
  }
3304
3954
  ]
3305
3955
  }],
3956
+ "array-callback-return": "error",
3306
3957
  "max-depth": ["error", 3],
3307
3958
  "max-nested-callbacks": ["error", 6],
3308
3959
  "no-cond-assign": "error",
@@ -3348,7 +3999,7 @@ const oxlint = defineConfig({
3348
3999
  name: "Error"
3349
4000
  },
3350
4001
  {
3351
- message: mapMessage,
4002
+ message: MAP_MESSAGE,
3352
4003
  name: "Map"
3353
4004
  },
3354
4005
  {
@@ -3376,7 +4027,7 @@ const oxlint = defineConfig({
3376
4027
  name: "Reflect"
3377
4028
  },
3378
4029
  {
3379
- message: setMessage,
4030
+ message: SET_MESSAGE,
3380
4031
  name: "Set"
3381
4032
  },
3382
4033
  {
@@ -3403,13 +4054,13 @@ const oxlint = defineConfig({
3403
4054
  message: "Use Predicate.hasProperty.",
3404
4055
  property: "hasOwnProperty"
3405
4056
  },
3406
- ...map$1(runners, (property) => ({
3407
- message: runMessage,
4057
+ ...map$1(RUNNERS, (property) => ({
4058
+ message: RUN_MESSAGE,
3408
4059
  object: "Effect",
3409
4060
  property
3410
4061
  })),
3411
4062
  {
3412
- message: runMessage,
4063
+ message: RUN_MESSAGE,
3413
4064
  object: "ManagedRuntime",
3414
4065
  property: "make"
3415
4066
  },
@@ -3433,12 +4084,12 @@ const oxlint = defineConfig({
3433
4084
  object: "Math",
3434
4085
  property: "round"
3435
4086
  },
3436
- ...map$1(reactLegacyApis, (property) => ({
3437
- message: reactLegacyMessage,
4087
+ ...map$1(REACT_LEGACY_APIS, (property) => ({
4088
+ message: REACT_LEGACY_MESSAGE,
3438
4089
  object: "React",
3439
4090
  property
3440
4091
  })),
3441
- ...map$1(reactHooks, (property) => ({
4092
+ ...map$1(REACT_HOOKS, (property) => ({
3442
4093
  message: `Import ${property} by name from react.`,
3443
4094
  object: "React",
3444
4095
  property
@@ -3555,6 +4206,12 @@ const oxlint = defineConfig({
3555
4206
  ignoreRestSiblings: true,
3556
4207
  reportUsedIgnorePattern: true
3557
4208
  }],
4209
+ "no-use-before-define": ["error", {
4210
+ classes: false,
4211
+ functions: false,
4212
+ typedefs: false,
4213
+ variables: true
4214
+ }],
3558
4215
  "no-useless-assignment": "error",
3559
4216
  "no-useless-backreference": "error",
3560
4217
  "no-useless-call": "error",
@@ -3576,6 +4233,12 @@ const oxlint = defineConfig({
3576
4233
  "prefer-const": ["error", { destructuring: "all" }],
3577
4234
  "prefer-template": "error",
3578
4235
  "require-unicode-regexp": "error",
4236
+ "jsx-a11y/autocomplete-valid": "error",
4237
+ "jsx-a11y/click-events-have-key-events": "error",
4238
+ "jsx-a11y/control-has-associated-label": "error",
4239
+ "jsx-a11y/interactive-supports-focus": "error",
4240
+ "jsx-a11y/label-has-associated-control": "error",
4241
+ "react-doctor/no-aria-invalid-without-description": "error",
3579
4242
  "react-doctor/no-call-component-as-function": "error",
3580
4243
  "react-doctor/no-controlled-input-value-without-state-update": "error",
3581
4244
  "react-doctor/no-create-context-in-render": "error",
@@ -3583,12 +4246,18 @@ const oxlint = defineConfig({
3583
4246
  "react-doctor/no-inline-exhaustive-style": "error",
3584
4247
  "react-doctor/no-jsx-element-type": "error",
3585
4248
  "react-doctor/no-many-boolean-props": "error",
4249
+ "react-doctor/no-nested-card-surface": "error",
4250
+ "react-doctor/no-placeholder-only-field": "error",
3586
4251
  "react-doctor/no-prop-types": "error",
3587
4252
  "react-doctor/no-uncontrolled-input": "error",
4253
+ "react-doctor/shadcn-dialog-content-requires-title": "error",
3588
4254
  "react-doctor/shadcn-icon-button-requires-label": "error",
3589
4255
  "react-doctor/effect-listener-cleanup-mismatch": "error",
4256
+ "react-doctor/effect-needs-cleanup": "error",
4257
+ "react-doctor/no-adjust-state-on-prop-change": "error",
3590
4258
  "react-doctor/no-async-effect-callback": "error",
3591
4259
  "react-doctor/no-create-object-url-without-revoke": "error",
4260
+ "react-doctor/no-derived-state": "error",
3592
4261
  "react-doctor/no-derived-useState": "error",
3593
4262
  "react-doctor/no-effect-event-in-deps": "error",
3594
4263
  "react-doctor/no-effect-with-fresh-deps": "error",
@@ -3616,10 +4285,10 @@ const oxlint = defineConfig({
3616
4285
  "react-doctor/no-large-animated-blur": "error",
3617
4286
  "react-doctor/no-layout-property-animation": "error",
3618
4287
  "react-doctor/no-layout-transition-inline": "error",
3619
- "react-doctor/no-long-transition-duration": "error",
3620
4288
  "react-doctor/no-outline-none": "error",
3621
- "react-doctor/no-scale-from-zero": "error",
4289
+ "react-doctor/no-reduced-motion-content-removal": "error",
3622
4290
  "react-doctor/no-transition-all": "error",
4291
+ "react-doctor/no-ungated-tailwind-animation": "error",
3623
4292
  "react/button-has-type": "error",
3624
4293
  "react/checked-requires-onchange-or-readonly": "error",
3625
4294
  "react/exhaustive-deps": "error",
@@ -3649,6 +4318,7 @@ const oxlint = defineConfig({
3649
4318
  "react/preserve-manual-memoization": "error",
3650
4319
  "react/purity": "error",
3651
4320
  "react/refs": "error",
4321
+ "react/rule-suppression": "error",
3652
4322
  "react/rules-of-hooks": "error",
3653
4323
  "react/self-closing-comp": "error",
3654
4324
  "react/set-state-in-effect": "error",
@@ -3678,17 +4348,19 @@ const oxlint = defineConfig({
3678
4348
  Date: "Use DateTime.",
3679
4349
  Error: "Use Schema.TaggedError.",
3680
4350
  Iterable: "Use T[].",
3681
- Map: mapMessage,
4351
+ Map: MAP_MESSAGE,
3682
4352
  Promise: "Use Effect.",
3683
4353
  ReadonlyArray: "Use T[].",
3684
- ReadonlyMap: mapMessage,
3685
- ReadonlySet: setMessage,
3686
- Set: setMessage,
4354
+ ReadonlyMap: MAP_MESSAGE,
4355
+ ReadonlySet: SET_MESSAGE,
4356
+ Set: SET_MESSAGE,
3687
4357
  undefined: "Use an optional property or parameter, or let inference supply undefined."
3688
4358
  } }],
3689
4359
  "typescript/no-unnecessary-type-assertion": "error",
3690
4360
  "typescript/no-useless-default-assignment": "error",
3691
4361
  "unicorn/filename-case": "error",
4362
+ "unicorn/no-abusive-eslint-disable": "error",
4363
+ "unicorn/no-empty-file": "error",
3692
4364
  "unicorn/no-immediate-mutation": "error",
3693
4365
  "unicorn/no-null": "error",
3694
4366
  "unicorn/no-object-as-default-parameter": "error",
@@ -3702,6 +4374,12 @@ const oxlint = defineConfig({
3702
4374
  "use-isnan": "error"
3703
4375
  },
3704
4376
  settings: {
4377
+ "jsx-a11y": { components: {
4378
+ Button: "button",
4379
+ Input: "input",
4380
+ Label: "label",
4381
+ Textarea: "textarea"
4382
+ } },
3705
4383
  react: { version: "19.0" },
3706
4384
  shadcn: { ui: ["@deslop/components-web/ui", "@dual/ui/components"] }
3707
4385
  }
@@ -3709,15 +4387,24 @@ const oxlint = defineConfig({
3709
4387
  var oxlint_default = definePlugin({
3710
4388
  meta: { name: "@deslop/coding-standards" },
3711
4389
  rules: {
4390
+ "explicit-effect-concurrency": explicitEffectConcurrency,
4391
+ "module-constant": moduleConstant,
4392
+ "motion-limits": motionLimits,
3712
4393
  "no-array-wrap-ternary": noArrayWrapTernary,
4394
+ "no-barrel-module": noBarrelModule,
4395
+ "no-compiler-opt-out": noCompilerOptOut,
4396
+ "no-component-atom-allocation": noComponentAtomAllocation,
3713
4397
  "no-constant-function": noConstantFunction,
3714
4398
  "no-deep-pipe": noDeepPipe,
3715
4399
  "no-destructured-parameter": noDestructuredParameter,
3716
4400
  "no-discarded-failure": noDiscardedFailure,
3717
4401
  "no-double-nullish-check": noDoubleNullishCheck,
3718
4402
  "no-effect-property-arrow": noEffectPropertyArrow,
4403
+ "no-empty-recovery": noEmptyRecovery,
3719
4404
  "no-error-message-assertion": noErrorMessageAssertion,
3720
4405
  "no-fake-ref-state": noFakeRefState,
4406
+ "no-floating-derived-type": noFloatingDerivedType,
4407
+ "no-gradient": noGradient,
3721
4408
  "no-hand-written-guard": noHandWrittenGuard,
3722
4409
  "no-in-operator": noInOperator,
3723
4410
  "no-let": noLet,
@@ -3736,13 +4423,16 @@ var oxlint_default = definePlugin({
3736
4423
  "no-renamed-import": noRenamedImport,
3737
4424
  "no-return-type": noReturnType,
3738
4425
  "no-single-use-value": noSingleUseValue,
4426
+ "no-stored-jsx": noStoredJsx,
3739
4427
  "no-stored-schema-operation": noStoredSchemaOperation,
3740
4428
  "no-switch-statement": noSwitchStatement,
3741
4429
  "no-trivial-indirection": noTrivialIndirection,
4430
+ "no-type-from-value": noTypeFromValue,
3742
4431
  "no-typeof": noTypeof,
3743
4432
  "no-undestructured-use-state": noUndestructuredUseState,
3744
4433
  "no-unexplained-disable": noUnexplainedDisable,
3745
4434
  "no-unvalidated-json-decode": noUnvalidatedJsonDecode,
4435
+ "preserve-error-cause": preserveErrorCause,
3746
4436
  "schema-type-pair": schemaTypePair
3747
4437
  }
3748
4438
  });