0.3.0 refactor

ui: adds overlay layer to patch-db-client

ui: getting towards mocks

ui: cleans up factory init

ui: nice type hack

ui: live api for patch

ui: api service source + http

starts up

ui: api source + http

ui: rework patchdb config, pass stashTimeout into patchDbModel

wires in temp patching into api service

ui: example of wiring patchdbmodel into page

begin integration

remove unnecessary method

linting

first data rendering

rework app initialization

http source working for ssh delete call

temp patches working

entire Embassy tab complete

not in kansas anymore

ripping, saving progress

progress for API request response types and endoint defs

Update data-model.ts

shambles, but in a good way

progress

big progress

progress

installed list working

big progress

progress

progress

begin marketplace redesign

Update api-types.ts

Update api-types.ts

marketplace improvements

cosmetic

dependencies and recommendations

begin nym auth approach

install wizard

restore flow and donations
This commit is contained in:
Aaron Greenspan
2021-02-16 13:45:09 -07:00
committed by Aiden McClelland
parent fd685ae32c
commit 594d93eb3b
238 changed files with 15137 additions and 21331 deletions

View File

@@ -1,32 +1,49 @@
import { Injectable } from '@angular/core'
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'
import { Observable, from, interval, race } from 'rxjs'
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams } from '@angular/common/http'
import { Observable, from, interval, race, Subject } from 'rxjs'
import { map, take } from 'rxjs/operators'
import { ConfigService } from './config.service'
import { Revision } from 'patch-db-client'
@Injectable({
providedIn: 'root',
})
export class HttpService {
private unauthorizedApiResponse$ = new Subject()
authReqEnabled: boolean = false
rootUrl: string
constructor (
private readonly http: HttpClient,
private readonly config: ConfigService,
) { }
get raw () : HttpClient {
return this.http
) {
const { url, version } = this.config.api
this.rootUrl = `${url}/${version}`
}
async serverRequest<T> (options: HttpOptions, overrides: Partial<{ version: string }> = { }): Promise<T> {
options.url = leadingSlash(`${this.config.api.url}${exists(overrides.version) ? overrides.version : this.config.api.version}${options.url}`)
if ( this.config.api.root && this.config.api.root !== '' ) {
options.url = `${this.config.api.root}${options.url}`
watch401$ (): Observable<{ }> {
return this.unauthorizedApiResponse$.asObservable()
}
async rpcRequest<T> (rpcOpts: RPCOptions): Promise<T> {
rpcOpts.params = rpcOpts.params || { }
const httpOpts = {
method: Method.POST,
data: rpcOpts,
url: '',
}
return this.request<T>(options)
const res = await this.httpRequest<RPCResponse<T>>(httpOpts)
if (isRpcError(res)) throw new RpcError(res.error)
if (isRpcSuccess(res)) return res.result
}
async request<T> (httpOpts: HttpOptions): Promise<T> {
const { url, body, timeout, ...rest} = translateOptions(httpOpts)
async httpRequest<T> (httpOpts: HttpOptions): Promise<T> {
let { url, body, timeout, ...rest} = translateOptions(httpOpts)
url = this.rootUrl + url
let req: Observable<{ body: T }>
switch (httpOpts.method){
case Method.GET: req = this.http.get(url, rest) as any; break
@@ -37,25 +54,42 @@ export class HttpService {
}
return (timeout ? withTimeout(req, timeout) : req)
.toPromise()
.then(res => res.body)
.catch(e => { console.error(e); throw humanReadableErrorMessage(e)})
.toPromise()
.then(res => res.body)
.catch(e => { throw new HttpError(e) })
}
}
function humanReadableErrorMessage (e: any): Error {
// server up, custom backend error
if (e.error && e.error.message) return { ...e, message: e.error.message }
if (e.message) return { ...e, message: e.message }
if (e.status && e.statusText) return { ...e, message: `${e.status} ${e.statusText}` }
return { ...e, message: `Unidentifiable HTTP exception` }
function RpcError (e: RPCError['error']): void {
const { code, message } = e
this.status = code
this.message = message
if (typeof e.data === 'string') {
throw new Error(`unexpected response for RPC Error data: ${e.data}`)
}
const data = e.data || { message: 'unknown RPC error', revision: null }
this.data = { ...data, code }
}
function leadingSlash (url: string): string {
let toReturn = url
toReturn = toReturn.startsWith('/') ? toReturn : '/' + toReturn
toReturn = !toReturn.endsWith('/') ? toReturn : toReturn.slice(0, -1)
return toReturn
function HttpError (e: HttpErrorResponse): void {
const { status, statusText, error } = e
this.status = status
this.message = statusText
this.data = error || { } // error = { code: string, message: string }
}
function isRpcError<Error, Result> (arg: { error: Error } | { result: Result}): arg is { error: Error } {
return !!(arg as any).error
}
function isRpcSuccess<Error, Result> (arg: { error: Error } | { result: Result}): arg is { result: Result } {
return !!(arg as any).result
}
export interface RequestError {
status: number
message: string
data: { code: string, message: string, revision: Revision | null }
}
export enum Method {
@@ -66,27 +100,64 @@ export enum Method {
DELETE = 'DELETE',
}
export interface RPCOptions {
method: string
// @TODO what are valid params? object, bool?
params?: {
[param: string]: string | number | boolean | object | string[] | number[];
}
}
interface RPCBase {
jsonrpc: '2.0'
id: string
}
export interface RPCRequest<T> extends RPCBase {
method: string
params?: T
}
export interface RPCSuccess<T> extends RPCBase {
result: T
}
export interface RPCError extends RPCBase {
error: {
code: number,
message: string
data?: {
message: string
revision: Revision | null
} | string
}
}
export type RPCResponse<T> = RPCSuccess<T> | RPCError
type HttpError = HttpErrorResponse & { error: { code: string, message: string } }
export interface HttpOptions {
withCredentials?: boolean
url: string
method: Method
params?: {
[param: string]: string | string[];
[param: string]: string | string[]
}
data?: any
headers?: {
[key: string]: string;
}
url: string
readTimeout?: number
}
export interface HttpJsonOptions {
headers?: HttpHeaders | {
[header: string]: string | string[];
[header: string]: string | string[]
}
observe: 'events'
params?: HttpParams | {
[param: string]: string | string[];
[param: string]: string | string[]
}
reportProgress?: boolean
responseType?: 'json'
@@ -116,7 +187,3 @@ function withTimeout<U> (req: Observable<U>, timeout: number): Observable<U> {
interval(timeout).pipe(take(1), map(() => { throw new Error('timeout') })),
)
}
function exists (str?: string): boolean {
return !!str || str === ''
}