lib/swagger/fileLoader.ts (94 lines of code) (raw):

import * as path from "path"; import { asyncWriteFile, readFile as vfsReadFile, pathJoin, pathResolve, urlParse, } from "@azure-tools/openapi-tools-common"; import * as fs from "fs-extra"; import { inject, injectable } from "inversify"; import mkdirp from "mkdirp"; import { TYPES } from "../inversifyUtils"; import { checkAndResolveGithubUrl } from "../util/utils"; import { Loader, setDefaultOpts } from "./loader"; export interface FileLoaderOption { fileRoot?: string; checkUnderFileRoot?: boolean; } @injectable() export class FileLoader implements Loader<string> { private preloadCache = new Map<string, string>(); public constructor(@inject(TYPES.opts) private opts: FileLoaderOption) { setDefaultOpts(opts, { checkUnderFileRoot: true, }); if (this.opts.fileRoot) { this.opts.fileRoot = checkAndResolveGithubUrl(pathResolve(this.opts.fileRoot)); } } public async load(filePath: string) { filePath = this.resolvePath(filePath); const preloadContent = this.preloadCache.get(filePath); if (preloadContent !== undefined) { return preloadContent; } return vfsReadFile(filePath); } public relativePath(filePath: string) { if (this.opts.fileRoot) { filePath = this.resolvePath(filePath); const url = urlParse(filePath); if (url) { const rootUrl = urlParse(this.opts.fileRoot); filePath = rootUrl === undefined ? filePath : path.relative(rootUrl.path, url.path); } else { filePath = path.relative(this.opts.fileRoot, filePath); } } return filePath; } public resolvePath(filePath: string) { const url = urlParse(filePath); if (url) { filePath = checkAndResolveGithubUrl(filePath); } else if (!path.isAbsolute(filePath)) { filePath = this.opts.fileRoot ? pathJoin(this.opts.fileRoot, filePath) : path.resolve(filePath); } if ( this.opts.fileRoot && this.opts.checkUnderFileRoot && !filePath.startsWith(this.opts.fileRoot) ) { throw new Error( `Try to load file "${filePath}" outside of root folder ${this.opts.fileRoot}` ); } return filePath; } public isUnderFileRoot(filePath: string) { if (!this.opts.fileRoot) { return true; } if (path.isAbsolute(filePath) && !filePath.startsWith(this.opts.fileRoot)) { return false; } filePath = pathJoin(this.opts.fileRoot, filePath); return filePath.startsWith(this.opts.fileRoot); } public async writeFile(filePath: string, content: string) { filePath = this.resolvePath(filePath); await mkdirp(path.dirname(filePath)); return asyncWriteFile(filePath, content); } public async appendFile(filePath: string, content: string) { filePath = this.resolvePath(filePath); await fs.appendFile(filePath, content); } public preloadExtraFile(filePath: string, content: string) { filePath = this.resolvePath(filePath); this.preloadCache.set(filePath, content); } }