Followup to #447. The audit ran on \`as unknown as\` first; this PR closes out \`as any\` separately. After this, \`grep -rn ' as any\\b' apps/ packages/\` returns 0 (excluding tests and node_modules). ## Sites fixed **\`apps/journal/server.ts\`** + **\`packages/jobs/src/types.ts\`** — \`komootBulkImportJob as any\`. The job had a typed payload (\`JobDefinition<KomootBulkImportData>\`) but the worker's \`JobDefinition[]\` array forced a contravariance cast at every site that mixed typed and untyped jobs. Dropped the generic from \`JobDefinition\` entirely; handlers narrow their own \`job.data\`. Only one job (komoot-bulk-import) used the generic, so the surface is tiny. **\`apps/journal/app/lib/connected-services/fit.ts\`** + same pattern in \`routes/sync.import.\$provider.server.ts\` — \`parser.parse(buffer as any, (err: unknown, d: any) => ...)\`. fit-file-parser's TypeScript types require \`Buffer<ArrayBuffer>\` specifically; a generic Node \`Buffer\` is structurally \`Buffer<ArrayBufferLike>\` (which includes SharedArrayBuffer). The runtime accepts either, so narrowed the cast to \`as Buffer<ArrayBuffer>\` — still a cast, but precise about what we're asserting and why. Removed the \`(err, d: any) => …\` ad-hoc callback typings; the library exports a proper \`FitParserCallback\`. **\`apps/mobile/lib/editor/RouteMap.tsx\`** — \`onLongPress\` handler took \`(event: any)\`. maplibre-react-native v11 generates the event type via React Native codegen but doesn't re-export it as a public TypeScript type. Replaced with a local structural slice of the parts we actually read. Net: 4 \`as any\` sites in prod code → 0. \`pnpm typecheck\` / \`lint\` / \`test\` all green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
29 lines
1,023 B
TypeScript
29 lines
1,023 B
TypeScript
import type { JobDefinition } from "@trails-cool/jobs";
|
|
import { logger } from "../lib/logger.server.ts";
|
|
import { runKomootBulkImport } from "../lib/komoot-bulk-import.server.ts";
|
|
|
|
type KomootCreds =
|
|
| { mode: "public"; komootUserId: string }
|
|
| { mode: "authenticated"; email: string; encryptedPassword: string; komootUserId: string };
|
|
|
|
interface KomootBulkImportData {
|
|
batchId: string;
|
|
userId: string;
|
|
creds: KomootCreds;
|
|
}
|
|
|
|
export const komootBulkImportJob: JobDefinition = {
|
|
name: "komoot-bulk-import",
|
|
retryLimit: 1,
|
|
expireInSeconds: 1800,
|
|
async handler(jobs) {
|
|
const batch = Array.isArray(jobs) ? jobs : [jobs];
|
|
for (const job of batch) {
|
|
// pg-boss serialized payload — caller (enqueueOptional) wrote it
|
|
// as KomootBulkImportData. Narrow at the boundary.
|
|
const { batchId, userId, creds } = job.data as KomootBulkImportData;
|
|
logger.info({ batchId, userId }, "komoot bulk import job started");
|
|
await runKomootBulkImport(batchId, userId, creds);
|
|
}
|
|
},
|
|
};
|