2022-02-24 06:00:35 +00:00
|
|
|
import {Integer, isInteger} from './types'
|
|
|
|
import {ErrorWithContext} from '../error/ErrorWithContext'
|
2022-03-29 06:14:46 +00:00
|
|
|
import {JSONState} from './Rehydratable'
|
|
|
|
import {isJSON} from './data'
|
2022-02-24 06:00:35 +00:00
|
|
|
|
|
|
|
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 ) {
|
2022-03-29 06:14:46 +00:00
|
|
|
this.thrower('Missing value', this.value)
|
2022-02-24 06:00:35 +00:00
|
|
|
}
|
|
|
|
|
2022-03-29 06:14:46 +00:00
|
|
|
return this
|
2022-02-24 06:00:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2022-03-29 06:14:46 +00:00
|
|
|
json(): JSONState {
|
|
|
|
const str = this.string()
|
|
|
|
if ( !isJSON(str) ) {
|
|
|
|
this.thrower('Invalid JSON', str)
|
|
|
|
}
|
|
|
|
|
|
|
|
return JSON.parse(str)
|
|
|
|
}
|
|
|
|
|
|
|
|
or(other: unknown): Safe {
|
|
|
|
if ( !this.value && this.value !== 0 && this.value !== false ) {
|
|
|
|
return new Safe(other)
|
|
|
|
}
|
|
|
|
|
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2022-02-24 06:00:35 +00:00
|
|
|
in<T>(allowed: T[]): T {
|
|
|
|
if ( allowed.includes(this.value as any) ) {
|
|
|
|
return this.value as T
|
|
|
|
}
|
|
|
|
|
|
|
|
this.thrower('Invalid value', this.value)
|
|
|
|
}
|
|
|
|
}
|