Skip to content

feat: Deprecate LiveQuery fields option in favor of keys for semantic consistency #8388

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Feb 17, 2023
1 change: 1 addition & 0 deletions DEPRECATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ The following is a list of deprecations, according to the [Deprecation Policy](h
| DEPPS6 | Auth providers disabled by default | [#7953](https://github.com/parse-community/parse-server/pull/7953) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - |
| DEPPS7 | Remove file trigger syntax `Parse.Cloud.beforeSaveFile((request) => {})` | [#7966](https://github.com/parse-community/parse-server/pull/7966) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - |
| DEPPS8 | Login with expired 3rd party authentication token defaults to `false` | [#7079](https://github.com/parse-community/parse-server/pull/7079) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - |
| DEPPS9 | Rename LiveQuery `fields` option to `keys` | [#8389](https://github.com/parse-community/parse-server/issues/8389) | 6.0.0 (2023) | 7.0.0 (2024) | deprecated | - |

[i_deprecation]: ## "The version and date of the deprecation."
[i_removal]: ## "The version and date of the planned removal."
Expand Down
68 changes: 62 additions & 6 deletions spec/ParseLiveQueryServer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ describe('ParseLiveQueryServer', function () {
where: {
key: 'value',
},
fields: ['test'],
keys: ['test'],
};
const requestId = 2;
const request = {
Expand Down Expand Up @@ -331,7 +331,7 @@ describe('ParseLiveQueryServer', function () {
where: {
key: 'value',
},
fields: ['test'],
keys: ['test'],
};
const requestId = 2;
const request = {
Expand Down Expand Up @@ -378,7 +378,7 @@ describe('ParseLiveQueryServer', function () {
where: {
key: 'value',
},
fields: ['test'],
keys: ['test'],
};
await addMockSubscription(parseLiveQueryServer, clientId, requestId, parseWebSocket, query);
// Add subscription for mock client 2
Expand All @@ -390,7 +390,7 @@ describe('ParseLiveQueryServer', function () {
where: {
key: 'value',
},
fields: ['testAgain'],
keys: ['testAgain'],
};
const requestIdAgain = 1;
await addMockSubscription(
Expand Down Expand Up @@ -1060,7 +1060,7 @@ describe('ParseLiveQueryServer', function () {
where: {
key: 'value',
},
fields: ['test'],
keys: ['test'],
};
await addMockSubscription(parseLiveQueryServer, clientId, requestId, parseWebSocket, query);
// Mock _matchesSubscription to return matching
Expand All @@ -1087,6 +1087,62 @@ describe('ParseLiveQueryServer', function () {
done();
});

it('can deprecate fields', async () => {
const Deprecator = require('../lib/Deprecator/Deprecator');
const spy = spyOn(Deprecator, 'logRuntimeDeprecation').and.callFake(() => {});
jasmine.restoreLibrary('../lib/LiveQuery/Client', 'Client');
const Client = require('../lib/LiveQuery/Client').Client;
const parseLiveQueryServer = new ParseLiveQueryServer({});
// Make mock request message
const message = generateMockMessage();

const clientId = 1;
const parseWebSocket = {
clientId,
send: jasmine.createSpy('send'),
};
const client = new Client(clientId, parseWebSocket);
spyOn(client, 'pushCreate').and.callThrough();
parseLiveQueryServer.clients.set(clientId, client);

// Add mock subscription
const requestId = 2;
const query = {
className: testClassName,
where: {
key: 'value',
},
fields: ['test'],
};
await addMockSubscription(parseLiveQueryServer, clientId, requestId, parseWebSocket, query);
// Mock _matchesSubscription to return matching
parseLiveQueryServer._matchesSubscription = function (parseObject) {
if (!parseObject) {
return false;
}
return true;
};
parseLiveQueryServer._matchesACL = function () {
return Promise.resolve(true);
};

parseLiveQueryServer._onAfterSave(message);

// Make sure we send create command to client
await timeout();

expect(client.pushCreate).toHaveBeenCalled();
const args = parseWebSocket.send.calls.mostRecent().args;
const toSend = JSON.parse(args[0]);
expect(toSend.object).toBeDefined();
expect(toSend.original).toBeUndefined();
expect(spy).toHaveBeenCalledWith({
usage: 'Subscribing using fields parameter',
solution:
`Subscribe using "keys" instead.`,
});
});

it('can handle create command with watch', async () => {
jasmine.restoreLibrary('../lib/LiveQuery/Client', 'Client');
const Client = require('../lib/LiveQuery/Client').Client;
Expand Down Expand Up @@ -1865,7 +1921,7 @@ describe('ParseLiveQueryServer', function () {
where: {
key: 'value',
},
fields: ['test'],
keys: ['test'],
};
}
const request = {
Expand Down
8 changes: 4 additions & 4 deletions src/LiveQuery/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,13 @@ class Client {
response['requestId'] = subscriptionId;
}
if (typeof parseObjectJSON !== 'undefined') {
let fields;
let keys;
if (this.subscriptionInfos.has(subscriptionId)) {
fields = this.subscriptionInfos.get(subscriptionId).fields;
keys = this.subscriptionInfos.get(subscriptionId).keys;
}
response['object'] = this._toJSONWithFields(parseObjectJSON, fields);
response['object'] = this._toJSONWithFields(parseObjectJSON, keys);
if (parseOriginalObjectJSON) {
response['original'] = this._toJSONWithFields(parseOriginalObjectJSON, fields);
response['original'] = this._toJSONWithFields(parseOriginalObjectJSON, keys);
}
}
Client.pushResponse(this.parseWebSocket, JSON.stringify(response));
Expand Down
15 changes: 11 additions & 4 deletions src/LiveQuery/ParseLiveQueryServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import LRU from 'lru-cache';
import UserRouter from '../Routers/UsersRouter';
import DatabaseController from '../Controllers/DatabaseController';
import { isDeepStrictEqual } from 'util';
import Deprecator from '../Deprecator/Deprecator';

class ParseLiveQueryServer {
clients: Map;
Expand Down Expand Up @@ -850,9 +851,6 @@ class ParseLiveQueryServer {
await runTrigger(trigger, `beforeSubscribe.${className}`, request, auth);

const query = request.query.toJSON();
if (query.keys) {
query.fields = query.keys.split(',');
}
request.query = query;
}

Expand Down Expand Up @@ -901,8 +899,17 @@ class ParseLiveQueryServer {
subscription: subscription,
};
// Add selected fields, sessionToken and installationId for this subscription if necessary
if (request.query.keys) {
subscriptionInfo.keys = Array.isArray(request.query.keys)
? request.query.keys
: request.query.keys.split(',');
}
if (request.query.fields) {
subscriptionInfo.fields = request.query.fields;
subscriptionInfo.keys = request.query.fields;
Deprecator.logRuntimeDeprecation({
usage: `Subscribing using fields parameter`,
solution: `Subscribe using "keys" instead.`,
});
}
if (request.query.watch) {
subscriptionInfo.watch = request.query.watch;
Expand Down
32 changes: 32 additions & 0 deletions src/LiveQuery/RequestSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,22 @@ const subscribe = {
minItems: 1,
uniqueItems: true,
},
keys: {
type: 'array',
items: {
type: 'string',
},
minItems: 1,
uniqueItems: true,
},
watch: {
type: 'array',
items: {
type: 'string',
},
minItems: 1,
uniqueItems: true,
},
},
required: ['where', 'className'],
additionalProperties: false,
Expand Down Expand Up @@ -108,6 +124,22 @@ const update = {
minItems: 1,
uniqueItems: true,
},
keys: {
type: 'array',
items: {
type: 'string',
},
minItems: 1,
uniqueItems: true,
},
watch: {
type: 'array',
items: {
type: 'string',
},
minItems: 1,
uniqueItems: true,
},
},
required: ['where', 'className'],
additionalProperties: false,
Expand Down