@loopback/cli 4.0.0-alpha.7 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.yo-rc.json +1697 -0
- package/{generators/project/templates/LICENSE → LICENSE} +2 -1
- package/README.md +44 -43
- package/bin/cli-main.js +61 -0
- package/generators/app/index.js +109 -15
- package/generators/app/templates/.dockerignore +5 -0
- package/generators/app/templates/Dockerfile +28 -0
- package/generators/app/templates/README.md.ejs +130 -0
- package/generators/app/templates/public/index.html.ejs +88 -0
- package/generators/app/templates/{test → src/__tests__}/README.md +0 -1
- package/generators/app/templates/src/__tests__/acceptance/home-page.acceptance.ts.ejs +31 -0
- package/generators/app/templates/src/__tests__/acceptance/ping.controller.acceptance.ts.ejs +21 -0
- package/generators/app/templates/src/__tests__/acceptance/test-helper.ts.ejs +32 -0
- package/generators/app/templates/src/application.ts.ejs +70 -0
- package/generators/app/templates/src/controllers/README.md +6 -0
- package/generators/app/templates/src/controllers/index.ts.ejs +1 -0
- package/generators/app/templates/src/controllers/ping.controller.ts.ejs +55 -0
- package/generators/app/templates/src/datasources/README.md +3 -0
- package/generators/app/templates/src/index.ts.ejs +39 -0
- package/generators/app/templates/src/migrate.ts.ejs +20 -0
- package/generators/app/templates/src/models/README.md +3 -0
- package/generators/app/templates/src/openapi-spec.ts.ejs +23 -0
- package/generators/app/templates/src/sequence.ts.ejs +3 -0
- package/generators/controller/index.js +279 -0
- package/generators/controller/templates/src/controllers/controller-rest-template.ts.ejs +150 -0
- package/generators/controller/templates/src/controllers/controller-template.ts.ejs +8 -0
- package/generators/copyright/fs.js +46 -0
- package/generators/copyright/git.js +78 -0
- package/generators/copyright/header.js +306 -0
- package/generators/copyright/index.js +230 -0
- package/generators/copyright/license.js +105 -0
- package/generators/datasource/index.js +341 -0
- package/generators/datasource/templates/datasource.ts.ejs +22 -0
- package/generators/discover/import-discovered-model.js +70 -0
- package/generators/discover/index.js +349 -0
- package/generators/example/downloader.js +16 -0
- package/generators/example/index.js +176 -0
- package/generators/extension/index.js +34 -5
- package/generators/extension/templates/README.md.ejs +32 -0
- package/generators/extension/templates/{test → src/__tests__}/acceptance/README.md +0 -0
- package/generators/extension/templates/{test → src/__tests__}/integration/README.md +0 -0
- package/generators/extension/templates/{test → src/__tests__}/unit/README.md +0 -0
- package/generators/extension/templates/src/component.ts.ejs +22 -0
- package/generators/extension/templates/src/controllers/README.md +3 -2
- package/generators/extension/templates/src/decorators/README.md +10 -4
- package/generators/extension/templates/src/index.ts.ejs +3 -0
- package/generators/extension/templates/src/keys.ts.ejs +11 -0
- package/generators/extension/templates/src/mixins/README.md +77 -21
- package/generators/extension/templates/src/providers/README.md +51 -25
- package/generators/extension/templates/src/repositories/README.md +1 -1
- package/generators/extension/templates/src/types.ts.ejs +15 -0
- package/generators/import-lb3-models/index.js +197 -0
- package/generators/import-lb3-models/lb3app-loader.js +31 -0
- package/generators/import-lb3-models/migrate-model.js +249 -0
- package/generators/import-lb3-models/model-names.js +32 -0
- package/generators/interceptor/index.js +178 -0
- package/generators/interceptor/templates/interceptor-template.ts.ejs +62 -0
- package/generators/model/index.js +536 -0
- package/generators/model/property-definition.js +85 -0
- package/generators/model/templates/model.ts.ejs +42 -0
- package/generators/observer/index.js +132 -0
- package/generators/observer/templates/observer-template.ts.ejs +40 -0
- package/generators/openapi/README.md +211 -0
- package/generators/openapi/index.js +535 -0
- package/generators/openapi/schema-helper.js +447 -0
- package/generators/openapi/spec-helper.js +484 -0
- package/generators/openapi/spec-loader.js +75 -0
- package/generators/openapi/templates/src/controllers/controller-template.ts.ejs +43 -0
- package/generators/openapi/templates/src/datasources/datasource.ts.ejs +42 -0
- package/generators/openapi/templates/src/models/model-template.ts.ejs +71 -0
- package/generators/openapi/templates/src/models/type-template.ts.ejs +13 -0
- package/generators/openapi/templates/src/services/service-proxy-template.ts.ejs +55 -0
- package/generators/openapi/utils.js +322 -0
- package/generators/project/templates/.eslintignore +4 -0
- package/generators/project/templates/.eslintrc.js.ejs +3 -0
- package/generators/project/templates/.mocharc.json +5 -0
- package/generators/project/templates/.prettierignore +0 -2
- package/generators/project/templates/.prettierrc +2 -1
- package/generators/project/templates/.vscode/launch.json +38 -0
- package/generators/project/templates/.vscode/settings.json +32 -0
- package/generators/project/templates/.vscode/tasks.json +29 -0
- package/generators/project/templates/DEVELOPING.md +36 -0
- package/generators/project/templates/_.gitignore +3 -5
- package/generators/project/templates/package.json.ejs +175 -0
- package/generators/project/templates/package.plain.json.ejs +176 -0
- package/generators/project/templates/tsconfig.json.ejs +39 -0
- package/generators/relation/base-relation.generator.js +220 -0
- package/generators/relation/belongs-to-relation.generator.js +196 -0
- package/generators/relation/has-many-relation.generator.js +200 -0
- package/generators/relation/has-many-through-relation.generator.js +331 -0
- package/generators/relation/has-one-relation.generator.js +200 -0
- package/generators/relation/index.js +795 -0
- package/generators/relation/references-many-relation.generator.js +142 -0
- package/generators/relation/templates/controller-relation-template-belongs-to.ts.ejs +38 -0
- package/generators/relation/templates/controller-relation-template-has-many-through.ts.ejs +110 -0
- package/generators/relation/templates/controller-relation-template-has-many.ts.ejs +110 -0
- package/generators/relation/templates/controller-relation-template-has-one.ts.ejs +110 -0
- package/generators/relation/utils.generator.js +260 -0
- package/generators/repository/index.js +576 -0
- package/generators/repository/templates/src/repositories/repository-crud-default-template.ts.ejs +21 -0
- package/generators/repository/templates/src/repositories/repository-kv-template.ts.ejs +19 -0
- package/generators/rest-crud/crud-rest-component.js +63 -0
- package/generators/rest-crud/index.js +401 -0
- package/generators/rest-crud/templates/src/model-endpoints/model.rest-config-template.ts.ejs +10 -0
- package/generators/service/index.js +351 -0
- package/generators/service/templates/local-service-class-template.ts.ejs +10 -0
- package/generators/service/templates/local-service-provider-template.ts.ejs +19 -0
- package/generators/service/templates/remote-service-proxy-template.ts.ejs +21 -0
- package/generators/update/index.js +55 -0
- package/intl/cs/messages.json +204 -0
- package/intl/de/messages.json +204 -0
- package/intl/en/messages.json +204 -0
- package/intl/es/messages.json +204 -0
- package/intl/fr/messages.json +204 -0
- package/intl/it/messages.json +204 -0
- package/intl/ja/messages.json +204 -0
- package/intl/ko/messages.json +204 -0
- package/intl/nl/messages.json +204 -0
- package/intl/pl/messages.json +204 -0
- package/intl/pt/messages.json +204 -0
- package/intl/ru/messages.json +204 -0
- package/intl/tr/messages.json +204 -0
- package/intl/zh-Hans/messages.json +204 -0
- package/intl/zh-Hant/messages.json +204 -0
- package/lib/artifact-generator.js +189 -0
- package/lib/ast-helper.js +214 -0
- package/lib/base-generator.js +509 -0
- package/lib/cli.js +233 -0
- package/lib/connectors.json +894 -0
- package/lib/debug.js +16 -0
- package/lib/globalize.js +12 -0
- package/lib/model-discoverer.js +118 -0
- package/lib/project-generator.js +154 -57
- package/lib/tab-completion.js +127 -0
- package/lib/update-index.js +44 -0
- package/lib/utils.js +746 -22
- package/lib/version-helper.js +299 -0
- package/package.json +183 -32
- package/CHANGELOG.md +0 -64
- package/bin/cli.js +0 -65
- package/generators/app/templates/index.js +0 -14
- package/generators/app/templates/src/application.ts +0 -27
- package/generators/app/templates/src/controllers/ping-controller.ts +0 -25
- package/generators/app/templates/src/index.ts +0 -25
- package/generators/app/templates/test/ping-controller.test.ts +0 -46
- package/generators/extension/templates/index.js +0 -8
- package/generators/extension/templates/src/component.ts +0 -14
- package/generators/extension/templates/src/index.ts +0 -6
- package/generators/project/templates/.npmrc +0 -1
- package/generators/project/templates/.yo-rc.json +0 -1
- package/generators/project/templates/README.md +0 -4
- package/generators/project/templates/index.d.ts +0 -6
- package/generators/project/templates/index.ts +0 -11
- package/generators/project/templates/package.json +0 -79
- package/generators/project/templates/package.plain.json +0 -82
- package/generators/project/templates/test/mocha.opts +0 -1
- package/generators/project/templates/tsconfig.json +0 -29
- package/generators/project/templates/tslint.build.json +0 -17
- package/generators/project/templates/tslint.json +0 -33
package/README.md
CHANGED
|
@@ -1,69 +1,70 @@
|
|
|
1
1
|
# @loopback/cli
|
|
2
2
|
|
|
3
|
-
This module contains the
|
|
3
|
+
This module contains the official CLI for LoopBack 4.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
Run the following command to install the CLI.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
```
|
|
10
|
+
$ npm install -g @loopback/cli
|
|
11
|
+
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## Basic Use
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Run `lb4 --commands` or `lb4 -l` to list all available commands:
|
|
16
16
|
|
|
17
17
|
```
|
|
18
|
-
|
|
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
|
|
18
|
+
$ lb4 -l
|
|
35
19
|
```
|
|
36
20
|
|
|
37
|
-
|
|
21
|
+
Use the option `--help` to learn more about any specific command:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
$ lb4 model --help
|
|
25
|
+
```
|
|
38
26
|
|
|
39
|
-
|
|
27
|
+
Run `lb4` or `lb4 app` to scaffold a new LoopBack 4 project.
|
|
40
28
|
|
|
41
29
|
```
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
|
30
|
+
$ lb4 app
|
|
31
|
+
? Project name: my-awesome-app
|
|
32
|
+
(etc.)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Use `lb4 --version` (or `lb4 -v`) to print out version information to include in
|
|
36
|
+
bug reports, for example:
|
|
56
37
|
|
|
57
38
|
```
|
|
39
|
+
$ lb4 -v
|
|
40
|
+
@loopback/cli version: 1.8.1
|
|
41
|
+
|
|
42
|
+
@loopback/* dependencies:
|
|
43
|
+
- @loopback/authentication: ^1.0.14
|
|
44
|
+
- @loopback/boot: ^1.0.14
|
|
45
|
+
- @loopback/build: ^1.3.1
|
|
46
|
+
- @loopback/context: ^1.6.0
|
|
47
|
+
- @loopback/core: ^1.1.7
|
|
48
|
+
- (etc.)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
See [CLI reference](https://loopback.io/doc/en/lb4/Command-line-interface.html)
|
|
52
|
+
for a detailed documentation.
|
|
53
|
+
|
|
54
|
+
## Contributions
|
|
55
|
+
|
|
56
|
+
- [Guidelines](https://github.com/loopbackio/loopback-next/blob/master/docs/CONTRIBUTING.md)
|
|
57
|
+
- [Join the team](https://github.com/loopbackio/loopback-next/issues/110)
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
## Tests
|
|
60
60
|
|
|
61
61
|
run `npm test` from the root folder.
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
## Contributors
|
|
64
64
|
|
|
65
|
-
See
|
|
65
|
+
See
|
|
66
|
+
[all contributors](https://github.com/loopbackio/loopback-next/graphs/contributors).
|
|
66
67
|
|
|
67
|
-
|
|
68
|
+
## License
|
|
68
69
|
|
|
69
70
|
MIT
|
package/bin/cli-main.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Copyright IBM Corp. 2018,2020. 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 pkg = require('../package.json');
|
|
10
|
+
const semver = require('semver');
|
|
11
|
+
const fs = require('fs-extra');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const chalk = require('chalk');
|
|
14
|
+
|
|
15
|
+
const {
|
|
16
|
+
tabCompletionCommands,
|
|
17
|
+
runTabCompletionCommand,
|
|
18
|
+
} = require('../lib/tab-completion');
|
|
19
|
+
|
|
20
|
+
// Make sure node version meets the requirement. This code intentionally only
|
|
21
|
+
// uses ES5 features so that it can be run with lower versions of Node
|
|
22
|
+
// to report the version requirement.
|
|
23
|
+
const nodeVer = process.versions.node;
|
|
24
|
+
const requiredVer = pkg.engines.node;
|
|
25
|
+
const ok = semver.satisfies(nodeVer, requiredVer);
|
|
26
|
+
if (!ok) {
|
|
27
|
+
const format =
|
|
28
|
+
'Node.js "%s" is not supported. Please use a version that satisfies "%s".';
|
|
29
|
+
console.warn(chalk.red(format), nodeVer, requiredVer);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Intentionally have a separate `main.js` which can use JS features
|
|
33
|
+
// supported by required version of Node
|
|
34
|
+
const minimist = require('minimist');
|
|
35
|
+
const opts = minimist(process.argv.slice(2), {
|
|
36
|
+
alias: {
|
|
37
|
+
version: 'v', // --version or -v: print versions
|
|
38
|
+
commands: 'l', // --commands or -l: print commands
|
|
39
|
+
help: 'h', // --help or -h: help
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const args = opts._;
|
|
44
|
+
|
|
45
|
+
const originalCommand = args[0];
|
|
46
|
+
if (tabCompletionCommands.includes(originalCommand)) {
|
|
47
|
+
const yoJsonFile = path.join(__dirname, '../.yo-rc.json');
|
|
48
|
+
const config = fs.readJsonSync(yoJsonFile);
|
|
49
|
+
return runTabCompletionCommand(config.commands, originalCommand, console.log);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const main = require('../lib/cli');
|
|
53
|
+
const updateNotifier = require('update-notifier');
|
|
54
|
+
// Force version check with `lb4 --version`
|
|
55
|
+
const interval = opts.version ? 0 : undefined;
|
|
56
|
+
updateNotifier({
|
|
57
|
+
pkg: pkg,
|
|
58
|
+
updateCheckInterval: interval,
|
|
59
|
+
}).notify({isGlobal: true});
|
|
60
|
+
|
|
61
|
+
main(opts);
|
package/generators/app/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright IBM Corp. 2017. All Rights Reserved.
|
|
1
|
+
// Copyright IBM Corp. 2017,2020. All Rights Reserved.
|
|
2
2
|
// Node module: @loopback/cli
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
@@ -6,73 +6,167 @@
|
|
|
6
6
|
'use strict';
|
|
7
7
|
const ProjectGenerator = require('../../lib/project-generator');
|
|
8
8
|
const utils = require('../../lib/utils');
|
|
9
|
+
const g = require('../../lib/globalize');
|
|
9
10
|
|
|
10
|
-
module.exports = class extends ProjectGenerator {
|
|
11
|
+
module.exports = class AppGenerator extends ProjectGenerator {
|
|
11
12
|
// Note: arguments and options should be defined in the constructor.
|
|
12
13
|
constructor(args, opts) {
|
|
13
14
|
super(args, opts);
|
|
15
|
+
this.buildOptions.push({
|
|
16
|
+
name: 'docker',
|
|
17
|
+
description: g.f('include Dockerfile and .dockerignore'),
|
|
18
|
+
});
|
|
19
|
+
this.buildOptions.push({
|
|
20
|
+
name: 'repositories',
|
|
21
|
+
description: g.f('include repository imports and RepositoryMixin'),
|
|
22
|
+
});
|
|
23
|
+
this.buildOptions.push({
|
|
24
|
+
name: 'services',
|
|
25
|
+
description: g.f('include service-proxy imports and ServiceMixin'),
|
|
26
|
+
});
|
|
14
27
|
}
|
|
15
28
|
|
|
16
29
|
_setupGenerator() {
|
|
17
30
|
this.projectType = 'application';
|
|
31
|
+
|
|
18
32
|
this.option('applicationName', {
|
|
19
33
|
type: String,
|
|
20
|
-
description: 'Application name',
|
|
34
|
+
description: g.f('Application class name'),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
this.option('docker', {
|
|
38
|
+
type: Boolean,
|
|
39
|
+
description: g.f('Include Dockerfile and .dockerignore'),
|
|
21
40
|
});
|
|
41
|
+
|
|
42
|
+
this.option('repositories', {
|
|
43
|
+
type: Boolean,
|
|
44
|
+
description: g.f('Include repository imports and RepositoryMixin'),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
this.option('services', {
|
|
48
|
+
type: Boolean,
|
|
49
|
+
description: g.f('Include service-proxy imports and ServiceMixin'),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
this.option('apiconnect', {
|
|
53
|
+
type: Boolean,
|
|
54
|
+
description: g.f('Include ApiConnectComponent'),
|
|
55
|
+
});
|
|
56
|
+
|
|
22
57
|
return super._setupGenerator();
|
|
23
58
|
}
|
|
24
59
|
|
|
25
|
-
setOptions() {
|
|
26
|
-
|
|
60
|
+
async setOptions() {
|
|
61
|
+
await super.setOptions();
|
|
62
|
+
if (this.shouldExit()) return;
|
|
63
|
+
if (this.options.applicationName) {
|
|
64
|
+
const clsName = utils.toClassName(this.options.applicationName);
|
|
65
|
+
if (typeof clsName === 'string') {
|
|
66
|
+
this.projectInfo.applicationName = clsName;
|
|
67
|
+
} else if (clsName instanceof Error) {
|
|
68
|
+
throw clsName;
|
|
69
|
+
}
|
|
70
|
+
const msg = utils.validateClassName(clsName);
|
|
71
|
+
if (msg !== true) {
|
|
72
|
+
throw new Error(msg);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
27
75
|
}
|
|
28
76
|
|
|
29
77
|
promptProjectName() {
|
|
78
|
+
if (this.shouldExit()) return;
|
|
30
79
|
return super.promptProjectName();
|
|
31
80
|
}
|
|
32
81
|
|
|
33
82
|
promptProjectDir() {
|
|
83
|
+
if (this.shouldExit()) return;
|
|
34
84
|
return super.promptProjectDir();
|
|
35
85
|
}
|
|
36
86
|
|
|
37
87
|
promptApplication() {
|
|
88
|
+
if (this.shouldExit()) return;
|
|
38
89
|
const prompts = [
|
|
39
90
|
{
|
|
40
91
|
type: 'input',
|
|
41
92
|
name: 'applicationName',
|
|
42
|
-
message: 'Application class name:',
|
|
43
|
-
default: utils.
|
|
93
|
+
message: g.f('Application class name:'),
|
|
94
|
+
default: utils.pascalCase(this.projectInfo.name) + 'Application',
|
|
95
|
+
validate: utils.validateClassName,
|
|
96
|
+
when: this.projectInfo.applicationName == null,
|
|
44
97
|
},
|
|
45
98
|
];
|
|
46
99
|
|
|
47
100
|
return this.prompt(prompts).then(props => {
|
|
48
|
-
|
|
101
|
+
props.applicationName = utils.toClassName(props.applicationName);
|
|
102
|
+
if (typeof props.applicationName === 'string') {
|
|
103
|
+
this.projectInfo.applicationName = props.applicationName;
|
|
104
|
+
}
|
|
49
105
|
});
|
|
50
106
|
}
|
|
51
107
|
|
|
52
108
|
promptOptions() {
|
|
109
|
+
if (this.shouldExit()) return;
|
|
53
110
|
return super.promptOptions();
|
|
54
111
|
}
|
|
55
112
|
|
|
113
|
+
promptYarnInstall() {
|
|
114
|
+
if (this.shouldExit()) return;
|
|
115
|
+
return super.promptYarnInstall();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
buildAppClassMixins() {
|
|
119
|
+
if (this.shouldExit()) return;
|
|
120
|
+
const {repositories, services} = this.projectInfo || {};
|
|
121
|
+
if (!repositories && !services) return;
|
|
122
|
+
|
|
123
|
+
let appClassWithMixins = 'RestApplication';
|
|
124
|
+
if (repositories) {
|
|
125
|
+
appClassWithMixins = `RepositoryMixin(${appClassWithMixins})`;
|
|
126
|
+
}
|
|
127
|
+
if (services) {
|
|
128
|
+
appClassWithMixins = `ServiceMixin(${appClassWithMixins})`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
this.projectInfo.appClassWithMixins = appClassWithMixins;
|
|
132
|
+
}
|
|
133
|
+
|
|
56
134
|
scaffold() {
|
|
57
|
-
|
|
135
|
+
const result = super.scaffold();
|
|
136
|
+
if (this.shouldExit()) return result;
|
|
137
|
+
|
|
138
|
+
const {docker, repositories} = this.projectInfo || {};
|
|
139
|
+
if (!docker) {
|
|
140
|
+
this.fs.delete(this.destinationPath('Dockerfile'));
|
|
141
|
+
this.fs.delete(this.destinationPath('.dockerignore'));
|
|
142
|
+
}
|
|
143
|
+
if (!repositories) {
|
|
144
|
+
this.fs.delete(this.destinationPath('src/migrate.ts.ejs'));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return result;
|
|
58
148
|
}
|
|
59
149
|
|
|
60
150
|
install() {
|
|
61
151
|
return super.install();
|
|
62
152
|
}
|
|
63
153
|
|
|
64
|
-
end() {
|
|
154
|
+
async end() {
|
|
155
|
+
await super.end();
|
|
156
|
+
if (this.shouldExit()) return;
|
|
65
157
|
this.log();
|
|
66
158
|
this.log(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
159
|
+
g.f(
|
|
160
|
+
'Application %s was created in %s.',
|
|
161
|
+
this.projectInfo.name,
|
|
162
|
+
this.projectInfo.outdir,
|
|
163
|
+
),
|
|
70
164
|
);
|
|
71
165
|
this.log();
|
|
72
|
-
this.log('Next steps:');
|
|
166
|
+
this.log(g.f('Next steps:'));
|
|
73
167
|
this.log();
|
|
74
168
|
this.log('$ cd ' + this.projectInfo.outdir);
|
|
75
|
-
this.log(
|
|
169
|
+
this.log(`$ ${this.options.packageManager || 'npm'} start`);
|
|
76
170
|
this.log();
|
|
77
171
|
}
|
|
78
172
|
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Check out https://hub.docker.com/_/node to select a new base image
|
|
2
|
+
FROM node:16-slim
|
|
3
|
+
|
|
4
|
+
# Set to a non-root built-in user `node`
|
|
5
|
+
USER node
|
|
6
|
+
|
|
7
|
+
# Create app directory (with user `node`)
|
|
8
|
+
RUN mkdir -p /home/node/app
|
|
9
|
+
|
|
10
|
+
WORKDIR /home/node/app
|
|
11
|
+
|
|
12
|
+
# Install app dependencies
|
|
13
|
+
# A wildcard is used to ensure both package.json AND package-lock.json are copied
|
|
14
|
+
# where available (npm@5+)
|
|
15
|
+
COPY --chown=node package*.json ./
|
|
16
|
+
|
|
17
|
+
RUN npm install
|
|
18
|
+
|
|
19
|
+
# Bundle app source code
|
|
20
|
+
COPY --chown=node . .
|
|
21
|
+
|
|
22
|
+
RUN npm run build
|
|
23
|
+
|
|
24
|
+
# Bind to all network interfaces so that it can be mapped to the host OS
|
|
25
|
+
ENV HOST=0.0.0.0 PORT=3000
|
|
26
|
+
|
|
27
|
+
EXPOSE ${PORT}
|
|
28
|
+
CMD [ "node", "." ]
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# <%= project.name %>
|
|
2
|
+
|
|
3
|
+
This application is generated using [LoopBack 4 CLI](https://loopback.io/doc/en/lb4/Command-line-interface.html) with the
|
|
4
|
+
[initial project layout](https://loopback.io/doc/en/lb4/Loopback-application-layout.html).
|
|
5
|
+
|
|
6
|
+
## Install dependencies
|
|
7
|
+
|
|
8
|
+
By default, dependencies were installed when this application was generated.
|
|
9
|
+
Whenever dependencies in `package.json` are changed, run the following command:
|
|
10
|
+
|
|
11
|
+
<% if (packageManager === 'yarn') { -%>
|
|
12
|
+
```sh
|
|
13
|
+
yarn install
|
|
14
|
+
```
|
|
15
|
+
<% } else { -%>
|
|
16
|
+
```sh
|
|
17
|
+
npm install
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
To only install resolved dependencies in `package-lock.json`:
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
npm ci
|
|
24
|
+
```
|
|
25
|
+
<% } -%>
|
|
26
|
+
|
|
27
|
+
## Run the application
|
|
28
|
+
|
|
29
|
+
<% if (packageManager === 'yarn') { -%>
|
|
30
|
+
```sh
|
|
31
|
+
yarn start
|
|
32
|
+
```
|
|
33
|
+
<% } else { -%>
|
|
34
|
+
```sh
|
|
35
|
+
npm start
|
|
36
|
+
```
|
|
37
|
+
<% } -%>
|
|
38
|
+
|
|
39
|
+
You can also run `node .` to skip the build step.
|
|
40
|
+
|
|
41
|
+
Open http://127.0.0.1:3000 in your browser.
|
|
42
|
+
|
|
43
|
+
## Rebuild the project
|
|
44
|
+
|
|
45
|
+
To incrementally build the project:
|
|
46
|
+
|
|
47
|
+
<% if (packageManager === 'yarn') { -%>
|
|
48
|
+
```sh
|
|
49
|
+
yarn run build
|
|
50
|
+
```
|
|
51
|
+
<% } else { -%>
|
|
52
|
+
```sh
|
|
53
|
+
npm run build
|
|
54
|
+
```
|
|
55
|
+
<% } -%>
|
|
56
|
+
|
|
57
|
+
To force a full build by cleaning up cached artifacts:
|
|
58
|
+
|
|
59
|
+
<% if (packageManager === 'yarn') { -%>
|
|
60
|
+
```sh
|
|
61
|
+
yarn run rebuild
|
|
62
|
+
```
|
|
63
|
+
<% } else { -%>
|
|
64
|
+
```sh
|
|
65
|
+
npm run rebuild
|
|
66
|
+
```
|
|
67
|
+
<% } -%>
|
|
68
|
+
|
|
69
|
+
<% if (project.prettier || project.eslint) { -%>
|
|
70
|
+
## Fix code style and formatting issues
|
|
71
|
+
|
|
72
|
+
<% if (packageManager === 'yarn') { -%>
|
|
73
|
+
```sh
|
|
74
|
+
yarn run lint
|
|
75
|
+
```
|
|
76
|
+
<% } else { -%>
|
|
77
|
+
```sh
|
|
78
|
+
npm run lint
|
|
79
|
+
```
|
|
80
|
+
<% } -%>
|
|
81
|
+
|
|
82
|
+
To automatically fix such issues:
|
|
83
|
+
|
|
84
|
+
<% if (packageManager === 'yarn') { -%>
|
|
85
|
+
```sh
|
|
86
|
+
yarn run lint:fix
|
|
87
|
+
```
|
|
88
|
+
<% } else { -%>
|
|
89
|
+
```sh
|
|
90
|
+
npm run lint:fix
|
|
91
|
+
```
|
|
92
|
+
<% } -%>
|
|
93
|
+
<% } -%>
|
|
94
|
+
|
|
95
|
+
## Other useful commands
|
|
96
|
+
|
|
97
|
+
<% if (packageManager === 'yarn') { -%>
|
|
98
|
+
- `yarn run migrate`: Migrate database schemas for models
|
|
99
|
+
- `yarn run openapi-spec`: Generate OpenAPI spec into a file
|
|
100
|
+
<% if (project.docker) { -%>
|
|
101
|
+
- `yarn run docker:build`: Build a Docker image for this application
|
|
102
|
+
- `yarn run docker:run`: Run this application inside a Docker container
|
|
103
|
+
<% } -%>
|
|
104
|
+
<% } else { -%>
|
|
105
|
+
- `npm run migrate`: Migrate database schemas for models
|
|
106
|
+
- `npm run openapi-spec`: Generate OpenAPI spec into a file
|
|
107
|
+
<% if (project.docker) { -%>
|
|
108
|
+
- `npm run docker:build`: Build a Docker image for this application
|
|
109
|
+
- `npm run docker:run`: Run this application inside a Docker container
|
|
110
|
+
<% } -%>
|
|
111
|
+
<% } -%>
|
|
112
|
+
|
|
113
|
+
## Tests
|
|
114
|
+
|
|
115
|
+
<% if (packageManager === 'yarn') { -%>
|
|
116
|
+
```sh
|
|
117
|
+
yarn test
|
|
118
|
+
```
|
|
119
|
+
<% } else { -%>
|
|
120
|
+
```sh
|
|
121
|
+
npm test
|
|
122
|
+
```
|
|
123
|
+
<% } -%>
|
|
124
|
+
|
|
125
|
+
## What's next
|
|
126
|
+
|
|
127
|
+
Please check out [LoopBack 4 documentation](https://loopback.io/doc/en/lb4/) to
|
|
128
|
+
understand how you can continue to add features to this application.
|
|
129
|
+
|
|
130
|
+
[-@2x.png)](http://loopback.io/)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<title><%= project.description %></title>
|
|
6
|
+
|
|
7
|
+
<meta charset="utf-8">
|
|
8
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
9
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
10
|
+
<link rel="shortcut icon" type="image/x-icon" href="https://loopback.io/favicon.ico">
|
|
11
|
+
|
|
12
|
+
<style>
|
|
13
|
+
h3 {
|
|
14
|
+
margin-left: 25px;
|
|
15
|
+
text-align: center;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
a, a:visited {
|
|
19
|
+
color: #3f5dff;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
h3 a {
|
|
23
|
+
margin-left: 10px;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
a:hover, a:focus, a:active {
|
|
27
|
+
color: #001956;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.power {
|
|
31
|
+
position: absolute;
|
|
32
|
+
bottom: 25px;
|
|
33
|
+
left: 50%;
|
|
34
|
+
transform: translateX(-50%);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.info {
|
|
38
|
+
position: absolute;
|
|
39
|
+
top: 50%;
|
|
40
|
+
left: 50%;
|
|
41
|
+
transform: translate(-50%, -50%)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.info h1 {
|
|
45
|
+
text-align: center;
|
|
46
|
+
margin-bottom: 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.info p {
|
|
50
|
+
text-align: center;
|
|
51
|
+
margin-bottom: 3em;
|
|
52
|
+
margin-top: 1em;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@media (prefers-color-scheme: dark) {
|
|
56
|
+
body {
|
|
57
|
+
background-color: rgb(29, 30, 32);
|
|
58
|
+
color: white;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
a, a:visited {
|
|
62
|
+
color: #4990e2;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
a:hover, a:focus, a:active {
|
|
66
|
+
color: #2b78ff;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
</style>
|
|
70
|
+
</head>
|
|
71
|
+
|
|
72
|
+
<body>
|
|
73
|
+
<div class="info">
|
|
74
|
+
<h1><%= project.name %></h1>
|
|
75
|
+
<p>Version <%= project.version || '1.0.0' %></p>
|
|
76
|
+
|
|
77
|
+
<h3>OpenAPI spec: <a href="./openapi.json">/openapi.json</a></h3>
|
|
78
|
+
<h3>API Explorer: <a href="./explorer">/explorer</a></h3>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<footer class="power">
|
|
82
|
+
<a href="https://loopback.io" target="_blank">
|
|
83
|
+
<img src="https://loopback.io/images/branding/powered-by-loopback/blue/powered-by-loopback-sm.png" />
|
|
84
|
+
</a>
|
|
85
|
+
</footer>
|
|
86
|
+
</body>
|
|
87
|
+
|
|
88
|
+
</html>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {Client} from '@loopback/testlab';
|
|
2
|
+
import {<%= project.applicationName %>} from '../..';
|
|
3
|
+
import {setupApplication} from './test-helper';
|
|
4
|
+
|
|
5
|
+
describe('HomePage', () => {
|
|
6
|
+
let app: <%= project.applicationName %>;
|
|
7
|
+
let client: Client;
|
|
8
|
+
|
|
9
|
+
before('setupApplication', async () => {
|
|
10
|
+
({app, client} = await setupApplication());
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
after(async () => {
|
|
14
|
+
await app.stop();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('exposes a default home page', async () => {
|
|
18
|
+
await client
|
|
19
|
+
.get('/')
|
|
20
|
+
.expect(200)
|
|
21
|
+
.expect('Content-Type', /text\/html/);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('exposes self-hosted explorer', async () => {
|
|
25
|
+
await client
|
|
26
|
+
.get('/explorer/')
|
|
27
|
+
.expect(200)
|
|
28
|
+
.expect('Content-Type', /text\/html/)
|
|
29
|
+
.expect(/<title>LoopBack API Explorer/);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {Client, expect} from '@loopback/testlab';
|
|
2
|
+
import {<%= project.applicationName %>} from '../..';
|
|
3
|
+
import {setupApplication} from './test-helper';
|
|
4
|
+
|
|
5
|
+
describe('PingController', () => {
|
|
6
|
+
let app: <%= project.applicationName %>;
|
|
7
|
+
let client: Client;
|
|
8
|
+
|
|
9
|
+
before('setupApplication', async () => {
|
|
10
|
+
({app, client} = await setupApplication());
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
after(async () => {
|
|
14
|
+
await app.stop();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('invokes GET /ping', async () => {
|
|
18
|
+
const res = await client.get('/ping?msg=world').expect(200);
|
|
19
|
+
expect(res.body).to.containEql({greeting: 'Hello from LoopBack'});
|
|
20
|
+
});
|
|
21
|
+
});
|