@nkmc/cli 0.2.5 → 0.3.3

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.
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  getToken,
4
4
  saveToken
5
- } from "./chunk-MPXYSTOK.js";
5
+ } from "./chunk-TDMTBOMD.js";
6
6
 
7
7
  // src/commands/register.ts
8
8
  import { readFile } from "fs/promises";
@@ -72,11 +72,43 @@ async function getToken(domain) {
72
72
  }
73
73
  return entry.publishToken;
74
74
  }
75
+ async function saveCredentials(creds) {
76
+ const dir = nkmcDir();
77
+ await mkdir(dir, { recursive: true });
78
+ const filePath = credentialsPath();
79
+ await writeFile(filePath, JSON.stringify(creds, null, 2) + "\n");
80
+ await chmod(filePath, 384);
81
+ }
82
+ async function saveKey(domain, auth) {
83
+ const creds = await loadCredentials();
84
+ if (!creds.keys) creds.keys = {};
85
+ creds.keys[domain] = { auth, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
86
+ await saveCredentials(creds);
87
+ }
88
+ async function getKey(domain) {
89
+ const creds = await loadCredentials();
90
+ return creds.keys?.[domain] ?? null;
91
+ }
92
+ async function listKeys() {
93
+ const creds = await loadCredentials();
94
+ return creds.keys ?? {};
95
+ }
96
+ async function deleteKey(domain) {
97
+ const creds = await loadCredentials();
98
+ if (!creds.keys?.[domain]) return false;
99
+ delete creds.keys[domain];
100
+ await saveCredentials(creds);
101
+ return true;
102
+ }
75
103
 
76
104
  export {
77
105
  loadCredentials,
78
106
  saveToken,
79
107
  saveAgentToken,
80
108
  getAgentToken,
81
- getToken
109
+ getToken,
110
+ saveKey,
111
+ getKey,
112
+ listKeys,
113
+ deleteKey
82
114
  };
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/gateway/client.ts
4
+ var GatewayClient = class {
5
+ constructor(gatewayUrl, token) {
6
+ this.gatewayUrl = gatewayUrl;
7
+ this.token = token;
8
+ }
9
+ baseUrl() {
10
+ return this.gatewayUrl.replace(/\/$/, "");
11
+ }
12
+ async execute(command) {
13
+ const url = `${this.baseUrl()}/execute`;
14
+ const res = await fetch(url, {
15
+ method: "POST",
16
+ headers: {
17
+ Authorization: `Bearer ${this.token}`,
18
+ "Content-Type": "application/json"
19
+ },
20
+ body: JSON.stringify({ command })
21
+ });
22
+ if (!res.ok) {
23
+ const body = await res.text();
24
+ throw new Error(`Gateway error ${res.status}: ${body}`);
25
+ }
26
+ return res.json();
27
+ }
28
+ // --- BYOK methods ---
29
+ async uploadByok(domain, auth) {
30
+ const url = `${this.baseUrl()}/byok/${domain}`;
31
+ const res = await fetch(url, {
32
+ method: "PUT",
33
+ headers: {
34
+ Authorization: `Bearer ${this.token}`,
35
+ "Content-Type": "application/json"
36
+ },
37
+ body: JSON.stringify({ auth })
38
+ });
39
+ if (!res.ok) {
40
+ const body = await res.text();
41
+ throw new Error(`BYOK upload failed ${res.status}: ${body}`);
42
+ }
43
+ }
44
+ async listByok() {
45
+ const url = `${this.baseUrl()}/byok`;
46
+ const res = await fetch(url, {
47
+ headers: { Authorization: `Bearer ${this.token}` }
48
+ });
49
+ if (!res.ok) {
50
+ const body = await res.text();
51
+ throw new Error(`BYOK list failed ${res.status}: ${body}`);
52
+ }
53
+ return res.json();
54
+ }
55
+ async deleteByok(domain) {
56
+ const url = `${this.baseUrl()}/byok/${domain}`;
57
+ const res = await fetch(url, {
58
+ method: "DELETE",
59
+ headers: { Authorization: `Bearer ${this.token}` }
60
+ });
61
+ if (!res.ok) {
62
+ const body = await res.text();
63
+ throw new Error(`BYOK delete failed ${res.status}: ${body}`);
64
+ }
65
+ }
66
+ };
67
+ async function createClient() {
68
+ const { getAgentToken } = await import("./credentials-O3WAXKAV.js");
69
+ const stored = await getAgentToken();
70
+ const gatewayUrl = process.env.NKMC_GATEWAY_URL ?? stored?.gatewayUrl ?? "https://api.nkmc.ai";
71
+ const token = process.env.NKMC_TOKEN ?? stored?.token ?? null;
72
+ if (!token) {
73
+ throw new Error(
74
+ "No token found. Run 'nkmc auth' first, or set NKMC_TOKEN."
75
+ );
76
+ }
77
+ return new GatewayClient(gatewayUrl, token);
78
+ }
79
+
80
+ export {
81
+ GatewayClient,
82
+ createClient
83
+ };
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ GatewayClient,
4
+ createClient
5
+ } from "./chunk-ZFNDBUPR.js";
6
+ export {
7
+ GatewayClient,
8
+ createClient
9
+ };
@@ -1,15 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ deleteKey,
3
4
  getAgentToken,
