@positronic/cli 0.0.73 → 0.0.74

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 (46) hide show
  1. package/dist/src/cli.js +86 -109
  2. package/dist/src/commands/auth.js +8 -34
  3. package/dist/src/commands/users.js +15 -14
  4. package/dist/src/components/auth-login.js +1 -1
  5. package/dist/src/components/project-auth-setup.js +1 -1
  6. package/dist/src/components/schedule-list.js +1 -1
  7. package/dist/src/components/store-explorer.js +2 -2
  8. package/dist/src/components/users-create.js +2 -4
  9. package/dist/src/components/users-delete.js +5 -5
  10. package/dist/src/components/users-keys-add.js +71 -17
  11. package/dist/src/components/users-keys-list.js +5 -5
  12. package/dist/src/components/users-keys-remove.js +5 -5
  13. package/dist/src/components/users-list.js +2 -11
  14. package/dist/src/components/whoami.js +71 -0
  15. package/dist/src/hooks/useApi.js +2 -2
  16. package/dist/src/lib/jwt-auth.js +1 -1
  17. package/dist/src/lib/ssh-key-utils.js +17 -0
  18. package/dist/types/cli.d.ts.map +1 -1
  19. package/dist/types/commands/auth.d.ts +5 -18
  20. package/dist/types/commands/auth.d.ts.map +1 -1
  21. package/dist/types/commands/users.d.ts +13 -12
  22. package/dist/types/commands/users.d.ts.map +1 -1
  23. package/dist/types/components/users-create.d.ts.map +1 -1
  24. package/dist/types/components/users-delete.d.ts +2 -2
  25. package/dist/types/components/users-delete.d.ts.map +1 -1
  26. package/dist/types/components/users-keys-add.d.ts +4 -3
  27. package/dist/types/components/users-keys-add.d.ts.map +1 -1
  28. package/dist/types/components/users-keys-list.d.ts +2 -2
  29. package/dist/types/components/users-keys-list.d.ts.map +1 -1
  30. package/dist/types/components/users-keys-remove.d.ts +2 -2
  31. package/dist/types/components/users-keys-remove.d.ts.map +1 -1
  32. package/dist/types/components/users-list.d.ts.map +1 -1
  33. package/dist/types/components/whoami.d.ts +8 -0
  34. package/dist/types/components/whoami.d.ts.map +1 -0
  35. package/dist/types/lib/ssh-key-utils.d.ts +5 -0
  36. package/dist/types/lib/ssh-key-utils.d.ts.map +1 -1
  37. package/package.json +4 -4
  38. package/dist/src/components/auth-format-jwk-key.js +0 -457
  39. package/dist/src/components/auth-list.js +0 -66
  40. package/dist/src/components/auth-status.js +0 -113
  41. package/dist/types/components/auth-format-jwk-key.d.ts +0 -6
  42. package/dist/types/components/auth-format-jwk-key.d.ts.map +0 -1
  43. package/dist/types/components/auth-list.d.ts +0 -8
  44. package/dist/types/components/auth-list.d.ts.map +0 -1
  45. package/dist/types/components/auth-status.d.ts +0 -8
  46. package/dist/types/components/auth-status.d.ts.map +0 -1
