@xrift/cli 0.1.7 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,20 +4,104 @@ XRift のワールドやアバターをコマンドラインからアップロ
4
4
 
5
5
  ## 機能
6
6
 
7
+ - 新規プロジェクトの作成(テンプレートから)
7
8
  - ブラウザ認証によるログイン
8
9
  - ワールドのアップロード(複数ファイル対応)
9
10
  - 新規作成と更新の自動判定
10
11
  - アップロード進捗の可視化
11
12
 
13
+ ## クイックスタート
14
+
15
+ ```bash
16
+ # 対話式モードで新規プロジェクトを作成(推奨)
17
+ npx @xrift/cli create
18
+
19
+ # または、コマンドラインで指定
20
+ npx @xrift/cli create my-world
21
+
22
+ # プロジェクトに移動(新しいディレクトリに作成した場合)
23
+ cd my-world
24
+
25
+ # 開発サーバーを起動
26
+ npm run dev
27
+
28
+ # ビルド
29
+ npm run build
30
+
31
+ # XRiftにログイン
32
+ npx @xrift/cli login
33
+
34
+ # ワールドをアップロード
35
+ npx @xrift/cli upload world
36
+ ```
37
+
12
38
  ## インストール
13
39
 
40
+ グローバルインストール(オプション):
41
+
14
42
  ```bash
15
43
  npm install -g @xrift/cli
16
44
  ```
17
45
 
46
+ グローバルインストールしない場合は `npx @xrift/cli` で実行できます。
47
+
18
48
  ## 使い方
19
49
 
20
- ### 1. ログイン
50
+ ### 1. 新規プロジェクトを作成
51
+
52
+ テンプレートから新しいワールドプロジェクトを作成します。
53
+
54
+ #### 対話式モード(推奨)
55
+
56
+ 基本的に対話式で、省略されたオプションのみ質問します:
57
+
58
+ ```bash
59
+ # 全て対話式で選択
60
+ npx @xrift/cli create
61
+
62
+ # プロジェクト名だけ指定、残りは対話式
63
+ npx @xrift/cli create my-world
64
+
65
+ # 場所も指定、テンプレートとインストールは対話式
66
+ xrift create my-world --here
67
+
68
+ # グローバルインストール後
69
+ xrift create
70
+ ```
71
+
72
+ 対話式モードでは以下を選択できます:
73
+ - プロジェクト名(省略時)
74
+ - 作成場所(`--here` がない場合)
75
+ - テンプレート(`--template` がない場合)
76
+ - 依存関係のインストール有無(`--skip-install` がない場合)
77
+
78
+ #### 完全自動モード
79
+
80
+ 対話を無効にして、全てコマンドラインで指定することもできます:
81
+
82
+ ```bash
83
+ # 対話なし(プロジェクト名は必須)
84
+ npx @xrift/cli create my-world -y
85
+ npx @xrift/cli create my-world --no-interactive
86
+
87
+ # 全てのオプションを指定
88
+ xrift create my-world --here --template WebXR-JP/custom-template --skip-install -y
89
+ ```
90
+
91
+ **オプション一覧:**
92
+ - `-y, --no-interactive` - 対話式を無効化(CI/スクリプト用)
93
+ - `--here` - カレントディレクトリに作成
94
+ - `-t, --template <repo>` - カスタムテンプレート
95
+ - `--skip-install` - npm install をスキップ
96
+
97
+ 作成されたプロジェクトには以下が含まれます:
98
+ - React Three Fiber + Three.js のセットアップ
99
+ - Rapier 物理エンジンの統合
100
+ - Vite ビルド設定
101
+ - TypeScript 設定
102
+ - 開発用サンプルワールド
103
+
104
+ ### 2. ログイン
21
105
 
22
106
  まず、ブラウザ認証でログインします。
23
107
 
@@ -27,7 +111,7 @@ xrift login
27
111
 
28
112
  ブラウザが自動的に開き、XRift での認証を行います。認証が完了すると、トークンが `~/.xrift/config.json` に保存されます。
29
113
 
30
- ### 2. プロジェクト設定
114
+ ### 3. プロジェクト設定
31
115
 
32
116
  プロジェクトのルートディレクトリに `xrift.json` を作成します。