5
+ getKey,
4
6
  getToken,
7
+ listKeys,
5
8
  loadCredentials,
6
9
  saveAgentToken,
10
+ saveKey,
7
11
  saveToken
8
- } from "./chunk-MPXYSTOK.js";
12
+ } from "./chunk-TDMTBOMD.js";
9
13
  export {
14
+ deleteKey,
10
15
  getAgentToken,
16
+ getKey,
11
17
  getToken,
18
+ listKeys,
12
19
  loadCredentials,
13
20
  saveAgentToken,
21
+ saveKey,
14
22
  saveToken
15
23
  };
package/dist/index.js CHANGED
@@ -1,13 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runRegister
4
- } from "./chunk-5ZYHHSZI.js";
4
+ } from "./chunk-HXHGF76V.js";
5
5
  import {
6
+ deleteKey,
7
+ listKeys,
6
8
  saveAgentToken,
9
+ saveKey,
7
10
  saveToken
8
- } from "./chunk-MPXYSTOK.js";
11
+ } from "./chunk-TDMTBOMD.js";
12
+ import {
13
+ createClient
14
+ } from "./chunk-ZFNDBUPR.js";
9
15
 
10
16
  // src/index.ts
17
+ import { createRequire } from "module";
11
18
  import { Command } from "commander";
12
19
 
13
20
  // src/scanner/detect.ts
