diffity 0.2.0 → 0.3.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.
package/dist/index.js CHANGED
@@ -1,15 +1,359 @@
1
1
  #!/usr/bin/env node
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf, __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from == "object" || typeof from == "function")
12
+ for (let key of __getOwnPropNames(from))
13
+ !__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: !0 }) : target,
22
+ mod
23
+ ));
24
+
25
+ // ../../node_modules/dayjs/dayjs.min.js
26
+ var require_dayjs_min = __commonJS({
27
+ "../../node_modules/dayjs/dayjs.min.js"(exports, module) {
28
+ (function(t, e) {
29
+ typeof exports == "object" && typeof module < "u" ? module.exports = e() : typeof define == "function" && define.amd ? define(e) : (t = typeof globalThis < "u" ? globalThis : t || self).dayjs = e();
30
+ })(exports, (function() {
31
+ "use strict";
32
+ var t = 1e3, e = 6e4, n = 36e5, r = "millisecond", i = "second", s = "minute", u = "hour", a = "day", o = "week", c = "month", f = "quarter", h = "year", d = "date", l = "Invalid Date", $ = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/, y = /\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g, M = { name: "en", weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), ordinal: function(t2) {
33
+ var e2 = ["th", "st", "nd", "rd"], n2 = t2 % 100;
34
+ return "[" + t2 + (e2[(n2 - 20) % 10] || e2[n2] || e2[0]) + "]";
35
+ } }, m = function(t2, e2, n2) {
36
+ var r2 = String(t2);
37
+ return !r2 || r2.length >= e2 ? t2 : "" + Array(e2 + 1 - r2.length).join(n2) + t2;
38
+ }, v = { s: m, z: function(t2) {
39
+ var e2 = -t2.utcOffset(), n2 = Math.abs(e2), r2 = Math.floor(n2 / 60), i2 = n2 % 60;
40
+ return (e2 <= 0 ? "+" : "-") + m(r2, 2, "0") + ":" + m(i2, 2, "0");
41
+ }, m: function t2(e2, n2) {
42
+ if (e2.date() < n2.date()) return -t2(n2, e2);
43
+ var r2 = 12 * (n2.year() - e2.year()) + (n2.month() - e2.month()), i2 = e2.clone().add(r2, c), s2 = n2 - i2 < 0, u2 = e2.clone().add(r2 + (s2 ? -1 : 1), c);
44
+ return +(-(r2 + (n2 - i2) / (s2 ? i2 - u2 : u2 - i2)) || 0);
45
+ }, a: function(t2) {
46
+ return t2 < 0 ? Math.ceil(t2) || 0 : Math.floor(t2);
47
+ }, p: function(t2) {
48
+ return { M: c, y: h, w: o, d: a, D: d, h: u, m: s, s: i, ms: r, Q: f }[t2] || String(t2 || "").toLowerCase().replace(/s$/, "");
49
+ }, u: function(t2) {
50
+ return t2 === void 0;
51
+ } }, g = "en", D = {};
52
+ D[g] = M;
53
+ var p = "$isDayjsObject", S = function(t2) {
54
+ return t2 instanceof _ || !(!t2 || !t2[p]);
55
+ }, w = function t2(e2, n2, r2) {
56
+ var i2;
57
+ if (!e2) return g;
58
+ if (typeof e2 == "string") {
59
+ var s2 = e2.toLowerCase();
60
+ D[s2] && (i2 = s2), n2 && (D[s2] = n2, i2 = s2);
61
+ var u2 = e2.split("-");
62
+ if (!i2 && u2.length > 1) return t2(u2[0]);
63
+ } else {
64
+ var a2 = e2.name;
65
+ D[a2] = e2, i2 = a2;
66
+ }
67
+ return !r2 && i2 && (g = i2), i2 || !r2 && g;
68
+ }, O = function(t2, e2) {
69
+ if (S(t2)) return t2.clone();
70
+ var n2 = typeof e2 == "object" ? e2 : {};
71
+ return n2.date = t2, n2.args = arguments, new _(n2);
72
+ }, b = v;
73
+ b.l = w, b.i = S, b.w = function(t2, e2) {
74
+ return O(t2, { locale: e2.$L, utc: e2.$u, x: e2.$x, $offset: e2.$offset });
75
+ };
76
+ var _ = (function() {
77
+ function M2(t2) {
78
+ this.$L = w(t2.locale, null, !0), this.parse(t2), this.$x = this.$x || t2.x || {}, this[p] = !0;
79
+ }
80
+ var m2 = M2.prototype;
81
+ return m2.parse = function(t2) {
82
+ this.$d = (function(t3) {
83
+ var e2 = t3.date, n2 = t3.utc;
84
+ if (e2 === null) return /* @__PURE__ */ new Date(NaN);
85
+ if (b.u(e2)) return /* @__PURE__ */ new Date();
86
+ if (e2 instanceof Date) return new Date(e2);
87
+ if (typeof e2 == "string" && !/Z$/i.test(e2)) {
88
+ var r2 = e2.match($);
89
+ if (r2) {
90
+ var i2 = r2[2] - 1 || 0, s2 = (r2[7] || "0").substring(0, 3);
91
+ return n2 ? new Date(Date.UTC(r2[1], i2, r2[3] || 1, r2[4] || 0, r2[5] || 0, r2[6] || 0, s2)) : new Date(r2[1], i2, r2[3] || 1, r2[4] || 0, r2[5] || 0, r2[6] || 0, s2);
92
+ }
93
+ }
94
+ return new Date(e2);
95
+ })(t2), this.init();
96
+ }, m2.init = function() {
97
+ var t2 = this.$d;
98
+ this.$y = t2.getFullYear(), this.$M = t2.getMonth(), this.$D = t2.getDate(), this.$W = t2.getDay(), this.$H = t2.getHours(), this.$m = t2.getMinutes(), this.$s = t2.getSeconds(), this.$ms = t2.getMilliseconds();
99
+ }, m2.$utils = function() {
100
+ return b;
101
+ }, m2.isValid = function() {
102
+ return this.$d.toString() !== l;
103
+ }, m2.isSame = function(t2, e2) {
104
+ var n2 = O(t2);
105
+ return this.startOf(e2) <= n2 && n2 <= this.endOf(e2);
106
+ }, m2.isAfter = function(t2, e2) {
107
+ return O(t2) < this.startOf(e2);
108
+ }, m2.isBefore = function(t2, e2) {
109
+ return this.endOf(e2) < O(t2);
110
+ }, m2.$g = function(t2, e2, n2) {
111
+ return b.u(t2) ? this[e2] : this.set(n2, t2);
112
+ }, m2.unix = function() {
113
+ return Math.floor(this.valueOf() / 1e3);
114
+ }, m2.valueOf = function() {
115
+ return this.$d.getTime();
116
+ }, m2.startOf = function(t2, e2) {
117
+ var n2 = this, r2 = !!b.u(e2) || e2, f2 = b.p(t2), l2 = function(t3, e3) {
118
+ var i2 = b.w(n2.$u ? Date.UTC(n2.$y, e3, t3) : new Date(n2.$y, e3, t3), n2);
119
+ return r2 ? i2 : i2.endOf(a);
120
+ }, $2 = function(t3, e3) {
121
+ return b.w(n2.toDate()[t3].apply(n2.toDate("s"), (r2 ? [0, 0, 0, 0] : [23, 59, 59, 999]).slice(e3)), n2);
122
+ }, y2 = this.$W, M3 = this.$M, m3 = this.$D, v2 = "set" + (this.$u ? "UTC" : "");
123
+ switch (f2) {
124
+ case h:
125
+ return r2 ? l2(1, 0) : l2(31, 11);
126
+ case c:
127
+ return r2 ? l2(1, M3) : l2(0, M3 + 1);
128
+ case o:
129
+ var g2 = this.$locale().weekStart || 0, D2 = (y2 < g2 ? y2 + 7 : y2) - g2;
130
+ return l2(r2 ? m3 - D2 : m3 + (6 - D2), M3);
131
+ case a:
132
+ case d:
133
+ return $2(v2 + "Hours", 0);
134
+ case u:
135
+ return $2(v2 + "Minutes", 1);
136
+ case s:
137
+ return $2(v2 + "Seconds", 2);
138
+ case i:
139
+ return $2(v2 + "Milliseconds", 3);
140
+ default:
141
+ return this.clone();
142
+ }
143
+ }, m2.endOf = function(t2) {
144
+ return this.startOf(t2, !1);
145
+ }, m2.$set = function(t2, e2) {
146
+ var n2, o2 = b.p(t2), f2 = "set" + (this.$u ? "UTC" : ""), l2 = (n2 = {}, n2[a] = f2 + "Date", n2[d] = f2 + "Date", n2[c] = f2 + "Month", n2[h] = f2 + "FullYear", n2[u] = f2 + "Hours", n2[s] = f2 + "Minutes", n2[i] = f2 + "Seconds", n2[r] = f2 + "Milliseconds", n2)[o2], $2 = o2 === a ? this.$D + (e2 - this.$W) : e2;
147
+ if (o2 === c || o2 === h) {
148
+ var y2 = this.clone().set(d, 1);
149
+ y2.$d[l2]($2), y2.init(), this.$d = y2.set(d, Math.min(this.$D, y2.daysInMonth())).$d;
150
+ } else l2 && this.$d[l2]($2);
151
+ return this.init(), this;
152
+ }, m2.set = function(t2, e2) {
153
+ return this.clone().$set(t2, e2);
154
+ }, m2.get = function(t2) {
155
+ return this[b.p(t2)]();
156
+ }, m2.add = function(r2, f2) {
157
+ var d2, l2 = this;
158
+ r2 = Number(r2);
159
+ var $2 = b.p(f2), y2 = function(t2) {
160
+ var e2 = O(l2);
161
+ return b.w(e2.date(e2.date() + Math.round(t2 * r2)), l2);
162
+ };
163
+ if ($2 === c) return this.set(c, this.$M + r2);
164
+ if ($2 === h) return this.set(h, this.$y + r2);
165
+ if ($2 === a) return y2(1);
166
+ if ($2 === o) return y2(7);
167
+ var M3 = (d2 = {}, d2[s] = e, d2[u] = n, d2[i] = t, d2)[$2] || 1, m3 = this.$d.getTime() + r2 * M3;
168
+ return b.w(m3, this);
169
+ }, m2.subtract = function(t2, e2) {
170
+ return this.add(-1 * t2, e2);
171
+ }, m2.format = function(t2) {
172
+ var e2 = this, n2 = this.$locale();
173
+ if (!this.isValid()) return n2.invalidDate || l;
174
+ var r2 = t2 || "YYYY-MM-DDTHH:mm:ssZ", i2 = b.z(this), s2 = this.$H, u2 = this.$m, a2 = this.$M, o2 = n2.weekdays, c2 = n2.months, f2 = n2.meridiem, h2 = function(t3, n3, i3, s3) {
175
+ return t3 && (t3[n3] || t3(e2, r2)) || i3[n3].slice(0, s3);
176
+ }, d2 = function(t3) {
177
+ return b.s(s2 % 12 || 12, t3, "0");
178
+ }, $2 = f2 || function(t3, e3, n3) {
179
+ var r3 = t3 < 12 ? "AM" : "PM";
180
+ return n3 ? r3.toLowerCase() : r3;
181
+ };
182
+ return r2.replace(y, (function(t3, r3) {
183
+ return r3 || (function(t4) {
184
+ switch (t4) {
185
+ case "YY":
186
+ return String(e2.$y).slice(-2);
187
+ case "YYYY":
188
+ return b.s(e2.$y, 4, "0");
189
+ case "M":
190
+ return a2 + 1;
191
+ case "MM":
192
+ return b.s(a2 + 1, 2, "0");
193
+ case "MMM":
194
+ return h2(n2.monthsShort, a2, c2, 3);
195
+ case "MMMM":
196
+ return h2(c2, a2);
197
+ case "D":
198
+ return e2.$D;
199
+ case "DD":
200
+ return b.s(e2.$D, 2, "0");
201
+ case "d":
202
+ return String(e2.$W);
203
+ case "dd":
204
+ return h2(n2.weekdaysMin, e2.$W, o2, 2);
205
+ case "ddd":
206
+ return h2(n2.weekdaysShort, e2.$W, o2, 3);
207
+ case "dddd":
208
+ return o2[e2.$W];
209
+ case "H":
210
+ return String(s2);
211
+ case "HH":
212
+ return b.s(s2, 2, "0");
213
+ case "h":
214
+ return d2(1);
215
+ case "hh":
216
+ return d2(2);
217
+ case "a":
218
+ return $2(s2, u2, !0);
219
+ case "A":
220
+ return $2(s2, u2, !1);
221
+ case "m":
222
+ return String(u2);
223
+ case "mm":
224
+ return b.s(u2, 2, "0");
225
+ case "s":
226
+ return String(e2.$s);
227
+ case "ss":
228
+ return b.s(e2.$s, 2, "0");
229
+ case "SSS":
230
+ return b.s(e2.$ms, 3, "0");
231
+ case "Z":
232
+ return i2;
233
+ }
234
+ return null;
235
+ })(t3) || i2.replace(":", "");
236
+ }));
237
+ }, m2.utcOffset = function() {
238
+ return 15 * -Math.round(this.$d.getTimezoneOffset() / 15);
239
+ }, m2.diff = function(r2, d2, l2) {
240
+ var $2, y2 = this, M3 = b.p(d2), m3 = O(r2), v2 = (m3.utcOffset() - this.utcOffset()) * e, g2 = this - m3, D2 = function() {
241
+ return b.m(y2, m3);
242
+ };
243
+ switch (M3) {
244
+ case h:
245
+ $2 = D2() / 12;
246
+ break;
247
+ case c:
248
+ $2 = D2();
249
+ break;
250
+ case f:
251
+ $2 = D2() / 3;
252
+ break;
253
+ case o:
254
+ $2 = (g2 - v2) / 6048e5;
255
+ break;
256
+ case a:
257
+ $2 = (g2 - v2) / 864e5;
258
+ break;
259
+ case u:
260
+ $2 = g2 / n;
261
+ break;
262
+ case s:
263
+ $2 = g2 / e;
264
+ break;
265
+ case i:
266
+ $2 = g2 / t;
267
+ break;
268
+ default:
269
+ $2 = g2;
270
+ }
271
+ return l2 ? $2 : b.a($2);
272
+ }, m2.daysInMonth = function() {
273
+ return this.endOf(c).$D;
274
+ }, m2.$locale = function() {
275
+ return D[this.$L];
276
+ }, m2.locale = function(t2, e2) {
277
+ if (!t2) return this.$L;
278
+ var n2 = this.clone(), r2 = w(t2, e2, !0);
279
+ return r2 && (n2.$L = r2), n2;
280
+ }, m2.clone = function() {
281
+ return b.w(this.$d, this);
282
+ }, m2.toDate = function() {
283
+ return new Date(this.valueOf());
284
+ }, m2.toJSON = function() {
285
+ return this.isValid() ? this.toISOString() : null;
286
+ }, m2.toISOString = function() {
287
+ return this.$d.toISOString();
288
+ }, m2.toString = function() {
289
+ return this.$d.toUTCString();
290
+ }, M2;
291
+ })(), k = _.prototype;
292
+ return O.prototype = k, [["$ms", r], ["$s", i], ["$m", s], ["$H", u], ["$W", a], ["$M", c], ["$y", h], ["$D", d]].forEach((function(t2) {
293
+ k[t2[1]] = function(e2) {
294
+ return this.$g(e2, t2[0], t2[1]);
295
+ };
296
+ })), O.extend = function(t2, e2) {
297
+ return t2.$i || (t2(e2, _, O), t2.$i = !0), O;
298
+ }, O.locale = w, O.isDayjs = S, O.unix = function(t2) {
299
+ return O(1e3 * t2);
300
+ }, O.en = D[g], O.Ls = D, O.p = {}, O;
301
+ }));
302
+ }
303
+ });
304
+
305
+ // ../../node_modules/dayjs/plugin/relativeTime.js
306
+ var require_relativeTime = __commonJS({
307
+ "../../node_modules/dayjs/plugin/relativeTime.js"(exports, module) {
308
+ (function(r, e) {
309
+ typeof exports == "object" && typeof module < "u" ? module.exports = e() : typeof define == "function" && define.amd ? define(e) : (r = typeof globalThis < "u" ? globalThis : r || self).dayjs_plugin_relativeTime = e();
310
+ })(exports, (function() {
311
+ "use strict";
312
+ return function(r, e, t) {
313
+ r = r || {};
314
+ var n = e.prototype, o = { future: "in %s", past: "%s ago", s: "a few seconds", m: "a minute", mm: "%d minutes", h: "an hour", hh: "%d hours", d: "a day", dd: "%d days", M: "a month", MM: "%d months", y: "a year", yy: "%d years" };
315
+ function i(r2, e2, t2, o2) {
316
+ return n.fromToBase(r2, e2, t2, o2);
317
+ }
318
+ t.en.relativeTime = o, n.fromToBase = function(e2, n2, i2, d2, u) {
319
+ for (var f, a, s, l = i2.$locale().relativeTime || o, h = r.thresholds || [{ l: "s", r: 44, d: "second" }, { l: "m", r: 89 }, { l: "mm", r: 44, d: "minute" }, { l: "h", r: 89 }, { l: "hh", r: 21, d: "hour" }, { l: "d", r: 35 }, { l: "dd", r: 25, d: "day" }, { l: "M", r: 45 }, { l: "MM", r: 10, d: "month" }, { l: "y", r: 17 }, { l: "yy", d: "year" }], m = h.length, c = 0; c < m; c += 1) {
320
+ var y = h[c];
321
+ y.d && (f = d2 ? t(e2).diff(i2, y.d, !0) : i2.diff(e2, y.d, !0));
322
+ var p = (r.rounding || Math.round)(Math.abs(f));
323
+ if (s = f > 0, p <= y.r || !y.r) {
324
+ p <= 1 && c > 0 && (y = h[c - 1]);
325
+ var v = l[y.l];
326
+ u && (p = u("" + p)), a = typeof v == "string" ? v.replace("%d", p) : v(p, n2, y.l, s);
327
+ break;
328
+ }
329
+ }
330
+ if (n2) return a;
331
+ var M = s ? l.future : l.past;
332
+ return typeof M == "function" ? M(a) : M.replace("%s", a);
333
+ }, n.to = function(r2, e2) {
334
+ return i(r2, e2, this, !0);
335
+ }, n.from = function(r2, e2) {
336
+ return i(r2, e2, this);
337
+ };
338
+ var d = function(r2) {
339
+ return r2.$u ? t.utc() : t();
340
+ };
341
+ n.toNow = function(r2) {
342
+ return this.to(d(this), r2);
343
+ }, n.fromNow = function(r2) {
344
+ return this.from(d(this), r2);
345
+ };
346
+ };
347
+ }));
348
+ }
349
+ });
2
350
 
