Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: pass generalAnswers to configure plugins #23

Merged
merged 4 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion __fixtures/config/withExpressions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ module.exports = {
baz: '4',
array: [
Boolean(100 + 500 * 1)
]
],
specials: /\n\t\r/g,
extraSlash: /\, \, \\/g
};
19 changes: 15 additions & 4 deletions src/configBuilder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import defaultHermioneConfig from "./constants/defaultHermioneConfig";
import { ConfigBuilder } from "./configBuilder";
import fsUtils from "./fsUtils";
import defaultPluginsConfig from "./pluginsConfig";
import type { GeneralPrompt, HermioneConfig } from "./types";
import type { Answers, GeneralPrompt, HermioneConfig } from "./types";

jest.mock("inquirer");

Expand Down Expand Up @@ -104,14 +104,21 @@ describe("configBuilder", () => {
});

it("should use default pluginsConfig, if not specified", async () => {
const generalAnswers: Answers = { _path: "/", _language: "ts" };
defaultPluginsConfig["html-reporter/hermione"] = jest.fn().mockImplementation((config: HermioneConfig) => {
_.set(config, "htmlReporterIsSet", true);
});

await configBuilder.configurePlugins(["html-reporter/hermione"]);
await configBuilder.configurePlugins({
pluginNames: ["html-reporter/hermione"],
generalAnswers,
});

expectConfig({ ...defaultHermioneConfig, htmlReporterIsSet: true });
expect(defaultPluginsConfig["html-reporter/hermione"]).toBeCalledWith(defaultHermioneConfig);
expect(defaultPluginsConfig["html-reporter/hermione"]).toBeCalledWith(
defaultHermioneConfig,
generalAnswers,
);
});

it("should use overwrited pluginsConfig, if specified", async () => {
Expand All @@ -125,7 +132,11 @@ describe("configBuilder", () => {
},
});

await configBuilder.configurePlugins(["html-reporter/hermione"], cb);
await configBuilder.configurePlugins({
pluginNames: ["html-reporter/hermione"],
createPluginsConfig: cb,
generalAnswers: { _path: "/", _language: "ts" },
});

expectConfig({ ...defaultHermioneConfig, foo: "bar" });
});
Expand Down
27 changes: 19 additions & 8 deletions src/configBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@ import defaultPluginsConfig from "./pluginsConfig";
import defaultToolOpts from "./constants/defaultToolOpts";
import defaultHermioneConfig from "./constants/defaultHermioneConfig";
import type { HermioneConfig, Language } from "./types/hermioneConfig";
import type { HandleGeneralPromptsCallback } from "./types/toolOpts";
import type { Answers, HandleGeneralPromptsCallback } from "./types/toolOpts";
import type { CreateBaseConfigCallback, CreatePluginsConfigCallback } from ".";
import type { GeneralPrompt } from "./types/toolOpts";
import { getTemplate } from "./utils/configTemplates";

type ConfigurePluginsOpts = {
pluginNames: string[];
createPluginsConfig?: CreatePluginsConfigCallback;
generalAnswers: Answers;
};

