vercel 53.1.1 → 53.3.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 (73) hide show
  1. package/dist/chunks/{add-UAZIKU22.js → add-PGPQCMJK.js} +9 -9
  2. package/dist/chunks/{chunk-5B27ZNJB.js → chunk-25WI74GM.js} +7 -7
  3. package/dist/chunks/{chunk-C7FXVPAA.js → chunk-2TNGZL25.js} +2 -2
  4. package/dist/chunks/{chunk-T2DVW5BM.js → chunk-3GJFG6GX.js} +4 -4
  5. package/dist/chunks/{chunk-4Q5VS23S.js → chunk-3NSIZGHP.js} +3 -3
  6. package/dist/chunks/{chunk-QIHIANBF.js → chunk-3XU5UGVN.js} +1 -0
  7. package/dist/chunks/{chunk-NFAQ5Q3Z.js → chunk-3YDXZRSZ.js} +2 -2
  8. package/dist/chunks/{chunk-KFFW6MSL.js → chunk-4L73BR7G.js} +11 -12
  9. package/dist/chunks/{chunk-HMM7V4AU.js → chunk-4LDQIDKG.js} +2 -2
  10. package/dist/chunks/{chunk-4Z7KJQGN.js → chunk-4OEA5ILS.js} +0 -1
  11. package/dist/chunks/{chunk-WMD7Y6HT.js → chunk-4VJ3GTBX.js} +1 -1
  12. package/dist/chunks/{chunk-KOCX7HWE.js → chunk-7EJTBI6M.js} +11 -11
  13. package/dist/chunks/{chunk-VQSAZO3U.js → chunk-7Z5XFBB4.js} +140 -86
  14. package/dist/chunks/{chunk-5GMV7WTU.js → chunk-AAPG3P4D.js} +9 -11
  15. package/dist/chunks/{chunk-WS4HI35O.js → chunk-AORK3I3E.js} +1 -1
  16. package/dist/chunks/{chunk-IABMY4Q3.js → chunk-AXQNAI65.js} +1 -1
  17. package/dist/chunks/{chunk-XZ7CVBQ4.js → chunk-EBEBY45K.js} +11 -1
  18. package/dist/chunks/{chunk-LN5ZMLBU.js → chunk-GCKUEAUE.js} +2 -2
  19. package/dist/chunks/{chunk-JNOMOD7R.js → chunk-GQLARSTH.js} +1 -1
  20. package/dist/chunks/{chunk-JDKASMB2.js → chunk-H57DZL5B.js} +3 -3
  21. package/dist/chunks/{chunk-NCUOSZ6X.js → chunk-HAJ2XRTQ.js} +2 -2
  22. package/dist/chunks/{chunk-AES77UB7.js → chunk-HJVSVCAZ.js} +59 -14
  23. package/dist/chunks/{chunk-3LRN4Q7G.js → chunk-IS56OO2J.js} +3 -3
  24. package/dist/chunks/{chunk-SPXTKMOV.js → chunk-JJ36CB7A.js} +722 -938
  25. package/dist/chunks/{chunk-P3H4MP5H.js → chunk-JZLADLMF.js} +2 -2
  26. package/dist/chunks/{chunk-ABDTA3V2.js → chunk-KSIISCB2.js} +1 -1
  27. package/dist/chunks/{chunk-VS4O4MKY.js → chunk-MUBKPS2Z.js} +1 -1
  28. package/dist/chunks/{chunk-DFUTSURK.js → chunk-NF7HK5MP.js} +2 -2
  29. package/dist/chunks/{chunk-77JGNI4Z.js → chunk-NIOGCTVR.js} +2 -2
  30. package/dist/chunks/{chunk-5EDL2IVB.js → chunk-ONYQGA2O.js} +2 -2
  31. package/dist/chunks/{chunk-EYQEF55O.js → chunk-PR72OE3G.js} +4 -3
  32. package/dist/chunks/{chunk-IEKDY4FP.js → chunk-QGLS47RE.js} +1 -1
  33. package/dist/chunks/{chunk-BAAZFRLH.js → chunk-QV34LTI7.js} +420 -108
  34. package/dist/chunks/{chunk-YIK5Y7MI.js → chunk-RI23R2QO.js} +4 -4
  35. package/dist/chunks/{chunk-LDFOVKJS.js → chunk-RYUPBGRO.js} +34 -45
  36. package/dist/chunks/{chunk-3P3YBOCQ.js → chunk-SOSCFYOT.js} +2 -2
  37. package/dist/chunks/{chunk-JPVQD2PJ.js → chunk-TR6DYQV6.js} +1 -1
  38. package/dist/chunks/{chunk-JCLLQ23G.js → chunk-WOWCXMTU.js} +1 -1
  39. package/dist/chunks/{chunk-MSJX3VKI.js → chunk-X7KU44KR.js} +1 -1
  40. package/dist/chunks/{chunk-GDOCMDCB.js → chunk-XYYGNWMQ.js} +4 -4
  41. package/dist/chunks/{compile-vercel-config-BUURMPDD.js → compile-vercel-config-H4BUE5BZ.js} +5 -5
  42. package/dist/chunks/{delete-GBLJYO3T.js → delete-HVWVDBQF.js} +7 -7
  43. package/dist/chunks/{disable-QFE5TGWG.js → disable-CMBQPZ7L.js} +7 -7
  44. package/dist/chunks/{discard-IPPO7M2N.js → discard-ZDNWUYLY.js} +7 -7
  45. package/dist/chunks/{edit-KQD3MEZA.js → edit-YJYM3EKS.js} +9 -9
  46. package/dist/chunks/{enable-JBL4DMGJ.js → enable-ITE7U5C4.js} +7 -7
  47. package/dist/chunks/{export-KLWZUAYD.js → export-VVN33IBK.js} +7 -7
  48. package/dist/chunks/{inspect-TWW2XBDE.js → inspect-I7ILS3E2.js} +9 -9
  49. package/dist/chunks/{list-WJGLZ5ES.js → list-6PZO3UIZ.js} +7 -7
  50. package/dist/chunks/{list-UM77B7WK.js → list-BWIEHOTA.js} +10 -10
  51. package/dist/chunks/{ls-WVHDFPT3.js → ls-LZZFID76.js} +9 -9
  52. package/dist/chunks/{publish-45SAIZE4.js → publish-NULVZ7RB.js} +7 -7
  53. package/dist/chunks/{query-VH2TS6IS.js → query-BGI3AVJA.js} +9 -9
  54. package/dist/chunks/{reorder-NYENR2XY.js → reorder-G66QSKTR.js} +7 -7
  55. package/dist/chunks/{restore-H2VIG7KZ.js → restore-LHDVXFOH.js} +7 -7
  56. package/dist/chunks/{rm-RQEP4KMK.js → rm-DTAOTWXD.js} +9 -9
  57. package/dist/chunks/{routes-KDWN24QA.js → routes-2YVMQEPC.js} +2 -2
  58. package/dist/chunks/{rule-inspect-GR3RMO2J.js → rule-inspect-AOITFBTB.js} +9 -9
  59. package/dist/chunks/{rules-EOBQZE3T.js → rules-IW3XGCNA.js} +8 -8
  60. package/dist/chunks/{schema-OOGMY2SS.js → schema-2VCQ2MAA.js} +10 -10
  61. package/dist/chunks/{types-FAFL42RV.js → types-7VDI75PV.js} +4 -4
  62. package/dist/chunks/{update-VLOWX7UQ.js → update-L3DZ5STE.js} +9 -9
  63. package/dist/commands/build/index.js +21 -26
  64. package/dist/commands/deploy/index.js +87 -34
  65. package/dist/commands/dev/index.js +15 -15
  66. package/dist/commands/env/index.js +19 -19
  67. package/dist/commands/link/index.js +26 -22
  68. package/dist/commands/list/index.js +11 -11
  69. package/dist/commands-bulk.js +397 -214
  70. package/dist/help.js +1 -1
  71. package/dist/index.js +299 -49
  72. package/dist/version.mjs +1 -1
  73. package/package.json +27 -30
