Skip to content

Commit

Permalink
Internal improvements (#26526)
Browse files Browse the repository at this point in the history
* JHipsterConfigs requires a cli, argument or prompt description otherwise it's a noop

* make configs and options optional in command

* fix destinationFile type

* allow withMockedJHipsterGenerators exceptList without 'jhipster:' prefix

* add cleanupFiles support to conditional files

* fix mergeDestinationYaml with arrays

* Update generators/spring-cloud/generators/gateway/command.ts
  • Loading branch information
mshima authored Jun 24, 2024
1 parent 91aa902 commit 9c58809
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 13 deletions.
9 changes: 7 additions & 2 deletions cli/program.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,13 @@ const buildAllDependencies = async (generatorNames, { env, blueprintNamespaces }
const addCommandGeneratorOptions = async (command, generatorMeta, { root, blueprintOptionDescription, info } = {}) => {
const generatorModule = await generatorMeta.importModule();
if (generatorModule.command) {
command.addJHipsterOptions(generatorModule.command.options, blueprintOptionDescription);
command.addJHipsterConfigs(generatorModule.command.configs, blueprintOptionDescription);
const { options, configs } = generatorModule.command;
if (options) {
command.addJHipsterOptions(options, blueprintOptionDescription);
}
if (configs) {
command.addJHipsterConfigs(configs, blueprintOptionDescription);
}
}
try {
if (root || !generatorModule.command || generatorModule.command.loadGeneratorOptions) {
Expand Down
9 changes: 7 additions & 2 deletions generators/base-core/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { requireNamespace } from '@yeoman/namespace';
import { GeneratorMeta } from '@yeoman/types';
import chalk from 'chalk';
import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
import { kebabCase, snakeCase, merge, get, set, defaults } from 'lodash-es';
import { kebabCase, snakeCase, merge, get, set, defaults, mergeWith } from 'lodash-es';
import { simpleGit } from 'simple-git';
import type { CopyOptions } from 'mem-fs-editor';
import type { Data as TemplateData, Options as TemplateOptions } from 'ejs';
Expand Down Expand Up @@ -96,6 +96,8 @@ const relativeDir = (from: string, to: string) => {
return rel ? `${rel}/` : '';
};

const deepMerge = (source1: any, source2: any) => mergeWith({}, source1, source2, (a, b) => (Array.isArray(a) ? a.concat(b) : undefined));

/**
* This is the base class for a generator for every generator.
*/
Expand Down Expand Up @@ -1123,7 +1125,10 @@ templates: ${JSON.stringify(existingTemplates, null, 2)}`;
}
return true;
});
return headerComments.join('\n').concat('\n', stringifyYaml(merge(parseYaml(content), value)));

const mergedContent = stringifyYaml(deepMerge(parseYaml(content), value));
const header = headerComments.length > 0 ? headerComments.join('\n').concat('\n') : '';
return `${header}${mergedContent}`;
});
}

Expand Down
12 changes: 6 additions & 6 deletions generators/base/api.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { BaseOptions, BaseFeatures, ArgumentSpec, CliOptionSpec } from 'yeoman-generator';
import type { SetOptional } from 'type-fest';
import type { RequireAtLeastOne, SetOptional } from 'type-fest';
import type CoreGenerator from '../base-core/index.js';

export type ApplicationWithConfig = {
Expand Down Expand Up @@ -114,13 +114,13 @@ export type WriteFileTemplate<Generator = CoreGenerator, DataType = any> =
| ((this: Generator, data: DataType, filePath: string) => string)
| {
/** source file */
sourceFile?: ((this: Generator, data: DataType) => string) | string;
sourceFile?: string | ((this: Generator, data: DataType) => string);
/** destination file */
destinationFile?: (this: Generator, destinationFile: DataType) => string | string;
destinationFile?: string | ((this: Generator, destinationFile: DataType) => string);
/** @deprecated, use sourceFile instead */
file?: ((this: Generator, data: DataType) => string) | string;
file?: string | ((this: Generator, data: DataType) => string);
/** @deprecated, use destinationFile instead */
renameTo?: ((this: Generator, data: DataType, filePath: string) => string) | string;
renameTo?: string | ((this: Generator, data: DataType, filePath: string) => string);
/** transforms (files processing) to be applied */
transform?: boolean | (() => string)[];
/** binary files skips ejs render, ejs extension and file transform */
Expand Down Expand Up @@ -232,7 +232,7 @@ export type JHipsterArguments = Record<string, JHipsterArgumentConfig>;

export type JHipsterOptions = Record<string, JHipsterOption>;

export type JHipsterConfigs = Record<string, ConfigSpec>;
export type JHipsterConfigs = Record<string, RequireAtLeastOne<ConfigSpec, 'argument' | 'cli' | 'prompt'>>;

export type JHipsterCommandDefinition = {
arguments?: JHipsterArguments;
Expand Down
15 changes: 13 additions & 2 deletions generators/base/shared-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,21 @@ export default class SharedData<ApplicationType extends BaseApplication = BaseAp
jhipsterOldVersion,
removeFiles,
customizeRemoveFiles: [],
cleanupFiles: async (cleanup: Record<string, string[]>) => {
cleanupFiles: async (cleanup: Record<string, Array<string | [boolean, ...string[]]>>) => {
await Promise.all(
Object.entries(cleanup).map(async ([version, files]) => {
await removeFiles({ removedInVersion: version }, ...files);
const stringFiles: string[] = [];
for (const file of files) {
if (Array.isArray(file)) {
const [condition, ...fileParts] = file;
if (condition) {
stringFiles.push(join(...fileParts));
}
} else {
stringFiles.push(file);
}
}
await removeFiles({ removedInVersion: version }, ...stringFiles);
}),
);
},
Expand Down
7 changes: 6 additions & 1 deletion generators/base/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,10 @@ export type Control = {
filterEntitiesAndPropertiesForClient?: (entity: Entity[]) => Entity[];
customizeRemoveFiles: Array<(file: string) => string | undefined>;
removeFiles: (options: { removedInVersion: string } | string, ...files: string[]) => Promise<void>;
cleanupFiles: (cleanup: Record<string, string[]>) => Promise<void>;
/**
* Cleanup files conditionally based on version and condition.
* @example
* cleanupFiles({ '6.0.0': ['file1', 'file2', [application.shouldRemove, 'file3']] })
*/
cleanupFiles: (cleanup: Record<string, Array<string | [boolean, ...string[]]>>) => Promise<void>;
};
5 changes: 5 additions & 0 deletions generators/spring-cloud/generators/gateway/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ import type { JHipsterCommandDefinition } from '../../../base/api.js';
const command: JHipsterCommandDefinition = {
configs: {
routes: {
description: 'Manually configured gateway routes',
cli: {
type: String,
hide: true,
},
scope: 'storage',
},
},
Expand Down
9 changes: 9 additions & 0 deletions testing/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,16 @@ class JHipsterRunContext extends RunContext<GeneratorTestType> {
return this.withSharedData({ sharedApplication: this.sharedApplication });
}

/**
* Mock every built-in generators except the ones in the exceptList and bootstrap-* generators.
* Note: Boostrap generator is mocked by default.
* @example
* withMockedJHipsterGenerators(['jhipster:bootstrap'])
* @example
* withMockedJHipsterGenerators(['bootstrap', 'server'])
*/
withMockedJHipsterGenerators(exceptList: string[] = []): this {
exceptList = exceptList.map(gen => (gen.startsWith('jhipster:') ? gen : `jhipster:${gen}`));
return this.withMockedGenerators(mockedGenerators.filter(gen => !exceptList.includes(gen) && (this as any).Generator !== gen));
}

Expand Down

0 comments on commit 9c58809

Please sign in to comment.