@strapi/cloud-cli 5.0.0-rc.1 → 5.0.0-rc.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.
package/dist/index.js CHANGED
@@ -195,7 +195,7 @@ async function saveLocalConfig(data) {
195
195
  await fse__default.default.writeJson(configFilePath, data, { encoding: "utf8", spaces: 2, mode: 384 });
196
196
  }
197
197
  const name = "@strapi/cloud-cli";
198
- const version = "5.0.0-rc.0";
198
+ const version = "5.0.0-rc.2";
199
199
  const description = "Commands to interact with the Strapi Cloud";
200
200
  const keywords = [
201
201
  "strapi",
@@ -239,7 +239,7 @@ const scripts = {
239
239
  watch: "pack-up watch"
240
240
  };
241
241
  const dependencies = {
242
- "@strapi/utils": "5.0.0-rc.0",
242
+ "@strapi/utils": "5.0.0-rc.2",
243
243
  axios: "1.6.0",
244
244
  chalk: "4.1.2",
245
245
  "cli-progress": "3.12.0",
@@ -264,8 +264,8 @@ const devDependencies = {
264
264
  "@types/cli-progress": "3.11.5",
265
265
  "@types/eventsource": "1.1.15",
266
266
  "@types/lodash": "^4.14.191",
267
- "eslint-config-custom": "5.0.0-rc.0",
268
- tsconfig: "5.0.0-rc.0"
267
+ "eslint-config-custom": "5.0.0-rc.2",
268
+ tsconfig: "5.0.0-rc.2"
269
269
  };
270
270
  const engines = {
271
271
  node: ">=18.0.0 <=20.x.x",
@@ -294,7 +294,7 @@ const packageJson = {
294
294
  engines
295
295
  };
296
296
  const VERSION = "v1";
297
- async function cloudApiFactory(token) {
297
+ async function cloudApiFactory({ logger }, token) {
298
298
  const localConfig = await getLocalConfig();
299
299
  const customHeaders = {
300
300
  "x-device-id": localConfig.deviceId,
@@ -347,8 +347,19 @@ async function cloudApiFactory(token) {
347
347
  getUserInfo() {
348
348
  return axiosCloudAPI.get("/user");
349
349
  },
350
- config() {
351
- return axiosCloudAPI.get("/config");
350
+ async config() {
351
+ try {
352
+ const response = await axiosCloudAPI.get("/config");
353
+ if (response.status !== 200) {
354
+ throw new Error("Error fetching cloud CLI config from the server.");
355
+ }
356
+ return response;
357
+ } catch (error) {
358
+ logger.debug(
359
+ "🥲 Oops! Couldn't retrieve the cloud CLI config from the server. Please try again."
360
+ );
361
+ throw error;
362
+ }
352
363
  },
353
364
  listProjects() {
354
365
  return axiosCloudAPI.get("/projects");
@@ -387,7 +398,7 @@ const strapiInfoSave = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defi
387
398
  }, Symbol.toStringTag, { value: "Module" }));
388
399
  let cliConfig;
389
400
  async function tokenServiceFactory({ logger }) {
390
- const cloudApiService = await cloudApiFactory();
401
+ const cloudApiService = await cloudApiFactory({ logger });
391
402
  async function saveToken(str) {
392
403
  const appConfig = await getLocalConfig();
393
404
  if (!appConfig) {
@@ -436,14 +447,17 @@ async function tokenServiceFactory({ logger }) {
436
447
  "There seems to be a problem with your login information. Please try logging in again."
437
448
  );
438
449
  }
450
+ return Promise.reject(new Error("Invalid token"));
439
451
  }
440
452
  return new Promise((resolve, reject) => {
441
453
  jwt__default.default.verify(idToken, getKey, (err) => {
442
454
  if (err) {
443
455
  reject(err);
444
- } else {
445
- resolve();
446
456
  }
457
+ if (decodedToken.payload.exp < Math.floor(Date.now() / 1e3)) {
458
+ reject(new Error("Token is expired"));
459
+ }
460
+ resolve();
447
461
  });
448
462
  });
449
463
  }
@@ -477,15 +491,15 @@ async function tokenServiceFactory({ logger }) {
477
491
  throw e;
478
492
  }
479
493
  }
480
- async function getValidToken() {
481
- const token = await retrieveToken();
482
- if (!token) {
483
- logger.log("No token found. Please login first.");
484
- return null;
485
- }
486
- if (!await isTokenValid(token)) {
487
- logger.log("Unable to proceed: Token is expired or not valid. Please login again.");
488
- return null;
494
+ async function getValidToken(ctx, loginAction2) {
495
+ let token = await retrieveToken();
496
+ while (!token || !await isTokenValid(token)) {
497
+ logger.log(
498
+ token ? "Oops! Your token seems expired or invalid. Please login again." : "We couldn't find a valid token. You need to be logged in to use this feature."
499
+ );
500
+ if (!await loginAction2(ctx))
501
+ return null;
502
+ token = await retrieveToken();
489
503
  }
490
504
  return token;
491
505
  }
@@ -619,17 +633,183 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
619
633
  local: strapiInfoSave,
620
634
  tokenServiceFactory
621
635
  }, Symbol.toStringTag, { value: "Module" }));
622
- async function handleError(ctx, error) {
636
+ const openModule$1 = import("open");
637
+ async function promptLogin(ctx) {
638
+ const response = await inquirer__default.default.prompt([
639
+ {
640
+ type: "confirm",
641
+ name: "login",
642
+ message: "Would you like to login?"
643
+ }
644
+ ]);
645
+ if (response.login) {
646
+ const loginSuccessful = await loginAction(ctx);
647
+ return loginSuccessful;
648
+ }
649
+ return false;
650
+ }
651
+ async function loginAction(ctx) {
652
+ const { logger } = ctx;
623
653
  const tokenService = await tokenServiceFactory(ctx);
654
+ const existingToken = await tokenService.retrieveToken();
655
+ const cloudApiService = await cloudApiFactory(ctx, existingToken || void 0);
656
+ const trackFailedLogin = async () => {
657
+ try {
658
+ await cloudApiService.track("didNotLogin", { loginMethod: "cli" });
659
+ } catch (e) {
660
+ logger.debug("Failed to track failed login", e);
661
+ }
662
+ };
663
+ if (existingToken) {
664
+ const isTokenValid = await tokenService.isTokenValid(existingToken);
665
+ if (isTokenValid) {
666
+ try {
667
+ const userInfo = await cloudApiService.getUserInfo();
668
+ const { email } = userInfo.data.data;
669
+ if (email) {
670
+ logger.log(`You are already logged into your account (${email}).`);
671
+ } else {
672
+ logger.log("You are already logged in.");
673
+ }
674
+ logger.log(
675
+ "To access your dashboard, please copy and paste the following URL into your web browser:"
676
+ );
677
+ logger.log(chalk__default.default.underline(`${apiConfig.dashboardBaseUrl}/projects`));
678
+ return true;
679
+ } catch (e) {
680
+ logger.debug("Failed to fetch user info", e);
681
+ }
682
+ }
683
+ }
684
+ let cliConfig2;
685
+ try {
686
+ logger.info("🔌 Connecting to the Strapi Cloud API...");
687
+ const config = await cloudApiService.config();
688
+ cliConfig2 = config.data;
689
+ } catch (e) {
690
+ logger.error("🥲 Oops! Something went wrong while logging you in. Please try again.");
691
+ logger.debug(e);
692
+ return false;
693
+ }
694
+ try {
695
+ await cloudApiService.track("willLoginAttempt", {});
696
+ } catch (e) {
697
+ logger.debug("Failed to track login attempt", e);
698
+ }
699
+ logger.debug("🔐 Creating device authentication request...", {
700
+ client_id: cliConfig2.clientId,
701
+ scope: cliConfig2.scope,
702
+ audience: cliConfig2.audience
703
+ });
704
+ const deviceAuthResponse = await axios__default.default.post(cliConfig2.deviceCodeAuthUrl, {
705
+ client_id: cliConfig2.clientId,
706
+ scope: cliConfig2.scope,
707
+ audience: cliConfig2.audience
708
+ }).catch((e) => {
709
+ logger.error("There was an issue with the authentication process. Please try again.");
710
+ if (e.message) {
711
+ logger.debug(e.message, e);
712
+ } else {
713
+ logger.debug(e);
714
+ }
715
+ });
716
+ openModule$1.then((open) => {
717
+ open.default(deviceAuthResponse.data.verification_uri_complete).catch((e) => {
718
+ logger.error("We encountered an issue opening the browser. Please try again later.");
719
+ logger.debug(e.message, e);
720
+ });
721
+ });
722
+ logger.log("If a browser tab does not open automatically, please follow the next steps:");
723
+ logger.log(
724
+ `1. Open this url in your device: ${deviceAuthResponse.data.verification_uri_complete}`
725
+ );
726
+ logger.log(
727
+ `2. Enter the following code: ${deviceAuthResponse.data.user_code} and confirm to login.
728
+ `
729
+ );
730
+ const tokenPayload = {
731
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
732
+ device_code: deviceAuthResponse.data.device_code,
733
+ client_id: cliConfig2.clientId
734
+ };
735
+ let isAuthenticated = false;
736
+ const authenticate = async () => {
737
+ const spinner = logger.spinner("Waiting for authentication");
738
+ spinner.start();
739
+ const spinnerFail = () => spinner.fail("Authentication failed!");
740
+ while (!isAuthenticated) {
741
+ try {
742
+ const tokenResponse = await axios__default.default.post(cliConfig2.tokenUrl, tokenPayload);
743
+ const authTokenData = tokenResponse.data;
744
+ if (tokenResponse.status === 200) {
745
+ try {
746
+ logger.debug("🔐 Validating token...");
747
+ await tokenService.validateToken(authTokenData.id_token, cliConfig2.jwksUrl);
748
+ logger.debug("🔐 Token validation successful!");
749
+ } catch (e) {
750
+ logger.debug(e);
751
+ spinnerFail();
752
+ throw new Error("Unable to proceed: Token validation failed");
753
+ }
754
+ logger.debug("🔍 Fetching user information...");
755
+ const cloudApiServiceWithToken = await cloudApiFactory(ctx, authTokenData.access_token);
756
+ await cloudApiServiceWithToken.getUserInfo();
757
+ logger.debug("🔍 User information fetched successfully!");
758
+ try {
759
+ logger.debug("📝 Saving login information...");
760
+ await tokenService.saveToken(authTokenData.access_token);
761
+ logger.debug("📝 Login information saved successfully!");
762
+ isAuthenticated = true;
763
+ } catch (e) {
764
+ logger.error(
765
+ "There was a problem saving your login information. Please try logging in again."
766
+ );
767
+ logger.debug(e);
768
+ spinnerFail();
769
+ return false;
770
+ }
771
+ }
772
+ } catch (e) {
773
+ if (e.message === "Unable to proceed: Token validation failed") {
774
+ logger.error(
775
+ "There seems to be a problem with your login information. Please try logging in again."
776
+ );
777
+ spinnerFail();
778
+ await trackFailedLogin();
779
+ return false;
780
+ }
781
+ if (e.response?.data.error && !["authorization_pending", "slow_down"].includes(e.response.data.error)) {
782
+ logger.debug(e);
783
+ spinnerFail();
784
+ await trackFailedLogin();
785
+ return false;
786
+ }
787
+ await new Promise((resolve) => {
788
+ setTimeout(resolve, deviceAuthResponse.data.interval * 1e3);
789
+ });
790
+ }
791
+ }
792
+ spinner.succeed("Authentication successful!");
793
+ logger.log("You are now logged into Strapi Cloud.");
794
+ logger.log(
795
+ "To access your dashboard, please copy and paste the following URL into your web browser:"
796
+ );
797
+ logger.log(chalk__default.default.underline(`${apiConfig.dashboardBaseUrl}/projects`));
798
+ try {
799
+ await cloudApiService.track("didLogin", { loginMethod: "cli" });
800
+ } catch (e) {
801
+ logger.debug("Failed to track login", e);
802
+ }
803
+ };
804
+ await authenticate();
805
+ return isAuthenticated;
806
+ }
807
+ async function handleError(ctx, error) {
624
808
  const { logger } = ctx;
625
809
  logger.debug(error);
626
810
  if (error instanceof axios.AxiosError) {
627
811
  const errorMessage = typeof error.response?.data === "string" ? error.response.data : null;
628
812
  switch (error.response?.status) {
629
- case 401:
630
- logger.error("Your session has expired. Please log in again.");
631
- await tokenService.eraseToken();
632
- return;
633
813
  case 403:
634
814
  logger.error(
635
815
  errorMessage || "You do not have permission to create a project. Please contact support for assistance."
@@ -655,28 +835,44 @@ async function handleError(ctx, error) {
655
835
  "We encountered an issue while creating your project. Please try again in a moment. If the problem persists, contact support for assistance."
656
836
  );
657
837
  }
658
- const action$3 = async (ctx) => {
838
+ async function createProject$1(ctx, cloudApi, projectInput) {
659
839
  const { logger } = ctx;
660
- const { getValidToken } = await tokenServiceFactory(ctx);
661
- const token = await getValidToken();
840
+ const spinner = logger.spinner("Setting up your project...").start();
841
+ try {
842
+ const { data } = await cloudApi.createProject(projectInput);
843
+ await save({ project: data });
844
+ spinner.succeed("Project created successfully!");
845
+ return data;
846
+ } catch (e) {
847
+ spinner.fail("An error occurred while creating the project on Strapi Cloud.");
848
+ throw e;
849
+ }
850
+ }
851
+ const action$2 = async (ctx) => {
852
+ const { logger } = ctx;
853
+ const { getValidToken, eraseToken } = await tokenServiceFactory(ctx);
854
+ const token = await getValidToken(ctx, promptLogin);
662
855
  if (!token) {
663
856
  return;
664
857
  }
665
- const cloudApi = await cloudApiFactory(token);
858
+ const cloudApi = await cloudApiFactory(ctx, token);
666
859
  const { data: config } = await cloudApi.config();
667
860
  const { questions, defaults: defaultValues } = config.projectCreation;
668
861
  const projectAnswersDefaulted = fp.defaults(defaultValues);
669
862
  const projectAnswers = await inquirer__default.default.prompt(questions);
670
863
  const projectInput = projectAnswersDefaulted(projectAnswers);
671
- const spinner = logger.spinner("Setting up your project...").start();
672
864
  try {
673
- const { data } = await cloudApi.createProject(projectInput);
674
- await save({ project: data });
675
- spinner.succeed("Project created successfully!");
676
- return data;
865
+ return await createProject$1(ctx, cloudApi, projectInput);
677
866
  } catch (e) {
678
- spinner.fail("Failed to create project on Strapi Cloud.");
679
- await handleError(ctx, e);
867
+ if (e instanceof axios.AxiosError && e.response?.status === 401) {
868
+ logger.warn("Oops! Your session has expired. Please log in again to retry.");
869
+ await eraseToken();
870
+ if (await promptLogin(ctx)) {
871
+ return await createProject$1(ctx, cloudApi, projectInput);
872
+ }
873
+ } else {
874
+ await handleError(ctx, e);
875
+ }
680
876
  }
681
877
  };
682
878
  function notificationServiceFactory({ logger }) {
@@ -807,7 +1003,7 @@ const buildLogsServiceFactory = ({ logger }) => {
807
1003
  };
808
1004
  };
809
1005
  async function upload(ctx, project, token, maxProjectFileSize) {
810
- const cloudApi = await cloudApiFactory(token);
1006
+ const cloudApi = await cloudApiFactory(ctx, token);
811
1007
  try {
812
1008
  const storagePath = await getTmpStoragePath();
813
1009
  const projectFolder = path__namespace.default.resolve(process.cwd());
@@ -898,7 +1094,7 @@ async function getProject(ctx) {
898
1094
  const { project } = await retrieve();
899
1095
  if (!project) {
900
1096
  try {
901
- return await action$3(ctx);
1097
+ return await action$2(ctx);
902
1098
  } catch (e) {
903
1099
  ctx.logger.error("An error occurred while deploying the project. Please try again later.");
904
1100
  ctx.logger.debug(e);
@@ -907,10 +1103,9 @@ async function getProject(ctx) {
907
1103
  }
908
1104
  return project;
909
1105
  }
910
- const action$2 = async (ctx) => {
1106
+ const action$1 = async (ctx) => {
911
1107
  const { getValidToken } = await tokenServiceFactory(ctx);
912
- const cloudApiService = await cloudApiFactory();
913
- const token = await getValidToken();
1108
+ const token = await getValidToken(ctx, promptLogin);
914
1109
  if (!token) {
915
1110
  return;
916
1111
  }
@@ -918,6 +1113,7 @@ const action$2 = async (ctx) => {
918
1113
  if (!project) {
919
1114
  return;
920
1115
  }
1116
+ const cloudApiService = await cloudApiFactory(ctx);
921
1117
  try {
922
1118
  await cloudApiService.track("willDeployWithCLI", { projectInternalName: project.name });
923
1119
  } catch (e) {
@@ -982,183 +1178,27 @@ const runAction = (name2, action2) => (...args) => {
982
1178
  });
983
1179
  };
984
1180
  const command$3 = ({ ctx }) => {
985
- return commander.createCommand("cloud:deploy").alias("deploy").description("Deploy a Strapi Cloud project").option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("deploy", action$2)(ctx));
1181
+ return commander.createCommand("cloud:deploy").alias("deploy").description("Deploy a Strapi Cloud project").option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("deploy", action$1)(ctx));
986
1182
  };
987
1183
  const deployProject = {
988
1184
  name: "deploy-project",
989
1185
  description: "Deploy a Strapi Cloud project",
990
- action: action$2,
1186
+ action: action$1,
991
1187
  command: command$3
992
1188
  };
993
- const openModule = import("open");
994
- const action$1 = async (ctx) => {
995
- const { logger } = ctx;
996
- const tokenService = await tokenServiceFactory(ctx);
997
- const existingToken = await tokenService.retrieveToken();
998
- const cloudApiService = await cloudApiFactory(existingToken || void 0);
999
- const trackFailedLogin = async () => {
1000
- try {
1001
- await cloudApiService.track("didNotLogin", { loginMethod: "cli" });
1002
- } catch (e) {
1003
- logger.debug("Failed to track failed login", e);
1004
- }
1005
- };
1006
- if (existingToken) {
1007
- const isTokenValid = await tokenService.isTokenValid(existingToken);
1008
- if (isTokenValid) {
1009
- try {
1010
- const userInfo = await cloudApiService.getUserInfo();
1011
- const { email } = userInfo.data.data;
1012
- if (email) {
1013
- logger.log(`You are already logged into your account (${email}).`);
1014
- } else {
1015
- logger.log("You are already logged in.");
1016
- }
1017
- logger.log(
1018
- "To access your dashboard, please copy and paste the following URL into your web browser:"
1019
- );
1020
- logger.log(chalk__default.default.underline(`${apiConfig.dashboardBaseUrl}/projects`));
1021
- return true;
1022
- } catch (e) {
1023
- logger.debug("Failed to fetch user info", e);
1024
- }
1025
- }
1026
- }
1027
- let cliConfig2;
1028
- try {
1029
- logger.info("🔌 Connecting to the Strapi Cloud API...");
1030
- const config = await cloudApiService.config();
1031
- cliConfig2 = config.data;
1032
- } catch (e) {
1033
- logger.error("🥲 Oops! Something went wrong while logging you in. Please try again.");
1034
- logger.debug(e);
1035
- return false;
1036
- }
1037
- try {
1038
- await cloudApiService.track("willLoginAttempt", {});
1039
- } catch (e) {
1040
- logger.debug("Failed to track login attempt", e);
1041
- }
1042
- logger.debug("🔐 Creating device authentication request...", {
1043
- client_id: cliConfig2.clientId,
1044
- scope: cliConfig2.scope,
1045
- audience: cliConfig2.audience
1046
- });
1047
- const deviceAuthResponse = await axios__default.default.post(cliConfig2.deviceCodeAuthUrl, {
1048
- client_id: cliConfig2.clientId,
1049
- scope: cliConfig2.scope,
1050
- audience: cliConfig2.audience
1051
- }).catch((e) => {
1052
- logger.error("There was an issue with the authentication process. Please try again.");
1053
- if (e.message) {
1054
- logger.debug(e.message, e);
1055
- } else {
1056
- logger.debug(e);
1057
- }
1058
- });
1059
- openModule.then((open) => {
1060
- open.default(deviceAuthResponse.data.verification_uri_complete).catch((e) => {
1061
- logger.error("We encountered an issue opening the browser. Please try again later.");
1062
- logger.debug(e.message, e);
1063
- });
1064
- });
1065
- logger.log("If a browser tab does not open automatically, please follow the next steps:");
1066
- logger.log(
1067
- `1. Open this url in your device: ${deviceAuthResponse.data.verification_uri_complete}`
1068
- );
1069
- logger.log(
1070
- `2. Enter the following code: ${deviceAuthResponse.data.user_code} and confirm to login.
1071
- `
1072
- );
1073
- const tokenPayload = {
1074
- grant_type: "urn:ietf:params:oauth:grant-type:device_code",
1075
- device_code: deviceAuthResponse.data.device_code,
1076
- client_id: cliConfig2.clientId
1077
- };
1078
- let isAuthenticated = false;
1079
- const authenticate = async () => {
1080
- const spinner = logger.spinner("Waiting for authentication");
1081
- spinner.start();
1082
- const spinnerFail = () => spinner.fail("Authentication failed!");
1083
- while (!isAuthenticated) {
1084
- try {
1085
- const tokenResponse = await axios__default.default.post(cliConfig2.tokenUrl, tokenPayload);
1086
- const authTokenData = tokenResponse.data;
1087
- if (tokenResponse.status === 200) {
1088
- try {
1089
- logger.debug("🔐 Validating token...");
1090
- await tokenService.validateToken(authTokenData.id_token, cliConfig2.jwksUrl);
1091
- logger.debug("🔐 Token validation successful!");
1092
- } catch (e) {
1093
- logger.debug(e);
1094
- spinnerFail();
1095
- throw new Error("Unable to proceed: Token validation failed");
1096
- }
1097
- logger.debug("🔍 Fetching user information...");
1098
- const cloudApiServiceWithToken = await cloudApiFactory(authTokenData.access_token);
1099
- await cloudApiServiceWithToken.getUserInfo();
1100
- logger.debug("🔍 User information fetched successfully!");
1101
- try {
1102
- logger.debug("📝 Saving login information...");
1103
- await tokenService.saveToken(authTokenData.access_token);
1104
- logger.debug("📝 Login information saved successfully!");
1105
- isAuthenticated = true;
1106
- } catch (e) {
1107
- logger.error(
1108
- "There was a problem saving your login information. Please try logging in again."
1109
- );
1110
- logger.debug(e);
1111
- spinnerFail();
1112
- return false;
1113
- }
1114
- }
1115
- } catch (e) {
1116
- if (e.message === "Unable to proceed: Token validation failed") {
1117
- logger.error(
1118
- "There seems to be a problem with your login information. Please try logging in again."
1119
- );
1120
- spinnerFail();
1121
- await trackFailedLogin();
1122
- return false;
1123
- }
1124
- if (e.response?.data.error && !["authorization_pending", "slow_down"].includes(e.response.data.error)) {
1125
- logger.debug(e);
1126
- spinnerFail();
1127
- await trackFailedLogin();
1128
- return false;
1129
- }
1130
- await new Promise((resolve) => {
1131
- setTimeout(resolve, deviceAuthResponse.data.interval * 1e3);
1132
- });
1133
- }
1134
- }
1135
- spinner.succeed("Authentication successful!");
1136
- logger.log("You are now logged into Strapi Cloud.");
1137
- logger.log(
1138
- "To access your dashboard, please copy and paste the following URL into your web browser:"
1139
- );
1140
- logger.log(chalk__default.default.underline(`${apiConfig.dashboardBaseUrl}/projects`));
1141
- try {
1142
- await cloudApiService.track("didLogin", { loginMethod: "cli" });
1143
- } catch (e) {
1144
- logger.debug("Failed to track login", e);
1145
- }
1146
- };
1147
- await authenticate();
1148
- return isAuthenticated;
1149
- };
1150
1189
  const command$2 = ({ ctx }) => {
1151
1190
  return commander.createCommand("cloud:login").alias("login").description("Strapi Cloud Login").addHelpText(
1152
1191
  "after",
1153
1192
  "\nAfter running this command, you will be prompted to enter your authentication information."
1154
- ).option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("login", action$1)(ctx));
1193
+ ).option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("login", loginAction)(ctx));
1155
1194
  };
1156
1195
  const login = {
1157
1196
  name: "login",
1158
1197
  description: "Strapi Cloud Login",
1159
- action: action$1,
1198
+ action: loginAction,
1160
1199
  command: command$2
1161
1200
  };
1201
+ const openModule = import("open");
1162
1202
  const action = async (ctx) => {
1163
1203
  const { logger } = ctx;
1164
1204
  const { retrieveToken, eraseToken } = await tokenServiceFactory(ctx);
@@ -1167,9 +1207,21 @@ const action = async (ctx) => {
1167
1207
  logger.log("You're already logged out.");
1168
1208
  return;
1169
1209
  }
1170
- const cloudApiService = await cloudApiFactory(token);
1210
+ const cloudApiService = await cloudApiFactory(ctx, token);
1211
+ const config = await cloudApiService.config();
1212
+ const cliConfig2 = config.data;
1171
1213
  try {
1172
1214
  await eraseToken();
1215
+ openModule.then((open) => {
1216
+ open.default(
1217
+ `${cliConfig2.baseUrl}/oidc/logout?client_id=${encodeURIComponent(
1218
+ cliConfig2.clientId
1219
+ )}&logout_hint=${encodeURIComponent(token)}
1220
+ `
1221
+ ).catch((e) => {
1222
+ logger.debug(e.message, e);
1223
+ });
1224
+ });
1173
1225
  logger.log(
1174
1226
  "🔌 You have been logged out from the CLI. If you are on a shared computer, please make sure to log out from the Strapi Cloud Dashboard as well."
1175
1227
  );
@@ -1193,12 +1245,12 @@ const logout = {
1193
1245
  command: command$1
1194
1246
  };
1195
1247
  const command = ({ ctx }) => {
1196
- return commander.createCommand("cloud:create-project").description("Create a Strapi Cloud project").option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("cloud:create-project", action$3)(ctx));
1248
+ return commander.createCommand("cloud:create-project").description("Create a Strapi Cloud project").option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("cloud:create-project", action$2)(ctx));
1197
1249
  };
1198
1250
  const createProject = {
1199
1251
  name: "create-project",
1200
1252
  description: "Create a new project",
1201
- action: action$3,
1253
+ action: action$2,
1202
1254
  command
1203
1255
  };
1204
1256
  const cli = {