Use TSyringe on background script

jh-changes
Shin'ya Ueoka 5 years ago
parent c7803e7c29
commit cdfd54ed99
  1. 35
      src/background/Application.ts
  2. 8
      src/background/controllers/AddonEnabledController.ts
  3. 13
      src/background/controllers/CommandController.ts
  4. 9
      src/background/controllers/FindController.ts
  5. 9
      src/background/controllers/LinkController.ts
  6. 9
      src/background/controllers/MarkController.ts
  7. 25
      src/background/controllers/OperationController.ts
  8. 13
      src/background/controllers/SettingController.ts
  9. 9
      src/background/controllers/VersionController.ts
  10. 27
      src/background/index.ts
  11. 2
      src/background/infrastructures/ConsoleClient.ts
  12. 2
      src/background/infrastructures/ContentMessageClient.ts
  13. 34
      src/background/infrastructures/ContentMessageListener.ts
  14. 3
      src/background/presenters/IndicatorPresenter.ts
  15. 3
      src/background/presenters/NotifyPresenter.ts
  16. 2
      src/background/presenters/TabPresenter.ts
  17. 3
      src/background/presenters/WindowPresenter.ts
  18. 3
      src/background/repositories/BookmarkRepository.ts
  19. 2
      src/background/repositories/BrowserSettingRepository.ts
  20. 3
      src/background/repositories/CompletionsRepository.ts
  21. 2
      src/background/repositories/FindRepository.ts
  22. 2
      src/background/repositories/MarkRepository.ts
  23. 2
      src/background/repositories/PersistentSettingRepository.ts
  24. 2
      src/background/repositories/SettingRepository.ts
  25. 20
      src/background/usecases/AddonEnabledUseCase.ts
  26. 30
      src/background/usecases/CommandUseCase.ts
  27. 17
      src/background/usecases/CompletionsUseCase.ts
  28. 12
      src/background/usecases/ConsoleUseCase.ts
  29. 17
      src/background/usecases/FindUseCase.ts
  30. 9
      src/background/usecases/LinkUseCase.ts
  31. 21
      src/background/usecases/MarkUseCase.ts
  32. 16
      src/background/usecases/SettingUseCase.ts
  33. 9
      src/background/usecases/TabSelectUseCase.ts
  34. 13
      src/background/usecases/TabUseCase.ts
  35. 13
      src/background/usecases/VersionUseCase.ts
  36. 9
      src/background/usecases/ZoomUseCase.ts
  37. 6
      test/main.ts

@ -0,0 +1,35 @@
import { injectable } from 'tsyringe';
import ContentMessageListener from './infrastructures/ContentMessageListener';
import SettingController from './controllers/SettingController';
import VersionController from './controllers/VersionController';
@injectable()
export default class Application {
constructor(
private contentMessageListener: ContentMessageListener,
private settingController: SettingController,
private versionController: VersionController,
) {
}
run() {
this.settingController.reload();
browser.runtime.onInstalled.addListener((details) => {
if (details.reason !== 'install' && details.reason !== 'update') {
return;
}
this.versionController.notify();
});
this.contentMessageListener.run();
browser.storage.onChanged.addListener((changes, area) => {
if (area !== 'local') {
return;
}
if (changes.settings) {
this.settingController.reload();
}
});
}
}