3
351
  // src/index.ts
4
352
  import { Command } from "commander";
5
- import { execSync as execSync3 } from "node:child_process";
6
- import { rmSync, existsSync as existsSync3 } from "node:fs";
7
- import { join as join6 } from "node:path";
8
- import { homedir as homedir3 } from "node:os";
9
- import { createHash as createHash3 } from "node:crypto";
10
- import { createRequire } from "node:module";
11
- import open from "open";
12
- import pc2 from "picocolors";
353
+ import { createHash as createHash4 } from "node:crypto";
354
+ import { createRequire as createRequire2 } from "node:module";
355
+ import open2 from "open";
356
+ import pc7 from "picocolors";
13
357
 
14
358
  // ../git/dist/repo.js
15
359
  import { execFileSync, execSync as execSync2 } from "node:child_process";
@@ -99,9 +443,16 @@ function isValidGitRef(ref) {
99
443
  return !1;
100
444
  }
101
445
  }
102
- var ACTIONABLE_REFS = /* @__PURE__ */ new Set(["work", "staged", "unstaged", "working", "untracked"]);
103
- function isActionableRef(ref) {
104
- return !!ref && ACTIONABLE_REFS.has(ref);
446
+ var WORKING_TREE_REFS = /* @__PURE__ */ new Set(["work", "staged", "unstaged", "working", "untracked"]);
447
+ function getRefCapabilities(ref) {
448
+ if (!ref)
449
+ return { reviews: !0, revert: !1, staleness: !1 };
450
+ let isWorkingTree = WORKING_TREE_REFS.has(ref);
451
+ return {
452
+ reviews: !0,
453
+ revert: isWorkingTree,
454
+ staleness: isWorkingTree || ref.includes("..")
455
+ };
105
456
  }
106
457
 
107
458
  // ../git/dist/diff.js
@@ -587,7 +938,9 @@ function addReply(threadId, body, author) {
587
938
  let db2 = getDb(), commentId = randomUUID2(), now = (/* @__PURE__ */ new Date()).toISOString();
588
939
  return db2.prepare(
589
940
  "INSERT INTO comments (id, thread_id, author_name, author_type, body, created_at) VALUES (?, ?, ?, ?, ?, ?)"
590
- ).run(commentId, threadId, author.name, author.type, body, now), db2.prepare(
941
+ ).run(commentId, threadId, author.name, author.type, body, now), author.type === "user" ? db2.prepare(
942
+ "UPDATE comment_threads SET status = ?, updated_at = ? WHERE id = ?"
943
+ ).run("open", now, threadId) : db2.prepare(
591
944
  "UPDATE comment_threads SET updated_at = ? WHERE id = ?"
592
945
  ).run(now, threadId), {
593
946
  id: commentId,
@@ -891,9 +1244,7 @@ function readBody2(req) {
891
1244
  });
892
1245
  }
893
1246
  function startServer(options) {
894
- let { port, portIsExplicit, diffArgs, description, effectiveRef, registryInfo } = options, sessionId = null, reviewsEnabled = isActionableRef(effectiveRef);
895
- reviewsEnabled && effectiveRef && (sessionId = findOrCreateSession(effectiveRef).id);
896
- let includeUntracked = diffArgs.length === 0;
1247
+ let { port, portIsExplicit, diffArgs, description, effectiveRef, registryInfo } = options, includeUntracked = diffArgs.length === 0;
897
1248
  function enrichWithLineCounts(diff, baseRef) {
898
1249
  for (let file of diff.files) {
899
1250
  if (file.status === "added" || file.isBinary)
@@ -1027,11 +1378,13 @@ function startServer(options) {
1027
1378
  return;
1028
1379
  }
1029
1380
  if (pathname === "/api/info") {
1030
- let ref = url.searchParams.get("ref"), info = getRepoInfo(), refDescription = description || diffArgs.join(" ") || "Unstaged changes";
1031
- ref && (refDescription = descriptionForRef(ref)), sendJson2(res, {
1381
+ let ref = url.searchParams.get("ref") || effectiveRef, info = getRepoInfo(), refDescription = description || diffArgs.join(" ") || "Unstaged changes";
1382
+ url.searchParams.get("ref") && (refDescription = descriptionForRef(url.searchParams.get("ref")));
1383
+ let capabilities = getRefCapabilities(ref), sessionId = null;
1384
+ ref && (sessionId = findOrCreateSession(ref).id), sendJson2(res, {
1032
1385
  ...info,
1033
1386
  description: refDescription,
1034
- capabilities: { reviews: reviewsEnabled },
1387
+ capabilities,
1035
1388
  sessionId
1036
1389
  });
1037
1390
  return;
@@ -1140,8 +1493,117 @@ Examples:
1140
1493
  });
1141
1494
  }
1142
1495
 
1496
+ // src/commands/open.ts
1497
+ import { createHash as createHash3 } from "node:crypto";
1498
+ import open from "open";
1499
+ import pc2 from "picocolors";
1500
+ function registerOpenCommand(program2) {
1501
+ program2.command("open").description("Open the browser to a running diffity instance").argument("[ref]", "Ref to view (e.g. work, staged, HEAD~1)").action(async (ref) => {
1502
+ isGitRepo() || (console.error(pc2.red("Error: Not a git repository")), process.exit(1));
1503
+ let repoRoot = getRepoRoot(), repoHash = createHash3("sha256").update(repoRoot).digest("hex").slice(0, 12), existing = findInstanceForRepo(repoHash);
1504
+ existing || (console.error(pc2.red("No running diffity instance for this repo.")), console.log(`Run ${pc2.cyan("diffity")} to start one.`), process.exit(1));
1505
+ let urlParams = new URLSearchParams();
1506
+ ref && urlParams.set("ref", ref);
1507
+ let qs = urlParams.toString(), url = `http://localhost:${existing.port}/${qs ? `?${qs}` : ""}`;
1508
+ console.log(` ${pc2.green("\u2192")} ${pc2.cyan(url)}`), await open(url);
1509
+ });
1510
+ }
1511
+
1512
+ // src/commands/list.ts
1513
+ var import_dayjs = __toESM(require_dayjs_min(), 1), import_relativeTime = __toESM(require_relativeTime(), 1);
1514
+ import pc3 from "picocolors";
1515
+ import_dayjs.default.extend(import_relativeTime.default);
1516
+ function registerListCommand(program2) {
1517
+ program2.command("list").description("List all running diffity instances").option("--json", "Output as JSON").action((opts) => {
1518
+ let entries = readRegistry();
1519
+ if (opts.json) {
1520
+ console.log(JSON.stringify(entries, null, 2));
1521
+ return;
1522
+ }
1523
+ if (entries.length === 0) {
1524
+ console.log(pc3.dim("No running diffity instances."));
1525
+ return;
1526
+ }
1527
+ console.log(""), console.log(
1528
+ ` ${pc3.dim("PORT")} ${pc3.dim("PID".padEnd(8))}${pc3.dim("REPO".padEnd(22))}${pc3.dim("REF".padEnd(22))}${pc3.dim("STARTED")}`
1529
+ );
1530
+ for (let entry of entries) {
1531
+ let ago = (0, import_dayjs.default)(entry.startedAt).fromNow();
1532
+ console.log(
1533
+ ` ${String(entry.port).padEnd(7)}${String(entry.pid).padEnd(8)}${entry.repoName.slice(0, 20).padEnd(22)}${entry.ref.slice(0, 20).padEnd(22)}${pc3.dim(ago)}`
1534
+ );
1535
+ }
1536
+ console.log("");
1537
+ });
1538
+ }
1539
+
1540
+ // src/commands/prune.ts
1541
+ import { rmSync, existsSync as existsSync3 } from "node:fs";
1542
+ import { join as join6 } from "node:path";
1543
+ import { homedir as homedir3 } from "node:os";
1544
+ import pc4 from "picocolors";
1545
+ function registerPruneCommand(program2) {
1546
+ program2.command("prune").description("Remove all diffity data (database, sessions) for all repos").action(() => {
1547
+ let dir = join6(homedir3(), ".diffity");
1548
+ if (!existsSync3(dir)) {
1549
+ console.log(pc4.dim("Nothing to prune."));
1550
+ return;
1551
+ }
1552
+ let running = readRegistry();
1553
+ for (let entry of running)
1554
+ try {
1555
+ process.kill(entry.pid, "SIGTERM");
1556
+ } catch {
1557
+ }
1558
+ running.length > 0 && console.log(pc4.dim(` Stopped ${running.length} running instance${running.length > 1 ? "s" : ""}.`)), rmSync(dir, { recursive: !0, force: !0 }), console.log(pc4.green("Pruned all diffity data (~/.diffity)."));
1559
+ });
1560
+ }
1561
+
1562
+ // src/commands/update.ts
1563
+ import { execSync as execSync3 } from "node:child_process";
1564
+ import pc5 from "picocolors";
1565
+ function registerUpdateCommand(program2, version) {
1566
+ program2.command("update").description("Update diffity to the latest version").action(() => {
1567
+ try {
1568
+ let registry = execSync3("npm view diffity version", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
1569
+ if (registry === version) {
1570
+ console.log(pc5.green(`Already on the latest version (${version}).`));
1571
+ return;
1572
+ }
1573
+ console.log(`${pc5.dim(`Current: ${version}`)} \u2192 ${pc5.bold(registry)}`), console.log(pc5.dim("Updating...")), execSync3("npm install -g diffity@latest", { stdio: "inherit" }), console.log(pc5.green(`Updated to ${registry}.`));
1574
+ } catch {
1575
+ console.error(pc5.red("Failed to update. Try running: npm install -g diffity@latest")), process.exit(1);
1576
+ }
1577
+ });
1578
+ }
1579
+
1580
+ // src/commands/doctor.ts
1581
+ import { execSync as execSync4 } from "node:child_process";
1582
+ import { createRequire } from "node:module";
1583
+ import pc6 from "picocolors";
1584
+ var require2 = createRequire(import.meta.url);
1585
+ function registerDoctorCommand(program2, version) {
1586
+ program2.command("doctor").description("Check that diffity can run correctly").action(() => {
1587
+ let ok = !0;
1588
+ process.stdout.write(" git ");
1589
+ try {
1590
+ let gitVersion = execSync4("git --version", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
1591
+ console.log(pc6.green(`\u2713 ${gitVersion}`));
1592
+ } catch {
1593
+ console.log(pc6.red("\u2717 git not found")), ok = !1;
1594
+ }
1595
+ process.stdout.write(" git repo "), isGitRepo() ? console.log(pc6.green("\u2713 inside a git repository")) : console.log(pc6.yellow("- not inside a git repository")), process.stdout.write(" node "), console.log(pc6.green(`\u2713 ${process.version}`)), process.stdout.write(" sqlite ");
1596
+ try {
1597
+ require2("better-sqlite3"), console.log(pc6.green("\u2713 better-sqlite3 loaded"));
1598
+ } catch {
1599
+ console.log(pc6.red("\u2717 better-sqlite3 failed to load (native module issue)")), ok = !1;
1600
+ }
1601
+ process.stdout.write(" version "), console.log(pc6.green(`\u2713 diffity ${version}`)), console.log(""), ok ? console.log(pc6.green(" All checks passed.")) : (console.log(pc6.red(" Some checks failed. Fix the issues above and try again.")), process.exit(1));
1602
+ });
1603
+ }
1604
+
1143
1605
  // src/index.ts
1144
- var require2 = createRequire(import.meta.url), pkg = require2("../package.json"), program = new Command();
1606
+ var require3 = createRequire2(import.meta.url), pkg = require3("../package.json"), program = new Command();
1145
1607
  program.name("diffity").description("GitHub-style git diff viewer in the browser").version(pkg.version).argument("[refs...]", "Git refs to diff (e.g. HEAD~3, main, main..feature)").option("--port <port>", "Port to use (default: auto-assigned from 5391)", "5391").option("--no-open", "Do not open browser automatically").option("--quiet", "Minimal terminal output").option("--dark", "Open in dark mode (default: light)").option("--unified", "Open in unified view (default: split)").option("--new", "Stop existing instance and start fresh").addHelpText("after", `
1146
1608
  Examples:
1147
1609
  $ diffity Working tree changes
@@ -1151,9 +1613,9 @@ Examples:
1151
1613
  $ diffity main..feature Compare branches
1152
1614
  $ diffity main feature Same as main..feature
1153
1615
  $ diffity v1.0.0..v2.0.0 Compare tags`).action(async (refs, opts) => {
1154
- isGitRepo() || (console.error(pc2.red("Error: Not a git repository")), process.exit(1));
1616
+ isGitRepo() || (console.error(pc7.red("Error: Not a git repository")), process.exit(1));
1155
1617
  for (let ref of refs)
1156
- isValidGitRef(ref) || (console.error(pc2.red(`Error: '${ref}' is not a valid git reference.`)), console.log(""), console.log("Usage:"), console.log(` ${pc2.cyan("diffity")} Working tree changes`), console.log(` ${pc2.cyan("diffity HEAD~1")} Last commit vs working tree`), console.log(` ${pc2.cyan("diffity main..feature")} Compare branches`), console.log(` ${pc2.cyan("diffity main feature")} Same as main..feature`), console.log(""), console.log(`Run ${pc2.cyan("diffity --help")} for more options.`), process.exit(1));
1618
+ isValidGitRef(ref) || (console.error(pc7.red(`Error: '${ref}' is not a valid git reference.`)), console.log(""), console.log("Usage:"), console.log(` ${pc7.cyan("diffity")} Working tree changes`), console.log(` ${pc7.cyan("diffity HEAD~1")} Last commit vs working tree`), console.log(` ${pc7.cyan("diffity main..feature")} Compare branches`), console.log(` ${pc7.cyan("diffity main feature")} Same as main..feature`), console.log(""), console.log(`Run ${pc7.cyan("diffity --help")} for more options.`), process.exit(1));
1157
1619
  let diffArgs = [], description = "";
1158
1620
  if (refs.length === 1) {
1159
1621
  let ref = refs[0];
@@ -1161,19 +1623,19 @@ Examples:
1161
1623
  } else refs.length === 2 ? (diffArgs.push(`${refs[0]}..${refs[1]}`), description = `${refs[0]}..${refs[1]}`) : description = "Unstaged changes";
1162
1624
  let effectiveRef;
1163
1625
  refs.length > 0 ? effectiveRef = refs.length === 2 ? `${refs[0]}..${refs[1]}` : refs[0] : effectiveRef = "work";
1164
- let repoRoot = getRepoRoot(), repoHash = createHash3("sha256").update(repoRoot).digest("hex").slice(0, 12), repoName = getRepoName(), existing = findInstanceForRepo(repoHash);
1626
+ let repoRoot = getRepoRoot(), repoHash = createHash4("sha256").update(repoRoot).digest("hex").slice(0, 12), repoName = getRepoName(), existing = findInstanceForRepo(repoHash);
1165
1627
  if (existing)
1166
1628
  if (opts.new) {
1167
1629
  try {
1168
1630
  process.kill(existing.pid, "SIGTERM");
1169
1631
  } catch {
1170
1632
  }
1171
- deregisterInstance(existing.pid), opts.quiet || console.log(pc2.dim(` Stopped existing instance (pid ${existing.pid})`));
1633
+ deregisterInstance(existing.pid), opts.quiet || console.log(pc7.dim(` Stopped existing instance (pid ${existing.pid})`));
1172
1634
  } else {
1173
1635
  let urlParams = new URLSearchParams({ ref: effectiveRef });
1174
1636
  opts.dark && urlParams.set("theme", "dark"), opts.unified && urlParams.set("view", "unified");
1175
1637
  let url = `http://localhost:${existing.port}/?${urlParams.toString()}`;
1176
- opts.quiet || (console.log(""), console.log(pc2.bold(" diffity")), console.log(` ${pc2.dim("Already running for this repo")}`), console.log(""), console.log(` ${pc2.green("\u2192")} ${pc2.cyan(url)}`), console.log("")), opts.open !== !1 && await open(url);
1638
+ opts.quiet || (console.log(""), console.log(pc7.bold(" diffity")), console.log(` ${pc7.dim("Already running for this repo")}`), console.log(""), console.log(` ${pc7.green("\u2192")} ${pc7.cyan(url)}`), console.log("")), opts.open !== !1 && await open2(url);
1177
1639
  return;
1178
1640
  }
1179
1641
  let explicitPort = program.getOptionValueSource("port") === "cli", port = explicitPort ? parseInt(opts.port, 10) : findAvailablePort();
@@ -1188,89 +1650,20 @@ Examples:
1188
1650
  }), urlParams = new URLSearchParams({ ref: effectiveRef });
1189
1651
  opts.dark && urlParams.set("theme", "dark"), opts.unified && urlParams.set("view", "unified");
1190
1652
  let url = `http://localhost:${actualPort}/?${urlParams.toString()}`;
1191
- opts.quiet || (console.log(""), console.log(pc2.bold(" diffity")), console.log(` ${pc2.dim(description)}`), console.log(""), console.log(` ${pc2.green("\u2192")} ${pc2.cyan(url)}`), console.log(` ${pc2.dim("Press Ctrl+C to stop")}`), console.log("")), process.on("SIGINT", () => {
1192
- opts.quiet || console.log(pc2.dim(`
1653
+ opts.quiet || (console.log(""), console.log(pc7.bold(" diffity")), console.log(` ${pc7.dim(description)}`), console.log(""), console.log(` ${pc7.green("\u2192")} ${pc7.cyan(url)}`), console.log(` ${pc7.dim("Press Ctrl+C to stop")}`), console.log("")), process.on("SIGINT", () => {
1654
+ opts.quiet || console.log(pc7.dim(`
1193
1655
  Shutting down...`)), deregisterInstance(process.pid), close(), process.exit(0);
1194
1656
  }), process.on("SIGTERM", () => {
1195
1657
  deregisterInstance(process.pid), close(), process.exit(0);
1196
- }), opts.open !== !1 && await open(url);
1658
+ }), opts.open !== !1 && await open2(url);
1197
1659
  } catch (err) {
1198
- console.error(pc2.red(`Failed to start server: ${err}`)), process.exit(1);
1199
- }
1200
- });
1201
- program.command("list").description("List all running diffity instances").option("--json", "Output as JSON").action((opts) => {
1202
- let entries = readRegistry();
1203
- if (opts.json) {
1204
- console.log(JSON.stringify(entries, null, 2));
1205
- return;
1206
- }
1207
- if (entries.length === 0) {
1208
- console.log(pc2.dim("No running diffity instances."));
1209
- return;
1210
- }
1211
- console.log(""), console.log(
1212
- ` ${pc2.dim("PORT")} ${pc2.dim("PID".padEnd(8))}${pc2.dim("REPO".padEnd(22))}${pc2.dim("REF".padEnd(22))}${pc2.dim("STARTED")}`
1213
- );
1214
- for (let entry of entries) {
1215
- let ago = getTimeAgo(entry.startedAt);
1216
- console.log(
1217
- ` ${String(entry.port).padEnd(7)}${String(entry.pid).padEnd(8)}${entry.repoName.slice(0, 20).padEnd(22)}${entry.ref.slice(0, 20).padEnd(22)}${pc2.dim(ago)}`
1218
- );
1219
- }
1220
- console.log("");
1221
- });
1222
- function getTimeAgo(isoDate) {
1223
- let diff = Date.now() - new Date(isoDate).getTime(), seconds = Math.floor(diff / 1e3);
1224
- if (seconds < 60)
1225
- return "just now";
1226
- let minutes = Math.floor(seconds / 60);
1227
- if (minutes < 60)
1228
- return `${minutes}m ago`;
1229
- let hours = Math.floor(minutes / 60);
1230
- return hours < 24 ? `${hours}h ago` : `${Math.floor(hours / 24)}d ago`;
1231
- }
1232
- program.command("prune").description("Remove all diffity data (database, sessions) for all repos").action(() => {
1233
- let dir = join6(homedir3(), ".diffity");
1234
- if (!existsSync3(dir)) {
1235
- console.log(pc2.dim("Nothing to prune."));
1236
- return;
1237
- }
1238
- let running = readRegistry();
1239
- for (let entry of running)
1240
- try {
1241
- process.kill(entry.pid, "SIGTERM");
1242
- } catch {
1243
- }
1244
- running.length > 0 && console.log(pc2.dim(` Stopped ${running.length} running instance${running.length > 1 ? "s" : ""}.`)), rmSync(dir, { recursive: !0, force: !0 }), console.log(pc2.green("Pruned all diffity data (~/.diffity)."));
1245
- });
1246
- program.command("update").description("Update diffity to the latest version").action(() => {
1247
- try {
1248
- let registry = execSync3("npm view diffity version", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
1249
- if (registry === pkg.version) {
1250
- console.log(pc2.green(`Already on the latest version (${pkg.version}).`));
1251
- return;
1252
- }
1253
- console.log(`${pc2.dim(`Current: ${pkg.version}`)} \u2192 ${pc2.bold(registry)}`), console.log(pc2.dim("Updating...")), execSync3("npm install -g diffity@latest", { stdio: "inherit" }), console.log(pc2.green(`Updated to ${registry}.`));
1254
- } catch {
1255
- console.error(pc2.red("Failed to update. Try running: npm install -g diffity@latest")), process.exit(1);
1256
- }
1257
- });
1258
- program.command("doctor").description("Check that diffity can run correctly").action(() => {
1259
- let ok = !0;
1260
- process.stdout.write(" git ");
1261
- try {
1262
- let gitVersion = execSync3("git --version", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
1263
- console.log(pc2.green(`\u2713 ${gitVersion}`));
1264
- } catch {
1265
- console.log(pc2.red("\u2717 git not found")), ok = !1;
1266
- }
1267
- process.stdout.write(" git repo "), isGitRepo() ? console.log(pc2.green("\u2713 inside a git repository")) : console.log(pc2.yellow("- not inside a git repository")), process.stdout.write(" node "), console.log(pc2.green(`\u2713 ${process.version}`)), process.stdout.write(" sqlite ");
1268
- try {
1269
- require2("better-sqlite3"), console.log(pc2.green("\u2713 better-sqlite3 loaded"));
1270
- } catch {
1271
- console.log(pc2.red("\u2717 better-sqlite3 failed to load (native module issue)")), ok = !1;
1660
+ console.error(pc7.red(`Failed to start server: ${err}`)), process.exit(1);
1272
1661
  }
1273
- process.stdout.write(" version "), console.log(pc2.green(`\u2713 diffity ${pkg.version}`)), console.log(""), ok ? console.log(pc2.green(" All checks passed.")) : (console.log(pc2.red(" Some checks failed. Fix the issues above and try again.")), process.exit(1));
1274
1662
  });
1663
+ registerOpenCommand(program);
1664
+ registerListCommand(program);
1665
+ registerPruneCommand(program);
1666
+ registerUpdateCommand(program, pkg.version);
1667
+ registerDoctorCommand(program, pkg.version);
1275
1668
  registerAgentCommands(program);
1276
1669
  program.parse();