@alpacali/papyrus-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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +188 -0
  3. package/dist/api.d.ts +67 -0
  4. package/dist/api.d.ts.map +1 -0
  5. package/dist/api.js +247 -0
  6. package/dist/api.js.map +1 -0
  7. package/dist/cli.d.ts +8 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +391 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/commands/cards.d.ts +52 -0
  12. package/dist/commands/cards.d.ts.map +1 -0
  13. package/dist/commands/cards.js +189 -0
  14. package/dist/commands/cards.js.map +1 -0
  15. package/dist/commands/data.d.ts +34 -0
  16. package/dist/commands/data.d.ts.map +1 -0
  17. package/dist/commands/data.js +230 -0
  18. package/dist/commands/data.js.map +1 -0
  19. package/dist/commands/review.d.ts +16 -0
  20. package/dist/commands/review.d.ts.map +1 -0
  21. package/dist/commands/review.js +132 -0
  22. package/dist/commands/review.js.map +1 -0
  23. package/dist/commands/serve.d.ts +24 -0
  24. package/dist/commands/serve.d.ts.map +1 -0
  25. package/dist/commands/serve.js +161 -0
  26. package/dist/commands/serve.js.map +1 -0
  27. package/dist/config.d.ts +37 -0
  28. package/dist/config.d.ts.map +1 -0
  29. package/dist/config.js +94 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/index.d.ts +10 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +12 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/types.d.ts +114 -0
  36. package/dist/types.d.ts.map +1 -0
  37. package/dist/types.js +5 -0
  38. package/dist/types.js.map +1 -0
  39. package/dist/utils.d.ts +52 -0
  40. package/dist/utils.d.ts.map +1 -0
  41. package/dist/utils.js +141 -0
  42. package/dist/utils.js.map +1 -0
  43. package/package.json +62 -0
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Papyrus CLI - Data Management Commands
3
+ */
4
+ /**
5
+ * Backup command
6
+ */
7
+ export declare function backupCommand(options: {
8
+ output?: string;
9
+ }): Promise<void>;
10
+ /**
11
+ * Restore command
12
+ */
13
+ export declare function restoreCommand(backupPath: string, force?: boolean): Promise<void>;
14
+ /**
15
+ * List backups command
16
+ */
17
+ export declare function listBackupsCommand(): Promise<void>;
18
+ /**
19
+ * Export command
20
+ */
21
+ export declare function exportCommand(output: string): Promise<void>;
22
+ /**
23
+ * Import command
24
+ */
25
+ export declare function importCommand(filePath: string, force?: boolean): Promise<void>;
26
+ /**
27
+ * Stats command
28
+ */
29
+ export declare function statsCommand(): Promise<void>;
30
+ /**
31
+ * Clean old backups command
32
+ */
33
+ export declare function cleanBackupsCommand(keep?: number): Promise<void>;
34
+ //# sourceMappingURL=data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../src/commands/data.ts"],"names":[],"mappings":"AAAA;;GAEG;AA0BH;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA+B/E;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BrF;AAED;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkCxD;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAejE;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAwClF;AAED;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAqBlD;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,SAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAoClE"}
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Papyrus CLI - Data Management Commands
3
+ */
4
+ import { copyFileSync, existsSync, mkdirSync, readdirSync, statSync, unlinkSync } from "fs";
5
+ import { dirname, join, resolve } from "path";
6
+ import { createBackup, exportData, importData } from "../api.js";
7
+ import { getDataDir } from "../config.js";
8
+ import { formatFileSize, readFileSafe } from "../utils.js";
9
+ /**
10
+ * Get database file path
11
+ */
12
+ function getDbPath() {
13
+ return join(getDataDir(), "Papyrusdata.db");
14
+ }
15
+ /**
16
+ * Get backup directory path
17
+ */
18
+ function getBackupDir() {
19
+ const dir = join(getDataDir(), "backups");
20
+ if (!existsSync(dir)) {
21
+ mkdirSync(dir, { recursive: true });
22
+ }
23
+ return dir;
24
+ }
25
+ /**
26
+ * Backup command
27
+ */
28
+ export async function backupCommand(options) {
29
+ try {
30
+ // Try API backup first
31
+ const result = await createBackup();
32
+ console.log(`\nāœ… Backup created via API: ${result.path}`);
33
+ }
34
+ catch {
35
+ // Fallback to local backup
36
+ const dbPath = getDbPath();
37
+ if (!existsSync(dbPath)) {
38
+ console.error("Database not found. Make sure Papyrus is set up correctly.");
39
+ process.exit(1);
40
+ }
41
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
42
+ const backupName = options.output || `papyrus-backup-${timestamp}.db.bak`;
43
+ const backupPath = resolve(backupName);
44
+ // Ensure backup directory exists
45
+ const backupDir = dirname(backupPath);
46
+ if (!existsSync(backupDir)) {
47
+ mkdirSync(backupDir, { recursive: true });
48
+ }
49
+ copyFileSync(dbPath, backupPath);
50
+ const size = statSync(backupPath).size;
51
+ console.log(`\nāœ… Backup created successfully!`);
52
+ console.log(` Path: ${backupPath}`);
53
+ console.log(` Size: ${formatFileSize(size)}`);
54
+ }
55
+ }
56
+ /**
57
+ * Restore command
58
+ */
59
+ export async function restoreCommand(backupPath, force = false) {
60
+ const resolvedPath = resolve(backupPath);
61
+ if (!existsSync(resolvedPath)) {
62
+ console.error(`Backup file not found: ${backupPath}`);
63
+ process.exit(1);
64
+ }
65
+ const dbPath = getDbPath();
66
+ if (!force) {
67
+ const { confirm } = await import("../utils.js");
68
+ const confirmed = await confirm("This will overwrite your current database. Are you sure?");
69
+ if (!confirmed) {
70
+ console.log("Cancelled.");
71
+ return;
72
+ }
73
+ }
74
+ // Create safety backup first
75
+ const safetyBackup = `${dbPath}.safety-${Date.now()}.bak`;
76
+ if (existsSync(dbPath)) {
77
+ copyFileSync(dbPath, safetyBackup);
78
+ console.log(`Safety backup created: ${safetyBackup}`);
79
+ }
80
+ copyFileSync(resolvedPath, dbPath);
81
+ console.log(`\nāœ… Database restored from ${backupPath}`);
82
+ }
83
+ /**
84
+ * List backups command
85
+ */
86
+ export async function listBackupsCommand() {
87
+ const backupDir = getBackupDir();
88
+ if (!existsSync(backupDir)) {
89
+ console.log("No backups found.");
90
+ return;
91
+ }
92
+ const files = readdirSync(backupDir)
93
+ .filter(f => f.endsWith(".bak") || f.endsWith(".db"))
94
+ .map(f => {
95
+ const path = join(backupDir, f);
96
+ const stats = statSync(path);
97
+ return {
98
+ name: f,
99
+ size: stats.size,
100
+ created: stats.birthtime,
101
+ path,
102
+ };
103
+ })
104
+ .sort((a, b) => b.created.getTime() - a.created.getTime());
105
+ if (files.length === 0) {
106
+ console.log("No backups found.");
107
+ return;
108
+ }
109
+ console.log(`\nšŸ“¦ Backups (${files.length}):\n`);
110
+ for (const file of files) {
111
+ console.log(` ${file.name}`);
112
+ console.log(` Size: ${formatFileSize(file.size)}`);
113
+ console.log(` Created: ${file.created.toLocaleString()}`);
114
+ }
115
+ }
116
+ /**
117
+ * Export command
118
+ */
119
+ export async function exportCommand(output) {
120
+ try {
121
+ const data = await exportData();
122
+ const { writeFileSync } = await import("fs");
123
+ const json = JSON.stringify(data, null, 2);
124
+ writeFileSync(resolve(output), json, "utf-8");
125
+ const size = statSync(resolve(output)).size;
126
+ console.log(`\nāœ… Data exported to ${output}`);
127
+ console.log(` Size: ${formatFileSize(size)}`);
128
+ }
129
+ catch (error) {
130
+ console.error(`Export failed: ${error}`);
131
+ process.exit(1);
132
+ }
133
+ }
134
+ /**
135
+ * Import command
136
+ */
137
+ export async function importCommand(filePath, force = false) {
138
+ const resolvedPath = resolve(filePath);
139
+ if (!existsSync(resolvedPath)) {
140
+ console.error(`File not found: ${filePath}`);
141
+ process.exit(1);
142
+ }
143
+ const content = readFileSafe(resolvedPath);
144
+ if (!content) {
145
+ console.error(`Cannot read file: ${filePath}`);
146
+ process.exit(1);
147
+ }
148
+ let data;
149
+ try {
150
+ data = JSON.parse(content);
151
+ }
152
+ catch {
153
+ console.error("Invalid JSON file.");
154
+ process.exit(1);
155
+ }
156
+ if (!force) {
157
+ const { confirm } = await import("../utils.js");
158
+ const confirmed = await confirm("This will import data into your database. Continue?");
159
+ if (!confirmed) {
160
+ console.log("Cancelled.");
161
+ return;
162
+ }
163
+ }
164
+ try {
165
+ await importData(data);
166
+ console.log(`\nāœ… Data imported successfully!`);
167
+ }
168
+ catch (error) {
169
+ console.error(`Import failed: ${error}`);
170
+ process.exit(1);
171
+ }
172
+ }
173
+ /**
174
+ * Stats command
175
+ */
176
+ export async function statsCommand() {
177
+ const dataDir = getDataDir();
178
+ const dbPath = getDbPath();
179
+ console.log("\nšŸ“Š Data Statistics\n");
180
+ console.log(` Data Directory: ${dataDir}`);
181
+ if (existsSync(dbPath)) {
182
+ const stats = statSync(dbPath);
183
+ console.log(` Database Size: ${formatFileSize(stats.size)}`);
184
+ console.log(` Last Modified: ${stats.mtime.toLocaleString()}`);
185
+ }
186
+ else {
187
+ console.log(" Database: Not found");
188
+ }
189
+ // Count backups
190
+ const backupDir = getBackupDir();
191
+ if (existsSync(backupDir)) {
192
+ const backups = readdirSync(backupDir).filter(f => f.endsWith(".bak"));
193
+ console.log(` Backups: ${backups.length}`);
194
+ }
195
+ }
196
+ /**
197
+ * Clean old backups command
198
+ */
199
+ export async function cleanBackupsCommand(keep = 10) {
200
+ const backupDir = getBackupDir();
201
+ if (!existsSync(backupDir)) {
202
+ console.log("No backups to clean.");
203
+ return;
204
+ }
205
+ const files = readdirSync(backupDir)
206
+ .filter(f => f.endsWith(".bak"))
207
+ .map(f => ({
208
+ name: f,
209
+ path: join(backupDir, f),
210
+ created: statSync(join(backupDir, f)).birthtime,
211
+ }))
212
+ .sort((a, b) => b.created.getTime() - a.created.getTime());
213
+ if (files.length <= keep) {
214
+ console.log(`Only ${files.length} backup(s) found. Nothing to clean.`);
215
+ return;
216
+ }
217
+ const toDelete = files.slice(keep);
218
+ console.log(`\n🧹 Cleaning ${toDelete.length} old backup(s)...\n`);
219
+ for (const file of toDelete) {
220
+ try {
221
+ unlinkSync(file.path);
222
+ console.log(` Deleted: ${file.name}`);
223
+ }
224
+ catch (error) {
225
+ console.log(` Failed to delete: ${file.name} (${error})`);
226
+ }
227
+ }
228
+ console.log(`\nāœ… Kept ${keep} most recent backup(s).`);
229
+ }
230
+ //# sourceMappingURL=data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data.js","sourceRoot":"","sources":["../../src/commands/data.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Papyrus CLI - Review Commands
3
+ */
4
+ /**
5
+ * Interactive review session
6
+ */
7
+ export declare function reviewCommand(): Promise<void>;
8
+ /**
9
+ * Quick review (non-interactive)
10
+ */
11
+ export declare function quickReviewCommand(): Promise<void>;
12
+ /**
13
+ * Review stats command
14
+ */
15
+ export declare function reviewStatsCommand(): Promise<void>;
16
+ //# sourceMappingURL=review.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../src/commands/review.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiCH;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAsEnD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAcxD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAyBxD"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Papyrus CLI - Review Commands
3
+ */
4
+ import { getReviewQueue, getReviewStats, submitReview } from "../api.js";
5
+ import { formatRelativeTime, prompt, truncate } from "../utils.js";
6
+ /**
7
+ * Display card for review
8
+ */
9
+ function displayReviewCard(card, index, total) {
10
+ console.clear();
11
+ console.log(`\nšŸ“š Review (${index + 1}/${total})\n`);
12
+ console.log("─".repeat(60));
13
+ console.log(`\nQ: ${card.q}\n`);
14
+ console.log("─".repeat(60));
15
+ console.log("\nPress Enter to reveal answer...\n");
16
+ }
17
+ /**
18
+ * Display answer and rating options
19
+ */
20
+ function displayAnswer(card) {
21
+ console.log("\n" + "═".repeat(60));
22
+ console.log(`\nA: ${card.a}\n`);
23
+ console.log("═".repeat(60));
24
+ console.log("\nRate your recall:");
25
+ console.log(" [1] Again - Complete blackout");
26
+ console.log(" [2] Hard - Incorrect response, remembered");
27
+ console.log(" [3] Good - Correct with difficulty");
28
+ console.log(" [4] Easy - Perfect response");
29
+ console.log(" [q] Quit review session\n");
30
+ }
31
+ /**
32
+ * Interactive review session
33
+ */
34
+ export async function reviewCommand() {
35
+ const queue = await getReviewQueue();
36
+ if (queue.length === 0) {
37
+ console.log("\nšŸŽ‰ No cards are due for review!");
38
+ console.log(" Great job keeping up with your studies.");
39
+ return;
40
+ }
41
+ console.log(`\nšŸ“š Starting review session with ${queue.length} card(s)...\n`);
42
+ let completed = 0;
43
+ let skipped = 0;
44
+ for (let i = 0; i < queue.length; i++) {
45
+ const card = queue[i];
46
+ displayReviewCard(card, i, queue.length);
47
+ // Wait for Enter to reveal
48
+ await prompt("");
49
+ displayAnswer(card);
50
+ // Get rating
51
+ let validInput = false;
52
+ while (!validInput) {
53
+ const input = await prompt("Your rating: ");
54
+ if (input.toLowerCase() === "q") {
55
+ console.log("\nšŸ‘‹ Review session ended.");
56
+ console.log(` Completed: ${completed}, Skipped: ${skipped + queue.length - i}`);
57
+ return;
58
+ }
59
+ const rating = parseInt(input, 10);
60
+ if (rating >= 1 && rating <= 4) {
61
+ // Map 1-4 to SM-2 quality ratings (0-5)
62
+ const quality = rating === 1 ? 0 : rating === 2 ? 3 : rating === 3 ? 4 : 5;
63
+ try {
64
+ await submitReview(card.id, quality);
65
+ completed++;
66
+ validInput = true;
67
+ // Show feedback
68
+ const feedback = rating === 1
69
+ ? "šŸ˜” Don't worry, you'll get it next time!"
70
+ : rating === 2
71
+ ? "😐 Keep practicing!"
72
+ : rating === 3
73
+ ? "šŸ™‚ Good job!"
74
+ : "🌟 Excellent!";
75
+ console.log(`\n ${feedback}`);
76
+ await new Promise(r => setTimeout(r, 1000));
77
+ }
78
+ catch (error) {
79
+ console.error(`\n Error submitting review: ${error}`);
80
+ }
81
+ }
82
+ else {
83
+ console.log(" Please enter 1-4 or q to quit.");
84
+ }
85
+ }
86
+ }
87
+ console.log("\nšŸŽ‰ Review session complete!");
88
+ console.log(` You reviewed ${completed} card(s).`);
89
+ console.log(" Keep up the great work!\n");
90
+ }
91
+ /**
92
+ * Quick review (non-interactive)
93
+ */
94
+ export async function quickReviewCommand() {
95
+ const stats = await getReviewStats();
96
+ console.log("\nšŸ“Š Review Statistics\n");
97
+ console.log(` Total Cards: ${stats.stats.total_cards}`);
98
+ console.log(` Due Today: ${stats.stats.due_today}`);
99
+ console.log(` New Cards: ${stats.stats.new_cards}`);
100
+ console.log(` Review Cards: ${stats.stats.review_cards}`);
101
+ if (stats.stats.due_today > 0) {
102
+ console.log(`\nšŸ’” Run 'papyrus review' to start your review session.`);
103
+ }
104
+ else {
105
+ console.log("\nšŸŽ‰ You're all caught up!");
106
+ }
107
+ }
108
+ /**
109
+ * Review stats command
110
+ */
111
+ export async function reviewStatsCommand() {
112
+ const stats = await getReviewStats();
113
+ console.log("\nšŸ“Š Review Statistics\n");
114
+ console.log(` Total Cards: ${stats.stats.total_cards}`);
115
+ console.log(` Due Today: ${stats.stats.due_today}`);
116
+ console.log(` New Cards: ${stats.stats.new_cards}`);
117
+ console.log(` Review Cards: ${stats.stats.review_cards}`);
118
+ // Get queue for more details
119
+ const queue = await getReviewQueue();
120
+ if (queue.length > 0) {
121
+ console.log(`\nšŸ“š Next ${Math.min(5, queue.length)} cards due:\n`);
122
+ for (let i = 0; i < Math.min(5, queue.length); i++) {
123
+ const card = queue[i];
124
+ console.log(` ${i + 1}. ${truncate(card.q, 45)}`);
125
+ console.log(` Due: ${formatRelativeTime(card.next_review)}`);
126
+ }
127
+ if (queue.length > 5) {
128
+ console.log(`\n ... and ${queue.length - 5} more`);
129
+ }
130
+ }
131
+ }
132
+ //# sourceMappingURL=review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/commands/review.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Papyrus CLI - Server Management Commands
3
+ */
4
+ /**
5
+ * Start server command
6
+ */
7
+ export declare function serveCommand(options: {
8
+ port?: number;
9
+ host?: string;
10
+ detach?: boolean;
11
+ }): Promise<void>;
12
+ /**
13
+ * Check server status
14
+ */
15
+ export declare function statusCommand(): Promise<void>;
16
+ /**
17
+ * Stop server command (if running in background)
18
+ */
19
+ export declare function stopCommand(): Promise<void>;
20
+ /**
21
+ * Open API documentation
22
+ */
23
+ export declare function docsCommand(): Promise<void>;
24
+ //# sourceMappingURL=serve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA;;GAEG;AA6BH;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuEhB;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CA0BnD;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAmBjD;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAkBjD"}
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Papyrus CLI - Server Management Commands
3
+ */
4
+ import { spawn } from "child_process";
5
+ import { existsSync } from "fs";
6
+ import { join, resolve } from "path";
7
+ import { getApiUrl } from "../config.js";
8
+ import { healthCheck, isApiAvailable } from "../api.js";
9
+ /**
10
+ * Find Papyrus project root
11
+ */
12
+ function findPapyrusRoot() {
13
+ // Check common locations
14
+ const candidates = [
15
+ resolve("../Papyrus"),
16
+ resolve("../../Papyrus"),
17
+ join(process.cwd(), "Papyrus"),
18
+ join(process.cwd(), "..", "Papyrus"),
19
+ ];
20
+ for (const candidate of candidates) {
21
+ if (existsSync(join(candidate, "src", "papyrus_api", "main.py"))) {
22
+ return candidate;
23
+ }
24
+ }
25
+ return null;
26
+ }
27
+ /**
28
+ * Start server command
29
+ */
30
+ export async function serveCommand(options) {
31
+ const papyrusRoot = findPapyrusRoot();
32
+ if (!papyrusRoot) {
33
+ console.error("Could not find Papyrus project root.");
34
+ console.error("Make sure Papyrus is installed in the parent directory.");
35
+ process.exit(1);
36
+ }
37
+ const port = options.port || 8000;
38
+ const host = options.host || "127.0.0.1";
39
+ console.log(`Starting Papyrus API server...`);
40
+ console.log(` Root: ${papyrusRoot}`);
41
+ console.log(` Host: ${host}`);
42
+ console.log(` Port: ${port}`);
43
+ const env = {
44
+ ...process.env,
45
+ PYTHONPATH: join(papyrusRoot, "src"),
46
+ };
47
+ const args = [
48
+ "-m", "uvicorn",
49
+ "src.papyrus_api.main:app",
50
+ "--host", host,
51
+ "--port", port.toString(),
52
+ ];
53
+ if (options.detach) {
54
+ // Detached mode - run in background
55
+ const { spawn: spawnWin } = await import("child_process");
56
+ const child = spawnWin("python", args, {
57
+ cwd: papyrusRoot,
58
+ env,
59
+ detached: true,
60
+ stdio: "ignore",
61
+ windowsHide: true,
62
+ });
63
+ child.unref();
64
+ console.log(`\nāœ… Server started in background (PID: ${child.pid})`);
65
+ console.log(` API: http://${host}:${port}`);
66
+ console.log(` Docs: http://${host}:${port}/docs`);
67
+ // Wait a moment and check if it's running
68
+ await new Promise(r => setTimeout(r, 2000));
69
+ if (await isApiAvailable()) {
70
+ console.log(" Status: Running āœ“");
71
+ }
72
+ else {
73
+ console.log(" Status: May have failed to start. Check logs.");
74
+ }
75
+ }
76
+ else {
77
+ // Foreground mode
78
+ console.log(`\nPress Ctrl+C to stop\n`);
79
+ const child = spawn("python", args, {
80
+ cwd: papyrusRoot,
81
+ env,
82
+ stdio: "inherit",
83
+ });
84
+ child.on("close", code => {
85
+ if (code !== 0) {
86
+ console.error(`Server exited with code ${code}`);
87
+ process.exit(code || 1);
88
+ }
89
+ });
90
+ }
91
+ }
92
+ /**
93
+ * Check server status
94
+ */
95
+ export async function statusCommand() {
96
+ console.log("\nšŸ” Papyrus Server Status\n");
97
+ const apiUrl = getApiUrl();
98
+ console.log(` API URL: ${apiUrl}`);
99
+ const available = await isApiAvailable();
100
+ if (available) {
101
+ try {
102
+ const health = await healthCheck();
103
+ console.log(` Status: ${health.status === "ok" ? "āœ… Running" : "āš ļø Unknown"}`);
104
+ // Get additional stats
105
+ const { getReviewStats } = await import("../api.js");
106
+ const stats = await getReviewStats();
107
+ console.log(`\n šŸ“Š Database Stats:`);
108
+ console.log(` Total Cards: ${stats.stats.total_cards}`);
109
+ console.log(` Due Today: ${stats.stats.due_today}`);
110
+ }
111
+ catch {
112
+ console.log(" Status: āš ļø API available but returned error");
113
+ }
114
+ }
115
+ else {
116
+ console.log(" Status: āŒ Not running");
117
+ console.log(`\n Start with: papyrus serve`);
118
+ }
119
+ }
120
+ /**
121
+ * Stop server command (if running in background)
122
+ */
123
+ export async function stopCommand() {
124
+ const { exec } = await import("child_process");
125
+ const { promisify } = await import("util");
126
+ const execAsync = promisify(exec);
127
+ console.log("Stopping Papyrus server...");
128
+ try {
129
+ // Find and kill uvicorn processes
130
+ if (process.platform === "win32") {
131
+ await execAsync(`taskkill /F /IM python.exe /FI "WINDOWTITLE eq uvicorn*"`);
132
+ }
133
+ else {
134
+ await execAsync(`pkill -f "uvicorn.*papyrus_api"`);
135
+ }
136
+ console.log("āœ… Server stopped.");
137
+ }
138
+ catch {
139
+ console.log("Server may not be running or could not be stopped.");
140
+ }
141
+ }
142
+ /**
143
+ * Open API documentation
144
+ */
145
+ export async function docsCommand() {
146
+ const apiUrl = getApiUrl();
147
+ const docsUrl = `${apiUrl}/docs`;
148
+ console.log(`Opening API documentation: ${docsUrl}`);
149
+ const { exec } = await import("child_process");
150
+ const command = process.platform === "win32"
151
+ ? `start "" "${docsUrl}"`
152
+ : process.platform === "darwin"
153
+ ? `open "${docsUrl}"`
154
+ : `xdg-open "${docsUrl}"`;
155
+ exec(command, error => {
156
+ if (error) {
157
+ console.log(`Please open manually: ${docsUrl}`);
158
+ }
159
+ });
160
+ }
161
+ //# sourceMappingURL=serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"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"}