From 790909cc1aa83127d273468de90d189678418bc4 Mon Sep 17 00:00:00 2001 From: Marcelo Shima Date: Mon, 18 Mar 2024 18:01:16 -0300 Subject: [PATCH 1/2] add JavaDependencyVersion and addJavaDefinition abstraction --- generators/gradle/generator.ts | 7 ++- generators/gradle/internal/needles.ts | 6 +- generators/gradle/types.d.ts | 5 +- generators/java/generator.ts | 60 ++++++++++++------- generators/java/support/artifacts.ts | 2 +- generators/java/types.d.ts | 19 +++++- generators/spring-boot/generator.ts | 2 +- generators/spring-cache/generator.ts | 4 +- .../spring-cache/internal/dependencies.ts | 6 +- .../internal/dependencies.ts | 4 +- 10 files changed, 75 insertions(+), 40 deletions(-) diff --git a/generators/gradle/generator.ts b/generators/gradle/generator.ts index 268601d19a91..97b9898a172d 100644 --- a/generators/gradle/generator.ts +++ b/generators/gradle/generator.ts @@ -34,7 +34,7 @@ import { addGradlePluginManagementCallback, addGradlePropertyCallback, addGradleBuildSrcDependencyCallback, - addGradleDependencyCatalogVersionCallback, + addGradleDependenciesCatalogVersionCallback, addGradleBuildSrcDependencyCatalogVersionCallback, addGradleDependencyCatalogLibrariesCallback, addGradleDependencyCatalogPluginsCallback, @@ -88,8 +88,9 @@ export default class GradleGenerator extends BaseApplicationGenerator { source.addGradleProperty = property => this.editFile('gradle.properties', addGradlePropertyCallback(property)); source.addGradleBuildSrcDependency = dependency => this.editFile(`${GRADLE_BUILD_SRC_DIR}/build.gradle`, addGradleBuildSrcDependencyCallback(dependency)); - source.addGradleDependencyCatalogVersion = version => - this.editFile('gradle/libs.versions.toml', addGradleDependencyCatalogVersionCallback(version)); + source.addGradleDependencyCatalogVersions = versions => + this.editFile('gradle/libs.versions.toml', addGradleDependenciesCatalogVersionCallback(versions)); + source.addGradleDependencyCatalogVersion = version => source.addGradleDependencyCatalogVersions!([version]); source.addGradleDependencyCatalogLibraries = (libs, { gradleFile = 'build.gradle' } = {}) => { libs = [...libs].sort((a, b) => a.libraryName.localeCompare(b.libraryName)); this.editFile('gradle/libs.versions.toml', addGradleDependencyCatalogLibrariesCallback(libs)); diff --git a/generators/gradle/internal/needles.ts b/generators/gradle/internal/needles.ts index d1a5f6f2a1ff..1d0f2a14d1cf 100644 --- a/generators/gradle/internal/needles.ts +++ b/generators/gradle/internal/needles.ts @@ -28,7 +28,7 @@ import type { GradleTomlPlugin, } from '../types.js'; -const tomlItemToString = (item: Record) => +const tomlItemToString = (item: Record) => `{ ${Object.entries(item) .filter(([_key, value]) => value !== undefined) .map(([key, value]) => `${key} = "${value}"`) @@ -84,10 +84,10 @@ export const addGradleBuildSrcDependencyCallback = ({ groupId, artifactId, versi contentToAdd: `${scope} "${groupId}:${artifactId}${version ? `:${version}` : ''}"`, }); -export const addGradleDependencyCatalogVersionCallback = ({ name, version }: GradleTomlVersion) => +export const addGradleDependenciesCatalogVersionCallback = (versions: GradleTomlVersion[]) => createNeedleCallback({ needle: 'gradle-dependency-catalog-version', - contentToAdd: `${name} = "${version}"`, + contentToAdd: versions.map(({ name, version }) => `${name} = "${version}"`), }); export const addGradleDependencyCatalogLibrariesCallback = (libraries: GradleLibrary[]) => diff --git a/generators/gradle/types.d.ts b/generators/gradle/types.d.ts index 1c70ce078e74..299024b53499 100644 --- a/generators/gradle/types.d.ts +++ b/generators/gradle/types.d.ts @@ -1,3 +1,5 @@ +import { RequireOneOrNone } from 'type-fest'; + export type GradleScript = { script: string }; export type GradleDependency = { groupId: string; artifactId: string; version?: string; scope: string; classifier?: string }; @@ -10,7 +12,7 @@ export type GradleRepository = { url: string; username?: string; password?: stri export type GradleTomlVersion = { name: string; version?: string }; -export type GradleTomlAnyItemVersion = { version: string } | { ['version.ref']: string }; +export type GradleTomlAnyItemVersion = RequireOneOrNone<{ version: string; 'version.ref': string }, 'version' | 'version.ref'>; export type GradleTomlLibraryId = { module: string } | { group: string; name: string }; @@ -36,6 +38,7 @@ export type GradleSourceType = { addGradleMavenRepository?(repository: GradleRepository): void; addGradleBuildSrcDependency?(dependency: GradleDependency): void; addGradleDependencyCatalogVersion?(catalogVersion: GradleTomlVersion): void; + addGradleDependencyCatalogVersions?(catalogVersion: GradleTomlVersion[]): void; addGradleDependencyCatalogLibrary?(catalogVersion: GradleLibrary, options?: GradleNeedleOptions): void; addGradleDependencyCatalogLibraries?(catalogVersion: GradleLibrary[], options?: GradleNeedleOptions): void; addGradleDependencyCatalogPlugin?(catalogVersion: GradleTomlPlugin): void; diff --git a/generators/java/generator.ts b/generators/java/generator.ts index f373d59cce8b..9c6f9b2e6354 100644 --- a/generators/java/generator.ts +++ b/generators/java/generator.ts @@ -27,7 +27,7 @@ import { generatedAnnotationTransform, checkJava, isReservedJavaKeyword, - mavenScopeToGradleScope, + javaScopeToGradleScope, } from './support/index.js'; import command from './command.js'; import { JAVA_COMPATIBLE_VERSIONS } from '../generator-constants.js'; @@ -36,7 +36,8 @@ import { entityServerFiles, enumFiles } from './entity-files.js'; import { getEnumInfo } from '../base-application/support/index.js'; import { mutateData } from '../base/support/index.js'; import { javaBeanCase } from '../server/support/index.js'; -import type { JavaArtifact } from './types.js'; +import type { JavaDependency } from './types.js'; +import type { MavenDependency } from '../maven/types.js'; export default class JavaGenerator extends BaseApplicationGenerator { packageInfoFile!: boolean; @@ -97,50 +98,65 @@ export default class JavaGenerator extends BaseApplicationGenerator { const annotationProcessors = dependencies.filter(dep => dep.scope === 'annotationProcessor'); const importDependencies = dependencies.filter(dep => dep.scope === 'import'); const commonDependencies = dependencies.filter(dep => !['annotationProcessor', 'import'].includes(dep.scope!)); - const convertVersionToProp = ({ version, artifactId, ...artifact }: JavaArtifact) => ({ - ...artifact, - artifactId, - version: version ? `\${${artifactId}.version}` : undefined, - }); + const convertVersionToRef = ({ version, versionRef, ...artifact }: JavaDependency): MavenDependency => + version || versionRef ? { ...artifact, version: `\${${versionRef ?? artifact.artifactId}.version}` } : artifact; + const removeScope = ({ scope: _scope, ...artifact }: MavenDependency) => artifact; source.addMavenDefinition?.({ properties: dependencies .filter(dep => dep.version) .map(({ artifactId, version }) => ({ property: `${artifactId}.version`, value: version })), dependencies: [ - ...commonDependencies.map(convertVersionToProp), + ...commonDependencies.map(convertVersionToRef), // Add a provided scope for annotation processors so that version is not required in annotationProcessor dependencies - ...annotationProcessors - .filter(dep => !dep.version) - .map(({ scope: _scope, ...artifact }) => ({ ...artifact, scope: 'provided' })), + ...annotationProcessors.filter(dep => !dep.version).map(artifact => ({ ...artifact, scope: 'provided' })), ], - dependencyManagement: importDependencies.map(convertVersionToProp), - annotationProcessors: annotationProcessors.map(convertVersionToProp).map(({ scope: _scope, ...artifact }) => artifact), + dependencyManagement: importDependencies.map(convertVersionToRef), + annotationProcessors: annotationProcessors.map(convertVersionToRef).map(removeScope), }); } if (application.buildToolGradle) { source.addGradleDependencies?.( dependencies - .filter(dep => !dep.version) + .filter(dep => !dep.version && !dep.versionRef) .map(({ scope, type, ...artifact }) => ({ ...artifact, - scope: mavenScopeToGradleScope({ scope, type }), + scope: javaScopeToGradleScope({ scope, type }), })), options, ); source.addGradleDependencyCatalogLibraries?.( dependencies - .filter(dep => dep.version) - .map(({ scope, type, groupId, artifactId, version }) => ({ - libraryName: artifactId, - module: `${groupId}:${artifactId}`, - version: version!, - scope: mavenScopeToGradleScope({ scope, type }), - })), + .filter(dep => dep.version || dep.versionRef) + .map(({ scope, type, groupId, artifactId, version, versionRef }) => { + const library = { + libraryName: artifactId, + module: `${groupId}:${artifactId}`, + scope: javaScopeToGradleScope({ scope, type }), + }; + return version ? { ...library, version } : { ...library, 'version.ref': versionRef! }; + }), ); } }; + + source.addJavaDefinition = (definition, options) => { + const { dependencies, versions } = definition; + if (dependencies) { + source.addJavaDependencies!(dependencies, options); + } + if (versions) { + if (application.buildToolMaven) { + source.addMavenDefinition!({ + properties: versions.map(({ name, version }) => ({ property: `${name}.version`, value: version })), + }); + } + if (application.buildToolGradle) { + source.addGradleDependencyCatalogVersions?.(versions); + } + } + }; }, }); } diff --git a/generators/java/support/artifacts.ts b/generators/java/support/artifacts.ts index e020c7d97572..2abaf30dccc5 100644 --- a/generators/java/support/artifacts.ts +++ b/generators/java/support/artifacts.ts @@ -1,6 +1,6 @@ import { JavaArtifactType } from '../types.js'; -export const mavenScopeToGradleScope = (artifactType: JavaArtifactType): string => { +export const javaScopeToGradleScope = (artifactType: JavaArtifactType): string => { const { scope = 'compile', type = 'jar' } = artifactType; if (type === 'pom') { if (scope === 'import') { diff --git a/generators/java/types.d.ts b/generators/java/types.d.ts index 673ae8367795..f9b96a7428f0 100644 --- a/generators/java/types.d.ts +++ b/generators/java/types.d.ts @@ -1,6 +1,12 @@ +import { RequireOneOrNone } from 'type-fest'; import { BaseApplication } from '../base-application/types.js'; import { GradleNeedleOptions } from '../gradle/types.js'; +export type JavaDependencyVersion = { + name: string; + version: string; +}; + export type JavaArtifactType = { type?: 'jar' | 'pom'; scope?: 'compile' | 'provided' | 'runtime' | 'test' | 'system' | 'import' | 'annotationProcessor'; @@ -9,10 +15,18 @@ export type JavaArtifactType = { export type JavaArtifact = { groupId: string; artifactId: string; - version?: string; classifier?: string; } & JavaArtifactType; +export type JavaArtifactVersion = RequireOneOrNone<{ version: string; versionRef: string }, 'version' | 'versionRef'>; + +export type JavaDependency = JavaArtifact & JavaArtifactVersion; + +export type JavaDefinition = { + versions: JavaDependencyVersion[]; + dependencies: JavaDependency[]; +}; + export type JavaNeedleOptions = GradleNeedleOptions; export type JavaApplication = BaseApplication & { @@ -42,5 +56,6 @@ export type JavaApplication = BaseApplication & { }; export type JavaSourceType = { - addJavaDependencies?(dependency: JavaArtifact[], options?: JavaNeedleOptions): void; + addJavaDefinition?(definition: JavaDefinition, options?: JavaNeedleOptions): void; + addJavaDependencies?(dependency: JavaDependency[], options?: JavaNeedleOptions): void; }; diff --git a/generators/spring-boot/generator.ts b/generators/spring-boot/generator.ts index 26f5b543ffa0..b72ce4cee4d6 100644 --- a/generators/spring-boot/generator.ts +++ b/generators/spring-boot/generator.ts @@ -405,7 +405,7 @@ public void set${javaBeanCase(propertyName)}(${propertyType} ${propertyName}) { { groupId: 'tech.jhipster', artifactId: 'jhipster-dependencies', - version: application.jhipsterDependenciesVersion, + version: application.jhipsterDependenciesVersion!, type: 'pom', scope: 'import', }, diff --git a/generators/spring-cache/generator.ts b/generators/spring-cache/generator.ts index f00c0269cadd..269276ae6575 100644 --- a/generators/spring-cache/generator.ts +++ b/generators/spring-cache/generator.ts @@ -22,7 +22,7 @@ import writeTask from './files.js'; import cleanupTask from './cleanup.js'; import { createNeedleCallback } from '../base/support/needles.js'; import { getCacheProviderMavenDefinition } from './internal/dependencies.js'; -import { JavaArtifact } from '../java/types.js'; +import { JavaDependency } from '../java/types.js'; export default class SpringCacheGenerator extends BaseApplicationGenerator { async beforeQueue() { @@ -135,7 +135,7 @@ export default class SpringCacheGenerator extends BaseApplicationGenerator { const { javaDependencies } = application; const { cacheProvider, enableHibernateCache } = application as any; - const dependencies: JavaArtifact[] = [{ groupId: 'org.springframework.boot', artifactId: 'spring-boot-starter-cache' }]; + const dependencies: JavaDependency[] = [{ groupId: 'org.springframework.boot', artifactId: 'spring-boot-starter-cache' }]; const definition = getCacheProviderMavenDefinition(cacheProvider, javaDependencies); dependencies.push(...definition.base.dependencies); if (enableHibernateCache && definition.hibernateCache) { diff --git a/generators/spring-cache/internal/dependencies.ts b/generators/spring-cache/internal/dependencies.ts index 1dc1c49f3661..7bceef70d674 100644 --- a/generators/spring-cache/internal/dependencies.ts +++ b/generators/spring-cache/internal/dependencies.ts @@ -17,7 +17,7 @@ * limitations under the License. */ -import { JavaArtifact } from '../../java/types.js'; +import { JavaDependency } from '../../java/types.js'; const javaxCacheApi = { groupId: 'javax.cache', @@ -29,8 +29,8 @@ const hibernateJCache = { }; type CacheProviderDependencies = { - base: { dependencies: JavaArtifact[] }; - hibernateCache?: { dependencies: JavaArtifact[] }; + base: { dependencies: JavaDependency[] }; + hibernateCache?: { dependencies: JavaDependency[] }; }; // eslint-disable-next-line import/prefer-default-export diff --git a/generators/spring-data-relational/internal/dependencies.ts b/generators/spring-data-relational/internal/dependencies.ts index 2a346f2ceaef..97f5786e9148 100644 --- a/generators/spring-data-relational/internal/dependencies.ts +++ b/generators/spring-data-relational/internal/dependencies.ts @@ -31,8 +31,8 @@ const testcontainerFileForDB = { postgresql: 'PostgreSqlTestContainer.java', }; -type JavaArtifact = { groupId: string; artifactId: string; version?: string }; -export type DatabaseArtifact = { jdbc: JavaArtifact; r2dbc: JavaArtifact }; +type JavaDependency = { groupId: string; artifactId: string; version?: string }; +export type DatabaseArtifact = { jdbc: JavaDependency; r2dbc: JavaDependency }; const databaseArtifactForDB: Record = { mariadb: { From 6084079b6512245a6406a4c42edcec318e038d1b Mon Sep 17 00:00:00 2001 From: Marcelo Shima Date: Mon, 18 Mar 2024 18:32:05 -0300 Subject: [PATCH 2/2] reorder maven artifacts --- generators/maven/support/pom-store.ts | 29 ++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/generators/maven/support/pom-store.ts b/generators/maven/support/pom-store.ts index 7e0922a1f1a2..75e7aced24c8 100644 --- a/generators/maven/support/pom-store.ts +++ b/generators/maven/support/pom-store.ts @@ -188,6 +188,25 @@ const ensureChild = (current: any, ...childPath) => { return current; }; +const reorderArtifact = ({ + groupId, + artifactId, + inProfile, + version, + ...rest +}: Artifact): Artifact => ({ inProfile, groupId, artifactId, version, ...rest }) as Artifact; + +const reorderDependency = ({ + groupId, + artifactId, + inProfile, + version, + type, + scope, + classifier, + ...rest +}: Dependency): Dependency => ({ inProfile, groupId, artifactId, version, type, scope, classifier, ...rest }) as Dependency; + export default class PomStorage extends XmlStorage { constructor({ saveFile, loadFile }: { saveFile: (string) => void; loadFile: () => string }) { super({ saveFile, loadFile }); @@ -200,12 +219,12 @@ export default class PomStorage extends XmlStorage { } public addDependency({ inProfile, ...dependency }: MavenDependency): void { - this.addDependencyAt(this.getNode({ profile: inProfile }), dependency); + this.addDependencyAt(this.getNode({ profile: inProfile }), reorderDependency(dependency)); this.persist(); } public addDependencyManagement({ inProfile, ...dependency }: MavenDependency): void { - this.addDependencyAt(this.getNode({ profile: inProfile, nodePath: 'dependencyManagement' }), dependency); + this.addDependencyAt(this.getNode({ profile: inProfile, nodePath: 'dependencyManagement' }), reorderDependency(dependency)); this.persist(); } @@ -268,7 +287,7 @@ export default class PomStorage extends XmlStorage { 'configuration.annotationProcessorPaths', ); const paths = ensureChildIsArray(annotationProcessorPaths, 'path'); - appendOrReplace(paths, artifact, artifactEquals); + appendOrReplace(paths, reorderArtifact(artifact), artifactEquals); this.persist(); } @@ -282,12 +301,12 @@ export default class PomStorage extends XmlStorage { protected addDependencyAt(node, { additionalContent, ...dependency }: MavenDependency) { const dependencyArray = ensureChildIsArray(node, 'dependencies.dependency'); - appendOrReplace(dependencyArray, this.mergeContent(dependency, additionalContent), dependencyEquals); + appendOrReplace(dependencyArray, this.mergeContent(reorderDependency(dependency), additionalContent), dependencyEquals); } protected addPluginAt(node, { additionalContent, ...artifact }: MavenPlugin) { const artifactArray = ensureChildIsArray(node, 'plugins.plugin'); - appendOrReplace(artifactArray, this.mergeContent(artifact, additionalContent), artifactEquals); + appendOrReplace(artifactArray, this.mergeContent(reorderArtifact(artifact), additionalContent), artifactEquals); } protected addRepositoryAt(node, { releasesEnabled, snapshotsEnabled, ...repository }: MavenRepository): void {