I am working with a javascript library that uses global.crypto, for example, makes a call to global.crypto.getRandomValues(). I want to use the library from the command line (1) for testing my scripts and knowledge, (2) perhaps for back-end code.
How can I make the global.crypto API available to that module from the command line?
Working example:
library.js:
export function getUUID() {
return crypto.randomUUID();
}
main.js:
import { getUUID } from "./library.js";
console.log(getUUID());
index.html:
<!DOCTYPE html>
<html>
<body>
<script type="module" src="main.js"></script>
</body>
</html>
Opening index.html from localhost writes a UUID to the console, but running "node main.js" gives
file:/.../library.js:2
return crypto.randomUUID();
^
ReferenceError: crypto is not defined
at getUUID (file:/.../library.js:2:3)
at file:/.../main.js:3:13
at ModuleJob.run (node:internal/modules/esm/module_job:195:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:337:24)
at async loadESM (node:internal/process/esm_loader:88:5)
at async handleMainPromise (node:internal/modules/run_main:61:12)
Edit based on tobiv's answer, here is a solution that works for me, however, may not be best practice? Note that I'm hoping not to edit the library file itself.
main.js (updated)
import * as crypto from 'crypto';
global.crypto = crypto.webcrypto;
import { getUUID } from "./library.js";
console.log(getUUID());
Now running "node main.js" correctly prints a UUID. And if I comment out the first two lines of main.js, I get a version that works in the browser.
Or for CommonJS and the library I'm actually using:
const crypto = require('node:crypto').webcrypto;
global.crypto = crypto;
const library = require("browser-passworder");
console.log(library.generateSalt());
I'm a bit concerned about robustness here if modules load asynchronously, but it's the best solution I've found.