Skip to content

fix(core): implement Session save/restore with JSON file persistence#1713

Open
ionfwsrijan wants to merge 2 commits into
Karanjot786:mainfrom
ionfwsrijan:fix/issue-1710-session-persist
Open

fix(core): implement Session save/restore with JSON file persistence#1713
ionfwsrijan wants to merge 2 commits into
Karanjot786:mainfrom
ionfwsrijan:fix/issue-1710-session-persist

Conversation

@ionfwsrijan

@ionfwsrijan ionfwsrijan commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Description

Session is an in-memory-only store with no persistence. When the terminal app restarts, all session state is lost. Widgets like form inputs, wizard steps, and multi-page flows cannot survive a restart.

Changes

  • Session.save(): Serializes this._data to JSON and writes it to ~/.termui/session.json (configurable via storagePath option)
  • Session.restore(): Reads the file from disk and merges data into _data
  • Constructor auto-calls restore() on creation
  • Uses node:fs, node:path, node:os imports as required by project conventions

Testing

  • Created and destroyed a Session, verified data persists across instances
  • Existing Session tests continue to pass

Closes #1710

Summary by CodeRabbit

Release Notes

  • New Features

    • Sessions now persist to disk, keeping your session data across restarts.
    • Session data is automatically restored on startup.
    • Added storagePath option to customize where session data is stored.
  • Bug Fixes

    • Improved resilience when the storage file is missing or contains invalid JSON (no longer throws).
  • Tests

    • Expanded test coverage for save/restore and persistence behavior.

save() and restore() were empty stubs — auto-save loop ran but
persisted nothing. Now writes _data as JSON to ~/.termui/session.json
(default) or a custom storagePath. restore() is called in the
constructor to reload on startup. Errors are silently handled to
avoid crashes on read-only filesystems or corrupt files.
@ionfwsrijan ionfwsrijan requested a review from Karanjot786 as a code owner June 21, 2026 07:40
@github-actions github-actions Bot added the area:core @termuijs/core label Jun 21, 2026
@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Session persistence is implemented by adding an optional storagePath to SessionOptions, deriving _storagePath in the constructor (defaulting to ~/.termui/session.json), calling restore() at construction time, and replacing the empty save()/restore() stubs with JSON file read/write operations that silently suppress errors. Tests verify persistence across instance restarts, corruption resilience, and missing-file handling.

Changes

Session filesystem persistence

Layer / File(s) Summary
SessionOptions storagePath and constructor wiring
packages/core/src/session/Session.ts
Adds fs, path, and os imports; adds storagePath?: string to SessionOptions; introduces _storagePath field; constructor resolves the path from options or defaults to ~/.termui/session.json and calls restore().
save() and restore() JSON file persistence
packages/core/src/session/Session.ts
Replaces console-log placeholder save()/restore() with real implementations: save() creates the parent directory and writes _data as JSON; restore() reads and parses the file, updating _data only when the result is a non-null object; both suppress errors via try/catch.
Session persistence test suite
packages/core/src/session/Session.test.ts
Adds filesystem and lifecycle test imports; creates persistence test block verifying save/restore across instances, restart cycles, corruption handling, and missing file behavior.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • Karanjot786/TermUI#1570: Introduced the Session/createSession API with the placeholder save()/restore() stubs and auto-save scaffolding that this PR replaces with real filesystem persistence.

Suggested labels

type:feature, type:testing, quality:clean, level:intermediate

🐇 A bunny dug a burrow deep and wide,
so session state has somewhere safe to hide.
JSON whispers to disk each night,
restore() brings it back to light.
No more stubs — the carrots are saved right! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: implementing Session persistence with JSON file-based save/restore functionality.
Description check ✅ Passed The description covers the key changes (save/restore with JSON file persistence, configurable storagePath, constructor auto-restore) and includes issue reference, but lacks explicit sections for package name, type of change checkbox, and detailed checklist completion.
Linked Issues check ✅ Passed The PR addresses the core requirement from #1710: implementing file-based JSON persistence for save()/restore() with error suppression. Constructor auto-restore and proper file handling are implemented.
Out of Scope Changes check ✅ Passed All changes directly support the Session persistence objective. Session.ts implements the persistence layer, Session.test.ts adds required test coverage. No unrelated refactors or scope creep detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

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

@github-actions github-actions Bot added the type:bug +10 pts. Bug fix. label Jun 21, 2026

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/core/src/session/Session.ts (1)

42-68: Enhance persistence tests with behavioral coverage.

