Skip to content

Commit

Permalink
Allow unserialised data to be written to store
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Patrick Corbett committed Mar 26, 2021
1 parent 06b4d7c commit a4d8949
Show file tree
Hide file tree
Showing 9 changed files with 31 additions and 13 deletions.
4 changes: 2 additions & 2 deletions src/Storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
} from './types';

export default class Storage<T> {
storage: PersistentStorage;
storage: PersistentStorage<PersistedData<T>>;
key: string;

constructor(options: ApolloPersistOptions<T>) {
Expand All @@ -20,7 +20,7 @@ export default class Storage<T> {
}

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

async purge(): Promise<void> {
Expand Down
18 changes: 18 additions & 0 deletions src/__tests__/Storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,22 @@ describe('Storage', () => {
await storage.purge();
await expect(storage.read()).resolves.toBe(undefined);
});

describe('when data is an object', () => {
it ('writes an object to persistent storage', async () => {
const obj = {
yo: 'yo yo'
}

await expect(storage.write(obj)).resolves.toBe(undefined);
await expect(storage.read()).resolves.toBe(obj);
})
})

describe('when data is a string', () => {
it ('writes a string to persistent storage', async () => {
await expect(storage.write('yo yo yo')).resolves.toBe(undefined);
await expect(storage.read()).resolves.toBe('yo yo yo');
})
})
});
2 changes: 1 addition & 1 deletion src/storageWrappers/AsyncStorageWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { PersistentStorage } from '../types';
* });
*
*/
export class AsyncStorageWrapper implements PersistentStorage {
export class AsyncStorageWrapper implements PersistentStorage<string> {
// Actual type definition: https://github.com/react-native-async-storage/async-storage/blob/master/types/index.d.ts
private storage;

Expand Down
2 changes: 1 addition & 1 deletion src/storageWrappers/IonicStorageWrapper.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PersistentStorage } from '../types';

export class IonicStorageWrapper implements PersistentStorage {
export class IonicStorageWrapper implements PersistentStorage<string> {
// Actual type definition: https://github.com/ionic-team/ionic-storage/blob/main/src/storage.ts#L102
private storage;

Expand Down
2 changes: 1 addition & 1 deletion src/storageWrappers/LocalForageWrapper.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PersistentStorage } from '../types';

export class LocalForageWrapper implements PersistentStorage {
export class LocalForageWrapper implements PersistentStorage<string | object> {
// Actual type definition: https://github.com/localForage/localForage/blob/master/typings/localforage.d.ts#L17
private storage;

Expand Down
2 changes: 1 addition & 1 deletion src/storageWrappers/LocalStorageWrapper.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PersistentStorage } from '../types';

export class LocalStorageWrapper implements PersistentStorage {
export class LocalStorageWrapper implements PersistentStorage<string> {
// Actual type definition: https://github.com/microsoft/TypeScript/blob/master/lib/lib.dom.d.ts#L15286
private storage;

Expand Down
2 changes: 1 addition & 1 deletion src/storageWrappers/MMKVStorageWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { PersistentStorage } from '../types';
* });
*
*/
export class MMKVStorageWrapper implements PersistentStorage {
export class MMKVStorageWrapper implements PersistentStorage<string> {
// Actual type definition: https://github.com/ammarahm-ed/react-native-mmkv-storage/blob/master/index.d.ts#L27
private storage;

Expand Down
2 changes: 1 addition & 1 deletion src/storageWrappers/SessionStorageWrapper.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PersistentStorage } from '../types';

export class SessionStorageWrapper implements PersistentStorage {
export class SessionStorageWrapper implements PersistentStorage<string> {
// Actual type definition: https://github.com/microsoft/TypeScript/blob/master/lib/lib.dom.d.ts#L15286
private storage;

Expand Down
10 changes: 5 additions & 5 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ export type TriggerFunction = (persist: () => void) => TriggerUninstallFunction;

export type PersistedData<T> = T | string | null;

export interface PersistentStorage {
getItem: (key: string) => string | null | Promise<string | null>;
setItem: (key: string, value: string) => void | Promise<void>;
removeItem: (key: string) => void | Promise<void>;
export interface PersistentStorage<T> {
getItem: (key: string) => Promise<T | null> | T | null;
setItem: (key: string, value: T) => Promise<T> | Promise<void> | void | T;
removeItem: (key: string) => Promise<T> | Promise<void> | void;
}

export interface ApolloPersistOptions<TSerialized> {
cache: ApolloCache<TSerialized>;
storage: PersistentStorage;
storage: PersistentStorage<PersistedData<TSerialized>>;
trigger?: 'write' | 'background' | TriggerFunction | false;
debounce?: number;
key?: string;
Expand Down

0 comments on commit a4d8949

Please sign in to comment.