@capraconsulting/cals-cli 3.6.0 → 3.7.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.
@@ -1,74 +1,32 @@
1
1
  #!/usr/bin/env node
2
- 'use strict';
2
+ import semver from 'semver';
3
+ import yargs from 'yargs';
4
+ import { hideBin } from 'yargs/helpers';
5
+ import fs from 'fs';
6
+ import yaml from 'js-yaml';
7
+ import { uniq, keyBy, sortBy, groupBy, sumBy, repeat } from 'lodash-es';
8
+ import pMap from 'p-map';
9
+ import AJV from 'ajv';
10
+ import { Octokit } from '@octokit/rest';
11
+ import fetch from 'node-fetch';
12
+ import pLimit from 'p-limit';
13
+ import keytar from 'keytar';
14
+ import * as process$2 from 'process';
15
+ import { performance } from 'perf_hooks';
16
+ import { deprecate } from 'util';
17
+ import path from 'path';
18
+ import rimraf from 'rimraf';
19
+ import cachedir from 'cachedir';
20
+ import https from 'https';
21
+ import os from 'os';
22
+ import chalk from 'chalk';
23
+ import readline from 'readline';
24
+ import { sprintf } from 'sprintf-js';
25
+ import read from 'read';
26
+ import findUp from 'find-up';
27
+ import execa from 'execa';
3
28
 
4
- var semver = require('semver');
5
- var yargs = require('yargs');
6
- var fs = require('fs');
7
- var yaml = require('js-yaml');
8
- var lodash = require('lodash');
9
- var pMap = require('p-map');
10
- var AJV = require('ajv');
11
- var rest = require('@octokit/rest');
12
- var fetch = require('node-fetch');
13
- var pLimit = require('p-limit');
14
- var keytar = require('keytar');
15
- var process$2 = require('process');
16
- var perf_hooks = require('perf_hooks');
17
- var util = require('util');
18
- var path = require('path');
19
- var rimraf = require('rimraf');
20
- var cachedir = require('cachedir');
21
- var https = require('https');
22
- var os = require('os');
23
- var chalk = require('chalk');
24
- var readline = require('readline');
25
- var sprintfJs = require('sprintf-js');
26
- var read = require('read');
27
- var findUp = require('find-up');
28
- var execa = require('execa');
29
-
30
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
31
-
32
- function _interopNamespace(e) {
33
- if (e && e.__esModule) return e;
34
- var n = Object.create(null);
35
- if (e) {
36
- Object.keys(e).forEach(function (k) {
37
- if (k !== 'default') {
38
- var d = Object.getOwnPropertyDescriptor(e, k);
39
- Object.defineProperty(n, k, d.get ? d : {
40
- enumerable: true,
41
- get: function () { return e[k]; }
42
- });
43
- }
44
- });
45
- }
46
- n["default"] = e;
47
- return Object.freeze(n);
48
- }
49
-
50
- var semver__default = /*#__PURE__*/_interopDefaultLegacy(semver);
51
- var yargs__default = /*#__PURE__*/_interopDefaultLegacy(yargs);
52
- var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
53
- var yaml__default = /*#__PURE__*/_interopDefaultLegacy(yaml);
54
- var pMap__default = /*#__PURE__*/_interopDefaultLegacy(pMap);
55
- var AJV__default = /*#__PURE__*/_interopDefaultLegacy(AJV);
56
- var fetch__default = /*#__PURE__*/_interopDefaultLegacy(fetch);
57
- var pLimit__default = /*#__PURE__*/_interopDefaultLegacy(pLimit);
58
- var keytar__default = /*#__PURE__*/_interopDefaultLegacy(keytar);
59
- var process__namespace = /*#__PURE__*/_interopNamespace(process$2);
60
- var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
61
- var rimraf__default = /*#__PURE__*/_interopDefaultLegacy(rimraf);
62
- var cachedir__default = /*#__PURE__*/_interopDefaultLegacy(cachedir);
63
- var https__default = /*#__PURE__*/_interopDefaultLegacy(https);
64
- var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
65
- var chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk);
66
- var readline__default = /*#__PURE__*/_interopDefaultLegacy(readline);
67
- var read__default = /*#__PURE__*/_interopDefaultLegacy(read);
68
- var findUp__default = /*#__PURE__*/_interopDefaultLegacy(findUp);
69
- var execa__default = /*#__PURE__*/_interopDefaultLegacy(execa);
70
-
71
- var version = "3.6.0";
29
+ var version = "3.7.1";
72
30
  var engines = {
73
31
  node: ">=12.0.0"
74
32
  };
@@ -374,12 +332,11 @@ function getRepoId(orgName, repoName) {
374
332
  return `${orgName}/${repoName}`;
375
333
  }
376
334
  function checkAgainstSchema(value) {
377
- var _a;
378
- const ajv = new AJV__default["default"]({ allErrors: true });
335
+ const ajv = new AJV({ allErrors: true });
379
336
  const valid = ajv.validate(schema, value);
380
337
  return valid
381
338
  ? { definition: value }
382
- : { error: (_a = ajv.errorsText()) !== null && _a !== void 0 ? _a : "Unknown error" };
339
+ : { error: ajv.errorsText() ?? "Unknown error" };
383
340
  }
