@strapi/cloud-cli 0.0.0-experimental.f77206734629a2b88793a7a8abca40388843c656 → 0.0.0-next.48485bcb4aa83c14d6d2cb99cbd47676d0d31b97
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/LICENSE +18 -3
- package/dist/bin.js +9 -210
- package/dist/bin.js.map +1 -1
- package/dist/index.js +360 -274
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +357 -273
- package/dist/index.mjs.map +1 -1
- package/dist/src/config/api.d.ts +1 -0
- package/dist/src/config/api.d.ts.map +1 -1
- package/dist/src/config/local.d.ts +3 -3
- package/dist/src/config/local.d.ts.map +1 -1
- package/dist/src/create-project/action.d.ts +1 -1
- package/dist/src/create-project/action.d.ts.map +1 -1
- package/dist/src/deploy-project/action.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/login/action.d.ts +2 -2
- package/dist/src/login/action.d.ts.map +1 -1
- package/dist/src/logout/action.d.ts.map +1 -1
- package/dist/src/services/cli-api.d.ts +4 -2
- package/dist/src/services/cli-api.d.ts.map +1 -1
- package/dist/src/services/strapi-info-save.d.ts +3 -6
- package/dist/src/services/strapi-info-save.d.ts.map +1 -1
- package/dist/src/services/token.d.ts +5 -5
- package/dist/src/services/token.d.ts.map +1 -1
- package/dist/src/types.d.ts +1 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/compress-files.d.ts.map +1 -1
- package/dist/src/utils/helpers.d.ts.map +1 -1
- package/dist/src/utils/pkg.d.ts +2 -2
- package/dist/src/utils/pkg.d.ts.map +1 -1
- package/package.json +6 -5
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import crypto$1 from "crypto";
|
|
2
|
-
import
|
|
3
|
-
import fs__default from "fs";
|
|
2
|
+
import fse from "fs-extra";
|
|
4
3
|
import * as path from "path";
|
|
5
4
|
import path__default from "path";
|
|
5
|
+
import chalk from "chalk";
|
|
6
6
|
import axios, { AxiosError } from "axios";
|
|
7
7
|
import * as crypto from "node:crypto";
|
|
8
8
|
import { env } from "@strapi/utils";
|
|
9
|
+
import * as fs from "fs";
|
|
9
10
|
import * as tar from "tar";
|
|
10
11
|
import { minimatch } from "minimatch";
|
|
11
12
|
import inquirer from "inquirer";
|
|
@@ -14,7 +15,6 @@ import os from "os";
|
|
|
14
15
|
import XDGAppPaths from "xdg-app-paths";
|
|
15
16
|
import jwksClient from "jwks-rsa";
|
|
16
17
|
import jwt from "jsonwebtoken";
|
|
17
|
-
import chalk from "chalk";
|
|
18
18
|
import stringify from "fast-safe-stringify";
|
|
19
19
|
import ora from "ora";
|
|
20
20
|
import * as cliProgress from "cli-progress";
|
|
@@ -23,7 +23,8 @@ import fs$1 from "fs/promises";
|
|
|
23
23
|
import pkgUp from "pkg-up";
|
|
24
24
|
import * as yup from "yup";
|
|
25
25
|
const apiConfig = {
|
|
26
|
-
apiBaseUrl: env("STRAPI_CLI_CLOUD_API", "https://cli.
|
|
26
|
+
apiBaseUrl: env("STRAPI_CLI_CLOUD_API", "https://cloud-cli-api.strapi.io"),
|
|
27
|
+
dashboardBaseUrl: env("STRAPI_CLI_CLOUD_DASHBOARD", "https://cloud.strapi.io")
|
|
27
28
|
};
|
|
28
29
|
const IGNORED_PATTERNS = [
|
|
29
30
|
"**/.git/**",
|
|
@@ -78,7 +79,7 @@ const readGitignore = (folderPath) => {
|
|
|
78
79
|
if (!fs.existsSync(gitignorePath))
|
|
79
80
|
return [];
|
|
80
81
|
const gitignoreContent = fs.readFileSync(gitignorePath, "utf8");
|
|
81
|
-
return gitignoreContent.split(
|
|
82
|
+
return gitignoreContent.split(/\r?\n/).filter((line) => Boolean(line.trim()) && !line.startsWith("#"));
|
|
82
83
|
};
|
|
83
84
|
const compressFilesToTar = async (storagePath, folderToCompress, filename) => {
|
|
84
85
|
const ignorePatterns = readGitignore(folderToCompress);
|
|
@@ -93,48 +94,45 @@ const compressFilesToTar = async (storagePath, folderToCompress, filename) => {
|
|
|
93
94
|
};
|
|
94
95
|
const APP_FOLDER_NAME = "com.strapi.cli";
|
|
95
96
|
const CONFIG_FILENAME = "config.json";
|
|
96
|
-
function checkDirectoryExists(directoryPath) {
|
|
97
|
+
async function checkDirectoryExists(directoryPath) {
|
|
97
98
|
try {
|
|
98
|
-
|
|
99
|
+
const fsStat = await fse.lstat(directoryPath);
|
|
100
|
+
return fsStat.isDirectory();
|
|
99
101
|
} catch (e) {
|
|
100
102
|
return false;
|
|
101
103
|
}
|
|
102
104
|
}
|
|
103
|
-
function getTmpStoragePath() {
|
|
105
|
+
async function getTmpStoragePath() {
|
|
104
106
|
const storagePath = path__default.join(os.tmpdir(), APP_FOLDER_NAME);
|
|
105
|
-
|
|
106
|
-
fs__default.mkdirSync(storagePath, { recursive: true });
|
|
107
|
-
}
|
|
107
|
+
await fse.ensureDir(storagePath);
|
|
108
108
|
return storagePath;
|
|
109
109
|
}
|
|
110
|
-
function getConfigPath() {
|
|
110
|
+
async function getConfigPath() {
|
|
111
111
|
const configDirs = XDGAppPaths(APP_FOLDER_NAME).configDirs();
|
|
112
112
|
const configPath = configDirs.find(checkDirectoryExists);
|
|
113
113
|
if (!configPath) {
|
|
114
|
-
|
|
114
|
+
await fse.ensureDir(configDirs[0]);
|
|
115
115
|
return configDirs[0];
|
|
116
116
|
}
|
|
117
117
|
return configPath;
|
|
118
118
|
}
|
|
119
|
-
function getLocalConfig() {
|
|
120
|
-
const configPath = getConfigPath();
|
|
119
|
+
async function getLocalConfig() {
|
|
120
|
+
const configPath = await getConfigPath();
|
|
121
121
|
const configFilePath = path__default.join(configPath, CONFIG_FILENAME);
|
|
122
|
-
|
|
123
|
-
return {};
|
|
124
|
-
}
|
|
122
|
+
await fse.ensureFile(configFilePath);
|
|
125
123
|
try {
|
|
126
|
-
return
|
|
124
|
+
return await fse.readJSON(configFilePath, { encoding: "utf8", throws: true });
|
|
127
125
|
} catch (e) {
|
|
128
126
|
return {};
|
|
129
127
|
}
|
|
130
128
|
}
|
|
131
|
-
function saveLocalConfig(data) {
|
|
132
|
-
const configPath = getConfigPath();
|
|
129
|
+
async function saveLocalConfig(data) {
|
|
130
|
+
const configPath = await getConfigPath();
|
|
133
131
|
const configFilePath = path__default.join(configPath, CONFIG_FILENAME);
|
|
134
|
-
|
|
132
|
+
await fse.writeJson(configFilePath, data, { encoding: "utf8", spaces: 2, mode: 384 });
|
|
135
133
|
}
|
|
136
134
|
const name = "@strapi/cloud-cli";
|
|
137
|
-
const version = "4.
|
|
135
|
+
const version = "4.25.1";
|
|
138
136
|
const description = "Commands to interact with the Strapi Cloud";
|
|
139
137
|
const keywords = [
|
|
140
138
|
"strapi",
|
|
@@ -178,13 +176,14 @@ const scripts = {
|
|
|
178
176
|
watch: "pack-up watch"
|
|
179
177
|
};
|
|
180
178
|
const dependencies = {
|
|
181
|
-
"@strapi/utils": "4.
|
|
179
|
+
"@strapi/utils": "4.25.1",
|
|
182
180
|
axios: "1.6.0",
|
|
183
181
|
chalk: "4.1.2",
|
|
184
182
|
"cli-progress": "3.12.0",
|
|
185
183
|
commander: "8.3.0",
|
|
186
184
|
eventsource: "2.0.2",
|
|
187
185
|
"fast-safe-stringify": "2.1.1",
|
|
186
|
+
"fs-extra": "10.0.0",
|
|
188
187
|
inquirer: "8.2.5",
|
|
189
188
|
jsonwebtoken: "9.0.0",
|
|
190
189
|
"jwks-rsa": "3.1.0",
|
|
@@ -202,8 +201,8 @@ const devDependencies = {
|
|
|
202
201
|
"@types/cli-progress": "3.11.5",
|
|
203
202
|
"@types/eventsource": "1.1.15",
|
|
204
203
|
"@types/lodash": "^4.14.191",
|
|
205
|
-
"eslint-config-custom": "4.
|
|
206
|
-
tsconfig: "4.
|
|
204
|
+
"eslint-config-custom": "4.25.1",
|
|
205
|
+
tsconfig: "4.25.1"
|
|
207
206
|
};
|
|
208
207
|
const engines = {
|
|
209
208
|
node: ">=18.0.0 <=20.x.x",
|
|
@@ -232,8 +231,8 @@ const packageJson = {
|
|
|
232
231
|
engines
|
|
233
232
|
};
|
|
234
233
|
const VERSION = "v1";
|
|
235
|
-
function cloudApiFactory(token) {
|
|
236
|
-
const localConfig = getLocalConfig();
|
|
234
|
+
async function cloudApiFactory({ logger }, token) {
|
|
235
|
+
const localConfig = await getLocalConfig();
|
|
237
236
|
const customHeaders = {
|
|
238
237
|
"x-device-id": localConfig.deviceId,
|
|
239
238
|
"x-app-version": packageJson.version,
|
|
@@ -256,7 +255,7 @@ function cloudApiFactory(token) {
|
|
|
256
255
|
deploy({ filePath, project }, { onUploadProgress }) {
|
|
257
256
|
return axiosCloudAPI.post(
|
|
258
257
|
`/deploy/${project.name}`,
|
|
259
|
-
{ file:
|
|
258
|
+
{ file: fse.createReadStream(filePath) },
|
|
260
259
|
{
|
|
261
260
|
headers: {
|
|
262
261
|
"Content-Type": "multipart/form-data"
|
|
@@ -285,8 +284,19 @@ function cloudApiFactory(token) {
|
|
|
285
284
|
getUserInfo() {
|
|
286
285
|
return axiosCloudAPI.get("/user");
|
|
287
286
|
},
|
|
288
|
-
config() {
|
|
289
|
-
|
|
287
|
+
async config() {
|
|
288
|
+
try {
|
|
289
|
+
const response = await axiosCloudAPI.get("/config");
|
|
290
|
+
if (response.status !== 200) {
|
|
291
|
+
throw new Error("Error fetching cloud CLI config from the server.");
|
|
292
|
+
}
|
|
293
|
+
return response;
|
|
294
|
+
} catch (error) {
|
|
295
|
+
logger.debug(
|
|
296
|
+
"🥲 Oops! Couldn't retrieve the cloud CLI config from the server. Please try again."
|
|
297
|
+
);
|
|
298
|
+
throw error;
|
|
299
|
+
}
|
|
290
300
|
},
|
|
291
301
|
listProjects() {
|
|
292
302
|
return axiosCloudAPI.get("/projects");
|
|
@@ -300,53 +310,48 @@ function cloudApiFactory(token) {
|
|
|
300
310
|
};
|
|
301
311
|
}
|
|
302
312
|
const LOCAL_SAVE_FILENAME = ".strapi-cloud.json";
|
|
303
|
-
function save(data, { directoryPath } = {}) {
|
|
304
|
-
const
|
|
313
|
+
async function save(data, { directoryPath } = {}) {
|
|
314
|
+
const alreadyInFileData = await retrieve({ directoryPath });
|
|
315
|
+
const storedData = { ...alreadyInFileData, ...data };
|
|
305
316
|
const pathToFile = path__default.join(directoryPath || process.cwd(), LOCAL_SAVE_FILENAME);
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}
|
|
309
|
-
fs__default.writeFileSync(pathToFile, JSON.stringify(storedData), "utf8");
|
|
317
|
+
await fse.ensureDir(path__default.dirname(pathToFile));
|
|
318
|
+
await fse.writeJson(pathToFile, storedData, { encoding: "utf8" });
|
|
310
319
|
}
|
|
311
|
-
function retrieve({
|
|
320
|
+
async function retrieve({
|
|
321
|
+
directoryPath
|
|
322
|
+
} = {}) {
|
|
312
323
|
const pathToFile = path__default.join(directoryPath || process.cwd(), LOCAL_SAVE_FILENAME);
|
|
313
|
-
|
|
324
|
+
const pathExists = await fse.pathExists(pathToFile);
|
|
325
|
+
if (!pathExists) {
|
|
314
326
|
return {};
|
|
315
327
|
}
|
|
316
|
-
return
|
|
317
|
-
}
|
|
318
|
-
function erase({ directoryPath } = {}) {
|
|
319
|
-
const pathToFile = path__default.join(directoryPath || process.cwd(), LOCAL_SAVE_FILENAME);
|
|
320
|
-
if (fs__default.existsSync(pathToFile)) {
|
|
321
|
-
fs__default.unlinkSync(pathToFile);
|
|
322
|
-
}
|
|
328
|
+
return fse.readJSON(pathToFile, { encoding: "utf8" });
|
|
323
329
|
}
|
|
324
330
|
const strapiInfoSave = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
325
331
|
__proto__: null,
|
|
326
332
|
LOCAL_SAVE_FILENAME,
|
|
327
|
-
erase,
|
|
328
333
|
retrieve,
|
|
329
334
|
save
|
|
330
335
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
331
|
-
const cloudApiService = cloudApiFactory();
|
|
332
336
|
let cliConfig;
|
|
333
|
-
function tokenServiceFactory({ logger }) {
|
|
334
|
-
|
|
335
|
-
|
|
337
|
+
async function tokenServiceFactory({ logger }) {
|
|
338
|
+
const cloudApiService = await cloudApiFactory({ logger });
|
|
339
|
+
async function saveToken(str) {
|
|
340
|
+
const appConfig = await getLocalConfig();
|
|
336
341
|
if (!appConfig) {
|
|
337
342
|
logger.error("There was a problem saving your token. Please try again.");
|
|
338
343
|
return;
|
|
339
344
|
}
|
|
340
345
|
appConfig.token = str;
|
|
341
346
|
try {
|
|
342
|
-
saveLocalConfig(appConfig);
|
|
343
|
-
} catch (
|
|
344
|
-
logger.debug(
|
|
347
|
+
await saveLocalConfig(appConfig);
|
|
348
|
+
} catch (e) {
|
|
349
|
+
logger.debug(e);
|
|
345
350
|
logger.error("There was a problem saving your token. Please try again.");
|
|
346
351
|
}
|
|
347
352
|
}
|
|
348
353
|
async function retrieveToken() {
|
|
349
|
-
const appConfig = getLocalConfig();
|
|
354
|
+
const appConfig = await getLocalConfig();
|
|
350
355
|
if (appConfig.token) {
|
|
351
356
|
if (await isTokenValid(appConfig.token)) {
|
|
352
357
|
return appConfig.token;
|
|
@@ -359,9 +364,9 @@ function tokenServiceFactory({ logger }) {
|
|
|
359
364
|
jwksUri: jwksUrl
|
|
360
365
|
});
|
|
361
366
|
const getKey = (header, callback) => {
|
|
362
|
-
client.getSigningKey(header.kid, (
|
|
363
|
-
if (
|
|
364
|
-
callback(
|
|
367
|
+
client.getSigningKey(header.kid, (e, key) => {
|
|
368
|
+
if (e) {
|
|
369
|
+
callback(e);
|
|
365
370
|
} else if (key) {
|
|
366
371
|
const publicKey = "publicKey" in key ? key.publicKey : key.rsaPublicKey;
|
|
367
372
|
callback(null, publicKey);
|
|
@@ -379,14 +384,17 @@ function tokenServiceFactory({ logger }) {
|
|
|
379
384
|
"There seems to be a problem with your login information. Please try logging in again."
|
|
380
385
|
);
|
|
381
386
|
}
|
|
387
|
+
return Promise.reject(new Error("Invalid token"));
|
|
382
388
|
}
|
|
383
389
|
return new Promise((resolve, reject) => {
|
|
384
390
|
jwt.verify(idToken, getKey, (err) => {
|
|
385
391
|
if (err) {
|
|
386
392
|
reject(err);
|
|
387
|
-
} else {
|
|
388
|
-
resolve();
|
|
389
393
|
}
|
|
394
|
+
if (decodedToken.payload.exp < Math.floor(Date.now() / 1e3)) {
|
|
395
|
+
reject(new Error("Token is expired"));
|
|
396
|
+
}
|
|
397
|
+
resolve();
|
|
390
398
|
});
|
|
391
399
|
});
|
|
392
400
|
}
|
|
@@ -399,35 +407,36 @@ function tokenServiceFactory({ logger }) {
|
|
|
399
407
|
return true;
|
|
400
408
|
}
|
|
401
409
|
return false;
|
|
402
|
-
} catch (
|
|
403
|
-
logger.debug(
|
|
410
|
+
} catch (e) {
|
|
411
|
+
logger.debug(e);
|
|
404
412
|
return false;
|
|
405
413
|
}
|
|
406
414
|
}
|
|
407
|
-
function eraseToken() {
|
|
408
|
-
const appConfig = getLocalConfig();
|
|
415
|
+
async function eraseToken() {
|
|
416
|
+
const appConfig = await getLocalConfig();
|
|
409
417
|
if (!appConfig) {
|
|
410
418
|
return;
|
|
411
419
|
}
|
|
412
420
|
delete appConfig.token;
|
|
413
421
|
try {
|
|
414
|
-
saveLocalConfig(appConfig);
|
|
415
|
-
} catch (
|
|
416
|
-
logger.debug(
|
|
422
|
+
await saveLocalConfig(appConfig);
|
|
423
|
+
} catch (e) {
|
|
424
|
+
logger.debug(e);
|
|
417
425
|
logger.error(
|
|
418
426
|
"There was an issue removing your login information. Please try logging out again."
|
|
419
427
|
);
|
|
428
|
+
throw e;
|
|
420
429
|
}
|
|
421
430
|
}
|
|
422
|
-
async function getValidToken() {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
logger.log(
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
+
async function getValidToken(ctx, loginAction2) {
|
|
432
|
+
let token = await retrieveToken();
|
|
433
|
+
while (!token || !await isTokenValid(token)) {
|
|
434
|
+
logger.log(
|
|
435
|
+
token ? "Oops! Your token seems expired or invalid. Please login again." : "We couldn't find a valid token. You need to be logged in to use this feature."
|
|
436
|
+
);
|
|
437
|
+
if (!await loginAction2(ctx))
|
|
438
|
+
return null;
|
|
439
|
+
token = await retrieveToken();
|
|
431
440
|
}
|
|
432
441
|
return token;
|
|
433
442
|
}
|
|
@@ -561,57 +570,246 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
|
|
|
561
570
|
local: strapiInfoSave,
|
|
562
571
|
tokenServiceFactory
|
|
563
572
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
564
|
-
|
|
565
|
-
|
|
573
|
+
const openModule$1 = import("open");
|
|
574
|
+
async function promptLogin(ctx) {
|
|
575
|
+
const response = await inquirer.prompt([
|
|
576
|
+
{
|
|
577
|
+
type: "confirm",
|
|
578
|
+
name: "login",
|
|
579
|
+
message: "Would you like to login?"
|
|
580
|
+
}
|
|
581
|
+
]);
|
|
582
|
+
if (response.login) {
|
|
583
|
+
const loginSuccessful = await loginAction(ctx);
|
|
584
|
+
return loginSuccessful;
|
|
585
|
+
}
|
|
586
|
+
return false;
|
|
587
|
+
}
|
|
588
|
+
async function loginAction(ctx) {
|
|
589
|
+
const { logger } = ctx;
|
|
590
|
+
const tokenService = await tokenServiceFactory(ctx);
|
|
591
|
+
const existingToken = await tokenService.retrieveToken();
|
|
592
|
+
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
|
+
if (existingToken) {
|
|
601
|
+
const isTokenValid = await tokenService.isTokenValid(existingToken);
|
|
602
|
+
if (isTokenValid) {
|
|
603
|
+
try {
|
|
604
|
+
const userInfo = await cloudApiService.getUserInfo();
|
|
605
|
+
const { email } = userInfo.data.data;
|
|
606
|
+
if (email) {
|
|
607
|
+
logger.log(`You are already logged into your account (${email}).`);
|
|
608
|
+
} else {
|
|
609
|
+
logger.log("You are already logged in.");
|
|
610
|
+
}
|
|
611
|
+
logger.log(
|
|
612
|
+
"To access your dashboard, please copy and paste the following URL into your web browser:"
|
|
613
|
+
);
|
|
614
|
+
logger.log(chalk.underline(`${apiConfig.dashboardBaseUrl}/projects`));
|
|
615
|
+
return true;
|
|
616
|
+
} catch (e) {
|
|
617
|
+
logger.debug("Failed to fetch user info", e);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
let cliConfig2;
|
|
622
|
+
try {
|
|
623
|
+
logger.info("🔌 Connecting to the Strapi Cloud API...");
|
|
624
|
+
const config = await cloudApiService.config();
|
|
625
|
+
cliConfig2 = config.data;
|
|
626
|
+
} catch (e) {
|
|
627
|
+
logger.error("🥲 Oops! Something went wrong while logging you in. Please try again.");
|
|
628
|
+
logger.debug(e);
|
|
629
|
+
return false;
|
|
630
|
+
}
|
|
631
|
+
try {
|
|
632
|
+
await cloudApiService.track("willLoginAttempt", {});
|
|
633
|
+
} catch (e) {
|
|
634
|
+
logger.debug("Failed to track login attempt", e);
|
|
635
|
+
}
|
|
636
|
+
logger.debug("🔐 Creating device authentication request...", {
|
|
637
|
+
client_id: cliConfig2.clientId,
|
|
638
|
+
scope: cliConfig2.scope,
|
|
639
|
+
audience: cliConfig2.audience
|
|
640
|
+
});
|
|
641
|
+
const deviceAuthResponse = await axios.post(cliConfig2.deviceCodeAuthUrl, {
|
|
642
|
+
client_id: cliConfig2.clientId,
|
|
643
|
+
scope: cliConfig2.scope,
|
|
644
|
+
audience: cliConfig2.audience
|
|
645
|
+
}).catch((e) => {
|
|
646
|
+
logger.error("There was an issue with the authentication process. Please try again.");
|
|
647
|
+
if (e.message) {
|
|
648
|
+
logger.debug(e.message, e);
|
|
649
|
+
} else {
|
|
650
|
+
logger.debug(e);
|
|
651
|
+
}
|
|
652
|
+
});
|
|
653
|
+
openModule$1.then((open) => {
|
|
654
|
+
open.default(deviceAuthResponse.data.verification_uri_complete).catch((e) => {
|
|
655
|
+
logger.error("We encountered an issue opening the browser. Please try again later.");
|
|
656
|
+
logger.debug(e.message, e);
|
|
657
|
+
});
|
|
658
|
+
});
|
|
659
|
+
logger.log("If a browser tab does not open automatically, please follow the next steps:");
|
|
660
|
+
logger.log(
|
|
661
|
+
`1. Open this url in your device: ${deviceAuthResponse.data.verification_uri_complete}`
|
|
662
|
+
);
|
|
663
|
+
logger.log(
|
|
664
|
+
`2. Enter the following code: ${deviceAuthResponse.data.user_code} and confirm to login.
|
|
665
|
+
`
|
|
666
|
+
);
|
|
667
|
+
const tokenPayload = {
|
|
668
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
669
|
+
device_code: deviceAuthResponse.data.device_code,
|
|
670
|
+
client_id: cliConfig2.clientId
|
|
671
|
+
};
|
|
672
|
+
let isAuthenticated = false;
|
|
673
|
+
const authenticate = async () => {
|
|
674
|
+
const spinner = logger.spinner("Waiting for authentication");
|
|
675
|
+
spinner.start();
|
|
676
|
+
const spinnerFail = () => spinner.fail("Authentication failed!");
|
|
677
|
+
while (!isAuthenticated) {
|
|
678
|
+
try {
|
|
679
|
+
const tokenResponse = await axios.post(cliConfig2.tokenUrl, tokenPayload);
|
|
680
|
+
const authTokenData = tokenResponse.data;
|
|
681
|
+
if (tokenResponse.status === 200) {
|
|
682
|
+
try {
|
|
683
|
+
logger.debug("🔐 Validating token...");
|
|
684
|
+
await tokenService.validateToken(authTokenData.id_token, cliConfig2.jwksUrl);
|
|
685
|
+
logger.debug("🔐 Token validation successful!");
|
|
686
|
+
} catch (e) {
|
|
687
|
+
logger.debug(e);
|
|
688
|
+
spinnerFail();
|
|
689
|
+
throw new Error("Unable to proceed: Token validation failed");
|
|
690
|
+
}
|
|
691
|
+
logger.debug("🔍 Fetching user information...");
|
|
692
|
+
const cloudApiServiceWithToken = await cloudApiFactory(ctx, authTokenData.access_token);
|
|
693
|
+
await cloudApiServiceWithToken.getUserInfo();
|
|
694
|
+
logger.debug("🔍 User information fetched successfully!");
|
|
695
|
+
try {
|
|
696
|
+
logger.debug("📝 Saving login information...");
|
|
697
|
+
await tokenService.saveToken(authTokenData.access_token);
|
|
698
|
+
logger.debug("📝 Login information saved successfully!");
|
|
699
|
+
isAuthenticated = true;
|
|
700
|
+
} catch (e) {
|
|
701
|
+
logger.error(
|
|
702
|
+
"There was a problem saving your login information. Please try logging in again."
|
|
703
|
+
);
|
|
704
|
+
logger.debug(e);
|
|
705
|
+
spinnerFail();
|
|
706
|
+
return false;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
} catch (e) {
|
|
710
|
+
if (e.message === "Unable to proceed: Token validation failed") {
|
|
711
|
+
logger.error(
|
|
712
|
+
"There seems to be a problem with your login information. Please try logging in again."
|
|
713
|
+
);
|
|
714
|
+
spinnerFail();
|
|
715
|
+
await trackFailedLogin();
|
|
716
|
+
return false;
|
|
717
|
+
}
|
|
718
|
+
if (e.response?.data.error && !["authorization_pending", "slow_down"].includes(e.response.data.error)) {
|
|
719
|
+
logger.debug(e);
|
|
720
|
+
spinnerFail();
|
|
721
|
+
await trackFailedLogin();
|
|
722
|
+
return false;
|
|
723
|
+
}
|
|
724
|
+
await new Promise((resolve) => {
|
|
725
|
+
setTimeout(resolve, deviceAuthResponse.data.interval * 1e3);
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
spinner.succeed("Authentication successful!");
|
|
730
|
+
logger.log("You are now logged into Strapi Cloud.");
|
|
731
|
+
logger.log(
|
|
732
|
+
"To access your dashboard, please copy and paste the following URL into your web browser:"
|
|
733
|
+
);
|
|
734
|
+
logger.log(chalk.underline(`${apiConfig.dashboardBaseUrl}/projects`));
|
|
735
|
+
try {
|
|
736
|
+
await cloudApiService.track("didLogin", { loginMethod: "cli" });
|
|
737
|
+
} catch (e) {
|
|
738
|
+
logger.debug("Failed to track login", e);
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
await authenticate();
|
|
742
|
+
return isAuthenticated;
|
|
743
|
+
}
|
|
744
|
+
async function handleError(ctx, error) {
|
|
566
745
|
const { logger } = ctx;
|
|
567
746
|
logger.debug(error);
|
|
568
747
|
if (error instanceof AxiosError) {
|
|
748
|
+
const errorMessage = typeof error.response?.data === "string" ? error.response.data : null;
|
|
569
749
|
switch (error.response?.status) {
|
|
570
|
-
case 401:
|
|
571
|
-
logger.error("Your session has expired. Please log in again.");
|
|
572
|
-
tokenService.eraseToken();
|
|
573
|
-
return;
|
|
574
750
|
case 403:
|
|
575
751
|
logger.error(
|
|
576
|
-
|
|
752
|
+
errorMessage || "You do not have permission to create a project. Please contact support for assistance."
|
|
577
753
|
);
|
|
578
754
|
return;
|
|
579
755
|
case 400:
|
|
580
|
-
logger.error("Invalid input. Please check your inputs and try again.");
|
|
756
|
+
logger.error(errorMessage || "Invalid input. Please check your inputs and try again.");
|
|
581
757
|
return;
|
|
582
758
|
case 503:
|
|
583
759
|
logger.error(
|
|
584
760
|
"Strapi Cloud project creation is currently unavailable. Please try again later."
|
|
585
761
|
);
|
|
586
762
|
return;
|
|
763
|
+
default:
|
|
764
|
+
if (errorMessage) {
|
|
765
|
+
logger.error(errorMessage);
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
break;
|
|
587
769
|
}
|
|
588
770
|
}
|
|
589
771
|
logger.error(
|
|
590
772
|
"We encountered an issue while creating your project. Please try again in a moment. If the problem persists, contact support for assistance."
|
|
591
773
|
);
|
|
592
774
|
}
|
|
593
|
-
|
|
775
|
+
async function createProject$1(ctx, cloudApi, projectInput) {
|
|
594
776
|
const { logger } = ctx;
|
|
595
|
-
const
|
|
596
|
-
|
|
777
|
+
const spinner = logger.spinner("Setting up your project...").start();
|
|
778
|
+
try {
|
|
779
|
+
const { data } = await cloudApi.createProject(projectInput);
|
|
780
|
+
await save({ project: data });
|
|
781
|
+
spinner.succeed("Project created successfully!");
|
|
782
|
+
return data;
|
|
783
|
+
} catch (e) {
|
|
784
|
+
spinner.fail("An error occurred while creating the project on Strapi Cloud.");
|
|
785
|
+
throw e;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
const action$2 = async (ctx) => {
|
|
789
|
+
const { logger } = ctx;
|
|
790
|
+
const { getValidToken, eraseToken } = await tokenServiceFactory(ctx);
|
|
791
|
+
const token = await getValidToken(ctx, promptLogin);
|
|
597
792
|
if (!token) {
|
|
598
793
|
return;
|
|
599
794
|
}
|
|
600
|
-
const cloudApi = cloudApiFactory(token);
|
|
795
|
+
const cloudApi = await cloudApiFactory(ctx, token);
|
|
601
796
|
const { data: config } = await cloudApi.config();
|
|
602
797
|
const { questions, defaults: defaultValues } = config.projectCreation;
|
|
603
798
|
const projectAnswersDefaulted = defaults(defaultValues);
|
|
604
799
|
const projectAnswers = await inquirer.prompt(questions);
|
|
605
800
|
const projectInput = projectAnswersDefaulted(projectAnswers);
|
|
606
|
-
const spinner = logger.spinner("Setting up your project...").start();
|
|
607
801
|
try {
|
|
608
|
-
|
|
609
|
-
save({ project: data });
|
|
610
|
-
spinner.succeed("Project created successfully!");
|
|
611
|
-
return data;
|
|
802
|
+
return await createProject$1(ctx, cloudApi, projectInput);
|
|
612
803
|
} catch (e) {
|
|
613
|
-
|
|
614
|
-
|
|
804
|
+
if (e instanceof AxiosError && e.response?.status === 401) {
|
|
805
|
+
logger.warn("Oops! Your session has expired. Please log in again to retry.");
|
|
806
|
+
await eraseToken();
|
|
807
|
+
if (await promptLogin(ctx)) {
|
|
808
|
+
return await createProject$1(ctx, cloudApi, projectInput);
|
|
809
|
+
}
|
|
810
|
+
} else {
|
|
811
|
+
await handleError(ctx, e);
|
|
812
|
+
}
|
|
615
813
|
}
|
|
616
814
|
};
|
|
617
815
|
function notificationServiceFactory({ logger }) {
|
|
@@ -739,9 +937,9 @@ const buildLogsServiceFactory = ({ logger }) => {
|
|
|
739
937
|
};
|
|
740
938
|
};
|
|
741
939
|
async function upload(ctx, project, token, maxProjectFileSize) {
|
|
742
|
-
const cloudApi = cloudApiFactory(token);
|
|
940
|
+
const cloudApi = await cloudApiFactory(ctx, token);
|
|
743
941
|
try {
|
|
744
|
-
const storagePath = getTmpStoragePath();
|
|
942
|
+
const storagePath = await getTmpStoragePath();
|
|
745
943
|
const projectFolder = path__default.resolve(process.cwd());
|
|
746
944
|
const packageJson2 = await loadPkg(ctx);
|
|
747
945
|
if (!packageJson2) {
|
|
@@ -772,11 +970,18 @@ async function upload(ctx, project, token, maxProjectFileSize) {
|
|
|
772
970
|
process.exit(1);
|
|
773
971
|
}
|
|
774
972
|
const tarFilePath = path__default.resolve(storagePath, compressedFilename);
|
|
775
|
-
const fileStats =
|
|
973
|
+
const fileStats = await fse.stat(tarFilePath);
|
|
776
974
|
if (fileStats.size > maxProjectFileSize) {
|
|
777
|
-
|
|
975
|
+
ctx.logger.log(
|
|
778
976
|
"Unable to proceed: Your project is too big to be transferred, please use a git repo instead."
|
|
779
977
|
);
|
|
978
|
+
try {
|
|
979
|
+
await fse.remove(tarFilePath);
|
|
980
|
+
} catch (e) {
|
|
981
|
+
ctx.logger.log("Unable to remove file: ", tarFilePath);
|
|
982
|
+
ctx.logger.debug(e);
|
|
983
|
+
}
|
|
984
|
+
return;
|
|
780
985
|
}
|
|
781
986
|
ctx.logger.info("🚀 Uploading project...");
|
|
782
987
|
const progressBar = ctx.logger.progressBar(100, "Upload Progress");
|
|
@@ -810,7 +1015,7 @@ async function upload(ctx, project, token, maxProjectFileSize) {
|
|
|
810
1015
|
}
|
|
811
1016
|
ctx.logger.debug(e);
|
|
812
1017
|
} finally {
|
|
813
|
-
|
|
1018
|
+
await fse.remove(tarFilePath);
|
|
814
1019
|
}
|
|
815
1020
|
process.exit(0);
|
|
816
1021
|
} catch (e) {
|
|
@@ -820,10 +1025,10 @@ async function upload(ctx, project, token, maxProjectFileSize) {
|
|
|
820
1025
|
}
|
|
821
1026
|
}
|
|
822
1027
|
async function getProject(ctx) {
|
|
823
|
-
const { project } = retrieve();
|
|
1028
|
+
const { project } = await retrieve();
|
|
824
1029
|
if (!project) {
|
|
825
1030
|
try {
|
|
826
|
-
return await action$
|
|
1031
|
+
return await action$2(ctx);
|
|
827
1032
|
} catch (e) {
|
|
828
1033
|
ctx.logger.error("An error occurred while deploying the project. Please try again later.");
|
|
829
1034
|
ctx.logger.debug(e);
|
|
@@ -832,9 +1037,9 @@ async function getProject(ctx) {
|
|
|
832
1037
|
}
|
|
833
1038
|
return project;
|
|
834
1039
|
}
|
|
835
|
-
const action$
|
|
836
|
-
const { getValidToken } = tokenServiceFactory(ctx);
|
|
837
|
-
const token = await getValidToken();
|
|
1040
|
+
const action$1 = async (ctx) => {
|
|
1041
|
+
const { getValidToken } = await tokenServiceFactory(ctx);
|
|
1042
|
+
const token = await getValidToken(ctx, promptLogin);
|
|
838
1043
|
if (!token) {
|
|
839
1044
|
return;
|
|
840
1045
|
}
|
|
@@ -842,10 +1047,15 @@ const action$2 = async (ctx) => {
|
|
|
842
1047
|
if (!project) {
|
|
843
1048
|
return;
|
|
844
1049
|
}
|
|
1050
|
+
const cloudApiService = await cloudApiFactory(ctx);
|
|
1051
|
+
try {
|
|
1052
|
+
await cloudApiService.track("willDeployWithCLI", { projectInternalName: project.name });
|
|
1053
|
+
} catch (e) {
|
|
1054
|
+
ctx.logger.debug("Failed to track willDeploy", e);
|
|
1055
|
+
}
|
|
845
1056
|
const notificationService = notificationServiceFactory(ctx);
|
|
846
1057
|
const buildLogsService = buildLogsServiceFactory(ctx);
|
|
847
|
-
const
|
|
848
|
-
const { data: cliConfig2 } = await cloudApiService2.config();
|
|
1058
|
+
const { data: cliConfig2 } = await cloudApiService.config();
|
|
849
1059
|
let maxSize = parseInt(cliConfig2.maxProjectFileSize, 10);
|
|
850
1060
|
if (Number.isNaN(maxSize)) {
|
|
851
1061
|
ctx.logger.debug(
|
|
@@ -854,9 +1064,18 @@ const action$2 = async (ctx) => {
|
|
|
854
1064
|
maxSize = 1e8;
|
|
855
1065
|
}
|
|
856
1066
|
const buildId = await upload(ctx, project, token, maxSize);
|
|
1067
|
+
if (!buildId) {
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
857
1070
|
try {
|
|
858
1071
|
notificationService(`${apiConfig.apiBaseUrl}/notifications`, token, cliConfig2);
|
|
859
1072
|
await buildLogsService(`${apiConfig.apiBaseUrl}/v1/logs/${buildId}`, token, cliConfig2);
|
|
1073
|
+
ctx.logger.log(
|
|
1074
|
+
"Visit the following URL for deployment logs. Your deployment will be available here shortly."
|
|
1075
|
+
);
|
|
1076
|
+
ctx.logger.log(
|
|
1077
|
+
chalk.underline(`${apiConfig.dashboardBaseUrl}/projects/${project.name}/deployments`)
|
|
1078
|
+
);
|
|
860
1079
|
} catch (e) {
|
|
861
1080
|
if (e instanceof Error) {
|
|
862
1081
|
ctx.logger.error(e.message);
|
|
@@ -893,185 +1112,50 @@ const runAction = (name2, action2) => (...args) => {
|
|
|
893
1112
|
});
|
|
894
1113
|
};
|
|
895
1114
|
const command$3 = ({ command: command2, ctx }) => {
|
|
896
|
-
|
|
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$1)(ctx));
|
|
897
1116
|
};
|
|
898
1117
|
const deployProject = {
|
|
899
1118
|
name: "deploy-project",
|
|
900
1119
|
description: "Deploy a Strapi Cloud project",
|
|
901
|
-
action: action$
|
|
1120
|
+
action: action$1,
|
|
902
1121
|
command: command$3
|
|
903
1122
|
};
|
|
904
|
-
const openModule = import("open");
|
|
905
|
-
const action$1 = async (ctx) => {
|
|
906
|
-
const { logger } = ctx;
|
|
907
|
-
const tokenService = tokenServiceFactory(ctx);
|
|
908
|
-
const existingToken = await tokenService.retrieveToken();
|
|
909
|
-
const cloudApiService2 = cloudApiFactory(existingToken || void 0);
|
|
910
|
-
const trackFailedLogin = async () => {
|
|
911
|
-
try {
|
|
912
|
-
await cloudApiService2.track("didNotLogin", { loginMethod: "cli" });
|
|
913
|
-
} catch (e) {
|
|
914
|
-
logger.debug("Failed to track failed login", e);
|
|
915
|
-
}
|
|
916
|
-
};
|
|
917
|
-
if (existingToken) {
|
|
918
|
-
const isTokenValid = await tokenService.isTokenValid(existingToken);
|
|
919
|
-
if (isTokenValid) {
|
|
920
|
-
try {
|
|
921
|
-
const userInfo = await cloudApiService2.getUserInfo();
|
|
922
|
-
const { email } = userInfo.data.data;
|
|
923
|
-
if (email) {
|
|
924
|
-
logger.log(`You are already logged into your account (${email}).`);
|
|
925
|
-
} else {
|
|
926
|
-
logger.log("You are already logged in.");
|
|
927
|
-
}
|
|
928
|
-
return;
|
|
929
|
-
} catch (e) {
|
|
930
|
-
logger.debug("Failed to fetch user info", e);
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
let cliConfig2;
|
|
935
|
-
try {
|
|
936
|
-
logger.info("🔌 Connecting to the Strapi Cloud API...");
|
|
937
|
-
const config = await cloudApiService2.config();
|
|
938
|
-
cliConfig2 = config.data;
|
|
939
|
-
} catch (e) {
|
|
940
|
-
logger.error("🥲 Oops! Something went wrong while logging you in. Please try again.");
|
|
941
|
-
logger.debug(e);
|
|
942
|
-
return;
|
|
943
|
-
}
|
|
944
|
-
try {
|
|
945
|
-
await cloudApiService2.track("willLoginAttempt", {});
|
|
946
|
-
} catch (e) {
|
|
947
|
-
logger.debug("Failed to track login attempt", e);
|
|
948
|
-
}
|
|
949
|
-
logger.debug("🔐 Creating device authentication request...", {
|
|
950
|
-
client_id: cliConfig2.clientId,
|
|
951
|
-
scope: cliConfig2.scope,
|
|
952
|
-
audience: cliConfig2.audience
|
|
953
|
-
});
|
|
954
|
-
const deviceAuthResponse = await axios.post(cliConfig2.deviceCodeAuthUrl, {
|
|
955
|
-
client_id: cliConfig2.clientId,
|
|
956
|
-
scope: cliConfig2.scope,
|
|
957
|
-
audience: cliConfig2.audience
|
|
958
|
-
}).catch((e) => {
|
|
959
|
-
logger.error("There was an issue with the authentication process. Please try again.");
|
|
960
|
-
if (e.message) {
|
|
961
|
-
logger.debug(e.message, e);
|
|
962
|
-
} else {
|
|
963
|
-
logger.debug(e);
|
|
964
|
-
}
|
|
965
|
-
});
|
|
966
|
-
openModule.then((open) => {
|
|
967
|
-
open.default(deviceAuthResponse.data.verification_uri_complete).catch((e) => {
|
|
968
|
-
logger.error("We encountered an issue opening the browser. Please try again later.");
|
|
969
|
-
logger.debug(e.message, e);
|
|
970
|
-
});
|
|
971
|
-
});
|
|
972
|
-
logger.log("If a browser tab does not open automatically, please follow the next steps:");
|
|
973
|
-
logger.log(
|
|
974
|
-
`1. Open this url in your device: ${deviceAuthResponse.data.verification_uri_complete}`
|
|
975
|
-
);
|
|
976
|
-
logger.log(
|
|
977
|
-
`2. Enter the following code: ${deviceAuthResponse.data.user_code} and confirm to login.
|
|
978
|
-
`
|
|
979
|
-
);
|
|
980
|
-
const tokenPayload = {
|
|
981
|
-
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
982
|
-
device_code: deviceAuthResponse.data.device_code,
|
|
983
|
-
client_id: cliConfig2.clientId
|
|
984
|
-
};
|
|
985
|
-
let isAuthenticated = false;
|
|
986
|
-
const authenticate = async () => {
|
|
987
|
-
const spinner = logger.spinner("Waiting for authentication");
|
|
988
|
-
spinner.start();
|
|
989
|
-
const spinnerFail = () => spinner.fail("Authentication failed!");
|
|
990
|
-
while (!isAuthenticated) {
|
|
991
|
-
try {
|
|
992
|
-
const tokenResponse = await axios.post(cliConfig2.tokenUrl, tokenPayload);
|
|
993
|
-
const authTokenData = tokenResponse.data;
|
|
994
|
-
if (tokenResponse.status === 200) {
|
|
995
|
-
try {
|
|
996
|
-
logger.debug("🔐 Validating token...");
|
|
997
|
-
await tokenService.validateToken(authTokenData.id_token, cliConfig2.jwksUrl);
|
|
998
|
-
logger.debug("🔐 Token validation successful!");
|
|
999
|
-
} catch (e) {
|
|
1000
|
-
logger.debug(e);
|
|
1001
|
-
spinnerFail();
|
|
1002
|
-
throw new Error("Unable to proceed: Token validation failed");
|
|
1003
|
-
}
|
|
1004
|
-
const cloudApiService22 = cloudApiFactory(authTokenData.access_token);
|
|
1005
|
-
logger.debug("🔍 Fetching user information...");
|
|
1006
|
-
await cloudApiService22.getUserInfo();
|
|
1007
|
-
logger.debug("🔍 User information fetched successfully!");
|
|
1008
|
-
try {
|
|
1009
|
-
logger.debug("📝 Saving login information...");
|
|
1010
|
-
await tokenService.saveToken(authTokenData.access_token);
|
|
1011
|
-
logger.debug("📝 Login information saved successfully!");
|
|
1012
|
-
isAuthenticated = true;
|
|
1013
|
-
} catch (e) {
|
|
1014
|
-
logger.error(
|
|
1015
|
-
"There was a problem saving your login information. Please try logging in again."
|
|
1016
|
-
);
|
|
1017
|
-
logger.debug(e);
|
|
1018
|
-
spinnerFail();
|
|
1019
|
-
return;
|
|
1020
|
-
}
|
|
1021
|
-
}
|
|
1022
|
-
} catch (e) {
|
|
1023
|
-
if (e.message === "Unable to proceed: Token validation failed") {
|
|
1024
|
-
logger.error(
|
|
1025
|
-
"There seems to be a problem with your login information. Please try logging in again."
|
|
1026
|
-
);
|
|
1027
|
-
spinnerFail();
|
|
1028
|
-
await trackFailedLogin();
|
|
1029
|
-
return;
|
|
1030
|
-
}
|
|
1031
|
-
if (e.response?.data.error && !["authorization_pending", "slow_down"].includes(e.response.data.error)) {
|
|
1032
|
-
logger.debug(e);
|
|
1033
|
-
spinnerFail();
|
|
1034
|
-
await trackFailedLogin();
|
|
1035
|
-
return;
|
|
1036
|
-
}
|
|
1037
|
-
await new Promise((resolve) => {
|
|
1038
|
-
setTimeout(resolve, deviceAuthResponse.data.interval * 1e3);
|
|
1039
|
-
});
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
spinner.succeed("Authentication successful!");
|
|
1043
|
-
logger.log("You are now logged into Strapi Cloud.");
|
|
1044
|
-
try {
|
|
1045
|
-
await cloudApiService2.track("didLogin", { loginMethod: "cli" });
|
|
1046
|
-
} catch (e) {
|
|
1047
|
-
logger.debug("Failed to track login", e);
|
|
1048
|
-
}
|
|
1049
|
-
};
|
|
1050
|
-
await authenticate();
|
|
1051
|
-
};
|
|
1052
1123
|
const command$2 = ({ command: command2, ctx }) => {
|
|
1053
|
-
|
|
1124
|
+
command2.command("cloud:login").alias("login").description("Strapi Cloud Login").addHelpText(
|
|
1054
1125
|
"after",
|
|
1055
1126
|
"\nAfter running this command, you will be prompted to enter your authentication information."
|
|
1056
|
-
).option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("login",
|
|
1127
|
+
).option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("login", loginAction)(ctx));
|
|
1057
1128
|
};
|
|
1058
1129
|
const login = {
|
|
1059
1130
|
name: "login",
|
|
1060
1131
|
description: "Strapi Cloud Login",
|
|
1061
|
-
action:
|
|
1132
|
+
action: loginAction,
|
|
1062
1133
|
command: command$2
|
|
1063
1134
|
};
|
|
1135
|
+
const openModule = import("open");
|
|
1064
1136
|
const action = async (ctx) => {
|
|
1065
1137
|
const { logger } = ctx;
|
|
1066
|
-
const { retrieveToken, eraseToken } = tokenServiceFactory(ctx);
|
|
1138
|
+
const { retrieveToken, eraseToken } = await tokenServiceFactory(ctx);
|
|
1067
1139
|
const token = await retrieveToken();
|
|
1068
1140
|
if (!token) {
|
|
1069
1141
|
logger.log("You're already logged out.");
|
|
1070
1142
|
return;
|
|
1071
1143
|
}
|
|
1072
|
-
const
|
|
1144
|
+
const cloudApiService = await cloudApiFactory(ctx, token);
|
|
1145
|
+
const config = await cloudApiService.config();
|
|
1146
|
+
const cliConfig2 = config.data;
|
|
1073
1147
|
try {
|
|
1074
1148
|
await eraseToken();
|
|
1149
|
+
openModule.then((open) => {
|
|
1150
|
+
open.default(
|
|
1151
|
+
`${cliConfig2.baseUrl}/oidc/logout?client_id=${encodeURIComponent(
|
|
1152
|
+
cliConfig2.clientId
|
|
1153
|
+
)}&logout_hint=${encodeURIComponent(token)}
|
|
1154
|
+
`
|
|
1155
|
+
).catch((e) => {
|
|
1156
|
+
logger.debug(e.message, e);
|
|
1157
|
+
});
|
|
1158
|
+
});
|
|
1075
1159
|
logger.log(
|
|
1076
1160
|
"🔌 You have been logged out from the CLI. If you are on a shared computer, please make sure to log out from the Strapi Cloud Dashboard as well."
|
|
1077
1161
|
);
|
|
@@ -1080,13 +1164,13 @@ const action = async (ctx) => {
|
|
|
1080
1164
|
logger.debug(e);
|
|
1081
1165
|
}
|
|
1082
1166
|
try {
|
|
1083
|
-
await
|
|
1167
|
+
await cloudApiService.track("didLogout", { loginMethod: "cli" });
|
|
1084
1168
|
} catch (e) {
|
|
1085
1169
|
logger.debug("Failed to track logout event", e);
|
|
1086
1170
|
}
|
|
1087
1171
|
};
|
|
1088
1172
|
const command$1 = ({ command: command2, ctx }) => {
|
|
1089
|
-
|
|
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));
|
|
1090
1174
|
};
|
|
1091
1175
|
const logout = {
|
|
1092
1176
|
name: "logout",
|
|
@@ -1095,12 +1179,12 @@ const logout = {
|
|
|
1095
1179
|
command: command$1
|
|
1096
1180
|
};
|
|
1097
1181
|
const command = ({ command: command2, ctx }) => {
|
|
1098
|
-
|
|
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$2)(ctx));
|
|
1099
1183
|
};
|
|
1100
1184
|
const createProject = {
|
|
1101
1185
|
name: "create-project",
|
|
1102
1186
|
description: "Create a new project",
|
|
1103
|
-
action: action$
|
|
1187
|
+
action: action$2,
|
|
1104
1188
|
command
|
|
1105
1189
|
};
|
|
1106
1190
|
const cli = {
|
|
@@ -1111,25 +1195,25 @@ const cli = {
|
|
|
1111
1195
|
};
|
|
1112
1196
|
const cloudCommands = [deployProject, login, logout];
|
|
1113
1197
|
async function initCloudCLIConfig() {
|
|
1114
|
-
const localConfig = getLocalConfig();
|
|
1198
|
+
const localConfig = await getLocalConfig();
|
|
1115
1199
|
if (!localConfig.deviceId) {
|
|
1116
1200
|
localConfig.deviceId = crypto$1.randomUUID();
|
|
1117
1201
|
}
|
|
1118
|
-
saveLocalConfig(localConfig);
|
|
1202
|
+
await saveLocalConfig(localConfig);
|
|
1119
1203
|
}
|
|
1120
|
-
function buildStrapiCloudCommands({
|
|
1204
|
+
async function buildStrapiCloudCommands({
|
|
1121
1205
|
command: command2,
|
|
1122
1206
|
ctx,
|
|
1123
1207
|
argv
|
|
1124
1208
|
}) {
|
|
1125
|
-
initCloudCLIConfig();
|
|
1126
|
-
|
|
1209
|
+
await initCloudCLIConfig();
|
|
1210
|
+
for (const cloudCommand of cloudCommands) {
|
|
1127
1211
|
try {
|
|
1128
|
-
cloudCommand.command({ command: command2, ctx, argv });
|
|
1212
|
+
await cloudCommand.command({ command: command2, ctx, argv });
|
|
1129
1213
|
} catch (e) {
|
|
1130
1214
|
console.error(`Failed to load command ${cloudCommand.name}`, e);
|
|
1131
1215
|
}
|
|
1132
|
-
}
|
|
1216
|
+
}
|
|
1133
1217
|
}
|
|
1134
1218
|
export {
|
|
1135
1219
|
buildStrapiCloudCommands,
|