UNPKG

generator-begcode

Version:

Spring Boot + Angular/React/Vue in one handy generator

292 lines (291 loc) 12 kB
import { set, get } from 'lodash-es'; import sortKeys from 'sort-keys'; import XmlStorage from '../internal/xml-store.js'; const rootOrder = [ 'modelVersion', 'groupId', 'artifactId', 'version', 'packaging', 'name', 'description', 'parent', 'repositories', 'pluginRepositories', 'distributionManagement', 'properties', 'dependencyManagement', 'dependencies', 'build', 'profiles', ]; const propertiesOrder = [ 'maven.version', 'java.version', 'node.version', 'npm.version', 'project.build.sourceEncoding', 'project.reporting.outputEncoding', 'maven.build.timestamp.format', 'maven.compiler.source', 'maven.compiler.target', 'start-class', 'argLine', 'm2e.apt.activation', 'run.addResources', 'jhipster-dependencies.version', 'spring-boot.version', ]; const formatFirstXmlLevel = content => content.replace(/(\n {4}<(?:groupId|distributionManagement|repositories|pluginRepositories|properties|dependencyManagement|dependencies|build|profiles)>)/g, '\n$1'); const sortSection = section => { return Object.fromEntries(Object.entries(section).sort(([key1, value1], [key2, value2]) => { if (typeof value1 === typeof value2) key1.localeCompare(key2); if (typeof value1 === 'string') return -1; if (typeof value2 === 'string') return 1; return 0; })); }; const isComment = name => name.startsWith('#'); const toMaxInt = nr => (nr === -1 ? Number.MAX_SAFE_INTEGER : nr); const sortWithTemplate = (template, a, b) => { if (isComment(a)) return -1; if (isComment(b)) return 1; const indexOfA = toMaxInt(template.findIndex(item => item === a)); const indexOfB = toMaxInt(template.findIndex(item => item === b)); if (indexOfA === indexOfB) { return a.localeCompare(b); } return indexOfA - indexOfB; }; const comparator = (order) => (a, b) => sortWithTemplate(order, a, b); const sortProperties = properties => sortKeys(properties, { compare: comparator(propertiesOrder) }); const artifactEquals = (a, b) => { return a.groupId === b.groupId && a.artifactId === b.artifactId; }; const dependencyEquals = (a, b) => { return artifactEquals(a, b) && a.scope === b.scope && a.type === b.type; }; const idEquals = (a, b) => { return a.id === b.id; }; const ensureChildIsArray = (node, childPath) => { let dependencyArray = get(node, childPath); if (!dependencyArray) { dependencyArray = []; set(node, childPath, dependencyArray); } else if (!Array.isArray(dependencyArray)) { dependencyArray = [dependencyArray]; set(node, childPath, dependencyArray); } return dependencyArray; }; function appendOrReplace(array, item, equals) { const dependencyIndex = array.findIndex(existing => equals(existing, item)); if (dependencyIndex === -1) { array.push(item); } else { array[dependencyIndex] = item; } } function appendOrGet(array, item, equals) { const child = array.find(existing => equals(existing, item)); if (child) { return child; } array.push(item); return item; } const ensureProfile = (project, profileId) => { const profileArray = ensureChildIsArray(project, 'profiles.profile'); return appendOrGet(profileArray, { id: profileId }, idEquals); }; const groupIdOrder = ['tech.jhipster', 'org.springframework.boot', 'org.springframework.security', 'org.springdoc']; const sortArtifacts = (artifacts) => artifacts.sort((a, b) => { if (a.groupId !== b.groupId) { if (a.groupId === undefined) { return -1; } if (b.groupId === undefined) { return 1; } const groupIdCompared = sortWithTemplate(groupIdOrder, a.groupId, b.groupId); if (groupIdCompared) return groupIdCompared; } return a.artifactId.localeCompare(b.artifactId); }); const sortProfiles = (profiles) => profiles.sort((a, b) => a.id?.localeCompare(b.id) ?? 1); const ensureChildPath = (node, childPath) => { let child = get(node, childPath); if (child) return child; child = {}; set(node, childPath, child); return child; }; const ensureChild = (current, ...childPath) => { for (const node of childPath) { if (typeof node === 'string') { current = ensureChildPath(current, node); } else if (typeof node === 'function') { current = node(current); } else { throw new Error(`Path section not supported ${node}`); } if (!current) { return undefined; } } return current; }; const reorderArtifact = ({ groupId, artifactId, inProfile, version, ...rest }) => ({ inProfile, groupId, artifactId, version, ...rest }); const reorderDependency = ({ groupId, artifactId, inProfile, version, type, scope, classifier, ...rest }) => ({ inProfile, groupId, artifactId, version, type, scope, classifier, ...rest }); export default class PomStorage extends XmlStorage { constructor({ saveFile, loadFile, sortFile }) { super({ saveFile, loadFile, sortFile }); } addProperty({ inProfile, property, value = null }) { const node = this.getNode({ nodePath: 'properties', profile: inProfile }); node[property] = value; this.persist(); } addDependency({ inProfile, ...dependency }) { this.addDependencyAt(this.getNode({ profile: inProfile }), reorderDependency(dependency)); this.persist(); } addDependencyManagement({ inProfile, ...dependency }) { this.addDependencyAt(this.getNode({ profile: inProfile, nodePath: 'dependencyManagement' }), reorderDependency(dependency)); this.persist(); } addDistributionManagement({ inProfile, snapshotsId, snapshotsUrl, releasesId, releasesUrl }) { const store = this.getNode({ profile: inProfile }); store.distributionManagement = { snapshotRepository: { id: snapshotsId, url: snapshotsUrl, }, repository: { id: releasesId, url: releasesUrl, }, }; this.persist(); } addProfile({ content, ...profile }) { const profileArray = ensureChildIsArray(this.getNode(), 'profiles.profile'); appendOrReplace(profileArray, this.mergeContent(profile, content), idEquals); this.persist(); } addPlugin({ inProfile, ...plugin }) { this.addPluginAt(this.getNode({ profile: inProfile, nodePath: 'build' }), plugin); this.persist(); } addPluginManagement({ inProfile, ...plugin }) { this.addPluginAt(this.getNode({ profile: inProfile, nodePath: 'build.pluginManagement' }), plugin); this.persist(); } addRepository({ inProfile, ...repository }) { this.addRepositoryAt(this.getNode({ profile: inProfile }), repository); this.persist(); } addPluginRepository({ inProfile, ...repository }) { this.addPluginRepositoryAt(this.getNode({ profile: inProfile }), repository); this.persist(); } addAnnotationProcessor({ inProfile, ...artifact }) { const node = this.getNode({ profile: inProfile }); const plugins = ensureChildIsArray(node, 'build.pluginManagement.plugins.plugin'); const annotationProcessorPaths = ensureChild(plugins, pluginArray => { return appendOrGet(pluginArray, { groupId: 'org.apache.maven.plugins', artifactId: 'maven-compiler-plugin', }, artifactEquals); }, 'configuration.annotationProcessorPaths'); const paths = ensureChildIsArray(annotationProcessorPaths, 'path'); appendOrReplace(paths, reorderArtifact(artifact), artifactEquals); this.persist(); } getNode({ profile, nodePath } = {}) { const node = profile ? ensureProfile(this.store.project, profile) : this.store.project; if (nodePath) { return ensureChild(node, nodePath); } return node; } addDependencyAt(node, { additionalContent, ...dependency }) { const dependencyArray = ensureChildIsArray(node, 'dependencies.dependency'); appendOrReplace(dependencyArray, this.mergeContent(reorderDependency(dependency), additionalContent), dependencyEquals); } addPluginAt(node, { additionalContent, ...artifact }) { const artifactArray = ensureChildIsArray(node, 'plugins.plugin'); appendOrReplace(artifactArray, this.mergeContent(reorderArtifact(artifact), additionalContent), artifactEquals); } addRepositoryAt(node, { releasesEnabled, snapshotsEnabled, ...repository }) { const releases = releasesEnabled === undefined ? undefined : { enabled: releasesEnabled }; const snapshots = snapshotsEnabled === undefined ? undefined : { enabled: snapshotsEnabled }; const repositoryArray = ensureChildIsArray(node, 'repositories.repository'); appendOrReplace(repositoryArray, { ...repository, releases, snapshots }, idEquals); } addPluginRepositoryAt(node, { releasesEnabled, snapshotsEnabled, ...repository }) { const releases = releasesEnabled === undefined ? undefined : { enabled: releasesEnabled }; const snapshots = snapshotsEnabled === undefined ? undefined : { enabled: snapshotsEnabled }; const repositoryArray = ensureChildIsArray(node, 'pluginRepositories.pluginRepository'); appendOrReplace(repositoryArray, { ...repository, releases, snapshots }, idEquals); } sort() { if (this.store.project) { const project = sortKeys(this.store.project, { compare: comparator(rootOrder) }); this.store.project = project; if (project.properties) { project.properties = sortProperties(project.properties); } if (Array.isArray(project.dependencies?.dependency)) { project.dependencies.dependency = sortArtifacts(project.dependencies.dependency); } if (Array.isArray(project.dependencyManagement?.dependencies?.dependency)) { project.dependencyManagement.dependencies.dependency = sortArtifacts(project.dependencyManagement.dependencies.dependency); } if (project.build) { project.build = sortSection(project.build); if (Array.isArray(project.build.plugins?.plugin)) { project.build.plugins.plugin = sortArtifacts(project.build.plugins.plugin); } if (Array.isArray(project.build.pluginManagement?.plugins?.plugin)) { project.build.pluginManagement.plugins.plugin = sortArtifacts(project.build.pluginManagement.plugins.plugin); } } if (Array.isArray(project.profiles?.profile)) { project.profiles.profile = sortProfiles(project.profiles.profile); } } } } const emptyPomFile = `<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> </project> `; export const createPomStorage = (generator, { sortFile } = {}) => { const loadFile = () => generator.readDestination('pom.xml', { defaults: emptyPomFile })?.toString() ?? ''; const pomStorage = new PomStorage({ loadFile, saveFile: content => generator.writeDestination('pom.xml', formatFirstXmlLevel(content)), sortFile, }); generator.fs.store.on('change', filename => { if (filename === generator.destinationPath('pom.xml')) { pomStorage.clearCache(); } }); return pomStorage; };