schemashift-cli 0.8.0 → 0.10.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/README.md CHANGED
@@ -33,6 +33,10 @@ schemashift analyze <path> [options]
33
33
  | `--detailed` | Full stats with complexity scoring | Individual+ |
34
34
  | `--readiness <path>` | Migration readiness report, e.g. `yup->zod` | Individual+ |
35
35
  | `--complexity` | Per-schema complexity scores | Individual+ |
36
+ | `--behavioral <migration>` | Behavioral difference warnings, e.g. `yup->zod` | Free |
37
+ | `--bundle <migration>` | Bundle size estimation, e.g. `zod->valibot` | Individual+ |
38
+ | `--performance <migration>` | Performance impact analysis, e.g. `zod-v3->v4` | Individual+ |
39
+ | `--dedup` | Detect duplicate type definitions | Individual+ |
36
40
 
37
41
  ### `migrate`
38
42
 
@@ -73,6 +77,8 @@ schemashift migrate <path> [options]
73
77
  | `--compat-check` | Run compatibility check before migration | Pro+ |
74
78
  | `--fail-on-warnings` | Exit 1 if any warnings | Team |
75
79
  | `--max-risk-score <n>` | Exit 1 if any file exceeds risk score | Team |
80
+ | `--scaffold-tests` | Generate validation tests after migration | Pro+ |
81
+ | `--audit` | Enable migration audit logging | Team |
76
82
 
77
83
  ### `watch`
78
84
 
@@ -193,6 +199,18 @@ schemashift migrate ./src --chain yup->zod->valibot
193
199
  # CI mode
194
200
  schemashift migrate ./src --from yup --to zod --ci --report json
195
201
 
202
+ # Backward migration: Zod→Yup
203
+ schemashift migrate ./src --from zod --to yup
204
+
205
+ # Backward migration: Valibot→Zod
206
+ schemashift migrate ./src --from valibot --to zod
207
+
208
+ # Analyze with behavioral warnings and bundle estimation
209
+ schemashift analyze ./src --behavioral yup->zod --bundle yup->zod
210
+
211
+ # Migrate with test scaffolding
212
+ schemashift migrate ./src --from yup --to zod --scaffold-tests
213
+
196
214
  # Rollback last migration
197
215
  schemashift rollback
198
216
  ```
package/dist/cli.js CHANGED
@@ -10,17 +10,25 @@ import { existsSync as existsSync4, readFileSync as readFileSync4, statSync, wri
10
10
  import { dirname as dirname2, join as join3, resolve as resolve2 } from "path";
11
11
  import { fileURLToPath } from "url";
12
12
  import {
13
+ BehavioralWarningAnalyzer,
14
+ BundleEstimator,
13
15
  CompatibilityAnalyzer,
14
16
  DetailedAnalyzer,
15
17
  detectFormLibraries,
16
18
  GovernanceEngine,
19
+ IncrementalTracker,
17
20
  loadConfig,
21
+ MigrationAuditLog,
18
22
  MigrationChain,
23
+ PerformanceAnalyzer,
19
24
  PluginLoader,
20
25
  SchemaAnalyzer,
21
26
  SchemaDependencyResolver,
22
- TransformEngine
27
+ TestScaffolder,
28
+ TransformEngine,
29
+ TypeDedupDetector
23
30
  } from "@schemashift/core";
31
+ import { createIoTsToEffectHandler } from "@schemashift/io-ts-effect";
24
32
  import { createIoTsToZodHandler } from "@schemashift/io-ts-zod";
25
33
  import { createJoiToZodHandler } from "@schemashift/joi-zod";
26
34
 
@@ -35827,7 +35835,13 @@ var TIER_FEATURES = {
35827
35835
  maxRiskScoreThreshold: false,
35828
35836
  formResolverMigration: false,
35829
35837
  complexityEstimator: false,
35830
- monorepoAware: false
35838
+ monorepoAware: false,
35839
+ behavioralWarnings: true,
35840
+ bundleEstimator: false,
35841
+ performanceAnalyzer: false,
35842
+ typeDeduplication: false,
35843
+ testScaffolding: false,
35844
+ auditLogging: false
35831
35845
  },
35832
35846
  [
35833
35847
  "individual"
@@ -35854,7 +35868,13 @@ var TIER_FEATURES = {
35854
35868
  maxRiskScoreThreshold: false,
35855
35869
  formResolverMigration: true,
35856
35870
  complexityEstimator: true,
35857
- monorepoAware: false
35871
+ monorepoAware: false,
35872
+ behavioralWarnings: true,
35873
+ bundleEstimator: true,
35874
+ performanceAnalyzer: true,
35875
+ typeDeduplication: true,
35876
+ testScaffolding: false,
35877
+ auditLogging: false
35858
35878
  },
35859
35879
  [
35860
35880
  "pro"
@@ -35867,7 +35887,14 @@ var TIER_FEATURES = {
35867
35887
  "zod-v3->v4",
35868
35888
  "io-ts->zod",
35869
35889
  "zod->valibot",
35870
- "any->valibot"
35890
+ "any->valibot",
35891
+ "zod->yup",
35892
+ "valibot->zod",
35893
+ "zod->arktype",
35894
+ "arktype->zod",
35895
+ "zod->superstruct",
35896
+ "superstruct->zod",
35897
+ "io-ts->effect"
35871
35898
  ],
35872
35899
  devices: 4,
35873
35900
  ciSupport: true,
@@ -35888,7 +35915,13 @@ var TIER_FEATURES = {
35888
35915
  maxRiskScoreThreshold: false,
35889
35916
  formResolverMigration: true,
35890
35917
  complexityEstimator: true,
35891
- monorepoAware: true
35918
+ monorepoAware: true,
35919
+ behavioralWarnings: true,
35920
+ bundleEstimator: true,
35921
+ performanceAnalyzer: true,
35922
+ typeDeduplication: true,
35923
+ testScaffolding: true,
35924
+ auditLogging: false
35892
35925
  },
35893
35926
  [
35894
35927
  "team"
@@ -35901,7 +35934,14 @@ var TIER_FEATURES = {
35901
35934
  "zod-v3->v4",
35902
35935
  "io-ts->zod",
35903
35936
  "any->valibot",
35904
- "zod->valibot"
35937
+ "zod->valibot",
35938
+ "zod->yup",
35939
+ "valibot->zod",
35940
+ "zod->arktype",
35941
+ "arktype->zod",
35942
+ "zod->superstruct",
35943
+ "superstruct->zod",
35944
+ "io-ts->effect"
35905
35945
  ],
35906
35946
  devices: Infinity,
35907
35947
  ciSupport: true,
@@ -35922,7 +35962,13 @@ var TIER_FEATURES = {
35922
35962
  maxRiskScoreThreshold: true,
35923
35963
  formResolverMigration: true,
35924
35964
  complexityEstimator: true,
35925
- monorepoAware: true
35965
+ monorepoAware: true,
35966
+ behavioralWarnings: true,
35967
+ bundleEstimator: true,
35968
+ performanceAnalyzer: true,
35969
+ typeDeduplication: true,
35970
+ testScaffolding: true,
35971
+ auditLogging: true
35926
35972
  }
35927
35973
  };
35928
35974
  function canUseMigration(tier, from, to) {
@@ -36199,9 +36245,14 @@ var LicenseManager = class {
36199
36245
  };
36200
36246
 
36201
36247
  // src/cli.ts
36202
- import { createYupToZodHandler } from "@schemashift/yup-zod";
36248
+ import { createYupToZodHandler, createZodToYupHandler } from "@schemashift/yup-zod";
36249
+ import { createArktypeToZodHandler, createZodToArktypeHandler } from "@schemashift/zod-arktype";
36250
+ import {
36251
+ createSuperstructToZodHandler,
36252
+ createZodToSuperstructHandler
36253
+ } from "@schemashift/zod-superstruct";
36203
36254
  import { createZodV3ToV4Handler } from "@schemashift/zod-v3-v4";
36204
- import { createZodToValibotHandler } from "@schemashift/zod-valibot";
36255
+ import { createValibotToZodHandler, createZodToValibotHandler } from "@schemashift/zod-valibot";
36205
36256
  import { Command } from "commander";
36206
36257
  import { glob as glob2 } from "glob";
36207
36258
  import { Listr } from "listr2";
@@ -36883,6 +36934,12 @@ var WatchMode = class {
36883
36934
  console.log(pc3.cyan(`
