openspec-stat 1.2.0 → 1.3.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 (43) hide show
  1. package/README.md +28 -0
  2. package/README.zh-CN.md +28 -0
  3. package/dist/cjs/cli.js +12 -127
  4. package/dist/cjs/commands/init.d.ts +7 -0
  5. package/dist/cjs/commands/init.js +58 -0
  6. package/dist/cjs/commands/multi.d.ts +16 -0
  7. package/dist/cjs/commands/multi.js +172 -0
  8. package/dist/cjs/commands/single.d.ts +2 -0
  9. package/dist/cjs/commands/single.js +148 -0
  10. package/dist/cjs/formatters.d.ts +4 -4
  11. package/dist/cjs/formatters.js +128 -36
  12. package/dist/cjs/git-analyzer.d.ts +1 -0
  13. package/dist/cjs/git-analyzer.js +6 -0
  14. package/dist/cjs/i18n/locales/en.json +74 -1
  15. package/dist/cjs/i18n/locales/zh-CN.json +74 -1
  16. package/dist/cjs/multi/config-validator.d.ts +3 -0
  17. package/dist/cjs/multi/config-validator.js +130 -0
  18. package/dist/cjs/multi/config-wizard.d.ts +50 -0
  19. package/dist/cjs/multi/config-wizard.js +331 -0
  20. package/dist/cjs/multi/multi-repo-analyzer.d.ts +14 -0
  21. package/dist/cjs/multi/multi-repo-analyzer.js +210 -0
  22. package/dist/cjs/types.d.ts +46 -0
  23. package/dist/esm/cli.js +54 -139
  24. package/dist/esm/commands/init.d.ts +7 -0
  25. package/dist/esm/commands/init.js +49 -0
  26. package/dist/esm/commands/multi.d.ts +16 -0
  27. package/dist/esm/commands/multi.js +192 -0
  28. package/dist/esm/commands/single.d.ts +2 -0
  29. package/dist/esm/commands/single.js +162 -0
  30. package/dist/esm/formatters.d.ts +4 -4
  31. package/dist/esm/formatters.js +173 -52
  32. package/dist/esm/git-analyzer.d.ts +1 -0
  33. package/dist/esm/git-analyzer.js +104 -77
  34. package/dist/esm/i18n/locales/en.json +74 -1
  35. package/dist/esm/i18n/locales/zh-CN.json +74 -1
  36. package/dist/esm/multi/config-validator.d.ts +3 -0
  37. package/dist/esm/multi/config-validator.js +109 -0
  38. package/dist/esm/multi/config-wizard.d.ts +50 -0
  39. package/dist/esm/multi/config-wizard.js +535 -0
  40. package/dist/esm/multi/multi-repo-analyzer.d.ts +14 -0
  41. package/dist/esm/multi/multi-repo-analyzer.js +446 -0
  42. package/dist/esm/types.d.ts +46 -0
  43. package/package.json +1 -1
