switch-profile 2.1.0 → 2.2.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 (3) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +24 -10
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -154,7 +154,7 @@ sp add # then choose "Accounts from an SSO portal"
154
154
  1. Pick an existing `[sso-session]` or create one: start URL (e.g. `https://acme.awsapps.com/start`), SSO region (where Identity Center lives, not where you deploy), and a short name, usually the client.
155
155
  2. Log in if needed.
156
156
  3. `switch-profile` lists every account and role you can access, then asks for a default region and a name prefix. Profiles are named `<prefix>-<account-name>-<role>`, for example `acme-prod-workloads-admin`.
157
- 4. A preview shows the new profiles, the ones already set up, and the ones that no longer exist. Confirm to write them.
157
+ 4. A preview shows the new profiles, the ones already set up, and the ones that no longer exist. Then pick the new profiles to add: all are selected, so press Enter to add everything, or untick the ones you don't want (type to search by name, account or role).
158
158
 
159
159
  Run it again later to pick up new accounts. Account/role pairs that already have a profile are never duplicated, whatever its name. Generated profiles that no longer exist can be pruned (after a backup); profiles you wrote by hand are never pruned.
160
160
 
package/dist/cli.js CHANGED
@@ -5351,7 +5351,7 @@ var require_package = __commonJS({
5351
5351
  "package.json"(exports2, module2) {
5352
5352
  module2.exports = {
5353
5353
  name: "switch-profile",
5354
- version: "2.1.0",
5354
+ version: "2.2.0",
5355
5355
  main: "index.js",
5356
5356
  bin: {
5357
5357
  "switch-profile": "index.js"
@@ -5396,7 +5396,7 @@ var require_package = __commonJS({
5396
5396
  eslint: "^10.0.0",
5397
5397
  fuzzysort: "^3.1.0",
5398
5398
  globals: "^17.13.0",
5399
- mocha: "^8.2.1",
5399
+ mocha: "^11.8.0",
5400
5400
  uqr: "^0.1.3"
5401
5401
  },
5402
5402
  files: [
@@ -5640,14 +5640,16 @@ var require_transforms = __commonJS({
5640
5640
  login_session: params.login_session || null
5641
5641
  };
5642
5642
  return p4.isSso = !!p4.sso_start_url, p4.isLegacySso = p4.isSso && !p4.sso_session, p4.kind = p4.isSso ? "sso" : p4.login_session ? "login" : p4.role_arn ? "role" : params.credential_process ? "process" : "keys", !p4.sso_account_id && p4.role_arn && (p4.sso_account_id = (p4.role_arn.match(/^arn:aws[^:]*:iam::(\d{12}):/) || [])[1] || null), p4;
5643
- }), slug = (text2) => String(text2 || "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, ""), generatedProfileName = (prefix, accountName, accountId, roleName) => [slug(prefix), slug(accountName) || accountId, slug(roleName)].filter(Boolean).join("-"), populateSsoProfiles = (configStr, { ssoSession, entries, region, prefix, prune, version }) => {
5644
- let config = configStr, profiles = listProfiles(config), session = ini.getSection(config, `sso-session ${ssoSession}`) || {}, samePortal = (p4) => p4.sso_session == ssoSession || p4.sso_start_url && p4.sso_start_url == session.sso_start_url, key = (accountId, roleName) => `${accountId}/${roleName}`, byKey = new Map(profiles.filter((p4) => p4.isSso && samePortal(p4)).map((p4) => [key(p4.sso_account_id, p4.sso_role_name), p4])), taken = new Set(profiles.map((p4) => p4.name)), wanted = new Set(entries.map((e) => key(e.accountId, e.roleName))), added = [], existing = [];
5643
+ }), slug = (text2) => String(text2 || "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, ""), generatedProfileName = (prefix, accountName, accountId, roleName) => [slug(prefix), slug(accountName) || accountId, slug(roleName)].filter(Boolean).join("-"), ssoEntryKey = (accountId, roleName) => `${accountId}/${roleName}`, populateSsoProfiles = (configStr, { ssoSession, entries, region, prefix, prune, include, version }) => {
5644
+ let config = configStr, profiles = listProfiles(config), session = ini.getSection(config, `sso-session ${ssoSession}`) || {}, samePortal = (p4) => p4.sso_session == ssoSession || p4.sso_start_url && p4.sso_start_url == session.sso_start_url, key = ssoEntryKey, included = include ? new Set(include) : null, byKey = new Map(profiles.filter((p4) => p4.isSso && samePortal(p4)).map((p4) => [key(p4.sso_account_id, p4.sso_role_name), p4])), taken = new Set(profiles.map((p4) => p4.name)), wanted = new Set(entries.map((e) => key(e.accountId, e.roleName))), added = [], addedEntries = [], existing = [];
5645
5645
  for (let e of entries) {
5646
5646
  let found = byKey.get(key(e.accountId, e.roleName));
5647
5647
  if (found) {
5648
5648
  existing.push(found.name);
5649
5649
  continue;
5650
5650
  }
5651
+ if (included && !included.has(key(e.accountId, e.roleName)))
5652
+ continue;
5651
5653
  let base = generatedProfileName(prefix || ssoSession, e.accountName, e.accountId, e.roleName), name = base;
5652
5654
  for (let i2 = 2; taken.has(name); i2++)
5653
5655
  name = `${base}-${i2}`;
@@ -5660,13 +5662,13 @@ var require_transforms = __commonJS({
5660
5662
  ...e.accountName ? [[ACCOUNT_NAME_KEY, e.accountName]] : [],
5661
5663
  [GENERATED_KEY, ssoSession],
5662
5664
  [VERSION_KEY, version]
5663
- ]), added.push(name);
5665
+ ]), added.push(name), addedEntries.push({ name, accountId: e.accountId, accountName: e.accountName, roleName: e.roleName });
5664
5666
  }
5665
5667
  let stale = profiles.filter((p4) => p4.generated == ssoSession && !wanted.has(key(p4.sso_account_id, p4.sso_role_name))).map((p4) => p4.name), removed = [];
5666
5668
  if (prune)
5667
5669
  for (let name of stale)
5668
5670
  config = ini.removeSection(config, configSectionName(config, name)), removed.push(name);
5669
- return { config, added, existing, stale, removed };
5671
+ return { config, added, addedEntries, existing, stale, removed };
5670
5672
  }, listSsoSessions = (configStr) => ini.listSections(configStr).filter((s) => s.startsWith("sso-session ")).map((s) => ({ name: s.replace(/^sso-session\s+/, ""), ...ini.getSection(configStr, s) })), addSsoSession = (configStr, { name, startUrl, region, version }) => ini.getSection(configStr, `sso-session ${name}`) ? configStr : ini.setSection(configStr, `sso-session ${name}`, [
5671
5673
  ["sso_start_url", startUrl],
5672
5674
  ["sso_region", region],
@@ -5678,6 +5680,7 @@ var require_transforms = __commonJS({
5678
5680
  ACCOUNT_NAME_KEY,
5679
5681
  generatedProfileName,
5680
5682
  populateSsoProfiles,
5683
+ ssoEntryKey,
5681
5684
  listSsoSessions,
5682
5685
  addSsoSession,
5683
5686
  NAME_KEY,
@@ -7902,14 +7905,25 @@ AWS recommends SSO or console sign-in instead.`), !await ask(p4.confirm({ messag
7902
7905
  ].filter(Boolean).join(`
7903
7906
  `);
7904
7907
  opts.json || p4.log.message(summary);
7905
- let prune = !!opts.prune;
7908
+ let prune = !!opts.prune, include;
7906
7909
  if (interactive && !opts.yes) {
7907
- if (preview.added.length && !await ask(p4.confirm({ message: `Add ${preview.added.length} profile${preview.added.length == 1 ? "" : "s"}?` })))
7908
- return p4.outro(ui2.dim("Nothing changed."));
7910
+ if (preview.added.length) {
7911
+ let all = preview.addedEntries.map((e) => transforms.ssoEntryKey(e.accountId, e.roleName)), picked = await ask(p4.autocompleteMultiselect({
7912
+ message: `Add which profiles? ${ui2.dim("(all selected: space to untick, type to search, enter to confirm)")}`,
7913
+ maxItems: 12,
7914
+ initialValues: all,
7915
+ options: preview.addedEntries.map((e, i2) => ({ value: all[i2], label: e.name, hint: [e.accountName, e.accountId, e.roleName].filter(Boolean).join(" \xB7 ") }))
7916
+ }));
7917
+ if (!picked.length && !preview.stale.length)
7918
+ return p4.outro(ui2.dim("Nothing changed."));
7919
+ picked.length < all.length && (include = picked);
7920
+ }
7909
7921
  preview.stale.length && (prune = await ask(p4.confirm({ message: `Remove the ${preview.stale.length} profile${preview.stale.length == 1 ? "" : "s"} that no longer exist${preview.stale.length == 1 ? "s" : ""}?`, initialValue: !1 })));
7910
7922
  }
7923
+ if (include && !include.length && !prune)
7924
+ return p4.outro(ui2.dim("Nothing changed."));
7911
7925
  prune && await aws.backupAwsFiles();
7912
- let result = transforms.populateSsoProfiles(configStr, { ssoSession: sessionName, entries, region, prefix, prune, version: settings2.CLI_VERSION });
7926
+ let result = transforms.populateSsoProfiles(configStr, { ssoSession: sessionName, entries, region, prefix, prune, include, version: settings2.CLI_VERSION });
7913
7927
  if (await aws.writeAwsFile(aws.AWS_CONFIG_FILE, result.config), await settings2.update({}), opts.json) {
7914
7928
  process.stdout.write(JSON.stringify({ added: result.added, existing: result.existing, removed: result.removed, stale: prune ? [] : result.stale }) + `
7915
7929
  `);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "switch-profile",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "main": "index.js",
5
5
  "bin": {
6
6
  "switch-profile": "index.js"
@@ -45,7 +45,7 @@
45
45
  "eslint": "^10.0.0",
46
46
  "fuzzysort": "^3.1.0",
47
47
  "globals": "^17.13.0",
48
- "mocha": "^8.2.1",
48
+ "mocha": "^11.8.0",
49
49
  "uqr": "^0.1.3"
50
50
  },
51
51
  "files": [