Skip to content

Commit de06c26

Browse files
feat: Support custom Agent in Typescript (box/box-codegen#452) (#117)
1 parent 2da73ee commit de06c26

10 files changed

+78
-4
lines changed

.codegen.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ "engineHash": "3970588", "specHash": "d50ab5f", "version": "0.5.1" }
1+
{ "engineHash": "0d4bf53", "specHash": "d50ab5f", "version": "0.5.1" }

docs/client.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,17 @@ const newClient = client.withCustomBaseUrls({
7777
});
7878
```
7979

80+
# Custom Agent Options
81+
82+
You can also specify the custom agent options, which will be used for API calls made by client.
83+
Calling the `client.withCustomAgentOptions()` method creates a new client, leaving the original client unmodified.
84+
85+
```js
86+
const options: AgentOptions = {};
87+
88+
const newClient = client.withCustomAgentOptions(options);
89+
```
90+
8091
# Interceptors
8192

8293
You can specify custom interceptors - methods that will be called just before making a request and right after

jest.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ module.exports = {
1717
],
1818
},
1919
moduleNameMapper: {
20-
'^(..?/.+).jsx?$': '$1',
20+
'^(..?/.+)\\.jsx?$': '$1',
2121
},
2222
clearMocks: true,
2323
setupFilesAfterEnv: ['<rootDir>/setup-jest.js'],

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@
3131
"buffer": "^6.0.3",
3232
"jose": "^5.2.2",
3333
"tslib": "^2.6.2",
34-
"uuid": "^9.0.0"
34+
"uuid": "^9.0.0",
35+
"proxy-agent": "^6.4.0"
3536
},
3637
"devDependencies": {
3738
"@rollup/plugin-commonjs": "^25.0.7",
39+
"@rollup/plugin-json": "^6.1.0",
3840
"@rollup/plugin-node-resolve": "^15.2.3",
3941
"@rollup/plugin-typescript": "^11.1.5",
4042
"@types/jest": "^29.5.1",

rollup.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ exports.default = {
1616
require('@rollup/plugin-typescript')({
1717
tsconfig: './tsconfig.rollup.json',
1818
}), // Compiles TypeScript
19+
require('@rollup/plugin-json')(), // Converts JSON files to ES6 modules
1920
],
2021
};

src/client.generated.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ import { IntegrationMappingsManager } from './managers/integrationMappings.gener
7171
import { Authentication } from './networking/auth.generated.js';
7272
import { NetworkSession } from './networking/network.generated.js';
7373
import { BaseUrls } from './networking/baseUrls.generated.js';
74+
import { AgentOptions } from './internal/utils.js';
7475
import { Interceptor } from './networking/interceptors.generated.js';
7576
import { SerializedData } from './serialization/json.js';
7677
import { sdIsEmpty } from './serialization/json.js';
@@ -229,6 +230,7 @@ export class BoxClient {
229230
| 'withSuppressedNotifications'
230231
| 'withExtraHeaders'
231232
| 'withCustomBaseUrls'
233+
| 'withCustomAgentOptions'
232234
| 'withInterceptors'
233235
>
234236
| Partial<Pick<BoxClient, 'networkSession'>>
@@ -545,6 +547,12 @@ export class BoxClient {
545547
networkSession: this.networkSession.withCustomBaseUrls(baseUrls),
546548
});
547549
}
550+
withCustomAgentOptions(agentOptions: AgentOptions): BoxClient {
551+
return new BoxClient({
552+
auth: this.auth,
553+
networkSession: this.networkSession.withCustomAgentOptions(agentOptions),
554+
});
555+
}
548556
withInterceptors(interceptors: readonly Interceptor[]): BoxClient {
549557
return new BoxClient({
550558
auth: this.auth,

src/internal/utils.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ export function hexToBase64(data: string): string {
2424
export { Buffer, Readable as ByteStream };
2525
export type { CancellationToken };
2626
export type Iterator<T = any> = AsyncIterator<T>;
27+
export type AgentOptions = any;
28+
export type Agent = any;
2729

2830
// Function to convert a hexadecimal string to base64
2931
export function hexStrToBase64(hex: string) {
@@ -322,3 +324,14 @@ export function readTextFromFile(filepath: string): string {
322324
export function getEpochTimeInSeconds(): number {
323325
return Math.floor(Date.now() / 1000);
324326
}
327+
328+
/**
329+
* Create web agent from proxy agent options.
330+
*/
331+
export function createAgent(options?: AgentOptions): Agent {
332+
if (isBrowser()) {
333+
return undefined;
334+
}
335+
const ProxyAgent = eval('require')('proxy-agent').ProxyAgent;
336+
return options ? new ProxyAgent(options) : new ProxyAgent();
337+
}

src/networking/fetch.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ async function createRequestInit(options: FetchOptions): Promise<RequestInit> {
196196
},
197197
body,
198198
signal: options.cancellationToken as RequestInit['signal'],
199+
agent: options.networkSession?.agent,
199200
};
200201
}
201202

src/networking/network.generated.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,31 @@
11
import { BaseUrls } from './baseUrls.generated.js';
22
import { Interceptor } from './interceptors.generated.js';
3+
import { Agent } from '../internal/utils.js';
4+
import { AgentOptions } from '../internal/utils.js';
5+
import { createAgent } from '../internal/utils.js';
36
export class NetworkSession {
47
readonly additionalHeaders: {
58
readonly [key: string]: string;
69
} = {};
710
readonly baseUrls!: BaseUrls;
811
readonly interceptors: readonly Interceptor[] = [];
12+
readonly agent: Agent = createAgent(void 0);
13+
readonly agentOptions?: AgentOptions;
914
constructor(
1015
fields:
1116
| Omit<
1217
NetworkSession,
1318
| 'additionalHeaders'
1419
| 'interceptors'
20+
| 'agent'
1521
| 'withAdditionalHeaders'
1622
| 'withCustomBaseUrls'
23+
| 'withCustomAgentOptions'
1724
| 'withInterceptors'
1825
>
19-
| Partial<Pick<NetworkSession, 'additionalHeaders' | 'interceptors'>>
26+
| Partial<
27+
Pick<NetworkSession, 'additionalHeaders' | 'interceptors' | 'agent'>
28+
>
2029
) {
2130
Object.assign(this, fields);
2231
}
@@ -29,20 +38,35 @@ export class NetworkSession {
2938
additionalHeaders: { ...this.additionalHeaders, ...additionalHeaders },
3039
baseUrls: this.baseUrls,
3140
interceptors: this.interceptors,
41+
agent: this.agent,
42+
agentOptions: this.agentOptions,
3243
});
3344
}
3445
withCustomBaseUrls(baseUrls: BaseUrls): NetworkSession {
3546
return new NetworkSession({
3647
additionalHeaders: this.additionalHeaders,
3748
baseUrls: baseUrls,
3849
interceptors: this.interceptors,
50+
agent: this.agent,
51+
agentOptions: this.agentOptions,
52+
});
53+
}
54+
withCustomAgentOptions(agentOptions: AgentOptions): NetworkSession {
55+
return new NetworkSession({
56+
additionalHeaders: this.additionalHeaders,
57+
baseUrls: this.baseUrls,
58+
interceptors: this.interceptors,
59+
agent: createAgent(agentOptions),
60+
agentOptions: this.agentOptions,
3961
});
4062
}
4163
withInterceptors(interceptors: readonly Interceptor[]): NetworkSession {
4264
return new NetworkSession({
4365
additionalHeaders: this.additionalHeaders,
4466
baseUrls: this.baseUrls,
4567
interceptors: this.interceptors.concat(interceptors),
68+
agent: this.agent,
69+
agentOptions: this.agentOptions,
4670
});
4771
}
4872
}

src/test/client.generated.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { serializeUserFull } from '../schemas.generated.js';
22
import { deserializeUserFull } from '../schemas.generated.js';
33
import { serializeCreateUserRequestBody } from '../managers/users.generated.js';
44
import { deserializeCreateUserRequestBody } from '../managers/users.generated.js';
5+
import { serializeBaseUrls } from '../networking/baseUrls.generated.js';
6+
import { deserializeBaseUrls } from '../networking/baseUrls.generated.js';
57
import { BoxClient } from '../client.generated.js';
68
import { UserFull } from '../schemas.generated.js';
79
import { CreateUserRequestBody } from '../managers/users.generated.js';
@@ -10,6 +12,7 @@ import { getUuid } from '../internal/utils.js';
1012
import { getDefaultClient } from './commons.generated.js';
1113
import { FetchOptions } from '../networking/fetch.js';
1214
import { FetchResponse } from '../networking/fetch.js';
15+
import { BaseUrls } from '../networking/baseUrls.generated.js';
1316
import { toString } from '../internal/utils.js';
1417
import { sdToJson } from '../serialization/json.js';
1518
import { jsonToSerializedData } from '../serialization/json.js';
@@ -64,6 +67,17 @@ test('testWithExtraHeaders', async function testWithExtraHeaders(): Promise<any>
6467
}
6568
await client.users.deleteUserById(createdUser.id);
6669
});
70+
test('testWithCustomBaseUrls', async function testWithCustomBaseUrls(): Promise<any> {
71+
const newBaseUrls: BaseUrls = new BaseUrls({
72+
baseUrl: 'https://box.com/',
73+
uploadUrl: 'https://box.com/',
74+
oauth2Url: 'https://box.com/',
75+
});
76+
const customBaseClient: BoxClient = client.withCustomBaseUrls(newBaseUrls);
77+
await expect(async () => {
78+
await customBaseClient.users.getUserMe();
79+
}).rejects.toThrow();
80+
});
6781
test('testWithInterceptors', async function testWithInterceptors(): Promise<any> {
6882
const user: UserFull = await client.users.getUserMe();
6983
if (!(user.role == void 0)) {

0 commit comments

Comments
 (0)