Skip to content

Commit

Permalink
feat: provide error utils
Browse files Browse the repository at this point in the history
  • Loading branch information
antongolub committed Dec 6, 2024
1 parent 0a9a386 commit 98b3e77
Show file tree
Hide file tree
Showing 10 changed files with 410 additions and 11 deletions.
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
"import": "./target/esm/index.mjs",
"default": "./target/esm/index.mjs"
},
"./error": {
"types": "./target/dts/error.d.ts",
"require": "./target/cjs/error.cjs",
"import": "./target/esm/error.mjs",
"default": "./target/esm/error.mjs"
},
"./spawn": {
"types": "./target/dts/spawn.d.ts",
"require": "./target/cjs/spawn.cjs",
Expand Down
209 changes: 209 additions & 0 deletions src/main/ts/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
export const EXIT_CODES = {
2: 'Misuse of shell builtins',
126: 'Invoked command cannot execute',
127: 'Command not found',
128: 'Invalid exit argument',
129: 'Hangup',
130: 'Interrupt',
131: 'Quit and dump core',
132: 'Illegal instruction',
133: 'Trace/breakpoint trap',
134: 'Process aborted',
135: 'Bus error: "access to undefined portion of memory object"',
136: 'Floating point exception: "erroneous arithmetic operation"',
137: 'Kill (terminate immediately)',
138: 'User-defined 1',
139: 'Segmentation violation',
140: 'User-defined 2',
141: 'Write to pipe with no one reading',
142: 'Signal raised by alarm',
143: 'Termination (request to terminate)',
145: 'Child process terminated, stopped (or continued*)',
146: 'Continue if stopped',
147: 'Stop executing temporarily',
148: 'Terminal stop signal',
149: 'Background process attempting to read from tty ("in")',
150: 'Background process attempting to write to tty ("out")',
151: 'Urgent data available on socket',
152: 'CPU time limit exceeded',
153: 'File size limit exceeded',
154: 'Signal raised by timer counting virtual time: "virtual timer expired"',
155: 'Profiling timer expired',
157: 'Pollable event',
159: 'Bad syscall',
}

export const ERRNO_CODES = {
0: 'Success',
1: 'Not super-user',
2: 'No such file or directory',
3: 'No such process',
4: 'Interrupted system call',
5: 'I/O error',
6: 'No such device or address',
7: 'Arg list too long',
8: 'Exec format error',
9: 'Bad file number',
10: 'No children',
11: 'No more processes',
12: 'Not enough core',
13: 'Permission denied',
14: 'Bad address',
15: 'Block device required',
16: 'Mount device busy',
17: 'File exists',
18: 'Cross-device link',
19: 'No such device',
20: 'Not a directory',
21: 'Is a directory',
22: 'Invalid argument',
23: 'Too many open files in system',
24: 'Too many open files',
25: 'Not a typewriter',
26: 'Text file busy',
27: 'File too large',
28: 'No space left on device',
29: 'Illegal seek',
30: 'Read only file system',
31: 'Too many links',
32: 'Broken pipe',
33: 'Math arg out of domain of func',
34: 'Math result not representable',
35: 'File locking deadlock error',
36: 'File or path name too long',
37: 'No record locks available',
38: 'Function not implemented',
39: 'Directory not empty',
40: 'Too many symbolic links',
42: 'No message of desired type',
43: 'Identifier removed',
44: 'Channel number out of range',
45: 'Level 2 not synchronized',
46: 'Level 3 halted',
47: 'Level 3 reset',
48: 'Link number out of range',
49: 'Protocol driver not attached',
50: 'No CSI structure available',
51: 'Level 2 halted',
52: 'Invalid exchange',
53: 'Invalid request descriptor',
54: 'Exchange full',
55: 'No anode',
56: 'Invalid request code',
57: 'Invalid slot',
59: 'Bad font file fmt',
60: 'Device not a stream',
61: 'No data (for no delay io)',
62: 'Timer expired',
63: 'Out of streams resources',
64: 'Machine is not on the network',
65: 'Package not installed',
66: 'The object is remote',
67: 'The link has been severed',
68: 'Advertise error',
69: 'Srmount error',
70: 'Communication error on send',
71: 'Protocol error',
72: 'Multihop attempted',
73: 'Cross mount point (not really error)',
74: 'Trying to read unreadable message',
75: 'Value too large for defined data type',
76: 'Given log. name not unique',
77: 'f.d. invalid for this operation',
78: 'Remote address changed',
79: 'Can access a needed shared lib',
80: 'Accessing a corrupted shared lib',
81: '.lib section in a.out corrupted',
82: 'Attempting to link in too many libs',
83: 'Attempting to exec a shared library',
84: 'Illegal byte sequence',
86: 'Streams pipe error',
87: 'Too many users',
88: 'Socket operation on non-socket',
89: 'Destination address required',
90: 'Message too long',
91: 'Protocol wrong type for socket',
92: 'Protocol not available',
93: 'Unknown protocol',
94: 'Socket type not supported',
95: 'Not supported',
96: 'Protocol family not supported',
97: 'Address family not supported by protocol family',
98: 'Address already in use',
99: 'Address not available',
100: 'Network interface is not configured',
101: 'Network is unreachable',
102: 'Connection reset by network',
103: 'Connection aborted',
104: 'Connection reset by peer',
105: 'No buffer space available',
106: 'Socket is already connected',
107: 'Socket is not connected',
108: "Can't send after socket shutdown",
109: 'Too many references',
110: 'Connection timed out',
111: 'Connection refused',
112: 'Host is down',
113: 'Host is unreachable',
114: 'Socket already connected',
115: 'Connection already in progress',
116: 'Stale file handle',
122: 'Quota exceeded',
123: 'No medium (in tape drive)',
125: 'Operation canceled',
130: 'Previous owner died',
131: 'State not recoverable',
}

export function getErrnoMessage(errno?: number): string {
return (
ERRNO_CODES[-(errno as number) as keyof typeof ERRNO_CODES] ||
'Unknown error'
)
}

export function getExitCodeInfo(exitCode: number | null): string | undefined {
return EXIT_CODES[exitCode as keyof typeof EXIT_CODES]
}

export const getExitMessage = (
code: number | null,
signal: NodeJS.Signals | null,
stderr: string,
from: string
) => {
let message = `exit code: ${code}`
if (code != 0 || signal != null) {
message = `${stderr || '\n'} at ${from}`
message += `\n exit code: ${code}${
getExitCodeInfo(code) ? ' (' + getExitCodeInfo(code) + ')' : ''
}`
if (signal != null) {
message += `\n signal: ${signal}`
}
}

return message
}

export const getErrorMessage = (err: NodeJS.ErrnoException, from: string) => {
return (
`${err.message}\n` +
` errno: ${err.errno} (${getErrnoMessage(err.errno)})\n` +
` code: ${err.code}\n` +
` at ${from}`
)
}

export function getCallerLocation(err = new Error()) {
return getCallerLocationFromString(err.stack)
}

export function getCallerLocationFromString(stackString = 'unknown') {
return (
stackString
.split(/^\s*(at\s)?/m)
.filter((s) => s?.includes(':'))[2]
?.trim() || stackString
)
}
24 changes: 15 additions & 9 deletions src/main/ts/spawn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export type TSpawnResult = {
ctx: TSpawnCtxNormalized
error?: TSpawnError,
child?: TChild
stack: string
}

export type TSpawnListeners = {
Expand Down Expand Up @@ -77,6 +78,7 @@ export interface TSpawnCtxNormalized {
fulfilled?: TSpawnResult
error?: any
run: (cb: () => void, ctx: TSpawnCtxNormalized) => void
stack: string
}

export const defaults: TSpawnCtxNormalized = {
Expand All @@ -102,7 +104,8 @@ export const defaults: TSpawnCtxNormalized = {
get stdout(){ return new VoidStream() },
get stderr(){ return new VoidStream() },
stdio: ['pipe', 'pipe', 'pipe'],
run: immediate
run: immediate,
stack: ''
}

export const normalizeCtx = (...ctxs: TSpawnCtx[]): TSpawnCtxNormalized => assign({
Expand Down Expand Up @@ -184,7 +187,8 @@ export const invoke = (c: TSpawnCtxNormalized): TSpawnCtxNormalized => {
get stdall() { return c.store.stdall.join('') },
stdio,
duration: Date.now() - now,
ctx: c
stack: c.stack,
ctx: c
})
c.ee.emit('end', c.fulfilled, c)

Expand Down Expand Up @@ -238,7 +242,8 @@ export const invoke = (c: TSpawnCtxNormalized): TSpawnCtxNormalized => {
get stdall() { return c.store.stdall.join('') },
stdio,
duration: Date.now() - now,
ctx: c
stack: c.stack,
ctx: c
}
opts.signal?.removeEventListener('abort', onAbort)
c.callback(error, c.fulfilled)
Expand All @@ -251,14 +256,15 @@ export const invoke = (c: TSpawnCtxNormalized): TSpawnCtxNormalized => {
error,
c.fulfilled = {
error,
status: null,
signal: null,
stdout: '',
stderr: '',
stdall: '',
status: null,
signal: null,
stdout: '',
stderr: '',
stdall: '',
stdio,
duration: Date.now() - now,
ctx: c
stack: c.stack,
ctx: c
}
)
c.ee.emit('err', error, c)
Expand Down
1 change: 1 addition & 0 deletions src/main/ts/zurk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ class Zurk implements TZurk {
this.ctx.stdout,
this.ctx.stderr
]}
get stack() { return this.ctx.stack }
get duration() { return this.ctx.fulfilled?.duration ?? 0 }
toString(){ return this.stdall.trim() }
valueOf(){ return this.stdall.trim() }
Expand Down
6 changes: 5 additions & 1 deletion target/cjs/spawn.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ var defaults = {
return new VoidStream();
},
stdio: ["pipe", "pipe", "pipe"],
run: import_util.immediate
run: import_util.immediate,
stack: ""
};
var normalizeCtx = (...ctxs) => (0, import_util.assign)(
__spreadProps(__spreadValues({}, defaults), {
Expand Down Expand Up @@ -154,6 +155,7 @@ var invoke = (c) => {
},
stdio,
duration: Date.now() - now,
stack: c.stack,
ctx: c
}));
c.ee.emit("end", c.fulfilled, c);
Expand Down Expand Up @@ -208,6 +210,7 @@ var invoke = (c) => {
},
stdio,
duration: Date.now() - now,
stack: c.stack,
ctx: c
};
(_a3 = opts.signal) == null ? void 0 : _a3.removeEventListener("abort", onAbort);
Expand All @@ -228,6 +231,7 @@ var invoke = (c) => {
stdall: "",
stdio,
duration: Date.now() - now,
stack: c.stack,
ctx: c
}
);
Expand Down
3 changes: 3 additions & 0 deletions target/cjs/zurk.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ var Zurk = class {
this.ctx.stderr
];
}
get stack() {
return this.ctx.stack;
}
get duration() {
var _a2, _b;
return (_b = (_a2 = this.ctx.fulfilled) == null ? void 0 : _a2.duration) != null ? _b : 0;
Expand Down
Loading

0 comments on commit 98b3e77

Please sign in to comment.