chore(cleanup): trim 13 dead exports surfaced by knip

Narrow each helper's visibility to its actual reach instead of leaving
it exported "just in case":

  - Drop the `export` keyword on file-local helpers / constants:
    `getTrendSentiment`, `isPRWithin30Days`, `buildCoachMetricSourceType`,
    `countPassedSchedules`, `getGithubConfig`, `isComparisonBaseline`,
    `DASHBOARD_LAYOUT_VERSION`, `INTL_LOCALE_MAP`, `SIDE_EFFECT_NOTES_MAX`,
    `MEDICATION_CATEGORIES`, `openApiBase`, `ALL_MOOD_GRANULARITIES`.
  - Remove never-used dead code:
    `CodexOAuthNotConfiguredError` (declared as a backwards-compat shim
    no caller ever consumed), `editMessageReplyMarkup` (Telegram method
    nothing on the bot dispatch tree calls), and the stale
    `DISPLAY_TIMEZONE` re-export from `src/lib/format.ts`.

Knip drops from 48 -> 35 unused exports. Pure narrowing / deletion;
no behaviour change.
This commit is contained in:
Marc-André Bombeck committed 2026-05-21 17:52:01 +02:00
1 parent 1b0bcadb50
commit 70ff3eef73
14 files changed
+17 -54

No files matched your search

