floq 0.1.0 → 0.2.1
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.ja.md +89 -9
- package/README.md +89 -9
- package/dist/changelog.d.ts +13 -0
- package/dist/changelog.js +95 -0
- package/dist/cli.js +44 -1
- package/dist/commands/comment.d.ts +2 -0
- package/dist/commands/comment.js +67 -0
- package/dist/commands/config.d.ts +4 -0
- package/dist/commands/config.js +123 -1
- package/dist/commands/setup.d.ts +1 -0
- package/dist/commands/setup.js +13 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.js +40 -3
- package/dist/db/index.js +20 -0
- package/dist/db/schema.d.ts +83 -0
- package/dist/db/schema.js +6 -0
- package/dist/i18n/en.d.ts +278 -0
- package/dist/i18n/en.js +148 -3
- package/dist/i18n/ja.js +148 -3
- package/dist/index.js +14 -4
- package/dist/paths.d.ts +4 -0
- package/dist/paths.js +63 -5
- package/dist/ui/App.js +320 -37
- package/dist/ui/ModeSelector.d.ts +7 -0
- package/dist/ui/ModeSelector.js +37 -0
- package/dist/ui/SetupWizard.d.ts +6 -0
- package/dist/ui/SetupWizard.js +321 -0
- package/dist/ui/components/HelpModal.d.ts +2 -1
- package/dist/ui/components/HelpModal.js +155 -4
- package/dist/ui/components/KanbanBoard.d.ts +6 -0
- package/dist/ui/components/KanbanBoard.js +498 -0
- package/dist/ui/components/KanbanColumn.d.ts +12 -0
- package/dist/ui/components/KanbanColumn.js +11 -0
- package/dist/ui/components/ProgressBar.d.ts +7 -0
- package/dist/ui/components/ProgressBar.js +13 -0
- package/dist/ui/components/SearchBar.d.ts +8 -0
- package/dist/ui/components/SearchBar.js +11 -0
- package/dist/ui/components/SearchResults.d.ts +9 -0
- package/dist/ui/components/SearchResults.js +18 -0
- package/dist/ui/components/TaskItem.d.ts +6 -1
- package/dist/ui/components/TaskItem.js +3 -2
- package/package.json +1 -1
package/README.ja.md
CHANGED
|
@@ -7,12 +7,16 @@ MS-DOSスタイルのテーマを備えたターミナルベースのGTD(Getti
|
|
|
7
7
|
## 特徴
|
|
8
8
|
|
|
9
9
|
- **TUIインターフェース**: Ink(CLI用React)で構築されたインタラクティブなターミナルUI
|
|
10
|
-
- **GTDワークフロー**: Inbox、Next Actions、Waiting For、Someday/Maybe
|
|
11
|
-
-
|
|
10
|
+
- **GTDワークフロー**: Inbox、Next Actions、Waiting For、Someday/Maybe、Done
|
|
11
|
+
- **カンバンモード**: 3カラムのカンバンボード表示(TODO、Doing、Done)
|
|
12
|
+
- **プロジェクト**: タスクをプロジェクトに整理(進捗バー表示付き)
|
|
13
|
+
- **タスク検索**: `/` キーで全タスクを素早く検索
|
|
14
|
+
- **コメント**: タスクにメモやコメントを追加
|
|
12
15
|
- **クラウド同期**: [Turso](https://turso.tech/)のembedded replicasによるオプションの同期機能
|
|
13
16
|
- **テーマ**: MS-DOSノスタルジックスタイルを含む複数テーマ
|
|
14
17
|
- **多言語対応**: 英語・日本語サポート
|
|
15
18
|
- **Vimスタイルナビゲーション**: hjklまたは矢印キーで操作
|
|
19
|
+
- **セットアップウィザード**: 初回起動時の簡単設定
|
|
16
20
|
|
|
17
21
|
## インストール
|
|
18
22
|
|
|
@@ -38,11 +42,11 @@ npm link
|
|
|
38
42
|
floq
|
|
39
43
|
```
|
|
40
44
|
|
|
41
|
-
###
|
|
45
|
+
### キーボードショートカット(GTDモード)
|
|
42
46
|
|
|
43
47
|
| キー | アクション |
|
|
44
48
|
|------|-----------|
|
|
45
|
-
| `1-
|
|
49
|
+
| `1-6` | タブ切り替え(Inbox/Next/Waiting/Someday/Projects/Done) |
|
|
46
50
|
| `h/l` または `←/→` | 前/次のタブ |
|
|
47
51
|
| `j/k` または `↑/↓` | タスク選択 |
|
|
48
52
|
| `a` | タスク追加 |
|
|
@@ -50,14 +54,75 @@ floq
|
|
|
50
54
|
| `n` | Next Actionsに移動 |
|
|
51
55
|
| `s` | Someday/Maybeに移動 |
|
|
52
56
|
| `i` | Inboxに移動 |
|
|
57
|
+
| `w` | Waiting Forに移動(担当者入力) |
|
|
53
58
|
| `p` | プロジェクトに変換 |
|
|
54
59
|
| `P` | プロジェクトに紐付け |
|
|
55
|
-
| `Enter` |
|
|
56
|
-
| `Esc/b` |
|
|
60
|
+
| `Enter` | タスク詳細を開く / プロジェクトを開く |
|
|
61
|
+
| `Esc/b` | 戻る |
|
|
62
|
+
| `/` | タスク検索 |
|
|
57
63
|
| `r` | 更新 |
|
|
58
64
|
| `?` | ヘルプ |
|
|
59
65
|
| `q` | 終了 |
|
|
60
66
|
|
|
67
|
+
#### プロジェクト詳細画面
|
|
68
|
+
|
|
69
|
+
| キー | アクション |
|
|
70
|
+
|------|-----------|
|
|
71
|
+
| `j/k` | タスク選択 |
|
|
72
|
+
| `a` | プロジェクトにタスク追加 |
|
|
73
|
+
| `d` | タスクを完了にする |
|
|
74
|
+
| `Enter` | タスク詳細を開く |
|
|
75
|
+
| `Esc/b` | プロジェクト一覧に戻る |
|
|
76
|
+
|
|
77
|
+
#### タスク詳細画面
|
|
78
|
+
|
|
79
|
+
| キー | アクション |
|
|
80
|
+
|------|-----------|
|
|
81
|
+
| `i` | コメント追加 |
|
|
82
|
+
| `d` | 選択中のコメントを削除 |
|
|
83
|
+
| `P` | プロジェクトに紐付け |
|
|
84
|
+
| `j/k` | コメント選択 |
|
|
85
|
+
| `Esc/b` | 一覧 / プロジェクトに戻る |
|
|
86
|
+
|
|
87
|
+
### キーボードショートカット(カンバンモード)
|
|
88
|
+
|
|
89
|
+
| キー | アクション |
|
|
90
|
+
|------|-----------|
|
|
91
|
+
| `1-3` | カラム切り替え(TODO/Doing/Done) |
|
|
92
|
+
| `h/l` または `←/→` | 前/次のカラム |
|
|
93
|
+
| `j/k` または `↑/↓` | タスク選択 |
|
|
94
|
+
| `a` | タスク追加 |
|
|
95
|
+
| `d` | 完了にする |
|
|
96
|
+
| `m` | タスクを右に移動(→) |
|
|
97
|
+
| `Backspace` | タスクを左に移動(←) |
|
|
98
|
+
| `Enter` | タスク詳細を開く |
|
|
99
|
+
| `/` | タスク検索 |
|
|
100
|
+
| `r` | 更新 |
|
|
101
|
+
| `?` | ヘルプ |
|
|
102
|
+
| `q` | 終了 |
|
|
103
|
+
|
|
104
|
+
#### タスク詳細画面(カンバン)
|
|
105
|
+
|
|
106
|
+
| キー | アクション |
|
|
107
|
+
|------|-----------|
|
|
108
|
+
| `i` | コメント追加 |
|
|
109
|
+
| `d` | 選択中のコメントを削除 |
|
|
110
|
+
| `j/k` | コメント選択 |
|
|
111
|
+
| `Esc/b` | ボードに戻る |
|
|
112
|
+
|
|
113
|
+
### セットアップウィザード
|
|
114
|
+
|
|
115
|
+
初回起動時、Floqはインタラクティブなセットアップウィザードを起動します:
|
|
116
|
+
- 言語(英語/日本語)
|
|
117
|
+
- テーマ選択
|
|
118
|
+
- 表示モード(GTD/カンバン)
|
|
119
|
+
|
|
120
|
+
手動でウィザードを起動することもできます:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
floq setup
|
|
124
|
+
```
|
|
125
|
+
|
|
61
126
|
### CLIコマンド
|
|
62
127
|
|
|
63
128
|
```bash
|
|
@@ -86,6 +151,10 @@ floq project add "プロジェクト名"
|
|
|
86
151
|
floq project list
|
|
87
152
|
floq project show <id>
|
|
88
153
|
floq project complete <id>
|
|
154
|
+
|
|
155
|
+
# コメント
|
|
156
|
+
floq comment <id> "コメント内容" # コメント追加
|
|
157
|
+
floq comment <id> # コメント一覧
|
|
89
158
|
```
|
|
90
159
|
|
|
91
160
|
## 設定
|
|
@@ -105,9 +174,20 @@ floq config theme
|
|
|
105
174
|
floq config theme modern # デフォルト
|
|
106
175
|
floq config theme synthwave # ネオン80sスタイル
|
|
107
176
|
|
|
177
|
+
# 表示モード設定(インタラクティブセレクター)
|
|
178
|
+
floq config mode
|
|
179
|
+
|
|
180
|
+
# または直接指定
|
|
181
|
+
floq config mode gtd # GTDワークフロー(デフォルト)
|
|
182
|
+
floq config mode kanban # カンバンボード
|
|
183
|
+
|
|
108
184
|
# データベースパス設定
|
|
109
185
|
floq config db /path/to/custom.db
|
|
110
186
|
floq config db # デフォルトに戻す
|
|
187
|
+
|
|
188
|
+
# データベースリセット(全データ削除)
|
|
189
|
+
floq db reset # 確認あり
|
|
190
|
+
floq db reset --force # 確認なし
|
|
111
191
|
```
|
|
112
192
|
|
|
113
193
|
## クラウド同期(Turso)
|
|
@@ -139,7 +219,7 @@ floq config turso --disable
|
|
|
139
219
|
- **Embedded Replicas**: ローカルSQLiteデータベースがTursoクラウドと同期
|
|
140
220
|
- **オフラインサポート**: オフラインでも動作し、接続時に同期
|
|
141
221
|
- **自動同期**: オンライン時は60秒ごとにバックグラウンド同期
|
|
142
|
-
- **データベース分離**: Tursoモードは`
|
|
222
|
+
- **データベース分離**: Tursoモードは`floq-turso.db`を使用し、ローカルDBと競合しない
|
|
143
223
|
|
|
144
224
|
### ステータス表示
|
|
145
225
|
|
|
@@ -173,8 +253,8 @@ floq config turso --disable
|
|
|
173
253
|
|
|
174
254
|
## データ保存場所
|
|
175
255
|
|
|
176
|
-
- 設定: `~/.config/
|
|
177
|
-
- データベース: `~/.local/share/
|
|
256
|
+
- 設定: `~/.config/floq/config.json`
|
|
257
|
+
- データベース: `~/.local/share/floq/floq.db`(Turso有効時は`floq-turso.db`)
|
|
178
258
|
|
|
179
259
|
## ライセンス
|
|
180
260
|
|
package/README.md
CHANGED
|
@@ -7,12 +7,16 @@ A terminal-based GTD (Getting Things Done) task manager with MS-DOS style themes
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- **TUI Interface**: Interactive terminal UI built with Ink (React for CLI)
|
|
10
|
-
- **GTD Workflow**: Inbox, Next Actions, Waiting For, Someday/Maybe
|
|
11
|
-
- **
|
|
10
|
+
- **GTD Workflow**: Inbox, Next Actions, Waiting For, Someday/Maybe, Done
|
|
11
|
+
- **Kanban Mode**: 3-column kanban board view (TODO, Doing, Done)
|
|
12
|
+
- **Projects**: Organize tasks into projects with progress tracking
|
|
13
|
+
- **Task Search**: Quick search across all tasks with `/`
|
|
14
|
+
- **Comments**: Add notes and comments to tasks
|
|
12
15
|
- **Cloud Sync**: Optional sync with [Turso](https://turso.tech/) using embedded replicas
|
|
13
16
|
- **Themes**: Multiple themes including MS-DOS nostalgic styles
|
|
14
17
|
- **i18n**: English and Japanese support
|
|
15
18
|
- **Vim-style Navigation**: Use hjkl or arrow keys
|
|
19
|
+
- **Setup Wizard**: First-run wizard for easy configuration
|
|
16
20
|
|
|
17
21
|
## Installation
|
|
18
22
|
|
|
@@ -38,11 +42,11 @@ npm link
|
|
|
38
42
|
floq
|
|
39
43
|
```
|
|
40
44
|
|
|
41
|
-
### Keyboard Shortcuts
|
|
45
|
+
### Keyboard Shortcuts (GTD Mode)
|
|
42
46
|
|
|
43
47
|
| Key | Action |
|
|
44
48
|
|-----|--------|
|
|
45
|
-
| `1-
|
|
49
|
+
| `1-6` | Switch tabs (Inbox/Next/Waiting/Someday/Projects/Done) |
|
|
46
50
|
| `h/l` or `←/→` | Previous/Next tab |
|
|
47
51
|
| `j/k` or `↑/↓` | Navigate tasks |
|
|
48
52
|
| `a` | Add task |
|
|
@@ -50,14 +54,75 @@ floq
|
|
|
50
54
|
| `n` | Move to Next Actions |
|
|
51
55
|
| `s` | Move to Someday/Maybe |
|
|
52
56
|
| `i` | Move to Inbox |
|
|
57
|
+
| `w` | Move to Waiting For (prompts for person) |
|
|
53
58
|
| `p` | Convert to project |
|
|
54
59
|
| `P` | Link to project |
|
|
55
|
-
| `Enter` | Open
|
|
56
|
-
| `Esc/b` | Back
|
|
60
|
+
| `Enter` | Open task detail / Open project |
|
|
61
|
+
| `Esc/b` | Back |
|
|
62
|
+
| `/` | Search tasks |
|
|
57
63
|
| `r` | Refresh |
|
|
58
64
|
| `?` | Help |
|
|
59
65
|
| `q` | Quit |
|
|
60
66
|
|
|
67
|
+
#### Project Detail View
|
|
68
|
+
|
|
69
|
+
| Key | Action |
|
|
70
|
+
|-----|--------|
|
|
71
|
+
| `j/k` | Navigate tasks |
|
|
72
|
+
| `a` | Add task to project |
|
|
73
|
+
| `d` | Mark task as done |
|
|
74
|
+
| `Enter` | Open task detail |
|
|
75
|
+
| `Esc/b` | Back to projects list |
|
|
76
|
+
|
|
77
|
+
#### Task Detail View
|
|
78
|
+
|
|
79
|
+
| Key | Action |
|
|
80
|
+
|-----|--------|
|
|
81
|
+
| `i` | Add comment |
|
|
82
|
+
| `d` | Delete selected comment |
|
|
83
|
+
| `P` | Link to project |
|
|
84
|
+
| `j/k` | Navigate comments |
|
|
85
|
+
| `Esc/b` | Back to list / project |
|
|
86
|
+
|
|
87
|
+
### Keyboard Shortcuts (Kanban Mode)
|
|
88
|
+
|
|
89
|
+
| Key | Action |
|
|
90
|
+
|-----|--------|
|
|
91
|
+
| `1-3` | Switch columns (TODO/Doing/Done) |
|
|
92
|
+
| `h/l` or `←/→` | Previous/Next column |
|
|
93
|
+
| `j/k` or `↑/↓` | Navigate tasks |
|
|
94
|
+
| `a` | Add task |
|
|
95
|
+
| `d` | Mark as done |
|
|
96
|
+
| `m` | Move task right (→) |
|
|
97
|
+
| `Backspace` | Move task left (←) |
|
|
98
|
+
| `Enter` | Open task detail |
|
|
99
|
+
| `/` | Search tasks |
|
|
100
|
+
| `r` | Refresh |
|
|
101
|
+
| `?` | Help |
|
|
102
|
+
| `q` | Quit |
|
|
103
|
+
|
|
104
|
+
#### Task Detail View (Kanban)
|
|
105
|
+
|
|
106
|
+
| Key | Action |
|
|
107
|
+
|-----|--------|
|
|
108
|
+
| `i` | Add comment |
|
|
109
|
+
| `d` | Delete selected comment |
|
|
110
|
+
| `j/k` | Navigate comments |
|
|
111
|
+
| `Esc/b` | Back to board |
|
|
112
|
+
|
|
113
|
+
### Setup Wizard
|
|
114
|
+
|
|
115
|
+
On first run, Floq will launch an interactive setup wizard to configure:
|
|
116
|
+
- Language (English/Japanese)
|
|
117
|
+
- Theme selection
|
|
118
|
+
- View mode (GTD/Kanban)
|
|
119
|
+
|
|
120
|
+
You can also run the wizard manually:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
floq setup
|
|
124
|
+
```
|
|
125
|
+
|
|
61
126
|
### CLI Commands
|
|
62
127
|
|
|
63
128
|
```bash
|
|
@@ -86,6 +151,10 @@ floq project add "Project name"
|
|
|
86
151
|
floq project list
|
|
87
152
|
floq project show <id>
|
|
88
153
|
floq project complete <id>
|
|
154
|
+
|
|
155
|
+
# Comments
|
|
156
|
+
floq comment <id> "Comment text" # Add comment
|
|
157
|
+
floq comment <id> # List comments
|
|
89
158
|
```
|
|
90
159
|
|
|
91
160
|
## Configuration
|
|
@@ -105,9 +174,20 @@ floq config theme
|
|
|
105
174
|
floq config theme modern # Default
|
|
106
175
|
floq config theme synthwave # Neon 80s aesthetic
|
|
107
176
|
|
|
177
|
+
# Set view mode (interactive selector)
|
|
178
|
+
floq config mode
|
|
179
|
+
|
|
180
|
+
# Or specify directly
|
|
181
|
+
floq config mode gtd # GTD workflow (default)
|
|
182
|
+
floq config mode kanban # Kanban board
|
|
183
|
+
|
|
108
184
|
# Set database path
|
|
109
185
|
floq config db /path/to/custom.db
|
|
110
186
|
floq config db # Reset to default
|
|
187
|
+
|
|
188
|
+
# Reset database (delete all data)
|
|
189
|
+
floq db reset # With confirmation
|
|
190
|
+
floq db reset --force # Skip confirmation
|
|
111
191
|
```
|
|
112
192
|
|
|
113
193
|
## Cloud Sync (Turso)
|
|
@@ -139,7 +219,7 @@ floq config turso --disable
|
|
|
139
219
|
- **Embedded Replicas**: Local SQLite database syncs with Turso cloud
|
|
140
220
|
- **Offline Support**: Works offline, syncs when connected
|
|
141
221
|
- **Auto Sync**: Background sync every 60 seconds when online
|
|
142
|
-
- **Separate Database**: Turso mode uses `
|
|
222
|
+
- **Separate Database**: Turso mode uses `floq-turso.db` to avoid conflicts
|
|
143
223
|
|
|
144
224
|
### Status Indicator
|
|
145
225
|
|
|
@@ -173,8 +253,8 @@ floq config turso --disable
|
|
|
173
253
|
|
|
174
254
|
## Data Storage
|
|
175
255
|
|
|
176
|
-
- Config: `~/.config/
|
|
177
|
-
- Database: `~/.local/share/
|
|
256
|
+
- Config: `~/.config/floq/config.json`
|
|
257
|
+
- Database: `~/.local/share/floq/floq.db` (or `floq-turso.db` with Turso enabled)
|
|
178
258
|
|
|
179
259
|
## License
|
|
180
260
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ChangelogEntry {
|
|
2
|
+
version: string;
|
|
3
|
+
date: string;
|
|
4
|
+
sections: {
|
|
5
|
+
type: 'Added' | 'Changed' | 'Deprecated' | 'Removed' | 'Fixed' | 'Security';
|
|
6
|
+
items: string[];
|
|
7
|
+
}[];
|
|
8
|
+
}
|
|
9
|
+
export interface Changelog {
|
|
10
|
+
entries: ChangelogEntry[];
|
|
11
|
+
}
|
|
12
|
+
export declare function parseChangelog(): Changelog;
|
|
13
|
+
export declare function getLatestVersion(): string;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { dirname, join } from 'path';
|
|
4
|
+
function findChangelogPath() {
|
|
5
|
+
// Get the directory of the current module
|
|
6
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
7
|
+
const currentDir = dirname(currentFile);
|
|
8
|
+
// Try to find CHANGELOG.md relative to the package root
|
|
9
|
+
// From dist/ or src/, go up one level
|
|
10
|
+
const possiblePaths = [
|
|
11
|
+
join(currentDir, '..', 'CHANGELOG.md'),
|
|
12
|
+
join(currentDir, '..', '..', 'CHANGELOG.md'),
|
|
13
|
+
join(process.cwd(), 'CHANGELOG.md'),
|
|
14
|
+
];
|
|
15
|
+
for (const path of possiblePaths) {
|
|
16
|
+
try {
|
|
17
|
+
readFileSync(path, 'utf-8');
|
|
18
|
+
return path;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// continue to next path
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return possiblePaths[0]; // Return first path as fallback
|
|
25
|
+
}
|
|
26
|
+
export function parseChangelog() {
|
|
27
|
+
const changelogPath = findChangelogPath();
|
|
28
|
+
let content;
|
|
29
|
+
try {
|
|
30
|
+
content = readFileSync(changelogPath, 'utf-8');
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return { entries: [] };
|
|
34
|
+
}
|
|
35
|
+
const entries = [];
|
|
36
|
+
const lines = content.split('\n');
|
|
37
|
+
let currentEntry = null;
|
|
38
|
+
let currentSection = null;
|
|
39
|
+
for (const line of lines) {
|
|
40
|
+
// Match version header: ## [0.1.0] - 2025-01-29 or ## [Unreleased]
|
|
41
|
+
const versionMatch = line.match(/^## \[([^\]]+)\](?:\s*-\s*(.+))?$/);
|
|
42
|
+
if (versionMatch) {
|
|
43
|
+
if (currentEntry) {
|
|
44
|
+
if (currentSection && currentSection.items.length > 0) {
|
|
45
|
+
currentEntry.sections.push(currentSection);
|
|
46
|
+
}
|
|
47
|
+
if (currentEntry.sections.length > 0 || currentEntry.version !== 'Unreleased') {
|
|
48
|
+
entries.push(currentEntry);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
currentEntry = {
|
|
52
|
+
version: versionMatch[1],
|
|
53
|
+
date: versionMatch[2]?.trim() || '',
|
|
54
|
+
sections: [],
|
|
55
|
+
};
|
|
56
|
+
currentSection = null;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
// Match section header: ### Added, ### Changed, etc.
|
|
60
|
+
const sectionMatch = line.match(/^### (Added|Changed|Deprecated|Removed|Fixed|Security)$/);
|
|
61
|
+
if (sectionMatch && currentEntry) {
|
|
62
|
+
if (currentSection && currentSection.items.length > 0) {
|
|
63
|
+
currentEntry.sections.push(currentSection);
|
|
64
|
+
}
|
|
65
|
+
currentSection = {
|
|
66
|
+
type: sectionMatch[1],
|
|
67
|
+
items: [],
|
|
68
|
+
};
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
// Match list item: - Item description
|
|
72
|
+
const itemMatch = line.match(/^- (.+)$/);
|
|
73
|
+
if (itemMatch && currentSection) {
|
|
74
|
+
currentSection.items.push(itemMatch[1]);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Add last entry
|
|
78
|
+
if (currentEntry) {
|
|
79
|
+
if (currentSection && currentSection.items.length > 0) {
|
|
80
|
+
currentEntry.sections.push(currentSection);
|
|
81
|
+
}
|
|
82
|
+
if (currentEntry.sections.length > 0) {
|
|
83
|
+
entries.push(currentEntry);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Filter out Unreleased if it has no content
|
|
87
|
+
return {
|
|
88
|
+
entries: entries.filter(e => e.version !== 'Unreleased' || e.sections.length > 0),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export function getLatestVersion() {
|
|
92
|
+
const changelog = parseChangelog();
|
|
93
|
+
const released = changelog.entries.find(e => e.version !== 'Unreleased');
|
|
94
|
+
return released?.version || '0.0.0';
|
|
95
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,9 @@ import { listTasks, listProjects } from './commands/list.js';
|
|
|
7
7
|
import { moveTask } from './commands/move.js';
|
|
8
8
|
import { markDone } from './commands/done.js';
|
|
9
9
|
import { addProject, listProjectsCommand, showProject, completeProject, } from './commands/project.js';
|
|
10
|
-
import { showConfig, setLanguage, setDbPath, resetDbPath, setTheme, selectTheme, setTurso, disableTurso, syncCommand } from './commands/config.js';
|
|
10
|
+
import { showConfig, setLanguage, setDbPath, resetDbPath, setTheme, selectTheme, setViewModeCommand, selectMode, setTurso, disableTurso, syncCommand, resetDatabase } from './commands/config.js';
|
|
11
|
+
import { addComment, listComments } from './commands/comment.js';
|
|
12
|
+
import { runSetupWizard } from './commands/setup.js';
|
|
11
13
|
import { VERSION } from './version.js';
|
|
12
14
|
const program = new Command();
|
|
13
15
|
program
|
|
@@ -121,6 +123,17 @@ configCmd
|
|
|
121
123
|
await selectTheme();
|
|
122
124
|
}
|
|
123
125
|
});
|
|
126
|
+
configCmd
|
|
127
|
+
.command('mode [mode]')
|
|
128
|
+
.description('Set view mode (gtd, kanban) or select interactively')
|
|
129
|
+
.action(async (mode) => {
|
|
130
|
+
if (mode) {
|
|
131
|
+
await setViewModeCommand(mode);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
await selectMode();
|
|
135
|
+
}
|
|
136
|
+
});
|
|
124
137
|
configCmd
|
|
125
138
|
.command('turso')
|
|
126
139
|
.description('Configure Turso cloud sync')
|
|
@@ -147,4 +160,34 @@ program
|
|
|
147
160
|
.action(async () => {
|
|
148
161
|
await syncCommand();
|
|
149
162
|
});
|
|
163
|
+
// Database commands
|
|
164
|
+
const dbCmd = program
|
|
165
|
+
.command('db')
|
|
166
|
+
.description('Database management commands');
|
|
167
|
+
dbCmd
|
|
168
|
+
.command('reset')
|
|
169
|
+
.description('Reset the database (delete all data)')
|
|
170
|
+
.option('-f, --force', 'Skip confirmation')
|
|
171
|
+
.action(async (options) => {
|
|
172
|
+
await resetDatabase(options.force ?? false);
|
|
173
|
+
});
|
|
174
|
+
// Comment command
|
|
175
|
+
program
|
|
176
|
+
.command('comment <taskId> [content]')
|
|
177
|
+
.description('Add or list comments for a task')
|
|
178
|
+
.action(async (taskId, content) => {
|
|
179
|
+
if (content) {
|
|
180
|
+
await addComment(taskId, content);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
await listComments(taskId);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
// Setup wizard command
|
|
187
|
+
program
|
|
188
|
+
.command('setup')
|
|
189
|
+
.description('Run the setup wizard')
|
|
190
|
+
.action(async () => {
|
|
191
|
+
await runSetupWizard();
|
|
192
|
+
});
|
|
150
193
|
export { program };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { eq, like } from 'drizzle-orm';
|
|
2
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
3
|
+
import { getDb, schema } from '../db/index.js';
|
|
4
|
+
import { t, fmt } from '../i18n/index.js';
|
|
5
|
+
export async function addComment(taskId, content) {
|
|
6
|
+
const db = getDb();
|
|
7
|
+
const i18n = t();
|
|
8
|
+
// Find task by ID prefix
|
|
9
|
+
const tasks = await db
|
|
10
|
+
.select()
|
|
11
|
+
.from(schema.tasks)
|
|
12
|
+
.where(like(schema.tasks.id, `${taskId}%`));
|
|
13
|
+
if (tasks.length === 0) {
|
|
14
|
+
console.error(fmt(i18n.commands.comment.notFound, { id: taskId }));
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
if (tasks.length > 1) {
|
|
18
|
+
console.error(fmt(i18n.commands.comment.multipleMatch, { id: taskId }));
|
|
19
|
+
for (const task of tasks) {
|
|
20
|
+
console.error(` [${task.id.slice(0, 8)}] ${task.title}`);
|
|
21
|
+
}
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
const task = tasks[0];
|
|
25
|
+
await db.insert(schema.comments).values({
|
|
26
|
+
id: uuidv4(),
|
|
27
|
+
taskId: task.id,
|
|
28
|
+
content: content.trim(),
|
|
29
|
+
createdAt: new Date(),
|
|
30
|
+
});
|
|
31
|
+
console.log(fmt(i18n.commands.comment.added, { title: task.title }));
|
|
32
|
+
}
|
|
33
|
+
export async function listComments(taskId) {
|
|
34
|
+
const db = getDb();
|
|
35
|
+
const i18n = t();
|
|
36
|
+
// Find task by ID prefix
|
|
37
|
+
const tasks = await db
|
|
38
|
+
.select()
|
|
39
|
+
.from(schema.tasks)
|
|
40
|
+
.where(like(schema.tasks.id, `${taskId}%`));
|
|
41
|
+
if (tasks.length === 0) {
|
|
42
|
+
console.error(fmt(i18n.commands.comment.notFound, { id: taskId }));
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
if (tasks.length > 1) {
|
|
46
|
+
console.error(fmt(i18n.commands.comment.multipleMatch, { id: taskId }));
|
|
47
|
+
for (const task of tasks) {
|
|
48
|
+
console.error(` [${task.id.slice(0, 8)}] ${task.title}`);
|
|
49
|
+
}
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
const task = tasks[0];
|
|
53
|
+
const comments = await db
|
|
54
|
+
.select()
|
|
55
|
+
.from(schema.comments)
|
|
56
|
+
.where(eq(schema.comments.taskId, task.id));
|
|
57
|
+
if (comments.length === 0) {
|
|
58
|
+
console.log(fmt(i18n.commands.comment.listHeader, { title: task.title }));
|
|
59
|
+
console.log(` ${i18n.commands.comment.noComments}`);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
console.log(fmt(i18n.commands.comment.listHeader, { title: task.title }));
|
|
63
|
+
for (const comment of comments) {
|
|
64
|
+
const date = comment.createdAt.toLocaleString();
|
|
65
|
+
console.log(` [${date}] ${comment.content}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -4,6 +4,10 @@ export declare function setDbPath(dbPath: string): Promise<void>;
|
|
|
4
4
|
export declare function resetDbPath(): Promise<void>;
|
|
5
5
|
export declare function setTheme(theme: string): Promise<void>;
|
|
6
6
|
export declare function selectTheme(): Promise<void>;
|
|
7
|
+
export declare function showViewMode(): Promise<void>;
|
|
8
|
+
export declare function setViewModeCommand(mode: string): Promise<void>;
|
|
9
|
+
export declare function selectMode(): Promise<void>;
|
|
7
10
|
export declare function setTurso(url: string, token: string): Promise<void>;
|
|
8
11
|
export declare function disableTurso(): Promise<void>;
|
|
9
12
|
export declare function syncCommand(): Promise<void>;
|
|
13
|
+
export declare function resetDatabase(force: boolean): Promise<void>;
|