zodvex 0.7.1-beta.2 → 0.7.1-beta.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"codemod.d.ts","sourceRoot":"","sources":["../../src/cli/codemod.ts"],"names":[],"mappings":"AAaA,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,IAAI,CAAC,CA+Df"}
1
+ {"version":3,"file":"codemod.d.ts","sourceRoot":"","sources":["../../src/cli/codemod.ts"],"names":[],"mappings":"AAyBA,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,IAAI,CAAC,CA6Ef"}
package/dist/cli/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bun
2
- import fs2, { readFileSync, writeFileSync } from 'fs';
3
- import path3, { resolve, relative } from 'path';
2
+ import fs2, { readFileSync, writeFileSync, existsSync } from 'fs';
3
+ import path3, { resolve, relative, join } from 'path';
4
4
  import { Project, SyntaxKind } from 'ts-morph';
5
5
  import { globSync } from 'tinyglobby';
6
6
  import { $ZodCodec, $ZodNumber, $ZodCustom, $ZodOptional, $ZodNullable, $ZodObject, $ZodUnion, $ZodArray, $ZodRecord, $ZodTuple, $ZodString, $ZodBoolean, $ZodNull, $ZodUndefined, $ZodAny, $ZodEnum, $ZodLiteral } from 'zod/v4/core';
@@ -341,6 +341,11 @@ function transformMethods(file, typeChecker) {
341
341
  count++;
342
342
  continue;
343
343
  }
344
+ if (method === "unwrap" && call.getArguments().length === 0) {
345
+ call.replaceWithText(`${obj}._zod.def.innerType`);
346
+ count++;
347
+ continue;
348
+ }
344
349
  if (CHECK_WRAP_METHODS.includes(method)) {
345
350
  const argsStr = args.join(", ");
346
351
  call.replaceWithText(`${obj}.check(z.${method}(${argsStr}))`);
@@ -378,6 +383,65 @@ function transformConstructorReplacements(file) {
378
383
  }
379
384
  return count;
380
385
  }
