Skip to content

Commit

Permalink
Merge pull request #287 from jaredwray/request---upgrading-xo-and-esl…
Browse files Browse the repository at this point in the history
…int-to-latest

request - upgrading xo and eslint to latest
  • Loading branch information
jaredwray committed Feb 21, 2024
2 parents ad6892c + c0be753 commit def291b
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 30 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yaml
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node: ['16', '18', '20']
node: ['18', '20']
name: Node ${{ matrix.node }}
steps:
- uses: actions/checkout@v2
Expand Down
10 changes: 5 additions & 5 deletions packages/request/package.json
Expand Up @@ -9,10 +9,10 @@
"exports": "./dist/index.js",
"types": "./dist/index.d.ts",
"engines": {
"node": ">=14.16"
"node": ">=18"
},
"scripts": {
"test": "xo && NODE_OPTIONS=--experimental-vm-modules jest --coverage ",
"test": "xo --fix && NODE_OPTIONS=--experimental-vm-modules jest --coverage ",
"prepare": "npm run build",
"build": "tsc --project tsconfig.build.json",
"clean": "rm -rf node_modules && rm -rf ./coverage && rm -rf ./test/testdb.sqlite && rm -rf ./dist"
Expand Down Expand Up @@ -53,16 +53,16 @@
"body-parser": "^1.20.2",
"delay": "^6.0.0",
"eslint": "^8.56.0",
"eslint-plugin-jest": "^27.6.3",
"eslint-plugin-jest": "^27.9.0",
"express": "^4.18.2",
"jest": "^29.7.0",
"pify": "^6.1.0",
"sqlite3": "^5.1.7",
"ts-jest": "^29.1.1",
"ts-jest": "^29.1.2",
"ts-jest-resolver": "^2.0.1",
"ts-node": "^10.9.2",
"typescript": "^5.3.3",
"xo": "^0.56.0"
"xo": "^0.57.0"
},
"jest": {
"collectCoverageFrom": [
Expand Down
35 changes: 21 additions & 14 deletions packages/request/src/index.ts
Expand Up @@ -9,14 +9,17 @@ import CachePolicy from 'http-cache-semantics';
import Response from 'responselike';
import Keyv from 'keyv';
import mimicResponse from 'mimic-response';
import {RequestFn, StorageAdapter, CacheResponse, CacheValue, CacheableOptions, UrlOption, CacheError, RequestError, Emitter, CacheableRequestFunction} from './types.js';
import {
RequestFn, StorageAdapter, CacheResponse, CacheValue, CacheableOptions, UrlOption, CacheError, RequestError, Emitter, CacheableRequestFunction,
} from './types.js';

type Func = (...args: any[]) => any;
// eslint-disable-next-line @typescript-eslint/naming-convention
type Function_ = (...arguments_: any[]) => any;

class CacheableRequest {
cache: StorageAdapter;
cacheRequest: RequestFn;
hooks: Map<string, Func> = new Map<string, Func>();
hooks: Map<string, Function_> = new Map<string, Function_>();
constructor(cacheRequest: RequestFn, cacheAdapter?: StorageAdapter | string) {
if (cacheAdapter instanceof Keyv) {
this.cache = cacheAdapter;
Expand All @@ -37,7 +40,7 @@ class CacheableRequest {
}

request = () => (options: CacheableOptions,
cb?: (response: CacheResponse) => void): Emitter => {
callback?: (response: CacheResponse) => void): Emitter => {
let url;
if (typeof options === 'string') {
url = normalizeUrlObject(urlLib.parse(options));
Expand Down Expand Up @@ -89,7 +92,7 @@ class CacheableRequest {
const makeRequest = (options_: any) => {
madeRequest = true;
let requestErrored = false;
let requestErrorCallback: (...args: any[]) => void = () => {/* do nothing */};
let requestErrorCallback: (...arguments_: any[]) => void = () => {/* do nothing */};

const requestErrorPromise = new Promise<void>(resolve => {
requestErrorCallback = () => {
Expand All @@ -111,7 +114,9 @@ class CacheableRequest {
.once('end', resolve);
});
const headers = convertHeaders(revalidatedPolicy.policy.responseHeaders());
response = new Response({statusCode: revalidate.statusCode, headers, body: revalidate.body, url: revalidate.url});
response = new Response({
statusCode: revalidate.statusCode, headers, body: revalidate.body, url: revalidate.url,
});
response.cachePolicy = revalidatedPolicy.policy;
response.fromCache = true;
}
Expand Down Expand Up @@ -169,8 +174,8 @@ class CacheableRequest {
}

ee.emit('response', clonedResponse ?? response);
if (typeof cb === 'function') {
cb(clonedResponse ?? response);
if (typeof callback === 'function') {
callback(clonedResponse ?? response);
}
};

Expand Down Expand Up @@ -198,12 +203,14 @@ class CacheableRequest {
const policy = CachePolicy.fromObject(cacheEntry.cachePolicy);
if (policy.satisfiesWithoutRevalidation(options_) && !options_.forceRefresh) {
const headers = convertHeaders(policy.responseHeaders());
const response: any = new Response({statusCode: cacheEntry.statusCode, headers, body: cacheEntry.body, url: cacheEntry.url});
const response: any = new Response({
statusCode: cacheEntry.statusCode, headers, body: cacheEntry.body, url: cacheEntry.url,
});
response.cachePolicy = policy;
response.fromCache = true;
ee.emit('response', response);
if (typeof cb === 'function') {
cb(response);
if (typeof callback === 'function') {
callback(response);
}
} else if (policy.satisfiesWithoutRevalidation(options_) && Date.now() >= policy.timeToLive() && options_.forceRefresh) {
await this.cache.delete(key);
Expand Down Expand Up @@ -238,17 +245,17 @@ class CacheableRequest {
return ee;
};

addHook = (name: string, fn: Func) => {
addHook = (name: string, function_: Function_) => {
if (!this.hooks.has(name)) {
this.hooks.set(name, fn);
this.hooks.set(name, function_);
}
};

removeHook = (name: string) => this.hooks.delete(name);

getHook = (name: string) => this.hooks.get(name);

runHook = async (name: string, ...args: any[]): Promise<CacheValue> => this.hooks.get(name)?.(...args);
runHook = async (name: string, ...arguments_: any[]): Promise<CacheValue> => this.hooks.get(name)?.(...arguments_);
}

const entries = Object.entries as <T>(object: T) => Array<[keyof T, T[keyof T]]>;
Expand Down
7 changes: 5 additions & 2 deletions packages/request/src/types.ts
Expand Up @@ -7,21 +7,24 @@

/// <reference types="node" />

import {request, RequestOptions, ClientRequest, ServerResponse} from 'node:http';
import {
request, RequestOptions, ClientRequest, ServerResponse,
} from 'node:http';
import {URL} from 'node:url';
import {EventEmitter} from 'node:events';
import {Buffer} from 'node:buffer';
import {Store} from 'keyv';
import ResponseLike from 'responselike';
import {CachePolicyObject} from 'http-cache-semantics';

// eslint-disable-next-line unicorn/prevent-abbreviations
export type RequestFn = typeof request;
export type RequestFunction = typeof request;
export type CacheResponse = ServerResponse | typeof ResponseLike;

export type CacheableRequestFunction = (
options: CacheableOptions,
cb?: (response: CacheResponse) => void
callback?: (response: CacheResponse) => void
) => Emitter;

export type CacheableOptions = Options & RequestOptions | string | URL;
Expand Down
16 changes: 8 additions & 8 deletions packages/request/test/cache.test.ts
Expand Up @@ -339,15 +339,15 @@ test('should return default url', async () => testCacheKey({method: 'POST'}, 'PO
test('request options path query is passed through', async () => {
const cacheableRequest = new CacheableRequest(request);
const cacheableRequestHelper = promisify(cacheableRequest.request());
const argString = `${s.url}/echo?foo=bar`;
const argUrl = new url.URL(argString);
const urlObject = url.parse(argString);
const argOptions = {
const argumentString = `${s.url}/echo?foo=bar`;
const argumentUrl = new url.URL(argumentString);
const urlObject = url.parse(argumentString);
const argumentOptions = {
hostname: urlObject.hostname,
port: urlObject.port,
path: urlObject.path,
};
const inputs = [argString, argUrl, argOptions];
const inputs = [argumentString, argumentUrl, argumentOptions];
for (const input of inputs) {
// eslint-disable-next-line no-await-in-loop
const response: any = await cacheableRequestHelper(input);
Expand Down Expand Up @@ -587,15 +587,15 @@ test('Keyv cache adapters load via connection uri', async () => {
'sqlite://test/testdb.sqlite',
);
const cacheableRequestHelper = promisify(cacheableRequest.request());
const db = new sqlite3.Database('test/testdb.sqlite');
const database = new sqlite3.Database('test/testdb.sqlite');
const firstResponse: any = await cacheableRequestHelper(s.url + endpoint);
await delay(1000);
const secondResponse: any = await cacheableRequestHelper(s.url + endpoint);
db.all(`SELECT * FROM keyv WHERE "key" = "cacheable-request:GET:${
database.all(`SELECT * FROM keyv WHERE "key" = "cacheable-request:GET:${
s.url + endpoint
}"`, (error, data) => {
expect(data.length).toBe(1);
db.all('DELETE FROM keyv');
database.all('DELETE FROM keyv');
});
expect(firstResponse.fromCache).toBeFalsy();
expect(secondResponse.fromCache).toBeTruthy();
Expand Down

0 comments on commit def291b

Please sign in to comment.