From 2c0f215409a3b5f4d2001703b7c174e654829b73 Mon Sep 17 00:00:00 2001 From: Baptiste Grob <60621355+baptiste-grob@users.noreply.github.com> Date: Wed, 16 Dec 2020 17:27:26 +0100 Subject: [PATCH] feat: (wip) sessions management --- .babelrc | 7 +- app/assets/javascripts/app.ts | 5 +- .../directives/views/accountMenu.ts | 7 + .../directives/views/sessionsModal.tsx | 251 ++++++++++++ app/assets/javascripts/index.ts | 2 + .../javascripts/services/archiveManager.ts | 2 +- app/assets/javascripts/tsconfig.json | 2 + app/assets/javascripts/ui_models/app_state.ts | 109 +++--- .../views/abstract/pure_view_ctrl.ts | 2 +- .../views/application/application-view.pug | 3 + app/assets/stylesheets/_main.scss | 12 +- app/assets/stylesheets/_notes.scss | 9 +- app/assets/stylesheets/_reach-sub.scss | 38 ++ app/assets/stylesheets/_sessions-modal.scss | 48 +++ app/assets/stylesheets/_stylekit-sub.scss | 8 +- app/assets/stylesheets/index.css.scss | 2 + .../templates/directives/account-menu.pug | 5 +- package.json | 24 +- webpack.config.js | 9 +- yarn.lock | 370 +++++++++++++++--- 20 files changed, 784 insertions(+), 131 deletions(-) create mode 100644 app/assets/javascripts/directives/views/sessionsModal.tsx create mode 100644 app/assets/stylesheets/_reach-sub.scss create mode 100644 app/assets/stylesheets/_sessions-modal.scss diff --git a/.babelrc b/.babelrc index 5711d2ada..766002c6b 100644 --- a/.babelrc +++ b/.babelrc @@ -4,7 +4,10 @@ "@babel/preset-env" ], "plugins": [ - "@babel/plugin-proposal-class-properties", - "angularjs-annotate" + "angularjs-annotate", + ["@babel/plugin-transform-react-jsx", { + "pragma": "h", + "pragmaFrag": "Fragment" + }] ] } diff --git a/app/assets/javascripts/app.ts b/app/assets/javascripts/app.ts index 63172c94e..69cb4fcab 100644 --- a/app/assets/javascripts/app.ts +++ b/app/assets/javascripts/app.ts @@ -55,9 +55,9 @@ import { trusted } from './filters'; import { isDev } from './utils'; import { BrowserBridge } from './services/browserBridge'; import { startErrorReporting } from './services/errorReporting'; -import { alertDialog } from './services/alertService'; import { StartApplication } from './startApplication'; import { Bridge } from './services/bridge'; +import { SessionsModalDirective } from './directives/views/sessionsModal'; const startApplication: StartApplication = async function startApplication( defaultSyncServerHost: string, @@ -122,7 +122,8 @@ const startApplication: StartApplication = async function startApplication( ) .directive('revisionPreviewModal', () => new RevisionPreviewModal()) .directive('historyMenu', () => new HistoryMenu()) - .directive('syncResolutionMenu', () => new SyncResolutionMenu()); + .directive('syncResolutionMenu', () => new SyncResolutionMenu()) + .directive('sessionsModal', SessionsModalDirective); // Filters angular.module('app').filter('trusted', ['$sce', trusted]); diff --git a/app/assets/javascripts/directives/views/accountMenu.ts b/app/assets/javascripts/directives/views/accountMenu.ts index c5c550582..3cfec1d99 100644 --- a/app/assets/javascripts/directives/views/accountMenu.ts +++ b/app/assets/javascripts/directives/views/accountMenu.ts @@ -69,6 +69,7 @@ type AccountMenuState = { syncInProgress: boolean; syncError: string; syncPercentage: string; + showSessions: boolean; } class AccountMenuCtrl extends PureViewCtrl<{}, AccountMenuState> { @@ -101,6 +102,7 @@ class AccountMenuCtrl extends PureViewCtrl<{}, AccountMenuState> { mutable: {}, showBetaWarning: false, errorReportingEnabled: !storage.get(StorageKey.DisableErrorReporting), + showSessions: this.appState.enableUnfinishedFeatures, } as AccountMenuState; } @@ -320,6 +322,11 @@ class AccountMenuCtrl extends PureViewCtrl<{}, AccountMenuState> { this.application!.presentPasswordWizard(PasswordWizardType.ChangePassword); } + openSessionsModal() { + this.close(); + this.appState.openSessionsModal(); + } + async openPrivilegesModal() { const run = () => { this.application!.presentPrivilegesManagementModal(); diff --git a/app/assets/javascripts/directives/views/sessionsModal.tsx b/app/assets/javascripts/directives/views/sessionsModal.tsx new file mode 100644 index 000000000..017fdbd3b --- /dev/null +++ b/app/assets/javascripts/directives/views/sessionsModal.tsx @@ -0,0 +1,251 @@ +import { AppState } from '@/ui_models/app_state'; +import { PureViewCtrl } from '@/views'; +import { SNApplication, RemoteSession, UuidString } from '@standardnotes/snjs'; +import { autorun, IAutorunOptions, IReactionPublic } from 'mobx'; +import { render, FunctionComponent } from 'preact'; +import { useState, useEffect, useRef } from 'preact/hooks'; +import { Dialog } from '@reach/dialog'; +import { Alert } from '@reach/alert'; +import { + AlertDialog, + AlertDialogDescription, + AlertDialogLabel, +} from '@reach/alert-dialog'; + +function useAutorun(view: (r: IReactionPublic) => any, opts?: IAutorunOptions) { + useEffect(() => autorun(view, opts), []); +} + +function useSessions( + application: SNApplication +): [ + RemoteSession[], + () => void, + boolean, + (uuid: UuidString) => Promise, + string +] { + const [sessions, setSessions] = useState([]); + const [lastRefreshDate, setLastRefreshDate] = useState(Date.now()); + const [refreshing, setRefreshing] = useState(true); + const [errorMessage, setErrorMessage] = useState(''); + + useEffect(() => { + (async () => { + setRefreshing(true); + const response = await application.getSessions(); + if ('error' in response) { + if (response.error?.message) { + setErrorMessage(response.error.message); + } else { + setErrorMessage('An unknown error occured while loading sessions.'); + } + } else { + const sessions = response as RemoteSession[]; + setSessions(sessions); + setErrorMessage(''); + } + setRefreshing(false); + })(); + }, [lastRefreshDate]); + + function refresh() { + setLastRefreshDate(Date.now()); + } + + async function revokeSession(uuid: UuidString) { + let sessionsBeforeRevoke = sessions; + setSessions(sessions.filter((session) => session.uuid !== uuid)); + const response = await application.revokeSession(uuid); + if ('error' in response) { + if (response.error?.message) { + setErrorMessage(response.error?.message); + } else { + setErrorMessage('An unknown error occured while revoking the session.'); + } + setSessions(sessionsBeforeRevoke); + } + } + + return [sessions, refresh, refreshing, revokeSession, errorMessage]; +} + +const SessionsModal: FunctionComponent<{ + appState: AppState; + application: SNApplication; +}> = ({ appState, application }) => { + const close = () => appState.closeSessionsModal(); + + const [ + sessions, + refresh, + refreshing, + revokeSession, + errorMessage, + ] = useSessions(application); + + const [revokingSessionUuid, setRevokingSessionUuid] = useState(''); + const closeRevokeSessionAlert = () => setRevokingSessionUuid(''); + const cancelRevokeRef = useRef(); + + const formatter = new Intl.DateTimeFormat(undefined, { + year: 'numeric', + month: 'long', + day: 'numeric', + weekday: 'long', + hour: 'numeric', + minute: 'numeric', + }); + + return ( + <> + +
+
+
+
+
Active Sessions
+
+ + +
+
+
+ {refreshing ? ( + <> +
+

+ Loading sessions +

+ + ) : ( + <> + {errorMessage && ( + {errorMessage} + )} + {sessions.length > 0 && ( +
    + {sessions.map((session) => ( +
  • +

    {session.device_info}

    + {session.current ? ( + Current session + ) : ( + <> +

    + Signed in on{' '} + {formatter.format(session.updated_at)} +

    + + + )} +
  • + ))} +
+ )} + + )} +
+
+
+
+
+ {revokingSessionUuid && ( + +
+
+
+
+
+ + Revoke this session? + + +

+ The associated app will not be able to sync unless you + sign in again. +

+
+
+
+ + +
+
+
+
+
+
+
+
+ )} + + ); +}; + +const Sessions: FunctionComponent<{ + appState: AppState; + application: SNApplication; +}> = ({ appState, application }) => { + const [showModal, setShowModal] = useState(false); + useAutorun(() => setShowModal(appState.isSessionsModalVisible)); + + if (showModal) { + return ; + } else { + return null; + } +}; + +class SessionsModalCtrl extends PureViewCtrl<{}, {}> { + /* @ngInject */ + constructor(private $element: JQLite, $timeout: ng.ITimeoutService) { + super($timeout); + this.$element = $element; + } + $onChanges() { + render( + , + this.$element[0] + ); + } +} + +export function SessionsModalDirective() { + return { + controller: SessionsModalCtrl, + bindToController: true, + scope: { + application: '=', + }, + }; +} diff --git a/app/assets/javascripts/index.ts b/app/assets/javascripts/index.ts index 5630efe70..2e0778d4a 100644 --- a/app/assets/javascripts/index.ts +++ b/app/assets/javascripts/index.ts @@ -1,8 +1,10 @@ //= require_tree ./app // css +import '@reach/dialog/styles.css'; import 'sn-stylekit/dist/stylekit.css'; import '../stylesheets/index.css.scss'; +// import '../stylesheets/_reach-sub.scss'; // Vendor import 'angular'; diff --git a/app/assets/javascripts/services/archiveManager.ts b/app/assets/javascripts/services/archiveManager.ts index b6e7f915c..c1b183dbd 100644 --- a/app/assets/javascripts/services/archiveManager.ts +++ b/app/assets/javascripts/services/archiveManager.ts @@ -87,7 +87,7 @@ export class ArchiveManager { scriptTag.async = false; const headTag = document.getElementsByTagName('head')[0]; headTag.appendChild(scriptTag); - return new Promise((resolve) => { + return new Promise((resolve) => { scriptTag.onload = () => { this.zip.workerScriptsPath = 'assets/zip/'; resolve(); diff --git a/app/assets/javascripts/tsconfig.json b/app/assets/javascripts/tsconfig.json index c0b12433f..1381b681e 100644 --- a/app/assets/javascripts/tsconfig.json +++ b/app/assets/javascripts/tsconfig.json @@ -12,6 +12,8 @@ "newLine": "lf", "declarationDir": "../../../dist/@types", "baseUrl": ".", + "jsx": "react-jsx", + "jsxImportSource": "preact", "paths": { "%/*": ["../templates/*"], "@/*": ["./*"], diff --git a/app/assets/javascripts/ui_models/app_state.ts b/app/assets/javascripts/ui_models/app_state.ts index ac09354a4..0bafd2df9 100644 --- a/app/assets/javascripts/ui_models/app_state.ts +++ b/app/assets/javascripts/ui_models/app_state.ts @@ -1,4 +1,4 @@ -import { isDesktopApplication } from '@/utils'; +import { isDesktopApplication, isDev } from '@/utils'; import pull from 'lodash/pull'; import { ProtectedAction, @@ -11,7 +11,7 @@ import { PayloadSource, DeinitSource, UuidString, - SyncOpStatus + SyncOpStatus, } from '@standardnotes/snjs'; import { WebApplication } from '@/ui_models/application'; import { Editor } from '@/ui_models/editor'; @@ -27,14 +27,14 @@ export enum AppStateEvent { EndedBackupDownload, WindowDidFocus, WindowDidBlur, -}; +} export enum EventSource { UserInteraction, Script, -}; +} -type ObserverCallback = (event: AppStateEvent, data?: any) => Promise +type ObserverCallback = (event: AppStateEvent, data?: any) => Promise; const SHOW_BETA_WARNING_KEY = 'show_beta_warning'; @@ -76,7 +76,8 @@ export class SyncState { this.errorMessage = status.error?.message; this.inProgress = status.syncInProgress; const stats = status.getStats(); - const completionPercentage = stats.uploadCompletionCount === 0 + const completionPercentage = + stats.uploadCompletionCount === 0 ? 0 : stats.uploadCompletionCount / stats.uploadTotalCount; @@ -92,6 +93,9 @@ export class SyncState { } export class AppState { + readonly enableUnfinishedFeatures = + isDev || location.host.includes('app-dev.standardnotes.org'); + $rootScope: ng.IRootScopeService; $timeout: ng.ITimeoutService; application: WebApplication; @@ -106,31 +110,36 @@ export class AppState { showBetaWarning = false; readonly actionsMenu = new ActionsMenuState(); readonly sync = new SyncState(); + isSessionsModalVisible = true; /* @ngInject */ constructor( $rootScope: ng.IRootScopeService, $timeout: ng.ITimeoutService, application: WebApplication, - private bridge: Bridge, + private bridge: Bridge ) { this.$timeout = $timeout; this.$rootScope = $rootScope; this.application = application; makeObservable(this, { showBetaWarning: observable, + isSessionsModalVisible: observable, + enableBetaWarning: action, disableBetaWarning: action, + openSessionsModal: action, + closeSessionsModal: action, }); this.addAppEventObserver(); this.streamNotesAndTags(); this.onVisibilityChange = () => { - const visible = document.visibilityState === "visible"; + const visible = document.visibilityState === 'visible'; const event = visible ? AppStateEvent.WindowDidFocus : AppStateEvent.WindowDidBlur; this.notifyEvent(event); - } + }; this.registerVisibilityObservers(); this.determineBetaWarningValue(); } @@ -153,6 +162,14 @@ export class AppState { this.onVisibilityChange = undefined; } + openSessionsModal() { + this.isSessionsModalVisible = true; + } + + closeSessionsModal() { + this.isSessionsModalVisible = false; + } + disableBetaWarning() { this.showBetaWarning = false; localStorage.setItem(SHOW_BETA_WARNING_KEY, 'false'); @@ -188,10 +205,10 @@ export class AppState { async createEditor(title?: string) { const activeEditor = this.getActiveEditor(); const activeTagUuid = this.selectedTag - ? this.selectedTag.isSmartTag() - ? undefined - : this.selectedTag.uuid - : undefined; + ? this.selectedTag.isSmartTag() + ? undefined + : this.selectedTag.uuid + : undefined; if (!activeEditor || this.multiEditorEnabled) { this.application.editorGroup.createEditor( @@ -216,10 +233,13 @@ export class AppState { } await this.notifyEvent(AppStateEvent.ActiveEditorChanged); }; - if (note && note.safeContent.protected && - await this.application.privilegesService!.actionRequiresPrivilege( + if ( + note && + note.safeContent.protected && + (await this.application.privilegesService!.actionRequiresPrivilege( ProtectedAction.ViewProtectedNotes - )) { + )) + ) { return new Promise((resolve) => { this.application.presentPrivilegesModal( ProtectedAction.ViewProtectedNotes, @@ -267,8 +287,8 @@ export class AppState { async (items, source) => { /** Close any editors for deleted/trashed/archived notes */ if (source === PayloadSource.PreSyncSave) { - const notes = items.filter((candidate) => - candidate.content_type === ContentType.Note + const notes = items.filter( + (candidate) => candidate.content_type === ContentType.Note ) as SNNote[]; for (const note of notes) { const editor = this.editorForNote(note); @@ -285,7 +305,9 @@ export class AppState { } } if (this.selectedTag) { - const matchingTag = items.find((candidate) => candidate.uuid === this.selectedTag!.uuid); + const matchingTag = items.find( + (candidate) => candidate.uuid === this.selectedTag!.uuid + ); if (matchingTag) { this.selectedTag = matchingTag as SNTag; } @@ -319,9 +341,12 @@ export class AppState { this.rootScopeCleanup1 = this.$rootScope.$on('window-lost-focus', () => { this.notifyEvent(AppStateEvent.WindowDidBlur); }); - this.rootScopeCleanup2 = this.$rootScope.$on('window-gained-focus', () => { - this.notifyEvent(AppStateEvent.WindowDidFocus); - }); + this.rootScopeCleanup2 = this.$rootScope.$on( + 'window-gained-focus', + () => { + this.notifyEvent(AppStateEvent.WindowDidFocus); + } + ); } else { /* Tab visibility listener, web only */ document.addEventListener('visibilitychange', this.onVisibilityChange); @@ -341,7 +366,7 @@ export class AppState { * Timeout is particullary important so we can give all initial * controllers a chance to construct before propogting any events * */ - return new Promise((resolve) => { + return new Promise((resolve) => { this.$timeout(async () => { for (const callback of this.observers) { await callback(eventName, data); @@ -357,20 +382,17 @@ export class AppState { } const previousTag = this.selectedTag; this.selectedTag = tag; - this.notifyEvent( - AppStateEvent.TagChanged, - { - tag: tag, - previousTag: previousTag - } - ); + this.notifyEvent(AppStateEvent.TagChanged, { + tag: tag, + previousTag: previousTag, + }); } /** Returns the tags that are referncing this note */ public getNoteTags(note: SNNote) { return this.application.referencingForItem(note).filter((ref) => { return ref.content_type === ContentType.Tag; - }) as SNTag[] + }) as SNTag[]; } public getSelectedTag() { @@ -378,32 +400,21 @@ export class AppState { } panelDidResize(name: string, collapsed: boolean) { - this.notifyEvent( - AppStateEvent.PanelResized, - { - panel: name, - collapsed: collapsed - } - ); + this.notifyEvent(AppStateEvent.PanelResized, { + panel: name, + collapsed: collapsed, + }); } editorDidFocus(eventSource: EventSource) { - this.notifyEvent( - AppStateEvent.EditorFocused, - { eventSource: eventSource } - ); + this.notifyEvent(AppStateEvent.EditorFocused, { eventSource: eventSource }); } beganBackupDownload() { - this.notifyEvent( - AppStateEvent.BeganBackupDownload - ); + this.notifyEvent(AppStateEvent.BeganBackupDownload); } endedBackupDownload(success: boolean) { - this.notifyEvent( - AppStateEvent.EndedBackupDownload, - { success: success } - ); + this.notifyEvent(AppStateEvent.EndedBackupDownload, { success: success }); } } diff --git a/app/assets/javascripts/views/abstract/pure_view_ctrl.ts b/app/assets/javascripts/views/abstract/pure_view_ctrl.ts index c3e275a1c..fb8af1751 100644 --- a/app/assets/javascripts/views/abstract/pure_view_ctrl.ts +++ b/app/assets/javascripts/views/abstract/pure_view_ctrl.ts @@ -69,7 +69,7 @@ export class PureViewCtrl

