@visulima/cerebro
Version:
A delightful toolkit for building Node-powered CLIs.
244 lines (235 loc) • 8.47 kB
JavaScript
;
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const node_fs = require('node:fs');
const findCacheDir = require('@visulima/find-cache-dir');
const node_https = require('node:https');
var __defProp$4 = Object.defineProperty;
var __name$4 = (target, value) => __defProp$4(target, "name", { value, configurable: true });
const semverGt = /* @__PURE__ */ __name$4((version1, version2) => {
const v1Components = version1.split(".").map(Number);
const v2Components = version2.split(".").map(Number);
for (const [index, v1Component] of v1Components.entries()) {
if (v1Component > v2Components[index]) {
return true;
}
if (v1Component < v2Components[index]) {
return false;
}
}
return false;
}, "semverGt");
var __defProp$3 = Object.defineProperty;
var __name$3 = (target, value) => __defProp$3(target, "name", { value, configurable: true });
var __defProp$2$1 = Object.defineProperty;
var __name$2$1 = /* @__PURE__ */ __name$3((target, value) => __defProp$2$1(target, "name", { value, configurable: true }), "__name$2");
const DRIVE_LETTER_START_RE = /^[A-Z]:\//i;
const normalizeWindowsPath = /* @__PURE__ */ __name$2$1((input = "") => {
if (!input) {
return input;
}
return input.replaceAll("\\", "/").replace(DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
}, "normalizeWindowsPath");
var __defProp2 = Object.defineProperty;
var __name2 = /* @__PURE__ */ __name$3((target, value) => __defProp2(target, "name", { value, configurable: true }), "__name");
const UNC_REGEX = /^[/\\]{2}/;
const IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Z]:[/\\]/i;
const DRIVE_LETTER_RE = /^[A-Z]:$/i;
const normalizeString = /* @__PURE__ */ __name2((path2, allowAboveRoot) => {
let result = "";
let lastSegmentLength = 0;
let lastSlash = -1;
let dots = 0;
let char = null;
for (let index = 0; index <= path2.length; ++index) {
if (index < path2.length) {
char = path2[index];
} else if (char === "/") {
break;
} else {
char = "/";
}
if (char === "/") {
if (lastSlash === index - 1 || dots === 1) ;
else if (dots === 2) {
if (result.length < 2 || lastSegmentLength !== 2 || !result.endsWith(".") || result.at(-2) !== ".") {
if (result.length > 2) {
const lastSlashIndex = result.lastIndexOf("/");
if (lastSlashIndex === -1) {
result = "";
lastSegmentLength = 0;
} else {
result = result.slice(0, lastSlashIndex);
lastSegmentLength = result.length - 1 - result.lastIndexOf("/");
}
lastSlash = index;
dots = 0;
continue;
} else if (result.length > 0) {
result = "";
lastSegmentLength = 0;
lastSlash = index;
dots = 0;
continue;
}
}
if (allowAboveRoot) {
result += result.length > 0 ? "/.." : "..";
lastSegmentLength = 2;
}
} else {
if (result.length > 0) {
result += `/${path2.slice(lastSlash + 1, index)}`;
} else {
result = path2.slice(lastSlash + 1, index);
}
lastSegmentLength = index - lastSlash - 1;
}
lastSlash = index;
dots = 0;
} else if (char === "." && dots !== -1) {
++dots;
} else {
dots = -1;
}
}
return result;
}, "normalizeString");
const isAbsolute = /* @__PURE__ */ __name2((path2) => IS_ABSOLUTE_RE.test(path2), "isAbsolute");
const normalize = /* @__PURE__ */ __name2(function(path2) {
if (path2.length === 0) {
return ".";
}
path2 = normalizeWindowsPath(path2);
const isUNCPath = UNC_REGEX.exec(path2);
const isPathAbsolute = isAbsolute(path2);
const trailingSeparator = path2.at(-1) === "/";
path2 = normalizeString(path2, !isPathAbsolute);
if (path2.length === 0) {
if (isPathAbsolute) {
return "/";
}
return trailingSeparator ? "./" : ".";
}
if (trailingSeparator) {
path2 += "/";
}
if (DRIVE_LETTER_RE.test(path2)) {
path2 += "/";
}
if (isUNCPath) {
if (!isPathAbsolute) {
return `//./${path2}`;
}
return `//${path2}`;
}
return isPathAbsolute && !isAbsolute(path2) ? `/${path2}` : path2;
}, "normalize");
const join = /* @__PURE__ */ __name2((...segments) => {
let path2 = "";
for (const seg of segments) {
if (!seg) {
continue;
}
if (path2.length > 0) {
const pathTrailing = path2[path2.length - 1] === "/";
const segLeading = seg[0] === "/";
const both = pathTrailing && segLeading;
if (both) {
path2 += seg.slice(1);
} else {
path2 += pathTrailing || segLeading ? seg : `/${seg}`;
}
} else {
path2 += seg;
}
}
return normalize(path2);
}, "join");
const dirname = /* @__PURE__ */ __name2((path2) => {
const segments = normalizeWindowsPath(path2).replace(/\/$/, "").split("/").slice(0, -1);
if (segments.length === 1 && DRIVE_LETTER_RE.test(segments[0])) {
segments[0] += "/";
}
return segments.join("/") || (isAbsolute(path2) ? "/" : ".");
}, "dirname");
var __defProp$2 = Object.defineProperty;
var __name$2 = (target, value) => __defProp$2(target, "name", { value, configurable: true });
const FILE_NAME = "last-update-check.json";
const getConfigFile = /* @__PURE__ */ __name$2((packageName) => {
const cacheDirectory = findCacheDir.findCacheDirSync(packageName);
if (cacheDirectory === void 0) {
throw new Error("Could not find cache directory");
}
return join(cacheDirectory, FILE_NAME);
}, "getConfigFile");
const getLastUpdate = /* @__PURE__ */ __name$2((packageName) => {
const configFile = getConfigFile(packageName);
try {
if (!node_fs.existsSync(configFile)) {
return void 0;
}
const { lastUpdateCheck } = JSON.parse(node_fs.readFileSync(configFile, "utf8"));
return lastUpdateCheck;
} catch {
return void 0;
}
}, "getLastUpdate");
const saveLastUpdate = /* @__PURE__ */ __name$2((packageName) => {
const configFile = getConfigFile(packageName);
const configDirectory = dirname(configFile);
if (!node_fs.existsSync(configDirectory)) {
node_fs.mkdirSync(configDirectory, { recursive: true });
}
node_fs.writeFileSync(configFile, JSON.stringify({ lastUpdateCheck: Date.now() }));
}, "saveLastUpdate");
var __defProp$1 = Object.defineProperty;
var __name$1 = (target, value) => __defProp$1(target, "name", { value, configurable: true });
const getDistributionVersion = /* @__PURE__ */ __name$1(async (packageName, distributionTag, registryUrl) => {
const url = registryUrl.replace("__NAME__", packageName);
return await new Promise((resolve, reject) => {
node_https.get(url, (message) => {
let body = "";
message.on("data", (chunk) => body += chunk);
message.on("end", () => {
try {
const json = JSON.parse(body);
const version = json[distributionTag];
if (!version) {
reject(new Error("Error getting version"));
}
resolve(version);
} catch {
reject(new Error("Could not parse version response"));
}
});
}).on("error", (error) => reject(error));
});
}, "getDistributionVersion");
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
const hasNewVersion = /* @__PURE__ */ __name(async ({
alwaysRun,
debug,
distTag: distributionTag = "latest",
pkg,
registryUrl = "https://registry.npmjs.org/-/package/__NAME__/dist-tags",
updateCheckInterval = 1e3 * 60 * 60 * 24
}) => {
const lastUpdateCheck = getLastUpdate(pkg.name);
if (alwaysRun || !lastUpdateCheck || lastUpdateCheck < Date.now() - updateCheckInterval) {
const latestVersion = await getDistributionVersion(pkg.name, distributionTag, registryUrl);
saveLastUpdate(pkg.name);
if (semverGt(latestVersion, pkg.version)) {
return latestVersion;
}
if (debug) {
console.error(`Latest version (${latestVersion}) not newer than current version (${pkg.version})`);
}
} else if (debug) {
console.error(
`Too recent to check for a new update. simpleUpdateNotifier() interval set to ${updateCheckInterval}ms but only ${Date.now() - lastUpdateCheck}ms since last check.`
);
}
return null;
}, "hasNewVersion");
exports.default = hasNewVersion;