Add Safe value API and start OAuth2Server
This commit is contained in:
@@ -31,6 +31,8 @@ export * from './support/path/Filesystem'
|
||||
export * from './support/path/LocalFilesystem'
|
||||
export * from './support/path/SSHFilesystem'
|
||||
|
||||
export * from './support/Safe'
|
||||
|
||||
export * from './support/Rehydratable'
|
||||
export * from './support/string'
|
||||
export * from './support/timeout'
|
||||
|
||||
@@ -47,6 +47,16 @@ export class Pipeline<TIn, TOut> {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Like tap, but operates on a tuple with both the first value and the tapped value.
|
||||
* @param op
|
||||
*/
|
||||
first<T2>(op: PipeOperator<[TIn, TOut], T2>): Pipeline<TIn, T2> {
|
||||
return new Pipeline((val: TIn) => {
|
||||
return op([val, this.factory(val)])
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Like tap, but always returns the original pipe type.
|
||||
* @param op
|
||||
|
||||
61
src/util/support/Safe.ts
Normal file
61
src/util/support/Safe.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import {Integer, isInteger} from './types'
|
||||
import {ErrorWithContext} from '../error/ErrorWithContext'
|
||||
|
||||
export class Safe {
|
||||
protected thrower: (message: string, value: unknown) => never
|
||||
|
||||
constructor(
|
||||
protected readonly value: unknown,
|
||||
) {
|
||||
this.thrower = (message) => {
|
||||
throw new ErrorWithContext('Invalid value', {
|
||||
message,
|
||||
value,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
onError(thrower: (message: string, value: unknown) => never): this {
|
||||
this.thrower = thrower
|
||||
return this
|
||||
}
|
||||
|
||||
present(): this {
|
||||
if ( !this.value && this.value !== 0 && this.value !== false ) {
|
||||
return this
|
||||
}
|
||||
|
||||
this.thrower('Missing value', this.value)
|
||||
}
|
||||
|
||||
integer(): Integer {
|
||||
const value = parseInt(String(this.value), 10)
|
||||
if ( !isInteger(value) ) {
|
||||
this.thrower('Invalid integer', this.value)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
number(): number {
|
||||
const value = parseFloat(String(this.value))
|
||||
if ( isNaN(value) ) {
|
||||
this.thrower('Invalid number', this.value)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
string(): string {
|
||||
this.present()
|
||||
return String(this.value)
|
||||
}
|
||||
|
||||
in<T>(allowed: T[]): T {
|
||||
if ( allowed.includes(this.value as any) ) {
|
||||
return this.value as T
|
||||
}
|
||||
|
||||
this.thrower('Invalid value', this.value)
|
||||
}
|
||||
}
|
||||
@@ -74,3 +74,9 @@ export type MethodsOf<T, TMethod = (...args: any[]) => any> = {
|
||||
}[keyof T]
|
||||
|
||||
export type Awaited<T> = T extends PromiseLike<infer U> ? U : T
|
||||
|
||||
export type Integer = TypeTag<'@extollo/lib.Integer'> & number
|
||||
|
||||
export function isInteger(num: number): num is Integer {
|
||||
return !isNaN(num) && parseInt(String(num), 10) === num
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user