grip/grip.ts

207 lines
4.1 KiB
TypeScript
Raw Normal View History

2024-10-16 06:18:40 +00:00
interface Status {
message?: string;
cause?: any;
2024-10-16 05:02:31 +00:00
Ok(): boolean;
2024-10-17 08:03:07 +00:00
ok(): boolean;
2024-10-16 05:02:31 +00:00
Fail(): boolean;
2024-10-17 08:03:07 +00:00
fail(): boolean;
2024-10-16 05:02:31 +00:00
Of(cls: any): boolean;
2024-10-17 08:03:07 +00:00
of(cls: any): boolean;
2024-10-16 05:02:31 +00:00
}
export class Err extends Error {
Ok() {
return false;
}
2024-10-17 08:03:07 +00:00
ok() {
return this.Ok();
}
2024-10-16 05:02:31 +00:00
Fail() {
return true;
}
2024-10-17 08:03:07 +00:00
fail() {
return this.Fail();
}
2024-10-16 05:02:31 +00:00
Of(cls: any) {
return this.cause instanceof cls || this instanceof cls;
}
2024-10-17 08:03:07 +00:00
of(cls: any) {
return this.Of(cls);
}
2024-10-16 05:02:31 +00:00
static fromCatch(error: any) {
const e = new Err(typeof error === "string" ? error : error.message);
e.cause = error;
e.stack = error.stack;
return e;
}
}
2024-10-16 06:18:40 +00:00
export class Ok {
2024-10-16 05:02:31 +00:00
Ok() {
return true;
}
2024-10-17 08:03:07 +00:00
ok() {
return this.Ok();
}
2024-10-16 05:02:31 +00:00
Fail() {
return false;
}
2024-10-17 08:03:07 +00:00
fail() {
return this.Fail();
}
2024-10-16 05:02:31 +00:00
Of(cls: any) {
return this instanceof cls;
}
2024-10-17 08:03:07 +00:00
of(cls: any) {
return this.Of(cls);
}
2024-10-16 06:18:40 +00:00
toString() {
return "Ok";
}
2024-10-16 05:02:31 +00:00
}
interface IResult<T> {
0: T;
1: Status;
value: T;
status: Status;
Of(cls: any): boolean;
Ok(): boolean;
Fail(): boolean;
}
class Result<T> extends Array<T | Status> implements IResult<T> {
0: T;
1: Status;
constructor(result: T, status: Status) {
super(2);
this[0] = result;
this[1] = status;
}
get value() {
return this[0];
}
get status() {
return this[1];
}
Ok() {
return (this[1] as Status).Ok();
}
2024-10-17 08:03:07 +00:00
ok() {
return this.Ok();
}
2024-10-16 05:02:31 +00:00
Fail() {
return (this[1] as Status).Fail();
}
2024-10-17 08:03:07 +00:00
fail() {
return this.Fail();
}
2024-10-17 03:24:06 +00:00
Of(cls: any) {
return (this[1] as Status).Of(cls);
}
2024-10-17 08:03:07 +00:00
of(cls: any) {
return this.Of(cls);
}
2024-10-17 03:24:06 +00:00
Iter() {
const value = this.value;
const that = this;
if (
typeof value !== "object" &&
!(
typeof (value as any)[Symbol.iterator] === "function" ||
typeof (value as any)[Symbol.asyncIterator] === "function"
)
) {
return {
async *[Symbol.asyncIterator]() {
yield new Result(that.value, that.status) as SafeResult<T>;
},
*[Symbol.iterator]() {
yield new Result(that.value, that.status) as SafeResult<T>;
},
};
}
return {
async *[Symbol.asyncIterator]() {
yield* asyncIterator<T>(value as AsyncGenerator);
},
*[Symbol.iterator]() {
yield* iterator<T>(value as Generator);
},
};
2024-10-16 05:02:31 +00:00
}
2024-10-17 08:03:07 +00:00
iter() {
return this.Iter();
}
2024-10-16 05:02:31 +00:00
}
type Unwrap<T> =
2024-10-17 03:24:06 +00:00
T extends AsyncGenerator<infer U>
2024-10-16 05:02:31 +00:00
? U
2024-10-17 03:24:06 +00:00
: T extends Generator<infer U>
2024-10-16 05:02:31 +00:00
? U
2024-10-17 03:24:06 +00:00
: T extends Promise<infer U>
2024-10-16 05:02:31 +00:00
? U
2024-10-17 03:24:06 +00:00
: T extends (...args: any) => Promise<infer U>
? U
: T extends (...args: any) => infer U
? U
: T;
2024-10-16 05:02:31 +00:00
export type SafeResult<T> =
T extends Promise<any>
? Promise<Result<Unwrap<T>>>
: T extends () => Promise<any>
? Promise<Result<Unwrap<T>>>
: Result<Unwrap<T>>;
2024-10-17 22:51:30 +00:00
export function grip<T>(action: T) {
2024-10-16 05:02:31 +00:00
if (action instanceof Promise) {
return promise<T>(action) as SafeResult<T>;
}
try {
const result = (action as any)();
if (result instanceof Promise) {
return promise<T>(result) as SafeResult<T>;
}
return new Result<T>(result, new Ok()) as SafeResult<T>;
} catch (err: any) {
2024-10-17 22:51:30 +00:00
return new Result<T>(
null as never,
Err.fromCatch(err),
) as SafeResult<never>;
2024-10-16 05:02:31 +00:00
}
}
2024-10-17 22:51:30 +00:00
const promise = async <T>(result: Promise<T>) => {
try {
return new Result(await result, new Ok());
} catch (err) {
return new Result<never>(null as never, Err.fromCatch(err));
}
2024-10-16 05:02:31 +00:00
};
2024-10-17 03:24:06 +00:00
const iterator = function* <T>(iter: Generator) {
try {
let data = iter.next();
while (!data.done) {
yield new Result<T>(data.value as T, new Ok()) as SafeResult<T>;
data = iter.next();
}
} catch (e) {
2024-10-17 22:51:30 +00:00
yield new Result<T>(null as never, Err.fromCatch(e)) as SafeResult<never>;
2024-10-17 03:24:06 +00:00
}
};
const asyncIterator = async function* <T>(iter: AsyncGenerator) {
try {
let data = await iter.next();
while (!data.done) {
yield new Result<T>(data.value as T, new Ok()) as SafeResult<T>;
data = await iter.next();
}
} catch (e) {
2024-10-17 22:51:30 +00:00
yield new Result<T>(null as T, Err.fromCatch(e)) as SafeResult<never>;
2024-10-17 03:24:06 +00:00
}
};