diff --git a/README.md b/README.md index f5a5c41..2312660 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,9 @@ The library provides the out of box accessing to MediaWiki API in both browsers - With unit tests - User authentication supports out of the box \*(also applicable to Node.js!) -## 开箱即用/Out of box +## 开箱即用 Out of box -**安装/installation** +**安装 Installation** ```sh # Via pnpm: @@ -42,7 +42,7 @@ const api = new MediaWikiApi('https://zh.moegirl.org.cn/api.php') // ... ``` -**在浏览器中直接使用/Use directly in the browser** +**在浏览器中直接使用 Use directly in the browser** ```js import('https://unpkg.com/wiki-saikou?module').then(({ MediaWikiApi }) => { @@ -53,7 +53,7 @@ import('https://unpkg.com/wiki-saikou?module').then(({ MediaWikiApi }) => { Then use it just like the `new mw.Api()` -## 使用方法/Usage +## 使用方法 Usage You can find some sample code snippets [here](test/). @@ -65,7 +65,7 @@ Below is the documentation of MediaWikiApi. **Main methods**: -#### `new MediaWikiApi(baseURL?: string, options?: LylaRequestOptions)` +#### `new MediaWikiApi(baseURL?: string, options?: Partial)` - `baseURL`: API endpoint of your target wiki site (e.g. https://mediawiki.org/w/api.php) - **Not required but with conditions**: If you are using it in the browser environment, and the website runs MediaWiki. The instance will automatically use the API endpoint of current wiki. @@ -75,15 +75,15 @@ Below is the documentation of MediaWikiApi. Login your account. -#### `get(params: MwApiParams, options?: LylaRequestOptions): Promise>` +#### `get(params: MwApiParams, options?: FexiosRequestOptions): Promise>` Make `GET` request -#### `post(body: MwApiParams, options?: LylaRequestOptions): Promise>` +#### `post(body: MwApiParams, options?: LylaRequestOptions): Promise>` Make `POST` request -#### `postWithToken(tokenType: MwTokenName, body: MwApiParams, options?: LylaRequestOptions): Promise>` +#### `postWithToken(tokenType: MwTokenName, body: MwApiParams, options?: LylaRequestOptions): Promise>` Make `POST` request with specified token. @@ -98,11 +98,11 @@ type MwTokenName = | 'watch' ``` -### Auxiliary utilities +### 工具函数 Auxiliary utilities -#### `get request` {AxiosInstance} +#### `get request` {Fexios} -Get `Lyla` instance of current MediaWikiApi instance +Get `Fexios` instance of current MediaWikiApi instance #### `MediaWikiApi.normalizeParamValue(params: MwApiParams[keyof MwApiParams]): string | File | undefined` (static) @@ -111,9 +111,9 @@ Normalize input params to standard MediaWiki request params. - `string[] → string`: `['foo', 'bar', 'baz'] → 'foo|bar|baz` - `false → undefined`: remove false items -#### `MediaWikiApi.createLylaInstance(baseURL: string, options?: LylaRequestOptions): Lyla` (static) +#### `MediaWikiApi.createRequestHandler(baseURL: string, options?: Partial): Fexios` (static) -Create your own Lyla instance. +Create your own Fexios instance. **Warning: The instance created by this method does not include responsive getters/setters (described below) and the out of box cookie controls.** diff --git a/package.json b/package.json index 1be8f51..127df92 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wiki-saikou", - "version": "2.0.0", + "version": "3.0.0-rc.1", "description": "The library provides the out of box accessing to MediaWiki API in both browsers & Node.js, and the syntax is very similar to vanilla `new mw.Api()`. TypeScript definition included~", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -32,7 +32,9 @@ "node", "api-wrapper", "typescript", - "axios" + "fetch", + "fetch-api", + "fexios" ], "author": "Dragon-Fish ", "license": "MIT", @@ -41,8 +43,9 @@ }, "homepage": "https://github.com/moegirlwiki/wiki-saikou#readme", "dependencies": { - "@lylajs/core": "^1.2.0", - "@vue/reactivity": "^3.3.4" + "@vue/reactivity": "^3.3.4", + "fexios": "^1.3.0", + "tslib": "^2.6.0" }, "devDependencies": { "@types/chai": "^4.3.5", @@ -56,7 +59,6 @@ "mocha": "^10.2.0", "rimraf": "^5.0.1", "ts-mocha": "^10.0.0", - "tslib": "^2.6.0", "tsup": "^7.1.0", "tsx": "^3.12.7", "typescript": "^5.1.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2741f97..6a9c797 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,12 +5,15 @@ settings: excludeLinksFromLockfile: false dependencies: - '@lylajs/core': - specifier: ^1.2.0 - version: 1.2.0 '@vue/reactivity': specifier: ^3.3.4 version: 3.3.4 + fexios: + specifier: ^1.3.0 + version: 1.3.0 + tslib: + specifier: ^2.6.0 + version: 2.6.0 devDependencies: '@types/chai': @@ -46,9 +49,6 @@ devDependencies: ts-mocha: specifier: ^10.0.0 version: 10.0.0(mocha@10.2.0) - tslib: - specifier: ^2.6.0 - version: 2.6.0 tsup: specifier: ^7.1.0 version: 7.1.0(typescript@5.1.6) @@ -523,10 +523,6 @@ packages: wrap-ansi-cjs: /wrap-ansi@7.0.0 dev: true - /@lylajs/core@1.2.0: - resolution: {integrity: sha512-JFkOzbi3i6g2Ho4Ec9AknOuL8lyr8jinQh3XPuv8QSJ0PIJG1wGMDgKPUEOeXJbKY5tKu7Y97+dP7oidpAehvw==} - dev: false - /@microsoft/api-extractor-model@7.27.4(@types/node@18.16.19): resolution: {integrity: sha512-HjqQFmuGPOS20rtnu+9Jj0QrqZyR59E+piUWXPMZTTn4jaZI+4UmsHSf3Id8vyueAhOBH2cgwBuRTE5R+MfSMw==} dependencies: @@ -1162,6 +1158,11 @@ packages: reusify: 1.0.4 dev: true + /fexios@1.3.0: + resolution: {integrity: sha512-OFRMKUkEE/hqIS6fG2WD5tmFTPqpCwhuBu1iwJho41ufHUPsNna+vLokzTuFGk2gMNF1fqy2M0pXwEUqKhza2g==} + engines: {node: ^16.15.0 || >=18.0.0} + dev: false + /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -2059,7 +2060,7 @@ packages: /tslib@2.6.0: resolution: {integrity: sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==} - dev: true + dev: false /tsup@7.1.0(typescript@5.1.6): resolution: {integrity: sha512-mazl/GRAk70j8S43/AbSYXGgvRP54oQeX8Un4iZxzATHt0roW0t6HYDVZIXMw0ZQIpvr1nFMniIVnN5186lW7w==} diff --git a/src/index.ts b/src/index.ts index 88d2d61..031f06a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,26 +8,21 @@ import { Ref, ref, computed, ComputedRef } from '@vue/reactivity' import { - LylaAdapterMeta, - createLyla, - LylaRequestOptions, - LylaResponse, -} from './modules/lyla-adapter-fetch' -import { Lyla } from '@lylajs/core' - -type LylaResponseWith = LylaResponse & { - data: T -} + Fexios, + FexiosConfigs, + FexiosRequestOptions, + FexiosFinalContext, +} from 'fexios' export class MediaWikiApi { baseURL: Ref - #requestHandler: ComputedRef> - #defaultOptions: Ref + #requestHandler: ComputedRef + #defaultOptions: Ref> #defaultParams: Ref #tokens: Record cookies: Record = {} - constructor(baseURL?: string, options?: LylaRequestOptions) { + constructor(baseURL?: string, options?: Partial) { // For MediaWiki environment if (!baseURL && typeof window === 'object' && (window as any).mediaWiki) { const scriptPath: string | undefined = ( @@ -42,7 +37,7 @@ export class MediaWikiApi { this.baseURL = ref(baseURL) this.#tokens = {} this.#defaultParams = ref({}) - this.#defaultOptions = ref({}) + this.#defaultOptions = ref({} as any) // Set default values this.defaultParams = { @@ -54,48 +49,21 @@ export class MediaWikiApi { this.defaultOptions = options || {} this.#requestHandler = computed(() => { - const options: LylaRequestOptions = { - ...this.#defaultOptions.value, - } - - options.hooks ??= {} - options.hooks.onInit ??= [] - options.hooks.onBeforeRequest ??= [] - options.hooks.onAfterResponse ??= [] - - // Inject default query params - options.hooks.onInit?.unshift((ctx) => { - // @ts-ignore FIXME: Type error during vite build, too bad! - ctx.query = { - ...this.#defaultParams.value, - ...ctx.query, - } - - // Fix baseURL - !ctx.url && (ctx.url = this.baseURL.value) - try { - ctx.url = new URL( - ctx.url, - this.baseURL.value.startsWith('http') - ? this.baseURL.value - : globalThis.location?.href - ).toString() - } catch (_) {} - - return ctx + const instance = MediaWikiApi.createRequestHandler(this.baseURL.value, { + ...this.defaultOptions, + query: this.defaultParams as any, }) - // Handle cookies for Node.js if (!('document' in globalThis)) { - options.hooks.onBeforeRequest.push((ctx) => { - ctx.headers = ctx.headers || {} + instance.interceptors.request.use((ctx) => { + ctx.headers = (ctx.headers as Record) || {} ctx.headers['cookie'] = Object.keys(this.cookies) .map((name) => `${name}=${this.cookies[name]}`) .join(';') return ctx }) - options.hooks.onAfterResponse.push((ctx) => { - const cookieHeaders = (ctx.detail.headers as Headers).get( + instance.interceptors.response.use((ctx) => { + const cookieHeaders = (ctx.rawResponse!.headers as Headers).get( 'set-cookie' ) const rawCookies = cookieHeaders?.split(',').map((i) => i.trim()) @@ -107,7 +75,7 @@ export class MediaWikiApi { }) } - return MediaWikiApi.createLylaInstance(this.baseURL.value, options) + return instance }) } @@ -122,36 +90,35 @@ export class MediaWikiApi { return item } } - static createLylaInstance(baseURL: string, options: LylaRequestOptions = {}) { - options.hooks ??= {} - options.hooks.onInit ??= [] - options.hooks.onBeforeRequest ??= [] - options.hooks.onAfterResponse ??= [] - options.hooks.onResponseError ??= [] - - options.hooks.onInit.push((ctx) => { - // console.info( - // '[onInit] beforeTransform', - // ctx.method, - // ctx.url, - // ctx.query, - // ctx.body - // ) - + static createRequestHandler( + baseURL: string, + options: Partial = {} + ) { + const instance = new Fexios(options) + instance.baseConfigs.baseURL = baseURL + + // Adjust body + instance.on('beforeInit', (ctx) => { if (ctx.method?.toLowerCase() !== 'post') { return ctx } - // Transform json to formdata - if (ctx.json) { - const form = new URLSearchParams('') - for (const key in ctx.json) { - const data = MediaWikiApi.normalizeParamValue(ctx.json[key]) - if (typeof data === 'undefined') continue - form.append(key, '' + data) - } - ctx.body = form - ctx.json = undefined + if ( + typeof ctx.body === 'object' && + ctx.body !== null && + !(ctx.body instanceof URLSearchParams) && + !(ctx.body instanceof FormData) + ) { + const body: any = ctx.body + Object.keys(body).forEach((key) => { + const data = MediaWikiApi.normalizeParamValue(body[key]) + if (typeof data === 'undefined' || data === null) { + delete body[key] + } else if (data !== body[key]) { + body[key] = data + } + }) + ctx.body = new URLSearchParams(ctx.body as any) } if ( @@ -169,18 +136,25 @@ export class MediaWikiApi { } }) // Adjust query - ctx.query ??= {} - ctx.query.format ??= '' + body.get('format') || 'json' - ctx.query.formatversion ??= '' + body.get('formatversion') || '2' - body.has('origin') && (ctx.query.origin = '' + body.get('origin')) + const searchParams = new URLSearchParams(ctx.query as any) + !searchParams.has('format') && + searchParams.set('format', '' + (body.get('format') || 'json')) + !searchParams.has('formatversion') && + searchParams.set( + 'formatversion', + '' + (body.get('formatversion') || '2') + ) + body.has('origin') && + searchParams.set('origin', '' + body.get('origin')) + ctx.query = Object.fromEntries(searchParams) } return ctx }) // Adjust query - options.hooks.onInit.push((ctx) => { - ctx.query ??= {} + instance.on('beforeInit', (ctx) => { + ctx.query = ctx.query as Record for (const key in ctx.query) { const data = MediaWikiApi.normalizeParamValue(ctx.query[key]) if (typeof data === 'undefined' || data === null) { @@ -189,52 +163,24 @@ export class MediaWikiApi { ctx.query[key] = '' + data } } - - // console.info('[onInit]', ctx.method?.toUpperCase(), ctx.url, { - // query: ctx.query, - // body: ctx.body, - // headers: ctx.headers, - // }) return ctx }) // Adjust origin param - options.hooks.onBeforeRequest.push((ctx) => { + instance.on('beforeRequest', (ctx) => { const url = new URL(ctx.url!) if (url.searchParams.has('origin')) { const origin = encodeURIComponent( url.searchParams.get('origin') || '' ).replace(/\./g, '%2E') - delete ctx.query + ctx.query = {} url.searchParams.delete('origin') ctx.url = `${url}${url.search ? '&' : '?'}origin=${origin}` } return ctx }) - /** - * response.data shortcut compatibility - */ - options.hooks.onAfterResponse.push((ctx) => { - Object.defineProperty(ctx, 'data', { - get() { - try { - return JSON.parse(ctx.body as string) - } catch (_) { - return ctx.body - } - }, - }) - return ctx - }) - - // @ts-ignore FIXME: Type error during vite build, too bad! - const { lyla } = createLyla({ - baseUrl: baseURL, - ...options, - }) - - return lyla + return instance } /** Syntactic Sugar */ @@ -246,7 +192,7 @@ export class MediaWikiApi { get defaultOptions() { return this.#defaultOptions.value } - set defaultOptions(options: LylaRequestOptions) { + set defaultOptions(options: Partial) { this.#defaultOptions.value = options } // defaultParams @@ -258,17 +204,17 @@ export class MediaWikiApi { } /** Base methods encapsulation */ - get(query: MwApiParams, options?: LylaRequestOptions) { - return this.request.get(this.baseURL.value, { + get(query: MwApiParams, options?: FexiosRequestOptions) { + return this.request.get('', { query: query as any, ...options, - }) as Promise> + }) } - post(data: MwApiParams, options?: LylaRequestOptions) { - return this.request.post(this.baseURL.value, { - json: data, - ...options, - }) as Promise> + post( + data: MwApiParams | URLSearchParams | FormData, + options?: FexiosRequestOptions + ) { + return this.request.post('', data, options) } async login( @@ -285,7 +231,7 @@ export class MediaWikiApi { lguserid: number lgusername: string }> { - this.defaultOptions.withCredentials = true + this.defaultOptions.credentials = 'include' const { data } = await this.postWithToken( 'login', { @@ -314,9 +260,9 @@ export class MediaWikiApi { blockid?: number blockedby?: string blockedbyid?: number - blockedtimestamp?: string blockreason?: string blockexpiry?: string + blockedtimestamp?: string } } }>({ @@ -329,7 +275,7 @@ export class MediaWikiApi { /** Token Handler */ async getTokens(type: MwTokenName[] = ['csrf']) { - this.defaultOptions.withCredentials = true + this.defaultOptions.credentials = 'include' const { data } = await this.get({ action: 'query', meta: 'tokens', @@ -350,7 +296,7 @@ export class MediaWikiApi { tokenType: MwTokenName, body: MwApiParams, options?: { tokenName?: string; retry?: number; noCache?: boolean } - ): Promise> { + ): Promise> { const { tokenName = 'token', retry = 3, noCache = false } = options || {} if (retry < 1) { return Promise.reject({ @@ -364,19 +310,23 @@ export class MediaWikiApi { return this.post({ [tokenName]: token, ...body, - }).catch(({ data }) => { - if ( - [data?.errors?.[0].code, data?.error?.code].includes('badtoken') || - ['NeedToken', 'WrongToken'].includes(data?.login?.result) - ) { - return this.postWithToken(tokenType, data, { - tokenName, - retry: retry - 1, - noCache: true, - }) - } - return Promise.reject(data) }) + .catch(({ data }) => { + if ( + [data?.errors?.[0].code, data?.error?.code].includes('badtoken') || + ['NeedToken', 'WrongToken'].includes(data?.login?.result) + ) { + return this.postWithToken(tokenType, data, { + tokenName, + retry: retry - 1, + noCache: true, + }) + } + return Promise.reject(data) + }) + .finally(() => { + delete this.#tokens[`${tokenType}token`] + }) } postWithEditToken(body: MwApiParams) { return this.postWithToken('csrf', body) @@ -407,7 +357,7 @@ export class MediaWikiApi { wikitext: string, title?: string, extraBody?: MwApiParams, - options?: LylaRequestOptions + options?: FexiosRequestOptions ): Promise { const { data } = await this.post( { @@ -423,9 +373,9 @@ export class MediaWikiApi { } export class MediaWikiForeignApi extends MediaWikiApi { - constructor(baseURL?: string, options?: LylaRequestOptions) { + constructor(baseURL?: string, options?: Partial) { super(baseURL, { - withCredentials: true, + credentials: 'include', ...options, }) this.defaultParams.origin = location.origin diff --git a/src/modules/lyla-adapter-fetch/adapter.ts b/src/modules/lyla-adapter-fetch/adapter.ts deleted file mode 100644 index e48fc45..0000000 --- a/src/modules/lyla-adapter-fetch/adapter.ts +++ /dev/null @@ -1,101 +0,0 @@ -import type { - LylaAdapter, - LylaAdapterMeta as LylaCoreAdapterMeta, -} from '@lylajs/core' - -export interface LylaAdapterMeta extends LylaCoreAdapterMeta { - method: - | 'get' - | 'GET' - | 'post' - | 'POST' - | 'put' - | 'PUT' - | 'patch' - | 'PATCH' - | 'head' - | 'HEAD' - | 'delete' - | 'DELETE' - | 'options' - | 'OPTIONS' - | 'connect' - | 'CONNECT' - | 'trace' - | 'TRACE' - networkErrorDetail: TypeError - requestBody: string | FormData - responseDetail: Response - responseType: 'arraybuffer' | 'blob' | 'text' - body: BodyInit -} - -function transformHeaders(headers: Headers): Record { - if (!headers) return {} - - const headerMap: Record = {} - headers.forEach((value, key) => { - headerMap[key] = value - }) - - return headerMap -} - -export const adapter: LylaAdapter = ({ - url, - method, - headers, - body, - responseType, - withCredentials, - onDownloadProgress, - onUploadProgress, - onResponse, - onNetworkError, -}): { - abort: () => void -} => { - const abortController = new AbortController() - const request = fetch(url, { - method, - headers, - body, - credentials: withCredentials ? 'include' : 'same-origin', - signal: abortController.signal, - }) - - request.then(async (response) => { - let body: any - if (responseType === 'blob') { - try { - body = await response.clone().blob() - } catch (error) {} - } else if (responseType === 'arraybuffer') { - try { - body = await response.clone().arrayBuffer() - } catch (error) {} - } - if (!body) { - body = await response.clone().text() - } - - onResponse( - { - status: response.status, - headers: transformHeaders(response.headers), - body, - }, - response - ) - }) - - request.catch((error) => { - onNetworkError(error) - }) - - return { - abort() { - abortController.abort() - }, - } -} diff --git a/src/modules/lyla-adapter-fetch/index.ts b/src/modules/lyla-adapter-fetch/index.ts deleted file mode 100644 index b6ca3a3..0000000 --- a/src/modules/lyla-adapter-fetch/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -export { adapter } from './adapter' -export type { LylaAdapterMeta } from './adapter' -export { lyla, isLylaError, createLyla } from './instance' -export type { - Lyla, - LylaError, - LylaProgress, - LylaRequestOptions, - LylaResponse, - LylaResponseError, - LylaDataConversionError, -} from './reexports' -export { LYLA_ERROR, LylaAbortController } from './reexports' diff --git a/src/modules/lyla-adapter-fetch/instance.ts b/src/modules/lyla-adapter-fetch/instance.ts deleted file mode 100644 index ab56e40..0000000 --- a/src/modules/lyla-adapter-fetch/instance.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createLyla as coreCreateLyla } from '@lylajs/core' -import { adapter } from './adapter' -import type { - LylaRequestOptions, - LylaRequestOptionsWithContext, -} from './reexports' - -export const { lyla, isLylaError } = coreCreateLyla(adapter, { - context: undefined, -}) - -export const createLyla = ( - options: LylaRequestOptionsWithContext, - ...overrides: LylaRequestOptions[] -) => { - return coreCreateLyla(adapter, options, ...overrides) -} diff --git a/src/modules/lyla-adapter-fetch/reexports.ts b/src/modules/lyla-adapter-fetch/reexports.ts deleted file mode 100644 index ba7b33a..0000000 --- a/src/modules/lyla-adapter-fetch/reexports.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { - LylaRequestOptions as LylaCoreRequestOptions, - LylaResponse as LylaCoreResponse, - Lyla as LylaCore, - LylaRequestOptionsWithContext as LylaCoreRequestOptionsWithContext, -} from '@lylajs/core' -import type { - LylaResponseError as LylaCoreResponseError, - LylaError as LylaCoreError, - LylaDataConversionError as LylaCoreDataConversionError, -} from '@lylajs/core' -import type { LylaAdapterMeta } from './adapter' - -// core -export type Lyla = LylaCore -export type LylaRequestOptions = LylaCoreRequestOptions< - C, - LylaAdapterMeta -> -export type LylaRequestOptionsWithContext = - LylaCoreRequestOptionsWithContext -export type LylaResponse = LylaCoreResponse< - T, - C, - LylaAdapterMeta -> - -// error -export type LylaResponseError = LylaCoreResponseError< - C, - LylaAdapterMeta -> -export type LylaDataConversionError = - LylaCoreDataConversionError -export type LylaError = LylaCoreError - -export { LYLA_ERROR, LylaProgress, LylaAbortController } from '@lylajs/core' diff --git a/test/1.core.spec.ts b/test/1.core.spec.ts index 3e70434..fbf448a 100644 --- a/test/1.core.spec.ts +++ b/test/1.core.spec.ts @@ -69,13 +69,13 @@ describe('MediaWikiApi', () => { // timeout: 114514, // } - // expect(api.ajax.defaults.baseURL).to.equal( + // expect(api.request.baseConfigs.baseURL).to.equal( // 'https://commons.moegirl.org.cn/api.php' // ) - // expect(api.ajax.defaults.params).to.deep.equal({ + // expect(api.request.baseConfigs.query).to.deep.equal({ // key1: 'value1', // key2: 'value2', // }) - // expect(api.ajax.defaults.timeout).to.equal(114514) + // expect(api.request.baseConfigs.timeout).to.equal(114514) // }) }) diff --git a/test/2.foreign.spec.ts b/test/2.foreign.spec.ts index df26c64..6422bac 100644 --- a/test/2.foreign.spec.ts +++ b/test/2.foreign.spec.ts @@ -14,7 +14,7 @@ const api = new MediaWikiForeignApi('https://commons.moegirl.org.cn/api.php', { describe('MediaWikiForeignApi', () => { it('[GET] siteinfo', async () => { - const { data, headers } = await api + const { data, response } = await api .get({ action: 'query', meta: 'siteinfo', @@ -23,22 +23,26 @@ describe('MediaWikiForeignApi', () => { console.warn(e) return Promise.reject(e) }) - expect(headers['access-control-allow-origin']).to.equal(location.origin) + expect(response.headers.get('access-control-allow-origin')).to.equal( + location.origin + ) expect(data.query.general.sitename).to.equal('萌娘共享') }) it('[GET] array as param', async () => { - const { data, headers } = await api.get({ + const { data, response } = await api.get({ action: 'query', meta: ['siteinfo', 'userinfo'], }) - expect(headers['access-control-allow-origin']).to.equal(location.origin) + expect(response.headers.get('access-control-allow-origin')).to.equal( + location.origin + ) expect(data.query.general).to.not.be.undefined expect(data.query.userinfo).to.not.be.undefined }) it('[POST] parse', async () => { - const { data, headers } = await api + const { data, response } = await api .post({ action: 'parse', title: 'Custom Page', @@ -51,7 +55,9 @@ describe('MediaWikiForeignApi', () => { return Promise.reject(e) }) // console.info({ data, headers }) - expect(headers['access-control-allow-origin']).to.equal(location.origin) + expect(response.headers.get('access-control-allow-origin')).to.equal( + location.origin + ) expect(data.parse.title).to.eq('Custom Page') expect(data.parse.text).to.includes('bold') expect(data.parse.text).to.includes('italic') diff --git a/vite.config.ts b/vite.config.ts index 56bf05c..104d7d9 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -2,6 +2,10 @@ import { resolve } from 'path' import { defineConfig } from 'vite' import dts from 'vite-plugin-dts' +const PROD = + process.env.NODE_ENV === 'production' && + process.env.BUILD_ENV !== 'development' + export default defineConfig({ build: { lib: { @@ -12,7 +16,9 @@ export default defineConfig({ }, sourcemap: true, }, - esbuild: {}, + esbuild: { + drop: PROD ? ['console'] : [], + }, define: { // @FIX Uncaught ReferenceError: process is not defined // @link https://github.com/vitejs/vite/issues/9186