feat: Upgrade to Parse JavaScript SDK 4 (#8332)
This commit is contained in:
51
package-lock.json
generated
51
package-lock.json
generated
@@ -39,7 +39,7 @@
|
||||
"mime": "3.0.0",
|
||||
"mongodb": "4.10.0",
|
||||
"mustache": "4.2.0",
|
||||
"parse": "3.4.2",
|
||||
"parse": "4.0.0",
|
||||
"path-to-regexp": "0.1.7",
|
||||
"pg-monitor": "1.5.0",
|
||||
"pg-promise": "10.12.1",
|
||||
@@ -1771,9 +1771,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.17.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz",
|
||||
"integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==",
|
||||
"version": "7.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.0.tgz",
|
||||
"integrity": "sha512-YMQvx/6nKEaucl0MY56mwIG483xk8SDNdlUwb2Ts6FUpr7fm85DxEmsY18LXBNhcTz6tO6JwZV8w1W06v8UKeg==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
},
|
||||
@@ -16116,18 +16116,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/parse": {
|
||||
"version": "3.4.2",
|
||||
"resolved": "https://registry.npmjs.org/parse/-/parse-3.4.2.tgz",
|
||||
"integrity": "sha512-Ruehcp/S7eB3A0lDG5eAPvZHa5pABCbUR+lMJL2gUNKJLZNcD9/s3RL255PwI5jTqa+TCJ7MdPqobUplouN1pQ==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse/-/parse-4.0.0.tgz",
|
||||
"integrity": "sha512-LKaHHqSLulEv1f76Cg3eJlDQL8FtK+mn6XehVbjY7uUGwm2B3LyzYjBH6iX0BXOFwfABcDRtq+8KCpuHXiIQ3g==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.17.9",
|
||||
"@babel/runtime": "7.18.0",
|
||||
"@babel/runtime-corejs3": "7.17.8",
|
||||
"idb-keyval": "6.0.3",
|
||||
"react-native-crypto-js": "1.0.0",
|
||||
"uuid": "3.4.0",
|
||||
"ws": "7.5.1",
|
||||
"ws": "8.6.0",
|
||||
"xmlhttprequest": "1.8.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.21.0 <17 || >=18 <19"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"crypto-js": "4.1.1"
|
||||
}
|
||||
@@ -16169,11 +16172,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/parse/node_modules/ws": {
|
||||
"version": "7.5.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.1.tgz",
|
||||
"integrity": "sha512-2c6faOUH/nhoQN6abwMloF7Iyl0ZS2E9HGtsiLrWn0zOOMWlhtDmdf/uihDt6jnuCxgtwGBNy6Onsoy2s2O2Ow==",
|
||||
"version": "8.6.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz",
|
||||
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==",
|
||||
"engines": {
|
||||
"node": ">=8.3.0"
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
@@ -21881,9 +21884,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/runtime": {
|
||||
"version": "7.17.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz",
|
||||
"integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==",
|
||||
"version": "7.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.0.tgz",
|
||||
"integrity": "sha512-YMQvx/6nKEaucl0MY56mwIG483xk8SDNdlUwb2Ts6FUpr7fm85DxEmsY18LXBNhcTz6tO6JwZV8w1W06v8UKeg==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
@@ -32871,17 +32874,17 @@
|
||||
}
|
||||
},
|
||||
"parse": {
|
||||
"version": "3.4.2",
|
||||
"resolved": "https://registry.npmjs.org/parse/-/parse-3.4.2.tgz",
|
||||
"integrity": "sha512-Ruehcp/S7eB3A0lDG5eAPvZHa5pABCbUR+lMJL2gUNKJLZNcD9/s3RL255PwI5jTqa+TCJ7MdPqobUplouN1pQ==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse/-/parse-4.0.0.tgz",
|
||||
"integrity": "sha512-LKaHHqSLulEv1f76Cg3eJlDQL8FtK+mn6XehVbjY7uUGwm2B3LyzYjBH6iX0BXOFwfABcDRtq+8KCpuHXiIQ3g==",
|
||||
"requires": {
|
||||
"@babel/runtime": "7.17.9",
|
||||
"@babel/runtime": "7.18.0",
|
||||
"@babel/runtime-corejs3": "7.17.8",
|
||||
"crypto-js": "4.1.1",
|
||||
"idb-keyval": "6.0.3",
|
||||
"react-native-crypto-js": "1.0.0",
|
||||
"uuid": "3.4.0",
|
||||
"ws": "7.5.1",
|
||||
"ws": "8.6.0",
|
||||
"xmlhttprequest": "1.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -32891,9 +32894,9 @@
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
},
|
||||
"ws": {
|
||||
"version": "7.5.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.1.tgz",
|
||||
"integrity": "sha512-2c6faOUH/nhoQN6abwMloF7Iyl0ZS2E9HGtsiLrWn0zOOMWlhtDmdf/uihDt6jnuCxgtwGBNy6Onsoy2s2O2Ow==",
|
||||
"version": "8.6.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz",
|
||||
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==",
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
"mime": "3.0.0",
|
||||
"mongodb": "4.10.0",
|
||||
"mustache": "4.2.0",
|
||||
"parse": "3.4.2",
|
||||
"parse": "4.0.0",
|
||||
"path-to-regexp": "0.1.7",
|
||||
"pg-monitor": "1.5.0",
|
||||
"pg-promise": "10.12.1",
|
||||
|
||||
@@ -7,6 +7,15 @@ const validatorFail = () => {
|
||||
};
|
||||
|
||||
describe('ParseLiveQuery', function () {
|
||||
beforeEach(() => {
|
||||
Parse.CoreManager.getLiveQueryController().setDefaultLiveQueryClient(null);
|
||||
});
|
||||
afterEach(async () => {
|
||||
const client = await Parse.CoreManager.getLiveQueryController().getDefaultLiveQueryClient();
|
||||
client.close();
|
||||
// Wait for live query client to disconnect
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
});
|
||||
it('access user on onLiveQueryEvent disconnect', async done => {
|
||||
await reconfigureServer({
|
||||
liveQuery: {
|
||||
@@ -16,7 +25,6 @@ describe('ParseLiveQuery', function () {
|
||||
verbose: false,
|
||||
silent: true,
|
||||
});
|
||||
Parse.CoreManager.getLiveQueryController().setDefaultLiveQueryClient(null);
|
||||
const requestedUser = new Parse.User();
|
||||
requestedUser.setUsername('username');
|
||||
requestedUser.setPassword('password');
|
||||
@@ -513,76 +521,67 @@ describe('ParseLiveQuery', function () {
|
||||
classNames: ['TestObject'],
|
||||
},
|
||||
startLiveQueryServer: true,
|
||||
verbose: false,
|
||||
silent: true,
|
||||
});
|
||||
const object = new TestObject();
|
||||
await object.save();
|
||||
|
||||
Parse.Cloud.beforeSubscribe('TestObject', req => {
|
||||
expect(req.op).toBe('subscribe');
|
||||
expect(req.requestId).toBe(1);
|
||||
expect(req.query).toBeDefined();
|
||||
expect(req.user).toBeUndefined();
|
||||
});
|
||||
|
||||
Parse.Cloud.beforeConnect(req => {
|
||||
expect(req.event).toBe('connect');
|
||||
expect(req.clients).toBe(0);
|
||||
expect(req.subscriptions).toBe(0);
|
||||
expect(req.useMasterKey).toBe(false);
|
||||
expect(req.installationId).toBeDefined();
|
||||
expect(req.user).toBeUndefined();
|
||||
expect(req.client).toBeDefined();
|
||||
});
|
||||
const hooks = {
|
||||
beforeSubscribe(req) {
|
||||
expect(req.op).toBe('subscribe');
|
||||
expect(req.requestId).toBe(1);
|
||||
expect(req.query).toBeDefined();
|
||||
expect(req.user).toBeUndefined();
|
||||
},
|
||||
beforeConnect(req) {
|
||||
expect(req.event).toBe('connect');
|
||||
expect(req.clients).toBe(0);
|
||||
expect(req.subscriptions).toBe(0);
|
||||
expect(req.useMasterKey).toBe(false);
|
||||
expect(req.installationId).toBeDefined();
|
||||
expect(req.user).toBeUndefined();
|
||||
expect(req.client).toBeDefined();
|
||||
},
|
||||
};
|
||||
spyOn(hooks, 'beforeSubscribe').and.callThrough();
|
||||
spyOn(hooks, 'beforeConnect').and.callThrough();
|
||||
Parse.Cloud.beforeSubscribe('TestObject', hooks.beforeSubscribe);
|
||||
Parse.Cloud.beforeConnect(hooks.beforeConnect);
|
||||
const query = new Parse.Query(TestObject);
|
||||
query.equalTo('objectId', object.id);
|
||||
const subscription = await query.subscribe();
|
||||
subscription.on('update', object => {
|
||||
expect(object.get('foo')).toBe('bar');
|
||||
expect(hooks.beforeConnect).toHaveBeenCalled();
|
||||
expect(hooks.beforeSubscribe).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
object.set({ foo: 'bar' });
|
||||
await object.save();
|
||||
});
|
||||
|
||||
it('can handle beforeConnect validation function', async done => {
|
||||
it('can handle beforeConnect validation function', async () => {
|
||||
await reconfigureServer({
|
||||
liveQuery: {
|
||||
classNames: ['TestObject'],
|
||||
},
|
||||
startLiveQueryServer: true,
|
||||
verbose: false,
|
||||
silent: true,
|
||||
});
|
||||
|
||||
const object = new TestObject();
|
||||
await object.save();
|
||||
|
||||
Parse.Cloud.beforeConnect(() => {}, validatorFail);
|
||||
let complete = false;
|
||||
Parse.LiveQuery.on('error', error => {
|
||||
Parse.LiveQuery.removeAllListeners('error');
|
||||
if (complete) {
|
||||
return;
|
||||
}
|
||||
complete = true;
|
||||
expect(error).toBe('you are not authorized');
|
||||
done();
|
||||
});
|
||||
const query = new Parse.Query(TestObject);
|
||||
query.equalTo('objectId', object.id);
|
||||
await query.subscribe();
|
||||
await expectAsync(query.subscribe()).toBeRejectedWith(
|
||||
new Parse.Error(Parse.Error.VALIDATION_ERROR, 'you are not authorized')
|
||||
);
|
||||
});
|
||||
|
||||
it('can handle beforeSubscribe validation function', async done => {
|
||||
it('can handle beforeSubscribe validation function', async () => {
|
||||
await reconfigureServer({
|
||||
liveQuery: {
|
||||
classNames: ['TestObject'],
|
||||
},
|
||||
startLiveQueryServer: true,
|
||||
verbose: false,
|
||||
silent: true,
|
||||
});
|
||||
const object = new TestObject();
|
||||
await object.save();
|
||||
@@ -590,11 +589,9 @@ describe('ParseLiveQuery', function () {
|
||||
Parse.Cloud.beforeSubscribe(TestObject, () => {}, validatorFail);
|
||||
const query = new Parse.Query(TestObject);
|
||||
query.equalTo('objectId', object.id);
|
||||
const subscription = await query.subscribe();
|
||||
subscription.on('error', error => {
|
||||
expect(error).toBe('you are not authorized');
|
||||
done();
|
||||
});
|
||||
await expectAsync(query.subscribe()).toBeRejectedWith(
|
||||
new Parse.Error(Parse.Error.VALIDATION_ERROR, 'you are not authorized')
|
||||
);
|
||||
});
|
||||
|
||||
it('can handle afterEvent validation function', async done => {
|
||||
@@ -620,14 +617,12 @@ describe('ParseLiveQuery', function () {
|
||||
await object.save();
|
||||
});
|
||||
|
||||
it('can handle beforeConnect error', async done => {
|
||||
it('can handle beforeConnect error', async () => {
|
||||
await reconfigureServer({
|
||||
liveQuery: {
|
||||
classNames: ['TestObject'],
|
||||
},
|
||||
startLiveQueryServer: true,
|
||||
verbose: false,
|
||||
silent: true,
|
||||
});
|
||||
const object = new TestObject();
|
||||
await object.save();
|
||||
@@ -635,14 +630,9 @@ describe('ParseLiveQuery', function () {
|
||||
Parse.Cloud.beforeConnect(() => {
|
||||
throw new Error('You shall not pass!');
|
||||
});
|
||||
Parse.LiveQuery.on('error', error => {
|
||||
Parse.LiveQuery.removeAllListeners('error');
|
||||
expect(error).toBe('You shall not pass!');
|
||||
done();
|
||||
});
|
||||
const query = new Parse.Query(TestObject);
|
||||
query.equalTo('objectId', object.id);
|
||||
await query.subscribe();
|
||||
await expectAsync(query.subscribe()).toBeRejectedWith(new Error('You shall not pass!'));
|
||||
});
|
||||
|
||||
it('can log on beforeConnect throw', async () => {
|
||||
@@ -651,8 +641,6 @@ describe('ParseLiveQuery', function () {
|
||||
classNames: ['TestObject'],
|
||||
},
|
||||
startLiveQueryServer: true,
|
||||
verbose: false,
|
||||
silent: true,
|
||||
});
|
||||
|
||||
const logger = require('../lib/logger').logger;
|
||||
@@ -664,22 +652,20 @@ describe('ParseLiveQuery', function () {
|
||||
foo.bar();
|
||||
/* eslint-enable no-undef */
|
||||
});
|
||||
new Parse.Query(TestObject).subscribe();
|
||||
await new Promise(resolve => Parse.LiveQuery.on('error', resolve));
|
||||
Parse.LiveQuery.removeAllListeners('error');
|
||||
await expectAsync(new Parse.Query(TestObject).subscribe()).toBeRejectedWith(
|
||||
new Error('foo is not defined')
|
||||
);
|
||||
expect(logger.error).toHaveBeenCalledWith(
|
||||
`Failed running beforeConnect for session ${token} with:\n Error: {"message":"foo is not defined","code":141}`
|
||||
);
|
||||
});
|
||||
|
||||
it('can handle beforeSubscribe error', async done => {
|
||||
it('can handle beforeSubscribe error', async () => {
|
||||
await reconfigureServer({
|
||||
liveQuery: {
|
||||
classNames: ['TestObject'],
|
||||
},
|
||||
startLiveQueryServer: true,
|
||||
verbose: false,
|
||||
silent: true,
|
||||
});
|
||||
const object = new TestObject();
|
||||
await object.save();
|
||||
@@ -687,17 +673,9 @@ describe('ParseLiveQuery', function () {
|
||||
Parse.Cloud.beforeSubscribe(TestObject, () => {
|
||||
throw new Error('You shall not subscribe!');
|
||||
});
|
||||
Parse.LiveQuery.on('error', error => {
|
||||
expect(error).toBe('You shall not subscribe!');
|
||||
});
|
||||
const query = new Parse.Query(TestObject);
|
||||
query.equalTo('objectId', object.id);
|
||||
const subscription = await query.subscribe();
|
||||
subscription.on('error', error => {
|
||||
Parse.LiveQuery.removeAllListeners('error');
|
||||
expect(error).toBe('You shall not subscribe!');
|
||||
done();
|
||||
});
|
||||
await expectAsync(query.subscribe()).toBeRejectedWith(new Error('You shall not subscribe!'));
|
||||
});
|
||||
|
||||
it('can log on beforeSubscribe error', async () => {
|
||||
@@ -706,8 +684,6 @@ describe('ParseLiveQuery', function () {
|
||||
classNames: ['TestObject'],
|
||||
},
|
||||
startLiveQueryServer: true,
|
||||
verbose: false,
|
||||
silent: true,
|
||||
});
|
||||
|
||||
const logger = require('../lib/logger').logger;
|
||||
@@ -720,8 +696,7 @@ describe('ParseLiveQuery', function () {
|
||||
});
|
||||
|
||||
const query = new Parse.Query(TestObject);
|
||||
const subscription = await query.subscribe();
|
||||
await new Promise(resolve => subscription.on('error', resolve));
|
||||
await expectAsync(query.subscribe()).toBeRejectedWith(new Error('foo is not defined'));
|
||||
|
||||
expect(logger.error).toHaveBeenCalledWith(
|
||||
`Failed running beforeSubscribe on TestObject for session undefined with:\n Error: {"message":"foo is not defined","code":141}`
|
||||
@@ -734,29 +709,35 @@ describe('ParseLiveQuery', function () {
|
||||
classNames: ['TestObject'],
|
||||
},
|
||||
startLiveQueryServer: true,
|
||||
verbose: false,
|
||||
silent: true,
|
||||
});
|
||||
Parse.Cloud.beforeSubscribe(TestObject, request => {
|
||||
const query = request.query;
|
||||
query.equalTo('yolo', 'abc');
|
||||
});
|
||||
|
||||
const hook = {
|
||||
beforeSubscribe(request) {
|
||||
request.query.equalTo('yolo', 'abc');
|
||||
},
|
||||
};
|
||||
spyOn(hook, 'beforeSubscribe').and.callThrough();
|
||||
Parse.Cloud.beforeSubscribe('TestObject', hook.beforeSubscribe);
|
||||
const object = new TestObject();
|
||||
await object.save();
|
||||
|
||||
const query = new Parse.Query(TestObject);
|
||||
const query = new Parse.Query('TestObject');
|
||||
query.equalTo('objectId', object.id);
|
||||
const subscription = await query.subscribe();
|
||||
|
||||
subscription.on('update', () => {
|
||||
fail();
|
||||
fail('beforeSubscribe should restrict subscription');
|
||||
});
|
||||
object.set({ foo: 'bar' });
|
||||
subscription.on('enter', object => {
|
||||
if (object.get('yolo') === 'abc') {
|
||||
done();
|
||||
} else {
|
||||
fail('beforeSubscribe should restrict queries');
|
||||
}
|
||||
});
|
||||
object.set({ yolo: 'bar' });
|
||||
await object.save();
|
||||
setTimeout(async () => {
|
||||
done();
|
||||
}, 1000);
|
||||
object.set({ yolo: 'abc' });
|
||||
await object.save();
|
||||
expect(hook.beforeSubscribe).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('can return a new beforeSubscribe query', async done => {
|
||||
@@ -954,26 +935,15 @@ describe('ParseLiveQuery', function () {
|
||||
await Parse.User.logIn('username', 'password');
|
||||
});
|
||||
|
||||
it('prevent liveQuery on Session class when not logged in', async done => {
|
||||
it('prevent liveQuery on Session class when not logged in', async () => {
|
||||
await reconfigureServer({
|
||||
liveQuery: {
|
||||
classNames: [Parse.Session],
|
||||
},
|
||||
startLiveQueryServer: true,
|
||||
verbose: false,
|
||||
silent: true,
|
||||
});
|
||||
|
||||
Parse.LiveQuery.on('error', error => {
|
||||
expect(error).toBe('Invalid session token');
|
||||
});
|
||||
const query = new Parse.Query(Parse.Session);
|
||||
const subscription = await query.subscribe();
|
||||
subscription.on('error', error => {
|
||||
Parse.LiveQuery.removeAllListeners('error');
|
||||
expect(error).toBe('Invalid session token');
|
||||
done();
|
||||
});
|
||||
await expectAsync(query.subscribe()).toBeRejectedWith(new Error('Invalid session token'));
|
||||
});
|
||||
|
||||
it('handle invalid websocket payload length', async done => {
|
||||
@@ -1242,13 +1212,4 @@ describe('ParseLiveQuery', function () {
|
||||
object.set({ location: secondPoint });
|
||||
await object.save();
|
||||
});
|
||||
|
||||
afterEach(async function (done) {
|
||||
const client = await Parse.CoreManager.getLiveQueryController().getDefaultLiveQueryClient();
|
||||
client.close();
|
||||
// Wait for live query client to disconnect
|
||||
setTimeout(() => {
|
||||
done();
|
||||
}, 1000);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user