Skip to content

Commit c4d4d24

Browse files
authored
Merge branch 'alpha' into expo-live-query
2 parents e64cc80 + a821777 commit c4d4d24

20 files changed

+288
-107
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ A library that gives you access to the powerful Parse Server backend from your J
2828

2929
- [Getting Started](#getting-started)
3030
- [Using Parse on Different Platforms](#using-parse-on-different-platforms)
31+
- [Core Manager](#core-manager)
3132
- [Compatibility](#compatibility)
3233
- [Parse Server](#parse-server)
3334
- [Node.js](#nodejs)
@@ -89,6 +90,18 @@ $ npm install @types/parse
8990

9091
Types are updated manually after every release. If a definition doesn't exist, please submit a pull request to [@types/parse][types-parse]
9192

93+
#### Core Manager
94+
95+
The SDK has a [Core Manager](src/CoreManager.js) that handles all configurations and controllers. These modules can be swapped out for customization before you initialize the SDK. For full list of all available modules take a look at the [Core Manager Documentation](src/CoreManager.js).
96+
97+
```js
98+
// Configuration example
99+
Parse.CoreManager.set('REQUEST_ATTEMPT_LIMIT', 1)
100+
101+
// Controller example
102+
Parse.CoreManager.setRESTController(MyRESTController);
103+
```
104+
92105
## Compatibility
93106

94107
### Parse Server

changelogs/CHANGELOG_alpha.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# [5.1.0-alpha.3](https://github.com/parse-community/Parse-SDK-JS/compare/5.1.0-alpha.2...5.1.0-alpha.3) (2024-04-14)
2+
3+
4+
### Features
5+
6+
* Lazy load `Parse.CoreManager` controllers to add support for swappable `CryptoController`, `LocalDatastoreController`, `StorageController`, `WebSocketController`, `ParseLiveQuery` ([#2100](https://github.com/parse-community/Parse-SDK-JS/issues/2100)) ([fbd0ab1](https://github.com/parse-community/Parse-SDK-JS/commit/fbd0ab1402792e241c4d9d6496b451e4cc268b8b))
7+
18
# [5.1.0-alpha.2](https://github.com/parse-community/Parse-SDK-JS/compare/5.1.0-alpha.1...5.1.0-alpha.2) (2024-04-13)
29

310

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
'use strict';
2+
3+
const Parse = require('../../react-native');
4+
const { resolvingPromise } = require('../../lib/react-native/promiseUtils');
5+
const CryptoController = require('../../lib/react-native/CryptoController');
6+
const LocalDatastoreController = require('../../lib/react-native/LocalDatastoreController.default');
7+
const StorageController = require('../../lib/react-native/StorageController.default');
8+
const RESTController = require('../../lib/react-native/RESTController');
9+
10+
RESTController._setXHR(require('xmlhttprequest').XMLHttpRequest);
11+
12+
describe('Parse React Native', () => {
13+
beforeEach(() => {
14+
// Set up missing controllers and configurations
15+
Parse.CoreManager.setWebSocketController(require('ws'));
16+
Parse.CoreManager.setEventEmitter(require('events').EventEmitter);
17+
Parse.CoreManager.setLocalDatastoreController(LocalDatastoreController);
18+
Parse.CoreManager.setStorageController(StorageController);
19+
Parse.CoreManager.setRESTController(RESTController);
20+
Parse.CoreManager.setCryptoController(CryptoController);
21+
22+
Parse.initialize('integration');
23+
Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse');
24+
Parse.CoreManager.set('MASTER_KEY', 'notsosecret');
25+
Parse.enableLocalDatastore();
26+
});
27+
28+
afterEach(async () => {
29+
await Parse.User.logOut();
30+
Parse.Storage._clear();
31+
});
32+
33+
it('can log in a user', async () => {
34+
// Handle Storage Controller
35+
await Parse.User.signUp('asdf', 'zxcv')
36+
const user = await Parse.User.logIn('asdf', 'zxcv');
37+
expect(user.get('username')).toBe('asdf');
38+
expect(user.existed()).toBe(true);
39+
});
40+
41+
it('can encrypt user', async () => {
42+
// Handle Crypto Controller
43+
Parse.User.enableUnsafeCurrentUser();
44+
Parse.enableEncryptedUser();
45+
Parse.secret = 'My Secret Key';
46+
const user = new Parse.User();
47+
user.setUsername('usernameENC');
48+
user.setPassword('passwordENC');
49+
await user.signUp();
50+
51+
const path = Parse.Storage.generatePath('currentUser');
52+
const encryptedUser = Parse.Storage.getItem(path);
53+
54+
const crypto = Parse.CoreManager.getCryptoController();
55+
56+
const decryptedUser = crypto.decrypt(encryptedUser, Parse.CoreManager.get('ENCRYPTED_KEY'));
57+
expect(JSON.parse(decryptedUser).objectId).toBe(user.id);
58+
59+
const currentUser = Parse.User.current();
60+
expect(currentUser).toEqual(user);
61+
62+
const currentUserAsync = await Parse.User.currentAsync();
63+
expect(currentUserAsync).toEqual(user);
64+
await Parse.User.logOut();
65+
Parse.CoreManager.set('ENCRYPTED_USER', false);
66+
Parse.CoreManager.set('ENCRYPTED_KEY', null);
67+
});
68+
69+
it('can pin saved object LDS', async () => {
70+
// Handle LocalDatastore Controller
71+
function LDS_KEY(object) {
72+
return Parse.LocalDatastore.getKeyForObject(object);
73+
}
74+
const object = new Parse.Object('TestObject');
75+
object.set('field', 'test');
76+
await object.save();
77+
await object.pin();
78+
const localDatastore = await Parse.LocalDatastore._getAllContents();
79+
const cachedObject = localDatastore[LDS_KEY(object)][0];
80+
expect(Object.keys(localDatastore).length).toBe(2);
81+
expect(cachedObject.objectId).toBe(object.id);
82+
expect(cachedObject.field).toBe('test');
83+
});
84+
85+
it('can subscribe to query', async () => {
86+
// Handle WebSocket Controller
87+
const object = new Parse.Object('TestObject');
88+
await object.save();
89+
const installationId = await Parse.CoreManager.getInstallationController().currentInstallationId();
90+
91+
const query = new Parse.Query('TestObject');
92+
query.equalTo('objectId', object.id);
93+
const subscription = await query.subscribe();
94+
const promise = resolvingPromise();
95+
subscription.on('update', (object, _, response) => {
96+
expect(object.get('foo')).toBe('bar');
97+
expect(response.installationId).toBe(installationId);
98+
promise.resolve();
99+
});
100+
object.set({ foo: 'bar' });
101+
await object.save();
102+
await promise;
103+
});
104+
});

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "parse",
3-
"version": "5.1.0-alpha.2",
3+
"version": "5.1.0-alpha.3",
44
"description": "Parse JavaScript SDK",
55
"homepage": "https://parseplatform.org",
66
"keywords": [

src/LiveQueryClient.js

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
/* global WebSocket */
2-
31
import CoreManager from './CoreManager';
42
import ParseObject from './ParseObject';
53
import LiveQuerySubscription from './LiveQuerySubscription';
@@ -502,16 +500,4 @@ class LiveQueryClient {
502500
}
503501
}
504502

505-
if (process.env.PARSE_BUILD === 'node') {
506-
CoreManager.setWebSocketController(require('ws'));
507-
} else if (process.env.PARSE_BUILD === 'browser') {
508-
CoreManager.setWebSocketController(
509-
typeof WebSocket === 'function' || typeof WebSocket === 'object' ? WebSocket : null
510-
);
511-
} else if (process.env.PARSE_BUILD === 'weapp') {
512-
CoreManager.setWebSocketController(require('./Socket.weapp'));
513-
} else if (process.env.PARSE_BUILD === 'react-native') {
514-
CoreManager.setWebSocketController(WebSocket);
515-
}
516-
517503
export default LiveQueryClient;
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* @flow
3+
*/
4+
import { isLocalDatastoreKey } from './LocalDatastoreUtils';
5+
import Storage from './Storage';
6+
7+
const LocalDatastoreController = {
8+
async fromPinWithName(name: string): Array<Object> {
9+
const values = await Storage.getItemAsync(name);
10+
if (!values) {
11+
return [];
12+
}
13+
const objects = JSON.parse(values);
14+
return objects;
15+
},
16+
17+
pinWithName(name: string, value: any) {
18+
const values = JSON.stringify(value);
19+
return Storage.setItemAsync(name, values);
20+
},
21+
22+
unPinWithName(name: string) {
23+
return Storage.removeItemAsync(name);
24+
},
25+
26+
async getAllContents(): Object {
27+
const keys = await Storage.getAllKeysAsync();
28+
return keys.reduce(async (previousPromise, key) => {
29+
const LDS = await previousPromise;
30+
if (isLocalDatastoreKey(key)) {
31+
const value = await Storage.getItemAsync(key);
32+
try {
33+
LDS[key] = JSON.parse(value);
34+
} catch (error) {
35+
console.error('Error getAllContents: ', error);
36+
}
37+
}
38+
return LDS;
39+
}, Promise.resolve({}));
40+
},
41+
42+
// Used for testing
43+
async getRawStorage(): Object {
44+
const keys = await Storage.getAllKeysAsync();
45+
return keys.reduce(async (previousPromise, key) => {
46+
const LDS = await previousPromise;
47+
const value = await Storage.getItemAsync(key);
48+
LDS[key] = value;
49+
return LDS;
50+
}, Promise.resolve({}));
51+
},
52+
53+
async clear(): Promise {
54+
const keys = await Storage.getAllKeysAsync();
55+
56+
const toRemove = [];
57+
for (const key of keys) {
58+
if (isLocalDatastoreKey(key)) {
59+
toRemove.push(key);
60+
}
61+
}
62+
const promises = toRemove.map(this.unPinWithName);
63+
return Promise.all(promises);
64+
},
65+
};
66+
67+
module.exports = LocalDatastoreController;

src/LocalDatastoreController.js

Lines changed: 5 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,5 @@
1-
/**
2-
* @flow
3-
*/
4-
import { isLocalDatastoreKey } from './LocalDatastoreUtils';
5-
import Storage from './Storage';
6-
7-
const LocalDatastoreController = {
8-
async fromPinWithName(name: string): Array<Object> {
9-
const values = await Storage.getItemAsync(name);
10-
if (!values) {
11-
return [];
12-
}
13-
const objects = JSON.parse(values);
14-
return objects;
15-
},
16-
17-
pinWithName(name: string, value: any) {
18-
const values = JSON.stringify(value);
19-
return Storage.setItemAsync(name, values);
20-
},
21-
22-
unPinWithName(name: string) {
23-
return Storage.removeItemAsync(name);
24-
},
25-
26-
async getAllContents(): Object {
27-
const keys = await Storage.getAllKeysAsync();
28-
return keys.reduce(async (previousPromise, key) => {
29-
const LDS = await previousPromise;
30-
if (isLocalDatastoreKey(key)) {
31-
const value = await Storage.getItemAsync(key);
32-
try {
33-
LDS[key] = JSON.parse(value);
34-
} catch (error) {
35-
console.error('Error getAllContents: ', error);
36-
}
37-
}
38-
return LDS;
39-
}, Promise.resolve({}));
40-
},
41-
42-
// Used for testing
43-
async getRawStorage(): Object {
44-
const keys = await Storage.getAllKeysAsync();
45-
return keys.reduce(async (previousPromise, key) => {
46-
const LDS = await previousPromise;
47-
const value = await Storage.getItemAsync(key);
48-
LDS[key] = value;
49-
return LDS;
50-
}, Promise.resolve({}));
51-
},
52-
53-
async clear(): Promise {
54-
const keys = await Storage.getAllKeysAsync();
55-
56-
const toRemove = [];
57-
for (const key of keys) {
58-
if (isLocalDatastoreKey(key)) {
59-
toRemove.push(key);
60-
}
61-
}
62-
const promises = toRemove.map(this.unPinWithName);
63-
return Promise.all(promises);
64-
},
65-
};
66-
67-
module.exports = LocalDatastoreController;
1+
if (process.env.PARSE_BUILD === 'react-native') {
2+
module.exports = require('./LocalDatastoreController.react-native');
3+
} else {
4+
module.exports = require('./LocalDatastoreController.default');
5+
}

0 commit comments

Comments
 (0)