dreame-action/app/services/dreame-client.server.ts

97 lines
2.6 KiB
TypeScript

import { buildSignedRequest } from "./signature.server";
import type { ActivityConfig, PushPayload, PushResponse, StatusResponse, ThirdPartyResult } from "./activity.server";
export async function callStatus(config: ActivityConfig): Promise<ThirdPartyResult<StatusResponse>> {
const payload = { activity_id: config.activityId };
return callDreame<StatusResponse>(config.statusApiUrl, config, payload, mockStatusResponse);
}
export async function callPush(config: ActivityConfig, payload: PushPayload): Promise<ThirdPartyResult<PushResponse>> {
return callDreame<PushResponse>(config.pushApiUrl, config, payload, mockPushResponse);
}
async function callDreame<TBody>(
url: string,
config: ActivityConfig,
payload: unknown,
mockFactory: () => TBody,
): Promise<ThirdPartyResult<TBody>> {
const signed = buildSignedRequest(payload, {
apiAppId: config.apiAppId,
apiSecret: config.apiSecret,
});
if ((process.env.THIRD_PARTY_MODE || "mock") === "mock") {
if (process.env.DREAME_MOCK_TIMEOUT === "true") {
return {
httpOk: false,
status: 408,
body: { code: 408, msg: "mock timeout" } as TBody,
requestBody: signed.bodyString,
responseBody: '{"code":408,"msg":"mock timeout"}',
};
}
const body = mockFactory();
return {
httpOk: true,
status: 200,
body,
requestBody: signed.bodyString,
responseBody: JSON.stringify(body),
};
}
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), Number(process.env.THIRD_PARTY_TIMEOUT_MS || 5000));
try {
const response = await fetch(url, {
method: "POST",
headers: signed.headers,
body: signed.bodyString,
signal: controller.signal,
});
const responseText = await response.text();
const body = parseJson(responseText) as TBody;
return {
httpOk: response.ok,
status: response.status,
body,
requestBody: signed.bodyString,
responseBody: responseText,
};
} finally {
clearTimeout(timeout);
}
}
function mockStatusResponse(): StatusResponse {
return {
code: Number(process.env.DREAME_MOCK_STATUS_CODE || 0),
data: {
status: process.env.DREAME_MOCK_STATUS_ACTIVE !== "false",
trigger: ["order_end", "card_add"],
},
};
}
function mockPushResponse(): PushResponse {
return {
code: Number(process.env.DREAME_MOCK_PUSH_CODE || 0),
};
}
function parseJson(text: string): unknown {
if (!text) {
return {};
}
try {
return JSON.parse(text);
} catch {
return { code: -1, msg: text };
}
}