package/dist/src/cli.js CHANGED
@@ -891,9 +891,9 @@ export function buildCli(options) {
891
891
  }, function(argv) {
892
892
  var element = usersCommand.create(argv);
893
893
  render(element);
894
- }).command('delete <id>', 'Delete a user\n', function(yargsDelete) {
895
- return yargsDelete.positional('id', {
896
- describe: 'ID of the user to delete',
894
+ }).command('delete <name>', 'Delete a user\n', function(yargsDelete) {
895
+ return yargsDelete.positional('name', {
896
+ describe: 'Name of the user to delete',
897
897
  type: 'string',
898
898
  demandOption: true
899
899
  }).option('force', {
@@ -901,67 +901,63 @@ export function buildCli(options) {
901
901
  type: 'boolean',
902
902
  alias: 'f',
903
903
  default: false
904
- }).example('$0 users delete abc123', 'Delete a user').example('$0 users delete abc123 --force', 'Delete without confirmation');
904
+ }).example('$0 users delete admin', 'Delete a user').example('$0 users delete admin --force', 'Delete without confirmation');
905
905
  }, function(argv) {
906
906
  var element = usersCommand.delete(argv);
907
907
  render(element);
908
- }).command('keys', 'Manage SSH keys for users\n', function(yargsKeys) {
909
- return yargsKeys.command('list <user-id>', 'List keys for a user\n', function(yargsKeysList) {
910
- return yargsKeysList.positional('user-id', {
911
- describe: 'User ID',
912
- type: 'string',
913
- demandOption: true
914
- }).example('$0 users keys list abc123', 'List keys for a user');
915
- }, function(argv) {
916
- var element = usersCommand.keysList({
917
- id: argv.userId
918
- });
919
- render(element);
920
- }).command('add <user-id> <pubkey-path>', 'Add an SSH public key to a user\n', function(yargsAdd) {
921
- return yargsAdd.positional('user-id', {
922
- describe: 'User ID',
923
- type: 'string',
924
- demandOption: true
925
- }).positional('pubkey-path', {
926
- describe: 'Path to the SSH public key file',
927
- type: 'string',
928
- demandOption: true
929
- }).option('label', {
930
- describe: 'Label for the key (e.g., "laptop", "desktop")',
931
- type: 'string',
932
- alias: 'l'
933
- }).example('$0 users keys add abc123 ~/.ssh/id_rsa.pub', 'Add RSA public key').example('$0 users keys add abc123 ~/.ssh/id_ed25519.pub --label laptop', 'Add key with label');
934
- }, function(argv) {
935
- var element = usersCommand.keysAdd({
936
- id: argv.userId,
937
- pubkeyPath: argv.pubkeyPath,
938
- label: argv.label
939
- });
940
- render(element);
941
- }).command('remove <user-id> <fingerprint>', 'Remove a key from a user\n', function(yargsRemove) {
942
- return yargsRemove.positional('user-id', {
943
- describe: 'User ID',
944
- type: 'string',
945
- demandOption: true
946
- }).positional('fingerprint', {
947
- describe: 'Fingerprint of the key to remove',
948
- type: 'string',
949
- demandOption: true
950
- }).option('force', {
951
- describe: 'Skip confirmation prompt',
952
- type: 'boolean',
953
- alias: 'f',
954
- default: false
955
- }).example('$0 users keys remove abc123 SHA256:...', 'Remove a key');
956
- }, function(argv) {
957
- var element = usersCommand.keysRemove({
958
- id: argv.userId,
959
- fingerprint: argv.fingerprint,
960
- force: argv.force
961
- });
962
- render(element);
963
- }).demandCommand(1, 'You need to specify a keys command (list, add, remove)');
964
- }).demandCommand(1, 'You need to specify a users command (list, create, delete, keys)');
908
+ }).command('list-keys <name>', 'List keys for a user\n', function(yargsKeysList) {
909
+ return yargsKeysList.positional('name', {
910
+ describe: 'Name of the user',
911
+ type: 'string',
912
+ demandOption: true
913
+ }).example('$0 users list-keys admin', 'List keys for a user');
914
+ }, function(argv) {
915
+ var element = usersCommand.listKeys(argv);
916
+ render(element);
917
+ }).command('add-key <name> [pubkey-path]', 'Add an SSH public key to a user\n', function(yargsAdd) {
918
+ return yargsAdd.positional('name', {
919
+ describe: 'Name of the user',
920
+ type: 'string',
921
+ demandOption: true
922
+ }).positional('pubkey-path', {
923
+ describe: 'Path to the SSH public key file',
924
+ type: 'string'
925
+ }).option('paste', {
926
+ describe: 'Paste a public key from clipboard',
927
+ type: 'boolean',
928
+ default: false
929
+ }).option('label', {
930
+ describe: 'Label for the key (e.g., "laptop", "desktop")',
931
+ type: 'string',
932
+ alias: 'l'
933
+ }).check(function(argv) {
934
+ if (!argv.pubkeyPath && !argv.paste) {
935
+ throw new Error('You must provide a pubkey-path or use --paste');
936
+ }
937
+ return true;
938
+ }).example('$0 users add-key admin ~/.ssh/id_ed25519.pub', 'Add an SSH public key').example('$0 users add-key admin --paste', 'Paste a public key interactively').example('$0 users add-key admin ~/.ssh/id_ed25519.pub --label laptop', 'Add key with label');
939
+ }, function(argv) {
940
+ var element = usersCommand.addKey(argv);
941
+ render(element);
942
+ }).command('remove-key <name> <fingerprint>', 'Remove a key from a user\n', function(yargsRemove) {
943
+ return yargsRemove.positional('name', {
944
+ describe: 'Name of the user',
945
+ type: 'string',
946
+ demandOption: true
947
+ }).positional('fingerprint', {
948
+ describe: 'Fingerprint of the key to remove',
949
+ type: 'string',
950
+ demandOption: true
951
+ }).option('force', {
952
+ describe: 'Skip confirmation prompt',
953
+ type: 'boolean',
954
+ alias: 'f',
955
+ default: false
956
+ }).example('$0 users remove-key admin SHA256:...', 'Remove a key');
957
+ }, function(argv) {
958
+ var element = usersCommand.removeKey(argv);
959
+ render(element);
960
+ }).demandCommand(1, 'You need to specify a users command (list, create, delete, list-keys, add-key, remove-key)');
965
961
  return yargsUsers;
966
962
  });
967
963
  // --- Store Explorer Command ---
@@ -970,55 +966,36 @@ export function buildCli(options) {
970
966
  var element = storeCommand.explore();
971
967
  render(element);
972
968
  });
973
- // --- Auth Commands (Available in both local and global mode) ---
969
+ // --- Auth Commands (Top-level) ---
974
970
  var authCommand = new AuthCommand(undefined, projectRootPath);
975
- {
976
- cli = cli.command('auth', 'Manage authentication configuration\n', function(yargsAuth) {
977
- yargsAuth.command('status', 'Show current auth configuration\n', function() {}, function() {
978
- var element = authCommand.status();
979
- render(element);
980
- }).command('login', 'Configure SSH key for authentication\n', function(yargsLogin) {
981
- return yargsLogin.option('path', {
982
- describe: 'Path to SSH private key',
983
- type: 'string',
984
- alias: 'p'
985
- }).option('project', {
986
- describe: 'Set key for current project instead of global',
987
- type: 'boolean',
988
- default: false
989
- }).example('$0 auth login', 'Interactive key selection').example('$0 auth login --path ~/.ssh/id_ed25519', 'Set key directly').example('$0 auth login --project', 'Set key for current project');
990
- }, function(argv) {
991
- var element = authCommand.login(argv);
992
- render(element);
993
- }).command('logout', 'Clear SSH key configuration\n', function(yargsLogout) {
994
- return yargsLogout.option('project', {
995
- describe: 'Clear key for current project only',
996
- type: 'boolean',
997
- default: false
998
- }).example('$0 auth logout', 'Clear global key configuration').example('$0 auth logout --project', 'Clear project-specific key');
999
- }, function(argv) {
1000
- var element = authCommand.logout(argv);
1001
- render(element);
1002
- }).command('list', 'List available SSH keys\n', function() {}, function() {
1003
- var element = authCommand.list();
1004
- render(element);
1005
- }).command('format-jwk-key', 'Convert an SSH public key to JWK format for ROOT_PUBLIC_KEY\n', function(yargsFormatJwkKey) {
1006
- return yargsFormatJwkKey.option('pubkey', {
1007
- describe: 'Path to SSH public key file',
1008
- type: 'string',
1009
- alias: 'p'
1010
- }).example('$0 auth format-jwk-key', 'Interactive public key selection').example('$0 auth format-jwk-key --pubkey ~/.ssh/id_ed25519.pub', 'Convert specific key');
1011
- }, function(argv) {
1012
- var element = authCommand.formatJwkKey(argv);
1013
- render(element);
1014
- }).command('$0', false, function() {}, function() {
1015
- // Default to status when just 'px auth' is run
1016
- var element = authCommand.status();
1017
- render(element);
1018
- });
1019
- return yargsAuth;
1020
- });
1021
- }
971
+ cli = cli.command('login', 'Configure SSH key for authentication\n', function(yargsLogin) {
972
+ return yargsLogin.option('path', {
973
+ describe: 'Path to SSH private key',
974
+ type: 'string',
975
+ alias: 'p'
976
+ }).option('project', {
977
+ describe: 'Set key for current project instead of global',
978
+ type: 'boolean',
979
+ default: false
980
+ }).example('$0 login', 'Interactive key selection').example('$0 login --path ~/.ssh/id_ed25519', 'Set key directly').example('$0 login --project', 'Set key for current project');
981
+ }, function(argv) {
982
+ var element = authCommand.login(argv);
983
+ render(element);
984
+ });
985
+ cli = cli.command('logout', 'Clear SSH key configuration\n', function(yargsLogout) {
986
+ return yargsLogout.option('project', {
987
+ describe: 'Clear key for current project only',
988
+ type: 'boolean',
989
+ default: false
990
+ }).example('$0 logout', 'Clear global key configuration').example('$0 logout --project', 'Clear project-specific key');
991
+ }, function(argv) {
992
+ var element = authCommand.logout(argv);
993
+ render(element);
994
+ });
995
+ cli = cli.command('whoami', 'Show your current authenticated identity\n', function() {}, function() {
996
+ var element = authCommand.whoami();
997
+ render(element);
998
+ });
1022
999
  cli = cli.epilogue('For more information, visit https://positronic.sh');
