diff --git a/src/servers/model/CHANGELOG.md b/src/servers/model/CHANGELOG.md index d522b8879c7e0b8c5a12c8e86b44139757e06d7a..1ed96c27f8f22368e875a638be715eb917d8d7c6 100644 --- a/src/servers/model/CHANGELOG.md +++ b/src/servers/model/CHANGELOG.md @@ -3,6 +3,7 @@ * Swagger UI support. * Response schemas. * Bug fixes. +* Refactored config which can now be provided as a seprate JSON file. # 0.8.0 * Let's call this an initial version. \ No newline at end of file diff --git a/src/servers/model/config.ts b/src/servers/model/config.ts index 7a8c495b59fc609055c4e9e5c628e956e1ec0c1a..819880b3741e37077979cb431dbe93cfc5c22cda 100644 --- a/src/servers/model/config.ts +++ b/src/servers/model/config.ts @@ -1,10 +1,10 @@ /** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> */ -const config = { +const DefaultModelServerConfig = { /** * Determine if and how long to cache entries after a request. */ @@ -50,6 +50,7 @@ const config = { /** * Provide a property config or a path a JSON file with the config. */ + // TODO: finish customProperty support customProperties: <import('./property-provider').ModelPropertyProviderConfig | string>{ sources: [ // 'pdbe', @@ -79,23 +80,37 @@ const config = { } }, + + /** + * Default source for fileMapping. + */ + defaultSource: 'pdb-cif' as string, + /** - * Maps a request identifier to a filename. + * Maps a request identifier to a filename given a 'source' and 'id' variables. * - * @param source - * Source of the data. - * @param id - * Id provided in the request. + * /static query uses 'pdb-cif' and 'pdb-bcif' source names. */ - mapFile(source: string, id: string) { - switch (source.toLowerCase()) { - case 'pdb': return `e:/test/quick/${id}_updated.cif`; - // case 'pdb': return `e:/test/mol-star/model/out/${id}_updated.bcif`; - // case 'pdb-bcif': return `c:/test/mol-star/model/out/${id}_updated.bcif`; - // case 'pdb-cif': return `c:/test/mol-star/model/out/${id}_updated.cif`; - default: return void 0; - } - } + fileMapping: [ + ['pdb-cif', 'e:/test/quick/${id}_updated.cif'], + // ['pdb-bcif', 'e:/test/quick/${id}.bcif'], + ] as [string, string][] }; -export default config; \ No newline at end of file +export type ModelServerConfig = typeof DefaultModelServerConfig +export const ModelServerConfig = DefaultModelServerConfig + +export let mapSourceAndIdToFilename: (source: string, id: string) => string = () => { + throw new Error('call setupConfig to initialize this function'); +} + +export function setupConfig(cfg?: ModelServerConfig) { + if (cfg) Object.assign(ModelServerConfig, cfg); + if (!ModelServerConfig.fileMapping) return; + + mapSourceAndIdToFilename = new Function('source', 'id', [ + 'switch (source.toLowerCase()) {', + ...ModelServerConfig.fileMapping.map(([source, path]) => `case '${source.toLowerCase()}': return \`${path}\`;`), + '}', + ].join('\n')) as any; +} \ No newline at end of file diff --git a/src/servers/model/property-provider.ts b/src/servers/model/property-provider.ts index d929c30c7320093b85d5b4677fe889fcb7c3b81f..20c1754105d04500f01c79daf11c2d11302f6686 100644 --- a/src/servers/model/property-provider.ts +++ b/src/servers/model/property-provider.ts @@ -6,7 +6,7 @@ import * as fs from 'fs' import { Model } from '../../mol-model/structure'; -import Config from './config'; +import { ModelServerConfig as Config } from './config'; import { ConsoleLogger } from '../../mol-util/console-logger'; // TODO enable dynamic imports again diff --git a/src/servers/model/server.ts b/src/servers/model/server.ts index b227cedac82712a35acedd4774d2bd660bfcbced..f9b966a33d2848b52586f576d70359d260c0b83a 100644 --- a/src/servers/model/server.ts +++ b/src/servers/model/server.ts @@ -1,12 +1,14 @@ /** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> */ import * as express from 'express' import * as compression from 'compression' -import ServerConfig from './config' +import * as fs from 'fs' +import * as argparse from 'argparse' +import { ModelServerConfig as ServerConfig, setupConfig } from './config' import { ConsoleLogger } from '../../mol-util/console-logger'; import { PerformanceMonitor } from '../../mol-util/performance-monitor'; import { initWebApi } from './server/api-web'; @@ -39,34 +41,37 @@ function setupShutdown() { } } -const port = process.env.port || ServerConfig.defaultPort; +const cmdParser = new argparse.ArgumentParser({ + addHelp: true +}); + +cmdParser.addArgument(['--cfg'], { help: 'Config file path.', required: false }); + +interface CmdArgs { + cfg?: string +} + +const cmdArgs = cmdParser.parseArgs() as CmdArgs; function startServer() { let app = express(); app.use(compression(<any>{ level: 6, memLevel: 9, chunkSize: 16 * 16384, filter: () => true })); - // app.get(ServerConfig.appPrefix + '/documentation', (req, res) => { - // res.writeHead(200, { 'Content-Type': 'text/html' }); - // res.write(Documentation.getHTMLDocs(ServerConfig.appPrefix)); - // res.end(); - // }); + const cfg = cmdArgs.cfg ? JSON.parse(fs.readFileSync(cmdArgs.cfg, 'utf8')) : void 0; + setupConfig(cfg); initWebApi(app); - // app.get('*', (req, res) => { - // res.writeHead(200, { 'Content-Type': 'text/html' }); - // res.write(Documentation.getHTMLDocs(ServerConfig.appPrefix)); - // res.end(); - // }); - + const port = process.env.port || ServerConfig.defaultPort; app.listen(port); + + console.log(`Mol* ModelServer ${Version}`); + console.log(``); + console.log(`The server is running on port ${port}.`); + console.log(``); } startServer(); -console.log(`Mol* ModelServer ${Version}`); -console.log(``); -console.log(`The server is running on port ${port}.`); -console.log(``); if (ServerConfig.shutdownParams && ServerConfig.shutdownParams.timeoutMinutes > 0) { setupShutdown(); diff --git a/src/servers/model/server/api-schema.ts b/src/servers/model/server/api-schema.ts index f22f874f1b7725b2b0338be8898e464986cd0c29..c52df819262feffcb32a507b74e2cc7d606a40d1 100644 --- a/src/servers/model/server/api-schema.ts +++ b/src/servers/model/server/api-schema.ts @@ -6,7 +6,7 @@ import VERSION from '../version' import { QueryParamInfo, QueryParamType, QueryDefinition, CommonQueryParamsInfo, QueryList } from './api'; -import ServerConfig from '../config'; +import { ModelServerConfig as ServerConfig } from '../config'; export const shortcutIconLink = `<link rel='shortcut icon' href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAnUExURQAAAMIrHrspHr0oH7soILonHrwqH7onILsoHrsoH7soH7woILwpIKgVokoAAAAMdFJOUwAQHzNxWmBHS5XO6jdtAmoAAACZSURBVDjLxZNRCsQgDAVNXmwb9f7nXZEaLRgXloXOhwQdjMYYwpOLw55fBT46KhbOKhmRR2zLcFJQj8UR+HxFgArIF5BKJbEncC6NDEdI5SatBRSDJwGAoiFDONrEJXWYhGMIcRJGCrb1TOtDahfUuQXd10jkFYq0ViIrbUpNcVT6redeC1+b9tH2WLR93Sx2VCzkv/7NjfABxjQHksGB7lAAAAAASUVORK5CYII=' />` diff --git a/src/servers/model/server/api-web.ts b/src/servers/model/server/api-web.ts index daf1c760bfdd0a6143dbbca45dd7b95305dcb11e..9dd4bb8f096d180c82125dc22b3ff8688479d6b3 100644 --- a/src/servers/model/server/api-web.ts +++ b/src/servers/model/server/api-web.ts @@ -7,7 +7,7 @@ import * as fs from 'fs'; import * as path from 'path'; import * as express from 'express'; -import Config from '../config'; +import { ModelServerConfig as Config, ModelServerConfig, mapSourceAndIdToFilename } from '../config'; import { ConsoleLogger } from '../../../mol-util/console-logger'; import { resolveJob } from './query'; import { JobManager } from './jobs'; @@ -92,7 +92,7 @@ function mapQuery(app: express.Express, queryName: string, queryDefinition: Quer const queryParams = normalizeRestQueryParams(queryDefinition, req.query); const commonParams = normalizeRestCommonParams(req.query); const jobId = JobManager.add({ - sourceId: commonParams.data_source || 'pdb', + sourceId: commonParams.data_source || ModelServerConfig.defaultSource, entryId, queryName: queryName as any, queryParams, @@ -107,7 +107,7 @@ export function initWebApi(app: express.Express) { app.get(makePath('static/:format/:id'), async (req, res) => { const binary = req.params.format === 'bcif'; const id = req.params.id; - const fn = Config.mapFile(binary ? 'pdb-bcif' : 'pdb-cif', id); + const fn = mapSourceAndIdToFilename(binary ? 'pdb-bcif' : 'pdb-cif', id); if (!fn || !fs.existsSync(fn)) { res.status(404); res.end(); diff --git a/src/servers/model/server/cache.ts b/src/servers/model/server/cache.ts index 24cafe58fe172c885ead26fb25a20d398c1a956d..b2978044db48d6ccfecf9a8e441b68c6188ff9c9 100644 --- a/src/servers/model/server/cache.ts +++ b/src/servers/model/server/cache.ts @@ -6,7 +6,7 @@ import { ConsoleLogger } from '../../../mol-util/console-logger' import { LinkedList } from '../../../mol-data/generic'; -import ServerConfig from '../config'; +import { ModelServerConfig as ServerConfig } from '../config'; interface CacheEntry<T> { key: string, diff --git a/src/servers/model/server/query.ts b/src/servers/model/server/query.ts index 7cf76311a85d5ca82ff24496e7bd2a8feb865e02..9bbcf807c932e4ba80520f9f3dc1ec065a77e57c 100644 --- a/src/servers/model/server/query.ts +++ b/src/servers/model/server/query.ts @@ -12,7 +12,7 @@ import { Progress } from '../../../mol-task'; import { now } from '../../../mol-util/now'; import { ConsoleLogger } from '../../../mol-util/console-logger'; import { PerformanceMonitor } from '../../../mol-util/performance-monitor'; -import Config from '../config'; +import { ModelServerConfig as Config } from '../config'; import Version from '../version'; import { Job } from './jobs'; import { createStructureWrapperFromJob, StructureWrapper, resolveStructures } from './structure-wrapper'; diff --git a/src/servers/model/server/structure-wrapper.ts b/src/servers/model/server/structure-wrapper.ts index 596ccd3e31bf4da7c763dff4c2df058d6b4a4f5b..148f3e35aff67a18608c9145de65c5c95b83650a 100644 --- a/src/servers/model/server/structure-wrapper.ts +++ b/src/servers/model/server/structure-wrapper.ts @@ -7,7 +7,7 @@ import { Structure, Model } from '../../../mol-model/structure'; import { PerformanceMonitor } from '../../../mol-util/performance-monitor'; import { Cache } from './cache'; -import Config from '../config'; +import { ModelServerConfig as Config, mapSourceAndIdToFilename } from '../config'; import { CIF, CifFrame, CifBlock } from '../../../mol-io/reader/cif' import * as util from 'util' import * as fs from 'fs' @@ -109,7 +109,7 @@ export async function readDataAndFrame(filename: string, key?: string): Promise< } export async function readStructureWrapper(key: string, sourceId: string | '_local_', entryId: string, propertyProvider: ModelPropertiesProvider | undefined) { - const filename = sourceId === '_local_' ? entryId : Config.mapFile(sourceId, entryId); + const filename = sourceId === '_local_' ? entryId : mapSourceAndIdToFilename(sourceId, entryId); if (!filename) throw new Error(`Cound not map '${key}' to a valid filename.`); if (!fs.existsSync(filename)) throw new Error(`Could not find source file for '${key}'.`);