@md2do/cli 0.3.1 → 0.5.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 (41) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +25 -0
  3. package/coverage/coverage-final.json +5 -4
  4. package/coverage/index.html +11 -11
  5. package/coverage/lcov-report/index.html +11 -11
  6. package/coverage/lcov-report/src/cli.ts.html +10 -4
  7. package/coverage/lcov-report/src/commands/config.ts.html +2269 -0
  8. package/coverage/lcov-report/src/commands/index.html +24 -9
  9. package/coverage/lcov-report/src/commands/index.ts.html +7 -4
  10. package/coverage/lcov-report/src/commands/list.ts.html +103 -22
  11. package/coverage/lcov-report/src/commands/stats.ts.html +1 -1
  12. package/coverage/lcov-report/src/commands/todoist.ts.html +1 -1
  13. package/coverage/lcov-report/src/formatters/index.html +1 -1
  14. package/coverage/lcov-report/src/formatters/json.ts.html +1 -1
  15. package/coverage/lcov-report/src/formatters/pretty.ts.html +1 -1
  16. package/coverage/lcov-report/src/index.html +7 -7
  17. package/coverage/lcov-report/src/index.ts.html +1 -1
  18. package/coverage/lcov-report/src/scanner.ts.html +87 -6
  19. package/coverage/lcov.info +817 -20
  20. package/coverage/src/cli.ts.html +10 -4
  21. package/coverage/src/commands/config.ts.html +2269 -0
  22. package/coverage/src/commands/index.html +24 -9
  23. package/coverage/src/commands/index.ts.html +7 -4
  24. package/coverage/src/commands/list.ts.html +103 -22
  25. package/coverage/src/commands/stats.ts.html +1 -1
  26. package/coverage/src/commands/todoist.ts.html +1 -1
  27. package/coverage/src/formatters/index.html +1 -1
  28. package/coverage/src/formatters/json.ts.html +1 -1
  29. package/coverage/src/formatters/pretty.ts.html +1 -1
  30. package/coverage/src/index.html +7 -7
  31. package/coverage/src/index.ts.html +1 -1
  32. package/coverage/src/scanner.ts.html +87 -6
  33. package/dist/cli.js +488 -12
  34. package/dist/index.d.ts +6 -1
  35. package/dist/index.js +483 -6
  36. package/package.json +7 -4
  37. package/src/cli.ts +2 -0
  38. package/src/commands/config.ts +731 -0
  39. package/src/commands/index.ts +1 -0
  40. package/src/commands/list.ts +16 -5
  41. package/src/scanner.ts +23 -1
package/dist/cli.js CHANGED
@@ -24,9 +24,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/cli.ts
27
- var import_commander4 = require("commander");
28
- var import_fs = require("fs");
29
- var import_path = require("path");
27
+ var import_commander5 = require("commander");
28
+ var import_fs2 = require("fs");
29
+ var import_path2 = require("path");
30
30
 
31
31
  // src/commands/list.ts
32
32
  var import_commander = require("commander");
@@ -49,7 +49,10 @@ async function scanMarkdownFiles(options = {}) {
49
49
  "**/build/**",
50
50
  "**/.next/**"
51
51
  ],
52
- followSymlinks = false
52
+ followSymlinks = false,
53
+ workdayStartTime,
54
+ workdayEndTime,
55
+ defaultDueTime
53
56
  } = options;
