oxlint-plugin-react-doctor 0.2.11-dev.b2934f9 → 0.2.11-dev.b5cf767

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -5542,74 +5542,6 @@ declare const REACT_DOCTOR_RULES: readonly [{
5542
5542
  readonly recommendation?: string;
5543
5543
  readonly create: (context: RuleContext) => RuleVisitors;
5544
5544
  };
5545
- }, {
5546
- readonly key: "react-doctor/zod-v4-no-deprecated-error-apis";
5547
- readonly id: "zod-v4-no-deprecated-error-apis";
5548
- readonly source: "react-doctor";
5549
- readonly originallyExternal: false;
5550
- readonly rule: {
5551
- readonly framework: "global";
5552
- readonly category: "Architecture";
5553
- readonly id: string;
5554
- readonly severity: RuleSeverity;
5555
- readonly requires?: ReadonlyArray<string>;
5556
- readonly disabledBy?: ReadonlyArray<string>;
5557
- readonly tags?: ReadonlyArray<string>;
5558
- readonly defaultEnabled?: boolean;
5559
- readonly recommendation?: string;
5560
- readonly create: (context: RuleContext) => RuleVisitors;
5561
- };
5562
- }, {
5563
- readonly key: "react-doctor/zod-v4-no-deprecated-error-customization";
5564
- readonly id: "zod-v4-no-deprecated-error-customization";
5565
- readonly source: "react-doctor";
5566
- readonly originallyExternal: false;
5567
- readonly rule: {
5568
- readonly framework: "global";
5569
- readonly category: "Architecture";
5570
- readonly id: string;
5571
- readonly severity: RuleSeverity;
5572
- readonly requires?: ReadonlyArray<string>;
5573
- readonly disabledBy?: ReadonlyArray<string>;
5574
- readonly tags?: ReadonlyArray<string>;
5575
- readonly defaultEnabled?: boolean;
5576
- readonly recommendation?: string;
5577
- readonly create: (context: RuleContext) => RuleVisitors;
5578
- };
5579
- }, {
5580
- readonly key: "react-doctor/zod-v4-no-deprecated-schema-apis";
5581
- readonly id: "zod-v4-no-deprecated-schema-apis";
5582
- readonly source: "react-doctor";
5583
- readonly originallyExternal: false;
5584
- readonly rule: {
5585
- readonly framework: "global";
5586
- readonly category: "Architecture";
5587
- readonly id: string;
5588
- readonly severity: RuleSeverity;
5589
- readonly requires?: ReadonlyArray<string>;
5590
- readonly disabledBy?: ReadonlyArray<string>;
5591
- readonly tags?: ReadonlyArray<string>;
5592
- readonly defaultEnabled?: boolean;
5593
- readonly recommendation?: string;
5594
- readonly create: (context: RuleContext) => RuleVisitors;
5595
- };
5596
- }, {
5597
- readonly key: "react-doctor/zod-v4-prefer-top-level-string-formats";
5598
- readonly id: "zod-v4-prefer-top-level-string-formats";
5599
- readonly source: "react-doctor";
5600
- readonly originallyExternal: false;
5601
- readonly rule: {
5602
- readonly framework: "global";
5603
- readonly category: "Architecture";
5604
- readonly id: string;
5605
- readonly severity: RuleSeverity;
5606
- readonly requires?: ReadonlyArray<string>;
5607
- readonly disabledBy?: ReadonlyArray<string>;
5608
- readonly tags?: ReadonlyArray<string>;
5609
- readonly defaultEnabled?: boolean;
5610
- readonly recommendation?: string;
5611
- readonly create: (context: RuleContext) => RuleVisitors;
5612
- };
5613
5545
  }];
