@hasna/todos 0.11.7 → 0.11.8

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.
@@ -444,6 +444,36 @@ function clearExpiredLocks(db) {
444
444
  const cutoff = lockExpiryCutoff();
445
445
  db.run("UPDATE tasks SET locked_by = NULL, locked_at = NULL WHERE locked_at IS NOT NULL AND locked_at < ?", [cutoff]);
446
446
  }
447
+ function resolvePartialId(db, table, partialId) {
448
+ if (partialId.length >= 36) {
449
+ const row = db.query(`SELECT id FROM ${table} WHERE id = ?`).get(partialId);
450
+ return row?.id ?? null;
451
+ }
452
+ const rows = db.query(`SELECT id FROM ${table} WHERE id LIKE ?`).all(`${partialId}%`);
453
+ if (rows.length === 1) {
454
+ return rows[0].id;
455
+ }
456
+ if (rows.length > 1) {
457
+ return null;
458
+ }
459
+ if (table === "tasks") {
460
+ const shortIdRows = db.query("SELECT id FROM tasks WHERE short_id = ?").all(partialId);
461
+ if (shortIdRows.length === 1) {
462
+ return shortIdRows[0].id;
463
+ }
464
+ }
465
+ if (table === "task_lists") {
466
+ const slugRow = db.query("SELECT id FROM task_lists WHERE slug = ?").get(partialId);
467
+ if (slugRow)
468
+ return slugRow.id;
469
+ }
470
+ if (table === "projects") {
471
+ const nameRow = db.query("SELECT id FROM projects WHERE lower(name) = ?").get(partialId.toLowerCase());
472
+ if (nameRow)
473
+ return nameRow.id;
474
+ }
475
+ return null;
476
+ }
447
477
  var LOCK_EXPIRY_MINUTES = 30, MIGRATIONS, _db = null;
448
478
  var init_database = __esm(() => {
449
479
  MIGRATIONS = [
@@ -1469,6 +1499,7 @@ var init_webhooks = __esm(() => {
1469
1499
  // src/db/templates.ts
1470
1500
  var exports_templates = {};
1471
1501
  __export(exports_templates, {
1502
+ updateTemplate: () => updateTemplate,
1472
1503
  taskFromTemplate: () => taskFromTemplate,
1473
1504
  listTemplates: () => listTemplates,
1474
1505
  getTemplate: () => getTemplate,
@@ -1483,6 +1514,9 @@ function rowToTemplate(row) {
1483
1514
  priority: row.priority || "medium"
1484
1515
  };
1485
1516
  }
1517
+ function resolveTemplateId(id, d) {
1518
+ return resolvePartialId(d, "task_templates", id);
1519
+ }
1486
1520
  function createTemplate(input, db) {
1487
1521
  const d = db || getDatabase();
1488
1522
  const id = uuid();
@@ -1503,7 +1537,10 @@ function createTemplate(input, db) {
1503
1537
  }
1504
1538
  function getTemplate(id, db) {
1505
1539
  const d = db || getDatabase();
1506
- const row = d.query("SELECT * FROM task_templates WHERE id = ?").get(id);
1540
+ const resolved = resolveTemplateId(id, d);
1541
+ if (!resolved)
1542
+ return null;
1543
+ const row = d.query("SELECT * FROM task_templates WHERE id = ?").get(resolved);
1507
1544
  return row ? rowToTemplate(row) : null;
1508
1545
  }
1509
1546
  function listTemplates(db) {
@@ -1512,7 +1549,55 @@ function listTemplates(db) {
1512
1549
  }
1513
1550
  function deleteTemplate(id, db) {
1514
1551
  const d = db || getDatabase();
1515
- return d.run("DELETE FROM task_templates WHERE id = ?", [id]).changes > 0;
1552
+ const resolved = resolveTemplateId(id, d);
1553
+ if (!resolved)
1554
+ return false;
1555
+ return d.run("DELETE FROM task_templates WHERE id = ?", [resolved]).changes > 0;
1556
+ }
1557
+ function updateTemplate(id, updates, db) {
1558
+ const d = db || getDatabase();
1559
+ const resolved = resolveTemplateId(id, d);
1560
+ if (!resolved)
1561
+ return null;
1562
+ const sets = [];
1563
+ const values = [];
1564
+ if (updates.name !== undefined) {
1565
+ sets.push("name = ?");
1566
+ values.push(updates.name);
1567
+ }
1568
+ if (updates.title_pattern !== undefined) {
1569
+ sets.push("title_pattern = ?");
1570
+ values.push(updates.title_pattern);
1571
+ }
1572
+ if (updates.description !== undefined) {
1573
+ sets.push("description = ?");
1574
+ values.push(updates.description);
1575
+ }
1576
+ if (updates.priority !== undefined) {
1577
+ sets.push("priority = ?");
1578
+ values.push(updates.priority);
1579
+ }
1580
+ if (updates.tags !== undefined) {
1581
+ sets.push("tags = ?");
1582
+ values.push(JSON.stringify(updates.tags));
1583
+ }
1584
+ if (updates.project_id !== undefined) {
1585
+ sets.push("project_id = ?");
1586
+ values.push(updates.project_id);
1587
+ }
1588
+ if (updates.plan_id !== undefined) {
1589
+ sets.push("plan_id = ?");
1590
+ values.push(updates.plan_id);
1591
+ }
1592
+ if (updates.metadata !== undefined) {
1593
+ sets.push("metadata = ?");
1594
+ values.push(JSON.stringify(updates.metadata));
1595
+ }
1596
+ if (sets.length === 0)
1597
+ return getTemplate(resolved, d);
1598
+ values.push(resolved);
1599
+ d.run(`UPDATE task_templates SET ${sets.join(", ")} WHERE id = ?`, values);
1600
+ return getTemplate(resolved, d);
1516
1601
  }
1517
1602
  function taskFromTemplate(templateId, overrides = {}, db) {
1518
1603
  const t = getTemplate(templateId, db);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/todos",
3
- "version": "0.11.7",
3
+ "version": "0.11.8",
4
4
  "description": "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -64,7 +64,7 @@
64
64
  "author": "Andrei Hasna <andrei@hasna.com>",
65
65
  "license": "Apache-2.0",
66
66
  "dependencies": {
67
- "@hasna/cloud": "0.1.6",
67
+ "@hasna/cloud": "0.1.12",
68
68
  "@modelcontextprotocol/sdk": "^1.12.1",
69
69
  "chalk": "^5.4.1",
70
70
  "commander": "^13.1.0",