@flyingboat/upup 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +11 -0
  2. package/dist/bundle.js +86 -34
  3. package/package.json +8 -5
package/README.md CHANGED
@@ -9,6 +9,12 @@ npm install -g @flyingboat/upup
9
9
  pnpm add -g @flyingboat/upup
10
10
  ```
11
11
 
12
+ or via npx:
13
+ ```
14
+ npx @flyingboat/upup
15
+ pnpm dlx @flyingboat/upup
16
+ ```
17
+
12
18
  ## Usage
13
19
 
14
20
  Run in the current project:
@@ -17,3 +23,8 @@ Run in the current project:
17
23
  upup
18
24
  ```
19
25
 
26
+ for CICD
27
+
28
+ ```
29
+ upup --ci
30
+ ```
package/dist/bundle.js CHANGED
@@ -60,6 +60,31 @@ const yellow = (t) => wrap(t, codes.yellow);
60
60
  const gray = (t) => wrap(t, codes.gray);
61
61
  const bold = (t) => wrap(t, codes.bold);
62
62
 
63
+ //#endregion
64
+ //#region src/cli-compact.ts
65
+ function renderCompact(rows) {
66
+ console.log(compact$1(rows).join("\n"));
67
+ }
68
+ function compact$1(rows) {
69
+ const content = [];
70
+ for (const row of rows) {
71
+ content.push(...block(row));
72
+ content.push("");
73
+ }
74
+ return content;
75
+ }
76
+ function block(row) {
77
+ const content = [];
78
+ let status = row.status;
79
+ if (status === "need update") status = yellow(status);
80
+ else if (status === "ok") status = green(status);
81
+ content.push(`[${bold(row.package)}]`);
82
+ content.push(` status: ${status}`);
83
+ content.push(` current: ${row.current} (${row.age} ago)`);
84
+ if (row.status === "need update") content.push(` latest: ${row.latest} (${row.latestAge} ago) change: ${row.change}`);
85
+ return content;
86
+ }
87
+
63
88
  //#endregion
64
89
  //#region src/cli-table.ts
65
90
  const leftTopCorner = "┌";
@@ -1605,12 +1630,13 @@ function timeAgoFromAge(ts) {
1605
1630
  if (ts < hour) return plural(Math.floor(ts / minute), "min");
1606
1631
  if (ts < day) return plural(Math.floor(ts / hour), "hour");
1607
1632
  if (ts < year) {
1608
- if (ts > month) return plural(Math.floor(ts / month), "month");
1633
+ if (ts >= month) return plural(Math.floor(ts / month), "month");
1609
1634
  return plural(Math.floor(ts / day), "day");
1610
1635
  }
1611
1636
  return plural(Math.floor(ts / year), "year");
1612
1637
  }
