@todu/cli 0.1.1 → 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/dist/commands/config.js +3 -3
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/daemon.d.ts +4 -0
- package/dist/commands/daemon.d.ts.map +1 -0
- package/dist/commands/daemon.js +675 -0
- package/dist/commands/daemon.js.map +1 -0
- package/dist/commands/habit.d.ts +2 -2
- package/dist/commands/habit.d.ts.map +1 -1
- package/dist/commands/habit.js +270 -315
- package/dist/commands/habit.js.map +1 -1
- package/dist/commands/label.d.ts +2 -2
- package/dist/commands/label.d.ts.map +1 -1
- package/dist/commands/label.js +76 -92
- package/dist/commands/label.js.map +1 -1
- package/dist/commands/note.d.ts +2 -2
- package/dist/commands/note.d.ts.map +1 -1
- package/dist/commands/note.js +97 -118
- package/dist/commands/note.js.map +1 -1
- package/dist/commands/plugin.d.ts +4 -0
- package/dist/commands/plugin.d.ts.map +1 -0
- package/dist/commands/plugin.js +527 -0
- package/dist/commands/plugin.js.map +1 -0
- package/dist/commands/project.d.ts +2 -2
- package/dist/commands/project.d.ts.map +1 -1
- package/dist/commands/project.js +99 -117
- package/dist/commands/project.js.map +1 -1
- package/dist/commands/recurring.d.ts +2 -2
- package/dist/commands/recurring.d.ts.map +1 -1
- package/dist/commands/recurring.js +250 -284
- package/dist/commands/recurring.js.map +1 -1
- package/dist/commands/sync.d.ts +2 -2
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +123 -12
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/task.d.ts +2 -2
- package/dist/commands/task.d.ts.map +1 -1
- package/dist/commands/task.js +181 -207
- package/dist/commands/task.js.map +1 -1
- package/dist/daemon-command-client.d.ts +11 -0
- package/dist/daemon-command-client.d.ts.map +1 -0
- package/dist/daemon-command-client.js +57 -0
- package/dist/daemon-command-client.js.map +1 -0
- package/dist/daemon-plugin-config.d.ts +8 -0
- package/dist/daemon-plugin-config.d.ts.map +1 -0
- package/dist/daemon-plugin-config.js +22 -0
- package/dist/daemon-plugin-config.js.map +1 -0
- package/dist/daemon-plugin-paths.d.ts +8 -0
- package/dist/daemon-plugin-paths.d.ts.map +1 -0
- package/dist/daemon-plugin-paths.js +28 -0
- package/dist/daemon-plugin-paths.js.map +1 -0
- package/dist/daemon-transport.d.ts +37 -0
- package/dist/daemon-transport.d.ts.map +1 -0
- package/dist/daemon-transport.js +422 -0
- package/dist/daemon-transport.js.map +1 -0
- package/dist/daemon-worker-assignment.d.ts +8 -0
- package/dist/daemon-worker-assignment.d.ts.map +1 -0
- package/dist/daemon-worker-assignment.js +22 -0
- package/dist/daemon-worker-assignment.js.map +1 -0
- package/dist/index.js +20 -23
- package/dist/index.js.map +1 -1
- package/dist/test-helpers/daemon-process.d.ts +5 -0
- package/dist/test-helpers/daemon-process.d.ts.map +1 -0
- package/dist/test-helpers/daemon-process.js +55 -0
- package/dist/test-helpers/daemon-process.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/dist/warnings.d.ts +7 -0
- package/dist/warnings.d.ts.map +1 -0
- package/dist/warnings.js +21 -0
- package/dist/warnings.js.map +1 -0
- package/package.json +5 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { createProjectId, createRecurringId } from "@todu/core";
|
|
2
1
|
import { describeSchedule } from "@todu/engine";
|
|
3
|
-
import {
|
|
2
|
+
import { formatDaemonCommandError } from "../daemon-command-client.js";
|
|
3
|
+
import { colorPriority, formatJSON, formatTable } from "../format.js";
|
|
4
4
|
const TEMPLATE_COLUMNS = [
|
|
5
5
|
{ key: "id", label: "ID" },
|
|
6
6
|
{ key: "title", label: "Title" },
|
|
@@ -46,48 +46,57 @@ function templateDetail(t, projectName) {
|
|
|
46
46
|
lines.push(`Updated: ${t.updatedAt}`);
|
|
47
47
|
return lines.join("\n");
|
|
48
48
|
}
|
|
49
|
-
async function resolveTemplate(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
49
|
+
async function resolveTemplate(invokeDaemon, ref) {
|
|
50
|
+
const byId = await invokeDaemon("recurring.get", { id: ref });
|
|
51
|
+
if (byId.ok) {
|
|
52
|
+
return { ok: true, value: byId.value };
|
|
53
|
+
}
|
|
54
|
+
if (byId.error.code !== "NOT_FOUND") {
|
|
55
|
+
return { ok: false, message: formatDaemonCommandError(byId.error) };
|
|
56
|
+
}
|
|
57
|
+
const listResult = await invokeDaemon("recurring.list", {});
|
|
58
|
+
if (!listResult.ok) {
|
|
59
|
+
return { ok: false, message: formatDaemonCommandError(listResult.error) };
|
|
60
|
+
}
|
|
58
61
|
const byName = listResult.value.filter((t) => t.title.toLowerCase() === ref.toLowerCase());
|
|
59
|
-
if (byName.length === 1)
|
|
62
|
+
if (byName.length === 1) {
|
|
60
63
|
return { ok: true, value: byName[0] };
|
|
64
|
+
}
|
|
61
65
|
if (byName.length > 1) {
|
|
62
66
|
return { ok: false, message: `Multiple templates match "${ref}". Use the template ID.` };
|
|
63
67
|
}
|
|
64
68
|
return { ok: false, message: `Recurring template not found: ${ref}` };
|
|
65
69
|
}
|
|
66
|
-
async function getProjectName(
|
|
67
|
-
const result = await
|
|
68
|
-
if (!result.ok)
|
|
70
|
+
async function getProjectName(invokeDaemon, projectId) {
|
|
71
|
+
const result = await invokeDaemon("project.list", {});
|
|
72
|
+
if (!result.ok) {
|
|
69
73
|
return projectId;
|
|
74
|
+
}
|
|
70
75
|
const project = result.value.find((p) => p.id === projectId);
|
|
71
76
|
return project?.name ?? projectId;
|
|
72
77
|
}
|
|
73
|
-
async function resolveProjectId(
|
|
74
|
-
const
|
|
75
|
-
if (
|
|
76
|
-
return { ok:
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
async function resolveProjectId(invokeDaemon, ref) {
|
|
79
|
+
const byId = await invokeDaemon("project.get", { id: ref });
|
|
80
|
+
if (byId.ok) {
|
|
81
|
+
return { ok: true, value: byId.value.id };
|
|
82
|
+
}
|
|
83
|
+
if (byId.error.code !== "NOT_FOUND") {
|
|
84
|
+
return { ok: false, message: formatDaemonCommandError(byId.error) };
|
|
85
|
+
}
|
|
86
|
+
const result = await invokeDaemon("project.list", {});
|
|
87
|
+
if (!result.ok) {
|
|
88
|
+
return { ok: false, message: formatDaemonCommandError(result.error) };
|
|
89
|
+
}
|
|
82
90
|
const byName = result.value.filter((p) => p.name.toLowerCase() === ref.toLowerCase());
|
|
83
|
-
if (byName.length === 1)
|
|
91
|
+
if (byName.length === 1) {
|
|
84
92
|
return { ok: true, value: byName[0].id };
|
|
93
|
+
}
|
|
85
94
|
if (byName.length > 1) {
|
|
86
95
|
return { ok: false, message: `Multiple projects match "${ref}". Use the project ID.` };
|
|
87
96
|
}
|
|
88
97
|
return { ok: false, message: `Project not found: ${ref}` };
|
|
89
98
|
}
|
|
90
|
-
export function registerRecurringCommands(program,
|
|
99
|
+
export function registerRecurringCommands(program, invokeDaemon) {
|
|
91
100
|
const recurring = program.command("recurring").description("Manage recurring task templates");
|
|
92
101
|
recurring
|
|
93
102
|
.command("create")
|
|
@@ -102,42 +111,38 @@ export function registerRecurringCommands(program, getTodu) {
|
|
|
102
111
|
.option("--description <text>", "template description")
|
|
103
112
|
.option("--label <labels...>", "labels to apply to generated tasks")
|
|
104
113
|
.action(async (opts) => {
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const result = await todu.recurring.create({
|
|
114
|
+
const projectRes = await resolveProjectId(invokeDaemon, opts.project);
|
|
115
|
+
if (!projectRes.ok) {
|
|
116
|
+
console.error(projectRes.message);
|
|
117
|
+
process.exitCode = 1;
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const result = await invokeDaemon("recurring.create", {
|
|
121
|
+
input: {
|
|
114
122
|
title: opts.title,
|
|
115
123
|
schedule: opts.schedule,
|
|
116
124
|
timezone: opts.timezone,
|
|
117
125
|
startDate: opts.startDate,
|
|
118
|
-
projectId:
|
|
126
|
+
projectId: projectRes.value,
|
|
119
127
|
description: opts.description,
|
|
120
128
|
priority: opts.priority,
|
|
121
129
|
endDate: opts.endDate,
|
|
122
130
|
labels: opts.label,
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
else {
|
|
134
|
-
const projectName = await getProjectName(todu, result.value.projectId);
|
|
135
|
-
console.log(`Created recurring template: ${result.value.id}`);
|
|
136
|
-
console.log(templateDetail(result.value, projectName));
|
|
137
|
-
}
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
if (!result.ok) {
|
|
134
|
+
console.error(formatDaemonCommandError(result.error));
|
|
135
|
+
process.exitCode = 1;
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const format = program.opts().format;
|
|
139
|
+
if (format === "json") {
|
|
140
|
+
console.log(formatJSON(result.value));
|
|
138
141
|
}
|
|
139
|
-
|
|
140
|
-
await
|
|
142
|
+
else {
|
|
143
|
+
const projectName = await getProjectName(invokeDaemon, result.value.projectId);
|
|
144
|
+
console.log(`Created recurring template: ${result.value.id}`);
|
|
145
|
+
console.log(templateDetail(result.value, projectName));
|
|
141
146
|
}
|
|
142
147
|
});
|
|
143
148
|
recurring
|
|
@@ -147,74 +152,61 @@ export function registerRecurringCommands(program, getTodu) {
|
|
|
147
152
|
.option("--paused", "show only paused templates")
|
|
148
153
|
.option("--project <project>", "filter by project")
|
|
149
154
|
.action(async (opts) => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (
|
|
154
|
-
|
|
155
|
-
if (!res.ok) {
|
|
156
|
-
console.error(res.message);
|
|
157
|
-
process.exitCode = 1;
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
projectId = res.value;
|
|
161
|
-
}
|
|
162
|
-
const filter = {};
|
|
163
|
-
if (opts.active)
|
|
164
|
-
filter.paused = false;
|
|
165
|
-
if (opts.paused)
|
|
166
|
-
filter.paused = true;
|
|
167
|
-
if (projectId)
|
|
168
|
-
filter.projectId = createProjectId(projectId);
|
|
169
|
-
const result = await todu.recurring.list(filter);
|
|
170
|
-
if (!result.ok) {
|
|
171
|
-
console.error(formatError(result.error));
|
|
155
|
+
let projectId;
|
|
156
|
+
if (opts.project) {
|
|
157
|
+
const res = await resolveProjectId(invokeDaemon, opts.project);
|
|
158
|
+
if (!res.ok) {
|
|
159
|
+
console.error(res.message);
|
|
172
160
|
process.exitCode = 1;
|
|
173
161
|
return;
|
|
174
162
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
163
|
+
projectId = res.value;
|
|
164
|
+
}
|
|
165
|
+
const filter = {};
|
|
166
|
+
if (opts.active)
|
|
167
|
+
filter.paused = false;
|
|
168
|
+
if (opts.paused)
|
|
169
|
+
filter.paused = true;
|
|
170
|
+
if (projectId)
|
|
171
|
+
filter.projectId = projectId;
|
|
172
|
+
const result = await invokeDaemon("recurring.list", { filter });
|
|
173
|
+
if (!result.ok) {
|
|
174
|
+
console.error(formatDaemonCommandError(result.error));
|
|
175
|
+
process.exitCode = 1;
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const format = program.opts().format;
|
|
179
|
+
if (format === "json") {
|
|
180
|
+
console.log(formatJSON(result.value));
|
|
181
|
+
return;
|
|
190
182
|
}
|
|
191
|
-
|
|
192
|
-
|
|
183
|
+
const projects = await invokeDaemon("project.list", {});
|
|
184
|
+
const projectNames = {};
|
|
185
|
+
if (projects.ok) {
|
|
186
|
+
for (const p of projects.value) {
|
|
187
|
+
projectNames[p.id] = p.name;
|
|
188
|
+
}
|
|
193
189
|
}
|
|
190
|
+
const rows = result.value.map((t) => templateToRow(t, projectNames[t.projectId]));
|
|
191
|
+
console.log(formatTable(rows, TEMPLATE_COLUMNS));
|
|
194
192
|
});
|
|
195
193
|
recurring
|
|
196
194
|
.command("show <id>")
|
|
197
195
|
.description("Show recurring template details")
|
|
198
196
|
.action(async (ref) => {
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
process.exitCode = 1;
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
const format = program.opts().format;
|
|
208
|
-
if (format === "json") {
|
|
209
|
-
console.log(formatJSON(resolved.value));
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
const projectName = await getProjectName(todu, resolved.value.projectId);
|
|
213
|
-
console.log(templateDetail(resolved.value, projectName));
|
|
197
|
+
const resolved = await resolveTemplate(invokeDaemon, ref);
|
|
198
|
+
if (!resolved.ok) {
|
|
199
|
+
console.error(resolved.message);
|
|
200
|
+
process.exitCode = 1;
|
|
201
|
+
return;
|
|
214
202
|
}
|
|
215
|
-
|
|
216
|
-
|
|
203
|
+
const format = program.opts().format;
|
|
204
|
+
if (format === "json") {
|
|
205
|
+
console.log(formatJSON(resolved.value));
|
|
206
|
+
return;
|
|
217
207
|
}
|
|
208
|
+
const projectName = await getProjectName(invokeDaemon, resolved.value.projectId);
|
|
209
|
+
console.log(templateDetail(resolved.value, projectName));
|
|
218
210
|
});
|
|
219
211
|
recurring
|
|
220
212
|
.command("update <id>")
|
|
@@ -228,144 +220,127 @@ export function registerRecurringCommands(program, getTodu) {
|
|
|
228
220
|
.option("--label <labels...>", "replace labels")
|
|
229
221
|
.option("--project <project>", "move to different project")
|
|
230
222
|
.action(async (ref, opts) => {
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
if (
|
|
255
|
-
|
|
256
|
-
if (!projectRes.ok) {
|
|
257
|
-
console.error(projectRes.message);
|
|
258
|
-
process.exitCode = 1;
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
input.projectId = createProjectId(projectRes.value);
|
|
262
|
-
}
|
|
263
|
-
const result = await todu.recurring.update(resolved.value.id, input);
|
|
264
|
-
if (!result.ok) {
|
|
265
|
-
console.error(formatError(result.error));
|
|
223
|
+
const resolved = await resolveTemplate(invokeDaemon, ref);
|
|
224
|
+
if (!resolved.ok) {
|
|
225
|
+
console.error(resolved.message);
|
|
226
|
+
process.exitCode = 1;
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
const input = {};
|
|
230
|
+
if (opts.title)
|
|
231
|
+
input.title = opts.title;
|
|
232
|
+
if (opts.schedule)
|
|
233
|
+
input.schedule = opts.schedule;
|
|
234
|
+
if (opts.timezone)
|
|
235
|
+
input.timezone = opts.timezone;
|
|
236
|
+
if (opts.priority)
|
|
237
|
+
input.priority = opts.priority;
|
|
238
|
+
if (opts.description)
|
|
239
|
+
input.description = opts.description;
|
|
240
|
+
if (opts.endDate)
|
|
241
|
+
input.endDate = opts.endDate;
|
|
242
|
+
if (opts.label)
|
|
243
|
+
input.labels = opts.label;
|
|
244
|
+
if (opts.project) {
|
|
245
|
+
const projectRes = await resolveProjectId(invokeDaemon, opts.project);
|
|
246
|
+
if (!projectRes.ok) {
|
|
247
|
+
console.error(projectRes.message);
|
|
266
248
|
process.exitCode = 1;
|
|
267
249
|
return;
|
|
268
250
|
}
|
|
269
|
-
|
|
270
|
-
if (format === "json") {
|
|
271
|
-
console.log(formatJSON(result.value));
|
|
272
|
-
}
|
|
273
|
-
else {
|
|
274
|
-
console.log(`Updated recurring template: ${result.value.id}`);
|
|
275
|
-
}
|
|
251
|
+
input.projectId = projectRes.value;
|
|
276
252
|
}
|
|
277
|
-
|
|
278
|
-
|
|
253
|
+
const result = await invokeDaemon("recurring.update", {
|
|
254
|
+
id: resolved.value.id,
|
|
255
|
+
input,
|
|
256
|
+
});
|
|
257
|
+
if (!result.ok) {
|
|
258
|
+
console.error(formatDaemonCommandError(result.error));
|
|
259
|
+
process.exitCode = 1;
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
const format = program.opts().format;
|
|
263
|
+
if (format === "json") {
|
|
264
|
+
console.log(formatJSON(result.value));
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
console.log(`Updated recurring template: ${result.value.id}`);
|
|
279
268
|
}
|
|
280
269
|
});
|
|
281
270
|
recurring
|
|
282
271
|
.command("delete <id>")
|
|
283
272
|
.description("Delete a recurring template")
|
|
284
273
|
.action(async (ref) => {
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
if (format === "json") {
|
|
301
|
-
console.log(formatJSON({ deleted: resolved.value.id }));
|
|
302
|
-
}
|
|
303
|
-
else {
|
|
304
|
-
console.log(`Deleted recurring template: ${resolved.value.id}`);
|
|
305
|
-
}
|
|
274
|
+
const resolved = await resolveTemplate(invokeDaemon, ref);
|
|
275
|
+
if (!resolved.ok) {
|
|
276
|
+
console.error(resolved.message);
|
|
277
|
+
process.exitCode = 1;
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
const result = await invokeDaemon("recurring.delete", { id: resolved.value.id });
|
|
281
|
+
if (!result.ok) {
|
|
282
|
+
console.error(formatDaemonCommandError(result.error));
|
|
283
|
+
process.exitCode = 1;
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
const format = program.opts().format;
|
|
287
|
+
if (format === "json") {
|
|
288
|
+
console.log(formatJSON({ deleted: resolved.value.id }));
|
|
306
289
|
}
|
|
307
|
-
|
|
308
|
-
|
|
290
|
+
else {
|
|
291
|
+
console.log(`Deleted recurring template: ${resolved.value.id}`);
|
|
309
292
|
}
|
|
310
293
|
});
|
|
311
294
|
recurring
|
|
312
295
|
.command("pause <id>")
|
|
313
296
|
.description("Pause a recurring template")
|
|
314
297
|
.action(async (ref) => {
|
|
315
|
-
const
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
}
|
|
329
|
-
const format = program.opts().format;
|
|
330
|
-
if (format === "json") {
|
|
331
|
-
console.log(formatJSON(result.value));
|
|
332
|
-
}
|
|
333
|
-
else {
|
|
334
|
-
console.log(`Paused recurring template: ${resolved.value.id}`);
|
|
335
|
-
}
|
|
298
|
+
const resolved = await resolveTemplate(invokeDaemon, ref);
|
|
299
|
+
if (!resolved.ok) {
|
|
300
|
+
console.error(resolved.message);
|
|
301
|
+
process.exitCode = 1;
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
const result = await invokeDaemon("recurring.pause", {
|
|
305
|
+
id: resolved.value.id,
|
|
306
|
+
});
|
|
307
|
+
if (!result.ok) {
|
|
308
|
+
console.error(formatDaemonCommandError(result.error));
|
|
309
|
+
process.exitCode = 1;
|
|
310
|
+
return;
|
|
336
311
|
}
|
|
337
|
-
|
|
338
|
-
|
|
312
|
+
const format = program.opts().format;
|
|
313
|
+
if (format === "json") {
|
|
314
|
+
console.log(formatJSON(result.value));
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
console.log(`Paused recurring template: ${resolved.value.id}`);
|
|
339
318
|
}
|
|
340
319
|
});
|
|
341
320
|
recurring
|
|
342
321
|
.command("resume <id>")
|
|
343
322
|
.description("Resume a recurring template")
|
|
344
323
|
.action(async (ref) => {
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
process.exitCode = 1;
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
const result = await todu.recurring.resume(resolved.value.id);
|
|
354
|
-
if (!result.ok) {
|
|
355
|
-
console.error(formatError(result.error));
|
|
356
|
-
process.exitCode = 1;
|
|
357
|
-
return;
|
|
358
|
-
}
|
|
359
|
-
const format = program.opts().format;
|
|
360
|
-
if (format === "json") {
|
|
361
|
-
console.log(formatJSON(result.value));
|
|
362
|
-
}
|
|
363
|
-
else {
|
|
364
|
-
console.log(`Resumed recurring template: ${resolved.value.id}`);
|
|
365
|
-
}
|
|
324
|
+
const resolved = await resolveTemplate(invokeDaemon, ref);
|
|
325
|
+
if (!resolved.ok) {
|
|
326
|
+
console.error(resolved.message);
|
|
327
|
+
process.exitCode = 1;
|
|
328
|
+
return;
|
|
366
329
|
}
|
|
367
|
-
|
|
368
|
-
|
|
330
|
+
const result = await invokeDaemon("recurring.resume", {
|
|
331
|
+
id: resolved.value.id,
|
|
332
|
+
});
|
|
333
|
+
if (!result.ok) {
|
|
334
|
+
console.error(formatDaemonCommandError(result.error));
|
|
335
|
+
process.exitCode = 1;
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
const format = program.opts().format;
|
|
339
|
+
if (format === "json") {
|
|
340
|
+
console.log(formatJSON(result.value));
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
console.log(`Resumed recurring template: ${resolved.value.id}`);
|
|
369
344
|
}
|
|
370
345
|
});
|
|
371
346
|
recurring
|
|
@@ -374,75 +349,66 @@ export function registerRecurringCommands(program, getTodu) {
|
|
|
374
349
|
.option("--days <days>", "number of days to look ahead", "14")
|
|
375
350
|
.option("--template <id>", "filter by template ID")
|
|
376
351
|
.action(async (opts) => {
|
|
377
|
-
const
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
console.log(formatJSON(result.value));
|
|
394
|
-
return;
|
|
395
|
-
}
|
|
396
|
-
if (result.value.length === 0) {
|
|
397
|
-
console.log("No upcoming occurrences.");
|
|
398
|
-
return;
|
|
399
|
-
}
|
|
400
|
-
const upcomingColumns = [
|
|
401
|
-
{ key: "date", label: "Date" },
|
|
402
|
-
{ key: "title", label: "Title" },
|
|
403
|
-
{ key: "priority", label: "Priority", colorize: colorPriority },
|
|
404
|
-
{ key: "schedule", label: "Schedule" },
|
|
405
|
-
];
|
|
406
|
-
const rows = result.value.map((o) => ({
|
|
407
|
-
date: o.date,
|
|
408
|
-
title: o.title,
|
|
409
|
-
priority: o.priority,
|
|
410
|
-
schedule: o.schedule,
|
|
411
|
-
}));
|
|
412
|
-
console.log(formatTable(rows, upcomingColumns));
|
|
413
|
-
}
|
|
414
|
-
finally {
|
|
415
|
-
await todu.close();
|
|
352
|
+
const options = {
|
|
353
|
+
days: Number.parseInt(opts.days, 10),
|
|
354
|
+
};
|
|
355
|
+
if (opts.template) {
|
|
356
|
+
options.templateId = opts.template;
|
|
357
|
+
}
|
|
358
|
+
const result = await invokeDaemon("recurring.upcoming", { options });
|
|
359
|
+
if (!result.ok) {
|
|
360
|
+
console.error(formatDaemonCommandError(result.error));
|
|
361
|
+
process.exitCode = 1;
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
const format = program.opts().format;
|
|
365
|
+
if (format === "json") {
|
|
366
|
+
console.log(formatJSON(result.value));
|
|
367
|
+
return;
|
|
416
368
|
}
|
|
369
|
+
if (result.value.length === 0) {
|
|
370
|
+
console.log("No upcoming occurrences.");
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
const upcomingColumns = [
|
|
374
|
+
{ key: "date", label: "Date" },
|
|
375
|
+
{ key: "title", label: "Title" },
|
|
376
|
+
{ key: "priority", label: "Priority", colorize: colorPriority },
|
|
377
|
+
{ key: "schedule", label: "Schedule" },
|
|
378
|
+
];
|
|
379
|
+
const rows = result.value.map((o) => ({
|
|
380
|
+
date: o.date,
|
|
381
|
+
title: o.title,
|
|
382
|
+
priority: o.priority,
|
|
383
|
+
schedule: o.schedule,
|
|
384
|
+
}));
|
|
385
|
+
console.log(formatTable(rows, upcomingColumns));
|
|
417
386
|
});
|
|
418
387
|
recurring
|
|
419
388
|
.command("generate <id> <date>")
|
|
420
389
|
.description("Create a task for a specific future date (early materialization)")
|
|
421
390
|
.action(async (ref, date) => {
|
|
422
|
-
const
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
else {
|
|
441
|
-
console.log(`Generated task: ${result.value.id} (${result.value.title} on ${date})`);
|
|
442
|
-
}
|
|
391
|
+
const resolved = await resolveTemplate(invokeDaemon, ref);
|
|
392
|
+
if (!resolved.ok) {
|
|
393
|
+
console.error(resolved.message);
|
|
394
|
+
process.exitCode = 1;
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
const result = await invokeDaemon("recurring.generate", {
|
|
398
|
+
templateId: resolved.value.id,
|
|
399
|
+
date,
|
|
400
|
+
});
|
|
401
|
+
if (!result.ok) {
|
|
402
|
+
console.error(formatDaemonCommandError(result.error));
|
|
403
|
+
process.exitCode = 1;
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
const format = program.opts().format;
|
|
407
|
+
if (format === "json") {
|
|
408
|
+
console.log(formatJSON(result.value));
|
|
443
409
|
}
|
|
444
|
-
|
|
445
|
-
|
|
410
|
+
else {
|
|
411
|
+
console.log(`Generated task: ${result.value.id} (${result.value.title} on ${date})`);
|
|
446
412
|
}
|
|
447
413
|
});
|
|
448
414
|
}
|