@@ -0,0 +1,162 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
3
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
4
+ function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
5
+ import chalk from 'chalk';
6
+ import { loadConfig } from "../config.js";
7
+ import { GitAnalyzer } from "../git-analyzer.js";
8
+ import { StatsAggregator } from "../stats-aggregator.js";
9
+ import { OutputFormatter } from "../formatters.js";
10
+ import { getDefaultTimeRange, parseDateTime, parseBranches } from "../time-utils.js";
11
+ import { selectBranches } from "../branch-selector.js";
12
+ import { initI18n, t } from "../i18n/index.js";
13
+ export function runSingleRepoCommand(_x) {
14
+ return _runSingleRepoCommand.apply(this, arguments);
15
+ }
16
+ function _runSingleRepoCommand() {
17
+ _runSingleRepoCommand = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(options) {
18
+ var config, since, until, defaultRange, branches, analyzer, activeAuthors, commits, analyses, i, commit, analysis, aggregator, result, formatter;
19
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
20
+ while (1) switch (_context.prev = _context.next) {
21
+ case 0:
22
+ _context.prev = 0;
23
+ initI18n(options.lang);
24
+ console.log(chalk.blue(t('loading.config')));
25
+ _context.next = 5;
26
+ return loadConfig(options.config, options.repo);
27
+ case 5:
28
+ config = _context.sent;
29
+ if (options.since || options.until) {
30
+ since = options.since ? parseDateTime(options.since) : getDefaultTimeRange(config.defaultSinceHours, config.defaultUntilHours).since;
31
+ until = options.until ? parseDateTime(options.until) : getDefaultTimeRange(config.defaultSinceHours, config.defaultUntilHours).until;
32
+ } else {
33
+ defaultRange = getDefaultTimeRange(config.defaultSinceHours, config.defaultUntilHours);
34
+ since = defaultRange.since;
35
+ until = defaultRange.until;
36
+ }
37
+ if (!options.branches) {
38
+ _context.next = 11;
39
+ break;
40
+ }
41
+ branches = parseBranches(options.branches);
42
+ _context.next = 18;
43
+ break;
44
+ case 11:
45
+ if (!(options.interactive !== false)) {
46
+ _context.next = 17;
47
+ break;
48
+ }
49
+ _context.next = 14;
50
+ return selectBranches(options.repo, config.defaultBranches);
51
+ case 14:
52
+ branches = _context.sent;
53
+ _context.next = 18;
54
+ break;
55
+ case 17:
56
+ branches = config.defaultBranches || [];
57
+ case 18:
58
+ console.log(chalk.blue(t('info.timeRange', {
59
+ since: since.toLocaleString(),
60
+ until: until.toLocaleString()
61
+ })));
62
+ console.log(chalk.blue(t('info.branches', {
63
+ branches: branches.join(', ') || t('info.allBranches')
64
+ })));
65
+ analyzer = new GitAnalyzer(options.repo, config); // Fetch remote branches to ensure data is up-to-date
66
+ if (!(!options.noFetch && config.autoFetch !== false)) {
67
+ _context.next = 25;
68
+ break;
69
+ }
70
+ console.log(chalk.blue(t('loading.fetching')));
71
+ _context.next = 25;
72
+ return analyzer.fetchRemote();
73
+ case 25:
74
+ console.log(chalk.blue(t('loading.activeUsers')));
75
+ _context.next = 28;
76
+ return analyzer.getActiveAuthors(config.activeUserWeeks || 2);
77
+ case 28:
78
+ activeAuthors = _context.sent;
79
+ if (options.verbose) {
80
+ console.log(chalk.gray(t('info.activeUsers', {
81
+ weeks: String(config.activeUserWeeks || 2),
82
+ users: Array.from(activeAuthors).join(', ')
83
+ })));
84
+ }
85
+ console.log(chalk.blue(t('loading.analyzing')));
86
+ _context.next = 33;
87
+ return analyzer.getCommits(since, until, branches);
88
+ case 33:
89
+ commits = _context.sent;
90
+ if (!(commits.length === 0)) {
91
+ _context.next = 37;
92
+ break;
93
+ }
94
+ console.log(chalk.yellow(t('warning.noCommits')));
95
+ return _context.abrupt("return");
96
+ case 37:
97
+ console.log(chalk.blue(t('info.foundCommits', {
98
+ count: String(commits.length)
99
+ })));
100
+ analyses = [];
101
+ i = 0;
102
+ case 40:
103
+ if (!(i < commits.length)) {
104
+ _context.next = 50;
105
+ break;
106
+ }
107
+ commit = commits[i];
108
+ if (options.verbose && i % 10 === 0) {
109
+ console.log(chalk.gray(t('info.analysisProgress', {
110
+ current: String(i + 1),
111
+ total: String(commits.length)
112
+ })));
113
+ }
114
+ _context.next = 45;
115
+ return analyzer.analyzeCommit(commit);
116
+ case 45:
117
+ analysis = _context.sent;
118
+ if (analysis) {
119
+ analyses.push(analysis);
120
+ }
121
+ case 47:
122
+ i++;
123
+ _context.next = 40;
124
+ break;
125
+ case 50:
126
+ if (!(analyses.length === 0)) {
127
+ _context.next = 53;
128
+ break;
129
+ }
130
+ console.log(chalk.yellow(t('warning.noQualifyingCommits')));
131
+ return _context.abrupt("return");
132
+ case 53:
133
+ console.log(chalk.blue(t('info.qualifyingCommits', {
134
+ count: String(analyses.length)
135
+ })));
136
+ aggregator = new StatsAggregator(config, activeAuthors);
137
+ result = aggregator.aggregate(analyses, since, until, branches, options.author);
138
+ formatter = new OutputFormatter();
139
+ if (options.json) {
140
+ console.log(formatter.formatJSON(result));
141
+ } else if (options.csv) {
142
+ console.log(formatter.formatCSV(result));
143
+ } else if (options.markdown) {
144
+ console.log(formatter.formatMarkdown(result));
145
+ } else {
146
+ console.log(formatter.formatTable(result, options.verbose));
147
+ }
148
+ _context.next = 64;
149
+ break;
150
+ case 60:
151
+ _context.prev = 60;
152
+ _context.t0 = _context["catch"](0);
153
+ console.error(chalk.red(t('error.prefix')), _context.t0);
154
+ process.exit(1);
155
+ case 64:
156
+ case "end":
157
+ return _context.stop();
158
+ }
159
+ }, _callee, null, [[0, 60]]);
160
+ }));
161
+ return _runSingleRepoCommand.apply(this, arguments);
162
+ }
@@ -1,7 +1,7 @@
1
1
  import { StatsResult } from './types.js';
