md4ai 0.9.9 → 0.9.10
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.bundled.js +91 -13
- package/package.json +1 -1
package/dist/index.bundled.js
CHANGED
|
@@ -887,20 +887,26 @@ var init_tooling_detector = __esm({
|
|
|
887
887
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
888
888
|
import { join as join7 } from "node:path";
|
|
889
889
|
import { homedir as homedir5 } from "node:os";
|
|
890
|
-
async function
|
|
890
|
+
async function resolveVercelTokenWithSource() {
|
|
891
891
|
const creds = await loadCredentials();
|
|
892
|
-
if (creds?.vercelToken)
|
|
893
|
-
return
|
|
892
|
+
if (creds?.vercelToken) {
|
|
893
|
+
return {
|
|
894
|
+
token: creds.vercelToken,
|
|
895
|
+
source: "md4ai-credentials",
|
|
896
|
+
sourcePath: join7(homedir5(), ".md4ai", "credentials.json")
|
|
897
|
+
};
|
|
898
|
+
}
|
|
894
899
|
const possiblePaths = [
|
|
895
|
-
join7(homedir5(), ".config", "com.vercel.cli", "auth.json"),
|
|
896
|
-
join7(homedir5(), ".local", "share", "com.vercel.cli", "auth.json")
|
|
900
|
+
{ path: join7(homedir5(), ".config", "com.vercel.cli", "auth.json"), source: "vercel-cli-config" },
|
|
901
|
+
{ path: join7(homedir5(), ".local", "share", "com.vercel.cli", "auth.json"), source: "vercel-cli-local-share" }
|
|
897
902
|
];
|
|
898
|
-
for (const authPath of possiblePaths) {
|
|
903
|
+
for (const { path: authPath, source } of possiblePaths) {
|
|
899
904
|
try {
|
|
900
905
|
const data = await readFile5(authPath, "utf-8");
|
|
901
906
|
const parsed = JSON.parse(data);
|
|
902
|
-
if (parsed.token)
|
|
903
|
-
return parsed.token;
|
|
907
|
+
if (parsed.token) {
|
|
908
|
+
return { token: parsed.token, source, sourcePath: authPath };
|
|
909
|
+
}
|
|
904
910
|
} catch {
|
|
905
911
|
}
|
|
906
912
|
}
|
|
@@ -956,7 +962,21 @@ async function fetchVercelEnvVars(projectId, orgId, token) {
|
|
|
956
962
|
});
|
|
957
963
|
if (!res.ok) {
|
|
958
964
|
const body = await res.text().catch(() => "");
|
|
959
|
-
|
|
965
|
+
let errorCode = null;
|
|
966
|
+
let invalidToken = false;
|
|
967
|
+
try {
|
|
968
|
+
const parsed = JSON.parse(body);
|
|
969
|
+
errorCode = parsed.error?.code ?? null;
|
|
970
|
+
invalidToken = parsed.error?.invalidToken === true;
|
|
971
|
+
} catch {
|
|
972
|
+
}
|
|
973
|
+
if (invalidToken || res.status === 401) {
|
|
974
|
+
throw new VercelApiError("Token is invalid or expired", res.status, errorCode, true);
|
|
975
|
+
}
|
|
976
|
+
if (res.status === 403) {
|
|
977
|
+
throw new VercelApiError("Token lacks permission for this project/team", res.status, errorCode, false);
|
|
978
|
+
}
|
|
979
|
+
throw new VercelApiError(`Vercel API ${res.status}: ${body.slice(0, 200)}`, res.status, errorCode, false);
|
|
960
980
|
}
|
|
961
981
|
const data = await res.json();
|
|
962
982
|
const envs = data.envs ?? [];
|
|
@@ -968,9 +988,22 @@ async function fetchVercelEnvVars(projectId, orgId, token) {
|
|
|
968
988
|
// populated later by the scanner
|
|
969
989
|
}));
|
|
970
990
|
}
|
|
991
|
+
var VercelApiError;
|
|
971
992
|
var init_fetch_env_vars = __esm({
|
|
972
993
|
"dist/vercel/fetch-env-vars.js"() {
|
|
973
994
|
"use strict";
|
|
995
|
+
VercelApiError = class extends Error {
|
|
996
|
+
statusCode;
|
|
997
|
+
errorCode;
|
|
998
|
+
isInvalidToken;
|
|
999
|
+
constructor(message, statusCode, errorCode, isInvalidToken) {
|
|
1000
|
+
super(message);
|
|
1001
|
+
this.statusCode = statusCode;
|
|
1002
|
+
this.errorCode = errorCode;
|
|
1003
|
+
this.isInvalidToken = isInvalidToken;
|
|
1004
|
+
this.name = "VercelApiError";
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
974
1007
|
}
|
|
975
1008
|
});
|
|
976
1009
|
|
|
@@ -1012,18 +1045,48 @@ async function scanEnvManifest(projectRoot) {
|
|
|
1012
1045
|
checkedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1013
1046
|
};
|
|
1014
1047
|
}
|
|
1048
|
+
function tokenSourceLabel(source) {
|
|
1049
|
+
switch (source) {
|
|
1050
|
+
case "md4ai-credentials":
|
|
1051
|
+
return "md4ai credentials (~/.md4ai/credentials.json)";
|
|
1052
|
+
case "vercel-cli-config":
|
|
1053
|
+
return "Vercel CLI (~/.config/com.vercel.cli/auth.json)";
|
|
1054
|
+
case "vercel-cli-local-share":
|
|
1055
|
+
return "Vercel CLI (~/.local/share/com.vercel.cli/auth.json)";
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
function tokenFixInstructions(source) {
|
|
1059
|
+
switch (source) {
|
|
1060
|
+
case "md4ai-credentials":
|
|
1061
|
+
return [
|
|
1062
|
+
"Generate a new token at https://vercel.com/account/tokens",
|
|
1063
|
+
"Then run: md4ai config set vercel-token <new-token>"
|
|
1064
|
+
];
|
|
1065
|
+
case "vercel-cli-config":
|
|
1066
|
+
case "vercel-cli-local-share":
|
|
1067
|
+
return [
|
|
1068
|
+
"Re-authenticate the Vercel CLI: npx vercel login",
|
|
1069
|
+
"Ensure you log into the correct team account",
|
|
1070
|
+
"Or set a dedicated token: md4ai config set vercel-token <token>"
|
|
1071
|
+
];
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1015
1074
|
async function checkVercelEnvVars(projectRoot, variables) {
|
|
1016
|
-
const
|
|
1017
|
-
if (!
|
|
1075
|
+
const tokenResult = await resolveVercelTokenWithSource();
|
|
1076
|
+
if (!tokenResult) {
|
|
1018
1077
|
console.log(chalk8.dim(" Vercel checks skipped (no token configured)"));
|
|
1078
|
+
console.log(chalk8.dim(" To enable: md4ai config set vercel-token <token>"));
|
|
1079
|
+
console.log(chalk8.dim(" Generate a token at https://vercel.com/account/tokens"));
|
|
1019
1080
|
return null;
|
|
1020
1081
|
}
|
|
1082
|
+
const { token, source } = tokenResult;
|
|
1021
1083
|
const projects = await discoverVercelProjects(projectRoot);
|
|
1022
1084
|
if (projects.length === 0)
|
|
1023
1085
|
return null;
|
|
1024
1086
|
console.log(chalk8.dim(` Checking ${projects.length} Vercel project(s)...`));
|
|
1025
1087
|
const discovered = [];
|
|
1026
1088
|
const manifestVarNames = new Set(variables.map((v) => v.name));
|
|
1089
|
+
let tokenErrorShown = false;
|
|
1027
1090
|
for (const proj of projects) {
|
|
1028
1091
|
try {
|
|
1029
1092
|
const vars = await fetchVercelEnvVars(proj.projectId, proj.orgId, token);
|
|
@@ -1044,7 +1107,22 @@ async function checkVercelEnvVars(projectRoot, variables) {
|
|
|
1044
1107
|
}
|
|
1045
1108
|
console.log(chalk8.dim(` ${proj.projectName}: ${vars.length} var(s)`));
|
|
1046
1109
|
} catch (err) {
|
|
1047
|
-
|
|
1110
|
+
if (err instanceof VercelApiError && err.isInvalidToken && !tokenErrorShown) {
|
|
1111
|
+
tokenErrorShown = true;
|
|
1112
|
+
console.log(chalk8.red(` ${proj.projectName}: Token is invalid or expired`));
|
|
1113
|
+
console.log(chalk8.yellow(` Token source: ${tokenSourceLabel(source)}`));
|
|
1114
|
+
console.log(chalk8.yellow(" To fix:"));
|
|
1115
|
+
for (const step of tokenFixInstructions(source)) {
|
|
1116
|
+
console.log(chalk8.yellow(` \u2192 ${step}`));
|
|
1117
|
+
}
|
|
1118
|
+
} else if (err instanceof VercelApiError && err.statusCode === 403) {
|
|
1119
|
+
console.log(chalk8.yellow(` ${proj.projectName}: ${err.message}`));
|
|
1120
|
+
console.log(chalk8.dim(` Token source: ${tokenSourceLabel(source)}`));
|
|
1121
|
+
console.log(chalk8.dim(" Ensure the token has access to this team/project"));
|
|
1122
|
+
console.log(chalk8.dim(" Check: https://vercel.com/account/tokens"));
|
|
1123
|
+
} else {
|
|
1124
|
+
console.log(chalk8.yellow(` ${proj.projectName}: ${err instanceof Error ? err.message : "API error"}`));
|
|
1125
|
+
}
|
|
1048
1126
|
}
|
|
1049
1127
|
}
|
|
1050
1128
|
return discovered.length > 0 ? discovered : null;
|
|
@@ -1645,7 +1723,7 @@ var CURRENT_VERSION;
|
|
|
1645
1723
|
var init_check_update = __esm({
|
|
1646
1724
|
"dist/check-update.js"() {
|
|
1647
1725
|
"use strict";
|
|
1648
|
-
CURRENT_VERSION = true ? "0.9.
|
|
1726
|
+
CURRENT_VERSION = true ? "0.9.10" : "0.0.0-dev";
|
|
1649
1727
|
}
|
|
1650
1728
|
});
|
|
1651
1729
|
|