@strapi/cloud-cli 0.0.0-next.84f5cfd43cfdb85f000d388b196a36d874382dab → 0.0.0-next.a237dfc081ee4788ee5abb71a735161aebec0ee5
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 +397 -134
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +397 -131
- package/dist/index.mjs.map +1 -1
- package/dist/src/create-project/action.d.ts.map +1 -1
- package/dist/src/create-project/utils/get-project-name-from-pkg.d.ts +3 -0
- package/dist/src/create-project/utils/get-project-name-from-pkg.d.ts.map +1 -0
- 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 +2 -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/list-projects/action.d.ts +4 -0
- package/dist/src/list-projects/action.d.ts.map +1 -0
- package/dist/src/list-projects/command.d.ts +7 -0
- package/dist/src/list-projects/command.d.ts.map +1 -0
- package/dist/src/list-projects/index.d.ts +7 -0
- package/dist/src/list-projects/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 +19 -7
- 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/dist/src/utils/compress-files.d.ts.map +1 -1
- package/dist/src/utils/pkg.d.ts.map +1 -1
- package/package.json +6 -5
- package/dist/src/utils/tests/compress-files.test.d.ts +0 -2
- package/dist/src/utils/tests/compress-files.test.d.ts.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import crypto$1 from "crypto";
|
|
2
|
-
import fse from "fs-extra";
|
|
2
|
+
import * as fse from "fs-extra";
|
|
3
|
+
import fse__default from "fs-extra";
|
|
3
4
|
import * as path from "path";
|
|
4
5
|
import path__default from "path";
|
|
5
6
|
import chalk from "chalk";
|
|
6
7
|
import axios, { AxiosError } from "axios";
|
|
7
8
|
import * as crypto from "node:crypto";
|
|
8
9
|
import { env } from "@strapi/utils";
|
|
9
|
-
import * as fs from "fs";
|
|
10
10
|
import * as tar from "tar";
|
|
11
11
|
import { minimatch } from "minimatch";
|
|
12
12
|
import inquirer from "inquirer";
|
|
@@ -18,10 +18,9 @@ import jwt from "jsonwebtoken";
|
|
|
18
18
|
import stringify from "fast-safe-stringify";
|
|
19
19
|
import ora from "ora";
|
|
20
20
|
import * as cliProgress from "cli-progress";
|
|
21
|
-
import EventSource from "eventsource";
|
|
22
|
-
import fs$1 from "fs/promises";
|
|
23
21
|
import pkgUp from "pkg-up";
|
|
24
22
|
import * as yup from "yup";
|
|
23
|
+
import EventSource from "eventsource";
|
|
25
24
|
const apiConfig = {
|
|
26
25
|
apiBaseUrl: env("STRAPI_CLI_CLOUD_API", "https://cloud-cli-api.strapi.io"),
|
|
27
26
|
dashboardBaseUrl: env("STRAPI_CLI_CLOUD_DASHBOARD", "https://cloud.strapi.io")
|
|
@@ -40,23 +39,6 @@ const IGNORED_PATTERNS = [
|
|
|
40
39
|
"**/.idea/**",
|
|
41
40
|
"**/.vscode/**"
|
|
42
41
|
];
|
|
43
|
-
const getFiles = (dirPath, ignorePatterns = [], arrayOfFiles = [], subfolder = "") => {
|
|
44
|
-
const entries = fs.readdirSync(path.join(dirPath, subfolder));
|
|
45
|
-
entries.forEach((entry) => {
|
|
46
|
-
const entryPathFromRoot = path.join(subfolder, entry);
|
|
47
|
-
const entryPath = path.relative(dirPath, entryPathFromRoot);
|
|
48
|
-
const isIgnored = isIgnoredFile(dirPath, entryPathFromRoot, ignorePatterns);
|
|
49
|
-
if (isIgnored) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
if (fs.statSync(entryPath).isDirectory()) {
|
|
53
|
-
getFiles(dirPath, ignorePatterns, arrayOfFiles, entryPathFromRoot);
|
|
54
|
-
} else {
|
|
55
|
-
arrayOfFiles.push(entryPath);
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
return arrayOfFiles;
|
|
59
|
-
};
|
|
60
42
|
const isIgnoredFile = (folderPath, file, ignorePatterns) => {
|
|
61
43
|
ignorePatterns.push(...IGNORED_PATTERNS);
|
|
62
44
|
const relativeFilePath = path.join(folderPath, file);
|
|
@@ -74,16 +56,35 @@ const isIgnoredFile = (folderPath, file, ignorePatterns) => {
|
|
|
74
56
|
}
|
|
75
57
|
return isIgnored;
|
|
76
58
|
};
|
|
77
|
-
const
|
|
59
|
+
const getFiles = async (dirPath, ignorePatterns = [], subfolder = "") => {
|
|
60
|
+
const arrayOfFiles = [];
|
|
61
|
+
const entries = await fse.readdir(path.join(dirPath, subfolder));
|
|
62
|
+
for (const entry of entries) {
|
|
63
|
+
const entryPathFromRoot = path.join(subfolder, entry);
|
|
64
|
+
const entryPath = path.relative(dirPath, entryPathFromRoot);
|
|
65
|
+
const isIgnored = isIgnoredFile(dirPath, entryPathFromRoot, ignorePatterns);
|
|
66
|
+
if (!isIgnored) {
|
|
67
|
+
if (fse.statSync(entryPath).isDirectory()) {
|
|
68
|
+
const subFiles = await getFiles(dirPath, ignorePatterns, entryPathFromRoot);
|
|
69
|
+
arrayOfFiles.push(...subFiles);
|
|
70
|
+
} else {
|
|
71
|
+
arrayOfFiles.push(entryPath);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return arrayOfFiles;
|
|
76
|
+
};
|
|
77
|
+
const readGitignore = async (folderPath) => {
|
|
78
78
|
const gitignorePath = path.resolve(folderPath, ".gitignore");
|
|
79
|
-
|
|
79
|
+
const pathExist = await fse.pathExists(gitignorePath);
|
|
80
|
+
if (!pathExist)
|
|
80
81
|
return [];
|
|
81
|
-
const gitignoreContent =
|
|
82
|
+
const gitignoreContent = await fse.readFile(gitignorePath, "utf8");
|
|
82
83
|
return gitignoreContent.split(/\r?\n/).filter((line) => Boolean(line.trim()) && !line.startsWith("#"));
|
|
83
84
|
};
|
|
84
85
|
const compressFilesToTar = async (storagePath, folderToCompress, filename) => {
|
|
85
|
-
const ignorePatterns = readGitignore(folderToCompress);
|
|
86
|
-
const filesToCompress = getFiles(folderToCompress, ignorePatterns);
|
|
86
|
+
const ignorePatterns = await readGitignore(folderToCompress);
|
|
87
|
+
const filesToCompress = await getFiles(folderToCompress, ignorePatterns);
|
|
87
88
|
return tar.c(
|
|
88
89
|
{
|
|
89
90
|
gzip: true,
|
|
@@ -96,7 +97,7 @@ const APP_FOLDER_NAME = "com.strapi.cli";
|
|
|
96
97
|
const CONFIG_FILENAME = "config.json";
|
|
97
98
|
async function checkDirectoryExists(directoryPath) {
|
|
98
99
|
try {
|
|
99
|
-
const fsStat = await
|
|
100
|
+
const fsStat = await fse__default.lstat(directoryPath);
|
|
100
101
|
return fsStat.isDirectory();
|
|
101
102
|
} catch (e) {
|
|
102
103
|
return false;
|
|
@@ -104,14 +105,14 @@ async function checkDirectoryExists(directoryPath) {
|
|
|
104
105
|
}
|
|
105
106
|
async function getTmpStoragePath() {
|
|
106
107
|
const storagePath = path__default.join(os.tmpdir(), APP_FOLDER_NAME);
|
|
107
|
-
await
|
|
108
|
+
await fse__default.ensureDir(storagePath);
|
|
108
109
|
return storagePath;
|
|
109
110
|
}
|
|
110
111
|
async function getConfigPath() {
|
|
111
112
|
const configDirs = XDGAppPaths(APP_FOLDER_NAME).configDirs();
|
|
112
113
|
const configPath = configDirs.find(checkDirectoryExists);
|
|
113
114
|
if (!configPath) {
|
|
114
|
-
await
|
|
115
|
+
await fse__default.ensureDir(configDirs[0]);
|
|
115
116
|
return configDirs[0];
|
|
116
117
|
}
|
|
117
118
|
return configPath;
|
|
@@ -119,9 +120,9 @@ async function getConfigPath() {
|
|
|
119
120
|
async function getLocalConfig() {
|
|
120
121
|
const configPath = await getConfigPath();
|
|
121
122
|
const configFilePath = path__default.join(configPath, CONFIG_FILENAME);
|
|
122
|
-
await
|
|
123
|
+
await fse__default.ensureFile(configFilePath);
|
|
123
124
|
try {
|
|
124
|
-
return await
|
|
125
|
+
return await fse__default.readJSON(configFilePath, { encoding: "utf8", throws: true });
|
|
125
126
|
} catch (e) {
|
|
126
127
|
return {};
|
|
127
128
|
}
|
|
@@ -129,10 +130,10 @@ async function getLocalConfig() {
|
|
|
129
130
|
async function saveLocalConfig(data) {
|
|
130
131
|
const configPath = await getConfigPath();
|
|
131
132
|
const configFilePath = path__default.join(configPath, CONFIG_FILENAME);
|
|
132
|
-
await
|
|
133
|
+
await fse__default.writeJson(configFilePath, data, { encoding: "utf8", spaces: 2, mode: 384 });
|
|
133
134
|
}
|
|
134
135
|
const name = "@strapi/cloud-cli";
|
|
135
|
-
const version = "4.25.
|
|
136
|
+
const version = "4.25.8";
|
|
136
137
|
const description = "Commands to interact with the Strapi Cloud";
|
|
137
138
|
const keywords = [
|
|
138
139
|
"strapi",
|
|
@@ -173,10 +174,11 @@ const scripts = {
|
|
|
173
174
|
build: "pack-up build",
|
|
174
175
|
clean: "run -T rimraf ./dist",
|
|
175
176
|
lint: "run -T eslint .",
|
|
177
|
+
"test:unit": "run -T jest",
|
|
176
178
|
watch: "pack-up watch"
|
|
177
179
|
};
|
|
178
180
|
const dependencies = {
|
|
179
|
-
"@strapi/utils": "4.25.
|
|
181
|
+
"@strapi/utils": "4.25.8",
|
|
180
182
|
axios: "1.6.0",
|
|
181
183
|
chalk: "4.1.2",
|
|
182
184
|
"cli-progress": "3.12.0",
|
|
@@ -201,8 +203,8 @@ const devDependencies = {
|
|
|
201
203
|
"@types/cli-progress": "3.11.5",
|
|
202
204
|
"@types/eventsource": "1.1.15",
|
|
203
205
|
"@types/lodash": "^4.14.191",
|
|
204
|
-
"eslint-config-custom": "4.25.
|
|
205
|
-
tsconfig: "4.25.
|
|
206
|
+
"eslint-config-custom": "4.25.8",
|
|
207
|
+
tsconfig: "4.25.8"
|
|
206
208
|
};
|
|
207
209
|
const engines = {
|
|
208
210
|
node: ">=18.0.0 <=20.x.x",
|
|
@@ -255,7 +257,7 @@ async function cloudApiFactory({ logger }, token) {
|
|
|
255
257
|
deploy({ filePath, project }, { onUploadProgress }) {
|
|
256
258
|
return axiosCloudAPI.post(
|
|
257
259
|
`/deploy/${project.name}`,
|
|
258
|
-
{ file:
|
|
260
|
+
{ file: fse__default.createReadStream(filePath) },
|
|
259
261
|
{
|
|
260
262
|
headers: {
|
|
261
263
|
"Content-Type": "multipart/form-data"
|
|
@@ -298,8 +300,33 @@ async function cloudApiFactory({ logger }, token) {
|
|
|
298
300
|
throw error;
|
|
299
301
|
}
|
|
300
302
|
},
|
|
301
|
-
listProjects() {
|
|
302
|
-
|
|
303
|
+
async listProjects() {
|
|
304
|
+
try {
|
|
305
|
+
const response = await axiosCloudAPI.get("/projects");
|
|
306
|
+
if (response.status !== 200) {
|
|
307
|
+
throw new Error("Error fetching cloud projects from the server.");
|
|
308
|
+
}
|
|
309
|
+
return response;
|
|
310
|
+
} catch (error) {
|
|
311
|
+
logger.debug(
|
|
312
|
+
"🥲 Oops! Couldn't retrieve your project's list from the server. Please try again."
|
|
313
|
+
);
|
|
314
|
+
throw error;
|
|
315
|
+
}
|
|
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
|
+
}
|
|
303
330
|
},
|
|
304
331
|
track(event, payload = {}) {
|
|
305
332
|
return axiosCloudAPI.post("/track", {
|
|
@@ -314,18 +341,18 @@ async function save(data, { directoryPath } = {}) {
|
|
|
314
341
|
const alreadyInFileData = await retrieve({ directoryPath });
|
|
315
342
|
const storedData = { ...alreadyInFileData, ...data };
|
|
316
343
|
const pathToFile = path__default.join(directoryPath || process.cwd(), LOCAL_SAVE_FILENAME);
|
|
317
|
-
await
|
|
318
|
-
await
|
|
344
|
+
await fse__default.ensureDir(path__default.dirname(pathToFile));
|
|
345
|
+
await fse__default.writeJson(pathToFile, storedData, { encoding: "utf8" });
|
|
319
346
|
}
|
|
320
347
|
async function retrieve({
|
|
321
348
|
directoryPath
|
|
322
349
|
} = {}) {
|
|
323
350
|
const pathToFile = path__default.join(directoryPath || process.cwd(), LOCAL_SAVE_FILENAME);
|
|
324
|
-
const pathExists = await
|
|
351
|
+
const pathExists = await fse__default.pathExists(pathToFile);
|
|
325
352
|
if (!pathExists) {
|
|
326
353
|
return {};
|
|
327
354
|
}
|
|
328
|
-
return
|
|
355
|
+
return fse__default.readJSON(pathToFile, { encoding: "utf8" });
|
|
329
356
|
}
|
|
330
357
|
const strapiInfoSave = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
331
358
|
__proto__: null,
|
|
@@ -570,6 +597,53 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
|
|
|
570
597
|
local: strapiInfoSave,
|
|
571
598
|
tokenServiceFactory
|
|
572
599
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
600
|
+
yup.object({
|
|
601
|
+
name: yup.string().required(),
|
|
602
|
+
exports: yup.lazy(
|
|
603
|
+
(value) => yup.object(
|
|
604
|
+
typeof value === "object" ? Object.entries(value).reduce((acc, [key, value2]) => {
|
|
605
|
+
if (typeof value2 === "object") {
|
|
606
|
+
acc[key] = yup.object({
|
|
607
|
+
types: yup.string().optional(),
|
|
608
|
+
source: yup.string().required(),
|
|
609
|
+
module: yup.string().optional(),
|
|
610
|
+
import: yup.string().required(),
|
|
611
|
+
require: yup.string().required(),
|
|
612
|
+
default: yup.string().required()
|
|
613
|
+
}).noUnknown(true);
|
|
614
|
+
} else {
|
|
615
|
+
acc[key] = yup.string().matches(/^\.\/.*\.json$/).required();
|
|
616
|
+
}
|
|
617
|
+
return acc;
|
|
618
|
+
}, {}) : void 0
|
|
619
|
+
).optional()
|
|
620
|
+
)
|
|
621
|
+
});
|
|
622
|
+
const loadPkg = async ({ cwd, logger }) => {
|
|
623
|
+
const pkgPath = await pkgUp({ cwd });
|
|
624
|
+
if (!pkgPath) {
|
|
625
|
+
throw new Error("Could not find a package.json in the current directory");
|
|
626
|
+
}
|
|
627
|
+
const buffer = await fse.readFile(pkgPath);
|
|
628
|
+
const pkg = JSON.parse(buffer.toString());
|
|
629
|
+
logger.debug("Loaded package.json:", os.EOL, pkg);
|
|
630
|
+
return pkg;
|
|
631
|
+
};
|
|
632
|
+
async function getProjectNameFromPackageJson(ctx) {
|
|
633
|
+
try {
|
|
634
|
+
const packageJson2 = await loadPkg(ctx);
|
|
635
|
+
return packageJson2.name || "my-strapi-project";
|
|
636
|
+
} catch (e) {
|
|
637
|
+
return "my-strapi-project";
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
const trackEvent = async (ctx, cloudApiService, eventName, eventData) => {
|
|
641
|
+
try {
|
|
642
|
+
await cloudApiService.track(eventName, eventData);
|
|
643
|
+
} catch (e) {
|
|
644
|
+
ctx.logger.debug(`Failed to track ${eventName}`, e);
|
|
645
|
+
}
|
|
646
|
+
};
|
|
573
647
|
const openModule$1 = import("open");
|
|
574
648
|
async function promptLogin(ctx) {
|
|
575
649
|
const response = await inquirer.prompt([
|
|
@@ -590,13 +664,6 @@ async function loginAction(ctx) {
|
|
|
590
664
|
const tokenService = await tokenServiceFactory(ctx);
|
|
591
665
|
const existingToken = await tokenService.retrieveToken();
|
|
592
666
|
const cloudApiService = await cloudApiFactory(ctx, existingToken || void 0);
|
|
593
|
-
const trackFailedLogin = async () => {
|
|
594
|
-
try {
|
|
595
|
-
await cloudApiService.track("didNotLogin", { loginMethod: "cli" });
|
|
596
|
-
} catch (e) {
|
|
597
|
-
logger.debug("Failed to track failed login", e);
|
|
598
|
-
}
|
|
599
|
-
};
|
|
600
667
|
if (existingToken) {
|
|
601
668
|
const isTokenValid = await tokenService.isTokenValid(existingToken);
|
|
602
669
|
if (isTokenValid) {
|
|
@@ -628,11 +695,7 @@ async function loginAction(ctx) {
|
|
|
628
695
|
logger.debug(e);
|
|
629
696
|
return false;
|
|
630
697
|
}
|
|
631
|
-
|
|
632
|
-
await cloudApiService.track("willLoginAttempt", {});
|
|
633
|
-
} catch (e) {
|
|
634
|
-
logger.debug("Failed to track login attempt", e);
|
|
635
|
-
}
|
|
698
|
+
await trackEvent(ctx, cloudApiService, "willLoginAttempt", {});
|
|
636
699
|
logger.debug("🔐 Creating device authentication request...", {
|
|
637
700
|
client_id: cliConfig2.clientId,
|
|
638
701
|
scope: cliConfig2.scope,
|
|
@@ -712,13 +775,13 @@ async function loginAction(ctx) {
|
|
|
712
775
|
"There seems to be a problem with your login information. Please try logging in again."
|
|
713
776
|
);
|
|
714
777
|
spinnerFail();
|
|
715
|
-
await
|
|
778
|
+
await trackEvent(ctx, cloudApiService, "didNotLogin", { loginMethod: "cli" });
|
|
716
779
|
return false;
|
|
717
780
|
}
|
|
718
781
|
if (e.response?.data.error && !["authorization_pending", "slow_down"].includes(e.response.data.error)) {
|
|
719
782
|
logger.debug(e);
|
|
720
783
|
spinnerFail();
|
|
721
|
-
await
|
|
784
|
+
await trackEvent(ctx, cloudApiService, "didNotLogin", { loginMethod: "cli" });
|
|
722
785
|
return false;
|
|
723
786
|
}
|
|
724
787
|
await new Promise((resolve) => {
|
|
@@ -732,15 +795,50 @@ async function loginAction(ctx) {
|
|
|
732
795
|
"To access your dashboard, please copy and paste the following URL into your web browser:"
|
|
733
796
|
);
|
|
734
797
|
logger.log(chalk.underline(`${apiConfig.dashboardBaseUrl}/projects`));
|
|
735
|
-
|
|
736
|
-
await cloudApiService.track("didLogin", { loginMethod: "cli" });
|
|
737
|
-
} catch (e) {
|
|
738
|
-
logger.debug("Failed to track login", e);
|
|
739
|
-
}
|
|
798
|
+
await trackEvent(ctx, cloudApiService, "didLogin", { loginMethod: "cli" });
|
|
740
799
|
};
|
|
741
800
|
await authenticate();
|
|
742
801
|
return isAuthenticated;
|
|
743
802
|
}
|
|
803
|
+
function questionDefaultValuesMapper(questionsMap) {
|
|
804
|
+
return (questions) => {
|
|
805
|
+
return questions.map((question) => {
|
|
806
|
+
const questionName = question.name;
|
|
807
|
+
if (questionName in questionsMap) {
|
|
808
|
+
const questionDefault = questionsMap[questionName];
|
|
809
|
+
if (typeof questionDefault === "function") {
|
|
810
|
+
return {
|
|
811
|
+
...question,
|
|
812
|
+
default: questionDefault(question)
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
return {
|
|
816
|
+
...question,
|
|
817
|
+
default: questionDefault
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
return question;
|
|
821
|
+
});
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
function getDefaultsFromQuestions(questions) {
|
|
825
|
+
return questions.reduce((acc, question) => {
|
|
826
|
+
if (question.default && question.name) {
|
|
827
|
+
return { ...acc, [question.name]: question.default };
|
|
828
|
+
}
|
|
829
|
+
return acc;
|
|
830
|
+
}, {});
|
|
831
|
+
}
|
|
832
|
+
function getProjectNodeVersionDefault(question) {
|
|
833
|
+
const currentNodeVersion = process.versions.node.split(".")[0];
|
|
834
|
+
if (question.type === "list" && Array.isArray(question.choices)) {
|
|
835
|
+
const choice = question.choices.find((choice2) => choice2.value === currentNodeVersion);
|
|
836
|
+
if (choice) {
|
|
837
|
+
return choice.value;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
return question.default;
|
|
841
|
+
}
|
|
744
842
|
async function handleError(ctx, error) {
|
|
745
843
|
const { logger } = ctx;
|
|
746
844
|
logger.debug(error);
|
|
@@ -785,7 +883,7 @@ async function createProject$1(ctx, cloudApi, projectInput) {
|
|
|
785
883
|
throw e;
|
|
786
884
|
}
|
|
787
885
|
}
|
|
788
|
-
const action$
|
|
886
|
+
const action$4 = async (ctx) => {
|
|
789
887
|
const { logger } = ctx;
|
|
790
888
|
const { getValidToken, eraseToken } = await tokenServiceFactory(ctx);
|
|
791
889
|
const token = await getValidToken(ctx, promptLogin);
|
|
@@ -794,7 +892,16 @@ const action$2 = async (ctx) => {
|
|
|
794
892
|
}
|
|
795
893
|
const cloudApi = await cloudApiFactory(ctx, token);
|
|
796
894
|
const { data: config } = await cloudApi.config();
|
|
797
|
-
const
|
|
895
|
+
const projectName = await getProjectNameFromPackageJson(ctx);
|
|
896
|
+
const defaultAnswersMapper = questionDefaultValuesMapper({
|
|
897
|
+
name: projectName,
|
|
898
|
+
nodeVersion: getProjectNodeVersionDefault
|
|
899
|
+
});
|
|
900
|
+
const questions = defaultAnswersMapper(config.projectCreation.questions);
|
|
901
|
+
const defaultValues = {
|
|
902
|
+
...config.projectCreation.defaults,
|
|
903
|
+
...getDefaultsFromQuestions(questions)
|
|
904
|
+
};
|
|
798
905
|
const projectAnswersDefaulted = defaults(defaultValues);
|
|
799
906
|
const projectAnswers = await inquirer.prompt(questions);
|
|
800
907
|
const projectInput = projectAnswersDefaulted(projectAnswers);
|
|
@@ -843,38 +950,6 @@ function notificationServiceFactory({ logger }) {
|
|
|
843
950
|
};
|
|
844
951
|
};
|
|
845
952
|
}
|
|
846
|
-
yup.object({
|
|
847
|
-
name: yup.string().required(),
|
|
848
|
-
exports: yup.lazy(
|
|
849
|
-
(value) => yup.object(
|
|
850
|
-
typeof value === "object" ? Object.entries(value).reduce((acc, [key, value2]) => {
|
|
851
|
-
if (typeof value2 === "object") {
|
|
852
|
-
acc[key] = yup.object({
|
|
853
|
-
types: yup.string().optional(),
|
|
854
|
-
source: yup.string().required(),
|
|
855
|
-
module: yup.string().optional(),
|
|
856
|
-
import: yup.string().required(),
|
|
857
|
-
require: yup.string().required(),
|
|
858
|
-
default: yup.string().required()
|
|
859
|
-
}).noUnknown(true);
|
|
860
|
-
} else {
|
|
861
|
-
acc[key] = yup.string().matches(/^\.\/.*\.json$/).required();
|
|
862
|
-
}
|
|
863
|
-
return acc;
|
|
864
|
-
}, {}) : void 0
|
|
865
|
-
).optional()
|
|
866
|
-
)
|
|
867
|
-
});
|
|
868
|
-
const loadPkg = async ({ cwd, logger }) => {
|
|
869
|
-
const pkgPath = await pkgUp({ cwd });
|
|
870
|
-
if (!pkgPath) {
|
|
871
|
-
throw new Error("Could not find a package.json in the current directory");
|
|
872
|
-
}
|
|
873
|
-
const buffer = await fs$1.readFile(pkgPath);
|
|
874
|
-
const pkg = JSON.parse(buffer.toString());
|
|
875
|
-
logger.debug("Loaded package.json:", os.EOL, pkg);
|
|
876
|
-
return pkg;
|
|
877
|
-
};
|
|
878
953
|
const buildLogsServiceFactory = ({ logger }) => {
|
|
879
954
|
return async (url, token, cliConfig2) => {
|
|
880
955
|
const CONN_TIMEOUT = Number(cliConfig2.buildLogsConnectionTimeout);
|
|
@@ -928,6 +1003,7 @@ const buildLogsServiceFactory = ({ logger }) => {
|
|
|
928
1003
|
if (retries > MAX_RETRIES) {
|
|
929
1004
|
spinner.fail("We were unable to connect to the server to get build logs at this time.");
|
|
930
1005
|
es.close();
|
|
1006
|
+
clearExistingTimeout();
|
|
931
1007
|
reject(new Error("Max retries reached"));
|
|
932
1008
|
}
|
|
933
1009
|
};
|
|
@@ -970,13 +1046,13 @@ async function upload(ctx, project, token, maxProjectFileSize) {
|
|
|
970
1046
|
process.exit(1);
|
|
971
1047
|
}
|
|
972
1048
|
const tarFilePath = path__default.resolve(storagePath, compressedFilename);
|
|
973
|
-
const fileStats = await
|
|
1049
|
+
const fileStats = await fse__default.stat(tarFilePath);
|
|
974
1050
|
if (fileStats.size > maxProjectFileSize) {
|
|
975
1051
|
ctx.logger.log(
|
|
976
1052
|
"Unable to proceed: Your project is too big to be transferred, please use a git repo instead."
|
|
977
1053
|
);
|
|
978
1054
|
try {
|
|
979
|
-
await
|
|
1055
|
+
await fse__default.remove(tarFilePath);
|
|
980
1056
|
} catch (e) {
|
|
981
1057
|
ctx.logger.log("Unable to remove file: ", tarFilePath);
|
|
982
1058
|
ctx.logger.debug(e);
|
|
@@ -1004,8 +1080,8 @@ async function upload(ctx, project, token, maxProjectFileSize) {
|
|
|
1004
1080
|
progressBar.stop();
|
|
1005
1081
|
if (e instanceof AxiosError && e.response?.data) {
|
|
1006
1082
|
if (e.response.status === 404) {
|
|
1007
|
-
ctx.logger.
|
|
1008
|
-
`The project does not exist.
|
|
1083
|
+
ctx.logger.warn(
|
|
1084
|
+
`The project does not exist. Please link your local project to a Strapi Cloud project using the link command.`
|
|
1009
1085
|
);
|
|
1010
1086
|
} else {
|
|
1011
1087
|
ctx.logger.error(e.response.data);
|
|
@@ -1015,7 +1091,7 @@ async function upload(ctx, project, token, maxProjectFileSize) {
|
|
|
1015
1091
|
}
|
|
1016
1092
|
ctx.logger.debug(e);
|
|
1017
1093
|
} finally {
|
|
1018
|
-
await
|
|
1094
|
+
await fse__default.remove(tarFilePath);
|
|
1019
1095
|
}
|
|
1020
1096
|
process.exit(0);
|
|
1021
1097
|
} catch (e) {
|
|
@@ -1028,7 +1104,7 @@ async function getProject(ctx) {
|
|
|
1028
1104
|
const { project } = await retrieve();
|
|
1029
1105
|
if (!project) {
|
|
1030
1106
|
try {
|
|
1031
|
-
return await action$
|
|
1107
|
+
return await action$4(ctx);
|
|
1032
1108
|
} catch (e) {
|
|
1033
1109
|
ctx.logger.error("An error occurred while deploying the project. Please try again later.");
|
|
1034
1110
|
ctx.logger.debug(e);
|
|
@@ -1037,7 +1113,19 @@ async function getProject(ctx) {
|
|
|
1037
1113
|
}
|
|
1038
1114
|
return project;
|
|
1039
1115
|
}
|
|
1040
|
-
|
|
1116
|
+
async function getConfig({
|
|
1117
|
+
ctx,
|
|
1118
|
+
cloudApiService
|
|
1119
|
+
}) {
|
|
1120
|
+
try {
|
|
1121
|
+
const { data: cliConfig2 } = await cloudApiService.config();
|
|
1122
|
+
return cliConfig2;
|
|
1123
|
+
} catch (e) {
|
|
1124
|
+
ctx.logger.debug("Failed to get cli config", e);
|
|
1125
|
+
return null;
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
const action$3 = async (ctx) => {
|
|
1041
1129
|
const { getValidToken } = await tokenServiceFactory(ctx);
|
|
1042
1130
|
const token = await getValidToken(ctx, promptLogin);
|
|
1043
1131
|
if (!token) {
|
|
@@ -1048,14 +1136,18 @@ const action$1 = async (ctx) => {
|
|
|
1048
1136
|
return;
|
|
1049
1137
|
}
|
|
1050
1138
|
const cloudApiService = await cloudApiFactory(ctx);
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
}
|
|
1054
|
-
ctx.logger.debug("Failed to track willDeploy", e);
|
|
1055
|
-
}
|
|
1139
|
+
await trackEvent(ctx, cloudApiService, "willDeployWithCLI", {
|
|
1140
|
+
projectInternalName: project.name
|
|
1141
|
+
});
|
|
1056
1142
|
const notificationService = notificationServiceFactory(ctx);
|
|
1057
1143
|
const buildLogsService = buildLogsServiceFactory(ctx);
|
|
1058
|
-
const
|
|
1144
|
+
const cliConfig2 = await getConfig({ ctx, cloudApiService });
|
|
1145
|
+
if (!cliConfig2) {
|
|
1146
|
+
ctx.logger.error(
|
|
1147
|
+
"An error occurred while retrieving data from Strapi Cloud. Please try check your network or again later."
|
|
1148
|
+
);
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1059
1151
|
let maxSize = parseInt(cliConfig2.maxProjectFileSize, 10);
|
|
1060
1152
|
if (Number.isNaN(maxSize)) {
|
|
1061
1153
|
ctx.logger.debug(
|
|
@@ -1077,10 +1169,11 @@ const action$1 = async (ctx) => {
|
|
|
1077
1169
|
chalk.underline(`${apiConfig.dashboardBaseUrl}/projects/${project.name}/deployments`)
|
|
1078
1170
|
);
|
|
1079
1171
|
} catch (e) {
|
|
1172
|
+
ctx.logger.debug(e);
|
|
1080
1173
|
if (e instanceof Error) {
|
|
1081
1174
|
ctx.logger.error(e.message);
|
|
1082
1175
|
} else {
|
|
1083
|
-
|
|
1176
|
+
ctx.logger.error("An error occurred while deploying the project. Please try again later.");
|
|
1084
1177
|
}
|
|
1085
1178
|
}
|
|
1086
1179
|
};
|
|
@@ -1111,16 +1204,162 @@ const runAction = (name2, action2) => (...args) => {
|
|
|
1111
1204
|
process.exit(1);
|
|
1112
1205
|
});
|
|
1113
1206
|
};
|
|
1114
|
-
const command$
|
|
1115
|
-
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$
|
|
1207
|
+
const command$5 = ({ command: command2, ctx }) => {
|
|
1208
|
+
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));
|
|
1116
1209
|
};
|
|
1117
1210
|
const deployProject = {
|
|
1118
1211
|
name: "deploy-project",
|
|
1119
1212
|
description: "Deploy a Strapi Cloud project",
|
|
1120
|
-
action: action$
|
|
1121
|
-
command: command$
|
|
1213
|
+
action: action$3,
|
|
1214
|
+
command: command$5
|
|
1122
1215
|
};
|
|
1123
|
-
const
|
|
1216
|
+
const QUIT_OPTION = "Quit";
|
|
1217
|
+
async function getExistingConfig(ctx) {
|
|
1218
|
+
try {
|
|
1219
|
+
return await retrieve();
|
|
1220
|
+
} catch (e) {
|
|
1221
|
+
ctx.logger.debug("Failed to get project config", e);
|
|
1222
|
+
ctx.logger.error("An error occurred while retrieving config data from your local project.");
|
|
1223
|
+
return null;
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
async function promptForRelink(ctx, cloudApiService, existingConfig) {
|
|
1227
|
+
if (existingConfig && existingConfig.project) {
|
|
1228
|
+
const { shouldRelink } = await inquirer.prompt([
|
|
1229
|
+
{
|
|
1230
|
+
type: "confirm",
|
|
1231
|
+
name: "shouldRelink",
|
|
1232
|
+
message: `A project named ${chalk.cyan(
|
|
1233
|
+
existingConfig.project.displayName ? existingConfig.project.displayName : existingConfig.project.name
|
|
1234
|
+
)} is already linked to this local folder. Do you want to update the link?`,
|
|
1235
|
+
default: false
|
|
1236
|
+
}
|
|
1237
|
+
]);
|
|
1238
|
+
if (!shouldRelink) {
|
|
1239
|
+
await trackEvent(ctx, cloudApiService, "didNotLinkProject", {
|
|
1240
|
+
currentProjectName: existingConfig.project?.name
|
|
1241
|
+
});
|
|
1242
|
+
return false;
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
return true;
|
|
1246
|
+
}
|
|
1247
|
+
async function getProjectsList(ctx, cloudApiService, existingConfig) {
|
|
1248
|
+
const spinner = ctx.logger.spinner("Fetching your projects...\n").start();
|
|
1249
|
+
try {
|
|
1250
|
+
const {
|
|
1251
|
+
data: { data: projectList }
|
|
1252
|
+
} = await cloudApiService.listLinkProjects();
|
|
1253
|
+
spinner.succeed();
|
|
1254
|
+
if (!Array.isArray(projectList)) {
|
|
1255
|
+
ctx.logger.log("We couldn't find any projects available for linking in Strapi Cloud");
|
|
1256
|
+
return null;
|
|
1257
|
+
}
|
|
1258
|
+
const projects = projectList.filter(
|
|
1259
|
+
(project) => !(project.isMaintainer || project.name === existingConfig?.project?.name)
|
|
1260
|
+
).map((project) => {
|
|
1261
|
+
return {
|
|
1262
|
+
name: project.displayName,
|
|
1263
|
+
value: { name: project.name, displayName: project.displayName }
|
|
1264
|
+
};
|
|
1265
|
+
});
|
|
1266
|
+
if (projects.length === 0) {
|
|
1267
|
+
ctx.logger.log("We couldn't find any projects available for linking in Strapi Cloud");
|
|
1268
|
+
return null;
|
|
1269
|
+
}
|
|
1270
|
+
return projects;
|
|
1271
|
+
} catch (e) {
|
|
1272
|
+
spinner.fail("An error occurred while fetching your projects from Strapi Cloud.");
|
|
1273
|
+
ctx.logger.debug("Failed to list projects", e);
|
|
1274
|
+
return null;
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
async function getUserSelection(ctx, projects) {
|
|
1278
|
+
const { logger } = ctx;
|
|
1279
|
+
try {
|
|
1280
|
+
const answer = await inquirer.prompt([
|
|
1281
|
+
{
|
|
1282
|
+
type: "list",
|
|
1283
|
+
name: "linkProject",
|
|
1284
|
+
message: "Which project do you want to link?",
|
|
1285
|
+
choices: [...projects, { name: chalk.grey(`(${QUIT_OPTION})`), value: null }]
|
|
1286
|
+
}
|
|
1287
|
+
]);
|
|
1288
|
+
if (!answer.linkProject) {
|
|
1289
|
+
return null;
|
|
1290
|
+
}
|
|
1291
|
+
return answer;
|
|
1292
|
+
} catch (e) {
|
|
1293
|
+
logger.debug("Failed to get user input", e);
|
|
1294
|
+
logger.error("An error occurred while trying to get your input.");
|
|
1295
|
+
return null;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
const action$2 = async (ctx) => {
|
|
1299
|
+
const { getValidToken } = await tokenServiceFactory(ctx);
|
|
1300
|
+
const token = await getValidToken(ctx, promptLogin);
|
|
1301
|
+
const { logger } = ctx;
|
|
1302
|
+
if (!token) {
|
|
1303
|
+
return;
|
|
1304
|
+
}
|
|
1305
|
+
const cloudApiService = await cloudApiFactory(ctx, token);
|
|
1306
|
+
const existingConfig = await getExistingConfig(ctx);
|
|
1307
|
+
const shouldRelink = await promptForRelink(ctx, cloudApiService, existingConfig);
|
|
1308
|
+
if (!shouldRelink) {
|
|
1309
|
+
return;
|
|
1310
|
+
}
|
|
1311
|
+
await trackEvent(ctx, cloudApiService, "willLinkProject", {});
|
|
1312
|
+
const projects = await getProjectsList(
|
|
1313
|
+
ctx,
|
|
1314
|
+
cloudApiService,
|
|
1315
|
+
existingConfig
|
|
1316
|
+
);
|
|
1317
|
+
if (!projects) {
|
|
1318
|
+
return;
|
|
1319
|
+
}
|
|
1320
|
+
const answer = await getUserSelection(ctx, projects);
|
|
1321
|
+
if (!answer) {
|
|
1322
|
+
return;
|
|
1323
|
+
}
|
|
1324
|
+
try {
|
|
1325
|
+
const { confirmAction } = await inquirer.prompt([
|
|
1326
|
+
{
|
|
1327
|
+
type: "confirm",
|
|
1328
|
+
name: "confirmAction",
|
|
1329
|
+
message: "Warning: Once linked, deploying from CLI will replace the existing project and its data. Confirm to proceed:",
|
|
1330
|
+
default: false
|
|
1331
|
+
}
|
|
1332
|
+
]);
|
|
1333
|
+
if (!confirmAction) {
|
|
1334
|
+
await trackEvent(ctx, cloudApiService, "didNotLinkProject", {
|
|
1335
|
+
cancelledProjectName: answer.linkProject.name,
|
|
1336
|
+
currentProjectName: existingConfig ? existingConfig.project?.name : null
|
|
1337
|
+
});
|
|
1338
|
+
return;
|
|
1339
|
+
}
|
|
1340
|
+
await save({ project: answer.linkProject });
|
|
1341
|
+
logger.log(`Project ${chalk.cyan(answer.linkProject.displayName)} linked successfully.`);
|
|
1342
|
+
await trackEvent(ctx, cloudApiService, "didLinkProject", {
|
|
1343
|
+
projectInternalName: answer.linkProject
|
|
1344
|
+
});
|
|
1345
|
+
} catch (e) {
|
|
1346
|
+
logger.debug("Failed to link project", e);
|
|
1347
|
+
logger.error("An error occurred while linking the project.");
|
|
1348
|
+
await trackEvent(ctx, cloudApiService, "didNotLinkProject", {
|
|
1349
|
+
projectInternalName: answer.linkProject
|
|
1350
|
+
});
|
|
1351
|
+
}
|
|
1352
|
+
};
|
|
1353
|
+
const command$4 = ({ command: command2, ctx }) => {
|
|
1354
|
+
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));
|
|
1355
|
+
};
|
|
1356
|
+
const link = {
|
|
1357
|
+
name: "link-project",
|
|
1358
|
+
description: "Link a local directory to a Strapi Cloud project",
|
|
1359
|
+
action: action$2,
|
|
1360
|
+
command: command$4
|
|
1361
|
+
};
|
|
1362
|
+
const command$3 = ({ command: command2, ctx }) => {
|
|
1124
1363
|
command2.command("cloud:login").alias("login").description("Strapi Cloud Login").addHelpText(
|
|
1125
1364
|
"after",
|
|
1126
1365
|
"\nAfter running this command, you will be prompted to enter your authentication information."
|
|
@@ -1130,10 +1369,10 @@ const login = {
|
|
|
1130
1369
|
name: "login",
|
|
1131
1370
|
description: "Strapi Cloud Login",
|
|
1132
1371
|
action: loginAction,
|
|
1133
|
-
command: command$
|
|
1372
|
+
command: command$3
|
|
1134
1373
|
};
|
|
1135
1374
|
const openModule = import("open");
|
|
1136
|
-
const action = async (ctx) => {
|
|
1375
|
+
const action$1 = async (ctx) => {
|
|
1137
1376
|
const { logger } = ctx;
|
|
1138
1377
|
const { retrieveToken, eraseToken } = await tokenServiceFactory(ctx);
|
|
1139
1378
|
const token = await retrieveToken();
|
|
@@ -1163,37 +1402,64 @@ const action = async (ctx) => {
|
|
|
1163
1402
|
logger.error("🥲 Oops! Something went wrong while logging you out. Please try again.");
|
|
1164
1403
|
logger.debug(e);
|
|
1165
1404
|
}
|
|
1166
|
-
|
|
1167
|
-
await cloudApiService.track("didLogout", { loginMethod: "cli" });
|
|
1168
|
-
} catch (e) {
|
|
1169
|
-
logger.debug("Failed to track logout event", e);
|
|
1170
|
-
}
|
|
1405
|
+
await trackEvent(ctx, cloudApiService, "didLogout", { loginMethod: "cli" });
|
|
1171
1406
|
};
|
|
1172
|
-
const command$
|
|
1173
|
-
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));
|
|
1407
|
+
const command$2 = ({ command: command2, ctx }) => {
|
|
1408
|
+
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));
|
|
1174
1409
|
};
|
|
1175
1410
|
const logout = {
|
|
1176
1411
|
name: "logout",
|
|
1177
1412
|
description: "Strapi Cloud Logout",
|
|
1178
|
-
action,
|
|
1179
|
-
command: command$
|
|
1413
|
+
action: action$1,
|
|
1414
|
+
command: command$2
|
|
1180
1415
|
};
|
|
1181
|
-
const command = ({ command: command2, ctx }) => {
|
|
1182
|
-
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$
|
|
1416
|
+
const command$1 = ({ command: command2, ctx }) => {
|
|
1417
|
+
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));
|
|
1183
1418
|
};
|
|
1184
1419
|
const createProject = {
|
|
1185
1420
|
name: "create-project",
|
|
1186
1421
|
description: "Create a new project",
|
|
1187
|
-
action: action$
|
|
1422
|
+
action: action$4,
|
|
1423
|
+
command: command$1
|
|
1424
|
+
};
|
|
1425
|
+
const action = async (ctx) => {
|
|
1426
|
+
const { getValidToken } = await tokenServiceFactory(ctx);
|
|
1427
|
+
const token = await getValidToken(ctx, promptLogin);
|
|
1428
|
+
const { logger } = ctx;
|
|
1429
|
+
if (!token) {
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1432
|
+
const cloudApiService = await cloudApiFactory(ctx, token);
|
|
1433
|
+
const spinner = logger.spinner("Fetching your projects...").start();
|
|
1434
|
+
try {
|
|
1435
|
+
const {
|
|
1436
|
+
data: { data: projectList }
|
|
1437
|
+
} = await cloudApiService.listProjects();
|
|
1438
|
+
spinner.succeed();
|
|
1439
|
+
logger.log(projectList);
|
|
1440
|
+
} catch (e) {
|
|
1441
|
+
ctx.logger.debug("Failed to list projects", e);
|
|
1442
|
+
spinner.fail("An error occurred while fetching your projects from Strapi Cloud.");
|
|
1443
|
+
}
|
|
1444
|
+
};
|
|
1445
|
+
const command = ({ command: command2, ctx }) => {
|
|
1446
|
+
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));
|
|
1447
|
+
};
|
|
1448
|
+
const listProjects = {
|
|
1449
|
+
name: "list-projects",
|
|
1450
|
+
description: "List Strapi Cloud projects",
|
|
1451
|
+
action,
|
|
1188
1452
|
command
|
|
1189
1453
|
};
|
|
1190
1454
|
const cli = {
|
|
1191
1455
|
deployProject,
|
|
1456
|
+
link,
|
|
1192
1457
|
login,
|
|
1193
1458
|
logout,
|
|
1194
|
-
createProject
|
|
1459
|
+
createProject,
|
|
1460
|
+
listProjects
|
|
1195
1461
|
};
|
|
1196
|
-
const cloudCommands = [deployProject, login, logout];
|
|
1462
|
+
const cloudCommands = [deployProject, link, login, logout, listProjects];
|
|
1197
1463
|
async function initCloudCLIConfig() {
|
|
1198
1464
|
const localConfig = await getLocalConfig();
|
|
1199
1465
|
if (!localConfig.deviceId) {
|