-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathgenerate-schemas.ts
More file actions
148 lines (121 loc) · 4.27 KB
/
Copy pathgenerate-schemas.ts
File metadata and controls
148 lines (121 loc) · 4.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env tsx
import { exec } from 'child_process';
import { readFileSync, writeFileSync } from 'fs';
import { join } from 'path';
import { promisify } from 'util';
const execAsync = promisify(exec);
// Legacy schema versions that should remain as JSON Schema draft-07
const LEGACY_SCHEMAS = ['2024-11-05', '2025-03-26', '2025-06-18'];
// Modern schema versions that use JSON Schema 2020-12
const MODERN_SCHEMAS = ['2025-11-25', '2026-07-28', 'draft'];
// All schema versions to generate
const ALL_SCHEMAS = [...LEGACY_SCHEMAS, ...MODERN_SCHEMAS];
// Check if we're in check mode (validate existing schemas match generated ones)
const CHECK_MODE = process.argv.includes('--check');
/**
* Apply JSON Schema 2020-12 transformations to a schema file
*/
function applyJsonSchema202012Transformations(schemaPath: string): void {
let content = readFileSync(schemaPath, 'utf-8');
// Replace $schema URL
content = content.replace(
/http:\/\/json-schema\.org\/draft-07\/schema#/g,
'https://json-schema.org/draft/2020-12/schema'
);
// Replace "definitions": with "$defs":
content = content.replace(
/"definitions":/g,
'"$defs":'
);
// Replace #/definitions/ with #/$defs/
content = content.replace(
/#\/definitions\//g,
'#/$defs/'
);
writeFileSync(schemaPath, content, 'utf-8');
}
/**
* Generate JSON schema for a specific version
*/
async function generateSchema(version: string, check: boolean = false): Promise<boolean> {
const schemaDir = join('schema', version);
const schemaTs = join(schemaDir, 'schema.ts');
const schemaJson = join(schemaDir, 'schema.json');
if (check) {
// Read existing schema
const existingSchema = readFileSync(schemaJson, 'utf-8');
// Generate schema to stdout and capture it
try {
const { stdout: generated } = await execAsync(
`npx typescript-json-schema --defaultNumberType integer --required --skipLibCheck "${schemaTs}" "*"`
);
let expectedSchema = generated;
// Apply transformations for non-legacy schemas
if (!LEGACY_SCHEMAS.includes(version)) {
expectedSchema = expectedSchema.replace(
/http:\/\/json-schema\.org\/draft-07\/schema#/g,
'https://json-schema.org/draft/2020-12/schema'
);
expectedSchema = expectedSchema.replace(/"definitions":/g, '"$defs":');
expectedSchema = expectedSchema.replace(/#\/definitions\//g, '#/$defs/');
}
// Compare
if (existingSchema.trim() !== expectedSchema.trim()) {
console.error(` ✗ Schema ${version} is out of date!`);
return false;
}
console.log(` ✓ Schema ${version} is up to date`);
return true;
} catch (error) {
console.error(`Failed to check schema for ${version}`);
throw error;
}
} else {
// Run typescript-json-schema
try {
await execAsync(
`npx typescript-json-schema --defaultNumberType integer --required --skipLibCheck "${schemaTs}" "*" -o "${schemaJson}"`
);
} catch (error) {
console.error(`Failed to generate schema for ${version}`);
throw error;
}
// Apply transformations for non-legacy schemas
if (!LEGACY_SCHEMAS.includes(version)) {
applyJsonSchema202012Transformations(schemaJson);
}
console.log(` ✓ Generated schema for ${version}`);
return true;
}
}
/**
* Main function
*/
async function main(): Promise<void> {
if (CHECK_MODE) {
console.log('Checking JSON schemas in parallel...\n');
const results = await Promise.all(
ALL_SCHEMAS.map(version => generateSchema(version, true))
);
const allValid = results.every(valid => valid);
console.log();
if (!allValid) {
console.error('Error: Some schemas are out of date. Run: npm run generate:schema:json');
process.exit(1);
} else {
console.log('All schemas are up to date!');
}
} else {
console.log('Generating JSON schemas in parallel...\n');
await Promise.all(
ALL_SCHEMAS.map(version => generateSchema(version, false))
);
console.log('\nSchema generation complete!');
console.log(`- (draft-07): ${LEGACY_SCHEMAS.join(', ')}`);
console.log(`- (2020-12): ${MODERN_SCHEMAS.join(', ')}`);
}
}
main().catch(error => {
console.error('Schema generation failed:', error);
process.exit(1);
});