1023
1000
  return cli;
1024
1001
  }
@@ -31,11 +31,9 @@ function _define_property(obj, key, value) {
31
31
  return obj;
32
32
  }
33
33
  import React from 'react';
34
- import { AuthStatus } from '../components/auth-status.js';
35
34
  import { AuthLogin } from '../components/auth-login.js';
36
35
  import { AuthLogout } from '../components/auth-logout.js';
37
- import { AuthList } from '../components/auth-list.js';
38
- import { AuthFormatJwkKey } from '../components/auth-format-jwk-key.js';
36
+ import { Whoami } from '../components/whoami.js';
39
37
  import { ProjectConfigManager } from './project-config-manager.js';
40
38
  export var AuthCommand = /*#__PURE__*/ function() {
41
39
  "use strict";
@@ -49,19 +47,7 @@ export var AuthCommand = /*#__PURE__*/ function() {
49
47
  _create_class(AuthCommand, [
50
48
  {
51
49
  /**
52
- * Handles the 'px auth' or 'px auth status' command.
53
- * Shows current auth configuration.
54
- */ key: "status",
55
- value: function status() {
56
- return React.createElement(AuthStatus, {
57
- configManager: this.configManager,
58
- projectRootPath: this.projectRootPath
59
- });
60
- }
61
- },
62
- {
63
- /**
64
- * Handles the 'px auth login' command.
50
+ * Handles the 'px login' command.
65
51
  * Configure SSH key for authentication.
66
52
  */ key: "login",
67
53
  value: function login(param) {
@@ -76,7 +62,7 @@ export var AuthCommand = /*#__PURE__*/ function() {
76
62
  },
77
63
  {
78
64
  /**
79
- * Handles the 'px auth logout' command.
65
+ * Handles the 'px logout' command.
80
66
  * Clear SSH key configuration.
81
67
  */ key: "logout",
82
68
  value: function logout(param) {
@@ -90,27 +76,15 @@ export var AuthCommand = /*#__PURE__*/ function() {
90
76
  },
91
77
  {
92
78
  /**
93
- * Handles the 'px auth list' command.
94
- * List available SSH keys.
95
- */ key: "list",
96
- value: function list() {
97
- return React.createElement(AuthList, {
79
+ * Handles the 'px whoami' command.
80
+ * Shows the current authenticated identity.
81
+ */ key: "whoami",
82
+ value: function whoami() {
83
+ return React.createElement(Whoami, {
98
84
  configManager: this.configManager,
99
85
  projectRootPath: this.projectRootPath
100
86
  });
101
87
  }
102
- },
103
- {
104
- /**
105
- * Handles the 'px auth format-jwk-key' command.
106
- * Convert an SSH public key to JWK format for ROOT_PUBLIC_KEY configuration.
107
- */ key: "formatJwkKey",
108
- value: function formatJwkKey(param) {
109
- var pubkey = param.pubkey;
110
- return React.createElement(AuthFormatJwkKey, {
111
- pubkeyPath: pubkey
112
- });
113
- }
114
88
  }
115
89
  ]);
116
90
  return AuthCommand;
@@ -48,39 +48,40 @@ export var UsersCommand = /*#__PURE__*/ function() {
48
48
  {
49
49
  key: "delete",
50
50
  value: function _delete(param) {
51
- var id = param.id, force = param.force;
51
+ var name = param.name, force = param.force;
52
52
  return React.createElement(UsersDelete, {
53
- userId: id,
53
+ userName: name,
54
54
  force: force
55
55
  });
56
56
  }
57
57
  },
58
58
  {
59
- key: "keysList",
60
- value: function keysList(param) {
61
- var id = param.id;
59
+ key: "listKeys",
60
+ value: function listKeys(param) {
61
+ var name = param.name;
62
62
  return React.createElement(UsersKeysList, {
63
- userId: id
63
+ userName: name
64
64
  });
65
65
  }
66
66
  },
67
67
  {
68
- key: "keysAdd",
69
- value: function keysAdd(param) {
70
- var id = param.id, pubkeyPath = param.pubkeyPath, label = param.label;
68
+ key: "addKey",
69
+ value: function addKey(param) {
70
+ var name = param.name, pubkeyPath = param.pubkeyPath, paste = param.paste, label = param.label;
71
71
  return React.createElement(UsersKeysAdd, {
72
- userId: id,
72
+ userName: name,
73
73
  pubkeyPath: pubkeyPath,
74
+ paste: paste,
74
75
  label: label
75
76
  });
76
77
  }
77
78
  },
78
79
  {
79
- key: "keysRemove",
80
- value: function keysRemove(param) {
81
- var id = param.id, fingerprint = param.fingerprint, force = param.force;
80
+ key: "removeKey",
81
+ value: function removeKey(param) {
82
+ var name = param.name, fingerprint = param.fingerprint, force = param.force;
82
83
  return React.createElement(UsersKeysRemove, {
83
- userId: id,
84
+ userName: name,
84
85
  fingerprint: fingerprint,
85
86
  force: force
86
87
  });
@@ -144,7 +144,7 @@ export var AuthLogin = function(param) {
144
144
  marginTop: 1
145
145
  }, /*#__PURE__*/ React.createElement(Text, {
146
146
  dimColor: true
147
- }, "Or specify a custom path with: px auth login --path /path/to/key")));
147
+ }, "Or specify a custom path with: px login --path /path/to/key")));
148
148
  }
149
149
  var items = discoveredKeys.map(function(key) {
150
150
  return {
@@ -235,7 +235,7 @@ export var ProjectAuthSetup = function(param) {
235
235
  marginTop: 1
236
236
  }, /*#__PURE__*/ React.createElement(Text, {
237
237
  dimColor: true
238
- }, "You can manually configure auth later with: px auth login")));
238
+ }, "You can manually configure auth later with: px login")));
239
239
  }
240
240
  return null;
241
241
  };
@@ -181,7 +181,7 @@ export var ScheduleList = function(param) {
181
181
  color: schedule.enabled ? 'green' : 'red'
182
182
  }, padRight(schedule.enabled ? 'Enabled' : 'Disabled', columns.status.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
183
183
  dimColor: true
184
- }, padRight(truncate(schedule.runAsUserId, columns.runAs.width), columns.runAs.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
184
+ }, padRight(truncate(schedule.runAsUserName, columns.runAs.width), columns.runAs.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
185
185
  dimColor: true
186
186
  }, padRight(truncate(schedule.timezone || 'UTC', columns.timezone.width), columns.timezone.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
187
187
  color: isOverdue ? 'red' : undefined
@@ -645,12 +645,12 @@ export var StoreExplorer = function() {
645
645
  color: "cyan"
646
646
  }, "Store: ", selectedBrain, " (", keys.length, " keys)")), keys.map(function(entry, i) {
647
647
  return /*#__PURE__*/ React.createElement(Box, {
648
- key: "".concat(entry.scope, "-").concat(entry.key, "-").concat(entry.userId || '')
648
+ key: "".concat(entry.scope, "-").concat(entry.key, "-").concat(entry.userName || '')
649
649
  }, /*#__PURE__*/ React.createElement(Text, {
650
650
  color: i === selectedIndex ? 'cyan' : undefined
651
651
  }, i === selectedIndex ? '> ' : ' ', entry.key, /*#__PURE__*/ React.createElement(Text, {
652
652
  dimColor: true
653
- }, ' ', "[", entry.scope, entry.userId ? ":".concat(entry.userId) : '', "] ", entry.size, "B")));
653
+ }, ' ', "[", entry.scope, entry.userName ? ":".concat(entry.userName) : '', "] ", entry.size, "B")));
654
654
  }), deleteMessage && /*#__PURE__*/ React.createElement(Box, {
655
655
  marginTop: 1
656
656
  }, /*#__PURE__*/ React.createElement(Text, {
@@ -281,13 +281,11 @@ export var UsersCreate = function(param) {
281
281
  flexDirection: "column"
282
282
  }, /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
283
283
  bold: true
284
- }, "Name:"), " ", data.name), /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
285
- bold: true
286
- }, "ID:"), " ", data.id)), /*#__PURE__*/ React.createElement(Box, {
284
+ }, "Name:"), " ", data.name)), /*#__PURE__*/ React.createElement(Box, {
287
285
  marginTop: 1
288
286
  }, /*#__PURE__*/ React.createElement(Text, {
289
287
  dimColor: true
290
- }, "Add a key with: px users keys add ", data.id, " ~/.ssh/id_rsa.pub")));
288
+ }, "Add a key with: px users add-key ", data.name, " ~/.ssh/id_ed25519.pub")));
291
289
  }