@ -1,10 +1,12 @@
import { injectable } from 'tsyringe';
import AddonEnabledUseCase from '../usecases/AddonEnabledUseCase';
@injectable()
export default class AddonEnabledController {
private addonEnabledUseCase: AddonEnabledUseCase;
constructor() {
this.addonEnabledUseCase = new AddonEnabledUseCase();
constructor(
private addonEnabledUseCase: AddonEnabledUseCase,
) {
}
indicate(enabled: boolean): Promise<any> {

@ -1,3 +1,4 @@
import { injectable } from 'tsyringe';
import CompletionsUseCase from '../usecases/CompletionsUseCase';
import CommandUseCase from '../usecases/CommandUseCase';
import CompletionGroup from '../domains/CompletionGroup';
@ -7,14 +8,12 @@ const trimStart = (str: string): string => {
return str.replace(/^\s+/, '');
};
@injectable()
export default class CommandController {
private completionsUseCase: CompletionsUseCase;
private commandIndicator: CommandUseCase;
constructor() {
this.completionsUseCase = new CompletionsUseCase();
this.commandIndicator = new CommandUseCase();
constructor(
private completionsUseCase: CompletionsUseCase,
private commandIndicator: CommandUseCase,
) {
}
getCompletions(line: string): Promise<CompletionGroup[]> {

@ -1,10 +1,11 @@
import { injectable } from 'tsyringe';
import FindUseCase from '../usecases/FindUseCase';
@injectable()
export default class FindController {
private findUseCase: FindUseCase;
constructor() {
this.findUseCase = new FindUseCase();
constructor(
private findUseCase: FindUseCase,
) {
}
getKeyword(): Promise<string> {

@ -1,10 +1,11 @@
import { injectable } from 'tsyringe';
import LinkUseCase from '../usecases/LinkUseCase';
@injectable()
export default class LinkController {
private linkUseCase: LinkUseCase;
constructor() {
this.linkUseCase = new LinkUseCase();
constructor(
private linkUseCase: LinkUseCase,
) {
}
openToTab(url: string, tabId: number): Promise<void> {

@ -1,10 +1,11 @@
import { injectable } from 'tsyringe';
import MarkUseCase from '../usecases/MarkUseCase';
@injectable()
export default class MarkController {
private markUseCase: MarkUseCase;
constructor() {
this.markUseCase = new MarkUseCase();
constructor(
private markUseCase: MarkUseCase,
) {
}
setGlobal(key: string, x: number, y: number): Promise<any> {

@ -1,3 +1,4 @@
import { injectable } from 'tsyringe';
import * as operations from '../../shared/operations';
import FindUseCase from '../usecases/FindUseCase';
import ConsoleUseCase from '../usecases/ConsoleUseCase';
@ -5,23 +6,15 @@ import TabUseCase from '../usecases/TabUseCase';
import TabSelectUseCase from '../usecases/TabSelectUseCase';
import ZoomUseCase from '../usecases/ZoomUseCase';
@injectable()
export default class OperationController {
private findUseCase: FindUseCase;
private consoleUseCase: ConsoleUseCase;
private tabUseCase: TabUseCase;
private tabSelectUseCase: TabSelectUseCase;
private zoomUseCase: ZoomUseCase;
constructor() {
this.findUseCase = new FindUseCase();
this.consoleUseCase = new ConsoleUseCase();
this.tabUseCase = new TabUseCase();
this.tabSelectUseCase = new TabSelectUseCase();
this.zoomUseCase = new ZoomUseCase();
constructor(
private findUseCase: FindUseCase,
private consoleUseCase: ConsoleUseCase,
private tabUseCase: TabUseCase,
private tabSelectUseCase: TabSelectUseCase,
private zoomUseCase: ZoomUseCase,
) {
}
// eslint-disable-next-line complexity, max-lines-per-function

@ -1,15 +1,14 @@
import { injectable } from 'tsyringe';
import SettingUseCase from '../usecases/SettingUseCase';
import ContentMessageClient from '../infrastructures/ContentMessageClient';
import Settings from '../../shared/Settings';
@injectable()
export default class SettingController {
private settingUseCase: SettingUseCase;
private contentMessageClient: ContentMessageClient;
constructor() {
this.settingUseCase = new SettingUseCase();
this.contentMessageClient = new ContentMessageClient();
constructor(
private settingUseCase: SettingUseCase,
private contentMessageClient: ContentMessageClient,
) {
}
getSetting(): Promise<Settings> {

@ -1,10 +1,11 @@
import { injectable } from 'tsyringe';
import VersionUseCase from '../usecases/VersionUseCase';
@injectable()
export default class VersionController {
private versionUseCase: VersionUseCase;
constructor() {
this.versionUseCase = new VersionUseCase();
constructor(
private versionUseCase: VersionUseCase,
) {
}
notify(): Promise<void> {

@ -1,23 +1,6 @@
import ContentMessageListener from './infrastructures/ContentMessageListener';
import SettingController from './controllers/SettingController';
import VersionController from './controllers/VersionController';
import 'reflect-metadata';
import { container } from 'tsyringe';
import Application from './Application';
let settingController = new SettingController();
settingController.reload();
browser.runtime.onInstalled.addListener((details) => {
if (details.reason !== 'install' && details.reason !== 'update') {
return;
}
new VersionController().notify();
});
new ContentMessageListener().run();
browser.storage.onChanged.addListener((changes, area) => {
if (area !== 'local') {
return;
}
if (changes.settings) {
settingController.reload();
}
});
let app = container.resolve(Application);
app.run();

@ -1,5 +1,7 @@
import { injectable } from 'tsyringe';
import * as messages from '../../shared/messages';
@injectable()
export default class ConsoleClient {
showCommand(tabId: number, command: string): Promise<any> {
return browser.tabs.sendMessage(tabId, {

@ -1,5 +1,7 @@
import { injectable } from 'tsyringe';
import * as messages from '../../shared/messages';
@injectable()
export default class ContentMessageClient {
async broadcastSettingsChanged(): Promise<void> {
let tabs = await browser.tabs.query({});

@ -1,3 +1,4 @@
import { injectable } from 'tsyringe';
import * as messages from '../../shared/messages';
import CompletionGroup from '../domains/CompletionGroup';
import CommandController from '../controllers/CommandController';
@ -8,32 +9,19 @@ import LinkController from '../controllers/LinkController';
import OperationController from '../controllers/OperationController';
import MarkController from '../controllers/MarkController';
@injectable()
export default class ContentMessageListener {
private settingController: SettingController;
private commandController: CommandController;
private findController: FindController;
private addonEnabledController: AddonEnabledController;
private linkController: LinkController;
private backgroundOperationController: OperationController;
private markController: MarkController;
private consolePorts: {[tabId: number]: browser.runtime.Port};
constructor() {
this.settingController = new SettingController();
this.commandController = new CommandController();
this.findController = new FindController();
this.addonEnabledController = new AddonEnabledController();
this.linkController = new LinkController();
this.backgroundOperationController = new OperationController();
this.markController = new MarkController();
constructor(
private settingController: SettingController,
private commandController: CommandController,
private findController: FindController,
private addonEnabledController: AddonEnabledController,
private linkController: LinkController,
private backgroundOperationController: OperationController,
private markController: MarkController,
) {
this.consolePorts = {};
}

@ -1,3 +1,6 @@
import { injectable } from 'tsyringe';
@injectable()
export default class IndicatorPresenter {
indicate(enabled: boolean): Promise<void> {
let path = enabled

@ -1,5 +1,8 @@
import { injectable } from 'tsyringe';
const NOTIFICATION_ID = 'vimvixen-update';
@injectable()
export default class NotifyPresenter {
async notify(
title: string,

@ -1,3 +1,4 @@
import { injectable } from 'tsyringe';
import MemoryStorage from '../infrastructures/MemoryStorage';
const CURRENT_SELECTED_KEY = 'tabs.current.selected';
@ -5,6 +6,7 @@ const LAST_SELECTED_KEY = 'tabs.last.selected';
type Tab = browser.tabs.Tab;
@injectable()
export default class TabPresenter {
open(url: string, tabId?: number): Promise<Tab> {
return browser.tabs.update(tabId, { url });

@ -1,3 +1,6 @@
import { injectable } from 'tsyringe';
@injectable()
export default class WindowPresenter {
create(url: string): Promise<browser.windows.Window> {
return browser.windows.create({ url });

@ -1,3 +1,6 @@
import { injectable } from 'tsyringe';
@injectable()
export default class BookmarkRepository {
async create(
title: string, url: string

@ -1,3 +1,4 @@
import { injectable } from 'tsyringe';
import * as urls from '../../shared/urls';
declare namespace browser.browserSettings.homepageOverride {
@ -16,6 +17,7 @@ declare namespace browser.browserSettings.homepageOverride {
function get(param: object): Promise<BrowserSettings>;
}
@injectable()
export default class BrowserSettingRepository {
async getHomepageUrls(): Promise<string[]> {
let { value } = await browser.browserSettings.homepageOverride.get({});

@ -1,6 +1,9 @@
import { injectable } from 'tsyringe';
type Tab = browser.tabs.Tab;
type BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode;
@injectable()
export default class CompletionsRepository {
async queryBookmarks(keywords: string): Promise<BookmarkTreeNode[]> {
let items = await browser.bookmarks.search({ query: keywords });

@ -1,7 +1,9 @@
import { injectable } from 'tsyringe';
import MemoryStorage from '../infrastructures/MemoryStorage';
const FIND_KEYWORD_KEY = 'find-keyword';
@injectable()
export default class FindRepository {
private cache: MemoryStorage;

@ -1,8 +1,10 @@
import { injectable } from 'tsyringe';
import MemoryStorage from '../infrastructures/MemoryStorage';
import GlobalMark from '../domains/GlobalMark';
const MARK_KEY = 'mark';
@injectable()
export default class MarkRepository {
private cache: MemoryStorage;

@ -1,5 +1,7 @@
import { injectable } from 'tsyringe';
import SettingData from '../../shared/SettingData';
@injectable()
export default class SettingRepository {
async load(): Promise<SettingData | null> {
let { settings } = await browser.storage.local.get('settings');

@ -1,9 +1,11 @@
import { injectable } from 'tsyringe';
import MemoryStorage from '../infrastructures/MemoryStorage';
import Settings from '../../shared/Settings';
import * as PropertyDefs from '../../shared/property-defs';
const CACHED_SETTING_KEY = 'setting';
@injectable()
export default class SettingRepository {
private cache: MemoryStorage;

@ -1,27 +1,21 @@
import { injectable } from 'tsyringe';
import IndicatorPresenter from '../presenters/IndicatorPresenter';
import TabPresenter from '../presenters/TabPresenter';
import ContentMessageClient from '../infrastructures/ContentMessageClient';
@injectable()
export default class AddonEnabledUseCase {
private indicatorPresentor: IndicatorPresenter;
private tabPresenter: TabPresenter;
private contentMessageClient: ContentMessageClient;
constructor() {
this.indicatorPresentor = new IndicatorPresenter();
constructor(
private indicatorPresentor: IndicatorPresenter,
private tabPresenter: TabPresenter,
private contentMessageClient: ContentMessageClient,
) {
this.indicatorPresentor.onClick((tab) => {
if (tab.id) {
this.onIndicatorClick(tab.id);
}
});
this.tabPresenter = new TabPresenter();
this.tabPresenter.onSelected(info => this.onTabSelected(info.tabId));
this.contentMessageClient = new ContentMessageClient();
}
indicate(enabled: boolean): Promise<void> {

@ -1,3 +1,4 @@
import { injectable } from 'tsyringe';
import * as parsers from './parsers';
import * as urls from '../../shared/urls';
import TabPresenter from '../presenters/TabPresenter';
@ -7,27 +8,16 @@ import BookmarkRepository from '../repositories/BookmarkRepository';
import ConsoleClient from '../infrastructures/ConsoleClient';
import ContentMessageClient from '../infrastructures/ContentMessageClient';
@injectable()
export default class CommandIndicator {
private tabPresenter: TabPresenter;
private windowPresenter: WindowPresenter;
private settingRepository: SettingRepository;
private bookmarkRepository: BookmarkRepository;
private consoleClient: ConsoleClient;
private contentMessageClient: ContentMessageClient;
constructor() {
this.tabPresenter = new TabPresenter();
this.windowPresenter = new WindowPresenter();
this.settingRepository = new SettingRepository();
this.bookmarkRepository = new BookmarkRepository();
this.consoleClient = new ConsoleClient();
this.contentMessageClient = new ContentMessageClient();
constructor(
private tabPresenter: TabPresenter,
private windowPresenter: WindowPresenter,
private settingRepository: SettingRepository,
private bookmarkRepository: BookmarkRepository,
private consoleClient: ConsoleClient,
private contentMessageClient: ContentMessageClient,
) {
}
async open(keywords: string): Promise<browser.tabs.Tab> {

@ -1,3 +1,4 @@
import { injectable } from 'tsyringe';
import CompletionGroup from '../domains/CompletionGroup';
import CommandDocs from '../domains/CommandDocs';
import CompletionsRepository from '../repositories/CompletionsRepository';
@ -11,17 +12,13 @@ const COMPLETION_ITEM_LIMIT = 10;
type Tab = browser.tabs.Tab;
type HistoryItem = browser.history.HistoryItem;
@injectable()
export default class CompletionsUseCase {
private tabPresenter: TabPresenter;
private completionsRepository: CompletionsRepository;
private settingRepository: SettingRepository;
constructor() {
this.tabPresenter = new TabPresenter();
this.completionsRepository = new CompletionsRepository();
this.settingRepository = new SettingRepository();
constructor(
private tabPresenter: TabPresenter,
private completionsRepository: CompletionsRepository,
private settingRepository: SettingRepository,
) {
}
queryConsoleCommand(prefix: string): Promise<CompletionGroup[]> {

@ -1,14 +1,14 @@
import { injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter';
import ConsoleClient from '../infrastructures/ConsoleClient';
@injectable()
export default class ConsoleUseCase {
private tabPresenter: TabPresenter;
private consoleClient: ConsoleClient;
constructor() {
this.tabPresenter = new TabPresenter();
this.consoleClient = new ConsoleClient();
constructor(
private tabPresenter: TabPresenter,
private consoleClient: ConsoleClient,
) {
}
async showCommand(): Promise<any> {

@ -1,18 +1,15 @@
import { injectable } from 'tsyringe';
import FindRepository from '../repositories/FindRepository';
import TabPresenter from '../presenters/TabPresenter';
import ConsoleClient from '../infrastructures/ConsoleClient';
@injectable()
export default class FindUseCase {
private tabPresenter: TabPresenter;
private findRepository: FindRepository;
private consoleClient: ConsoleClient;
constructor() {
this.tabPresenter = new TabPresenter();
this.findRepository = new FindRepository();
this.consoleClient = new ConsoleClient();
constructor(
private tabPresenter: TabPresenter,
private findRepository: FindRepository,
private consoleClient: ConsoleClient,
) {
}
getKeyword(): Promise<string> {

@ -1,10 +1,11 @@
import { injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter';
@injectable()
export default class LinkUseCase {
private tabPresenter: TabPresenter;
constructor() {
this.tabPresenter = new TabPresenter();
constructor(
private tabPresenter: TabPresenter,
) {
}
openToTab(url: string, tabId: number): Promise<any> {

@ -1,22 +1,17 @@
import { injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter';
import MarkRepository from '../repositories/MarkRepository';
import ConsoleClient from '../infrastructures/ConsoleClient';
import ContentMessageClient from '../infrastructures/ContentMessageClient';
@injectable()
export default class MarkUseCase {
private tabPresenter: TabPresenter;
private markRepository: MarkRepository;
private consoleClient: ConsoleClient;
private contentMessageClient: ContentMessageClient;
constructor() {
this.tabPresenter = new TabPresenter();
this.markRepository = new MarkRepository();
this.consoleClient = new ConsoleClient();
this.contentMessageClient = new ContentMessageClient();
constructor(
private tabPresenter: TabPresenter,
private markRepository: MarkRepository,
private consoleClient: ConsoleClient,
private contentMessageClient: ContentMessageClient,
) {
}
async setGlobal(key: string, x: number, y: number): Promise<any> {

@ -1,17 +1,17 @@
// eslint-disable-next-line max-len
import PersistentSettingRepository from '../repositories/PersistentSettingRepository';
import { injectable } from 'tsyringe';
import PersistentSettingRepository
from '../repositories/PersistentSettingRepository';
import SettingRepository from '../repositories/SettingRepository';
import { DefaultSettingData } from '../../shared/SettingData';
import Settings from '../../shared/Settings';
@injectable()
export default class SettingUseCase {
private persistentSettingRepository: PersistentSettingRepository;
private settingRepository: SettingRepository;
constructor() {
this.persistentSettingRepository = new PersistentSettingRepository();
this.settingRepository = new SettingRepository();
constructor(
private persistentSettingRepository: PersistentSettingRepository,
private settingRepository: SettingRepository,
) {
}
get(): Promise<Settings> {

@ -1,10 +1,11 @@
import { injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter';
@injectable()
export default class TabSelectUseCase {
private tabPresenter: TabPresenter;
constructor() {
this.tabPresenter = new TabPresenter();
constructor(
private tabPresenter: TabPresenter,
) {
}
async selectPrev(count: number): Promise<any> {

@ -1,14 +1,13 @@
import { injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter';
import BrowserSettingRepository from '../repositories/BrowserSettingRepository';
@injectable()
export default class TabUseCase {
private tabPresenter: TabPresenter;
private browserSettingRepository: BrowserSettingRepository;
constructor() {
this.tabPresenter = new TabPresenter();
this.browserSettingRepository = new BrowserSettingRepository();
constructor(
private tabPresenter: TabPresenter,
private browserSettingRepository: BrowserSettingRepository,
) {
}
async close(force: boolean): Promise<any> {

@ -1,14 +1,13 @@
import { injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter';
import NotifyPresenter from '../presenters/NotifyPresenter';
@injectable()
export default class VersionUseCase {
private tabPresenter: TabPresenter;
private notifyPresenter: NotifyPresenter;
constructor() {
this.tabPresenter = new TabPresenter();
this.notifyPresenter = new NotifyPresenter();
constructor(
private tabPresenter: TabPresenter,
private notifyPresenter: NotifyPresenter,
) {
}
notify(): Promise<void> {

@ -1,3 +1,4 @@
import { injectable } from 'tsyringe';
import TabPresenter from '../presenters/TabPresenter';
const ZOOM_SETTINGS: number[] = [
@ -5,11 +6,11 @@ const ZOOM_SETTINGS: number[] = [
1.10, 1.25, 1.50, 1.75, 2.00, 2.50, 3.00
];
@injectable()
export default class ZoomUseCase {
private tabPresenter: TabPresenter;
constructor() {
this.tabPresenter = new TabPresenter();
constructor(
private tabPresenter: TabPresenter,
) {
}
async zoomIn(): Promise<any> {

@ -1,6 +1,8 @@
import chai from 'chai';
import 'reflect-metadata';
import { expect } from 'chai';
const browserFake = require('webextensions-api-fake');
const browser = browserFake();
global.expect = chai.expect;
global.expect = expect;
global.browser = browser;