386
+ function isZodSchemaByTypePA(pa, typeChecker) {
387
+ const receiver = pa.getExpression();
388
+ try {
389
+ const type = typeChecker.getTypeAtLocation(receiver);
390
+ if (type.isAny()) return null;
391
+ return type.getProperties().some((p) => p.getName() === "_zod");
392
+ } catch {
393
+ return null;
394
+ }
395
+ }
396
+ function transformPropertyAccessors(file, typeChecker) {
397
+ let count = 0;
398
+ const propAccesses = file.getDescendantsOfKind(SyntaxKind.PropertyAccessExpression).reverse();
399
+ for (const pa of propAccesses) {
400
+ if (pa.wasForgotten()) continue;
401
+ const propName = pa.getName();
402
+ const replacement = INTERNAL_PROPERTY_ACCESSORS[propName];
403
+ if (!replacement) continue;
404
+ const receiver = pa.getExpression();
405
+ const receiverText = receiver.getText();
406
+ if (NAMESPACE_IDENTIFIERS.has(receiverText.trim())) continue;
407
+ if (receiverText.includes("._zod.def.") || receiverText.endsWith("._zod.def")) continue;
408
+ let isSchema;
409
+ if (typeChecker) {
410
+ const typeResult = isZodSchemaByTypePA(pa, typeChecker);
411
+ isSchema = typeResult === true || typeResult === null && isLikelySchemaExpr(receiverText);
412
+ } else {
413
+ isSchema = isLikelySchemaExpr(receiverText);
414
+ }
415
+ if (!isSchema) continue;
416
+ pa.replaceWithText(`${receiverText}.${replacement}`);
417
+ count++;
418
+ }
419
+ return count;
420
+ }
421
+ function findInternalPropertyAccess(file, typeChecker) {
422
+ const results = [];
423
+ const propAccesses = file.getDescendantsOfKind(SyntaxKind.PropertyAccessExpression);
424
+ for (const pa of propAccesses) {
425
+ if (pa.wasForgotten()) continue;
426
+ const propName = pa.getName();
427
+ if (!(propName in INTERNAL_PROPERTY_ACCESSORS)) continue;
428
+ const receiver = pa.getExpression();
429
+ const receiverText = receiver.getText();
430
+ if (NAMESPACE_IDENTIFIERS.has(receiverText.trim())) continue;
431
+ if (receiverText.includes("._zod.def.") || receiverText.endsWith("._zod.def")) continue;
432
+ if (isLikelySchemaExpr(receiverText)) continue;
433
+ if (typeChecker) {
434
+ const typeResult = isZodSchemaByTypePA(pa, typeChecker);
435
+ if (typeResult === false) continue;
436
+ }
437
+ results.push({
438
+ line: pa.getStartLineNumber(),
439
+ property: propName,
440
+ text: pa.getText().slice(0, 80)
441
+ });
442
+ }
443
+ return results;
444
+ }
381
445
  function findObjectOnlyMethods(file) {
382
446
  const results = [];
383
447
  const calls = file.getDescendantsOfKind(SyntaxKind.CallExpression);
@@ -406,7 +470,8 @@ function transformImports(file) {
406
470
  }
407
471
  function transformClassRefs(file) {
408
472
  let count = 0;
409
- const neededImports = /* @__PURE__ */ new Set();
473
+ const runtimeImports = /* @__PURE__ */ new Set();
474
+ const typeOnlyImports = /* @__PURE__ */ new Set();
410
475
  const propAccesses = file.getDescendantsOfKind(SyntaxKind.PropertyAccessExpression);
411
476
  for (const pa of propAccesses) {
412
477
  if (pa.wasForgotten()) continue;
@@ -414,33 +479,69 @@ function transformClassRefs(file) {
414
479
  const replacement = CLASS_RENAMES[text];
415
480
  if (!replacement) continue;
416
481
  pa.replaceWithText(replacement);
417
- neededImports.add(replacement);
482
+ runtimeImports.add(replacement);
483
+ count++;
484
+ }
485
+ const qualNames = file.getDescendantsOfKind(SyntaxKind.QualifiedName);
486
+ for (const qn of qualNames) {
487
+ if (qn.wasForgotten()) continue;
488
+ const text = qn.getText();
489
+ const replacement = CLASS_RENAMES[text];
490
+ if (!replacement) continue;
491
+ qn.replaceWithText(replacement);
492
+ if (!runtimeImports.has(replacement)) {
493
+ typeOnlyImports.add(replacement);
494
+ }
418
495
  count++;
419
496
  }
420
- if (neededImports.size > 0) {
497
+ for (const name of runtimeImports) {
498
+ typeOnlyImports.delete(name);
499
+ }
500
+ const addToExistingImport = (imp, names) => {
501
+ if (!imp) return;
502
+ for (const name of names) {
503
+ if (!imp.getNamedImports().some((n) => n.getName() === name)) {
504
+ imp.addNamedImport(name);
505
+ }
506
+ }
507
+ };
508
+ if (runtimeImports.size > 0) {
421
509
  const existingCoreImport = file.getImportDeclaration(
422
- (d) => d.getModuleSpecifierValue() === "zod/v4/core"
510
+ (d) => d.getModuleSpecifierValue() === "zod/v4/core" && !d.isTypeOnly()
423
511
  );
424
512
  if (existingCoreImport) {
425
- for (const name of neededImports) {
426
- if (!existingCoreImport.getNamedImports().some((n) => n.getName() === name)) {
427
- existingCoreImport.addNamedImport(name);
428
- }
429
- }
513
+ addToExistingImport(existingCoreImport, runtimeImports);
430
514
  } else {
431
515
  const internalImport = file.getImportDeclaration(
432
- (d) => d.getModuleSpecifierValue().endsWith("/zod-core")
516
+ (d) => d.getModuleSpecifierValue().endsWith("/zod-core") && !d.isTypeOnly()
433
517
  );
434
518
  if (internalImport) {
435
- for (const name of neededImports) {
436
- if (!internalImport.getNamedImports().some((n) => n.getName() === name)) {
437
- internalImport.addNamedImport(name);
438
- }
439
- }
519
+ addToExistingImport(internalImport, runtimeImports);
520
+ } else {
521
+ file.addImportDeclaration({
522
+ moduleSpecifier: "zod/v4/core",
523
+ namedImports: [...runtimeImports].sort()
524
+ });
525
+ }
526
+ }
527
+ }
528
+ if (typeOnlyImports.size > 0) {
529
+ const existingTypeImport = file.getImportDeclaration(
530
+ (d) => d.getModuleSpecifierValue() === "zod/v4/core" && d.isTypeOnly()
531
+ );
532
+ if (existingTypeImport) {
533
+ addToExistingImport(existingTypeImport, typeOnlyImports);
534
+ } else {
535
+ const internalTypeImport = file.getImportDeclaration(
536
+ (d) => d.getModuleSpecifierValue().endsWith("/zod-core") && d.isTypeOnly()
537
+ );
538
+ if (internalTypeImport) {
539
+ addToExistingImport(internalTypeImport, typeOnlyImports);
440
540
  } else {
441
541
  file.addImportDeclaration({
442
542
  moduleSpecifier: "zod/v4/core",
443
- namedImports: [...neededImports].sort()
543
+ namedImports: [...typeOnlyImports].sort(),
544
+ isTypeOnly: true
444
545
  });
445
546
  }
446
547
  }
@@ -453,19 +554,23 @@ function transformFile(file, typeChecker) {
453
554
  let wrappers = 0;
454
555
  let checks = 0;
455
556
  let methods = 0;
557
+ let propertyAccessors = 0;
456
558
  for (let i = 0; i < 10; i++) {
457
559
  const cr = transformConstructorReplacements(file);
458
560
  const w = transformWrappers(file);
459
561
  const c = transformChecks(file);
460
562
  const m = transformMethods(file, typeChecker);
563
+ const pa = transformPropertyAccessors(file, typeChecker);
461
564
  constructorReplacements += cr;
462
565
  wrappers += w;
463
566
  checks += c;
464
567
  methods += m;
465
- if (cr + w + c + m === 0) break;
568
+ propertyAccessors += pa;
569
+ if (cr + w + c + m + pa === 0) break;
466
570
  }
467
571
  const classRefs = transformClassRefs(file);
468
572
  const objectOnlyWarnings = findObjectOnlyMethods(file);
573
+ const propertyAccessWarnings = findInternalPropertyAccess(file, typeChecker);
469
574
  const imports = 0;
470
575
  return {
471
576
  filePath,
@@ -473,10 +578,12 @@ function transformFile(file, typeChecker) {
473
578
  wrappers,
474
579
  checks,
475
580
  methods,
581
+ propertyAccessors,
476
582
  imports,
477
583
  classRefs,
478
584
  objectOnlyWarnings,
479
- totalChanges: constructorReplacements + wrappers + checks + methods + classRefs
585
+ propertyAccessWarnings,
586
+ totalChanges: constructorReplacements + wrappers + checks + methods + propertyAccessors + classRefs
480
587
  };
481
588
  }
482
589
  function transformCode(code, options) {
@@ -504,7 +611,7 @@ function transformCode(code, options) {
504
611
  return { code, changed: false };
505
612
  }
506
613
  }
507
- var WRAPPER_METHODS, NAMESPACE_IDENTIFIERS, ZOD_ONLY_CHECK_METHODS, AMBIGUOUS_CHECK_METHODS, STRING_RENAME, NUMBER_RENAME, UNCONDITIONAL_TOP_LEVEL, AMBIGUOUS_TOP_LEVEL, RENAMED_METHODS, TRANSFORM_METHOD, CHECK_WRAP_METHODS, CONSTRUCTOR_REPLACEMENTS, WARN_METHODS, CLASS_RENAMES;
614
+ var WRAPPER_METHODS, NAMESPACE_IDENTIFIERS, ZOD_ONLY_CHECK_METHODS, AMBIGUOUS_CHECK_METHODS, STRING_RENAME, NUMBER_RENAME, UNCONDITIONAL_TOP_LEVEL, AMBIGUOUS_TOP_LEVEL, RENAMED_METHODS, TRANSFORM_METHOD, CHECK_WRAP_METHODS, CONSTRUCTOR_REPLACEMENTS, INTERNAL_PROPERTY_ACCESSORS, WARN_METHODS, CLASS_RENAMES;
508
615
  var init_transforms = __esm({
509
616
  "../zod-to-mini/src/transforms.ts"() {
510
617
  WRAPPER_METHODS = ["optional", "nullable"];
@@ -550,7 +657,7 @@ var init_transforms = __esm({
550
657
  min: "gte",
551
658
  max: "lte"
552
659
  };
553
- UNCONDITIONAL_TOP_LEVEL = ["pipe", "brand"];
660
+ UNCONDITIONAL_TOP_LEVEL = ["pipe", "brand", "parse", "safeParse"];
554
661
  AMBIGUOUS_TOP_LEVEL = ["partial", "extend", "catchall", "omit", "pick"];
555
662
  RENAMED_METHODS = /* @__PURE__ */ new Map([
556
663
  ["default", "_default"]
@@ -561,6 +668,11 @@ var init_transforms = __esm({
561
668
  passthrough: "looseObject",
562
669
  strict: "strictObject"
563
670
  };
671
+ INTERNAL_PROPERTY_ACCESSORS = {
672
+ shape: "_zod.def.shape",
673
+ element: "_zod.def.element",
674
+ options: "_zod.def.options"
675
+ };
564
676
  WARN_METHODS = [
565
677
  "merge"
566
678
  // use z.extend() or spread
@@ -569,6 +681,7 @@ var init_transforms = __esm({
569
681
  "z.ZodError": "$ZodError",
570
682
  "z.ZodType": "$ZodType",
571
683
  "z.ZodTypeAny": "$ZodType",
684
+ "z.ZodRawShape": "$ZodShape",
572
685
  "z.ZodObject": "$ZodObject",
573
686
  "z.ZodArray": "$ZodArray",
574
687
  "z.ZodString": "$ZodString",
@@ -583,7 +696,12 @@ var init_transforms = __esm({
583
696
  "z.ZodCustom": "$ZodCustom",
584
697
  "z.ZodDefault": "$ZodDefault",
585
698
  "z.ZodRecord": "$ZodRecord",
586
- "z.ZodTuple": "$ZodTuple"
699
+ "z.ZodTuple": "$ZodTuple",
700
+ "z.ZodDiscriminatedUnion": "$ZodDiscriminatedUnion",
701
+ "z.ZodLazy": "$ZodLazy",
702
+ "z.ZodPipe": "$ZodPipe",
703
+ "z.ZodTransform": "$ZodTransform",
704
+ "z.ZodReadonly": "$ZodReadonly"
587
705
  };
588
706
  }
589
707
  });
@@ -646,6 +764,16 @@ var codemod_exports = {};
646
764
  __export(codemod_exports, {
647
765
  runToMiniCodemod: () => runToMiniCodemod
648
766
  });
767
+ function findTsconfig(startDir) {
768
+ let dir = startDir;
769
+ while (true) {
770
+ const candidate = join(dir, "tsconfig.json");
771
+ if (existsSync(candidate)) return candidate;
772
+ const parent = resolve(dir, "..");
773
+ if (parent === dir) return void 0;
774
+ dir = parent;
775
+ }
776
+ }
649
777
  async function runToMiniCodemod(targetDir, options = {}) {
650
778
  const { transformCode: transformCode2, transformImports: transformImports2 } = await Promise.resolve().then(() => (init_src(), src_exports));
651
779
  const { Project: Project3 } = await import('ts-morph');
@@ -655,6 +783,15 @@ async function runToMiniCodemod(targetDir, options = {}) {
655
783
  ignore: ["_generated/**", "_zodvex/**", "**/*.d.ts", "node_modules/**"],
656
784
  absolute: true
657
785
  });
786
+ let typeProject;
787
+ const tsconfigPath = findTsconfig(dir);
788
+ if (tsconfigPath) {
789
+ typeProject = new Project3({
790
+ tsConfigFilePath: tsconfigPath,
791
+ skipAddingFilesFromTsConfig: true
792
+ });
793
+ console.log(`[zodvex codemod] Using type checker (${relative(process.cwd(), tsconfigPath)})`);
794
+ }
658
795
  console.log(
659
796
  `[zodvex codemod] ${options.dryRun ? "Dry run \u2014 " : ""}Processing ${files.length} files in ${targetDir}/`
660
797
  );
@@ -663,7 +800,10 @@ async function runToMiniCodemod(targetDir, options = {}) {
663
800
  for (const filePath of files) {
664
801
  const code = readFileSync(filePath, "utf-8");
665
802
  if (!code.includes("'zod'") && !code.includes('"zod"')) continue;
666
- const result = transformCode2(code);
803
+ const result = transformCode2(code, {
804
+ filename: filePath,
805
+ project: typeProject
806
+ });
667
807
  let output = result.code;
668
808
  const project = new Project3({ useInMemoryFileSystem: true });
669
809
  const sf = project.createSourceFile("tmp.ts", output);
@@ -1591,8 +1731,8 @@ Usage:
1591
1731
  zodvex init Set up zodvex in an existing Convex project
1592
1732
  zodvex migrate [dir] Migrate pre-0.6 APIs (renames + import fixes)
1593
1733
  zodvex migrate [dir] --dry-run Preview changes without writing
1594
- zodvex codemod --to-mini [dir] Convert full-zod code to zod/mini syntax
1595
- zodvex codemod --to-mini [dir] --dry-run Preview changes without writing
1734
+ zodvex codemod --to-mini [dir] Convert full-zod code to zod/mini syntax
1735
+ zodvex codemod --to-mini [dir] --dry-run Preview changes without writing
1596
1736
  zodvex help Show this help message
1597
1737
 
1598
1738
  Flags: