Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
7 changes: 3 additions & 4 deletions spec/ParseHooks.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ describe('Hooks', () => {

it('should run the function on the test server (error handling)', done => {
app.post('/SomeFunctionError', function (req, res) {
res.json({ error: { code: 1337, error: 'hacking that one!' } });
res.json({ error: { code: 1337, message: 'hacking that one!' } });
});
// The function is deleted as the DB is dropped between calls
Parse.Hooks.createFunction('SOME_TEST_FUNCTION', hookServerURL + '/SomeFunctionError')
Expand All @@ -464,9 +464,8 @@ describe('Hooks', () => {
expect(err).not.toBe(undefined);
expect(err).not.toBe(null);
if (err) {
expect(err.code).toBe(Parse.Error.SCRIPT_FAILED);
expect(err.message.code).toEqual(1337);
expect(err.message.error).toEqual('hacking that one!');
expect(err.code).toBe(1337);
expect(err.message).toEqual('hacking that one!');
}
done();
}
Expand Down
90 changes: 90 additions & 0 deletions spec/ParseLiveQuery.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,41 @@ describe('ParseLiveQuery', function () {
await object.save();
});

it('can log on afterLiveQueryEvent throw', async () => {
await reconfigureServer({
liveQuery: {
classNames: ['TestObject'],
},
startLiveQueryServer: true,
verbose: false,
silent: true,
});

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

const logger = require('../lib/logger').logger;
spyOn(logger, 'error').and.callFake(() => {});

let session = undefined;
Parse.Cloud.afterLiveQueryEvent('TestObject', ({ sessionToken }) => {
session = sessionToken;
/* eslint-disable no-undef */
foo.bar();
/* eslint-enable no-undef */
});

const query = new Parse.Query(TestObject);
query.equalTo('objectId', object.id);
const subscription = await query.subscribe();
object.set({ foo: 'bar' });
await object.save();
await new Promise(resolve => subscription.on('error', resolve));
expect(logger.error).toHaveBeenCalledWith(
`Failed running afterLiveQueryEvent on class TestObject for event update with session ${session} with:\n Error: {"message":"foo is not defined","code":141}`
);
});

it('can handle afterEvent sendEvent to false', async done => {
await reconfigureServer({
liveQuery: {
Expand Down Expand Up @@ -566,6 +601,33 @@ describe('ParseLiveQuery', function () {
await query.subscribe();
});

it('can log on beforeConnect throw', async () => {
await reconfigureServer({
liveQuery: {
classNames: ['TestObject'],
},
startLiveQueryServer: true,
verbose: false,
silent: true,
});

const logger = require('../lib/logger').logger;
spyOn(logger, 'error').and.callFake(() => {});
let token = undefined;
Parse.Cloud.beforeConnect(({ sessionToken }) => {
token = sessionToken;
/* eslint-disable no-undef */
foo.bar();
/* eslint-enable no-undef */
});
new Parse.Query(TestObject).subscribe();
await new Promise(resolve => Parse.LiveQuery.on('error', resolve));
Parse.LiveQuery.removeAllListeners('error');
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 => {
await reconfigureServer({
liveQuery: {
Expand Down Expand Up @@ -594,6 +656,34 @@ describe('ParseLiveQuery', function () {
});
});

it('can log on beforeSubscribe error', async () => {
await reconfigureServer({
liveQuery: {
classNames: ['TestObject'],
},
startLiveQueryServer: true,
verbose: false,
silent: true,
});

const logger = require('../lib/logger').logger;
spyOn(logger, 'error').and.callFake(() => {});

Parse.Cloud.beforeSubscribe(TestObject, () => {
/* eslint-disable no-undef */
foo.bar();
/* eslint-enable no-undef */
});

const query = new Parse.Query(TestObject);
const subscription = await query.subscribe();
await new Promise(resolve => subscription.on('error', resolve));

expect(logger.error).toHaveBeenCalledWith(
`Failed running beforeSubscribe on TestObject for session undefined with:\n Error: {"message":"foo is not defined","code":141}`
);
});

it('can handle mutate beforeSubscribe query', async done => {
await reconfigureServer({
liveQuery: {
Expand Down
45 changes: 13 additions & 32 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, toJSONwithObjects } from '../triggers';
import { runLiveQueryEventHandlers, getTrigger, runTrigger, resolveError, toJSONwithObjects } from '../triggers';
import { getAuthForSessionToken, Auth } from '../Auth';
import { getCacheController } from '../Controllers';
import LRU from 'lru-cache';
Expand Down Expand Up @@ -194,14 +194,9 @@ class ParseLiveQueryServer {
delete deletedParseObject.authData;
}
client.pushDelete(requestId, deletedParseObject);
} catch (error) {
Client.pushError(
client.parseWebSocket,
error.code || Parse.Error.SCRIPT_FAILED,
error.message || error,
false,
requestId
);
} catch (e) {
const error = resolveError(e);
Client.pushError(client.parseWebSocket, error.code, error.message, false, requestId);
logger.error(
`Failed running afterLiveQueryEvent on class ${className} for event ${res.event} with session ${res.sessionToken} with:\n Error: ` +
JSON.stringify(error)
Expand Down Expand Up @@ -358,14 +353,9 @@ class ParseLiveQueryServer {
if (client[functionName]) {
client[functionName](requestId, currentParseObject, originalParseObject);
}
} catch (error) {
Client.pushError(
client.parseWebSocket,
error.code || Parse.Error.SCRIPT_FAILED,
error.message || error,
false,
requestId
);
} catch (e) {
const error = resolveError(e);
Client.pushError(client.parseWebSocket, error.code, error.message, false, requestId);
logger.error(
`Failed running afterLiveQueryEvent on class ${className} for event ${res.event} with session ${res.sessionToken} with:\n Error: ` +
JSON.stringify(error)
Expand Down Expand Up @@ -681,13 +671,9 @@ class ParseLiveQueryServer {
logger.info(`Create new client: ${parseWebsocket.clientId}`);
client.pushConnect();
runLiveQueryEventHandlers(req);
} catch (error) {
Client.pushError(
parseWebsocket,
error.code || Parse.Error.SCRIPT_FAILED,
error.message || error,
false
);
} catch (e) {
const error = resolveError(e);
Client.pushError(parseWebsocket, error.code, error.message, false);
logger.error(
`Failed running beforeConnect for session ${request.sessionToken} with:\n Error: ` +
JSON.stringify(error)
Expand Down Expand Up @@ -827,16 +813,11 @@ class ParseLiveQueryServer {
installationId: client.installationId,
});
} catch (e) {
Client.pushError(
parseWebsocket,
e.code || Parse.Error.SCRIPT_FAILED,
e.message || e,
false,
request.requestId
);
const error = resolveError(e);
Client.pushError(parseWebsocket, error.code, error.message, false, request.requestId);
logger.error(
`Failed running beforeSubscribe on ${className} for session ${request.sessionToken} with:\n Error: ` +
JSON.stringify(e)
JSON.stringify(error)
);
}
}
Expand Down
31 changes: 14 additions & 17 deletions src/triggers.js
Original file line number Diff line number Diff line change
Expand Up @@ -599,28 +599,25 @@ export function maybeRunQueryTrigger(
);
}

export function resolveError(message, defaultOpts) {
if (!defaultOpts) {
defaultOpts = {};
}
if (!message) {
return new Parse.Error(
defaultOpts.code || Parse.Error.SCRIPT_FAILED,
defaultOpts.message || 'Script failed.'
);
export function resolveError(e, defaultOpts = {}) {
const { code = Parse.Error.SCRIPT_FAILED, message = 'Script failed.' } = defaultOpts;
if (!e) {
return new Parse.Error(code, message);
}
if (message instanceof Parse.Error) {
return message;
if (e instanceof Parse.Error) {
return e;
}

const code = defaultOpts.code || Parse.Error.SCRIPT_FAILED;
// If it's an error, mark it as a script failed
if (typeof message === 'string') {
return new Parse.Error(code, message);
if (typeof e === 'string') {
return new Parse.Error(code, e);
}
const error = new Parse.Error(code, e.message || message);
if (e instanceof Error) {
error.stack = e.stack;
}
const error = new Parse.Error(code, message.message || message);
if (message instanceof Error) {
error.stack = message.stack;
if (Number.isInteger(e.code)) {
error.code = e.code;
}
return error;
}
Expand Down