Skip to content

Commit d3ca85b

Browse files
committed
Use manifest v3 for Chrome, switch axios for ky
1 parent 8f43628 commit d3ca85b

File tree

11 files changed

+100
-86
lines changed

11 files changed

+100
-86
lines changed

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,11 @@
9797
"@babel/runtime": "^7.17.9",
9898
"@headlessui/react": "^1.6.1",
9999
"@reduxjs/toolkit": "^1.8.1",
100-
"axios": "^0.27.2",
101100
"entities": "^4.3.0",
102101
"glob-to-regexp": "^0.4.1",
102+
"ky": "^0.30.0",
103103
"lodash": "^4.17.21",
104+
"qs": "^6.10.3",
104105
"react": "^18.1.0",
105106
"react-color": "^2.19.3",
106107
"react-device-detect": "^2.2.2",

src/api/anilist-http-client/anilist-http-client.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export class AnilistHttpClient extends BaseHttpClient {
2929
variables,
3030
};
3131

32-
const response = await this.request({ route, method: 'POST', data });
32+
const response = await this.request({ route, method: 'POST', json: data });
3333

3434
return response.data;
3535
}

src/api/aniskip-http-client/aniskip-http-client.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,11 @@ export class AniskipHttpClient extends BaseHttpClient {
9191
submitterId,
9292
};
9393

94-
const response = await this.request<typeof data, PostResponseFromSkipTimes>(
95-
{ route, method: 'POST', data }
96-
);
94+
const response = await this.request<PostResponseFromSkipTimes>({
95+
route,
96+
method: 'POST',
97+
json: data,
98+
});
9799
const json = response.data;
98100

