directus
1/**
2* Call the passed function in a try-catch, and return the output wrapped in a state object.
3*
4* This is needed as isolated-vm doesn't allow the isolate to catch errors that are thrown in the
5* host. Instead, we'll wrap the output in a known shape which allows the isolated sdk context to
6* re-throw the error in the correct context.
7*
8* @see https://github.com/laverdet/isolated-vm/issues/417
9*/
10export function wrap(name: string, util: (...args: any[]) => any) {11return async (...args: any[]) => {12try {13return { result: await util(...args), error: false };14} catch (error) {15// isolated-vm expects objects thrown from within the vm to be an instance of `Error`16let result;17
18if (error instanceof Error) {19// Don't expose the stack trace to the vm20delete error.stack;21
22// Serialize the remaining error properties23for (const key of Object.getOwnPropertyNames(error)) {24const value = error[key as keyof typeof error];25
26if (!value || typeof value !== 'object') continue;27
28error[key as keyof typeof error] = JSON.stringify(value, getCircularReplacer());29}30
31result = error;32} else if (error && typeof error !== 'object') {33result = error;34} else {35result = new Error(`Unknown error in "${name}" Sandbox SDK function`);36}37
38return { result, error: true };39}40};41}
42
43function getCircularReplacer() {44const seen = new WeakSet();45
46return (_key: string, value: unknown) => {47if (value !== null && typeof value === 'object') {48if (seen.has(value)) {49return '[Circular]';50}51
52seen.add(value);53}54
55return value;56};57}
58