Closed33

create-babylon-appの開発調査

にー兄さんにー兄さん

babylonjsのscaffoldingsが作りたい
create-vite的に、yarn create viteでプロジェクト作成をする

にー兄さんにー兄さん

こうみるとcreate-viteとコードが似通っていることがわかる
つまりこの構成を参考にすればいいのかな

にー兄さんにー兄さん

やはり時代はAI!()
ということで僕よりも優秀なChatGPT君に質問

create-viteのような、create-babylon-appというBabylon.js向けScaffoldingツールを作りたいのでその方法を教えてくださいと
最初は的外れだったけど、徐々に良さそうな回答をくれた

ディレクトリ構成

create-babylon-app/
  ├── package.json
  ├── bin/
  │   └── create-babylon-app.js
  └── templates/
      └── default/
          ├── index.html
          ├── src/
          │   ├── index.ts
          │   └── game.ts
          ├── package.json
          └── vite.config.ts

index.tsの中身

index.ts
#!/usr/bin/env node

import fs from 'fs';
import path from 'path';
import { promisify } from 'util';
import { program } from 'commander';
import execa from 'execa';

const access = promisify(fs.access);
const mkdir = promisify(fs.mkdir);
const copyFile = promisify(fs.copyFile);

async function copyTemplateFiles(templateDir: string, targetDir: string) {
  const filesToCreate = await fs.promises.readdir(templateDir);

  for (const file of filesToCreate) {
    const origFilePath = path.join(templateDir, file);

    const stats = await fs.promises.stat(origFilePath);

    if (stats.isFile()) {
      const contents = await fs.promises.readFile(origFilePath, 'utf8');
      const writePath = path.join(targetDir, file);
      await fs.promises.writeFile(writePath, contents, 'utf8');
    } else if (stats.isDirectory()) {
      await mkdir(path.join(targetDir, file));
      await copyTemplateFiles(
        path.join(templateDir, file),
        path.join(targetDir, file),
      );
    }
  }
}

program.version('0.0.1');
program.command('init <projectName>').action(async (projectName) => {
  const targetDir = path.join(process.cwd(), projectName);
  try {
    await access(targetDir, fs.constants.R_OK);
    console.error(`Directory ${targetDir} already exists`);
    process.exit(1);
  } catch (error) {
    if (error.code !== 'ENOENT') {
      console.error(error);
      process.exit(1);
    }
  }

  console.log(`Creating a new Babylon.js app in ${targetDir}.`);
  await mkdir(targetDir);

  const templateDir = path.join(__dirname, 'templates', 'babylon-app');
  await copyTemplateFiles(templateDir, targetDir);

  console.log('Installing packages. This might take a couple of minutes.');
  await execa('yarn', ['install'], { cwd: targetDir });

  console.log('App ready');
});

program.parse(process.argv);
にー兄さんにー兄さん

chorkパッケージを使って、babylon-appを使うtsファイル

index.ts
import { createProject } from './createProject';
import { Command } from 'commander';
import chalk from 'chalk';
import inquirer from 'inquirer';

const program = new Command('create-babylon-app');

program
  .version('1.0.0')
  .arguments('<project-name>')
  .action(async (projectName: string) => {
    const { confirm } = await inquirer.prompt([
      {
        type: 'confirm',
        name: 'confirm',
        message: `Create a new Babylon.js project in ${chalk.green(projectName)}?`,
        default: true,
      },
    ]);

    if (confirm) {
      createProject(projectName);
    } else {
      console.log(chalk.yellow('Aborting...'));
    }
  });

program.parse(process.argv);
にー兄さんにー兄さん

知見だなと思ったのが、npmパッケージとして作るCLIをテストする場合
ビルドした後にnpm linkをして、npm create xxxを実行することで動作確認ができるというもの
なるほどな~~~~
npm create xxxってローカルパッケージも含まれるのか

にー兄さんにー兄さん

TypeScript CLI
よりも
nodejs CLI
のほうが検索結果的に合ったものが得られやすいな

にー兄さんにー兄さん

create-babylonも同じような構成でいいのかなと思ってる

  • Project Name
  • Build tool / bundler
    • Vite
    • Webpack
  • variant
    • TypeScript
    • JavaScript
にー兄さんにー兄さん

ビルドフローなどの整備をしていた
現状はビルドにtscを使い、dev実行にはvite-nodeを使用している

にー兄さんにー兄さん

create-viteにならい、./index.jsで./dist/index.mjsを呼ぶ構成にしている

./index.js
import "./dist/index.mjs"
にー兄さんにー兄さん

いったん処理フローなど整理したい感じもするけど、その前にinquirerの使いが手を確認しておくか

にー兄さんにー兄さん

inquirerを入れて簡単なプロンプトの動作確認はできたが、ビルドする際にエラーになってしまっているよう
tsconfig.jsonの設定が悪いのかもしれない

にー兄さんにー兄さん

本日の進捗:

  • フォルダーのコピーができるようになった
  • vite-tsのテンプレを作成して動作できた
にー兄さんにー兄さん

vite-jsのテンプレを用意し、CLIとして完成してきた
package.jsonのnameをProjectNameに変更できるようになり、いよいよ

にー兄さんにー兄さん

だいたい完成してきたので、done is better than perferct ということで速くリリースしたいね
残る作業としては

  • npmへ公開
    • CI/CDの作成
  • READMEの執筆
にー兄さんにー兄さん

ActionsでCIを組んでみたが、なぜかPermission errorで止まる

2023-06-12T15:50:15.3342748Z npm notice Publishing to https://registry.npmjs.org/ with tag latest and default access
2023-06-12T15:50:15.6904028Z npm ERR! code E403
2023-06-12T15:50:15.6922186Z npm ERR! 403 403 Forbidden - PUT https://registry.npmjs.org/create-babylon-app - You may not perform that action with these credentials.
2023-06-12T15:50:15.6923241Z npm ERR! 403 In most cases, you or one of your dependencies are requesting
2023-06-12T15:50:15.6925408Z npm ERR! 403 a package version that is forbidden by your security policy, or
2023-06-12T15:50:15.6926062Z npm ERR! 403 on a server you do not have access to.
2023-06-12T15:50:15.6928441Z 
2023-06-12T15:50:15.6930015Z npm ERR! A complete log of this run can be found in:
2023-06-12T15:50:15.6930841Z npm ERR!     /home/runner/.npm/_logs/2023-06-12T15_50_14_576Z-debug-0.log
このスクラップは2023/06/13にクローズされました