From 137738e0cac48d5cad76f920823ff98a54d5dccc Mon Sep 17 00:00:00 2001 From: marudor Date: Mon, 15 Apr 2019 00:07:05 +0200 Subject: [PATCH] TS Server --- .babelrc.js | 3 +- .babelrc.server.js | 22 + .eslintrc.js | 21 +- .flowconfig | 2 + .gitlab-ci.yml | 10 + @types/db-stations.d.ts | 28 + @types/flowMigration.d.ts | 1 + @types/global.d.ts | 22 + @types/react-router.d.ts | 6 + @types/universal-cookie-koa.d.ts | 7 + devIndex.js | 10 + package.json | 74 +- scripts/generateMostSearched.js | 24 +- src/client/Abfahrten/reducer/abfahrten.js | 2 +- .../Abfahrten/{Timetable.js => Timetable.ts} | 150 ++-- src/server/Abfahrten/{helper.js => helper.ts} | 19 +- src/server/Abfahrten/{index.js => index.ts} | 17 +- .../{messageLookup.js => messageLookup.ts} | 3 - .../{performance.js => performance.ts} | 4 +- .../Abfahrten/{station.js => station.ts} | 32 +- src/server/Abfahrten/{wings.js => wings.ts} | 5 +- src/server/{Auslastung.js => Auslastung.ts} | 10 +- .../Bahnhof/{Lageplan.js => Lageplan.ts} | 5 +- src/server/{Controller.js => Controller.ts} | 30 +- src/server/{Reihung.js => Reihung.ts} | 30 +- .../{DBNavigator.js => DBNavigator.ts} | 7 +- src/server/Routing/index.js | 17 - src/server/Routing/index.ts | 17 + src/server/Routing/{parse.js => parse.ts} | 52 +- .../Search/{DBNavigator.js => DBNavigator.ts} | 5 +- src/server/Search/{Favendo.js => Favendo.ts} | 5 +- src/server/Search/{Hafas.js => Hafas.ts} | 5 +- src/server/Search/{OpenDB.js => OpenDB.ts} | 5 +- .../Search/{OpenData.js => OpenData.ts} | 11 +- ...{OpenDataOffline.js => OpenDataOffline.ts} | 16 +- .../{StationsData.js => StationsData.ts} | 29 +- src/server/Search/{index.js => index.ts} | 19 +- src/server/{admin.js => admin.ts} | 0 src/server/{app.js => app.ts} | 13 +- src/server/{dbNavUtil.js => dbNavUtil.ts} | 1 - .../{errorHandler.js => errorHandler.ts} | 4 +- .../features/{default.js => default.ts} | 1 - src/server/features/{index.js => index.ts} | 4 +- src/server/index.js | 17 - src/server/index.ts | 8 + src/server/localStorageShim.js | 16 - src/server/{logger.js => logger.ts} | 21 +- .../{webpackDev.js => webpackDev.ts} | 20 +- src/server/{render.js => render.tsx} | 26 +- src/server/{seo.js => seo.ts} | 3 +- src/types/abfahrten.d.ts | 93 +++ src/types/auslastung.d.ts | 14 + src/types/reihung.d.ts | 113 +++ src/types/reihungStation.d.ts | 68 ++ src/types/routing.d.ts | 294 +++++++ src/types/station.d.ts | 8 + test/server/Abfahrten/index.test.js | 9 +- test/server/Abfahrten/onlyPlan.test.js | 5 +- test/server/Abfahrten/parseTimetableS.test.js | 9 +- test/server/Abfahrten/withFchg.test.js | 14 +- test/server/Bahnhof/Lageplan.test.js | 8 +- test/server/Search/Favendo.test.js | 6 +- .../__fixtures__/DBNavigator.example.js | 34 +- .../__fixtures__/OpenDB-forCombine.example.js | 17 +- .../__fixtures__/OpenDB-single.example.js | 10 +- .../Search/__fixtures__/OpenDB.example.js | 17 +- .../Search/__fixtures__/OpenData.example.js | 6 +- .../__fixtures__/OpenDataOffline.example.js | 84 +- test/server/Search/common.js | 5 +- test/server/config.js | 1 - test/server/jest.config.js | 5 +- tsconfig.json | 29 + webpack.config.js | 2 +- yarn.lock | 771 +++++++++++++++++- 74 files changed, 2046 insertions(+), 435 deletions(-) create mode 100644 @types/db-stations.d.ts create mode 100644 @types/flowMigration.d.ts create mode 100644 @types/global.d.ts create mode 100644 @types/react-router.d.ts create mode 100644 @types/universal-cookie-koa.d.ts create mode 100644 devIndex.js rename src/server/Abfahrten/{Timetable.js => Timetable.ts} (85%) rename src/server/Abfahrten/{helper.js => helper.ts} (50%) rename src/server/Abfahrten/{index.js => index.ts} (87%) rename src/server/Abfahrten/{messageLookup.js => messageLookup.ts} (96%) rename src/server/Abfahrten/{performance.js => performance.ts} (97%) rename src/server/Abfahrten/{station.js => station.ts} (80%) rename src/server/Abfahrten/{wings.js => wings.ts} (92%) rename src/server/{Auslastung.js => Auslastung.ts} (91%) rename src/server/Bahnhof/{Lageplan.js => Lageplan.ts} (91%) rename src/server/{Controller.js => Controller.ts} (83%) rename src/server/{Reihung.js => Reihung.ts} (91%) rename src/server/Routing/{DBNavigator.js => DBNavigator.ts} (94%) delete mode 100644 src/server/Routing/index.js create mode 100644 src/server/Routing/index.ts rename src/server/Routing/{parse.js => parse.ts} (85%) rename src/server/Search/{DBNavigator.js => DBNavigator.ts} (91%) rename src/server/Search/{Favendo.js => Favendo.ts} (89%) rename src/server/Search/{Hafas.js => Hafas.ts} (88%) rename src/server/Search/{OpenDB.js => OpenDB.ts} (91%) rename src/server/Search/{OpenData.js => OpenData.ts} (75%) rename src/server/Search/{OpenDataOffline.js => OpenDataOffline.ts} (59%) rename src/server/Search/{StationsData.js => StationsData.ts} (69%) rename src/server/Search/{index.js => index.ts} (83%) rename src/server/{admin.js => admin.ts} (100%) rename src/server/{app.js => app.ts} (93%) rename src/server/{dbNavUtil.js => dbNavUtil.ts} (98%) rename src/server/{errorHandler.js => errorHandler.ts} (84%) rename src/server/features/{default.js => default.ts} (88%) rename src/server/features/{index.js => index.ts} (92%) delete mode 100644 src/server/index.js create mode 100644 src/server/index.ts delete mode 100644 src/server/localStorageShim.js rename src/server/{logger.js => logger.ts} (71%) rename src/server/middleware/{webpackDev.js => webpackDev.ts} (75%) rename src/server/{render.js => render.tsx} (85%) rename src/server/{seo.js => seo.ts} (97%) create mode 100644 src/types/abfahrten.d.ts create mode 100644 src/types/auslastung.d.ts create mode 100644 src/types/reihung.d.ts create mode 100644 src/types/reihungStation.d.ts create mode 100644 src/types/routing.d.ts create mode 100644 src/types/station.d.ts create mode 100644 tsconfig.json diff --git a/.babelrc.js b/.babelrc.js index 306d09909..632e45072 100644 --- a/.babelrc.js +++ b/.babelrc.js @@ -1,4 +1,4 @@ -const TestConfig = require('./.babelrc.server.js'); +const { overrides, ...TestConfig } = require('./.babelrc.server.js'); module.exports = { presets: [ @@ -31,4 +31,5 @@ module.exports = { }, test: TestConfig, }, + overrides, }; diff --git a/.babelrc.server.js b/.babelrc.server.js index 53f605cb8..5268a761f 100644 --- a/.babelrc.server.js +++ b/.babelrc.server.js @@ -23,6 +23,7 @@ module.exports = { 'module-resolver', { root: 'src', + extensions: ['.js', '.jsx', '.ts', '.tsx'], resolvePath: (sourcePath, currentFile, opts) => { const path = require('babel-plugin-module-resolver').resolvePath( sourcePath.replace(/^(Abfahrten|Common|Routing)\//, 'client/$1/'), @@ -42,4 +43,25 @@ module.exports = { }, ], ], + overrides: [ + { + test: ['**/*.ts'], + presets: [ + '@babel/preset-typescript', + [ + '@babel/preset-env', + { + targets: { + node: '10', + }, + loose: false, + useBuiltIns: 'entry', + modules: 'commonjs', + corejs: 3, + }, + ], + 'babel-preset-joblift', + ], + }, + ], }; diff --git a/.eslintrc.js b/.eslintrc.js index b379db853..75201d31a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,5 +1,10 @@ module.exports = { - extends: ['joblift/base', 'joblift/react', 'joblift/flowtype'], + extends: [ + 'joblift/base', + 'joblift/react', + 'joblift/sort-imports', + 'joblift/flowtype', + ], parser: 'babel-eslint', env: { browser: true, @@ -18,4 +23,18 @@ module.exports = { settings: { 'import/resolver': 'webpack', }, + overrides: [ + { + rules: { + 'no-unused-vars': 0, + }, + files: ['**/*.ts', '**/*.tsx'], + parser: '@typescript-eslint/parser', + parserOptions: { + sourceType: 'module', + project: './tsconfig.json', + tsconfigRootDir: './', + }, + }, + ], }; diff --git a/.flowconfig b/.flowconfig index a698590a4..67b7d3fe0 100644 --- a/.flowconfig +++ b/.flowconfig @@ -28,6 +28,8 @@ module.system.node.resolve_dirname=./src module.file_ext=.js module.file_ext=.jsx module.file_ext=.json +module.file_ext=.ts +module.file_ext=.tsx module.system=haste include_warnings=true diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7bbf0f23b..a02625cd6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -66,6 +66,16 @@ flow: paths: - node_modules/ +tsc: + image: node:10 + stage: test + script: yarn tsc + cache: + policy: pull + key: '$CI_COMMIT_REF_SLUG' + paths: + - node_modules/ + build:app: stage: build variables: diff --git a/@types/db-stations.d.ts b/@types/db-stations.d.ts new file mode 100644 index 000000000..59c178c35 --- /dev/null +++ b/@types/db-stations.d.ts @@ -0,0 +1,28 @@ +declare module 'db-stations/data.json' { + export type OpenDataStation = { + type: 'station'; + id: string; + ds100: string; + nr: number; + name: string; + weight: number; + location: { + type: 'location'; + latitude: number; + longitude: number; + }; + operator: { + type: 'operator'; + id: string; + name: string; + }; + address: { + city: string; + zipcode: string; + street: string; + }; + }; + + declare const stations: OpenDataStation[]; + export default stations; +} diff --git a/@types/flowMigration.d.ts b/@types/flowMigration.d.ts new file mode 100644 index 000000000..ab9a33694 --- /dev/null +++ b/@types/flowMigration.d.ts @@ -0,0 +1 @@ +type $Values = O[keyof O]; diff --git a/@types/global.d.ts b/@types/global.d.ts new file mode 100644 index 000000000..675f28de8 --- /dev/null +++ b/@types/global.d.ts @@ -0,0 +1,22 @@ +namespace NodeJS { + interface Global { + PROD: boolean; + SERVER: boolean; + } +} + +type Features = { + 'google-analytics': boolean; + routing: boolean; +}; + +type StationSearchType = + | 'dbNav' + | 'openData' + | 'openDataOffline' + | 'openDB' + | 'hafas' + | 'favOpenDB' + | 'stationsData' + | 'favendo' + | ''; diff --git a/@types/react-router.d.ts b/@types/react-router.d.ts new file mode 100644 index 000000000..16891af4a --- /dev/null +++ b/@types/react-router.d.ts @@ -0,0 +1,6 @@ +declare module 'react-router' { + interface StaticRouterContext { + url?: string; + status?: number; + } +} diff --git a/@types/universal-cookie-koa.d.ts b/@types/universal-cookie-koa.d.ts new file mode 100644 index 000000000..e34774734 --- /dev/null +++ b/@types/universal-cookie-koa.d.ts @@ -0,0 +1,7 @@ +import Cookies from 'universal-cookie'; + +declare module 'koa' { + interface Request { + universalCookies: Cookies; + } +} diff --git a/devIndex.js b/devIndex.js new file mode 100644 index 000000000..f51706157 --- /dev/null +++ b/devIndex.js @@ -0,0 +1,10 @@ +if (process.env.NODE_ENV !== 'production') { + const config = require('./.babelrc.server'); + + require('@babel/register')({ + extensions: ['.js', '.jsx', '.ts', '.tsx'], + ...config, + }); +} + +require('./src/server/index.ts'); diff --git a/package.json b/package.json index 528bd7d24..fd243b9f0 100644 --- a/package.json +++ b/package.json @@ -10,18 +10,19 @@ "scripts": { "build:client:perf": "npm run cleanup && NODE_ENV=production webpack --profile --json > ./webpack-stats.json && webpack-bundle-analyzer ./webpack-stats.json dist/client/static --mode static -s gzip --report ./BundleReport.html --no-open", "build:client": "node scripts/buildClient", - "build:server": "babel src --no-babelrc --config-file ./.babelrc.server.js --out-dir dist/server --copy-files", + "build:server": "babel src -x '.ts,.tsx,.js,.jsx' --no-babelrc --config-file ./.babelrc.server.js --out-dir dist/server --copy-files", "build": "npm run cleanup && npm run build:client && npm run build:server", "cleanup": "rimraf dist && mkdir dist", "dev:server:test": "npm run start:server:test", "dev:server": "npm run start:server", "dev:test": "npm run dev:server:test", "dev": "npm run dev:server", - "lint": "eslint --ext .js,.jsx src", + "lint": "eslint --ext .js,.jsx,.ts,.tsx src test scripts", "start:server:test": "TESTDATA=1 npm run start:server", - "start:server": "node --inspect src/server/index.js", + "start:server": "node --inspect devIndex.js", "flow": "flow check", - "test": "npm run lint && npm run test:server && npm run test:client && flow", + "tsc": "tsc", + "test": "npm run lint && npm run test:server && npm run test:client && tsc && flow", "test:codecov": "codecov", "test:client": "jest --config test/client/jest.config.js", "test:server": "TZ=Europe/Berlin jest --config test/server/jest.config.js" @@ -43,7 +44,66 @@ "@babel/preset-env": "^7.4.3", "@babel/preset-flow": "^7.0.0", "@babel/preset-react": "^7.0.0", + "@babel/preset-typescript": "^7.3.3", "@babel/register": "^7.4.0", + "@types/axios": "^0.14.0", + "@types/babel-core": "^6.25.6", + "@types/bunyan": "^1.8.6", + "@types/bunyan-format": "^0.2.0", + "@types/cheerio": "^0.22.11", + "@types/chokidar": "^2.1.3", + "@types/compression-webpack-plugin": "^2.0.0", + "@types/core-js": "^2.5.0", + "@types/create-react-class": "^15.6.2", + "@types/date-fns": "^2.6.0", + "@types/debounce-promise": "^3.1.1", + "@types/diff": "^4.0.2", + "@types/ejs": "^2.6.3", + "@types/eslint": "^4.16.6", + "@types/eslint-plugin-prettier": "^2.2.0", + "@types/iconv-lite": "^0.0.1", + "@types/iltorb": "^2.3.0", + "@types/jest": "^24.0.11", + "@types/jss": "^9.5.8", + "@types/koa": "^2.0.48", + "@types/koa-bodyparser": "^4.2.2", + "@types/koa-bunyan-logger": "^2.1.0", + "@types/koa-router": "^7.0.40", + "@types/koa-static": "^4.0.1", + "@types/koa-webpack": "^5.0.1", + "@types/lodash": "^4.14.123", + "@types/lolex": "^3.1.1", + "@types/mini-css-extract-plugin": "^0.2.0", + "@types/nock": "^9.3.1", + "@types/node-cache": "^4.1.3", + "@types/node-sass": "^4.11.0", + "@types/optimize-css-assets-webpack-plugin": "^1.3.4", + "@types/prettier": "^1.16.1", + "@types/qs": "^6.5.3", + "@types/react": "^16.8.13", + "@types/react-dom": "^16.8.4", + "@types/react-helmet-async": "^1.0.0", + "@types/react-jss": "^8.6.3", + "@types/react-redux": "^7.0.6", + "@types/react-router": "^4.4.5", + "@types/react-router-config": "^1.1.2", + "@types/react-router-dom": "^4.3.2", + "@types/react-select": "^2.0.16", + "@types/redux": "^3.6.0", + "@types/redux-actions": "^2.6.0", + "@types/redux-thunk": "^2.1.0", + "@types/reselect": "^2.2.0", + "@types/rimraf": "^2.0.2", + "@types/serialize-javascript": "^1.5.0", + "@types/stylelint": "^9.10.0", + "@types/supertest": "^2.0.7", + "@types/terser-webpack-plugin": "^1.2.1", + "@types/typescript": "^2.0.0", + "@types/universal-cookie": "^2.2.0", + "@types/uuid": "^3.4.4", + "@types/webpack": "^4.4.27", + "@types/webpack-bundle-analyzer": "^2.13.1", + "@typescript-eslint/parser": "^1.6.0", "autoprefixer": "^9.5.1", "babel-core": "^7.0.0-bridge.0", "babel-eslint": "^10.0.1", @@ -53,7 +113,6 @@ "babel-plugin-lodash": "^3.3.4", "babel-plugin-module-resolver": "^3.2.0", "babel-plugin-remove-webpack": "^1.1.0", - "babel-plugin-stateless-func-to-pure": "^0.0.2", "babel-plugin-transform-require-ignore": "^0.1.1", "babel-preset-joblift": "^3.3.2", "cache-loader": "^2.0.1", @@ -62,13 +121,13 @@ "compression-webpack-plugin": "^2.0.0", "css-loader": "^2.1.1", "eslint": "^5.16.0", - "eslint-config-joblift": "^3.3.2", + "eslint-config-joblift": "^3.3.4", "eslint-config-prettier": "^4.1.0", "eslint-import-resolver-webpack": "^0.11.1", "eslint-plugin-babel": "^5.3.0", "eslint-plugin-flowtype": "^3.6.1", "eslint-plugin-header": "^3.0.0", - "eslint-plugin-import": "^2.17.0", + "eslint-plugin-import": "^2.17.1", "eslint-plugin-jest": "^22.4.1", "eslint-plugin-prettier": "^3.0.1", "eslint-plugin-react": "^7.12.4", @@ -96,6 +155,7 @@ "stylelint-config-standard": "^18.2.0", "supertest": "^4.0.2", "terser-webpack-plugin": "^1.2.3", + "typescript": "^3.4.3", "url-loader": "^1.1.2", "webpack": "^4.30.0", "webpack-bundle-analyzer": "^3.3.2", diff --git a/scripts/generateMostSearched.js b/scripts/generateMostSearched.js index c11c39188..e75cbbb03 100644 --- a/scripts/generateMostSearched.js +++ b/scripts/generateMostSearched.js @@ -24,14 +24,16 @@ const mostUsedNames = [ 'Berlin-Spandau', ].map(n => n.toLowerCase()); -Promise.all(mostUsedNames.map(s => search(s).then(s => s[0]))).then(stations => { - // eslint-disable-next-line no-console - console.log( - JSON.stringify( - stations.map(s => ({ - title: s.title, - id: s.id, - })) - ) - ); -}); +Promise.all(mostUsedNames.map(s => search(s).then(s => s[0]))).then( + stations => { + // eslint-disable-next-line no-console + console.log( + JSON.stringify( + stations.map(s => ({ + title: s.title, + id: s.id, + })) + ) + ); + } +); diff --git a/src/client/Abfahrten/reducer/abfahrten.js b/src/client/Abfahrten/reducer/abfahrten.js index a4c6fd035..b8530cd96 100644 --- a/src/client/Abfahrten/reducer/abfahrten.js +++ b/src/client/Abfahrten/reducer/abfahrten.js @@ -34,7 +34,7 @@ export type State = { }; const defaultState = { - selectedDetail: localStorage.getItem('selectedDetail'), + selectedDetail: null, abfahrten: null, wings: null, currentStation: null, diff --git a/src/server/Abfahrten/Timetable.js b/src/server/Abfahrten/Timetable.ts similarity index 85% rename from src/server/Abfahrten/Timetable.js rename to src/server/Abfahrten/Timetable.ts index b0c512043..28815f871 100644 --- a/src/server/Abfahrten/Timetable.js +++ b/src/server/Abfahrten/Timetable.ts @@ -1,9 +1,9 @@ -// @flow /* eslint no-continue: 0 */ /* ** This algorithm is heavily inspired by https://github.com/derf/Travel-Status-DE-IRIS ** derf did awesome work reverse engineering the XML stuff! */ +import { Abfahrt } from 'types/abfahrten'; import { addHours, addMinutes, @@ -14,68 +14,63 @@ import { isBefore, subHours, } from 'date-fns'; +import { AxiosInstance } from 'axios'; import { diffArrays } from 'diff'; import { findLast, flatten, last, uniqBy } from 'lodash'; import { getAttr, getNumberAttr, parseTs } from './helper'; import { getCachedLageplan, getLageplan } from '../Bahnhof/Lageplan'; import messageLookup, { messageTypeLookup, - type MessageTypeLookup, - type MessageTypeValues, supersededMessages, } from './messageLookup'; import NodeCache from 'node-cache'; -import xmljs, { type XmlNode } from 'libxmljs2'; -import type { Abfahrt } from 'types/abfahrten'; -import type { Axios } from 'axios'; +import xmljs from 'libxmljs2'; export type Result = { - departures: Abfahrt[], - wings: Object, - lageplan?: ?string, + departures: Abfahrt[]; + wings: Object; + lageplan?: string; }; -type ArDp = {| - platform: ?string, - status: ?string, -|}; -type ParsedDp = {| - ...ArDp, - departureTs: ?string, - scheduledDepartureTs: ?string, - routePost: ?(string[]), -|}; - -type ParsedAr = {| - ...ArDp, - arrivalTs: ?string, - scheduledArrivalTs: ?string, - routePre: ?(string[]), -|}; +type ArDp = { + platform?: string; + status?: string; +}; +type ParsedDp = ArDp & { + departureTs?: string; + scheduledDepartureTs?: string; + routePost?: string[]; +}; + +type ParsedAr = ArDp & { + arrivalTs?: string; + scheduledArrivalTs?: string; + routePre?: string[]; +}; // 6 Hours in seconds const stdTTL = 6 * 60 * 60; -const timetableCache: NodeCache = new NodeCache({ stdTTL }); +const timetableCache = new NodeCache({ stdTTL }); type Route = { - name: string, - isCancelled?: boolean, - isAdditional?: boolean, + name: string; + isCancelled?: boolean; + isAdditional?: boolean; }; export type TimetableOptions = { - lookahead: number, - lookbehind: number, + lookahead: number; + lookbehind: number; }; -const routeMap: string => Route = name => ({ name }); +const routeMap: (s: string) => Route = name => ({ name }); const normalizeRouteName = (name: string) => name .replace('(', ' (') .replace(')', ') ') .trim(); -export function parseDp(dp: ?XmlNode): ?ParsedDp { +export function parseDp(dp): undefined | ParsedDp { if (!dp) return undefined; const routePost = getAttr(dp, 'cpth'); @@ -92,7 +87,7 @@ export function parseDp(dp: ?XmlNode): ?ParsedDp { }; } -export function parseRealtimeAr(ar: ?XmlNode): ?ParsedAr { +export function parseRealtimeAr(ar): undefined | ParsedAr { if (!ar) return undefined; const routePre = getAttr(ar, 'cpth'); @@ -158,7 +153,7 @@ export function splitTrainType(train: string = '') { }; } -export function parseTl(tl: XmlNode) { +export function parseTl(tl) { return { // D = Irregular, like third party // N = Nahverkehr @@ -176,18 +171,21 @@ const idRegex = /-?(\w+)/; const mediumIdRegex = /-?(\w+-\w+)/; function parseRawId(rawId: string) { + const idMatch = rawId.match(idRegex); + const mediumIdMatch = rawId.match(mediumIdRegex); + return { - id: rawId.match(idRegex)?.[1] || rawId, - mediumId: rawId.match(mediumIdRegex)?.[1] || rawId, + id: (idMatch && idMatch[1]) || rawId, + mediumId: (mediumIdMatch && mediumIdMatch[1]) || rawId, }; } const longDistanceRegex = /(ICE?|TGV|ECE?|RJ).*/; export default class Timetable { - axios: Axios; + axios: AxiosInstance; timetable: { - [key: string]: any, + [key: string]: any; } = {}; realtimeIds: string[] = []; evaId: string; @@ -201,7 +199,7 @@ export default class Timetable { evaId: string, currentStation: string, options: TimetableOptions, - axios: Axios + axios: AxiosInstance ) { this.axios = axios; this.evaId = evaId; @@ -238,22 +236,26 @@ export default class Timetable { { name: timetable.currentStation, isCancelled: timetable.isCancelled }, ...timetable.routePost, ]; + const last = findLast(timetable.route, r => !r.isCancelled); + timetable.destination = - findLast(timetable.route, r => !r.isCancelled)?.name || - timetable.scheduledDestination; + (last && last.name) || timetable.scheduledDestination; timetable.via = this.getVia(timetable); - // $FlowFixMe - optional chaining call - const filteredRoutePost = timetable.routePost?.filter(r => !r.isCancelled); + let filteredRoutePost = []; + + if (timetable.routePost) { + filteredRoutePost = timetable.routePost.filter(r => !r.isCancelled); + } timetable.auslastung = !timetable.isCancelled && timetable.longDistance && !timetable.substitute && - Boolean(filteredRoutePost?.length); + Boolean(filteredRoutePost.length); timetable.reihung = !timetable.isCancelled && timetable.longDistance && - Boolean(filteredRoutePost?.length); + Boolean(filteredRoutePost.length); delete timetable.routePre; delete timetable.routePost; @@ -333,7 +335,8 @@ export default class Timetable { } while (viaShow.length < maxParts && important.length) { - const stop = important.shift(); + // @ts-ignore this is correct + const stop: string = important.shift(); if (!viaShow.includes(stop)) { viaShow.push(stop); @@ -343,7 +346,7 @@ export default class Timetable { return viaShow.map(v => v.replace(' Hbf', '')); } - parseRef(tl: XmlNode) { + parseRef(tl) { const { trainType, trainNumber } = parseTl(tl); const train = `${trainType} ${trainNumber}`; @@ -353,12 +356,12 @@ export default class Timetable { train, }; } - parseMessage(mNode: XmlNode) { + parseMessage(mNode) { const value = getNumberAttr(mNode, 'c'); const indexType = getAttr(mNode, 't'); if (!indexType) return undefined; - const type: ?$Keys = messageTypeLookup[indexType]; + const type: undefined | string = messageTypeLookup[indexType]; if (!type || !value || value <= 1) { return undefined; @@ -378,7 +381,7 @@ export default class Timetable { message, }; } - parseRealtimeS(sNode: XmlNode) { + parseRealtimeS(sNode) { const rawId = getAttr(sNode, 'id'); if (!rawId) return; @@ -400,9 +403,9 @@ export default class Timetable { if (!mArr) return; const messages: { - [key: MessageTypeValues]: { - [key: number]: *, - }, + [key: string]: { + [key: number]: any; + }; } = { delay: {}, qos: {}, @@ -446,7 +449,7 @@ export default class Timetable { ref: ref ? this.parseRef(ref) : undefined, }; } - addArrivalInfo(timetable: any, ar: ?ParsedAr) { + addArrivalInfo(timetable: any, ar: undefined | ParsedAr) { if (!ar) return; timetable.arrivalIsCancelled = ar.status === 'c'; timetable.arrivalIsAdditional = ar.status === 'a'; @@ -474,7 +477,7 @@ export default class Timetable { } timetable.platform = ar.platform || timetable.scheduledPlatform; } - addDepartureInfo(timetable: any, dp: ?ParsedDp) { + addDepartureInfo(timetable: any, dp: undefined | ParsedDp) { if (!dp) return; timetable.departureIsCancelled = dp.status === 'c'; timetable.departureIsAdditional = dp.status === 'a'; @@ -539,11 +542,11 @@ export default class Timetable { timetable.ref = realtime.ref; }); } - getWings(node: ?XmlNode, displayAsWing: boolean) { - // $FlowFixMe - optional chaining call - const rawWings: ?(string[]) = getAttr(node, 'wings')?.split('|'); + getWings(node, displayAsWing: boolean) { + const wingAttr = getAttr(node, 'wings'); - if (!rawWings) return undefined; + if (!wingAttr) return; + const rawWings = wingAttr.split('|'); const mediumWings = rawWings.map(w => parseRawId(w).mediumId); @@ -553,7 +556,7 @@ export default class Timetable { return mediumWings; } - parseTimetableS(sNode: XmlNode) { + parseTimetableS(sNode) { const rawId = getAttr(sNode, 'id'); if (!rawId) { @@ -573,14 +576,15 @@ export default class Timetable { const lineNumber = getAttr(dp || ar, 'l'); const { trainNumber, trainType, t, o, productClass } = parseTl(tl); const train = `${trainType} ${lineNumber || trainNumber}`; - // $FlowFixMe - optional chaining call - const routePost: string[] = (getAttr(dp, 'ppth')?.split('|') || []).map( - normalizeRouteName - ); - // $FlowFixMe - optional chaining call - const routePre: string[] = (getAttr(ar, 'ppth')?.split('|') || []).map( - normalizeRouteName - ); + + function getNormalizedRoute(node) { + const rawRoute = getAttr(node, 'ppth'); + + return (rawRoute ? rawRoute.split('|') : []).map(normalizeRouteName); + } + + const routePost = getNormalizedRoute(dp); + const routePre = getNormalizedRoute(ar); return { o, @@ -637,17 +641,17 @@ export default class Timetable { return Promise.all( this.segments.map(async date => { const key = `/plan/${this.evaId}/${format(date, 'yyMMdd/HH')}`; - let rawXml = timetableCache.get(key); + let rawXml = timetableCache.get(key); if (!rawXml) { - rawXml = await this.axios.get(`${key}`).then(x => x.data); + rawXml = await this.axios.get(`${key}`).then(x => x.data); } this.timetable = { ...this.timetable, ...this.getTimetable(rawXml), }; - timetableCache.set(key, rawXml); + timetableCache.set(key, rawXml); }) ); } diff --git a/src/server/Abfahrten/helper.js b/src/server/Abfahrten/helper.ts similarity index 50% rename from src/server/Abfahrten/helper.js rename to src/server/Abfahrten/helper.ts index f70a3d877..64b3d67ae 100644 --- a/src/server/Abfahrten/helper.js +++ b/src/server/Abfahrten/helper.ts @@ -1,13 +1,16 @@ -// @flow import { parseFromTimeZone } from 'date-fns-timezone'; -import { type XmlNode } from 'libxmljs2'; -export function getAttr(node: ?XmlNode, name: string): ?string { - // $FlowFixMe - optional chaining call - return node?.attr(name)?.value(); +export function getAttr(node: any, name: string): undefined | string { + if (node) { + const attr = node.attr(name); + + if (attr) { + return attr.value(); + } + } } -export function getNumberAttr(node: ?XmlNode, name: string): ?number { +export function getNumberAttr(node: any, name: string): undefined | number { const attr = getAttr(node, name); if (!attr) return undefined; @@ -15,7 +18,7 @@ export function getNumberAttr(node: ?XmlNode, name: string): ?number { return Number.parseInt(attr, 10); } -export function getBoolAttr(node: ?XmlNode, name: string): boolean { +export function getBoolAttr(node: any, name: string): boolean { const attr = getAttr(node, name); if (!attr) return false; @@ -23,7 +26,7 @@ export function getBoolAttr(node: ?XmlNode, name: string): boolean { return attr === 'true'; } -export function parseTs(ts: ?string): ?Date { +export function parseTs(ts?: string): undefined | number { if (ts) { return parseFromTimeZone(ts, 'YYMMDDHHmm', { timeZone: 'Europe/Berlin', diff --git a/src/server/Abfahrten/index.js b/src/server/Abfahrten/index.ts similarity index 87% rename from src/server/Abfahrten/index.js rename to src/server/Abfahrten/index.ts index f1710b3b3..fa1241dfc 100644 --- a/src/server/Abfahrten/index.js +++ b/src/server/Abfahrten/index.ts @@ -1,13 +1,12 @@ -// @flow -import { Axios } from 'axios'; import { compareAsc } from 'date-fns'; import { getStation } from './station'; -import Timetable, { type Result } from './Timetable'; +import Axios, { AxiosInstance } from 'axios'; +import Timetable, { Result } from './Timetable'; -export const noncdAxios = new Axios({ +export const noncdAxios = Axios.create({ baseURL: 'http://iris.noncd.db.de/iris-tts/timetable', }); -export const openDataAxios = new Axios({ +export const openDataAxios = Axios.create({ baseURL: 'https://api.deutschebahn.com/timetables/v1', headers: { Authorization: `Bearer ${process.env.TIMETABLES_OPEN_DATA_KEY || ''}`, @@ -15,8 +14,8 @@ export const openDataAxios = new Axios({ }); type AbfahrtenOptions = { - lookahead?: number, - lookbehind?: number, + lookahead?: number; + lookbehind?: number; }; const defaultOptions = { lookahead: 150, @@ -45,7 +44,7 @@ export async function getAbfahrten( evaId: string, withRelated: boolean = true, options: AbfahrtenOptions = {}, - axios: Axios = noncdAxios + axios: AxiosInstance = noncdAxios ): Promise { const lookahead = options.lookahead || defaultOptions.lookahead; const lookbehind = options.lookbehind || defaultOptions.lookbehind; @@ -82,7 +81,7 @@ export async function getAbfahrten( b.departureIsCancelled && !b.isCancelled ? b.scheduledArrival : b.scheduledDeparture || b.scheduledArrival; - // $FlowFixMe - either arrival or departure always exists + // @ts-ignore - either arrival or departure always exists const sort = compareAsc(timeA, timeB); if (!sort) { diff --git a/src/server/Abfahrten/messageLookup.js b/src/server/Abfahrten/messageLookup.ts similarity index 96% rename from src/server/Abfahrten/messageLookup.js rename to src/server/Abfahrten/messageLookup.ts index 62cc98c4a..807256b7c 100644 --- a/src/server/Abfahrten/messageLookup.js +++ b/src/server/Abfahrten/messageLookup.ts @@ -1,4 +1,3 @@ -// @flow /* ** Initially this file is copied from https://github.com/derf/Travel-Status-DE-IRIS ** Thanks for finding these! @@ -97,8 +96,6 @@ export const messageTypeLookup = { r: 'disruption', c: 'connection', }; -export type MessageTypeLookup = typeof messageTypeLookup; -export type MessageTypeValues = $Values; export const supersededMessages = { '84': ['80', '82', '85'], diff --git a/src/server/Abfahrten/performance.js b/src/server/Abfahrten/performance.ts similarity index 97% rename from src/server/Abfahrten/performance.js rename to src/server/Abfahrten/performance.ts index 26f84cb80..425ed5cdb 100644 --- a/src/server/Abfahrten/performance.js +++ b/src/server/Abfahrten/performance.ts @@ -5,8 +5,8 @@ import { max, min, sum } from 'lodash'; import { performance, PerformanceObserver } from 'perf_hooks'; const timeMap = { - noncd: [], - openData: [], + noncd: [] as number[], + openData: [] as number[], }; const obs = new PerformanceObserver(items => { items.getEntries().forEach(e => { diff --git a/src/server/Abfahrten/station.js b/src/server/Abfahrten/station.ts similarity index 80% rename from src/server/Abfahrten/station.js rename to src/server/Abfahrten/station.ts index e9a98a4b1..a9ec9b968 100644 --- a/src/server/Abfahrten/station.js +++ b/src/server/Abfahrten/station.ts @@ -1,27 +1,26 @@ -// @flow /* eslint no-param-reassign: 0, no-await-in-loop: 0 */ +import { AxiosInstance } from 'axios'; import { flatten } from 'lodash'; import { noncdAxios } from './index'; import NodeCache from 'node-cache'; import xmljs from 'libxmljs2'; -import type { Axios } from 'axios'; export type Station = { - name: string, - meta: string[], - eva: string, - ds100: string, - db: string, - creationts: string, - p: string, + name: string; + meta: string[]; + eva: string; + ds100: string; + db: string; + creationts: string; + p: string; }; // 4 Hours in seconds const stdTTL = 4 * 60 * 60; -const cache: NodeCache = new NodeCache({ stdTTL }); +const cache = new NodeCache({ stdTTL }); function parseStation(stationNode): Station { - const station = {}; + const station: any = {}; stationNode.attrs().forEach(a => { station[a.name()] = a.value(); @@ -37,9 +36,9 @@ function parseStation(stationNode): Station { export async function getSingleStation( evaId: string, - axios: Axios = noncdAxios -) { - const cached = cache.get(evaId); + axios: AxiosInstance = noncdAxios +): Promise { + const cached = cache.get(evaId); if (cached) { return cached; @@ -68,15 +67,14 @@ export async function getSingleStation( export async function getStation( evaId: string, recursive: number = 0, - axios?: Axios + axios?: AxiosInstance ) { const station = await getSingleStation(evaId, axios); let queue = station.meta; const seen = [station.eva]; - const relatedStations = []; + const relatedStations: Station[] = []; while (recursive > 0 && queue.length) { - // $FlowFixMe recursive -= 1; queue = flatten( await Promise.all( diff --git a/src/server/Abfahrten/wings.js b/src/server/Abfahrten/wings.ts similarity index 92% rename from src/server/Abfahrten/wings.js rename to src/server/Abfahrten/wings.ts index 0fe723584..555e3ef62 100644 --- a/src/server/Abfahrten/wings.js +++ b/src/server/Abfahrten/wings.ts @@ -1,5 +1,4 @@ -// @flow -import { type Axios } from 'axios'; +import { AxiosInstance } from 'axios'; import { getAttr, getBoolAttr, parseTs } from './helper'; import { noncdAxios } from '.'; import xmljs from 'libxmljs2'; @@ -22,7 +21,7 @@ function parseNode(node) { export default async function wingInfo( rawId1: string, rawId2: string, - axios: Axios = noncdAxios + axios: AxiosInstance = noncdAxios ) { const rawXml = (await axios.get(`/wingdef/${rawId1}/${rawId2}`)).data; const node = xmljs.parseXml(rawXml); diff --git a/src/server/Auslastung.js b/src/server/Auslastung.ts similarity index 91% rename from src/server/Auslastung.js rename to src/server/Auslastung.ts index 5eacf42a6..2737ec491 100644 --- a/src/server/Auslastung.js +++ b/src/server/Auslastung.ts @@ -1,4 +1,3 @@ -// @flow import axios from 'axios'; import cheerio from 'cheerio'; import NodeCache from 'node-cache'; @@ -6,12 +5,7 @@ import qs from 'qs'; // 15 Minutes in seconds const stdTTL = 15 * 60; -const cache: NodeCache< - number, - { - data: Object, - } -> = new NodeCache({ stdTTL }); +const cache = new NodeCache({ stdTTL }); function mapStop(stop) { switch (stop) { @@ -30,7 +24,7 @@ export default function createAuslastungsFunction( username: string, password: string ) { - return async function zugAuslastung(trainId: number, date: string) { + return async function zugAuslastung(trainId: string, date: string) { const cached = cache.get(trainId); if (cached) { diff --git a/src/server/Bahnhof/Lageplan.js b/src/server/Bahnhof/Lageplan.ts similarity index 91% rename from src/server/Bahnhof/Lageplan.js rename to src/server/Bahnhof/Lageplan.ts index d5e49dac1..b0cb83fda 100644 --- a/src/server/Bahnhof/Lageplan.js +++ b/src/server/Bahnhof/Lageplan.ts @@ -1,10 +1,9 @@ -// @flow import axios from 'axios'; import cheerio from 'cheerio'; import NodeCache from 'node-cache'; import qs from 'qs'; -export const cache: NodeCache = new NodeCache(); +export const cache: NodeCache = new NodeCache(); export async function getLageplan(stationName: string) { const cached = cache.get(stationName); @@ -51,5 +50,5 @@ export async function getLageplan(stationName: string) { return pdfLink; } export function getCachedLageplan(stationName: string) { - return cache.get(stationName); + return cache.get(stationName); } diff --git a/src/server/Controller.js b/src/server/Controller.ts similarity index 83% rename from src/server/Controller.js rename to src/server/Controller.ts index 242acb1ce..7bd033518 100644 --- a/src/server/Controller.js +++ b/src/server/Controller.ts @@ -1,4 +1,3 @@ -// @flow import { getAbfahrten } from './Abfahrten'; import { getLageplan } from './Bahnhof/Lageplan'; import { getStation } from './Abfahrten/station'; @@ -19,7 +18,7 @@ import wingInfo from './Abfahrten/wings'; const router = new KoaRouter(); // Favendo offline? -async function stationInfo(station: number) { +async function stationInfo(station: string) { const info = (await axios.get( `https://si.favendo.de/station-info/rest/api/station/${station}` )).data; @@ -35,32 +34,31 @@ async function stationInfo(station: number) { router .prefix('/api') .get('/lageplan/:stationName', async ctx => { - const { stationName } = ctx.params; + const { stationName }: { stationName: string } = ctx.params; ctx.body = { lageplan: await getLageplan(stationName), }; }) .get('/search/:searchTerm', async ctx => { - const { searchTerm } = ctx.params; + const { searchTerm }: { searchTerm: string } = ctx.params; const { type } = ctx.query; - // $FlowFixMe - assume type is StationSearchType ctx.body = await stationSearch(searchTerm, type); }) // https://si.favendo.de/station-info/rest/api/station/724 .get('/station/:station', async ctx => { - const { station } = ctx.params; + const { station }: { station: string } = ctx.params; ctx.body = await stationInfo(station); }) .get('/irisStation/:evaId', async ctx => { - const { evaId } = ctx.params; + const { evaId }: { evaId: string } = ctx.params; ctx.body = await getStation(evaId, 1); }) .get('/ownAbfahrten/:evaId', async ctx => { - const { evaId } = ctx.params; + const { evaId }: { evaId: string } = ctx.params; if (evaId.length < 6) { ctx.status = 400; @@ -76,7 +74,7 @@ router } }) .get('/ownAbfahrtenOpen/:evaId', async ctx => { - const { evaId } = ctx.params; + const { evaId }: { evaId: string } = ctx.params; if (evaId.length < 6) { ctx.status = 400; @@ -97,12 +95,15 @@ router } }) .get('/wagenstation/:train/:station', async ctx => { - const { train, station } = ctx.params; + const { train, station }: { train: string; station: string } = ctx.params; ctx.body = await wagenReihungStation([train], station); }) .get('/wagen/:trainNumber/:date', async ctx => { - const { date, trainNumber } = ctx.params; + const { + date, + trainNumber, + }: { date: string; trainNumber: string } = ctx.params; ctx.body = await wagenReihung(trainNumber, Number.parseInt(date, 10)); }) @@ -113,7 +114,7 @@ router } }) .get('/wings/:rawId1/:rawId2', async ctx => { - const { rawId1, rawId2 } = ctx.params; + const { rawId1, rawId2 }: { rawId1: string; rawId2: string } = ctx.params; ctx.body = await wingInfo(rawId1, rawId2); }) @@ -138,7 +139,10 @@ if (AuslastungsUser && AuslastungsPW) { // YYYYMMDD router.get('/auslastung/:trainNumber/:date', async ctx => { - const { date, trainNumber } = ctx.params; + const { + date, + trainNumber, + }: { date: string; trainNumber: string } = ctx.params; ctx.body = await auslastung(trainNumber, date); }); diff --git a/src/server/Reihung.js b/src/server/Reihung.ts similarity index 91% rename from src/server/Reihung.js rename to src/server/Reihung.ts index 710bf688b..c9231f9f6 100644 --- a/src/server/Reihung.js +++ b/src/server/Reihung.ts @@ -1,12 +1,10 @@ -// @flow import { convertToTimeZone } from 'date-fns-timezone'; +import { Fahrzeug, Formation, Wagenreihung } from 'types/reihung'; import { flatten, maxBy, minBy } from 'lodash'; import { format } from 'date-fns'; import { getAbfahrten } from './Abfahrten'; +import { WagenreihungStation } from 'types/reihungStation'; import axios from 'axios'; -import type { Abfahrt } from 'types/abfahrten'; -import type { Fahrzeug, Formation, Wagenreihung } from 'types/reihung'; -import type { WagenreihungStation } from 'types/reihungStation'; // Rausfinden ob alle Teile zum gleichen Ort fahren function differentDestination(formation: Formation) { @@ -57,13 +55,13 @@ function specificTrainType(formation: Formation, fahrzeuge: Fahrzeug[]) { if (minFahrzeug) { g.startProzent = Number.parseInt( - minFahrzeug?.positionamhalt.startprozent, + minFahrzeug.positionamhalt.startprozent, 10 ); } if (maxFahrzeug) { g.endeProzent = Number.parseInt( - maxFahrzeug?.positionamhalt.endeprozent, + maxFahrzeug.positionamhalt.endeprozent, 10 ); } @@ -162,8 +160,8 @@ export async function wagenReihung(trainNumber: string, date: number) { fahrzeuge ); info.data.istformation.realFahrtrichtung = fahrtrichtung(fahrzeuge); - info.data.istformation.allFahrzeuggruppe.forEach(g => { - g.allFahrzeug.forEach(f => { + info.data.istformation.allFahrzeuggruppe.every(g => + g.allFahrzeug.every(f => { const start = Number.parseInt(f.positionamhalt.startprozent, 10); const end = Number.parseInt(f.positionamhalt.endeprozent, 10); @@ -173,8 +171,10 @@ export async function wagenReihung(trainNumber: string, date: number) { if (end > endPercentage) { endPercentage = end; } - }); - }); + + return true; + }) + ); info.data.istformation.scale = 100 / (endPercentage - startPercentage); info.data.istformation.startPercentage = startPercentage; @@ -186,7 +186,7 @@ export async function wagenReihung(trainNumber: string, date: number) { // https://ws.favendo.de/wagon-order/rest/v1/si/1401 export async function wagenReihungStation( trainNumbers: string[], - station: number + station: string ) { const info: WagenreihungStation = (await axios.post( `https://ws.favendo.de/wagon-order/rest/v1/si/${station}`, @@ -210,7 +210,7 @@ export async function wagenReihungMonitoring() { d => d.reihung && d.scheduledDeparture ); - let departure: ?Abfahrt = maybeDepartures.shift(); + let departure = maybeDepartures.shift(); while (departure) { const departureTime = departure.scheduledDeparture; @@ -229,7 +229,11 @@ export async function wagenReihungMonitoring() { departure = maybeDepartures.shift(); } catch (e) { // eslint-disable-next-line no-console - console.warn('Failed to get WR for Monitoring!', e, departure.train); + console.warn( + 'Failed to get WR for Monitoring!', + e, + departure && departure.train + ); departure = maybeDepartures.shift(); } } diff --git a/src/server/Routing/DBNavigator.js b/src/server/Routing/DBNavigator.ts similarity index 94% rename from src/server/Routing/DBNavigator.js rename to src/server/Routing/DBNavigator.ts index 5eeb28c2a..e2ff78e51 100644 --- a/src/server/Routing/DBNavigator.js +++ b/src/server/Routing/DBNavigator.ts @@ -1,10 +1,9 @@ -// @flow import { formatToTimeZone } from 'date-fns-timezone'; +import { Options } from '.'; +import { SRoute$Result } from 'types/routing'; import axios from 'axios'; import createChecksum from 'server/dbNavUtil'; import parse from './parse'; -import type { Options } from '.'; -import type { SRoute$Result } from 'types/routing'; const BASE_URL = 'https://reiseauskunft.bahn.de/bin/mgate.exe'; @@ -90,7 +89,7 @@ function createRequest({ } export default function routeDBNav( options: Options, - parseFunction: SRoute$Result => any = parse + parseFunction: (result: SRoute$Result) => any = parse ) { const { data, checksum } = createRequest(options); diff --git a/src/server/Routing/index.js b/src/server/Routing/index.js deleted file mode 100644 index d9d1c8910..000000000 --- a/src/server/Routing/index.js +++ /dev/null @@ -1,17 +0,0 @@ -// @flow -import routeSearch from './DBNavigator'; - -export type Options = { - start: string, - destination: string, - time: number, - transferTime?: number, - maxChanges?: number, - getPasslist?: boolean, - searchForDeparture?: boolean, - economic?: boolean, - getTariff?: boolean, -}; - -export default (options: Options, parse?: Function) => - routeSearch(options, parse); diff --git a/src/server/Routing/index.ts b/src/server/Routing/index.ts new file mode 100644 index 000000000..cc8767818 --- /dev/null +++ b/src/server/Routing/index.ts @@ -0,0 +1,17 @@ +import { SRoute$Result } from 'types/routing'; +import routeSearch from './DBNavigator'; + +export type Options = { + start: string; + destination: string; + time: number; + transferTime?: number; + maxChanges?: number; + getPasslist?: boolean; + searchForDeparture?: boolean; + economic?: boolean; + getTariff?: boolean; +}; + +export default (options: Options, parse?: (result: SRoute$Result) => any) => + routeSearch(options, parse); diff --git a/src/server/Routing/parse.js b/src/server/Routing/parse.ts similarity index 85% rename from src/server/Routing/parse.js rename to src/server/Routing/parse.ts index 1671b5c52..9e6f9679a 100644 --- a/src/server/Routing/parse.js +++ b/src/server/Routing/parse.ts @@ -1,7 +1,6 @@ -// @flow import { addMilliseconds, differenceInMinutes, parse } from 'date-fns'; import { flatten } from 'lodash'; -import type { +import { Route, Route$Arrival, Route$Departure, @@ -12,7 +11,7 @@ import type { SRoute$Result, SRoute$StopL, } from 'types/routing'; -import type { Station } from 'types/station'; +import { Station } from 'types/station'; function parseDuration(duration: string) { const sanitized = duration.padStart(8, '0'); @@ -30,11 +29,18 @@ const nameRegex = /O=([^@]+)/; const evaRegex = /L=(\d+)/; function parseFullStation(fullStation: string): Station { + const titleMatch = fullStation.match(nameRegex); + const idMatch = fullStation.match(evaRegex); + + let title; + let id; + + if (titleMatch && titleMatch[1]) title = titleMatch[1]; + if (idMatch && idMatch[1]) id = idMatch[1].padStart(7, '0'); + return { - // $FlowFixMe - title: fullStation.match(nameRegex)?.[1], - // $FlowFixMe - id: fullStation.match(evaRegex)?.[1].padStart(7, '0'), + title, + id, }; } @@ -42,7 +48,7 @@ class Journey { raw: SRoute$Journey; date: number; journey: Route; - prodL: *; + prodL; locL: Station[]; constructor(raw: SRoute$Journey, prodL, locL) { this.raw = raw; @@ -63,10 +69,10 @@ class Journey { ...this.parseDeparture(raw.dep), segments, segmentTypes: segments.map(s => s.trainType), - raw: PROD ? undefined : raw, + raw: global.PROD ? undefined : raw, }; } - parseStops = (stops: void | SRoute$StopL[]): Route$Stop[] | void => { + parseStops = (stops?: SRoute$StopL[]): Route$Stop[] | undefined => { if (!stops) return; return stops.map(stop => { @@ -82,7 +88,9 @@ class Journey { }; }); }; - parseSegment = (t: SRoute$JourneySegment): ?Route$JourneySegment => { + parseSegment = ( + t: SRoute$JourneySegment + ): undefined | Route$JourneySegment => { switch (t.type) { case 'JNY': { const [ @@ -126,8 +134,8 @@ class Journey { scheduledDeparture && scheduledArrival - scheduledDeparture, finalDestination: t.jny.dirTxt, - product: PROD ? undefined : product, - raw: PROD ? undefined : t, + product: global.PROD ? undefined : product, + raw: global.PROD ? undefined : t, }; } // case 'WALK': @@ -135,16 +143,16 @@ class Journey { return undefined; } }; - parseTime(time: ?string): number | void { + parseTime(time?: string): number | undefined { if (!time) return undefined; return addMilliseconds(this.date, parseDuration(time)).getTime(); } parseArrival(a: { - +aTimeS?: string, - +aTimeR?: string, - +aPlatfS?: string, - +aPlatfR?: string, + aTimeS?: string; + aTimeR?: string; + aPlatfS?: string; + aPlatfR?: string; }): Route$Arrival { const scheduledArrival = this.parseTime(a.aTimeS); let arrival = scheduledArrival; @@ -167,10 +175,10 @@ class Journey { }; } parseDeparture(d: { - +dTimeS?: string, - +dTimeR?: string, - +dPlatfS?: string, - +dPlatfR?: string, + dTimeS?: string; + dTimeR?: string; + dPlatfS?: string; + dPlatfR?: string; }): Route$Departure { const scheduledDeparture = this.parseTime(d.dTimeS); let departure = scheduledDeparture; diff --git a/src/server/Search/DBNavigator.js b/src/server/Search/DBNavigator.ts similarity index 91% rename from src/server/Search/DBNavigator.js rename to src/server/Search/DBNavigator.ts index c1ee2ea1c..f8f1e3d0c 100644 --- a/src/server/Search/DBNavigator.js +++ b/src/server/Search/DBNavigator.ts @@ -1,7 +1,6 @@ -// @flow +import { Station } from 'types/station'; import axios from 'axios'; import createChecksum from 'server/dbNavUtil'; -import type { Station } from 'types/station'; function createRequest(searchTerm: string, type: 'S' | 'ALL') { const data = { @@ -43,7 +42,7 @@ export default ( .map(s => ({ title: s.name, id: s.extId.substr(2), - raw: PROD ? undefined : s, + raw: global.PROD ? undefined : s, })) ); }; diff --git a/src/server/Search/Favendo.js b/src/server/Search/Favendo.ts similarity index 89% rename from src/server/Search/Favendo.js rename to src/server/Search/Favendo.ts index 9157061e8..35bd9745b 100644 --- a/src/server/Search/Favendo.js +++ b/src/server/Search/Favendo.ts @@ -1,6 +1,5 @@ -// @flow +import { Station } from 'types/station'; import axios from 'axios'; -import type { Station } from 'types/station'; function encodeSearchTerm(term: string) { return term @@ -26,6 +25,6 @@ export default async function(searchTerm: string): Promise { title: s.title, id: s.eva_ids.shift(), favendoId: s.id, - raw: PROD ? undefined : s, + raw: global.PROD ? undefined : s, })); } diff --git a/src/server/Search/Hafas.js b/src/server/Search/Hafas.ts similarity index 88% rename from src/server/Search/Hafas.js rename to src/server/Search/Hafas.ts index 0bab88834..13e51119f 100644 --- a/src/server/Search/Hafas.js +++ b/src/server/Search/Hafas.ts @@ -1,7 +1,6 @@ -// @flow +import { Station } from 'types/station'; import axios from 'axios'; import iconv from 'iconv-lite'; -import type { Station } from 'types/station'; export default async function(searchTerm: string): Promise { const buffer = (await axios.get( @@ -22,6 +21,6 @@ export default async function(searchTerm: string): Promise { .map(s => ({ title: s.value, id: Number.parseInt(s.extId, 10).toString(), - raw: PROD ? undefined : s, + raw: global.PROD ? undefined : s, })); } diff --git a/src/server/Search/OpenDB.js b/src/server/Search/OpenDB.ts similarity index 91% rename from src/server/Search/OpenDB.js rename to src/server/Search/OpenDB.ts index d4ae7930f..01f46275e 100644 --- a/src/server/Search/OpenDB.js +++ b/src/server/Search/OpenDB.ts @@ -1,6 +1,5 @@ -// @flow +import { Station } from 'types/station'; import axios from 'axios'; -import type { Station } from 'types/station'; // istanbul ignore next const authKey = process.env.OPENDB_AUTH_KEY || ''; @@ -28,6 +27,6 @@ export default async (rawSearchTerm: string): Promise => { return stations.map(s => ({ title: s.name, id: Number.parseInt(s.id, 10).toString(), - raw: PROD ? undefined : s, + raw: global.PROD ? undefined : s, })); }; diff --git a/src/server/Search/OpenData.js b/src/server/Search/OpenData.ts similarity index 75% rename from src/server/Search/OpenData.js rename to src/server/Search/OpenData.ts index 3ac4c1adc..4026e2be2 100644 --- a/src/server/Search/OpenData.js +++ b/src/server/Search/OpenData.ts @@ -1,6 +1,5 @@ -// @flow +import { Station } from 'types/station'; import axios from 'axios'; -import type { Station } from 'types/station'; // https://developer.deutschebahn.com/store/apis/info?name=StaDa-Station_Data&version=v2&provider=DBOpenData // istanbul ignore next @@ -27,8 +26,10 @@ export default async (rawSearchTerm: string): Promise => { return result.result.map(s => ({ title: s.name, favendoId: s.number, - id: String(s.evaNumbers[0]?.number), - DS100: s.ril100Identifiers[0]?.rilIdentifier, - raw: PROD ? undefined : s, + id: String(s.evaNumbers[0] ? s.evaNumbers[0].number : undefined), + DS100: s.ril100Identifiers[0] + ? s.ril100Identifiers[0].rilIdentifier + : undefined, + raw: global.PROD ? undefined : s, })); }; diff --git a/src/server/Search/OpenDataOffline.js b/src/server/Search/OpenDataOffline.ts similarity index 59% rename from src/server/Search/OpenDataOffline.js rename to src/server/Search/OpenDataOffline.ts index 54fd72214..92d4979c3 100644 --- a/src/server/Search/OpenDataOffline.js +++ b/src/server/Search/OpenDataOffline.ts @@ -1,8 +1,7 @@ -// @flow import { orderBy } from 'lodash'; +import { Station } from 'types/station'; import Fuse from 'fuse.js'; -import rawStations, { type OpenDataStation } from 'db-stations/data.json'; -import type { Station } from 'types/station'; +import rawStations from 'db-stations/data.json'; const searchableStations = new Fuse(rawStations, { includeScore: true, @@ -17,23 +16,20 @@ const searchableStations = new Fuse(rawStations, { }); export default function(searchTerm: string): Promise { - const matches: { - item: OpenDataStation, - score: number, - }[] = searchableStations.search(searchTerm); + const matches = searchableStations.search(searchTerm); const weightedMatches = matches.map(m => ({ item: m.item, - score: (1 - m.score * 2) * m.item.weight, + score: (1 - (m.score || 0) * 2) * m.item.weight, })); return Promise.resolve( - orderBy(weightedMatches, 'score', ['desc']).map(({ item }) => ({ + orderBy(weightedMatches, 'score', ['desc']).map(({ item }) => ({ title: item.name, id: item.id, DS100: item.ds100, favendoId: item.nr, - raw: PROD ? undefined : item, + raw: global.PROD ? undefined : item, })) ); } diff --git a/src/server/Search/StationsData.js b/src/server/Search/StationsData.ts similarity index 69% rename from src/server/Search/StationsData.js rename to src/server/Search/StationsData.ts index 9a062bba8..a6c69236e 100644 --- a/src/server/Search/StationsData.js +++ b/src/server/Search/StationsData.ts @@ -1,9 +1,8 @@ -// @flow import { orderBy } from 'lodash'; +import { Station } from 'types/station'; import fs from 'fs'; import Fuse from 'fuse.js'; import path from 'path'; -import type { Station } from 'types/station'; const dataPath = path.resolve(__dirname, 'data/Stationsdaten.csv'); // eslint-disable-next-line no-sync @@ -12,13 +11,13 @@ const csv = fs.readFileSync(dataPath, 'utf8'); const entries: Array> = csv.split('\n').map(l => l.split(';')); type StationsData = { - id: string, - DS100: string, - ifopt: string, - name: string, - verkehr: 'FV' | 'NV' | 'DPN', - lng: string, - lat: string, + id: string; + DS100: string; + ifopt: string; + name: string; + verkehr: 'FV' | 'NV' | 'DPN'; + lng: string; + lat: string; }; // Remve HeaderLine @@ -31,8 +30,7 @@ const stationData: StationsData[] = entries.map(e => { DS100, ifopt, name, - // $FlowFixMe this works - verkehr, + verkehr: verkehr as any, lng, lat, }; @@ -49,17 +47,14 @@ const searchableStations = new Fuse(stationData, { }); export default function(searchTerm: string): Promise { - const matches: { - item: StationsData, - score: number, - }[] = searchableStations.search(searchTerm); + const matches = searchableStations.search(searchTerm); return Promise.resolve( - orderBy<_>(matches, 'score', ['asc']).map(({ item }) => ({ + orderBy(matches, 'score', ['asc']).map(({ item }) => ({ title: item.name, id: item.id, DS100: item.DS100, - raw: PROD ? undefined : item, + raw: global.PROD ? undefined : item, })) ); } diff --git a/src/server/Search/index.js b/src/server/Search/index.ts similarity index 83% rename from src/server/Search/index.js rename to src/server/Search/index.ts index dff845006..fa74fc0ed 100644 --- a/src/server/Search/index.js +++ b/src/server/Search/index.ts @@ -1,6 +1,6 @@ -// @flow import { flatten, uniqBy } from 'lodash'; import { logger } from 'server/logger'; +import { Station } from 'types/station'; import DBNavigatorSearch from './DBNavigator'; import FavendoSearch from './Favendo'; import HafasSearch from './Hafas'; @@ -9,7 +9,6 @@ import OpenDataOfflineSearch from './OpenDataOffline'; import OpenDataSearch from './OpenData'; import OpenDBSearch from './OpenDB'; import StationsDataSearch from './StationsData'; -import type { Station } from 'types/station'; export async function favendoOpenDBCombined( searchTerm: string @@ -22,7 +21,7 @@ export async function favendoOpenDBCombined( return uniqBy(flatten(stations), 'id'); } -export function getSearchMethod(type: ?StationSearchType) { +export function getSearchMethod(type?: StationSearchType) { switch (type) { case 'dbNav': return DBNavigatorSearch; @@ -44,7 +43,7 @@ export function getSearchMethod(type: ?StationSearchType) { } } -const searchCaches: Map> = new Map(); +const searchCaches: Map = new Map(); // 6 Hours in seconds const stdTTL = 6 * 60 * 60; @@ -54,14 +53,14 @@ function getCache(key: Function) { if (cached) { return cached; } - const cache: NodeCache = new NodeCache({ stdTTL }); + const cache: NodeCache = new NodeCache({ stdTTL }); searchCaches.set(key, cache); return cache; } -export default async (rawSearchTerm: string, type: ?StationSearchType) => { +export default async (rawSearchTerm: string, type?: StationSearchType) => { const searchTerm = rawSearchTerm.replace(/ {2}/g, ' '); try { @@ -93,9 +92,11 @@ export default async (rawSearchTerm: string, type: ?StationSearchType) => { logger.error(message, { searchMethod: type, error: { - statusText: e.response?.statusText, - data: e.response?.data, - status: e.response?.status, + ...(e.response && { + statusText: e.response.statustext, + data: e.response.data, + status: e.response.status, + }), raw: e, }, }); diff --git a/src/server/admin.js b/src/server/admin.ts similarity index 100% rename from src/server/admin.js rename to src/server/admin.ts diff --git a/src/server/app.js b/src/server/app.ts similarity index 93% rename from src/server/app.js rename to src/server/app.ts index 6ca480c79..175abc916 100644 --- a/src/server/app.js +++ b/src/server/app.ts @@ -1,18 +1,17 @@ -// @flow import './features'; import { middlewares } from './logger'; +import { Server } from 'https'; import axios from 'axios'; import cookiesMiddleware from 'universal-cookie-koa'; import createAdmin from './admin'; import errorHandler from './errorHandler'; import http from 'http'; -import Koa, { type Middleware } from 'koa'; +import Koa, { Middleware } from 'koa'; import KoaBodyparser from 'koa-bodyparser'; import koaStatic from 'koa-static'; import path from 'path'; -// eslint-disable-next-line no-underscore-dangle -global.__SERVER__ = true; +global.SERVER = true; function transformStats(stats) { const newStats = {}; @@ -45,7 +44,7 @@ function hotHelper(getMiddleware: () => Middleware) { return (ctx, next) => getMiddleware()(ctx, next); } -export async function createApp(wsServer: ?https$Server) { +export async function createApp(wsServer: undefined | Server) { const app = new Koa(); app.use(errorHandler); @@ -101,14 +100,14 @@ export async function createApp(wsServer: ?https$Server) { app.use(hotHelper(() => serverRender)); - return (app: any); + return app; } export default async () => { const port = process.env.WEB_PORT || 9042; let server; - let wsServer; + let wsServer: undefined | Server; if ( process.env.NODE_ENV !== 'production' && diff --git a/src/server/dbNavUtil.js b/src/server/dbNavUtil.ts similarity index 98% rename from src/server/dbNavUtil.js rename to src/server/dbNavUtil.ts index c3c3f1e5b..6a40c8e29 100644 --- a/src/server/dbNavUtil.js +++ b/src/server/dbNavUtil.ts @@ -1,4 +1,3 @@ -// @flow import Crypto from 'crypto'; function getSecret() { diff --git a/src/server/errorHandler.js b/src/server/errorHandler.ts similarity index 84% rename from src/server/errorHandler.js rename to src/server/errorHandler.ts index 9aeb628f2..73d47850a 100644 --- a/src/server/errorHandler.js +++ b/src/server/errorHandler.ts @@ -1,7 +1,7 @@ -// @ƒlow +import { Context } from 'koa'; import serialize from 'serialize-javascript'; -export default async (ctx, next) => { +export default async (ctx: Context, next: Function) => { try { // eslint-disable-next-line callback-return await next(); diff --git a/src/server/features/default.js b/src/server/features/default.ts similarity index 88% rename from src/server/features/default.js rename to src/server/features/default.ts index a31f960d0..3d14dcd91 100644 --- a/src/server/features/default.js +++ b/src/server/features/default.ts @@ -1,4 +1,3 @@ -// @flow export default { 'google-analytics': false, routing: true, diff --git a/src/server/features/index.js b/src/server/features/index.ts similarity index 92% rename from src/server/features/index.js rename to src/server/features/index.ts index 83fd9bd11..e030aab85 100644 --- a/src/server/features/index.js +++ b/src/server/features/index.ts @@ -1,4 +1,3 @@ -// @flow const Unleash = require('unleash-client'); const url = process.env.FEATURE_URL; @@ -14,7 +13,6 @@ if (url && instanceId && appName) { } else { // eslint-disable-next-line no-console console.log('Overriding feature stuff to always true!'); - // $FlowFixMe Unleash.isEnabled = key => Boolean(require('./default').default[key]); } @@ -24,6 +22,6 @@ export function getFeatures(): Features { features[key] = Unleash.isEnabled(key); return features; - // $FlowFixMe - this works + // @ts-ignore this works }, {}); } diff --git a/src/server/index.js b/src/server/index.js deleted file mode 100644 index d7cb32cf0..000000000 --- a/src/server/index.js +++ /dev/null @@ -1,17 +0,0 @@ -// @flow -if (process.env.NODE_ENV !== 'production') { - // $FlowFixMe - const config = require('../../.babelrc.server'); - - require('@babel/register')(config); -} - -if (!process.env.BASE_URL) { - throw new Error('Missing BASE_URL'); -} - -global.PROD = process.env.NODE_ENV === 'production'; -global.SERVER = true; - -require('./localStorageShim'); -require('./app').default(); diff --git a/src/server/index.ts b/src/server/index.ts new file mode 100644 index 000000000..838c6a980 --- /dev/null +++ b/src/server/index.ts @@ -0,0 +1,8 @@ +if (!process.env.BASE_URL) { + throw new Error('Missing BASE_URL'); +} + +global.PROD = process.env.NODE_ENV === 'production'; +global.SERVER = true; + +require('./app').default(); diff --git a/src/server/localStorageShim.js b/src/server/localStorageShim.js deleted file mode 100644 index 362e4d864..000000000 --- a/src/server/localStorageShim.js +++ /dev/null @@ -1,16 +0,0 @@ -// @flow -global.localStorage = { - data: {}, - setItem(id, val) { - return (this.data[id] = String(val)); - }, - getItem(id) { - return this.data.hasOwnProperty(id) ? this.data[id] : undefined; - }, - removeItem(id) { - return delete this.data[id]; - }, - clear() { - return (this.data = {}); - }, -}; diff --git a/src/server/logger.js b/src/server/logger.ts similarity index 71% rename from src/server/logger.js rename to src/server/logger.ts index fc331e25a..0c5a91241 100644 --- a/src/server/logger.js +++ b/src/server/logger.ts @@ -1,4 +1,3 @@ -// @flow import bunyan, { INFO } from 'bunyan'; import bunyanFormat from 'bunyan-format'; import bunyanLoggly from 'bunyan-loggly'; @@ -10,7 +9,7 @@ const config = { origin: 'BahnhofsAbfahrten', streams: [ { - stream: bunyanFormat({ + stream: new bunyanFormat({ outputMode: 'short', }), }, @@ -18,21 +17,19 @@ const config = { serializers: bunyan.stdSerializers, }; -const logglyConfig = { - token: process.env.LOGGLY_TOKEN, - subdomain: process.env.LOGGLY_SUBDOMAIN, -}; +const token = process.env.LOGGLY_TOKEN; +const subdomain = process.env.LOGGLY_SUBDOMAIN; // istanbul ignore next -if ( - process.env.NODE_ENV === 'production' && - logglyConfig.token && - logglyConfig.subdomain -) { +if (process.env.NODE_ENV === 'production' && token && subdomain) { // eslint-disable-next-line console.log('Using loggly to log'); config.streams.push({ - stream: new bunyanLoggly(logglyConfig), + // @ts-ignore + stream: new bunyanLoggly({ + token, + subdomain, + }), type: 'raw', }); } diff --git a/src/server/middleware/webpackDev.js b/src/server/middleware/webpackDev.ts similarity index 75% rename from src/server/middleware/webpackDev.js rename to src/server/middleware/webpackDev.ts index 4ba325214..96105c183 100644 --- a/src/server/middleware/webpackDev.js +++ b/src/server/middleware/webpackDev.ts @@ -1,17 +1,17 @@ -// @flow -import type Koa from 'koa'; -const webpack = require('webpack'); -const webpackConfig = require('../../../webpack.config'); -const chokidar = require('chokidar'); -const path = require('path'); +import { Server } from 'https'; +import chokidar from 'chokidar'; +import Koa from 'koa'; +import koaWebpack from 'koa-webpack'; +import path from 'path'; +import webpack from 'webpack'; +import webpackConfig from '../../../webpack.config'; + const compiler = webpack(webpackConfig); -const koaWebpack = require('koa-webpack'); -module.exports = function webpackDev(koa: Koa, server: ?https$Server) { +module.exports = function webpackDev(koa: Koa, server: undefined | Server) { // Do "hot-reloading" of react stuff on the server // Throw away the cached client modules and let them be re-required next time // see https://github.com/glenjamin/ultimate-hot-reloading-example - // $FlowFixMe compiler.hooks.done.tap('CacheBusting', () => { // eslint-disable-next-line no-console console.log('Clearing webpack module cache from server'); @@ -37,7 +37,7 @@ module.exports = function webpackDev(koa: Koa, server: ?https$Server) { return koaWebpack({ compiler, - devMiddleware: { serverSideRender: true }, + devMiddleware: { publicPath: '/static/', serverSideRender: true }, hotClient: { https: true, host: 'local.marudor.de', server }, }).then(middleware => { koa.use(middleware); diff --git a/src/server/render.js b/src/server/render.tsx similarity index 85% rename from src/server/render.js rename to src/server/render.tsx index 39da2d52c..95429d54f 100644 --- a/src/server/render.js +++ b/src/server/render.tsx @@ -1,5 +1,5 @@ -// @flow import { configSanitize } from 'client/util'; +import { Context } from 'koa'; import { getFeatures } from './features'; import { HelmetProvider } from 'react-helmet-async'; import { isEnabled } from 'unleash-client'; @@ -9,6 +9,7 @@ import { Provider } from 'react-redux'; import { renderStylesToString } from 'emotion-server'; import { renderToString } from 'react-dom/server'; import { StaticRouter } from 'react-router-dom'; +import { StaticRouterContext } from 'react-router'; import abfahrtenRoutes from 'Abfahrten/routes'; import Actions, { setCookies } from 'Abfahrten/actions/config'; import createJssProviderProps from 'client/createJssProviderProps'; @@ -35,11 +36,11 @@ const footerEjs = fs .trim(); const footerTemplate = ejs.compile(footerEjs); -export default async (ctx: any) => { +export default async (ctx: Context) => { const theme = createTheme(); const sheetsManager = new Map(); - const routeContext = {}; - const helmetContext = {}; + const routeContext: StaticRouterContext = {}; + const helmetContext: any = {}; const store = createStore({ features: getFeatures(), @@ -65,11 +66,15 @@ export default async (ctx: any) => { : abfahrtenRoutes; await Promise.all( - matchRoutes(routes, ctx.path).map(({ route, match }) => - route.component.loadData - ? route.component.loadData(store, match) - : Promise.resolve() - ) + matchRoutes(routes, ctx.path).map(({ route, match }) => { + const component: any = route.component; + + if (component && component.loadData) { + return component.loadData(store, match); + } + + return Promise.resolve(); + }) ); const jssProps = createJssProviderProps(); @@ -107,8 +112,7 @@ export default async (ctx: any) => { clientState: serialize(state), }); ctx.body += app; - // $FlowFixMe - const jssCss = jssProps.registry?.toString(); + const jssCss = jssProps.registry ? jssProps.registry.toString() : undefined; ctx.body += footerTemplate({ jsBundles: ctx.stats.main.js, diff --git a/src/server/seo.js b/src/server/seo.ts similarity index 97% rename from src/server/seo.js rename to src/server/seo.ts index 92b055470..36e5ebeef 100644 --- a/src/server/seo.js +++ b/src/server/seo.ts @@ -1,8 +1,7 @@ -// @flow import KoaRouter from 'koa-router'; import rawStations from 'db-stations/data.json'; -// $FlowFixMe +// @ts-ignore const baseUrl: string = process.env.BASE_URL; const filterRegex = /(hbf|airport|flughafen)/i; diff --git a/src/types/abfahrten.d.ts b/src/types/abfahrten.d.ts new file mode 100644 index 000000000..584b2d43b --- /dev/null +++ b/src/types/abfahrten.d.ts @@ -0,0 +1,93 @@ +export type SubstituteRef = { + trainNumber: string; + trainType: string; + train: string; +}; + +export type Message$Priority = + | '1' // HIGH + | '2' // MEDIUM + | '3' // LOW + | '4'; // DONE +export type Message = { + text: string; + timestamp: number; + superseded?: boolean; + superseeds?: boolean; + priority?: Message$Priority; +}; + +export type Train = { + isAdditional?: boolean; + isCancelled?: boolean; + name: string; +}; + +export type Messages = { + qos: Message[]; + delay: Message[]; + [String]: Message[]; +}; + +export type Abfahrt = { + arrival?: number; + arrivalIsCancelled: boolean; + arrivalWingIds: null | (string[]); + auslastung: boolean; + currentStation: string; + currentStationEva: string; + delayArrival?: number; + delayDeparture?: number; + departure?: number; + departureIsCancelled: boolean; + departureWingIds: null | (string[]); + destination: string; + hiddenArrival?: number; + hiddenDeparture?: number; + id: string; + isCancelled: boolean; + longDistance: boolean; + mediumId: string; + messages: Messages; + platform: string; + productClass: 'D' | 'N' | 'S' | 'F'; + rawId: string; + ref?: SubstituteRef; + reihung: boolean; + route: Train[]; + scheduledArrival?: number; + scheduledDeparture?: number; + scheduledDestination: string; + scheduledPlatform: string; + substitute: boolean; + thirdParty?: string; + train: string; + trainId: string; + trainNumber: string; + trainType: string; + via: string[]; +}; + +export type Wings = { + [mediumId: string]: Abfahrt; +}; + +export type ResolvedWings = { + arrivalWings: null | (Abfahrt[]); + departureWings: null | (Abfahrt[]); +}; + +export type AbfahrtAPIResult = { + departures: Abfahrt[]; + wings: Wings; + lageplan?: null | string; +}; + +export type WingNode = { + station: { + id: string; + title: string; + }; + pt: number; + fl: boolean; +}; diff --git a/src/types/auslastung.d.ts b/src/types/auslastung.d.ts new file mode 100644 index 000000000..8f9123266 --- /dev/null +++ b/src/types/auslastung.d.ts @@ -0,0 +1,14 @@ +export type AuslastungEntry = { + time: string; + start: string; + stop: string; + first: 0 | 1 | 2; + second: 0 | 1 | 2; +}; + +export type AuslasungData = AuslastungEntry[]; + +export type Auslastung = { + lastUpdate: string; + data: AuslastungEntry[]; +}; diff --git a/src/types/reihung.d.ts b/src/types/reihung.d.ts new file mode 100644 index 000000000..00cd97df2 --- /dev/null +++ b/src/types/reihung.d.ts @@ -0,0 +1,113 @@ +export type FahrzeugType = 'IC' | 'EC' | 'ICE' | 'TGV'; +export type SpecificType = + | 'ICET411' + | 'ICET415' + | 'ICE4' + | 'ICE3' + | 'ICE3V' + | 'ICE2' + | 'ICE1' + | 'IC2' + | 'MET'; + +export type Meta = { + id: string; + owner: 'vz'; + format: 'JSON'; + version: string; + created: string; + sequence: number; +}; + +export type Fahrzeugausstattung = { + anzahl: string; + ausstattungsart: string; + bezeichnung: string; + status: string; +}; + +export type Position = { + endemeter: string; + endeprozent: string; + startmeter: string; + startprozent: string; +}; + +export type Fahrzeug = { + allFahrzeugausstattung: Fahrzeugausstattung[]; + kategorie: string; + fahrzeugnummer: string; + orientierung: string; + positioningruppe: string; + fahrzeugsektor: string; + fahrzeugtyp: string; + wagenordnungsnummer: string; + positionamhalt: Position; + status: string; +}; + +export type Fahrzeuggruppe = { + // custom + startProzent: number; + endeProzent: number; + // custom + allFahrzeug: Fahrzeug[]; + fahrzeuggruppebezeichnung: string; + zielbetriebsstellename: string; + startbetriebsstellename: string; + verkehrlichezugnummer: string; +}; + +export type Sektor = { + positionamgleis: Position; + sektorbezeichnung: string; +}; + +export type Halt = { + // ISO String + abfahrtszeit: string; + // ISO String + ankunftszeit: string; + bahmhofsname: string; + evanummer: string; + gleisbezeichnung: string; + haltid: string; + rl100: string; + allSektor: Sektor[]; +}; + +export type Formation = { + fahrtrichtung: 'VORWAERTS' | 'RUCKWAERTS'; + /* Custom */ + differentDestination: boolean; + differentZugnummer: boolean; + specificTrainType: null | SpecificType; + scale: number; + startPercentage: number; + endPercentage: number; + // 1 = Vorwärts, 0 = Rückwärts + realFahrtrichtung: boolean; + /* End Custom */ + allFahrzeuggruppe: Fahrzeuggruppe[]; + halt: Halt; + liniebezeichnung: string; + zuggattung: FahrzeugType; + zugnummer: string; + serviceid: string; + planstarttag: string; + fahrtid: string; + istplaninformation: boolean; +}; + +export type Data = { + istformation: Formation; +}; + +export type Wagenreihung = { + meta: Meta; + data: Data; +}; + +export type Reihung = Formation; + +export default {}; diff --git a/src/types/reihungStation.d.ts b/src/types/reihungStation.d.ts new file mode 100644 index 000000000..b57f408d5 --- /dev/null +++ b/src/types/reihungStation.d.ts @@ -0,0 +1,68 @@ +/* Type + 2 - 2. Klasse + 1 - 1. Klasse + e - ??? + s - ??? +*/ + +/* symbols + h - ??? + e - ??? + k - ??? + n - ??? + o - ??? + C - ??? + A - ??? +*/ +type Waggon = { + position: number; + waggon: boolean; + sections: string[]; + number: string; + type: '2' | '1' | 's' | 'e'; + symbols: string; + differentDestination: string; + length: number; +}; + +type Destination = { + destinationName: string; + destinationVia: string[]; +}; + +type Subtrain = { + destination: Destination; + sections: string[]; +}; + +type TrackRecord = { + time: string; + additionalText: string; + name: string; + trainNumbers: string[]; + days: any[]; + subtrains: Subtrain[]; + waggons: Waggon[]; + traintypes: string; +}; + +export type SpecificWagenreihung = { + name: string; + additionalId: { + evaNr: string; + shortName: string; + }; + trackRecords: TrackRecord[]; +}; + +export type WagenreihungStation = { + trainNubmer: string; + trainType: null | any; + time: null | any; + timeOffset: null | any; + weekday: null | any; + platform: null | any; + waggon: null | any; + trainId: null | any; + stations: SpecificWagenreihung[]; +}; diff --git a/src/types/routing.d.ts b/src/types/routing.d.ts new file mode 100644 index 000000000..f87701ba7 --- /dev/null +++ b/src/types/routing.d.ts @@ -0,0 +1,294 @@ +import { Station } from './station'; +export type SRoute$cInfo = { + code: string; + url: string; + msg: string; +}; +export type SRoute$Departure = { + locX: number; + idx: number; + dProdX: number; + dInR: boolean; + dTimeS?: string; + dTimeR?: string; + dPlatfS?: string; + dPlatfR?: string; + dProgType: string; + dTZOffset: number; + type: string; +}; + +export type SRoute$Arrival = { + locX: number; + idx: number; + aOutR: boolean; + aTimeS?: string; + aTimeR?: string; + aPlatfS?: string; + aPlatfR?: string; + aProgType: string; + aTZOffset: number; + type: string; +}; +export type SRoute$JourneySegment = { + type: 'JNY'; + icoX: number; + dep: SRoute$Departure; + arr: SRoute$Arrival; + jny: { + stopL?: SRoute$StopL[]; + jid: string; + prodX: number; + dirTxt: string; + status: string; + isRchbl: boolean; + polyG: { + polyXL: $ReadOnlyArray; + layerX: number; + crdSysX: number; + }; + freq: { + minC: number; + maxC: number; + numC: number; + jnyL: $ReadOnlyArray<{ + jid: string; + prodX: number; + stopL: $ReadOnlyArray<{ + locX: number; + dTimeS: string; + }>; + }>; + }; + ctxRecon: string; + subscr: string; + chgDurR: number; + }; + minChg: string; + resState: string; + resRecommendation: string; +}; + +export type SRoute$Journey = { + cid: string; + date: string; + dur: string; + chg: number; + sDays: { + sDaysR: string; + sDaysI: string; + sDaysB: string; + }; + dep: SRoute$Departure; + arr: SRoute$Arrival; + secL: $ReadOnlyArray; + ctxRecon: string; + conSubscr: string; + resState: string; + resRecommendation: string; + recState: string; + sotRating: number; + isSotCon: boolean; + showARSLink: boolean; + sotCtxt: { + cnLocX: number; + calcDate: string; + jid: string; + locMode: string; + pLocX: number; + reqMode: string; + sectX: number; + calcTime: string; + }; + cksum: string; + cksumDti: string; +}; +export type SRoute$Product = { + name: string; + number: string; + icoX: number; + cls: number; + oprX: number; + prodCtx: { + addName?: string; + name: string; + line?: string; + num: string; + matchId: string; + catOut: string; + catOutS: string; + catOutL: string; + catIn: string; + catCode: string; + admin: string; + }; + addName?: string; +}; + +export type SRoute$StopL = { + aOutR?: boolean; + aPlatfR?: string; + aPlatfS?: string; + aProdX?: number; + aTZOffset?: number; + aTimeR?: string; + aTimeS?: string; + dDirTxt?: string; + dInR?: boolean; + dInS?: boolean; + dPlatfR?: string; + dPlatfS?: string; + dProdX?: number; + dTrnCmpSX?: { + tcocX: $ReadOnlyArray; + }; + dTZOffset?: number; + dTimeR?: string; + dTimeS?: string; + idx: number; + locX: number; + type: string; +}; + +export type SRoute$InnerResult = { + common: { + locL: $ReadOnlyArray<{ + lid: string; + type: string; + name: string; + icoX: number; + extId: string; + state: string; + crd: { + x: number; + y: number; + z: number; + layerX: number; + crdSysX: number; + }; + pCls: number; + }>; + prodL: $ReadOnlyArray; + polyL: $ReadOnlyArray; + layerL: $ReadOnlyArray<{ + id: string; + name: string; + index: number; + annoCnt: number; + }>; + crdSysL: $ReadOnlyArray<{ + id: string; + index: number; + type: string; + }>; + opL: $ReadOnlyArray<{ + name: string; + icoX: number; + }>; + remL: $ReadOnlyArray<{ + type: string; + code: string; + prio: number; + icoX: number; + txtN: string; + }>; + icoL: $ReadOnlyArray<{ + res: string; + txt?: string; + }>; + }; + outConL: $ReadOnlyArray; + outCtxScrB: string; + outCtxScrF: string; + fpB: string; + fpE: string; + bfATS: number; + bfIOSTS: number; + planrtTS: string; + outConGrpL: $ReadOnlyArray<{ + name: string; + icoX: number; + grpid: string; + conScoringL: $ReadOnlyArray<{ + type: string; + conScoreL: $ReadOnlyArray<{ + score: number; + conRefL: $ReadOnlyArray; + }>; + }>; + initScoringType: string; + }>; +}; + +export type SRoute$svcResL = { + meth: string; + err: string; + res: SRoute$InnerResult; +}; + +export type SRoute$Result = { + ver: string; + ext: string; + lang: string; + id: string; + err: string; + cInfo: SRoute$cInfo; + svcResL: $ReadOnlyArray; +}; + +export type Route$Arrival = { + scheduledArrivalPlatform?: string; + arrivalPlatform?: string; + scheduledArrival?: number; + arrival?: number; + arrivalDelay?: number; +}; + +export type Route$Departure = { + scheduledDeparturePlatform?: string; + departurePlatform?: string; + scheduledDeparture?: number; + departure?: number; + departureDelay?: number; +}; + +export type Route$Stop = { + station: Station; + scheduledDeparturePlatform?: string; + departurePlatform?: string; + // +scheduledDeparture?: number, + departure?: number; + departureDelay?: number; + scheduledArrivalPlatform?: string; + arrivalPlatform?: string; + // +scheduledArrival?: number, + arrival?: number; + arrivalDelay?: number; +}; +export type Route$JourneySegment = Route$JourneySegmentTrain; +export type Route$JourneySegmentTrain = Route$Arrival & + Route$Departure & { + train: string; + trainId?: string; + trainNumber: string; + trainType: string; + changeDuration?: number; + segmentStart: Station; + segmentDestination: Station; + stops?: Route$Stop[]; + duration?: number; + finalDestination: string; + raw?: SRoute$JourneySegment; + product?: SRoute$Product; + }; + +export type Route = Route$Arrival & + Route$Departure & { + cid: string; + date: number; + duration: number; + changes: number; + segments: Route$JourneySegment[]; + segmentTypes: $ReadOnlyArray; + raw?: any; + }; diff --git a/src/types/station.d.ts b/src/types/station.d.ts new file mode 100644 index 000000000..c8c3b054c --- /dev/null +++ b/src/types/station.d.ts @@ -0,0 +1,8 @@ +// eslint-disable-next-line import/prefer-default-export +export type Station = { + title: string; + id: string; + favendoId?: number; + DS100?: string; + raw?: Object; +}; diff --git a/test/server/Abfahrten/index.test.js b/test/server/Abfahrten/index.test.js index b034f9598..2048e47f1 100644 --- a/test/server/Abfahrten/index.test.js +++ b/test/server/Abfahrten/index.test.js @@ -9,7 +9,8 @@ describe('Abfahrten', () => { wings: {}, lageplan, }); - const testData = data => expect(data.reduce(reduceResults, baseResult).lageplan); + const testData = data => + expect(data.reduce(reduceResults, baseResult).lageplan); it('all undefined', () => { const data = [rLageplan(undefined), rLageplan(undefined)]; @@ -30,7 +31,11 @@ describe('Abfahrten', () => { }); it('null in middle', () => { - const data = [rLageplan(undefined), rLageplan(null), rLageplan(undefined)]; + const data = [ + rLageplan(undefined), + rLageplan(null), + rLageplan(undefined), + ]; testData(data).toBeNull(); }); diff --git a/test/server/Abfahrten/onlyPlan.test.js b/test/server/Abfahrten/onlyPlan.test.js index b21d8fa58..e42a9cd49 100644 --- a/test/server/Abfahrten/onlyPlan.test.js +++ b/test/server/Abfahrten/onlyPlan.test.js @@ -26,7 +26,10 @@ describe('onlyPlan', () => { fixtures.forEach(file => { it(file, async () => { - const inXml = fs.readFileSync(path.resolve(__dirname, baseFixturePath, file), 'utf8'); + const inXml = fs.readFileSync( + path.resolve(__dirname, baseFixturePath, file), + 'utf8' + ); mockLageplan(); mockFchg(); diff --git a/test/server/Abfahrten/parseTimetableS.test.js b/test/server/Abfahrten/parseTimetableS.test.js index 7f618da91..50c0de2a7 100644 --- a/test/server/Abfahrten/parseTimetableS.test.js +++ b/test/server/Abfahrten/parseTimetableS.test.js @@ -21,10 +21,15 @@ describe('parseTimetableS', () => { }, noncdAxios ); - const inXml = fs.readFileSync(path.resolve(__dirname, baseFixturePath, file), 'utf8'); + const inXml = fs.readFileSync( + path.resolve(__dirname, baseFixturePath, file), + 'utf8' + ); const nodes = xmljs.parseXml(inXml).find('//timetable/s'); - nodes.forEach(n => expect(timetable.parseTimetableS(n)).toMatchSnapshot()); + nodes.forEach(n => + expect(timetable.parseTimetableS(n)).toMatchSnapshot() + ); }); }); }); diff --git a/test/server/Abfahrten/withFchg.test.js b/test/server/Abfahrten/withFchg.test.js index 6f48a42ec..68f97fec3 100644 --- a/test/server/Abfahrten/withFchg.test.js +++ b/test/server/Abfahrten/withFchg.test.js @@ -22,12 +22,20 @@ describe('onlyPlan', () => { clock.uninstall(); }); const baseFixturePath = 'fixtures'; - const fchgFixtures = fs.readdirSync(path.resolve(__dirname, baseFixturePath, 'fchg')); + const fchgFixtures = fs.readdirSync( + path.resolve(__dirname, baseFixturePath, 'fchg') + ); fchgFixtures.forEach(file => { it(file, async () => { - const fchgXml = fs.readFileSync(path.resolve(__dirname, baseFixturePath, 'fchg', file), 'utf8'); - const planxml = fs.readFileSync(path.resolve(__dirname, baseFixturePath, 'plan', file), 'utf8'); + const fchgXml = fs.readFileSync( + path.resolve(__dirname, baseFixturePath, 'fchg', file), + 'utf8' + ); + const planxml = fs.readFileSync( + path.resolve(__dirname, baseFixturePath, 'plan', file), + 'utf8' + ); mockLageplan(); mockFchg(fchgXml); diff --git a/test/server/Bahnhof/Lageplan.test.js b/test/server/Bahnhof/Lageplan.test.js index 6cd1a0688..6b26c6ebc 100644 --- a/test/server/Bahnhof/Lageplan.test.js +++ b/test/server/Bahnhof/Lageplan.test.js @@ -31,7 +31,9 @@ describe('Lageplan', () => { }) .reply(200, readFixutre('LangenfeldeSearch.html')); - nock.get('/bahnhof-de/bahnhof/Langenfelde-1025344').reply(200, readFixutre('Langenfelde.html')); + nock + .get('/bahnhof-de/bahnhof/Langenfelde-1025344') + .reply(200, readFixutre('Langenfelde.html')); await expect(getLageplan('Langenfelde')).resolves.toBeNull(); }); @@ -52,7 +54,9 @@ describe('Lageplan', () => { }) .reply(200, readFixutre('HamburgHbfSearch.html')); - nock.get('/bahnhof-de/bahnhof/Hamburg_Hbf-1030112').reply(200, readFixutre('HamburgHbf.html')); + nock + .get('/bahnhof-de/bahnhof/Hamburg_Hbf-1030112') + .reply(200, readFixutre('HamburgHbf.html')); await expect(getLageplan('Hamburg Hbf')).resolves.toBe( 'https://www.bahnhof.de/resource/blob/1029874/4869d8dea83b386b0bb773ec64ddb021/Hamburg-Hbf_locationPdf-data.pdf' ); diff --git a/test/server/Search/Favendo.test.js b/test/server/Search/Favendo.test.js index dc119d734..63359ddcd 100644 --- a/test/server/Search/Favendo.test.js +++ b/test/server/Search/Favendo.test.js @@ -40,7 +40,11 @@ describe('Favendo Search', () => { const result = await favendoOpenDBCombined('Hamburg'); - expect(result.map(r => r.title)).toEqual(['Hamburg Hbf', 'Hamburg Dammtor', 'Hamburg Dammtor-test']); + expect(result.map(r => r.title)).toEqual([ + 'Hamburg Hbf', + 'Hamburg Dammtor', + 'Hamburg Dammtor-test', + ]); }); it('Throws instead of fallback to default', async () => { diff --git a/test/server/Search/__fixtures__/DBNavigator.example.js b/test/server/Search/__fixtures__/DBNavigator.example.js index a5603ec10..babb8bf22 100644 --- a/test/server/Search/__fixtures__/DBNavigator.example.js +++ b/test/server/Search/__fixtures__/DBNavigator.example.js @@ -1302,7 +1302,8 @@ export default { state: 'L', locL: [ { - lid: 'A=1@O=HAMBURG@X=9997434@Y=53557110@U=80@L=008096009@B=1@p=1541025646@', + lid: + 'A=1@O=HAMBURG@X=9997434@Y=53557110@U=80@L=008096009@B=1@p=1541025646@', type: 'S', name: 'HAMBURG', icoX: 0, @@ -1397,7 +1398,8 @@ export default { wt: 32184, }, { - lid: 'A=1@O=Hamburg Hbf@X=10006909@Y=53552733@U=80@L=008002549@B=1@p=1541025646@', + lid: + 'A=1@O=Hamburg Hbf@X=10006909@Y=53552733@U=80@L=008002549@B=1@p=1541025646@', type: 'S', name: 'Hamburg Hbf', icoX: 0, @@ -1451,7 +1453,8 @@ export default { wt: 31141, }, { - lid: 'A=1@O=Hamburg Dammtor@X=9989569@Y=53560751@U=80@L=008002548@B=1@p=1541025646@', + lid: + 'A=1@O=Hamburg Dammtor@X=9989569@Y=53560751@U=80@L=008002548@B=1@p=1541025646@', type: 'S', name: 'Hamburg Dammtor', icoX: 0, @@ -1459,7 +1462,30 @@ export default { state: 'F', crd: { x: 9989533, y: 53560841, z: 0, layerX: 0, crdSysX: 0 }, pCls: 59, - pRefL: [0, 1, 2, 3, 111, 11, 19, 26, 29, 30, 31, 32, 33, 34, 35, 112, 39, 45, 49, 113, 114, 115], + pRefL: [ + 0, + 1, + 2, + 3, + 111, + 11, + 19, + 26, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 112, + 39, + 45, + 49, + 113, + 114, + 115, + ], wt: 30199, }, ], diff --git a/test/server/Search/__fixtures__/OpenDB-forCombine.example.js b/test/server/Search/__fixtures__/OpenDB-forCombine.example.js index 863a61b2a..0f2a9a782 100644 --- a/test/server/Search/__fixtures__/OpenDB-forCombine.example.js +++ b/test/server/Search/__fixtures__/OpenDB-forCombine.example.js @@ -1,11 +1,22 @@ // @flow export default { LocationList: { - noNamespaceSchemaLocation: 'https://open-api.bahn.de/bin/rest.exe/v1.0/xsd?name=hafasRestLocation.xsd', + noNamespaceSchemaLocation: + 'https://open-api.bahn.de/bin/rest.exe/v1.0/xsd?name=hafasRestLocation.xsd', StopLocation: [ { name: 'HAMBURG', lon: '9.997434', lat: '53.557110', id: '008096009' }, - { name: 'Hamburg Hbf', lon: '10.006909', lat: '53.552733', id: '008002549' }, - { name: 'Hamburg Dammtor-test', lon: '9.989569', lat: '53.560751', id: '998002548' }, + { + name: 'Hamburg Hbf', + lon: '10.006909', + lat: '53.552733', + id: '008002549', + }, + { + name: 'Hamburg Dammtor-test', + lon: '9.989569', + lat: '53.560751', + id: '998002548', + }, ], }, }; diff --git a/test/server/Search/__fixtures__/OpenDB-single.example.js b/test/server/Search/__fixtures__/OpenDB-single.example.js index f57bc42fd..3748b8b27 100644 --- a/test/server/Search/__fixtures__/OpenDB-single.example.js +++ b/test/server/Search/__fixtures__/OpenDB-single.example.js @@ -1,7 +1,13 @@ // @flow export default { LocationList: { - noNamespaceSchemaLocation: 'https://open-api.bahn.de/bin/rest.exe/v1.0/xsd?name=hafasRestLocation.xsd', - StopLocation: { name: 'Hamburg Hbf', lon: '10.006909', lat: '53.552733', id: '008002549' }, + noNamespaceSchemaLocation: + 'https://open-api.bahn.de/bin/rest.exe/v1.0/xsd?name=hafasRestLocation.xsd', + StopLocation: { + name: 'Hamburg Hbf', + lon: '10.006909', + lat: '53.552733', + id: '008002549', + }, }, }; diff --git a/test/server/Search/__fixtures__/OpenDB.example.js b/test/server/Search/__fixtures__/OpenDB.example.js index 50515c9ac..390008afb 100644 --- a/test/server/Search/__fixtures__/OpenDB.example.js +++ b/test/server/Search/__fixtures__/OpenDB.example.js @@ -1,11 +1,22 @@ // @flow export default { LocationList: { - noNamespaceSchemaLocation: 'https://open-api.bahn.de/bin/rest.exe/v1.0/xsd?name=hafasRestLocation.xsd', + noNamespaceSchemaLocation: + 'https://open-api.bahn.de/bin/rest.exe/v1.0/xsd?name=hafasRestLocation.xsd', StopLocation: [ { name: 'HAMBURG', lon: '9.997434', lat: '53.557110', id: '008096009' }, - { name: 'Hamburg Hbf', lon: '10.006909', lat: '53.552733', id: '008002549' }, - { name: 'Hamburg Dammtor', lon: '9.989569', lat: '53.560751', id: '008002548' }, + { + name: 'Hamburg Hbf', + lon: '10.006909', + lat: '53.552733', + id: '008002549', + }, + { + name: 'Hamburg Dammtor', + lon: '9.989569', + lat: '53.560751', + id: '008002548', + }, ], }, }; diff --git a/test/server/Search/__fixtures__/OpenData.example.js b/test/server/Search/__fixtures__/OpenData.example.js index cc10e0512..c00057957 100644 --- a/test/server/Search/__fixtures__/OpenData.example.js +++ b/test/server/Search/__fixtures__/OpenData.example.js @@ -22,7 +22,8 @@ export default { hasTaxiRank: true, hasTravelNecessities: true, hasSteplessAccess: 'yes', - hasMobilityService: 'Ja, um Voranmeldung unter 01806 512 512 wird gebeten', + hasMobilityService: + 'Ja, um Voranmeldung unter 01806 512 512 wird gebeten', hasWiFi: true, hasTravelCenter: true, hasRailwayMission: false, @@ -106,7 +107,8 @@ export default { hasTaxiRank: true, hasTravelNecessities: true, hasSteplessAccess: 'yes', - hasMobilityService: 'Ja, um Voranmeldung unter 01806 512 512 wird gebeten', + hasMobilityService: + 'Ja, um Voranmeldung unter 01806 512 512 wird gebeten', hasWiFi: true, hasTravelCenter: true, hasRailwayMission: true, diff --git a/test/server/Search/__fixtures__/OpenDataOffline.example.js b/test/server/Search/__fixtures__/OpenDataOffline.example.js index 22b77ae55..a122efeb6 100644 --- a/test/server/Search/__fixtures__/OpenDataOffline.example.js +++ b/test/server/Search/__fixtures__/OpenDataOffline.example.js @@ -13,30 +13,90 @@ export default [ { DS100: 'FHO', favendoId: 284, id: '8000712', title: 'Bad Homburg' }, { DS100: 'NBA', favendoId: 393, id: '8000025', title: 'Bamberg' }, { DS100: 'SHO', favendoId: 2892, id: '8000176', title: 'Homburg (Saar) Hbf' }, - { DS100: 'AAI', favendoId: 2458, id: '8002547', title: 'Hamburg Airport (Flughafen)' }, + { + DS100: 'AAI', + favendoId: 2458, + id: '8002547', + title: 'Hamburg Airport (Flughafen)', + }, { DS100: 'FMBG', favendoId: 3943, id: '8000337', title: 'Marburg (Lahn)' }, { DS100: 'FL', favendoId: 3720, id: '8000229', title: 'Limburg (Lahn)' }, { DS100: 'FMBS', favendoId: 3944, id: '8003856', title: 'Marburg Süd' }, { DS100: 'NAM', favendoId: 134, id: '8000566', title: 'Amberg' }, - { DS100: 'UNM', favendoId: 4309, id: '8010240', title: 'Naumburg (Saale) Hbf' }, - { DS100: 'SLB', favendoId: 3717, id: '8003684', title: 'Limbach (b Homburg,Saar)' }, + { + DS100: 'UNM', + favendoId: 4309, + id: '8010240', + title: 'Naumburg (Saale) Hbf', + }, + { + DS100: 'SLB', + favendoId: 3717, + id: '8003684', + title: 'Limbach (b Homburg,Saar)', + }, { DS100: 'RLI', favendoId: 3721, id: '8003687', title: 'Limburgerhof' }, { DS100: 'UCB', favendoId: 1026, id: '8013474', title: 'Camburg (Saale)' }, { DS100: 'HBHA', favendoId: 281, id: '8000019', title: 'Bad Harzburg' }, - { DS100: 'HHSB', favendoId: 2576, id: '8002615', title: 'Hasbergen (Kr Osnabrück)' }, + { + DS100: 'HHSB', + favendoId: 2576, + id: '8002615', + title: 'Hasbergen (Kr Osnabrück)', + }, { DS100: 'HWAR', favendoId: 6537, id: '8000196', title: 'Warburg (Westf)' }, - { DS100: 'FHDT', favendoId: 2482, id: '8002531', title: 'Hainburg Hainstadt' }, - { DS100: 'SSAB', favendoId: 5456, id: '8005245', title: 'Saarburg (Bz Trier)' }, + { + DS100: 'FHDT', + favendoId: 2482, + id: '8002531', + title: 'Hainburg Hainstadt', + }, + { + DS100: 'SSAB', + favendoId: 5456, + id: '8005245', + title: 'Saarburg (Bz Trier)', + }, { DS100: 'FCA', favendoId: 261, id: '8001322', title: 'Bad Camberg' }, { DS100: 'MHRG', favendoId: 2555, id: '8002593', title: 'Harburg (Schwab)' }, - { DS100: 'FSTM', favendoId: 6033, id: '8000347', title: 'Glauburg-Stockheim' }, + { + DS100: 'FSTM', + favendoId: 6033, + id: '8000347', + title: 'Glauburg-Stockheim', + }, { DS100: 'FLIS', favendoId: 3723, id: '8003680', title: 'Limburg Süd' }, { DS100: 'NNAB', favendoId: 4290, id: '8004191', title: 'Nabburg' }, { DS100: 'FGBG', favendoId: 2140, id: '8002288', title: 'Glauburg-Glauberg' }, { DS100: 'NHAP', favendoId: 8194, id: '8002578', title: 'Happurg' }, - { DS100: 'UNMO', favendoId: 4310, id: '8012415', title: 'Naumburg (Saale) Ost' }, - { DS100: 'FELS', favendoId: 1575, id: '8001765', title: 'Elz (Kr Limburg/Lahn) Süd' }, - { DS100: 'FNSM', favendoId: 4448, id: '8004328', title: 'Neustadt (Kr Marburg)' }, - { DS100: 'FELZ', favendoId: 1574, id: '8001764', title: 'Elz (Kr Limburg/Lahn)' }, - { DS100: 'NHAL', favendoId: 2506, id: '8002542', title: 'Hallstadt (b Bamberg)' }, + { + DS100: 'UNMO', + favendoId: 4310, + id: '8012415', + title: 'Naumburg (Saale) Ost', + }, + { + DS100: 'FELS', + favendoId: 1575, + id: '8001765', + title: 'Elz (Kr Limburg/Lahn) Süd', + }, + { + DS100: 'FNSM', + favendoId: 4448, + id: '8004328', + title: 'Neustadt (Kr Marburg)', + }, + { + DS100: 'FELZ', + favendoId: 1574, + id: '8001764', + title: 'Elz (Kr Limburg/Lahn)', + }, + { + DS100: 'NHAL', + favendoId: 2506, + id: '8002542', + title: 'Hallstadt (b Bamberg)', + }, ]; diff --git a/test/server/Search/common.js b/test/server/Search/common.js index 6d077ed2e..0b54891a6 100644 --- a/test/server/Search/common.js +++ b/test/server/Search/common.js @@ -31,7 +31,10 @@ function buildResults(options: Options): any[] { return [Hbf, Dammtor]; } -export async function testHamburgSearch(searchFn: string => Promise, options?: Options = ({}: any)) { +export async function testHamburgSearch( + searchFn: string => Promise, + options?: Options = ({}: any) +) { const result = await searchFn('Hamburg'); const expectedResult = buildResults(options); diff --git a/test/server/config.js b/test/server/config.js index 810be620a..5a15bf558 100644 --- a/test/server/config.js +++ b/test/server/config.js @@ -1,7 +1,6 @@ // @flow import 'core-js/stable'; import 'regenerator-runtime/runtime'; -import 'server/localStorageShim'; import Nock from 'nock'; global.PROD = true; diff --git a/test/server/jest.config.js b/test/server/jest.config.js index 8dfc052e3..d65e2c3ea 100644 --- a/test/server/jest.config.js +++ b/test/server/jest.config.js @@ -7,7 +7,10 @@ module.exports = { setupFilesAfterEnv: ['/test/server/config.js'], collectCoverage: true, collectCoverageFrom: ['/src/server/**/*.{js,jsx}'], - coveragePathIgnorePatterns: ['/src/server/testData/', '/src/server/index.js'], + coveragePathIgnorePatterns: [ + '/src/server/testData/', + '/src/server/index.js', + ], coverageReporters: ['text-summary', 'lcov'], coverageDirectory: '/reports/server', rootDir: '../..', diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..0a3310898 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "jsx": "preserve", + "lib": ["es6", "dom", "esnext"], + "module": "esnext", + "moduleResolution": "node", + "noEmit": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "preserveConstEnums": true, + "removeComments": false, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + // "strictPropertyInitialization": false, + "noImplicitAny": false, + "target": "es5", + "emitDecoratorMetadata": true, + "resolveJsonModule": true, + "baseUrl": "src", + "paths": { + "Routing/*": ["client/Routing/*"], + "Abfahrten/*": ["client/Abfahrten/*"], + "Common/*": ["client/Common/*"] + } + } +} diff --git a/webpack.config.js b/webpack.config.js index 501ea7bf0..9a0f34a9f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -79,7 +79,7 @@ module.exports = { resolve: { plugins: [new ReactJssHmrPlugin()], modules: ['node_modules', path.resolve(__dirname, 'src')], - extensions: ['.js', '.json', '.jsx'], + extensions: ['.js', '.json', '.jsx', '.ts', '.tsx'], alias: { 'lodash-es$': 'lodash', AppState$: 'client/AppState', diff --git a/yarn.lock b/yarn.lock index 40bfd7faa..a643b5d75 100644 --- a/yarn.lock +++ b/yarn.lock @@ -518,6 +518,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-syntax-typescript@^7.2.0": + version "7.3.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.3.3.tgz#a7cc3f66119a9f7ebe2de5383cce193473d65991" + integrity sha512-dGwbSMA1YhVS8+31CnPR7LB4pcbrzcV99wQzby4uAfrkZPYZlQ7ImwdpzLqi6Z6IL02b8IAL379CaMwo0x5Lag== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-arrow-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" @@ -800,6 +807,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-typescript@^7.3.2": + version "7.4.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.4.0.tgz#0389ec53a34e80f99f708c4ca311181449a68eb1" + integrity sha512-U7/+zKnRZg04ggM/Bm+xmu2B/PrwyDQTT/V89FXWYWNMxBDwSx56u6jtk9SEbfLFbZaEI72L+5LPvQjeZgFCrQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-typescript" "^7.2.0" + "@babel/plugin-transform-unicode-regex@^7.4.3": version "7.4.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.3.tgz#3868703fc0e8f443dda65654b298df576f7b863b" @@ -890,6 +905,14 @@ "@babel/plugin-transform-react-jsx-self" "^7.0.0" "@babel/plugin-transform-react-jsx-source" "^7.0.0" +"@babel/preset-typescript@^7.3.3": + version "7.3.3" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.3.3.tgz#88669911053fa16b2b276ea2ede2ca603b3f307a" + integrity sha512-mzMVuIP4lqtn4du2ynEfdO0+RYcslwrZiJHXu4MGaC1ctJiW2fyaeDrtjJGs7R/KebZ1sgowcIoWf4uRpEfKEg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-transform-typescript" "^7.3.2" + "@babel/register@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.0.0.tgz#fa634bae1bfa429f60615b754fc1f1d745edd827" @@ -929,7 +952,7 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/template@^7.0.0", "@babel/template@^7.0.0-beta.55", "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2": +"@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2": version "7.2.2" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907" integrity sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g== @@ -1294,6 +1317,63 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@types/accepts@*": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.5.tgz#c34bec115cfc746e04fe5a059df4ce7e7b391575" + integrity sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ== + dependencies: + "@types/node" "*" + +"@types/anymatch@*": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" + integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA== + +"@types/axios@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@types/axios/-/axios-0.14.0.tgz#ec2300fbe7d7dddd7eb9d3abf87999964cafce46" + integrity sha1-7CMA++fX3d1+udOr+HmZlkyvzkY= + dependencies: + axios "*" + +"@types/babel-core@^6.25.6": + version "6.25.6" + resolved "https://registry.yarnpkg.com/@types/babel-core/-/babel-core-6.25.6.tgz#9e4faefcb300fd3abf0d2c2d85c505071462c1e1" + integrity sha512-OzYuLL6Lw0wpE8qXFIuyS0GsagzCr3beo/+AIttM7slM9cUhbgHjU3oWvgVE+uOhcZYS4NesBilF2iZj3gM4LQ== + dependencies: + "@types/babel-generator" "*" + "@types/babel-template" "*" + "@types/babel-traverse" "*" + "@types/babel-types" "*" + "@types/babylon" "*" + +"@types/babel-generator@*": + version "6.25.3" + resolved "https://registry.yarnpkg.com/@types/babel-generator/-/babel-generator-6.25.3.tgz#8f06caa12d0595a0538560abe771966d77d29286" + integrity sha512-pGgnuxVddKcYIc+VJkRDop7gxLhqclNKBdlsm/5Vp8d+37pQkkDK7fef8d9YYImRzw9xcojEPc18pUYnbxmjqA== + dependencies: + "@types/babel-types" "*" + +"@types/babel-template@*": + version "6.25.2" + resolved "https://registry.yarnpkg.com/@types/babel-template/-/babel-template-6.25.2.tgz#3c4cde02dbcbbf461a58d095a9f69f35eabd5f06" + integrity sha512-QKtDQRJmAz3Y1HSxfMl0syIHebMc/NnOeH/8qeD0zjgU2juD0uyC922biMxCy5xjTNvHinigML2l8kxE8eEBmw== + dependencies: + "@types/babel-types" "*" + "@types/babylon" "*" + +"@types/babel-traverse@*": + version "6.25.5" + resolved "https://registry.yarnpkg.com/@types/babel-traverse/-/babel-traverse-6.25.5.tgz#6d293cf7523e48b524faa7b86dc3c488191484e5" + integrity sha512-WrMbwmu+MWf8FiUMbmVOGkc7bHPzndUafn1CivMaBHthBBoo0VNIcYk1KV71UovYguhsNOwf3UF5oRmkkGOU3w== + dependencies: + "@types/babel-types" "*" + +"@types/babel-types@*": + version "7.0.6" + resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.6.tgz#a7cfaaeee96e90c4c54da0e580aaff3f4cffacac" + integrity sha512-8zYZyy2kgwBXdz2j8Ix7LOghGiZbOiHf6vqmmBX1r76FdAzVNv7cODyJTEglUWiOdRnXh0s/o58neUwv5vaitQ== + "@types/babel__core@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.0.tgz#710f2487dda4dcfd010ca6abb2b4dc7394365c51" @@ -1327,17 +1407,158 @@ dependencies: "@babel/types" "^7.3.0" +"@types/babylon@*": + version "6.16.5" + resolved "https://registry.yarnpkg.com/@types/babylon/-/babylon-6.16.5.tgz#1c5641db69eb8cdf378edd25b4be7754beeb48b4" + integrity sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w== + dependencies: + "@types/babel-types" "*" + +"@types/body-parser@*": + version "1.17.0" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.17.0.tgz#9f5c9d9bd04bb54be32d5eb9fc0d8c974e6cf58c" + integrity sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/bunyan-format@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@types/bunyan-format/-/bunyan-format-0.2.0.tgz#de79bf9fe67ea0dcf5416c5f1acc46abb0bb68d8" + integrity sha512-e87MeYM9rZUaQ7UgNU5webttfTlJWhc8oFU/hQBe/GGcf3bspY4ajVHqF1YgbysXnCwZDZgAq1FEe8ufFZZsLw== + dependencies: + "@types/node" "*" + +"@types/bunyan@*", "@types/bunyan@^1.8.6": + version "1.8.6" + resolved "https://registry.yarnpkg.com/@types/bunyan/-/bunyan-1.8.6.tgz#6527641cca30bedec5feb9ab527b7803b8000582" + integrity sha512-YiozPOOsS6bIuz31ilYqR5SlLif4TBWsousN2aCWLi5233nZSX19tFbcQUPdR7xJ8ypPyxkCGNxg0CIV5n9qxQ== + dependencies: + "@types/node" "*" + +"@types/cheerio@^0.22.11": + version "0.22.11" + resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.11.tgz#61c0facf9636d14ba5f77fc65ed8913aa845d717" + integrity sha512-x0X3kPbholdJZng9wDMhb2swvUi3UYRNAuWAmIPIWlfgAJZp//cql/qblE7181Mg7SjWVwq6ldCPCLn5AY/e7w== + dependencies: + "@types/node" "*" + +"@types/chokidar@^2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@types/chokidar/-/chokidar-2.1.3.tgz#123ab795dba6d89be04bf076e6aecaf8620db674" + integrity sha512-6qK3xoLLAhQVTucQGHTySwOVA1crHRXnJeLwqK6KIFkkKa2aoMFXh+WEi8PotxDtvN6MQJLyYN9ag9P6NLV81w== + dependencies: + chokidar "*" + +"@types/compression-webpack-plugin@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/compression-webpack-plugin/-/compression-webpack-plugin-2.0.0.tgz#a20a1c8467d99730fe54d782d2bcdd4dd883afcb" + integrity sha512-UPaWgei0nx3HafALKSVb3UYrDxoLnS7reeBF10gXHGkGf0aQe6Qkdb8J3XsCewhoPiW6JUrr7gG4HZ2acfMPsQ== + dependencies: + "@types/webpack" "*" + +"@types/connect@*": + version "3.4.32" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.32.tgz#aa0e9616b9435ccad02bc52b5b454ffc2c70ba28" + integrity sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg== + dependencies: + "@types/node" "*" + "@types/cookie@^0.3.1": version "0.3.2" resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.3.2.tgz#453f4b14b25da6a8ea4494842dedcbf0151deef9" integrity sha512-aHQA072E10/8iUQsPH7mQU/KUyQBZAGzTVRCUvnSz8mSvbrYsP4xEO2RSA0Pjltolzi0j8+8ixrm//Hr4umPzw== +"@types/cookiejar@*": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.1.tgz#90b68446364baf9efd8e8349bb36bd3852b75b80" + integrity sha512-aRnpPa7ysx3aNW60hTiCtLHlQaIFsXFCgQlpakNgDNVFzbtusSY8PwjAQgRWfSk0ekNoBjO51eQRB6upA9uuyw== + +"@types/cookies@*": + version "0.7.1" + resolved "https://registry.yarnpkg.com/@types/cookies/-/cookies-0.7.1.tgz#f9f204bd6767d389eea3b87609e30c090c77a540" + integrity sha512-ku6IvbucEyuC6i4zAVK/KnuzWNXdbFd1HkXlNLg/zhWDGTtQT5VhumiPruB/BHW34PWVFwyfwGftDQHfWNxu3Q== + dependencies: + "@types/connect" "*" + "@types/express" "*" + "@types/keygrip" "*" + "@types/node" "*" + +"@types/core-js@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@types/core-js/-/core-js-2.5.0.tgz#35cc282488de6f10af1d92902899a3b8ca3fbc47" + integrity sha512-qjkHL3wF0JMHMqgm/kmL8Pf8rIiqvueEiZ0g6NVTcBX1WN46GWDr+V5z+gsHUeL0n8TfAmXnYmF7ajsxmBp4PQ== + +"@types/create-react-class@^15.6.2": + version "15.6.2" + resolved "https://registry.yarnpkg.com/@types/create-react-class/-/create-react-class-15.6.2.tgz#0e1b89153be31ded959359c2b827cceaa9d18cf6" + integrity sha512-jeDUr85ld9dTUmrb0VEX1P4dGDPZocWXjeW/+jFJpdCqpCcs0Hdrv3awZqjkEsRaB/IEDe+v0ARYgBqNoDORFQ== + dependencies: + "@types/react" "*" + +"@types/date-fns@^2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@types/date-fns/-/date-fns-2.6.0.tgz#b062ca46562002909be0c63a6467ed173136acc1" + integrity sha1-sGLKRlYgApCb4MY6ZGftFzE2rME= + dependencies: + date-fns "*" + +"@types/debounce-promise@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@types/debounce-promise/-/debounce-promise-3.1.1.tgz#38fcb523f7d11d521fca2e8ccb43f0982fbf5ce7" + integrity sha512-eOSiMKpPYI5Cx5tmx4xQ1e0bLz9n56NVv4ao0YQcYtIJYZjdoCDFvZwIQgXDiFHU5SFtKtN2vcqx5ZIXvj1Ccg== + +"@types/diff@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/diff/-/diff-4.0.2.tgz#2e9bb89f9acc3ab0108f0f3dc4dbdcf2fff8a99c" + integrity sha512-mIenTfsIe586/yzsyfql69KRnA75S8SVXQbTLpDejRrjH0QSJcpu3AUOi/Vjnt9IOsXKxPhJfGpQUNMueIU1fQ== + +"@types/ejs@^2.6.3": + version "2.6.3" + resolved "https://registry.yarnpkg.com/@types/ejs/-/ejs-2.6.3.tgz#b6509e9925d7eb5e95c8c73b6492e5baae7c1e6a" + integrity sha512-/F+qQ0Fr0Dr1YvHjX+FCvbba4sQ27RdCPDqmP/si0e1v1GOkbQ3VRBvZPSQM7NoQ3iz3SyiJVscCP2f0vKuIhQ== + +"@types/eslint-plugin-prettier@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@types/eslint-plugin-prettier/-/eslint-plugin-prettier-2.2.0.tgz#26170ee65ce05d811f3ef6fc2987acd525066c7f" + integrity sha512-x/+VXokaYVDxXw6GyDwBhMRkow8HAXlqYKZGpOdMwNcCZvthpEXiDXAQsi2NJOQJqWiqvXK9OI4l67jdyWt3fw== + +"@types/eslint@^4.16.6": + version "4.16.6" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-4.16.6.tgz#96d4ecddbea618ab0b55eaf0dffedf387129b06c" + integrity sha512-GL7tGJig55FeclpOytU7nCCqtR143jBoC7AUdH0DO9xBSIFiNNUFCY/S3KNWsHeQJuU3hjw/OC1+kRTFNXqUZQ== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + "@types/events@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== -"@types/glob@^7.1.1": +"@types/express-serve-static-core@*": + version "4.16.2" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.16.2.tgz#5ee8a22e602005be6767df6b2cba9879df3f75aa" + integrity sha512-qgc8tjnDrc789rAQed8NoiFLV5VGcItA4yWNFphqGU0RcuuQngD00g3LHhWIK3HQ2XeDgVCmlNPDlqi3fWBHnQ== + dependencies: + "@types/node" "*" + "@types/range-parser" "*" + +"@types/express@*": + version "4.16.1" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.16.1.tgz#d756bd1a85c34d87eaf44c888bad27ba8a4b7cf0" + integrity sha512-V0clmJow23WeyblmACoxbHBu2JKlE5TiIme6Lem14FnPW9gsttyHtk6wq7njcdIWH1njAaFgR8gW09lgY98gQg== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "*" + "@types/serve-static" "*" + +"@types/glob@*", "@types/glob@^7.1.1": version "7.1.1" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== @@ -1346,12 +1567,61 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/history@*": + version "4.7.2" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.2.tgz#0e670ea254d559241b6eeb3894f8754991e73220" + integrity sha512-ui3WwXmjTaY73fOQ3/m3nnajU/Orhi6cEu5rzX+BrAAJxa3eITXZ5ch9suPqtM03OWhAHhPSyBGCN4UKoxO20Q== + +"@types/hoist-non-react-statics@^3.3.0": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" + integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + +"@types/http-assert@*": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@types/http-assert/-/http-assert-1.4.0.tgz#41d173466e396e99a14d75f7160cc997f2f9ed8b" + integrity sha512-TZDqvFW4nQwL9DVSNJIJu4lPLttKgzRF58COa7Vs42Ki/MrhIqUbeIw0MWn4kGLiZLXB7oCBibm7nkSjPkzfKQ== + +"@types/iconv-lite@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@types/iconv-lite/-/iconv-lite-0.0.1.tgz#aa3b8bda2be512b1ae0a057b942e869c370a5569" + integrity sha1-qjuL2ivlErGuCgV7lC6GnDcKVWk= + dependencies: + "@types/node" "*" + +"@types/iltorb@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@types/iltorb/-/iltorb-2.3.0.tgz#22a10a64ab48f059289ad2ec9005f2ff47656cf3" + integrity sha512-Sa9udsJtXhLt277FDLp9kWGdfl7YGNhg5WFzBS00YEgLbQYYIAXM7zFEdaqfJ7pqQsvGzaDWpu/0Z27l95fqww== + dependencies: + "@types/node" "*" + "@types/istanbul-lib-coverage@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.0.tgz#1eb8c033e98cf4e1a4cedcaf8bcafe8cb7591e85" integrity sha512-eAtOAFZefEnfJiRFQBGw1eYqa5GTLCZ1y86N0XSI/D6EB+E8z6VPV/UL7Gi5UEclFqoQk+6NRqEDsfmDLXn8sg== -"@types/jss@^9.5.6": +"@types/jest-diff@*": + version "20.0.1" + resolved "https://registry.yarnpkg.com/@types/jest-diff/-/jest-diff-20.0.1.tgz#35cc15b9c4f30a18ef21852e255fdb02f6d59b89" + integrity sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA== + +"@types/jest@^24.0.11": + version "24.0.11" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.11.tgz#1f099bea332c228ea6505a88159bfa86a5858340" + integrity sha512-2kLuPC5FDnWIDvaJBzsGTBQaBbnDweznicvK7UGYzlIJP4RJR2a4A/ByLUXEyEgag6jz8eHdlWExGDtH3EYUXQ== + dependencies: + "@types/jest-diff" "*" + +"@types/json-schema@*": + version "7.0.3" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" + integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A== + +"@types/jss@*", "@types/jss@^9.5.6", "@types/jss@^9.5.8": version "9.5.8" resolved "https://registry.yarnpkg.com/@types/jss/-/jss-9.5.8.tgz#258391f42211c042fc965508d505cbdc579baa5b" integrity sha512-bBbHvjhm42UKki+wZpR89j73ykSXg99/bhuKuYYePtpma3ZAnmeGnl0WxXiZhPGsIfzKwCUkpPC0jlrVMBfRxA== @@ -1359,11 +1629,137 @@ csstype "^2.0.0" indefinite-observable "^1.0.1" +"@types/keygrip@*": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.1.tgz#ff540462d2fb4d0a88441ceaf27d287b01c3d878" + integrity sha1-/1QEYtL7TQqIRBzq8n0oewHD2Hg= + +"@types/koa-bodyparser@^4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@types/koa-bodyparser/-/koa-bodyparser-4.2.2.tgz#7066e2871fbc4f15571c34e68ca587f5acc95d28" + integrity sha512-liOoUnpv7V+NX46kAqYDh503t0PI0NFjALn+L8IAlS/mdwOAg9jJoso88mN22MaWt7hLdQ+Z/MMwb9RglhEAcQ== + dependencies: + "@types/koa" "*" + +"@types/koa-bunyan-logger@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/koa-bunyan-logger/-/koa-bunyan-logger-2.1.0.tgz#f642557aa285852744b0c2aeaa306e15a6b3b0ce" + integrity sha512-b5LcT74iewNkk8SISKguNQTlCmDKyesi/aWKsH4eELEUQodQWYAz9ONhyijXDxEWU+VsE/8wtMufPo9/nUAGdQ== + dependencies: + "@types/bunyan" "*" + "@types/koa" "*" + +"@types/koa-compose@*": + version "3.2.3" + resolved "https://registry.yarnpkg.com/@types/koa-compose/-/koa-compose-3.2.3.tgz#4e2981f7bc4ce0f4797219516a91bf6ff3a70fa1" + integrity sha512-kXvR0DPyZ3gaFxZs4WycA8lpzlPGtFmwdbgce+NWd+TG3PycPO3o5FkePH60HoBPd8BBaSiw3vhtgM42O2kQcg== + dependencies: + "@types/koa" "*" + +"@types/koa-router@^7.0.40": + version "7.0.40" + resolved "https://registry.yarnpkg.com/@types/koa-router/-/koa-router-7.0.40.tgz#9654dbc43375a0380c44c49c4504b4dbfc3e4e6a" + integrity sha512-YK4+WGXch6Ig9PreZ9jlHZb2onm0S1szGw0oQxWvPhoyjSHo1Tq+CpjxMmthEUIQUc9KznOGgehFarOx8XwsFw== + dependencies: + "@types/koa" "*" + +"@types/koa-send@*": + version "4.1.2" + resolved "https://registry.yarnpkg.com/@types/koa-send/-/koa-send-4.1.2.tgz#978f8267ad116d12ac6a18fecd8f34c5657e09ad" + integrity sha512-rfqKIv9bFds39Jxvsp8o3YJLnEQVPVriYA14AuO2OY65IHh/4UX4U/iMs5L0wATpcRmm1bbe0BNk23TRwx3VQQ== + dependencies: + "@types/koa" "*" + +"@types/koa-static@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/koa-static/-/koa-static-4.0.1.tgz#b740d80a549b0a0a7a3b38918daecde88a7a50ec" + integrity sha512-SSpct5fEcAeRkBHa3RiwCIRfDHcD1cZRhwRF///ZfvRt8KhoqRrhK6wpDlYPk/vWHVFE9hPGqh68bhzsHkir4w== + dependencies: + "@types/koa" "*" + "@types/koa-send" "*" + +"@types/koa-webpack@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@types/koa-webpack/-/koa-webpack-5.0.1.tgz#dd239c0d1e352cae206c8cd0fc308329abc0c20f" + integrity sha512-OXijJpzQw+qHdvWDy/GaEEM8D4JZ6u7b1kpbmDKLs+Lyo4OXCstKiGj4jOdwN3ANQag6fhIklGQ5enURWVphUw== + dependencies: + "@types/koa" "*" + "@types/webpack" "*" + "@types/webpack-dev-middleware" "*" + "@types/webpack-hot-client" "*" + +"@types/koa@*", "@types/koa@^2.0.48": + version "2.0.48" + resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.0.48.tgz#29162783029d3e5df8b58c55f6bf0d35f78fc39f" + integrity sha512-CiIUYhHlOFJhSCTmsFoFkV2t9ij1JwW26nt0W9XZoWTvmAw6zTE0+k3IAoGICtjzIfhZpZcO323NHmI1LGmdDw== + dependencies: + "@types/accepts" "*" + "@types/cookies" "*" + "@types/http-assert" "*" + "@types/keygrip" "*" + "@types/koa-compose" "*" + "@types/node" "*" + +"@types/lodash@^4.14.123": + version "4.14.123" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.123.tgz#39be5d211478c8dd3bdae98ee75bb7efe4abfe4d" + integrity sha512-pQvPkc4Nltyx7G1Ww45OjVqUsJP4UsZm+GWJpigXgkikZqJgRm4c48g027o6tdgubWHwFRF15iFd+Y4Pmqv6+Q== + +"@types/loglevel@*": + version "1.5.4" + resolved "https://registry.yarnpkg.com/@types/loglevel/-/loglevel-1.5.4.tgz#6e296bf20d9f6b0a3274cfb01a918f1d634e4c32" + integrity sha512-8dx4ckP0vndJeN+iKZwdGiapLqFjVQ3JLOt92uqK0C63acs5NcPLbUOpfXCJkKVRjZLBQjw8NIGNBSsnatFnFQ== + +"@types/lolex@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@types/lolex/-/lolex-3.1.1.tgz#d40895223e5c8f8aa64f5500c6ca4eeab067d432" + integrity sha512-NU2qVtKxbt4IBvjEOW1QeUnV6KGUF6hpgJyvwZt3JrXe2qmwQF0+BiazQw+iFy9qL5ie+QHOxTzXkcvJUEh76g== + +"@types/memory-fs@*": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@types/memory-fs/-/memory-fs-0.3.2.tgz#5d4753f9b390cb077c8c8af97bc96463399ceccd" + integrity sha512-j5AcZo7dbMxHoOimcHEIh0JZe5e1b8q8AqGSpZJrYc7xOgCIP79cIjTdx5jSDLtySnQDwkDTqwlC7Xw7uXw7qg== + dependencies: + "@types/node" "*" + +"@types/mime@*": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" + integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw== + +"@types/mini-css-extract-plugin@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@types/mini-css-extract-plugin/-/mini-css-extract-plugin-0.2.0.tgz#afb037dbbd76f6c13803927c2751d194188b5d47" + integrity sha512-oHec+Vasp+K3C1Hb9HpwbA9Iw8ywqDgo9edWQJdBqxu05JH2AQsR56Zo5THpYbu1ieh/xJCvMRIHRdvrUBDmcA== + dependencies: + "@types/webpack" "*" + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== +"@types/nock@^9.3.1": + version "9.3.1" + resolved "https://registry.yarnpkg.com/@types/nock/-/nock-9.3.1.tgz#7d761a43a10aebc7ec6bae29d89afc6cbffa5d30" + integrity sha512-eOVHXS5RnWOjTVhu3deCM/ruy9E6JCgeix2g7wpFiekQh3AaEAK1cz43tZDukKmtSmQnwvSySq7ubijCA32I7Q== + dependencies: + "@types/node" "*" + +"@types/node-cache@^4.1.3": + version "4.1.3" + resolved "https://registry.yarnpkg.com/@types/node-cache/-/node-cache-4.1.3.tgz#524b8b13b787dec4fe982b9d77b251f7d59416f4" + integrity sha512-3hsqnv3H1zkOhjygJaJUYmgz5+FcPO3vejBX7cE9/cnuINOJYrzkfOnUCvpwGe9kMZANIHJA7J5pOdeyv52OEw== + dependencies: + "@types/node" "*" + +"@types/node-sass@^4.11.0": + version "4.11.0" + resolved "https://registry.yarnpkg.com/@types/node-sass/-/node-sass-4.11.0.tgz#b0372075546e83f39df52bd37359eab00165a04d" + integrity sha512-uNpVWhwVmbB5luE7b8vxcJwu5np75YkVTBJS0O3ar+hrxqLfyhOKXg9NYBwJ6mMQX/V6/8d6mMZTB7x2r5x9Bw== + dependencies: + "@types/node" "*" + "@types/node@*": version "11.11.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.3.tgz#7c6b0f8eaf16ae530795de2ad1b85d34bf2f5c58" @@ -1374,6 +1770,18 @@ resolved "https://registry.yarnpkg.com/@types/object-assign/-/object-assign-4.0.30.tgz#8949371d5a99f4381ee0f1df0a9b7a187e07e652" integrity sha1-iUk3HVqZ9Dge4PHfCpt6GH4H5lI= +"@types/optimize-css-assets-webpack-plugin@^1.3.4": + version "1.3.4" + resolved "https://registry.yarnpkg.com/@types/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-1.3.4.tgz#6838ab7a3a5ec1253ad98c348bdcd009e91b39cd" + integrity sha512-04LJJFAdZ7sW7V66htTeKz95WP/E+aTuKv3wikgM6bmmeO1alcqQ9eDoRSTrrkL/zeuoaoW4WR1FdjvqiWoSkQ== + dependencies: + "@types/webpack" "*" + +"@types/prettier@^1.16.1": + version "1.16.1" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.16.1.tgz#328d1c9b54402e44119398bcb6a31b7bbd606d59" + integrity sha512-db6pZL5QY3JrlCHBhYQzYDci0xnoDuxfseUuguLRr3JNk+bnCfpkK6p8quiUDyO8A0vbpBKkk59Fw125etrNeA== + "@types/prop-types@*": version "15.7.0" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.0.tgz#4c48fed958d6dcf9487195a0ef6456d5f6e0163a" @@ -1384,6 +1792,92 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== +"@types/qs@^6.5.3": + version "6.5.3" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.5.3.tgz#1c3b71b091eaeaf5924538006b7f70603ce63d38" + integrity sha512-Jugo5V/1bS0fRhy2z8+cUAHEyWOATaz4rbyLVvcFs7+dXp5HfwpEwzF1Q11bB10ApUqHf+yTauxI0UXQDwGrbA== + +"@types/range-parser@*": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" + integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== + +"@types/react-dom@*", "@types/react-dom@^16.8.4": + version "16.8.4" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.8.4.tgz#7fb7ba368857c7aa0f4e4511c4710ca2c5a12a88" + integrity sha512-eIRpEW73DCzPIMaNBDP5pPIpK1KXyZwNgfxiVagb5iGiz6da+9A5hslSX6GAQKdO7SayVCS/Fr2kjqprgAvkfA== + dependencies: + "@types/react" "*" + +"@types/react-helmet-async@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/react-helmet-async/-/react-helmet-async-1.0.0.tgz#9fbf82382a95807506f2c43e89ff47f97ddca7cf" + integrity sha512-7q+2sDPNNYkX5rtwj56OCT7OPOlM8aayWZ5JXILDdStV7Bi2Lp7nkxwHpP7dVojYTsUx//iWQiOdSFSP2+QzlQ== + dependencies: + "@types/react" "*" + "@types/react-helmet" "*" + +"@types/react-helmet@*": + version "5.0.8" + resolved "https://registry.yarnpkg.com/@types/react-helmet/-/react-helmet-5.0.8.tgz#f080eea6652e44f60b4574463d238f268d81d9af" + integrity sha512-ZTr12eDAYI0yUiMx1K82EHqRYa8J1BOOLus+0gL+AkksUiIPwLE0wLiXa9FNqD8r9GXAi+yRPZImkRh1JNlTkQ== + dependencies: + "@types/react" "*" + +"@types/react-jss@^8.6.3": + version "8.6.3" + resolved "https://registry.yarnpkg.com/@types/react-jss/-/react-jss-8.6.3.tgz#cd2a7ec23599713f2caf5b24f734f1f59c60ef6b" + integrity sha512-7oJIKxb8+/k0ebGDkWnwzzOqXvxOVVgaUd8Y7WP2hevEGY0tLH7XzrvKyrPaLGPDs8y6uYOyRJYY9RUODZuH7A== + dependencies: + "@types/jss" "*" + "@types/react" "*" + "@types/theming" "*" + csstype "^2.0.0" + +"@types/react-redux@^7.0.6": + version "7.0.6" + resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.0.6.tgz#992271450e0d3bf61130ad9e356ad018841c7f78" + integrity sha512-Nlofk/xq8oVWpylvrFayezNb/HONsYJfjlSmTmZ7xoMDe+Muf6c1qHMVRZ7C5S2W1+iVcY21ggZwlUgLv+66hQ== + dependencies: + "@types/hoist-non-react-statics" "^3.3.0" + "@types/react" "*" + redux "^4.0.0" + +"@types/react-router-config@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@types/react-router-config/-/react-router-config-1.1.2.tgz#990f668b1ad91cfaf31053f0d84a89f2887b87a0" + integrity sha512-dgKDQHbredbwy8fSVmGeAItb42Q3q5i2/5iNzhoB4ryV/IYiaKPV/spnJE5KMSb49aonhnXS1UoTGa1doJanQQ== + dependencies: + "@types/history" "*" + "@types/react" "*" + "@types/react-router" "*" + +"@types/react-router-dom@^4.3.2": + version "4.3.2" + resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.3.2.tgz#52c17c3682597638f31c17c42620403dc5c2a3f5" + integrity sha512-biesHodFxPgDxku2m08XwPeAfUYBcxAnrQG7pwFikuA3L2e3u2OKAb+Sb16bJuU3L5CTHd+Ivap+ke4mmGsHqQ== + dependencies: + "@types/history" "*" + "@types/react" "*" + "@types/react-router" "*" + +"@types/react-router@*", "@types/react-router@^4.4.5": + version "4.4.5" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-4.4.5.tgz#1166997dc7eef2917b5ebce890ebecb32ee5c1b3" + integrity sha512-12+VOu1+xiC8RPc9yrgHCyLI79VswjtuqeS2gPrMcywH6tkc8rGIUhs4LaL3AJPqo5d+RPnfRpNKiJ7MK2Qhcg== + dependencies: + "@types/history" "*" + "@types/react" "*" + +"@types/react-select@^2.0.16": + version "2.0.16" + resolved "https://registry.yarnpkg.com/@types/react-select/-/react-select-2.0.16.tgz#2f79dfa5cd1ac7b28773d0e2c8844e67e3a8beb7" + integrity sha512-bO3GH4FJ8UmZSV058Ky4d1rCieOwwXPHwZ3a9/rJP6V/IR4E3FZzttaxOZ1db1x+prAGaBh9FHma1CilrHT9bw== + dependencies: + "@types/react" "*" + "@types/react-dom" "*" + "@types/react-transition-group" "*" + "@types/react-text-mask@^5.4.3": version "5.4.4" resolved "https://registry.yarnpkg.com/@types/react-text-mask/-/react-text-mask-5.4.4.tgz#eb4606e1c431b7bd2f5e817ea141432cc63b58c1" @@ -1391,6 +1885,13 @@ dependencies: "@types/react" "*" +"@types/react-transition-group@*": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-2.9.0.tgz#2a74a885432d673a93a2c93c34ce5dbf9f1426f8" + integrity sha512-hP7vUaZMVSWKxo133P8U51U6UZ7+pbY+eAQb8+p6SZ2rB1rj3mOTDgTzhhi+R2SCB4S+sWekAAGoxdiZPG0ReQ== + dependencies: + "@types/react" "*" + "@types/react-transition-group@^2.0.8": version "2.0.16" resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-2.0.16.tgz#2dcb9e396ab385ee19c4af1c9caa469a14cd042f" @@ -1406,16 +1907,139 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/react@^16.8.13": + version "16.8.13" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.13.tgz#a82b15aad9ab91c40edca0d6889b7745ae24f053" + integrity sha512-otJ4ntMuHGrvm67CdDJMAls4WqotmAmW0g3HmWi9LCjSWXrxoXY/nHXrtmMfvPEEmGFNm6NdgMsJmnfH820Qaw== + dependencies: + "@types/prop-types" "*" + csstype "^2.2.0" + +"@types/redux-actions@^2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@types/redux-actions/-/redux-actions-2.6.0.tgz#3732391d7086e464b3341a190d914a72432dae9d" + integrity sha512-K1LwS+MW7CGzZyOS35xEWvKz0pTyQyfygCgj57qpntbP5SD/F/f1qJwRpJIFmJUpHPwOX/eqWe/8O19bycu8eg== + +"@types/redux-thunk@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/redux-thunk/-/redux-thunk-2.1.0.tgz#bc2b6e972961831afb82a9bf4f06726e351f9416" + integrity sha1-vCtulylhgxr7gqm/TwZybjUflBY= + dependencies: + redux-thunk "*" + +"@types/redux@^3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@types/redux/-/redux-3.6.0.tgz#f1ebe1e5411518072e4fdfca5c76e16e74c1399a" + integrity sha1-8evh5UEVGAcuT9/KXHbhbnTBOZo= + dependencies: + redux "*" + +"@types/reselect@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@types/reselect/-/reselect-2.2.0.tgz#c667206cfdc38190e1d379babe08865b2288575f" + integrity sha1-xmcgbP3DgZDh03m6vgiGWyKIV18= + dependencies: + reselect "*" + +"@types/rimraf@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.2.tgz#7f0fc3cf0ff0ad2a99bb723ae1764f30acaf8b6e" + integrity sha512-Hm/bnWq0TCy7jmjeN5bKYij9vw5GrDFWME4IuxV08278NtU/VdGbzsBohcCUJ7+QMqmUq5hpRKB39HeQWJjztQ== + dependencies: + "@types/glob" "*" + "@types/node" "*" + +"@types/serialize-javascript@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@types/serialize-javascript/-/serialize-javascript-1.5.0.tgz#bdd334cfbb4fc0eca1fc608da37ad733c86381eb" + integrity sha512-WxnnhYOtVJnDFznZPVdbW3NmUJXVyrdQtiq7/vUNg55fVI1B+BP+xp/4dgwIlQXaejbH8gCRu2txtu6LREzK8g== + +"@types/serve-static@*": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.2.tgz#f5ac4d7a6420a99a6a45af4719f4dcd8cd907a48" + integrity sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q== + dependencies: + "@types/express-serve-static-core" "*" + "@types/mime" "*" + "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== +"@types/stylelint@^9.10.0": + version "9.10.0" + resolved "https://registry.yarnpkg.com/@types/stylelint/-/stylelint-9.10.0.tgz#843e5fbe068a9275fe3ebfbc4ad94c8fa9b1aea9" + integrity sha512-xnlufv0Pn+UxHpCEsobMQ/AFvGoD1YkXtHpz7S49UJcw60tzUnKQWrZs+ICYwUcw9MIaHcURUsqN7iPd59iG4g== + dependencies: + postcss "7.x.x" + +"@types/superagent@*": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@types/superagent/-/superagent-4.1.1.tgz#61f0b43d7db93a3c286c124512b7c228183c32fa" + integrity sha512-NetXrraTWPcdGG6IwYJhJ5esUGx8AYNiozbc1ENWEsF6BsD4JmNODJczI6Rm1xFPVp6HZESds9YCfqz4zIsM6A== + dependencies: + "@types/cookiejar" "*" + "@types/node" "*" + +"@types/supertest@^2.0.7": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@types/supertest/-/supertest-2.0.7.tgz#46ff6508075cd4519736be060f0d6331a5c8ca7b" + integrity sha512-GibTh4OTkal71btYe2fpZP/rVHIPnnUsYphEaoywVHo+mo2a/LhlOFkIm5wdN0H0DA0Hx8x+tKgCYMD9elHu5w== + dependencies: + "@types/superagent" "*" + +"@types/tapable@*": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.4.tgz#b4ffc7dc97b498c969b360a41eee247f82616370" + integrity sha512-78AdXtlhpCHT0K3EytMpn4JNxaf5tbqbLcbIRoQIHzpTIyjpxLQKRoxU55ujBXAtg3Nl2h/XWvfDa9dsMOd0pQ== + +"@types/terser-webpack-plugin@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@types/terser-webpack-plugin/-/terser-webpack-plugin-1.2.1.tgz#02c2cacd7769c533cbdac28dd7610c24e46b5c95" + integrity sha512-5mzQulZabFsqiLh0PhJdccIKqpd5535UYpZ+Skugz8kPzZdajMMYBRKQSzM1KOkZ42NwLxbZSzQp6xKtaq46Gg== + dependencies: + "@types/webpack" "*" + terser "^3.16.1" + +"@types/theming@*": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@types/theming/-/theming-1.3.3.tgz#e770833b38b43f138acd4d0794b52892caf34c6c" + integrity sha512-xcCIvBHFFxNDxDUn0Po6FXQPpGA6Y5dzt6/fbzVhBba7Qx4cxkxStmLVEkFqEF4jy01SH9DjbRUqdj7RziC/XA== + dependencies: + "@types/react" "*" + +"@types/typescript@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/typescript/-/typescript-2.0.0.tgz#c433539c98bae28682b307eaa7a0fd2115b83c28" + integrity sha1-xDNTnJi64oaCswfqp6D9IRW4PCg= + dependencies: + typescript "*" + +"@types/uglify-js@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.0.4.tgz#96beae23df6f561862a830b4288a49e86baac082" + integrity sha512-SudIN9TRJ+v8g5pTG8RRCqfqTMNqgWCKKd3vtynhGzkIIjxaicNAMuY5TRadJ6tzDu3Dotf3ngaMILtmOdmWEQ== + dependencies: + source-map "^0.6.1" + "@types/unist@*", "@types/unist@^2.0.0": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== +"@types/universal-cookie@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@types/universal-cookie/-/universal-cookie-2.2.0.tgz#36fba91f8a8c64cfd109520d15ec2ec3f32561e9" + integrity sha512-fNgC782wfxAZZLDfFM70AgDzYh/VX7tH8NPl/fYNgoseXVLTg+vQf2zhzbWDlJiO0fKXwCL54HOKtXpjcV5C+A== + +"@types/uuid@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.4.tgz#7af69360fa65ef0decb41fd150bf4ca5c0cefdf5" + integrity sha512-tPIgT0GUmdJQNSHxp0X2jnpQfBSTfGxUMc/2CXBU2mnyTFVYVa2ojpoQ74w0U2yn2vw3jnC640+77lkFFpdVDw== + dependencies: + "@types/node" "*" + "@types/vfile-message@*": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/vfile-message/-/vfile-message-1.0.1.tgz#e1e9895cc6b36c462d4244e64e6d0b6eaf65355a" @@ -1433,11 +2057,64 @@ "@types/unist" "*" "@types/vfile-message" "*" +"@types/webpack-bundle-analyzer@^2.13.1": + version "2.13.1" + resolved "https://registry.yarnpkg.com/@types/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.13.1.tgz#25154f36585c0abc90f7e58fd3197c83fced789a" + integrity sha512-9M9jingj0izx1VfglYYJ+dvd0YCMlFgtrSCeb+C3VIQP8hmTXGJ5qqVeqiBnv0ffMyeKWqyij4K2F4VBcazQNw== + dependencies: + "@types/webpack" "*" + +"@types/webpack-dev-middleware@*": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/webpack-dev-middleware/-/webpack-dev-middleware-2.0.2.tgz#33934f15de582f1a6c21ea21c42f69282e328c76" + integrity sha512-uZ1avIbAcnspcDKKm0WfgIdvBYRqUapPmwb0MYGzzB74q2F3T4Xi+qPSoS0Oq5iQvIMVxOm7KMqHQJii4VDCsw== + dependencies: + "@types/connect" "*" + "@types/loglevel" "*" + "@types/memory-fs" "*" + "@types/webpack" "*" + +"@types/webpack-hot-client@*": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/webpack-hot-client/-/webpack-hot-client-4.0.0.tgz#8dc631153a0ae68de202f2e0e4b5b58527e41467" + integrity sha512-C/2kSW1HKcYkVN1J++HlIyb4LyQX2xSFJu+Epk6BG+2BU9OWWm14QQkJtc6nvwM5mgp64SK83A3Ddr0Uz0/FRQ== + dependencies: + "@types/node" "*" + "@types/webpack" "*" + +"@types/webpack@*", "@types/webpack@^4.4.27": + version "4.4.27" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.4.27.tgz#8bb9429185977a6b3b9e6e6132f561066aa7e7c2" + integrity sha512-xSll/4UXnLQ0xjdAoTRIFxA6NPC2abJ8nHxRH6SqTymHrfGCc8er7qH0npwCP8q3VFoJh2Hjz1wH8oTjwx9/jQ== + dependencies: + "@types/anymatch" "*" + "@types/node" "*" + "@types/tapable" "*" + "@types/uglify-js" "*" + source-map "^0.6.0" + "@types/yargs@^12.0.2", "@types/yargs@^12.0.9": version "12.0.9" resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.9.tgz#693e76a52f61a2f1e7fb48c0eef167b95ea4ffd0" integrity sha512-sCZy4SxP9rN2w30Hlmg5dtdRwgYQfYRiLo9usw8X9cxlf+H4FqM1xX7+sNH7NNKVdbXMJWqva7iyy+fxh/V7fA== +"@typescript-eslint/parser@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-1.6.0.tgz#f01189c8b90848e3b8e45a6cdad27870529d1804" + integrity sha512-VB9xmSbfafI+/kI4gUK3PfrkGmrJQfh0N4EScT1gZXSZyUxpsBirPL99EWZg9MmPG0pzq/gMtgkk7/rAHj4aQw== + dependencies: + "@typescript-eslint/typescript-estree" "1.6.0" + eslint-scope "^4.0.0" + eslint-visitor-keys "^1.0.0" + +"@typescript-eslint/typescript-estree@1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-1.6.0.tgz#6cf43a07fee08b8eb52e4513b428c8cdc9751ef0" + integrity sha512-A4CanUwfaG4oXobD5y7EXbsOHjCwn8tj1RDd820etpPAjH+Icjc2K9e/DQM1Hac5zH2BSy+u6bjvvF2wwREvYA== + dependencies: + lodash.unescape "4.0.1" + semver "5.5.0" + "@webassemblyjs/ast@1.8.5": version "1.8.5" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" @@ -1970,7 +2647,7 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== -axios@^0.18.0: +axios@*, axios@^0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102" integrity sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI= @@ -2092,13 +2769,6 @@ babel-plugin-remove-webpack@^1.1.0: resolved "https://registry.yarnpkg.com/babel-plugin-remove-webpack/-/babel-plugin-remove-webpack-1.1.0.tgz#82925cab871230c0c6b82cf67a3af243c094d1d6" integrity sha1-gpJcq4cSMMDGuCz2ejryQ8CU0dY= -babel-plugin-stateless-func-to-pure@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/babel-plugin-stateless-func-to-pure/-/babel-plugin-stateless-func-to-pure-0.0.2.tgz#392a3f6ccdbab64d7855ca5604530481cbffb0d1" - integrity sha1-OSo/bM26tk14VcpWBFMEgcv/sNE= - dependencies: - "@babel/template" "^7.0.0-beta.55" - babel-plugin-syntax-jsx@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" @@ -2697,10 +3367,10 @@ cheerio@^1.0.0-rc.3: lodash "^4.15.0" parse5 "^3.0.1" -chokidar@^2.0.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.2.tgz#9c23ea40b01638439e0513864d362aeacc5ad058" - integrity sha512-IwXUx0FXc5ibYmPC2XeEj5mpXoV66sR+t3jqu2NS2GYwCktt3KF1/Qqjws/NkegajBA4RbZ5+DDwlOiJsxDHEg== +chokidar@*, chokidar@^2.0.4, chokidar@^2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.5.tgz#0ae8434d962281a5f56c72869e79cb6d9d86ad4d" + integrity sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A== dependencies: anymatch "^2.0.0" async-each "^1.0.1" @@ -2712,14 +3382,14 @@ chokidar@^2.0.2: normalize-path "^3.0.0" path-is-absolute "^1.0.0" readdirp "^2.2.1" - upath "^1.1.0" + upath "^1.1.1" optionalDependencies: fsevents "^1.2.7" -chokidar@^2.0.4, chokidar@^2.1.5: - version "2.1.5" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.5.tgz#0ae8434d962281a5f56c72869e79cb6d9d86ad4d" - integrity sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A== +chokidar@^2.0.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.2.tgz#9c23ea40b01638439e0513864d362aeacc5ad058" + integrity sha512-IwXUx0FXc5ibYmPC2XeEj5mpXoV66sR+t3jqu2NS2GYwCktt3KF1/Qqjws/NkegajBA4RbZ5+DDwlOiJsxDHEg== dependencies: anymatch "^2.0.0" async-each "^1.0.1" @@ -2731,7 +3401,7 @@ chokidar@^2.0.4, chokidar@^2.1.5: normalize-path "^3.0.0" path-is-absolute "^1.0.0" readdirp "^2.2.1" - upath "^1.1.1" + upath "^1.1.0" optionalDependencies: fsevents "^1.2.7" @@ -3469,7 +4139,7 @@ date-fns-timezone@^0.1.4: date-fns "^1.29.0" timezone-support "^1.5.5" -date-fns@^1.29.0: +date-fns@*, date-fns@^1.29.0: version "1.30.1" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== @@ -4020,10 +4690,10 @@ escodegen@^1.9.1: optionalDependencies: source-map "~0.6.1" -eslint-config-joblift@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/eslint-config-joblift/-/eslint-config-joblift-3.3.2.tgz#a96d632e3d758aeeba591f8b4a56150bfb40797f" - integrity sha512-4Mct6mX38i5e6fToDwZydsuhdPT5MECNrurC3zimChSGoGBHihKE5DBkaPCGWU1BoZx07ZZoVyZcRHoMs6s+ZA== +eslint-config-joblift@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/eslint-config-joblift/-/eslint-config-joblift-3.3.4.tgz#aa49b9b20ffecd0b8d4e9f76a75d84bf4b85541e" + integrity sha512-SW3V2zJrXyscukcUm0okcge4cqnwcPexFv7otrFAfhIXhl3EZdZdWtRxEehXEbXEJpuG8B57U3j/sqv8KdF3kQ== eslint-config-prettier@^4.1.0: version "4.1.0" @@ -4056,10 +4726,10 @@ eslint-import-resolver-webpack@^0.11.1: resolve "^1.10.0" semver "^5.3.0" -eslint-module-utils@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz#546178dab5e046c8b562bbb50705e2456d7bda49" - integrity sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w== +eslint-module-utils@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.4.0.tgz#8b93499e9b00eab80ccb6614e69f03678e84e09a" + integrity sha512-14tltLm38Eu3zS+mt0KvILC3q8jyIAH518MlG+HO0p+yK885Lb1UHTY/UgR91eOyGdmxAPb+OLoW4znqIT6Ndw== dependencies: debug "^2.6.8" pkg-dir "^2.0.0" @@ -4083,17 +4753,17 @@ eslint-plugin-header@^3.0.0: resolved "https://registry.yarnpkg.com/eslint-plugin-header/-/eslint-plugin-header-3.0.0.tgz#0e048b5f0adfdd9754142d59d551ae6bfdaf90ad" integrity sha512-OIu2ciVW8jK4Ove4JHm1I7X0C98PZuLCyCsoUhAm2HpyGS+zr34qLM6iV06unnDvssvvEh5BkOfaLRF+N7cGoQ== -eslint-plugin-import@^2.17.0: - version "2.17.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.17.0.tgz#bdf6598aded839a27454d824b0758fd46f80eb72" - integrity sha512-JCsOtNwPYUoeZPlSr8t0+uCU5OVlHh+dIBn8Rw7FiOPjCECG+QzDIKDqshbyJE6CYoj9wpcstEl8vUY7rXkqVA== +eslint-plugin-import@^2.17.1: + version "2.17.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.17.1.tgz#b888feb4d9b3ee155113c8dccdd4bec5db33bdf4" + integrity sha512-lzD9uvRvW4MsHzIOMJEDSb5MOV9LzgxRPBaovvOhJqzgxRHYfGy9QOrMuwHIh5ehKFJ7Z3DcrcGKDQ0IbP0EdQ== dependencies: array-includes "^3.0.3" contains-path "^0.1.0" debug "^2.6.9" doctrine "1.5.0" eslint-import-resolver-node "^0.3.2" - eslint-module-utils "^2.3.0" + eslint-module-utils "^2.4.0" has "^1.0.3" lodash "^4.17.11" minimatch "^3.0.4" @@ -6844,6 +7514,11 @@ lodash.tail@^4.1.1: resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" integrity sha1-0jM6NtnncXyK0vfKyv7HwytERmQ= +lodash.unescape@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" + integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= + lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" @@ -8677,7 +9352,7 @@ postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.0, postcss-value-parser@^ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.13, postcss@^7.0.14, postcss@^7.0.2, postcss@^7.0.5, postcss@^7.0.6, postcss@^7.0.7: +postcss@7.x.x, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.13, postcss@^7.0.14, postcss@^7.0.2, postcss@^7.0.5, postcss@^7.0.6, postcss@^7.0.7: version "7.0.14" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.14.tgz#4527ed6b1ca0d82c53ce5ec1a2041c2346bbd6e5" integrity sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg== @@ -9297,7 +9972,7 @@ redux-actions@^2.6.5: reduce-reducers "^0.4.3" to-camel-case "^1.0.0" -redux-thunk@^2.3.0: +redux-thunk@*, redux-thunk@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622" integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== @@ -9309,7 +9984,7 @@ redux-unhandled-action@^1.3.0: dependencies: lodash.isplainobject "^4.0.6" -redux@^4.0.1: +redux@*, redux@^4.0.0, redux@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.1.tgz#436cae6cc40fbe4727689d7c8fae44808f1bfef5" integrity sha512-R7bAtSkk7nY6O/OYMVR9RiBI+XghjF9rlbl5806HJbQph0LJVHZrU5oaO4q70eUKiqMRqm4y07KLTlMZ2BlVmg== @@ -9527,16 +10202,16 @@ require-package-name@^2.0.1: resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9" integrity sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk= +reselect@*, reselect@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7" + integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA== + reselect@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/reselect/-/reselect-3.0.1.tgz#efdaa98ea7451324d092b2b2163a6a1d7a9a2147" integrity sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc= -reselect@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7" - integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA== - resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" @@ -9757,6 +10432,11 @@ scss-tokenizer@^0.2.3: resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== +semver@5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== + semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" @@ -10877,6 +11557,11 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typescript@*, typescript@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.3.tgz#0eb320e4ace9b10eadf5bc6103286b0f8b7c224f" + integrity sha512-FFgHdPt4T/duxx6Ndf7hwgMZZjZpB+U0nMNGVCYPq0rEzWKjEDobm4J6yb3CS7naZ0yURFqdw9Gwc7UOh/P9oQ== + ua-parser-js@^0.7.18: version "0.7.19" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.19.tgz#94151be4c0a7fb1d001af7022fdaca4642659e4b"