Skip to content

Commit 6096295

Browse files
committed
Introdced defered publishing of Asset, Entries and Entry variants
1 parent 522c717 commit 6096295

25 files changed

Lines changed: 3214 additions & 1238 deletions

File tree

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@ contents-*
2121
*.todo
2222
talisman_output.log
2323
snyk_output.log
24-
*.logs
24+
*.logs
25+
# Snyk Security Extension - AI Rules (auto-generated)
26+
.cursor/rules/snyk_rules.mdc

.talismanrc

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
fileignoreconfig:
2-
- filename: packages/contentstack-export-to-csv/src/types/index.ts
3-
checksum: 28c19efb0c13969d40df964f86fa6de444316e320801f19dee7392df7a36851d
2+
- filename: pnpm-lock.yaml
3+
checksum: 7a37a4f6466a7d088f884a4a1b79e88b97823b46b26ee7eef7103e06ca57a30c
44
- filename: package-lock.json
5-
checksum: faa364dac78a89d142916b71b5ceba7fdc80acbf8dc71f15dfb38d622c9dc664
5+
checksum: cb80670641a4e501ed170d114c5bb756983f07bf08d113f7c3514aab46feb116
6+
- filename: packages/contentstack-import/test/unit/import/modules/publish.test.ts
7+
checksum: 2ea7d2876efd58a90366342b89b26b1353b4230e136ee2be51b1feeb40e1a8b8
8+
- filename: packages/contentstack-import/src/import/modules/publish.ts
9+
checksum: 2437f4e0e69ef00a511ad432602f6545ed2483675d32245bc47ad7e17a962869
610
version: '1.0'

package-lock.json

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

packages/contentstack-import/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ $ npm install -g @contentstack/cli-cm-import
4747
$ csdx COMMAND
4848
running command...
4949
$ csdx (--version)
50-
@contentstack/cli-cm-import/1.31.2 darwin-arm64 node-v24.13.0
50+
@contentstack/cli-cm-import/1.32.0 darwin-arm64 node-v24.13.0
5151
$ csdx --help [COMMAND]
5252
USAGE
5353
$ csdx COMMAND

