apn-app-manager 1.4.1 → 1.5.0

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/README.md CHANGED
@@ -12,7 +12,7 @@ The functionality provided by this tool is not supported, nor endorsed by Appian
12
12
 
13
13
  Importing an application export modified by this tool should be done at your own discretion.
14
14
 
15
- Latest compatible Appian platform version tested against: **22.3**.
15
+ Latest compatible Appian platform version tested against: **23.3**.
16
16
 
17
17
  ## Installation
18
18
 
@@ -43,6 +43,7 @@ Used to duplicate all objects of an application, which replaces the namespace of
43
43
  1. Enter your current namespace.
44
44
  - For example, an application with objects such as `SMP APP Artifacts` and `SMP_APP_displayUser` would have a namespace of `SMP_APP`
45
45
  1. Enter your new namespace.
46
+ 1. Do advanced options if necessary.
46
47
  1. Access your cloned application in the generated `/out/` folder.
47
48
 
48
49
  #### Notes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apn-app-manager",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "Appian App Manager",
5
5
  "license": "Apache-2.0",
6
6
  "preferGlobal": true,
@@ -14,6 +14,11 @@ const obExtract = require("../handlers/objectExtractHandler");
14
14
  const obMapsUpdates = require("../handlers/objectMapsUpdateHandler");
15
15
  const obModify = require("../handlers/objectModifyHandler");
16
16
 
17
+ // Options
18
+ const options = {
19
+ renameDbTables: true,
20
+ };
21
+
17
22
  // Entry-point
18
23
  function main(callback) {
19
24
  util.delFile(cons.outDir);
@@ -24,7 +29,16 @@ function main(callback) {
24
29
  promptNamespace("What is your new namespace?", function (newNamespace) {
25
30
  const namespaceMap = {};
26
31
  namespaceMap[curNamespace] = { newNamespace: newNamespace };
27
- executeClone(appZipPath, icfPath, namespaceMap, callback);
32
+ prompt.promptList("Advanced options?", ["No", "Yes"], function (enhancedOptions) {
33
+ if (enhancedOptions == "Yes") {
34
+ prompt.promptList("Rename database tables?", ["Yes", "No"], function (renameDbTables) {
35
+ options["renameDbTables"] = renameDbTables == "Yes";
36
+ executeClone(appZipPath, icfPath, namespaceMap, options, callback);
37
+ });
38
+ } else {
39
+ executeClone(appZipPath, icfPath, namespaceMap, options, callback);
40
+ }
41
+ });
28
42
  });
29
43
  });
30
44
  });
@@ -32,7 +46,7 @@ function main(callback) {
32
46
  }
33
47
 
34
48
  // Executes all the steps of the clone
