nitor 1.1.0 → 1.2.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.
@@ -0,0 +1,251 @@
1
+ const omelette = require('omelette');
2
+ const { ACTIONS } = require('./enums/actions.enum');
3
+
4
+ const setupAutocomplete = () => {
5
+ const completion = omelette('nitor|nu');
6
+
7
+ // Define the completion tree
8
+ completion.tree({
9
+ [ACTIONS.BUILD]: {
10
+ '-project': [
11
+ 'portal',
12
+ 'gateway',
13
+ 'phr',
14
+ 'configService',
15
+ 'healthRecords',
16
+ 'centralAuth',
17
+ 'mpi',
18
+ 'phrAdminBackend',
19
+ 'phrAdminClient',
20
+ 'terminologyService',
21
+ ],
22
+ '-p': [
23
+ 'portal',
24
+ 'gateway',
25
+ 'phr',
26
+ 'configService',
27
+ 'healthRecords',
28
+ 'centralAuth',
29
+ 'mpi',
30
+ 'phrAdminBackend',
31
+ 'phrAdminClient',
32
+ 'terminologyService',
33
+ ],
34
+ '-components': ['client', 'administration', 'provider', 'rest-api'],
35
+ '-c': ['client', 'administration', 'provider', 'rest-api'],
36
+ '-instance': ['dev', 'qa', 'pilot'],
37
+ '-i': ['dev', 'qa', 'pilot'],
38
+ '-help': [],
39
+ '--h': [],
40
+ },
41
+ [ACTIONS.DEPLOY]: {
42
+ '-project': [
43
+ 'portal',
44
+ 'gateway',
45
+ 'phr',
46
+ 'configService',
47
+ 'healthRecords',
48
+ 'centralAuth',
49
+ 'mpi',
50
+ 'phrAdminBackend',
51
+ 'phrAdminClient',
52
+ 'terminologyService',
53
+ ],
54
+ '-p': [
55
+ 'portal',
56
+ 'gateway',
57
+ 'phr',
58
+ 'configService',
59
+ 'healthRecords',
60
+ 'centralAuth',
61
+ 'mpi',
62
+ 'phrAdminBackend',
63
+ 'phrAdminClient',
64
+ 'terminologyService',
65
+ ],
66
+ '-components': ['client', 'administration', 'provider', 'rest-api'],
67
+ '-c': ['client', 'administration', 'provider', 'rest-api'],
68
+ '-instance': ['dev', 'qa', 'pilot'],
69
+ '-i': ['dev', 'qa', 'pilot'],
70
+ '-help': [],
71
+ '--h': [],
72
+ },
73
+ [ACTIONS.BUILD_DEPLOY]: {
74
+ '-project': [
75
+ 'portal',
76
+ 'gateway',
77
+ 'phr',
78
+ 'configService',
79
+ 'healthRecords',
80
+ 'centralAuth',
81
+ 'mpi',
82
+ 'phrAdminBackend',
83
+ 'phrAdminClient',
84
+ 'terminologyService',
85
+ ],
86
+ '-p': [
87
+ 'portal',
88
+ 'gateway',
89
+ 'phr',
90
+ 'configService',
91
+ 'healthRecords',
92
+ 'centralAuth',
93
+ 'mpi',
94
+ 'phrAdminBackend',
95
+ 'phrAdminClient',
96
+ 'terminologyService',
97
+ ],
98
+ '-components': ['client', 'administration', 'provider', 'rest-api'],
99
+ '-c': ['client', 'administration', 'provider', 'rest-api'],
100
+ '-instance': ['dev', 'qa', 'pilot'],
101
+ '-i': ['dev', 'qa', 'pilot'],
102
+ '-help': [],
103
+ '--h': [],
104
+ },
105
+ [ACTIONS.CREATE_BRANCH]: {
106
+ '-task': [],
107
+ '-t': [],
108
+ '-type': ['feat', 'fix'],
109
+ '-ty': ['feat', 'fix'],
110
+ '-description': [],
111
+ '-d': [],
112
+ '-project': [
113
+ 'portal',
114
+ 'gateway',
115
+ 'phr',
116
+ 'configService',
117
+ 'healthRecords',
118
+ 'centralAuth',
119
+ 'mpi',
120
+ 'phrAdminBackend',
121
+ 'phrAdminClient',
122
+ 'terminologyService',
123
+ ],
124
+ '-p': [
125
+ 'portal',
126
+ 'gateway',
127
+ 'phr',
128
+ 'configService',
129
+ 'healthRecords',
130
+ 'centralAuth',
131
+ 'mpi',
132
+ 'phrAdminBackend',
133
+ 'phrAdminClient',
134
+ 'terminologyService',
135
+ ],
136
+ '-help': [],
137
+ '--h': [],
138
+ },
139
+ [ACTIONS.REVIEW]: {
140
+ '-project': [
141
+ 'portal',
142
+ 'gateway',
143
+ 'phr',
144
+ 'configService',
145
+ 'healthRecords',
146
+ 'centralAuth',
147
+ 'mpi',
148
+ 'phrAdminBackend',
149
+ 'phrAdminClient',
150
+ 'terminologyService',
151
+ ],
152
+ '-p': [
153
+ 'portal',
154
+ 'gateway',
155
+ 'phr',
156
+ 'configService',
157
+ 'healthRecords',
158
+ 'centralAuth',
159
+ 'mpi',
160
+ 'phrAdminBackend',
161
+ 'phrAdminClient',
162
+ 'terminologyService',
163
+ ],
164
+ '-mergeId': [],
165
+ '-mId': [],
166
+ '-repository': [
167
+ 'portalClient',
168
+ 'portalBackend',
169
+ 'portalDeployment',
170
+ 'portalAutomation',
171
+ 'gatewayBackend',
172
+ 'gatewayClient',
173
+ 'gatewayDeployment',
174
+ 'phrClient',
175
+ 'phrBackend',
176
+ 'phrDeployment',
177
+ 'configService',
178
+ 'healthRecords',
179
+ 'centralAuth',
180
+ 'mpi',
181
+ 'phrAdminBackend',
182
+ 'phrAdminClient',
183
+ 'terminologyService',
184
+ ],
185
+ '-r': [
186
+ 'portalClient',
187
+ 'portalBackend',
188
+ 'portalDeployment',
189
+ 'portalAutomation',
190
+ 'gatewayBackend',
191
+ 'gatewayClient',
192
+ 'gatewayDeployment',
193
+ 'phrClient',
194
+ 'phrBackend',
195
+ 'phrDeployment',
196
+ 'configService',
197
+ 'healthRecords',
198
+ 'centralAuth',
199
+ 'mpi',
200
+ 'phrAdminBackend',
201
+ 'phrAdminClient',
202
+ 'terminologyService',
203
+ ],
204
+ '-help': [],
205
+ '--h': [],
206
+ },
207
+ [ACTIONS.REFACTOR]: {
208
+ '-help': [],
209
+ '--h': [],
210
+ },
211
+ [ACTIONS.BACKUP]: {
212
+ '-project': ['configService', 'medicaCentralAuth', 'medicaPortal', 'phr'],
213
+ '-p': ['configService', 'medicaCentralAuth', 'medicaPortal', 'phr'],
214
+ '-components': [],
215
+ '-c': [],
216
+ '-help': [],
217
+ '--h': [],
218
+ },
219
+ [ACTIONS.MERGE]: {
220
+ '-source': [],
221
+ '-s': [],
222
+ '-target': [],
223
+ '-ta': [],
224
+ '-help': [],
225
+ '--h': [],
226
+ },
227
+ [ACTIONS.CLEANUP]: {
228
+ '-help': [],
229
+ '--h': [],
230
+ },
231
+ [ACTIONS.TIME_INIT]: [],
232
+ [ACTIONS.TIME_SWITCH]: [],
233
+ [ACTIONS.TIME_ADD]: [],
234
+ [ACTIONS.TIME_UPDATE]: [],
235
+ [ACTIONS.TIME_DELETE]: [],
236
+ [ACTIONS.TIME_STATUS]: [],
237
+ [ACTIONS.TIME_ENTRIES]: [],
238
+ [ACTIONS.TIME_ZOHO]: [],
239
+ [ACTIONS.TIME_GITLAB]: [],
240
+ [ACTIONS.TIME_MERGE]: [],
241
+ [ACTIONS.VERSION]: [],
242
+ [ACTIONS.HELP]: [],
243
+ });
244
+
245
+ // Initialize the completion
246
+ completion.init();
247
+
248
+ return completion;
249
+ };
250
+
251
+ module.exports = { setupAutocomplete };
@@ -11,5 +11,17 @@ module.exports = {
11
11
  REFACTOR: 'refactor',
12
12
  REVIEW: 'review',
13
13
  VERSION: 'version',
14
+
15
+ // Time entry commands
16
+ TIME_INIT: 'time-init',
17
+ TIME_SWITCH: 'time-switch',
18
+ TIME_ADD: 'time-add',
19
+ TIME_UPDATE: 'time-update',
20
+ TIME_DELETE: 'time-delete',
21
+ TIME_STATUS: 'time-stats',
22
+ TIME_ENTRIES: 'time-entries',
23
+ TIME_ZOHO: 'time-zoho',
24
+ TIME_GITLAB: 'time-gitlab',
25
+ TIME_MERGE: 'time-merge',
14
26
  },
