gen-jhipster
Version:
VHipster - Spring Boot + Angular/React/Vue in one handy generator
211 lines (210 loc) • 9.27 kB
JavaScript
/**
* Copyright 2013-2026 the original author or authors from the JHipster project.
*
* This file is part of the JHipster project, see https://www.jhipster.tech/
* for more information.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { rm } from 'node:fs/promises';
import { createConflicterTransform, createYoResolveTransform, forceYoFiles } from '@yeoman/conflicter';
import { transform } from '@yeoman/transform';
import { isFilePending, isFileStateModified } from 'mem-fs-editor/state';
import { createCommitTransform } from 'mem-fs-editor/transform';
import BaseGenerator, { CommandBaseGenerator } from "../base/index.js";
import { PRIORITY_NAMES, QUEUES } from "../base-application/priorities.js";
import { createNeedleTransform } from "../base-core/support/needles.js";
import { PRETTIER_EXTENSIONS } from "../generator-constants.js";
import { autoCrlfTransform, createESLintTransform, createForceWriteConfigFilesTransform, createMultiStepTransform, createPrettierTransform, createRemoveUnusedImportsTransform, createSortConfigFilesTransform, isPrettierConfigFilePath, } from "./support/index.js";
const { MULTISTEP_TRANSFORM, PRE_CONFLICTS } = PRIORITY_NAMES;
const { MULTISTEP_TRANSFORM_QUEUE, PRE_CONFLICTS_QUEUE } = QUEUES;
const MULTISTEP_TRANSFORM_PRIORITY = BaseGenerator.asPriority(MULTISTEP_TRANSFORM);
const PRE_CONFLICTS_PRIORITY = BaseGenerator.asPriority(PRE_CONFLICTS);
export default class BootstrapGenerator extends CommandBaseGenerator {
static MULTISTEP_TRANSFORM = MULTISTEP_TRANSFORM_PRIORITY;
static PRE_CONFLICTS = PRE_CONFLICTS_PRIORITY;
upgradeCommand;
skipPrettier;
skipEslint;
prettierExtensions = PRETTIER_EXTENSIONS.split(',');
prettierOptions = { plugins: [] };
refreshOnCommit = false;
constructor(args, options, features) {
super(args, options, { uniqueGlobally: true, customCommitTask: () => this.commitTask(), ...features });
}
async beforeQueue() {
// Force npm override later if needed
this.env.options.nodePackageManager = 'npm';
this.upgradeCommand = this.options.commandName === 'upgrade';
if (!this.fromBlueprint) {
await this.composeWithBlueprints();
}
if (this.delegateToBlueprint) {
throw new Error('Only sbs blueprint is supported');
}
}
get multistepTransform() {
return {
queueMultistepTransform() {
this.queueMultistepTransform();
},
};
}
get [MULTISTEP_TRANSFORM_PRIORITY]() {
return this.multistepTransform;
}
get preConflicts() {
return this.asAnyTaskGroup({
queueCommitPrettierConfig() {
this.queueCommitPrettierConfig();
},
});
}
get [PRE_CONFLICTS_PRIORITY]() {
return this.preConflicts;
}
/**
* Queue multi step templates transform
*/
queueMultistepTransform() {
const templateData = { ...this.jhipsterConfig };
const multiStepTransform = createMultiStepTransform(templateData);
const listener = (filePath) => {
if (multiStepTransform.templateFileFs.isTemplate(filePath)) {
this.env.sharedFs.removeListener('change', listener);
this.queueMultistepTransform();
}
};
this.queueTask({
method: async () => {
await this.pipeline({
name: 'applying multi-step templates',
filter: file => isFileStateModified(file) && multiStepTransform.templateFileFs.isTemplate(file.path),
refresh: true,
resolveConflict: (current, newFile) => (isFileStateModified(current) ? current : newFile),
}, multiStepTransform);
this.env.sharedFs.on('change', listener);
},
taskName: MULTISTEP_TRANSFORM_QUEUE,
queueName: MULTISTEP_TRANSFORM_QUEUE,
once: true,
});
}
queueCommitPrettierConfig() {
const listener = (filePath) => {
if (isPrettierConfigFilePath(filePath)) {
this.env.sharedFs.removeListener('change', listener);
this.queueCommitPrettierConfig();
}
};
this.queueTask({
method: async () => {
await this.commitPrettierConfig();
this.env.sharedFs.on('change', listener);
},
taskName: 'commitPrettierConfig',
queueName: PRE_CONFLICTS_QUEUE,
once: true,
});
}
async commitPrettierConfig() {
await this.commitSharedFs({
log: 'prettier configuration files committed to disk',
filter: file => isPrettierConfigFilePath(file.path),
});
}
async commitTask() {
await this.commitSharedFs({ refresh: this.refreshOnCommit }, ...this.env.findFeature('commitTransformFactory').flatMap(({ feature }) => feature()));
}
/**
* Commits the MemFs to the disc.
*/
async commitSharedFs({ log, ...options } = {}, ...transforms) {
const skipYoResolveTransforms = [];
if (!this.options.skipYoResolve) {
skipYoResolveTransforms.push(createYoResolveTransform());
}
const prettierTransforms = [];
if (!this.skipPrettier) {
const ignoreErrors = this.options.ignoreErrors || this.upgradeCommand;
if (!this.skipEslint) {
prettierTransforms.push(await createESLintTransform.call(this, { ignoreErrors }), await createRemoveUnusedImportsTransform.call(this, { ignoreErrors }));
}
prettierTransforms.push(await createPrettierTransform.call(this, {
ignoreErrors,
prettierPackageJson: true,
prettierJava: !this.jhipsterConfig.skipServer,
extensions: this.prettierExtensions.join(','),
prettierOptions: this.prettierOptions,
}));
}
const autoCrlfTransforms = [];
if (this.jhipsterConfigWithDefaults.autoCrlf) {
autoCrlfTransforms.push(await autoCrlfTransform({ baseDir: this.destinationPath() }));
}
let customizeActions;
if (this.options.devBlueprintEnabled) {
customizeActions = (actions, { separator }) => {
return [
...actions,
...(separator ? [separator()] : []),
{
key: 't',
name: 'apply to template',
value: async ({ file }) => {
const { applyChangesToFileOrCopy } = await import("../../lib/ci/apply-patch-to-template.js");
if (file.history?.[0] && file.conflicterData?.diskContents) {
const templateFile = file.history[0];
if (file.contents) {
const oldFileContents = file.conflicterData.diskContents.toString();
const newFileContents = file.contents.toString();
applyChangesToFileOrCopy({ templateFile, oldFileContents, newFileContents });
}
else {
await rm(templateFile, { force: true });
}
}
return 'skip';
},
},
];
};
}
const removeNeedlesTransforms = [];
if (this.jhipsterConfig.removeNeedles) {
removeNeedlesTransforms.push(createNeedleTransform());
}
const transformStreams = [
...skipYoResolveTransforms,
forceYoFiles(),
createSortConfigFilesTransform(),
createForceWriteConfigFilesTransform(),
...removeNeedlesTransforms,
...prettierTransforms,
...autoCrlfTransforms,
createConflicterTransform(this.env.adapter, { ...this.env.conflicterOptions, customizeActions }),
createCommitTransform(),
];
await this.pipeline({
refresh: false,
// Let pending files pass through.
pendingFiles: false,
...options,
// Disable progress since it blocks stdin.
disabled: true,
}, ...transforms,
// Filter out pending files.
transform((file) => (isFilePending(file) ? file : undefined)), ...transformStreams);
this.log.ok(log ?? 'files committed to disk');
}
}