From a5fa9f9401a3ca669fb74a0ae3148c27a3cb2b3e Mon Sep 17 00:00:00 2001 From: csgulati09 Date: Fri, 3 Oct 2025 21:05:30 +0530 Subject: [PATCH 1/3] WIP: check for fs module --- src/apis/audio.ts | 18 +++++++++++++++--- src/client.ts | 2 ++ src/core.ts | 25 +++++++++++++++++++++++++ src/getAudioDuration.ts | 13 +++++++++---- 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/apis/audio.ts b/src/apis/audio.ts index 30f3b03..fc0533c 100644 --- a/src/apis/audio.ts +++ b/src/apis/audio.ts @@ -17,7 +17,7 @@ import { SpeechCreateParams } from 'openai/resources/audio/speech'; import { Stream } from '../streaming'; import { AUDIO_FILE_DURATION_HEADER } from '../constants'; import getAudioFileDuration from '../getAudioDuration'; -import { isRunningInBrowser } from '../core'; +import { isNode, isFsModuleAvailable } from '../core'; export class Audio extends ApiResource { transcriptions: transcriptions; @@ -78,7 +78,13 @@ export class transcriptions extends ApiResource { > { // @ts-ignore const path = body.file?.path; - if (path && this.client.calculateAudioDuration && !isRunningInBrowser()) { + // Use more robust environment detection for audio duration calculation + if ( + path && + this.client.calculateAudioDuration && + isNode() && + isFsModuleAvailable() + ) { const duration = await getAudioFileDuration(path); if (duration) { params = { @@ -110,7 +116,13 @@ export class translations extends ApiResource { ): Promise { const body: any = _body; const path = body.file?.path; - if (path && this.client.calculateAudioDuration && !isRunningInBrowser()) { + // Use more robust environment detection for audio duration calculation + if ( + path && + this.client.calculateAudioDuration && + isNode() && + isFsModuleAvailable() + ) { const duration = await getAudioFileDuration(path); if (duration) { params = { diff --git a/src/client.ts b/src/client.ts index e1830ca..c6ff19d 100644 --- a/src/client.ts +++ b/src/client.ts @@ -95,6 +95,8 @@ export class Portkey extends ApiClient { calculateAudioDuration, ...rest }: ApiClientInterface) { + // Security check: Use isRunningInBrowser() to err on the side of caution + // This prevents API key exposure even in environments with browser-like polyfills if (isRunningInBrowser() && !dangerouslyAllowBrowser) { throw new Error( "It looks like you're running in a browser-like environment.\n\nThis is disabled by default, as it risks exposing your secret API credentials to attackers.\nIf you understand the risks and have appropriate mitigations in place,\nyou can set the `dangerouslyAllowBrowser` option to `true`, e.g.,\n\nnew Portkey({ ..., dangerouslyAllowBrowser: true, ... });" diff --git a/src/core.ts b/src/core.ts index dd62504..e44abce 100644 --- a/src/core.ts +++ b/src/core.ts @@ -59,3 +59,28 @@ export const isRunningInBrowser = () => { typeof navigator !== 'undefined' ); }; + +/** + * Check if running in Node.js environment + * More reliable than isRunningInBrowser() when polyfills are present + */ +export const isNode = () => { + return ( + typeof process !== 'undefined' && + typeof process.versions !== 'undefined' && + typeof process.versions.node !== 'undefined' + ); +}; + +/** + * Check if fs module is available + * Useful for determining if file system operations are possible + */ +export const isFsModuleAvailable = () => { + try { + require('fs'); + return true; + } catch (e) { + return false; + } +}; diff --git a/src/getAudioDuration.ts b/src/getAudioDuration.ts index 49d75a6..1e0ccf3 100644 --- a/src/getAudioDuration.ts +++ b/src/getAudioDuration.ts @@ -1,6 +1,7 @@ -import { isRunningInBrowser } from './core'; +import { isNode, isFsModuleAvailable } from './core'; -const isBrowser = isRunningInBrowser(); +const isNodeEnv = isNode(); +const fsAvailable = isFsModuleAvailable(); let fs: any; let open: any; @@ -8,7 +9,9 @@ let read: any; let stat: any; let close: any; -if (!isBrowser) { +// Use more robust environment detection +// Check if we're in Node.js AND fs module is available +if (isNodeEnv && fsAvailable) { try { fs = require('fs'); const { promisify } = require('util'); @@ -27,7 +30,9 @@ if (!isBrowser) { * Uses optimized file reading to avoid loading entire files into memory */ async function getAudioFileDuration(filePath: string): Promise { - if (isBrowser || !fs) { + // Use more robust environment detection + // Only proceed if we're in Node.js, fs is available, and fs module loaded successfully + if (!isNodeEnv || !fsAvailable || !fs) { return null; } From e7143305a9058280db116fbbbd1006f2f8c500fc Mon Sep 17 00:00:00 2001 From: csgulati09 Date: Sun, 5 Oct 2025 16:20:25 +0530 Subject: [PATCH 2/3] feat: clean up --- src/apis/audio.ts | 4 ++-- src/client.ts | 2 -- src/core.ts | 8 -------- src/getAudioDuration.ts | 2 -- 4 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/apis/audio.ts b/src/apis/audio.ts index fc0533c..2e61e25 100644 --- a/src/apis/audio.ts +++ b/src/apis/audio.ts @@ -78,7 +78,7 @@ export class transcriptions extends ApiResource { > { // @ts-ignore const path = body.file?.path; - // Use more robust environment detection for audio duration calculation + if ( path && this.client.calculateAudioDuration && @@ -116,7 +116,7 @@ export class translations extends ApiResource { ): Promise { const body: any = _body; const path = body.file?.path; - // Use more robust environment detection for audio duration calculation + if ( path && this.client.calculateAudioDuration && diff --git a/src/client.ts b/src/client.ts index c6ff19d..e1830ca 100644 --- a/src/client.ts +++ b/src/client.ts @@ -95,8 +95,6 @@ export class Portkey extends ApiClient { calculateAudioDuration, ...rest }: ApiClientInterface) { - // Security check: Use isRunningInBrowser() to err on the side of caution - // This prevents API key exposure even in environments with browser-like polyfills if (isRunningInBrowser() && !dangerouslyAllowBrowser) { throw new Error( "It looks like you're running in a browser-like environment.\n\nThis is disabled by default, as it risks exposing your secret API credentials to attackers.\nIf you understand the risks and have appropriate mitigations in place,\nyou can set the `dangerouslyAllowBrowser` option to `true`, e.g.,\n\nnew Portkey({ ..., dangerouslyAllowBrowser: true, ... });" diff --git a/src/core.ts b/src/core.ts index e44abce..c4b9768 100644 --- a/src/core.ts +++ b/src/core.ts @@ -60,10 +60,6 @@ export const isRunningInBrowser = () => { ); }; -/** - * Check if running in Node.js environment - * More reliable than isRunningInBrowser() when polyfills are present - */ export const isNode = () => { return ( typeof process !== 'undefined' && @@ -72,10 +68,6 @@ export const isNode = () => { ); }; -/** - * Check if fs module is available - * Useful for determining if file system operations are possible - */ export const isFsModuleAvailable = () => { try { require('fs'); diff --git a/src/getAudioDuration.ts b/src/getAudioDuration.ts index 1e0ccf3..74b3c9a 100644 --- a/src/getAudioDuration.ts +++ b/src/getAudioDuration.ts @@ -9,7 +9,6 @@ let read: any; let stat: any; let close: any; -// Use more robust environment detection // Check if we're in Node.js AND fs module is available if (isNodeEnv && fsAvailable) { try { @@ -30,7 +29,6 @@ if (isNodeEnv && fsAvailable) { * Uses optimized file reading to avoid loading entire files into memory */ async function getAudioFileDuration(filePath: string): Promise { - // Use more robust environment detection // Only proceed if we're in Node.js, fs is available, and fs module loaded successfully if (!isNodeEnv || !fsAvailable || !fs) { return null; From 6dbc50cd139644504e19207625f2224f4569f1ba Mon Sep 17 00:00:00 2001 From: csgulati09 Date: Mon, 6 Oct 2025 16:32:13 +0530 Subject: [PATCH 3/3] feat: only fs modiule check --- src/apis/audio.ts | 16 +++------------- src/core.ts | 8 -------- src/getAudioDuration.ts | 7 +++---- 3 files changed, 6 insertions(+), 25 deletions(-) diff --git a/src/apis/audio.ts b/src/apis/audio.ts index 2e61e25..ddd403c 100644 --- a/src/apis/audio.ts +++ b/src/apis/audio.ts @@ -17,7 +17,7 @@ import { SpeechCreateParams } from 'openai/resources/audio/speech'; import { Stream } from '../streaming'; import { AUDIO_FILE_DURATION_HEADER } from '../constants'; import getAudioFileDuration from '../getAudioDuration'; -import { isNode, isFsModuleAvailable } from '../core'; +import { isFsModuleAvailable } from '../core'; export class Audio extends ApiResource { transcriptions: transcriptions; @@ -79,12 +79,7 @@ export class transcriptions extends ApiResource { // @ts-ignore const path = body.file?.path; - if ( - path && - this.client.calculateAudioDuration && - isNode() && - isFsModuleAvailable() - ) { + if (path && this.client.calculateAudioDuration && isFsModuleAvailable()) { const duration = await getAudioFileDuration(path); if (duration) { params = { @@ -117,12 +112,7 @@ export class translations extends ApiResource { const body: any = _body; const path = body.file?.path; - if ( - path && - this.client.calculateAudioDuration && - isNode() && - isFsModuleAvailable() - ) { + if (path && this.client.calculateAudioDuration && isFsModuleAvailable()) { const duration = await getAudioFileDuration(path); if (duration) { params = { diff --git a/src/core.ts b/src/core.ts index c4b9768..316baec 100644 --- a/src/core.ts +++ b/src/core.ts @@ -60,14 +60,6 @@ export const isRunningInBrowser = () => { ); }; -export const isNode = () => { - return ( - typeof process !== 'undefined' && - typeof process.versions !== 'undefined' && - typeof process.versions.node !== 'undefined' - ); -}; - export const isFsModuleAvailable = () => { try { require('fs'); diff --git a/src/getAudioDuration.ts b/src/getAudioDuration.ts index 74b3c9a..c75fd29 100644 --- a/src/getAudioDuration.ts +++ b/src/getAudioDuration.ts @@ -1,6 +1,5 @@ -import { isNode, isFsModuleAvailable } from './core'; +import { isFsModuleAvailable } from './core'; -const isNodeEnv = isNode(); const fsAvailable = isFsModuleAvailable(); let fs: any; @@ -10,7 +9,7 @@ let stat: any; let close: any; // Check if we're in Node.js AND fs module is available -if (isNodeEnv && fsAvailable) { +if (fsAvailable) { try { fs = require('fs'); const { promisify } = require('util'); @@ -30,7 +29,7 @@ if (isNodeEnv && fsAvailable) { */ async function getAudioFileDuration(filePath: string): Promise { // Only proceed if we're in Node.js, fs is available, and fs module loaded successfully - if (!isNodeEnv || !fsAvailable || !fs) { + if (!fsAvailable || !fs) { return null; }