@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.
Files changed (159) hide show
  1. package/.yo-rc.json +1697 -0
  2. package/{generators/project/templates/LICENSE → LICENSE} +2 -1
  3. package/README.md +44 -43
  4. package/bin/cli-main.js +61 -0
  5. package/generators/app/index.js +109 -15
  6. package/generators/app/templates/.dockerignore +5 -0
  7. package/generators/app/templates/Dockerfile +28 -0
  8. package/generators/app/templates/README.md.ejs +130 -0
  9. package/generators/app/templates/public/index.html.ejs +88 -0
  10. package/generators/app/templates/{test → src/__tests__}/README.md +0 -1
  11. package/generators/app/templates/src/__tests__/acceptance/home-page.acceptance.ts.ejs +31 -0
  12. package/generators/app/templates/src/__tests__/acceptance/ping.controller.acceptance.ts.ejs +21 -0
  13. package/generators/app/templates/src/__tests__/acceptance/test-helper.ts.ejs +32 -0
  14. package/generators/app/templates/src/application.ts.ejs +70 -0
  15. package/generators/app/templates/src/controllers/README.md +6 -0
  16. package/generators/app/templates/src/controllers/index.ts.ejs +1 -0
  17. package/generators/app/templates/src/controllers/ping.controller.ts.ejs +55 -0
  18. package/generators/app/templates/src/datasources/README.md +3 -0
  19. package/generators/app/templates/src/index.ts.ejs +39 -0
  20. package/generators/app/templates/src/migrate.ts.ejs +20 -0
  21. package/generators/app/templates/src/models/README.md +3 -0
  22. package/generators/app/templates/src/openapi-spec.ts.ejs +23 -0
  23. package/generators/app/templates/src/sequence.ts.ejs +3 -0
  24. package/generators/controller/index.js +279 -0
  25. package/generators/controller/templates/src/controllers/controller-rest-template.ts.ejs +150 -0
  26. package/generators/controller/templates/src/controllers/controller-template.ts.ejs +8 -0
  27. package/generators/copyright/fs.js +46 -0
  28. package/generators/copyright/git.js +78 -0
  29. package/generators/copyright/header.js +306 -0
  30. package/generators/copyright/index.js +230 -0
  31. package/generators/copyright/license.js +105 -0
  32. package/generators/datasource/index.js +341 -0
  33. package/generators/datasource/templates/datasource.ts.ejs +22 -0
  34. package/generators/discover/import-discovered-model.js +70 -0
  35. package/generators/discover/index.js +349 -0
  36. package/generators/example/downloader.js +16 -0
  37. package/generators/example/index.js +176 -0
  38. package/generators/extension/index.js +34 -5
  39. package/generators/extension/templates/README.md.ejs +32 -0
  40. package/generators/extension/templates/{test → src/__tests__}/acceptance/README.md +0 -0
  41. package/generators/extension/templates/{test → src/__tests__}/integration/README.md +0 -0
  42. package/generators/extension/templates/{test → src/__tests__}/unit/README.md +0 -0
  43. package/generators/extension/templates/src/component.ts.ejs +22 -0
  44. package/generators/extension/templates/src/controllers/README.md +3 -2
  45. package/generators/extension/templates/src/decorators/README.md +10 -4
  46. package/generators/extension/templates/src/index.ts.ejs +3 -0
  47. package/generators/extension/templates/src/keys.ts.ejs +11 -0
  48. package/generators/extension/templates/src/mixins/README.md +77 -21
  49. package/generators/extension/templates/src/providers/README.md +51 -25
  50. package/generators/extension/templates/src/repositories/README.md +1 -1
  51. package/generators/extension/templates/src/types.ts.ejs +15 -0
  52. package/generators/import-lb3-models/index.js +197 -0
  53. package/generators/import-lb3-models/lb3app-loader.js +31 -0
  54. package/generators/import-lb3-models/migrate-model.js +249 -0
  55. package/generators/import-lb3-models/model-names.js +32 -0
  56. package/generators/interceptor/index.js +178 -0
  57. package/generators/interceptor/templates/interceptor-template.ts.ejs +62 -0
  58. package/generators/model/index.js +536 -0
  59. package/generators/model/property-definition.js +85 -0
  60. package/generators/model/templates/model.ts.ejs +42 -0
  61. package/generators/observer/index.js +132 -0
  62. package/generators/observer/templates/observer-template.ts.ejs +40 -0
  63. package/generators/openapi/README.md +211 -0
  64. package/generators/openapi/index.js +535 -0
  65. package/generators/openapi/schema-helper.js +447 -0
  66. package/generators/openapi/spec-helper.js +484 -0
  67. package/generators/openapi/spec-loader.js +75 -0
  68. package/generators/openapi/templates/src/controllers/controller-template.ts.ejs +43 -0
  69. package/generators/openapi/templates/src/datasources/datasource.ts.ejs +42 -0
  70. package/generators/openapi/templates/src/models/model-template.ts.ejs +71 -0
  71. package/generators/openapi/templates/src/models/type-template.ts.ejs +13 -0
  72. package/generators/openapi/templates/src/services/service-proxy-template.ts.ejs +55 -0
  73. package/generators/openapi/utils.js +322 -0
  74. package/generators/project/templates/.eslintignore +4 -0
  75. package/generators/project/templates/.eslintrc.js.ejs +3 -0
  76. package/generators/project/templates/.mocharc.json +5 -0
  77. package/generators/project/templates/.prettierignore +0 -2
  78. package/generators/project/templates/.prettierrc +2 -1
  79. package/generators/project/templates/.vscode/launch.json +38 -0
  80. package/generators/project/templates/.vscode/settings.json +32 -0
  81. package/generators/project/templates/.vscode/tasks.json +29 -0
  82. package/generators/project/templates/DEVELOPING.md +36 -0
  83. package/generators/project/templates/_.gitignore +3 -5
  84. package/generators/project/templates/package.json.ejs +175 -0
  85. package/generators/project/templates/package.plain.json.ejs +176 -0
  86. package/generators/project/templates/tsconfig.json.ejs +39 -0
  87. package/generators/relation/base-relation.generator.js +220 -0
  88. package/generators/relation/belongs-to-relation.generator.js +196 -0
  89. package/generators/relation/has-many-relation.generator.js +200 -0
  90. package/generators/relation/has-many-through-relation.generator.js +331 -0
  91. package/generators/relation/has-one-relation.generator.js +200 -0
  92. package/generators/relation/index.js +795 -0
  93. package/generators/relation/references-many-relation.generator.js +142 -0
  94. package/generators/relation/templates/controller-relation-template-belongs-to.ts.ejs +38 -0
  95. package/generators/relation/templates/controller-relation-template-has-many-through.ts.ejs +110 -0
  96. package/generators/relation/templates/controller-relation-template-has-many.ts.ejs +110 -0
  97. package/generators/relation/templates/controller-relation-template-has-one.ts.ejs +110 -0
  98. package/generators/relation/utils.generator.js +260 -0
  99. package/generators/repository/index.js +576 -0
  100. package/generators/repository/templates/src/repositories/repository-crud-default-template.ts.ejs +21 -0
  101. package/generators/repository/templates/src/repositories/repository-kv-template.ts.ejs +19 -0
  102. package/generators/rest-crud/crud-rest-component.js +63 -0
  103. package/generators/rest-crud/index.js +401 -0
  104. package/generators/rest-crud/templates/src/model-endpoints/model.rest-config-template.ts.ejs +10 -0
  105. package/generators/service/index.js +351 -0
  106. package/generators/service/templates/local-service-class-template.ts.ejs +10 -0
  107. package/generators/service/templates/local-service-provider-template.ts.ejs +19 -0
  108. package/generators/service/templates/remote-service-proxy-template.ts.ejs +21 -0
  109. package/generators/update/index.js +55 -0
  110. package/intl/cs/messages.json +204 -0
  111. package/intl/de/messages.json +204 -0
  112. package/intl/en/messages.json +204 -0
  113. package/intl/es/messages.json +204 -0
  114. package/intl/fr/messages.json +204 -0
  115. package/intl/it/messages.json +204 -0
  116. package/intl/ja/messages.json +204 -0
  117. package/intl/ko/messages.json +204 -0
  118. package/intl/nl/messages.json +204 -0
  119. package/intl/pl/messages.json +204 -0
  120. package/intl/pt/messages.json +204 -0
  121. package/intl/ru/messages.json +204 -0
  122. package/intl/tr/messages.json +204 -0
  123. package/intl/zh-Hans/messages.json +204 -0
  124. package/intl/zh-Hant/messages.json +204 -0
  125. package/lib/artifact-generator.js +189 -0
  126. package/lib/ast-helper.js +214 -0
  127. package/lib/base-generator.js +509 -0
  128. package/lib/cli.js +233 -0
  129. package/lib/connectors.json +894 -0
  130. package/lib/debug.js +16 -0
  131. package/lib/globalize.js +12 -0
  132. package/lib/model-discoverer.js +118 -0
  133. package/lib/project-generator.js +154 -57
  134. package/lib/tab-completion.js +127 -0
  135. package/lib/update-index.js +44 -0
  136. package/lib/utils.js +746 -22
  137. package/lib/version-helper.js +299 -0
  138. package/package.json +183 -32
  139. package/CHANGELOG.md +0 -64
  140. package/bin/cli.js +0 -65
  141. package/generators/app/templates/index.js +0 -14
  142. package/generators/app/templates/src/application.ts +0 -27
  143. package/generators/app/templates/src/controllers/ping-controller.ts +0 -25
  144. package/generators/app/templates/src/index.ts +0 -25
  145. package/generators/app/templates/test/ping-controller.test.ts +0 -46
  146. package/generators/extension/templates/index.js +0 -8
  147. package/generators/extension/templates/src/component.ts +0 -14
  148. package/generators/extension/templates/src/index.ts +0 -6
  149. package/generators/project/templates/.npmrc +0 -1
  150. package/generators/project/templates/.yo-rc.json +0 -1
  151. package/generators/project/templates/README.md +0 -4
  152. package/generators/project/templates/index.d.ts +0 -6
  153. package/generators/project/templates/index.ts +0 -11
  154. package/generators/project/templates/package.json +0 -79
  155. package/generators/project/templates/package.plain.json +0 -82
  156. package/generators/project/templates/test/mocha.opts +0 -1
  157. package/generators/project/templates/tsconfig.json +0 -29
  158. package/generators/project/templates/tslint.build.json +0 -17
  159. package/generators/project/templates/tslint.json +0 -33