15
27
  };
@@ -1,4 +1,4 @@
1
- // const { checkConfig } = require('./init-config');
1
+ const axios = require('axios');
2
2
  const { build, buildStatus } = require('./build');
3
3
  const { deploy } = require('./deploy');
4
4
  const { ACTIONS } = require('./enums/actions.enum');
@@ -10,17 +10,35 @@ const { backup } = require('./mongodb-backup');
10
10
  const { merge } = require('./merge');
11
11
  const { cleanup } = require('./cleanup');
12
12
 
13
+ // Time entry imports
14
+ const { removeEmpty } = require('./time-entry/utils');
15
+ const { getStatus, getTasksByDate } = require('./time-entry/get-report');
16
+ const { logTaskHoursAndSync } = require('./time-entry/log-task-hours-and-sync');
17
+ const { addNewTask } = require('./time-entry/add-task');
18
+ const { updateTask, deleteTask } = require('./time-entry/update-delete-task');
19
+ const { getGitlabActivities } = require('./time-entry/get-gitlab-activities');
20
+ const { getZohoTasks } = require('./time-entry/get-zoho-tasks');
21
+
13
22
  const processArgs = async (type, value) => {
14
23
  try {
15
24
  let values;
16
25
 
17
- if (
18
- type !== ACTIONS.HELP &&
19
- type !== ACTIONS.VERSION &&
20
- type !== ACTIONS.CLEANUP &&
21
- !value.includes('--h') &&
22
- !value.includes('-help')
23
- ) {
26
+ // Skip convertParamsToMap for time commands and other special commands
27
+ const skipConversion = [
28
+ ACTIONS.HELP,
29
+ ACTIONS.VERSION,
30
+ ACTIONS.CLEANUP,
31
+ ACTIONS.TIME_ADD,
32
+ ACTIONS.TIME_UPDATE,
33
+ ACTIONS.TIME_DELETE,
34
+ ACTIONS.TIME_STATUS,
35
+ ACTIONS.TIME_ENTRIES,
36
+ ACTIONS.TIME_ZOHO,
37
+ ACTIONS.TIME_GITLAB,
38
+ ACTIONS.TIME_MERGE,
39
+ ];
40
+
41
+ if (!skipConversion.includes(type) && !value?.includes('--h') && !value?.includes('-help')) {
24
42
  values = await convertParamsToMap(value, type);
25
43
  }
26
44
 
@@ -140,22 +158,22 @@ Options:
140
158
  -r, --repository <repository name> repository name
141
159
 
142
160
  Repository list:
143
- portalClient
144
- portalBackend
145
- portalDeployment
146
- portalAutomation
161
+ centralAuth
162
+ configService
147
163
  gatewayBackend
148
164
  gatewayClient
149
165
  gatewayDeployment
150
- phrClient
151
- phrBackend
152
- phrDeployment
153
- configService
154
166
  healthRecords
155
- centralAuth
156
167
  mpi
157
168
  phrAdminBackend
158
169
  phrAdminClient
170
+ phrBackend
171
+ phrClient
172
+ phrDeployment
173
+ portalAutomation
174
+ portalBackend
175
+ portalClient
176
+ portalDeployment
159
177
  terminologyService`);
160
178
 
161
179
  return;
@@ -250,8 +268,141 @@ Note: This operation cannot be undone. Make sure you have pushed any important c
250
268
  const path = require('path');
251
269
  const packageJson = require(path.resolve(__dirname, '../package.json'));
252
270
  const packageVersion = packageJson.version;
271
+ // ANSI color codes
272
+ const cyan = '\x1b[36m';
273
+ const green = '\x1b[32m';
274
+ const yellow = '\x1b[33m';
275
+ const reset = '\x1b[0m';
276
+ const bold = '\x1b[1m';
277
+
278
+ console.log(`
279
+ ${cyan}${bold}╔════════════════════════════════════════════════════╗
280
+ ║ ║
281
+ ║ ${yellow}███╗ ██╗ ██╗ ████████╗ ██████╗ ██████╗${cyan} ║
282
+ ║ ${yellow}████╗ ██║ ██║ ╚══██╔══╝ ██╔═══██╗ ██╔══██╗${cyan} ║
283
+ ║ ${yellow}██╔██╗ ██║ ██║ ██║ ██║ ██║ ██████╔╝${cyan} ║
284
+ ║ ${yellow}██║╚██╗██║ ██║ ██║ ██║ ██║ ██╔══██╗${cyan} ║
285
+ ║ ${yellow}██║ ╚████║ ██║ ██║ ╚██████╔╝ ██║ ██║${cyan} ║
286
+ ║ ${yellow}╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝${cyan} ║
287
+ ║ ║
288
+ ╚════════════════════════════════════════════════════╝${reset}
289
+
290
+ ${green}${bold}Version:${reset} ${bold}v${packageVersion}${reset}`);
291
+
292
+ break;
293
+ }
294
+
295
+ // Time entry commands
296
+ case ACTIONS.TIME_ADD: {
297
+ const timeValues = value ? removeEmpty(value?.split(' -')) : value;
298
+
299
+ await addNewTask(timeValues);
300
+
301
+ break;
302
+ }
303
+
304
+ case ACTIONS.TIME_UPDATE: {
305
+ const timeValues = value ? removeEmpty(value?.split(' -')) : value;
306
+
307
+ await updateTask(timeValues);
308
+
309
+ break;
310
+ }
311
+
312
+ case ACTIONS.TIME_DELETE: {
313
+ const timeValues = value ? removeEmpty(value?.split(' -')) : value;
314
+
315
+ console.log(await deleteTask(timeValues));
316
+
317
+ break;
318
+ }
319
+
320
+ case ACTIONS.TIME_STATUS: {
321
+ const timeValues = value ? removeEmpty(value?.split(' -')) : value;
253
322
 
254
- console.log('Package version:', packageVersion);
323
+ await getStatus(timeValues);
324
+
325
+ break;
326
+ }
327
+
328
+ case ACTIONS.TIME_ENTRIES: {
329
+ const timeValues = value ? removeEmpty(value?.split(' -')) : value;
330
+
331
+ console.table(await getTasksByDate(timeValues));
332
+
333
+ break;
334
+ }
335
+
336
+ case ACTIONS.TIME_ZOHO: {
337
+ console.log('Final status: ', await logTaskHoursAndSync());
338
+
339
+ break;
340
+ }
341
+
342
+ case ACTIONS.TIME_GITLAB: {
343
+ const timeValues = value ? removeEmpty(value?.split(' -')) : value;
344
+
345
+ await getGitlabActivities(timeValues);
346
+
347
+ break;
348
+ }
349
+
350
+ case ACTIONS.TIME_MERGE: {
351
+ const tasks = await getZohoTasks({ params: { type: ['2'] } });
352
+ const taskIds = tasks.reduce((acc, task) => {
353
+ if (task.gitlab_iid) {
354
+ acc.push({ taskId: task.taskId, gitlabIid: task.gitlab_iid });
355
+ }
356
+
357
+ return acc;
358
+ }, []);
359
+
360
+ if (!taskIds.length) {
361
+ console.log('No active tasks with GitLab IIDs found');
362
+ break;
363
+ }
364
+
365
+ const mergeRequests = await Promise.all(
366
+ taskIds.map(async ({ taskId, gitlabIid }) => {
367
+ try {
368
+ const response = await axios.get(
369
+ `${process.env.GITLAB_API_URL}/projects/${process.env.GITLAB_PROJECT_ID}/merge_requests/${gitlabIid}`,
370
+ {
371
+ headers: {
372
+ 'PRIVATE-TOKEN': process.env.GITLAB_TOKEN,
373
+ },
374
+ },
375
+ );
376
+ return {
377
+ taskId,
378
+ gitlabIid,
379
+ status: response.data.state,
380
+ assignee: response.data.assignee?.name || 'Unassigned',
381
+ title: response.data.title,
382
+ webUrl: response.data.web_url,
383
+ };
384
+ } catch (error) {
385
+ return {
386
+ taskId,
387
+ gitlabIid,
388
+ status: 'error',
389
+ error: error.response?.status === 404 ? 'MR not found' : 'Failed to fetch MR',
390
+ };
391
+ }
392
+ }),
393
+ );
394
+
395
+ console.table(
396
+ mergeRequests.map((mr) => ({
397
+ 'Task ID': mr.taskId,
398
+ 'MR IID': mr.gitlabIid,
399
+ Status: mr.status,
400
+ Assignee: mr.assignee || '-',
401
+ Title: mr.title || '-',
402
+ URL: mr.webUrl || '-',
403
+ Error: mr.error || '-',
404
+ })),
405
+ );
255
406
 
256
407
  break;
257
408
  }
@@ -260,30 +411,48 @@ Note: This operation cannot be undone. Make sure you have pushed any important c
260
411
  console.log(`usage: nitor \t[${ACTIONS.VERSION}] [${ACTIONS.HELP}]
261
412
  \t[${ACTIONS.BUILD}] [${ACTIONS.DEPLOY}] [${ACTIONS.BUILD_DEPLOY}]
262
413
  \t[${ACTIONS.CREATE_BRANCH}] [${ACTIONS.REVIEW}] [${ACTIONS.MERGE}]
263
- \t[${ACTIONS.CLEANUP}]\n
414
+ \t[${ACTIONS.CLEANUP}] [${ACTIONS.BACKUP}] [${ACTIONS.REFACTOR}]
415
+ \t[${ACTIONS.TIME_INIT}] [${ACTIONS.TIME_ADD}] [${ACTIONS.TIME_STATUS}]\n
264
416
  Available commands:\n
417
+ backup : Backup MongoDB databases
265
418
  build : Build specified components
266
- deploy : Deploy specified components
267
419
  build-deploy : Build and then deploy
420
+ cleanup : Cleanup local git branches (checkout to master and delete all other branches)
421
+ completion : Setup shell autocomplete
268
422
  create-branch : Create git branch
269
- review : AI Review specified merge request
270
- refactor : REFACTOR the provided text for improved clarity, conciseness, and professional quality.
423
+ deploy : Deploy specified components
271
424
  merge : Merge source branch into target branch
272
- cleanup : Cleanup local git branches (checkout to master and delete all other branches)
425
+ refactor : Refactor the provided text for improved clarity, conciseness, and professional quality
426
+ review : AI Review specified merge request
273
427
  version : Show version info
274
428
  help : Show help
275
429
 
430
+ Time Entry commands:
431
+ time-init : Initialize time entry configuration
432
+ time-add : Add time entry
433
+ time-delete : Delete time entry
434
+ time-entries : View time entries by date
435
+ time-gitlab : Get GitLab activities
436
+ time-merge : View merge request status for tasks
437
+ time-stats : View daily status of time entries
438
+ time-switch : Switch between default projects
439
+ time-update : Update existing time entry
440
+ time-zoho : Sync time entries to Zoho
441
+
276
442
  For details of each actions run 'nitor <action> -help'
277
443
 
278
444
  Example usage:\n
279
445
  nitor build -project <project> -components <components> -instance <instance>
280
- nitor deploy -project <project> -components <components> -instance <instance>
281
446
  nitor build-deploy -project <project> -components <components> -instance <instance>
447
+ nitor cleanup
282
448
  nitor create-branch -task <task number> -type <feat|fix> -description <description> -project <project short name>
283
- nitor review -project <project short name> -mergeId <merge id> -repository <repository name>
284
- nitor refactor <text>
449
+ nitor deploy -project <project> -components <components> -instance <instance>
285
450
  nitor merge -source <source branch> -target <target branch>
286
- nitor cleanup
451
+ nitor refactor <text>
452
+ nitor review -project <project short name> -mergeId <merge id> -repository <repository name>
453
+ nitor time-init
454
+ nitor time-add
455
+ nitor time-stats
287
456
 
288
457
  Running 'nitor help' will list available subcommands and provide some conceptual guides.`);
289
458
  break;
@@ -1,4 +1,4 @@
1
- const { gitlabToken, projectIdMap, mrPrompt, mrLang, mrApiUri } = require('./utils');
1
+ const { gitlabConfig, projectIdMap, mrPrompt, mrLang, mrApiUri } = require('./utils');
2
2
  const axios = require('axios');
3
3
 
4
4
  const executeMergeRequestReview = async (values) => {
@@ -9,7 +9,7 @@ const executeMergeRequestReview = async (values) => {
9
9
  headers: { 'Content-Type': 'application/json' },
10
10
  data: JSON.stringify({
11
11
  language: mrLang,
12
- gitlabToken,
12
+ gitlabToken: gitlabConfig.token,
13
13
  llmModel: 'claude',
14
14
  prompt: mrPrompt,
15
15
  }),
@@ -0,0 +1,50 @@
1
+ const path = require('path');
2
+ const {
3
+ contentTableHeading,
4
+ contentTableSeparator,
5
+ convertToTaskData,
6
+ readFileSync,
7
+ accessFileSync,
8
+ writeFileSync,
9
+ userHomeDir,
10
+ appendFileSync,
11
+ } = require('./utils');
12
+ const checkDateEntry = async (date, entryContent) => {
13
+ const isExists = { file: false, entry: false };
14
+
15
+ try {
16
+ if (accessFileSync(path.join(userHomeDir, `.${date}`))) {
17
+ const entries = readFileSync(path.join(userHomeDir, `.${date}`));
18
+
19
+ isExists.file = entries.includes(`### ${date}`);
20
+ isExists.entry = entries.includes(entryContent);
21
+ }
22
+
23
+ return isExists;
24
+ } catch {
25
+ return isExists;
26
+ }
27
+ };
28
+ const addNewTask = async (values) => {
29
+ const { project, sprint, task, date, work, duration, remarks } = await convertToTaskData(values);
30
+
31
+ try {
32
+ const entryHeading = `---\ntags: [Time entry task]\ntitle: ${date}\ncreated: ${new Date().toISOString()}\n---\n\n### ${date}\n${contentTableHeading}\n${contentTableSeparator}`;
33
+ const entryContent = `\n| ${new Date().getTime()} | ${project} | ${sprint} | ${date} | ${task} | ${work} | ${duration} | ${remarks} | false |`;
34
+ const isExists = await checkDateEntry(date, entryContent);
35
+
36
+ if (isExists.file && isExists.entry) {
37
+ console.log('Same entry already exists');
38
+ } else if (isExists.file && !isExists.entry) {
39
+ console.log('New entry added');
40
+ appendFileSync(path.join(userHomeDir, `.${date}`), `${entryContent}`);
41
+ } else {
42
+ console.log('New entry added');
43
+ writeFileSync(path.join(userHomeDir, `.${date}`), `${entryHeading}${entryContent}`);
44
+ }
45
+ } catch (error) {
46
+ console.log(error);
47
+ }
48
+ };
49
+
50
+ module.exports = { addNewTask };
@@ -0,0 +1,16 @@
1
+ module.exports = {
2
+ ACTIONS: {
3
+ INIT: 'init',
4
+ SWITCH: 'switch',
5
+ ADD: 'add',
6
+ UPDATE: 'update',
7
+ DELETE: 'delete',
8
+ STATUS: 'status',
9
+ ENTRIES: 'entries',
10
+ ZOHO: 'zoho',
11
+ GITLAB: 'gitlab',
12
+ MERGE: 'merge',
13
+ VERSION: 'version',
14
+ HELP: 'help',
15
+ },
16
+ };