Skip to content

Comments

Extract domain modules from monolithic state.svelte.ts#12

Merged
tyom merged 2 commits intomainfrom
state
Feb 21, 2026
Merged

Extract domain modules from monolithic state.svelte.ts#12
tyom merged 2 commits intomainfrom
state

Conversation

@tyom
Copy link
Owner

@tyom tyom commented Feb 21, 2026

  • Split 582-line state.svelte.ts into three domain modules under lib/state/: messages.svelte.ts, channels.svelte.ts, bots.svelte.ts
  • Barrel file keeps shared simulatorState and re-exports everything — zero consumer changes
  • No functional changes

Summary by CodeRabbit

  • Refactor
    • Split the monolithic state into domain-specific modules for messages, channels and bots while keeping all functionality available via updated exports.
  • New Features / UI Behaviour
    • Improved channel navigation and hash-driven switching, enhanced message/thread handling (drafts, reactions, restore/undo) and richer bot features (command filtering, shortcuts, modals, connected-bot status).

- Split 582-line monolith into messages, channels, and bots modules
- Barrel file retains simulatorState definition and re-exports all operations
- Zero consumer import changes required
@coderabbitai
Copy link

coderabbitai bot commented Feb 21, 2026

No actionable comments were generated in the recent review. 🎉

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2bdfcf3 and 35a63e4.

📒 Files selected for processing (1)
  • apps/ui/src/lib/state/channels.svelte.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/ui/src/lib/state/channels.svelte.ts

📝 Walkthrough

Walkthrough

Refactors the monolithic UI state file into three domain modules — messages, channels, and bots — converting the original implementation file into a re-export barrel and moving ~518 lines of state logic into the new modules.

Changes

Cohort / File(s) Summary
Barrel Re-export Module
apps/ui/src/lib/state.svelte.ts
Converted from implementation to a re-export barrel; removed direct implementations and now re-exports APIs from the three new domain modules.
Message State Management
apps/ui/src/lib/state/messages.svelte.ts
New module with message CRUD, reaction handling, thread/draft management, timestamp generation, restoration, and immutable updates to trigger Svelte reactivity.
Channel State Management
apps/ui/src/lib/state/channels.svelte.ts
New module for channel list and navigation state: display name logic, set/add/remove channels, hash parsing/syncing, switchChannel/openThread/closeThread, and SSR-safe init from URL hash.
Bot & Command State Management
apps/ui/src/lib/state/bots.svelte.ts
New module managing slash commands, app config & shortcuts, modal lifecycle, connected bots tracking, and bot identity helpers (legacy and U_... user ID handling).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: extracting a monolithic state file into three domain-specific modules (messages, channels, bots) while maintaining backward compatibility through re-exports.
Docstring Coverage ✅ Passed Docstring coverage is 97.67% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch state

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
apps/ui/src/lib/state/bots.svelte.ts (1)

6-13: Consider using $lib path alias for imports.

Same as in channels.svelte.ts, these imports should use the $lib alias per coding guidelines.

Suggested change
-import type {
-  SlashCommand,
-  SlackView,
-  SlackAppConfig,
-  ConnectedBotInfo,
-} from '../types'
-import { BOT_USER_ID } from '../types'
-import { simulatorState } from '../state.svelte'
+import type {
+  SlashCommand,
+  SlackView,
+  SlackAppConfig,
+  ConnectedBotInfo,
+} from '$lib/types'
+import { BOT_USER_ID } from '$lib/types'
+import { simulatorState } from '$lib/state.svelte'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ui/src/lib/state/bots.svelte.ts` around lines 6 - 13, Replace the
relative imports in this module with the $lib path alias: change imports that
currently reference '../types' (used for SlashCommand, SlackView,
SlackAppConfig, ConnectedBotInfo and BOT_USER_ID) and '../state.svelte'
(simulatorState) to use the $lib alias (e.g., $lib/types and $lib/state.svelte)
so they match the coding guidelines and the pattern used in channels.svelte.ts.
apps/ui/src/lib/state/messages.svelte.ts (1)

6-8: Consider using $lib path alias for imports.

Consistent with the other new modules, these imports should use the $lib alias.

Suggested change
-import { SvelteMap } from 'svelte/reactivity'
-import type { SimulatorMessage } from '../types'
-import { simulatorState } from '../state.svelte'
+import { SvelteMap } from 'svelte/reactivity'
+import type { SimulatorMessage } from '$lib/types'
+import { simulatorState } from '$lib/state.svelte'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ui/src/lib/state/messages.svelte.ts` around lines 6 - 8, Update the
imports in this module to use the $lib path alias instead of relative paths:
replace the '../types' import that references SimulatorMessage with '$lib/types'
and replace the '../state.svelte' import that references simulatorState with the
corresponding '$lib/...' alias (e.g., '$lib/state' or '$lib/state.svelte'
depending on how other modules reference it) while leaving framework imports
like 'svelte/reactivity' unchanged.
apps/ui/src/lib/state/channels.svelte.ts (1)