292
290
  return null;
293
291
  };
@@ -169,9 +169,9 @@ import { Box, Text, useInput, useApp } from 'ink';
169
169
  import { ErrorComponent } from './error.js';
170
170
  import { useApiDelete, useApiGet } from '../hooks/useApi.js';
171
171
  export var UsersDelete = function(param) {
172
- var userId = param.userId, force = param.force;
172
+ var userName = param.userName, force = param.force;
173
173
  var exit = useApp().exit;
174
- var _useApiGet = useApiGet("/users/".concat(userId)), user = _useApiGet.data, loadingUser = _useApiGet.loading, getUserError = _useApiGet.error;
174
+ var _useApiGet = useApiGet("/users/".concat(userName)), user = _useApiGet.data, loadingUser = _useApiGet.loading, getUserError = _useApiGet.error;
175
175
  var _useApiDelete = useApiDelete('user'), deleting = _useApiDelete.loading, deleteError = _useApiDelete.error, execute = _useApiDelete.execute;
176
176
  var _useState = _sliced_to_array(useState(force), 2), confirmed = _useState[0], setConfirmed = _useState[1];
177
177
  var _useState1 = _sliced_to_array(useState(false), 2), deleted = _useState1[0], setDeleted = _useState1[1];
@@ -196,7 +196,7 @@ export var UsersDelete = function(param) {
196
196
  ]);
