Merge pull request #425 from trails-cool/fix/journal-dynamic-import-warnings

fix(journal): remove ineffective dynamic imports
This commit is contained in:
Ullrich Schäfer 2026-05-24 12:08:45 +02:00 committed by GitHub
commit 8729ad03c7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 13 additions and 14 deletions

View file

@ -5,6 +5,7 @@ import { activities, routes, syncImports, users, follows } from "@trails-cool/db
import type { Visibility } from "@trails-cool/db/schema/journal";
import { validateGpx, writeGeom } from "./gpx-save.server.ts";
import type { GpxData } from "./gpx-save.server.ts";
import { enqueueOptional } from "./boss.server.ts";
export interface ActivityInput {
name: string;
@ -36,7 +37,6 @@ export async function updateActivityVisibility(
// idempotent, so toggling private→public→private→public won't spam
// followers (only the first transition per activity emits).
if (visibility === "public") {
const { enqueueOptional } = await import("./boss.server.ts");
await enqueueOptional("notifications-fanout", { activityId: id }, { source: "updateActivityVisibility" });
}
@ -91,7 +91,6 @@ export async function createActivity(ownerId: string, input: ActivityInput) {
// updateActivityVisibility path for the case where visibility is set
// up-front rather than flipped later).
if (input.visibility === "public") {
const { enqueueOptional } = await import("./boss.server.ts");
await enqueueOptional("notifications-fanout", { activityId: id }, { source: "createActivity" });
}

View file

@ -4,6 +4,8 @@
// is bound to the Node process — startWorker calls boss.start(); the
// SIGTERM handler stops it.
import { logger } from "./logger.server.ts";
// Structurally typed (we only need `send`) so we don't have to pull
// pg-boss into the journal app's dep graph just for the typedef.
interface BossLike {
@ -43,9 +45,6 @@ export async function enqueueOptional(
const boss = getBoss();
await boss.send(queue, data);
} catch (err) {
// Lazy import to avoid cycles in test environments where logger.server
// pulls in env-dependent setup.
const { logger } = await import("./logger.server.ts");
logger.warn({ err, queue, ...ctx }, "boss.send failed; continuing");
}
}

View file

@ -8,6 +8,7 @@
import { decrypt } from "../../../crypto.server.ts";
import { fetchKomootTours, fetchKomootTourGpx } from "../../../komoot.server.ts";
import { isAlreadyImported, importActivity } from "../../../sync/imports.server.ts";
import { getServiceById } from "../../manager.ts";
import type {
CapabilityContext,
ImportableList,
@ -58,7 +59,6 @@ export const komootImporter: Importer = {
return ctx.withFreshCredentials(async (rawCreds) => {
const creds = rawCreds as KomootCreds;
const { getServiceById } = await import("../../manager.ts");
const service = await getServiceById(ctx.serviceId);
if (!service) throw new Error(`Connected service ${ctx.serviceId} not found`);

View file

@ -7,6 +7,7 @@
import { fitToGpx } from "../../fit.ts";
import { fetchWithTimeout } from "../../../http.server.ts";
import { importActivity, isAlreadyImported } from "../../../sync/imports.server.ts";
import { getServiceById } from "../../manager.ts";
import type {
CapabilityContext,
ImportableList,
@ -116,7 +117,6 @@ export const wahooImporter: Importer = {
// Resolve the connected service's user id via the capability context.
// The caller (route handler) supplies userId out-of-band — for now the
// route handler bridges the gap. We use the manager's getServiceById.
const { getServiceById } = await import("../../manager.ts");
const service = await getServiceById(ctx.serviceId);
if (!service) throw new Error(`Connected service ${ctx.serviceId} not found`);

View file

@ -9,6 +9,7 @@ import { getSessionUser } from "~/lib/auth/session.server";
import { LocaleProvider } from "~/components/LocaleContext";
import { AlphaBanner } from "~/components/AlphaBanner";
import { useUnreadNotifications } from "~/hooks/useUnreadNotifications";
import { countUnread } from "~/lib/notifications.server";
import { Footer } from "~/components/Footer";
import { AccountDropdown } from "~/components/AccountDropdown";
import { MobileNavMenu } from "~/components/MobileNavMenu";
@ -69,12 +70,9 @@ export async function loader({ request }: Route.LoaderArgs) {
// Unread-notification count for the navbar bell badge. Pending follow
// requests are not separately counted here — each pending request
// creates an unread `follow_request_received` notification, so the
// unread count already covers them. Hidden behind a dynamic import so
// the root layout doesn't pull in the notifications module on
// anonymous renders.
// unread count already covers them.
let unreadNotifications = 0;
if (user) {
const { countUnread } = await import("./lib/notifications.server.ts");
unreadNotifications = await countUnread(user.id);
}

View file

@ -8,6 +8,7 @@ import { getRoute, getRouteWithVersions, deleteRoute, updateRoute } from "~/lib/
import { getDb } from "~/lib/db";
import { syncPushes } from "@trails-cool/db/schema/journal";
import { getService } from "~/lib/connected-services";
import { computeDays, parseGpxAsync } from "@trails-cool/gpx";
export async function loadRouteDetail(request: Request, id: string | undefined) {
const routeId = id ?? "";
@ -32,7 +33,6 @@ export async function loadRouteDetail(request: Request, id: string | undefined)
let waypoints: Array<{ lat: number; lon: number; name?: string; isDayBreak?: boolean; note?: string; osmId?: number; poiTags?: Record<string, string> }> = [];
if (route.gpx) {
try {
const { computeDays, parseGpxAsync } = await import("@trails-cool/gpx");
const gpxData = await parseGpxAsync(route.gpx);
waypoints = gpxData.waypoints.map((w) => ({
lat: w.lat,

View file

@ -9,6 +9,7 @@ import {
} from "~/lib/connected-services";
import { getImportedIds, recordImport } from "~/lib/sync/imports.server";
import { createActivity } from "~/lib/activities.server";
import { generateGpx } from "@trails-cool/gpx";
export async function loadSyncImportProvider(request: Request, provider: string | undefined) {
const user = await requireSessionUser(request);
@ -77,9 +78,11 @@ export async function syncImportProviderAction(request: Request, provider: strin
if (!resp.ok) throw new Error(`Download failed: ${resp.status}`);
return Buffer.from(await resp.arrayBuffer());
});
// Lazy-load to avoid bundling fit-file-parser into all routes.
// Lazy-load fit-file-parser only — it's heavy and only the FIT
// ingestion path needs it. @trails-cool/gpx is already pulled in
// statically by other modules in the chunk, so the dynamic import
// there was ineffective.
const { default: FitParser } = await import("fit-file-parser");
const { generateGpx } = await import("@trails-cool/gpx");
const parsed = await new Promise<Record<string, unknown>>((resolve, reject) => {
const parser = new FitParser({ force: true });
// eslint-disable-next-line @typescript-eslint/no-explicit-any