35
- function executeClone(appZipPath, icfPath, namespaceMap, callback) {
49
+ function executeClone(appZipPath, icfPath, namespaceMap, options, callback) {
36
50
  // Initialize output variables
37
51
  const outZipPath = path.resolve(cons.outDir, path.basename(appZipPath));
38
52
  const outIcfPath = icfPath ? path.resolve(cons.outDir, path.basename(icfPath)) : null;
@@ -53,7 +67,7 @@ function executeClone(appZipPath, icfPath, namespaceMap, callback) {
53
67
 
54
68
  // Update the object maps we are cloning based on the application prefix
55
69
  util.print(`Cloning the objects files...`);
56
- obMapsUpdates.renameObjectMaps(objectMaps, uuidCollector, namespaceMap, obProps.usageTypes.CLONE);
70
+ obMapsUpdates.renameObjectMaps(objectMaps, uuidCollector, namespaceMap, options, obProps.usageTypes.CLONE);
57
71
 
58
72
  // These output files are helpful for debugging
59
73
  util.writeJson(path.resolve(cons.outDir, `objects.json`), objectMaps);
@@ -64,7 +64,22 @@ function extractObProps(objectMaps, uuidCollector, fileCount, obPath, usageType)
64
64
  const xpath = util.replaceKeys(haulField.xpath, { "{OBTYPE}": obType });
65
65
  let result = util.xpath(xpath, fileContent, haulField.isArray, obProps.xmlNamespaces);
66
66
  if (!util.isBlank(haulField.extractRegex) && !util.isBlank(result)) {
67
- result = util.firstMatch(result, haulField.extractRegex, "");
67
+ if (!haulField.isArray) {
68
+ result = util.firstMatch(result, haulField.extractRegex, "");
69
+ } else {
70
+ if (!Array.isArray(result)) {
71
+ result = util.regexMatches(result, haulField.extractRegex);
72
+ } else {
73
+ console.log("i did this");
74
+ result = result
75
+ .map(function (thisResult) {
76
+ return util.firstMatch(thisResult, haulField.extractRegex, "");
77
+ })
78
+ .filter(function (thisResult) {
79
+ return thisResult != "";
80
+ });
81
+ }
82
+ }
68
83
  }
69
84
  builder[haulField.fieldName] = result;
70
85
  }
@@ -11,9 +11,9 @@ const { remove } = require("fs-extra");
11
11
  // Exports
12
12
  module.exports = {
13
13
  // Goes through all of the objectMaps and creates new name, uuid, etc.
14
- renameObjectMaps: function (objectMaps, uuidCollector, namespaceMap, usageType) {
14
+ renameObjectMaps: function (objectMaps, uuidCollector, namespaceMap, options, usageType) {
15
15
  // Update all objectMaps with new names
16
- renameObjectMaps(objectMaps, uuidCollector, namespaceMap, usageType);
16
+ renameObjectMaps(objectMaps, uuidCollector, namespaceMap, options, usageType);
17
17
  },
18
18
  };
19
19
 
@@ -22,7 +22,7 @@ module.exports = {
22
22
  // ---------------------------------------------------
23
23
 
24
24
  // Goes through all of the objectMaps and creates new name, uuid, etc.
25
- function renameObjectMaps(objectMaps, uuidCollector, namespaceMap, usageType) {
25
+ function renameObjectMaps(objectMaps, uuidCollector, namespaceMap, options, usageType) {
26
26
  obProps.haulTypes.forEach(haulType => {
27
27
  objectMaps[haulType.haulName].forEach(function (objectMap, objectMapIndex) {
28
28
  let curNamespaceForObject = findNamespaceForObject(objectMap["current"][obProps.fieldNames.NAME], namespaceMap);
@@ -44,16 +44,20 @@ function renameObjectMaps(objectMaps, uuidCollector, namespaceMap, usageType) {
44
44
  let newValue;
45
45
  let curValue = objectMap["current"][haulField.fieldName];
46
46
  removeFoundUuids(uuidCollector, haulField, curValue);
47
- if (haulField.isArray) {
48
- let newValueArray = [];
49
- curValue.forEach(curValueIter => {
50
- newValueArray.push(renameObjectProp(curValueIter, haulField, curNamespaceForObject, newNamespaceForObject));
51
- });
52
- newValue = newValueArray;
47
+ if (haulField.fieldName == obProps.fieldNames.DB_TABLE && !options.renameDbTables) {
48
+ newValue = curValue;
53
49
  } else {
54
- newValue = renameObjectProp(curValue, haulField, curNamespaceForObject, newNamespaceForObject);
50
+ if (haulField.isArray) {
51
+ let newValueArray = [];
52
+ curValue.forEach(curValueIter => {
53
+ newValueArray.push(renameObjectProp(curValueIter, haulField, curNamespaceForObject, newNamespaceForObject));
54
+ });
55
+ newValue = newValueArray;
56
+ } else {
57
+ newValue = renameObjectProp(curValue, haulField, curNamespaceForObject, newNamespaceForObject);
58
+ }
59
+ objectMaps[haulType.haulName][objectMapIndex]["new"][haulField.fieldName] = newValue;
55
60
  }
56
- objectMaps[haulType.haulName][objectMapIndex]["new"][haulField.fieldName] = newValue;
57
61
  }
58
62
  });
59
63
  }
@@ -17,11 +17,13 @@ const obTypes = {
17
17
  APPLICATION: "application",
18
18
  REPORT: "tempoReport",
19
19
  SITE: "site",
20
+ PORTAL: "portal",
20
21
  WEBAPI: "webApi",
21
22
  GROUP: "group",
22
23
  GROUPTYPE: "groupType",
23
24
  PROCESSMODELFOLDER: "processModelFolder",
24
25
  CONNECTEDSYSTEM: "connectedSystem",
26
+ AISKILL: "aiSkill",
25
27
  CONTENT: "content", // obTypes.CONTENT contains: [rule, document, rulesFolder, constant, folder, communityKnowledgeCenter, decision, outboundIntegration, report (process report)]
26
28
  };
27
29
 
@@ -32,6 +34,7 @@ const fieldNames = {
32
34
  INPUT_DESCRIPTION: "inputDescription",
33
35
  VERSION: "version",
34
36
  CACHE_VERSION: "cacheVersionKey",
37
+ MODEL_IDS: "modelIds",
35
38
  HISTORY_UUIDS: "historyUuids",
36
39
  CDT_NAMESPACE: "cdtNamespace",
37
40
  CDT_UUID_ENCODED: "cdtUuidEncoded",
@@ -41,7 +44,7 @@ const fieldNames = {
41
44
  NODE_UUIDS: "nodeUuids",
42
45
  PM_PERSISTENT_UUIDS: "pmPersistentUuids",
43
46
  URL_STUB: "urlStub",
44
- SITE_PAGE_UUIDS: "sitePageUuids",
47
+ PAGE_UUIDS: "pageUuids",
45
48
  APP_PREFIX: "appPrefix",
46
49
  RECORD_ACTION_UUIDS: "recordActionUuids",
47
50
  RECORD_ACTION_REF_IDS: "recordActionRefIds",
@@ -396,8 +399,8 @@ const haulTypes = [
396
399
  ],
397
400
  },
398
401
  {
399
- haulName: "Reports, Sites, and Web APIs",
400
- obs: [obTypes.REPORT, obTypes.SITE, obTypes.WEBAPI],
402
+ haulName: "Reports, Sites, Portals, and Web APIs",
403
+ obs: [obTypes.REPORT, obTypes.SITE, obTypes.WEBAPI, obTypes.PORTAL],
401
404
  fields: [
402
405
  {
403
406
  fieldName: fieldNames.UUID,
@@ -438,8 +441,8 @@ const haulTypes = [
438
441
  usage: [usageTypes.CLONE, usageTypes.BUILD],
439
442
  },
440
443
  {
441
- fieldName: fieldNames.SITE_PAGE_UUIDS,
442
- xpath: `siteHaul/site/page/@a:uuid`,
444
+ fieldName: fieldNames.PAGE_UUIDS,
445
+ xpath: `siteHaul/site/page/@a:uuid | portalHaul/portal/navigationNode/@a:uuid`,
443
446
  type: propTypes.UUID,
444
447
  usage: [usageTypes.CLONE, usageTypes.BUILD],
445
448
  isArray: true,
@@ -448,31 +451,35 @@ const haulTypes = [
448
451
  },
449
452
  {
450
453
  haulName: "Everything Else",
451
- obs: [obTypes.GROUP, obTypes.GROUPTYPE, obTypes.PROCESSMODELFOLDER, obTypes.CONNECTEDSYSTEM, obTypes.CONTENT],
454
+ obs: [obTypes.GROUP, obTypes.GROUPTYPE, obTypes.PROCESSMODELFOLDER, obTypes.CONNECTEDSYSTEM, obTypes.AISKILL, obTypes.CONTENT],
452
455
  // obTypes.CONTENT contains: [rule, document, rulesFolder, constant, folder, communityKnowledgeCenter, decision, outboundIntegration, report (process report)]
456
+ /*
457
+ Note, that the leading xpath for almost every object type is `{OBTYPE}Haul` (e.g. "groupHaul"), however for AI skills it's actually "aiSkillRemoteHaul"
458
+ Therefore, what should be `{OBTYPE}Haul/` is now replaced with ``*[starts-with(name(), '{OBTYPE}') and contains(name(), 'Haul')]/`
459
+ */
453
460
  fields: [
454
461
  {
455
462
  fieldName: fieldNames.UUID,
456
- xpath: `{OBTYPE}Haul/*[contains(name(), '')]/uuid/node()`,
463
+ xpath: `*[starts-with(name(), '{OBTYPE}') and contains(name(), 'Haul')]/*[contains(name(), '')]/uuid/node()`,
457
464
  type: propTypes.UUID,
458
465
  usage: [usageTypes.CLONE, usageTypes.BUILD, usageTypes.RENAME],
459
466
  },
460
467
  {
461
468
  fieldName: fieldNames.NAME,
462
- xpath: `{OBTYPE}Haul/*[contains(name(), '')]/name/node()`,
469
+ xpath: `*[starts-with(name(), '{OBTYPE}') and contains(name(), 'Haul')]/*[contains(name(), '')]/name/node()`,
463
470
  type: propTypes.NAME,
464
471
  usage: [usageTypes.CLONE, usageTypes.BUILD, usageTypes.RENAME],
465
472
  },
466
473
  {
467
474
  fieldName: fieldNames.DESCRIPTION,
468
- xpath: `{OBTYPE}Haul/*[contains(name(), '')]/description/node()`,
475
+ xpath: `*[starts-with(name(), '{OBTYPE}') and contains(name(), 'Haul')]/*[contains(name(), '')]/description/node()`,
469
476
  type: propTypes.TEXT,
470
477
  usage: [usageTypes.CLONE, usageTypes.BUILD, usageTypes.RENAME],
471
478
  replaceFormat: "description>{VALUE}</",
472
479
  },
473
480
  {
474
481
  fieldName: fieldNames.INPUT_DESCRIPTION,
475
- xpath: `{OBTYPE}Haul/*[contains(name(), '')]/namedTypedValue/description/node()`,
482
+ xpath: `*[starts-with(name(), '{OBTYPE}') and contains(name(), 'Haul')]/*[contains(name(), '')]/namedTypedValue/description/node()`,
476
483
  type: propTypes.TEXT,
477
484
  usage: [usageTypes.CLONE, usageTypes.BUILD, usageTypes.RENAME],
478
485
  replaceFormat: "description>{VALUE}</",
@@ -480,13 +487,13 @@ const haulTypes = [
480
487
  },
481
488
  {
482
489
  fieldName: fieldNames.VERSION,
483
- xpath: `{OBTYPE}Haul/versionUuid/node()`,
490
+ xpath: `*[starts-with(name(), '{OBTYPE}') and contains(name(), 'Haul')]/versionUuid/node()`,
484
491
  type: propTypes.UUID,
485
492
  usage: [usageTypes.CLONE, usageTypes.BUILD],
486
493
  },
487
494
  {
488
495
  fieldName: fieldNames.HISTORY_UUIDS,
489
- xpath: `{OBTYPE}Haul/history/historyInfo/@versionUuid`,
496
+ xpath: `*[starts-with(name(), '{OBTYPE}') and contains(name(), 'Haul')]/history/historyInfo/@versionUuid`,
490
497
  type: propTypes.UUID,
491
498
  usage: [usageTypes.CLONE, usageTypes.BUILD],
492
499
  isArray: true,
@@ -494,7 +501,7 @@ const haulTypes = [
494
501
  // Only used in documents
495
502
  {
496
503
  fieldName: fieldNames.DOCUMENT_RAW_NAME,
497
- xpath: `{OBTYPE}Haul/document/name/node()`,
504
+ xpath: `contentHaul/document/name/node()`,
498
505
  extractRegex: /.*(?=_default)/g,
499
506
  type: propTypes.TEXT,
500
507
  usage: [usageTypes.CLONE, usageTypes.BUILD, usageTypes.RENAME],
@@ -502,7 +509,7 @@ const haulTypes = [
502
509
  // Only used in documents
503
510
  {
504
511
  fieldName: fieldNames.DOCUMENT_EXTENSION,
505
- xpath: `{OBTYPE}Haul/file/node()`,
512
+ xpath: `contentHaul/file/node()`,
506
513
  extractRegex: /(?<=\.).*/g,
507
514
  type: propTypes.TEXT,
508
515
  usage: [usageTypes.BUILD],
@@ -510,11 +517,20 @@ const haulTypes = [
510
517
  // Only used in decision objects
511
518
  {
512
519
  fieldName: fieldNames.CACHE_VERSION,
513
- xpath: `{OBTYPE}Haul/*[contains(name(), '')]/definition/node()`,
520
+ xpath: `contentHaul/*[contains(name(), '')]/definition/node()`,
514
521
  extractRegex: /(?<=versionKey: ")[A-Za-z0-9-_]{10,}[0-9][A-Za-z0-9-_]{1,}-[A-Za-z0-9-_]{10,}(?=")/g,
515
522
  type: propTypes.UUID,
516
523
  usage: [usageTypes.CLONE, usageTypes.BUILD],
517
524
  },
525
+ // Only used in aiSkills
526
+ {
527
+ fieldName: fieldNames.MODEL_IDS,
528
+ xpath: `aiSkillRemoteHaul/*[contains(name(), '')]/content/node()`,
529
+ extractRegex: /(?<="models":.*"id":")[A-Za-z0-9-_]{10,}[0-9][A-Za-z0-9-_]{1,}-[A-Za-z0-9-_]{10,}(?=")/g,
530
+ type: propTypes.UUID,
531
+ usage: [usageTypes.CLONE, usageTypes.BUILD],
532
+ isArray: true,
533
+ },
518
534
  ],
519
535
  },
520
536
  ];