Skip to content
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
8 changes: 0 additions & 8 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,3 @@ jobs:

- name: Code formatting
run: yarn check-style

- name: SonarQube Scan
if: ${{ github.actor != 'dependabot[bot]' }}
uses: SonarSource/sonarqube-scan-action@v5.2.0
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
projectBaseDir: .
34 changes: 34 additions & 0 deletions .github/workflows/sonar-qube-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: SonarQube Scan
on:
push:
branches: [master]
pull_request:
branches: [master]

jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0

- uses: actions/setup-node@v1
with:
node-version: "18.x"

- name: Install deps
run: yarn

- name: Build
run: yarn build

- name: Test
run: yarn test

- name: SonarQube Scan
if: ${{ github.actor != 'dependabot[bot]' }}
uses: SonarSource/sonarqube-scan-action@v5.2.0
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29 changes: 15 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,22 @@ They provide common runtime utilities needed by SDKs to make API calls and handl

## List of Packages

| Name | Version | Description |
|-----------------------------------------------------------------------| --- | --- |
| [@apimatic/schema](packages/schema) | [![npm shield](https://img.shields.io/npm/v/@apimatic/schema)](https://www.npmjs.com/package/@apimatic/schema) | Validate and transform data using schema definitions. |
| Name | Version | Description |
|-----------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------| --- |
| [@apimatic/schema](packages/schema) | [![npm shield](https://img.shields.io/npm/v/@apimatic/schema)](https://www.npmjs.com/package/@apimatic/schema) | Validate and transform data using schema definitions. |
| [@apimatic/authentication-adapters](packages/authentication-adapters) | [![npm shield](https://img.shields.io/npm/v/@apimatic/authentication-adapters)](https://www.npmjs.com/package/@apimatic/authentication-adapters) | Provides pluggable adapters for different authentication schemes. |
| [@apimatic/axios-client-adapter](packages/axios-client-adapter) | [![npm shield](https://img.shields.io/npm/v/@apimatic/axios-client-adapter)](https://www.npmjs.com/package/@apimatic/axios-client-adapter) | Axios HTTP Client adapter which can be plugged into @apimatic/core package. |
| [@apimatic/convert-to-stream](packages/convert-to-stream) | [![npm shield](https://img.shields.io/npm/v/@apimatic/convert-to-stream)](https://www.npmjs.com/package/@apimatic/convert-to-stream) | Converts data into streams/blobs. |
| [@apimatic/core](packages/core) | [![npm shield](https://img.shields.io/npm/v/@apimatic/core)](https://www.npmjs.com/package/@apimatic/core) | Provides core http logic of request building, response handling and validation and using api error classes |
| [@apimatic/core-interfaces](packages/core-interfaces) | [![npm shield](https://img.shields.io/npm/v/@apimatic/core-interfaces)](https://www.npmjs.com/package/@apimatic/core-interfaces) | Abstraction layer for @apimatic/core. |
| [@apimatic/file-wrapper](packages/file-wrapper) | [![npm shield](https://img.shields.io/npm/v/@apimatic/file-wrapper)](https://www.npmjs.com/package/@apimatic/file-wrapper) | Wrapper around the file types and their utilities. |
| [@apimatic/http-headers](packages/http-headers) | [![npm shield](https://img.shields.io/npm/v/@apimatic/http-headers)](https://www.npmjs.com/package/@apimatic/http-headers) | HTTP Headers utilities for apimatic-js-runtime libraries. |
| [@apimatic/http-query](packages/http-query) | [![npm shield](https://img.shields.io/npm/v/@apimatic/http-query)](https://www.npmjs.com/package/@apimatic/http-query) | HTTP Query utilities for apimatic-js-runtime libraries |
| [@apimatic/oauth-adapters](packages/oauth-adapters) | [![npm shield](https://img.shields.io/npm/v/@apimatic/oauth-adapters)](https://www.npmjs.com/package/@apimatic/oauth-adapters) | Provides pluggable adapters for OAuth 2.0 authentication schemes. |
| [@apimatic/xml-adapter](packages/xml-adapter) | [![npm shield](https://img.shields.io/npm/v/@apimatic/xml-adapter)](https://www.npmjs.com/package/@apimatic/xml-adapter) | Provides XML serialization and deserialization utilities for apimatic-js-runtime libraries. |
| [@apimatic/test-utilities](packages/test-utilities) | [![npm shield](https://img.shields.io/npm/v/@apimatic/test-utilities)](https://www.npmjs.com/package/@apimatic/test-utilities) | Provides assertion utilities for testing api calls. It can be plugged in as dev dependency to any library. |
| [@apimatic/pagination](packages/pagination) | [![npm shield](https://img.shields.io/npm/v/@apimatic/pagination)](https://www.npmjs.com/package/@apimatic/pagination) | Provides utilities to handle paginated API responses, including support for asynchronous iteration over pages or items. |
| [@apimatic/axios-client-adapter](packages/axios-client-adapter) | [![npm shield](https://img.shields.io/npm/v/@apimatic/axios-client-adapter)](https://www.npmjs.com/package/@apimatic/axios-client-adapter) | Axios HTTP Client adapter which can be plugged into @apimatic/core package. |
| [@apimatic/convert-to-stream](packages/convert-to-stream) | [![npm shield](https://img.shields.io/npm/v/@apimatic/convert-to-stream)](https://www.npmjs.com/package/@apimatic/convert-to-stream) | Converts data into streams/blobs. |
| [@apimatic/core](packages/core) | [![npm shield](https://img.shields.io/npm/v/@apimatic/core)](https://www.npmjs.com/package/@apimatic/core) | Provides core http logic of request building, response handling and validation and using api error classes |
| [@apimatic/core-interfaces](packages/core-interfaces) | [![npm shield](https://img.shields.io/npm/v/@apimatic/core-interfaces)](https://www.npmjs.com/package/@apimatic/core-interfaces) | Abstraction layer for @apimatic/core. |
| [@apimatic/file-wrapper](packages/file-wrapper) | [![npm shield](https://img.shields.io/npm/v/@apimatic/file-wrapper)](https://www.npmjs.com/package/@apimatic/file-wrapper) | Wrapper around the file types and their utilities. |
| [@apimatic/http-headers](packages/http-headers) | [![npm shield](https://img.shields.io/npm/v/@apimatic/http-headers)](https://www.npmjs.com/package/@apimatic/http-headers) | HTTP Headers utilities for apimatic-js-runtime libraries. |
| [@apimatic/http-query](packages/http-query) | [![npm shield](https://img.shields.io/npm/v/@apimatic/http-query)](https://www.npmjs.com/package/@apimatic/http-query) | HTTP Query utilities for apimatic-js-runtime libraries |
| [@apimatic/oauth-adapters](packages/oauth-adapters) | [![npm shield](https://img.shields.io/npm/v/@apimatic/oauth-adapters)](https://www.npmjs.com/package/@apimatic/oauth-adapters) | Provides pluggable adapters for OAuth 2.0 authentication schemes. |
| [@apimatic/xml-adapter](packages/xml-adapter) | [![npm shield](https://img.shields.io/npm/v/@apimatic/xml-adapter)](https://www.npmjs.com/package/@apimatic/xml-adapter) | Provides XML serialization and deserialization utilities for apimatic-js-runtime libraries. |
| [@apimatic/test-utilities](packages/test-utilities) | [![npm shield](https://img.shields.io/npm/v/@apimatic/test-utilities)](https://www.npmjs.com/package/@apimatic/test-utilities) | Provides assertion utilities for testing api calls. It can be plugged in as dev dependency to any library. |
| [@apimatic/pagination](packages/pagination) | [![npm shield](https://img.shields.io/npm/v/@apimatic/pagination)](https://www.npmjs.com/package/@apimatic/pagination) | Provides utilities to handle paginated API responses, including support for asynchronous iteration over pages or items. |
| [@apimatic/proxy](packages/proxy) | [![npm shield](https://img.shields.io/npm/v/@apimatic/proxy)](https://www.npmjs.com/package/@apimatic/proxy) | Provides proxy configuration utilities for HTTP clients. |


[ci-badge]: https://github.com/apimatic/apimatic-js-runtime/actions/workflows/main.yml/badge.svg
Expand Down
1 change: 1 addition & 0 deletions packages/axios-client-adapter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"@apimatic/http-headers": "^0.3.6",
"@apimatic/http-query": "^0.3.6",
"@apimatic/json-bigint": "^1.2.0",
"@apimatic/proxy": "^0.1.0",
"@apimatic/schema": "^0.7.17",
"axios": "^1.8.4",
"detect-browser": "^5.3.0",
Expand Down
25 changes: 25 additions & 0 deletions packages/axios-client-adapter/src/httpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import {
} from '@apimatic/core-interfaces';
import { urlEncodeKeyValuePairs } from '@apimatic/http-query';
import { isFileWrapper } from '@apimatic/file-wrapper';
import { createProxyAgents } from '@apimatic/proxy';
import { ProxySettings } from '.';

export const DEFAULT_AXIOS_CONFIG_OVERRIDES: AxiosRequestConfig = {
transformResponse: [],
Expand All @@ -36,6 +38,7 @@ export class HttpClient {
private _axiosInstance: AxiosInstance;
private _timeout: number;
private _abortErrorFactory: AbortErrorConstructor;
private readonly _proxySettings?: ProxySettings;

constructor(
abortErrorFactory: AbortErrorConstructor,
Expand All @@ -44,13 +47,16 @@ export class HttpClient {
timeout = DEFAULT_TIMEOUT,
httpAgent,
httpsAgent,
proxySettings,
}: {
clientConfigOverrides?: AxiosRequestConfig;
timeout?: number;
httpAgent?: any;
httpsAgent?: any;
proxySettings?: ProxySettings;
} = {}
) {
this._proxySettings = proxySettings;
this._timeout = timeout;
this._axiosInstance = axios.create({
...DEFAULT_AXIOS_CONFIG_OVERRIDES,
Expand Down Expand Up @@ -143,6 +149,8 @@ export class HttpClient {
// set headers
newRequest.headers = headers;

this.setProxyAgent(newRequest);

return newRequest;
}

Expand Down Expand Up @@ -213,6 +221,21 @@ export class HttpClient {
}
}

private setProxyAgent(axiosRequest: AxiosRequestConfig): void {
if (!this._proxySettings || !axiosRequest.url) {
return;
}
const proxyAgents = createProxyAgents(this._proxySettings);

const protocol = new URL(axiosRequest.url).protocol;

if (protocol === 'https:') {
axiosRequest.httpsAgent = proxyAgents?.httpsAgent;
} else if (protocol === 'http:') {
axiosRequest.httpAgent = proxyAgents?.httpAgent;
}
}

private abortError() {
return new this._abortErrorFactory('The HTTP call was aborted.');
}
Expand All @@ -226,6 +249,8 @@ export interface HttpClientOptions {
httpAgent?: any;
/** Custom https agent to be used when performing https requests. */
httpsAgent?: any;
/** Proxy configuration to route requests through a proxy server. */
proxySettings?: ProxySettings;
Comment thread
Ayeshas09 marked this conversation as resolved.
/** Configurations to retry requests */
retryConfig: Partial<RetryConfiguration>;
}
Expand Down
1 change: 1 addition & 0 deletions packages/axios-client-adapter/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/// <reference path='./shim/index.ts' />

export * from './httpClient';
export type { ProxySettings } from '@apimatic/proxy';
12 changes: 0 additions & 12 deletions packages/axios-client-adapter/test/abortError.ts

This file was deleted.

73 changes: 72 additions & 1 deletion packages/axios-client-adapter/test/httpClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,19 @@ import {
import { FileWrapper } from '@apimatic/file-wrapper';
import FormData from 'form-data';
import fs from 'fs';
import { AbortError } from './abortError';

/**
* Thrown when the API call is aborted by the caller.
*
* Note that when an AbortError is thrown, it is not a guarantee that the API call
* did not go through.
*/
class AbortError extends Error {
constructor(message?: string) {
super(message);
Object.setPrototypeOf(this, new.target.prototype);
}
}

describe('HTTP Client', () => {
it('converts request with http text body and http get method', () => {
Expand Down Expand Up @@ -239,6 +251,65 @@ describe('HTTP Client', () => {
const httpResponse = httpClient.convertHttpResponse(response);
expect(httpResponse).toMatchObject(expectedHttpResponse);
});

const proxySettings = {
address: 'http://proxy.example.com',
port: 8080,
auth: {
username: 'user',
password: 'pass',
},
};
const httpRequest: HttpRequest = {
method: 'GET',
headers: { 'test-header': 'test-value' },
body: {
content: 'testBody',
type: 'text',
},
url: '',
responseType: 'text',
auth: { username: 'test-username', password: 'test-password' },
};
const expectedProxyConfig = {
protocol: 'http:',
username: 'user',
password: 'pass',
host: 'proxy.example.com:8080',
port: '8080',
};

it('adds httpAgent to axios request config for http URLs when proxySettings are provided', () => {
const httpClient = new HttpClient(AbortError, { proxySettings });
httpRequest.url = 'http://apimatic.hopto.org:3000/test/requestBuilder';
const axiosRequestConfig = httpClient.convertHttpRequest(httpRequest);
expect(axiosRequestConfig.httpAgent.proxy).toMatchObject(
expectedProxyConfig
);
});

it('adds httpsAgent to axios request config for https URLs when proxySettings are provided', () => {
const httpClient = new HttpClient(AbortError, { proxySettings });
httpRequest.url = 'https://apimatic.hopto.org:3000/test/requestBuilder';
const axiosRequestConfig = httpClient.convertHttpRequest(httpRequest);
expect(axiosRequestConfig.httpsAgent.proxy).toMatchObject(
expectedProxyConfig
);
});

it('httpsAgent should be undefined when proxySettings are not provided', () => {
const httpClient = new HttpClient(AbortError);
httpRequest.url = 'https://apimatic.hopto.org:3000/test/requestBuilder';
const axiosRequestConfig = httpClient.convertHttpRequest(httpRequest);
expect(axiosRequestConfig.httpsAgent).toBeUndefined();
});

it('httpsAgent and httpAgent should be undefined when requestUrl is not set', () => {
const httpClient = new HttpClient(AbortError);
const axiosRequestConfig = httpClient.convertHttpRequest(httpRequest);
expect(axiosRequestConfig.httpsAgent).toBeUndefined();
expect(axiosRequestConfig.httpAgent).toBeUndefined();
});
});

describe('test blob type', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/pagination/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ This library is used by JavaScript SDKs generated by the [APIMatic Code Generato

The following environments are supported:

1. Node.js v10+
1. Node.js v14+ and v16+
1. Bundlers like Rollup or Webpack
1. Web browsers

Expand Down
33 changes: 33 additions & 0 deletions packages/proxy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# APIMatic Proxy Libary for JavaScript

> This library is currently in preview.

Provides utility functions to generate HTTP and HTTPS proxy agents based on configuration. It supports conditional behavior for both Node.js and browser environments.

The exported helper functions and interfaces include:

1. **createProxyAgents**: Creates and returns HTTP and HTTPS proxy agents using provided proxy settings. In browser environments, this function returns undefined with a warning, as proxy agents are not supported in browsers.
2. **ProxySettings**: Defines the proxy configuration, including a required address and optional port and authentication credentials.

This library is used by JavaScript SDKs generated by the [APIMatic Code Generator](http://www.apimatic.io).

## Builds

The following environments are supported:

1. Node.js v14+ and v16+
1. Bundlers like Rollup or Webpack
1. Web browsers

To support multiple environments, we export various builds:

| Environment | Usage |
| --- |----------------------------------------------------------------------------|
| Common.js | Import like this: `require('@apimatic/proxy')`. |
| ES Module | Import like this: `import { /* your imports */ } from '@apimatic/proxy'`. |
| Browsers | *Use script: `https://unpkg.com/@apimatic/proxy@VERSION/umd/schema.js` |
| Modern Browsers (supports ESM and uses modern JS) | *Use script: `https://unpkg.com/@apimatic/proxy@VERSION/umd/schema.esm.js` |

_* Don't forget to replace VERSION with the version number._

**Note**: We discourage importing files or modules directly from the package. These are likely to change in the future and should not be considered stable.
7 changes: 7 additions & 0 deletions packages/proxy/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const { jest: lernaAliases } = require('lerna-alias');

module.exports = {
preset: 'ts-jest',
moduleNameMapper: lernaAliases(),
coverageReporters: [['lcov', { projectRoot: '../../' }]]
};
42 changes: 42 additions & 0 deletions packages/proxy/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "@apimatic/proxy",
"version": "0.1.0",
"description": "provides utilities to route requests through a configurable proxy",
"main": "lib/index.js",
"module": "lib/index.js",
"types": "lib/index.d.ts",
"engines": {
"node": ">=14.15.0 || >=16.0.0"
},
"scripts": {
"clean": "rimraf lib es umd tsconfig.tsbuildinfo",
"test": "jest --passWithNoTests",
"build": "npm run clean && tsc && rollup -c --bundleConfigAsCjs && npm run annotate:es",
"annotate:es": "babel es --out-dir es --no-babelrc --plugins annotate-pure-calls",
"preversion": "npm run test",
"prepublishOnly": "npm run build",
"size": "size-limit",
"analyze": "size-limit --why",
"lint": "tslint --project .",
"lint:fix": "tslint --project . --fix",
"check-style": "prettier --check \"{src,test}/**/*.ts\"",
"check-style:fix": "prettier --write \"{src,test}/**/*.ts\""
},
"author": "APIMatic Ltd.",
"license": "ISC",
"browser": {
"./lib/proxyAgent.js": "./lib/proxyAgentBrowser.js"
},
"dependencies": {
"http-proxy-agent": "^7.0.2",
"https-proxy-agent": "^7.0.6"
},
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git@github.com:apimatic/apimatic-js-runtime.git",
"directory": "packages/proxy"
}
}
Loading