@keywaysh/cli 0.1.6 → 0.1.7
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 +84 -29
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -101,7 +101,7 @@ var INTERNAL_POSTHOG_HOST = "https://eu.i.posthog.com";
|
|
|
101
101
|
// package.json
|
|
102
102
|
var package_default = {
|
|
103
103
|
name: "@keywaysh/cli",
|
|
104
|
-
version: "0.1.
|
|
104
|
+
version: "0.1.7",
|
|
105
105
|
description: "One link to all your secrets",
|
|
106
106
|
type: "module",
|
|
107
107
|
bin: {
|
|
@@ -444,6 +444,29 @@ async function getSyncStatus(accessToken, repoFullName, connectionId, projectId,
|
|
|
444
444
|
const wrapped = await handleResponse(response);
|
|
445
445
|
return wrapped.data;
|
|
446
446
|
}
|
|
447
|
+
async function getSyncDiff(accessToken, repoFullName, options) {
|
|
448
|
+
const [owner, repo] = repoFullName.split("/");
|
|
449
|
+
const params = new URLSearchParams({
|
|
450
|
+
connectionId: options.connectionId,
|
|
451
|
+
projectId: options.projectId,
|
|
452
|
+
keywayEnvironment: options.keywayEnvironment || "production",
|
|
453
|
+
providerEnvironment: options.providerEnvironment || "production"
|
|
454
|
+
});
|
|
455
|
+
const response = await fetchWithTimeout(
|
|
456
|
+
`${API_BASE_URL}/v1/integrations/vaults/${owner}/${repo}/sync/diff?${params}`,
|
|
457
|
+
{
|
|
458
|
+
method: "GET",
|
|
459
|
+
headers: {
|
|
460
|
+
"User-Agent": USER_AGENT,
|
|
461
|
+
Authorization: `Bearer ${accessToken}`
|
|
462
|
+
}
|
|
463
|
+
},
|
|
464
|
+
6e4
|
|
465
|
+
// 60 seconds
|
|
466
|
+
);
|
|
467
|
+
const wrapped = await handleResponse(response);
|
|
468
|
+
return wrapped.data;
|
|
469
|
+
}
|
|
447
470
|
async function getSyncPreview(accessToken, repoFullName, options) {
|
|
448
471
|
const [owner, repo] = repoFullName.split("/");
|
|
449
472
|
const params = new URLSearchParams({
|
|
@@ -1087,6 +1110,9 @@ async function pushCommand(options) {
|
|
|
1087
1110
|
let environment = options.env;
|
|
1088
1111
|
let envFile = options.file;
|
|
1089
1112
|
const candidates = discoverEnvCandidates(process.cwd());
|
|
1113
|
+
if (candidates.length === 0 && !envFile) {
|
|
1114
|
+
throw new Error("No .env file found. Create a .env file first, or use --file <path> to specify one.");
|
|
1115
|
+
}
|
|
1090
1116
|
if (environment && !envFile) {
|
|
1091
1117
|
const match = candidates.find((c) => c.env === environment);
|
|
1092
1118
|
if (match) {
|
|
@@ -1145,34 +1171,9 @@ async function pushCommand(options) {
|
|
|
1145
1171
|
if (!envFile) {
|
|
1146
1172
|
envFile = ".env";
|
|
1147
1173
|
}
|
|
1148
|
-
|
|
1174
|
+
const envFilePath = path4.resolve(process.cwd(), envFile);
|
|
1149
1175
|
if (!fs4.existsSync(envFilePath)) {
|
|
1150
|
-
|
|
1151
|
-
throw new Error(`File not found: ${envFile}. Provide --file <path> or run interactively to choose a file.`);
|
|
1152
|
-
}
|
|
1153
|
-
const { newPath } = await prompts3(
|
|
1154
|
-
{
|
|
1155
|
-
type: "text",
|
|
1156
|
-
name: "newPath",
|
|
1157
|
-
message: `File not found: ${envFile}. Enter an env file path to use:`,
|
|
1158
|
-
validate: (value) => {
|
|
1159
|
-
if (!value || typeof value !== "string") return "Path is required";
|
|
1160
|
-
const resolved = path4.resolve(process.cwd(), value);
|
|
1161
|
-
if (!fs4.existsSync(resolved)) return `File not found: ${value}`;
|
|
1162
|
-
return true;
|
|
1163
|
-
}
|
|
1164
|
-
},
|
|
1165
|
-
{
|
|
1166
|
-
onCancel: () => {
|
|
1167
|
-
throw new Error("Push cancelled (no env file provided).");
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1170
|
-
);
|
|
1171
|
-
if (!newPath || typeof newPath !== "string") {
|
|
1172
|
-
throw new Error("Push cancelled (no env file provided).");
|
|
1173
|
-
}
|
|
1174
|
-
envFile = newPath.trim();
|
|
1175
|
-
envFilePath = path4.resolve(process.cwd(), envFile);
|
|
1176
|
+
throw new Error(`File not found: ${envFile}`);
|
|
1176
1177
|
}
|
|
1177
1178
|
const content = fs4.readFileSync(envFilePath, "utf-8");
|
|
1178
1179
|
if (content.trim().length === 0) {
|
|
@@ -1231,7 +1232,9 @@ async function pushCommand(options) {
|
|
|
1231
1232
|
}
|
|
1232
1233
|
console.log(`
|
|
1233
1234
|
Your secrets are now encrypted and stored securely.`);
|
|
1234
|
-
|
|
1235
|
+
const dashboardLink = `https://www.keyway.sh/dashboard/vaults/${repoFullName}`;
|
|
1236
|
+
console.log(`
|
|
1237
|
+
${pc5.blue("\u2394")} Dashboard: ${pc5.underline(dashboardLink)}`);
|
|
1235
1238
|
await shutdownAnalytics();
|
|
1236
1239
|
} catch (error) {
|
|
1237
1240
|
let message;
|
|
@@ -2136,6 +2139,42 @@ function mapToProviderEnvironment(provider, keywayEnv) {
|
|
|
2136
2139
|
return keywayEnv;
|
|
2137
2140
|
}
|
|
2138
2141
|
}
|
|
2142
|
+
function displayDiffSummary(diff, providerName) {
|
|
2143
|
+
const totalDiff = diff.onlyInKeyway.length + diff.onlyInProvider.length + diff.different.length;
|
|
2144
|
+
if (totalDiff === 0 && diff.same.length > 0) {
|
|
2145
|
+
console.log(pc10.green(`
|
|
2146
|
+
\u2713 Already in sync (${diff.same.length} secrets)`));
|
|
2147
|
+
return;
|
|
2148
|
+
}
|
|
2149
|
+
console.log(pc10.blue("\n\u{1F4CA} Comparison Summary\n"));
|
|
2150
|
+
console.log(pc10.gray(` Keyway: ${diff.keywayCount} secrets | ${providerName}: ${diff.providerCount} secrets
|
|
2151
|
+
`));
|
|
2152
|
+
if (diff.onlyInKeyway.length > 0) {
|
|
2153
|
+
console.log(pc10.cyan(` \u2192 ${diff.onlyInKeyway.length} only in Keyway`));
|
|
2154
|
+
diff.onlyInKeyway.slice(0, 3).forEach((key) => console.log(pc10.gray(` ${key}`)));
|
|
2155
|
+
if (diff.onlyInKeyway.length > 3) {
|
|
2156
|
+
console.log(pc10.gray(` ... and ${diff.onlyInKeyway.length - 3} more`));
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
if (diff.onlyInProvider.length > 0) {
|
|
2160
|
+
console.log(pc10.magenta(` \u2190 ${diff.onlyInProvider.length} only in ${providerName}`));
|
|
2161
|
+
diff.onlyInProvider.slice(0, 3).forEach((key) => console.log(pc10.gray(` ${key}`)));
|
|
2162
|
+
if (diff.onlyInProvider.length > 3) {
|
|
2163
|
+
console.log(pc10.gray(` ... and ${diff.onlyInProvider.length - 3} more`));
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
if (diff.different.length > 0) {
|
|
2167
|
+
console.log(pc10.yellow(` \u2260 ${diff.different.length} with different values`));
|
|
2168
|
+
diff.different.slice(0, 3).forEach((key) => console.log(pc10.gray(` ${key}`)));
|
|
2169
|
+
if (diff.different.length > 3) {
|
|
2170
|
+
console.log(pc10.gray(` ... and ${diff.different.length - 3} more`));
|
|
2171
|
+
}
|
|
2172
|
+
}
|
|
2173
|
+
if (diff.same.length > 0) {
|
|
2174
|
+
console.log(pc10.gray(` = ${diff.same.length} identical`));
|
|
2175
|
+
}
|
|
2176
|
+
console.log("");
|
|
2177
|
+
}
|
|
2139
2178
|
function findMatchingProject(projects, repoFullName) {
|
|
2140
2179
|
const repoFullNameLower = repoFullName.toLowerCase();
|
|
2141
2180
|
const repoName = repoFullName.split("/")[1]?.toLowerCase();
|
|
@@ -2369,6 +2408,22 @@ Connection to ${providerDisplayName} failed.`));
|
|
|
2369
2408
|
providerEnv = mapToProviderEnvironment(provider, keywayEnv);
|
|
2370
2409
|
}
|
|
2371
2410
|
}
|
|
2411
|
+
if (needsDirectionPrompt) {
|
|
2412
|
+
const effectiveKeywayEnv = keywayEnv || "production";
|
|
2413
|
+
const effectiveProviderEnv = providerEnv || mapToProviderEnvironment(provider, effectiveKeywayEnv);
|
|
2414
|
+
console.log(pc10.gray("\nComparing secrets..."));
|
|
2415
|
+
const diff = await getSyncDiff(accessToken, repoFullName, {
|
|
2416
|
+
connectionId: connection.id,
|
|
2417
|
+
projectId: selectedProject.id,
|
|
2418
|
+
keywayEnvironment: effectiveKeywayEnv,
|
|
2419
|
+
providerEnvironment: effectiveProviderEnv
|
|
2420
|
+
});
|
|
2421
|
+
displayDiffSummary(diff, providerName);
|
|
2422
|
+
const totalDiff = diff.onlyInKeyway.length + diff.onlyInProvider.length + diff.different.length;
|
|
2423
|
+
if (totalDiff === 0) {
|
|
2424
|
+
return;
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2372
2427
|
if (needsDirectionPrompt) {
|
|
2373
2428
|
const { selectedDirection } = await prompts7({
|
|
2374
2429
|
type: "select",
|