packages/contentstack-import/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
22
"name": "@contentstack/cli-cm-import",
33
"description": "Contentstack CLI plugin to import content into stack",
4-
"version": "1.31.2",
4+
"version": "1.32.0",
55
"author": "Contentstack",
66
"bugs": "https://github.com/contentstack/cli/issues",
77
"dependencies": {
88
"@contentstack/cli-audit": "~1.17.1",
99
"@contentstack/cli-command": "~1.7.1",
1010
"@contentstack/cli-utilities": "~1.17.0",
1111
"@contentstack/management": "~1.27.3",
12-
"@contentstack/cli-variants": "~1.3.7",
12+
"@contentstack/cli-variants": "~1.4.0",
1313
"@oclif/core": "^4.3.0",
1414
"big-json": "^3.2.0",
1515
"bluebird": "^3.7.2",

packages/contentstack-import/src/config/index.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const config: DefaultConfig = {
4545
'variant-entries',
4646
'labels',
4747
'webhooks',
48+
'publish',
4849
],
4950
locales: {
5051
dirName: 'locales',
@@ -206,6 +207,18 @@ const config: DefaultConfig = {
206207
apiBaseUrl: 'https://composable-studio-api.contentstack.com',
207208
apiVersion: 'v1',
208209
},
210+
publish: {
211+
dirName: 'publish',
212+
pendingAssetsFileName: 'pending-assets.json',
213+
successAssetsFileName: 'success-assets.json',
214+
failedAssetsFileName: 'failed-assets.json',
215+
pendingEntriesFileName: 'pending-entries.json',
216+
successEntriesFileName: 'success-entries.json',
217+
failedEntriesFileName: 'failed-entries.json',
218+
pendingVariantEntriesFileName: 'pending-variant-entries.json',
219+
successVariantEntriesFileName: 'success-variant-entries.json',
220+
failedVariantEntriesFileName: 'failed-variant-entries.json',
221+
},
209222
},
210223
languagesCode: [
211224
'af-za',
@@ -443,7 +456,7 @@ const config: DefaultConfig = {
443456
getEncryptionKeyMaxRetry: 3,
444457
// useBackedupDir: '',
445458
// backupConcurrency: 10,
446-
onlyTSModules: ['taxonomies', 'personalize', 'variant-entries', 'stack'],
459+
onlyTSModules: ['taxonomies', 'personalize', 'variant-entries', 'stack', 'publish'],
447460
auditConfig: {
448461
noLog: false, // Skip logs printing on terminal
449462
skipConfirm: true, // Skip confirmation if any

packages/contentstack-import/src/import/modules/assets.ts

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ import { existsSync } from 'node:fs';
99
import includes from 'lodash/includes';
1010
import { v4 as uuid } from 'uuid';
1111
import { resolve as pResolve, join } from 'node:path';
12-
import { FsUtility, log, handleAndLogError } from '@contentstack/cli-utilities';
12+
import { FsUtility, log, handleAndLogError, sanitizePath } from '@contentstack/cli-utilities';
1313

1414
import config from '../../config';
1515
import { ModuleClassParams } from '../../types';
16-
import { formatDate } from '../../utils';
16+
import { formatDate, fsUtil } from '../../utils';
1717
import BaseClass, { ApiOptions } from './base-class';
1818

1919
export default class ImportAssets extends BaseClass {
@@ -29,6 +29,7 @@ export default class ImportAssets extends BaseClass {
2929
private assetsUidMap: Record<string, unknown> = {};
3030
private assetsUrlMap: Record<string, unknown> = {};
3131
private assetsFolderMap: Record<string, unknown> = {};
32+
private pendingPublishAssets: Array<{ oldUid: string; newUid: string }> = [];
3233
private rootFolder: { uid: string; name: string; parent_uid: string; created_at: string };
3334

3435
constructor({ importConfig, stackAPIClient }: ModuleClassParams) {
@@ -54,11 +55,11 @@ export default class ImportAssets extends BaseClass {
5455
*/
5556
async start(): Promise<void> {
5657
try {
57-
// NOTE Step 1: Import folders and create uid mapping file
58+
// NOTE Step 1: Import folders and create uid mapping file
5859
log.debug('Starting folder import process...', this.importConfig.context);
5960
await this.importFolders();
6061

61-
// NOTE Step 2: Import versioned assets and create it mapping files (uid, url)
62+
// NOTE Step 2: Import versioned assets and create it mapping files (uid, url)
6263
if (this.assetConfig.includeVersionedAssets) {
6364
const versionsPath = `${this.assetsPath}/versions`;
6465
if (existsSync(versionsPath)) {
@@ -69,17 +70,15 @@ export default class ImportAssets extends BaseClass {
6970
}
7071
}
7172

72-
// NOTE Step 3: Import Assets and create it mapping files (uid, url)
73+
// NOTE Step 3: Import Assets and create it mapping files (uid, url)
7374
log.debug('Starting assets import...', this.importConfig.context);
7475
await this.importAssets();
7576

76-
// NOTE Step 4: Publish assets
77-
if (!this.importConfig.skipAssetsPublish) {
78-
log.debug('Starting assets publishing...', this.importConfig.context);
79-
await this.publish();
80-
}
77+
// NOTE Step 4: Save publish details for deferred publishing
78+
log.debug('Saving asset publish details for deferred publishing', this.importConfig.context);
79+
await this.savePublishDetails();
8180

82-
log.success('Assets imported successfully!', this.importConfig.context);
81+
log.success('Assets imported successfully', this.importConfig.context);
8382
} catch (error) {
8483
handleAndLogError(error, { ...this.importConfig.context });
8584
}
@@ -179,9 +178,18 @@ export default class ImportAssets extends BaseClass {
179178

180179
log.debug(`Found ${indexerCount} asset chunks to process`, this.importConfig.context);
181180

182-
const onSuccess = ({ response = {}, apiData: { uid, url, title } = undefined }: any) => {
181+
const onSuccess = ({ response = {}, apiData: { uid, url, title, publish_details } = undefined }: any) => {
183182
this.assetsUidMap[uid] = response.uid;
184183
this.assetsUrlMap[url] = response.url;
184+
// Track assets with valid publish_details for deferred publishing
185+
if (!isEmpty(publish_details)) {
186+
const validPublishDetails = filter(publish_details, ({ environment }: any) =>
187+
this.environments?.hasOwnProperty(environment),
188+
);
189+
if (validPublishDetails.length > 0) {
190+
this.pendingPublishAssets.push({ oldUid: uid, newUid: response.uid });
191+
}
192+
}
185193
log.debug(`Created asset: ${title} (Mapped ${uid}${response.uid})`, this.importConfig.context);
186194
log.success(`Created asset: '${title}'`, this.importConfig.context);
187195
};
@@ -387,6 +395,30 @@ export default class ImportAssets extends BaseClass {
387395
}
388396
}
389397

398+
/**
399+
* @method savePublishDetails
400+
* @description Saves pending asset UID mappings for deferred publishing
401+
* @returns {Promise<void>} Promise<void>
402+
*/
403+
async savePublishDetails(): Promise<void> {
404+
if (this.pendingPublishAssets.length === 0) {
405+
log.info('No assets with publish details to track', this.importConfig.context);
406+
return;
407+
}
408+
409+
const publishConfig = this.importConfig.modules.publish;
410+
const publishDirPath = join(sanitizePath(this.importConfig.backupDir), 'mapper', publishConfig.dirName);
411+
const pendingFilePath = join(publishDirPath, publishConfig.pendingAssetsFileName);
412+
413+
// Ensure the publish directory exists
414+
await fsUtil.makeDirectory(publishDirPath);
415+
416+
const assetCount = this.pendingPublishAssets.length;
417+
log.debug(`Writing ${assetCount} pending asset UID mappings to file`, this.importConfig.context);
418+
await fsUtil.writeFile(pendingFilePath, this.pendingPublishAssets);
419+
log.success(`Saved ${assetCount} assets for deferred publishing`, this.importConfig.context);
420+
}
421+
390422
/**
391423
* @method constructFolderImportOrder
392424
* @param {Record<string, any>[]} folders object

packages/contentstack-import/src/import/modules/base-class.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export type ApiModuleType =
4646
| 'create-entries'
4747
| 'update-entries'
4848
| 'publish-entries'
49+
| 'publish-variant-entries'
4950
| 'delete-entries'
5051
| 'create-taxonomies'
5152
| 'create-terms'
@@ -400,6 +401,8 @@ export default abstract class BaseClass {
400401
})
401402
.then(onSuccess)
402403
.catch(onReject);
404+
case 'publish-variant-entries':
405+
return Promise.resolve();
403406
case 'delete-entries':
404407
return this.stack
405408
.contentType(apiData.cTUid)

0 commit comments

Comments
 (0)