import urls, { normalizeUrl } from '@cloudpss/env'; import * as defaultFetcher from '@cloudpss/fetch'; /** HTTP client 使用的 fetch 实现 */ export type HttpFetcher = Pick; /** HTTP 选项 */ interface HttpClientOptionsBase { /** 使用的 token */ token?: string; /** 使用的其他 token */ altTokens: readonly string[]; /** API 地址,eg: https://cloudpss.net/api */ apiUrl: string; /** 使用 `X-Http-Method` `X-Http-Path` 进行访问 */ apiTunnel?: boolean; /** GraphQL 地址,eg: https://cloudpss.net/graphql */ gqlUrl: string; /** fetch 实现 */ fetcher: HttpFetcher; /** WebSocket 实现 */ webSocket: typeof WebSocket; /** 是否为开发环境 */ dev: boolean; } /** HTTP 选项 */ export type HttpClientOptions = Partial; /** HTTP 配置 */ export type HttpClientConfig = Readonly; /** 检查 JWT */ function simpleCheckToken(token: string): void { if (!/^(?:[\w-]+\.){2}[\w-]+$/g.test(token)) { throw new Error(`Invalid JWT token.`); } } /** 获取 token */ function getToken(token?: string): string | undefined { if (token == null || token === '') return undefined; if (typeof token != 'string') throw new Error('token must be a string'); simpleCheckToken(token); return token; } /** 获取 url */ function getUrl(url: string | undefined): string | undefined { if (!url) return undefined; return normalizeUrl(url); } /** 校验并生成完整配置 */ export function createConfig(options: HttpClientOptions = {}): HttpClientConfig { const token = getToken(options.token); const altTokens = Object.freeze( (options.altTokens ?? (options as { alterTokens?: string[] }).alterTokens ?? []) .map((t) => getToken(t)) .filter((t): t is string => t != null), ); const apiUrl = getUrl(options.apiUrl); const gqlUrl = getUrl(options.gqlUrl); return Object.freeze({ token, altTokens, get apiUrl() { return apiUrl ?? urls.API_URL; }, apiTunnel: !!options.apiTunnel, get gqlUrl() { return gqlUrl ?? urls.GQL_URL; }, fetcher: options.fetcher ?? defaultFetcher, webSocket: options.webSocket ?? defaultFetcher.WebSocket, dev: !!options.dev, }); }