Skip to content

Commit 79ad122

Browse files
committed
feat(oxlint/oxfmt): generate config types from json schema
1 parent 75ac90c commit 79ad122

File tree

6 files changed

+292
-35
lines changed

6 files changed

+292
-35
lines changed

apps/oxfmt/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"devDependencies": {
2626
"@types/node": "catalog:",
2727
"execa": "^9.6.0",
28+
"quicktype-core": "catalog:",
2829
"tsdown": "catalog:",
2930
"typescript": "catalog:",
3031
"vitest": "catalog:"

apps/oxfmt/scripts/build.js

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ import { execSync } from "node:child_process";
44
import { copyFileSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
55
import { join } from "node:path";
66

7+
import { quicktype, InputData, JSONSchemaInput, FetchingJSONSchemaStore } from "quicktype-core";
8+
79
const oxfmtDirPath = join(import.meta.dirname, ".."),
8-
distDirPath = join(oxfmtDirPath, "dist");
10+
distDirPath = join(oxfmtDirPath, "dist"),
11+
jsonSchemaPath = join(oxfmtDirPath, "..", "..", "npm/oxfmt/configuration_schema.json");
912

1013
// Modify `bindings.js` to use correct package names
1114
console.log("Modifying bindings.js...");
@@ -28,6 +31,14 @@ for (const filename of readdirSync(join(oxfmtDirPath, "src-js"))) {
2831
if (!filename.endsWith(".node")) continue;
2932
copyFile(join(oxfmtDirPath, "src-js", filename), join(distDirPath, filename));
3033
}
34+
try {
35+
const { lines } = await quicktypeJSONSchema("OxfmtConfig", readFileSync(jsonSchemaPath, "utf8"));
36+
writeFileSync(join(distDirPath, "config.d.ts"), lines.join("\n"));
37+
console.log("Translated oxfmt config JSON schema into TypeScript");
38+
} catch (error) {
39+
console.error("Translating oxfmt config JSON schema into TypeScript failed:", error);
40+
process.exit(1);
41+
}
3142

3243
console.log("Build complete!");
3344

@@ -42,3 +53,29 @@ function copyFile(srcPath, destPath) {
4253
copyFileSync(srcPath, destPath);
4354
console.log(`- Copied ${srcPath.split("/").pop()}`);
4455
}
56+
57+
/**
58+
* Quicktype a JSON schema into a target language.
59+
* @param {string} targetLanguage - The target language to quicktype to.
60+
* @param {string} typeName - The name of the type to quicktype.
61+
* @param {string} jsonSchemaString - The JSON schema string to quicktype.
62+
* @returns {Promise<import('quicktype-core').SerializedRenderResult>} The quicktyped code.
63+
*/
64+
async function quicktypeJSONSchema(typeName, jsonSchemaString) {
65+
const schemaInput = new JSONSchemaInput(new FetchingJSONSchemaStore());
66+
67+
// We could add multiple schemas for multiple types,
68+
// but here we're just making one type from JSON schema.
69+
await schemaInput.addSource({ name: typeName, schema: jsonSchemaString });
70+
71+
const inputData = new InputData();
72+
inputData.addInput(schemaInput);
73+
74+
return await quicktype({
75+
inputData,
76+
lang: "typescript",
77+
rendererOptions: {
78+
"prefer-unions": true,
79+
},
80+
});
81+
}

apps/oxlint/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"jiti": "^2.6.0",
3333
"json-stable-stringify-without-jsonify": "^1.0.1",
3434
"oxc-parser": "^0.99.0",
35+
"quicktype-core": "catalog:",
3536
"rolldown": "catalog:",
3637
"tsdown": "catalog:",
3738
"type-fest": "^5.2.0",

apps/oxlint/scripts/build.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ import { execSync } from "node:child_process";
44
import { copyFileSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
55
import { join } from "node:path";
66

7+
import { quicktype, InputData, JSONSchemaInput, FetchingJSONSchemaStore } from "quicktype-core";
8+
79
const oxlintDirPath = join(import.meta.dirname, ".."),
810
srcDirPath = join(oxlintDirPath, "src-js"),
9-
distDirPath = join(oxlintDirPath, "dist");
11+
distDirPath = join(oxlintDirPath, "dist"),
12+
jsonSchemaPath = join(oxlintDirPath, "..", "..", "npm/oxlint/configuration_schema.json");
1013

1114
// Modify `bindings.js` to use correct package names
1215
console.log("Modifying bindings.js...");
@@ -34,4 +37,35 @@ for (const filename of readdirSync(srcDirPath)) {
3437
copyFileSync(srcPath, join(distDirPath, filename));
3538
}
3639

40+
try {
41+
const { lines } = await quicktypeJSONSchema(
42+
"OxlintConfig",
43+
readFileSync(jsonSchemaPath, "utf8"),
44+
);
45+
writeFileSync(join(distDirPath, "config.d.ts"), lines.join("\n"));
46+
console.log("Translated oxlint config JSON schema into TypeScript");
47+
} catch (error) {
48+
console.error("Translating oxlint config JSON schema into TypeScript failed:", error);
49+
process.exit(1);
50+
}
51+
3752
console.log("Build complete!");
53+
54+
async function quicktypeJSONSchema(typeName: string, jsonSchemaString: string) {
55+
const schemaInput = new JSONSchemaInput(new FetchingJSONSchemaStore());
56+
57+
// We could add multiple schemas for multiple types,
58+
// but here we're just making one type from JSON schema.
59+
await schemaInput.addSource({ name: typeName, schema: jsonSchemaString });
60+
61+
const inputData = new InputData();
62+
inputData.addInput(schemaInput);
63+
64+
return await quicktype({
65+
inputData,
66+
lang: "typescript",
67+
rendererOptions: {
68+
"prefer-unions": true,
69+
}
70+
});
71+
}

0 commit comments

Comments
 (0)