@rxap/plugin-nestjs 16.1.0-dev.8 → 16.1.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 (114) hide show
  1. package/CHANGELOG.md +385 -0
  2. package/README.md +127 -1
  3. package/generators.json +90 -0
  4. package/package.json +63 -42
  5. package/src/executors/package-json/executor.js +27 -13
  6. package/src/executors/package-json/executor.js.map +1 -1
  7. package/src/executors/package-json/schema.d.ts +3 -1
  8. package/src/executors/package-json/schema.json +11 -1
  9. package/src/generators/feature-microservice/generator.d.ts +4 -0
  10. package/src/generators/feature-microservice/generator.js +17 -0
  11. package/src/generators/feature-microservice/generator.js.map +1 -0
  12. package/src/generators/feature-microservice/index.d.ts +2 -0
  13. package/src/generators/feature-microservice/index.js +7 -0
  14. package/src/generators/feature-microservice/index.js.map +1 -0
  15. package/src/generators/feature-microservice/schema.d.ts +5 -0
  16. package/src/generators/feature-microservice/schema.json +23 -0
  17. package/src/generators/frontend-microservice/generator.d.ts +4 -0
  18. package/src/generators/frontend-microservice/generator.js +17 -0
  19. package/src/generators/frontend-microservice/generator.js.map +1 -0
  20. package/src/generators/frontend-microservice/index.d.ts +2 -0
  21. package/src/generators/frontend-microservice/index.js +7 -0
  22. package/src/generators/frontend-microservice/index.js.map +1 -0
  23. package/src/generators/frontend-microservice/schema.d.ts +6 -0
  24. package/src/generators/frontend-microservice/schema.json +29 -0
  25. package/src/generators/health-indicator/generator.d.ts +4 -0
  26. package/src/generators/health-indicator/generator.js +31 -0
  27. package/src/generators/health-indicator/generator.js.map +1 -0
  28. package/src/generators/health-indicator/index.d.ts +2 -0
  29. package/src/generators/health-indicator/index.js +7 -0
  30. package/src/generators/health-indicator/index.js.map +1 -0
  31. package/src/generators/health-indicator/schema.d.ts +5 -0
  32. package/src/generators/health-indicator/schema.json +32 -0
  33. package/src/generators/health-indicator-init/generator.d.ts +4 -0
  34. package/src/generators/health-indicator-init/generator.js +35 -0
  35. package/src/generators/health-indicator-init/generator.js.map +1 -0
  36. package/src/generators/health-indicator-init/index.d.ts +2 -0
  37. package/src/generators/health-indicator-init/index.js +7 -0
  38. package/src/generators/health-indicator-init/index.js.map +1 -0
  39. package/src/generators/health-indicator-init/schema.d.ts +4 -0
  40. package/src/generators/health-indicator-init/schema.json +22 -0
  41. package/src/generators/init/generator.js +29 -25
  42. package/src/generators/init/generator.js.map +1 -1
  43. package/src/generators/init/index.js +6 -4
  44. package/src/generators/init/index.js.map +1 -1
  45. package/src/generators/init/schema.d.ts +2 -0
  46. package/src/generators/init/schema.json +10 -0
  47. package/src/generators/init-application/extract-existing-config-validation.d.ts +3 -0
  48. package/src/generators/init-application/extract-existing-config-validation.js +47 -0
  49. package/src/generators/init-application/extract-existing-config-validation.js.map +1 -0
  50. package/src/generators/init-application/files/shared/Dockerfile +35 -0
  51. package/src/generators/init-application/generator.js +625 -80
  52. package/src/generators/init-application/generator.js.map +1 -1
  53. package/src/generators/init-application/index.js +6 -4
  54. package/src/generators/init-application/index.js.map +1 -1
  55. package/src/generators/init-application/schema.d.ts +5 -2
  56. package/src/generators/init-application/schema.json +36 -21
  57. package/src/generators/init-library/generator.js +58 -22
  58. package/src/generators/init-library/generator.js.map +1 -1
  59. package/src/generators/init-library/index.js +6 -4
  60. package/src/generators/init-library/index.js.map +1 -1
  61. package/src/generators/init-library/schema.d.ts +2 -0
  62. package/src/generators/init-library/schema.json +10 -0
  63. package/src/generators/jwt/generator.d.ts +4 -0
  64. package/src/generators/jwt/generator.js +76 -0
  65. package/src/generators/jwt/generator.js.map +1 -0
  66. package/src/generators/jwt/index.d.ts +2 -0
  67. package/src/generators/jwt/index.js +7 -0
  68. package/src/generators/jwt/index.js.map +1 -0
  69. package/src/generators/jwt/schema.d.ts +4 -0
  70. package/src/generators/jwt/schema.json +18 -0
  71. package/src/generators/microservice/generator.d.ts +4 -0
  72. package/src/generators/microservice/generator.js +26 -0
  73. package/src/generators/microservice/generator.js.map +1 -0
  74. package/src/generators/microservice/index.d.ts +2 -0
  75. package/src/generators/microservice/index.js +7 -0
  76. package/src/generators/microservice/index.js.map +1 -0
  77. package/src/generators/microservice/schema.d.ts +6 -0
  78. package/src/generators/microservice/schema.json +27 -0
  79. package/src/generators/open-api/generator.d.ts +4 -0
  80. package/src/generators/open-api/generator.js +74 -0
  81. package/src/generators/open-api/generator.js.map +1 -0
  82. package/src/generators/open-api/index.d.ts +2 -0
  83. package/src/generators/open-api/index.js +7 -0
  84. package/src/generators/open-api/index.js.map +1 -0
  85. package/src/generators/open-api/schema.d.ts +4 -0
  86. package/src/generators/open-api/schema.json +18 -0
  87. package/src/generators/sentry/generator.d.ts +4 -0
  88. package/src/generators/sentry/generator.js +152 -0
  89. package/src/generators/sentry/generator.js.map +1 -0
  90. package/src/generators/sentry/index.d.ts +2 -0
  91. package/src/generators/sentry/index.js +7 -0
  92. package/src/generators/sentry/index.js.map +1 -0
  93. package/src/generators/sentry/schema.d.ts +6 -0
  94. package/src/generators/sentry/schema.json +32 -0
  95. package/src/generators/swagger/files/environments/environment.swagger.ts__tmpl__ +1 -0
  96. package/src/generators/swagger/files/swagger.ts__tmpl__ +17 -15
  97. package/src/generators/swagger/generator.js +38 -36
  98. package/src/generators/swagger/generator.js.map +1 -1
  99. package/src/generators/swagger/index.js +6 -4
  100. package/src/generators/swagger/index.js.map +1 -1
  101. package/src/generators/swagger/schema.d.ts +1 -0
  102. package/src/generators/swagger/schema.json +3 -0
  103. package/src/generators/validator/generator.d.ts +4 -0
  104. package/src/generators/validator/generator.js +14 -0
  105. package/src/generators/validator/generator.js.map +1 -0
  106. package/src/generators/validator/index.d.ts +2 -0
  107. package/src/generators/validator/index.js +7 -0
  108. package/src/generators/validator/index.js.map +1 -0
  109. package/src/generators/validator/schema.d.ts +4 -0
  110. package/src/generators/validator/schema.json +22 -0
  111. package/src/index.js +7 -2
  112. package/src/index.js.map +1 -1
  113. package/src/lib/skip-non-nest-project.js +10 -5
  114. package/src/lib/skip-non-nest-project.js.map +1 -1
