Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enabled 3rd party imports #46

Merged
merged 4 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/pretty-countries-look.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@chainlink/functions-toolkit': patch
---

Added support for 3rd party imports in the simulator
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,17 @@ const result = await simulateScript({
}
```

Any 3rd party imports used in the JavaScript source code are loaded asynchronously at runtime. Therefore, to use 3rd party imports in the source code that is executed by the `simulateScript` function, you must use the async `import` function as shown in the examples below.

```
const { format } = await import("npm:date-fns");
return Functions.encodeString(format(new Date(), "yyyy-MM-dd"));
```
```
const { escape } = await import("https://deno.land/std/regexp/mod.ts");
return Functions.encodeString(escape("$hello*world?"));
```

**_NOTE:_** When running `simulateScript`, depending on your security settings, you may get a popup asking if you would like to accept incoming network connections. You can safely accept or ignore this popup and it should disappear when the simulation is complete.

**_NOTE:_** The `simulateScript` function is a debugging tool and hence is not a perfect representation of the actual Chainlink oracle execution environment. Therefore, it is important to make a Functions request on a supported testnet blockchain before mainnet usage.
Expand Down
2 changes: 0 additions & 2 deletions src/simulateScript/simulateScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,6 @@ export const simulateScript = async ({
const simulation = spawn('deno', [
'run',
'--no-prompt',
'--no-npm',
'--no-remote',
`--v8-flags=--max-old-space-size=${maxMemoryUsageMb}`,
'--allow-net',
scriptPath,
Expand Down
37 changes: 22 additions & 15 deletions test/unit/simulateScript.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,21 +207,6 @@ describe('simulateScript', () => {
expect(result).toEqual(expected)
})

it('should capture import error', async () => {
const result = await simulateScript({
source: 'const http = await import("https://deno.land/std/http/mod.ts");',
maxExecutionTimeMs: 100,
})

const expected = {
capturedTerminalOutput: '',
errorString:
'A remote specifier was requested: "https://deno.land/std/http/mod.ts", but --no-remote is specified.',
}

expect(result).toEqual(expected)
})

it('should capture permissions error', async () => {
const result = await simulateScript({
source: "Deno.openSync('test.txt')",
Expand Down Expand Up @@ -296,6 +281,28 @@ describe('simulateScript', () => {

await expect(result).rejects.toThrow('bytesArgs param contains invalid hex string')
})

it('should allow 3rd party imports', async () => {
const result = await simulateScript({
source:
'const { escape } = await import("https://deno.land/std/regexp/mod.ts"); return Functions.encodeString(escape("$hello*world?"));',
})

expect(result.responseBytesHexstring).toEqual(
`0x${Buffer.from('\\$hello\\*world\\?').toString('hex')}`,
)
})

it('should allow NPM imports', async () => {
const result = await simulateScript({
source:
'const { format } = await import("npm:date-fns"); return Functions.encodeString(format(new Date(), "yyyy-MM-dd"));',
})

expect(Buffer.from(result.responseBytesHexstring?.slice(2) as string, 'hex').length).toEqual(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we be testing that the import works as expected by asserting against the value of the result hex versus the length of the hex?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the import doesn't work, then this whole this will just throw an error, so I don't think this is needed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KuphJr sorry wasnt clear- - was suggesting an alternate assert on this existing test

10,
)
})
})
})

Expand Down