Commit 7073275
feat(config): add typed ConfigService with Zod validation (PR 1 of 4) (#425)
* feat(config): add typed ConfigService with Zod validation
- Add lib/config/config-service.ts - centralized configuration singleton
- Add lib/config/schemas/ with Zod schemas for all config sections:
- core.schema.ts: NODE_ENV, APP_URL, DATABASE_URL, site info
- auth.schema.ts: AUTH_SECRET, OAuth providers, JWT, cookies
- email.schema.ts: SMTP, Resend, Novu providers
- payment.schema.ts: Stripe, LemonSqueezy, Polar, trial amounts
- analytics.schema.ts: PostHog, Sentry, Recaptcha, Vercel
- integrations.schema.ts: Trigger.dev, Twenty CRM, cron
- Add lib/config/utils/ with parsing and logging utilities
- Add lib/config/types.ts with exported TypeScript types
- Add lib/config/index.ts as module barrel export
- ConfigService validates all 113 env vars at startup
- Uses 'server-only' to prevent client-side usage
- Fail-fast on critical errors, warnings for non-critical
- Secrets automatically masked in logs
- Tree-shakeable exports for each config section
- No breaking changes - existing config files unchanged
* feat(config): migrate auth and payment to typed ConfigService
Migrate security-critical auth and payment code to use the new
typed ConfigService, replacing direct process.env access with
validated configuration.
Changes:
- lib/auth/providers.ts: Use authConfig for OAuth credentials
- lib/auth/config.ts: Use authConfig.supabase for Supabase config
- auth.config.ts: Use authConfig for OAuth provider setup
- lib/payment/config/payment-provider-manager.ts: Use paymentConfig for Stripe, LemonSqueezy, Polar
- lib/payment/lib/lemonsqueezy.ts: Use paymentConfig and coreConfig
- lib/payment/lib/providers/stripe-provider.ts: Use paymentConfig
- lib/payment/lib/providers/lemonsqueezy-provider.ts: Use paymentConfig and coreConfig
- lib/payment/lib/providers/polar-provider.ts: Use paymentConfig and coreConfig
- lib/types.ts: Use paymentConfig for pricing plan constants
- app/api/stripe/webhook/route.ts: Use coreConfig and emailConfig
- app/api/polar/webhook/route.ts: Use coreConfig for NODE_ENV
- app/api/polar/webhook/utils.ts: Use coreConfig and emailConfig
- app/api/polar/checkout/route.ts: Use coreConfig for NODE_ENV
- app/api/polar/subscription/portal/route.ts: Use coreConfig for NODE_ENV
- app/api/polar/subscription/portal/utils.ts: Use coreConfig for URLs
- app/api/polar/subscription/[subscriptionId]/reactivate/route.ts: Use coreConfig
- app/api/polar/subscription/[subscriptionId]/cancel/route.ts: Use coreConfig
- lib/config/server-config.ts: Wrap with ConfigService, add @deprecated notices
- lib/config.ts: Re-export ConfigService to fix module resolution
* feat(config): migrate core services to use ConfigService
- Migrate lib/db/ files (drizzle.ts, initialize.ts, seed.ts) to use coreConfig.DATABASE_URL and coreConfig.NODE_ENV
- Migrate lib/mail/index.ts to use coreConfig.APP_URL and emailConfig (renamed import to avoid conflict)
- Migrate lib/services/email-notification.service.ts with new getEmailServiceConfig() helper to reduce duplication
- Migrate lib/background-jobs/ files (config.ts, job-factory.ts, local-job-manager.ts) to use integrationsConfig.triggerDev and coreConfig.NODE_ENV
- Migrate lib/repositories/category.repository.ts to use coreConfig.content.dataRepository, ghToken, githubBranch
- Migrate lib/repositories/tag.repository.ts to use coreConfig.content.*
- Migrate lib/repositories/item.repository.ts to use coreConfig.content.*
- Migrate lib/repositories/twenty-crm-config.repository.ts to use integrationsConfig.twentyCrm
- Fix integrations.schema.ts TwentyCrmSyncMode to match actual types ('disabled' | 'platform' | 'direct_crm')
- Skip drizzle.config.ts (CLI tool correctly uses dotenv)
* feat(config): complete ConfigService migration across codebase
- Migrate lib/auth/index.ts to use coreConfig.DATABASE_URL and coreConfig.NODE_ENV
- Migrate lib/auth/supabase/server.ts and middleware.ts to use authConfig.supabase.url/anonKey
- Migrate lib/auth/session-cache.ts and cached-session.ts to use coreConfig.NODE_ENV for debug logging
- Migrate lib/auth/error-handler.ts to use authConfig for OAuth provider credentials
- Migrate app/api/auth/[...nextauth]/error-handler.ts to use coreConfig.NODE_ENV
- Migrate lib/payment/lib/utils/prices.ts to use paymentConfig.pricing.free/standard/premium
- Migrate lib/payment/services/payment-email.service.ts to use paymentConfig.stripe.*PriceId
- Migrate lib/services/sync-service.ts to use coreConfig.NODE_ENV
- Migrate lib/services/twenty-crm-sync-factory.ts to use integrationsConfig.twentyCrm.baseUrl/apiKey
- Migrate lib/repository.ts to use coreConfig.content.ghToken and dataRepository
- Migrate lib/newsletter/config.ts to use coreConfig.APP_URL and emailConfig.resend/novu.apiKey
- Migrate lib/constants.ts to use coreConfig.NODE_ENV and analyticsConfig.posthog.personalApiKey/projectId
- Migrate app/api/cron/sync/route.ts to use integrationsConfig.cron.secret
- Migrate app/api/verify-recaptcha/route.ts to use analyticsConfig.recaptcha.secretKey and coreConfig.NODE_ENV
- Fix integrations.schema.ts TwentyCrmSyncMode to match actual types ('disabled' | 'platform' | 'direct_crm')
* fix(config): correct AUTH_SECRET critical path from core to auth section
* fix(config): implement graceful fallback for non-critical validation errors
- Add .catch() handlers to URL/email fields to provide defaults on invalid format
- Add .catch() handlers to enum fields to fallback on invalid values
- Fix loadAndValidate() to use simplified logic (no more broken re-parse)
- Invalid URLs/emails/enums now silently use defaults instead of crashing
- Remaining validation errors after .catch() are truly unrecoverable
* fix(config): resolve client/server boundary issues in config imports
- Create lib/config/client.ts with client-safe siteConfig
- Update client components to import from @/lib/config/client
- Remove @/lib/config imports from payment providers (use process.env)
- Update lib/types.ts to use NEXT_PUBLIC_ env vars for pricing defaults
- Update lib/auth/config.ts to use NEXT_PUBLIC_SUPABASE_* directly
- Add sandbox/apiUrl options to PolarConfig interface
* fix(config): add safe default for EMAIL_SUPPORT to prevent webhook failures
- Schema marks EMAIL_SUPPORT as optional but getEmailConfig() throws when absent
- This breaks Stripe/LemonSqueezy webhooks for installs without EMAIL_SUPPORT set
- Add fallback default '[email protected]' consistent with existing patterns
- Polar handlers already handle this gracefully; align Stripe/Lemon behavior
* fix(db): resolve server-only import breaking migration scripts
Changes
- Created lib/db/config.ts - Script-safe database configuration
module that reads directly from process.env without server-only
guard, allowing migration/seed scripts to run outside Next.js
context
- Updated lib/db/drizzle.ts - Replaced @/lib/config import with
local ./config module; updated all coreConfig.DATABASE_URL and
coreConfig.NODE_ENV usages to use getDatabaseUrl() and getNodeEnv()
functions
- Updated lib/db/seed.ts - Replaced config import with ./config;
changed seed credential access to read directly from process.env
(SEED_ADMIN_EMAIL, SEED_ADMIN_PASSWORD, SEED_FAKE_USER_COUNT) to
avoid server-only issues
- Updated lib/db/initialize.ts - Replaced @/lib/config import with
./config; updated all database URL and NODE_ENV checks to use
script-safe functions
- Fixed lib/config/schemas/integrations.schema.ts - Corrected
TwentyCrmSyncMode enum values from 'disabled' | 'manual' |
'automatic' to 'disabled' | 'platform' | 'direct_crm' to match type
* fix(db): resolve server-only import breaking migration scripts
* fix(config): remove server-only imports from client-accessible modules
* fix(payment): align FREE price env var name with config schema
* fix(payment): handle NaN fallback for price env vars
* feat(config): centralize client-side config access
* feat(config): add DISABLE_AUTO_SYNC to core config schema
* refactor(repository): remove dead githubBranch fallback
* refactor(mail): remove dead APP_URL fallback
* fix(types): correct trial env var names to match .env.example
* fix: resolve config inconsistencies and OAuth env var mismatch
* fix(config): respect explicit enabled=false in integration schemas
* fix(config): handle NaN in payment pricing collection
* fix(config): handle NaN in SMTP port collection
* fix(config): handle NaN in seed user count collection
* fix(polar): add support email fallback in webhook utils
* style(auth): move import to top of session-cache.ts
* docs(config): clarify client import path in barrel export
* fix(config): resolve server-only import chain and missing exports
* fix: remove unused sponsor hook and add APP_URL fallback
- Comment out unused useActiveSponsorAds hook in item-detail.tsx
The sponsor ads rendering was disabled but hook was still called,
causing unnecessary API calls on every render
- Add fallback for undefined APP_URL in email config
Prevents malformed email links (password reset, verification)
when APP_URL is not configured
* fix(payment): remove dead APP_URL fallback in payment-provider-manager
* fix(config): restore EMAIL_PROVIDER env var support
- Add EMAIL_PROVIDER to email schema (string, default: 'resend')
- Collect EMAIL_PROVIDER from environment variables
- Add EMAIL_PROVIDER to .env.example with available options
- Fix regression from config service migration that hardcoded 'resend'
* fix(config): use EMAIL_PROVIDER in email-notification service
* fix(mail): use production-safe APP_URL fallback
---------
Co-authored-by: Ruslan Konviser <[email protected]>1 parent 3c60240 commit 7073275
File tree
72 files changed
+2601
-864
lines changed- .github/workflows
- app/api
- auth/[...nextauth]
- cron/sync
- polar
- checkout
- subscription
- [subscriptionId]
- cancel
- reactivate
- portal
- webhook
- stripe/webhook
- verify-recaptcha
- components
- item-detail
- lib
- auth
- supabase
- background-jobs
- config
- schemas
- utils
- constants
- db
- mail
- newsletter
- payment
- config
- lib
- providers
- utils
- services
- repositories
- seo
- services
- scripts
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
72 files changed
+2601
-864
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
134 | 134 | | |
135 | 135 | | |
136 | 136 | | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
137 | 140 | | |
138 | 141 | | |
139 | 142 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
102 | 102 | | |
103 | 103 | | |
104 | 104 | | |
105 | | - | |
106 | | - | |
| 105 | + | |
| 106 | + | |
107 | 107 | | |
108 | 108 | | |
109 | 109 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
35 | 36 | | |
36 | 37 | | |
37 | 38 | | |
38 | | - | |
39 | | - | |
| 39 | + | |
| 40 | + | |
40 | 41 | | |
41 | 42 | | |
42 | 43 | | |
| |||
57 | 58 | | |
58 | 59 | | |
59 | 60 | | |
60 | | - | |
| 61 | + | |
61 | 62 | | |
62 | | - | |
| 63 | + | |
63 | 64 | | |
64 | | - | |
| 65 | + | |
65 | 66 | | |
66 | 67 | | |
67 | 68 | | |
| |||
100 | 101 | | |
101 | 102 | | |
102 | 103 | | |
103 | | - | |
| 104 | + | |
104 | 105 | | |
105 | 106 | | |
106 | 107 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
14 | | - | |
| 14 | + | |
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
| |||
26 | 27 | | |
27 | 28 | | |
28 | 29 | | |
29 | | - | |
| 30 | + | |
30 | 31 | | |
31 | 32 | | |
32 | 33 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
| |||
314 | 315 | | |
315 | 316 | | |
316 | 317 | | |
317 | | - | |
| 318 | + | |
318 | 319 | | |
319 | 320 | | |
320 | 321 | | |
| |||
460 | 461 | | |
461 | 462 | | |
462 | 463 | | |
463 | | - | |
| 464 | + | |
464 | 465 | | |
465 | 466 | | |
466 | 467 | | |
| |||
Lines changed: 2 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
| |||
302 | 303 | | |
303 | 304 | | |
304 | 305 | | |
305 | | - | |
| 306 | + | |
306 | 307 | | |
307 | 308 | | |
308 | 309 | | |
| |||
Lines changed: 2 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
| |||
240 | 241 | | |
241 | 242 | | |
242 | 243 | | |
243 | | - | |
| 244 | + | |
244 | 245 | | |
245 | 246 | | |
246 | 247 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
| |||
165 | 166 | | |
166 | 167 | | |
167 | 168 | | |
168 | | - | |
| 169 | + | |
169 | 170 | | |
170 | 171 | | |
171 | 172 | | |
| |||
175 | 176 | | |
176 | 177 | | |
177 | 178 | | |
178 | | - | |
| 179 | + | |
179 | 180 | | |
180 | 181 | | |
181 | 182 | | |
182 | 183 | | |
183 | 184 | | |
184 | 185 | | |
185 | | - | |
| 186 | + | |
186 | 187 | | |
187 | 188 | | |
188 | | - | |
| 189 | + | |
189 | 190 | | |
190 | 191 | | |
191 | 192 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | |
| |||
64 | 65 | | |
65 | 66 | | |
66 | 67 | | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
| 68 | + | |
71 | 69 | | |
72 | 70 | | |
73 | 71 | | |
| |||
162 | 160 | | |
163 | 161 | | |
164 | 162 | | |
165 | | - | |
| 163 | + | |
166 | 164 | | |
167 | 165 | | |
168 | 166 | | |
| |||
0 commit comments