1
import type { ExtensionSandboxRequestedScopes } from '@directus/extensions';
2
import { numberGenerator } from '@directus/utils';
3
import type { Isolate, Module } from 'isolated-vm';
4
import { generateHostFunctionReference } from '../generate-host-function-reference.js';
5
import { getSdk } from './sdk.js';
6
import { wrap } from './utils/wrap.js';
9
* Creates a new isolate context, generates the sandbox SDK, and returns an isolate Module with the
10
* SDK included in it's global scope
12
* @param isolate - Existing isolate in which to inject the SDK globally
13
* @param requestedScopes - Permissions as requested by the extension to generate the SDK for
14
* @returns Isolate module with SDK available in it's global scope
16
export async function instantiateSandboxSdk(
18
requestedScopes: ExtensionSandboxRequestedScopes,
20
const apiContext = await isolate.createContext();
22
await apiContext.global.set('sdk', apiContext.global.derefInto());
24
const index = numberGenerator();
27
const handlerCode = sdk
28
.map(({ name, args, async }) => `sdk.${name} = ${generateHostFunctionReference(index, args, { async })}`)
31
await apiContext.evalClosure(
33
sdk.map(({ name, generator, async }) =>
34
async ? wrap(name, generator(requestedScopes)) : generator(requestedScopes),
36
{ filename: '<extensions-sdk>', arguments: { reference: true } },
39
const exportCode = sdk.map(({ name }) => `export const ${name} = sdk.${name};`).join('\n');
41
const apiModule = await isolate.compileModule(exportCode);
43
await apiModule.instantiate(apiContext, () => {