terminal-quest 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.
- package/LICENSE +21 -0
- package/bin/terminal-quest.js +2 -0
- package/dist/App.d.ts +2 -0
- package/dist/App.js +33 -0
- package/dist/components/HintBar.d.ts +9 -0
- package/dist/components/HintBar.js +11 -0
- package/dist/components/MenuItem.d.ts +9 -0
- package/dist/components/MenuItem.js +9 -0
- package/dist/components/ObjectivePanel.d.ts +8 -0
- package/dist/components/ObjectivePanel.js +10 -0
- package/dist/components/ProgressBar.d.ts +8 -0
- package/dist/components/ProgressBar.js +10 -0
- package/dist/components/TerminalOutput.d.ts +11 -0
- package/dist/components/TerminalOutput.js +25 -0
- package/dist/components/TerminalPrompt.d.ts +10 -0
- package/dist/components/TerminalPrompt.js +46 -0
- package/dist/data/commands-meta.d.ts +17 -0
- package/dist/data/commands-meta.js +256 -0
- package/dist/data/stories/00-beginner-pc.d.ts +3 -0
- package/dist/data/stories/00-beginner-pc.js +841 -0
- package/dist/data/stories/01-first-server.d.ts +3 -0
- package/dist/data/stories/01-first-server.js +364 -0
- package/dist/data/stories/02-messy-project.d.ts +3 -0
- package/dist/data/stories/02-messy-project.js +433 -0
- package/dist/data/stories/03-log-detective.d.ts +3 -0
- package/dist/data/stories/03-log-detective.js +291 -0
- package/dist/data/stories/04-deploy-day.d.ts +3 -0
- package/dist/data/stories/04-deploy-day.js +337 -0
- package/dist/data/stories/05-git-incident.d.ts +3 -0
- package/dist/data/stories/05-git-incident.js +534 -0
- package/dist/data/stories/06-pipe-master.d.ts +3 -0
- package/dist/data/stories/06-pipe-master.js +377 -0
- package/dist/data/stories/07-dangerous-commands.d.ts +3 -0
- package/dist/data/stories/07-dangerous-commands.js +411 -0
- package/dist/data/stories/index.d.ts +4 -0
- package/dist/data/stories/index.js +14 -0
- package/dist/data/stories/k1-treasure-hunt.d.ts +3 -0
- package/dist/data/stories/k1-treasure-hunt.js +815 -0
- package/dist/data/types.d.ts +97 -0
- package/dist/data/types.js +2 -0
- package/dist/engine/Achievements.d.ts +5 -0
- package/dist/engine/Achievements.js +93 -0
- package/dist/engine/CommandHandler.d.ts +17 -0
- package/dist/engine/CommandHandler.js +177 -0
- package/dist/engine/HintEngine.d.ts +10 -0
- package/dist/engine/HintEngine.js +26 -0
- package/dist/engine/MissionEngine.d.ts +17 -0
- package/dist/engine/MissionEngine.js +84 -0
- package/dist/engine/TabCompletion.d.ts +14 -0
- package/dist/engine/TabCompletion.js +93 -0
- package/dist/engine/VirtualFS.d.ts +33 -0
- package/dist/engine/VirtualFS.js +276 -0
- package/dist/engine/commands/cat.d.ts +4 -0
- package/dist/engine/commands/cat.js +18 -0
- package/dist/engine/commands/cd.d.ts +4 -0
- package/dist/engine/commands/cd.js +12 -0
- package/dist/engine/commands/chmod.d.ts +4 -0
- package/dist/engine/commands/chmod.js +98 -0
- package/dist/engine/commands/clear.d.ts +4 -0
- package/dist/engine/commands/clear.js +4 -0
- package/dist/engine/commands/cp.d.ts +4 -0
- package/dist/engine/commands/cp.js +26 -0
- package/dist/engine/commands/cut.d.ts +4 -0
- package/dist/engine/commands/cut.js +76 -0
- package/dist/engine/commands/echo.d.ts +4 -0
- package/dist/engine/commands/echo.js +4 -0
- package/dist/engine/commands/find.d.ts +4 -0
- package/dist/engine/commands/find.js +60 -0
- package/dist/engine/commands/git.d.ts +4 -0
- package/dist/engine/commands/git.js +510 -0
- package/dist/engine/commands/grep.d.ts +4 -0
- package/dist/engine/commands/grep.js +127 -0
- package/dist/engine/commands/head.d.ts +4 -0
- package/dist/engine/commands/head.js +59 -0
- package/dist/engine/commands/help.d.ts +4 -0
- package/dist/engine/commands/help.js +32 -0
- package/dist/engine/commands/hint.d.ts +4 -0
- package/dist/engine/commands/hint.js +4 -0
- package/dist/engine/commands/index.d.ts +8 -0
- package/dist/engine/commands/index.js +51 -0
- package/dist/engine/commands/ls.d.ts +4 -0
- package/dist/engine/commands/ls.js +50 -0
- package/dist/engine/commands/man.d.ts +4 -0
- package/dist/engine/commands/man.js +51 -0
- package/dist/engine/commands/mkdir.d.ts +4 -0
- package/dist/engine/commands/mkdir.js +31 -0
- package/dist/engine/commands/mv.d.ts +4 -0
- package/dist/engine/commands/mv.js +15 -0
- package/dist/engine/commands/pwd.d.ts +4 -0
- package/dist/engine/commands/pwd.js +4 -0
- package/dist/engine/commands/rm.d.ts +4 -0
- package/dist/engine/commands/rm.js +49 -0
- package/dist/engine/commands/sort.d.ts +4 -0
- package/dist/engine/commands/sort.js +100 -0
- package/dist/engine/commands/tail.d.ts +4 -0
- package/dist/engine/commands/tail.js +59 -0
- package/dist/engine/commands/touch.d.ts +4 -0
- package/dist/engine/commands/touch.js +18 -0
- package/dist/engine/commands/uniq.d.ts +4 -0
- package/dist/engine/commands/uniq.js +61 -0
- package/dist/engine/commands/wc.d.ts +4 -0
- package/dist/engine/commands/wc.js +67 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +6 -0
- package/dist/screens/MissionBriefScreen.d.ts +9 -0
- package/dist/screens/MissionBriefScreen.js +27 -0
- package/dist/screens/MissionCompleteScreen.d.ts +9 -0
- package/dist/screens/MissionCompleteScreen.js +30 -0
- package/dist/screens/ProgressScreen.d.ts +8 -0
- package/dist/screens/ProgressScreen.js +24 -0
- package/dist/screens/SettingsScreen.d.ts +8 -0
- package/dist/screens/SettingsScreen.js +45 -0
- package/dist/screens/StorySelectScreen.d.ts +8 -0
- package/dist/screens/StorySelectScreen.js +81 -0
- package/dist/screens/TerminalScreen.d.ts +12 -0
- package/dist/screens/TerminalScreen.js +150 -0
- package/dist/screens/TitleScreen.d.ts +7 -0
- package/dist/screens/TitleScreen.js +27 -0
- package/dist/state/GameState.d.ts +8 -0
- package/dist/state/GameState.js +12 -0
- package/dist/state/ProgressStore.d.ts +9 -0
- package/dist/state/ProgressStore.js +45 -0
- package/dist/state/useGameState.d.ts +11 -0
- package/dist/state/useGameState.js +92 -0
- package/dist/utils/ascii-art.d.ts +4 -0
- package/dist/utils/ascii-art.js +22 -0
- package/dist/utils/colors.d.ts +17 -0
- package/dist/utils/colors.js +17 -0
- package/dist/utils/text.d.ts +4 -0
- package/dist/utils/text.js +28 -0
- package/package.json +58 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { homedir } from 'os';
|
|
4
|
+
import { initialProgress } from './GameState.js';
|
|
5
|
+
const SAVE_DIR = join(homedir(), '.terminal-quest');
|
|
6
|
+
const SAVE_FILE = join(SAVE_DIR, 'progress.json');
|
|
7
|
+
export function loadProgress() {
|
|
8
|
+
try {
|
|
9
|
+
if (!existsSync(SAVE_FILE))
|
|
10
|
+
return { ...initialProgress };
|
|
11
|
+
const data = readFileSync(SAVE_FILE, 'utf-8');
|
|
12
|
+
const parsed = JSON.parse(data);
|
|
13
|
+
// Migration: add achievements if missing
|
|
14
|
+
if (!parsed.achievements) {
|
|
15
|
+
parsed.achievements = [];
|
|
16
|
+
}
|
|
17
|
+
return parsed;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return { ...initialProgress };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function saveProgress(progress) {
|
|
24
|
+
try {
|
|
25
|
+
if (!existsSync(SAVE_DIR)) {
|
|
26
|
+
mkdirSync(SAVE_DIR, { recursive: true });
|
|
27
|
+
}
|
|
28
|
+
writeFileSync(SAVE_FILE, JSON.stringify(progress, null, 2), 'utf-8');
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// 保存失敗は無視(ゲーム継続可能)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function resetProgress() {
|
|
35
|
+
saveProgress(initialProgress);
|
|
36
|
+
}
|
|
37
|
+
export function isStoryUnlocked(progress, storyId, allStories) {
|
|
38
|
+
const story = allStories.find(s => s.id === storyId);
|
|
39
|
+
if (!story)
|
|
40
|
+
return false;
|
|
41
|
+
if (story.unlockRequires.length === 0)
|
|
42
|
+
return true;
|
|
43
|
+
return story.unlockRequires.every(reqId => progress.completedStories.includes(reqId));
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=ProgressStore.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { GameProgress, Screen } from '../data/types.js';
|
|
2
|
+
export declare function useGameState(): {
|
|
3
|
+
screen: Screen;
|
|
4
|
+
progress: GameProgress;
|
|
5
|
+
navigateTo: (newScreen: Screen) => void;
|
|
6
|
+
completeMission: (storyId: string, missionId: string, hintsUsed: number) => void;
|
|
7
|
+
completeStory: (storyId: string) => void;
|
|
8
|
+
incrementCommands: () => void;
|
|
9
|
+
resetAll: () => void;
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=useGameState.d.ts.map
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { useState, useCallback, useEffect } from 'react';
|
|
2
|
+
import { initialGameState } from './GameState.js';
|
|
3
|
+
import { loadProgress, saveProgress } from './ProgressStore.js';
|
|
4
|
+
import { checkAchievements } from '../engine/Achievements.js';
|
|
5
|
+
import { stories } from '../data/stories/index.js';
|
|
6
|
+
export function useGameState() {
|
|
7
|
+
const [screen, setScreen] = useState(initialGameState.screen);
|
|
8
|
+
const [progress, setProgress] = useState(() => loadProgress());
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
saveProgress(progress);
|
|
11
|
+
}, [progress]);
|
|
12
|
+
const navigateTo = useCallback((newScreen) => {
|
|
13
|
+
setScreen(newScreen);
|
|
14
|
+
}, []);
|
|
15
|
+
const completeMission = useCallback((storyId, missionId, hintsUsed) => {
|
|
16
|
+
setProgress(prev => {
|
|
17
|
+
const storyProg = prev.storyProgress[storyId] ?? {
|
|
18
|
+
storyId,
|
|
19
|
+
completedMissions: [],
|
|
20
|
+
currentMissionIndex: 0,
|
|
21
|
+
hintsUsed: {},
|
|
22
|
+
};
|
|
23
|
+
if (storyProg.completedMissions.includes(missionId))
|
|
24
|
+
return prev;
|
|
25
|
+
const newCompletedMissions = [...storyProg.completedMissions, missionId];
|
|
26
|
+
const newStoryProg = {
|
|
27
|
+
...storyProg,
|
|
28
|
+
completedMissions: newCompletedMissions,
|
|
29
|
+
currentMissionIndex: storyProg.currentMissionIndex + 1,
|
|
30
|
+
hintsUsed: {
|
|
31
|
+
...storyProg.hintsUsed,
|
|
32
|
+
[missionId]: hintsUsed,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
return {
|
|
36
|
+
...prev,
|
|
37
|
+
storyProgress: {
|
|
38
|
+
...prev.storyProgress,
|
|
39
|
+
[storyId]: newStoryProg,
|
|
40
|
+
},
|
|
41
|
+
totalHintsUsed: prev.totalHintsUsed + hintsUsed,
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
}, []);
|
|
45
|
+
const completeStory = useCallback((storyId) => {
|
|
46
|
+
setProgress(prev => {
|
|
47
|
+
if (prev.completedStories.includes(storyId))
|
|
48
|
+
return prev;
|
|
49
|
+
return {
|
|
50
|
+
...prev,
|
|
51
|
+
completedStories: [...prev.completedStories, storyId],
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
}, []);
|
|
55
|
+
const incrementCommands = useCallback(() => {
|
|
56
|
+
setProgress(prev => ({
|
|
57
|
+
...prev,
|
|
58
|
+
totalCommandsExecuted: prev.totalCommandsExecuted + 1,
|
|
59
|
+
}));
|
|
60
|
+
}, []);
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
const engineerStoryIds = stories
|
|
63
|
+
.filter(s => s.course === 'engineer')
|
|
64
|
+
.map(s => s.id);
|
|
65
|
+
const newAchievements = checkAchievements(progress, engineerStoryIds);
|
|
66
|
+
if (newAchievements.length > 0) {
|
|
67
|
+
setProgress(prev => {
|
|
68
|
+
const currentAchievements = prev.achievements ?? [];
|
|
69
|
+
const toAdd = newAchievements.filter(a => !currentAchievements.includes(a));
|
|
70
|
+
if (toAdd.length === 0)
|
|
71
|
+
return prev;
|
|
72
|
+
return {
|
|
73
|
+
...prev,
|
|
74
|
+
achievements: [...currentAchievements, ...toAdd],
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}, [progress]);
|
|
79
|
+
const resetAll = useCallback(() => {
|
|
80
|
+
setProgress(initialGameState.progress);
|
|
81
|
+
}, []);
|
|
82
|
+
return {
|
|
83
|
+
screen,
|
|
84
|
+
progress,
|
|
85
|
+
navigateTo,
|
|
86
|
+
completeMission,
|
|
87
|
+
completeStory,
|
|
88
|
+
incrementCommands,
|
|
89
|
+
resetAll,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=useGameState.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const titleArt = "\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551 \u2551\n\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2551\n\u2551 \u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551 \u2551\n\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551 \u2551\n\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2551\n\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551 \u2551\n\u2551 \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u2551\n\u2551 \u2551\n\u2551 \u25C6 TERMINAL QUEST \u25C6 \u2551\n\u2551 \uFF5E\u30BF\u30FC\u30DF\u30CA\u30EB\u306E\u5192\u967A\uFF5E \u2551\n\u2551 \u2551\n\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n";
|
|
2
|
+
export declare const missionCompleteArt = "\n \u2605 \u30DF\u30C3\u30B7\u30E7\u30F3\u5B8C\u4E86\uFF01 \u2605\n";
|
|
3
|
+
export declare const storyCompleteArt = "\n \u25C6\u25C6\u25C6 \u30B9\u30C8\u30FC\u30EA\u30FC\u30AF\u30EA\u30A2\uFF01 \u25C6\u25C6\u25C6\n";
|
|
4
|
+
//# sourceMappingURL=ascii-art.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const titleArt = `
|
|
2
|
+
╔══════════════════════════════════════════╗
|
|
3
|
+
║ ║
|
|
4
|
+
║ ████████╗███████╗██████╗ ███╗ ███╗ ║
|
|
5
|
+
║ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║ ║
|
|
6
|
+
║ ██║ █████╗ ██████╔╝██╔████╔██║ ║
|
|
7
|
+
║ ██║ ██╔══╝ ██╔══██╗██║╚██╔╝██║ ║
|
|
8
|
+
║ ██║ ███████╗██║ ██║██║ ╚═╝ ██║ ║
|
|
9
|
+
║ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ║
|
|
10
|
+
║ ║
|
|
11
|
+
║ ◆ TERMINAL QUEST ◆ ║
|
|
12
|
+
║ ~ターミナルの冒険~ ║
|
|
13
|
+
║ ║
|
|
14
|
+
╚══════════════════════════════════════════╝
|
|
15
|
+
`;
|
|
16
|
+
export const missionCompleteArt = `
|
|
17
|
+
★ ミッション完了! ★
|
|
18
|
+
`;
|
|
19
|
+
export const storyCompleteArt = `
|
|
20
|
+
◆◆◆ ストーリークリア! ◆◆◆
|
|
21
|
+
`;
|
|
22
|
+
//# sourceMappingURL=ascii-art.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const colors: {
|
|
2
|
+
primary: string;
|
|
3
|
+
secondary: string;
|
|
4
|
+
error: string;
|
|
5
|
+
warning: string;
|
|
6
|
+
success: string;
|
|
7
|
+
muted: string;
|
|
8
|
+
info: string;
|
|
9
|
+
directory: string;
|
|
10
|
+
file: string;
|
|
11
|
+
prompt: string;
|
|
12
|
+
narrative: string;
|
|
13
|
+
hint1: string;
|
|
14
|
+
hint2: string;
|
|
15
|
+
hint3: string;
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=colors.d.ts.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const colors = {
|
|
2
|
+
primary: '#00D4AA',
|
|
3
|
+
secondary: '#FFD700',
|
|
4
|
+
error: '#FF6B6B',
|
|
5
|
+
warning: '#FFA500',
|
|
6
|
+
success: '#00FF88',
|
|
7
|
+
muted: '#888888',
|
|
8
|
+
info: '#87CEEB',
|
|
9
|
+
directory: '#5FAFFF',
|
|
10
|
+
file: '#FFFFFF',
|
|
11
|
+
prompt: '#00D4AA',
|
|
12
|
+
narrative: '#DDA0DD',
|
|
13
|
+
hint1: '#87CEEB',
|
|
14
|
+
hint2: '#FFD700',
|
|
15
|
+
hint3: '#FF6B6B',
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=colors.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function truncate(text, maxLength) {
|
|
2
|
+
if (text.length <= maxLength)
|
|
3
|
+
return text;
|
|
4
|
+
return text.slice(0, maxLength - 3) + '...';
|
|
5
|
+
}
|
|
6
|
+
export function padRight(text, width) {
|
|
7
|
+
if (text.length >= width)
|
|
8
|
+
return text;
|
|
9
|
+
return text + ' '.repeat(width - text.length);
|
|
10
|
+
}
|
|
11
|
+
export function wrapText(text, maxWidth) {
|
|
12
|
+
const words = text.split(' ');
|
|
13
|
+
const lines = [];
|
|
14
|
+
let currentLine = '';
|
|
15
|
+
for (const word of words) {
|
|
16
|
+
if (currentLine.length + word.length + 1 > maxWidth) {
|
|
17
|
+
lines.push(currentLine);
|
|
18
|
+
currentLine = word;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
currentLine = currentLine ? currentLine + ' ' + word : word;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (currentLine)
|
|
25
|
+
lines.push(currentLine);
|
|
26
|
+
return lines;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=text.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "terminal-quest",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "ストーリー駆動型ターミナルコマンド学習CLI - Learn terminal commands through interactive stories",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"terminal-quest": "bin/terminal-quest.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin/",
|
|
12
|
+
"dist/",
|
|
13
|
+
"!dist/**/*.test.*",
|
|
14
|
+
"!dist/**/*.map",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dev": "tsx src/index.tsx",
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"start": "node dist/index.js",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest",
|
|
23
|
+
"prepublishOnly": "npm run build && npm test"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"terminal",
|
|
27
|
+
"cli",
|
|
28
|
+
"learning",
|
|
29
|
+
"tutorial",
|
|
30
|
+
"command-line",
|
|
31
|
+
"interactive",
|
|
32
|
+
"japanese",
|
|
33
|
+
"education"
|
|
34
|
+
],
|
|
35
|
+
"author": "nasuda",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/nasuda/terminal-quest.git"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://github.com/nasuda/terminal-quest",
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=18"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"ink": "^5.1.0",
|
|
47
|
+
"ink-text-input": "^6.0.0",
|
|
48
|
+
"react": "^18.3.1"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/node": "^25.2.1",
|
|
52
|
+
"@types/react": "^18.3.12",
|
|
53
|
+
"ink-testing-library": "^4.0.0",
|
|
54
|
+
"tsx": "^4.19.2",
|
|
55
|
+
"typescript": "^5.7.2",
|
|
56
|
+
"vitest": "^2.1.8"
|
|
57
|
+
}
|
|
58
|
+
}
|