generator-jhipster 7.4.0 → 7.4.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 (51) hide show
  1. package/cli/import-jdl.js +3 -2
  2. package/cli/program.js +1 -0
  3. package/generators/app/index.js +5 -1
  4. package/generators/bootstrap/index.js +24 -20
  5. package/generators/client/files-common.js +1 -1
  6. package/generators/client/files-react.js +3 -1
  7. package/generators/client/index.js +2 -2
  8. package/generators/client/needle-api/needle-client-angular.js +1 -1
  9. package/generators/client/needle-api/needle-client-vue.js +56 -6
  10. package/generators/client/templates/angular/package.json +7 -7
  11. package/generators/client/templates/common/package.json +2 -2
  12. package/generators/client/templates/react/package.json +20 -20
  13. package/generators/client/templates/react/package.json.ejs +1 -1
  14. package/generators/client/templates/vue/package.json +13 -13
  15. package/generators/client/templates/vue/src/main/webapp/app/account/account.service.ts.ejs +3 -1
  16. package/generators/client/templates/vue/src/main/webapp/app/core/jhi-navbar/jhi-navbar.component.ts.ejs +14 -5
  17. package/generators/client/templates/vue/src/main/webapp/app/declarations.d.ts.ejs +2 -2
  18. package/generators/client/templates/vue/src/main/webapp/app/entities/entities.component.ts.ejs +2 -0
  19. package/generators/client/templates/vue/src/main/webapp/app/main.ts.ejs +11 -6
  20. package/generators/client/templates/vue/src/main/webapp/app/router/entities.ts.ejs +2 -3
  21. package/generators/client/templates/vue/src/main/webapp/app/router/index.ts.ejs +19 -14
  22. package/generators/client/templates/vue/src/test/javascript/jest.conf.js.ejs +2 -2
  23. package/generators/client/templates/vue/src/test/javascript/spec/app/account/login-form/login-form.component.spec.ts.ejs +2 -2
  24. package/generators/client/templates/vue/src/test/javascript/spec/app/admin/user-management/user-management-edit.component.spec.ts.ejs +2 -0
  25. package/generators/client/templates/vue/src/test/javascript/spec/app/admin/user-management/user-management.component.spec.ts.ejs +2 -0
  26. package/generators/client/templates/vue/src/test/javascript/spec/app/core/jhi-navbar/jhi-navbar.component.spec.ts.ejs +10 -4
  27. package/generators/client/templates/vue/tsconfig.json.ejs +1 -1
  28. package/generators/client/templates/vue/tsconfig.spec.json.ejs +1 -1
  29. package/generators/client/templates/vue/webpack/webpack.microfrontend.js.jhi.vue.ejs +1 -1
  30. package/generators/common/templates/README.md.jhi.ejs +21 -0
  31. package/generators/common/templates/package.json +1 -1
  32. package/generators/cypress/templates/cypress.json.ejs +1 -1
  33. package/generators/cypress/templates/src/test/javascript/cypress/plugins/index.ts.ejs +1 -1
  34. package/generators/entity/index.js +7 -1
  35. package/generators/entity-client/files.js +3 -7
  36. package/generators/entity-client/index.js +1 -5
  37. package/generators/entity-client/templates/common/src/test/javascript/cypress/integration/entity/entity.spec.ts.ejs +9 -3
  38. package/generators/entity-client/templates/react/src/main/webapp/app/entities/entity.tsx.ejs +4 -6
  39. package/generators/entity-client/templates/vue/src/main/webapp/app/entities/entity-update.component.ts.ejs +1 -5
  40. package/generators/entity-client/templates/vue/src/test/javascript/spec/app/entities/entity-update.component.spec.ts.ejs +6 -1
  41. package/generators/entity-client/templates/vue/src/test/javascript/spec/app/entities/entity.component.spec.ts.ejs +5 -1
  42. package/generators/generator-base-blueprint.js +7 -2
  43. package/generators/generator-base.js +31 -14
  44. package/generators/generator-constants.js +1 -1
  45. package/generators/generator-transforms.js +12 -4
  46. package/generators/languages/templates/src/main/webapp/i18n/vi/login.json +1 -1
  47. package/generators/server/index.js +9 -1
  48. package/generators/server/templates/src/main/resources/config/application.yml.ejs +5 -5
  49. package/generators/upgrade/index.js +1 -1
  50. package/package.json +7 -7
  51. package/generators/client/templates/react/.npmrc.ejs +0 -1
@@ -13,7 +13,7 @@ const <%= entity.entityAngularName %>Details = () => import('@/entities/<%= enti
13
13
  <%_ } _%>
14
14
  // jhipster-needle-add-entity-to-router-import - JHipster will import entities to the router here
15
15
 
16
- export default [
16
+ export default
17
17
  {
18
18
  path: '/<%= applicationTypeMicroservice ? baseName.toLowerCase() : '' %>',
19
19
  component: Entities,
@@ -48,5 +48,4 @@ export default [
48
48
  <%_ } _%>
49
49
  // jhipster-needle-add-entity-to-router - JHipster will add entities to the router here
50
50
  ],
51
- },
52
- ];
51
+ };
@@ -5,7 +5,7 @@ Component.registerHooks([
5
5
  'beforeRouteLeave',
6
6
  'beforeRouteUpdate' // for vue-router 2.2+
7
7
  ])
