@strapi/cloud-cli 0.0.0-next.e9b6852d1c05518ff6e37d599321f7aa7aa0683b → 0.0.0-next.ec9b1b708d4d319f2b8b39d9397bd752d250d541
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/bin.js +1 -0
- package/dist/bin.js.map +1 -1
- package/dist/index.js +388 -74
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +387 -73
- package/dist/index.mjs.map +1 -1
- package/dist/src/cloud/command.d.ts +3 -0
- package/dist/src/cloud/command.d.ts.map +1 -0
- package/dist/src/create-project/command.d.ts.map +1 -1
- package/dist/src/deploy-project/action.d.ts +4 -1
- package/dist/src/deploy-project/action.d.ts.map +1 -1
- package/dist/src/deploy-project/command.d.ts.map +1 -1
- package/dist/src/environment/command.d.ts +3 -0
- package/dist/src/environment/command.d.ts.map +1 -0
- package/dist/src/environment/link/action.d.ts +4 -0
- package/dist/src/environment/link/action.d.ts.map +1 -0
- package/dist/src/environment/link/command.d.ts +4 -0
- package/dist/src/environment/link/command.d.ts.map +1 -0
- package/dist/src/environment/link/index.d.ts +7 -0
- package/dist/src/environment/link/index.d.ts.map +1 -0
- package/dist/src/environment/list/action.d.ts +4 -0
- package/dist/src/environment/list/action.d.ts.map +1 -0
- package/dist/src/environment/list/command.d.ts +4 -0
- package/dist/src/environment/list/command.d.ts.map +1 -0
- package/dist/src/environment/list/index.d.ts +7 -0
- package/dist/src/environment/list/index.d.ts.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/link/action.d.ts.map +1 -1
- package/dist/src/login/command.d.ts.map +1 -1
- package/dist/src/logout/command.d.ts.map +1 -1
- package/dist/src/services/cli-api.d.ts +23 -3
- package/dist/src/services/cli-api.d.ts.map +1 -1
- package/dist/src/services/strapi-info-save.d.ts +15 -2
- package/dist/src/services/strapi-info-save.d.ts.map +1 -1
- package/dist/src/types.d.ts +4 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/get-local-config.d.ts +6 -0
- package/dist/src/utils/get-local-config.d.ts.map +1 -0
- package/dist/src/utils/pkg.d.ts.map +1 -1
- package/dist/src/utils/tests/compress-files.test.d.ts +2 -0
- package/dist/src/utils/tests/compress-files.test.d.ts.map +1 -0
- package/package.json +8 -8
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import crypto$1 from "crypto";
|
|
2
2
|
import * as fse from "fs-extra";
|
|
3
3
|
import fse__default from "fs-extra";
|
|
4
|
+
import inquirer from "inquirer";
|
|
4
5
|
import * as path from "path";
|
|
5
6
|
import path__default from "path";
|
|
6
7
|
import chalk from "chalk";
|
|
@@ -9,10 +10,10 @@ import * as crypto from "node:crypto";
|
|
|
9
10
|
import { env } from "@strapi/utils";
|
|
10
11
|
import * as tar from "tar";
|
|
11
12
|
import { minimatch } from "minimatch";
|
|
12
|
-
import inquirer from "inquirer";
|
|
13
13
|
import { defaults, has } from "lodash/fp";
|
|
14
14
|
import os from "os";
|
|
15
15
|
import XDGAppPaths from "xdg-app-paths";
|
|
16
|
+
import { merge } from "lodash";
|
|
16
17
|
import jwksClient from "jwks-rsa";
|
|
17
18
|
import jwt from "jsonwebtoken";
|
|
18
19
|
import stringify from "fast-safe-stringify";
|
|
@@ -21,6 +22,7 @@ import * as cliProgress from "cli-progress";
|
|
|
21
22
|
import pkgUp from "pkg-up";
|
|
22
23
|
import * as yup from "yup";
|
|
23
24
|
import EventSource from "eventsource";
|
|
25
|
+
import { createCommand } from "commander";
|
|
24
26
|
const apiConfig = {
|
|
25
27
|
apiBaseUrl: env("STRAPI_CLI_CLOUD_API", "https://cloud-cli-api.strapi.io"),
|
|
26
28
|
dashboardBaseUrl: env("STRAPI_CLI_CLOUD_DASHBOARD", "https://cloud.strapi.io")
|
|
@@ -117,7 +119,7 @@ async function getConfigPath() {
|
|
|
117
119
|
}
|
|
118
120
|
return configPath;
|
|
119
121
|
}
|
|
120
|
-
async function getLocalConfig() {
|
|
122
|
+
async function getLocalConfig$1() {
|
|
121
123
|
const configPath = await getConfigPath();
|
|
122
124
|
const configFilePath = path__default.join(configPath, CONFIG_FILENAME);
|
|
123
125
|
await fse__default.ensureFile(configFilePath);
|
|
@@ -133,7 +135,7 @@ async function saveLocalConfig(data) {
|
|
|
133
135
|
await fse__default.writeJson(configFilePath, data, { encoding: "utf8", spaces: 2, mode: 384 });
|
|
134
136
|
}
|
|
135
137
|
const name = "@strapi/cloud-cli";
|
|
136
|
-
const version = "4.
|
|
138
|
+
const version = "5.4.0";
|
|
137
139
|
const description = "Commands to interact with the Strapi Cloud";
|
|
138
140
|
const keywords = [
|
|
139
141
|
"strapi",
|
|
@@ -178,14 +180,14 @@ const scripts = {
|
|
|
178
180
|
watch: "pack-up watch"
|
|
179
181
|
};
|
|
180
182
|
const dependencies = {
|
|
181
|
-
"@strapi/utils": "4.
|
|
183
|
+
"@strapi/utils": "5.4.0",
|
|
182
184
|
axios: "1.7.4",
|
|
183
185
|
chalk: "4.1.2",
|
|
184
186
|
"cli-progress": "3.12.0",
|
|
185
187
|
commander: "8.3.0",
|
|
186
188
|
eventsource: "2.0.2",
|
|
187
189
|
"fast-safe-stringify": "2.1.1",
|
|
188
|
-
"fs-extra": "
|
|
190
|
+
"fs-extra": "11.2.0",
|
|
189
191
|
inquirer: "8.2.5",
|
|
190
192
|
jsonwebtoken: "9.0.0",
|
|
191
193
|
"jwks-rsa": "3.1.0",
|
|
@@ -194,7 +196,7 @@ const dependencies = {
|
|
|
194
196
|
open: "8.4.0",
|
|
195
197
|
ora: "5.4.1",
|
|
196
198
|
"pkg-up": "3.1.0",
|
|
197
|
-
tar: "6.1
|
|
199
|
+
tar: "6.2.1",
|
|
198
200
|
"xdg-app-paths": "8.3.0",
|
|
199
201
|
yup: "0.32.9"
|
|
200
202
|
};
|
|
@@ -203,13 +205,14 @@ const devDependencies = {
|
|
|
203
205
|
"@types/cli-progress": "3.11.5",
|
|
204
206
|
"@types/eventsource": "1.1.15",
|
|
205
207
|
"@types/lodash": "^4.14.191",
|
|
206
|
-
"eslint-config-custom": "4.
|
|
207
|
-
tsconfig: "4.
|
|
208
|
+
"eslint-config-custom": "5.4.0",
|
|
209
|
+
tsconfig: "5.4.0"
|
|
208
210
|
};
|
|
209
211
|
const engines = {
|
|
210
|
-
node: ">=18.0.0 <=
|
|
212
|
+
node: ">=18.0.0 <=22.x.x",
|
|
211
213
|
npm: ">=6.0.0"
|
|
212
214
|
};
|
|
215
|
+
const gitHead = "7d785703f52464577d077c4618cbe68b44f8a9cd";
|
|
213
216
|
const packageJson = {
|
|
214
217
|
name,
|
|
215
218
|
version,
|
|
@@ -230,11 +233,12 @@ const packageJson = {
|
|
|
230
233
|
scripts,
|
|
231
234
|
dependencies,
|
|
232
235
|
devDependencies,
|
|
233
|
-
engines
|
|
236
|
+
engines,
|
|
237
|
+
gitHead
|
|
234
238
|
};
|
|
235
239
|
const VERSION = "v1";
|
|
236
240
|
async function cloudApiFactory({ logger }, token) {
|
|
237
|
-
const localConfig = await getLocalConfig();
|
|
241
|
+
const localConfig = await getLocalConfig$1();
|
|
238
242
|
const customHeaders = {
|
|
239
243
|
"x-device-id": localConfig.deviceId,
|
|
240
244
|
"x-app-version": packageJson.version,
|
|
@@ -257,7 +261,7 @@ async function cloudApiFactory({ logger }, token) {
|
|
|
257
261
|
deploy({ filePath, project }, { onUploadProgress }) {
|
|
258
262
|
return axiosCloudAPI.post(
|
|
259
263
|
`/deploy/${project.name}`,
|
|
260
|
-
{ file: fse__default.createReadStream(filePath) },
|
|
264
|
+
{ file: fse__default.createReadStream(filePath), targetEnvironment: project.targetEnvironment },
|
|
261
265
|
{
|
|
262
266
|
headers: {
|
|
263
267
|
"Content-Type": "multipart/form-data"
|
|
@@ -328,6 +332,34 @@ async function cloudApiFactory({ logger }, token) {
|
|
|
328
332
|
throw error;
|
|
329
333
|
}
|
|
330
334
|
},
|
|
335
|
+
async listEnvironments({ name: name2 }) {
|
|
336
|
+
try {
|
|
337
|
+
const response = await axiosCloudAPI.get(`/projects/${name2}/environments`);
|
|
338
|
+
if (response.status !== 200) {
|
|
339
|
+
throw new Error("Error fetching cloud environments from the server.");
|
|
340
|
+
}
|
|
341
|
+
return response;
|
|
342
|
+
} catch (error) {
|
|
343
|
+
logger.debug(
|
|
344
|
+
"🥲 Oops! Couldn't retrieve your project's environments from the server. Please try again."
|
|
345
|
+
);
|
|
346
|
+
throw error;
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
async listLinkEnvironments({ name: name2 }) {
|
|
350
|
+
try {
|
|
351
|
+
const response = await axiosCloudAPI.get(`/projects/${name2}/environments-linkable`);
|
|
352
|
+
if (response.status !== 200) {
|
|
353
|
+
throw new Error("Error fetching cloud environments from the server.");
|
|
354
|
+
}
|
|
355
|
+
return response;
|
|
356
|
+
} catch (error) {
|
|
357
|
+
logger.debug(
|
|
358
|
+
"🥲 Oops! Couldn't retrieve your project's environments from the server. Please try again."
|
|
359
|
+
);
|
|
360
|
+
throw error;
|
|
361
|
+
}
|
|
362
|
+
},
|
|
331
363
|
async getProject({ name: name2 }) {
|
|
332
364
|
try {
|
|
333
365
|
const response = await axiosCloudAPI.get(`/projects/${name2}`);
|
|
@@ -351,26 +383,43 @@ async function cloudApiFactory({ logger }, token) {
|
|
|
351
383
|
};
|
|
352
384
|
}
|
|
353
385
|
const LOCAL_SAVE_FILENAME = ".strapi-cloud.json";
|
|
386
|
+
const getFilePath = (directoryPath) => path__default.join(directoryPath || process.cwd(), LOCAL_SAVE_FILENAME);
|
|
354
387
|
async function save(data, { directoryPath } = {}) {
|
|
355
|
-
const
|
|
356
|
-
const storedData = { ...alreadyInFileData, ...data };
|
|
357
|
-
const pathToFile = path__default.join(directoryPath || process.cwd(), LOCAL_SAVE_FILENAME);
|
|
388
|
+
const pathToFile = getFilePath(directoryPath);
|
|
358
389
|
await fse__default.ensureDir(path__default.dirname(pathToFile));
|
|
359
|
-
await fse__default.writeJson(pathToFile,
|
|
390
|
+
await fse__default.writeJson(pathToFile, data, { encoding: "utf8" });
|
|
360
391
|
}
|
|
361
392
|
async function retrieve({
|
|
362
393
|
directoryPath
|
|
363
394
|
} = {}) {
|
|
364
|
-
const pathToFile =
|
|
395
|
+
const pathToFile = getFilePath(directoryPath);
|
|
365
396
|
const pathExists = await fse__default.pathExists(pathToFile);
|
|
366
397
|
if (!pathExists) {
|
|
367
398
|
return {};
|
|
368
399
|
}
|
|
369
400
|
return fse__default.readJSON(pathToFile, { encoding: "utf8" });
|
|
370
401
|
}
|
|
402
|
+
async function patch(patchData, { directoryPath } = {}) {
|
|
403
|
+
const pathToFile = getFilePath(directoryPath);
|
|
404
|
+
const existingData = await retrieve({ directoryPath });
|
|
405
|
+
if (!existingData) {
|
|
406
|
+
throw new Error("No configuration data found to patch.");
|
|
407
|
+
}
|
|
408
|
+
const newData = merge(existingData, patchData);
|
|
409
|
+
await fse__default.writeJson(pathToFile, newData, { encoding: "utf8" });
|
|
410
|
+
}
|
|
411
|
+
async function deleteConfig({ directoryPath } = {}) {
|
|
412
|
+
const pathToFile = getFilePath(directoryPath);
|
|
413
|
+
const pathExists = await fse__default.pathExists(pathToFile);
|
|
414
|
+
if (pathExists) {
|
|
415
|
+
await fse__default.remove(pathToFile);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
371
418
|
const strapiInfoSave = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
372
419
|
__proto__: null,
|
|
373
420
|
LOCAL_SAVE_FILENAME,
|
|
421
|
+
deleteConfig,
|
|
422
|
+
patch,
|
|
374
423
|
retrieve,
|
|
375
424
|
save
|
|
376
425
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
@@ -378,7 +427,7 @@ let cliConfig;
|
|
|
378
427
|
async function tokenServiceFactory({ logger }) {
|
|
379
428
|
const cloudApiService = await cloudApiFactory({ logger });
|
|
380
429
|
async function saveToken(str) {
|
|
381
|
-
const appConfig = await getLocalConfig();
|
|
430
|
+
const appConfig = await getLocalConfig$1();
|
|
382
431
|
if (!appConfig) {
|
|
383
432
|
logger.error("There was a problem saving your token. Please try again.");
|
|
384
433
|
return;
|
|
@@ -392,7 +441,7 @@ async function tokenServiceFactory({ logger }) {
|
|
|
392
441
|
}
|
|
393
442
|
}
|
|
394
443
|
async function retrieveToken() {
|
|
395
|
-
const appConfig = await getLocalConfig();
|
|
444
|
+
const appConfig = await getLocalConfig$1();
|
|
396
445
|
if (appConfig.token) {
|
|
397
446
|
if (await isTokenValid(appConfig.token)) {
|
|
398
447
|
return appConfig.token;
|
|
@@ -454,7 +503,7 @@ async function tokenServiceFactory({ logger }) {
|
|
|
454
503
|
}
|
|
455
504
|
}
|
|
456
505
|
async function eraseToken() {
|
|
457
|
-
const appConfig = await getLocalConfig();
|
|
506
|
+
const appConfig = await getLocalConfig$1();
|
|
458
507
|
if (!appConfig) {
|
|
459
508
|
return;
|
|
460
509
|
}
|
|
@@ -615,21 +664,24 @@ yup.object({
|
|
|
615
664
|
name: yup.string().required(),
|
|
616
665
|
exports: yup.lazy(
|
|
617
666
|
(value) => yup.object(
|
|
618
|
-
typeof value === "object" ? Object.entries(value).reduce(
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
667
|
+
typeof value === "object" ? Object.entries(value).reduce(
|
|
668
|
+
(acc, [key, value2]) => {
|
|
669
|
+
if (typeof value2 === "object") {
|
|
670
|
+
acc[key] = yup.object({
|
|
671
|
+
types: yup.string().optional(),
|
|
672
|
+
source: yup.string().required(),
|
|
673
|
+
module: yup.string().optional(),
|
|
674
|
+
import: yup.string().required(),
|
|
675
|
+
require: yup.string().required(),
|
|
676
|
+
default: yup.string().required()
|
|
677
|
+
}).noUnknown(true);
|
|
678
|
+
} else {
|
|
679
|
+
acc[key] = yup.string().matches(/^\.\/.*\.json$/).required();
|
|
680
|
+
}
|
|
681
|
+
return acc;
|
|
682
|
+
},
|
|
683
|
+
{}
|
|
684
|
+
) : void 0
|
|
633
685
|
).optional()
|
|
634
686
|
)
|
|
635
687
|
});
|
|
@@ -897,7 +949,7 @@ async function createProject$1(ctx, cloudApi, projectInput) {
|
|
|
897
949
|
throw e;
|
|
898
950
|
}
|
|
899
951
|
}
|
|
900
|
-
const action$
|
|
952
|
+
const action$6 = async (ctx) => {
|
|
901
953
|
const { logger } = ctx;
|
|
902
954
|
const { getValidToken, eraseToken } = await tokenServiceFactory(ctx);
|
|
903
955
|
const token = await getValidToken(ctx, promptLogin);
|
|
@@ -1026,6 +1078,32 @@ const buildLogsServiceFactory = ({ logger }) => {
|
|
|
1026
1078
|
});
|
|
1027
1079
|
};
|
|
1028
1080
|
};
|
|
1081
|
+
const QUIT_OPTION$2 = "Quit";
|
|
1082
|
+
async function promptForEnvironment(environments) {
|
|
1083
|
+
const choices = environments.map((env2) => ({ name: env2, value: env2 }));
|
|
1084
|
+
const { selectedEnvironment } = await inquirer.prompt([
|
|
1085
|
+
{
|
|
1086
|
+
type: "list",
|
|
1087
|
+
name: "selectedEnvironment",
|
|
1088
|
+
message: "Select the environment to deploy:",
|
|
1089
|
+
choices: [...choices, { name: chalk.grey(`(${QUIT_OPTION$2})`), value: null }]
|
|
1090
|
+
}
|
|
1091
|
+
]);
|
|
1092
|
+
if (selectedEnvironment === null) {
|
|
1093
|
+
process.exit(1);
|
|
1094
|
+
}
|
|
1095
|
+
const { confirm } = await inquirer.prompt([
|
|
1096
|
+
{
|
|
1097
|
+
type: "confirm",
|
|
1098
|
+
name: "confirm",
|
|
1099
|
+
message: `Do you want to proceed with deployment to ${chalk.cyan(selectedEnvironment)}?`
|
|
1100
|
+
}
|
|
1101
|
+
]);
|
|
1102
|
+
if (!confirm) {
|
|
1103
|
+
process.exit(1);
|
|
1104
|
+
}
|
|
1105
|
+
return selectedEnvironment;
|
|
1106
|
+
}
|
|
1029
1107
|
async function upload(ctx, project, token, maxProjectFileSize) {
|
|
1030
1108
|
const cloudApi = await cloudApiFactory(ctx, token);
|
|
1031
1109
|
try {
|
|
@@ -1108,7 +1186,7 @@ async function getProject(ctx) {
|
|
|
1108
1186
|
const { project } = await retrieve();
|
|
1109
1187
|
if (!project) {
|
|
1110
1188
|
try {
|
|
1111
|
-
return await action$
|
|
1189
|
+
return await action$6(ctx);
|
|
1112
1190
|
} catch (e) {
|
|
1113
1191
|
ctx.logger.error("An error occurred while deploying the project. Please try again later.");
|
|
1114
1192
|
ctx.logger.debug(e);
|
|
@@ -1129,7 +1207,26 @@ async function getConfig({
|
|
|
1129
1207
|
return null;
|
|
1130
1208
|
}
|
|
1131
1209
|
}
|
|
1132
|
-
|
|
1210
|
+
function validateEnvironment(ctx, environment, environments) {
|
|
1211
|
+
if (!environments.includes(environment)) {
|
|
1212
|
+
ctx.logger.error(`Environment ${environment} does not exist.`);
|
|
1213
|
+
process.exit(1);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
async function getTargetEnvironment(ctx, opts, project, environments) {
|
|
1217
|
+
if (opts.env) {
|
|
1218
|
+
validateEnvironment(ctx, opts.env, environments);
|
|
1219
|
+
return opts.env;
|
|
1220
|
+
}
|
|
1221
|
+
if (project.targetEnvironment) {
|
|
1222
|
+
return project.targetEnvironment;
|
|
1223
|
+
}
|
|
1224
|
+
if (environments.length > 1) {
|
|
1225
|
+
return promptForEnvironment(environments);
|
|
1226
|
+
}
|
|
1227
|
+
return environments[0];
|
|
1228
|
+
}
|
|
1229
|
+
const action$5 = async (ctx, opts) => {
|
|
1133
1230
|
const { getValidToken } = await tokenServiceFactory(ctx);
|
|
1134
1231
|
const token = await getValidToken(ctx, promptLogin);
|
|
1135
1232
|
if (!token) {
|
|
@@ -1140,11 +1237,13 @@ const action$3 = async (ctx) => {
|
|
|
1140
1237
|
return;
|
|
1141
1238
|
}
|
|
1142
1239
|
const cloudApiService = await cloudApiFactory(ctx, token);
|
|
1240
|
+
let environments;
|
|
1143
1241
|
try {
|
|
1144
1242
|
const {
|
|
1145
1243
|
data: { data: projectData, metadata }
|
|
1146
1244
|
} = await cloudApiService.getProject({ name: project.name });
|
|
1147
1245
|
const isProjectSuspended = projectData.suspendedAt;
|
|
1246
|
+
environments = projectData.environments;
|
|
1148
1247
|
if (isProjectSuspended) {
|
|
1149
1248
|
ctx.logger.log(
|
|
1150
1249
|
"\n Oops! This project has been suspended. \n\n Please reactivate it from the dashboard to continue deploying: "
|
|
@@ -1191,11 +1290,15 @@ Please link your local project to an existing Strapi Cloud project using the ${c
|
|
|
1191
1290
|
);
|
|
1192
1291
|
maxSize = 1e8;
|
|
1193
1292
|
}
|
|
1293
|
+
project.targetEnvironment = await getTargetEnvironment(ctx, opts, project, environments);
|
|
1194
1294
|
const buildId = await upload(ctx, project, token, maxSize);
|
|
1195
1295
|
if (!buildId) {
|
|
1196
1296
|
return;
|
|
1197
1297
|
}
|
|
1198
1298
|
try {
|
|
1299
|
+
ctx.logger.log(
|
|
1300
|
+
`🚀 Deploying project to ${chalk.cyan(project.targetEnvironment ?? `production`)} environment...`
|
|
1301
|
+
);
|
|
1199
1302
|
notificationService(`${apiConfig.apiBaseUrl}/notifications`, token, cliConfig2);
|
|
1200
1303
|
await buildLogsService(`${apiConfig.apiBaseUrl}/v1/logs/${buildId}`, token, cliConfig2);
|
|
1201
1304
|
ctx.logger.log(
|
|
@@ -1240,17 +1343,16 @@ const runAction = (name2, action2) => (...args) => {
|
|
|
1240
1343
|
process.exit(1);
|
|
1241
1344
|
});
|
|
1242
1345
|
};
|
|
1243
|
-
const command$
|
|
1244
|
-
|
|
1346
|
+
const command$7 = ({ ctx }) => {
|
|
1347
|
+
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").option("-e, --env <name>", "Specify the environment to deploy").action((opts) => runAction("deploy", action$5)(ctx, opts));
|
|
1245
1348
|
};
|
|
1246
1349
|
const deployProject = {
|
|
1247
1350
|
name: "deploy-project",
|
|
1248
1351
|
description: "Deploy a Strapi Cloud project",
|
|
1249
|
-
action: action$
|
|
1250
|
-
command: command$
|
|
1352
|
+
action: action$5,
|
|
1353
|
+
command: command$7
|
|
1251
1354
|
};
|
|
1252
|
-
|
|
1253
|
-
async function getExistingConfig(ctx) {
|
|
1355
|
+
async function getLocalConfig(ctx) {
|
|
1254
1356
|
try {
|
|
1255
1357
|
return await retrieve();
|
|
1256
1358
|
} catch (e) {
|
|
@@ -1259,6 +1361,21 @@ async function getExistingConfig(ctx) {
|
|
|
1259
1361
|
return null;
|
|
1260
1362
|
}
|
|
1261
1363
|
}
|
|
1364
|
+
async function getLocalProject(ctx) {
|
|
1365
|
+
const localConfig = await getLocalConfig(ctx);
|
|
1366
|
+
if (!localConfig || !localConfig.project) {
|
|
1367
|
+
ctx.logger.warn(
|
|
1368
|
+
`
|
|
1369
|
+
We couldn't find a valid local project config.
|
|
1370
|
+
Please link your local project to an existing Strapi Cloud project using the ${chalk.cyan(
|
|
1371
|
+
"link"
|
|
1372
|
+
)} command.`
|
|
1373
|
+
);
|
|
1374
|
+
process.exit(1);
|
|
1375
|
+
}
|
|
1376
|
+
return localConfig.project;
|
|
1377
|
+
}
|
|
1378
|
+
const QUIT_OPTION$1 = "Quit";
|
|
1262
1379
|
async function promptForRelink(ctx, cloudApiService, existingConfig) {
|
|
1263
1380
|
if (existingConfig && existingConfig.project) {
|
|
1264
1381
|
const { shouldRelink } = await inquirer.prompt([
|
|
@@ -1288,7 +1405,7 @@ async function getProjectsList(ctx, cloudApiService, existingConfig) {
|
|
|
1288
1405
|
} = await cloudApiService.listLinkProjects();
|
|
1289
1406
|
spinner.succeed();
|
|
1290
1407
|
if (!Array.isArray(projectList)) {
|
|
1291
|
-
ctx.logger.log("We couldn't find any projects available for linking in Strapi Cloud");
|
|
1408
|
+
ctx.logger.log("We couldn't find any projects available for linking in Strapi Cloud.");
|
|
1292
1409
|
return null;
|
|
1293
1410
|
}
|
|
1294
1411
|
const projects = projectList.filter(
|
|
@@ -1300,7 +1417,7 @@ async function getProjectsList(ctx, cloudApiService, existingConfig) {
|
|
|
1300
1417
|
};
|
|
1301
1418
|
});
|
|
1302
1419
|
if (projects.length === 0) {
|
|
1303
|
-
ctx.logger.log("We couldn't find any projects available for linking in Strapi Cloud");
|
|
1420
|
+
ctx.logger.log("We couldn't find any projects available for linking in Strapi Cloud.");
|
|
1304
1421
|
return null;
|
|
1305
1422
|
}
|
|
1306
1423
|
return projects;
|
|
@@ -1318,7 +1435,7 @@ async function getUserSelection(ctx, projects) {
|
|
|
1318
1435
|
type: "list",
|
|
1319
1436
|
name: "linkProject",
|
|
1320
1437
|
message: "Which project do you want to link?",
|
|
1321
|
-
choices: [...projects, { name: chalk.grey(`(${QUIT_OPTION})`), value: null }]
|
|
1438
|
+
choices: [...projects, { name: chalk.grey(`(${QUIT_OPTION$1})`), value: null }]
|
|
1322
1439
|
}
|
|
1323
1440
|
]);
|
|
1324
1441
|
if (!answer.linkProject) {
|
|
@@ -1331,7 +1448,7 @@ async function getUserSelection(ctx, projects) {
|
|
|
1331
1448
|
return null;
|
|
1332
1449
|
}
|
|
1333
1450
|
}
|
|
1334
|
-
const action$
|
|
1451
|
+
const action$4 = async (ctx) => {
|
|
1335
1452
|
const { getValidToken } = await tokenServiceFactory(ctx);
|
|
1336
1453
|
const token = await getValidToken(ctx, promptLogin);
|
|
1337
1454
|
const { logger } = ctx;
|
|
@@ -1339,7 +1456,7 @@ const action$2 = async (ctx) => {
|
|
|
1339
1456
|
return;
|
|
1340
1457
|
}
|
|
1341
1458
|
const cloudApiService = await cloudApiFactory(ctx, token);
|
|
1342
|
-
const existingConfig = await
|
|
1459
|
+
const existingConfig = await getLocalConfig(ctx);
|
|
1343
1460
|
const shouldRelink = await promptForRelink(ctx, cloudApiService, existingConfig);
|
|
1344
1461
|
if (!shouldRelink) {
|
|
1345
1462
|
return;
|
|
@@ -1374,7 +1491,9 @@ const action$2 = async (ctx) => {
|
|
|
1374
1491
|
return;
|
|
1375
1492
|
}
|
|
1376
1493
|
await save({ project: answer.linkProject });
|
|
1377
|
-
logger.log(
|
|
1494
|
+
logger.log(
|
|
1495
|
+
` You have successfully linked your project to ${chalk.cyan(answer.linkProject.displayName)}. You are now able to deploy your project.`
|
|
1496
|
+
);
|
|
1378
1497
|
await trackEvent(ctx, cloudApiService, "didLinkProject", {
|
|
1379
1498
|
projectInternalName: answer.linkProject
|
|
1380
1499
|
});
|
|
@@ -1386,17 +1505,17 @@ const action$2 = async (ctx) => {
|
|
|
1386
1505
|
});
|
|
1387
1506
|
}
|
|
1388
1507
|
};
|
|
1389
|
-
const command$
|
|
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$
|
|
1508
|
+
const command$6 = ({ command: command2, ctx }) => {
|
|
1509
|
+
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$4)(ctx));
|
|
1391
1510
|
};
|
|
1392
1511
|
const link = {
|
|
1393
1512
|
name: "link-project",
|
|
1394
1513
|
description: "Link a local directory to a Strapi Cloud project",
|
|
1395
|
-
action: action$
|
|
1396
|
-
command: command$
|
|
1514
|
+
action: action$4,
|
|
1515
|
+
command: command$6
|
|
1397
1516
|
};
|
|
1398
|
-
const command$
|
|
1399
|
-
|
|
1517
|
+
const command$5 = ({ ctx }) => {
|
|
1518
|
+
return createCommand("cloud:login").alias("login").description("Strapi Cloud Login").addHelpText(
|
|
1400
1519
|
"after",
|
|
1401
1520
|
"\nAfter running this command, you will be prompted to enter your authentication information."
|
|
1402
1521
|
).option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("login", loginAction)(ctx));
|
|
@@ -1405,10 +1524,10 @@ const login = {
|
|
|
1405
1524
|
name: "login",
|
|
1406
1525
|
description: "Strapi Cloud Login",
|
|
1407
1526
|
action: loginAction,
|
|
1408
|
-
command: command$
|
|
1527
|
+
command: command$5
|
|
1409
1528
|
};
|
|
1410
1529
|
const openModule = import("open");
|
|
1411
|
-
const action$
|
|
1530
|
+
const action$3 = async (ctx) => {
|
|
1412
1531
|
const { logger } = ctx;
|
|
1413
1532
|
const { retrieveToken, eraseToken } = await tokenServiceFactory(ctx);
|
|
1414
1533
|
const token = await retrieveToken();
|
|
@@ -1440,25 +1559,25 @@ const action$1 = async (ctx) => {
|
|
|
1440
1559
|
}
|
|
1441
1560
|
await trackEvent(ctx, cloudApiService, "didLogout", { loginMethod: "cli" });
|
|
1442
1561
|
};
|
|
1443
|
-
const command$
|
|
1444
|
-
|
|
1562
|
+
const command$4 = ({ ctx }) => {
|
|
1563
|
+
return createCommand("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$3)(ctx));
|
|
1445
1564
|
};
|
|
1446
1565
|
const logout = {
|
|
1447
1566
|
name: "logout",
|
|
1448
1567
|
description: "Strapi Cloud Logout",
|
|
1449
|
-
action: action$
|
|
1450
|
-
command: command$
|
|
1568
|
+
action: action$3,
|
|
1569
|
+
command: command$4
|
|
1451
1570
|
};
|
|
1452
|
-
const command$
|
|
1453
|
-
|
|
1571
|
+
const command$3 = ({ ctx }) => {
|
|
1572
|
+
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$6)(ctx));
|
|
1454
1573
|
};
|
|
1455
1574
|
const createProject = {
|
|
1456
1575
|
name: "create-project",
|
|
1457
1576
|
description: "Create a new project",
|
|
1458
|
-
action: action$
|
|
1459
|
-
command: command$
|
|
1577
|
+
action: action$6,
|
|
1578
|
+
command: command$3
|
|
1460
1579
|
};
|
|
1461
|
-
const action = async (ctx) => {
|
|
1580
|
+
const action$2 = async (ctx) => {
|
|
1462
1581
|
const { getValidToken } = await tokenServiceFactory(ctx);
|
|
1463
1582
|
const token = await getValidToken(ctx, promptLogin);
|
|
1464
1583
|
const { logger } = ctx;
|
|
@@ -1478,12 +1597,194 @@ const action = async (ctx) => {
|
|
|
1478
1597
|
spinner.fail("An error occurred while fetching your projects from Strapi Cloud.");
|
|
1479
1598
|
}
|
|
1480
1599
|
};
|
|
1481
|
-
const command = ({ command: command2, ctx }) => {
|
|
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));
|
|
1600
|
+
const command$2 = ({ command: command2, ctx }) => {
|
|
1601
|
+
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$2)(ctx));
|
|
1483
1602
|
};
|
|
1484
1603
|
const listProjects = {
|
|
1485
1604
|
name: "list-projects",
|
|
1486
1605
|
description: "List Strapi Cloud projects",
|
|
1606
|
+
action: action$2,
|
|
1607
|
+
command: command$2
|
|
1608
|
+
};
|
|
1609
|
+
const action$1 = async (ctx) => {
|
|
1610
|
+
const { getValidToken } = await tokenServiceFactory(ctx);
|
|
1611
|
+
const token = await getValidToken(ctx, promptLogin);
|
|
1612
|
+
const { logger } = ctx;
|
|
1613
|
+
if (!token) {
|
|
1614
|
+
return;
|
|
1615
|
+
}
|
|
1616
|
+
const project = await getLocalProject(ctx);
|
|
1617
|
+
if (!project) {
|
|
1618
|
+
ctx.logger.debug(`No valid local project configuration was found.`);
|
|
1619
|
+
return;
|
|
1620
|
+
}
|
|
1621
|
+
const cloudApiService = await cloudApiFactory(ctx, token);
|
|
1622
|
+
const spinner = logger.spinner("Fetching environments...").start();
|
|
1623
|
+
await trackEvent(ctx, cloudApiService, "willListEnvironment", {
|
|
1624
|
+
projectInternalName: project.name
|
|
1625
|
+
});
|
|
1626
|
+
try {
|
|
1627
|
+
const {
|
|
1628
|
+
data: { data: environmentsList }
|
|
1629
|
+
} = await cloudApiService.listEnvironments({ name: project.name });
|
|
1630
|
+
spinner.succeed();
|
|
1631
|
+
logger.log(environmentsList);
|
|
1632
|
+
await trackEvent(ctx, cloudApiService, "didListEnvironment", {
|
|
1633
|
+
projectInternalName: project.name
|
|
1634
|
+
});
|
|
1635
|
+
} catch (e) {
|
|
1636
|
+
if (e.response && e.response.status === 404) {
|
|
1637
|
+
spinner.succeed();
|
|
1638
|
+
logger.warn(
|
|
1639
|
+
`
|
|
1640
|
+
The project associated with this folder does not exist in Strapi Cloud.
|
|
1641
|
+
Please link your local project to an existing Strapi Cloud project using the ${chalk.cyan(
|
|
1642
|
+
"link"
|
|
1643
|
+
)} command`
|
|
1644
|
+
);
|
|
1645
|
+
} else {
|
|
1646
|
+
spinner.fail("An error occurred while fetching environments data from Strapi Cloud.");
|
|
1647
|
+
logger.debug("Failed to list environments", e);
|
|
1648
|
+
}
|
|
1649
|
+
await trackEvent(ctx, cloudApiService, "didNotListEnvironment", {
|
|
1650
|
+
projectInternalName: project.name
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
};
|
|
1654
|
+
function defineCloudNamespace(command2, ctx) {
|
|
1655
|
+
const cloud = command2.command("cloud").description("Manage Strapi Cloud projects");
|
|
1656
|
+
cloud.command("environments").description("Alias for cloud environment list").action(() => runAction("list", action$1)(ctx));
|
|
1657
|
+
return cloud;
|
|
1658
|
+
}
|
|
1659
|
+
let environmentCmd = null;
|
|
1660
|
+
const initializeEnvironmentCommand = (command2, ctx) => {
|
|
1661
|
+
if (!environmentCmd) {
|
|
1662
|
+
const cloud = defineCloudNamespace(command2, ctx);
|
|
1663
|
+
environmentCmd = cloud.command("environment").description("Manage environments");
|
|
1664
|
+
}
|
|
1665
|
+
return environmentCmd;
|
|
1666
|
+
};
|
|
1667
|
+
const command$1 = ({ command: command2, ctx }) => {
|
|
1668
|
+
const environmentCmd2 = initializeEnvironmentCommand(command2, ctx);
|
|
1669
|
+
environmentCmd2.command("list").description("List Strapi Cloud project environments").option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("list", action$1)(ctx));
|
|
1670
|
+
};
|
|
1671
|
+
const listEnvironments = {
|
|
1672
|
+
name: "list-environments",
|
|
1673
|
+
description: "List Strapi Cloud environments",
|
|
1674
|
+
action: action$1,
|
|
1675
|
+
command: command$1
|
|
1676
|
+
};
|
|
1677
|
+
const QUIT_OPTION = "Quit";
|
|
1678
|
+
const action = async (ctx) => {
|
|
1679
|
+
const { getValidToken } = await tokenServiceFactory(ctx);
|
|
1680
|
+
const token = await getValidToken(ctx, promptLogin);
|
|
1681
|
+
const { logger } = ctx;
|
|
1682
|
+
if (!token) {
|
|
1683
|
+
return;
|
|
1684
|
+
}
|
|
1685
|
+
const project = await getLocalProject(ctx);
|
|
1686
|
+
if (!project) {
|
|
1687
|
+
logger.debug(`No valid local project configuration was found.`);
|
|
1688
|
+
return;
|
|
1689
|
+
}
|
|
1690
|
+
const cloudApiService = await cloudApiFactory(ctx, token);
|
|
1691
|
+
const environments = await getEnvironmentsList(ctx, cloudApiService, project);
|
|
1692
|
+
if (!environments) {
|
|
1693
|
+
logger.debug(`Fetching environments failed.`);
|
|
1694
|
+
return;
|
|
1695
|
+
}
|
|
1696
|
+
if (environments.length === 0) {
|
|
1697
|
+
logger.log(
|
|
1698
|
+
`The only available environment is already linked. You can add a new one from your project settings on the Strapi Cloud dashboard.`
|
|
1699
|
+
);
|
|
1700
|
+
return;
|
|
1701
|
+
}
|
|
1702
|
+
const answer = await promptUserForEnvironment(ctx, environments);
|
|
1703
|
+
if (!answer) {
|
|
1704
|
+
return;
|
|
1705
|
+
}
|
|
1706
|
+
await trackEvent(ctx, cloudApiService, "willLinkEnvironment", {
|
|
1707
|
+
projectName: project.name,
|
|
1708
|
+
environmentName: answer.targetEnvironment
|
|
1709
|
+
});
|
|
1710
|
+
try {
|
|
1711
|
+
await patch({ project: { targetEnvironment: answer.targetEnvironment } });
|
|
1712
|
+
} catch (e) {
|
|
1713
|
+
await trackEvent(ctx, cloudApiService, "didNotLinkEnvironment", {
|
|
1714
|
+
projectName: project.name,
|
|
1715
|
+
environmentName: answer.targetEnvironment
|
|
1716
|
+
});
|
|
1717
|
+
logger.debug("Failed to link environment", e);
|
|
1718
|
+
logger.error(
|
|
1719
|
+
"Failed to link the environment. If this issue persists, try re-linking your project or contact support."
|
|
1720
|
+
);
|
|
1721
|
+
process.exit(1);
|
|
1722
|
+
}
|
|
1723
|
+
logger.log(
|
|
1724
|
+
` You have successfully linked your project to ${chalk.cyan(answer.targetEnvironment)}, on ${chalk.cyan(project.displayName)}. You are now able to deploy your project.`
|
|
1725
|
+
);
|
|
1726
|
+
await trackEvent(ctx, cloudApiService, "didLinkEnvironment", {
|
|
1727
|
+
projectName: project.name,
|
|
1728
|
+
environmentName: answer.targetEnvironment
|
|
1729
|
+
});
|
|
1730
|
+
};
|
|
1731
|
+
async function promptUserForEnvironment(ctx, environments) {
|
|
1732
|
+
const { logger } = ctx;
|
|
1733
|
+
try {
|
|
1734
|
+
const answer = await inquirer.prompt([
|
|
1735
|
+
{
|
|
1736
|
+
type: "list",
|
|
1737
|
+
name: "targetEnvironment",
|
|
1738
|
+
message: "Which environment do you want to link?",
|
|
1739
|
+
choices: [...environments, { name: chalk.grey(`(${QUIT_OPTION})`), value: null }]
|
|
1740
|
+
}
|
|
1741
|
+
]);
|
|
1742
|
+
if (!answer.targetEnvironment) {
|
|
1743
|
+
return null;
|
|
1744
|
+
}
|
|
1745
|
+
return answer;
|
|
1746
|
+
} catch (e) {
|
|
1747
|
+
logger.debug("Failed to get user input", e);
|
|
1748
|
+
logger.error("An error occurred while trying to get your environment selection.");
|
|
1749
|
+
return null;
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
async function getEnvironmentsList(ctx, cloudApiService, project) {
|
|
1753
|
+
const spinner = ctx.logger.spinner("Fetching environments...\n").start();
|
|
1754
|
+
try {
|
|
1755
|
+
const {
|
|
1756
|
+
data: { data: environmentsList }
|
|
1757
|
+
} = await cloudApiService.listLinkEnvironments({ name: project.name });
|
|
1758
|
+
if (!Array.isArray(environmentsList) || environmentsList.length === 0) {
|
|
1759
|
+
throw new Error("Environments not found in server response");
|
|
1760
|
+
}
|
|
1761
|
+
spinner.succeed();
|
|
1762
|
+
return environmentsList.filter(
|
|
1763
|
+
(environment) => environment.name !== project.targetEnvironment
|
|
1764
|
+
);
|
|
1765
|
+
} catch (e) {
|
|
1766
|
+
if (e.response && e.response.status === 404) {
|
|
1767
|
+
spinner.succeed();
|
|
1768
|
+
ctx.logger.warn(
|
|
1769
|
+
`
|
|
1770
|
+
The project associated with this folder does not exist in Strapi Cloud.
|
|
1771
|
+
Please link your local project to an existing Strapi Cloud project using the ${chalk.cyan(
|
|
1772
|
+
"link"
|
|
1773
|
+
)} command.`
|
|
1774
|
+
);
|
|
1775
|
+
} else {
|
|
1776
|
+
spinner.fail("An error occurred while fetching environments data from Strapi Cloud.");
|
|
1777
|
+
ctx.logger.debug("Failed to list environments", e);
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
const command = ({ command: command2, ctx }) => {
|
|
1782
|
+
const environmentCmd2 = initializeEnvironmentCommand(command2, ctx);
|
|
1783
|
+
environmentCmd2.command("link").description("Link project to a specific Strapi Cloud project environment").option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("link", action)(ctx));
|
|
1784
|
+
};
|
|
1785
|
+
const linkEnvironment = {
|
|
1786
|
+
name: "link-environment",
|
|
1787
|
+
description: "Link Strapi Cloud environment to a local project",
|
|
1487
1788
|
action,
|
|
1488
1789
|
command
|
|
1489
1790
|
};
|
|
@@ -1493,11 +1794,21 @@ const cli = {
|
|
|
1493
1794
|
login,
|
|
1494
1795
|
logout,
|
|
1495
1796
|
createProject,
|
|
1496
|
-
|
|
1797
|
+
linkEnvironment,
|
|
1798
|
+
listProjects,
|
|
1799
|
+
listEnvironments
|
|
1497
1800
|
};
|
|
1498
|
-
const cloudCommands = [
|
|
1801
|
+
const cloudCommands = [
|
|
1802
|
+
deployProject,
|
|
1803
|
+
link,
|
|
1804
|
+
login,
|
|
1805
|
+
logout,
|
|
1806
|
+
linkEnvironment,
|
|
1807
|
+
listProjects,
|
|
1808
|
+
listEnvironments
|
|
1809
|
+
];
|
|
1499
1810
|
async function initCloudCLIConfig() {
|
|
1500
|
-
const localConfig = await getLocalConfig();
|
|
1811
|
+
const localConfig = await getLocalConfig$1();
|
|
1501
1812
|
if (!localConfig.deviceId) {
|
|
1502
1813
|
localConfig.deviceId = crypto$1.randomUUID();
|
|
1503
1814
|
}
|
|
@@ -1511,7 +1822,10 @@ async function buildStrapiCloudCommands({
|
|
|
1511
1822
|
await initCloudCLIConfig();
|
|
1512
1823
|
for (const cloudCommand of cloudCommands) {
|
|
1513
1824
|
try {
|
|
1514
|
-
await cloudCommand.command({ command: command2, ctx, argv });
|
|
1825
|
+
const subCommand = await cloudCommand.command({ command: command2, ctx, argv });
|
|
1826
|
+
if (subCommand) {
|
|
1827
|
+
command2.addCommand(subCommand);
|
|
1828
|
+
}
|
|
1515
1829
|
} catch (e) {
|
|
1516
1830
|
console.error(`Failed to load command ${cloudCommand.name}`, e);
|
|
1517
1831
|
}
|