storyblok 4.17.0 → 4.17.1
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 +171 -27
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1106,7 +1106,7 @@ const isVitest = process.env.VITEST === "true";
|
|
|
1106
1106
|
const noopProgressBar = {
|
|
1107
1107
|
increment: () => {
|
|
1108
1108
|
},
|
|
1109
|
-
setTotal: (
|
|
1109
|
+
setTotal: () => {
|
|
1110
1110
|
},
|
|
1111
1111
|
stop: () => {
|
|
1112
1112
|
}
|
|
@@ -1190,7 +1190,17 @@ class UI {
|
|
|
1190
1190
|
}
|
|
1191
1191
|
}
|
|
1192
1192
|
createProgressBar(options) {
|
|
1193
|
-
|
|
1193
|
+
const bar = this.multiBar?.create(0, 0, options);
|
|
1194
|
+
if (!bar) {
|
|
1195
|
+
return noopProgressBar;
|
|
1196
|
+
}
|
|
1197
|
+
return {
|
|
1198
|
+
increment: (count = 1) => bar.increment(count),
|
|
1199
|
+
// cli-progress renders `{eta_formatted}` as "LLs" when total is 0.
|
|
1200
|
+
// Floor at 1 so an empty phase stays a clean 0/1 instead.
|
|
1201
|
+
setTotal: (total) => bar.setTotal(Math.max(total, 1)),
|
|
1202
|
+
stop: () => bar.stop()
|
|
1203
|
+
};
|
|
1194
1204
|
}
|
|
1195
1205
|
stopAllProgressBars() {
|
|
1196
1206
|
this.multiBar?.stop();
|
|
@@ -8968,6 +8978,105 @@ pullCmd.action(async (options, command) => {
|
|
|
8968
8978
|
}
|
|
8969
8979
|
});
|
|
8970
8980
|
|
|
8981
|
+
function formatStoryIdentifier(record) {
|
|
8982
|
+
const title = record.full_slug ?? record.slug ?? record.uuid ?? record.id?.toString() ?? record.filename ?? "unknown story";
|
|
8983
|
+
const extras = [];
|
|
8984
|
+
if (record.uuid && record.uuid !== title) {
|
|
8985
|
+
extras.push(`uuid: ${record.uuid}`);
|
|
8986
|
+
}
|
|
8987
|
+
if (record.filename && record.filename !== title) {
|
|
8988
|
+
extras.push(`file: ${record.filename}`);
|
|
8989
|
+
}
|
|
8990
|
+
return extras.length > 0 ? `${title} (${extras.join(", ")})` : title;
|
|
8991
|
+
}
|
|
8992
|
+
const ENRICHABLE_FIELDS = ["full_slug", "slug", "uuid", "id", "filename"];
|
|
8993
|
+
function enrichFieldMessage(detail, record) {
|
|
8994
|
+
const match = detail.match(/^(\w+):/);
|
|
8995
|
+
if (!match) {
|
|
8996
|
+
return detail;
|
|
8997
|
+
}
|
|
8998
|
+
const field = match[1];
|
|
8999
|
+
if (!ENRICHABLE_FIELDS.includes(field)) {
|
|
9000
|
+
return detail;
|
|
9001
|
+
}
|
|
9002
|
+
const value = record[field];
|
|
9003
|
+
if (value == null || value === "" || value instanceof Error) {
|
|
9004
|
+
return detail;
|
|
9005
|
+
}
|
|
9006
|
+
return `${field} (${String(value)})${detail.slice(field.length)}`;
|
|
9007
|
+
}
|
|
9008
|
+
function renderFailureReport(ui, records, verbose) {
|
|
9009
|
+
if (records.length === 0) {
|
|
9010
|
+
return;
|
|
9011
|
+
}
|
|
9012
|
+
ui.error(`Failed stories (${records.length}):`, void 0, { header: false, margin: false });
|
|
9013
|
+
const lines = [];
|
|
9014
|
+
for (const record of records) {
|
|
9015
|
+
lines.push(formatStoryIdentifier(record));
|
|
9016
|
+
const messages = record.error instanceof APIError ? record.error.messageStack : [record.error.message];
|
|
9017
|
+
const [primary, ...rest] = messages;
|
|
9018
|
+
lines.push(` \u2022 ${enrichFieldMessage(primary ?? "Unknown error", record)}`);
|
|
9019
|
+
for (const detail of rest) {
|
|
9020
|
+
lines.push(` \u2514\u2500 ${enrichFieldMessage(detail, record)}`);
|
|
9021
|
+
}
|
|
9022
|
+
if (verbose && record.error.stack) {
|
|
9023
|
+
for (const frame of record.error.stack.split("\n")) {
|
|
9024
|
+
lines.push(` ${frame}`);
|
|
9025
|
+
}
|
|
9026
|
+
}
|
|
9027
|
+
}
|
|
9028
|
+
ui.list(lines);
|
|
9029
|
+
ui.br();
|
|
9030
|
+
if (!verbose) {
|
|
9031
|
+
ui.info("Re-run with the `--verbose` flag for full stack traces.", { margin: false });
|
|
9032
|
+
}
|
|
9033
|
+
}
|
|
9034
|
+
class FailureCollector {
|
|
9035
|
+
records = /* @__PURE__ */ new Map();
|
|
9036
|
+
keyFor(story) {
|
|
9037
|
+
return story.full_slug ?? story.uuid ?? story.filename ?? `__unknown_${this.records.size}`;
|
|
9038
|
+
}
|
|
9039
|
+
/**
|
|
9040
|
+
* Record a failure. Returns `true` if this is the first failure seen for
|
|
9041
|
+
* this story's identity, `false` if one was already recorded (in which case
|
|
9042
|
+
* the caller should skip counter updates to avoid double-billing).
|
|
9043
|
+
*/
|
|
9044
|
+
record(story, error) {
|
|
9045
|
+
const key = this.keyFor(story);
|
|
9046
|
+
if (this.records.has(key)) {
|
|
9047
|
+
return false;
|
|
9048
|
+
}
|
|
9049
|
+
this.records.set(key, {
|
|
9050
|
+
filename: story.filename,
|
|
9051
|
+
full_slug: story.full_slug,
|
|
9052
|
+
slug: story.slug,
|
|
9053
|
+
uuid: story.uuid,
|
|
9054
|
+
id: story.id,
|
|
9055
|
+
error
|
|
9056
|
+
});
|
|
9057
|
+
return true;
|
|
9058
|
+
}
|
|
9059
|
+
get isEmpty() {
|
|
9060
|
+
return this.records.size === 0;
|
|
9061
|
+
}
|
|
9062
|
+
get size() {
|
|
9063
|
+
return this.records.size;
|
|
9064
|
+
}
|
|
9065
|
+
render(ui, verbose = false) {
|
|
9066
|
+
renderFailureReport(ui, [...this.records.values()], verbose);
|
|
9067
|
+
}
|
|
9068
|
+
toReporterMeta() {
|
|
9069
|
+
return [...this.records.values()].map((r) => ({
|
|
9070
|
+
filename: r.filename,
|
|
9071
|
+
full_slug: r.full_slug,
|
|
9072
|
+
slug: r.slug,
|
|
9073
|
+
uuid: r.uuid,
|
|
9074
|
+
id: r.id,
|
|
9075
|
+
error: r.error.message
|
|
9076
|
+
}));
|
|
9077
|
+
}
|
|
9078
|
+
}
|
|
9079
|
+
|
|
8971
9080
|
const pushCmd = storiesCommand.command("push").option("-s, --space <space>", "space ID").option("-f, --from <from>", "source space id").option("-d, --dry-run", "Preview changes without applying them to Storyblok").option("--publish", "Publish stories after pushing").option("--cleanup", "delete local stories after a successful push (note: does not cleanup manifests)").description(`Push local stories to a Storyblok space.`);
|
|
8972
9081
|
pushCmd.action(async (options, command) => {
|
|
8973
9082
|
const ui = getUI();
|
|
@@ -8991,6 +9100,7 @@ pushCmd.action(async (options, command) => {
|
|
|
8991
9100
|
return;
|
|
8992
9101
|
}
|
|
8993
9102
|
const pendingWarnings = [];
|
|
9103
|
+
const failures = new FailureCollector();
|
|
8994
9104
|
const summary = {
|
|
8995
9105
|
creationResults: { total: 0, succeeded: 0, skipped: 0, failed: 0 },
|
|
8996
9106
|
processResults: { total: 0, succeeded: 0, failed: 0 },
|
|
@@ -9064,8 +9174,10 @@ pushCmd.action(async (options, command) => {
|
|
|
9064
9174
|
scanProgress.increment();
|
|
9065
9175
|
},
|
|
9066
9176
|
onError(error, filename) {
|
|
9067
|
-
|
|
9068
|
-
|
|
9177
|
+
if (failures.record({ filename }, error)) {
|
|
9178
|
+
summary.creationResults.failed += 1;
|
|
9179
|
+
}
|
|
9180
|
+
logOnlyError(error, { storyFile: filename });
|
|
9069
9181
|
}
|
|
9070
9182
|
});
|
|
9071
9183
|
const levels = groupStoriesByDepth(storyIndex);
|
|
@@ -9093,8 +9205,11 @@ pushCmd.action(async (options, command) => {
|
|
|
9093
9205
|
dryRun: options.dryRun ?? false,
|
|
9094
9206
|
appendToManifest,
|
|
9095
9207
|
onStorySuccess(entry, remoteStory) {
|
|
9096
|
-
if (!entry.uuid
|
|
9097
|
-
throw new Error("
|
|
9208
|
+
if (!entry.uuid) {
|
|
9209
|
+
throw new Error(`Local story file "${entry.filename}" is missing a "uuid" field. Re-pull the story or add the uuid manually.`);
|
|
9210
|
+
}
|
|
9211
|
+
if (!remoteStory.uuid) {
|
|
9212
|
+
throw new Error(`Storyblok API returned a story without a uuid for slug "${entry.slug}".`);
|
|
9098
9213
|
}
|
|
9099
9214
|
maps.stories.set(entry.id, remoteStory.id);
|
|
9100
9215
|
maps.stories.set(entry.uuid, remoteStory.uuid);
|
|
@@ -9103,8 +9218,11 @@ pushCmd.action(async (options, command) => {
|
|
|
9103
9218
|
creationProgress.increment();
|
|
9104
9219
|
},
|
|
9105
9220
|
onStorySkipped(entry, remoteStory, reason) {
|
|
9106
|
-
if (!entry.uuid
|
|
9107
|
-
throw new Error("
|
|
9221
|
+
if (!entry.uuid) {
|
|
9222
|
+
throw new Error(`Local story file "${entry.filename}" is missing a "uuid" field. Re-pull the story or add the uuid manually.`);
|
|
9223
|
+
}
|
|
9224
|
+
if (!remoteStory.uuid) {
|
|
9225
|
+
throw new Error(`Storyblok API returned a story without a uuid for slug "${entry.slug}".`);
|
|
9108
9226
|
}
|
|
9109
9227
|
maps.stories.set(entry.id, remoteStory.id);
|
|
9110
9228
|
maps.stories.set(entry.uuid, remoteStory.uuid);
|
|
@@ -9113,13 +9231,15 @@ pushCmd.action(async (options, command) => {
|
|
|
9113
9231
|
creationProgress.increment();
|
|
9114
9232
|
},
|
|
9115
9233
|
onStoryError(error, entry) {
|
|
9116
|
-
|
|
9117
|
-
|
|
9118
|
-
|
|
9119
|
-
|
|
9120
|
-
|
|
9234
|
+
if (failures.record(entry, error)) {
|
|
9235
|
+
summary.creationResults.failed += 1;
|
|
9236
|
+
summary.processResults.total -= 1;
|
|
9237
|
+
summary.updateResults.total -= 1;
|
|
9238
|
+
processProgress.setTotal(summary.processResults.total);
|
|
9239
|
+
updateProgress.setTotal(summary.updateResults.total);
|
|
9240
|
+
}
|
|
9121
9241
|
creationProgress.increment();
|
|
9122
|
-
|
|
9242
|
+
logOnlyError(error, { storyId: entry.uuid });
|
|
9123
9243
|
}
|
|
9124
9244
|
});
|
|
9125
9245
|
}
|
|
@@ -9142,12 +9262,15 @@ pushCmd.action(async (options, command) => {
|
|
|
9142
9262
|
updateProgress.setTotal(total);
|
|
9143
9263
|
},
|
|
9144
9264
|
onStoryError(error, filename) {
|
|
9145
|
-
|
|
9146
|
-
|
|
9265
|
+
if (failures.record({ filename }, error)) {
|
|
9266
|
+
summary.processResults.failed += 1;
|
|
9267
|
+
} else {
|
|
9268
|
+
summary.processResults.total -= 1;
|
|
9269
|
+
processProgress.setTotal(summary.processResults.total);
|
|
9270
|
+
}
|
|
9147
9271
|
summary.updateResults.total -= 1;
|
|
9148
|
-
processProgress.setTotal(summary.processResults.total);
|
|
9149
9272
|
updateProgress.setTotal(summary.updateResults.total);
|
|
9150
|
-
|
|
9273
|
+
logOnlyError(error, { storyFile: filename });
|
|
9151
9274
|
}
|
|
9152
9275
|
}),
|
|
9153
9276
|
// Map all references to numeric ids and uuids.
|
|
@@ -9163,10 +9286,15 @@ pushCmd.action(async (options, command) => {
|
|
|
9163
9286
|
summary.processResults.succeeded += 1;
|
|
9164
9287
|
},
|
|
9165
9288
|
onStoryError(error, localStory) {
|
|
9166
|
-
|
|
9289
|
+
logOnlyError(error, { storyId: localStory.uuid });
|
|
9290
|
+
if (failures.record(localStory, error)) {
|
|
9291
|
+
summary.processResults.failed += 1;
|
|
9292
|
+
} else {
|
|
9293
|
+
summary.processResults.total -= 1;
|
|
9294
|
+
processProgress.setTotal(summary.processResults.total);
|
|
9295
|
+
}
|
|
9167
9296
|
summary.updateResults.total -= 1;
|
|
9168
9297
|
updateProgress.setTotal(summary.updateResults.total);
|
|
9169
|
-
handleError(error, verbose, { storyId: localStory.uuid });
|
|
9170
9298
|
}
|
|
9171
9299
|
}),
|
|
9172
9300
|
// Update remote stories with correct references.
|
|
@@ -9186,8 +9314,13 @@ pushCmd.action(async (options, command) => {
|
|
|
9186
9314
|
summary.updateResults.succeeded += 1;
|
|
9187
9315
|
},
|
|
9188
9316
|
onStoryError(error, localStory) {
|
|
9189
|
-
|
|
9190
|
-
|
|
9317
|
+
logOnlyError(error, { storyId: localStory.uuid });
|
|
9318
|
+
if (failures.record(localStory, error)) {
|
|
9319
|
+
summary.updateResults.failed += 1;
|
|
9320
|
+
} else {
|
|
9321
|
+
summary.updateResults.total -= 1;
|
|
9322
|
+
updateProgress.setTotal(summary.updateResults.total);
|
|
9323
|
+
}
|
|
9191
9324
|
}
|
|
9192
9325
|
})
|
|
9193
9326
|
);
|
|
@@ -9196,19 +9329,30 @@ pushCmd.action(async (options, command) => {
|
|
|
9196
9329
|
} finally {
|
|
9197
9330
|
logger.info("Pushing stories finished", summary);
|
|
9198
9331
|
ui.stopAllProgressBars();
|
|
9199
|
-
|
|
9200
|
-
|
|
9201
|
-
}
|
|
9202
|
-
const failedStories = Math.max(summary.creationResults.failed, summary.processResults.failed, summary.updateResults.failed);
|
|
9203
|
-
ui.info(`Push results: ${summary.creationResults.total} ${summary.creationResults.total === 1 ? "story" : "stories"} pushed, ${failedStories} ${failedStories === 1 ? "story" : "stories"} failed`);
|
|
9332
|
+
ui.br();
|
|
9333
|
+
const failedCount = failures.size;
|
|
9334
|
+
ui.info(`Push results: ${summary.creationResults.total} ${summary.creationResults.total === 1 ? "story" : "stories"} pushed, ${failedCount} ${failedCount === 1 ? "story" : "stories"} failed`);
|
|
9204
9335
|
ui.list([
|
|
9205
9336
|
`Creating stories: ${summary.creationResults.succeeded + summary.creationResults.skipped}/${summary.creationResults.total} succeeded, ${summary.creationResults.failed} failed.`,
|
|
9206
9337
|
`Processing stories: ${summary.processResults.succeeded}/${summary.processResults.total} succeeded, ${summary.processResults.failed} failed.`,
|
|
9207
9338
|
`Updating stories: ${summary.updateResults.succeeded}/${summary.updateResults.total} succeeded, ${summary.updateResults.failed} failed.`
|
|
9208
9339
|
]);
|
|
9340
|
+
if (pendingWarnings.length > 0 || !failures.isEmpty) {
|
|
9341
|
+
ui.br();
|
|
9342
|
+
}
|
|
9343
|
+
for (const warning of pendingWarnings) {
|
|
9344
|
+
ui.warn(warning);
|
|
9345
|
+
}
|
|
9346
|
+
if (pendingWarnings.length > 0 && !failures.isEmpty) {
|
|
9347
|
+
ui.br();
|
|
9348
|
+
}
|
|
9349
|
+
failures.render(ui, verbose);
|
|
9209
9350
|
reporter.addSummary("creationResults", summary.creationResults);
|
|
9210
9351
|
reporter.addSummary("processResults", summary.processResults);
|
|
9211
9352
|
reporter.addSummary("updateResults", summary.updateResults);
|
|
9353
|
+
if (!failures.isEmpty) {
|
|
9354
|
+
reporter.addMeta("failedStories", failures.toReporterMeta());
|
|
9355
|
+
}
|
|
9212
9356
|
reporter.finalize();
|
|
9213
9357
|
}
|
|
9214
9358
|
});
|