{ if (!this.$timeout) { return; } - return new Promise((resolve) => { + return new Promise((resolve) => { this.stateTimeout = this.$timeout(() => { /** * State changes must be *inside* the timeout block for them to be affected in the UI diff --git a/app/assets/javascripts/views/application/application-view.pug b/app/assets/javascripts/views/application/application-view.pug index 9da7ffde2..bb7149b0a 100644 --- a/app/assets/javascripts/views/application/application-view.pug +++ b/app/assets/javascripts/views/application/application-view.pug @@ -24,3 +24,6 @@ symbol#layers-sharp.ionicon(viewbox="0 0 512 512") path(d="M480 150L256 48 32 150l224 104 224-104zM255.71 392.95l-144.81-66.2L32 362l224 102 224-102-78.69-35.3-145.6 66.25z") path(d="M480 256l-75.53-33.53L256.1 290.6l-148.77-68.17L32 256l224 102 224-102z") + sessions-modal( + application='self.application' + ) diff --git a/app/assets/stylesheets/_main.scss b/app/assets/stylesheets/_main.scss index cacf5add5..c0db8f3b5 100644 --- a/app/assets/stylesheets/_main.scss +++ b/app/assets/stylesheets/_main.scss @@ -48,10 +48,16 @@ body { color: var(--sn-stylekit-info-contrast-color); } -*:focus {outline:0;} +h1 { + font-size: var(--sn-stylekit-font-size-h1); +} -button:focus { - outline:0; +h2 { + font-size: var(--sn-stylekit-font-size-h2); +} + +h3 { + font-size: var(--sn-stylekit-font-size-h3); } input, button, select, textarea { diff --git a/app/assets/stylesheets/_notes.scss b/app/assets/stylesheets/_notes.scss index 70d7cb7bd..38a22d8a7 100644 --- a/app/assets/stylesheets/_notes.scss +++ b/app/assets/stylesheets/_notes.scss @@ -63,9 +63,16 @@ font-weight: normal; font-size: var(--sn-stylekit-font-size-h3); - border: none; + border-style: solid; + border-color: transparent; width: 100%; position: relative; + + &:focus { + outline: 0; + border-color: var(--sn-stylekit-info-color); + border-width: 1px; + } } #search-clear-button { diff --git a/app/assets/stylesheets/_reach-sub.scss b/app/assets/stylesheets/_reach-sub.scss new file mode 100644 index 000000000..b6a9446cf --- /dev/null +++ b/app/assets/stylesheets/_reach-sub.scss @@ -0,0 +1,38 @@ +[data-reach-dialog-overlay] { + z-index: $z-index-modal; + background: none; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + overflow: unset; +} +[data-reach-dialog-overlay]::before { + background-color: var(--sn-stylekit-contrast-background-color); + content: ""; + position: fixed; + top: 0px; + right: 0px; + bottom: 0px; + left: 0px; + opacity: 0.75; + +} + +[data-reach-dialog-content] { + padding: 0; + margin: 0; + position: relative; + overflow: unset; + flex-basis: 0; +} + +[data-reach-dialog-content] .sk-modal-content, +[data-reach-dialog-content] .sn-component, +[data-reach-dialog-content] .sk-panel { + height: 100%; +} + +[data-reach-alert-dialog-content] { + width: auto; +} diff --git a/app/assets/stylesheets/_sessions-modal.scss b/app/assets/stylesheets/_sessions-modal.scss new file mode 100644 index 000000000..09b9f919f --- /dev/null +++ b/app/assets/stylesheets/_sessions-modal.scss @@ -0,0 +1,48 @@ +.sessions-modal { + h2, ul, p { + margin: 0; + padding: 0; + } + h2 { + font-size: var(--sn-stylekit-font-size-h2); + } + ul { + grid-column: 1 / 3; + display: grid; + gap: 16px; + grid-gap: 16px; + } + li { + display: grid; + grid-template-columns: 1fr max-content; + border-bottom: 1px solid var(--sn-stylekit-border-color); + padding-bottom: 16px; + grid-column-gap: 12px; + column-gap: 12px; + } + li:last-of-type { + border: none; + padding-bottom: 0; + } + li > * { + grid-column: 1; + } + li button { + grid-column: 2; + grid-row: 1 / span 3; + align-self: center; + } + .sn-component .sk-panel-content { + padding-bottom: 1.6rem; + display: grid; + grid-template-columns: auto 1fr; + align-items: center; + grid-gap: 8px; + gap: 8px; + } +} + +.sessions-modal-refreshing { + grid-column: 2; + font-weight: normal; +} diff --git a/app/assets/stylesheets/_stylekit-sub.scss b/app/assets/stylesheets/_stylekit-sub.scss index 201a604d2..8ccf6d2ed 100644 --- a/app/assets/stylesheets/_stylekit-sub.scss +++ b/app/assets/stylesheets/_stylekit-sub.scss @@ -77,6 +77,12 @@ button.sk-button { border: none; } -a { +a, .sk-a { + background: none; + border: none; color: var(--sn-stylekit-info-color); } + +button.sk-a { + min-height: 24px; +} diff --git a/app/assets/stylesheets/index.css.scss b/app/assets/stylesheets/index.css.scss index 89b23f1f6..52ca8b997 100644 --- a/app/assets/stylesheets/index.css.scss +++ b/app/assets/stylesheets/index.css.scss @@ -9,3 +9,5 @@ @import "lock-screen"; @import "stylekit-sub"; @import "ionicons"; +@import "reach-sub"; +@import "sessions-modal"; diff --git a/app/assets/templates/directives/account-menu.pug b/app/assets/templates/directives/account-menu.pug index c521a899c..d58739d7c 100644 --- a/app/assets/templates/directives/account-menu.pug +++ b/app/assets/templates/directives/account-menu.pug @@ -161,9 +161,12 @@ span(ng-if='self.state.syncPercentage') | ({{self.state.syncPercentage}}) .sk-panel-row + a.sk-a.info.sk-panel-row.condensed( + ng-click="self.openSessionsModal()" + ng-if="self.state.showSessions" + ) Review active sessions a.sk-a.info.sk-panel-row.condensed( ng-click="self.openPasswordWizard()" - ng-if="!self.state.showBetaWarning" ) Change Password a.sk-a.info.sk-panel-row.condensed( ng-click="self.openPrivilegesModal('')", diff --git a/package.json b/package.json index e613ed578..e26f58e9f 100644 --- a/package.json +++ b/package.json @@ -20,21 +20,20 @@ "tsc": "tsc --project app/assets/javascripts/tsconfig.json" }, "devDependencies": { - "@babel/core": "^7.12.9", - "@babel/plugin-proposal-class-properties": "^7.10.4", - "@babel/preset-env": "^7.12.7", + "@babel/core": "^7.12.10", + "@babel/plugin-transform-react-jsx": "^7.12.10", + "@babel/preset-env": "^7.12.10", "@babel/preset-typescript": "^7.12.7", - "@types/angular": "^1.7.0", + "@types/angular": "^1.8.0", "@types/chai": "^4.2.11", "@types/lodash": "^4.14.149", "@types/mocha": "^7.0.2", "@types/pug": "^2.0.4", "@typescript-eslint/eslint-plugin": "^2.23.0", "@typescript-eslint/parser": "^2.23.0", - "angular": "1.8.0", + "angular": "^1.8.2", "apply-loader": "^2.0.0", "babel-eslint": "^10.1.0", - "babel-loader": "^8.1.0", "babel-plugin-angularjs-annotate": "^0.10.0", "chai": "^4.2.0", "connect": "^3.7.0", @@ -57,8 +56,8 @@ "sass-loader": "^8.0.2", "serve-static": "^1.14.1", "sn-stylekit": "2.1.0", - "ts-loader": "^8.0.11", - "typescript": "^3.9.7", + "ts-loader": "^8.0.12", + "typescript": "^4.1.3", "typescript-eslint": "0.0.1-alpha.0", "webpack": "^4.44.1", "webpack-cli": "^3.3.12", @@ -67,8 +66,13 @@ }, "dependencies": { "@bugsnag/js": "^7.5.1", + "@reach/alert": "^0.12.1", + "@reach/alert-dialog": "^0.12.1", + "@reach/dialog": "^0.12.1", "@standardnotes/sncrypto-web": "^1.2.9", - "@standardnotes/snjs": "^2.0.20", - "mobx": "^6.0.1" + "@standardnotes/snjs": "^2.0.23", + "babel-loader": "^8.2.2", + "mobx": "^6.0.4", + "preact": "^10.5.7" } } diff --git a/webpack.config.js b/webpack.config.js index 46cb9738b..4fb2589cd 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -25,7 +25,7 @@ module.exports = ( }), ], resolve: { - extensions: ['.ts', '.js'], + extensions: ['.ts', '.tsx', '.js'], alias: { '%': path.resolve(__dirname, 'app/assets/templates'), '@': path.resolve(__dirname, 'app/assets/javascripts'), @@ -36,13 +36,16 @@ module.exports = ( '@Views': path.resolve(__dirname, 'app/assets/javascripts/views'), '@Services': path.resolve(__dirname, 'app/assets/javascripts/services'), '@node_modules': path.resolve(__dirname, 'node_modules'), + react: 'preact/compat', + 'react-dom/test-utils': 'preact/test-utils', + 'react-dom': 'preact/compat', }, }, module: { rules: [ { - test: /\.(js|ts)$/, - exclude: /(node_modules|snjs)/, + test: /\.(js|tsx?)$/, + exclude: /(node_modules)/, use: [ 'babel-loader', { diff --git a/yarn.lock b/yarn.lock index 4903c3a51..96c57bfe8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14,28 +14,36 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41" integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== -"@babel/core@^7.12.9": - version "7.12.9" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8" - integrity sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ== +"@babel/core@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd" + integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.5" + "@babel/generator" "^7.12.10" "@babel/helper-module-transforms" "^7.12.1" "@babel/helpers" "^7.12.5" - "@babel/parser" "^7.12.7" + "@babel/parser" "^7.12.10" "@babel/template" "^7.12.7" - "@babel/traverse" "^7.12.9" - "@babel/types" "^7.12.7" + "@babel/traverse" "^7.12.10" + "@babel/types" "^7.12.10" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" json5 "^2.1.2" lodash "^4.17.19" - resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" +"@babel/generator@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.10.tgz#2b188fc329fb8e4f762181703beffc0fe6df3460" + integrity sha512-6mCdfhWgmqLdtTkhXjnIz0LcdVCd26wS2JXRtj2XY0u5klDsXBREA/pG5NVOuVnF2LUrBGNFtQkIqqTbblg0ww== + dependencies: + "@babel/types" "^7.12.10" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/generator@^7.12.5": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.5.tgz#a2c50de5c8b6d708ab95be5e6053936c1884a4de" @@ -52,6 +60,13 @@ dependencies: "@babel/types" "^7.10.4" +"@babel/helper-annotate-as-pure@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz#54ab9b000e60a93644ce17b3f37d313aaf1d115d" + integrity sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ== + dependencies: + "@babel/types" "^7.12.10" + "@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" @@ -60,6 +75,23 @@ "@babel/helper-explode-assignable-expression" "^7.10.4" "@babel/types" "^7.10.4" +"@babel/helper-builder-react-jsx-experimental@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.12.10.tgz#a58cb96a793dc0fcd5c9ed3bb36d62fdc60534c2" + integrity sha512-3Kcr2LGpL7CTRDTTYm1bzeor9qZbxbvU2AxsLA6mUG9gYarSfIKMK0UlU+azLWI+s0+BH768bwyaziWB2NOJlQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.12.10" + "@babel/helper-module-imports" "^7.12.5" + "@babel/types" "^7.12.10" + +"@babel/helper-builder-react-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.4.tgz#8095cddbff858e6fa9c326daee54a2f2732c1d5d" + integrity sha512-5nPcIZ7+KKDxT1427oBivl9V9YTal7qk0diccnh7RrcgrT/pGFOjgGw1dgryyx1GvHEpXVfoDF6Ak3rTiWh8Rg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/helper-compilation-targets@^7.12.5": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" @@ -247,6 +279,11 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/parser@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.10.tgz#824600d59e96aea26a5a2af5a9d812af05c3ae81" + integrity sha512-PJdRPwyoOqFAWfLytxrWwGrAxghCgh/yTNCYciOz8QgjflA7aZhECPZAa2VUedKg2+QMWkI0L9lynh2SNmNEgA== + "@babel/parser@^7.12.7", "@babel/parser@^7.7.0": version "7.12.7" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.7.tgz#fee7b39fe809d0e73e5b25eecaf5780ef3d73056" @@ -261,7 +298,7 @@ "@babel/helper-remap-async-to-generator" "^7.12.1" "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/plugin-proposal-class-properties@^7.10.4", "@babel/plugin-proposal-class-properties@^7.12.1": +"@babel/plugin-proposal-class-properties@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz#a082ff541f2a29a4821065b8add9346c0c16e5de" integrity sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w== @@ -394,6 +431,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-jsx@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz#9d9d357cc818aa7ae7935917c1257f67677a0926" + integrity sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" @@ -634,6 +678,16 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-react-jsx@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.10.tgz#a7af3097c73479123594c8c8fe39545abebd44e3" + integrity sha512-MM7/BC8QdHXM7Qc1wdnuk73R4gbuOpfrSUgfV/nODGc86sPY1tgmY2M9E9uAnf2e4DOIp8aKGWqgZfQxnTNGuw== + dependencies: + "@babel/helper-builder-react-jsx" "^7.10.4" + "@babel/helper-builder-react-jsx-experimental" "^7.12.10" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.12.1" + "@babel/plugin-transform-regenerator@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz#5f0a28d842f6462281f06a964e88ba8d7ab49753" @@ -677,10 +731,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-typeof-symbol@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.1.tgz#9ca6be343d42512fbc2e68236a82ae64bc7af78a" - integrity sha512-EPGgpGy+O5Kg5pJFNDKuxt9RdmTgj5sgrus2XVeMp/ZIbOESadgILUbm50SNpghOh3/6yrbsH+NB5+WJTmsA7Q== +"@babel/plugin-transform-typeof-symbol@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz#de01c4c8f96580bd00f183072b0d0ecdcf0dec4b" + integrity sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -708,10 +762,10 @@ "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/preset-env@^7.12.7": - version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.7.tgz#54ea21dbe92caf6f10cb1a0a576adc4ebf094b55" - integrity sha512-OnNdfAr1FUQg7ksb7bmbKoby4qFOHw6DKWWUNB9KqnnCldxhxJlP+21dpyaWFmf2h0rTbOkXJtAGevY3XW1eew== +"@babel/preset-env@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.10.tgz#ca981b95f641f2610531bd71948656306905e6ab" + integrity sha512-Gz9hnBT/tGeTE2DBNDkD7BiWRELZt+8lSysHuDwmYXUIvtwZl0zI+D6mZgXZX0u8YBlLS4tmai9ONNY9tjRgRA== dependencies: "@babel/compat-data" "^7.12.7" "@babel/helper-compilation-targets" "^7.12.5" @@ -772,12 +826,12 @@ "@babel/plugin-transform-spread" "^7.12.1" "@babel/plugin-transform-sticky-regex" "^7.12.7" "@babel/plugin-transform-template-literals" "^7.12.1" - "@babel/plugin-transform-typeof-symbol" "^7.12.1" + "@babel/plugin-transform-typeof-symbol" "^7.12.10" "@babel/plugin-transform-unicode-escapes" "^7.12.1" "@babel/plugin-transform-unicode-regex" "^7.12.1" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.12.7" - core-js-compat "^3.7.0" + "@babel/types" "^7.12.10" + core-js-compat "^3.8.0" semver "^5.5.0" "@babel/preset-modules@^0.1.3": @@ -800,7 +854,7 @@ "@babel/helper-validator-option" "^7.12.1" "@babel/plugin-transform-typescript" "^7.12.1" -"@babel/runtime@^7.8.4": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.8.4": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== @@ -816,7 +870,7 @@ "@babel/parser" "^7.12.7" "@babel/types" "^7.12.7" -"@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5", "@babel/traverse@^7.12.9", "@babel/traverse@^7.7.0": +"@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5", "@babel/traverse@^7.7.0": version "7.12.9" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.9.tgz#fad26c972eabbc11350e0b695978de6cc8e8596f" integrity sha512-iX9ajqnLdoU1s1nHt36JDI9KG4k+vmI8WgjK5d+aDTwQbL2fUnzedNedssA645Ede3PM2ma1n8Q4h2ohwXgMXw== @@ -831,6 +885,21 @@ globals "^11.1.0" lodash "^4.17.19" +"@babel/traverse@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.10.tgz#2d1f4041e8bf42ea099e5b2dc48d6a594c00017a" + integrity sha512-6aEtf0IeRgbYWzta29lePeYSk+YAFIC3kyqESeft8o5CkFlYIMX+EQDDWEiAQ9LHOA3d0oHdgrSsID/CKqXJlg== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.10" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.12.10" + "@babel/types" "^7.12.10" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.2.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0": version "7.12.7" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.7.tgz#6039ff1e242640a29452c9ae572162ec9a8f5d13" @@ -840,6 +909,15 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@babel/types@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.10.tgz#7965e4a7260b26f09c56bcfcb0498af1f6d9b260" + integrity sha512-sf6wboJV5mGyip2hIpDSKsr80RszPinEFjsHTalMxZAZkoQ2/2yQzxlcFN52SJqsyPfLtPmenL4g2KB3KJXPDw== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@bugsnag/browser@^7.5.3": version "7.5.3" resolved "https://registry.yarnpkg.com/@bugsnag/browser/-/browser-7.5.3.tgz#a91e9fe74422f5866d4058a05cf6d6881e15c26d" @@ -888,6 +966,72 @@ resolved "https://registry.yarnpkg.com/@bugsnag/safe-json-stringify/-/safe-json-stringify-6.0.0.tgz#22abdcd83e008c369902976730c34c150148a758" integrity sha512-htzFO1Zc57S8kgdRK9mLcPVTW1BY2ijfH7Dk2CeZmspTWKdKqSo1iwmqrq2WtRjFlo8aRZYgLX0wFrDXF/9DLA== +"@reach/alert-dialog@^0.12.1": + version "0.12.1" + resolved "https://registry.yarnpkg.com/@reach/alert-dialog/-/alert-dialog-0.12.1.tgz#61f9bd20722761555aded777c80ec29b30c25040" + integrity sha512-LbgWXKOAnqjOvIrgcHYtQtbU93KY5Nom8OuHrMaR2wVQWtFyem/+OgPR0/cc6bvnLd6XiLDn4HFGIWDBf1Ca6w== + dependencies: + "@reach/auto-id" "0.12.1" + "@reach/dialog" "0.12.1" + "@reach/utils" "0.12.1" + invariant "^2.2.4" + prop-types "^15.7.2" + tslib "^2.0.0" + +"@reach/alert@^0.12.1": + version "0.12.1" + resolved "https://registry.yarnpkg.com/@reach/alert/-/alert-0.12.1.tgz#16b9493aaae3b41dbf945517d881bbbda0f79930" + integrity sha512-kIVsKgc4Vv3jFfzBEFdDmwWekMQaDfOhmJLAZczMMI/t4wqQjLANU6JVmRZsOF13/Wj2cMFNje/CIZU/VCVdsA== + dependencies: + "@reach/utils" "0.12.1" + "@reach/visually-hidden" "0.12.0" + prop-types "^15.7.2" + tslib "^2.0.0" + +"@reach/auto-id@0.12.1": + version "0.12.1" + resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.12.1.tgz#2e4a7250d2067ec16a9b4ea732695bc75572405c" + integrity sha512-s8cdY6dF0hEBB/28BbidB2EX6JfEBVIWLP6S2Jg0Xqq2H3xijL+zrsjL40jACwXRkignjuP+CvYsuFuO0+/GRA== + dependencies: + "@reach/utils" "0.12.1" + tslib "^2.0.0" + +"@reach/dialog@0.12.1", "@reach/dialog@^0.12.1": + version "0.12.1" + resolved "https://registry.yarnpkg.com/@reach/dialog/-/dialog-0.12.1.tgz#1fe67d7d09eccac57292a06a9388b5ef7d529d06" + integrity sha512-PBAzBXrChxeufhROhRuYkZmJhZeZVXGU6fa9/EVZs+Prsv40MgPdrSR6CBDAxLaYJfeZIbOwy7xoAawtlWlmpw== + dependencies: + "@reach/portal" "0.12.1" + "@reach/utils" "0.12.1" + prop-types "^15.7.2" + react-focus-lock "^2.3.1" + react-remove-scroll "^2.3.0" + tslib "^2.0.0" + +"@reach/portal@0.12.1": + version "0.12.1" + resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.12.1.tgz#995858a6e758d9446870937b60b8707a2efa11cb" + integrity sha512-Lhmtd2Qw1DzNZ2m0GHNzCu+2TYUf6kBREPSQJf44AP6kThRs02p1clntbJcmW/rrpYFYgFNbgf5Lso7NyW9ZXg== + dependencies: + "@reach/utils" "0.12.1" + tslib "^2.0.0" + +"@reach/utils@0.12.1": + version "0.12.1" + resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.12.1.tgz#02b9c15ba5cddf23e16f2d2ca77aef98a9702607" + integrity sha512-5uH4OgO+GupAzZuf3b6Wv/9uC6NdMBlxS6FSKD6YqSxP4QJ0vjD34RVon6N/RMRORacCLyD/aaZIA7283YgeOg== + dependencies: + "@types/warning" "^3.0.0" + tslib "^2.0.0" + warning "^4.0.3" + +"@reach/visually-hidden@0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@reach/visually-hidden/-/visually-hidden-0.12.0.tgz#c6c39f0bf292ae97a480ba3ed32e8a6149e852d4" + integrity sha512-VXtyR36WOS0FHmFQ/BzfswwPyBXICl/YjmTPtx/I0Vy5C6djjhD9kDsE+h/FpHzP3ugTdqdqiPBVElIZTSwOSA== + dependencies: + tslib "^2.0.0" + "@standardnotes/sncrypto-common@^1.2.7", "@standardnotes/sncrypto-common@^1.2.9": version "1.2.9" resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-common/-/sncrypto-common-1.2.9.tgz#5212a959e4ec563584e42480bfd39ef129c3cbdf" @@ -901,14 +1045,14 @@ "@standardnotes/sncrypto-common" "^1.2.7" libsodium-wrappers "^0.7.8" -"@standardnotes/snjs@^2.0.20": - version "2.0.20" - resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.20.tgz#46e265ac35826f74d669f7d2c97ae307e5fbf7c0" - integrity sha512-H38QYxJPXmYrH+QBZdkIGzZxUAHPlqC0geMx6hc2Z8kVVu4lIGaYE4mfBhp5KjRgSVcRQxNFnx5SKqgitRLUpg== +"@standardnotes/snjs@^2.0.23": + version "2.0.23" + resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.23.tgz#0eccabd196b867b36132c20df50090ffc8c7b80f" + integrity sha512-2hHHh66SvblqSihjBwqqcsM9hXHQS1DVn3MY6tOXpzxNJ7Jruyp+QqgR4yQkVuA0AC+LkZtzd61g2kFN+wV6AQ== dependencies: "@standardnotes/sncrypto-common" "^1.2.9" -"@types/angular@^1.7.0": +"@types/angular@^1.8.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@types/angular/-/angular-1.8.0.tgz#6bce6f21d69f9dfa45e3e3dd76f723496b12c32c" integrity sha512-tF4Ulq9GC54wKboxfvt91tkfJNGcFWEfkuptX5HCNVt4emwJQqWloCpUzepyKLjpKSIEOZaxupb/GX2ESwz3wQ== @@ -1005,6 +1149,11 @@ dependencies: source-map "^0.6.1" +"@types/warning@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52" + integrity sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI= + "@types/webpack-sources@*": version "2.1.0" resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-2.1.0.tgz#8882b0bd62d1e0ce62f183d0d01b72e6e82e8c10" @@ -1303,10 +1452,10 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= -angular@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/angular/-/angular-1.8.0.tgz#b1ec179887869215cab6dfd0df2e42caa65b1b51" - integrity sha512-VdaMx+Qk0Skla7B5gw77a8hzlcOakwF8mjlW13DpIWIDlfqwAbSSLfd8N/qZnzEmQF4jC4iofInd3gE7vL8ZZg== +angular@^1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/angular/-/angular-1.8.2.tgz#5983bbb5a9fa63e213cb7749199e0d352de3a2f1" + integrity sha512-IauMOej2xEe7/7Ennahkbb5qd/HFADiNuLSESz9Q27inmi32zB0lnAsFeLEWcox3Gd1F6YhNd1CP7/9IukJ0Gw== ansi-colors@3.2.3: version "3.2.3" @@ -1583,7 +1732,7 @@ babel-eslint@^10.1.0: eslint-visitor-keys "^1.0.0" resolve "^1.12.0" -babel-loader@^8.1.0: +babel-loader@^8.2.2: version "8.2.2" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.2.tgz#9363ce84c10c9a40e6c753748e1441b60c8a0b81" integrity sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g== @@ -2394,7 +2543,7 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-js-compat@^3.7.0: +core-js-compat@^3.8.0: version "3.8.1" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.8.1.tgz#8d1ddd341d660ba6194cbe0ce60f4c794c87a36e" integrity sha512-a16TLmy9NVD1rkjUGbwuyWkiDoN0FDpAwrfLONvHFQx0D9k7J9y0srwMT8QP/Z6HE3MIFaVynEeYwZwPX1o5RQ== @@ -2682,6 +2831,11 @@ detect-file@^1.0.0: resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= +detect-node-es@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.0.0.tgz#c0318b9e539a5256ca780dd9575c9345af05b8ed" + integrity sha512-S4AHriUkTX9FoFvL4G8hXDcx6t3gp2HpfCza3Q0v6S78gul2hKWifLQbeW+ZF89+hSm2ZIc/uF3J97ZgytgTRg== + detect-node@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" @@ -2981,16 +3135,6 @@ eslint-config-prettier@^6.10.0: dependencies: get-stdin "^6.0.0" -eslint-config-semistandard@^15.0.0: - version "15.0.1" - resolved "https://registry.yarnpkg.com/eslint-config-semistandard/-/eslint-config-semistandard-15.0.1.tgz#a868397af8fb26d1bb6b907aa9d575d385581099" - integrity sha512-sfV+qNBWKOmF0kZJll1VH5XqOAdTmLlhbOl9WKI11d2eMEe+Kicxnpm24PQWHOqAfk5pAWU2An0LjNCXKa4Usg== - -eslint-config-standard@^14.1.0: - version "14.1.1" - resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz#830a8e44e7aef7de67464979ad06b406026c56ea" - integrity sha512-Z9B+VR+JIXRxz21udPTL9HpFMyoMUEeX1G251EQ6e05WD9aPVtVBn09XUmZ259wCMlCDmYDSZG62Hhm+ZTJcUg== - eslint-import-resolver-node@^0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" @@ -3492,6 +3636,13 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" +focus-lock@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.8.1.tgz#bb36968abf77a2063fa173cb6c47b12ac8599d33" + integrity sha512-/LFZOIo82WDsyyv7h7oc0MJF9ACOvDRdx9rWPZ2pgMfNWu/z8hQDBtOchuB/0BVLmuFOZjV02YwUVzNsWx/EzA== + dependencies: + tslib "^1.9.3" + follow-redirects@^1.0.0: version "1.13.0" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" @@ -3634,6 +3785,11 @@ get-intrinsic@^1.0.0, get-intrinsic@^1.0.1: has "^1.0.3" has-symbols "^1.0.1" +get-nonce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" + integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== + get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" @@ -4181,6 +4337,13 @@ interpret@^1.4.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" @@ -4500,7 +4663,7 @@ js-stringify@^1.0.1: resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" integrity sha1-Fzb939lyTyijaCrcYjCufk6Weds= -js-tokens@^4.0.0: +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== @@ -4732,6 +4895,13 @@ longest@^1.0.1: resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= +loose-envify@^1.0.0, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + loud-rejection@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" @@ -4992,7 +5162,7 @@ mkdirp@0.5.5, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkd dependencies: minimist "^1.2.5" -mobx@^6.0.1: +mobx@^6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.0.4.tgz#8fc3e3629a3346f8afddf5bd954411974744dad1" integrity sha512-wT2QJT9tW19VSHo9x7RPKU3z/I2Ps6wUS8Kb1OO+kzmg7UY3n4AkcaYG6jq95Lp1R9ohjC/NGYuT2PtuvBjhFg== @@ -5812,6 +5982,11 @@ postcss@^7.0.14, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: source-map "^0.6.1" supports-color "^6.1.0" +preact@^10.5.7: + version "10.5.7" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.5.7.tgz#f1d84725539e18f7ccbea937cf3db5895661dbd3" + integrity sha512-4oEpz75t/0UNcwmcsjk+BIcDdk68oao+7kxcpc1hQPNs2Oo3ZL9xFz8UBf350mxk/VEdD41L5b4l2dE3Ug3RYg== + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -5857,6 +6032,15 @@ promise@^7.0.1: dependencies: asap "~2.0.3" +prop-types@^15.6.2, prop-types@^15.7.2: + version "15.7.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" + integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.8.1" + proxy-addr@~2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" @@ -6109,6 +6293,58 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +react-clientside-effect@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.2.tgz#6212fb0e07b204e714581dd51992603d1accc837" + integrity sha512-nRmoyxeok5PBO6ytPvSjKp9xwXg9xagoTK1mMjwnQxqM9Hd7MNPl+LS1bOSOe+CV2+4fnEquc7H/S8QD3q697A== + dependencies: + "@babel/runtime" "^7.0.0" + +react-focus-lock@^2.3.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.5.0.tgz#12e3a3940e897c26e2c2a0408cd25ea3c99b3709" + integrity sha512-XLxj6uTXgz0US8TmqNU2jMfnXwZG0mH2r/afQqvPEaX6nyEll5LHVcEXk2XDUQ34RVeLPkO/xK5x6c/qiuSq/A== + dependencies: + "@babel/runtime" "^7.0.0" + focus-lock "^0.8.1" + prop-types "^15.6.2" + react-clientside-effect "^1.2.2" + use-callback-ref "^1.2.1" + use-sidecar "^1.0.1" + +react-is@^16.8.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-remove-scroll-bar@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.1.1.tgz#5876428dfd546f2f63a4d277aea2197925505c1e" + integrity sha512-IZbfQPSozIr8ylHE9MFcQeb2TTzj4abfE7OBXjmtUeXQ5h6ColGKDNo5h7OmzrJRilAx3YIKBf3jb0yrb31BJQ== + dependencies: + react-style-singleton "^2.1.0" + tslib "^1.0.0" + +react-remove-scroll@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.4.1.tgz#e0af6126621083a5064591d367291a81b2d107f5" + integrity sha512-K7XZySEzOHMTq7dDwcHsZA6Y7/1uX5RsWhRXVYv8rdh+y9Qz2nMwl9RX/Mwnj/j7JstCGmxyfyC0zbVGXYh3mA== + dependencies: + react-remove-scroll-bar "^2.1.0" + react-style-singleton "^2.1.0" + tslib "^1.0.0" + use-callback-ref "^1.2.3" + use-sidecar "^1.0.1" + +react-style-singleton@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.1.1.tgz#ce7f90b67618be2b6b94902a30aaea152ce52e66" + integrity sha512-jNRp07Jza6CBqdRKNgGhT3u9umWvils1xsuMOjZlghBDH2MU0PL2WZor4PGYjXpnRCa9DQSlHMs/xnABWOwYbA== + dependencies: + get-nonce "^1.0.0" + invariant "^2.2.4" + tslib "^1.0.0" + read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -6384,7 +6620,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.3.2: +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0: version "1.19.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== @@ -7279,10 +7515,10 @@ trim-newlines@^1.0.0: dependencies: glob "^7.1.2" -ts-loader@^8.0.11: - version "8.0.11" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.11.tgz#35d58a65932caacb120426eea59eca841786c899" - integrity sha512-06X+mWA2JXoXJHYAesUUL4mHFYhnmyoCdQVMXofXF552Lzd4wNwSGg7unJpttqUP7ziaruM8d7u8LUB6I1sgzA== +ts-loader@^8.0.12: + version "8.0.12" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.12.tgz#1de9f1de65176318c1e6d187bfc496182f8dc2a0" + integrity sha512-UIivVfGVJDdwwjgSrbtcL9Nf10c1BWnL1mxAQUVcnhNIn/P9W3nP5v60Z0aBMtc7ZrE11lMmU6+5jSgAXmGaYw== dependencies: chalk "^2.3.0" enhanced-resolve "^4.0.0" @@ -7300,12 +7536,12 @@ tsconfig-paths@^3.9.0: minimist "^1.2.0" strip-bom "^3.0.0" -tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.0.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.3: +tslib@^2.0.0, tslib@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c" integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ== @@ -7374,10 +7610,10 @@ typescript-eslint@0.0.1-alpha.0: resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-0.0.1-alpha.0.tgz#285d68a4e96588295cd436278801bcb6a6b916c1" integrity sha512-1hNKM37dAWML/2ltRXupOq2uqcdRQyDFphl+341NTPXFLLLiDhErXx8VtaSLh3xP7SyHZdcCgpt9boYYVb3fQg== -typescript@^3.9.7: - version "3.9.7" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" - integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== +typescript@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" + integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== uglify-js@3.4.x: version "3.4.10" @@ -7505,6 +7741,19 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" +use-callback-ref@^1.2.1, use-callback-ref@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.2.4.tgz#d86d1577bfd0b955b6e04aaf5971025f406bea3c" + integrity sha512-rXpsyvOnqdScyied4Uglsp14qzag1JIemLeTWGKbwpotWht57hbP78aNT+Q4wdFKQfQibbUX4fb6Qb4y11aVOQ== + +use-sidecar@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.0.3.tgz#17a4e567d4830c0c0ee100040e85a7fe68611e0f" + integrity sha512-ygJwGUBeQfWgDls7uTrlEDzJUUR67L8Rm14v/KfFtYCdHhtjHZx1Krb3DIQl3/Q5dJGfXLEQ02RY8BdNBv87SQ== + dependencies: + detect-node-es "^1.0.0" + tslib "^1.9.3" + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" @@ -7589,6 +7838,13 @@ void-elements@^2.0.1: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= +warning@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" + integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== + dependencies: + loose-envify "^1.0.0" + watchpack-chokidar2@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957"