char/avril

(wip) why'd you have to go and make things so complicaaaaated?

git clone https://git.t4t.associates/char/avril

Charlotte Somport file extension to typescriptdea05b4

main
2.3 KiB90 linesraw
1import {
2  Error,
3  ObjectCreate,
4  ObjectDefineProperty as define,
5  ObjectFreeze as freeze,
6  ReflectConstruct as construct,
7  WeakMap,
8  WeakMapPrototypeGet as get,
9  WeakMapPrototypeSet as set,
10} from "ext:core/primordials";
11
12export type FileReply<T> =
13  | [value: T, error: null]
14  | [value: null, error: [kind: string, message: string]];
15
16type FileErrorName =
17  | "NotFound"
18  | "PermissionDenied"
19  | "AlreadyExists"
20  | "NotEmpty"
21  | "CrossDevice"
22  | "NotADirectory"
23  | "IsADirectory"
24  | "InvalidInput"
25  | "BadResource"
26  | "Busy"
27  | "BrokenPipe"
28  | "NotSupported"
29  | "IoError";
30type FileErrorConstructor = new (message?: string) => Error;
31const errors = ObjectCreate(null) as Readonly<Record<
32  FileErrorName,
33  FileErrorConstructor
34>>;
35const codes = new WeakMap<object, string>();
36export function errorCode(error: unknown): string | undefined {
37  return get(codes, error as object);
38}
39for (
40  const name of [
41    "NotFound",
42    "PermissionDenied",
43    "AlreadyExists",
44    "NotEmpty",
45    "CrossDevice",
46    "NotADirectory",
47    "IsADirectory",
48    "InvalidInput",
49    "BadResource",
50    "Busy",
51    "BrokenPipe",
52    "NotSupported",
53    "IoError",
54  ]
55) {
56  const ctor = class extends Error {
57    // @ts-expect-error Reflect.construct avoids a guest-replaceable superclass constructor.
58    constructor(message = "") {
59      const self = construct(Error, [message], new.target) as Error;
60      define(self, "name", { value: name, writable: true, configurable: true });
61      return self;
62    }
63  };
64  define(ctor, "name", { value: name, configurable: true });
65  define(errors, name, { value: ctor, enumerable: true });
66}
67freeze(errors);
68export { errors };
69export function failure(name: string, message: string): Error {
70  const result = construct(
71    Error,
72    [message],
73    (errors as Record<string, FileErrorConstructor>)[name] || errors.IoError,
74  ) as Error;
75  const descriptor: {
76    value: string;
77    writable: boolean;
78    configurable: boolean;
79  } = ObjectCreate(null);
80  descriptor.value = name;
81  descriptor.writable = true;
82  descriptor.configurable = true;
83  define(result, "name", descriptor);
84  set(codes, result, name);
85  return result;
86}
87export function result<T>(reply: FileReply<T>): T {
88  if (reply[1] !== null) throw failure(reply[1][0], reply[1][1]);
89  return reply[0];
90}