Skip to content

Commit

Permalink
Merge 3494fde into 4caede2
Browse files Browse the repository at this point in the history
  • Loading branch information
dplewis authored Feb 13, 2021
2 parents 4caede2 + 3494fde commit c7f1e82
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 33 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ const Parse = require('parse');
import Parse from 'parse/dist/parse.min.js';
```

For web worker or browser applications, indexedDB storage is available:

```js
Parse.CoreManager.setStorageController(Parse.IndexedDB);
```

For server-side applications or Node.js command line tools, include `'parse/node'`:

```js
Expand Down
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@
"react-native": false
},
"dependencies": {
"@babel/runtime-corejs3": "7.12.5",
"@babel/runtime": "7.12.5",
"@babel/runtime-corejs3": "7.12.5",
"idb-keyval": "5.0.2",
"react-native-crypto-js": "1.0.0",
"uuid": "3.4.0",
"ws": "7.4.2",
Expand Down
32 changes: 32 additions & 0 deletions src/IndexedDBStorageController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* @flow
*/

import { createStore, del, set, get, clear, keys } from 'idb-keyval';

try {
const ParseStore = createStore('parseDB', 'parseStore');

const IndexedDBStorageController = {
async: 1,
getItemAsync(path: string) {
return get(path, ParseStore);
},
setItemAsync(path: string, value: string) {
return set(path, value, ParseStore);
},
removeItemAsync(path: string) {
return del(path, ParseStore);
},
getAllKeysAsync() {
return keys(ParseStore);
},
clear() {
return clear(ParseStore);
},
};

module.exports = IndexedDBStorageController;
} catch (e) {
// IndexedDB not supported
}
1 change: 1 addition & 0 deletions src/Parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ Parse.Storage = require('./Storage');
Parse.User = require('./ParseUser').default;
Parse.LiveQuery = require('./ParseLiveQuery').default;
Parse.LiveQueryClient = require('./LiveQueryClient').default;
Parse.IndexedDB = require('./IndexedDBStorageController');

Parse._request = function (...args) {
return CoreManager.getRESTController().request.apply(null, args);
Expand Down
8 changes: 8 additions & 0 deletions src/__tests__/Parse-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,4 +200,12 @@ describe('Parse module', () => {
it('_encode', () => {
expect(Parse._encode(12)).toBe(12);
});

it('can get IndexedDB storage', () => {
console.log(Parse.IndexedDB);
expect(Parse.IndexedDB).toBeDefined();
CoreManager.setStorageController(Parse.IndexedDB);
const currentStorage = CoreManager.getStorageController();
expect(currentStorage).toEqual(Parse.IndexedDB);
});
});
77 changes: 45 additions & 32 deletions src/__tests__/Storage-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,43 +10,16 @@
jest.autoMockOff();

const mockRNStorageInterface = require('./test_helpers/mockRNStorage');
const mockStorageInterface = require('./test_helpers/mockStorageInteface');
const mockIndexedDB = require('./test_helpers/mockIndexedDB');
const mockWeChat = require('./test_helpers/mockWeChat');
const CoreManager = require('../CoreManager');

global.wx = mockWeChat;

let mockStorage = {};
const mockStorageInterface = {
getItem(path) {
return mockStorage[path] || null;
},

getItemAsync(path) {
return Promise.resolve(mockStorageInterface.getItem(path));
},

setItem(path, value) {
mockStorage[path] = value;
},

setItemAsync(path, value) {
return Promise.resolve(mockStorageInterface.setItem(path, value));
},

removeItem(path) {
delete mockStorage[path];
},

removeItemAsync(path) {
return Promise.resolve(mockStorageInterface.removeItem(path));
},

clear() {
mockStorage = {};
},
};

global.localStorage = mockStorageInterface;
jest.mock('idb-keyval', () => {
return mockIndexedDB;
});

const BrowserStorageController = require('../StorageController.browser');

Expand Down Expand Up @@ -192,6 +165,46 @@ describe('React Native StorageController', () => {
});
});

const IndexedDBStorageController = require('../IndexedDBStorageController');

describe('React Native StorageController', () => {
beforeEach(() => {
IndexedDBStorageController.clear();
});

it('is asynchronous', () => {
expect(IndexedDBStorageController.async).toBe(1);
expect(typeof IndexedDBStorageController.getItemAsync).toBe('function');
expect(typeof IndexedDBStorageController.setItemAsync).toBe('function');
expect(typeof IndexedDBStorageController.removeItemAsync).toBe('function');
});

it('can store and retrieve values', async () => {
let result = await IndexedDBStorageController.getItemAsync('myKey');
expect(result).toBe(null);
await IndexedDBStorageController.setItemAsync('myKey', 'myValue');
result = await IndexedDBStorageController.getItemAsync('myKey');
expect(result).toBe('myValue');
});

it('can remove values', async () => {
await IndexedDBStorageController.setItemAsync('myKey', 'myValue');
let result = await IndexedDBStorageController.getItemAsync('myKey');
expect(result).toBe('myValue');
await IndexedDBStorageController.removeItemAsync('myKey');
result = await IndexedDBStorageController.getItemAsync('myKey');
expect(result).toBe(null);
});

it('can getAllKeys', async () => {
await IndexedDBStorageController.setItemAsync('myKey', 'myValue');
const result = await IndexedDBStorageController.getItemAsync('myKey');
expect(result).toBe('myValue');
const keys = await IndexedDBStorageController.getAllKeysAsync();
expect(keys[0]).toBe('myKey');
});
});

const DefaultStorageController = require('../StorageController.default');

describe('Default StorageController', () => {
Expand Down
34 changes: 34 additions & 0 deletions src/__tests__/test_helpers/mockIndexedDB.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Copyright (c) 2015-present, Parse, LLC.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
let mockStorage = {};
const mockStorageInterface = {
createStore() {},

async get(path) {
return mockStorage[path] || null;
},

async set(path, value) {
mockStorage[path] = value;
},

async del(path) {
delete mockStorage[path];
},

async keys() {
return Object.keys(mockStorage);
},

async clear() {
mockStorage = {};
},
};

module.exports = mockStorageInterface;
39 changes: 39 additions & 0 deletions src/__tests__/test_helpers/mockStorageInteface.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Copyright (c) 2015-present, Parse, LLC.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
let mockStorage = {};
const mockStorageInterface = {
getItem(path) {
return mockStorage[path] || null;
},

getItemAsync(path) {
return Promise.resolve(mockStorageInterface.getItem(path));
},

setItem(path, value) {
mockStorage[path] = value;
},

setItemAsync(path, value) {
return Promise.resolve(mockStorageInterface.setItem(path, value));
},

removeItem(path) {
delete mockStorage[path];
},

removeItemAsync(path) {
return Promise.resolve(mockStorageInterface.removeItem(path));
},

clear() {
mockStorage = {};
},
};
module.exports = mockStorageInterface;

0 comments on commit c7f1e82

Please sign in to comment.