99101
if (response.ok) {
@@ -118,7 +120,7 @@ export class AniskipHttpClient extends BaseHttpClient {
118120
voteType: type,
119121
};
120122

121-
const response = await this.request({ route, method: 'POST', data });
123+
const response = await this.request({ route, method: 'POST', json: data });
122124

123125
if (response.status === 429) {
124126
throw new AniskipHttpClientError('Rate limited', 'vote/rate-limited');

src/api/base-http-client/base-http-client.ts

+15-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import axios from 'axios';
1+
import ky from 'ky';
2+
import QueryString from 'qs';
23
import { browser } from 'webextension-polyfill-ts';
34
import { Response, HttpClient, Config } from './base-http-client.types';
45
import { Message } from '../../scripts/background';
6+
import { parseResponse } from '../../utils/http';
57

68
export abstract class BaseHttpClient implements HttpClient {
79
baseUrl: string;
@@ -10,34 +12,39 @@ export abstract class BaseHttpClient implements HttpClient {
1012
this.baseUrl = baseUrl;
1113
}
1214

13-
async request<T = any, D = any>(
14-
{ route, ...rest }: Config<T>,
15+
async request<D = any>(
16+
{ route, params, ...rest }: Config,
1517
isCallingBackgroundScript: boolean = true
1618
): Promise<Response<D>> {
1719
const url = `${this.baseUrl}${route}`;
20+
const config = {
21+
...(params && {
22+
searchParams: QueryString.stringify(params, { encodeValuesOnly: true }),
23+
}),
24+
...rest,
25+
};
1826

1927
if (isCallingBackgroundScript) {
2028
const response = await browser.runtime.sendMessage({
2129
type: 'fetch',
22-
payload: { url, ...rest },
30+
payload: { url, config },
2331
} as Message);
2432

2533
return response;
2634
}
2735

2836
let response;
29-
3037
try {
31-
const succesfulResponse = await axios({ url, ...rest });
38+
const succesfulResponse = await ky(url, config);
3239

3340
response = {
34-
data: succesfulResponse.data,
41+
data: await parseResponse<D>(succesfulResponse),
3542
status: succesfulResponse.status,
3643
ok: true,
3744
};
3845
} catch (err: any) {
3946
response = {
40-
data: err.response.data,
47+
data: await parseResponse<D>(err.response),
4148
status: err.response.status,
4249
ok: false,
4350
};

src/api/base-http-client/base-http-client.types.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { AxiosRequestConfig } from 'axios';
1+
import { Options } from 'ky';
22

33
export type Response<D = any> = {
44
data: D;
@@ -15,10 +15,10 @@ export type HttpClient = {
1515
* @param config Axios config.
1616
* @param isCallingBackgroundScript Proxy the HTTP request using the background script.
1717
*/
18-
request<T = any, D = any>(
19-
config: Config<T>,
18+
request<D = any>(
19+
config: Config,
2020
isCallingBackgroundScript?: boolean
2121
): Promise<Response<D>>;
2222
};
2323

24-
export type Config<T = any> = AxiosRequestConfig<T> & { route: string };
24+
export type Config = Options & { route: string; params?: any };

src/api/crunchyroll-beta-http-client/crunchyroll-beta-http-client.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ export class CrunchyrollBetaHttpClient extends BaseHttpClient {
5454
'Content-Type': 'application/x-www-form-urlencoded',
5555
};
5656

57-
const authV1Response = await super.request<string, PostResponseFromAuthV1>(
58-
{ route, method: 'POST', data, headers, withCredentials: true },
57+
const authV1Response = await super.request<PostResponseFromAuthV1>(
58+
{ route, method: 'POST', body: data, headers, credentials: 'include' },
5959
false
6060
);
6161

@@ -66,10 +66,10 @@ export class CrunchyrollBetaHttpClient extends BaseHttpClient {
6666
Authorization: `Bearer ${authV1Response.data.access_token}`,
6767
};
6868

69-
const authV2Response = await super.request<
70-
undefined,
71-
GetResponseFromIndexV2
72-
>({ route, headers }, false);
69+
const authV2Response = await super.request<GetResponseFromIndexV2>(
70+
{ route, headers },
71+
false
72+
);
7373

7474
const { cms_beta: cmsBeta } = authV2Response.data;
7575

@@ -80,11 +80,11 @@ export class CrunchyrollBetaHttpClient extends BaseHttpClient {
8080
this.isAuthenticated = true;
8181
}
8282

83-
async request<T = any, D = any>({
83+
async request<D = any>({
8484
route,
8585
params,
8686
...rest
87-
}: Config<T>): Promise<Response<D>> {
87+
}: Config): Promise<Response<D>> {
8888
await this.authenticate();
8989

9090
const authenticatedRoute = `/cms/v2${this.bucket}${route}`;

src/scripts/background/script.ts

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { browser, Runtime } from 'webextension-polyfill-ts';
22
import { v4 as uuidv4 } from 'uuid';
3-
import axios from 'axios';
3+
import ky from 'ky';
44
import {
55
LocalOptions,
66
Message,
77
DEFAULT_LOCAL_OPTIONS,
88
DEFAULT_SYNC_OPTIONS,
99
SyncOptions,
1010
} from './types';
11-
import { waitForMessage } from '../../utils';
11+
import { parseResponse, waitForMessage } from '../../utils';
1212

1313
/**
1414
* Relay messages between content scripts.
@@ -30,18 +30,19 @@ const messageHandler = (
3030
case 'fetch': {
3131
return (async (): Promise<any> => {
3232
try {
33-
const response = await axios(message.payload);
33+
const { url, config } = message.payload;
34+
const response = await ky(url, config);
3435

3536
return {
36-
data: response.data,
37+
data: await parseResponse(response),
3738
status: response.status,
38-
ok: true,
39+
ok: response.ok,
3940
};
4041
} catch (err: any) {
4142
return {
42-
data: err.response.data,
43+
data: await parseResponse(err.response),
4344
status: err.response.status,
44-
ok: false,
45+
ok: err.response.ok,
4546
};
4647
}
4748
})();

src/utils/http.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* Parses the HTTP response according to its type.
3+
*
4+
* @param response HTTP response object.
5+
*/
6+
export const parseResponse = async <T>(response: Response): Promise<T> => {
7+
if (response.headers.get('content-type')?.includes('application/json')) {
8+
return (await response.json()) as T;
9+
}
10+
11+
return (await response.text()) as unknown as T;
12+
};

src/utils/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from './http';
12
export * from './keybinds';
23
export * from './message';
34
export * from './page';

webpack/manifest.js

+32-19
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,35 @@
1-
const { merge } = require('lodash');
1+
// eslint-disable-next-line import/no-extraneous-dependencies
2+
const { default: merge } = require('webpack-merge');
23
const fs = require('fs');
34
const path = require('path');
45
const packageJson = require('../package.json');
56

67
const manifestTemplate = {
7-
manifest_version: 2,
88
name: packageJson.extensionName,
99
version: packageJson.version,
1010
description: packageJson.description,
1111
options_ui: {
1212
page: 'options.html',
1313
open_in_tab: true,
1414
},
15-
browser_action: {
16-
default_popup: 'popup.html',
17-
},
18-
background: {
19-
scripts: ['background-script.js'],
20-
},
21-
web_accessible_resources: ['window-proxy-script.js'],
22-
permissions: [
23-
'storage',
24-
'*://api.aniskip.com/*',
25-
'*://api.malsync.moe/*',
26-
'*://graphql.anilist.co/*',
27-
'*://beta-api.crunchyroll.com/*',
28-
],
15+
permissions: ['storage'],
2916
icons: {
3017
16: 'icon_16.png',
3118
48: 'icon_48.png',
3219
128: 'icon_128.png',
3320
},
3421
};
3522

23+
const apiPermissions = [
24+
'*://api.aniskip.com/*',
25+
'*://api.malsync.moe/*',
26+
'*://graphql.anilist.co/*',
27+
'*://beta-api.crunchyroll.com/*',
28+
];
29+
30+
const backgroundScript = 'background-script.js';
31+
const windowProxyScript = 'window-proxy-script.js';
32+
3633
const browser = process.env.BROWSER;
3734

3835
const getPageUrls = () => {
@@ -97,26 +94,42 @@ module.exports = () => {
9794
switch (browser) {
9895
case 'chromium':
9996
return merge(manifestTemplate, {
100-
options_ui: {
101-
chrome_style: false,
97+
manifest_version: 3,
98+
background: {
99+
service_worker: backgroundScript,
102100
},
103-
browser_action: {
101+
action: {
102+
default_popup: 'popup.html',
104103
chrome_style: false,
105104
},
105+
host_permissions: apiPermissions,
106+
web_accessible_resources: [
107+
{
108+
resources: [windowProxyScript],
109+
matches: ['https://beta.crunchyroll.com/*'],
110+
},
111+
],
106112
});
107113
case 'firefox':
108114
return merge(manifestTemplate, {
115+
manifest_version: 2,
116+
background: {
117+
scripts: [backgroundScript],
118+
},
109119
options_ui: {
110120
browser_style: false,
111121
},
112122
browser_action: {
123+
default_popup: 'popup.html',
113124
browser_style: false,
114125
},
115126
browser_specific_settings: {
116127
gecko: {
117128
id: '{c67645fa-ad86-4b2f-ab7a-67fc5f3e9f5a}',
118129
},
119130
},
131+
permissions: apiPermissions,
132+
web_accessible_resources: [windowProxyScript],
120133
});
121134
default:
122135
throw new Error(`Invalid browser type '${browser}'`);

0 commit comments

Comments
 (0)