diff options
Diffstat (limited to 'src/shared/settings/Search.ts')
-rw-r--r-- | src/shared/settings/Search.ts | 68 |
1 files changed, 25 insertions, 43 deletions
diff --git a/src/shared/settings/Search.ts b/src/shared/settings/Search.ts index 4580236..bdbe4a8 100644 --- a/src/shared/settings/Search.ts +++ b/src/shared/settings/Search.ts @@ -1,3 +1,22 @@ +import Validator from './Validator'; + +const Schema = { + type: 'object', + properties: { + default: { type: 'string' }, + engines: { + type: 'object', + propertyNames: { + pattern: '^[A-Za-z_][A-Za-z0-9_]+$', + }, + patternProperties: { + '.*': { type: 'string' }, + }, + }, + }, + required: ['default'], +}; + type Entries = { [name: string]: string }; export type SearchJSON = { @@ -12,19 +31,10 @@ export default class Search { ) { } - static fromJSON(json: any): Search { - let defaultEngine = Search.getStringField(json, 'default'); - let engines = Search.getObjectField(json, 'engines'); + static fromJSON(json: unknown): Search { + let obj = new Validator<SearchJSON>(Schema).validate(json); - for (let [name, url] of Object.entries(engines)) { - if ((/\s/).test(name)) { - throw new TypeError( - `While space in the search engine not allowed: "${name}"`); - } - if (typeof url !== 'string') { - throw new TypeError( - `Invalid type of value in filed "engines": ${JSON.stringify(json)}`); - } + for (let [name, url] of Object.entries(obj.engines)) { let matches = url.match(/{}/g); if (matches === null) { throw new TypeError(`No {}-placeholders in URL of "${name}"`); @@ -32,15 +42,11 @@ export default class Search { throw new TypeError(`Multiple {}-placeholders in URL of "${name}"`); } } - - if (!Object.keys(engines).includes(defaultEngine)) { - throw new TypeError(`Default engine "${defaultEngine}" not found`); + if (!Object.keys(obj.engines).includes(obj.default)) { + throw new TypeError(`Default engine "${obj.default}" not found`); } - return new Search( - json.default as string, - json.engines, - ); + return new Search(obj.default, obj.engines); } toJSON(): SearchJSON { @@ -49,28 +55,4 @@ export default class Search { engines: this.engines, }; } - - private static getStringField(json: any, name: string): string { - if (!Object.prototype.hasOwnProperty.call(json, name)) { - throw new TypeError( - `missing field "${name}" on search: ${JSON.stringify(json)}`); - } - if (typeof json[name] !== 'string') { - throw new TypeError( - `invalid type of filed "${name}" on search: ${JSON.stringify(json)}`); - } - return json[name]; - } - - private static getObjectField(json: any, name: string): Object { - if (!Object.prototype.hasOwnProperty.call(json, name)) { - throw new TypeError( - `missing field "${name}" on search: ${JSON.stringify(json)}`); - } - if (typeof json[name] !== 'object' || json[name] === null) { - throw new TypeError( - `invalid type of filed "${name}" on search: ${JSON.stringify(json)}`); - } - return json[name]; - } } |