@keywaysh/cli 0.0.9 → 0.0.11
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 +102 -58
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,8 @@ import { Command } from "commander";
|
|
|
5
5
|
import chalk7 from "chalk";
|
|
6
6
|
|
|
7
7
|
// src/cmds/init.ts
|
|
8
|
-
import
|
|
8
|
+
import chalk4 from "chalk";
|
|
9
|
+
import prompts4 from "prompts";
|
|
9
10
|
|
|
10
11
|
// src/utils/git.ts
|
|
11
12
|
import { execSync } from "child_process";
|
|
@@ -68,7 +69,7 @@ var INTERNAL_POSTHOG_HOST = "https://eu.i.posthog.com";
|
|
|
68
69
|
// package.json with { type: 'json' }
|
|
69
70
|
var package_default = {
|
|
70
71
|
name: "@keywaysh/cli",
|
|
71
|
-
version: "0.0.
|
|
72
|
+
version: "0.0.11",
|
|
72
73
|
description: "One link to all your secrets",
|
|
73
74
|
type: "module",
|
|
74
75
|
bin: {
|
|
@@ -280,7 +281,7 @@ import fs from "fs";
|
|
|
280
281
|
// package.json
|
|
281
282
|
var package_default2 = {
|
|
282
283
|
name: "@keywaysh/cli",
|
|
283
|
-
version: "0.0.
|
|
284
|
+
version: "0.0.11",
|
|
284
285
|
description: "One link to all your secrets",
|
|
285
286
|
type: "module",
|
|
286
287
|
bin: {
|
|
@@ -696,62 +697,32 @@ async function ensureReadme(repoName, cwd) {
|
|
|
696
697
|
fs2.writeFileSync(defaultPath, content, "utf-8");
|
|
697
698
|
return defaultPath;
|
|
698
699
|
}
|
|
699
|
-
async function addBadgeToReadme() {
|
|
700
|
+
async function addBadgeToReadme(silent = false) {
|
|
700
701
|
const repo = detectGitRepo();
|
|
701
702
|
if (!repo) {
|
|
702
703
|
throw new Error("This directory is not a Git repository.");
|
|
703
704
|
}
|
|
704
705
|
const cwd = process.cwd();
|
|
705
706
|
const readmePath = await ensureReadme(repo, cwd);
|
|
706
|
-
if (!readmePath) return;
|
|
707
|
+
if (!readmePath) return false;
|
|
707
708
|
const badge = generateBadge(repo);
|
|
708
709
|
const content = fs2.readFileSync(readmePath, "utf-8");
|
|
709
710
|
const updated = insertBadgeIntoReadme(content, badge);
|
|
710
711
|
if (updated === content) {
|
|
711
|
-
|
|
712
|
-
|
|
712
|
+
if (!silent) {
|
|
713
|
+
console.log(chalk2.gray("Keyway badge already present in README."));
|
|
714
|
+
}
|
|
715
|
+
return false;
|
|
713
716
|
}
|
|
714
717
|
fs2.writeFileSync(readmePath, updated, "utf-8");
|
|
715
|
-
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
// src/cmds/init.ts
|
|
719
|
-
async function initCommand(options = {}) {
|
|
720
|
-
try {
|
|
721
|
-
console.log(chalk3.blue("\u{1F510} Initializing Keyway vault...\n"));
|
|
722
|
-
const repoFullName = getCurrentRepoFullName();
|
|
723
|
-
console.log(`Repository: ${chalk3.cyan(repoFullName)}`);
|
|
724
|
-
const accessToken = await ensureLogin({ allowPrompt: options.loginPrompt !== false });
|
|
725
|
-
trackEvent(AnalyticsEvents.CLI_INIT, { repoFullName });
|
|
726
|
-
console.log("\nInitializing vault...");
|
|
727
|
-
const response = await initVault(repoFullName, accessToken);
|
|
728
|
-
console.log(chalk3.green("\n\u2713 " + response.message));
|
|
729
|
-
console.log(`
|
|
730
|
-
Vault ID: ${chalk3.gray(response.vaultId)}`);
|
|
731
|
-
console.log("\nNext steps:");
|
|
732
|
-
console.log(` 1. Create a ${chalk3.cyan(".env")} file with your secrets`);
|
|
733
|
-
console.log(` 2. Run ${chalk3.cyan("keyway push")} to upload your secrets`);
|
|
734
|
-
try {
|
|
735
|
-
await addBadgeToReadme();
|
|
736
|
-
} catch (badgeError) {
|
|
737
|
-
console.log(chalk3.yellow("Badge insertion skipped:"), badgeError instanceof Error ? badgeError.message : String(badgeError));
|
|
738
|
-
}
|
|
739
|
-
await shutdownAnalytics();
|
|
740
|
-
} catch (error) {
|
|
741
|
-
const message = error instanceof APIError ? `API ${error.statusCode}: ${error.message}` : error instanceof Error ? error.message.slice(0, 200) : "Unknown error";
|
|
742
|
-
trackEvent(AnalyticsEvents.CLI_ERROR, {
|
|
743
|
-
command: "init",
|
|
744
|
-
error: message
|
|
745
|
-
});
|
|
746
|
-
await shutdownAnalytics();
|
|
747
|
-
console.error(chalk3.red(`
|
|
748
|
-
\u2717 Error: ${message}`));
|
|
749
|
-
process.exit(1);
|
|
718
|
+
if (!silent) {
|
|
719
|
+
console.log(chalk2.green(`\u2713 Keyway badge added to ${path2.basename(readmePath)}`));
|
|
750
720
|
}
|
|
721
|
+
return true;
|
|
751
722
|
}
|
|
752
723
|
|
|
753
724
|
// src/cmds/push.ts
|
|
754
|
-
import
|
|
725
|
+
import chalk3 from "chalk";
|
|
755
726
|
import fs3 from "fs";
|
|
756
727
|
import path3 from "path";
|
|
757
728
|
import prompts3 from "prompts";
|
|
@@ -768,7 +739,7 @@ function discoverEnvCandidates(cwd) {
|
|
|
768
739
|
const entries = fs3.readdirSync(cwd);
|
|
769
740
|
const hasEnvLocal = entries.includes(".env.local");
|
|
770
741
|
if (hasEnvLocal) {
|
|
771
|
-
console.log(
|
|
742
|
+
console.log(chalk3.gray("\u2139\uFE0F Detected .env.local \u2014 not synced by design (machine-specific secrets)"));
|
|
772
743
|
}
|
|
773
744
|
const candidates = entries.filter((name) => name.startsWith(".env") && name !== ".env.local").map((name) => {
|
|
774
745
|
const fullPath = path3.join(cwd, name);
|
|
@@ -794,7 +765,7 @@ function discoverEnvCandidates(cwd) {
|
|
|
794
765
|
}
|
|
795
766
|
async function pushCommand(options) {
|
|
796
767
|
try {
|
|
797
|
-
console.log(
|
|
768
|
+
console.log(chalk3.blue("\u{1F510} Pushing secrets to Keyway...\n"));
|
|
798
769
|
const isInteractive2 = process.stdin.isTTY && process.stdout.isTTY;
|
|
799
770
|
let environment = options.env;
|
|
800
771
|
let envFile = options.file;
|
|
@@ -894,11 +865,11 @@ async function pushCommand(options) {
|
|
|
894
865
|
const trimmed = line.trim();
|
|
895
866
|
return trimmed.length > 0 && !trimmed.startsWith("#");
|
|
896
867
|
});
|
|
897
|
-
console.log(`File: ${
|
|
898
|
-
console.log(`Environment: ${
|
|
899
|
-
console.log(`Variables: ${
|
|
868
|
+
console.log(`File: ${chalk3.cyan(envFile)}`);
|
|
869
|
+
console.log(`Environment: ${chalk3.cyan(environment)}`);
|
|
870
|
+
console.log(`Variables: ${chalk3.cyan(lines.length.toString())}`);
|
|
900
871
|
const repoFullName = getCurrentRepoFullName();
|
|
901
|
-
console.log(`Repository: ${
|
|
872
|
+
console.log(`Repository: ${chalk3.cyan(repoFullName)}`);
|
|
902
873
|
if (!options.yes) {
|
|
903
874
|
const isInteractive3 = process.stdin.isTTY && process.stdout.isTTY;
|
|
904
875
|
if (!isInteractive3) {
|
|
@@ -918,7 +889,7 @@ async function pushCommand(options) {
|
|
|
918
889
|
}
|
|
919
890
|
);
|
|
920
891
|
if (!confirm) {
|
|
921
|
-
console.log(
|
|
892
|
+
console.log(chalk3.yellow("Push aborted."));
|
|
922
893
|
return;
|
|
923
894
|
}
|
|
924
895
|
}
|
|
@@ -930,20 +901,20 @@ async function pushCommand(options) {
|
|
|
930
901
|
});
|
|
931
902
|
console.log("\nUploading secrets...");
|
|
932
903
|
const response = await pushSecrets(repoFullName, environment, content, accessToken);
|
|
933
|
-
console.log(
|
|
904
|
+
console.log(chalk3.green("\n\u2713 " + response.message));
|
|
934
905
|
if (response.stats) {
|
|
935
906
|
const { created, updated, deleted } = response.stats;
|
|
936
907
|
const parts = [];
|
|
937
|
-
if (created > 0) parts.push(
|
|
938
|
-
if (updated > 0) parts.push(
|
|
939
|
-
if (deleted > 0) parts.push(
|
|
908
|
+
if (created > 0) parts.push(chalk3.green(`+${created} created`));
|
|
909
|
+
if (updated > 0) parts.push(chalk3.yellow(`~${updated} updated`));
|
|
910
|
+
if (deleted > 0) parts.push(chalk3.red(`-${deleted} deleted`));
|
|
940
911
|
if (parts.length > 0) {
|
|
941
912
|
console.log(`Stats: ${parts.join(", ")}`);
|
|
942
913
|
}
|
|
943
914
|
}
|
|
944
915
|
console.log(`
|
|
945
916
|
Your secrets are now encrypted and stored securely.`);
|
|
946
|
-
console.log(`To retrieve them, run: ${
|
|
917
|
+
console.log(`To retrieve them, run: ${chalk3.cyan(`keyway pull --env ${environment}`)}`);
|
|
947
918
|
await shutdownAnalytics();
|
|
948
919
|
} catch (error) {
|
|
949
920
|
const message = error instanceof APIError ? `API ${error.statusCode}: ${error.message}` : error instanceof Error ? error.message.slice(0, 200) : "Unknown error";
|
|
@@ -952,17 +923,90 @@ Your secrets are now encrypted and stored securely.`);
|
|
|
952
923
|
error: message
|
|
953
924
|
});
|
|
954
925
|
await shutdownAnalytics();
|
|
955
|
-
console.error(
|
|
926
|
+
console.error(chalk3.red(`
|
|
956
927
|
\u2717 Error: ${message}`));
|
|
957
928
|
process.exit(1);
|
|
958
929
|
}
|
|
959
930
|
}
|
|
960
931
|
|
|
932
|
+
// src/cmds/init.ts
|
|
933
|
+
var DASHBOARD_URL = "https://www.keyway.sh/dashboard/vaults";
|
|
934
|
+
async function initCommand(options = {}) {
|
|
935
|
+
try {
|
|
936
|
+
const repoFullName = getCurrentRepoFullName();
|
|
937
|
+
const dashboardLink = `${DASHBOARD_URL}/${repoFullName}`;
|
|
938
|
+
console.log(chalk4.blue("\u{1F510} Initializing Keyway vault...\n"));
|
|
939
|
+
console.log(` ${chalk4.gray("Repository:")} ${chalk4.white(repoFullName)}`);
|
|
940
|
+
const accessToken = await ensureLogin({ allowPrompt: options.loginPrompt !== false });
|
|
941
|
+
trackEvent(AnalyticsEvents.CLI_INIT, { repoFullName });
|
|
942
|
+
const response = await initVault(repoFullName, accessToken);
|
|
943
|
+
console.log(chalk4.green("\u2713 Vault created!"));
|
|
944
|
+
try {
|
|
945
|
+
const badgeAdded = await addBadgeToReadme(true);
|
|
946
|
+
if (badgeAdded) {
|
|
947
|
+
console.log(chalk4.green("\u2713 Badge added to README.md"));
|
|
948
|
+
}
|
|
949
|
+
} catch {
|
|
950
|
+
}
|
|
951
|
+
console.log("");
|
|
952
|
+
const envCandidates = discoverEnvCandidates(process.cwd());
|
|
953
|
+
const isInteractive2 = process.stdin.isTTY && process.stdout.isTTY;
|
|
954
|
+
if (envCandidates.length > 0 && isInteractive2) {
|
|
955
|
+
console.log(chalk4.gray(` Found ${envCandidates.length} env file(s): ${envCandidates.map((c) => c.file).join(", ")}
|
|
956
|
+
`));
|
|
957
|
+
const { shouldPush } = await prompts4({
|
|
958
|
+
type: "confirm",
|
|
959
|
+
name: "shouldPush",
|
|
960
|
+
message: "Push secrets now?",
|
|
961
|
+
initial: true
|
|
962
|
+
});
|
|
963
|
+
if (shouldPush) {
|
|
964
|
+
console.log("");
|
|
965
|
+
await pushCommand({ loginPrompt: false, yes: false });
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
console.log(chalk4.dim("\u2500".repeat(50)));
|
|
970
|
+
console.log("");
|
|
971
|
+
if (envCandidates.length === 0) {
|
|
972
|
+
console.log(` ${chalk4.yellow("\u2192")} Create a ${chalk4.cyan(".env")} file with your secrets`);
|
|
973
|
+
console.log(` ${chalk4.yellow("\u2192")} Run ${chalk4.cyan("keyway push")} to sync them
|
|
974
|
+
`);
|
|
975
|
+
} else {
|
|
976
|
+
console.log(` ${chalk4.yellow("\u2192")} Run ${chalk4.cyan("keyway push")} to sync your secrets
|
|
977
|
+
`);
|
|
978
|
+
}
|
|
979
|
+
console.log(` ${chalk4.blue("\u2394")} Dashboard: ${chalk4.underline(dashboardLink)}`);
|
|
980
|
+
console.log("");
|
|
981
|
+
await shutdownAnalytics();
|
|
982
|
+
} catch (error) {
|
|
983
|
+
if (error instanceof APIError) {
|
|
984
|
+
if (error.statusCode === 409) {
|
|
985
|
+
console.log(chalk4.yellow("\n\u26A0 Vault already exists for this repository.\n"));
|
|
986
|
+
console.log(` ${chalk4.yellow("\u2192")} Run ${chalk4.cyan("keyway push")} to sync your secrets`);
|
|
987
|
+
console.log(` ${chalk4.blue("\u2394")} Dashboard: ${chalk4.underline(`${DASHBOARD_URL}/${getCurrentRepoFullName()}`)}`);
|
|
988
|
+
console.log("");
|
|
989
|
+
await shutdownAnalytics();
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
const message = error instanceof APIError ? error.message : error instanceof Error ? error.message.slice(0, 200) : "Unknown error";
|
|
994
|
+
trackEvent(AnalyticsEvents.CLI_ERROR, {
|
|
995
|
+
command: "init",
|
|
996
|
+
error: message
|
|
997
|
+
});
|
|
998
|
+
await shutdownAnalytics();
|
|
999
|
+
console.error(chalk4.red(`
|
|
1000
|
+
\u2717 ${message}`));
|
|
1001
|
+
process.exit(1);
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
|
|
961
1005
|
// src/cmds/pull.ts
|
|
962
1006
|
import chalk5 from "chalk";
|
|
963
1007
|
import fs4 from "fs";
|
|
964
1008
|
import path4 from "path";
|
|
965
|
-
import
|
|
1009
|
+
import prompts5 from "prompts";
|
|
966
1010
|
async function pullCommand(options) {
|
|
967
1011
|
try {
|
|
968
1012
|
const environment = options.env || "development";
|
|
@@ -987,7 +1031,7 @@ async function pullCommand(options) {
|
|
|
987
1031
|
} else if (!isInteractive2) {
|
|
988
1032
|
throw new Error(`File ${envFile} exists. Re-run with --yes to overwrite or choose a different --file.`);
|
|
989
1033
|
} else {
|
|
990
|
-
const { confirm } = await
|
|
1034
|
+
const { confirm } = await prompts5(
|
|
991
1035
|
{
|
|
992
1036
|
type: "confirm",
|
|
993
1037
|
name: "confirm",
|