sb-mig 6.0.0-beta.7 → 6.0.0-beta.9
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/api/data-migration/component-data-migration.js +1 -0
- package/dist/api/data-migration/migration-run-log.d.ts +5 -1
- package/dist/api/data-migration/migration-run-log.js +13 -7
- package/dist/api/data-migration/write-summary.d.ts +2 -0
- package/dist/api/stories/stories.d.ts +21 -0
- package/dist/api/stories/stories.js +64 -4
- package/dist/api/stories/stories.types.d.ts +1 -0
- package/dist/cli/cli-descriptions.d.ts +1 -1
- package/dist/cli/cli-descriptions.js +2 -2
- package/dist-cjs/api/stories/stories.js +66 -5
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import type { MigrateFrom, MigrationPipelineResult } from "./component-data-migr
|
|
|
2
2
|
import type { MutationWriteResult, MutationWriteSummary } from "./write-summary.js";
|
|
3
3
|
import type { PublishLanguagesOption } from "../stories/stories.types.js";
|
|
4
4
|
import type { RequestBaseConfig } from "../utils/request.js";
|
|
5
|
-
type MigrationRunLogEvent = "update_success" | "update_failed" | "publish_success" | "publish_failed" | "migration_write_summary";
|
|
5
|
+
type MigrationRunLogEvent = "update_success" | "update_failed" | "publish_success" | "publish_failed" | "publish_skipped" | "migration_write_summary";
|
|
6
6
|
export interface MigrationRunLogRecord {
|
|
7
7
|
timestamp: string;
|
|
8
8
|
event: MigrationRunLogEvent;
|
|
@@ -37,6 +37,8 @@ export interface MigrationRunLogRecord {
|
|
|
37
37
|
status?: number | string;
|
|
38
38
|
response?: string | null;
|
|
39
39
|
stage?: "update" | "publish";
|
|
40
|
+
sourcePublishState?: string;
|
|
41
|
+
publishSkippedReason?: string;
|
|
40
42
|
}>;
|
|
41
43
|
};
|
|
42
44
|
item?: {
|
|
@@ -49,6 +51,8 @@ export interface MigrationRunLogRecord {
|
|
|
49
51
|
status?: number | string | null;
|
|
50
52
|
response?: string | null;
|
|
51
53
|
stage?: "update" | "publish";
|
|
54
|
+
sourcePublishState?: string;
|
|
55
|
+
publishSkippedReason?: string;
|
|
52
56
|
error?: unknown;
|
|
53
57
|
}
|
|
54
58
|
interface SaveMigrationRunLogArgs {
|
|
@@ -64,13 +64,15 @@ export const buildMigrationRunLogRecords = ({ from, to, itemType, dryRun, publis
|
|
|
64
64
|
const value = resolveWriteResultValue(result);
|
|
65
65
|
const changedItem = resolveChangedItemPayload(pipelineResult.changedItems[index]);
|
|
66
66
|
const stage = value.stage || "update";
|
|
67
|
-
const event = value.
|
|
68
|
-
?
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
: "
|
|
67
|
+
const event = value.publishSkippedReason
|
|
68
|
+
? "publish_skipped"
|
|
69
|
+
: value.ok
|
|
70
|
+
? stage === "publish"
|
|
71
|
+
? "publish_success"
|
|
72
|
+
: "update_success"
|
|
73
|
+
: stage === "publish"
|
|
74
|
+
? "publish_failed"
|
|
75
|
+
: "update_failed";
|
|
74
76
|
return {
|
|
75
77
|
...baseRecord,
|
|
76
78
|
event,
|
|
@@ -86,6 +88,8 @@ export const buildMigrationRunLogRecords = ({ from, to, itemType, dryRun, publis
|
|
|
86
88
|
status: value.status || null,
|
|
87
89
|
response: value.response || null,
|
|
88
90
|
stage,
|
|
91
|
+
sourcePublishState: value.sourcePublishState,
|
|
92
|
+
publishSkippedReason: value.publishSkippedReason,
|
|
89
93
|
...(value.ok ? {} : { error: serializeError(value.error) }),
|
|
90
94
|
};
|
|
91
95
|
});
|
|
@@ -104,6 +108,8 @@ export const buildMigrationRunLogRecords = ({ from, to, itemType, dryRun, publis
|
|
|
104
108
|
status: item.status,
|
|
105
109
|
response: item.response || null,
|
|
106
110
|
stage: item.stage,
|
|
111
|
+
sourcePublishState: item.sourcePublishState,
|
|
112
|
+
publishSkippedReason: item.publishSkippedReason,
|
|
107
113
|
})),
|
|
108
114
|
},
|
|
109
115
|
};
|
|
@@ -1,4 +1,24 @@
|
|
|
1
1
|
import type { GetAllStories, GetStoryById, RemoveStory, CreateStory, UpdateStory, UpdateStories, RemoveAllStories, UpsertStory, DeepUpsertStory, GetStoryBySlug, PublishLanguagesOption } from "./stories.types.js";
|
|
2
|
+
type StoryPublishState = {
|
|
3
|
+
status: "draft";
|
|
4
|
+
shouldPublish: false;
|
|
5
|
+
skipReason: "source_story_draft";
|
|
6
|
+
message: string;
|
|
7
|
+
} | {
|
|
8
|
+
status: "published_with_unpublished_changes";
|
|
9
|
+
shouldPublish: false;
|
|
10
|
+
skipReason: "source_story_has_unpublished_changes";
|
|
11
|
+
message: string;
|
|
12
|
+
} | {
|
|
13
|
+
status: "published_unknown";
|
|
14
|
+
shouldPublish: false;
|
|
15
|
+
skipReason: "source_story_publish_state_unknown";
|
|
16
|
+
message: string;
|
|
17
|
+
} | {
|
|
18
|
+
status: "published_clean";
|
|
19
|
+
shouldPublish: true;
|
|
20
|
+
};
|
|
21
|
+
export declare const resolveStoryPublishState: (story: any) => StoryPublishState;
|
|
2
22
|
export declare const parsePublishLanguagesOption: (publishLanguages?: string) => PublishLanguagesOption;
|
|
3
23
|
export declare const resolvePublishLanguageCodes: (publishLanguages: PublishLanguagesOption | undefined, config: {
|
|
4
24
|
spaceId: string;
|
|
@@ -22,3 +42,4 @@ export declare const publishStoryLanguages: ({ storyId, story, languages, }: {
|
|
|
22
42
|
export declare const updateStories: UpdateStories;
|
|
23
43
|
export declare const upsertStory: UpsertStory;
|
|
24
44
|
export declare const deepUpsertStory: DeepUpsertStory;
|
|
45
|
+
export {};
|
|
@@ -6,6 +6,7 @@ import { getAllItemsWithPagination } from "../utils/request.js";
|
|
|
6
6
|
const resolveStoryLabel = (content, storyId) => content?.full_slug || content?.slug || content?.name || String(storyId);
|
|
7
7
|
const DEFAULT_PUBLISH_LANGUAGE = "[default]";
|
|
8
8
|
const STORY_CONTENT_FETCH_CONCURRENCY = 10;
|
|
9
|
+
const isSkippedStoryPublishState = (publishState) => publishState?.shouldPublish === false;
|
|
9
10
|
const isDefaultLanguageToken = (language) => language.toLowerCase() === "default" ||
|
|
10
11
|
language === DEFAULT_PUBLISH_LANGUAGE;
|
|
11
12
|
const normalizePublishLanguageCodes = (languages) => {
|
|
@@ -21,6 +22,46 @@ const normalizePublishLanguageCodes = (languages) => {
|
|
|
21
22
|
}
|
|
22
23
|
return Array.from(new Set(cleanLanguages));
|
|
23
24
|
};
|
|
25
|
+
export const resolveStoryPublishState = (story) => {
|
|
26
|
+
if (story?.published !== true) {
|
|
27
|
+
return {
|
|
28
|
+
status: "draft",
|
|
29
|
+
shouldPublish: false,
|
|
30
|
+
skipReason: "source_story_draft",
|
|
31
|
+
message: "source story was draft-only",
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (story.unpublished_changes === true) {
|
|
35
|
+
return {
|
|
36
|
+
status: "published_with_unpublished_changes",
|
|
37
|
+
shouldPublish: false,
|
|
38
|
+
skipReason: "source_story_has_unpublished_changes",
|
|
39
|
+
message: "source story had unpublished draft changes",
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
if (story.unpublished_changes !== false) {
|
|
43
|
+
return {
|
|
44
|
+
status: "published_unknown",
|
|
45
|
+
shouldPublish: false,
|
|
46
|
+
skipReason: "source_story_publish_state_unknown",
|
|
47
|
+
message: "source story publish state was missing unpublished_changes",
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
status: "published_clean",
|
|
52
|
+
shouldPublish: true,
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
const withSkippedPublish = ({ updateResult, story, storyId, spaceId, publishLanguages, publishState, }) => {
|
|
56
|
+
const storyLabel = resolveStoryLabel(story, String(storyId));
|
|
57
|
+
Logger.warning(`Skipping publish for story '${storyLabel}' in space '${spaceId}' because ${publishState.message}.`);
|
|
58
|
+
return {
|
|
59
|
+
...updateResult,
|
|
60
|
+
sourcePublishState: publishState.status,
|
|
61
|
+
publishSkippedReason: publishState.skipReason,
|
|
62
|
+
...(publishLanguages ? { publishLanguages } : {}),
|
|
63
|
+
};
|
|
64
|
+
};
|
|
24
65
|
export const parsePublishLanguagesOption = (publishLanguages) => {
|
|
25
66
|
if (!publishLanguages) {
|
|
26
67
|
return "default";
|
|
@@ -193,7 +234,7 @@ export const createStory = (content, config) => {
|
|
|
193
234
|
return sbApi
|
|
194
235
|
.post(`spaces/${spaceId}/stories/`, {
|
|
195
236
|
story: content,
|
|
196
|
-
publish:
|
|
237
|
+
publish: true,
|
|
197
238
|
})
|
|
198
239
|
.then((res) => res.data)
|
|
199
240
|
.catch((err) => console.error(err));
|
|
@@ -209,8 +250,8 @@ export const updateStory = (content, storyId, options, config) => {
|
|
|
209
250
|
return sbApi
|
|
210
251
|
.put(`spaces/${spaceId}/stories/${storyId}`, {
|
|
211
252
|
story: content,
|
|
212
|
-
publish: options.publish
|
|
213
|
-
force_update: options.force_update
|
|
253
|
+
publish: options.publish === true,
|
|
254
|
+
force_update: options.force_update === true,
|
|
214
255
|
})
|
|
215
256
|
.then((res) => {
|
|
216
257
|
console.log(`${chalk.green(res.data.story.full_slug)} updated.`);
|
|
@@ -293,6 +334,7 @@ export const publishStoryLanguages = async ({ storyId, story, languages, }, conf
|
|
|
293
334
|
export const updateStories = async (args, config) => {
|
|
294
335
|
const { stories, options, spaceId } = args;
|
|
295
336
|
const shouldPublishLanguages = options.publish && options.publishLanguages !== undefined;
|
|
337
|
+
const shouldPreservePublishState = Boolean(options.preservePublishState);
|
|
296
338
|
const publishLanguages = shouldPublishLanguages
|
|
297
339
|
? await resolvePublishLanguageCodes(options.publishLanguages, {
|
|
298
340
|
...config,
|
|
@@ -303,9 +345,27 @@ export const updateStories = async (args, config) => {
|
|
|
303
345
|
// Run through stories, and update the space with migrated version of stories
|
|
304
346
|
stories.map(async (stories) => {
|
|
305
347
|
const story = stories.story;
|
|
348
|
+
const publishState = shouldPreservePublishState
|
|
349
|
+
? resolveStoryPublishState(story)
|
|
350
|
+
: undefined;
|
|
351
|
+
const shouldPublishStory = options.publish &&
|
|
352
|
+
(!publishState || publishState.shouldPublish);
|
|
306
353
|
const updateResult = await updateStory(story, story.id, {
|
|
307
|
-
publish:
|
|
354
|
+
publish: shouldPublishStory && !shouldPublishLanguages,
|
|
355
|
+
force_update: options.force_update,
|
|
308
356
|
}, { ...config, spaceId });
|
|
357
|
+
if (options.publish &&
|
|
358
|
+
updateResult?.ok &&
|
|
359
|
+
isSkippedStoryPublishState(publishState)) {
|
|
360
|
+
return withSkippedPublish({
|
|
361
|
+
updateResult,
|
|
362
|
+
story,
|
|
363
|
+
storyId: story.id,
|
|
364
|
+
spaceId,
|
|
365
|
+
publishLanguages,
|
|
366
|
+
publishState,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
309
369
|
if (!shouldPublishLanguages ||
|
|
310
370
|
!publishLanguages ||
|
|
311
371
|
!updateResult?.ok) {
|
|
@@ -7,6 +7,7 @@ interface ModifyStoryOptions {
|
|
|
7
7
|
publish?: boolean;
|
|
8
8
|
force_update?: boolean;
|
|
9
9
|
publishLanguages?: PublishLanguagesOption;
|
|
10
|
+
preservePublishState?: boolean;
|
|
10
11
|
}
|
|
11
12
|
export type PublishLanguagesOption = "default" | "all" | string[];
|
|
12
13
|
export type RemoveStory = (args: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare const mainDescription = "\n USAGE\n $ sb-mig [command]\n \n COMMANDS\n sync Synchronize components, datasources, roles, stories, assets with Storyblok space.\n discover Discover components, migration configs and write to file or stdout.\n backup Command for backing up anything related to Storyblok\n migrate Migrate content from space to space, or from file to space.\n debug Output extra debugging information\n help This screen\n \n Examples\n $ sb-mig sync components --all\n $ sb-mig debug \n";
|
|
2
2
|
export declare const syncDescription = "\n Usage\n $ sb-mig sync [components|roles|datasources|plugins|content] [space separated file names] or --all\n \n Description\n Synchronize components, roles, datasources, plugins, content with Storyblok space.\n \n COMMANDS\n components - sync components\n roles - sync roles\n datasources - sync datasources\n plugins - sync plugins\n content - sync content (stories, assets) - ! right now destructive, it will move content from 1 space to another, completelly overwriting it\n \n FLAGS\n --all - Sync all components, roles, datasources [components, roles, datasources]\n --presets - Pass it, if u want to sync also with presets (will take longer) [components only]\n --dry-run - Preview planned changes without making writes [components, roles, datasources, plugins, content]\n \n --yes - Skip ask for confirmation (dangerous, but useful in CI/CD) [content only]\n --from - Space ID from which you want to sync content [content only]\n --to - Space ID to which you want to sync content [content only]\n --syncDirection [fromSpaceToFile|fromFileToSpace|fromSpaceToSpace|fromAWStoSpace] \n - Sync direction (from, to) [content only]\n \n EXAMPLES\n $ sb-mig sync components --all\n $ sb-mig sync components --all --dry-run\n $ sb-mig sync components --all --presets\n $ sb-mig sync components accordion accordion-item\n $ sb-mig sync components accordion accordion-item --presets\n \n $ sb-mig sync roles --all\n $ sb-mig sync roles --all --dry-run\n \n $ sb-mig sync datasources --all\n $ sb-mig sync datasources --all --dry-run\n \n $ sb-mig sync plugins my-awesome-plugin - (you have to be in catalog which has ./dist/export.js file with compiled plugin)\n \n $ sb-mig sync content --all --from 12345 --to 12345\n $ sb-mig sync content --stories --from 12345 --to 12345\n $ sb-mig sync content --assets --from 12345 --to 12345\n";
|
|
3
3
|
export declare const copyDescription = "\n Usage\n $ sb-mig copy\n \n Description\n Copy stuff\n \n COMMANDS\n ?\n \n FLAGS\n ?\n \n EXAMPLES\n $ sb-mig copy ?\n";
|
|
4
|
-
export declare const migrateDescription = "\n Usage\n $ sb-mig migrate [content] [space separated file names] or --all --from [spaceId] --to [spaceId] --migration [migration-config-filename]\n $ sb-mig migrate content --all --migration migration-a --migration migration-b --migration migration-c\n \n Description\n Migrate content from space to space, or from file to space. It's potentially dangerous command, so it will ask for confirmation.\n Use with care.\n \n COMMANDS\n content - migrate content \n \n FLAGS\n --from - Space ID from which you want to migrate / or file name if passed '--migrate-from file'\n --fromFilePath - Direct path to stories JSON file when using '--migrate-from file'\n --to - Space ID to which you want to migrate\n --migrate-from - Migrate from (space, file) default: space\n --migration - File name of migration file (without extension). Can be repeated for ordered pipeline in content migration.\n --migrationComponentAlias - Add extra component aliases for a migration. Repeatable. Format: <migration>:<source>=<alias1>,<alias2>\n --migrationComponents - Override the exact component scope for a migration. Repeatable. Format: <migration>:<component1>,<component2>\n --withSlug - Filter stories by full slug (can be repeated)\n --startsWith - Filter stories by starts_with prefix\n --yes - Skip ask for confirmation (dangerous, but useful in CI/CD)\n --dry-run - Preview what would be migrated without making any API changes\n --publish - Publish changed stories
|
|
4
|
+
export declare const migrateDescription = "\n Usage\n $ sb-mig migrate [content] [space separated file names] or --all --from [spaceId] --to [spaceId] --migration [migration-config-filename]\n $ sb-mig migrate content --all --migration migration-a --migration migration-b --migration migration-c\n \n Description\n Migrate content from space to space, or from file to space. It's potentially dangerous command, so it will ask for confirmation.\n Use with care.\n \n COMMANDS\n content - migrate content \n \n FLAGS\n --from - Space ID from which you want to migrate / or file name if passed '--migrate-from file'\n --fromFilePath - Direct path to stories JSON file when using '--migrate-from file'\n --to - Space ID to which you want to migrate\n --migrate-from - Migrate from (space, file) default: space\n --migration - File name of migration file (without extension). Can be repeated for ordered pipeline in content migration.\n --migrationComponentAlias - Add extra component aliases for a migration. Repeatable. Format: <migration>:<source>=<alias1>,<alias2>\n --migrationComponents - Override the exact component scope for a migration. Repeatable. Format: <migration>:<component1>,<component2>\n --withSlug - Filter stories by full slug (can be repeated)\n --startsWith - Filter stories by starts_with prefix\n --yes - Skip ask for confirmation (dangerous, but useful in CI/CD)\n --dry-run - Preview what would be migrated without making any API changes\n --publish - Publish changed stories after migration only if they were clean-published before migration. Default: save draft. [content only]\n --publishLanguages - Languages to publish when --publish is set. Values: default, all, or comma-separated Storyblok language codes. Skips stories that were draft-only or had unpublished changes before migration. [content only]\n --fileName - Stable base name for migration output files (disables timestamp suffix for migration artifacts)\n\n EXAMPLES\n $ sb-mig migrate content --all --from 12345 --to 12345 --migration file-with-migration\n $ sb-mig migrate content --all --from 12345 --to 12345 --migration migration-a --migration migration-b --migration migration-c\n $ sb-mig migrate content --all --from 12345 --to 12345 --migration colorPickerModeValues --migrationComponentAlias colorPickerModeValues:sb-button=sb-open-drift-button\n $ sb-mig migrate content --all --from 12345 --to 12345 --migration colorPickerModeValues --migrationComponentAlias colorPickerModeValues:sb-section=sb-tour-page-section --migrationComponents colorPickerModeValues:sb-section,sb-tour-page-section\n $ sb-mig migrate content --all --from 12345 --to 12345 --migration file-with-migration --withSlug blog/home --withSlug docs/getting-started\n $ sb-mig migrate content --all --from 12345 --to 12345 --migration file-with-migration --startsWith blog/\n $ sb-mig migrate content --all --from 12345 --to 12345 --migration file-with-migration --publish --yes\n $ sb-mig migrate content --all --from 12345 --to 12345 --migration file-with-migration --publish --publishLanguages all --yes\n $ sb-mig migrate content --all --from 12345 --to 12345 --migration file-with-migration --publish --publishLanguages default,fr,de --yes\n $ sb-mig migrate content --all --from 12345 --to 12345 --migration v3toV4AllMigrations --dry-run --fileName brand-hub-v3-v4-run\n $ sb-mig migrate content --all --migrate-from file --from file-with-stories --to 12345 --migration file-with-migration\n $ sb-mig migrate content --all --migrate-from file --fromFilePath sbmig/migrations/dry-run--123---story-to-migrate__2026-2-9_20-51.json --to 12345 --migration migration-a --migration migration-b\n $ sb-mig migrate content my-component-1 my-component-2 --from 12345 --to 12345 --migration file-with-migration\n $ sb-mig migrate content my-component-1 my-component-2 --migrate-from file --from file-with-stories --to 12345 --migration file-with-migration \n";
|
|
5
5
|
export declare const revertDescription = "\n Usage\n $ sb-mig revert [content] --migration\n \n Description\n Revert content migration\n \n COMMANDS\n content - revert content migration \n \n FLAGS\n --migration - ???\n --yes - Skip ask for confirmation (dangerous, but useful in CI/CD) \n \n EXAMPLES\n $ sb-mig revert content --migration \n";
|
|
6
6
|
export declare const discoverDescription = "\n Usage\n $ sb-mig discover [components|migrations] --all --write\n\n Description\n Discover all components or migration configs and write to file or stdout\n\n COMMANDS\n components - discover components\n migrations - discover migration config files\n\n FLAGS\n --all - Discover all components or migration configs\n --write - Write to file\n\n EXAMPLES\n $ sb-mig discover components --all\n $ sb-mig discover components --all --write\n $ sb-mig discover migrations --all\n";
|
|
7
7
|
export declare const migrationsDescription = "\n Usage\n $ sb-mig migrations recognize\n \n Description\n Recognize migrations you need to apply\n \n COMMANDS\n recognize - recognize migrations\n \n FLAGS \n \n EXAMPLES\n $ sb-mig migrations recognize\n\n";
|
|
@@ -98,8 +98,8 @@ export const migrateDescription = `
|
|
|
98
98
|
--startsWith - Filter stories by starts_with prefix
|
|
99
99
|
--yes - Skip ask for confirmation (dangerous, but useful in CI/CD)
|
|
100
100
|
--dry-run - Preview what would be migrated without making any API changes
|
|
101
|
-
--publish - Publish changed stories
|
|
102
|
-
--publishLanguages - Languages to publish when --publish is set. Values: default, all, or comma-separated Storyblok language codes. [content only]
|
|
101
|
+
--publish - Publish changed stories after migration only if they were clean-published before migration. Default: save draft. [content only]
|
|
102
|
+
--publishLanguages - Languages to publish when --publish is set. Values: default, all, or comma-separated Storyblok language codes. Skips stories that were draft-only or had unpublished changes before migration. [content only]
|
|
103
103
|
--fileName - Stable base name for migration output files (disables timestamp suffix for migration artifacts)
|
|
104
104
|
|
|
105
105
|
EXAMPLES
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.deepUpsertStory = exports.upsertStory = exports.updateStories = exports.publishStoryLanguages = exports.updateStory = exports.createStory = exports.getStoryBySlug = exports.getStoryById = exports.getAllStories = exports.removeAllStories = exports.removeStory = exports.resolvePublishLanguageCodes = exports.parsePublishLanguagesOption = void 0;
|
|
6
|
+
exports.deepUpsertStory = exports.upsertStory = exports.updateStories = exports.publishStoryLanguages = exports.updateStory = exports.createStory = exports.getStoryBySlug = exports.getStoryById = exports.getAllStories = exports.removeAllStories = exports.removeStory = exports.resolvePublishLanguageCodes = exports.parsePublishLanguagesOption = exports.resolveStoryPublishState = void 0;
|
|
7
7
|
const chalk_1 = __importDefault(require("chalk"));
|
|
8
8
|
const async_utils_js_1 = require("../../utils/async-utils.js");
|
|
9
9
|
const logger_js_1 = __importDefault(require("../../utils/logger.js"));
|
|
@@ -12,6 +12,7 @@ const request_js_1 = require("../utils/request.js");
|
|
|
12
12
|
const resolveStoryLabel = (content, storyId) => content?.full_slug || content?.slug || content?.name || String(storyId);
|
|
13
13
|
const DEFAULT_PUBLISH_LANGUAGE = "[default]";
|
|
14
14
|
const STORY_CONTENT_FETCH_CONCURRENCY = 10;
|
|
15
|
+
const isSkippedStoryPublishState = (publishState) => publishState?.shouldPublish === false;
|
|
15
16
|
const isDefaultLanguageToken = (language) => language.toLowerCase() === "default" ||
|
|
16
17
|
language === DEFAULT_PUBLISH_LANGUAGE;
|
|
17
18
|
const normalizePublishLanguageCodes = (languages) => {
|
|
@@ -27,6 +28,47 @@ const normalizePublishLanguageCodes = (languages) => {
|
|
|
27
28
|
}
|
|
28
29
|
return Array.from(new Set(cleanLanguages));
|
|
29
30
|
};
|
|
31
|
+
const resolveStoryPublishState = (story) => {
|
|
32
|
+
if (story?.published !== true) {
|
|
33
|
+
return {
|
|
34
|
+
status: "draft",
|
|
35
|
+
shouldPublish: false,
|
|
36
|
+
skipReason: "source_story_draft",
|
|
37
|
+
message: "source story was draft-only",
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
if (story.unpublished_changes === true) {
|
|
41
|
+
return {
|
|
42
|
+
status: "published_with_unpublished_changes",
|
|
43
|
+
shouldPublish: false,
|
|
44
|
+
skipReason: "source_story_has_unpublished_changes",
|
|
45
|
+
message: "source story had unpublished draft changes",
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (story.unpublished_changes !== false) {
|
|
49
|
+
return {
|
|
50
|
+
status: "published_unknown",
|
|
51
|
+
shouldPublish: false,
|
|
52
|
+
skipReason: "source_story_publish_state_unknown",
|
|
53
|
+
message: "source story publish state was missing unpublished_changes",
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
status: "published_clean",
|
|
58
|
+
shouldPublish: true,
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
exports.resolveStoryPublishState = resolveStoryPublishState;
|
|
62
|
+
const withSkippedPublish = ({ updateResult, story, storyId, spaceId, publishLanguages, publishState, }) => {
|
|
63
|
+
const storyLabel = resolveStoryLabel(story, String(storyId));
|
|
64
|
+
logger_js_1.default.warning(`Skipping publish for story '${storyLabel}' in space '${spaceId}' because ${publishState.message}.`);
|
|
65
|
+
return {
|
|
66
|
+
...updateResult,
|
|
67
|
+
sourcePublishState: publishState.status,
|
|
68
|
+
publishSkippedReason: publishState.skipReason,
|
|
69
|
+
...(publishLanguages ? { publishLanguages } : {}),
|
|
70
|
+
};
|
|
71
|
+
};
|
|
30
72
|
const parsePublishLanguagesOption = (publishLanguages) => {
|
|
31
73
|
if (!publishLanguages) {
|
|
32
74
|
return "default";
|
|
@@ -206,7 +248,7 @@ const createStory = (content, config) => {
|
|
|
206
248
|
return sbApi
|
|
207
249
|
.post(`spaces/${spaceId}/stories/`, {
|
|
208
250
|
story: content,
|
|
209
|
-
publish:
|
|
251
|
+
publish: true,
|
|
210
252
|
})
|
|
211
253
|
.then((res) => res.data)
|
|
212
254
|
.catch((err) => console.error(err));
|
|
@@ -223,8 +265,8 @@ const updateStory = (content, storyId, options, config) => {
|
|
|
223
265
|
return sbApi
|
|
224
266
|
.put(`spaces/${spaceId}/stories/${storyId}`, {
|
|
225
267
|
story: content,
|
|
226
|
-
publish: options.publish
|
|
227
|
-
force_update: options.force_update
|
|
268
|
+
publish: options.publish === true,
|
|
269
|
+
force_update: options.force_update === true,
|
|
228
270
|
})
|
|
229
271
|
.then((res) => {
|
|
230
272
|
console.log(`${chalk_1.default.green(res.data.story.full_slug)} updated.`);
|
|
@@ -309,6 +351,7 @@ exports.publishStoryLanguages = publishStoryLanguages;
|
|
|
309
351
|
const updateStories = async (args, config) => {
|
|
310
352
|
const { stories, options, spaceId } = args;
|
|
311
353
|
const shouldPublishLanguages = options.publish && options.publishLanguages !== undefined;
|
|
354
|
+
const shouldPreservePublishState = Boolean(options.preservePublishState);
|
|
312
355
|
const publishLanguages = shouldPublishLanguages
|
|
313
356
|
? await (0, exports.resolvePublishLanguageCodes)(options.publishLanguages, {
|
|
314
357
|
...config,
|
|
@@ -319,9 +362,27 @@ const updateStories = async (args, config) => {
|
|
|
319
362
|
// Run through stories, and update the space with migrated version of stories
|
|
320
363
|
stories.map(async (stories) => {
|
|
321
364
|
const story = stories.story;
|
|
365
|
+
const publishState = shouldPreservePublishState
|
|
366
|
+
? (0, exports.resolveStoryPublishState)(story)
|
|
367
|
+
: undefined;
|
|
368
|
+
const shouldPublishStory = options.publish &&
|
|
369
|
+
(!publishState || publishState.shouldPublish);
|
|
322
370
|
const updateResult = await (0, exports.updateStory)(story, story.id, {
|
|
323
|
-
publish:
|
|
371
|
+
publish: shouldPublishStory && !shouldPublishLanguages,
|
|
372
|
+
force_update: options.force_update,
|
|
324
373
|
}, { ...config, spaceId });
|
|
374
|
+
if (options.publish &&
|
|
375
|
+
updateResult?.ok &&
|
|
376
|
+
isSkippedStoryPublishState(publishState)) {
|
|
377
|
+
return withSkippedPublish({
|
|
378
|
+
updateResult,
|
|
379
|
+
story,
|
|
380
|
+
storyId: story.id,
|
|
381
|
+
spaceId,
|
|
382
|
+
publishLanguages,
|
|
383
|
+
publishState,
|
|
384
|
+
});
|
|
385
|
+
}
|
|
325
386
|
if (!shouldPublishLanguages ||
|
|
326
387
|
!publishLanguages ||
|
|
327
388
|
!updateResult?.ok) {
|
package/package.json
CHANGED