storyblok 4.8.0 → 4.10.0
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.mjs +320 -167
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -5,12 +5,12 @@ import { dirname } from 'pathe';
|
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
import { Command } from 'commander';
|
|
7
7
|
import { readPackageUp } from 'read-package-up';
|
|
8
|
-
import path, { join, resolve, parse, dirname as dirname$1, extname } from 'node:path';
|
|
8
|
+
import path, { join, resolve, parse, dirname as dirname$1, extname, relative } from 'node:path';
|
|
9
9
|
import { MultiBar, Presets } from 'cli-progress';
|
|
10
10
|
import { Spinner } from '@topcli/spinner';
|
|
11
11
|
import fs, { mkdir, writeFile, readFile as readFile$1, appendFile, access, readdir } from 'node:fs/promises';
|
|
12
12
|
import filenamify from 'filenamify';
|
|
13
|
-
import { mkdirSync, appendFileSync, existsSync, readdirSync, unlinkSync, readFileSync } from 'node:fs';
|
|
13
|
+
import { mkdirSync, appendFileSync, writeFileSync, existsSync, readdirSync, unlinkSync, readFileSync } from 'node:fs';
|
|
14
14
|
import { select, password, input, confirm } from '@inquirer/prompts';
|
|
15
15
|
import { ManagementApiClient } from '@storyblok/management-api-client';
|
|
16
16
|
import { RateLimit, Sema } from 'async-sema';
|
|
@@ -34,7 +34,8 @@ const commands = {
|
|
|
34
34
|
TYPES: "types",
|
|
35
35
|
DATASOURCES: "datasources",
|
|
36
36
|
CREATE: "create",
|
|
37
|
-
LOGS: "logs"
|
|
37
|
+
LOGS: "logs",
|
|
38
|
+
REPORTS: "reports"
|
|
38
39
|
};
|
|
39
40
|
const colorPalette = {
|
|
40
41
|
PRIMARY: "#8d60ff",
|
|
@@ -51,7 +52,8 @@ const colorPalette = {
|
|
|
51
52
|
TAGS: "#fbbf24",
|
|
52
53
|
PRESETS: "#a855f7",
|
|
53
54
|
DATASOURCES: "#4ade80",
|
|
54
|
-
LOGS: "#4ade80"
|
|
55
|
+
LOGS: "#4ade80",
|
|
56
|
+
REPORTS: "#4ade80"
|
|
55
57
|
};
|
|
56
58
|
const regions = {
|
|
57
59
|
EU: "eu",
|
|
@@ -92,7 +94,8 @@ const regionNames = {
|
|
|
92
94
|
SB_Agent_Version: process.env.npm_package_version || "4.x"
|
|
93
95
|
});
|
|
94
96
|
const directories = {
|
|
95
|
-
log: "logs"
|
|
97
|
+
log: "logs",
|
|
98
|
+
report: "reports"
|
|
96
99
|
};
|
|
97
100
|
|
|
98
101
|
class FetchError extends Error {
|
|
@@ -701,6 +704,22 @@ const saveToFile = async (filePath, data, options) => {
|
|
|
701
704
|
handleFileSystemError("write", writeError);
|
|
702
705
|
}
|
|
703
706
|
};
|
|
707
|
+
const saveToFileSync = (filePath, data, options) => {
|
|
708
|
+
const resolvedPath = parse(filePath).dir;
|
|
709
|
+
if (resolvedPath) {
|
|
710
|
+
try {
|
|
711
|
+
mkdirSync(resolvedPath, { recursive: true });
|
|
712
|
+
} catch (mkdirError) {
|
|
713
|
+
handleFileSystemError("mkdir", mkdirError);
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
try {
|
|
718
|
+
writeFileSync(filePath, data, options);
|
|
719
|
+
} catch (writeError) {
|
|
720
|
+
handleFileSystemError("write", writeError);
|
|
721
|
+
}
|
|
722
|
+
};
|
|
704
723
|
const appendToFile = async (filePath, data, options) => {
|
|
705
724
|
const resolvedPath = parse(filePath).dir;
|
|
706
725
|
try {
|
|
@@ -747,6 +766,12 @@ const resolvePath = (path, folder) => {
|
|
|
747
766
|
}
|
|
748
767
|
return resolve(resolve(process.cwd(), ".storyblok"), folder);
|
|
749
768
|
};
|
|
769
|
+
function resolveCommandPath(commandPath, space, baseDir) {
|
|
770
|
+
if (space) {
|
|
771
|
+
return resolvePath(baseDir, join(commandPath, space));
|
|
772
|
+
}
|
|
773
|
+
return resolvePath(baseDir, commandPath);
|
|
774
|
+
}
|
|
750
775
|
const getComponentNameFromFilename = (filename) => {
|
|
751
776
|
return filename.replace(/\.js$/, "");
|
|
752
777
|
};
|
|
@@ -770,11 +795,101 @@ async function readJsonFile(filePath) {
|
|
|
770
795
|
function importModule(filePath) {
|
|
771
796
|
return import(`file://${filePath}`);
|
|
772
797
|
}
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
798
|
+
|
|
799
|
+
const REPORT_STATUS = {
|
|
800
|
+
unfinished: "UNFINISHED",
|
|
801
|
+
success: "SUCCESS",
|
|
802
|
+
partialSuccess: "PARTIAL_SUCCESS",
|
|
803
|
+
failure: "FAILURE"
|
|
804
|
+
};
|
|
805
|
+
class Reporter {
|
|
806
|
+
filePath;
|
|
807
|
+
enabled;
|
|
808
|
+
startedAt = /* @__PURE__ */ new Date();
|
|
809
|
+
maxFiles;
|
|
810
|
+
report = {
|
|
811
|
+
status: REPORT_STATUS.unfinished,
|
|
812
|
+
meta: {
|
|
813
|
+
startedAt: this.startedAt.toISOString()
|
|
814
|
+
},
|
|
815
|
+
summary: {}
|
|
816
|
+
};
|
|
817
|
+
constructor(options) {
|
|
818
|
+
this.enabled = options?.enabled || false;
|
|
819
|
+
this.filePath = options?.filePath ?? `./${Date.now()}.json`;
|
|
820
|
+
this.maxFiles = options?.maxFiles;
|
|
821
|
+
}
|
|
822
|
+
addMeta(key, value) {
|
|
823
|
+
this.report.meta[key] = value;
|
|
824
|
+
return this;
|
|
825
|
+
}
|
|
826
|
+
addSummary(key, value) {
|
|
827
|
+
this.report.summary[key] = value;
|
|
828
|
+
return this;
|
|
829
|
+
}
|
|
830
|
+
finalize() {
|
|
831
|
+
if (!this.enabled) {
|
|
832
|
+
return;
|
|
833
|
+
}
|
|
834
|
+
const endedAt = /* @__PURE__ */ new Date();
|
|
835
|
+
this.report.meta.endedAt = endedAt.toISOString();
|
|
836
|
+
this.report.meta.durationMs = endedAt.getTime() - this.startedAt.getTime();
|
|
837
|
+
this.updateStatus();
|
|
838
|
+
saveToFileSync(this.filePath, JSON.stringify(this.report, null, 2));
|
|
839
|
+
if (this.maxFiles !== void 0) {
|
|
840
|
+
this.pruneOldFiles();
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
updateStatus() {
|
|
844
|
+
let succeededTotal = 0;
|
|
845
|
+
let failedTotal = 0;
|
|
846
|
+
for (const item of Object.values(this.report.summary)) {
|
|
847
|
+
succeededTotal += item.succeeded;
|
|
848
|
+
failedTotal += item.failed;
|
|
849
|
+
}
|
|
850
|
+
if (failedTotal === 0) {
|
|
851
|
+
this.report.status = REPORT_STATUS.success;
|
|
852
|
+
} else if (succeededTotal > 0) {
|
|
853
|
+
this.report.status = REPORT_STATUS.partialSuccess;
|
|
854
|
+
} else {
|
|
855
|
+
this.report.status = REPORT_STATUS.failure;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
pruneOldFiles() {
|
|
859
|
+
if (this.maxFiles === void 0) {
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
862
|
+
const dir = dirname$1(this.filePath);
|
|
863
|
+
const ext = extname(this.filePath);
|
|
864
|
+
Reporter.pruneReportFiles(dir, this.maxFiles, ext);
|
|
865
|
+
}
|
|
866
|
+
static pruneReportFiles(directory, keep, extension = ".json") {
|
|
867
|
+
if (!existsSync(directory)) {
|
|
868
|
+
return 0;
|
|
869
|
+
}
|
|
870
|
+
const files = readdirSync(directory).filter((file) => extname(file) === extension).sort();
|
|
871
|
+
const filesToDelete = files.length - keep;
|
|
872
|
+
if (filesToDelete <= 0) {
|
|
873
|
+
return 0;
|
|
874
|
+
}
|
|
875
|
+
for (const file of files.slice(0, filesToDelete)) {
|
|
876
|
+
unlinkSync(join(directory, file));
|
|
877
|
+
}
|
|
878
|
+
return filesToDelete;
|
|
879
|
+
}
|
|
880
|
+
static listReportFiles(directory, extension = ".json") {
|
|
881
|
+
if (!existsSync(directory)) {
|
|
882
|
+
return [];
|
|
883
|
+
}
|
|
884
|
+
return readdirSync(directory).filter((file) => extname(file) === extension).map((f) => relative(process.cwd(), join(directory, f))).sort();
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
let reporterInstance = null;
|
|
888
|
+
function getReporter(options) {
|
|
889
|
+
if (!reporterInstance) {
|
|
890
|
+
reporterInstance = new Reporter(options);
|
|
776
891
|
}
|
|
777
|
-
return
|
|
892
|
+
return reporterInstance;
|
|
778
893
|
}
|
|
779
894
|
|
|
780
895
|
class FileTransport {
|
|
@@ -896,7 +1011,7 @@ let programInstance = null;
|
|
|
896
1011
|
function getProgram() {
|
|
897
1012
|
if (!programInstance) {
|
|
898
1013
|
programInstance = new Command();
|
|
899
|
-
programInstance.name(packageJson.name).description(packageJson.description || "").version(packageJson.version).hook("preAction", (_, actionCmd) => {
|
|
1014
|
+
programInstance.name(packageJson.name).description(packageJson.description || "").version(packageJson.version, "-v, --vers", "Output the current version").helpOption("-h, --help", "Display help for command").option("--verbose", "Enable verbose output").hook("preAction", (_, actionCmd) => {
|
|
900
1015
|
const options = actionCmd.optsWithGlobals();
|
|
901
1016
|
const commandPieces = [];
|
|
902
1017
|
for (let c = actionCmd; c; c = c.parent) {
|
|
@@ -905,7 +1020,7 @@ function getProgram() {
|
|
|
905
1020
|
const command = commandPieces.join(" ");
|
|
906
1021
|
const runId = Date.now();
|
|
907
1022
|
const transports = [];
|
|
908
|
-
const logsPath =
|
|
1023
|
+
const logsPath = resolveCommandPath(directories.log, options.space, options.path);
|
|
909
1024
|
const logFilename = `${commandPieces.join("-")}-${runId}.jsonl`;
|
|
910
1025
|
const filePath = path.join(logsPath, logFilename);
|
|
911
1026
|
transports.push(new FileTransport({
|
|
@@ -917,6 +1032,10 @@ function getProgram() {
|
|
|
917
1032
|
transports
|
|
918
1033
|
});
|
|
919
1034
|
getUI({ enabled: true });
|
|
1035
|
+
const reportPath = resolveCommandPath(directories.report, options.space, options.path);
|
|
1036
|
+
const reportFilename = `${commandPieces.join("-")}-${runId}.jsonl`;
|
|
1037
|
+
const reportFilePath = path.join(reportPath, reportFilename);
|
|
1038
|
+
getReporter({ enabled: true, filePath: reportFilePath }).addMeta("command", command).addMeta("cliVersion", packageJson.version).addMeta("runId", String(runId)).addMeta("logPath", filePath).addMeta("config", options);
|
|
920
1039
|
});
|
|
921
1040
|
programInstance.configureOutput({
|
|
922
1041
|
writeErr: (str) => handleError(new Error(str))
|
|
@@ -1172,7 +1291,7 @@ function session() {
|
|
|
1172
1291
|
return sessionInstance;
|
|
1173
1292
|
}
|
|
1174
1293
|
|
|
1175
|
-
const program$
|
|
1294
|
+
const program$h = getProgram();
|
|
1176
1295
|
const allRegionsText = Object.values(regions).join(",");
|
|
1177
1296
|
const loginStrategy = {
|
|
1178
1297
|
message: "How would you like to login?",
|
|
@@ -1189,12 +1308,12 @@ const loginStrategy = {
|
|
|
1189
1308
|
}
|
|
1190
1309
|
]
|
|
1191
1310
|
};
|
|
1192
|
-
program$
|
|
1311
|
+
program$h.command(commands.LOGIN).description("Login to the Storyblok CLI").option("-t, --token <token>", "Token to login directly without questions, like for CI environments").option(
|
|
1193
1312
|
"-r, --region <region>",
|
|
1194
1313
|
`The region you would like to work in. Please keep in mind that the region must match the region of your space. This region flag will be used for the other cli's commands. You can use the values: ${allRegionsText}.`
|
|
1195
1314
|
).action(async (options) => {
|
|
1196
1315
|
konsola.title(`${commands.LOGIN}`, colorPalette.LOGIN);
|
|
1197
|
-
const verbose = program$
|
|
1316
|
+
const verbose = program$h.opts().verbose;
|
|
1198
1317
|
const { token, region } = options;
|
|
1199
1318
|
const { state, updateSession, persistCredentials, initializeSession } = session();
|
|
1200
1319
|
await initializeSession();
|
|
@@ -1322,10 +1441,10 @@ program$g.command(commands.LOGIN).description("Login to the Storyblok CLI").opti
|
|
|
1322
1441
|
konsola.br();
|
|
1323
1442
|
});
|
|
1324
1443
|
|
|
1325
|
-
const program$
|
|
1326
|
-
program$
|
|
1444
|
+
const program$g = getProgram();
|
|
1445
|
+
program$g.command(commands.LOGOUT).description("Logout from the Storyblok CLI").action(async () => {
|
|
1327
1446
|
konsola.title(`${commands.LOGOUT}`, colorPalette.LOGOUT);
|
|
1328
|
-
const verbose = program$
|
|
1447
|
+
const verbose = program$g.opts().verbose;
|
|
1329
1448
|
try {
|
|
1330
1449
|
const { state, initializeSession } = session();
|
|
1331
1450
|
await initializeSession();
|
|
@@ -1373,10 +1492,10 @@ async function openSignupInBrowser(url) {
|
|
|
1373
1492
|
}
|
|
1374
1493
|
}
|
|
1375
1494
|
|
|
1376
|
-
const program$
|
|
1377
|
-
program$
|
|
1495
|
+
const program$f = getProgram();
|
|
1496
|
+
program$f.command(commands.SIGNUP).description("Sign up for Storyblok").action(async () => {
|
|
1378
1497
|
konsola.title(`${commands.SIGNUP}`, colorPalette.SIGNUP);
|
|
1379
|
-
const verbose = program$
|
|
1498
|
+
const verbose = program$f.opts().verbose;
|
|
1380
1499
|
const { state, initializeSession } = session();
|
|
1381
1500
|
await initializeSession();
|
|
1382
1501
|
if (state.isLoggedIn && !state.envLogin) {
|
|
@@ -1398,10 +1517,10 @@ program$e.command(commands.SIGNUP).description("Sign up for Storyblok").action(a
|
|
|
1398
1517
|
konsola.br();
|
|
1399
1518
|
});
|
|
1400
1519
|
|
|
1401
|
-
const program$
|
|
1402
|
-
program$
|
|
1520
|
+
const program$e = getProgram();
|
|
1521
|
+
program$e.command(commands.USER).description("Get the current user").action(async () => {
|
|
1403
1522
|
konsola.title(`${commands.USER}`, colorPalette.USER);
|
|
1404
|
-
const verbose = program$
|
|
1523
|
+
const verbose = program$e.opts().verbose;
|
|
1405
1524
|
const { state, initializeSession } = session();
|
|
1406
1525
|
await initializeSession();
|
|
1407
1526
|
if (!requireAuthentication(state)) {
|
|
@@ -1430,8 +1549,8 @@ program$d.command(commands.USER).description("Get the current user").action(asyn
|
|
|
1430
1549
|
konsola.br();
|
|
1431
1550
|
});
|
|
1432
1551
|
|
|
1433
|
-
const program$
|
|
1434
|
-
const componentsCommand = program$
|
|
1552
|
+
const program$d = getProgram();
|
|
1553
|
+
const componentsCommand = program$d.command(commands.COMPONENTS).alias("comp").description(`Manage your space's block schema`).option("-s, --space <space>", "space ID").option("-p, --path <path>", "path to save the file. Default is .storyblok/components");
|
|
1435
1554
|
|
|
1436
1555
|
const fetchComponents = async (spaceId) => {
|
|
1437
1556
|
try {
|
|
@@ -1811,10 +1930,10 @@ async function readConsolidatedFiles$1(resolvedPath, suffix) {
|
|
|
1811
1930
|
};
|
|
1812
1931
|
}
|
|
1813
1932
|
|
|
1814
|
-
const program$
|
|
1933
|
+
const program$c = getProgram();
|
|
1815
1934
|
componentsCommand.command("pull [componentName]").option("-f, --filename <filename>", "custom name to be used in file(s) name instead of space id").option("--sf, --separate-files", "Argument to create a single file for each component").option("--su, --suffix <suffix>", "suffix to add to the file name (e.g. components.<suffix>.json)").description(`Download your space's components schema as json. Optionally specify a component name to pull a single component.`).action(async (componentName, options) => {
|
|
1816
1935
|
konsola.title(`${commands.COMPONENTS}`, colorPalette.COMPONENTS, componentName ? `Pulling component ${componentName}...` : "Pulling components...");
|
|
1817
|
-
const verbose = program$
|
|
1936
|
+
const verbose = program$c.opts().verbose;
|
|
1818
1937
|
const { space, path } = componentsCommand.opts();
|
|
1819
1938
|
const { separateFiles, suffix, filename = "components" } = options;
|
|
1820
1939
|
const { state, initializeSession } = session();
|
|
@@ -1952,7 +2071,7 @@ function buildDependencyGraph(context) {
|
|
|
1952
2071
|
graph.nodes.set(nodeId, node);
|
|
1953
2072
|
});
|
|
1954
2073
|
spaceState.local.groups.forEach((group) => {
|
|
1955
|
-
if (group.parent_uuid) {
|
|
2074
|
+
if (group.parent_uuid && group.parent_id && group.parent_uuid !== group.uuid) {
|
|
1956
2075
|
const childId = `group:${group.uuid}`;
|
|
1957
2076
|
const parentId = `group:${group.parent_uuid}`;
|
|
1958
2077
|
addDependency(childId, parentId);
|
|
@@ -2847,12 +2966,13 @@ async function pushWithDependencyGraph(space, spaceState, maxConcurrency = 5) {
|
|
|
2847
2966
|
return results;
|
|
2848
2967
|
}
|
|
2849
2968
|
|
|
2850
|
-
const program$
|
|
2969
|
+
const program$b = getProgram();
|
|
2851
2970
|
componentsCommand.command("push [componentName]").description(`Push your space's components schema as json`).option("-f, --from <from>", "source space id").option("--fi, --filter <filter>", "glob filter to apply to the components before pushing").option("--sf, --separate-files", "Read from separate files instead of consolidated files").option("--su, --suffix <suffix>", "Suffix to add to the component name").action(async (componentName, options) => {
|
|
2852
2971
|
konsola.title(`${commands.COMPONENTS}`, colorPalette.COMPONENTS, componentName ? `Pushing component ${componentName}...` : "Pushing components...");
|
|
2853
|
-
const verbose = program$
|
|
2972
|
+
const verbose = program$b.opts().verbose;
|
|
2854
2973
|
const { space, path } = componentsCommand.opts();
|
|
2855
|
-
const {
|
|
2974
|
+
const { filter } = options;
|
|
2975
|
+
const fromSpace = options.from || space;
|
|
2856
2976
|
const { state, initializeSession } = session();
|
|
2857
2977
|
await initializeSession();
|
|
2858
2978
|
if (!requireAuthentication(state, verbose)) {
|
|
@@ -2862,10 +2982,7 @@ componentsCommand.command("push [componentName]").description(`Push your space's
|
|
|
2862
2982
|
handleError(new CommandError(`Please provide the target space as argument --space TARGET_SPACE_ID.`), verbose);
|
|
2863
2983
|
return;
|
|
2864
2984
|
}
|
|
2865
|
-
|
|
2866
|
-
options.from = space;
|
|
2867
|
-
}
|
|
2868
|
-
konsola.info(`Attempting to push components ${chalk.bold("from")} space ${chalk.hex(colorPalette.COMPONENTS)(options.from)} ${chalk.bold("to")} ${chalk.hex(colorPalette.COMPONENTS)(space)}`);
|
|
2985
|
+
konsola.info(`Attempting to push components ${chalk.bold("from")} space ${chalk.hex(colorPalette.COMPONENTS)(fromSpace)} ${chalk.bold("to")} ${chalk.hex(colorPalette.COMPONENTS)(space)}`);
|
|
2869
2986
|
konsola.br();
|
|
2870
2987
|
const { password, region } = state;
|
|
2871
2988
|
let requestCount = 0;
|
|
@@ -2883,7 +3000,7 @@ componentsCommand.command("push [componentName]").description(`Push your space's
|
|
|
2883
3000
|
const componentsData = await readComponentsFiles({
|
|
2884
3001
|
...options,
|
|
2885
3002
|
path,
|
|
2886
|
-
|
|
3003
|
+
from: fromSpace
|
|
2887
3004
|
});
|
|
2888
3005
|
const localData = {
|
|
2889
3006
|
...componentsData,
|
|
@@ -3046,11 +3163,11 @@ const saveLanguagesToFile = async (space, internationalizationOptions, options)
|
|
|
3046
3163
|
}
|
|
3047
3164
|
};
|
|
3048
3165
|
|
|
3049
|
-
const program$
|
|
3050
|
-
const languagesCommand = program$
|
|
3166
|
+
const program$a = getProgram();
|
|
3167
|
+
const languagesCommand = program$a.command(commands.LANGUAGES).alias("lang").description(`Manage your space's languages`).option("-s, --space <space>", "space ID").option("-p, --path <path>", "path to save the file. Default is .storyblok/languages");
|
|
3051
3168
|
languagesCommand.command("pull").description(`Download your space's languages schema as json`).option("-f, --filename <filename>", "filename to save the file as <filename>.<suffix>.json").option("--su, --suffix <suffix>", "suffix to add to the file name (e.g. languages.<suffix>.json). By default, the space ID is used.").action(async (options) => {
|
|
3052
3169
|
konsola.title(`${commands.LANGUAGES}`, colorPalette.LANGUAGES);
|
|
3053
|
-
const verbose = program$
|
|
3170
|
+
const verbose = program$a.opts().verbose;
|
|
3054
3171
|
const { space, path } = languagesCommand.opts();
|
|
3055
3172
|
const { filename = "languages", suffix = options.space } = options;
|
|
3056
3173
|
const { state, initializeSession } = session();
|
|
@@ -3097,8 +3214,8 @@ languagesCommand.command("pull").description(`Download your space's languages sc
|
|
|
3097
3214
|
konsola.br();
|
|
3098
3215
|
});
|
|
3099
3216
|
|
|
3100
|
-
const program$
|
|
3101
|
-
const migrationsCommand = program$
|
|
3217
|
+
const program$9 = getProgram();
|
|
3218
|
+
const migrationsCommand = program$9.command(commands.MIGRATIONS).alias("mig").description(`Manage your space's migrations`).option("-s, --space <space>", "space ID").option("-p, --path <path>", "path to save the file. Default is .storyblok/migrations");
|
|
3102
3219
|
|
|
3103
3220
|
const getMigrationTemplate = () => {
|
|
3104
3221
|
return `export default function (block) {
|
|
@@ -3817,6 +3934,7 @@ migrationsCommand.command("run [componentName]").description("Run migrations").o
|
|
|
3817
3934
|
const program = getProgram();
|
|
3818
3935
|
const ui = getUI();
|
|
3819
3936
|
const logger = getLogger();
|
|
3937
|
+
const reporter = getReporter();
|
|
3820
3938
|
ui.title(`${commands.MIGRATIONS}`, colorPalette.MIGRATIONS, componentName ? `Running migrations for component ${componentName}...` : "Running migrations...");
|
|
3821
3939
|
logger.info("Migration started");
|
|
3822
3940
|
if (options.dryRun) {
|
|
@@ -3919,21 +4037,26 @@ migrationsCommand.command("run [componentName]").description("Run migrations").o
|
|
|
3919
4037
|
ui.info(migrationSummary);
|
|
3920
4038
|
const updateSummary = updateStream.getSummary();
|
|
3921
4039
|
ui.info(updateSummary);
|
|
3922
|
-
const
|
|
3923
|
-
const
|
|
4040
|
+
const migrationStreamResults = migrationStream.getResults();
|
|
4041
|
+
const migrationResults = {
|
|
4042
|
+
total: migrationStreamResults.totalProcessed,
|
|
4043
|
+
succeeded: migrationStreamResults.successful.length,
|
|
4044
|
+
skipped: migrationStreamResults.skipped.length,
|
|
4045
|
+
failed: migrationStreamResults.failed.length
|
|
4046
|
+
};
|
|
4047
|
+
const updateStreamResults = updateStream.getResults();
|
|
4048
|
+
const updateResults = {
|
|
4049
|
+
total: updateStreamResults.totalProcessed,
|
|
4050
|
+
succeeded: updateStreamResults.successful.length,
|
|
4051
|
+
failed: updateStreamResults.failed.length
|
|
4052
|
+
};
|
|
3924
4053
|
logger.info("Migration finished", {
|
|
3925
|
-
migrationResults
|
|
3926
|
-
|
|
3927
|
-
succeeded: migrationResults.successful.length,
|
|
3928
|
-
skipped: migrationResults.skipped.length,
|
|
3929
|
-
failed: migrationResults.failed.length
|
|
3930
|
-
},
|
|
3931
|
-
updateResults: {
|
|
3932
|
-
total: updateResults.totalProcessed,
|
|
3933
|
-
succeeded: updateResults.successful.length,
|
|
3934
|
-
failed: updateResults.failed.length
|
|
3935
|
-
}
|
|
4054
|
+
migrationResults,
|
|
4055
|
+
updateResults
|
|
3936
4056
|
});
|
|
4057
|
+
reporter.addSummary("migrationResults", migrationResults);
|
|
4058
|
+
reporter.addSummary("updateResults", updateResults);
|
|
4059
|
+
reporter.finalize();
|
|
3937
4060
|
} catch (error) {
|
|
3938
4061
|
handleError(error, verbose);
|
|
3939
4062
|
}
|
|
@@ -4028,8 +4151,8 @@ migrationsCommand.command("rollback [migrationFile]").description("Rollback a mi
|
|
|
4028
4151
|
}
|
|
4029
4152
|
});
|
|
4030
4153
|
|
|
4031
|
-
const program$
|
|
4032
|
-
const typesCommand = program$
|
|
4154
|
+
const program$8 = getProgram();
|
|
4155
|
+
const typesCommand = program$8.command(commands.TYPES).alias("ts").description(`Generate types d.ts for your component schemas`).option("-s, --space <space>", "space ID").option("-p, --path <path>", "path to save the file. Default is .storyblok/types");
|
|
4033
4156
|
|
|
4034
4157
|
const getAssetJSONSchema = (title) => ({
|
|
4035
4158
|
$id: "#/asset",
|
|
@@ -4869,7 +4992,7 @@ const upsertDatasourceEntry = async (space, datasourceId, entry, existingId) =>
|
|
|
4869
4992
|
}
|
|
4870
4993
|
};
|
|
4871
4994
|
const readDatasourcesFiles = async (options) => {
|
|
4872
|
-
const { from, path, separateFiles = false, suffix
|
|
4995
|
+
const { from, path, separateFiles = false, suffix } = options;
|
|
4873
4996
|
const resolvedPath = resolvePath(path, `datasources/${from}`);
|
|
4874
4997
|
try {
|
|
4875
4998
|
await readdir(resolvedPath);
|
|
@@ -4880,7 +5003,7 @@ const readDatasourcesFiles = async (options) => {
|
|
|
4880
5003
|
${chalk.cyan(`storyblok datasources pull --space ${from}`)}
|
|
4881
5004
|
|
|
4882
5005
|
2. Then try pushing again:
|
|
4883
|
-
${chalk.cyan(`storyblok datasources push --space
|
|
5006
|
+
${chalk.cyan(`storyblok datasources push --space <target_space> --from ${from}`)}`;
|
|
4884
5007
|
throw new FileSystemError(
|
|
4885
5008
|
"file_not_found",
|
|
4886
5009
|
"read",
|
|
@@ -4937,13 +5060,13 @@ async function readConsolidatedFiles(resolvedPath, suffix) {
|
|
|
4937
5060
|
};
|
|
4938
5061
|
}
|
|
4939
5062
|
|
|
4940
|
-
const program$
|
|
5063
|
+
const program$7 = getProgram();
|
|
4941
5064
|
typesCommand.command("generate").description("Generate types d.ts for your component schemas").option("--sf, --separate-files", "Generate one .d.ts file per component instead of a single combined file").option(
|
|
4942
5065
|
"--filename <name>",
|
|
4943
5066
|
"Base file name for all component types when generating a single declarations file (e.g. components.d.ts). Ignored when using --separate-files."
|
|
4944
5067
|
).option("--strict", "strict mode, no loose typing").option("--type-prefix <prefix>", "prefix to be prepended to all generated component type names").option("--type-suffix <suffix>", "suffix to be appended to all generated component type names").option("--suffix <suffix>", "Components suffix").option("--custom-fields-parser <path>", "Path to the parser file for Custom Field Types").option("--compiler-options <options>", "path to the compiler options from json-schema-to-typescript").action(async (options) => {
|
|
4945
5068
|
konsola.title(`${commands.TYPES}`, colorPalette.TYPES, "Generating types...");
|
|
4946
|
-
const verbose = program$
|
|
5069
|
+
const verbose = program$7.opts().verbose;
|
|
4947
5070
|
const { space, path } = typesCommand.opts();
|
|
4948
5071
|
const spinner = new Spinner({
|
|
4949
5072
|
verbose: !isVitest
|
|
@@ -4996,8 +5119,8 @@ typesCommand.command("generate").description("Generate types d.ts for your compo
|
|
|
4996
5119
|
}
|
|
4997
5120
|
});
|
|
4998
5121
|
|
|
4999
|
-
const program$
|
|
5000
|
-
const datasourcesCommand = program$
|
|
5122
|
+
const program$6 = getProgram();
|
|
5123
|
+
const datasourcesCommand = program$6.command(commands.DATASOURCES).alias("ds").description(`Manage your space's datasources`).option("-s, --space <space>", "space ID").option("-p, --path <path>", "path to save the file. Default is .storyblok/datasources");
|
|
5001
5124
|
|
|
5002
5125
|
async function fetchAllPages(fetchFunction, extractDataFunction, page = 1, collectedItems = []) {
|
|
5003
5126
|
const { data, response } = await fetchFunction(page);
|
|
@@ -5103,10 +5226,10 @@ const saveDatasourcesToFiles = async (space, datasources, options) => {
|
|
|
5103
5226
|
}
|
|
5104
5227
|
};
|
|
5105
5228
|
|
|
5106
|
-
const program$
|
|
5229
|
+
const program$5 = getProgram();
|
|
5107
5230
|
datasourcesCommand.command("pull [datasourceName]").option("-f, --filename <filename>", "custom name to be used in file(s) name instead of space id").option("--sf, --separate-files", "Argument to create a single file for each datasource").option("--su, --suffix <suffix>", "suffix to add to the file name (e.g. datasources.<suffix>.json)").description("Pull datasources from your space").action(async (datasourceName, options) => {
|
|
5108
5231
|
konsola.title(`${commands.DATASOURCES}`, colorPalette.DATASOURCES, datasourceName ? `Pulling datasource ${datasourceName}...` : "Pulling datasources...");
|
|
5109
|
-
const verbose = program$
|
|
5232
|
+
const verbose = program$5.opts().verbose;
|
|
5110
5233
|
const { space, path } = datasourcesCommand.opts();
|
|
5111
5234
|
const { separateFiles, suffix, filename = "datasources" } = options;
|
|
5112
5235
|
const { state, initializeSession } = session();
|
|
@@ -5175,12 +5298,13 @@ datasourcesCommand.command("pull [datasourceName]").option("-f, --filename <file
|
|
|
5175
5298
|
}
|
|
5176
5299
|
});
|
|
5177
5300
|
|
|
5178
|
-
const program$
|
|
5301
|
+
const program$4 = getProgram();
|
|
5179
5302
|
datasourcesCommand.command("push [datasourceName]").description(`Push your space's datasources schema as json`).option("-f, --from <from>", "source space id").option("--fi, --filter <filter>", "glob filter to apply to the datasources before pushing").option("--sf, --separate-files", "Read from separate files instead of consolidated files").option("--su, --suffix <suffix>", "Suffix to add to the datasource name").action(async (datasourceName, options) => {
|
|
5180
5303
|
konsola.title(`${commands.DATASOURCES}`, colorPalette.DATASOURCES, datasourceName ? `Pushing datasource ${datasourceName}...` : "Pushing datasources...");
|
|
5181
|
-
const verbose = program$
|
|
5304
|
+
const verbose = program$4.opts().verbose;
|
|
5182
5305
|
const { space, path } = datasourcesCommand.opts();
|
|
5183
|
-
const {
|
|
5306
|
+
const { filter } = options;
|
|
5307
|
+
const fromSpace = options.from || space;
|
|
5184
5308
|
const { state, initializeSession } = session();
|
|
5185
5309
|
await initializeSession();
|
|
5186
5310
|
if (!requireAuthentication(state, verbose)) {
|
|
@@ -5190,10 +5314,7 @@ datasourcesCommand.command("push [datasourceName]").description(`Push your space
|
|
|
5190
5314
|
handleError(new CommandError(`Please provide the target space as argument --space TARGET_SPACE_ID.`), verbose);
|
|
5191
5315
|
return;
|
|
5192
5316
|
}
|
|
5193
|
-
|
|
5194
|
-
options.from = space;
|
|
5195
|
-
}
|
|
5196
|
-
konsola.info(`Attempting to push datasources ${chalk.bold("from")} space ${chalk.hex(colorPalette.DATASOURCES)(options.from || space)} ${chalk.bold("to")} ${chalk.hex(colorPalette.DATASOURCES)(space)}`);
|
|
5317
|
+
konsola.info(`Attempting to push datasources ${chalk.bold("from")} space ${chalk.hex(colorPalette.DATASOURCES)(fromSpace)} ${chalk.bold("to")} ${chalk.hex(colorPalette.DATASOURCES)(space)}`);
|
|
5197
5318
|
konsola.br();
|
|
5198
5319
|
const { password, region } = state;
|
|
5199
5320
|
mapiClient({
|
|
@@ -5207,7 +5328,7 @@ datasourcesCommand.command("push [datasourceName]").description(`Push your space
|
|
|
5207
5328
|
local: await readDatasourcesFiles({
|
|
5208
5329
|
...options,
|
|
5209
5330
|
path,
|
|
5210
|
-
|
|
5331
|
+
from: fromSpace
|
|
5211
5332
|
}),
|
|
5212
5333
|
target: {
|
|
5213
5334
|
datasources: /* @__PURE__ */ new Map()
|
|
@@ -5495,11 +5616,33 @@ const fetchBlueprintRepositories = async () => {
|
|
|
5495
5616
|
}
|
|
5496
5617
|
};
|
|
5497
5618
|
|
|
5498
|
-
|
|
5499
|
-
|
|
5619
|
+
function showNextSteps(technologyTemplate, finalProjectPath) {
|
|
5620
|
+
konsola.br();
|
|
5621
|
+
konsola.ok(`Your ${chalk.hex(colorPalette.PRIMARY)(technologyTemplate)} project is ready \u{1F389} !`);
|
|
5622
|
+
konsola.br();
|
|
5623
|
+
konsola.info(`Next steps:
|
|
5624
|
+
cd ${finalProjectPath}
|
|
5625
|
+
npm install
|
|
5626
|
+
npm run dev
|
|
5627
|
+
`);
|
|
5628
|
+
konsola.info(`Or check the dedicated guide at: ${chalk.hex(colorPalette.PRIMARY)(`https://www.storyblok.com/docs/guides/${technologyTemplate}`)}`);
|
|
5629
|
+
}
|
|
5630
|
+
async function handleEnvFileCreation(resolvedPath, token) {
|
|
5631
|
+
try {
|
|
5632
|
+
await createEnvFile(resolvedPath, token);
|
|
5633
|
+
konsola.ok(`Created .env file with Storyblok access token`, true);
|
|
5634
|
+
return true;
|
|
5635
|
+
} catch (error) {
|
|
5636
|
+
konsola.warn(`Failed to create .env file: ${error.message}`);
|
|
5637
|
+
konsola.info(`You can manually add this token to your .env file: ${token}`);
|
|
5638
|
+
return false;
|
|
5639
|
+
}
|
|
5640
|
+
}
|
|
5641
|
+
const program$3 = getProgram();
|
|
5642
|
+
program$3.command(`${commands.CREATE} [project-path]`).alias("c").description(`Scaffold a new project using Storyblok`).option("-t, --template <template>", "technology starter template").option("-b, --blueprint <blueprint>", "[DEPRECATED] use --template instead").option("--skip-space", "skip space creation").option("--token <token>", "Storyblok access token (skip space creation and use this token)").action(async (projectPath, options) => {
|
|
5500
5643
|
konsola.title(`${commands.CREATE}`, colorPalette.CREATE);
|
|
5501
|
-
const verbose = program$
|
|
5502
|
-
const { template, blueprint } = options;
|
|
5644
|
+
const verbose = program$3.opts().verbose;
|
|
5645
|
+
const { template, blueprint, token } = options;
|
|
5503
5646
|
let selectedTemplate = template;
|
|
5504
5647
|
if (blueprint && !template) {
|
|
5505
5648
|
konsola.warn(`The --blueprint flag is deprecated. Please use --template instead.`);
|
|
@@ -5525,18 +5668,6 @@ program$2.command(`${commands.CREATE} [project-path]`).alias("c").description(`S
|
|
|
5525
5668
|
const spinnerSpace = new Spinner({
|
|
5526
5669
|
verbose: !isVitest
|
|
5527
5670
|
});
|
|
5528
|
-
let userData;
|
|
5529
|
-
try {
|
|
5530
|
-
const user = await getUser(password, region);
|
|
5531
|
-
if (!user) {
|
|
5532
|
-
throw new Error("User data is undefined");
|
|
5533
|
-
}
|
|
5534
|
-
userData = user;
|
|
5535
|
-
} catch (error) {
|
|
5536
|
-
konsola.error("Failed to fetch user info. Please login again.", error);
|
|
5537
|
-
konsola.br();
|
|
5538
|
-
return;
|
|
5539
|
-
}
|
|
5540
5671
|
try {
|
|
5541
5672
|
spinnerBlueprints.start("Fetching starter templates...");
|
|
5542
5673
|
const templates = await fetchBlueprintRepositories();
|
|
@@ -5592,91 +5723,96 @@ program$2.command(`${commands.CREATE} [project-path]`).alias("c").description(`S
|
|
|
5592
5723
|
await generateProject(technologyTemplate, projectName, targetDirectory);
|
|
5593
5724
|
konsola.ok(`Project ${chalk.hex(colorPalette.PRIMARY)(projectName)} created successfully in ${chalk.hex(colorPalette.PRIMARY)(finalProjectPath)}`, true);
|
|
5594
5725
|
let createdSpace;
|
|
5595
|
-
|
|
5596
|
-
{ name: "My personal account", value: "personal" }
|
|
5597
|
-
];
|
|
5598
|
-
if (userData.has_org) {
|
|
5599
|
-
choices.push({ name: `Organization (${userData?.org?.name})`, value: "org" });
|
|
5600
|
-
}
|
|
5601
|
-
if (userData.has_partner) {
|
|
5602
|
-
choices.push({ name: "Partner Portal", value: "partner" });
|
|
5603
|
-
}
|
|
5726
|
+
let userData;
|
|
5604
5727
|
let whereToCreateSpace = "personal";
|
|
5605
|
-
if (
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
});
|
|
5610
|
-
}
|
|
5611
|
-
if (region !== "eu" && userData.has_org) {
|
|
5612
|
-
whereToCreateSpace = "org";
|
|
5728
|
+
if (token) {
|
|
5729
|
+
await handleEnvFileCreation(resolvedPath, token);
|
|
5730
|
+
showNextSteps(technologyTemplate, finalProjectPath);
|
|
5731
|
+
return;
|
|
5613
5732
|
}
|
|
5614
|
-
if (
|
|
5615
|
-
|
|
5616
|
-
konsola.br();
|
|
5733
|
+
if (options.skipSpace) {
|
|
5734
|
+
showNextSteps(technologyTemplate, finalProjectPath);
|
|
5617
5735
|
return;
|
|
5618
5736
|
}
|
|
5619
|
-
|
|
5737
|
+
try {
|
|
5620
5738
|
try {
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
const spaceToCreate = {
|
|
5625
|
-
name: toHumanReadable(projectName),
|
|
5626
|
-
domain: blueprintDomain
|
|
5627
|
-
};
|
|
5628
|
-
if (whereToCreateSpace === "org") {
|
|
5629
|
-
spaceToCreate.org = userData.org;
|
|
5630
|
-
spaceToCreate.in_org = true;
|
|
5631
|
-
} else if (whereToCreateSpace === "partner") {
|
|
5632
|
-
spaceToCreate.assign_partner = true;
|
|
5739
|
+
const user = await getUser(password, region);
|
|
5740
|
+
if (!user) {
|
|
5741
|
+
throw new Error("User data is undefined");
|
|
5633
5742
|
}
|
|
5634
|
-
|
|
5635
|
-
spinnerSpace.succeed(`Space "${chalk.hex(colorPalette.PRIMARY)(toHumanReadable(projectName))}" created successfully`);
|
|
5743
|
+
userData = user;
|
|
5636
5744
|
} catch (error) {
|
|
5637
|
-
|
|
5745
|
+
konsola.error("Failed to fetch user info. Please login again.", error);
|
|
5638
5746
|
konsola.br();
|
|
5639
|
-
handleError(error, verbose);
|
|
5640
5747
|
return;
|
|
5641
5748
|
}
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
} catch (error) {
|
|
5648
|
-
konsola.warn(`Failed to create .env file: ${error.message}`);
|
|
5649
|
-
konsola.info(`You can manually add this token to your .env file: ${createdSpace.first_token}`);
|
|
5749
|
+
const choices = [
|
|
5750
|
+
{ name: "My personal account", value: "personal" }
|
|
5751
|
+
];
|
|
5752
|
+
if (userData.has_org) {
|
|
5753
|
+
choices.push({ name: `Organization (${userData?.org?.name})`, value: "org" });
|
|
5650
5754
|
}
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
try {
|
|
5654
|
-
await openSpaceInBrowser(createdSpace.id, region);
|
|
5655
|
-
konsola.info(`Opened space in your browser`);
|
|
5656
|
-
} catch (error) {
|
|
5657
|
-
konsola.warn(`Failed to open browser: ${error.message}`);
|
|
5658
|
-
const spaceUrl = generateSpaceUrl(createdSpace.id, region);
|
|
5659
|
-
konsola.info(`You can manually open your space at: ${chalk.hex(colorPalette.PRIMARY)(spaceUrl)}`);
|
|
5755
|
+
if (userData.has_partner) {
|
|
5756
|
+
choices.push({ name: "Partner Portal", value: "partner" });
|
|
5660
5757
|
}
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5758
|
+
if (region === regions.EU && (userData.has_partner || userData.has_org)) {
|
|
5759
|
+
whereToCreateSpace = await select({
|
|
5760
|
+
message: `Where would you like to create this space?`,
|
|
5761
|
+
choices
|
|
5762
|
+
});
|
|
5763
|
+
}
|
|
5764
|
+
if (region !== regions.EU && userData.has_org) {
|
|
5765
|
+
whereToCreateSpace = "org";
|
|
5766
|
+
}
|
|
5767
|
+
if (region !== regions.EU && !userData.has_org) {
|
|
5768
|
+
konsola.warn(`Space creation in this region is limited to Enterprise accounts. If you're part of an organization, please ensure you have the required permissions. For more information about Enterprise access, contact our Sales Team.`);
|
|
5769
|
+
konsola.br();
|
|
5770
|
+
return;
|
|
5771
|
+
}
|
|
5772
|
+
spinnerSpace.start(`Creating space "${toHumanReadable(projectName)}"`);
|
|
5773
|
+
const selectedBlueprint = templates.find((bp) => bp.value === technologyTemplate);
|
|
5774
|
+
const blueprintDomain = selectedBlueprint?.location || "https://localhost:3000/";
|
|
5775
|
+
const spaceToCreate = {
|
|
5776
|
+
name: toHumanReadable(projectName),
|
|
5777
|
+
domain: blueprintDomain
|
|
5778
|
+
};
|
|
5665
5779
|
if (whereToCreateSpace === "org") {
|
|
5666
|
-
|
|
5780
|
+
spaceToCreate.org = userData.org;
|
|
5781
|
+
spaceToCreate.in_org = true;
|
|
5667
5782
|
} else if (whereToCreateSpace === "partner") {
|
|
5668
|
-
|
|
5669
|
-
}
|
|
5670
|
-
|
|
5783
|
+
spaceToCreate.assign_partner = true;
|
|
5784
|
+
}
|
|
5785
|
+
createdSpace = await createSpace(spaceToCreate);
|
|
5786
|
+
spinnerSpace.succeed(`Space "${chalk.hex(colorPalette.PRIMARY)(toHumanReadable(projectName))}" created successfully`);
|
|
5787
|
+
if (createdSpace?.first_token) {
|
|
5788
|
+
await handleEnvFileCreation(resolvedPath, createdSpace.first_token);
|
|
5789
|
+
}
|
|
5790
|
+
if (createdSpace?.id) {
|
|
5791
|
+
try {
|
|
5792
|
+
await openSpaceInBrowser(createdSpace.id, region);
|
|
5793
|
+
konsola.info(`Opened space in your browser`);
|
|
5794
|
+
} catch (error) {
|
|
5795
|
+
konsola.warn(`Failed to open browser: ${error.message}`);
|
|
5796
|
+
const spaceUrl = generateSpaceUrl(createdSpace.id, region);
|
|
5797
|
+
konsola.info(`You can manually open your space at: ${chalk.hex(colorPalette.PRIMARY)(spaceUrl)}`);
|
|
5798
|
+
}
|
|
5799
|
+
}
|
|
5800
|
+
showNextSteps(technologyTemplate, finalProjectPath);
|
|
5801
|
+
if (createdSpace?.first_token) {
|
|
5802
|
+
if (whereToCreateSpace === "org") {
|
|
5803
|
+
konsola.ok(`Storyblok space created in organization ${chalk.hex(colorPalette.PRIMARY)(userData?.org?.name)}, preview url and .env configured automatically. You can now open your space in the browser at ${chalk.hex(colorPalette.PRIMARY)(generateSpaceUrl(createdSpace.id, region))}`);
|
|
5804
|
+
} else if (whereToCreateSpace === "partner") {
|
|
5805
|
+
konsola.ok(`Storyblok space created in partner portal, preview url and .env configured automatically. You can now open your space in the browser at ${chalk.hex(colorPalette.PRIMARY)(generateSpaceUrl(createdSpace.id, region))}`);
|
|
5806
|
+
} else {
|
|
5807
|
+
konsola.ok(`Storyblok space created, preview url and .env configured automatically. You can now open your space in the browser at ${chalk.hex(colorPalette.PRIMARY)(generateSpaceUrl(createdSpace.id, region))}`);
|
|
5808
|
+
}
|
|
5671
5809
|
}
|
|
5810
|
+
} catch (error) {
|
|
5811
|
+
spinnerSpace.failed();
|
|
5812
|
+
konsola.br();
|
|
5813
|
+
handleError(error, verbose);
|
|
5814
|
+
return;
|
|
5672
5815
|
}
|
|
5673
|
-
konsola.br();
|
|
5674
|
-
konsola.info(`Next steps:
|
|
5675
|
-
cd ${finalProjectPath}
|
|
5676
|
-
npm install
|
|
5677
|
-
npm run dev
|
|
5678
|
-
`);
|
|
5679
|
-
konsola.info(`Or check the dedicated guide at: ${chalk.hex(colorPalette.PRIMARY)(`https://www.storyblok.com/docs/guides/${technologyTemplate}`)}`);
|
|
5680
5816
|
} catch (error) {
|
|
5681
5817
|
spinnerSpace.failed();
|
|
5682
5818
|
spinnerBlueprints.failed();
|
|
@@ -5686,13 +5822,13 @@ program$2.command(`${commands.CREATE} [project-path]`).alias("c").description(`S
|
|
|
5686
5822
|
konsola.br();
|
|
5687
5823
|
});
|
|
5688
5824
|
|
|
5689
|
-
const program$
|
|
5690
|
-
const logsCommand = program$
|
|
5825
|
+
const program$2 = getProgram();
|
|
5826
|
+
const logsCommand = program$2.command(commands.LOGS).alias("lg").description(`Inspect and manage logs.`).option("-s, --space <space>", "The space ID.").option("-p, --path <path>", "Path to the directory containing the logs directory. Defaults to '.storyblok'.");
|
|
5691
5827
|
|
|
5692
5828
|
logsCommand.command("list").description("List logs").action(async () => {
|
|
5693
5829
|
const { space, path } = logsCommand.opts();
|
|
5694
5830
|
const ui = getUI();
|
|
5695
|
-
const logsPath =
|
|
5831
|
+
const logsPath = resolveCommandPath(directories.log, space, path);
|
|
5696
5832
|
const logFiles = FileTransport.listLogFiles(logsPath);
|
|
5697
5833
|
if (logFiles.length === 0) {
|
|
5698
5834
|
ui.info(`No logs found for space "${space}".`);
|
|
@@ -5705,23 +5841,40 @@ logsCommand.command("list").description("List logs").action(async () => {
|
|
|
5705
5841
|
logsCommand.command("prune").description("Prune logs").option("--keep <number>", "Max number of log files to keep (default `0`, meaning remove all)", Number.parseInt, 0).action(async ({ keep }) => {
|
|
5706
5842
|
const { space, path } = logsCommand.opts();
|
|
5707
5843
|
const ui = getUI();
|
|
5708
|
-
const logsPath =
|
|
5844
|
+
const logsPath = resolveCommandPath(directories.log, space, path);
|
|
5709
5845
|
const deletedFilesCount = FileTransport.pruneLogFiles(logsPath, keep);
|
|
5710
5846
|
ui.info(`Deleted ${deletedFilesCount} log file${deletedFilesCount === 1 ? "" : "s"}`);
|
|
5711
5847
|
});
|
|
5712
5848
|
|
|
5713
|
-
const
|
|
5714
|
-
const
|
|
5715
|
-
|
|
5849
|
+
const program$1 = getProgram();
|
|
5850
|
+
const reportsCommand = program$1.command(commands.REPORTS).alias("rp").description("Inspect and manage reports.").option("-s, --space <space>", "The space ID.").option("-p, --path <path>", "Path to the directory containing the reports directory. Defaults to '.storyblok'.");
|
|
5851
|
+
|
|
5852
|
+
reportsCommand.command("list").description("List reports").action(async () => {
|
|
5853
|
+
const { space, path } = reportsCommand.opts();
|
|
5854
|
+
const ui = getUI();
|
|
5855
|
+
const reportsPath = resolveCommandPath(directories.report, space, path);
|
|
5856
|
+
const reportFiles = Reporter.listReportFiles(reportsPath, ".jsonl");
|
|
5857
|
+
if (reportFiles.length === 0) {
|
|
5858
|
+
ui.info(`No reports found for space "${space}".`);
|
|
5859
|
+
return;
|
|
5860
|
+
}
|
|
5861
|
+
ui.info(`Found ${reportFiles.length} report file${reportFiles.length === 1 ? "" : "s"} for space "${space}":`);
|
|
5862
|
+
ui.list(reportFiles);
|
|
5863
|
+
});
|
|
5864
|
+
|
|
5865
|
+
reportsCommand.command("prune").description("Prune reports").option("--keep <number>", "Max number of report files to keep (default `0`, meaning remove all)", Number.parseInt, 0).action(async ({ keep }) => {
|
|
5866
|
+
const { space, path } = reportsCommand.opts();
|
|
5867
|
+
const ui = getUI();
|
|
5868
|
+
const reportsPath = resolveCommandPath(directories.report, space, path);
|
|
5869
|
+
const deletedFilesCount = Reporter.pruneReportFiles(reportsPath, keep, ".jsonl");
|
|
5870
|
+
ui.info(`Deleted ${deletedFilesCount} report file${deletedFilesCount === 1 ? "" : "s"}`);
|
|
5871
|
+
});
|
|
5716
5872
|
|
|
5717
5873
|
dotenv.config();
|
|
5718
5874
|
const program = getProgram();
|
|
5719
5875
|
konsola.br();
|
|
5720
5876
|
konsola.br();
|
|
5721
5877
|
konsola.title(` Storyblok CLI `, colorPalette.PRIMARY);
|
|
5722
|
-
program.option("--verbose", "Enable verbose output");
|
|
5723
|
-
program.version(pkg.version, "-v, --vers", "Output the current version");
|
|
5724
|
-
program.helpOption("-h, --help", "Display help for command");
|
|
5725
5878
|
program.on("command:*", () => {
|
|
5726
5879
|
console.error(`Invalid command: ${program.args.join(" ")}`);
|
|
5727
5880
|
konsola.br();
|