1import type {
2 AuthClientMetadataDeviceType,
3 AuthClientPresentationMetadata,
4 ClientOs,
5 DesktopBridge,
6} from "@t3tools/contracts";
7
8interface BrowserIdentity {
9 readonly userAgent: string;
10 readonly platform: string;
11 readonly maxTouchPoints: number;
12}
13
14function clientOsFromElectronPlatform(platform: string | undefined): ClientOs {
15 switch (platform) {
16 case "darwin":
17 return "macOS";
18 case "win32":
19 return "Windows";
20 case "linux":
21 return "Linux";
22 default:
23 return platform ? "other" : "unknown";
24 }
25}
26
27function isIpadosDesktopUserAgent(identity: BrowserIdentity): boolean {
28 return (
29 /macintosh/i.test(identity.userAgent) &&
30 /mac/i.test(identity.platform) &&
31 identity.maxTouchPoints > 1
32 );
33}
34
35export function browserClientOs(identity: BrowserIdentity): ClientOs {
36 const userAgent = identity.userAgent;
37 if (userAgent.trim() === "") return "unknown";
38 if (/iphone|ipad|ipod/i.test(userAgent) || isIpadosDesktopUserAgent(identity)) return "iOS";
39 if (/android/i.test(userAgent)) return "Android";
40 if (/cros/i.test(userAgent)) return "ChromeOS";
41 if (/windows/i.test(userAgent)) return "Windows";
42 if (/macintosh|mac os x/i.test(userAgent)) return "macOS";
43 if (/linux|x11/i.test(userAgent)) return "Linux";
44 return "other";
45}
46
47export function browserDeviceType(identity: BrowserIdentity): AuthClientMetadataDeviceType {
48 const userAgent = identity.userAgent;
49 if (userAgent.trim() === "") return "unknown";
50 if (
51 /ipad|tablet|kindle|silk/i.test(userAgent) ||
52 (/android/i.test(userAgent) && !/mobile/i.test(userAgent)) ||
53 isIpadosDesktopUserAgent(identity)
54 ) {
55 return "tablet";
56 }
57 if (/iphone|ipod|android.+mobile|mobile/i.test(userAgent)) return "mobile";
58 return "desktop";
59}
60
61export function clientPresentationMetadata(input: {
62 readonly appVersion: string;
63 readonly identity: BrowserIdentity;
64 readonly desktopBridge: Pick<DesktopBridge, "getClientPlatform"> | undefined;
65}): AuthClientPresentationMetadata {
66 if (input.desktopBridge !== undefined) {
67 return {
68 label: "The Knife Desktop",
69 deviceType: "desktop",
70 os: clientOsFromElectronPlatform(input.desktopBridge.getClientPlatform?.()),
71 surface: "desktop",
72 ...(input.appVersion === "0.0.0" ? {} : { appVersion: input.appVersion }),
73 };
74 }
75
76 return {
77 label: "The Knife Web",
78 deviceType: browserDeviceType(input.identity),
79 os: browserClientOs(input.identity),
80 surface: "web",
81 ...(input.appVersion === "0.0.0" ? {} : { appVersion: input.appVersion }),
82 };
83}