diff --git a/src/common/services/provideServices.js b/src/common/services/provideServices.ts similarity index 84% rename from src/common/services/provideServices.js rename to src/common/services/provideServices.ts index 87454117..ad3f1bb3 100644 --- a/src/common/services/provideServices.js +++ b/src/common/services/provideServices.ts @@ -1,3 +1,4 @@ +import Bottle, { Decorator } from 'bottlejs'; import ScrollToTop from '../ScrollToTop'; import MainHeader from '../MainHeader'; import Home from '../Home'; @@ -5,9 +6,10 @@ import MenuLayout from '../MenuLayout'; import AsideMenu from '../AsideMenu'; import ErrorHandler from '../ErrorHandler'; import ShlinkVersions from '../ShlinkVersions'; +import { ConnectDecorator } from '../../container/types'; -const provideServices = (bottle, connect, withRouter) => { - bottle.constant('window', global.window); +const provideServices = (bottle: Bottle, connect: ConnectDecorator, withRouter: Decorator) => { + bottle.constant('window', (global as any).window); bottle.constant('console', global.console); bottle.serviceFactory('ScrollToTop', ScrollToTop, 'window'); diff --git a/src/container/index.ts b/src/container/index.ts index ae20ae63..9b9a7c14 100644 --- a/src/container/index.ts +++ b/src/container/index.ts @@ -11,6 +11,7 @@ import provideTagsServices from '../tags/services/provideServices'; import provideUtilsServices from '../utils/services/provideServices'; import provideMercureServices from '../mercure/services/provideServices'; import provideSettingsServices from '../settings/services/provideServices'; +import { ConnectDecorator } from './types'; type ActionMap = Record; @@ -20,11 +21,10 @@ const { container } = bottle; const lazyService = (container: IContainer, serviceName: string) => (...args: any[]) => container[serviceName](...args); const mapActionService = (map: ActionMap, actionName: string): ActionMap => ({ ...map, - // Wrap actual action service in a function so that it is lazily created the first time it is called [actionName]: lazyService(container, actionName), }); -const connect = (propsFromState: string[], actionServiceNames: string[] = []) => +const connect: ConnectDecorator = (propsFromState: string[], actionServiceNames: string[] = []) => reduxConnect( propsFromState ? pick(propsFromState) : null, actionServiceNames.reduce(mapActionService, {}), diff --git a/src/container/types.ts b/src/container/types.ts new file mode 100644 index 00000000..27759ea8 --- /dev/null +++ b/src/container/types.ts @@ -0,0 +1 @@ +export type ConnectDecorator = (props: string[], actions?: string[]) => any; diff --git a/src/mercure/services/provideServices.js b/src/mercure/services/provideServices.ts similarity index 71% rename from src/mercure/services/provideServices.js rename to src/mercure/services/provideServices.ts index 152ebe4a..bf29b207 100644 --- a/src/mercure/services/provideServices.js +++ b/src/mercure/services/provideServices.ts @@ -1,6 +1,7 @@ +import Bottle from 'bottlejs'; import { loadMercureInfo } from '../reducers/mercureInfo'; -const provideServices = (bottle) => { +const provideServices = (bottle: Bottle) => { // Actions bottle.serviceFactory('loadMercureInfo', loadMercureInfo, 'buildShlinkApiClient'); }; diff --git a/src/settings/services/provideServices.js b/src/settings/services/provideServices.ts similarity index 74% rename from src/settings/services/provideServices.js rename to src/settings/services/provideServices.ts index 1c9e7863..ed8bb7d0 100644 --- a/src/settings/services/provideServices.js +++ b/src/settings/services/provideServices.ts @@ -1,11 +1,14 @@ +import Bottle from 'bottlejs'; import RealTimeUpdates from '../RealTimeUpdates'; import Settings from '../Settings'; import { setRealTimeUpdates } from '../reducers/settings'; +import { ConnectDecorator } from '../../container/types'; -const provideServices = (bottle, connect) => { +const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { // Components bottle.serviceFactory('Settings', Settings, 'RealTimeUpdates'); + // Services bottle.serviceFactory('RealTimeUpdates', () => RealTimeUpdates); bottle.decorator('RealTimeUpdates', connect([ 'settings' ], [ 'setRealTimeUpdates' ])); diff --git a/src/short-urls/services/provideServices.js b/src/short-urls/services/provideServices.ts similarity index 93% rename from src/short-urls/services/provideServices.js rename to src/short-urls/services/provideServices.ts index ad1f71fa..a5f43f4c 100644 --- a/src/short-urls/services/provideServices.js +++ b/src/short-urls/services/provideServices.ts @@ -1,5 +1,6 @@ import { connect as reduxConnect } from 'react-redux'; import { assoc } from 'ramda'; +import Bottle from 'bottlejs'; import ShortUrls from '../ShortUrls'; import SearchBar from '../SearchBar'; import ShortUrlsList from '../ShortUrlsList'; @@ -18,14 +19,16 @@ import { editShortUrlTags, resetShortUrlsTags } from '../reducers/shortUrlTags'; import { editShortUrlMeta, resetShortUrlMeta } from '../reducers/shortUrlMeta'; import { resetShortUrlParams } from '../reducers/shortUrlsListParams'; import { editShortUrl } from '../reducers/shortUrlEdition'; +import { ConnectDecorator } from '../../container/types'; -const provideServices = (bottle, connect) => { +const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { // Components bottle.serviceFactory('ShortUrls', ShortUrls, 'SearchBar', 'ShortUrlsList'); bottle.decorator('ShortUrls', reduxConnect( - (state) => assoc('shortUrlsList', state.shortUrlsList.shortUrls, state.shortUrlsList), + (state: any) => assoc('shortUrlsList', state.shortUrlsList.shortUrls, state.shortUrlsList), )); + // Services bottle.serviceFactory('SearchBar', SearchBar, 'ColorGenerator', 'ForServerVersion'); bottle.decorator('SearchBar', connect([ 'shortUrlsListParams' ], [ 'listShortUrls' ])); diff --git a/src/tags/services/provideServices.js b/src/tags/services/provideServices.ts similarity index 85% rename from src/tags/services/provideServices.js rename to src/tags/services/provideServices.ts index 66204c16..be38b20d 100644 --- a/src/tags/services/provideServices.js +++ b/src/tags/services/provideServices.ts @@ -1,3 +1,4 @@ +import Bottle, { IContainer } from 'bottlejs'; import TagsSelector from '../helpers/TagsSelector'; import TagCard from '../TagCard'; import DeleteTagConfirmModal from '../helpers/DeleteTagConfirmModal'; @@ -6,8 +7,9 @@ import TagsList from '../TagsList'; import { filterTags, listTags } from '../reducers/tagsList'; import { deleteTag, tagDeleted } from '../reducers/tagDelete'; import { editTag, tagEdited } from '../reducers/tagEdit'; +import { ConnectDecorator } from '../../container/types'; -const provideServices = (bottle, connect) => { +const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { // Components bottle.serviceFactory('TagsSelector', TagsSelector, 'ColorGenerator'); bottle.decorator('TagsSelector', connect([ 'tagsList' ], [ 'listTags' ])); @@ -34,7 +36,8 @@ const provideServices = (bottle, connect) => { )); // Actions - const listTagsActionFactory = (force) => ({ buildShlinkApiClient }) => listTags(buildShlinkApiClient, force); + const listTagsActionFactory = (force: boolean) => + ({ buildShlinkApiClient }: IContainer) => listTags(buildShlinkApiClient, force); bottle.factory('listTags', listTagsActionFactory(false)); bottle.factory('forceListTags', listTagsActionFactory(true)); diff --git a/src/utils/services/provideServices.js b/src/utils/services/provideServices.ts similarity index 83% rename from src/utils/services/provideServices.js rename to src/utils/services/provideServices.ts index 5bc62442..458cb680 100644 --- a/src/utils/services/provideServices.js +++ b/src/utils/services/provideServices.ts @@ -1,11 +1,12 @@ import axios from 'axios'; +import Bottle from 'bottlejs'; import { useStateFlagTimeout } from '../helpers/hooks'; import Storage from './Storage'; import ColorGenerator from './ColorGenerator'; import buildShlinkApiClient from './ShlinkApiClientBuilder'; -const provideServices = (bottle) => { - bottle.constant('localStorage', global.localStorage); +const provideServices = (bottle: Bottle) => { + bottle.constant('localStorage', (global as any).localStorage); bottle.service('Storage', Storage, 'localStorage'); bottle.service('ColorGenerator', ColorGenerator, 'Storage'); diff --git a/src/visits/services/provideServices.js b/src/visits/services/provideServices.ts similarity index 92% rename from src/visits/services/provideServices.js rename to src/visits/services/provideServices.ts index cc7062f5..0d0c0b09 100644 --- a/src/visits/services/provideServices.js +++ b/src/visits/services/provideServices.ts @@ -1,3 +1,4 @@ +import Bottle from 'bottlejs'; import ShortUrlVisits from '../ShortUrlVisits'; import { cancelGetShortUrlVisits, getShortUrlVisits } from '../reducers/shortUrlVisits'; import { getShortUrlDetail } from '../reducers/shortUrlDetail'; @@ -7,9 +8,10 @@ import VisitsStats from '../VisitsStats'; import { createNewVisit } from '../reducers/visitCreation'; import { cancelGetTagVisits, getTagVisits } from '../reducers/tagVisits'; import TagVisits from '../TagVisits'; +import { ConnectDecorator } from '../../container/types'; import * as visitsParser from './VisitsParser'; -const provideServices = (bottle, connect) => { +const provideServices = (bottle: Bottle, connect: ConnectDecorator) => { // Components bottle.serviceFactory('OpenMapModalBtn', OpenMapModalBtn, 'MapModal'); bottle.serviceFactory('MapModal', () => MapModal); diff --git a/test/utils/Checkbox.test.tsx b/test/utils/Checkbox.test.tsx index b923e3f8..9aac2863 100644 --- a/test/utils/Checkbox.test.tsx +++ b/test/utils/Checkbox.test.tsx @@ -17,12 +17,10 @@ describe('', () => { it('includes extra class names when provided', () => { const classNames = [ 'foo', 'bar', 'baz' ]; - const checked = false; - const onChange = () => {}; expect.assertions(classNames.length); classNames.forEach((className) => { - const wrapped = createComponent({ className, checked, onChange }); + const wrapped = createComponent({ className }); expect(wrapped.prop('className')).toContain(className); }); @@ -30,11 +28,10 @@ describe('', () => { it('marks input as checked if defined', () => { const checkeds = [ true, false ]; - const onChange = () => {}; expect.assertions(checkeds.length); checkeds.forEach((checked) => { - const wrapped = createComponent({ checked, onChange }); + const wrapped = createComponent({ checked }); const input = wrapped.find('input'); expect(input.prop('checked')).toEqual(checked); @@ -43,12 +40,10 @@ describe('', () => { it('renders provided children inside the label', () => { const labels = [ 'foo', 'bar', 'baz' ]; - const checked = false; - const onChange = () => {}; expect.assertions(labels.length); labels.forEach((children) => { - const wrapped = createComponent({ children, checked, onChange }); + const wrapped = createComponent({ children }); const label = wrapped.find('label'); expect(label.text()).toEqual(children);