6-7: Consider using $lib path alias for imports.

The coding guidelines specify using $lib path alias when importing from src/lib/ in Svelte applications. This applies to these relative imports.

Suggested change
-import type { Channel } from '../types'
-import { simulatorState } from '../state.svelte'
+import type { Channel } from '$lib/types'
+import { simulatorState } from '$lib/state.svelte'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ui/src/lib/state/channels.svelte.ts` around lines 6 - 7, The imports use
relative paths; replace them with the $lib path alias so Svelte's coding
guidelines are followed—change the import of the Channel type (symbol: Channel)
and the simulatorState export (symbol: simulatorState) to use '$lib' imports
(e.g., '$lib/types' and '$lib/state.svelte') and update any related import
statements in channels.svelte.ts accordingly.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6ac4f7c and 2bdfcf3.

📒 Files selected for processing (4)
  • apps/ui/src/lib/state.svelte.ts
  • apps/ui/src/lib/state/bots.svelte.ts
  • apps/ui/src/lib/state/channels.svelte.ts
  • apps/ui/src/lib/state/messages.svelte.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Use camelCase for variable names in TypeScript/JavaScript code
No semicolons in code, enforced by Prettier
Use single quotes instead of double quotes
Use trailing commas in es5 format
Prefix unused variables with underscore (_)

Files:

  • apps/ui/src/lib/state/channels.svelte.ts
  • apps/ui/src/lib/state/messages.svelte.ts
  • apps/ui/src/lib/state/bots.svelte.ts
  • apps/ui/src/lib/state.svelte.ts
apps/ui/src/**/*.{ts,tsx,svelte}

📄 CodeRabbit inference engine (CLAUDE.md)

Use $lib path alias when importing from src/lib/ in Svelte applications

Files:

  • apps/ui/src/lib/state/channels.svelte.ts
  • apps/ui/src/lib/state/messages.svelte.ts
  • apps/ui/src/lib/state/bots.svelte.ts
  • apps/ui/src/lib/state.svelte.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
Repo: tyom/botarium PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-02-20T00:31:35.696Z
Learning: Applies to packages/*/src/server/*.ts : Organize platform plugin packages with `server/state.ts` for in-memory state, `server/web-api.ts` for API handlers, and `server/persistence.ts` for storage
📚 Learning: 2026-02-20T00:31:35.696Z
Learnt from: CR
Repo: tyom/botarium PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-02-20T00:31:35.696Z
Learning: Applies to apps/electron/**/*.ts : Slack emulator bot child processes should be managed by the Electron app

Applied to files:

  • apps/ui/src/lib/state/bots.svelte.ts
📚 Learning: 2026-02-20T00:31:35.696Z
Learnt from: CR
Repo: tyom/botarium PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-02-20T00:31:35.696Z
Learning: Applies to packages/*/src/server/*.ts : Organize platform plugin packages with `server/state.ts` for in-memory state, `server/web-api.ts` for API handlers, and `server/persistence.ts` for storage

Applied to files:

  • apps/ui/src/lib/state.svelte.ts
📚 Learning: 2026-02-20T00:31:35.696Z
Learnt from: CR
Repo: tyom/botarium PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-02-20T00:31:35.696Z
Learning: Applies to **/*.svelte : Use Svelte 5 runes (`$state`, `$derived`, `$effect`) for reactivity instead of legacy stores

Applied to files:

  • apps/ui/src/lib/state.svelte.ts
🧬 Code graph analysis (2)
apps/ui/src/lib/state/channels.svelte.ts (2)
apps/ui/src/lib/state.svelte.ts (1)
  • simulatorState (30-65)
apps/ui/src/lib/types.ts (1)
  • Channel (28-33)
apps/ui/src/lib/state/bots.svelte.ts (2)
apps/ui/src/lib/state.svelte.ts (1)
  • simulatorState (30-65)
apps/ui/src/lib/types.ts (2)
  • ConnectedBotInfo (576-584)
  • BOT_USER_ID (43-43)
🔇 Additional comments (4)
apps/ui/src/lib/state/bots.svelte.ts (1)

126-141: LGTM!

The isBotUserId function appropriately handles both legacy and multi-bot formats. The decision to treat any U_ prefix as a bot for display purposes is well-documented in the comments.

apps/ui/src/lib/state/messages.svelte.ts (2)

10-16: LGTM!

The timestamp generation with monotonically increasing counter ensures uniqueness. The restoreMessages function properly synchronises the counter to prevent collisions after restoration.


130-200: LGTM!

The restoreMessages function properly handles rehydration from persisted records, including counter synchronisation to prevent timestamp collisions and correct mapping of file attachments.

apps/ui/src/lib/state.svelte.ts (1)

67-116: Well-structured barrel file maintaining backwards compatibility.

The re-export pattern ensures existing consumer imports remain unchanged while enabling the modular organisation. The shared simulatorState definition appropriately stays in this central file and is defined before the re-exports, ensuring the circular import with domain modules (which import simulatorState from this file) works correctly in ES modules.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/ui/src/lib/state/channels.svelte.ts`:
- Around line 96-101: The DM detection in switchChannel incorrectly uses
startsWith('D') which can misclassify channels; update switchChannel to use the
same DM prefix logic as parseHash (use startsWith('D_') on the channelId) so
simulatorState.isDM is only true for IDs in the documented 'D_{botId}' form, and
ensure switchChannel handles null/undefined channelId consistently with
parseHash.
- Around line 121-124: The DM detection is inconsistent: in the block that sets
simulatorState.currentChannel and simulatorState.isDM (the assignment to
simulatorState.isDM uses channelId.startsWith('D')), update it to match the DM
prefix used elsewhere (use channelId.startsWith('D_')) so DM detection is
consistent with the logic in switchChannel; locate the assignment to
simulatorState.isDM and change the startsWith argument to 'D_'.

