Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ ___
- EXPERIMENTAL: Added new page router with placeholder rendering and localization of custom and feature pages such as password reset and email verification (Manuel Trezza) [#6891](https://github.com/parse-community/parse-server/issues/6891)
- EXPERIMENTAL: Added custom routes to easily customize flows for password reset, email verification or build entirely new flows (Manuel Trezza) [#7231](https://github.com/parse-community/parse-server/issues/7231)
### Other Changes
- Allow afterFind and afterLiveQueryEvent to set pointers (dblythy) [#7310](https://github.com/parse-community/parse-server/pull/7310)
- Fix error when a not yet inserted job is updated (Antonio Davi Macedo Coelho de Castro) [#7196](https://github.com/parse-community/parse-server/pull/7196)
- request.context for afterFind triggers (dblythy) [#7078](https://github.com/parse-community/parse-server/pull/7078)
- Winston Logger interpolating stdout to console (dplewis) [#7114](https://github.com/parse-community/parse-server/pull/7114)
Expand Down
19 changes: 19 additions & 0 deletions spec/CloudCode.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2383,6 +2383,25 @@ describe('afterFind hooks', () => {
});
});

it('can set a pointer object in afterFind', async done => {
const obj = new Parse.Object('MyObject');
await obj.save();
Parse.Cloud.afterFind('MyObject', async ({ objects }) => {
const otherObject = new Parse.Object('Test');
otherObject.set('foo', 'bar');
await otherObject.save();
objects[0].set('Pointer', otherObject);
expect(objects[0].get('Pointer').get('foo')).toBe('bar');
return objects;
});
const query = new Parse.Query('MyObject');
query.equalTo('objectId', obj.id);
const [obj2] = await query.find();
const pointer = obj2.get('Pointer');
expect(pointer.get('foo')).toBe('bar');
done();
});

it('should have request headers', done => {
Parse.Cloud.afterFind('MyObject', req => {
expect(req.headers).toBeDefined();
Expand Down
38 changes: 38 additions & 0 deletions spec/ParseLiveQuery.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,44 @@ describe('ParseLiveQuery', function () {
await object.save();
});

it('can handle afterEvent set pointers', async done => {
await reconfigureServer({
liveQuery: {
classNames: ['TestObject'],
},
startLiveQueryServer: true,
verbose: false,
silent: true,
});

const object = new TestObject();
await object.save();

const secondObject = new Parse.Object('Test2');
secondObject.set('foo', 'bar');
await secondObject.save();

Parse.Cloud.afterLiveQueryEvent('TestObject', async ({ object }) => {
const query = new Parse.Query('Test2');
const obj = await query.first();
object.set('obj', obj);
});

const query = new Parse.Query(TestObject);
query.equalTo('objectId', object.id);
const subscription = await query.subscribe();
subscription.on('update', object => {
expect(object.get('obj')).toBeDefined();
expect(object.get('obj').get('foo')).toBe('bar');
done();
});
subscription.on('error', () => {
fail('error should not have been called.');
});
object.set({ foo: 'bar' });
await object.save();
});

it('can handle async afterEvent modification', async done => {
await reconfigureServer({
liveQuery: {
Expand Down
15 changes: 7 additions & 8 deletions src/LiveQuery/ParseLiveQueryServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ParsePubSub } from './ParsePubSub';
import SchemaController from '../Controllers/SchemaController';
import _ from 'lodash';
import { v4 as uuidv4 } from 'uuid';
import { runLiveQueryEventHandlers, getTrigger, runTrigger } from '../triggers';
import { runLiveQueryEventHandlers, getTrigger, runTrigger, toJSONwithObjects } from '../triggers';
import { getAuthForSessionToken, Auth } from '../Auth';
import { getCacheController } from '../Controllers';
import LRU from 'lru-cache';
Expand Down Expand Up @@ -181,8 +181,7 @@ class ParseLiveQueryServer {
return;
}
if (res.object && typeof res.object.toJSON === 'function') {
deletedParseObject = res.object.toJSON();
deletedParseObject.className = className;
deletedParseObject = toJSONwithObjects(res.object, res.object.className || className);
}
client.pushDelete(requestId, deletedParseObject);
} catch (error) {
Expand Down Expand Up @@ -326,13 +325,13 @@ class ParseLiveQueryServer {
return;
}
if (res.object && typeof res.object.toJSON === 'function') {
currentParseObject = res.object.toJSON();
currentParseObject.className = res.object.className || className;
currentParseObject = toJSONwithObjects(res.object, res.object.className || className);
}

if (res.original && typeof res.original.toJSON === 'function') {
originalParseObject = res.original.toJSON();
originalParseObject.className = res.original.className || className;
originalParseObject = toJSONwithObjects(
res.original,
res.original.className || className
);
}
const functionName =
'push' + message.event.charAt(0).toUpperCase() + message.event.slice(1);
Expand Down
24 changes: 23 additions & 1 deletion src/triggers.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,28 @@ export function _unregisterAll() {
Object.keys(_triggerStore).forEach(appId => delete _triggerStore[appId]);
}

export function toJSONwithObjects(object, className) {
if (!object || !object.toJSON) {
return {};
}
const toJSON = object.toJSON();
for (const key of Object.keys(toJSON)) {
const val = toJSON[key];
if (!val || !val.__type || val.__type !== 'Pointer') {
continue;
}
const pointer = object.get(key);
const json = pointer.toJSON();
json.className = pointer.className;
json.__type = 'Object';
toJSON[key] = json;
}
if (className) {
toJSON.className = className;
}
return toJSON;
}

export function getTrigger(className, triggerType, applicationId) {
if (!applicationId) {
throw 'Missing ApplicationID';
Expand Down Expand Up @@ -316,7 +338,7 @@ export function getResponseObject(request, resolve, reject) {
response = request.objects;
}
response = response.map(object => {
return object.toJSON();
return toJSONwithObjects(object);
});
return resolve(response);
}
Expand Down