Skip to content

Commit 6f082ef

Browse files
committed
feature #150 Add a 'Did you mean ...' error message in case of an unrecognized API property (Lyrkan)
This PR was squashed before being merged into the master branch (closes #150). Discussion ---------- Add a 'Did you mean ...' error message in case of an unrecognized API property This PR aims to improve the error message displayed when an user makes a typo in the name of one of the API methods he's trying to use. Since pictures speak louder than words: **Before** ![2017-08-30_19-01-27](https://user-images.githubusercontent.com/850046/29885253-724d45a0-8db6-11e7-8ec5-9e63fa9d786e.png) **After** ![2017-08-30_19-03-44](https://user-images.githubusercontent.com/850046/29885266-7a0f3d0c-8db6-11e7-9af8-d9aad52917c2.png) Note that the error is triggered when trying to access the property, not when the method is called (since it doesn't exist), hence the "is not a recognized property" message. I'm aware that the use of the "property" word in it may not be ideal, but using "method" instead feels wrong too since we could theoretically have other things than methods in the API object. Commits ------- a16e1af Only add the "Did you mean" message if the levenshtein distance is less than 3 1ceabc1 Add "or method" to the "Did you mean ..." error message d592481 Add a 'Did you mean ...' error message for unrecognized API methods
2 parents 2a65613 + a16e1af commit 6f082ef

File tree

3 files changed

+26
-1
lines changed

3 files changed

+26
-1
lines changed

index.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ const validator = require('./lib/config/validator');
1515
const PrettyError = require('pretty-error');
1616
const logger = require('./lib/logger');
1717
const parseRuntime = require('./lib/config/parse-runtime');
18+
const chalk = require('chalk');
19+
const levenshtein = require('fast-levenshtein');
1820

1921
let webpackConfig = null;
2022
let runtimeConfig = require('./lib/context').runtimeConfig;
@@ -777,6 +779,28 @@ const publicApiProxy = new Proxy(publicApi, {
777779
};
778780
}
779781

782+
if (typeof target[prop] === 'undefined') {
783+
// Find the property with the closest Levenshtein distance
784+
let similarProperty;
785+
let minDistance = Number.MAX_VALUE;
786+
for (const apiProperty in target) {
787+
const distance = levenshtein.get(apiProperty, prop);
788+
if (distance <= minDistance) {
789+
similarProperty = apiProperty;
790+
minDistance = distance;
791+
}
792+
}
793+
794+
let errorMessage = `${chalk.red(`Encore.${prop}`)} is not a recognized property or method.`;
795+
if (minDistance < 3) {
796+
errorMessage += ` Did you mean ${chalk.green(`Encore.${similarProperty}`)}?`;
797+
}
798+
799+
const error = new Error(errorMessage);
800+
console.log(new PrettyError().render(error));
801+
process.exit(1); // eslint-disable-line
802+
}
803+
780804
return target[prop];
781805
}
782806
});

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"clean-webpack-plugin": "^0.1.16",
3434
"css-loader": "^0.26.2",
3535
"extract-text-webpack-plugin": "^3.0.0",
36+
"fast-levenshtein": "^2.0.6",
3637
"file-loader": "^0.10.1",
3738
"friendly-errors-webpack-plugin": "^1.6.1",
3839
"fs-extra": "^2.0.0",

yarn.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2162,7 +2162,7 @@ fast-deep-equal@^1.0.0:
21622162
version "1.0.0"
21632163
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff"
21642164

2165-
fast-levenshtein@~2.0.4:
2165+
fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.4:
21662166
version "2.0.6"
21672167
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
21682168

0 commit comments

Comments
 (0)