2026-06-04 21:32:28 -05:00
|
|
|
|
'use strict';
|
|
|
|
|
|
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
import type { Db } from '../types/db';
|
|
|
|
|
|
|
2026-05-03 19:51:57 -05:00
|
|
|
|
const cron = require('node-cron');
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
const { getDb, getSetting } = require('../db/database.cts');
|
refactor(server): migrate 10 services to TypeScript (.cts)
Continues the incremental server TS migration (after utils/*.mts and
paymentValidation.cts): converts 10 services to .cts (CommonJS TypeScript,
run natively via Node type-stripping — no build step), type-checked by
tsconfig.server.json.
Migrated: totpService, amountSuggestionService, encryptionService,
paymentAccountingService, statusService, aprService, driftService,
analyticsService, spendingService, billMerchantRuleService.
- types/db.d.ts: shared minimal better-sqlite3 Db/Statement types (the lib
ships none), reused across the migrated modules.
- Every require of a migrated service updated to the explicit .cts extension
(extensionless require does not resolve .cts) across routes / services /
db migrations / server.js / workers / tests — require-only changes.
- package.json: check:server find pattern now includes *.cts (it silently
skipped .cts before, so paymentValidation.cts had no node --check gate).
Behavior-preserving (types only). Verified: typecheck:server 0,
check:server 0, full server suite 226/226, real boot → /api/health 200.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 10:35:29 -05:00
|
|
|
|
const { buildTrackerRow, getCycleRange } = require('../services/statusService.cts');
|
2026-07-06 11:06:05 -05:00
|
|
|
|
const { pruneExpiredSessions } = require('../services/authService.cts');
|
|
|
|
|
|
const { pruneExpiredChallenges: pruneWebAuthnChallenges } = require('../services/webauthnService.cts');
|
2026-07-06 11:12:06 -05:00
|
|
|
|
const { runNotifications, runDriftNotifications } = require('../services/notificationService.cts');
|
2026-07-06 11:06:05 -05:00
|
|
|
|
const { runAllCleanup } = require('../services/cleanupService.cts');
|
2026-05-03 19:51:57 -05:00
|
|
|
|
const {
|
|
|
|
|
|
markWorkerError,
|
|
|
|
|
|
markWorkerStarted,
|
|
|
|
|
|
markWorkerSuccess,
|
2026-07-06 10:47:16 -05:00
|
|
|
|
} = require('../services/statusRuntime.cts');
|
2026-07-05 13:48:44 -05:00
|
|
|
|
const { localDateString, localDateStringDaysAgo } = require('../utils/dates.mts');
|
2026-05-03 19:51:57 -05:00
|
|
|
|
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
// The hour (0–23) the single daily job runs — configurable via 'reminder_hour'
|
|
|
|
|
|
// (default 6 AM). One source of truth for both the cron expression and next-run.
|
|
|
|
|
|
function resolveReminderHour(): number {
|
2026-07-05 16:10:25 -05:00
|
|
|
|
const parsed = parseInt(getSetting('reminder_hour') ?? '6', 10);
|
|
|
|
|
|
return Number.isInteger(parsed) && parsed >= 0 && parsed <= 23 ? parsed : 6;
|
|
|
|
|
|
}
|
2026-05-03 19:51:57 -05:00
|
|
|
|
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
function nextDailyRunIso(from: Date = new Date()): string {
|
2026-05-03 19:51:57 -05:00
|
|
|
|
const next = new Date(from);
|
2026-07-05 16:10:25 -05:00
|
|
|
|
next.setHours(resolveReminderHour(), 0, 0, 0);
|
2026-05-03 19:51:57 -05:00
|
|
|
|
if (next <= from) next.setDate(next.getDate() + 1);
|
|
|
|
|
|
return next.toISOString();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
async function runDailyTasks(): Promise<void> {
|
|
|
|
|
|
const db: Db = getDb();
|
2026-05-03 19:51:57 -05:00
|
|
|
|
const now = new Date();
|
|
|
|
|
|
const year = now.getFullYear();
|
|
|
|
|
|
const month = now.getMonth() + 1;
|
2026-06-10 19:28:54 -05:00
|
|
|
|
const todayStr = localDateString(now);
|
2026-05-03 19:51:57 -05:00
|
|
|
|
|
2026-06-04 21:32:28 -05:00
|
|
|
|
const bills = db.prepare('SELECT * FROM bills WHERE active = 1 AND deleted_at IS NULL').all();
|
|
|
|
|
|
|
|
|
|
|
|
if (bills.length > 0) {
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
const billIds = bills.map((b: any) => b.id);
|
2026-06-04 21:32:28 -05:00
|
|
|
|
const placeholders = billIds.map(() => '?').join(',');
|
2026-06-10 19:28:54 -05:00
|
|
|
|
const windowStart = localDateStringDaysAgo(90, now);
|
2026-06-04 21:32:28 -05:00
|
|
|
|
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
let allPayments: any[] = [];
|
2026-06-04 21:32:28 -05:00
|
|
|
|
try {
|
|
|
|
|
|
allPayments = db.prepare(`
|
|
|
|
|
|
SELECT * FROM payments
|
|
|
|
|
|
WHERE bill_id IN (${placeholders})
|
|
|
|
|
|
AND paid_date >= ?
|
|
|
|
|
|
AND deleted_at IS NULL
|
|
|
|
|
|
`).all(...billIds, windowStart);
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
} catch (err: any) {
|
2026-06-04 21:32:28 -05:00
|
|
|
|
console.error('[worker] Failed to batch-fetch payments:', err.message);
|
|
|
|
|
|
}
|
2026-05-03 19:51:57 -05:00
|
|
|
|
|
2026-06-04 21:32:28 -05:00
|
|
|
|
// Group payments by bill_id in memory
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
const paymentsByBill = new Map<any, any>();
|
2026-06-04 21:32:28 -05:00
|
|
|
|
for (const p of allPayments) {
|
|
|
|
|
|
if (!paymentsByBill.has(p.bill_id)) paymentsByBill.set(p.bill_id, []);
|
|
|
|
|
|
paymentsByBill.get(p.bill_id).push(p);
|
|
|
|
|
|
}
|
2026-06-03 21:55:15 -05:00
|
|
|
|
|
2026-06-04 21:32:28 -05:00
|
|
|
|
const markAutopay = db.prepare(
|
|
|
|
|
|
"UPDATE bills SET autodraft_status = 'assumed_paid', updated_at = datetime('now') WHERE id = ?"
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
for (const bill of bills) {
|
|
|
|
|
|
const range = getCycleRange(year, month, bill);
|
|
|
|
|
|
if (!range) continue; // bill does not apply this cycle
|
|
|
|
|
|
|
|
|
|
|
|
const payments = (paymentsByBill.get(bill.id) || []).filter(
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
(p: any) => p.paid_date >= range.start && p.paid_date <= range.end
|
2026-06-04 21:32:28 -05:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const row = buildTrackerRow(bill, payments, year, month, todayStr);
|
|
|
|
|
|
if (!row) continue;
|
|
|
|
|
|
|
|
|
|
|
|
// Auto-mark autopay bills as assumed_paid on due date
|
|
|
|
|
|
if (
|
|
|
|
|
|
bill.autopay_enabled &&
|
|
|
|
|
|
bill.autodraft_status === 'pending' &&
|
|
|
|
|
|
todayStr >= row.due_date
|
|
|
|
|
|
) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
markAutopay.run(bill.id);
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
} catch (err: any) {
|
2026-06-04 21:32:28 -05:00
|
|
|
|
console.error(`[worker] Failed to mark autopay for bill ${bill.id}:`, err.message);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-05-03 19:51:57 -05:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pruneExpiredSessions();
|
2026-06-05 22:05:23 -05:00
|
|
|
|
pruneWebAuthnChallenges(db);
|
2026-06-04 21:32:28 -05:00
|
|
|
|
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
await runNotifications().catch((err: any) => {
|
2026-06-04 21:32:28 -05:00
|
|
|
|
console.error('[worker] Notification error (non-fatal):', err.message);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
await runDriftNotifications().catch((err: any) => {
|
2026-05-30 14:33:55 -05:00
|
|
|
|
console.error('[worker] Drift notification error (non-fatal):', err.message);
|
|
|
|
|
|
});
|
2026-05-03 19:51:57 -05:00
|
|
|
|
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
await runAllCleanup().catch((err: any) => {
|
2026-05-03 19:51:57 -05:00
|
|
|
|
console.error('[worker] Cleanup error (non-fatal):', err.message);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
markWorkerSuccess(nextDailyRunIso());
|
|
|
|
|
|
console.log(`[worker] Daily tasks ran at ${todayStr}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
let scheduledTask: any = null;
|
2026-07-05 16:10:25 -05:00
|
|
|
|
|
|
|
|
|
|
// (Re)create the daily cron at the configured hour. Stops any prior task first.
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
function scheduleDaily(): void {
|
2026-07-05 16:10:25 -05:00
|
|
|
|
if (scheduledTask) {
|
|
|
|
|
|
scheduledTask.stop();
|
|
|
|
|
|
scheduledTask = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
const hour = resolveReminderHour();
|
|
|
|
|
|
scheduledTask = cron.schedule(`0 ${hour} * * *`, () => {
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
runDailyTasks().catch((err: any) => {
|
2026-07-05 16:10:25 -05:00
|
|
|
|
markWorkerError(err, nextDailyRunIso());
|
|
|
|
|
|
console.error('[worker] Daily task error:', err);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
// Called when 'reminder_hour' changes so it applies without a restart.
|
|
|
|
|
|
function rescheduleDailyWorker(): void {
|
2026-07-05 16:10:25 -05:00
|
|
|
|
try {
|
|
|
|
|
|
scheduleDaily();
|
|
|
|
|
|
markWorkerStarted(nextDailyRunIso());
|
|
|
|
|
|
console.log(`[worker] Rescheduled daily tasks to ${resolveReminderHour()}:00`);
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
} catch (err: any) {
|
2026-07-05 16:10:25 -05:00
|
|
|
|
console.error('[worker] Failed to reschedule daily worker:', err.message);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
function start(): void {
|
2026-05-03 19:51:57 -05:00
|
|
|
|
markWorkerStarted(nextDailyRunIso());
|
|
|
|
|
|
|
|
|
|
|
|
// Run once at startup
|
refactor(server): migrate middleware, workers, and db layer to TypeScript (.cts)
- middleware/ (5): requireAuth, securityHeaders, errorFormatter, csrf,
rateLimiter — fully typed against the shared http Req/Res/Next types.
- workers/dailyWorker — fully typed.
- db/ (4): database, subscriptionCatalogSeed, migrations/versionedMigrations,
migrations/legacyReconcileMigrations — large dynamic schema/migration infra,
converted with @ts-nocheck (typing deferred). All requires updated to .cts.
Behavior-preserving. Verified: typecheck:server 0, check:server 0, suite 226/226.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:34:08 -05:00
|
|
|
|
runDailyTasks().catch((err: any) => {
|
2026-05-03 19:51:57 -05:00
|
|
|
|
markWorkerError(err, nextDailyRunIso());
|
|
|
|
|
|
console.error('[worker] Startup task error:', err);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-07-05 16:10:25 -05:00
|
|
|
|
// Run every day at the configured hour (default 6 AM)
|
|
|
|
|
|
scheduleDaily();
|
2026-05-03 19:51:57 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-05 16:10:25 -05:00
|
|
|
|
module.exports = { start, runDailyTasks, nextDailyRunIso, rescheduleDailyWorker };
|