Skip to content

Commit f502c45

Browse files
committed
Merge branch 'master' into add-deprecation-policy
2 parents 2d998fb + ba32dae commit f502c45

File tree

8 files changed

+135
-5
lines changed

8 files changed

+135
-5
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ jobs:
9191
MONGODB_VERSION: 4.4.4
9292
MONGODB_TOPOLOGY: standalone
9393
MONGODB_STORAGE_ENGINE: wiredTiger
94-
NODE_VERSION: 12.21.0
94+
NODE_VERSION: 12.22.0
9595
- name: Node 15
9696
MONGODB_VERSION: 4.4.4
9797
MONGODB_TOPOLOGY: standalone

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ ___
119119
- LDAP: Properly unbind client on group search error (Diamond Lewis) [#7265](https://github.com/parse-community/parse-server/pull/7265)
120120
- Improve data consistency in Push and Job Status update (Diamond Lewis) [#7267](https://github.com/parse-community/parse-server/pull/7267)
121121
- Excluding keys that have trailing edges.node when performing GraphQL resolver (Chris Bland) [#7273](https://github.com/parse-community/parse-server/pull/7273)
122-
- Adds Deprecation Policy to make the introduction of breaking changes more predictable. [#7199](https://github.com/parse-community/parse-server/pull/7199). Thanks to [Manuel Trezza](https://github.com/mtrezza).
122+
- Add Deprecation Policy to make the introduction of breaking changes more predictable. [#7199](https://github.com/parse-community/parse-server/pull/7199). Thanks to [Manuel Trezza](https://github.com/mtrezza).
123+
- Add centralized deprecation with standardized warning logs (Manuel Trezza) [#7303](https://github.com/parse-community/parse-server/pull/7303)
123124
___
124125
## 4.5.0
125126
[Full Changelog](https://github.com/parse-community/parse-server/compare/4.4.0...4.5.0)

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,9 @@ Parse Server is continuously tested with the most recent releases of Node.js to
113113
| Version | Latest Patch Version | End-of-Life Date | Compatibility |
114114
|------------|----------------------|------------------|--------------------|
115115
| Node.js 10 | 10.24.0 | April 2021 | ✅ Fully compatible |
116-
| Node.js 12 | 12.21.0 | April 2022 | ✅ Fully compatible |
116+
| Node.js 12 | 12.22.0 | April 2022 | ✅ Fully compatible |
117117
| Node.js 14 | 14.16.0 | April 2023 | ✅ Fully compatible |
118-
| Node.js 15 | 15.12.0 | June 2021 | ✅ Fully compatible |
118+
| Node.js 15 | 15.12.0 | June 2021 | ✅ Fully compatible |
119119

120120
#### MongoDB
121121
Parse Server is continuously tested with the most recent releases of MongoDB to ensure compatibility. We follow the [MongoDB support schedule](https://www.mongodb.com/support-policy) and only test against versions that are officially supported and have not reached their end-of-life date.

spec/Deprecator.spec.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use strict';
2+
3+
const Deprecator = require('../lib/Deprecator/Deprecator');
4+
5+
describe('Deprecator', () => {
6+
let deprecations = [];
7+
8+
beforeEach(async () => {
9+
deprecations = [{ optionKey: 'exampleKey', changeNewDefault: 'exampleNewDefault' }];
10+
});
11+
12+
it('deprecations are an array', async () => {
13+
expect(Deprecator._getDeprecations()).toBeInstanceOf(Array);
14+
});
15+
16+
it('logs deprecation for new default', async () => {
17+
deprecations = [{ optionKey: 'exampleKey', changeNewDefault: 'exampleNewDefault' }];
18+
19+
spyOn(Deprecator, '_getDeprecations').and.callFake(() => deprecations);
20+
const logger = require('../lib/logger').logger;
21+
const logSpy = spyOn(logger, 'warn').and.callFake(() => {});
22+
23+
await reconfigureServer();
24+
expect(logSpy.calls.all()[0].args[0]).toContain(deprecations[0].optionKey);
25+
expect(logSpy.calls.all()[0].args[0]).toContain(deprecations[0].changeNewDefault);
26+
});
27+
28+
it('does not log deprecation for new default if option is set manually', async () => {
29+
deprecations = [{ optionKey: 'exampleKey', changeNewDefault: 'exampleNewDefault' }];
30+
31+
spyOn(Deprecator, '_getDeprecations').and.callFake(() => deprecations);
32+
const logSpy = spyOn(Deprecator, '_log').and.callFake(() => {});
33+
await reconfigureServer({ [deprecations[0].optionKey]: 'manuallySet' });
34+
expect(logSpy).not.toHaveBeenCalled();
35+
});
36+
});

src/Deprecator/Deprecations.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* The deprecations.
3+
*
4+
* Add deprecations to the array using the following keys:
5+
* - `optionKey`: The option key incl. its path, e.g. `security.enableCheck`.
6+
* - `envKey`: The environment key, e.g. `PARSE_SERVER_SECURITY`.
7+
* - `changeNewKey`: Set the new key name if the current key will be replaced,
8+
* or set to an empty string if the current key will be removed without replacement.
9+
* - `changeNewDefault`: Set the new default value if the key's default value
10+
* will change in a future version.
11+
*
12+
* If there are no deprecations this must return an empty array anyway.
13+
*/
14+
module.exports = [];

src/Deprecator/Deprecator.js

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import logger from '../logger';
2+
import Deprecations from './Deprecations';
3+
4+
/**
5+
* The deprecator class.
6+
*/
7+
class Deprecator {
8+
/**
9+
* Scans the Parse Server for deprecated options.
10+
* This needs to be called before setting option defaults, otherwise it
11+
* becomes indistinguishable whether an option has been set manually or
12+
* by default.
13+
* @param {any} options The Parse Server options.
14+
*/
15+
static scanParseServerOptions(options) {
16+
// Scan for deprecations
17+
for (const deprecation of Deprecator._getDeprecations()) {
18+
// Get deprecation properties
19+
const optionKey = deprecation.optionKey;
20+
const changeNewDefault = deprecation.changeNewDefault;
21+
22+
// If default will change, only throw a warning if option is not set
23+
if (changeNewDefault != null && options[optionKey] == null) {
24+
Deprecator._log({ optionKey, changeNewDefault });
25+
}
26+
}
27+
}
28+
29+
/**
30+
* Returns the deprecation definitions.
31+
* @returns {Array<Object>} The deprecations.
32+
*/
33+
static _getDeprecations() {
34+
return Deprecations;
35+
}
36+
37+
/**
38+
* Logs a deprecation warning for a Parse Server option.
39+
* @param {String} optionKey The option key incl. its path, e.g. `security.enableCheck`.
40+
* @param {String} envKey The environment key, e.g. `PARSE_SERVER_SECURITY`.
41+
* @param {String} changeNewKey Set the new key name if the current key will be replaced,
42+
* or set to an empty string if the current key will be removed without replacement.
43+
* @param {String} changeNewDefault Set the new default value if the key's default value
44+
* will change in a future version.
45+
* @param {String} [solution] The instruction to resolve this deprecation warning. This
46+
* message must not include the warning that the parameter is deprecated, that is
47+
* automatically added to the message. It should only contain the instruction on how
48+
* to resolve this warning.
49+
*/
50+
static _log({ optionKey, envKey, changeNewKey, changeNewDefault, solution }) {
51+
const type = optionKey ? 'option' : 'environment key';
52+
const key = optionKey ? optionKey : envKey;
53+
const keyAction =
54+
changeNewKey == null
55+
? undefined
56+
: changeNewKey.length > 0
57+
? `renamed to '${changeNewKey}'`
58+
: `removed`;
59+
60+
// Compose message
61+
let output = `DeprecationWarning: The Parse Server ${type} '${key}' `;
62+
output += changeNewKey ? `is deprecated and will be ${keyAction} in a future version.` : '';
63+
output += changeNewDefault
64+
? `default will change to '${changeNewDefault}' in a future version.`
65+
: '';
66+
output += solution ? ` ${solution}` : '';
67+
logger.warn(output);
68+
}
69+
}
70+
71+
module.exports = Deprecator;

src/ParseServer.js

+4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import * as controllers from './Controllers';
4343
import { ParseGraphQLServer } from './GraphQL/ParseGraphQLServer';
4444
import { SecurityRouter } from './Routers/SecurityRouter';
4545
import CheckRunner from './Security/CheckRunner';
46+
import Deprecator from './Deprecator/Deprecator';
4647

4748
// Mutate the Parse object to add the Cloud Code handlers
4849
addParseCloud();
@@ -55,6 +56,9 @@ class ParseServer {
5556
* @param {ParseServerOptions} options the parse server initialization options
5657
*/
5758
constructor(options: ParseServerOptions) {
59+
// Scan for deprecated Parse Server options
60+
Deprecator.scanParseServerOptions(options);
61+
// Set option defaults
5862
injectDefaults(options);
5963
const {
6064
appId = requiredParameter('You must provide an appId!'),

src/cli/utils/commander.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/* eslint-disable no-console */
22
import { Command } from 'commander';
33
import path from 'path';
4+
import Deprecator from '../../Deprecator/Deprecator';
5+
46
let _definitions;
57
let _reverseDefinitions;
68
let _defaults;
@@ -40,7 +42,7 @@ Command.prototype.loadDefinitions = function (definitions) {
4042
}, {});
4143

4244
_defaults = Object.keys(definitions).reduce((defs, opt) => {
43-
if (_definitions[opt].default) {
45+
if (_definitions[opt].default !== undefined) {
4446
defs[opt] = _definitions[opt].default;
4547
}
4648
return defs;
@@ -119,6 +121,8 @@ Command.prototype.parse = function (args, env) {
119121
this.setValuesIfNeeded(envOptions);
120122
// Load from file to override
121123
this.setValuesIfNeeded(fromFile);
124+
// Scan for deprecated Parse Server options
125+
Deprecator.scanParseServerOptions(this);
122126
// Last set the defaults
123127
this.setValuesIfNeeded(_defaults);
124128
};

0 commit comments

Comments
 (0)