@schemashift/core 0.7.0 → 0.8.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 +353 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -1
- package/dist/index.d.ts +57 -1
- package/dist/index.js +346 -37
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -21,11 +21,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
CompatibilityAnalyzer: () => CompatibilityAnalyzer,
|
|
24
|
+
ComplexityEstimator: () => ComplexityEstimator,
|
|
24
25
|
DetailedAnalyzer: () => DetailedAnalyzer,
|
|
25
26
|
EcosystemAnalyzer: () => EcosystemAnalyzer,
|
|
27
|
+
FormResolverMigrator: () => FormResolverMigrator,
|
|
26
28
|
GovernanceEngine: () => GovernanceEngine,
|
|
27
29
|
IncrementalTracker: () => IncrementalTracker,
|
|
28
30
|
MigrationChain: () => MigrationChain,
|
|
31
|
+
MonorepoResolver: () => MonorepoResolver,
|
|
29
32
|
PackageUpdater: () => PackageUpdater,
|
|
30
33
|
PluginLoader: () => PluginLoader,
|
|
31
34
|
SchemaAnalyzer: () => SchemaAnalyzer,
|
|
@@ -393,7 +396,8 @@ var ECOSYSTEM_RULES = [
|
|
|
393
396
|
check: () => ({
|
|
394
397
|
issue: "drizzle-zod may not support Zod v4. Check for a compatible version before upgrading.",
|
|
395
398
|
suggestion: "Upgrade drizzle-zod to the latest version that supports Zod v4, or use --legacy-peer-deps.",
|
|
396
|
-
severity: "warning"
|
|
399
|
+
severity: "warning",
|
|
400
|
+
upgradeCommand: "npm install drizzle-zod@latest"
|
|
397
401
|
})
|
|
398
402
|
},
|
|
399
403
|
{
|
|
@@ -403,7 +407,8 @@ var ECOSYSTEM_RULES = [
|
|
|
403
407
|
check: () => ({
|
|
404
408
|
issue: "zod-prisma generates Zod v3 schemas. Generated files will need regeneration after upgrading to Zod v4.",
|
|
405
409
|
suggestion: "Upgrade zod-prisma to a v4-compatible version and regenerate schemas.",
|
|
406
|
-
severity: "warning"
|
|
410
|
+
severity: "warning",
|
|
411
|
+
upgradeCommand: "npm install zod-prisma@latest"
|
|
407
412
|
})
|
|
408
413
|
},
|
|
409
414
|
{
|
|
@@ -413,7 +418,8 @@ var ECOSYSTEM_RULES = [
|
|
|
413
418
|
check: () => ({
|
|
414
419
|
issue: "zod-prisma-types generates Zod v3 schemas. Generated files will need regeneration.",
|
|
415
420
|
suggestion: "Check for a Zod v4-compatible version of zod-prisma-types.",
|
|
416
|
-
severity: "warning"
|
|
421
|
+
severity: "warning",
|
|
422
|
+
upgradeCommand: "npm install zod-prisma-types@latest"
|
|
417
423
|
})
|
|
418
424
|
},
|
|
419
425
|
// API framework integrations
|
|
@@ -428,7 +434,8 @@ var ECOSYSTEM_RULES = [
|
|
|
428
434
|
return {
|
|
429
435
|
issue: `tRPC v${major} expects Zod v3 types. A v3 ZodType is not assignable to a v4 ZodType.`,
|
|
430
436
|
suggestion: "Upgrade to tRPC v11+ which supports Zod v4 via Standard Schema.",
|
|
431
|
-
severity: "error"
|
|
437
|
+
severity: "error",
|
|
438
|
+
upgradeCommand: "npm install @trpc/server@latest"
|
|
432
439
|
};
|
|
433
440
|
}
|
|
434
441
|
return {
|
|
@@ -445,7 +452,8 @@ var ECOSYSTEM_RULES = [
|
|
|
445
452
|
check: () => ({
|
|
446
453
|
issue: "trpc-ui breaks entirely with Zod v4 schemas.",
|
|
447
454
|
suggestion: "Check for a Zod v4-compatible version of trpc-ui before upgrading.",
|
|
448
|
-
severity: "error"
|
|
455
|
+
severity: "error",
|
|
456
|
+
upgradeCommand: "npm install trpc-ui@latest"
|
|
449
457
|
})
|
|
450
458
|
},
|
|
451
459
|
// Validation utilities
|
|
@@ -460,7 +468,8 @@ var ECOSYSTEM_RULES = [
|
|
|
460
468
|
return {
|
|
461
469
|
issue: `zod-validation-error v${major} is not compatible with Zod v4.`,
|
|
462
470
|
suggestion: "Upgrade zod-validation-error to v5.0.0+ for Zod v4 support.",
|
|
463
|
-
severity: "error"
|
|
471
|
+
severity: "error",
|
|
472
|
+
upgradeCommand: "npm install zod-validation-error@^5.0.0"
|
|
464
473
|
};
|
|
465
474
|
}
|
|
466
475
|
return null;
|
|
@@ -476,13 +485,15 @@ var ECOSYSTEM_RULES = [
|
|
|
476
485
|
return {
|
|
477
486
|
issue: "@hookform/resolvers zodResolver may need updating for Zod v4.",
|
|
478
487
|
suggestion: "Upgrade @hookform/resolvers to the latest version with Zod v4 support.",
|
|
479
|
-
severity: "warning"
|
|
488
|
+
severity: "warning",
|
|
489
|
+
upgradeCommand: "npm install @hookform/resolvers@latest"
|
|
480
490
|
};
|
|
481
491
|
}
|
|
482
492
|
return {
|
|
483
493
|
issue: "@hookform/resolvers will need its resolver import updated for the new schema library.",
|
|
484
494
|
suggestion: "Switch from the old resolver (e.g., yupResolver) to zodResolver from @hookform/resolvers/zod.",
|
|
485
|
-
severity: "warning"
|
|
495
|
+
severity: "warning",
|
|
496
|
+
upgradeCommand: "npm install @hookform/resolvers@latest"
|
|
486
497
|
};
|
|
487
498
|
}
|
|
488
499
|
},
|
|
@@ -514,7 +525,8 @@ var ECOSYSTEM_RULES = [
|
|
|
514
525
|
check: () => ({
|
|
515
526
|
issue: "zod-openapi may not support Zod v4 yet.",
|
|
516
527
|
suggestion: "Check for a Zod v4-compatible version of zod-openapi.",
|
|
517
|
-
severity: "warning"
|
|
528
|
+
severity: "warning",
|
|
529
|
+
upgradeCommand: "npm install zod-openapi@latest"
|
|
518
530
|
})
|
|
519
531
|
},
|
|
520
532
|
{
|
|
@@ -524,7 +536,8 @@ var ECOSYSTEM_RULES = [
|
|
|
524
536
|
check: () => ({
|
|
525
537
|
issue: "@asteasolutions/zod-to-openapi may not support Zod v4 yet.",
|
|
526
538
|
suggestion: "Check for a Zod v4-compatible version of @asteasolutions/zod-to-openapi.",
|
|
527
|
-
severity: "warning"
|
|
539
|
+
severity: "warning",
|
|
540
|
+
upgradeCommand: "npm install @asteasolutions/zod-to-openapi@latest"
|
|
528
541
|
})
|
|
529
542
|
}
|
|
530
543
|
];
|
|
@@ -558,7 +571,8 @@ var EcosystemAnalyzer = class {
|
|
|
558
571
|
issue: result.issue,
|
|
559
572
|
suggestion: result.suggestion,
|
|
560
573
|
severity: result.severity,
|
|
561
|
-
category: rule.category
|
|
574
|
+
category: rule.category,
|
|
575
|
+
...result.upgradeCommand ? { upgradeCommand: result.upgradeCommand } : {}
|
|
562
576
|
};
|
|
563
577
|
dependencies.push(issue);
|
|
564
578
|
if (result.severity === "error") {
|
|
@@ -696,6 +710,120 @@ var CompatibilityAnalyzer = class {
|
|
|
696
710
|
}
|
|
697
711
|
};
|
|
698
712
|
|
|
713
|
+
// src/complexity-estimator.ts
|
|
714
|
+
var SCHEMA_FACTORY_PATTERN = /z\.(object|string|number|boolean|array|enum|union|discriminatedUnion|intersection|lazy|tuple|record|literal|nativeEnum|any|unknown|void|null|undefined|never|date|bigint|symbol|function|promise|map|set|custom|preprocess|pipeline|brand|coerce)\s*\(/g;
|
|
715
|
+
var ADVANCED_PATTERNS = [
|
|
716
|
+
[/z\.discriminatedUnion\s*\(/g, "discriminatedUnion"],
|
|
717
|
+
[/z\.intersection\s*\(/g, "intersection"],
|
|
718
|
+
[/z\.lazy\s*\(/g, "recursive"],
|
|
719
|
+
[/\.brand\s*[<(]/g, "branded"],
|
|
720
|
+
[/\.superRefine\s*\(/g, "superRefine"],
|
|
721
|
+
[/\.transform\s*\(/g, "transform"],
|
|
722
|
+
[/\.pipe\s*\(/g, "pipe"],
|
|
723
|
+
[/\.refine\s*\(/g, "refine"]
|
|
724
|
+
];
|
|
725
|
+
function countMatches(text, pattern) {
|
|
726
|
+
pattern.lastIndex = 0;
|
|
727
|
+
let count = 0;
|
|
728
|
+
while (pattern.exec(text)) count++;
|
|
729
|
+
return count;
|
|
730
|
+
}
|
|
731
|
+
function getMaxChainDepth(text) {
|
|
732
|
+
let maxDepth = 0;
|
|
733
|
+
const lines = text.split("\n");
|
|
734
|
+
for (const line of lines) {
|
|
735
|
+
const dotCalls = line.match(/\.\w+\s*\(/g);
|
|
736
|
+
if (dotCalls && dotCalls.length > maxDepth) {
|
|
737
|
+
maxDepth = dotCalls.length;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
return maxDepth;
|
|
741
|
+
}
|
|
742
|
+
var ComplexityEstimator = class {
|
|
743
|
+
estimate(files) {
|
|
744
|
+
const fileResults = [];
|
|
745
|
+
const warnings = [];
|
|
746
|
+
const riskAreas = [];
|
|
747
|
+
let totalSchemas = 0;
|
|
748
|
+
let advancedPatternCount = 0;
|
|
749
|
+
let hasDeepDiscriminatedUnions = false;
|
|
750
|
+
for (const file of files) {
|
|
751
|
+
const text = file.getFullText();
|
|
752
|
+
const filePath = file.getFilePath();
|
|
753
|
+
const lineCount = file.getEndLineNumber();
|
|
754
|
+
const schemaCount = countMatches(text, new RegExp(SCHEMA_FACTORY_PATTERN.source, "g"));
|
|
755
|
+
totalSchemas += schemaCount;
|
|
756
|
+
const advancedPatterns = [];
|
|
757
|
+
for (const [pattern, name] of ADVANCED_PATTERNS) {
|
|
758
|
+
const count = countMatches(text, new RegExp(pattern.source, "g"));
|
|
759
|
+
if (count > 0) {
|
|
760
|
+
advancedPatterns.push(name);
|
|
761
|
+
advancedPatternCount += count;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
const chainDepth = getMaxChainDepth(text);
|
|
765
|
+
fileResults.push({ filePath, schemaCount, advancedPatterns, chainDepth, lineCount });
|
|
766
|
+
if (lineCount > 500) {
|
|
767
|
+
warnings.push({
|
|
768
|
+
file: filePath,
|
|
769
|
+
message: `Large file (${lineCount} lines) may be difficult to migrate in one pass`,
|
|
770
|
+
severity: "warning"
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
if (schemaCount > 50) {
|
|
774
|
+
warnings.push({
|
|
775
|
+
file: filePath,
|
|
776
|
+
message: `High schema density (${schemaCount} schemas) \u2014 consider splitting before migration`,
|
|
777
|
+
severity: "warning"
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
if (chainDepth > 20) {
|
|
781
|
+
warnings.push({
|
|
782
|
+
file: filePath,
|
|
783
|
+
message: `Long method chain (${chainDepth} calls) \u2014 higher transformation risk`,
|
|
784
|
+
severity: "warning"
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
const duCount = countMatches(text, /z\.discriminatedUnion\s*\(/g);
|
|
788
|
+
if (duCount > 10) {
|
|
789
|
+
hasDeepDiscriminatedUnions = true;
|
|
790
|
+
warnings.push({
|
|
791
|
+
file: filePath,
|
|
792
|
+
message: `${duCount} discriminated unions \u2014 TypeScript TS2589 performance risk in Zod v4`,
|
|
793
|
+
severity: "error"
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
if (advancedPatterns.includes("recursive")) {
|
|
797
|
+
riskAreas.push(`Recursive schemas in ${filePath}`);
|
|
798
|
+
}
|
|
799
|
+
if (advancedPatterns.includes("branded")) {
|
|
800
|
+
riskAreas.push(`Branded types in ${filePath}`);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
const effort = this.calculateEffort(
|
|
804
|
+
totalSchemas,
|
|
805
|
+
advancedPatternCount,
|
|
806
|
+
hasDeepDiscriminatedUnions
|
|
807
|
+
);
|
|
808
|
+
return {
|
|
809
|
+
effort,
|
|
810
|
+
totalSchemas,
|
|
811
|
+
totalFiles: files.length,
|
|
812
|
+
advancedPatternCount,
|
|
813
|
+
files: fileResults,
|
|
814
|
+
warnings,
|
|
815
|
+
riskAreas
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
calculateEffort(totalSchemas, advancedCount, hasDeepDU) {
|
|
819
|
+
if (totalSchemas >= 500 && hasDeepDU) return "extreme";
|
|
820
|
+
if (totalSchemas >= 200 || advancedCount >= 20) return "high";
|
|
821
|
+
if (totalSchemas >= 50 || advancedCount >= 5) return "moderate";
|
|
822
|
+
if (totalSchemas >= 10) return "low";
|
|
823
|
+
return "trivial";
|
|
824
|
+
}
|
|
825
|
+
};
|
|
826
|
+
|
|
699
827
|
// src/config.ts
|
|
700
828
|
var import_cosmiconfig = require("cosmiconfig");
|
|
701
829
|
function validateConfig(config) {
|
|
@@ -757,6 +885,8 @@ async function loadConfig(configPath) {
|
|
|
757
885
|
}
|
|
758
886
|
|
|
759
887
|
// src/dependency-graph.ts
|
|
888
|
+
var import_node_fs3 = require("fs");
|
|
889
|
+
var import_node_path3 = require("path");
|
|
760
890
|
var SchemaDependencyResolver = class {
|
|
761
891
|
resolve(project, filePaths) {
|
|
762
892
|
const fileSet = new Set(filePaths);
|
|
@@ -842,10 +972,105 @@ var SchemaDependencyResolver = class {
|
|
|
842
972
|
return parts.slice(-2).join("/");
|
|
843
973
|
}
|
|
844
974
|
};
|
|
975
|
+
var SCHEMA_PACKAGES = /* @__PURE__ */ new Set(["zod", "yup", "joi", "io-ts", "valibot", "@effect/schema"]);
|
|
976
|
+
var MonorepoResolver = class {
|
|
977
|
+
detect(projectPath) {
|
|
978
|
+
const pkgPath = (0, import_node_path3.join)(projectPath, "package.json");
|
|
979
|
+
if (!(0, import_node_fs3.existsSync)(pkgPath)) return false;
|
|
980
|
+
try {
|
|
981
|
+
const pkg = JSON.parse((0, import_node_fs3.readFileSync)(pkgPath, "utf-8"));
|
|
982
|
+
return !!pkg.workspaces;
|
|
983
|
+
} catch {
|
|
984
|
+
return false;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
analyze(projectPath) {
|
|
988
|
+
const pkgPath = (0, import_node_path3.join)(projectPath, "package.json");
|
|
989
|
+
if (!(0, import_node_fs3.existsSync)(pkgPath)) {
|
|
990
|
+
return { isMonorepo: false, packages: [], suggestedOrder: [] };
|
|
991
|
+
}
|
|
992
|
+
let workspaceGlobs;
|
|
993
|
+
try {
|
|
994
|
+
const pkg = JSON.parse((0, import_node_fs3.readFileSync)(pkgPath, "utf-8"));
|
|
995
|
+
if (!pkg.workspaces) {
|
|
996
|
+
return { isMonorepo: false, packages: [], suggestedOrder: [] };
|
|
997
|
+
}
|
|
998
|
+
workspaceGlobs = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces.packages;
|
|
999
|
+
} catch {
|
|
1000
|
+
return { isMonorepo: false, packages: [], suggestedOrder: [] };
|
|
1001
|
+
}
|
|
1002
|
+
const packages = [];
|
|
1003
|
+
const resolvedDirs = this.resolveWorkspaceDirs(projectPath, workspaceGlobs);
|
|
1004
|
+
for (const dir of resolvedDirs) {
|
|
1005
|
+
const wsPkgPath = (0, import_node_path3.join)(dir, "package.json");
|
|
1006
|
+
if (!(0, import_node_fs3.existsSync)(wsPkgPath)) continue;
|
|
1007
|
+
try {
|
|
1008
|
+
const wsPkg = JSON.parse((0, import_node_fs3.readFileSync)(wsPkgPath, "utf-8"));
|
|
1009
|
+
if (!wsPkg.name) continue;
|
|
1010
|
+
const allDeps = { ...wsPkg.dependencies, ...wsPkg.devDependencies };
|
|
1011
|
+
const depNames = Object.keys(allDeps);
|
|
1012
|
+
const schemaLibrary = depNames.find((d) => SCHEMA_PACKAGES.has(d));
|
|
1013
|
+
packages.push({
|
|
1014
|
+
name: wsPkg.name,
|
|
1015
|
+
path: dir,
|
|
1016
|
+
schemaLibrary,
|
|
1017
|
+
dependencies: depNames
|
|
1018
|
+
});
|
|
1019
|
+
} catch {
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
const suggestedOrder = this.suggestOrder(packages);
|
|
1023
|
+
return { isMonorepo: true, packages, suggestedOrder };
|
|
1024
|
+
}
|
|
1025
|
+
suggestOrder(packages) {
|
|
1026
|
+
const nameSet = new Set(packages.map((p) => p.name));
|
|
1027
|
+
const depMap = /* @__PURE__ */ new Map();
|
|
1028
|
+
for (const pkg of packages) {
|
|
1029
|
+
const internalDeps = pkg.dependencies.filter((d) => nameSet.has(d));
|
|
1030
|
+
depMap.set(pkg.name, internalDeps);
|
|
1031
|
+
}
|
|
1032
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1033
|
+
const sorted = [];
|
|
1034
|
+
const visit = (name) => {
|
|
1035
|
+
if (visited.has(name)) return;
|
|
1036
|
+
visited.add(name);
|
|
1037
|
+
for (const dep of depMap.get(name) ?? []) {
|
|
1038
|
+
visit(dep);
|
|
1039
|
+
}
|
|
1040
|
+
sorted.push(name);
|
|
1041
|
+
};
|
|
1042
|
+
for (const pkg of packages) {
|
|
1043
|
+
visit(pkg.name);
|
|
1044
|
+
}
|
|
1045
|
+
return sorted;
|
|
1046
|
+
}
|
|
1047
|
+
resolveWorkspaceDirs(projectPath, globs) {
|
|
1048
|
+
const dirs = [];
|
|
1049
|
+
for (const glob of globs) {
|
|
1050
|
+
const clean = glob.replace(/\/?\*$/, "");
|
|
1051
|
+
const base = (0, import_node_path3.resolve)(projectPath, clean);
|
|
1052
|
+
if (!(0, import_node_fs3.existsSync)(base)) continue;
|
|
1053
|
+
if (glob.endsWith("*")) {
|
|
1054
|
+
try {
|
|
1055
|
+
const entries = (0, import_node_fs3.readdirSync)(base, { withFileTypes: true });
|
|
1056
|
+
for (const entry of entries) {
|
|
1057
|
+
if (entry.isDirectory()) {
|
|
1058
|
+
dirs.push((0, import_node_path3.join)(base, entry.name));
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
} catch {
|
|
1062
|
+
}
|
|
1063
|
+
} else {
|
|
1064
|
+
dirs.push(base);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
return dirs;
|
|
1068
|
+
}
|
|
1069
|
+
};
|
|
845
1070
|
|
|
846
1071
|
// src/detailed-analyzer.ts
|
|
847
|
-
var
|
|
848
|
-
var
|
|
1072
|
+
var import_node_fs4 = require("fs");
|
|
1073
|
+
var import_node_path4 = require("path");
|
|
849
1074
|
var COMPLEXITY_CHAIN_WEIGHT = 2;
|
|
850
1075
|
var COMPLEXITY_DEPTH_WEIGHT = 3;
|
|
851
1076
|
var COMPLEXITY_VALIDATION_WEIGHT = 1;
|
|
@@ -910,10 +1135,10 @@ var DetailedAnalyzer = class {
|
|
|
910
1135
|
}
|
|
911
1136
|
detectLibraryVersions(projectPath) {
|
|
912
1137
|
const versions = [];
|
|
913
|
-
const pkgPath = (0,
|
|
914
|
-
if (!(0,
|
|
1138
|
+
const pkgPath = (0, import_node_path4.join)(projectPath, "package.json");
|
|
1139
|
+
if (!(0, import_node_fs4.existsSync)(pkgPath)) return versions;
|
|
915
1140
|
try {
|
|
916
|
-
const pkg = JSON.parse((0,
|
|
1141
|
+
const pkg = JSON.parse((0, import_node_fs4.readFileSync)(pkgPath, "utf-8"));
|
|
917
1142
|
const knownLibs = ["zod", "yup", "joi", "io-ts", "valibot"];
|
|
918
1143
|
const allDeps = {
|
|
919
1144
|
...pkg.dependencies,
|
|
@@ -1086,6 +1311,90 @@ var DetailedAnalyzer = class {
|
|
|
1086
1311
|
}
|
|
1087
1312
|
};
|
|
1088
1313
|
|
|
1314
|
+
// src/form-resolver-migrator.ts
|
|
1315
|
+
var RESOLVER_MAPPINGS = {
|
|
1316
|
+
"yup->zod": [
|
|
1317
|
+
{
|
|
1318
|
+
fromImport: "@hookform/resolvers/yup",
|
|
1319
|
+
toImport: "@hookform/resolvers/zod",
|
|
1320
|
+
fromResolver: "yupResolver",
|
|
1321
|
+
toResolver: "zodResolver"
|
|
1322
|
+
}
|
|
1323
|
+
],
|
|
1324
|
+
"joi->zod": [
|
|
1325
|
+
{
|
|
1326
|
+
fromImport: "@hookform/resolvers/joi",
|
|
1327
|
+
toImport: "@hookform/resolvers/zod",
|
|
1328
|
+
fromResolver: "joiResolver",
|
|
1329
|
+
toResolver: "zodResolver"
|
|
1330
|
+
}
|
|
1331
|
+
],
|
|
1332
|
+
"zod->valibot": [
|
|
1333
|
+
{
|
|
1334
|
+
fromImport: "@hookform/resolvers/zod",
|
|
1335
|
+
toImport: "@hookform/resolvers/valibot",
|
|
1336
|
+
fromResolver: "zodResolver",
|
|
1337
|
+
toResolver: "valibotResolver"
|
|
1338
|
+
}
|
|
1339
|
+
]
|
|
1340
|
+
};
|
|
1341
|
+
var TODO_PATTERNS = [
|
|
1342
|
+
{
|
|
1343
|
+
pattern: /from\s+['"]formik['"]/,
|
|
1344
|
+
comment: "/* TODO(schemashift): Formik is unmaintained. Consider migrating to React Hook Form with zodResolver */"
|
|
1345
|
+
},
|
|
1346
|
+
{
|
|
1347
|
+
pattern: /from\s+['"]@mantine\/form['"]/,
|
|
1348
|
+
comment: "/* TODO(schemashift): Update @mantine/form to use Zod schema adapter */"
|
|
1349
|
+
}
|
|
1350
|
+
];
|
|
1351
|
+
var FormResolverMigrator = class {
|
|
1352
|
+
migrate(sourceFile, from, to) {
|
|
1353
|
+
const migration = `${from}->${to}`;
|
|
1354
|
+
let code = sourceFile.getFullText();
|
|
1355
|
+
const changes = [];
|
|
1356
|
+
const warnings = [];
|
|
1357
|
+
const mappings = RESOLVER_MAPPINGS[migration];
|
|
1358
|
+
if (mappings) {
|
|
1359
|
+
for (const mapping of mappings) {
|
|
1360
|
+
if (code.includes(mapping.fromImport)) {
|
|
1361
|
+
code = code.replaceAll(mapping.fromImport, mapping.toImport);
|
|
1362
|
+
code = code.replaceAll(mapping.fromResolver, mapping.toResolver);
|
|
1363
|
+
changes.push(
|
|
1364
|
+
`Replaced ${mapping.fromResolver} import from '${mapping.fromImport}' with ${mapping.toResolver} from '${mapping.toImport}'`
|
|
1365
|
+
);
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
const lines = code.split("\n");
|
|
1370
|
+
const insertions = [];
|
|
1371
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1372
|
+
const line = lines[i] ?? "";
|
|
1373
|
+
for (const { pattern, comment } of TODO_PATTERNS) {
|
|
1374
|
+
if (pattern.test(line) && !code.includes(comment)) {
|
|
1375
|
+
insertions.push({ index: i, comment });
|
|
1376
|
+
warnings.push(comment.replace(/\/\*\s*|\s*\*\//g, "").trim());
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
for (let i = insertions.length - 1; i >= 0; i--) {
|
|
1381
|
+
const insertion = insertions[i];
|
|
1382
|
+
if (!insertion) continue;
|
|
1383
|
+
lines.splice(insertion.index, 0, insertion.comment);
|
|
1384
|
+
changes.push(`Added TODO comment for ${lines[insertion.index + 1]?.trim()}`);
|
|
1385
|
+
}
|
|
1386
|
+
if (insertions.length > 0) {
|
|
1387
|
+
code = lines.join("\n");
|
|
1388
|
+
}
|
|
1389
|
+
return {
|
|
1390
|
+
success: true,
|
|
1391
|
+
transformedCode: code,
|
|
1392
|
+
changes,
|
|
1393
|
+
warnings
|
|
1394
|
+
};
|
|
1395
|
+
}
|
|
1396
|
+
};
|
|
1397
|
+
|
|
1089
1398
|
// src/governance.ts
|
|
1090
1399
|
var GovernanceEngine = class {
|
|
1091
1400
|
rules = /* @__PURE__ */ new Map();
|
|
@@ -1207,16 +1516,16 @@ var GovernanceEngine = class {
|
|
|
1207
1516
|
};
|
|
1208
1517
|
|
|
1209
1518
|
// src/incremental.ts
|
|
1210
|
-
var
|
|
1211
|
-
var
|
|
1519
|
+
var import_node_fs5 = require("fs");
|
|
1520
|
+
var import_node_path5 = require("path");
|
|
1212
1521
|
var STATE_DIR = ".schemashift";
|
|
1213
1522
|
var STATE_FILE = "incremental.json";
|
|
1214
1523
|
var IncrementalTracker = class {
|
|
1215
1524
|
stateDir;
|
|
1216
1525
|
statePath;
|
|
1217
1526
|
constructor(projectPath) {
|
|
1218
|
-
this.stateDir = (0,
|
|
1219
|
-
this.statePath = (0,
|
|
1527
|
+
this.stateDir = (0, import_node_path5.join)(projectPath, STATE_DIR);
|
|
1528
|
+
this.statePath = (0, import_node_path5.join)(this.stateDir, STATE_FILE);
|
|
1220
1529
|
}
|
|
1221
1530
|
start(files, from, to) {
|
|
1222
1531
|
const state = {
|
|
@@ -1251,9 +1560,9 @@ var IncrementalTracker = class {
|
|
|
1251
1560
|
this.saveState(state);
|
|
1252
1561
|
}
|
|
1253
1562
|
getState() {
|
|
1254
|
-
if (!(0,
|
|
1563
|
+
if (!(0, import_node_fs5.existsSync)(this.statePath)) return null;
|
|
1255
1564
|
try {
|
|
1256
|
-
return JSON.parse((0,
|
|
1565
|
+
return JSON.parse((0, import_node_fs5.readFileSync)(this.statePath, "utf-8"));
|
|
1257
1566
|
} catch {
|
|
1258
1567
|
return null;
|
|
1259
1568
|
}
|
|
@@ -1280,21 +1589,21 @@ var IncrementalTracker = class {
|
|
|
1280
1589
|
};
|
|
1281
1590
|
}
|
|
1282
1591
|
clear() {
|
|
1283
|
-
if ((0,
|
|
1284
|
-
(0,
|
|
1592
|
+
if ((0, import_node_fs5.existsSync)(this.statePath)) {
|
|
1593
|
+
(0, import_node_fs5.writeFileSync)(this.statePath, "");
|
|
1285
1594
|
}
|
|
1286
1595
|
}
|
|
1287
1596
|
saveState(state) {
|
|
1288
|
-
if (!(0,
|
|
1289
|
-
(0,
|
|
1597
|
+
if (!(0, import_node_fs5.existsSync)(this.stateDir)) {
|
|
1598
|
+
(0, import_node_fs5.mkdirSync)(this.stateDir, { recursive: true });
|
|
1290
1599
|
}
|
|
1291
|
-
(0,
|
|
1600
|
+
(0, import_node_fs5.writeFileSync)(this.statePath, JSON.stringify(state, null, 2));
|
|
1292
1601
|
}
|
|
1293
1602
|
};
|
|
1294
1603
|
|
|
1295
1604
|
// src/package-updater.ts
|
|
1296
|
-
var
|
|
1297
|
-
var
|
|
1605
|
+
var import_node_fs6 = require("fs");
|
|
1606
|
+
var import_node_path6 = require("path");
|
|
1298
1607
|
var TARGET_VERSIONS = {
|
|
1299
1608
|
"yup->zod": { zod: "^3.24.0" },
|
|
1300
1609
|
"joi->zod": { zod: "^3.24.0" },
|
|
@@ -1315,14 +1624,14 @@ var PackageUpdater = class {
|
|
|
1315
1624
|
const add = {};
|
|
1316
1625
|
const remove = [];
|
|
1317
1626
|
const warnings = [];
|
|
1318
|
-
const pkgPath = (0,
|
|
1319
|
-
if (!(0,
|
|
1627
|
+
const pkgPath = (0, import_node_path6.join)(projectPath, "package.json");
|
|
1628
|
+
if (!(0, import_node_fs6.existsSync)(pkgPath)) {
|
|
1320
1629
|
warnings.push("No package.json found. Cannot plan dependency updates.");
|
|
1321
1630
|
return { add, remove, warnings };
|
|
1322
1631
|
}
|
|
1323
1632
|
let pkg;
|
|
1324
1633
|
try {
|
|
1325
|
-
pkg = JSON.parse((0,
|
|
1634
|
+
pkg = JSON.parse((0, import_node_fs6.readFileSync)(pkgPath, "utf-8"));
|
|
1326
1635
|
} catch {
|
|
1327
1636
|
warnings.push("Could not parse package.json.");
|
|
1328
1637
|
return { add, remove, warnings };
|
|
@@ -1352,9 +1661,9 @@ var PackageUpdater = class {
|
|
|
1352
1661
|
return { add, remove, warnings };
|
|
1353
1662
|
}
|
|
1354
1663
|
apply(projectPath, plan) {
|
|
1355
|
-
const pkgPath = (0,
|
|
1356
|
-
if (!(0,
|
|
1357
|
-
const pkgText = (0,
|
|
1664
|
+
const pkgPath = (0, import_node_path6.join)(projectPath, "package.json");
|
|
1665
|
+
if (!(0, import_node_fs6.existsSync)(pkgPath)) return;
|
|
1666
|
+
const pkgText = (0, import_node_fs6.readFileSync)(pkgPath, "utf-8");
|
|
1358
1667
|
const pkg = JSON.parse(pkgText);
|
|
1359
1668
|
if (!pkg.dependencies) pkg.dependencies = {};
|
|
1360
1669
|
for (const [name, version] of Object.entries(plan.add)) {
|
|
@@ -1364,7 +1673,7 @@ var PackageUpdater = class {
|
|
|
1364
1673
|
pkg.dependencies[name] = version;
|
|
1365
1674
|
}
|
|
1366
1675
|
}
|
|
1367
|
-
(0,
|
|
1676
|
+
(0, import_node_fs6.writeFileSync)(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
1368
1677
|
`);
|
|
1369
1678
|
}
|
|
1370
1679
|
};
|
|
@@ -1414,8 +1723,8 @@ var PluginLoader = class {
|
|
|
1414
1723
|
};
|
|
1415
1724
|
|
|
1416
1725
|
// src/standard-schema.ts
|
|
1417
|
-
var
|
|
1418
|
-
var
|
|
1726
|
+
var import_node_fs7 = require("fs");
|
|
1727
|
+
var import_node_path7 = require("path");
|
|
1419
1728
|
var STANDARD_SCHEMA_LIBRARIES = {
|
|
1420
1729
|
zod: { minMajor: 3, minMinor: 23 },
|
|
1421
1730
|
// Zod v3.23+ and v4+
|
|
@@ -1444,13 +1753,13 @@ function isVersionCompatible(version, minMajor, minMinor) {
|
|
|
1444
1753
|
return false;
|
|
1445
1754
|
}
|
|
1446
1755
|
function detectStandardSchema(projectPath) {
|
|
1447
|
-
const pkgPath = (0,
|
|
1448
|
-
if (!(0,
|
|
1756
|
+
const pkgPath = (0, import_node_path7.join)(projectPath, "package.json");
|
|
1757
|
+
if (!(0, import_node_fs7.existsSync)(pkgPath)) {
|
|
1449
1758
|
return { detected: false, compatibleLibraries: [], recommendation: "" };
|
|
1450
1759
|
}
|
|
1451
1760
|
let allDeps = {};
|
|
1452
1761
|
try {
|
|
1453
|
-
const pkg = JSON.parse((0,
|
|
1762
|
+
const pkg = JSON.parse((0, import_node_fs7.readFileSync)(pkgPath, "utf-8"));
|
|
1454
1763
|
allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
1455
1764
|
} catch {
|
|
1456
1765
|
return { detected: false, compatibleLibraries: [], recommendation: "" };
|
|
@@ -1510,11 +1819,14 @@ var TransformEngine = class {
|
|
|
1510
1819
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1511
1820
|
0 && (module.exports = {
|
|
1512
1821
|
CompatibilityAnalyzer,
|
|
1822
|
+
ComplexityEstimator,
|
|
1513
1823
|
DetailedAnalyzer,
|
|
1514
1824
|
EcosystemAnalyzer,
|
|
1825
|
+
FormResolverMigrator,
|
|
1515
1826
|
GovernanceEngine,
|
|
1516
1827
|
IncrementalTracker,
|
|
1517
1828
|
MigrationChain,
|
|
1829
|
+
MonorepoResolver,
|
|
1518
1830
|
PackageUpdater,
|
|
1519
1831
|
PluginLoader,
|
|
1520
1832
|
SchemaAnalyzer,
|