repo-wrapped 0.0.7 → 0.0.9

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 (172) hide show
  1. package/.github/agents/complete.agent.md +257 -0
  2. package/.github/agents/feature-scaffold.agent.md +248 -0
  3. package/.github/agents/jsdoc.agent.md +243 -0
  4. package/.github/agents/plan.agent.md +202 -0
  5. package/.github/agents/spec-writer.agent.md +169 -0
  6. package/.github/agents/test-writer.agent.md +169 -0
  7. package/.stylelintrc.json +27 -0
  8. package/README.md +94 -94
  9. package/coverage/base.css +224 -0
  10. package/coverage/block-navigation.js +87 -0
  11. package/coverage/favicon.png +0 -0
  12. package/coverage/index.html +446 -0
  13. package/coverage/lcov-report/base.css +224 -0
  14. package/coverage/lcov-report/block-navigation.js +87 -0
  15. package/coverage/lcov-report/favicon.png +0 -0
  16. package/coverage/lcov-report/index.html +446 -0
  17. package/coverage/lcov-report/prettify.css +1 -0
  18. package/coverage/lcov-report/prettify.js +2 -0
  19. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  20. package/coverage/lcov-report/sorter.js +210 -0
  21. package/coverage/lcov.info +7039 -0
  22. package/coverage/prettify.css +1 -0
  23. package/coverage/prettify.js +2 -0
  24. package/coverage/sort-arrow-sprite.png +0 -0
  25. package/coverage/sorter.js +210 -0
  26. package/dist/commands/generate.js +56 -56
  27. package/dist/config/defaults.js +158 -0
  28. package/dist/config/index.js +10 -0
  29. package/dist/features/achievements/data/achievements.json +284 -0
  30. package/dist/features/achievements/engine.js +140 -0
  31. package/dist/features/achievements/evaluators.js +246 -0
  32. package/dist/features/achievements/helpers.js +58 -0
  33. package/dist/features/achievements/index.js +57 -0
  34. package/dist/features/achievements/loader.js +88 -0
  35. package/dist/features/achievements/template.js +155 -0
  36. package/dist/features/achievements/types.js +7 -0
  37. package/dist/features/commit-quality/analyzer.js +378 -0
  38. package/dist/features/commit-quality/analyzer.test.js +484 -0
  39. package/dist/features/commit-quality/index.js +28 -0
  40. package/dist/features/commit-quality/template.js +114 -0
  41. package/dist/features/commit-quality/types.js +2 -0
  42. package/dist/features/comparison/analyzer.js +222 -0
  43. package/dist/features/comparison/index.js +28 -0
  44. package/dist/features/comparison/template.js +119 -0
  45. package/dist/features/comparison/types.js +2 -0
  46. package/dist/features/contribution-graph/index.js +9 -0
  47. package/dist/features/contribution-graph/template.js +89 -0
  48. package/dist/features/events/index.js +31 -0
  49. package/dist/features/events/parser.js +253 -0
  50. package/dist/features/events/template.js +113 -0
  51. package/dist/features/events/types.js +2 -0
  52. package/dist/features/executive-summary/generator.js +275 -0
  53. package/dist/features/executive-summary/index.js +27 -0
  54. package/dist/features/executive-summary/template.js +80 -0
  55. package/dist/features/executive-summary/types.js +2 -0
  56. package/dist/features/gaps/analyzer.js +298 -0
  57. package/dist/features/gaps/analyzer.test.js +517 -0
  58. package/dist/features/gaps/index.js +27 -0
  59. package/dist/features/gaps/template.js +190 -0
  60. package/dist/features/gaps/types.js +2 -0
  61. package/dist/features/impact/analyzer.js +248 -0
  62. package/dist/features/impact/index.js +26 -0
  63. package/dist/features/impact/template.js +118 -0
  64. package/dist/features/impact/types.js +2 -0
  65. package/dist/features/index.js +40 -0
  66. package/dist/features/knowledge/analyzer.js +385 -0
  67. package/dist/features/knowledge/index.js +26 -0
  68. package/dist/features/knowledge/template.js +239 -0
  69. package/dist/features/knowledge/types.js +2 -0
  70. package/dist/features/streaks/calculator.js +184 -0
  71. package/dist/features/streaks/calculator.test.js +366 -0
  72. package/dist/features/streaks/index.js +36 -0
  73. package/dist/features/streaks/template.js +41 -0
  74. package/dist/features/streaks/types.js +9 -0
  75. package/dist/features/team/analyzer.js +316 -0
  76. package/dist/features/team/index.js +30 -0
  77. package/dist/features/team/template.js +146 -0
  78. package/dist/features/team/types.js +2 -0
  79. package/dist/features/time-patterns/analyzer.js +319 -0
  80. package/dist/features/time-patterns/analyzer.test.js +278 -0
  81. package/dist/features/time-patterns/index.js +37 -0
  82. package/dist/features/time-patterns/template.js +109 -0
  83. package/dist/features/time-patterns/types.js +9 -0
  84. package/dist/features/velocity/analyzer.js +257 -0
  85. package/dist/features/velocity/analyzer.test.js +383 -0
  86. package/dist/features/velocity/index.js +27 -0
  87. package/dist/features/velocity/template.js +189 -0
  88. package/dist/features/velocity/types.js +2 -0
  89. package/dist/generators/html/scripts/knowledge.js +17 -0
  90. package/dist/generators/html/styles/base.css +8 -3
  91. package/dist/generators/html/styles/components.css +121 -1
  92. package/dist/generators/html/styles/knowledge.css +21 -0
  93. package/dist/generators/html/styles/leaddev.css +108 -48
  94. package/dist/generators/html/styles/strategic-insights.css +1337 -0
  95. package/dist/generators/html/templates/commitQualitySection.js +28 -2
  96. package/dist/generators/html/templates/executiveSummarySection.js +0 -4
  97. package/dist/generators/html/templates/impactSection.js +8 -6
  98. package/dist/generators/html/templates/knowledgeSection.js +16 -2
  99. package/dist/generators/html/templates/velocitySection.js +2 -2
  100. package/dist/generators/html/types.js +7 -0
  101. package/dist/generators/html/utils/analysisRunner.js +93 -0
  102. package/dist/generators/html/utils/cardBuilder.js +47 -0
  103. package/dist/generators/html/utils/contextBuilder.js +54 -0
  104. package/dist/generators/html/utils/htmlDocumentBuilder.js +396 -0
  105. package/dist/generators/html/utils/kpiBuilder.js +76 -0
  106. package/dist/generators/html/utils/sectionWrapper.js +71 -0
  107. package/dist/generators/html/utils/styleLoader.js +2 -2
  108. package/dist/html/analysisRunner.js +93 -0
  109. package/dist/html/htmlDocumentBuilder.js +396 -0
  110. package/dist/html/index.js +29 -0
  111. package/dist/html/shared/colorUtils.js +61 -0
  112. package/dist/html/shared/commitMapBuilder.js +23 -0
  113. package/dist/html/shared/components/cardBuilder.js +47 -0
  114. package/dist/html/shared/components/index.js +18 -0
  115. package/dist/html/shared/components/kpiBuilder.js +76 -0
  116. package/dist/html/shared/components/sectionWrapper.js +71 -0
  117. package/dist/html/shared/contextBuilder.js +54 -0
  118. package/dist/html/shared/dateRangeCalculator.js +56 -0
  119. package/dist/html/shared/developerStatsCalculator.js +28 -0
  120. package/dist/html/shared/index.js +39 -0
  121. package/dist/html/shared/scriptLoader.js +15 -0
  122. package/dist/html/shared/scripts/export.js +125 -0
  123. package/dist/html/shared/scripts/knowledge.js +137 -0
  124. package/dist/html/shared/scripts/modal.js +68 -0
  125. package/dist/html/shared/scripts/navigation.js +156 -0
  126. package/dist/html/shared/scripts/tabs.js +18 -0
  127. package/dist/html/shared/scripts/tooltip.js +21 -0
  128. package/dist/html/shared/styleLoader.js +18 -0
  129. package/dist/html/shared/styles/achievements.css +387 -0
  130. package/dist/html/shared/styles/base.css +822 -0
  131. package/dist/html/shared/styles/components.css +1511 -0
  132. package/dist/html/shared/styles/knowledge.css +242 -0
  133. package/dist/html/shared/styles/strategic-insights.css +1337 -0
  134. package/dist/html/shared/weekGrouper.js +27 -0
  135. package/dist/html/types.js +7 -0
  136. package/dist/index.js +39 -39
  137. package/dist/test/helpers/commitFactory.js +166 -0
  138. package/dist/test/helpers/dateUtils.js +101 -0
  139. package/dist/test/helpers/index.js +29 -0
  140. package/dist/test/setup.js +17 -0
  141. package/dist/test/smoke.test.js +94 -0
  142. package/dist/types/achievements.js +7 -0
  143. package/dist/types/analysis.js +7 -0
  144. package/dist/types/core.js +7 -0
  145. package/dist/types/index.js +38 -0
  146. package/dist/types/options.js +7 -0
  147. package/dist/types/shared.js +7 -0
  148. package/dist/types/strategic.js +7 -0
  149. package/dist/types/summary.js +7 -0
  150. package/dist/utils/achievementDefinitions.js +22 -22
  151. package/dist/utils/analyzerContextBuilder.js +124 -0
  152. package/dist/utils/commitQualityAnalyzer.js +13 -2
  153. package/dist/utils/emptyResults.js +95 -0
  154. package/dist/utils/fileHotspotAnalyzer.js +4 -12
  155. package/dist/utils/gapAnalyzer.js +26 -28
  156. package/dist/utils/gitParser.test.js +363 -0
  157. package/dist/utils/htmlGenerator.js +62 -466
  158. package/dist/utils/impactAnalyzer.js +20 -19
  159. package/dist/utils/knowledgeDistributionAnalyzer.js +32 -27
  160. package/dist/utils/matrixGenerator.js +13 -13
  161. package/dist/utils/rangeComparisonAnalyzer.js +2 -2
  162. package/dist/utils/streakCalculator.js +77 -27
  163. package/dist/utils/teamAnalyzer.js +20 -1
  164. package/dist/utils/timePatternAnalyzer.js +18 -3
  165. package/dist/utils/velocityAnalyzer.js +23 -18
  166. package/dist/utils/wrappedGenerator.js +8 -8
  167. package/package.json +74 -64
  168. package/vitest.config.ts +46 -0
  169. package/SPECS.md +0 -490
  170. package/dist/cli.js +0 -24
  171. package/dist/commands/index.js +0 -24
  172. package/test-team.txt +0 -2
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.groupDaysIntoWeeks = groupDaysIntoWeeks;
4
+ exports.getDayLabels = getDayLabels;
5
+ const date_fns_1 = require("date-fns");
6
+ /**
7
+ * Groups days into weeks for the contribution graph
8
+ */
9
+ function groupDaysIntoWeeks(startDate, endDate) {
10
+ const days = (0, date_fns_1.eachDayOfInterval)({ start: startDate, end: endDate });
11
+ const weeks = [];
12
+ let currentWeek = [];
13
+ days.forEach(day => {
14
+ currentWeek.push(day);
15
+ if (currentWeek.length === 7) {
16
+ weeks.push(currentWeek);
17
+ currentWeek = [];
18
+ }
19
+ });
20
+ return weeks;
21
+ }
22
+ /**
23
+ * Gets day labels for the contribution graph
24
+ */
25
+ function getDayLabels() {
26
+ return ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
27
+ }
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * Types for HTML generation pipeline.
4
+ *
5
+ * @module html/types
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
package/dist/index.js CHANGED
@@ -18,45 +18,45 @@ program
18
18
  .name('repo-wrapped')
