diff --git a/app/assets/javascripts/services/index.ts b/app/assets/javascripts/services/index.ts index b63b520e8..1099f9088 100644 --- a/app/assets/javascripts/services/index.ts +++ b/app/assets/javascripts/services/index.ts @@ -4,6 +4,5 @@ export { DesktopManager } from './desktopManager'; export { KeyboardManager } from './keyboardManager'; export { AutolockService } from './autolock_service'; export { NativeExtManager } from './nativeExtManager'; -export { PreferencesManager } from './preferencesManager'; export { StatusManager } from './statusManager'; export { ThemeManager } from './themeManager'; diff --git a/app/assets/javascripts/services/preferencesManager.ts b/app/assets/javascripts/services/preferencesManager.ts deleted file mode 100644 index 9e8ef35ae..000000000 --- a/app/assets/javascripts/services/preferencesManager.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { WebApplication } from '@/ui_models/application'; -import { - SNPredicate, - ContentType, - ApplicationService, - SNUserPrefs, - WebPrefKey, - UserPrefsMutator, - FillItemContent, - ApplicationEvent, -} from '@standardnotes/snjs'; - -export class PreferencesManager extends ApplicationService { - private userPreferences!: SNUserPrefs; - private loadingPrefs = false; - private unubscribeStreamItems?: () => void; - private needsSingletonReload = true; - - /** @override */ - async onAppLaunch() { - super.onAppLaunch(); - this.reloadSingleton(); - this.streamPreferences(); - } - - async onAppEvent(event: ApplicationEvent) { - super.onAppEvent(event); - if (event === ApplicationEvent.CompletedFullSync) { - this.reloadSingleton(); - } - } - - deinit() { - this.unubscribeStreamItems?.(); - } - - get webApplication() { - return this.application as WebApplication; - } - - streamPreferences() { - this.unubscribeStreamItems = this.application!.streamItems( - ContentType.UserPrefs, - () => { - this.needsSingletonReload = true; - } - ); - } - - private async reloadSingleton() { - if (this.loadingPrefs || !this.needsSingletonReload) { - return; - } - this.loadingPrefs = true; - const contentType = ContentType.UserPrefs; - const predicate = new SNPredicate('content_type', '=', contentType); - const previousRef = this.userPreferences; - this.userPreferences = (await this.application!.singletonManager!.findOrCreateSingleton( - predicate, - contentType, - FillItemContent({}) - )) as SNUserPrefs; - this.loadingPrefs = false; - this.needsSingletonReload = false; - if ( - previousRef?.uuid !== this.userPreferences.uuid || - this.userPreferences.lastSyncBegan?.getTime() !== - previousRef?.lastSyncBegan?.getTime() - ) { - this.webApplication - .getAppState() - .setUserPreferences(this.userPreferences); - } - } - - syncUserPreferences() { - if (this.userPreferences) { - this.application!.saveItem(this.userPreferences.uuid); - } - } - - getValue(key: WebPrefKey, defaultValue?: any) { - if (!this.userPreferences) { - return defaultValue; - } - const value = this.userPreferences.getPref(key); - return value !== undefined && value !== null ? value : defaultValue; - } - - async setUserPrefValue(key: WebPrefKey, value: any, sync = false) { - await this.application!.changeItem(this.userPreferences.uuid, (m) => { - const mutator = m as UserPrefsMutator; - mutator.setWebPref(key, value); - }); - if (sync) { - this.syncUserPreferences(); - } - } -} diff --git a/app/assets/javascripts/ui_models/app_state.ts b/app/assets/javascripts/ui_models/app_state.ts index 4ecffc365..ac09354a4 100644 --- a/app/assets/javascripts/ui_models/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state.ts @@ -19,20 +19,19 @@ import { action, makeObservable, observable } from 'mobx'; import { Bridge } from '@/services/bridge'; export enum AppStateEvent { - TagChanged = 1, - ActiveEditorChanged = 2, - PreferencesChanged = 3, - PanelResized = 4, - EditorFocused = 5, - BeganBackupDownload = 6, - EndedBackupDownload = 7, - WindowDidFocus = 9, - WindowDidBlur = 10, + TagChanged, + ActiveEditorChanged, + PanelResized, + EditorFocused, + BeganBackupDownload, + EndedBackupDownload, + WindowDidFocus, + WindowDidBlur, }; export enum EventSource { - UserInteraction = 1, - Script = 2 + UserInteraction, + Script, }; type ObserverCallback = (event: AppStateEvent, data?: any) => Promise @@ -103,7 +102,6 @@ export class AppState { rootScopeCleanup2: any; onVisibilityChange: any; selectedTag?: SNTag; - userPreferences?: SNUserPrefs; multiEditorEnabled = false; showBetaWarning = false; readonly actionsMenu = new ActionsMenuState(); @@ -379,13 +377,6 @@ export class AppState { return this.selectedTag; } - setUserPreferences(preferences: SNUserPrefs) { - this.userPreferences = preferences; - this.notifyEvent( - AppStateEvent.PreferencesChanged - ); - } - panelDidResize(name: string, collapsed: boolean) { this.notifyEvent( AppStateEvent.PanelResized, diff --git a/app/assets/javascripts/ui_models/application.ts b/app/assets/javascripts/ui_models/application.ts index 59465b74f..79f628799 100644 --- a/app/assets/javascripts/ui_models/application.ts +++ b/app/assets/javascripts/ui_models/application.ts @@ -22,7 +22,6 @@ import { NativeExtManager, StatusManager, ThemeManager, - PreferencesManager, KeyboardManager } from '@/services'; import { AppState } from '@/ui_models/app_state'; @@ -38,7 +37,6 @@ type WebServices = { nativeExtService: NativeExtManager statusManager: StatusManager themeService: ThemeManager - prefsService: PreferencesManager keyboardService: KeyboardManager } @@ -141,10 +139,6 @@ export class WebApplication extends SNApplication { return this.webServices.themeService; } - public getPrefsService() { - return this.webServices.prefsService; - } - public getKeyboardService() { return this.webServices.keyboardService; } diff --git a/app/assets/javascripts/ui_models/application_group.ts b/app/assets/javascripts/ui_models/application_group.ts index abe36b84e..dd89019cc 100644 --- a/app/assets/javascripts/ui_models/application_group.ts +++ b/app/assets/javascripts/ui_models/application_group.ts @@ -7,7 +7,6 @@ import { KeyboardManager, AutolockService, NativeExtManager, - PreferencesManager, StatusManager, ThemeManager } from '@/services'; @@ -82,9 +81,6 @@ export class ApplicationGroup extends SNApplicationGroup { const nativeExtService = new NativeExtManager( application ); - const prefsService = new PreferencesManager( - application - ); const statusService = new StatusManager(); const themeService = new ThemeManager( application, @@ -96,7 +92,6 @@ export class ApplicationGroup extends SNApplicationGroup { keyboardService, autolockService, nativeExtService, - prefsService, statusManager: statusService, themeService }); diff --git a/app/assets/javascripts/views/editor/editor_view.ts b/app/assets/javascripts/views/editor/editor_view.ts index d00e33e5c..1379dccd2 100644 --- a/app/assets/javascripts/views/editor/editor_view.ts +++ b/app/assets/javascripts/views/editor/editor_view.ts @@ -16,7 +16,7 @@ import { Uuids, ComponentArea, ComponentAction, - WebPrefKey, + PrefKey, ComponentMutator, } from '@standardnotes/snjs'; import find from 'lodash/find'; @@ -135,9 +135,9 @@ class EditorViewCtrl extends PureViewCtrl<{}, EditorState> { onReady: () => this.reloadPreferences() }; /** Used by .pug template */ - this.prefKeyMonospace = WebPrefKey.EditorMonospaceEnabled; - this.prefKeySpellcheck = WebPrefKey.EditorSpellcheck; - this.prefKeyMarginResizers = WebPrefKey.EditorResizersEnabled; + this.prefKeyMonospace = PrefKey.EditorMonospaceEnabled; + this.prefKeySpellcheck = PrefKey.EditorSpellcheck; + this.prefKeyMarginResizers = PrefKey.EditorResizersEnabled; this.editorMenuOnSelect = this.editorMenuOnSelect.bind(this); this.onPanelResizeFinish = this.onPanelResizeFinish.bind(this); @@ -239,38 +239,39 @@ class EditorViewCtrl extends PureViewCtrl<{}, EditorState> { this.registerComponentHandler(); } - /** @override */ - onAppStateEvent(eventName: AppStateEvent, data: any) { - if (eventName === AppStateEvent.PreferencesChanged) { - this.reloadPreferences(); - } - } - /** @override */ onAppEvent(eventName: ApplicationEvent) { - if (eventName === ApplicationEvent.HighLatencySync) { - this.setState({ syncTakingTooLong: true }); - } else if (eventName === ApplicationEvent.CompletedFullSync) { - this.setState({ syncTakingTooLong: false }); - const isInErrorState = this.state.saveError; - /** if we're still dirty, don't change status, a sync is likely upcoming. */ - if (!this.note.dirty && isInErrorState) { - this.showAllChangesSavedStatus(); - } - } else if (eventName === ApplicationEvent.FailedSync) { - /** - * Only show error status in editor if the note is dirty. - * Otherwise, it means the originating sync came from somewhere else - * and we don't want to display an error here. - */ - if (this.note.dirty) { - this.showErrorStatus(); - } - } else if (eventName === ApplicationEvent.LocalDatabaseWriteError) { - this.showErrorStatus({ - message: "Offline Saving Issue", - desc: "Changes not saved" - }); + switch (eventName) { + case ApplicationEvent.PreferencesChanged: + this.reloadPreferences(); + break; + case ApplicationEvent.HighLatencySync: + this.setState({ syncTakingTooLong: true }); + break; + case ApplicationEvent.CompletedFullSync: + this.setState({ syncTakingTooLong: false }); + const isInErrorState = this.state.saveError; + /** if we're still dirty, don't change status, a sync is likely upcoming. */ + if (!this.note.dirty && isInErrorState) { + this.showAllChangesSavedStatus(); + } + break; + case ApplicationEvent.FailedSync: + /** + * Only show error status in editor if the note is dirty. + * Otherwise, it means the originating sync came from somewhere else + * and we don't want to display an error here. + */ + if (this.note.dirty) { + this.showErrorStatus(); + } + break; + case ApplicationEvent.LocalDatabaseWriteError: + this.showErrorStatus({ + message: "Offline Saving Issue", + desc: "Changes not saved" + }); + break; } } @@ -891,40 +892,40 @@ class EditorViewCtrl extends PureViewCtrl<{}, EditorState> { async onPanelResizeFinish(width: number, left: number, isMaxWidth: boolean) { if (isMaxWidth) { - await this.application.getPrefsService().setUserPrefValue( - WebPrefKey.EditorWidth, + await this.application.setPreference( + PrefKey.EditorWidth, null ); } else { if (width !== undefined && width !== null) { - await this.application.getPrefsService().setUserPrefValue( - WebPrefKey.EditorWidth, + await this.application.setPreference( + PrefKey.EditorWidth, width ); this.leftPanelPuppet!.setWidth!(width); } } if (left !== undefined && left !== null) { - await this.application.getPrefsService().setUserPrefValue( - WebPrefKey.EditorLeft, + await this.application.setPreference( + PrefKey.EditorLeft, left ); this.rightPanelPuppet!.setLeft!(left); } - this.application.getPrefsService().syncUserPreferences(); + this.application.sync(); } async reloadPreferences() { - const monospaceFont = this.application.getPrefsService().getValue( - WebPrefKey.EditorMonospaceEnabled, + const monospaceFont = this.application.getPreference( + PrefKey.EditorMonospaceEnabled, true ); - const spellcheck = this.application.getPrefsService().getValue( - WebPrefKey.EditorSpellcheck, + const spellcheck = this.application.getPreference( + PrefKey.EditorSpellcheck, true ); - const marginResizersEnabled = this.application.getPrefsService().getValue( - WebPrefKey.EditorResizersEnabled, + const marginResizersEnabled = this.application.getPreference( + PrefKey.EditorResizersEnabled, true ); await this.setState({ @@ -945,16 +946,16 @@ class EditorViewCtrl extends PureViewCtrl<{}, EditorState> { this.leftPanelPuppet?.ready && this.rightPanelPuppet?.ready ) { - const width = this.application.getPrefsService().getValue( - WebPrefKey.EditorWidth, + const width = this.application.getPreference( + PrefKey.EditorWidth, null ); if (width != null) { this.leftPanelPuppet!.setWidth!(width); this.rightPanelPuppet!.setWidth!(width); } - const left = this.application.getPrefsService().getValue( - WebPrefKey.EditorLeft, + const left = this.application.getPreference( + PrefKey.EditorLeft, null ); if (left != null) { @@ -982,24 +983,23 @@ class EditorViewCtrl extends PureViewCtrl<{}, EditorState> { } } - async toggleWebPrefKey(key: WebPrefKey) { + async toggleWebPrefKey(key: PrefKey) { const currentValue = (this.state as any)[key]; - await this.application.getPrefsService().setUserPrefValue( + await this.application.setPreference( key, !currentValue, - true ); await this.setState({ [key]: !currentValue }) this.reloadFont(); - if (key === WebPrefKey.EditorSpellcheck) { + if (key === PrefKey.EditorSpellcheck) { /** Allows textarea to reload */ await this.setState({ textareaUnloading: true }); await this.setState({ textareaUnloading: false }); this.reloadFont(); - } else if (key === WebPrefKey.EditorResizersEnabled && this.state[key] === true) { + } else if (key === PrefKey.EditorResizersEnabled && this.state[key] === true) { this.$timeout(() => { this.leftPanelPuppet!.flash!(); this.rightPanelPuppet!.flash!(); diff --git a/app/assets/javascripts/views/notes/note_utils.ts b/app/assets/javascripts/views/notes/note_utils.ts index 83c860796..4ca9604c3 100644 --- a/app/assets/javascripts/views/notes/note_utils.ts +++ b/app/assets/javascripts/views/notes/note_utils.ts @@ -1,16 +1,5 @@ import { SNNote } from '@standardnotes/snjs'; -export enum NoteSortKey { - CreatedAt = 'created_at', - UserUpdatedAt = 'userModifiedDate', - Title = 'title', - - /** @legacy Use UserUpdatedAt instead */ - UpdatedAt = 'updated_at', - /** @legacy Use UserUpdatedAt instead */ - ClientUpdatedAt = 'client_updated_at', -} - export function notePassesFilter( note: SNNote, showArchived: boolean, diff --git a/app/assets/javascripts/views/notes/notes_view.ts b/app/assets/javascripts/views/notes/notes_view.ts index 36ccba36b..df3d0792a 100644 --- a/app/assets/javascripts/views/notes/notes_view.ts +++ b/app/assets/javascripts/views/notes/notes_view.ts @@ -6,7 +6,7 @@ import { removeFromArray, SNNote, SNTag, - WebPrefKey, + PrefKey, findInArray, CollectionSort, } from '@standardnotes/snjs'; @@ -17,7 +17,6 @@ import { PANEL_NAME_NOTES } from '@/views/constants'; import { - NoteSortKey, notePassesFilter } from './note_utils'; import { UuidString } from '@standardnotes/snjs'; @@ -37,13 +36,13 @@ type NotesState = { noteFilter: { text: string } mutable: { showMenu: boolean } completedFullSync: boolean - [WebPrefKey.TagsPanelWidth]?: number - [WebPrefKey.NotesPanelWidth]?: number - [WebPrefKey.EditorWidth]?: number - [WebPrefKey.EditorLeft]?: number - [WebPrefKey.EditorMonospaceEnabled]?: boolean - [WebPrefKey.EditorSpellcheck]?: boolean - [WebPrefKey.EditorResizersEnabled]?: boolean + [PrefKey.TagsPanelWidth]?: number + [PrefKey.NotesPanelWidth]?: number + [PrefKey.EditorWidth]?: number + [PrefKey.EditorLeft]?: number + [PrefKey.EditorMonospaceEnabled]?: boolean + [PrefKey.EditorSpellcheck]?: boolean + [PrefKey.EditorResizersEnabled]?: boolean } type NoteFlag = { @@ -147,8 +146,6 @@ class NotesViewCtrl extends PureViewCtrl<{}, NotesState> { this.handleTagChange(this.selectedTag!); } else if (eventName === AppStateEvent.ActiveEditorChanged) { this.handleEditorChange(); - } else if (eventName === AppStateEvent.PreferencesChanged) { - this.reloadPreferences(); } else if (eventName === AppStateEvent.EditorFocused) { this.setShowMenuFalse(); } @@ -166,6 +163,9 @@ class NotesViewCtrl extends PureViewCtrl<{}, NotesState> { /** @override */ async onAppEvent(eventName: ApplicationEvent) { switch (eventName) { + case ApplicationEvent.PreferencesChanged: + this.reloadPreferences(); + break; case ApplicationEvent.SignedIn: this.appState.closeAllEditors(); this.selectFirstNote(); @@ -420,37 +420,40 @@ class NotesViewCtrl extends PureViewCtrl<{}, NotesState> { async reloadPreferences() { const viewOptions = {} as NotesState; const prevSortValue = this.getState().sortBy; - let sortBy = this.application!.getPrefsService().getValue( - WebPrefKey.SortNotesBy, - NoteSortKey.CreatedAt + let sortBy = this.application!.getPreference( + PrefKey.SortNotesBy, + CollectionSort.CreatedAt ); - if (sortBy === NoteSortKey.UpdatedAt || sortBy === NoteSortKey.ClientUpdatedAt) { + if ( + sortBy === CollectionSort.UpdatedAt || + (sortBy as string) === "client_updated_at" + ) { /** Use UserUpdatedAt instead */ - sortBy = NoteSortKey.UserUpdatedAt; + sortBy = CollectionSort.UpdatedAt; } viewOptions.sortBy = sortBy; - viewOptions.sortReverse = this.application!.getPrefsService().getValue( - WebPrefKey.SortNotesReverse, + viewOptions.sortReverse = this.application!.getPreference( + PrefKey.SortNotesReverse, false ); - viewOptions.showArchived = this.application!.getPrefsService().getValue( - WebPrefKey.NotesShowArchived, + viewOptions.showArchived = this.application!.getPreference( + PrefKey.NotesShowArchived, false ); - viewOptions.hidePinned = this.application!.getPrefsService().getValue( - WebPrefKey.NotesHidePinned, + viewOptions.hidePinned = this.application!.getPreference( + PrefKey.NotesHidePinned, false ); - viewOptions.hideNotePreview = this.application!.getPrefsService().getValue( - WebPrefKey.NotesHideNotePreview, + viewOptions.hideNotePreview = this.application!.getPreference( + PrefKey.NotesHideNotePreview, false ); - viewOptions.hideDate = this.application!.getPrefsService().getValue( - WebPrefKey.NotesHideDate, + viewOptions.hideDate = this.application!.getPreference( + PrefKey.NotesHideDate, false ); - viewOptions.hideTags = this.application.getPrefsService().getValue( - WebPrefKey.NotesHideTags, + viewOptions.hideTags = this.application.getPreference( + PrefKey.NotesHideTags, true, ); const state = this.getState(); @@ -475,8 +478,8 @@ class NotesViewCtrl extends PureViewCtrl<{}, NotesState> { } reloadPanelWidth() { - const width = this.application!.getPrefsService().getValue( - WebPrefKey.NotesPanelWidth + const width = this.application!.getPreference( + PrefKey.NotesPanelWidth ); if (width && this.panelPuppet!.ready) { this.panelPuppet!.setWidth!(width); @@ -495,10 +498,9 @@ class NotesViewCtrl extends PureViewCtrl<{}, NotesState> { __: boolean, isCollapsed: boolean ) { - this.application!.getPrefsService().setUserPrefValue( - WebPrefKey.NotesPanelWidth, - newWidth, - true + this.application!.setPreference( + PrefKey.NotesPanelWidth, + newWidth ); this.application!.getAppState().panelDidResize( PANEL_NAME_NOTES, @@ -541,11 +543,11 @@ class NotesViewCtrl extends PureViewCtrl<{}, NotesState> { optionsSubtitle() { let base = ""; - if (this.getState().sortBy === NoteSortKey.CreatedAt) { + if (this.getState().sortBy === CollectionSort.CreatedAt) { base += " Date Added"; - } else if (this.getState().sortBy === NoteSortKey.UserUpdatedAt) { + } else if (this.getState().sortBy === CollectionSort.UpdatedAt) { base += " Date Modified"; - } else if (this.getState().sortBy === NoteSortKey.Title) { + } else if (this.getState().sortBy === CollectionSort.Title) { base += " Title"; } if (this.getState().showArchived) { @@ -709,40 +711,37 @@ class NotesViewCtrl extends PureViewCtrl<{}, NotesState> { this.setShowMenuFalse(); } - toggleWebPrefKey(key: WebPrefKey) { - this.application!.getPrefsService().setUserPrefValue( + togglePrefKey(key: PrefKey) { + this.application!.setPreference( key, - !this.state[key], - true + !this.state[key] ); } selectedSortByCreated() { - this.setSortBy(NoteSortKey.CreatedAt); + this.setSortBy(CollectionSort.CreatedAt); } selectedSortByUpdated() { - this.setSortBy(NoteSortKey.ClientUpdatedAt); + this.setSortBy(CollectionSort.UpdatedAt); } selectedSortByTitle() { - this.setSortBy(NoteSortKey.Title); + this.setSortBy(CollectionSort.Title); } toggleReverseSort() { this.selectedMenuItem(); - this.application!.getPrefsService().setUserPrefValue( - WebPrefKey.SortNotesReverse, - !this.getState().sortReverse, - true + this.application!.setPreference( + PrefKey.SortNotesReverse, + !this.getState().sortReverse ); } - setSortBy(type: NoteSortKey) { - this.application!.getPrefsService().setUserPrefValue( - WebPrefKey.SortNotesBy, - type, - true + setSortBy(type: CollectionSort) { + this.application!.setPreference( + PrefKey.SortNotesBy, + type ); } diff --git a/app/assets/javascripts/views/tags/tags_view.ts b/app/assets/javascripts/views/tags/tags_view.ts index 3b36dfb0d..01f9bcb8a 100644 --- a/app/assets/javascripts/views/tags/tags_view.ts +++ b/app/assets/javascripts/views/tags/tags_view.ts @@ -9,7 +9,7 @@ import { SNSmartTag, ComponentArea, SNComponent, - WebPrefKey, + PrefKey, UuidString, TagMutator } from '@standardnotes/snjs'; @@ -145,10 +145,8 @@ class TagsViewCtrl extends PureViewCtrl<{}, TagState> { } /** @override */ - onAppStateEvent(eventName: AppStateEvent, data?: any) { - if (eventName === AppStateEvent.PreferencesChanged) { - this.loadPreferences(); - } else if (eventName === AppStateEvent.TagChanged) { + onAppStateEvent(eventName: AppStateEvent) { + if (eventName === AppStateEvent.TagChanged) { this.setState({ selectedTag: this.application.getAppState().getSelectedTag() }); @@ -159,8 +157,13 @@ class TagsViewCtrl extends PureViewCtrl<{}, TagState> { /** @override */ async onAppEvent(eventName: ApplicationEvent) { super.onAppEvent(eventName); - if (eventName === ApplicationEvent.LocalDataIncrementalLoad) { - this.reloadNoteCounts(); + switch (eventName) { + case ApplicationEvent.LocalDataIncrementalLoad: + this.reloadNoteCounts(); + break; + case ApplicationEvent.PreferencesChanged: + this.loadPreferences(); + break; } } @@ -203,7 +206,7 @@ class TagsViewCtrl extends PureViewCtrl<{}, TagState> { if (!this.panelPuppet.ready) { return; } - const width = this.application.getPrefsService().getValue(WebPrefKey.TagsPanelWidth); + const width = this.application.getPreference(PrefKey.TagsPanelWidth); if (width) { this.panelPuppet.setWidth!(width); if (this.panelPuppet.isCollapsed!()) { @@ -221,11 +224,10 @@ class TagsViewCtrl extends PureViewCtrl<{}, TagState> { _isAtMaxWidth: boolean, isCollapsed: boolean ) => { - this.application.getPrefsService().setUserPrefValue( - WebPrefKey.TagsPanelWidth, - newWidth, - true - ); + this.application.setPreference( + PrefKey.TagsPanelWidth, + newWidth + ).then(() => this.application.sync()); this.application.getAppState().panelDidResize( PANEL_NAME_TAGS, isCollapsed diff --git a/package.json b/package.json index c5407ca43..e613ed578 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,6 @@ "dotenv": "^8.2.0", "eslint": "^6.8.0", "eslint-config-prettier": "^6.10.0", - "eslint-config-semistandard": "^15.0.0", - "eslint-config-standard": "^14.1.0", "eslint-plugin-import": "^2.20.1", "eslint-plugin-promise": "^4.2.1", "eslint-plugin-standard": "^4.0.1",