mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 12:11:56 +00:00
basic info checkpoint (#1230)
* basic info * preview manifest * textarea not long * show error message details always * reinstall button in marketplace Co-authored-by: Drew Ansbacher <drew@start9labs.com> Co-authored-by: Matt Hill <matthewonthemoon@gmail.com>
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams } from '@angular/common/http'
|
||||
import {
|
||||
HttpClient,
|
||||
HttpErrorResponse,
|
||||
HttpHeaders,
|
||||
HttpParams,
|
||||
} from '@angular/common/http'
|
||||
import { Observable, from, interval, race } from 'rxjs'
|
||||
import { map, take } from 'rxjs/operators'
|
||||
import { ConfigService } from './config.service'
|
||||
@@ -12,7 +17,7 @@ import { AuthService } from './auth.service'
|
||||
export class HttpService {
|
||||
fullUrl: string
|
||||
|
||||
constructor (
|
||||
constructor(
|
||||
private readonly http: HttpClient,
|
||||
private readonly config: ConfigService,
|
||||
private readonly auth: AuthService,
|
||||
@@ -21,9 +26,9 @@ export class HttpService {
|
||||
this.fullUrl = `${window.location.protocol}//${window.location.hostname}:${port}`
|
||||
}
|
||||
|
||||
async rpcRequest<T> (rpcOpts: RPCOptions): Promise<T> {
|
||||
async rpcRequest<T>(rpcOpts: RPCOptions): Promise<T> {
|
||||
const { url, version } = this.config.api
|
||||
rpcOpts.params = rpcOpts.params || { }
|
||||
rpcOpts.params = rpcOpts.params || {}
|
||||
const httpOpts: HttpOptions = {
|
||||
method: Method.POST,
|
||||
body: rpcOpts,
|
||||
@@ -40,17 +45,15 @@ export class HttpService {
|
||||
if (isRpcSuccess(res)) return res.result
|
||||
}
|
||||
|
||||
async httpRequest<T> (httpOpts: HttpOptions): Promise<T> {
|
||||
async httpRequest<T>(httpOpts: HttpOptions): Promise<T> {
|
||||
if (httpOpts.withCredentials !== false) {
|
||||
httpOpts.withCredentials = true
|
||||
}
|
||||
|
||||
const urlIsRelative = httpOpts.url.startsWith('/')
|
||||
const url = urlIsRelative ?
|
||||
this.fullUrl + httpOpts.url :
|
||||
httpOpts.url
|
||||
const url = urlIsRelative ? this.fullUrl + httpOpts.url : httpOpts.url
|
||||
|
||||
Object.keys(httpOpts.params || { }).forEach(key => {
|
||||
Object.keys(httpOpts.params || {}).forEach(key => {
|
||||
if (httpOpts.params[key] === undefined) {
|
||||
delete httpOpts.params[key]
|
||||
}
|
||||
@@ -69,36 +72,51 @@ export class HttpService {
|
||||
|
||||
let req: Observable<{ body: T }>
|
||||
switch (httpOpts.method) {
|
||||
case Method.GET: req = this.http.get(url, options) as any; break
|
||||
case Method.POST: req = this.http.post(url, httpOpts.body, options) as any; break
|
||||
case Method.PUT: req = this.http.put(url, httpOpts.body, options) as any; break
|
||||
case Method.PATCH: req = this.http.patch(url, httpOpts.body, options) as any; break
|
||||
case Method.DELETE: req = this.http.delete(url, options) as any; break
|
||||
case Method.GET:
|
||||
req = this.http.get(url, options) as any
|
||||
break
|
||||
case Method.POST:
|
||||
req = this.http.post(url, httpOpts.body, options) as any
|
||||
break
|
||||
case Method.PUT:
|
||||
req = this.http.put(url, httpOpts.body, options) as any
|
||||
break
|
||||
case Method.PATCH:
|
||||
req = this.http.patch(url, httpOpts.body, options) as any
|
||||
break
|
||||
case Method.DELETE:
|
||||
req = this.http.delete(url, options) as any
|
||||
break
|
||||
}
|
||||
|
||||
return (httpOpts.timeout ? withTimeout(req, httpOpts.timeout) : req)
|
||||
.toPromise()
|
||||
.then(res => res.body)
|
||||
.catch(e => { throw new HttpError(e) })
|
||||
.catch(e => {
|
||||
throw new HttpError(e)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function RpcError (e: RPCError['error']): void {
|
||||
function RpcError(e: RPCError['error']): void {
|
||||
const { code, message, data } = e
|
||||
|
||||
this.code = code
|
||||
this.message = message
|
||||
|
||||
if (typeof data === 'string') {
|
||||
this.details = e.data
|
||||
this.message = `${message}\n\n${data}`
|
||||
this.revision = null
|
||||
} else {
|
||||
this.details = data.details
|
||||
if (data.details) {
|
||||
this.message = `${message}\n\n${data.details}`
|
||||
} else {
|
||||
this.message = message
|
||||
}
|
||||
this.revision = data.revision
|
||||
}
|
||||
}
|
||||
|
||||
function HttpError (e: HttpErrorResponse): void {
|
||||
function HttpError(e: HttpErrorResponse): void {
|
||||
const { status, statusText } = e
|
||||
|
||||
this.code = status
|
||||
@@ -107,11 +125,15 @@ function HttpError (e: HttpErrorResponse): void {
|
||||
this.revision = null
|
||||
}
|
||||
|
||||
function isRpcError<Error, Result> (arg: { error: Error } | { result: Result}): arg is { error: Error } {
|
||||
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 } {
|
||||
function isRpcSuccess<Error, Result>(
|
||||
arg: { error: Error } | { result: Result },
|
||||
): arg is { result: Result } {
|
||||
return !!(arg as any).result
|
||||
}
|
||||
|
||||
@@ -154,36 +176,49 @@ export interface RPCError extends RPCBase {
|
||||
error: {
|
||||
code: number
|
||||
message: string
|
||||
data?: {
|
||||
details: string
|
||||
revision: Revision | null
|
||||
debug: string | null
|
||||
} | string
|
||||
data?:
|
||||
| {
|
||||
details: string
|
||||
revision: Revision | null
|
||||
debug: string | null
|
||||
}
|
||||
| string
|
||||
}
|
||||
}
|
||||
|
||||
export type RPCResponse<T> = RPCSuccess<T> | RPCError
|
||||
|
||||
type HttpError = HttpErrorResponse & { error: { code: string, message: string } }
|
||||
type HttpError = HttpErrorResponse & {
|
||||
error: { code: string; message: string }
|
||||
}
|
||||
|
||||
export interface HttpOptions {
|
||||
method: Method
|
||||
url: string
|
||||
headers?: HttpHeaders | {
|
||||
[header: string]: string | string[]
|
||||
}
|
||||
params?: HttpParams | {
|
||||
[param: string]: string | string[]
|
||||
}
|
||||
headers?:
|
||||
| HttpHeaders
|
||||
| {
|
||||
[header: string]: string | string[]
|
||||
}
|
||||
params?:
|
||||
| HttpParams
|
||||
| {
|
||||
[param: string]: string | string[]
|
||||
}
|
||||
responseType?: 'json' | 'text'
|
||||
withCredentials?: boolean
|
||||
body?: any
|
||||
timeout?: number
|
||||
}
|
||||
|
||||
function withTimeout<U> (req: Observable<U>, timeout: number): Observable<U> {
|
||||
function withTimeout<U>(req: Observable<U>, timeout: number): Observable<U> {
|
||||
return race(
|
||||
from(req.toPromise()), // this guarantees it only emits on completion, intermediary emissions are suppressed.
|
||||
interval(timeout).pipe(take(1), map(() => { throw new Error('timeout') })),
|
||||
interval(timeout).pipe(
|
||||
take(1),
|
||||
map(() => {
|
||||
throw new Error('timeout')
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user