@capraconsulting/cals-cli 2.22.2 → 2.23.2

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.
package/lib/cals-cli.js CHANGED
@@ -47,7 +47,7 @@ var read__default = /*#__PURE__*/_interopDefaultLegacy(read);
47
47
  var findUp__default = /*#__PURE__*/_interopDefaultLegacy(findUp);
48
48
  var execa__default = /*#__PURE__*/_interopDefaultLegacy(execa);
49
49
 
50
- var version = "2.22.2";
50
+ var version = "2.23.2";
51
51
  var engines = {
52
52
  node: ">=12.0.0"
53
53
  };
@@ -357,7 +357,7 @@ function getRepoId(orgName, repoName) {
357
357
  }
358
358
  function checkAgainstSchema(value) {
359
359
  var _a;
360
- const ajv = new AJV__default['default']({ allErrors: true });
360
+ const ajv = new AJV__default["default"]({ allErrors: true });
361
361
  const valid = ajv.validate(schema, value);
362
362
  return valid
363
363
  ? { definition: value }
@@ -434,7 +434,7 @@ class DefinitionFile {
434
434
  this.path = path;
435
435
  }
436
436
  async getContents() {
437
- return new Promise((resolve, reject) => fs__default['default'].readFile(this.path, "utf-8", (err, data) => {
437
+ return new Promise((resolve, reject) => fs__default["default"].readFile(this.path, "utf-8", (err, data) => {
438
438
  if (err)
439
439
  reject(err);
440
440
  else
@@ -446,7 +446,7 @@ class DefinitionFile {
446
446
  }
447
447
  }
448
448
  function parseDefinition(value) {
449
- const result = checkAgainstSchema(yaml__default['default'].load(value));
449
+ const result = checkAgainstSchema(yaml__default["default"].load(value));
450
450
  if ("error" in result) {
451
451
  throw new Error("Definition content invalid: " + result.error);
452
452
  }
@@ -476,7 +476,7 @@ class GitHubTokenCliProvider {
476
476
  if (process.env.CALS_GITHUB_TOKEN) {
477
477
  return process.env.CALS_GITHUB_TOKEN;
478
478
  }
479
- const result = await keytar__default['default'].getPassword(this.keyringService, this.keyringAccount);
479
+ const result = await keytar__default["default"].getPassword(this.keyringService, this.keyringAccount);
480
480
  if (result == null) {
481
481
  process.stderr.write("No token found. Register using `cals github set-token`\n");
482
482
  return undefined;
@@ -484,10 +484,10 @@ class GitHubTokenCliProvider {
484
484
  return result;
485
485
  }
486
486
  async markInvalid() {
487
- await keytar__default['default'].deletePassword(this.keyringService, this.keyringAccount);
487
+ await keytar__default["default"].deletePassword(this.keyringService, this.keyringAccount);
488
488
  }
489
489
  async setToken(value) {
490
- await keytar__default['default'].setPassword(this.keyringService, this.keyringAccount, value);
490
+ await keytar__default["default"].setPassword(this.keyringService, this.keyringAccount, value);
491
491
  }
492
492
  }
493
493
 
@@ -560,7 +560,7 @@ class GitHubService {
560
560
  this.tokenProvider = props.tokenProvider;
561
561
  // Control concurrency to GitHub API at service level so we
562
562
  // can maximize concurrency all other places.
563
- this.semaphore = pLimit__default['default'](6);
563
+ this.semaphore = pLimit__default["default"](6);
564
564
  this.octokit.hook.wrap("request", async (request, options) => {
565
565
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
566
566
  this._requestCount++;
@@ -640,7 +640,7 @@ class GitHubService {
640
640
  const headers = {
641
641
  Authorization: `Bearer ${token}`,
642
642
  };
643
- const response = await this.semaphore(() => fetch__default['default'](url, {
643
+ const response = await this.semaphore(() => fetch__default["default"](url, {
644
644
  method: "POST",
645
645
  headers,
646
646
  body: JSON.stringify({ query }),
@@ -1049,7 +1049,7 @@ class SnykTokenCliProvider {
1049
1049
  if (process.env.CALS_SNYK_TOKEN) {
1050
1050
  return process.env.CALS_SNYK_TOKEN;
1051
1051
  }
1052
- const result = await keytar__default['default'].getPassword(this.keyringService, this.keyringAccount);
1052
+ const result = await keytar__default["default"].getPassword(this.keyringService, this.keyringAccount);
1053
1053
  if (result == null) {
1054
1054
  process.stderr.write("No token found. Register using `cals snyk set-token`\n");
1055
1055
  return undefined;
@@ -1057,10 +1057,10 @@ class SnykTokenCliProvider {
1057
1057
  return result;
1058
1058
  }
1059
1059
  async markInvalid() {
1060
- await keytar__default['default'].deletePassword(this.keyringService, this.keyringAccount);
1060
+ await keytar__default["default"].deletePassword(this.keyringService, this.keyringAccount);
1061
1061
  }
1062
1062
  async setToken(value) {
1063
- await keytar__default['default'].setPassword(this.keyringService, this.keyringAccount, value);
1063
+ await keytar__default["default"].setPassword(this.keyringService, this.keyringAccount, value);
1064
1064
  }
1065
1065
  }
1066
1066
 
@@ -1082,7 +1082,7 @@ class SnykService {
1082
1082
  if (token === undefined) {
1083
1083
  throw new Error("Missing token for Snyk");
1084
1084
  }
1085
- const response = await fetch__default['default'](`https://snyk.io/api/v1/org/${encodeURIComponent(snykAccountId)}/projects`, {
1085
+ const response = await fetch__default["default"](`https://snyk.io/api/v1/org/${encodeURIComponent(snykAccountId)}/projects`, {
1086
1086
  method: "GET",
1087
1087
  headers: {
1088
1088
  Accept: "application/json",
@@ -1110,18 +1110,32 @@ function createSnykService(props) {
1110
1110
  }
1111
1111
 
1112
1112
  function getGitHubRepo(snykProject) {
1113
- if (snykProject.origin !== "github") {
1114
- return undefined;
1113
+ if (snykProject.origin === "github") {
1114
+ const match = /^([^/]+)\/([^:]+)(:(.+))?$/.exec(snykProject.name);
1115
+ if (match === null) {
1116
+ throw Error(`Could not extract components from Snyk project name: ${snykProject.name} (id: ${snykProject.id})`);
1117
+ }
1118
+ return {
1119
+ owner: match[1],
1120
+ name: match[2],
1121
+ };
1115
1122
  }
1116
- const match = /^([^/]+)\/([^:]+):(.+)$/.exec(snykProject.name);
1117
- if (match === null) {
1118
- throw Error(`Could not extract components from Snyk project name: ${snykProject.name} (id: ${snykProject.id})`);
1123
+ else if (snykProject.origin === "cli" &&
1124
+ snykProject.remoteRepoUrl != null) {
1125
+ // The remoteRepoUrl can be overriden when using the CLI, so don't
1126
+ // fail if we cannot extract the value.
1127
+ const match = /github.com\/([^/]+)\/(.+)\.git$/.exec(snykProject.remoteRepoUrl);
1128
+ if (match === null) {
1129
+ return undefined;
1130
+ }
1131
+ return {
1132
+ owner: match[1],
1133
+ name: match[2],
1134
+ };
1135
+ }
1136
+ else {
1137
+ return undefined;
1119
1138
  }
1120
- return {
1121
- owner: match[1],
1122
- name: match[2],
1123
- file: match[3],
1124
- };
1125
1139
  }
1126
1140
  function getGitHubRepoId(repo) {
1127
1141
  return repo ? `${repo.owner}/${repo.name}` : undefined;
@@ -1139,13 +1153,13 @@ class CacheProvider {
1139
1153
  * The caller is responsible for handling proper validation,
1140
1154
  */
1141
1155
  retrieveJson(cachekey) {
1142
- const cachefile = path__default['default'].join(this.config.cacheDir, `${cachekey}.json`);
1143
- if (!fs__default['default'].existsSync(cachefile)) {
1156
+ const cachefile = path__default["default"].join(this.config.cacheDir, `${cachekey}.json`);
1157
+ if (!fs__default["default"].existsSync(cachefile)) {
1144
1158
  return undefined;
1145
1159
  }
1146
- const data = fs__default['default'].readFileSync(cachefile, "utf-8");
1160
+ const data = fs__default["default"].readFileSync(cachefile, "utf-8");
1147
1161
  return {
1148
- cacheTime: fs__default['default'].statSync(cachefile).mtime.getTime(),
1162
+ cacheTime: fs__default["default"].statSync(cachefile).mtime.getTime(),
1149
1163
  data: (data === "undefined" ? undefined : JSON.parse(data)),
1150
1164
  };
1151
1165
  }
@@ -1153,11 +1167,11 @@ class CacheProvider {
1153
1167
  * Save data to cache.
1154
1168
  */
1155
1169
  storeJson(cachekey, data) {
1156
- const cachefile = path__default['default'].join(this.config.cacheDir, `${cachekey}.json`);
1157
- if (!fs__default['default'].existsSync(this.config.cacheDir)) {
1158
- fs__default['default'].mkdirSync(this.config.cacheDir, { recursive: true });
1170
+ const cachefile = path__default["default"].join(this.config.cacheDir, `${cachekey}.json`);
1171
+ if (!fs__default["default"].existsSync(this.config.cacheDir)) {
1172
+ fs__default["default"].mkdirSync(this.config.cacheDir, { recursive: true });
1159
1173
  }
1160
- fs__default['default'].writeFileSync(cachefile, data === undefined ? "undefined" : JSON.stringify(data));
1174
+ fs__default["default"].writeFileSync(cachefile, data === undefined ? "undefined" : JSON.stringify(data));
1161
1175
  }
1162
1176
  async json(cachekey, block, cachetime = this.defaultCacheTime) {
1163
1177
  const cacheItem = this.mustValidate
@@ -1175,16 +1189,16 @@ class CacheProvider {
1175
1189
  * Delete all cached data.
1176
1190
  */
1177
1191
  cleanup() {
1178
- rimraf__default['default'].sync(this.config.cacheDir);
1192
+ rimraf__default["default"].sync(this.config.cacheDir);
1179
1193
  }
1180
1194
  }
1181
1195
 
1182
1196
  class Config {
1183
1197
  constructor() {
1184
- this.cwd = path__default['default'].resolve(process.cwd());
1185
- this.configFile = path__default['default'].join(os__default['default'].homedir(), ".cals-config.json");
1186
- this.cacheDir = cachedir__default['default']("cals-cli");
1187
- this.agent = new https__default['default'].Agent({
1198
+ this.cwd = path__default["default"].resolve(process.cwd());
1199
+ this.configFile = path__default["default"].join(os__default["default"].homedir(), ".cals-config.json");
1200
+ this.cacheDir = cachedir__default["default"]("cals-cli");
1201
+ this.agent = new https__default["default"].Agent({
1188
1202
  keepAlive: true,
1189
1203
  });
1190
1204
  this.configCached = undefined;
@@ -1199,12 +1213,12 @@ class Config {
1199
1213
  return config;
1200
1214
  }
1201
1215
  readConfig() {
1202
- if (!fs__default['default'].existsSync(this.configFile)) {
1216
+ if (!fs__default["default"].existsSync(this.configFile)) {
1203
1217
  return {};
1204
1218
  }
1205
1219
  try {
1206
1220
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
1207
- return JSON.parse(fs__default['default'].readFileSync(this.configFile, "utf-8"));
1221
+ return JSON.parse(fs__default["default"].readFileSync(this.configFile, "utf-8"));
1208
1222
  }
1209
1223
  catch (e) {
1210
1224
  console.error("Failed", e);
@@ -1226,15 +1240,15 @@ class Config {
1226
1240
  ...this.readConfig(),
1227
1241
  [key]: value, // undefined will remove
1228
1242
  };
1229
- fs__default['default'].writeFileSync(this.configFile, JSON.stringify(updatedConfig, null, " "));
1243
+ fs__default["default"].writeFileSync(this.configFile, JSON.stringify(updatedConfig, null, " "));
1230
1244
  this.configCached = updatedConfig;
1231
1245
  }
1232
1246
  }
1233
1247
 
1234
1248
  const CLEAR_WHOLE_LINE = 0;
1235
1249
  function clearLine(stdout) {
1236
- readline__default['default'].clearLine(stdout, CLEAR_WHOLE_LINE);
1237
- readline__default['default'].cursorTo(stdout, 0);
1250
+ readline__default["default"].clearLine(stdout, CLEAR_WHOLE_LINE);
1251
+ readline__default["default"].cursorTo(stdout, 0);
1238
1252
  }
1239
1253
  class Reporter {
1240
1254
  constructor(opts = {}) {
@@ -1242,7 +1256,7 @@ class Reporter {
1242
1256
  this.stderr = process.stderr;
1243
1257
  this.stdin = process.stdin;
1244
1258
  this.isTTY = this.stdout.isTTY;
1245
- this.format = chalk__default['default'];
1259
+ this.format = chalk__default["default"];
1246
1260
  this.startTime = Date.now();
1247
1261
  this.nonInteractive = !!opts.nonInteractive;
1248
1262
  this.isVerbose = !!opts.verbose;
@@ -1303,7 +1317,7 @@ function getDefinitionFile(argv) {
1303
1317
  throw Error("Missing --definition-file option");
1304
1318
  }
1305
1319
  const definitionFile = argv.definitionFile;
1306
- if (!fs__default['default'].existsSync(definitionFile)) {
1320
+ if (!fs__default["default"].existsSync(definitionFile)) {
1307
1321
  throw Error(`The file ${definitionFile} does not exist`);
1308
1322
  }
1309
1323
  return new DefinitionFile(definitionFile);
@@ -1360,9 +1374,9 @@ function reorderListToSimilarAsBefore(oldList, updatedList, selector, insertLast
1360
1374
  }
1361
1375
 
1362
1376
  async function getReposFromGitHub(github, orgs) {
1363
- return (await pMap__default['default'](orgs, async (org) => {
1377
+ return (await pMap__default["default"](orgs, async (org) => {
1364
1378
  const repos = await github.getOrgRepoList({ org: org.login });
1365
- return pMap__default['default'](repos, async (repo) => {
1379
+ return pMap__default["default"](repos, async (repo) => {
1366
1380
  const detailedRepo = await github.getRepository(repo.owner.login, repo.name);
1367
1381
  if (detailedRepo === undefined) {
1368
1382
  throw Error(`Repo not found: ${repo.owner.login}/${repo.name}`);
@@ -1376,11 +1390,11 @@ async function getReposFromGitHub(github, orgs) {
1376
1390
  })).flat();
1377
1391
  }
1378
1392
  async function getTeams(github, orgs) {
1379
- const intermediate = await pMap__default['default'](orgs, async (org) => {
1393
+ const intermediate = await pMap__default["default"](orgs, async (org) => {
1380
1394
  const teams = await github.getTeamList(org);
1381
1395
  return {
1382
1396
  org,
1383
- teams: await pMap__default['default'](teams, async (team) => ({
1397
+ teams: await pMap__default["default"](teams, async (team) => ({
1384
1398
  team,
1385
1399
  users: await github.getTeamMemberListIncludingInvited(org, team),
1386
1400
  })),
@@ -1413,7 +1427,7 @@ function getFormattedTeams(oldTeams, teams) {
1413
1427
  : undefined;
1414
1428
  }
1415
1429
  async function getOrgs(github, orgs) {
1416
- return pMap__default['default'](orgs, (it) => github.getOrg(it));
1430
+ return pMap__default["default"](orgs, (it) => github.getOrg(it));
1417
1431
  }
1418
1432
  function removeDuplicates(items, selector) {
1419
1433
  const ids = [];
@@ -1428,7 +1442,7 @@ function removeDuplicates(items, selector) {
1428
1442
  return result;
1429
1443
  }
1430
1444
  async function getMembers(github, orgs) {
1431
- return removeDuplicates((await pMap__default['default'](orgs, (org) => github.getOrgMembersListIncludingInvited(org.login)))
1445
+ return removeDuplicates((await pMap__default["default"](orgs, (org) => github.getOrgMembersListIncludingInvited(org.login)))
1432
1446
  .flat()
1433
1447
  .map((it) => it.login), (it) => it);
1434
1448
  }
@@ -1543,7 +1557,7 @@ async function dumpSetup(config, reporter, github, snyk, outfile, definitionFile
1543
1557
  // package. However it often produced invalid yaml, so we have removed
1544
1558
  // it. We might want to revisit it to preserve comments.
1545
1559
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-explicit-any
1546
- const doc = yaml__default['default'].load(await definitionFile.getContents());
1560
+ const doc = yaml__default["default"].load(await definitionFile.getContents());
1547
1561
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
1548
1562
  doc.snyk = generatedDefinition.snyk;
1549
1563
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
@@ -1551,7 +1565,7 @@ async function dumpSetup(config, reporter, github, snyk, outfile, definitionFile
1551
1565
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
1552
1566
  doc.github = generatedDefinition.github;
1553
1567
  // Convert to/from plain JSON so that undefined elements are removed.
1554
- fs__default['default'].writeFileSync(outfile, yaml__default['default'].dump(JSON.parse(JSON.stringify(doc))));
1568
+ fs__default["default"].writeFileSync(outfile, yaml__default["default"].dump(JSON.parse(JSON.stringify(doc))));
1555
1569
  reporter.info(`Saved to ${outfile}`);
1556
1570
  reporter.info(`Number of GitHub requests: ${github.requestCount}`);
1557
1571
  }
@@ -1596,7 +1610,7 @@ const command$i = {
1596
1610
  .demandCommand()
1597
1611
  .usage(`cals definition`),
1598
1612
  handler: () => {
1599
- yargs__default['default'].showHelp();
1613
+ yargs__default["default"].showHelp();
1600
1614
  },
1601
1615
  };
1602
1616
 
@@ -1621,7 +1635,7 @@ class DetectifyTokenCliProvider {
1621
1635
  if (process.env.CALS_DETECTIFY_TOKEN) {
1622
1636
  return process.env.CALS_DETECTIFY_TOKEN;
1623
1637
  }
1624
- const result = await keytar__default['default'].getPassword(this.keyringService, this.keyringAccount);
1638
+ const result = await keytar__default["default"].getPassword(this.keyringService, this.keyringAccount);
1625
1639
  if (result == null) {
1626
1640
  process.stderr.write("No token found. Register using `cals detectify set-token`\n");
1627
1641
  return undefined;
@@ -1629,10 +1643,10 @@ class DetectifyTokenCliProvider {
1629
1643
  return result;
1630
1644
  }
1631
1645
  async markInvalid() {
1632
- await keytar__default['default'].deletePassword(this.keyringService, this.keyringAccount);
1646
+ await keytar__default["default"].deletePassword(this.keyringService, this.keyringAccount);
1633
1647
  }
1634
1648
  async setToken(value) {
1635
- await keytar__default['default'].setPassword(this.keyringService, this.keyringAccount, value);
1649
+ await keytar__default["default"].setPassword(this.keyringService, this.keyringAccount, value);
1636
1650
  }
1637
1651
  }
1638
1652
 
@@ -1652,7 +1666,7 @@ class DetectifyService {
1652
1666
  if (token === undefined) {
1653
1667
  throw new Error("Missing token for Detectify");
1654
1668
  }
1655
- const response = await fetch__default['default'](url, {
1669
+ const response = await fetch__default["default"](url, {
1656
1670
  method: "GET",
1657
1671
  headers: {
1658
1672
  Accept: "application/json",
@@ -1730,7 +1744,7 @@ async function setToken$2({ reporter, token, tokenProvider, }) {
1730
1744
  reporter.info("Need API token to talk to Detectify");
1731
1745
  reporter.info("See API keys under https://detectify.com/dashboard/team");
1732
1746
  token = await new Promise((resolve, reject) => {
1733
- read__default['default']({
1747
+ read__default["default"]({
1734
1748
  prompt: "Enter new Detectify API token: ",
1735
1749
  silent: true,
1736
1750
  }, (err, answer) => {
@@ -1771,7 +1785,7 @@ Notes:
1771
1785
  and provide a link to generate one:
1772
1786
  $ cals detectify set-token`),
1773
1787
  handler: () => {
1774
- yargs__default['default'].showHelp();
1788
+ yargs__default["default"].showHelp();
1775
1789
  },
1776
1790
  };
1777
1791
 
@@ -1787,9 +1801,9 @@ const command$d = {
1787
1801
  async function analyzeDirectory(reporter, config, github, org) {
1788
1802
  const repos = await github.getOrgRepoList({ org });
1789
1803
  const reposDict = repos.reduce((acc, cur) => ({ ...acc, [cur.name]: cur }), {});
1790
- const dirs = fs__default['default']
1804
+ const dirs = fs__default["default"]
1791
1805
  .readdirSync(config.cwd)
1792
- .filter((it) => fs__default['default'].statSync(path__default['default'].join(config.cwd, it)).isDirectory())
1806
+ .filter((it) => fs__default["default"].statSync(path__default["default"].join(config.cwd, it)).isDirectory())
1793
1807
  // Skip hidden folders
1794
1808
  .filter((it) => !it.startsWith("."))
1795
1809
  .sort((a, b) => a.localeCompare(b));
@@ -1865,7 +1879,7 @@ function getChangedRepoAttribs(definitionRepo, actualRepo) {
1865
1879
  async function getUnknownRepos(github, definition, limitToOrg) {
1866
1880
  const knownRepos = getRepos(definition).map((it) => it.id);
1867
1881
  const orgs = getGitHubOrgs(definition).filter((orgName) => limitToOrg === undefined || limitToOrg === orgName);
1868
- return lodash.sortBy((await pMap__default['default'](orgs, (orgName) => github.getOrgRepoList({ org: orgName })))
1882
+ return lodash.sortBy((await pMap__default["default"](orgs, (orgName) => github.getOrgRepoList({ org: orgName })))
1869
1883
  .flat()
1870
1884
  .filter((it) => !knownRepos.includes(`${it.owner.login}/${it.name}`)), (it) => `${it.owner.login}/${it.name}`);
1871
1885
  }
@@ -1960,7 +1974,7 @@ async function createChangeSetItemsForProjects(github, definition, limitToOrg) {
1960
1974
  const orgs = definition.projects
1961
1975
  .flatMap((it) => it.github)
1962
1976
  .filter((org) => limitToOrg === undefined || limitToOrg === org.organization);
1963
- changes.push(...(await pMap__default['default'](orgs, async (org) => pMap__default['default'](org.repos || [], (projectRepo) => getProjectRepoChanges({
1977
+ changes.push(...(await pMap__default["default"](orgs, async (org) => pMap__default["default"](org.repos || [], (projectRepo) => getProjectRepoChanges({
1964
1978
  github,
1965
1979
  org,
1966
1980
  projectRepo,
@@ -2058,7 +2072,7 @@ async function createChangeSetItemsForTeams(github, definition, org) {
2058
2072
  }
2059
2073
  });
2060
2074
  const overlappingTeams = actualTeams.filter((it) => wantedTeamNames.includes(it.name));
2061
- await pMap__default['default'](overlappingTeams, async (actualTeam) => {
2075
+ await pMap__default["default"](overlappingTeams, async (actualTeam) => {
2062
2076
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
2063
2077
  const wantedTeam = teams.find((it) => it.name === actualTeam.name);
2064
2078
  const actualMembers = await github.getTeamMemberListIncludingInvited(org, actualTeam);
@@ -2256,7 +2270,7 @@ function createOrgGetter(github) {
2256
2270
  const semaphores = {};
2257
2271
  function getSemaphore(orgName) {
2258
2272
  if (!(orgName in semaphores)) {
2259
- semaphores[orgName] = pLimit__default['default'](1);
2273
+ semaphores[orgName] = pLimit__default["default"](1);
2260
2274
  }
2261
2275
  return semaphores[orgName];
2262
2276
  }
@@ -2313,7 +2327,7 @@ async function process$1(reporter, github, definition, getOrg, execute, limitToO
2313
2327
  }
2314
2328
  if (execute && changes.length > 0) {
2315
2329
  const cont = await new Promise((resolve, reject) => {
2316
- read__default['default']({
2330
+ read__default["default"]({
2317
2331
  prompt: "Confirm you want to execute the changes [y/N]: ",
2318
2332
  timeout: 60000,
2319
2333
  }, (err, answer) => {
@@ -2363,7 +2377,7 @@ const command$b = {
2363
2377
 
2364
2378
  async function generateCloneCommands({ reporter, config, github, org, ...opt }) {
2365
2379
  if (!opt.listGroups && !opt.all && opt.group === undefined) {
2366
- yargs__default['default'].showHelp();
2380
+ yargs__default["default"].showHelp();
2367
2381
  return;
2368
2382
  }
2369
2383
  const repos = await github.getOrgRepoList({ org });
@@ -2383,7 +2397,7 @@ async function generateCloneCommands({ reporter, config, github, org, ...opt })
2383
2397
  .filter((it) => opt.name === undefined || it.name.includes(opt.name))
2384
2398
  .filter((it) => opt.topic === undefined || includesTopic(it, opt.topic))
2385
2399
  .filter((it) => !opt.excludeExisting ||
2386
- !fs__default['default'].existsSync(path__default['default'].resolve(config.cwd, it.name)))
2400
+ !fs__default["default"].existsSync(path__default["default"].resolve(config.cwd, it.name)))
2387
2401
  .forEach((repo) => {
2388
2402
  // The output of this is used to pipe into e.g. bash.
2389
2403
  // We cannot use reporter.log as it adds additional characters.
@@ -2690,7 +2704,7 @@ async function setToken$1({ reporter, token, tokenProvider, }) {
2690
2704
  reporter.info("Need API token to talk to GitHub");
2691
2705
  reporter.info("https://github.com/settings/tokens/new?scopes=repo:status,read:repo_hook");
2692
2706
  token = await new Promise((resolve, reject) => {
2693
- read__default['default']({
2707
+ read__default["default"]({
2694
2708
  prompt: "Enter new GitHub API token: ",
2695
2709
  silent: true,
2696
2710
  }, (err, answer) => {
@@ -2758,33 +2772,35 @@ class GitRepo {
2758
2772
  this.logCommand = logCommand;
2759
2773
  }
2760
2774
  async cloneGitHubRepo(org, name, cloneType) {
2761
- const parent = path__default['default'].dirname(this.path);
2762
- if (!fs__default['default'].existsSync(parent)) {
2763
- await fs__default['default'].promises.mkdir(parent, { recursive: true });
2775
+ const parent = path__default["default"].dirname(this.path);
2776
+ if (!fs__default["default"].existsSync(parent)) {
2777
+ await fs__default["default"].promises.mkdir(parent, { recursive: true });
2764
2778
  }
2765
2779
  const cloneUrl = cloneType === CloneType.SSH
2766
2780
  ? `git@github.com:${org}/${name}.git`
2767
2781
  : `https://github.com/${org}/${name}.git`;
2768
2782
  try {
2769
- const result = await execa__default['default']("git", ["clone", cloneUrl, this.path], {
2783
+ const result = await execa__default["default"]("git", ["clone", cloneUrl, this.path], {
2770
2784
  cwd: parent,
2771
2785
  });
2772
2786
  await this.logCommand(result);
2773
2787
  }
2774
2788
  catch (e) {
2789
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
2775
2790
  await this.logCommand(e);
2776
2791
  throw e;
2777
2792
  }
2778
2793
  }
2779
2794
  async git(args) {
2780
2795
  try {
2781
- const result = await execa__default['default']("git", args, {
2796
+ const result = await execa__default["default"]("git", args, {
2782
2797
  cwd: this.path,
2783
2798
  });
2784
2799
  await this.logCommand(result);
2785
2800
  return result;
2786
2801
  }
2787
2802
  catch (e) {
2803
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
2788
2804
  await this.logCommand(e);
2789
2805
  throw e;
2790
2806
  }
@@ -2845,11 +2861,11 @@ const CALS_LOG = ".cals.log";
2845
2861
  * backward slashes in paths.
2846
2862
  */
2847
2863
  function getRelpath(it) {
2848
- return path__default['default'].join(it.group, it.name);
2864
+ return path__default["default"].join(it.group, it.name);
2849
2865
  }
2850
2866
  async function appendFile(path, data) {
2851
2867
  return new Promise((resolve, reject) => {
2852
- fs__default['default'].appendFile(path, data, { encoding: "utf-8" }, (err) => {
2868
+ fs__default["default"].appendFile(path, data, { encoding: "utf-8" }, (err) => {
2853
2869
  if (err !== null) {
2854
2870
  reject(err);
2855
2871
  }
@@ -2866,7 +2882,7 @@ function getAliases(repo) {
2866
2882
  }
2867
2883
  async function updateReposInParallel(reporter, items) {
2868
2884
  // Perform git operations in parallel, but limit how much.
2869
- const semaphore = pLimit__default['default'](30);
2885
+ const semaphore = pLimit__default["default"](30);
2870
2886
  const promises = items.map((repo) => semaphore(async () => {
2871
2887
  try {
2872
2888
  return {
@@ -2928,8 +2944,8 @@ async function updateRepos(reporter, foundRepos) {
2928
2944
  }
2929
2945
  }
2930
2946
  function guessDefinitionRepoName(rootdir, cals) {
2931
- const p = path__default['default'].resolve(rootdir, cals.resourcesDefinition.path);
2932
- const relativePath = path__default['default'].relative(rootdir, p);
2947
+ const p = path__default["default"].resolve(rootdir, cals.resourcesDefinition.path);
2948
+ const relativePath = path__default["default"].relative(rootdir, p);
2933
2949
  if (relativePath.slice(0, 1) == ".") {
2934
2950
  return null;
2935
2951
  }
@@ -2942,8 +2958,8 @@ function guessDefinitionRepoName(rootdir, cals) {
2942
2958
  return parts[1];
2943
2959
  }
2944
2960
  async function getDefinition(rootdir, cals) {
2945
- const p = path__default['default'].resolve(rootdir, cals.resourcesDefinition.path);
2946
- if (!fs__default['default'].existsSync(p)) {
2961
+ const p = path__default["default"].resolve(rootdir, cals.resourcesDefinition.path);
2962
+ if (!fs__default["default"].existsSync(p)) {
2947
2963
  throw Error(`The file ${p} does not exist`);
2948
2964
  }
2949
2965
  return new DefinitionFile(p).getDefinition();
@@ -2952,9 +2968,9 @@ async function getDefinition(rootdir, cals) {
2952
2968
  * Get directory names within a directory.
2953
2969
  */
2954
2970
  function getDirNames(parent) {
2955
- return (fs__default['default']
2971
+ return (fs__default["default"]
2956
2972
  .readdirSync(parent)
2957
- .filter((it) => fs__default['default'].statSync(path__default['default'].join(parent, it)).isDirectory())
2973
+ .filter((it) => fs__default["default"].statSync(path__default["default"].join(parent, it)).isDirectory())
2958
2974
  // Skip hidden folders
2959
2975
  .filter((it) => !it.startsWith("."))
2960
2976
  .sort((a, b) => a.localeCompare(b)));
@@ -2966,7 +2982,7 @@ async function getReposInOrg(cals, rootdir) {
2966
2982
  .filter((it) => cals.resourcesDefinition.tags === undefined ||
2967
2983
  (it.project.tags || []).some((tag) => { var _a; return (_a = cals.resourcesDefinition.tags) === null || _a === void 0 ? void 0 : _a.includes(tag); }) ||
2968
2984
  // Always include if already checked out to avoid stale state.
2969
- fs__default['default'].existsSync(path__default['default'].join(rootdir, it.project.name, it.repo.name)));
2985
+ fs__default["default"].existsSync(path__default["default"].join(rootdir, it.project.name, it.repo.name)));
2970
2986
  }
2971
2987
  function getExpectedRepo(item) {
2972
2988
  return {
@@ -2979,8 +2995,8 @@ function getExpectedRepo(item) {
2979
2995
  };
2980
2996
  }
2981
2997
  function getGitRepo(rootdir, relpath) {
2982
- return new GitRepo(path__default['default'].resolve(rootdir, relpath), async (result) => {
2983
- await appendFile(path__default['default'].resolve(rootdir, CALS_LOG), JSON.stringify({
2998
+ return new GitRepo(path__default["default"].resolve(rootdir, relpath), async (result) => {
2999
+ await appendFile(path__default["default"].resolve(rootdir, CALS_LOG), JSON.stringify({
2984
3000
  time: new Date().toISOString(),
2985
3001
  context: relpath,
2986
3002
  type: "exec-result",
@@ -3034,7 +3050,7 @@ async function getExpectedRepos(reporter, github, cals, rootdir) {
3034
3050
  }
3035
3051
  async function getInput(prompt) {
3036
3052
  return new Promise((resolve, reject) => {
3037
- read__default['default']({
3053
+ read__default["default"]({
3038
3054
  prompt,
3039
3055
  timeout: 60000,
3040
3056
  }, (err, answer) => {
@@ -3071,15 +3087,15 @@ async function sync$1({ reporter, github, cals, rootdir, askClone, askMove, }) {
3071
3087
  const foundRepos = [];
3072
3088
  // Categorize all dirs.
3073
3089
  for (const topdir of getDirNames(rootdir)) {
3074
- const isGitDir = fs__default['default'].existsSync(path__default['default'].join(rootdir, topdir, ".git"));
3090
+ const isGitDir = fs__default["default"].existsSync(path__default["default"].join(rootdir, topdir, ".git"));
3075
3091
  if (isGitDir) {
3076
3092
  // Do not traverse deeper inside another Git repo, as that might
3077
3093
  // mean we do not have the proper grouped structure.
3078
3094
  unknownDirs.push(topdir);
3079
3095
  continue;
3080
3096
  }
3081
- for (const subdir of getDirNames(path__default['default'].join(rootdir, topdir))) {
3082
- const p = path__default['default'].join(topdir, subdir);
3097
+ for (const subdir of getDirNames(path__default["default"].join(rootdir, topdir))) {
3098
+ const p = path__default["default"].join(topdir, subdir);
3083
3099
  const expectedRepo = expectedRepos.find((it) => getRelpath(it) === p ||
3084
3100
  it.aliases.some((alias) => getRelpath(alias) === p));
3085
3101
  if (expectedRepo === undefined) {
@@ -3107,9 +3123,9 @@ async function sync$1({ reporter, github, cals, rootdir, askClone, askMove, }) {
3107
3123
  for (const it of archivedRepos) {
3108
3124
  reporter.info(` ${it.actualRelpath}`);
3109
3125
  }
3110
- const thisDirName = path__default['default'].basename(process.cwd());
3126
+ const thisDirName = path__default["default"].basename(process.cwd());
3111
3127
  const archiveDir = `../${thisDirName}-archive`;
3112
- const hasArchiveDir = fs__default['default'].existsSync(archiveDir);
3128
+ const hasArchiveDir = fs__default["default"].existsSync(archiveDir);
3113
3129
  if (hasArchiveDir) {
3114
3130
  reporter.info("To move these:");
3115
3131
  for (const it of archivedRepos) {
@@ -3132,17 +3148,17 @@ async function sync$1({ reporter, github, cals, rootdir, askClone, askMove, }) {
3132
3148
  const shouldMove = await askMoveConfirm();
3133
3149
  if (shouldMove) {
3134
3150
  for (const it of movedRepos) {
3135
- const src = path__default['default'].join(rootdir, it.actualRelpath);
3136
- const dest = path__default['default'].join(rootdir, getRelpath(it));
3137
- const destParent = path__default['default'].join(rootdir, it.group);
3138
- if (fs__default['default'].existsSync(dest)) {
3151
+ const src = path__default["default"].join(rootdir, it.actualRelpath);
3152
+ const dest = path__default["default"].join(rootdir, getRelpath(it));
3153
+ const destParent = path__default["default"].join(rootdir, it.group);
3154
+ if (fs__default["default"].existsSync(dest)) {
3139
3155
  throw new Error(`Target directory already exists: ${dest} - cannot move ${it.actualRelpath}`);
3140
3156
  }
3141
3157
  reporter.info(`Moving ${it.actualRelpath} -> ${getRelpath(it)}`);
3142
- if (!fs__default['default'].existsSync(destParent)) {
3143
- await fs__default['default'].promises.mkdir(destParent, { recursive: true });
3158
+ if (!fs__default["default"].existsSync(destParent)) {
3159
+ await fs__default["default"].promises.mkdir(destParent, { recursive: true });
3144
3160
  }
3145
- await fs__default['default'].promises.rename(src, dest);
3161
+ await fs__default["default"].promises.rename(src, dest);
3146
3162
  }
3147
3163
  // We would have to update expectedRepos if we want to continue.
3148
3164
  // Let's try keeping this simple.
@@ -3186,7 +3202,7 @@ async function sync$1({ reporter, github, cals, rootdir, askClone, askMove, }) {
3186
3202
  }
3187
3203
  }
3188
3204
  async function loadCalsManifest(config, reporter) {
3189
- const p = await findUp__default['default'](CALS_YAML, { cwd: config.cwd });
3205
+ const p = await findUp__default["default"](CALS_YAML, { cwd: config.cwd });
3190
3206
  if (p === undefined) {
3191
3207
  reporter.error(`File ${CALS_YAML} not found. See help`);
3192
3208
  process.exitCode = 1;
@@ -3195,12 +3211,12 @@ async function loadCalsManifest(config, reporter) {
3195
3211
  // TODO: Verify file has expected contents.
3196
3212
  // (Can we easily generate schema for type and verify?)
3197
3213
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-explicit-any
3198
- const cals = yaml__default['default'].load(fs__default['default'].readFileSync(p, "utf-8"));
3214
+ const cals = yaml__default["default"].load(fs__default["default"].readFileSync(p, "utf-8"));
3199
3215
  if (cals.version !== 2) {
3200
3216
  throw new Error(`Unexpected version in ${p}`);
3201
3217
  }
3202
3218
  return {
3203
- dir: path__default['default'].dirname(p),
3219
+ dir: path__default["default"].dirname(p),
3204
3220
  cals,
3205
3221
  };
3206
3222
  }
@@ -3305,20 +3321,23 @@ Notes:
3305
3321
  option to avoid stale cache. The cache can also be cleared with
3306
3322
  the "cals delete-cache" command.`),
3307
3323
  handler: () => {
3308
- yargs__default['default'].showHelp();
3324
+ yargs__default["default"].showHelp();
3309
3325
  },
3310
3326
  };
3311
3327
 
3312
3328
  function totalSeverityCount(project) {
3313
- return (project.issueCountsBySeverity.high +
3329
+ var _a;
3330
+ return (((_a = project.issueCountsBySeverity.critical) !== null && _a !== void 0 ? _a : 0) +
3331
+ project.issueCountsBySeverity.high +
3314
3332
  project.issueCountsBySeverity.medium +
3315
3333
  project.issueCountsBySeverity.low);
3316
3334
  }
3317
3335
  function buildStatsLine(stats) {
3336
+ var _a;
3318
3337
  function item(num, str) {
3319
3338
  return num === 0 ? lodash.repeat(" ", str.length + 4) : sprintfJs.sprintf("%3d %s", num, str);
3320
3339
  }
3321
- return sprintfJs.sprintf("%s %s %s", item(stats.high, "high"), item(stats.medium, "medium"), item(stats.low, "low"));
3340
+ 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"));
3322
3341
  }
3323
3342
  async function report({ reporter, snyk, definitionFile, }) {
3324
3343
  const definition = await definitionFile.getDefinition();
@@ -3342,6 +3361,7 @@ async function report({ reporter, snyk, definitionFile, }) {
3342
3361
  }
3343
3362
  else {
3344
3363
  reporter.info(sprintfJs.sprintf("%-70s %s", "Total count", buildStatsLine({
3364
+ critical: lodash.sumBy(reposWithIssues, (it) => { var _a; return (_a = it.issueCountsBySeverity.critical) !== null && _a !== void 0 ? _a : 0; }),
3345
3365
  high: lodash.sumBy(reposWithIssues, (it) => it.issueCountsBySeverity.high),
3346
3366
  medium: lodash.sumBy(reposWithIssues, (it) => it.issueCountsBySeverity.medium),
3347
3367
  low: lodash.sumBy(reposWithIssues, (it) => it.issueCountsBySeverity.low),
@@ -3350,6 +3370,7 @@ async function report({ reporter, snyk, definitionFile, }) {
3350
3370
  byProjects.forEach((repos) => {
3351
3371
  const project = repos[0].project;
3352
3372
  const totalCount = {
3373
+ critical: lodash.sumBy(repos, (it) => { var _a; return (_a = it.repo.issueCountsBySeverity.critical) !== null && _a !== void 0 ? _a : 0; }),
3353
3374
  high: lodash.sumBy(repos, (it) => it.repo.issueCountsBySeverity.high),
3354
3375
  medium: lodash.sumBy(repos, (it) => it.repo.issueCountsBySeverity.medium),
3355
3376
  low: lodash.sumBy(repos, (it) => it.repo.issueCountsBySeverity.low),
@@ -3378,7 +3399,7 @@ async function setToken({ reporter, token, tokenProvider, }) {
3378
3399
  reporter.info("Need API token to talk to Snyk");
3379
3400
  reporter.info("See https://app.snyk.io/account");
3380
3401
  token = await new Promise((resolve, reject) => {
3381
- read__default['default']({
3402
+ read__default["default"]({
3382
3403
  prompt: "Enter new Snyk API token: ",
3383
3404
  silent: true,
3384
3405
  }, (err, answer) => {
@@ -3449,12 +3470,12 @@ Notes:
3449
3470
  and provide a link to generate one:
3450
3471
  $ cals snyk set-token`),
3451
3472
  handler: () => {
3452
- yargs__default['default'].showHelp();
3473
+ yargs__default["default"].showHelp();
3453
3474
  },
3454
3475
  };
3455
3476
 
3456
3477
  async function main() {
3457
- if (!semver__default['default'].satisfies(process.version, engines.node)) {
3478
+ if (!semver__default["default"].satisfies(process.version, engines.node)) {
3458
3479
  console.error(`Required node version ${engines.node} not satisfied with current version ${process.version}.`);
3459
3480
  process.exit(1);
3460
3481
  }
@@ -3466,12 +3487,12 @@ async function main() {
3466
3487
  / /___/ ___ |/ /______/ /
3467
3488
  \\____/_/ |_/_____/____/
3468
3489
  cli ${version}
3469
- built ${"2021-09-16T15:27:43+0000"}
3490
+ built ${"2022-02-07T10:11:46+0000"}
3470
3491
 
3471
3492
  https://github.com/capralifecycle/cals-cli/
3472
3493
 
3473
3494
  Usage: cals <command>`;
3474
- await yargs__default['default']
3495
+ await yargs__default["default"]
3475
3496
  .usage(header)
3476
3497
  .scriptName("cals")
3477
3498
  .locale("en")