Skip to content
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

Fix Storage API types #388

Merged
merged 1 commit into from
Oct 19, 2020
Merged

Conversation

dchambers
Copy link
Contributor

Alignment of PersistentStorage with Typescript's internal types for the Storage interface of the Web Storage API (potential fix for #55).

This change removes the generic type T from PersistentStorage, which seemed unnecessary and unused. Apart from some type changes there's a single code change within src/Storage.ts which will want some scrutiny from those who understand the code better.

@@ -20,7 +20,7 @@ export default class Storage<T> {
}

async write(data: PersistedData<T>): Promise<void> {
await this.storage.setItem(this.key, data);
await this.storage.setItem(this.key, data.toString());
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sole code change here 👀.

data here is of type PersistedData<T> = string | T, giving us two options:

  1. In the case it's string then it has a toString method, and calling this leaves the string unchanged (no-op).
  2. In the case it's T then this seems to always be inferred as NormalizedCacheObject, which is an object whose toString would yield [object Object], but where relying on implicit type conversion within localStorage would (I believe) give the same result of [object Object] (also no-op?).

@dchambers
Copy link
Contributor Author

dchambers commented Oct 18, 2020

@dchambers - Reopening then - We need to provide wrapper with single interface and then document how to wrap incompatible storages.

@wtrocki, I took a look at this with an eye to use a wrapper as you suggested, but I actually couldn't find any reason (based on the code as-is) why PersistedData was generic in the first place. Therefore the PR is to merely simplify the types. Please let me know if I've misunderstood things here?

@dchambers dchambers force-pushed the fix-storage-api-types branch from 7677fff to 356c653 Compare October 18, 2020 15:15
@dchambers dchambers force-pushed the fix-storage-api-types branch from 356c653 to d5f016c Compare October 18, 2020 15:17
getItem: (key: string) => Promise<T | null> | T | null;
setItem: (key: string, data: T) => Promise<T> | Promise<void> | void | T;
removeItem: (key: string) => Promise<T> | Promise<void> | void;
export interface PersistentStorage {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The definitions within PersistentStorage were updated to match TypeScript's internal types for the Storage interface, but then amended to also support asynchronous storage APIs too, as needed by AsyncStorage, localForage and Ionic Storage.

Copy link
Collaborator

@wtrocki wtrocki left a comment

Choose a reason for hiding this comment

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

Amazing work @dchambers!
This was outstanding for very very long time.

I might need to leave it for a while before releasing for the test purposes, but all sounds good!

@wtrocki wtrocki merged commit d3abad6 into apollographql:master Oct 19, 2020
@wtrocki
Copy link
Collaborator

wtrocki commented Oct 19, 2020

apollo3-cache-persist (0.8.0)

@MatthiasKunnen
Copy link

This PR broke assignment of localForage, see #399.

PMCorbett pushed a commit to PMCorbett/apollo-cache-persist that referenced this pull request Mar 26, 2021
This PR: apollographql#388
stops the cache being written as anything other than a string.

The CachePersistor accepts an option "serialize: boolean" that can allow
for data to be written to the store without being serialised to a string
first. However with the .toString() coercion, when serialize is true,
all that gets written to the store is [object object], rather than the
object.

This change makes sense, to bring the api inline with the web storage
api. However, it means all data must be stored as JSON, which, when
there is a large data set, is very expensive in memory and cpu.
PMCorbett pushed a commit to PMCorbett/apollo-cache-persist that referenced this pull request Mar 26, 2021
This PR: apollographql#388
stops the cache being written as anything other than a string.

The CachePersistor accepts an option "serialize: boolean" that can allow
for data to be written to the store without being serialised to a string
first. However with the .toString() coercion, when serialize is true,
all that gets written to the store is [object object], rather than the
object.

This change makes sense, to bring the api inline with the web storage
api. However, it means all data must be stored as JSON, which, when
there is a large data set, is very expensive in memory and cpu.

So this resolves the issue by putting the generic back in, removing the
coercion, and assigning the appropriate generic to each of the storage
wrappers (I think everything is string apart from localForage, but
perhaps other wrappers can support non-string values)
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.

3 participants