wiki-saikou
Version:
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~
181 lines (174 loc) • 7.52 kB
text/typescript
import { Fexios, FexiosFinalContext, FexiosConfigs, FexiosRequestOptions } from 'fexios';
export * from 'fexios';
interface FexiosSaikou extends Fexios {
_tokens: Map<string, string>;
}
/**
* FexiosSaikou
*
* A pre-configured Fexios instance with MediaWiki-friendly defaults:
* - MediaWiki-specific request/response params normalization
* - built-in token management
* - error handling
*
* @author dragon-fish <dragon-fish@qq.com>
* @license MIT
*
* @param {string|URL} payload create a new FexiosSaikou instance with the given baseURL
* @param {Fexios} payload or make the given Fexios instance a FexiosSaikou instance
*/
declare function createFexiosSaikou(payload: string | URL | Fexios): FexiosSaikou;
type MwApiParams = Record<string, string | number | string[] | undefined | boolean | File | Blob>;
type MwTokenName = 'createaccount' | 'csrf' | 'login' | 'patrol' | 'rollback' | 'userrights' | 'watch';
type MwApiResponse<T = any> = T & {
batchcomplete?: string;
continue?: {
[key: string]: string;
continue: string;
};
limits?: Record<string, number>;
error?: MwApiResponseError;
errors?: MwApiResponseError[];
warnings?: Record<string, {
warnings: string;
}>;
};
interface MwApiResponseError {
code: string;
text: string;
module?: string;
docref?: string;
}
/**
* Error codes for WikiSaikouError
*/
declare enum WikiSaikouErrorCode {
HTTP_ERROR = "HTTP_ERROR",
LOGIN_FAILED = "LOGIN_FAILED",
LOGIN_RETRY_LIMIT_EXCEEDED = "LOGIN_RETRY_LIMIT_EXCEEDED",
TOKEN_RETRY_LIMIT_EXCEEDED = "TOKEN_RETRY_LIMIT_EXCEEDED"
}
/**
* Server-side (MediaWiki API) business error:
* - fetch succeeded but JSON includes `error` or `errors.length > 0`
* - Special states (e.g., login NeedToken/WrongToken) are also considered API-side errors
* Note: network/retry issues belong to WikiSaikouError, not this class
*/
declare class MediaWikiApiError extends Error {
readonly errors: MwApiResponseError[];
readonly cause?: FexiosFinalContext;
readonly name = "MediaWikiApiError";
readonly code: string;
constructor(errors: MwApiResponseError[], cause?: FexiosFinalContext);
get firstError(): MwApiResponseError;
isBadTokenError(): boolean;
toString(): string;
static is(data?: any): data is MediaWikiApiError;
static normalizeErrors(errors: MwApiResponseError[]): MwApiResponseError[];
}
/**
* WikiSaikou Error:
* - Transport/network failures (e.g., fetch failure, HTTP layer issues)
* - SDK behavioral errors such as exhausted internal retries or misconfigurations
* Note: When MediaWiki API responds with JSON containing error/errors, a MediaWikiApiError should be thrown instead
*/
declare class WikiSaikouError extends Error {
readonly code: WikiSaikouErrorCode;
readonly message: string;
readonly cause?: FexiosFinalContext;
readonly name = "WikiSaikouError";
constructor(code: WikiSaikouErrorCode, message?: string, cause?: FexiosFinalContext);
static is(data?: any, code?: WikiSaikouErrorCode): data is WikiSaikouError;
}
/**
* Helper functions for WikiSaikouError and MediaWikiApiError
*/
declare namespace WikiSaikouError {
function includesMediaWikiApiError(data?: any): boolean;
const normalizeMwApiErrors: typeof MediaWikiApiError.normalizeErrors;
function extractMediaWikiApiErrors(data?: any): MwApiResponseError[];
function isBadTokenError(data?: any): boolean;
}
declare namespace MwParamNormalizer {
function normalizeParamValue(item: any): string | Blob | undefined;
function normalizeBody(body: any): FormData | undefined;
}
interface WikiSaikouConfig {
/**
* @default undefined // required in Node.js environment
* @default `${wgServer}${wgScriptPath}/api.php` // in MW pages
* @description The MediaWiki API endpoint, e.g. "https://www.mediawiki.org/w/api.php"
* @optional In real MediaWiki browser pages, `baseURL` can be omitted and will be inferred automatically based on `window.mw`
*/
baseURL: string;
/**
* Transport/runtime options passed to the underlying Fexios instance (headers, fetch, credentials, etc.).
* @default { responseType: 'json' }
*/
fexiosConfigs: Partial<FexiosConfigs>;
/**
* Default query parameters merged into every request.
* @default { action: 'query' }
*/
defaultParams: MwApiParams;
/**
* When true, responses whose JSON body contains `error`/`errors` will throw `MediaWikiApiError` even if HTTP status is 2xx.
* @default false
*/
throwOnApiError: boolean;
}
type WikiSaikouInitConfig = Omit<Partial<WikiSaikouConfig>, 'baseURL'> & {
baseURL: string;
};
/**
* WikiSaikou Core class
* @internal You **SHOULD NOT** use this class directly, instead, use the `MediaWikiApi` class.
* @author dragon-fish <dragon-fish@qq.com>
* @license MIT
*/
declare class WikiSaikouCore {
readonly config: Required<WikiSaikouConfig>;
readonly version: any;
readonly request: FexiosSaikou;
static INIT_DEFAULT_PARAMS: MwApiParams;
static DEFAULT_CONFIGS: Required<WikiSaikouConfig>;
/** @deprecated Use `new MediaWikiApi(config)` instead */
constructor(baseURL?: string, defaultOptions?: Partial<FexiosConfigs>, defaultParams?: MwApiParams);
constructor(config?: WikiSaikouInitConfig);
setBaseURL(baseURL: string): this;
/** Base methods encapsulation */
get<T = any>(query: MwApiParams, options?: Partial<FexiosRequestOptions>): Promise<FexiosFinalContext<MwApiResponse<T>>>;
post<T = any>(data: MwApiParams | URLSearchParams | FormData, options?: Partial<FexiosRequestOptions>): Promise<FexiosFinalContext<MwApiResponse<T>>>;
/**
* Wrap a request to map non-2xx responses containing MediaWiki API error bodies
* into MediaWikiApiError when throwOnApiError=true, and then pass 2xx responses
* through handleApiResponse for unified processing.
*/
private runRequestWithApiErrorMapping;
private throwIfApiError;
private handleApiResponse;
/** Token Handler */
get tokens(): Map<string, string>;
fetchTokens(types?: MwTokenName[]): Promise<Map<string, string>>;
getToken(type?: MwTokenName, noCache?: boolean): Promise<string>;
badToken(type: MwTokenName): Map<string, string>;
postWithToken<T = any>(tokenType: MwTokenName, body: MwApiParams, options?: {
tokenName?: string;
retry?: number;
noCache?: boolean;
fexiosOptions?: Partial<FexiosRequestOptions>;
}): Promise<FexiosFinalContext<MwApiResponse<T>>>;
postWithEditToken<T = any>(body: MwApiParams): Promise<FexiosFinalContext<MwApiResponse<T>>>;
/** @deprecated Use `this.config.baseURL` instead */
get baseURL(): string;
/** @deprecated Use `this.config.defaultParams` instead */
get defaultParams(): MwApiParams;
/** @deprecated Use `this.config.fexiosConfigs` instead */
get defaultOptions(): Partial<FexiosConfigs>;
/** @deprecated Use `createFexiosSaikou` instead */
static readonly createRequestHandler: typeof createFexiosSaikou;
/** @deprecated Use `this.getToken` instead */
token: (type?: MwTokenName, noCache?: boolean) => Promise<string>;
}
export { MediaWikiApiError, WikiSaikouCore as MwApiBase, MwParamNormalizer, WikiSaikouCore, WikiSaikouError, WikiSaikouErrorCode, createFexiosSaikou };
export type { FexiosSaikou, MwApiParams, MwApiResponse, MwApiResponseError, MwTokenName, WikiSaikouConfig, WikiSaikouInitConfig };