@@ -6,10 +6,10 @@ const __filename = __fileURLToPath(import.meta.url);
6
6
  const __dirname = __dirname_(__filename);
7
7
  import {
8
8
  getLocalPathConfig
9
- } from "./chunk-KFFW6MSL.js";
9
+ } from "./chunk-4L73BR7G.js";
10
10
  import {
11
11
  table
12
- } from "./chunk-ABDTA3V2.js";
12
+ } from "./chunk-KSIISCB2.js";
13
13
  import {
14
14
  VERCEL_DIR_PROJECT,
15
15
  VERCEL_DIR_README,
@@ -17,35 +17,40 @@ import {
17
17
  compileVercelConfig,
18
18
  createProject,
19
19
  detectProjects,
20
+ fetchProjectsForRepoUrl,
21
+ findProjectsFromPath,
22
+ findRepoRoot,
20
23
  findSourceVercelConfigFile,
21
24
  getLinkedProject,
22
25
  getProjectByNameOrId,
23
26
  getServicesConfigWriteBlocker,
24
27
  getTeams,
25
- getUser,
26
28
  getVercelDirectory,
27
29
  humanizePath,
28
30
  isDirectory,
29
31
  linkFolderToProject,
32
+ linkRepoProject,
30
33
  parseGitConfig,
31
34
  pluckRemoteUrls,
35
+ pull,
32
36
  readJSONFile,
33
37
  require_dist3 as require_dist,
34
38
  require_frameworks,
35
39
  require_lib,
36
40
  require_slugify,
41
+ resolveGitRemote,
37
42
  selectAndParseRemoteUrl,
38
43
  selectOrg,
39
44
  writeServicesConfig
40
- } from "./chunk-SPXTKMOV.js";
45
+ } from "./chunk-JJ36CB7A.js";
41
46
  import {
42
47
  printError
43
- } from "./chunk-JNOMOD7R.js";
48
+ } from "./chunk-GQLARSTH.js";
44
49
  import {
45
50
  CantParseJSONFile,
46
51
  ProjectNotFound,
47
52
  isAPIError
48
- } from "./chunk-XZ7CVBQ4.js";
53
+ } from "./chunk-EBEBY45K.js";
49
54
  import {
50
55
  output_manager_default
51
56
  } from "./chunk-ZQKJVHXY.js";
