@mshima/generator-jhipster-nodejs 0.0.0-stage → 0.0.1

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 (209) hide show
  1. package/LICENSE.txt +204 -0
  2. package/README.md +243 -2
  3. package/build-info.json +3 -0
  4. package/cli/cli-customizations.cjs +9 -0
  5. package/cli/cli.cjs +40 -0
  6. package/cli/logo.js +31 -0
  7. package/cli/version.cjs +12 -0
  8. package/generators/ci-cd/USAGE +5 -0
  9. package/generators/ci-cd/command.js +5 -0
  10. package/generators/ci-cd/generator.js +158 -0
  11. package/generators/ci-cd/index.js +2 -0
  12. package/generators/ci-cd/templates/.gitlab-ci.yml.ejs +137 -0
  13. package/generators/ci-cd/templates/azure-pipelines.yml.ejs +68 -0
  14. package/generators/ci-cd/templates/circle.yml.ejs +59 -0
  15. package/generators/ci-cd/templates/docker-registry.yml.ejs +58 -0
  16. package/generators/ci-cd/templates/github-ci.yml.ejs +90 -0
  17. package/generators/ci-cd/templates/jenkins/Jenkinsfile.ejs +104 -0
  18. package/generators/ci-cd/templates/jenkins/idea.gdsl +90 -0
  19. package/generators/ci-cd/templates/jenkins/jenkins.yml.ejs +33 -0
  20. package/generators/ci-cd/templates/travis.yml.ejs +75 -0
  21. package/generators/client/command.js +5 -0
  22. package/generators/client/generator.js +21 -0
  23. package/generators/client/generators/bootstrap/command.js +5 -0
  24. package/generators/client/generators/bootstrap/generator.js +28 -0
  25. package/generators/client/generators/bootstrap/index.js +2 -0
  26. package/generators/client/index.js +2 -0
  27. package/generators/common/generators/bootstrap/command.js +5 -0
  28. package/generators/common/generators/bootstrap/generator.js +37 -0
  29. package/generators/common/generators/bootstrap/index.js +2 -0
  30. package/generators/docker/command.js +5 -0
  31. package/generators/docker/generator.js +16 -0
  32. package/generators/docker/generators/bootstrap/command.js +5 -0
  33. package/generators/docker/generators/bootstrap/generator.js +56 -0
  34. package/generators/docker/generators/bootstrap/index.js +2 -0
  35. package/generators/docker/index.js +2 -0
  36. package/generators/docker/templates/docker/app.yml.ejs +25 -0
  37. package/generators/generator-nodejs-constants.js +32 -0
  38. package/generators/languages/command.js +5 -0
  39. package/generators/languages/generator.js +22 -0
  40. package/generators/languages/index.js +2 -0
  41. package/generators/languages/templates/src/main/webapp/i18n/en/home.json +19 -0
  42. package/generators/languages/templates/src/main/webapp/i18n/es/home.json +19 -0
  43. package/generators/languages/templates/src/main/webapp/i18n/it/home.json +19 -0
  44. package/generators/node-server/command.js +96 -0
  45. package/generators/node-server/entity-files.js +41 -0
  46. package/generators/node-server/files.js +254 -0
  47. package/generators/node-server/generator.js +702 -0
  48. package/generators/node-server/generators/bootstrap/command.js +5 -0
  49. package/generators/node-server/generators/bootstrap/generator.js +83 -0
  50. package/generators/node-server/generators/bootstrap/index.js +2 -0
  51. package/generators/node-server/index.js +2 -0
  52. package/generators/node-server/resources/package.json +76 -0
  53. package/generators/node-server/support/api-fake-data.js +54 -0
  54. package/generators/node-server/support/columns.js +73 -0
  55. package/generators/node-server/support/database.js +24 -0
  56. package/generators/node-server/support/entity-authorities.js +32 -0
  57. package/generators/node-server/support/entity-paths.js +13 -0
  58. package/generators/node-server/support/enums.js +11 -0
  59. package/generators/node-server/support/index.js +9 -0
  60. package/generators/node-server/support/mail-templates.js +82 -0
  61. package/generators/node-server/support/migrations.js +197 -0
  62. package/generators/node-server/support/validators.js +25 -0
  63. package/generators/node-server/templates/.dockerignore.ejs +16 -0
  64. package/generators/node-server/templates/.gitignore.jhi.nodejs.ejs +24 -0
  65. package/generators/node-server/templates/Dockerfile.ejs +54 -0
  66. package/generators/node-server/templates/README.md.jhi.nodejs.ejs +220 -0
  67. package/generators/node-server/templates/package.json.ejs +84 -0
  68. package/generators/node-server/templates/server/README.md.ejs +269 -0
  69. package/generators/node-server/templates/server/e2e/_entityFileName_.database.e2e-spec.ts.ejs +192 -0
  70. package/generators/node-server/templates/server/e2e/_entityFileName_.e2e-spec.ts.ejs +402 -0
  71. package/generators/node-server/templates/server/e2e/account.e2e-spec.ts.ejs +349 -0
  72. package/generators/node-server/templates/server/e2e/app.e2e-spec.ts.ejs +188 -0
  73. package/generators/node-server/templates/server/e2e/authority.e2e-spec.ts.ejs +50 -0
  74. package/generators/node-server/templates/server/e2e/cors.e2e-spec.ts.ejs +110 -0
  75. package/generators/node-server/templates/server/e2e/management.e2e-spec.ts.ejs +180 -0
  76. package/generators/node-server/templates/server/e2e/oauth2-bearer.e2e-spec.ts.ejs +71 -0
  77. package/generators/node-server/templates/server/e2e/session.e2e-spec.ts.ejs +219 -0
  78. package/generators/node-server/templates/server/e2e/setup.test.js.ejs +1 -0
  79. package/generators/node-server/templates/server/e2e/user.e2e-spec.ts.ejs +318 -0
  80. package/generators/node-server/templates/server/env.ejs +1 -0
  81. package/generators/node-server/templates/server/eslint.config.mjs.ejs +48 -0
  82. package/generators/node-server/templates/server/nest-cli.json.ejs +11 -0
  83. package/generators/node-server/templates/server/ormconfig.ts.ejs +35 -0
  84. package/generators/node-server/templates/server/package.json.ejs +143 -0
  85. package/generators/node-server/templates/server/sonar-project.properties.ejs +10 -0
  86. package/generators/node-server/templates/server/src/app.config.spec.ts.ejs +13 -0
  87. package/generators/node-server/templates/server/src/app.config.ts.ejs +179 -0
  88. package/generators/node-server/templates/server/src/app.module.ts.ejs +80 -0
  89. package/generators/node-server/templates/server/src/application-config.ts.ejs +153 -0
  90. package/generators/node-server/templates/server/src/auth/account.controller.ts.ejs +183 -0
  91. package/generators/node-server/templates/server/src/auth/auth.module.ts.ejs +104 -0
  92. package/generators/node-server/templates/server/src/auth/auth.service.ts.ejs +294 -0
  93. package/generators/node-server/templates/server/src/auth/csrf.middleware.spec.ts.ejs +65 -0
  94. package/generators/node-server/templates/server/src/auth/csrf.middleware.ts.ejs +76 -0
  95. package/generators/node-server/templates/server/src/auth/decorators/auth-user.decorator.ts.ejs +8 -0
  96. package/generators/node-server/templates/server/src/auth/decorators/roles.decorator.ts.ejs +4 -0
  97. package/generators/node-server/templates/server/src/auth/dto/key-and-password.dto.ts.ejs +17 -0
  98. package/generators/node-server/templates/server/src/auth/dto/password-change.dto.ts.ejs +17 -0
  99. package/generators/node-server/templates/server/src/auth/dto/user-login.dto.ts.ejs +21 -0
  100. package/generators/node-server/templates/server/src/auth/guards/auth.guard.ts.ejs +50 -0
  101. package/generators/node-server/templates/server/src/auth/guards/oauth2-login.guard.ts.ejs +6 -0
  102. package/generators/node-server/templates/server/src/auth/guards/roles.guard.ts.ejs +25 -0
  103. package/generators/node-server/templates/server/src/auth/index.ts.ejs +8 -0
  104. package/generators/node-server/templates/server/src/auth/jwt.config.spec.ts.ejs +22 -0
  105. package/generators/node-server/templates/server/src/auth/jwt.config.ts.ejs +29 -0
  106. package/generators/node-server/templates/server/src/auth/oauth2.authorities.spec.ts.ejs +24 -0
  107. package/generators/node-server/templates/server/src/auth/oauth2.authorities.ts.ejs +33 -0
  108. package/generators/node-server/templates/server/src/auth/oauth2.config.ts.ejs +51 -0
  109. package/generators/node-server/templates/server/src/auth/passport.jwt.strategy.ts.ejs +45 -0
  110. package/generators/node-server/templates/server/src/auth/passport.oauth2-bearer.strategy.ts.ejs +32 -0
  111. package/generators/node-server/templates/server/src/auth/passport.oauth2.strategy.spec.ts.ejs +27 -0
  112. package/generators/node-server/templates/server/src/auth/passport.oauth2.strategy.ts.ejs +44 -0
  113. package/generators/node-server/templates/server/src/auth/password-util.ts.ejs +10 -0
  114. package/generators/node-server/templates/server/src/auth/password.service.ts.ejs +34 -0
  115. package/generators/node-server/templates/server/src/auth/payload.interface.ts.ejs +14 -0
  116. package/generators/node-server/templates/server/src/auth/role-type.ts.ejs +7 -0
  117. package/generators/node-server/templates/server/src/auth/session-user.middleware.ts.ejs +33 -0
  118. package/generators/node-server/templates/server/src/auth/session.entity.ts.ejs +36 -0
  119. package/generators/node-server/templates/server/src/auth/session.store.spec.ts.ejs +99 -0
  120. package/generators/node-server/templates/server/src/auth/session.store.ts.ejs +116 -0
  121. package/generators/node-server/templates/server/src/auth/user.jwt.controller.ts.ejs +26 -0
  122. package/generators/node-server/templates/server/src/auth/user.oauth2.controller.ts.ejs +78 -0
  123. package/generators/node-server/templates/server/src/auth/user.session.controller.ts.ejs +103 -0
  124. package/generators/node-server/templates/server/src/common/common.module.ts.ejs +19 -0
  125. package/generators/node-server/templates/server/src/common/database/base.entity.ts.ejs +13 -0
  126. package/generators/node-server/templates/server/src/common/database/column-transformers.spec.ts.ejs +46 -0
  127. package/generators/node-server/templates/server/src/common/database/column-transformers.ts.ejs +69 -0
  128. package/generators/node-server/templates/server/src/common/database/column-types.spec.ts.ejs +21 -0
  129. package/generators/node-server/templates/server/src/common/database/column-types.ts.ejs +29 -0
  130. package/generators/node-server/templates/server/src/common/database/pagination.entity.spec.ts.ejs +66 -0
  131. package/generators/node-server/templates/server/src/common/database/pagination.entity.ts.ejs +108 -0
  132. package/generators/node-server/templates/server/src/common/dto/base.dto.ts.ejs +19 -0
  133. package/generators/node-server/templates/server/src/common/errors/error-constants.ts.ejs +10 -0
  134. package/generators/node-server/templates/server/src/common/errors/problem-details.filter.ts.ejs +63 -0
  135. package/generators/node-server/templates/server/src/common/errors/problem.exception.ts.ejs +92 -0
  136. package/generators/node-server/templates/server/src/common/field_validators.ejs +77 -0
  137. package/generators/node-server/templates/server/src/common/header-util.ts.ejs +105 -0
  138. package/generators/node-server/templates/server/src/common/interceptors/logging.interceptor.spec.ts.ejs +93 -0
  139. package/generators/node-server/templates/server/src/common/interceptors/logging.interceptor.ts.ejs +48 -0
  140. package/generators/node-server/templates/server/src/common/logging.spec.ts.ejs +83 -0
  141. package/generators/node-server/templates/server/src/common/logging.ts.ejs +129 -0
  142. package/generators/node-server/templates/server/src/common/metrics.spec.ts.ejs +43 -0
  143. package/generators/node-server/templates/server/src/common/metrics.ts.ejs +198 -0
  144. package/generators/node-server/templates/server/src/common/request.ts.ejs +8 -0
  145. package/generators/node-server/templates/server/src/common/sortable-properties.ts.ejs +43 -0
  146. package/generators/node-server/templates/server/src/common/updatable-properties.ts.ejs +14 -0
  147. package/generators/node-server/templates/server/src/config/application-dev.yml.ejs +118 -0
  148. package/generators/node-server/templates/server/src/config/application-prod.yml.ejs +97 -0
  149. package/generators/node-server/templates/server/src/config/application-secret-samples.yml.ejs +42 -0
  150. package/generators/node-server/templates/server/src/config/application-test.yml.ejs +68 -0
  151. package/generators/node-server/templates/server/src/config/application-tls-samples.yml.ejs +15 -0
  152. package/generators/node-server/templates/server/src/config/application-tls.yml.ejs +15 -0
  153. package/generators/node-server/templates/server/src/config/application.yml.ejs +149 -0
  154. package/generators/node-server/templates/server/src/config.spec.ts.ejs +81 -0
  155. package/generators/node-server/templates/server/src/config.ts.ejs +255 -0
  156. package/generators/node-server/templates/server/src/entities/_entityFileName_/_entityFileName_.controller.ts.ejs +178 -0
  157. package/generators/node-server/templates/server/src/entities/_entityFileName_/_entityFileName_.entity.ts.ejs +110 -0
  158. package/generators/node-server/templates/server/src/entities/_entityFileName_/_entityFileName_.mapper.ts.ejs +37 -0
  159. package/generators/node-server/templates/server/src/entities/_entityFileName_/_entityFileName_.module.ts.ejs +14 -0
  160. package/generators/node-server/templates/server/src/entities/_entityFileName_/_entityFileName_.service.ts.ejs +123 -0
  161. package/generators/node-server/templates/server/src/entities/_entityFileName_/dto/_entityFileName_.dto.ts.ejs +99 -0
  162. package/generators/node-server/templates/server/src/mail/mail.module.ts.ejs +49 -0
  163. package/generators/node-server/templates/server/src/mail/mail.service.spec.ts.ejs +105 -0
  164. package/generators/node-server/templates/server/src/mail/mail.service.ts.ejs +120 -0
  165. package/generators/node-server/templates/server/src/main.ts.ejs +114 -0
  166. package/generators/node-server/templates/server/src/management/api-docs.controller.ts.ejs +27 -0
  167. package/generators/node-server/templates/server/src/management/api-docs.service.ts.ejs +8 -0
  168. package/generators/node-server/templates/server/src/management/configuration.controller.ts.ejs +80 -0
  169. package/generators/node-server/templates/server/src/management/health.controller.spec.ts.ejs +79 -0
  170. package/generators/node-server/templates/server/src/management/health.controller.ts.ejs +87 -0
  171. package/generators/node-server/templates/server/src/management/health.module.ts.ejs +9 -0
  172. package/generators/node-server/templates/server/src/management/loggers.controller.ts.ejs +40 -0
  173. package/generators/node-server/templates/server/src/management/management.controller.spec.ts.ejs +26 -0
  174. package/generators/node-server/templates/server/src/management/management.controller.ts.ejs +34 -0
  175. package/generators/node-server/templates/server/src/management/management.module.ts.ejs +21 -0
  176. package/generators/node-server/templates/server/src/management/metrics.controller.ts.ejs +85 -0
  177. package/generators/node-server/templates/server/src/migrations/1570200270081-CreateTables.ts.ejs +64 -0
  178. package/generators/node-server/templates/server/src/migrations/1570200270082-CreateSessions.ts.ejs +26 -0
  179. package/generators/node-server/templates/server/src/migrations/1570200490072-SeedUsersRoles.ts.ejs +74 -0
  180. package/generators/node-server/templates/server/src/migrations/_entityConstraintsMigration_.ts.ejs +40 -0
  181. package/generators/node-server/templates/server/src/migrations/_entityMigration_.ts.ejs +26 -0
  182. package/generators/node-server/templates/server/src/migrations/support/schema.ts.ejs +202 -0
  183. package/generators/node-server/templates/server/src/orm.config.ts.ejs +147 -0
  184. package/generators/node-server/templates/server/src/registry/consul.service.ts.ejs +70 -0
  185. package/generators/node-server/templates/server/src/registry/eureka.service.ts.ejs +129 -0
  186. package/generators/node-server/templates/server/src/swagger.ts.ejs +24 -0
  187. package/generators/node-server/templates/server/src/tls.ts.ejs +27 -0
  188. package/generators/node-server/templates/server/src/users/authority.controller.ts.ejs +85 -0
  189. package/generators/node-server/templates/server/src/users/authority.entity.ts.ejs +22 -0
  190. package/generators/node-server/templates/server/src/users/dto/authority.dto.ts.ejs +10 -0
  191. package/generators/node-server/templates/server/src/users/dto/user.dto.ts.ejs +116 -0
  192. package/generators/node-server/templates/server/src/users/public.user.controller.ts.ejs +51 -0
  193. package/generators/node-server/templates/server/src/users/user.controller.ts.ejs +191 -0
  194. package/generators/node-server/templates/server/src/users/user.entity.ts.ejs +63 -0
  195. package/generators/node-server/templates/server/src/users/user.mapper.ts.ejs +26 -0
  196. package/generators/node-server/templates/server/src/users/user.module.ts.ejs +19 -0
  197. package/generators/node-server/templates/server/src/users/user.service.ts.ejs +156 -0
  198. package/generators/node-server/templates/server/tsconfig.build.json.ejs +9 -0
  199. package/generators/node-server/templates/server/tsconfig.json.ejs +23 -0
  200. package/generators/node-server/templates/server/typeorm-migration.ts.ejs +18 -0
  201. package/generators/node-server/templates/server/vitest.config.e2e.ts.ejs +16 -0
  202. package/generators/node-server/templates/server/vitest.config.ts.ejs +16 -0
  203. package/generators/server/command.js +7 -0
  204. package/generators/server/generator.js +20 -0
  205. package/generators/server/generators/bootstrap/command.js +5 -0
  206. package/generators/server/generators/bootstrap/generator.js +15 -0
  207. package/generators/server/generators/bootstrap/index.js +2 -0
  208. package/generators/server/index.js +2 -0
  209. package/package.json +75 -4
