mirror of
https://github.com/enso-org/enso.git
synced 2024-12-24 02:42:28 +03:00
a6fc8cb932
Fixes #9313 [Screencast from 2024-03-22 09-09-07.webm](https://github.com/enso-org/enso/assets/3919101/6ad86145-6882-4bde-993d-b1270f1ec06c) # Important Notes * This is PoC, so I didn't spend time on polishing the visuals; the design will likely change. * I modified the shortcut handler a bit, allowing making multiple actions for same binding - the action's handler will be called in unspecified order, until one of them handle the event (i.e. not return false). * To make it working regardless of imports, I needed to export AI module in Standard.Visualization. Moreover, needed to remove build_ai_prompt for Any, because it was causing issues - expect a bug report soon.
90 lines
2.4 KiB
TypeScript
90 lines
2.4 KiB
TypeScript
/** @file A generic type that can either hold a value representing a successful result,
|
|
* or an error. */
|
|
|
|
import { isSome, type Opt } from './opt'
|
|
|
|
export type Result<T = undefined, E = string> =
|
|
| { ok: true; value: T }
|
|
| { ok: false; error: ResultError<E> }
|
|
|
|
export function Ok<T>(data: T): Result<T, never> {
|
|
return { ok: true, value: data }
|
|
}
|
|
|
|
export function Err<E>(error: E): Result<never, E> {
|
|
return { ok: false, error: new ResultError(error) }
|
|
}
|
|
|
|
export function okOr<T, E>(data: Opt<T>, error: E): Result<T, E> {
|
|
if (isSome(data)) return Ok(data)
|
|
else return Err(error)
|
|
}
|
|
|
|
export function unwrap<T, E>(result: Result<T, E>): T {
|
|
if (result.ok) return result.value
|
|
else throw result.error
|
|
}
|
|
|
|
export function mapOk<T, U, E>(result: Result<T, E>, f: (value: T) => U): Result<U, E> {
|
|
if (result.ok) return Ok(f(result.value))
|
|
else return result
|
|
}
|
|
|
|
export function isResult(v: unknown): v is Result {
|
|
return (
|
|
v != null &&
|
|
typeof v === 'object' &&
|
|
'ok' in v &&
|
|
typeof v.ok === 'boolean' &&
|
|
('value' in v || ('error' in v && v.error instanceof ResultError))
|
|
)
|
|
}
|
|
|
|
export class ResultError<E = string> {
|
|
payload: E
|
|
context: (() => string)[]
|
|
|
|
constructor(payload: E) {
|
|
this.payload = payload
|
|
this.context = []
|
|
}
|
|
|
|
log(preamble: string = 'Error') {
|
|
console.error(this.message(preamble))
|
|
}
|
|
|
|
message(preamble: string = 'error') {
|
|
const ctx =
|
|
this.context.length > 0 ? `\n${Array.from(this.context, (ctx) => ctx()).join('\n')}` : ''
|
|
return `${preamble}: ${this.payload}${ctx}`
|
|
}
|
|
}
|
|
|
|
export function withContext<T, E>(context: () => string, f: () => Result<T, E>): Result<T, E> {
|
|
const result = f()
|
|
if (result == null) {
|
|
throw new Error('withContext: f() returned null or undefined')
|
|
}
|
|
if (!result.ok) result.error.context.splice(0, 0, context)
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* Catch promise rejection of provided types and convert them to a Result type.
|
|
*/
|
|
export function rejectionToResult<ErrorKind extends new (...args: any[]) => any>(
|
|
errorKinds: ErrorKind | ErrorKind[],
|
|
): <T>(promise: Promise<T>) => Promise<Result<T, InstanceType<ErrorKind>>> {
|
|
const errorKindArray = Array.isArray(errorKinds) ? errorKinds : [errorKinds]
|
|
return async (promise) => {
|
|
try {
|
|
return Ok(await promise)
|
|
} catch (error) {
|
|
for (const errorKind of errorKindArray) {
|
|
if (error instanceof errorKind) return Err(error)
|
|
}
|
|
throw error
|
|
}
|
|
}
|
|
}
|