Skip to content

refactor: withStorageSync #191

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

rainerhahnekamp
Copy link
Collaborator

No description provided.

@rainerhahnekamp rainerhahnekamp requested a review from Copilot July 26, 2025 20:36
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors the withStorageSync function to improve its architecture and API design. The changes introduce new storage strategy patterns, support for both synchronous and asynchronous storage operations, and enhanced type safety.

Key changes include:

  • Replaced class-based storage service factories with functional storage strategies
  • Added support for both sync (localStorage/sessionStorage) and async (IndexedDB) storage patterns
  • Introduced new warning mechanisms for storage sync state conflicts
  • Updated API to use strategy-based configuration instead of service classes

Reviewed Changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
libs/ngrx-toolkit/src/lib/storage-sync/with-storage-sync.ts Complete refactor to use strategy pattern with separate sync/async implementations
libs/ngrx-toolkit/src/lib/storage-sync/internal/models.ts New type definitions for storage strategies and feature results
libs/ngrx-toolkit/src/lib/storage-sync/features/with-local-storage.ts Converted to functional strategy pattern for sync storage
libs/ngrx-toolkit/src/lib/storage-sync/features/with-indexed-db.ts New async storage strategy implementation with sync status tracking
libs/ngrx-toolkit/src/lib/storage-sync/tests/*.spec.ts Updated tests for new API and added async storage test coverage
libs/ngrx-toolkit/src/index.ts Updated exports to reflect API changes

@@ -41,7 +39,7 @@ export type SyncConfig<State> = {
*
* Returns the whole state object by default
*/
select?: (state: State) => Partial<State>;
select?: (state: State) => unknown;
Copy link
Preview

Copilot AI Jul 26, 2025

Choose a reason for hiding this comment

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

The select function return type changed from Partial<State> to unknown, which is too permissive and could lead to runtime errors. Consider using a more specific type like Partial<State> or Record<string, unknown> to maintain type safety.

Suggested change
select?: (state: State) => unknown;
select?: (state: State) => Partial<State>;

Copilot uses AI. Check for mistakes.

Comment on lines 50 to 52
// TODO: select doesn't guarantee that State is returned
const slicedState = select(getState(store)) as State;
storage.setItem(key, stringify(slicedState));
Copy link
Preview

Copilot AI Jul 26, 2025

Choose a reason for hiding this comment

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

The TODO comment indicates a type safety issue where select doesn't guarantee State is returned, but the code performs an unsafe cast on line 51. This should be addressed to prevent potential runtime errors.

Suggested change
// TODO: select doesn't guarantee that State is returned
const slicedState = select(getState(store)) as State;
storage.setItem(key, stringify(slicedState));
// Validate that the result of select conforms to the State type
const selectedState = select(getState(store));
if (isState(selectedState)) {
storage.setItem(key, stringify(selectedState));
} else {
throw new Error('Selected state does not match the expected State type.');
}

Copilot uses AI. Check for mistakes.

warnOnSyncing('write');
store[SYNC_STATUS].set('syncing');
// TODO: select doesn't guarantee that State is returned
const slicedState = select(getState(store)) as State;
Copy link
Preview

Copilot AI Jul 26, 2025

Choose a reason for hiding this comment

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

Same type safety issue as in with-local-storage.ts. The TODO comment indicates that select doesn't guarantee State is returned, but an unsafe cast is performed on line 73.

Suggested change
const slicedState = select(getState(store)) as State;
const selectedState = select(getState(store));
if (!isState(selectedState)) {
throw new Error('Selected state does not conform to the expected State type.');
}
const slicedState = selectedState;

Copilot uses AI. Check for mistakes.

return;
}

console.warn(
Copy link
Preview

Copilot AI Jul 26, 2025

Choose a reason for hiding this comment

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

[nitpick] Using console.warn directly in production code can clutter console output and may not be appropriate for all environments. Consider using a configurable logging mechanism or allowing users to disable these warnings.

Suggested change
console.warn(
logWarning(

Copilot uses AI. Check for mistakes.

@rainerhahnekamp rainerhahnekamp merged commit 01172da into angular-architects:main Jul 26, 2025
1 check passed
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