36884
36935
  Watching ${files.length} files for changes...
36885
36936
  `));
36937
+ if (options.dependents && options.dependents.size > 0) {
36938
+ console.log(
36939
+ pc3.dim(`Dependency-aware mode: ${options.dependents.size} files with dependents
36940
+ `)
36941
+ );
36942
+ }
36886
36943
  console.log(pc3.dim("Press Ctrl+C to stop\n"));
36887
36944
  const directories = new Set(files.map((f) => f.split("/").slice(0, -1).join("/")));
36888
36945
  for (const dir of directories) {
@@ -36903,8 +36960,26 @@ Watching ${files.length} files for changes...
36903
36960
  Changed: ${relative2(process.cwd(), fullPath)}`));
36904
36961
  try {
36905
36962
  await options.onTransform(fullPath);
36906
- console.log(pc3.green(`Transformed successfully
36907
- `));
36963
+ console.log(pc3.green(`Transformed successfully`));
36964
+ const dependentFiles = options.dependents?.get(fullPath);
36965
+ if (dependentFiles && dependentFiles.length > 0) {
36966
+ console.log(
36967
+ pc3.cyan(` Re-transforming ${dependentFiles.length} dependent file(s)...`)
36968
+ );
36969
+ for (const depFile of dependentFiles) {
36970
+ try {
36971
+ await options.onTransform(depFile);
36972
+ console.log(pc3.green(` \u2713 ${relative2(process.cwd(), depFile)}`));
36973
+ } catch (error) {
36974
+ console.error(
36975
+ pc3.red(
36976
+ ` \u2717 ${relative2(process.cwd(), depFile)}: ${error instanceof Error ? error.message : String(error)}`
36977
+ )
36978
+ );
36979
+ }
36980
+ }
36981
+ }
36982
+ console.log("");
36908
36983
  } catch (error) {
36909
36984
  console.error(
36910
36985
  pc3.red(
@@ -36930,6 +37005,21 @@ Changed: ${relative2(process.cwd(), fullPath)}`));
36930
37005
  }
36931
37006
  this.debounceTimers.clear();
36932
37007
  }
37008
+ /**
37009
+ * Build a reverse dependency map (file -> files that depend on it).
37010
+ * Takes the forward dependency map from SchemaDependencyResolver and inverts it.
37011
+ */
37012
+ static buildDependentsMap(dependencies) {
37013
+ const dependents = /* @__PURE__ */ new Map();
37014
+ for (const [file, deps] of dependencies) {
37015
+ for (const dep of deps) {
37016
+ const existing = dependents.get(dep) ?? [];
37017
+ existing.push(file);
37018
+ dependents.set(dep, existing);
37019
+ }
37020
+ }
37021
+ return dependents;
37022
+ }
36933
37023
  matchesPatterns(file, include, exclude) {
36934
37024
  const isIncluded = include.some((p) => minimatch(file, p));
36935
37025
  const isExcluded = exclude.some((p) => minimatch(file, p));
@@ -36948,6 +37038,13 @@ engine.registerHandler("joi", "zod", createJoiToZodHandler());
36948
37038
  engine.registerHandler("io-ts", "zod", createIoTsToZodHandler());
36949
37039
  engine.registerHandler("zod-v3", "v4", createZodV3ToV4Handler());
36950
37040
  engine.registerHandler("zod", "valibot", createZodToValibotHandler());
37041
+ engine.registerHandler("zod", "yup", createZodToYupHandler());
37042
+ engine.registerHandler("valibot", "zod", createValibotToZodHandler());
37043
+ engine.registerHandler("zod", "arktype", createZodToArktypeHandler());
37044
+ engine.registerHandler("arktype", "zod", createArktypeToZodHandler());
37045
+ engine.registerHandler("zod", "superstruct", createZodToSuperstructHandler());
37046
+ engine.registerHandler("superstruct", "zod", createSuperstructToZodHandler());
37047
+ engine.registerHandler("io-ts", "effect", createIoTsToEffectHandler());
36951
37048
  var POLAR_URL = "https://schemashift.qwady.app";
36952
37049
  program.name("schemashift").version(pkg.version).description("TypeScript schema migration CLI");
36953
37050
  program.command("init").description("Create .schemashiftrc.json config file").option("-f, --force", "Overwrite existing config").action((options) => {
@@ -36977,7 +37074,10 @@ program.command("init").description("Create .schemashiftrc.json config file").op
36977
37074
  console.log(pc4.green("Created .schemashiftrc.json"));
36978
37075
  console.log(pc4.dim("Edit the file to customize your migration settings."));
36979
37076
  });
36980
- program.command("analyze <path>").description("Analyze schemas in your project").option("--json", "Output as JSON").option("-v, --verbose", "Show detailed analysis").option("--detailed", "Show complexity analysis (Individual+)").option("--readiness <migration>", "Check migration readiness, e.g. yup->zod (Individual+)").option("--complexity", "Show per-schema complexity scores (Individual+)").action(async (targetPath, options) => {
37077
+ program.command("analyze <path>").description("Analyze schemas in your project").option("--json", "Output as JSON").option("-v, --verbose", "Show detailed analysis").option("--detailed", "Show complexity analysis (Individual+)").option("--readiness <migration>", "Check migration readiness, e.g. yup->zod (Individual+)").option("--complexity", "Show per-schema complexity scores (Individual+)").option("--behavioral <migration>", "Show behavioral difference warnings, e.g. yup->zod").option("--bundle <migration>", "Show bundle size estimation, e.g. zod->valibot (Individual+)").option(
37078
+ "--performance <migration>",
37079
+ "Show performance impact analysis, e.g. zod-v3->v4 (Individual+)"
37080
+ ).option("--dedup", "Detect duplicate type definitions (Individual+)").action(async (targetPath, options) => {
36981
37081
  const analyzer = new SchemaAnalyzer();
36982
37082
  let files;
36983
37083
  if (existsSync4(targetPath) && statSync(targetPath).isFile()) {
@@ -37158,13 +37258,147 @@ Migration Readiness: ${from} -> ${to}
37158
37258
  }
37159
37259
  }
37160
37260
  }
37261
+ if (options.behavioral) {
37262
+ const migParts = options.behavioral.split("->");
37263
+ if (migParts.length !== 2) {
37264
+ console.error(pc4.red("Invalid format. Use: --behavioral yup->zod"));
37265
+ } else {
37266
+ const [bFrom, bTo] = migParts;
37267
+ const behavioralAnalyzer = new BehavioralWarningAnalyzer();
37268
+ const sourceFiles = analyzer.getProject().getSourceFiles();
37269
+ const behavioralResult = behavioralAnalyzer.analyze(
37270
+ sourceFiles,
37271
+ bFrom,
37272
+ bTo
37273
+ );
37274
+ if (behavioralResult.warnings.length > 0) {
37275
+ console.log(pc4.bold("\nBehavioral Difference Warnings\n"));
37276
+ const byCategory = /* @__PURE__ */ new Map();
37277
+ for (const w of behavioralResult.warnings) {
37278
+ const existing = byCategory.get(w.category) ?? [];
37279
+ existing.push(w);
37280
+ byCategory.set(w.category, existing);
37281
+ }
37282
+ for (const [category, catWarnings] of byCategory) {
37283
+ console.log(pc4.yellow(` [${category}] ${catWarnings.length} warning(s)`));
37284
+ for (const w of catWarnings.slice(0, 5)) {
37285
+ console.log(` ${w.message}`);
37286
+ console.log(` ${pc4.dim(w.detail)}`);
37287
+ }
37288
+ if (catWarnings.length > 5) {
37289
+ console.log(pc4.dim(` ... and ${catWarnings.length - 5} more`));
37290
+ }
37291
+ }
37292
+ } else {
37293
+ console.log(pc4.green("\nNo behavioral difference warnings found."));
37294
+ }
37295
+ }
37296
+ }
37297
+ if (options.bundle) {
37298
+ const validation = await licenseManager.validate();
37299
+ const tier = validation.license?.features || TIER_FEATURES[LicenseTier.FREE];
37300
+ if (!tier.bundleEstimator) {
37301
+ console.error(pc4.red("\nBundle estimation requires Individual tier or higher."));
37302
+ console.log(`Upgrade at: ${pc4.cyan(POLAR_URL)}`);
37303
+ } else {
37304
+ const migParts = options.bundle.split("->");
37305
+ if (migParts.length !== 2) {
37306
+ console.error(pc4.red("Invalid format. Use: --bundle zod->valibot"));
37307
+ } else {
37308
+ const [bFrom, bTo] = migParts;
37309
+ const bundleEstimator = new BundleEstimator();
37310
+ const sourceFiles = analyzer.getProject().getSourceFiles();
37311
+ const estimate = bundleEstimator.estimate(
37312
+ sourceFiles,
37313
+ bFrom,
37314
+ bTo
37315
+ );
37316
+ console.log(pc4.bold("\nBundle Size Estimation\n"));
37317
+ console.log(
37318
+ ` ${estimate.from.library}: ~${pc4.cyan(`${estimate.from.minifiedGzipKb}kB`)}`
37319
+ );
37320
+ console.log(` ${estimate.to.library}: ~${pc4.cyan(`${estimate.to.minifiedGzipKb}kB`)}`);
37321
+ console.log(
37322
+ ` Delta: ${pc4.yellow(`${estimate.estimatedDelta > 0 ? "+" : ""}${estimate.estimatedDelta.toFixed(1)}kB (${estimate.deltaPercent.toFixed(0)}%)`)}`
37323
+ );
37324
+ console.log(`
37325
+ ${pc4.dim(estimate.summary)}`);
37326
+ }
37327
+ }
37328
+ }
37329
+ if (options.performance) {
37330
+ const validation = await licenseManager.validate();
37331
+ const tier = validation.license?.features || TIER_FEATURES[LicenseTier.FREE];
37332
+ if (!tier.performanceAnalyzer) {
37333
+ console.error(pc4.red("\nPerformance analysis requires Individual tier or higher."));
37334
+ console.log(`Upgrade at: ${pc4.cyan(POLAR_URL)}`);
37335
+ } else {
37336
+ const migParts = options.performance.split("->");
37337
+ if (migParts.length !== 2) {
37338
+ console.error(pc4.red("Invalid format. Use: --performance zod-v3->v4"));
37339
+ } else {
37340
+ const [pFrom, pTo] = migParts;
37341
+ const perfAnalyzer = new PerformanceAnalyzer();
37342
+ const sourceFiles = analyzer.getProject().getSourceFiles();
37343
+ const perfResult = perfAnalyzer.analyze(
37344
+ sourceFiles,
37345
+ pFrom,
37346
+ pTo
37347
+ );
37348
+ if (perfResult.warnings.length > 0) {
37349
+ console.log(pc4.bold("\nPerformance Impact Analysis\n"));
37350
+ for (const w of perfResult.warnings) {
37351
+ const color = w.severity === "error" ? pc4.red : w.severity === "warning" ? pc4.yellow : pc4.dim;
37352
+ console.log(` ${color(`[${w.severity}]`)} ${w.message}`);
37353
+ console.log(` ${pc4.dim(w.detail)}`);
37354
+ }
37355
+ console.log(`
37356
+ ${pc4.dim(perfResult.recommendation)}`);
37357
+ } else {
37358
+ console.log(pc4.green("\nNo performance concerns detected."));
37359
+ }
37360
+ }
37361
+ }
37362
+ }
37363
+ if (options.dedup) {
37364
+ const validation = await licenseManager.validate();
37365
+ const tier = validation.license?.features || TIER_FEATURES[LicenseTier.FREE];
37366
+ if (!tier.typeDeduplication) {
37367
+ console.error(pc4.red("\nType deduplication detection requires Individual tier or higher."));
37368
+ console.log(`Upgrade at: ${pc4.cyan(POLAR_URL)}`);
37369
+ } else {
37370
+ const dedupDetector = new TypeDedupDetector();
37371
+ const sourceFiles = analyzer.getProject().getSourceFiles();
37372
+ const dedupResult = dedupDetector.detect(sourceFiles);
37373
+ if (dedupResult.candidates.length > 0) {
37374
+ console.log(pc4.bold("\nDuplicate Type Candidates\n"));
37375
+ for (const c of dedupResult.candidates.slice(0, 10)) {
37376
+ console.log(` ${pc4.cyan(c.typeName)} <-> ${pc4.cyan(c.schemaName)}`);
37377
+ console.log(` Type: ${pc4.dim(c.typeFilePath)}:${c.typeLineNumber}`);
37378
+ console.log(` Schema: ${pc4.dim(c.schemaFilePath)}:${c.schemaLineNumber}`);
37379
+ console.log(` Confidence: ${pc4.dim(c.confidence)} | ${pc4.dim(c.suggestion)}`);
37380
+ }
37381
+ if (dedupResult.candidates.length > 10) {
37382
+ console.log(pc4.dim(` ... and ${dedupResult.candidates.length - 10} more`));
37383
+ }
37384
+ } else {
37385
+ console.log(pc4.green("\nNo duplicate type candidates found."));
37386
+ }
37387
+ }
37388
+ }
37161
37389
  });
37162
- program.command("migrate <path>").description("Migrate schemas from one library to another").requiredOption("-f, --from <library>", "Source library (yup, joi, io-ts, zod-v3, zod)").requiredOption("-t, --to <library>", "Target library (zod, v4, valibot)").option("-d, --dry-run", "Preview changes without writing files").option("-v, --verbose", "Show detailed transformation info").option("-c, --config <path>", "Path to config file").option("--report <format>", "Generate report (json, html, csv)").option("--report-output <path>", "Report output path").option("--git-branch", "Create git branch for changes").option("--git-commit", "Auto-commit changes").option("--no-backup", "Skip backup creation").option("--yes", "Skip confirmation prompt").option("--ci", "CI mode (non-interactive, exit code on failure)").option("--cross-file", "Resolve cross-file schema dependencies (Pro+)").option("--chain <path>", "Chain migrations, e.g. yup->zod->valibot (Pro+)").option("--compat-check", "Run compatibility check before migration (Pro+)").option("--fail-on-warnings", "Exit 1 if any warnings (Team+)").option(
37390
+ program.command("migrate <path>").description("Migrate schemas from one library to another").option("-f, --from <library>", "Source library (yup, joi, io-ts, zod-v3, zod)").option("-t, --to <library>", "Target library (zod, v4, valibot, yup, arktype, superstruct)").option("-d, --dry-run", "Preview changes without writing files").option("-v, --verbose", "Show detailed transformation info").option("-c, --config <path>", "Path to config file").option("--report <format>", "Generate report (json, html, csv)").option("--report-output <path>", "Report output path").option("--git-branch", "Create git branch for changes").option("--git-commit", "Auto-commit changes").option("--no-backup", "Skip backup creation").option("--yes", "Skip confirmation prompt").option("--ci", "CI mode (non-interactive, exit code on failure)").option("--cross-file", "Resolve cross-file schema dependencies (Pro+)").option("--chain <path>", "Chain migrations, e.g. yup->zod->valibot (Pro+)").option("--compat-check", "Run compatibility check before migration (Pro+)").option("--fail-on-warnings", "Exit 1 if any warnings (Team+)").option(
37163
37391
  "--max-risk-score <score>",
37164
37392
  "Exit 1 if any file exceeds risk score (Team+)",
37165
37393
  Number.parseInt
37166
- ).action(async (targetPath, options) => {
37394
+ ).option("--incremental", "Enable incremental migration (file-by-file with progress tracking)").option("--resume", "Resume a previously started incremental migration").option("--incremental-status", "Show incremental migration progress").option("--scaffold-tests", "Generate validation tests after migration (Pro+)").option("--audit", "Enable migration audit logging (Team+)").action(async (targetPath, options) => {
37167
37395
  const startTime = Date.now();
37396
+ if (!options.chain && (!options.from || !options.to)) {
37397
+ console.error(pc4.red("Either --from and --to, or --chain must be specified."));
37398
+ console.error(pc4.dim(" Single-step: schemashift migrate <path> -f yup -t zod"));
37399
+ console.error(pc4.dim(" Chain: schemashift migrate <path> --chain yup->zod->valibot"));
37400
+ process.exit(1);
37401
+ }
37168
37402
  if (options.maxRiskScore !== void 0 && Number.isNaN(options.maxRiskScore)) {
37169
37403
  console.error(pc4.red("--max-risk-score must be a valid number."));
37170
37404
  process.exit(1);
@@ -37288,10 +37522,14 @@ Compatibility score: ${pc4.cyan(compatResult.overallScore.toString())}%`);
37288
37522
  if (options.chain) {
37289
37523
  const migrationChain = new MigrationChain();
37290
37524
  chainSteps = migrationChain.parseChain(options.chain);
37291
- const validation2 = migrationChain.validateChain(chainSteps, engine);
37292
- if (!validation2.valid) {
37525
+ if (chainSteps.length > 0) {
37526
+ if (!options.from) options.from = chainSteps[0]?.from;
37527
+ if (!options.to) options.to = chainSteps[chainSteps.length - 1]?.to;
37528
+ }
37529
+ const chainValidation = migrationChain.validateChain(chainSteps, engine);
37530
+ if (!chainValidation.valid) {
37293
37531
  console.error(pc4.red("Chain migration validation failed:"));
37294
- for (const err of validation2.errors) {
37532
+ for (const err of chainValidation.errors) {
37295
37533
  console.error(` ${pc4.red(err)}`);
37296
37534
  }
37297
37535
  process.exit(1);
@@ -37318,6 +37556,41 @@ Compatibility score: ${pc4.cyan(compatResult.overallScore.toString())}%`);
37318
37556
  console.log(pc4.yellow("No files found matching patterns."));
37319
37557
  process.exit(0);
37320
37558
  }
37559
+ const incrementalTracker = new IncrementalTracker(resolve2(targetPath));
37560
+ if (options.incrementalStatus) {
37561
+ const progress = incrementalTracker.getProgress();
37562
+ if (!progress) {
37563
+ console.log(pc4.yellow("No incremental migration in progress."));
37564
+ process.exit(0);
37565
+ }
37566
+ console.log(pc4.bold("\nIncremental Migration Status\n"));
37567
+ console.log(`Completed: ${pc4.green(progress.completed.toString())}`);
37568
+ console.log(`Remaining: ${pc4.cyan(progress.remaining.toString())}`);
37569
+ console.log(`Failed: ${pc4.red(progress.failed.toString())}`);
37570
+ console.log(`Total: ${progress.total}`);
37571
+ console.log(`Progress: ${pc4.cyan(`${progress.percent}%`)}`);
37572
+ process.exit(0);
37573
+ }
37574
+ if (options.resume) {
37575
+ const state = incrementalTracker.resume();
37576
+ if (!state) {
37577
+ console.error(pc4.red("No incremental migration to resume."));
37578
+ process.exit(1);
37579
+ }
37580
+ files = state.remainingFiles;
37581
+ console.log(pc4.dim(`Resuming incremental migration: ${state.migrationId}`));
37582
+ const progress = incrementalTracker.getProgress();
37583
+ if (progress) {
37584
+ console.log(
37585
+ pc4.dim(
37586
+ `Progress: ${progress.completed}/${progress.total} completed (${progress.percent}%)`
37587
+ )
37588
+ );
37589
+ }
37590
+ } else if (options.incremental) {
37591
+ incrementalTracker.start(files, options.from, options.to);
37592
+ console.log(pc4.dim("Started incremental migration."));
37593
+ }
37321
37594
  if (files.length > features.maxFiles) {
37322
37595
  console.error(
37323
37596
  pc4.red(`File limit exceeded. Found ${files.length}, max ${features.maxFiles}.`)
@@ -37452,6 +37725,30 @@ Migrating ${displayPath}
37452
37725
  }
37453
37726
  }
37454
37727
  }
37728
+ if (options.incremental || options.resume) {
37729
+ for (const result of results) {
37730
+ if (result.success) {
37731
+ incrementalTracker.markComplete(result.filePath);
37732
+ } else {
37733
+ incrementalTracker.markFailed(result.filePath);
37734
+ }
37735
+ }
37736
+ const progress = incrementalTracker.getProgress();
37737
+ if (progress) {
37738
+ console.log(
37739
+ pc4.bold(`
37740
+ Incremental: ${progress.completed}/${progress.total} (${progress.percent}%)`)
37741
+ );
37742
+ if (progress.remaining > 0) {
37743
+ console.log(
37744
+ pc4.dim(`Run with --resume to continue. ${progress.remaining} files remaining.`)
37745
+ );
37746
+ }
37747
+ if (progress.failed > 0) {
37748
+ console.log(pc4.yellow(`${progress.failed} file(s) failed. Run with --resume to retry.`));
37749
+ }
37750
+ }
37751
+ }
37455
37752
  if (options.gitCommit && git.isAvailable() && !options.dryRun) {
37456
37753
  const successFiles = results.filter((r) => r.success).map((r) => r.filePath);
37457
37754
  if (successFiles.length > 0) {
@@ -37464,9 +37761,11 @@ Migrating ${displayPath}
37464
37761
  if (options.report === "html" && !features.htmlReports) {
37465
37762
  console.error(pc4.red("HTML reports require Individual tier or higher."));
37466
37763
  console.log(`Upgrade at: ${pc4.cyan(POLAR_URL)}`);
37764
+ process.exit(1);
37467
37765
  } else if (options.report === "csv" && !features.csvExport) {
37468
37766
  console.error(pc4.red("CSV export requires Individual tier or higher."));
37469
37767
  console.log(`Upgrade at: ${pc4.cyan(POLAR_URL)}`);
37768
+ process.exit(1);
37470
37769
  } else {
37471
37770
  const reporter = new ReportGenerator();
37472
37771
  const includeRisk = features.riskScoring;
@@ -37489,6 +37788,58 @@ Migrating ${displayPath}
37489
37788
  console.log(pc4.green(`Report saved: ${outputPath}`));
37490
37789
  }
37491
37790
  }
37791
+ if (options.scaffoldTests) {
37792
+ if (!features.testScaffolding) {
37793
+ console.error(pc4.red("\nTest scaffolding requires Pro tier or higher."));
37794
+ console.log(`Upgrade at: ${pc4.cyan(POLAR_URL)}`);
37795
+ } else {
37796
+ const scaffolder = new TestScaffolder();
37797
+ const successfulFiles = results.filter((r) => r.success).map((r) => r.filePath);
37798
+ if (successfulFiles.length > 0) {
37799
+ const scaffoldAnalyzer = new SchemaAnalyzer();
37800
+ for (const f of successfulFiles) {
37801
+ scaffoldAnalyzer.addSourceFiles([f]);
37802
+ }
37803
+ const sourceFiles = scaffoldAnalyzer.getProject().getSourceFiles();
37804
+ const scaffoldResult = scaffolder.scaffold(sourceFiles, options.from, options.to);
37805
+ console.log(pc4.bold("\nTest Scaffolding\n"));
37806
+ console.log(
37807
+ ` Generated ${pc4.cyan(scaffoldResult.tests.length.toString())} test file(s) for ${scaffoldResult.totalSchemas} schema(s)`
37808
+ );
37809
+ for (const test of scaffoldResult.tests) {
37810
+ console.log(` ${pc4.dim(test.filePath)} (${test.schemaCount} schemas)`);
37811
+ }
37812
+ }
37813
+ }
37814
+ }
37815
+ if (options.audit) {
37816
+ if (!features.auditLogging) {
37817
+ console.error(pc4.red("\nAudit logging requires Team tier."));
37818
+ console.log(`Upgrade at: ${pc4.cyan(POLAR_URL)}`);
37819
+ } else {
37820
+ const projectPath = resolve2(targetPath);
37821
+ const auditLog = new MigrationAuditLog(projectPath);
37822
+ const migrationId = `${options.from}->${options.to}-${Date.now()}`;
37823
+ for (const result of results) {
37824
+ const entry = auditLog.createEntry({
37825
+ migrationId,
37826
+ filePath: result.filePath,
37827
+ from: options.from,
37828
+ to: options.to,
37829
+ originalCode: result.originalCode ?? "",
37830
+ transformedCode: result.transformedCode,
37831
+ success: result.success,
37832
+ warningCount: result.warnings.length,
37833
+ errorCount: result.errors.length
37834
+ });
37835
+ auditLog.append(entry);
37836
+ }
37837
+ console.log(
37838
+ pc4.dim(`
37839
+ Audit log saved to .schemashift/audit-log.json (${results.length} entries)`)
37840
+ );
37841
+ }
37842
+ }
37492
37843
  if (options.dryRun) {
37493
37844
  const diffOutput = generateDiffPreview(results);
37494
37845
  if (diffOutput) {
@@ -37571,15 +37922,15 @@ program.command("watch <path>").description("Watch files and migrate on change")
37571
37922
  };
37572
37923
  }
37573
37924
  const watchMode = new WatchMode();
37574
- const analyzer = new SchemaAnalyzer();
37575
37925
  await watchMode.start({
37576
37926
  patterns: config2.include.map((p) => join3(targetPath, p)),
37577
37927
  exclude: config2.exclude,
37578
37928
  from: options.from,
37579
37929
  to: options.to,
37580
37930
  onTransform: async (file) => {
37581
- analyzer.addSourceFiles([file]);
37582
- const sourceFile = analyzer.getProject().getSourceFileOrThrow(resolve2(file));
37931
+ const fileAnalyzer = new SchemaAnalyzer();
37932
+ fileAnalyzer.addSourceFiles([file]);
37933
+ const sourceFile = fileAnalyzer.getProject().getSourceFileOrThrow(resolve2(file));
37583
37934
  const result = engine.transform(sourceFile, options.from, options.to, {
37584
37935
  from: options.from,
37585
37936
  to: options.to,
package/dist/index.cjs CHANGED
@@ -33791,7 +33791,13 @@ var TIER_FEATURES = {
33791
33791
  maxRiskScoreThreshold: false,
33792
33792
  formResolverMigration: false,
33793
33793
  complexityEstimator: false,
33794
- monorepoAware: false
33794
+ monorepoAware: false,
33795
+ behavioralWarnings: true,
33796
+ bundleEstimator: false,
33797
+ performanceAnalyzer: false,
33798
+ typeDeduplication: false,
33799
+ testScaffolding: false,
33800
+ auditLogging: false
33795
33801
  },
33796
33802
  [
33797
33803
  "individual"
@@ -33818,7 +33824,13 @@ var TIER_FEATURES = {
33818
33824
  maxRiskScoreThreshold: false,
33819
33825
  formResolverMigration: true,
33820
33826
  complexityEstimator: true,
33821
- monorepoAware: false
33827
+ monorepoAware: false,
33828
+ behavioralWarnings: true,
33829
+ bundleEstimator: true,
33830
+ performanceAnalyzer: true,
33831
+ typeDeduplication: true,
33832
+ testScaffolding: false,
33833
+ auditLogging: false
33822
33834
  },
33823
33835
  [
33824
33836
  "pro"
@@ -33831,7 +33843,14 @@ var TIER_FEATURES = {
33831
33843
  "zod-v3->v4",
33832
33844
  "io-ts->zod",
33833
33845
  "zod->valibot",
33834
- "any->valibot"
33846
+ "any->valibot",
33847
+ "zod->yup",
33848
+ "valibot->zod",
33849
+ "zod->arktype",
33850
+ "arktype->zod",
33851
+ "zod->superstruct",
33852
+ "superstruct->zod",
33853
+ "io-ts->effect"
33835
33854
  ],
33836
33855
  devices: 4,
33837
33856
  ciSupport: true,
@@ -33852,7 +33871,13 @@ var TIER_FEATURES = {
33852
33871
  maxRiskScoreThreshold: false,
33853
33872
  formResolverMigration: true,
33854
33873
  complexityEstimator: true,
33855
- monorepoAware: true
33874
+ monorepoAware: true,
33875
+ behavioralWarnings: true,
33876
+ bundleEstimator: true,
33877
+ performanceAnalyzer: true,
33878
+ typeDeduplication: true,
33879
+ testScaffolding: true,
33880
+ auditLogging: false
33856
33881
  },
33857
33882
  [
33858
33883
  "team"
@@ -33865,7 +33890,14 @@ var TIER_FEATURES = {
33865
33890
  "zod-v3->v4",
33866
33891
  "io-ts->zod",
33867
33892
  "any->valibot",
33868
- "zod->valibot"
33893
+ "zod->valibot",
33894
+ "zod->yup",
33895
+ "valibot->zod",
33896
+ "zod->arktype",
33897
+ "arktype->zod",
33898
+ "zod->superstruct",
33899
+ "superstruct->zod",
33900
+ "io-ts->effect"
33869
33901
  ],
33870
33902
  devices: Infinity,
33871
33903
  ciSupport: true,
@@ -33886,7 +33918,13 @@ var TIER_FEATURES = {
33886
33918
  maxRiskScoreThreshold: true,
33887
33919
  formResolverMigration: true,
33888
33920
  complexityEstimator: true,
33889
- monorepoAware: true
33921
+ monorepoAware: true,
33922
+ behavioralWarnings: true,
33923
+ bundleEstimator: true,
33924
+ performanceAnalyzer: true,
33925
+ typeDeduplication: true,
33926
+ testScaffolding: true,
33927
+ auditLogging: true
33890
33928
  }
33891
33929
  };
33892
33930
  var POLAR_ORG_ID = process.env.POLAR_ORG_ID || "79bbe935-1836-4b9e-9ca8-4c7a94217f5e";
@@ -34641,6 +34679,12 @@ var WatchMode = class {
34641
34679
  console.log(import_picocolors.default.cyan(`
34642
34680
  Watching ${files.length} files for changes...
34643
34681
  `));
34682
+ if (options.dependents && options.dependents.size > 0) {
34683
+ console.log(
34684
+ import_picocolors.default.dim(`Dependency-aware mode: ${options.dependents.size} files with dependents
34685
+ `)
34686
+ );
34687
+ }
34644
34688
  console.log(import_picocolors.default.dim("Press Ctrl+C to stop\n"));
34645
34689
  const directories = new Set(files.map((f) => f.split("/").slice(0, -1).join("/")));
34646
34690
  for (const dir of directories) {
@@ -34661,8 +34705,26 @@ Watching ${files.length} files for changes...
34661
34705
  Changed: ${(0, import_node_path2.relative)(process.cwd(), fullPath)}`));
34662
34706
  try {
34663
34707
  await options.onTransform(fullPath);
34664
- console.log(import_picocolors.default.green(`Transformed successfully
34665
- `));
34708
+ console.log(import_picocolors.default.green(`Transformed successfully`));
34709
+ const dependentFiles = options.dependents?.get(fullPath);
34710
+ if (dependentFiles && dependentFiles.length > 0) {
34711
+ console.log(
34712
+ import_picocolors.default.cyan(` Re-transforming ${dependentFiles.length} dependent file(s)...`)
34713
+ );
34714
+ for (const depFile of dependentFiles) {
34715
+ try {
34716
+ await options.onTransform(depFile);
34717
+ console.log(import_picocolors.default.green(` \u2713 ${(0, import_node_path2.relative)(process.cwd(), depFile)}`));
34718
+ } catch (error) {
34719
+ console.error(
34720
+ import_picocolors.default.red(
34721
+ ` \u2717 ${(0, import_node_path2.relative)(process.cwd(), depFile)}: ${error instanceof Error ? error.message : String(error)}`
34722
+ )
34723
+ );
34724
+ }
34725
+ }
34726
+ }
34727
+ console.log("");
34666
34728
  } catch (error) {
34667
34729
  console.error(
34668
34730
  import_picocolors.default.red(
@@ -34688,6 +34750,21 @@ Changed: ${(0, import_node_path2.relative)(process.cwd(), fullPath)}`));
34688
34750
  }
34689
34751
  this.debounceTimers.clear();
34690
34752
  }
34753
+ /**
34754
+ * Build a reverse dependency map (file -> files that depend on it).
34755
+ * Takes the forward dependency map from SchemaDependencyResolver and inverts it.
34756
+ */
34757
+ static buildDependentsMap(dependencies) {
34758
+ const dependents = /* @__PURE__ */ new Map();
34759
+ for (const [file, deps] of dependencies) {
34760
+ for (const dep of deps) {
34761
+ const existing = dependents.get(dep) ?? [];
34762
+ existing.push(file);
34763
+ dependents.set(dep, existing);
34764
+ }
34765
+ }
34766
+ return dependents;
34767
+ }
34691
34768
  matchesPatterns(file, include, exclude) {
34692
34769
  const isIncluded = include.some((p) => (0, import_minimatch.minimatch)(file, p));
34693
34770
  const isExcluded = exclude.some((p) => (0, import_minimatch.minimatch)(file, p));
package/dist/index.d.cts CHANGED
@@ -91,12 +91,19 @@ interface WatchOptions {
91
91
  from: string;
92
92
  to: string;
93
93
  onTransform: (file: string) => Promise<void>;
94
+ /** Optional: dependency map from SchemaDependencyResolver. Keys are file paths, values are lists of files that depend on the key. */
95
+ dependents?: Map<string, string[]>;
94
96
  }
95
97
  declare class WatchMode {
96
98
  private watchers;
97
99
  private debounceTimers;
98
100
  start(options: WatchOptions): Promise<void>;
99
101
  stop(): void;
102
+ /**
103
+ * Build a reverse dependency map (file -> files that depend on it).
104
+ * Takes the forward dependency map from SchemaDependencyResolver and inverts it.
105
+ */
106
+ static buildDependentsMap(dependencies: Map<string, string[]>): Map<string, string[]>;
100
107
  private matchesPatterns;
101
108
  }
102
109
 
package/dist/index.d.ts CHANGED
@@ -91,12 +91,19 @@ interface WatchOptions {
91
91
  from: string;
92
92
  to: string;
93
93
  onTransform: (file: string) => Promise<void>;
94
+ /** Optional: dependency map from SchemaDependencyResolver. Keys are file paths, values are lists of files that depend on the key. */
95
+ dependents?: Map<string, string[]>;
94
96
  }
95
97
  declare class WatchMode {
96
98
  private watchers;
97
99
  private debounceTimers;
98
100
  start(options: WatchOptions): Promise<void>;
99
101
  stop(): void;
102
+ /**
103
+ * Build a reverse dependency map (file -> files that depend on it).
104
+ * Takes the forward dependency map from SchemaDependencyResolver and inverts it.
105
+ */
106
+ static buildDependentsMap(dependencies: Map<string, string[]>): Map<string, string[]>;
100
107
  private matchesPatterns;
101
108
  }
102
109
 
package/dist/index.js CHANGED
@@ -33750,7 +33750,13 @@ var TIER_FEATURES = {
33750
33750
  maxRiskScoreThreshold: false,
33751
33751
  formResolverMigration: false,
33752
33752
  complexityEstimator: false,
33753
- monorepoAware: false
33753
+ monorepoAware: false,
33754
+ behavioralWarnings: true,
33755
+ bundleEstimator: false,
33756
+ performanceAnalyzer: false,
33757
+ typeDeduplication: false,
33758
+ testScaffolding: false,
33759
+ auditLogging: false
33754
33760
  },
33755
33761
  [
33756
33762
  "individual"
@@ -33777,7 +33783,13 @@ var TIER_FEATURES = {
33777
33783
  maxRiskScoreThreshold: false,
33778
33784
  formResolverMigration: true,
33779
33785
  complexityEstimator: true,
33780
- monorepoAware: false
33786
+ monorepoAware: false,
33787
+ behavioralWarnings: true,
33788
+ bundleEstimator: true,
33789
+ performanceAnalyzer: true,
33790
+ typeDeduplication: true,
33791
+ testScaffolding: false,
33792
+ auditLogging: false
33781
33793
  },
33782
33794
  [
33783
33795
  "pro"
@@ -33790,7 +33802,14 @@ var TIER_FEATURES = {
33790
33802
  "zod-v3->v4",
33791
33803
  "io-ts->zod",
33792
33804
  "zod->valibot",
33793
- "any->valibot"
33805
+ "any->valibot",
33806
+ "zod->yup",
33807
+ "valibot->zod",
33808
+ "zod->arktype",
33809
+ "arktype->zod",
33810
+ "zod->superstruct",
33811
+ "superstruct->zod",
33812
+ "io-ts->effect"
33794
33813
  ],
33795
33814
  devices: 4,
33796
33815
  ciSupport: true,
@@ -33811,7 +33830,13 @@ var TIER_FEATURES = {
33811
33830
  maxRiskScoreThreshold: false,
33812
33831
  formResolverMigration: true,
33813
33832
  complexityEstimator: true,
33814
- monorepoAware: true
33833
+ monorepoAware: true,
33834
+ behavioralWarnings: true,
33835
+ bundleEstimator: true,
33836
+ performanceAnalyzer: true,
33837
+ typeDeduplication: true,
33838
+ testScaffolding: true,
33839
+ auditLogging: false
33815
33840
  },
33816
33841
  [
33817
33842
  "team"
@@ -33824,7 +33849,14 @@ var TIER_FEATURES = {
33824
33849
  "zod-v3->v4",
33825
33850
  "io-ts->zod",
33826
33851
  "any->valibot",
33827
- "zod->valibot"
33852
+ "zod->valibot",
33853
+ "zod->yup",
33854
+ "valibot->zod",
33855
+ "zod->arktype",
33856
+ "arktype->zod",
33857
+ "zod->superstruct",
33858
+ "superstruct->zod",
33859
+ "io-ts->effect"
33828
33860
  ],
33829
33861
  devices: Infinity,
33830
33862
  ciSupport: true,
@@ -33845,7 +33877,13 @@ var TIER_FEATURES = {
33845
33877
  maxRiskScoreThreshold: true,
33846
33878
  formResolverMigration: true,
33847
33879
  complexityEstimator: true,
33848
- monorepoAware: true
33880
+ monorepoAware: true,
33881
+ behavioralWarnings: true,
33882
+ bundleEstimator: true,
33883
+ performanceAnalyzer: true,
33884
+ typeDeduplication: true,
33885
+ testScaffolding: true,
33886
+ auditLogging: true
33849
33887
  }
33850
33888
  };
33851
33889
  var POLAR_ORG_ID = process.env.POLAR_ORG_ID || "79bbe935-1836-4b9e-9ca8-4c7a94217f5e";
@@ -34608,6 +34646,12 @@ var WatchMode = class {
34608
34646
  console.log(pc.cyan(`
34609
34647
  Watching ${files.length} files for changes...
34610
34648
  `));
34649
+ if (options.dependents && options.dependents.size > 0) {
34650
+ console.log(
34651
+ pc.dim(`Dependency-aware mode: ${options.dependents.size} files with dependents
34652
+ `)
34653
+ );
34654
+ }
34611
34655
  console.log(pc.dim("Press Ctrl+C to stop\n"));
34612
34656
  const directories = new Set(files.map((f) => f.split("/").slice(0, -1).join("/")));
34613
34657
  for (const dir of directories) {
@@ -34628,8 +34672,26 @@ Watching ${files.length} files for changes...
34628
34672
  Changed: ${relative2(process.cwd(), fullPath)}`));
34629
34673
  try {
34630
34674
  await options.onTransform(fullPath);
34631
- console.log(pc.green(`Transformed successfully
34632
- `));
34675
+ console.log(pc.green(`Transformed successfully`));
34676
+ const dependentFiles = options.dependents?.get(fullPath);
34677
+ if (dependentFiles && dependentFiles.length > 0) {
34678
+ console.log(
34679
+ pc.cyan(` Re-transforming ${dependentFiles.length} dependent file(s)...`)
34680
+ );
34681
+ for (const depFile of dependentFiles) {
34682
+ try {
34683
+ await options.onTransform(depFile);
34684
+ console.log(pc.green(` \u2713 ${relative2(process.cwd(), depFile)}`));
34685
+ } catch (error) {
34686
+ console.error(
34687
+ pc.red(
34688
+ ` \u2717 ${relative2(process.cwd(), depFile)}: ${error instanceof Error ? error.message : String(error)}`
34689
+ )
34690
+ );
34691
+ }
34692
+ }
34693
+ }
34694
+ console.log("");
34633
34695
  } catch (error) {
34634
34696
  console.error(
34635
34697
  pc.red(
@@ -34655,6 +34717,21 @@ Changed: ${relative2(process.cwd(), fullPath)}`));
34655
34717
  }
34656
34718
  this.debounceTimers.clear();
34657
34719
  }
34720
+ /**
34721
+ * Build a reverse dependency map (file -> files that depend on it).
34722
+ * Takes the forward dependency map from SchemaDependencyResolver and inverts it.
34723
+ */
34724
+ static buildDependentsMap(dependencies) {
34725
+ const dependents = /* @__PURE__ */ new Map();
34726
+ for (const [file, deps] of dependencies) {
34727
+ for (const dep of deps) {
34728
+ const existing = dependents.get(dep) ?? [];
34729
+ existing.push(file);
34730
+ dependents.set(dep, existing);
34731
+ }
34732
+ }
34733
+ return dependents;
34734
+ }
34658
34735
  matchesPatterns(file, include, exclude) {
34659
34736
  const isIncluded = include.some((p) => minimatch(file, p));
34660
34737
  const isExcluded = exclude.some((p) => minimatch(file, p));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "schemashift-cli",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "TypeScript schema migration CLI - migrate between Zod, Yup, Joi, and more",
5
5
  "type": "module",
6
6
  "bin": {
@@ -48,13 +48,19 @@
48
48
  },
49
49
  "author": "Joseph May",
50
50
  "license": "MIT",
51
+ "engines": {
52
+ "node": ">=22.0.0"
53
+ },
51
54
  "dependencies": {
52
- "@schemashift/core": "0.8.0",
53
- "@schemashift/io-ts-zod": "0.8.0",
54
- "@schemashift/joi-zod": "0.8.0",
55
- "@schemashift/yup-zod": "0.8.0",
56
- "@schemashift/zod-valibot": "0.8.0",
57
- "@schemashift/zod-v3-v4": "0.8.0",
55
+ "@schemashift/core": "0.10.0",
56
+ "@schemashift/io-ts-effect": "0.10.0",
57
+ "@schemashift/io-ts-zod": "0.10.0",
58
+ "@schemashift/joi-zod": "0.10.0",
59
+ "@schemashift/yup-zod": "0.10.0",
60
+ "@schemashift/zod-arktype": "0.10.0",
61
+ "@schemashift/zod-superstruct": "0.10.0",
62
+ "@schemashift/zod-valibot": "0.10.0",
63
+ "@schemashift/zod-v3-v4": "0.10.0",
58
64
  "commander": "14.0.2",
59
65
  "cosmiconfig": "9.0.0",
60
66
  "glob": "13.0.0",
@@ -63,7 +69,7 @@
63
69
  "picocolors": "1.1.1"
64
70
  },
65
71
  "devDependencies": {
66
- "@schemashift/license": "0.5.0"
72
+ "@schemashift/license": "0.10.0"
67
73
  },
68
74
  "publishConfig": {
69
75
  "access": "public"