-
Notifications
You must be signed in to change notification settings - Fork 0
20240910 クラス(JavaScript) #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
af9e537
3a6be0e
5cada90
9fb1338
615278a
b652d11
f6c4670
f884a7f
b3e75c7
86921e2
e9a43b2
36d8dd8
38245af
bfa9e8d
2175c99
8fc5a52
f03ccb4
c403443
f92aa83
93db65b
89b6bde
20665ea
f3288c8
c194940
86fe4a9
f5ce052
748d963
9aac457
d5e0e7d
f11b24f
5690b10
be2fa74
2b281ee
3164ab7
66e6ef1
0ca3b85
1ad1a24
bfd1058
5c6bb39
6d30a0c
874405b
3b820c0
8051761
19192a2
b26f70b
c09c1a7
5ce7476
98b82e4
da3d426
8a9f10b
1e9207f
bb2dfa5
6feccac
b58dd99
8417087
67f9782
a87ed58
a038466
8b7d0dc
8acbaa5
5806291
9401114
d519f13
adc2b7d
5389332
5a9d3bf
7b8b2bf
ce0a070
82ceffd
176ed38
5bac5d6
740f2ed
cec5c9d
2399ee4
e988392
d9cc68e
e407227
11101c5
e8603c7
547a645
6e42d3d
7385187
9fbff4a
9e78123
3e0fdb7
ecb8ccc
d5aaae1
68b2cc3
da5a39e
8578808
a1939c3
8ec8247
f0a4c37
24d614a
a4c3d34
29bc0c8
7385c44
5753e3b
dbda513
5e37171
3da8156
04b26b5
e4725e6
3ba39f7
07372dd
91edcb8
4fb6530
75d1487
dfeb341
0d103b4
385c5a4
a7db3b7
4dfcc22
39c7dec
92760af
8cb0312
fbcee09
e5e4ecb
219798e
e3b23f9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| db/memo.db |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| import { stdin as input } from "process"; | ||
| import { createInterface } from "readline"; | ||
|
|
||
| export async function addMemo(database) { | ||
| if (process.stdin.isTTY) { | ||
| console.log( | ||
| "メモの内容を入力してください(保存するにはCtrl+Dを押してください):", | ||
| ); | ||
| } | ||
|
|
||
| let lines; | ||
| try { | ||
| lines = await getInputLines(input); | ||
| } catch (err) { | ||
| if (err.message === "SIGINT") { | ||
| console.log("Ctrl+Cが入力された為メモの作成を中止しました"); | ||
| process.exit(1); | ||
| } | ||
| if (err.code == "ENOMEM") { | ||
| throw err; | ||
| } | ||
| } | ||
|
|
||
| const isBlank = /^\s*$/.test(lines); | ||
| if (isBlank) { | ||
| console.log("メモの内容が空です。"); | ||
| return; | ||
| } | ||
|
|
||
| try { | ||
| await database.insert(lines); | ||
| console.log("メモを追加しました。"); | ||
| } catch (err) { | ||
| console.error(`メモの保存処理中にエラーが発生しました: "${err.message}`); | ||
| process.exit(1); | ||
| } | ||
| } | ||
|
|
||
| function getInputLines(input) { | ||
| return new Promise((resolve, reject) => { | ||
| const rl = createInterface({ | ||
| input, | ||
| }); | ||
| const lines = []; | ||
|
|
||
| rl.on("SIGINT", () => { | ||
| reject(new Error("SIGINT")); | ||
| }); | ||
|
|
||
| rl.on("line", (line) => { | ||
| lines.push(line); | ||
| }); | ||
|
|
||
| rl.on("close", () => { | ||
| resolve(lines.join("\n")); | ||
| }); | ||
|
|
||
| rl.on("error", (err) => { | ||
| reject(err); | ||
| }); | ||
| }); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| import { selectMemo } from "../helpers/memoHelpers.js"; | ||
|
|
||
| export async function deleteMemo(database) { | ||
| const memo = await selectMemo(database, "削除するメモを選んでください:"); | ||
| if (!memo) { | ||
| console.log("メモが存在しません。"); | ||
| return; | ||
| } | ||
| await database.delete(memo.id); | ||
| console.log("メモを削除しました。"); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| export async function listMemos(database) { | ||
| const memos = await database.fetchAll(); | ||
| if (memos.length === 0) { | ||
| console.log("メモが存在しません。"); | ||
| return; | ||
| } | ||
|
|
||
| console.log("メモ一覧:"); | ||
| memos.forEach((memo) => { | ||
| const firstLine = memo.content.split("\n")[0]; | ||
| console.log(`・${firstLine}`); | ||
| }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import { selectMemo } from "../helpers/memoHelpers.js"; | ||
|
|
||
| export async function readMemo(database) { | ||
| const memo = await selectMemo(database, "表示するメモを選んでください:"); | ||
| if (!memo) { | ||
| console.log("メモが存在しません。"); | ||
| return; | ||
| } | ||
| console.log(memo.content); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| export const DATABASE_PATH = "db/memo.db"; | ||
| export const OPTIONS = { | ||
| LIST: "-l", | ||
| READ: "-r", | ||
| DELETE: "-d", | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| import sqlite3 from "sqlite3"; | ||
|
|
||
| export class MemoDatabase { | ||
| #database; | ||
| #databasePath; | ||
|
|
||
| constructor(databasePath = "db/memo.db") { | ||
| this.#databasePath = databasePath; | ||
| } | ||
|
|
||
| async connect() { | ||
| try { | ||
| this.#database = await this.#openDatabase(this.#databasePath); | ||
| } catch (err) { | ||
| throw err; | ||
| } | ||
|
Comment on lines
+14
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. catch したものを throw するだけならそもそも try...catch で処理する意味がないです。#5 (comment) |
||
| } | ||
|
|
||
| async createTable() { | ||
| try { | ||
| await this.#createMemosTable(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @cafedomancer memoDatabase.jsの一部 async connect() {
try {
this.#database = await this.#openDatabase(this.#databasePath);
} catch (err) {
if (err.code === "SQLITE_CANTOPEN" || err.code === "SQLITE_NOTADB") {
throw err;
}
}
}
async createTable() {
try {
await this.#createMemosTable();
} catch (err) {
if (err.code === "SQLITE_ERROR") {
throw err;
}
}
}memo.jsの一部 try {
await memoDatabase.connect();
} catch (err) {
switch (err.code) {
case "SQLITE_CANTOPEN":
console.error(`データベースを開けません: ${err.message}`);
break;
case "SQLITE_NOTADB":
console.error(`データベースファイルではありません: ${err.message}`);
break;
}
return;
}
try {
await memoDatabase.createTable();
} catch (err) {
if (err.code === "SQLITE_ERROR") {
return console.error(`テーブルを作成できません: ${err.message}`);
}
} |
||
| } catch (err) { | ||
| if (err.code === "SQLITE_ERROR") { | ||
| throw err; | ||
| } | ||
|
Comment on lines
+23
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ここも修正が必要です。#5 (comment) |
||
| } | ||
| } | ||
|
|
||
| insert(content) { | ||
| return new Promise((resolve, reject) => { | ||
| this.#database.run( | ||
| "INSERT INTO memos (content) VALUES (?)", | ||
| [content], | ||
| (err) => { | ||
| if (err) { | ||
| reject(err); | ||
| } else { | ||
| resolve(); | ||
| } | ||
| }, | ||
| ); | ||
| }); | ||
| } | ||
|
|
||
| fetchAll() { | ||
| return new Promise((resolve, reject) => { | ||
| this.#database.all( | ||
| "SELECT * FROM memos ORDER BY id DESC", | ||
| (err, rows) => { | ||
| if (err) { | ||
| reject(err); | ||
| } else { | ||
| resolve(rows); | ||
| } | ||
| }, | ||
| ); | ||
| }); | ||
| } | ||
|
|
||
| delete(id) { | ||
| return new Promise((resolve, reject) => { | ||
| this.#database.run("DELETE FROM memos WHERE id = ?", [id], (err) => { | ||
| if (err) { | ||
| reject(err); | ||
| } else { | ||
| resolve(); | ||
| } | ||
| }); | ||
| }); | ||
| } | ||
|
|
||
| #openDatabase(path) { | ||
| return new Promise((resolve, reject) => { | ||
| const db = new sqlite3.Database(path, (err) => { | ||
| if (err) { | ||
| reject(err); | ||
| } else { | ||
| resolve(db); | ||
| } | ||
| }); | ||
| }); | ||
| } | ||
|
|
||
| #createMemosTable() { | ||
| return new Promise((resolve, reject) => { | ||
| this.#database.run( | ||
| "CREATE TABLE IF NOT EXISTS memos (id INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT NOT NULL)", | ||
| (err) => { | ||
| if (err) { | ||
| reject(err); | ||
| } else { | ||
| resolve(); | ||
| } | ||
| }, | ||
| ); | ||
| }); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import inquirer from "inquirer"; | ||
| import { ExitPromptError } from "@inquirer/core"; | ||
|
|
||
| export async function selectMemo(database, message) { | ||
| const memos = await database.fetchAll(); | ||
| if (memos.length === 0) { | ||
| return null; | ||
| } | ||
|
|
||
| const choices = memos.map((memo) => ({ | ||
| name: memo.content.split("\n")[0], | ||
| value: memo, | ||
| })); | ||
|
|
||
| try { | ||
| const answer = await inquirer.prompt([ | ||
| { | ||
| type: "list", | ||
| name: "selectedMemo", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (現状の実装では) 結果として得られるのは memo ではなく memo の id だと思います。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @cafedomancer |
||
| message, | ||
| choices, | ||
| }, | ||
| ]); | ||
|
|
||
| return answer.selectedMemo; | ||
| } catch (error) { | ||
| if (error instanceof ExitPromptError) { | ||
| process.stdout.write("Ctrl+C/Dが入力された為処理を終了させました"); | ||
| process.exit(0); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| #!/usr/bin/env node | ||
|
|
||
| import { MemoDatabase } from "./db/memoDatabase.js"; | ||
| import { DATABASE_PATH, OPTIONS } from "./config/settings.js"; | ||
| import { listMemos } from "./actions/listMemos.js"; | ||
| import { readMemo } from "./actions/readMemo.js"; | ||
| import { deleteMemo } from "./actions/deleteMemo.js"; | ||
| import { addMemo } from "./actions/addMemo.js"; | ||
|
|
||
| async function main() { | ||
| const memoDatabase = new MemoDatabase(DATABASE_PATH); | ||
|
|
||
| try { | ||
| await memoDatabase.connect(); | ||
| } catch (err) { | ||
| if (err.code === "SQLITE_CANTOPEN") { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. この行で |
||
| console.error(`データベースを開けません: ${err.message}`); | ||
| } else if (err.code === "SQLITE_NOTADB") { | ||
| console.error(`データベースファイルではありません: ${err.message}`); | ||
| } else { | ||
| console.error(`データベースに接続できません: ${err.message}`); | ||
| } | ||
| process.exit(1); | ||
| } | ||
|
|
||
| try { | ||
| await memoDatabase.createTable(); | ||
| } catch (err) { | ||
| if (err.code === "SQLITE_ERROR") { | ||
| console.error(`テーブルを作成できません: ${err.message}`); | ||
| } else { | ||
| console.error(`エラーが発生しました: ${err.message}`); | ||
| } | ||
| process.exit(1); | ||
| } | ||
|
|
||
| const args = process.argv.slice(2); | ||
|
|
||
| switch (args[0]) { | ||
| case OPTIONS.LIST: | ||
| await listMemos(memoDatabase); | ||
| break; | ||
| case OPTIONS.READ: | ||
| await readMemo(memoDatabase); | ||
| break; | ||
| case OPTIONS.DELETE: | ||
| await deleteMemo(memoDatabase); | ||
| break; | ||
| default: | ||
| try { | ||
| await addMemo(memoDatabase); | ||
| break; | ||
| } catch (err) { | ||
| if (err.code === "ENOMEM") { | ||
| console.error(`システムのメモリ制限を超過しました: ${err.message}`); | ||
| process.exit(1); | ||
| } | ||
|
Comment on lines
+54
to
+57
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ここで |
||
| } | ||
| } | ||
| } | ||
|
|
||
| main(); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exit する処理は
memo.jsに寄せたほうがよいかと。