@@ -1,41 +1,146 @@
1
- import { getProjects, readNxJson, updateNxJson, updateProjectConfiguration, } from '@nx/devkit';
2
- import libraryGenerator from '@nx/js/src/generators/library/library';
3
- import { CoerceIgnorePattern, SkipNonApplicationProject, } from '@rxap/generator-utilities';
4
- import { CoerceTarget, CoerceTargetDefaultsDependency, } from '@rxap/workspace-utilities';
5
- import { wrapAngularDevkitSchematic } from 'nx/src/adapter/ngcli-adapter';
6
- import { join } from 'path';
7
- import { SkipNonNestProject } from '../../lib/skip-non-nest-project';
8
- import swaggerGenerator from '../swagger/generator';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initApplicationGenerator = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const devkit_1 = require("@nx/devkit");
6
+ const library_1 = require("@nx/js/src/generators/library/library");
7
+ const generator_utilities_1 = require("@rxap/generator-utilities");
8
+ const ts_morph_1 = require("@rxap/ts-morph");
9
+ const workspace_ts_morph_1 = require("@rxap/workspace-ts-morph");
10
+ const workspace_utilities_1 = require("@rxap/workspace-utilities");
11
+ const path_1 = require("path");
12
+ const ts_morph_2 = require("ts-morph");
13
+ const skip_non_nest_project_1 = require("../../lib/skip-non-nest-project");
14
+ const generator_1 = require("../health-indicator-init/generator");
15
+ const generator_2 = require("../health-indicator/generator");
16
+ const generator_3 = require("../jwt/generator");
17
+ const generator_4 = require("../open-api/generator");
18
+ const generator_5 = require("../sentry/generator");
19
+ const generator_6 = require("../swagger/generator");
20
+ const generator_7 = require("../validator/generator");
21
+ const extract_existing_config_validation_1 = require("./extract-existing-config-validation");
22
+ function coerceEnvironmentFiles(tree, options) {
23
+ (0, workspace_ts_morph_1.TsMorphNestProjectTransform)(tree, {
24
+ project: options.project,
25
+ }, (project, [sourceFile, prodSourceFile]) => {
26
+ (0, ts_morph_1.CoerceImports)(sourceFile, {
27
+ moduleSpecifier: '@rxap/nest-utilities',
28
+ namedImports: ['Environment'],
29
+ });
30
+ (0, ts_morph_1.CoerceImports)(prodSourceFile, {
31
+ moduleSpecifier: '@rxap/nest-utilities',
32
+ namedImports: ['Environment'],
33
+ });
34
+ const baseEnvironment = {
35
+ name: w => w.quote('development'),
36
+ production: 'false',
37
+ app: w => w.quote(options.project),
38
+ };
39
+ if (options.sentry) {
40
+ baseEnvironment['sentry'] = ts_morph_2.Writers.object({
41
+ enabled: 'false',
42
+ debug: 'false',
43
+ });
44
+ }
45
+ const normal = (0, ts_morph_1.CoerceVariableDeclaration)(sourceFile, 'environment', {
46
+ type: 'Environment',
47
+ initializer: ts_morph_2.Writers.object(baseEnvironment),
48
+ });
49
+ if (options.overwrite) {
50
+ normal.set({ initializer: ts_morph_2.Writers.object(baseEnvironment) });
51
+ }
52
+ baseEnvironment['name'] = w => w.quote('production');
53
+ baseEnvironment['production'] = 'true';
54
+ if (options.sentry) {
55
+ baseEnvironment['sentry'] = ts_morph_2.Writers.object({
56
+ enabled: 'true',
57
+ debug: 'false',
58
+ });
59
+ }
60
+ const prod = (0, ts_morph_1.CoerceVariableDeclaration)(prodSourceFile, 'environment', {
61
+ type: 'Environment',
62
+ initializer: ts_morph_2.Writers.object(baseEnvironment),
63
+ });
64
+ if (options.overwrite) {
65
+ prod.set({ initializer: ts_morph_2.Writers.object(baseEnvironment) });
66
+ }
67
+ }, [
68
+ '/environments/environment.ts?',
69
+ '/environments/environment.prod.ts?',
70
+ ]);
71
+ }
72
+ function removeAppServiceFile(tree, projectSourceRoot) {
73
+ var _a, _b;
74
+ const appServiceFilePath = (0, path_1.join)(projectSourceRoot, 'app', 'app.service.ts');
75
+ if (tree.exists(appServiceFilePath)) {
76
+ if ((_b = (_a = tree.read(appServiceFilePath)) === null || _a === void 0 ? void 0 : _a.toString('utf-8')) === null || _b === void 0 ? void 0 : _b.includes('return { message: \'Hello API\' };')) {
77
+ console.warn('Remove the app service file');
78
+ tree.delete(appServiceFilePath);
79
+ if (tree.exists((0, path_1.join)(projectSourceRoot, 'app', 'app.service.spec.ts'))) {
80
+ console.warn('Remove the app service spec file');
81
+ tree.delete((0, path_1.join)(projectSourceRoot, 'app', 'app.service.spec.ts'));
82
+ }
83
+ else {
84
+ console.warn('The app service spec file does not exists');
85
+ }
86
+ }
87
+ else {
88
+ console.warn('The app service file does not contains the default method');
89
+ }
90
+ }
91
+ else {
92
+ console.warn('The app service file does not exists');
93
+ }
94
+ }
95
+ function removeAppControllerSpecFile(tree, projectSourceRoot) {
96
+ var _a, _b;
97
+ const appControllerSpecFilePath = (0, path_1.join)(projectSourceRoot, 'app', 'app.controller.spec.ts');
98
+ if (tree.exists(appControllerSpecFilePath)) {
99
+ if ((_b = (_a = tree.read(appControllerSpecFilePath)) === null || _a === void 0 ? void 0 : _a.toString('utf-8')) === null || _b === void 0 ? void 0 : _b.includes('should return "Hello API"')) {
100
+ console.warn('Remove the app controller spec file');
101
+ tree.delete(appControllerSpecFilePath);
102
+ }
103
+ else {
104
+ console.warn('The app controller spec file does not contains the default test');
105
+ }
106
+ }
107
+ else {
108
+ console.warn('The app controller spec file does not exists');
109
+ }
110
+ }
9
111
  function skipProject(tree, options, project, projectName) {
10
- if (SkipNonNestProject(tree, options, project, projectName)) {
112
+ if ((0, skip_non_nest_project_1.SkipNonNestProject)(tree, options, project, projectName)) {
11
113
  return true;
12
114
  }
13
- if (SkipNonApplicationProject(tree, options, project, projectName)) {
115
+ if ((0, generator_utilities_1.SkipNonApplicationProject)(tree, options, project, projectName)) {
14
116
  return true;
15
117
  }
16
118
  return false;
17
119
  }
18
120
  function setGeneralTargetDefaults(tree) {
19
- const nxJson = readNxJson(tree);
20
- CoerceTargetDefaultsDependency(nxJson, 'build', 'generate-package-json');
21
- CoerceTargetDefaultsDependency(nxJson, 'generate-open-api', 'swagger-generate');
22
- updateNxJson(tree, nxJson);
121
+ const nxJson = (0, devkit_1.readNxJson)(tree);
122
+ (0, workspace_utilities_1.CoerceTargetDefaultsDependency)(nxJson, 'build', 'generate-package-json');
123
+ (0, workspace_utilities_1.CoerceTargetDefaultsDependency)(nxJson, 'generate-open-api', 'swagger-generate');
124
+ (0, workspace_utilities_1.CoerceNxJsonCacheableOperation)(nxJson, 'generate-package-json', 'generate-open-api', 'swagger-generate', 'swagger-build');
125
+ (0, devkit_1.updateNxJson)(tree, nxJson);
23
126
  }
24
127
  function updateProjectTargets(project) {
25
- CoerceTarget(project, 'generate-package-json', {
128
+ var _a, _b, _c, _d, _e, _f;
129
+ var _g, _h, _j;
130
+ (0, workspace_utilities_1.CoerceTarget)(project, 'generate-package-json', {
26
131
  executor: '@rxap/plugin-nestjs:package-json',
27
132
  configurations: {
28
133
  production: {},
29
134
  },
30
135
  });
31
- const outputPath = project.targets?.build?.options?.outputPath;
136
+ const outputPath = (_c = (_b = (_a = project.targets) === null || _a === void 0 ? void 0 : _a.build) === null || _b === void 0 ? void 0 : _b.options) === null || _c === void 0 ? void 0 : _c.outputPath;
32
137
  if (!outputPath) {
33
138
  throw new Error(`No outputPath found for project ${project.name}`);
34
139
  }
35
- CoerceTarget(project, 'generate-open-api', {
140
+ (0, workspace_utilities_1.CoerceTarget)(project, 'generate-open-api', {
36
141
  executor: '@rxap/plugin-library:run-generator',
37
142
  options: {
38
- generator: '@rxap/schematics-open-api:generate',
143
+ generator: '@rxap/plugin-open-api:generate',
39
144
  options: {
40
145
  project: `open-api-${project.name}`,
41
146
  path: `${outputPath.replace('dist/', 'dist/swagger/')}/openapi.json`,
@@ -43,78 +148,518 @@ function updateProjectTargets(project) {
43
148
  },
44
149
  },
45
150
  });
151
+ (0, workspace_utilities_1.CoerceTarget)(project, 'build', {
152
+ options: {
153
+ generatePackageJson: true,
154
+ },
155
+ configurations: {
156
+ production: {
157
+ fileReplacements: [
158
+ {
159
+ replace: `${project.sourceRoot}/environments/environment.ts`,
160
+ with: `${project.sourceRoot}/environments/environment.prod.ts`,
161
+ },
162
+ ],
163
+ },
164
+ development: {
165
+ progress: true,
166
+ },
167
+ },
168
+ }, workspace_utilities_1.Strategy.OVERWRITE);
169
+ if (project.targets['docker']) {
170
+ (_d = (_g = project.targets['docker']).options) !== null && _d !== void 0 ? _d : (_g.options = {});
171
+ (_e = (_h = project.targets['docker'].options).dockerfile) !== null && _e !== void 0 ? _e : (_h.dockerfile = 'shared/nestjs/Dockerfile');
172
+ (_f = (_j = project.targets['docker'].options).buildArgList) !== null && _f !== void 0 ? _f : (_j.buildArgList = []);
173
+ if (!project.targets['docker'].options.buildArgList.some((arg) => arg.startsWith('PATH_PREFIX='))) {
174
+ project.targets['docker'].options.buildArgList.push('REGEX:app/app.config.ts:validationSchema\\[\'GLOBAL_API_PREFIX\'\\]\\s*=\\s*Joi.string\\(\\).default\\(\\s*\'(.+)\',?\\s*\\);');
175
+ }
176
+ }
46
177
  }
47
178
  function updateGitIgnore(tree, project) {
48
- CoerceIgnorePattern(tree, join(project.root, '.gitignore'), ['package.json']);
179
+ (0, generator_utilities_1.CoerceIgnorePattern)(tree, (0, path_1.join)(project.root, '.gitignore'), ['package.json']);
49
180
  }
50
- async function createOpenApiClientSdkLibrary(tree, project, projects) {
51
- const openApiProjectName = `open-api-${project.name}`;
52
- if (projects.has(openApiProjectName)) {
53
- return;
54
- }
55
- const projectRoot = project.root;
56
- const fragments = projectRoot.split('/');
57
- const name = fragments.pop();
58
- fragments.shift(); // remove the root folder
59
- const directory = `open-api/${fragments.join('/')}`;
60
- try {
61
- await libraryGenerator(tree, {
62
- name,
63
- directory,
64
- unitTestRunner: 'none',
65
- tags: 'open-api',
66
- buildable: false,
67
- bundler: 'none',
68
- });
69
- }
70
- catch (e) {
71
- console.warn(`Can't create open api client sdk library: ${e.message}`);
72
- return;
181
+ function addDependencies(tree, options) {
182
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
183
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@nestjs/throttler', 'latest', { soft: true });
184
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, 'cookie-parser', 'latest', { soft: true });
185
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@nestjs/config', 'latest', { soft: true });
186
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, 'joi', 'latest', { soft: true });
187
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@rxap/nest-utilities', 'latest', { soft: true });
188
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@rxap/nest-server', 'latest', { soft: true });
189
+ yield (0, workspace_utilities_1.AddPackageJsonDevDependency)(tree, '@types/cookie-parser', 'latest', { soft: true });
190
+ yield (0, workspace_utilities_1.AddPackageJsonDevDependency)(tree, '@types/csurf', 'latest', { soft: true });
191
+ yield (0, workspace_utilities_1.AddPackageJsonDevDependency)(tree, '@rxap/plugin-application', 'latest', { soft: true });
192
+ yield (0, workspace_utilities_1.AddPackageJsonDevDependency)(tree, '@rxap/plugin-docker', 'latest', { soft: true });
193
+ if (options.swagger) {
194
+ yield (0, workspace_utilities_1.AddPackageJsonDevDependency)(tree, '@rxap/json-schema-to-typescript', 'latest', { soft: true });
195
+ }
196
+ switch (options.platform) {
197
+ case 'express':
198
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@nestjs/platform-express', 'latest', { soft: true });
199
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, 'helmet', 'latest', { soft: true });
200
+ break;
201
+ case 'fastify':
202
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@nestjs/platform-fastify', 'latest', { soft: true });
203
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@fastify/helmet', 'latest', { soft: true });
204
+ break;
205
+ }
206
+ });
207
+ }
208
+ function createOpenApiClientSdkLibrary(tree, project, projects) {
209
+ var _a;
210
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
211
+ const openApiProjectName = `open-api-${project.name}`;
212
+ if (projects.has(openApiProjectName)) {
213
+ console.log(`Open api client sdk library for project ${project.name} already exists`);
214
+ return;
215
+ }
216
+ const projectRoot = project.root;
217
+ const fragments = projectRoot.split('/');
218
+ const name = fragments.pop();
219
+ // only remove the root folder if it is one of the following
220
+ if (['libs', 'applications', 'apps', 'packages'].includes(fragments[0])) {
221
+ fragments.shift(); // remove the root folder
222
+ }
223
+ const directory = ['open-api', ...fragments].filter(Boolean).join('/');
224
+ const manuelCreateCommand = `nx g @nx/js:library --name ${name} --directory ${directory} --unitTestRunner none --tags open-api --buildable false --bundler none`;
225
+ try {
226
+ yield (0, library_1.default)(tree, {
227
+ name,
228
+ directory,
229
+ unitTestRunner: 'none',
230
+ tags: 'open-api',
231
+ buildable: false,
232
+ bundler: 'none',
233
+ });
234
+ }
235
+ catch (e) {
236
+ console.log(`Manuel create open api client sdk library: ${manuelCreateCommand}`);
237
+ throw new Error(`Can't create open api client sdk library: ${e.message}`);
238
+ }
239
+ let tsConfig;
240
+ try {
241
+ tsConfig = JSON.parse(tree.read('tsconfig.base.json').toString('utf-8'));
242
+ }
243
+ catch (e) {
244
+ throw new Error(`Can't parse tsconfig.base.json: ${e.message}`);
245
+ }
246
+ projects = (0, devkit_1.getProjects)(tree);
247
+ if (!projects.has(openApiProjectName)) {
248
+ console.log(`Manuel create open api client sdk library: ${manuelCreateCommand}`);
249
+ throw new Error(`Can't find project ${openApiProjectName}`);
250
+ }
251
+ const openApiProjectConfiguration = projects.get(openApiProjectName);
252
+ const openApiProjectRoot = openApiProjectConfiguration.root;
253
+ if (tsConfig.compilerOptions.paths[`${directory}/${name}`]) {
254
+ delete tsConfig.compilerOptions.paths[`${directory}/${name}`];
255
+ tsConfig.compilerOptions.paths[`${openApiProjectName}/*`] = [`${openApiProjectRoot}/src/lib/*`];
256
+ tree.write('tsconfig.base.json', JSON.stringify(tsConfig, null, 2));
257
+ }
258
+ tree.write(`${openApiProjectRoot}/src/index.ts`, 'export {};');
259
+ if (tree.exists(`${openApiProjectRoot}/src/lib/${openApiProjectName}.ts`)) {
260
+ tree.delete(`${openApiProjectRoot}/src/lib/${openApiProjectName}.ts`);
261
+ }
262
+ if (tree.exists(`${openApiProjectRoot}/README.md`)) {
263
+ tree.delete(`${openApiProjectRoot}/README.md`);
264
+ }
265
+ (_a = openApiProjectConfiguration.implicitDependencies) !== null && _a !== void 0 ? _a : (openApiProjectConfiguration.implicitDependencies = []);
266
+ if (!openApiProjectConfiguration.implicitDependencies.includes(project.name)) {
267
+ openApiProjectConfiguration.implicitDependencies.push(project.name);
268
+ }
269
+ (0, devkit_1.updateProjectConfiguration)(tree, openApiProjectName, openApiProjectConfiguration);
270
+ });
271
+ }
272
+ function getPort(tree, options, projectSourceRoot) {
273
+ if (options.port && options.projects.length === 1) {
274
+ return options.port;
73
275
  }
74
- let tsConfig;
75
- try {
76
- tsConfig = JSON.parse(tree.read('tsconfig.base.json').toString('utf-8'));
276
+ if (tree.exists((0, path_1.join)(projectSourceRoot, 'app', 'app.config.ts'))) {
277
+ const match = tree.read((0, path_1.join)(projectSourceRoot, 'app', 'app.config.ts'))
278
+ .toString()
279
+ .match(/validationSchema\['PORT'\] = Joi.number\(\).default\((\d+)\);/);
280
+ if (match) {
281
+ return parseInt(match[1]);
282
+ }
77
283
  }
78
- catch (e) {
79
- throw new Error(`Can't parse tsconfig.base.json: ${e.message}`);
284
+ if (tree.exists((0, path_1.join)(projectSourceRoot, 'app', 'app.module.ts'))) {
285
+ const match = tree.read((0, path_1.join)(projectSourceRoot, 'app', 'app.module.ts'))
286
+ .toString()
287
+ .match(/PORT: Joi.number\(\).default\((\d+)\)/);
288
+ if (match) {
289
+ return parseInt(match[1]);
290
+ }
80
291
  }
81
- projects = getProjects(tree);
82
- if (!projects.has(openApiProjectName)) {
83
- throw new Error(`Can't find project ${openApiProjectName}`);
292
+ return Math.floor(Math.random() * 1000) + 3000;
293
+ }
294
+ const MAIN_NEST_APP_OPTIONS_STATEMENT = 'const options: NestApplicationOptions = {};';
295
+ const MAIN_BOOTSTRAP_OPTIONS_STATEMENT = 'const bootstrapOptions: Partial<MonolithicBootstrapOptions> = {};';
296
+ const MAIN_SERVER_STATEMENT = 'const server = new Monolithic<NestApplicationOptions, NestExpressApplication>(AppModule, environment, options, bootstrapOptions);';
297
+ const MAIN_BOOTSTRAP_STATEMENT = 'server.bootstrap().catch((e) => console.error(\'Server bootstrap failed: \' + e.message));';
298
+ const MAIN_SETUP_HELMET_STATEMENT = 'server.after(SetupHelmet());';
299
+ const MAIN_SETUP_COOKIE_STATEMENT = 'server.after(SetupCookieParser());';
300
+ const MAIN_SETUP_CORS_STATEMENT = 'server.after(SetupCors());';
301
+ function assertMainStatements(sourceFile) {
302
+ var _a;
303
+ const statements = [];
304
+ statements.push('const options: NestApplicationOptions = {');
305
+ statements.push('const bootstrapOptions: Partial<MonolithicBootstrapOptions> = {');
306
+ statements.push('const server = new Monolithic<NestApplicationOptions, NestExpressApplication>(AppModule, environment, options, bootstrapOptions);');
307
+ const existingStatements = (_a = sourceFile.getStatements().map(s => s.getText())) !== null && _a !== void 0 ? _a : [];
308
+ for (const statement of statements) {
309
+ if (!existingStatements.includes(statement)) {
310
+ console.error(`Missing statement from main.ts: ${statement}`);
311
+ sourceFile.set({
312
+ statements: [
313
+ MAIN_NEST_APP_OPTIONS_STATEMENT,
314
+ MAIN_BOOTSTRAP_OPTIONS_STATEMENT,
315
+ MAIN_SERVER_STATEMENT,
316
+ MAIN_SETUP_HELMET_STATEMENT,
317
+ MAIN_SETUP_COOKIE_STATEMENT,
318
+ MAIN_SETUP_CORS_STATEMENT,
319
+ MAIN_BOOTSTRAP_STATEMENT,
320
+ ],
321
+ });
322
+ (0, ts_morph_1.CoerceImports)(sourceFile, [
323
+ {
324
+ moduleSpecifier: '@nestjs/common',
325
+ namedImports: ['NestApplicationOptions'],
326
+ },
327
+ {
328
+ moduleSpecifier: '@nestjs/platform-express',
329
+ namedImports: ['NestExpressApplication'],
330
+ },
331
+ {
332
+ moduleSpecifier: '@rxap/nest-server',
333
+ namedImports: [
334
+ 'MonolithicBootstrapOptions',
335
+ 'Monolithic',
336
+ 'SetupHelmet',
337
+ 'SetupCookieParser',
338
+ 'SetupCors',
339
+ ],
340
+ },
341
+ {
342
+ moduleSpecifier: './app/app.module',
343
+ namedImports: ['AppModule'],
344
+ },
345
+ {
346
+ moduleSpecifier: './environments/environment',
347
+ namedImports: ['environment'],
348
+ },
349
+ ]);
350
+ return;
351
+ }
84
352
  }
85
- const openApiProjectRoot = projects.get(openApiProjectName).root;
86
- delete tsConfig.compilerOptions.paths[`${directory}/${name}`];
87
- tsConfig.compilerOptions.paths[`${openApiProjectName}/*`] = [`${openApiProjectRoot}/src/lib/*`];
88
- tree.write('tsconfig.base.json', JSON.stringify(tsConfig, null, 2));
89
- tree.write(`${openApiProjectRoot}/src/index.ts`, 'export {};');
90
- tree.delete(`${openApiProjectRoot}/src/lib/${openApiProjectName}.ts`);
91
- tree.delete(`${openApiProjectRoot}/README.md`);
92
353
  }
93
- export async function initApplicationGenerator(tree, options) {
94
- console.log('nestjs application init generator:', options);
95
- setGeneralTargetDefaults(tree);
96
- const projects = getProjects(tree);
97
- for (const [projectName, project] of projects.entries()) {
98
- if (skipProject(tree, options, project, projectName)) {
99
- continue;
100
- }
101
- console.log(`init project: ${projectName}`);
102
- updateProjectTargets(project);
103
- updateGitIgnore(tree, project);
104
- await createOpenApiClientSdkLibrary(tree, project, projects);
105
- // apply changes to the project configuration
106
- updateProjectConfiguration(tree, projectName, project);
107
- if (options.swagger !== false) {
108
- await swaggerGenerator(tree, { project: projectName });
109
- }
110
- if (options.legacy) {
111
- await wrapAngularDevkitSchematic('@rxap/schematic-nestjs', 'init')(tree, {
112
- ...options,
113
- swagger: false,
114
- project: projectName,
354
+ function updateMainFile(tree, project, projectName, options) {
355
+ (0, workspace_ts_morph_1.TsMorphAngularProjectTransform)(tree, {
356
+ project: project.name,
357
+ // directory: '..' // to move from the apps/demo/src/app folder into the apps/demo/src folder
358
+ }, (project, [sourceFile]) => {
359
+ var _a;
360
+ assertMainStatements(sourceFile);
361
+ const importDeclarations = [];
362
+ const statements = [];
363
+ if (options.sentry) {
364
+ importDeclarations.push({
365
+ moduleSpecifier: '@rxap/nest-sentry',
366
+ namedImports: ['SetupSentryLogger'],
367
+ });
368
+ statements.push('server.after(SetupSentryLogger());');
369
+ }
370
+ else {
371
+ importDeclarations.push({
372
+ moduleSpecifier: '@rxap/nest-logger',
373
+ namedImports: ['RxapLogger'],
374
+ });
375
+ statements.push('server.after(app => app.useLogger(new RxapLogger()));');
376
+ }
377
+ if (options.validator) {
378
+ importDeclarations.push({
379
+ moduleSpecifier: '@rxap/nest-server',
380
+ namedImports: ['ValidationPipeSetup'],
381
+ });
382
+ statements.push('server.after(ValidationPipeSetup());');
383
+ }
384
+ if (options.swaggerLive) {
385
+ importDeclarations.push({
386
+ moduleSpecifier: '@rxap/nest-server',
387
+ namedImports: ['SetupSwagger'],
388
+ });
389
+ statements.push('server.after(SetupSwagger());');
390
+ }
391
+ if (options.statusRegister) {
392
+ importDeclarations.push({
393
+ moduleSpecifier: '@rxap/nest-server',
394
+ namedImports: ['RegisterToStatusService'],
115
395
  });
396
+ statements.push('server.ready(RegisterToStatusService());');
397
+ }
398
+ (0, ts_morph_1.CoerceImports)(sourceFile, importDeclarations);
399
+ for (let i = 0; i < statements.length; i++) {
400
+ const statement = statements[i];
401
+ const lastStatement = i > 0 ? statements[i - 1] : null;
402
+ const nestStatement = i < statements.length - 1 ? statements[i + 1] : null;
403
+ const existingStatements = (_a = sourceFile.getStatements().map(s => s.getText())) !== null && _a !== void 0 ? _a : [];
404
+ if (!existingStatements.includes(statement)) {
405
+ let index;
406
+ if (lastStatement) {
407
+ index = existingStatements.findIndex(s => s.includes(lastStatement)) + 1;
408
+ }
409
+ else if (nestStatement) {
410
+ index = existingStatements.findIndex(s => s.includes(nestStatement));
411
+ }
412
+ else {
413
+ index = existingStatements.findIndex(s => s.includes(MAIN_BOOTSTRAP_STATEMENT));
414
+ }
415
+ console.log(`insert statement: ${statement} at index ${index}`);
416
+ sourceFile.insertStatements(index, statement);
417
+ }
418
+ }
419
+ if (projectName === 'service-status') {
420
+ const variableDeclaration = (0, ts_morph_1.CoerceVariableDeclaration)(sourceFile, 'bootstrapOptions', { initializer: '{}' });
421
+ const objectLiteralExpression = variableDeclaration.getInitializerIfKindOrThrow(ts_morph_2.SyntaxKind.ObjectLiteralExpression);
422
+ let objectLiteralElementLike = objectLiteralExpression.getProperty('globalPrefixOptions');
423
+ if (!objectLiteralElementLike) {
424
+ objectLiteralElementLike = objectLiteralExpression.addPropertyAssignment({
425
+ name: 'globalPrefixOptions',
426
+ initializer: '{}',
427
+ });
428
+ }
429
+ const gpoPropertyAssigment = objectLiteralElementLike.asKindOrThrow(ts_morph_2.SyntaxKind.PropertyAssignment);
430
+ const gpoObjectLiteralExpression = gpoPropertyAssigment.getInitializerIfKindOrThrow(ts_morph_2.SyntaxKind.ObjectLiteralExpression);
431
+ let gpoElementLike = gpoObjectLiteralExpression.getProperty('exclude');
432
+ if (!gpoElementLike) {
433
+ gpoElementLike = gpoObjectLiteralExpression.addPropertyAssignment({
434
+ name: 'exclude',
435
+ initializer: `[ '/health(.*)', '/info', '/openapi', '/register' ]`,
436
+ });
437
+ }
116
438
  }
439
+ }, ['main.ts']);
440
+ }
441
+ function updateTags(project, options) {
442
+ const tags = ['backend', 'nest', 'service'];
443
+ if (options.sentry) {
444
+ tags.push('sentry');
445
+ }
446
+ if (options.swagger) {
447
+ tags.push('swagger');
117
448
  }
449
+ if (options.jwt) {
450
+ tags.push('jwt');
451
+ }
452
+ if (options.healthIndicator) {
453
+ tags.push('health-indicator');
454
+ }
455
+ if (options.openApi) {
456
+ tags.push('openapi');
457
+ }
458
+ if (options.platform) {
459
+ tags.push(options.platform);
460
+ }
461
+ (0, generator_utilities_1.CoerceProjectTags)(project, tags);
462
+ }
463
+ function updateApiConfigurationFile(tree, projectName, apiPrefix, apiConfigurationFile) {
464
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
465
+ if (apiConfigurationFile) {
466
+ yield (0, workspace_utilities_1.UpdateJsonFile)(tree, json => {
467
+ json[projectName] = { baseUrl: `/${apiPrefix}` };
468
+ }, apiConfigurationFile, { create: true });
469
+ }
470
+ });
471
+ }
472
+ function initApplicationGenerator(tree, options) {
473
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
474
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
475
+ (_a = options.sentry) !== null && _a !== void 0 ? _a : (options.sentry = true);
476
+ (_b = options.swagger) !== null && _b !== void 0 ? _b : (options.swagger = true);
477
+ (_c = options.healthIndicator) !== null && _c !== void 0 ? _c : (options.healthIndicator = true);
478
+ (_d = options.platform) !== null && _d !== void 0 ? _d : (options.platform = 'express');
479
+ (_e = options.validator) !== null && _e !== void 0 ? _e : (options.validator = true);
480
+ (_f = options.healthIndicatorList) !== null && _f !== void 0 ? _f : (options.healthIndicatorList = []);
481
+ (_g = options.port) !== null && _g !== void 0 ? _g : (options.port = undefined);
482
+ (_h = options.apiPrefix) !== null && _h !== void 0 ? _h : (options.apiPrefix = undefined);
483
+ (_j = options.sentryDsn) !== null && _j !== void 0 ? _j : (options.sentryDsn = undefined);
484
+ (_k = options.overwrite) !== null && _k !== void 0 ? _k : (options.overwrite = false);
485
+ (_l = options.openApi) !== null && _l !== void 0 ? _l : (options.openApi = false);
486
+ (_m = options.jwt) !== null && _m !== void 0 ? _m : (options.jwt = false);
487
+ (_o = options.statusRegister) !== null && _o !== void 0 ? _o : (options.statusRegister = true);
488
+ (_p = options.apiConfigurationFile) !== null && _p !== void 0 ? _p : (options.apiConfigurationFile = 'shared/service/configuration/latest/config.api.json');
489
+ console.log('nestjs application init generator:', options);
490
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@rxap/nest-server', 'latest', { soft: true });
491
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@rxap/nest-utilities', 'latest', { soft: true });
492
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@rxap/nest-logger', 'latest', { soft: true });
493
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@nestjs/terminus', 'latest', { soft: true });
494
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@nestjs/config', 'latest', { soft: true });
495
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, 'joi', 'latest', { soft: true });
496
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@rxap/plugin-nestjs', 'latest', { soft: true });
497
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@rxap/plugin-library', 'latest', { soft: true });
498
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@rxap/plugin-open-api', 'latest', { soft: true });
499
+ if (options.sentry) {
500
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@rxap/nest-sentry', 'latest', { soft: true });
501
+ }
502
+ if (options.swagger) {
503
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@nestjs/swagger', 'latest', { soft: true });
504
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@rxap/workspace-open-api', 'latest', { soft: true });
505
+ }
506
+ if (options.jwt) {
507
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@rxap/nest-jwt', 'latest', { soft: true });
508
+ }
509
+ if (options.openApi) {
510
+ yield (0, workspace_utilities_1.AddPackageJsonDependency)(tree, '@rxap/nest-open-api', 'latest', { soft: true });
511
+ }
512
+ (0, workspace_utilities_1.CoerceFilesStructure)(tree, {
513
+ srcFolder: (0, path_1.join)(__dirname, 'files', 'shared'),
514
+ target: 'shared/nestjs',
515
+ overwrite: options.overwrite,
516
+ });
517
+ setGeneralTargetDefaults(tree);
518
+ yield addDependencies(tree, options);
519
+ if (!options.skipProjects) {
520
+ const projects = (0, devkit_1.getProjects)(tree);
521
+ for (const [projectName, project] of projects.entries()) {
522
+ if (skipProject(tree, options, project, projectName)) {
523
+ continue;
524
+ }
525
+ const projectSourceRoot = project.sourceRoot;
526
+ if (!projectSourceRoot) {
527
+ throw new Error(`Can't find project source root for project ${projectName}`);
528
+ }
529
+ const port = getPort(tree, options, projectSourceRoot);
530
+ const globalApiPrefix = (0, workspace_utilities_1.GetNestApiPrefix)(tree, options, projectSourceRoot, projectName);
531
+ console.log(`init project: ${projectName}`);
532
+ updateProjectTargets(project);
533
+ updateGitIgnore(tree, project);
534
+ updateTags(project, options);
535
+ yield updateApiConfigurationFile(tree, projectName, globalApiPrefix, options.apiConfigurationFile);
536
+ yield createOpenApiClientSdkLibrary(tree, project, projects);
537
+ // apply changes to the project configuration
538
+ (0, devkit_1.updateProjectConfiguration)(tree, projectName, project);
539
+ coerceEnvironmentFiles(tree, {
540
+ project: projectName,
541
+ sentry: options.sentry,
542
+ overwrite: options.overwrite,
543
+ });
544
+ (0, workspace_ts_morph_1.TsMorphNestProjectTransform)(tree, { project: projectName }, (project, [moduleSourceFile, controllerSourceFile, configSourceFile]) => {
545
+ (0, ts_morph_1.CoerceNestAppModule)(moduleSourceFile);
546
+ (0, ts_morph_1.CoerceNestAppController)(controllerSourceFile);
547
+ (0, ts_morph_1.CoerceNestThrottlerModuleImport)(moduleSourceFile, { overwrite: options.overwrite });
548
+ (0, ts_morph_1.CoerceNestConfigModuleImport)(moduleSourceFile, { overwrite: options.overwrite });
549
+ (0, ts_morph_1.CoerceAppGuardProvider)(moduleSourceFile);
550
+ (0, ts_morph_1.CoerceNestEnvironmentProvider)(moduleSourceFile);
551
+ (0, ts_morph_1.CoerceNestLoggerProvider)(moduleSourceFile);
552
+ const itemList = (0, extract_existing_config_validation_1.ExtractExistingConfigValidation)(moduleSourceFile);
553
+ for (const item of [
554
+ {
555
+ name: 'PORT',
556
+ type: 'number',
557
+ defaultValue: port.toFixed(0),
558
+ },
559
+ {
560
+ name: 'GLOBAL_API_PREFIX',
561
+ defaultValue: w => w.quote(globalApiPrefix),
562
+ },
563
+ {
564
+ name: 'THROTTLER_TTL',
565
+ defaultValue: '1',
566
+ },
567
+ {
568
+ name: 'THROTTLER_LIMIT',
569
+ defaultValue: '10',
570
+ },
571
+ {
572
+ name: 'COOKIE_SECRET',
573
+ defaultValue: 'GenerateRandomString()',
574
+ },
575
+ ]) {
576
+ if (!itemList.find(i => i.name === item.name)) {
577
+ itemList.push(item);
578
+ }
579
+ }
580
+ if (options.statusRegister && projectName !== 'service-status') {
581
+ if (!itemList.find(i => i.name === 'STATUS_SERVICE_BASE_URL')) {
582
+ itemList.push({
583
+ name: 'STATUS_SERVICE_BASE_URL',
584
+ defaultValue: `environment.production ? 'http://rxap-service-status:3000' : 'http://localhost:5300'`,
585
+ });
586
+ }
587
+ (0, ts_morph_1.CoerceImports)(configSourceFile, {
588
+ namespaceImport: 'process',
589
+ moduleSpecifier: 'process',
590
+ });
591
+ }
592
+ (0, ts_morph_1.CoerceNestAppConfig)(configSourceFile, {
593
+ itemList,
594
+ overwrite: options.overwrite,
595
+ });
596
+ (0, ts_morph_1.CoerceImports)(configSourceFile, {
597
+ namedImports: ['GenerateRandomString'],
598
+ moduleSpecifier: '@rxap/utilities',
599
+ });
600
+ }, [
601
+ '/app/app.module.ts',
602
+ '/app/app.controller.ts',
603
+ '/app/app.config.ts?',
604
+ ]);
605
+ removeAppServiceFile(tree, projectSourceRoot);
606
+ removeAppControllerSpecFile(tree, projectSourceRoot);
607
+ if (options.generateMain) {
608
+ updateMainFile(tree, project, projectName, options);
609
+ }
610
+ if (options.healthIndicator || ((_q = options.healthIndicatorList) === null || _q === void 0 ? void 0 : _q.length)) {
611
+ if ((_r = options.healthIndicatorList) === null || _r === void 0 ? void 0 : _r.length) {
612
+ for (const healthIndicator of options.healthIndicatorList) {
613
+ yield (0, generator_2.default)(tree, {
614
+ name: healthIndicator,
615
+ project: projectName,
616
+ overwrite: options.overwrite,
617
+ });
618
+ }
619
+ }
620
+ else {
621
+ yield (0, generator_1.default)(tree, {
622
+ project: projectName,
623
+ overwrite: options.overwrite,
624
+ });
625
+ }
626
+ }
627
+ if (options.sentry) {
628
+ yield (0, generator_5.default)(tree, {
629
+ project: projectName,
630
+ dsn: options.sentryDsn,
631
+ required: !!options.sentryDsn,
632
+ overwrite: options.overwrite,
633
+ });
634
+ }
635
+ if (options.validator) {
636
+ yield (0, generator_7.default)(tree, {
637
+ project: projectName,
638
+ overwrite: options.overwrite,
639
+ });
640
+ }
641
+ if (options.openApi) {
642
+ yield (0, generator_4.default)(tree, {
643
+ project: projectName,
644
+ overwrite: options.overwrite,
645
+ });
646
+ }
647
+ if (options.jwt) {
648
+ yield (0, generator_3.default)(tree, {
649
+ project: projectName,
650
+ overwrite: options.overwrite,
651
+ });
652
+ }
653
+ if (options.swagger !== false) {
654
+ yield (0, generator_6.default)(tree, {
655
+ project: projectName,
656
+ overwrite: options.overwrite,
657
+ });
658
+ }
659
+ }
660
+ }
661
+ });
118
662
  }
119
- export default initApplicationGenerator;
663
+ exports.initApplicationGenerator = initApplicationGenerator;
664
+ exports.default = initApplicationGenerator;
120
665
  //# sourceMappingURL=generator.js.map