@j0hanz/todokit-mcp 1.2.1 → 1.2.2
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.md +2 -0
- package/dist/storage.js +28 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -66,6 +66,8 @@ npm start
|
|
|
66
66
|
|
|
67
67
|
By default, todos are stored in `todos.json` in the current working directory. To control where data is written, set the `TODOKIT_TODO_FILE` environment variable to an absolute or relative path ending with `.json`. Relative paths resolve from the current working directory. The directory is created as needed; if the file does not exist, the server starts with an empty list.
|
|
68
68
|
|
|
69
|
+
When all todos are completed, the server removes the storage file so it does not linger on disk.
|
|
70
|
+
|
|
69
71
|
Examples:
|
|
70
72
|
|
|
71
73
|
```bash
|
package/dist/storage.js
CHANGED
|
@@ -283,9 +283,33 @@ export async function withTodos(mutate) {
|
|
|
283
283
|
if (nextTodos === todos) {
|
|
284
284
|
return { kind: 'no_change', result };
|
|
285
285
|
}
|
|
286
|
+
if (areAllTodosCompleted(nextTodos)) {
|
|
287
|
+
return { kind: 'delete_file', result };
|
|
288
|
+
}
|
|
286
289
|
return { kind: 'save', todos: nextTodos, result };
|
|
287
290
|
});
|
|
288
291
|
}
|
|
292
|
+
function areAllTodosCompleted(todos) {
|
|
293
|
+
return todos.length > 0 && todos.every((todo) => todo.completed);
|
|
294
|
+
}
|
|
295
|
+
function normalizeTodoFileUpdate(outcome, current, hasPersistedFile) {
|
|
296
|
+
if (outcome.kind === 'save' && areAllTodosCompleted(outcome.todos)) {
|
|
297
|
+
return {
|
|
298
|
+
kind: 'proceed',
|
|
299
|
+
outcome: { kind: 'delete_file', result: outcome.result },
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
if (outcome.kind !== 'no_change') {
|
|
303
|
+
return { kind: 'proceed', outcome };
|
|
304
|
+
}
|
|
305
|
+
if (hasPersistedFile && areAllTodosCompleted(current)) {
|
|
306
|
+
return {
|
|
307
|
+
kind: 'proceed',
|
|
308
|
+
outcome: { kind: 'delete_file', result: outcome.result },
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
return { kind: 'return', result: outcome.result };
|
|
312
|
+
}
|
|
289
313
|
async function deleteTodoFile(path) {
|
|
290
314
|
const start = nowMs();
|
|
291
315
|
await withTimeout(rm(path, { force: true }), WRITE_TIMEOUT_MS, 'File remove timed out').catch((error) => {
|
|
@@ -311,10 +335,11 @@ async function withTodoFileUpdate(work) {
|
|
|
311
335
|
const mtimeMs = await getFileMtime(path, IO_TIMEOUT_MS);
|
|
312
336
|
const current = cache?.mtimeMs === mtimeMs ? cache.todos : await loadTodos(path);
|
|
313
337
|
cache = { todos: current, mtimeMs };
|
|
314
|
-
const
|
|
315
|
-
if (
|
|
316
|
-
return
|
|
338
|
+
const normalized = normalizeTodoFileUpdate(work(current), current, mtimeMs !== null);
|
|
339
|
+
if (normalized.kind === 'return') {
|
|
340
|
+
return normalized.result;
|
|
317
341
|
}
|
|
342
|
+
const { outcome } = normalized;
|
|
318
343
|
const release = await acquireWriteLock(path, getLockTimeoutMs());
|
|
319
344
|
try {
|
|
320
345
|
const latestMtime = await getFileMtime(path, IO_TIMEOUT_MS);
|
package/package.json
CHANGED