Skip to content

feat: Support custom Agent in Typescript (box/box-codegen#452) #117

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .codegen.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{ "engineHash": "3970588", "specHash": "d50ab5f", "version": "0.5.1" }
{ "engineHash": "0d4bf53", "specHash": "d50ab5f", "version": "0.5.1" }
11 changes: 11 additions & 0 deletions docs/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ const newClient = client.withCustomBaseUrls({
});
```

# Custom Agent Options

You can also specify the custom agent options, which will be used for API calls made by client.
Calling the `client.withCustomAgentOptions()` method creates a new client, leaving the original client unmodified.

```js
const options: AgentOptions = {};

const newClient = client.withCustomAgentOptions(options);
```

# Interceptors

You can specify custom interceptors - methods that will be called just before making a request and right after
Expand Down
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module.exports = {
],
},
moduleNameMapper: {
'^(..?/.+).jsx?$': '$1',
'^(..?/.+)\\.jsx?$': '$1',
},
clearMocks: true,
setupFilesAfterEnv: ['<rootDir>/setup-jest.js'],
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@
"buffer": "^6.0.3",
"jose": "^5.2.2",
"tslib": "^2.6.2",
"uuid": "^9.0.0"
"uuid": "^9.0.0",
"proxy-agent": "^6.4.0"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-typescript": "^11.1.5",
"@types/jest": "^29.5.1",
Expand Down
1 change: 1 addition & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ exports.default = {
require('@rollup/plugin-typescript')({
tsconfig: './tsconfig.rollup.json',
}), // Compiles TypeScript
require('@rollup/plugin-json')(), // Converts JSON files to ES6 modules
],
};
8 changes: 8 additions & 0 deletions src/client.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ import { IntegrationMappingsManager } from './managers/integrationMappings.gener
import { Authentication } from './networking/auth.generated.js';
import { NetworkSession } from './networking/network.generated.js';
import { BaseUrls } from './networking/baseUrls.generated.js';
import { AgentOptions } from './internal/utils.js';
import { Interceptor } from './networking/interceptors.generated.js';
import { SerializedData } from './serialization/json.js';
import { sdIsEmpty } from './serialization/json.js';
Expand Down Expand Up @@ -229,6 +230,7 @@ export class BoxClient {
| 'withSuppressedNotifications'
| 'withExtraHeaders'
| 'withCustomBaseUrls'
| 'withCustomAgentOptions'
| 'withInterceptors'
>
| Partial<Pick<BoxClient, 'networkSession'>>
Expand Down Expand Up @@ -545,6 +547,12 @@ export class BoxClient {
networkSession: this.networkSession.withCustomBaseUrls(baseUrls),
});
}
withCustomAgentOptions(agentOptions: AgentOptions): BoxClient {
return new BoxClient({
auth: this.auth,
networkSession: this.networkSession.withCustomAgentOptions(agentOptions),
});
}
withInterceptors(interceptors: readonly Interceptor[]): BoxClient {
return new BoxClient({
auth: this.auth,
Expand Down
13 changes: 13 additions & 0 deletions src/internal/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export function hexToBase64(data: string): string {
export { Buffer, Readable as ByteStream };
export type { CancellationToken };
export type Iterator<T = any> = AsyncIterator<T>;
export type AgentOptions = any;
export type Agent = any;

// Function to convert a hexadecimal string to base64
export function hexStrToBase64(hex: string) {
Expand Down Expand Up @@ -322,3 +324,14 @@ export function readTextFromFile(filepath: string): string {
export function getEpochTimeInSeconds(): number {
return Math.floor(Date.now() / 1000);
}

/**
* Create web agent from proxy agent options.
*/
export function createAgent(options?: AgentOptions): Agent {
if (isBrowser()) {
return undefined;
}
const ProxyAgent = eval('require')('proxy-agent').ProxyAgent;
return options ? new ProxyAgent(options) : new ProxyAgent();
}
1 change: 1 addition & 0 deletions src/networking/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ async function createRequestInit(options: FetchOptions): Promise<RequestInit> {
},
body,
signal: options.cancellationToken as RequestInit['signal'],
agent: options.networkSession?.agent,
};
}

Expand Down
26 changes: 25 additions & 1 deletion src/networking/network.generated.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
import { BaseUrls } from './baseUrls.generated.js';
import { Interceptor } from './interceptors.generated.js';
import { Agent } from '../internal/utils.js';
import { AgentOptions } from '../internal/utils.js';
import { createAgent } from '../internal/utils.js';
export class NetworkSession {
readonly additionalHeaders: {
readonly [key: string]: string;
} = {};
readonly baseUrls!: BaseUrls;
readonly interceptors: readonly Interceptor[] = [];
readonly agent: Agent = createAgent(void 0);
readonly agentOptions?: AgentOptions;
constructor(
fields:
| Omit<
NetworkSession,
| 'additionalHeaders'
| 'interceptors'
| 'agent'
| 'withAdditionalHeaders'
| 'withCustomBaseUrls'
| 'withCustomAgentOptions'
| 'withInterceptors'
>
| Partial<Pick<NetworkSession, 'additionalHeaders' | 'interceptors'>>
| Partial<
Pick<NetworkSession, 'additionalHeaders' | 'interceptors' | 'agent'>
>
) {
Object.assign(this, fields);
}
Expand All @@ -29,20 +38,35 @@ export class NetworkSession {
additionalHeaders: { ...this.additionalHeaders, ...additionalHeaders },
baseUrls: this.baseUrls,
interceptors: this.interceptors,
agent: this.agent,
agentOptions: this.agentOptions,
});
}
withCustomBaseUrls(baseUrls: BaseUrls): NetworkSession {
return new NetworkSession({
additionalHeaders: this.additionalHeaders,
baseUrls: baseUrls,
interceptors: this.interceptors,
agent: this.agent,
agentOptions: this.agentOptions,
});
}
withCustomAgentOptions(agentOptions: AgentOptions): NetworkSession {
return new NetworkSession({
additionalHeaders: this.additionalHeaders,
baseUrls: this.baseUrls,
interceptors: this.interceptors,
agent: createAgent(agentOptions),
agentOptions: this.agentOptions,
});
}
withInterceptors(interceptors: readonly Interceptor[]): NetworkSession {
return new NetworkSession({
additionalHeaders: this.additionalHeaders,
baseUrls: this.baseUrls,
interceptors: this.interceptors.concat(interceptors),
agent: this.agent,
agentOptions: this.agentOptions,
});
}
}
14 changes: 14 additions & 0 deletions src/test/client.generated.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { serializeUserFull } from '../schemas.generated.js';
import { deserializeUserFull } from '../schemas.generated.js';
import { serializeCreateUserRequestBody } from '../managers/users.generated.js';
import { deserializeCreateUserRequestBody } from '../managers/users.generated.js';
import { serializeBaseUrls } from '../networking/baseUrls.generated.js';
import { deserializeBaseUrls } from '../networking/baseUrls.generated.js';
import { BoxClient } from '../client.generated.js';
import { UserFull } from '../schemas.generated.js';
import { CreateUserRequestBody } from '../managers/users.generated.js';
Expand All @@ -10,6 +12,7 @@ import { getUuid } from '../internal/utils.js';
import { getDefaultClient } from './commons.generated.js';
import { FetchOptions } from '../networking/fetch.js';
import { FetchResponse } from '../networking/fetch.js';
import { BaseUrls } from '../networking/baseUrls.generated.js';
import { toString } from '../internal/utils.js';
import { sdToJson } from '../serialization/json.js';
import { jsonToSerializedData } from '../serialization/json.js';
Expand Down Expand Up @@ -64,6 +67,17 @@ test('testWithExtraHeaders', async function testWithExtraHeaders(): Promise<any>
}
await client.users.deleteUserById(createdUser.id);
});
test('testWithCustomBaseUrls', async function testWithCustomBaseUrls(): Promise<any> {
const newBaseUrls: BaseUrls = new BaseUrls({
baseUrl: 'https://box.com/',
uploadUrl: 'https://box.com/',
oauth2Url: 'https://box.com/',
});
const customBaseClient: BoxClient = client.withCustomBaseUrls(newBaseUrls);
await expect(async () => {
await customBaseClient.users.getUserMe();
}).rejects.toThrow();
});
test('testWithInterceptors', async function testWithInterceptors(): Promise<any> {
const user: UserFull = await client.users.getUserMe();
if (!(user.role == void 0)) {
Expand Down