mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-05 07:28:37 +08:00
fix: 兼容插件自由 API 响应
This commit is contained in:
@@ -154,6 +154,19 @@ describe('MoviePilot API client', () => {
|
||||
expect(notifier.error).toHaveBeenCalledWith('Plugin rejected request')
|
||||
})
|
||||
|
||||
it.each([
|
||||
['object', { plugin: 'demo', count: 2 }],
|
||||
['array', [{ id: 1 }, { id: 2 }]],
|
||||
['scalar', 'ready'],
|
||||
['null', null],
|
||||
])('插件客户端原样交付非 envelope payload:%s', async (_label, payload) => {
|
||||
const { pluginApi } = createApiClients({ adapter: resolveWith(payload), notifier })
|
||||
|
||||
await expect(pluginApi.get('/plugin/demo')).resolves.toEqual(payload)
|
||||
expect(notifier.error).not.toHaveBeenCalled()
|
||||
expect(notifier.success).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('Blob 成功响应绕过 envelope 解包', async () => {
|
||||
const blob = new Blob(['moviepilot'], { type: 'application/octet-stream' })
|
||||
const { api } = createApiClients({ adapter: resolveWith(blob), notifier })
|
||||
|
||||
@@ -74,7 +74,7 @@ describe('API application wiring', () => {
|
||||
vi.useRealTimers()
|
||||
})
|
||||
|
||||
it('向 window 暴露插件 envelope 客户端,而内部默认导出数据客户端', async () => {
|
||||
it('向 window 暴露插件最终 payload 客户端,而内部默认导出数据客户端', async () => {
|
||||
const module = await import('@/api')
|
||||
|
||||
expect(window.MoviePilotAPI).toBe(module.pluginApi)
|
||||
|
||||
+8
-4
@@ -68,6 +68,9 @@ export interface DataApiClient extends Omit<
|
||||
): Promise<R>
|
||||
}
|
||||
|
||||
/** 插件与联邦组件接收 endpoint 最终 payload,方法签名不暴露 AxiosResponse 外壳。 */
|
||||
export type PluginApiClient = DataApiClient
|
||||
|
||||
/** 请求层使用的反馈出口,由应用入口接到全局 Toast。 */
|
||||
export interface ApiFeedbackNotifier {
|
||||
error(message: string): void
|
||||
@@ -83,7 +86,7 @@ export interface ApiClientHooks {
|
||||
reportConnectionFailure?(reason: 'network-error' | 'timeout' | 'server-unreachable'): void
|
||||
}
|
||||
|
||||
/** 创建内部数据客户端与插件原始协议客户端时所需的配置。 */
|
||||
/** 创建内部数据客户端与插件最终 payload 客户端时所需的配置。 */
|
||||
export interface CreateApiClientsOptions extends CreateAxiosDefaults {
|
||||
hooks?: ApiClientHooks
|
||||
notifier?: ApiFeedbackNotifier
|
||||
@@ -181,10 +184,10 @@ export function resolveConnectionFailureReason(
|
||||
return null
|
||||
}
|
||||
|
||||
/** 创建普通数据客户端和保持插件 ABI 的原始 envelope 客户端。 */
|
||||
/** 创建普通数据客户端和保持插件自由响应 ABI 的最终 payload 客户端。 */
|
||||
export function createApiClients(options: CreateApiClientsOptions = {}): {
|
||||
api: DataApiClient
|
||||
pluginApi: AxiosInstance
|
||||
pluginApi: PluginApiClient
|
||||
} {
|
||||
const { hooks, notifier, resolveFallbackMessage, setupInstance, ...axiosConfig } = options
|
||||
const api = axios.create(axiosConfig)
|
||||
@@ -202,7 +205,7 @@ export function createApiClients(options: CreateApiClientsOptions = {}): {
|
||||
|
||||
return {
|
||||
api: api as DataApiClient,
|
||||
pluginApi,
|
||||
pluginApi: pluginApi as PluginApiClient,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,6 +229,7 @@ function installResponseInterceptors(
|
||||
|
||||
const payload: unknown = response.data
|
||||
if (!isApiResponse(payload)) {
|
||||
// 联邦插件自行声明 API 响应;非宿主 envelope 必须原样交给插件调用方。
|
||||
if (responseMode === 'envelope') return payload
|
||||
const error = new ApiRequestError(resolveFallback('invalid-envelope', resolveFallbackMessage), {
|
||||
code: AxiosError.ERR_BAD_RESPONSE,
|
||||
|
||||
+4
-3
@@ -14,6 +14,7 @@ import {
|
||||
type ApiFeedbackMode,
|
||||
type ApiFallbackMessageKey,
|
||||
type DataApiClient,
|
||||
type PluginApiClient,
|
||||
} from './client'
|
||||
|
||||
/** 带连接探测和反馈策略的 MoviePilot 请求配置。 */
|
||||
@@ -70,7 +71,7 @@ const { api, pluginApi } = createApiClients({
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
MoviePilotAPI: AxiosInstance
|
||||
MoviePilotAPI: PluginApiClient
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,10 +89,10 @@ function initializeClient(instance: AxiosInstance | DataApiClient) {
|
||||
})
|
||||
}
|
||||
|
||||
// 插件远程组件依赖完整 envelope ABI,内部页面则默认使用已解包的数据客户端。
|
||||
// 插件远程组件接收 endpoint 的最终 payload,内部页面默认使用严格 envelope 解包客户端。
|
||||
if (typeof window !== 'undefined') window.MoviePilotAPI = pluginApi
|
||||
|
||||
export { ApiRequestError, getApiBusinessErrorMessage, isApiBusinessFailure, isApiResponse, pluginApi }
|
||||
export type { ApiFeedbackMode, DataApiClient }
|
||||
export type { ApiFeedbackMode, DataApiClient, PluginApiClient }
|
||||
|
||||
export default api
|
||||
|
||||
Reference in New Issue
Block a user