@freecodecamp/universe-cli 0.7.1 → 0.7.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/dist/index.cjs +157 -1
- package/dist/index.js +157 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -24621,8 +24621,162 @@ async function update(options, deps = {}) {
|
|
|
24621
24621
|
}
|
|
24622
24622
|
}
|
|
24623
24623
|
|
|
24624
|
+
// src/lib/update-notifier.ts
|
|
24625
|
+
var import_node_fs3 = require("fs");
|
|
24626
|
+
var import_promises8 = require("fs/promises");
|
|
24627
|
+
var import_node_os2 = require("os");
|
|
24628
|
+
var import_node_path9 = require("path");
|
|
24629
|
+
var APP_DIR2 = "universe-cli";
|
|
24630
|
+
var CACHE_FILE = "update-check.json";
|
|
24631
|
+
var PKG_NAME = "@freecodecamp/universe-cli";
|
|
24632
|
+
var NPM_LATEST_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
24633
|
+
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
24634
|
+
var FETCH_TIMEOUT_MS = 3e3;
|
|
24635
|
+
function configBase2() {
|
|
24636
|
+
const xdg = process.env["XDG_CONFIG_HOME"];
|
|
24637
|
+
if (xdg && xdg.length > 0) return xdg;
|
|
24638
|
+
return (0, import_node_path9.join)((0, import_node_os2.homedir)(), ".config");
|
|
24639
|
+
}
|
|
24640
|
+
function cachePath() {
|
|
24641
|
+
return (0, import_node_path9.join)(configBase2(), APP_DIR2, CACHE_FILE);
|
|
24642
|
+
}
|
|
24643
|
+
function isDisabled() {
|
|
24644
|
+
const v = process.env["UNIVERSE_NO_UPDATE_CHECK"];
|
|
24645
|
+
return v === "1" || v === "true";
|
|
24646
|
+
}
|
|
24647
|
+
function parseCache(raw) {
|
|
24648
|
+
let parsed;
|
|
24649
|
+
try {
|
|
24650
|
+
parsed = JSON.parse(raw);
|
|
24651
|
+
} catch {
|
|
24652
|
+
return null;
|
|
24653
|
+
}
|
|
24654
|
+
if (typeof parsed !== "object" || parsed === null || !("latest" in parsed) || !("lastCheck" in parsed)) {
|
|
24655
|
+
return null;
|
|
24656
|
+
}
|
|
24657
|
+
const { latest, lastCheck } = parsed;
|
|
24658
|
+
if (typeof latest !== "string" || typeof lastCheck !== "number") {
|
|
24659
|
+
return null;
|
|
24660
|
+
}
|
|
24661
|
+
return { latest, lastCheck };
|
|
24662
|
+
}
|
|
24663
|
+
async function readCache() {
|
|
24664
|
+
try {
|
|
24665
|
+
const raw = await (0, import_promises8.readFile)(cachePath(), "utf-8");
|
|
24666
|
+
return parseCache(raw);
|
|
24667
|
+
} catch {
|
|
24668
|
+
return null;
|
|
24669
|
+
}
|
|
24670
|
+
}
|
|
24671
|
+
function readCacheSync() {
|
|
24672
|
+
try {
|
|
24673
|
+
const raw = (0, import_node_fs3.readFileSync)(cachePath(), "utf-8");
|
|
24674
|
+
return parseCache(raw);
|
|
24675
|
+
} catch {
|
|
24676
|
+
return null;
|
|
24677
|
+
}
|
|
24678
|
+
}
|
|
24679
|
+
async function writeCache(c2) {
|
|
24680
|
+
const path = cachePath();
|
|
24681
|
+
await (0, import_promises8.mkdir)((0, import_node_path9.dirname)(path), { recursive: true, mode: 448 });
|
|
24682
|
+
await (0, import_promises8.writeFile)(path, JSON.stringify(c2), { mode: 420 });
|
|
24683
|
+
}
|
|
24684
|
+
async function fetchLatest() {
|
|
24685
|
+
const ctl = new AbortController();
|
|
24686
|
+
const timer = setTimeout(() => ctl.abort(), FETCH_TIMEOUT_MS);
|
|
24687
|
+
try {
|
|
24688
|
+
const res = await fetch(NPM_LATEST_URL, {
|
|
24689
|
+
signal: ctl.signal,
|
|
24690
|
+
headers: { accept: "application/json" }
|
|
24691
|
+
});
|
|
24692
|
+
if (!res.ok) return null;
|
|
24693
|
+
const body = await res.json();
|
|
24694
|
+
return typeof body.version === "string" ? body.version : null;
|
|
24695
|
+
} catch {
|
|
24696
|
+
return null;
|
|
24697
|
+
} finally {
|
|
24698
|
+
clearTimeout(timer);
|
|
24699
|
+
}
|
|
24700
|
+
}
|
|
24701
|
+
function compareVersions(a, b) {
|
|
24702
|
+
const pa = parseVersion(a);
|
|
24703
|
+
const pb = parseVersion(b);
|
|
24704
|
+
if (pa === null || pb === null) return 0;
|
|
24705
|
+
for (let i = 0; i < 3; i += 1) {
|
|
24706
|
+
const ai = pa[i] ?? 0;
|
|
24707
|
+
const bi = pb[i] ?? 0;
|
|
24708
|
+
if (ai < bi) return -1;
|
|
24709
|
+
if (ai > bi) return 1;
|
|
24710
|
+
}
|
|
24711
|
+
return 0;
|
|
24712
|
+
}
|
|
24713
|
+
function parseVersion(s) {
|
|
24714
|
+
const core = s.split("-")[0] ?? "";
|
|
24715
|
+
const parts = core.split(".");
|
|
24716
|
+
if (parts.length !== 3) return null;
|
|
24717
|
+
const nums = parts.map((p2) => Number.parseInt(p2, 10));
|
|
24718
|
+
if (nums.some((n) => Number.isNaN(n))) return null;
|
|
24719
|
+
return [nums[0], nums[1], nums[2]];
|
|
24720
|
+
}
|
|
24721
|
+
async function refreshIfStale(now = Date.now()) {
|
|
24722
|
+
if (isDisabled()) return;
|
|
24723
|
+
const cache = await readCache();
|
|
24724
|
+
if (cache !== null && now - cache.lastCheck < TTL_MS) return;
|
|
24725
|
+
const latest = await fetchLatest();
|
|
24726
|
+
if (latest === null) return;
|
|
24727
|
+
try {
|
|
24728
|
+
await writeCache({ latest, lastCheck: now });
|
|
24729
|
+
} catch {
|
|
24730
|
+
}
|
|
24731
|
+
}
|
|
24732
|
+
function getNoticeSync(current) {
|
|
24733
|
+
if (isDisabled()) return null;
|
|
24734
|
+
const cache = readCacheSync();
|
|
24735
|
+
if (cache === null) return null;
|
|
24736
|
+
if (compareVersions(current, cache.latest) >= 0) return null;
|
|
24737
|
+
return { current, latest: cache.latest };
|
|
24738
|
+
}
|
|
24739
|
+
function useColor() {
|
|
24740
|
+
if (process.env["NO_COLOR"] && process.env["NO_COLOR"].length > 0) {
|
|
24741
|
+
return false;
|
|
24742
|
+
}
|
|
24743
|
+
return process.stderr.isTTY === true;
|
|
24744
|
+
}
|
|
24745
|
+
function paint(s, code, color) {
|
|
24746
|
+
if (!color) return s;
|
|
24747
|
+
return `\x1B[${code}m${s}\x1B[0m`;
|
|
24748
|
+
}
|
|
24749
|
+
function formatNotice(n, color = useColor()) {
|
|
24750
|
+
const dim = (s) => paint(s, "2", color);
|
|
24751
|
+
const yellow = (s) => paint(s, "33", color);
|
|
24752
|
+
const cyan = (s) => paint(s, "36", color);
|
|
24753
|
+
const bar = dim("\u2502");
|
|
24754
|
+
const lines = [
|
|
24755
|
+
"",
|
|
24756
|
+
bar,
|
|
24757
|
+
`${yellow("\u25B2")} Update available: ${dim(n.current)} \u2192 ${cyan(n.latest)}`,
|
|
24758
|
+
`${bar} Run ${cyan(`npm i -g ${PKG_NAME}`)} to upgrade`,
|
|
24759
|
+
dim("\u2514"),
|
|
24760
|
+
""
|
|
24761
|
+
];
|
|
24762
|
+
return lines.join("\n");
|
|
24763
|
+
}
|
|
24764
|
+
function installExitNotice(current) {
|
|
24765
|
+
if (isDisabled()) return;
|
|
24766
|
+
let printed = false;
|
|
24767
|
+
const emit = () => {
|
|
24768
|
+
if (printed) return;
|
|
24769
|
+
printed = true;
|
|
24770
|
+
const n = getNoticeSync(current);
|
|
24771
|
+
if (n === null) return;
|
|
24772
|
+
process.stderr.write(formatNotice(n));
|
|
24773
|
+
};
|
|
24774
|
+
process.on("beforeExit", emit);
|
|
24775
|
+
process.on("exit", emit);
|
|
24776
|
+
}
|
|
24777
|
+
|
|
24624
24778
|
// src/cli.ts
|
|
24625
|
-
var version2 = true ? "0.7.
|
|
24779
|
+
var version2 = true ? "0.7.2" : "0.0.0";
|
|
24626
24780
|
function handleActionError(command, json2, err) {
|
|
24627
24781
|
const ctx = { json: json2, command };
|
|
24628
24782
|
const message = err instanceof Error ? err.message : "unknown error";
|
|
@@ -24638,6 +24792,8 @@ function findFirstPositional(args) {
|
|
|
24638
24792
|
return -1;
|
|
24639
24793
|
}
|
|
24640
24794
|
function run(argv = process.argv) {
|
|
24795
|
+
installExitNotice(version2);
|
|
24796
|
+
void refreshIfStale();
|
|
24641
24797
|
const args = argv.slice(2);
|
|
24642
24798
|
const firstPosIdx = findFirstPositional(args);
|
|
24643
24799
|
const namespace = firstPosIdx >= 0 ? args[firstPosIdx] : void 0;
|
package/dist/index.js
CHANGED
|
@@ -2130,8 +2130,162 @@ async function update(options, deps = {}) {
|
|
|
2130
2130
|
}
|
|
2131
2131
|
}
|
|
2132
2132
|
|
|
2133
|
+
// src/lib/update-notifier.ts
|
|
2134
|
+
import { readFileSync } from "fs";
|
|
2135
|
+
import { mkdir as mkdir2, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
|
|
2136
|
+
import { homedir as homedir2 } from "os";
|
|
2137
|
+
import { dirname as dirname2, join as join3 } from "path";
|
|
2138
|
+
var APP_DIR2 = "universe-cli";
|
|
2139
|
+
var CACHE_FILE = "update-check.json";
|
|
2140
|
+
var PKG_NAME = "@freecodecamp/universe-cli";
|
|
2141
|
+
var NPM_LATEST_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
2142
|
+
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
2143
|
+
var FETCH_TIMEOUT_MS = 3e3;
|
|
2144
|
+
function configBase2() {
|
|
2145
|
+
const xdg = process.env["XDG_CONFIG_HOME"];
|
|
2146
|
+
if (xdg && xdg.length > 0) return xdg;
|
|
2147
|
+
return join3(homedir2(), ".config");
|
|
2148
|
+
}
|
|
2149
|
+
function cachePath() {
|
|
2150
|
+
return join3(configBase2(), APP_DIR2, CACHE_FILE);
|
|
2151
|
+
}
|
|
2152
|
+
function isDisabled() {
|
|
2153
|
+
const v = process.env["UNIVERSE_NO_UPDATE_CHECK"];
|
|
2154
|
+
return v === "1" || v === "true";
|
|
2155
|
+
}
|
|
2156
|
+
function parseCache(raw) {
|
|
2157
|
+
let parsed;
|
|
2158
|
+
try {
|
|
2159
|
+
parsed = JSON.parse(raw);
|
|
2160
|
+
} catch {
|
|
2161
|
+
return null;
|
|
2162
|
+
}
|
|
2163
|
+
if (typeof parsed !== "object" || parsed === null || !("latest" in parsed) || !("lastCheck" in parsed)) {
|
|
2164
|
+
return null;
|
|
2165
|
+
}
|
|
2166
|
+
const { latest, lastCheck } = parsed;
|
|
2167
|
+
if (typeof latest !== "string" || typeof lastCheck !== "number") {
|
|
2168
|
+
return null;
|
|
2169
|
+
}
|
|
2170
|
+
return { latest, lastCheck };
|
|
2171
|
+
}
|
|
2172
|
+
async function readCache() {
|
|
2173
|
+
try {
|
|
2174
|
+
const raw = await readFile6(cachePath(), "utf-8");
|
|
2175
|
+
return parseCache(raw);
|
|
2176
|
+
} catch {
|
|
2177
|
+
return null;
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
function readCacheSync() {
|
|
2181
|
+
try {
|
|
2182
|
+
const raw = readFileSync(cachePath(), "utf-8");
|
|
2183
|
+
return parseCache(raw);
|
|
2184
|
+
} catch {
|
|
2185
|
+
return null;
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
async function writeCache(c) {
|
|
2189
|
+
const path = cachePath();
|
|
2190
|
+
await mkdir2(dirname2(path), { recursive: true, mode: 448 });
|
|
2191
|
+
await writeFile2(path, JSON.stringify(c), { mode: 420 });
|
|
2192
|
+
}
|
|
2193
|
+
async function fetchLatest() {
|
|
2194
|
+
const ctl = new AbortController();
|
|
2195
|
+
const timer = setTimeout(() => ctl.abort(), FETCH_TIMEOUT_MS);
|
|
2196
|
+
try {
|
|
2197
|
+
const res = await fetch(NPM_LATEST_URL, {
|
|
2198
|
+
signal: ctl.signal,
|
|
2199
|
+
headers: { accept: "application/json" }
|
|
2200
|
+
});
|
|
2201
|
+
if (!res.ok) return null;
|
|
2202
|
+
const body = await res.json();
|
|
2203
|
+
return typeof body.version === "string" ? body.version : null;
|
|
2204
|
+
} catch {
|
|
2205
|
+
return null;
|
|
2206
|
+
} finally {
|
|
2207
|
+
clearTimeout(timer);
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
function compareVersions(a, b) {
|
|
2211
|
+
const pa = parseVersion(a);
|
|
2212
|
+
const pb = parseVersion(b);
|
|
2213
|
+
if (pa === null || pb === null) return 0;
|
|
2214
|
+
for (let i = 0; i < 3; i += 1) {
|
|
2215
|
+
const ai = pa[i] ?? 0;
|
|
2216
|
+
const bi = pb[i] ?? 0;
|
|
2217
|
+
if (ai < bi) return -1;
|
|
2218
|
+
if (ai > bi) return 1;
|
|
2219
|
+
}
|
|
2220
|
+
return 0;
|
|
2221
|
+
}
|
|
2222
|
+
function parseVersion(s) {
|
|
2223
|
+
const core = s.split("-")[0] ?? "";
|
|
2224
|
+
const parts = core.split(".");
|
|
2225
|
+
if (parts.length !== 3) return null;
|
|
2226
|
+
const nums = parts.map((p) => Number.parseInt(p, 10));
|
|
2227
|
+
if (nums.some((n) => Number.isNaN(n))) return null;
|
|
2228
|
+
return [nums[0], nums[1], nums[2]];
|
|
2229
|
+
}
|
|
2230
|
+
async function refreshIfStale(now = Date.now()) {
|
|
2231
|
+
if (isDisabled()) return;
|
|
2232
|
+
const cache = await readCache();
|
|
2233
|
+
if (cache !== null && now - cache.lastCheck < TTL_MS) return;
|
|
2234
|
+
const latest = await fetchLatest();
|
|
2235
|
+
if (latest === null) return;
|
|
2236
|
+
try {
|
|
2237
|
+
await writeCache({ latest, lastCheck: now });
|
|
2238
|
+
} catch {
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
function getNoticeSync(current) {
|
|
2242
|
+
if (isDisabled()) return null;
|
|
2243
|
+
const cache = readCacheSync();
|
|
2244
|
+
if (cache === null) return null;
|
|
2245
|
+
if (compareVersions(current, cache.latest) >= 0) return null;
|
|
2246
|
+
return { current, latest: cache.latest };
|
|
2247
|
+
}
|
|
2248
|
+
function useColor() {
|
|
2249
|
+
if (process.env["NO_COLOR"] && process.env["NO_COLOR"].length > 0) {
|
|
2250
|
+
return false;
|
|
2251
|
+
}
|
|
2252
|
+
return process.stderr.isTTY === true;
|
|
2253
|
+
}
|
|
2254
|
+
function paint(s, code, color) {
|
|
2255
|
+
if (!color) return s;
|
|
2256
|
+
return `\x1B[${code}m${s}\x1B[0m`;
|
|
2257
|
+
}
|
|
2258
|
+
function formatNotice(n, color = useColor()) {
|
|
2259
|
+
const dim = (s) => paint(s, "2", color);
|
|
2260
|
+
const yellow = (s) => paint(s, "33", color);
|
|
2261
|
+
const cyan = (s) => paint(s, "36", color);
|
|
2262
|
+
const bar = dim("\u2502");
|
|
2263
|
+
const lines = [
|
|
2264
|
+
"",
|
|
2265
|
+
bar,
|
|
2266
|
+
`${yellow("\u25B2")} Update available: ${dim(n.current)} \u2192 ${cyan(n.latest)}`,
|
|
2267
|
+
`${bar} Run ${cyan(`npm i -g ${PKG_NAME}`)} to upgrade`,
|
|
2268
|
+
dim("\u2514"),
|
|
2269
|
+
""
|
|
2270
|
+
];
|
|
2271
|
+
return lines.join("\n");
|
|
2272
|
+
}
|
|
2273
|
+
function installExitNotice(current) {
|
|
2274
|
+
if (isDisabled()) return;
|
|
2275
|
+
let printed = false;
|
|
2276
|
+
const emit = () => {
|
|
2277
|
+
if (printed) return;
|
|
2278
|
+
printed = true;
|
|
2279
|
+
const n = getNoticeSync(current);
|
|
2280
|
+
if (n === null) return;
|
|
2281
|
+
process.stderr.write(formatNotice(n));
|
|
2282
|
+
};
|
|
2283
|
+
process.on("beforeExit", emit);
|
|
2284
|
+
process.on("exit", emit);
|
|
2285
|
+
}
|
|
2286
|
+
|
|
2133
2287
|
// src/cli.ts
|
|
2134
|
-
var version = true ? "0.7.
|
|
2288
|
+
var version = true ? "0.7.2" : "0.0.0";
|
|
2135
2289
|
function handleActionError(command, json, err) {
|
|
2136
2290
|
const ctx = { json, command };
|
|
2137
2291
|
const message = err instanceof Error ? err.message : "unknown error";
|
|
@@ -2147,6 +2301,8 @@ function findFirstPositional(args) {
|
|
|
2147
2301
|
return -1;
|
|
2148
2302
|
}
|
|
2149
2303
|
function run(argv = process.argv) {
|
|
2304
|
+
installExitNotice(version);
|
|
2305
|
+
void refreshIfStale();
|
|
2150
2306
|
const args = argv.slice(2);
|
|
2151
2307
|
const firstPosIdx = findFirstPositional(args);
|
|
2152
2308
|
const namespace = firstPosIdx >= 0 ? args[firstPosIdx] : void 0;
|