@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.js
CHANGED
|
@@ -23,11 +23,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
));
|
|
24
24
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
25
25
|
const crypto$1 = require("crypto");
|
|
26
|
-
const
|
|
26
|
+
const fse = require("fs-extra");
|
|
27
27
|
const path = require("path");
|
|
28
|
+
const chalk = require("chalk");
|
|
28
29
|
const axios = require("axios");
|
|
29
30
|
const crypto = require("node:crypto");
|
|
30
31
|
const utils = require("@strapi/utils");
|
|
32
|
+
const fs = require("fs");
|
|
31
33
|
const tar = require("tar");
|
|
32
34
|
const minimatch = require("minimatch");
|
|
33
35
|
const inquirer = require("inquirer");
|
|
@@ -36,7 +38,6 @@ const os = require("os");
|
|
|
36
38
|
const XDGAppPaths = require("xdg-app-paths");
|
|
37
39
|
const jwksClient = require("jwks-rsa");
|
|
38
40
|
const jwt = require("jsonwebtoken");
|
|
39
|
-
const chalk = require("chalk");
|
|
40
41
|
const stringify = require("fast-safe-stringify");
|
|
41
42
|
const ora = require("ora");
|
|
42
43
|
const cliProgress = require("cli-progress");
|
|
@@ -64,17 +65,18 @@ function _interopNamespace(e) {
|
|
|
64
65
|
return Object.freeze(n);
|
|
65
66
|
}
|
|
66
67
|
const crypto__default = /* @__PURE__ */ _interopDefault(crypto$1);
|
|
67
|
-
const
|
|
68
|
+
const fse__default = /* @__PURE__ */ _interopDefault(fse);
|
|
68
69
|
const path__namespace = /* @__PURE__ */ _interopNamespace(path);
|
|
70
|
+
const chalk__default = /* @__PURE__ */ _interopDefault(chalk);
|
|
69
71
|
const axios__default = /* @__PURE__ */ _interopDefault(axios);
|
|
70
72
|
const crypto__namespace = /* @__PURE__ */ _interopNamespace(crypto);
|
|
73
|
+
const fs__namespace = /* @__PURE__ */ _interopNamespace(fs);
|
|
71
74
|
const tar__namespace = /* @__PURE__ */ _interopNamespace(tar);
|
|
72
75
|
const inquirer__default = /* @__PURE__ */ _interopDefault(inquirer);
|
|
73
76
|
const os__default = /* @__PURE__ */ _interopDefault(os);
|
|
74
77
|
const XDGAppPaths__default = /* @__PURE__ */ _interopDefault(XDGAppPaths);
|
|
75
78
|
const jwksClient__default = /* @__PURE__ */ _interopDefault(jwksClient);
|
|
76
79
|
const jwt__default = /* @__PURE__ */ _interopDefault(jwt);
|
|
77
|
-
const chalk__default = /* @__PURE__ */ _interopDefault(chalk);
|
|
78
80
|
const stringify__default = /* @__PURE__ */ _interopDefault(stringify);
|
|
79
81
|
const ora__default = /* @__PURE__ */ _interopDefault(ora);
|
|
80
82
|
const cliProgress__namespace = /* @__PURE__ */ _interopNamespace(cliProgress);
|
|
@@ -83,7 +85,8 @@ const fs__default = /* @__PURE__ */ _interopDefault(fs$1);
|
|
|
83
85
|
const pkgUp__default = /* @__PURE__ */ _interopDefault(pkgUp);
|
|
84
86
|
const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
|
|
85
87
|
const apiConfig = {
|
|
86
|
-
apiBaseUrl: utils.env("STRAPI_CLI_CLOUD_API", "https://cli.
|
|
88
|
+
apiBaseUrl: utils.env("STRAPI_CLI_CLOUD_API", "https://cloud-cli-api.strapi.io"),
|
|
89
|
+
dashboardBaseUrl: utils.env("STRAPI_CLI_CLOUD_DASHBOARD", "https://cloud.strapi.io")
|
|
87
90
|
};
|
|
88
91
|
const IGNORED_PATTERNS = [
|
|
89
92
|
"**/.git/**",
|
|
@@ -138,7 +141,7 @@ const readGitignore = (folderPath) => {
|
|
|
138
141
|
if (!fs__namespace.existsSync(gitignorePath))
|
|
139
142
|
return [];
|
|
140
143
|
const gitignoreContent = fs__namespace.readFileSync(gitignorePath, "utf8");
|
|
141
|
-
return gitignoreContent.split(
|
|
144
|
+
return gitignoreContent.split(/\r?\n/).filter((line) => Boolean(line.trim()) && !line.startsWith("#"));
|
|
142
145
|
};
|
|
143
146
|
const compressFilesToTar = async (storagePath, folderToCompress, filename) => {
|
|
144
147
|
const ignorePatterns = readGitignore(folderToCompress);
|
|
@@ -153,48 +156,45 @@ const compressFilesToTar = async (storagePath, folderToCompress, filename) => {
|
|
|
153
156
|
};
|
|
154
157
|
const APP_FOLDER_NAME = "com.strapi.cli";
|
|
155
158
|
const CONFIG_FILENAME = "config.json";
|
|
156
|
-
function checkDirectoryExists(directoryPath) {
|
|
159
|
+
async function checkDirectoryExists(directoryPath) {
|
|
157
160
|
try {
|
|
158
|
-
|
|
161
|
+
const fsStat = await fse__default.default.lstat(directoryPath);
|
|
162
|
+
return fsStat.isDirectory();
|
|
159
163
|
} catch (e) {
|
|
160
164
|
return false;
|
|
161
165
|
}
|
|
162
166
|
}
|
|
163
|
-
function getTmpStoragePath() {
|
|
167
|
+
async function getTmpStoragePath() {
|
|
164
168
|
const storagePath = path__namespace.default.join(os__default.default.tmpdir(), APP_FOLDER_NAME);
|
|
165
|
-
|
|
166
|
-
fs__namespace.default.mkdirSync(storagePath, { recursive: true });
|
|
167
|
-
}
|
|
169
|
+
await fse__default.default.ensureDir(storagePath);
|
|
168
170
|
return storagePath;
|
|
169
171
|
}
|
|
170
|
-
function getConfigPath() {
|
|
172
|
+
async function getConfigPath() {
|
|
171
173
|
const configDirs = XDGAppPaths__default.default(APP_FOLDER_NAME).configDirs();
|
|
172
174
|
const configPath = configDirs.find(checkDirectoryExists);
|
|
173
175
|
if (!configPath) {
|
|
174
|
-
|
|
176
|
+
await fse__default.default.ensureDir(configDirs[0]);
|
|
175
177
|
return configDirs[0];
|
|
176
178
|
}
|
|
177
179
|
return configPath;
|
|
178
180
|
}
|
|
179
|
-
function getLocalConfig() {
|
|
180
|
-
const configPath = getConfigPath();
|
|
181
|
+
async function getLocalConfig() {
|
|
182
|
+
const configPath = await getConfigPath();
|
|
181
183
|
const configFilePath = path__namespace.default.join(configPath, CONFIG_FILENAME);
|
|
182
|
-
|
|
183
|
-
return {};
|
|
184
|
-
}
|
|
184
|
+
await fse__default.default.ensureFile(configFilePath);
|
|
185
185
|
try {
|
|
186
|
-
return
|
|
186
|
+
return await fse__default.default.readJSON(configFilePath, { encoding: "utf8", throws: true });
|
|
187
187
|
} catch (e) {
|
|
188
188
|
return {};
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
|
-
function saveLocalConfig(data) {
|
|
192
|
-
const configPath = getConfigPath();
|
|
191
|
+
async function saveLocalConfig(data) {
|
|
192
|
+
const configPath = await getConfigPath();
|
|
193
193
|
const configFilePath = path__namespace.default.join(configPath, CONFIG_FILENAME);
|
|
194
|
-
|
|
194
|
+
await fse__default.default.writeJson(configFilePath, data, { encoding: "utf8", spaces: 2, mode: 384 });
|
|
195
195
|
}
|
|
196
196
|
const name = "@strapi/cloud-cli";
|
|
197
|
-
const version = "4.
|
|
197
|
+
const version = "4.25.1";
|
|
198
198
|
const description = "Commands to interact with the Strapi Cloud";
|
|
199
199
|
const keywords = [
|
|
200
200
|
"strapi",
|
|
@@ -238,13 +238,14 @@ const scripts = {
|
|
|
238
238
|
watch: "pack-up watch"
|
|
239
239
|
};
|
|
240
240
|
const dependencies = {
|
|
241
|
-
"@strapi/utils": "4.
|
|
241
|
+
"@strapi/utils": "4.25.1",
|
|
242
242
|
axios: "1.6.0",
|
|
243
243
|
chalk: "4.1.2",
|
|
244
244
|
"cli-progress": "3.12.0",
|
|
245
245
|
commander: "8.3.0",
|
|
246
246
|
eventsource: "2.0.2",
|
|
247
247
|
"fast-safe-stringify": "2.1.1",
|
|
248
|
+
"fs-extra": "10.0.0",
|
|
248
249
|
inquirer: "8.2.5",
|
|
249
250
|
jsonwebtoken: "9.0.0",
|
|
250
251
|
"jwks-rsa": "3.1.0",
|
|
@@ -262,8 +263,8 @@ const devDependencies = {
|
|
|
262
263
|
"@types/cli-progress": "3.11.5",
|
|
263
264
|
"@types/eventsource": "1.1.15",
|
|
264
265
|
"@types/lodash": "^4.14.191",
|
|
265
|
-
"eslint-config-custom": "4.
|
|
266
|
-
tsconfig: "4.
|
|
266
|
+
"eslint-config-custom": "4.25.1",
|
|
267
|
+
tsconfig: "4.25.1"
|
|
267
268
|
};
|
|
268
269
|
const engines = {
|
|
269
270
|
node: ">=18.0.0 <=20.x.x",
|
|
@@ -292,8 +293,8 @@ const packageJson = {
|
|
|
292
293
|
engines
|
|
293
294
|
};
|
|
294
295
|
const VERSION = "v1";
|
|
295
|
-
function cloudApiFactory(token) {
|
|
296
|
-
const localConfig = getLocalConfig();
|
|
296
|
+
async function cloudApiFactory({ logger }, token) {
|
|
297
|
+
const localConfig = await getLocalConfig();
|
|
297
298
|
const customHeaders = {
|
|
298
299
|
"x-device-id": localConfig.deviceId,
|
|
299
300
|
"x-app-version": packageJson.version,
|
|
@@ -316,7 +317,7 @@ function cloudApiFactory(token) {
|
|
|
316
317
|
deploy({ filePath, project }, { onUploadProgress }) {
|
|
317
318
|
return axiosCloudAPI.post(
|
|
318
319
|
`/deploy/${project.name}`,
|
|
319
|
-
{ file:
|
|
320
|
+
{ file: fse__default.default.createReadStream(filePath) },
|
|
320
321
|
{
|
|
321
322
|
headers: {
|
|
322
323
|
"Content-Type": "multipart/form-data"
|
|
@@ -345,8 +346,19 @@ function cloudApiFactory(token) {
|
|
|
345
346
|
getUserInfo() {
|
|
346
347
|
return axiosCloudAPI.get("/user");
|
|
347
348
|
},
|
|
348
|
-
config() {
|
|
349
|
-
|
|
349
|
+
async config() {
|
|
350
|
+
try {
|
|
351
|
+
const response = await axiosCloudAPI.get("/config");
|
|
352
|
+
if (response.status !== 200) {
|
|
353
|
+
throw new Error("Error fetching cloud CLI config from the server.");
|
|
354
|
+
}
|
|
355
|
+
return response;
|
|
356
|
+
} catch (error) {
|
|
357
|
+
logger.debug(
|
|
358
|
+
"🥲 Oops! Couldn't retrieve the cloud CLI config from the server. Please try again."
|
|
359
|
+
);
|
|
360
|
+
throw error;
|
|
361
|
+
}
|
|
350
362
|
},
|
|
351
363
|
listProjects() {
|
|
352
364
|
return axiosCloudAPI.get("/projects");
|
|
@@ -360,53 +372,48 @@ function cloudApiFactory(token) {
|
|
|
360
372
|
};
|
|
361
373
|
}
|
|
362
374
|
const LOCAL_SAVE_FILENAME = ".strapi-cloud.json";
|
|
363
|
-
function save(data, { directoryPath } = {}) {
|
|
364
|
-
const
|
|
375
|
+
async function save(data, { directoryPath } = {}) {
|
|
376
|
+
const alreadyInFileData = await retrieve({ directoryPath });
|
|
377
|
+
const storedData = { ...alreadyInFileData, ...data };
|
|
365
378
|
const pathToFile = path__namespace.default.join(directoryPath || process.cwd(), LOCAL_SAVE_FILENAME);
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
}
|
|
369
|
-
fs__namespace.default.writeFileSync(pathToFile, JSON.stringify(storedData), "utf8");
|
|
379
|
+
await fse__default.default.ensureDir(path__namespace.default.dirname(pathToFile));
|
|
380
|
+
await fse__default.default.writeJson(pathToFile, storedData, { encoding: "utf8" });
|
|
370
381
|
}
|
|
371
|
-
function retrieve({
|
|
382
|
+
async function retrieve({
|
|
383
|
+
directoryPath
|
|
384
|
+
} = {}) {
|
|
372
385
|
const pathToFile = path__namespace.default.join(directoryPath || process.cwd(), LOCAL_SAVE_FILENAME);
|
|
373
|
-
|
|
386
|
+
const pathExists = await fse__default.default.pathExists(pathToFile);
|
|
387
|
+
if (!pathExists) {
|
|
374
388
|
return {};
|
|
375
389
|
}
|
|
376
|
-
return
|
|
377
|
-
}
|
|
378
|
-
function erase({ directoryPath } = {}) {
|
|
379
|
-
const pathToFile = path__namespace.default.join(directoryPath || process.cwd(), LOCAL_SAVE_FILENAME);
|
|
380
|
-
if (fs__namespace.default.existsSync(pathToFile)) {
|
|
381
|
-
fs__namespace.default.unlinkSync(pathToFile);
|
|
382
|
-
}
|
|
390
|
+
return fse__default.default.readJSON(pathToFile, { encoding: "utf8" });
|
|
383
391
|
}
|
|
384
392
|
const strapiInfoSave = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
385
393
|
__proto__: null,
|
|
386
394
|
LOCAL_SAVE_FILENAME,
|
|
387
|
-
erase,
|
|
388
395
|
retrieve,
|
|
389
396
|
save
|
|
390
397
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
391
|
-
const cloudApiService = cloudApiFactory();
|
|
392
398
|
let cliConfig;
|
|
393
|
-
function tokenServiceFactory({ logger }) {
|
|
394
|
-
|
|
395
|
-
|
|
399
|
+
async function tokenServiceFactory({ logger }) {
|
|
400
|
+
const cloudApiService = await cloudApiFactory({ logger });
|
|
401
|
+
async function saveToken(str) {
|
|
402
|
+
const appConfig = await getLocalConfig();
|
|
396
403
|
if (!appConfig) {
|
|
397
404
|
logger.error("There was a problem saving your token. Please try again.");
|
|
398
405
|
return;
|
|
399
406
|
}
|
|
400
407
|
appConfig.token = str;
|
|
401
408
|
try {
|
|
402
|
-
saveLocalConfig(appConfig);
|
|
403
|
-
} catch (
|
|
404
|
-
logger.debug(
|
|
409
|
+
await saveLocalConfig(appConfig);
|
|
410
|
+
} catch (e) {
|
|
411
|
+
logger.debug(e);
|
|
405
412
|
logger.error("There was a problem saving your token. Please try again.");
|
|
406
413
|
}
|
|
407
414
|
}
|
|
408
415
|
async function retrieveToken() {
|
|
409
|
-
const appConfig = getLocalConfig();
|
|
416
|
+
const appConfig = await getLocalConfig();
|
|
410
417
|
if (appConfig.token) {
|
|
411
418
|
if (await isTokenValid(appConfig.token)) {
|
|
412
419
|
return appConfig.token;
|
|
@@ -419,9 +426,9 @@ function tokenServiceFactory({ logger }) {
|
|
|
419
426
|
jwksUri: jwksUrl
|
|
420
427
|
});
|
|
421
428
|
const getKey = (header, callback) => {
|
|
422
|
-
client.getSigningKey(header.kid, (
|
|
423
|
-
if (
|
|
424
|
-
callback(
|
|
429
|
+
client.getSigningKey(header.kid, (e, key) => {
|
|
430
|
+
if (e) {
|
|
431
|
+
callback(e);
|
|
425
432
|
} else if (key) {
|
|
426
433
|
const publicKey = "publicKey" in key ? key.publicKey : key.rsaPublicKey;
|
|
427
434
|
callback(null, publicKey);
|
|
@@ -439,14 +446,17 @@ function tokenServiceFactory({ logger }) {
|
|
|
439
446
|
"There seems to be a problem with your login information. Please try logging in again."
|
|
440
447
|
);
|
|
441
448
|
}
|
|
449
|
+
return Promise.reject(new Error("Invalid token"));
|
|
442
450
|
}
|
|
443
451
|
return new Promise((resolve, reject) => {
|
|
444
452
|
jwt__default.default.verify(idToken, getKey, (err) => {
|
|
445
453
|
if (err) {
|
|
446
454
|
reject(err);
|
|
447
|
-
} else {
|
|
448
|
-
resolve();
|
|
449
455
|
}
|
|
456
|
+
if (decodedToken.payload.exp < Math.floor(Date.now() / 1e3)) {
|
|
457
|
+
reject(new Error("Token is expired"));
|
|
458
|
+
}
|
|
459
|
+
resolve();
|
|
450
460
|
});
|
|
451
461
|
});
|
|
452
462
|
}
|
|
@@ -459,35 +469,36 @@ function tokenServiceFactory({ logger }) {
|
|
|
459
469
|
return true;
|
|
460
470
|
}
|
|
461
471
|
return false;
|
|
462
|
-
} catch (
|
|
463
|
-
logger.debug(
|
|
472
|
+
} catch (e) {
|
|
473
|
+
logger.debug(e);
|
|
464
474
|
return false;
|
|
465
475
|
}
|
|
466
476
|
}
|
|
467
|
-
function eraseToken() {
|
|
468
|
-
const appConfig = getLocalConfig();
|
|
477
|
+
async function eraseToken() {
|
|
478
|
+
const appConfig = await getLocalConfig();
|
|
469
479
|
if (!appConfig) {
|
|
470
480
|
return;
|
|
471
481
|
}
|
|
472
482
|
delete appConfig.token;
|
|
473
483
|
try {
|
|
474
|
-
saveLocalConfig(appConfig);
|
|
475
|
-
} catch (
|
|
476
|
-
logger.debug(
|
|
484
|
+
await saveLocalConfig(appConfig);
|
|
485
|
+
} catch (e) {
|
|
486
|
+
logger.debug(e);
|
|
477
487
|
logger.error(
|
|
478
488
|
"There was an issue removing your login information. Please try logging out again."
|
|
479
489
|
);
|
|
490
|
+
throw e;
|
|
480
491
|
}
|
|
481
492
|
}
|
|
482
|
-
async function getValidToken() {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
logger.log(
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
493
|
+
async function getValidToken(ctx, loginAction2) {
|
|
494
|
+
let token = await retrieveToken();
|
|
495
|
+
while (!token || !await isTokenValid(token)) {
|
|
496
|
+
logger.log(
|
|
497
|
+
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."
|
|
498
|
+
);
|
|
499
|
+
if (!await loginAction2(ctx))
|
|
500
|
+
return null;
|
|
501
|
+
token = await retrieveToken();
|
|
491
502
|
}
|
|
492
503
|
return token;
|
|
493
504
|
}
|
|
@@ -621,57 +632,246 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
|
|
|
621
632
|
local: strapiInfoSave,
|
|
622
633
|
tokenServiceFactory
|
|
623
634
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
624
|
-
|
|
625
|
-
|
|
635
|
+
const openModule$1 = import("open");
|
|
636
|
+
async function promptLogin(ctx) {
|
|
637
|
+
const response = await inquirer__default.default.prompt([
|
|
638
|
+
{
|
|
639
|
+
type: "confirm",
|
|
640
|
+
name: "login",
|
|
641
|
+
message: "Would you like to login?"
|
|
642
|
+
}
|
|
643
|
+
]);
|
|
644
|
+
if (response.login) {
|
|
645
|
+
const loginSuccessful = await loginAction(ctx);
|
|
646
|
+
return loginSuccessful;
|
|
647
|
+
}
|
|
648
|
+
return false;
|
|
649
|
+
}
|
|
650
|
+
async function loginAction(ctx) {
|
|
651
|
+
const { logger } = ctx;
|
|
652
|
+
const tokenService = await tokenServiceFactory(ctx);
|
|
653
|
+
const existingToken = await tokenService.retrieveToken();
|
|
654
|
+
const cloudApiService = await cloudApiFactory(ctx, existingToken || void 0);
|
|
655
|
+
const trackFailedLogin = async () => {
|
|
656
|
+
try {
|
|
657
|
+
await cloudApiService.track("didNotLogin", { loginMethod: "cli" });
|
|
658
|
+
} catch (e) {
|
|
659
|
+
logger.debug("Failed to track failed login", e);
|
|
660
|
+
}
|
|
661
|
+
};
|
|
662
|
+
if (existingToken) {
|
|
663
|
+
const isTokenValid = await tokenService.isTokenValid(existingToken);
|
|
664
|
+
if (isTokenValid) {
|
|
665
|
+
try {
|
|
666
|
+
const userInfo = await cloudApiService.getUserInfo();
|
|
667
|
+
const { email } = userInfo.data.data;
|
|
668
|
+
if (email) {
|
|
669
|
+
logger.log(`You are already logged into your account (${email}).`);
|
|
670
|
+
} else {
|
|
671
|
+
logger.log("You are already logged in.");
|
|
672
|
+
}
|
|
673
|
+
logger.log(
|
|
674
|
+
"To access your dashboard, please copy and paste the following URL into your web browser:"
|
|
675
|
+
);
|
|
676
|
+
logger.log(chalk__default.default.underline(`${apiConfig.dashboardBaseUrl}/projects`));
|
|
677
|
+
return true;
|
|
678
|
+
} catch (e) {
|
|
679
|
+
logger.debug("Failed to fetch user info", e);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
let cliConfig2;
|
|
684
|
+
try {
|
|
685
|
+
logger.info("🔌 Connecting to the Strapi Cloud API...");
|
|
686
|
+
const config = await cloudApiService.config();
|
|
687
|
+
cliConfig2 = config.data;
|
|
688
|
+
} catch (e) {
|
|
689
|
+
logger.error("🥲 Oops! Something went wrong while logging you in. Please try again.");
|
|
690
|
+
logger.debug(e);
|
|
691
|
+
return false;
|
|
692
|
+
}
|
|
693
|
+
try {
|
|
694
|
+
await cloudApiService.track("willLoginAttempt", {});
|
|
695
|
+
} catch (e) {
|
|
696
|
+
logger.debug("Failed to track login attempt", e);
|
|
697
|
+
}
|
|
698
|
+
logger.debug("🔐 Creating device authentication request...", {
|
|
699
|
+
client_id: cliConfig2.clientId,
|
|
700
|
+
scope: cliConfig2.scope,
|
|
701
|
+
audience: cliConfig2.audience
|
|
702
|
+
});
|
|
703
|
+
const deviceAuthResponse = await axios__default.default.post(cliConfig2.deviceCodeAuthUrl, {
|
|
704
|
+
client_id: cliConfig2.clientId,
|
|
705
|
+
scope: cliConfig2.scope,
|
|
706
|
+
audience: cliConfig2.audience
|
|
707
|
+
}).catch((e) => {
|
|
708
|
+
logger.error("There was an issue with the authentication process. Please try again.");
|
|
709
|
+
if (e.message) {
|
|
710
|
+
logger.debug(e.message, e);
|
|
711
|
+
} else {
|
|
712
|
+
logger.debug(e);
|
|
713
|
+
}
|
|
714
|
+
});
|
|
715
|
+
openModule$1.then((open) => {
|
|
716
|
+
open.default(deviceAuthResponse.data.verification_uri_complete).catch((e) => {
|
|
717
|
+
logger.error("We encountered an issue opening the browser. Please try again later.");
|
|
718
|
+
logger.debug(e.message, e);
|
|
719
|
+
});
|
|
720
|
+
});
|
|
721
|
+
logger.log("If a browser tab does not open automatically, please follow the next steps:");
|
|
722
|
+
logger.log(
|
|
723
|
+
`1. Open this url in your device: ${deviceAuthResponse.data.verification_uri_complete}`
|
|
724
|
+
);
|
|
725
|
+
logger.log(
|
|
726
|
+
`2. Enter the following code: ${deviceAuthResponse.data.user_code} and confirm to login.
|
|
727
|
+
`
|
|
728
|
+
);
|
|
729
|
+
const tokenPayload = {
|
|
730
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
731
|
+
device_code: deviceAuthResponse.data.device_code,
|
|
732
|
+
client_id: cliConfig2.clientId
|
|
733
|
+
};
|
|
734
|
+
let isAuthenticated = false;
|
|
735
|
+
const authenticate = async () => {
|
|
736
|
+
const spinner = logger.spinner("Waiting for authentication");
|
|
737
|
+
spinner.start();
|
|
738
|
+
const spinnerFail = () => spinner.fail("Authentication failed!");
|
|
739
|
+
while (!isAuthenticated) {
|
|
740
|
+
try {
|
|
741
|
+
const tokenResponse = await axios__default.default.post(cliConfig2.tokenUrl, tokenPayload);
|
|
742
|
+
const authTokenData = tokenResponse.data;
|
|
743
|
+
if (tokenResponse.status === 200) {
|
|
744
|
+
try {
|
|
745
|
+
logger.debug("🔐 Validating token...");
|
|
746
|
+
await tokenService.validateToken(authTokenData.id_token, cliConfig2.jwksUrl);
|
|
747
|
+
logger.debug("🔐 Token validation successful!");
|
|
748
|
+
} catch (e) {
|
|
749
|
+
logger.debug(e);
|
|
750
|
+
spinnerFail();
|
|
751
|
+
throw new Error("Unable to proceed: Token validation failed");
|
|
752
|
+
}
|
|
753
|
+
logger.debug("🔍 Fetching user information...");
|
|
754
|
+
const cloudApiServiceWithToken = await cloudApiFactory(ctx, authTokenData.access_token);
|
|
755
|
+
await cloudApiServiceWithToken.getUserInfo();
|
|
756
|
+
logger.debug("🔍 User information fetched successfully!");
|
|
757
|
+
try {
|
|
758
|
+
logger.debug("📝 Saving login information...");
|
|
759
|
+
await tokenService.saveToken(authTokenData.access_token);
|
|
760
|
+
logger.debug("📝 Login information saved successfully!");
|
|
761
|
+
isAuthenticated = true;
|
|
762
|
+
} catch (e) {
|
|
763
|
+
logger.error(
|
|
764
|
+
"There was a problem saving your login information. Please try logging in again."
|
|
765
|
+
);
|
|
766
|
+
logger.debug(e);
|
|
767
|
+
spinnerFail();
|
|
768
|
+
return false;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
} catch (e) {
|
|
772
|
+
if (e.message === "Unable to proceed: Token validation failed") {
|
|
773
|
+
logger.error(
|
|
774
|
+
"There seems to be a problem with your login information. Please try logging in again."
|
|
775
|
+
);
|
|
776
|
+
spinnerFail();
|
|
777
|
+
await trackFailedLogin();
|
|
778
|
+
return false;
|
|
779
|
+
}
|
|
780
|
+
if (e.response?.data.error && !["authorization_pending", "slow_down"].includes(e.response.data.error)) {
|
|
781
|
+
logger.debug(e);
|
|
782
|
+
spinnerFail();
|
|
783
|
+
await trackFailedLogin();
|
|
784
|
+
return false;
|
|
785
|
+
}
|
|
786
|
+
await new Promise((resolve) => {
|
|
787
|
+
setTimeout(resolve, deviceAuthResponse.data.interval * 1e3);
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
spinner.succeed("Authentication successful!");
|
|
792
|
+
logger.log("You are now logged into Strapi Cloud.");
|
|
793
|
+
logger.log(
|
|
794
|
+
"To access your dashboard, please copy and paste the following URL into your web browser:"
|
|
795
|
+
);
|
|
796
|
+
logger.log(chalk__default.default.underline(`${apiConfig.dashboardBaseUrl}/projects`));
|
|
797
|
+
try {
|
|
798
|
+
await cloudApiService.track("didLogin", { loginMethod: "cli" });
|
|
799
|
+
} catch (e) {
|
|
800
|
+
logger.debug("Failed to track login", e);
|
|
801
|
+
}
|
|
802
|
+
};
|
|
803
|
+
await authenticate();
|
|
804
|
+
return isAuthenticated;
|
|
805
|
+
}
|
|
806
|
+
async function handleError(ctx, error) {
|
|
626
807
|
const { logger } = ctx;
|
|
627
808
|
logger.debug(error);
|
|
628
809
|
if (error instanceof axios.AxiosError) {
|
|
810
|
+
const errorMessage = typeof error.response?.data === "string" ? error.response.data : null;
|
|
629
811
|
switch (error.response?.status) {
|
|
630
|
-
case 401:
|
|
631
|
-
logger.error("Your session has expired. Please log in again.");
|
|
632
|
-
tokenService.eraseToken();
|
|
633
|
-
return;
|
|
634
812
|
case 403:
|
|
635
813
|
logger.error(
|
|
636
|
-
|
|
814
|
+
errorMessage || "You do not have permission to create a project. Please contact support for assistance."
|
|
637
815
|
);
|
|
638
816
|
return;
|
|
639
817
|
case 400:
|
|
640
|
-
logger.error("Invalid input. Please check your inputs and try again.");
|
|
818
|
+
logger.error(errorMessage || "Invalid input. Please check your inputs and try again.");
|
|
641
819
|
return;
|
|
642
820
|
case 503:
|
|
643
821
|
logger.error(
|
|
644
822
|
"Strapi Cloud project creation is currently unavailable. Please try again later."
|
|
645
823
|
);
|
|
646
824
|
return;
|
|
825
|
+
default:
|
|
826
|
+
if (errorMessage) {
|
|
827
|
+
logger.error(errorMessage);
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
break;
|
|
647
831
|
}
|
|
648
832
|
}
|
|
649
833
|
logger.error(
|
|
650
834
|
"We encountered an issue while creating your project. Please try again in a moment. If the problem persists, contact support for assistance."
|
|
651
835
|
);
|
|
652
836
|
}
|
|
653
|
-
|
|
837
|
+
async function createProject$1(ctx, cloudApi, projectInput) {
|
|
654
838
|
const { logger } = ctx;
|
|
655
|
-
const
|
|
656
|
-
|
|
839
|
+
const spinner = logger.spinner("Setting up your project...").start();
|
|
840
|
+
try {
|
|
841
|
+
const { data } = await cloudApi.createProject(projectInput);
|
|
842
|
+
await save({ project: data });
|
|
843
|
+
spinner.succeed("Project created successfully!");
|
|
844
|
+
return data;
|
|
845
|
+
} catch (e) {
|
|
846
|
+
spinner.fail("An error occurred while creating the project on Strapi Cloud.");
|
|
847
|
+
throw e;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
const action$2 = async (ctx) => {
|
|
851
|
+
const { logger } = ctx;
|
|
852
|
+
const { getValidToken, eraseToken } = await tokenServiceFactory(ctx);
|
|
853
|
+
const token = await getValidToken(ctx, promptLogin);
|
|
657
854
|
if (!token) {
|
|
658
855
|
return;
|
|
659
856
|
}
|
|
660
|
-
const cloudApi = cloudApiFactory(token);
|
|
857
|
+
const cloudApi = await cloudApiFactory(ctx, token);
|
|
661
858
|
const { data: config } = await cloudApi.config();
|
|
662
859
|
const { questions, defaults: defaultValues } = config.projectCreation;
|
|
663
860
|
const projectAnswersDefaulted = fp.defaults(defaultValues);
|
|
664
861
|
const projectAnswers = await inquirer__default.default.prompt(questions);
|
|
665
862
|
const projectInput = projectAnswersDefaulted(projectAnswers);
|
|
666
|
-
const spinner = logger.spinner("Setting up your project...").start();
|
|
667
863
|
try {
|
|
668
|
-
|
|
669
|
-
save({ project: data });
|
|
670
|
-
spinner.succeed("Project created successfully!");
|
|
671
|
-
return data;
|
|
864
|
+
return await createProject$1(ctx, cloudApi, projectInput);
|
|
672
865
|
} catch (e) {
|
|
673
|
-
|
|
674
|
-
|
|
866
|
+
if (e instanceof axios.AxiosError && e.response?.status === 401) {
|
|
867
|
+
logger.warn("Oops! Your session has expired. Please log in again to retry.");
|
|
868
|
+
await eraseToken();
|
|
869
|
+
if (await promptLogin(ctx)) {
|
|
870
|
+
return await createProject$1(ctx, cloudApi, projectInput);
|
|
871
|
+
}
|
|
872
|
+
} else {
|
|
873
|
+
await handleError(ctx, e);
|
|
874
|
+
}
|
|
675
875
|
}
|
|
676
876
|
};
|
|
677
877
|
function notificationServiceFactory({ logger }) {
|
|
@@ -799,9 +999,9 @@ const buildLogsServiceFactory = ({ logger }) => {
|
|
|
799
999
|
};
|
|
800
1000
|
};
|
|
801
1001
|
async function upload(ctx, project, token, maxProjectFileSize) {
|
|
802
|
-
const cloudApi = cloudApiFactory(token);
|
|
1002
|
+
const cloudApi = await cloudApiFactory(ctx, token);
|
|
803
1003
|
try {
|
|
804
|
-
const storagePath = getTmpStoragePath();
|
|
1004
|
+
const storagePath = await getTmpStoragePath();
|
|
805
1005
|
const projectFolder = path__namespace.default.resolve(process.cwd());
|
|
806
1006
|
const packageJson2 = await loadPkg(ctx);
|
|
807
1007
|
if (!packageJson2) {
|
|
@@ -832,11 +1032,18 @@ async function upload(ctx, project, token, maxProjectFileSize) {
|
|
|
832
1032
|
process.exit(1);
|
|
833
1033
|
}
|
|
834
1034
|
const tarFilePath = path__namespace.default.resolve(storagePath, compressedFilename);
|
|
835
|
-
const fileStats =
|
|
1035
|
+
const fileStats = await fse__default.default.stat(tarFilePath);
|
|
836
1036
|
if (fileStats.size > maxProjectFileSize) {
|
|
837
|
-
|
|
1037
|
+
ctx.logger.log(
|
|
838
1038
|
"Unable to proceed: Your project is too big to be transferred, please use a git repo instead."
|
|
839
1039
|
);
|
|
1040
|
+
try {
|
|
1041
|
+
await fse__default.default.remove(tarFilePath);
|
|
1042
|
+
} catch (e) {
|
|
1043
|
+
ctx.logger.log("Unable to remove file: ", tarFilePath);
|
|
1044
|
+
ctx.logger.debug(e);
|
|
1045
|
+
}
|
|
1046
|
+
return;
|
|
840
1047
|
}
|
|
841
1048
|
ctx.logger.info("🚀 Uploading project...");
|
|
842
1049
|
const progressBar = ctx.logger.progressBar(100, "Upload Progress");
|
|
@@ -870,7 +1077,7 @@ async function upload(ctx, project, token, maxProjectFileSize) {
|
|
|
870
1077
|
}
|
|
871
1078
|
ctx.logger.debug(e);
|
|
872
1079
|
} finally {
|
|
873
|
-
|
|
1080
|
+
await fse__default.default.remove(tarFilePath);
|
|
874
1081
|
}
|
|
875
1082
|
process.exit(0);
|
|
876
1083
|
} catch (e) {
|
|
@@ -880,10 +1087,10 @@ async function upload(ctx, project, token, maxProjectFileSize) {
|
|
|
880
1087
|
}
|
|
881
1088
|
}
|
|
882
1089
|
async function getProject(ctx) {
|
|
883
|
-
const { project } = retrieve();
|
|
1090
|
+
const { project } = await retrieve();
|
|
884
1091
|
if (!project) {
|
|
885
1092
|
try {
|
|
886
|
-
return await action$
|
|
1093
|
+
return await action$2(ctx);
|
|
887
1094
|
} catch (e) {
|
|
888
1095
|
ctx.logger.error("An error occurred while deploying the project. Please try again later.");
|
|
889
1096
|
ctx.logger.debug(e);
|
|
@@ -892,9 +1099,9 @@ async function getProject(ctx) {
|
|
|
892
1099
|
}
|
|
893
1100
|
return project;
|
|
894
1101
|
}
|
|
895
|
-
const action$
|
|
896
|
-
const { getValidToken } = tokenServiceFactory(ctx);
|
|
897
|
-
const token = await getValidToken();
|
|
1102
|
+
const action$1 = async (ctx) => {
|
|
1103
|
+
const { getValidToken } = await tokenServiceFactory(ctx);
|
|
1104
|
+
const token = await getValidToken(ctx, promptLogin);
|
|
898
1105
|
if (!token) {
|
|
899
1106
|
return;
|
|
900
1107
|
}
|
|
@@ -902,10 +1109,15 @@ const action$2 = async (ctx) => {
|
|
|
902
1109
|
if (!project) {
|
|
903
1110
|
return;
|
|
904
1111
|
}
|
|
1112
|
+
const cloudApiService = await cloudApiFactory(ctx);
|
|
1113
|
+
try {
|
|
1114
|
+
await cloudApiService.track("willDeployWithCLI", { projectInternalName: project.name });
|
|
1115
|
+
} catch (e) {
|
|
1116
|
+
ctx.logger.debug("Failed to track willDeploy", e);
|
|
1117
|
+
}
|
|
905
1118
|
const notificationService = notificationServiceFactory(ctx);
|
|
906
1119
|
const buildLogsService = buildLogsServiceFactory(ctx);
|
|
907
|
-
const
|
|
908
|
-
const { data: cliConfig2 } = await cloudApiService2.config();
|
|
1120
|
+
const { data: cliConfig2 } = await cloudApiService.config();
|
|
909
1121
|
let maxSize = parseInt(cliConfig2.maxProjectFileSize, 10);
|
|
910
1122
|
if (Number.isNaN(maxSize)) {
|
|
911
1123
|
ctx.logger.debug(
|
|
@@ -914,9 +1126,18 @@ const action$2 = async (ctx) => {
|
|
|
914
1126
|
maxSize = 1e8;
|
|
915
1127
|
}
|
|
916
1128
|
const buildId = await upload(ctx, project, token, maxSize);
|
|
1129
|
+
if (!buildId) {
|
|
1130
|
+
return;
|
|
1131
|
+
}
|
|
917
1132
|
try {
|
|
918
1133
|
notificationService(`${apiConfig.apiBaseUrl}/notifications`, token, cliConfig2);
|
|
919
1134
|
await buildLogsService(`${apiConfig.apiBaseUrl}/v1/logs/${buildId}`, token, cliConfig2);
|
|
1135
|
+
ctx.logger.log(
|
|
1136
|
+
"Visit the following URL for deployment logs. Your deployment will be available here shortly."
|
|
1137
|
+
);
|
|
1138
|
+
ctx.logger.log(
|
|
1139
|
+
chalk__default.default.underline(`${apiConfig.dashboardBaseUrl}/projects/${project.name}/deployments`)
|
|
1140
|
+
);
|
|
920
1141
|
} catch (e) {
|
|
921
1142
|
if (e instanceof Error) {
|
|
922
1143
|
ctx.logger.error(e.message);
|
|
@@ -953,185 +1174,50 @@ const runAction = (name2, action2) => (...args) => {
|
|
|
953
1174
|
});
|
|
954
1175
|
};
|
|
955
1176
|
const command$3 = ({ command: command2, ctx }) => {
|
|
956
|
-
|
|
1177
|
+
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));
|
|
957
1178
|
};
|
|
958
1179
|
const deployProject = {
|
|
959
1180
|
name: "deploy-project",
|
|
960
1181
|
description: "Deploy a Strapi Cloud project",
|
|
961
|
-
action: action$
|
|
1182
|
+
action: action$1,
|
|
962
1183
|
command: command$3
|
|
963
1184
|
};
|
|
964
|
-
const openModule = import("open");
|
|
965
|
-
const action$1 = async (ctx) => {
|
|
966
|
-
const { logger } = ctx;
|
|
967
|
-
const tokenService = tokenServiceFactory(ctx);
|
|
968
|
-
const existingToken = await tokenService.retrieveToken();
|
|
969
|
-
const cloudApiService2 = cloudApiFactory(existingToken || void 0);
|
|
970
|
-
const trackFailedLogin = async () => {
|
|
971
|
-
try {
|
|
972
|
-
await cloudApiService2.track("didNotLogin", { loginMethod: "cli" });
|
|
973
|
-
} catch (e) {
|
|
974
|
-
logger.debug("Failed to track failed login", e);
|
|
975
|
-
}
|
|
976
|
-
};
|
|
977
|
-
if (existingToken) {
|
|
978
|
-
const isTokenValid = await tokenService.isTokenValid(existingToken);
|
|
979
|
-
if (isTokenValid) {
|
|
980
|
-
try {
|
|
981
|
-
const userInfo = await cloudApiService2.getUserInfo();
|
|
982
|
-
const { email } = userInfo.data.data;
|
|
983
|
-
if (email) {
|
|
984
|
-
logger.log(`You are already logged into your account (${email}).`);
|
|
985
|
-
} else {
|
|
986
|
-
logger.log("You are already logged in.");
|
|
987
|
-
}
|
|
988
|
-
return;
|
|
989
|
-
} catch (e) {
|
|
990
|
-
logger.debug("Failed to fetch user info", e);
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
let cliConfig2;
|
|
995
|
-
try {
|
|
996
|
-
logger.info("🔌 Connecting to the Strapi Cloud API...");
|
|
997
|
-
const config = await cloudApiService2.config();
|
|
998
|
-
cliConfig2 = config.data;
|
|
999
|
-
} catch (e) {
|
|
1000
|
-
logger.error("🥲 Oops! Something went wrong while logging you in. Please try again.");
|
|
1001
|
-
logger.debug(e);
|
|
1002
|
-
return;
|
|
1003
|
-
}
|
|
1004
|
-
try {
|
|
1005
|
-
await cloudApiService2.track("willLoginAttempt", {});
|
|
1006
|
-
} catch (e) {
|
|
1007
|
-
logger.debug("Failed to track login attempt", e);
|
|
1008
|
-
}
|
|
1009
|
-
logger.debug("🔐 Creating device authentication request...", {
|
|
1010
|
-
client_id: cliConfig2.clientId,
|
|
1011
|
-
scope: cliConfig2.scope,
|
|
1012
|
-
audience: cliConfig2.audience
|
|
1013
|
-
});
|
|
1014
|
-
const deviceAuthResponse = await axios__default.default.post(cliConfig2.deviceCodeAuthUrl, {
|
|
1015
|
-
client_id: cliConfig2.clientId,
|
|
1016
|
-
scope: cliConfig2.scope,
|
|
1017
|
-
audience: cliConfig2.audience
|
|
1018
|
-
}).catch((e) => {
|
|
1019
|
-
logger.error("There was an issue with the authentication process. Please try again.");
|
|
1020
|
-
if (e.message) {
|
|
1021
|
-
logger.debug(e.message, e);
|
|
1022
|
-
} else {
|
|
1023
|
-
logger.debug(e);
|
|
1024
|
-
}
|
|
1025
|
-
});
|
|
1026
|
-
openModule.then((open) => {
|
|
1027
|
-
open.default(deviceAuthResponse.data.verification_uri_complete).catch((e) => {
|
|
1028
|
-
logger.error("We encountered an issue opening the browser. Please try again later.");
|
|
1029
|
-
logger.debug(e.message, e);
|
|
1030
|
-
});
|
|
1031
|
-
});
|
|
1032
|
-
logger.log("If a browser tab does not open automatically, please follow the next steps:");
|
|
1033
|
-
logger.log(
|
|
1034
|
-
`1. Open this url in your device: ${deviceAuthResponse.data.verification_uri_complete}`
|
|
1035
|
-
);
|
|
1036
|
-
logger.log(
|
|
1037
|
-
`2. Enter the following code: ${deviceAuthResponse.data.user_code} and confirm to login.
|
|
1038
|
-
`
|
|
1039
|
-
);
|
|
1040
|
-
const tokenPayload = {
|
|
1041
|
-
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
1042
|
-
device_code: deviceAuthResponse.data.device_code,
|
|
1043
|
-
client_id: cliConfig2.clientId
|
|
1044
|
-
};
|
|
1045
|
-
let isAuthenticated = false;
|
|
1046
|
-
const authenticate = async () => {
|
|
1047
|
-
const spinner = logger.spinner("Waiting for authentication");
|
|
1048
|
-
spinner.start();
|
|
1049
|
-
const spinnerFail = () => spinner.fail("Authentication failed!");
|
|
1050
|
-
while (!isAuthenticated) {
|
|
1051
|
-
try {
|
|
1052
|
-
const tokenResponse = await axios__default.default.post(cliConfig2.tokenUrl, tokenPayload);
|
|
1053
|
-
const authTokenData = tokenResponse.data;
|
|
1054
|
-
if (tokenResponse.status === 200) {
|
|
1055
|
-
try {
|
|
1056
|
-
logger.debug("🔐 Validating token...");
|
|
1057
|
-
await tokenService.validateToken(authTokenData.id_token, cliConfig2.jwksUrl);
|
|
1058
|
-
logger.debug("🔐 Token validation successful!");
|
|
1059
|
-
} catch (e) {
|
|
1060
|
-
logger.debug(e);
|
|
1061
|
-
spinnerFail();
|
|
1062
|
-
throw new Error("Unable to proceed: Token validation failed");
|
|
1063
|
-
}
|
|
1064
|
-
const cloudApiService22 = cloudApiFactory(authTokenData.access_token);
|
|
1065
|
-
logger.debug("🔍 Fetching user information...");
|
|
1066
|
-
await cloudApiService22.getUserInfo();
|
|
1067
|
-
logger.debug("🔍 User information fetched successfully!");
|
|
1068
|
-
try {
|
|
1069
|
-
logger.debug("📝 Saving login information...");
|
|
1070
|
-
await tokenService.saveToken(authTokenData.access_token);
|
|
1071
|
-
logger.debug("📝 Login information saved successfully!");
|
|
1072
|
-
isAuthenticated = true;
|
|
1073
|
-
} catch (e) {
|
|
1074
|
-
logger.error(
|
|
1075
|
-
"There was a problem saving your login information. Please try logging in again."
|
|
1076
|
-
);
|
|
1077
|
-
logger.debug(e);
|
|
1078
|
-
spinnerFail();
|
|
1079
|
-
return;
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
} catch (e) {
|
|
1083
|
-
if (e.message === "Unable to proceed: Token validation failed") {
|
|
1084
|
-
logger.error(
|
|
1085
|
-
"There seems to be a problem with your login information. Please try logging in again."
|
|
1086
|
-
);
|
|
1087
|
-
spinnerFail();
|
|
1088
|
-
await trackFailedLogin();
|
|
1089
|
-
return;
|
|
1090
|
-
}
|
|
1091
|
-
if (e.response?.data.error && !["authorization_pending", "slow_down"].includes(e.response.data.error)) {
|
|
1092
|
-
logger.debug(e);
|
|
1093
|
-
spinnerFail();
|
|
1094
|
-
await trackFailedLogin();
|
|
1095
|
-
return;
|
|
1096
|
-
}
|
|
1097
|
-
await new Promise((resolve) => {
|
|
1098
|
-
setTimeout(resolve, deviceAuthResponse.data.interval * 1e3);
|
|
1099
|
-
});
|
|
1100
|
-
}
|
|
1101
|
-
}
|
|
1102
|
-
spinner.succeed("Authentication successful!");
|
|
1103
|
-
logger.log("You are now logged into Strapi Cloud.");
|
|
1104
|
-
try {
|
|
1105
|
-
await cloudApiService2.track("didLogin", { loginMethod: "cli" });
|
|
1106
|
-
} catch (e) {
|
|
1107
|
-
logger.debug("Failed to track login", e);
|
|
1108
|
-
}
|
|
1109
|
-
};
|
|
1110
|
-
await authenticate();
|
|
1111
|
-
};
|
|
1112
1185
|
const command$2 = ({ command: command2, ctx }) => {
|
|
1113
|
-
|
|
1186
|
+
command2.command("cloud:login").alias("login").description("Strapi Cloud Login").addHelpText(
|
|
1114
1187
|
"after",
|
|
1115
1188
|
"\nAfter running this command, you will be prompted to enter your authentication information."
|
|
1116
|
-
).option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("login",
|
|
1189
|
+
).option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("login", loginAction)(ctx));
|
|
1117
1190
|
};
|
|
1118
1191
|
const login = {
|
|
1119
1192
|
name: "login",
|
|
1120
1193
|
description: "Strapi Cloud Login",
|
|
1121
|
-
action:
|
|
1194
|
+
action: loginAction,
|
|
1122
1195
|
command: command$2
|
|
1123
1196
|
};
|
|
1197
|
+
const openModule = import("open");
|
|
1124
1198
|
const action = async (ctx) => {
|
|
1125
1199
|
const { logger } = ctx;
|
|
1126
|
-
const { retrieveToken, eraseToken } = tokenServiceFactory(ctx);
|
|
1200
|
+
const { retrieveToken, eraseToken } = await tokenServiceFactory(ctx);
|
|
1127
1201
|
const token = await retrieveToken();
|
|
1128
1202
|
if (!token) {
|
|
1129
1203
|
logger.log("You're already logged out.");
|
|
1130
1204
|
return;
|
|
1131
1205
|
}
|
|
1132
|
-
const
|
|
1206
|
+
const cloudApiService = await cloudApiFactory(ctx, token);
|
|
1207
|
+
const config = await cloudApiService.config();
|
|
1208
|
+
const cliConfig2 = config.data;
|
|
1133
1209
|
try {
|
|
1134
1210
|
await eraseToken();
|
|
1211
|
+
openModule.then((open) => {
|
|
1212
|
+
open.default(
|
|
1213
|
+
`${cliConfig2.baseUrl}/oidc/logout?client_id=${encodeURIComponent(
|
|
1214
|
+
cliConfig2.clientId
|
|
1215
|
+
)}&logout_hint=${encodeURIComponent(token)}
|
|
1216
|
+
`
|
|
1217
|
+
).catch((e) => {
|
|
1218
|
+
logger.debug(e.message, e);
|
|
1219
|
+
});
|
|
1220
|
+
});
|
|
1135
1221
|
logger.log(
|
|
1136
1222
|
"🔌 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."
|
|
1137
1223
|
);
|
|
@@ -1140,13 +1226,13 @@ const action = async (ctx) => {
|
|
|
1140
1226
|
logger.debug(e);
|
|
1141
1227
|
}
|
|
1142
1228
|
try {
|
|
1143
|
-
await
|
|
1229
|
+
await cloudApiService.track("didLogout", { loginMethod: "cli" });
|
|
1144
1230
|
} catch (e) {
|
|
1145
1231
|
logger.debug("Failed to track logout event", e);
|
|
1146
1232
|
}
|
|
1147
1233
|
};
|
|
1148
1234
|
const command$1 = ({ command: command2, ctx }) => {
|
|
1149
|
-
|
|
1235
|
+
command2.command("cloud:logout").alias("logout").description("Strapi Cloud Logout").option("-d, --debug", "Enable debugging mode with verbose logs").option("-s, --silent", "Don't log anything").action(() => runAction("logout", action)(ctx));
|
|
1150
1236
|
};
|
|
1151
1237
|
const logout = {
|
|
1152
1238
|
name: "logout",
|
|
@@ -1155,12 +1241,12 @@ const logout = {
|
|
|
1155
1241
|
command: command$1
|
|
1156
1242
|
};
|
|
1157
1243
|
const command = ({ command: command2, ctx }) => {
|
|
1158
|
-
|
|
1244
|
+
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));
|
|
1159
1245
|
};
|
|
1160
1246
|
const createProject = {
|
|
1161
1247
|
name: "create-project",
|
|
1162
1248
|
description: "Create a new project",
|
|
1163
|
-
action: action$
|
|
1249
|
+
action: action$2,
|
|
1164
1250
|
command
|
|
1165
1251
|
};
|
|
1166
1252
|
const cli = {
|
|
@@ -1171,25 +1257,25 @@ const cli = {
|
|
|
1171
1257
|
};
|
|
1172
1258
|
const cloudCommands = [deployProject, login, logout];
|
|
1173
1259
|
async function initCloudCLIConfig() {
|
|
1174
|
-
const localConfig = getLocalConfig();
|
|
1260
|
+
const localConfig = await getLocalConfig();
|
|
1175
1261
|
if (!localConfig.deviceId) {
|
|
1176
1262
|
localConfig.deviceId = crypto__default.default.randomUUID();
|
|
1177
1263
|
}
|
|
1178
|
-
saveLocalConfig(localConfig);
|
|
1264
|
+
await saveLocalConfig(localConfig);
|
|
1179
1265
|
}
|
|
1180
|
-
function buildStrapiCloudCommands({
|
|
1266
|
+
async function buildStrapiCloudCommands({
|
|
1181
1267
|
command: command2,
|
|
1182
1268
|
ctx,
|
|
1183
1269
|
argv
|
|
1184
1270
|
}) {
|
|
1185
|
-
initCloudCLIConfig();
|
|
1186
|
-
|
|
1271
|
+
await initCloudCLIConfig();
|
|
1272
|
+
for (const cloudCommand of cloudCommands) {
|
|
1187
1273
|
try {
|
|
1188
|
-
cloudCommand.command({ command: command2, ctx, argv });
|
|
1274
|
+
await cloudCommand.command({ command: command2, ctx, argv });
|
|
1189
1275
|
} catch (e) {
|
|
1190
1276
|
console.error(`Failed to load command ${cloudCommand.name}`, e);
|
|
1191
1277
|
}
|
|
1192
|
-
}
|
|
1278
|
+
}
|
|
1193
1279
|
}
|
|
1194
1280
|
exports.buildStrapiCloudCommands = buildStrapiCloudCommands;
|
|
1195
1281
|
exports.cli = cli;
|