Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

watcher mode #591

Open
jonnytest1 opened this issue Feb 21, 2024 · 0 comments
Open

watcher mode #591

jonnytest1 opened this issue Feb 21, 2024 · 0 comments

Comments

@jonnytest1
Copy link

jonnytest1 commented Feb 21, 2024

i'Ve seen that your implemenation always loads the entire program source each time a schema is generated (including all the node_modules types)
so in order to decrease the time it takes to generate a schema ive therefore made the follwing class to asycnhronously load new SourceFiles

just ognna drop this here in case it seems useful (PS: it seems getTypeDefinition and reffedDefinitions is private :/ i think protected might be best )

import { Node, Program, SyntaxKind, TypeFormatFlags, forEachChild, Symbol as TSSymbol, SourceFile, Type } from 'typescript';
import { Args, JsonSchemaGenerator, SymbolRef, getDefaultArgs } from 'typescript-json-schema';
import { relative } from "path"


export class JsonSchemaWatcher {

  typeChecker = this.program.getTypeChecker()

  symbols: Array<SymbolRef> = []

  allTypes: Record<string, Type> = {}

  userSymbols: Record<string, TSSymbol> = {}

  inheritingTypes: Record<string, Array<string>> = {}
  workingDir: string;
  settings: Args;
  constructor(private program: Program) {

    this.workingDir = this.program.getCurrentDirectory();
  }

  isUserFile(file: SourceFile) {
    return !file.fileName.includes("node_modules")
  }

  buildWatchGenerator(args: Args) {
    this.settings = getDefaultArgs()
    for (const pref in args) {
      if (args.hasOwnProperty(pref)) {
        this.settings[pref] = args[pref];
      }
    }
    this.program.getSourceFiles().forEach((sourceFile: SourceFile & { relativePath?: string }) => {
      this.addSourceFile(sourceFile)
      const relativePath = relative(this.workingDir, sourceFile.fileName);
      sourceFile.relativePath = relativePath
      this.inspect(sourceFile, sourceFile);
    });
    return new JsonSchemaGenerator(this.symbols, this.allTypes, this.userSymbols, this.inheritingTypes, this.typeChecker, this.settings);
  }

  inspect(node: Node, sourceFile: SourceFile & { relativePath?: string }) {
    const tc = this.typeChecker
    if (node.kind === SyntaxKind.ClassDeclaration ||
      node.kind === SyntaxKind.InterfaceDeclaration ||
      node.kind === SyntaxKind.EnumDeclaration ||
      node.kind === SyntaxKind.TypeAliasDeclaration) {
      //@ts-ignore
      const symbol = node.symbol as TSSymbol;
      const nodeType = tc.getTypeAtLocation(node);
      const fullyQualifiedName = tc.getFullyQualifiedName(symbol);
      const typeName = fullyQualifiedName.replace(/".*"\./, "");

      const name_1 = typeName;
      this.symbols.push({ name: name_1, typeName: typeName, fullyQualifiedName: fullyQualifiedName, symbol: symbol });
      if (!this.userSymbols[name_1]) {
        this.allTypes[name_1] = nodeType;
      }
      if (this.isUserFile(sourceFile)) {
        this.userSymbols[name_1] = symbol;
      }
      const baseTypes = nodeType.getBaseTypes() || [];
      baseTypes.forEach((baseType) => {
        const baseName = tc.typeToString(baseType, undefined, TypeFormatFlags.UseFullyQualifiedType);
        if (!this.inheritingTypes[baseName]) {
          this.inheritingTypes[baseName] = [];
        }
        this.inheritingTypes[baseName].push(name_1);
      });
    }
    else {
      forEachChild(node, (n) => this.inspect(n, sourceFile));
    }
  }


  addSourceFile(sourceFile: SourceFile & { relativePath?: string }) {
    const relativePath = relative(this.workingDir, sourceFile.fileName);
    sourceFile.relativePath = relativePath
    this.inspect(sourceFile, sourceFile);
  }


  getTypeDefinition(typDecl: Type) {
    const schemaGEn = new JsonSchemaGenerator(this.symbols, this.allTypes, this.userSymbols, this.inheritingTypes, this.typeChecker, this.settings);
    //@ts-ignore
    const schema: ExtendedJsonSchema = schemaGEn.getTypeDefinition(typDecl, false, undefined, undefined, undefined, undefined, true)
    //@ts-ignore
    schema.definitions = schemaGEn?.reffedDefinitions

    return schema
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant