Skip to content

Fix API ESM module resolution (production 500s) - #52

Merged
rphlr merged 1 commit into
productionfrom
fix/api-esm-module-resolution
Jul 7, 2026
Merged

Fix API ESM module resolution (production 500s)#52
rphlr merged 1 commit into
productionfrom
fix/api-esm-module-resolution

Conversation

@rphlr

@rphlr rphlr commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Incident fix

Every /api/* function was returning HTTP 500 FUNCTION_INVOCATION_FAILED in production with:

ERR_MODULE_NOT_FOUND: Cannot find module '/var/task/api/_shared/rate-limit' imported from /var/task/api/booking/availability.js

Vercel's Node runtime loads the compiled functions as ESM, which requires explicit file extensions on relative imports. The extensionless imports (pre-existing) only surfaced now because this was the first production rebuild in 43 days and the Vercel builder changed. This affected contact, newsletter, and all booking endpoints.

Adds .js extensions to all relative imports under api/ (44 imports, 14 files). Works for both ESM and CJS; vite/esbuild resolves .js.ts in dev and tests (109 tests still pass).

…lution

Vercel's Node runtime resolves compiled functions as ESM, which requires explicit file extensions on relative imports. The extensionless imports crashed every /api function with ERR_MODULE_NOT_FOUND once the project was rebuilt with the current Vercel builder. Adding .js works for both ESM and CJS and is resolved by vite/esbuild in dev and tests.
Copilot AI review requested due to automatic review settings July 7, 2026 12:17
@rphlr
rphlr merged commit 1e0e633 into production Jul 7, 2026
5 checks passed
@rphlr
rphlr deleted the fix/api-esm-module-resolution branch July 7, 2026 12:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses production 500s on Vercel caused by ESM module resolution requiring explicit file extensions on relative imports in compiled /api/* serverless functions. It updates API code to use .js extensions in relative import specifiers so the deployed ESM output can be loaded correctly.

Changes:

  • Added .js extensions to relative imports across API endpoints and shared modules to satisfy Vercel’s ESM loader.
  • Updated booking endpoint internal imports under api/booking/_lib to use explicit .js specifiers.
  • Updated a booking library test import to match the new explicit extension style.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
api/send.ts Adds explicit .js extensions for shared API imports to avoid ESM runtime resolution failures.
api/newsletter.ts Adds explicit .js extensions for shared API imports to avoid ESM runtime resolution failures.
api/booking/create.ts Adds explicit .js extensions for booking endpoint internal module imports for ESM compatibility.
api/booking/cancel.ts Adds explicit .js extensions for booking endpoint internal module imports for ESM compatibility.
api/booking/lookup.ts Adds explicit .js extensions for booking endpoint internal module imports for ESM compatibility.
api/booking/reschedule.ts Adds explicit .js extensions for booking endpoint internal module imports for ESM compatibility.
api/booking/availability.ts Adds explicit .js extensions for booking endpoint internal module imports for ESM compatibility.
api/booking/_lib/tokens.ts Adds explicit .js extension for internal config import used at runtime.
api/booking/_lib/slots.ts Adds explicit .js extension for internal config import used at runtime.
api/booking/_lib/mailer.ts Adds explicit .js extension for internal config import used at runtime.
api/booking/_lib/google-calendar.ts Adds explicit .js extension for internal config import used at runtime.
api/booking/_lib/d1.ts Adds explicit .js extension for internal config import used at runtime.
api/booking/_lib/slots.test.ts Updates test import to use explicit .js extension for consistency with ESM-style specifiers.
api/_shared/rate-limit.ts Adds explicit .js extension for shared type import to align specifiers under ESM.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread api/booking/create.ts
Comment on lines +13 to +17
} from './_lib/config.js';
import { exec, isUniqueConstraintError, queryFirst } from './_lib/d1.js';
import { createEvent, deleteEvent, getBusyIntervals } from './_lib/google-calendar.js';
import { sendBookingConfirmation } from './_lib/mailer.js';
import { isSlotValid } from './_lib/slots.js';
Comment thread api/send.ts
Comment on lines 4 to +8
import {
applyRateLimitHeaders,
checkRateLimit,
getRateLimitIdentifier,
} from './_shared/rate-limit';
} from './_shared/rate-limit.js';
Comment on lines 1 to +3
import { createHmac, randomUUID, timingSafeEqual } from 'crypto';

import { getRuntimeEnv } from './config';
import { getRuntimeEnv } from './config.js';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants