@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
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {<%= project.applicationName %>} from '../..';
|
|
2
|
+
import {
|
|
3
|
+
createRestAppClient,
|
|
4
|
+
givenHttpServerConfig,
|
|
5
|
+
Client,
|
|
6
|
+
} from '@loopback/testlab';
|
|
7
|
+
|
|
8
|
+
export async function setupApplication(): Promise<AppWithClient> {
|
|
9
|
+
const restConfig = givenHttpServerConfig({
|
|
10
|
+
// Customize the server configuration here.
|
|
11
|
+
// Empty values (undefined, '') will be ignored by the helper.
|
|
12
|
+
//
|
|
13
|
+
// host: process.env.HOST,
|
|
14
|
+
// port: +process.env.PORT,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const app = new <%= project.applicationName %>({
|
|
18
|
+
rest: restConfig,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
await app.boot();
|
|
22
|
+
await app.start();
|
|
23
|
+
|
|
24
|
+
const client = createRestAppClient(app);
|
|
25
|
+
|
|
26
|
+
return {app, client};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface AppWithClient {
|
|
30
|
+
app: <%= project.applicationName %>;
|
|
31
|
+
client: Client;
|
|
32
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import {BootMixin} from '@loopback/boot';
|
|
2
|
+
import {ApplicationConfig} from '@loopback/core';
|
|
3
|
+
import {
|
|
4
|
+
RestExplorerBindings,
|
|
5
|
+
RestExplorerComponent,
|
|
6
|
+
} from '@loopback/rest-explorer';
|
|
7
|
+
<% if (project.repositories) { -%>
|
|
8
|
+
import {RepositoryMixin} from '@loopback/repository';
|
|
9
|
+
<% } -%>
|
|
10
|
+
import {RestApplication} from '@loopback/rest';
|
|
11
|
+
<% if (project.services) { -%>
|
|
12
|
+
import {ServiceMixin} from '@loopback/service-proxy';
|
|
13
|
+
<% } -%>
|
|
14
|
+
<% if (project.apiconnect) { -%>
|
|
15
|
+
import {
|
|
16
|
+
ApiConnectBindings,
|
|
17
|
+
ApiConnectComponent,
|
|
18
|
+
ApiConnectSpecOptions,
|
|
19
|
+
} from '@loopback/apiconnect';
|
|
20
|
+
<% } -%>
|
|
21
|
+
import path from 'path';
|
|
22
|
+
import {MySequence} from './sequence';
|
|
23
|
+
|
|
24
|
+
export {ApplicationConfig};
|
|
25
|
+
|
|
26
|
+
<% if (project.appClassWithMixins) { -%>
|
|
27
|
+
export class <%= project.applicationName %> extends BootMixin(
|
|
28
|
+
<%= project.appClassWithMixins %>,
|
|
29
|
+
) {
|
|
30
|
+
<%
|
|
31
|
+
} else { // no optional mixins
|
|
32
|
+
-%>
|
|
33
|
+
export class <%= project.applicationName %> extends BootMixin(RestApplication) {
|
|
34
|
+
<% } -%>
|
|
35
|
+
constructor(options: ApplicationConfig = {}) {
|
|
36
|
+
super(options);
|
|
37
|
+
|
|
38
|
+
// Set up the custom sequence
|
|
39
|
+
this.sequence(MySequence);
|
|
40
|
+
|
|
41
|
+
// Set up default home page
|
|
42
|
+
this.static('/', path.join(__dirname, '../public'));
|
|
43
|
+
|
|
44
|
+
// Customize @loopback/rest-explorer configuration here
|
|
45
|
+
this.configure(RestExplorerBindings.COMPONENT).to({
|
|
46
|
+
path: '/explorer',
|
|
47
|
+
});
|
|
48
|
+
this.component(RestExplorerComponent);
|
|
49
|
+
<%_ if (project.apiconnect) { -%>
|
|
50
|
+
this.component(ApiConnectComponent);
|
|
51
|
+
const apiConnectOptions: ApiConnectSpecOptions = {
|
|
52
|
+
targetUrl: 'http://localhost:3000/',
|
|
53
|
+
};
|
|
54
|
+
this.configure(ApiConnectBindings.API_CONNECT_SPEC_ENHANCER).to(
|
|
55
|
+
apiConnectOptions,
|
|
56
|
+
);
|
|
57
|
+
<%_ } -%>
|
|
58
|
+
|
|
59
|
+
this.projectRoot = __dirname;
|
|
60
|
+
// Customize @loopback/boot Booter Conventions here
|
|
61
|
+
this.bootOptions = {
|
|
62
|
+
controllers: {
|
|
63
|
+
// Customize ControllerBooter Conventions here
|
|
64
|
+
dirs: ['controllers'],
|
|
65
|
+
extensions: ['.controller.js'],
|
|
66
|
+
nested: true,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
# Controllers
|
|
2
2
|
|
|
3
3
|
This directory contains source files for the controllers exported by this app.
|
|
4
|
+
|
|
5
|
+
To add a new empty controller, type in `lb4 controller [<name>]` from the
|
|
6
|
+
command-line of your application's root directory.
|
|
7
|
+
|
|
8
|
+
For more information, please visit
|
|
9
|
+
[Controller generator](http://loopback.io/doc/en/lb4/Controller-generator.html).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ping.controller';
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {inject} from '@loopback/core';
|
|
2
|
+
import {
|
|
3
|
+
Request,
|
|
4
|
+
RestBindings,
|
|
5
|
+
get,
|
|
6
|
+
response,
|
|
7
|
+
ResponseObject,
|
|
8
|
+
} from '@loopback/rest';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* OpenAPI response for ping()
|
|
12
|
+
*/
|
|
13
|
+
const PING_RESPONSE: ResponseObject = {
|
|
14
|
+
description: 'Ping Response',
|
|
15
|
+
content: {
|
|
16
|
+
'application/json': {
|
|
17
|
+
schema: {
|
|
18
|
+
type: 'object',
|
|
19
|
+
title: 'PingResponse',
|
|
20
|
+
properties: {
|
|
21
|
+
greeting: {type: 'string'},
|
|
22
|
+
date: {type: 'string'},
|
|
23
|
+
url: {type: 'string'},
|
|
24
|
+
headers: {
|
|
25
|
+
type: 'object',
|
|
26
|
+
properties: {
|
|
27
|
+
'Content-Type': {type: 'string'},
|
|
28
|
+
},
|
|
29
|
+
additionalProperties: true,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A simple controller to bounce back http requests
|
|
39
|
+
*/
|
|
40
|
+
export class PingController {
|
|
41
|
+
constructor(@inject(RestBindings.Http.REQUEST) private req: Request) {}
|
|
42
|
+
|
|
43
|
+
// Map to `GET /ping`
|
|
44
|
+
@get('/ping')
|
|
45
|
+
@response(200, PING_RESPONSE)
|
|
46
|
+
ping(): object {
|
|
47
|
+
// Reply with a greeting, the current time, the url, and request headers
|
|
48
|
+
return {
|
|
49
|
+
greeting: 'Hello from LoopBack',
|
|
50
|
+
date: new Date(),
|
|
51
|
+
url: this.req.url,
|
|
52
|
+
headers: Object.assign({}, this.req.headers),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {ApplicationConfig, <%= project.applicationName %>} from './application';
|
|
2
|
+
|
|
3
|
+
export * from './application';
|
|
4
|
+
|
|
5
|
+
export async function main(options: ApplicationConfig = {}) {
|
|
6
|
+
const app = new <%= project.applicationName %>(options);
|
|
7
|
+
await app.boot();
|
|
8
|
+
await app.start();
|
|
9
|
+
|
|
10
|
+
const url = app.restServer.url;
|
|
11
|
+
console.log(`Server is running at ${url}`);
|
|
12
|
+
console.log(`Try ${url}/ping`);
|
|
13
|
+
|
|
14
|
+
return app;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (require.main === module) {
|
|
18
|
+
// Run the application
|
|
19
|
+
const config = {
|
|
20
|
+
rest: {
|
|
21
|
+
port: +(process.env.PORT ?? 3000),
|
|
22
|
+
host: process.env.HOST,
|
|
23
|
+
// The `gracePeriodForClose` provides a graceful close for http/https
|
|
24
|
+
// servers with keep-alive clients. The default value is `Infinity`
|
|
25
|
+
// (don't force-close). If you want to immediately destroy all sockets
|
|
26
|
+
// upon stop, set its value to `0`.
|
|
27
|
+
// See https://www.npmjs.com/package/stoppable
|
|
28
|
+
gracePeriodForClose: 5000, // 5 seconds
|
|
29
|
+
openApiSpec: {
|
|
30
|
+
// useful when used with OpenAPI-to-GraphQL to locate your application
|
|
31
|
+
setServersFromRequest: true,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
main(config).catch(err => {
|
|
36
|
+
console.error('Cannot start the application.', err);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {<%= project.applicationName %>} from './application';
|
|
2
|
+
|
|
3
|
+
export async function migrate(args: string[]) {
|
|
4
|
+
const existingSchema = args.includes('--rebuild') ? 'drop' : 'alter';
|
|
5
|
+
console.log('Migrating schemas (%s existing schema)', existingSchema);
|
|
6
|
+
|
|
7
|
+
const app = new <%= project.applicationName %>();
|
|
8
|
+
await app.boot();
|
|
9
|
+
await app.migrateSchema({existingSchema});
|
|
10
|
+
|
|
11
|
+
// Connectors usually keep a pool of opened connections,
|
|
12
|
+
// this keeps the process running even after all work is done.
|
|
13
|
+
// We need to exit explicitly.
|
|
14
|
+
process.exit(0);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
migrate(process.argv).catch(err => {
|
|
18
|
+
console.error('Cannot migrate database schema', err);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {ApplicationConfig} from '@loopback/core';
|
|
2
|
+
import {<%= project.applicationName %>} from './application';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Export the OpenAPI spec from the application
|
|
6
|
+
*/
|
|
7
|
+
async function exportOpenApiSpec(): Promise<void> {
|
|
8
|
+
const config: ApplicationConfig = {
|
|
9
|
+
rest: {
|
|
10
|
+
port: +(process.env.PORT ?? 3000),
|
|
11
|
+
host: process.env.HOST ?? 'localhost',
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
const outFile = process.argv[2] ?? '';
|
|
15
|
+
const app = new <%= project.applicationName %>(config);
|
|
16
|
+
await app.boot();
|
|
17
|
+
await app.exportOpenApiSpec(outFile);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
exportOpenApiSpec().catch(err => {
|
|
21
|
+
console.error('Fail to export OpenAPI spec from the application.', err);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
});
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2017,2020. 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
|
+
// no translation: Controller
|
|
7
|
+
'use strict';
|
|
8
|
+
const _ = require('lodash');
|
|
9
|
+
const ArtifactGenerator = require('../../lib/artifact-generator');
|
|
10
|
+
const debug = require('../../lib/debug')('controller-generator');
|
|
11
|
+
const inspect = require('util').inspect;
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const chalk = require('chalk');
|
|
14
|
+
const utils = require('../../lib/utils');
|
|
15
|
+
const g = require('../../lib/globalize');
|
|
16
|
+
|
|
17
|
+
// Exportable constants
|
|
18
|
+
module.exports = class ControllerGenerator extends ArtifactGenerator {
|
|
19
|
+
// Note: arguments and options should be defined in the constructor.
|
|
20
|
+
constructor(args, opts) {
|
|
21
|
+
super(args, opts);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static get BASIC() {
|
|
25
|
+
return g.f('Empty Controller');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static get REST() {
|
|
29
|
+
return g.f('REST Controller with CRUD functions');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
_setupGenerator() {
|
|
33
|
+
this.artifactInfo = {
|
|
34
|
+
type: 'controller',
|
|
35
|
+
rootDir: 'src',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// XXX(kjdelisle): These should be more extensible to allow custom paths
|
|
39
|
+
// for each artifact type.
|
|
40
|
+
|
|
41
|
+
this.artifactInfo.outDir = path.resolve(
|
|
42
|
+
this.artifactInfo.rootDir,
|
|
43
|
+
'controllers',
|
|
44
|
+
);
|
|
45
|
+
this.artifactInfo.modelDir = path.resolve(
|
|
46
|
+
this.artifactInfo.rootDir,
|
|
47
|
+
'models',
|
|
48
|
+
);
|
|
49
|
+
this.artifactInfo.repositoryDir = path.resolve(
|
|
50
|
+
this.artifactInfo.rootDir,
|
|
51
|
+
'repositories',
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
this.option('controllerType', {
|
|
55
|
+
type: String,
|
|
56
|
+
required: false,
|
|
57
|
+
description: g.f('Type for the %s', this.artifactInfo.type),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return super._setupGenerator();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
setOptions() {
|
|
64
|
+
return super.setOptions();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
checkLoopBackProject() {
|
|
68
|
+
if (this.shouldExit()) return;
|
|
69
|
+
return super.checkLoopBackProject();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
promptArtifactName() {
|
|
73
|
+
if (this.shouldExit()) return;
|
|
74
|
+
return super.promptArtifactName();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
promptArtifactType() {
|
|
78
|
+
debug('Prompting for controller type');
|
|
79
|
+
if (this.shouldExit()) return;
|
|
80
|
+
|
|
81
|
+
super.promptWarningMsgForName();
|
|
82
|
+
// inform user what controller/file names will be created
|
|
83
|
+
super.promptClassFileName(
|
|
84
|
+
'controller',
|
|
85
|
+
'controllers',
|
|
86
|
+
utils.toClassName(this.artifactInfo.name),
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
if (this.options.controllerType) {
|
|
90
|
+
Object.assign(this.artifactInfo, {
|
|
91
|
+
controllerType: this.options.controllerType,
|
|
92
|
+
});
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return this.prompt([
|
|
97
|
+
{
|
|
98
|
+
type: 'list',
|
|
99
|
+
name: 'controllerType',
|
|
100
|
+
message: g.f('What kind of controller would you like to generate?'),
|
|
101
|
+
when: this.artifactInfo.controllerType === undefined,
|
|
102
|
+
choices: [ControllerGenerator.BASIC, ControllerGenerator.REST],
|
|
103
|
+
default: ControllerGenerator.BASIC,
|
|
104
|
+
},
|
|
105
|
+
])
|
|
106
|
+
.then(props => {
|
|
107
|
+
Object.assign(this.artifactInfo, props);
|
|
108
|
+
return props;
|
|
109
|
+
})
|
|
110
|
+
.catch(err => {
|
|
111
|
+
debug(`Error during controller type prompt: ${err.stack}`);
|
|
112
|
+
return this.exit(err);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async promptArtifactCrudVars() {
|
|
117
|
+
if (this.shouldExit()) return;
|
|
118
|
+
if (
|
|
119
|
+
!this.artifactInfo.controllerType ||
|
|
120
|
+
this.artifactInfo.controllerType === ControllerGenerator.BASIC
|
|
121
|
+
) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
let modelList, repositoryList;
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
modelList = await utils.getArtifactList(
|
|
129
|
+
this.artifactInfo.modelDir,
|
|
130
|
+
'model',
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
repositoryList = await utils.getArtifactList(
|
|
134
|
+
this.artifactInfo.repositoryDir,
|
|
135
|
+
'repository',
|
|
136
|
+
true,
|
|
137
|
+
);
|
|
138
|
+
} catch (err) {
|
|
139
|
+
return this.exit(err);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (_.isEmpty(modelList)) {
|
|
143
|
+
const file = g.f('No models found in %s. ', this.artifactInfo.modelDir);
|
|
144
|
+
const site = g.f(
|
|
145
|
+
'Please visit http://loopback.io/doc/en/lb4/Controller-generator.html for information on how models are discovered.',
|
|
146
|
+
);
|
|
147
|
+
return this.exit(file + chalk.yellow(site));
|
|
148
|
+
}
|
|
149
|
+
if (_.isEmpty(repositoryList)) {
|
|
150
|
+
const file = g.f(
|
|
151
|
+
'No repositories found in %s. ',
|
|
152
|
+
this.artifactInfo.repositoryDir,
|
|
153
|
+
);
|
|
154
|
+
const site = g.f(
|
|
155
|
+
'Please visit http://loopback.io/doc/en/lb4/Controller-generator.html for information on how repositories are discovered.',
|
|
156
|
+
);
|
|
157
|
+
return this.exit(file + chalk.yellow(site));
|
|
158
|
+
}
|
|
159
|
+
return this.prompt([
|
|
160
|
+
{
|
|
161
|
+
type: 'list',
|
|
162
|
+
name: 'modelName',
|
|
163
|
+
message: g.f(
|
|
164
|
+
'What is the name of the model to use with this CRUD repository?',
|
|
165
|
+
),
|
|
166
|
+
choices: modelList,
|
|
167
|
+
when: this.artifactInfo.modelName === undefined,
|
|
168
|
+
default: modelList[0],
|
|
169
|
+
validate: utils.validateClassName,
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
type: 'list',
|
|
173
|
+
name: 'repositoryName',
|
|
174
|
+
message: g.f('What is the name of your CRUD repository?'),
|
|
175
|
+
choices: repositoryList,
|
|
176
|
+
when: this.artifactInfo.repositoryName === undefined,
|
|
177
|
+
default: repositoryList[0],
|
|
178
|
+
validate: utils.validateClassName,
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
type: 'input',
|
|
182
|
+
name: 'id',
|
|
183
|
+
message: g.f('What is the name of ID property?'),
|
|
184
|
+
when: this.artifactInfo.id === undefined,
|
|
185
|
+
default: 'id',
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
type: 'list',
|
|
189
|
+
name: 'idType',
|
|
190
|
+
message: g.f('What is the type of your ID?'),
|
|
191
|
+
choices: ['number', 'string', 'object'],
|
|
192
|
+
when: this.artifactInfo.idType === undefined,
|
|
193
|
+
default: 'number',
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
type: 'confirm',
|
|
197
|
+
name: 'idOmitted',
|
|
198
|
+
message: g.f('Is the id omitted when creating a new instance?'),
|
|
199
|
+
default: true,
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
type: 'input',
|
|
203
|
+
name: 'httpPathName',
|
|
204
|
+
message: g.f('What is the base HTTP path name of the CRUD operations?'),
|
|
205
|
+
when: this.artifactInfo.httpPathName === undefined,
|
|
206
|
+
default: answers =>
|
|
207
|
+
utils.prependBackslash(
|
|
208
|
+
utils.pluralize(utils.urlSlug(answers.modelName)),
|
|
209
|
+
),
|
|
210
|
+
validate: utils.validateUrlSlug,
|
|
211
|
+
filter: utils.prependBackslash,
|
|
212
|
+
},
|
|
213
|
+
])
|
|
214
|
+
.then(props => {
|
|
215
|
+
debug(`props: ${inspect(props)}`);
|
|
216
|
+
Object.assign(this.artifactInfo, props);
|
|
217
|
+
// Ensure that the artifact names are valid.
|
|
218
|
+
[
|
|
219
|
+
this.artifactInfo.name,
|
|
220
|
+
this.artifactInfo.modelName,
|
|
221
|
+
this.artifactInfo.repositoryName,
|
|
222
|
+
].forEach(item => {
|
|
223
|
+
item = utils.toClassName(item);
|
|
224
|
+
});
|
|
225
|
+
// Create camel-case names for variables.
|
|
226
|
+
this.artifactInfo.repositoryNameCamel = utils.camelCase(
|
|
227
|
+
this.artifactInfo.repositoryName,
|
|
228
|
+
);
|
|
229
|
+
return props;
|
|
230
|
+
})
|
|
231
|
+
.catch(err => {
|
|
232
|
+
debug(`Error during prompt for controller variables: ${err}`);
|
|
233
|
+
return this.exit(err);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
scaffold() {
|
|
238
|
+
// We don't want to call the base scaffold function since it copies
|
|
239
|
+
// all of the templates!
|
|
240
|
+
if (this.shouldExit()) return false;
|
|
241
|
+
this.artifactInfo.className = utils.toClassName(this.artifactInfo.name);
|
|
242
|
+
this.artifactInfo.outFile =
|
|
243
|
+
utils.toFileName(this.artifactInfo.name) + '.controller.ts';
|
|
244
|
+
if (debug.enabled) {
|
|
245
|
+
debug(`Artifact output filename set to: ${this.artifactInfo.outFile}`);
|
|
246
|
+
}
|
|
247
|
+
this.artifactInfo.modelVariableName = utils.toVarName(
|
|
248
|
+
this.artifactInfo.modelName || '',
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
// renames the file
|
|
252
|
+
let template = 'controller-template.ts.ejs';
|
|
253
|
+
switch (this.artifactInfo.controllerType) {
|
|
254
|
+
case ControllerGenerator.REST:
|
|
255
|
+
template = 'controller-rest-template.ts.ejs';
|
|
256
|
+
break;
|
|
257
|
+
default:
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
const source = this.templatePath(path.join('src', 'controllers', template));
|
|
261
|
+
if (debug.enabled) {
|
|
262
|
+
debug(`Using template at: ${source}`);
|
|
263
|
+
}
|
|
264
|
+
const dest = this.destinationPath(
|
|
265
|
+
path.join(this.artifactInfo.outDir, this.artifactInfo.outFile),
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
if (debug.enabled) {
|
|
269
|
+
debug(`artifactInfo: ${inspect(this.artifactInfo)}`);
|
|
270
|
+
debug(`Copying artifact to: ${dest}`);
|
|
271
|
+
}
|
|
272
|
+
this.copyTemplatedFiles(source, dest, this.artifactInfo);
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
async end() {
|
|
277
|
+
await super.end();
|
|
278
|
+
}
|
|
279
|
+
};
|