1import { DEFAULT_HOSTED_APP_URL } from "@t3tools/shared/connectAuth";
2
3import { getPairingTokenFromUrl, setPairingTokenOnUrl } from "@t3tools/shared/remote";
4
5export interface HostedPairingRequest {
6 readonly host: string;
7 readonly token: string;
8 readonly label: string;
9}
10
11export type HostedAppChannel = "latest" | "nightly";
12
13export function configuredHostedAppUrl(): string {
14 return import.meta.env.VITE_HOSTED_APP_URL?.trim() || DEFAULT_HOSTED_APP_URL;
15}
16
17function configuredBackendUrl(): string {
18 return import.meta.env.VITE_HTTP_URL?.trim() || import.meta.env.VITE_WS_URL?.trim() || "";
19}
20
21function configuredHostedAppChannel(): HostedAppChannel | null {
22 const channel = import.meta.env.VITE_HOSTED_APP_CHANNEL?.trim().toLowerCase();
23 return channel === "latest" || channel === "nightly" ? channel : null;
24}
25
26function originFromUrl(value: string): string | null {
27 try {
28 return new URL(value).origin;
29 } catch {
30 return null;
31 }
32}
33
34export function isHostedStaticApp(url?: URL): boolean {
35 if (configuredBackendUrl()) {
36 return false;
37 }
38
39 if (configuredHostedAppChannel()) {
40 return true;
41 }
42
43 if (url === undefined && (typeof window === "undefined" || window.location === undefined)) {
44 return false;
45 }
46
47 const hostedOrigin = originFromUrl(configuredHostedAppUrl());
48 return hostedOrigin !== null && (url ?? new URL(window.location.href)).origin === hostedOrigin;
49}
50
51export function readHostedPairingRequest(url: URL = new URL(window.location.href)) {
52 const host = url.searchParams.get("host")?.trim() ?? "";
53 const token = getPairingTokenFromUrl(url)?.trim() ?? "";
54 const label = url.searchParams.get("label")?.trim() ?? "";
55
56 if (!host || !token) {
57 return null;
58 }
59
60 return {
61 host,
62 token,
63 label,
64 } satisfies HostedPairingRequest;
65}
66
67export function hasHostedPairingRequest(url: URL = new URL(window.location.href)): boolean {
68 return readHostedPairingRequest(url) !== null;
69}
70
71export function buildHostedPairingUrl(input: {
72 readonly host: string;
73 readonly token: string;
74 readonly label?: string | null;
75}): string {
76 const url = new URL("/pair", configuredHostedAppUrl());
77 url.searchParams.set("host", input.host);
78
79 const label = input.label?.trim();
80 if (label) {
81 url.searchParams.set("label", label);
82 }
83
84 return setPairingTokenOnUrl(url, input.token).toString();
85}
86
87export function buildHostedChannelSelectionUrl(input: {
88 readonly channel: HostedAppChannel;
89}): string {
90 const url = new URL("/__t3code/channel", configuredHostedAppUrl());
91 url.searchParams.set("channel", input.channel);
92 return url.toString();
93}