昨日、hygenに関する説明としてこちらの記事を作成しました。
https://qiita.com/ikea_shark_jk/items/7cf561af4a107b079d65
その際、_template/<command>/index.js
についてはなくても問題ないとして省略したんですが、流石にサンプルで使っておいて説明しないのはどうなのかと一晩経って思い直したので、今回index.jsを用いた分岐選択肢を作成するまでの流れを解説したいと思います。
作成する分岐のフローチャート
今回は、こちらのフローチャートに応じた質問を生成します。
index.jsで小さな設問を書いてみる
まずは、index.js
でちょっとした質問ができるようにします。
前回の記事でprompt.jsによって設定した、選択肢形式の設問を設置します。
module.exports = {
prompt: ({ prompter }) => {
return prompter
.prompt({
type: "select",
name: "user_name",
message: "What's your name?",
choices: ["foo", "bar", "baz", "ikea_shark"],
})
.then(({ user_name }) => {
return { user_name };
});
},
};
こんな感じのPromiseみを感じる記述をします。
thenの引数は、nameの値です。
$ pnpm hygen sample new
? What's your name? …
❯ foo
bar
baz
ikea_shark
Loaded templates: _templates
added: app/hello.js
単一の設問であれば、こうして作成できます。
次に、2つ以上の質問があるケースを記述します。
prompter.promptを無限に羅列しても良いですが、複数の設問のためにinquirer.prompt
というものが用意されているのでこちらを使用します。
prompter.promptの引数が連想配列なのに対し、inquirer.promptはその連想配列の配列を渡すことで実現できます。
質問順序は、配列の順序に則します。
module.exports = {
prompt: ({ inquirer }) => {
return inquirer
.prompt([
{
type: "select",
name: "user_name",
message: "What's your name?",
choices: ["foo", "bar", "baz", "ikea_shark"],
},
{
type: "select",
name: "js_or_ts",
message: "Javascript or Typescript",
choices: ["Javascript", "Typescript"],
},
])
.then(({ user_name, js_or_ts }) => {
return { user_name, js_or_ts };
});
},
};
$ pnpm hygen sample new
✔ What's your name? · ikea_shark
✔ Javascript or Typescript · Typescript
Loaded templates: _templates
added: app/hello.js
これで、質問を複数設置できました。
もし、設問と設問の間に処理を挟みたい場合は、最後のreturnで値ではなくprompter.promptを渡すことで実現できます。
module.exports = {
prompt: ({ prompter }) => {
return prompter
.prompt({
type: "select",
name: "user_name",
message: "What's your name?",
choices: ["foo", "bar", "baz", "ikea_shark"],
})
.then(({ user_name }) => {
return prompter.prompt({
type: "select",
name: "js_or_user",
message: `Javascript or ${user_name}`,
choices: ["Javascript", user_name],
})
.then(({ js_or_user }) => {
return { user_name, js_or_user }
});
});
},
};
$ pnpm hygen sample new
✔ What's your name? · ikea_shark
✔ Javascript or ikea_shark · ikea_shark
Loaded templates: _templates
added: app/hello.js
これで一通りの書き方がわかりました。
あとは、これらのルールに従ってフローチャートに合わせて記述すれば完成です!
module.exports = {
prompt: ({ prompter, inquirer }) => {
return inquirer
.prompt([
{
type: "select",
name: "js_or_ts",
message: "Javascript or Typescript",
choices: ["Javascript", "Typescript"],
},
{
type: "confirm",
name: "is_next_page",
message: "Is NextPage",
},
])
.then(({ js_or_ts, is_next_page }) => {
if (is_next_page) {
return prompter
.prompt({
type: "confirm",
name: "use_app_dir",
message: "Is this app dir",
})
.then(({ use_app_dir }) => {
const ask_api_or_page = {
type: "select",
name: "api_or_page",
message: "API or Page",
choices: ["API", "Page"],
};
const ask_dir_path = {
type: "input",
name: "dir_path",
message: "what is path",
};
return use_app_dir
? prompter.prompt(ask_dir_path).then(({ dir_path }) => {
return {
api_or_page: null,
dir_path,
use_app_dir,
js_or_ts,
is_next_page,
atomic: null,
component_name: null,
};
})
: inquirer
.prompt([ask_api_or_page, ask_dir_path])
.then(({ api_or_page, dir_path }) => {
return {
api_or_page,
dir_path,
use_app_dir,
js_or_ts,
is_next_page,
atomic: null,
component_name: null,
};
});
});
} else {
return inquirer
.prompt([
{
type: "select",
name: "atomic",
message: "what is atomic design category",
choices: ["atoms", "molecules", "organisms", "templates"],
},
{
type: "input",
name: "component_name",
message: "what is component name",
},
])
.then(({ atomic, component_name }) => {
return {
atomic,
component_name,
js_or_ts,
is_next_page,
api_or_page: null,
dir_path: null,
use_app_dir: null,
};
});
}
});
},
};
実行するとこうなります。
$ pnpm hygen component new
✔ Javascript or Typescript · Typescript
✔ Is NextPage (y/N) · false
✔ what is atomic design category · atoms
✔ what is component name · something_component
Loaded templates: _templates
生成するファイルを選択する
分岐を好きに弄れるようになりましたが、これだけではまだ不足です。
今のままだとファイルの中身は好きにいじれますが、ファイルの生成そのものを操作できません。
なので、任意のファイルを生成する方法を解説します。
とはいったものの、方法はとても簡単です。
---
to: "<%= is_next_page ? `app/hello.js` : null %>"
---
こうやって、テンプレートのto
にnullを渡してあげるとファイルの生成を阻止できます。
これで、分岐内容に応じて好きにファイルを生成できるようになりますね。
注意点として、生成するしないに関係なくテンプレートとなるファイルにindex.js
で返していないkeyが存在する場合はエラーを吐きます。
なので、分岐上にその値が存在しなかったとしても、nullでいいので何かしら値を当てておきましょう。
終わりに
以上で分岐を持つhygenの解説を終わります。
あまりゴリゴリ分岐を増やすとファイルが見にくくなるので、その辺りは自分の心かチームに確認して程よい感じに留めておきましょう。