Skip to content

Commit

Permalink
impr: use undici for handling http request
Browse files Browse the repository at this point in the history
chore: remove some unused libraries as a result
  • Loading branch information
yhnavein committed Jul 3, 2024
1 parent bf6641c commit 6704687
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 195 deletions.
6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,16 @@
"eta": "^3.4.0",
"js-yaml": "^4.1.0",
"nanocolors": "^0.2.0",
"node-fetch": "^2.6.7"
"undici": "^6.19.2"
},
"devDependencies": {
"@types/chai": "4.3.16",
"@types/js-yaml": "4.0.9",
"@types/mocha": "10.0.7",
"@types/node-fetch": "2.6.11",
"@types/sinon": "17.0.3",
"@types/node": "20.14.9",
"chai": "4.4.1",
"mocha": "10.6.0",
"openapi-types": "^12.1.3",
"sinon": "18.0.0",
"sucrase": "3.35.0",
"typescript": "5.5.3"
}
Expand Down
27 changes: 17 additions & 10 deletions src/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { expect } from 'chai';
import fs from 'node:fs';
import * as fetch from 'node-fetch';
import { Response } from 'node-fetch';
import sinon from 'sinon';
import { MockAgent, setGlobalDispatcher } from 'undici';

import { runCodeGenerator, applyConfigFile } from './';
import { mockRequest } from './utils';

describe('runCodeGenerator', () => {
afterEach(sinon.restore);
let mockAgent: MockAgent;

beforeEach(() => {
// Create a new MockAgent
mockAgent = new MockAgent();
// Make sure that we don't actually make real requests
mockAgent.disableNetConnect();
// Set the mocked agent as the global dispatcher
setGlobalDispatcher(mockAgent);
});

it('fails with no parameters provided', async () => {
const parameters = {};
Expand Down Expand Up @@ -91,11 +98,11 @@ describe('runCodeGenerator', () => {
});

it('works with proper --config provided', async () => {
const stub = sinon.stub(fetch, 'default');
const response = fs.readFileSync(`${__dirname}/../test/petstore-v3.json`, {
encoding: 'utf-8',
});
stub.returns(new Promise((resolve) => resolve(new Response(response))));
mockRequest(
mockAgent,
'https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.json',
'petstore-v3.json'
);

const parameters = {
config: './test/sample-config.json',
Expand Down
34 changes: 17 additions & 17 deletions src/utils/documentLoader.spec.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
import { expect } from 'chai';
import fs from 'node:fs';
import * as fetch from 'node-fetch';
import { Response } from 'node-fetch';
import sinon from 'sinon';
import { MockAgent, setGlobalDispatcher } from 'undici';

import { loadSpecDocument } from './documentLoader';
import { mockRequest } from './test.utils';

// URLs are not used to fetch anything. We are faking responses through SinonJS
const petstore3 = {
json: 'http://petstore.swagger.io/v3/swagger.json',
yaml: 'http://petstore.swagger.io/v3/swagger.yaml',
json: 'https://petstore.swagger.io/v3/swagger.json',
yaml: 'https://petstore.swagger.io/v3/swagger.yaml',
};

describe('loadSpecDocument', () => {
afterEach(sinon.restore);
let mockAgent: MockAgent;

beforeEach(() => {
// Create a new MockAgent
mockAgent = new MockAgent();
// Make sure that we don't actually make real requests
mockAgent.disableNetConnect();
// Set the mocked agent as the global dispatcher
setGlobalDispatcher(mockAgent);
});

it('should resolve a JSON spec from url', async () => {
const stub = sinon.stub(fetch, 'default');
const response = fs.readFileSync(`${__dirname}/../../test/petstore-v3.json`, {
encoding: 'utf-8',
});
stub.returns(new Promise((resolve) => resolve(new Response(response))));
mockRequest(mockAgent, petstore3.json, 'petstore-v3.json');

const spec = await loadSpecDocument(petstore3.json);
expect(spec).to.be.ok;
expect(spec.paths).to.be.ok;
});

it('should resolve a YAML spec from url', async () => {
const stub = sinon.stub(fetch, 'default');
const response = fs.readFileSync(`${__dirname}/../../test/petstore-v3.yml`, {
encoding: 'utf-8',
});
stub.returns(new Promise((resolve) => resolve(new Response(response))));
mockRequest(mockAgent, petstore3.yaml, 'petstore-v3.yml');

const spec = await loadSpecDocument(petstore3.yaml);
expect(spec).to.be.ok;
Expand Down
12 changes: 6 additions & 6 deletions src/utils/documentLoader.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import YAML from 'js-yaml';
import fs from 'node:fs';
import fetch from 'node-fetch';
import YAML from 'js-yaml';
import type { OpenAPIV3 as OA3 } from 'openapi-types';
import { request } from 'undici';

export async function loadSpecDocument(src: string | object): Promise<OA3.Document> {
if (typeof src === 'string') {
Expand All @@ -21,10 +21,10 @@ function loadFile(src: string): Promise<OA3.Document | any> {
throw new Error(`Unable to load api at '${src}'`);
}

function loadFromUrl(url: string) {
return fetch(url)
.then((resp) => resp.text())
.then((contents) => parseFileContents(contents, url));
async function loadFromUrl(url: string) {
const { body } = await request(url);
const contents = await body.text();
return parseFileContents(contents, url);
}

function readLocalFile(filePath: string) {
Expand Down
27 changes: 27 additions & 0 deletions src/utils/test.utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import fs from 'node:fs';
import path from 'node:path';
import type { OpenAPIV3 as OA3 } from 'openapi-types';
import type { MockAgent } from 'undici';

import type { ClientOptions } from '../types';

/**
Expand Down Expand Up @@ -31,3 +35,26 @@ export function getClientOptions(opts: Partial<ClientOptions> = {}): ClientOptio
...opts,
};
}

/**
* Utility that will set up a mock response for a given URL
* @param mockAgent Agent that will be used to intercept the request
* @param url Full URL to intercept
* @param responseFileName Filename that contains the response. It will be loaded from the test folder
*/
export function mockRequest(mockAgent: MockAgent, url: string, responseFileName: string) {
const urlObject = new URL(url);
const mockPool = mockAgent.get(urlObject.origin);

const response = fs.readFileSync(path.join(__dirname, '..', '..', 'test', responseFileName), {
encoding: 'utf-8',
});

// Set up the mock response
mockPool
.intercept({
path: urlObject.pathname,
method: 'GET',
})
.reply(200, response);
}
Loading

0 comments on commit 6704687

Please sign in to comment.