2
2
  export declare class OutputFormatter {
3
- formatTable(result: StatsResult, verbose?: boolean): string;
4
- formatJSON(result: StatsResult): string;
5
- formatCSV(result: StatsResult): string;
6
- formatMarkdown(result: StatsResult): string;
3
+ formatTable(result: StatsResult, verbose?: boolean, showContributors?: boolean): string;
4
+ formatJSON(result: StatsResult, showContributors?: boolean): string;
5
+ formatCSV(result: StatsResult, showContributors?: boolean): string;
6
+ formatMarkdown(result: StatsResult, showContributors?: boolean): string;
7
7
  }
@@ -18,6 +18,7 @@ export var OutputFormatter = /*#__PURE__*/function () {
18
18
  key: "formatTable",
19
19
  value: function formatTable(result) {
20
20
  var verbose = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
21
+ var showContributors = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
21
22
  var output = '';
22
23
  output += chalk.bold(t('output.title'));
23
24
  output += chalk.gray(t('output.timeRange', {
@@ -93,6 +94,42 @@ export var OutputFormatter = /*#__PURE__*/function () {
93
94
  var sortedAuthors = Array.from(result.authors.values()).sort(function (a, b) {
94
95
  return b.commits - a.commits;
95
96
  });
97
+ if (!showContributors) {
98
+ // Show only summary when showContributors is false
99
+ var totalAuthors = sortedAuthors.length;
100
+ var totalCommits = sortedAuthors.reduce(function (sum, s) {
101
+ return sum + s.commits;
102
+ }, 0);
103
+ var totalProposalsSet = new Set();
104
+ sortedAuthors.forEach(function (s) {
105
+ return s.openspecProposals.forEach(function (p) {
106
+ return totalProposalsSet.add(p);
107
+ });
108
+ });
109
+ var totalFiles = sortedAuthors.reduce(function (sum, s) {
110
+ return sum + s.codeFilesChanged;
111
+ }, 0);
112
+ var totalAdditions = sortedAuthors.reduce(function (sum, s) {
113
+ return sum + s.additions;
114
+ }, 0);
115
+ var totalDeletions = sortedAuthors.reduce(function (sum, s) {
116
+ return sum + s.deletions;
117
+ }, 0);
118
+ var totalNetChanges = sortedAuthors.reduce(function (sum, s) {
119
+ return sum + s.netChanges;
120
+ }, 0);
121
+ var summaryTable = new Table({
122
+ head: [chalk.cyan(t('table.contributors')), chalk.cyan(t('table.commits')), chalk.cyan(t('table.proposals')), chalk.cyan(t('table.codeFiles')), chalk.cyan(t('table.additions')), chalk.cyan(t('table.deletions')), chalk.cyan(t('table.netChanges'))],
123
+ style: {
124
+ head: [],
125
+ border: []
126
+ }
127
+ });
128
+ summaryTable.push([totalAuthors.toString(), totalCommits.toString(), totalProposalsSet.size.toString(), totalFiles.toString(), chalk.green("+".concat(totalAdditions)), chalk.red("-".concat(totalDeletions)), totalNetChanges >= 0 ? chalk.green("+".concat(totalNetChanges)) : chalk.red("".concat(totalNetChanges))]);
129
+ output += summaryTable.toString() + '\n';
130
+ output += chalk.gray(t('output.contributorHint')) + '\n';
131
+ return output;
132
+ }
96
133
  var _iterator2 = _createForOfIteratorHelper(sortedAuthors),
97
134
  _step2;
98
135
  try {
@@ -151,6 +188,8 @@ export var OutputFormatter = /*#__PURE__*/function () {
151
188
  }, {
152
189
  key: "formatJSON",
153
190
  value: function formatJSON(result) {
191
+ var showContributors = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
192
+ var sortedAuthors = Array.from(result.authors.values());
154
193
  var data = {
155
194
  timeRange: {
156
195
  since: result.timeRange.since.toISOString(),
@@ -189,8 +228,10 @@ export var OutputFormatter = /*#__PURE__*/function () {
189
228
  return sum + p.netChanges;
190
229
  }, 0)
191
230
  }
192
- },
193
- authors: Array.from(result.authors.values()).map(function (stats) {
231
+ }
232
+ };
233
+ if (showContributors) {
234
+ data.authors = sortedAuthors.map(function (stats) {
194
235
  var _stats$lastCommitDate;
195
236
  return {
196
237
  author: stats.author,
@@ -203,13 +244,40 @@ export var OutputFormatter = /*#__PURE__*/function () {
203
244
  netChanges: stats.netChanges,
204
245
  lastCommitDate: (_stats$lastCommitDate = stats.lastCommitDate) === null || _stats$lastCommitDate === void 0 ? void 0 : _stats$lastCommitDate.toISOString()
205
246
  };
206
- })
207
- };
247
+ });
248
+ } else {
249
+ var totalProposalsSet = new Set();
250
+ sortedAuthors.forEach(function (s) {
251
+ return s.openspecProposals.forEach(function (p) {
252
+ return totalProposalsSet.add(p);
253
+ });
254
+ });
255
+ data.authorsSummary = {
256
+ totalContributors: sortedAuthors.length,
257
+ totalCommits: sortedAuthors.reduce(function (sum, s) {
258
+ return sum + s.commits;
259
+ }, 0),
260
+ totalProposals: totalProposalsSet.size,
261
+ totalCodeFiles: sortedAuthors.reduce(function (sum, s) {
262
+ return sum + s.codeFilesChanged;
263
+ }, 0),
264
+ totalAdditions: sortedAuthors.reduce(function (sum, s) {
265
+ return sum + s.additions;
266
+ }, 0),
267
+ totalDeletions: sortedAuthors.reduce(function (sum, s) {
268
+ return sum + s.deletions;
269
+ }, 0),
270
+ totalNetChanges: sortedAuthors.reduce(function (sum, s) {
271
+ return sum + s.netChanges;
272
+ }, 0)
273
+ };
274
+ }
208
275
  return JSON.stringify(data, null, 2);
209
276
  }
210
277
  }, {
211
278
  key: "formatCSV",
212
279
  value: function formatCSV(result) {
280
+ var showContributors = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
213
281
  var rows = [];
214
282
 
215
283
  // Proposal summary section
@@ -222,9 +290,9 @@ export var OutputFormatter = /*#__PURE__*/function () {
222
290
  _step4;
223
291
  try {
224
292
  for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
225
- var stats = _step4.value;
226
- var contributors = Array.from(stats.contributors).join(';');
227
- rows.push([stats.proposal, stats.commits, "\"".concat(contributors, "\""), stats.codeFilesChanged, stats.additions, stats.deletions, stats.netChanges].join(','));
293
+ var _stats = _step4.value;
294
+ var contributors = Array.from(_stats.contributors).join(';');
295
+ rows.push([_stats.proposal, _stats.commits, "\"".concat(contributors, "\""), _stats.codeFilesChanged, _stats.additions, _stats.deletions, _stats.netChanges].join(','));
228
296
  }
229
297
 
230
298
  // Proposal totals
@@ -260,29 +328,53 @@ export var OutputFormatter = /*#__PURE__*/function () {
260
328
 
261
329
  // Author summary section
262
330
  rows.push("\n# ".concat(t('output.authorSummary')));
263
- rows.push("".concat(t('table.author'), ",").concat(t('table.period'), ",").concat(t('table.commits'), ",").concat(t('table.proposalsCount'), ",").concat(t('table.proposalsList'), ",").concat(t('table.codeFiles'), ",").concat(t('table.additions'), ",").concat(t('table.deletions'), ",").concat(t('table.netChanges'), ",").concat(t('table.lastCommitDate')));
264
331
  var sortedAuthors = Array.from(result.authors.values()).sort(function (a, b) {
265
332
  return b.commits - a.commits;
266
333
  });
267
- var _iterator5 = _createForOfIteratorHelper(sortedAuthors),
268
- _step5;
269
- try {
270
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
271
- var _stats$lastCommitDate2;
272
- var _stats = _step5.value;
273
- var proposals = Array.from(_stats.openspecProposals).join(';');
274
- rows.push([_stats.author, _stats.statisticsPeriod || '-', _stats.commits, _stats.openspecProposals.size, "\"".concat(proposals, "\""), _stats.codeFilesChanged, _stats.additions, _stats.deletions, _stats.netChanges, ((_stats$lastCommitDate2 = _stats.lastCommitDate) === null || _stats$lastCommitDate2 === void 0 ? void 0 : _stats$lastCommitDate2.toISOString()) || ''].join(','));
334
+ if (showContributors) {
335
+ rows.push("".concat(t('table.author'), ",").concat(t('table.period'), ",").concat(t('table.commits'), ",").concat(t('table.proposalsCount'), ",").concat(t('table.proposalsList'), ",").concat(t('table.codeFiles'), ",").concat(t('table.additions'), ",").concat(t('table.deletions'), ",").concat(t('table.netChanges'), ",").concat(t('table.lastCommitDate')));
336
+ var _iterator5 = _createForOfIteratorHelper(sortedAuthors),
337
+ _step5;
338
+ try {
339
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
340
+ var _stats$lastCommitDate2;
341
+ var stats = _step5.value;
342
+ var proposals = Array.from(stats.openspecProposals).join(';');
343
+ rows.push([stats.author, stats.statisticsPeriod || '-', stats.commits, stats.openspecProposals.size, "\"".concat(proposals, "\""), stats.codeFilesChanged, stats.additions, stats.deletions, stats.netChanges, ((_stats$lastCommitDate2 = stats.lastCommitDate) === null || _stats$lastCommitDate2 === void 0 ? void 0 : _stats$lastCommitDate2.toISOString()) || ''].join(','));
344
+ }
345
+ } catch (err) {
346
+ _iterator5.e(err);
347
+ } finally {
348
+ _iterator5.f();
275
349
  }
276
- } catch (err) {
277
- _iterator5.e(err);
278
- } finally {
279
- _iterator5.f();
350
+ } else {
351
+ rows.push("".concat(t('table.contributors'), ",").concat(t('table.commits'), ",").concat(t('table.proposals'), ",").concat(t('table.codeFiles'), ",").concat(t('table.additions'), ",").concat(t('table.deletions'), ",").concat(t('table.netChanges')));
352
+ var totalProposalsSet = new Set();
353
+ sortedAuthors.forEach(function (s) {
354
+ return s.openspecProposals.forEach(function (p) {
355
+ return totalProposalsSet.add(p);
356
+ });
357
+ });
358
+ rows.push([sortedAuthors.length, sortedAuthors.reduce(function (sum, s) {
359
+ return sum + s.commits;
360
+ }, 0), totalProposalsSet.size, sortedAuthors.reduce(function (sum, s) {
361
+ return sum + s.codeFilesChanged;
362
+ }, 0), sortedAuthors.reduce(function (sum, s) {
363
+ return sum + s.additions;
364
+ }, 0), sortedAuthors.reduce(function (sum, s) {
365
+ return sum + s.deletions;
366
+ }, 0), sortedAuthors.reduce(function (sum, s) {
367
+ return sum + s.netChanges;
368
+ }, 0)].join(','));
369
+ rows.push('');
370
+ rows.push("# ".concat(t('output.contributorHint')));
280
371
  }
281
372
  return rows.join('\n');
282
373
  }
283
374
  }, {
284
375
  key: "formatMarkdown",
285
376
  value: function formatMarkdown(result) {
377
+ var showContributors = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
286
378
  var md = '';
287
379
  md += t('markdown.title');
288
380
  md += t('markdown.timeRange', {
@@ -311,9 +403,9 @@ export var OutputFormatter = /*#__PURE__*/function () {
311
403
  _step6;
312
404
  try {
313
405
  for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
314
- var stats = _step6.value;
315
- var contributors = Array.from(stats.contributors).join(', ');
316
- md += "| ".concat(stats.proposal, " | ").concat(stats.commits, " | ").concat(contributors, " | ").concat(stats.codeFilesChanged, " | +").concat(stats.additions, " | -").concat(stats.deletions, " | ").concat(stats.netChanges >= 0 ? '+' : '').concat(stats.netChanges, " |\n");
406
+ var _stats3 = _step6.value;
407
+ var contributors = Array.from(_stats3.contributors).join(', ');
408
+ md += "| ".concat(_stats3.proposal, " | ").concat(_stats3.commits, " | ").concat(contributors, " | ").concat(_stats3.codeFilesChanged, " | +").concat(_stats3.additions, " | -").concat(_stats3.deletions, " | ").concat(_stats3.netChanges >= 0 ? '+' : '').concat(_stats3.netChanges, " |\n");
317
409
  }
318
410
 
319
411
  // Proposal totals
@@ -348,42 +440,71 @@ export var OutputFormatter = /*#__PURE__*/function () {
348
440
 
349
441
  // Author summary
350
442
  md += "\n## ".concat(t('output.authorSummary'), "\n\n");
351
- md += "| ".concat(t('table.author'), " | ").concat(t('table.period'), " | ").concat(t('table.commits'), " | ").concat(t('table.proposals'), " | ").concat(t('table.codeFiles'), " | ").concat(t('table.additions'), " | ").concat(t('table.deletions'), " | ").concat(t('table.netChanges'), " |\n");
352
- md += '|--------|--------|---------|-----------|------------|-----------|-----------|-------------|\n';
353
443
  var sortedAuthors = Array.from(result.authors.values()).sort(function (a, b) {
354
444
  return b.commits - a.commits;
355
445
  });
356
- var _iterator7 = _createForOfIteratorHelper(sortedAuthors),
357
- _step7;
358
- try {
359
- for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
360
- var _stats2 = _step7.value;
361
- md += "| ".concat(_stats2.author, " | ").concat(_stats2.statisticsPeriod || '-', " | ").concat(_stats2.commits, " | ").concat(_stats2.openspecProposals.size, " | ").concat(_stats2.codeFilesChanged, " | +").concat(_stats2.additions, " | -").concat(_stats2.deletions, " | ").concat(_stats2.netChanges >= 0 ? '+' : '').concat(_stats2.netChanges, " |\n");
446
+ if (showContributors) {
447
+ md += "| ".concat(t('table.author'), " | ").concat(t('table.period'), " | ").concat(t('table.commits'), " | ").concat(t('table.proposals'), " | ").concat(t('table.codeFiles'), " | ").concat(t('table.additions'), " | ").concat(t('table.deletions'), " | ").concat(t('table.netChanges'), " |\n");
448
+ md += '|--------|--------|---------|-----------|------------|-----------|-----------|-------------|\n';
449
+ var _iterator7 = _createForOfIteratorHelper(sortedAuthors),
450
+ _step7;
451
+ try {
452
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
453
+ var stats = _step7.value;
454
+ md += "| ".concat(stats.author, " | ").concat(stats.statisticsPeriod || '-', " | ").concat(stats.commits, " | ").concat(stats.openspecProposals.size, " | ").concat(stats.codeFilesChanged, " | +").concat(stats.additions, " | -").concat(stats.deletions, " | ").concat(stats.netChanges >= 0 ? '+' : '').concat(stats.netChanges, " |\n");
455
+ }
456
+ } catch (err) {
457
+ _iterator7.e(err);
458
+ } finally {
459
+ _iterator7.f();
362
460
  }
363
- } catch (err) {
364
- _iterator7.e(err);
365
- } finally {
366
- _iterator7.f();
367
- }
368
- md += t('markdown.proposalDetails');
369
- var _iterator8 = _createForOfIteratorHelper(sortedAuthors),
370
- _step8;
371
- try {
372
- for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
373
- var _stats3 = _step8.value;
374
- if (_stats3.openspecProposals.size > 0) {
375
- md += "### ".concat(_stats3.author, "\n\n");
376
- for (var _i = 0, _Array$from = Array.from(_stats3.openspecProposals); _i < _Array$from.length; _i++) {
377
- var proposal = _Array$from[_i];
378
- md += "- ".concat(proposal, "\n");
461
+ md += t('markdown.proposalDetails');
462
+ var _iterator8 = _createForOfIteratorHelper(sortedAuthors),
463
+ _step8;
464
+ try {
465
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
466
+ var _stats2 = _step8.value;
467
+ if (_stats2.openspecProposals.size > 0) {
468
+ md += "### ".concat(_stats2.author, "\n\n");
469
+ for (var _i = 0, _Array$from = Array.from(_stats2.openspecProposals); _i < _Array$from.length; _i++) {
470
+ var proposal = _Array$from[_i];
471
+ md += "- ".concat(proposal, "\n");
472
+ }
473
+ md += '\n';
379
474
  }
380
- md += '\n';
381
475
  }
476
+ } catch (err) {
477
+ _iterator8.e(err);
478
+ } finally {
479
+ _iterator8.f();
382
480
  }
383
- } catch (err) {
384
- _iterator8.e(err);
385
- } finally {
386
- _iterator8.f();
481
+ } else {
482
+ md += "| ".concat(t('table.contributors'), " | ").concat(t('table.commits'), " | ").concat(t('table.proposals'), " | ").concat(t('table.codeFiles'), " | ").concat(t('table.additions'), " | ").concat(t('table.deletions'), " | ").concat(t('table.netChanges'), " |\n");
483
+ md += '|------------|---------|-----------|------------|-----------|-----------|-------------|\n';
484
+ var totalProposalsSet = new Set();
485
+ sortedAuthors.forEach(function (s) {
486
+ return s.openspecProposals.forEach(function (p) {
487
+ return totalProposalsSet.add(p);
488
+ });
489
+ });
490
+ var totalAuthors = sortedAuthors.length;
491
+ var totalCommits = sortedAuthors.reduce(function (sum, s) {
492
+ return sum + s.commits;
493
+ }, 0);
494
+ var totalFiles = sortedAuthors.reduce(function (sum, s) {
495
+ return sum + s.codeFilesChanged;
496
+ }, 0);
497
+ var totalAdditions = sortedAuthors.reduce(function (sum, s) {
498
+ return sum + s.additions;
499
+ }, 0);
500
+ var totalDeletions = sortedAuthors.reduce(function (sum, s) {
501
+ return sum + s.deletions;
502
+ }, 0);
503
+ var totalNetChanges = sortedAuthors.reduce(function (sum, s) {
504
+ return sum + s.netChanges;
505
+ }, 0);
506
+ md += "| ".concat(totalAuthors, " | ").concat(totalCommits, " | ").concat(totalProposalsSet.size, " | ").concat(totalFiles, " | +").concat(totalAdditions, " | -").concat(totalDeletions, " | ").concat(totalNetChanges >= 0 ? '+' : '').concat(totalNetChanges, " |\n");
507
+ md += "\n*".concat(t('output.contributorHint'), "*\n");
387
508
  }
388
509
  return md;
389
510
  }
@@ -3,6 +3,7 @@ export declare class GitAnalyzer {
3
3
  private git;
4
4
  private config;
5
5
  constructor(repoPath: string, config: Config);
6
+ fetchRemote(): Promise<void>;
6
7
  getCommits(since: Date, until: Date, branches: string[]): Promise<CommitInfo[]>;
7
8
  getCommitBranches(commitHash: string, targetBranches: string[]): Promise<string[]>;
8
9
  analyzeCommit(commit: CommitInfo): Promise<CommitAnalysis | null>;