Skip to content

Commit f74b6d4

Browse files
authored
feat: passing sync options to support force sync (#250)
1 parent 1ecf947 commit f74b6d4

7 files changed

Lines changed: 83 additions & 32 deletions

File tree

docs/CONTENT-ITEM.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -514,15 +514,17 @@ If no `id` is provided, all content items in all content repositories in the spe
514514

515515
#### Options
516516

517-
| Option | Alias | Description |
518-
| -------------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
519-
| `--destinationHubId` | | The destination hub ID to sync the content item with |
520-
| `--repoId` | | The ID of a content repository to restrict sync scope. _(Optional)_ |
521-
| `--folderId` | | The ID of a folder to restrict sync scope. _(Optional)_ |
522-
| `--facet` | | Filter content using facets. Format: <br>`label:example name,locale:en-GB` <br>Regex supported with `/pattern/`. <br>See README for more examples. |
523-
| `-f`, `--force` | | Skip confirmation prompts before sync. |
524-
| `-s`, `--silent` | | Disable log file creation. |
525-
| `--logFile` | | Path to write the log file. <br>Default: `(log_filename)` |
517+
| Option | Alias | Description |
518+
| -------------------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
519+
| `--destinationHubId` | | The destination hub ID to sync the content item with |
520+
| `--repoId` | | The ID of a content repository to restrict sync scope. _(Optional)_ |
521+
| `--folderId` | | The ID of a folder to restrict sync scope. _(Optional)_ |
522+
| `--facet` | | Filter content using facets. Format: <br>`label:example name,locale:en-GB` <br>Regex supported with `/pattern/`. <br>See README for more examples. |
523+
| `-f`, `--force` | | Skip confirmation prompts before sync. |
524+
| `-s`, `--silent` | | Disable log file creation. |
525+
| `--logFile` | | Path to write the log file. <br>Default: `(log_filename)` |
526+
| `--ignoreSchemaValidation` | | Ignore schema validation when syncing content items. _(Optional)_ |
527+
| `--forceSync` | | Sync destination content item when modified (overwrite destination modifications). _(Optional)_ |
526528

527529
---
528530

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@
115115
"bottleneck": "2.19.5",
116116
"chalk": "2.4.2",
117117
"cli-progress": "3.12.0",
118-
"dc-management-sdk-js": "3.2.0",
118+
"dc-management-sdk-js": "3.3.0",
119119
"enquirer": "2.3.6",
120120
"fs-extra": "10.1.0",
121121
"graceful-fs": "4.2.11",

src/commands/content-item/sync.service.spec.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ describe('sync.service', () => {
1111
});
1212
describe('ContentItemSyncService', () => {
1313
describe('sync', () => {
14-
it('should add a content item sync job to the queue and process the queue item', async () => {
14+
it('should add a content item sync job to the queue and process the queue item (with sync options enabled)', async () => {
1515
const JOB_ID = '68e5289f0aba3024bde050f9';
1616
const DEST_HUB_ID = '67d2a201642fa239dbe1523d';
1717
const CONTENT_ITEM_ID = 'c5b659df-680e-4711-bfbe-84eaa10d76cc';
@@ -22,11 +22,15 @@ describe('sync.service', () => {
2222
hub.related.jobs.get.mockResolvedValue(new Job({ id: JOB_ID, status: 'COMPLETED' }));
2323

2424
const syncService = new ContentItemSyncService();
25-
syncService.sync(DEST_HUB_ID, hub as unknown as Hub, contentItem, () => {});
25+
syncService.sync(DEST_HUB_ID, hub as unknown as Hub, contentItem, () => {}, {
26+
ignoreSchemaValidation: true,
27+
forceSync: true
28+
});
2629
await syncService.onIdle();
2730

2831
expect(hub.related.jobs.createDeepSyncJob).toHaveBeenCalledWith({
2932
label: `dc-cli content item: sync service test`,
33+
forceSync: true,
3034
ignoreSchemaValidation: true,
3135
destinationHubId: DEST_HUB_ID,
3236
input: { rootContentItemIds: [CONTENT_ITEM_ID] }
@@ -47,11 +51,12 @@ describe('sync.service', () => {
4751
.mockResolvedValueOnce(new Job({ id: JOB_ID, status: 'COMPLETED' }));
4852

4953
const syncService = new ContentItemSyncService();
50-
syncService.sync(DEST_HUB_ID, hub as unknown as Hub, contentItem, () => {});
54+
syncService.sync(DEST_HUB_ID, hub as unknown as Hub, contentItem, () => {}, {});
5155
await syncService.onIdle();
5256

5357
expect(hub.related.jobs.createDeepSyncJob).toHaveBeenCalledWith({
5458
label: `dc-cli content item: sync service test`,
59+
forceSync: false,
5560
ignoreSchemaValidation: true,
5661
destinationHubId: DEST_HUB_ID,
5762
input: { rootContentItemIds: [CONTENT_ITEM_ID] }
@@ -70,11 +75,12 @@ describe('sync.service', () => {
7075
hub.related.jobs.get.mockResolvedValueOnce(new Job({ id: JOB_ID, status: 'FAILED' }));
7176

7277
const syncService = new ContentItemSyncService();
73-
syncService.sync(DEST_HUB_ID, hub as unknown as Hub, contentItem, () => {});
78+
syncService.sync(DEST_HUB_ID, hub as unknown as Hub, contentItem, () => {}, {});
7479
await syncService.onIdle();
7580

7681
expect(hub.related.jobs.createDeepSyncJob).toHaveBeenCalledWith({
7782
label: `dc-cli content item: sync service test`,
83+
forceSync: false,
7884
ignoreSchemaValidation: true,
7985
destinationHubId: DEST_HUB_ID,
8086
input: { rootContentItemIds: [CONTENT_ITEM_ID] }

src/commands/content-item/sync.service.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,19 @@ export class ContentItemSyncService {
1212
this.queue = new BurstableQueue({ concurrency: 1 });
1313
}
1414

15-
sync(destinationHubId: string, hub: Hub, contentItem: ContentItem, action: (job: Job) => void): void {
15+
sync(
16+
destinationHubId: string,
17+
hub: Hub,
18+
contentItem: ContentItem,
19+
action: (job: Job) => void,
20+
options: { ignoreSchemaValidation?: boolean; forceSync?: boolean }
21+
): void {
1622
this.queue.add(async () => {
1723
const createSyncJob = await hub.related.jobs.createDeepSyncJob(
1824
new CreateDeepSyncJobRequest({
1925
label: `dc-cli content item: ${contentItem.label}`,
20-
ignoreSchemaValidation: true,
26+
ignoreSchemaValidation: options.ignoreSchemaValidation ?? true,
27+
forceSync: options.forceSync || false,
2128
destinationHubId,
2229
input: { rootContentItemIds: [contentItem.id] }
2330
})

src/commands/content-item/sync.spec.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,18 @@ describe('content-item sync', () => {
102102
requiresArg: true,
103103
demandOption: true
104104
});
105+
106+
expect(spyOption).toHaveBeenCalledWith('ignoreSchemaValidation', {
107+
type: 'boolean',
108+
boolean: true,
109+
describe: 'Ignore schema validation when syncing content items.'
110+
});
111+
112+
expect(spyOption).toHaveBeenCalledWith('forceSync', {
113+
type: 'boolean',
114+
boolean: true,
115+
describe: 'Sync destination content item when modified (overwrite destination modifications).'
116+
});
105117
});
106118
});
107119

@@ -149,6 +161,8 @@ describe('content-item sync', () => {
149161
...globalArgs,
150162
id: CONTENT_ITEM_ID,
151163
destinationHubId: DEST_HUB_ID,
164+
ignoreSchemaValidation: true,
165+
forceSync: true,
152166
logFile: mockLog
153167
});
154168

@@ -158,7 +172,8 @@ describe('content-item sync', () => {
158172
DEST_HUB_ID,
159173
expect.any(Hub),
160174
expect.any(ContentItem),
161-
expect.any(Function)
175+
expect.any(Function),
176+
{ forceSync: true, ignoreSchemaValidation: true }
162177
);
163178
});
164179
it('should sync content items by query', async () => {
@@ -200,7 +215,8 @@ describe('content-item sync', () => {
200215
DEST_HUB_ID,
201216
expect.any(Hub),
202217
expect.any(ContentItem),
203-
expect.any(Function)
218+
expect.any(Function),
219+
{ forceSync: undefined, ignoreSchemaValidation: undefined }
204220
);
205221
});
206222
});

src/commands/content-item/sync.ts

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ export const builder = (yargs: Argv): void => {
6565
describe: 'The ID of a destination hub to sync with.',
6666
requiresArg: true,
6767
demandOption: true
68+
})
69+
.option('ignoreSchemaValidation', {
70+
type: 'boolean',
71+
boolean: true,
72+
describe: 'Ignore schema validation when syncing content items.'
73+
})
74+
75+
.option('forceSync', {
76+
type: 'boolean',
77+
boolean: true,
78+
describe: 'Sync destination content item when modified (overwrite destination modifications).'
6879
});
6980
};
7081

@@ -77,10 +88,13 @@ export default interface SyncOptions {
7788
force?: boolean;
7889
silent?: boolean;
7990
destinationHubId: string;
91+
ignoreSchemaValidation?: boolean;
92+
forceSync?: boolean;
8093
}
8194

8295
export const handler = async (argv: Arguments<SyncOptions & ConfigurationParameters>): Promise<void> => {
83-
const { id, logFile, force, silent, hubId, repoId, folderId, destinationHubId } = argv;
96+
const { id, logFile, force, silent, hubId, repoId, folderId, destinationHubId, ignoreSchemaValidation, forceSync } =
97+
argv;
8498
const log = logFile.open();
8599
const client = dynamicContentClientFactory(argv);
86100
const facet = withOldFilters(argv.facet, argv);
@@ -143,15 +157,21 @@ export const handler = async (argv: Arguments<SyncOptions & ConfigurationParamet
143157

144158
dedupedContentItems.forEach(contentItem => {
145159
log.addComment(`Requesting content item sync: ${contentItem.label}`);
146-
syncService.sync(destinationHubId, hub, contentItem, (syncJob: Job) => {
147-
progress.increment();
148-
const logComment =
149-
syncJob.status === 'FAILED'
150-
? `Failed content item sync job ${syncJob.id}: ${JSON.stringify(syncJob.errors)}`
151-
: `Content item synced: ${contentItem.label} (jobId: ${syncJob.id})`;
152-
153-
log.addComment(logComment);
154-
});
160+
syncService.sync(
161+
destinationHubId,
162+
hub,
163+
contentItem,
164+
(syncJob: Job) => {
165+
progress.increment();
166+
const logComment =
167+
syncJob.status === 'FAILED'
168+
? `Failed content item sync job ${syncJob.id}: ${JSON.stringify(syncJob.errors)}`
169+
: `Content item synced: ${contentItem.label} (jobId: ${syncJob.id})`;
170+
171+
log.addComment(logComment);
172+
},
173+
{ ignoreSchemaValidation, forceSync }
174+
);
155175
});
156176

157177
await syncService.onIdle();

0 commit comments

Comments
 (0)