8
- import Router from 'vue-router';
8
+ import Router, { RouteConfig } from 'vue-router';
9
9
 
10
10
  const Home = () => import('@/core/home/home.vue');
11
11
  const Error = () => import('@/core/error/error.vue');
@@ -15,17 +15,11 @@ import account from "@/router/account";
15
15
  import admin from "@/router/admin";
16
16
  import entities from "@/router/entities";
17
17
  import pages from "@/router/pages";
18
- <%_ if (applicationTypeGateway && microfrontend) { _%>
19
-
20
- <%_ for (const remote of remotes) { _%>
21
- const <%= remote.lowercaseBaseName %>Router = await import('@<%= remote.lowercaseBaseName %>/entities-router').then(module => module.default).catch(() => []);
22
- <%_ } _%>
23
- <%_ } _%>
24
18
 
25
19
  Vue.use(Router);
26
20
 
27
21
  // prettier-ignore
28
- export default new Router({
22
+ const router = new Router({
29
23
  mode: 'history',
30
24
  routes: [
31
25
  {
@@ -49,12 +43,23 @@ export default new Router({
49
43
  ...account,
50
44
  <%_ } _%>
51
45
  ...admin,
52
- ...entities,
53
- <%_ if (applicationTypeGateway && microfrontend) { _%>
54
- <%_ for (const remote of remotes) { _%>
55
- ...<%= remote.lowercaseBaseName %>Router,
56
- <%_ } _%>
57
- <%_ } _%>
46
+ entities,
58
47
  ...pages
59
48
  ]
60
49
  });
50
+
51
+ <%_ if (applicationTypeGateway && microfrontend) { _%>
52
+ export const lazyRoutes = Promise.all([
53
+ <%_ for (const remote of microfrontends) { _%>
54
+ import('@<%= remote.lowercaseBaseName %>/entities-router')
55
+ .then(<%= remote.lowercaseBaseName %>Router => {
56
+ router.addRoute(<%= remote.lowercaseBaseName %>Router.default as RouteConfig);
57
+ return <%= remote.lowercaseBaseName %>Router.default;
58
+ }).catch(() => {
59
+ console.log("Error loading <%= remote.lowercaseBaseName %> menus. Make sure it's up.");
60
+ }),
61
+ <%_ } _%>
62
+ ]);
63
+
64
+ <%_ } _%>
65
+ export default router;
@@ -17,8 +17,8 @@ module.exports = {
17
17
  moduleNameMapper: {
18
18
  '^@/(.*)$': '<rootDir>/<%= CLIENT_MAIN_SRC_DIR %>app/$1',
19
19
  ...pathsToModuleNameMapper(paths, { prefix: `<rootDir>/${baseUrl}/` }),
20
- <%_ if (applicationTypeGateway) { _%>
21
- '^@(<%= remotes.map(remote => remote.lowercaseBaseName).join('|') %>)/(.*)$': '<rootDir>/<%= CLIENT_TEST_SRC_DIR %>spec/app/microfrontends/$2',
20
+ <%_ if (applicationTypeGateway && microfrontend) { _%>
21
+ '^@(<%= microfrontends.map(remote => remote.lowercaseBaseName).join('|') %>)/(.*)$': '<rootDir>/<%= CLIENT_TEST_SRC_DIR %>spec/app/microfrontends/$2',
22
22
  <%_ } _%>
23
23
  },
24
24
  reporters: [
@@ -2,7 +2,7 @@ import { shallowMount, createLocalVue, Wrapper } from '@vue/test-utils';
2
2
  import axios from 'axios';
3
3
  import sinon from 'sinon';
4
4
  import AccountService from '@/account/account.service';
5
- import router from '@/router';
5
+ import VueRouter from 'vue-router';
6
6
  <%_ if (enableTranslation) { _%>
7
7
  import TranslationService from '@/locale/translation.service';
8
8
  <%_ } _%>
@@ -50,7 +50,7 @@ describe('LoginForm Component', () => {
50
50
  <%_ } _%>
51
51
  localVue,
52
52
  provide: {
53
- accountService: () => new AccountService(store, <% if (enableTranslation) { %>new TranslationService(store, i18n), <% } %><% if (authenticationTypeSession) { %> { get: () => {} }, <% } %><% if (communicationSpringWebsocket) { %>new TrackerService(router<%_ if (authenticationTypeSession) { _%>,{ get: jest.fn()}<%_ } %>), <% } %>router)
53
+ accountService: () => new AccountService(store, <% if (enableTranslation) { %>new TranslationService(store, i18n), <% } %><% if (authenticationTypeSession) { %> { get: () => {} }, <% } %><% if (communicationSpringWebsocket) { %>new TrackerService(new VueRouter()<%_ if (authenticationTypeSession) { _%>,{ get: jest.fn()}<%_ } %>), <% } %>new VueRouter())
54
54
  }
55
55
  });
56
56
  loginForm = wrapper.vm;
@@ -11,10 +11,12 @@ import UserManagementEdit from '@/admin/user-management/user-management-edit.vue
11
11
  import UserManagementEditClass from '@/admin/user-management/user-management-edit.component';
12
12
  import UserManagementService from '@/admin/user-management/user-management.service';
13
13
  import VueRouter from 'vue-router';
14
+ import { ToastPlugin } from 'bootstrap-vue';
14
15
  import AlertService from '@/shared/alert/alert.service';
15
16
 
16
17
  const localVue = createLocalVue();
17
18
  localVue.use(VueRouter);
19
+ localVue.use(ToastPlugin);
18
20
 
19
21
  config.initVueApp(localVue);
20
22
  <%_ if (enableTranslation) { _%>
@@ -5,6 +5,7 @@ import { shallowMount, createLocalVue, Wrapper } from '@vue/test-utils';
5
5
  import axios from 'axios';
6
6
  import sinon from 'sinon';
7
7
  import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
8
+ import { ToastPlugin } from 'bootstrap-vue';
8
9
 
9
10
  import * as config from '@/shared/config/config';
10
11
  import UserManagement from '@/admin/user-management/user-management.vue';
@@ -14,6 +15,7 @@ import AlertService from '@/shared/alert/alert.service';
14
15
 
15
16
  const localVue = createLocalVue();
16
17
 
18
+ localVue.use(ToastPlugin);
17
19
  config.initVueApp(localVue);
18
20
  <%_ if (enableTranslation) { _%>
19
21
  const i18n = config.initI18N(localVue);
@@ -94,15 +94,21 @@ let wrapper: Wrapper<JhiNavbarClass>;
94
94
  expect(accountService.hasAnyAuthorityAndCheckAuth).toHaveBeenCalled();
95
95
  });
96
96
 
97
- it('logout should clear credentials', () => {
97
+ it('logout should clear credentials', async () => {
98
98
  store.commit('authenticated', { login: 'test' });
99
- <%_ if (!authenticationTypeJwt) { _%>
100
- loginService.logout.mockReturnValue(Promise.resolve());
99
+ <%_ if (authenticationTypeOauth2) { _%>
100
+ const logoutUrl = '/to-match';
101
+ loginService.logout.mockReturnValue(Promise.resolve({ data: { logoutUrl } }));
102
+ <%_ } else if (!authenticationTypeJwt) { _%>
103
+ loginService.logout.mockReturnValue(Promise.resolve({}));
101
104
  <%_ } _%>
102
- jhiNavbar.logout();
105
+ await jhiNavbar.logout();
103
106
 
104
107
  <%_ if (!authenticationTypeJwt) { _%>
105
108
  expect(loginService.logout).toHaveBeenCalled();
109
+ <%_ if (authenticationTypeOauth2) { _%>
110
+ expect(router.currentRoute.path).toBe(logoutUrl);
111
+ <%_ } _%>
106
112
  <%_ } else { _%>
107
113
  expect(jhiNavbar.authenticated).toBeFalsy();
108
114
  <%_ } _%>
@@ -24,5 +24,5 @@
24
24
  "include": [
25
25
  "<%= CLIENT_MAIN_SRC_DIR %>app"
26
26
  ],
27
- "exclude": ["node_modules"<% if (!cypressTests) { %>,"<%= CLIENT_TEST_SRC_DIR %>cypress"<% } %>]
27
+ "exclude": ["node_modules"<% if (cypressTests) { %>,"<%= CLIENT_TEST_SRC_DIR %>cypress"<% } %>]
28
28
  }
@@ -22,7 +22,7 @@
22
22
  "outDir": "<%= BUILD_DIR %>out-tsc/spec",
23
23
  <%_ if (microfrontend && applicationTypeGateway) { _%>
24
24
  "paths": {
25
- <%_ for (const remote of remotes) { _%>
25
+ <%_ for (const remote of microfrontends) { _%>
26
26
  "@<%= remote.lowercaseBaseName %>/*": ["<%= CLIENT_TEST_SRC_DIR %>spec/app/microfrontends/*"],
27
27
  <%_ } _%>
28
28
  "@/*": ["*"]
@@ -24,7 +24,7 @@ const { DefinePlugin } = require('webpack');
24
24
  <&_ if (fragment.moduleFederationSection) { -&>
25
25
  <%_ if (applicationTypeGateway) { _%>
26
26
  remotes: {
27
- <%_ for (const remote of remotes) { _%>
27
+ <%_ for (const remote of microfrontends) { _%>
28
28
  '@<%= remote.lowercaseBaseName %>': `<%= remote.lowercaseBaseName %>@/<%= remote.endpointPrefix %>/remoteEntry.js`,
29
29
  <%_ } _%>
30
30
  },
@@ -46,6 +46,27 @@ This is a "<%= applicationType %>" application intended to be part of a microser
46
46
  This application is configured for Service Discovery and Configuration with <% if (serviceDiscoveryEureka) { %>the JHipster-Registry<% } %><% if (serviceDiscoveryConsul) { %>Consul<% } %>. On launch, it will refuse to start if it is not able to connect to <% if (serviceDiscoveryEureka) { %>the JHipster-Registry at [http://localhost:8761](http://localhost:8761)<% } %><% if (serviceDiscoveryConsul) { %>Consul at [http://localhost:8500](http://localhost:8500)<% } %>.<% if (serviceDiscoveryEureka) { %> For more information, read our documentation on [Service Discovery and Configuration with the JHipster-Registry][].<% } %><% if (serviceDiscoveryConsul) { %> For more information, read our documentation on [Service Discovery and Configuration with Consul][].<% } %>
47
47
  <%_ } _%>
48
48
 
49
+ ## Project Structure
50
+
51
+ Node is required for generation and recommended for development. `package.json` is always generated for a better development experience with prettier, commit hooks, scripts and so on.
52
+
53
+ In the project root, JHipster generates configuration files for tools like git, prettier, eslint, husk, and others that are well known and you can find references in the web.
54
+
55
+ <%_ if (configOptions.backendName === 'Java') { %>
56
+ `/src/*` structure follows default <%= configOptions.backendName %> structure.
57
+
58
+ <%_ } _%>
59
+ - `.yo-rc.json` - Yeoman configuration file
60
+ JHipster configuration is stored in this file at `generator-jhipster` key. You may find `generator-jhipster-*` for specific blueprints configuration.
61
+ - `.yo-resolve` (optional) - Yeoman conflict resolver
62
+ Allows to use a specific action when conflicts are found skipping prompts for files that matches a pattern. Each line should match `[pattern] [action]` with pattern been a [Minimatch](https://github.com/isaacs/minimatch#minimatch) pattern and action been one of skip (default if ommited) or force. Lines starting with `#` are considered comments and are ignored.
63
+ - `.jhipster/*.json` - JHipster entity configuration files
64
+ <%_ if (buildToolMaven) { _%>
65
+ - `npmw` - wrapper to use locally installed npm.
66
+ JHipster installs Node and npm locally using the build tool by default. This wrapper makes sure npm is installed locally and uses it avoiding some differences different versions can cause. By using `./npmw` instead of the traditional `npm` you can configure a Node-less environment to develop your application.
67
+ <%_ } _%>
68
+ - `/src/main/docker` - Docker configurations for the application and services that the application depends on
69
+
49
70
  ## Development
50
71
 
51
72
  <%_ if (skipClient) { _%>
@@ -2,7 +2,7 @@
2
2
  "devDependencies": {
3
3
  "concurrently": "6.4.0",
4
4
  "husky": "7.0.4",
5
- "lint-staged": "12.0.2",
5
+ "lint-staged": "12.1.2",
6
6
  "npm": "8.1.4",
7
7
  "wait-on": "6.0.0"
8
8
  }
@@ -17,7 +17,7 @@
17
17
  limitations under the License.
18
18
  -%>
19
19
  {
20
- "baseUrl": "http://localhost:<%= serverPort %>/",
20
+ "baseUrl": "http://localhost:<%= gatewayServerPort || serverPort %>/",
21
21
  "testFiles": "**/*.spec.ts",
22
22
  "supportFile": "<%= CLIENT_TEST_SRC_DIR %>cypress/support/index.ts",
23
23
  "video": false,
@@ -41,7 +41,7 @@ module.exports = (on<%_ if (cypressCoverage) { _%>, config<%_ } _%>) => {
41
41
  prepareAudit(launchOptions);
42
42
  if (browser.name === 'chrome' && browser.isHeadless) {
43
43
  launchOptions.args.push('--disable-gpu');
44
- return launchOptions
44
+ return launchOptions;
45
45
  }
46
46
  });
47
47
 
@@ -204,7 +204,6 @@ class EntityGenerator extends BaseBlueprintGenerator {
204
204
  const context = this.context;
205
205
 
206
206
  if (this.jhipsterConfig.applicationType === MICROSERVICE) {
207
- context.skipClient = context.skipClient || !this.jhipsterConfig.microfrontend;
208
207
  context.microserviceName = this.entityConfig.microserviceName = this.jhipsterConfig.baseName;
209
208
  if (!this.entityConfig.clientRootFolder) {
210
209
  context.clientRootFolder = this.entityConfig.clientRootFolder = this.entityConfig.microserviceName;
@@ -232,6 +231,13 @@ class EntityGenerator extends BaseBlueprintGenerator {
232
231
  ? ''
233
232
  : this.entityConfig.microserviceName;
234
233
  }
234
+
235
+ if (this.jhipsterConfig.applications && !this.entityConfig.skipClient) {
236
+ const remoteConfig = this.jhipsterConfig.applications[this.entityConfig.microserviceName];
237
+ if (remoteConfig.clientFramework === 'vue') {
238
+ this.entityConfig.skipClient = true;
239
+ }
240
+ }
235
241
  }
236
242
  },
237
243
 
@@ -437,11 +437,7 @@ function addSampleRegexTestingStrings(generator) {
437
437
  function writeFiles() {
438
438
  return {
439
439
  writeClientFiles() {
440
- if (
441
- this.skipClient ||
442
- (this.jhipsterConfig.microfrontend && this.jhipsterConfig.applicationType === 'gateway' && this.microserviceName)
443
- )
444
- return undefined;
440
+ if (this.skipClient || (this.microfrontend && this.applicationTypeGateway && this.microserviceName)) return undefined;
445
441
  if (this.protractorTests) {
446
442
  addSampleRegexTestingStrings(this);
447
443
  }
@@ -478,12 +474,12 @@ function writeFiles() {
478
474
  }
479
475
 
480
476
  function addToMenu() {
481
- if (this.skipClient || this.clientFrameworkVue) return;
477
+ if (this.skipClient) return;
482
478
 
483
479
  if (!this.embedded) {
484
480
  this.addEntityToModule();
485
481
  this.addEntityToMenu(
486
- this.entityStateName,
482
+ this.entityPage,
487
483
  this.enableTranslation,
488
484
  this.clientFramework,
489
485
  this.entityTranslationKeyMenu,
@@ -157,11 +157,7 @@ module.exports = class extends BaseBlueprintGenerator {
157
157
  },
158
158
 
159
159
  replaceTranslations() {
160
- if (
161
- this.skipClient ||
162
- (this.jhipsterConfig.microfrontend && this.jhipsterConfig.applicationType === 'gateway' && this.microserviceName)
163
- )
164
- return undefined;
160
+ if (this.skipClient || (this.microfrontend && this.applicationTypeGateway && this.microserviceName)) return undefined;
165
161
  return replaceTranslations.call(this);
166
162
  },
167
163
  };
@@ -14,7 +14,7 @@ import {
14
14
  } from '../../support/entity';
15
15
  <%_
16
16
 
17
- const baseApi = (applicationTypeGateway && locals.microserviceName) ? 'services/' + microserviceName.toLowerCase() + '/api/' : 'api/';
17
+ const baseApi = entityApi + 'api/';
18
18
 
19
19
  const entityFakeData = generateFakeData('cypress');
20
20
  const requiredRelationships = relationships.filter(rel => rel.relationshipRequired || rel.id);
@@ -32,9 +32,15 @@ const skipCreateTest =
32
32
  const sampleFields = fields.filter(f => !f.autoGenerate && !f.nullable);
33
33
 
34
34
  if (workaroundRelationshipReactivePostgress && sampleFields.length === 0) {
35
- sampleFields.push(fields.find(f => !f.autoGenerate));
35
+ const sample = fields.find(f => !f.autoGenerate);
36
+ if (sample) {
37
+ sampleFields.push(sample);
38
+ }
36
39
  } else if (workaroundInstantReactiveMariaDB) {
37
- sampleFields.push(...fields.filter(f => !f.autoGenerate && f.nullable && f.fieldType === 'Instant'));
40
+ const samples = fields.filter(f => !f.autoGenerate && f.nullable && f.fieldType === 'Instant');
41
+ if (samples.length > 0) {
42
+ sampleFields.push(...samples);
43
+ }
38
44
  }
39
45
  _%>
40
46
 
@@ -18,7 +18,7 @@
18
18
  -%>
19
19
  import React, { useState, useEffect } from 'react';
20
20
  <%_ if (paginationInfiniteScroll) { _%>
21
- import InfiniteScroll from 'react-infinite-scroller';
21
+ import InfiniteScroll from 'react-infinite-scroll-component';
22
22
  <%_ } _%>
23
23
  import { Link, RouteComponentProps } from 'react-router-dom';
24
24
  import { Button, <% if (searchEngine) { %>Input, InputGroup, FormGroup, Form, Row, Col, <% } %>Table } from 'reactstrap';
@@ -324,12 +324,10 @@ export const <%= entityReactName %> = (props: RouteComponentProps<{url: string}>
324
324
  <%_ } _%>
325
325
  <div className="table-responsive">
326
326
  <%_ if (paginationInfiniteScroll) { _%>
327
- <InfiniteScroll pageStart={paginationState.activePage}
328
- loadMore={handleLoadMore}
327
+ <InfiniteScroll dataLength={<%= entityInstance %>List ? <%= entityInstance %>List.length : 0}
328
+ next={handleLoadMore}
329
329
  hasMore={paginationState.activePage - 1 < links.next}
330
- loader={<div className="loader">Loading ...</div>}
331
- threshold={0}
332
- initialLoad={false}>
330
+ loader={<div className="loader">Loading ...</div>}>
333
331
  <%_ } _%>
334
332
  {
335
333
  <%= entityInstance %>List && <%= entityInstance %>List.length > 0 ?(
@@ -330,11 +330,7 @@ _%>
330
330
  <%_ if (hasManyToMany) { _%>
331
331
  public getSelected(selectedVals, option) : any {
332
332
  if (selectedVals) {
333
- for (let i = 0; i < selectedVals.length; i++) {
334
- if (option.id === selectedVals[i].id) {
335
- return selectedVals[i];
336
- }
337
- }
333
+ return selectedVals.find(value => option.id === value.id) ?? option;
338
334
  }
339
335
  return option;
340
336
  }
@@ -21,6 +21,7 @@
21
21
  import { shallowMount, createLocalVue, Wrapper } from '@vue/test-utils';
22
22
  import sinon, { SinonStubbedInstance } from 'sinon';
23
23
  import Router from 'vue-router';
24
+ import { ToastPlugin } from 'bootstrap-vue';
24
25
 
25
26
  <%_ let dayJsIncluded = false;
26
27
  for (field of fields.filter(field => !field.id)) { _%>
@@ -66,6 +67,7 @@ const i18n = config.initI18N(localVue);
66
67
  const store = config.initVueXStore(localVue);
67
68
  const router = new Router();
68
69
  localVue.use(Router);
70
+ localVue.use(ToastPlugin);
69
71
  localVue.component('font-awesome-icon', {});
70
72
  localVue.component('b-input-group', {});
71
73
  localVue.component('b-input-group-prepend', {});
@@ -102,7 +104,10 @@ describe('Component Tests', () => {
102
104
  <%_ if (relationship.otherEntityUser && authenticationTypeOauth2) { _%>
103
105
  userOAuth2Service: () => new UserOAuth2Service(),
104
106
  <%_ } else { _%>
105
- <%= otherEntityName %>Service: () => new <%= otherEntityAngularName %>Service(),
107
+ <%= otherEntityName %>Service: () =>
108
+ sinon.createStubInstance<<%= otherEntityAngularName %>Service>(<%= otherEntityAngularName %>Service, {
109
+ retrieve: sinon.stub().resolves({}),
110
+ } as any),
106
111
  <%_ } _%>
107
112
  <%_ } _%>
108
113
  <%_ entitiesSeen.push(otherEntityAngularName); _%>
@@ -22,6 +22,7 @@ _%>
22
22
  /* tslint:disable max-line-length */
23
23
  import { shallowMount, createLocalVue, Wrapper } from '@vue/test-utils';
24
24
  import sinon, { SinonStubbedInstance } from 'sinon';
25
+ import { ToastPlugin } from 'bootstrap-vue';
25
26
 
26
27
  import * as config from '@/shared/config/config';
27
28
  import <%= entityAngularName %>Component from '@/entities/<%= entityFolderName %>/<%= entityFileName %>.vue';
@@ -30,6 +31,7 @@ import <%= entityAngularName %>Service from '@/entities/<%= entityFolderName %>/
30
31
  import AlertService from '@/shared/alert/alert.service';
31
32
 
32
33
  const localVue = createLocalVue();
34
+ localVue.use(ToastPlugin);
33
35
 
34
36
  config.initVueApp(localVue);
35
37
  <%_ if (enableTranslation) { _%>
@@ -185,12 +187,14 @@ describe('Component Tests', () => {
185
187
 
186
188
  // WHEN
187
189
  comp.prepareRemove({id: <%- tsKeyId %>});
190
+ expect(<%= entityInstance %>ServiceStub.retrieve.callCount).toEqual(1);
191
+
188
192
  comp.remove<%= entityAngularName %>();
189
193
  await comp.$nextTick();
190
194
 
191
195
  // THEN
192
196
  expect(<%= entityInstance %>ServiceStub.delete.called).toBeTruthy();
193
- expect(<%= entityInstance %>ServiceStub.retrieve.callCount).toEqual(1);
197
+ expect(<%= entityInstance %>ServiceStub.retrieve.callCount).toEqual(2);
194
198
  });
195
199
  <%_ } _%>
196
200
  });
@@ -51,8 +51,13 @@ module.exports = class JHipsterBaseBlueprintGenerator extends BaseGenerator {
51
51
  // jhipsterContext is the original generator
52
52
  this.jhipsterContext = this.options.jhipsterContext;
53
53
 
54
- // Fallback to the original generator if the file does not exists in the blueprint.
55
- this.jhipsterTemplatesFolders.push(this.jhipsterTemplatePath());
54
+ try {
55
+ // Fallback to the original generator if the file does not exists in the blueprint.
56
+ this.jhipsterTemplatesFolders.push(this.jhipsterTemplatePath());
57
+ } catch (error) {
58
+ this.warning('Error adding current blueprint templates as alternative for JHipster templates.');
59
+ this.log(error);
60
+ }
56
61
  }
57
62
  }
58
63
 
@@ -41,15 +41,13 @@ const { formatDateForChangelog } = require('../utils/liquibase');
41
41
  const { calculateDbNameWithLimit, hibernateSnakeCase } = require('../utils/db');
42
42
  const defaultApplicationOptions = require('../jdl/jhipster/default-application-options');
43
43
  const databaseTypes = require('../jdl/jhipster/database-types');
44
+ const { ANGULAR_X: ANGULAR, REACT, VUE, NO: CLIENT_FRAMEWORK_NO } = require('../jdl/jhipster/client-framework-types');
44
45
 
45
46
  const JHIPSTER_CONFIG_DIR = constants.JHIPSTER_CONFIG_DIR;
46
47
  const MODULES_HOOK_FILE = `${JHIPSTER_CONFIG_DIR}/modules/jhi-hooks.json`;
47
48
  const GENERATOR_JHIPSTER = 'generator-jhipster';
48
49
 
49
50
  const SERVER_MAIN_RES_DIR = constants.SERVER_MAIN_RES_DIR;
50
- const ANGULAR = constants.SUPPORTED_CLIENT_FRAMEWORKS.ANGULAR;
51
- const REACT = constants.SUPPORTED_CLIENT_FRAMEWORKS.REACT;
52
- const VUE = constants.SUPPORTED_CLIENT_FRAMEWORKS.VUE;
53
51
 
54
52
  const { ORACLE, MYSQL, POSTGRESQL, MARIADB, MSSQL, SQL, MONGODB, COUCHBASE, NEO4J, CASSANDRA, H2_MEMORY, H2_DISK } = databaseTypes;
55
53
  const NO_DATABASE = databaseTypes.NO;
@@ -159,7 +157,13 @@ module.exports = class JHipsterBaseGenerator extends PrivateBase {
159
157
  * Alternative templatePath that fetches from the blueprinted generator, instead of the blueprint.
160
158
  */
161
159
  jhipsterTemplatePath(...args) {
162
- this._jhipsterGenerator = this._jhipsterGenerator || this.env.requireNamespace(this.options.namespace).generator;
160
+ try {
161
+ this._jhipsterGenerator = this._jhipsterGenerator || this.env.requireNamespace(this.options.namespace).generator;
162
+ } catch (error) {
163
+ throw new Error(
164
+ `The Namespace ${this.options.namespace} may not be correct. Please check your configuration and ensure your blueprint folder start with "generator-". Detail: ${error}`
165
+ );
166
+ }
163
167
  return this.fetchFromInstalledJHipster(this._jhipsterGenerator, 'templates', ...args);
164
168
  }
165
169
 
@@ -450,8 +454,8 @@ module.exports = class JHipsterBaseGenerator extends PrivateBase {
450
454
  } else if (clientFramework === VUE) {
451
455
  this.needleApi.clientVue.addEntityToRouterImport(entityName, entityFileName, entityFolderName, readOnly);
452
456
  this.needleApi.clientVue.addEntityToRouter(entityInstance, entityName, entityFileName, readOnly);
453
- this.needleApi.clientVue.addEntityServiceToMainImport(entityName, entityClass, entityFileName, entityFolderName);
454
- this.needleApi.clientVue.addEntityServiceToMain(entityInstance, entityName);
457
+ this.needleApi.clientVue.addEntityServiceToEntitiesComponentImport(entityName, entityClass, entityFileName, entityFolderName);
458
+ this.needleApi.clientVue.addEntityServiceToEntitiesComponent(entityInstance, entityName);
455
459
  }
456
460
  }
457
461
 
@@ -2660,7 +2664,7 @@ templates: ${JSON.stringify(existingTemplates, null, 2)}`;
2660
2664
  }
2661
2665
 
2662
2666
  if (options.microfrontend) {
2663
- this.jhipsterConfig.microfrontend = options.microfrontend;
2667
+ this.warning('Microfrontend option is deprecated.');
2664
2668
  }
2665
2669
 
2666
2670
  if (options.reactive !== undefined) {
@@ -2721,7 +2725,7 @@ templates: ${JSON.stringify(existingTemplates, null, 2)}`;
2721
2725
  * @param {any} config - config to load config from
2722
2726
  * @param {any} dest - destination context to use default is context
2723
2727
  */
2724
- loadAppConfig(config = _.defaults({}, this.jhipsterConfig, defaultConfig), dest = this) {
2728
+ loadAppConfig(config = _.defaults({}, this.jhipsterConfig, this.jhipsterDefaults), dest = this) {
2725
2729
  dest.jhipsterVersion = config.jhipsterVersion;
2726
2730
  dest.baseName = config.baseName;
2727
2731
  dest.applicationType = config.applicationType;
@@ -2741,7 +2745,6 @@ templates: ${JSON.stringify(existingTemplates, null, 2)}`;
2741
2745
  dest.pages = config.pages;
2742
2746
  dest.skipJhipsterDependencies = !!config.skipJhipsterDependencies;
2743
2747
  dest.withAdminUi = config.withAdminUi;
2744
- dest.microfrontend = config.microfrontend;
2745
2748
  dest.gatewayServerPort = config.gatewayServerPort;
2746
2749
 
2747
2750
  dest.capitalizedBaseName = config.capitalizedBaseName;
@@ -2786,7 +2789,11 @@ templates: ${JSON.stringify(existingTemplates, null, 2)}`;
2786
2789
 
2787
2790
  if (dest.remotes) {
2788
2791
  dest.remotes.forEach(app => this.loadDerivedAppConfig(app));
2792
+ dest.microfrontends = dest.remotes.filter(r => r.clientFramework && r.clientFramework !== CLIENT_FRAMEWORK_NO);
2789
2793
  }
2794
+ dest.microfrontend =
2795
+ (dest.applicationTypeMicroservice && !dest.skipClient) ||
2796
+ (dest.applicationTypeGateway && dest.microfrontends && dest.microfrontends.length > 0);
2790
2797
  }
2791
2798
 
2792
2799
  /**
@@ -2796,7 +2803,7 @@ templates: ${JSON.stringify(existingTemplates, null, 2)}`;
2796
2803
  * @param {any} config - config to load config from
2797
2804
  * @param {any} dest - destination context to use default is context
2798
2805
  */
2799
- loadClientConfig(config = _.defaults({}, this.jhipsterConfig, defaultConfig), dest = this) {
2806
+ loadClientConfig(config = _.defaults({}, this.jhipsterConfig, this.jhipsterDefaults), dest = this) {
2800
2807
  dest.clientPackageManager = config.clientPackageManager;
2801
2808
  dest.clientFramework = config.clientFramework;
2802
2809
  dest.clientTheme = config.clientTheme;
@@ -2827,7 +2834,7 @@ templates: ${JSON.stringify(existingTemplates, null, 2)}`;
2827
2834
  * @param {any} config - config to load config from
2828
2835
  * @param {any} dest - destination context to use default is context
2829
2836
  */
2830
- loadTranslationConfig(config = _.defaults({}, this.jhipsterConfig, defaultConfig), dest = this) {
2837
+ loadTranslationConfig(config = _.defaults({}, this.jhipsterConfig, this.jhipsterDefaults), dest = this) {
2831
2838
  dest.enableTranslation = config.enableTranslation;
2832
2839
  dest.nativeLanguage = config.nativeLanguage;
2833
2840
  dest.languages = config.languages;
@@ -2840,7 +2847,7 @@ templates: ${JSON.stringify(existingTemplates, null, 2)}`;
2840
2847
  * @param {any} config - config to load config from
2841
2848
  * @param {any} dest - destination context to use default is context
2842
2849
  */
2843
- loadServerConfig(config = _.defaults({}, this.jhipsterConfig, defaultConfig), dest = this) {
2850
+ loadServerConfig(config = _.defaults({}, this.jhipsterConfig, this.jhipsterDefaults), dest = this) {
2844
2851
  dest.packageName = config.packageName;
2845
2852
  dest.packageFolder = config.packageFolder;
2846
2853
  dest.serverPort = config.serverPort;
@@ -2954,7 +2961,7 @@ templates: ${JSON.stringify(existingTemplates, null, 2)}`;
2954
2961
  [MYSQL, POSTGRESQL, MSSQL, MARIADB].includes(dest.devDatabaseType));
2955
2962
  }
2956
2963
 
2957
- loadPlatformConfig(config = _.defaults({}, this.jhipsterConfig, defaultConfig), dest = this) {
2964
+ loadPlatformConfig(config = _.defaults({}, this.jhipsterConfig, this.jhipsterDefaults), dest = this) {
2958
2965
  dest.serviceDiscoveryType = config.serviceDiscoveryType;
2959
2966
  dest.monitoring = config.monitoring;
2960
2967
  this.loadDerivedPlatformConfig(dest);
@@ -3024,11 +3031,21 @@ templates: ${JSON.stringify(existingTemplates, null, 2)}`;
3024
3031
  return this._needleApi;
3025
3032
  }
3026
3033
 
3034
+ /**
3035
+ * Default config based on current applicationType
3036
+ */
3037
+ get jhipsterDefaults() {
3038
+ return this.getDefaultConfigForApplicationType();
3039
+ }
3040
+
3027
3041
  /**
3028
3042
  * Get default config based on applicationType
3029
3043
  */
3030
3044
  getDefaultConfigForApplicationType(applicationType = this.jhipsterConfig.applicationType) {
3031
- return { ...defaultApplicationOptions.getConfigForApplicationType(applicationType), ...defaultConfig };
3045
+ return {
3046
+ ...defaultApplicationOptions.getConfigForApplicationType(applicationType),
3047
+ ...(applicationType === MICROSERVICE ? defaultConfigMicroservice : defaultConfig),
3048
+ };
3032
3049
  }
3033
3050
 
3034
3051
  setConfigDefaults(defaults = this.jhipsterConfig.applicationType === MICROSERVICE ? defaultConfigMicroservice : defaultConfig) {
@@ -34,7 +34,7 @@ const GRADLE_VERSION = '7.0.2';
34
34
  const JIB_VERSION = '3.1.4';
35
35
 
36
36
  // Libraries version
37
- const JHIPSTER_DEPENDENCIES_VERSION = '7.4.0';
37
+ const JHIPSTER_DEPENDENCIES_VERSION = '7.4.1';
38
38
  // The spring-boot version should match the one managed by https://mvnrepository.com/artifact/tech.jhipster/jhipster-dependencies/JHIPSTER_DEPENDENCIES_VERSION
39
39
  const SPRING_BOOT_VERSION = '2.5.7';
40
40
  const LIQUIBASE_VERSION = '4.6.1';
@@ -36,6 +36,9 @@ const prettierTransform = function (options, generator, transformOptions = {}) {
36
36
  if (isFileStateDeleted(file)) {
37
37
  return file;
38
38
  }
39
+ if (!file.contents) {
40
+ throw new Error(`File content doesn't exist for ${file.relative}`);
41
+ }
39
42
  /* resolve from the projects config */
40
43
  let fileContent;
41
44
  try {
@@ -58,12 +61,17 @@ const prettierTransform = function (options, generator, transformOptions = {}) {
58
61
  file.contents = Buffer.from(data);
59
62
  return file;
60
63
  } catch (error) {
61
- const errorMessage = `Error parsing file ${file.relative}: ${error}
64
+ let errorMessage;
65
+ if (fileContent) {
66
+ errorMessage = `Error parsing file ${file.relative}: ${error}
62
67
 
63
68
  At: ${fileContent
64
- .split('\n')
65
- .map((value, idx) => `${idx + 1}: ${value}`)
66
- .join('\n')}`;
69
+ .split('\n')
70
+ .map((value, idx) => `${idx + 1}: ${value}`)
71
+ .join('\n')}`;
72
+ } else {
73
+ errorMessage = `Unknown prettier error: ${error}`;
74
+ }
67
75
  if (ignoreErrors) {
68
76
  generator.warning(errorMessage);
69
77
  return file;