+1 -1
View File
@@ -64,7 +64,7 @@ export type TrendDirectionSentiment = "up-good" | "up-bad" | "neutral";
*/
export type TrendSentimentDirection = "positive" | "negative" | "neutral";
export function getTrendSentiment(
function getTrendSentiment(
change: number | null | undefined,
sentiment: TrendDirectionSentiment,
): TrendSentimentDirection {
@@ -52,14 +52,12 @@ interface PersonalRecordBadgeProps {
const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000;
/**
* Pure freshness check — exported for unit testing so the component
* itself stays free of clock calls (the React purity linter rejects
* `Date.now()` inside a component body or hook initializer). Callers
* pass a `now` reference; consumers in production read it from the
* surrounding query refetch boundary where one stale-time tick =
* one new clock reading.
* Pure freshness check kept out of the component body so the React
* purity linter doesn't trip on the `Date.now()` reference; callers
* pass `now` from the surrounding query refetch boundary where one
* stale-time tick = one new clock reading.
*/
export function isPRWithin30Days(achievedAtIso: string, now: number): boolean {
function isPRWithin30Days(achievedAtIso: string, now: number): boolean {
const ts = new Date(achievedAtIso).getTime();
return Number.isFinite(ts) && now - ts <= THIRTY_DAYS_MS;
}
-14
View File
@@ -53,20 +53,6 @@ export function generateState(): string {
return base64url(randomBytes(32));
}
/**
* Backwards-compatible no-op type. Older callers that imported the error
* type continue to compile. Codex OAuth always considers itself
* configured because we ship the public client ID as the default.
*/
export class CodexOAuthNotConfiguredError extends Error {
constructor() {
super(
"Codex OAuth is not configured on this instance — set CODEX_OAUTH_CLIENT_ID",
);
this.name = "CodexOAuthNotConfiguredError";
}
}
export function getCodexClientId(): string {
return process.env.CODEX_OAUTH_CLIENT_ID?.trim() || DEFAULT_CLIENT_ID;
}
+1 -1
View File
@@ -106,7 +106,7 @@ export interface CoachFeedbackAttribution extends FeedbackAttribution {
metricSourceType: string;
}
export function buildCoachMetricSourceType(
function buildCoachMetricSourceType(
tone: string,
verbosity: string,
): string {
+2 -2
View File
@@ -91,7 +91,7 @@ export interface DashboardWidgetConfig {
export const COMPARISON_BASELINES = ["none", "lastMonth", "lastYear"] as const;
export type ComparisonBaseline = (typeof COMPARISON_BASELINES)[number];
export function isComparisonBaseline(
function isComparisonBaseline(
value: unknown,
): value is ComparisonBaseline {
return (
@@ -196,7 +196,7 @@ export interface DashboardLayout {
chartOverlayPrefs?: ChartOverlayPrefsMap;
}
export const DASHBOARD_LAYOUT_VERSION = 1;
const DASHBOARD_LAYOUT_VERSION = 1;
/**
* Default layout mirrors v1.1 behavior: core vitals always on, mood +
+1 -1
View File
@@ -37,7 +37,7 @@ export class GithubPublishError extends Error {
* Resolves the configured GitHub token + repo from AppSettings (or env).
* Returns null if no configuration is present (caller should treat as 503).
*/
export async function getGithubConfig(): Promise<{
async function getGithubConfig(): Promise<{
token: string;
repo: string;
} | null> {
+1 -1
View File
@@ -29,7 +29,7 @@ export const DISPLAY_TIMEZONE = "Europe/Berlin";
* `Intl.*`. When we add locales, extend this map — do not rely on the short
* tag directly since browsers differ in how they handle "en" vs "en-US".
*/
export const INTL_LOCALE_MAP: Record<Locale, string> = {
const INTL_LOCALE_MAP: Record<Locale, string> = {
de: "de-DE",
en: "en-US",
fr: "fr-FR",
+1 -3
View File
@@ -15,11 +15,9 @@
* stay consistent with the server-rendered locale.
*/
import { makeFormatters, DISPLAY_TIMEZONE } from "./format-locale";
import { makeFormatters } from "./format-locale";
import type { Locale } from "./i18n/config";
export { DISPLAY_TIMEZONE };
function activeLocale(): Locale {
if (typeof document === "undefined") return "en";
// Prefer the cookie (what SSR used) over localStorage to stay in sync
+1 -1
View File
@@ -1,7 +1,7 @@
import { prisma } from "@/lib/db";
import { MEDICATION_CATEGORY_VALUES } from "@/lib/validations/medication";
export const MEDICATION_CATEGORIES = MEDICATION_CATEGORY_VALUES;
const MEDICATION_CATEGORIES = MEDICATION_CATEGORY_VALUES;
export type MedicationCategory = (typeof MEDICATION_CATEGORIES)[number];
@@ -40,7 +40,7 @@ export const SIDE_EFFECT_ENTRY_VALUES = Object.values(
MedicationSideEffectEntry,
) as readonly MedicationSideEffectEntry[];
export const SIDE_EFFECT_NOTES_MAX = 280;
const SIDE_EFFECT_NOTES_MAX = 280;
/**
* v1.4.25 W21 Fix-N (code-M6) — `category` was dropped from the wire
+1 -1
View File
@@ -124,7 +124,7 @@ function isLastIntakeInCurrentWindow<Schedule extends ScheduleWindowInput>(
* to suppress "overdue" pills once the user has already covered every
* passed schedule with intake events for the day.
*/
export function countPassedSchedules<Schedule extends ScheduleWindowInput>(
function countPassedSchedules<Schedule extends ScheduleWindowInput>(
schedules: Schedule[],
nowBerlin: Date,
): number {
+1 -1
View File
@@ -26,7 +26,7 @@ import { createDocument, type ZodOpenApiObject } from "zod-openapi";
import { openApiPaths, openApiComponents } from "./routes";
export const openApiBase: Pick<
const openApiBase: Pick<
ZodOpenApiObject,
"openapi" | "info" | "servers" | "tags"
> = {
+1 -1
View File
@@ -51,7 +51,7 @@ import type {
const ASYNC_GRANULARITIES: RollupGranularity[] = ["WEEK", "MONTH", "YEAR"];
/** All granularities the rollup table tracks. */
export const ALL_MOOD_GRANULARITIES: RollupGranularity[] = [
const ALL_MOOD_GRANULARITIES: RollupGranularity[] = [
"DAY",
"WEEK",
"MONTH",
-19
View File
@@ -115,25 +115,6 @@ export async function answerTelegramCallbackQuery(
return json.ok;
}
export async function editMessageReplyMarkup(
botToken: string,
chatId: string,
messageId: number,
replyMarkup?: TelegramReplyMarkup,
): Promise<boolean> {
const json = await telegramApiRequest(botToken, "editMessageReplyMarkup", {
chat_id: chatId,
message_id: messageId,
reply_markup: replyMarkup ?? { inline_keyboard: [] },
});
if (!json.ok) {
getEvent()?.addWarning(
`[telegram] editMessageReplyMarkup failed: ${json.description}`,
);
}
return json.ok;
}
export async function setTelegramWebhook(
botToken: string,
webhookUrl: string,