@strapi/cloud-cli 5.0.0-rc.0 → 5.0.0-rc.10

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.mjs CHANGED
@@ -133,7 +133,7 @@ async function saveLocalConfig(data) {
133
133
  await fse.writeJson(configFilePath, data, { encoding: "utf8", spaces: 2, mode: 384 });
134
134
  }
135
135
  const name = "@strapi/cloud-cli";
136
- const version = "5.0.0-beta.17";
136
+ const version = "5.0.0-rc.9";
137
137
  const description = "Commands to interact with the Strapi Cloud";
138
138
  const keywords = [
139
139
  "strapi",
@@ -177,14 +177,14 @@ const scripts = {
177
177
  watch: "pack-up watch"
178
178
  };
179
179
  const dependencies = {
180
- "@strapi/utils": "5.0.0-beta.17",
181
- axios: "1.6.0",
180
+ "@strapi/utils": "workspace:*",
181
+ axios: "1.6.8",
182
182
  chalk: "4.1.2",
183
183
  "cli-progress": "3.12.0",
184
184
  commander: "8.3.0",
185
185
  eventsource: "2.0.2",
186
186
  "fast-safe-stringify": "2.1.1",
187
- "fs-extra": "10.0.0",
187
+ "fs-extra": "11.2.0",
188
188
  inquirer: "8.2.5",
189
189
  jsonwebtoken: "9.0.0",
190
190
  "jwks-rsa": "3.1.0",
@@ -202,8 +202,8 @@ const devDependencies = {
202
202
  "@types/cli-progress": "3.11.5",
203
203
  "@types/eventsource": "1.1.15",
204
204
  "@types/lodash": "^4.14.191",
205
- "eslint-config-custom": "5.0.0-beta.17",
206
- tsconfig: "5.0.0-beta.17"
205
+ "eslint-config-custom": "workspace:*",
206
+ tsconfig: "workspace:*"
207
207
  };
208
208
  const engines = {
209
209
  node: ">=18.0.0 <=20.x.x",
@@ -232,7 +232,7 @@ const packageJson = {
232
232
  engines
233
233
  };
234
234
  const VERSION = "v1";
235
- async function cloudApiFactory(token) {
235
+ async function cloudApiFactory({ logger }, token) {
236
236
  const localConfig = await getLocalConfig();
237
237
  const customHeaders = {
238
238
  "x-device-id": localConfig.deviceId,
@@ -285,8 +285,19 @@ async function cloudApiFactory(token) {
285
285
  getUserInfo() {
286
286
  return axiosCloudAPI.get("/user");
287
287
  },
288
- config() {
289
- return axiosCloudAPI.get("/config");
288
+ async config() {
289
+ try {
290
+ const response = await axiosCloudAPI.get("/config");
291
+ if (response.status !== 200) {
292
+ throw new Error("Error fetching cloud CLI config from the server.");
293
+ }
294
+ return response;
295
+ } catch (error) {
296
+ logger.debug(
297
+ "🥲 Oops! Couldn't retrieve the cloud CLI config from the server. Please try again."
298
+ );
299
+ throw error;
300
+ }
290
301
  },
291
302
  listProjects() {
292
303
  return axiosCloudAPI.get("/projects");
@@ -325,7 +336,7 @@ const strapiInfoSave = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defi
325
336
  }, Symbol.toStringTag, { value: "Module" }));
326
337
  let cliConfig;
327
338
  async function tokenServiceFactory({ logger }) {
328
- const cloudApiService = await cloudApiFactory();
339
+ const cloudApiService = await cloudApiFactory({ logger });
329
340
  async function saveToken(str) {
330
341
  const appConfig = await getLocalConfig();
331
342
  if (!appConfig) {
@@ -374,14 +385,17 @@ async function tokenServiceFactory({ logger }) {
374
385
  "There seems to be a problem with your login information. Please try logging in again."
375
386
  );
376
387
  }
388
+ return Promise.reject(new Error("Invalid token"));
377
389
  }
378
390
  return new Promise((resolve, reject) => {
379
391
  jwt.verify(idToken, getKey, (err) => {
380
392
  if (err) {
381
393
  reject(err);
382
- } else {
383
- resolve();
384
394
  }
395
+ if (decodedToken.payload.exp < Math.floor(Date.now() / 1e3)) {
396
+ reject(new Error("Token is expired"));
397
+ }
398
+ resolve();
385
399
  });
386
400
  });
387
401
  }
@@ -415,15 +429,15 @@ async function tokenServiceFactory({ logger }) {
415
429
  throw e;
416
430
  }
417
431
  }
418
- async function getValidToken() {
419
- const token = await retrieveToken();
420
- if (!token) {
421
- logger.log("No token found. Please login first.");
422
- return null;
423
- }
424
- if (!await isTokenValid(token)) {
425
- logger.log("Unable to proceed: Token is expired or not valid. Please login again.");
426
- return null;
432
+ async function getValidToken(ctx, loginAction2) {
433
+ let token = await retrieveToken();
434
+ while (!token || !await isTokenValid(token)) {
435
+ logger.log(
436
+ 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."
437
+ );
438
+ if (!await loginAction2(ctx))
439
+ return null;
440
+ token = await retrieveToken();
427
441
  }
428
442
  return token;
429
443
  }
@@ -557,17 +571,183 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
557
571
  local: strapiInfoSave,
558
572
  tokenServiceFactory
559
573
  }, Symbol.toStringTag, { value: "Module" }));
560
- async function handleError(ctx, error) {
574
+ const openModule$1 = import("open");
575
+ async function promptLogin(ctx) {
576
+ const response = await inquirer.prompt([
577
+ {
578
+ type: "confirm",
579
+ name: "login",
580
+ message: "Would you like to login?"
581
+ }
582
+ ]);
583
+ if (response.login) {
584
+ const loginSuccessful = await loginAction(ctx);
585
+ return loginSuccessful;
586
+ }
587
+ return false;
588
+ }
589
+ async function loginAction(ctx) {
590
+ const { logger } = ctx;
561
591
  const tokenService = await tokenServiceFactory(ctx);
592
+ const existingToken = await tokenService.retrieveToken();
593
+ const cloudApiService = await cloudApiFactory(ctx, existingToken || void 0);
594
+ const trackFailedLogin = async () => {
595
+ try {
596
+ await cloudApiService.track("didNotLogin", { loginMethod: "cli" });
597
+ } catch (e) {
598
+ logger.debug("Failed to track failed login", e);
599
+ }
600
+ };
601
+ if (existingToken) {
602
+ const isTokenValid = await tokenService.isTokenValid(existingToken);
603
+ if (isTokenValid) {
604
+ try {
605
+ const userInfo = await cloudApiService.getUserInfo();
606
+ const { email } = userInfo.data.data;
607
+ if (email) {
608
+ logger.log(`You are already logged into your account (${email}).`);
609
+ } else {
610
+ logger.log("You are already logged in.");
611
+ }
612
+ logger.log(
613
+ "To access your dashboard, please copy and paste the following URL into your web browser:"
614
+ );
615
+ logger.log(chalk.underline(`${apiConfig.dashboardBaseUrl}/projects`));
616
+ return true;
617
+ } catch (e) {
618
+ logger.debug("Failed to fetch user info", e);
619
+ }
620
+ }
621
+ }
622
+ let cliConfig2;
623
+ try {
624
+ logger.info("🔌 Connecting to the Strapi Cloud API...");
625
+ const config = await cloudApiService.config();
626
+ cliConfig2 = config.data;
627
+ } catch (e) {
628
+ logger.error("🥲 Oops! Something went wrong while logging you in. Please try again.");
629
+ logger.debug(e);
630
+ return false;
631
+ }
632
+ try {
633
+ await cloudApiService.track("willLoginAttempt", {});
634
+ } catch (e) {
635
+ logger.debug("Failed to track login attempt", e);
636
+ }
637
+ logger.debug("🔐 Creating device authentication request...", {
638
+ client_id: cliConfig2.clientId,
639
+ scope: cliConfig2.scope,
640
+ audience: cliConfig2.audience
641
+ });
642
+ const deviceAuthResponse = await axios.post(cliConfig2.deviceCodeAuthUrl, {
643
+ client_id: cliConfig2.clientId,
644
+ scope: cliConfig2.scope,
645
+ audience: cliConfig2.audience
646
+ }).catch((e) => {
647
+ logger.error("There was an issue with the authentication process. Please try again.");
648
+ if (e.message) {
649
+ logger.debug(e.message, e);
650
+ } else {
651
+ logger.debug(e);
652
+ }
653
+ });
654
+ openModule$1.then((open) => {
655
+ open.default(deviceAuthResponse.data.verification_uri_complete).catch((e) => {
656
+ logger.error("We encountered an issue opening the browser. Please try again later.");
657
+ logger.debug(e.message, e);
658
+ });
659
+ });
660
+ logger.log("If a browser tab does not open automatically, please follow the next steps:");
661
+ logger.log(
662
+ `1. Open this url in your device: ${deviceAuthResponse.data.verification_uri_complete}`
663
+ );
664
+ logger.log(
665
+ `2. Enter the following code: ${deviceAuthResponse.data.user_code} and confirm to login.
666
+ `
667
+ );
668
+ const tokenPayload = {
669
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
670
+ device_code: deviceAuthResponse.data.device_code,
671
+ client_id: cliConfig2.clientId
672
+ };
673
+ let isAuthenticated = false;
674
+ const authenticate = async () => {
675
+ const spinner = logger.spinner("Waiting for authentication");
676
+ spinner.start();
677
+ const spinnerFail = () => spinner.fail("Authentication failed!");
678
+ while (!isAuthenticated) {
679
+ try {
680
+ const tokenResponse = await axios.post(cliConfig2.tokenUrl, tokenPayload);
681
+ const authTokenData = tokenResponse.data;
682
+ if (tokenResponse.status === 200) {
683
+ try {
684
+ logger.debug("🔐 Validating token...");
685
+ await tokenService.validateToken(authTokenData.id_token, cliConfig2.jwksUrl);
686
+ logger.debug("🔐 Token validation successful!");
687
+ } catch (e) {
688
+ logger.debug(e);
689
+ spinnerFail();
690
+ throw new Error("Unable to proceed: Token validation failed");
691
+ }
692
+ logger.debug("🔍 Fetching user information...");
693
+ const cloudApiServiceWithToken = await cloudApiFactory(ctx, authTokenData.access_token);
694
+ await cloudApiServiceWithToken.getUserInfo();
695
+ logger.debug("🔍 User information fetched successfully!");
696
+ try {
697
+ logger.debug("📝 Saving login information...");
698
+ await tokenService.saveToken(authTokenData.access_token);
699
+ logger.debug("📝 Login information saved successfully!");
700
+ isAuthenticated = true;
701
+ } catch (e) {
702
+ logger.error(
703
+ "There was a problem saving your login information. Please try logging in again."
704
+ );
705
+ logger.debug(e);
706
+ spinnerFail();
707
+ return false;
708
+ }
709
+ }
710
+ } catch (e) {
711
+ if (e.message === "Unable to proceed: Token validation failed") {
712
+ logger.error(
713
+ "There seems to be a problem with your login information. Please try logging in again."
714
+ );
715
+ spinnerFail();
716
+ await trackFailedLogin();
717
+ return false;
718
+ }
719
+ if (e.response?.data.error && !["authorization_pending", "slow_down"].includes(e.response.data.error)) {
720
+ logger.debug(e);
721
+ spinnerFail();
722
+ await trackFailedLogin();
723
+ return false;
724
+ }
725
+ await new Promise((resolve) => {
726
+ setTimeout(resolve, deviceAuthResponse.data.interval * 1e3);
727
+ });
728
+ }
729
+ }
730
+ spinner.succeed("Authentication successful!");
731
+ logger.log("You are now logged into Strapi Cloud.");
732
+ logger.log(
733
+ "To access your dashboard, please copy and paste the following URL into your web browser:"
734
+ );
735
+ logger.log(chalk.underline(`${apiConfig.dashboardBaseUrl}/projects`));
736
+ try {
737
+ await cloudApiService.track("didLogin", { loginMethod: "cli" });
738
+ } catch (e) {
739
+ logger.debug("Failed to track login", e);
740
+ }
741
+ };
742
+ await authenticate();
743
+ return isAuthenticated;
744
+ }
745
+ async function handleError(ctx, error) {
562
746
  const { logger } = ctx;
563
747
  logger.debug(error);
564
748
  if (error instanceof AxiosError) {
565
749
  const errorMessage = typeof error.response?.data === "string" ? error.response.data : null;
566
750
  switch (error.response?.status) {
567
- case 401:
568
- logger.error("Your session has expired. Please log in again.");
569
- await tokenService.eraseToken();
570
- return;
571
751
  case 403:
572
752
  logger.error(
573
753
  errorMessage || "You do not have permission to create a project. Please contact support for assistance."
@@ -593,28 +773,44 @@ async function handleError(ctx, error) {
593
773
  "We encountered an issue while creating your project. Please try again in a moment. If the problem persists, contact support for assistance."
594
774
  );
595
775
  }
596
- const action$3 = async (ctx) => {
776
+ async function createProject$1(ctx, cloudApi, projectInput) {
597
777
  const { logger } = ctx;
598
- const { getValidToken } = await tokenServiceFactory(ctx);
599
- const token = await getValidToken();
778
+ const spinner = logger.spinner("Setting up your project...").start();
779
+ try {
780
+ const { data } = await cloudApi.createProject(projectInput);
781
+ await save({ project: data });
782
+ spinner.succeed("Project created successfully!");
783
+ return data;
784
+ } catch (e) {
785
+ spinner.fail("An error occurred while creating the project on Strapi Cloud.");
786
+ throw e;
787
+ }
788
+ }
789
+ const action$2 = async (ctx) => {
790
+ const { logger } = ctx;
791
+ const { getValidToken, eraseToken } = await tokenServiceFactory(ctx);
792
+ const token = await getValidToken(ctx, promptLogin);
600
793
  if (!token) {
601
794
  return;
602
795
  }
603
- const cloudApi = await cloudApiFactory(token);
796
+ const cloudApi = await cloudApiFactory(ctx, token);
604
797
  const { data: config } = await cloudApi.config();
605
798
  const { questions, defaults: defaultValues } = config.projectCreation;
606
799
  const projectAnswersDefaulted = defaults(defaultValues);
607
800
  const projectAnswers = await inquirer.prompt(questions);
608
801
  const projectInput = projectAnswersDefaulted(projectAnswers);
609
- const spinner = logger.spinner("Setting up your project...").start();
610
802
  try {
611
- const { data } = await cloudApi.createProject(projectInput);
612
- await save({ project: data });
613
- spinner.succeed("Project created successfully!");
614
- return data;
803
+ return await createProject$1(ctx, cloudApi, projectInput);
615
804
  } catch (e) {
616
- spinner.fail("Failed to create project on Strapi Cloud.");
617
- await handleError(ctx, e);
805
+ if (e instanceof AxiosError && e.response?.status === 401) {
806
+ logger.warn("Oops! Your session has expired. Please log in again to retry.");
807
+ await eraseToken();
808
+ if (await promptLogin(ctx)) {
809
+ return await createProject$1(ctx, cloudApi, projectInput);
810
+ }
811
+ } else {
812
+ await handleError(ctx, e);
813
+ }
618
814
  }
619
815
  };
620
816
  function notificationServiceFactory({ logger }) {
@@ -745,7 +941,7 @@ const buildLogsServiceFactory = ({ logger }) => {
745
941
  };
746
942
  };
747
943
  async function upload(ctx, project, token, maxProjectFileSize) {
748
- const cloudApi = await cloudApiFactory(token);
944
+ const cloudApi = await cloudApiFactory(ctx, token);
749
945
  try {
750
946
  const storagePath = await getTmpStoragePath();
751
947
  const projectFolder = path__default.resolve(process.cwd());
@@ -836,7 +1032,7 @@ async function getProject(ctx) {
836
1032
  const { project } = await retrieve();
837
1033
  if (!project) {
838
1034
  try {
839
- return await action$3(ctx);
1035
+ return await action$2(ctx);
840
1036
  } catch (e) {
841
1037
  ctx.logger.error("An error occurred while deploying the project. Please try again later.");
842
1038
  ctx.logger.debug(e);
@@ -845,10 +1041,9 @@ async function getProject(ctx) {
845
1041
  }
846
1042
  return project;
847
1043
  }
848
- const action$2 = async (ctx) => {
1044
+ const action$1 = async (ctx) => {
849
1045
  const { getValidToken } = await tokenServiceFactory(ctx);
850
- const cloudApiService = await cloudApiFactory();
851
- const token = await getValidToken();
1046
+ const token = await getValidToken(ctx, promptLogin);
852
1047
  if (!token) {
853
1048
  return;
854
1049
  }
@@ -856,6 +1051,7 @@ const action$2 = async (ctx) => {
856
1051
  if (!project) {
857
1052
  return;
858
1053
  }
1054
+ const cloudApiService = await cloudApiFactory(ctx);
859
1055
  try {
860
1056
  await cloudApiService.track("willDeployWithCLI", { projectInternalName: project.name });
861
1057
  } catch (e) {
@@ -920,183 +1116,27 @@ const runAction = (name2, action2) => (...args) => {
920
1116
  });
921
1117
  };
922
1118
  const command$3 = ({ ctx }) => {
923
- return 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));
1119
+ return 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));
924
1120
  };
925
1121
  const deployProject = {
926
1122
  name: "deploy-project",
927
1123
  description: "Deploy a Strapi Cloud project",
928
- action: action$2,
1124
+ action: action$1,
929
1125
  command: command$3
930
1126
  };
931
- const openModule = import("open");
932
- const action$1 = async (ctx) => {
933
- const { logger } = ctx;
934
- const tokenService = await tokenServiceFactory(ctx);
935
- const existingToken = await tokenService.retrieveToken();
936
- const cloudApiService = await cloudApiFactory(existingToken || void 0);
937
- const trackFailedLogin = async () => {
938
- try {
939
- await cloudApiService.track("didNotLogin", { loginMethod: "cli" });
940
- } catch (e) {
941
- logger.debug("Failed to track failed login", e);
942
- }
943
- };
944
- if (existingToken) {
945
- const isTokenValid = await tokenService.isTokenValid(existingToken);
946
- if (isTokenValid) {
947
- try {
948
- const userInfo = await cloudApiService.getUserInfo();
949
- const { email } = userInfo.data.data;
950
- if (email) {
951
- logger.log(`You are already logged into your account (${email}).`);
952
- } else {
953
- logger.log("You are already logged in.");
954
- }
955
- logger.log(
956
- "To access your dashboard, please copy and paste the following URL into your web browser:"
957
- );
958
- logger.log(chalk.underline(`${apiConfig.dashboardBaseUrl}/projects`));
959
- return true;
960
- } catch (e) {
961
- logger.debug("Failed to fetch user info", e);
962
- }
963
- }
964
- }
965
- let cliConfig2;
966
- try {
967
- logger.info("🔌 Connecting to the Strapi Cloud API...");
968
- const config = await cloudApiService.config();
969
- cliConfig2 = config.data;
970
- } catch (e) {
971
- logger.error("🥲 Oops! Something went wrong while logging you in. Please try again.");
972
- logger.debug(e);
973
- return false;
974
- }
975
- try {
976
- await cloudApiService.track("willLoginAttempt", {});
977
- } catch (e) {
978
- logger.debug("Failed to track login attempt", e);
979
- }
980
- logger.debug("🔐 Creating device authentication request...", {
981
- client_id: cliConfig2.clientId,
982
- scope: cliConfig2.scope,
983
- audience: cliConfig2.audience
984
- });
985
- const deviceAuthResponse = await axios.post(cliConfig2.deviceCodeAuthUrl, {
986
- client_id: cliConfig2.clientId,
987
- scope: cliConfig2.scope,
988
- audience: cliConfig2.audience
989
- }).catch((e) => {
990
- logger.error("There was an issue with the authentication process. Please try again.");
991
- if (e.message) {
992
- logger.debug(e.message, e);
993
- } else {
994
- logger.debug(e);
995
- }
996
- });
997
- openModule.then((open) => {
998
- open.default(deviceAuthResponse.data.verification_uri_complete).catch((e) => {
999
- logger.error("We encountered an issue opening the browser. Please try again later.");
1000
- logger.debug(e.message, e);
1001
- });
1002
- });
1003
- logger.log("If a browser tab does not open automatically, please follow the next steps:");
1004
- logger.log(
1005
- `1. Open this url in your device: ${deviceAuthResponse.data.verification_uri_complete}`
1006
- );
1007
- logger.log(
1008
- `2. Enter the following code: ${deviceAuthResponse.data.user_code} and confirm to login.
1009
- `
1010
- );
1011
- const tokenPayload = {
1012
- grant_type: "urn:ietf:params:oauth:grant-type:device_code",
1013
- device_code: deviceAuthResponse.data.device_code,
1014
- client_id: cliConfig2.clientId
1015
- };
1016
- let isAuthenticated = false;
1017
- const authenticate = async () => {
1018
- const spinner = logger.spinner("Waiting for authentication");
1019
- spinner.start();
1020
- const spinnerFail = () => spinner.fail("Authentication failed!");
1021
- while (!isAuthenticated) {
1022
- try {
1023
- const tokenResponse = await axios.post(cliConfig2.tokenUrl, tokenPayload);
1024
- const authTokenData = tokenResponse.data;
1025
- if (tokenResponse.status === 200) {
1026
- try {
1027
- logger.debug("🔐 Validating token...");
1028
- await tokenService.validateToken(authTokenData.id_token, cliConfig2.jwksUrl);
1029
- logger.debug("🔐 Token validation successful!");
1030
- } catch (e) {
1031
- logger.debug(e);
1032
- spinnerFail();
1033
- throw new Error("Unable to proceed: Token validation failed");
1034
- }
1035
- logger.debug("🔍 Fetching user information...");
1036
- const cloudApiServiceWithToken = await cloudApiFactory(authTokenData.access_token);
1037
- await cloudApiServiceWithToken.getUserInfo();
1038
- logger.debug("🔍 User information fetched successfully!");
1039
- try {
1040
- logger.debug("📝 Saving login information...");
1041
- await tokenService.saveToken(authTokenData.access_token);
1042
- logger.debug("📝 Login information saved successfully!");
1043
- isAuthenticated = true;
1044
- } catch (e) {
1045
- logger.error(
1046
- "There was a problem saving your login information. Please try logging in again."
1047
- );
1048
- logger.debug(e);
1049
- spinnerFail();
1050
- return false;
1051
- }
1052
- }
1053
- } catch (e) {
1054
- if (e.message === "Unable to proceed: Token validation failed") {
1055
- logger.error(
1056
- "There seems to be a problem with your login information. Please try logging in again."
1057
- );
1058
- spinnerFail();
1059
- await trackFailedLogin();
1060
- return false;
1061
- }
1062
- if (e.response?.data.error && !["authorization_pending", "slow_down"].includes(e.response.data.error)) {
1063
- logger.debug(e);
1064
- spinnerFail();
1065
- await trackFailedLogin();
1066
- return false;
1067
- }
1068
- await new Promise((resolve) => {
1069
- setTimeout(resolve, deviceAuthResponse.data.interval * 1e3);
1070
- });
1071
- }
1072
- }
1073
- spinner.succeed("Authentication successful!");
1074
- logger.log("You are now logged into Strapi Cloud.");
1075
- logger.log(
1076
- "To access your dashboard, please copy and paste the following URL into your web browser:"
1077
- );
1078
- logger.log(chalk.underline(`${apiConfig.dashboardBaseUrl}/projects`));
1079
- try {
1080
- await cloudApiService.track("didLogin", { loginMethod: "cli" });
1081
- } catch (e) {
1082
- logger.debug("Failed to track login", e);
1083
- }
1084
- };
1085
- await authenticate();
1086
- return isAuthenticated;
1087
- };
1088
1127
  const command$2 = ({ ctx }) => {
1089
1128
  return createCommand("cloud:login").alias("login").description("Strapi Cloud Login").addHelpText(
1090
1129
  "after",
1091
1130
  "\nAfter running this command, you will be prompted to enter your authentication information."
1092
- ).option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("login", action$1)(ctx));
1131
+ ).option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("login", loginAction)(ctx));
1093
1132
  };
1094
1133
  const login = {
1095
1134
  name: "login",
1096
1135
  description: "Strapi Cloud Login",
1097
- action: action$1,
1136
+ action: loginAction,
1098
1137
  command: command$2
1099
1138
  };
1139
+ const openModule = import("open");
1100
1140
  const action = async (ctx) => {
1101
1141
  const { logger } = ctx;
1102
1142
  const { retrieveToken, eraseToken } = await tokenServiceFactory(ctx);
@@ -1105,9 +1145,21 @@ const action = async (ctx) => {
1105
1145
  logger.log("You're already logged out.");
1106
1146
  return;
1107
1147
  }
1108
- const cloudApiService = await cloudApiFactory(token);
1148
+ const cloudApiService = await cloudApiFactory(ctx, token);
1149
+ const config = await cloudApiService.config();
1150
+ const cliConfig2 = config.data;
1109
1151
  try {
1110
1152
  await eraseToken();
1153
+ openModule.then((open) => {
1154
+ open.default(
1155
+ `${cliConfig2.baseUrl}/oidc/logout?client_id=${encodeURIComponent(
1156
+ cliConfig2.clientId
1157
+ )}&logout_hint=${encodeURIComponent(token)}
1158
+ `
1159
+ ).catch((e) => {
1160
+ logger.debug(e.message, e);
1161
+ });
1162
+ });
1111
1163
  logger.log(
1112
1164
  "🔌 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."
1113
1165
  );
@@ -1131,12 +1183,12 @@ const logout = {
1131
1183
  command: command$1
1132
1184
  };
1133
1185
  const command = ({ ctx }) => {
1134
- return 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));
1186
+ return 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));
1135
1187
  };
1136
1188
  const createProject = {
1137
1189
  name: "create-project",
1138
1190
  description: "Create a new project",
1139
- action: action$3,
1191
+ action: action$2,
1140
1192
  command
1141
1193
  };
1142
1194
  const cli = {