Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,28 @@ async function rawRequest<T>(
if (opts.body !== undefined) headers['Content-Type'] = 'application/json';
if (token) headers.Authorization = `Bearer ${token}`;

const res = await fetch(url, {
method: opts.method ?? 'GET',
headers,
body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,
});
let res: Response;
try {
res = await fetch(url, {
method: opts.method ?? 'GET',
headers,
body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,
});
} catch (err) {
// Node's undici throws a bare `TypeError: fetch failed` and stashes the
// real reason (DNS, ECONNREFUSED, cert errors, …) on `cause`. Surface
// both so users can tell a misconfigured API URL from a real outage.
const cause = (err as { cause?: unknown }).cause;
const reason =
cause && typeof cause === 'object'
? ((cause as { code?: string }).code ?? (cause as Error).message ?? '')
: '';
throw new Error(
`Network error reaching ${url.origin}${reason ? ` (${reason})` : ''}. ` +
`Check TIMEBOOK_API_URL or your connection.`,
{ cause: err },
);
}

const text = await res.text();
let data: unknown = undefined;
Expand Down
5 changes: 4 additions & 1 deletion src/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ export interface StoredConfig {
createdAt?: string;
}

// Production serves both the React app and the JSON API from the same
// origin (`usetimebook.com/api/*`). There is no `api.usetimebook.com`
// subdomain, so the API URL defaults to the same host as the web URL.
const DEFAULT_CONFIG: StoredConfig = {
apiUrl: process.env.TIMEBOOK_API_URL ?? 'https://api.usetimebook.com',
apiUrl: process.env.TIMEBOOK_API_URL ?? 'https://usetimebook.com',
webUrl: process.env.TIMEBOOK_WEB_URL ?? 'https://usetimebook.com',
};

Expand Down
Loading