Files
pastilhasandClaude Opus 5 8a446bb4b5 offscale, extracted from the platform into its own repository
The tailnet plugin — machines, users, pre-auth keys, access policy and device
invites. Moved out of officerdev/platform, where it had lived in plugins/ since
the plugin system was built.

Until now this code existed in exactly one place: the platform repository. That
made "gitignore the plugins directory" impossible to do safely, because
untracking it would have left 49 files on a single disk with no remote. This
repository is what makes that move safe.

Same extraction as plugins/music before it: source only, no history. The
platform's history still holds every commit that shaped this, and the SHAs cited
across the codebase keep resolving — replaying it here would have created a
second, divergent account of the same work.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 18:12:57 +00:00

36 lines
1.5 KiB
TypeScript

// Date formatting for the Headscale views. The sidecar already turned protobuf's zero timestamp into null,
// so null genuinely means "never" here and every helper says so rather than printing a fake date.
export function timeAgo(iso: string | null): string {
if (!iso) return 'never';
const seconds = Math.round((Date.now() - new Date(iso).getTime()) / 1000);
if (!Number.isFinite(seconds)) return 'unknown';
if (seconds < 0) return 'just now';
if (seconds < 60) return 'just now';
const minutes = Math.round(seconds / 60);
if (minutes < 60) return `${minutes}m ago`;
const hours = Math.round(minutes / 60);
if (hours < 24) return `${hours}h ago`;
const days = Math.round(hours / 24);
if (days < 365) return `${days}d ago`;
return `${Math.round(days / 365)}y ago`;
}
/** "in 3d" / "5h ago" — signed, for expiry dates that may be either side of now. */
export function timeUntil(iso: string | null): string {
if (!iso) return 'never';
const seconds = Math.round((new Date(iso).getTime() - Date.now()) / 1000);
if (!Number.isFinite(seconds)) return 'unknown';
if (seconds < 0) return timeAgo(iso);
const minutes = Math.round(seconds / 60);
if (minutes < 60) return `in ${Math.max(1, minutes)}m`;
const hours = Math.round(minutes / 60);
if (hours < 24) return `in ${hours}h`;
return `in ${Math.round(hours / 24)}d`;
}
export function fullDate(iso: string | null): string {
if (!iso) return 'never';
return new Date(iso).toLocaleString();
}