From a526d41e893b34b26c5d909d98c56f219be194e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jind=C5=99ich=20B=C3=A4r?= Date: Tue, 18 Nov 2025 11:44:52 +0100 Subject: [PATCH 1/3] fix: use `require` for `SubtleCrypto` in older Node.JS versions --- packages/utilities/src/hmac.ts | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/utilities/src/hmac.ts b/packages/utilities/src/hmac.ts index 921b7983..c34d6707 100644 --- a/packages/utilities/src/hmac.ts +++ b/packages/utilities/src/hmac.ts @@ -37,11 +37,21 @@ export function createHmacSignature(secretKey: string, message: string): string return encodeBase62(BigInt(`0x${signature}`)); } -let webcrypto = globalThis.crypto?.subtle; +let subtleCrypto = globalThis.crypto?.subtle; -async function ensureCryptoSubtleExists() { - // this might happen in Node.js versions < 19 - webcrypto ??= (await import('node:crypto')).webcrypto.subtle as typeof webcrypto; +function ensureSubtleCryptoExists() { + if (!subtleCrypto) { + if (require) { + // eslint-disable-next-line @typescript-eslint/no-require-imports, global-require -- Backward compatibility for Node.js versions < 19 + subtleCrypto = require('node:crypto')?.webcrypto.subtle; + } + + if (!subtleCrypto) { + throw new Error(`SubtleCrypto is not available in this environment. +Please ensure you're running in an environment that supports Web Crypto API, +or submit an issue to https://github.com/apify/apify-shared-js so we can help you further.`); + } + } } /** @@ -53,10 +63,10 @@ async function ensureCryptoSubtleExists() { * @returns Promise */ export async function createHmacSignatureAsync(secretKey: string, message: string): Promise { - await ensureCryptoSubtleExists(); + ensureSubtleCryptoExists(); const encoder = new TextEncoder(); - const key = await webcrypto.importKey( + const key = await subtleCrypto.importKey( 'raw', encoder.encode(secretKey), { name: 'HMAC', hash: 'SHA-256' }, @@ -64,7 +74,7 @@ export async function createHmacSignatureAsync(secretKey: string, message: strin ['sign'], ); - const signatureBuffer = await webcrypto.sign( + const signatureBuffer = await subtleCrypto.sign( 'HMAC', key, encoder.encode(message), From 48cb7b5b541347dbcd749b923534e3483ee7a910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jind=C5=99ich=20B=C3=A4r?= Date: Tue, 18 Nov 2025 12:19:29 +0100 Subject: [PATCH 2/3] chore: keep async `import` call for non-node environments --- packages/utilities/src/hmac.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/utilities/src/hmac.ts b/packages/utilities/src/hmac.ts index c34d6707..873ad392 100644 --- a/packages/utilities/src/hmac.ts +++ b/packages/utilities/src/hmac.ts @@ -39,11 +39,13 @@ export function createHmacSignature(secretKey: string, message: string): string let subtleCrypto = globalThis.crypto?.subtle; -function ensureSubtleCryptoExists() { +async function ensureSubtleCryptoExists() { if (!subtleCrypto) { if (require) { // eslint-disable-next-line @typescript-eslint/no-require-imports, global-require -- Backward compatibility for Node.js versions < 19 - subtleCrypto = require('node:crypto')?.webcrypto.subtle; + subtleCrypto = require('node:crypto')?.webcrypto?.subtle; + } else { + subtleCrypto = (await import('node:crypto'))?.webcrypto?.subtle as SubtleCrypto; } if (!subtleCrypto) { @@ -63,7 +65,7 @@ or submit an issue to https://github.com/apify/apify-shared-js so we can help yo * @returns Promise */ export async function createHmacSignatureAsync(secretKey: string, message: string): Promise { - ensureSubtleCryptoExists(); + await ensureSubtleCryptoExists(); const encoder = new TextEncoder(); const key = await subtleCrypto.importKey( From 6ec5c89a3eeb3c24d5d72aa7edd500064a1319db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jind=C5=99ich=20B=C3=A4r?= Date: Tue, 18 Nov 2025 12:30:56 +0100 Subject: [PATCH 3/3] chore: use `global.require` explicitly --- packages/utilities/src/hmac.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/utilities/src/hmac.ts b/packages/utilities/src/hmac.ts index 873ad392..3784a308 100644 --- a/packages/utilities/src/hmac.ts +++ b/packages/utilities/src/hmac.ts @@ -41,9 +41,8 @@ let subtleCrypto = globalThis.crypto?.subtle; async function ensureSubtleCryptoExists() { if (!subtleCrypto) { - if (require) { - // eslint-disable-next-line @typescript-eslint/no-require-imports, global-require -- Backward compatibility for Node.js versions < 19 - subtleCrypto = require('node:crypto')?.webcrypto?.subtle; + if (globalThis.require) { + subtleCrypto = globalThis.require('node:crypto')?.webcrypto?.subtle; } else { subtleCrypto = (await import('node:crypto'))?.webcrypto?.subtle as SubtleCrypto; }