384
341
  function requireValidDefinition(definition) {
385
342
  // Verify no duplicates in users and extract known logins.
@@ -424,7 +381,8 @@ function requireValidDefinition(definition) {
424
381
  if (!teamIdList.includes(id)) {
425
382
  throw new Error(`Project team ${id} in project ${project.name} is not registered in team list`);
426
383
  }
427
- });
384
+ }) // Verify repo teams exists as teams.
385
+ ;
428
386
  (org.repos || []).forEach((repo) => {
429
387
  (repo.teams || []).forEach((team) => {
430
388
  const id = getTeamId(org.organization, team.name);
@@ -448,11 +406,12 @@ function requireValidDefinition(definition) {
448
406
  }, []);
449
407
  }
450
408
  class DefinitionFile {
409
+ path;
451
410
  constructor(path) {
452
411
  this.path = path;
453
412
  }
454
413
  async getContents() {
455
- return new Promise((resolve, reject) => fs__default["default"].readFile(this.path, "utf-8", (err, data) => {
414
+ return new Promise((resolve, reject) => fs.readFile(this.path, "utf-8", (err, data) => {
456
415
  if (err)
457
416
  reject(err);
458
417
  else
@@ -464,7 +423,7 @@ class DefinitionFile {
464
423
  }
465
424
  }
466
425
  function parseDefinition(value) {
467
- const result = checkAgainstSchema(yaml__default["default"].load(value));
426
+ const result = checkAgainstSchema(yaml.load(value));
468
427
  if ("error" in result) {
469
428
  throw new Error("Definition content invalid: " + result.error);
470
429
  }
@@ -482,19 +441,17 @@ function getRepos(definition) {
482
441
  .flat());
483
442
  }
484
443
  function getGitHubOrgs(definition) {
485
- return lodash.uniq(definition.projects.flatMap((project) => project.github.map((it) => it.organization)));
444
+ return uniq(definition.projects.flatMap((project) => project.github.map((it) => it.organization)));
486
445
  }
487
446
 
488
447
  class GitHubTokenCliProvider {
489
- constructor() {
490
- this.keyringService = "cals";
491
- this.keyringAccount = "github-token";
492
- }
448
+ keyringService = "cals";
449
+ keyringAccount = "github-token";
493
450
  async getToken() {
494
451
  if (process.env.CALS_GITHUB_TOKEN) {
495
452
  return process.env.CALS_GITHUB_TOKEN;
496
453
  }
497
- const result = await keytar__default["default"].getPassword(this.keyringService, this.keyringAccount);
454
+ const result = await keytar.getPassword(this.keyringService, this.keyringAccount);
498
455
  if (result == null) {
499
456
  process.stderr.write("No token found. Register using `cals github set-token`\n");
500
457
  return undefined;
@@ -502,10 +459,10 @@ class GitHubTokenCliProvider {
502
459
  return result;
503
460
  }
504
461
  async markInvalid() {
505
- await keytar__default["default"].deletePassword(this.keyringService, this.keyringAccount);
462
+ await keytar.deletePassword(this.keyringService, this.keyringAccount);
506
463
  }
507
464
  async setToken(value) {
508
- await keytar__default["default"].setPassword(this.keyringService, this.keyringAccount, value);
465
+ await keytar.setPassword(this.keyringService, this.keyringAccount, value);
509
466
  }
510
467
  }
511
468
 
@@ -570,15 +527,19 @@ async function undefinedForNotFound(value) {
570
527
  }
571
528
 
572
529
  class GitHubService {
530
+ config;
531
+ octokit;
532
+ cache;
533
+ tokenProvider;
534
+ semaphore;
573
535
  constructor(props) {
574
- this._requestCount = 0;
575
536
  this.config = props.config;
576
537
  this.octokit = props.octokit;
577
538
  this.cache = props.cache;
578
539
  this.tokenProvider = props.tokenProvider;
579
540
  // Control concurrency to GitHub API at service level so we
580
541
  // can maximize concurrency all other places.
581
- this.semaphore = pLimit__default["default"](6);
542
+ this.semaphore = pLimit(6);
582
543
  this.octokit.hook.wrap("request", async (request, options) => {
583
544
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
584
545
  this._requestCount++;
@@ -644,6 +605,7 @@ class GitHubService {
644
605
  /* eslint-enable @typescript-eslint/no-unsafe-member-access */
645
606
  });
646
607
  }
608
+ _requestCount = 0;
647
609
  get requestCount() {
648
610
  return this._requestCount;
649
611
  }
@@ -658,18 +620,18 @@ class GitHubService {
658
620
  };
659
621
  let requestDuration = -1;
660
622
  const response = await this.semaphore(() => {
661
- const requestStart = perf_hooks.performance.now();
662
- const result = fetch__default["default"](url, {
623
+ const requestStart = performance.now();
624
+ const result = fetch(url, {
663
625
  method: "POST",
664
626
  headers,
665
627
  body: JSON.stringify({ query }),
666
628
  agent: this.config.agent,
667
629
  });
668
- requestDuration = perf_hooks.performance.now() - requestStart;
630
+ requestDuration = performance.now() - requestStart;
669
631
  return result;
670
632
  });
671
633
  if (response.status === 401) {
672
- process__namespace.stderr.write("Unauthorized\n");
634
+ process$2.stderr.write("Unauthorized\n");
673
635
  await this.tokenProvider.markInvalid();
674
636
  }
675
637
  // If you get 502 after 10s, it is a timeout.
@@ -762,15 +724,12 @@ class GitHubService {
762
724
  login: it.login,
763
725
  data: it,
764
726
  })),
765
- ...(await this.getOrgMembersInvitedList(org)).map((it) => {
766
- var _a;
767
- return ({
768
- type: "invited",
769
- // TODO: Fix ?? case properly
770
- login: (_a = it.login) !== null && _a !== void 0 ? _a : "invalid",
771
- data: it,
772
- });
773
- }),
727
+ ...(await this.getOrgMembersInvitedList(org)).map((it) => ({
728
+ type: "invited",
729
+ // TODO: Fix ?? case properly
730
+ login: it.login ?? "invalid",
731
+ data: it,
732
+ })),
774
733
  ];
775
734
  }
776
735
  async getRepository(owner, repo) {
@@ -839,15 +798,12 @@ class GitHubService {
839
798
  login: it.login,
840
799
  data: it,
841
800
  })),
842
- ...(await this.getTeamMemberInvitedList(org, team)).map((it) => {
843
- var _a;
844
- return ({
845
- type: "invited",
846
- // TODO: Fix ?? case properly
847
- login: (_a = it.login) !== null && _a !== void 0 ? _a : "invalid",
848
- data: it,
849
- });
850
- }),
801
+ ...(await this.getTeamMemberInvitedList(org, team)).map((it) => ({
802
+ type: "invited",
803
+ // TODO: Fix ?? case properly
804
+ login: it.login ?? "invalid",
805
+ data: it,
806
+ })),
851
807
  ];
852
808
  }
853
809
  async getSearchedPullRequestList(owner) {
@@ -972,17 +928,16 @@ class GitHubService {
972
928
  }
973
929
  }`;
974
930
  return this.cache.json(`vulnerability-alerts-${owner}-${repo}`, async () => {
975
- var _a, _b, _c, _d, _e;
976
931
  const result = [];
977
932
  let after = null;
978
933
  while (true) {
979
934
  const query = getQuery(after);
980
935
  const res = await this.runGraphqlQuery(query);
981
- result.push(...((_c = (_b = (_a = res.repository) === null || _a === void 0 ? void 0 : _a.vulnerabilityAlerts.edges) === null || _b === void 0 ? void 0 : _b.map((it) => it.node)) !== null && _c !== void 0 ? _c : []));
982
- if (!((_d = res.repository) === null || _d === void 0 ? void 0 : _d.vulnerabilityAlerts.pageInfo.hasNextPage)) {
936
+ result.push(...(res.repository?.vulnerabilityAlerts.edges?.map((it) => it.node) ?? []));
937
+ if (!res.repository?.vulnerabilityAlerts.pageInfo.hasNextPage) {
983
938
  break;
984
939
  }
985
- after = (_e = res.repository) === null || _e === void 0 ? void 0 : _e.vulnerabilityAlerts.pageInfo.endCursor;
940
+ after = res.repository?.vulnerabilityAlerts.pageInfo.endCursor;
986
941
  }
987
942
  return result;
988
943
  });
@@ -1024,27 +979,23 @@ class GitHubService {
1024
979
  }
1025
980
  }`;
1026
981
  const issues = await this.cache.json(`renovate-bot-issues-${owner}-${repo}`, async () => {
1027
- var _a, _b, _c, _d, _e;
1028
982
  const result = [];
1029
983
  let after = null;
1030
984
  while (true) {
1031
985
  const query = getQuery(after);
1032
986
  const res = await this.runGraphqlQuery(query);
1033
- const nodes = (_c = (_b = (_a = res.repository) === null || _a === void 0 ? void 0 : _a.issues.edges) === null || _b === void 0 ? void 0 : _b.map((it) => it.node)) !== null && _c !== void 0 ? _c : [];
987
+ const nodes = res.repository?.issues.edges?.map((it) => it.node) ?? [];
1034
988
  result.push(...nodes
1035
989
  .filter((it) => it.title === "Dependency Dashboard")
1036
- .map((it) => {
1037
- var _a, _b, _c, _d, _e;
1038
- return ({
1039
- number: it.number,
1040
- body: it.body,
1041
- lastUpdatedByRenovate: (_e = (_d = (_c = (_b = (_a = it.userContentEdits) === null || _a === void 0 ? void 0 : _a.nodes) === null || _b === void 0 ? void 0 : _b.filter((it) => { var _a; return ((_a = it.editor) === null || _a === void 0 ? void 0 : _a.login) === "renovate"; })) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.createdAt) !== null && _e !== void 0 ? _e : null,
1042
- });
1043
- }));
1044
- if (!((_d = res.repository) === null || _d === void 0 ? void 0 : _d.issues.pageInfo.hasNextPage)) {
990
+ .map((it) => ({
991
+ number: it.number,
992
+ body: it.body,
993
+ lastUpdatedByRenovate: it.userContentEdits?.nodes?.filter((it) => it.editor?.login === "renovate")?.[0]?.createdAt ?? null,
994
+ })));
995
+ if (!res.repository?.issues.pageInfo.hasNextPage) {
1045
996
  break;
1046
997
  }
1047
- after = (_e = res.repository) === null || _e === void 0 ? void 0 : _e.issues.pageInfo.endCursor;
998
+ after = res.repository?.issues.pageInfo.endCursor;
1048
999
  }
1049
1000
  return result;
1050
1001
  });
@@ -1055,7 +1006,7 @@ class GitHubService {
1055
1006
  }
1056
1007
  }
1057
1008
  async function createOctokit(config, tokenProvider) {
1058
- return new rest.Octokit({
1009
+ return new Octokit({
1059
1010
  auth: await tokenProvider.getToken(),
1060
1011
  request: {
1061
1012
  agent: config.agent,
@@ -1063,8 +1014,7 @@ async function createOctokit(config, tokenProvider) {
1063
1014
  });
1064
1015
  }
1065
1016
  async function createGitHubService(props) {
1066
- var _a;
1067
- const tokenProvider = (_a = props.tokenProvider) !== null && _a !== void 0 ? _a : new GitHubTokenCliProvider();
1017
+ const tokenProvider = props.tokenProvider ?? new GitHubTokenCliProvider();
1068
1018
  return new GitHubService({
1069
1019
  config: props.config,
1070
1020
  octokit: await createOctokit(props.config, tokenProvider),
@@ -1074,15 +1024,13 @@ async function createGitHubService(props) {
1074
1024
  }
1075
1025
 
1076
1026
  class SnykTokenCliProvider {
1077
- constructor() {
1078
- this.keyringService = "cals";
1079
- this.keyringAccount = "snyk-token";
1080
- }
1027
+ keyringService = "cals";
1028
+ keyringAccount = "snyk-token";
1081
1029
  async getToken() {
1082
1030
  if (process.env.CALS_SNYK_TOKEN) {
1083
1031
  return process.env.CALS_SNYK_TOKEN;
1084
1032
  }
1085
- const result = await keytar__default["default"].getPassword(this.keyringService, this.keyringAccount);
1033
+ const result = await keytar.getPassword(this.keyringService, this.keyringAccount);
1086
1034
  if (result == null) {
1087
1035
  process.stderr.write("No token found. Register using `cals snyk set-token`\n");
1088
1036
  return undefined;
@@ -1090,21 +1038,22 @@ class SnykTokenCliProvider {
1090
1038
  return result;
1091
1039
  }
1092
1040
  async markInvalid() {
1093
- await keytar__default["default"].deletePassword(this.keyringService, this.keyringAccount);
1041
+ await keytar.deletePassword(this.keyringService, this.keyringAccount);
1094
1042
  }
1095
1043
  async setToken(value) {
1096
- await keytar__default["default"].setPassword(this.keyringService, this.keyringAccount, value);
1044
+ await keytar.setPassword(this.keyringService, this.keyringAccount, value);
1097
1045
  }
1098
1046
  }
1099
1047
 
1100
1048
  class SnykService {
1049
+ config;
1050
+ tokenProvider;
1101
1051
  constructor(props) {
1102
1052
  this.config = props.config;
1103
1053
  this.tokenProvider = props.tokenProvider;
1104
1054
  }
1105
1055
  async getProjects(definition) {
1106
- var _a;
1107
- const snykAccountId = (_a = definition.snyk) === null || _a === void 0 ? void 0 : _a.accountId;
1056
+ const snykAccountId = definition.snyk?.accountId;
1108
1057
  if (snykAccountId === undefined) {
1109
1058
  return [];
1110
1059
  }
@@ -1132,7 +1081,7 @@ class SnykService {
1132
1081
  * We continue calling the Snyk API and retrieving more projects until links.next is null
1133
1082
  * */
1134
1083
  while (nextUrl) {
1135
- const response = await fetch__default["default"](`https://api.snyk.io/rest${nextUrl}`, {
1084
+ const response = await fetch(`https://api.snyk.io/rest${nextUrl}`, {
1136
1085
  method: "GET",
1137
1086
  headers: {
1138
1087
  Accept: "application/json",
@@ -1169,7 +1118,7 @@ class SnykService {
1169
1118
  totalDependencies: project.meta.latest_dependency_total.total,
1170
1119
  issueCountsBySeverity: project.meta.latest_issue_counts,
1171
1120
  lastTestedDate: project.meta.latest_dependency_total.updated_at,
1172
- browseUrl: `https://app.snyk.io/org/${snykOrgSlugId !== null && snykOrgSlugId !== void 0 ? snykOrgSlugId : "it"}/project/${project.id}`,
1121
+ browseUrl: `https://app.snyk.io/org/${snykOrgSlugId ?? "it"}/project/${project.id}`,
1173
1122
  };
1174
1123
  }),
1175
1124
  ];
@@ -1181,10 +1130,9 @@ class SnykService {
1181
1130
  }
1182
1131
  }
1183
1132
  function createSnykService(props) {
1184
- var _a;
1185
1133
  return new SnykService({
1186
1134
  config: props.config,
1187
- tokenProvider: (_a = props.tokenProvider) !== null && _a !== void 0 ? _a : new SnykTokenCliProvider(),
1135
+ tokenProvider: props.tokenProvider ?? new SnykTokenCliProvider(),
1188
1136
  });
1189
1137
  }
1190
1138
 
@@ -1222,23 +1170,24 @@ function getGitHubRepoId(repo) {
1222
1170
 
1223
1171
  class CacheProvider {
1224
1172
  constructor(config) {
1225
- this.mustValidate = false;
1226
- this.defaultCacheTime = 1800;
1227
1173
  this.config = config;
1228
1174
  }
1175
+ mustValidate = false;
1176
+ config;
1177
+ defaultCacheTime = 1800;
1229
1178
  /**
1230
1179
  * Retrieve cache if existent, ignoring the time.
1231
1180
  *
1232
1181
  * The caller is responsible for handling proper validation,
1233
1182
  */
1234
1183
  retrieveJson(cachekey) {
1235
- const cachefile = path__default["default"].join(this.config.cacheDir, `${cachekey}.json`);
1236
- if (!fs__default["default"].existsSync(cachefile)) {
1184
+ const cachefile = path.join(this.config.cacheDir, `${cachekey}.json`);
1185
+ if (!fs.existsSync(cachefile)) {
1237
1186
  return undefined;
1238
1187
  }
1239
- const data = fs__default["default"].readFileSync(cachefile, "utf-8");
1188
+ const data = fs.readFileSync(cachefile, "utf-8");
1240
1189
  return {
1241
- cacheTime: fs__default["default"].statSync(cachefile).mtime.getTime(),
1190
+ cacheTime: fs.statSync(cachefile).mtime.getTime(),
1242
1191
  data: (data === "undefined" ? undefined : JSON.parse(data)),
1243
1192
  };
1244
1193
  }
@@ -1246,11 +1195,11 @@ class CacheProvider {
1246
1195
  * Save data to cache.
1247
1196
  */
1248
1197
  storeJson(cachekey, data) {
1249
- const cachefile = path__default["default"].join(this.config.cacheDir, `${cachekey}.json`);
1250
- if (!fs__default["default"].existsSync(this.config.cacheDir)) {
1251
- fs__default["default"].mkdirSync(this.config.cacheDir, { recursive: true });
1198
+ const cachefile = path.join(this.config.cacheDir, `${cachekey}.json`);
1199
+ if (!fs.existsSync(this.config.cacheDir)) {
1200
+ fs.mkdirSync(this.config.cacheDir, { recursive: true });
1252
1201
  }
1253
- fs__default["default"].writeFileSync(cachefile, data === undefined ? "undefined" : JSON.stringify(data));
1202
+ fs.writeFileSync(cachefile, data === undefined ? "undefined" : JSON.stringify(data));
1254
1203
  }
1255
1204
  async json(cachekey, block, cachetime = this.defaultCacheTime) {
1256
1205
  const cacheItem = this.mustValidate
@@ -1268,20 +1217,18 @@ class CacheProvider {
1268
1217
  * Delete all cached data.
1269
1218
  */
1270
1219
  cleanup() {
1271
- rimraf__default["default"].sync(this.config.cacheDir);
1220
+ rimraf.sync(this.config.cacheDir);
1272
1221
  }
1273
1222
  }
1274
1223
 
1275
1224
  class Config {
1276
- constructor() {
1277
- this.cwd = path__default["default"].resolve(process.cwd());
1278
- this.configFile = path__default["default"].join(os__default["default"].homedir(), ".cals-config.json");
1279
- this.cacheDir = cachedir__default["default"]("cals-cli");
1280
- this.agent = new https__default["default"].Agent({
1281
- keepAlive: true,
1282
- });
1283
- this.configCached = undefined;
1284
- }
1225
+ cwd = path.resolve(process.cwd());
1226
+ configFile = path.join(os.homedir(), ".cals-config.json");
1227
+ cacheDir = cachedir("cals-cli");
1228
+ agent = new https.Agent({
1229
+ keepAlive: true,
1230
+ });
1231
+ configCached = undefined;
1285
1232
  get config() {
1286
1233
  const existingConfig = this.configCached;
1287
1234
  if (existingConfig !== undefined) {
@@ -1292,12 +1239,12 @@ class Config {
1292
1239
  return config;
1293
1240
  }
1294
1241
  readConfig() {
1295
- if (!fs__default["default"].existsSync(this.configFile)) {
1242
+ if (!fs.existsSync(this.configFile)) {
1296
1243
  return {};
1297
1244
  }
1298
1245
  try {
1299
1246
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
1300
- return JSON.parse(fs__default["default"].readFileSync(this.configFile, "utf-8"));
1247
+ return JSON.parse(fs.readFileSync(this.configFile, "utf-8"));
1301
1248
  }
1302
1249
  catch (e) {
1303
1250
  console.error("Failed", e);
@@ -1319,27 +1266,29 @@ class Config {
1319
1266
  ...this.readConfig(),
1320
1267
  [key]: value, // undefined will remove
1321
1268
  };
1322
- fs__default["default"].writeFileSync(this.configFile, JSON.stringify(updatedConfig, null, " "));
1269
+ fs.writeFileSync(this.configFile, JSON.stringify(updatedConfig, null, " "));
1323
1270
  this.configCached = updatedConfig;
1324
1271
  }
1325
1272
  }
1326
1273
 
1327
1274
  const CLEAR_WHOLE_LINE = 0;
1328
1275
  function clearLine(stdout) {
1329
- readline__default["default"].clearLine(stdout, CLEAR_WHOLE_LINE);
1330
- readline__default["default"].cursorTo(stdout, 0);
1276
+ readline.clearLine(stdout, CLEAR_WHOLE_LINE);
1277
+ readline.cursorTo(stdout, 0);
1331
1278
  }
1332
1279
  class Reporter {
1333
1280
  constructor(opts = {}) {
1334
- this.stdout = process.stdout;
1335
- this.stderr = process.stderr;
1336
- this.stdin = process.stdin;
1337
- this.isTTY = this.stdout.isTTY;
1338
- this.format = chalk__default["default"];
1339
- this.startTime = Date.now();
1340
1281
  this.nonInteractive = !!opts.nonInteractive;
1341
1282
  this.isVerbose = !!opts.verbose;
1342
1283
  }
1284
+ stdout = process.stdout;
1285
+ stderr = process.stderr;
1286
+ stdin = process.stdin;
1287
+ isTTY = this.stdout.isTTY;
1288
+ nonInteractive;
1289
+ isVerbose;
1290
+ format = chalk;
1291
+ startTime = Date.now();
1343
1292
  error(msg) {
1344
1293
  clearLine(this.stderr);
1345
1294
  this.stderr.write(`${this.format.red("error")} ${msg}\n`);
@@ -1376,7 +1325,7 @@ function createCacheProvider(config, argv) {
1376
1325
  }
1377
1326
  // old option: --no-cache
1378
1327
  if (argv.cache === false) {
1379
- util.deprecate(() => {
1328
+ deprecate(() => {
1380
1329
  cache.mustValidate = true;
1381
1330
  }, "The --no-cache option is deprecated. See new --validate-cache option")();
1382
1331
  }
@@ -1396,7 +1345,7 @@ function getDefinitionFile(argv) {
1396
1345
  throw Error("Missing --definition-file option");
1397
1346
  }
1398
1347
  const definitionFile = argv.definitionFile;
1399
- if (!fs__default["default"].existsSync(definitionFile)) {
1348
+ if (!fs.existsSync(definitionFile)) {
1400
1349
  throw Error(`The file ${definitionFile} does not exist`);
1401
1350
  }
1402
1351
  return new DefinitionFile(definitionFile);
@@ -1453,9 +1402,9 @@ function reorderListToSimilarAsBefore(oldList, updatedList, selector, insertLast
1453
1402
  }
1454
1403
 
1455
1404
  async function getReposFromGitHub(github, orgs) {
1456
- return (await pMap__default["default"](orgs, async (org) => {
1405
+ return (await pMap(orgs, async (org) => {
1457
1406
  const repos = await github.getOrgRepoList({ org: org.login });
1458
- return pMap__default["default"](repos, async (repo) => {
1407
+ return pMap(repos, async (repo) => {
1459
1408
  const detailedRepo = await github.getRepository(repo.owner.login, repo.name);
1460
1409
  if (detailedRepo === undefined) {
1461
1410
  throw Error(`Repo not found: ${repo.owner.login}/${repo.name}`);
@@ -1469,11 +1418,11 @@ async function getReposFromGitHub(github, orgs) {
1469
1418
  })).flat();
1470
1419
  }
1471
1420
  async function getTeams(github, orgs) {
1472
- const intermediate = await pMap__default["default"](orgs, async (org) => {
1421
+ const intermediate = await pMap(orgs, async (org) => {
1473
1422
  const teams = await github.getTeamList(org);
1474
1423
  return {
1475
1424
  org,
1476
- teams: await pMap__default["default"](teams, async (team) => ({
1425
+ teams: await pMap(teams, async (team) => ({
1477
1426
  team,
1478
1427
  users: await github.getTeamMemberListIncludingInvited(org, team),
1479
1428
  })),
@@ -1502,11 +1451,11 @@ function getFormattedTeams(oldTeams, teams) {
1502
1451
  permission: it.permission,
1503
1452
  }));
1504
1453
  return result
1505
- ? reorderListToSimilarAsBefore(oldTeams !== null && oldTeams !== void 0 ? oldTeams : [], result, (it) => it.name)
1454
+ ? reorderListToSimilarAsBefore(oldTeams ?? [], result, (it) => it.name)
1506
1455
  : undefined;
1507
1456
  }
1508
1457
  async function getOrgs(github, orgs) {
1509
- return pMap__default["default"](orgs, (it) => github.getOrg(it));
1458
+ return pMap(orgs, (it) => github.getOrg(it));
1510
1459
  }
1511
1460
  function removeDuplicates(items, selector) {
1512
1461
  const ids = [];
@@ -1521,7 +1470,7 @@ function removeDuplicates(items, selector) {
1521
1470
  return result;
1522
1471
  }
1523
1472
  async function getMembers(github, orgs) {
1524
- return removeDuplicates((await pMap__default["default"](orgs, (org) => github.getOrgMembersListIncludingInvited(org.login)))
1473
+ return removeDuplicates((await pMap(orgs, (org) => github.getOrgMembersListIncludingInvited(org.login)))
1525
1474
  .flat()
1526
1475
  .map((it) => it.login), (it) => it);
1527
1476
  }
@@ -1535,15 +1484,14 @@ async function getProjects(github, orgs, definition, snyk) {
1535
1484
  const snykReposPromise = getSnykRepos(snyk, definition);
1536
1485
  const repos = await getReposFromGitHub(github, orgs);
1537
1486
  const snykRepos = await snykReposPromise;
1538
- const definitionRepos = lodash.keyBy(getRepos(definition), (it) => it.id);
1487
+ const definitionRepos = keyBy(getRepos(definition), (it) => it.id);
1539
1488
  const projectGroups = Object.values(repos.reduce((acc, cur) => {
1540
- var _a, _b, _c, _d;
1541
1489
  const org = cur.repository.owner.login;
1542
1490
  const repoId = getRepoId(org, cur.repository.name);
1543
- const projectName = (_c = (_b = (_a = definitionRepos[repoId]) === null || _a === void 0 ? void 0 : _a.project) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : "Unknown";
1491
+ const projectName = definitionRepos[repoId]?.project?.name ?? "Unknown";
1544
1492
  const project = acc[projectName] || {
1545
1493
  name: projectName,
1546
- definition: (_d = definitionRepos[repoId]) === null || _d === void 0 ? void 0 : _d.project,
1494
+ definition: definitionRepos[repoId]?.project,
1547
1495
  repos: [],
1548
1496
  };
1549
1497
  return {
@@ -1558,39 +1506,36 @@ async function getProjects(github, orgs, definition, snyk) {
1558
1506
  };
1559
1507
  }, {}));
1560
1508
  const projects = projectGroups.map((project) => {
1561
- var _a, _b;
1562
1509
  const github = Object.entries(project.repos).map(([org, list]) => {
1563
- var _a, _b, _c, _d;
1564
1510
  const commonTeams = getCommonTeams(list);
1565
- const oldOrg = (_b = (_a = project.definition) === null || _a === void 0 ? void 0 : _a.github) === null || _b === void 0 ? void 0 : _b.find((it) => it.organization == org);
1511
+ const oldOrg = project.definition?.github?.find((it) => it.organization == org);
1566
1512
  const repos = list.map((repo) => {
1567
- var _a, _b;
1568
1513
  const repoId = getRepoId(repo.basic.owner.login, repo.basic.name);
1569
1514
  const definitionRepo = definitionRepos[repoId];
1570
1515
  const result = {
1571
1516
  name: repo.basic.name,
1572
- previousNames: definitionRepo === null || definitionRepo === void 0 ? void 0 : definitionRepo.repo.previousNames,
1517
+ previousNames: definitionRepo?.repo.previousNames,
1573
1518
  archived: repo.repository.archived ? true : undefined,
1574
1519
  issues: repo.repository.has_issues ? undefined : false,
1575
1520
  wiki: repo.repository.has_wiki ? undefined : false,
1576
- teams: getFormattedTeams((_b = (_a = definitionRepo === null || definitionRepo === void 0 ? void 0 : definitionRepo.repo) === null || _a === void 0 ? void 0 : _a.teams) !== null && _b !== void 0 ? _b : [], getSpecificTeams(repo.teams, commonTeams)),
1521
+ teams: getFormattedTeams(definitionRepo?.repo?.teams ?? [], getSpecificTeams(repo.teams, commonTeams)),
1577
1522
  snyk: snykRepos.includes(repoId) ? true : undefined,
1578
1523
  public: repo.repository.private ? undefined : true,
1579
- responsible: definitionRepo === null || definitionRepo === void 0 ? void 0 : definitionRepo.repo.responsible,
1524
+ responsible: definitionRepo?.repo.responsible,
1580
1525
  };
1581
1526
  // Try to preserve property order.
1582
1527
  return Object.fromEntries(reorderListToSimilarAsBefore(definitionRepo ? Object.entries(definitionRepo.repo) : [], Object.entries(result), (it) => it[0], true));
1583
1528
  });
1584
- const teams = getFormattedTeams((_c = oldOrg === null || oldOrg === void 0 ? void 0 : oldOrg.teams) !== null && _c !== void 0 ? _c : [], commonTeams);
1529
+ const teams = getFormattedTeams(oldOrg?.teams ?? [], commonTeams);
1585
1530
  return {
1586
1531
  organization: org,
1587
1532
  teams: teams,
1588
- repos: reorderListToSimilarAsBefore((_d = oldOrg === null || oldOrg === void 0 ? void 0 : oldOrg.repos) !== null && _d !== void 0 ? _d : [], repos, (it) => it.name),
1533
+ repos: reorderListToSimilarAsBefore(oldOrg?.repos ?? [], repos, (it) => it.name),
1589
1534
  };
1590
1535
  });
1591
1536
  return {
1592
1537
  name: project.name,
1593
- github: reorderListToSimilarAsBefore((_b = (_a = project.definition) === null || _a === void 0 ? void 0 : _a.github) !== null && _b !== void 0 ? _b : [], github, (it) => it.organization),
1538
+ github: reorderListToSimilarAsBefore(project.definition?.github ?? [], github, (it) => it.organization),
1594
1539
  };
1595
1540
  });
1596
1541
  return reorderListToSimilarAsBefore(definition.projects, projects, (it) => it.name);
@@ -1635,7 +1580,7 @@ async function dumpSetup(config, reporter, github, snyk, outfile, definitionFile
1635
1580
  // package. However it often produced invalid yaml, so we have removed
1636
1581
  // it. We might want to revisit it to preserve comments.
1637
1582
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-explicit-any
1638
- const doc = yaml__default["default"].load(await definitionFile.getContents());
1583
+ const doc = yaml.load(await definitionFile.getContents());
1639
1584
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
1640
1585
  doc.snyk = generatedDefinition.snyk;
1641
1586
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
@@ -1643,7 +1588,7 @@ async function dumpSetup(config, reporter, github, snyk, outfile, definitionFile
1643
1588
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
1644
1589
  doc.github = generatedDefinition.github;
1645
1590
  // Convert to/from plain JSON so that undefined elements are removed.
1646
- fs__default["default"].writeFileSync(outfile, yaml__default["default"].dump(JSON.parse(JSON.stringify(doc))));
1591
+ fs.writeFileSync(outfile, yaml.dump(JSON.parse(JSON.stringify(doc))));
1647
1592
  reporter.info(`Saved to ${outfile}`);
1648
1593
  reporter.info(`Number of GitHub requests: ${github.requestCount}`);
1649
1594
  }
@@ -1688,7 +1633,7 @@ const command$f = {
1688
1633
  .demandCommand()
1689
1634
  .usage(`cals definition`),
1690
1635
  handler: () => {
1691
- yargs__default["default"].showHelp();
1636
+ yargs(hideBin(process.argv)).showHelp();
1692
1637
  },
1693
1638
  };
1694
1639
 
@@ -1716,9 +1661,9 @@ const command$d = {
1716
1661
  async function analyzeDirectory(reporter, config, github, org) {
1717
1662
  const repos = await github.getOrgRepoList({ org });
1718
1663
  const reposDict = repos.reduce((acc, cur) => ({ ...acc, [cur.name]: cur }), {});
1719
- const dirs = fs__default["default"]
1664
+ const dirs = fs
1720
1665
  .readdirSync(config.cwd)
1721
- .filter((it) => fs__default["default"].statSync(path__default["default"].join(config.cwd, it)).isDirectory())
1666
+ .filter((it) => fs.statSync(path.join(config.cwd, it)).isDirectory())
1722
1667
  // Skip hidden folders
1723
1668
  .filter((it) => !it.startsWith("."))
1724
1669
  .sort((a, b) => a.localeCompare(b));
@@ -1729,18 +1674,18 @@ async function analyzeDirectory(reporter, config, github, org) {
1729
1674
  };
1730
1675
  dirs.forEach((it) => {
1731
1676
  if (!(it in reposDict)) {
1732
- reporter.warn(sprintfJs.sprintf("%-30s <-- Not found in repository list (maybe changed name?)", it));
1677
+ reporter.warn(sprintf("%-30s <-- Not found in repository list (maybe changed name?)", it));
1733
1678
  stats.unknown++;
1734
1679
  return;
1735
1680
  }
1736
1681
  if (reposDict[it].isArchived) {
1737
- reporter.info(sprintfJs.sprintf("%-30s <-- Archived", it));
1682
+ reporter.info(sprintf("%-30s <-- Archived", it));
1738
1683
  stats.archived++;
1739
1684
  return;
1740
1685
  }
1741
1686
  stats.ok += 1;
1742
1687
  });
1743
- reporter.info(sprintfJs.sprintf("Stats: unknown=%d archived=%d ok=%d", stats.unknown, stats.archived, stats.ok));
1688
+ reporter.info(sprintf("Stats: unknown=%d archived=%d ok=%d", stats.unknown, stats.archived, stats.ok));
1744
1689
  reporter.info("Use `cals github generate-clone-commands` to check for repositories not checked out");
1745
1690
  }
1746
1691
  const command$c = {
@@ -1763,7 +1708,6 @@ const command$c = {
1763
1708
  };
1764
1709
 
1765
1710
  function getChangedRepoAttribs(definitionRepo, actualRepo) {
1766
- var _a, _b;
1767
1711
  const attribs = [];
1768
1712
  const archived = definitionRepo.archived || false;
1769
1713
  if (archived !== actualRepo.archived) {
@@ -1771,13 +1715,13 @@ function getChangedRepoAttribs(definitionRepo, actualRepo) {
1771
1715
  archived,
1772
1716
  });
1773
1717
  }
1774
- const issues = (_a = definitionRepo.issues) !== null && _a !== void 0 ? _a : true;
1718
+ const issues = definitionRepo.issues ?? true;
1775
1719
  if (issues !== actualRepo.has_issues && !actualRepo.archived) {
1776
1720
  attribs.push({
1777
1721
  issues,
1778
1722
  });
1779
1723
  }
1780
- const wiki = (_b = definitionRepo.wiki) !== null && _b !== void 0 ? _b : true;
1724
+ const wiki = definitionRepo.wiki ?? true;
1781
1725
  if (wiki !== actualRepo.has_wiki && !actualRepo.archived) {
1782
1726
  attribs.push({
1783
1727
  wiki,
@@ -1794,7 +1738,7 @@ function getChangedRepoAttribs(definitionRepo, actualRepo) {
1794
1738
  async function getUnknownRepos(github, definition, limitToOrg) {
1795
1739
  const knownRepos = getRepos(definition).map((it) => it.id);
1796
1740
  const orgs = getGitHubOrgs(definition).filter((orgName) => limitToOrg === undefined || limitToOrg === orgName);
1797
- return lodash.sortBy((await pMap__default["default"](orgs, (orgName) => github.getOrgRepoList({ org: orgName })))
1741
+ return sortBy((await pMap(orgs, (orgName) => github.getOrgRepoList({ org: orgName })))
1798
1742
  .flat()
1799
1743
  .filter((it) => !knownRepos.includes(`${it.owner.login}/${it.name}`)), (it) => `${it.owner.login}/${it.name}`);
1800
1744
  }
@@ -1809,9 +1753,8 @@ function getExpectedTeams(projectTeams, repoTeams) {
1809
1753
  ];
1810
1754
  }
1811
1755
  async function getRepoTeamChanges({ github, org, projectRepo, repo, }) {
1812
- var _a, _b;
1813
1756
  const changes = [];
1814
- const expectedTeams = getExpectedTeams((_a = org.teams) !== null && _a !== void 0 ? _a : [], (_b = projectRepo.teams) !== null && _b !== void 0 ? _b : []);
1757
+ const expectedTeams = getExpectedTeams(org.teams ?? [], projectRepo.teams ?? []);
1815
1758
  const existingTeams = await github.getRepositoryTeamsList(repo);
1816
1759
  // Check for teams to be added / modified.
1817
1760
  for (const repoteam of expectedTeams) {
@@ -1889,7 +1832,7 @@ async function createChangeSetItemsForProjects(github, definition, limitToOrg) {
1889
1832
  const orgs = definition.projects
1890
1833
  .flatMap((it) => it.github)
1891
1834
  .filter((org) => limitToOrg === undefined || limitToOrg === org.organization);
1892
- changes.push(...(await pMap__default["default"](orgs, async (org) => pMap__default["default"](org.repos || [], (projectRepo) => getProjectRepoChanges({
1835
+ changes.push(...(await pMap(orgs, async (org) => pMap(org.repos || [], (projectRepo) => getProjectRepoChanges({
1893
1836
  github,
1894
1837
  org,
1895
1838
  projectRepo,
@@ -1987,7 +1930,7 @@ async function createChangeSetItemsForTeams(github, definition, org) {
1987
1930
  }
1988
1931
  });
1989
1932
  const overlappingTeams = actualTeams.filter((it) => wantedTeamNames.includes(it.name));
1990
- await pMap__default["default"](overlappingTeams, async (actualTeam) => {
1933
+ await pMap(overlappingTeams, async (actualTeam) => {
1991
1934
  const wantedTeam = teams.find((it) => it.name === actualTeam.name);
1992
1935
  const actualMembers = await github.getTeamMemberListIncludingInvited(org, actualTeam);
1993
1936
  actualMembers
@@ -2190,7 +2133,7 @@ function createOrgGetter(github) {
2190
2133
  const semaphores = {};
2191
2134
  function getSemaphore(orgName) {
2192
2135
  if (!(orgName in semaphores)) {
2193
- semaphores[orgName] = pLimit__default["default"](1);
2136
+ semaphores[orgName] = pLimit(1);
2194
2137
  }
2195
2138
  return semaphores[orgName];
2196
2139
  }
@@ -2247,7 +2190,7 @@ async function process$1(reporter, github, definition, getOrg, execute, limitToO
2247
2190
  }
2248
2191
  if (execute && changes.length > 0) {
2249
2192
  const cont = await new Promise((resolve, reject) => {
2250
- read__default["default"]({
2193
+ read({
2251
2194
  prompt: "Confirm you want to execute the changes [y/N]: ",
2252
2195
  timeout: 60000,
2253
2196
  }, (err, answer) => {
@@ -2298,7 +2241,7 @@ const command$b = {
2298
2241
 
2299
2242
  async function generateCloneCommands({ reporter, config, github, org, ...opt }) {
2300
2243
  if (!opt.listGroups && !opt.all && opt.group === undefined) {
2301
- yargs__default["default"].showHelp();
2244
+ yargs(hideBin(process.argv)).showHelp();
2302
2245
  return;
2303
2246
  }
2304
2247
  const repos = await github.getOrgRepoList({ org });
@@ -2318,11 +2261,11 @@ async function generateCloneCommands({ reporter, config, github, org, ...opt })
2318
2261
  .filter((it) => opt.name === undefined || it.name.includes(opt.name))
2319
2262
  .filter((it) => opt.topic === undefined || includesTopic(it, opt.topic))
2320
2263
  .filter((it) => !opt.excludeExisting ||
2321
- !fs__default["default"].existsSync(path__default["default"].resolve(config.cwd, it.name)))
2264
+ !fs.existsSync(path.resolve(config.cwd, it.name)))
2322
2265
  .forEach((repo) => {
2323
2266
  // The output of this is used to pipe into e.g. bash.
2324
2267
  // We cannot use reporter.log as it adds additional characters.
2325
- process.stdout.write(sprintfJs.sprintf('[ ! -e "%s" ] && git clone %s\n', repo.name, repo.sshUrl));
2268
+ process.stdout.write(sprintf('[ ! -e "%s" ] && git clone %s\n', repo.name, repo.sshUrl));
2326
2269
  });
2327
2270
  });
2328
2271
  }
@@ -2420,10 +2363,10 @@ async function listPullRequestsStats({ reporter, github, }) {
2420
2363
  reporter.log("Pull requests stats:");
2421
2364
  reporter.log("A pull request is considered old after 60 days");
2422
2365
  reporter.log("");
2423
- reporter.log(sprintfJs.sprintf("%-40s %12s %2s %12s %2s", "", "normal", "", "snyk", ""));
2424
- reporter.log(sprintfJs.sprintf("%-40s %7s %7s %7s %7s", "Repo", "old", "recent", "old", "recent"));
2366
+ reporter.log(sprintf("%-40s %12s %2s %12s %2s", "", "normal", "", "snyk", ""));
2367
+ reporter.log(sprintf("%-40s %7s %7s %7s %7s", "Repo", "old", "recent", "old", "recent"));
2425
2368
  categories.forEach((cat) => {
2426
- reporter.log(sprintfJs.sprintf("%-40s %7s %7s %7s %7s", cat.key, cat.old.length === 0 ? "" : cat.old.length, cat.recent.length === 0 ? "" : cat.recent.length, cat.oldSnyk.length === 0 ? "" : cat.oldSnyk.length, cat.recentSnyk.length === 0 ? "" : cat.recentSnyk.length));
2369
+ reporter.log(sprintf("%-40s %7s %7s %7s %7s", cat.key, cat.old.length === 0 ? "" : cat.old.length, cat.recent.length === 0 ? "" : cat.recent.length, cat.oldSnyk.length === 0 ? "" : cat.oldSnyk.length, cat.recentSnyk.length === 0 ? "" : cat.recentSnyk.length));
2427
2370
  });
2428
2371
  }
2429
2372
  }
@@ -2588,15 +2531,15 @@ async function listWebhooks(reporter, cache, github, org) {
2588
2531
  }
2589
2532
  switch (hook.name) {
2590
2533
  case "web":
2591
- reporter.log(sprintfJs.sprintf(" web: %s (%s) (%s)", hook.config.url, hook.last_response.code, hook.events.join(", ")));
2534
+ reporter.log(sprintf(" web: %s (%s) (%s)", hook.config.url, hook.last_response.code, hook.events.join(", ")));
2592
2535
  break;
2593
2536
  case "jenkinsgit":
2594
- reporter.log(sprintfJs.sprintf(" jenkinsgit: %s (%s) (%s)",
2537
+ reporter.log(sprintf(" jenkinsgit: %s (%s) (%s)",
2595
2538
  // This is undocumented.
2596
2539
  hook.config.jenkins_url, hook.last_response.code, hook.events.join(", ")));
2597
2540
  break;
2598
2541
  case "docker":
2599
- reporter.log(sprintfJs.sprintf(" docker (%s) (%s)", hook.last_response.code, hook.events.join(", ")));
2542
+ reporter.log(sprintf(" docker (%s) (%s)", hook.last_response.code, hook.events.join(", ")));
2600
2543
  break;
2601
2544
  default:
2602
2545
  reporter.log(` ${hook.name}: <unknown type>`);
@@ -2625,7 +2568,7 @@ async function setToken$1({ reporter, token, tokenProvider, }) {
2625
2568
  reporter.info("Need API token to talk to GitHub");
2626
2569
  reporter.info("https://github.com/settings/tokens/new?scopes=repo:status,read:repo_hook");
2627
2570
  token = await new Promise((resolve, reject) => {
2628
- read__default["default"]({
2571
+ read({
2629
2572
  prompt: "Enter new GitHub API token: ",
2630
2573
  silent: true,
2631
2574
  }, (err, answer) => {
@@ -2689,20 +2632,22 @@ var CloneType;
2689
2632
  CloneType[CloneType["SSH"] = 1] = "SSH";
2690
2633
  })(CloneType || (CloneType = {}));
2691
2634
  class GitRepo {
2635
+ path;
2636
+ logCommand;
2692
2637
  constructor(path, logCommand) {
2693
2638
  this.path = path;
2694
2639
  this.logCommand = logCommand;
2695
2640
  }
2696
2641
  async cloneGitHubRepo(org, name, cloneType) {
2697
- const parent = path__default["default"].dirname(this.path);
2698
- if (!fs__default["default"].existsSync(parent)) {
2699
- await fs__default["default"].promises.mkdir(parent, { recursive: true });
2642
+ const parent = path.dirname(this.path);
2643
+ if (!fs.existsSync(parent)) {
2644
+ await fs.promises.mkdir(parent, { recursive: true });
2700
2645
  }
2701
2646
  const cloneUrl = cloneType === CloneType.SSH
2702
2647
  ? `git@github.com:${org}/${name}.git`
2703
2648
  : `https://github.com/${org}/${name}.git`;
2704
2649
  try {
2705
- const result = await execa__default["default"]("git", ["clone", cloneUrl, this.path], {
2650
+ const result = await execa("git", ["clone", cloneUrl, this.path], {
2706
2651
  cwd: parent,
2707
2652
  });
2708
2653
  await this.logCommand(result);
@@ -2715,7 +2660,7 @@ class GitRepo {
2715
2660
  }
2716
2661
  async git(args) {
2717
2662
  try {
2718
- const result = await execa__default["default"]("git", args, {
2663
+ const result = await execa("git", args, {
2719
2664
  cwd: this.path,
2720
2665
  });
2721
2666
  await this.logCommand(result);
@@ -2748,7 +2693,6 @@ class GitRepo {
2748
2693
  return parseShortlogSummary(result.stdout);
2749
2694
  }
2750
2695
  async update() {
2751
- var _a;
2752
2696
  const fetchOnly = async () => {
2753
2697
  await this.git(["fetch"]);
2754
2698
  return {
@@ -2771,7 +2715,7 @@ class GitRepo {
2771
2715
  return {
2772
2716
  dirty: false,
2773
2717
  updated: wasUpdated(result.stdout),
2774
- updatedRange: (_a = getUpdateRange(result.stdout)) !== null && _a !== void 0 ? _a : undefined,
2718
+ updatedRange: getUpdateRange(result.stdout) ?? undefined,
2775
2719
  };
2776
2720
  }
2777
2721
  }
@@ -2783,11 +2727,11 @@ const CALS_LOG = ".cals.log";
2783
2727
  * backward slashes in paths.
2784
2728
  */
2785
2729
  function getRelpath(it) {
2786
- return path__default["default"].join(it.group, it.name);
2730
+ return path.join(it.group, it.name);
2787
2731
  }
2788
2732
  async function appendFile(path, data) {
2789
2733
  return new Promise((resolve, reject) => {
2790
- fs__default["default"].appendFile(path, data, { encoding: "utf-8" }, (err) => {
2734
+ fs.appendFile(path, data, { encoding: "utf-8" }, (err) => {
2791
2735
  if (err !== null) {
2792
2736
  reject(err);
2793
2737
  }
@@ -2796,15 +2740,14 @@ async function appendFile(path, data) {
2796
2740
  });
2797
2741
  }
2798
2742
  function getAliases(repo) {
2799
- var _a;
2800
- return ((_a = repo.previousNames) !== null && _a !== void 0 ? _a : []).map((it) => ({
2743
+ return (repo.previousNames ?? []).map((it) => ({
2801
2744
  group: it.project,
2802
2745
  name: it.name,
2803
2746
  }));
2804
2747
  }
2805
2748
  async function updateReposInParallel(reporter, items) {
2806
2749
  // Perform git operations in parallel, but limit how much.
2807
- const semaphore = pLimit__default["default"](30);
2750
+ const semaphore = pLimit(30);
2808
2751
  const promises = items.map((repo) => semaphore(async () => {
2809
2752
  try {
2810
2753
  return {
@@ -2848,7 +2791,7 @@ async function updateRepos(reporter, foundRepos) {
2848
2791
  : undefined;
2849
2792
  // We only focus on changes made by humans, which we make
2850
2793
  // green while keeping the other changes gray.
2851
- const repoNameFormat = (authors === null || authors === void 0 ? void 0 : authors.every(({ name }) => isBotAuthor(name)))
2794
+ const repoNameFormat = authors?.every(({ name }) => isBotAuthor(name))
2852
2795
  ? reporter.format.gray
2853
2796
  : reporter.format.greenBright;
2854
2797
  reporter.info(`Updated: ${repoNameFormat(repo.id)}`);
@@ -2865,8 +2808,8 @@ async function updateRepos(reporter, foundRepos) {
2865
2808
  }
2866
2809
  }
2867
2810
  function guessDefinitionRepoName(rootdir, cals) {
2868
- const p = path__default["default"].resolve(rootdir, cals.resourcesDefinition.path);
2869
- const relativePath = path__default["default"].relative(rootdir, p);
2811
+ const p = path.resolve(rootdir, cals.resourcesDefinition.path);
2812
+ const relativePath = path.relative(rootdir, p);
2870
2813
  if (relativePath.slice(0, 1) == ".") {
2871
2814
  return null;
2872
2815
  }
@@ -2879,8 +2822,8 @@ function guessDefinitionRepoName(rootdir, cals) {
2879
2822
  return parts[1];
2880
2823
  }
2881
2824
  async function getDefinition(rootdir, cals) {
2882
- const p = path__default["default"].resolve(rootdir, cals.resourcesDefinition.path);
2883
- if (!fs__default["default"].existsSync(p)) {
2825
+ const p = path.resolve(rootdir, cals.resourcesDefinition.path);
2826
+ if (!fs.existsSync(p)) {
2884
2827
  throw Error(`The file ${p} does not exist`);
2885
2828
  }
2886
2829
  return new DefinitionFile(p).getDefinition();
@@ -2889,9 +2832,9 @@ async function getDefinition(rootdir, cals) {
2889
2832
  * Get directory names within a directory.
2890
2833
  */
2891
2834
  function getDirNames(parent) {
2892
- return (fs__default["default"]
2835
+ return (fs
2893
2836
  .readdirSync(parent)
2894
- .filter((it) => fs__default["default"].statSync(path__default["default"].join(parent, it)).isDirectory())
2837
+ .filter((it) => fs.statSync(path.join(parent, it)).isDirectory())
2895
2838
  // Skip hidden folders
2896
2839
  .filter((it) => !it.startsWith("."))
2897
2840
  .sort((a, b) => a.localeCompare(b)));
@@ -2901,9 +2844,9 @@ async function getReposInOrg(cals, rootdir) {
2901
2844
  return getRepos(definition)
2902
2845
  .filter((it) => it.orgName === cals.githubOrganization)
2903
2846
  .filter((it) => cals.resourcesDefinition.tags === undefined ||
2904
- (it.project.tags || []).some((tag) => { var _a; return (_a = cals.resourcesDefinition.tags) === null || _a === void 0 ? void 0 : _a.includes(tag); }) ||
2847
+ (it.project.tags || []).some((tag) => cals.resourcesDefinition.tags?.includes(tag)) ||
2905
2848
  // Always include if already checked out to avoid stale state.
2906
- fs__default["default"].existsSync(path__default["default"].join(rootdir, it.project.name, it.repo.name)));
2849
+ fs.existsSync(path.join(rootdir, it.project.name, it.repo.name)));
2907
2850
  }
2908
2851
  function getExpectedRepo(item) {
2909
2852
  return {
@@ -2916,8 +2859,8 @@ function getExpectedRepo(item) {
2916
2859
  };
2917
2860
  }
2918
2861
  function getGitRepo(rootdir, relpath) {
2919
- return new GitRepo(path__default["default"].resolve(rootdir, relpath), async (result) => {
2920
- await appendFile(path__default["default"].resolve(rootdir, CALS_LOG), JSON.stringify({
2862
+ return new GitRepo(path.resolve(rootdir, relpath), async (result) => {
2863
+ await appendFile(path.resolve(rootdir, CALS_LOG), JSON.stringify({
2921
2864
  time: new Date().toISOString(),
2922
2865
  context: relpath,
2923
2866
  type: "exec-result",
@@ -2971,7 +2914,7 @@ async function getExpectedRepos(reporter, github, cals, rootdir) {
2971
2914
  }
2972
2915
  async function getInput(prompt) {
2973
2916
  return new Promise((resolve, reject) => {
2974
- read__default["default"]({
2917
+ read({
2975
2918
  prompt,
2976
2919
  timeout: 60000,
2977
2920
  }, (err, answer) => {
@@ -3009,15 +2952,15 @@ async function sync$1({ reporter, github, cals, rootdir, askClone, askMove, }) {
3009
2952
  const foundRepos = [];
3010
2953
  // Categorize all dirs.
3011
2954
  for (const topdir of getDirNames(rootdir)) {
3012
- const isGitDir = fs__default["default"].existsSync(path__default["default"].join(rootdir, topdir, ".git"));
2955
+ const isGitDir = fs.existsSync(path.join(rootdir, topdir, ".git"));
3013
2956
  if (isGitDir) {
3014
2957
  // Do not traverse deeper inside another Git repo, as that might
3015
2958
  // mean we do not have the proper grouped structure.
3016
2959
  unknownDirs.push(topdir);
3017
2960
  continue;
3018
2961
  }
3019
- for (const subdir of getDirNames(path__default["default"].join(rootdir, topdir))) {
3020
- const p = path__default["default"].join(topdir, subdir);
2962
+ for (const subdir of getDirNames(path.join(rootdir, topdir))) {
2963
+ const p = path.join(topdir, subdir);
3021
2964
  const expectedRepo = expectedRepos.find((it) => getRelpath(it) === p ||
3022
2965
  it.aliases.some((alias) => getRelpath(alias) === p));
3023
2966
  if (expectedRepo === undefined) {
@@ -3045,9 +2988,9 @@ async function sync$1({ reporter, github, cals, rootdir, askClone, askMove, }) {
3045
2988
  for (const it of archivedRepos) {
3046
2989
  reporter.info(` ${it.actualRelpath}`);
3047
2990
  }
3048
- const thisDirName = path__default["default"].basename(process.cwd());
2991
+ const thisDirName = path.basename(process.cwd());
3049
2992
  const archiveDir = `../${thisDirName}-archive`;
3050
- const hasArchiveDir = fs__default["default"].existsSync(archiveDir);
2993
+ const hasArchiveDir = fs.existsSync(archiveDir);
3051
2994
  if (hasArchiveDir) {
3052
2995
  reporter.info("To move these:");
3053
2996
  for (const it of archivedRepos) {
@@ -3070,17 +3013,17 @@ async function sync$1({ reporter, github, cals, rootdir, askClone, askMove, }) {
3070
3013
  const shouldMove = await askMoveConfirm();
3071
3014
  if (shouldMove) {
3072
3015
  for (const it of movedRepos) {
3073
- const src = path__default["default"].join(rootdir, it.actualRelpath);
3074
- const dest = path__default["default"].join(rootdir, getRelpath(it));
3075
- const destParent = path__default["default"].join(rootdir, it.group);
3076
- if (fs__default["default"].existsSync(dest)) {
3016
+ const src = path.join(rootdir, it.actualRelpath);
3017
+ const dest = path.join(rootdir, getRelpath(it));
3018
+ const destParent = path.join(rootdir, it.group);
3019
+ if (fs.existsSync(dest)) {
3077
3020
  throw new Error(`Target directory already exists: ${dest} - cannot move ${it.actualRelpath}`);
3078
3021
  }
3079
3022
  reporter.info(`Moving ${it.actualRelpath} -> ${getRelpath(it)}`);
3080
- if (!fs__default["default"].existsSync(destParent)) {
3081
- await fs__default["default"].promises.mkdir(destParent, { recursive: true });
3023
+ if (!fs.existsSync(destParent)) {
3024
+ await fs.promises.mkdir(destParent, { recursive: true });
3082
3025
  }
3083
- await fs__default["default"].promises.rename(src, dest);
3026
+ await fs.promises.rename(src, dest);
3084
3027
  }
3085
3028
  // We would have to update expectedRepos if we want to continue.
3086
3029
  // Let's try keeping this simple.
@@ -3113,7 +3056,7 @@ async function sync$1({ reporter, github, cals, rootdir, askClone, askMove, }) {
3113
3056
  }
3114
3057
  const reposToUpdate = foundRepos.filter((it) =>
3115
3058
  // Avoid double-processing the defintion repo.
3116
- (definitionRepo === null || definitionRepo === void 0 ? void 0 : definitionRepo.id) !== it.id);
3059
+ definitionRepo?.id !== it.id);
3117
3060
  reporter.info(`${reposToUpdate.length} repos identified to be updated`);
3118
3061
  await updateRepos(reporter, reposToUpdate);
3119
3062
  // Report repos with changes ahead.
@@ -3124,7 +3067,7 @@ async function sync$1({ reporter, github, cals, rootdir, askClone, askMove, }) {
3124
3067
  }
3125
3068
  }
3126
3069
  async function loadCalsManifest(config, reporter) {
3127
- const p = await findUp__default["default"](CALS_YAML, { cwd: config.cwd });
3070
+ const p = await findUp(CALS_YAML, { cwd: config.cwd });
3128
3071
  if (p === undefined) {
3129
3072
  reporter.error(`File ${CALS_YAML} not found. See help`);
3130
3073
  process.exitCode = 1;
@@ -3133,12 +3076,12 @@ async function loadCalsManifest(config, reporter) {
3133
3076
  // TODO: Verify file has expected contents.
3134
3077
  // (Can we easily generate schema for type and verify?)
3135
3078
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-explicit-any
3136
- const cals = yaml__default["default"].load(fs__default["default"].readFileSync(p, "utf-8"));
3079
+ const cals = yaml.load(fs.readFileSync(p, "utf-8"));
3137
3080
  if (cals.version !== 2) {
3138
3081
  throw new Error(`Unexpected version in ${p}`);
3139
3082
  }
3140
3083
  return {
3141
- dir: path__default["default"].dirname(p),
3084
+ dir: path.dirname(p),
3142
3085
  cals,
3143
3086
  };
3144
3087
  }
@@ -3243,23 +3186,21 @@ Notes:
3243
3186
  option to avoid stale cache. The cache can also be cleared with
3244
3187
  the "cals delete-cache" command.`),
3245
3188
  handler: () => {
3246
- yargs__default["default"].showHelp();
3189
+ yargs(hideBin(process.argv)).showHelp();
3247
3190
  },
3248
3191
  };
3249
3192
 
3250
3193
  function totalSeverityCount(project) {
3251
- var _a;
3252
- return (((_a = project.issueCountsBySeverity.critical) !== null && _a !== void 0 ? _a : 0) +
3194
+ return ((project.issueCountsBySeverity.critical ?? 0) +
3253
3195
  project.issueCountsBySeverity.high +
3254
3196
  project.issueCountsBySeverity.medium +
3255
3197
  project.issueCountsBySeverity.low);
3256
3198
  }
3257
3199
  function buildStatsLine(stats) {
3258
- var _a;
3259
3200
  function item(num, str) {
3260
- return num === 0 ? lodash.repeat(" ", str.length + 4) : sprintfJs.sprintf("%3d %s", num, str);
3201
+ return num === 0 ? repeat(" ", str.length + 4) : sprintf("%3d %s", num, str);
3261
3202
  }
3262
- return sprintfJs.sprintf("%s %s %s %s", item((_a = stats.critical) !== null && _a !== void 0 ? _a : 0, "critical"), item(stats.high, "high"), item(stats.medium, "medium"), item(stats.low, "low"));
3203
+ return sprintf("%s %s %s %s", item(stats.critical ?? 0, "critical"), item(stats.high, "high"), item(stats.medium, "medium"), item(stats.low, "low"));
3263
3204
  }
3264
3205
  async function report({ reporter, snyk, definitionFile, }) {
3265
3206
  const definition = await definitionFile.getDefinition();
@@ -3277,30 +3218,30 @@ async function report({ reporter, snyk, definitionFile, }) {
3277
3218
  function getProjectName(project) {
3278
3219
  return project ? project.name : "unknown project";
3279
3220
  }
3280
- const byProjects = lodash.sortBy(Object.values(lodash.groupBy(enhancedRepos, (it) => it.project ? it.project.name : "unknown")), (it) => getProjectName(it[0].project));
3221
+ const byProjects = sortBy(Object.values(groupBy(enhancedRepos, (it) => it.project ? it.project.name : "unknown")), (it) => getProjectName(it[0].project));
3281
3222
  if (byProjects.length === 0) {
3282
3223
  reporter.info("No issues found");
3283
3224
  }
3284
3225
  else {
3285
- reporter.info(sprintfJs.sprintf("%-70s %s", "Total count", buildStatsLine({
3286
- critical: lodash.sumBy(reposWithIssues, (it) => { var _a; return (_a = it.issueCountsBySeverity.critical) !== null && _a !== void 0 ? _a : 0; }),
3287
- high: lodash.sumBy(reposWithIssues, (it) => it.issueCountsBySeverity.high),
3288
- medium: lodash.sumBy(reposWithIssues, (it) => it.issueCountsBySeverity.medium),
3289
- low: lodash.sumBy(reposWithIssues, (it) => it.issueCountsBySeverity.low),
3226
+ reporter.info(sprintf("%-70s %s", "Total count", buildStatsLine({
3227
+ critical: sumBy(reposWithIssues, (it) => it.issueCountsBySeverity.critical ?? 0),
3228
+ high: sumBy(reposWithIssues, (it) => it.issueCountsBySeverity.high),
3229
+ medium: sumBy(reposWithIssues, (it) => it.issueCountsBySeverity.medium),
3230
+ low: sumBy(reposWithIssues, (it) => it.issueCountsBySeverity.low),
3290
3231
  })));
3291
3232
  reporter.info("Issues by project:");
3292
3233
  byProjects.forEach((repos) => {
3293
3234
  const project = repos[0].project;
3294
3235
  const totalCount = {
3295
- critical: lodash.sumBy(repos, (it) => { var _a; return (_a = it.repo.issueCountsBySeverity.critical) !== null && _a !== void 0 ? _a : 0; }),
3296
- high: lodash.sumBy(repos, (it) => it.repo.issueCountsBySeverity.high),
3297
- medium: lodash.sumBy(repos, (it) => it.repo.issueCountsBySeverity.medium),
3298
- low: lodash.sumBy(repos, (it) => it.repo.issueCountsBySeverity.low),
3236
+ critical: sumBy(repos, (it) => it.repo.issueCountsBySeverity.critical ?? 0),
3237
+ high: sumBy(repos, (it) => it.repo.issueCountsBySeverity.high),
3238
+ medium: sumBy(repos, (it) => it.repo.issueCountsBySeverity.medium),
3239
+ low: sumBy(repos, (it) => it.repo.issueCountsBySeverity.low),
3299
3240
  };
3300
3241
  reporter.info("");
3301
- reporter.info(sprintfJs.sprintf("%-70s %s", getProjectName(project), buildStatsLine(totalCount)));
3242
+ reporter.info(sprintf("%-70s %s", getProjectName(project), buildStatsLine(totalCount)));
3302
3243
  for (const { repo } of repos) {
3303
- reporter.info(sprintfJs.sprintf(" %-68s %s", repo.name, buildStatsLine(repo.issueCountsBySeverity)));
3244
+ reporter.info(sprintf(" %-68s %s", repo.name, buildStatsLine(repo.issueCountsBySeverity)));
3304
3245
  }
3305
3246
  });
3306
3247
  }
@@ -3321,7 +3262,7 @@ async function setToken({ reporter, token, tokenProvider, }) {
3321
3262
  reporter.info("Need API token to talk to Snyk");
3322
3263
  reporter.info("See https://app.snyk.io/account");
3323
3264
  token = await new Promise((resolve, reject) => {
3324
- read__default["default"]({
3265
+ read({
3325
3266
  prompt: "Enter new Snyk API token: ",
3326
3267
  silent: true,
3327
3268
  }, (err, answer) => {
@@ -3393,30 +3334,17 @@ Notes:
3393
3334
  and provide a link to generate one:
3394
3335
  $ cals snyk set-token`),
3395
3336
  handler: () => {
3396
- yargs__default["default"].showHelp();
3337
+ yargs(hideBin(process.argv)).showHelp();
3397
3338
  },
3398
3339
  };
3399
3340
 
3400
3341
  async function main() {
3401
- if (!semver__default["default"].satisfies(process.version, engines.node)) {
3342
+ if (!semver.satisfies(process.version, engines.node)) {
3402
3343
  console.error(`Required node version ${engines.node} not satisfied with current version ${process.version}.`);
3403
3344
  process.exit(1);
3404
3345
  }
3405
- // http://patorjk.com/software/taag/#p=display&f=Slant&t=CALS
3406
- const header = `
3407
- _________ __ _____
3408
- / ____/ | / / / ___/
3409
- / / / /| | / / \\__ \\
3410
- / /___/ ___ |/ /______/ /
3411
- \\____/_/ |_/_____/____/
3412
- cli ${version}
3413
- built ${"2024-12-05T12:13:34+0000"}
3414
-
3415
- https://github.com/capralifecycle/cals-cli/
3416
-
3417
- Usage: cals <command>`;
3418
- await yargs__default["default"]
3419
- .usage(header)
3346
+ await yargs(hideBin(process.argv))
3347
+ .usage(`cals-cli v${version} (build: ${"2024-12-13T14:35:35+0000"})`)
3420
3348
  .scriptName("cals")
3421
3349
  .locale("en")
3422
3350
  .help("help")
@@ -3441,12 +3369,6 @@ Usage: cals <command>`;
3441
3369
  })
3442
3370
  .parse();
3443
3371
  }
3444
- // Definer prosjekt-navn
3445
- // Definer ønskede miljøer
3446
- // Baselines som skal brukse
3447
- // Er bruker logget inn?
3448
- // Lag repo og endre commit
3449
- // Osv. osv. osv.
3450
3372
 
3451
3373
  void main();
3452
- //# sourceMappingURL=cals-cli.js.map
3374
+ //# sourceMappingURL=cals-cli.mjs.map