@schemashift/zod-v3-v4 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -50,8 +50,10 @@ var BEHAVIOR_CHANGES = /* @__PURE__ */ new Set([
50
50
  // Stricter discriminator requirements
51
51
  "function",
52
52
  // Input/output parameter changes
53
- "pipe"
53
+ "pipe",
54
54
  // Stricter type checking in v4
55
+ "catch"
56
+ // .catch() on optional properties always returns catch value in v4
55
57
  ]);
56
58
  var DEPRECATED_METHODS = /* @__PURE__ */ new Set([
57
59
  "merge",
@@ -64,8 +66,19 @@ var DEPRECATED_METHODS = /* @__PURE__ */ new Set([
64
66
  // Use z.looseObject() instead
65
67
  ]);
66
68
  var AUTO_TRANSFORMABLE = /* @__PURE__ */ new Set([
67
- "superRefine"
69
+ "superRefine",
68
70
  // -> .check()
71
+ "flatten",
72
+ // error.flatten() -> z.flattenError(error)
73
+ "format"
74
+ // error.format() -> z.treeifyError(error)
75
+ ]);
76
+ var UTILITY_TYPES = /* @__PURE__ */ new Set([
77
+ "ZodType",
78
+ "ZodSchema",
79
+ "ZodRawShape",
80
+ "ZodTypeAny",
81
+ "ZodFirstPartyTypeKind"
69
82
  ]);
70
83
 
71
84
  // src/transformer.ts
@@ -85,11 +98,15 @@ var ZodV3ToV4Transformer = class {
85
98
  this.transformErrorProperties(sourceFile);
86
99
  this.transformErrorParams(sourceFile);
87
100
  this.transformFlatten(sourceFile);
101
+ this.transformFormat(sourceFile);
102
+ this.transformDefAccess(sourceFile);
88
103
  this.checkDeprecatedMethods(sourceFile);
89
104
  this.checkBehaviorChanges(sourceFile);
90
105
  this.checkInstanceofError(sourceFile);
91
106
  this.checkTransformRefineOrder(sourceFile);
92
107
  this.checkDefaultOptional(sourceFile);
108
+ this.checkCatchOptional(sourceFile);
109
+ this.checkUtilityTypeImports(sourceFile);
93
110
  return {
94
111
  success: this.errors.length === 0,
95
112
  filePath,
@@ -138,18 +155,16 @@ var ZodV3ToV4Transformer = class {
138
155
  });
139
156
  }
140
157
  /**
141
- * Transform error.errors to error.issues using AST-based detection
142
- * instead of heuristic name matching.
158
+ * Build a set of variable names that are likely ZodError instances.
159
+ * Used by transformErrorProperties, transformFlatten, and transformFormat.
143
160
  */
144
- transformErrorProperties(sourceFile) {
145
- const filePath = sourceFile.getFilePath();
161
+ buildZodErrorVarSet(sourceFile) {
146
162
  const zodErrorVars = /* @__PURE__ */ new Set();
147
163
  sourceFile.forEachDescendant((node) => {
148
164
  if (import_ts_morph.Node.isVariableDeclaration(node)) {
149
165
  const typeNode = node.getTypeNode();
150
166
  if (typeNode?.getText().includes("ZodError")) {
151
- const name = node.getName();
152
- zodErrorVars.add(name);
167
+ zodErrorVars.add(node.getName());
153
168
  }
154
169
  }
155
170
  if (import_ts_morph.Node.isCatchClause(node)) {
@@ -177,6 +192,15 @@ var ZodV3ToV4Transformer = class {
177
192
  }
178
193
  }
179
194
  });
195
+ return zodErrorVars;
196
+ }
197
+ /**
198
+ * Transform error.errors to error.issues using AST-based detection
199
+ * instead of heuristic name matching.
200
+ */
201
+ transformErrorProperties(sourceFile) {
202
+ const filePath = sourceFile.getFilePath();
203
+ const zodErrorVars = this.buildZodErrorVarSet(sourceFile);
180
204
  sourceFile.forEachDescendant((node) => {
181
205
  if (import_ts_morph.Node.isPropertyAccessExpression(node)) {
182
206
  const name = node.getName();
@@ -198,21 +222,90 @@ var ZodV3ToV4Transformer = class {
198
222
  });
199
223
  }
200
224
  /**
201
- * Transform .flatten() usage removed in v4.
225
+ * Auto-transform error.flatten() to z.flattenError(error) in v4.
202
226
  */
203
227
  transformFlatten(sourceFile) {
204
228
  const filePath = sourceFile.getFilePath();
229
+ const zodErrorVars = this.buildZodErrorVarSet(sourceFile);
230
+ const nodesToTransform = [];
205
231
  sourceFile.forEachDescendant((node) => {
206
232
  if (import_ts_morph.Node.isCallExpression(node)) {
207
233
  const expression = node.getExpression();
208
234
  if (import_ts_morph.Node.isPropertyAccessExpression(expression) && expression.getName() === "flatten") {
209
- const lineNumber = node.getStartLineNumber();
210
- this.warnings.push(
211
- `${filePath}:${lineNumber}: .flatten() is removed in v4. Use error.issues directly or implement custom flattening. See: https://zod.dev/v4/changelog#flatten-removed`
212
- );
235
+ const objectText = expression.getExpression().getText();
236
+ const isZodError = zodErrorVars.has(objectText) || objectText.endsWith(".error") && zodErrorVars.has(`${objectText.replace(/\.error$/, "")}.error`);
237
+ if (isZodError) {
238
+ nodesToTransform.push({
239
+ node,
240
+ objectText,
241
+ lineNumber: node.getStartLineNumber()
242
+ });
243
+ } else {
244
+ this.warnings.push(
245
+ `${filePath}:${node.getStartLineNumber()}: .flatten() is removed in v4. Use z.flattenError(error) or access error.issues directly. See: https://zod.dev/v4/changelog`
246
+ );
247
+ }
248
+ }
249
+ }
250
+ });
251
+ nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());
252
+ for (const { node, objectText, lineNumber } of nodesToTransform) {
253
+ node.replaceWithText(`z.flattenError(${objectText})`);
254
+ this.warnings.push(
255
+ `${filePath}:${lineNumber}: .flatten() auto-transformed to z.flattenError(). Removed in v4 \u2014 now a standalone function.`
256
+ );
257
+ }
258
+ }
259
+ /**
260
+ * Auto-transform error.format() to z.treeifyError(error) in v4.
261
+ */
262
+ transformFormat(sourceFile) {
263
+ const filePath = sourceFile.getFilePath();
264
+ const zodErrorVars = this.buildZodErrorVarSet(sourceFile);
265
+ const nodesToTransform = [];
266
+ sourceFile.forEachDescendant((node) => {
267
+ if (import_ts_morph.Node.isCallExpression(node)) {
268
+ const expression = node.getExpression();
269
+ if (import_ts_morph.Node.isPropertyAccessExpression(expression) && expression.getName() === "format") {
270
+ const objectText = expression.getExpression().getText();
271
+ const isZodError = zodErrorVars.has(objectText) || objectText.endsWith(".error") && zodErrorVars.has(`${objectText.replace(/\.error$/, "")}.error`);
272
+ if (isZodError) {
273
+ nodesToTransform.push({
274
+ node,
275
+ objectText,
276
+ lineNumber: node.getStartLineNumber()
277
+ });
278
+ }
213
279
  }
214
280
  }
215
281
  });
282
+ nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());
283
+ for (const { node, objectText, lineNumber } of nodesToTransform) {
284
+ node.replaceWithText(`z.treeifyError(${objectText})`);
285
+ this.warnings.push(
286
+ `${filePath}:${lineNumber}: .format() auto-transformed to z.treeifyError(). Removed in v4 \u2014 now a standalone function.`
287
+ );
288
+ }
289
+ }
290
+ /**
291
+ * Auto-transform ._def property access to ._zod.def in v4.
292
+ */
293
+ transformDefAccess(sourceFile) {
294
+ const filePath = sourceFile.getFilePath();
295
+ const nodesToTransform = [];
296
+ sourceFile.forEachDescendant((node) => {
297
+ if (import_ts_morph.Node.isPropertyAccessExpression(node) && node.getName() === "_def") {
298
+ nodesToTransform.push({ node, lineNumber: node.getStartLineNumber() });
299
+ }
300
+ });
301
+ nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());
302
+ for (const { node, lineNumber } of nodesToTransform) {
303
+ const objectText = node.getExpression().getText();
304
+ node.replaceWithText(`${objectText}._zod.def`);
305
+ this.warnings.push(
306
+ `${filePath}:${lineNumber}: ._def auto-transformed to ._zod.def. Internal API \u2014 structure may change between releases.`
307
+ );
308
+ }
216
309
  }
217
310
  /**
218
311
  * Transform .merge(otherSchema) to .extend(otherSchema.shape)
@@ -305,7 +398,28 @@ var ZodV3ToV4Transformer = class {
305
398
  const parent = node.getParent();
306
399
  if (parent && import_ts_morph.Node.isCallExpression(parent)) {
307
400
  const objectText = node.getExpression().getText();
308
- const argsText = parent.getArguments().map((a) => a.getText()).join(", ");
401
+ const args = parent.getArguments();
402
+ let argsText = args.map((a) => a.getText()).join(", ");
403
+ if (args.length > 0) {
404
+ const callbackText = args[0]?.getText() ?? "";
405
+ const paramMatch = callbackText.match(
406
+ /^\s*\(?\s*\w+\s*,\s*(\w+)\s*\)?(?:\s*:\s*[^)]+)?\s*=>/
407
+ );
408
+ if (paramMatch?.[1]) {
409
+ const ctxName = paramMatch[1];
410
+ const addIssuePattern = new RegExp(`${ctxName}\\.addIssue\\(`, "g");
411
+ if (addIssuePattern.test(callbackText)) {
412
+ argsText = callbackText.replace(
413
+ new RegExp(`${ctxName}\\.addIssue\\(`, "g"),
414
+ `${ctxName}.issues.push(`
415
+ );
416
+ if (args.length > 1) {
417
+ const remaining = args.slice(1).map((a) => a.getText()).join(", ");
418
+ argsText = `${argsText}, ${remaining}`;
419
+ }
420
+ }
421
+ }
422
+ }
309
423
  parent.replaceWithText(`${objectText}.check(${argsText})`);
310
424
  this.warnings.push(
311
425
  `${filePath}:${lineNumber}: .superRefine() auto-transformed to .check() (deprecated in v4).`
@@ -475,16 +589,51 @@ var ZodV3ToV4Transformer = class {
475
589
  break;
476
590
  }
477
591
  }
478
- if (name === "format") {
592
+ }
593
+ }
594
+ });
595
+ }
596
+ /**
597
+ * Detect .catch() combined with .optional() — behavior changed in v4.
598
+ * In v4, .catch() on optional properties always returns the catch value.
599
+ */
600
+ checkCatchOptional(sourceFile) {
601
+ const filePath = sourceFile.getFilePath();
602
+ sourceFile.forEachDescendant((node) => {
603
+ if (import_ts_morph.Node.isCallExpression(node)) {
604
+ const expression = node.getExpression();
605
+ if (import_ts_morph.Node.isPropertyAccessExpression(expression) && (expression.getName() === "optional" || expression.getName() === "catch")) {
606
+ const chainText = node.getText();
607
+ if (chainText.includes(".catch(") && chainText.includes(".optional(")) {
479
608
  const lineNumber = node.getStartLineNumber();
480
609
  this.warnings.push(
481
- `${filePath}:${lineNumber}: .format() is removed in v4. Use z.treeifyError() or custom error formatting. See: https://zod.dev/v4/changelog`
610
+ `${filePath}:${lineNumber}: .catch() + .optional() behavior changed in v4. .catch() on optional properties now always returns the catch value, even when the property is absent from input.`
482
611
  );
483
612
  }
484
613
  }
485
614
  }
486
615
  });
487
616
  }
617
+ /**
618
+ * Detect imports of utility types that moved to 'zod/v4/core' in v4.
619
+ */
620
+ checkUtilityTypeImports(sourceFile) {
621
+ const filePath = sourceFile.getFilePath();
622
+ for (const importDecl of sourceFile.getImportDeclarations()) {
623
+ const moduleSpecifier = importDecl.getModuleSpecifierValue();
624
+ if (moduleSpecifier !== "zod") continue;
625
+ const namedImports = importDecl.getNamedImports();
626
+ for (const namedImport of namedImports) {
627
+ const name = namedImport.getName();
628
+ if (UTILITY_TYPES.has(name)) {
629
+ const lineNumber = importDecl.getStartLineNumber();
630
+ this.warnings.push(
631
+ `${filePath}:${lineNumber}: '${name}' may need to be imported from 'zod/v4/core' in v4. Internal utility types have moved to a separate subpackage.`
632
+ );
633
+ }
634
+ }
635
+ }
636
+ }
488
637
  };
489
638
 
490
639
  // src/handler.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/transformer.ts","../src/mappings.ts","../src/handler.ts"],"sourcesContent":["export { createZodV3ToV4Handler } from './handler.js';\nexport { BEHAVIOR_CHANGES, V3_TO_V4_PATTERNS } from './mappings.js';\nexport { ZodV3ToV4Transformer } from './transformer.js';\n","import type { TransformError, TransformResult } from '@schemashift/core';\nimport { Node, type SourceFile } from 'ts-morph';\nimport { AUTO_TRANSFORMABLE, BEHAVIOR_CHANGES, DEPRECATED_METHODS } from './mappings.js';\n\n/**\n * Zod v3 to v4 Transformer\n *\n * Handles breaking changes between Zod v3 and v4:\n * - z.record() now requires explicit key type\n * - error.errors -> error.issues\n * - Stricter UUID validation\n * - Type inference changes in .default()\n * - .flatten() removed\n * - z.preprocess() -> z.pipe() migration\n */\nexport class ZodV3ToV4Transformer {\n private errors: TransformError[] = [];\n private warnings: string[] = [];\n\n transform(sourceFile: SourceFile): TransformResult {\n this.errors = [];\n this.warnings = [];\n\n const filePath = sourceFile.getFilePath();\n const originalCode = sourceFile.getFullText();\n\n try {\n this.transformRecordCalls(sourceFile);\n this.transformMerge(sourceFile);\n this.transformNativeEnum(sourceFile);\n this.transformSuperRefine(sourceFile);\n this.transformErrorProperties(sourceFile);\n this.transformErrorParams(sourceFile);\n this.transformFlatten(sourceFile);\n this.checkDeprecatedMethods(sourceFile);\n this.checkBehaviorChanges(sourceFile);\n this.checkInstanceofError(sourceFile);\n this.checkTransformRefineOrder(sourceFile);\n this.checkDefaultOptional(sourceFile);\n\n return {\n success: this.errors.length === 0,\n filePath,\n originalCode,\n transformedCode: sourceFile.getFullText(),\n errors: this.errors,\n warnings: this.warnings,\n };\n } catch (error) {\n this.errors.push({\n message: error instanceof Error ? error.message : 'Unknown error',\n });\n return {\n success: false,\n filePath,\n originalCode,\n errors: this.errors,\n warnings: this.warnings,\n };\n }\n }\n\n /**\n * Transform z.record(valueSchema) to z.record(z.string(), valueSchema)\n */\n private transformRecordCalls(sourceFile: SourceFile): void {\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n\n if (Node.isPropertyAccessExpression(expression)) {\n const name = expression.getName();\n const object = expression.getExpression();\n\n if (name === 'record' && object.getText() === 'z') {\n const args = node.getArguments();\n\n // If only one argument, add z.string() as key type\n if (args.length === 1) {\n const valueSchema = args[0]?.getText();\n if (valueSchema) {\n node.replaceWithText(`z.record(z.string(), ${valueSchema})`);\n\n this.warnings.push(\n `${sourceFile.getFilePath()}:${node.getStartLineNumber()}: ` +\n 'z.record() updated to include explicit key type z.string()',\n );\n }\n }\n }\n }\n }\n });\n }\n\n /**\n * Transform error.errors to error.issues using AST-based detection\n * instead of heuristic name matching.\n */\n private transformErrorProperties(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n // First, find all variables that are likely ZodError instances\n const zodErrorVars = new Set<string>();\n\n sourceFile.forEachDescendant((node) => {\n // Check variable declarations with ZodError type annotation\n if (Node.isVariableDeclaration(node)) {\n const typeNode = node.getTypeNode();\n if (typeNode?.getText().includes('ZodError')) {\n const name = node.getName();\n zodErrorVars.add(name);\n }\n }\n\n // Check catch clause parameters\n if (Node.isCatchClause(node)) {\n const param = node.getVariableDeclaration();\n if (param) {\n // Check if the catch block uses instanceof ZodError\n const block = node.getBlock();\n const blockText = block.getText();\n if (blockText.includes('instanceof ZodError') || blockText.includes('ZodError')) {\n zodErrorVars.add(param.getName());\n }\n }\n }\n\n // Check for .safeParse() result — the error is in result.error\n if (Node.isVariableDeclaration(node)) {\n const initializer = node.getInitializer();\n if (initializer?.getText().includes('.safeParse(')) {\n // The result of safeParse has a .error property that is ZodError\n zodErrorVars.add(`${node.getName()}.error`);\n }\n }\n\n // Check for import { ZodError } or new ZodError patterns\n if (Node.isNewExpression(node)) {\n if (node.getExpression().getText() === 'ZodError') {\n const parent = node.getParent();\n if (parent && Node.isVariableDeclaration(parent)) {\n zodErrorVars.add(parent.getName());\n }\n }\n }\n });\n\n // Now transform .errors -> .issues only on identified ZodError variables\n sourceFile.forEachDescendant((node) => {\n if (Node.isPropertyAccessExpression(node)) {\n const name = node.getName();\n if (name === 'errors') {\n const object = node.getExpression();\n const objectText = object.getText();\n\n // Check if this object is a known ZodError variable\n const isZodError =\n zodErrorVars.has(objectText) ||\n // Also check if accessing .error.errors (safeParse pattern)\n (objectText.endsWith('.error') &&\n zodErrorVars.has(`${objectText.replace(/\\.error$/, '')}.error`));\n\n if (isZodError) {\n const fullText = node.getText();\n const newText = fullText.replace(/\\.errors$/, '.issues');\n node.replaceWithText(newText);\n\n this.warnings.push(\n `${filePath}:${node.getStartLineNumber()}: ` +\n '.errors renamed to .issues (ZodError property change)',\n );\n }\n }\n }\n });\n }\n\n /**\n * Transform .flatten() usage — removed in v4.\n */\n private transformFlatten(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression) && expression.getName() === 'flatten') {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: .flatten() is removed in v4. ` +\n 'Use error.issues directly or implement custom flattening. ' +\n 'See: https://zod.dev/v4/changelog#flatten-removed',\n );\n }\n }\n });\n }\n\n /**\n * Transform .merge(otherSchema) to .extend(otherSchema.shape)\n */\n private transformMerge(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const nodesToTransform: Array<{ node: import('ts-morph').CallExpression; lineNumber: number }> =\n [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression) && expression.getName() === 'merge') {\n nodesToTransform.push({ node, lineNumber: node.getStartLineNumber() });\n }\n }\n });\n\n // Process in reverse order\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, lineNumber } of nodesToTransform) {\n const args = node.getArguments();\n if (args.length === 1) {\n const argText = args[0]?.getText();\n if (argText) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression)) {\n const objectText = expression.getExpression().getText();\n node.replaceWithText(`${objectText}.extend(${argText}.shape)`);\n this.warnings.push(\n `${filePath}:${lineNumber}: .merge() renamed to .extend() with .shape access. ` +\n 'Verify the merged schema exposes .shape.',\n );\n }\n }\n }\n }\n }\n\n /**\n * Transform z.nativeEnum(X) to z.enum(X)\n */\n private transformNativeEnum(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const fullText = sourceFile.getFullText();\n const newText = fullText.replace(/\\bz\\.nativeEnum\\(/g, 'z.enum(');\n if (newText !== fullText) {\n sourceFile.replaceWithText(newText);\n this.warnings.push(\n `${filePath}: z.nativeEnum() renamed to z.enum() in v4. ` +\n 'Verify enum values are compatible.',\n );\n }\n }\n\n /**\n * Check for deprecated methods and add warnings\n */\n private checkDeprecatedMethods(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression)) {\n const name = expression.getName();\n if (DEPRECATED_METHODS.has(name) && !AUTO_TRANSFORMABLE.has(name)) {\n const lineNumber = node.getStartLineNumber();\n switch (name) {\n case 'strict':\n this.warnings.push(\n `${filePath}:${lineNumber}: .strict() is deprecated in v4. ` +\n 'Use z.strictObject() instead.',\n );\n break;\n case 'passthrough':\n this.warnings.push(\n `${filePath}:${lineNumber}: .passthrough() is deprecated in v4. ` +\n 'Use z.looseObject() instead.',\n );\n break;\n // merge is handled by transformMerge\n }\n }\n }\n }\n });\n }\n\n /**\n * Auto-transform .superRefine() to .check() — callback signature is identical.\n */\n private transformSuperRefine(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const nodesToTransform: Array<{\n node: import('ts-morph').PropertyAccessExpression;\n lineNumber: number;\n }> = [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isPropertyAccessExpression(node) && node.getName() === 'superRefine') {\n nodesToTransform.push({ node, lineNumber: node.getStartLineNumber() });\n }\n });\n\n // Process in reverse to preserve positions\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, lineNumber } of nodesToTransform) {\n const parent = node.getParent();\n if (parent && Node.isCallExpression(parent)) {\n const objectText = node.getExpression().getText();\n const argsText = parent\n .getArguments()\n .map((a) => a.getText())\n .join(', ');\n parent.replaceWithText(`${objectText}.check(${argsText})`);\n this.warnings.push(\n `${filePath}:${lineNumber}: .superRefine() auto-transformed to .check() (deprecated in v4).`,\n );\n }\n }\n }\n\n /**\n * Auto-transform invalid_type_error/required_error params to unified `error` param.\n */\n private transformErrorParams(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const nodesToTransform: Array<{\n node: import('ts-morph').ObjectLiteralExpression;\n lineNumber: number;\n }> = [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isObjectLiteralExpression(node)) {\n const properties = node.getProperties();\n const propNames = properties\n .filter((p) => Node.isPropertyAssignment(p))\n .map((p) => (Node.isPropertyAssignment(p) ? p.getName() : ''));\n\n const hasInvalidType = propNames.includes('invalid_type_error');\n const hasRequired = propNames.includes('required_error');\n\n if (hasInvalidType || hasRequired) {\n // Only transform if this is an argument to a z.xxx() factory call\n const parent = node.getParent();\n if (parent && Node.isCallExpression(parent)) {\n const expr = parent.getExpression();\n if (Node.isPropertyAccessExpression(expr) && expr.getExpression().getText() === 'z') {\n nodesToTransform.push({ node, lineNumber: node.getStartLineNumber() });\n }\n }\n }\n }\n });\n\n // Process in reverse to preserve positions\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, lineNumber } of nodesToTransform) {\n const properties = node.getProperties();\n let invalidTypeValue: string | undefined;\n let requiredValue: string | undefined;\n const otherProps: string[] = [];\n\n for (const prop of properties) {\n if (Node.isPropertyAssignment(prop)) {\n const name = prop.getName();\n const value = prop.getInitializer()?.getText() ?? '';\n if (name === 'invalid_type_error') {\n invalidTypeValue = value;\n } else if (name === 'required_error') {\n requiredValue = value;\n } else {\n otherProps.push(prop.getText());\n }\n }\n }\n\n let errorValue: string;\n if (invalidTypeValue && requiredValue) {\n // Both present: generate error function\n errorValue = `error: (issue) => issue.input === undefined ? ${requiredValue} : ${invalidTypeValue}`;\n } else if (requiredValue) {\n errorValue = `error: ${requiredValue}`;\n } else if (invalidTypeValue) {\n errorValue = `error: ${invalidTypeValue}`;\n } else {\n continue;\n }\n\n const allProps = [errorValue, ...otherProps].join(', ');\n node.replaceWithText(`{ ${allProps} }`);\n\n this.warnings.push(\n `${filePath}:${lineNumber}: invalid_type_error/required_error auto-transformed to unified error param.`,\n );\n }\n }\n\n /**\n * Detect instanceof Error patterns in catch blocks that reference ZodError.\n * In v4, ZodError no longer extends Error.\n */\n private checkInstanceofError(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCatchClause(node)) {\n const block = node.getBlock();\n const blockText = block.getText();\n\n // Check if the catch block references ZodError AND uses instanceof Error\n if (blockText.includes('ZodError') && blockText.includes('instanceof Error')) {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: ZodError no longer extends Error in v4. ` +\n '`instanceof Error` checks on ZodError will return false. ' +\n 'Use `instanceof ZodError` or check for `.issues` property instead.',\n );\n }\n }\n });\n }\n\n /**\n * Detect .refine()/.superRefine() followed by .transform() in the same chain.\n * In v4, .transform() runs even when .refine() fails.\n */\n private checkTransformRefineOrder(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression) && expression.getName() === 'transform') {\n // Walk up the chain to see if .refine() or .superRefine() precedes\n const chainText = node.getText();\n if (\n chainText.includes('.refine(') ||\n chainText.includes('.superRefine(') ||\n chainText.includes('.check(')\n ) {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: In v4, .transform() executes even if preceding .refine() fails. ` +\n 'Consider using .pipe() to sequence validation before transforms.',\n );\n }\n }\n }\n });\n }\n\n /**\n * Detect .default() combined with .optional() — behavior changed silently in v4.\n * In v4, .default() always provides a value, making .optional() a no-op.\n */\n private checkDefaultOptional(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (\n Node.isPropertyAccessExpression(expression) &&\n (expression.getName() === 'optional' || expression.getName() === 'default')\n ) {\n const chainText = node.getText();\n const hasDefault = chainText.includes('.default(');\n const hasOptional = chainText.includes('.optional(');\n\n if (hasDefault && hasOptional) {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: .default() + .optional() behavior changed in v4. ` +\n '.default() now always provides a value, making .optional() effectively a no-op. ' +\n 'Review whether .optional() is still needed.',\n );\n }\n }\n }\n });\n }\n\n /**\n * Check for methods with behavior changes and add warnings\n */\n private checkBehaviorChanges(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n\n if (Node.isPropertyAccessExpression(expression)) {\n const name = expression.getName();\n\n if (BEHAVIOR_CHANGES.has(name)) {\n const lineNumber = node.getStartLineNumber();\n\n switch (name) {\n case 'default':\n this.warnings.push(\n `${filePath}:${lineNumber}: .default() has stricter type inference in v4. ` +\n 'Verify default value matches schema type exactly.',\n );\n break;\n\n case 'uuid':\n this.warnings.push(\n `${filePath}:${lineNumber}: .uuid() now enforces strict RFC 4122 compliance. ` +\n 'Non-standard UUIDs may fail validation.',\n );\n break;\n\n case 'discriminatedUnion':\n this.warnings.push(\n `${filePath}:${lineNumber}: z.discriminatedUnion() now requires ` +\n 'a literal type for the discriminator property.',\n );\n break;\n\n case 'function':\n this.warnings.push(\n `${filePath}:${lineNumber}: z.function() parameter handling has changed. ` +\n 'Review input/output schema definitions.',\n );\n break;\n\n case 'pipe':\n this.warnings.push(\n `${filePath}:${lineNumber}: .pipe() has stricter type checking in v4. ` +\n 'If you get type errors, add explicit type annotations to .transform() return types ' +\n 'or cast through unknown as a last resort.',\n );\n break;\n }\n }\n\n // Check for .format() which was removed\n if (name === 'format') {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: .format() is removed in v4. ` +\n 'Use z.treeifyError() or custom error formatting. ' +\n 'See: https://zod.dev/v4/changelog',\n );\n }\n }\n }\n });\n }\n}\n","/**\n * Zod v3 to v4 Breaking Changes\n *\n * Key changes in Zod v4:\n * 1. z.record() now requires explicit key type\n * 2. .default() has stricter type inference\n * 3. error.errors renamed to error.issues\n * 4. .uuid() has stricter validation (RFC 4122 compliant)\n * 5. z.function() input/output changed\n * 6. Branded types use different syntax\n * 7. z.discriminatedUnion() requires literal discriminator\n */\n\n// Patterns that need transformation\nexport const V3_TO_V4_PATTERNS = {\n // z.record(valueSchema) -> z.record(z.string(), valueSchema)\n recordSingleArg: /z\\.record\\((?!z\\.string\\(\\)|z\\.number\\(\\)|z\\.symbol\\(\\))/g,\n\n // error.errors -> error.issues\n errorErrors: /\\.errors\\b/g,\n\n // .brand<T>() -> .brand<T>() (same but check for proper usage)\n brandUsage: /\\.brand<([^>]+)>\\(\\)/g,\n};\n\n// Methods that have changed behavior\nexport const BEHAVIOR_CHANGES = new Set([\n 'default', // Type inference changed\n 'uuid', // Stricter validation\n 'record', // Requires key type\n 'discriminatedUnion', // Stricter discriminator requirements\n 'function', // Input/output parameter changes\n 'pipe', // Stricter type checking in v4\n]);\n\n// Error property renames\nexport const ERROR_RENAMES: Record<string, string> = {\n errors: 'issues',\n formErrors: 'formErrors', // Unchanged\n fieldErrors: 'fieldErrors', // Unchanged\n};\n\n// Methods that are deprecated in v4\nexport const DEPRECATED_METHODS = new Set([\n 'merge', // Use .extend() instead\n 'superRefine', // Use .check() instead\n 'strict', // Use z.strictObject() instead\n 'passthrough', // Use z.looseObject() instead\n]);\n\n// Method renames in v4\nexport const METHOD_RENAMES: Record<string, string> = {\n merge: 'extend',\n};\n\n// Factory function renames in v4\nexport const FACTORY_RENAMES: Record<string, string> = {\n nativeEnum: 'enum',\n};\n\n// Error params that changed in v4 (unified under `error`)\nexport const ERROR_PARAM_NAMES = new Set(['invalid_type_error', 'required_error']);\n\n// Methods that can be automatically transformed (renamed) in v4\nexport const AUTO_TRANSFORMABLE = new Set([\n 'superRefine', // -> .check()\n]);\n\n// Runtime behavior patterns that silently break in v4 (no compile-time error)\nexport const RUNTIME_BREAK_PATTERNS = new Set([\n 'instanceofError', // ZodError no longer extends Error\n 'transformAfterRefine', // .transform() runs even when .refine() fails\n 'defaultOptional', // .default() + .optional() behavior change\n]);\n","import type { TransformHandler, TransformOptions, TransformResult } from '@schemashift/core';\nimport type { SourceFile } from 'ts-morph';\nimport { ZodV3ToV4Transformer } from './transformer.js';\n\nexport function createZodV3ToV4Handler(): TransformHandler {\n const transformer = new ZodV3ToV4Transformer();\n return {\n transform(sourceFile: SourceFile, _options: TransformOptions): TransformResult {\n return transformer.transform(sourceFile);\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,sBAAsC;;;ACa/B,IAAM,oBAAoB;AAAA;AAAA,EAE/B,iBAAiB;AAAA;AAAA,EAGjB,aAAa;AAAA;AAAA,EAGb,YAAY;AACd;AAGO,IAAM,mBAAmB,oBAAI,IAAI;AAAA,EACtC;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF,CAAC;AAUM,IAAM,qBAAqB,oBAAI,IAAI;AAAA,EACxC;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF,CAAC;AAgBM,IAAM,qBAAqB,oBAAI,IAAI;AAAA,EACxC;AAAA;AACF,CAAC;;;ADnDM,IAAM,uBAAN,MAA2B;AAAA,EACxB,SAA2B,CAAC;AAAA,EAC5B,WAAqB,CAAC;AAAA,EAE9B,UAAU,YAAyC;AACjD,SAAK,SAAS,CAAC;AACf,SAAK,WAAW,CAAC;AAEjB,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,eAAe,WAAW,YAAY;AAE5C,QAAI;AACF,WAAK,qBAAqB,UAAU;AACpC,WAAK,eAAe,UAAU;AAC9B,WAAK,oBAAoB,UAAU;AACnC,WAAK,qBAAqB,UAAU;AACpC,WAAK,yBAAyB,UAAU;AACxC,WAAK,qBAAqB,UAAU;AACpC,WAAK,iBAAiB,UAAU;AAChC,WAAK,uBAAuB,UAAU;AACtC,WAAK,qBAAqB,UAAU;AACpC,WAAK,qBAAqB,UAAU;AACpC,WAAK,0BAA0B,UAAU;AACzC,WAAK,qBAAqB,UAAU;AAEpC,aAAO;AAAA,QACL,SAAS,KAAK,OAAO,WAAW;AAAA,QAChC;AAAA,QACA;AAAA,QACA,iBAAiB,WAAW,YAAY;AAAA,QACxC,QAAQ,KAAK;AAAA,QACb,UAAU,KAAK;AAAA,MACjB;AAAA,IACF,SAAS,OAAO;AACd,WAAK,OAAO,KAAK;AAAA,QACf,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MACpD,CAAC;AACD,aAAO;AAAA,QACL,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA,QAAQ,KAAK;AAAA,QACb,UAAU,KAAK;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,YAA8B;AACzD,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,qBAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,aAAa,KAAK,cAAc;AAEtC,YAAI,qBAAK,2BAA2B,UAAU,GAAG;AAC/C,gBAAM,OAAO,WAAW,QAAQ;AAChC,gBAAM,SAAS,WAAW,cAAc;AAExC,cAAI,SAAS,YAAY,OAAO,QAAQ,MAAM,KAAK;AACjD,kBAAM,OAAO,KAAK,aAAa;AAG/B,gBAAI,KAAK,WAAW,GAAG;AACrB,oBAAM,cAAc,KAAK,CAAC,GAAG,QAAQ;AACrC,kBAAI,aAAa;AACf,qBAAK,gBAAgB,wBAAwB,WAAW,GAAG;AAE3D,qBAAK,SAAS;AAAA,kBACZ,GAAG,WAAW,YAAY,CAAC,IAAI,KAAK,mBAAmB,CAAC;AAAA,gBAE1D;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,yBAAyB,YAA8B;AAC7D,UAAM,WAAW,WAAW,YAAY;AAGxC,UAAM,eAAe,oBAAI,IAAY;AAErC,eAAW,kBAAkB,CAAC,SAAS;AAErC,UAAI,qBAAK,sBAAsB,IAAI,GAAG;AACpC,cAAM,WAAW,KAAK,YAAY;AAClC,YAAI,UAAU,QAAQ,EAAE,SAAS,UAAU,GAAG;AAC5C,gBAAM,OAAO,KAAK,QAAQ;AAC1B,uBAAa,IAAI,IAAI;AAAA,QACvB;AAAA,MACF;AAGA,UAAI,qBAAK,cAAc,IAAI,GAAG;AAC5B,cAAM,QAAQ,KAAK,uBAAuB;AAC1C,YAAI,OAAO;AAET,gBAAM,QAAQ,KAAK,SAAS;AAC5B,gBAAM,YAAY,MAAM,QAAQ;AAChC,cAAI,UAAU,SAAS,qBAAqB,KAAK,UAAU,SAAS,UAAU,GAAG;AAC/E,yBAAa,IAAI,MAAM,QAAQ,CAAC;AAAA,UAClC;AAAA,QACF;AAAA,MACF;AAGA,UAAI,qBAAK,sBAAsB,IAAI,GAAG;AACpC,cAAM,cAAc,KAAK,eAAe;AACxC,YAAI,aAAa,QAAQ,EAAE,SAAS,aAAa,GAAG;AAElD,uBAAa,IAAI,GAAG,KAAK,QAAQ,CAAC,QAAQ;AAAA,QAC5C;AAAA,MACF;AAGA,UAAI,qBAAK,gBAAgB,IAAI,GAAG;AAC9B,YAAI,KAAK,cAAc,EAAE,QAAQ,MAAM,YAAY;AACjD,gBAAM,SAAS,KAAK,UAAU;AAC9B,cAAI,UAAU,qBAAK,sBAAsB,MAAM,GAAG;AAChD,yBAAa,IAAI,OAAO,QAAQ,CAAC;AAAA,UACnC;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAGD,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,qBAAK,2BAA2B,IAAI,GAAG;AACzC,cAAM,OAAO,KAAK,QAAQ;AAC1B,YAAI,SAAS,UAAU;AACrB,gBAAM,SAAS,KAAK,cAAc;AAClC,gBAAM,aAAa,OAAO,QAAQ;AAGlC,gBAAM,aACJ,aAAa,IAAI,UAAU;AAAA,UAE1B,WAAW,SAAS,QAAQ,KAC3B,aAAa,IAAI,GAAG,WAAW,QAAQ,YAAY,EAAE,CAAC,QAAQ;AAElE,cAAI,YAAY;AACd,kBAAM,WAAW,KAAK,QAAQ;AAC9B,kBAAM,UAAU,SAAS,QAAQ,aAAa,SAAS;AACvD,iBAAK,gBAAgB,OAAO;AAE5B,iBAAK,SAAS;AAAA,cACZ,GAAG,QAAQ,IAAI,KAAK,mBAAmB,CAAC;AAAA,YAE1C;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAiB,YAA8B;AACrD,UAAM,WAAW,WAAW,YAAY;AAExC,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,qBAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,aAAa,KAAK,cAAc;AACtC,YAAI,qBAAK,2BAA2B,UAAU,KAAK,WAAW,QAAQ,MAAM,WAAW;AACrF,gBAAM,aAAa,KAAK,mBAAmB;AAC3C,eAAK,SAAS;AAAA,YACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,UAG3B;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,YAA8B;AACnD,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,mBACJ,CAAC;AAEH,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,qBAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,aAAa,KAAK,cAAc;AACtC,YAAI,qBAAK,2BAA2B,UAAU,KAAK,WAAW,QAAQ,MAAM,SAAS;AACnF,2BAAiB,KAAK,EAAE,MAAM,YAAY,KAAK,mBAAmB,EAAE,CAAC;AAAA,QACvE;AAAA,MACF;AAAA,IACF,CAAC;AAGD,qBAAiB,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS,CAAC;AAErE,eAAW,EAAE,MAAM,WAAW,KAAK,kBAAkB;AACnD,YAAM,OAAO,KAAK,aAAa;AAC/B,UAAI,KAAK,WAAW,GAAG;AACrB,cAAM,UAAU,KAAK,CAAC,GAAG,QAAQ;AACjC,YAAI,SAAS;AACX,gBAAM,aAAa,KAAK,cAAc;AACtC,cAAI,qBAAK,2BAA2B,UAAU,GAAG;AAC/C,kBAAM,aAAa,WAAW,cAAc,EAAE,QAAQ;AACtD,iBAAK,gBAAgB,GAAG,UAAU,WAAW,OAAO,SAAS;AAC7D,iBAAK,SAAS;AAAA,cACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,YAE3B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAoB,YAA8B;AACxD,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,UAAU,SAAS,QAAQ,sBAAsB,SAAS;AAChE,QAAI,YAAY,UAAU;AACxB,iBAAW,gBAAgB,OAAO;AAClC,WAAK,SAAS;AAAA,QACZ,GAAG,QAAQ;AAAA,MAEb;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAAuB,YAA8B;AAC3D,UAAM,WAAW,WAAW,YAAY;AAExC,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,qBAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,aAAa,KAAK,cAAc;AACtC,YAAI,qBAAK,2BAA2B,UAAU,GAAG;AAC/C,gBAAM,OAAO,WAAW,QAAQ;AAChC,cAAI,mBAAmB,IAAI,IAAI,KAAK,CAAC,mBAAmB,IAAI,IAAI,GAAG;AACjE,kBAAM,aAAa,KAAK,mBAAmB;AAC3C,oBAAQ,MAAM;AAAA,cACZ,KAAK;AACH,qBAAK,SAAS;AAAA,kBACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,gBAE3B;AACA;AAAA,cACF,KAAK;AACH,qBAAK,SAAS;AAAA,kBACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,gBAE3B;AACA;AAAA,YAEJ;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,YAA8B;AACzD,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,mBAGD,CAAC;AAEN,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,qBAAK,2BAA2B,IAAI,KAAK,KAAK,QAAQ,MAAM,eAAe;AAC7E,yBAAiB,KAAK,EAAE,MAAM,YAAY,KAAK,mBAAmB,EAAE,CAAC;AAAA,MACvE;AAAA,IACF,CAAC;AAGD,qBAAiB,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS,CAAC;AAErE,eAAW,EAAE,MAAM,WAAW,KAAK,kBAAkB;AACnD,YAAM,SAAS,KAAK,UAAU;AAC9B,UAAI,UAAU,qBAAK,iBAAiB,MAAM,GAAG;AAC3C,cAAM,aAAa,KAAK,cAAc,EAAE,QAAQ;AAChD,cAAM,WAAW,OACd,aAAa,EACb,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EACtB,KAAK,IAAI;AACZ,eAAO,gBAAgB,GAAG,UAAU,UAAU,QAAQ,GAAG;AACzD,aAAK,SAAS;AAAA,UACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,YAA8B;AACzD,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,mBAGD,CAAC;AAEN,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,qBAAK,0BAA0B,IAAI,GAAG;AACxC,cAAM,aAAa,KAAK,cAAc;AACtC,cAAM,YAAY,WACf,OAAO,CAAC,MAAM,qBAAK,qBAAqB,CAAC,CAAC,EAC1C,IAAI,CAAC,MAAO,qBAAK,qBAAqB,CAAC,IAAI,EAAE,QAAQ,IAAI,EAAG;AAE/D,cAAM,iBAAiB,UAAU,SAAS,oBAAoB;AAC9D,cAAM,cAAc,UAAU,SAAS,gBAAgB;AAEvD,YAAI,kBAAkB,aAAa;AAEjC,gBAAM,SAAS,KAAK,UAAU;AAC9B,cAAI,UAAU,qBAAK,iBAAiB,MAAM,GAAG;AAC3C,kBAAM,OAAO,OAAO,cAAc;AAClC,gBAAI,qBAAK,2BAA2B,IAAI,KAAK,KAAK,cAAc,EAAE,QAAQ,MAAM,KAAK;AACnF,+BAAiB,KAAK,EAAE,MAAM,YAAY,KAAK,mBAAmB,EAAE,CAAC;AAAA,YACvE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAGD,qBAAiB,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS,CAAC;AAErE,eAAW,EAAE,MAAM,WAAW,KAAK,kBAAkB;AACnD,YAAM,aAAa,KAAK,cAAc;AACtC,UAAI;AACJ,UAAI;AACJ,YAAM,aAAuB,CAAC;AAE9B,iBAAW,QAAQ,YAAY;AAC7B,YAAI,qBAAK,qBAAqB,IAAI,GAAG;AACnC,gBAAM,OAAO,KAAK,QAAQ;AAC1B,gBAAM,QAAQ,KAAK,eAAe,GAAG,QAAQ,KAAK;AAClD,cAAI,SAAS,sBAAsB;AACjC,+BAAmB;AAAA,UACrB,WAAW,SAAS,kBAAkB;AACpC,4BAAgB;AAAA,UAClB,OAAO;AACL,uBAAW,KAAK,KAAK,QAAQ,CAAC;AAAA,UAChC;AAAA,QACF;AAAA,MACF;AAEA,UAAI;AACJ,UAAI,oBAAoB,eAAe;AAErC,qBAAa,iDAAiD,aAAa,MAAM,gBAAgB;AAAA,MACnG,WAAW,eAAe;AACxB,qBAAa,UAAU,aAAa;AAAA,MACtC,WAAW,kBAAkB;AAC3B,qBAAa,UAAU,gBAAgB;AAAA,MACzC,OAAO;AACL;AAAA,MACF;AAEA,YAAM,WAAW,CAAC,YAAY,GAAG,UAAU,EAAE,KAAK,IAAI;AACtD,WAAK,gBAAgB,KAAK,QAAQ,IAAI;AAEtC,WAAK,SAAS;AAAA,QACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,qBAAqB,YAA8B;AACzD,UAAM,WAAW,WAAW,YAAY;AAExC,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,qBAAK,cAAc,IAAI,GAAG;AAC5B,cAAM,QAAQ,KAAK,SAAS;AAC5B,cAAM,YAAY,MAAM,QAAQ;AAGhC,YAAI,UAAU,SAAS,UAAU,KAAK,UAAU,SAAS,kBAAkB,GAAG;AAC5E,gBAAM,aAAa,KAAK,mBAAmB;AAC3C,eAAK,SAAS;AAAA,YACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,UAG3B;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,0BAA0B,YAA8B;AAC9D,UAAM,WAAW,WAAW,YAAY;AAExC,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,qBAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,aAAa,KAAK,cAAc;AACtC,YAAI,qBAAK,2BAA2B,UAAU,KAAK,WAAW,QAAQ,MAAM,aAAa;AAEvF,gBAAM,YAAY,KAAK,QAAQ;AAC/B,cACE,UAAU,SAAS,UAAU,KAC7B,UAAU,SAAS,eAAe,KAClC,UAAU,SAAS,SAAS,GAC5B;AACA,kBAAM,aAAa,KAAK,mBAAmB;AAC3C,iBAAK,SAAS;AAAA,cACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,YAE3B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,qBAAqB,YAA8B;AACzD,UAAM,WAAW,WAAW,YAAY;AAExC,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,qBAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,aAAa,KAAK,cAAc;AACtC,YACE,qBAAK,2BAA2B,UAAU,MACzC,WAAW,QAAQ,MAAM,cAAc,WAAW,QAAQ,MAAM,YACjE;AACA,gBAAM,YAAY,KAAK,QAAQ;AAC/B,gBAAM,aAAa,UAAU,SAAS,WAAW;AACjD,gBAAM,cAAc,UAAU,SAAS,YAAY;AAEnD,cAAI,cAAc,aAAa;AAC7B,kBAAM,aAAa,KAAK,mBAAmB;AAC3C,iBAAK,SAAS;AAAA,cACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,YAG3B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,YAA8B;AACzD,UAAM,WAAW,WAAW,YAAY;AAExC,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,qBAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,aAAa,KAAK,cAAc;AAEtC,YAAI,qBAAK,2BAA2B,UAAU,GAAG;AAC/C,gBAAM,OAAO,WAAW,QAAQ;AAEhC,cAAI,iBAAiB,IAAI,IAAI,GAAG;AAC9B,kBAAM,aAAa,KAAK,mBAAmB;AAE3C,oBAAQ,MAAM;AAAA,cACZ,KAAK;AACH,qBAAK,SAAS;AAAA,kBACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,gBAE3B;AACA;AAAA,cAEF,KAAK;AACH,qBAAK,SAAS;AAAA,kBACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,gBAE3B;AACA;AAAA,cAEF,KAAK;AACH,qBAAK,SAAS;AAAA,kBACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,gBAE3B;AACA;AAAA,cAEF,KAAK;AACH,qBAAK,SAAS;AAAA,kBACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,gBAE3B;AACA;AAAA,cAEF,KAAK;AACH,qBAAK,SAAS;AAAA,kBACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,gBAG3B;AACA;AAAA,YACJ;AAAA,UACF;AAGA,cAAI,SAAS,UAAU;AACrB,kBAAM,aAAa,KAAK,mBAAmB;AAC3C,iBAAK,SAAS;AAAA,cACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,YAG3B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AEriBO,SAAS,yBAA2C;AACzD,QAAM,cAAc,IAAI,qBAAqB;AAC7C,SAAO;AAAA,IACL,UAAU,YAAwB,UAA6C;AAC7E,aAAO,YAAY,UAAU,UAAU;AAAA,IACzC;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/transformer.ts","../src/mappings.ts","../src/handler.ts"],"sourcesContent":["export { createZodV3ToV4Handler } from './handler.js';\nexport { BEHAVIOR_CHANGES, V3_TO_V4_PATTERNS } from './mappings.js';\nexport { ZodV3ToV4Transformer } from './transformer.js';\n","import type { TransformError, TransformResult } from '@schemashift/core';\nimport { Node, type SourceFile } from 'ts-morph';\nimport {\n AUTO_TRANSFORMABLE,\n BEHAVIOR_CHANGES,\n DEPRECATED_METHODS,\n UTILITY_TYPES,\n} from './mappings.js';\n\n/**\n * Zod v3 to v4 Transformer\n *\n * Handles breaking changes between Zod v3 and v4:\n * - z.record() now requires explicit key type\n * - error.errors -> error.issues\n * - Stricter UUID validation\n * - Type inference changes in .default()\n * - .flatten() removed\n * - z.preprocess() -> z.pipe() migration\n */\nexport class ZodV3ToV4Transformer {\n private errors: TransformError[] = [];\n private warnings: string[] = [];\n\n transform(sourceFile: SourceFile): TransformResult {\n this.errors = [];\n this.warnings = [];\n\n const filePath = sourceFile.getFilePath();\n const originalCode = sourceFile.getFullText();\n\n try {\n this.transformRecordCalls(sourceFile);\n this.transformMerge(sourceFile);\n this.transformNativeEnum(sourceFile);\n this.transformSuperRefine(sourceFile);\n this.transformErrorProperties(sourceFile);\n this.transformErrorParams(sourceFile);\n this.transformFlatten(sourceFile);\n this.transformFormat(sourceFile);\n this.transformDefAccess(sourceFile);\n this.checkDeprecatedMethods(sourceFile);\n this.checkBehaviorChanges(sourceFile);\n this.checkInstanceofError(sourceFile);\n this.checkTransformRefineOrder(sourceFile);\n this.checkDefaultOptional(sourceFile);\n this.checkCatchOptional(sourceFile);\n this.checkUtilityTypeImports(sourceFile);\n\n return {\n success: this.errors.length === 0,\n filePath,\n originalCode,\n transformedCode: sourceFile.getFullText(),\n errors: this.errors,\n warnings: this.warnings,\n };\n } catch (error) {\n this.errors.push({\n message: error instanceof Error ? error.message : 'Unknown error',\n });\n return {\n success: false,\n filePath,\n originalCode,\n errors: this.errors,\n warnings: this.warnings,\n };\n }\n }\n\n /**\n * Transform z.record(valueSchema) to z.record(z.string(), valueSchema)\n */\n private transformRecordCalls(sourceFile: SourceFile): void {\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n\n if (Node.isPropertyAccessExpression(expression)) {\n const name = expression.getName();\n const object = expression.getExpression();\n\n if (name === 'record' && object.getText() === 'z') {\n const args = node.getArguments();\n\n // If only one argument, add z.string() as key type\n if (args.length === 1) {\n const valueSchema = args[0]?.getText();\n if (valueSchema) {\n node.replaceWithText(`z.record(z.string(), ${valueSchema})`);\n\n this.warnings.push(\n `${sourceFile.getFilePath()}:${node.getStartLineNumber()}: ` +\n 'z.record() updated to include explicit key type z.string()',\n );\n }\n }\n }\n }\n }\n });\n }\n\n /**\n * Build a set of variable names that are likely ZodError instances.\n * Used by transformErrorProperties, transformFlatten, and transformFormat.\n */\n private buildZodErrorVarSet(sourceFile: SourceFile): Set<string> {\n const zodErrorVars = new Set<string>();\n\n sourceFile.forEachDescendant((node) => {\n // Check variable declarations with ZodError type annotation\n if (Node.isVariableDeclaration(node)) {\n const typeNode = node.getTypeNode();\n if (typeNode?.getText().includes('ZodError')) {\n zodErrorVars.add(node.getName());\n }\n }\n\n // Check catch clause parameters\n if (Node.isCatchClause(node)) {\n const param = node.getVariableDeclaration();\n if (param) {\n const block = node.getBlock();\n const blockText = block.getText();\n if (blockText.includes('instanceof ZodError') || blockText.includes('ZodError')) {\n zodErrorVars.add(param.getName());\n }\n }\n }\n\n // Check for .safeParse() result — the error is in result.error\n if (Node.isVariableDeclaration(node)) {\n const initializer = node.getInitializer();\n if (initializer?.getText().includes('.safeParse(')) {\n zodErrorVars.add(`${node.getName()}.error`);\n }\n }\n\n // Check for new ZodError patterns\n if (Node.isNewExpression(node)) {\n if (node.getExpression().getText() === 'ZodError') {\n const parent = node.getParent();\n if (parent && Node.isVariableDeclaration(parent)) {\n zodErrorVars.add(parent.getName());\n }\n }\n }\n });\n\n return zodErrorVars;\n }\n\n /**\n * Transform error.errors to error.issues using AST-based detection\n * instead of heuristic name matching.\n */\n private transformErrorProperties(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const zodErrorVars = this.buildZodErrorVarSet(sourceFile);\n\n // Now transform .errors -> .issues only on identified ZodError variables\n sourceFile.forEachDescendant((node) => {\n if (Node.isPropertyAccessExpression(node)) {\n const name = node.getName();\n if (name === 'errors') {\n const object = node.getExpression();\n const objectText = object.getText();\n\n // Check if this object is a known ZodError variable\n const isZodError =\n zodErrorVars.has(objectText) ||\n // Also check if accessing .error.errors (safeParse pattern)\n (objectText.endsWith('.error') &&\n zodErrorVars.has(`${objectText.replace(/\\.error$/, '')}.error`));\n\n if (isZodError) {\n const fullText = node.getText();\n const newText = fullText.replace(/\\.errors$/, '.issues');\n node.replaceWithText(newText);\n\n this.warnings.push(\n `${filePath}:${node.getStartLineNumber()}: ` +\n '.errors renamed to .issues (ZodError property change)',\n );\n }\n }\n }\n });\n }\n\n /**\n * Auto-transform error.flatten() to z.flattenError(error) in v4.\n */\n private transformFlatten(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const zodErrorVars = this.buildZodErrorVarSet(sourceFile);\n\n const nodesToTransform: Array<{\n node: import('ts-morph').CallExpression;\n objectText: string;\n lineNumber: number;\n }> = [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression) && expression.getName() === 'flatten') {\n const objectText = expression.getExpression().getText();\n const isZodError =\n zodErrorVars.has(objectText) ||\n (objectText.endsWith('.error') &&\n zodErrorVars.has(`${objectText.replace(/\\.error$/, '')}.error`));\n\n if (isZodError) {\n nodesToTransform.push({\n node,\n objectText,\n lineNumber: node.getStartLineNumber(),\n });\n } else {\n this.warnings.push(\n `${filePath}:${node.getStartLineNumber()}: .flatten() is removed in v4. ` +\n 'Use z.flattenError(error) or access error.issues directly. ' +\n 'See: https://zod.dev/v4/changelog',\n );\n }\n }\n }\n });\n\n // Process in reverse order to preserve positions\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, objectText, lineNumber } of nodesToTransform) {\n node.replaceWithText(`z.flattenError(${objectText})`);\n this.warnings.push(\n `${filePath}:${lineNumber}: .flatten() auto-transformed to z.flattenError(). ` +\n 'Removed in v4 — now a standalone function.',\n );\n }\n }\n\n /**\n * Auto-transform error.format() to z.treeifyError(error) in v4.\n */\n private transformFormat(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const zodErrorVars = this.buildZodErrorVarSet(sourceFile);\n\n const nodesToTransform: Array<{\n node: import('ts-morph').CallExpression;\n objectText: string;\n lineNumber: number;\n }> = [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression) && expression.getName() === 'format') {\n const objectText = expression.getExpression().getText();\n const isZodError =\n zodErrorVars.has(objectText) ||\n (objectText.endsWith('.error') &&\n zodErrorVars.has(`${objectText.replace(/\\.error$/, '')}.error`));\n\n if (isZodError) {\n nodesToTransform.push({\n node,\n objectText,\n lineNumber: node.getStartLineNumber(),\n });\n }\n // Skip non-ZodError .format() calls to avoid false positives\n }\n }\n });\n\n // Process in reverse order to preserve positions\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, objectText, lineNumber } of nodesToTransform) {\n node.replaceWithText(`z.treeifyError(${objectText})`);\n this.warnings.push(\n `${filePath}:${lineNumber}: .format() auto-transformed to z.treeifyError(). ` +\n 'Removed in v4 — now a standalone function.',\n );\n }\n }\n\n /**\n * Auto-transform ._def property access to ._zod.def in v4.\n */\n private transformDefAccess(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const nodesToTransform: Array<{\n node: import('ts-morph').PropertyAccessExpression;\n lineNumber: number;\n }> = [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isPropertyAccessExpression(node) && node.getName() === '_def') {\n nodesToTransform.push({ node, lineNumber: node.getStartLineNumber() });\n }\n });\n\n // Process in reverse order to preserve positions\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, lineNumber } of nodesToTransform) {\n const objectText = node.getExpression().getText();\n node.replaceWithText(`${objectText}._zod.def`);\n this.warnings.push(\n `${filePath}:${lineNumber}: ._def auto-transformed to ._zod.def. ` +\n 'Internal API — structure may change between releases.',\n );\n }\n }\n\n /**\n * Transform .merge(otherSchema) to .extend(otherSchema.shape)\n */\n private transformMerge(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const nodesToTransform: Array<{ node: import('ts-morph').CallExpression; lineNumber: number }> =\n [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression) && expression.getName() === 'merge') {\n nodesToTransform.push({ node, lineNumber: node.getStartLineNumber() });\n }\n }\n });\n\n // Process in reverse order\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, lineNumber } of nodesToTransform) {\n const args = node.getArguments();\n if (args.length === 1) {\n const argText = args[0]?.getText();\n if (argText) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression)) {\n const objectText = expression.getExpression().getText();\n node.replaceWithText(`${objectText}.extend(${argText}.shape)`);\n this.warnings.push(\n `${filePath}:${lineNumber}: .merge() renamed to .extend() with .shape access. ` +\n 'Verify the merged schema exposes .shape.',\n );\n }\n }\n }\n }\n }\n\n /**\n * Transform z.nativeEnum(X) to z.enum(X)\n */\n private transformNativeEnum(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const fullText = sourceFile.getFullText();\n const newText = fullText.replace(/\\bz\\.nativeEnum\\(/g, 'z.enum(');\n if (newText !== fullText) {\n sourceFile.replaceWithText(newText);\n this.warnings.push(\n `${filePath}: z.nativeEnum() renamed to z.enum() in v4. ` +\n 'Verify enum values are compatible.',\n );\n }\n }\n\n /**\n * Check for deprecated methods and add warnings\n */\n private checkDeprecatedMethods(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression)) {\n const name = expression.getName();\n if (DEPRECATED_METHODS.has(name) && !AUTO_TRANSFORMABLE.has(name)) {\n const lineNumber = node.getStartLineNumber();\n switch (name) {\n case 'strict':\n this.warnings.push(\n `${filePath}:${lineNumber}: .strict() is deprecated in v4. ` +\n 'Use z.strictObject() instead.',\n );\n break;\n case 'passthrough':\n this.warnings.push(\n `${filePath}:${lineNumber}: .passthrough() is deprecated in v4. ` +\n 'Use z.looseObject() instead.',\n );\n break;\n // merge is handled by transformMerge\n }\n }\n }\n }\n });\n }\n\n /**\n * Auto-transform .superRefine() to .check() — callback signature is identical.\n */\n private transformSuperRefine(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const nodesToTransform: Array<{\n node: import('ts-morph').PropertyAccessExpression;\n lineNumber: number;\n }> = [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isPropertyAccessExpression(node) && node.getName() === 'superRefine') {\n nodesToTransform.push({ node, lineNumber: node.getStartLineNumber() });\n }\n });\n\n // Process in reverse to preserve positions\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, lineNumber } of nodesToTransform) {\n const parent = node.getParent();\n if (parent && Node.isCallExpression(parent)) {\n const objectText = node.getExpression().getText();\n const args = parent.getArguments();\n let argsText = args.map((a) => a.getText()).join(', ');\n\n // Also transform ctx.addIssue() -> ctx.issues.push() inside the callback\n if (args.length > 0) {\n const callbackText = args[0]?.getText() ?? '';\n // Detect the context parameter name (2nd param in arrow/function)\n const paramMatch = callbackText.match(\n /^\\s*\\(?\\s*\\w+\\s*,\\s*(\\w+)\\s*\\)?(?:\\s*:\\s*[^)]+)?\\s*=>/,\n );\n if (paramMatch?.[1]) {\n const ctxName = paramMatch[1];\n const addIssuePattern = new RegExp(`${ctxName}\\\\.addIssue\\\\(`, 'g');\n if (addIssuePattern.test(callbackText)) {\n argsText = callbackText.replace(\n new RegExp(`${ctxName}\\\\.addIssue\\\\(`, 'g'),\n `${ctxName}.issues.push(`,\n );\n // Re-add remaining args if any\n if (args.length > 1) {\n const remaining = args\n .slice(1)\n .map((a) => a.getText())\n .join(', ');\n argsText = `${argsText}, ${remaining}`;\n }\n }\n }\n }\n\n parent.replaceWithText(`${objectText}.check(${argsText})`);\n this.warnings.push(\n `${filePath}:${lineNumber}: .superRefine() auto-transformed to .check() (deprecated in v4).`,\n );\n }\n }\n }\n\n /**\n * Auto-transform invalid_type_error/required_error params to unified `error` param.\n */\n private transformErrorParams(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const nodesToTransform: Array<{\n node: import('ts-morph').ObjectLiteralExpression;\n lineNumber: number;\n }> = [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isObjectLiteralExpression(node)) {\n const properties = node.getProperties();\n const propNames = properties\n .filter((p) => Node.isPropertyAssignment(p))\n .map((p) => (Node.isPropertyAssignment(p) ? p.getName() : ''));\n\n const hasInvalidType = propNames.includes('invalid_type_error');\n const hasRequired = propNames.includes('required_error');\n\n if (hasInvalidType || hasRequired) {\n // Only transform if this is an argument to a z.xxx() factory call\n const parent = node.getParent();\n if (parent && Node.isCallExpression(parent)) {\n const expr = parent.getExpression();\n if (Node.isPropertyAccessExpression(expr) && expr.getExpression().getText() === 'z') {\n nodesToTransform.push({ node, lineNumber: node.getStartLineNumber() });\n }\n }\n }\n }\n });\n\n // Process in reverse to preserve positions\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, lineNumber } of nodesToTransform) {\n const properties = node.getProperties();\n let invalidTypeValue: string | undefined;\n let requiredValue: string | undefined;\n const otherProps: string[] = [];\n\n for (const prop of properties) {\n if (Node.isPropertyAssignment(prop)) {\n const name = prop.getName();\n const value = prop.getInitializer()?.getText() ?? '';\n if (name === 'invalid_type_error') {\n invalidTypeValue = value;\n } else if (name === 'required_error') {\n requiredValue = value;\n } else {\n otherProps.push(prop.getText());\n }\n }\n }\n\n let errorValue: string;\n if (invalidTypeValue && requiredValue) {\n // Both present: generate error function\n errorValue = `error: (issue) => issue.input === undefined ? ${requiredValue} : ${invalidTypeValue}`;\n } else if (requiredValue) {\n errorValue = `error: ${requiredValue}`;\n } else if (invalidTypeValue) {\n errorValue = `error: ${invalidTypeValue}`;\n } else {\n continue;\n }\n\n const allProps = [errorValue, ...otherProps].join(', ');\n node.replaceWithText(`{ ${allProps} }`);\n\n this.warnings.push(\n `${filePath}:${lineNumber}: invalid_type_error/required_error auto-transformed to unified error param.`,\n );\n }\n }\n\n /**\n * Detect instanceof Error patterns in catch blocks that reference ZodError.\n * In v4, ZodError no longer extends Error.\n */\n private checkInstanceofError(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCatchClause(node)) {\n const block = node.getBlock();\n const blockText = block.getText();\n\n // Check if the catch block references ZodError AND uses instanceof Error\n if (blockText.includes('ZodError') && blockText.includes('instanceof Error')) {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: ZodError no longer extends Error in v4. ` +\n '`instanceof Error` checks on ZodError will return false. ' +\n 'Use `instanceof ZodError` or check for `.issues` property instead.',\n );\n }\n }\n });\n }\n\n /**\n * Detect .refine()/.superRefine() followed by .transform() in the same chain.\n * In v4, .transform() runs even when .refine() fails.\n */\n private checkTransformRefineOrder(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression) && expression.getName() === 'transform') {\n // Walk up the chain to see if .refine() or .superRefine() precedes\n const chainText = node.getText();\n if (\n chainText.includes('.refine(') ||\n chainText.includes('.superRefine(') ||\n chainText.includes('.check(')\n ) {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: In v4, .transform() executes even if preceding .refine() fails. ` +\n 'Consider using .pipe() to sequence validation before transforms.',\n );\n }\n }\n }\n });\n }\n\n /**\n * Detect .default() combined with .optional() — behavior changed silently in v4.\n * In v4, .default() always provides a value, making .optional() a no-op.\n */\n private checkDefaultOptional(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (\n Node.isPropertyAccessExpression(expression) &&\n (expression.getName() === 'optional' || expression.getName() === 'default')\n ) {\n const chainText = node.getText();\n const hasDefault = chainText.includes('.default(');\n const hasOptional = chainText.includes('.optional(');\n\n if (hasDefault && hasOptional) {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: .default() + .optional() behavior changed in v4. ` +\n '.default() now always provides a value, making .optional() effectively a no-op. ' +\n 'Review whether .optional() is still needed.',\n );\n }\n }\n }\n });\n }\n\n /**\n * Check for methods with behavior changes and add warnings\n */\n private checkBehaviorChanges(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n\n if (Node.isPropertyAccessExpression(expression)) {\n const name = expression.getName();\n\n if (BEHAVIOR_CHANGES.has(name)) {\n const lineNumber = node.getStartLineNumber();\n\n switch (name) {\n case 'default':\n this.warnings.push(\n `${filePath}:${lineNumber}: .default() has stricter type inference in v4. ` +\n 'Verify default value matches schema type exactly.',\n );\n break;\n\n case 'uuid':\n this.warnings.push(\n `${filePath}:${lineNumber}: .uuid() now enforces strict RFC 4122 compliance. ` +\n 'Non-standard UUIDs may fail validation.',\n );\n break;\n\n case 'discriminatedUnion':\n this.warnings.push(\n `${filePath}:${lineNumber}: z.discriminatedUnion() now requires ` +\n 'a literal type for the discriminator property.',\n );\n break;\n\n case 'function':\n this.warnings.push(\n `${filePath}:${lineNumber}: z.function() parameter handling has changed. ` +\n 'Review input/output schema definitions.',\n );\n break;\n\n case 'pipe':\n this.warnings.push(\n `${filePath}:${lineNumber}: .pipe() has stricter type checking in v4. ` +\n 'If you get type errors, add explicit type annotations to .transform() return types ' +\n 'or cast through unknown as a last resort.',\n );\n break;\n }\n }\n }\n }\n });\n }\n\n /**\n * Detect .catch() combined with .optional() — behavior changed in v4.\n * In v4, .catch() on optional properties always returns the catch value.\n */\n private checkCatchOptional(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (\n Node.isPropertyAccessExpression(expression) &&\n (expression.getName() === 'optional' || expression.getName() === 'catch')\n ) {\n const chainText = node.getText();\n if (chainText.includes('.catch(') && chainText.includes('.optional(')) {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: .catch() + .optional() behavior changed in v4. ` +\n '.catch() on optional properties now always returns the catch value, ' +\n 'even when the property is absent from input.',\n );\n }\n }\n }\n });\n }\n\n /**\n * Detect imports of utility types that moved to 'zod/v4/core' in v4.\n */\n private checkUtilityTypeImports(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const moduleSpecifier = importDecl.getModuleSpecifierValue();\n if (moduleSpecifier !== 'zod') continue;\n\n const namedImports = importDecl.getNamedImports();\n for (const namedImport of namedImports) {\n const name = namedImport.getName();\n if (UTILITY_TYPES.has(name)) {\n const lineNumber = importDecl.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: '${name}' may need to be imported from 'zod/v4/core' in v4. ` +\n 'Internal utility types have moved to a separate subpackage.',\n );\n }\n }\n }\n }\n}\n","/**\n * Zod v3 to v4 Breaking Changes\n *\n * Key changes in Zod v4:\n * 1. z.record() now requires explicit key type\n * 2. .default() has stricter type inference\n * 3. error.errors renamed to error.issues\n * 4. .uuid() has stricter validation (RFC 4122 compliant)\n * 5. z.function() input/output changed\n * 6. Branded types use different syntax\n * 7. z.discriminatedUnion() requires literal discriminator\n */\n\n// Patterns that need transformation\nexport const V3_TO_V4_PATTERNS = {\n // z.record(valueSchema) -> z.record(z.string(), valueSchema)\n recordSingleArg: /z\\.record\\((?!z\\.string\\(\\)|z\\.number\\(\\)|z\\.symbol\\(\\))/g,\n\n // error.errors -> error.issues\n errorErrors: /\\.errors\\b/g,\n\n // .brand<T>() -> .brand<T>() (same but check for proper usage)\n brandUsage: /\\.brand<([^>]+)>\\(\\)/g,\n};\n\n// Methods that have changed behavior\nexport const BEHAVIOR_CHANGES = new Set([\n 'default', // Type inference changed\n 'uuid', // Stricter validation\n 'record', // Requires key type\n 'discriminatedUnion', // Stricter discriminator requirements\n 'function', // Input/output parameter changes\n 'pipe', // Stricter type checking in v4\n 'catch', // .catch() on optional properties always returns catch value in v4\n]);\n\n// Error property renames\nexport const ERROR_RENAMES: Record<string, string> = {\n errors: 'issues',\n formErrors: 'formErrors', // Unchanged\n fieldErrors: 'fieldErrors', // Unchanged\n};\n\n// Methods that are deprecated in v4\nexport const DEPRECATED_METHODS = new Set([\n 'merge', // Use .extend() instead\n 'superRefine', // Use .check() instead\n 'strict', // Use z.strictObject() instead\n 'passthrough', // Use z.looseObject() instead\n]);\n\n// Method renames in v4\nexport const METHOD_RENAMES: Record<string, string> = {\n merge: 'extend',\n};\n\n// Factory function renames in v4\nexport const FACTORY_RENAMES: Record<string, string> = {\n nativeEnum: 'enum',\n};\n\n// Error params that changed in v4 (unified under `error`)\nexport const ERROR_PARAM_NAMES = new Set(['invalid_type_error', 'required_error']);\n\n// Methods that can be automatically transformed (renamed) in v4\nexport const AUTO_TRANSFORMABLE = new Set([\n 'superRefine', // -> .check()\n 'flatten', // error.flatten() -> z.flattenError(error)\n 'format', // error.format() -> z.treeifyError(error)\n]);\n\n// Utility types that moved to 'zod/v4/core' in v4\nexport const UTILITY_TYPES = new Set([\n 'ZodType',\n 'ZodSchema',\n 'ZodRawShape',\n 'ZodTypeAny',\n 'ZodFirstPartyTypeKind',\n]);\n\n// Runtime behavior patterns that silently break in v4 (no compile-time error)\nexport const RUNTIME_BREAK_PATTERNS = new Set([\n 'instanceofError', // ZodError no longer extends Error\n 'transformAfterRefine', // .transform() runs even when .refine() fails\n 'defaultOptional', // .default() + .optional() behavior change\n]);\n","import type { TransformHandler, TransformOptions, TransformResult } from '@schemashift/core';\nimport type { SourceFile } from 'ts-morph';\nimport { ZodV3ToV4Transformer } from './transformer.js';\n\nexport function createZodV3ToV4Handler(): TransformHandler {\n const transformer = new ZodV3ToV4Transformer();\n return {\n transform(sourceFile: SourceFile, _options: TransformOptions): TransformResult {\n return transformer.transform(sourceFile);\n },\n };\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -41,15 +41,28 @@ declare class ZodV3ToV4Transformer {
41
41
  * Transform z.record(valueSchema) to z.record(z.string(), valueSchema)
42
42
  */
43
43
  private transformRecordCalls;
44
+ /**
45
+ * Build a set of variable names that are likely ZodError instances.
46
+ * Used by transformErrorProperties, transformFlatten, and transformFormat.
47
+ */
48
+ private buildZodErrorVarSet;
44
49
  /**
45
50
  * Transform error.errors to error.issues using AST-based detection
46
51
  * instead of heuristic name matching.
47
52
  */
48
53
  private transformErrorProperties;
49
54
  /**
50
- * Transform .flatten() usage removed in v4.
55
+ * Auto-transform error.flatten() to z.flattenError(error) in v4.
51
56
  */
52
57
  private transformFlatten;
58
+ /**
59
+ * Auto-transform error.format() to z.treeifyError(error) in v4.
60
+ */
61
+ private transformFormat;
62
+ /**
63
+ * Auto-transform ._def property access to ._zod.def in v4.
64
+ */
65
+ private transformDefAccess;
53
66
  /**
54
67
  * Transform .merge(otherSchema) to .extend(otherSchema.shape)
55
68
  */
@@ -89,6 +102,15 @@ declare class ZodV3ToV4Transformer {
89
102
  * Check for methods with behavior changes and add warnings
90
103
  */
91
104
  private checkBehaviorChanges;
105
+ /**
106
+ * Detect .catch() combined with .optional() — behavior changed in v4.
107
+ * In v4, .catch() on optional properties always returns the catch value.
108
+ */
109
+ private checkCatchOptional;
110
+ /**
111
+ * Detect imports of utility types that moved to 'zod/v4/core' in v4.
112
+ */
113
+ private checkUtilityTypeImports;
92
114
  }
93
115
 
94
116
  export { BEHAVIOR_CHANGES, V3_TO_V4_PATTERNS, ZodV3ToV4Transformer, createZodV3ToV4Handler };
package/dist/index.d.ts CHANGED
@@ -41,15 +41,28 @@ declare class ZodV3ToV4Transformer {
41
41
  * Transform z.record(valueSchema) to z.record(z.string(), valueSchema)
42
42
  */
43
43
  private transformRecordCalls;
44
+ /**
45
+ * Build a set of variable names that are likely ZodError instances.
46
+ * Used by transformErrorProperties, transformFlatten, and transformFormat.
47
+ */
48
+ private buildZodErrorVarSet;
44
49
  /**
45
50
  * Transform error.errors to error.issues using AST-based detection
46
51
  * instead of heuristic name matching.
47
52
  */
48
53
  private transformErrorProperties;
49
54
  /**
50
- * Transform .flatten() usage removed in v4.
55
+ * Auto-transform error.flatten() to z.flattenError(error) in v4.
51
56
  */
52
57
  private transformFlatten;
58
+ /**
59
+ * Auto-transform error.format() to z.treeifyError(error) in v4.
60
+ */
61
+ private transformFormat;
62
+ /**
63
+ * Auto-transform ._def property access to ._zod.def in v4.
64
+ */
65
+ private transformDefAccess;
53
66
  /**
54
67
  * Transform .merge(otherSchema) to .extend(otherSchema.shape)
55
68
  */
@@ -89,6 +102,15 @@ declare class ZodV3ToV4Transformer {
89
102
  * Check for methods with behavior changes and add warnings
90
103
  */
91
104
  private checkBehaviorChanges;
105
+ /**
106
+ * Detect .catch() combined with .optional() — behavior changed in v4.
107
+ * In v4, .catch() on optional properties always returns the catch value.
108
+ */
109
+ private checkCatchOptional;
110
+ /**
111
+ * Detect imports of utility types that moved to 'zod/v4/core' in v4.
112
+ */
113
+ private checkUtilityTypeImports;
92
114
  }
93
115
 
94
116
  export { BEHAVIOR_CHANGES, V3_TO_V4_PATTERNS, ZodV3ToV4Transformer, createZodV3ToV4Handler };
package/dist/index.js CHANGED
@@ -21,8 +21,10 @@ var BEHAVIOR_CHANGES = /* @__PURE__ */ new Set([
21
21
  // Stricter discriminator requirements
22
22
  "function",
23
23
  // Input/output parameter changes
24
- "pipe"
24
+ "pipe",
25
25
  // Stricter type checking in v4
26
+ "catch"
27
+ // .catch() on optional properties always returns catch value in v4
26
28
  ]);
27
29
  var DEPRECATED_METHODS = /* @__PURE__ */ new Set([
28
30
  "merge",
@@ -35,8 +37,19 @@ var DEPRECATED_METHODS = /* @__PURE__ */ new Set([
35
37
  // Use z.looseObject() instead
36
38
  ]);
37
39
  var AUTO_TRANSFORMABLE = /* @__PURE__ */ new Set([
38
- "superRefine"
40
+ "superRefine",
39
41
  // -> .check()
42
+ "flatten",
43
+ // error.flatten() -> z.flattenError(error)
44
+ "format"
45
+ // error.format() -> z.treeifyError(error)
46
+ ]);
47
+ var UTILITY_TYPES = /* @__PURE__ */ new Set([
48
+ "ZodType",
49
+ "ZodSchema",
50
+ "ZodRawShape",
51
+ "ZodTypeAny",
52
+ "ZodFirstPartyTypeKind"
40
53
  ]);
41
54
 
42
55
  // src/transformer.ts
@@ -56,11 +69,15 @@ var ZodV3ToV4Transformer = class {
56
69
  this.transformErrorProperties(sourceFile);
57
70
  this.transformErrorParams(sourceFile);
58
71
  this.transformFlatten(sourceFile);
72
+ this.transformFormat(sourceFile);
73
+ this.transformDefAccess(sourceFile);
59
74
  this.checkDeprecatedMethods(sourceFile);
60
75
  this.checkBehaviorChanges(sourceFile);
61
76
  this.checkInstanceofError(sourceFile);
62
77
  this.checkTransformRefineOrder(sourceFile);
63
78
  this.checkDefaultOptional(sourceFile);
79
+ this.checkCatchOptional(sourceFile);
80
+ this.checkUtilityTypeImports(sourceFile);
64
81
  return {
65
82
  success: this.errors.length === 0,
66
83
  filePath,
@@ -109,18 +126,16 @@ var ZodV3ToV4Transformer = class {
109
126
  });
110
127
  }
111
128
  /**
112
- * Transform error.errors to error.issues using AST-based detection
113
- * instead of heuristic name matching.
129
+ * Build a set of variable names that are likely ZodError instances.
130
+ * Used by transformErrorProperties, transformFlatten, and transformFormat.
114
131
  */
115
- transformErrorProperties(sourceFile) {
116
- const filePath = sourceFile.getFilePath();
132
+ buildZodErrorVarSet(sourceFile) {
117
133
  const zodErrorVars = /* @__PURE__ */ new Set();
118
134
  sourceFile.forEachDescendant((node) => {
119
135
  if (Node.isVariableDeclaration(node)) {
120
136
  const typeNode = node.getTypeNode();
121
137
  if (typeNode?.getText().includes("ZodError")) {
122
- const name = node.getName();
123
- zodErrorVars.add(name);
138
+ zodErrorVars.add(node.getName());
124
139
  }
125
140
  }
126
141
  if (Node.isCatchClause(node)) {
@@ -148,6 +163,15 @@ var ZodV3ToV4Transformer = class {
148
163
  }
149
164
  }
150
165
  });
166
+ return zodErrorVars;
167
+ }
168
+ /**
169
+ * Transform error.errors to error.issues using AST-based detection
170
+ * instead of heuristic name matching.
171
+ */
172
+ transformErrorProperties(sourceFile) {
173
+ const filePath = sourceFile.getFilePath();
174
+ const zodErrorVars = this.buildZodErrorVarSet(sourceFile);
151
175
  sourceFile.forEachDescendant((node) => {
152
176
  if (Node.isPropertyAccessExpression(node)) {
153
177
  const name = node.getName();
@@ -169,21 +193,90 @@ var ZodV3ToV4Transformer = class {
169
193
  });
170
194
  }
171
195
  /**
172
- * Transform .flatten() usage removed in v4.
196
+ * Auto-transform error.flatten() to z.flattenError(error) in v4.
173
197
  */
174
198
  transformFlatten(sourceFile) {
175
199
  const filePath = sourceFile.getFilePath();
200
+ const zodErrorVars = this.buildZodErrorVarSet(sourceFile);
201
+ const nodesToTransform = [];
176
202
  sourceFile.forEachDescendant((node) => {
177
203
  if (Node.isCallExpression(node)) {
178
204
  const expression = node.getExpression();
179
205
  if (Node.isPropertyAccessExpression(expression) && expression.getName() === "flatten") {
180
- const lineNumber = node.getStartLineNumber();
181
- this.warnings.push(
182
- `${filePath}:${lineNumber}: .flatten() is removed in v4. Use error.issues directly or implement custom flattening. See: https://zod.dev/v4/changelog#flatten-removed`
183
- );
206
+ const objectText = expression.getExpression().getText();
207
+ const isZodError = zodErrorVars.has(objectText) || objectText.endsWith(".error") && zodErrorVars.has(`${objectText.replace(/\.error$/, "")}.error`);
208
+ if (isZodError) {
209
+ nodesToTransform.push({
210
+ node,
211
+ objectText,
212
+ lineNumber: node.getStartLineNumber()
213
+ });
214
+ } else {
215
+ this.warnings.push(
216
+ `${filePath}:${node.getStartLineNumber()}: .flatten() is removed in v4. Use z.flattenError(error) or access error.issues directly. See: https://zod.dev/v4/changelog`
217
+ );
218
+ }
219
+ }
220
+ }
221
+ });
222
+ nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());
223
+ for (const { node, objectText, lineNumber } of nodesToTransform) {
224
+ node.replaceWithText(`z.flattenError(${objectText})`);
225
+ this.warnings.push(
226
+ `${filePath}:${lineNumber}: .flatten() auto-transformed to z.flattenError(). Removed in v4 \u2014 now a standalone function.`
227
+ );
228
+ }
229
+ }
230
+ /**
231
+ * Auto-transform error.format() to z.treeifyError(error) in v4.
232
+ */
233
+ transformFormat(sourceFile) {
234
+ const filePath = sourceFile.getFilePath();
235
+ const zodErrorVars = this.buildZodErrorVarSet(sourceFile);
236
+ const nodesToTransform = [];
237
+ sourceFile.forEachDescendant((node) => {
238
+ if (Node.isCallExpression(node)) {
239
+ const expression = node.getExpression();
240
+ if (Node.isPropertyAccessExpression(expression) && expression.getName() === "format") {
241
+ const objectText = expression.getExpression().getText();
242
+ const isZodError = zodErrorVars.has(objectText) || objectText.endsWith(".error") && zodErrorVars.has(`${objectText.replace(/\.error$/, "")}.error`);
243
+ if (isZodError) {
244
+ nodesToTransform.push({
245
+ node,
246
+ objectText,
247
+ lineNumber: node.getStartLineNumber()
248
+ });
249
+ }
184
250
  }
185
251
  }
186
252
  });
253
+ nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());
254
+ for (const { node, objectText, lineNumber } of nodesToTransform) {
255
+ node.replaceWithText(`z.treeifyError(${objectText})`);
256
+ this.warnings.push(
257
+ `${filePath}:${lineNumber}: .format() auto-transformed to z.treeifyError(). Removed in v4 \u2014 now a standalone function.`
258
+ );
259
+ }
260
+ }
261
+ /**
262
+ * Auto-transform ._def property access to ._zod.def in v4.
263
+ */
264
+ transformDefAccess(sourceFile) {
265
+ const filePath = sourceFile.getFilePath();
266
+ const nodesToTransform = [];
267
+ sourceFile.forEachDescendant((node) => {
268
+ if (Node.isPropertyAccessExpression(node) && node.getName() === "_def") {
269
+ nodesToTransform.push({ node, lineNumber: node.getStartLineNumber() });
270
+ }
271
+ });
272
+ nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());
273
+ for (const { node, lineNumber } of nodesToTransform) {
274
+ const objectText = node.getExpression().getText();
275
+ node.replaceWithText(`${objectText}._zod.def`);
276
+ this.warnings.push(
277
+ `${filePath}:${lineNumber}: ._def auto-transformed to ._zod.def. Internal API \u2014 structure may change between releases.`
278
+ );
279
+ }
187
280
  }
188
281
  /**
189
282
  * Transform .merge(otherSchema) to .extend(otherSchema.shape)
@@ -276,7 +369,28 @@ var ZodV3ToV4Transformer = class {
276
369
  const parent = node.getParent();
277
370
  if (parent && Node.isCallExpression(parent)) {
278
371
  const objectText = node.getExpression().getText();
279
- const argsText = parent.getArguments().map((a) => a.getText()).join(", ");
372
+ const args = parent.getArguments();
373
+ let argsText = args.map((a) => a.getText()).join(", ");
374
+ if (args.length > 0) {
375
+ const callbackText = args[0]?.getText() ?? "";
376
+ const paramMatch = callbackText.match(
377
+ /^\s*\(?\s*\w+\s*,\s*(\w+)\s*\)?(?:\s*:\s*[^)]+)?\s*=>/
378
+ );
379
+ if (paramMatch?.[1]) {
380
+ const ctxName = paramMatch[1];
381
+ const addIssuePattern = new RegExp(`${ctxName}\\.addIssue\\(`, "g");
382
+ if (addIssuePattern.test(callbackText)) {
383
+ argsText = callbackText.replace(
384
+ new RegExp(`${ctxName}\\.addIssue\\(`, "g"),
385
+ `${ctxName}.issues.push(`
386
+ );
387
+ if (args.length > 1) {
388
+ const remaining = args.slice(1).map((a) => a.getText()).join(", ");
389
+ argsText = `${argsText}, ${remaining}`;
390
+ }
391
+ }
392
+ }
393
+ }
280
394
  parent.replaceWithText(`${objectText}.check(${argsText})`);
281
395
  this.warnings.push(
282
396
  `${filePath}:${lineNumber}: .superRefine() auto-transformed to .check() (deprecated in v4).`
@@ -446,16 +560,51 @@ var ZodV3ToV4Transformer = class {
446
560
  break;
447
561
  }
448
562
  }
449
- if (name === "format") {
563
+ }
564
+ }
565
+ });
566
+ }
567
+ /**
568
+ * Detect .catch() combined with .optional() — behavior changed in v4.
569
+ * In v4, .catch() on optional properties always returns the catch value.
570
+ */
571
+ checkCatchOptional(sourceFile) {
572
+ const filePath = sourceFile.getFilePath();
573
+ sourceFile.forEachDescendant((node) => {
574
+ if (Node.isCallExpression(node)) {
575
+ const expression = node.getExpression();
576
+ if (Node.isPropertyAccessExpression(expression) && (expression.getName() === "optional" || expression.getName() === "catch")) {
577
+ const chainText = node.getText();
578
+ if (chainText.includes(".catch(") && chainText.includes(".optional(")) {
450
579
  const lineNumber = node.getStartLineNumber();
451
580
  this.warnings.push(
452
- `${filePath}:${lineNumber}: .format() is removed in v4. Use z.treeifyError() or custom error formatting. See: https://zod.dev/v4/changelog`
581
+ `${filePath}:${lineNumber}: .catch() + .optional() behavior changed in v4. .catch() on optional properties now always returns the catch value, even when the property is absent from input.`
453
582
  );
454
583
  }
455
584
  }
456
585
  }
457
586
  });
458
587
  }
588
+ /**
589
+ * Detect imports of utility types that moved to 'zod/v4/core' in v4.
590
+ */
591
+ checkUtilityTypeImports(sourceFile) {
592
+ const filePath = sourceFile.getFilePath();
593
+ for (const importDecl of sourceFile.getImportDeclarations()) {
594
+ const moduleSpecifier = importDecl.getModuleSpecifierValue();
595
+ if (moduleSpecifier !== "zod") continue;
596
+ const namedImports = importDecl.getNamedImports();
597
+ for (const namedImport of namedImports) {
598
+ const name = namedImport.getName();
599
+ if (UTILITY_TYPES.has(name)) {
600
+ const lineNumber = importDecl.getStartLineNumber();
601
+ this.warnings.push(
602
+ `${filePath}:${lineNumber}: '${name}' may need to be imported from 'zod/v4/core' in v4. Internal utility types have moved to a separate subpackage.`
603
+ );
604
+ }
605
+ }
606
+ }
607
+ }
459
608
  };
460
609
 
461
610
  // src/handler.ts
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/transformer.ts","../src/mappings.ts","../src/handler.ts"],"sourcesContent":["import type { TransformError, TransformResult } from '@schemashift/core';\nimport { Node, type SourceFile } from 'ts-morph';\nimport { AUTO_TRANSFORMABLE, BEHAVIOR_CHANGES, DEPRECATED_METHODS } from './mappings.js';\n\n/**\n * Zod v3 to v4 Transformer\n *\n * Handles breaking changes between Zod v3 and v4:\n * - z.record() now requires explicit key type\n * - error.errors -> error.issues\n * - Stricter UUID validation\n * - Type inference changes in .default()\n * - .flatten() removed\n * - z.preprocess() -> z.pipe() migration\n */\nexport class ZodV3ToV4Transformer {\n private errors: TransformError[] = [];\n private warnings: string[] = [];\n\n transform(sourceFile: SourceFile): TransformResult {\n this.errors = [];\n this.warnings = [];\n\n const filePath = sourceFile.getFilePath();\n const originalCode = sourceFile.getFullText();\n\n try {\n this.transformRecordCalls(sourceFile);\n this.transformMerge(sourceFile);\n this.transformNativeEnum(sourceFile);\n this.transformSuperRefine(sourceFile);\n this.transformErrorProperties(sourceFile);\n this.transformErrorParams(sourceFile);\n this.transformFlatten(sourceFile);\n this.checkDeprecatedMethods(sourceFile);\n this.checkBehaviorChanges(sourceFile);\n this.checkInstanceofError(sourceFile);\n this.checkTransformRefineOrder(sourceFile);\n this.checkDefaultOptional(sourceFile);\n\n return {\n success: this.errors.length === 0,\n filePath,\n originalCode,\n transformedCode: sourceFile.getFullText(),\n errors: this.errors,\n warnings: this.warnings,\n };\n } catch (error) {\n this.errors.push({\n message: error instanceof Error ? error.message : 'Unknown error',\n });\n return {\n success: false,\n filePath,\n originalCode,\n errors: this.errors,\n warnings: this.warnings,\n };\n }\n }\n\n /**\n * Transform z.record(valueSchema) to z.record(z.string(), valueSchema)\n */\n private transformRecordCalls(sourceFile: SourceFile): void {\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n\n if (Node.isPropertyAccessExpression(expression)) {\n const name = expression.getName();\n const object = expression.getExpression();\n\n if (name === 'record' && object.getText() === 'z') {\n const args = node.getArguments();\n\n // If only one argument, add z.string() as key type\n if (args.length === 1) {\n const valueSchema = args[0]?.getText();\n if (valueSchema) {\n node.replaceWithText(`z.record(z.string(), ${valueSchema})`);\n\n this.warnings.push(\n `${sourceFile.getFilePath()}:${node.getStartLineNumber()}: ` +\n 'z.record() updated to include explicit key type z.string()',\n );\n }\n }\n }\n }\n }\n });\n }\n\n /**\n * Transform error.errors to error.issues using AST-based detection\n * instead of heuristic name matching.\n */\n private transformErrorProperties(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n // First, find all variables that are likely ZodError instances\n const zodErrorVars = new Set<string>();\n\n sourceFile.forEachDescendant((node) => {\n // Check variable declarations with ZodError type annotation\n if (Node.isVariableDeclaration(node)) {\n const typeNode = node.getTypeNode();\n if (typeNode?.getText().includes('ZodError')) {\n const name = node.getName();\n zodErrorVars.add(name);\n }\n }\n\n // Check catch clause parameters\n if (Node.isCatchClause(node)) {\n const param = node.getVariableDeclaration();\n if (param) {\n // Check if the catch block uses instanceof ZodError\n const block = node.getBlock();\n const blockText = block.getText();\n if (blockText.includes('instanceof ZodError') || blockText.includes('ZodError')) {\n zodErrorVars.add(param.getName());\n }\n }\n }\n\n // Check for .safeParse() result — the error is in result.error\n if (Node.isVariableDeclaration(node)) {\n const initializer = node.getInitializer();\n if (initializer?.getText().includes('.safeParse(')) {\n // The result of safeParse has a .error property that is ZodError\n zodErrorVars.add(`${node.getName()}.error`);\n }\n }\n\n // Check for import { ZodError } or new ZodError patterns\n if (Node.isNewExpression(node)) {\n if (node.getExpression().getText() === 'ZodError') {\n const parent = node.getParent();\n if (parent && Node.isVariableDeclaration(parent)) {\n zodErrorVars.add(parent.getName());\n }\n }\n }\n });\n\n // Now transform .errors -> .issues only on identified ZodError variables\n sourceFile.forEachDescendant((node) => {\n if (Node.isPropertyAccessExpression(node)) {\n const name = node.getName();\n if (name === 'errors') {\n const object = node.getExpression();\n const objectText = object.getText();\n\n // Check if this object is a known ZodError variable\n const isZodError =\n zodErrorVars.has(objectText) ||\n // Also check if accessing .error.errors (safeParse pattern)\n (objectText.endsWith('.error') &&\n zodErrorVars.has(`${objectText.replace(/\\.error$/, '')}.error`));\n\n if (isZodError) {\n const fullText = node.getText();\n const newText = fullText.replace(/\\.errors$/, '.issues');\n node.replaceWithText(newText);\n\n this.warnings.push(\n `${filePath}:${node.getStartLineNumber()}: ` +\n '.errors renamed to .issues (ZodError property change)',\n );\n }\n }\n }\n });\n }\n\n /**\n * Transform .flatten() usage — removed in v4.\n */\n private transformFlatten(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression) && expression.getName() === 'flatten') {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: .flatten() is removed in v4. ` +\n 'Use error.issues directly or implement custom flattening. ' +\n 'See: https://zod.dev/v4/changelog#flatten-removed',\n );\n }\n }\n });\n }\n\n /**\n * Transform .merge(otherSchema) to .extend(otherSchema.shape)\n */\n private transformMerge(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const nodesToTransform: Array<{ node: import('ts-morph').CallExpression; lineNumber: number }> =\n [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression) && expression.getName() === 'merge') {\n nodesToTransform.push({ node, lineNumber: node.getStartLineNumber() });\n }\n }\n });\n\n // Process in reverse order\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, lineNumber } of nodesToTransform) {\n const args = node.getArguments();\n if (args.length === 1) {\n const argText = args[0]?.getText();\n if (argText) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression)) {\n const objectText = expression.getExpression().getText();\n node.replaceWithText(`${objectText}.extend(${argText}.shape)`);\n this.warnings.push(\n `${filePath}:${lineNumber}: .merge() renamed to .extend() with .shape access. ` +\n 'Verify the merged schema exposes .shape.',\n );\n }\n }\n }\n }\n }\n\n /**\n * Transform z.nativeEnum(X) to z.enum(X)\n */\n private transformNativeEnum(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const fullText = sourceFile.getFullText();\n const newText = fullText.replace(/\\bz\\.nativeEnum\\(/g, 'z.enum(');\n if (newText !== fullText) {\n sourceFile.replaceWithText(newText);\n this.warnings.push(\n `${filePath}: z.nativeEnum() renamed to z.enum() in v4. ` +\n 'Verify enum values are compatible.',\n );\n }\n }\n\n /**\n * Check for deprecated methods and add warnings\n */\n private checkDeprecatedMethods(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression)) {\n const name = expression.getName();\n if (DEPRECATED_METHODS.has(name) && !AUTO_TRANSFORMABLE.has(name)) {\n const lineNumber = node.getStartLineNumber();\n switch (name) {\n case 'strict':\n this.warnings.push(\n `${filePath}:${lineNumber}: .strict() is deprecated in v4. ` +\n 'Use z.strictObject() instead.',\n );\n break;\n case 'passthrough':\n this.warnings.push(\n `${filePath}:${lineNumber}: .passthrough() is deprecated in v4. ` +\n 'Use z.looseObject() instead.',\n );\n break;\n // merge is handled by transformMerge\n }\n }\n }\n }\n });\n }\n\n /**\n * Auto-transform .superRefine() to .check() — callback signature is identical.\n */\n private transformSuperRefine(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const nodesToTransform: Array<{\n node: import('ts-morph').PropertyAccessExpression;\n lineNumber: number;\n }> = [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isPropertyAccessExpression(node) && node.getName() === 'superRefine') {\n nodesToTransform.push({ node, lineNumber: node.getStartLineNumber() });\n }\n });\n\n // Process in reverse to preserve positions\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, lineNumber } of nodesToTransform) {\n const parent = node.getParent();\n if (parent && Node.isCallExpression(parent)) {\n const objectText = node.getExpression().getText();\n const argsText = parent\n .getArguments()\n .map((a) => a.getText())\n .join(', ');\n parent.replaceWithText(`${objectText}.check(${argsText})`);\n this.warnings.push(\n `${filePath}:${lineNumber}: .superRefine() auto-transformed to .check() (deprecated in v4).`,\n );\n }\n }\n }\n\n /**\n * Auto-transform invalid_type_error/required_error params to unified `error` param.\n */\n private transformErrorParams(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const nodesToTransform: Array<{\n node: import('ts-morph').ObjectLiteralExpression;\n lineNumber: number;\n }> = [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isObjectLiteralExpression(node)) {\n const properties = node.getProperties();\n const propNames = properties\n .filter((p) => Node.isPropertyAssignment(p))\n .map((p) => (Node.isPropertyAssignment(p) ? p.getName() : ''));\n\n const hasInvalidType = propNames.includes('invalid_type_error');\n const hasRequired = propNames.includes('required_error');\n\n if (hasInvalidType || hasRequired) {\n // Only transform if this is an argument to a z.xxx() factory call\n const parent = node.getParent();\n if (parent && Node.isCallExpression(parent)) {\n const expr = parent.getExpression();\n if (Node.isPropertyAccessExpression(expr) && expr.getExpression().getText() === 'z') {\n nodesToTransform.push({ node, lineNumber: node.getStartLineNumber() });\n }\n }\n }\n }\n });\n\n // Process in reverse to preserve positions\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, lineNumber } of nodesToTransform) {\n const properties = node.getProperties();\n let invalidTypeValue: string | undefined;\n let requiredValue: string | undefined;\n const otherProps: string[] = [];\n\n for (const prop of properties) {\n if (Node.isPropertyAssignment(prop)) {\n const name = prop.getName();\n const value = prop.getInitializer()?.getText() ?? '';\n if (name === 'invalid_type_error') {\n invalidTypeValue = value;\n } else if (name === 'required_error') {\n requiredValue = value;\n } else {\n otherProps.push(prop.getText());\n }\n }\n }\n\n let errorValue: string;\n if (invalidTypeValue && requiredValue) {\n // Both present: generate error function\n errorValue = `error: (issue) => issue.input === undefined ? ${requiredValue} : ${invalidTypeValue}`;\n } else if (requiredValue) {\n errorValue = `error: ${requiredValue}`;\n } else if (invalidTypeValue) {\n errorValue = `error: ${invalidTypeValue}`;\n } else {\n continue;\n }\n\n const allProps = [errorValue, ...otherProps].join(', ');\n node.replaceWithText(`{ ${allProps} }`);\n\n this.warnings.push(\n `${filePath}:${lineNumber}: invalid_type_error/required_error auto-transformed to unified error param.`,\n );\n }\n }\n\n /**\n * Detect instanceof Error patterns in catch blocks that reference ZodError.\n * In v4, ZodError no longer extends Error.\n */\n private checkInstanceofError(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCatchClause(node)) {\n const block = node.getBlock();\n const blockText = block.getText();\n\n // Check if the catch block references ZodError AND uses instanceof Error\n if (blockText.includes('ZodError') && blockText.includes('instanceof Error')) {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: ZodError no longer extends Error in v4. ` +\n '`instanceof Error` checks on ZodError will return false. ' +\n 'Use `instanceof ZodError` or check for `.issues` property instead.',\n );\n }\n }\n });\n }\n\n /**\n * Detect .refine()/.superRefine() followed by .transform() in the same chain.\n * In v4, .transform() runs even when .refine() fails.\n */\n private checkTransformRefineOrder(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression) && expression.getName() === 'transform') {\n // Walk up the chain to see if .refine() or .superRefine() precedes\n const chainText = node.getText();\n if (\n chainText.includes('.refine(') ||\n chainText.includes('.superRefine(') ||\n chainText.includes('.check(')\n ) {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: In v4, .transform() executes even if preceding .refine() fails. ` +\n 'Consider using .pipe() to sequence validation before transforms.',\n );\n }\n }\n }\n });\n }\n\n /**\n * Detect .default() combined with .optional() — behavior changed silently in v4.\n * In v4, .default() always provides a value, making .optional() a no-op.\n */\n private checkDefaultOptional(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (\n Node.isPropertyAccessExpression(expression) &&\n (expression.getName() === 'optional' || expression.getName() === 'default')\n ) {\n const chainText = node.getText();\n const hasDefault = chainText.includes('.default(');\n const hasOptional = chainText.includes('.optional(');\n\n if (hasDefault && hasOptional) {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: .default() + .optional() behavior changed in v4. ` +\n '.default() now always provides a value, making .optional() effectively a no-op. ' +\n 'Review whether .optional() is still needed.',\n );\n }\n }\n }\n });\n }\n\n /**\n * Check for methods with behavior changes and add warnings\n */\n private checkBehaviorChanges(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n\n if (Node.isPropertyAccessExpression(expression)) {\n const name = expression.getName();\n\n if (BEHAVIOR_CHANGES.has(name)) {\n const lineNumber = node.getStartLineNumber();\n\n switch (name) {\n case 'default':\n this.warnings.push(\n `${filePath}:${lineNumber}: .default() has stricter type inference in v4. ` +\n 'Verify default value matches schema type exactly.',\n );\n break;\n\n case 'uuid':\n this.warnings.push(\n `${filePath}:${lineNumber}: .uuid() now enforces strict RFC 4122 compliance. ` +\n 'Non-standard UUIDs may fail validation.',\n );\n break;\n\n case 'discriminatedUnion':\n this.warnings.push(\n `${filePath}:${lineNumber}: z.discriminatedUnion() now requires ` +\n 'a literal type for the discriminator property.',\n );\n break;\n\n case 'function':\n this.warnings.push(\n `${filePath}:${lineNumber}: z.function() parameter handling has changed. ` +\n 'Review input/output schema definitions.',\n );\n break;\n\n case 'pipe':\n this.warnings.push(\n `${filePath}:${lineNumber}: .pipe() has stricter type checking in v4. ` +\n 'If you get type errors, add explicit type annotations to .transform() return types ' +\n 'or cast through unknown as a last resort.',\n );\n break;\n }\n }\n\n // Check for .format() which was removed\n if (name === 'format') {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: .format() is removed in v4. ` +\n 'Use z.treeifyError() or custom error formatting. ' +\n 'See: https://zod.dev/v4/changelog',\n );\n }\n }\n }\n });\n }\n}\n","/**\n * Zod v3 to v4 Breaking Changes\n *\n * Key changes in Zod v4:\n * 1. z.record() now requires explicit key type\n * 2. .default() has stricter type inference\n * 3. error.errors renamed to error.issues\n * 4. .uuid() has stricter validation (RFC 4122 compliant)\n * 5. z.function() input/output changed\n * 6. Branded types use different syntax\n * 7. z.discriminatedUnion() requires literal discriminator\n */\n\n// Patterns that need transformation\nexport const V3_TO_V4_PATTERNS = {\n // z.record(valueSchema) -> z.record(z.string(), valueSchema)\n recordSingleArg: /z\\.record\\((?!z\\.string\\(\\)|z\\.number\\(\\)|z\\.symbol\\(\\))/g,\n\n // error.errors -> error.issues\n errorErrors: /\\.errors\\b/g,\n\n // .brand<T>() -> .brand<T>() (same but check for proper usage)\n brandUsage: /\\.brand<([^>]+)>\\(\\)/g,\n};\n\n// Methods that have changed behavior\nexport const BEHAVIOR_CHANGES = new Set([\n 'default', // Type inference changed\n 'uuid', // Stricter validation\n 'record', // Requires key type\n 'discriminatedUnion', // Stricter discriminator requirements\n 'function', // Input/output parameter changes\n 'pipe', // Stricter type checking in v4\n]);\n\n// Error property renames\nexport const ERROR_RENAMES: Record<string, string> = {\n errors: 'issues',\n formErrors: 'formErrors', // Unchanged\n fieldErrors: 'fieldErrors', // Unchanged\n};\n\n// Methods that are deprecated in v4\nexport const DEPRECATED_METHODS = new Set([\n 'merge', // Use .extend() instead\n 'superRefine', // Use .check() instead\n 'strict', // Use z.strictObject() instead\n 'passthrough', // Use z.looseObject() instead\n]);\n\n// Method renames in v4\nexport const METHOD_RENAMES: Record<string, string> = {\n merge: 'extend',\n};\n\n// Factory function renames in v4\nexport const FACTORY_RENAMES: Record<string, string> = {\n nativeEnum: 'enum',\n};\n\n// Error params that changed in v4 (unified under `error`)\nexport const ERROR_PARAM_NAMES = new Set(['invalid_type_error', 'required_error']);\n\n// Methods that can be automatically transformed (renamed) in v4\nexport const AUTO_TRANSFORMABLE = new Set([\n 'superRefine', // -> .check()\n]);\n\n// Runtime behavior patterns that silently break in v4 (no compile-time error)\nexport const RUNTIME_BREAK_PATTERNS = new Set([\n 'instanceofError', // ZodError no longer extends Error\n 'transformAfterRefine', // .transform() runs even when .refine() fails\n 'defaultOptional', // .default() + .optional() behavior change\n]);\n","import type { TransformHandler, TransformOptions, TransformResult } from '@schemashift/core';\nimport type { SourceFile } from 'ts-morph';\nimport { ZodV3ToV4Transformer } from './transformer.js';\n\nexport function createZodV3ToV4Handler(): TransformHandler {\n const transformer = new ZodV3ToV4Transformer();\n return {\n transform(sourceFile: SourceFile, _options: TransformOptions): TransformResult {\n return transformer.transform(sourceFile);\n },\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/transformer.ts","../src/mappings.ts","../src/handler.ts"],"sourcesContent":["import type { TransformError, TransformResult } from '@schemashift/core';\nimport { Node, type SourceFile } from 'ts-morph';\nimport {\n AUTO_TRANSFORMABLE,\n BEHAVIOR_CHANGES,\n DEPRECATED_METHODS,\n UTILITY_TYPES,\n} from './mappings.js';\n\n/**\n * Zod v3 to v4 Transformer\n *\n * Handles breaking changes between Zod v3 and v4:\n * - z.record() now requires explicit key type\n * - error.errors -> error.issues\n * - Stricter UUID validation\n * - Type inference changes in .default()\n * - .flatten() removed\n * - z.preprocess() -> z.pipe() migration\n */\nexport class ZodV3ToV4Transformer {\n private errors: TransformError[] = [];\n private warnings: string[] = [];\n\n transform(sourceFile: SourceFile): TransformResult {\n this.errors = [];\n this.warnings = [];\n\n const filePath = sourceFile.getFilePath();\n const originalCode = sourceFile.getFullText();\n\n try {\n this.transformRecordCalls(sourceFile);\n this.transformMerge(sourceFile);\n this.transformNativeEnum(sourceFile);\n this.transformSuperRefine(sourceFile);\n this.transformErrorProperties(sourceFile);\n this.transformErrorParams(sourceFile);\n this.transformFlatten(sourceFile);\n this.transformFormat(sourceFile);\n this.transformDefAccess(sourceFile);\n this.checkDeprecatedMethods(sourceFile);\n this.checkBehaviorChanges(sourceFile);\n this.checkInstanceofError(sourceFile);\n this.checkTransformRefineOrder(sourceFile);\n this.checkDefaultOptional(sourceFile);\n this.checkCatchOptional(sourceFile);\n this.checkUtilityTypeImports(sourceFile);\n\n return {\n success: this.errors.length === 0,\n filePath,\n originalCode,\n transformedCode: sourceFile.getFullText(),\n errors: this.errors,\n warnings: this.warnings,\n };\n } catch (error) {\n this.errors.push({\n message: error instanceof Error ? error.message : 'Unknown error',\n });\n return {\n success: false,\n filePath,\n originalCode,\n errors: this.errors,\n warnings: this.warnings,\n };\n }\n }\n\n /**\n * Transform z.record(valueSchema) to z.record(z.string(), valueSchema)\n */\n private transformRecordCalls(sourceFile: SourceFile): void {\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n\n if (Node.isPropertyAccessExpression(expression)) {\n const name = expression.getName();\n const object = expression.getExpression();\n\n if (name === 'record' && object.getText() === 'z') {\n const args = node.getArguments();\n\n // If only one argument, add z.string() as key type\n if (args.length === 1) {\n const valueSchema = args[0]?.getText();\n if (valueSchema) {\n node.replaceWithText(`z.record(z.string(), ${valueSchema})`);\n\n this.warnings.push(\n `${sourceFile.getFilePath()}:${node.getStartLineNumber()}: ` +\n 'z.record() updated to include explicit key type z.string()',\n );\n }\n }\n }\n }\n }\n });\n }\n\n /**\n * Build a set of variable names that are likely ZodError instances.\n * Used by transformErrorProperties, transformFlatten, and transformFormat.\n */\n private buildZodErrorVarSet(sourceFile: SourceFile): Set<string> {\n const zodErrorVars = new Set<string>();\n\n sourceFile.forEachDescendant((node) => {\n // Check variable declarations with ZodError type annotation\n if (Node.isVariableDeclaration(node)) {\n const typeNode = node.getTypeNode();\n if (typeNode?.getText().includes('ZodError')) {\n zodErrorVars.add(node.getName());\n }\n }\n\n // Check catch clause parameters\n if (Node.isCatchClause(node)) {\n const param = node.getVariableDeclaration();\n if (param) {\n const block = node.getBlock();\n const blockText = block.getText();\n if (blockText.includes('instanceof ZodError') || blockText.includes('ZodError')) {\n zodErrorVars.add(param.getName());\n }\n }\n }\n\n // Check for .safeParse() result — the error is in result.error\n if (Node.isVariableDeclaration(node)) {\n const initializer = node.getInitializer();\n if (initializer?.getText().includes('.safeParse(')) {\n zodErrorVars.add(`${node.getName()}.error`);\n }\n }\n\n // Check for new ZodError patterns\n if (Node.isNewExpression(node)) {\n if (node.getExpression().getText() === 'ZodError') {\n const parent = node.getParent();\n if (parent && Node.isVariableDeclaration(parent)) {\n zodErrorVars.add(parent.getName());\n }\n }\n }\n });\n\n return zodErrorVars;\n }\n\n /**\n * Transform error.errors to error.issues using AST-based detection\n * instead of heuristic name matching.\n */\n private transformErrorProperties(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const zodErrorVars = this.buildZodErrorVarSet(sourceFile);\n\n // Now transform .errors -> .issues only on identified ZodError variables\n sourceFile.forEachDescendant((node) => {\n if (Node.isPropertyAccessExpression(node)) {\n const name = node.getName();\n if (name === 'errors') {\n const object = node.getExpression();\n const objectText = object.getText();\n\n // Check if this object is a known ZodError variable\n const isZodError =\n zodErrorVars.has(objectText) ||\n // Also check if accessing .error.errors (safeParse pattern)\n (objectText.endsWith('.error') &&\n zodErrorVars.has(`${objectText.replace(/\\.error$/, '')}.error`));\n\n if (isZodError) {\n const fullText = node.getText();\n const newText = fullText.replace(/\\.errors$/, '.issues');\n node.replaceWithText(newText);\n\n this.warnings.push(\n `${filePath}:${node.getStartLineNumber()}: ` +\n '.errors renamed to .issues (ZodError property change)',\n );\n }\n }\n }\n });\n }\n\n /**\n * Auto-transform error.flatten() to z.flattenError(error) in v4.\n */\n private transformFlatten(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const zodErrorVars = this.buildZodErrorVarSet(sourceFile);\n\n const nodesToTransform: Array<{\n node: import('ts-morph').CallExpression;\n objectText: string;\n lineNumber: number;\n }> = [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression) && expression.getName() === 'flatten') {\n const objectText = expression.getExpression().getText();\n const isZodError =\n zodErrorVars.has(objectText) ||\n (objectText.endsWith('.error') &&\n zodErrorVars.has(`${objectText.replace(/\\.error$/, '')}.error`));\n\n if (isZodError) {\n nodesToTransform.push({\n node,\n objectText,\n lineNumber: node.getStartLineNumber(),\n });\n } else {\n this.warnings.push(\n `${filePath}:${node.getStartLineNumber()}: .flatten() is removed in v4. ` +\n 'Use z.flattenError(error) or access error.issues directly. ' +\n 'See: https://zod.dev/v4/changelog',\n );\n }\n }\n }\n });\n\n // Process in reverse order to preserve positions\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, objectText, lineNumber } of nodesToTransform) {\n node.replaceWithText(`z.flattenError(${objectText})`);\n this.warnings.push(\n `${filePath}:${lineNumber}: .flatten() auto-transformed to z.flattenError(). ` +\n 'Removed in v4 — now a standalone function.',\n );\n }\n }\n\n /**\n * Auto-transform error.format() to z.treeifyError(error) in v4.\n */\n private transformFormat(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const zodErrorVars = this.buildZodErrorVarSet(sourceFile);\n\n const nodesToTransform: Array<{\n node: import('ts-morph').CallExpression;\n objectText: string;\n lineNumber: number;\n }> = [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression) && expression.getName() === 'format') {\n const objectText = expression.getExpression().getText();\n const isZodError =\n zodErrorVars.has(objectText) ||\n (objectText.endsWith('.error') &&\n zodErrorVars.has(`${objectText.replace(/\\.error$/, '')}.error`));\n\n if (isZodError) {\n nodesToTransform.push({\n node,\n objectText,\n lineNumber: node.getStartLineNumber(),\n });\n }\n // Skip non-ZodError .format() calls to avoid false positives\n }\n }\n });\n\n // Process in reverse order to preserve positions\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, objectText, lineNumber } of nodesToTransform) {\n node.replaceWithText(`z.treeifyError(${objectText})`);\n this.warnings.push(\n `${filePath}:${lineNumber}: .format() auto-transformed to z.treeifyError(). ` +\n 'Removed in v4 — now a standalone function.',\n );\n }\n }\n\n /**\n * Auto-transform ._def property access to ._zod.def in v4.\n */\n private transformDefAccess(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const nodesToTransform: Array<{\n node: import('ts-morph').PropertyAccessExpression;\n lineNumber: number;\n }> = [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isPropertyAccessExpression(node) && node.getName() === '_def') {\n nodesToTransform.push({ node, lineNumber: node.getStartLineNumber() });\n }\n });\n\n // Process in reverse order to preserve positions\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, lineNumber } of nodesToTransform) {\n const objectText = node.getExpression().getText();\n node.replaceWithText(`${objectText}._zod.def`);\n this.warnings.push(\n `${filePath}:${lineNumber}: ._def auto-transformed to ._zod.def. ` +\n 'Internal API — structure may change between releases.',\n );\n }\n }\n\n /**\n * Transform .merge(otherSchema) to .extend(otherSchema.shape)\n */\n private transformMerge(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const nodesToTransform: Array<{ node: import('ts-morph').CallExpression; lineNumber: number }> =\n [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression) && expression.getName() === 'merge') {\n nodesToTransform.push({ node, lineNumber: node.getStartLineNumber() });\n }\n }\n });\n\n // Process in reverse order\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, lineNumber } of nodesToTransform) {\n const args = node.getArguments();\n if (args.length === 1) {\n const argText = args[0]?.getText();\n if (argText) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression)) {\n const objectText = expression.getExpression().getText();\n node.replaceWithText(`${objectText}.extend(${argText}.shape)`);\n this.warnings.push(\n `${filePath}:${lineNumber}: .merge() renamed to .extend() with .shape access. ` +\n 'Verify the merged schema exposes .shape.',\n );\n }\n }\n }\n }\n }\n\n /**\n * Transform z.nativeEnum(X) to z.enum(X)\n */\n private transformNativeEnum(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const fullText = sourceFile.getFullText();\n const newText = fullText.replace(/\\bz\\.nativeEnum\\(/g, 'z.enum(');\n if (newText !== fullText) {\n sourceFile.replaceWithText(newText);\n this.warnings.push(\n `${filePath}: z.nativeEnum() renamed to z.enum() in v4. ` +\n 'Verify enum values are compatible.',\n );\n }\n }\n\n /**\n * Check for deprecated methods and add warnings\n */\n private checkDeprecatedMethods(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression)) {\n const name = expression.getName();\n if (DEPRECATED_METHODS.has(name) && !AUTO_TRANSFORMABLE.has(name)) {\n const lineNumber = node.getStartLineNumber();\n switch (name) {\n case 'strict':\n this.warnings.push(\n `${filePath}:${lineNumber}: .strict() is deprecated in v4. ` +\n 'Use z.strictObject() instead.',\n );\n break;\n case 'passthrough':\n this.warnings.push(\n `${filePath}:${lineNumber}: .passthrough() is deprecated in v4. ` +\n 'Use z.looseObject() instead.',\n );\n break;\n // merge is handled by transformMerge\n }\n }\n }\n }\n });\n }\n\n /**\n * Auto-transform .superRefine() to .check() — callback signature is identical.\n */\n private transformSuperRefine(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const nodesToTransform: Array<{\n node: import('ts-morph').PropertyAccessExpression;\n lineNumber: number;\n }> = [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isPropertyAccessExpression(node) && node.getName() === 'superRefine') {\n nodesToTransform.push({ node, lineNumber: node.getStartLineNumber() });\n }\n });\n\n // Process in reverse to preserve positions\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, lineNumber } of nodesToTransform) {\n const parent = node.getParent();\n if (parent && Node.isCallExpression(parent)) {\n const objectText = node.getExpression().getText();\n const args = parent.getArguments();\n let argsText = args.map((a) => a.getText()).join(', ');\n\n // Also transform ctx.addIssue() -> ctx.issues.push() inside the callback\n if (args.length > 0) {\n const callbackText = args[0]?.getText() ?? '';\n // Detect the context parameter name (2nd param in arrow/function)\n const paramMatch = callbackText.match(\n /^\\s*\\(?\\s*\\w+\\s*,\\s*(\\w+)\\s*\\)?(?:\\s*:\\s*[^)]+)?\\s*=>/,\n );\n if (paramMatch?.[1]) {\n const ctxName = paramMatch[1];\n const addIssuePattern = new RegExp(`${ctxName}\\\\.addIssue\\\\(`, 'g');\n if (addIssuePattern.test(callbackText)) {\n argsText = callbackText.replace(\n new RegExp(`${ctxName}\\\\.addIssue\\\\(`, 'g'),\n `${ctxName}.issues.push(`,\n );\n // Re-add remaining args if any\n if (args.length > 1) {\n const remaining = args\n .slice(1)\n .map((a) => a.getText())\n .join(', ');\n argsText = `${argsText}, ${remaining}`;\n }\n }\n }\n }\n\n parent.replaceWithText(`${objectText}.check(${argsText})`);\n this.warnings.push(\n `${filePath}:${lineNumber}: .superRefine() auto-transformed to .check() (deprecated in v4).`,\n );\n }\n }\n }\n\n /**\n * Auto-transform invalid_type_error/required_error params to unified `error` param.\n */\n private transformErrorParams(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n const nodesToTransform: Array<{\n node: import('ts-morph').ObjectLiteralExpression;\n lineNumber: number;\n }> = [];\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isObjectLiteralExpression(node)) {\n const properties = node.getProperties();\n const propNames = properties\n .filter((p) => Node.isPropertyAssignment(p))\n .map((p) => (Node.isPropertyAssignment(p) ? p.getName() : ''));\n\n const hasInvalidType = propNames.includes('invalid_type_error');\n const hasRequired = propNames.includes('required_error');\n\n if (hasInvalidType || hasRequired) {\n // Only transform if this is an argument to a z.xxx() factory call\n const parent = node.getParent();\n if (parent && Node.isCallExpression(parent)) {\n const expr = parent.getExpression();\n if (Node.isPropertyAccessExpression(expr) && expr.getExpression().getText() === 'z') {\n nodesToTransform.push({ node, lineNumber: node.getStartLineNumber() });\n }\n }\n }\n }\n });\n\n // Process in reverse to preserve positions\n nodesToTransform.sort((a, b) => b.node.getStart() - a.node.getStart());\n\n for (const { node, lineNumber } of nodesToTransform) {\n const properties = node.getProperties();\n let invalidTypeValue: string | undefined;\n let requiredValue: string | undefined;\n const otherProps: string[] = [];\n\n for (const prop of properties) {\n if (Node.isPropertyAssignment(prop)) {\n const name = prop.getName();\n const value = prop.getInitializer()?.getText() ?? '';\n if (name === 'invalid_type_error') {\n invalidTypeValue = value;\n } else if (name === 'required_error') {\n requiredValue = value;\n } else {\n otherProps.push(prop.getText());\n }\n }\n }\n\n let errorValue: string;\n if (invalidTypeValue && requiredValue) {\n // Both present: generate error function\n errorValue = `error: (issue) => issue.input === undefined ? ${requiredValue} : ${invalidTypeValue}`;\n } else if (requiredValue) {\n errorValue = `error: ${requiredValue}`;\n } else if (invalidTypeValue) {\n errorValue = `error: ${invalidTypeValue}`;\n } else {\n continue;\n }\n\n const allProps = [errorValue, ...otherProps].join(', ');\n node.replaceWithText(`{ ${allProps} }`);\n\n this.warnings.push(\n `${filePath}:${lineNumber}: invalid_type_error/required_error auto-transformed to unified error param.`,\n );\n }\n }\n\n /**\n * Detect instanceof Error patterns in catch blocks that reference ZodError.\n * In v4, ZodError no longer extends Error.\n */\n private checkInstanceofError(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCatchClause(node)) {\n const block = node.getBlock();\n const blockText = block.getText();\n\n // Check if the catch block references ZodError AND uses instanceof Error\n if (blockText.includes('ZodError') && blockText.includes('instanceof Error')) {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: ZodError no longer extends Error in v4. ` +\n '`instanceof Error` checks on ZodError will return false. ' +\n 'Use `instanceof ZodError` or check for `.issues` property instead.',\n );\n }\n }\n });\n }\n\n /**\n * Detect .refine()/.superRefine() followed by .transform() in the same chain.\n * In v4, .transform() runs even when .refine() fails.\n */\n private checkTransformRefineOrder(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (Node.isPropertyAccessExpression(expression) && expression.getName() === 'transform') {\n // Walk up the chain to see if .refine() or .superRefine() precedes\n const chainText = node.getText();\n if (\n chainText.includes('.refine(') ||\n chainText.includes('.superRefine(') ||\n chainText.includes('.check(')\n ) {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: In v4, .transform() executes even if preceding .refine() fails. ` +\n 'Consider using .pipe() to sequence validation before transforms.',\n );\n }\n }\n }\n });\n }\n\n /**\n * Detect .default() combined with .optional() — behavior changed silently in v4.\n * In v4, .default() always provides a value, making .optional() a no-op.\n */\n private checkDefaultOptional(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (\n Node.isPropertyAccessExpression(expression) &&\n (expression.getName() === 'optional' || expression.getName() === 'default')\n ) {\n const chainText = node.getText();\n const hasDefault = chainText.includes('.default(');\n const hasOptional = chainText.includes('.optional(');\n\n if (hasDefault && hasOptional) {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: .default() + .optional() behavior changed in v4. ` +\n '.default() now always provides a value, making .optional() effectively a no-op. ' +\n 'Review whether .optional() is still needed.',\n );\n }\n }\n }\n });\n }\n\n /**\n * Check for methods with behavior changes and add warnings\n */\n private checkBehaviorChanges(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n\n if (Node.isPropertyAccessExpression(expression)) {\n const name = expression.getName();\n\n if (BEHAVIOR_CHANGES.has(name)) {\n const lineNumber = node.getStartLineNumber();\n\n switch (name) {\n case 'default':\n this.warnings.push(\n `${filePath}:${lineNumber}: .default() has stricter type inference in v4. ` +\n 'Verify default value matches schema type exactly.',\n );\n break;\n\n case 'uuid':\n this.warnings.push(\n `${filePath}:${lineNumber}: .uuid() now enforces strict RFC 4122 compliance. ` +\n 'Non-standard UUIDs may fail validation.',\n );\n break;\n\n case 'discriminatedUnion':\n this.warnings.push(\n `${filePath}:${lineNumber}: z.discriminatedUnion() now requires ` +\n 'a literal type for the discriminator property.',\n );\n break;\n\n case 'function':\n this.warnings.push(\n `${filePath}:${lineNumber}: z.function() parameter handling has changed. ` +\n 'Review input/output schema definitions.',\n );\n break;\n\n case 'pipe':\n this.warnings.push(\n `${filePath}:${lineNumber}: .pipe() has stricter type checking in v4. ` +\n 'If you get type errors, add explicit type annotations to .transform() return types ' +\n 'or cast through unknown as a last resort.',\n );\n break;\n }\n }\n }\n }\n });\n }\n\n /**\n * Detect .catch() combined with .optional() — behavior changed in v4.\n * In v4, .catch() on optional properties always returns the catch value.\n */\n private checkCatchOptional(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n sourceFile.forEachDescendant((node) => {\n if (Node.isCallExpression(node)) {\n const expression = node.getExpression();\n if (\n Node.isPropertyAccessExpression(expression) &&\n (expression.getName() === 'optional' || expression.getName() === 'catch')\n ) {\n const chainText = node.getText();\n if (chainText.includes('.catch(') && chainText.includes('.optional(')) {\n const lineNumber = node.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: .catch() + .optional() behavior changed in v4. ` +\n '.catch() on optional properties now always returns the catch value, ' +\n 'even when the property is absent from input.',\n );\n }\n }\n }\n });\n }\n\n /**\n * Detect imports of utility types that moved to 'zod/v4/core' in v4.\n */\n private checkUtilityTypeImports(sourceFile: SourceFile): void {\n const filePath = sourceFile.getFilePath();\n\n for (const importDecl of sourceFile.getImportDeclarations()) {\n const moduleSpecifier = importDecl.getModuleSpecifierValue();\n if (moduleSpecifier !== 'zod') continue;\n\n const namedImports = importDecl.getNamedImports();\n for (const namedImport of namedImports) {\n const name = namedImport.getName();\n if (UTILITY_TYPES.has(name)) {\n const lineNumber = importDecl.getStartLineNumber();\n this.warnings.push(\n `${filePath}:${lineNumber}: '${name}' may need to be imported from 'zod/v4/core' in v4. ` +\n 'Internal utility types have moved to a separate subpackage.',\n );\n }\n }\n }\n }\n}\n","/**\n * Zod v3 to v4 Breaking Changes\n *\n * Key changes in Zod v4:\n * 1. z.record() now requires explicit key type\n * 2. .default() has stricter type inference\n * 3. error.errors renamed to error.issues\n * 4. .uuid() has stricter validation (RFC 4122 compliant)\n * 5. z.function() input/output changed\n * 6. Branded types use different syntax\n * 7. z.discriminatedUnion() requires literal discriminator\n */\n\n// Patterns that need transformation\nexport const V3_TO_V4_PATTERNS = {\n // z.record(valueSchema) -> z.record(z.string(), valueSchema)\n recordSingleArg: /z\\.record\\((?!z\\.string\\(\\)|z\\.number\\(\\)|z\\.symbol\\(\\))/g,\n\n // error.errors -> error.issues\n errorErrors: /\\.errors\\b/g,\n\n // .brand<T>() -> .brand<T>() (same but check for proper usage)\n brandUsage: /\\.brand<([^>]+)>\\(\\)/g,\n};\n\n// Methods that have changed behavior\nexport const BEHAVIOR_CHANGES = new Set([\n 'default', // Type inference changed\n 'uuid', // Stricter validation\n 'record', // Requires key type\n 'discriminatedUnion', // Stricter discriminator requirements\n 'function', // Input/output parameter changes\n 'pipe', // Stricter type checking in v4\n 'catch', // .catch() on optional properties always returns catch value in v4\n]);\n\n// Error property renames\nexport const ERROR_RENAMES: Record<string, string> = {\n errors: 'issues',\n formErrors: 'formErrors', // Unchanged\n fieldErrors: 'fieldErrors', // Unchanged\n};\n\n// Methods that are deprecated in v4\nexport const DEPRECATED_METHODS = new Set([\n 'merge', // Use .extend() instead\n 'superRefine', // Use .check() instead\n 'strict', // Use z.strictObject() instead\n 'passthrough', // Use z.looseObject() instead\n]);\n\n// Method renames in v4\nexport const METHOD_RENAMES: Record<string, string> = {\n merge: 'extend',\n};\n\n// Factory function renames in v4\nexport const FACTORY_RENAMES: Record<string, string> = {\n nativeEnum: 'enum',\n};\n\n// Error params that changed in v4 (unified under `error`)\nexport const ERROR_PARAM_NAMES = new Set(['invalid_type_error', 'required_error']);\n\n// Methods that can be automatically transformed (renamed) in v4\nexport const AUTO_TRANSFORMABLE = new Set([\n 'superRefine', // -> .check()\n 'flatten', // error.flatten() -> z.flattenError(error)\n 'format', // error.format() -> z.treeifyError(error)\n]);\n\n// Utility types that moved to 'zod/v4/core' in v4\nexport const UTILITY_TYPES = new Set([\n 'ZodType',\n 'ZodSchema',\n 'ZodRawShape',\n 'ZodTypeAny',\n 'ZodFirstPartyTypeKind',\n]);\n\n// Runtime behavior patterns that silently break in v4 (no compile-time error)\nexport const RUNTIME_BREAK_PATTERNS = new Set([\n 'instanceofError', // ZodError no longer extends Error\n 'transformAfterRefine', // .transform() runs even when .refine() fails\n 'defaultOptional', // .default() + .optional() behavior change\n]);\n","import type { TransformHandler, TransformOptions, TransformResult } from '@schemashift/core';\nimport type { SourceFile } from 'ts-morph';\nimport { ZodV3ToV4Transformer } from './transformer.js';\n\nexport function createZodV3ToV4Handler(): TransformHandler {\n const transformer = new ZodV3ToV4Transformer();\n return {\n transform(sourceFile: SourceFile, _options: TransformOptions): TransformResult {\n return transformer.transform(sourceFile);\n },\n };\n}\n"],"mappings":";AACA,SAAS,YAA6B;;;ACa/B,IAAM,oBAAoB;AAAA;AAAA,EAE/B,iBAAiB;AAAA;AAAA,EAGjB,aAAa;AAAA;AAAA,EAGb,YAAY;AACd;AAGO,IAAM,mBAAmB,oBAAI,IAAI;AAAA,EACtC;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF,CAAC;AAUM,IAAM,qBAAqB,oBAAI,IAAI;AAAA,EACxC;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF,CAAC;AAgBM,IAAM,qBAAqB,oBAAI,IAAI;AAAA,EACxC;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF,CAAC;AAGM,IAAM,gBAAgB,oBAAI,IAAI;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;;;AD1DM,IAAM,uBAAN,MAA2B;AAAA,EACxB,SAA2B,CAAC;AAAA,EAC5B,WAAqB,CAAC;AAAA,EAE9B,UAAU,YAAyC;AACjD,SAAK,SAAS,CAAC;AACf,SAAK,WAAW,CAAC;AAEjB,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,eAAe,WAAW,YAAY;AAE5C,QAAI;AACF,WAAK,qBAAqB,UAAU;AACpC,WAAK,eAAe,UAAU;AAC9B,WAAK,oBAAoB,UAAU;AACnC,WAAK,qBAAqB,UAAU;AACpC,WAAK,yBAAyB,UAAU;AACxC,WAAK,qBAAqB,UAAU;AACpC,WAAK,iBAAiB,UAAU;AAChC,WAAK,gBAAgB,UAAU;AAC/B,WAAK,mBAAmB,UAAU;AAClC,WAAK,uBAAuB,UAAU;AACtC,WAAK,qBAAqB,UAAU;AACpC,WAAK,qBAAqB,UAAU;AACpC,WAAK,0BAA0B,UAAU;AACzC,WAAK,qBAAqB,UAAU;AACpC,WAAK,mBAAmB,UAAU;AAClC,WAAK,wBAAwB,UAAU;AAEvC,aAAO;AAAA,QACL,SAAS,KAAK,OAAO,WAAW;AAAA,QAChC;AAAA,QACA;AAAA,QACA,iBAAiB,WAAW,YAAY;AAAA,QACxC,QAAQ,KAAK;AAAA,QACb,UAAU,KAAK;AAAA,MACjB;AAAA,IACF,SAAS,OAAO;AACd,WAAK,OAAO,KAAK;AAAA,QACf,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MACpD,CAAC;AACD,aAAO;AAAA,QACL,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA,QAAQ,KAAK;AAAA,QACb,UAAU,KAAK;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,YAA8B;AACzD,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,KAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,aAAa,KAAK,cAAc;AAEtC,YAAI,KAAK,2BAA2B,UAAU,GAAG;AAC/C,gBAAM,OAAO,WAAW,QAAQ;AAChC,gBAAM,SAAS,WAAW,cAAc;AAExC,cAAI,SAAS,YAAY,OAAO,QAAQ,MAAM,KAAK;AACjD,kBAAM,OAAO,KAAK,aAAa;AAG/B,gBAAI,KAAK,WAAW,GAAG;AACrB,oBAAM,cAAc,KAAK,CAAC,GAAG,QAAQ;AACrC,kBAAI,aAAa;AACf,qBAAK,gBAAgB,wBAAwB,WAAW,GAAG;AAE3D,qBAAK,SAAS;AAAA,kBACZ,GAAG,WAAW,YAAY,CAAC,IAAI,KAAK,mBAAmB,CAAC;AAAA,gBAE1D;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,oBAAoB,YAAqC;AAC/D,UAAM,eAAe,oBAAI,IAAY;AAErC,eAAW,kBAAkB,CAAC,SAAS;AAErC,UAAI,KAAK,sBAAsB,IAAI,GAAG;AACpC,cAAM,WAAW,KAAK,YAAY;AAClC,YAAI,UAAU,QAAQ,EAAE,SAAS,UAAU,GAAG;AAC5C,uBAAa,IAAI,KAAK,QAAQ,CAAC;AAAA,QACjC;AAAA,MACF;AAGA,UAAI,KAAK,cAAc,IAAI,GAAG;AAC5B,cAAM,QAAQ,KAAK,uBAAuB;AAC1C,YAAI,OAAO;AACT,gBAAM,QAAQ,KAAK,SAAS;AAC5B,gBAAM,YAAY,MAAM,QAAQ;AAChC,cAAI,UAAU,SAAS,qBAAqB,KAAK,UAAU,SAAS,UAAU,GAAG;AAC/E,yBAAa,IAAI,MAAM,QAAQ,CAAC;AAAA,UAClC;AAAA,QACF;AAAA,MACF;AAGA,UAAI,KAAK,sBAAsB,IAAI,GAAG;AACpC,cAAM,cAAc,KAAK,eAAe;AACxC,YAAI,aAAa,QAAQ,EAAE,SAAS,aAAa,GAAG;AAClD,uBAAa,IAAI,GAAG,KAAK,QAAQ,CAAC,QAAQ;AAAA,QAC5C;AAAA,MACF;AAGA,UAAI,KAAK,gBAAgB,IAAI,GAAG;AAC9B,YAAI,KAAK,cAAc,EAAE,QAAQ,MAAM,YAAY;AACjD,gBAAM,SAAS,KAAK,UAAU;AAC9B,cAAI,UAAU,KAAK,sBAAsB,MAAM,GAAG;AAChD,yBAAa,IAAI,OAAO,QAAQ,CAAC;AAAA,UACnC;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,yBAAyB,YAA8B;AAC7D,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,eAAe,KAAK,oBAAoB,UAAU;AAGxD,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,KAAK,2BAA2B,IAAI,GAAG;AACzC,cAAM,OAAO,KAAK,QAAQ;AAC1B,YAAI,SAAS,UAAU;AACrB,gBAAM,SAAS,KAAK,cAAc;AAClC,gBAAM,aAAa,OAAO,QAAQ;AAGlC,gBAAM,aACJ,aAAa,IAAI,UAAU;AAAA,UAE1B,WAAW,SAAS,QAAQ,KAC3B,aAAa,IAAI,GAAG,WAAW,QAAQ,YAAY,EAAE,CAAC,QAAQ;AAElE,cAAI,YAAY;AACd,kBAAM,WAAW,KAAK,QAAQ;AAC9B,kBAAM,UAAU,SAAS,QAAQ,aAAa,SAAS;AACvD,iBAAK,gBAAgB,OAAO;AAE5B,iBAAK,SAAS;AAAA,cACZ,GAAG,QAAQ,IAAI,KAAK,mBAAmB,CAAC;AAAA,YAE1C;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAiB,YAA8B;AACrD,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,eAAe,KAAK,oBAAoB,UAAU;AAExD,UAAM,mBAID,CAAC;AAEN,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,KAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,aAAa,KAAK,cAAc;AACtC,YAAI,KAAK,2BAA2B,UAAU,KAAK,WAAW,QAAQ,MAAM,WAAW;AACrF,gBAAM,aAAa,WAAW,cAAc,EAAE,QAAQ;AACtD,gBAAM,aACJ,aAAa,IAAI,UAAU,KAC1B,WAAW,SAAS,QAAQ,KAC3B,aAAa,IAAI,GAAG,WAAW,QAAQ,YAAY,EAAE,CAAC,QAAQ;AAElE,cAAI,YAAY;AACd,6BAAiB,KAAK;AAAA,cACpB;AAAA,cACA;AAAA,cACA,YAAY,KAAK,mBAAmB;AAAA,YACtC,CAAC;AAAA,UACH,OAAO;AACL,iBAAK,SAAS;AAAA,cACZ,GAAG,QAAQ,IAAI,KAAK,mBAAmB,CAAC;AAAA,YAG1C;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAGD,qBAAiB,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS,CAAC;AAErE,eAAW,EAAE,MAAM,YAAY,WAAW,KAAK,kBAAkB;AAC/D,WAAK,gBAAgB,kBAAkB,UAAU,GAAG;AACpD,WAAK,SAAS;AAAA,QACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,MAE3B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,YAA8B;AACpD,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,eAAe,KAAK,oBAAoB,UAAU;AAExD,UAAM,mBAID,CAAC;AAEN,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,KAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,aAAa,KAAK,cAAc;AACtC,YAAI,KAAK,2BAA2B,UAAU,KAAK,WAAW,QAAQ,MAAM,UAAU;AACpF,gBAAM,aAAa,WAAW,cAAc,EAAE,QAAQ;AACtD,gBAAM,aACJ,aAAa,IAAI,UAAU,KAC1B,WAAW,SAAS,QAAQ,KAC3B,aAAa,IAAI,GAAG,WAAW,QAAQ,YAAY,EAAE,CAAC,QAAQ;AAElE,cAAI,YAAY;AACd,6BAAiB,KAAK;AAAA,cACpB;AAAA,cACA;AAAA,cACA,YAAY,KAAK,mBAAmB;AAAA,YACtC,CAAC;AAAA,UACH;AAAA,QAEF;AAAA,MACF;AAAA,IACF,CAAC;AAGD,qBAAiB,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS,CAAC;AAErE,eAAW,EAAE,MAAM,YAAY,WAAW,KAAK,kBAAkB;AAC/D,WAAK,gBAAgB,kBAAkB,UAAU,GAAG;AACpD,WAAK,SAAS;AAAA,QACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,MAE3B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB,YAA8B;AACvD,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,mBAGD,CAAC;AAEN,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,KAAK,2BAA2B,IAAI,KAAK,KAAK,QAAQ,MAAM,QAAQ;AACtE,yBAAiB,KAAK,EAAE,MAAM,YAAY,KAAK,mBAAmB,EAAE,CAAC;AAAA,MACvE;AAAA,IACF,CAAC;AAGD,qBAAiB,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS,CAAC;AAErE,eAAW,EAAE,MAAM,WAAW,KAAK,kBAAkB;AACnD,YAAM,aAAa,KAAK,cAAc,EAAE,QAAQ;AAChD,WAAK,gBAAgB,GAAG,UAAU,WAAW;AAC7C,WAAK,SAAS;AAAA,QACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,MAE3B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,YAA8B;AACnD,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,mBACJ,CAAC;AAEH,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,KAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,aAAa,KAAK,cAAc;AACtC,YAAI,KAAK,2BAA2B,UAAU,KAAK,WAAW,QAAQ,MAAM,SAAS;AACnF,2BAAiB,KAAK,EAAE,MAAM,YAAY,KAAK,mBAAmB,EAAE,CAAC;AAAA,QACvE;AAAA,MACF;AAAA,IACF,CAAC;AAGD,qBAAiB,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS,CAAC;AAErE,eAAW,EAAE,MAAM,WAAW,KAAK,kBAAkB;AACnD,YAAM,OAAO,KAAK,aAAa;AAC/B,UAAI,KAAK,WAAW,GAAG;AACrB,cAAM,UAAU,KAAK,CAAC,GAAG,QAAQ;AACjC,YAAI,SAAS;AACX,gBAAM,aAAa,KAAK,cAAc;AACtC,cAAI,KAAK,2BAA2B,UAAU,GAAG;AAC/C,kBAAM,aAAa,WAAW,cAAc,EAAE,QAAQ;AACtD,iBAAK,gBAAgB,GAAG,UAAU,WAAW,OAAO,SAAS;AAC7D,iBAAK,SAAS;AAAA,cACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,YAE3B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAoB,YAA8B;AACxD,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,UAAU,SAAS,QAAQ,sBAAsB,SAAS;AAChE,QAAI,YAAY,UAAU;AACxB,iBAAW,gBAAgB,OAAO;AAClC,WAAK,SAAS;AAAA,QACZ,GAAG,QAAQ;AAAA,MAEb;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAAuB,YAA8B;AAC3D,UAAM,WAAW,WAAW,YAAY;AAExC,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,KAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,aAAa,KAAK,cAAc;AACtC,YAAI,KAAK,2BAA2B,UAAU,GAAG;AAC/C,gBAAM,OAAO,WAAW,QAAQ;AAChC,cAAI,mBAAmB,IAAI,IAAI,KAAK,CAAC,mBAAmB,IAAI,IAAI,GAAG;AACjE,kBAAM,aAAa,KAAK,mBAAmB;AAC3C,oBAAQ,MAAM;AAAA,cACZ,KAAK;AACH,qBAAK,SAAS;AAAA,kBACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,gBAE3B;AACA;AAAA,cACF,KAAK;AACH,qBAAK,SAAS;AAAA,kBACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,gBAE3B;AACA;AAAA,YAEJ;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,YAA8B;AACzD,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,mBAGD,CAAC;AAEN,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,KAAK,2BAA2B,IAAI,KAAK,KAAK,QAAQ,MAAM,eAAe;AAC7E,yBAAiB,KAAK,EAAE,MAAM,YAAY,KAAK,mBAAmB,EAAE,CAAC;AAAA,MACvE;AAAA,IACF,CAAC;AAGD,qBAAiB,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS,CAAC;AAErE,eAAW,EAAE,MAAM,WAAW,KAAK,kBAAkB;AACnD,YAAM,SAAS,KAAK,UAAU;AAC9B,UAAI,UAAU,KAAK,iBAAiB,MAAM,GAAG;AAC3C,cAAM,aAAa,KAAK,cAAc,EAAE,QAAQ;AAChD,cAAM,OAAO,OAAO,aAAa;AACjC,YAAI,WAAW,KAAK,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,KAAK,IAAI;AAGrD,YAAI,KAAK,SAAS,GAAG;AACnB,gBAAM,eAAe,KAAK,CAAC,GAAG,QAAQ,KAAK;AAE3C,gBAAM,aAAa,aAAa;AAAA,YAC9B;AAAA,UACF;AACA,cAAI,aAAa,CAAC,GAAG;AACnB,kBAAM,UAAU,WAAW,CAAC;AAC5B,kBAAM,kBAAkB,IAAI,OAAO,GAAG,OAAO,kBAAkB,GAAG;AAClE,gBAAI,gBAAgB,KAAK,YAAY,GAAG;AACtC,yBAAW,aAAa;AAAA,gBACtB,IAAI,OAAO,GAAG,OAAO,kBAAkB,GAAG;AAAA,gBAC1C,GAAG,OAAO;AAAA,cACZ;AAEA,kBAAI,KAAK,SAAS,GAAG;AACnB,sBAAM,YAAY,KACf,MAAM,CAAC,EACP,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EACtB,KAAK,IAAI;AACZ,2BAAW,GAAG,QAAQ,KAAK,SAAS;AAAA,cACtC;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,eAAO,gBAAgB,GAAG,UAAU,UAAU,QAAQ,GAAG;AACzD,aAAK,SAAS;AAAA,UACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,YAA8B;AACzD,UAAM,WAAW,WAAW,YAAY;AACxC,UAAM,mBAGD,CAAC;AAEN,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,KAAK,0BAA0B,IAAI,GAAG;AACxC,cAAM,aAAa,KAAK,cAAc;AACtC,cAAM,YAAY,WACf,OAAO,CAAC,MAAM,KAAK,qBAAqB,CAAC,CAAC,EAC1C,IAAI,CAAC,MAAO,KAAK,qBAAqB,CAAC,IAAI,EAAE,QAAQ,IAAI,EAAG;AAE/D,cAAM,iBAAiB,UAAU,SAAS,oBAAoB;AAC9D,cAAM,cAAc,UAAU,SAAS,gBAAgB;AAEvD,YAAI,kBAAkB,aAAa;AAEjC,gBAAM,SAAS,KAAK,UAAU;AAC9B,cAAI,UAAU,KAAK,iBAAiB,MAAM,GAAG;AAC3C,kBAAM,OAAO,OAAO,cAAc;AAClC,gBAAI,KAAK,2BAA2B,IAAI,KAAK,KAAK,cAAc,EAAE,QAAQ,MAAM,KAAK;AACnF,+BAAiB,KAAK,EAAE,MAAM,YAAY,KAAK,mBAAmB,EAAE,CAAC;AAAA,YACvE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAGD,qBAAiB,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS,CAAC;AAErE,eAAW,EAAE,MAAM,WAAW,KAAK,kBAAkB;AACnD,YAAM,aAAa,KAAK,cAAc;AACtC,UAAI;AACJ,UAAI;AACJ,YAAM,aAAuB,CAAC;AAE9B,iBAAW,QAAQ,YAAY;AAC7B,YAAI,KAAK,qBAAqB,IAAI,GAAG;AACnC,gBAAM,OAAO,KAAK,QAAQ;AAC1B,gBAAM,QAAQ,KAAK,eAAe,GAAG,QAAQ,KAAK;AAClD,cAAI,SAAS,sBAAsB;AACjC,+BAAmB;AAAA,UACrB,WAAW,SAAS,kBAAkB;AACpC,4BAAgB;AAAA,UAClB,OAAO;AACL,uBAAW,KAAK,KAAK,QAAQ,CAAC;AAAA,UAChC;AAAA,QACF;AAAA,MACF;AAEA,UAAI;AACJ,UAAI,oBAAoB,eAAe;AAErC,qBAAa,iDAAiD,aAAa,MAAM,gBAAgB;AAAA,MACnG,WAAW,eAAe;AACxB,qBAAa,UAAU,aAAa;AAAA,MACtC,WAAW,kBAAkB;AAC3B,qBAAa,UAAU,gBAAgB;AAAA,MACzC,OAAO;AACL;AAAA,MACF;AAEA,YAAM,WAAW,CAAC,YAAY,GAAG,UAAU,EAAE,KAAK,IAAI;AACtD,WAAK,gBAAgB,KAAK,QAAQ,IAAI;AAEtC,WAAK,SAAS;AAAA,QACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,qBAAqB,YAA8B;AACzD,UAAM,WAAW,WAAW,YAAY;AAExC,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,KAAK,cAAc,IAAI,GAAG;AAC5B,cAAM,QAAQ,KAAK,SAAS;AAC5B,cAAM,YAAY,MAAM,QAAQ;AAGhC,YAAI,UAAU,SAAS,UAAU,KAAK,UAAU,SAAS,kBAAkB,GAAG;AAC5E,gBAAM,aAAa,KAAK,mBAAmB;AAC3C,eAAK,SAAS;AAAA,YACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,UAG3B;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,0BAA0B,YAA8B;AAC9D,UAAM,WAAW,WAAW,YAAY;AAExC,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,KAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,aAAa,KAAK,cAAc;AACtC,YAAI,KAAK,2BAA2B,UAAU,KAAK,WAAW,QAAQ,MAAM,aAAa;AAEvF,gBAAM,YAAY,KAAK,QAAQ;AAC/B,cACE,UAAU,SAAS,UAAU,KAC7B,UAAU,SAAS,eAAe,KAClC,UAAU,SAAS,SAAS,GAC5B;AACA,kBAAM,aAAa,KAAK,mBAAmB;AAC3C,iBAAK,SAAS;AAAA,cACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,YAE3B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,qBAAqB,YAA8B;AACzD,UAAM,WAAW,WAAW,YAAY;AAExC,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,KAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,aAAa,KAAK,cAAc;AACtC,YACE,KAAK,2BAA2B,UAAU,MACzC,WAAW,QAAQ,MAAM,cAAc,WAAW,QAAQ,MAAM,YACjE;AACA,gBAAM,YAAY,KAAK,QAAQ;AAC/B,gBAAM,aAAa,UAAU,SAAS,WAAW;AACjD,gBAAM,cAAc,UAAU,SAAS,YAAY;AAEnD,cAAI,cAAc,aAAa;AAC7B,kBAAM,aAAa,KAAK,mBAAmB;AAC3C,iBAAK,SAAS;AAAA,cACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,YAG3B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,YAA8B;AACzD,UAAM,WAAW,WAAW,YAAY;AAExC,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,KAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,aAAa,KAAK,cAAc;AAEtC,YAAI,KAAK,2BAA2B,UAAU,GAAG;AAC/C,gBAAM,OAAO,WAAW,QAAQ;AAEhC,cAAI,iBAAiB,IAAI,IAAI,GAAG;AAC9B,kBAAM,aAAa,KAAK,mBAAmB;AAE3C,oBAAQ,MAAM;AAAA,cACZ,KAAK;AACH,qBAAK,SAAS;AAAA,kBACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,gBAE3B;AACA;AAAA,cAEF,KAAK;AACH,qBAAK,SAAS;AAAA,kBACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,gBAE3B;AACA;AAAA,cAEF,KAAK;AACH,qBAAK,SAAS;AAAA,kBACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,gBAE3B;AACA;AAAA,cAEF,KAAK;AACH,qBAAK,SAAS;AAAA,kBACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,gBAE3B;AACA;AAAA,cAEF,KAAK;AACH,qBAAK,SAAS;AAAA,kBACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,gBAG3B;AACA;AAAA,YACJ;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmB,YAA8B;AACvD,UAAM,WAAW,WAAW,YAAY;AAExC,eAAW,kBAAkB,CAAC,SAAS;AACrC,UAAI,KAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,aAAa,KAAK,cAAc;AACtC,YACE,KAAK,2BAA2B,UAAU,MACzC,WAAW,QAAQ,MAAM,cAAc,WAAW,QAAQ,MAAM,UACjE;AACA,gBAAM,YAAY,KAAK,QAAQ;AAC/B,cAAI,UAAU,SAAS,SAAS,KAAK,UAAU,SAAS,YAAY,GAAG;AACrE,kBAAM,aAAa,KAAK,mBAAmB;AAC3C,iBAAK,SAAS;AAAA,cACZ,GAAG,QAAQ,IAAI,UAAU;AAAA,YAG3B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,wBAAwB,YAA8B;AAC5D,UAAM,WAAW,WAAW,YAAY;AAExC,eAAW,cAAc,WAAW,sBAAsB,GAAG;AAC3D,YAAM,kBAAkB,WAAW,wBAAwB;AAC3D,UAAI,oBAAoB,MAAO;AAE/B,YAAM,eAAe,WAAW,gBAAgB;AAChD,iBAAW,eAAe,cAAc;AACtC,cAAM,OAAO,YAAY,QAAQ;AACjC,YAAI,cAAc,IAAI,IAAI,GAAG;AAC3B,gBAAM,aAAa,WAAW,mBAAmB;AACjD,eAAK,SAAS;AAAA,YACZ,GAAG,QAAQ,IAAI,UAAU,MAAM,IAAI;AAAA,UAErC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AEluBO,SAAS,yBAA2C;AACzD,QAAM,cAAc,IAAI,qBAAqB;AAC7C,SAAO;AAAA,IACL,UAAU,YAAwB,UAA6C;AAC7E,aAAO,YAAY,UAAU,UAAU;AAAA,IACzC;AAAA,EACF;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schemashift/zod-v3-v4",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "Zod v3 to v4 upgrade transformer for SchemaShift — handles 17+ breaking changes with auto-transforms and runtime warnings",
5
5
  "keywords": [
6
6
  "zod",
@@ -37,7 +37,7 @@
37
37
  "typecheck": "tsc --noEmit"
38
38
  },
39
39
  "dependencies": {
40
- "@schemashift/core": "0.7.0",
40
+ "@schemashift/core": "0.9.0",
41
41
  "ts-morph": "27.0.2"
42
42
  },
43
43
  "publishConfig": {