@schemashift/core 0.3.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/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { Project, SourceFile } from 'ts-morph';
1
+ import { Project, CallExpression, Node, SourceFile } from 'ts-morph';
2
2
 
3
3
  type SchemaLibrary = 'zod' | 'zod-v3' | 'yup' | 'joi' | 'io-ts' | 'valibot' | 'v4' | 'unknown';
4
4
  interface SchemaInfo {
@@ -46,6 +46,186 @@ declare class SchemaAnalyzer {
46
46
  getProject(): Project;
47
47
  }
48
48
 
49
+ /**
50
+ * Represents a single method call in a chain.
51
+ * e.g., `.email()` or `.min(5, 'Too short')`
52
+ */
53
+ interface MethodCallInfo {
54
+ name: string;
55
+ args: string[];
56
+ node: CallExpression;
57
+ }
58
+ /**
59
+ * Represents a full call chain like `yup.string().email().min(5)`.
60
+ */
61
+ interface CallChainInfo {
62
+ /** The base expression before the first method, e.g., 'yup' or 'Joi' */
63
+ base: string;
64
+ /** The initial factory call, e.g., 'string' from `yup.string()` */
65
+ factoryMethod: string;
66
+ /** Arguments to the factory method */
67
+ factoryArgs: string[];
68
+ /** All chained method calls after the factory */
69
+ methods: MethodCallInfo[];
70
+ /** The outermost call expression node */
71
+ rootNode: CallExpression;
72
+ }
73
+ /**
74
+ * Parse a method call chain from the outermost CallExpression.
75
+ *
76
+ * Given `yup.string().email().min(5)`, returns:
77
+ * ```
78
+ * {
79
+ * base: 'yup',
80
+ * factoryMethod: 'string',
81
+ * factoryArgs: [],
82
+ * methods: [
83
+ * { name: 'email', args: [] },
84
+ * { name: 'min', args: ['5'] }
85
+ * ]
86
+ * }
87
+ * ```
88
+ *
89
+ * Returns `undefined` if the node is not a recognizable method chain
90
+ * (e.g., it's a standalone function call).
91
+ */
92
+ declare function parseCallChain(node: CallExpression): CallChainInfo | undefined;
93
+ /**
94
+ * Build a method chain string from parts.
95
+ *
96
+ * ```ts
97
+ * buildCallChain('z', 'string', [], [
98
+ * { name: 'email', args: [] },
99
+ * { name: 'min', args: ['5'] },
100
+ * ])
101
+ * // => 'z.string().email().min(5)'
102
+ * ```
103
+ */
104
+ declare function buildCallChain(base: string, factoryMethod: string, factoryArgs: string[], methods: Array<{
105
+ name: string;
106
+ args: string[];
107
+ }>): string;
108
+ /**
109
+ * Check whether a node is inside a string literal or template literal.
110
+ */
111
+ declare function isInsideStringLiteral(node: Node): boolean;
112
+ /**
113
+ * Check whether a node is inside a comment.
114
+ * Since ts-morph's AST doesn't include comment nodes in the tree,
115
+ * we check by position against leading/trailing comment ranges.
116
+ */
117
+ declare function isInsideComment(node: Node, sourceFile: SourceFile): boolean;
118
+ /**
119
+ * Check if a call expression starts with a specific base identifier.
120
+ * Traverses into the chain to find the root identifier.
121
+ *
122
+ * e.g., `startsWithBase(node, 'yup')` returns true for `yup.string().email()`
123
+ */
124
+ declare function startsWithBase(node: CallExpression, ...bases: string[]): boolean;
125
+ /**
126
+ * Transform a method chain by applying a mapping function to each method.
127
+ * Returns the rebuilt chain as a string, or undefined if no transformation was needed.
128
+ *
129
+ * The mapper receives each method and can return:
130
+ * - `{ name, args }` to transform the method
131
+ * - `null` to remove the method from the chain
132
+ * - `undefined` to keep it unchanged
133
+ * - An array to expand into multiple methods
134
+ */
135
+ declare function transformMethodChain(chain: CallChainInfo, newBase: string, factoryMapper: (method: string, args: string[]) => {
136
+ name: string;
137
+ args: string[];
138
+ } | undefined, methodMapper: (method: MethodCallInfo) => {
139
+ name: string;
140
+ args: string[];
141
+ } | {
142
+ name: string;
143
+ args: string[];
144
+ }[] | null | undefined): string;
145
+
146
+ interface TransformHandler {
147
+ transform(sourceFile: SourceFile, options: TransformOptions): TransformResult;
148
+ }
149
+ declare class TransformEngine {
150
+ private handlers;
151
+ registerHandler(from: SchemaLibrary, to: SchemaLibrary, handler: TransformHandler): void;
152
+ getHandler(from: SchemaLibrary, to: SchemaLibrary): TransformHandler | undefined;
153
+ hasHandler(from: SchemaLibrary, to: SchemaLibrary): boolean;
154
+ getSupportedPaths(): Array<{
155
+ from: SchemaLibrary;
156
+ to: SchemaLibrary;
157
+ }>;
158
+ transform(sourceFile: SourceFile, from: SchemaLibrary, to: SchemaLibrary, options: TransformOptions): TransformResult;
159
+ }
160
+
161
+ interface ChainStep {
162
+ from: SchemaLibrary;
163
+ to: SchemaLibrary;
164
+ }
165
+ interface ChainValidation {
166
+ valid: boolean;
167
+ errors: string[];
168
+ steps: ChainStep[];
169
+ }
170
+ interface ChainStepResult {
171
+ step: ChainStep;
172
+ result: TransformResult;
173
+ }
174
+ interface ChainResult {
175
+ success: boolean;
176
+ steps: ChainStepResult[];
177
+ finalCode?: string;
178
+ errors: string[];
179
+ }
180
+ declare class MigrationChain {
181
+ parseChain(chain: string): ChainStep[];
182
+ validateChain(steps: ChainStep[], engine: TransformEngine): ChainValidation;
183
+ executeChain(sourceCode: string, filePath: string, steps: ChainStep[], engine: TransformEngine): ChainResult;
184
+ }
185
+
186
+ interface EcosystemIssue {
187
+ package: string;
188
+ installedVersion: string;
189
+ migration: string;
190
+ issue: string;
191
+ suggestion: string;
192
+ severity: 'info' | 'warning' | 'error';
193
+ category: 'orm' | 'form' | 'api' | 'validation-util' | 'openapi' | 'ui';
194
+ }
195
+ interface EcosystemReport {
196
+ dependencies: EcosystemIssue[];
197
+ warnings: string[];
198
+ blockers: string[];
199
+ }
200
+ declare class EcosystemAnalyzer {
201
+ analyze(projectPath: string, from: string, to: string): EcosystemReport;
202
+ }
203
+
204
+ interface VersionIssue {
205
+ library: string;
206
+ detectedVersion: string;
207
+ issue: string;
208
+ suggestion: string;
209
+ severity: 'info' | 'warning' | 'error';
210
+ }
211
+ interface CompatibilityResult {
212
+ detectedVersions: Array<{
213
+ library: string;
214
+ version: string;
215
+ }>;
216
+ issues: VersionIssue[];
217
+ ecosystemIssues: EcosystemIssue[];
218
+ overallScore: number;
219
+ }
220
+ declare class CompatibilityAnalyzer {
221
+ private ecosystemAnalyzer;
222
+ detectVersions(projectPath: string): Array<{
223
+ library: string;
224
+ version: string;
225
+ }>;
226
+ checkCompatibility(projectPath: string, from?: string, to?: string): CompatibilityResult;
227
+ }
228
+
49
229
  interface SchemaShiftConfig {
50
230
  include: string[];
51
231
  exclude: string[];
@@ -65,7 +245,22 @@ interface SchemaShiftConfig {
65
245
  dir?: string;
66
246
  };
67
247
  customRules?: CustomRule[];
248
+ suppressWarnings?: WarningSuppressionRule[];
68
249
  ci?: boolean;
250
+ plugins?: string[];
251
+ governance?: {
252
+ rules: Record<string, GovernanceRuleConfig>;
253
+ failOnViolation?: boolean;
254
+ };
255
+ }
256
+ interface GovernanceRuleConfig {
257
+ enabled?: boolean;
258
+ pattern?: string;
259
+ threshold?: number;
260
+ }
261
+ interface WarningSuppressionRule {
262
+ code: string;
263
+ files?: string[];
69
264
  }
70
265
  interface CustomRule {
71
266
  name: string;
@@ -81,23 +276,177 @@ interface CustomRule {
81
276
  warning?: string;
82
277
  };
83
278
  }
279
+ declare function validateConfig(config: SchemaShiftConfig): {
280
+ valid: boolean;
281
+ errors: string[];
282
+ };
283
+ declare function shouldSuppressWarning(warning: string, filePath: string, rules: WarningSuppressionRule[]): boolean;
84
284
  declare function loadConfig(configPath?: string): Promise<SchemaShiftConfig>;
85
285
 
286
+ interface DependencyGraphResult {
287
+ /** Files sorted in dependency order (dependencies first) */
288
+ sortedFiles: string[];
289
+ /** Map of file -> files it depends on */
290
+ dependencies: Map<string, string[]>;
291
+ /** Circular dependency warnings */
292
+ circularWarnings: string[];
293
+ /** Total cross-file schema references */
294
+ crossFileRefs: number;
295
+ }
296
+ declare class SchemaDependencyResolver {
297
+ resolve(project: Project, filePaths: string[]): DependencyGraphResult;
298
+ private findDependencies;
299
+ private detectCycles;
300
+ private topologicalSort;
301
+ private shortenPath;
302
+ }
303
+
304
+ interface SchemaComplexity {
305
+ schemaName: string;
306
+ filePath: string;
307
+ library: SchemaLibrary;
308
+ lineNumber: number;
309
+ chainLength: number;
310
+ nestedDepth: number;
311
+ validationCount: number;
312
+ score: number;
313
+ level: 'low' | 'medium' | 'high' | 'critical';
314
+ }
315
+ interface MigrationReadiness {
316
+ from: SchemaLibrary;
317
+ to: SchemaLibrary;
318
+ totalSchemas: number;
319
+ supportedSchemas: number;
320
+ unsupportedPatterns: string[];
321
+ estimatedManualFixes: number;
322
+ readinessPercent: number;
323
+ riskLevel: 'low' | 'medium' | 'high' | 'critical';
324
+ }
325
+ interface LibraryVersionInfo {
326
+ library: string;
327
+ version: string;
328
+ }
329
+ interface DetailedAnalysisResult {
330
+ complexities: SchemaComplexity[];
331
+ averageComplexity: number;
332
+ maxComplexity: number;
333
+ libraryVersions: LibraryVersionInfo[];
334
+ readiness?: MigrationReadiness;
335
+ }
336
+ declare class DetailedAnalyzer {
337
+ analyzeComplexity(analyzer: SchemaAnalyzer): SchemaComplexity[];
338
+ analyzeReadiness(schemas: SchemaInfo[], from: SchemaLibrary, to: SchemaLibrary, supportedMethods: Set<string>): MigrationReadiness;
339
+ detectLibraryVersions(projectPath: string): LibraryVersionInfo[];
340
+ generateDetailedResult(complexities: SchemaComplexity[], projectPath: string, readiness?: MigrationReadiness): DetailedAnalysisResult;
341
+ private computeComplexity;
342
+ private countChainLength;
343
+ private countNestedDepth;
344
+ private countValidations;
345
+ private extractMethodNames;
346
+ private getLibraryPrefix;
347
+ private escapeRegex;
348
+ private detectFileLibrary;
349
+ private isSchemaExpression;
350
+ }
351
+
86
352
  declare function detectSchemaLibrary(moduleSpecifier: string): SchemaLibrary;
353
+ interface FormLibraryDetection {
354
+ library: string;
355
+ importPath: string;
356
+ lineNumber: number;
357
+ }
358
+ declare function detectFormLibraries(sourceFile: SourceFile): FormLibraryDetection[];
87
359
 
88
- interface TransformHandler {
89
- transform(sourceFile: SourceFile, options: TransformOptions): TransformResult;
360
+ interface GovernanceViolation {
361
+ rule: string;
362
+ message: string;
363
+ filePath: string;
364
+ lineNumber: number;
365
+ schemaName: string;
366
+ severity: 'warning' | 'error';
367
+ fixable: boolean;
90
368
  }
91
- declare class TransformEngine {
92
- private handlers;
93
- registerHandler(from: SchemaLibrary, to: SchemaLibrary, handler: TransformHandler): void;
94
- getHandler(from: SchemaLibrary, to: SchemaLibrary): TransformHandler | undefined;
95
- hasHandler(from: SchemaLibrary, to: SchemaLibrary): boolean;
96
- getSupportedPaths(): Array<{
369
+ interface GovernanceResult {
370
+ violations: GovernanceViolation[];
371
+ filesScanned: number;
372
+ schemasChecked: number;
373
+ passed: boolean;
374
+ }
375
+ declare class GovernanceEngine {
376
+ private rules;
377
+ configure(rules: Record<string, GovernanceRuleConfig>): void;
378
+ analyze(project: Project): GovernanceResult;
379
+ private detectFileLibrary;
380
+ private isSchemaExpression;
381
+ }
382
+
383
+ interface IncrementalState {
384
+ migrationId: string;
385
+ from: SchemaLibrary;
386
+ to: SchemaLibrary;
387
+ startedAt: string;
388
+ completedFiles: string[];
389
+ remainingFiles: string[];
390
+ failedFiles: string[];
391
+ }
392
+ declare class IncrementalTracker {
393
+ private stateDir;
394
+ private statePath;
395
+ constructor(projectPath: string);
396
+ start(files: string[], from: SchemaLibrary, to: SchemaLibrary): IncrementalState;
397
+ markComplete(filePath: string): void;
398
+ markFailed(filePath: string): void;
399
+ getState(): IncrementalState | null;
400
+ resume(): IncrementalState | null;
401
+ getNextBatch(batchSize: number): string[];
402
+ getProgress(): {
403
+ completed: number;
404
+ remaining: number;
405
+ failed: number;
406
+ total: number;
407
+ percent: number;
408
+ } | null;
409
+ clear(): void;
410
+ private saveState;
411
+ }
412
+
413
+ interface PackageUpdatePlan {
414
+ add: Record<string, string>;
415
+ remove: string[];
416
+ warnings: string[];
417
+ }
418
+ declare class PackageUpdater {
419
+ plan(projectPath: string, from: string, to: string): PackageUpdatePlan;
420
+ apply(projectPath: string, plan: PackageUpdatePlan): void;
421
+ }
422
+
423
+ interface SchemaShiftPlugin {
424
+ name: string;
425
+ version: string;
426
+ handlers?: Array<{
97
427
  from: SchemaLibrary;
98
428
  to: SchemaLibrary;
429
+ handler: TransformHandler;
99
430
  }>;
100
- transform(sourceFile: SourceFile, from: SchemaLibrary, to: SchemaLibrary, options: TransformOptions): TransformResult;
431
+ rules?: CustomRule[];
432
+ }
433
+ interface PluginLoadResult {
434
+ loaded: SchemaShiftPlugin[];
435
+ errors: string[];
436
+ }
437
+ declare class PluginLoader {
438
+ loadPlugins(pluginPaths: string[]): Promise<PluginLoadResult>;
439
+ private validatePlugin;
440
+ }
441
+
442
+ interface StandardSchemaInfo {
443
+ detected: boolean;
444
+ compatibleLibraries: Array<{
445
+ name: string;
446
+ version: string;
447
+ }>;
448
+ recommendation: string;
101
449
  }
450
+ declare function detectStandardSchema(projectPath: string): StandardSchemaInfo;
102
451
 
103
- export { type AnalysisResult, type CustomRule, SchemaAnalyzer, type SchemaInfo, type SchemaLibrary, type SchemaShiftConfig, TransformEngine, type TransformError, type TransformHandler, type TransformOptions, type TransformResult, detectSchemaLibrary, loadConfig };
452
+ export { type AnalysisResult, type CallChainInfo, type ChainResult, type ChainStep, type ChainStepResult, type ChainValidation, CompatibilityAnalyzer, type CompatibilityResult, type CustomRule, type DependencyGraphResult, type DetailedAnalysisResult, DetailedAnalyzer, EcosystemAnalyzer, type EcosystemIssue, type EcosystemReport, type FormLibraryDetection, GovernanceEngine, type GovernanceResult, type GovernanceRuleConfig, type GovernanceViolation, type IncrementalState, IncrementalTracker, type LibraryVersionInfo, type MethodCallInfo, MigrationChain, type MigrationReadiness, type PackageUpdatePlan, PackageUpdater, type PluginLoadResult, PluginLoader, SchemaAnalyzer, type SchemaComplexity, SchemaDependencyResolver, type SchemaInfo, type SchemaLibrary, type SchemaShiftConfig, type SchemaShiftPlugin, type StandardSchemaInfo, TransformEngine, type TransformError, type TransformHandler, type TransformOptions, type TransformResult, type VersionIssue, type WarningSuppressionRule, buildCallChain, detectFormLibraries, detectSchemaLibrary, detectStandardSchema, isInsideComment, isInsideStringLiteral, loadConfig, parseCallChain, shouldSuppressWarning, startsWithBase, transformMethodChain, validateConfig };