packages/quicktype-typescript-input/src/index.ts (69 lines of code) (raw):
import * as ts from "typescript";
import { PartialArgs, generateSchema } from "@mark.probst/typescript-json-schema";
import { defined, JSONSchemaSourceData, messageError } from "quicktype-core";
const settings: PartialArgs = {
required: true,
titles: true,
topRef: true,
noExtraProps: true
};
const compilerOptions: ts.CompilerOptions = {
noEmit: true,
emitDecoratorMetadata: true,
experimentalDecorators: true,
target: ts.ScriptTarget.ES5,
module: ts.ModuleKind.CommonJS,
strictNullChecks: true,
typeRoots: [],
rootDir: "."
};
// FIXME: We're stringifying and then parsing this schema again. Just pass around
// the schema directly.
export function schemaForTypeScriptSources(sourceFileNames: string[]): JSONSchemaSourceData {
const program = ts.createProgram(sourceFileNames, compilerOptions);
const diagnostics = ts.getPreEmitDiagnostics(program);
const error = diagnostics.find(d => d.category === ts.DiagnosticCategory.Error);
if (error !== undefined) {
return messageError("TypeScriptCompilerError", {
message: ts.flattenDiagnosticMessageText(error.messageText, "\n")
});
}
const schema = generateSchema(program, "*", settings);
const uris: string[] = [];
let topLevelName: string | undefined = undefined;
if (schema !== null && typeof schema === "object" && typeof schema.definitions === "object") {
for (const name of Object.getOwnPropertyNames(schema.definitions)) {
const definition = schema.definitions[name];
if (
definition === null ||
Array.isArray(definition) ||
typeof definition !== "object" ||
typeof definition.description !== "string"
) {
continue;
}
const description = definition.description as string;
const matches = description.match(/#TopLevel/);
if (matches === null) {
continue;
}
const index = defined(matches.index);
definition.description = description.slice(0, index) + description.slice(index + matches[0].length);
uris.push(`#/definitions/${name}`);
if (topLevelName === undefined) {
if (typeof definition.title === "string") {
topLevelName = definition.title;
} else {
topLevelName = name;
}
} else {
topLevelName = "";
}
}
}
if (uris.length === 0) {
uris.push("#/definitions/");
}
if (topLevelName === undefined) {
topLevelName = "";
}
return { schema: JSON.stringify(schema), name: topLevelName, uris, isConverted: true };
}