@@ -0,0 +1,331 @@
1
+ // Copyright IBM Corp. 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
+ 'use strict';
7
+
8
+ const ast = require('ts-morph');
9
+ const path = require('path');
10
+ const BaseRelationGenerator = require('./base-relation.generator');
11
+ const relationUtils = require('./utils.generator');
12
+ const utils = require('../../lib/utils');
13
+
14
+ const CONTROLLER_TEMPLATE_PATH_HAS_MANY_THROUGH =
15
+ 'controller-relation-template-has-many-through.ts.ejs';
16
+
17
+ module.exports = class HasManyThroughRelationGenerator extends (
18
+ BaseRelationGenerator
19
+ ) {
20
+ constructor(args, opts) {
21
+ super(args, opts);
22
+ }
23
+
24
+ async generateControllers(options) {
25
+ this.artifactInfo.sourceModelClassName = options.sourceModel;
26
+ this.artifactInfo.targetModelClassName = options.destinationModel;
27
+ this.artifactInfo.throughModelClassName = options.throughModel;
28
+ // source
29
+ this.artifactInfo.sourceRepositoryClassName =
30
+ this.artifactInfo.sourceModelClassName + 'Repository';
31
+ this.artifactInfo.controllerClassName =
32
+ this.artifactInfo.sourceModelClassName +
33
+ this.artifactInfo.targetModelClassName +
34
+ 'Controller';
35
+ this.artifactInfo.paramSourceRepository = utils.camelCase(
36
+ this.artifactInfo.sourceModelClassName + 'Repository',
37
+ );
38
+
39
+ this.artifactInfo.sourceModelName = utils.toFileName(options.sourceModel);
40
+ this.artifactInfo.sourceModelPath = utils.pluralize(
41
+ this.artifactInfo.sourceModelName,
42
+ );
43
+ // through
44
+ this.artifactInfo.throughRepositoryClassName =
45
+ this.artifactInfo.throughModelClassName + 'Repository';
46
+ this.artifactInfo.paramThroughRepository = utils.camelCase(
47
+ this.artifactInfo.throughModelClassName + 'Repository',
48
+ );
49
+ this.artifactInfo.throughModelName = utils.toFileName(options.throughModel);
50
+ // target
51
+ this.artifactInfo.targetModelName = utils.toFileName(
52
+ options.destinationModel,
53
+ );
54
+ this.artifactInfo.targetRepositoryClassName =
55
+ this.artifactInfo.targetModelName + 'Repository';
56
+ this.artifactInfo.paramTargetRepository = utils.camelCase(
57
+ this.artifactInfo.targetModelName + 'Repository',
58
+ );
59
+ this.artifactInfo.targetModelPath = utils.pluralize(
60
+ this.artifactInfo.targetModelName,
61
+ );
62
+ this.artifactInfo.targetModelRequestBody = utils.camelCase(
63
+ this.artifactInfo.targetModelName,
64
+ );
65
+ this.artifactInfo.relationPropertyName = options.relationName;
66
+
67
+ this.artifactInfo.sourceModelPrimaryKey = options.sourceModelPrimaryKey;
68
+ this.artifactInfo.sourceModelPrimaryKeyType =
69
+ options.sourceModelPrimaryKeyType;
70
+
71
+ this.artifactInfo.targetModelPrimaryKey =
72
+ options.destinationModelPrimaryKey;
73
+ this.artifactInfo.foreignKeyName = options.foreignKeyName;
74
+ const source = this.templatePath(CONTROLLER_TEMPLATE_PATH_HAS_MANY_THROUGH);
75
+
76
+ this.artifactInfo.name =
77
+ options.sourceModel + '-' + options.destinationModel;
78
+ this.artifactInfo.outFile =
79
+ utils.toFileName(this.artifactInfo.name) + '.controller.ts';
80
+ const dest = this.destinationPath(
81
+ path.join(this.artifactInfo.outDir, this.artifactInfo.outFile),
82
+ );
83
+
84
+ this.copyTemplatedFiles(source, dest, this.artifactInfo);
85
+ await relationUtils.addExportController(
86
+ this,
87
+ path.resolve(this.artifactInfo.outDir, 'index.ts'),
88
+ this.artifactInfo.controllerClassName,
89
+ utils.toFileName(this.artifactInfo.name) + '.controller',
90
+ );
91
+ }
92
+
93
+ async generateModels(options) {
94
+ // for repo to generate relation name
95
+ this.artifactInfo.relationName = options.relationName;
96
+ const modelDir = this.artifactInfo.modelDir;
97
+ const sourceModel = options.sourceModel;
98
+ const throughModel = options.throughModel;
99
+ const targetModel = options.destinationModel;
100
+ // hasManyThrough is part of hasMany
101
+ const relationType = 'hasMany';
102
+ const relationName = options.relationName;
103
+ const sourceKey = options.sourceKeyOnThrough;
104
+ const targetKey = options.targetKeyOnThrough;
105
+ const dftSourceKey = options.defaultSourceKeyOnThrough;
106
+ const dftTargetKey = options.defaultTargetKeyOnThrough;
107
+ const sourceKeyType = options.sourceModelPrimaryKeyType;
108
+ const targetKeyType = options.destinationModelPrimaryKeyType;
109
+
110
+ // checks if both target and source key exist in through model
111
+ const project = new relationUtils.AstLoopBackProject();
112
+ const throughFile = relationUtils.addFileToProject(
113
+ project,
114
+ modelDir,
115
+ throughModel,
116
+ );
117
+
118
+ const throughClass = relationUtils.getClassObj(throughFile, throughModel);
119
+ const doesSourceKeyExist = relationUtils.doesPropertyExist(
120
+ throughClass,
121
+ sourceKey,
122
+ );
123
+ const doesTargetKeyExist = relationUtils.doesPropertyExist(
124
+ throughClass,
125
+ targetKey,
126
+ );
127
+
128
+ let modelProperty;
129
+ // checks if the relation name already exists
130
+ const sourceFile = relationUtils.addFileToProject(
131
+ project,
132
+ modelDir,
133
+ sourceModel,
134
+ );
135
+ const sourceClass = relationUtils.getClassObj(sourceFile, sourceModel);
136
+ relationUtils.doesRelationExist(sourceClass, relationName);
137
+ // add the relation to the source model
138
+ const isDefaultSourceKey = sourceKey === dftSourceKey;
139
+ const isDefaultTargetKey = targetKey === dftTargetKey;
140
+ modelProperty = this.getHasManyThrough(
141
+ targetModel,
142
+ throughModel,
143
+ relationName,
144
+ isDefaultSourceKey,
145
+ sourceKey,
146
+ isDefaultTargetKey,
147
+ targetKey,
148
+ );
149
+ relationUtils.addProperty(sourceClass, modelProperty);
150
+ let imports;
151
+ // no need to import target model for self-through case
152
+ if (!(sourceModel === targetModel)) {
153
+ imports = relationUtils.getRequiredImports(targetModel, relationType);
154
+ relationUtils.addRequiredImports(sourceFile, imports);
155
+ }
156
+ imports = relationUtils.getRequiredImports(throughModel, relationType);
157
+ relationUtils.addRequiredImports(sourceFile, imports);
158
+ await sourceFile.save();
159
+
160
+ // checks if fks exist in through
161
+ if (doesSourceKeyExist) {
162
+ if (
163
+ !relationUtils.isValidPropertyType(
164
+ throughClass,
165
+ sourceKey,
166
+ sourceKeyType,
167
+ )
168
+ ) {
169
+ throw new Error('SourceKeyOnThrough Type Error');
170
+ }
171
+ } else {
172
+ modelProperty = relationUtils.addForeignKey(sourceKey, sourceKeyType);
173
+ relationUtils.addProperty(throughClass, modelProperty);
174
+ throughClass.formatText();
175
+ }
176
+
177
+ if (doesTargetKeyExist) {
178
+ if (
179
+ !relationUtils.isValidPropertyType(
180
+ throughClass,
181
+ targetKey,
182
+ targetKeyType,
183
+ )
184
+ ) {
185
+ throw new Error('TargetKeyOnThrough Type Error');
186
+ }
187
+ } else {
188
+ modelProperty = relationUtils.addForeignKey(targetKey, targetKeyType);
189
+ relationUtils.addProperty(throughClass, modelProperty);
190
+ throughClass.formatText();
191
+ await throughFile.save();
192
+ }
193
+ }
194
+
195
+ getHasManyThrough(
196
+ targetClass,
197
+ throughModel,
198
+ relationName,
199
+ isDefaultSourceKey,
200
+ sourceKey,
201
+ isDefaultTargetKey,
202
+ targetKey,
203
+ ) {
204
+ let keyFrom = '';
205
+ let keyTo = '';
206
+ if (!isDefaultSourceKey) {
207
+ keyFrom = `, keyFrom: '${sourceKey}'`;
208
+ }
209
+ if (!isDefaultTargetKey) {
210
+ keyTo = `, keyTo: '${targetKey}'`;
211
+ }
212
+
213
+ const relationDecorator = [
214
+ {
215
+ name: 'hasMany',
216
+ arguments: [
217
+ `() => ${targetClass}, {through: {model: () => ${throughModel}${keyFrom}${keyTo}}}`,
218
+ ],
219
+ },
220
+ ];
221
+ return {
222
+ decorators: relationDecorator,
223
+ name: relationName,
224
+ type: targetClass + '[]',
225
+ };
226
+ }
227
+
228
+ _addThroughRepoToRepositoryConstructor(repositoryConstructor) {
229
+ const throughRepoGetterName =
230
+ utils.camelCase(this.artifactInfo.throughRepoClassName) + 'Getter';
231
+
232
+ if (
233
+ relationUtils.doesParameterExist(
234
+ repositoryConstructor,
235
+ throughRepoGetterName,
236
+ )
237
+ ) {
238
+ // no need to check if the getter already exists
239
+ return;
240
+ }
241
+
242
+ repositoryConstructor.addParameter({
243
+ decorators: [
244
+ {
245
+ name: 'repository.getter',
246
+ arguments: ["'" + this.artifactInfo.throughRepoClassName + "'"],
247
+ },
248
+ ],
249
+ name: throughRepoGetterName,
250
+ type: 'Getter<' + this.artifactInfo.throughRepoClassName + '>,',
251
+ scope: ast.Scope.Protected,
252
+ });
253
+ }
254
+
255
+ _getRepositoryRequiredImports(dstModelClassName, dstRepositoryClassName) {
256
+ const throughModel = this.artifactInfo.throughModelClass;
257
+ const sourceModel = this.artifactInfo.srcModelClass;
258
+ const throughRepoClassName = this.artifactInfo.throughRepoClassName;
259
+ this.artifactInfo.throughRepoClassName = throughRepoClassName;
260
+ const importsArray = [
261
+ {
262
+ name: dstModelClassName,
263
+ module: '../models',
264
+ },
265
+ {
266
+ name: throughModel,
267
+ module: '../models',
268
+ },
269
+ {
270
+ name: 'repository',
271
+ module: '@loopback/repository',
272
+ },
273
+ {
274
+ name: 'Getter',
275
+ module: '@loopback/core',
276
+ },
277
+ {
278
+ name: throughRepoClassName,
279
+ module: `./${utils.toFileName(throughModel)}.repository`,
280
+ },
281
+ {
282
+ name: 'HasManyThroughRepositoryFactory',
283
+ module: '@loopback/repository',
284
+ },
285
+ ];
286
+ if (!(sourceModel === dstModelClassName)) {
287
+ importsArray.push({
288
+ name: dstRepositoryClassName,
289
+ module: `./${utils.toFileName(dstModelClassName)}.repository`,
290
+ });
291
+ }
292
+ return importsArray;
293
+ }
294
+
295
+ _getRepositoryRelationPropertyName() {
296
+ return this.artifactInfo.relationName;
297
+ }
298
+
299
+ _getRepositoryRelationPropertyType() {
300
+ return `HasManyThroughRepositoryFactory<${utils.toClassName(
301
+ this.artifactInfo.dstModelClass,
302
+ )}, typeof ${utils.toClassName(
303
+ this.artifactInfo.dstModelClass,
304
+ )}.prototype.${this.artifactInfo.dstModelPrimaryKey},
305
+ ${utils.toClassName(this.artifactInfo.throughModelClass)},
306
+ typeof ${utils.toClassName(this.artifactInfo.srcModelClass)}.prototype.${
307
+ this.artifactInfo.srcModelPrimaryKey
308
+ }
309
+ >`;
310
+ }
311
+
312
+ _addCreatorToRepositoryConstructor(classConstructor) {
313
+ const relationPropertyName = this._getRepositoryRelationPropertyName();
314
+ const statement =
315
+ `this.${relationPropertyName} = ` +
316
+ `this.createHasManyThroughRepositoryFactoryFor('${relationPropertyName}', ` +
317
+ `${utils.camelCase(this.artifactInfo.dstRepositoryClassName)}Getter, ` +
318
+ `${utils.camelCase(this.artifactInfo.throughRepoClassName)}Getter,);`;
319
+ classConstructor.insertStatements(1, statement);
320
+ }
321
+
322
+ _registerInclusionResolverForRelation(classConstructor, options) {
323
+ const relationPropertyName = this._getRepositoryRelationPropertyName();
324
+ if (options.registerInclusionResolver) {
325
+ const statement =
326
+ `this.registerInclusionResolver(` +
327
+ `'${relationPropertyName}', this.${relationPropertyName}.inclusionResolver);`;
328
+ classConstructor.insertStatements(2, statement);
329
+ }
330
+ }
331
+ };
@@ -0,0 +1,200 @@
1
+ // Copyright IBM Corp. 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
+ 'use strict';
7
+
8
+ const path = require('path');
9
+ const BaseRelationGenerator = require('./base-relation.generator');
10
+ const relationUtils = require('./utils.generator');
11
+ const utils = require('../../lib/utils');
12
+
13
+ const CONTROLLER_TEMPLATE_PATH_HAS_ONE =
14
+ 'controller-relation-template-has-one.ts.ejs';
15
+
16
+ module.exports = class HasOneRelationGenerator extends BaseRelationGenerator {
17
+ constructor(args, opts) {
18
+ super(args, opts);
19
+ }
20
+
21
+ async generateControllers(options) {
22
+ this.artifactInfo.sourceModelClassName = options.sourceModel;
23
+ this.artifactInfo.targetModelClassName = options.destinationModel;
24
+ this.artifactInfo.sourceRepositoryClassName =
25
+ this.artifactInfo.sourceModelClassName + 'Repository';
26
+ this.artifactInfo.controllerClassName =
27
+ this.artifactInfo.sourceModelClassName +
28
+ this.artifactInfo.targetModelClassName +
29
+ 'Controller';
30
+ this.artifactInfo.paramSourceRepository = utils.camelCase(
31
+ this.artifactInfo.sourceModelClassName + 'Repository',
32
+ );
33
+
34
+ this.artifactInfo.sourceModelName = utils.toFileName(options.sourceModel);
35
+ this.artifactInfo.sourceModelPath = utils.pluralize(
36
+ this.artifactInfo.sourceModelName,
37
+ );
38
+ this.artifactInfo.targetModelName = utils.toFileName(
39
+ options.destinationModel,
40
+ );
41
+ this.artifactInfo.targetModelPath = this.artifactInfo.targetModelName;
42
+ this.artifactInfo.targetModelRequestBody = utils.camelCase(
43
+ this.artifactInfo.targetModelName,
44
+ );
45
+ this.artifactInfo.relationPropertyName = options.relationName;
46
+ this.artifactInfo.sourceModelPrimaryKey = options.sourceModelPrimaryKey;
47
+ this.artifactInfo.sourceModelPrimaryKeyType =
48
+ options.sourceModelPrimaryKeyType;
49
+ this.artifactInfo.targetModelPrimaryKey =
50
+ options.destinationModelPrimaryKey;
51
+ this.artifactInfo.foreignKeyName = options.foreignKeyName;
52
+
53
+ const source = this.templatePath(CONTROLLER_TEMPLATE_PATH_HAS_ONE);
54
+
55
+ this.artifactInfo.name =
56
+ options.sourceModel + '-' + options.destinationModel;
57
+ this.artifactInfo.outFile =
58
+ utils.toFileName(this.artifactInfo.name) + '.controller.ts';
59
+
60
+ const dest = this.destinationPath(
61
+ path.join(this.artifactInfo.outDir, this.artifactInfo.outFile),
62
+ );
63
+
64
+ this.copyTemplatedFiles(source, dest, this.artifactInfo);
65
+ await relationUtils.addExportController(
66
+ this,
67
+ path.resolve(this.artifactInfo.outDir, 'index.ts'),
68
+ this.artifactInfo.controllerClassName,
69
+ utils.toFileName(this.artifactInfo.name) + '.controller',
70
+ );
71
+ }
72
+
73
+ async generateModels(options) {
74
+ // for repo to generate relation name
75
+ this.artifactInfo.relationName = options.relationName;
76
+ const modelDir = this.artifactInfo.modelDir;
77
+ const sourceModel = options.sourceModel;
78
+
79
+ const targetModel = options.destinationModel;
80
+
81
+ const relationType = options.relationType;
82
+ const relationName = options.relationName;
83
+ const fktype = options.sourceModelPrimaryKeyType;
84
+ const isForeignKeyExist = options.doesForeignKeyExist;
85
+ const foreignKeyName = options.foreignKeyName;
86
+
87
+ const isDefaultForeignKey =
88
+ foreignKeyName === utils.camelCase(options.sourceModel) + 'Id';
89
+
90
+ let modelProperty;
91
+ const project = new relationUtils.AstLoopBackProject();
92
+
93
+ const sourceFile = relationUtils.addFileToProject(
94
+ project,
95
+ modelDir,
96
+ sourceModel,
97
+ );
98
+ const sourceClass = relationUtils.getClassObj(sourceFile, sourceModel);
99
+ relationUtils.doesRelationExist(sourceClass, relationName);
100
+
101
+ modelProperty = this.getHasOne(
102
+ targetModel,
103
+ relationName,
104
+ isDefaultForeignKey,
105
+ foreignKeyName,
106
+ );
107
+
108
+ relationUtils.addProperty(sourceClass, modelProperty);
109
+ const imports = relationUtils.getRequiredImports(targetModel, relationType);
110
+
111
+ relationUtils.addRequiredImports(sourceFile, imports);
112
+ await sourceFile.save();
113
+
114
+ const targetFile = relationUtils.addFileToProject(
115
+ project,
116
+ modelDir,
117
+ targetModel,
118
+ );
119
+ const targetClass = relationUtils.getClassObj(targetFile, targetModel);
120
+
121
+ if (isForeignKeyExist) {
122
+ if (
123
+ !relationUtils.isValidPropertyType(targetClass, foreignKeyName, fktype)
124
+ ) {
125
+ throw new Error('foreignKey Type Error');
126
+ }
127
+ } else {
128
+ modelProperty = relationUtils.addForeignKey(foreignKeyName, fktype);
129
+ relationUtils.addProperty(targetClass, modelProperty);
130
+ targetClass.formatText();
131
+ await targetFile.save();
132
+ }
133
+ }
134
+
135
+ getHasOne(className, relationName, isDefaultForeignKey, foreignKeyName) {
136
+ let relationDecorator = [
137
+ {
138
+ name: 'hasOne',
139
+ arguments: [`() => ${className}, {keyTo: '${foreignKeyName}'}`],
140
+ },
141
+ ];
142
+ if (isDefaultForeignKey) {
143
+ relationDecorator = [
144
+ {
145
+ name: 'hasOne',
146
+ arguments: [`() => ${className}`],
147
+ },
148
+ ];
149
+ }
150
+
151
+ return {
152
+ decorators: relationDecorator,
153
+ name: relationName,
154
+ type: className,
155
+ };
156
+ }
157
+
158
+ _getRepositoryRequiredImports(dstModelClassName, dstRepositoryClassName) {
159
+ const importsArray = super._getRepositoryRequiredImports(
160
+ dstModelClassName,
161
+ dstRepositoryClassName,
162
+ );
163
+ importsArray.push({
164
+ name: 'HasOneRepositoryFactory',
165
+ module: '@loopback/repository',
166
+ });
167
+ return importsArray;
168
+ }
169
+
170
+ _getRepositoryRelationPropertyName() {
171
+ return this.artifactInfo.relationName;
172
+ }
173
+
174
+ _getRepositoryRelationPropertyType() {
175
+ return `HasOneRepositoryFactory<${utils.toClassName(
176
+ this.artifactInfo.dstModelClass,
177
+ )}, typeof ${utils.toClassName(
178
+ this.artifactInfo.srcModelClass,
179
+ )}.prototype.${this.artifactInfo.srcModelPrimaryKey}>`;
180
+ }
181
+
182
+ _addCreatorToRepositoryConstructor(classConstructor) {
183
+ const relationPropertyName = this._getRepositoryRelationPropertyName();
184
+ const statement =
185
+ `this.${relationPropertyName} = ` +
186
+ `this.createHasOneRepositoryFactoryFor('${relationPropertyName}', ` +
187
+ `${utils.camelCase(this.artifactInfo.dstRepositoryClassName)}Getter);`;
188
+ classConstructor.insertStatements(1, statement);
189
+ }
190
+
191
+ _registerInclusionResolverForRelation(classConstructor, options) {
192
+ const relationPropertyName = this._getRepositoryRelationPropertyName();
193
+ if (options.registerInclusionResolver) {
194
+ const statement =
195
+ `this.registerInclusionResolver(` +
196
+ `'${relationPropertyName}', this.${relationPropertyName}.inclusionResolver);`;
197
+ classConstructor.insertStatements(2, statement);
198
+ }
199
+ }
200
+ };