@heyditto/cli 2.5.2 → 2.7.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.
Files changed (59) hide show
  1. package/README.md +47 -19
  2. package/dist/api.d.ts +13 -0
  3. package/dist/api.js +20 -0
  4. package/dist/api.js.map +1 -1
  5. package/dist/commands.d.ts +41 -3
  6. package/dist/commands.js +237 -61
  7. package/dist/commands.js.map +1 -1
  8. package/dist/secret-stores/aws.d.ts +8 -0
  9. package/dist/secret-stores/aws.js +59 -0
  10. package/dist/secret-stores/aws.js.map +1 -0
  11. package/dist/secret-stores/azure.d.ts +7 -0
  12. package/dist/secret-stores/azure.js +63 -0
  13. package/dist/secret-stores/azure.js.map +1 -0
  14. package/dist/secret-stores/cloudflare.d.ts +7 -0
  15. package/dist/secret-stores/cloudflare.js +46 -0
  16. package/dist/secret-stores/cloudflare.js.map +1 -0
  17. package/dist/secret-stores/doppler.d.ts +7 -0
  18. package/dist/secret-stores/doppler.js +52 -0
  19. package/dist/secret-stores/doppler.js.map +1 -0
  20. package/dist/secret-stores/exec.d.ts +55 -0
  21. package/dist/secret-stores/exec.js +132 -0
  22. package/dist/secret-stores/exec.js.map +1 -0
  23. package/dist/secret-stores/fly.d.ts +7 -0
  24. package/dist/secret-stores/fly.js +54 -0
  25. package/dist/secret-stores/fly.js.map +1 -0
  26. package/dist/secret-stores/gcloud.d.ts +7 -0
  27. package/dist/secret-stores/gcloud.js +62 -0
  28. package/dist/secret-stores/gcloud.js.map +1 -0
  29. package/dist/secret-stores/github.d.ts +9 -0
  30. package/dist/secret-stores/github.js +74 -0
  31. package/dist/secret-stores/github.js.map +1 -0
  32. package/dist/secret-stores/gitlab.d.ts +7 -0
  33. package/dist/secret-stores/gitlab.js +82 -0
  34. package/dist/secret-stores/gitlab.js.map +1 -0
  35. package/dist/secret-stores/index.d.ts +42 -0
  36. package/dist/secret-stores/index.js +106 -0
  37. package/dist/secret-stores/index.js.map +1 -0
  38. package/dist/secret-stores/kubernetes.d.ts +8 -0
  39. package/dist/secret-stores/kubernetes.js +76 -0
  40. package/dist/secret-stores/kubernetes.js.map +1 -0
  41. package/dist/secret-stores/naming.d.ts +20 -0
  42. package/dist/secret-stores/naming.js +62 -0
  43. package/dist/secret-stores/naming.js.map +1 -0
  44. package/dist/secret-stores/onepassword.d.ts +7 -0
  45. package/dist/secret-stores/onepassword.js +50 -0
  46. package/dist/secret-stores/onepassword.js.map +1 -0
  47. package/dist/secret-stores/types.d.ts +108 -0
  48. package/dist/secret-stores/types.js +25 -0
  49. package/dist/secret-stores/types.js.map +1 -0
  50. package/dist/secret-stores/vault.d.ts +7 -0
  51. package/dist/secret-stores/vault.js +47 -0
  52. package/dist/secret-stores/vault.js.map +1 -0
  53. package/dist/secret-stores/vercel.d.ts +9 -0
  54. package/dist/secret-stores/vercel.js +49 -0
  55. package/dist/secret-stores/vercel.js.map +1 -0
  56. package/package.json +1 -1
  57. package/dist/gh-secret.d.ts +0 -31
  58. package/dist/gh-secret.js +0 -94
  59. package/dist/gh-secret.js.map +0 -1
