@tasklumina/cli 1.0.1 → 1.1.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 (2) hide show
  1. package/dist/index.js +133 -68
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -507,8 +507,8 @@ var listLists = (
507
507
  var listListItems = (
508
508
  /* GraphQL */
509
509
  `
510
- query ListListItems($listId: ID!) {
511
- listListItems(listId: $listId) {
510
+ query ListListItems($listId: ID!, $completed: Boolean) {
511
+ listListItems(listId: $listId, completed: $completed) {
512
512
  id
513
513
  listId
514
514
  name
@@ -518,6 +518,8 @@ var listListItems = (
518
518
  tags
519
519
  link
520
520
  customFields
521
+ completed
522
+ completedBy
521
523
  position
522
524
  createdAt
523
525
  updatedAt
@@ -949,6 +951,8 @@ var createListItem = (
949
951
  tags
950
952
  link
951
953
  customFields
954
+ completed
955
+ completedBy
952
956
  position
953
957
  createdAt
954
958
  updatedAt
@@ -970,6 +974,8 @@ var updateListItem = (
970
974
  tags
971
975
  link
972
976
  customFields
977
+ completed
978
+ completedBy
973
979
  position
974
980
  createdAt
975
981
  updatedAt
@@ -1718,9 +1724,9 @@ categoriesCommand.command("create").description("Create a category").argument("<
1718
1724
  try {
1719
1725
  validateStringLength(name, "Name", 100);
1720
1726
  if (opts.color) validateHexColor(opts.color);
1721
- const input2 = { id: randomUUID(), name, position: Date.now() };
1722
- if (opts.color) input2.color = opts.color;
1723
- const data = await graphql(createCategory, { input: input2 });
1727
+ const input = { id: randomUUID(), name, position: Date.now() };
1728
+ if (opts.color) input.color = opts.color;
1729
+ const data = await graphql(createCategory, { input });
1724
1730
  if (isJsonMode()) {
1725
1731
  printJson(data.createCategory);
1726
1732
  return;
@@ -1736,10 +1742,10 @@ categoriesCommand.command("update").description("Update a category").argument("<
1736
1742
  validateUuid(id, "Category ID");
1737
1743
  if (opts.name) validateStringLength(opts.name, "Name", 100);
1738
1744
  if (opts.color) validateHexColor(opts.color);
1739
- const input2 = { id };
1740
- if (opts.name) input2.name = opts.name;
1741
- if (opts.color) input2.color = opts.color;
1742
- const data = await graphql(updateCategory, { input: input2 });
1745
+ const input = { id };
1746
+ if (opts.name) input.name = opts.name;
1747
+ if (opts.color) input.color = opts.color;
1748
+ const data = await graphql(updateCategory, { input });
1743
1749
  if (isJsonMode()) {
1744
1750
  printJson(data.updateCategory);
1745
1751
  return;
@@ -1811,9 +1817,9 @@ tagsCommand.command("update").description("Update a tag").argument("<id>", "Tag
1811
1817
  try {
1812
1818
  validateUuid(id, "Tag ID");
1813
1819
  if (opts.name) validateStringLength(opts.name, "Tag name", 100);
1814
- const input2 = { id };
1815
- if (opts.name) input2.name = opts.name;
1816
- const data = await graphql(updateTag, { input: input2 });
1820
+ const input = { id };
1821
+ if (opts.name) input.name = opts.name;
1822
+ const data = await graphql(updateTag, { input });
1817
1823
  if (isJsonMode()) {
1818
1824
  printJson(data.updateTag);
1819
1825
  return;
@@ -1958,16 +1964,16 @@ contactsCommand.command("create").description("Create a contact").argument("<nam
1958
1964
  contactsCommand.command("update").description("Update a contact").argument("<id>", "Contact ID").option("--name <name>", "New name").option("--email <email>", "New email").action(async (id, opts) => {
1959
1965
  try {
1960
1966
  validateUuid(id, "Contact ID");
1961
- const input2 = { id };
1967
+ const input = { id };
1962
1968
  if (opts.name) {
1963
1969
  validateStringLength(opts.name, "Name", 200);
1964
- input2.name = opts.name;
1970
+ input.name = opts.name;
1965
1971
  }
1966
1972
  if (opts.email) {
1967
1973
  validateEmail(opts.email);
1968
- input2.email = opts.email;
1974
+ input.email = opts.email;
1969
1975
  }
1970
- const data = await graphql(updateContact, { input: input2 });
1976
+ const data = await graphql(updateContact, { input });
1971
1977
  if (isJsonMode()) {
1972
1978
  printJson(data.updateContact);
1973
1979
  return;
@@ -2034,9 +2040,9 @@ prefsCommand.command("set").description("Update a preference").option("--theme <
2034
2040
  if (opts.defaultView) validateView(opts.defaultView);
2035
2041
  if (opts.defaultPriority && opts.defaultPriority !== "none") validatePriority(opts.defaultPriority);
2036
2042
  if (opts.defaultColor && opts.defaultColor !== "none") validateHexColor(opts.defaultColor);
2037
- const input2 = {};
2038
- if (opts.theme) input2.theme = opts.theme;
2039
- if (opts.defaultView) input2.defaultView = opts.defaultView;
2043
+ const input = {};
2044
+ if (opts.theme) input.theme = opts.theme;
2045
+ if (opts.defaultView) input.defaultView = opts.defaultView;
2040
2046
  if (opts.archiveDelay) {
2041
2047
  const delay = parseInt(opts.archiveDelay, 10);
2042
2048
  if (isNaN(delay) || delay < 0 || delay > 8760) {
@@ -2044,22 +2050,22 @@ prefsCommand.command("set").description("Update a preference").option("--theme <
2044
2050
  process.exitCode = 1;
2045
2051
  return;
2046
2052
  }
2047
- input2.archiveDelay = delay;
2053
+ input.archiveDelay = delay;
2048
2054
  }
2049
- if (opts.defaultPriority) input2.defaultPriority = opts.defaultPriority === "none" ? "" : opts.defaultPriority;
2050
- if (opts.defaultCategory) input2.defaultCategoryId = opts.defaultCategory === "none" ? "" : opts.defaultCategory;
2051
- if (opts.defaultColor) input2.defaultColor = opts.defaultColor === "none" ? "" : opts.defaultColor;
2052
- if (Object.keys(input2).length === 0) {
2055
+ if (opts.defaultPriority) input.defaultPriority = opts.defaultPriority === "none" ? "" : opts.defaultPriority;
2056
+ if (opts.defaultCategory) input.defaultCategoryId = opts.defaultCategory === "none" ? "" : opts.defaultCategory;
2057
+ if (opts.defaultColor) input.defaultColor = opts.defaultColor === "none" ? "" : opts.defaultColor;
2058
+ if (Object.keys(input).length === 0) {
2053
2059
  printError("Provide at least one option: --theme, --default-view, --archive-delay, --default-priority, --default-category, --default-color");
2054
2060
  process.exitCode = 1;
2055
2061
  return;
2056
2062
  }
2057
- const data = await graphql(updatePreferences, { input: input2 });
2063
+ const data = await graphql(updatePreferences, { input });
2058
2064
  if (isJsonMode()) {
2059
2065
  printJson(data.updatePreferences);
2060
2066
  return;
2061
2067
  }
2062
- for (const [key, value] of Object.entries(input2)) {
2068
+ for (const [key, value] of Object.entries(input)) {
2063
2069
  printSuccess(`Updated preference: ${key} = ${value}`);
2064
2070
  }
2065
2071
  } catch (err) {
@@ -2178,34 +2184,57 @@ colorRulesCommand.command("remove").description("Remove a color rule").argument(
2178
2184
 
2179
2185
  // src/commands/lists.ts
2180
2186
  import { Command as Command9 } from "commander";
2181
- import { randomUUID as randomUUID6 } from "crypto";
2182
2187
  import { confirm as confirm6 } from "@inquirer/prompts";
2183
- var listsCommand = new Command9("lists").description("Manage lists").action(async () => {
2188
+ var SORT_FIELDS = ["name", "created", "updated", "items"];
2189
+ function sortLists(lists, sort, reverse) {
2190
+ const sorted = [...lists].sort((a, b) => {
2191
+ switch (sort) {
2192
+ case "name":
2193
+ return a.name.localeCompare(b.name);
2194
+ case "created":
2195
+ return b.createdAt.localeCompare(a.createdAt);
2196
+ case "updated":
2197
+ return b.updatedAt.localeCompare(a.updatedAt);
2198
+ case "items":
2199
+ return b.itemCount - a.itemCount;
2200
+ }
2201
+ });
2202
+ return reverse ? sorted.reverse() : sorted;
2203
+ }
2204
+ var listsCommand = new Command9("lists").description("Manage lists").option("--sort <field>", "Sort by: name, created, updated, items (default: created)").option("--reverse", "Reverse sort order").action(async (opts) => {
2184
2205
  try {
2206
+ const sort = opts.sort && SORT_FIELDS.includes(opts.sort) ? opts.sort : "created";
2207
+ if (opts.sort && !SORT_FIELDS.includes(opts.sort)) {
2208
+ printError(`Invalid sort field: ${opts.sort}. Valid: ${SORT_FIELDS.join(", ")}`);
2209
+ process.exitCode = 1;
2210
+ return;
2211
+ }
2185
2212
  const data = await graphql(listLists);
2213
+ const lists = sortLists(data.listLists, sort, !!opts.reverse);
2186
2214
  if (isJsonMode()) {
2187
- printJson(data.listLists);
2215
+ printJson(lists);
2188
2216
  return;
2189
2217
  }
2190
- if (data.listLists.length === 0) {
2218
+ if (lists.length === 0) {
2191
2219
  console.log("No lists.");
2192
2220
  return;
2193
2221
  }
2194
2222
  printTable(
2195
2223
  ["ID", "Name", "Items", "Created"],
2196
- data.listLists.map((l) => [truncateId(l.id), l.name, String(l.itemCount), formatDate(l.createdAt)])
2224
+ lists.map((l) => [truncateId(l.id), l.name, String(l.itemCount), formatDate(l.createdAt)])
2197
2225
  );
2198
2226
  } catch (err) {
2199
2227
  printError(err.message);
2200
2228
  process.exitCode = 1;
2201
2229
  }
2202
2230
  });
2203
- listsCommand.command("show").description("Show a list with items").argument("<id>", "List ID").action(async (id) => {
2231
+ listsCommand.command("show").description("Show a list with items").argument("<id>", "List ID").option("--completed", "Show completed items (default: active)").action(async (id, opts) => {
2204
2232
  try {
2205
2233
  validateUuid(id, "List ID");
2234
+ const completed = opts.completed === true ? true : false;
2206
2235
  const [listsData, itemsData] = await Promise.all([
2207
2236
  graphql(listLists),
2208
- graphql(listListItems, { listId: id })
2237
+ graphql(listListItems, { listId: id, completed })
2209
2238
  ]);
2210
2239
  const list = listsData.listLists.find((l) => l.id === id || l.id.startsWith(id));
2211
2240
  if (!list) {
@@ -2224,11 +2253,21 @@ listsCommand.command("show").description("Show a list with items").argument("<id
2224
2253
  console.log(`Color: ${list.color || "\u2014"}`);
2225
2254
  console.log(`Items: ${list.itemCount}`);
2226
2255
  console.log(`Created: ${formatDate(list.createdAt)}`);
2227
- if (itemsData.listListItems.length > 0) {
2256
+ console.log(`Showing: ${completed ? "Completed" : "Active"} items`);
2257
+ if (itemsData.listListItems.length === 0) {
2258
+ console.log(`
2259
+ No ${completed ? "completed" : "active"} items.`);
2260
+ } else {
2228
2261
  console.log("\nItems:");
2229
2262
  printTable(
2230
- ["ID", "Name", "Qty", "Category"],
2231
- itemsData.listListItems.map((i) => [truncateId(i.id), i.name, i.quantity != null ? String(i.quantity) : "\u2014", i.category || "\u2014"])
2263
+ ["ID", "Name", "Qty", "Category", "Done"],
2264
+ itemsData.listListItems.map((i) => [
2265
+ truncateId(i.id),
2266
+ i.name,
2267
+ i.quantity != null ? String(i.quantity) : "\u2014",
2268
+ i.category || "\u2014",
2269
+ i.completed ? `\u2713 ${i.completedBy || ""}`.trim() : "\u2014"
2270
+ ])
2232
2271
  );
2233
2272
  }
2234
2273
  } catch (err) {
@@ -2241,11 +2280,11 @@ listsCommand.command("create").description("Create a list").argument("<name>", "
2241
2280
  validateStringLength(name, "Name", 200);
2242
2281
  if (opts.desc) validateStringLength(opts.desc, "Description", 2e3);
2243
2282
  if (opts.color) validateHexColor(opts.color);
2244
- const input2 = { id: randomUUID6(), name };
2245
- if (opts.desc) input2.description = opts.desc;
2246
- if (opts.icon) input2.icon = opts.icon;
2247
- if (opts.color) input2.color = opts.color;
2248
- const data = await graphql(createList, { input: input2 });
2283
+ const input = { name };
2284
+ if (opts.desc) input.description = opts.desc;
2285
+ if (opts.icon) input.icon = opts.icon;
2286
+ if (opts.color) input.color = opts.color;
2287
+ const data = await graphql(createList, { input });
2249
2288
  if (isJsonMode()) {
2250
2289
  printJson(data.createList);
2251
2290
  return;
@@ -2262,12 +2301,12 @@ listsCommand.command("update").description("Update a list").argument("<id>", "Li
2262
2301
  if (opts.name) validateStringLength(opts.name, "Name", 200);
2263
2302
  if (opts.desc) validateStringLength(opts.desc, "Description", 2e3);
2264
2303
  if (opts.color) validateHexColor(opts.color);
2265
- const input2 = { id };
2266
- if (opts.name) input2.name = opts.name;
2267
- if (opts.desc) input2.description = opts.desc;
2268
- if (opts.icon) input2.icon = opts.icon;
2269
- if (opts.color) input2.color = opts.color;
2270
- const data = await graphql(updateList, { input: input2 });
2304
+ const input = { id };
2305
+ if (opts.name) input.name = opts.name;
2306
+ if (opts.desc) input.description = opts.desc;
2307
+ if (opts.icon) input.icon = opts.icon;
2308
+ if (opts.color) input.color = opts.color;
2309
+ const data = await graphql(updateList, { input });
2271
2310
  if (isJsonMode()) {
2272
2311
  printJson(data.updateList);
2273
2312
  return;
@@ -2305,11 +2344,11 @@ listsCommand.command("add-item").description("Add an item to a list").argument("
2305
2344
  validateStringLength(name, "Name", 500);
2306
2345
  if (opts.qty) validateQuantity(opts.qty);
2307
2346
  if (opts.link) validateUrl(opts.link);
2308
- const input2 = { id: randomUUID6(), listId, name, tags: [], customFields: "{}", position: Date.now() };
2309
- if (opts.qty) input2.quantity = validateQuantity(opts.qty);
2310
- if (opts.category) input2.category = opts.category;
2311
- if (opts.link) input2.link = opts.link;
2312
- const data = await graphql(createListItem, { input: input2 });
2347
+ const input = { listId, name };
2348
+ if (opts.qty) input.quantity = validateQuantity(opts.qty);
2349
+ if (opts.category) input.category = opts.category;
2350
+ if (opts.link) input.link = opts.link;
2351
+ const data = await graphql(createListItem, { input });
2313
2352
  if (isJsonMode()) {
2314
2353
  printJson(data.createListItem);
2315
2354
  return;
@@ -2326,16 +2365,8 @@ listsCommand.command("bulk-add").description("Add multiple items to a list").arg
2326
2365
  for (const name of items) {
2327
2366
  validateStringLength(name, "Item name", 500);
2328
2367
  }
2329
- const itemInputs = items.map((name, i) => ({
2330
- id: randomUUID6(),
2331
- listId,
2332
- name,
2333
- tags: [],
2334
- customFields: "{}",
2335
- position: Date.now() + i
2336
- }));
2337
2368
  const data = await graphql(bulkCreateListItems, {
2338
- input: { listId, items: itemInputs }
2369
+ input: { listId, names: items }
2339
2370
  });
2340
2371
  if (isJsonMode()) {
2341
2372
  printJson(data.bulkCreateListItems);
@@ -2354,12 +2385,12 @@ listsCommand.command("update-item").description("Update a list item").argument("
2354
2385
  if (opts.name) validateStringLength(opts.name, "Name", 500);
2355
2386
  if (opts.qty) validateQuantity(opts.qty);
2356
2387
  if (opts.link) validateUrl(opts.link);
2357
- const input2 = { id: itemId, listId: opts.list };
2358
- if (opts.name) input2.name = opts.name;
2359
- if (opts.qty) input2.quantity = validateQuantity(opts.qty);
2360
- if (opts.category) input2.category = opts.category;
2361
- if (opts.link) input2.link = opts.link;
2362
- const data = await graphql(updateListItem, { input: input2 });
2388
+ const input = { id: itemId, listId: opts.list };
2389
+ if (opts.name) input.name = opts.name;
2390
+ if (opts.qty) input.quantity = validateQuantity(opts.qty);
2391
+ if (opts.category) input.category = opts.category;
2392
+ if (opts.link) input.link = opts.link;
2393
+ const data = await graphql(updateListItem, { input });
2363
2394
  if (isJsonMode()) {
2364
2395
  printJson(data.updateListItem);
2365
2396
  return;
@@ -2392,6 +2423,40 @@ listsCommand.command("remove-item").description("Remove a list item").argument("
2392
2423
  process.exitCode = 1;
2393
2424
  }
2394
2425
  });
2426
+ listsCommand.command("check").description("Mark a list item as complete").argument("<item-id>", "Item ID").requiredOption("--list <list-id>", "List ID").action(async (itemId, opts) => {
2427
+ try {
2428
+ validateUuid(itemId, "Item ID");
2429
+ validateUuid(opts.list, "List ID");
2430
+ const data = await graphql(updateListItem, {
2431
+ input: { id: itemId, listId: opts.list, completed: true }
2432
+ });
2433
+ if (isJsonMode()) {
2434
+ printJson(data.updateListItem);
2435
+ return;
2436
+ }
2437
+ printSuccess(`Marked complete: ${data.updateListItem.name}`);
2438
+ } catch (err) {
2439
+ printError(err.message);
2440
+ process.exitCode = 1;
2441
+ }
2442
+ });
2443
+ listsCommand.command("uncheck").description("Mark a list item as active (not complete)").argument("<item-id>", "Item ID").requiredOption("--list <list-id>", "List ID").action(async (itemId, opts) => {
2444
+ try {
2445
+ validateUuid(itemId, "Item ID");
2446
+ validateUuid(opts.list, "List ID");
2447
+ const data = await graphql(updateListItem, {
2448
+ input: { id: itemId, listId: opts.list, completed: false }
2449
+ });
2450
+ if (isJsonMode()) {
2451
+ printJson(data.updateListItem);
2452
+ return;
2453
+ }
2454
+ printSuccess(`Marked active: ${data.updateListItem.name}`);
2455
+ } catch (err) {
2456
+ printError(err.message);
2457
+ process.exitCode = 1;
2458
+ }
2459
+ });
2395
2460
 
2396
2461
  // src/commands/shares.ts
2397
2462
  import { Command as Command10 } from "commander";
@@ -2846,7 +2911,7 @@ apikeysCommand.command("revoke").description("Revoke an API key").argument("<id>
2846
2911
 
2847
2912
  // src/index.ts
2848
2913
  var program = new Command13();
2849
- program.name("tasklumina").version("1.0.0").description("Task Lumina CLI \u2014 manage tasks from the terminal").option("--json", "Output as JSON").option("--no-color", "Disable colored output").option("--verbose", "Show detailed request info (endpoint masked)").option("--redact", "Mask emails and sensitive data in output");
2914
+ program.name("tasklumina").version("1.0.3").description("Task Lumina CLI \u2014 manage tasks from the terminal").option("--json", "Output as JSON").option("--no-color", "Disable colored output").option("--verbose", "Show detailed request info (endpoint masked)").option("--redact", "Mask emails and sensitive data in output");
2850
2915
  program.hook("postAction", async () => {
2851
2916
  await maybeAutoRotate();
2852
2917
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tasklumina/cli",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "Task Lumina CLI — manage tasks, notes, categories, and shares from the terminal",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -26,15 +26,15 @@
26
26
  "prepublishOnly": "npm run build"
27
27
  },
28
28
  "dependencies": {
29
+ "@inquirer/prompts": "^7.3.2",
29
30
  "chalk": "^5.4.1",
30
31
  "cli-table3": "^0.6.5",
31
32
  "commander": "^13.1.0",
32
- "@inquirer/prompts": "^7.3.2",
33
33
  "keytar": "^7.9.0"
34
34
  },
35
35
  "devDependencies": {
36
+ "@types/node": "^22.0.0",
36
37
  "tsup": "^8.4.0",
37
- "typescript": "~5.7.0",
38
- "@types/node": "^22.0.0"
38
+ "typescript": "~5.7.0"
39
39
  }
40
40
  }