refactor: adjust to new tslint settings

This commit is contained in:
Karl-Philipp Wulfert
2019-06-04 14:02:55 +02:00
committed by Rainer Killinger
parent 6ffa4efbaf
commit b621a12689
44 changed files with 520 additions and 100305 deletions

View File

@@ -57,7 +57,7 @@ package:
- secrecy
stage: deploy
script:
- echo "//registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN" > /root/.npmrc
- echo "//registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN" > ~/.npmrc
- npm publish
only:
- /^v[0-9]+.[0-9]+.[0-9]+$/

143
package-lock.json generated
View File

@@ -146,27 +146,62 @@
"dev": true
},
"@openstapps/configuration": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/@openstapps/configuration/-/configuration-0.16.0.tgz",
"integrity": "sha512-wnaSjxP0NZcK3Ke1eG/19rwChbCjLn+UCo2SsU4QN35MgyUUci/Y/4/v1kKxznHL7VWlx0bW3cLxCVvNtBMw7w==",
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/@openstapps/configuration/-/configuration-0.18.0.tgz",
"integrity": "sha512-Ufi3jzCozVqCymNeaeRzuOHO2Yd5qXJ10uF4xNHk6Q4LFD9NAMMBkYbawkjmecZoNR+Llqs4AnwSxIkuEAxcxA==",
"dev": true,
"requires": {
"@types/node": "10.14.4",
"@types/node": "10.14.7",
"@types/semver": "6.0.0",
"@types/yaml": "1.0.2",
"chalk": "2.4.2",
"commander": "2.20.0",
"semver": "6.0.0",
"semver": "6.1.0",
"tslint": "5.16.0",
"tslint-eslint-rules": "5.4.0",
"yaml": "1.5.0"
"yaml": "1.6.0"
},
"dependencies": {
"@types/node": {
"version": "10.14.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.4.tgz",
"integrity": "sha512-DT25xX/YgyPKiHFOpNuANIQIVvYEwCWXgK2jYYwqgaMrYE6+tq+DtmMwlD3drl6DJbUwtlIDnn0d7tIn/EbXBg==",
"version": "10.14.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.7.tgz",
"integrity": "sha512-on4MmIDgHXiuJDELPk1NFaKVUxxCFr37tm8E9yN6rAiF5Pzp/9bBfBHkoexqRiY+hk/Z04EJU9kKEb59YqJ82A==",
"dev": true
},
"semver": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.1.0.tgz",
"integrity": "sha512-kCqEOOHoBcFs/2Ccuk4Xarm/KiWRSLEX9CAZF8xkJ6ZPlIoTZ8V5f7J16vYLJqDbR7KrxTJpR2lqjIEm2Qx9cQ==",
"dev": true
},
"tslint": {
"version": "5.16.0",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.16.0.tgz",
"integrity": "sha512-UxG2yNxJ5pgGwmMzPMYh/CCnCnh0HfPgtlVRDs1ykZklufFBL1ZoTlWFRz2NQjcoEiDoRp+JyT0lhBbbH/obyA==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"builtin-modules": "^1.1.1",
"chalk": "^2.3.0",
"commander": "^2.12.1",
"diff": "^3.2.0",
"glob": "^7.1.1",
"js-yaml": "^3.13.0",
"minimatch": "^3.0.4",
"mkdirp": "^0.5.1",
"resolve": "^1.3.2",
"semver": "^5.3.0",
"tslib": "^1.8.0",
"tsutils": "^2.29.0"
},
"dependencies": {
"semver": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
"dev": true
}
}
}
}
},
@@ -241,32 +276,45 @@
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"ts-node": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.1.0.tgz",
"integrity": "sha512-34jpuOrxDuf+O6iW1JpgTRDFynUZ1iEqtYruBqh35gICNjN8x+LpVcPAcwzLPi9VU6mdA3ym+x233nZmZp445A==",
"dev": true,
"requires": {
"arg": "^4.1.0",
"diff": "^3.1.0",
"make-error": "^1.1.1",
"source-map-support": "^0.5.6",
"yn": "^3.0.0"
}
}
}
},
"@openstapps/logger": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/@openstapps/logger/-/logger-0.1.0.tgz",
"integrity": "sha512-5z7Yf3WrzayEVNPp1TBoGiCVgPlQtqzOFh0yQ06gac/vFedWLPLBmENGDdRoEKar8bXzghkxDLy6Rvj/8HEQaQ==",
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@openstapps/logger/-/logger-0.2.1.tgz",
"integrity": "sha512-6+F1nxEBuNTrd3hhBxKnvkH8B84HvB/dVmoMP9Pmv2g3mL3pYJ9l2BBGaACDRA7oUCyLpbNQw+4Kf+VdyzOttw==",
"dev": true,
"requires": {
"@types/node": "10.14.6",
"@types/nodemailer": "4.6.8",
"@types/node": "10.14.7",
"@types/nodemailer": "6.1.0",
"chalk": "2.4.2",
"flatted": "2.0.0",
"nodemailer": "6.1.1"
},
"dependencies": {
"@types/node": {
"version": "10.14.6",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.6.tgz",
"integrity": "sha512-Fvm24+u85lGmV4hT5G++aht2C5I4Z4dYlWZIh62FAfFO/TfzXtPpoLI6I7AuBWkIFqZCnhFOoTT7RjjaIL5Fjg==",
"version": "10.14.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.7.tgz",
"integrity": "sha512-on4MmIDgHXiuJDELPk1NFaKVUxxCFr37tm8E9yN6rAiF5Pzp/9bBfBHkoexqRiY+hk/Z04EJU9kKEb59YqJ82A==",
"dev": true
},
"@types/nodemailer": {
"version": "4.6.8",
"resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-4.6.8.tgz",
"integrity": "sha512-IX1P3bxDP1VIdZf6/kIWYNmSejkYm9MOyMEtoDFi4DVzKjJ3kY4GhOcOAKs6lZRjqVVmF9UjPOZXuQczlpZThw==",
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.1.0.tgz",
"integrity": "sha512-WysSJ4sGW2Aum1Cs6HFosZdlR3WUzX0XoSLsI53q77gLd4wDfE84OXffZu5/nLIjeKh4SwfTsdrKsgBL9WowMA==",
"dev": true,
"requires": {
"@types/node": "*"
@@ -374,9 +422,9 @@
"dev": true
},
"@types/node": {
"version": "10.14.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.7.tgz",
"integrity": "sha512-on4MmIDgHXiuJDELPk1NFaKVUxxCFr37tm8E9yN6rAiF5Pzp/9bBfBHkoexqRiY+hk/Z04EJU9kKEb59YqJ82A=="
"version": "10.14.8",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.8.tgz",
"integrity": "sha512-I4+DbJEhLEg4/vIy/2gkWDvXBOOtPKV9EnLhYjMoqxcRW+TTZtUftkHktz/a8suoD5mUL7m6ReLrkPvSsCQQmw=="
},
"@types/nodemailer": {
"version": "4.6.5",
@@ -1733,6 +1781,11 @@
"integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==",
"dev": true
},
"http-status-codes": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-1.3.2.tgz",
"integrity": "sha512-nDUtj0ltIt08tGi2VWSpSzNNFye0v3YSe9lX3lIqLTuVvvRiYCvs4QQBSHo0eomFYw1wlUuofurUAlTm+vHnXg=="
},
"humanize-string": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/humanize-string/-/humanize-string-2.1.0.tgz",
@@ -3565,16 +3618,24 @@
}
},
"ts-node": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.1.0.tgz",
"integrity": "sha512-34jpuOrxDuf+O6iW1JpgTRDFynUZ1iEqtYruBqh35gICNjN8x+LpVcPAcwzLPi9VU6mdA3ym+x233nZmZp445A==",
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.2.0.tgz",
"integrity": "sha512-m8XQwUurkbYqXrKqr3WHCW310utRNvV5OnRVeISeea7LoCWVcdfeB/Ntl8JYWFh+WRoUAdBgESrzKochQt7sMw==",
"dev": true,
"requires": {
"arg": "^4.1.0",
"diff": "^3.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"source-map-support": "^0.5.6",
"yn": "^3.0.0"
},
"dependencies": {
"diff": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz",
"integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==",
"dev": true
}
}
},
"ts-optchain": {
@@ -3589,9 +3650,9 @@
"dev": true
},
"tslint": {
"version": "5.16.0",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.16.0.tgz",
"integrity": "sha512-UxG2yNxJ5pgGwmMzPMYh/CCnCnh0HfPgtlVRDs1ykZklufFBL1ZoTlWFRz2NQjcoEiDoRp+JyT0lhBbbH/obyA==",
"version": "5.17.0",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.17.0.tgz",
"integrity": "sha512-pflx87WfVoYepTet3xLfDOLDm9Jqi61UXIKePOuca0qoAZyrGWonDG9VTbji58Fy+8gciUn8Bt7y69+KEVjc/w==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
@@ -3600,7 +3661,7 @@
"commander": "^2.12.1",
"diff": "^3.2.0",
"glob": "^7.1.1",
"js-yaml": "^3.13.0",
"js-yaml": "^3.13.1",
"minimatch": "^3.0.4",
"mkdirp": "^0.5.1",
"resolve": "^1.3.2",
@@ -3635,9 +3696,9 @@
"dev": true
},
"tsutils": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.10.0.tgz",
"integrity": "sha512-q20XSMq7jutbGB8luhKKsQldRKWvyBO2BGqni3p4yq8Ys9bEP/xQw3KepKmMRt9gJ4lvQSScrihJrcKdKoSU7Q==",
"version": "3.13.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.13.0.tgz",
"integrity": "sha512-wRtEjVU8Su72sDIDoqno5Scwt8x4eaF0teKO3m4hu8K1QFPnIZMM88CLafs2tapUeWnY9SwwO3bWeOt2uauBcg==",
"dev": true,
"requires": {
"tslib": "^1.8.1"
@@ -3700,9 +3761,9 @@
"dev": true
},
"typescript": {
"version": "3.4.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.5.tgz",
"integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==",
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.1.tgz",
"integrity": "sha512-64HkdiRv1yYZsSe4xC1WVgamNigVYjlssIoaH2HcZF0+ijsk5YK2g0G34w9wJkze8+5ow4STd22AynfO6ZYYLw==",
"dev": true
},
"uglify-js": {
@@ -3872,12 +3933,12 @@
"dev": true
},
"yaml": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.5.0.tgz",
"integrity": "sha512-nKxSWOa7vxAP2pikrGxbkZsG/garQseRiLn9mIDjzwoQsyVy7ZWIpLoARejnINGGLA4fttuzRFFNxxbsztdJgw==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.6.0.tgz",
"integrity": "sha512-iZfse3lwrJRoSlfs/9KQ9iIXxs9++RvBFVzAqbbBiFT+giYtyanevreF9r61ZTbGMgWQBxAua3FzJiniiJXWWw==",
"dev": true,
"requires": {
"@babel/runtime": "^7.4.3"
"@babel/runtime": "^7.4.5"
}
},
"yargs": {

View File

@@ -20,10 +20,13 @@
"compile": "rimraf lib && tsc",
"documentation": "typedoc --name \"@openstapps/core\" --includeDeclarations --mode modules --out docs --readme README.md --listInvalidSymbolLinks lib",
"pack": "openstapps-core-tools pack",
"postversion": "npm run changelog",
"prepublishOnly": "npm ci && npm run build",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\"",
"schema": "node --max-old-space-size=8192 --stack-size=10240 ./node_modules/.bin/openstapps-core-tools schema src/core lib/schema",
"test": "nyc mocha --require ts-node/register --require source-map-support/register --ui mocha-typescript test/*.spec.ts",
"tslint": "tslint 'src/**/*.ts'"
"tslint": "tslint -p tsconfig.json -c tslint.json 'src/**/*.ts'"
},
"author": "Karl-Philipp Wulfert <krlwlfrt@gmail.com>",
"contributors": [
@@ -39,17 +42,18 @@
"dependencies": {
"@types/geojson": "1.0.6",
"@types/json-patch": "0.0.30",
"@types/node": "10.14.7",
"@types/node": "10.14.8",
"fast-clone": "1.5.13",
"http-status-codes": "1.3.2",
"json-patch": "0.7.0",
"jsonschema": "1.2.4",
"ts-optchain": "0.1.3"
},
"devDependencies": {
"@krlwlfrt/async-pool": "0.1.0",
"@openstapps/configuration": "0.16.0",
"@openstapps/configuration": "0.18.0",
"@openstapps/core-tools": "0.6.0",
"@openstapps/logger": "0.1.0",
"@openstapps/logger": "0.2.1",
"@types/chai": "4.1.7",
"@types/rimraf": "2.0.2",
"chai": "4.2.0",
@@ -61,10 +65,10 @@
"nyc": "14.1.1",
"rimraf": "2.6.3",
"source-map-support": "0.5.12",
"ts-node": "8.1.0",
"tslint": "5.16.0",
"ts-node": "8.2.0",
"tslint": "5.17.0",
"typedoc": "0.14.2",
"typescript": "3.4.5"
"typescript": "3.5.1"
},
"nyc": {
"check-coverage": true,
@@ -76,7 +80,8 @@
"include": [
"src/core/Route.ts",
"src/core/Thing.ts",
"src/core/Translator.ts"
"src/core/Translator.ts",
"src/core/types/Guards.ts"
],
"exclude": [],
"extension": [

File diff suppressed because it is too large Load Diff

View File

@@ -42,7 +42,7 @@ import {SCVideo, SCVideoMeta, SCVideoWithoutReferences} from './things/Video';
/**
* A map of things, from type to meta data
*/
export const SCClasses: { [K in SCThingType]: any } = {
export const SCClasses: { [K in SCThingType]: object } = {
/* tslint:enable */
'academic event': SCAcademicEventMeta,
'article': SCArticleMeta,

View File

@@ -48,7 +48,8 @@ export enum SCRouteHttpVerbs {
/**
* The constructor of an error response
*/
export type SCErrorResponseConstructor = new (...args: any) => SCErrorResponse;
// tslint:disable-next-line:no-any
export type SCErrorResponseConstructor = new (...args: any[]) => SCErrorResponse;
/**
* A description of a route
@@ -94,19 +95,41 @@ export interface SCRoute {
* An abstract route
*/
export abstract class SCAbstractRoute implements SCRoute {
/**
* @see SCRoute.errorNames
*/
errorNames: SCErrorResponseConstructor[] = [];
/**
* @see SCRoute.method
*/
method: SCRouteHttpVerbs = SCRouteHttpVerbs.GET;
/**
* @see SCRoute.obligatoryParameters
*/
obligatoryParameters?: SCMap<string>;
/**
* @see SCRoute.requestBodyName
*/
requestBodyName = 'any';
/**
* @see SCRoute.responseBodyName
*/
responseBodyName = 'any';
/**
* @see SCRoute.statusCodeSuccess
*/
statusCodeSuccess = 200;
/**
* @see SCRoute.urlFragment
*/
urlFragment = '/';
public getUrlFragment(parameters?: SCMap<string>): string {
if (typeof parameters === 'undefined') {
parameters = {};
}
/**
* Get "compiled" URL fragment
*
* @param parameters Parameters to compile URL fragment with
*/
public getUrlFragment(parameters: SCMap<string> = {}): string {
let obligatoryParameters: string[] = [];
if (typeof this.obligatoryParameters === 'object') {
@@ -126,14 +149,13 @@ export abstract class SCAbstractRoute implements SCRoute {
const parameter = part.substr(1);
// @ts-ignore
if (typeof parameters[parameter] === 'undefined') {
throw new Error(`Parameter '${parameter}' not provided.`);
}
// @ts-ignore
return parameters[parameter];
}).join('/');
})
.join('/');
}
}

View File

@@ -289,14 +289,16 @@ export class SCThingMeta implements SCMetaTranslations<SCThing> {
},
};
// tslint:disable:static-this
/**
* Function to retrieve typed singleton instance
*/
public static getInstance<T extends SCThingMeta>(): T {
if (!this._instance.has(this.name)) {
this._instance.set(this.name, new this());
if (!SCThingMeta._instance.has(this.name)) {
SCThingMeta._instance.set(this.name, new this());
}
return this._instance.get(this.name) as T;
return SCThingMeta._instance.get(this.name) as T;
}
protected constructor() {

View File

@@ -21,6 +21,9 @@ import {SCTranslations} from './types/i18n';
import clone = require('fast-clone');
import {Defined, OCType} from 'ts-optchain';
// tslint:disable:no-any
const standardCacheSize = 200;
/**
* SCThingTranslator class
*/
@@ -35,21 +38,19 @@ export class SCThingTranslator {
* Property representing the translators base language
* This means every translation is given for this language
*/
private cache: LRUCache<SCThing>;
private readonly cache: LRUCache<SCThing>;
/**
* Property providing a mapping from a SCThingType to its known own meta class
*/
private metaClasses: typeof SCClasses;
private readonly metaClasses: typeof SCClasses;
/**
*
* @constructor
* @example
* // returns translator instance for german
* new SCThingTranslator('de');
*/
constructor(language: keyof SCTranslations<SCThing>, cacheCapacity: number = 200) {
constructor(language: keyof SCTranslations<SCThing>, cacheCapacity: number = standardCacheSize) {
this.cache = new LRUCache(cacheCapacity);
this._language = language;
this.metaClasses = SCClasses;
@@ -80,16 +81,19 @@ export class SCThingTranslator {
* @param data The intermediate object / primitive returned by the Proxys get() method
* @returns an OCType<T> object allowing for access to translations or a translated value(s)
*/
// tslint:disable-next-line:prefer-function-over-method
private deeptranslate<T>(data?: T): OCType<T> {
const proxy = new Proxy(
((defaultValue?: Defined<T>) => (data == null ? defaultValue : data)) as OCType<T>,
{
get: (target, key) => {
const obj: any = target();
return this.deeptranslate(obj[key]);
},
},
);
return proxy;
}
@@ -110,30 +114,34 @@ export class SCThingTranslator {
// Assigns every property in fieldTranslations to the known base language translation
if (typeof metaClass.fieldTranslations.en !== 'undefined') {
Object.keys(metaClass.fieldTranslations.en).forEach((key) => {
Object.keys(metaClass.fieldTranslations.en)
.forEach((key) => {
(fieldTranslations as any)[key] = metaClass.fieldTranslations.en[key];
});
}
// Assigns every property in fieldTranslations to the known translation in given language
if (typeof metaClass.fieldTranslations[language] !== 'undefined') {
Object.keys(metaClass.fieldTranslations[language]).forEach((key) => {
Object.keys(metaClass.fieldTranslations[language])
.forEach((key) => {
(fieldTranslations as any)[key] = metaClass.fieldTranslations[language][key];
});
}
return fieldTranslations;
}
/**
* Returns meta class needed for translations given a SCThingType
*
* @param thingType
* @param thingType Type of the thing
* @returns An instance of the metaclass
*/
private getMetaClassInstance(thingType: SCThingType): any {
if (thingType in this.metaClasses) {
return new (this.metaClasses as any)[thingType]();
}
return undefined;
}
@@ -152,10 +160,12 @@ export class SCThingTranslator {
return instance;
}
if (typeof metaClass.fieldValueTranslations[language] !== 'undefined') {
Object.keys(metaClass.fieldValueTranslations[language]).forEach((key) => {
Object.keys(metaClass.fieldValueTranslations[language])
.forEach((key) => {
if (metaClass.fieldValueTranslations[language][key] instanceof Object) {
// Assigns known translations of subproperties to property in given language (e.g. categories)
Object.keys((instance as any)[key]).forEach((subKey) => {
Object.keys((instance as any)[key])
.forEach((subKey) => {
(instance as any)[key][subKey] =
metaClass.fieldValueTranslations[language][key][(instance as any)[key][subKey]];
});
@@ -165,6 +175,7 @@ export class SCThingTranslator {
}
});
}
return instance;
}
@@ -193,6 +204,7 @@ export class SCThingTranslator {
}
const objTranslated = this.translateWholeThingDestructively(clone(obj));
this.cache.putObject(objTranslated);
return this.deeptranslate(objTranslated[key]);
},
},
@@ -205,13 +217,13 @@ export class SCThingTranslator {
* @example
* const translatedMetaDish = translator.translatedPropertyNames<SCCourseOfStudies>(SCThingType.CourseOfStudies);
* @param language The language the object is translated to
* @param thingType
* @param thingType Type of the thing
* @returns An object with the properties of the SCThingType where the values are the known property tranlations
*/
public translatedPropertyNames<T extends SCThing>(thing: T,
language?: keyof SCTranslations<T>): T | undefined {
const targetLanguage = (language) ? language : this.language;
// return {...{}, ...this.getAllMetaFieldTranslations(thing.type, targetLanguage) as T};
const targetLanguage = (typeof language !== 'undefined') ? language : this.language;
return this.getAllMetaFieldTranslations(thing.type, targetLanguage) as T;
}
@@ -225,26 +237,29 @@ export class SCThingTranslator {
*/
public translateWholeThingDestructively(instance: any,
language?: keyof SCTranslations<any>): any {
const targetLanguage = (language) ? language : this.language;
const targetLanguage = (typeof language !== 'undefined') ? language : this.language;
let nextInstance = instance;
// Recursively call this function on all nested SCThings, arrays and objects
Object.keys(instance).forEach((key) => {
Object.keys(nextInstance)
.forEach((key) => {
if (
isThing((instance as any)[key]) ||
instance[key] instanceof Array ||
instance[key] instanceof Object) {
instance[key] = this.translateWholeThingDestructively(instance[key], targetLanguage);
isThing((nextInstance as any)[key]) ||
nextInstance[key] instanceof Array ||
nextInstance[key] instanceof Object) {
nextInstance[key] = this.translateWholeThingDestructively(nextInstance[key], targetLanguage);
}
});
// Spread variable translations given by the connector into thing
if (typeof instance.translations !== 'undefined') {
if (typeof instance.translations![targetLanguage] !== 'undefined') {
instance = {...instance, ...instance.translations![targetLanguage]} as typeof instance;
if (typeof nextInstance.translations !== 'undefined') {
if (typeof nextInstance.translations![targetLanguage] !== 'undefined') {
nextInstance = {...nextInstance, ...nextInstance.translations![targetLanguage]} as typeof instance;
}
}
// Spread known translations from meta classes into (partly) translated thing
this.replaceAvailableMetaFieldValueTranslations(instance, targetLanguage);
return instance;
this.replaceAvailableMetaFieldValueTranslations(nextInstance, targetLanguage);
return nextInstance;
}
}
@@ -257,15 +272,14 @@ class LRUCache<T> {
/**
* Map property that manages cached content
*/
private entries: Map<string, T> = new Map<string, T>();
private readonly entries: Map<string, T> = new Map<string, T>();
/**
* Property representing cache maximum capacity
*/
private maxEntries: number;
private readonly maxEntries: number;
/**
* @constructor
* @example
* // returns LRUCache instance with a maximum capacity of 500
* new LRUCache(500);
@@ -308,11 +322,12 @@ class LRUCache<T> {
}
const entry = this.entries.get(key);
if (entry) {
if (typeof entry !== 'undefined') {
// LRU behavior
this.entries.delete(key);
this.entries.set(key, entry);
}
return entry;
}
@@ -325,7 +340,8 @@ class LRUCache<T> {
public put(key: string, content: T) {
if (this.entries.size >= this.maxEntries) {
// LRU behavior
const keyToDelete = this.entries.keys().next().value;
const keyToDelete = this.entries.keys()
.next().value;
this.entries.delete(keyToDelete);
}
this.entries.set(key, content);

View File

@@ -65,6 +65,9 @@ export interface SCPlace
*/
export interface SCPlaceWithoutReferencesTranslatableProperties
extends SCThingTranslatableProperties {
/**
* Address of a place
*/
address?: SCPostalAddress;
}

View File

@@ -155,7 +155,10 @@ export type SCThingThatCanBeOfferedAvailability =
export class SCThingThatCanBeOfferedMeta<T extends SCPriceGroup> implements
SCMetaTranslations<SCThingThatCanBeOffered<T>> {
protected static _instance: any;
/**
* Instance
*/
protected static _instance = new Map<string, unknown>();
/**
* Translations of fields
@@ -183,12 +186,17 @@ export class SCThingThatCanBeOfferedMeta<T extends SCPriceGroup> implements
},
};
// tslint:disable:static-this
/**
* Function to retrieve typed singleton instance (including generics)
*/
public static getInstance<T extends SCPriceGroup>(): SCThingThatCanBeOfferedMeta<T> {
return this._instance || (this._instance = new this<T>());
if (!SCThingThatCanBeOfferedMeta._instance.has(this.name)) {
SCThingThatCanBeOfferedMeta._instance.set(this.name, new SCThingThatCanBeOfferedMeta<T>());
}
return SCThingThatCanBeOfferedMeta._instance
.get(this.name) as SCThingThatCanBeOfferedMeta<T>;
}
protected constructor() {}
}

View File

@@ -116,7 +116,10 @@ export interface SCThingWithCategoriesSpecificValues {
export class SCThingWithCategoriesWithoutReferencesMeta<T, U>
implements SCMetaTranslations<SCThingWithCategoriesWithoutReferences<T, U>> {
protected static _instance: any;
/**
* Instance
*/
protected static _instance = new Map<string, unknown>();
/**
* Translations of fields
@@ -146,11 +149,18 @@ export class SCThingWithCategoriesWithoutReferencesMeta<T, U>
},
};
// tslint:disable:static-this
/**
* Function to retrieve typed singleton instance (including generics)
*/
public static getInstance<T, U>(): SCThingWithCategoriesWithoutReferencesMeta<T, U> {
return this._instance || (this._instance = new this<T, U>());
if (!SCThingWithCategoriesWithoutReferencesMeta._instance.has(this.name)) {
SCThingWithCategoriesWithoutReferencesMeta._instance
.set(this.name, new SCThingWithCategoriesWithoutReferencesMeta<T, U>());
}
return SCThingWithCategoriesWithoutReferencesMeta._instance
.get(this.name) as SCThingWithCategoriesWithoutReferencesMeta<T, U>;
}
protected constructor() {

View File

@@ -12,6 +12,14 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {
BAD_GATEWAY,
BAD_REQUEST, CONFLICT, INTERNAL_SERVER_ERROR,
METHOD_NOT_ALLOWED, NOT_ACCEPTABLE, NOT_FOUND,
REQUEST_TOO_LONG,
TOO_MANY_REQUESTS,
UNSUPPORTED_MEDIA_TYPE,
} from 'http-status-codes';
import {ValidationError} from 'jsonschema';
import {SCPluginMetaData} from '../routes/plugin/PluginRegisterRequest';
@@ -24,7 +32,7 @@ export interface SCErrorResponse extends Error {
/**
* Additional data that describes the error
*/
additionalData?: any;
additionalData?: unknown;
/**
* HTTP status code to return this error with
@@ -49,7 +57,7 @@ export abstract class SCError implements SCErrorResponse {
* @param statusCode HTTP status code to return this error with
* @param stack Set to true if a stack trace should be created
*/
constructor(public name: string, public message: string, public statusCode: number, stack?: boolean) {
constructor(public name: string, public message: string, public statusCode: number, stack = false) {
// generate stacktrace if needed
if (stack) {
this.stack = (new Error()).stack;
@@ -73,7 +81,7 @@ export class SCValidationErrorResponse extends SCError {
* @param stack Set to true if a stack trace should be created
*/
constructor(errors: ValidationError[], stack?: boolean) {
super('ValidationError', 'Validation of request failed', 400, stack);
super('ValidationError', 'Validation of request failed', BAD_REQUEST, stack);
this.additionalData = errors;
}
}
@@ -88,7 +96,7 @@ export class SCUnsupportedMediaTypeErrorResponse extends SCError {
* @param stack Set to true if a stack trace should be created
*/
constructor(stack?: boolean) {
super('UnsupportedMediaTypeError', 'Unsupported media type', 415, stack);
super('UnsupportedMediaTypeError', 'Unsupported media type', UNSUPPORTED_MEDIA_TYPE, stack);
}
}
@@ -102,7 +110,7 @@ export class SCMethodNotAllowedErrorResponse extends SCError {
* @param stack Set to true if a stack trace should be created
*/
constructor(stack?: boolean) {
super('MethodNotAllowedError', 'HTTP method is not allowed on this route', 405, stack);
super('MethodNotAllowedError', 'HTTP method is not allowed on this route', METHOD_NOT_ALLOWED, stack);
}
}
@@ -116,7 +124,7 @@ export class SCRequestBodyTooLargeErrorResponse extends SCError {
* @param stack Set to true if a stack trace should be created
*/
constructor(stack?: boolean) {
super('RequestBodyTooLargeError', 'The request body is too large.', 413, stack);
super('RequestBodyTooLargeError', 'The request body is too large.', REQUEST_TOO_LONG, stack);
}
}
@@ -130,7 +138,12 @@ export class SCTooManyRequestsErrorResponse extends SCError {
* @param stack Set to true if a stack trace should be created
*/
constructor(stack?: boolean) {
super('TooManyRequestsError', 'Too many requests. You can not submit more than 5 queries an once', 429, stack);
super(
'TooManyRequestsError',
'Too many requests. You can not submit more than 5 queries an once',
TOO_MANY_REQUESTS,
stack,
);
}
}
@@ -144,7 +157,7 @@ export class SCNotFoundErrorResponse extends SCError {
* @param stack Set to true if a stack trace should be created
*/
constructor(stack?: boolean) {
super('NotFoundError', 'Resource not found', 404, stack);
super('NotFoundError', 'Resource not found', NOT_FOUND, stack);
}
}
@@ -160,7 +173,7 @@ export class SCParametersNotAcceptable extends SCError {
* @param stack Set to true if a stack trace should be created
*/
constructor(message: string, stack?: boolean) {
super('ParametersNotAcceptable', message, 406, stack);
super('ParametersNotAcceptable', message, NOT_ACCEPTABLE, stack);
}
}
@@ -183,8 +196,8 @@ export class SCPluginAlreadyRegisteredErrorResponse extends SCError {
* @param plugin Provides meta data of a registered plugin, which is in a conflict with the plugin we want to register
* @param stack Set to true if a stack trace should be created
*/
constructor(message: string, plugin: SCPluginMetaData, stack?: boolean) {
super('SCPluginAlreadyRegisteredError', message, 409, stack);
constructor(message: string, plugin: SCPluginMetaData, stack = false) {
super('SCPluginAlreadyRegisteredError', message, CONFLICT, stack);
if (stack) {
this.additionalData = plugin;
}
@@ -202,7 +215,7 @@ export class SCPluginRegisteringFailedErrorResponse extends SCError {
* @param stack Set to true if a stack trace should be created
*/
constructor(message: string, stack?: boolean) {
super('PluginRegisteringFailedError', message, 500, stack);
super('PluginRegisteringFailedError', message, INTERNAL_SERVER_ERROR, stack);
}
}
@@ -217,7 +230,7 @@ export class SCSyntaxErrorResponse extends SCError {
* @param stack Set to true if a stack trace should be created
*/
constructor(message: string, stack?: boolean) {
super('SyntaxError', message, 400, stack);
super('SyntaxError', message, BAD_REQUEST, stack);
}
}
@@ -237,8 +250,8 @@ export class SCInternalServerErrorResponse extends SCError {
* @param stack Set to true if a stack trace should be created
* and the internal server error should be displayed to the client
*/
constructor(err?: Error, stack?: boolean) {
super('InternalServerError', 'Internal server error', 502, stack);
constructor(err?: Error, stack = false) {
super('InternalServerError', 'Internal server error', BAD_GATEWAY, stack);
if (stack) {
this.additionalData = err;

View File

@@ -12,6 +12,7 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {OK} from 'http-status-codes';
import {SCAbstractRoute, SCRouteHttpVerbs} from '../../../Route';
import {
SCInternalServerErrorResponse,
@@ -47,7 +48,7 @@ export class SCIndexRoute extends SCAbstractRoute {
this.method = SCRouteHttpVerbs.POST;
this.requestBodyName = 'SCIndexRequest';
this.responseBodyName = 'SCIndexResponse';
this.statusCodeSuccess = 200;
this.statusCodeSuccess = OK;
this.urlFragment = '/';
}
}

View File

@@ -21,7 +21,13 @@ import {SCBackendConfiguration} from '../../../types/config/Backend';
* @validatable
*/
export interface SCIndexResponse {
/**
* @see SCAppConfiguration
*/
app: SCAppConfiguration;
/**
* @see SCBackendConfiguration
*/
backend: SCBackendConfiguration;
}

View File

@@ -12,6 +12,7 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {OK} from 'http-status-codes';
import {SCThings} from '../../../../Classes';
import {SCAbstractRoute, SCRouteHttpVerbs} from '../../../../Route';
import {
@@ -53,7 +54,7 @@ export class SCThingUpdateRoute extends SCAbstractRoute {
};
this.requestBodyName = 'SCThingUpdateRequest';
this.responseBodyName = 'SCThingUpdateResponse';
this.statusCodeSuccess = 200;
this.statusCodeSuccess = OK;
this.urlFragment = '/:TYPE/:UID';
}
}

View File

@@ -12,6 +12,7 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {OK} from 'http-status-codes';
import {SCAbstractRoute, SCRouteHttpVerbs} from '../../../Route';
import {SCUuid} from '../../../types/UUID';
import {
@@ -81,7 +82,7 @@ export class SCBookAvailabilityRoute extends SCAbstractRoute {
this.method = SCRouteHttpVerbs.POST;
this.requestBodyName = 'SCBookAvailabilityRequest';
this.responseBodyName = 'SCBookAvailabilityResponse';
this.statusCodeSuccess = 200;
this.statusCodeSuccess = OK;
this.urlFragment = '/bookAvailability';
}
}

View File

@@ -12,6 +12,7 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {OK} from 'http-status-codes';
import {SCAbstractRoute, SCRouteHttpVerbs} from '../../../Route';
import {SCThingType} from '../../../Thing';
import {SCISO8601Date} from '../../../types/Time';
@@ -78,7 +79,7 @@ export class SCBulkRoute extends SCAbstractRoute {
this.method = SCRouteHttpVerbs.POST;
this.requestBodyName = 'SCBulkRequest';
this.responseBodyName = 'SCBulkResponse';
this.statusCodeSuccess = 200;
this.statusCodeSuccess = OK;
this.urlFragment = '/bulk';
}
}

View File

@@ -12,6 +12,7 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {CREATED} from 'http-status-codes';
import {SCThings} from '../../../../Classes';
import {SCAbstractRoute, SCRouteHttpVerbs} from '../../../../Route';
import {
@@ -52,7 +53,7 @@ export class SCBulkAddRoute extends SCAbstractRoute {
};
this.requestBodyName = 'SCBulkAddRequest';
this.responseBodyName = 'SCBulkAddResponse';
this.statusCodeSuccess = 201;
this.statusCodeSuccess = CREATED;
this.urlFragment = '/bulk/:UID';
}
}

View File

@@ -12,6 +12,7 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {NO_CONTENT} from 'http-status-codes';
import {SCAbstractRoute, SCRouteHttpVerbs} from '../../../../Route';
import {
SCInternalServerErrorResponse,
@@ -52,7 +53,7 @@ export class SCBulkDoneRoute extends SCAbstractRoute {
};
this.requestBodyName = 'SCBulkDoneRequest';
this.responseBodyName = 'SCBulkDoneResponse';
this.statusCodeSuccess = 204;
this.statusCodeSuccess = NO_CONTENT;
this.urlFragment = '/bulk/:UID/done';
}
}

View File

@@ -12,6 +12,7 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {NO_CONTENT} from 'http-status-codes';
import {SCAbstractRoute, SCRouteHttpVerbs} from '../../../Route';
import {SCMessage} from '../../../things/Message';
import {
@@ -52,7 +53,7 @@ export class SCFeedbackRoute extends SCAbstractRoute {
this.method = SCRouteHttpVerbs.POST;
this.requestBodyName = 'SCFeedbackRequest';
this.responseBodyName = 'SCFeedbackResponse';
this.statusCodeSuccess = 204;
this.statusCodeSuccess = NO_CONTENT;
this.urlFragment = '/feedback';
}
}
@@ -74,7 +75,7 @@ export interface SCFeedbackRequestMetaData {
/**
* Scope/app state at feedback invocation
*/
scope: any;
scope: unknown;
/**
* Whether or not the feedback is sendable
@@ -84,7 +85,7 @@ export interface SCFeedbackRequestMetaData {
/**
* App state that feedback was invoked from
*/
state: any;
state: unknown;
/**
* User agent

View File

@@ -12,6 +12,7 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {OK} from 'http-status-codes';
import {Schema} from 'jsonschema';
import {SCAbstractRoute, SCRouteHttpVerbs} from '../../../Route';
import {
@@ -108,7 +109,7 @@ export class SCPluginRegisterRoute extends SCAbstractRoute {
this.method = SCRouteHttpVerbs.POST;
this.requestBodyName = 'SCPluginRegisterRequest';
this.responseBodyName = 'SCPluginRegisterResponse';
this.statusCodeSuccess = 200;
this.statusCodeSuccess = OK;
this.urlFragment = '/plugin/register';
}
}

View File

@@ -12,6 +12,7 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {OK} from 'http-status-codes';
import {SCAbstractRoute, SCRouteHttpVerbs} from '../../../Route';
import {SCMap} from '../../../types/Map';
import {
@@ -54,7 +55,7 @@ export class SCMultiSearchRoute extends SCAbstractRoute {
this.method = SCRouteHttpVerbs.POST;
this.requestBodyName = 'SCMultiSearchRequest';
this.responseBodyName = 'SCMultiSearchResponse';
this.statusCodeSuccess = 200;
this.statusCodeSuccess = OK;
this.urlFragment = '/search/multi';
}
}

View File

@@ -12,6 +12,7 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {OK} from 'http-status-codes';
import {SCAbstractRoute, SCRouteHttpVerbs} from '../../../Route';
import {SCSearchContext} from '../../../types/config/Backend';
import {SCSearchFilter} from '../../../types/filters/Abstract';
@@ -85,7 +86,7 @@ export class SCSearchRoute extends SCAbstractRoute {
this.method = SCRouteHttpVerbs.POST;
this.requestBodyName = 'SCSearchRequest';
this.responseBodyName = 'SCSearchResponse';
this.statusCodeSuccess = 200;
this.statusCodeSuccess = OK;
this.urlFragment = '/search';
}
}

View File

@@ -89,6 +89,9 @@ export interface SCBuilding
export interface SCBuildingTranslatableProperties
extends SCPlaceWithoutReferencesTranslatableProperties, SCThingWithCategoriesTranslatableProperties {
/**
* @see SCBuilding.floors
*/
floors?: string[];
}

View File

@@ -172,5 +172,8 @@ export class SCDateSeriesMeta
*/
export interface SCDateSeriesTranslatableProperties
extends SCThingThatCanBeOfferedTranslatableProperties {
/**
* @see SCDateSeriesWithoutReferences.frequency
*/
frequency?: string;
}

View File

@@ -12,6 +12,7 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
// tslint:disable-next-line:no-implicit-dependencies
import {Feature, FeatureCollection, GeometryObject, LineString} from 'geojson';
import {SCThingInPlace, SCThingInPlaceMeta} from '../base/ThingInPlace';
import {SCThingMeta, SCThingTranslatableProperties, SCThingType, SCThingWithoutReferences} from '../Thing';
@@ -34,7 +35,7 @@ export interface SCFloorWithoutReferences
/**
* Floor plan
*/
plan: SCFloorFeatureCollectionWithPlaces<LineString, any>;
plan: SCFloorFeatureCollectionWithPlaces<LineString>;
/**
* Translated fields of a floor
@@ -69,19 +70,19 @@ export interface SCFloor
/**
* A feature collection
*/
export interface SCFloorFeatureCollectionWithPlaces<T extends GeometryObject, P = any>
extends FeatureCollection<T, P> {
export interface SCFloorFeatureCollectionWithPlaces<T extends GeometryObject>
extends FeatureCollection<T> {
/**
* Features of the collection
*/
features: Array<SCFloorFeatureWithPlace<T, P>>;
features: Array<SCFloorFeatureWithPlace<T>>;
}
/***
* A feature with a place
*/
export interface SCFloorFeatureWithPlace<T extends GeometryObject, P = any>
extends Feature<T, P> {
export interface SCFloorFeatureWithPlace<T extends GeometryObject>
extends Feature<T> {
/**
* The place of the feature
*/

View File

@@ -12,6 +12,7 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
// tslint:disable-next-line:no-implicit-dependencies
import {Point, Polygon} from 'geojson';
/**

View File

@@ -5,7 +5,7 @@
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* unknown WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
@@ -23,12 +23,25 @@ import {SCTranslations} from './i18n';
*
* @param something Something to check
*/
export function isThing(something: any): something is SCThing {
return (
typeof something === 'object'
&& typeof something.type === 'string'
&& Object.values(SCThingType).indexOf(something.type) >= 0
);
export function isThing(something: unknown): something is SCThing {
if (typeof something !== 'object' || something === null) {
return false;
}
if (!('type' in something)) {
return false;
}
// tslint:disable-next-line:completed-docs
const type = (something as { type: unknown; }).type;
if (typeof type !== 'string') {
return false;
}
return Object
.values(SCThingType)
.indexOf(type) >= 0;
}
/**
@@ -37,7 +50,8 @@ export function isThing(something: any): something is SCThing {
* @param thing Thing to check
*/
export function isThingWithTranslations(thing: SCThingWithoutReferences)
: thing is SCThingWithoutReferences & { translations: SCTranslations<SCThingTranslatableProperties> } {
// tslint:disable-next-line:completed-docs
: thing is SCThingWithoutReferences & { translations: SCTranslations<SCThingTranslatableProperties>; } {
return typeof thing.translations !== 'undefined';
}
@@ -46,12 +60,34 @@ export function isThingWithTranslations(thing: SCThingWithoutReferences)
*
* @param something Something to check
*/
export function isBulkResponse(something: any): something is SCBulkResponse {
return typeof something.expiration === 'string'
&& typeof something.source === 'string'
&& typeof something.state === 'string'
&& typeof something.type === 'string'
&& typeof something.uid === 'string';
export function isBulkResponse(something: unknown): something is SCBulkResponse {
if (typeof something !== 'object' || something === null) {
return false;
}
if (!('expiration' in something)
|| !('source' in something)
|| !('state' in something)
|| !('type' in something)
|| !('uid' in something)) {
return false;
}
const {expiration, source, state, type, uid} = something as {
// tslint:disable:completed-docs
expiration: unknown;
source: unknown;
state: unknown;
type: unknown;
uid: unknown;
// tslint:enable
};
return typeof expiration === 'string'
&& typeof source === 'string'
&& typeof state === 'string'
&& typeof type === 'string'
&& typeof uid === 'string';
}
/**
@@ -59,15 +95,20 @@ export function isBulkResponse(something: any): something is SCBulkResponse {
*
* @param something Something to check
*/
export function isSearchResponse(something: any): something is SCSearchResponse {
return Array.isArray(something.data)
&& Array.isArray(something.facets)
&& typeof something.pagination !== 'undefined'
&& typeof something.pagination.count === 'number'
&& typeof something.pagination.offset === 'number'
&& typeof something.pagination.total === 'number'
&& typeof something.stats !== 'undefined'
&& typeof something.stats.time === 'number';
export function isSearchResponse(something: unknown): something is SCSearchResponse {
if (!(typeof something === 'object') || something === null) {
return false;
}
const somethingObject = (something as { [key: string]: { [key: string]: string; }; });
return Array.isArray(somethingObject.data)
&& Array.isArray(somethingObject.facets)
&& typeof somethingObject.pagination !== 'undefined'
&& typeof somethingObject.pagination.count === 'number'
&& typeof somethingObject.pagination.offset === 'number'
&& typeof somethingObject.pagination.total === 'number'
&& typeof somethingObject.stats !== 'undefined'
&& typeof somethingObject.stats.time === 'number';
}
/**
@@ -75,8 +116,11 @@ export function isSearchResponse(something: any): something is SCSearchResponse
*
* @param something Something to check
*/
export function isMultiSearchResponse(something: any): something is SCMultiSearchResponse {
return Object.keys(something).reduce((previousOnesAreSearchResponses, key) => {
return previousOnesAreSearchResponses && isSearchResponse(something[key]);
}, true as boolean);
export function isMultiSearchResponse(something: unknown): something is SCMultiSearchResponse {
const initialValue = Object.keys(something as { [key: string]: string; }).length > 0 ? true : false;
return Object.keys(something as { [key: string]: string; })
.reduce((previousOnesAreSearchResponses, key) => {
return previousOnesAreSearchResponses && isSearchResponse((something as { [key: string]: string; })[key]);
}, initialValue as boolean);
}

View File

@@ -12,6 +12,7 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
// tslint:disable-next-line:no-implicit-dependencies
import {Polygon} from 'geojson';
import {SCSetting} from '../../things/Setting';
import {SCTranslations} from '../i18n';
@@ -126,11 +127,11 @@ export interface SCAppConfiguration {
}
/**
*
* Map of features
*/
export interface SCAppConfigurationFeature {
/**
*
* Whether or not widgets are enabled
*/
widgets: boolean;
}

View File

@@ -176,10 +176,9 @@ export interface SCBackendInternalConfiguration {
/**
* Configuration of the database
*/
export interface SCBackendConfigurationDatabaseConfiguration extends SCMap<any> {
export interface SCBackendConfigurationDatabaseConfiguration extends SCMap<unknown> {
/**
* Name of the database used by the backend
*/
name: string;
}

View File

@@ -140,7 +140,7 @@ export interface SCMonitoringWatcher {
/**
* Query to execute against the database
*/
query: any;
query: unknown;
/**
* A list of triggers

View File

@@ -48,7 +48,7 @@ export interface SCSearchAbstractFilter<T extends SCSearchAbstractFilterArgument
/**
* Arguments for the filter instruction
*/
export type SCSearchAbstractFilterArguments = SCMap<any>;
export type SCSearchAbstractFilterArguments = SCMap<unknown>;
/**
* Available filter instructions

View File

@@ -22,6 +22,9 @@ import {SCSearchAbstractFilter, SCSearchAbstractFilterArguments} from './Abstrac
* Filter for documents where it cannot be safely determined that they are not available
*/
export interface SCSearchAvailabilityFilter extends SCSearchAbstractFilter<SCAvailabilityFilterArguments> {
/**
* @see SCSearchAbstractFilter.type
*/
type: 'availability';
}

View File

@@ -20,6 +20,9 @@ import {SCSearchAbstractFilter, SCSearchAbstractFilterArguments, SCSearchFilter}
* This filter can be used to combine multiple filters with boolean operations.
*/
export interface SCSearchBooleanFilter extends SCSearchAbstractFilter<SCBooleanFilterArguments> {
/**
* @see SCSearchAbstractFilter.type
*/
type: 'boolean';
}

View File

@@ -12,6 +12,7 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
// tslint:disable-next-line:no-implicit-dependencies
import {Position} from 'geojson';
import {SCThingsField} from '../../Classes';
import {SCSearchAbstractFilter, SCSearchAbstractFilterArguments} from './Abstract';
@@ -22,6 +23,9 @@ import {SCSearchAbstractFilter, SCSearchAbstractFilterArguments} from './Abstrac
* Filter for documents that are in the given distance of the given location
*/
export interface SCSearchDistanceFilter extends SCSearchAbstractFilter<SCSearchAbstractFilterArguments> {
/**
* @see SCSearchAbstractFilter.type
*/
type: 'distance';
}

View File

@@ -19,6 +19,9 @@ import {SCSearchAbstractFilter, SCSearchAbstractFilterArguments} from './Abstrac
* Filters for documents that match the value on the given field
*/
export interface SCSearchValueFilter extends SCSearchAbstractFilter<SCValueFilterArguments> {
/**
* @see SCSearchAbstractFilter.type
*/
type: 'value';
}

View File

@@ -714,6 +714,12 @@ type SCRequiredTranslation<T> = {
* Interface to be implemented by all Meta classes
*/
export interface SCMetaTranslations<T> {
/**
* Field translations
*/
fieldTranslations: SCRequiredTranslation<T>;
fieldValueTranslations: any;
/**
* Field value translations
*/
fieldValueTranslations: unknown;
}

View File

@@ -41,7 +41,7 @@ export interface SCSearchAbstractSort<T extends SCSearchAbstractSortArguments> {
/**
* Map of arguments for the sort instruction
*/
export interface SCSearchAbstractSortArguments extends SCMap<any> {
export interface SCSearchAbstractSortArguments extends SCMap<unknown> {
/**
* Field to sort by
*/

View File

@@ -12,6 +12,7 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
// tslint:disable-next-line:no-implicit-dependencies
import {Position} from 'geojson';
import {SCSearchAbstractSort, SCSearchAbstractSortArguments} from './Abstract';
@@ -19,6 +20,9 @@ import {SCSearchAbstractSort, SCSearchAbstractSortArguments} from './Abstract';
* Sort instruction to sort by distance
*/
export interface SCDistanceSort extends SCSearchAbstractSort<SCDistanceSortArguments> {
/**
* @see SCSearchAbstractSort.type
*/
type: 'distance';
}

View File

@@ -18,5 +18,8 @@ import {SCSearchAbstractSort, SCSearchAbstractSortArguments} from './Abstract';
* Sort instruction for ducet sort
*/
export interface SCDucetSort extends SCSearchAbstractSort<SCSearchAbstractSortArguments> {
/**
* @see SCSearchAbstractSort.type
*/
type: 'ducet';
}

View File

@@ -19,6 +19,9 @@ import {SCSearchAbstractSort, SCSearchAbstractSortArguments} from './Abstract';
* Sort instruction to sort by price
*/
export interface SCPriceSort extends SCSearchAbstractSort<SCPriceSortArguments> {
/**
* @see SCSearchAbstractSort.type
*/
type: 'price';
}

View File

@@ -14,15 +14,49 @@
*/
import {expect} from 'chai';
import {slow, suite, test, timeout} from 'mocha-typescript';
import {SCBulkResponse} from '../src/core/protocol/routes/bulk/BulkResponse';
import {SCMultiSearchResponse} from '../src/core/protocol/routes/search/MultiSearchResponse';
import {SCSearchResponse} from '../src/core/protocol/routes/search/SearchResponse';
import {SCThingOriginType, SCThingType} from '../src/core/Thing';
import {SCDish} from '../src/core/things/Dish';
import {isThing} from '../src/core/types/Guards';
import {
isBulkResponse,
isMultiSearchResponse,
isSearchResponse,
isThing,
isThingWithTranslations,
} from '../src/core/types/Guards';
@suite(timeout(10000), slow(5000))
export class GuardsSpec {
@test
public isThing() {
const notADish = {
static bulkResponse: SCBulkResponse = {
expiration: '2009-06-30T18:30:00+02:00 ',
source: 'bar',
state: 'done',
type: SCThingType.Dish,
uid: 'foo',
};
static dishWithTranslation: SCDish = {
categories: [
'appetizer',
],
name: 'foo',
origin: {
created: '',
type: SCThingOriginType.User,
},
translations: {
de: {
name: 'Foo',
},
},
type: SCThingType.Dish,
uid: 'bar',
};
static notADish = {
categories: [
'appetizer',
],
@@ -35,23 +69,74 @@ export class GuardsSpec {
uid: 'bar',
};
const dish: SCDish = {
categories: [
'appetizer',
static searchResponse: SCSearchResponse = {
data: [
GuardsSpec.dishWithTranslation,
],
name: 'foo',
origin: {
created: '',
type: SCThingOriginType.User,
facets: [
{
buckets: [
{
count: 1,
key: 'key',
},
],
field: 'field',
},
],
pagination: {
count: 1,
offset: 0,
total: 1,
},
stats: {
time: 1,
},
type: SCThingType.Dish,
uid: 'bar',
};
@test
public isBulkResponse() {
expect(isBulkResponse(null)).to.be.equal(false);
expect(isBulkResponse(GuardsSpec.dishWithTranslation)).to.be.equal(false);
expect(isBulkResponse(GuardsSpec.bulkResponse)).to.be.equal(true);
}
@test
public isMultiSearchResponse() {
const multiSearchResponse: SCMultiSearchResponse = {
foo: GuardsSpec.searchResponse,
};
expect(isMultiSearchResponse(multiSearchResponse)).to.be.equal(true);
const notAMultiSearchResponse = {...multiSearchResponse, ...{bar: 'baz'}};
expect(isMultiSearchResponse(notAMultiSearchResponse)).to.be.equal(false);
delete multiSearchResponse.foo;
expect(isMultiSearchResponse(multiSearchResponse)).to.be.equal(false);
}
@test
public isSearchResponse() {
const notASearchResponse = {...GuardsSpec.searchResponse};
delete notASearchResponse.pagination;
expect(isSearchResponse(notASearchResponse)).to.be.equal(false);
delete notASearchResponse.data;
expect(isSearchResponse(notASearchResponse)).to.be.equal(false);
expect(isSearchResponse(null)).to.be.equal(false);
expect(isSearchResponse(GuardsSpec.searchResponse)).to.be.equal(true);
}
@test
public isThing() {
expect(isThing('foo')).to.be.equal(false);
expect(isThing({type: 'foo'})).to.be.equal(false);
expect(isThing(GuardsSpec.notADish)).to.be.equal(false);
expect(isThing(GuardsSpec.dishWithTranslation)).to.be.equal(true);
}
expect(isThing(notADish)).to.be.equal(false);
expect(isThing(dish)).to.be.equal(true);
@test
public isThingWithTranslations() {
const dishWithoutTranslation = {...GuardsSpec.dishWithTranslation};
delete dishWithoutTranslation.translations;
expect(isThingWithTranslations(dishWithoutTranslation)).to.be.equal(false);
expect(isThingWithTranslations(GuardsSpec.dishWithTranslation)).to.be.equal(true);
}
}

View File

@@ -237,6 +237,7 @@ export class MetaTranslationSpec {
public consistencyWithMetaClass() {
const dishMetaTranslationsDE = translator.translatedPropertyNames(dish);
const dishMetaTranslationsEN = translator.translatedPropertyNames(dish, 'en');
expect(dishMetaTranslationsEN).to.not.deep.equal(dishMetaTranslationsDE);
expect(dishMetaTranslationsDE).to.deep.equal(SCDishMeta.getInstance().fieldTranslations.de);
expect(dishMetaTranslationsEN).to.deep.equal(SCDishMeta.getInstance().fieldTranslations.en);
}

View File

@@ -1,6 +1,7 @@
{
"extends": "./node_modules/@openstapps/configuration/tslint.json",
"rules": {
"no-empty-interface": false
"no-empty-interface": false,
"file-name-casing": [false, "camel-case"]
}
}