github-issue-tower-defence-management 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. package/.env.example +6 -0
  2. package/.eslintrc.cjs +55 -0
  3. package/.github/CODEOWNERS +2 -0
  4. package/.github/workflows/assign-all-cards-to-owner.yml +14 -0
  5. package/.github/workflows/commit-lint.yml +54 -0
  6. package/.github/workflows/configs/commitlint.config.js +27 -0
  7. package/.github/workflows/create-pr.yml +64 -0
  8. package/.github/workflows/format.yml +25 -0
  9. package/.github/workflows/publish.yml +47 -0
  10. package/.github/workflows/test.yml +45 -0
  11. package/.github/workflows/umino-project.yml +181 -0
  12. package/.prettierignore +22 -0
  13. package/.prettierrc +5 -0
  14. package/CHANGELOG.md +49 -0
  15. package/CONTRIBUTING.md +107 -0
  16. package/README.md +108 -0
  17. package/bin/adapter/entry-points/cli/index.js +26 -0
  18. package/bin/adapter/entry-points/cli/index.js.map +1 -0
  19. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +142 -0
  20. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -0
  21. package/bin/adapter/repositories/AxiosSlackRepository.js +124 -0
  22. package/bin/adapter/repositories/AxiosSlackRepository.js.map +1 -0
  23. package/bin/adapter/repositories/BaseGitHubRepository.js +136 -0
  24. package/bin/adapter/repositories/BaseGitHubRepository.js.map +1 -0
  25. package/bin/adapter/repositories/GoogleSpreadsheetRepository.js +123 -0
  26. package/bin/adapter/repositories/GoogleSpreadsheetRepository.js.map +1 -0
  27. package/bin/adapter/repositories/GraphqlProjectRepository.js +167 -0
  28. package/bin/adapter/repositories/GraphqlProjectRepository.js.map +1 -0
  29. package/bin/adapter/repositories/LocalStorageCacheRepository.js +46 -0
  30. package/bin/adapter/repositories/LocalStorageCacheRepository.js.map +1 -0
  31. package/bin/adapter/repositories/LocalStorageRepository.js +30 -0
  32. package/bin/adapter/repositories/LocalStorageRepository.js.map +1 -0
  33. package/bin/adapter/repositories/SystemDateRepository.js +23 -0
  34. package/bin/adapter/repositories/SystemDateRepository.js.map +1 -0
  35. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js +148 -0
  36. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js.map +1 -0
  37. package/bin/adapter/repositories/issue/ApiV3IssueRepository.js +48 -0
  38. package/bin/adapter/repositories/issue/ApiV3IssueRepository.js.map +1 -0
  39. package/bin/adapter/repositories/issue/CheerioIssueRepository.js +120 -0
  40. package/bin/adapter/repositories/issue/CheerioIssueRepository.js.map +1 -0
  41. package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js +485 -0
  42. package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js.map +1 -0
  43. package/bin/adapter/repositories/issue/InternalGraphqlIssueRepository.js +114 -0
  44. package/bin/adapter/repositories/issue/InternalGraphqlIssueRepository.js.map +1 -0
  45. package/bin/adapter/repositories/issue/RestIssueRepository.js +79 -0
  46. package/bin/adapter/repositories/issue/RestIssueRepository.js.map +1 -0
  47. package/bin/adapter/repositories/issue/issueTimelineUtils.js +38 -0
  48. package/bin/adapter/repositories/issue/issueTimelineUtils.js.map +1 -0
  49. package/bin/adapter/repositories/utils.js +45 -0
  50. package/bin/adapter/repositories/utils.js.map +1 -0
  51. package/bin/domain/entities/Issue.js +3 -0
  52. package/bin/domain/entities/Issue.js.map +1 -0
  53. package/bin/domain/entities/Member.js +3 -0
  54. package/bin/domain/entities/Member.js.map +1 -0
  55. package/bin/domain/entities/Project.js +3 -0
  56. package/bin/domain/entities/Project.js.map +1 -0
  57. package/bin/domain/entities/ProjectField.js +3 -0
  58. package/bin/domain/entities/ProjectField.js.map +1 -0
  59. package/bin/domain/entities/ProjectFieldSingleSelect.js +3 -0
  60. package/bin/domain/entities/ProjectFieldSingleSelect.js.map +1 -0
  61. package/bin/domain/entities/ProjectFieldSingleSelectOption.js +3 -0
  62. package/bin/domain/entities/ProjectFieldSingleSelectOption.js.map +1 -0
  63. package/bin/domain/entities/WorkingTime.js +3 -0
  64. package/bin/domain/entities/WorkingTime.js.map +1 -0
  65. package/bin/domain/usecases/ActionAnnouncementUseCase.js +46 -0
  66. package/bin/domain/usecases/ActionAnnouncementUseCase.js.map +1 -0
  67. package/bin/domain/usecases/AnalyzeProblemByIssueUseCase.js +116 -0
  68. package/bin/domain/usecases/AnalyzeProblemByIssueUseCase.js.map +1 -0
  69. package/bin/domain/usecases/ClearNextActionHourUseCase.js +38 -0
  70. package/bin/domain/usecases/ClearNextActionHourUseCase.js.map +1 -0
  71. package/bin/domain/usecases/GenerateWorkingTimeReportUseCase.js +180 -0
  72. package/bin/domain/usecases/GenerateWorkingTimeReportUseCase.js.map +1 -0
  73. package/bin/domain/usecases/HandleScheduledEventUseCase.js +122 -0
  74. package/bin/domain/usecases/HandleScheduledEventUseCase.js.map +1 -0
  75. package/bin/domain/usecases/SetWorkflowManagementIssueToStoryUseCase.js +35 -0
  76. package/bin/domain/usecases/SetWorkflowManagementIssueToStoryUseCase.js.map +1 -0
  77. package/bin/domain/usecases/adapter-interfaces/DateRepository.js +3 -0
  78. package/bin/domain/usecases/adapter-interfaces/DateRepository.js.map +1 -0
  79. package/bin/domain/usecases/adapter-interfaces/IssueRepository.js +3 -0
  80. package/bin/domain/usecases/adapter-interfaces/IssueRepository.js.map +1 -0
  81. package/bin/domain/usecases/adapter-interfaces/ProjectRepository.js +3 -0
  82. package/bin/domain/usecases/adapter-interfaces/ProjectRepository.js.map +1 -0
  83. package/bin/domain/usecases/adapter-interfaces/SlackRepository.js +3 -0
  84. package/bin/domain/usecases/adapter-interfaces/SlackRepository.js.map +1 -0
  85. package/bin/domain/usecases/adapter-interfaces/SpreadsheetRepository.js +3 -0
  86. package/bin/domain/usecases/adapter-interfaces/SpreadsheetRepository.js.map +1 -0
  87. package/bin/index.js +13 -0
  88. package/bin/index.js.map +1 -0
  89. package/commitlint.config.js +6 -0
  90. package/jest.config.js +19 -0
  91. package/package.json +80 -0
  92. package/renovate.json +37 -0
  93. package/src/adapter/entry-points/cli/index.test.ts +20 -0
  94. package/src/adapter/entry-points/cli/index.ts +36 -0
  95. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +95 -0
  96. package/src/adapter/repositories/AxiosSlackRepository.test.ts +119 -0
  97. package/src/adapter/repositories/AxiosSlackRepository.ts +184 -0
  98. package/src/adapter/repositories/BaseGitHubRepository.test.ts +95 -0
  99. package/src/adapter/repositories/BaseGitHubRepository.ts +172 -0
  100. package/src/adapter/repositories/GoogleSpreadsheetRepository.test.ts +124 -0
  101. package/src/adapter/repositories/GoogleSpreadsheetRepository.ts +151 -0
  102. package/src/adapter/repositories/GraphqlProjectRepository.test.ts +46 -0
  103. package/src/adapter/repositories/GraphqlProjectRepository.ts +236 -0
  104. package/src/adapter/repositories/LocalStorageCacheRepository.test.ts +146 -0
  105. package/src/adapter/repositories/LocalStorageCacheRepository.ts +53 -0
  106. package/src/adapter/repositories/LocalStorageRepository.integration.test.ts +142 -0
  107. package/src/adapter/repositories/LocalStorageRepository.test.ts +161 -0
  108. package/src/adapter/repositories/LocalStorageRepository.ts +21 -0
  109. package/src/adapter/repositories/SystemDateRepository.ts +20 -0
  110. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.test.ts +158 -0
  111. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.ts +274 -0
  112. package/src/adapter/repositories/issue/ApiV3IssueRepository.test.ts +26 -0
  113. package/src/adapter/repositories/issue/ApiV3IssueRepository.ts +59 -0
  114. package/src/adapter/repositories/issue/CheerioIssueRepository.test.ts +6610 -0
  115. package/src/adapter/repositories/issue/CheerioIssueRepository.ts +127 -0
  116. package/src/adapter/repositories/issue/GraphqlProjectItemRepository.test.ts +49 -0
  117. package/src/adapter/repositories/issue/GraphqlProjectItemRepository.ts +745 -0
  118. package/src/adapter/repositories/issue/InternalGraphqlIssueRepository.test.ts +71 -0
  119. package/src/adapter/repositories/issue/InternalGraphqlIssueRepository.ts +263 -0
  120. package/src/adapter/repositories/issue/RestIssueRepository.test.ts +29 -0
  121. package/src/adapter/repositories/issue/RestIssueRepository.ts +105 -0
  122. package/src/adapter/repositories/issue/issueTimelineUtils.test.ts +79 -0
  123. package/src/adapter/repositories/issue/issueTimelineUtils.ts +52 -0
  124. package/src/adapter/repositories/utils.test.ts +40 -0
  125. package/src/adapter/repositories/utils.ts +50 -0
  126. package/src/domain/entities/Issue.ts +23 -0
  127. package/src/domain/entities/Member.ts +3 -0
  128. package/src/domain/entities/Project.ts +29 -0
  129. package/src/domain/entities/ProjectField.ts +3 -0
  130. package/src/domain/entities/ProjectFieldSingleSelect.ts +8 -0
  131. package/src/domain/entities/ProjectFieldSingleSelectOption.ts +8 -0
  132. package/src/domain/entities/WorkingTime.ts +8 -0
  133. package/src/domain/usecases/ActionAnnouncementUseCase.ts +76 -0
  134. package/src/domain/usecases/AnalyzeProblemByIssueUseCase.ts +209 -0
  135. package/src/domain/usecases/ClearNextActionHourUseCase.ts +51 -0
  136. package/src/domain/usecases/GenerateWorkingTimeReportUseCase.test.ts +382 -0
  137. package/src/domain/usecases/GenerateWorkingTimeReportUseCase.ts +284 -0
  138. package/src/domain/usecases/HandleScheduledEventUseCase.test.ts +58 -0
  139. package/src/domain/usecases/HandleScheduledEventUseCase.ts +209 -0
  140. package/src/domain/usecases/SetWorkflowManagementIssueToStoryUseCase.ts +46 -0
  141. package/src/domain/usecases/adapter-interfaces/DateRepository.ts +5 -0
  142. package/src/domain/usecases/adapter-interfaces/IssueRepository.ts +44 -0
  143. package/src/domain/usecases/adapter-interfaces/ProjectRepository.ts +6 -0
  144. package/src/domain/usecases/adapter-interfaces/SlackRepository.ts +20 -0
  145. package/src/domain/usecases/adapter-interfaces/SpreadsheetRepository.ts +18 -0
  146. package/src/index.test.ts +8 -0
  147. package/src/index.ts +7 -0
  148. package/tsconfig.build.json +11 -0
  149. package/tsconfig.json +22 -0
  150. package/types/adapter/entry-points/cli/index.d.ts +3 -0
  151. package/types/adapter/entry-points/cli/index.d.ts.map +1 -0
  152. package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts +11 -0
  153. package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -0
  154. package/types/adapter/repositories/AxiosSlackRepository.d.ts +13 -0
  155. package/types/adapter/repositories/AxiosSlackRepository.d.ts.map +1 -0
  156. package/types/adapter/repositories/BaseGitHubRepository.d.ts +32 -0
  157. package/types/adapter/repositories/BaseGitHubRepository.d.ts.map +1 -0
  158. package/types/adapter/repositories/GoogleSpreadsheetRepository.d.ts +13 -0
  159. package/types/adapter/repositories/GoogleSpreadsheetRepository.d.ts.map +1 -0
  160. package/types/adapter/repositories/GraphqlProjectRepository.d.ts +13 -0
  161. package/types/adapter/repositories/GraphqlProjectRepository.d.ts.map +1 -0
  162. package/types/adapter/repositories/LocalStorageCacheRepository.d.ts +12 -0
  163. package/types/adapter/repositories/LocalStorageCacheRepository.d.ts.map +1 -0
  164. package/types/adapter/repositories/LocalStorageRepository.d.ts +7 -0
  165. package/types/adapter/repositories/LocalStorageRepository.d.ts.map +1 -0
  166. package/types/adapter/repositories/SystemDateRepository.d.ts +7 -0
  167. package/types/adapter/repositories/SystemDateRepository.d.ts.map +1 -0
  168. package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts +38 -0
  169. package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts.map +1 -0
  170. package/types/adapter/repositories/issue/ApiV3IssueRepository.d.ts +17 -0
  171. package/types/adapter/repositories/issue/ApiV3IssueRepository.d.ts.map +1 -0
  172. package/types/adapter/repositories/issue/CheerioIssueRepository.d.ts +31 -0
  173. package/types/adapter/repositories/issue/CheerioIssueRepository.d.ts.map +1 -0
  174. package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts +39 -0
  175. package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts.map +1 -0
  176. package/types/adapter/repositories/issue/InternalGraphqlIssueRepository.d.ts +83 -0
  177. package/types/adapter/repositories/issue/InternalGraphqlIssueRepository.d.ts.map +1 -0
  178. package/types/adapter/repositories/issue/RestIssueRepository.d.ts +16 -0
  179. package/types/adapter/repositories/issue/RestIssueRepository.d.ts.map +1 -0
  180. package/types/adapter/repositories/issue/issueTimelineUtils.d.ts +12 -0
  181. package/types/adapter/repositories/issue/issueTimelineUtils.d.ts.map +1 -0
  182. package/types/adapter/repositories/utils.d.ts +4 -0
  183. package/types/adapter/repositories/utils.d.ts.map +1 -0
  184. package/types/domain/entities/Issue.d.ts +24 -0
  185. package/types/domain/entities/Issue.d.ts.map +1 -0
  186. package/types/domain/entities/Member.d.ts +4 -0
  187. package/types/domain/entities/Member.d.ts.map +1 -0
  188. package/types/domain/entities/Project.d.ts +29 -0
  189. package/types/domain/entities/Project.d.ts.map +1 -0
  190. package/types/domain/entities/ProjectField.d.ts +3 -0
  191. package/types/domain/entities/ProjectField.d.ts.map +1 -0
  192. package/types/domain/entities/ProjectFieldSingleSelect.d.ts +8 -0
  193. package/types/domain/entities/ProjectFieldSingleSelect.d.ts.map +1 -0
  194. package/types/domain/entities/ProjectFieldSingleSelectOption.d.ts +8 -0
  195. package/types/domain/entities/ProjectFieldSingleSelectOption.d.ts.map +1 -0
  196. package/types/domain/entities/WorkingTime.d.ts +8 -0
  197. package/types/domain/entities/WorkingTime.d.ts.map +1 -0
  198. package/types/domain/usecases/ActionAnnouncementUseCase.d.ts +17 -0
  199. package/types/domain/usecases/ActionAnnouncementUseCase.d.ts.map +1 -0
  200. package/types/domain/usecases/AnalyzeProblemByIssueUseCase.d.ts +26 -0
  201. package/types/domain/usecases/AnalyzeProblemByIssueUseCase.d.ts.map +1 -0
  202. package/types/domain/usecases/ClearNextActionHourUseCase.d.ts +14 -0
  203. package/types/domain/usecases/ClearNextActionHourUseCase.d.ts.map +1 -0
  204. package/types/domain/usecases/GenerateWorkingTimeReportUseCase.d.ts +50 -0
  205. package/types/domain/usecases/GenerateWorkingTimeReportUseCase.d.ts.map +1 -0
  206. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts +63 -0
  207. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts.map +1 -0
  208. package/types/domain/usecases/SetWorkflowManagementIssueToStoryUseCase.d.ts +14 -0
  209. package/types/domain/usecases/SetWorkflowManagementIssueToStoryUseCase.d.ts.map +1 -0
  210. package/types/domain/usecases/adapter-interfaces/DateRepository.d.ts +6 -0
  211. package/types/domain/usecases/adapter-interfaces/DateRepository.d.ts.map +1 -0
  212. package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts +23 -0
  213. package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts.map +1 -0
  214. package/types/domain/usecases/adapter-interfaces/ProjectRepository.d.ts +6 -0
  215. package/types/domain/usecases/adapter-interfaces/ProjectRepository.d.ts.map +1 -0
  216. package/types/domain/usecases/adapter-interfaces/SlackRepository.d.ts +9 -0
  217. package/types/domain/usecases/adapter-interfaces/SlackRepository.d.ts.map +1 -0
  218. package/types/domain/usecases/adapter-interfaces/SpreadsheetRepository.d.ts +6 -0
  219. package/types/domain/usecases/adapter-interfaces/SpreadsheetRepository.d.ts.map +1 -0
  220. package/types/index.d.ts +10 -0
  221. package/types/index.d.ts.map +1 -0
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GenerateWorkingTimeReportUseCase = void 0;
4
+ class GenerateWorkingTimeReportUseCase {
5
+ constructor(issueRepository, spreadsheetRepository, dateRepository) {
6
+ this.issueRepository = issueRepository;
7
+ this.spreadsheetRepository = spreadsheetRepository;
8
+ this.dateRepository = dateRepository;
9
+ this.run = async (input) => {
10
+ const workingReportIssueTemplate = await this.getWorkingReportIssueTemplate(input);
11
+ const reportRows = [];
12
+ for (const member of input.members) {
13
+ try {
14
+ const memberReportRows = await this.createIssueForEachAuthor(member, input.targetDate, input.issues, input.org, input.repo, input.reportIssueLabels, workingReportIssueTemplate, input.warningThresholdHour);
15
+ reportRows.push(...memberReportRows);
16
+ await new Promise((resolve) => setTimeout(resolve, 5000));
17
+ }
18
+ catch (e) {
19
+ await this.issueRepository.createNewIssue(input.org, input.repo, `Error occured while creating working report for ${member}`, `${JSON.stringify(e)}`, [input.manager], ['bug']);
20
+ }
21
+ }
22
+ await this.spreadsheetRepository.appendSheetValues(input.spreadsheetUrl, 'IssueLogEditable', reportRows);
23
+ await this.spreadsheetRepository.appendSheetValues(input.spreadsheetUrl, 'IssueLogRawData', reportRows);
24
+ };
25
+ this.getWorkingReportIssueTemplate = async (input) => {
26
+ if (input.reportIssueTemplate) {
27
+ return input.reportIssueTemplate;
28
+ }
29
+ return `
30
+ Please confirm each working time and total working time and assign to :bow:
31
+ Fix warnings if you have :warning: mark in Detail section.
32
+ If you have any questions, please put comment and assign to @${input.manager} :pray:
33
+
34
+ ## Working report for {AUTHOR} on {DATE_WITH_DAY_OF_WEEK}
35
+ ### Total
36
+ \`\`\`
37
+ {TOTAL_WORKING_TIME_HHMM}
38
+ \`\`\`
39
+
40
+ ### Detail
41
+ {TIMELINE_DETAILS}
42
+
43
+ Summary of working report: ${input.spreadsheetUrl}
44
+ `;
45
+ };
46
+ this.createIssueForEachAuthor = async (author, date, issues, org, repo, labels, workingReportIssueTemplate, workingTimeThresholdHour = 6) => {
47
+ const dateString = `${date.toISOString().split('T')[0]}`;
48
+ const dateStringWithDoW = `${date.toISOString().split('T')[0]} (${['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][date.getDay()]})`;
49
+ const timelineEvents = this.filterTimelineAndSortByAuthor(issues, date, author, workingTimeThresholdHour);
50
+ const totalHhmm = this.calculateTotalHhmm(timelineEvents);
51
+ const timelineDetails = this.applyToTimelineDetails(timelineEvents);
52
+ const title = this.applyReplacementToTemplate({
53
+ template: 'Working report for {AUTHOR} on {DATE_WITH_DAY_OF_WEEK}',
54
+ replacement: {
55
+ AUTHOR: author,
56
+ DATE_WITH_DAY_OF_WEEK: dateStringWithDoW,
57
+ },
58
+ });
59
+ const body = this.applyReplacementToTemplate({
60
+ template: workingReportIssueTemplate,
61
+ replacement: {
62
+ AUTHOR: author,
63
+ DATE_WITH_DAY_OF_WEEK: dateStringWithDoW,
64
+ TOTAL_WORKING_TIME_HHMM: totalHhmm,
65
+ TIMELINE_DETAILS: timelineDetails,
66
+ },
67
+ });
68
+ await this.issueRepository.createNewIssue(org, repo, title, body, [author], labels);
69
+ const issueLogRows = timelineEvents.map((event) => [
70
+ dateString,
71
+ event.startHhmm,
72
+ event.endHhmm,
73
+ author,
74
+ event.warnings.join(':'),
75
+ event.issueUrl,
76
+ event.labels.join(':'),
77
+ ]);
78
+ return issueLogRows;
79
+ };
80
+ this.filterTimelineAndSortByAuthor = (issues, targetDate, author, workingTimeThresholdHour) => {
81
+ const dateString = targetDate.toISOString().split('T')[0];
82
+ const timelineEvents = [];
83
+ for (const issue of issues) {
84
+ const filteredTimeline = issue.workingTimeline.filter((event) => event.author === author);
85
+ for (const event of filteredTimeline) {
86
+ const start = event.startedAt.toISOString();
87
+ const end = event.endedAt.toISOString();
88
+ if (end.split('T')[0] !== dateString) {
89
+ continue;
90
+ }
91
+ const startHhmm = this.convertIsoToHhmm(start);
92
+ const endHhmm = this.convertIsoToHhmm(end);
93
+ const durationHhmm = this.calculateDuration(start, end);
94
+ timelineEvents.push({
95
+ issueUrl: issue.url,
96
+ issueTitle: issue.title,
97
+ startHhmm,
98
+ endHhmm,
99
+ durationHhmm,
100
+ warnings: [],
101
+ labels: issue.labels,
102
+ nameWithOwner: issue.nameWithOwner,
103
+ });
104
+ }
105
+ }
106
+ const sortedTimelineEvents = timelineEvents.sort((a, b) => {
107
+ if (a.endHhmm === b.endHhmm) {
108
+ return a.startHhmm.localeCompare(b.startHhmm);
109
+ }
110
+ return a.endHhmm.localeCompare(b.endHhmm);
111
+ });
112
+ for (let i = 0; i < sortedTimelineEvents.length - 1; i++) {
113
+ const current = sortedTimelineEvents[i];
114
+ const currentDuration = sortedTimelineEvents[i].durationHhmm;
115
+ const [hh] = currentDuration.split(':').map(Number);
116
+ if (hh >= workingTimeThresholdHour) {
117
+ current.warnings.push(`Over ${workingTimeThresholdHour} hours`);
118
+ }
119
+ if (i === 0) {
120
+ continue;
121
+ }
122
+ const previous = sortedTimelineEvents[i - 1];
123
+ if (previous.endHhmm > current.startHhmm) {
124
+ current.warnings.push(`Overlap`);
125
+ }
126
+ }
127
+ return sortedTimelineEvents;
128
+ };
129
+ this.convertIsoToHhmm = (isoString) => {
130
+ const date = new Date(isoString);
131
+ const hh = date.getHours();
132
+ const mm = date.getMinutes();
133
+ return `${String(hh).padStart(2, '0')}:${String(mm).padStart(2, '0')}`;
134
+ };
135
+ this.calculateDuration = (startIsoString, endIsoString) => {
136
+ const startDate = new Date(startIsoString);
137
+ const endDate = new Date(endIsoString);
138
+ startDate.setMilliseconds(0);
139
+ startDate.setSeconds(0);
140
+ endDate.setMilliseconds(0);
141
+ endDate.setSeconds(0);
142
+ const duration = endDate.getTime() - startDate.getTime();
143
+ const hh = Math.floor(duration / (1000 * 60 * 60));
144
+ const mm = Math.floor((duration % (1000 * 60 * 60)) / (1000 * 60));
145
+ return `${String(hh).padStart(2, '0')}:${String(mm).padStart(2, '0')}`;
146
+ };
147
+ this.calculateTotalHhmm = (timelineEvents) => {
148
+ const totalDuration = timelineEvents.reduce((acc, event) => {
149
+ const [hh, mm] = event.durationHhmm.split(':').map(Number);
150
+ return acc + hh * 60 + mm;
151
+ }, 0);
152
+ return this.dateRepository.formatDurationToHHMM(totalDuration);
153
+ };
154
+ this.applyToTimelineDetails = (timelineEvents) => {
155
+ return `
156
+ - Start, End, Duration, Issue title, Labels
157
+ ${timelineEvents.map((event) => this.applyToTimelineDetail(event)).join('\n')}
158
+ `;
159
+ };
160
+ this.applyToTimelineDetail = (timelineEvents) => {
161
+ const labelUrls = timelineEvents.labels.map((label) => `https://github.com/${timelineEvents.nameWithOwner}/labels/${encodeURI(label).replace(/:/g, '%3A')}`);
162
+ return `- ${timelineEvents.startHhmm}, ${timelineEvents.endHhmm}, ${timelineEvents.durationHhmm}, ${timelineEvents.warnings.length > 0 ? `:warning: ${timelineEvents.warnings.join(' ')}` : ''} ${timelineEvents.issueUrl}, ${labelUrls.join(' ')}`;
163
+ };
164
+ this.applyReplacementToTemplate = (input) => {
165
+ const replacedText = Object.entries(input.replacement).reduce((acc, [key, value]) => {
166
+ return acc.replace(new RegExp(`{${key}}`, 'g'), value);
167
+ }, input.template);
168
+ if (replacedText.includes('{')) {
169
+ const unknownKeys = replacedText.match(/\{[^}]+}/g);
170
+ if (!unknownKeys) {
171
+ throw new Error(`Broken template: ${replacedText}`);
172
+ }
173
+ throw new Error(`Failed to replace. Unknown keys: ${unknownKeys.map((key) => key.slice(1, -1)).join(', ')}`);
174
+ }
175
+ return replacedText;
176
+ };
177
+ }
178
+ }
179
+ exports.GenerateWorkingTimeReportUseCase = GenerateWorkingTimeReportUseCase;
180
+ //# sourceMappingURL=GenerateWorkingTimeReportUseCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GenerateWorkingTimeReportUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/GenerateWorkingTimeReportUseCase.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HandleScheduledEventUseCase = exports.ProjectNotFoundError = void 0;
4
+ class ProjectNotFoundError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = 'ProjectNotFoundError';
8
+ }
9
+ }
10
+ exports.ProjectNotFoundError = ProjectNotFoundError;
11
+ class HandleScheduledEventUseCase {
12
+ constructor(generateWorkingTimeReportUseCase, actionAnnouncementUseCase, setWorkflowManagementIssueToStoryUseCase, clearNextActionHourUseCase, analyzeProblemByIssueUseCase, dateRepository, spreadsheetRepository, projectRepository, issueRepository) {
13
+ this.generateWorkingTimeReportUseCase = generateWorkingTimeReportUseCase;
14
+ this.actionAnnouncementUseCase = actionAnnouncementUseCase;
15
+ this.setWorkflowManagementIssueToStoryUseCase = setWorkflowManagementIssueToStoryUseCase;
16
+ this.clearNextActionHourUseCase = clearNextActionHourUseCase;
17
+ this.analyzeProblemByIssueUseCase = analyzeProblemByIssueUseCase;
18
+ this.dateRepository = dateRepository;
19
+ this.spreadsheetRepository = spreadsheetRepository;
20
+ this.projectRepository = projectRepository;
21
+ this.issueRepository = issueRepository;
22
+ this.run = async (input) => {
23
+ const projectId = await this.projectRepository.findProjectIdByUrl(input.projectUrl);
24
+ if (!projectId) {
25
+ throw new ProjectNotFoundError(`Project not found. projectUrl: ${input.projectUrl}`);
26
+ }
27
+ const project = await this.projectRepository.getProject(projectId);
28
+ if (!project) {
29
+ throw new ProjectNotFoundError(`Project not found. projectId: ${projectId} projectUrl: ${input.projectUrl}`);
30
+ }
31
+ const now = await this.dateRepository.now();
32
+ const allowIssueCacheMinutes = 60;
33
+ const { issues, cacheUsed } = await this.issueRepository.getAllIssues(projectId, allowIssueCacheMinutes);
34
+ const targetDateTimes = await this.findTargetDateAndUpdateLastExecutionDateTime(input.workingReport.spreadsheetUrl, now);
35
+ for (const targetDateTime of targetDateTimes) {
36
+ await this.runForTargetDateTime({
37
+ org: input.org,
38
+ manager: input.manager,
39
+ workingReport: input.workingReport,
40
+ projectId,
41
+ issues,
42
+ targetDateTime,
43
+ });
44
+ }
45
+ await this.analyzeProblemByIssueUseCase.run({
46
+ targetDates: targetDateTimes,
47
+ project,
48
+ issues,
49
+ cacheUsed,
50
+ manager: input.manager,
51
+ org: input.org,
52
+ repo: input.workingReport.repo,
53
+ });
54
+ await this.actionAnnouncementUseCase.run({
55
+ targetDates: targetDateTimes,
56
+ project,
57
+ issues,
58
+ cacheUsed,
59
+ members: input.workingReport.members,
60
+ manager: input.manager,
61
+ });
62
+ await this.setWorkflowManagementIssueToStoryUseCase.run({
63
+ targetDates: targetDateTimes,
64
+ project,
65
+ issues,
66
+ cacheUsed,
67
+ });
68
+ await this.clearNextActionHourUseCase.run({
69
+ targetDates: targetDateTimes,
70
+ project,
71
+ issues,
72
+ cacheUsed,
73
+ });
74
+ return { project, issues, cacheUsed, targetDateTimes };
75
+ };
76
+ this.runForTargetDateTime = async (input) => {
77
+ const targetHour = input.targetDateTime.getHours();
78
+ const targetMinute = input.targetDateTime.getMinutes();
79
+ if (targetHour === 0 && targetMinute === 0) {
80
+ const yesterday = new Date(input.targetDateTime.getTime() - 24 * 60 * 60 * 1000);
81
+ await this.generateWorkingTimeReportUseCase.run({
82
+ ...input,
83
+ ...input.workingReport,
84
+ targetDate: yesterday,
85
+ });
86
+ }
87
+ };
88
+ this.findTargetDateAndUpdateLastExecutionDateTime = async (spreadsheetUrl, now) => {
89
+ const sheetValues = await this.spreadsheetRepository.getSheet(spreadsheetUrl, 'HandleScheduledEvent');
90
+ if (!sheetValues) {
91
+ await this.spreadsheetRepository.updateCell(spreadsheetUrl, 'HandleScheduledEvent', 1, 1, 'LastExecutionDateTime');
92
+ }
93
+ const lastExecutionDateTime = sheetValues && sheetValues[1][2] ? new Date(sheetValues[1][2]) : null;
94
+ const targetDateTimes = lastExecutionDateTime
95
+ ? HandleScheduledEventUseCase.createTargetDateTimes(lastExecutionDateTime, now)
96
+ : [now];
97
+ await this.spreadsheetRepository.updateCell(spreadsheetUrl, 'HandleScheduledEvent', 1, 2, targetDateTimes[targetDateTimes.length - 1].toISOString());
98
+ return targetDateTimes;
99
+ };
100
+ }
101
+ }
102
+ exports.HandleScheduledEventUseCase = HandleScheduledEventUseCase;
103
+ HandleScheduledEventUseCase.createTargetDateTimes = (from, to) => {
104
+ const targetDateTimes = [];
105
+ if (from.getTime() > to.getTime()) {
106
+ const targetDate = new Date(to);
107
+ targetDate.setSeconds(0);
108
+ targetDate.setMilliseconds(0);
109
+ return [targetDate];
110
+ }
111
+ const targetDate = new Date(from);
112
+ targetDate.setTime(targetDate.getTime() + 60 * 1000);
113
+ targetDate.setSeconds(0);
114
+ targetDate.setMilliseconds(0);
115
+ while (targetDate.getTime() <= to.getTime() &&
116
+ targetDateTimes.length < 30) {
117
+ targetDateTimes.push(new Date(targetDate));
118
+ targetDate.setMinutes(targetDate.getMinutes() + 1);
119
+ }
120
+ return targetDateTimes;
121
+ };
122
+ //# sourceMappingURL=HandleScheduledEventUseCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HandleScheduledEventUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/HandleScheduledEventUseCase.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SetWorkflowManagementIssueToStoryUseCase = void 0;
4
+ class SetWorkflowManagementIssueToStoryUseCase {
5
+ constructor(issueRepository) {
6
+ this.issueRepository = issueRepository;
7
+ this.run = async (input) => {
8
+ const story = input.project.story;
9
+ if (!story ||
10
+ input.cacheUsed ||
11
+ !input.targetDates.find((targetDate) => targetDate.getMinutes() === 0)) {
12
+ return;
13
+ }
14
+ const isTargetIssue = (issue) => {
15
+ return ((issue.labels.includes('story:workflow-management') ||
16
+ issue.labels.includes('daily-routine') ||
17
+ issue.isPr) &&
18
+ (issue.nextActionDate === null ||
19
+ issue.nextActionDate.getTime() <= input.targetDates[0].getTime()) &&
20
+ issue.nextActionHour === null &&
21
+ issue.state === 'OPEN' &&
22
+ issue.story === null);
23
+ };
24
+ for (const issue of input.issues) {
25
+ if (!isTargetIssue(issue)) {
26
+ continue;
27
+ }
28
+ await this.issueRepository.updateStory({ ...input.project, story }, issue, story.workflowManagementStory.id);
29
+ await new Promise((resolve) => setTimeout(resolve, 5000));
30
+ }
31
+ };
32
+ }
33
+ }
34
+ exports.SetWorkflowManagementIssueToStoryUseCase = SetWorkflowManagementIssueToStoryUseCase;
35
+ //# sourceMappingURL=SetWorkflowManagementIssueToStoryUseCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SetWorkflowManagementIssueToStoryUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/SetWorkflowManagementIssueToStoryUseCase.ts"],"names":[],"mappings":";;;AAIA,MAAa,wCAAwC;IACnD,YAAqB,eAAqD;QAArD,oBAAe,GAAf,eAAe,CAAsC;QAE1E,QAAG,GAAG,KAAK,EAAE,KAKZ,EAAiB,EAAE;YAClB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAClC,IACE,CAAC,KAAK;gBACN,KAAK,CAAC,SAAS;gBACf,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,EACtE,CAAC;gBACD,OAAO;YACT,CAAC;YACD,MAAM,aAAa,GAAG,CAAC,KAAY,EAAW,EAAE;gBAC9C,OAAO,CACL,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,2BAA2B,CAAC;oBACjD,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC;oBACtC,KAAK,CAAC,IAAI,CAAC;oBACb,CAAC,KAAK,CAAC,cAAc,KAAK,IAAI;wBAC5B,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;oBACnE,KAAK,CAAC,cAAc,KAAK,IAAI;oBAC7B,KAAK,CAAC,KAAK,KAAK,MAAM;oBACtB,KAAK,CAAC,KAAK,KAAK,IAAI,CACrB,CAAC;YACJ,CAAC,CAAC;YACF,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBACjC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC1B,SAAS;gBACX,CAAC;gBACD,MAAM,IAAI,CAAC,eAAe,CAAC,WAAW,CACpC,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,EAC3B,KAAK,EACL,KAAK,CAAC,uBAAuB,CAAC,EAAE,CACjC,CAAC;gBACF,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC,CAAC;IAvC2E,CAAC;CAwC/E;AAzCD,4FAyCC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=DateRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateRepository.js","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/DateRepository.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=IssueRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IssueRepository.js","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/IssueRepository.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ProjectRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProjectRepository.js","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/ProjectRepository.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=SlackRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlackRepository.js","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/SlackRepository.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=SpreadsheetRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpreadsheetRepository.js","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/SpreadsheetRepository.ts"],"names":[],"mappings":""}
package/bin/index.js ADDED
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.scheduledEvent = exports.hello = void 0;
7
+ const dotenv_1 = __importDefault(require("dotenv"));
8
+ const HandleScheduledEventUseCaseHandler_1 = require("./adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler");
9
+ dotenv_1.default.config();
10
+ const hello = (name) => `hello ${name}`;
11
+ exports.hello = hello;
12
+ exports.scheduledEvent = new HandleScheduledEventUseCaseHandler_1.HandleScheduledEventUseCaseHandler().handle;
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,oDAA4B;AAC5B,2HAAwH;AACxH,gBAAM,CAAC,MAAM,EAAE,CAAC;AACT,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,SAAS,IAAI,EAAE,CAAC;AAA1C,QAAA,KAAK,SAAqC;AAG1C,QAAA,cAAc,GAAG,IAAI,uEAAkC,EAAE,CAAC,MAAM,CAAC"}
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ parserPreset: 'conventional-changelog-conventionalcommits',
3
+ rules: {
4
+ 'body-max-line-length': [2, 'always', 'Infinity'],
5
+ },
6
+ };
package/jest.config.js ADDED
@@ -0,0 +1,19 @@
1
+ module.exports = {
2
+ preset: 'ts-jest',
3
+ testEnvironment: 'node',
4
+ transform: {
5
+ '^.+\\.ts?$': 'ts-jest',
6
+ },
7
+ transformIgnorePatterns: ['<rootDir>/node_modules/'],
8
+ collectCoverage: true,
9
+ coverageDirectory: 'reports/coverage',
10
+ reporters: [
11
+ 'default',
12
+ ['jest-junit', { outputDirectory: 'reports/jest-junit' }],
13
+ [
14
+ './node_modules/jest-html-reporter',
15
+ { outputPath: 'reports/jest-html-reporter/index.html' },
16
+ ],
17
+ ],
18
+ testPathIgnorePatterns: ['/node_modules/', '/bin/', '/dist/'],
19
+ };
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "github-issue-tower-defence-management",
3
+ "version": "1.1.0",
4
+ "description": "",
5
+ "main": "bin/index.js",
6
+ "scripts": {
7
+ "prebuild": "npm run doctor",
8
+ "doctor:node-version": "check-node-version --node 22 --npx 10 --npm 10",
9
+ "doctor": "npm run doctor:node-version",
10
+ "prettier": "prettier --write '**/*'",
11
+ "lint": "eslint src",
12
+ "lint-fix": "eslint src --fix",
13
+ "fmt": "npm run prettier && npm run lint-fix",
14
+ "build": "tsc -p ./tsconfig.build.json",
15
+ "test": "jest",
16
+ "prepare": "ts-patch install && typia patch"
17
+ },
18
+ "bin": {
19
+ "github-issue-tower-defence-management": "./bin/adapter/entry-points/cli/index.js"
20
+ },
21
+ "types": "types/index.d.ts",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management.git"
25
+ },
26
+ "keywords": [],
27
+ "author": "",
28
+ "license": "ISC",
29
+ "bugs": {
30
+ "url": "https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues"
31
+ },
32
+ "release": {
33
+ "plugins": [
34
+ "@semantic-release/commit-analyzer",
35
+ "@semantic-release/release-notes-generator",
36
+ "@semantic-release/changelog",
37
+ "@semantic-release/npm"
38
+ ],
39
+ "branches": [
40
+ "main"
41
+ ]
42
+ },
43
+ "homepage": "https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management#readme",
44
+ "devDependencies": {
45
+ "@semantic-release/changelog": "^6.0.3",
46
+ "@semantic-release/commit-analyzer": "^13.0.0",
47
+ "@types/cookie": "^1.0.0",
48
+ "@types/jest": "^29.5.12",
49
+ "@typescript-eslint/eslint-plugin": "^7.2.0",
50
+ "@typescript-eslint/parser": "^7.2.0",
51
+ "check-node-version": "^4.2.1",
52
+ "commitlint": "^19.1.0",
53
+ "conventional-changelog-conventionalcommits": "^8.0.0",
54
+ "eslint": "^8.57.0",
55
+ "eslint-plugin-import": "^2.29.1",
56
+ "eslint-plugin-no-type-assertion": "^1.3.0",
57
+ "eslint-plugin-unused-imports": "^3.1.0",
58
+ "jest": "^29.7.0",
59
+ "jest-html-reporter": "^3.10.2",
60
+ "jest-junit": "^16.0.0",
61
+ "jest-mock-extended": "^4.0.0-beta1",
62
+ "prettier": "^3.2.5",
63
+ "semantic-release": "^24.0.0",
64
+ "ts-jest": "^29.1.2",
65
+ "ts-patch": "^3.2.1",
66
+ "typescript": "^5.6.3"
67
+ },
68
+ "dependencies": {
69
+ "@semantic-release/npm": "^12.0.1",
70
+ "axios": "^1.7.7",
71
+ "cheerio": "^1.0.0",
72
+ "commander": "^12.0.0",
73
+ "cookie": "^1.0.1",
74
+ "dotenv": "^16.4.5",
75
+ "gh-cookie": "^1.1.2",
76
+ "googleapis": "^144.0.0",
77
+ "typia": "^6.11.3",
78
+ "yaml": "^2.6.0"
79
+ }
80
+ }
package/renovate.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3
+ "extends": ["config:base"],
4
+ "automerge": true,
5
+ "platformAutomerge": true,
6
+ "rebaseWhen": "auto",
7
+ "prConcurrentLimit": 2,
8
+ "schedule": ["every weekend"],
9
+ "ignorePresets": [],
10
+ "dependencyDashboard": false,
11
+ "branchConcurrentLimit": 2,
12
+ "ignorePaths": ["**/generated/*", "**/_gen/*"],
13
+ "packageRules": [
14
+ {
15
+ "matchPackagePatterns": ["*"],
16
+ "matchUpdateTypes": ["minor", "patch"],
17
+ "groupName": "all non-major dependencies",
18
+ "groupSlug": "all-minor-patch"
19
+ },
20
+ {
21
+ "matchPackageNames": ["eslint"],
22
+ "allowedVersions": "<9.0.0"
23
+ },
24
+ {
25
+ "matchPackageNames": ["@typescript-eslint/eslint-plugin"],
26
+ "allowedVersions": "<6.0.0"
27
+ },
28
+ {
29
+ "matchPackageNames": ["@typescript-eslint/parser"],
30
+ "allowedVersions": "<6.0.0"
31
+ },
32
+ {
33
+ "matchPackageNames": ["eslint-plugin-unused-imports"],
34
+ "allowedVersions": "<4.0.0"
35
+ }
36
+ ]
37
+ }
@@ -0,0 +1,20 @@
1
+ import { execSync } from 'child_process';
2
+
3
+ describe('commander program', () => {
4
+ it('should output help contents', () => {
5
+ const output = execSync(
6
+ 'npx ts-node ./src/adapter/entry-points/cli/index.ts -h',
7
+ ).toString();
8
+
9
+ expect(output.trim())
10
+ .toEqual(`Usage: github-issue-tower-defence-management [options]
11
+
12
+ CLI tool for GitHub Issue Tower Defence Management
13
+
14
+ Options:
15
+ -t, --trigger <type> Trigger type: issue or schedule
16
+ -c, --config <path> Path to config YAML file
17
+ -i, --issue <url> GitHub Issue URL
18
+ -h, --help display help for command`);
19
+ });
20
+ });
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { HandleScheduledEventUseCaseHandler } from '../handlers/HandleScheduledEventUseCaseHandler';
4
+
5
+ const program = new Command();
6
+
7
+ interface Options {
8
+ trigger: 'issue' | 'schedule';
9
+ config: string;
10
+ issue?: string;
11
+ }
12
+
13
+ program
14
+ .name('github-issue-tower-defence-management')
15
+ .description('CLI tool for GitHub Issue Tower Defence Management')
16
+ .requiredOption(
17
+ '-t, --trigger <type>',
18
+ 'Trigger type: issue or schedule',
19
+ /^(issue|schedule)$/i,
20
+ )
21
+ .requiredOption('-c, --config <path>', 'Path to config YAML file')
22
+ .option('-i, --issue <url>', 'GitHub Issue URL')
23
+ .action(async (options: Options) => {
24
+ if (options.trigger === 'issue' && !options.issue) {
25
+ console.error('Issue URL is required when trigger type is "issue"');
26
+ process.exit(1);
27
+ }
28
+ if (options.trigger === 'schedule') {
29
+ const handler = new HandleScheduledEventUseCaseHandler();
30
+ await handler.handle(options.config);
31
+ }
32
+ });
33
+
34
+ if (process.argv) {
35
+ program.parse(process.argv);
36
+ }