54
57
  const files = await (0, import_fast_glob.default)(pattern, {
55
58
  cwd: root,
@@ -65,7 +68,11 @@ async function scanMarkdownFiles(options = {}) {
65
68
  try {
66
69
  const fullPath = `${root}/${file}`;
67
70
  const content = await (0, import_promises.readFile)(fullPath, "utf-8");
68
- const result = scanner.scanFile(file, content);
71
+ const result = scanner.scanFile(file, content, {
72
+ ...workdayStartTime && { workdayStartTime },
73
+ ...workdayEndTime && { workdayEndTime },
74
+ ...defaultDueTime && { defaultDueTime }
75
+ });
69
76
  allTasks.push(...result.tasks);
70
77
  allWarnings.push(...result.warnings);
71
78
  } catch (error) {
@@ -299,10 +306,22 @@ function createListCommand() {
299
306
  "pretty"
300
307
  ).option("--no-colors", "Disable colors in output").option("--no-paths", "Hide file paths").option("--context", "Show context information (project, person, heading)").option("--no-warnings", "Hide all warnings").option("--all-warnings", "Show all warnings (default shows first 5)").action(async (options) => {
301
308
  try {
309
+ const config = await (0, import_config.loadConfig)({
310
+ cwd: options.path || process.cwd()
311
+ });
302
312
  const scanResult = await scanMarkdownFiles({
303
313
  root: options.path || process.cwd(),
304
314
  ...options.pattern !== void 0 && { pattern: options.pattern },
305
- ...options.exclude !== void 0 && { exclude: options.exclude }
315
+ ...options.exclude !== void 0 && { exclude: options.exclude },
316
+ ...config.workday?.startTime && {
317
+ workdayStartTime: config.workday.startTime
318
+ },
319
+ ...config.workday?.endTime && {
320
+ workdayEndTime: config.workday.endTime
321
+ },
322
+ ...config.workday?.defaultDueTime && {
323
+ defaultDueTime: config.workday.defaultDueTime
324
+ }
306
325
  });
307
326
  let tasks = scanResult.tasks;
308
327
  const taskFilters = [];
@@ -395,9 +414,6 @@ function createListCommand() {
395
414
  }
396
415
  console.log(output);
397
416
  if (options.warnings !== false) {
398
- const config = await (0, import_config.loadConfig)({
399
- cwd: options.path || process.cwd()
400
- });
401
417
  const warningConfig = config.warnings ?? import_config.DEFAULT_CONFIG.warnings;
402
418
  const filteredWarnings = (0, import_core2.filterWarnings)(
403
419
  scanResult.warnings,
@@ -1186,21 +1202,481 @@ async function todoistSyncAction(options) {
1186
1202
  console.log("");
1187
1203
  }
1188
1204
 
1205
+ // src/commands/config.ts
1206
+ var import_commander4 = require("commander");
1207
+ var import_config3 = require("@md2do/config");
1208
+ var import_fs = require("fs");
1209
+ var import_path = require("path");
1210
+ var import_os = require("os");
1211
+ var import_child_process = require("child_process");
1212
+ var import_js_yaml = __toESM(require("js-yaml"));
1213
+ function createConfigCommand() {
1214
+ const command = new import_commander4.Command("config");
1215
+ command.description("Manage md2do configuration");
1216
+ command.addCommand(createConfigInitCommand());
1217
+ command.addCommand(createConfigSetCommand());
1218
+ command.addCommand(createConfigGetCommand());
1219
+ command.addCommand(createConfigListCommand());
1220
+ command.addCommand(createConfigEditCommand());
1221
+ command.addCommand(createConfigValidateCommand());
1222
+ return command;
1223
+ }
1224
+ function createConfigInitCommand() {
1225
+ const command = new import_commander4.Command("init");
1226
+ command.description("Initialize md2do configuration with interactive prompts").option("-g, --global", "Create global configuration in home directory").option(
1227
+ "--format <type>",
1228
+ "Config file format (json|yaml|js)",
1229
+ "json"
1230
+ ).option("--default-assignee <username>", "Default assignee username").option("--workday-start <time>", "Work day start time (HH:MM)").option("--workday-end <time>", "Work day end time (HH:MM)").option(
1231
+ "--default-due-time <when>",
1232
+ "Default due time (start|end)",
1233
+ "end"
1234
+ ).option(
1235
+ "--output-format <type>",
1236
+ "Output format (pretty|table|json)",
1237
+ "pretty"
1238
+ ).option("--no-colors", "Disable colored output").option(
1239
+ "--warnings <level>",
1240
+ "Warning level (recommended|strict|off)",
1241
+ "recommended"
1242
+ ).action(async (options) => {
1243
+ try {
1244
+ await configInitAction(options);
1245
+ } catch (error) {
1246
+ if (error instanceof Error && error.message === "canceled") {
1247
+ const p = await import("@clack/prompts");
1248
+ p.cancel("Configuration canceled");
1249
+ process.exit(0);
1250
+ }
1251
+ console.error(
1252
+ "Error:",
1253
+ error instanceof Error ? error.message : String(error)
1254
+ );
1255
+ process.exit(1);
1256
+ }
1257
+ });
1258
+ return command;
1259
+ }
1260
+ async function configInitAction(options) {
1261
+ const p = await import("@clack/prompts");
1262
+ p.intro("Welcome to md2do configuration!");
1263
+ const hasAnyOption = options.defaultAssignee !== void 0 || options.workdayStart !== void 0 || options.workdayEnd !== void 0 || options.defaultDueTime !== void 0 || options.outputFormat !== void 0 || options.colors !== void 0 || options.warnings !== void 0;
1264
+ const interactive = !hasAnyOption;
1265
+ const config = {};
1266
+ if (interactive) {
1267
+ const defaultAssignee = await p.text({
1268
+ message: "Your username (for filtering tasks):",
1269
+ placeholder: "Leave empty to skip",
1270
+ validate: (value) => {
1271
+ if (value && !/^[a-zA-Z0-9_-]+$/.test(value)) {
1272
+ return "Username should only contain letters, numbers, dashes, and underscores";
1273
+ }
1274
+ }
1275
+ });
1276
+ const workdayStart = await p.text({
1277
+ message: "Work day start time (HH:MM):",
1278
+ initialValue: "08:00",
1279
+ validate: (value) => {
1280
+ if (typeof value === "string" && !/^\d{2}:\d{2}$/.test(value)) {
1281
+ return "Time must be in HH:MM format";
1282
+ }
1283
+ }
1284
+ });
1285
+ const workdayEnd = await p.text({
1286
+ message: "Work day end time (HH:MM):",
1287
+ initialValue: "17:00",
1288
+ validate: (value) => {
1289
+ if (typeof value === "string" && !/^\d{2}:\d{2}$/.test(value)) {
1290
+ return "Time must be in HH:MM format";
1291
+ }
1292
+ }
1293
+ });
1294
+ const defaultDueTime = await p.select({
1295
+ message: "Default due time:",
1296
+ options: [
1297
+ { value: "end", label: "End of day" },
1298
+ { value: "start", label: "Start of day" }
1299
+ ],
1300
+ initialValue: "end"
1301
+ });
1302
+ const outputFormat = await p.select({
1303
+ message: "Output format:",
1304
+ options: [
1305
+ { value: "pretty", label: "Pretty (human-readable)" },
1306
+ { value: "table", label: "Table (structured)" },
1307
+ { value: "json", label: "JSON (machine-readable)" }
1308
+ ],
1309
+ initialValue: "pretty"
1310
+ });
1311
+ const colors = await p.confirm({
1312
+ message: "Enable colored output?",
1313
+ initialValue: true
1314
+ });
1315
+ const warnings = await p.select({
1316
+ message: "Warning level:",
1317
+ options: [
1318
+ {
1319
+ value: "recommended",
1320
+ label: "Recommended (validates format, metadata optional)"
1321
+ },
1322
+ {
1323
+ value: "strict",
1324
+ label: "Strict (enforces complete metadata)"
1325
+ },
1326
+ { value: "off", label: "Off (no warnings)" }
1327
+ ],
1328
+ initialValue: "recommended"
1329
+ });
1330
+ if (defaultAssignee && typeof defaultAssignee === "string") {
1331
+ config.defaultAssignee = defaultAssignee;
1332
+ }
1333
+ config.workday = {
1334
+ startTime: typeof workdayStart === "string" ? workdayStart : "08:00",
1335
+ endTime: typeof workdayEnd === "string" ? workdayEnd : "17:00",
1336
+ defaultDueTime: typeof defaultDueTime === "string" ? defaultDueTime : "end"
1337
+ };
1338
+ config.output = {
1339
+ format: typeof outputFormat === "string" ? outputFormat : "pretty",
1340
+ colors: typeof colors === "boolean" ? colors : true,
1341
+ paths: true
1342
+ };
1343
+ if (typeof warnings === "string" && warnings === "off") {
1344
+ config.warnings = { enabled: false };
1345
+ } else if (typeof warnings === "string" && warnings === "strict") {
1346
+ config.warnings = {
1347
+ enabled: true,
1348
+ rules: {
1349
+ "unsupported-bullet": "warn",
1350
+ "malformed-checkbox": "warn",
1351
+ "missing-space-after": "warn",
1352
+ "missing-space-before": "warn",
1353
+ "relative-date-no-context": "warn",
1354
+ "missing-due-date": "warn",
1355
+ "missing-completed-date": "warn",
1356
+ "duplicate-todoist-id": "error",
1357
+ "file-read-error": "error"
1358
+ }
1359
+ };
1360
+ }
1361
+ } else {
1362
+ if (options.defaultAssignee) {
1363
+ config.defaultAssignee = options.defaultAssignee;
1364
+ }
1365
+ config.workday = {
1366
+ startTime: options.workdayStart || "08:00",
1367
+ endTime: options.workdayEnd || "17:00",
1368
+ defaultDueTime: options.defaultDueTime || "end"
1369
+ };
1370
+ config.output = {
1371
+ format: options.outputFormat || "pretty",
1372
+ colors: options.colors ?? true,
1373
+ paths: true
1374
+ };
1375
+ if (options.warnings === "off") {
1376
+ config.warnings = { enabled: false };
1377
+ } else if (options.warnings === "strict") {
1378
+ config.warnings = {
1379
+ enabled: true,
1380
+ rules: {
1381
+ "unsupported-bullet": "warn",
1382
+ "malformed-checkbox": "warn",
1383
+ "missing-space-after": "warn",
1384
+ "missing-space-before": "warn",
1385
+ "relative-date-no-context": "warn",
1386
+ "missing-due-date": "warn",
1387
+ "missing-completed-date": "warn",
1388
+ "duplicate-todoist-id": "error",
1389
+ "file-read-error": "error"
1390
+ }
1391
+ };
1392
+ }
1393
+ }
1394
+ try {
1395
+ (0, import_config3.validateConfig)(config);
1396
+ } catch (error) {
1397
+ p.cancel(
1398
+ `Invalid configuration: ${error instanceof Error ? error.message : String(error)}`
1399
+ );
1400
+ process.exit(1);
1401
+ }
1402
+ const format = options.format || "json";
1403
+ const configPath = getConfigPath(options.global || false, format);
1404
+ if ((0, import_fs.existsSync)(configPath)) {
1405
+ if (interactive) {
1406
+ const overwrite = await p.confirm({
1407
+ message: `Configuration file already exists at ${configPath}. Overwrite?`,
1408
+ initialValue: false
1409
+ });
1410
+ if (!overwrite) {
1411
+ p.cancel("Configuration canceled");
1412
+ process.exit(0);
1413
+ }
1414
+ }
1415
+ }
1416
+ writeConfigFile(configPath, config, format);
1417
+ p.outro(`\u2713 Configuration saved to ${configPath}`);
1418
+ }
1419
+ function createConfigSetCommand() {
1420
+ const command = new import_commander4.Command("set");
1421
+ command.description("Set a configuration value").argument("<key>", "Configuration key (e.g., workday.startTime)").argument("<value>", "Configuration value").option("-g, --global", "Set in global configuration").action((key, value, options) => {
1422
+ try {
1423
+ configSetAction(key, value, options);
1424
+ } catch (error) {
1425
+ console.error(
1426
+ "Error:",
1427
+ error instanceof Error ? error.message : String(error)
1428
+ );
1429
+ process.exit(1);
1430
+ }
1431
+ });
1432
+ return command;
1433
+ }
1434
+ function configSetAction(key, value, options) {
1435
+ const isGlobal = options.global || false;
1436
+ const configPath = findExistingConfigPath(isGlobal);
1437
+ let config = {};
1438
+ let format = "json";
1439
+ if (configPath) {
1440
+ format = getConfigFormat(configPath);
1441
+ const content = (0, import_fs.readFileSync)(configPath, "utf-8");
1442
+ config = parseConfigFile(content, format);
1443
+ } else {
1444
+ format = "json";
1445
+ }
1446
+ const parsedValue = parseValue(value);
1447
+ setNestedValue(config, key, parsedValue);
1448
+ try {
1449
+ (0, import_config3.validateConfig)(config);
1450
+ } catch (error) {
1451
+ console.error(
1452
+ `Invalid configuration: ${error instanceof Error ? error.message : String(error)}`
1453
+ );
1454
+ process.exit(1);
1455
+ }
1456
+ const finalPath = configPath || getConfigPath(isGlobal, format);
1457
+ writeConfigFile(finalPath, config, format);
1458
+ console.log(`\u2713 Set ${key} = ${value} in ${finalPath}`);
1459
+ }
1460
+ function createConfigGetCommand() {
1461
+ const command = new import_commander4.Command("get");
1462
+ command.description("Get a configuration value").argument("<key>", "Configuration key (e.g., workday.startTime)").option("-g, --global", "Get from global configuration only").action(async (key, options) => {
1463
+ try {
1464
+ await configGetAction(key, options);
1465
+ } catch (error) {
1466
+ console.error(
1467
+ "Error:",
1468
+ error instanceof Error ? error.message : String(error)
1469
+ );
1470
+ process.exit(1);
1471
+ }
1472
+ });
1473
+ return command;
1474
+ }
1475
+ async function configGetAction(key, options) {
1476
+ const config = options.global ? await (0, import_config3.loadConfig)({ loadGlobal: true, loadEnv: false, cwd: (0, import_os.homedir)() }) : await (0, import_config3.loadConfig)();
1477
+ const value = getNestedValue(config, key);
1478
+ if (value === void 0) {
1479
+ console.log("(not set)");
1480
+ } else if (typeof value === "object") {
1481
+ console.log(JSON.stringify(value, null, 2));
1482
+ } else {
1483
+ console.log(value);
1484
+ }
1485
+ }
1486
+ function createConfigListCommand() {
1487
+ const command = new import_commander4.Command("list");
1488
+ command.description("Show all configuration values").option("--show-origin", "Show where each value comes from").action(async (options) => {
1489
+ try {
1490
+ await configListAction(options);
1491
+ } catch (error) {
1492
+ console.error(
1493
+ "Error:",
1494
+ error instanceof Error ? error.message : String(error)
1495
+ );
1496
+ process.exit(1);
1497
+ }
1498
+ });
1499
+ return command;
1500
+ }
1501
+ async function configListAction(options) {
1502
+ const config = await (0, import_config3.loadConfig)();
1503
+ console.log("");
1504
+ console.log("Current configuration:");
1505
+ console.log("");
1506
+ console.log(JSON.stringify(config, null, 2));
1507
+ console.log("");
1508
+ if (options.showOrigin) {
1509
+ console.log("Configuration sources:");
1510
+ console.log(" 1. Default values (built-in)");
1511
+ console.log(` 2. Global config (${getConfigPath(true, "json")})`);
1512
+ console.log(` 3. Project config (${getConfigPath(false, "json")})`);
1513
+ console.log(" 4. Environment variables");
1514
+ console.log("");
1515
+ }
1516
+ }
1517
+ function createConfigEditCommand() {
1518
+ const command = new import_commander4.Command("edit");
1519
+ command.description("Open configuration file in your default editor").option("-g, --global", "Edit global configuration").action((options) => {
1520
+ try {
1521
+ configEditAction(options);
1522
+ } catch (error) {
1523
+ console.error(
1524
+ "Error:",
1525
+ error instanceof Error ? error.message : String(error)
1526
+ );
1527
+ process.exit(1);
1528
+ }
1529
+ });
1530
+ return command;
1531
+ }
1532
+ function configEditAction(options) {
1533
+ const isGlobal = options.global || false;
1534
+ let configPath = findExistingConfigPath(isGlobal);
1535
+ if (!configPath) {
1536
+ configPath = getConfigPath(isGlobal, "json");
1537
+ writeConfigFile(configPath, {}, "json");
1538
+ console.log(`Created new configuration file: ${configPath}`);
1539
+ }
1540
+ const editor = process.env.VISUAL || process.env.EDITOR || (process.platform === "win32" ? "notepad" : "vi");
1541
+ console.log(`Opening ${configPath} in ${editor}...`);
1542
+ try {
1543
+ (0, import_child_process.execSync)(`${editor} '${configPath}'`, { stdio: "inherit" });
1544
+ } catch (error) {
1545
+ console.error("Failed to open editor");
1546
+ console.error(`You can manually edit the file at: ${configPath}`);
1547
+ process.exit(1);
1548
+ }
1549
+ }
1550
+ function createConfigValidateCommand() {
1551
+ const command = new import_commander4.Command("validate");
1552
+ command.description("Validate current configuration").action(async () => {
1553
+ try {
1554
+ await configValidateAction();
1555
+ } catch (error) {
1556
+ console.error(
1557
+ "Error:",
1558
+ error instanceof Error ? error.message : String(error)
1559
+ );
1560
+ process.exit(1);
1561
+ }
1562
+ });
1563
+ return command;
1564
+ }
1565
+ async function configValidateAction() {
1566
+ try {
1567
+ const config = await (0, import_config3.loadConfig)();
1568
+ (0, import_config3.validateConfig)(config);
1569
+ console.log("\u2713 Configuration is valid");
1570
+ } catch (error) {
1571
+ console.error(
1572
+ `Invalid configuration: ${error instanceof Error ? error.message : String(error)}`
1573
+ );
1574
+ process.exit(1);
1575
+ }
1576
+ }
1577
+ function getConfigPath(isGlobal, format) {
1578
+ const base = isGlobal ? (0, import_os.homedir)() : process.cwd();
1579
+ const fileName = format === "json" ? ".md2do.json" : format === "yaml" ? ".md2do.yaml" : ".md2do.js";
1580
+ return (0, import_path.join)(base, fileName);
1581
+ }
1582
+ function findExistingConfigPath(isGlobal) {
1583
+ const base = isGlobal ? (0, import_os.homedir)() : process.cwd();
1584
+ const possibleFiles = [
1585
+ ".md2do.json",
1586
+ ".md2do.yaml",
1587
+ ".md2do.yml",
1588
+ ".md2do.js",
1589
+ ".md2do.cjs",
1590
+ "md2do.config.js",
1591
+ "md2do.config.cjs"
1592
+ ];
1593
+ for (const file of possibleFiles) {
1594
+ const path = (0, import_path.join)(base, file);
1595
+ if ((0, import_fs.existsSync)(path)) {
1596
+ return path;
1597
+ }
1598
+ }
1599
+ return null;
1600
+ }
1601
+ function getConfigFormat(path) {
1602
+ if (path.endsWith(".json")) return "json";
1603
+ if (path.endsWith(".yaml") || path.endsWith(".yml")) return "yaml";
1604
+ return "js";
1605
+ }
1606
+ function parseConfigFile(content, format) {
1607
+ if (format === "json") {
1608
+ return JSON.parse(content);
1609
+ } else if (format === "yaml") {
1610
+ const loaded = import_js_yaml.default.load(content);
1611
+ return loaded || {};
1612
+ } else {
1613
+ return JSON.parse(content);
1614
+ }
1615
+ }
1616
+ function writeConfigFile(path, config, format) {
1617
+ let content;
1618
+ if (format === "json") {
1619
+ content = JSON.stringify(config, null, 2) + "\n";
1620
+ } else if (format === "yaml") {
1621
+ content = import_js_yaml.default.dump(config);
1622
+ } else {
1623
+ content = `module.exports = ${JSON.stringify(config, null, 2)};
1624
+ `;
1625
+ }
1626
+ (0, import_fs.writeFileSync)(path, content, "utf-8");
1627
+ }
1628
+ function parseValue(value) {
1629
+ if (value === "true") return true;
1630
+ if (value === "false") return false;
1631
+ const num = Number(value);
1632
+ if (!isNaN(num)) return num;
1633
+ try {
1634
+ return JSON.parse(value);
1635
+ } catch {
1636
+ return value;
1637
+ }
1638
+ }
1639
+ function getNestedValue(obj, path) {
1640
+ const keys = path.split(".");
1641
+ let current = obj;
1642
+ for (const key of keys) {
1643
+ if (current === null || current === void 0 || typeof current !== "object") {
1644
+ return void 0;
1645
+ }
1646
+ current = current[key];
1647
+ }
1648
+ return current;
1649
+ }
1650
+ function setNestedValue(obj, path, value) {
1651
+ const keys = path.split(".");
1652
+ const lastKey = keys.pop();
1653
+ if (!lastKey) return;
1654
+ let current = obj;
1655
+ for (const key of keys) {
1656
+ if (!(key in current) || typeof current[key] !== "object") {
1657
+ current[key] = {};
1658
+ }
1659
+ current = current[key];
1660
+ }
1661
+ current[lastKey] = value;
1662
+ }
1663
+
1189
1664
  // src/cli.ts
1190
1665
  var getVersion = () => {
1191
1666
  try {
1192
- const packagePath = (0, import_path.join)(__dirname, "../package.json");
1193
- const packageJson = JSON.parse((0, import_fs.readFileSync)(packagePath, "utf-8"));
1667
+ const packagePath = (0, import_path2.join)(__dirname, "../package.json");
1668
+ const packageJson = JSON.parse((0, import_fs2.readFileSync)(packagePath, "utf-8"));
1194
1669
  return packageJson.version;
1195
1670
  } catch {
1196
1671
  return "0.0.0";
1197
1672
  }
1198
1673
  };
1199
- var program = new import_commander4.Command();
1674
+ var program = new import_commander5.Command();
1200
1675
  program.name("md2do").description("Scan and manage TODOs in markdown files").version(getVersion());
1201
1676
  program.addCommand(createListCommand());
1202
1677
  program.addCommand(createStatsCommand());
1203
1678
  program.addCommand(createTodoistCommand());
1679
+ program.addCommand(createConfigCommand());
1204
1680
  if (process.argv.length === 2) {
1205
1681
  program.help();
1206
1682
  }
package/dist/index.d.ts CHANGED
@@ -9,4 +9,9 @@ declare function createStatsCommand(): Command;
9
9
  */
10
10
  declare function createTodoistCommand(): Command;
11
11
 
12
- export { createListCommand, createStatsCommand, createTodoistCommand };
12
+ /**
13
+ * Create the config command group
14
+ */
15
+ declare function createConfigCommand(): Command;
16
+
17
+ export { createConfigCommand, createListCommand, createStatsCommand, createTodoistCommand };