---

Nitpick comments:
In `@apps/ui/src/lib/state/bots.svelte.ts`:
- Around line 6-13: Replace the relative imports in this module with the $lib
path alias: change imports that currently reference '../types' (used for
SlashCommand, SlackView, SlackAppConfig, ConnectedBotInfo and BOT_USER_ID) and
'../state.svelte' (simulatorState) to use the $lib alias (e.g., $lib/types and
$lib/state.svelte) so they match the coding guidelines and the pattern used in
channels.svelte.ts.

In `@apps/ui/src/lib/state/channels.svelte.ts`:
- Around line 6-7: The imports use relative paths; replace them with the $lib
path alias so Svelte's coding guidelines are followed—change the import of the
Channel type (symbol: Channel) and the simulatorState export (symbol:
simulatorState) to use '$lib' imports (e.g., '$lib/types' and
'$lib/state.svelte') and update any related import statements in
channels.svelte.ts accordingly.

In `@apps/ui/src/lib/state/messages.svelte.ts`:
- Around line 6-8: Update the imports in this module to use the $lib path alias
instead of relative paths: replace the '../types' import that references
SimulatorMessage with '$lib/types' and replace the '../state.svelte' import that
references simulatorState with the corresponding '$lib/...' alias (e.g.,
'$lib/state' or '$lib/state.svelte' depending on how other modules reference it)
while leaving framework imports like 'svelte/reactivity' unchanged.

switchChannel and initFromHash used startsWith('D') which could
misclassify non-DM channels; aligned with parseHash's startsWith('D_').
@tyom tyom merged commit f8639ec into main Feb 21, 2026
2 checks passed
@tyom tyom deleted the state branch February 21, 2026 16:15
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.

1 participant