feat: ENABLE_MINI feature flag + conditional build (#409)#420
feat: ENABLE_MINI feature flag + conditional build (#409)#420
Conversation
Wire up ENABLE_MINI env var for the Sleepypod Mini module. When unset (default), zero Mini code is bundled: webpack resolve alias nulls out pubnub, and the tRPC Mini router is not imported. When ENABLE_MINI=true, the Mini router is dynamically imported and merged into the app router. Adds PubNub SDK dependency and stub Mini service/router files that will be implemented in the TS Snoo client step. Closes #409 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move pubnub to optionalDependencies and use MiniLevel[] for type safety
📝 WalkthroughWalkthroughImplements a build-time feature flag system for Mini functionality using Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@next.config.mjs`:
- Around line 33-40: When enableMini is false, you currently set
config.resolve.alias.pubnub = false for webpack but forgot to mirror this for
Turbopack; add the same alias to config.experimental?.turbopack?.resolveAlias
(or config.turbopack.resolveAlias if that structure is used) so
turbopack.resolveAlias includes pubnub: false alongside config.resolve.alias;
update the conditional that checks enableMini (the block around
config.resolve.alias) to also set turbopack.resolveAlias to ensure Mini-off
behavior is consistent across both bundlers.
In `@package.json`:
- Around line 72-74: package.json now adds an optional dependency "pubnub" but
the pnpm lockfile wasn't updated; run pnpm install (or pnpm install
--lockfile-only) to regenerate pnpm-lock.yaml so it includes the new
optionalDependencies entry, verify the lockfile reflects "pubnub" under
optionalDependencies, and commit the updated pnpm-lock.yaml alongside the
package.json change before merging.
In `@src/server/routers/app.ts`:
- Around line 16-21: The current conditional top-level import of './mini'
(miniRouter) still creates a static dependency edge and the inline comment
incorrectly implies webpack aliasing removes the module; either add a build-time
alias for './mini' → false in the webpack/next config (matching how pubnub is
aliased) so the module is guaranteed excluded when ENABLE_MINI='false', or move
the import into the runtime branch so you only call await import('./mini') when
process.env.ENABLE_MINI==='true' (ensuring no static edge), and update the
comment to accurately reflect which modules are aliased/excluded; refer to
miniRouter, './mini', ENABLE_MINI and the existing pubnub alias when making the
change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e79e4e57-ef3b-46f2-a4a8-c603999f9f2c
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (8)
next.config.mjspackage.jsonsrc/server/routers/app.tssrc/server/routers/mini.tssrc/services/mini/client.tssrc/services/mini/index.tssrc/services/mini/pubnub.tssrc/services/mini/types.ts
| // When ENABLE_MINI is not set, replace Mini modules with empty stubs | ||
| // so zero Mini code (including PubNub SDK) is bundled. | ||
| if (!enableMini) { | ||
| config.resolve.alias = { | ||
| ...config.resolve.alias, | ||
| pubnub: false, | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
In Next.js 16.1.6, does next devuse Turbopack by default, and should a package alias configured inwebpack.resolve.aliasalso be duplicated inturbopack.resolveAlias to keep module resolution behavior consistent?
💡 Result:
In Next.js 16.1.6, next dev uses Turbopack by default. Yes, a package alias configured in webpack.resolve.alias should be duplicated in turbopack.resolveAlias to keep module resolution behavior consistent, as Turbopack does not automatically use webpack aliases and has its own resolveAlias configuration in next.config.js under the top-level turbopack key (moved from experimental in Next.js 16). Multiple GitHub discussions and issues confirm users need to explicitly configure resolveAlias for Turbopack to match webpack behavior, especially for custom aliases, symlinks, or fallbacks.
Citations:
- 1: https://nextjs.org/blog/next-16
- 2: Add a --webpack flag and default --turbopack to true vercel/next.js#84216
- 3: Can't resolve 'xyz' with turbopack vercel/next.js#84809
- 4: Next.js 15 import alias not working with turbopack vercel/next.js#71886
- 5: https://nextjs.org/blog/next-16-1
Add the pubnub: false alias to turbopack.resolveAlias as well.
The pubnub: false alias is set in the webpack config but missing from turbopack.resolveAlias. Since Next.js 16.1.6 uses Turbopack by default, the Mini-off behavior won't work consistently—Turbopack doesn't inherit webpack aliases and requires the alias to be explicitly configured in its own resolveAlias block to match webpack behavior.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@next.config.mjs` around lines 33 - 40, When enableMini is false, you
currently set config.resolve.alias.pubnub = false for webpack but forgot to
mirror this for Turbopack; add the same alias to
config.experimental?.turbopack?.resolveAlias (or config.turbopack.resolveAlias
if that structure is used) so turbopack.resolveAlias includes pubnub: false
alongside config.resolve.alias; update the conditional that checks enableMini
(the block around config.resolve.alias) to also set turbopack.resolveAlias to
ensure Mini-off behavior is consistent across both bundlers.
| "optionalDependencies": { | ||
| "pubnub": "^10.2.9" | ||
| }, |
There was a problem hiding this comment.
Update pnpm-lock.yaml with the new optional dependency.
CI is already red on pnpm install --frozen-lockfile because the lockfile still has optionalDependencies: {}. Regenerate and commit the lockfile before merging.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@package.json` around lines 72 - 74, package.json now adds an optional
dependency "pubnub" but the pnpm lockfile wasn't updated; run pnpm install (or
pnpm install --lockfile-only) to regenerate pnpm-lock.yaml so it includes the
new optionalDependencies entry, verify the lockfile reflects "pubnub" under
optionalDependencies, and commit the updated pnpm-lock.yaml alongside the
package.json change before merging.
| // Mini router — conditional dynamic import, only loaded when ENABLE_MINI=true. | ||
| // When disabled: no Mini code is bundled (webpack resolve alias → false), | ||
| // no PubNub SDK loaded, no Mini routes registered. | ||
| const miniRouter = process.env.ENABLE_MINI === 'true' | ||
| ? (await import('./mini')).miniRouter | ||
| : null |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find build config files
git ls-files | grep -E '(next\.config|webpack|tsconfig|\.env)' | head -20Repository: sleepypod/core
Length of output: 106
🏁 Script executed:
# Search for ENABLE_MINI references in the codebase
rg 'ENABLE_MINI' --type ts --type js --type json -nRepository: sleepypod/core
Length of output: 249
🏁 Script executed:
# Check the structure of src/server/routers/
ls -la src/server/routers/ 2>/dev/null || echo "Directory not found"Repository: sleepypod/core
Length of output: 1152
🏁 Script executed:
# Look for the mini module
fd -type f -path '*mini*' | grep -E '\.(ts|js|tsx|jsx)$' | head -20Repository: sleepypod/core
Length of output: 228
🏁 Script executed:
# Check next.config.mjs for any aliases or configuration
cat next.config.mjs 2>/dev/null | head -100Repository: sleepypod/core
Length of output: 1454
🏁 Script executed:
# Read the mini.ts file to see what it contains
cat -n src/server/routers/mini.tsRepository: sleepypod/core
Length of output: 509
🏁 Script executed:
# Check if there are any other references to the mini router or ENABLE_MINI in app.ts
cat -n src/server/routers/app.tsRepository: sleepypod/core
Length of output: 2248
🏁 Script executed:
# Search for any build-time webpack plugin or setup for env variable handling
rg 'DefinePlugin|process.env' next.config.mjs webpack.configRepository: sleepypod/core
Length of output: 199
🏁 Script executed:
# Check if mini.ts has any dependencies on pubnub
rg -A 5 -B 5 'pubnub|pubsub' src/server/routers/mini.ts src/server/trpc.ts 2>/dev/null || echo "No pubnub refs found in mini or trpc"Repository: sleepypod/core
Length of output: 94
🏁 Script executed:
# Search for any build-time env defines or extra webpack config
rg 'DefinePlugin|ENABLE_MINI' . --type js --type mjs -A 3 -B 3 2>/dev/null | head -50Repository: sleepypod/core
Length of output: 40
🏁 Script executed:
# Check if there's any documentation about the build exclusion objective
cat README.md 2>/dev/null | grep -i -A 5 -B 5 'mini\|enable_mini\|bundle' | head -40Repository: sleepypod/core
Length of output: 827
The static import statement creates a dependency edge without explicit build-time exclusion.
The code conditionally imports ./mini at runtime, but relies on Next.js dead-code elimination to remove it from the bundle when ENABLE_MINI=false. However, only pubnub is explicitly aliased to false in webpack config—there is no matching alias for ./mini itself. If build-time exclusion is a release requirement, either:
- Add a build-time alias for
./mini(like pubnub) to guarantee it's excluded, or - Verify that the standalone output with
ENABLE_MINI=falseactually contains no mini code
The inline comment claiming "webpack resolve alias → false" is misleading since the alias only applies to pubnub, not to the mini module itself.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/server/routers/app.ts` around lines 16 - 21, The current conditional
top-level import of './mini' (miniRouter) still creates a static dependency edge
and the inline comment incorrectly implies webpack aliasing removes the module;
either add a build-time alias for './mini' → false in the webpack/next config
(matching how pubnub is aliased) so the module is guaranteed excluded when
ENABLE_MINI='false', or move the import into the runtime branch so you only call
await import('./mini') when process.env.ENABLE_MINI==='true' (ensuring no static
edge), and update the comment to accurately reflect which modules are
aliased/excluded; refer to miniRouter, './mini', ENABLE_MINI and the existing
pubnub alias when making the change.
## Summary Promotes everything on \`dev\` since the last main release (82 commits, 143 files, +9239/-2699). ### Headlining features - **Schedule redesign (#303)** — read-only schedule view with explicit curve management, full-screen \`CurveEditor\` (day picker + bedtime/wake + temp range + presets), \`Left | Right | Both\` side selector, active-curve highlight, atomic \`batchUpdate\` writes, day-conflict resolution, sparkline cards. - **Mini feature flag (#420)** — \`ENABLE_MINI\` env var; PubNub moved to \`optionalDependencies\`; conditional Mini router import. - **Auto-off on no presence (#301)** — schedule respects bed presence. - **Auto-unblock internet during update check (#308)**. - **Schedule batchUpdate cap raised to 1000 (#424)** — fixes AI-curve apply-to-all-days rejection. ### Operational fixes - Pod 3 install path (#383, #384, #386, #392) - Yocto image Python venv (#336) - DAC socket / Avahi on device startup (#331) - Free-sleep/sleepypod switch persistence (#337) - Cross-machine standalone deploys (#308) - Temperature unit conversion (#333) ### Dependency updates ~20 renovate PRs across React 19.2.5, Next 16.2.3, vitest 4.1.4, tanstack/react-query 5.97.0, tRPC 11.16, lucide-react 1.x, etc. ### Misc - ADR 0017 (uv) compiled into deployment wiki - Snoo pentest methodology + recon plan - Git hooks + ESLint cleanup (#313) - CI hardening (#388) ## Test plan - [x] All unit tests pass on dev (606+ tests) - [x] Typecheck clean - [x] Build succeeds (standalone output) - [x] Deployed to Pod 4 at \`192.168.1.88\` and smoke-tested: - schedule on/off - create curve from preset - edit curve, change days, save - day-conflict reassign dialog - delete curve - side selector left/right/both - active-curve highlighting + next set point
Summary
ENABLE_MINIenv var for the Sleepypod Mini modulepubnub, tRPC Mini router not importedENABLE_MINI=true: Mini router dynamically imported and merged into app routerpubnub@10.x)src/services/mini/) and router (src/server/routers/mini.ts)Closes #409
Changes since #410
pubnubtooptionalDependenciesper review feedbackMiniLevel[]instead ofstring[]for type safetyTest plan
pnpm tscpassespnpm buildwithENABLE_MINIunset succeedsENABLE_MINI=true pnpm buildsucceeds — Mini routes availableSummary by CodeRabbit
New Features
/mini/statusAPI endpoint to check feature availability.Chores