contensis-cli 1.5.1-beta.1 → 1.5.1-beta.11

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.
@@ -28,17 +28,17 @@ import {
28
28
  import ContensisAuthService from './ContensisAuthService';
29
29
 
30
30
  import { LogMessages } from '~/localisation/en-GB';
31
+ import { MixedFileData } from '~/mappers/MixedFileData';
31
32
  import {
32
33
  CliUrls,
33
34
  OutputFormat,
34
35
  OutputOptionsConstructorArg,
35
36
  } from '~/models/CliService';
36
37
 
37
- import { readFileAsJSON } from '~/providers/file-provider';
38
38
  import SessionCacheProvider from '../providers/SessionCacheProvider';
39
39
  import CredentialProvider from '~/providers/CredentialProvider';
40
40
 
41
- import { splitTagsAndGroups, url } from '~/util';
41
+ import { url } from '~/util';
42
42
  import { sanitiseIds } from '~/util/api-ids';
43
43
  import {
44
44
  isPassword,
@@ -67,16 +67,6 @@ import { promiseDelay } from '~/util/timers';
67
67
  import { GetTagsArgs } from 'migratortron/dist/services/TagsMigrationService';
68
68
  import { GetTagGroupsArgs } from 'migratortron/dist/services/TagGroupsMigrationService';
69
69
 
70
- type ImportDataType =
71
- | 'entries'
72
- | 'contentTypes'
73
- | 'components'
74
- | 'models'
75
- | 'nodes'
76
- | 'tagGroups'
77
- | 'tags'
78
- | 'user-input';
79
-
80
70
  let insecurePasswordWarningShown = false;
81
71
 
82
72
  class ContensisCli {
@@ -167,8 +157,11 @@ class ContensisCli {
167
157
  }
168
158
 
169
159
  this.format = outputOpts?.format;
170
- this.output =
171
- outputOpts?.output && path.join(process.cwd(), outputOpts.output);
160
+ this.output = outputOpts?.output
161
+ ? path.isAbsolute(outputOpts.output)
162
+ ? outputOpts.output
163
+ : path.join(process.cwd(), outputOpts.output)
164
+ : undefined;
172
165
 
173
166
  const currentEnvironment = outputOpts?.alias || this.currentEnv;
174
167
  const environments = this.cache.environments || {};
@@ -341,27 +334,21 @@ class ContensisCli {
341
334
 
342
335
  ConnectContensisImport = async ({
343
336
  commit = false,
337
+ noSource = false,
344
338
  fromFile,
345
- importDataType,
346
339
  importData,
347
- mixedData,
348
340
  }: {
349
341
  commit?: boolean;
342
+ noSource?: boolean;
350
343
  fromFile?: string;
351
- importDataType?: ImportDataType;
352
- importData?: any[];
353
- mixedData?: {
354
- [K in ImportDataType]?: any[];
355
- };
344
+ importData?: MixedFileData;
356
345
  }) => {
357
- const source: 'contensis' | 'file' =
358
- fromFile || importData || mixedData ? 'file' : 'contensis';
346
+ const source: 'contensis' | 'user-input' =
347
+ fromFile || importData || noSource ? 'user-input' : 'contensis';
359
348
 
360
- const fileData =
361
- importData || (fromFile ? (await readFileAsJSON(fromFile)) || [] : []);
362
-
363
- if (typeof fileData === 'string')
364
- throw new Error(`Import file format must be of type JSON`);
349
+ const mixedData = fromFile
350
+ ? await new MixedFileData().readFile(fromFile)
351
+ : importData;
365
352
 
366
353
  const { contensisOpts, currentEnv, env, log, messages, sourceAlias } = this;
367
354
  const environments = this.cache.environments || {};
@@ -402,7 +389,7 @@ class ContensisCli {
402
389
  const cachedTargetPassword = targetCredentials?.current?.password;
403
390
 
404
391
  if (cachedSourcePassword && cachedTargetPassword) {
405
- if (source === 'file' || importDataType === 'user-input') {
392
+ if (source === 'user-input') {
406
393
  this.contensis = new ContensisMigrationService(
407
394
  {
408
395
  concurrency: 2,
@@ -417,7 +404,6 @@ class ContensisCli {
417
404
  targetProjects: [env.currentProject || ''],
418
405
  assetHostname: this.urls?.previewWeb,
419
406
  },
420
- ...(importDataType ? { [importDataType]: fileData } : {}),
421
407
  ...(mixedData || {}),
422
408
  },
423
409
  !commit
@@ -1172,14 +1158,17 @@ class ContensisCli {
1172
1158
  }) => {
1173
1159
  const { currentEnv, currentProject, log, messages } = this;
1174
1160
 
1161
+ let importData;
1162
+ if (tags) {
1163
+ importData = new MixedFileData();
1164
+ importData.tags = tags;
1165
+ importData.tagGroups = data || [];
1166
+ }
1167
+
1175
1168
  const contensis = await this.ConnectContensisImport({
1176
1169
  commit,
1177
1170
  fromFile,
1178
- importDataType: tags ? 'user-input' : 'tagGroups',
1179
- mixedData: {
1180
- tagGroups: data,
1181
- tags: tags,
1182
- },
1171
+ importData,
1183
1172
  });
1184
1173
 
1185
1174
  if (contensis) {
@@ -1301,10 +1290,7 @@ class ContensisCli {
1301
1290
  });
1302
1291
 
1303
1292
  if (Array.isArray(result)) {
1304
- let tags: ICreateTag[] = [];
1305
- const groups: ICreateTagGroup[] = [];
1306
- if (withDependents) splitTagsAndGroups(result, tags, groups);
1307
- else tags = result;
1293
+ const { tags, tagGroups } = new MixedFileData(result);
1308
1294
 
1309
1295
  log.success(messages.tags.list(currentEnv, tags.length));
1310
1296
 
@@ -1315,11 +1301,13 @@ class ContensisCli {
1315
1301
  log.raw('');
1316
1302
  log.object(tag);
1317
1303
  }
1318
- if (groups.length) {
1304
+ if (tagGroups.length) {
1319
1305
  log.raw('');
1320
- log.success(messages.taggroups.list(currentEnv, groups.length));
1306
+ log.success(
1307
+ messages.taggroups.list(currentEnv, tagGroups.length)
1308
+ );
1321
1309
 
1322
- for (const group of groups) {
1310
+ for (const group of tagGroups) {
1323
1311
  log.raw('');
1324
1312
  log.object(group);
1325
1313
  }
@@ -1343,25 +1331,22 @@ class ContensisCli {
1343
1331
  });
1344
1332
 
1345
1333
  if (Array.isArray(result)) {
1346
- let tags: Tag[] = [];
1347
- const groups: TagGroup[] = [];
1348
- if (withDependents) splitTagsAndGroups(result, tags, groups);
1349
- else tags = result;
1334
+ const { tags, tagGroups } = new MixedFileData(result);
1350
1335
  log.success(messages.tags.list(currentEnv, tags.length));
1351
1336
 
1352
1337
  if (!tags.length) log.help(messages.tags.noneExist());
1353
1338
 
1354
1339
  await this.HandleFormattingAndOutput(result, () => {
1355
1340
  // print the tags to console
1356
- for (const { version, ...tag } of tags) {
1341
+ for (const { version, ...tag } of tags as Tag[]) {
1357
1342
  log.raw('');
1358
1343
  log.object(tag);
1359
1344
  }
1360
- if (groups.length) {
1345
+ if (tagGroups.length) {
1361
1346
  log.raw('');
1362
- log.success(messages.taggroups.list(currentEnv, groups.length));
1347
+ log.success(messages.taggroups.list(currentEnv, tagGroups.length));
1363
1348
 
1364
- for (const { version, ...group } of groups) {
1349
+ for (const { version, ...group } of tagGroups as TagGroup[]) {
1365
1350
  log.raw('');
1366
1351
  log.object(group);
1367
1352
  }
@@ -1388,30 +1373,23 @@ class ContensisCli {
1388
1373
  }) => {
1389
1374
  const { currentEnv, currentProject, log, messages } = this;
1390
1375
 
1391
- const mixedData: {
1392
- tags: ICreateTag[];
1393
- tagGroups: ICreateTagGroup[];
1394
- } = { tags: [], tagGroups: [] };
1376
+ let importData;
1395
1377
 
1396
1378
  if (data) {
1397
- mixedData.tags = data;
1398
- mixedData.tagGroups = [...new Set(data.map(t => t.groupId))].map(
1379
+ importData = new MixedFileData();
1380
+ importData.tags = data;
1381
+ importData.tagGroups = [...new Set(data.map(t => t.groupId))].map(
1399
1382
  id =>
1400
1383
  ({
1401
1384
  id,
1402
1385
  }) as ICreateTagGroup
1403
1386
  );
1404
1387
  }
1405
- if (fromFile) {
1406
- // File may contain mix of tags and tag groups, separate those here
1407
- const fileData = fromFile ? (await readFileAsJSON(fromFile)) || [] : [];
1408
- splitTagsAndGroups(fileData, mixedData.tags, mixedData.tagGroups);
1409
- }
1410
1388
 
1411
1389
  const contensis = await this.ConnectContensisImport({
1412
1390
  commit,
1413
- importDataType: 'tags',
1414
- mixedData,
1391
+ fromFile,
1392
+ importData,
1415
1393
  });
1416
1394
 
1417
1395
  if (contensis) {
@@ -1460,13 +1438,22 @@ class ContensisCli {
1460
1438
  log.help(messages.migrate.commitTip());
1461
1439
  }
1462
1440
  } else {
1463
- log.error(
1464
- messages.tags.failedCreate(
1465
- currentEnv,
1466
- data?.length === 1 ? data?.[0].label['en-GB'] : undefined
1467
- ),
1468
- err
1469
- );
1441
+ const noChanges =
1442
+ result?.tagsToMigrate?.[currentProject]?.['no change'] &&
1443
+ result?.tagsToMigrate?.[currentProject].totalCount === 0 &&
1444
+ result?.groupsToMigrate?.[currentProject].totalCount === 0;
1445
+
1446
+ if (noChanges && !err && !result.errors?.length) {
1447
+ log.help(messages.tags.noChange(currentEnv));
1448
+ } else {
1449
+ log.error(
1450
+ messages.tags.failedCreate(
1451
+ currentEnv,
1452
+ data?.length === 1 ? data?.[0].label['en-GB'] : undefined
1453
+ ),
1454
+ err
1455
+ );
1456
+ }
1470
1457
  }
1471
1458
  } else {
1472
1459
  log.warning(messages.models.noList(currentProject));
@@ -1480,7 +1467,7 @@ class ContensisCli {
1480
1467
  this.contensisOpts.concurrency = 1;
1481
1468
  const contensis = await this.ConnectContensisImport({
1482
1469
  commit,
1483
- importDataType: 'user-input', // 'user-input' import type does not require a source cms
1470
+ noSource: true,
1484
1471
  });
1485
1472
  if (contensis) {
1486
1473
  log.line();
@@ -1681,6 +1668,7 @@ class ContensisCli {
1681
1668
  const models = await contensis.models.contentModels();
1682
1669
  const contentTypes = await contensis.models.contentTypes();
1683
1670
  const components = await contensis.models.components();
1671
+ const tagGroups = await contensis.models.tagGroups();
1684
1672
 
1685
1673
  // Models to output to console
1686
1674
  const returnModels = modelIds?.length
@@ -1688,11 +1676,11 @@ class ContensisCli {
1688
1676
  modelIds.some(id => id.toLowerCase() === m.id.toLowerCase())
1689
1677
  )
1690
1678
  : undefined;
1691
- const exportResources: (ContentType | Component)[] = [];
1679
+ const exportResources: (ContentType | Component | TagGroup)[] = [];
1692
1680
 
1693
1681
  if (opts.export) {
1694
- // Generate a list of contentTypeIds and componentIds from all models
1695
- // and dependencies
1682
+ // Generate a list of contentTypeIds, componentIds and tagGroupIds from all models
1683
+ // and their dependencies
1696
1684
  const contentTypeIds = Array.from(
1697
1685
  new Set([
1698
1686
  ...(returnModels || models || []).map(m => m.id),
@@ -1708,9 +1696,16 @@ class ContensisCli {
1708
1696
  .flat()
1709
1697
  )
1710
1698
  );
1699
+ const tagGroupIds = Array.from(
1700
+ new Set(
1701
+ (returnModels || models || [])
1702
+ .map(m => m.dependencies?.tagGroups?.map(g => g[0]) || [])
1703
+ .flat()
1704
+ )
1705
+ );
1711
1706
 
1712
- // Create an array of all the content types and component definitions
1713
- // we will use this when outputting to a file
1707
+ // Create an array of all the content types, component and tag group
1708
+ // definitions, we will use this when outputting to a file
1714
1709
  exportResources.push(
1715
1710
  ...contentTypes.filter(c =>
1716
1711
  contentTypeIds
@@ -1719,6 +1714,9 @@ class ContensisCli {
1719
1714
  ),
1720
1715
  ...components.filter(c =>
1721
1716
  componentIds.map(i => i.toLowerCase()).includes(c.id.toLowerCase())
1717
+ ),
1718
+ ...tagGroups.filter(g =>
1719
+ tagGroupIds.map(i => i.toLowerCase()).includes(g.id.toLowerCase())
1722
1720
  )
1723
1721
  );
1724
1722
  }
@@ -1760,17 +1758,23 @@ class ContensisCli {
1760
1758
  for (const model of models) {
1761
1759
  const components = model.components?.length || 0;
1762
1760
  const contentTypes = model.contentTypes?.length || 0;
1761
+ const tagGroups = model.tagGroups?.length || 0;
1763
1762
  const defaults =
1764
1763
  (model.defaults?.length || 0) + (model.nodes?.length || 0);
1765
1764
  const dependencies =
1766
1765
  (model.dependencies?.components?.length || 0) +
1767
- (model.dependencies?.contentTypes?.length || 0);
1766
+ (model.dependencies?.contentTypes?.length || 0) +
1767
+ (model.dependencies?.tagGroups?.length || 0);
1768
1768
  const dependencyOf =
1769
1769
  (model.dependencyOf?.components?.length || 0) +
1770
1770
  (model.dependencyOf?.contentTypes?.length || 0);
1771
1771
 
1772
1772
  const hasAny =
1773
- components + contentTypes + dependencies + dependencyOf;
1773
+ components +
1774
+ contentTypes +
1775
+ tagGroups +
1776
+ dependencies +
1777
+ dependencyOf;
1774
1778
  log.raw(
1775
1779
  ` - ${log.highlightText(log.boldText(model.id))} ${
1776
1780
  hasAny
@@ -1781,6 +1785,8 @@ class ContensisCli {
1781
1785
  contentTypes
1782
1786
  ? `contentTypes: ${contentTypes}, `
1783
1787
  : ''
1788
+ }${
1789
+ tagGroups ? `tagGroups: ${tagGroups}, ` : ''
1784
1790
  }${defaults ? `defaults: ${defaults}, ` : ''}${
1785
1791
  dependencies ? `references: ${dependencies}, ` : ''
1786
1792
  }${
@@ -1808,16 +1814,9 @@ class ContensisCli {
1808
1814
  }) => {
1809
1815
  const { currentProject, log, messages } = this;
1810
1816
 
1811
- const fileData = fromFile
1812
- ? (await readFileAsJSON<(ContentType | Component)[]>(fromFile)) || []
1813
- : [];
1814
- if (typeof fileData === 'string')
1815
- throw new Error(`Import file format must be of type JSON`);
1816
-
1817
1817
  const contensis = await this.ConnectContensisImport({
1818
1818
  commit,
1819
1819
  fromFile,
1820
- importDataType: 'models',
1821
1820
  });
1822
1821
 
1823
1822
  if (contensis) {
@@ -1843,6 +1842,10 @@ class ContensisCli {
1843
1842
  if (!result.components) log.info(`- None returned\n`);
1844
1843
  else printModelMigrationAnalysis(this, result.components);
1845
1844
 
1845
+ if (result.tagGroups && Object.keys(result.tagGroups).length) {
1846
+ log.raw(log.boldText(`\nTag Groups:`));
1847
+ printModelMigrationAnalysis(this, result.tagGroups);
1848
+ }
1846
1849
  if (result.defaults && Object.keys(result.defaults).length) {
1847
1850
  log.raw(log.boldText(`\nDefaults:`));
1848
1851
  printModelMigrationAnalysis(this, result.defaults);
@@ -1874,6 +1877,17 @@ class ContensisCli {
1874
1877
  modelsResult[currentProject].components
1875
1878
  );
1876
1879
  }
1880
+ if (
1881
+ Object.values(modelsResult[currentProject].tagGroups || {}).some(
1882
+ r => r.length > 0
1883
+ )
1884
+ ) {
1885
+ log.raw(log.boldText(`\nTag Groups:`));
1886
+ printModelMigrationResult(
1887
+ this,
1888
+ modelsResult[currentProject].tagGroups
1889
+ );
1890
+ }
1877
1891
  if (
1878
1892
  Object.values(modelsResult[currentProject].defaults || {}).some(
1879
1893
  r => r.length > 0
@@ -1958,7 +1972,7 @@ class ContensisCli {
1958
1972
  const { currentProject, log, messages } = this;
1959
1973
  const contensis = await this.ConnectContensisImport({
1960
1974
  commit,
1961
- importDataType: 'user-input', // 'user-input' import type does not require a source cms
1975
+ noSource: true,
1962
1976
  });
1963
1977
  if (contensis) {
1964
1978
  const [err, result] = await contensis.DeleteContentTypes(contentTypeIds);
@@ -1981,6 +1995,7 @@ class ContensisCli {
1981
1995
  );
1982
1996
  // print the results to console
1983
1997
  await this.HandleFormattingAndOutput(result, log.object);
1998
+ if (!commit) log.help(messages.migrate.commitTip());
1984
1999
  }
1985
2000
  }
1986
2001
  };
@@ -1997,23 +2012,18 @@ class ContensisCli {
1997
2012
  ) => {
1998
2013
  const { currentProject, log, messages } = this;
1999
2014
 
2000
- let fileData = fromFile
2001
- ? (await readFileAsJSON<ContentType[]>(fromFile)) || []
2002
- : [];
2003
- if (typeof fileData === 'string')
2004
- throw new Error(`Import file format must be of type JSON`);
2005
-
2006
- if (!Array.isArray(fileData)) fileData = [fileData];
2015
+ let importData;
2016
+ if (fromFile) importData = await new MixedFileData().readFile(fromFile);
2007
2017
 
2008
2018
  const contensis = await this.ConnectContensisImport({
2009
2019
  commit,
2010
- importDataType: fromFile ? 'user-input' : undefined,
2020
+ noSource: !!fromFile,
2011
2021
  });
2012
2022
 
2013
2023
  if (contensis) {
2014
2024
  if (fromFile)
2015
2025
  // Pass each content type to the target repo
2016
- for (const contentType of fileData) {
2026
+ for (const contentType of importData.models) {
2017
2027
  // Fix invalid data
2018
2028
  contentType.projectId = currentProject;
2019
2029
  delete contentType.uuid;
@@ -2042,6 +2052,7 @@ class ContensisCli {
2042
2052
  );
2043
2053
  await this.HandleFormattingAndOutput(result, log.object);
2044
2054
  }
2055
+ if (!commit) log.help(messages.migrate.commitTip());
2045
2056
  }
2046
2057
  };
2047
2058
 
@@ -2055,22 +2066,16 @@ class ContensisCli {
2055
2066
  ) => {
2056
2067
  const { log } = this;
2057
2068
 
2058
- let fileData = fromFile
2059
- ? (await readFileAsJSON<ContentType[]>(fromFile)) || []
2060
- : [];
2061
- if (typeof fileData === 'string')
2062
- throw new Error(`Import file format must be of type JSON`);
2063
-
2064
- if (!Array.isArray(fileData)) fileData = [fileData];
2069
+ let importData;
2070
+ if (fromFile) importData = await new MixedFileData().readFile(fromFile);
2065
2071
 
2066
- const contensis = await this.ConnectContensisImport({
2067
- fromFile,
2068
- importDataType: 'models',
2069
- });
2072
+ const contensis = await this.ConnectContensisImport({ fromFile });
2070
2073
 
2071
2074
  if (contensis) {
2072
2075
  const [err, result] = (await to(
2073
- contensis.models.Diff(fileData.length ? fileData : modelIds)
2076
+ contensis.models.Diff(
2077
+ importData.models.length ? importData.models : modelIds
2078
+ )
2074
2079
  )) as [Error | null, ContentTypesResult | undefined];
2075
2080
 
2076
2081
  if (err) log.error(err.message, err);
@@ -2144,10 +2149,12 @@ class ContensisCli {
2144
2149
 
2145
2150
  RemoveComponents = async (componentIds: string[], commit = false) => {
2146
2151
  const { currentProject, log, messages } = this;
2152
+
2147
2153
  const contensis = await this.ConnectContensisImport({
2148
2154
  commit,
2149
- importDataType: 'user-input', // 'user-input' import type does not require a source cms
2155
+ noSource: true,
2150
2156
  });
2157
+
2151
2158
  if (contensis) {
2152
2159
  const [err, result] = await contensis.DeleteContentTypes(
2153
2160
  undefined,
@@ -2172,6 +2179,8 @@ class ContensisCli {
2172
2179
  );
2173
2180
  // print the results to console
2174
2181
  await this.HandleFormattingAndOutput(result, log.object);
2182
+
2183
+ if (!commit) log.help(messages.migrate.commitTip());
2175
2184
  }
2176
2185
  }
2177
2186
  };
@@ -2188,23 +2197,18 @@ class ContensisCli {
2188
2197
  ) => {
2189
2198
  const { currentProject, log, messages } = this;
2190
2199
 
2191
- let fileData = fromFile
2192
- ? (await readFileAsJSON<Component[]>(fromFile)) || []
2193
- : [];
2194
- if (typeof fileData === 'string')
2195
- throw new Error(`Import file format must be of type JSON`);
2196
-
2197
- if (!Array.isArray(fileData)) fileData = [fileData];
2200
+ let importData;
2201
+ if (fromFile) importData = await new MixedFileData().readFile(fromFile);
2198
2202
 
2199
2203
  const contensis = await this.ConnectContensisImport({
2200
2204
  commit,
2201
- importDataType: fromFile ? 'user-input' : undefined,
2205
+ noSource: !!fromFile,
2202
2206
  });
2203
2207
 
2204
2208
  if (contensis) {
2205
2209
  // Pass each component to the target repo
2206
2210
  if (fromFile)
2207
- for (const component of fileData) {
2211
+ for (const component of importData.models) {
2208
2212
  // Fix invalid data
2209
2213
  component.projectId = currentProject;
2210
2214
  delete component.uuid;
@@ -2233,6 +2237,7 @@ class ContensisCli {
2233
2237
  );
2234
2238
  await this.HandleFormattingAndOutput(result, log.object);
2235
2239
  }
2240
+ if (!commit) log.help(messages.migrate.commitTip());
2236
2241
  }
2237
2242
  };
2238
2243
 
@@ -2242,7 +2247,7 @@ class ContensisCli {
2242
2247
  this.contensisOpts.concurrency = 1;
2243
2248
  const contensis = await this.ConnectContensisImport({
2244
2249
  commit,
2245
- importDataType: 'user-input', // 'user-input' import type does not require a source cms
2250
+ noSource: true,
2246
2251
  });
2247
2252
 
2248
2253
  if (contensis) {
@@ -2332,11 +2337,13 @@ class ContensisCli {
2332
2337
  }) => {
2333
2338
  const { currentEnv, currentProject, log, messages } = this;
2334
2339
 
2340
+ let importData;
2341
+ if (data) importData = new MixedFileData(data);
2342
+
2335
2343
  const contensis = await this.ConnectContensisImport({
2336
2344
  commit,
2337
2345
  fromFile,
2338
- importDataType: 'entries',
2339
- importData: data,
2346
+ importData,
2340
2347
  });
2341
2348
 
2342
2349
  if (contensis) {
@@ -2351,13 +2358,16 @@ class ContensisCli {
2351
2358
 
2352
2359
  if (err) logError(err);
2353
2360
  else {
2354
- const { entries, nodes } = contensis.content.targets[currentProject];
2361
+ const { entries, nodes, tags } =
2362
+ contensis.content.targets[currentProject];
2355
2363
 
2356
2364
  const output = saveEntries
2357
- ? // include entries and dependent nodes when saving entries
2365
+ ? // include entries and dependent nodes (or tags) when saving entries
2358
2366
  [
2359
2367
  entries.migrate?.map(me => me.toJSON()) || [],
2360
2368
  nodes.migrateNodes.map(mn => mn.node),
2369
+ tags.migrateTags.map(mt => mt.toJSON()),
2370
+ tags.migrateGroups.map(mg => mg.toJSON()),
2361
2371
  ].flat()
2362
2372
  : result;
2363
2373
  await this.HandleFormattingAndOutput(output, () => {
@@ -2401,7 +2411,12 @@ class ContensisCli {
2401
2411
  ? (result.nodesResult?.created || 0) +
2402
2412
  (result.nodesResult?.updated || 0)
2403
2413
  : (result.nodesToMigrate?.[currentProject]
2404
- .totalCount as number) || 0
2414
+ .totalCount as number) || 0,
2415
+ commit
2416
+ ? (result.tagsResult?.created || 0) +
2417
+ (result.tagsResult?.updated || 0)
2418
+ : (result.tagsToMigrate?.[currentProject].totalCount as number) ||
2419
+ 0
2405
2420
  )
2406
2421
  );
2407
2422
  if (!commit) {
@@ -2409,9 +2424,25 @@ class ContensisCli {
2409
2424
  log.help(messages.migrate.commitTip());
2410
2425
  }
2411
2426
  } else {
2412
- log.error(messages.entries.failedImport(currentEnv), err);
2413
- if (!result?.entriesToMigrate?.[currentProject]?.totalCount)
2414
- log.help(messages.entries.notFound(currentEnv));
2427
+ const noChanges =
2428
+ Object.values(result?.entriesToMigrate?.[currentProject] || {}).every(
2429
+ status =>
2430
+ typeof status === 'number' || (status['no change'] || 0) > 0
2431
+ ) && result?.entriesToMigrate?.[currentProject].totalCount === 0;
2432
+
2433
+ if (
2434
+ noChanges &&
2435
+ !err &&
2436
+ !result?.migrateResult?.errors &&
2437
+ !result?.nodesResult?.errors &&
2438
+ !result?.tagsResult?.errors
2439
+ ) {
2440
+ log.help(messages.entries.noChange(currentEnv));
2441
+ } else {
2442
+ log.error(messages.entries.failedImport(currentEnv), err);
2443
+ if (!result?.entriesToMigrate?.[currentProject]?.totalCount)
2444
+ log.help(messages.entries.notFound(currentEnv));
2445
+ }
2415
2446
  }
2416
2447
  } else {
2417
2448
  log.warning(messages.models.noList(currentProject));
@@ -2435,7 +2466,6 @@ class ContensisCli {
2435
2466
  const contensis = await this.ConnectContensisImport({
2436
2467
  commit,
2437
2468
  fromFile,
2438
- importDataType: 'entries',
2439
2469
  });
2440
2470
 
2441
2471
  if (contensis) {
@@ -2516,7 +2546,6 @@ class ContensisCli {
2516
2546
  const contensis = await this.ConnectContensisImport({
2517
2547
  commit,
2518
2548
  fromFile,
2519
- importDataType: 'entries',
2520
2549
  });
2521
2550
 
2522
2551
  if (contensis) {
@@ -2623,7 +2652,6 @@ class ContensisCli {
2623
2652
  const contensis = await this.ConnectContensisImport({
2624
2653
  commit,
2625
2654
  fromFile,
2626
- importDataType: 'nodes',
2627
2655
  });
2628
2656
 
2629
2657
  if (contensis) {
@@ -2698,7 +2726,7 @@ class ContensisCli {
2698
2726
  const { currentEnv, currentProject, log, messages } = this;
2699
2727
  const contensis = await this.ConnectContensisImport({
2700
2728
  commit,
2701
- importDataType: 'user-input', // 'user-input' import type does not require a source cms
2729
+ noSource: true,
2702
2730
  });
2703
2731
 
2704
2732
  if (contensis) {
@@ -140,14 +140,14 @@ export const printEntriesMigrateResult = (
140
140
  string,
141
141
  any,
142
142
  ][]) {
143
+ const projectStatus = Object.entries(
144
+ Object.entries(entryStatus[currentProject])[0]
145
+ )[1][1] as any;
143
146
  if (
144
147
  showAll ||
145
148
  (showChanged &&
146
- (
147
- Object.entries(
148
- Object.entries(entryStatus[currentProject])[0]
149
- )[1][1] as any
150
- ).status !== 'no change')
149
+ projectStatus.status !== 'no change' &&
150
+ projectStatus.status !== 'ignore')
151
151
  ) {
152
152
  console.log(
153
153
  log.infoText(
@@ -215,7 +215,8 @@ export const printEntriesMigrateResult = (
215
215
  const existingPercent = ((existingCount / count) * 100).toFixed(0);
216
216
  const noChangeOrTotalEntriesCount =
217
217
  typeof migrateStatusAndCount !== 'number'
218
- ? migrateStatusAndCount?.['no change'] || 0
218
+ ? (migrateStatusAndCount?.['no change'] || 0) +
219
+ (migrateStatusAndCount?.['ignore'] || 0)
219
220
  : migrateStatusAndCount;
220
221
 
221
222
  const changedPercentage = (
@@ -273,8 +274,8 @@ export const printEntriesMigrateResult = (
273
274
  console.log(
274
275
  ` - ${log.errorText(`errors: ${migrateResult.errors.length}`)}\n`
275
276
  );
276
- for (const error of migrateResult.errors)
277
- log.error(error.message, null, '');
277
+ // for (const error of migrateResult.errors)
278
+ // log.error(error.message, null, '');
278
279
  }
279
280
  };
280
281
 
@@ -434,7 +435,7 @@ export const printModelMigrationAnalysis = (
434
435
  )}`;
435
436
  if (projectDetails.error)
436
437
  errorOutput += ` ${log.highlightText(
437
- `error::`
438
+ `error:`
438
439
  )} ${log.errorText(projectDetails.error)}`;
439
440
  }
440
441
  }