5614
5546
  declare const EXTERNAL_RULES: readonly [{
5615
5547
  readonly key: "react-hooks-js/set-state-in-render";
@@ -11082,74 +11014,6 @@ declare const RULES: readonly [{
11082
11014
  readonly recommendation?: string;
11083
11015
  readonly create: (context: RuleContext) => RuleVisitors;
11084
11016
  };
11085
- }, {
11086
- readonly key: "react-doctor/zod-v4-no-deprecated-error-apis";
11087
- readonly id: "zod-v4-no-deprecated-error-apis";
11088
- readonly source: "react-doctor";
11089
- readonly originallyExternal: false;
11090
- readonly rule: {
11091
- readonly framework: "global";
11092
- readonly category: "Architecture";
11093
- readonly id: string;
11094
- readonly severity: RuleSeverity;
11095
- readonly requires?: ReadonlyArray<string>;
11096
- readonly disabledBy?: ReadonlyArray<string>;
11097
- readonly tags?: ReadonlyArray<string>;
11098
- readonly defaultEnabled?: boolean;
11099
- readonly recommendation?: string;
11100
- readonly create: (context: RuleContext) => RuleVisitors;
11101
- };
11102
- }, {
11103
- readonly key: "react-doctor/zod-v4-no-deprecated-error-customization";
11104
- readonly id: "zod-v4-no-deprecated-error-customization";
11105
- readonly source: "react-doctor";
11106
- readonly originallyExternal: false;
11107
- readonly rule: {
11108
- readonly framework: "global";
11109
- readonly category: "Architecture";
11110
- readonly id: string;
11111
- readonly severity: RuleSeverity;
11112
- readonly requires?: ReadonlyArray<string>;
11113
- readonly disabledBy?: ReadonlyArray<string>;
11114
- readonly tags?: ReadonlyArray<string>;
11115
- readonly defaultEnabled?: boolean;
11116
- readonly recommendation?: string;
11117
- readonly create: (context: RuleContext) => RuleVisitors;
11118
- };
11119
- }, {
11120
- readonly key: "react-doctor/zod-v4-no-deprecated-schema-apis";
11121
- readonly id: "zod-v4-no-deprecated-schema-apis";
11122
- readonly source: "react-doctor";
11123
- readonly originallyExternal: false;
11124
- readonly rule: {
11125
- readonly framework: "global";
11126
- readonly category: "Architecture";
11127
- readonly id: string;
11128
- readonly severity: RuleSeverity;
11129
- readonly requires?: ReadonlyArray<string>;
11130
- readonly disabledBy?: ReadonlyArray<string>;
11131
- readonly tags?: ReadonlyArray<string>;
11132
- readonly defaultEnabled?: boolean;
11133
- readonly recommendation?: string;
11134
- readonly create: (context: RuleContext) => RuleVisitors;
11135
- };
11136
- }, {
11137
- readonly key: "react-doctor/zod-v4-prefer-top-level-string-formats";
11138
- readonly id: "zod-v4-prefer-top-level-string-formats";
11139
- readonly source: "react-doctor";
11140
- readonly originallyExternal: false;
11141
- readonly rule: {
11142
- readonly framework: "global";
11143
- readonly category: "Architecture";
11144
- readonly id: string;
11145
- readonly severity: RuleSeverity;
11146
- readonly requires?: ReadonlyArray<string>;
11147
- readonly disabledBy?: ReadonlyArray<string>;
11148
- readonly tags?: ReadonlyArray<string>;
11149
- readonly defaultEnabled?: boolean;
11150
- readonly recommendation?: string;
11151
- readonly create: (context: RuleContext) => RuleVisitors;
11152
- };
11153
11017
  }, {
11154
11018
  readonly key: "react-hooks-js/set-state-in-render";
11155
11019
  readonly source: "react-compiler";
package/dist/index.js CHANGED
@@ -26668,7 +26668,6 @@ const REACT_NATIVE_TEXT_COMPONENT_KEYWORDS = new Set([
26668
26668
  "Description",
26669
26669
  "Body"
26670
26670
  ]);
26671
- const REACT_NATIVE_TEXT_TRANSPARENT_COMPONENTS = new Set(["fbt", "fbs"]);
26672
26671
  const DEPRECATED_RN_MODULE_REPLACEMENTS = new Map([
26673
26672
  ["AsyncStorage", "@react-native-async-storage/async-storage"],
26674
26673
  ["Picker", "@react-native-picker/picker"],
@@ -27501,29 +27500,10 @@ const getRawTextDescription = (child) => {
27501
27500
  }
27502
27501
  return "text content";
27503
27502
  };
27504
- const resolveTextBoundaryName = (openingElement) => {
27505
- if (isNodeOfType(openingElement.name, "JSXNamespacedName")) return openingElement.name.namespace.name;
27506
- return resolveJsxElementName(openingElement);
27507
- };
27508
27503
  const isTextHandlingComponent = (elementName) => {
27509
27504
  if (REACT_NATIVE_TEXT_COMPONENTS.has(elementName)) return true;
27510
27505
  return [...REACT_NATIVE_TEXT_COMPONENT_KEYWORDS].some((keyword) => elementName.includes(keyword));
27511
27506
  };
27512
- const isTransparentTextWrapper = (elementName) => elementName !== null && REACT_NATIVE_TEXT_TRANSPARENT_COMPONENTS.has(elementName);
27513
- const isInsideTextHandlingComponent = (node) => {
27514
- let parentNode = node.parent;
27515
- while (parentNode) {
27516
- if (!isNodeOfType(parentNode, "JSXElement")) {
27517
- parentNode = parentNode.parent;
27518
- continue;
27519
- }
27520
- const parentName = resolveTextBoundaryName(parentNode.openingElement);
27521
- if (parentName && isTextHandlingComponent(parentName)) return true;
27522
- if (!isTransparentTextWrapper(parentName)) return false;
27523
- parentNode = parentNode.parent;
27524
- }
27525
- return false;
27526
- };
27527
27507
  const rnNoRawText = defineRule({
27528
27508
  id: "rn-no-raw-text",
27529
27509
  requires: ["react-native"],
@@ -27537,10 +27517,9 @@ const rnNoRawText = defineRule({
27537
27517
  },
27538
27518
  JSXElement(node) {
27539
27519
  if (isDomComponentFile) return;
27540
- const elementName = resolveTextBoundaryName(node.openingElement);
27520
+ const elementName = resolveJsxElementName(node.openingElement);
27541
27521
  if (elementName && isTextHandlingComponent(elementName)) return;
27542
27522
  if (isInsidePlatformOsWebBranch(node)) return;
27543
- if (isTransparentTextWrapper(elementName) && isInsideTextHandlingComponent(node)) return;
27544
27523
  for (const child of node.children ?? []) {
27545
27524
  if (!isRawTextContent(child)) continue;
27546
27525
  context.report({
@@ -33379,410 +33358,6 @@ const voidDomElementsNoChildren = defineRule({
33379
33358
  })
33380
33359
  });
33381
33360
  //#endregion
33382
- //#region src/plugin/rules/zod/utils/zod-ast.ts
33383
- const ZOD_MODULE = "zod";
33384
- const getStaticPropertyName = (member) => {
33385
- const property = member.property;
33386
- if (!member.computed && isNodeOfType(property, "Identifier")) return property.name;
33387
- if (member.computed && isNodeOfType(property, "Literal") && typeof property.value === "string") return property.value;
33388
- return null;
33389
- };
33390
- const getImportInfoForIdentifier = (identifier) => {
33391
- const specifier = findVariableInitializer(identifier, identifier.name)?.initializer;
33392
- if (!specifier) return null;
33393
- const declaration = specifier.parent;
33394
- if (!declaration || !isNodeOfType(declaration, "ImportDeclaration")) return null;
33395
- if (declaration.source?.value !== ZOD_MODULE) return null;
33396
- if (isNodeOfType(specifier, "ImportNamespaceSpecifier")) return {
33397
- imported: null,
33398
- isDefault: false,
33399
- isNamespace: true
33400
- };
33401
- if (isNodeOfType(specifier, "ImportDefaultSpecifier")) return {
33402
- imported: null,
33403
- isDefault: true,
33404
- isNamespace: false
33405
- };
33406
- if (isNodeOfType(specifier, "ImportSpecifier")) {
33407
- const imported = specifier.imported;
33408
- if (isNodeOfType(imported, "Identifier")) return {
33409
- imported: imported.name,
33410
- isDefault: false,
33411
- isNamespace: false
33412
- };
33413
- if (isNodeOfType(imported, "Literal") && typeof imported.value === "string") return {
33414
- imported: imported.value,
33415
- isDefault: false,
33416
- isNamespace: false
33417
- };
33418
- }
33419
- return null;
33420
- };
33421
- const isZodNamespaceIdentifier = (node) => {
33422
- const inner = stripParenExpression(node);
33423
- if (!isNodeOfType(inner, "Identifier")) return false;
33424
- const info = getImportInfoForIdentifier(inner);
33425
- return Boolean(info && (info.isNamespace || info.isDefault || info.imported === "z"));
33426
- };
33427
- const getZodNamedImport = (node) => {
33428
- const inner = stripParenExpression(node);
33429
- if (!isNodeOfType(inner, "Identifier")) return null;
33430
- const info = getImportInfoForIdentifier(inner);
33431
- if (!info || info.isNamespace || info.isDefault) return null;
33432
- return info.imported;
33433
- };
33434
- const getZodNamespaceMemberName = (node) => {
33435
- const inner = stripParenExpression(node);
33436
- if (!isNodeOfType(inner, "MemberExpression")) return null;
33437
- if (!isZodNamespaceIdentifier(inner.object)) return null;
33438
- return getStaticPropertyName(inner);
33439
- };
33440
- const isZodFactoryCall = (callExpression, factoryNames) => {
33441
- const factoryName = getZodFactoryCallName(callExpression);
33442
- return factoryName !== null && factoryNames.has(factoryName);
33443
- };
33444
- const getZodFactoryCallName = (callExpression) => {
33445
- const callee = stripParenExpression(callExpression.callee);
33446
- if (isNodeOfType(callee, "Identifier")) return getZodNamedImport(callee);
33447
- if (!isNodeOfType(callee, "MemberExpression")) return null;
33448
- const memberName = getStaticPropertyName(callee);
33449
- if (memberName === null) return null;
33450
- if (!isZodNamespaceIdentifier(callee.object)) return null;
33451
- return memberName;
33452
- };
33453
- const getMethodCall = (callExpression) => {
33454
- const callee = stripParenExpression(callExpression.callee);
33455
- if (!isNodeOfType(callee, "MemberExpression")) return null;
33456
- const methodName = getStaticPropertyName(callee);
33457
- if (!methodName) return null;
33458
- return {
33459
- methodName,
33460
- receiver: callee.object
33461
- };
33462
- };
33463
- const isDirectMethodCallOnZodFactory = (callExpression, factoryNames, methodNames) => {
33464
- const methodCall = getMethodCall(callExpression);
33465
- if (!methodCall || !methodNames.has(methodCall.methodName)) return false;
33466
- const receiver = stripParenExpression(methodCall.receiver);
33467
- return isNodeOfType(receiver, "CallExpression") && isZodFactoryCall(receiver, factoryNames);
33468
- };
33469
- const isObjectExpressionWithAnyProperty = (node, propertyNames) => {
33470
- if (!node) return false;
33471
- const inner = stripParenExpression(node);
33472
- if (!isNodeOfType(inner, "ObjectExpression")) return false;
33473
- return inner.properties.some((property) => {
33474
- if (!isNodeOfType(property, "Property")) return false;
33475
- const key = property.key;
33476
- if (isNodeOfType(key, "Identifier")) return propertyNames.has(key.name);
33477
- return isNodeOfType(key, "Literal") && typeof key.value === "string" && propertyNames.has(key.value);
33478
- });
33479
- };
33480
- //#endregion
33481
- //#region src/plugin/rules/zod/zod-v4-no-deprecated-error-apis.ts
33482
- const DEPRECATED_ZOD_ERROR_MEMBERS = new Set([
33483
- "addIssue",
33484
- "addIssues",
33485
- "errors",
33486
- "flatten",
33487
- "formErrors",
33488
- "format"
33489
- ]);
33490
- const ZOD_ERROR_API_MESSAGE = "Zod 4 removes or deprecates this ZodError API; use `error.issues` or the new top-level error formatting helpers.";
33491
- const isZodErrorReference = (node) => {
33492
- const inner = stripParenExpression(node);
33493
- if (isNodeOfType(inner, "Identifier")) return getZodNamedImport(inner) === "ZodError";
33494
- if (!isNodeOfType(inner, "MemberExpression")) return false;
33495
- return getZodNamespaceMemberName(inner) === "ZodError";
33496
- };
33497
- const isDirectZodErrorValue = (node) => {
33498
- const inner = stripParenExpression(node);
33499
- if (isNodeOfType(inner, "NewExpression")) return isZodErrorReference(inner.callee);
33500
- if (!isNodeOfType(inner, "CallExpression")) return false;
33501
- const methodCall = getMethodCall(inner);
33502
- return methodCall?.methodName === "create" && isZodErrorReference(methodCall.receiver);
33503
- };
33504
- const isDeprecatedZodErrorMemberAccess = (node) => {
33505
- if (!isNodeOfType(node, "MemberExpression")) return false;
33506
- const memberExpression = node;
33507
- const propertyName = getStaticPropertyName(memberExpression);
33508
- return propertyName !== null && DEPRECATED_ZOD_ERROR_MEMBERS.has(propertyName) && isDirectZodErrorValue(memberExpression.object);
33509
- };
33510
- const isZodErrorCreateCall = (callExpression) => {
33511
- const methodCall = getMethodCall(callExpression);
33512
- return methodCall?.methodName === "create" && isZodErrorReference(methodCall.receiver);
33513
- };
33514
- const isReceiverOfDeprecatedZodErrorMember = (callExpression) => {
33515
- const parent = callExpression.parent;
33516
- if (!parent || !isNodeOfType(parent, "MemberExpression")) return false;
33517
- if (stripParenExpression(parent.object) !== callExpression) return false;
33518
- return isDeprecatedZodErrorMemberAccess(parent);
33519
- };
33520
- const zodV4NoDeprecatedErrorApis = defineRule({
33521
- id: "zod-v4-no-deprecated-error-apis",
33522
- requires: ["zod:4"],
33523
- tags: ["migration-hint"],
33524
- severity: "warn",
33525
- recommendation: "Replace deprecated ZodError helpers with the Zod 4 functions: `z.treeifyError()`, `z.flattenError()`, `z.prettifyError()`, or direct `error.issues` access.",
33526
- create: (context) => ({
33527
- CallExpression(node) {
33528
- if (isZodErrorCreateCall(node) && isReceiverOfDeprecatedZodErrorMember(node)) return;
33529
- if (!isZodErrorCreateCall(node) && !isDeprecatedZodErrorMemberAccess(node.callee)) return;
33530
- context.report({
33531
- node,
33532
- message: ZOD_ERROR_API_MESSAGE
33533
- });
33534
- },
33535
- MemberExpression(node) {
33536
- const parent = node.parent;
33537
- if (parent && isNodeOfType(parent, "CallExpression") && stripParenExpression(parent.callee) === node) return;
33538
- if (!isDeprecatedZodErrorMemberAccess(node)) return;
33539
- context.report({
33540
- node,
33541
- message: ZOD_ERROR_API_MESSAGE
33542
- });
33543
- }
33544
- })
33545
- });
33546
- //#endregion
33547
- //#region src/plugin/rules/zod/zod-v4-no-deprecated-error-customization.ts
33548
- const ZOD_FACTORIES_WITH_ERROR_PARAMS = new Set([
33549
- "any",
33550
- "array",
33551
- "bigint",
33552
- "boolean",
33553
- "date",
33554
- "enum",
33555
- "literal",
33556
- "map",
33557
- "nativeEnum",
33558
- "never",
33559
- "null",
33560
- "number",
33561
- "object",
33562
- "record",
33563
- "set",
33564
- "string",
33565
- "tuple",
33566
- "undefined",
33567
- "union",
33568
- "unknown",
33569
- "void"
33570
- ]);
33571
- const DROPPED_ERROR_OPTION_PROPERTIES = new Set([
33572
- "errorMap",
33573
- "invalid_type_error",
33574
- "required_error"
33575
- ]);
33576
- const FACTORIES_WITH_LEGACY_FIRST_ARG_MESSAGE = new Set([
33577
- "bigint",
33578
- "boolean",
33579
- "date",
33580
- "number",
33581
- "string"
33582
- ]);
33583
- const ERROR_MAP_PROPERTY = new Set(["errorMap"]);
33584
- const PARSE_METHODS = new Set([
33585
- "parse",
33586
- "safeParse",
33587
- "parseAsync",
33588
- "safeParseAsync"
33589
- ]);
33590
- const firstArgumentIsMessageString = (callExpression) => {
33591
- const firstArgument = callExpression.arguments[0];
33592
- const inner = firstArgument ? stripParenExpression(firstArgument) : null;
33593
- return Boolean(inner && isNodeOfType(inner, "Literal") && typeof inner.value === "string");
33594
- };
33595
- const factoryUsesDeprecatedErrorParameter = (callExpression) => {
33596
- const factoryName = getZodFactoryCallName(callExpression);
33597
- if (factoryName === null || !ZOD_FACTORIES_WITH_ERROR_PARAMS.has(factoryName)) return false;
33598
- return FACTORIES_WITH_LEGACY_FIRST_ARG_MESSAGE.has(factoryName) && firstArgumentIsMessageString(callExpression) || callExpression.arguments.some((argument) => isObjectExpressionWithAnyProperty(argument, DROPPED_ERROR_OPTION_PROPERTIES));
33599
- };
33600
- const parseCallUsesErrorMap = (callExpression) => {
33601
- const methodCall = getMethodCall(callExpression);
33602
- if (!methodCall || !PARSE_METHODS.has(methodCall.methodName)) return false;
33603
- const receiver = stripParenExpression(methodCall.receiver);
33604
- if (!isNodeOfType(receiver, "CallExpression")) return false;
33605
- if (!isZodFactoryCall(receiver, ZOD_FACTORIES_WITH_ERROR_PARAMS)) return false;
33606
- return isObjectExpressionWithAnyProperty(callExpression.arguments[1], ERROR_MAP_PROPERTY);
33607
- };
33608
- const zodV4NoDeprecatedErrorCustomization = defineRule({
33609
- id: "zod-v4-no-deprecated-error-customization",
33610
- requires: ["zod:4"],
33611
- tags: ["migration-hint"],
33612
- severity: "warn",
33613
- recommendation: "Use Zod 4's unified `{ error }` callback/object customization instead of string message parameters, `invalid_type_error`, `required_error`, or `errorMap`.",
33614
- create: (context) => ({ CallExpression(node) {
33615
- if (!factoryUsesDeprecatedErrorParameter(node) && !parseCallUsesErrorMap(node)) return;
33616
- context.report({
33617
- node,
33618
- message: "Zod 4 replaces message parameters, `invalid_type_error`, `required_error`, and `errorMap` with the unified `error` API."
33619
- });
33620
- } })
33621
- });
33622
- //#endregion
33623
- //#region src/plugin/rules/zod/zod-v4-no-deprecated-schema-apis.ts
33624
- const OBJECT_FACTORY = new Set(["object"]);
33625
- const OBJECT_METHODS = new Set([
33626
- "deepPartial",
33627
- "merge",
33628
- "nonstrict",
33629
- "passthrough",
33630
- "strict",
33631
- "strip"
33632
- ]);
33633
- const NUMBER_FACTORY = new Set(["number"]);
33634
- const NUMBER_METHODS = new Set(["safe"]);
33635
- const FUNCTION_FACTORY = new Set(["function"]);
33636
- const FUNCTION_CHAIN_METHODS = new Set(["args", "returns"]);
33637
- const DEPRECATED_TOP_LEVEL_FACTORIES = new Set([
33638
- "nativeEnum",
33639
- "ostring",
33640
- "onumber",
33641
- "oboolean",
33642
- "oarray",
33643
- "promise"
33644
- ]);
33645
- const FACTORIES_WITH_DROPPED_CREATE = new Set([
33646
- "any",
33647
- "array",
33648
- "bigint",
33649
- "boolean",
33650
- "date",
33651
- "enum",
33652
- "function",
33653
- "literal",
33654
- "map",
33655
- "nativeEnum",
33656
- "never",
33657
- "null",
33658
- "number",
33659
- "object",
33660
- "optional",
33661
- "promise",
33662
- "record",
33663
- "set",
33664
- "string",
33665
- "tuple",
33666
- "undefined",
33667
- "union",
33668
- "unknown",
33669
- "void"
33670
- ]);
33671
- const ENUM_PROPERTY_ALIASES = new Set(["Enum", "Values"]);
33672
- const ENUM_FACTORY = new Set(["enum"]);
33673
- const RECORD_FACTORY = new Set(["record"]);
33674
- const LITERAL_FACTORY = new Set(["literal"]);
33675
- const reportSchemaMigration = (context, node) => {
33676
- context.report({
33677
- node,
33678
- message: "This Zod API is deprecated or changed in Zod 4; migrate to the recommended Zod 4 schema API."
33679
- });
33680
- };
33681
- const isCallToDeprecatedTopLevelFactory = (callExpression) => isZodFactoryCall(callExpression, DEPRECATED_TOP_LEVEL_FACTORIES);
33682
- const isCallToDroppedCreateFactory = (callExpression) => {
33683
- const methodCall = getMethodCall(callExpression);
33684
- if (!methodCall || methodCall.methodName !== "create") return false;
33685
- const receiver = stripParenExpression(methodCall.receiver);
33686
- const namespaceMemberName = getZodNamespaceMemberName(receiver);
33687
- if (namespaceMemberName !== null) return FACTORIES_WITH_DROPPED_CREATE.has(namespaceMemberName);
33688
- if (!isNodeOfType(receiver, "Identifier")) return false;
33689
- const imported = getZodNamedImport(receiver);
33690
- return imported !== null && FACTORIES_WITH_DROPPED_CREATE.has(imported);
33691
- };
33692
- const isSingleArgumentRecordCall = (callExpression) => callExpression.arguments.length === 1 && isZodFactoryCall(callExpression, RECORD_FACTORY);
33693
- const isDeprecatedFunctionChainCall = (callExpression) => isDirectMethodCallOnZodFactory(callExpression, FUNCTION_FACTORY, FUNCTION_CHAIN_METHODS);
33694
- const isSymbolLiteralArgument = (node) => {
33695
- if (!node) return false;
33696
- const inner = stripParenExpression(node);
33697
- if (isNodeOfType(inner, "CallExpression")) {
33698
- const callee = stripParenExpression(inner.callee);
33699
- return isNodeOfType(callee, "Identifier") && callee.name === "Symbol";
33700
- }
33701
- if (!isNodeOfType(inner, "MemberExpression")) return false;
33702
- const object = stripParenExpression(inner.object);
33703
- return isNodeOfType(object, "Identifier") && object.name === "Symbol";
33704
- };
33705
- const isLiteralSymbolCall = (callExpression) => callExpression.arguments.length > 0 && isZodFactoryCall(callExpression, LITERAL_FACTORY) && isSymbolLiteralArgument(callExpression.arguments[0]);
33706
- const isDroppedEnumAliasAccess = (memberExpression) => {
33707
- const propertyName = getStaticPropertyName(memberExpression);
33708
- if (propertyName === null || !ENUM_PROPERTY_ALIASES.has(propertyName)) return false;
33709
- const receiver = stripParenExpression(memberExpression.object);
33710
- return isNodeOfType(receiver, "CallExpression") && isZodFactoryCall(receiver, ENUM_FACTORY);
33711
- };
33712
- const isRefineSecondArgumentFunction = (callExpression) => {
33713
- const methodCall = getMethodCall(callExpression);
33714
- if (!methodCall || methodCall.methodName !== "refine") return false;
33715
- const receiver = stripParenExpression(methodCall.receiver);
33716
- if (!isNodeOfType(receiver, "CallExpression")) return false;
33717
- if (!isZodFactoryCall(receiver, FACTORIES_WITH_DROPPED_CREATE)) return false;
33718
- const secondArgument = callExpression.arguments[1];
33719
- return isNodeOfType(secondArgument, "FunctionExpression") || isNodeOfType(secondArgument, "ArrowFunctionExpression");
33720
- };
33721
- const isZodNamespaceImportMemberCreate = (memberExpression) => {
33722
- if (getStaticPropertyName(memberExpression) !== "create") return false;
33723
- const receiver = stripParenExpression(memberExpression.object);
33724
- if (!isNodeOfType(receiver, "MemberExpression")) return false;
33725
- const factoryName = getStaticPropertyName(receiver);
33726
- return factoryName !== null && FACTORIES_WITH_DROPPED_CREATE.has(factoryName) && isZodNamespaceIdentifier(receiver.object);
33727
- };
33728
- const zodV4NoDeprecatedSchemaApis = defineRule({
33729
- id: "zod-v4-no-deprecated-schema-apis",
33730
- requires: ["zod:4"],
33731
- tags: ["migration-hint"],
33732
- severity: "warn",
33733
- recommendation: "Migrate Zod 4 schema APIs that were deprecated, changed, or removed: use top-level factories such as `z.enum()`, object helpers such as `z.strictObject()`, the new `z.function({ input, output })` form, and explicit key/value schemas for `z.record()`.",
33734
- create: (context) => ({
33735
- CallExpression(node) {
33736
- if (isCallToDeprecatedTopLevelFactory(node) || isCallToDroppedCreateFactory(node) || isSingleArgumentRecordCall(node) || isLiteralSymbolCall(node) || isDeprecatedFunctionChainCall(node) || isDirectMethodCallOnZodFactory(node, OBJECT_FACTORY, OBJECT_METHODS) || isDirectMethodCallOnZodFactory(node, NUMBER_FACTORY, NUMBER_METHODS) || isRefineSecondArgumentFunction(node)) reportSchemaMigration(context, node);
33737
- },
33738
- MemberExpression(node) {
33739
- const parent = node.parent;
33740
- if (parent && isNodeOfType(parent, "CallExpression") && stripParenExpression(parent.callee) === node) return;
33741
- if (isDroppedEnumAliasAccess(node) || isZodNamespaceImportMemberCreate(node)) reportSchemaMigration(context, node);
33742
- }
33743
- })
33744
- });
33745
- //#endregion
33746
- //#region src/plugin/rules/zod/zod-v4-prefer-top-level-string-formats.ts
33747
- const ZOD_STRING_FACTORY = new Set(["string"]);
33748
- const STRING_FORMAT_METHODS = new Set([
33749
- "base64",
33750
- "base64url",
33751
- "cidr",
33752
- "cidrv4",
33753
- "cidrv6",
33754
- "cuid",
33755
- "cuid2",
33756
- "date",
33757
- "datetime",
33758
- "duration",
33759
- "email",
33760
- "emoji",
33761
- "ip",
33762
- "ipv4",
33763
- "ipv6",
33764
- "jwt",
33765
- "nanoid",
33766
- "time",
33767
- "ulid",
33768
- "url",
33769
- "uuid"
33770
- ]);
33771
- const zodV4PreferTopLevelStringFormats = defineRule({
33772
- id: "zod-v4-prefer-top-level-string-formats",
33773
- requires: ["zod:4"],
33774
- tags: ["migration-hint"],
33775
- severity: "warn",
33776
- recommendation: "Replace deprecated `z.string().<format>()` calls with Zod 4 top-level string format APIs like `z.email()`, `z.uuid()`, `z.ipv4()`, or `z.cidrv4()`.",
33777
- create: (context) => ({ CallExpression(node) {
33778
- if (!isDirectMethodCallOnZodFactory(node, ZOD_STRING_FACTORY, STRING_FORMAT_METHODS)) return;
33779
- context.report({
33780
- node,
33781
- message: "Zod 4 deprecates string format methods on `z.string()`; use the matching top-level Zod format API instead."
33782
- });
33783
- } })
33784
- });
33785
- //#endregion
33786
33361
  //#region src/plugin/rule-registry.ts
33787
33362
  const reactDoctorRules = [
33788
33363
  {
@@ -37319,50 +36894,6 @@ const reactDoctorRules = [
37319
36894
  framework: "global",
37320
36895
  category: "Correctness"
37321
36896
  }
37322
- },
37323
- {
37324
- key: "react-doctor/zod-v4-no-deprecated-error-apis",
37325
- id: "zod-v4-no-deprecated-error-apis",
37326
- source: "react-doctor",
37327
- originallyExternal: false,
37328
- rule: {
37329
- ...zodV4NoDeprecatedErrorApis,
37330
- framework: "global",
37331
- category: "Architecture"
37332
- }
37333
- },
37334
- {
37335
- key: "react-doctor/zod-v4-no-deprecated-error-customization",
37336
- id: "zod-v4-no-deprecated-error-customization",
37337
- source: "react-doctor",
37338
- originallyExternal: false,
37339
- rule: {
37340
- ...zodV4NoDeprecatedErrorCustomization,
37341
- framework: "global",
37342
- category: "Architecture"
37343
- }
37344
- },
37345
- {
37346
- key: "react-doctor/zod-v4-no-deprecated-schema-apis",
37347
- id: "zod-v4-no-deprecated-schema-apis",
37348
- source: "react-doctor",
37349
- originallyExternal: false,
37350
- rule: {
37351
- ...zodV4NoDeprecatedSchemaApis,
37352
- framework: "global",
37353
- category: "Architecture"
37354
- }
37355
- },
37356
- {
37357
- key: "react-doctor/zod-v4-prefer-top-level-string-formats",
37358
- id: "zod-v4-prefer-top-level-string-formats",
37359
- source: "react-doctor",
37360
- originallyExternal: false,
37361
- rule: {
37362
- ...zodV4PreferTopLevelStringFormats,
37363
- framework: "global",
37364
- category: "Architecture"
37365
- }
37366
36897
  }
37367
36898
  ];
37368
36899
  const ruleRegistry = Object.fromEntries(reactDoctorRules.map((rule) => [rule.id, rule.rule]));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oxlint-plugin-react-doctor",
3
- "version": "0.2.11-dev.b2934f9",
3
+ "version": "0.2.11-dev.b5cf767",
4
4
  "description": "oxlint plugin for React Doctor: diagnose React codebases for security, performance, correctness, accessibility, bundle-size, and architecture issues",
5
5
  "keywords": [
6
6
  "accessibility",