197
197
  return [
198
198
  4,
199
- execute("/users/".concat(userId))
199
+ execute("/users/".concat(userName))
200
200
  ];
201
201
  case 2:
202
202
  _state.sent();
@@ -220,7 +220,7 @@ export var UsersDelete = function(param) {
220
220
  })();
221
221
  }, [
222
222
  execute,
223
- userId,
223
+ userName,
224
224
  deletionStarted
225
225
  ]);
226
226
  useEffect(function() {
@@ -259,7 +259,7 @@ export var UsersDelete = function(param) {
259
259
  if (!user) {
260
260
  return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, {
261
261
  color: "red"
262
- }, "User not found: ", userId));
262
+ }, "User not found: ", userName));
263
263
  }
264
264
  if (deleted) {
265
265
  return /*#__PURE__*/ React.createElement(Box, {
@@ -45,43 +45,83 @@ function _unsupported_iterable_to_array(o, minLen) {
45
45
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
46
46
  }
47
47
  import React, { useEffect, useState } from 'react';
48
- import { Box, Text } from 'ink';
48
+ import { Box, Text, useInput } from 'ink';
49
49
  import { ErrorComponent } from './error.js';
50
50
  import { useApiPost, useApiGet } from '../hooks/useApi.js';
51
- import { convertSSHPubKeyToJWK } from '../lib/ssh-key-utils.js';
51
+ import { convertSSHPubKeyToJWK, convertSSHPubKeyStringToJWK } from '../lib/ssh-key-utils.js';
52
52
  import { existsSync } from 'fs';
53
53
  import { homedir } from 'os';
54
54
  import { join } from 'path';
55
55
  export var UsersKeysAdd = function(param) {
56
- var userId = param.userId, pubkeyPath = param.pubkeyPath, label = param.label;
57
- var _useApiGet = useApiGet("/users/".concat(userId)), user = _useApiGet.data, loadingUser = _useApiGet.loading, userError = _useApiGet.error;
58
- var _useApiPost = useApiPost("/users/".concat(userId, "/keys")), data = _useApiPost.data, loading = _useApiPost.loading, error = _useApiPost.error, execute = _useApiPost.execute;
56
+ var userName = param.userName, pubkeyPath = param.pubkeyPath, paste = param.paste, label = param.label;
57
+ var _useApiGet = useApiGet("/users/".concat(userName)), user = _useApiGet.data, loadingUser = _useApiGet.loading, userError = _useApiGet.error;
58
+ var _useApiPost = useApiPost("/users/".concat(userName, "/keys")), data = _useApiPost.data, loading = _useApiPost.loading, error = _useApiPost.error, execute = _useApiPost.execute;
59
59
  var _useState = _sliced_to_array(useState(false), 2), added = _useState[0], setAdded = _useState[1];
60
60
  var _useState1 = _sliced_to_array(useState(null), 2), parseError = _useState1[0], setParseError = _useState1[1];
61
61
  var _useState2 = _sliced_to_array(useState(null), 2), keyInfo = _useState2[0], setKeyInfo = _useState2[1];
62
+ var _useState3 = _sliced_to_array(useState(paste && !pubkeyPath), 2), pasteMode = _useState3[0], setPasteMode = _useState3[1];
63
+ var _useState4 = _sliced_to_array(useState(''), 2), pastedKey = _useState4[0], setPastedKey = _useState4[1];
64
+ var _useState5 = _sliced_to_array(useState(false), 2), pasteSubmitted = _useState5[0], setPasteSubmitted = _useState5[1];
65
+ useInput(function(input, key) {
66
+ if (!pasteMode || pasteSubmitted) return;
67
+ if (key.return) {
68
+ setPasteSubmitted(true);
69
+ return;
70
+ }
71
+ if (key.backspace || key.delete) {
72
+ setPastedKey(function(prev) {
73
+ return prev.slice(0, -1);
74
+ });
75
+ return;
76
+ }
77
+ if (input) {
78
+ setPastedKey(function(prev) {
79
+ return prev + input;
80
+ });
81
+ }
82
+ }, {
83
+ isActive: pasteMode && !pasteSubmitted
84
+ });
62
85
  useEffect(function() {
63
- if (!added && user && !parseError) {
64
- // Resolve the path
86
+ if (!user || added || parseError) return;
87
+ if (pasteMode && !pasteSubmitted) return;
88
+ if (pasteMode && pasteSubmitted && pastedKey) {
89
+ try {
90
+ var _convertSSHPubKeyStringToJWK = convertSSHPubKeyStringToJWK(pastedKey.trim()), jwk = _convertSSHPubKeyStringToJWK.jwk, fingerprint = _convertSSHPubKeyStringToJWK.fingerprint, algorithm = _convertSSHPubKeyStringToJWK.algorithm;
91
+ setKeyInfo({
92
+ fingerprint: fingerprint,
93
+ algorithm: algorithm
94
+ });
95
+ execute({
96
+ jwk: jwk,
97
+ fingerprint: fingerprint,
98
+ label: label || ''
99
+ }).then(function() {
100
+ return setAdded(true);
101
+ }).catch(function() {});
102
+ } catch (err) {
103
+ setParseError(err.message || 'Failed to parse SSH public key');
104
+ }
105
+ return;
106
+ }
107
+ if (pubkeyPath) {
65
108
  var resolvedPath = pubkeyPath;
66
109
  if (resolvedPath.startsWith('~')) {
67
110
  resolvedPath = join(homedir(), resolvedPath.slice(1));
68
111
  }
69
- // Check if file exists
70
112
  if (!existsSync(resolvedPath)) {
71
113
  setParseError("Public key file not found: ".concat(resolvedPath));
72
114
  return;
73
115
  }
74
116
  try {
75
- // Convert SSH public key to JWK
76
- var _convertSSHPubKeyToJWK = convertSSHPubKeyToJWK(resolvedPath), jwk = _convertSSHPubKeyToJWK.jwk, fingerprint = _convertSSHPubKeyToJWK.fingerprint, algorithm = _convertSSHPubKeyToJWK.algorithm;
117
+ var _convertSSHPubKeyToJWK = convertSSHPubKeyToJWK(resolvedPath), jwk1 = _convertSSHPubKeyToJWK.jwk, fingerprint1 = _convertSSHPubKeyToJWK.fingerprint, algorithm1 = _convertSSHPubKeyToJWK.algorithm;
77
118
  setKeyInfo({
78
- fingerprint: fingerprint,
79
- algorithm: algorithm
119
+ fingerprint: fingerprint1,
120
+ algorithm: algorithm1
80
121
  });
81
- // Upload the key
82
122
  execute({
83
- jwk: jwk,
84
- fingerprint: fingerprint,
123
+ jwk: jwk1,
124
+ fingerprint: fingerprint1,
85
125
  label: label || ''
86
126
  }).then(function() {
87
127
  return setAdded(true);
@@ -96,7 +136,10 @@ export var UsersKeysAdd = function(param) {
96
136
  pubkeyPath,
97
137
  label,
98
138
  execute,
99
- parseError
139
+ parseError,
140
+ pasteMode,
141
+ pasteSubmitted,
142
+ pastedKey
100
143
  ]);
101
144
  if (userError) {
102
145
  return /*#__PURE__*/ React.createElement(ErrorComponent, {
@@ -127,7 +170,18 @@ export var UsersKeysAdd = function(param) {
127
170
  if (!user) {
128
171
  return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, {
129
172
  color: "red"
130
- }, "User not found: ", userId));
173
+ }, "User not found: ", userName));
174
+ }
175
+ if (pasteMode && !pasteSubmitted) {
176
+ return /*#__PURE__*/ React.createElement(Box, {
177
+ flexDirection: "column",
178
+ paddingTop: 1,
179
+ paddingBottom: 1
180
+ }, /*#__PURE__*/ React.createElement(Text, null, "Paste your SSH public key and press ", /*#__PURE__*/ React.createElement(Text, {
181
+ bold: true
182
+ }, "Enter"), ":"), /*#__PURE__*/ React.createElement(Box, {
183
+ marginTop: 1
184
+ }, /*#__PURE__*/ React.createElement(Text, null, pastedKey || '...')));
131
185
  }
132
186
  if (loading) {
133
187
  return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, null, 'Adding key to user "', user.name, '"...'));
@@ -39,9 +39,9 @@ var padRight = function(text, width) {
39
39
  return text + ' '.repeat(Math.max(0, width - text.length));
40
40
  };
41
41
  export var UsersKeysList = function(param) {
42
- var userId = param.userId;
43
- var _useApiGet = useApiGet("/users/".concat(userId)), user = _useApiGet.data, loadingUser = _useApiGet.loading, userError = _useApiGet.error;
44
- var _useApiGet1 = useApiGet("/users/".concat(userId, "/keys")), data = _useApiGet1.data, loading = _useApiGet1.loading, error = _useApiGet1.error;
42
+ var userName = param.userName;
43
+ var _useApiGet = useApiGet("/users/".concat(userName)), user = _useApiGet.data, loadingUser = _useApiGet.loading, userError = _useApiGet.error;
44
+ var _useApiGet1 = useApiGet("/users/".concat(userName, "/keys")), data = _useApiGet1.data, loading = _useApiGet1.loading, error = _useApiGet1.error;
45
45
  if (userError) {
46
46
  return /*#__PURE__*/ React.createElement(ErrorComponent, {
47
47
  error: userError
@@ -58,7 +58,7 @@ export var UsersKeysList = function(param) {
58
58
  if (!user) {
59
59
  return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, {
60
60
  color: "red"
61
- }, "User not found: ", userId));
61
+ }, "User not found: ", userName));
62
62
  }
63
63
  if (!data || data.keys.length === 0) {
64
64
  return /*#__PURE__*/ React.createElement(Box, {
@@ -67,7 +67,7 @@ export var UsersKeysList = function(param) {
67
67
  marginTop: 1
68
68
  }, /*#__PURE__*/ React.createElement(Text, {
69
69
  dimColor: true
70
- }, 'Tip: Add a key with "px users keys add ', userId, ' ~/.ssh/id_rsa.pub"')));
70
+ }, 'Tip: Add a key with "px users add-key ', userName, ' ~/.ssh/id_ed25519.pub"')));
71
71
  }
72
72
  var sortedKeys = _to_consumable_array(data.keys).sort(function(a, b) {
73
73
  return b.addedAt - a.addedAt;