The current test only verifies save() and restore() do not throw, which would pass even if these methods were still no-ops. Add tests that:

  • Use a temp storagePath and verify data persists across Session instances
  • Confirm corrupt JSON and non-object JSON gracefully fall back without restoring stale data
  • Validate that _storagePath is actually being used
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/session/Session.ts` around lines 42 - 68, The tests for the
save() and restore() methods in the Session class only verify that these methods
do not throw errors, which means they would pass even if the methods were
non-functional. Enhance the test suite by adding tests that use a temporary
storagePath to verify session data actually persists to disk and can be
successfully restored across different Session instances, add tests that confirm
corrupt JSON and non-object JSON are gracefully handled without restoring
corrupted data, and validate that the _storagePath property is actually being
used in the file operations. These behavioral tests will ensure the persistence
logic is working correctly rather than just verifying it doesn't throw.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/session/Session.ts`:
- Around line 43-49: Implement atomic file writing to prevent session data
corruption on failed saves. In the try block where writeFileSync writes directly
to this._storagePath, modify the logic to first write to a temporary file (you
can use a temp filename like this._storagePath with a .tmp extension), and only
after the temporary file write succeeds, replace the original file at
this._storagePath with the temporary file. This ensures that if a write
operation fails due to a kill signal, disk-full error, or partial write, the
existing valid session.json remains untouched instead of being left truncated or
corrupted.
- Around line 61-63: The restore() method has two issues: the JSON.parse() call
lacks an explicit type annotation which violates TypeScript coding guidelines,
and the runtime guard that checks typeof parsed === 'object' && parsed !== null
accepts arrays which can corrupt _data since SessionData expects a record type.
Add an explicit type annotation to the JSON.parse call and update the guard
condition to also reject arrays by adding a check like !Array.isArray(parsed) to
the existing condition, ensuring only plain objects pass through.

---

Nitpick comments:
In `@packages/core/src/session/Session.ts`:
- Around line 42-68: The tests for the save() and restore() methods in the
Session class only verify that these methods do not throw errors, which means
they would pass even if the methods were non-functional. Enhance the test suite
by adding tests that use a temporary storagePath to verify session data actually
persists to disk and can be successfully restored across different Session
instances, add tests that confirm corrupt JSON and non-object JSON are
gracefully handled without restoring corrupted data, and validate that the
_storagePath property is actually being used in the file operations. These
behavioral tests will ensure the persistence logic is working correctly rather
than just verifying it doesn't throw.
🪄 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 Plus

Run ID: 1d9a2395-acf0-4554-808f-e1c49cd3e9b8

📥 Commits

Reviewing files that changed from the base of the PR and between 35c2213 and 6096747.

📒 Files selected for processing (1)
  • packages/core/src/session/Session.ts

Comment thread packages/core/src/session/Session.ts
Comment thread packages/core/src/session/Session.ts
@github-actions github-actions Bot added the type:testing +10 pts. Tests. label Jun 21, 2026

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/session/Session.test.ts`:
- Around line 35-45: The testPath variable on line 35 uses a hardcoded path
string '/tmp/termui-test-session.json' which can cause test collisions in
parallel test runs and platform compatibility issues. Move the testPath
initialization inside the beforeEach block and generate a unique temporary
directory for each test using mkdtempSync(tmpdir()) from the os module, then
construct the session file path within that unique directory. This ensures each
test gets its own isolated temp file and cleanup happens correctly with
removeSync or similar for the entire directory.
- Line 70: The code on line 70 uses an inline require('node:fs').writeFileSync()
call instead of importing writeFileSync at the top of the file with other
node:fs imports. Add writeFileSync to the existing node:fs import statement at
line 3 (alongside any other fs imports already present), then replace the inline
require('node:fs').writeFileSync() call on line 70 with just writeFileSync() to
maintain consistency with the file's ESM import pattern.
🪄 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 Plus

Run ID: 73ecbdb3-f392-4833-a218-36a90421ae97

📥 Commits

Reviewing files that changed from the base of the PR and between 6096747 and 2fed2f6.

📒 Files selected for processing (1)
  • packages/core/src/session/Session.test.ts

Comment thread packages/core/src/session/Session.test.ts
Comment thread packages/core/src/session/Session.test.ts
@ionfwsrijan

Copy link
Copy Markdown
Contributor Author

@Karanjot786 Please review this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core @termuijs/core type:bug +10 pts. Bug fix. type:testing +10 pts. Tests.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] Session save()/restore() Are Empty Stubs — Auto-Save Runs Every 30 Seconds But Persists Nothing

1 participant