simonj
09/19/2025, 4:21 PMvmContext and the package.json and esbuild-script.mjs from the examples/medplum-demo-bots to build and deploy bots locally with the CLI.
All works well with a simple hello world ✅
But when I include and call the AWS SDK (see below), it builds and deploys OK but I get the error Error: process is not defined when I run it from the CLI or medplum UI ❌
However, if I make an edit from the medplum UI and deploy and execute it, it works ✅
I don't know a whole lot about JS packaging and modules etc and I'm not fully across everything that's going on in the esbuild-script.mjs from the medplum example - do I need to polyfill somehow in the build script because there's no node process available?
Is there a standard script/approach to this?
Any help would be great
Thanks!
import { MedplumClient } from '@medplum/core';
import { OperationOutcome } from '@medplum/fhirtypes';
import { LambdaClient, InvokeCommand, InvokeCommandInput } from '@aws-sdk/client-lambda';
export async function handler(medplum: MedplumClient, event: any): Promise<OperationOutcome> {
const lambdaClient = new LambdaClient({
region: 'us-east-1',
credentials: { accessKeyId: '...', secretAccessKey: '...' },
});
const invokeParams: InvokeCommandInput = {
FunctionName: 'my_function',
InvocationType: 'RequestResponse',
Payload: JSON.stringify({
key1: 'value1',
}),
};
const lambdaResponse = await lambdaClient.send(new InvokeCommand(invokeParams));
console.log(lambdaResponse);
console.log('Hello World!');
return {
resourceType: 'OperationOutcome',
issue: [{ severity: 'information', code: 'informational', details: { text: 'Hello World!' } }],
} as OperationOutcome;
}
{
"bots": [
{
"name": "bot-aws-test",
"id": "662363f7-1aae-43c0-bc1d-9b5a8640538a",
"source": "src/bot-aws-test.ts",
"dist": "dist/bot-aws-test.js"
}
]
}cody
09/20/2025, 1:28 AMprocess is not included in the VMContext sandbox. You can see the exported values here: https://github.com/medplum/medplum/blob/main/packages/server/src/bots/vmcontext.ts#L50-L72
I filed a tracking ticket here: https://github.com/medplum/medplum/issues/7427
This would be an excellent first issue for an aspiring contributor, just need to add the token process to an array!simonj
09/20/2025, 1:53 PMprocess to get the AWS SDK running in the sandbox, but once I added them all (below) it worked 🎉
IMHO calling AWS SDK in bots should be a supported design pattern (eg our next bot uses SQS) so if it's OK to add the additional 6 functions to the sandbox I'll open a new ticket with a more appropriate title and can submit a PR.
My final question: do you have any idea why it was working if I copied/pasted the code into the Meplum bot editor UI then clicked the deploy and execute buttons 🤔 ? Is there something special that happens with the medplum bot build process that doesn't happen with the examples/medplum-demo-bots IDE build? It would be great to have them consistent
const sandbox = {
// required for AWS SDK
process,
setTimeout,
clearTimeout,
Buffer,
setInterval,
clearInterval,
...cody
09/20/2025, 5:04 PMmedplum-demo-bots package uses esbuild to compile the TypeScript to CommonJS
2. The Bot Editor UI uses the Monaco Editor / TypeScript sandbox (https://www.typescriptlang.org/dev/sandbox/)
In theory, those should produce roughly the same code, but that obviously didn't happen in this case. It's possible that the TypeScript sandbox build tool added a process shim, or transpiled the calling code away somehow.
Do you have a minimal bot example you can share? We can take a look at the CommonJS output of the 2 different lows, and see if there's a clean way to update the esbuild code to align them.simonj
09/21/2025, 7:43 PMcody
09/21/2025, 10:08 PMesbuild will bundle any dependency that is not marked as external into the output. So, before, the entire @aws-sdk/client-lambda was included in the build output 😱
On the other hand, the Bot Editor / Monaco Editor / TypeScript Sandbox uses the opposite default, and assumes all dependencies are external, so does not bundle anything.
The reason that works is because AWS Lambdas already include most client SDKs in the base image, so you don't need to install them or inline them, they're just already there.
As a fix, I updated our build script to mark '@aws-sdk/client-*' as external. That's not a perfect solution (depending on which SDK and which runtime environment, you may want different behavior). But this is a better default, and anything other than this would be a pretty advanced configuration.
Interesting follow-up question: Why does process matter here? Well, the inline code did not have access to process, but when the code calls require, that is a new context, and then it inherits it. That's a kinda wonky setup, but it works.
I think adding process to the vmcontext sandbox is still the right call, and we should still do it.
Overall, this is a great find. Thanks @simonj !simonj
09/22/2025, 3:35 AM