Migrate to TypeScript, Netlify Functions v2, and pnpm#28
Open
Migrate to TypeScript, Netlify Functions v2, and pnpm#28
Conversation
Pure renames with no content changes to preserve git history.
- Migrate from yarn to pnpm - Add TypeScript 6.0.2 with tsconfig.json - Update to Node 24 - Update dependencies: @netlify/functions v5, @slack/web-api v7, airtable v0.12, graphql-request v7, luxon v3.7 - Remove node-fetch (using native fetch) and graphql peer dep - Move dotenv to devDependencies - Add type packages and tsx for build script - Update netlify.toml for pnpm and v2 functions config
- util/slack.ts: ESM imports, type annotations, drop node-fetch/dotenv - functions/slack-events/messages.ts: ESM exports, add SlackUser types
- Convert daily, hourly, and weekly reminders to v2 Request/Response - Replace schedule() wrapper with export const config - Convert CommonJS to ESM imports - Add shared CMS GraphQL types in types/cms.ts - Remove dotenv dependency (Netlify injects env vars)
- slack-events: v2 handler with HMAC verification via req.text() - slack-interactivity: v2 handler (stub) - slack-send-message-background: v2 handler for async message dispatch - Convert CommonJS to ESM, add type annotations
- Convert handler to v2 Request/Response pattern - Move lazy requires to top-level ESM imports - Add Room type and Zoom webhook request types - HMAC verification uses req.text() for raw body - Airtable helper with proper types
- Convert CommonJS requires to ESM imports - Replace __dirname with import.meta.url derivation - Keep dotenv/config for local development
esbuild handles module resolution for Netlify Functions and tsx handles it for the build script, so nodenext's strict .js extension requirement is unnecessary.
Add util/env.ts with requireEnv() helper that throws a clear error if a required environment variable is missing. Applied to all env vars that were previously using the ! operator.
- verifyHmacSignature: core timing-safe HMAC-SHA256 comparison - verifySlackRequest: Slack-specific wrapper with timestamp staleness check - verifyZoomSignature: Zoom-specific wrapper for x-zm-signature header
Add hmacSha256Hex() for Zoom's endpoint URL validation challenge. Remove node:crypto import from zoom handler — all crypto operations now go through the shared verify module.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Request/Responseinstead of Lambdaevent/context)@netlify/functionsv5,@slack/web-apiv7,graphql-requestv7,airtablev0.12,luxonv3.7node-fetch(using native fetch) andgraphqlpeer deputil/verify.tsutil/env.tswithrequireEnv()for runtime env var validation (no non-null assertions)env.d.tsfor typedprocess.envtypes/cms.ts(GraphQL responses),types/room.ts(Airtable room shape)Netlify Functions v2 changes
export const config: Config = { schedule }instead ofschedule()wrapperRequestand returnResponsereq.text()for raw body access (critical for signature computation)-backgroundsuffix) convention still works in v2File renames
All
.js→.tsrenames done viagit mvin the first commit to preserve git history.Test plan
pnpm run typecheckpasses with zero errorspnpm run buildgeneratesdata/rooms.json(requiresAIRTABLE_COWORKING_BASE)