33
117
 
@@ -41,7 +125,9 @@ xrift login
41
125
 
42
126
  - `distDir`: アップロードするビルド済みファイルが格納されているディレクトリ
43
127
 
44
- ### 3. ワールドをアップロード
128
+ 注:`xrift create` で作成したプロジェクトには自動的に `xrift.json` が含まれています。
129
+
130
+ ### 4. ワールドをアップロード
45
131
 
46
132
  ```bash
47
133
  xrift upload world
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const createCommand: Command;
3
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqDpC,eAAO,MAAM,aAAa,SAqMtB,CAAC"}
@@ -0,0 +1,202 @@
1
+ import { Command } from 'commander';
2
+ import { resolve } from 'path';
3
+ import { access, constants, readdir } from 'fs';
4
+ import chalk from 'chalk';
5
+ import prompts from 'prompts';
6
+ import { downloadTemplate, customizeProject, installDependencies, } from '../lib/template.js';
7
+ /**
8
+ * ファイルまたはディレクトリが存在するかチェック
9
+ */
10
+ async function pathExists(path) {
11
+ try {
12
+ await new Promise((resolve, reject) => {
13
+ access(path, constants.F_OK, (err) => {
14
+ if (err)
15
+ reject(err);
16
+ else
17
+ resolve();
18
+ });
19
+ });
20
+ return true;
21
+ }
22
+ catch {
23
+ return false;
24
+ }
25
+ }
26
+ /**
27
+ * ディレクトリが空かチェック
28
+ */
29
+ async function isDirectoryEmpty(path) {
30
+ return new Promise((resolve, reject) => {
31
+ readdir(path, (err, files) => {
32
+ if (err) {
33
+ reject(err);
34
+ }
35
+ else {
36
+ // .git などの隠しファイルを除外
37
+ const visibleFiles = files.filter((file) => !file.startsWith('.'));
38
+ resolve(visibleFiles.length === 0);
39
+ }
40
+ });
41
+ });
42
+ }
43
+ export const createCommand = new Command('create')
44
+ .argument('[project-name]', 'プロジェクト名(省略時は対話式)')
45
+ .option('-t, --template <repository>', 'テンプレートリポジトリ(例: WebXR-JP/xrift-world-template)', 'WebXR-JP/xrift-test-world')
46
+ .option('--skip-install', '依存関係のインストールをスキップ')
47
+ .option('--here', 'カレントディレクトリに直接作成')
48
+ .option('-y, --no-interactive', '対話式モードを無効化')
49
+ .description('新しいXRiftプロジェクトを作成')
50
+ .action(async (projectName, options) => {
51
+ try {
52
+ // --no-interactive の場合、プロジェクト名が必須
53
+ if (options.interactive === false && !projectName) {
54
+ console.error(chalk.red('\nエラー: --no-interactive を使用する場合はプロジェクト名が必要です'));
55
+ process.exit(1);
56
+ }
57
+ // 対話式モードが必要か判定
58
+ const needsInteraction = options.interactive !== false &&
59
+ (!projectName ||
60
+ options.here === undefined ||
61
+ options.skipInstall === undefined);
62
+ if (needsInteraction) {
63
+ console.log(chalk.cyan('\n✨ XRiftワールドを作成します\n'));
64
+ const questions = [];
65
+ // プロジェクト名が未指定の場合のみ質問
66
+ if (!projectName) {
67
+ questions.push({
68
+ type: 'text',
69
+ name: 'projectName',
70
+ message: 'プロジェクト名を入力してください',
71
+ validate: (value) => /^[a-z0-9-]+$/.test(value)
72
+ ? true
73
+ : '小文字の英数字とハイフンのみ使用できます',
74
+ });
75
+ }
76
+ // 作成場所が未指定の場合のみ質問
77
+ if (options.here === undefined) {
78
+ questions.push({
79
+ type: 'select',
80
+ name: 'location',
81
+ message: 'どこに作成しますか?',
82
+ choices: [
83
+ { title: '新しいディレクトリを作成', value: 'new' },
84
+ { title: 'カレントディレクトリに直接作成', value: 'here' },
85
+ ],
86
+ initial: 0,
87
+ });
88
+ }
89
+ // テンプレートがデフォルトの場合のみ質問
90
+ if (!options.template || options.template === 'WebXR-JP/xrift-test-world') {
91
+ questions.push({
92
+ type: 'select',
93
+ name: 'templateType',
94
+ message: 'テンプレートを選択してください',
95
+ choices: [
96
+ { title: 'デフォルト (WebXR-JP/xrift-test-world)', value: 'default' },
97
+ { title: 'カスタムテンプレート', value: 'custom' },
98
+ ],
99
+ initial: 0,
100
+ });
101
+ questions.push({
102
+ type: (prev) => (prev === 'custom' ? 'text' : null),
103
+ name: 'customTemplate',
104
+ message: 'GitHubリポジトリを入力してください (例: username/repo)',
105
+ validate: (value) => value && value.includes('/')
106
+ ? true
107
+ : '正しい形式で入力してください (username/repo)',
108
+ });
109
+ }
110
+ // インストール有無が未指定の場合のみ質問
111
+ if (options.skipInstall === undefined) {
112
+ questions.push({
113
+ type: 'confirm',
114
+ name: 'install',
115
+ message: '依存関係をインストールしますか?',
116
+ initial: true,
117
+ });
118
+ }
119
+ const response = await prompts(questions);
120
+ // ユーザーがキャンセルした場合
121
+ if (Object.keys(response).length === 0) {
122
+ console.log(chalk.yellow('\n❌ キャンセルされました'));
123
+ process.exit(0);
124
+ }
125
+ // 対話式モードの回答を変数に設定
126
+ if (response.projectName) {
127
+ projectName = response.projectName;
128
+ }
129
+ if (response.location !== undefined) {
130
+ options.here = response.location === 'here';
131
+ }
132
+ if (response.install !== undefined) {
133
+ options.skipInstall = !response.install;
134
+ }
135
+ if (response.templateType === 'custom') {
136
+ options.template = response.customTemplate;
137
+ }
138
+ }
139
+ // この時点で projectName は必ず定義されている
140
+ if (!projectName) {
141
+ console.error(chalk.red('\nエラー: プロジェクト名が指定されていません'));
142
+ process.exit(1);
143
+ }
144
+ console.log(chalk.cyan(`\n✨ XRiftワールドを作成します...\n`));
145
+ // プロジェクト名のバリデーション
146
+ if (!/^[a-z0-9-]+$/.test(projectName)) {
147
+ console.error(chalk.red('エラー: プロジェクト名は小文字の英数字とハイフンのみ使用できます'));
148
+ process.exit(1);
149
+ }
150
+ // プロジェクトパスの設定
151
+ let projectPath;
152
+ if (options.here) {
153
+ // カレントディレクトリに作成
154
+ projectPath = process.cwd();
155
+ // カレントディレクトリが空かチェック
156
+ const isEmpty = await isDirectoryEmpty(projectPath);
157
+ if (!isEmpty) {
158
+ console.log(chalk.yellow('⚠️ カレントディレクトリは空ではありません。既存のファイルは上書きされる可能性があります。'));
159
+ }
160
+ }
161
+ else {
162
+ // 新しいディレクトリを作成
163
+ projectPath = resolve(process.cwd(), projectName);
164
+ // 既存ディレクトリのチェック
165
+ const exists = await pathExists(projectPath);
166
+ if (exists) {
167
+ console.error(chalk.red(`エラー: ディレクトリ "${projectName}" は既に存在します`));
168
+ process.exit(1);
169
+ }
170
+ }
171
+ // テンプレートのダウンロード
172
+ await downloadTemplate(options.template, projectPath);
173
+ // プロジェクトのカスタマイズ
174
+ await customizeProject(projectName, projectPath);
175
+ // 依存関係のインストール
176
+ if (!options.skipInstall) {
177
+ await installDependencies(projectPath);
178
+ }
179
+ // 完了メッセージ
180
+ console.log(chalk.green('\n✅ プロジェクトが作成されました!\n'));
181
+ console.log(chalk.cyan('次のステップ:'));
182
+ if (!options.here) {
183
+ console.log(` ${chalk.yellow(`cd ${projectName}`)}`);
184
+ }
185
+ if (options.skipInstall) {
186
+ console.log(` ${chalk.yellow('npm install')} # 依存関係をインストール`);
187
+ }
188
+ console.log(` ${chalk.yellow('npm run dev')} # 開発サーバー起動`);
189
+ console.log(` ${chalk.yellow('npm run build')} # ビルド`);
190
+ console.log(` ${chalk.yellow('xrift upload world')} # XRiftにアップロード\n`);
191
+ }
192
+ catch (error) {
193
+ if (error instanceof Error) {
194
+ console.error(chalk.red('\nエラー:'), error.message);
195
+ }
196
+ else {
197
+ console.error(chalk.red('\n予期しないエラーが発生しました'));
198
+ }
199
+ process.exit(1);
200
+ }
201
+ });
202
+ //# sourceMappingURL=create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import { Command } from 'commander';
3
3
  import { readFileSync } from 'node:fs';