export class ConfigBuilder {
static create(createBaseConfig?: CreateBaseConfigCallback, opts?: { language: Language }): ConfigBuilder {
return new this(createBaseConfig, opts);
Expand All @@ -30,9 +36,14 @@ export class ConfigBuilder {
promts: GeneralPrompt[],
handlers: HandleGeneralPromptsCallback[],
{ path, noQuestions }: { path: string; noQuestions: boolean },
): Promise<void> {
): Promise<Answers> {
const answers: Answers = {
_path: path,
_language: this._config.__template!.language,
};

if (_.isEmpty(promts) || _.isEmpty(handlers)) {
return;
return answers;
}

const defaults = promts.reduce((acc, prompt) => {
Expand All @@ -45,23 +56,23 @@ export class ConfigBuilder {

const promptsToAsk = noQuestions ? promts.filter(prompt => _.isUndefined(prompt.default)) : promts;
const inquirerAnswers = await inquirer.prompt(promptsToAsk);
const answers = noQuestions ? { ...defaults, ...inquirerAnswers } : inquirerAnswers;

answers._path = path;
answers._language = this._config.__template!.language;
Object.assign(answers, defaults, inquirerAnswers, answers);

for (const handler of handlers) {
this._config = await handler(this._config, answers);
}

return answers;
}

async configurePlugins(pluginNames: string[], createPluginsConfig?: CreatePluginsConfigCallback): Promise<void> {
async configurePlugins({ pluginNames, createPluginsConfig, generalAnswers }: ConfigurePluginsOpts): Promise<void> {
const pluginsConfig = createPluginsConfig ? createPluginsConfig(defaultPluginsConfig) : defaultPluginsConfig;

this._config.plugins ||= {};

for (const plugin of pluginNames) {
await pluginsConfig[plugin](this._config);
await pluginsConfig[plugin](this._config, generalAnswers);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/fsUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ describe("fsUtils", () => {
bar: 4,
baz: "4",
array: ["__expression: Boolean(100 + 500 * 1)"],
specials: "__expression: /\n\t\r/g",
extraSlash: "__expression: /\\, \\, \\\\/g",
} as unknown as HermioneConfig;

await expectConfig(withExpressionsConfig, configs["withExpressions"]);
Expand Down
10 changes: 7 additions & 3 deletions src/fsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,15 @@ export const writeHermioneConfig = async (dirPath: string, hermioneConfig: Hermi
const quote = template.quote;
const expressionRegExp = new RegExp(`${quote}__expression: (.*)${quote}(,?)$`, "gm");

// unescapes and restores double quotes in expressions
const withRestoredQuotesConfigStr = configStr.replace(expressionRegExp, match => match.replace(/\\"/g, '"'));
const repairQuotes = (match: string): string => match.replace(/\\"/g, '"');
const repairSlash = (match: string): string => match.replace(/\\\\/g, "\\");

const repairedConfig = configStr
.replace(expressionRegExp, repairQuotes) // unescapes and restores double quotes in expressions
.replace(expressionRegExp, repairSlash); // restores '\\' in expressions

// strings like '__expression: <expression>' are turned into <expression>
return withRestoredQuotesConfigStr.replace(expressionRegExp, "$1$2");
return repairedConfig.replace(expressionRegExp, "$1$2");
};

const getObjectRepr = _.flow([toIndentedJson, withComments, withReplacedQuotes, withExpressions]);
Expand Down
6 changes: 3 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ export const run = async ({
? [baseGeneralPromptsHandler, generalPromptsHandler]
: [baseGeneralPromptsHandler];

await configBuilder.handleGeneralQuestions(generalPrompts, generalPromptsHandlers, opts);
const generalAnswers = await configBuilder.handleGeneralQuestions(generalPrompts, generalPromptsHandlers, opts);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это может быть полезно в тех случаях, когда от ответа на такой вопрос зависит, как именно будет производиться настройка плагина


const { pluginNames, configNotes } = await getPluginNames(opts);
const extraPackages = getExtraPackagesToInstall ? getExtraPackagesToInstall() : { names: [], notes: [] };

await configBuilder.configurePlugins(pluginNames, createPluginsConfig);
await configBuilder.configurePlugins({ pluginNames, createPluginsConfig, generalAnswers });

const extraPackages = getExtraPackagesToInstall ? getExtraPackagesToInstall() : { names: [], notes: [] };
Comment on lines +72 to +74
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Поменял их местами, чтобы при настройке одного плагина можно было добавить и другой: комплиментарный

const packageNamesToInstall = pluginNames.concat(extraPackages.names);

if (opts.language === "ts") {
Expand Down
2 changes: 1 addition & 1 deletion src/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export const installPackages = async (
pluginsToInstall: string[],
registry: string,
): Promise<string> => {
const spinner = ora("Installing packages").start();
const spinner = ora("Installing packages (this may take a while)").start();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Изначально хотел сделать так, чтоб процесс установки выводился в консоль, но чет не нашел, как это сделать с сабпроцессами, чтобы оно работало как с нативными пакетными менеджерами.

Добавил тут эту приписку, чтобы не выглядело, так, как будто оно зависло. Гермиона устанавливается не быстро (например, сборка нативных модулей занимает какое-то время)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А чего не юзнуть execa - https://github.com/sindresorhus/execa? В нем вроде удобно можно пайпить stdout в основной процесс.

Copy link
Member Author

@KuznetsovRoman KuznetsovRoman Feb 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Попробовал

Удобно

Нет. С 6 версии он pure esm, а cwd только в 7 можно передавать

Можно пайпить stdout

Это все еще ничего не даст. Сам npm install логов не пишет, он отображает текст в терминале (то есть, npm install 2> errLogs > logs ничего интересного не дает)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Пробовал по-всякому, и shell в spawn передавать, и на события смотреть... npm видит, что его запустили не совсем в терминале и молчит


const pluginsPackages = pluginsToInstall.map(packageNameFromPlugin).join(" ");

Expand Down
3 changes: 2 additions & 1 deletion src/types/pluginsConfig.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { HermioneConfig } from "./hermioneConfig";
import type { Answers } from "./toolOpts";

export interface PluginsConfig {
[plugin: string]: (config: HermioneConfig) => void | Promise<void>;
[plugin: string]: (config: HermioneConfig, generalAnswers?: Answers) => void | Promise<void>;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Сделал тут | Answers, чтобы не обязательно было при указании этого коллэка использовать generalAnswers

}
Loading