74 lines
2.1 KiB
TypeScript
74 lines
2.1 KiB
TypeScript
/**
|
|
* Browser/React Native-safe kill switch client for platform-service.
|
|
*
|
|
* Checks GET /api/flags/kill-switch to determine if the app is disabled.
|
|
* Fail-open: returns { disabled: false } on any network error.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* import { createKillSwitchClient } from '@bytelyst/kill-switch-client';
|
|
*
|
|
* const ks = createKillSwitchClient({
|
|
* baseUrl: 'http://localhost:4003/api',
|
|
* productId: 'nomgap',
|
|
* });
|
|
*
|
|
* const result = await ks.check();
|
|
* if (result.disabled) showBlockScreen(result.message);
|
|
* ```
|
|
*/
|
|
|
|
export interface KillSwitchClientConfig {
|
|
/** Platform-service base URL (e.g. "http://localhost:4003/api"). */
|
|
baseUrl: string;
|
|
|
|
/** Product identifier sent as x-product-id header. */
|
|
productId: string;
|
|
|
|
/** Platform string for the query (e.g. "mobile", "web"). Default: "mobile". */
|
|
platform?: string;
|
|
}
|
|
|
|
export interface KillSwitchResult {
|
|
disabled: boolean;
|
|
message: string | null;
|
|
}
|
|
|
|
export interface KillSwitchClient {
|
|
/** Check if the app is disabled. Fail-open on any error. */
|
|
check(): Promise<KillSwitchResult>;
|
|
}
|
|
|
|
export function createKillSwitchClient(config: KillSwitchClientConfig): KillSwitchClient {
|
|
const { baseUrl, productId, platform = 'mobile' } = config;
|
|
|
|
async function check(): Promise<KillSwitchResult> {
|
|
try {
|
|
const requestId =
|
|
typeof globalThis.crypto?.randomUUID === 'function'
|
|
? globalThis.crypto.randomUUID()
|
|
: `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
|
|
const res = await globalThis.fetch(
|
|
`${baseUrl}/flags/kill-switch?platform=${encodeURIComponent(platform)}`,
|
|
{
|
|
headers: { 'x-product-id': productId, 'x-request-id': requestId },
|
|
}
|
|
);
|
|
|
|
if (!res.ok) return { disabled: false, message: null };
|
|
|
|
const data = (await res.json()) as KillSwitchResult;
|
|
return {
|
|
disabled: data.disabled ?? false,
|
|
message: data.message ?? null,
|
|
};
|
|
} catch {
|
|
// Fail-open: network errors should NOT block the user
|
|
return { disabled: false, message: null };
|
|
}
|
|
}
|
|
|
|
return { check };
|
|
}
|