Skip to content

Commit

Permalink
add runtime deprecation warning (#7451)
Browse files Browse the repository at this point in the history
  • Loading branch information
mtrezza authored Jul 12, 2021
1 parent 05882bc commit 1594afe
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 7 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ ___
- Fix incorrect LiveQuery events triggered for multiple subscriptions on the same class with different events [#7341](https://github.com/parse-community/parse-server/pull/7341)
- Fix select and excludeKey queries to properly accept JSON string arrays. Also allow nested fields in exclude (Corey Baker) [#7242](https://github.com/parse-community/parse-server/pull/7242)
- Fix LiveQuery server crash when using $all query operator on a missing object key (Jason Posthuma) [#7421](https://github.com/parse-community/parse-server/pull/7421)

- Added runtime deprecation warnings (Manuel Trezza) [#7451](https://github.com/parse-community/parse-server/pull/7451)
___
## 4.5.0
[Full Changelog](https://github.com/parse-community/parse-server/compare/4.4.0...4.5.0)
Expand Down
4 changes: 3 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,9 @@ If you change or remove an existing feature that would lead to a breaking change
- Use a default value that falls back to existing behavior.
- Add a deprecation definition in `Deprecator/Deprecations.js` that will output a deprecation warning log message on Parse Server launch, for example:
> DeprecationWarning: The Parse Server option 'example' will be removed in a future release.
For deprecations that can only be determined ad-hoc during runtime, for example Parse Query syntax deprecations, use the `Deprecator.logRuntimeDeprecation()` method.

Deprecations become breaking changes after notifying developers through deprecation warnings for at least one entire previous major release. For example:
- `4.5.0` is the current version
- `4.6.0` adds a new optional feature and a deprecation warning for the existing feature
Expand Down
18 changes: 15 additions & 3 deletions spec/Deprecator.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,28 @@ describe('Deprecator', () => {
const logSpy = spyOn(logger, 'warn').and.callFake(() => {});

await reconfigureServer();
expect(logSpy.calls.all()[0].args[0]).toContain(deprecations[0].optionKey);
expect(logSpy.calls.all()[0].args[0]).toContain(deprecations[0].changeNewDefault);
expect(logSpy.calls.all()[0].args[0]).toEqual(
`DeprecationWarning: The Parse Server option '${deprecations[0].optionKey}' default will change to '${deprecations[0].changeNewDefault}' in a future version.`
);
});

it('does not log deprecation for new default if option is set manually', async () => {
deprecations = [{ optionKey: 'exampleKey', changeNewDefault: 'exampleNewDefault' }];

spyOn(Deprecator, '_getDeprecations').and.callFake(() => deprecations);
const logSpy = spyOn(Deprecator, '_log').and.callFake(() => {});
const logSpy = spyOn(Deprecator, '_logOption').and.callFake(() => {});
await reconfigureServer({ [deprecations[0].optionKey]: 'manuallySet' });
expect(logSpy).not.toHaveBeenCalled();
});

it('logs runtime deprecation', async () => {
const logger = require('../lib/logger').logger;
const logSpy = spyOn(logger, 'warn').and.callFake(() => {});
const options = { usage: 'Doing this', solution: 'Do that instead.' };

Deprecator.logRuntimeDeprecation(options);
expect(logSpy.calls.all()[0].args[0]).toEqual(
`DeprecationWarning: ${options.usage} is deprecated and will be removed in a future version. ${options.solution}`
);
});
});
50 changes: 48 additions & 2 deletions src/Deprecator/Deprecator.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,41 @@ class Deprecator {

// If default will change, only throw a warning if option is not set
if (changeNewDefault != null && options[optionKey] == null) {
Deprecator._log({ optionKey, changeNewDefault, solution });
Deprecator._logOption({ optionKey, changeNewDefault, solution });
}
}
}

/**
* Logs a deprecation warning for a parameter that can only be determined dynamically
* during runtime.
*
* Note: Do not use this to log deprecations of Parse Server options, but add such
* deprecations to `Deprecations.js` instead. See the contribution docs for more
* details.
*
* For consistency, the deprecation warning is composed of the following parts:
*
* > DeprecationWarning: `usage` is deprecated and will be removed in a future version.
* `solution`.
*
* - `usage`: The deprecated usage.
* - `solution`: The instruction to resolve this deprecation warning.
*
* For example:
* > DeprecationWarning: `Prefixing field names with dollar sign ($) in aggregation query`
* is deprecated and will be removed in a future version. `Reference field names without
* dollar sign prefix.`
*
* @param {Object} options The deprecation options.
* @param {String} options.usage The usage that is deprecated.
* @param {String} [options.solution] The instruction to resolve this deprecation warning.
* Optional. It is recommended to add an instruction for the convenience of the developer.
*/
static logRuntimeDeprecation(options) {
Deprecator._logGeneric(options);
}

/**
* Returns the deprecation definitions.
* @returns {Array<Object>} The deprecations.
Expand All @@ -35,8 +65,24 @@ class Deprecator {
return Deprecations;
}

/**
* Logs a generic deprecation warning.
*
* @param {Object} options The deprecation options.
* @param {String} options.usage The usage that is deprecated.
* @param {String} [options.solution] The instruction to resolve this deprecation warning.
* Optional. It is recommended to add an instruction for the convenience of the developer.
*/
static _logGeneric({ usage, solution }) {
// Compose message
let output = `DeprecationWarning: ${usage} is deprecated and will be removed in a future version.`;
output += solution ? ` ${solution}` : '';
logger.warn(output);
}

/**
* Logs a deprecation warning for a Parse Server option.
*
* @param {String} optionKey The option key incl. its path, e.g. `security.enableCheck`.
* @param {String} envKey The environment key, e.g. `PARSE_SERVER_SECURITY`.
* @param {String} changeNewKey Set the new key name if the current key will be replaced,
Expand All @@ -48,7 +94,7 @@ class Deprecator {
* automatically added to the message. It should only contain the instruction on how
* to resolve this warning.
*/
static _log({ optionKey, envKey, changeNewKey, changeNewDefault, solution }) {
static _logOption({ optionKey, envKey, changeNewKey, changeNewDefault, solution }) {
const type = optionKey ? 'option' : 'environment key';
const key = optionKey ? optionKey : envKey;
const keyAction =
Expand Down

0 comments on commit 1594afe

Please sign in to comment.