Skip to content

Commit 707f692

Browse files
Raymond Fengraymondfeng
authored andcommitted
feat: Add experimental CLI for LoopBack 4
Usage: npm i -g @loopback/cli lb4 app <name> lb4 extension <name>
1 parent a351932 commit 707f692

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1607
-1
lines changed

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
packages/*/dist
22
packages/*/dist6
33
packages/*/api-docs
4+
packages/cli/generators/*/templates
45
package.json
56
packages/*/package.json

packages/cli/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
coverage

packages/cli/.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package-lock=false

packages/cli/.prettierrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"bracketSpacing": false,
3+
"singleQuote": true,
4+
"printWidth": 80,
5+
"trailingComma": "es5"
6+
}

packages/cli/.yo-rc.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{
2+
}

packages/cli/README.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# @loopback/cli
2+
3+
This module contains the experimental CLI for LoopBack 4.
4+
5+
## Installation
6+
7+
Run the following command to install the CLI.
8+
9+
`npm install -g @loopback/cli`
10+
11+
## Usage
12+
13+
1. To scaffold a LoopBack 4 application
14+
15+
`lb4 app`
16+
17+
```
18+
Usage:
19+
lb4 app [options] [<name>]
20+
21+
Options:
22+
-h, --help # Print the generator's options and usage
23+
--skip-cache # Do not remember prompt answers Default: false
24+
--skip-install # Do not automatically install dependencies Default: false
25+
--applicationName # Application name
26+
--description # Description for the application
27+
--outdir # Project root directory for the application
28+
--tslint # Enable tslint
29+
--prettier # Enable prettier
30+
--mocha # Enable mocha
31+
--loopbackBuild # Use @loopback/build
32+
33+
Arguments:
34+
name # Project name for the application Type: String Required: false
35+
```
36+
37+
2. To scaffold a LoopBack 4 extension
38+
39+
`lb4 extension`
40+
41+
```
42+
Usage:
43+
lb4 extension [options] [<name>]
44+
45+
Options:
46+
-h, --help # Print the generator's options and usage
47+
--skip-cache # Do not remember prompt answers Default: false
48+
--skip-install # Do not automatically install dependencies Default: false
49+
--description # Description for the extension
50+
--outdir # Project root directory for the extension
51+
--tslint # Enable tslint
52+
--prettier # Enable prettier
53+
--mocha # Enable mocha
54+
--loopbackBuild # Use @loopback/build
55+
--componentName # Component name
56+
57+
```

packages/cli/bin/cli.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/usr/bin/env node
2+
// Copyright IBM Corp. 2017. All Rights Reserved.
3+
// Node module: @loopback/cli
4+
// This file is licensed under the MIT License.
5+
// License text available at https://opensource.org/licenses/MIT
6+
7+
'use strict';
8+
9+
const assert = require('assert');
10+
const camelCaseKeys = require('camelcase-keys');
11+
const debug = require('debug')('loopback:cli');
12+
const minimist = require('minimist');
13+
const path = require('path');
14+
const yeoman = require('yeoman-environment');
15+
16+
const opts = minimist(process.argv.slice(2), {
17+
alias: {
18+
help: 'h',
19+
version: 'v',
20+
commands: 'l',
21+
},
22+
});
23+
24+
if (opts.version) {
25+
const ver = require('../package.json').version;
26+
console.log('Version: %s', ver);
27+
return;
28+
}
29+
30+
var env = yeoman.createEnv();
31+
32+
env.register(path.join(__dirname, '../generators/app'), 'loopback4:app');
33+
env.register(path.join(__dirname, '../generators/extension'), 'loopback4:extension');
34+
35+
// list generators
36+
if (opts.commands) {
37+
console.log('Available commands: ');
38+
var list = Object.keys(env.getGeneratorsMeta())
39+
.filter(name => /^loopback4:/.test(name))
40+
.map(name => name.replace(/^loopback4:/, ' lb4 '));
41+
console.log(list.join('\n'));
42+
return;
43+
}
44+
45+
const args = opts._;
46+
const originalCommand = args.shift();
47+
let command = 'loopback4:' + (originalCommand || 'app');
48+
const supportedCommands = env.getGeneratorsMeta();
49+
50+
if (!(command in supportedCommands)) {
51+
command = 'loopback4:app';
52+
args.unshift(originalCommand);
53+
args.unshift(command);
54+
} else {
55+
args.unshift(command);
56+
}
57+
58+
debug('invoking generator', args);
59+
60+
// `yo` is adding flags converted to CamelCase
61+
const options = camelCaseKeys(opts, {exclude: ['--', /^\w$/, 'argv']});
62+
Object.assign(options, opts);
63+
64+
debug('env.run %j %j', args, options);
65+
env.run(args, options);

packages/cli/generators/app/index.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright IBM Corp. 2017. All Rights Reserved.
2+
// Node module: @loopback/cli
3+
// This file is licensed under the MIT License.
4+
// License text available at https://opensource.org/licenses/MIT
5+
6+
'use strict';
7+
const ProjectGenerator = require('../../lib/project-generator');
8+
const utils = require('../../lib/utils');
9+
10+
module.exports = class extends ProjectGenerator {
11+
// Note: arguments and options should be defined in the constructor.
12+
constructor(args, opts) {
13+
super(args, opts);
14+
}
15+
16+
_setupGenerator() {
17+
this.projectType = 'application';
18+
this.option('applicationName', {
19+
type: String,
20+
description: 'Application name',
21+
});
22+
return super._setupGenerator();
23+
}
24+
25+
setOptions() {
26+
return super.setOptions();
27+
}
28+
29+
promptProjectName() {
30+
return super.promptProjectName();
31+
}
32+
33+
promptProjectDir() {
34+
return super.promptProjectDir();
35+
}
36+
37+
promptApplication() {
38+
const prompts = [
39+
{
40+
type: 'input',
41+
name: 'applicationName',
42+
message: 'Application class name:',
43+
default: utils.toClassName(this.projectInfo.name) + 'Application',
44+
},
45+
];
46+
47+
return this.prompt(prompts).then(props => {
48+
Object.assign(this.projectInfo, props);
49+
});
50+
}
51+
52+
promptOptions() {
53+
return super.promptOptions();
54+
}
55+
56+
scaffold() {
57+
return super.scaffold();
58+
}
59+
60+
install() {
61+
return super.install();
62+
}
63+
64+
end() {
65+
this.log();
66+
this.log(
67+
'Application %s is now created in %s.',
68+
this.projectInfo.name,
69+
this.projectInfo.outdir
70+
);
71+
this.log();
72+
this.log('Next steps:');
73+
this.log();
74+
this.log('$ cd ' + this.projectInfo.outdir);
75+
this.log('$ npm start');
76+
this.log();
77+
}
78+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright IBM Corp. 2017. All Rights Reserved.
2+
// Node module: <%= project.name %>
3+
// This file is licensed under the MIT License.
4+
// License text available at https://opensource.org/licenses/MIT
5+
6+
const nodeMajorVersion = +process.versions.node.split('.')[0];
7+
const dist = nodeMajorVersion >= 7 ? './dist' : './dist6';
8+
9+
const application = (module.exports = require(dist));
10+
11+
if (require.main === module) {
12+
// Run the application
13+
application.main();
14+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright IBM Corp. 2017. All Rights Reserved.
2+
// Node module: <%= project.name %>
3+
// This file is licensed under the MIT License.
4+
// License text available at https://opensource.org/licenses/MIT
5+
6+
import {Application, ApplicationConfig} from '@loopback/core';
7+
import {RestComponent} from '@loopback/rest';
8+
import {PingController} from './controllers/ping-controller';
9+
10+
export class <%= project.applicationName %> extends Application {
11+
constructor(options?: ApplicationConfig) {
12+
// Allow options to replace the defined components array, if desired.
13+
options = Object.assign(
14+
{},
15+
{
16+
components: [RestComponent],
17+
},
18+
options,
19+
);
20+
super(options);
21+
this.setupControllers();
22+
}
23+
24+
setupControllers() {
25+
this.controller(PingController);
26+
}
27+
}

0 commit comments

Comments
 (0)