@@ -0,0 +1,8 @@
1
+ import type { SecretStore } from "./types.js";
2
+ /**
3
+ * AWS Secrets Manager. `--secret-string` accepts the AWS CLI's `file://`
4
+ * paramfile syntax, so the plaintext is read from `/dev/stdin` rather than
5
+ * argv. `create-secret` refuses an existing name, so a second attempt stores
6
+ * a new version of it instead.
7
+ */
8
+ export declare const aws: SecretStore;
@@ -0,0 +1,59 @@
1
+ import { PATH_PLACEHOLDER, preflight } from "./exec.js";
2
+ import { resourceName, slug } from "./naming.js";
3
+ const INSTALL_HINT = "install the AWS CLI from https://aws.amazon.com/cli (brew install awscli), then configure credentials with `aws configure` or `aws sso login`";
4
+ function target(options) {
5
+ const region = options.region ? slug("--region", options.region, /^[a-z0-9-]+$/) : undefined;
6
+ return {
7
+ describe: region ? `AWS Secrets Manager in ${region}` : "AWS Secrets Manager in the configured region",
8
+ fields: region ? { region } : {},
9
+ };
10
+ }
11
+ /**
12
+ * AWS Secrets Manager. `--secret-string` accepts the AWS CLI's `file://`
13
+ * paramfile syntax, so the plaintext is read from `/dev/stdin` rather than
14
+ * argv. `create-secret` refuses an existing name, so a second attempt stores
15
+ * a new version of it instead.
16
+ */
17
+ export const aws = {
18
+ id: "aws",
19
+ label: "AWS Secrets Manager",
20
+ bin: "aws",
21
+ shorthand: "--aws-secret",
22
+ nameLabel: "NAME",
23
+ installHint: INSTALL_HINT,
24
+ options: ["region"],
25
+ validateName: (name) => resourceName("AWS Secrets Manager secret", name, "_./+=@"),
26
+ preflight: () => preflight({
27
+ bin: "aws",
28
+ label: "AWS Secrets Manager",
29
+ installHint: INSTALL_HINT,
30
+ authArgs: ["sts", "get-caller-identity"],
31
+ authHint: "Configure credentials with `aws configure` or `aws sso login` first.",
32
+ }),
33
+ resolveTarget: target,
34
+ deliveries: (name, t) => {
35
+ const region = t.fields.region ? ["--region", t.fields.region] : [];
36
+ return [
37
+ {
38
+ note: "aws secretsmanager create-secret",
39
+ kind: "path",
40
+ args: ["secretsmanager", "create-secret", "--name", name, "--secret-string", `file://${PATH_PLACEHOLDER}`, ...region],
41
+ },
42
+ {
43
+ note: "aws secretsmanager put-secret-value",
44
+ kind: "path",
45
+ args: ["secretsmanager", "put-secret-value", "--secret-id", name, "--secret-string", `file://${PATH_PLACEHOLDER}`, ...region],
46
+ },
47
+ ];
48
+ },
49
+ usage: (name, t, gateway) => {
50
+ const region = t.fields.region ? ` --region ${t.fields.region}` : "";
51
+ return [
52
+ "Read it back at runtime:",
53
+ ` aws secretsmanager get-secret-value --secret-id ${name}${region} --query SecretString --output text`,
54
+ ` # export OPENAI_API_KEY=$(…) with OPENAI_BASE_URL=${gateway.openaiBaseUrl}`,
55
+ ` # or ANTHROPIC_AUTH_TOKEN with ANTHROPIC_BASE_URL=${gateway.anthropicBaseUrl}`,
56
+ ];
57
+ },
58
+ };
59
+ //# sourceMappingURL=aws.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aws.js","sourceRoot":"","sources":["../../src/secret-stores/aws.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGjD,MAAM,YAAY,GAChB,+IAA+I,CAAC;AAElJ,SAAS,MAAM,CAAC,OAAqB;IACnC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7F,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,0BAA0B,MAAM,EAAE,CAAC,CAAC,CAAC,8CAA8C;QACtG,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE;KACjC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,GAAG,GAAgB;IAC9B,EAAE,EAAE,KAAK;IACT,KAAK,EAAE,qBAAqB;IAC5B,GAAG,EAAE,KAAK;IACV,SAAS,EAAE,cAAc;IACzB,SAAS,EAAE,MAAM;IACjB,WAAW,EAAE,YAAY;IACzB,OAAO,EAAE,CAAC,QAAQ,CAAC;IACnB,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,4BAA4B,EAAE,IAAI,EAAE,QAAQ,CAAC;IAClF,SAAS,EAAE,GAAG,EAAE,CACd,SAAS,CAAC;QACR,GAAG,EAAE,KAAK;QACV,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE,YAAY;QACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,qBAAqB,CAAC;QACxC,QAAQ,EAAE,sEAAsE;KACjF,CAAC;IACJ,aAAa,EAAE,MAAM;IACrB,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACtB,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,OAAO;YACL;gBACE,IAAI,EAAE,kCAAkC;gBACxC,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,CAAC,gBAAgB,EAAE,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,iBAAiB,EAAE,UAAU,gBAAgB,EAAE,EAAE,GAAG,MAAM,CAAC;aACtH;YACD;gBACE,IAAI,EAAE,qCAAqC;gBAC3C,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,CAAC,gBAAgB,EAAE,kBAAkB,EAAE,aAAa,EAAE,IAAI,EAAE,iBAAiB,EAAE,UAAU,gBAAgB,EAAE,EAAE,GAAG,MAAM,CAAC;aAC9H;SACF,CAAC;IACJ,CAAC;IACD,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE;QAC1B,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,OAAO;YACL,0BAA0B;YAC1B,qDAAqD,IAAI,GAAG,MAAM,qCAAqC;YACvG,uDAAuD,OAAO,CAAC,aAAa,EAAE;YAC9E,uDAAuD,OAAO,CAAC,gBAAgB,EAAE;SAClF,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { SecretStore } from "./types.js";
2
+ /**
3
+ * Azure Key Vault. `az keyvault secret set --file` reads the value from a
4
+ * file, so the plaintext travels through `/dev/stdin` instead of `--value`
5
+ * in argv. `set` already creates a new version when the secret exists.
6
+ */
7
+ export declare const azure: SecretStore;
@@ -0,0 +1,63 @@
1
+ import { PATH_PLACEHOLDER, preflight } from "./exec.js";
2
+ import { resourceName, slug } from "./naming.js";
3
+ const INSTALL_HINT = "install the Azure CLI from https://learn.microsoft.com/cli/azure/install-azure-cli (brew install azure-cli), then run `az login`";
4
+ function target(options) {
5
+ const vault = options.keyVault?.trim();
6
+ if (!vault)
7
+ throw new Error("Azure Key Vault needs --key-vault <name> (the vault the secret goes into)");
8
+ const name = slug("--key-vault", vault, /^[A-Za-z0-9-]+$/);
9
+ return { describe: `Azure Key Vault ${name}`, fields: { keyVault: name } };
10
+ }
11
+ /**
12
+ * Azure Key Vault. `az keyvault secret set --file` reads the value from a
13
+ * file, so the plaintext travels through `/dev/stdin` instead of `--value`
14
+ * in argv. `set` already creates a new version when the secret exists.
15
+ */
16
+ export const azure = {
17
+ id: "azure",
18
+ label: "Azure Key Vault",
19
+ bin: "az",
20
+ shorthand: "--az-secret",
21
+ nameLabel: "NAME",
22
+ installHint: INSTALL_HINT,
23
+ versionArgs: ["version"],
24
+ options: ["keyVault"],
25
+ validateName: (name) => resourceName("Azure Key Vault secret", name),
26
+ preflight: () => preflight({
27
+ bin: "az",
28
+ label: "Azure Key Vault",
29
+ installHint: INSTALL_HINT,
30
+ versionArgs: azure.versionArgs,
31
+ authArgs: ["account", "show"],
32
+ authHint: "Run `az login` first.",
33
+ }),
34
+ resolveTarget: target,
35
+ deliveries: (name, t) => [
36
+ {
37
+ note: "az keyvault secret set",
38
+ kind: "path",
39
+ args: [
40
+ "keyvault",
41
+ "secret",
42
+ "set",
43
+ "--vault-name",
44
+ t.fields.keyVault,
45
+ "--name",
46
+ name,
47
+ "--file",
48
+ PATH_PLACEHOLDER,
49
+ "--encoding",
50
+ "utf-8",
51
+ "--output",
52
+ "none",
53
+ ],
54
+ },
55
+ ],
56
+ usage: (name, t, gateway) => [
57
+ "Read it back at runtime:",
58
+ ` az keyvault secret show --vault-name ${t.fields.keyVault} --name ${name} --query value -o tsv`,
59
+ ` # Container Apps / App Service: reference @Microsoft.KeyVault(SecretUri=…) as OPENAI_API_KEY`,
60
+ ` # with OPENAI_BASE_URL=${gateway.openaiBaseUrl}`,
61
+ ],
62
+ };
63
+ //# sourceMappingURL=azure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure.js","sourceRoot":"","sources":["../../src/secret-stores/azure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGjD,MAAM,YAAY,GAChB,kIAAkI,CAAC;AAErI,SAAS,MAAM,CAAC,OAAqB;IACnC,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;IACzG,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC;IAC3D,OAAO,EAAE,QAAQ,EAAE,mBAAmB,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC;AAC7E,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,KAAK,GAAgB;IAChC,EAAE,EAAE,OAAO;IACX,KAAK,EAAE,iBAAiB;IACxB,GAAG,EAAE,IAAI;IACT,SAAS,EAAE,aAAa;IACxB,SAAS,EAAE,MAAM;IACjB,WAAW,EAAE,YAAY;IACzB,WAAW,EAAE,CAAC,SAAS,CAAC;IACxB,OAAO,EAAE,CAAC,UAAU,CAAC;IACrB,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,wBAAwB,EAAE,IAAI,CAAC;IACpE,SAAS,EAAE,GAAG,EAAE,CACd,SAAS,CAAC;QACR,GAAG,EAAE,IAAI;QACT,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,YAAY;QACzB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC;QAC7B,QAAQ,EAAE,uBAAuB;KAClC,CAAC;IACJ,aAAa,EAAE,MAAM;IACrB,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;QACvB;YACE,IAAI,EAAE,wBAAwB;YAC9B,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE;gBACJ,UAAU;gBACV,QAAQ;gBACR,KAAK;gBACL,cAAc;gBACd,CAAC,CAAC,MAAM,CAAC,QAAQ;gBACjB,QAAQ;gBACR,IAAI;gBACJ,QAAQ;gBACR,gBAAgB;gBAChB,YAAY;gBACZ,OAAO;gBACP,UAAU;gBACV,MAAM;aACP;SACF;KACF;IACD,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC;QAC3B,0BAA0B;QAC1B,0CAA0C,CAAC,CAAC,MAAM,CAAC,QAAQ,WAAW,IAAI,uBAAuB;QACjG,gGAAgG;QAChG,4BAA4B,OAAO,CAAC,aAAa,EAAE;KACpD;CACF,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { SecretStore } from "./types.js";
2
+ /**
3
+ * Cloudflare Workers. `wrangler secret put NAME` reads the value from stdin
4
+ * when it is not attached to a terminal, and replaces an existing secret.
5
+ * Without `--name` it uses the Worker in the local wrangler config.
6
+ */
7
+ export declare const cloudflare: SecretStore;
@@ -0,0 +1,46 @@
1
+ import { preflight } from "./exec.js";
2
+ import { envStyleName, slug } from "./naming.js";
3
+ const INSTALL_HINT = "install Wrangler from https://developers.cloudflare.com/workers/wrangler/install-and-update (npm i -g wrangler), then run `wrangler login`";
4
+ function target(options) {
5
+ const worker = options.worker ? slug("--worker", options.worker, /^[A-Za-z0-9_.-]+$/) : undefined;
6
+ return {
7
+ describe: worker ? `Cloudflare Worker ${worker}` : "the Worker in this directory's wrangler config",
8
+ fields: worker ? { worker } : {},
9
+ };
10
+ }
11
+ /**
12
+ * Cloudflare Workers. `wrangler secret put NAME` reads the value from stdin
13
+ * when it is not attached to a terminal, and replaces an existing secret.
14
+ * Without `--name` it uses the Worker in the local wrangler config.
15
+ */
16
+ export const cloudflare = {
17
+ id: "cloudflare",
18
+ label: "Cloudflare Workers",
19
+ bin: "wrangler",
20
+ shorthand: "--cf-secret",
21
+ nameLabel: "NAME",
22
+ installHint: INSTALL_HINT,
23
+ options: ["worker"],
24
+ validateName: (name) => envStyleName("Cloudflare Worker secret", name),
25
+ preflight: () => preflight({
26
+ bin: "wrangler",
27
+ label: "Cloudflare Workers",
28
+ installHint: INSTALL_HINT,
29
+ authArgs: ["whoami"],
30
+ authHint: "Run `wrangler login` first, or set CLOUDFLARE_API_TOKEN.",
31
+ }),
32
+ resolveTarget: target,
33
+ deliveries: (name, t) => {
34
+ const args = ["secret", "put", name];
35
+ if (t.fields.worker)
36
+ args.push("--name", t.fields.worker);
37
+ return [{ note: "wrangler secret put", kind: "stdin", args }];
38
+ },
39
+ usage: (name, _t, gateway) => [
40
+ "Use it inside the Worker:",
41
+ ` const key = env.${name};`,
42
+ ` // OpenAI-compatible base: ${gateway.openaiBaseUrl}`,
43
+ ` // Anthropic base: ${gateway.anthropicBaseUrl}`,
44
+ ],
45
+ };
46
+ //# sourceMappingURL=cloudflare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../../src/secret-stores/cloudflare.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGjD,MAAM,YAAY,GAChB,4IAA4I,CAAC;AAE/I,SAAS,MAAM,CAAC,OAAqB;IACnC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAClG,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,qBAAqB,MAAM,EAAE,CAAC,CAAC,CAAC,gDAAgD;QACnG,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE;KACjC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAgB;IACrC,EAAE,EAAE,YAAY;IAChB,KAAK,EAAE,oBAAoB;IAC3B,GAAG,EAAE,UAAU;IACf,SAAS,EAAE,aAAa;IACxB,SAAS,EAAE,MAAM;IACjB,WAAW,EAAE,YAAY;IACzB,OAAO,EAAE,CAAC,QAAQ,CAAC;IACnB,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,0BAA0B,EAAE,IAAI,CAAC;IACtE,SAAS,EAAE,GAAG,EAAE,CACd,SAAS,CAAC;QACR,GAAG,EAAE,UAAU;QACf,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EAAE,YAAY;QACzB,QAAQ,EAAE,CAAC,QAAQ,CAAC;QACpB,QAAQ,EAAE,0DAA0D;KACrE,CAAC;IACJ,aAAa,EAAE,MAAM;IACrB,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACtB,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC1D,OAAO,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC;QAC5B,2BAA2B;QAC3B,qBAAqB,IAAI,GAAG;QAC5B,gCAAgC,OAAO,CAAC,aAAa,EAAE;QACvD,wBAAwB,OAAO,CAAC,gBAAgB,EAAE;KACnD;CACF,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { SecretStore } from "./types.js";
2
+ /**
3
+ * Doppler. `doppler secrets set NAME` reads the value from stdin;
4
+ * `--no-interactive` keeps it from prompting and `--silent` stops it echoing
5
+ * the value back into logs. Setting an existing secret updates it.
6
+ */
7
+ export declare const doppler: SecretStore;
@@ -0,0 +1,52 @@
1
+ import { preflight } from "./exec.js";
2
+ import { envStyleName, slug } from "./naming.js";
3
+ const INSTALL_HINT = "install the Doppler CLI from https://docs.doppler.com/docs/install-cli (brew install dopplerhq/cli/doppler), then run `doppler login`";
4
+ function target(options) {
5
+ const project = options.project ? slug("--project", options.project) : undefined;
6
+ const config = options.dopplerConfig ? slug("--doppler-config", options.dopplerConfig) : undefined;
7
+ if (config && !project)
8
+ throw new Error("--doppler-config needs --project (a config belongs to one project)");
9
+ const where = project ? `Doppler ${project}${config ? `/${config}` : ""}` : "the Doppler project configured for this directory";
10
+ return { describe: where, fields: { ...(project ? { project } : {}), ...(config ? { config } : {}) } };
11
+ }
12
+ /**
13
+ * Doppler. `doppler secrets set NAME` reads the value from stdin;
14
+ * `--no-interactive` keeps it from prompting and `--silent` stops it echoing
15
+ * the value back into logs. Setting an existing secret updates it.
16
+ */
17
+ export const doppler = {
18
+ id: "doppler",
19
+ label: "Doppler",
20
+ bin: "doppler",
21
+ shorthand: "--doppler-secret",
22
+ nameLabel: "NAME",
23
+ installHint: INSTALL_HINT,
24
+ options: ["project", "dopplerConfig"],
25
+ validateName: (name) => envStyleName("Doppler secret", name),
26
+ preflight: () => preflight({
27
+ bin: "doppler",
28
+ label: "Doppler",
29
+ installHint: INSTALL_HINT,
30
+ authArgs: ["me"],
31
+ authHint: "Run `doppler login` first.",
32
+ }),
33
+ resolveTarget: target,
34
+ deliveries: (name, t) => {
35
+ const args = ["secrets", "set", name, "--no-interactive", "--silent"];
36
+ if (t.fields.project)
37
+ args.push("--project", t.fields.project);
38
+ if (t.fields.config)
39
+ args.push("--config", t.fields.config);
40
+ return [{ note: "doppler secrets set", kind: "stdin", args }];
41
+ },
42
+ usage: (name, t, gateway) => {
43
+ const scope = `${t.fields.project ? ` -p ${t.fields.project}` : ""}${t.fields.config ? ` -c ${t.fields.config}` : ""}`;
44
+ return [
45
+ "Run anything with it injected:",
46
+ ` doppler run${scope} -- your-command`,
47
+ ` # ${name} is in the environment; point clients at OPENAI_BASE_URL=${gateway.openaiBaseUrl}`,
48
+ ` doppler secrets get ${name} --plain${scope} # read it back`,
49
+ ];
50
+ },
51
+ };
52
+ //# sourceMappingURL=doppler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doppler.js","sourceRoot":"","sources":["../../src/secret-stores/doppler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import type { Delivery, SecretStore } from "./types.js";
2
+ /**
3
+ * Subprocess plumbing shared by every store. Generalized from the original
4
+ * GitHub-only helper: the plaintext goes to the child's stdin, so it never
5
+ * appears in argv, `ps`, shell history or our own output.
6
+ */
7
+ export interface RunResult {
8
+ status: number | null;
9
+ stdout: string;
10
+ stderr: string;
11
+ /** The binary is not on PATH. */
12
+ missing: boolean;
13
+ }
14
+ export declare function run(bin: string, args: string[], input?: string): RunResult;
15
+ /** Last few stderr lines, clamped — platform CLIs can be very chatty on failure. */
16
+ export declare function trimmedStderr(res: RunResult): string;
17
+ /**
18
+ * True when `bin` is on PATH. Memoized: `endpoints keys stores` asks about a
19
+ * dozen CLIs, and resolving alternate names asks again.
20
+ */
21
+ export declare function installed(bin: string, versionArgs?: readonly string[]): boolean;
22
+ /**
23
+ * Some CLIs ship under more than one name (`fly` and `flyctl`). Picks the
24
+ * first that answers, remembering it so one command spawns the probe once.
25
+ */
26
+ export declare function resolveBin(store: {
27
+ bin: string;
28
+ altBins?: readonly string[];
29
+ versionArgs?: readonly string[];
30
+ }): string;
31
+ /**
32
+ * Standard preflight: the binary answers, and the account check exits 0.
33
+ * Runs before anything is minted so a missing CLI costs nothing.
34
+ */
35
+ export declare function preflight(input: {
36
+ bin: string;
37
+ altBins?: readonly string[];
38
+ label: string;
39
+ installHint: string;
40
+ versionArgs?: readonly string[];
41
+ authArgs: string[];
42
+ authHint: string;
43
+ }): void;
44
+ /** Placeholder in `path` delivery argv, replaced with the file the CLI should read. */
45
+ export declare const PATH_PLACEHOLDER = "{}";
46
+ /**
47
+ * Hands `value` to the store's CLI, trying each attempt in order. Throws with
48
+ * every attempt's own last stderr lines when all of them fail, so the caller
49
+ * can revoke the key it just minted and the operator can see why.
50
+ *
51
+ * `path` delivery uses `/dev/stdin` wherever it exists, keeping the plaintext
52
+ * off disk. Only on Windows does it fall back to a 0600 file in a private
53
+ * temp directory, which is overwritten and removed before returning.
54
+ */
55
+ export declare function deliver(store: SecretStore, name: string, attempts: Delivery[], value: string): void;
@@ -0,0 +1,132 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ /** Keeps platform CLIs quiet and non-interactive; they must never prompt. */
6
+ const QUIET_ENV = {
7
+ GH_NO_UPDATE_NOTIFIER: "1",
8
+ GH_PROMPT_DISABLED: "1",
9
+ GLAB_CHECK_UPDATE: "0",
10
+ NO_COLOR: "1",
11
+ AWS_PAGER: "",
12
+ CLOUDSDK_CORE_DISABLE_PROMPTS: "1",
13
+ AZURE_CORE_ONLY_SHOW_ERRORS: "true",
14
+ DO_NOT_TRACK: "1",
15
+ };
16
+ export function run(bin, args, input) {
17
+ const res = spawnSync(bin, args, {
18
+ encoding: "utf8",
19
+ // Always an explicit (possibly empty) stdin: a CLI that reads stdin on a
20
+ // probe like `gh auth status` must see EOF rather than wait for us.
21
+ input: input ?? "",
22
+ stdio: ["pipe", "pipe", "pipe"],
23
+ env: { ...process.env, ...QUIET_ENV },
24
+ });
25
+ const missing = res.error !== undefined && res.error.code === "ENOENT";
26
+ return { status: res.status, stdout: res.stdout ?? "", stderr: res.stderr ?? "", missing };
27
+ }
28
+ /** Last few stderr lines, clamped — platform CLIs can be very chatty on failure. */
29
+ export function trimmedStderr(res) {
30
+ return (res.stderr || res.stdout).trim().split("\n").slice(-3).join(" ").slice(0, 300);
31
+ }
32
+ const presence = new Map();
33
+ /**
34
+ * True when `bin` is on PATH. Memoized: `endpoints keys stores` asks about a
35
+ * dozen CLIs, and resolving alternate names asks again.
36
+ */
37
+ export function installed(bin, versionArgs = ["--version"]) {
38
+ const cached = presence.get(bin);
39
+ if (cached !== undefined)
40
+ return cached;
41
+ const found = !run(bin, [...versionArgs]).missing;
42
+ presence.set(bin, found);
43
+ return found;
44
+ }
45
+ const resolvedBins = new Map();
46
+ /**
47
+ * Some CLIs ship under more than one name (`fly` and `flyctl`). Picks the
48
+ * first that answers, remembering it so one command spawns the probe once.
49
+ */
50
+ export function resolveBin(store) {
51
+ const cached = resolvedBins.get(store.bin);
52
+ if (cached)
53
+ return cached;
54
+ const candidates = [store.bin, ...(store.altBins ?? [])];
55
+ const found = candidates.find((bin) => installed(bin, store.versionArgs)) ?? store.bin;
56
+ resolvedBins.set(store.bin, found);
57
+ return found;
58
+ }
59
+ /**
60
+ * Standard preflight: the binary answers, and the account check exits 0.
61
+ * Runs before anything is minted so a missing CLI costs nothing.
62
+ */
63
+ export function preflight(input) {
64
+ const bin = resolveBin(input);
65
+ const version = run(bin, [...(input.versionArgs ?? ["--version"])]);
66
+ if (version.missing) {
67
+ throw new Error(`storing a key in ${input.label} needs ${input.bin} on PATH; ${input.installHint}`);
68
+ }
69
+ const auth = run(bin, input.authArgs);
70
+ if (auth.missing) {
71
+ throw new Error(`storing a key in ${input.label} needs ${input.bin} on PATH; ${input.installHint}`);
72
+ }
73
+ if (auth.status !== 0) {
74
+ const detail = trimmedStderr(auth);
75
+ throw new Error(`${bin} is not signed in (\`${bin} ${input.authArgs.join(" ")}\` failed${detail ? `: ${detail}` : ""}). ${input.authHint}`);
76
+ }
77
+ }
78
+ /** Placeholder in `path` delivery argv, replaced with the file the CLI should read. */
79
+ export const PATH_PLACEHOLDER = "{}";
80
+ /** POSIX CLIs can read the piped stdin through this path; Windows cannot. */
81
+ const STDIN_PATH = "/dev/stdin";
82
+ function substitute(args, path) {
83
+ return args.map((arg) => arg.split(PATH_PLACEHOLDER).join(path));
84
+ }
85
+ /**
86
+ * Hands `value` to the store's CLI, trying each attempt in order. Throws with
87
+ * every attempt's own last stderr lines when all of them fail, so the caller
88
+ * can revoke the key it just minted and the operator can see why.
89
+ *
90
+ * `path` delivery uses `/dev/stdin` wherever it exists, keeping the plaintext
91
+ * off disk. Only on Windows does it fall back to a 0600 file in a private
92
+ * temp directory, which is overwritten and removed before returning.
93
+ */
94
+ export function deliver(store, name, attempts, value) {
95
+ const failures = [];
96
+ for (const attempt of attempts) {
97
+ const payload = attempt.payload ? attempt.payload(value) : value;
98
+ const res = attempt.kind === "stdin" ? runStdin(store, attempt, payload) : runPath(store, attempt, payload);
99
+ if (res.missing) {
100
+ throw new Error(`${store.bin} disappeared from PATH while storing the secret; ${store.installHint}`);
101
+ }
102
+ if (res.status === 0)
103
+ return;
104
+ const detail = trimmedStderr(res);
105
+ failures.push(`${attempt.note}: ${detail || `exit ${res.status}`}`);
106
+ }
107
+ throw new Error(`${store.bin} could not store ${name} — ${failures.join("; ")}`);
108
+ }
109
+ function runStdin(store, attempt, payload) {
110
+ return run(resolveBin(store), attempt.args, payload);
111
+ }
112
+ function runPath(store, attempt, payload) {
113
+ if (process.platform !== "win32") {
114
+ return run(resolveBin(store), substitute(attempt.args, STDIN_PATH), payload);
115
+ }
116
+ const dir = mkdtempSync(join(tmpdir(), "heyditto-secret-"));
117
+ const file = join(dir, "value");
118
+ try {
119
+ writeFileSync(file, payload, { mode: 0o600 });
120
+ return run(resolveBin(store), substitute(attempt.args, file));
121
+ }
122
+ finally {
123
+ try {
124
+ writeFileSync(file, "0".repeat(payload.length), { mode: 0o600 });
125
+ }
126
+ catch {
127
+ // Best effort; the directory removal below is what matters.
128
+ }
129
+ rmSync(dir, { recursive: true, force: true });
130
+ }
131
+ }
132
+ //# sourceMappingURL=exec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.js","sourceRoot":"","sources":["../../src/secret-stores/exec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { SecretStore } from "./types.js";
2
+ /**
3
+ * Fly.io. `fly secrets import` reads `KEY=VALUE` lines from stdin, which is
4
+ * the only way to set a secret without putting the value in argv. It replaces
5
+ * an existing secret and stages a release for the app.
6
+ */
7
+ export declare const fly: SecretStore;
@@ -0,0 +1,54 @@
1
+ import { preflight } from "./exec.js";
2
+ import { envStyleName, slug } from "./naming.js";
3
+ const INSTALL_HINT = "install flyctl from https://fly.io/docs/flyctl/install (brew install flyctl), then run `fly auth login`";
4
+ function target(options) {
5
+ const app = options.app ? slug("--app", options.app, /^[a-z0-9-]+$/) : undefined;
6
+ return {
7
+ describe: app ? `Fly app ${app}` : "the Fly app in this directory's fly.toml",
8
+ fields: app ? { app } : {},
9
+ };
10
+ }
11
+ /**
12
+ * Fly.io. `fly secrets import` reads `KEY=VALUE` lines from stdin, which is
13
+ * the only way to set a secret without putting the value in argv. It replaces
14
+ * an existing secret and stages a release for the app.
15
+ */
16
+ export const fly = {
17
+ id: "fly",
18
+ label: "Fly.io",
19
+ bin: "fly",
20
+ altBins: ["flyctl"],
21
+ shorthand: "--fly-secret",
22
+ nameLabel: "NAME",
23
+ installHint: INSTALL_HINT,
24
+ options: ["app"],
25
+ validateName: (name) => envStyleName("Fly secret", name),
26
+ preflight: () => preflight({
27
+ bin: "fly",
28
+ altBins: ["flyctl"],
29
+ label: "Fly.io",
30
+ installHint: INSTALL_HINT,
31
+ authArgs: ["auth", "whoami"],
32
+ authHint: "Run `fly auth login` first, or set FLY_API_TOKEN.",
33
+ }),
34
+ resolveTarget: target,
35
+ deliveries: (name, t) => {
36
+ const args = ["secrets", "import"];
37
+ if (t.fields.app)
38
+ args.push("--app", t.fields.app);
39
+ return [
40
+ {
41
+ note: "fly secrets import",
42
+ kind: "stdin",
43
+ args,
44
+ payload: (value) => `${name}=${value}\n`,
45
+ },
46
+ ];
47
+ },
48
+ usage: (name, _t, gateway) => [
49
+ `${name} is in the app's environment after the release finishes:`,
50
+ ` OPENAI_API_KEY=$${name} with OPENAI_BASE_URL=${gateway.openaiBaseUrl}`,
51
+ ` # or ANTHROPIC_AUTH_TOKEN with ANTHROPIC_BASE_URL=${gateway.anthropicBaseUrl}`,
52
+ ],
53
+ };
54
+ //# sourceMappingURL=fly.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fly.js","sourceRoot":"","sources":["../../src/secret-stores/fly.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGjD,MAAM,YAAY,GAChB,yGAAyG,CAAC;AAE5G,SAAS,MAAM,CAAC,OAAqB;IACnC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACjF,OAAO;QACL,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,WAAW,GAAG,EAAE,CAAC,CAAC,CAAC,0CAA0C;QAC7E,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE;KAC3B,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,GAAG,GAAgB;IAC9B,EAAE,EAAE,KAAK;IACT,KAAK,EAAE,QAAQ;IACf,GAAG,EAAE,KAAK;IACV,OAAO,EAAE,CAAC,QAAQ,CAAC;IACnB,SAAS,EAAE,cAAc;IACzB,SAAS,EAAE,MAAM;IACjB,WAAW,EAAE,YAAY;IACzB,OAAO,EAAE,CAAC,KAAK,CAAC;IAChB,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,IAAI,CAAC;IACxD,SAAS,EAAE,GAAG,EAAE,CACd,SAAS,CAAC;QACR,GAAG,EAAE,KAAK;QACV,OAAO,EAAE,CAAC,QAAQ,CAAC;QACnB,KAAK,EAAE,QAAQ;QACf,WAAW,EAAE,YAAY;QACzB,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC;QAC5B,QAAQ,EAAE,mDAAmD;KAC9D,CAAC;IACJ,aAAa,EAAE,MAAM;IACrB,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACtB,MAAM,IAAI,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACnC,IAAI,CAAC,CAAC,MAAM,CAAC,GAAG;YAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnD,OAAO;YACL;gBACE,IAAI,EAAE,oBAAoB;gBAC1B,IAAI,EAAE,OAAO;gBACb,IAAI;gBACJ,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,IAAI,IAAI,KAAK,IAAI;aACzC;SACF,CAAC;IACJ,CAAC;IACD,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC;QAC5B,GAAG,IAAI,0DAA0D;QACjE,qBAAqB,IAAI,yBAAyB,OAAO,CAAC,aAAa,EAAE;QACzE,uDAAuD,OAAO,CAAC,gBAAgB,EAAE;KAClF;CACF,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { SecretStore } from "./types.js";
2
+ /**
3
+ * Google Secret Manager. Both `secrets create` and `versions add` read the
4
+ * payload from stdin with `--data-file=-`; creation fails when the secret
5
+ * already exists, so the second attempt adds a version to it.
6
+ */
7
+ export declare const gcloud: SecretStore;
@@ -0,0 +1,62 @@
1
+ import { preflight, run, trimmedStderr } from "./exec.js";
2
+ import { resourceName, slug } from "./naming.js";
3
+ const INSTALL_HINT = "install the Google Cloud CLI from https://cloud.google.com/sdk/docs/install (brew install --cask google-cloud-sdk), then run `gcloud auth login`";
4
+ /** The project gcloud is currently configured for, so --project stays optional. */
5
+ function resolveProjectFromConfig() {
6
+ const res = run("gcloud", ["config", "get-value", "project"]);
7
+ const project = res.stdout.trim();
8
+ if (res.status !== 0 || !project || project === "(unset)") {
9
+ const detail = trimmedStderr(res);
10
+ throw new Error(`gcloud has no active project${detail ? ` (${detail})` : ""}. Pass --project my-project, or run \`gcloud config set project my-project\`.`);
11
+ }
12
+ return project;
13
+ }
14
+ function target(options) {
15
+ const project = options.project ? slug("--project", options.project) : resolveProjectFromConfig();
16
+ return { describe: `Google Secret Manager in project ${project}`, fields: { project } };
17
+ }
18
+ /**
19
+ * Google Secret Manager. Both `secrets create` and `versions add` read the
20
+ * payload from stdin with `--data-file=-`; creation fails when the secret
21
+ * already exists, so the second attempt adds a version to it.
22
+ */
23
+ export const gcloud = {
24
+ id: "gcloud",
25
+ label: "Google Secret Manager",
26
+ bin: "gcloud",
27
+ shorthand: "--gcp-secret",
28
+ nameLabel: "NAME",
29
+ installHint: INSTALL_HINT,
30
+ options: ["project"],
31
+ validateName: (name) => resourceName("Google Secret Manager secret", name, "_"),
32
+ preflight: () => preflight({
33
+ bin: "gcloud",
34
+ label: "Google Secret Manager",
35
+ installHint: INSTALL_HINT,
36
+ authArgs: ["auth", "print-access-token"],
37
+ authHint: "Run `gcloud auth login` first.",
38
+ }),
39
+ resolveTarget: target,
40
+ deliveries: (name, t) => {
41
+ const project = ["--project", t.fields.project];
42
+ return [
43
+ {
44
+ note: "gcloud secrets create",
45
+ kind: "stdin",
46
+ args: ["secrets", "create", name, "--data-file=-", "--replication-policy=automatic", ...project],
47
+ },
48
+ {
49
+ note: "gcloud secrets versions add",
50
+ kind: "stdin",
51
+ args: ["secrets", "versions", "add", name, "--data-file=-", ...project],
52
+ },
53
+ ];
54
+ },
55
+ usage: (name, t, gateway) => [
56
+ "Read it back at runtime:",
57
+ ` gcloud secrets versions access latest --secret=${name} --project=${t.fields.project}`,
58
+ ` # export OPENAI_API_KEY=$(…) with OPENAI_BASE_URL=${gateway.openaiBaseUrl}`,
59
+ ` # Cloud Run: gcloud run deploy … --set-secrets OPENAI_API_KEY=${name}:latest`,
60
+ ],
61
+ };
62
+ //# sourceMappingURL=gcloud.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcloud.js","sourceRoot":"","sources":["../../src/secret-stores/gcloud.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGjD,MAAM,YAAY,GAChB,kJAAkJ,CAAC;AAErJ,mFAAmF;AACnF,SAAS,wBAAwB;IAC/B,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAClC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1D,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,+BAA+B,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,+EAA+E,CAC3I,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,MAAM,CAAC,OAAqB;IACnC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,wBAAwB,EAAE,CAAC;IAClG,OAAO,EAAE,QAAQ,EAAE,oCAAoC,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC;AAC1F,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,MAAM,GAAgB;IACjC,EAAE,EAAE,QAAQ;IACZ,KAAK,EAAE,uBAAuB;IAC9B,GAAG,EAAE,QAAQ;IACb,SAAS,EAAE,cAAc;IACzB,SAAS,EAAE,MAAM;IACjB,WAAW,EAAE,YAAY;IACzB,OAAO,EAAE,CAAC,SAAS,CAAC;IACpB,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,8BAA8B,EAAE,IAAI,EAAE,GAAG,CAAC;IAC/E,SAAS,EAAE,GAAG,EAAE,CACd,SAAS,CAAC;QACR,GAAG,EAAE,QAAQ;QACb,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EAAE,YAAY;QACzB,QAAQ,EAAE,CAAC,MAAM,EAAE,oBAAoB,CAAC;QACxC,QAAQ,EAAE,gCAAgC;KAC3C,CAAC;IACJ,aAAa,EAAE,MAAM;IACrB,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACtB,MAAM,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAChD,OAAO;YACL;gBACE,IAAI,EAAE,uBAAuB;gBAC7B,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,eAAe,EAAE,gCAAgC,EAAE,GAAG,OAAO,CAAC;aACjG;YACD;gBACE,IAAI,EAAE,6BAA6B;gBACnC,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC;aACxE;SACF,CAAC;IACJ,CAAC;IACD,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC;QAC3B,0BAA0B;QAC1B,oDAAoD,IAAI,cAAc,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE;QACxF,uDAAuD,OAAO,CAAC,aAAa,EAAE;QAC9E,mEAAmE,IAAI,SAAS;KACjF;CACF,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { SecretStore } from "./types.js";
2
+ export declare const GH_INSTALL_HINT = "install the GitHub CLI from https://cli.github.com (brew install gh / winget install GitHub.cli), then run `gh auth login`";
3
+ /** Resolves owner/repo for the current directory the same way `gh` does (git remotes + gh config). */
4
+ export declare function resolveRepoFromCwd(): string;
5
+ /**
6
+ * GitHub Actions. `gh secret set` reads the value from stdin when `--body` is
7
+ * omitted, so the key never appears in argv, `ps`, shell history or our output.
8
+ */
9
+ export declare const github: SecretStore;