mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
prep for live mocks
This commit is contained in:
committed by
Aiden McClelland
parent
8b84bdefac
commit
53a16775fe
@@ -11,13 +11,24 @@ export function PatchDbModelFactory (
|
|||||||
http: ApiService,
|
http: ApiService,
|
||||||
): PatchDbModel {
|
): PatchDbModel {
|
||||||
|
|
||||||
const { patchDb: { usePollOverride, poll, websocket, timeoutForMissingRevision }, isConsulate } = config
|
const { mocks, patchDb: { poll, timeoutForMissingRevision }, isConsulate, isLan } = config
|
||||||
|
|
||||||
let source: Source<DataModel>
|
let source: Source<DataModel>
|
||||||
if (isConsulate || usePollOverride) {
|
|
||||||
source = new PollSource({ ...poll }, http)
|
if (mocks.enabled) {
|
||||||
|
if (mocks.connection === 'poll') {
|
||||||
|
source = new PollSource({ ...poll }, http)
|
||||||
|
} else {
|
||||||
|
source = new WebsocketSource('ws://localhost:8081')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
source = new WebsocketSource({ ...websocket })
|
if (isConsulate) {
|
||||||
|
source = new PollSource({ ...poll }, http)
|
||||||
|
} else {
|
||||||
|
const protocol = window.location.protocol === 'http:' ? 'ws' : 'wss'
|
||||||
|
const host = window.location.host
|
||||||
|
source = new WebsocketSource(`${protocol}://${host}/ws/db`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new PatchDbModel({ sources: [source, http], bootstrapper, http, timeoutForMissingRevision })
|
return new PatchDbModel({ sources: [source, http], bootstrapper, http, timeoutForMissingRevision })
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export class LoginPage {
|
|||||||
async submit () {
|
async submit () {
|
||||||
try {
|
try {
|
||||||
await this.loader.displayDuringP(
|
await this.loader.displayDuringP(
|
||||||
this.authService.submitPassword(this.password),
|
this.authService.login(this.password),
|
||||||
)
|
)
|
||||||
this.password = ''
|
this.password = ''
|
||||||
await this.navCtrl.navigateForward(['/'])
|
await this.navCtrl.navigateForward(['/'])
|
||||||
|
|||||||
@@ -16,11 +16,8 @@ export module RR {
|
|||||||
|
|
||||||
// auth
|
// auth
|
||||||
|
|
||||||
export type SubmitPinReq = { pin: string } // auth.pin - unauthed
|
export type LoginReq = { password: string } // auth.login - unauthed
|
||||||
export type SubmitPinRes = null
|
export type loginRes = null
|
||||||
|
|
||||||
export type SubmitPasswordReq = { password: string } // auth.password - unauthed
|
|
||||||
export type SubmitPasswordRes = null
|
|
||||||
|
|
||||||
export type LogoutReq = { } // auth.logout
|
export type LogoutReq = { } // auth.logout
|
||||||
export type LogoutRes = null
|
export type LogoutRes = null
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import { LiveApiService } from './live-api.service'
|
|||||||
import { ConfigService } from '../config.service'
|
import { ConfigService } from '../config.service'
|
||||||
|
|
||||||
export function ApiServiceFactory (config: ConfigService, http: HttpService) {
|
export function ApiServiceFactory (config: ConfigService, http: HttpService) {
|
||||||
if (config.api.mocks) {
|
if (config.mocks.enabled) {
|
||||||
return new MockApiService(config)
|
return new MockApiService(http)
|
||||||
} else {
|
} else {
|
||||||
return new LiveApiService(http, config)
|
return new LiveApiService(http)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export abstract class ApiService implements Source<DataModel>, Http<DataModel> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// used for determining internet connectivity
|
// used for determining internet connectivity
|
||||||
abstract ping (): Promise<void>
|
abstract echo (): Promise<string>
|
||||||
|
|
||||||
// for getting static files: ex icons, instructions, licenses
|
// for getting static files: ex icons, instructions, licenses
|
||||||
abstract getStatic (url: string): Promise<string>
|
abstract getStatic (url: string): Promise<string>
|
||||||
@@ -34,9 +34,7 @@ export abstract class ApiService implements Source<DataModel>, Http<DataModel> {
|
|||||||
|
|
||||||
// auth
|
// auth
|
||||||
|
|
||||||
abstract submitPin (params: RR.SubmitPinReq): Promise<RR.SubmitPinRes>
|
abstract login (params: RR.LoginReq): Promise<RR.loginRes>
|
||||||
|
|
||||||
abstract submitPassword (params: RR.SubmitPasswordReq): Promise<RR.SubmitPasswordReq>
|
|
||||||
|
|
||||||
abstract logout (params: RR.LogoutReq): Promise<RR.LogoutRes>
|
abstract logout (params: RR.LogoutReq): Promise<RR.LogoutRes>
|
||||||
|
|
||||||
|
|||||||
@@ -3,17 +3,15 @@ import { HttpService, Method } from '../http.service'
|
|||||||
import { ApiService } from './api.service'
|
import { ApiService } from './api.service'
|
||||||
import { RR } from './api-types'
|
import { RR } from './api-types'
|
||||||
import { parsePropertiesPermissive } from 'src/app/util/properties.util'
|
import { parsePropertiesPermissive } from 'src/app/util/properties.util'
|
||||||
import { ConfigService } from '../config.service'
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LiveApiService extends ApiService {
|
export class LiveApiService extends ApiService {
|
||||||
constructor (
|
constructor (
|
||||||
private readonly http: HttpService,
|
private readonly http: HttpService,
|
||||||
private readonly config: ConfigService,
|
|
||||||
) { super() }
|
) { super() }
|
||||||
|
|
||||||
async ping (): Promise<void> {
|
async echo (): Promise<string> {
|
||||||
return this.http.rpcRequest({ method: 'ping', params: { } })
|
return this.http.rpcRequest({ method: 'echo', params: { } })
|
||||||
}
|
}
|
||||||
|
|
||||||
async getStatic (url: string): Promise<string> {
|
async getStatic (url: string): Promise<string> {
|
||||||
@@ -36,12 +34,8 @@ export class LiveApiService extends ApiService {
|
|||||||
|
|
||||||
// auth
|
// auth
|
||||||
|
|
||||||
async submitPin (params: RR.SubmitPinReq): Promise<RR.SubmitPinRes> {
|
async login (params: RR.LoginReq): Promise<RR.loginRes> {
|
||||||
return this.http.rpcRequest({ method: 'auth.pin', params })
|
return this.http.rpcRequest({ method: 'auth.login', params })
|
||||||
}
|
|
||||||
|
|
||||||
async submitPassword (params: RR.SubmitPasswordReq): Promise<RR.SubmitPasswordRes> {
|
|
||||||
return this.http.rpcRequest({ method: 'auth.password', params })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async logout (params: RR.LogoutReq): Promise<RR.LogoutRes> {
|
async logout (params: RR.LogoutReq): Promise<RR.LogoutRes> {
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import { ApiService } from './api.service'
|
|||||||
import { Observable } from 'rxjs'
|
import { Observable } from 'rxjs'
|
||||||
import { PatchOp, Update } from 'patch-db-client'
|
import { PatchOp, Update } from 'patch-db-client'
|
||||||
import { DataModel, PackageDataEntry, PackageMainStatus, PackageState, ServerStatus } from 'src/app/models/patch-db/data-model'
|
import { DataModel, PackageDataEntry, PackageMainStatus, PackageState, ServerStatus } from 'src/app/models/patch-db/data-model'
|
||||||
import { ConfigService } from '../config.service'
|
|
||||||
import { RR } from './api-types'
|
import { RR } from './api-types'
|
||||||
import { parsePropertiesPermissive } from 'src/app/util/properties.util'
|
import { parsePropertiesPermissive } from 'src/app/util/properties.util'
|
||||||
import { Mock } from './mock-app-fixures'
|
import { Mock } from './mock-app-fixures'
|
||||||
|
import { HttpService } from '../http.service'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MockApiService extends ApiService {
|
export class MockApiService extends ApiService {
|
||||||
@@ -15,7 +15,7 @@ export class MockApiService extends ApiService {
|
|||||||
welcomeAck = false
|
welcomeAck = false
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private readonly config: ConfigService,
|
private readonly http: HttpService,
|
||||||
) { super() }
|
) { super() }
|
||||||
|
|
||||||
// every time a patch is returned from the mock, we override its sequence to be 1 more than the last sequence in the patch-db as provided by `o`.
|
// every time a patch is returned from the mock, we override its sequence to be 1 more than the last sequence in the patch-db as provided by `o`.
|
||||||
@@ -24,9 +24,9 @@ export class MockApiService extends ApiService {
|
|||||||
return super.watch$()
|
return super.watch$()
|
||||||
}
|
}
|
||||||
|
|
||||||
async ping (): Promise<void> {
|
async echo (): Promise<string> {
|
||||||
console.log('pinging server')
|
console.log('echo...echo')
|
||||||
return
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
async getStatic (url: string): Promise<string> {
|
async getStatic (url: string): Promise<string> {
|
||||||
@@ -36,47 +36,20 @@ export class MockApiService extends ApiService {
|
|||||||
// db
|
// db
|
||||||
|
|
||||||
async getRevisions (since: number): Promise<RR.GetRevisionsRes> {
|
async getRevisions (since: number): Promise<RR.GetRevisionsRes> {
|
||||||
await pauseFor(2000)
|
return this.http.rpcRequest({ method: 'db.revisions', params: { since } })
|
||||||
return {
|
|
||||||
...Mock.DbDump,
|
|
||||||
id: this.nextSequence(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDump (): Promise<RR.GetDumpRes> {
|
async getDump (): Promise<RR.GetDumpRes> {
|
||||||
await pauseFor(2000)
|
return this.http.rpcRequest({ method: 'db.dump' })
|
||||||
return {
|
|
||||||
...Mock.DbDump,
|
|
||||||
id: this.nextSequence(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async setDbValueRaw (params: RR.SetDBValueReq): Promise<RR.SetDBValueRes> {
|
async setDbValueRaw (params: RR.SetDBValueReq): Promise<RR.SetDBValueRes> {
|
||||||
await pauseFor(2000)
|
return this.http.rpcRequest({ method: 'db.put.ui', params })
|
||||||
return {
|
|
||||||
response: null,
|
|
||||||
revision: {
|
|
||||||
id: this.nextSequence(),
|
|
||||||
patch: [
|
|
||||||
{
|
|
||||||
op: PatchOp.REPLACE,
|
|
||||||
path: params.pointer,
|
|
||||||
value: params.value,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
expireId: null,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// auth
|
// auth
|
||||||
|
|
||||||
async submitPin (params: RR.SubmitPinReq): Promise<RR.SubmitPinRes> {
|
async login (params: RR.LoginReq): Promise<RR.loginRes> {
|
||||||
await pauseFor(2000)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
async submitPassword (params: RR.SubmitPasswordReq): Promise<RR.SubmitPasswordRes> {
|
|
||||||
await pauseFor(2000)
|
await pauseFor(2000)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,12 +38,8 @@ export class AuthService {
|
|||||||
return this.authState$.pipe(distinctUntilChanged())
|
return this.authState$.pipe(distinctUntilChanged())
|
||||||
}
|
}
|
||||||
|
|
||||||
async submitPin (pin: string): Promise<void> {
|
async login (password: string): Promise<void> {
|
||||||
await this.api.submitPin({ pin })
|
await this.api.login({ password })
|
||||||
}
|
|
||||||
|
|
||||||
async submitPassword (password: string): Promise<void> {
|
|
||||||
await this.api.submitPassword({ password })
|
|
||||||
await this.storage.set(StorageKeys.LOGGED_IN_KEY, true)
|
await this.storage.set(StorageKeys.LOGGED_IN_KEY, true)
|
||||||
this.authState$.next(AuthState.VERIFIED)
|
this.authState$.next(AuthState.VERIFIED)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,28 @@
|
|||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { InstalledPackageDataEntry, InterfaceDef, Manifest, PackageDataEntry, PackageMainStatus, PackageState } from '../models/patch-db/data-model'
|
import { InstalledPackageDataEntry, InterfaceDef, Manifest, PackageDataEntry, PackageMainStatus, PackageState } from '../models/patch-db/data-model'
|
||||||
|
|
||||||
const { patchDb, maskAs, api, skipStartupAlerts } = require('../../../ui-config.json') as UiConfig
|
const { patchDb, api, mocks } = require('../../../ui-config.json') as UiConfig
|
||||||
|
|
||||||
type UiConfig = {
|
type UiConfig = {
|
||||||
patchDb: {
|
patchDb: {
|
||||||
// If this is false (the default), poll will be used if in consulate only. If true it will be on regardless of env. This is useful in concert with api mocks.
|
|
||||||
usePollOverride: boolean
|
|
||||||
poll: {
|
poll: {
|
||||||
cooldown: number /* in ms */
|
cooldown: number /* in ms */
|
||||||
}
|
}
|
||||||
websocket: {
|
|
||||||
type: 'ws'
|
|
||||||
url: string
|
|
||||||
version: number
|
|
||||||
}
|
|
||||||
// Wait this long (ms) before asking BE for a dump when out of order messages are received
|
// Wait this long (ms) before asking BE for a dump when out of order messages are received
|
||||||
timeoutForMissingRevision: number
|
timeoutForMissingRevision: number
|
||||||
}
|
}
|
||||||
api: {
|
api: {
|
||||||
mocks: boolean
|
|
||||||
url: string
|
url: string
|
||||||
version: string
|
version: string
|
||||||
root: string
|
|
||||||
}
|
}
|
||||||
maskAs: 'tor' | 'lan' | 'none'
|
mocks: {
|
||||||
skipStartupAlerts: boolean
|
enabled: boolean
|
||||||
|
connection: 'ws' | 'poll'
|
||||||
|
rpcPort: number
|
||||||
|
wsPort: number
|
||||||
|
maskAs: 'tor' | 'lan'
|
||||||
|
skipStartupAlerts: boolean
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
@@ -36,16 +33,21 @@ export class ConfigService {
|
|||||||
|
|
||||||
patchDb = patchDb
|
patchDb = patchDb
|
||||||
api = api
|
api = api
|
||||||
|
mocks = mocks
|
||||||
|
|
||||||
skipStartupAlerts = skipStartupAlerts
|
skipStartupAlerts = mocks.enabled && mocks.skipStartupAlerts
|
||||||
isConsulate = window['platform'] === 'ios'
|
isConsulate = window['platform'] === 'ios'
|
||||||
|
|
||||||
isTor () : boolean {
|
isTor (): boolean {
|
||||||
return (maskAs === 'tor') || this.origin.endsWith('.onion')
|
return (mocks.enabled && mocks.maskAs === 'tor') || this.origin.endsWith('.onion')
|
||||||
}
|
}
|
||||||
|
|
||||||
isLan () : boolean {
|
isLan (): boolean {
|
||||||
return (maskAs === 'lan') || this.origin.endsWith('.local')
|
return (mocks.enabled && mocks.maskAs === 'lan') || this.origin.endsWith('.local')
|
||||||
|
}
|
||||||
|
|
||||||
|
usePoll (): boolean {
|
||||||
|
return this.isConsulate || (mocks.enabled && mocks.connection === 'poll')
|
||||||
}
|
}
|
||||||
|
|
||||||
isLaunchable (pkg: PackageDataEntry): boolean {
|
isLaunchable (pkg: PackageDataEntry): boolean {
|
||||||
|
|||||||
@@ -66,11 +66,11 @@ export class ConnectionService {
|
|||||||
// ping server every 10 seconds
|
// ping server every 10 seconds
|
||||||
this.httpSubscription = timer(0, 10000)
|
this.httpSubscription = timer(0, 10000)
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap(() => this.apiService.ping()),
|
switchMap(() => this.apiService.echo()),
|
||||||
retryWhen(errors =>
|
retryWhen(errors =>
|
||||||
errors.pipe(
|
errors.pipe(
|
||||||
tap(val => {
|
tap(val => {
|
||||||
console.error('Ping error: ', val)
|
console.error('Echo error: ', val)
|
||||||
this.currentState.internet = true
|
this.currentState.internet = true
|
||||||
this.emitEvent()
|
this.emitEvent()
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -3,20 +3,17 @@
|
|||||||
"timeoutForMissingRevision": 5000,
|
"timeoutForMissingRevision": 5000,
|
||||||
"poll": {
|
"poll": {
|
||||||
"cooldown": 40000
|
"cooldown": 40000
|
||||||
},
|
}
|
||||||
"websocket": {
|
|
||||||
"type": "ws",
|
|
||||||
"url": "",
|
|
||||||
"version": 0
|
|
||||||
},
|
|
||||||
"usePollOverride": true
|
|
||||||
},
|
},
|
||||||
"api": {
|
"api": {
|
||||||
"mocks": true,
|
"url": "/rpc",
|
||||||
"url": "/api",
|
"version": "v1"
|
||||||
"version": "v1",
|
|
||||||
"root": ""
|
|
||||||
},
|
},
|
||||||
"maskAs": "tor",
|
"mocks": {
|
||||||
"skipStartupAlerts": true
|
"enabled": true,
|
||||||
|
"connection": "poll",
|
||||||
|
"websocketUrl": "",
|
||||||
|
"maskAs": "tor",
|
||||||
|
"skipStartupAlerts": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user