@sudocode-ai/cli 0.1.0 → 0.1.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.
Files changed (112) hide show
  1. package/dist/cli/feedback-commands.d.ts.map +1 -0
  2. package/dist/cli/feedback-commands.js +274 -0
  3. package/dist/cli/feedback-commands.js.map +1 -0
  4. package/dist/cli/init-commands.d.ts.map +1 -0
  5. package/dist/cli/init-commands.js +148 -0
  6. package/dist/cli/init-commands.js.map +1 -0
  7. package/dist/cli/issue-commands.d.ts.map +1 -0
  8. package/dist/cli/issue-commands.js +310 -0
  9. package/dist/cli/issue-commands.js.map +1 -0
  10. package/dist/cli/query-commands.d.ts.map +1 -0
  11. package/dist/cli/query-commands.js +61 -0
  12. package/dist/cli/query-commands.js.map +1 -0
  13. package/dist/cli/reference-commands.d.ts.map +1 -0
  14. package/dist/cli/reference-commands.js +136 -0
  15. package/dist/cli/reference-commands.js.map +1 -0
  16. package/dist/cli/relationship-commands.d.ts.map +1 -0
  17. package/dist/cli/relationship-commands.js +76 -0
  18. package/dist/cli/relationship-commands.js.map +1 -0
  19. package/dist/cli/server-commands.d.ts.map +1 -0
  20. package/dist/cli/server-commands.js +99 -0
  21. package/dist/cli/server-commands.js.map +1 -0
  22. package/dist/cli/spec-commands.d.ts.map +1 -0
  23. package/dist/cli/spec-commands.js +321 -0
  24. package/dist/cli/spec-commands.js.map +1 -0
  25. package/dist/cli/status-commands.d.ts.map +1 -0
  26. package/dist/cli/status-commands.js +131 -0
  27. package/dist/cli/status-commands.js.map +1 -0
  28. package/dist/cli/sync-commands.d.ts.map +1 -0
  29. package/dist/cli/sync-commands.js +416 -0
  30. package/dist/cli/sync-commands.js.map +1 -0
  31. package/dist/cli/update-commands.d.ts.map +1 -0
  32. package/dist/cli/update-commands.js +78 -0
  33. package/dist/cli/update-commands.js.map +1 -0
  34. package/dist/cli.d.ts.map +1 -0
  35. package/dist/cli.js +425 -195
  36. package/dist/cli.js.map +1 -0
  37. package/dist/db.d.ts.map +1 -0
  38. package/dist/db.js +54 -0
  39. package/dist/db.js.map +1 -0
  40. package/dist/export.d.ts.map +1 -0
  41. package/dist/export.js +195 -0
  42. package/dist/export.js.map +1 -0
  43. package/dist/filename-generator.d.ts.map +1 -0
  44. package/dist/filename-generator.js +93 -0
  45. package/dist/filename-generator.js.map +1 -0
  46. package/dist/id-generator.d.ts.map +1 -0
  47. package/dist/id-generator.js +123 -0
  48. package/dist/id-generator.js.map +1 -0
  49. package/dist/import.d.ts.map +1 -0
  50. package/dist/import.js +608 -0
  51. package/dist/import.js.map +1 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +13 -189
  54. package/dist/index.js.map +1 -0
  55. package/dist/jsonl.d.ts.map +1 -0
  56. package/dist/jsonl.js +333 -0
  57. package/dist/jsonl.js.map +1 -0
  58. package/dist/markdown.d.ts.map +1 -0
  59. package/dist/markdown.js +357 -0
  60. package/dist/markdown.js.map +1 -0
  61. package/dist/migrations.d.ts.map +1 -0
  62. package/dist/migrations.js +57 -0
  63. package/dist/migrations.js.map +1 -0
  64. package/dist/operations/events.d.ts.map +1 -0
  65. package/dist/operations/events.js +108 -0
  66. package/dist/operations/events.js.map +1 -0
  67. package/dist/operations/feedback-anchors.d.ts.map +1 -0
  68. package/dist/operations/feedback-anchors.js +444 -0
  69. package/dist/operations/feedback-anchors.js.map +1 -0
  70. package/dist/operations/feedback.d.ts.map +1 -0
  71. package/dist/operations/feedback.js +234 -0
  72. package/dist/operations/feedback.js.map +1 -0
  73. package/dist/operations/index.d.ts.map +1 -0
  74. package/dist/operations/index.js +10 -0
  75. package/dist/operations/index.js.map +1 -0
  76. package/dist/operations/issues.d.ts.map +1 -0
  77. package/dist/operations/issues.js +411 -0
  78. package/dist/operations/issues.js.map +1 -0
  79. package/dist/operations/references.d.ts.map +1 -0
  80. package/dist/operations/references.js +117 -0
  81. package/dist/operations/references.js.map +1 -0
  82. package/dist/operations/relationships.d.ts.map +1 -0
  83. package/dist/operations/relationships.js +236 -0
  84. package/dist/operations/relationships.js.map +1 -0
  85. package/dist/operations/specs.d.ts.map +1 -0
  86. package/dist/operations/specs.js +290 -0
  87. package/dist/operations/specs.js.map +1 -0
  88. package/dist/operations/tags.d.ts.map +1 -0
  89. package/dist/operations/tags.js +127 -0
  90. package/dist/operations/tags.js.map +1 -0
  91. package/dist/operations/transactions.d.ts.map +1 -0
  92. package/dist/operations/transactions.js +111 -0
  93. package/dist/operations/transactions.js.map +1 -0
  94. package/dist/sync.d.ts.map +1 -0
  95. package/dist/sync.js +442 -0
  96. package/dist/sync.js.map +1 -0
  97. package/dist/test-schema.d.ts.map +1 -0
  98. package/dist/test-schema.js +46 -0
  99. package/dist/test-schema.js.map +1 -0
  100. package/dist/types.d.ts.map +1 -0
  101. package/dist/types.js +7 -0
  102. package/dist/types.js.map +1 -0
  103. package/dist/update-checker.d.ts.map +1 -0
  104. package/dist/update-checker.js +151 -0
  105. package/dist/update-checker.js.map +1 -0
  106. package/dist/version.d.ts.map +1 -0
  107. package/dist/version.js +23 -0
  108. package/dist/version.js.map +1 -0
  109. package/dist/watcher.d.ts.map +1 -0
  110. package/dist/watcher.js +438 -0
  111. package/dist/watcher.js.map +1 -0
  112. package/package.json +4 -7
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Update checker with caching
3
+ * Checks npm registry for new versions and caches results
4
+ */
5
+ import * as fs from "fs";
6
+ import * as path from "path";
7
+ import * as os from "os";
8
+ import { VERSION } from "./version.js";
9
+ const PACKAGE_NAME = "@sudocode-ai/cli";
10
+ const CACHE_DIR = path.join(os.tmpdir(), "sudocode-cli");
11
+ const CACHE_FILE = path.join(CACHE_DIR, "update-cache.json");
12
+ const CACHE_DURATION = 1000 * 60 * 60 * 24; // 24 hours
13
+ /**
14
+ * Fetch latest version from npm registry
15
+ */
16
+ async function fetchLatestVersion() {
17
+ try {
18
+ const response = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, {
19
+ headers: {
20
+ Accept: "application/json",
21
+ },
22
+ });
23
+ if (!response.ok) {
24
+ return null;
25
+ }
26
+ const data = (await response.json());
27
+ return data.version || null;
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ }
33
+ /**
34
+ * Read cached version info
35
+ */
36
+ function readCache() {
37
+ try {
38
+ if (!fs.existsSync(CACHE_FILE)) {
39
+ return null;
40
+ }
41
+ const content = fs.readFileSync(CACHE_FILE, "utf-8");
42
+ const cache = JSON.parse(content);
43
+ // Check if cache is still valid
44
+ const now = Date.now();
45
+ if (now - cache.timestamp > CACHE_DURATION) {
46
+ return null;
47
+ }
48
+ return cache;
49
+ }
50
+ catch {
51
+ return null;
52
+ }
53
+ }
54
+ /**
55
+ * Write version info to cache
56
+ */
57
+ function writeCache(latest) {
58
+ try {
59
+ // Ensure cache directory exists
60
+ fs.mkdirSync(CACHE_DIR, { recursive: true });
61
+ const cache = {
62
+ timestamp: Date.now(),
63
+ latest,
64
+ };
65
+ fs.writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8");
66
+ }
67
+ catch {
68
+ // Silently fail if we can't write cache
69
+ }
70
+ }
71
+ /**
72
+ * Check for updates
73
+ * Returns null if check fails or update info if successful
74
+ */
75
+ export async function checkForUpdates() {
76
+ // Try to use cached version first
77
+ const cached = readCache();
78
+ if (cached) {
79
+ return {
80
+ current: VERSION,
81
+ latest: cached.latest,
82
+ updateAvailable: VERSION !== cached.latest,
83
+ };
84
+ }
85
+ // Fetch latest version from npm
86
+ const latest = await fetchLatestVersion();
87
+ if (!latest) {
88
+ return null;
89
+ }
90
+ // Cache the result
91
+ writeCache(latest);
92
+ return {
93
+ current: VERSION,
94
+ latest,
95
+ updateAvailable: VERSION !== latest,
96
+ };
97
+ }
98
+ /**
99
+ * Compare semver versions
100
+ * Returns true if v1 < v2
101
+ */
102
+ function isOlderVersion(v1, v2) {
103
+ const parts1 = v1.split(".").map(Number);
104
+ const parts2 = v2.split(".").map(Number);
105
+ for (let i = 0; i < 3; i++) {
106
+ const p1 = parts1[i] || 0;
107
+ const p2 = parts2[i] || 0;
108
+ if (p1 < p2)
109
+ return true;
110
+ if (p1 > p2)
111
+ return false;
112
+ }
113
+ return false;
114
+ }
115
+ /**
116
+ * Check for updates and return formatted notification message
117
+ */
118
+ export async function getUpdateNotification() {
119
+ const info = await checkForUpdates();
120
+ if (!info || !info.updateAvailable) {
121
+ return null;
122
+ }
123
+ // Only notify if latest is actually newer (not just different)
124
+ if (!isOlderVersion(info.current, info.latest)) {
125
+ return null;
126
+ }
127
+ return `
128
+ ╭─────────────────────────────────────────────────╮
129
+ │ │
130
+ │ Update available: ${info.current} → ${info.latest} │
131
+ │ │
132
+ │ Run: npm install -g ${PACKAGE_NAME} │
133
+ │ Or: sudocode update │
134
+ │ │
135
+ ╰─────────────────────────────────────────────────╯
136
+ `.trim();
137
+ }
138
+ /**
139
+ * Clear update cache (useful for testing)
140
+ */
141
+ export function clearUpdateCache() {
142
+ try {
143
+ if (fs.existsSync(CACHE_FILE)) {
144
+ fs.unlinkSync(CACHE_FILE);
145
+ }
146
+ }
147
+ catch {
148
+ // Silently fail
149
+ }
150
+ }
151
+ //# sourceMappingURL=update-checker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-checker.js","sourceRoot":"","sources":["../src/update-checker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,MAAM,YAAY,GAAG,kBAAkB,CAAC;AACxC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC;AACzD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;AAC7D,MAAM,cAAc,GAAG,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,WAAW;AAiBvD;;GAEG;AACH,KAAK,UAAU,kBAAkB;IAC/B,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,8BAA8B,YAAY,SAAS,EACnD;YACE,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB;aAC3B;SACF,CACF,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAwB,CAAC;QAC5D,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,SAAS;IAChB,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACrD,MAAM,KAAK,GAAgB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAE/C,gCAAgC;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,GAAG,cAAc,EAAE,CAAC;YAC3C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,UAAU,CAAC,MAAc;IAChC,IAAI,CAAC;QACH,gCAAgC;QAChC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE7C,MAAM,KAAK,GAAgB;YACzB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,MAAM;SACP,CAAC;QAEF,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,wCAAwC;IAC1C,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,kCAAkC;IAClC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,IAAI,MAAM,EAAE,CAAC;QACX,OAAO;YACL,OAAO,EAAE,OAAO;YAChB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,eAAe,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM;SAC3C,CAAC;IACJ,CAAC;IAED,gCAAgC;IAChC,MAAM,MAAM,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mBAAmB;IACnB,UAAU,CAAC,MAAM,CAAC,CAAC;IAEnB,OAAO;QACL,OAAO,EAAE,OAAO;QAChB,MAAM;QACN,eAAe,EAAE,OAAO,KAAK,MAAM;KACpC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,cAAc,CAAC,EAAU,EAAE,EAAU;IAC5C,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAEzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAE1B,IAAI,EAAE,GAAG,EAAE;YAAE,OAAO,IAAI,CAAC;QACzB,IAAI,EAAE,GAAG,EAAE;YAAE,OAAO,KAAK,CAAC;IAC5B,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,MAAM,IAAI,GAAG,MAAM,eAAe,EAAE,CAAC;IAErC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,+DAA+D;IAC/D,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;;;uBAGc,IAAI,CAAC,OAAO,MAAM,IAAI,CAAC,MAAM;;yBAE3B,YAAY;;;;GAIlC,CAAC,IAAI,EAAE,CAAC;AACX,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gBAAgB;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAMnC;AAED;;GAEG;AACH,eAAO,MAAM,OAAO,QAAe,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Version utilities
3
+ */
4
+ import * as fs from "fs";
5
+ import * as path from "path";
6
+ import { fileURLToPath } from "url";
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+ /**
10
+ * Get the CLI version from package.json
11
+ */
12
+ export function getVersion() {
13
+ // In development (running from src/), go up one level
14
+ // In production (running from dist/), go up one level
15
+ const packageJsonPath = path.join(__dirname, "..", "package.json");
16
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
17
+ return packageJson.version;
18
+ }
19
+ /**
20
+ * The current CLI version
21
+ */
22
+ export const VERSION = getVersion();
23
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,sDAAsD;IACtD,sDAAsD;IACtD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;IACnE,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;IACzE,OAAO,WAAW,CAAC,OAAO,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAe3C,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC;IACtB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B;;OAEG;IACH,QAAQ,EAAE,MAAM,YAAY,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,CA+dpE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CA+BnE"}
@@ -0,0 +1,438 @@
1
+ /**
2
+ * File watcher for automatic synchronization
3
+ * Watches .sudocode directory for changes and triggers sync operations
4
+ */
5
+ import chokidar from "chokidar";
6
+ import * as path from "path";
7
+ import * as fs from "fs";
8
+ import { syncMarkdownToJSONL, syncJSONLToMarkdown } from "./sync.js";
9
+ import { importFromJSONL } from "./import.js";
10
+ import { exportToJSONL } from "./export.js";
11
+ import { getSpecByFilePath, deleteSpec, listSpecs, getSpec, } from "./operations/specs.js";
12
+ import { listIssues, getIssue } from "./operations/issues.js";
13
+ import { parseMarkdownFile } from "./markdown.js";
14
+ import { listFeedback } from "./operations/feedback.js";
15
+ import { getTags } from "./operations/tags.js";
16
+ /**
17
+ * Start watching files for changes
18
+ * Returns a control object to stop the watcher
19
+ */
20
+ export function startWatcher(options) {
21
+ const { db, baseDir, debounceDelay = 2000, onLog = console.log, onError = console.error, ignoreInitial = true, syncJSONLToMarkdown: enableReverseSync = false, } = options;
22
+ const stats = {
23
+ filesWatched: 0,
24
+ changesPending: 0,
25
+ changesProcessed: 0,
26
+ errors: 0,
27
+ };
28
+ // Map of file paths to pending timeout IDs
29
+ const pendingChanges = new Map();
30
+ /**
31
+ * Check if markdown file content matches database content
32
+ * Returns true if they match (no sync needed)
33
+ */
34
+ function contentMatches(mdPath, entityId, entityType) {
35
+ try {
36
+ // Check if file exists
37
+ if (!fs.existsSync(mdPath)) {
38
+ return false; // File doesn't exist, needs to be created
39
+ }
40
+ // Parse markdown file
41
+ const parsed = parseMarkdownFile(mdPath, db, baseDir);
42
+ const { data: frontmatter, content: mdContent } = parsed;
43
+ // Get entity from database
44
+ const dbEntity = entityType === "spec" ? getSpec(db, entityId) : getIssue(db, entityId);
45
+ if (!dbEntity) {
46
+ return false; // Entity not in DB, shouldn't happen
47
+ }
48
+ // Compare title
49
+ if (frontmatter.title !== dbEntity.title) {
50
+ return false;
51
+ }
52
+ // Compare content (trim to ignore whitespace differences)
53
+ if (mdContent.trim() !== (dbEntity.content || "").trim()) {
54
+ return false;
55
+ }
56
+ // Compare other key fields
57
+ if (entityType === "spec") {
58
+ if (frontmatter.priority !== dbEntity.priority)
59
+ return false;
60
+ }
61
+ else {
62
+ const issue = dbEntity;
63
+ if (frontmatter.status !== issue.status)
64
+ return false;
65
+ if (frontmatter.priority !== issue.priority)
66
+ return false;
67
+ }
68
+ return true; // Content matches
69
+ }
70
+ catch (error) {
71
+ // If there's an error parsing, assume they don't match
72
+ return false;
73
+ }
74
+ }
75
+ /**
76
+ * Check if JSONL file needs to be imported to database
77
+ * Returns true if import is needed (JSONL has changes not in DB)
78
+ */
79
+ function jsonlNeedsImport(jsonlPath) {
80
+ try {
81
+ if (!fs.existsSync(jsonlPath)) {
82
+ return false; // File doesn't exist
83
+ }
84
+ // Read JSONL file
85
+ const content = fs.readFileSync(jsonlPath, "utf8");
86
+ const lines = content
87
+ .trim()
88
+ .split("\n")
89
+ .filter((line) => line.trim());
90
+ // Parse each line and check if it differs from database
91
+ for (const line of lines) {
92
+ const jsonlEntity = JSON.parse(line);
93
+ const entityId = jsonlEntity.id;
94
+ const entityType = jsonlPath.includes("specs.jsonl") ? "spec" : "issue";
95
+ // Get entity from database
96
+ const dbEntity = entityType === "spec"
97
+ ? getSpec(db, entityId)
98
+ : getIssue(db, entityId);
99
+ // If entity doesn't exist in DB, import is needed
100
+ if (!dbEntity) {
101
+ return true;
102
+ }
103
+ // Compare all substantial fields
104
+ if (jsonlEntity.title !== dbEntity.title)
105
+ return true;
106
+ if ((jsonlEntity.content || "").trim() !== (dbEntity.content || "").trim())
107
+ return true;
108
+ if (jsonlEntity.priority !== dbEntity.priority)
109
+ return true;
110
+ if (jsonlEntity.parent_id !== dbEntity.parent_id)
111
+ return true;
112
+ if (jsonlEntity.archived !== dbEntity.archived)
113
+ return true;
114
+ if (jsonlEntity.archived_at !== dbEntity.archived_at)
115
+ return true;
116
+ if (entityType === "spec") {
117
+ const dbSpec = dbEntity;
118
+ // Compare spec-specific fields
119
+ if (jsonlEntity.file_path !== dbSpec.file_path)
120
+ return true;
121
+ }
122
+ else if (entityType === "issue") {
123
+ const dbIssue = dbEntity;
124
+ if (jsonlEntity.status !== dbIssue.status)
125
+ return true;
126
+ if (jsonlEntity.assignee !== dbIssue.assignee)
127
+ return true;
128
+ if (jsonlEntity.closed_at !== dbIssue.closed_at)
129
+ return true;
130
+ // Compare feedback
131
+ const dbFeedback = listFeedback(db, { issue_id: entityId });
132
+ const jsonlFeedback = jsonlEntity.feedback || [];
133
+ if (jsonlFeedback.length !== dbFeedback.length)
134
+ return true;
135
+ // Compare feedback content
136
+ for (const jf of jsonlFeedback) {
137
+ const dbf = dbFeedback.find((f) => f.id === jf.id);
138
+ if (!dbf)
139
+ return true;
140
+ if (jf.content !== dbf.content)
141
+ return true;
142
+ if (jf.feedback_type !== dbf.feedback_type)
143
+ return true;
144
+ if (jf.spec_id !== dbf.spec_id)
145
+ return true;
146
+ if (jf.dismissed !== dbf.dismissed)
147
+ return true;
148
+ // Compare anchor (stringified for comparison)
149
+ const jfAnchor = JSON.stringify(jf.anchor || null);
150
+ const dbfAnchor = JSON.stringify(dbf.anchor && typeof dbf.anchor === "string"
151
+ ? JSON.parse(dbf.anchor)
152
+ : dbf.anchor || null);
153
+ if (jfAnchor !== dbfAnchor)
154
+ return true;
155
+ }
156
+ }
157
+ // Compare tags
158
+ const dbTags = getTags(db, entityId, entityType);
159
+ const jsonlTags = jsonlEntity.tags || [];
160
+ if (jsonlTags.length !== dbTags.length)
161
+ return true;
162
+ const dbTagsSet = new Set(dbTags);
163
+ if (jsonlTags.some((tag) => !dbTagsSet.has(tag)))
164
+ return true;
165
+ // Compare relationships
166
+ const { getOutgoingRelationships } = require("./operations/relationships.js");
167
+ const dbRels = getOutgoingRelationships(db, entityId, entityType);
168
+ const jsonlRels = jsonlEntity.relationships || [];
169
+ if (jsonlRels.length !== dbRels.length)
170
+ return true;
171
+ // Compare relationship content
172
+ for (const jr of jsonlRels) {
173
+ const dr = dbRels.find((r) => r.to_id === jr.to &&
174
+ r.to_type === jr.to_type &&
175
+ r.relationship_type === jr.type);
176
+ if (!dr)
177
+ return true;
178
+ }
179
+ // Compare updated_at timestamp - if JSONL is newer, import is needed
180
+ if (jsonlEntity.updated_at &&
181
+ new Date(jsonlEntity.updated_at).getTime() >
182
+ new Date(dbEntity.updated_at).getTime()) {
183
+ return true;
184
+ }
185
+ }
186
+ return false; // All entities match
187
+ }
188
+ catch (error) {
189
+ // If there's an error, assume import is needed
190
+ return true;
191
+ }
192
+ }
193
+ // Paths to watch
194
+ const specsDir = path.join(baseDir, "specs");
195
+ const issuesDir = path.join(baseDir, "issues");
196
+ const specsJSONL = path.join(baseDir, "specs.jsonl");
197
+ const issuesJSONL = path.join(baseDir, "issues.jsonl");
198
+ // Watch directories and JSONL files - chokidar will recursively watch all files inside
199
+ const watcher = chokidar.watch([specsDir, issuesDir, specsJSONL, issuesJSONL], {
200
+ persistent: true,
201
+ ignoreInitial,
202
+ awaitWriteFinish: {
203
+ stabilityThreshold: 100, // Reduced for faster detection in tests
204
+ pollInterval: 50,
205
+ },
206
+ });
207
+ // Log watch patterns for debugging
208
+ onLog(`[watch] Watching directories: ${specsDir}, ${issuesDir} and JSONL files`);
209
+ /**
210
+ * Process a file change
211
+ */
212
+ async function processChange(filePath, event) {
213
+ try {
214
+ const ext = path.extname(filePath);
215
+ const basename = path.basename(filePath);
216
+ if (ext === ".md") {
217
+ // Markdown file changed - sync to database and JSONL
218
+ onLog(`[watch] ${event} ${path.relative(baseDir, filePath)}`);
219
+ if (event === "unlink") {
220
+ // File was deleted - remove from database and JSONL
221
+ // Calculate relative file path
222
+ const relPath = path.relative(baseDir, filePath);
223
+ // Look up spec by file path
224
+ const spec = getSpecByFilePath(db, relPath);
225
+ if (spec) {
226
+ // Delete from database
227
+ const deleted = deleteSpec(db, spec.id);
228
+ if (deleted) {
229
+ onLog(`[watch] Deleted spec ${spec.id} (file removed)`);
230
+ // Export to JSONL to reflect deletion
231
+ await exportToJSONL(db, { outputDir: baseDir });
232
+ }
233
+ }
234
+ else {
235
+ onLog(`[watch] File deleted but no spec found: ${relPath}`);
236
+ }
237
+ }
238
+ else {
239
+ // Parse markdown to get entity info
240
+ try {
241
+ const parsed = parseMarkdownFile(filePath, db, baseDir);
242
+ const { data: frontmatter } = parsed;
243
+ const entityId = frontmatter.id;
244
+ // Determine entity type based on file location
245
+ const relPath = path.relative(baseDir, filePath);
246
+ const entityType = relPath.startsWith("specs/") || relPath.startsWith("specs\\")
247
+ ? "spec"
248
+ : "issue";
249
+ // Skip if content already matches (prevents oscillation)
250
+ if (entityId && contentMatches(filePath, entityId, entityType)) {
251
+ return;
252
+ }
253
+ // Check timestamps to determine sync direction
254
+ if (entityId) {
255
+ const dbEntity = entityType === "spec"
256
+ ? getSpec(db, entityId)
257
+ : getIssue(db, entityId);
258
+ if (dbEntity) {
259
+ // Get file modification time
260
+ const fileStat = fs.statSync(filePath);
261
+ const fileTime = fileStat.mtimeMs;
262
+ // Get database updated_at time
263
+ const dbTime = new Date(dbEntity.updated_at).getTime();
264
+ // If database is newer than file, skip markdown → database sync
265
+ if (dbTime > fileTime) {
266
+ onLog(`[watch] Skipping sync for ${entityType} ${entityId} (database is newer)`);
267
+ return;
268
+ }
269
+ }
270
+ }
271
+ }
272
+ catch (error) {
273
+ // If parsing fails, continue with sync (might be a new file)
274
+ }
275
+ // Sync markdown to database
276
+ const result = await syncMarkdownToJSONL(db, filePath, {
277
+ outputDir: baseDir,
278
+ autoExport: true,
279
+ autoInitialize: true,
280
+ writeBackFrontmatter: true,
281
+ });
282
+ if (result.success) {
283
+ onLog(`[watch] Synced ${result.entityType} ${result.entityId} (${result.action})`);
284
+ }
285
+ else {
286
+ onError(new Error(`Failed to sync ${filePath}: ${result.error}`));
287
+ stats.errors++;
288
+ }
289
+ }
290
+ }
291
+ else if (basename === "specs.jsonl" || basename === "issues.jsonl") {
292
+ // JSONL file changed (e.g., from git pull) - check if import is needed
293
+ onLog(`[watch] ${event} ${path.relative(baseDir, filePath)}`);
294
+ if (event !== "unlink") {
295
+ // Check if JSONL actually differs from database before importing
296
+ if (jsonlNeedsImport(filePath)) {
297
+ await importFromJSONL(db, {
298
+ inputDir: baseDir,
299
+ });
300
+ onLog(`[watch] Imported JSONL changes to database`);
301
+ }
302
+ // Optionally sync database changes back to markdown files
303
+ // Only sync entities where content actually differs (contentMatches check)
304
+ if (enableReverseSync) {
305
+ onLog(`[watch] Checking for entities that need markdown updates...`);
306
+ let syncedCount = 0;
307
+ // Get all specs and sync to markdown
308
+ const specs = listSpecs(db);
309
+ for (const spec of specs) {
310
+ if (spec.file_path) {
311
+ const mdPath = path.join(baseDir, spec.file_path);
312
+ // Skip if content already matches (prevents oscillation)
313
+ if (contentMatches(mdPath, spec.id, "spec")) {
314
+ continue;
315
+ }
316
+ const result = await syncJSONLToMarkdown(db, spec.id, "spec", mdPath);
317
+ if (result.success) {
318
+ syncedCount++;
319
+ onLog(`[watch] Synced spec ${spec.id} to ${spec.file_path} (${result.action})`);
320
+ }
321
+ else if (result.error) {
322
+ onError(new Error(`Failed to sync spec ${spec.id}: ${result.error}`));
323
+ }
324
+ }
325
+ }
326
+ // Get all issues and check if any need syncing
327
+ const issues = listIssues(db);
328
+ const issuesDir = path.join(baseDir, "issues");
329
+ for (const issue of issues) {
330
+ const fileName = `${issue.id}.md`;
331
+ const mdPath = path.join(issuesDir, fileName);
332
+ // Skip if content already matches (prevents unnecessary writes and oscillation)
333
+ if (contentMatches(mdPath, issue.id, "issue")) {
334
+ continue;
335
+ }
336
+ const result = await syncJSONLToMarkdown(db, issue.id, "issue", mdPath);
337
+ if (result.success) {
338
+ syncedCount++;
339
+ onLog(`[watch] Synced issue ${issue.id} to markdown (${result.action})`);
340
+ }
341
+ else if (result.error) {
342
+ onError(new Error(`Failed to sync issue ${issue.id}: ${result.error}`));
343
+ }
344
+ }
345
+ if (syncedCount > 0) {
346
+ onLog(`[watch] Synced ${syncedCount} entities to markdown`);
347
+ }
348
+ else {
349
+ onLog(`[watch] All markdown files are up to date`);
350
+ }
351
+ }
352
+ }
353
+ }
354
+ stats.changesProcessed++;
355
+ }
356
+ catch (error) {
357
+ const message = error instanceof Error ? error.message : String(error);
358
+ onError(new Error(`Error processing ${filePath}: ${message}`));
359
+ stats.errors++;
360
+ }
361
+ }
362
+ /**
363
+ * Debounced file change handler
364
+ */
365
+ function handleFileChange(filePath, event) {
366
+ // Cancel pending change for this file
367
+ const existingTimeout = pendingChanges.get(filePath);
368
+ if (existingTimeout) {
369
+ clearTimeout(existingTimeout);
370
+ stats.changesPending--;
371
+ }
372
+ // Schedule new change
373
+ stats.changesPending++;
374
+ const timeout = setTimeout(() => {
375
+ pendingChanges.delete(filePath);
376
+ stats.changesPending--;
377
+ processChange(filePath, event);
378
+ }, debounceDelay);
379
+ pendingChanges.set(filePath, timeout);
380
+ }
381
+ // Set up event handlers
382
+ watcher.on("add", (filePath) => handleFileChange(filePath, "add"));
383
+ watcher.on("change", (filePath) => handleFileChange(filePath, "change"));
384
+ watcher.on("unlink", (filePath) => handleFileChange(filePath, "unlink"));
385
+ watcher.on("ready", () => {
386
+ const watched = watcher.getWatched();
387
+ stats.filesWatched = Object.keys(watched).reduce((total, dir) => total + watched[dir].length, 0);
388
+ onLog(`[watch] Watching ${stats.filesWatched} files in ${baseDir}`);
389
+ });
390
+ watcher.on("error", (error) => {
391
+ onError(error);
392
+ stats.errors++;
393
+ });
394
+ // Return control object
395
+ return {
396
+ stop: async () => {
397
+ onLog("[watch] Stopping watcher...");
398
+ // Cancel all pending changes
399
+ for (const timeout of pendingChanges.values()) {
400
+ clearTimeout(timeout);
401
+ }
402
+ pendingChanges.clear();
403
+ stats.changesPending = 0;
404
+ // Close watcher
405
+ await watcher.close();
406
+ onLog("[watch] Watcher stopped");
407
+ },
408
+ getStats: () => ({ ...stats }),
409
+ };
410
+ }
411
+ /**
412
+ * Wait for termination signal and stop watcher gracefully
413
+ */
414
+ export function setupGracefulShutdown(control) {
415
+ let isShuttingDown = false;
416
+ const shutdown = async (signal) => {
417
+ if (isShuttingDown)
418
+ return;
419
+ isShuttingDown = true;
420
+ console.log(`\n[watch] Received ${signal}, shutting down gracefully...`);
421
+ try {
422
+ await control.stop();
423
+ process.exit(0);
424
+ }
425
+ catch (error) {
426
+ console.error("[watch] Error during shutdown:", error);
427
+ process.exit(1);
428
+ }
429
+ };
430
+ // Handle termination signals
431
+ process.on("SIGINT", () => shutdown("SIGINT"));
432
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
433
+ // Handle unhandled promise rejections
434
+ process.on("unhandledRejection", (reason, promise) => {
435
+ console.error("[watch] Unhandled Rejection at:", promise, "reason:", reason);
436
+ });
437
+ }
438
+ //# sourceMappingURL=watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"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"}