sandstream-kit 1.5.0 → 1.6.0
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/README.md +6 -0
- package/dist/cli.js +27 -7
- package/dist/cli.js.map +1 -1
- package/dist/service-registry.d.ts +54 -0
- package/dist/service-registry.js +248 -0
- package/dist/service-registry.js.map +1 -0
- package/dist/stack-detector.js +176 -55
- package/dist/stack-detector.js.map +1 -1
- package/dist/toml-generator.d.ts +4 -0
- package/dist/toml-generator.js +55 -99
- package/dist/toml-generator.js.map +1 -1
- package/dist/vault-meta.d.ts +7 -0
- package/dist/vault-meta.js +13 -0
- package/dist/vault-meta.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -6,6 +6,8 @@ For AI agents and humans. Manages tools, auth, secrets, and project setup. Zero
|
|
|
6
6
|
|
|
7
7
|
🌐 [sandstre.am/kit](https://sandstre.am/kit)
|
|
8
8
|
|
|
9
|
+
[](https://buymeacoffee.com/sandstream)
|
|
10
|
+
|
|
9
11
|
## Quick start
|
|
10
12
|
|
|
11
13
|
**Prerequisites:** Node.js 22+, git, and [mise](https://mise.jdx.dev) for installing tools (`brew install mise`, or `curl https://mise.run | sh`).
|
|
@@ -708,6 +710,10 @@ For Cline, add the same config to your `cline_mcp_settings.json`.
|
|
|
708
710
|
- 🐛 **Issues**: [github.com/sandstream/kit/issues](https://github.com/sandstream/kit/issues)
|
|
709
711
|
- 🤝 **Contributing**: [CONTRIBUTING.md](CONTRIBUTING.md), [COMMUNITY.md](COMMUNITY.md)
|
|
710
712
|
|
|
713
|
+
### Support
|
|
714
|
+
|
|
715
|
+
kit is free and MIT-licensed. If it saved you setup time or caught a leak before it shipped, you can [buy me a coffee](https://buymeacoffee.com/sandstream). It funds development time and keeps kit free and open.
|
|
716
|
+
|
|
711
717
|
### Code of Conduct
|
|
712
718
|
|
|
713
719
|
See [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
|
package/dist/cli.js
CHANGED
|
@@ -65,8 +65,8 @@ import { cmdHooks } from "./commands/hooks.js";
|
|
|
65
65
|
import { resolveAllAuth } from "./service-auth.js";
|
|
66
66
|
import { runDoctor } from "./doctor.js";
|
|
67
67
|
import { detectStack } from "./stack-detector.js";
|
|
68
|
-
import { generateToml } from "./toml-generator.js";
|
|
69
|
-
import { vaultMeta } from "./vault-meta.js";
|
|
68
|
+
import { generateToml, parseEnvTemplateKeys } from "./toml-generator.js";
|
|
69
|
+
import { vaultMeta, detectSecretStore } from "./vault-meta.js";
|
|
70
70
|
import { vaultCliInstalled } from "./secret-backends.js";
|
|
71
71
|
import { createPlugin } from "./create-plugin.js";
|
|
72
72
|
import { cmdPlugin } from "./plugins-cli.js";
|
|
@@ -1035,10 +1035,16 @@ async function generateConfigFile(configPath, nonInteractive) {
|
|
|
1035
1035
|
`${c.bold}kit secrets migrate${c.reset}${c.yellow} after.${c.reset}\n`);
|
|
1036
1036
|
}
|
|
1037
1037
|
// ── Secret-backend choice (interactive) ────────────────────────────────
|
|
1038
|
-
|
|
1038
|
+
// Respect a backend the repo is already bound to (.infisical.json / doppler.yaml);
|
|
1039
|
+
// it becomes the default (and the non-interactive choice) instead of 1Password.
|
|
1040
|
+
const detectedStore = await detectSecretStore(async (p) => existsSync(resolve(process.cwd(), p)));
|
|
1041
|
+
let chosenStore = detectedStore ?? "1password";
|
|
1042
|
+
if (detectedStore) {
|
|
1043
|
+
console.log(` ${c.green}✓${c.reset} Detected ${c.bold}${detectedStore}${c.reset} config in repo — using it as the secret backend.\n`);
|
|
1044
|
+
}
|
|
1039
1045
|
if (!nonInteractive) {
|
|
1040
|
-
|
|
1041
|
-
{ value: "1password", label: "1Password", hint: "interactive signin via op CLI"
|
|
1046
|
+
const opts = [
|
|
1047
|
+
{ value: "1password", label: "1Password", hint: "interactive signin via op CLI" },
|
|
1042
1048
|
{ value: "infisical", label: "Infisical", hint: "self-hosted or cloud, token-based" },
|
|
1043
1049
|
{ value: "vault", label: "HashiCorp Vault", hint: "KV v2 paths" },
|
|
1044
1050
|
{ value: "aws-sm", label: "AWS Secrets Manager", hint: "IAM credentials required" },
|
|
@@ -1047,7 +1053,8 @@ async function generateConfigFile(configPath, nonInteractive) {
|
|
|
1047
1053
|
{ value: "doppler", label: "Doppler", hint: "doppler login required" },
|
|
1048
1054
|
{ value: "bitwarden", label: "Bitwarden", hint: "bw login + unlock required" },
|
|
1049
1055
|
{ value: "env", label: "env (no vault)", hint: "not recommended — use only for local dev" },
|
|
1050
|
-
]));
|
|
1056
|
+
].map((o) => ({ ...o, recommended: o.value === chosenStore }));
|
|
1057
|
+
chosenStore = (await promptSelect("Secret backend?", opts));
|
|
1051
1058
|
console.log();
|
|
1052
1059
|
}
|
|
1053
1060
|
// Detect a Dockerfile so generateToml can provision the trivy container/IaC
|
|
@@ -1055,7 +1062,20 @@ async function generateConfigFile(configPath, nonInteractive) {
|
|
|
1055
1062
|
const hasDockerfile = existsSync(resolve(process.cwd(), "Dockerfile")) ||
|
|
1056
1063
|
existsSync(resolve(process.cwd(), "docker-compose.yml")) ||
|
|
1057
1064
|
existsSync(resolve(process.cwd(), "compose.yml"));
|
|
1058
|
-
|
|
1065
|
+
// Seed [secrets.keys] from an existing .env example so the project's real
|
|
1066
|
+
// secret contract isn't lost to just the detected services' template keys.
|
|
1067
|
+
let extraSecretKeys = [];
|
|
1068
|
+
for (const f of [".env.example", ".env.template", ".env.sample"]) {
|
|
1069
|
+
const p = resolve(process.cwd(), f);
|
|
1070
|
+
if (existsSync(p)) {
|
|
1071
|
+
extraSecretKeys = parseEnvTemplateKeys(readFileSync(p, "utf-8"));
|
|
1072
|
+
if (extraSecretKeys.length > 0) {
|
|
1073
|
+
console.log(` ${c.green}✓${c.reset} Seeded ${extraSecretKeys.length} key(s) from ${c.bold}${f}${c.reset}\n`);
|
|
1074
|
+
}
|
|
1075
|
+
break;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
const tomlContent = generateToml(stack, { secretsStore: chosenStore, hasDockerfile, extraSecretKeys });
|
|
1059
1079
|
// Show diff preview
|
|
1060
1080
|
console.log(`${c.bold}Preview — .kit.toml${c.reset}\n`);
|
|
1061
1081
|
for (const line of tomlContent.split("\n")) {
|