@strapi/cloud-cli 0.0.0-experimental.f77206734629a2b88793a7a8abca40388843c656 → 0.0.0-next.b11829e6c6aacb45bc1ec2f341609d04d88080d2

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
@@ -23,11 +23,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  ));
24
24
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
25
25
  const crypto$1 = require("crypto");
26
- const fs = require("fs");
26
+ const fse = require("fs-extra");
27
27
  const path = require("path");
28
+ const chalk = require("chalk");
28
29
  const axios = require("axios");
29
30
  const crypto = require("node:crypto");
30
31
  const utils = require("@strapi/utils");
32
+ const fs = require("fs");
31
33
  const tar = require("tar");
32
34
  const minimatch = require("minimatch");
33
35
  const inquirer = require("inquirer");
@@ -36,7 +38,6 @@ const os = require("os");
36
38
  const XDGAppPaths = require("xdg-app-paths");
37
39
  const jwksClient = require("jwks-rsa");
38
40
  const jwt = require("jsonwebtoken");
39
- const chalk = require("chalk");
40
41
  const stringify = require("fast-safe-stringify");
41
42
  const ora = require("ora");
42
43
  const cliProgress = require("cli-progress");
@@ -64,17 +65,18 @@ function _interopNamespace(e) {
64
65
  return Object.freeze(n);
65
66
  }
66
67
  const crypto__default = /* @__PURE__ */ _interopDefault(crypto$1);
67
- const fs__namespace = /* @__PURE__ */ _interopNamespace(fs);
68
+ const fse__default = /* @__PURE__ */ _interopDefault(fse);
68
69
  const path__namespace = /* @__PURE__ */ _interopNamespace(path);
70
+ const chalk__default = /* @__PURE__ */ _interopDefault(chalk);
69
71
  const axios__default = /* @__PURE__ */ _interopDefault(axios);
70
72
  const crypto__namespace = /* @__PURE__ */ _interopNamespace(crypto);
73
+ const fs__namespace = /* @__PURE__ */ _interopNamespace(fs);
71
74
  const tar__namespace = /* @__PURE__ */ _interopNamespace(tar);
72
75
  const inquirer__default = /* @__PURE__ */ _interopDefault(inquirer);
73
76
  const os__default = /* @__PURE__ */ _interopDefault(os);
74
77
  const XDGAppPaths__default = /* @__PURE__ */ _interopDefault(XDGAppPaths);
75
78
  const jwksClient__default = /* @__PURE__ */ _interopDefault(jwksClient);
76
79
  const jwt__default = /* @__PURE__ */ _interopDefault(jwt);
77
- const chalk__default = /* @__PURE__ */ _interopDefault(chalk);
78
80
  const stringify__default = /* @__PURE__ */ _interopDefault(stringify);
79
81
  const ora__default = /* @__PURE__ */ _interopDefault(ora);
80
82
  const cliProgress__namespace = /* @__PURE__ */ _interopNamespace(cliProgress);
@@ -83,7 +85,8 @@ const fs__default = /* @__PURE__ */ _interopDefault(fs$1);
83
85
  const pkgUp__default = /* @__PURE__ */ _interopDefault(pkgUp);
84
86
  const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
85
87
  const apiConfig = {
86
- apiBaseUrl: utils.env("STRAPI_CLI_CLOUD_API", "https://cli.cloud.strapi.io")
88
+ apiBaseUrl: utils.env("STRAPI_CLI_CLOUD_API", "https://cloud-cli-api.strapi.io"),
89
+ dashboardBaseUrl: utils.env("STRAPI_CLI_CLOUD_DASHBOARD", "https://cloud.strapi.io")
87
90
  };