@@ -55,14 +62,14 @@ async function detectFramework(projectDir) {
55
62
  import { readFile as readFile2, writeFile } from "fs/promises";
56
63
  import { join as join2 } from "path";
57
64
  function generateConfig(options) {
58
- const { name, version, roles, detected } = options;
65
+ const { name, version: version2, roles, detected } = options;
59
66
  const rolesStr = roles.map((r) => `"${r}"`).join(", ");
60
67
  const lines = [
61
68
  `import { defineConfig } from "@nkmc/core";`,
62
69
  ``,
63
70
  `export default defineConfig({`,
64
71
  ` name: "${name}",`,
65
- ` version: "${version}",`,
72
+ ` version: "${version2}",`,
66
73
  ` roles: [${rolesStr}],`,
67
74
  ` framework: "${detected.framework}",`
68
75
  ];
@@ -444,7 +451,7 @@ async function runGenerate(projectDir, options) {
444
451
  await writeFile2(outputPath, md);
445
452
  console.log(`Generated ${outputPath}`);
446
453
  if (options?.register) {
447
- const { registerService, resolveToken } = await import("./register-7SUETZ7U.js");
454
+ const { registerService, resolveToken } = await import("./register-UBRUY256.js");
448
455
  const gatewayUrl = options.gatewayUrl ?? process.env.NKMC_GATEWAY_URL;
449
456
  const domain = options.domain ?? process.env.NKMC_DOMAIN;
450
457
  if (!gatewayUrl || !domain) {
@@ -560,40 +567,160 @@ async function runAuth(opts) {
560
567
  console.log(` Gateway: ${gatewayUrl}`);
561
568
  }
562
569
 
563
- // src/gateway/client.ts
564
- var GatewayClient = class {
565
- constructor(gatewayUrl, token) {
566
- this.gatewayUrl = gatewayUrl;
567
- this.token = token;
568
- }
569
- async execute(command) {
570
- const url = `${this.gatewayUrl.replace(/\/$/, "")}/execute`;
571
- const res = await fetch(url, {
572
- method: "POST",
573
- headers: {
574
- Authorization: `Bearer ${this.token}`,
575
- "Content-Type": "application/json"
576
- },
577
- body: JSON.stringify({ command })
578
- });
579
- if (!res.ok) {
580
- const body = await res.text();
581
- throw new Error(`Gateway error ${res.status}: ${body}`);
582
- }
583
- return res.json();
570
+ // src/keys/provider-map.ts
571
+ var DOMAIN_AUTH_HINTS = {
572
+ // --- AI ---
573
+ "api.openai.com": {
574
+ envVar: "OPENAI_API_KEY",
575
+ authType: "bearer",
576
+ guideUrl: "https://platform.openai.com/api-keys"
577
+ },
578
+ "api.anthropic.com": {
579
+ envVar: "ANTHROPIC_API_KEY",
580
+ authType: "api-key",
581
+ headerName: "x-api-key",
582
+ guideUrl: "https://console.anthropic.com/settings/keys"
583
+ },
584
+ "generativelanguage.googleapis.com": {
585
+ envVar: "GEMINI_API_KEY",
586
+ authType: "api-key",
587
+ headerName: "x-goog-api-key",
588
+ guideUrl: "https://aistudio.google.com/apikey"
589
+ },
590
+ "openrouter.ai": {
591
+ envVar: "OPENROUTER_API_KEY",
592
+ authType: "bearer",
593
+ guideUrl: "https://openrouter.ai/keys"
594
+ },
595
+ "api.replicate.com": {
596
+ envVar: "REPLICATE_API_TOKEN",
597
+ authType: "bearer",
598
+ guideUrl: "https://replicate.com/account/api-tokens"
599
+ },
600
+ // --- DevOps ---
601
+ "api.github.com": {
602
+ envVar: "GITHUB_TOKEN",
603
+ authType: "bearer",
604
+ guideUrl: "https://github.com/settings/tokens"
605
+ },
606
+ "gitlab.com": {
607
+ envVar: "GITLAB_TOKEN",
608
+ authType: "bearer",
609
+ guideUrl: "https://gitlab.com/-/user_settings/personal_access_tokens"
610
+ },
611
+ "api.cloudflare.com": {
612
+ envVar: "CLOUDFLARE_API_TOKEN",
613
+ authType: "bearer",
614
+ guideUrl: "https://dash.cloudflare.com/profile/api-tokens"
615
+ },
616
+ "api.vercel.com": {
617
+ envVar: "VERCEL_TOKEN",
618
+ authType: "bearer",
619
+ guideUrl: "https://vercel.com/account/tokens"
620
+ },
621
+ "fly.io": {
622
+ envVar: "FLY_API_TOKEN",
623
+ authType: "bearer",
624
+ guideUrl: "https://fly.io/user/personal_access_tokens"
625
+ },
626
+ "api.render.com": {
627
+ envVar: "RENDER_API_KEY",
628
+ authType: "bearer",
629
+ guideUrl: "https://render.com/docs/api#authentication"
630
+ },
631
+ // --- Collaboration ---
632
+ "api.notion.com": {
633
+ envVar: "NOTION_API_KEY",
634
+ authType: "bearer",
635
+ guideUrl: "https://www.notion.so/my-integrations"
636
+ },
637
+ "app.asana.com": {
638
+ envVar: "ASANA_TOKEN",
639
+ authType: "bearer",
640
+ guideUrl: "https://app.asana.com/0/developer-console"
641
+ },
642
+ "jira.atlassian.com": {
643
+ envVar: "JIRA_API_TOKEN",
644
+ authType: "bearer",
645
+ guideUrl: "https://id.atlassian.com/manage-profile/security/api-tokens"
646
+ },
647
+ "slack.com": {
648
+ envVar: "SLACK_TOKEN",
649
+ authType: "bearer",
650
+ guideUrl: "https://api.slack.com/apps"
651
+ },
652
+ "discord.com": {
653
+ envVar: "DISCORD_TOKEN",
654
+ authType: "bearer",
655
+ guideUrl: "https://discord.com/developers/applications"
656
+ },
657
+ // --- Databases ---
658
+ "api.supabase.com": {
659
+ envVar: "SUPABASE_SERVICE_ROLE_KEY",
660
+ authType: "bearer",
661
+ guideUrl: "https://supabase.com/dashboard/project/_/settings/api"
662
+ },
663
+ "api.turso.tech": {
664
+ envVar: "TURSO_AUTH_TOKEN",
665
+ authType: "bearer",
666
+ guideUrl: "https://turso.tech/app"
667
+ },
668
+ "console.neon.tech": {
669
+ envVar: "NEON_API_KEY",
670
+ authType: "bearer",
671
+ guideUrl: "https://console.neon.tech"
672
+ },
673
+ // --- Communication ---
674
+ "api.twilio.com": {
675
+ envVar: "TWILIO_AUTH_TOKEN",
676
+ authType: "bearer",
677
+ guideUrl: "https://console.twilio.com"
678
+ },
679
+ "api.resend.com": {
680
+ envVar: "RESEND_API_KEY",
681
+ authType: "bearer",
682
+ guideUrl: "https://resend.com/api-keys"
683
+ },
684
+ // --- Payments ---
685
+ "api.stripe.com": {
686
+ envVar: "STRIPE_SECRET_KEY",
687
+ authType: "bearer",
688
+ guideUrl: "https://dashboard.stripe.com/apikeys"
689
+ },
690
+ // --- Monitoring ---
691
+ "sentry.io": {
692
+ envVar: "SENTRY_AUTH_TOKEN",
693
+ authType: "bearer",
694
+ guideUrl: "https://sentry.io/settings/account/api/auth-tokens/"
695
+ },
696
+ "api.datadoghq.com": {
697
+ envVar: "DD_API_KEY",
698
+ authType: "api-key",
699
+ headerName: "DD-API-KEY",
700
+ guideUrl: "https://app.datadoghq.com/account/settings#api"
701
+ },
702
+ // --- Music ---
703
+ "api.spotify.com": {
704
+ envVar: "SPOTIFY_TOKEN",
705
+ authType: "bearer",
706
+ guideUrl: "https://developer.spotify.com/dashboard"
707
+ },
708
+ // --- CI/CD ---
709
+ "circleci.com": {
710
+ envVar: "CIRCLECI_TOKEN",
711
+ authType: "bearer",
712
+ guideUrl: "https://app.circleci.com/settings/user/tokens"
713
+ },
714
+ // --- API Tools ---
715
+ "api.getpostman.com": {
716
+ envVar: "POSTMAN_API_KEY",
717
+ authType: "api-key",
718
+ headerName: "X-Api-Key",
719
+ guideUrl: "https://web.postman.co/settings/me/api-keys"
584
720
  }
585
721
  };
586
- async function createClient() {
587
- const { getAgentToken } = await import("./credentials-42DL3WPT.js");
588
- const stored = await getAgentToken();
589
- const gatewayUrl = process.env.NKMC_GATEWAY_URL ?? stored?.gatewayUrl ?? "https://api.nkmc.ai";
590
- const token = process.env.NKMC_TOKEN ?? stored?.token ?? null;
591
- if (!token) {
592
- throw new Error(
593
- "No token found. Run 'nkmc auth' first, or set NKMC_TOKEN."
594
- );
595
- }
596
- return new GatewayClient(gatewayUrl, token);
722
+ function getAuthHint(domain) {
723
+ return DOMAIN_AUTH_HINTS[domain] ?? null;
597
724
  }
598
725
 
599
726
  // src/commands/fs.ts
@@ -628,8 +755,33 @@ ${endpoints}`;
628
755
  }
629
756
  return JSON.stringify(data);
630
757
  }
631
- function handleError(err) {
758
+ function extractDomain(path) {
759
+ const segments = path.replace(/^\/+/, "").split("/");
760
+ const first = segments[0];
761
+ if (!first) return null;
762
+ const domain = first.includes("@") ? first.slice(0, first.indexOf("@")) : first;
763
+ return domain.includes(".") ? domain : null;
764
+ }
765
+ function isAuthError(message) {
766
+ if (/Gateway error (401|403):/.test(message)) return true;
767
+ if (/Gateway error 500:/.test(message) && /\b(Unauthorized|Unauthenticated|authenticate|API key|api[_-]?key)\b/i.test(message)) return true;
768
+ return false;
769
+ }
770
+ function handleError(err, cmdPath) {
632
771
  const message = err instanceof Error ? err.message : String(err);
772
+ if (isAuthError(message)) {
773
+ const domain = cmdPath && extractDomain(cmdPath) || message.match(/([a-z0-9-]+(?:\.[a-z0-9-]+){1,})/i)?.[1] || null;
774
+ if (domain) {
775
+ const hint = getAuthHint(domain);
776
+ console.error(`Error: Authentication required for ${domain}`);
777
+ if (hint?.guideUrl) {
778
+ console.error(` Get your key: ${hint.guideUrl}`);
779
+ }
780
+ console.error(` Set your key: nkmc keys set ${domain} --token <YOUR_KEY> --sync`);
781
+ console.error(` Then retry your command.`);
782
+ process.exit(1);
783
+ }
784
+ }
633
785
  console.error(JSON.stringify({ error: message }));
634
786
  process.exit(1);
635
787
  }
@@ -640,7 +792,7 @@ function registerFsCommands(program2) {
640
792
  const result = await client.execute(`ls ${path}`);
641
793
  output(result);
642
794
  } catch (err) {
643
- handleError(err);
795
+ handleError(err, path);
644
796
  }
645
797
  });
646
798
  program2.command("cat").description("Read file contents").argument("<path>", "File path").action(async (path) => {
@@ -649,7 +801,7 @@ function registerFsCommands(program2) {
649
801
  const result = await client.execute(`cat ${path}`);
650
802
  output(result);
651
803
  } catch (err) {
652
- handleError(err);
804
+ handleError(err, path);
653
805
  }
654
806
  });
655
807
  program2.command("write").description("Write data to a file").argument("<path>", "File path").argument("<data>", "Data to write").action(async (path, data) => {
@@ -658,7 +810,7 @@ function registerFsCommands(program2) {
658
810
  const result = await client.execute(`write ${path} ${data}`);
659
811
  output(result);
660
812
  } catch (err) {
661
- handleError(err);
813
+ handleError(err, path);
662
814
  }
663
815
  });
664
816
  program2.command("rm").description("Remove a file").argument("<path>", "File path").action(async (path) => {
@@ -667,7 +819,7 @@ function registerFsCommands(program2) {
667
819
  const result = await client.execute(`rm ${path}`);
668
820
  output(result);
669
821
  } catch (err) {
670
- handleError(err);
822
+ handleError(err, path);
671
823
  }
672
824
  });
673
825
  program2.command("grep").description("Search file contents").argument("<pattern>", "Search pattern").argument("<path>", "File or directory path").action(async (pattern, path) => {
@@ -676,7 +828,7 @@ function registerFsCommands(program2) {
676
828
  const result = await client.execute(`grep ${pattern} ${path}`);
677
829
  console.log(formatGrepResults(result));
678
830
  } catch (err) {
679
- handleError(err);
831
+ handleError(err, path);
680
832
  }
681
833
  });
682
834
  program2.command("pipe").description("Pipe commands: cat <path> | write <path>").argument("<expression...>", "Pipe expression").action(async (expression) => {
@@ -686,8 +838,8 @@ function registerFsCommands(program2) {
686
838
  if (parts.length !== 2) {
687
839
  throw new Error("Pipe expression must have exactly two stages separated by '|'");
688
840
  }
689
- const [source, target] = parts;
690
- if (!source.startsWith("cat ")) {
841
+ const [source2, target] = parts;
842
+ if (!source2.startsWith("cat ")) {
691
843
  throw new Error("Pipe step 1 must be a 'cat' command");
692
844
  }
693
845
  if (!target.startsWith("write ")) {
@@ -696,7 +848,7 @@ function registerFsCommands(program2) {
696
848
  const client = await createClient();
697
849
  let data;
698
850
  try {
699
- data = await client.execute(source);
851
+ data = await client.execute(source2);
700
852
  } catch (err) {
701
853
  const msg = err instanceof Error ? err.message : String(err);
702
854
  throw new Error(`Pipe step 1 failed: ${msg}`);
@@ -711,14 +863,130 @@ function registerFsCommands(program2) {
711
863
  }
712
864
  output(result);
713
865
  } catch (err) {
714
- handleError(err);
866
+ handleError(err, source.slice("cat ".length).trim());
867
+ }
868
+ });
869
+ }
870
+
871
+ // src/commands/keys.ts
872
+ function registerKeysCommand(program2) {
873
+ const keys = program2.command("keys").description("Manage API keys for authenticated services (BYOK)");
874
+ keys.command("set <domain>").description("Set an API key for a domain").option("--token <value>", "API key / token value").option("--sync", "Also upload to gateway (BYOK)").action(async (domain, opts) => {
875
+ try {
876
+ const hint = getAuthHint(domain);
877
+ let tokenValue = opts.token;
878
+ if (!tokenValue) {
879
+ const envHint = hint ? `(${hint.envVar})` : "";
880
+ console.error(
881
+ `Usage: nkmc keys set ${domain} --token <value> ${envHint}`
882
+ );
883
+ if (hint?.guideUrl) {
884
+ console.error(` Get your key: ${hint.guideUrl}`);
885
+ }
886
+ process.exit(1);
887
+ }
888
+ const auth = buildAuth(domain, tokenValue, hint);
889
+ await saveKey(domain, auth);
890
+ console.log(`Key saved for ${domain}`);
891
+ if (opts.sync) {
892
+ await syncToGateway(domain, auth);
893
+ }
894
+ } catch (err) {
895
+ const msg = err instanceof Error ? err.message : String(err);
896
+ console.error(`Error: ${msg}`);
897
+ process.exit(1);
898
+ }
899
+ });
900
+ keys.command("list").description("List all saved API keys").option("--remote", "Also list keys stored on gateway").action(async (opts) => {
901
+ try {
902
+ const localKeys = await listKeys();
903
+ const domains = Object.keys(localKeys);
904
+ if (domains.length === 0 && !opts.remote) {
905
+ console.log("No keys stored. Use 'nkmc keys set <domain>' to add one.");
906
+ return;
907
+ }
908
+ if (domains.length > 0) {
909
+ console.log("Local keys:");
910
+ for (const domain of domains) {
911
+ const entry = localKeys[domain];
912
+ const maskedAuth = maskAuth(entry.auth);
913
+ console.log(` ${domain} ${maskedAuth} (${entry.updatedAt})`);
914
+ }
915
+ }
916
+ if (opts.remote) {
917
+ try {
918
+ const { createClient: createClient2 } = await import("./client-GXGVRLEH.js");
919
+ const client = await createClient2();
920
+ const { domains: remoteDomains } = await client.listByok();
921
+ console.log("\nGateway BYOK keys:");
922
+ if (remoteDomains.length === 0) {
923
+ console.log(" (none)");
924
+ } else {
925
+ for (const d of remoteDomains) {
926
+ console.log(` ${d}`);
927
+ }
928
+ }
929
+ } catch (err) {
930
+ const msg = err instanceof Error ? err.message : String(err);
931
+ console.error(`
932
+ Could not fetch remote keys: ${msg}`);
933
+ }
934
+ }
935
+ } catch (err) {
936
+ const msg = err instanceof Error ? err.message : String(err);
937
+ console.error(`Error: ${msg}`);
938
+ process.exit(1);
939
+ }
940
+ });
941
+ keys.command("remove <domain>").description("Remove an API key for a domain").option("--remote", "Also remove from gateway").action(async (domain, opts) => {
942
+ try {
943
+ const removed = await deleteKey(domain);
944
+ if (removed) {
945
+ console.log(`Key removed for ${domain}`);
946
+ } else {
947
+ console.log(`No key found for ${domain}`);
948
+ }
949
+ if (opts.remote) {
950
+ try {
951
+ const { createClient: createClient2 } = await import("./client-GXGVRLEH.js");
952
+ const client = await createClient2();
953
+ await client.deleteByok(domain);
954
+ console.log(`Gateway BYOK key removed for ${domain}`);
955
+ } catch (err) {
956
+ const msg = err instanceof Error ? err.message : String(err);
957
+ console.error(`Could not remove remote key: ${msg}`);
958
+ }
959
+ }
960
+ } catch (err) {
961
+ const msg = err instanceof Error ? err.message : String(err);
962
+ console.error(`Error: ${msg}`);
963
+ process.exit(1);
715
964
  }
716
965
  });
717
966
  }
967
+ function buildAuth(domain, token, hint) {
968
+ if (hint?.authType === "api-key" && hint.headerName) {
969
+ return { type: "api-key", header: hint.headerName, key: token };
970
+ }
971
+ return { type: "bearer", token };
972
+ }
973
+ function maskAuth(auth) {
974
+ const value = auth.token ?? auth.key ?? "";
975
+ if (value.length <= 8) return `${auth.type}:****`;
976
+ return `${auth.type}:${value.slice(0, 4)}...${value.slice(-4)}`;
977
+ }
978
+ async function syncToGateway(domain, auth) {
979
+ const { createClient: createClient2 } = await import("./client-GXGVRLEH.js");
980
+ const client = await createClient2();
981
+ await client.uploadByok(domain, auth);
982
+ console.log(`Key synced to gateway for ${domain}`);
983
+ }
718
984
 
719
985
  // src/index.ts
986
+ var require2 = createRequire(import.meta.url);
987
+ var { version } = require2("../../package.json");
720
988
  var program = new Command();
721
- program.name("nkmc").description("nkmc SDK CLI").version("0.1.0");
989
+ program.name("nkmc").description("nkmc SDK CLI").version(version);
722
990
  program.command("init").description("Initialize nkmc in the current project").argument("[dir]", "Project directory", ".").action(async (dir) => {
723
991
  const projectDir = dir === "." ? process.cwd() : dir;
724
992
  await runInit(projectDir);
@@ -754,4 +1022,5 @@ program.command("auth").description("Authenticate with the nkmc gateway").option
754
1022
  await runAuth({ gatewayUrl: opts.gatewayUrl });
755
1023
  });
756
1024
  registerFsCommands(program);
1025
+ registerKeysCommand(program);
757
1026
  program.parse();
@@ -3,8 +3,8 @@ import {
3
3
  registerService,
4
4
  resolveToken,
5
5
  runRegister
6
- } from "./chunk-5ZYHHSZI.js";
7
- import "./chunk-MPXYSTOK.js";
6
+ } from "./chunk-HXHGF76V.js";
7
+ import "./chunk-TDMTBOMD.js";
8
8
  export {
9
9
  registerService,
10
10
  resolveToken,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nkmc/cli",
3
- "version": "0.2.5",
3
+ "version": "0.3.3",
4
4
  "description": "CLI for scanning and registering APIs with the nkmc gateway",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "@mrleebo/prisma-ast": "^0.13.1",
16
- "@nkmc/core": "^0.1.0",
16
+ "@nkmc/core": "^0.1.1",
17
17
  "commander": "^13.0.0",
18
18
  "ts-morph": "^27.0.2"
19
19
  },