// (C) 2007-2019 GoodData Corporation import * as fs from "fs"; import { Application } from "express"; import { isPlainObject, values, merge } from "lodash"; import * as bodyParser from "body-parser"; import * as session from "express-session"; import { buildProject } from "../schema/builder"; import { ISchema } from "../schema/model/Schema"; import { IConfig } from "../model/Config"; import { IMockProject } from "../model/MockProject"; import * as bear from "./bear"; import * as webapp from "./webapp"; import * as mockBuilder from "./utils"; import { IEndpoint } from "./Endpoint"; import { tokenExpiration } from "../middleware/tokenExpiration"; export interface IOptions { schema: ISchema[]; config?: IConfig; absolutePathToRootMockFile?: string; suffixOfMockFilesImportedInRootMockFile?: string; getSchema?: (mockObject: any) => ISchema[]; } const defaultConfig: IConfig = { randomSeed: null, pollCount: 5, }; const getSuffix = (str: string, delimiter: string): string => str.split(delimiter).pop(); const getPathsToLoadedModulesWithSuffix = (suffix: string, delimiter: string): string[] => Object.keys(require.cache).filter((path: string) => getSuffix(path, delimiter) === suffix); function reloadModule(module: string, ...submodules: string[]) { submodules.forEach(submodule => { delete require.cache[require.resolve(submodule)]; }); delete require.cache[require.resolve(module)]; return require(module); } export function register(app: Application, options: IOptions): Application { app.use(bodyParser.json({ limit: "50mb" })); app.use( session({ secret: "#sorryjako", resave: false, saveUninitialized: false, }), ); if (options.config && options.config.useTokenExpiration) { app.use( tokenExpiration({ expirationTime: 10000, // in miliseconds publicPaths: ["/gdc/account/login"], }), ); } const projects: IMockProject[] = []; options.schema.forEach(schema => { const endpoints = { ...bear, ...webapp, ...mockBuilder, }; const config: IConfig = { ...defaultConfig, ...options.config, }; const project = buildProject(schema); projects.push(project); values(endpoints) .filter(isPlainObject) .forEach((endpoint: IEndpoint) => endpoint.register(app, project, config)); }); if (options.absolutePathToRootMockFile && options.getSchema) { const pathsToMockFiles = options.suffixOfMockFilesImportedInRootMockFile ? getPathsToLoadedModulesWithSuffix(options.suffixOfMockFilesImportedInRootMockFile, "_") : []; pathsToMockFiles.push(options.absolutePathToRootMockFile); pathsToMockFiles.forEach((pathToMockFile: string) => { fs.watch(pathToMockFile, { encoding: "buffer" }, (_, fileName) => { const newOptions = reloadModule(options.absolutePathToRootMockFile, pathToMockFile); const newProjects = options.getSchema(newOptions).map(buildProject); merge(projects, newProjects); // tslint:disable-next-line:no-console console.log(`Mockfile '${fileName}' was reloaded.`); }); }); } return app; }