From da6233cced733f86f46a6788405ffcb5c13ac1e5 Mon Sep 17 00:00:00 2001 From: Marcelo Shima Date: Mon, 9 Sep 2024 11:06:08 -0300 Subject: [PATCH] fix types and enable type check for entire project --- eslint.config.js | 2 +- generators/angular/generator.ts | 10 +- .../needle-api/needle-client-angular.ts | 4 +- generators/angular/support/needles.ts | 6 +- .../app/__snapshots__/generator.spec.ts.snap | 12 -- generators/app/command.ts | 5 + generators/base-application/generator.spec.ts | 4 +- generators/base-application/generator.ts | 6 +- generators/base-core/generator-core.spec.ts | 8 +- generators/base-core/generator.ts | 19 ++- generators/base-entity-changes/generator.ts | 9 +- generators/base/api.d.ts | 114 ++++++++---------- generators/base/blueprints.spec.ts | 41 ++++--- generators/base/command.ts | 8 +- generators/base/generator.spec.ts | 2 +- generators/base/generator.ts | 7 +- generators/base/internal/blueprint.ts | 2 +- generators/base/support/needles.spec.ts | 37 +++--- generators/base/support/needles.ts | 24 ++-- generators/base/support/timestamp.spec.ts | 1 + generators/base/types.d.ts | 4 +- .../bootstrap-application-base/command.ts | 4 +- .../generator.spec.ts | 2 +- generators/ci-cd/command.ts | 30 ++--- generators/ci-cd/generator.ts | 45 ++++--- generators/client/generator-needles.spec.ts | 2 +- generators/client/generator.spec.ts | 3 +- .../client/needle-api/needle-client-vue.ts | 4 +- generators/client/needle-api/needle-client.ts | 4 +- generators/client/needle-client.spec.ts | 2 +- generators/client/types.d.ts | 2 +- .../__snapshots__/export-jdl.spec.ts.snap | 2 - generators/export-jdl/export-jdl.spec.ts | 7 +- generators/git/command.ts | 4 +- generators/gradle/needles.spec.ts | 4 +- generators/heroku/generator.ts | 2 +- generators/heroku/heroku.spec.ts | 2 +- .../java/generators/bootstrap/command.ts | 9 +- .../java/generators/bootstrap/generator.ts | 2 +- .../java/generators/build-tool/command.ts | 8 +- .../generators/openapi-generator/command.ts | 6 +- generators/java/types.d.ts | 8 +- .../javascript/generators/prettier/command.ts | 4 +- generators/languages/command.ts | 46 ++++--- .../languages/generator-needles.spec.ts | 2 +- generators/liquibase/needles.spec.ts | 2 +- generators/maven/needles.spec.ts | 6 +- generators/react/generator.ts | 2 +- .../react/needle-api/needle-client-react.ts | 2 +- generators/server/command.ts | 8 +- generators/server/needle-logback.spec.ts | 4 +- generators/server/support/needles.spec.ts | 10 +- generators/server/support/needles.ts | 14 ++- generators/spring-boot/command.ts | 8 ++ generators/spring-boot/generator.ts | 4 +- generators/spring-cache/needles.spec.ts | 6 +- .../__snapshots__/generator.spec.ts.snap | 6 + .../generators/gateway/generator.spec.ts | 2 +- generators/spring-data-relational/command.ts | 14 ++- generators/vue/generator.ts | 2 +- lib/command/converter.ts | 1 + lib/command/types.d.ts | 73 ++++++----- lib/command/types.spec.ts | 111 +++++++++++++++++ lib/internal/config-def.ts | 20 +-- lib/types/application/options.d.ts | 17 +++ lib/types/application/yo-rc.d.ts | 19 ++- test/needle-api/needle-base.spec.ts | 1 + .../needle-client-angular-generator.spec.ts | 7 +- test/needle-api/needle-client-angular.spec.ts | 13 +- .../needle-client-react-generator.spec.ts | 9 +- test/needle-api/needle-client-react.spec.ts | 7 +- .../needle-client-vue-generator.spec.ts | 7 +- test/needle-api/needle-client-vue.spec.ts | 2 +- test/support/tests.js | 4 +- testing/helpers.ts | 7 +- tsconfig.eslint.json | 8 -- tsconfig.spec.json | 8 +- 77 files changed, 559 insertions(+), 374 deletions(-) create mode 100644 lib/command/types.spec.ts create mode 100644 lib/types/application/options.d.ts delete mode 100644 tsconfig.eslint.json diff --git a/eslint.config.js b/eslint.config.js index 6b77f8925e00..6d01d6c24ac2 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -24,7 +24,7 @@ export default ts.config( extends: [...ts.configs.recommended, ...ts.configs.stylistic], languageOptions: { parserOptions: { - project: ['./tsconfig.spec.json', './tsconfig.eslint.json'], + project: ['./tsconfig.spec.json'], }, }, rules: { diff --git a/generators/angular/generator.ts b/generators/angular/generator.ts index df7d1ca91242..b3ea7497a819 100644 --- a/generators/angular/generator.ts +++ b/generators/angular/generator.ts @@ -336,7 +336,7 @@ export default class AngularGenerator extends BaseApplicationGenerator { * } * */ - addVendorSCSSStyle(style, comment) { + addVendorSCSSStyle(style, comment?) { this.needleApi.clientAngular.addVendorSCSSStyle(style, comment); } @@ -392,7 +392,7 @@ export default class AngularGenerator extends BaseApplicationGenerator { this.needleApi.clientAngular.addElementToAdminMenu(routerName, iconName, enableTranslation, translationKeyMenu, jhiPrefix); } - addEntitiesToMenu({ application, entities }: PostWritingEntitiesTaskParam) { + addEntitiesToMenu({ application, entities }: Pick) { const filePath = `${application.clientSrcDir}app/layouts/navbar/navbar.component.html`; const ignoreNonExisting = chalk.yellow('Reference to entities not added to menu.'); const editCallback = addToEntitiesMenu({ application, entities }); @@ -400,7 +400,7 @@ export default class AngularGenerator extends BaseApplicationGenerator { this.editFile(filePath, { ignoreNonExisting }, editCallback); } - addEntitiesToModule(param: PostWritingEntitiesTaskParam) { + addEntitiesToModule(param: Pick) { const filePath = `${param.application.clientSrcDir}app/entities/entity.routes.ts`; const ignoreNonExisting = chalk.yellow(`Route(s) not added to ${filePath}.`); const addRouteCallback = addEntitiesRoute(param); @@ -427,7 +427,7 @@ export default class AngularGenerator extends BaseApplicationGenerator { * } * */ - addMainSCSSStyle(style, comment) { + addMainSCSSStyle(style, comment?) { this.needleApi.clientAngular.addGlobalSCSSStyle(style, comment); } @@ -504,7 +504,7 @@ export default class AngularGenerator extends BaseApplicationGenerator { * @param {string} clientFramework - The name of the client framework * @param {string} translationKeyMenu - i18n key for entry in the menu */ - addElementToMenu(routerName, iconName, enableTranslation, clientFramework, translationKeyMenu = camelCase(routerName)) { + addElementToMenu(routerName, iconName, enableTranslation, _clientFramework?, translationKeyMenu = camelCase(routerName)) { this.needleApi.clientAngular.addElementToMenu(routerName, iconName, enableTranslation, translationKeyMenu); } } diff --git a/generators/angular/needle-api/needle-client-angular.ts b/generators/angular/needle-api/needle-client-angular.ts index fce521111abb..3c83cd7202c2 100644 --- a/generators/angular/needle-api/needle-client-angular.ts +++ b/generators/angular/needle-api/needle-client-angular.ts @@ -27,12 +27,12 @@ import { createNeedleCallback } from '../../base/support/needles.js'; const { ANGULAR } = clientFrameworkTypes; export default class extends needleClientBase { - addGlobalSCSSStyle(style, comment) { + addGlobalSCSSStyle(style, comment?) { const filePath = `${this.clientSrcDir}content/scss/global.scss`; this.addStyle(style, comment, filePath, 'jhipster-needle-scss-add-main'); } - addVendorSCSSStyle(style, comment) { + addVendorSCSSStyle(style, comment?) { const filePath = `${this.clientSrcDir}content/scss/vendor.scss`; super.addStyle(style, comment, filePath, 'jhipster-needle-scss-add-vendor'); } diff --git a/generators/angular/support/needles.ts b/generators/angular/support/needles.ts index c479e29ea9cb..cf281e2b35fd 100644 --- a/generators/angular/support/needles.ts +++ b/generators/angular/support/needles.ts @@ -16,8 +16,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import type { Entity } from '../../../lib/types/application/entity.js'; -import type { BaseApplication } from '../../base-application/types.js'; import { createNeedleCallback } from '../../base/support/needles.js'; import { upperFirstCamelCase } from '../../../lib/utils/string.js'; import { joinCallbacks } from '../../base/support/write-files.js'; @@ -56,7 +54,7 @@ export function addRoute({ }); } -export function addEntitiesRoute({ application, entities }: PostWritingEntitiesTaskParam) { +export function addEntitiesRoute({ application, entities }: Pick) { const { enableTranslation } = application; return joinCallbacks( ...entities.map(entity => { @@ -128,7 +126,7 @@ export const addIconImport = ({ icon }: { icon: string }) => { }); }; -export function addToEntitiesMenu({ application, entities }: { application: BaseApplication; entities: Entity[] }) { +export function addToEntitiesMenu({ application, entities }: Pick) { const { enableTranslation, jhiPrefix } = application; return joinCallbacks( ...entities.map(entity => { diff --git a/generators/app/__snapshots__/generator.spec.ts.snap b/generators/app/__snapshots__/generator.spec.ts.snap index ed64f7680b31..39c1b8eda638 100644 --- a/generators/app/__snapshots__/generator.spec.ts.snap +++ b/generators/app/__snapshots__/generator.spec.ts.snap @@ -453,7 +453,6 @@ exports[`generator - app with default config should match snapshot 1`] = ` "eslintConfigFile": "eslint.config.mjs", "fakerSeed": undefined, "feignClient": false, - "fromInit": undefined, "frontendAppName": "jhipsterApp", "gatewayRoutes": undefined, "gatewayServerPort": undefined, @@ -595,7 +594,6 @@ exports[`generator - app with default config should match snapshot 1`] = ` "microfrontend": false, "microfrontends": undefined, "monorepository": undefined, - "monorepositoryRoot": undefined, "nativeLanguage": "en", "nativeLanguageDefinition": { "angularLocale": "en", @@ -726,7 +724,6 @@ exports[`generator - app with default config should match snapshot 1`] = ` "packageJsonType": "commonjs", "packageName": "com.mycompany.myapp", "pages": [], - "prettierConfigFile": ".prettierrc", "prettierExtensions": "md,json,yml,js,cjs,mjs,ts,cts,mts,java,html,css,scss", "prettierFolders": ",**/", "prettierJava": undefined, @@ -779,7 +776,6 @@ exports[`generator - app with default config should match snapshot 1`] = ` "skipJhipsterDependencies": undefined, "skipServer": undefined, "skipUserManagement": false, - "sortMavenPom": true, "springBootDependencies": Any, "srcMainDir": "src/main/", "srcMainJava": "src/main/java/", @@ -1073,7 +1069,6 @@ exports[`generator - app with gateway should match snapshot 1`] = ` "eslintConfigFile": "eslint.config.mjs", "fakerSeed": undefined, "feignClient": false, - "fromInit": undefined, "frontendAppName": "jhipsterApp", "gatewayRoutes": [], "gatewayServerPort": undefined, @@ -1209,7 +1204,6 @@ exports[`generator - app with gateway should match snapshot 1`] = ` "microfrontend": undefined, "microfrontends": undefined, "monorepository": undefined, - "monorepositoryRoot": undefined, "nativeLanguage": "en", "nativeLanguageDefinition": { "angularLocale": "en", @@ -1340,7 +1334,6 @@ exports[`generator - app with gateway should match snapshot 1`] = ` "packageJsonType": "commonjs", "packageName": "com.mycompany.myapp", "pages": [], - "prettierConfigFile": ".prettierrc", "prettierExtensions": "md,json,yml,js,cjs,mjs,ts,cts,mts,java,html,css,scss", "prettierFolders": ",**/", "prettierJava": undefined, @@ -1395,7 +1388,6 @@ exports[`generator - app with gateway should match snapshot 1`] = ` "skipJhipsterDependencies": undefined, "skipServer": undefined, "skipUserManagement": false, - "sortMavenPom": true, "springBootDependencies": Any, "srcMainDir": "src/main/", "srcMainJava": "src/main/java/", @@ -1686,7 +1678,6 @@ exports[`generator - app with microservice should match snapshot 1`] = ` "entitySuffix": "", "fakerSeed": undefined, "feignClient": false, - "fromInit": undefined, "frontendAppName": "jhipsterApp", "gatewayRoutes": undefined, "gatewayServerPort": undefined, @@ -1828,7 +1819,6 @@ exports[`generator - app with microservice should match snapshot 1`] = ` "microfrontend": false, "microfrontends": undefined, "monorepository": undefined, - "monorepositoryRoot": undefined, "nativeLanguage": "en", "nativeLanguageDefinition": { "angularLocale": "en", @@ -1900,7 +1890,6 @@ exports[`generator - app with microservice should match snapshot 1`] = ` "packageJsonType": "commonjs", "packageName": "com.mycompany.myapp", "pages": [], - "prettierConfigFile": ".prettierrc", "prettierExtensions": "md,json,yml,js,cjs,mjs,ts,cts,mts,java", "prettierFolders": ",**/", "prettierJava": undefined, @@ -1953,7 +1942,6 @@ exports[`generator - app with microservice should match snapshot 1`] = ` "skipJhipsterDependencies": undefined, "skipServer": undefined, "skipUserManagement": true, - "sortMavenPom": true, "springBootDependencies": Any, "srcMainDir": "src/main/", "srcMainJava": "src/main/java/", diff --git a/generators/app/command.ts b/generators/app/command.ts index cc8e50bdec6b..74b52225caa5 100644 --- a/generators/app/command.ts +++ b/generators/app/command.ts @@ -33,6 +33,7 @@ const command = { defaults: { description: 'Execute jhipster with default config', type: Boolean, + scope: 'none', }, skipClient: { description: 'Skip the client-side application generation', @@ -62,15 +63,18 @@ const command = { blueprint: { description: 'DEPRECATED: Specify a generator blueprint to use for the sub generators', type: Array, + scope: 'none', }, blueprints: { description: 'A comma separated list of one or more generator blueprints to use for the sub generators, e.g. --blueprints kotlin,vuejs', type: String, + scope: 'none', }, ignoreErrors: { description: "Don't fail on prettier errors.", type: Boolean, + scope: 'none', }, pkType: { description: 'Default primary key type (beta)', @@ -85,6 +89,7 @@ const command = { testFrameworks: { description: 'Test frameworks to be generated', type: Array, + scope: 'none', }, }, import: [ diff --git a/generators/base-application/generator.spec.ts b/generators/base-application/generator.spec.ts index 56815c0cb39a..8da8983dc4e4 100644 --- a/generators/base-application/generator.spec.ts +++ b/generators/base-application/generator.spec.ts @@ -157,7 +157,7 @@ describe(`generator - ${generator}`, () => { } before(async () => { - await helpers.run(CustomGenerator).withJHipsterConfig({}, [ + await helpers.run(CustomGenerator as any).withJHipsterConfig({}, [ { name: 'One', fields: [{ fieldName: 'id', fieldType: 'Long' }], @@ -396,7 +396,7 @@ describe(`generator - ${generator}`, () => { before(async () => { await helpers - .run(CustomGenerator) + .run(CustomGenerator as any) .withJHipsterConfig({}, [ { name: 'One', diff --git a/generators/base-application/generator.ts b/generators/base-application/generator.ts index db13bb33d77b..4db4d6e816aa 100644 --- a/generators/base-application/generator.ts +++ b/generators/base-application/generator.ts @@ -35,6 +35,7 @@ import type { Entity } from '../../lib/types/application/entity.js'; import type { Entity as BaseEntity } from '../../lib/types/base/entity.js'; import type { GenericTaskGroup } from '../../lib/types/base/tasks.js'; import type { ApplicationConfiguration } from '../../lib/types/application/yo-rc.js'; +import type SharedData from '../base/shared-data.js'; import { getEntitiesFromDir } from './support/index.js'; import { CUSTOM_PRIORITIES, PRIORITY_NAMES, QUEUES } from './priorities.js'; @@ -75,8 +76,8 @@ const asPriority = BaseGenerator.asPriority; * This is the base class for a generator that generates entities. */ export default class BaseApplicationGenerator< - E = Entity, - A = ApplicationType, + E extends Entity = Entity, + A extends ApplicationType = ApplicationType, TaskTypes extends DefaultTaskTypes = DefaultTaskTypes, > extends BaseGenerator { static CONFIGURING_EACH_ENTITY = asPriority(CONFIGURING_EACH_ENTITY); @@ -96,6 +97,7 @@ export default class BaseApplicationGenerator< static POST_WRITING_ENTITIES = asPriority(POST_WRITING_ENTITIES); declare jhipsterConfig: ApplicationConfiguration & Record; + declare sharedData: SharedData; constructor(args: string | string[], options: JHipsterGeneratorOptions, features: JHipsterGeneratorFeatures) { super(args, options, features); diff --git a/generators/base-core/generator-core.spec.ts b/generators/base-core/generator-core.spec.ts index 947724802e33..7e9da7a853b2 100644 --- a/generators/base-core/generator-core.spec.ts +++ b/generators/base-core/generator-core.spec.ts @@ -18,7 +18,7 @@ describe('generator - base-core', () => { let Dummy; beforeEach(async () => { await helpers.prepareTemporaryDir(); - Dummy = helpers.createDummyGenerator(Base); + Dummy = helpers.createDummyGenerator(Base as any); }); it('no argument', async () => { @@ -77,7 +77,8 @@ describe('generator - base-core', () => { }, }); jestExpect(base.first).toBe('bar'); - jestExpect(base.jdlFiles).toMatchObject(['foo']); + jestExpect(base.jdlFiles).toHaveLength(1); + jestExpect(base.jdlFiles[0]).toMatch('foo'); }); it('vararg arguments using positionalArguments', async () => { const base = new Dummy({ positionalArguments: ['bar', ['foo']], sharedData: {}, env: await helpers.createTestEnv() }); @@ -90,7 +91,8 @@ describe('generator - base-core', () => { }, }); jestExpect(base.first).toBe('bar'); - jestExpect(base.jdlFiles).toMatchObject(['foo']); + jestExpect(base.jdlFiles).toHaveLength(1); + jestExpect(base.jdlFiles[0]).toBe('foo'); }); }); }); diff --git a/generators/base-core/generator.ts b/generators/base-core/generator.ts index a282c82a5a08..75f2d979c9b6 100644 --- a/generators/base-core/generator.ts +++ b/generators/base-core/generator.ts @@ -56,7 +56,7 @@ import { convertConfigToOption, } from '../../lib/command/index.js'; import { packageJson } from '../../lib/index.js'; -import type { BaseApplication, CommonClientServerApplication } from '../base-application/types.js'; +import type { BaseApplication } from '../base-application/types.js'; import { GENERATOR_BOOTSTRAP } from '../generator-list.js'; import NeedleApi from '../needle-api.js'; import command from '../base/command.js'; @@ -66,7 +66,6 @@ import { getGradleLibsVersionsProperties } from '../gradle/support/dependabot-gr import { dockerPlaceholderGenerator } from '../docker/utils.js'; import { getConfigWithDefaults } from '../../lib/jhipster/index.js'; import { extractArgumentsFromConfigs } from '../../lib/command/index.js'; -import type { Entity } from '../../lib/types/base/entity.js'; import type BaseApplicationGenerator from '../base-application/generator.js'; import type { ApplicationConfiguration } from '../../lib/types/application/yo-rc.js'; @@ -133,6 +132,7 @@ export default class CoreGenerator extends YeomanGenerator; useVersionPlaceholders?: boolean; skipChecks?: boolean; ignoreNeedlesError?: boolean; @@ -142,7 +142,7 @@ export default class CoreGenerator extends YeomanGenerator>; + readonly sharedData!: SharedData; readonly logger: Logger; jhipsterConfig!: Record; /** @@ -544,7 +544,9 @@ You can ignore this error by passing '--skip-checks' to jhipster command.`); this.sharedData.getControl()[optionName] = optionValue; } else if (optionDesc.scope === 'generator') { this[optionName] = optionValue; - } else { + } else if (optionDesc.scope === 'context') { + this.context![optionName] = optionValue; + } else if (optionDesc.scope !== 'none') { throw new Error(`Scope ${optionDesc.scope} not supported`); } } else if (optionDesc.default && optionDesc.scope === 'generator' && this[optionName] === undefined) { @@ -574,8 +576,10 @@ You can ignore this error by passing '--skip-checks' to jhipster command.`); } if (argument !== undefined) { const convertedValue = !argumentDef.type || argumentDef.type === Array ? argument : argumentDef.type(argument); - if ((argumentDef.scope ?? 'generator') === 'generator') { + if (argumentDef.scope === undefined || argumentDef.scope === 'generator') { this[argumentName] = convertedValue; + } else if (argumentDef.scope === 'context') { + this.context![argumentName] = convertedValue; } else if (argumentDef.scope === 'storage') { this.config.set(argumentName, convertedValue); } else if (argumentDef.scope === 'blueprint') { @@ -613,6 +617,11 @@ You can ignore this error by passing '--skip-checks' to jhipster command.`); getPath: path => get(this, path), setPath: (path, value) => set(this, path, value), }; + } else if (def.scope === 'context') { + storage = { + getPath: path => get(this.context, path), + setPath: (path, value) => set(this.context!, path, value), + }; } return { name, diff --git a/generators/base-entity-changes/generator.ts b/generators/base-entity-changes/generator.ts index 6520d5569d0a..aae56c854189 100644 --- a/generators/base-entity-changes/generator.ts +++ b/generators/base-entity-changes/generator.ts @@ -53,11 +53,10 @@ type TaskTypes = ApplicationTaskTypes & { /** * This is the base class for a generator for every generator. */ -export default abstract class GeneratorBaseEntityChanges> extends GeneratorBaseApplication< - E, - A, - TaskTypes -> { +export default abstract class GeneratorBaseEntityChanges< + E extends Entity = Entity, + A extends ApplicationType = ApplicationType, +> extends GeneratorBaseApplication> { recreateInitialChangelog!: boolean; private entityChanges!: any[]; diff --git a/generators/base/api.d.ts b/generators/base/api.d.ts index 3c96024d0390..680917d47009 100644 --- a/generators/base/api.d.ts +++ b/generators/base/api.d.ts @@ -1,77 +1,59 @@ -import type { BaseFeatures, BaseOptions, CliOptionSpec } from 'yeoman-generator'; +import type { BaseFeatures, BaseOptions } from 'yeoman-generator'; import type CoreGenerator from '../base-core/index.js'; import type { ApplicationType } from '../../lib/types/application/application.js'; import type { Entity } from '../../lib/types/application/entity.js'; - -type ConfigScope = 'storage' | 'blueprint' | 'control' | 'generator'; -type CliSpecType = CliOptionSpec['type']; +import type { ApplicationOptions } from '../../lib/types/application/options.js'; export type ApplicationWithConfig = { config: Record; entities: Record; }; -export type JHipsterGeneratorOptions = BaseOptions & { - /* cli options */ - commandName: string; - programName: string; - positionalArguments?: unknown[]; - createEnvBuilder?: any; - - /* yeoman options */ - skipYoResolve?: boolean; - sharedData: any; - force?: boolean; - - /* base options */ - defaults?: boolean; - applicationId?: string; - applicationWithConfig?: ApplicationWithConfig; - /** - * @deprecated - */ - applicationWithEntities?: any; - creationTimestamp?: string; - ignoreErrors?: boolean; - ignoreNeedlesError?: boolean; - reproducible?: boolean; - reproducibleTests?: boolean; - skipPriorities?: string[]; - skipWriting?: boolean; - entities?: string[]; - disableBlueprints?: boolean; - - /* Init based application */ - fromInit?: boolean; - - /* blueprint options */ - blueprints?: string; - blueprint?: any; - jhipsterContext?: any; - composeWithLocalBlueprint?: boolean; - - /* generate-blueprint options */ - localBlueprint?: boolean; - - /* jdl generator options */ - jdlFile?: string; - - /* application options */ - baseName?: string; - db?: string; - applicationType?: string; - skipUserManagement?: boolean; - skipDbChangelog?: boolean; - recreateInitialChangelog?: boolean; - - /* workspaces options */ - generateApplications?: boolean; - generateWorkspaces?: boolean; - generateWith?: string; - monorepository?: boolean; - workspaces?: boolean; - workspacesFolders?: string[]; -}; +export type JHipsterGeneratorOptions = BaseOptions & + ApplicationOptions & { + /* cli options */ + commandName: string; + programName: string; + positionalArguments?: unknown[]; + createEnvBuilder?: any; + + /* yeoman options */ + skipYoResolve?: boolean; + sharedData: any; + force?: boolean; + + /* base options */ + applicationId?: string; + applicationWithConfig?: ApplicationWithConfig; + /** + * @deprecated + */ + applicationWithEntities?: any; + reproducibleTests?: boolean; + skipPriorities?: string[]; + skipWriting?: boolean; + entities?: string[]; + + jhipsterContext?: any; + composeWithLocalBlueprint?: boolean; + + /* generate-blueprint options */ + localBlueprint?: boolean; + + /* jdl generator options */ + jdlFile?: string; + + /* application options */ + db?: string; + + /* workspaces options */ + generateApplications?: boolean; + generateWorkspaces?: boolean; + generateWith?: string; + monorepository?: boolean; + workspaces?: boolean; + workspacesFolders?: string[]; + }; export type JHipsterGeneratorFeatures = BaseFeatures & { priorityArgs?: boolean; @@ -120,6 +102,8 @@ export type JHipsterGeneratorFeatures = BaseFeatures & { queueCommandTasks?: boolean; }; +export type NeedleCallback = (content: string) => string; + export type EditFileCallback = (this: Generator, content: string, filePath: string) => string; export type EditFileOptions = { create?: boolean; ignoreNonExisting?: boolean | string; assertModified?: boolean }; diff --git a/generators/base/blueprints.spec.ts b/generators/base/blueprints.spec.ts index 1805f3d5695a..99a6dfb3592e 100644 --- a/generators/base/blueprints.spec.ts +++ b/generators/base/blueprints.spec.ts @@ -1,12 +1,12 @@ -import { before, describe, esmocha, expect, it } from 'esmocha'; +import type { Mock } from 'node:test'; +import { mock } from 'node:test'; +import { before, describe, expect, it } from 'esmocha'; import type { RunResult } from 'yeoman-test'; -import { toHaveBeenCalledAfter } from 'jest-extended'; import { basicHelpers as helpers } from '../../testing/index.js'; import { packageJson } from '../../lib/index.js'; import BaseGenerator from './index.js'; -expect.extend({ toHaveBeenCalledAfter }); const jhipsterVersion = packageJson.version; describe('generator - base - with blueprint', () => { @@ -26,7 +26,7 @@ describe('generator - base - with blueprint', () => { .withJHipsterConfig() .withOptions({ skipChecks: false, - blueprint: 'myblueprint', + blueprint: ['myblueprint'], }); }); @@ -58,7 +58,7 @@ describe('generator - base - with blueprint', () => { .withJHipsterConfig() .withOptions({ skipChecks: false, - blueprint: 'myblueprint', + blueprint: ['myblueprint'], }), ).rejects.toThrow(/targets JHipster v1.1.1 and is not compatible with this JHipster version/)); }); @@ -78,7 +78,7 @@ describe('generator - base - with blueprint', () => { .withJHipsterConfig() .withOptions({ skipChecks: false, - blueprint: 'myblueprint', + blueprint: ['myblueprint'], })); }); @@ -96,7 +96,7 @@ describe('generator - base - with blueprint', () => { }) .withOptions({ skipChecks: false, - blueprint: 'myblueprint', + blueprint: ['myblueprint'], }); }); @@ -123,7 +123,7 @@ describe('generator - base - with blueprint', () => { .withJHipsterConfig() .withOptions({ skipChecks: false, - blueprint: 'myblueprint', + blueprint: ['myblueprint'], }), ).rejects.toThrow(/targets JHipster v1.1.1 and is not compatible with this JHipster version/)); }); @@ -148,7 +148,7 @@ describe('generator - base - with blueprint', () => { }) .withOptions({ skipChecks: false, - blueprint: 'myblueprint', + blueprint: ['myblueprint'], }); }); @@ -181,7 +181,7 @@ describe('generator - base - with blueprint', () => { .withJHipsterConfig() .withOptions({ skipChecks: false, - blueprint: 'myblueprint', + blueprint: ['myblueprint'], }), ).rejects.toThrow(/targets JHipster v1.1.1 and is not compatible with this JHipster version/)); }); @@ -247,7 +247,7 @@ describe('generator - base - with blueprint with constructor error', () => { await expect( helpers .runTestBlueprintGenerator() - .withGenerators([[BlueprintBlueprintedGenerator, 'jhipster-throwing-constructor:test-blueprint']]) + .withGenerators([[BlueprintBlueprintedGenerator, { namespace: 'jhipster-throwing-constructor:test-blueprint' }]]) .withJHipsterConfig() .withOptions({ blueprints: 'generator-jhipster-throwing-constructor', @@ -343,10 +343,11 @@ describe('generator - base-blueprint', () => { 'end', ]; - const createPrioritiesFakes = (): Record => { - const mockedPriorities: Record = {}; + const createPrioritiesFakes = (): Record number>> => { + const mockedPriorities: Record number>> = {}; + let callOrder = 0; priorities.forEach(priority => { - mockedPriorities[priority] = esmocha.fn(); + mockedPriorities[priority] = mock.fn(() => callOrder++); }); return mockedPriorities; }; @@ -493,7 +494,7 @@ describe('generator - base-blueprint', () => { describe('priorities', () => { describe('when every priority has been implemented', () => { - let mockedPriorities: Record; + let mockedPriorities: Record number>>; let mockBlueprintSubGen; before(() => { mockedPriorities = createPrioritiesFakes(); @@ -503,19 +504,19 @@ describe('generator - base-blueprint', () => { priorities.forEach((priority, idx) => { it(`should execute ${priority} once`, () => { - expect(mockedPriorities[priority]).toBeCalledTimes(1); + expect(mockedPriorities[priority].mock.callCount()).toBe(1); }); if (idx > 0) { const priorityBefore = priorities[idx - 1]; it(`should execute ${priority} after ${priorityBefore} `, () => { - expect(mockedPriorities[priority]).toHaveBeenCalledAfter(mockedPriorities[priorityBefore]); + expect(mockedPriorities[priority].mock.calls[0].result).toBeGreaterThan(mockedPriorities[priorityBefore].mock.calls[0].result!); }); } }); }); describe('when custom priorities are missing and the blueprint is sbs', () => { - let mockedPriorities; + let mockedPriorities: Record number>>; let mockBlueprintSubGen; before(() => { mockedPriorities = createPrioritiesFakes(); @@ -559,11 +560,11 @@ describe('generator - base-blueprint', () => { priorities.forEach(priority => { if (['composing', 'loading', 'preparing', 'postWriting'].includes(priority)) { it(`should not execute ${priority}`, () => { - expect(mockedPriorities[priority]).not.toBeCalled(); + expect(mockedPriorities[priority].mock.callCount()).toBe(0); }); } else { it(`should execute ${priority} once`, () => { - expect(mockedPriorities[priority]).toBeCalledTimes(1); + expect(mockedPriorities[priority].mock.callCount()).toBe(1); }); } }); diff --git a/generators/base/command.ts b/generators/base/command.ts index 76072b716cbc..f33d6722fac0 100644 --- a/generators/base/command.ts +++ b/generators/base/command.ts @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { asCommand } from '../type-utils.js'; +import type { JHipsterCommandDefinition } from '../../lib/command/types.js'; const command = { options: { @@ -67,8 +67,6 @@ const command = { scope: 'generator', }, }, -} as const; +} as const satisfies JHipsterCommandDefinition; -export type Command = typeof command; - -export default asCommand(command); +export default command; diff --git a/generators/base/generator.spec.ts b/generators/base/generator.spec.ts index 49aede1e41e8..eee1f0ee1f70 100644 --- a/generators/base/generator.spec.ts +++ b/generators/base/generator.spec.ts @@ -81,7 +81,7 @@ describe(`generator - ${generator}`, () => { } before(async () => { - await helpers.run(CustomGenerator).withOptions({ + await helpers.run(CustomGenerator as any).withOptions({ skipPriorities: ['prompting', 'writing', 'postWriting'], }); }); diff --git a/generators/base/generator.ts b/generators/base/generator.ts index 9f78ccff428c..2b2b5285445f 100644 --- a/generators/base/generator.ts +++ b/generators/base/generator.ts @@ -22,6 +22,7 @@ import chalk from 'chalk'; import semver from 'semver'; import type { ComposeOptions } from 'yeoman-generator'; +import { union } from 'lodash-es'; import { packageJson } from '../../lib/index.js'; import CoreGenerator from '../base-core/index.js'; import { loadStoredAppOptions } from '../app/support/index.js'; @@ -539,12 +540,10 @@ export default class JHipsterBaseBlueprintGenerator { @@ -218,37 +220,38 @@ ${needlePrefix} jhipster-needle-a-needle" }); it('returned function should throw on missing content', () => { - expect(() => createNeedleCallback({ contentToAdd, needle }).call({ log() {} })).toThrow(/content is required/); + const needleCallback = createNeedleCallback({ contentToAdd, needle }); + // @ts-expect-error invalid params + expect(() => needleCallback.call({ log() {} })).toThrow(/content is required/); }); it('returned function should throw on missing needle', () => { - expect(() => createNeedleCallback({ contentToAdd, needle }).call({ log() {} }, 'no needle')).toThrow( - /Missing required jhipster-needle/, - ); + const log = test.mock.fn(createJHipsterLogger()); + const needleCallback = createNeedleCallback({ contentToAdd, needle }); + // @ts-expect-error invalid params + expect(() => needleCallback.call({ log } as any, 'no needle')).toThrow(/Missing required jhipster-needle/); }); it('returned function should not throw on optional missing needle', () => { const content = 'no needle'; - const log = () => {}; - log.warn = () => {}; - expect(createNeedleCallback({ contentToAdd, needle, optional: true }).call({ log }, content, 'file')).toBe(content); + const log = test.mock.fn(createJHipsterLogger()); + const needleCallback = createNeedleCallback({ contentToAdd, needle, optional: true }); + expect(needleCallback.call({ log } as any, content, 'file')).toBe(content); }); it('returned function should add contentToAdd', () => { - expect(createNeedleCallback({ contentToAdd, needle }).call({ log() {} }, `\\\\ jhipster-needle-${needle}`, 'file')) - .toMatchInlineSnapshot(` + const log = test.mock.fn(createJHipsterLogger()); + const needleCallback = createNeedleCallback({ contentToAdd, needle }); + expect(needleCallback.call({ log } as any, `\\\\ jhipster-needle-${needle}`, 'file')).toMatchInlineSnapshot(` "content to add \\\\ jhipster-needle-a-needle" `); }); it('returned function should add contentToAdd array', () => { - expect( - createNeedleCallback({ contentToAdd: [contentToAdd, `${contentToAdd}2`], needle }).call( - { log() {} }, - `\\\\ jhipster-needle-${needle}`, - ), - ).toMatchInlineSnapshot(` + const log = test.mock.fn(createJHipsterLogger()); + const needleCallback = createNeedleCallback({ contentToAdd: [contentToAdd, `${contentToAdd}2`], needle }); + expect(needleCallback.call({ log } as any, `\\\\ jhipster-needle-${needle}`, 'any-file')).toMatchInlineSnapshot(` "content to add content to add2 \\\\ jhipster-needle-a-needle" @@ -276,7 +279,6 @@ content to add2 }); it('should throw with options and empty needles', () => { - // @ts-expect-error expect(() => createBaseNeedle({ optional: true }, {})).toThrow(/At least 1 needle is required/); }); @@ -286,12 +288,13 @@ content to add2 it('should throw with filePath without generator', () => { const filePath = 'file.foo'; + // @ts-expect-error invalid params expect(() => createBaseNeedle({ filePath }, needles)).toThrow(/when passing filePath, the generator is required/); }); it('should execute editFile if generator and filePath is passed', () => { const filePath = 'file.foo'; - createBaseNeedle.call(generator, { filePath }, needles); + createBaseNeedle.call(generator as any, { filePath }, needles); expect(generator.editFile).toBeCalledTimes(1); expect(generator.editFile.mock.lastCall[0]).toBe(filePath); expect(typeof generator.editFile.mock.lastCall[1]).toBe('function'); diff --git a/generators/base/support/needles.ts b/generators/base/support/needles.ts index bfeda315349e..0d874903c21a 100644 --- a/generators/base/support/needles.ts +++ b/generators/base/support/needles.ts @@ -19,7 +19,7 @@ import assert from 'assert'; import { escapeRegExp, kebabCase } from 'lodash-es'; import type CoreGenerator from '../../base-core/index.js'; -import type { CascatedEditFileCallback, EditFileCallback } from '../api.js'; +import type { CascatedEditFileCallback, EditFileCallback, NeedleCallback } from '../api.js'; import { joinCallbacks } from './write-files.js'; export type NeedleInsertion = { @@ -210,7 +210,7 @@ export const createNeedleCallback = , + needles: Record, +): NeedleCallback; +export function createBaseNeedle(needles: Record): NeedleCallback; +export function createBaseNeedle( + this: Generator, + options: Omit & { filePath: string }, + needles: Record, +): CascatedEditFileCallback; export function createBaseNeedle( this: Generator | void, - options: NeedleFileInsertion | Record, + options: Omit | Record, needles?: Record, ): EditFileCallback | CascatedEditFileCallback { const actualNeedles = needles === undefined ? (options as Record) : needles; const actualOptions: Partial | undefined = needles === undefined ? {} : (options as NeedleFileInsertion); assert(actualNeedles, 'needles is required'); - const { filePath, optional = false, ignoreWhitespaces = true } = actualOptions; - let { needlesPrefix } = actualOptions; - needlesPrefix = needlesPrefix ? `${needlesPrefix}-` : ''; + const { needlesPrefix, filePath, ...needleOptions } = actualOptions; + needleOptions.optional = needleOptions.optional ?? false; + needleOptions.ignoreWhitespaces = needleOptions.ignoreWhitespaces ?? true; const callbacks = Object.entries(actualNeedles) .filter(([_key, contentToAdd]) => contentToAdd) .map(([key, contentToAdd]) => - createNeedleCallback({ needle: `${needlesPrefix}${kebabCase(key)}`, contentToAdd, optional, ignoreWhitespaces }), + createNeedleCallback({ ...needleOptions, needle: `${needlesPrefix ? `${needlesPrefix}-` : ''}${kebabCase(key)}`, contentToAdd }), ); assert(callbacks.length > 0, 'At least 1 needle is required'); diff --git a/generators/base/support/timestamp.spec.ts b/generators/base/support/timestamp.spec.ts index 1cc04f25b114..9e2d79821625 100644 --- a/generators/base/support/timestamp.spec.ts +++ b/generators/base/support/timestamp.spec.ts @@ -28,6 +28,7 @@ describe('generator - base - support - timestamp', () => { }); describe('when passing a number', () => { it('throws', () => { + // @ts-expect-error invalid argument expect(() => parseChangelog(123)).toThrow(/^changelogDate 123 must be a string\.$/); }); }); diff --git a/generators/base/types.d.ts b/generators/base/types.d.ts index 1e7bded2b3e1..e4ce9a51f3c0 100644 --- a/generators/base/types.d.ts +++ b/generators/base/types.d.ts @@ -1,8 +1,8 @@ import type { Entity } from '../base-application/index.js'; import type { ExportControlPropertiesFromCommand } from '../../lib/command/index.js'; -import type { Command } from './command.ts'; +import type command from './command.ts'; -type BaseApplicationControlProperties = ExportControlPropertiesFromCommand; +type BaseApplicationControlProperties = ExportControlPropertiesFromCommand; export type Control = BaseApplicationControlProperties & { existingProject: boolean; diff --git a/generators/bootstrap-application-base/command.ts b/generators/bootstrap-application-base/command.ts index fcb0218dea5b..5020591ae9c7 100644 --- a/generators/bootstrap-application-base/command.ts +++ b/generators/bootstrap-application-base/command.ts @@ -19,7 +19,7 @@ import type { JHipsterCommandDefinition } from '../../lib/command/index.js'; import { parseCreationTimestamp } from '../base/support/timestamp.js'; -const command: JHipsterCommandDefinition = { +const command = { options: { baseName: { description: 'Application base name', @@ -46,6 +46,6 @@ const command: JHipsterCommandDefinition = { scope: 'storage', }, }, -}; +} as const satisfies JHipsterCommandDefinition; export default command; diff --git a/generators/bootstrap-application-base/generator.spec.ts b/generators/bootstrap-application-base/generator.spec.ts index a647775f845b..56ea0d3e893d 100644 --- a/generators/bootstrap-application-base/generator.spec.ts +++ b/generators/bootstrap-application-base/generator.spec.ts @@ -105,7 +105,7 @@ describe(`generator - ${generator}`, () => { const lastLiquibaseTimestamp = new Date(Date.parse('2030-01-01')); await helpers .run(generatorPath) - .withJHipsterConfig({ lastLiquibaseTimestamp: lastLiquibaseTimestamp.getTime(), creationTimestamp: null }) + .withJHipsterConfig({ lastLiquibaseTimestamp: lastLiquibaseTimestamp.getTime(), creationTimestamp: undefined }) .withOptions({ reproducible: false }); firstChangelogDate = runResult.generator.dateFormatForLiquibase(); secondChangelogDate = runResult.generator.dateFormatForLiquibase(); diff --git a/generators/ci-cd/command.ts b/generators/ci-cd/command.ts index d5d72e9603bb..dba7ccce0f6b 100644 --- a/generators/ci-cd/command.ts +++ b/generators/ci-cd/command.ts @@ -41,7 +41,7 @@ const command: JHipsterCommandDefinition = { { name: 'Travis CI', value: 'travis' }, { name: 'CircleCI', value: 'circle' }, ], - scope: 'generator', + scope: 'context', }, ciCdIntegrations: { prompt: { @@ -73,7 +73,7 @@ const command: JHipsterCommandDefinition = { value: 'cypressDashboard', }, ], - scope: 'generator', + scope: 'context', }, insideDocker: { prompt: { @@ -82,7 +82,7 @@ const command: JHipsterCommandDefinition = { message: 'Would you like to perform the build in a Docker container ?', default: false, }, - scope: 'generator', + scope: 'context', }, sendBuildToGitlab: { prompt: { @@ -91,7 +91,7 @@ const command: JHipsterCommandDefinition = { message: 'Would you like to send build status to GitLab ?', default: false, }, - scope: 'generator', + scope: 'context', }, artifactorySnapshotsId: { prompt: { @@ -100,7 +100,7 @@ const command: JHipsterCommandDefinition = { message: `${chalk.yellow('*Artifactory*')}: what is the ID of distributionManagement for snapshots ?`, }, default: 'snapshots', - scope: 'generator', + scope: 'context', }, artifactorySnapshotsUrl: { prompt: { @@ -109,7 +109,7 @@ const command: JHipsterCommandDefinition = { message: `${chalk.yellow('*Artifactory*')}: what is the URL of distributionManagement for snapshots ?`, }, default: 'http://artifactory:8081/artifactory/libs-snapshot', - scope: 'generator', + scope: 'context', }, artifactoryReleasesId: { prompt: { @@ -118,7 +118,7 @@ const command: JHipsterCommandDefinition = { message: `${chalk.yellow('*Artifactory*')}: what is the ID of distributionManagement for releases ?`, }, default: 'releases', - scope: 'generator', + scope: 'context', }, artifactoryReleasesUrl: { prompt: { @@ -127,7 +127,7 @@ const command: JHipsterCommandDefinition = { message: `${chalk.yellow('*Artifactory*')}: what is the URL of distributionManagement for releases ?`, }, default: 'http://artifactory:8081/artifactory/libs-release', - scope: 'generator', + scope: 'context', }, sonarName: { prompt: { @@ -136,7 +136,7 @@ const command: JHipsterCommandDefinition = { message: `${chalk.yellow('*Sonar*')}: what is the name of the Sonar server ?`, }, default: 'sonar', - scope: 'generator', + scope: 'context', }, sonarUrl: { prompt: { @@ -147,7 +147,7 @@ const command: JHipsterCommandDefinition = { message: `${chalk.yellow('*Sonar*')}: what is the URL of the Sonar server ?`, }, default: 'https://sonarcloud.io', - scope: 'generator', + scope: 'context', }, sonarOrga: { prompt: { @@ -157,7 +157,7 @@ const command: JHipsterCommandDefinition = { type: 'input', message: `${chalk.yellow('*Sonar*')}: what is the Organization of the Sonar server ?`, }, - scope: 'generator', + scope: 'context', }, dockerImage: { prompt: ({ jhipsterConfigWithDefaults: config }) => ({ @@ -166,7 +166,7 @@ const command: JHipsterCommandDefinition = { message: `${chalk.yellow('*Docker*')}: what is the name of the image ?`, default: () => `jhipster/${config.dasherizedBaseName}`, }), - scope: 'generator', + scope: 'context', }, herokuAppName: { prompt: { @@ -174,8 +174,10 @@ const command: JHipsterCommandDefinition = { type: 'input', message: `${chalk.yellow('*Heroku*')}: name of your Heroku Application ?`, }, - scope: 'generator', - default: gen => kebabCase(gen.jhipsterConfigWithDefaults.baseName), + scope: 'context', + default() { + return kebabCase(this.jhipsterConfigWithDefaults.baseName); + }, }, }, }; diff --git a/generators/ci-cd/generator.ts b/generators/ci-cd/generator.ts index 057bb1957086..944e38fd21ab 100644 --- a/generators/ci-cd/generator.ts +++ b/generators/ci-cd/generator.ts @@ -30,6 +30,7 @@ const { REACT } = clientFrameworkTypes; export default class CiCdGenerator extends BaseApplicationGenerator { insideDocker; + context = {}; async beforeQueue() { if (!this.fromBlueprint) { @@ -57,8 +58,8 @@ export default class CiCdGenerator extends BaseApplicationGenerator { // Public API method used by the getter and also by Blueprints get loading() { return this.asLoadingTaskGroup({ - loadSharedConfig({ application }) { - loadConfig.call(this, command.configs, { application }); + loadSharedConfig() { + loadConfig.call(this, command.configs, { application: this.context }); }, }); } @@ -69,19 +70,19 @@ export default class CiCdGenerator extends BaseApplicationGenerator { get preparing() { return this.asPreparingTaskGroup({ - setTemplateConstants({ application }) { - loadDerivedConfig(command.configs, { application }); + setTemplateConstants() { + loadDerivedConfig(command.configs, { application: this.context }); - if (application.ciCdIntegrations === undefined) { - application.ciCdIntegrations = []; + if (this.context.ciCdIntegrations === undefined) { + this.context.ciCdIntegrations = []; } - application.gitLabIndent = application.sendBuildToGitlab ? ' ' : ''; - application.indent = application.insideDocker ? ' ' : ''; - application.indent += application.gitLabIndent; - if (application.clientFramework === REACT) { - application.frontTestCommand = 'test-ci'; + this.context.gitLabIndent = this.context.sendBuildToGitlab ? ' ' : ''; + this.context.indent = this.context.insideDocker ? ' ' : ''; + this.context.indent += this.context.gitLabIndent; + if (this.context.clientFramework === REACT) { + this.context.frontTestCommand = 'test-ci'; } else { - application.frontTestCommand = 'test'; + this.context.frontTestCommand = 'test'; } }, }); @@ -91,6 +92,18 @@ export default class CiCdGenerator extends BaseApplicationGenerator { return this.delegateTasksToBlueprint(() => this.preparing); } + get default() { + return this.asDefaultTaskGroup({ + loadContext({ application }) { + Object.assign(application, this.context); + }, + }); + } + + get [BaseApplicationGenerator.DEFAULT]() { + return this.delegateTasksToBlueprint(() => this.default); + } + // Public API method used by the getter and also by Blueprints get writing() { return this.asWritingTaskGroup({ @@ -106,11 +119,11 @@ export default class CiCdGenerator extends BaseApplicationGenerator { }, { sourceFile: 'jenkins/jenkins.yml', - destinationFile: `${application.dockerServicesDir}jenkins.yml`, + destinationFile: ctx => `${ctx.dockerServicesDir}jenkins.yml`, }, { sourceFile: 'jenkins/idea.gdsl', - destinationFile: `${application.srcMainResources}idea.gdsl`, + destinationFile: ctx => `${ctx.srcMainResources}idea.gdsl`, }, ], }, @@ -138,7 +151,7 @@ export default class CiCdGenerator extends BaseApplicationGenerator { context: application, }); - if (application.ciCdIntegrations.includes('publishDocker')) { + if (application.ciCdIntegrations?.includes('publishDocker')) { this.writeFile('docker-registry.yml.ejs', `${application.dockerServicesDir}docker-registry.yml`); } }, @@ -153,7 +166,7 @@ export default class CiCdGenerator extends BaseApplicationGenerator { get postWriting() { return this.asPostWritingTaskGroup({ postWriting({ application }) { - if (application.ciCdIntegrations.includes('deploy')) { + if (application.ciCdIntegrations?.includes('deploy')) { if (application.buildToolMaven) { createPomStorage(this, { sortFile: false }).addDistributionManagement({ releasesId: application.artifactoryReleasesId, diff --git a/generators/client/generator-needles.spec.ts b/generators/client/generator-needles.spec.ts index 28272e1d15cc..c23d1245527e 100644 --- a/generators/client/generator-needles.spec.ts +++ b/generators/client/generator-needles.spec.ts @@ -25,7 +25,7 @@ describe('needle API Webpack: JHipster client generator with blueprint', () => { return helpers .create(getGenerator('client')) .withOptions({ - blueprint: 'myblueprint', + blueprint: ['myblueprint'], }) .withJHipsterConfig({ buildTool: 'maven', diff --git a/generators/client/generator.spec.ts b/generators/client/generator.spec.ts index d480576dd4ed..597aad778ddb 100644 --- a/generators/client/generator.spec.ts +++ b/generators/client/generator.spec.ts @@ -142,12 +142,11 @@ describe(`generator - ${generator}`, () => { 'jhipster:react', 'jhipster:vue', ]; - const options = { applicationType: 'microservice' }; before(async () => { await helpers .run(generatorFile) .withControl({ getWebappTranslation: () => 'translations' }) - .withJHipsterConfig(options) + .withJHipsterConfig({ applicationType: 'microservice' }) .withSkipWritingPriorities() .withMockedGenerators(mockedComposedGenerators); }); diff --git a/generators/client/needle-api/needle-client-vue.ts b/generators/client/needle-api/needle-client-vue.ts index 723bb73d146d..b05c9c9afe66 100644 --- a/generators/client/needle-api/needle-client-vue.ts +++ b/generators/client/needle-api/needle-client-vue.ts @@ -57,7 +57,7 @@ export default class extends needleClientBase { ); } - addEntityToRouterImport(entityName: string, fileName: string, folderName: string, readOnly: string) { + addEntityToRouterImport(entityName: string, fileName: string, folderName: string, readOnly?: string) { const ignoreNonExisting = this.generator.sharedData.getControl().ignoreNeedlesError && `${chalk.yellow('Reference to entity ') + entityName} ${chalk.yellow('not added to router entities import.\n')}`; @@ -97,7 +97,7 @@ export default class extends needleClientBase { ); } - addEntityToRouter(entityInstance: string, entityName: string, entityFileName: string, readOnly: boolean) { + addEntityToRouter(entityInstance: string, entityName: string, entityFileName: string, readOnly?: boolean) { const ignoreNonExisting = this.generator.sharedData.getControl().ignoreNeedlesError && `${chalk.yellow('Reference to entity ') + entityName} ${chalk.yellow('not added to router entities.\n')}`; diff --git a/generators/client/needle-api/needle-client.ts b/generators/client/needle-api/needle-client.ts index 3a21525c9ae6..189053ab3a17 100644 --- a/generators/client/needle-api/needle-client.ts +++ b/generators/client/needle-api/needle-client.ts @@ -19,7 +19,7 @@ import needleBase from '../../needle-base.js'; export default class extends needleBase { - addStyle(style: string, comment: string, filePath: string, needle: string) { + addStyle(style: string, comment: string | undefined, filePath: string, needle: string) { const content = this._mergeStyleAndComment(style, comment); this.addBlockContentToFile( @@ -28,7 +28,7 @@ export default class extends needleBase { ); } - _mergeStyleAndComment(style: string, comment: string) { + _mergeStyleAndComment(style: string, comment?: string) { let styleBlock = ''; if (comment) { diff --git a/generators/client/needle-client.spec.ts b/generators/client/needle-client.spec.ts index 7c8cea6a2c8e..6f0ad7790070 100644 --- a/generators/client/needle-client.spec.ts +++ b/generators/client/needle-client.spec.ts @@ -35,7 +35,7 @@ describe('needle API Client: JHipster client generator with blueprint', () => { skipServer: true, }) .withOptions({ - blueprint: 'myblueprint', + blueprint: ['myblueprint'], }) .withGenerators([[mockBlueprintSubGen, { namespace: 'jhipster-myblueprint:client' }]]); }); diff --git a/generators/client/types.d.ts b/generators/client/types.d.ts index 9ff5815d95aa..35cf78e2b8f8 100644 --- a/generators/client/types.d.ts +++ b/generators/client/types.d.ts @@ -29,7 +29,7 @@ export type ClientResources = { }; export type ClientSourceType = JavaScriptSourceType & { - addEntitiesToClient: (arg1: PostWritingEntitiesTaskParam) => void; + addEntitiesToClient: (arg1: Pick) => void; /** * Add external resources to root file(index.html). */ diff --git a/generators/export-jdl/__snapshots__/export-jdl.spec.ts.snap b/generators/export-jdl/__snapshots__/export-jdl.spec.ts.snap index b82a6e00c4f2..db8ddf979404 100644 --- a/generators/export-jdl/__snapshots__/export-jdl.spec.ts.snap +++ b/generators/export-jdl/__snapshots__/export-jdl.spec.ts.snap @@ -26,7 +26,6 @@ exports[`generator - export-jdl exports entities to a JDL file with file argumen serverPort 8080 skipClient true skipServer true - testFrameworks [] websocket no } @@ -145,7 +144,6 @@ exports[`generator - export-jdl exports entities to a JDL file without argument serverPort 8080 skipClient true skipServer true - testFrameworks [] websocket no } diff --git a/generators/export-jdl/export-jdl.spec.ts b/generators/export-jdl/export-jdl.spec.ts index 69d615c19340..4418c45357af 100644 --- a/generators/export-jdl/export-jdl.spec.ts +++ b/generators/export-jdl/export-jdl.spec.ts @@ -358,21 +358,20 @@ const applicationConfig = { buildTool: 'gradle', rememberMeKey: '5f1100e7eae25e2abe32d7b2031ac1f2acc778d8', applicationType: 'monolith', - testFrameworks: [], jhiPrefix: 'jhi', enableTranslation: true, nativeLanguage: 'en', languages: ['en'], skipClient: true, skipServer: true, -}; +} as const; describe('generator - export-jdl', () => { describe('exports entities to a JDL file without argument', () => { let runResult; before(async () => { - runResult = await helpers.runJHipster(GENERATOR_EXPORT_JDL).withJHipsterConfig(applicationConfig).withFiles(files).commitFiles(); + runResult = await helpers.runJHipster(GENERATOR_EXPORT_JDL).withJHipsterConfig(applicationConfig).withFiles(files).commitFiles(); }); it('should match snapshot', () => { @@ -389,7 +388,7 @@ describe('generator - export-jdl', () => { before(async () => { runResult = await helpers .runJHipster(GENERATOR_EXPORT_JDL) - .withJHipsterConfig(applicationConfig) + .withJHipsterConfig(applicationConfig) .withFiles(files) .commitFiles() .withArguments('custom-app.jdl'); diff --git a/generators/git/command.ts b/generators/git/command.ts index 5fa7b63b533e..78fd48ef5b83 100644 --- a/generators/git/command.ts +++ b/generators/git/command.ts @@ -18,7 +18,7 @@ */ import type { JHipsterCommandDefinition } from '../../lib/command/index.js'; -const command: JHipsterCommandDefinition = { +const command = { configs: { skipGit: { description: 'Skip git repository initialization', @@ -42,6 +42,6 @@ const command: JHipsterCommandDefinition = { scope: 'storage', }, }, -}; +} as const satisfies JHipsterCommandDefinition; export default command; diff --git a/generators/gradle/needles.spec.ts b/generators/gradle/needles.spec.ts index 365328daee4e..c43e26c7f92e 100644 --- a/generators/gradle/needles.spec.ts +++ b/generators/gradle/needles.spec.ts @@ -45,10 +45,12 @@ describe('needle API server gradle: JHipster server generator with blueprint', ( await helpers .runJHipster(GENERATOR_SERVER) .withJHipsterConfig({ - blueprint: 'myblueprint', clientFramework: 'no', buildTool: 'gradle', }) + .withOptions({ + blueprint: ['myblueprint'], + }) .withGenerators([[mockBlueprintSubGen, { namespace: 'jhipster-myblueprint:server' }]]); }); diff --git a/generators/heroku/generator.ts b/generators/heroku/generator.ts index 82d0866e70e0..1765265366cd 100644 --- a/generators/heroku/generator.ts +++ b/generators/heroku/generator.ts @@ -140,7 +140,7 @@ export default class HerokuGenerator extends BaseGenerator { type: 'input', name: 'herokuAppName', message: 'Name to deploy as:', - default: this.baseName, + default: this.jhipsterConfigWithDefaults.baseName, }, ], this.config, diff --git a/generators/heroku/heroku.spec.ts b/generators/heroku/heroku.spec.ts index e2997bef970e..6e5a519dcd7f 100644 --- a/generators/heroku/heroku.spec.ts +++ b/generators/heroku/heroku.spec.ts @@ -222,7 +222,7 @@ describe('generator - Heroku', () => { .returns(createSpawnCommandReturn({ stdout: `{"app":{"name":"${existingHerokuAppName}"}, "dynos":[]}` })); await helpers .createJHipster(GENERATOR_HEROKU) - .withJHipsterConfig({ herokuAppName: 'jhipster-existing', herokuDeployType: 'git' }) + .withJHipsterConfig({ herokuAppName: 'jhipster-existing', herokuDeployType: 'git' }) .withOptions({ skipBuild: true }) .withSpawnMock(stub) .run(); diff --git a/generators/java/generators/bootstrap/command.ts b/generators/java/generators/bootstrap/command.ts index 387fd7067cd6..22a974b53352 100644 --- a/generators/java/generators/bootstrap/command.ts +++ b/generators/java/generators/bootstrap/command.ts @@ -16,8 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import type { PromptSpec } from '../../../../lib/command/index.js'; -import { asCommand } from '../../../type-utils.js'; +import type { JHipsterCommandDefinition, PromptSpec } from '../../../../lib/command/index.js'; const command = { options: { @@ -53,8 +52,6 @@ const command = { }, }, import: [], -} as const; +} as const satisfies JHipsterCommandDefinition; -export type Command = typeof command; - -export default asCommand(command); +export default command; diff --git a/generators/java/generators/bootstrap/generator.ts b/generators/java/generators/bootstrap/generator.ts index f7a9e6b0f0fe..02462d836977 100644 --- a/generators/java/generators/bootstrap/generator.ts +++ b/generators/java/generators/bootstrap/generator.ts @@ -61,7 +61,7 @@ export default class BootstrapGenerator extends BaseApplicationGenerator { return this.asConfiguringTaskGroup({ checkConfig() { const { packageName } = this.jhipsterConfigWithDefaults; - const reservedKeywork = packageName.split('.').find(isReservedJavaKeyword); + const reservedKeywork = packageName!.split('.').find(isReservedJavaKeyword); if (reservedKeywork) { throw new Error(`The package name "${packageName}" contains a reserved Java keyword "${reservedKeywork}".`); } diff --git a/generators/java/generators/build-tool/command.ts b/generators/java/generators/build-tool/command.ts index ea6b665a523c..38265ab2eaff 100644 --- a/generators/java/generators/build-tool/command.ts +++ b/generators/java/generators/build-tool/command.ts @@ -16,9 +16,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import type { JHipsterCommandDefinition } from '../../../../lib/command/types.js'; import { buildToolTypes } from '../../../../lib/jhipster/index.js'; import { GENERATOR_GRADLE, GENERATOR_MAVEN } from '../../../generator-list.js'; -import { asCommand } from '../../../type-utils.js'; const { GRADLE, MAVEN } = buildToolTypes; @@ -44,8 +44,6 @@ const command = { }, }, import: [GENERATOR_GRADLE, GENERATOR_MAVEN], -} as const; +} as const satisfies JHipsterCommandDefinition; -export type Command = typeof command; - -export default asCommand(command); +export default command; diff --git a/generators/java/generators/openapi-generator/command.ts b/generators/java/generators/openapi-generator/command.ts index 0fd84a85f3e5..0703c340e48f 100644 --- a/generators/java/generators/openapi-generator/command.ts +++ b/generators/java/generators/openapi-generator/command.ts @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { asCommand } from '../../../type-utils.js'; +import type { JHipsterCommandDefinition } from '../../../../lib/command/types.js'; const command = { configs: { @@ -30,8 +30,8 @@ const command = { }, }, import: [], -} as const; +} as const satisfies JHipsterCommandDefinition; export type Command = typeof command; -export default asCommand(command); +export default command; diff --git a/generators/java/types.d.ts b/generators/java/types.d.ts index bfd22ce9c787..36a27aedcd01 100644 --- a/generators/java/types.d.ts +++ b/generators/java/types.d.ts @@ -4,11 +4,11 @@ import type { EditFileCallback } from '../base/api.js'; import type { MavenDefinition } from '../maven/types.js'; import type { ExportStoragePropertiesFromCommand } from '../../lib/command/index.js'; import type { JavaAnnotation } from './support/add-java-annotation.ts'; -import type { Command as OpenapiGeneratorCommand } from './generators/openapi-generator/command.js'; -import type { Command as BootstrapCommand } from './generators/bootstrap/command.js'; +import type { default as OpenapiGeneratorCommand } from './generators/openapi-generator/command.js'; +import type { default as BootstrapCommand } from './generators/bootstrap/command.js'; -type JavaBootstrapStorageProperties = ExportStoragePropertiesFromCommand; -type JavaOpenapiGeneratorStorageProperties = ExportStoragePropertiesFromCommand; +type JavaBootstrapStorageProperties = ExportStoragePropertiesFromCommand; +type JavaOpenapiGeneratorStorageProperties = ExportStoragePropertiesFromCommand; export type JavaDependencyVersion = { name: string; diff --git a/generators/javascript/generators/prettier/command.ts b/generators/javascript/generators/prettier/command.ts index 248132526fdd..1656ed37a6ad 100644 --- a/generators/javascript/generators/prettier/command.ts +++ b/generators/javascript/generators/prettier/command.ts @@ -21,7 +21,7 @@ import gitCommand from '../../../git/command.js'; const { monorepository } = gitCommand.configs!; -const command: JHipsterCommandDefinition = { +const command = { configs: { fromInit: { description: 'Generate prettier config using init defaults', @@ -60,6 +60,6 @@ const command: JHipsterCommandDefinition = { }, }, import: [], -}; +} as const satisfies JHipsterCommandDefinition; export default command; diff --git a/generators/languages/command.ts b/generators/languages/command.ts index c04f0e6fbbbc..8424fd9247e8 100644 --- a/generators/languages/command.ts +++ b/generators/languages/command.ts @@ -18,7 +18,7 @@ */ import type { JHipsterCommandDefinition } from '../../lib/command/index.js'; -const command: JHipsterCommandDefinition = { +const command = { arguments: { languages: { description: 'Languages to generate', @@ -26,30 +26,46 @@ const command: JHipsterCommandDefinition = { required: false, }, }, - options: { + configs: { + languages: { + cli: { + type: Array, + hide: true, + }, + scope: 'storage', + }, enableTranslation: { - description: 'Enable translation', - type: Boolean, - required: false, + cli: { + description: 'Enable translation', + type: Boolean, + }, scope: 'storage', }, language: { - alias: 'l', - description: 'Language to be added to application (existing languages are not removed)', - type: Array, + cli: { + alias: 'l', + description: 'Language to be added to application (existing languages are not removed)', + type: Array, + }, + scope: 'none', }, nativeLanguage: { - alias: 'n', - description: 'Set application native language', - type: String, - required: false, + cli: { + alias: 'n', + description: 'Set application native language', + type: String, + required: false, + }, + scope: 'storage', }, regenerateLanguages: { - description: 'Regenerate languages', - type: Boolean, + cli: { + description: 'Regenerate languages', + type: Boolean, + }, scope: 'generator', }, }, -}; +} as const satisfies JHipsterCommandDefinition; export default command; diff --git a/generators/languages/generator-needles.spec.ts b/generators/languages/generator-needles.spec.ts index 93b47b7998de..99363225ca06 100644 --- a/generators/languages/generator-needles.spec.ts +++ b/generators/languages/generator-needles.spec.ts @@ -37,7 +37,7 @@ describe('needle API i18n: JHipster language generator with blueprint', () => { build: 'maven', auth: 'jwt', db: 'mysql', - blueprint: 'myblueprint', + blueprint: ['myblueprint'], nativeLanguage: 'en', languages: ['en', 'fr'], }) diff --git a/generators/liquibase/needles.spec.ts b/generators/liquibase/needles.spec.ts index 11a86956b55f..f211c7a30379 100644 --- a/generators/liquibase/needles.spec.ts +++ b/generators/liquibase/needles.spec.ts @@ -39,10 +39,10 @@ describe('generator - liquibase - needles', () => { `, }) .withJHipsterConfig({ - blueprint: 'myblueprint', clientFramework: 'no', }) .withOptions({ + blueprint: ['myblueprint'], skipPriorities: ['writing'], }) .withGenerators([[mockBlueprintSubGen, { namespace: 'jhipster-myblueprint:liquibase' }]]); diff --git a/generators/maven/needles.spec.ts b/generators/maven/needles.spec.ts index 33c31846056f..e21e5f83c12a 100644 --- a/generators/maven/needles.spec.ts +++ b/generators/maven/needles.spec.ts @@ -122,8 +122,10 @@ describe('generator - maven - needles', () => { before(async () => { await helpers .runJHipster(GENERATOR_MAVEN) + .withOptions({ + blueprint: ['myblueprint'], + }) .withJHipsterConfig({ - blueprint: 'myblueprint', clientFramework: 'no', }) .withGenerators([[mockBlueprintSubGen, { namespace: 'jhipster-myblueprint:maven' }]]); @@ -247,10 +249,10 @@ describe('generator - maven - needles', () => { await helpers .runJHipster(GENERATOR_MAVEN) .withJHipsterConfig({ - blueprint: 'myblueprint', clientFramework: 'no', }) .withOptions({ + blueprint: ['myblueprint'], profile: 'prod', }) .withGenerators([[mockBlueprintSubGen, { namespace: 'jhipster-myblueprint:maven' }]]); diff --git a/generators/react/generator.ts b/generators/react/generator.ts index b4c847450d23..24d041e48de8 100644 --- a/generators/react/generator.ts +++ b/generators/react/generator.ts @@ -335,7 +335,7 @@ export default class ReactGenerator extends BaseApplicationGenerator { * } * */ - addAppSCSSStyle(style, comment) { + addAppSCSSStyle(style, comment?) { this.needleApi.clientReact.addAppSCSSStyle(style, comment); } diff --git a/generators/react/needle-api/needle-client-react.ts b/generators/react/needle-api/needle-client-react.ts index faa166b24181..33f75f777c2e 100644 --- a/generators/react/needle-api/needle-client-react.ts +++ b/generators/react/needle-api/needle-client-react.ts @@ -23,7 +23,7 @@ import needleClientBase from '../../client/needle-api/needle-client.js'; import { stripMargin } from '../../base/support/index.js'; export default class extends needleClientBase { - addAppSCSSStyle(style: string, comment: string) { + addAppSCSSStyle(style: string, comment?: string) { const filePath = `${this.clientSrcDir}app/app.scss`; this.addStyle(style, comment, filePath, 'jhipster-needle-scss-add-main'); } diff --git a/generators/server/command.ts b/generators/server/command.ts index 74ac1a67a4fb..65f82713b865 100644 --- a/generators/server/command.ts +++ b/generators/server/command.ts @@ -21,11 +21,12 @@ import type { JHipsterCommandDefinition } from '../../lib/command/index.js'; import { GENERATOR_COMMON, GENERATOR_SPRING_BOOT } from '../generator-list.js'; import { APPLICATION_TYPE_GATEWAY, APPLICATION_TYPE_MICROSERVICE, APPLICATION_TYPE_MONOLITH } from '../../lib/jhipster/index.js'; -const command: JHipsterCommandDefinition = { +const command = { options: { db: { description: 'Provide DB name for the application when skipping server side generation', type: String, + scope: 'none', }, incrementalChangelog: { description: 'Creates incremental database changelogs', @@ -40,6 +41,7 @@ const command: JHipsterCommandDefinition = { recreateInitialChangelog: { description: 'Recreate the initial database changelog based on the current config', type: Boolean, + scope: 'none', }, cacheProvider: { description: 'Cache provider', @@ -74,6 +76,7 @@ const command: JHipsterCommandDefinition = { skipDbChangelog: { description: 'Skip the generation of database migrations', type: Boolean, + scope: 'none', }, skipFakeData: { description: 'Skip generation of fake data for development', @@ -122,9 +125,10 @@ const command: JHipsterCommandDefinition = { name: 'Microservice application', }, ], + scope: 'storage', }, }, import: [GENERATOR_COMMON, GENERATOR_SPRING_BOOT], -}; +} as const satisfies JHipsterCommandDefinition; export default command; diff --git a/generators/server/needle-logback.spec.ts b/generators/server/needle-logback.spec.ts index 462b035b5b93..27345bb5cdab 100644 --- a/generators/server/needle-logback.spec.ts +++ b/generators/server/needle-logback.spec.ts @@ -26,8 +26,10 @@ describe('generators - server - needle - logback', () => { before(async () => { await helpers .runJHipster(GENERATOR_SERVER) + .withOptions({ + blueprint: ['myblueprint'], + }) .withJHipsterConfig({ - blueprint: 'myblueprint', clientFramework: 'no', }) .withGenerators([[mockBlueprintSubGen, { namespace: 'jhipster-myblueprint:server' }]]); diff --git a/generators/server/support/needles.spec.ts b/generators/server/support/needles.spec.ts index 3cb7d02e9cd3..8302a7bf6def 100644 --- a/generators/server/support/needles.spec.ts +++ b/generators/server/support/needles.spec.ts @@ -19,7 +19,6 @@ import { before, describe, expect, it } from 'esmocha'; import { defaultHelpers as helpers, runResult } from '../../../testing/index.js'; import { GENERATOR_SPRING_BOOT } from '../../generator-list.js'; -import type { SpringBootApplication } from '../types.js'; import { insertContentIntoApplicationProperties } from './needles.js'; describe('generator - server - support - needles', () => { @@ -36,10 +35,11 @@ describe('generator - server - support - needles', () => { describe('insertContentIntoApplicationProperties needle', () => { it('with a non existing needle', () => { - const application: SpringBootApplication = runResult.generator.sharedData.getApplication(); - expect(() => insertContentIntoApplicationProperties.call(runResult.generator, application, { foo: 'foo' })).toThrow( - /Missing required jhipster-needle application-properties-foo not found at/, - ); + const application = runResult.generator.sharedData.getApplication(); + expect(() => { + // @ts-expect-error invalid needle + insertContentIntoApplicationProperties.call(runResult.generator, application, { foo: 'foo' }); + }).toThrow(/Missing required jhipster-needle application-properties-foo not found at/); }); it('without a needle', () => { diff --git a/generators/server/support/needles.ts b/generators/server/support/needles.ts index 799ee68076ad..1c9616afee99 100644 --- a/generators/server/support/needles.ts +++ b/generators/server/support/needles.ts @@ -16,9 +16,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import assert from 'assert'; import type CoreGenerator from '../../base-core/index.js'; import { createBaseNeedle } from '../../base/support/needles.js'; -import type { SpringBootApplication } from '../types.js'; export type ApplicationPropertiesNeedles = { property?: string; @@ -56,22 +56,24 @@ export type ApplicationPropertiesNeedles = { * }); * ); */ +export function insertContentIntoApplicationProperties(needles: ApplicationPropertiesNeedles); export function insertContentIntoApplicationProperties( this: CoreGenerator, - application: SpringBootApplication, + application: { javaPackageSrcDir: string }, needles: ApplicationPropertiesNeedles, ); -export function insertContentIntoApplicationProperties(this: void, needles: ApplicationPropertiesNeedles); export function insertContentIntoApplicationProperties( this: CoreGenerator | void, - application: SpringBootApplication | ApplicationPropertiesNeedles, + application: { javaPackageSrcDir: string } | ApplicationPropertiesNeedles, needles?: ApplicationPropertiesNeedles, ) { - if (this) { + if (needles) { + assert.ok(this, 'Generator context is required'); + return createBaseNeedle.call( this, { - filePath: `${(application as SpringBootApplication).javaPackageSrcDir}config/ApplicationProperties.java`, + filePath: `${(application as { javaPackageSrcDir: string }).javaPackageSrcDir}config/ApplicationProperties.java`, needlesPrefix: 'application-properties', }, needles, diff --git a/generators/spring-boot/command.ts b/generators/spring-boot/command.ts index f00ad9f728c6..c57815e64bc7 100644 --- a/generators/spring-boot/command.ts +++ b/generators/spring-boot/command.ts @@ -172,6 +172,14 @@ const command = { } }, }, + databaseType: { + cli: { + type: String, + hide: true, + }, + choices: ['sql', 'mongodb', 'couchbase', 'cassandra', 'neo4j', 'no'], + scope: 'storage', + }, }, import: [GENERATOR_JAVA, GENERATOR_LIQUIBASE, GENERATOR_SPRING_DATA_RELATIONAL], } as const satisfies JHipsterCommandDefinition; diff --git a/generators/spring-boot/generator.ts b/generators/spring-boot/generator.ts index 9ae2efaa9465..3e479550ee6f 100644 --- a/generators/spring-boot/generator.ts +++ b/generators/spring-boot/generator.ts @@ -105,7 +105,7 @@ export default class SpringBootGenerator extends BaseApplicationGenerator { return this.asConfiguringTaskGroup({ checks() { const config = this.jhipsterConfigWithDefaults; - if (config.enableHibernateCache && [NO_CACHE, MEMCACHED].includes(config.cacheProvider)) { + if (config.enableHibernateCache && [NO_CACHE, MEMCACHED].includes(config.cacheProvider!)) { this.log.verboseInfo(`Disabling hibernate cache for cache provider ${config.cacheProvider}`); this.jhipsterConfig.enableHibernateCache = false; } @@ -199,7 +199,7 @@ export default class SpringBootGenerator extends BaseApplicationGenerator { if (websocket === SPRING_WEBSOCKET) { await this.composeWithJHipster(GENERATOR_SPRING_WEBSOCKET); } - if ([EHCACHE, CAFFEINE, HAZELCAST, INFINISPAN, MEMCACHED, REDIS].includes(cacheProvider)) { + if ([EHCACHE, CAFFEINE, HAZELCAST, INFINISPAN, MEMCACHED, REDIS].includes(cacheProvider!)) { await this.composeWithJHipster(GENERATOR_SPRING_CACHE); } }, diff --git a/generators/spring-cache/needles.spec.ts b/generators/spring-cache/needles.spec.ts index 128fc81edb99..2ec0194e6865 100644 --- a/generators/spring-cache/needles.spec.ts +++ b/generators/spring-cache/needles.spec.ts @@ -33,7 +33,7 @@ describe('needle API server cache: JHipster server generator with blueprint', () await helpers .runJHipster(GENERATOR_SPRING_CACHE) .withOptions({ - blueprint: 'myblueprint', + blueprint: ['myblueprint'], }) .withJHipsterConfig({ cacheProvider: 'ehcache', @@ -68,7 +68,7 @@ describe('needle API server cache: JHipster server generator with blueprint', () await helpers .runJHipster(GENERATOR_SPRING_CACHE) .withOptions({ - blueprint: 'myblueprint', + blueprint: ['myblueprint'], }) .withJHipsterConfig({ cacheProvider: 'caffeine', @@ -103,7 +103,7 @@ describe('needle API server cache: JHipster server generator with blueprint', () await helpers .runJHipster(GENERATOR_SPRING_CACHE) .withOptions({ - blueprint: 'myblueprint', + blueprint: ['myblueprint'], }) .withJHipsterConfig({ cacheProvider: 'redis', diff --git a/generators/spring-cloud/generators/gateway/__snapshots__/generator.spec.ts.snap b/generators/spring-cloud/generators/gateway/__snapshots__/generator.spec.ts.snap index b0bbddf98867..b946a0b24026 100644 --- a/generators/spring-cloud/generators/gateway/__snapshots__/generator.spec.ts.snap +++ b/generators/spring-cloud/generators/gateway/__snapshots__/generator.spec.ts.snap @@ -72,5 +72,11 @@ exports[`generator - spring-cloud:gateway with serviceDiscovery option should ma "src/main/java/com/mycompany/myapp/security/jwt/JWTRelayGatewayFilterFactory.java": { "stateCleared": "modified", }, + "src/main/java/com/mycompany/myapp/web/rest/GatewayResource.java": { + "stateCleared": "modified", + }, + "src/main/java/com/mycompany/myapp/web/rest/vm/RouteVM.java": { + "stateCleared": "modified", + }, } `; diff --git a/generators/spring-cloud/generators/gateway/generator.spec.ts b/generators/spring-cloud/generators/gateway/generator.spec.ts index b5bbc2a797c8..3bb5b8e2cd1c 100644 --- a/generators/spring-cloud/generators/gateway/generator.spec.ts +++ b/generators/spring-cloud/generators/gateway/generator.spec.ts @@ -62,7 +62,7 @@ describe(`generator - ${generator}`, () => { .withMockedJHipsterGenerators() .withMockedSource() .withSharedApplication({}) - .withJHipsterConfig({ serviceDiscovery: 'consul' }); + .withJHipsterConfig({ serviceDiscoveryType: 'consul' }); }); it('should match files snapshot', () => { diff --git a/generators/spring-data-relational/command.ts b/generators/spring-data-relational/command.ts index 1781ab370b61..f519e0854b61 100644 --- a/generators/spring-data-relational/command.ts +++ b/generators/spring-data-relational/command.ts @@ -18,7 +18,7 @@ */ import type { JHipsterCommandDefinition } from '../../lib/command/index.js'; -const command: JHipsterCommandDefinition = { +const command = { options: { devDatabaseType: { description: 'Development database', @@ -26,6 +26,16 @@ const command: JHipsterCommandDefinition = { scope: 'storage', }, }, -}; + configs: { + prodDatabaseType: { + cli: { + type: String, + hide: true, + }, + choices: ['postgresql', 'mysql', 'mariadb', 'oracle', 'mssql'], + scope: 'storage', + }, + }, +} as const satisfies JHipsterCommandDefinition; export default command; diff --git a/generators/vue/generator.ts b/generators/vue/generator.ts index a42eb36bae3c..e2d65daa2091 100644 --- a/generators/vue/generator.ts +++ b/generators/vue/generator.ts @@ -252,7 +252,7 @@ export default class VueGenerator extends BaseApplicationGenerator { * @param {boolean} readOnly - If the entity is read-only or not * @param {string} pageTitle - The translation key or the text for the page title in the browser */ - addEntityToModule(entityInstance, entityClass, entityName, entityFolderName, entityFileName, _entityUrl, _microserviceName, readOnly) { + addEntityToModule(entityInstance, entityClass, entityName, entityFolderName, entityFileName, _entityUrl, _microserviceName, readOnly?) { this.needleApi.clientVue.addEntityToRouterImport(entityName, entityFileName, entityFolderName, readOnly); this.needleApi.clientVue.addEntityToRouter(entityInstance, entityName, entityFileName, readOnly); this.needleApi.clientVue.addEntityServiceToEntitiesComponentImport(entityName, entityClass, entityFileName, entityFolderName); diff --git a/lib/command/converter.ts b/lib/command/converter.ts index 223edbf8715b..381dca3bd49f 100644 --- a/lib/command/converter.ts +++ b/lib/command/converter.ts @@ -10,6 +10,7 @@ export const extractArgumentsFromConfigs = (configs: JHipsterConfigs | undefined name, { description: def.description, + scope: def.scope, ...def.argument, }, ]), diff --git a/lib/command/types.d.ts b/lib/command/types.d.ts index 09caa1389b70..21ad8358aba3 100644 --- a/lib/command/types.d.ts +++ b/lib/command/types.d.ts @@ -1,17 +1,19 @@ import type { ArgumentSpec, CliOptionSpec } from 'yeoman-generator'; -import type { RequireAtLeastOne, SetOptional, Simplify, TaggedUnion, TupleToUnion, ValueOf } from 'type-fest'; +import type { IsNever, RequireAtLeastOne, SetOptional, Simplify, TaggedUnion, TupleToUnion, ValueOf } from 'type-fest'; import type { JHipsterOptionDefinition } from '../jdl/core/types/parsing.js'; import type { DerivedPropertiesOf, DerivedPropertiesWithInferenceUnion } from '../types/utils/derived-properties.js'; import type { MergeUnion } from './support/merge-union.js'; -type ConfigScope = 'storage' | 'blueprint' | 'control' | 'generator'; +type CommandConfigScope = 'storage' | 'blueprint' | 'generator' | 'context' | 'none'; + +export type ConfigScope = CommandConfigScope | 'control'; type CliSpecType = CliOptionSpec['type']; export type JHispterChoices = readonly [...(string | { value: string; name: string })[]]; export type JHipsterOption = SetOptional & { readonly name?: string; - readonly scope?: 'storage' | 'blueprint' | 'control' | 'generator'; + readonly scope?: ConfigScope; readonly env?: string; readonly choices?: JHispterChoices; readonly commandName?: string; @@ -27,7 +29,7 @@ export type PromptSpec = { readonly validate?: any | ((any) => any); }; -type JHipsterArgumentConfig = SetOptional & { scope?: 'storage' | 'blueprint' | 'generator' }; +type JHipsterArgumentConfig = SetOptional & { scope?: CommandConfigScope }; export type ConfigSpec = { readonly description?: string; @@ -39,7 +41,10 @@ export type ConfigSpec = { | PromptSpec | ((gen: Generator & { jhipsterConfigWithDefaults: Record }, config: ConfigSpec) => PromptSpec); readonly jdl?: Omit; - readonly scope?: 'storage' | 'blueprint' | 'generator'; + readonly storage?: { + readonly type?: typeof Boolean | typeof String | typeof Number | typeof Array; + }; + readonly scope?: CommandConfigScope; /** * The callback receives the generator as input for 'generator' scope. * The callback receives jhipsterConfigWithDefaults as input for 'storage' (default) scope. @@ -64,7 +69,10 @@ export type JHipsterArguments = Record; export type JHipsterOptions = Record; -export type JHipsterConfigs = Record, 'argument' | 'cli' | 'prompt'>>; +export type JHipsterConfigs = Record< + string, + RequireAtLeastOne, 'argument' | 'cli' | 'prompt' | 'storage'> +>; export type JHipsterCommandDefinition = { readonly arguments?: JHipsterArguments; @@ -116,6 +124,13 @@ type FilteredConfigScope = ConfigScope | undefined; /** Add name to Options/Configs */ type TaggedParseableConfigUnion = D extends Record ? Simplify> : never; +/** Filter Options/Config by scope */ +type FilterScope = D extends Record<'scope', S> ? D : never; + +type FilterCommandScope = { + [K in keyof D as IsNever> extends true ? never : K]: D[K]; +}; + /** * @example * ```ts @@ -125,16 +140,14 @@ type TaggedParseableConfigUnion = D extends Record ? Simplify * ``` */ -type MergeConfigsOptions = Simplify< - D extends { configs: ParseableConfigs } - ? { [K in keyof D['configs']]: D['configs'][K] } - : never & D extends { options: ParseableConfigs } - ? { [K in keyof D['options']]: D['options'][K] } - : never +type MergeConfigsOptions = Simplify< + (D extends { configs: ParseableConfigs } ? { [K in keyof FilterCommandScope]: D['configs'][K] } : object) & + (D extends { options: ParseableConfigs } ? { [K in keyof FilterCommandScope]: D['options'][K] } : object) >; type GetType = C extends Record<'type', CliSpecType> ? C['type'] : C extends Record<'cli', Record<'type', CliSpecType>> ? C['cli']['type'] : undefined; + // eslint-disable-next-line @typescript-eslint/no-wrapper-object-types type WrapperToPrimitive = T extends Boolean ? boolean : T extends String ? string : T extends Number ? number : T; @@ -207,14 +220,6 @@ type PrepareConfigsWithType = Simplify<{ : never; }>; -/** Filter Options/Config by scope */ -type FilterScope = - D extends Record<'scope', S> ? D : D extends Record<'scope', ConfigScope> ? never : S extends undefined ? D : never; - -type FilterCommandScope = { - [K in keyof D as FilterScope extends D[K] ? K : never]: D[K]; -}; - /** Keep Options/Config filtered by choices */ type OnlyChoices = D extends { choices: JHispterChoices } ? (C extends true ? D : never) : C extends true ? never : D; @@ -224,32 +229,22 @@ type OnlyCofigsWithChoice = { }; export type ExportApplicationPropertiesFromCommand = - MergeConfigsOptions extends infer Merged + MergeConfigsOptions extends infer Merged ? Merged extends ParseableConfigs - ? FilterCommandScope extends infer F - ? F extends ParseableConfigs - ? // Add value inference to properties with choices - // ? PrepareConfigsWithType> & ValueOf>> - Simplify< - PrepareConfigsWithType> & - MergeUnion>>> - > - : never - : never + ? // Add value inference to properties with choices + // ? PrepareConfigsWithType> & ValueOf>> + Simplify< + PrepareConfigsWithType> & + MergeUnion>>> + > : never : never; type ExportScopedPropertiesFromCommand = - MergeConfigsOptions extends infer Merged - ? Merged extends ParseableConfigs - ? PrepareConfigsWithType> - : never - : never; + MergeConfigsOptions extends infer Merged ? (Merged extends ParseableConfigs ? PrepareConfigsWithType : never) : never; export type ExportStoragePropertiesFromCommand = ExportScopedPropertiesFromCommand; -export type ExportGeneratorPropertiesFromCommand = ExportScopedPropertiesFromCommand; +export type ExportGeneratorOptionsFromCommand = ExportScopedPropertiesFromCommand; export type ExportControlPropertiesFromCommand = ExportScopedPropertiesFromCommand; - -export type ExportBlueprintPropertiesFromCommand = ExportScopedPropertiesFromCommand; diff --git a/lib/command/types.spec.ts b/lib/command/types.spec.ts new file mode 100644 index 000000000000..f467099e5550 --- /dev/null +++ b/lib/command/types.spec.ts @@ -0,0 +1,111 @@ +import type { + ExportApplicationPropertiesFromCommand, + ExportGeneratorOptionsFromCommand, + ExportStoragePropertiesFromCommand, +} from './types.js'; + +type TestCommand = { + options: { + arrayOptionsType: { + type: ArrayConstructor; + scope: 'storage'; + }; + }; + configs: { + stringRootType: { + cli: { type: StringConstructor }; + scope: 'storage'; + }; + booleanCliType: { + cli: { type: BooleanConstructor }; + scope: 'storage'; + }; + none: { + scope: 'none'; + }; + choiceType: { + cli: { + type: StringConstructor; + }; + choices: ['foo', 'no']; + scope: 'storage'; + }; + }; +}; + +type StorageProperties = ExportStoragePropertiesFromCommand; + +const _stringRootType = { + stringRootType: 'foo', +} satisfies StorageProperties; + +const _stringRootTypeError = { + // @ts-expect-error invalid value + stringRootType: false, +} satisfies StorageProperties; + +const _booleanCliType = { + booleanCliType: false, +} satisfies StorageProperties; + +const _booleanCliTypeError = { + // @ts-expect-error invalid value + booleanCliType: 'false', +} satisfies StorageProperties; + +const _arrayCliType = { + arrayOptionsType: ['false'], +} satisfies StorageProperties; + +const _choiceType = { + choiceType: 'foo', +} satisfies StorageProperties; + +const _choiceTypeError = { + // @ts-expect-error invalid value + choiceType: 'bar', +} satisfies StorageProperties; + +type ApplicationProperties = ExportApplicationPropertiesFromCommand; + +const applicationChoiceType = { + choiceType: 'foo', + // @ts-expect-error missing fields +} satisfies ApplicationProperties; + +const applicationChoiceTypeNo = { + choiceTypeNo: false, + // @ts-expect-error missing fields +} satisfies ApplicationProperties; + +const applicationChoiceTypeFoo = { + choiceTypeFoo: true, + // @ts-expect-error missing fields +} satisfies ApplicationProperties; + +const applicationChoiceTypeAny = { + choiceTypeAny: true, + // @ts-expect-error missing fields +} satisfies ApplicationProperties; + +const _applicationChoiceComplete = { + ...applicationChoiceType, + ...applicationChoiceTypeNo, + ...applicationChoiceTypeFoo, + ...applicationChoiceTypeAny, +} satisfies ApplicationProperties; + +type ApplicationOptions = ExportGeneratorOptionsFromCommand; + +const _applicationOptions = { + arrayOptionsType: ['false'], + stringRootType: 'foo', + booleanCliType: false, + choiceType: 'foo', + none: 'foo', +} satisfies ApplicationOptions; + +const _applicationOptionsError = { + // @ts-expect-error unknow field + foo: 'bar', +} satisfies ApplicationOptions; diff --git a/lib/internal/config-def.ts b/lib/internal/config-def.ts index 282f49f30b80..3a42898547f4 100644 --- a/lib/internal/config-def.ts +++ b/lib/internal/config-def.ts @@ -2,6 +2,8 @@ import type { JHipsterConfigs } from '../../lib/command/index.js'; import type CoreGenerator from '../../generators/base-core/index.js'; import { upperFirstCamelCase } from '../utils/string.js'; +export function loadConfig(this: CoreGenerator, configsDef: JHipsterConfigs | undefined, data: { application: any }); +export function loadConfig(configsDef: JHipsterConfigs | undefined, data: { application: any; config?: any }); export function loadConfig( this: CoreGenerator | void, configsDef: JHipsterConfigs | undefined, @@ -13,18 +15,20 @@ export function loadConfig( if (value === undefined || value === null) { let source = config; if (!source) { - if (def.scope === 'generator') { - source = this; + if (def.scope === 'context') { + source = (this as CoreGenerator).context!; } else if (def.scope === 'blueprint') { source = (this as any).blueprintStorage.getAll(); - } else { - source = (this as any).jhipsterConfigWithDefaults; + } else if (def.scope === 'storage' || def.scope === undefined) { + source = (this as CoreGenerator).jhipsterConfigWithDefaults; } } - value = application[name] = source[name] ?? undefined; - if (value === undefined && def.default !== undefined) { - application[name] = typeof def.default === 'function' ? def.default.call(this, source) : def.default; + if (source) { + value = application[name] = source[name] ?? undefined; + if (value === undefined && def.default !== undefined) { + application[name] = typeof def.default === 'function' ? def.default.call(this, source) : def.default; + } } } } @@ -34,7 +38,7 @@ export function loadConfig( export const loadDerivedConfig = (configsDef: JHipsterConfigs | undefined, { application }) => { if (configsDef) { for (const [name, def] of Object.entries(configsDef)) { - if (def.choices) { + if ((def.scope === undefined || ['storage', 'blueprint', 'context'].includes(def.scope)) && def.choices) { const configVal = application[name]; for (const choice of def.choices) { const choiceVal = typeof choice === 'string' ? choice : choice.value; diff --git a/lib/types/application/options.d.ts b/lib/types/application/options.d.ts new file mode 100644 index 000000000000..56475beacb92 --- /dev/null +++ b/lib/types/application/options.d.ts @@ -0,0 +1,17 @@ +/* eslint-disable @typescript-eslint/consistent-type-imports */ +import type { Simplify } from 'type-fest'; +import type { ExportGeneratorOptionsFromCommand } from '../../command/types.js'; + +export type ApplicationOptions = Simplify< + ExportGeneratorOptionsFromCommand & + ExportGeneratorOptionsFromCommand & + ExportGeneratorOptionsFromCommand & + ExportGeneratorOptionsFromCommand & + ExportGeneratorOptionsFromCommand & + ExportGeneratorOptionsFromCommand & + ExportGeneratorOptionsFromCommand & + ExportGeneratorOptionsFromCommand & + ExportGeneratorOptionsFromCommand & + ExportGeneratorOptionsFromCommand & + ExportGeneratorOptionsFromCommand +>; diff --git a/lib/types/application/yo-rc.d.ts b/lib/types/application/yo-rc.d.ts index 0c20dfe7e281..b7d1df3e5a5a 100644 --- a/lib/types/application/yo-rc.d.ts +++ b/lib/types/application/yo-rc.d.ts @@ -1,11 +1,24 @@ /* eslint-disable @typescript-eslint/consistent-type-imports */ -import { Simplify } from 'type-fest'; +import type { Simplify } from 'type-fest'; import type { ExportStoragePropertiesFromCommand } from '../../command/types.js'; export type ApplicationConfiguration = Simplify< { jhipsterVersion: string; baseName: string; - } & ExportStoragePropertiesFromCommand & - ExportStoragePropertiesFromCommand + creationTimestamp: number; + lastLiquibaseTimestamp?: number; + blueprints?: { name: string }[]; + testFrameworks?: string[]; + } & ExportStoragePropertiesFromCommand & + ExportStoragePropertiesFromCommand & + ExportStoragePropertiesFromCommand & + ExportStoragePropertiesFromCommand & + ExportStoragePropertiesFromCommand & + ExportStoragePropertiesFromCommand & + ExportStoragePropertiesFromCommand & + ExportStoragePropertiesFromCommand & + ExportStoragePropertiesFromCommand & + ExportStoragePropertiesFromCommand & + ExportStoragePropertiesFromCommand >; diff --git a/test/needle-api/needle-base.spec.ts b/test/needle-api/needle-base.spec.ts index d77ec239ca83..300d23592415 100644 --- a/test/needle-api/needle-base.spec.ts +++ b/test/needle-api/needle-base.spec.ts @@ -4,6 +4,7 @@ import NeedleApiBase from '../../generators/needle-base.js'; describe('needle-api - base', () => { let needleApiBase; before(() => { + // @ts-expect-error testing purposes needleApiBase = new NeedleApiBase(); }); describe('generate a file model without path', () => { diff --git a/test/needle-api/needle-client-angular-generator.spec.ts b/test/needle-api/needle-client-angular-generator.spec.ts index b138cde11545..06181dc9ea6d 100644 --- a/test/needle-api/needle-client-angular-generator.spec.ts +++ b/test/needle-api/needle-client-angular-generator.spec.ts @@ -16,7 +16,7 @@ const mockAngularBlueprintSubGen = class extends AngularGenerator { addToMenuStep() { this.addElementToAdminMenu('routerName2', 'iconName2', true); }, - addToModuleStep({ application, source }) { + addToModuleStep({ source, application }) { source.addEntitiesToClient({ application, entities: [ @@ -47,7 +47,7 @@ describe('needle API Angular angular generator : JHipster with blueprint', () => skipServer: true, }) .withOptions({ - blueprint: 'myblueprint2', + blueprint: ['myblueprint2'], }) .withGenerators([[mockAngularBlueprintSubGen, { namespace: 'jhipster-myblueprint2:angular' }]]); }); @@ -99,7 +99,8 @@ describe('needle API Angular angular generator : JHipster with blueprint', () => .create('jhipster:angular') .withGenerators([[mockAngularBlueprintSubGen, { namespace: 'jhipster-myblueprint2:angular' }]]) .withOptions({ - blueprint: 'myblueprint2', + // @ts-expect-error TODO + blueprint: ['myblueprint2'], force: false, }); }); diff --git a/test/needle-api/needle-client-angular.spec.ts b/test/needle-api/needle-client-angular.spec.ts index 269815dd2468..5665fb00189f 100644 --- a/test/needle-api/needle-client-angular.spec.ts +++ b/test/needle-api/needle-client-angular.spec.ts @@ -1,13 +1,10 @@ import { before, describe, it } from 'esmocha'; import { getGenerator, basicHelpers as helpers, result as runResult } from '../../testing/index.js'; -import { clientFrameworkTypes } from '../../lib/jhipster/index.js'; import { CLIENT_MAIN_SRC_DIR } from '../../generators/generator-constants.js'; import BaseApplicationGenerator from '../../generators/base-application/index.js'; import AngularGenerator from '../../generators/angular/index.js'; -const { ANGULAR } = clientFrameworkTypes; - const mockBlueprintSubGen = class extends AngularGenerator { constructor(args, opts, features) { super(args, opts, features); @@ -15,7 +12,7 @@ const mockBlueprintSubGen = class extends AngularGenerator { } get [BaseApplicationGenerator.POST_WRITING]() { - return { + return this.asPostWritingTaskGroup({ addCssStylesProperty() { this.addMainSCSSStyle('@import style_without_comment;'); this.addMainSCSSStyle('@import style;', 'my comment'); @@ -23,13 +20,13 @@ const mockBlueprintSubGen = class extends AngularGenerator { this.addVendorSCSSStyle('@import style_without_comment;'); }, addToMenuStep() { - this.addElementToMenu('routerName1', 'iconName1', true, ANGULAR); + this.addElementToMenu('routerName1', 'iconName1', true); }, addToModuleStep() { - this.addAngularModule('appName', 'angularName', 'folderName', 'fileName', true, ANGULAR); + this.addAngularModule('appName', 'angularName', 'folderName', 'fileName', true); this.addAdminRoute('entity-audit', './entity-audit/entity-audit.module', 'EntityAuditModule', 'entityAudit.home.title'); }, - }; + }); } }; @@ -41,7 +38,7 @@ describe('needle API Angular: JHipster angular generator with blueprint', () => skipServer: true, }) .withOptions({ - blueprint: 'myblueprint', + blueprint: ['myblueprint'], }) .withGenerators([[mockBlueprintSubGen, { namespace: 'jhipster-myblueprint:angular' }]]) .run(); diff --git a/test/needle-api/needle-client-react-generator.spec.ts b/test/needle-api/needle-client-react-generator.spec.ts index c33c5b1b0e12..da4911379477 100644 --- a/test/needle-api/needle-client-react-generator.spec.ts +++ b/test/needle-api/needle-client-react-generator.spec.ts @@ -19,9 +19,9 @@ const mockReactBlueprintSubGen: any = class extends ReactGenerator { } get [BaseApplicationGenerator.POST_WRITING]() { - const customPhaseSteps = { + return this.asPostWritingTaskGroup({ addEntityToMenuStep() { - this.addEntityToMenu('routerName', false, false); + this.addEntityToMenu('routerName', false); }, addEntityToModuleStep({ application }) { const { applicationTypeMicroservice, clientSrcDir } = application; @@ -30,8 +30,7 @@ const mockReactBlueprintSubGen: any = class extends ReactGenerator { clientSrcDir, }); }, - }; - return { ...customPhaseSteps }; + }); } }; @@ -45,7 +44,7 @@ describe('needle API React: JHipster client generator with blueprint', () => { build: 'maven', auth: 'jwt', db: 'mysql', - blueprint: 'myblueprint', + blueprint: ['myblueprint'], ignoreNeedlesError: true, }) .withGenerators([[mockReactBlueprintSubGen, { namespace: 'jhipster-myblueprint:react' }]]) diff --git a/test/needle-api/needle-client-react.spec.ts b/test/needle-api/needle-client-react.spec.ts index 0237c440d4a8..04a1a2ea4ad6 100644 --- a/test/needle-api/needle-client-react.spec.ts +++ b/test/needle-api/needle-client-react.spec.ts @@ -19,14 +19,13 @@ const mockBlueprintSubGen: any = class extends ReactGenerator { } get [BaseApplicationGenerator.POST_WRITING]() { - const customPhaseSteps = { + return this.asPostWritingTaskGroup({ addAppCssStep() { // please change this to public API when it will be available see https://github.com/jhipster/generator-jhipster/issues/9234 this.addAppSCSSStyle('@import without-comment'); this.addAppSCSSStyle('@import with-comment', 'my comment'); }, - }; - return { ...customPhaseSteps }; + }); } }; @@ -38,7 +37,7 @@ describe('needle API React: JHipster react generator with blueprint', () => { build: 'maven', auth: 'jwt', db: 'mysql', - blueprint: 'myblueprint', + blueprint: ['myblueprint'], ignoreNeedlesError: true, }) .withGenerators([[mockBlueprintSubGen, { namespace: 'jhipster-myblueprint:react' }]]) diff --git a/test/needle-api/needle-client-vue-generator.spec.ts b/test/needle-api/needle-client-vue-generator.spec.ts index 9bf4f267ef7d..375cb41a0b41 100644 --- a/test/needle-api/needle-client-vue-generator.spec.ts +++ b/test/needle-api/needle-client-vue-generator.spec.ts @@ -18,7 +18,7 @@ const mockBlueprintSubGen: any = class extends VueGenerator { } get [BaseApplicationGenerator.POST_WRITING]() { - const customPhaseSteps = { + return this.asPostWritingTaskGroup({ addCustomMethods() { this.addEntityToMenu('routerName', false); }, @@ -33,8 +33,7 @@ const mockBlueprintSubGen: any = class extends VueGenerator { 'microserviceName', ); }, - }; - return { ...customPhaseSteps }; + }); } }; @@ -46,7 +45,7 @@ describe('needle API Vue: JHipster client generator with blueprint', () => { build: 'maven', auth: 'jwt', db: 'mysql', - blueprint: 'myblueprint', + blueprint: ['myblueprint'], }) .withGenerators([[mockBlueprintSubGen, { namespace: 'jhipster-myblueprint:vue' }]]) .withAnswers({ diff --git a/test/needle-api/needle-client-vue.spec.ts b/test/needle-api/needle-client-vue.spec.ts index fcb5c3ce8b1c..7f2b84c60a0e 100644 --- a/test/needle-api/needle-client-vue.spec.ts +++ b/test/needle-api/needle-client-vue.spec.ts @@ -25,7 +25,7 @@ describe('needle API Vue: JHipster client generator with blueprint', () => { build: 'maven', auth: 'jwt', db: 'mysql', - blueprint: 'myblueprint', + blueprint: ['myblueprint'], }) .withMockedGenerators(['jhipster:languages']) .withGenerators([[mockBlueprintSubGen, { namespace: 'jhipster-myblueprint:client' }]]) diff --git a/test/support/tests.js b/test/support/tests.js index 1856ae4bbc79..f633d5141b09 100644 --- a/test/support/tests.js +++ b/test/support/tests.js @@ -277,7 +277,7 @@ export const testBlueprintSupport = (generatorName, options = {}) => { .withMockedJHipsterGenerators({ filter: () => true }) .withMockedGenerators([`jhipster-foo:${generatorName}`]) .withJHipsterConfig() - .withOptions({ blueprint: 'foo' }) + .withOptions({ blueprint: ['foo'] }) .onGenerator(generator => { spy = addSpies(generator); }); @@ -327,7 +327,7 @@ export const testBlueprintSupport = (generatorName, options = {}) => { : undefined, ) .commitFiles() - .withOptions({ blueprint: 'foo-sbs' }) + .withOptions({ blueprint: ['foo-sbs'] }) .onGenerator(generator => { spy = addSpies(generator); }); diff --git a/testing/helpers.ts b/testing/helpers.ts index b2c69e3361da..90331d922b8b 100644 --- a/testing/helpers.ts +++ b/testing/helpers.ts @@ -6,6 +6,7 @@ import { RunContext, YeomanTest, result } from 'yeoman-test'; import { globSync } from 'glob'; import type { BaseEnvironmentOptions, GetGeneratorConstructor, BaseGenerator as YeomanGenerator } from '@yeoman/types'; +import type { EmptyObject } from 'type-fest'; import EnvironmentBuilder from '../cli/environment-builder.mjs'; import { JHIPSTER_CONFIG_DIR } from '../generators/generator-constants.js'; import { GENERATOR_WORKSPACES } from '../generators/generator-list.js'; @@ -15,6 +16,7 @@ import type { JHipsterGeneratorOptions } from '../generators/base/api.js'; import { getPackageRoot, isDistFolder } from '../lib/index.js'; import type { JSONEntity } from '../lib/jdl/core/types/json-config.js'; import type CoreGenerator from '../generators/base-core/generator.js'; +import type { ApplicationConfiguration } from '../lib/types/application/yo-rc.js'; import getGenerator from './get-generator.js'; type BaseEntity = { name: string } & JSONEntity; @@ -138,7 +140,10 @@ class JHipsterRunContext extends RunContext { return super.withOptions(options as any); } - withJHipsterConfig(configuration?: Record, entities?: BaseEntity[]): this { + withJHipsterConfig( + configuration?: Readonly>, + entities?: BaseEntity[], + ): this { return this.withFiles( createFiles('', { baseName: 'jhipster', creationTimestamp: parseCreationTimestamp('2020-01-01'), ...configuration }, entities), ); diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json deleted file mode 100644 index c85b9bbac31f..000000000000 --- a/tsconfig.eslint.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "exclude": [], - "extends": "./tsconfig.spec.json", - "compilerOptions": { - "noEmit": false, - "types": [] - } -} diff --git a/tsconfig.spec.json b/tsconfig.spec.json index 654337ac9f36..c8bd752d052f 100644 --- a/tsconfig.spec.json +++ b/tsconfig.spec.json @@ -1,12 +1,6 @@ { "include": ["cli/**/*", "generators/**/*", "jdl/**/*", "lib/**/*", "testing/**/*", "test/**/*", ".blueprint/**/*"], - "exclude": [ - "generators/base-application/generator.spec.*", - "generators/base-core/generator-core.spec.*", - "generators/base/**/*.spec.*", - "generators/server/support/needles.spec.ts", - "test/needle-api/**" - ], + "exclude": [], "extends": "./tsconfig.json", "compilerOptions": { "noEmit": true,