63 lines
1.9 KiB
TypeScript
63 lines
1.9 KiB
TypeScript
function trimTrailingSlashes(value: string): string {
|
||
return value.replace(/\/+$/, '');
|
||
}
|
||
|
||
export type AppVariant = 'development' | 'staging' | 'production';
|
||
|
||
function resolveAppVariant(): AppVariant {
|
||
const raw = process.env.EXPO_PUBLIC_APP_VARIANT;
|
||
if (raw === 'development' || raw === 'staging' || raw === 'production') {
|
||
return raw;
|
||
}
|
||
if (__DEV__) {
|
||
return 'development';
|
||
}
|
||
// Release 包若 env 未写入 APP_VARIANT(例如仅复制了 env/staging 到 .env 但变量缺失),
|
||
// 仍按 API 是否为 http 推断预发,避免关于页误隐藏后端地址。
|
||
const apiUrl = process.env.EXPO_PUBLIC_API_URL ?? '';
|
||
if (apiUrl.startsWith('http://')) {
|
||
return 'staging';
|
||
}
|
||
return 'production';
|
||
}
|
||
|
||
/** Shown on About screen for dev/staging builds only (never production Release). */
|
||
export function shouldShowAboutBackendUrl(variant: AppVariant = appVariant): boolean {
|
||
// Metro / 调试包:始终显示,避免 .env 误用 production variant 时看不到实际 API
|
||
if (__DEV__) {
|
||
return true;
|
||
}
|
||
return variant === 'development' || variant === 'staging';
|
||
}
|
||
|
||
export const appVariant = resolveAppVariant();
|
||
|
||
export const config = {
|
||
apiBaseUrl: trimTrailingSlashes(
|
||
process.env.EXPO_PUBLIC_API_URL ?? 'http://192.168.10.151:8000',
|
||
),
|
||
wsBaseUrl: trimTrailingSlashes(
|
||
process.env.EXPO_PUBLIC_WS_URL ?? 'ws://192.168.10.151:8000',
|
||
),
|
||
isDebugMode: __DEV__,
|
||
appVariant,
|
||
showAboutBackendUrl: shouldShowAboutBackendUrl(),
|
||
|
||
api: {
|
||
timeoutMs: 30_000,
|
||
refreshPath: '/api/auth/refresh',
|
||
},
|
||
|
||
ws: {
|
||
reconnectMaxRetries: 10,
|
||
reconnectBaseDelayMs: 1_000,
|
||
reconnectMaxDelayMs: 30_000,
|
||
heartbeatIntervalMs: 30_000,
|
||
/**
|
||
* 仅当 App 处于 `background` 连续超过该毫秒数才释放当前会话 WebSocket。
|
||
* 短暂切到其它应用再返回时保持连接,避免反复重连。
|
||
*/
|
||
backgroundDisconnectAfterMs: 300_000,
|
||
},
|
||
} as const;
|