fork of hey-api/openapi-ts because I need some additional things
at main 82 lines 2.7 kB view raw
1import path from 'node:path'; 2 3import type { IProjectRenderMeta } from '../extensions'; 4import { FileRegistry } from '../files/registry'; 5import { defaultExtensions } from '../languages/extensions'; 6import { defaultNameConflictResolvers } from '../languages/resolvers'; 7import type { Extensions, NameConflictResolvers } from '../languages/types'; 8import type { AstContext } from '../nodes/context'; 9import { NodeRegistry } from '../nodes/registry'; 10import type { IOutput } from '../output'; 11import { Planner } from '../planner/planner'; 12import { simpleNameConflictResolver } from '../planner/resolvers'; 13import type { NameConflictResolver } from '../planner/types'; 14import type { Renderer } from '../renderer'; 15import { SymbolRegistry } from '../symbols/registry'; 16import type { IProject } from './types'; 17 18export class Project implements IProject { 19 readonly files: FileRegistry; 20 readonly nodes = new NodeRegistry(); 21 readonly symbols = new SymbolRegistry(); 22 23 readonly defaultFileName: string; 24 readonly defaultNameConflictResolver: NameConflictResolver; 25 readonly extensions: Extensions; 26 readonly fileName?: (name: string) => string; 27 readonly nameConflictResolvers: NameConflictResolvers; 28 readonly renderers: ReadonlyArray<Renderer>; 29 readonly root: string; 30 31 constructor( 32 args: Pick< 33 Partial<IProject>, 34 | 'defaultFileName' 35 | 'defaultNameConflictResolver' 36 | 'extensions' 37 | 'fileName' 38 | 'nameConflictResolvers' 39 | 'renderers' 40 > & 41 Pick<IProject, 'root'>, 42 ) { 43 const fileName = args.fileName; 44 this.defaultFileName = args.defaultFileName ?? 'main'; 45 this.defaultNameConflictResolver = 46 args.defaultNameConflictResolver ?? simpleNameConflictResolver; 47 this.extensions = { 48 ...defaultExtensions, 49 ...args.extensions, 50 }; 51 this.fileName = typeof fileName === 'string' ? () => fileName : fileName; 52 this.files = new FileRegistry(this); 53 this.nameConflictResolvers = { 54 ...defaultNameConflictResolvers, 55 ...args.nameConflictResolvers, 56 }; 57 this.renderers = args.renderers ?? []; 58 this.root = path.resolve(args.root).replace(/[/\\]+$/, ''); 59 } 60 61 render(meta?: IProjectRenderMeta): ReadonlyArray<IOutput> { 62 new Planner(this).plan(meta); 63 const files: Array<IOutput> = []; 64 const astContext: AstContext = { 65 getAccess(node) { 66 return node; 67 }, 68 }; 69 for (const file of this.files.registered()) { 70 if (file.finalPath && file.renderer) { 71 const content = file.renderer.render({ 72 astContext, 73 file, 74 meta, 75 project: this, 76 }); 77 files.push({ content, path: file.finalPath }); 78 } 79 } 80 return files; 81 } 82}