-
-
Notifications
You must be signed in to change notification settings - Fork 595
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Lazy load
Parse.CoreManager
controllers to add support for sw…
…appable `CryptoController`, `LocalDatastoreController`, `StorageController`, `WebSocketController`, `ParseLiveQuery` (#2100)
- Loading branch information
Showing
17 changed files
with
278 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
'use strict'; | ||
|
||
const Parse = require('../../react-native'); | ||
const { resolvingPromise } = require('../../lib/react-native/promiseUtils'); | ||
const CryptoController = require('../../lib/react-native/CryptoController'); | ||
const LocalDatastoreController = require('../../lib/react-native/LocalDatastoreController.default'); | ||
const StorageController = require('../../lib/react-native/StorageController.default'); | ||
const RESTController = require('../../lib/react-native/RESTController'); | ||
|
||
RESTController._setXHR(require('xmlhttprequest').XMLHttpRequest); | ||
|
||
describe('Parse React Native', () => { | ||
beforeEach(() => { | ||
// Set up missing controllers and configurations | ||
Parse.CoreManager.setWebSocketController(require('ws')); | ||
Parse.CoreManager.setEventEmitter(require('events').EventEmitter); | ||
Parse.CoreManager.setLocalDatastoreController(LocalDatastoreController); | ||
Parse.CoreManager.setStorageController(StorageController); | ||
Parse.CoreManager.setRESTController(RESTController); | ||
Parse.CoreManager.setCryptoController(CryptoController); | ||
|
||
Parse.initialize('integration'); | ||
Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); | ||
Parse.CoreManager.set('MASTER_KEY', 'notsosecret'); | ||
Parse.enableLocalDatastore(); | ||
}); | ||
|
||
afterEach(async () => { | ||
await Parse.User.logOut(); | ||
Parse.Storage._clear(); | ||
}); | ||
|
||
it('can log in a user', async () => { | ||
// Handle Storage Controller | ||
await Parse.User.signUp('asdf', 'zxcv') | ||
const user = await Parse.User.logIn('asdf', 'zxcv'); | ||
expect(user.get('username')).toBe('asdf'); | ||
expect(user.existed()).toBe(true); | ||
}); | ||
|
||
it('can encrypt user', async () => { | ||
// Handle Crypto Controller | ||
Parse.User.enableUnsafeCurrentUser(); | ||
Parse.enableEncryptedUser(); | ||
Parse.secret = 'My Secret Key'; | ||
const user = new Parse.User(); | ||
user.setUsername('usernameENC'); | ||
user.setPassword('passwordENC'); | ||
await user.signUp(); | ||
|
||
const path = Parse.Storage.generatePath('currentUser'); | ||
const encryptedUser = Parse.Storage.getItem(path); | ||
|
||
const crypto = Parse.CoreManager.getCryptoController(); | ||
|
||
const decryptedUser = crypto.decrypt(encryptedUser, Parse.CoreManager.get('ENCRYPTED_KEY')); | ||
expect(JSON.parse(decryptedUser).objectId).toBe(user.id); | ||
|
||
const currentUser = Parse.User.current(); | ||
expect(currentUser).toEqual(user); | ||
|
||
const currentUserAsync = await Parse.User.currentAsync(); | ||
expect(currentUserAsync).toEqual(user); | ||
await Parse.User.logOut(); | ||
Parse.CoreManager.set('ENCRYPTED_USER', false); | ||
Parse.CoreManager.set('ENCRYPTED_KEY', null); | ||
}); | ||
|
||
it('can pin saved object LDS', async () => { | ||
// Handle LocalDatastore Controller | ||
function LDS_KEY(object) { | ||
return Parse.LocalDatastore.getKeyForObject(object); | ||
} | ||
const object = new Parse.Object('TestObject'); | ||
object.set('field', 'test'); | ||
await object.save(); | ||
await object.pin(); | ||
const localDatastore = await Parse.LocalDatastore._getAllContents(); | ||
const cachedObject = localDatastore[LDS_KEY(object)][0]; | ||
expect(Object.keys(localDatastore).length).toBe(2); | ||
expect(cachedObject.objectId).toBe(object.id); | ||
expect(cachedObject.field).toBe('test'); | ||
}); | ||
|
||
it('can subscribe to query', async () => { | ||
// Handle WebSocket Controller | ||
const object = new Parse.Object('TestObject'); | ||
await object.save(); | ||
const installationId = await Parse.CoreManager.getInstallationController().currentInstallationId(); | ||
|
||
const query = new Parse.Query('TestObject'); | ||
query.equalTo('objectId', object.id); | ||
const subscription = await query.subscribe(); | ||
const promise = resolvingPromise(); | ||
subscription.on('update', (object, _, response) => { | ||
expect(object.get('foo')).toBe('bar'); | ||
expect(response.installationId).toBe(installationId); | ||
promise.resolve(); | ||
}); | ||
object.set({ foo: 'bar' }); | ||
await object.save(); | ||
await promise; | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/** | ||
* @flow | ||
*/ | ||
import { isLocalDatastoreKey } from './LocalDatastoreUtils'; | ||
import Storage from './Storage'; | ||
|
||
const LocalDatastoreController = { | ||
async fromPinWithName(name: string): Array<Object> { | ||
const values = await Storage.getItemAsync(name); | ||
if (!values) { | ||
return []; | ||
} | ||
const objects = JSON.parse(values); | ||
return objects; | ||
}, | ||
|
||
pinWithName(name: string, value: any) { | ||
const values = JSON.stringify(value); | ||
return Storage.setItemAsync(name, values); | ||
}, | ||
|
||
unPinWithName(name: string) { | ||
return Storage.removeItemAsync(name); | ||
}, | ||
|
||
async getAllContents(): Object { | ||
const keys = await Storage.getAllKeysAsync(); | ||
return keys.reduce(async (previousPromise, key) => { | ||
const LDS = await previousPromise; | ||
if (isLocalDatastoreKey(key)) { | ||
const value = await Storage.getItemAsync(key); | ||
try { | ||
LDS[key] = JSON.parse(value); | ||
} catch (error) { | ||
console.error('Error getAllContents: ', error); | ||
} | ||
} | ||
return LDS; | ||
}, Promise.resolve({})); | ||
}, | ||
|
||
// Used for testing | ||
async getRawStorage(): Object { | ||
const keys = await Storage.getAllKeysAsync(); | ||
return keys.reduce(async (previousPromise, key) => { | ||
const LDS = await previousPromise; | ||
const value = await Storage.getItemAsync(key); | ||
LDS[key] = value; | ||
return LDS; | ||
}, Promise.resolve({})); | ||
}, | ||
|
||
async clear(): Promise { | ||
const keys = await Storage.getAllKeysAsync(); | ||
|
||
const toRemove = []; | ||
for (const key of keys) { | ||
if (isLocalDatastoreKey(key)) { | ||
toRemove.push(key); | ||
} | ||
} | ||
const promises = toRemove.map(this.unPinWithName); | ||
return Promise.all(promises); | ||
}, | ||
}; | ||
|
||
module.exports = LocalDatastoreController; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,67 +1,5 @@ | ||
/** | ||
* @flow | ||
*/ | ||
import { isLocalDatastoreKey } from './LocalDatastoreUtils'; | ||
import Storage from './Storage'; | ||
|
||
const LocalDatastoreController = { | ||
async fromPinWithName(name: string): Array<Object> { | ||
const values = await Storage.getItemAsync(name); | ||
if (!values) { | ||
return []; | ||
} | ||
const objects = JSON.parse(values); | ||
return objects; | ||
}, | ||
|
||
pinWithName(name: string, value: any) { | ||
const values = JSON.stringify(value); | ||
return Storage.setItemAsync(name, values); | ||
}, | ||
|
||
unPinWithName(name: string) { | ||
return Storage.removeItemAsync(name); | ||
}, | ||
|
||
async getAllContents(): Object { | ||
const keys = await Storage.getAllKeysAsync(); | ||
return keys.reduce(async (previousPromise, key) => { | ||
const LDS = await previousPromise; | ||
if (isLocalDatastoreKey(key)) { | ||
const value = await Storage.getItemAsync(key); | ||
try { | ||
LDS[key] = JSON.parse(value); | ||
} catch (error) { | ||
console.error('Error getAllContents: ', error); | ||
} | ||
} | ||
return LDS; | ||
}, Promise.resolve({})); | ||
}, | ||
|
||
// Used for testing | ||
async getRawStorage(): Object { | ||
const keys = await Storage.getAllKeysAsync(); | ||
return keys.reduce(async (previousPromise, key) => { | ||
const LDS = await previousPromise; | ||
const value = await Storage.getItemAsync(key); | ||
LDS[key] = value; | ||
return LDS; | ||
}, Promise.resolve({})); | ||
}, | ||
|
||
async clear(): Promise { | ||
const keys = await Storage.getAllKeysAsync(); | ||
|
||
const toRemove = []; | ||
for (const key of keys) { | ||
if (isLocalDatastoreKey(key)) { | ||
toRemove.push(key); | ||
} | ||
} | ||
const promises = toRemove.map(this.unPinWithName); | ||
return Promise.all(promises); | ||
}, | ||
}; | ||
|
||
module.exports = LocalDatastoreController; | ||
if (process.env.PARSE_BUILD === 'react-native') { | ||
module.exports = require('./LocalDatastoreController.react-native'); | ||
} else { | ||
module.exports = require('./LocalDatastoreController.default'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
if (process.env.PARSE_BUILD === 'react-native') { | ||
module.exports = require('./StorageController.react-native'); | ||
} else if (process.env.PARSE_BUILD === 'browser') { | ||
module.exports = require('./StorageController.browser'); | ||
} else if (process.env.PARSE_BUILD === 'weapp') { | ||
module.exports = require('./StorageController.weapp'); | ||
} else { | ||
module.exports = require('./StorageController.default'); | ||
} |
Oops, something went wrong.