///
namespace Leaf {
export class ErrorDoc {
private errorNames: string[]
private errors: TErrors = {} as TErrors
static create(): ErrorDoc {
return new ErrorDoc()
}
static build(info: TErrors): {
[K in keyof TErrors]: CustomErrorConstructor
} {
let result = {}
for (let name in info) {
result[name as string] = createError(name, Error, info[name] || {})
}
return result as any
}
public define(name: string, base?: string | Error | Constructor, defaultProperty?: any) {
let Base: Function = Error
if (typeof base === "string") {
let _ = this[base]
if (typeof _ === "function") {
Base = _
}
} else if (typeof base === "function") {
Base = base
} else if (base) {
console.warn("Unknown base error", base)
}
let E = createError(name, Base as Constructor, defaultProperty)
this.errors[name] = E
return this
}
public generate() {
return this.errors
}
}
export type Constructor = {
new(...params: any[]): T
}
export function createError(name: string, Base?: Constructor, defaultProperty?: any) {
return class E extends Base {
constructor(message: string, detail: any) {
super(message, detail)
if (typeof message === "object") {
if (!detail) {
detail = message
message = name
} else {
try {
message = JSON.stringify(message, null, 4)
} catch (e) {
message = name + "Warning: recursive error property" + e.toString()
}
}
}
this.name = name
this.message = message || name
if (typeof defaultProperty === "function") {
let _ = Base
Base = defaultProperty
defaultProperty = _
}
if (!detail) detail = {}
if (!defaultProperty) defaultProperty = {}
for (let prop in defaultProperty) {
this[prop] = defaultProperty[prop]
}
if (!this.detail) {
this.detail = {}
}
for (let prop in detail) {
this.detail[prop] = detail[prop]
}
for (let prop in detail) {
this[prop] = detail[prop]
}
if (detail.via) {
this.via = detail.via
}
this.toJSON = () => {
let result = {} as any
for (let prop in this) {
if (this.hasOwnProperty(prop) && typeof this[prop] !== "function") {
result[prop] = this[prop]
}
}
if (this.message) {
result["message"] = this.message
}
result["name"] = this.name
return result
}
}
message: string
name: string
detail: any = null
via: Error = null
toJSON: () => any = null
}
//let E = function (message: string, detail: any) {
// if (typeof message === "object") {
// if (!detail) {
// detail = message
// message = name
// } else {
// try {
// message = JSON.stringify(message, null, 4)
// } catch (e) {
// message = name + "Warning: recursive error property" + e.toString()
// }
// }
// }
// this.name = name
// this.message = message || name
// if (typeof defaultProperty === "function") {
// let _ = base
// base = defaultProperty
// defaultProperty = _
// }
// if (!detail) detail = {}
// if (!defaultProperty) defaultProperty = {}
// for (let prop in defaultProperty) {
// this[prop] = defaultProperty[prop]
// }
// if (!this.detail) {
// this.detail = {}
// }
// for (let prop in detail) {
// this.detail[prop] = detail[prop]
// }
// if (detail.via) {
// this.via = detail.via
// }
//}
}
export type Partial = {
[P in keyof T]?: T[P]
}
export interface CustomErrorConstructor {
//new (message?: string, detail?: any): void
new(message?: string, detail?: Partial & { via?: Error }): { detail: TDetail } & Error & { via: Error }
}
export const Errors = ErrorDoc.create()
.define("Timeout")
.define("Abort")
.define("IOError")
.define("NetworkError")
.generate() as ErrorsOf<{
Timeout: {}
Abort: {}
IOError: {}
NetworkError: {
raw?: string
}
}>
export type ErrorsOf = {
[P in keyof T]?: CustomErrorConstructor;
}
}