19
19
  .description('Generate Git repository analytics and visualizations')
20
20
  .version('1.0.0')
21
- .addHelpText('after', `
22
- Commands:
23
- generate [path] Generate commit visualization (default command)
24
- wrapped [year] [path] Generate Year in Code summary
25
-
26
- Generate Options:
27
- -y, --year <year> Year to analyze (default: current year)
28
- -m, --months <months> Number of months to show (default: 12)
29
- -a, --all Analyze entire repository lifetime
30
- --html Generate HTML report and open in browser
31
- --body-check Include commit body in quality scoring
32
- --deep-analysis Enable file-level knowledge distribution analysis
33
-
34
- Strategic Insights:
35
- --velocity Enable velocity timeline analysis
36
- --velocity-window <w> Rolling average window in weeks (default: 4)
37
- --gap-analysis Enable gap detection and blocker analysis
38
- --gap-threshold <days> Minimum gap days to report (default: 3)
39
- --compare <r1> <r2> Compare two date ranges (format: YYYY-MM-DD..YYYY-MM-DD)
40
- --compare-labels <l> Labels for comparison (format: "Label1,Label2")
41
- --author <name> Filter to specific author (partial match)
42
- --authors <names> Filter to multiple authors (comma-separated)
43
- --team <file> Path to team members file (one name per line)
44
- --exclude-author <name> Exclude specific author (e.g., bots)
45
- --executive-summary Generate executive summary with KPIs
46
- --summary-only Output only the executive summary (terminal or HTML)
47
- --events <file> Path to events annotation JSON file
48
-
49
- Wrapped Options:
50
- --html Generate HTML slideshow and open in browser
51
- --compare Compare with previous year
52
-
53
- Examples:
54
- repo-wrapped generate . --html
55
- repo-wrapped generate . --all --html --deep-analysis
56
- repo-wrapped generate . --velocity --gap-analysis --executive-summary
57
- repo-wrapped generate . --compare "2025-01-01..2025-06-30" "2025-07-01..2025-12-31"
58
- repo-wrapped generate . --author "John" --html
59
- repo-wrapped wrapped 2025 . --html
21
+ .addHelpText('after', `
22
+ Commands:
23
+ generate [path] Generate commit visualization (default command)
24
+ wrapped [year] [path] Generate Year in Code summary
25
+
26
+ Generate Options:
27
+ -y, --year <year> Year to analyze (default: current year)
28
+ -m, --months <months> Number of months to show (default: 12)
29
+ -a, --all Analyze entire repository lifetime
30
+ --html Generate HTML report and open in browser
31
+ --body-check Include commit body in quality scoring
32
+ --deep-analysis Enable file-level knowledge distribution analysis
33
+
34
+ Strategic Insights:
35
+ --velocity Enable velocity timeline analysis
36
+ --velocity-window <w> Rolling average window in weeks (default: 4)
37
+ --gap-analysis Enable gap detection and blocker analysis
38
+ --gap-threshold <days> Minimum gap days to report (default: 3)
39
+ --compare <r1> <r2> Compare two date ranges (format: YYYY-MM-DD..YYYY-MM-DD)
40
+ --compare-labels <l> Labels for comparison (format: "Label1,Label2")
41
+ --author <name> Filter to specific author (partial match)
42
+ --authors <names> Filter to multiple authors (comma-separated)
43
+ --team <file> Path to team members file (one name per line)
44
+ --exclude-author <name> Exclude specific author (e.g., bots)
45
+ --executive-summary Generate executive summary with KPIs
46
+ --summary-only Output only the executive summary (terminal or HTML)
47
+ --events <file> Path to events annotation JSON file
48
+
49
+ Wrapped Options:
50
+ --html Generate HTML slideshow and open in browser
51
+ --compare Compare with previous year
52
+
53
+ Examples:
54
+ repo-wrapped generate . --html
55
+ repo-wrapped generate . --all --html --deep-analysis
56
+ repo-wrapped generate . --velocity --gap-analysis --executive-summary
57
+ repo-wrapped generate . --compare "2025-01-01..2025-06-30" "2025-07-01..2025-12-31"
58
+ repo-wrapped generate . --author "John" --html
59
+ repo-wrapped wrapped 2025 . --html
60
60
  `);
61
61
  program
62
62
  .command('generate')
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ /**
3
+ * Test Commit Factory
4
+ *
5
+ * Provides utilities for creating test commit data with sensible defaults.
6
+ * Use these helpers to create consistent test data across all test files.
7
+ *
8
+ * @module test/helpers/commitFactory
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.createCommit = createCommit;
12
+ exports.createCommitSequence = createCommitSequence;
13
+ exports.createWorkWeekCommits = createWorkWeekCommits;
14
+ exports.createCommitsByHour = createCommitsByHour;
15
+ exports.createConventionalCommits = createConventionalCommits;
16
+ exports.resetHashCounter = resetHashCounter;
17
+ /**
18
+ * Creates a single CommitData object with default values.
19
+ * Override any property by passing it in the overrides object.
20
+ *
21
+ * @param overrides - Partial commit data to override defaults
22
+ * @returns Complete CommitData object
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * // Basic usage
27
+ * const commit = createCommit();
28
+ *
29
+ * // With overrides
30
+ * const feat = createCommit({ message: 'feat: add login' });
31
+ *
32
+ * // With specific date
33
+ * const oldCommit = createCommit({ date: '2025-01-01T10:00:00Z' });
34
+ * ```
35
+ */
36
+ function createCommit(overrides = {}) {
37
+ return {
38
+ hash: generateHash(),
39
+ author: 'Test Author',
40
+ date: '2025-06-15T10:00:00Z',
41
+ message: 'test: example commit message',
42
+ ...overrides,
43
+ };
44
+ }
45
+ /**
46
+ * Creates an array of commits on consecutive days.
47
+ *
48
+ * @param count - Number of commits to create
49
+ * @param options - Configuration options
50
+ * @returns Array of CommitData objects
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * // 5 commits on consecutive days
55
+ * const commits = createCommitSequence(5);
56
+ *
57
+ * // Starting from a specific date
58
+ * const commits = createCommitSequence(3, {
59
+ * startDate: new Date('2025-01-01')
60
+ * });
61
+ *
62
+ * // With gaps between commits
63
+ * const commits = createCommitSequence(3, { intervalDays: 7 });
64
+ * ```
65
+ */
66
+ function createCommitSequence(count, options = {}) {
67
+ const { startDate = new Date('2025-06-01'), intervalDays = 1, author = 'Test Author', messagePrefix = 'test', } = options;
68
+ return Array.from({ length: count }, (_, i) => {
69
+ const date = new Date(startDate);
70
+ date.setDate(date.getDate() + i * intervalDays);
71
+ return createCommit({
72
+ hash: `hash${String(i).padStart(3, '0')}`,
73
+ date: date.toISOString(),
74
+ author,
75
+ message: `${messagePrefix}: commit ${i + 1}`,
76
+ });
77
+ });
78
+ }
79
+ /**
80
+ * Creates commits for a full work week (Monday-Friday).
81
+ *
82
+ * @param weekStartMonday - The Monday to start the week
83
+ * @param commitsPerDay - Number of commits per day (default: 1)
84
+ * @returns Array of commits for Mon-Fri
85
+ */
86
+ function createWorkWeekCommits(weekStartMonday, commitsPerDay = 1) {
87
+ const commits = [];
88
+ for (let day = 0; day < 5; day++) {
89
+ for (let c = 0; c < commitsPerDay; c++) {
90
+ const date = new Date(weekStartMonday);
91
+ date.setDate(date.getDate() + day);
92
+ date.setHours(9 + c, 0, 0, 0);
93
+ commits.push(createCommit({
94
+ hash: `week${day}commit${c}`,
95
+ date: date.toISOString(),
96
+ message: `feat: day ${day + 1} commit ${c + 1}`,
97
+ }));
98
+ }
99
+ }
100
+ return commits;
101
+ }
102
+ /**
103
+ * Creates commits with specific hour distribution for time pattern testing.
104
+ *
105
+ * @param hourCommitMap - Map of hour (0-23) to number of commits
106
+ * @param baseDate - Base date for all commits
107
+ * @returns Array of commits at specified hours
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * // 3 commits at 9am, 5 commits at 2pm
112
+ * const commits = createCommitsByHour({ 9: 3, 14: 5 });
113
+ * ```
114
+ */
115
+ function createCommitsByHour(hourCommitMap, baseDate = new Date('2025-06-15')) {
116
+ const commits = [];
117
+ for (const [hour, count] of Object.entries(hourCommitMap)) {
118
+ for (let i = 0; i < count; i++) {
119
+ const date = new Date(baseDate);
120
+ date.setHours(Number(hour), i * 10, 0, 0);
121
+ commits.push(createCommit({
122
+ hash: `hour${hour}commit${i}`,
123
+ date: date.toISOString(),
124
+ }));
125
+ }
126
+ }
127
+ return commits;
128
+ }
129
+ /**
130
+ * Creates commits with various conventional commit types for quality testing.
131
+ *
132
+ * @param typeCounts - Map of commit type to count
133
+ * @returns Array of commits with specified types
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * const commits = createConventionalCommits({
138
+ * feat: 5,
139
+ * fix: 3,
140
+ * docs: 1,
141
+ * });
142
+ * ```
143
+ */
144
+ function createConventionalCommits(typeCounts) {
145
+ const commits = [];
146
+ for (const [type, count] of Object.entries(typeCounts)) {
147
+ for (let i = 0; i < count; i++) {
148
+ commits.push(createCommit({
149
+ hash: `${type}${i}`,
150
+ message: `${type}: example ${type} commit ${i + 1}`,
151
+ }));
152
+ }
153
+ }
154
+ return commits;
155
+ }
156
+ // Internal helper
157
+ let hashCounter = 0;
158
+ function generateHash() {
159
+ return `abc${String(++hashCounter).padStart(10, '0')}`;
160
+ }
161
+ /**
162
+ * Resets the hash counter. Call this in beforeEach for deterministic hashes.
163
+ */
164
+ function resetHashCounter() {
165
+ hashCounter = 0;
166
+ }
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ /**
3
+ * Date Testing Utilities
4
+ *
5
+ * Helpers for working with dates in tests.
6
+ *
7
+ * @module test/helpers/dateUtils
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.TEST_TODAY = void 0;
11
+ exports.getMonday = getMonday;
12
+ exports.daysAgo = daysAgo;
13
+ exports.daysFromNow = daysFromNow;
14
+ exports.isWeekend = isWeekend;
15
+ exports.getBusinessDaysBetween = getBusinessDaysBetween;
16
+ exports.mockDateNow = mockDateNow;
17
+ exports.toISOString = toISOString;
18
+ exports.parseDate = parseDate;
19
+ /**
20
+ * Gets the Monday of a given week.
21
+ *
22
+ * @param date - Any date in the target week
23
+ * @returns The Monday of that week
24
+ */
25
+ function getMonday(date) {
26
+ const d = new Date(date);
27
+ const day = d.getDay();
28
+ const diff = d.getDate() - day + (day === 0 ? -6 : 1);
29
+ d.setDate(diff);
30
+ d.setHours(0, 0, 0, 0);
31
+ return d;
32
+ }
33
+ /**
34
+ * Creates a date N days ago from a base date.
35
+ *
36
+ * @param days - Number of days ago
37
+ * @param from - Base date (default: 2025-06-15)
38
+ * @returns Date N days before the base
39
+ */
40
+ function daysAgo(days, from = new Date('2025-06-15')) {
41
+ const date = new Date(from);
42
+ date.setDate(date.getDate() - days);
43
+ return date;
44
+ }
45
+ /**
46
+ * Creates a date N days from now relative to base date.
47
+ */
48
+ function daysFromNow(days, from = new Date('2025-06-15')) {
49
+ const date = new Date(from);
50
+ date.setDate(date.getDate() + days);
51
+ return date;
52
+ }
53
+ /**
54
+ * Checks if a date is a weekend (Saturday or Sunday).
55
+ */
56
+ function isWeekend(date) {
57
+ const day = date.getDay();
58
+ return day === 0 || day === 6;
59
+ }
60
+ /**
61
+ * Gets business days between two dates (Mon-Fri).
62
+ */
63
+ function getBusinessDaysBetween(start, end) {
64
+ let count = 0;
65
+ const current = new Date(start);
66
+ while (current <= end) {
67
+ if (!isWeekend(current)) {
68
+ count++;
69
+ }
70
+ current.setDate(current.getDate() + 1);
71
+ }
72
+ return count;
73
+ }
74
+ /**
75
+ * Fixed "today" for deterministic tests.
76
+ * Use this instead of new Date() in tests.
77
+ */
78
+ exports.TEST_TODAY = new Date('2025-06-15T12:00:00Z');
79
+ /**
80
+ * Mock Date.now() to return a fixed timestamp.
81
+ * Call in beforeEach and restore in afterEach.
82
+ */
83
+ function mockDateNow(fixedDate = exports.TEST_TODAY) {
84
+ const originalNow = Date.now;
85
+ Date.now = () => fixedDate.getTime();
86
+ return () => {
87
+ Date.now = originalNow;
88
+ };
89
+ }
90
+ /**
91
+ * Converts a Date to ISO string for CommitData compatibility.
92
+ */
93
+ function toISOString(date) {
94
+ return date.toISOString();
95
+ }
96
+ /**
97
+ * Parses an ISO date string to Date object.
98
+ */
99
+ function parseDate(isoString) {
100
+ return new Date(isoString);
101
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ /**
3
+ * Test Helpers
4
+ *
5
+ * Central export for all test utilities.
6
+ *
7
+ * @module test/helpers
8
+ * @example
9
+ * ```typescript
10
+ * import { createCommit, createCommitSequence, daysAgo } from '../test/helpers';
11
+ * ```
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
25
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
26
+ };
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ __exportStar(require("./commitFactory"), exports);
29
+ __exportStar(require("./dateUtils"), exports);
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ /**
3
+ * Global Test Setup
4
+ *
5
+ * Runs before all tests. Configure global mocks and settings here.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ const vitest_1 = require("vitest");
9
+ const commitFactory_1 = require("./helpers/commitFactory");
10
+ // Reset hash counter before each test for deterministic results
11
+ (0, vitest_1.beforeEach)(() => {
12
+ (0, commitFactory_1.resetHashCounter)();
13
+ });
14
+ // Global cleanup if needed
15
+ (0, vitest_1.afterEach)(() => {
16
+ // Add any global cleanup here
17
+ });
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ /**
3
+ * Smoke Test for Test Infrastructure
4
+ *
5
+ * Verifies that the test setup and helpers work correctly.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ const vitest_1 = require("vitest");
9
+ const helpers_1 = require("./helpers");
10
+ const dateUtils_1 = require("./helpers/dateUtils");
11
+ (0, vitest_1.describe)('Test Infrastructure', () => {
12
+ (0, vitest_1.describe)('commitFactory', () => {
13
+ (0, vitest_1.it)('creates a valid commit with defaults', () => {
14
+ const commit = (0, helpers_1.createCommit)();
15
+ (0, vitest_1.expect)(commit.hash).toBeDefined();
16
+ (0, vitest_1.expect)(commit.author).toBe('Test Author');
17
+ (0, vitest_1.expect)(commit.date).toBeDefined();
18
+ (0, vitest_1.expect)(commit.message).toBe('test: example commit message');
19
+ });
20
+ (0, vitest_1.it)('creates a commit with overrides', () => {
21
+ const commit = (0, helpers_1.createCommit)({
22
+ author: 'Custom Author',
23
+ message: 'feat: custom feature',
24
+ });
25
+ (0, vitest_1.expect)(commit.author).toBe('Custom Author');
26
+ (0, vitest_1.expect)(commit.message).toBe('feat: custom feature');
27
+ });
28
+ (0, vitest_1.it)('creates a sequence of commits', () => {
29
+ const commits = (0, helpers_1.createCommitSequence)(5);
30
+ (0, vitest_1.expect)(commits).toHaveLength(5);
31
+ commits.forEach((commit, i) => {
32
+ (0, vitest_1.expect)(commit.hash).toBe(`hash${String(i).padStart(3, '0')}`);
33
+ });
34
+ });
35
+ (0, vitest_1.it)('creates commits on consecutive days', () => {
36
+ const commits = (0, helpers_1.createCommitSequence)(3, {
37
+ startDate: new Date('2025-06-01'),
38
+ });
39
+ (0, vitest_1.expect)(new Date(commits[0].date).getDate()).toBe(1);
40
+ (0, vitest_1.expect)(new Date(commits[1].date).getDate()).toBe(2);
41
+ (0, vitest_1.expect)(new Date(commits[2].date).getDate()).toBe(3);
42
+ });
43
+ (0, vitest_1.it)('creates work week commits', () => {
44
+ const monday = new Date('2025-06-02'); // A Monday
45
+ const commits = (0, helpers_1.createWorkWeekCommits)(monday);
46
+ (0, vitest_1.expect)(commits).toHaveLength(5);
47
+ });
48
+ (0, vitest_1.it)('creates commits by hour', () => {
49
+ const commits = (0, helpers_1.createCommitsByHour)({ 9: 2, 14: 3 });
50
+ (0, vitest_1.expect)(commits).toHaveLength(5);
51
+ });
52
+ (0, vitest_1.it)('creates conventional commits', () => {
53
+ const commits = (0, helpers_1.createConventionalCommits)({
54
+ feat: 2,
55
+ fix: 1,
56
+ });
57
+ (0, vitest_1.expect)(commits).toHaveLength(3);
58
+ (0, vitest_1.expect)(commits.filter((c) => c.message.startsWith('feat:'))).toHaveLength(2);
59
+ (0, vitest_1.expect)(commits.filter((c) => c.message.startsWith('fix:'))).toHaveLength(1);
60
+ });
61
+ });
62
+ (0, vitest_1.describe)('dateUtils', () => {
63
+ (0, vitest_1.it)('TEST_TODAY is a fixed date', () => {
64
+ (0, vitest_1.expect)(dateUtils_1.TEST_TODAY).toEqual(new Date('2025-06-15T12:00:00Z'));
65
+ });
66
+ (0, vitest_1.it)('getMonday returns the Monday of a week', () => {
67
+ const wednesday = new Date('2025-06-11'); // Wednesday
68
+ const monday = (0, dateUtils_1.getMonday)(wednesday);
69
+ (0, vitest_1.expect)(monday.getDay()).toBe(1); // Monday
70
+ (0, vitest_1.expect)(monday.getDate()).toBe(9); // June 9, 2025
71
+ });
72
+ (0, vitest_1.it)('daysAgo calculates correct date', () => {
73
+ const result = (0, dateUtils_1.daysAgo)(5, new Date('2025-06-15'));
74
+ (0, vitest_1.expect)(result.getDate()).toBe(10);
75
+ });
76
+ (0, vitest_1.it)('daysFromNow calculates correct date', () => {
77
+ const result = (0, dateUtils_1.daysFromNow)(5, new Date('2025-06-15'));
78
+ (0, vitest_1.expect)(result.getDate()).toBe(20);
79
+ });
80
+ (0, vitest_1.it)('isWeekend detects weekends correctly', () => {
81
+ const saturday = new Date('2025-06-14');
82
+ const sunday = new Date('2025-06-15');
83
+ const monday = new Date('2025-06-16');
84
+ (0, vitest_1.expect)((0, dateUtils_1.isWeekend)(saturday)).toBe(true);
85
+ (0, vitest_1.expect)((0, dateUtils_1.isWeekend)(sunday)).toBe(true);
86
+ (0, vitest_1.expect)((0, dateUtils_1.isWeekend)(monday)).toBe(false);
87
+ });
88
+ (0, vitest_1.it)('getBusinessDaysBetween counts correctly', () => {
89
+ const start = new Date('2025-06-09'); // Monday
90
+ const end = new Date('2025-06-13'); // Friday
91
+ (0, vitest_1.expect)((0, dateUtils_1.getBusinessDaysBetween)(start, end)).toBe(5);
92
+ });
93
+ });
94
+ });
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * Achievement system types.
4
+ *
5
+ * @module types/achievements
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * Analysis result types for file hotspots and code ownership.
4
+ *
5
+ * @module types/analysis
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * Core data structures used throughout the application.
4
+ *
5
+ * @module types/core
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,2 +1,40 @@
1
1
  "use strict";
2
+ /**
3
+ * Type definitions for repo-wrapped.
4
+ *
5
+ * This module re-exports all types for backward compatibility.
6
+ * For new code, consider importing from specific domain modules:
7
+ *
8
+ * - `./shared` - Shared type aliases (RiskLevel, TrendDirection, etc.)
9
+ * - `./core` - Core data structures (CommitData, StreakData, etc.)
10
+ * - `./analysis` - File analysis types (FileHotspot, ImpactAnalysis, etc.)
11
+ * - `../features/achievements` - Achievement system types
12
+ * - `./strategic` - Strategic insights (Velocity, Gaps, Team, etc.)
13
+ * - `./summary` - Year-in-code summary types
14
+ * - `./options` - CLI and generation options
15
+ *
16
+ * @module types
17
+ */
18
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ var desc = Object.getOwnPropertyDescriptor(m, k);
21
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
22
+ desc = { enumerable: true, get: function() { return m[k]; } };
23
+ }
24
+ Object.defineProperty(o, k2, desc);
25
+ }) : (function(o, m, k, k2) {
26
+ if (k2 === undefined) k2 = k;
27
+ o[k2] = m[k];
28
+ }));
29
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
30
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
31
+ };
2
32
  Object.defineProperty(exports, "__esModule", { value: true });
33
+ // Re-export all types for backward compatibility
34
+ __exportStar(require("./shared"), exports);
35
+ __exportStar(require("./core"), exports);
36
+ __exportStar(require("./analysis"), exports);
37
+ __exportStar(require("../features/achievements/types"), exports);
38
+ __exportStar(require("./strategic"), exports);
39
+ __exportStar(require("./summary"), exports);
40
+ __exportStar(require("./options"), exports);
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * CLI and generation options types.
4
+ *
5
+ * @module types/options
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * Shared type aliases used across all modules.
4
+ *
5
+ * @module types/shared
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * Strategic insights types for velocity, gaps, team analysis, etc.
4
+ *
5
+ * @module types/strategic
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * Year-in-code summary and comparison types.
4
+ *
5
+ * @module types/summary
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });