Add Safe value API and start OAuth2Server

This commit is contained in:
2022-02-24 00:00:35 -06:00
parent 70d67c2730
commit a039b1ff25
14 changed files with 474 additions and 2 deletions

View File

@@ -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'

View File

@@ -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
View 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)
}
}

View File

@@ -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
}