Skip to content

Commit dd67027

Browse files
authored
Merge pull request #42 from ImmoweltGroup/feature/33/addUpdatePrompt
FEATURE: Integrate a update prompt if the globally installed CLI is outdated
2 parents 37a6501 + d99a53d commit dd67027

File tree

9 files changed

+105
-17
lines changed

9 files changed

+105
-17
lines changed

packages/create-react-microservice/.bin/create-react-microservice

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,30 @@ var path = require('path');
66
var pkg = require(path.join(__dirname, './../package.json'));
77

88
require('check-engines')(pkg, function (err) {
9+
var ora = require('ora');
10+
911
if (err) {
10-
console.log(err);
11-
require('ora')().fail(`System binaries do not meet constraints: ${JSON.stringify(pkg.engines)}.`);
12-
process.exit(1);
12+
ora().fail(err.message);
13+
ora().fail('System binaries do not meet constraints: ' + JSON.stringify(pkg.engines));
1314

14-
return;
15+
return process.exit(1);
1516
}
1617

17-
const meow = require('meow');
18-
const ora = require('ora');
19-
const cli = meow({pkg, autoHelp: false});
20-
const commandsByName = {
18+
var cli = require('meow')({pkg, autoHelp: false});
19+
var commandsByName = {
2120
default: require('./../dist/commands/default.js')
2221
};
23-
const commandName = cli.input.join(' ');
24-
const Command = commandsByName[commandName] || commandsByName.default;
25-
const instance = new Command({
22+
var commandName = cli.input.join(' ');
23+
var Command = commandsByName[commandName] || commandsByName.default;
24+
var instance = new Command({
2625
pkg,
2726
input: cli.input,
2827
flags: cli.flags
2928
});
3029

31-
instance.exec().catch(e => {
30+
instance.exec().catch(function (e) {
31+
ora().fail(e.message);
3232
console.error(e);
33-
3433
process.exit(1);
3534
});
3635
});

packages/create-react-microservice/package.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"private": false,
55
"author": "Immonet dev team <[email protected]> (https://immonet.de)",
66
"license": "MIT",
7-
"description": "Create highly scalable and universal React microservices/applications within seconds.",
7+
"description":
8+
"Create highly scalable and universal React microservices/applications within seconds.",
89
"bin": {
910
"create-react-microservice": "./.bin/create-react-microservice"
1011
},
@@ -19,14 +20,16 @@
1920
"jest:watch": "yarn run jest -- --watch",
2021
"jest:coverage": "yarn run jest -- --coverage",
2122
"build:clean": "rimraf dist",
22-
"build:babel": "NODE_ENV=production babel src --out-dir dist --ignore spec.js",
23+
"build:babel":
24+
"NODE_ENV=production babel src --out-dir dist --ignore spec.js",
2325
"build:flow": "flow-copy-source -v src dist --ignore='*.spec.js'",
2426
"build:watch": "yarn run build:babel -- -w",
2527
"prebuild": "yarn run build:clean",
2628
"build": "yarn run build:babel && yarn run build:flow",
2729
"flow": "flow",
2830
"flow-typed": "flow-typed",
29-
"flow-typed-install": "flow-typed install --ignoreDeps=bundled peer --overwrite"
31+
"flow-typed-install":
32+
"flow-typed install --ignoreDeps=bundled peer --overwrite"
3033
},
3134
"devDependencies": {
3235
"@immowelt/babel-preset-immowelt-node": "1.1.0",
@@ -50,6 +53,7 @@
5053
"create-react-microservice-scaffold": "0.0.0-development",
5154
"execa": "0.8.0",
5255
"find-node-modules": "1.0.4",
56+
"latest-version": "^3.1.0",
5357
"meow": "4.0.0",
5458
"node-emoji": "1.8.1",
5559
"ora": "1.3.0",

packages/create-react-microservice/src/commands/default.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class CreateReactMicroService extends Command {
2525
return this.printHelp();
2626
}
2727

28+
await this.validateInstallation();
29+
2830
const name = await this.resolveAppName();
2931
const src = await this.resolveScaffold();
3032
const dist = await this.resolveDistFolder();

packages/create-react-microservice/src/commands/default.spec.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ describe('DefaultCommand', () => {
2121

2222
describe('new Command().exec()', () => {
2323
let instance;
24+
let validateInstallation;
2425
let processTemplateAndCreate;
2526
let resolveAndPromptTemplateArgs;
2627
let resolveDistFolder;
@@ -32,6 +33,9 @@ describe('new Command().exec()', () => {
3233

3334
beforeEach(() => {
3435
instance = new DefaultCommand({input: [], flags: {}, pkg: {}});
36+
validateInstallation = jest
37+
.spyOn(instance, 'validateInstallation')
38+
.mockImplementation(jest.fn());
3539
processTemplateAndCreate = jest
3640
.spyOn(create, 'processTemplateAndCreate')
3741
.mockImplementation(jest.fn());
@@ -86,6 +90,7 @@ describe('new Command().exec()', () => {
8690
it('should resolve the dist folder, the app name and template args', async () => {
8791
await instance.exec();
8892

93+
expect(validateInstallation).toHaveBeenCalledTimes(1);
8994
expect(resolveAppName).toHaveBeenCalledTimes(1);
9095
expect(resolveDistFolder).toHaveBeenCalledTimes(1);
9196
expect(resolveAndPromptTemplateArgs).toHaveBeenCalledTimes(1);

packages/create-react-microservice/src/lib/command.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const exec = require('execa');
44
const chalk = require('chalk');
55
const ora = require('ora');
6+
const npm = require('./npm.js');
67

78
class Command {
89
static exec = exec;
@@ -22,6 +23,20 @@ class Command {
2223
this.flags = args.flags;
2324
}
2425

26+
/**
27+
* Validates the global CLI installation so we can be sure that the newest version is always installed.
28+
*
29+
* @return {Promise} The Promise that resolves if everything is installed properly / rejects if something is wrong.
30+
*/
31+
async validateInstallation() {
32+
const {name, version} = this.pkg;
33+
const latestPublishedVersion = await npm.latestVersion(name);
34+
35+
if (latestPublishedVersion !== version && version !== '0.0.0-development') {
36+
throw new Error(`Oudated version of "${name}" found. Please update your global installation by executing "yarn global upgrade ${name}@${latestPublishedVersion}".`);
37+
}
38+
}
39+
2540
/**
2641
* Logs a message to the users console.
2742
*

packages/create-react-microservice/src/lib/command.spec.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// @flow
22

3+
jest.mock('./npm.js');
4+
5+
const npm: any = require('./npm.js');
36
const Command = require('./command.js');
47

58
describe('Command()', () => {
@@ -8,6 +11,46 @@ describe('Command()', () => {
811
});
912
});
1013

14+
describe('new Command().validateInstallation()', () => {
15+
let instance;
16+
17+
beforeEach(() => {
18+
instance = new Command({input: [], flags: {}, pkg: {name: 'foo-name', version: '1.0.0'}});
19+
});
20+
21+
afterEach(() => {
22+
// $FlowFixMe: Ignore errors since the jest type-def is out of date.
23+
jest.restoreAllMocks();
24+
jest.clearAllMocks();
25+
});
26+
27+
it('should be a function', () => {
28+
expect(typeof instance.validateInstallation).toBe('function');
29+
});
30+
31+
it('should query the latest published version and should not throw an erorr if it matches the initialized version number in the package.json.', async () => {
32+
npm.latestVersion.mockReturnValue('1.0.0');
33+
34+
await instance.validateInstallation();
35+
36+
expect(npm.latestVersion).toHaveBeenCalledWith('foo-name');
37+
});
38+
39+
it('should not throw an erorr if the initialized version number in the package.json matches "0.0.0-development".', async () => {
40+
instance.pkg.version = '0.0.0-development';
41+
42+
npm.latestVersion.mockReturnValue('1.2.0');
43+
44+
await expect(instance.validateInstallation()).resolves;
45+
});
46+
47+
it('should throw an erorr if the queried version does not match the initialized version number in the package.json.', async () => {
48+
npm.latestVersion.mockReturnValue('1.2.0');
49+
50+
await expect(instance.validateInstallation()).rejects;
51+
});
52+
});
53+
1154
describe('new Command().log()', () => {
1255
let instance;
1356
let createLogMsg;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const latestVersion = require('latest-version');
2+
3+
module.exports = {
4+
latestVersion
5+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// @flow
2+
3+
const npm = require('./npm.js');
4+
5+
describe('npm.latestVersion()', () => {
6+
it('should be a function', () => {
7+
expect(typeof npm.latestVersion).toBe('function');
8+
});
9+
});

yarn.lock

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3581,6 +3581,12 @@ kind-of@^6.0.0:
35813581
version "6.0.1"
35823582
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.1.tgz#4948e6263553ac3712fc44d305b77851d9e40ea4"
35833583

3584+
latest-version@^3.1.0:
3585+
version "3.1.0"
3586+
resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15"
3587+
dependencies:
3588+
package-json "^4.0.0"
3589+
35843590
lazy-cache@^1.0.3:
35853591
version "1.0.4"
35863592
resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
@@ -4508,7 +4514,7 @@ p-timeout@^1.1.1:
45084514
dependencies:
45094515
p-finally "^1.0.0"
45104516

4511-
package-json@^4.0.1:
4517+
package-json@^4.0.0, package-json@^4.0.1:
45124518
version "4.0.1"
45134519
resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed"
45144520
dependencies:

0 commit comments

Comments
 (0)