Skip to content

Commit 73d5bc9

Browse files
committed
feat: Create script for generating .ts json fixtures
1 parent 43486d9 commit 73d5bc9

File tree

3 files changed

+198
-0
lines changed

3 files changed

+198
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { loadTestCaseFixture } from "../loadTestCaseFixture";
2+
import { loadYamlFiles } from "./loadYamlFiles";
3+
4+
export interface LoadAndProcessFixturesOptions {
5+
fixturesDir: string;
6+
allowList?: string[];
7+
deps: {
8+
fs: any;
9+
path: any;
10+
yaml: any;
11+
};
12+
}
13+
14+
/**
15+
* Loads YAML test case files from a directory, processes them into fixtures, and returns an array of processed test case data.
16+
* Optionally filters which files to load using an allow list.
17+
*
18+
* @param {Object} options - Options for loading and processing fixtures.
19+
* @param {string} options.fixturesDir - Directory containing YAML fixture files.
20+
* @param {string[]=} options.allowList - Optional list of filenames to include.
21+
* @returns {Promise<any[]>} Array of processed test case data, each with a `raw` property containing the original YAML object.
22+
*/
23+
export async function loadAndProcessFixtures({
24+
fixturesDir,
25+
allowList,
26+
deps,
27+
}: LoadAndProcessFixturesOptions) {
28+
const fixtures = await loadYamlFiles({
29+
dir: fixturesDir,
30+
deps,
31+
allowList,
32+
});
33+
const data_errors: any[] = [];
34+
35+
const data = (
36+
await Promise.all(
37+
fixtures.map(async (val: any) => {
38+
try {
39+
const fixture = await loadTestCaseFixture(val);
40+
return { ...fixture, raw: val };
41+
} catch (err) {
42+
console.error(err);
43+
data_errors.push(val);
44+
return null;
45+
}
46+
})
47+
)
48+
).filter((test: any) => test != null);
49+
50+
if (data_errors.length > 0) {
51+
console.error("data errors:", data_errors);
52+
}
53+
54+
return data;
55+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
export type LoadYamlFilesArgs = {
2+
dir: string;
3+
deps: {
4+
fs: any;
5+
path: any;
6+
yaml: any;
7+
};
8+
allowList?: string[];
9+
};
10+
11+
/**
12+
* Loads YAML files from a directory, optionally filtering by an allow list.
13+
* @param args Object containing dir, deps, and optional allowList
14+
* @returns Array of parsed YAML objects, each with a filename property
15+
*/
16+
export async function loadYamlFiles(args: LoadYamlFilesArgs) {
17+
const { dir, deps, allowList } = args;
18+
const { fs, path, yaml } = deps;
19+
// Use dir as-is, since it is already absolute
20+
const directoryPath = dir;
21+
const files = fs.readdirSync(directoryPath);
22+
const data: any[] = [];
23+
24+
files.forEach((file: string) => {
25+
if (
26+
path.extname(file) === ".yml" &&
27+
(!allowList || allowList.includes(file))
28+
) {
29+
try {
30+
const filePath = path.join(directoryPath, file);
31+
const fileContents = fs.readFileSync(filePath, "utf8");
32+
const yamlData: any = yaml.load(fileContents);
33+
yamlData.filename = file;
34+
data.push(yamlData);
35+
} catch {
36+
console.error("File load failure", file);
37+
}
38+
}
39+
});
40+
41+
return data;
42+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env ts-node
2+
3+
// scripts/yml-to-json.ts
4+
// Usage: pnpm ts-node scripts/yml-to-json.ts <input-folder> <output-folder> [--destructive]
5+
6+
import fs from "fs";
7+
import path from "path";
8+
import yaml from "js-yaml";
9+
import { loadAndProcessFixtures } from "../processFixtures/loadAndProcessFixtures";
10+
11+
console.log("[yml-to-json] Begin");
12+
13+
if (process.argv.length < 4) {
14+
console.error(
15+
"Usage: pnpm ts-node scripts/yml-to-json.ts <input-folder> <output-folder> [--destructive]",
16+
);
17+
process.exit(1);
18+
}
19+
20+
const inputDir = path.resolve(process.argv[2]);
21+
const outputDir = path.resolve(process.argv[3]);
22+
const outputSubdir = process.argv[4];
23+
let outputLanguagesDir: string | undefined = undefined;
24+
if (outputSubdir) {
25+
outputLanguagesDir = path.join(outputDir, outputSubdir);
26+
if (!fs.existsSync(outputLanguagesDir)) {
27+
fs.mkdirSync(outputLanguagesDir, { recursive: true });
28+
}
29+
}
30+
31+
if (!fs.existsSync(outputDir)) {
32+
fs.mkdirSync(outputDir, { recursive: true });
33+
}
34+
const isDestructive = process.argv.includes("--destructive");
35+
36+
if (fs.existsSync(outputDir) && isDestructive) {
37+
fs.readdirSync(outputDir).forEach((file) => {
38+
const filePath = path.join(outputDir, file);
39+
if (fs.statSync(filePath).isFile()) {
40+
fs.unlinkSync(filePath);
41+
}
42+
});
43+
}
44+
45+
/**
46+
* Groups processed fixtures by language
47+
*/
48+
function groupFixturesByLanguage(processedFixtures: Array<{ language: string; processed: any }>): Record<string, any[]> {
49+
const languageMap: Record<string, any[]> = {};
50+
for (const item of processedFixtures) {
51+
if (!item) { continue; }
52+
if (!languageMap[item.language]) { languageMap[item.language] = []; }
53+
languageMap[item.language].push(item.processed);
54+
}
55+
return languageMap;
56+
}
57+
58+
/**
59+
* Writes grouped fixtures to JSON files
60+
*/
61+
function writeLanguageJsonFiles(languageMap: Record<string, any[]>, outputDir: string, debug: boolean): Record<string, number> {
62+
const results: Record<string, number> = {};
63+
Object.entries(languageMap).forEach(([language, fixtures]) => {
64+
const targetDir = outputLanguagesDir || outputDir;
65+
const outputPath = path.join(targetDir, `${language}.ts`);
66+
if (debug) { console.log(`[yml-to-json] Writing ${fixtures.length} fixtures to ${outputPath}`); }
67+
fs.writeFileSync(outputPath, `export default ${JSON.stringify(fixtures, null, 2)};\n`);
68+
results[language] = fixtures.length;
69+
if (debug) { console.log(`Wrote ${fixtures.length} fixtures to ${outputPath}`); }
70+
});
71+
return results;
72+
}
73+
74+
const deps = { fs, path, yaml };
75+
76+
async function main() {
77+
console.log("🦋 [main] being:");
78+
const debug = false;
79+
const fixtures = await loadAndProcessFixtures({
80+
fixturesDir: inputDir,
81+
allowList: undefined,
82+
deps
83+
});
84+
if (debug) { console.log("🦋 processedFixtures:", JSON.stringify(fixtures, null, 2)); }
85+
const languageMap = groupFixturesByLanguage(
86+
fixtures.map((fixture: any) => ({
87+
language: fixture.language || "plaintext",
88+
processed: fixture,
89+
}))
90+
);
91+
writeLanguageJsonFiles(languageMap, outputDir, debug);
92+
console.log("🦋 languageMap:");
93+
Object.entries(languageMap).forEach(([key, arr]) => {
94+
console.log(`${key}: ${arr.length}`);
95+
});
96+
}
97+
98+
main().catch((err) => {
99+
console.error(err);
100+
process.exit(1);
101+
});

0 commit comments

Comments
 (0)