@strapi/cloud-cli 0.0.0-next.ae38a9dcdeddea4b4c0978686fb024413e5c54f5 → 0.0.0-next.aff9d09e4edf4d38b8a0de5abf83d79bedb28313
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 +305 -72
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +305 -71
- package/dist/index.mjs.map +1 -1
- package/dist/src/create-project/action.d.ts.map +1 -1
- package/dist/src/create-project/utils/project-questions.utils.d.ts +20 -0
- package/dist/src/create-project/utils/project-questions.utils.d.ts.map +1 -0
- package/dist/src/deploy-project/action.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/link/action.d.ts +4 -0
- package/dist/src/link/action.d.ts.map +1 -0
- package/dist/src/link/command.d.ts +7 -0
- package/dist/src/link/command.d.ts.map +1 -0
- package/dist/src/link/index.d.ts +7 -0
- package/dist/src/link/index.d.ts.map +1 -0
- package/dist/src/login/action.d.ts.map +1 -1
- package/dist/src/logout/action.d.ts.map +1 -1
- package/dist/src/services/build-logs.d.ts.map +1 -1
- package/dist/src/services/cli-api.d.ts +29 -6
- package/dist/src/services/cli-api.d.ts.map +1 -1
- package/dist/src/services/strapi-info-save.d.ts +1 -1
- package/dist/src/services/strapi-info-save.d.ts.map +1 -1
- package/dist/src/types.d.ts +1 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/analytics.d.ts +4 -0
- package/dist/src/utils/analytics.d.ts.map +1 -0
- package/package.json +5 -5
- package/dist/src/create-project/utils/apply-default-name.d.ts +0 -7
- package/dist/src/create-project/utils/apply-default-name.d.ts.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -20,7 +20,6 @@ import ora from "ora";
|
|
|
20
20
|
import * as cliProgress from "cli-progress";
|
|
21
21
|
import pkgUp from "pkg-up";
|
|
22
22
|
import * as yup from "yup";
|
|
23
|
-
import _ from "lodash";
|
|
24
23
|
import EventSource from "eventsource";
|
|
25
24
|
const apiConfig = {
|
|
26
25
|
apiBaseUrl: env("STRAPI_CLI_CLOUD_API", "https://cloud-cli-api.strapi.io"),
|
|
@@ -134,7 +133,7 @@ async function saveLocalConfig(data) {
|
|
|
134
133
|
await fse__default.writeJson(configFilePath, data, { encoding: "utf8", spaces: 2, mode: 384 });
|
|
135
134
|
}
|
|
136
135
|
const name = "@strapi/cloud-cli";
|
|
137
|
-
const version = "4.25.
|
|
136
|
+
const version = "4.25.8";
|
|
138
137
|
const description = "Commands to interact with the Strapi Cloud";
|
|
139
138
|
const keywords = [
|
|
140
139
|
"strapi",
|
|
@@ -179,7 +178,7 @@ const scripts = {
|
|
|
179
178
|
watch: "pack-up watch"
|
|
180
179
|
};
|
|
181
180
|
const dependencies = {
|
|
182
|
-
"@strapi/utils": "4.25.
|
|
181
|
+
"@strapi/utils": "4.25.8",
|
|
183
182
|
axios: "1.6.0",
|
|
184
183
|
chalk: "4.1.2",
|
|
185
184
|
"cli-progress": "3.12.0",
|
|
@@ -204,8 +203,8 @@ const devDependencies = {
|
|
|
204
203
|
"@types/cli-progress": "3.11.5",
|
|
205
204
|
"@types/eventsource": "1.1.15",
|
|
206
205
|
"@types/lodash": "^4.14.191",
|
|
207
|
-
"eslint-config-custom": "4.25.
|
|
208
|
-
tsconfig: "4.25.
|
|
206
|
+
"eslint-config-custom": "4.25.8",
|
|
207
|
+
tsconfig: "4.25.8"
|
|
209
208
|
};
|
|
210
209
|
const engines = {
|
|
211
210
|
node: ">=18.0.0 <=20.x.x",
|
|
@@ -315,6 +314,34 @@ async function cloudApiFactory({ logger }, token) {
|
|
|
315
314
|
throw error;
|
|
316
315
|
}
|
|
317
316
|
},
|
|
317
|
+
async listLinkProjects() {
|
|
318
|
+
try {
|
|
319
|
+
const response = await axiosCloudAPI.get("/projects/linkable");
|
|
320
|
+
if (response.status !== 200) {
|
|
321
|
+
throw new Error("Error fetching cloud projects from the server.");
|
|
322
|
+
}
|
|
323
|
+
return response;
|
|
324
|
+
} catch (error) {
|
|
325
|
+
logger.debug(
|
|
326
|
+
"🥲 Oops! Couldn't retrieve your project's list from the server. Please try again."
|
|
327
|
+
);
|
|
328
|
+
throw error;
|
|
329
|
+
}
|
|
330
|
+
},
|
|
331
|
+
async getProject({ name: name2 }) {
|
|
332
|
+
try {
|
|
333
|
+
const response = await axiosCloudAPI.get(`/projects/${name2}`);
|
|
334
|
+
if (response.status !== 200) {
|
|
335
|
+
throw new Error("Error fetching project's details.");
|
|
336
|
+
}
|
|
337
|
+
return response;
|
|
338
|
+
} catch (error) {
|
|
339
|
+
logger.debug(
|
|
340
|
+
"🥲 Oops! There was a problem retrieving your project's details. Please try again."
|
|
341
|
+
);
|
|
342
|
+
throw error;
|
|
343
|
+
}
|
|
344
|
+
},
|
|
318
345
|
track(event, payload = {}) {
|
|
319
346
|
return axiosCloudAPI.post("/track", {
|
|
320
347
|
event,
|
|
@@ -624,18 +651,13 @@ async function getProjectNameFromPackageJson(ctx) {
|
|
|
624
651
|
return "my-strapi-project";
|
|
625
652
|
}
|
|
626
653
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
}
|
|
635
|
-
return questionCopy;
|
|
636
|
-
});
|
|
637
|
-
return { newQuestions, newDefaultValues };
|
|
638
|
-
}
|
|
654
|
+
const trackEvent = async (ctx, cloudApiService, eventName, eventData) => {
|
|
655
|
+
try {
|
|
656
|
+
await cloudApiService.track(eventName, eventData);
|
|
657
|
+
} catch (e) {
|
|
658
|
+
ctx.logger.debug(`Failed to track ${eventName}`, e);
|
|
659
|
+
}
|
|
660
|
+
};
|
|
639
661
|
const openModule$1 = import("open");
|
|
640
662
|
async function promptLogin(ctx) {
|
|
641
663
|
const response = await inquirer.prompt([
|
|
@@ -656,13 +678,6 @@ async function loginAction(ctx) {
|
|
|
656
678
|
const tokenService = await tokenServiceFactory(ctx);
|
|
657
679
|
const existingToken = await tokenService.retrieveToken();
|
|
658
680
|
const cloudApiService = await cloudApiFactory(ctx, existingToken || void 0);
|
|
659
|
-
const trackFailedLogin = async () => {
|
|
660
|
-
try {
|
|
661
|
-
await cloudApiService.track("didNotLogin", { loginMethod: "cli" });
|
|
662
|
-
} catch (e) {
|
|
663
|
-
logger.debug("Failed to track failed login", e);
|
|
664
|
-
}
|
|
665
|
-
};
|
|
666
681
|
if (existingToken) {
|
|
667
682
|
const isTokenValid = await tokenService.isTokenValid(existingToken);
|
|
668
683
|
if (isTokenValid) {
|
|
@@ -694,11 +709,7 @@ async function loginAction(ctx) {
|
|
|
694
709
|
logger.debug(e);
|
|
695
710
|
return false;
|
|
696
711
|
}
|
|
697
|
-
|
|
698
|
-
await cloudApiService.track("willLoginAttempt", {});
|
|
699
|
-
} catch (e) {
|
|
700
|
-
logger.debug("Failed to track login attempt", e);
|
|
701
|
-
}
|
|
712
|
+
await trackEvent(ctx, cloudApiService, "willLoginAttempt", {});
|
|
702
713
|
logger.debug("🔐 Creating device authentication request...", {
|
|
703
714
|
client_id: cliConfig2.clientId,
|
|
704
715
|
scope: cliConfig2.scope,
|
|
@@ -778,13 +789,13 @@ async function loginAction(ctx) {
|
|
|
778
789
|
"There seems to be a problem with your login information. Please try logging in again."
|
|
779
790
|
);
|
|
780
791
|
spinnerFail();
|
|
781
|
-
await
|
|
792
|
+
await trackEvent(ctx, cloudApiService, "didNotLogin", { loginMethod: "cli" });
|
|
782
793
|
return false;
|
|
783
794
|
}
|
|
784
795
|
if (e.response?.data.error && !["authorization_pending", "slow_down"].includes(e.response.data.error)) {
|
|
785
796
|
logger.debug(e);
|
|
786
797
|
spinnerFail();
|
|
787
|
-
await
|
|
798
|
+
await trackEvent(ctx, cloudApiService, "didNotLogin", { loginMethod: "cli" });
|
|
788
799
|
return false;
|
|
789
800
|
}
|
|
790
801
|
await new Promise((resolve) => {
|
|
@@ -798,15 +809,50 @@ async function loginAction(ctx) {
|
|
|
798
809
|
"To access your dashboard, please copy and paste the following URL into your web browser:"
|
|
799
810
|
);
|
|
800
811
|
logger.log(chalk.underline(`${apiConfig.dashboardBaseUrl}/projects`));
|
|
801
|
-
|
|
802
|
-
await cloudApiService.track("didLogin", { loginMethod: "cli" });
|
|
803
|
-
} catch (e) {
|
|
804
|
-
logger.debug("Failed to track login", e);
|
|
805
|
-
}
|
|
812
|
+
await trackEvent(ctx, cloudApiService, "didLogin", { loginMethod: "cli" });
|
|
806
813
|
};
|
|
807
814
|
await authenticate();
|
|
808
815
|
return isAuthenticated;
|
|
809
816
|
}
|
|
817
|
+
function questionDefaultValuesMapper(questionsMap) {
|
|
818
|
+
return (questions) => {
|
|
819
|
+
return questions.map((question) => {
|
|
820
|
+
const questionName = question.name;
|
|
821
|
+
if (questionName in questionsMap) {
|
|
822
|
+
const questionDefault = questionsMap[questionName];
|
|
823
|
+
if (typeof questionDefault === "function") {
|
|
824
|
+
return {
|
|
825
|
+
...question,
|
|
826
|
+
default: questionDefault(question)
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
return {
|
|
830
|
+
...question,
|
|
831
|
+
default: questionDefault
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
return question;
|
|
835
|
+
});
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
function getDefaultsFromQuestions(questions) {
|
|
839
|
+
return questions.reduce((acc, question) => {
|
|
840
|
+
if (question.default && question.name) {
|
|
841
|
+
return { ...acc, [question.name]: question.default };
|
|
842
|
+
}
|
|
843
|
+
return acc;
|
|
844
|
+
}, {});
|
|
845
|
+
}
|
|
846
|
+
function getProjectNodeVersionDefault(question) {
|
|
847
|
+
const currentNodeVersion = process.versions.node.split(".")[0];
|
|
848
|
+
if (question.type === "list" && Array.isArray(question.choices)) {
|
|
849
|
+
const choice = question.choices.find((choice2) => choice2.value === currentNodeVersion);
|
|
850
|
+
if (choice) {
|
|
851
|
+
return choice.value;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
return question.default;
|
|
855
|
+
}
|
|
810
856
|
async function handleError(ctx, error) {
|
|
811
857
|
const { logger } = ctx;
|
|
812
858
|
logger.debug(error);
|
|
@@ -851,7 +897,7 @@ async function createProject$1(ctx, cloudApi, projectInput) {
|
|
|
851
897
|
throw e;
|
|
852
898
|
}
|
|
853
899
|
}
|
|
854
|
-
const action$
|
|
900
|
+
const action$4 = async (ctx) => {
|
|
855
901
|
const { logger } = ctx;
|
|
856
902
|
const { getValidToken, eraseToken } = await tokenServiceFactory(ctx);
|
|
857
903
|
const token = await getValidToken(ctx, promptLogin);
|
|
@@ -860,11 +906,16 @@ const action$3 = async (ctx) => {
|
|
|
860
906
|
}
|
|
861
907
|
const cloudApi = await cloudApiFactory(ctx, token);
|
|
862
908
|
const { data: config } = await cloudApi.config();
|
|
863
|
-
const
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
);
|
|
909
|
+
const projectName = await getProjectNameFromPackageJson(ctx);
|
|
910
|
+
const defaultAnswersMapper = questionDefaultValuesMapper({
|
|
911
|
+
name: projectName,
|
|
912
|
+
nodeVersion: getProjectNodeVersionDefault
|
|
913
|
+
});
|
|
914
|
+
const questions = defaultAnswersMapper(config.projectCreation.questions);
|
|
915
|
+
const defaultValues = {
|
|
916
|
+
...config.projectCreation.defaults,
|
|
917
|
+
...getDefaultsFromQuestions(questions)
|
|
918
|
+
};
|
|
868
919
|
const projectAnswersDefaulted = defaults(defaultValues);
|
|
869
920
|
const projectAnswers = await inquirer.prompt(questions);
|
|
870
921
|
const projectInput = projectAnswersDefaulted(projectAnswers);
|
|
@@ -966,6 +1017,7 @@ const buildLogsServiceFactory = ({ logger }) => {
|
|
|
966
1017
|
if (retries > MAX_RETRIES) {
|
|
967
1018
|
spinner.fail("We were unable to connect to the server to get build logs at this time.");
|
|
968
1019
|
es.close();
|
|
1020
|
+
clearExistingTimeout();
|
|
969
1021
|
reject(new Error("Max retries reached"));
|
|
970
1022
|
}
|
|
971
1023
|
};
|
|
@@ -1040,17 +1092,7 @@ async function upload(ctx, project, token, maxProjectFileSize) {
|
|
|
1040
1092
|
return data.build_id;
|
|
1041
1093
|
} catch (e) {
|
|
1042
1094
|
progressBar.stop();
|
|
1043
|
-
|
|
1044
|
-
if (e.response.status === 404) {
|
|
1045
|
-
ctx.logger.error(
|
|
1046
|
-
`The project does not exist. Remove the ${LOCAL_SAVE_FILENAME} file and try again.`
|
|
1047
|
-
);
|
|
1048
|
-
} else {
|
|
1049
|
-
ctx.logger.error(e.response.data);
|
|
1050
|
-
}
|
|
1051
|
-
} else {
|
|
1052
|
-
ctx.logger.error("An error occurred while deploying the project. Please try again later.");
|
|
1053
|
-
}
|
|
1095
|
+
ctx.logger.error("An error occurred while deploying the project. Please try again later.");
|
|
1054
1096
|
ctx.logger.debug(e);
|
|
1055
1097
|
} finally {
|
|
1056
1098
|
await fse__default.remove(tarFilePath);
|
|
@@ -1066,7 +1108,7 @@ async function getProject(ctx) {
|
|
|
1066
1108
|
const { project } = await retrieve();
|
|
1067
1109
|
if (!project) {
|
|
1068
1110
|
try {
|
|
1069
|
-
return await action$
|
|
1111
|
+
return await action$4(ctx);
|
|
1070
1112
|
} catch (e) {
|
|
1071
1113
|
ctx.logger.error("An error occurred while deploying the project. Please try again later.");
|
|
1072
1114
|
ctx.logger.debug(e);
|
|
@@ -1075,7 +1117,19 @@ async function getProject(ctx) {
|
|
|
1075
1117
|
}
|
|
1076
1118
|
return project;
|
|
1077
1119
|
}
|
|
1078
|
-
|
|
1120
|
+
async function getConfig({
|
|
1121
|
+
ctx,
|
|
1122
|
+
cloudApiService
|
|
1123
|
+
}) {
|
|
1124
|
+
try {
|
|
1125
|
+
const { data: cliConfig2 } = await cloudApiService.config();
|
|
1126
|
+
return cliConfig2;
|
|
1127
|
+
} catch (e) {
|
|
1128
|
+
ctx.logger.debug("Failed to get cli config", e);
|
|
1129
|
+
return null;
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
const action$3 = async (ctx) => {
|
|
1079
1133
|
const { getValidToken } = await tokenServiceFactory(ctx);
|
|
1080
1134
|
const token = await getValidToken(ctx, promptLogin);
|
|
1081
1135
|
if (!token) {
|
|
@@ -1085,15 +1139,51 @@ const action$2 = async (ctx) => {
|
|
|
1085
1139
|
if (!project) {
|
|
1086
1140
|
return;
|
|
1087
1141
|
}
|
|
1088
|
-
const cloudApiService = await cloudApiFactory(ctx);
|
|
1142
|
+
const cloudApiService = await cloudApiFactory(ctx, token);
|
|
1089
1143
|
try {
|
|
1090
|
-
|
|
1144
|
+
const {
|
|
1145
|
+
data: { data: projectData, metadata }
|
|
1146
|
+
} = await cloudApiService.getProject({ name: project.name });
|
|
1147
|
+
const isProjectSuspended = projectData.suspendedAt;
|
|
1148
|
+
if (isProjectSuspended) {
|
|
1149
|
+
ctx.logger.log(
|
|
1150
|
+
"\n Oops! This project has been suspended. \n\n Please reactivate it from the dashboard to continue deploying: "
|
|
1151
|
+
);
|
|
1152
|
+
ctx.logger.log(chalk.underline(`${metadata.dashboardUrls.project}`));
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1091
1155
|
} catch (e) {
|
|
1092
|
-
|
|
1156
|
+
if (e instanceof AxiosError && e.response?.data) {
|
|
1157
|
+
if (e.response.status === 404) {
|
|
1158
|
+
ctx.logger.warn(
|
|
1159
|
+
`The project associated with this folder does not exist in Strapi Cloud.
|
|
1160
|
+
Please link your local project to an existing Strapi Cloud project using the ${chalk.cyan(
|
|
1161
|
+
"link"
|
|
1162
|
+
)} command before deploying.`
|
|
1163
|
+
);
|
|
1164
|
+
} else {
|
|
1165
|
+
ctx.logger.error(e.response.data);
|
|
1166
|
+
}
|
|
1167
|
+
} else {
|
|
1168
|
+
ctx.logger.error(
|
|
1169
|
+
"An error occurred while retrieving the project's information. Please try again later."
|
|
1170
|
+
);
|
|
1171
|
+
}
|
|
1172
|
+
ctx.logger.debug(e);
|
|
1173
|
+
return;
|
|
1093
1174
|
}
|
|
1175
|
+
await trackEvent(ctx, cloudApiService, "willDeployWithCLI", {
|
|
1176
|
+
projectInternalName: project.name
|
|
1177
|
+
});
|
|
1094
1178
|
const notificationService = notificationServiceFactory(ctx);
|
|
1095
1179
|
const buildLogsService = buildLogsServiceFactory(ctx);
|
|
1096
|
-
const
|
|
1180
|
+
const cliConfig2 = await getConfig({ ctx, cloudApiService });
|
|
1181
|
+
if (!cliConfig2) {
|
|
1182
|
+
ctx.logger.error(
|
|
1183
|
+
"An error occurred while retrieving data from Strapi Cloud. Please check your network or try again later."
|
|
1184
|
+
);
|
|
1185
|
+
return;
|
|
1186
|
+
}
|
|
1097
1187
|
let maxSize = parseInt(cliConfig2.maxProjectFileSize, 10);
|
|
1098
1188
|
if (Number.isNaN(maxSize)) {
|
|
1099
1189
|
ctx.logger.debug(
|
|
@@ -1115,10 +1205,11 @@ const action$2 = async (ctx) => {
|
|
|
1115
1205
|
chalk.underline(`${apiConfig.dashboardBaseUrl}/projects/${project.name}/deployments`)
|
|
1116
1206
|
);
|
|
1117
1207
|
} catch (e) {
|
|
1208
|
+
ctx.logger.debug(e);
|
|
1118
1209
|
if (e instanceof Error) {
|
|
1119
1210
|
ctx.logger.error(e.message);
|
|
1120
1211
|
} else {
|
|
1121
|
-
|
|
1212
|
+
ctx.logger.error("An error occurred while deploying the project. Please try again later.");
|
|
1122
1213
|
}
|
|
1123
1214
|
}
|
|
1124
1215
|
};
|
|
@@ -1149,12 +1240,158 @@ const runAction = (name2, action2) => (...args) => {
|
|
|
1149
1240
|
process.exit(1);
|
|
1150
1241
|
});
|
|
1151
1242
|
};
|
|
1152
|
-
const command$
|
|
1153
|
-
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$
|
|
1243
|
+
const command$5 = ({ command: command2, ctx }) => {
|
|
1244
|
+
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$3)(ctx));
|
|
1154
1245
|
};
|
|
1155
1246
|
const deployProject = {
|
|
1156
1247
|
name: "deploy-project",
|
|
1157
1248
|
description: "Deploy a Strapi Cloud project",
|
|
1249
|
+
action: action$3,
|
|
1250
|
+
command: command$5
|
|
1251
|
+
};
|
|
1252
|
+
const QUIT_OPTION = "Quit";
|
|
1253
|
+
async function getExistingConfig(ctx) {
|
|
1254
|
+
try {
|
|
1255
|
+
return await retrieve();
|
|
1256
|
+
} catch (e) {
|
|
1257
|
+
ctx.logger.debug("Failed to get project config", e);
|
|
1258
|
+
ctx.logger.error("An error occurred while retrieving config data from your local project.");
|
|
1259
|
+
return null;
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
async function promptForRelink(ctx, cloudApiService, existingConfig) {
|
|
1263
|
+
if (existingConfig && existingConfig.project) {
|
|
1264
|
+
const { shouldRelink } = await inquirer.prompt([
|
|
1265
|
+
{
|
|
1266
|
+
type: "confirm",
|
|
1267
|
+
name: "shouldRelink",
|
|
1268
|
+
message: `A project named ${chalk.cyan(
|
|
1269
|
+
existingConfig.project.displayName ? existingConfig.project.displayName : existingConfig.project.name
|
|
1270
|
+
)} is already linked to this local folder. Do you want to update the link?`,
|
|
1271
|
+
default: false
|
|
1272
|
+
}
|
|
1273
|
+
]);
|
|
1274
|
+
if (!shouldRelink) {
|
|
1275
|
+
await trackEvent(ctx, cloudApiService, "didNotLinkProject", {
|
|
1276
|
+
currentProjectName: existingConfig.project?.name
|
|
1277
|
+
});
|
|
1278
|
+
return false;
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
return true;
|
|
1282
|
+
}
|
|
1283
|
+
async function getProjectsList(ctx, cloudApiService, existingConfig) {
|
|
1284
|
+
const spinner = ctx.logger.spinner("Fetching your projects...\n").start();
|
|
1285
|
+
try {
|
|
1286
|
+
const {
|
|
1287
|
+
data: { data: projectList }
|
|
1288
|
+
} = await cloudApiService.listLinkProjects();
|
|
1289
|
+
spinner.succeed();
|
|
1290
|
+
if (!Array.isArray(projectList)) {
|
|
1291
|
+
ctx.logger.log("We couldn't find any projects available for linking in Strapi Cloud");
|
|
1292
|
+
return null;
|
|
1293
|
+
}
|
|
1294
|
+
const projects = projectList.filter(
|
|
1295
|
+
(project) => !(project.isMaintainer || project.name === existingConfig?.project?.name)
|
|
1296
|
+
).map((project) => {
|
|
1297
|
+
return {
|
|
1298
|
+
name: project.displayName,
|
|
1299
|
+
value: { name: project.name, displayName: project.displayName }
|
|
1300
|
+
};
|
|
1301
|
+
});
|
|
1302
|
+
if (projects.length === 0) {
|
|
1303
|
+
ctx.logger.log("We couldn't find any projects available for linking in Strapi Cloud");
|
|
1304
|
+
return null;
|
|
1305
|
+
}
|
|
1306
|
+
return projects;
|
|
1307
|
+
} catch (e) {
|
|
1308
|
+
spinner.fail("An error occurred while fetching your projects from Strapi Cloud.");
|
|
1309
|
+
ctx.logger.debug("Failed to list projects", e);
|
|
1310
|
+
return null;
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
async function getUserSelection(ctx, projects) {
|
|
1314
|
+
const { logger } = ctx;
|
|
1315
|
+
try {
|
|
1316
|
+
const answer = await inquirer.prompt([
|
|
1317
|
+
{
|
|
1318
|
+
type: "list",
|
|
1319
|
+
name: "linkProject",
|
|
1320
|
+
message: "Which project do you want to link?",
|
|
1321
|
+
choices: [...projects, { name: chalk.grey(`(${QUIT_OPTION})`), value: null }]
|
|
1322
|
+
}
|
|
1323
|
+
]);
|
|
1324
|
+
if (!answer.linkProject) {
|
|
1325
|
+
return null;
|
|
1326
|
+
}
|
|
1327
|
+
return answer;
|
|
1328
|
+
} catch (e) {
|
|
1329
|
+
logger.debug("Failed to get user input", e);
|
|
1330
|
+
logger.error("An error occurred while trying to get your input.");
|
|
1331
|
+
return null;
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
const action$2 = async (ctx) => {
|
|
1335
|
+
const { getValidToken } = await tokenServiceFactory(ctx);
|
|
1336
|
+
const token = await getValidToken(ctx, promptLogin);
|
|
1337
|
+
const { logger } = ctx;
|
|
1338
|
+
if (!token) {
|
|
1339
|
+
return;
|
|
1340
|
+
}
|
|
1341
|
+
const cloudApiService = await cloudApiFactory(ctx, token);
|
|
1342
|
+
const existingConfig = await getExistingConfig(ctx);
|
|
1343
|
+
const shouldRelink = await promptForRelink(ctx, cloudApiService, existingConfig);
|
|
1344
|
+
if (!shouldRelink) {
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1347
|
+
await trackEvent(ctx, cloudApiService, "willLinkProject", {});
|
|
1348
|
+
const projects = await getProjectsList(
|
|
1349
|
+
ctx,
|
|
1350
|
+
cloudApiService,
|
|
1351
|
+
existingConfig
|
|
1352
|
+
);
|
|
1353
|
+
if (!projects) {
|
|
1354
|
+
return;
|
|
1355
|
+
}
|
|
1356
|
+
const answer = await getUserSelection(ctx, projects);
|
|
1357
|
+
if (!answer) {
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
try {
|
|
1361
|
+
const { confirmAction } = await inquirer.prompt([
|
|
1362
|
+
{
|
|
1363
|
+
type: "confirm",
|
|
1364
|
+
name: "confirmAction",
|
|
1365
|
+
message: "Warning: Once linked, deploying from CLI will replace the existing project and its data. Confirm to proceed:",
|
|
1366
|
+
default: false
|
|
1367
|
+
}
|
|
1368
|
+
]);
|
|
1369
|
+
if (!confirmAction) {
|
|
1370
|
+
await trackEvent(ctx, cloudApiService, "didNotLinkProject", {
|
|
1371
|
+
cancelledProjectName: answer.linkProject.name,
|
|
1372
|
+
currentProjectName: existingConfig ? existingConfig.project?.name : null
|
|
1373
|
+
});
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
await save({ project: answer.linkProject });
|
|
1377
|
+
logger.log(`Project ${chalk.cyan(answer.linkProject.displayName)} linked successfully.`);
|
|
1378
|
+
await trackEvent(ctx, cloudApiService, "didLinkProject", {
|
|
1379
|
+
projectInternalName: answer.linkProject
|
|
1380
|
+
});
|
|
1381
|
+
} catch (e) {
|
|
1382
|
+
logger.debug("Failed to link project", e);
|
|
1383
|
+
logger.error("An error occurred while linking the project.");
|
|
1384
|
+
await trackEvent(ctx, cloudApiService, "didNotLinkProject", {
|
|
1385
|
+
projectInternalName: answer.linkProject
|
|
1386
|
+
});
|
|
1387
|
+
}
|
|
1388
|
+
};
|
|
1389
|
+
const command$4 = ({ command: command2, ctx }) => {
|
|
1390
|
+
command2.command("cloud:link").alias("link").description("Link a local directory to a Strapi Cloud project").option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("link", action$2)(ctx));
|
|
1391
|
+
};
|
|
1392
|
+
const link = {
|
|
1393
|
+
name: "link-project",
|
|
1394
|
+
description: "Link a local directory to a Strapi Cloud project",
|
|
1158
1395
|
action: action$2,
|
|
1159
1396
|
command: command$4
|
|
1160
1397
|
};
|
|
@@ -1201,11 +1438,7 @@ const action$1 = async (ctx) => {
|
|
|
1201
1438
|
logger.error("🥲 Oops! Something went wrong while logging you out. Please try again.");
|
|
1202
1439
|
logger.debug(e);
|
|
1203
1440
|
}
|
|
1204
|
-
|
|
1205
|
-
await cloudApiService.track("didLogout", { loginMethod: "cli" });
|
|
1206
|
-
} catch (e) {
|
|
1207
|
-
logger.debug("Failed to track logout event", e);
|
|
1208
|
-
}
|
|
1441
|
+
await trackEvent(ctx, cloudApiService, "didLogout", { loginMethod: "cli" });
|
|
1209
1442
|
};
|
|
1210
1443
|
const command$2 = ({ command: command2, ctx }) => {
|
|
1211
1444
|
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$1)(ctx));
|
|
@@ -1217,12 +1450,12 @@ const logout = {
|
|
|
1217
1450
|
command: command$2
|
|
1218
1451
|
};
|
|
1219
1452
|
const command$1 = ({ command: command2, ctx }) => {
|
|
1220
|
-
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$
|
|
1453
|
+
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$4)(ctx));
|
|
1221
1454
|
};
|
|
1222
1455
|
const createProject = {
|
|
1223
1456
|
name: "create-project",
|
|
1224
1457
|
description: "Create a new project",
|
|
1225
|
-
action: action$
|
|
1458
|
+
action: action$4,
|
|
1226
1459
|
command: command$1
|
|
1227
1460
|
};
|
|
1228
1461
|
const action = async (ctx) => {
|
|
@@ -1246,7 +1479,7 @@ const action = async (ctx) => {
|
|
|
1246
1479
|
}
|
|
1247
1480
|
};
|
|
1248
1481
|
const command = ({ command: command2, ctx }) => {
|
|
1249
|
-
command2.command("cloud:projects").alias("projects").description("List Strapi Cloud projects").option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("
|
|
1482
|
+
command2.command("cloud:projects").alias("projects").description("List Strapi Cloud projects").option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("projects", action)(ctx));
|
|
1250
1483
|
};
|
|
1251
1484
|
const listProjects = {
|
|
1252
1485
|
name: "list-projects",
|
|
@@ -1256,12 +1489,13 @@ const listProjects = {
|
|
|
1256
1489
|
};
|
|
1257
1490
|
const cli = {
|
|
1258
1491
|
deployProject,
|
|
1492
|
+
link,
|
|
1259
1493
|
login,
|
|
1260
1494
|
logout,
|
|
1261
1495
|
createProject,
|
|
1262
1496
|
listProjects
|
|
1263
1497
|
};
|
|
1264
|
-
const cloudCommands = [deployProject, login, logout, listProjects];
|
|
1498
|
+
const cloudCommands = [deployProject, link, login, logout, listProjects];
|
|
1265
1499
|
async function initCloudCLIConfig() {
|
|
1266
1500
|
const localConfig = await getLocalConfig();
|
|
1267
1501
|
if (!localConfig.deviceId) {
|