Skip to content

Commit

Permalink
fix: Added dangerouslyAllowBrowser
Browse files Browse the repository at this point in the history
  • Loading branch information
asafgardin committed Nov 15, 2024
1 parent 4357ef5 commit cf5aa90
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 6 deletions.
19 changes: 15 additions & 4 deletions src/AI21.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import * as Types from './types';
import { AI21EnvConfig } from './EnvConfig';
import { MissingAPIKeyError } from './errors';
import { AI21Error, MissingAPIKeyError } from './errors';
import { Chat } from './resources/chat';
import { APIClient } from './APIClient';
import { Headers } from './types';
import * as Runtime from './runtime';

export type ClientOptions = {
export interface ClientOptions {
baseURL?: string;
apiKey?: string;
maxRetries?: number;
timeout?: number;
via?: string | null;
defaultHeaders?: Headers;
/**
* By default, using this library on the client side is prohibited to prevent exposing your secret API credentials to potential attackers.
* Only enable this option by setting it to `true` if you fully understand the risks and have implemented appropriate security measures.
*/
dangerouslyAllowBrowser?: boolean;
};
}

export class AI21 extends APIClient {
protected options: ClientOptions;
Expand All @@ -27,7 +32,7 @@ export class AI21 extends APIClient {
maxRetries,
via,
...opts
}: ClientOptions) {
}: ClientOptions = {}) {
const options: ClientOptions = {
apiKey,
baseURL,
Expand All @@ -37,6 +42,12 @@ export class AI21 extends APIClient {
...opts,
};

if (!options.dangerouslyAllowBrowser && Runtime.isBrowser) {
throw new AI21Error(
'AI21 client is not supported in the browser by default due to potential API key exposure. Use `dangerouslyAllowBrowser` option to `true` to override it.',
);
}

super({
baseURL,
timeout,
Expand Down
9 changes: 7 additions & 2 deletions tests/AI21.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AI21, ClientOptions } from '../src/AI21';
import { MissingAPIKeyError } from '../src/errors';
import { AI21Error, MissingAPIKeyError } from '../src/errors';
import { Chat } from '../src/resources/chat';

describe('AI21', () => {
Expand All @@ -8,11 +8,12 @@ describe('AI21', () => {
apiKey: mockApiKey,
baseURL: 'https://some-url/v1',
timeout: 600,
dangerouslyAllowBrowser: true, // Test env is in the browser and we need to allow it
};

describe('constructor', () => {
it('should initialize with default options', () => {
const client = new AI21({ apiKey: mockApiKey });
const client = new AI21({ apiKey: mockApiKey, dangerouslyAllowBrowser: true });
expect(client).toBeInstanceOf(AI21);
expect(client.chat).toBeInstanceOf(Chat);
});
Expand All @@ -21,6 +22,10 @@ describe('AI21', () => {
expect(() => new AI21({apiKey: undefined} as ClientOptions)).toThrow(MissingAPIKeyError);
});

it('should throw AI21Error when browser is detected without dangerouslyAllowBrowser option', () => {
expect(() => new AI21({...defaultOptions, dangerouslyAllowBrowser: false})).toThrow(AI21Error);
});

it('should initialize with custom options', () => {
const customOptions: ClientOptions = {
...defaultOptions,
Expand Down

0 comments on commit cf5aa90

Please sign in to comment.