@review-my-code/rmcode 0.1.2 → 0.1.3
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/cli.js +121 -14
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -9,7 +9,7 @@ const path_1 = require("path");
|
|
|
9
9
|
const readline_1 = require("readline");
|
|
10
10
|
const API_URL = process.env.RMC_API_URL || "https://review-my-code.com";
|
|
11
11
|
const APP_URL = process.env.RMC_APP_URL || "https://review-my-code.com";
|
|
12
|
-
const VERSION = "0.1.
|
|
12
|
+
const VERSION = "0.1.3";
|
|
13
13
|
const FREE_PLAN_CREDITS_PER_MONTH = 30;
|
|
14
14
|
const REQUEST_TIMEOUT_MS = 290_000;
|
|
15
15
|
const POLL_TIMEOUT_MS = 10 * 60_000;
|
|
@@ -834,6 +834,7 @@ ${header}
|
|
|
834
834
|
${style("rmcode <file>", c.cyan)} Review a single local file
|
|
835
835
|
${style("rmcode login", c.cyan)} Set up your API key
|
|
836
836
|
${style("rmcode install", c.cyan)} Install the GitHub App for automatic PR reviews
|
|
837
|
+
${style("rmcode update", c.cyan)} Update rmcode to the latest version
|
|
837
838
|
${style("rmcode help", c.cyan)} Show this help
|
|
838
839
|
|
|
839
840
|
${style("OPTIONS", c.bold)}
|
|
@@ -889,18 +890,120 @@ ${header}
|
|
|
889
890
|
${style("https://review-my-code.com", c.dim)}
|
|
890
891
|
`);
|
|
891
892
|
}
|
|
892
|
-
// ──
|
|
893
|
-
|
|
893
|
+
// ── Self-update ───────────────────────────────────────────────────────
|
|
894
|
+
const PACKAGE_NAME = "@review-my-code/rmcode";
|
|
895
|
+
const REGISTRY_LATEST_URL = "https://registry.npmjs.org/@review-my-code%2Frmcode/latest";
|
|
896
|
+
/** Resolved real path of the running entry script, for install detection. */
|
|
897
|
+
function entryScriptPath() {
|
|
898
|
+
const binPath = process.argv[1] || "";
|
|
894
899
|
try {
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
900
|
+
return (0, fs_1.realpathSync)(binPath);
|
|
901
|
+
}
|
|
902
|
+
catch {
|
|
903
|
+
return binPath;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
function isNpxInvocation(binPath) {
|
|
907
|
+
// npm's exec cache lives under .../_npx/<hash>/; older layouts use /npx/.
|
|
908
|
+
return /[\\/]_?npx[\\/]/.test(binPath);
|
|
909
|
+
}
|
|
910
|
+
function updateCommandFor(binPath) {
|
|
911
|
+
const ext = process.platform === "win32" ? ".cmd" : "";
|
|
912
|
+
if (/[\\/]pnpm[\\/]/.test(binPath))
|
|
913
|
+
return { cmd: `pnpm${ext}`, args: ["add", "-g", `${PACKAGE_NAME}@latest`] };
|
|
914
|
+
if (/[\\/]bun[\\/]/.test(binPath))
|
|
915
|
+
return { cmd: "bun", args: ["add", "-g", `${PACKAGE_NAME}@latest`] };
|
|
916
|
+
return {
|
|
917
|
+
cmd: `npm${ext}`,
|
|
918
|
+
args: ["install", "-g", `${PACKAGE_NAME}@latest`],
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
async function runUpdate() {
|
|
922
|
+
const binPath = entryScriptPath();
|
|
923
|
+
if (isNpxInvocation(binPath)) {
|
|
924
|
+
console.log(`\n ${style("Running via npx — already using the latest published version each run.", c.dim)}\n`);
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
const { cmd, args } = updateCommandFor(binPath);
|
|
928
|
+
console.log(`\n ${style(`Updating ${PACKAGE_NAME} via ${cmd}...`, c.bold)}\n`);
|
|
929
|
+
const result = (0, child_process_1.spawnSync)(cmd, args, { stdio: "inherit" });
|
|
930
|
+
if (result.status === 0) {
|
|
931
|
+
const latest = await fetchLatestVersion().catch(() => null);
|
|
932
|
+
console.log(`\n ${style("✓", c.green)} ${latest
|
|
933
|
+
? `Updated to v${latest}.`
|
|
934
|
+
: "Updated. Run rmcode --version to confirm."}\n`);
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
console.error(style(`\n Update failed. Run it manually:`, c.red));
|
|
938
|
+
console.error(` ${style([cmd, ...args].join(" "), c.cyan, c.bold)}\n`);
|
|
939
|
+
process.exit(1);
|
|
940
|
+
}
|
|
941
|
+
// ── Update nudge ──────────────────────────────────────────────────────
|
|
942
|
+
//
|
|
943
|
+
// After a successful human-mode review, print at most one dim line when a
|
|
944
|
+
// newer version is published. The registry is queried at most once per
|
|
945
|
+
// 24h (cached in ~/.config/rmcode/update-check.json) and only after the
|
|
946
|
+
// review output has been printed. Any failure here is silently swallowed
|
|
947
|
+
// — the nudge must never affect review output or exit codes.
|
|
948
|
+
const UPDATE_CHECK_TIMEOUT_MS = 1_500;
|
|
949
|
+
const UPDATE_CHECK_TTL_MS = 24 * 60 * 60 * 1000;
|
|
950
|
+
function updateCachePath() {
|
|
951
|
+
return (0, path_1.join)((0, os_1.homedir)(), ".config", "rmcode", "update-check.json");
|
|
952
|
+
}
|
|
953
|
+
async function fetchLatestVersion() {
|
|
954
|
+
const resp = await fetch(REGISTRY_LATEST_URL, {
|
|
955
|
+
signal: AbortSignal.timeout(UPDATE_CHECK_TIMEOUT_MS),
|
|
956
|
+
});
|
|
957
|
+
if (!resp.ok)
|
|
958
|
+
return null;
|
|
959
|
+
const data = (await resp.json());
|
|
960
|
+
return typeof data.version === "string" ? data.version : null;
|
|
961
|
+
}
|
|
962
|
+
/** Latest published version, from the daily cache when fresh. */
|
|
963
|
+
async function latestPublishedVersion() {
|
|
964
|
+
const cachePath = updateCachePath();
|
|
965
|
+
try {
|
|
966
|
+
const cached = JSON.parse((0, fs_1.readFileSync)(cachePath, "utf-8"));
|
|
967
|
+
if (typeof cached.latest === "string" &&
|
|
968
|
+
typeof cached.checkedAt === "number" &&
|
|
969
|
+
Date.now() - cached.checkedAt < UPDATE_CHECK_TTL_MS) {
|
|
970
|
+
return cached.latest;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
catch {
|
|
974
|
+
// Missing or unreadable cache — fall through to a fresh fetch.
|
|
975
|
+
}
|
|
976
|
+
const latest = await fetchLatestVersion();
|
|
977
|
+
if (!latest)
|
|
978
|
+
return null;
|
|
979
|
+
try {
|
|
980
|
+
(0, fs_1.mkdirSync)((0, path_1.join)((0, os_1.homedir)(), ".config", "rmcode"), { recursive: true });
|
|
981
|
+
(0, fs_1.writeFileSync)(cachePath, JSON.stringify({ latest, checkedAt: Date.now() }));
|
|
982
|
+
}
|
|
983
|
+
catch {
|
|
984
|
+
// Cache writes are best-effort.
|
|
985
|
+
}
|
|
986
|
+
return latest;
|
|
987
|
+
}
|
|
988
|
+
/** Hand-rolled x.y.z compare: 1 if a > b, -1 if a < b, 0 if equal. */
|
|
989
|
+
function compareVersions(a, b) {
|
|
990
|
+
const pa = a.split(".").map((n) => parseInt(n, 10));
|
|
991
|
+
const pb = b.split(".").map((n) => parseInt(n, 10));
|
|
992
|
+
for (let i = 0; i < 3; i++) {
|
|
993
|
+
const da = pa[i] || 0;
|
|
994
|
+
const db = pb[i] || 0;
|
|
995
|
+
if (da !== db)
|
|
996
|
+
return da > db ? 1 : -1;
|
|
997
|
+
}
|
|
998
|
+
return 0;
|
|
999
|
+
}
|
|
1000
|
+
async function maybeShowUpdateNudge() {
|
|
1001
|
+
if (noColor || isCI)
|
|
1002
|
+
return;
|
|
1003
|
+
try {
|
|
1004
|
+
const latest = await latestPublishedVersion();
|
|
1005
|
+
if (latest && compareVersions(latest, VERSION) > 0) {
|
|
1006
|
+
console.log(style(` Update available ${VERSION} → ${latest} · run rmcode update`, c.dim));
|
|
904
1007
|
}
|
|
905
1008
|
}
|
|
906
1009
|
catch {
|
|
@@ -958,6 +1061,10 @@ async function main() {
|
|
|
958
1061
|
console.error(style(` Run: rmcode help\n`, c.dim));
|
|
959
1062
|
process.exit(1);
|
|
960
1063
|
}
|
|
1064
|
+
if (positional[0] === "update") {
|
|
1065
|
+
await runUpdate();
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
961
1068
|
if (positional[0] === "install") {
|
|
962
1069
|
console.log(`\n ${style("Install the GitHub App for automatic PR reviews:", c.bold)}\n`);
|
|
963
1070
|
console.log(` ${style("https://github.com/apps/rmcode-ai", c.cyan, c.bold)}\n`);
|
|
@@ -1056,7 +1163,7 @@ async function main() {
|
|
|
1056
1163
|
}
|
|
1057
1164
|
await runReview(code, [file], file, jsonMode, failOnFindings, "file", detectLanguage([file]));
|
|
1058
1165
|
if (!jsonMode)
|
|
1059
|
-
await
|
|
1166
|
+
await maybeShowUpdateNudge();
|
|
1060
1167
|
return;
|
|
1061
1168
|
}
|
|
1062
1169
|
// Git modes
|
|
@@ -1108,7 +1215,7 @@ async function main() {
|
|
|
1108
1215
|
console.log();
|
|
1109
1216
|
}
|
|
1110
1217
|
if (!jsonMode)
|
|
1111
|
-
await
|
|
1218
|
+
await maybeShowUpdateNudge();
|
|
1112
1219
|
}
|
|
1113
1220
|
main()
|
|
1114
1221
|
.then(() => {
|
package/package.json
CHANGED