From 5071d9dfc4cfac0083357c1a4980bd2dd4c94ff6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 21 Aug 2024 10:07:05 +0900 Subject: [PATCH] chore(deps): update dependency inquirer to v10 (#2864) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Takahiko Kawakami <53943902+shabaraba@users.noreply.github.com> --- packages/create-plugin/__e2e__/e2e.test.ts | 12 + .../pluginDescriptionContain201Chars.ts | 2 +- .../fixtures/pluginNameContain65Chars.ts | 2 +- packages/create-plugin/package.json | 2 +- .../src/__tests__/manifest.test.ts | 29 +- .../create-plugin/src/__tests__/qa.test.ts | 312 ++++++++--------- packages/create-plugin/src/index.ts | 80 +++-- packages/create-plugin/src/manifest.ts | 10 +- packages/create-plugin/src/messages.ts | 6 +- packages/create-plugin/src/qa.ts | 242 ++++++-------- packages/create-plugin/src/qa/prompt.ts | 96 ++++++ packages/create-plugin/src/qa/validator.ts | 14 + packages/customize-uploader/package.json | 2 +- packages/customize-uploader/src/messages.ts | 6 +- .../customize-uploader/src/params/index.ts | 53 ++- .../customize-uploader/src/params/init.ts | 27 +- .../src/params/prompts/index.ts | 37 +++ .../src/params/prompts/init.ts | 22 ++ packages/plugin-uploader/package.json | 2 +- packages/plugin-uploader/src/params.ts | 48 +-- .../plugin-uploader/src/prompts/params.ts | 37 +++ pnpm-lock.yaml | 314 +++++++++++------- 22 files changed, 763 insertions(+), 592 deletions(-) create mode 100644 packages/create-plugin/src/qa/prompt.ts create mode 100644 packages/create-plugin/src/qa/validator.ts create mode 100644 packages/customize-uploader/src/params/prompts/index.ts create mode 100644 packages/customize-uploader/src/params/prompts/init.ts create mode 100644 packages/plugin-uploader/src/prompts/params.ts diff --git a/packages/create-plugin/__e2e__/e2e.test.ts b/packages/create-plugin/__e2e__/e2e.test.ts index d72c251401..0fe5a22e52 100644 --- a/packages/create-plugin/__e2e__/e2e.test.ts +++ b/packages/create-plugin/__e2e__/e2e.test.ts @@ -45,6 +45,9 @@ export type TestPattern = { stdout?: string; stderr?: string; }; + validation?: { + stdout?: string; + } }; }; @@ -122,6 +125,15 @@ describe("create-plugin", function () { ); } } + + if (expected.validation !== undefined) { + if (expected.validation.stdout) { + assert.match( + response.stdout.trim(), + new RegExp(expected.validation.stdout), + ); + } + } } catch (e: any) { assert.fail(e); } diff --git a/packages/create-plugin/__e2e__/fixtures/pluginDescriptionContain201Chars.ts b/packages/create-plugin/__e2e__/fixtures/pluginDescriptionContain201Chars.ts index 3a639b6b40..d455c0bada 100644 --- a/packages/create-plugin/__e2e__/fixtures/pluginDescriptionContain201Chars.ts +++ b/packages/create-plugin/__e2e__/fixtures/pluginDescriptionContain201Chars.ts @@ -23,6 +23,6 @@ export const pattern: TestPattern = { ], }, expected: { - failure: { stdout: ">> Plug-in description must be 1-200chars" }, + validation: { stdout: "> Plug-in description must be 1-200chars" }, }, }; diff --git a/packages/create-plugin/__e2e__/fixtures/pluginNameContain65Chars.ts b/packages/create-plugin/__e2e__/fixtures/pluginNameContain65Chars.ts index 7a55c11a7a..a423a3a424 100644 --- a/packages/create-plugin/__e2e__/fixtures/pluginNameContain65Chars.ts +++ b/packages/create-plugin/__e2e__/fixtures/pluginNameContain65Chars.ts @@ -19,6 +19,6 @@ export const pattern: TestPattern = { ], }, expected: { - failure: { stdout: ">> Plug-in name must be 1-64chars" }, + validation: { stdout: "> Plug-in name must be 1-64chars" }, }, }; diff --git a/packages/create-plugin/package.json b/packages/create-plugin/package.json index 46d79c2307..717fc16b55 100644 --- a/packages/create-plugin/package.json +++ b/packages/create-plugin/package.json @@ -18,9 +18,9 @@ "homepage": "https://github.com/kintone/js-sdk/tree/main/packages/create-plugin", "bugs": "https://github.com/kintone/js-sdk/issues", "dependencies": { + "@inquirer/prompts": "^5.3.7", "chalk": "^4.1.2", "glob": "^10.4.5", - "inquirer": "^8.2.6", "lodash": "^4.17.21", "meow": "^9.0.0", "node-rsa": "^1.1.1", diff --git a/packages/create-plugin/src/__tests__/manifest.test.ts b/packages/create-plugin/src/__tests__/manifest.test.ts index 53e674c49f..ad6d9620c3 100644 --- a/packages/create-plugin/src/__tests__/manifest.test.ts +++ b/packages/create-plugin/src/__tests__/manifest.test.ts @@ -7,12 +7,15 @@ describe("manifest", () => { describe("buildManifest", () => { const templateType = "minimum"; it("should include basic settings", () => { + const baseManifest = createBaseManifest(); // @ts-ignore We can fix this using conditional types const manifest = buildManifest( { - ...createBaseManifest(), - ja: false, - cn: false, + name: baseManifest.name, + description: baseManifest.name, + homepage_url: {}, + supportMobile: false, + enablePluginUploader: false, }, templateType, ); @@ -21,26 +24,30 @@ describe("manifest", () => { assert.strictEqual(manifest.mobile, undefined); }); it("should include mobile.js if the answers enable mobile", () => { + const baseManifest = createBaseManifest(); // @ts-ignore We can fix this using conditional types const manifest = buildManifest( { - ...createBaseManifest(), - ja: false, - cn: false, - mobile: true, + name: baseManifest.name, + description: baseManifest.name, + homepage_url: {}, + supportMobile: true, + enablePluginUploader: false, }, templateType, ); assert(manifest.mobile && Array.isArray(manifest.mobile.js)); }); it("should include config if the answers enable config", () => { + const baseManifest = createBaseManifest(); // @ts-ignore We can fix this using conditional types const manifest = buildManifest( { - ...createBaseManifest(), - ja: false, - cn: false, - config: true, + name: baseManifest.name, + description: baseManifest.name, + homepage_url: {}, + supportMobile: false, + enablePluginUploader: false, }, templateType, ); diff --git a/packages/create-plugin/src/__tests__/qa.test.ts b/packages/create-plugin/src/__tests__/qa.test.ts index 1b2ae1683c..4d59f98e8a 100644 --- a/packages/create-plugin/src/__tests__/qa.test.ts +++ b/packages/create-plugin/src/__tests__/qa.test.ts @@ -1,195 +1,147 @@ import assert from "assert"; -import type { Question } from "inquirer"; -import { buildQuestions } from "../qa"; - -const getQuestion = ( - questions: Question[], - predicate: (q: Question) => boolean, -): Question => { - return questions.find(predicate) as Question; -}; +import * as prompt from "../qa/prompt"; +import { validateForDescription, validateForName } from "../qa/validator"; +import { getDefaultName, runPrompt } from "../qa"; +import type { BoundMessage } from "../messages"; +import { getBoundMessage } from "../messages"; describe("qa", () => { - describe("buildQuestions", () => { - it("should return questions", () => { - const questions = buildQuestions("dist", "en"); - assert(Array.isArray(questions)); - }); - describe("name.en", () => { - it("should be set the default value of name.en based on the passed directory", () => { - const questions = buildQuestions("foo/bar/dist", "en"); - const nameEn = getQuestion( - questions, - ({ name }: Question) => name === "name.en", - ); - assert.equal(nameEn.default, "dist"); - }); - it("should be able to validate name.en", () => { - const questions = buildQuestions("dist", "en"); - const q = getQuestion( - questions, - ({ name }: Question) => name === "name.en", - ); - assert( - typeof q.validate !== "undefined" && q.validate("hoge") === true, - ); - assert( - typeof q.validate !== "undefined" && - q.validate("a".repeat(64)) === true, - ); - assert( - typeof q.validate !== "undefined" && - typeof q.validate("") === "string", - ); - assert( - typeof q.validate !== "undefined" && - typeof q.validate("a".repeat(65)) === "string", - ); - }); - }); - describe("description.en", () => { - it("should be set the default value of description.en based on name.en", () => { - const questions = buildQuestions("dist", "en"); - const q = getQuestion( - questions, - ({ name }: Question) => name === "description.en", - ); - assert.equal(q.default({ name: { en: "foo" } }), "foo"); - }); - it("should be able to validate description.en", () => { - const questions = buildQuestions("dist", "en"); - const q = getQuestion( - questions, - ({ name }: Question) => name === "description.en", - ); - assert( - typeof q.validate !== "undefined" && q.validate("hoge") === true, - ); - assert( - typeof q.validate !== "undefined" && - q.validate("a".repeat(200)) === true, - ); - assert( - typeof q.validate !== "undefined" && - typeof q.validate("") === "string", - ); - assert( - typeof q.validate !== "undefined" && - typeof q.validate("a".repeat(201)) === "string", - ); - }); + describe("validator", () => { + it("should be able to validate by validateForName", () => { + assert(validateForName("hoge")); + assert(validateForName("a".repeat(64))); + assert(!validateForName("")); + assert(!validateForName("a".repeat(65))); }); - describe("ja", () => { - it("should be true by default if the lang is ja", () => { - const questions = buildQuestions("dist", "ja"); - const q = getQuestion(questions, ({ name }: Question) => name === "ja"); - assert(q.default === true); - }); - it("should be false by default if the lang is not ja", () => { - const questions = buildQuestions("dist", "en"); - const q = getQuestion(questions, ({ name }: Question) => name === "ja"); - assert(q.default === false); - }); + it("should be able to validate by validateForDescription", () => { + assert(validateForDescription("hoge")); + assert(validateForDescription("a".repeat(200))); + assert(!validateForDescription("")); + assert(!validateForDescription("a".repeat(201))); }); - describe("name.ja", () => { - it("should be enabled only in answer.ja is true", () => { - const questions = buildQuestions("dist", "en"); - const q = getQuestion( - questions, - ({ name }: Question) => name === "name.ja", - ); - assert(typeof q.when === "function" && q.when({ ja: false }) === false); - assert(typeof q.when === "function" && q.when({ ja: true }) === true); - }); + }); + describe("getDefaultName", () => { + it("should be set the default value of name.en based on the passed directory", () => { + assert.equal(getDefaultName("foo/bar/dist"), "dist"); }); - describe("description.ja", () => { - it("should be enabled only in answer.ja is true", () => { - const questions = buildQuestions("dist", "en"); - const q = getQuestion( - questions, - ({ name }: Question) => name === "description.ja", - ); - assert(typeof q.when === "function" && q.when({ ja: false }) === false); - assert(typeof q.when === "function" && q.when({ ja: true }) === true); + }); + describe("runPrompt", () => { + describe("optional lang parameters", () => { + beforeEach(() => { + jest.spyOn(prompt, "promptForName").mockResolvedValue("pass"); + jest.spyOn(prompt, "promptForDescription").mockResolvedValue("pass"); + jest.spyOn(prompt, "promptForOptionalName").mockResolvedValue("pass"); + jest + .spyOn(prompt, "promptForOptionalDescription") + .mockResolvedValue("pass"); + jest.spyOn(prompt, "promptForHomepage").mockResolvedValue("pass"); + jest.spyOn(prompt, "promptForSupportLang").mockResolvedValue(true); + jest.spyOn(prompt, "promptForSupportMobile").mockResolvedValue(true); + jest + .spyOn(prompt, "promptForEnablePluginUploader") + .mockResolvedValue(true); }); - }); - describe("name.zh", () => { - it("should be enabled only in answer.zh is true", () => { - const questions = buildQuestions("dist", "en"); - const q = getQuestion( - questions, - ({ name }: Question) => name === "name.zh", - ); - assert(typeof q.when === "function" && q.when({ zh: false }) === false); - assert(typeof q.when === "function" && q.when({ zh: true }) === true); + it("should be set ja parameters in supportJa is true", async () => { + jest + .spyOn(prompt, "promptForSupportLang") + .mockImplementation( + async (m: BoundMessage, supportLang: prompt.SupportLang) => { + return supportLang === "Ja"; + }, + ); + const result1 = await runPrompt( + getBoundMessage("ja"), + "foo/bar/dist", + "ja", + ); + assert.notEqual(result1.name.ja, undefined); + assert.notEqual(result1.description.ja, undefined); + assert.notEqual(result1.homepage_url, undefined); + assert.notEqual(result1.homepage_url?.ja, undefined); }); - }); - describe("description.zh", () => { - it("should be enabled only in answer.zh is true", () => { - const questions = buildQuestions("dist", "en"); - const q = getQuestion( - questions, - ({ name }: Question) => name === "description.zh", - ); - assert(typeof q.when === "function" && q.when({ zh: false }) === false); - assert(typeof q.when === "function" && q.when({ zh: true }) === true); + it("should not be set ja parameters in supportJa is false", async () => { + jest + .spyOn(prompt, "promptForSupportLang") + .mockImplementation( + async (m: BoundMessage, supportLang: prompt.SupportLang) => { + return !(supportLang === "Ja"); + }, + ); + const result2 = await runPrompt( + getBoundMessage("en"), + "foo/bar/dist", + "en", + ); + assert.equal(result2.name.ja, undefined); + assert.equal(result2.description.ja, undefined); }); - }); - - describe("name.es", () => { - it("should be enabled only in answer.es is true", () => { - const questions = buildQuestions("dist", "en"); - const q = getQuestion( - questions, - ({ name }: Question) => name === "name.es", - ); - assert(typeof q.when === "function" && q.when({ es: false }) === false); - assert(typeof q.when === "function" && q.when({ es: true }) === true); + it("should be set zh parameters in supportZh is true", async () => { + jest + .spyOn(prompt, "promptForSupportLang") + .mockImplementation( + async (m: BoundMessage, supportLang: prompt.SupportLang) => { + return supportLang === "Zh"; + }, + ); + const result1 = await runPrompt( + getBoundMessage("ja"), + "foo/bar/dist", + "ja", + ); + assert.notEqual(result1.name.zh, undefined); + assert.notEqual(result1.description.zh, undefined); + assert.notEqual(result1.homepage_url, undefined); + assert.notEqual(result1.homepage_url?.zh, undefined); }); - }); - describe("description.es", () => { - it("should be enabled only in answer.es is true", () => { - const questions = buildQuestions("dist", "en"); - const q = getQuestion( - questions, - ({ name }: Question) => name === "description.es", - ); - assert(typeof q.when === "function" && q.when({ es: false }) === false); - assert(typeof q.when === "function" && q.when({ es: true }) === true); - }); - }); - - describe("homepage_url.ja", () => { - it("should be enabled only in answer.ja is true", () => { - const questions = buildQuestions("dist", "en"); - const q = getQuestion( - questions, - ({ name }: Question) => name === "homepage_url.ja", - ); - assert(typeof q.when === "function" && q.when({ ja: false }) === false); - assert(typeof q.when === "function" && q.when({ ja: true }) === true); + it("should not be set zh parameters in supportZh is false", async () => { + jest + .spyOn(prompt, "promptForSupportLang") + .mockImplementation( + async (m: BoundMessage, supportLang: prompt.SupportLang) => { + return !(supportLang === "Zh"); + }, + ); + const result2 = await runPrompt( + getBoundMessage("en"), + "foo/bar/dist", + "en", + ); + assert.equal(result2.name.zh, undefined); + assert.equal(result2.description.zh, undefined); }); - }); - describe("homepage_url.zh", () => { - it("should be enabled only in answer.zh is true", () => { - const questions = buildQuestions("dist", "en"); - const q = getQuestion( - questions, - ({ name }: Question) => name === "homepage_url.zh", - ); - assert(typeof q.when === "function" && q.when({ zh: false }) === false); - assert(typeof q.when === "function" && q.when({ zh: true }) === true); + it("should be set es parameters in supportEs is true", async () => { + jest + .spyOn(prompt, "promptForSupportLang") + .mockImplementation( + async (m: BoundMessage, supportLang: prompt.SupportLang) => { + return supportLang === "Es"; + }, + ); + const result1 = await runPrompt( + getBoundMessage("ja"), + "foo/bar/dist", + "ja", + ); + assert.notEqual(result1.name.es, undefined); + assert.notEqual(result1.description.es, undefined); + assert.notEqual(result1.homepage_url, undefined); + assert.notEqual(result1.homepage_url?.es, undefined); }); - }); - describe("homepage_url.es", () => { - it("should be enabled only in answer.es is true", () => { - const questions = buildQuestions("dist", "en"); - const q = getQuestion( - questions, - ({ name }: Question) => name === "homepage_url.es", - ); - assert(typeof q.when === "function" && q.when({ es: false }) === false); - assert(typeof q.when === "function" && q.when({ es: true }) === true); + it("should not be set es parameters in supportEs is false", async () => { + jest + .spyOn(prompt, "promptForSupportLang") + .mockImplementation( + async (m: BoundMessage, supportLang: prompt.SupportLang) => { + return !(supportLang === "Es"); + }, + ); + const result2 = await runPrompt( + getBoundMessage("en"), + "foo/bar/dist", + "en", + ); + assert.equal(result2.name.es, undefined); + assert.equal(result2.description.es, undefined); }); }); }); diff --git a/packages/create-plugin/src/index.ts b/packages/create-plugin/src/index.ts index 45d1263b0e..f856b4b47b 100644 --- a/packages/create-plugin/src/index.ts +++ b/packages/create-plugin/src/index.ts @@ -2,15 +2,15 @@ import chalk = require("chalk"); import * as fs from "fs"; -import * as inquirer from "inquirer"; import { rimraf } from "rimraf"; import { generatePlugin } from "./generator"; import type { Lang } from "./lang"; import { printError, printLog } from "./logger"; +import type { Manifest } from "./manifest"; import { buildManifest } from "./manifest"; import { getBoundMessage, getMessage } from "./messages"; -import { buildQuestions } from "./qa"; import type { TemplateType } from "./template"; +import { runPrompt } from "./qa"; /** * Verify whether the output directory is valid @@ -25,36 +25,14 @@ const verifyOutputDirectory = (outputDirectory: string, lang: Lang): void => { } }; -/** - * Run create-kintone-plugin script - * @param outputDir - * @param lang - * @param templateType - */ -const run = (outputDir: string, lang: Lang, templateType: TemplateType) => { +const getSuccessCreatedPluginMessage = ( + manifest: Manifest, + outputDir: string, + enablePluginUploader: boolean, + lang: Lang, +) => { const m = getBoundMessage(lang); - verifyOutputDirectory(outputDir, lang); - printLog(` - - ${m("introduction")} - - `); - - inquirer - .prompt(buildQuestions(outputDir, lang)) - .then(async (answers) => { - const manifest = buildManifest(answers, templateType); - await generatePlugin( - outputDir, - manifest, - lang, - answers.pluginUploader, - templateType, - ); - return [manifest, answers.pluginUploader]; - }) - .then(([manifest, enablePluginUploader]) => { - printLog(` + return ` Success! Created ${manifest.name.en} at ${outputDir} @@ -80,7 +58,45 @@ ${enablePluginUploader ? m("howToUsePluginUploader") : ""} ${m("lastMessage")} ${m("developerSite")} - `); + `; +}; + +/** + * Run create-kintone-plugin script + * @param outputDir + * @param lang + * @param templateType + */ +const run = (outputDir: string, lang: Lang, templateType: TemplateType) => { + const m = getBoundMessage(lang); + verifyOutputDirectory(outputDir, lang); + printLog(` + + ${m("introduction")} + + `); + + runPrompt(m, outputDir, lang) + .then(async (answers): Promise<[Manifest, boolean]> => { + const manifest = buildManifest(answers, templateType); + await generatePlugin( + outputDir, + manifest, + lang, + answers.enablePluginUploader, + templateType, + ); + return [manifest, answers.enablePluginUploader]; + }) + .then(([manifest, enablePluginUploader]) => { + printLog( + getSuccessCreatedPluginMessage( + manifest, + outputDir, + enablePluginUploader, + lang, + ), + ); }) .catch((error: Error) => { rimraf(outputDir, { glob: true }) diff --git a/packages/create-plugin/src/manifest.ts b/packages/create-plugin/src/manifest.ts index 68965b2144..5c2138f6cd 100644 --- a/packages/create-plugin/src/manifest.ts +++ b/packages/create-plugin/src/manifest.ts @@ -1,6 +1,6 @@ "use strict"; -import type { Answers } from "inquirer"; +import type { Answers } from "./qa"; import type { TemplateType } from "./template"; const minimumManifest = { @@ -49,17 +49,20 @@ export interface Manifest { ja?: string; en: string; zh?: string; + es?: string; }; description?: { ja?: string; en: string; zh?: string; + es?: string; }; icon: string; homepage_url?: { ja?: string; en?: string; zh?: string; + es?: string; }; desktop?: { js?: string[]; @@ -88,9 +91,6 @@ const answer2Manifest = (answers: Answers): Manifest => { ) { return acc; } - if (typeof answers[key] === "object" && !Array.isArray(answers[key])) { - return { ...acc, [key]: answer2Manifest(answers[key]) }; - } return { ...acc, ...{ [key]: answers[key] } }; }, {}) as { [key: string]: string }; return Object.keys(filteredAnswer).reduce((acc, key) => { @@ -118,7 +118,7 @@ export const buildManifest = ( ...(templateType === "modern" ? modernManifest : minimumManifest), ...answer2Manifest(answers), }; - if (answers.mobile) { + if (answers.supportMobile) { manifest = { ...manifest, ...{ diff --git a/packages/create-plugin/src/messages.ts b/packages/create-plugin/src/messages.ts index d5ea526623..c6b95b7e20 100644 --- a/packages/create-plugin/src/messages.ts +++ b/packages/create-plugin/src/messages.ts @@ -177,12 +177,12 @@ export const getMessage = ( return messages[key][lang]; }; +export type BoundMessage = (key: keyof MessageMap) => string; + /** * Returns a function bound lang to getMessage * @param lang */ -export const getBoundMessage = ( - lang: keyof LangMap, -): ((key: keyof MessageMap) => string) => { +export const getBoundMessage = (lang: keyof LangMap): BoundMessage => { return getMessage.bind(null, lang); }; diff --git a/packages/create-plugin/src/qa.ts b/packages/create-plugin/src/qa.ts index 7091ef0143..b560566054 100644 --- a/packages/create-plugin/src/qa.ts +++ b/packages/create-plugin/src/qa.ts @@ -1,152 +1,102 @@ "use strict"; -import type { Answers, Question } from "inquirer"; import type { Lang } from "./lang"; -import { getBoundMessage } from "./messages"; +import type { BoundMessage } from "./messages"; +import { + promptForDescription, + promptForEnablePluginUploader, + promptForHomepage, + promptForName, + promptForOptionalDescription, + promptForOptionalName, + promptForSupportLang, + promptForSupportMobile, +} from "./qa/prompt"; -const NAME_MAX_LENGTH = 64; -const DESCRIPTION_MAX_LENGTH = 200; +export type Answers = { + name: { + ja?: string; + en: string; + zh?: string; + es?: string; + }; + description: { + ja?: string; + en: string; + zh?: string; + es?: string; + }; + homepage_url?: { + ja?: string; + en?: string; + zh?: string; + es?: string; + }; + supportMobile: boolean; + enablePluginUploader: boolean; + [key: string]: unknown; +}; -/** - * Build questions for creating a kintone plugin project - * @param outputDir - * @param lang - */ -export const buildQuestions = (outputDir: string, lang: Lang): Question[] => { - const m = getBoundMessage(lang); - return [ - { - type: "input", - name: "name.en", - message: m("Q_NameEn"), - default: outputDir.replace(/.*\//, ""), - validate: (value) => - value.length > 0 && value.length <= NAME_MAX_LENGTH - ? true - : m("Q_NameEnError"), - }, - { - type: "input", - name: "description.en", - message: m("Q_DescriptionEn"), - default: (answers: Answers) => answers.name.en, - validate: (value) => - value.length > 0 && value.length <= DESCRIPTION_MAX_LENGTH - ? true - : m("Q_DescriptionEnError"), - }, - { - type: "confirm", - name: "ja", - default: lang === "ja", - message: m("Q_SupportJa"), - }, - { - type: "input", - name: "name.ja", - when: (answers) => answers.ja, - message: m("Q_NameJa"), - validate: (value) => - value.length === 0 || value.length <= NAME_MAX_LENGTH - ? true - : m("Q_NameJaError"), - }, - { - type: "input", - name: "description.ja", - when: (answers) => answers.ja, - message: m("Q_DescriptionJa"), - validate: (value) => - value.length === 0 || value.length <= DESCRIPTION_MAX_LENGTH - ? true - : m("Q_DescriptionJaError"), - }, - { - type: "confirm", - name: "zh", - default: false, - message: m("Q_SupportZh"), - }, - { - type: "input", - name: "name.zh", - when: (answers) => answers.zh, - message: m("Q_NameZh"), - validate: (value) => - value.length === 0 || value.length <= NAME_MAX_LENGTH - ? true - : m("Q_NameZhError"), - }, - { - type: "input", - name: "description.zh", - when: (answers) => answers.zh, - message: m("Q_DescriptionZh"), - validate: (value) => - value.length === 0 || value.length <= DESCRIPTION_MAX_LENGTH - ? true - : m("Q_DescriptionZhError"), - }, - { - type: "confirm", - name: "es", - default: false, - message: m("Q_SupportEs"), - }, - { - type: "input", - name: "name.es", - when: (answers) => answers.es, - message: m("Q_NameEs"), - validate: (value) => - value.length === 0 || value.length <= NAME_MAX_LENGTH - ? true - : m("Q_NameEsError"), - }, - { - type: "input", - name: "description.es", - when: (answers) => answers.es, - message: m("Q_DescriptionEs"), - validate: (value) => - value.length === 0 || value.length <= DESCRIPTION_MAX_LENGTH - ? true - : m("Q_DescriptionEsError"), - }, - { - type: "input", - name: "homepage_url.en", - message: m("Q_WebsiteUrlEn"), - }, - { - type: "input", - name: "homepage_url.ja", - when: (answers) => answers.ja, - message: m("Q_WebsiteUrlJa"), - }, - { - type: "input", - name: "homepage_url.zh", - when: (answers) => answers.zh, - message: m("Q_WebsiteUrlZh"), - }, - { - type: "input", - name: "homepage_url.es", - when: (answers) => answers.es, - message: m("Q_WebsiteUrlEs"), - }, - { - type: "confirm", - name: "mobile", - default: true, - message: m("Q_MobileSupport"), - }, - { - type: "confirm", - name: "pluginUploader", - default: true, - message: m("Q_EnablePluginUploader"), - }, - ]; +export const getDefaultName = (outputDir: string) => + outputDir.replace(/.*\//, ""); + +export const runPrompt = async ( + m: BoundMessage, + outputDir: string, + lang: Lang, +): Promise => { + const enName = await promptForName(m, "En", getDefaultName(outputDir)); + const enDescription = await promptForDescription(m, "En", enName); + + const supportJa = await promptForSupportLang(m, "Ja", lang === "ja"); + const jaName = supportJa ? await promptForOptionalName(m, "Ja") : undefined; + const jaDescription = supportJa + ? await promptForOptionalDescription(m, "Ja") + : undefined; + + const supportZh = await promptForSupportLang(m, "Zh"); + const zhName = supportZh ? await promptForOptionalName(m, "Zh") : undefined; + const zhDescription = supportZh + ? await promptForOptionalDescription(m, "Zh") + : undefined; + + const supportEs = await promptForSupportLang(m, "Es"); + const esName = supportEs ? await promptForOptionalName(m, "Es") : undefined; + const esDescription = supportEs + ? await promptForOptionalDescription(m, "Es") + : undefined; + + const enHomepage = await promptForHomepage(m, "En"); + const jaHomepage = supportJa ? await promptForHomepage(m, "Ja") : undefined; + const zhHomepage = supportZh ? await promptForHomepage(m, "Zh") : undefined; + const esHomepage = supportEs ? await promptForHomepage(m, "Es") : undefined; + + const supportMobile = await promptForSupportMobile(m); + const enablePluginUploader = await promptForEnablePluginUploader(m); + + const result = { + name: { + en: enName, + ja: jaName, + zh: zhName, + es: esName, + }, + description: { + en: enDescription, + ja: jaDescription, + zh: zhDescription, + es: esDescription, + }, + supportMobile: supportMobile, + enablePluginUploader: enablePluginUploader, + } as Answers; + if (enHomepage) { + result.homepage_url = { + en: enHomepage, + ja: jaHomepage, + zh: zhHomepage, + es: esHomepage, + }; + } + return result; }; diff --git a/packages/create-plugin/src/qa/prompt.ts b/packages/create-plugin/src/qa/prompt.ts new file mode 100644 index 0000000000..ea2de9bb53 --- /dev/null +++ b/packages/create-plugin/src/qa/prompt.ts @@ -0,0 +1,96 @@ +import { confirm, input } from "@inquirer/prompts"; +import type { BoundMessage } from "../messages"; +import { + validateForDescription, + validateForName, + validateForOptionalDescription, + validateForOptionalName, +} from "./validator"; + +export type SupportLang = "En" | "Ja" | "Zh" | "Es"; + +export const promptForName = async ( + m: BoundMessage, + supportLang: SupportLang, + defaultAnswer: string, +) => { + return input({ + message: m(`Q_Name${supportLang}`), + default: defaultAnswer, + validate: (value) => + validateForName(value) ? true : m(`Q_Name${supportLang}Error`), + }); +}; + +export const promptForDescription = async ( + m: BoundMessage, + supportLang: SupportLang, + defaultAnswer: string, +) => { + return input({ + message: m(`Q_Description${supportLang}`), + default: defaultAnswer, + validate: (value) => + validateForDescription(value) + ? true + : m(`Q_Description${supportLang}Error`), + }); +}; + +export const promptForOptionalName = async ( + m: BoundMessage, + supportLang: SupportLang, +) => { + return input({ + message: m(`Q_Name${supportLang}`), + validate: (value) => + validateForOptionalName(value) ? true : m(`Q_Name${supportLang}Error`), + }); +}; + +export const promptForOptionalDescription = async ( + m: BoundMessage, + supportLang: SupportLang, +) => { + return input({ + message: m(`Q_Description${supportLang}`), + validate: (value) => + validateForOptionalDescription(value) + ? true + : m(`Q_Description${supportLang}Error`), + }); +}; + +export const promptForSupportLang = async ( + m: BoundMessage, + supportLang: Exclude, + defaultAnswer: boolean = false, +) => { + return confirm({ + default: defaultAnswer, + message: m(`Q_Support${supportLang}`), + }); +}; + +export const promptForHomepage = async ( + m: BoundMessage, + supportLang: SupportLang, +) => { + return input({ + message: m(`Q_WebsiteUrl${supportLang}`), + }); +}; + +export const promptForSupportMobile = async (m: BoundMessage) => { + return confirm({ + default: true, + message: m("Q_MobileSupport"), + }); +}; + +export const promptForEnablePluginUploader = async (m: BoundMessage) => { + return confirm({ + default: true, + message: m("Q_EnablePluginUploader"), + }); +}; diff --git a/packages/create-plugin/src/qa/validator.ts b/packages/create-plugin/src/qa/validator.ts new file mode 100644 index 0000000000..17c25f89d3 --- /dev/null +++ b/packages/create-plugin/src/qa/validator.ts @@ -0,0 +1,14 @@ +const NAME_MAX_LENGTH = 64; +const DESCRIPTION_MAX_LENGTH = 200; + +export const validateForName = (value: string) => + value.length > 0 && value.length <= NAME_MAX_LENGTH; + +export const validateForDescription = (value: string) => + value.length > 0 && value.length <= DESCRIPTION_MAX_LENGTH; + +export const validateForOptionalName = (value: string) => + value.length === 0 || value.length <= NAME_MAX_LENGTH; + +export const validateForOptionalDescription = (value: string) => + value.length === 0 || value.length <= DESCRIPTION_MAX_LENGTH; diff --git a/packages/customize-uploader/package.json b/packages/customize-uploader/package.json index 72a1b34f1b..95f6e8f752 100644 --- a/packages/customize-uploader/package.json +++ b/packages/customize-uploader/package.json @@ -44,9 +44,9 @@ "@types/inquirer": "8.2.10" }, "dependencies": { + "@inquirer/prompts": "^5.3.7", "@kintone/rest-api-client": "^5.5.2", "chokidar": "^3.6.0", - "inquirer": "^8.2.6", "meow": "^9.0.0", "mkdirp": "^3.0.1", "os-locale": "^5.0.0", diff --git a/packages/customize-uploader/src/messages.ts b/packages/customize-uploader/src/messages.ts index bc3b88b5fb..bfa40ba3f2 100755 --- a/packages/customize-uploader/src/messages.ts +++ b/packages/customize-uploader/src/messages.ts @@ -104,12 +104,12 @@ export const getMessage = (lang: Lang, key: keyof typeof messages) => { return messages[key][lang]; }; +export type BoundMessage = (key: keyof typeof messages) => string; + /** * Returns a function bound lang to getMessage * @param lang */ -export const getBoundMessage = ( - lang: Lang, -): ((key: keyof typeof messages) => string) => { +export const getBoundMessage = (lang: Lang): BoundMessage => { return (key) => getMessage(lang, key); }; diff --git a/packages/customize-uploader/src/params/index.ts b/packages/customize-uploader/src/params/index.ts index 715749c765..71b0fedaf9 100755 --- a/packages/customize-uploader/src/params/index.ts +++ b/packages/customize-uploader/src/params/index.ts @@ -1,6 +1,10 @@ -import * as inquirer from "inquirer"; import type { Lang } from "../lang"; import { getBoundMessage } from "../messages"; +import { + promptForBaseUrl, + promptForPassword, + promptForUsername, +} from "./prompts"; interface Params { username?: string; @@ -10,7 +14,9 @@ interface Params { lang: Lang; } -export const inquireParams = ({ +const isSet = (v: string | null | undefined) => typeof v === "string"; + +export const inquireParams = async ({ username, password, baseUrl, @@ -18,36 +24,21 @@ export const inquireParams = ({ oAuthToken, }: Params) => { const m = getBoundMessage(lang); - const questions = [ - { - type: "input", - message: m("Q_BaseUrl"), - name: "baseUrl", - default: baseUrl, - when: () => !baseUrl, - validate: (v: string) => !!v, - }, - { - type: "input", - name: "username", - message: m("Q_UserName"), - default: username, - when: () => !oAuthToken && !username, - validate: (v: string) => !!v, - }, - { - type: "password", - name: "password", - message: m("Q_Password"), - default: password, - when: () => !oAuthToken && !password, - validate: (v: string) => !!v, - }, - ]; + const _baseUrl = isSet(baseUrl) ? baseUrl : await promptForBaseUrl(m); + const _username = + isSet(oAuthToken) || isSet(username) + ? username + : await promptForUsername(m); + const _password = + isSet(oAuthToken) || isSet(password) + ? password + : await promptForPassword(m); - return inquirer - .prompt(questions) - .then((answers) => Object.assign({ username, password, baseUrl }, answers)); + return { + username: _username, + password: _password, + baseUrl: _baseUrl, + }; }; export * from "./init"; diff --git a/packages/customize-uploader/src/params/init.ts b/packages/customize-uploader/src/params/init.ts index f2a8ec603c..1a9ff90c74 100755 --- a/packages/customize-uploader/src/params/init.ts +++ b/packages/customize-uploader/src/params/init.ts @@ -1,27 +1,10 @@ -import * as inquirer from "inquirer"; import type { Lang } from "../lang"; import { getBoundMessage } from "../messages"; +import { promptForAppId, promptForScope } from "./prompts/init"; -export const inquireInitParams = (lang: Lang) => { - const appId: string = ""; - const scope: string = ""; +export const inquireInitParams = async (lang: Lang) => { const m = getBoundMessage(lang); - const questions = [ - { - type: "input", - message: m("Q_AppId"), - name: "appId", - validate: (v: string) => !!v, - }, - { - type: "list", - message: m("Q_Scope"), - name: "scope", - choices: ["ALL", "ADMIN", "NONE"], - }, - ]; - - return inquirer - .prompt(questions) - .then((answers) => Object.assign({ appId, scope, lang }, answers)); + const appId = await promptForAppId(m); + const scope = await promptForScope(m); + return { appId, scope, lang }; }; diff --git a/packages/customize-uploader/src/params/prompts/index.ts b/packages/customize-uploader/src/params/prompts/index.ts new file mode 100644 index 0000000000..775f34036d --- /dev/null +++ b/packages/customize-uploader/src/params/prompts/index.ts @@ -0,0 +1,37 @@ +import { input } from "@inquirer/prompts"; +import type { BoundMessage } from "../../messages"; + +const validateForString = (v: string) => !!v; + +export const promptForBaseUrl = async ( + m: BoundMessage, + defaultAnswer?: string, +) => { + return input({ + message: m("Q_BaseUrl"), + default: defaultAnswer, + validate: validateForString, + }); +}; + +export const promptForUsername = async ( + m: BoundMessage, + defaultAnswer?: string, +) => { + return input({ + message: m("Q_UserName"), + default: defaultAnswer, + validate: validateForString, + }); +}; + +export const promptForPassword = async ( + m: BoundMessage, + defaultAnswer?: string, +) => { + return input({ + message: m("Q_UserName"), + default: defaultAnswer, + validate: validateForString, + }); +}; diff --git a/packages/customize-uploader/src/params/prompts/init.ts b/packages/customize-uploader/src/params/prompts/init.ts new file mode 100644 index 0000000000..e58bd449fa --- /dev/null +++ b/packages/customize-uploader/src/params/prompts/init.ts @@ -0,0 +1,22 @@ +import { input, select } from "@inquirer/prompts"; +import type { BoundMessage } from "../../messages"; + +const validateForAppId = (v: string) => !!v; + +export const promptForAppId = async (m: BoundMessage) => { + return input({ + message: m("Q_AppId"), + validate: validateForAppId, + }); +}; + +export const promptForScope = async (m: BoundMessage) => { + return select({ + message: m("Q_Scope"), + choices: [ + { name: "ALL", value: "ALL" }, + { name: "ADMIN", value: "ADMIN" }, + { name: "NONE", value: "NONE" }, + ], + }); +}; diff --git a/packages/plugin-uploader/package.json b/packages/plugin-uploader/package.json index 6ffee6d25f..1910a74c0f 100644 --- a/packages/plugin-uploader/package.json +++ b/packages/plugin-uploader/package.json @@ -41,8 +41,8 @@ }, "homepage": "https://github.com/kintone/js-sdk/tree/main/packages/plugin-uploader#readme", "dependencies": { + "@inquirer/prompts": "^5.3.7", "chalk": "^4.1.2", - "inquirer": "^8.2.6", "meow": "^9.0.0", "os-locale": "^5.0.0", "puppeteer": "^23.1.0" diff --git a/packages/plugin-uploader/src/params.ts b/packages/plugin-uploader/src/params.ts index 7dc91b9452..4d78f6cac2 100644 --- a/packages/plugin-uploader/src/params.ts +++ b/packages/plugin-uploader/src/params.ts @@ -1,6 +1,10 @@ -import * as inquirer from "inquirer"; import type { Lang } from "./lang"; import { getBoundMessage } from "./messages"; +import { + promptForBaseUrl, + promptForPassword, + promptForUsername, +} from "./prompts/params"; interface Params { username?: string; @@ -9,6 +13,8 @@ interface Params { lang: Lang; } +const isSet = (v: string | null | undefined) => typeof v === "string"; + export const inquireParams = async ({ username, password, @@ -20,36 +26,14 @@ export const inquireParams = async ({ baseUrl: string; }> => { const m = getBoundMessage(lang); - const questions: inquirer.Question[] = [ - { - type: "input", - message: m("Q_BaseUrl"), - name: "baseUrl", - default: baseUrl, - when: () => !baseUrl, - validate: (v: string) => !!v, - }, - { - type: "input", - name: "username", - message: m("Q_UserName"), - default: username, - when: () => !username, - validate: (v: string) => !!v, - }, - { - type: "password", - name: "password", - message: m("Q_Password"), - default: password, - when: () => !password, - validate: (v: string) => !!v, - }, - ]; - return inquirer.prompt(questions).then((answers) => ({ - username: answers.username ?? username, - password: answers.password ?? password, - baseUrl: answers.baseUrl ?? baseUrl, - })); + const _baseUrl = isSet(baseUrl) ? baseUrl : await promptForBaseUrl(m); + const _username = isSet(username) ? username : await promptForUsername(m); + const _password = isSet(password) ? password : await promptForPassword(m); + + return { + baseUrl: _baseUrl, + username: _username, + password: _password, + }; }; diff --git a/packages/plugin-uploader/src/prompts/params.ts b/packages/plugin-uploader/src/prompts/params.ts new file mode 100644 index 0000000000..136ae10fef --- /dev/null +++ b/packages/plugin-uploader/src/prompts/params.ts @@ -0,0 +1,37 @@ +import { input } from "@inquirer/prompts"; +import type { BoundMessage } from "../messages"; + +const validateForString = (v: string) => !!v; + +export const promptForBaseUrl = async ( + m: BoundMessage, + defaultAnswer?: string, +) => { + return input({ + message: m("Q_BaseUrl"), + default: defaultAnswer, + validate: validateForString, + }); +}; + +export const promptForUsername = async ( + m: BoundMessage, + defaultAnswer?: string, +) => { + return input({ + message: m("Q_UserName"), + default: defaultAnswer, + validate: validateForString, + }); +}; + +export const promptForPassword = async ( + m: BoundMessage, + defaultAnswer?: string, +) => { + return input({ + message: m("Q_Password"), + default: defaultAnswer, + validate: validateForString, + }); +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e7de9a1838..018a7a400c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -71,15 +71,15 @@ importers: packages/create-plugin: dependencies: + '@inquirer/prompts': + specifier: ^5.3.7 + version: 5.3.8 chalk: specifier: ^4.1.2 version: 4.1.2 glob: specifier: ^10.4.5 version: 10.4.5 - inquirer: - specifier: ^8.2.6 - version: 8.2.6 lodash: specifier: ^4.17.21 version: 4.17.21 @@ -129,15 +129,15 @@ importers: packages/customize-uploader: dependencies: + '@inquirer/prompts': + specifier: ^5.3.7 + version: 5.3.8 '@kintone/rest-api-client': specifier: ^5.5.2 version: link:../rest-api-client chokidar: specifier: ^3.6.0 version: 3.6.0 - inquirer: - specifier: ^8.2.6 - version: 8.2.6 meow: specifier: ^9.0.0 version: 9.0.0 @@ -361,12 +361,12 @@ importers: packages/plugin-uploader: dependencies: + '@inquirer/prompts': + specifier: ^5.3.7 + version: 5.3.8 chalk: specifier: ^4.1.2 version: 4.1.2 - inquirer: - specifier: ^8.2.6 - version: 8.2.6 meow: specifier: ^9.0.0 version: 9.0.0 @@ -2206,6 +2206,145 @@ packages: /@humanwhocodes/object-schema@2.0.2: resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} + /@inquirer/checkbox@2.4.7: + resolution: {integrity: sha512-5YwCySyV1UEgqzz34gNsC38eKxRBtlRDpJLlKcRtTjlYA/yDKuc1rfw+hjw+2WJxbAZtaDPsRl5Zk7J14SBoBw==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.0.10 + '@inquirer/figures': 1.0.5 + '@inquirer/type': 1.5.2 + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.2 + dev: false + + /@inquirer/confirm@3.1.22: + resolution: {integrity: sha512-gsAKIOWBm2Q87CDfs9fEo7wJT3fwWIJfnDGMn9Qy74gBnNFOACDNfhUzovubbJjWnKLGBln7/NcSmZwj5DuEXg==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.0.10 + '@inquirer/type': 1.5.2 + dev: false + + /@inquirer/core@9.0.10: + resolution: {integrity: sha512-TdESOKSVwf6+YWDz8GhS6nKscwzkIyakEzCLJ5Vh6O3Co2ClhCJ0A4MG909MUWfaWdpJm7DE45ii51/2Kat9tA==} + engines: {node: '>=18'} + dependencies: + '@inquirer/figures': 1.0.5 + '@inquirer/type': 1.5.2 + '@types/mute-stream': 0.0.4 + '@types/node': 22.1.0 + '@types/wrap-ansi': 3.0.0 + ansi-escapes: 4.3.2 + cli-spinners: 2.9.2 + cli-width: 4.1.0 + mute-stream: 1.0.0 + signal-exit: 4.1.0 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.2 + dev: false + + /@inquirer/editor@2.1.22: + resolution: {integrity: sha512-K1QwTu7GCK+nKOVRBp5HY9jt3DXOfPGPr6WRDrPImkcJRelG9UTx2cAtK1liXmibRrzJlTWOwqgWT3k2XnS62w==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.0.10 + '@inquirer/type': 1.5.2 + external-editor: 3.1.0 + dev: false + + /@inquirer/expand@2.1.22: + resolution: {integrity: sha512-wTZOBkzH+ItPuZ3ZPa9lynBsdMp6kQ9zbjVPYEtSBG7UulGjg2kQiAnUjgyG4SlntpTce5bOmXAPvE4sguXjpA==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.0.10 + '@inquirer/type': 1.5.2 + yoctocolors-cjs: 2.1.2 + dev: false + + /@inquirer/figures@1.0.5: + resolution: {integrity: sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA==} + engines: {node: '>=18'} + dev: false + + /@inquirer/input@2.2.9: + resolution: {integrity: sha512-7Z6N+uzkWM7+xsE+3rJdhdG/+mQgejOVqspoW+w0AbSZnL6nq5tGMEVASaYVWbkoSzecABWwmludO2evU3d31g==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.0.10 + '@inquirer/type': 1.5.2 + dev: false + + /@inquirer/number@1.0.10: + resolution: {integrity: sha512-kWTxRF8zHjQOn2TJs+XttLioBih6bdc5CcosXIzZsrTY383PXI35DuhIllZKu7CdXFi2rz2BWPN9l0dPsvrQOA==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.0.10 + '@inquirer/type': 1.5.2 + dev: false + + /@inquirer/password@2.1.22: + resolution: {integrity: sha512-5Fxt1L9vh3rAKqjYwqsjU4DZsEvY/2Gll+QkqR4yEpy6wvzLxdSgFhUcxfDAOtO4BEoTreWoznC0phagwLU5Kw==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.0.10 + '@inquirer/type': 1.5.2 + ansi-escapes: 4.3.2 + dev: false + + /@inquirer/prompts@5.3.8: + resolution: {integrity: sha512-b2BudQY/Si4Y2a0PdZZL6BeJtl8llgeZa7U2j47aaJSCeAl1e4UI7y8a9bSkO3o/ZbZrgT5muy/34JbsjfIWxA==} + engines: {node: '>=18'} + dependencies: + '@inquirer/checkbox': 2.4.7 + '@inquirer/confirm': 3.1.22 + '@inquirer/editor': 2.1.22 + '@inquirer/expand': 2.1.22 + '@inquirer/input': 2.2.9 + '@inquirer/number': 1.0.10 + '@inquirer/password': 2.1.22 + '@inquirer/rawlist': 2.2.4 + '@inquirer/search': 1.0.7 + '@inquirer/select': 2.4.7 + dev: false + + /@inquirer/rawlist@2.2.4: + resolution: {integrity: sha512-pb6w9pWrm7EfnYDgQObOurh2d2YH07+eDo3xQBsNAM2GRhliz6wFXGi1thKQ4bN6B0xDd6C3tBsjdr3obsCl3Q==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.0.10 + '@inquirer/type': 1.5.2 + yoctocolors-cjs: 2.1.2 + dev: false + + /@inquirer/search@1.0.7: + resolution: {integrity: sha512-p1wpV+3gd1eST/o5N3yQpYEdFNCzSP0Klrl+5bfD3cTTz8BGG6nf4Z07aBW0xjlKIj1Rp0y3x/X4cZYi6TfcLw==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.0.10 + '@inquirer/figures': 1.0.5 + '@inquirer/type': 1.5.2 + yoctocolors-cjs: 2.1.2 + dev: false + + /@inquirer/select@2.4.7: + resolution: {integrity: sha512-JH7XqPEkBpNWp3gPCqWqY8ECbyMoFcCZANlL6pV9hf59qK6dGmkOlx1ydyhY+KZ0c5X74+W6Mtp+nm2QX0/MAQ==} + engines: {node: '>=18'} + dependencies: + '@inquirer/core': 9.0.10 + '@inquirer/figures': 1.0.5 + '@inquirer/type': 1.5.2 + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.2 + dev: false + + /@inquirer/type@1.5.2: + resolution: {integrity: sha512-w9qFkumYDCNyDZmNQjf/n6qQuvQ4dMC3BJesY4oF+yr0CxR5vxujflAVeIcS6U336uzi9GM0kAfZlLrZ9UTkpA==} + engines: {node: '>=18'} + dependencies: + mute-stream: 1.0.0 + dev: false + /@isaacs/cliui@8.0.2: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -3191,6 +3330,12 @@ packages: resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} dev: true + /@types/mute-stream@0.0.4: + resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} + dependencies: + '@types/node': 18.19.45 + dev: false + /@types/node-forge@1.3.11: resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} dependencies: @@ -3213,6 +3358,12 @@ packages: dependencies: undici-types: 5.26.5 + /@types/node@22.1.0: + resolution: {integrity: sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==} + dependencies: + undici-types: 6.13.0 + dev: false + /@types/normalize-package-data@2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} dev: false @@ -3287,6 +3438,10 @@ packages: resolution: {integrity: sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==} dev: true + /@types/wrap-ansi@3.0.0: + resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} + dev: false + /@types/ws@8.5.10: resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} dependencies: @@ -4207,14 +4362,6 @@ packages: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} - /bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - dev: false - /bn.js@4.12.0: resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} dev: true @@ -4573,21 +4720,14 @@ packages: timers-ext: 0.1.7 dev: true - /cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} - dependencies: - restore-cursor: 3.1.0 - dev: false - - /cli-spinners@2.9.0: - resolution: {integrity: sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==} + /cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} dev: false - /cli-width@3.0.0: - resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} - engines: {node: '>= 10'} + /cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} dev: false /cliui@8.0.1: @@ -4607,11 +4747,6 @@ packages: shallow-clone: 3.0.1 dev: true - /clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - dev: false - /co@4.6.0: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} @@ -5201,12 +5336,6 @@ packages: execa: 5.1.1 dev: true - /defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - dependencies: - clone: 1.0.4 - dev: false - /define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} @@ -6442,13 +6571,6 @@ packages: web-streams-polyfill: 3.3.3 dev: true - /figures@3.2.0: - resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} - engines: {node: '>=8'} - dependencies: - escape-string-regexp: 1.0.5 - dev: false - /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -7116,27 +7238,6 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - /inquirer@8.2.6: - resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==} - engines: {node: '>=12.0.0'} - dependencies: - ansi-escapes: 4.3.2 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-width: 3.0.0 - external-editor: 3.1.0 - figures: 3.2.0 - lodash: 4.17.21 - mute-stream: 0.0.8 - ora: 5.4.1 - run-async: 2.4.1 - rxjs: 7.8.1 - string-width: 4.2.3 - strip-ansi: 6.0.1 - through: 2.3.8 - wrap-ansi: 6.2.0 - dev: false - /intelli-espower-loader@1.1.0: resolution: {integrity: sha512-GmnpIM5tRU5n8R4bQAcu2gJMlfRukrtklbE1auRN8qGK9KSLboGdmHSLSLLnIHKrnRmgWRBXNqy5sIOrbT2l8g==} dependencies: @@ -7317,11 +7418,6 @@ packages: dependencies: is-docker: 3.0.0 - /is-interactive@1.0.0: - resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} - engines: {node: '>=8'} - dev: false - /is-map@2.0.2: resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} @@ -7453,11 +7549,6 @@ packages: dependencies: which-typed-array: 1.1.15 - /is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - dev: false - /is-url@1.2.4: resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} dev: true @@ -8290,14 +8381,6 @@ packages: /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - /log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - dev: false - /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -8608,8 +8691,9 @@ packages: thunky: 1.1.0 dev: true - /mute-stream@0.0.8: - resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + /mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dev: false /nanoid@3.3.7: @@ -8896,21 +8980,6 @@ packages: prelude-ls: 1.2.1 type-check: 0.4.0 - /ora@5.4.1: - resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} - engines: {node: '>=10'} - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.9.0 - is-interactive: 1.0.0 - is-unicode-supported: 0.1.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - dev: false - /os-locale@5.0.0: resolution: {integrity: sha512-tqZcNEDAIZKBEPnHPlVDvKrp7NzgLi7jRmhKiUoa2NUmhl13FtkAGLUVR+ZsYvApBQdBfYm43A4tXXQ4IrYLBA==} engines: {node: '>=10'} @@ -9915,6 +9984,7 @@ packages: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 + dev: true /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} @@ -10093,14 +10163,6 @@ packages: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - /restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: false - /retry@0.13.1: resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} engines: {node: '>= 4'} @@ -10222,11 +10284,6 @@ packages: engines: {node: '>=18'} dev: true - /run-async@2.4.1: - resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} - engines: {node: '>=0.12.0'} - dev: false - /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: @@ -10236,6 +10293,7 @@ packages: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} dependencies: tslib: 2.6.0 + dev: true /safe-array-concat@1.0.1: resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} @@ -10261,6 +10319,7 @@ packages: /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true /safe-regex-test@1.0.0: resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} @@ -10497,6 +10556,11 @@ packages: resolution: {integrity: sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==} engines: {node: '>=14'} + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: false + /sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} dev: true @@ -10828,6 +10892,7 @@ packages: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} dependencies: safe-buffer: 5.2.1 + dev: true /stringifier@1.4.0: resolution: {integrity: sha512-cNsMOqqrcbLcHTXEVmkw9y0fwDwkdgtZwlfyolzpQDoAE1xdNGhQhxBUfiDvvZIKl1hnUEgMv66nHwtMz3OjPw==} @@ -11162,6 +11227,7 @@ packages: /tslib@2.6.0: resolution: {integrity: sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==} + dev: true /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} @@ -11328,6 +11394,10 @@ packages: /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + /undici-types@6.13.0: + resolution: {integrity: sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==} + dev: false + /unicode-canonical-property-names-ecmascript@2.0.0: resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} engines: {node: '>=4'} @@ -11432,6 +11502,7 @@ packages: /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true /util@0.12.5: resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} @@ -11547,12 +11618,6 @@ packages: minimalistic-assert: 1.0.1 dev: true - /wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - dependencies: - defaults: 1.0.4 - dev: false - /web-streams-polyfill@3.3.3: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} @@ -12008,6 +12073,11 @@ packages: engines: {node: '>=12.20'} dev: true + /yoctocolors-cjs@2.1.2: + resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} + engines: {node: '>=18'} + dev: false + /zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} dev: false