From 12c44565ff82917a4c6fd1d334c74f8c4b8bcd64 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Wed, 16 Jun 2021 18:02:06 -0600 Subject: [PATCH] update bootstrapper and startup flow --- ui/package-lock.json | 34 +++++++++-- ui/package.json | 2 +- ui/src/app/app.component.html | 7 ++- ui/src/app/app.component.ts | 2 +- .../patch-db/local-storage-bootstrap.ts | 16 ++++-- .../models/patch-db/patch-db-model.factory.ts | 4 +- ui/src/app/models/patch-db/patch-db-model.ts | 8 ++- .../app-installed-list.page.html | 3 +- ui/src/app/services/api/mock-api.service.ts | 57 ++++++++++--------- ui/src/app/services/auth.service.ts | 14 +---- ui/src/app/services/http.service.ts | 47 ++++++++------- ui/ui-config.json | 4 +- 12 files changed, 114 insertions(+), 84 deletions(-) diff --git a/ui/package-lock.json b/ui/package-lock.json index fe206b2c0..251f9c866 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -27,7 +27,7 @@ "json-pointer": "^0.6.1", "jsonpointerx": "^1.0.30", "marked": "^2.0.0", - "patch-db-client": "file: ../../../../patch-db-client", + "patch-db-client": "file: ../../../../patch-db/client", "rxjs": "^6.6.0", "uuid": "^8.3.0", "zone.js": "^0.11.2" @@ -50,7 +50,23 @@ "typescript": "4.1.5" } }, - "../../patch-db-client": {}, + "../../patch-db/client": { + "name": "patch-db", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "rxjs": "^6.6.3", + "sorted-btree": "^1.5.0", + "uuid": "^8.3.2" + }, + "devDependencies": { + "@types/node": "^15.0.0", + "@types/uuid": "^8.3.0", + "ts-node": "^9.1.1", + "tslint": "^6.1.0", + "typescript": "4.1.5" + } + }, "node_modules/@angular-devkit/architect": { "version": "0.1102.14", "dev": true, @@ -9816,7 +9832,7 @@ } }, "node_modules/patch-db-client": { - "resolved": "../../patch-db-client", + "resolved": "../../patch-db/client", "link": true }, "node_modules/path-browserify": { @@ -22163,7 +22179,17 @@ "dev": true }, "patch-db-client": { - "version": "file:../../patch-db-client" + "version": "file:../../patch-db/client", + "requires": { + "@types/node": "^15.0.0", + "@types/uuid": "^8.3.0", + "rxjs": "^6.6.3", + "sorted-btree": "^1.5.0", + "ts-node": "^9.1.1", + "tslint": "^6.1.0", + "typescript": "4.1.5", + "uuid": "^8.3.2" + } }, "path-browserify": { "version": "0.0.1", diff --git a/ui/package.json b/ui/package.json index 5ffa09059..e4583c943 100644 --- a/ui/package.json +++ b/ui/package.json @@ -34,7 +34,7 @@ "json-pointer": "^0.6.1", "jsonpointerx": "^1.0.30", "marked": "^2.0.0", - "patch-db-client": "file: ../../../../patch-db-client", + "patch-db-client": "file: ../../../../patch-db/client", "rxjs": "^6.6.0", "uuid": "^8.3.0", "zone.js": "^0.11.2" diff --git a/ui/src/app/app.component.html b/ui/src/app/app.component.html index 8c5d2463b..5eee4fa14 100644 --- a/ui/src/app/app.component.html +++ b/ui/src/app/app.component.html @@ -1,5 +1,8 @@ - - + + + + + diff --git a/ui/src/app/app.component.ts b/ui/src/app/app.component.ts index 418d0e6f0..83d1dd8a7 100644 --- a/ui/src/app/app.component.ts +++ b/ui/src/app/app.component.ts @@ -68,9 +68,9 @@ export class AppComponent { async init () { await this.storage.create() - await this.patch.init() await this.authService.init() await this.emver.init() + await this.patch.init() this.router.initialNavigation() diff --git a/ui/src/app/models/patch-db/local-storage-bootstrap.ts b/ui/src/app/models/patch-db/local-storage-bootstrap.ts index 24880030d..8f0f4ac40 100644 --- a/ui/src/app/models/patch-db/local-storage-bootstrap.ts +++ b/ui/src/app/models/patch-db/local-storage-bootstrap.ts @@ -2,6 +2,7 @@ import { Bootstrapper, DBCache } from 'patch-db-client' import { DataModel } from './data-model' import { Injectable } from '@angular/core' import { Storage } from '@ionic/storage' +import { ApiService } from 'src/app/services/api/api.service' @Injectable({ providedIn: 'root', @@ -11,19 +12,22 @@ export class LocalStorageBootstrap implements Bootstrapper { constructor ( private readonly storage: Storage, + private readonly apiService: ApiService, ) { } async init (): Promise> { - const cache = await this.storage.get(LocalStorageBootstrap.CONTENT_KEY) - if (!cache) return { sequence: 0, data: { } as DataModel } + let cache = await this.storage.get(LocalStorageBootstrap.CONTENT_KEY) as DBCache + if (!cache || cache.sequence === 0) { + console.log('No cached data, getting dump from server') + const { id, value } = await this.apiService.getDump() + cache.sequence = id + cache.data = value + await this.update(cache) + } return cache } async update (cache: DBCache): Promise { return this.storage.set(LocalStorageBootstrap.CONTENT_KEY, cache) } - - async clear (): Promise { - return this.storage.remove(LocalStorageBootstrap.CONTENT_KEY) - } } diff --git a/ui/src/app/models/patch-db/patch-db-model.factory.ts b/ui/src/app/models/patch-db/patch-db-model.factory.ts index ae626e926..c24a166f4 100644 --- a/ui/src/app/models/patch-db/patch-db-model.factory.ts +++ b/ui/src/app/models/patch-db/patch-db-model.factory.ts @@ -11,7 +11,7 @@ export function PatchDbModelFactory ( http: ApiService, ): PatchDbModel { - const { mocks, patchDb: { poll, timeoutForMissingRevision }, isConsulate, isLan } = config + const { mocks, patchDb: { poll, timeoutForMissingRevision }, isConsulate } = config let source: Source @@ -19,7 +19,7 @@ export function PatchDbModelFactory ( if (mocks.connection === 'poll') { source = new PollSource({ ...poll }, http) } else { - source = new WebsocketSource('ws://localhost:8081') + source = new WebsocketSource(`ws://localhost:${config.mocks.wsPort}/db`) } } else { if (isConsulate) { diff --git a/ui/src/app/models/patch-db/patch-db-model.ts b/ui/src/app/models/patch-db/patch-db-model.ts index c477e5e3d..f94967f07 100644 --- a/ui/src/app/models/patch-db/patch-db-model.ts +++ b/ui/src/app/models/patch-db/patch-db-model.ts @@ -20,8 +20,12 @@ export class PatchDbModel { async init (): Promise { if (this.patchDb) return console.warn('Cannot re-init patchDbModel') - this.patchDb = await PatchDB.init(this.conf) - this.initialized = true + try { + this.patchDb = await PatchDB.init(this.conf) + this.initialized = true + } catch (e) { + console.log('Failed to initialize PatchDB', e) + } } start (): void { diff --git a/ui/src/app/pages/apps-routes/app-installed-list/app-installed-list.page.html b/ui/src/app/pages/apps-routes/app-installed-list/app-installed-list.page.html index 3ba67e552..5ff999afc 100644 --- a/ui/src/app/pages/apps-routes/app-installed-list/app-installed-list.page.html +++ b/ui/src/app/pages/apps-routes/app-installed-list/app-installed-list.page.html @@ -32,12 +32,13 @@ - + icon +

{{ (pkg.value | manifest).title }}

diff --git a/ui/src/app/services/api/mock-api.service.ts b/ui/src/app/services/api/mock-api.service.ts index 0cfb47d7f..4c3e788c6 100644 --- a/ui/src/app/services/api/mock-api.service.ts +++ b/ui/src/app/services/api/mock-api.service.ts @@ -8,6 +8,7 @@ import { RR } from './api-types' import { parsePropertiesPermissive } from 'src/app/util/properties.util' import { Mock } from './mock-app-fixures' import { HttpService } from '../http.service' +import { ConfigService } from '../config.service' @Injectable() export class MockApiService extends ApiService { @@ -36,40 +37,40 @@ export class MockApiService extends ApiService { // db async getRevisions (since: number): Promise { - await pauseFor(2000) - return { - ...Mock.DbDump, - id: this.nextSequence(), - } - // return this.http.rpcRequest({ method: 'db.revisions', params: { since } }) + // await pauseFor(2000) + // return { + // ...Mock.DbDump, + // id: this.nextSequence(), + // } + return this.http.rpcRequest({ method: 'db.revisions', params: { since } }) } async getDump (): Promise { - await pauseFor(2000) - return { - ...Mock.DbDump, - id: this.nextSequence(), - } - // return this.http.rpcRequest({ method: 'db.dump' }) + // await pauseFor(2000) + // return { + // ...Mock.DbDump, + // id: this.nextSequence(), + // } + return this.http.rpcRequest({ method: 'db.dump' }) } async setDbValueRaw (params: RR.SetDBValueReq): Promise { - await pauseFor(2000) - return { - response: null, - revision: { - id: this.nextSequence(), - patch: [ - { - op: PatchOp.REPLACE, - path: params.pointer, - value: params.value, - }, - ], - expireId: null, - }, - } - // return this.http.rpcRequest({ method: 'db.put.ui', params }) + // await pauseFor(2000) + // return { + // response: null, + // revision: { + // id: this.nextSequence(), + // patch: [ + // { + // op: PatchOp.REPLACE, + // path: params.pointer, + // value: params.value, + // }, + // ], + // expireId: null, + // }, + // } + return this.http.rpcRequest({ method: 'db.put.ui', params }) } // auth diff --git a/ui/src/app/services/auth.service.ts b/ui/src/app/services/auth.service.ts index 188defbb9..a13cfb9b2 100644 --- a/ui/src/app/services/auth.service.ts +++ b/ui/src/app/services/auth.service.ts @@ -19,19 +19,11 @@ export class AuthService { constructor ( private readonly api: ApiService, private readonly storage: Storage, - ) { - this.storage.create() - } + ) { } - async init (): Promise { + async init (): Promise { const loggedIn = await this.storage.get(StorageKeys.LOGGED_IN_KEY) - if (loggedIn) { - this.authState$.next(AuthState.VERIFIED) - return AuthState.VERIFIED - } else { - this.authState$.next(AuthState.UNVERIFIED) - return AuthState.UNVERIFIED - } + this.authState$.next( loggedIn ? AuthState.VERIFIED : AuthState.UNVERIFIED) } watch$ (): Observable { diff --git a/ui/src/app/services/http.service.ts b/ui/src/app/services/http.service.ts index 50365766a..fedde0893 100644 --- a/ui/src/app/services/http.service.ts +++ b/ui/src/app/services/http.service.ts @@ -11,14 +11,15 @@ import { Revision } from 'patch-db-client' export class HttpService { private unauthorizedApiResponse$ = new Subject() authReqEnabled: boolean = false - rootUrl: string + fullUrl: string constructor ( private readonly http: HttpClient, private readonly config: ConfigService, ) { const { url, version } = this.config.api - this.rootUrl = `${url}/${version}` + const port = config.mocks.enabled ? this.config.mocks.rpcPort : window.location.port + this.fullUrl = `${window.location.protocol}//${window.location.hostname}:${port}/${url}/${version}` } watch401$ (): Observable<{ }> { @@ -41,16 +42,14 @@ export class HttpService { } async httpRequest (httpOpts: HttpOptions): Promise { - let { url, body, timeout, ...rest} = translateOptions(httpOpts) - url = this.rootUrl + url - + let { body, timeout, ...rest} = this.translateOptions(httpOpts) let req: Observable<{ body: T }> switch (httpOpts.method){ - case Method.GET: req = this.http.get(url, rest) as any; break - case Method.POST: req = this.http.post(url, body, rest) as any; break - case Method.PUT: req = this.http.put(url, body, rest) as any; break - case Method.PATCH: req = this.http.patch(url, body, rest) as any; break - case Method.DELETE: req = this.http.delete(url, rest) as any; break + case Method.GET: req = this.http.get(this.fullUrl, rest) as any; break + case Method.POST: req = this.http.post(this.fullUrl, body, rest) as any; break + case Method.PUT: req = this.http.put(this.fullUrl, body, rest) as any; break + case Method.PATCH: req = this.http.patch(this.fullUrl, body, rest) as any; break + case Method.DELETE: req = this.http.delete(this.fullUrl, rest) as any; break } return (timeout ? withTimeout(req, timeout) : req) @@ -58,6 +57,20 @@ export class HttpService { .then(res => res.body) .catch(e => { throw new HttpError(e) }) } + + translateOptions (httpOpts: HttpOptions): HttpJsonOptions { + return { + observe: 'events', + responseType: 'json', + reportProgress: false, + withCredentials: this.config.mocks.enabled ? false : true, + headers: httpOpts.headers, + params: httpOpts.params, + body: httpOpts.data || { }, + url: httpOpts.url, + timeout: httpOpts.readTimeout, + } + } } function RpcError (e: RPCError['error']): void { @@ -167,20 +180,6 @@ export interface HttpJsonOptions { timeout: number } -function translateOptions (httpOpts: HttpOptions): HttpJsonOptions { - return { - observe: 'events', - responseType: 'json', - reportProgress: false, - withCredentials: true, - headers: httpOpts.headers, - params: httpOpts.params, - body: httpOpts.data || { }, - url: httpOpts.url, - timeout: httpOpts.readTimeout, - } -} - function withTimeout (req: Observable, timeout: number): Observable { return race( from(req.toPromise()), // this guarantees it only emits on completion, intermediary emissions are suppressed. diff --git a/ui/ui-config.json b/ui/ui-config.json index afee30e0f..ceab7143b 100644 --- a/ui/ui-config.json +++ b/ui/ui-config.json @@ -2,11 +2,11 @@ "patchDb": { "timeoutForMissingRevision": 5000, "poll": { - "cooldown": 40000 + "cooldown": 10000 } }, "api": { - "url": "/rpc", + "url": "rpc", "version": "v1" }, "mocks": {