4
4
  import { fileURLToPath } from 'node:url';
5
5
  import { dirname, join } from 'node:path';
6
+ import { createCommand } from './commands/create.js';
6
7
  import { loginCommand } from './commands/login.js';
7
8
  import { logoutCommand } from './commands/logout.js';
8
9
  import { whoamiCommand } from './commands/whoami.js';
@@ -17,6 +18,7 @@ program
17
18
  .description('XRift CLI - Upload worlds and avatars to XRift')
18
19
  .version(packageJson.version);
19
20
  // Register commands
21
+ program.addCommand(createCommand);
20
22
  program.addCommand(loginCommand);
21
23
  program.addCommand(logoutCommand);
22
24
  program.addCommand(whoamiCommand);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,4BAA4B;AAC5B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAC5B,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAC1D,CAAC;AAEF,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,gDAAgD,CAAC;KAC7D,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAEhC,oBAAoB;AACpB,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAElC,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,4BAA4B;AAC5B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAC5B,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAC1D,CAAC;AAEF,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,gDAAgD,CAAC;KAC7D,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAEhC,oBAAoB;AACpB,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAElC,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * GitHubからテンプレートをダウンロードする
3
+ */
4
+ export declare function downloadTemplate(template: string, destination: string): Promise<void>;
5
+ /**
6
+ * プロジェクトファイルをカスタマイズする
7
+ */
8
+ export declare function customizeProject(projectName: string, projectPath: string): Promise<void>;
9
+ /**
10
+ * 依存関係をインストールする
11
+ */
12
+ export declare function installDependencies(projectPath: string): Promise<void>;
13
+ //# sourceMappingURL=template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/lib/template.ts"],"names":[],"mappings":"AAmBA;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAaf;AAkCD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CA+Bf;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB5E"}
@@ -0,0 +1,118 @@
1
+ import { downloadTemplate as gigetDownload } from 'giget';
2
+ import { readFile, writeFile, access } from 'fs/promises';
3
+ import { constants } from 'fs';
4
+ import { join } from 'path';
5
+ import { spawn } from 'child_process';
6
+ import ora from 'ora';
7
+ /**
8
+ * ファイルまたはディレクトリが存在するかチェック
9
+ */
10
+ async function pathExists(path) {
11
+ try {
12
+ await access(path, constants.F_OK);
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ /**
20
+ * GitHubからテンプレートをダウンロードする
21
+ */
22
+ export async function downloadTemplate(template, destination) {
23
+ const spinner = ora('テンプレートをダウンロード中...').start();
24
+ try {
25
+ await gigetDownload(`github:${template}`, {
26
+ dir: destination,
27
+ force: true, // 既存ディレクトリへの展開を許可
28
+ });
29
+ spinner.succeed('テンプレートをダウンロードしました');
30
+ }
31
+ catch (error) {
32
+ spinner.fail('テンプレートのダウンロードに失敗しました');
33
+ throw error;
34
+ }
35
+ }
36
+ /**
37
+ * プロジェクト名をkebab-caseからsnake_caseに変換
38
+ */
39
+ function toSnakeCase(str) {
40
+ return str.replace(/-/g, '_');
41
+ }
42
+ /**
43
+ * ファイル内の文字列を置換する
44
+ */
45
+ async function replaceInFile(filePath, replacements) {
46
+ const exists = await pathExists(filePath);
47
+ if (!exists) {
48
+ return;
49
+ }
50
+ let content = await readFile(filePath, 'utf-8');
51
+ for (const { from, to } of replacements) {
52
+ if (typeof from === 'string') {
53
+ content = content.split(from).join(to);
54
+ }
55
+ else {
56
+ content = content.replace(from, to);
57
+ }
58
+ }
59
+ await writeFile(filePath, content, 'utf-8');
60
+ }
61
+ /**
62
+ * プロジェクトファイルをカスタマイズする
63
+ */
64
+ export async function customizeProject(projectName, projectPath) {
65
+ const spinner = ora('プロジェクトをカスタマイズ中...').start();
66
+ try {
67
+ const snakeCaseName = toSnakeCase(projectName);
68
+ // package.json を更新
69
+ await replaceInFile(join(projectPath, 'package.json'), [
70
+ { from: '@xrift/test-world', to: `@xrift/${projectName}` },
71
+ { from: '@xrift/world-template', to: `@xrift/${projectName}` },
72
+ { from: '"version": "0.2.1"', to: '"version": "0.1.0"' },
73
+ { from: '"version": "1.0.0"', to: '"version": "0.1.0"' },
74
+ ]);
75
+ // vite.config.ts を更新
76
+ await replaceInFile(join(projectPath, 'vite.config.ts'), [
77
+ { from: 'xrift_test_world', to: `xrift_${snakeCaseName}` },
78
+ { from: 'xrift_world_template', to: `xrift_${snakeCaseName}` },
79
+ ]);
80
+ // index.html を更新
81
+ await replaceInFile(join(projectPath, 'index.html'), [
82
+ { from: '<title>XRift Test World</title>', to: `<title>${projectName}</title>` },
83
+ { from: '<title>XRift World Template</title>', to: `<title>${projectName}</title>` },
84
+ ]);
85
+ spinner.succeed('プロジェクトをカスタマイズしました');
86
+ }
87
+ catch (error) {
88
+ spinner.fail('プロジェクトのカスタマイズに失敗しました');
89
+ throw error;
90
+ }
91
+ }
92
+ /**
93
+ * 依存関係をインストールする
94
+ */
95
+ export async function installDependencies(projectPath) {
96
+ const spinner = ora('依存関係をインストール中...').start();
97
+ return new Promise((resolve, reject) => {
98
+ const npm = spawn('npm', ['install'], {
99
+ cwd: projectPath,
100
+ stdio: 'pipe',
101
+ });
102
+ npm.on('close', (code) => {
103
+ if (code === 0) {
104
+ spinner.succeed('依存関係をインストールしました');
105
+ resolve();
106
+ }
107
+ else {
108
+ spinner.fail('依存関係のインストールに失敗しました');
109
+ reject(new Error(`npm install exited with code ${code}`));
110
+ }
111
+ });
112
+ npm.on('error', (error) => {
113
+ spinner.fail('依存関係のインストールに失敗しました');
114
+ reject(error);
115
+ });
116
+ });
117
+ }
118
+ //# sourceMappingURL=template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.js","sourceRoot":"","sources":["../../src/lib/template.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xrift/cli",
3
- "version": "0.1.7",
3
+ "version": "0.3.0",
4
4
  "description": "XRift CLI tool for world and avatar uploads",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -47,14 +47,17 @@
47
47
  "chalk": "^5.3.0",
48
48
  "cli-progress": "^3.12.0",
49
49
  "commander": "^12.1.0",
50
+ "giget": "^2.0.0",
50
51
  "open": "^10.1.0",
51
- "ora": "^8.1.1"
52
+ "ora": "^8.1.1",
53
+ "prompts": "^2.4.2"
52
54
  },
53
55
  "devDependencies": {
54
56
  "@jest/globals": "^30.2.0",
55
57
  "@types/cli-progress": "^3.11.6",
56
58
  "@types/jest": "^30.0.0",
57
59
  "@types/node": "^22.10.2",
60
+ "@types/prompts": "^2.4.9",
58
61
  "@typescript-eslint/eslint-plugin": "^8.18.1",
59
62
  "@typescript-eslint/parser": "^8.18.1",
60
63
  "eslint": "^9.17.0",