88
91
  const IGNORED_PATTERNS = [
89
92
  "**/.git/**",
@@ -138,7 +141,7 @@ const readGitignore = (folderPath) => {
138
141
  if (!fs__namespace.existsSync(gitignorePath))
139
142
  return [];
140
143
  const gitignoreContent = fs__namespace.readFileSync(gitignorePath, "utf8");
141
- return gitignoreContent.split("\n").filter((line) => Boolean(line.trim()) && !line.startsWith("#"));
144
+ return gitignoreContent.split(/\r?\n/).filter((line) => Boolean(line.trim()) && !line.startsWith("#"));
142
145
  };
143
146
  const compressFilesToTar = async (storagePath, folderToCompress, filename) => {
144
147
  const ignorePatterns = readGitignore(folderToCompress);
@@ -153,48 +156,45 @@ const compressFilesToTar = async (storagePath, folderToCompress, filename) => {
153
156
  };
154
157
  const APP_FOLDER_NAME = "com.strapi.cli";
155
158
  const CONFIG_FILENAME = "config.json";
156
- function checkDirectoryExists(directoryPath) {
159
+ async function checkDirectoryExists(directoryPath) {
157
160
  try {
158
- return fs__namespace.default.lstatSync(directoryPath).isDirectory();
161
+ const fsStat = await fse__default.default.lstat(directoryPath);
162
+ return fsStat.isDirectory();
159
163
  } catch (e) {
160
164
  return false;
161
165
  }
162
166
  }
163
- function getTmpStoragePath() {
167
+ async function getTmpStoragePath() {
164
168
  const storagePath = path__namespace.default.join(os__default.default.tmpdir(), APP_FOLDER_NAME);
165
- if (!checkDirectoryExists(storagePath)) {
166
- fs__namespace.default.mkdirSync(storagePath, { recursive: true });
167
- }
169
+ await fse__default.default.ensureDir(storagePath);
168
170
  return storagePath;
169
171
  }
170
- function getConfigPath() {
172
+ async function getConfigPath() {
171
173
  const configDirs = XDGAppPaths__default.default(APP_FOLDER_NAME).configDirs();
172
174
  const configPath = configDirs.find(checkDirectoryExists);
173
175
  if (!configPath) {
174
- fs__namespace.default.mkdirSync(configDirs[0], { recursive: true });
176
+ await fse__default.default.ensureDir(configDirs[0]);
175
177
  return configDirs[0];
176
178
  }
177
179
  return configPath;
178
180
  }
179
- function getLocalConfig() {
180
- const configPath = getConfigPath();
181
+ async function getLocalConfig() {
182
+ const configPath = await getConfigPath();
181
183
  const configFilePath = path__namespace.default.join(configPath, CONFIG_FILENAME);
182
- if (!fs__namespace.default.existsSync(configFilePath)) {
183
- return {};
184
- }
184
+ await fse__default.default.ensureFile(configFilePath);
185
185
  try {
186
- return JSON.parse(fs__namespace.default.readFileSync(configFilePath, "utf8"));
186
+ return await fse__default.default.readJSON(configFilePath, { encoding: "utf8", throws: true });
187
187
  } catch (e) {
188
188
  return {};
189
189
  }
190
190
  }
191
- function saveLocalConfig(data) {
192
- const configPath = getConfigPath();
191
+ async function saveLocalConfig(data) {
192
+ const configPath = await getConfigPath();
193
193
  const configFilePath = path__namespace.default.join(configPath, CONFIG_FILENAME);
194
- fs__namespace.default.writeFileSync(configFilePath, JSON.stringify(data), { encoding: "utf8", mode: 384 });
194
+ await fse__default.default.writeJson(configFilePath, data, { encoding: "utf8", spaces: 2, mode: 384 });
195
195
  }
196
196
  const name = "@strapi/cloud-cli";
197
- const version = "4.24.3";
197
+ const version = "4.25.0";
198
198
  const description = "Commands to interact with the Strapi Cloud";
199
199
  const keywords = [
200
200
  "strapi",
@@ -238,13 +238,14 @@ const scripts = {
238
238
  watch: "pack-up watch"
239
239
  };
240
240
  const dependencies = {
241
- "@strapi/utils": "4.24.3",
241
+ "@strapi/utils": "4.25.0",
242
242
  axios: "1.6.0",
243
243
  chalk: "4.1.2",
244
244
  "cli-progress": "3.12.0",
245
245
  commander: "8.3.0",
246
246
  eventsource: "2.0.2",
247
247
  "fast-safe-stringify": "2.1.1",
248
+ "fs-extra": "10.0.0",
248
249
  inquirer: "8.2.5",
249
250
  jsonwebtoken: "9.0.0",
250
251
  "jwks-rsa": "3.1.0",
@@ -262,8 +263,8 @@ const devDependencies = {
262
263
  "@types/cli-progress": "3.11.5",
263
264
  "@types/eventsource": "1.1.15",
264
265
  "@types/lodash": "^4.14.191",
265
- "eslint-config-custom": "4.24.3",
266
- tsconfig: "4.24.3"
266
+ "eslint-config-custom": "4.25.0",
267
+ tsconfig: "4.25.0"
267
268
  };
268
269
  const engines = {
269
270
  node: ">=18.0.0 <=20.x.x",
@@ -292,8 +293,8 @@ const packageJson = {
292
293
  engines
293
294
  };
294
295
  const VERSION = "v1";
295
- function cloudApiFactory(token) {
296
- const localConfig = getLocalConfig();
296
+ async function cloudApiFactory(token) {
297
+ const localConfig = await getLocalConfig();
297
298
  const customHeaders = {
298
299
  "x-device-id": localConfig.deviceId,
299
300
  "x-app-version": packageJson.version,
@@ -316,7 +317,7 @@ function cloudApiFactory(token) {
316
317
  deploy({ filePath, project }, { onUploadProgress }) {
317
318
  return axiosCloudAPI.post(
318
319
  `/deploy/${project.name}`,
319
- { file: fs__namespace.createReadStream(filePath) },
320
+ { file: fse__default.default.createReadStream(filePath) },
320
321
  {
321
322
  headers: {
322
323
  "Content-Type": "multipart/form-data"
@@ -360,53 +361,48 @@ function cloudApiFactory(token) {
360
361
  };
361
362
  }
362
363
  const LOCAL_SAVE_FILENAME = ".strapi-cloud.json";
363
- function save(data, { directoryPath } = {}) {
364
- const storedData = { ...retrieve(), ...data };
364
+ async function save(data, { directoryPath } = {}) {
365
+ const alreadyInFileData = await retrieve({ directoryPath });
366
+ const storedData = { ...alreadyInFileData, ...data };
365
367
  const pathToFile = path__namespace.default.join(directoryPath || process.cwd(), LOCAL_SAVE_FILENAME);
366
- if (!fs__namespace.default.existsSync(path__namespace.default.dirname(pathToFile))) {
367
- fs__namespace.default.mkdirSync(path__namespace.default.dirname(pathToFile), { recursive: true });
368
- }
369
- fs__namespace.default.writeFileSync(pathToFile, JSON.stringify(storedData), "utf8");
368
+ await fse__default.default.ensureDir(path__namespace.default.dirname(pathToFile));
369
+ await fse__default.default.writeJson(pathToFile, storedData, { encoding: "utf8" });
370
370
  }
371
- function retrieve({ directoryPath } = {}) {
371
+ async function retrieve({
372
+ directoryPath
373
+ } = {}) {
372
374
  const pathToFile = path__namespace.default.join(directoryPath || process.cwd(), LOCAL_SAVE_FILENAME);
373
- if (!fs__namespace.default.existsSync(pathToFile)) {
375
+ const pathExists = await fse__default.default.pathExists(pathToFile);
376
+ if (!pathExists) {
374
377
  return {};
375
378
  }
376
- return JSON.parse(fs__namespace.default.readFileSync(pathToFile, "utf8"));
377
- }
378
- function erase({ directoryPath } = {}) {
379
- const pathToFile = path__namespace.default.join(directoryPath || process.cwd(), LOCAL_SAVE_FILENAME);
380
- if (fs__namespace.default.existsSync(pathToFile)) {
381
- fs__namespace.default.unlinkSync(pathToFile);
382
- }
379
+ return fse__default.default.readJSON(pathToFile, { encoding: "utf8" });
383
380
  }
384
381
  const strapiInfoSave = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
385
382
  __proto__: null,
386
383
  LOCAL_SAVE_FILENAME,
387
- erase,
388
384
  retrieve,
389
385
  save
390
386
  }, Symbol.toStringTag, { value: "Module" }));
391
- const cloudApiService = cloudApiFactory();
392
387
  let cliConfig;
393
- function tokenServiceFactory({ logger }) {
394
- function saveToken(str) {
395
- const appConfig = getLocalConfig();
388
+ async function tokenServiceFactory({ logger }) {
389
+ const cloudApiService = await cloudApiFactory();
390
+ async function saveToken(str) {
391
+ const appConfig = await getLocalConfig();
396
392
  if (!appConfig) {
397
393
  logger.error("There was a problem saving your token. Please try again.");
398
394
  return;
399
395
  }
400
396
  appConfig.token = str;
401
397
  try {
402
- saveLocalConfig(appConfig);
403
- } catch (error) {
404
- logger.debug(error);
398
+ await saveLocalConfig(appConfig);
399
+ } catch (e) {
400
+ logger.debug(e);
405
401
  logger.error("There was a problem saving your token. Please try again.");
406
402
  }
407
403
  }
408
404
  async function retrieveToken() {
409
- const appConfig = getLocalConfig();
405
+ const appConfig = await getLocalConfig();
410
406
  if (appConfig.token) {
411
407
  if (await isTokenValid(appConfig.token)) {
412
408
  return appConfig.token;
@@ -419,9 +415,9 @@ function tokenServiceFactory({ logger }) {
419
415
  jwksUri: jwksUrl
420
416
  });
421
417
  const getKey = (header, callback) => {
422
- client.getSigningKey(header.kid, (err, key) => {
423
- if (err) {
424
- callback(err);
418
+ client.getSigningKey(header.kid, (e, key) => {
419
+ if (e) {
420
+ callback(e);
425
421
  } else if (key) {
426
422
  const publicKey = "publicKey" in key ? key.publicKey : key.rsaPublicKey;
427
423
  callback(null, publicKey);
@@ -459,24 +455,25 @@ function tokenServiceFactory({ logger }) {
459
455
  return true;
460
456
  }
461
457
  return false;
462
- } catch (error) {
463
- logger.debug(error);
458
+ } catch (e) {
459
+ logger.debug(e);
464
460
  return false;
465
461
  }
466
462
  }
467
- function eraseToken() {
468
- const appConfig = getLocalConfig();
463
+ async function eraseToken() {
464
+ const appConfig = await getLocalConfig();
469
465
  if (!appConfig) {
470
466
  return;
471
467
  }
472
468
  delete appConfig.token;
473
469
  try {
474
- saveLocalConfig(appConfig);
475
- } catch (error) {
476
- logger.debug(error);
470
+ await saveLocalConfig(appConfig);
471
+ } catch (e) {
472
+ logger.debug(e);
477
473
  logger.error(
478
474
  "There was an issue removing your login information. Please try logging out again."
479
475
  );
476
+ throw e;
480
477
  }
481
478
  }
482
479
  async function getValidToken() {
@@ -621,29 +618,36 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
621
618
  local: strapiInfoSave,
622
619
  tokenServiceFactory
623
620
  }, Symbol.toStringTag, { value: "Module" }));
624
- function handleError(ctx, error) {
625
- const tokenService = tokenServiceFactory(ctx);
621
+ async function handleError(ctx, error) {
622
+ const tokenService = await tokenServiceFactory(ctx);
626
623
  const { logger } = ctx;
627
624
  logger.debug(error);
628
625
  if (error instanceof axios.AxiosError) {
626
+ const errorMessage = typeof error.response?.data === "string" ? error.response.data : null;
629
627
  switch (error.response?.status) {
630
628
  case 401:
631
629
  logger.error("Your session has expired. Please log in again.");
632
- tokenService.eraseToken();
630
+ await tokenService.eraseToken();
633
631
  return;
634
632
  case 403:
635
633
  logger.error(
636
- error.response.data || "You do not have permission to create a project. Please contact support for assistance."
634
+ errorMessage || "You do not have permission to create a project. Please contact support for assistance."
637
635
  );
638
636
  return;
639
637
  case 400:
640
- logger.error("Invalid input. Please check your inputs and try again.");
638
+ logger.error(errorMessage || "Invalid input. Please check your inputs and try again.");
641
639
  return;
642
640
  case 503:
643
641
  logger.error(
644
642
  "Strapi Cloud project creation is currently unavailable. Please try again later."
645
643
  );
646
644
  return;
645
+ default:
646
+ if (errorMessage) {
647
+ logger.error(errorMessage);
648
+ return;
649
+ }
650
+ break;
647
651
  }
648
652
  }
649
653
  logger.error(
@@ -652,12 +656,12 @@ function handleError(ctx, error) {
652
656
  }
653
657
  const action$3 = async (ctx) => {
654
658
  const { logger } = ctx;
655
- const { getValidToken } = tokenServiceFactory(ctx);
659
+ const { getValidToken } = await tokenServiceFactory(ctx);
656
660
  const token = await getValidToken();
657
661
  if (!token) {
658
662
  return;
659
663
  }
660
- const cloudApi = cloudApiFactory(token);
664
+ const cloudApi = await cloudApiFactory(token);
661
665
  const { data: config } = await cloudApi.config();
662
666
  const { questions, defaults: defaultValues } = config.projectCreation;
663
667
  const projectAnswersDefaulted = fp.defaults(defaultValues);
@@ -666,12 +670,12 @@ const action$3 = async (ctx) => {
666
670
  const spinner = logger.spinner("Setting up your project...").start();
667
671
  try {
668
672
  const { data } = await cloudApi.createProject(projectInput);
669
- save({ project: data });
673
+ await save({ project: data });
670
674
  spinner.succeed("Project created successfully!");
671
675
  return data;
672
676
  } catch (e) {
673
677
  spinner.fail("Failed to create project on Strapi Cloud.");
674
- handleError(ctx, e);
678
+ await handleError(ctx, e);
675
679
  }
676
680
  };
677
681
  function notificationServiceFactory({ logger }) {
@@ -799,9 +803,9 @@ const buildLogsServiceFactory = ({ logger }) => {
799
803
  };
800
804
  };
801
805
  async function upload(ctx, project, token, maxProjectFileSize) {
802
- const cloudApi = cloudApiFactory(token);
806
+ const cloudApi = await cloudApiFactory(token);
803
807
  try {
804
- const storagePath = getTmpStoragePath();
808
+ const storagePath = await getTmpStoragePath();
805
809
  const projectFolder = path__namespace.default.resolve(process.cwd());
806
810
  const packageJson2 = await loadPkg(ctx);
807
811
  if (!packageJson2) {
@@ -832,11 +836,18 @@ async function upload(ctx, project, token, maxProjectFileSize) {
832
836
  process.exit(1);
833
837
  }
834
838
  const tarFilePath = path__namespace.default.resolve(storagePath, compressedFilename);
835
- const fileStats = fs__namespace.default.statSync(tarFilePath);
839
+ const fileStats = await fse__default.default.stat(tarFilePath);
836
840
  if (fileStats.size > maxProjectFileSize) {
837
- return ctx.logger.log(
841
+ ctx.logger.log(
838
842
  "Unable to proceed: Your project is too big to be transferred, please use a git repo instead."
839
843
  );
844
+ try {
845
+ await fse__default.default.remove(tarFilePath);
846
+ } catch (e) {
847
+ ctx.logger.log("Unable to remove file: ", tarFilePath);
848
+ ctx.logger.debug(e);
849
+ }
850
+ return;
840
851
  }
841
852
  ctx.logger.info("🚀 Uploading project...");
842
853
  const progressBar = ctx.logger.progressBar(100, "Upload Progress");
@@ -870,7 +881,7 @@ async function upload(ctx, project, token, maxProjectFileSize) {
870
881
  }
871
882
  ctx.logger.debug(e);
872
883
  } finally {
873
- fs__namespace.default.rmSync(tarFilePath, { force: true });
884
+ await fse__default.default.remove(tarFilePath);
874
885
  }
875
886
  process.exit(0);
876
887
  } catch (e) {
@@ -880,7 +891,7 @@ async function upload(ctx, project, token, maxProjectFileSize) {
880
891
  }
881
892
  }
882
893
  async function getProject(ctx) {
883
- const { project } = retrieve();
894
+ const { project } = await retrieve();
884
895
  if (!project) {
885
896
  try {
886
897
  return await action$3(ctx);
@@ -893,7 +904,8 @@ async function getProject(ctx) {
893
904
  return project;
894
905
  }
895
906
  const action$2 = async (ctx) => {
896
- const { getValidToken } = tokenServiceFactory(ctx);
907
+ const { getValidToken } = await tokenServiceFactory(ctx);
908
+ const cloudApiService = await cloudApiFactory();
897
909
  const token = await getValidToken();
898
910
  if (!token) {
899
911
  return;
@@ -902,10 +914,14 @@ const action$2 = async (ctx) => {
902
914
  if (!project) {
903
915
  return;
904
916
  }
917
+ try {
918
+ await cloudApiService.track("willDeployWithCLI", { projectInternalName: project.name });
919
+ } catch (e) {
920
+ ctx.logger.debug("Failed to track willDeploy", e);
921
+ }
905
922
  const notificationService = notificationServiceFactory(ctx);
906
923
  const buildLogsService = buildLogsServiceFactory(ctx);
907
- const cloudApiService2 = cloudApiFactory();
908
- const { data: cliConfig2 } = await cloudApiService2.config();
924
+ const { data: cliConfig2 } = await cloudApiService.config();
909
925
  let maxSize = parseInt(cliConfig2.maxProjectFileSize, 10);
910
926
  if (Number.isNaN(maxSize)) {
911
927
  ctx.logger.debug(
@@ -914,9 +930,18 @@ const action$2 = async (ctx) => {
914
930
  maxSize = 1e8;
915
931
  }
916
932
  const buildId = await upload(ctx, project, token, maxSize);
933
+ if (!buildId) {
934
+ return;
935
+ }
917
936
  try {
918
937
  notificationService(`${apiConfig.apiBaseUrl}/notifications`, token, cliConfig2);
919
938
  await buildLogsService(`${apiConfig.apiBaseUrl}/v1/logs/${buildId}`, token, cliConfig2);
939
+ ctx.logger.log(
940
+ "Visit the following URL for deployment logs. Your deployment will be available here shortly."
941
+ );
942
+ ctx.logger.log(
943
+ chalk__default.default.underline(`${apiConfig.dashboardBaseUrl}/projects/${project.name}/deployments`)
944
+ );
920
945
  } catch (e) {
921
946
  if (e instanceof Error) {
922
947
  ctx.logger.error(e.message);
@@ -953,7 +978,7 @@ const runAction = (name2, action2) => (...args) => {
953
978
  });
954
979
  };
955
980
  const command$3 = ({ command: command2, ctx }) => {
956
- return command2.command("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));
981
+ command2.command("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));
957
982
  };
958
983
  const deployProject = {
959
984
  name: "deploy-project",
@@ -964,12 +989,12 @@ const deployProject = {
964
989
  const openModule = import("open");
965
990
  const action$1 = async (ctx) => {
966
991
  const { logger } = ctx;
967
- const tokenService = tokenServiceFactory(ctx);
992
+ const tokenService = await tokenServiceFactory(ctx);
968
993
  const existingToken = await tokenService.retrieveToken();
969
- const cloudApiService2 = cloudApiFactory(existingToken || void 0);
994
+ const cloudApiService = await cloudApiFactory(existingToken || void 0);
970
995
  const trackFailedLogin = async () => {
971
996
  try {
972
- await cloudApiService2.track("didNotLogin", { loginMethod: "cli" });
997
+ await cloudApiService.track("didNotLogin", { loginMethod: "cli" });
973
998
  } catch (e) {
974
999
  logger.debug("Failed to track failed login", e);
975
1000
  }
@@ -978,14 +1003,18 @@ const action$1 = async (ctx) => {
978
1003
  const isTokenValid = await tokenService.isTokenValid(existingToken);
979
1004
  if (isTokenValid) {
980
1005
  try {
981
- const userInfo = await cloudApiService2.getUserInfo();
1006
+ const userInfo = await cloudApiService.getUserInfo();
982
1007
  const { email } = userInfo.data.data;
983
1008
  if (email) {
984
1009
  logger.log(`You are already logged into your account (${email}).`);
985
1010
  } else {
986
1011
  logger.log("You are already logged in.");
987
1012
  }
988
- return;
1013
+ logger.log(
1014
+ "To access your dashboard, please copy and paste the following URL into your web browser:"
1015
+ );
1016
+ logger.log(chalk__default.default.underline(`${apiConfig.dashboardBaseUrl}/projects`));
1017
+ return true;
989
1018
  } catch (e) {
990
1019
  logger.debug("Failed to fetch user info", e);
991
1020
  }
@@ -994,15 +1023,15 @@ const action$1 = async (ctx) => {
994
1023
  let cliConfig2;
995
1024
  try {
996
1025
  logger.info("🔌 Connecting to the Strapi Cloud API...");
997
- const config = await cloudApiService2.config();
1026
+ const config = await cloudApiService.config();
998
1027
  cliConfig2 = config.data;
999
1028
  } catch (e) {
1000
1029
  logger.error("🥲 Oops! Something went wrong while logging you in. Please try again.");
1001
1030
  logger.debug(e);
1002
- return;
1031
+ return false;
1003
1032
  }
1004
1033
  try {
1005
- await cloudApiService2.track("willLoginAttempt", {});
1034
+ await cloudApiService.track("willLoginAttempt", {});
1006
1035
  } catch (e) {
1007
1036
  logger.debug("Failed to track login attempt", e);
1008
1037
  }
@@ -1061,9 +1090,9 @@ const action$1 = async (ctx) => {
1061
1090
  spinnerFail();
1062
1091
  throw new Error("Unable to proceed: Token validation failed");
1063
1092
  }
1064
- const cloudApiService22 = cloudApiFactory(authTokenData.access_token);
1065
1093
  logger.debug("🔍 Fetching user information...");
1066
- await cloudApiService22.getUserInfo();
1094
+ const cloudApiServiceWithToken = await cloudApiFactory(authTokenData.access_token);
1095
+ await cloudApiServiceWithToken.getUserInfo();
1067
1096
  logger.debug("🔍 User information fetched successfully!");
1068
1097
  try {
1069
1098
  logger.debug("📝 Saving login information...");
@@ -1076,7 +1105,7 @@ const action$1 = async (ctx) => {
1076
1105
  );
1077
1106
  logger.debug(e);
1078
1107
  spinnerFail();
1079
- return;
1108
+ return false;
1080
1109
  }
1081
1110
  }
1082
1111
  } catch (e) {
@@ -1086,13 +1115,13 @@ const action$1 = async (ctx) => {
1086
1115
  );
1087
1116
  spinnerFail();
1088
1117
  await trackFailedLogin();
1089
- return;
1118
+ return false;
1090
1119
  }
1091
1120
  if (e.response?.data.error && !["authorization_pending", "slow_down"].includes(e.response.data.error)) {
1092
1121
  logger.debug(e);
1093
1122
  spinnerFail();
1094
1123
  await trackFailedLogin();
1095
- return;
1124
+ return false;
1096
1125
  }
1097
1126
  await new Promise((resolve) => {
1098
1127
  setTimeout(resolve, deviceAuthResponse.data.interval * 1e3);
@@ -1101,16 +1130,21 @@ const action$1 = async (ctx) => {
1101
1130
  }
1102
1131
  spinner.succeed("Authentication successful!");
1103
1132
  logger.log("You are now logged into Strapi Cloud.");
1133
+ logger.log(
1134
+ "To access your dashboard, please copy and paste the following URL into your web browser:"
1135
+ );
1136
+ logger.log(chalk__default.default.underline(`${apiConfig.dashboardBaseUrl}/projects`));
1104
1137
  try {
1105
- await cloudApiService2.track("didLogin", { loginMethod: "cli" });
1138
+ await cloudApiService.track("didLogin", { loginMethod: "cli" });
1106
1139
  } catch (e) {
1107
1140
  logger.debug("Failed to track login", e);
1108
1141
  }
1109
1142
  };
1110
1143
  await authenticate();
1144
+ return isAuthenticated;
1111
1145
  };
1112
1146
  const command$2 = ({ command: command2, ctx }) => {
1113
- return command2.command("cloud:login").alias("login").description("Strapi Cloud Login").addHelpText(
1147
+ command2.command("cloud:login").alias("login").description("Strapi Cloud Login").addHelpText(
1114
1148
  "after",
1115
1149
  "\nAfter running this command, you will be prompted to enter your authentication information."
1116
1150
  ).option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("login", action$1)(ctx));
@@ -1123,13 +1157,13 @@ const login = {
1123
1157
  };
1124
1158
  const action = async (ctx) => {
1125
1159
  const { logger } = ctx;
1126
- const { retrieveToken, eraseToken } = tokenServiceFactory(ctx);
1160
+ const { retrieveToken, eraseToken } = await tokenServiceFactory(ctx);
1127
1161
  const token = await retrieveToken();
1128
1162
  if (!token) {
1129
1163
  logger.log("You're already logged out.");
1130
1164
  return;
1131
1165
  }
1132
- const cloudApiService2 = cloudApiFactory(token);
1166
+ const cloudApiService = await cloudApiFactory(token);
1133
1167
  try {
1134
1168
  await eraseToken();
1135
1169
  logger.log(
@@ -1140,13 +1174,13 @@ const action = async (ctx) => {
1140
1174
  logger.debug(e);
1141
1175
  }
1142
1176
  try {
1143
- await cloudApiService2.track("didLogout", { loginMethod: "cli" });
1177
+ await cloudApiService.track("didLogout", { loginMethod: "cli" });
1144
1178
  } catch (e) {
1145
1179
  logger.debug("Failed to track logout event", e);
1146
1180
  }
1147
1181
  };
1148
1182
  const command$1 = ({ command: command2, ctx }) => {
1149
- return command2.command("cloud:logout").alias("logout").description("Strapi Cloud Logout").option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("logout", action)(ctx));
1183
+ command2.command("cloud:logout").alias("logout").description("Strapi Cloud Logout").option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("logout", action)(ctx));
1150
1184
  };
1151
1185
  const logout = {
1152
1186
  name: "logout",
@@ -1155,7 +1189,7 @@ const logout = {
1155
1189
  command: command$1
1156
1190
  };
1157
1191
  const command = ({ command: command2, ctx }) => {
1158
- return command2.command("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));
1192
+ command2.command("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));
1159
1193
  };
1160
1194
  const createProject = {
1161
1195
  name: "create-project",
@@ -1171,25 +1205,25 @@ const cli = {
1171
1205
  };
1172
1206
  const cloudCommands = [deployProject, login, logout];
1173
1207
  async function initCloudCLIConfig() {
1174
- const localConfig = getLocalConfig();
1208
+ const localConfig = await getLocalConfig();
1175
1209
  if (!localConfig.deviceId) {
1176
1210
  localConfig.deviceId = crypto__default.default.randomUUID();
1177
1211
  }
1178
- saveLocalConfig(localConfig);
1212
+ await saveLocalConfig(localConfig);
1179
1213
  }
1180
- function buildStrapiCloudCommands({
1214
+ async function buildStrapiCloudCommands({
1181
1215
  command: command2,
1182
1216
  ctx,
1183
1217
  argv
1184
1218
  }) {
1185
- initCloudCLIConfig();
1186
- cloudCommands.forEach((cloudCommand) => {
1219
+ await initCloudCLIConfig();
1220
+ for (const cloudCommand of cloudCommands) {
1187
1221
  try {
1188
- cloudCommand.command({ command: command2, ctx, argv });
1222
+ await cloudCommand.command({ command: command2, ctx, argv });
1189
1223
  } catch (e) {
1190
1224
  console.error(`Failed to load command ${cloudCommand.name}`, e);
1191
1225
  }
1192
- });
1226
+ }
1193
1227
  }
1194
1228
  exports.buildStrapiCloudCommands = buildStrapiCloudCommands;
1195
1229
  exports.cli = cli;