@schemashift/core 0.2.0 → 0.7.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
@@ -1,6 +1,6 @@
1
1
  # @schemashift/core
2
2
 
3
- Core functionality for SchemaShift schema migrations. Provides schema analysis, detection, and the transform engine.
3
+ Core functionality for SchemaShift schema migrations. Provides schema analysis, detection, transformation engine, ecosystem analysis, governance, and migration utilities.
4
4
 
5
5
  ## Installation
6
6
 
@@ -26,21 +26,262 @@ console.log(`Found ${result.schemas.length} schemas in ${result.filesWithSchemas
26
26
 
27
27
  #### Methods
28
28
 
29
- - `addSourceFiles(patterns: string[])` - Add files to analyze by glob patterns
30
- - `analyze(): AnalysisResult` - Run analysis and return results
31
- - `getProject(): Project` - Get the underlying ts-morph Project
29
+ - `addSourceFiles(patterns: string[])` Add files to analyze by glob patterns
30
+ - `analyze(): AnalysisResult` Run analysis and return results
31
+ - `getProject(): Project` Get the underlying ts-morph Project
32
32
 
33
- #### AnalysisResult
33
+ ### TransformEngine
34
+
35
+ Manages transformation handlers and executes migrations.
36
+
37
+ ```typescript
38
+ import { TransformEngine } from '@schemashift/core';
39
+ import { createYupToZodHandler } from '@schemashift/yup-zod';
40
+
41
+ const engine = new TransformEngine();
42
+ engine.registerHandler('yup', 'zod', createYupToZodHandler());
43
+
44
+ const sourceFile = project.getSourceFileOrThrow('schema.ts');
45
+ const result = engine.transform(sourceFile, 'yup', 'zod');
46
+
47
+ if (result.success) {
48
+ console.log(result.transformedCode);
49
+ }
50
+ ```
51
+
52
+ #### Methods
53
+
54
+ - `registerHandler(from, to, handler)` — Register a transformation handler
55
+ - `getHandler(from, to)` — Get a registered handler
56
+ - `transform(sourceFile, from, to)` — Transform a source file
57
+
58
+ ### DetailedAnalyzer
59
+
60
+ Provides complexity scoring, migration readiness analysis, and library version detection.
61
+
62
+ ```typescript
63
+ import { DetailedAnalyzer, SchemaAnalyzer } from '@schemashift/core';
64
+
65
+ const analyzer = new SchemaAnalyzer();
66
+ analyzer.addSourceFiles(['src/**/*.ts']);
67
+
68
+ const detailed = new DetailedAnalyzer();
69
+
70
+ // Complexity scoring per-schema
71
+ const complexities = detailed.analyzeComplexity(analyzer);
72
+ for (const c of complexities) {
73
+ console.log(`${c.schemaName}: score=${c.score}, level=${c.level}`);
74
+ }
75
+
76
+ // Migration readiness
77
+ const readiness = detailed.analyzeReadiness(schemas, 'yup', 'zod', supportedMethods);
78
+ console.log(`${readiness.readinessPercent}% ready, risk: ${readiness.riskLevel}`);
79
+
80
+ // Library versions from package.json
81
+ const versions = detailed.detectLibraryVersions('./project');
82
+ // [{ library: 'zod', version: '^3.22.0' }, ...]
83
+
84
+ // Full detailed result
85
+ const result = detailed.generateDetailedResult(complexities, './project');
86
+ console.log(`Average complexity: ${result.averageComplexity}`);
87
+ ```
88
+
89
+ ### EcosystemAnalyzer
90
+
91
+ Detects ecosystem packages affected by a migration. Checks for compatibility issues with tRPC, drizzle-zod, zod-validation-error, @hookform/resolvers, Formik, Mantine, OpenAPI generators, and more.
92
+
93
+ ```typescript
94
+ import { EcosystemAnalyzer } from '@schemashift/core';
95
+
96
+ const ecosystem = new EcosystemAnalyzer();
97
+ const report = ecosystem.analyze('./project', 'zod-v3', 'v4');
98
+
99
+ // Blockers — packages that will break
100
+ for (const blocker of report.blockers) {
101
+ console.error(blocker);
102
+ }
103
+
104
+ // Warnings — packages that may need updating
105
+ for (const warning of report.warnings) {
106
+ console.warn(warning);
107
+ }
108
+
109
+ // Full issue details
110
+ for (const dep of report.dependencies) {
111
+ console.log(`${dep.package}@${dep.installedVersion}: ${dep.issue}`);
112
+ console.log(` Suggestion: ${dep.suggestion}`);
113
+ console.log(` Severity: ${dep.severity}, Category: ${dep.category}`);
114
+ }
115
+ ```
116
+
117
+ #### Detected Packages
118
+
119
+ | Package | Migration | Category |
120
+ |---------|-----------|----------|
121
+ | `drizzle-zod` | zod-v3→v4 | ORM |
122
+ | `zod-prisma` / `zod-prisma-types` | zod-v3→v4 | ORM |
123
+ | `@trpc/server` | zod-v3→v4 | API |
124
+ | `trpc-ui` | zod-v3→v4 | UI |
125
+ | `zod-validation-error` | zod-v3→v4 | Validation |
126
+ | `@hookform/resolvers` | all→zod, zod-v3→v4 | Form |
127
+ | `formik` | yup→zod, joi→zod | Form |
128
+ | `@mantine/form` | yup→zod, joi→zod | Form |
129
+ | `zod-openapi` / `@asteasolutions/zod-to-openapi` | zod-v3→v4 | OpenAPI |
130
+
131
+ ### PackageUpdater
132
+
133
+ Plans and applies dependency changes to `package.json` after migration.
134
+
135
+ ```typescript
136
+ import { PackageUpdater } from '@schemashift/core';
137
+
138
+ const updater = new PackageUpdater();
139
+
140
+ // Plan changes (doesn't modify files)
141
+ const plan = updater.plan('./project', 'yup', 'zod');
142
+ console.log('Add:', plan.add); // { zod: '^3.24.0' }
143
+ console.log('Remove:', plan.remove); // ['yup'] (suggested, not auto-removed)
144
+ console.log('Warnings:', plan.warnings);
145
+
146
+ // Apply the additions to package.json
147
+ updater.apply('./project', plan);
148
+ ```
149
+
150
+ ### IncrementalTracker
151
+
152
+ Tracks progress for file-by-file incremental migrations. State is persisted in `.schemashift/incremental.json`.
153
+
154
+ ```typescript
155
+ import { IncrementalTracker } from '@schemashift/core';
156
+
157
+ const tracker = new IncrementalTracker('./project');
158
+
159
+ // Start a new incremental migration
160
+ const state = tracker.start(['a.ts', 'b.ts', 'c.ts'], 'yup', 'zod');
161
+
162
+ // Process files in batches
163
+ const batch = tracker.getNextBatch(2); // ['a.ts', 'b.ts']
164
+
165
+ // Mark files as complete or failed
166
+ tracker.markComplete('a.ts');
167
+ tracker.markFailed('b.ts');
168
+
169
+ // Check progress
170
+ const progress = tracker.getProgress();
171
+ // { completed: 1, remaining: 1, failed: 1, total: 3, percent: 33 }
172
+
173
+ // Resume a previous migration
174
+ const resumed = tracker.resume();
175
+
176
+ // Clear state when done
177
+ tracker.clear();
178
+ ```
179
+
180
+ ### GovernanceEngine
181
+
182
+ Enforces schema quality rules across a codebase.
34
183
 
35
184
  ```typescript
36
- interface AnalysisResult {
37
- schemas: SchemaInfo[];
38
- imports: Map<string, SchemaLibrary>;
39
- totalFiles: number;
40
- filesWithSchemas: number;
185
+ import { GovernanceEngine } from '@schemashift/core';
186
+ import { Project } from 'ts-morph';
187
+
188
+ const engine = new GovernanceEngine();
189
+ engine.configure({
190
+ 'naming-convention': { pattern: '.*Schema$' },
191
+ 'max-complexity': { threshold: 80 },
192
+ 'no-any': {},
193
+ 'required-validations': {},
194
+ });
195
+
196
+ const project = new Project();
197
+ project.addSourceFilesAtPaths(['src/**/*.ts']);
198
+
199
+ const result = engine.analyze(project);
200
+ console.log(`Passed: ${result.passed}`);
201
+ console.log(`Files scanned: ${result.filesScanned}`);
202
+ console.log(`Schemas checked: ${result.schemasChecked}`);
203
+
204
+ for (const v of result.violations) {
205
+ console.log(`[${v.severity}] ${v.rule}: ${v.message} (${v.filePath}:${v.lineNumber})`);
41
206
  }
42
207
  ```
43
208
 
209
+ #### Built-in Rules
210
+
211
+ | Rule | Description | Severity |
212
+ |------|-------------|----------|
213
+ | `naming-convention` | Schemas must match a regex pattern | warning |
214
+ | `max-complexity` | Reject schemas exceeding a complexity score | warning |
215
+ | `no-any` | Disallow `.any()` usage | error |
216
+ | `required-validations` | String schemas must include `.max()` | warning |
217
+
218
+ ### CompatibilityAnalyzer
219
+
220
+ Checks schema library version compatibility before migration.
221
+
222
+ ```typescript
223
+ import { CompatibilityAnalyzer } from '@schemashift/core';
224
+
225
+ const compat = new CompatibilityAnalyzer();
226
+ const result = compat.checkCompatibility('./project', 'zod-v3', 'v4');
227
+ ```
228
+
229
+ ### MigrationChain
230
+
231
+ Executes multi-step migrations (e.g., `yup→zod→valibot`).
232
+
233
+ ```typescript
234
+ import { MigrationChain } from '@schemashift/core';
235
+
236
+ const chain = new MigrationChain(engine);
237
+ const result = chain.execute(sourceFile, [
238
+ { from: 'yup', to: 'zod' },
239
+ { from: 'zod', to: 'valibot' },
240
+ ]);
241
+ ```
242
+
243
+ ### SchemaDependencyResolver
244
+
245
+ Resolves cross-file schema imports for dependency-ordered transformations.
246
+
247
+ ```typescript
248
+ import { SchemaDependencyResolver } from '@schemashift/core';
249
+
250
+ const resolver = new SchemaDependencyResolver();
251
+ const graph = resolver.resolve(project, files);
252
+ // graph.order: files sorted by dependency (leaves first)
253
+ ```
254
+
255
+ ### PluginLoader
256
+
257
+ Loads custom transform plugins from file paths or npm packages.
258
+
259
+ ```typescript
260
+ import { PluginLoader } from '@schemashift/core';
261
+
262
+ const loader = new PluginLoader();
263
+ const result = loader.load('./my-plugin.js');
264
+ if (result.success) {
265
+ engine.registerHandler(result.plugin.from, result.plugin.to, result.plugin.handler);
266
+ }
267
+ ```
268
+
269
+ ### detectStandardSchema
270
+
271
+ Detects Standard Schema-compatible libraries in a project.
272
+
273
+ ```typescript
274
+ import { detectStandardSchema } from '@schemashift/core';
275
+
276
+ const info = detectStandardSchema('./project');
277
+ if (info.detected) {
278
+ console.log('Compatible libraries:', info.compatibleLibraries);
279
+ console.log(info.recommendation);
280
+ }
281
+ ```
282
+
283
+ Supports: Zod 3.23+, Valibot 1.0+, ArkType 2.0+, @effect/schema, TypeBox 0.34+.
284
+
44
285
  ### detectSchemaLibrary
45
286
 
46
287
  Detects which schema library a module import refers to.
@@ -56,45 +297,40 @@ detectSchemaLibrary('valibot'); // 'valibot'
56
297
  detectSchemaLibrary('lodash'); // 'unknown'
57
298
  ```
58
299
 
59
- ### TransformEngine
300
+ ### detectFormLibraries
60
301
 
61
- Manages transformation handlers and executes migrations.
302
+ Detects form libraries (React Hook Form, Formik, Mantine) in use.
62
303
 
63
304
  ```typescript
64
- import { TransformEngine } from '@schemashift/core';
65
- import { createYupToZodHandler } from '@schemashift/yup-zod';
66
-
67
- const engine = new TransformEngine();
68
- engine.registerHandler('yup', 'zod', createYupToZodHandler());
69
-
70
- const sourceFile = project.getSourceFileOrThrow('schema.ts');
71
- const result = engine.transform(sourceFile, 'yup', 'zod');
305
+ import { detectFormLibraries } from '@schemashift/core';
72
306
 
73
- if (result.success) {
74
- console.log(result.transformedCode);
75
- } else {
76
- console.error(result.errors);
77
- }
307
+ const forms = detectFormLibraries(project);
308
+ // [{ library: 'react-hook-form', resolverUsed: 'yupResolver' }]
78
309
  ```
79
310
 
80
- #### Methods
311
+ ### AST Utilities
312
+
313
+ Low-level helpers for working with schema ASTs:
81
314
 
82
- - `registerHandler(from, to, handler)` - Register a transformation handler
83
- - `getHandler(from, to)` - Get a registered handler
84
- - `transform(sourceFile, from, to)` - Transform a source file
315
+ ```typescript
316
+ import {
317
+ parseCallChain,
318
+ buildCallChain,
319
+ isInsideStringLiteral,
320
+ isInsideComment,
321
+ startsWithBase,
322
+ transformMethodChain,
323
+ } from '@schemashift/core';
324
+
325
+ // Parse z.string().email().min(5) into structured chain info
326
+ const chain = parseCallChain(callExpression);
327
+ // { base: 'z', factoryMethod: 'string', factoryArgs: [], methods: [...] }
328
+ ```
85
329
 
86
- ### Types
330
+ ## Types
87
331
 
88
332
  ```typescript
89
- type SchemaLibrary =
90
- | 'zod'
91
- | 'zod-v3'
92
- | 'yup'
93
- | 'joi'
94
- | 'io-ts'
95
- | 'valibot'
96
- | 'v4'
97
- | 'unknown';
333
+ type SchemaLibrary = 'zod' | 'zod-v3' | 'yup' | 'joi' | 'io-ts' | 'valibot' | 'v4' | 'unknown';
98
334
 
99
335
  interface SchemaInfo {
100
336
  name: string;
@@ -119,8 +355,61 @@ interface TransformError {
119
355
  code?: string;
120
356
  }
121
357
 
122
- interface TransformHandler {
123
- transform(sourceFile: SourceFile): TransformResult;
358
+ interface EcosystemReport {
359
+ dependencies: EcosystemIssue[];
360
+ warnings: string[];
361
+ blockers: string[];
362
+ }
363
+
364
+ interface EcosystemIssue {
365
+ package: string;
366
+ installedVersion: string;
367
+ migration: string;
368
+ issue: string;
369
+ suggestion: string;
370
+ severity: 'info' | 'warning' | 'error';
371
+ category: 'orm' | 'form' | 'api' | 'validation-util' | 'openapi' | 'ui';
372
+ }
373
+
374
+ interface PackageUpdatePlan {
375
+ add: Record<string, string>;
376
+ remove: string[];
377
+ warnings: string[];
378
+ }
379
+
380
+ interface IncrementalState {
381
+ migrationId: string;
382
+ from: SchemaLibrary;
383
+ to: SchemaLibrary;
384
+ startedAt: string;
385
+ completedFiles: string[];
386
+ remainingFiles: string[];
387
+ failedFiles: string[];
388
+ }
389
+
390
+ interface StandardSchemaInfo {
391
+ detected: boolean;
392
+ compatibleLibraries: Array<{ name: string; version: string }>;
393
+ recommendation: string;
394
+ }
395
+
396
+ interface SchemaComplexity {
397
+ schemaName: string;
398
+ filePath: string;
399
+ library: SchemaLibrary;
400
+ lineNumber: number;
401
+ chainLength: number;
402
+ nestedDepth: number;
403
+ validationCount: number;
404
+ score: number;
405
+ level: 'low' | 'medium' | 'high' | 'critical';
406
+ }
407
+
408
+ interface GovernanceResult {
409
+ violations: GovernanceViolation[];
410
+ filesScanned: number;
411
+ schemasChecked: number;
412
+ passed: boolean;
124
413
  }
125
414
  ```
126
415