@@ -0,0 +1,40 @@
1
+ import type { MigrationInterface, QueryRunner } from 'typeorm';
2
+
3
+ import { <%= [nodejsConstraintsMigration.foreignKeys.length > 0 && 'createForeignKeys', nodejsConstraintsMigration.joinTables.length > 0 && 'createJoinTable'].filter(Boolean).join(', ') %> } from './support/schema.ts';
4
+
5
+ /**
6
+ * Added the constraints of the entity <%= entityClass %>: its foreign keys and its join tables, after the tables they
7
+ * reference.
8
+ */
9
+ export class <%= nodejsConstraintsMigration.className %> implements MigrationInterface {
10
+ public async up(queryRunner: QueryRunner): Promise<void> {
11
+ <%_ if (nodejsConstraintsMigration.foreignKeys.length > 0) { _%>
12
+ await createForeignKeys(queryRunner, '<%= nodejsConstraintsMigration.tableName %>', [
13
+ <%_ for (const foreignKey of nodejsConstraintsMigration.foreignKeys) { _%>
14
+ { columnName: '<%= foreignKey.columnName %>', referencedTableName: '<%= foreignKey.referencedTableName %>', referencedColumnName: '<%= foreignKey.referencedColumnName %>' },
15
+ <%_ } _%>
16
+ ]);
17
+ <%_ } _%>
18
+ <%_ for (const joinTable of nodejsConstraintsMigration.joinTables) { _%>
19
+ await createJoinTable(
20
+ queryRunner,
21
+ '<%= joinTable.name %>',
22
+ <%_ for (const column of [joinTable.joinColumn, joinTable.inverseJoinColumn]) { _%>
23
+ { name: '<%= column.name %>', type: <%- column.type %>, referencedTableName: '<%= column.referencedTableName %>', referencedColumnName: '<%= column.referencedColumnName %>' },
24
+ <%_ } _%>
25
+ );
26
+ <%_ } _%>
27
+ }
28
+
29
+ public async down(queryRunner: QueryRunner): Promise<void> {
30
+ <%_ for (const joinTable of nodejsConstraintsMigration.joinTables) { _%>
31
+ await queryRunner.dropTable('<%= joinTable.name %>', true);
32
+ <%_ } _%>
33
+ <%_ if (nodejsConstraintsMigration.foreignKeys.length > 0) { _%>
34
+ const table = await queryRunner.getTable('<%= nodejsConstraintsMigration.tableName %>');
35
+ if (table) {
36
+ await queryRunner.dropForeignKeys(table, table.foreignKeys);
37
+ }
38
+ <%_ } _%>
39
+ }
40
+ }
@@ -0,0 +1,26 @@
1
+ import type { MigrationInterface, QueryRunner } from 'typeorm';
2
+
3
+ import { auditColumns, createTable } from './support/schema.ts';
4
+
5
+ /** Added the entity <%= entityClass %>. */
6
+ export class <%= nodejsMigration.className %> implements MigrationInterface {
7
+ public async up(queryRunner: QueryRunner): Promise<void> {
8
+ await createTable(
9
+ queryRunner,
10
+ '<%= nodejsMigration.tableName %>',
11
+ [
12
+ ...auditColumns(queryRunner),
13
+ <%_ for (const column of nodejsMigration.columns) { _%>
14
+ { name: '<%= column.name %>', type: <%- column.type %><% if (column.enum) { %>, enum: <%- column.enum %><% } %><% if (column.length) { %>, length: <%= column.length %><% } %><% if (column.precision) { %>, precision: <%= column.precision %>, scale: <%= column.scale %><% } %><% if (column.primary) { %>, primary: true, generated: '<%= column.generated %>'<% } %><% if (column.nullable) { %>, nullable: true<% } %><% if (column.unique) { %>, unique: true<% } %> },
15
+ <%_ } _%>
16
+ ],
17
+ <%_ if (nodejsMigration.relationUniques.length > 0) { _%>
18
+ { relationUniques: [<%- nodejsMigration.relationUniques.map(name => `'${name}'`).join(', ') %>] },
19
+ <%_ } _%>
20
+ );
21
+ }
22
+
23
+ public async down(queryRunner: QueryRunner): Promise<void> {
24
+ await queryRunner.dropTable('<%= nodejsMigration.tableName %>', true);
25
+ }
26
+ }
@@ -0,0 +1,202 @@
1
+ import { type ColumnType, type QueryRunner, Table, type TableColumnOptions, TableForeignKey } from 'typeorm';
2
+ import type { ColumnMetadata } from 'typeorm/metadata/ColumnMetadata.js';
3
+
4
+ import { databaseColumnType, databaseDatetimePrecision } from '../../common/database/column-types.ts';
5
+
6
+ /**
7
+ * A column of a migration, with the options of the @Column decorator of its entity: the driver of the database gives its
8
+ * type, its length and its default like it does for the entity, so the table is the one the entity maps.
9
+ */
10
+ export interface MigrationColumn {
11
+ name: string;
12
+ /** String, Number, Boolean, Date or a type of the database, like the type of the @Column decorator. */
13
+ type: ColumnType;
14
+ length?: number;
15
+ precision?: number;
16
+ scale?: number;
17
+ nullable?: boolean;
18
+ unique?: boolean;
19
+ default?: unknown;
20
+ onUpdate?: string;
21
+ primary?: boolean;
22
+ generated?: 'increment' | 'uuid';
23
+ enum?: string[];
24
+ }
25
+
26
+ /** A foreign key of a migration: the column of the table referencing the primary key of another table. */
27
+ export interface MigrationForeignKey {
28
+ columnName: string;
29
+ referencedTableName: string;
30
+ referencedColumnName: string;
31
+ onDelete?: string;
32
+ onUpdate?: string;
33
+ }
34
+
35
+ const tableColumn = (queryRunner: QueryRunner, migrationColumn: MigrationColumn): TableColumnOptions => {
36
+ const { driver } = queryRunner.connection;
37
+ // The type and the precision of the database, like the ones the @Column decorators give (common/database/column-types.ts).
38
+ const instant = migrationColumn.type === Date && migrationColumn.precision === undefined;
39
+ const column = {
40
+ ...migrationColumn,
41
+ type: databaseColumnType(driver.options.type, migrationColumn.type),
42
+ ...(instant ? { precision: databaseDatetimePrecision(driver.options.type) } : {}),
43
+ };
44
+ // The properties of the column metadata the driver reads.
45
+ const metadata = {
46
+ ...column,
47
+ databaseName: column.name,
48
+ isArray: false,
49
+ isNullable: column.nullable ?? false,
50
+ isPrimary: column.primary ?? false,
51
+ isGenerated: !!column.generated,
52
+ generationStrategy: column.generated,
53
+ } as unknown as ColumnMetadata;
54
+ const type = driver.normalizeType(metadata);
55
+ // A uuid is a varchar(36) of MySQL, the column referencing one too, like TypeORM gives it to a join column.
56
+ const uuidLength = ['mysql', 'mariadb', 'aurora-mysql'].includes(driver.options.type) && column.type === 'uuid' && type !== 'uuid';
57
+ return {
58
+ name: column.name,
59
+ type,
60
+ length: uuidLength && !column.length ? '36' : driver.getColumnLength(metadata),
61
+ precision: column.precision,
62
+ scale: column.scale,
63
+ default: driver.normalizeDefault(metadata),
64
+ onUpdate: column.onUpdate,
65
+ isNullable: metadata.isNullable,
66
+ isPrimary: metadata.isPrimary,
67
+ isUnique: column.unique ?? false,
68
+ isGenerated: metadata.isGenerated,
69
+ generationStrategy: column.generated,
70
+ enum: column.enum,
71
+ };
72
+ };
73
+
74
+ /** The audit columns of the entities extending BaseEntity: createdBy, createdDate, lastModifiedBy, lastModifiedDate. */
75
+ export const auditColumns = (queryRunner: QueryRunner): MigrationColumn[] => {
76
+ const { mappedDataTypes } = queryRunner.connection.driver;
77
+ return [
78
+ { name: 'createdBy', type: String, nullable: true },
79
+ {
80
+ name: 'createdDate',
81
+ type: mappedDataTypes.createDate,
82
+ precision: mappedDataTypes.createDatePrecision,
83
+ default: () => mappedDataTypes.createDateDefault,
84
+ nullable: true,
85
+ },
86
+ { name: 'lastModifiedBy', type: String, nullable: true },
87
+ {
88
+ name: 'lastModifiedDate',
89
+ type: mappedDataTypes.updateDate,
90
+ precision: mappedDataTypes.updateDatePrecision,
91
+ default: () => mappedDataTypes.updateDateDefault,
92
+ onUpdate: mappedDataTypes.updateDateDefault,
93
+ nullable: true,
94
+ },
95
+ ];
96
+ };
97
+
98
+ /**
99
+ * The databases storing the unique constraints as unique indices, like TypeORM does: the unique columns and the one-to-one
100
+ * join columns of MySQL and MariaDB, the one-to-one join columns of SQL Server (a filtered index, allowing several nulls).
101
+ */
102
+ const uniqueIndexDatabases = ['mysql', 'mariadb', 'aurora-mysql', 'sap', 'spanner'];
103
+
104
+ /**
105
+ * Creates a table, unless it exists: a database created by a former version of the application (its schema synchronized
106
+ * from the entities) has it already.
107
+ */
108
+ export const createTable = async (
109
+ queryRunner: QueryRunner,
110
+ name: string,
111
+ columns: MigrationColumn[],
112
+ options: { relationUniques?: string[] } = {},
113
+ ): Promise<void> => {
114
+ const { driver, namingStrategy } = queryRunner.connection;
115
+ const uniqueIndices = uniqueIndexDatabases.includes(driver.options.type);
116
+ const relationUniqueIndices = uniqueIndices || driver.options.type === 'mssql';
117
+ // The unique constraint of the join column of a one-to-one relationship, named like TypeORM names it.
118
+ const relationUniques = (options.relationUniques ?? []).map(columnName => ({
119
+ name: namingStrategy.relationConstraintName(name, [columnName]),
120
+ columnNames: [columnName],
121
+ }));
122
+ await queryRunner.createTable(
123
+ new Table({
124
+ name,
125
+ columns: columns.map(column => tableColumn(queryRunner, { ...column, unique: column.unique && !uniqueIndices })),
126
+ uniques: relationUniqueIndices ? [] : relationUniques,
127
+ indices: [
128
+ ...(uniqueIndices ? columns.filter(column => column.unique).map(column => ({ columnNames: [column.name], isUnique: true })) : []),
129
+ ...(relationUniqueIndices
130
+ ? relationUniques.map(unique => ({
131
+ ...unique,
132
+ isUnique: true,
133
+ where: driver.options.type === 'mssql' ? `${driver.escape(unique.columnNames[0])} IS NOT NULL` : undefined,
134
+ }))
135
+ : []),
136
+ ],
137
+ }),
138
+ true,
139
+ );
140
+ };
141
+
142
+ /**
143
+ * Creates the foreign keys of a table missing in the database: a database created by a former version of the application
144
+ * has them already.
145
+ */
146
+ export const createForeignKeys = async (queryRunner: QueryRunner, tableName: string, foreignKeys: MigrationForeignKey[]): Promise<void> => {
147
+ const table = await queryRunner.getTable(tableName);
148
+ if (!table) {
149
+ throw new Error(`The table ${tableName} does not exist`);
150
+ }
151
+ const missing = foreignKeys.filter(
152
+ foreignKey =>
153
+ !table.foreignKeys.some(existing => existing.columnNames.length === 1 && existing.columnNames[0] === foreignKey.columnName),
154
+ );
155
+ if (missing.length > 0) {
156
+ await queryRunner.createForeignKeys(
157
+ table,
158
+ missing.map(
159
+ ({ columnName, referencedTableName, referencedColumnName, onDelete, onUpdate }) =>
160
+ new TableForeignKey({
161
+ columnNames: [columnName],
162
+ referencedTableName,
163
+ referencedColumnNames: [referencedColumnName],
164
+ // The actions of the foreign keys of TypeORM, declared: the default of some databases differs (RESTRICT).
165
+ onDelete: onDelete ?? 'NO ACTION',
166
+ onUpdate: onUpdate ?? 'NO ACTION',
167
+ }),
168
+ ),
169
+ );
170
+ }
171
+ };
172
+
173
+ /**
174
+ * Creates the join table of a many-to-many relationship, with its indices and its foreign keys, unless it exists, like
175
+ * TypeORM creates the junction table of a @JoinTable.
176
+ */
177
+ export const createJoinTable = async (
178
+ queryRunner: QueryRunner,
179
+ name: string,
180
+ joinColumn: MigrationColumn & { referencedTableName: string; referencedColumnName: string },
181
+ inverseJoinColumn: MigrationColumn & { referencedTableName: string; referencedColumnName: string },
182
+ ): Promise<void> => {
183
+ const exists = await queryRunner.hasTable(name);
184
+ if (exists) return;
185
+ const columns = [joinColumn, inverseJoinColumn];
186
+ await queryRunner.createTable(
187
+ new Table({
188
+ name,
189
+ columns: columns.map(({ referencedTableName: _table, referencedColumnName: _column, ...column }) =>
190
+ tableColumn(queryRunner, { ...column, primary: true }),
191
+ ),
192
+ indices: columns.map(column => ({ columnNames: [column.name] })),
193
+ foreignKeys: columns.map(column => ({
194
+ columnNames: [column.name],
195
+ referencedTableName: column.referencedTableName,
196
+ referencedColumnNames: [column.referencedColumnName],
197
+ onDelete: 'CASCADE',
198
+ onUpdate: 'CASCADE',
199
+ })),
200
+ }),
201
+ );
202
+ };
@@ -0,0 +1,147 @@
1
+ import { createRequire } from 'module';
2
+ import { TypeOrmModuleOptions } from '@nestjs/typeorm';
3
+ <%_ if (generateBuiltInAuthorityEntity) { _%>
4
+ import { SeedUsersRoles1570200490072 } from './migrations/1570200490072-SeedUsersRoles.ts';
5
+ <%_ } _%>
6
+ <%_ if (databaseTypeMongodb || generateBuiltInUserEntity || generateBuiltInAuthorityEntity) { _%>
7
+ import { CreateTables1570200270081 } from './migrations/1570200270081-CreateTables.ts';
8
+ <%_ } _%>
9
+ <%_ if (authenticationUsesCsrf && databaseTypeSql) { _%>
10
+ import { CreateSessions1570200270082 } from './migrations/1570200270082-CreateSessions.ts';
11
+ <%_ } _%>
12
+ // jhipster-needle-add-entity-to-ormconfig-imports - JHipster will add code here, do not remove
13
+
14
+ import { activeProfiles, config } from './config.ts';
15
+
16
+ /** Reads a property of the configuration: ConfigService in the application, config outside of it (the typeorm CLI). */
17
+ export type ConfigReader = (key: string) => any;
18
+
19
+ // typeorm fails to auto load the drivers due to workspaces resolution: the driver of each database type, required when
20
+ // its database is used.
21
+ const require = createRequire(import.meta.url);
22
+ <%_ if (prodDatabaseTypePostgresql) { _%>
23
+
24
+ /**
25
+ * The pg driver keeping the instants in UTC, like the hibernate.jdbc.time_zone of JHipster Spring Boot: a timestamp
26
+ * (without time zone) is sent and read as UTC, not as the local time of the server.
27
+ */
28
+ function pgDriver(): unknown {
29
+ const pg = require('pg');
30
+ pg.defaults.parseInputDatesAsUTC = true;
31
+ pg.types.setTypeParser(pg.types.builtins.TIMESTAMP, (value: string) => new Date(`${value.replace(' ', 'T')}Z`));
32
+ return pg;
33
+ }
34
+ <%_ } _%>
35
+ const drivers: Record<string, () => unknown> = {
36
+ <%_ if (databaseTypeSql) { _%>
37
+ <%_ if (prodDatabaseTypePostgresql) { _%>
38
+ '<%= nodeProdDatabaseType %>': pgDriver,
39
+ <%_ } else { _%>
40
+ '<%= nodeProdDatabaseType %>': () => require('<%= nodeProdDatabaseDriver %>'),
41
+ <%_ } _%>
42
+ 'better-sqlite3': () => require('better-sqlite3'),
43
+ <%_ } else { _%>
44
+ mongodb: () => require('mongodb'),
45
+ <%_ } _%>
46
+ };
47
+ <%_ if (databaseTypeMongodb) { _%>
48
+
49
+ /**
50
+ * An in-memory MongoDB server, created again when another one took its port: mongodb-memory-server draws a free port and
51
+ * releases it before mongod listens on it, so the test files running in parallel can draw the same port.
52
+ */
53
+ async function createMongoMemoryServer(
54
+ MongoMemoryServer: typeof import('mongodb-memory-server').MongoMemoryServer,
55
+ attempts = 3,
56
+ ): Promise<import('mongodb-memory-server').MongoMemoryServer> {
57
+ try {
58
+ return await MongoMemoryServer.create();
59
+ } catch (error) {
60
+ if (attempts > 1 && String(error).includes('already in use')) {
61
+ return createMongoMemoryServer(MongoMemoryServer, attempts - 1);
62
+ }
63
+ throw error;
64
+ }
65
+ }
66
+ <%_ } _%>
67
+
68
+ /**
69
+ * The TypeORM options of the database of the active profiles: the database section of their application-{profile}.yml
70
+ * files, which environment variables override (DATABASE_HOST, DATABASE_PASSWORD, ...).
71
+ */
72
+ <%_ if (databaseTypeMongodb) { _%>
73
+ async function ormConfig(read: ConfigReader = key => config.get(key)): Promise<TypeOrmModuleOptions> {
74
+ <%_ } else { _%>
75
+ function ormConfig(read: ConfigReader = key => config.get(key)): TypeOrmModuleOptions {
76
+ <%_ } _%>
77
+ const type = read('database.type');
78
+ const driver = drivers[type];
79
+ if (!driver) {
80
+ throw new Error(`The database.type '${type}' of the ${activeProfiles.join(',')} profiles is not supported`);
81
+ }
82
+ <%= databaseTypeMongodb ? 'let' : 'const' %> host = read('database.host');
83
+ <%= databaseTypeMongodb ? 'let' : 'const' %> port = read('database.port');
84
+ <%= databaseTypeMongodb ? 'let' : 'const' %> database = read('database.name');
85
+ <%_ if (databaseTypeMongodb) { _%>
86
+ if (read('database.embedded')) {
87
+ // An in-memory MongoDB server, mongodb-memory-server is a dev dependency only loaded for it (test profile).
88
+ const { MongoMemoryServer } = await import('mongodb-memory-server');
89
+ const mongod = await createMongoMemoryServer(MongoMemoryServer);
90
+ host = '127.0.0.1';
91
+ port = mongod.instanceInfo?.port;
92
+ database = mongod.instanceInfo?.dbName;
93
+ }
94
+ <%_ } _%>
95
+
96
+ return {
97
+ type,
98
+ driver: driver(),
99
+ host,
100
+ port,
101
+ username: read('database.username'),
102
+ password: read('database.password'),
103
+ database,
104
+ <%_ if (prodDatabaseTypeMysql || prodDatabaseTypeMariadb) { _%>
105
+ // The instants in UTC, like the hibernate.jdbc.time_zone of JHipster Spring Boot (better-sqlite3 ignores it).
106
+ timezone: 'Z',
107
+ <%_ } _%>
108
+ logging: read('database.logging') ?? false,
109
+ synchronize: read('database.synchronize') ?? false,
110
+ migrationsRun: true,
111
+ <%_ if (databaseTypeMongodb) { _%>
112
+ // each migration runs in its own transaction, unless it sets transaction = false (CreateTables)
113
+ <%_ } else { _%>
114
+ // each migration runs in its own transaction
115
+ <%_ } _%>
116
+ migrationsTransactionMode: 'each',
117
+ entities: [
118
+ // jhipster-needle-add-entity-to-ormconfig-entities - JHipster will add code here, do not remove
119
+ ],
120
+ migrations: [
121
+ <%_ if (databaseTypeMongodb || generateBuiltInUserEntity || generateBuiltInAuthorityEntity) { _%>
122
+ CreateTables1570200270081,
123
+ <%_ } _%>
124
+ <%_ if (authenticationUsesCsrf && databaseTypeSql) { _%>
125
+ CreateSessions1570200270082,
126
+ <%_ } _%>
127
+ <%_ if (generateBuiltInAuthorityEntity) { _%>
128
+ SeedUsersRoles1570200490072,
129
+ <%_ } _%>
130
+ // jhipster-needle-add-migration-to-ormconfig-migrations - JHipster will add code here, do not remove
131
+ ],
132
+ autoLoadEntities: true,
133
+ // A bounded start: TypeORM tries to connect (and to run the migrations) 5 times, 3 seconds apart (10 times by default), then the start fails
134
+ // and the process exits, for the container orchestrator (docker compose, Kubernetes) to restart it.
135
+ retryAttempts: 5,
136
+ retryDelay: 3000,
137
+ // The retry logs tell the error of the connection.
138
+ verboseRetryLog: true,
139
+ <%_ if (prodDatabaseTypeMssql) { _%>
140
+ extra: {
141
+ trustServerCertificate: true,
142
+ },
143
+ <%_ } _%>
144
+ };
145
+ }
146
+
147
+ export { ormConfig };
@@ -0,0 +1,70 @@
1
+ import { hostname } from 'os';
2
+
3
+ import { BeforeApplicationShutdown, Injectable, Logger } from '@nestjs/common';
4
+ import { ConfigService } from '@nestjs/config';
5
+ import Consul from 'consul';
6
+
7
+ import type { ApplicationConfig } from '../application-config.ts';
8
+ import { activeProfiles } from '../config.ts';
9
+
10
+ /**
11
+ * The registration of the application in Consul, like Spring Cloud Consul: the service of cloud.consul.discovery with
12
+ * the HTTP health check of the application, registered once it listens and deregistered when it stops, so a gateway
13
+ * routes to it while it answers only.
14
+ */
15
+ @Injectable()
16
+ export class ConsulService implements BeforeApplicationShutdown {
17
+ private readonly logger = new Logger('ConsulService');
18
+
19
+ constructor(private readonly configService: ConfigService<ApplicationConfig, true>) {}
20
+ private consul?: Consul;
21
+ private serviceId?: string;
22
+
23
+ /** Registers the application listening on the port, when cloud.consul.enabled. */
24
+ async register(port: number): Promise<void> {
25
+ const { enabled, host, port: consulPort, discovery } = this.configService.get('cloud.consul', { infer: true });
26
+ if (!enabled) {
27
+ return;
28
+ }
29
+ const consul = new Consul({ host, port: Number(consulPort) });
30
+ const name = discovery['service-name'];
31
+ const id = discovery['instance-id'];
32
+ const address = discovery['prefer-ip-address'] ? this.configService.get('ipAddress', { infer: true }) || '127.0.0.1' : hostname();
33
+ this.logger.log(`Registering ${name} with Consul at ${host}:${consulPort}`);
34
+ try {
35
+ await consul.agent.service.register({
36
+ name,
37
+ id,
38
+ address,
39
+ port,
40
+ tags: [`profile=${activeProfiles.join(',')}`],
41
+ check: {
42
+ name: `Service '${name}' check`,
43
+ http: `http://${address}:${port}${discovery['health-check-path']}`,
44
+ interval: discovery['health-check-interval'],
45
+ timeout: discovery['health-check-timeout'],
46
+ },
47
+ });
48
+ this.consul = consul;
49
+ this.serviceId = id;
50
+ this.logger.log('Consul registration complete');
51
+ } catch (error) {
52
+ this.logger.error(`Consul registration failed: ${error instanceof Error ? error.message : String(error)}`);
53
+ }
54
+ }
55
+
56
+ /** Deregisters the application before the server stops, so a gateway no longer routes to it. */
57
+ async beforeApplicationShutdown(): Promise<void> {
58
+ const { consul, serviceId } = this;
59
+ if (!consul || !serviceId) {
60
+ return;
61
+ }
62
+ this.consul = undefined;
63
+ try {
64
+ await consul.agent.service.deregister(serviceId);
65
+ this.logger.log('Consul deregistration complete');
66
+ } catch (error) {
67
+ this.logger.warn(`Consul deregistration failed: ${error instanceof Error ? error.message : String(error)}`);
68
+ }
69
+ }
70
+ }
@@ -0,0 +1,129 @@
1
+ import { createRequire } from 'module';
2
+ import { hostname } from 'os';
3
+
4
+ import { BeforeApplicationShutdown, Injectable, Logger } from '@nestjs/common';
5
+ import { ConfigService } from '@nestjs/config';
6
+
7
+ import type { ApplicationConfig } from '../application-config.ts';
8
+ import { isProfileActive } from '../config.ts';
9
+
10
+ /** The client of eureka-js-client (the maintained fork of Rocket Software), which has no types. */
11
+ interface EurekaClient {
12
+ start(callback: (error?: Error) => void): void;
13
+ stop(callback: (error?: Error) => void): void;
14
+ startHeartbeats(): void;
15
+ startRegistryFetches(): void;
16
+ on(event: 'registered', listener: () => void): void;
17
+ logger: { level(level: string): void };
18
+ }
19
+
20
+ /**
21
+ * The registration of the application in the Eureka server (the JHipster Registry), like Spring Cloud Netflix: at the
22
+ * eureka.client.service-url.defaultZone, once the application listens, with the intervals of the configuration, and
23
+ * cancelled when the application stops, so a gateway no longer routes to it.
24
+ */
25
+ @Injectable()
26
+ export class EurekaService implements BeforeApplicationShutdown {
27
+ private readonly logger = new Logger('EurekaService');
28
+
29
+ constructor(private readonly configService: ConfigService<ApplicationConfig, true>) {}
30
+ private client?: EurekaClient;
31
+
32
+ /** Registers the application listening on the port, when eureka.client.enabled. */
33
+ register(port: number): void {
34
+ if (!this.configService.get('eureka.client.enabled', { infer: true })) {
35
+ return;
36
+ }
37
+ const serviceUrl = new URL(this.configService.get('eureka.client.service-url.defaultZone', { infer: true }));
38
+ const appName = this.configService.get('eureka.instance.appname', { infer: true });
39
+ const ipAddress = this.configService.get('ipAddress', { infer: true }) || '127.0.0.1';
40
+ const hostName = this.configService.get('eureka.instance.prefer-ip-address', { infer: true }) ? ipAddress : hostname();
41
+ const baseUrl = `http://${hostName}:${port}`;
42
+ const leaseRenewalInterval = Number(this.configService.get('eureka.instance.lease-renewal-interval-in-seconds', { infer: true }));
43
+ const user = decodeURIComponent(serviceUrl.username) || this.configService.get('jhipster.registry.username', { infer: true }) || 'admin';
44
+ const password = decodeURIComponent(serviceUrl.password) || this.configService.get('jhipster.registry.password', { infer: true }) || 'admin';
45
+ const { Eureka } = createRequire(import.meta.url)('@rocketsoftware/eureka-js-client');
46
+ const client: EurekaClient = new Eureka({
47
+ instance: {
48
+ app: appName,
49
+ instanceId: this.configService.get('eureka.instance.instanceId', { infer: true }),
50
+ hostName,
51
+ ipAddr: ipAddress,
52
+ status: 'UP',
53
+ port: { $: port, '@enabled': 'true' },
54
+ // The service id Spring Cloud looks the instances up by (the routes of a JHipster gateway), like its spring.application.name.
55
+ vipAddress: appName,
56
+ homePageUrl: `${baseUrl}/`,
57
+ statusPageUrl: `${baseUrl}/management/info`,
58
+ healthCheckUrl: `${baseUrl}/management/health`,
59
+ leaseInfo: {
60
+ renewalIntervalInSecs: leaseRenewalInterval,
61
+ durationInSecs: Number(this.configService.get('eureka.instance.lease-expiration-duration-in-seconds', { infer: true })),
62
+ },
63
+ dataCenterInfo: {
64
+ '@class': 'com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo',
65
+ name: 'MyOwn',
66
+ },
67
+ },
68
+ eureka: {
69
+ host: serviceUrl.hostname,
70
+ port: Number(serviceUrl.port) || (serviceUrl.protocol === 'https:' ? 443 : 80),
71
+ ssl: serviceUrl.protocol === 'https:',
72
+ servicePath: `${serviceUrl.pathname.replace(/\/$/, '')}/apps/`,
73
+ heartbeatInterval: leaseRenewalInterval * 1000,
74
+ registryFetchInterval: Number(this.configService.get('eureka.client.registry-fetch-interval-seconds', { infer: true })) * 1000,
75
+ fetchRegistry: this.configService.get('eureka.client.fetch-registry', { infer: true }),
76
+ registerWithEureka: this.configService.get('eureka.client.register-with-eureka', { infer: true }),
77
+ },
78
+ requestMiddleware: (requestOpts: any, done: (requestOpts: any) => void): void => {
79
+ requestOpts.auth = { user, password };
80
+ done(requestOpts);
81
+ },
82
+ });
83
+ // The requests to the Eureka server are logged in development only.
84
+ client.logger.level(isProfileActive('dev') ? 'debug' : 'warn');
85
+ this.logger.log(`Registering ${appName} with Eureka at ${serviceUrl.host}`);
86
+ let registered = false;
87
+ client.on('registered', () => {
88
+ registered = true;
89
+ });
90
+ client.start(error => {
91
+ if (!error) {
92
+ this.logger.log('Eureka registration complete');
93
+ return;
94
+ }
95
+ if (registered || !this.configService.get('eureka.client.register-with-eureka', { infer: true })) {
96
+ // The first registry fetch failed: the next ones are at its interval.
97
+ this.logger.warn(`Eureka registry fetch failed: ${error.message}`);
98
+ return;
99
+ }
100
+ this.logger.error(`Eureka registration failed, retried at each heartbeat: ${error.message}`);
101
+ // Registered by the first heartbeat the server answers (404 for an unknown instance), like the Eureka client of Spring
102
+ // Cloud keeps on registering: eureka-js-client starts the heartbeats and the registry fetches once registered only.
103
+ client.startHeartbeats();
104
+ if (this.configService.get('eureka.client.fetch-registry', { infer: true })) {
105
+ client.startRegistryFetches();
106
+ }
107
+ });
108
+ this.client = client;
109
+ }
110
+
111
+ /** Cancels the registration before the server stops, so a gateway no longer routes to the application. */
112
+ beforeApplicationShutdown(): Promise<void> {
113
+ const { client } = this;
114
+ if (!client) {
115
+ return Promise.resolve();
116
+ }
117
+ this.client = undefined;
118
+ return new Promise(resolve => {
119
+ client.stop(error => {
120
+ if (error) {
121
+ this.logger.warn(`Eureka deregistration failed: ${error.message}`);
122
+ } else {
123
+ this.logger.log('Eureka deregistration complete');
124
+ }
125
+ resolve();
126
+ });
127
+ });
128
+ }
129
+ }
@@ -0,0 +1,24 @@
1
+ import { Logger, INestApplication } from '@nestjs/common';
2
+ import { ConfigService } from '@nestjs/config';
3
+ import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
4
+
5
+ import { ApiDocsService } from './management/api-docs.service.ts';
6
+
7
+ export function setupSwagger(app: INestApplication): any {
8
+
9
+ const logger: Logger = new Logger('Swagger');
10
+ const configService = app.get(ConfigService);
11
+
12
+ const options = new DocumentBuilder()
13
+ .setTitle(configService.getOrThrow<string>('jhipster.swagger.title'))
14
+ .setDescription(configService.getOrThrow<string>('jhipster.swagger.description'))
15
+ .setVersion(configService.getOrThrow<string>('jhipster.swagger.version'))
16
+ <%_ if (authenticationType === 'jwt') { _%>
17
+ .addBearerAuth()
18
+ <%_ } _%>
19
+ .build();
20
+ // Served by ApiDocsController at /v3/api-docs, the path of springdoc, for the administrators.
21
+ app.get(ApiDocsService).document = SwaggerModule.createDocument(app, options);
22
+ logger.log('Added the API documentation on /v3/api-docs');
23
+
24
+ }
@@ -0,0 +1,27 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { HttpsOptions } from '@nestjs/common/interfaces/external/https-options.interface';
4
+ import { config } from './config.ts';
5
+
6
+ /**
7
+ * The HTTPS options of the server.ssl properties, like Spring Boot: the tls profile enables them (server.ssl.enabled)
8
+ * and the tls-samples profile adds the self-signed sample keystore. The keystore is a PKCS#12 file, a path relative to
9
+ * the working directory, or classpath:config/... for a file of the config folder (copied to dist with the yml files).
10
+ */
11
+ export function httpsOptions(): HttpsOptions | undefined {
12
+ if (!config.get('server.ssl.enabled')) {
13
+ return undefined;
14
+ }
15
+ const keyStoreType = config.get('server.ssl.key-store-type');
16
+ if (keyStoreType !== 'PKCS12') {
17
+ throw new Error(`The server.ssl.key-store-type '${keyStoreType}' is not supported, use a PKCS12 keystore`);
18
+ }
19
+ const keyStore = config.get('server.ssl.key-store');
20
+ if (!keyStore) {
21
+ throw new Error('TLS is enabled without a keystore: set server.ssl.key-store, or activate the tls-samples profile in development');
22
+ }
23
+ return {
24
+ pfx: fs.readFileSync(keyStore.startsWith('classpath:') ? path.join(import.meta.dirname, keyStore.substring('classpath:'.length)) : keyStore),
25
+ passphrase: config.get('server.ssl.key-store-password'),
26
+ };
27
+ }