@taminororo/002-create-cli 1.0.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.
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ // Node.jsのモジュールをインポート
3
+ import fs from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ // カスタムコンソールモジュールをインポート
6
+ import { debug, error, info } from "./console.js";
7
+ console.log('Welcome to the Basic CLI!');
8
+ const helpMessage = 'Usage: basic-cli <file-path> [--out <output-path>] [--debug]';
9
+ // コマンドの引数を取得(0番目はnodeの実行パス、1番目はスクリプトのパスなので省く)
10
+ const args = process.argv.slice(2);
11
+ console.log("デバッグ: 受け取った引数はこれです ->", args);
12
+ // 引数が不足している場合はヘルプメッセージを表示
13
+ if (args.length === 0) {
14
+ info(helpMessage);
15
+ process.exit(1);
16
+ }
17
+ // --- 以下を追加 ---
18
+ let [inputFilePath, ...restArgs] = args;
19
+ console.log("デバッグ: 残りの引数(restArgs)はこれです ->", restArgs);
20
+ console.log("デバッグ: 入力ファイルパス(inputFilePath)はこれです ->", inputFilePath);
21
+ // コマンドの1つ目の引数に、入力ファイルパスが指定されていない場合はエラーにする
22
+ if (!inputFilePath || inputFilePath.startsWith('--')) {
23
+ error('Input file path is required');
24
+ info(helpMessage);
25
+ process.exit(1);
26
+ }
27
+ let outputFilePath = '';
28
+ for (let i = 0; i < restArgs.length; i++) {
29
+ const arg = restArgs[i];
30
+ if (arg === '--out') {
31
+ // --outオプションが指定された場合、次の引数を出力ファイルパスとして取得する
32
+ // 次の引数がない、または次の引数がオプション形式(--で始まる)ならエラーにする
33
+ if (i + 1 >= args.length || restArgs[i + 1].startsWith('--')) {
34
+ error('--out requires a file path');
35
+ process.exit(1);
36
+ }
37
+ outputFilePath = restArgs[++i];
38
+ }
39
+ else if (arg === '--debug') {
40
+ // --debugオプションが指定された場合、デバッグモードを有効にする
41
+ process.env.DEBUG = 'true';
42
+ }
43
+ else {
44
+ error(`Unknown argument: ${arg}`);
45
+ process.exit(1);
46
+ }
47
+ }
48
+ // 入力ファイルを読み込む
49
+ try {
50
+ const absoluteInputPath = path.resolve(inputFilePath);
51
+ const data = (await fs.readFile(absoluteInputPath)).toString();
52
+ debug(`Input file path: ${absoluteInputPath}`);
53
+ debug(`Input file content:\n${data}`);
54
+ const reverseData = data.split("").reverse().join("");
55
+ if (outputFilePath) {
56
+ // 出力ファイルパスが指定されている場合,内容を逆順にしてファイルに書き込む
57
+ const absoluteOutputPath = path.resolve(outputFilePath);
58
+ await fs.writeFile(absoluteOutputPath, reverseData);
59
+ debug('Oputput written to: ${absoluteOutputPath}');
60
+ }
61
+ else {
62
+ // 出力ファイルパスが指定されていない場合,コンソールに出力する
63
+ info(`Reversed file content:\n${reverseData}`);
64
+ }
65
+ }
66
+ catch (err) {
67
+ if (err instanceof Error) {
68
+ error(err.message);
69
+ }
70
+ else {
71
+ error('An unknown error occurred');
72
+ }
73
+ process.exit(1);
74
+ }
@@ -0,0 +1,17 @@
1
+ export function error(message) {
2
+ console.error(`[ERROR] ${message}`);
3
+ }
4
+ export function info(message) {
5
+ console.log(`[INFO] ${message}`);
6
+ }
7
+ export function warn(message) {
8
+ console.warn(`[WARN] ${message}`);
9
+ }
10
+ export function success(message) {
11
+ console.log(`[SUCCESS] ${message}`);
12
+ }
13
+ export function debug(message) {
14
+ if (process.env.DEBUG === 'true') {
15
+ console.log(`[DEBUG] ${message}`);
16
+ }
17
+ }
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import readline from 'node:readline';
5
+ import { debug, error, info } from "./console.js";
6
+ console.log(`Welcome to the Interactice CLI!`);
7
+ // readlineインタフェースを作成する
8
+ // インタフェースは実体みたいなもので、質問を受け取って回答を返す
9
+ const rl = readline.createInterface({
10
+ input: process.stdin,
11
+ output: process.stdout,
12
+ });
13
+ // そもそもコールバックとは何か
14
+ // コールバックは電話をかけ返すこと
15
+ // コールバック関数は,関数に引数として渡される関数
16
+ // Promiseはチケットのようなもの
17
+ // 呼び出す側ではawaitを使ってチケットを待てるようになる
18
+ // 質問を非同期で行う関数を定義する
19
+ function question(query) {
20
+ return new Promise(resolve => rl.question(query, resolve));
21
+ }
22
+ // 以下を追加
23
+ try {
24
+ // それぞれのユーザから入力を受け付ける
25
+ const inputFilePath = await question(`Enter the input file path: `);
26
+ if (!inputFilePath) {
27
+ error(`Input file path is required`);
28
+ rl.close();
29
+ process.exit(1);
30
+ }
31
+ const outputFilePath = await question(`Enter output file path (leave blank to print to console): `);
32
+ const debugMode = await question(`Enable debug mode? (y/N): `);
33
+ if (debugMode.trim().toLowerCase() === 'y') {
34
+ process.env.DEBUG = 'true';
35
+ }
36
+ // basiciCli.tsと処理は一緒
37
+ const absoluteInputPath = path.resolve(inputFilePath);
38
+ const data = (await fs.readFile(absoluteInputPath)).toString();
39
+ debug(`Input file path: ${absoluteInputPath}`);
40
+ debug(`Input file content:\n${data}`);
41
+ const reversedData = data.split('').reverse().join('');
42
+ if (outputFilePath) {
43
+ const absoluteOutputPath = path.resolve(outputFilePath);
44
+ await fs.writeFile(absoluteOutputPath, reversedData);
45
+ debug(`Output written to: ${absoluteOutputPath}`);
46
+ }
47
+ else {
48
+ info(`Reversed file content:\n${reversedData}`);
49
+ }
50
+ // readline インターフェースを閉じる
51
+ rl.close();
52
+ }
53
+ catch (err) {
54
+ if (err instanceof Error) {
55
+ error(err.message);
56
+ }
57
+ else {
58
+ error(`An unknown error occurred`);
59
+ }
60
+ rl.close();
61
+ process.exit(1);
62
+ }
@@ -0,0 +1,6 @@
1
+ import * as readiline from 'node:readline/promises';
2
+ import { stdin as input, stdout as output } from 'node:process';
3
+ const rl = readiline.createInterface({ input, output });
4
+ const answer = await rl.question('What do you think of Node.js? ');
5
+ console.log(`Thank you for your valuable feedback: ${answer}`);
6
+ rl.close();
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@taminororo/002-create-cli",
3
+ "bin": {
4
+ "basic-cli": "dist/basicCli.js",
5
+ "interactive-cli": "dist/interactiveCli.js"
6
+ },
7
+ "version": "1.0.0",
8
+ "description": "",
9
+ "main": "index.js",
10
+ "scripts": {
11
+ "dev": "node --experimental-default-config-file",
12
+ "test": "echo \"Error: no test specified\" && exit 1",
13
+ "typecheck": "tsc --noEmit",
14
+ "build": "tsc"
15
+ },
16
+ "keywords": [],
17
+ "author": "",
18
+ "license": "ISC",
19
+ "type": "module",
20
+ "devDependencies": {
21
+ "@types/node": "^25.0.3",
22
+ "@typescript/native-preview": "^7.0.0-dev.20260109.1",
23
+ "typescript": "^5.9.3"
24
+ },
25
+ "files": [
26
+ "dist"
27
+ ]
28
+ }