@@ -701,29 +706,63 @@ async function promptForInferredServicesSetup({
701
706
 
702
707
  // src/util/projects/search-project-across-teams.ts
703
708
  var import_slugify2 = __toESM(require_slugify(), 1);
704
- async function searchProjectAcrossTeams(client, projectName) {
705
- const [user, teams] = await Promise.all([getUser(client), getTeams(client)]);
706
- const orgs = [
707
- ...user.version === "northstar" ? [] : [{ type: "user", id: user.id, slug: user.username }],
708
- ...teams.map((t) => ({
709
- type: "team",
710
- id: t.id,
711
- slug: t.slug
712
- }))
713
- ];
709
+ import { relative as relative2 } from "path";
710
+ async function searchProjectAcrossTeams(client, projectName, cwd, {
711
+ autoConfirm = false,
712
+ nonInteractive = false,
713
+ teams,
714
+ skipLimited,
715
+ gitProjectName
716
+ } = {}) {
717
+ const teamsToSearch = teams ?? await getTeams(client);
718
+ const shouldSkipLimited = skipLimited ?? true;
719
+ const accessibleTeams = [];
720
+ const skippedTeams = [];
721
+ const skippedSlugs = [];
722
+ for (const t of teamsToSearch) {
723
+ if (shouldSkipLimited && t.limited) {
724
+ skippedTeams.push(t);
725
+ skippedSlugs.push(t.slug);
726
+ } else {
727
+ accessibleTeams.push(t);
728
+ }
729
+ }
730
+ if (skippedSlugs.length > 0) {
731
+ output_manager_default.debug(
732
+ `Skipping limited teams during cross-team project search: ${skippedSlugs.join(", ")}`
733
+ );
734
+ }
735
+ const searchedTeamSlugs = accessibleTeams.map((team) => team.slug);
736
+ const orgs = accessibleTeams.map((t) => ({
737
+ type: "team",
738
+ id: t.id,
739
+ slug: t.slug
740
+ }));
741
+ const repoMatchesPromise = searchProjectsByRepoRoot({
742
+ client,
743
+ cwd,
744
+ gitProjectName,
745
+ orgs,
746
+ autoConfirm,
747
+ nonInteractive
748
+ });
714
749
  const slugifiedName = (0, import_slugify2.default)(projectName);
715
750
  const searchNames = [projectName];
716
751
  if (slugifiedName !== projectName) {
717
752
  searchNames.push(slugifiedName);
718
753
  }
719
- const searchPromises = orgs.flatMap(
754
+ const folderNameSearchPromises = orgs.flatMap(
720
755
  (org) => searchNames.map(
721
756
  (name) => getProjectByNameOrId(client, name, org.id).then(
722
- (result) => result instanceof ProjectNotFound ? null : { project: result, org }
757
+ (result) => result instanceof ProjectNotFound ? null : { project: result, org, reason: "folder-name" }
723
758
  ).catch(() => null)
724
759
  )
725
760
  );
726
- const results = await Promise.all(searchPromises);
761
+ const [repoMatches, folderNameMatches] = await Promise.all([
762
+ repoMatchesPromise,
763
+ Promise.all(folderNameSearchPromises)
764
+ ]);
765
+ const results = [...repoMatches, ...folderNameMatches];
727
766
  const seen = /* @__PURE__ */ new Set();
728
767
  const matches = [];
729
768
  for (const r of results) {
@@ -732,23 +771,320 @@ async function searchProjectAcrossTeams(client, projectName) {
732
771
  matches.push(r);
733
772
  }
734
773
  }
735
- return matches;
774
+ return {
775
+ matches,
776
+ searchedTeamSlugs,
777
+ skippedLimitedTeamSlugs: skippedSlugs,
778
+ skippedLimitedTeams: skippedTeams
779
+ };
780
+ }
781
+ async function searchProjectsByRepoRoot({
782
+ client,
783
+ cwd,
784
+ gitProjectName,
785
+ orgs,
786
+ autoConfirm,
787
+ nonInteractive
788
+ }) {
789
+ const rootPath = await findRepoRoot(cwd);
790
+ if (!rootPath) {
791
+ return [];
792
+ }
793
+ let remote;
794
+ try {
795
+ remote = await resolveGitRemote(client, rootPath, {
796
+ yes: autoConfirm || nonInteractive
797
+ });
798
+ } catch (error) {
799
+ output_manager_default.debug(
800
+ `Failed to resolve Git remote for cross-team search: ${error}`
801
+ );
802
+ return [];
803
+ }
804
+ if (!remote) {
805
+ return [];
806
+ }
807
+ const relativePath = relative2(rootPath, cwd);
808
+ const results = await Promise.all(
809
+ orgs.map(async (org) => {
810
+ try {
811
+ const projects = await fetchProjectsForRepoUrl(
812
+ client,
813
+ remote.repoUrl,
814
+ org.id
815
+ );
816
+ const repoProjectConfigs = projects.filter(
817
+ (project) => !gitProjectName || project.id === gitProjectName || project.name === gitProjectName
818
+ ).map((project) => ({
819
+ id: project.id,
820
+ name: project.name,
821
+ directory: project.rootDirectory || ".",
822
+ orgId: org.id
823
+ }));
824
+ const matchingProjects = findProjectsFromPath(
825
+ repoProjectConfigs,
826
+ relativePath
827
+ );
828
+ return matchingProjects.map((match) => {
829
+ const project = projects.find((p) => p.id === match.id);
830
+ if (!project) {
831
+ return null;
832
+ }
833
+ return {
834
+ project,
835
+ org,
836
+ reason: "repo-root",
837
+ repo: {
838
+ ...remote,
839
+ directory: match.directory
840
+ }
841
+ };
842
+ }).filter(Boolean);
843
+ } catch (error) {
844
+ output_manager_default.debug(
845
+ `Failed to search Git-linked projects under ${org.slug}: ${error}`
846
+ );
847
+ return [];
848
+ }
849
+ })
850
+ );
851
+ return results.flat();
736
852
  }
737
853
 
738
854
  // src/util/link/setup-and-link.ts
855
+ function formatMatchReason(match) {
856
+ if (match.reason === "repo-root") {
857
+ return import_chalk6.default.gray("(linked by git)");
858
+ }
859
+ return import_chalk6.default.gray("(folder name)");
860
+ }
861
+ function formatCrossTeamMatch(match) {
862
+ return `${import_chalk6.default.blue(match.org.slug)}/${match.project.name} ${formatMatchReason(
863
+ match
864
+ )}`;
865
+ }
866
+ function formatTeamList(slugs) {
867
+ const shown = slugs.slice(0, 5);
868
+ const suffix = slugs.length > shown.length ? `, and ${slugs.length - shown.length} more` : "";
869
+ return `${shown.join(", ")}${suffix}`;
870
+ }
871
+ function printCrossTeamSearchScope({
872
+ searchedTeamSlugs,
873
+ skippedLimitedTeamSlugs
874
+ }) {
875
+ if (searchedTeamSlugs.length > 0) {
876
+ output_manager_default.log(`Searched teams: ${formatTeamList(searchedTeamSlugs)}`);
877
+ }
878
+ if (skippedLimitedTeamSlugs.length > 0) {
879
+ output_manager_default.log(
880
+ `Skipped ${skippedLimitedTeamSlugs.length} SSO-protected ${skippedLimitedTeamSlugs.length === 1 ? "team" : "teams"}`
881
+ );
882
+ }
883
+ }
884
+ async function maybePullEnvAfterLink(client, path2, autoConfirm, pullEnv) {
885
+ if (!pullEnv || !client.stdin.isTTY || client.nonInteractive) {
886
+ return;
887
+ }
888
+ const pullEnvConfirmed = autoConfirm || await client.input.confirm(
889
+ "Would you like to pull environment variables now?",
890
+ true
891
+ );
892
+ if (!pullEnvConfirmed) {
893
+ return;
894
+ }
895
+ const originalCwd = client.cwd;
896
+ try {
897
+ client.cwd = path2;
898
+ const args = autoConfirm ? ["--yes"] : [];
899
+ const exitCode = await pull(client, args, "vercel-cli:link");
900
+ if (exitCode !== 0) {
901
+ output_manager_default.error(
902
+ "Failed to pull environment variables. You can run `vc env pull` manually."
903
+ );
904
+ }
905
+ } catch (_error) {
906
+ output_manager_default.error(
907
+ "Failed to pull environment variables. You can run `vc env pull` manually."
908
+ );
909
+ } finally {
910
+ client.cwd = originalCwd;
911
+ }
912
+ }
913
+ async function linkCrossTeamMatch({
914
+ client,
915
+ path: path2,
916
+ match,
917
+ successEmoji,
918
+ autoConfirm,
919
+ pullEnv
920
+ }) {
921
+ client.config.currentTeam = match.org.type === "team" ? match.org.id : void 0;
922
+ if (match.reason === "repo-root" && match.repo) {
923
+ await linkRepoProject(client, path2, {
924
+ project: match.project,
925
+ orgId: match.org.id,
926
+ orgSlug: match.org.slug,
927
+ remoteName: match.repo.remoteName,
928
+ successEmoji
929
+ });
930
+ await maybePullEnvAfterLink(client, path2, autoConfirm, pullEnv);
931
+ return {
932
+ status: "linked",
933
+ org: match.org,
934
+ project: match.project,
935
+ repoRoot: match.repo.rootPath
936
+ };
937
+ }
938
+ await linkFolderToProject(
939
+ client,
940
+ path2,
941
+ { projectId: match.project.id, orgId: match.org.id },
942
+ match.project.name,
943
+ match.org.slug,
944
+ successEmoji,
945
+ autoConfirm,
946
+ pullEnv
947
+ );
948
+ return { status: "linked", org: match.org, project: match.project };
949
+ }
950
+ async function promptForLimitedTeams(client, teams) {
951
+ if (teams.length === 0) {
952
+ return [];
953
+ }
954
+ return await client.input.checkbox({
955
+ message: "Which SSO-protected teams should be searched?",
956
+ choices: teams.map((team) => ({
957
+ name: team.name ? `${team.name} (${team.slug})` : team.slug,
958
+ value: team
959
+ }))
960
+ });
961
+ }
962
+ async function searchSelectedLimitedTeams({
963
+ client,
964
+ path: path2,
965
+ projectName,
966
+ gitProjectName,
967
+ teams
968
+ }) {
969
+ const selectedTeams = await promptForLimitedTeams(client, teams);
970
+ if (selectedTeams.length === 0) {
971
+ return [];
972
+ }
973
+ output_manager_default.spinner("Searching selected SSO-protected teams\u2026", 1e3);
974
+ try {
975
+ const result = await searchProjectAcrossTeams(client, projectName, path2, {
976
+ teams: selectedTeams,
977
+ skipLimited: false,
978
+ gitProjectName
979
+ });
980
+ printCrossTeamSearchScope({
981
+ searchedTeamSlugs: result.searchedTeamSlugs,
982
+ skippedLimitedTeamSlugs: []
983
+ });
984
+ return result.matches;
985
+ } catch (err) {
986
+ output_manager_default.debug(`Selected SSO-protected team search failed: ${err}`);
987
+ return [];
988
+ } finally {
989
+ output_manager_default.stopSpinner();
990
+ }
991
+ }
992
+ async function linkCrossTeamMatches({
993
+ client,
994
+ path: path2,
995
+ matches,
996
+ successEmoji,
997
+ autoConfirm,
998
+ nonInteractive,
999
+ pullEnv
1000
+ }) {
1001
+ if (matches.length === 0) {
1002
+ return null;
1003
+ }
1004
+ if (matches.length === 1) {
1005
+ const match = matches[0];
1006
+ if (autoConfirm || nonInteractive) {
1007
+ return await linkCrossTeamMatch({
1008
+ client,
1009
+ path: path2,
1010
+ match,
1011
+ successEmoji,
1012
+ autoConfirm,
1013
+ pullEnv
1014
+ });
1015
+ }
1016
+ const confirmed = await client.input.confirm(
1017
+ `Found project ${formatCrossTeamMatch(match)}. Link to it?`,
1018
+ true
1019
+ );
1020
+ if (confirmed) {
1021
+ return await linkCrossTeamMatch({
1022
+ client,
1023
+ path: path2,
1024
+ match,
1025
+ successEmoji,
1026
+ autoConfirm,
1027
+ pullEnv
1028
+ });
1029
+ }
1030
+ return null;
1031
+ }
1032
+ const currentTeamMatch = matches.find(
1033
+ (match) => match.org.id === client.config.currentTeam
1034
+ );
1035
+ if (autoConfirm && currentTeamMatch) {
1036
+ return await linkCrossTeamMatch({
1037
+ client,
1038
+ path: path2,
1039
+ match: currentTeamMatch,
1040
+ successEmoji,
1041
+ autoConfirm,
1042
+ pullEnv
1043
+ });
1044
+ }
1045
+ if (nonInteractive) {
1046
+ return null;
1047
+ }
1048
+ const choices = matches.map((match) => ({
1049
+ name: formatCrossTeamMatch(match),
1050
+ value: match
1051
+ }));
1052
+ choices.push({
1053
+ name: "Not one of these projects",
1054
+ value: null
1055
+ });
1056
+ const selected = await client.input.select({
1057
+ message: "Found matching projects across teams. Which one do you want to link?",
1058
+ choices,
1059
+ default: currentTeamMatch ?? void 0
1060
+ });
1061
+ if (!selected) {
1062
+ return null;
1063
+ }
1064
+ return await linkCrossTeamMatch({
1065
+ client,
1066
+ path: path2,
1067
+ match: selected,
1068
+ successEmoji,
1069
+ autoConfirm,
1070
+ pullEnv
1071
+ });
1072
+ }
739
1073
  async function setupAndLink(client, path2, {
740
1074
  autoConfirm = false,
741
1075
  forceDelete = false,
742
1076
  link,
743
1077
  successEmoji = "link",
744
1078
  setupMsg = "Set up",
745
- projectName = basename(path2),
1079
+ projectName,
746
1080
  nonInteractive = false,
747
1081
  pullEnv = true,
748
1082
  v0,
749
1083
  searchAcrossTeams = false
750
1084
  }) {
751
1085
  const { config } = client;
1086
+ const gitProjectName = projectName;
1087
+ projectName = projectName ?? basename(path2);
752
1088
  if (!isDirectory(path2)) {
753
1089
  output_manager_default.error(`Expected directory but found file: ${path2}`);
754
1090
  return { status: "error", exitCode: 1, reason: "PATH_IS_FILE" };
@@ -783,105 +1119,81 @@ async function setupAndLink(client, path2, {
783
1119
  let skipAutoDetect = false;
784
1120
  if (searchAcrossTeams) {
785
1121
  let crossTeamMatches = [];
1122
+ let searchedTeamSlugs = [];
1123
+ let skippedLimitedTeamSlugs = [];
1124
+ let skippedLimitedTeams = [];
786
1125
  output_manager_default.spinner("Searching for existing projects\u2026", 1e3);
787
1126
  try {
788
- crossTeamMatches = await searchProjectAcrossTeams(client, projectName);
1127
+ const searchResult = await searchProjectAcrossTeams(
1128
+ client,
1129
+ projectName,
1130
+ path2,
1131
+ {
1132
+ autoConfirm,
1133
+ nonInteractive,
1134
+ gitProjectName
1135
+ }
1136
+ );
1137
+ crossTeamMatches = searchResult.matches;
1138
+ searchedTeamSlugs = searchResult.searchedTeamSlugs;
1139
+ skippedLimitedTeamSlugs = searchResult.skippedLimitedTeamSlugs;
1140
+ skippedLimitedTeams = searchResult.skippedLimitedTeams;
789
1141
  } catch (err) {
790
1142
  output_manager_default.debug(`Cross-team search failed: ${err}`);
791
1143
  } finally {
792
1144
  output_manager_default.stopSpinner();
793
1145
  }
794
- if (crossTeamMatches.length === 1) {
795
- const match = crossTeamMatches[0];
796
- if (autoConfirm || nonInteractive) {
797
- config.currentTeam = match.org.type === "team" ? match.org.id : void 0;
798
- await linkFolderToProject(
799
- client,
800
- path2,
801
- { projectId: match.project.id, orgId: match.org.id },
802
- match.project.name,
803
- match.org.slug,
804
- successEmoji,
805
- autoConfirm,
806
- pullEnv
1146
+ if (crossTeamMatches.length > 0 && !autoConfirm && !nonInteractive) {
1147
+ printCrossTeamSearchScope({
1148
+ searchedTeamSlugs,
1149
+ skippedLimitedTeamSlugs
1150
+ });
1151
+ }
1152
+ const linkedMatch = await linkCrossTeamMatches({
1153
+ client,
1154
+ path: path2,
1155
+ matches: crossTeamMatches,
1156
+ successEmoji,
1157
+ autoConfirm,
1158
+ nonInteractive,
1159
+ pullEnv
1160
+ });
1161
+ if (linkedMatch) {
1162
+ return linkedMatch;
1163
+ }
1164
+ if (!autoConfirm && !nonInteractive && skippedLimitedTeams.length > 0) {
1165
+ if (crossTeamMatches.length === 0) {
1166
+ output_manager_default.log(
1167
+ `No matching projects found in the ${searchedTeamSlugs.length} ${searchedTeamSlugs.length === 1 ? "team" : "teams"} available in your current session.`
807
1168
  );
808
- return { status: "linked", org: match.org, project: match.project };
809
1169
  }
810
- const confirmed = await client.input.confirm(
811
- `Found project ${import_chalk6.default.blue(match.org.slug)}/${match.project.name}. Link to it?`,
812
- true
813
- );
814
- if (confirmed) {
815
- config.currentTeam = match.org.type === "team" ? match.org.id : void 0;
816
- await linkFolderToProject(
817
- client,
818
- path2,
819
- { projectId: match.project.id, orgId: match.org.id },
820
- match.project.name,
821
- match.org.slug,
822
- successEmoji,
823
- autoConfirm,
824
- pullEnv
825
- );
826
- return { status: "linked", org: match.org, project: match.project };
1170
+ const limitedTeamMatches = await searchSelectedLimitedTeams({
1171
+ client,
1172
+ path: path2,
1173
+ projectName,
1174
+ gitProjectName,
1175
+ teams: skippedLimitedTeams
1176
+ });
1177
+ const linkedLimitedMatch = await linkCrossTeamMatches({
1178
+ client,
1179
+ path: path2,
1180
+ matches: limitedTeamMatches,
1181
+ successEmoji,
1182
+ autoConfirm,
1183
+ nonInteractive,
1184
+ pullEnv
1185
+ });
1186
+ if (linkedLimitedMatch) {
1187
+ return linkedLimitedMatch;
827
1188
  }
828
- skipAutoDetect = true;
829
- } else if (crossTeamMatches.length > 1) {
830
- const currentTeamMatch = autoConfirm ? crossTeamMatches.find((m) => m.org.id === config.currentTeam) : void 0;
831
- if (currentTeamMatch) {
832
- config.currentTeam = currentTeamMatch.org.type === "team" ? currentTeamMatch.org.id : void 0;
833
- await linkFolderToProject(
834
- client,
835
- path2,
836
- {
837
- projectId: currentTeamMatch.project.id,
838
- orgId: currentTeamMatch.org.id
839
- },
840
- currentTeamMatch.project.name,
841
- currentTeamMatch.org.slug,
842
- successEmoji,
843
- autoConfirm,
844
- pullEnv
1189
+ if (limitedTeamMatches.length === 0) {
1190
+ output_manager_default.log(
1191
+ "No matching projects found in the selected SSO-protected teams."
845
1192
  );
846
- return {
847
- status: "linked",
848
- org: currentTeamMatch.org,
849
- project: currentTeamMatch.project
850
- };
851
- }
852
- if (!nonInteractive) {
853
- const choices = crossTeamMatches.map((m) => ({
854
- name: `${import_chalk6.default.blue(m.org.slug)}/${m.project.name}`,
855
- value: m
856
- }));
857
- choices.push({
858
- name: "Don't link to an existing project",
859
- value: null
860
- });
861
- const selected = await client.input.select({
862
- message: "Found matching projects across teams. Which one do you want to link?",
863
- choices
864
- });
865
- if (selected) {
866
- config.currentTeam = selected.org.type === "team" ? selected.org.id : void 0;
867
- await linkFolderToProject(
868
- client,
869
- path2,
870
- { projectId: selected.project.id, orgId: selected.org.id },
871
- selected.project.name,
872
- selected.org.slug,
873
- successEmoji,
874
- autoConfirm,
875
- pullEnv
876
- );
877
- return {
878
- status: "linked",
879
- org: selected.org,
880
- project: selected.project
881
- };
882
- }
883
- skipAutoDetect = true;
884
1193
  }
1194
+ skipAutoDetect = skipAutoDetect || crossTeamMatches.length > 0 || limitedTeamMatches.length > 0;
1195
+ } else if (crossTeamMatches.length > 0) {
1196
+ skipAutoDetect = true;
885
1197
  }
886
1198
  }
887
1199
  try {
@@ -9,22 +9,22 @@ import {
9
9
  } from "./chunk-HTOH3MSD.js";
10
10
  import {
11
11
  getScope
12
- } from "./chunk-EYQEF55O.js";
12
+ } from "./chunk-PR72OE3G.js";
13
13
  import {
14
14
  AGENT_REASON
15
15
  } from "./chunk-E3NE4SKN.js";
16
16
  import {
17
17
  getLinkedProject,
18
18
  getProjectByNameOrId
19
- } from "./chunk-SPXTKMOV.js";
19
+ } from "./chunk-JJ36CB7A.js";
20
20
  import {
21
21
  buildCommandWithGlobalFlags,
22
22
  outputAgentError
23
- } from "./chunk-IABMY4Q3.js";
23
+ } from "./chunk-AXQNAI65.js";
24
24
  import {
25
25
  ProjectNotFound,
26
26
  isAPIError
27
- } from "./chunk-XZ7CVBQ4.js";
27
+ } from "./chunk-EBEBY45K.js";
28
28
 
29
29
  // src/commands/alerts/resolve-alerts-scope.ts
30
30
  function emitAlertsScopeError(client, jsonOutput, code, message, agent) {