glideapps / quicktype

Generate types and converters from JSON, Schema, and GraphQL
https://app.quicktype.io
Apache License 2.0
12.43k stars 1.08k forks source link

Another example for programmatic usage #1511

Closed GavinRay97 closed 4 years ago

GavinRay97 commented 4 years ago

I have been using this and thought I might leave it here in case others might benefit from it. The tricky part was that you absolutely need the definition path ("#/definitions/") in typeName or it won't work at all, and rendererOptions I had to do a bit of digging to find how to use.

Install the quicktype packages and then run with ts-node filename.ts after changing files value to point to your files :+1:

import fs from "fs"
import { schemaForTypeScriptSources } from "quicktype-typescript-input"
import {
  quicktype,
  InputData,
  JSONSchemaInput,
  JSONSchemaStore,
  RendererOptions,
} from "quicktype-core"

interface typegenOptions {
  lang: string
  typeName: string
  files: string[]
  rendererOptions?: RendererOptions
}

async function typescriptTypesTo(options: typegenOptions) {
  const { lang, rendererOptions, typeName, files } = options
  const { schema } = schemaForTypeScriptSources(files)
  //@ts-ignore
  const schemaInput = new JSONSchemaInput(new JSONSchemaStore())
  await schemaInput.addSource({ name: typeName, schema })
  const inputData = new InputData()
  inputData.addInput(schemaInput)
  return quicktype({ inputData, rendererOptions, lang })
}

/**
 * CONFIG
 */

const ALL_TYPES = "#/definitions/"
const files = ["./myTSTypes.ts"]

interface LanguageEntry {
  [key: string]: {
    outfile: string
    rendererOptions?: RendererOptions
  }
}

const languages: LanguageEntry = {
  python: {
    outfile: "my_sdk.py",
    rendererOptions: {
      "python-version": "3.7"
    },
  },
  java: {
    outfile: "MySdk.java",
    rendererOptions: {
      package: "org.my.sdk",
    },
  },
  kotlin: {
    outfile: "MySdk.kt",
    rendererOptions: {
      framework: "kotlinx",
      package: "org.my.sdk",
    },
  },
  go: {
    outfile: "my_sdk.go",
    rendererOptions: {
      package: "my_sdk",
    },
  },
  ruby: { outfile: "my_sdk.rb" },
  csharp: { outfile: "MySdk.cs" },
  rust: { outfile: "my_sdk.rs" },
  schema: { outfile: "mySdk.schema.json" },
}

async function main() {
  for (let lang in languages) {
    console.log("Generating types for language:", lang)
    const { outfile, rendererOptions } = languages[lang]

    const params = { lang, files, rendererOptions, typeName: ALL_TYPES }
    const result = await typescriptTypesTo(params)

    const text = result.lines.join("\n")
    const path = `./generated/${outfile}`

    fs.writeFileSync(path, text, "utf-8")
    console.log("Wrote to:", path, "\n")
  }
}

main()
dvdsgl commented 4 years ago

Thanks!

kmturley commented 8 months ago

Here is another example using TypeScript input:

import { mkdirSync, writeFileSync } from 'fs';
import { globSync } from 'glob';
import { dirname } from 'path';
import { InputData, JSONSchemaInput, JSONSchemaSourceData, JSONSchemaStore, RendererOptions, SerializedRenderResult, quicktype } from 'quicktype-core';
import { schemaForTypeScriptSources } from 'quicktype-typescript-input';

interface Config {
  lang: string;
  ext: string;
  rendererOptions: RendererOptions
}

async function load(globPath: string, configs: Config[]) {
  const filePaths: string[] = globSync(globPath);
  console.log(`📁 ${filePaths}`);
  const jsonSchema: JSONSchemaSourceData = schemaForTypeScriptSources(filePaths);
  // @ts-ignore
  const jsonStore: JSONSchemaStore = new JSONSchemaStore();
  const jsonInput: JSONSchemaInput = new JSONSchemaInput(jsonStore);
  await jsonInput.addSource({ name: '#/definitions/', schema: jsonSchema.schema });
  const inputData: InputData = new InputData();
  inputData.addInput(jsonInput);
  for (let i = 0; i < configs.length; i++) {
    const { lang, ext, rendererOptions } = configs[i];
    const result: SerializedRenderResult = await quicktype({ inputData, rendererOptions, lang });
    createFile(`./dist/${lang}/types.${ext}`, result.lines.join('\n'));
  }
}

function createFile(filePath: string, fileContents: string) {
  mkdirSync(dirname(filePath), { recursive: true });
  writeFileSync(filePath, fileContents);
  console.log(`+ ${filePath}`);
}

load('./src/**/*.ts', [
  { lang: 'java', ext: 'java', rendererOptions: { "just-types": true } },
  { lang: 'schema', ext: 'json', rendererOptions: { "just-types": true } },
  { lang: 'ts', ext: 'ts', rendererOptions: { "just-types": true } }
]);

You can see the full source code here: https://github.com/kmturley/quicktype-typescript-input-demo/