1import { environmentEndpointUrl } from "./environment/endpoint.ts";
2import type { ScheduledTaskWebhookEndpoint } from "@t3tools/contracts";
3import { isLocalLoopbackHost } from "@t3tools/shared/hostClassification";
4
5/**
6 * Where a sender can call a webhook task, as a client shows it. With T3
7 * Connect the server returns a public URL; without it the path is resolved on
8 * the address this client reaches the environment at.
9 */
10export interface WebhookAddress {
11 /** The URL to give a sender, or the bare path when no address is known. */
12 readonly address: string;
13 /** Whether `address` is a full URL a sender can call. */
14 readonly copyable: boolean;
15 /** One line on who can reach `address`; null for a T3 Connect URL. */
16 readonly note: string | null;
17}
18
19export function webhookAddress(
20 endpoint: ScheduledTaskWebhookEndpoint,
21 httpBaseUrl: string | null,
22): WebhookAddress {
23 if (endpoint.url !== null) {
24 return { address: endpoint.url, copyable: true, note: null };
25 }
26 if (httpBaseUrl === null) {
27 return {
28 address: endpoint.path,
29 copyable: false,
30 note: "Link this environment to T3 Connect for a public URL.",
31 };
32 }
33 const url = new URL(environmentEndpointUrl(httpBaseUrl, endpoint.path));
34 return {
35 address: url.href,
36 copyable: true,
37 note: isLocalLoopbackHost(url.hostname)
38 ? "Only this computer can call this address. Link T3 Connect for a public URL."
39 : "Works wherever this environment's address is reachable, for example over Tailscale or your own proxy. Link T3 Connect for a public URL.",
40 };
41}