1613
1638
  function getBump(current, latest) {
1639
+ if (!import_semver.default.prerelease(current) && import_semver.default.prerelease(latest)) return "prerelease";
1614
1640
  const c = import_semver.default.coerce(current)?.version;
1615
1641
  const l = import_semver.default.coerce(latest)?.version;
1616
1642
  if (!c || !l) return "invalid";
@@ -1624,7 +1650,6 @@ function getBump(current, latest) {
1624
1650
 
1625
1651
  //#endregion
1626
1652
  //#region src/cli.ts
1627
- const defaultRefreshInterval = 80;
1628
1653
  const spinnerFrames = [
1629
1654
  "⠋",
1630
1655
  "⠙",
@@ -1637,6 +1662,7 @@ const spinnerFrames = [
1637
1662
  "⠇",
1638
1663
  "⠏"
1639
1664
  ];
1665
+ const defaultCtx = { refreshInterval: 80 };
1640
1666
  var Renderer = class {
1641
1667
  _renderFn;
1642
1668
  constructor(renderFn) {
@@ -1646,38 +1672,58 @@ var Renderer = class {
1646
1672
  this._renderFn(props);
1647
1673
  }
1648
1674
  };
1649
- function spinner(refreshInterval = defaultRefreshInterval) {
1650
- return spinnerFrames[Math.floor(Date.now() / refreshInterval) % spinnerFrames.length];
1675
+ function spinner(ctx) {
1676
+ return spinnerFrames[Math.floor(Date.now() / ctx.refreshInterval) % spinnerFrames.length];
1651
1677
  }
1652
- function renderDepsTable(rows, refreshInterval = defaultRefreshInterval) {
1653
- const nDeps = rows.filter((x) => x.dep.type === "dep").length;
1654
- const nDevDeps = rows.filter((x) => x.dep.type === "devDep").length;
1655
- const fn = (r) => {
1656
- if (r.status === "error") console.error(`Failed to fetch ${r.dep.name}`);
1657
- let age = r.dep.versionValid ? "-" : "invalid version";
1658
- if (!r.dep.localDep && r.dep.versionValid) age = r.dep.versionAge ? timeAgoFromAge(r.dep.versionAge) : spinner(refreshInterval);
1659
- let latestAge = r.dep.localDep ? "-" : spinner(refreshInterval);
1660
- if (!r.dep.localDep && r.dep.latestVersionAge) latestAge = timeAgoFromAge(r.dep.latestVersionAge);
1661
- const status = r.status === "pending" ? spinner(refreshInterval) : r.status === "done" && r.needUpdate ? "need update" : "ok";
1662
- const change = r.needUpdate ? getBump(r.dep.version, r.dep.latestVersion ?? "") : "-";
1663
- return {
1664
- package: r.dep.name,
1665
- current: r.dep.version,
1666
- age,
1667
- latest: r.dep.latestVersion ?? spinner(refreshInterval),
1668
- latestAge,
1669
- status,
1670
- change
1671
- };
1678
+ function parseRow(r, ctx) {
1679
+ if (r.status === "error") console.error(`Failed to fetch ${r.dep.name}`);
1680
+ let age = r.dep.versionValid ? "-" : "invalid version";
1681
+ if (!r.dep.localDep && r.dep.versionValid) age = r.dep.versionAge ? timeAgoFromAge(r.dep.versionAge) : spinner(ctx);
1682
+ let latestAge = r.dep.localDep ? "-" : spinner(ctx);
1683
+ if (!r.dep.localDep && r.dep.latestVersionAge) latestAge = timeAgoFromAge(r.dep.latestVersionAge);
1684
+ const status = r.status === "pending" ? spinner(ctx) : r.status === "done" && r.needUpdate ? "need update" : "ok";
1685
+ const change = r.needUpdate ? getBump(r.dep.version, r.dep.latestVersion ?? "") : "-";
1686
+ return {
1687
+ package: r.dep.name,
1688
+ current: r.dep.version,
1689
+ age,
1690
+ latest: r.dep.latestVersion ?? spinner(ctx),
1691
+ latestAge,
1692
+ status,
1693
+ change
1672
1694
  };
1673
- if (nDeps > 0) {
1674
- console.log(`${nDeps} Dependencies`);
1675
- renderTable(rows.filter((x) => x.dep.type === "dep").map((r) => fn(r)));
1695
+ }
1696
+ function unwrap(rows, ctx) {
1697
+ return {
1698
+ deps: rows.filter((x) => x.dep.type === "dep").map((r) => parseRow(r, ctx)),
1699
+ devDeps: rows.filter((x) => x.dep.type === "devDep").map((r) => parseRow(r, ctx))
1700
+ };
1701
+ }
1702
+ function pluralDependency(n) {
1703
+ return `${n} Dependenc${n === 1 ? "y" : "ies"}`;
1704
+ }
1705
+ function renderDepsCompact(rows, ctx) {
1706
+ const { deps, devDeps } = unwrap(rows, ctx);
1707
+ if (deps.length > 0) {
1708
+ console.log(`${pluralDependency(deps.length)}\n`);
1709
+ renderCompact(deps);
1676
1710
  }
1677
- if (nDevDeps > 0) {
1678
- if (nDeps > 0) console.log("");
1679
- console.log(`${nDevDeps} Dev Dependencies`);
1680
- renderTable(rows.filter((x) => x.dep.type === "devDep").map((r) => fn(r)));
1711
+ if (devDeps.length > 0) {
1712
+ if (deps.length > 0) console.log("");
1713
+ console.log(`${pluralDependency(devDeps.length)}\n`);
1714
+ renderCompact(devDeps);
1715
+ }
1716
+ }
1717
+ function renderDepsTable(rows, ctx) {
1718
+ const { deps, devDeps } = unwrap(rows, ctx);
1719
+ if (deps.length > 0) {
1720
+ console.log(`${pluralDependency(deps.length)}\n`);
1721
+ renderTable(deps);
1722
+ }
1723
+ if (devDeps.length > 0) {
1724
+ if (deps.length > 0) console.log("");
1725
+ console.log(`${pluralDependency(devDeps.length)}\n`);
1726
+ renderTable(devDeps);
1681
1727
  }
1682
1728
  }
1683
1729
 
@@ -1743,17 +1789,23 @@ if (!process$1 || !process$1.argv) {
1743
1789
  }
1744
1790
  let args = process$1.argv;
1745
1791
  args = args.slice(2);
1792
+ let compact = false;
1746
1793
  let ci = false;
1747
1794
  let cwd = process$1.cwd();
1748
1795
  if (args.length > 0) for (const arg of args) if (arg.startsWith("--")) {
1749
1796
  if (arg === "--ci") ci = true;
1797
+ else if (arg === "--compact") compact = true;
1750
1798
  } else cwd = args[0];
1751
- const refreshInterval = 80;
1799
+ const ctx = defaultCtx;
1752
1800
  async function run() {
1753
1801
  console.log("Checking for packages updates ...\n");
1754
1802
  const renderer = new Renderer((props) => {
1755
1803
  if (!ci) console.clear();
1756
- renderDepsTable(props.deps);
1804
+ if (compact) {
1805
+ renderDepsCompact(props.deps, ctx);
1806
+ return;
1807
+ }
1808
+ renderDepsTable(props.deps, ctx);
1757
1809
  });
1758
1810
  const pkgFile = `${cwd}/package.json`;
1759
1811
  if (!fs.existsSync(pkgFile)) {
@@ -1765,7 +1817,7 @@ async function run() {
1765
1817
  needUpdate: false,
1766
1818
  status: "pending"
1767
1819
  })) };
1768
- const ticker = ci ? null : setInterval(() => renderer.render(props), refreshInterval);
1820
+ const ticker = ci ? null : setInterval(() => renderer.render(props), ctx.refreshInterval);
1769
1821
  const tasks = props.deps.map(async (row) => {
1770
1822
  try {
1771
1823
  if (row.dep.localDep) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flyingboat/upup",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "CLI tool for listing outdated dependencies",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Francois Lajoie",
@@ -19,17 +19,20 @@
19
19
  "dev": "node src/main.ts",
20
20
  "build": "rolldown -c rolldown.config.ts",
21
21
  "check": "pnpm dlx @biomejs/biome check --write",
22
- "prepublish": "pnpm run check && pnpm run build"
22
+ "prepublish": "pnpm test && pnpm run check && pnpm run build",
23
+ "test": "vitest run",
24
+ "test:watch": "vitest run --watch"
23
25
  },
24
- "packageManager": "pnpm@10.29.1",
26
+ "packageManager": "pnpm@10.29.2",
25
27
  "dependencies": {
26
28
  "semver": "^7.7.4"
27
29
  },
28
30
  "devDependencies": {
29
- "@biomejs/biome": "^4.3.14",
31
+ "@biomejs/biome": "^2.3.14",
30
32
  "@types/node": "^25.2.2",
31
33
  "@types/semver": "^7.7.1",
32
34
  "rolldown": "^1.0.0-rc.3",
33
- "typescript": "~5.9.3"
35
+ "typescript": "~5.9.3",
36
+ "vitest": "^4.0.18"
34
37
  }
35
38
  }