Skip to content
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

add runtime deprecation warning #7451

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
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