mcdev 6.0.0 → 6.0.2
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/.github/ISSUE_TEMPLATE/bug.yml +2 -0
- package/.github/PULL_REQUEST_TEMPLATE/pr_template_release.md +4 -3
- package/.github/workflows/code-test.yml +1 -1
- package/.github/workflows/coverage-base-update.yml +2 -2
- package/.github/workflows/coverage-develop-branch.yml +1 -1
- package/.github/workflows/coverage-main-branch.yml +1 -1
- package/.github/workflows/coverage.yml +2 -2
- package/.github/workflows/npm-publish.yml +2 -2
- package/.vscode/settings.json +2 -2
- package/docs/dist/documentation.md +11 -23
- package/lib/Retriever.js +3 -2
- package/lib/cli.js +9 -9
- package/lib/metadataTypes/Automation.js +8 -8
- package/lib/metadataTypes/DataExtension.js +9 -18
- package/lib/metadataTypes/EmailSend.js +48 -28
- package/lib/metadataTypes/Journey.js +2 -2
- package/lib/metadataTypes/TransactionalSMS.js +18 -38
- package/lib/metadataTypes/definitions/MobileKeyword.definition.js +1 -1
- package/lib/util/file.js +9 -9
- package/lib/util/init.npm.js +4 -4
- package/lib/util/util.js +2 -2
- package/package.json +15 -15
- package/test/mockRoot/.mcdevrc.json +1 -1
- package/test/resourceFactory.js +3 -1
- package/test/resources/9999999/asset/block-1157-retrieve-expected.html +22 -0
- package/test/resources/9999999/asset/block-1157-retrieve-expected.json +41 -0
- package/test/resources/9999999/asset/v1/content/assets/1209971/get-response.json +61 -0
- package/test/resources/9999999/asset/v1/content/assets/1295064/get-response.json +60 -0
- package/test/resources/9999999/asset/v1/content/assets/808714/get-response.json +184 -0
- package/test/resources/9999999/asset/v1/content/assets/query/post-response.json +40 -2
- package/test/resources/9999999/automation/v1/scripts/get-response.json +32 -2
- package/test/resources/9999999/dataFolder/retrieve-ContentType=asset-sharedORContentType=asset-response.xml +70 -0
- package/test/resources/9999999/legacy/v1/beta/mobile/keyword/get-response.json +1 -1
- package/test/resources/9999999/legacy/v1/beta/mobile/message/get-response.json +1 -1
- package/test/resources/9999999/messaging/v1/sms/definitions/post-response.json +3 -1
- package/test/resources/9999999/messaging/v1/sms/definitions/testExisting_tsms/get-response.json +3 -1
- package/test/resources/9999999/messaging/v1/sms/definitions/testExisting_tsms/patch-response.json +3 -1
- package/test/resources/9999999/mobileKeyword/build-expected.amp +5 -1
- package/test/resources/9999999/mobileKeyword/get-expected.amp +5 -1
- package/test/resources/9999999/mobileKeyword/post-create-expected.amp +1 -1
- package/test/resources/9999999/mobileKeyword/template-expected.amp +5 -1
- package/test/resources/9999999/mobileMessage/build-expected.amp +6 -1
- package/test/resources/9999999/mobileMessage/get-expected.amp +6 -1
- package/test/resources/9999999/mobileMessage/post-create-expected.amp +1 -1
- package/test/resources/9999999/mobileMessage/post-update-expected.amp +1 -1
- package/test/resources/9999999/mobileMessage/template-expected.amp +6 -1
- package/test/resources/9999999/script/get_ampincluded-expected.json +8 -0
- package/test/resources/9999999/script/get_ampincluded-expected.ssjs +5 -0
- package/test/resources/9999999/script/get_ampscript-expected.html +5 -0
- package/test/resources/9999999/script/get_ampscript-expected.json +8 -0
- package/test/resources/9999999/script/get_mixed-expected.html +9 -0
- package/test/resources/9999999/script/get_mixed-expected.json +8 -0
- package/test/resources/9999999/transactionalSMS/build-expected.amp +105 -1
- package/test/resources/9999999/transactionalSMS/get-expected.amp +105 -1
- package/test/resources/9999999/transactionalSMS/patch-expected.amp +99 -1
- package/test/resources/9999999/transactionalSMS/post-expected.amp +99 -1
- package/test/resources/9999999/transactionalSMS/template-expected.amp +105 -1
- package/test/type.asset.test.js +84 -0
- package/test/type.automation.test.js +0 -1
- package/test/type.script.test.js +54 -14
- package/test/utils.js +3 -0
|
@@ -4,15 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
- [ ] Wiki updated with info in ticket listed under **Documentation**
|
|
6
6
|
- [ ] ran `npm audit fix`
|
|
7
|
+
- [ ] ran `lint:fix`
|
|
7
8
|
- [ ] ran task version:major/minor/patch
|
|
8
9
|
- [ ] updated [bug template](/.github/ISSUE_TEMPLATE/bug.yml) to include the new version
|
|
9
|
-
- [ ] updated [.mcdevrc](/test/mockRoot/.mcdevrc.json) to the new version
|
|
10
|
+
- [ ] updated [.mcdevrc](/test/mockRoot/.mcdevrc.json) for tests to the new version
|
|
10
11
|
- [ ] (after merge) moved version tag to merge commit
|
|
11
|
-
- [ ] created [new GitHub Release](https://github.com/Accenture/sfmc-devtools/releases/new)
|
|
12
|
+
- [ ] created [new GitHub Release](https://github.com/Accenture/sfmc-devtools/releases/new)
|
|
12
13
|
|
|
13
14
|
## Documentation
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
... insert updated documentation here ...
|
|
16
17
|
|
|
17
18
|
## Issues
|
|
18
19
|
|
|
@@ -24,7 +24,7 @@ jobs:
|
|
|
24
24
|
git fetch origin ${{ github.event.pull_request.base.ref }} --depth=1000
|
|
25
25
|
|
|
26
26
|
- name: Download artifact for base branch
|
|
27
|
-
uses: dawidd6/action-download-artifact@
|
|
27
|
+
uses: dawidd6/action-download-artifact@v3
|
|
28
28
|
continue-on-error: true
|
|
29
29
|
with:
|
|
30
30
|
workflow: ${{ github.event.pull_request.base.ref == 'main' && 'coverage-main-branch.yml' || github.event.pull_request.base.ref == 'develop' && 'coverage-develop-branch.yml' || 'coverage.yml' }}
|
|
@@ -35,7 +35,7 @@ jobs:
|
|
|
35
35
|
search_artifacts: true
|
|
36
36
|
|
|
37
37
|
- name: Download artifact for to be merged branch
|
|
38
|
-
uses: dawidd6/action-download-artifact@
|
|
38
|
+
uses: dawidd6/action-download-artifact@v3
|
|
39
39
|
continue-on-error: true
|
|
40
40
|
with:
|
|
41
41
|
workflow: 'coverage.yml'
|
|
@@ -17,7 +17,7 @@ jobs:
|
|
|
17
17
|
ref: ${{ github.event.pull_request.head.sha }}
|
|
18
18
|
fetch-depth: 1000
|
|
19
19
|
|
|
20
|
-
- uses: actions/setup-node@
|
|
20
|
+
- uses: actions/setup-node@v4
|
|
21
21
|
with:
|
|
22
22
|
node-version: 16
|
|
23
23
|
|
|
@@ -56,7 +56,7 @@ jobs:
|
|
|
56
56
|
GITHUB_TOKEN: ${{ github.token }}
|
|
57
57
|
|
|
58
58
|
- name: Download artifact for base branch if available, previous
|
|
59
|
-
uses: dawidd6/action-download-artifact@
|
|
59
|
+
uses: dawidd6/action-download-artifact@v3
|
|
60
60
|
continue-on-error: true
|
|
61
61
|
with:
|
|
62
62
|
workflow: ${{ github.event.pull_request.base.ref == 'main' && 'coverage-main-branch.yml' || github.event.pull_request.base.ref == 'develop' && 'coverage-develop-branch.yml' || 'coverage.yml' }}
|
|
@@ -12,7 +12,7 @@ jobs:
|
|
|
12
12
|
runs-on: ubuntu-latest
|
|
13
13
|
steps:
|
|
14
14
|
- uses: actions/checkout@v4
|
|
15
|
-
- uses: actions/setup-node@
|
|
15
|
+
- uses: actions/setup-node@v4
|
|
16
16
|
with:
|
|
17
17
|
node-version: 16
|
|
18
18
|
- run: npm ci
|
|
@@ -23,7 +23,7 @@ jobs:
|
|
|
23
23
|
runs-on: ubuntu-latest
|
|
24
24
|
steps:
|
|
25
25
|
- uses: actions/checkout@v4
|
|
26
|
-
- uses: actions/setup-node@
|
|
26
|
+
- uses: actions/setup-node@v4
|
|
27
27
|
with:
|
|
28
28
|
node-version: 16
|
|
29
29
|
registry-url: https://registry.npmjs.org/
|
package/.vscode/settings.json
CHANGED
|
@@ -2472,7 +2472,6 @@ MessageSendActivity MetadataType
|
|
|
2472
2472
|
* [.deleteByKey(customerKey)](#EmailSend.deleteByKey) ⇒ <code>Promise.<boolean></code>
|
|
2473
2473
|
* [.preDeployTasks(metadata)](#EmailSend.preDeployTasks) ⇒ <code>Promise.<TYPE.MetadataTypeItem></code>
|
|
2474
2474
|
* [.postRetrieveTasks(metadata)](#EmailSend.postRetrieveTasks) ⇒ <code>TYPE.MetadataTypeItem</code>
|
|
2475
|
-
* [.parseMetadata(metadata)](#EmailSend.parseMetadata) ⇒ <code>TYPE.MetadataTypeItem</code>
|
|
2476
2475
|
|
|
2477
2476
|
<a name="EmailSend.retrieve"></a>
|
|
2478
2477
|
|
|
@@ -2549,18 +2548,6 @@ manages post retrieve steps
|
|
|
2549
2548
|
| --- | --- | --- |
|
|
2550
2549
|
| metadata | <code>TYPE.MetadataTypeItem</code> | a single query |
|
|
2551
2550
|
|
|
2552
|
-
<a name="EmailSend.parseMetadata"></a>
|
|
2553
|
-
|
|
2554
|
-
### EmailSend.parseMetadata(metadata) ⇒ <code>TYPE.MetadataTypeItem</code>
|
|
2555
|
-
parses retrieved Metadata before saving
|
|
2556
|
-
|
|
2557
|
-
**Kind**: static method of [<code>EmailSend</code>](#EmailSend)
|
|
2558
|
-
**Returns**: <code>TYPE.MetadataTypeItem</code> - Array with one metadata object and one sql string
|
|
2559
|
-
|
|
2560
|
-
| Param | Type | Description |
|
|
2561
|
-
| --- | --- | --- |
|
|
2562
|
-
| metadata | <code>TYPE.MetadataTypeItem</code> | a single query activity definition |
|
|
2563
|
-
|
|
2564
2551
|
<a name="Event"></a>
|
|
2565
2552
|
|
|
2566
2553
|
## Event ⇐ [<code>MetadataType</code>](#MetadataType)
|
|
@@ -5645,8 +5632,8 @@ TransactionalSMS MetadataType
|
|
|
5645
5632
|
* [.postDeleteTasks(customerKey)](#TransactionalSMS.postDeleteTasks) ⇒ <code>void</code>
|
|
5646
5633
|
* [.preDeployTasks(metadata, deployDir)](#TransactionalSMS.preDeployTasks) ⇒ <code>Promise.<TYPE.MetadataTypeItem></code>
|
|
5647
5634
|
* [._mergeCode(metadata, deployDir, [templateName])](#TransactionalSMS._mergeCode) ⇒ <code>Promise.<string></code>
|
|
5648
|
-
* [.postRetrieveTasks(metadata)](#TransactionalSMS.postRetrieveTasks) ⇒ <code>TYPE.CodeExtractItem
|
|
5649
|
-
* [.prepExtractedCode(metadataScript)](#TransactionalSMS.prepExtractedCode) ⇒ <code>
|
|
5635
|
+
* [.postRetrieveTasks(metadata)](#TransactionalSMS.postRetrieveTasks) ⇒ <code>Promise.<TYPE.CodeExtractItem></code>
|
|
5636
|
+
* [.prepExtractedCode(metadataScript)](#TransactionalSMS.prepExtractedCode) ⇒ <code>Promise.<{fileExt:string, code:string}></code>
|
|
5650
5637
|
* [.buildDefinitionForNested(templateDir, targetDir, metadata, templateVariables, templateName)](#TransactionalSMS.buildDefinitionForNested) ⇒ <code>Promise.<Array.<Array.<string>>></code>
|
|
5651
5638
|
* [.buildTemplateForNested(templateDir, targetDir, metadata, templateVariables, templateName)](#TransactionalSMS.buildTemplateForNested) ⇒ <code>Promise.<Array.<Array.<string>>></code>
|
|
5652
5639
|
* [._buildForNested(templateDir, targetDir, metadata, templateVariables, templateName, mode)](#TransactionalSMS._buildForNested) ⇒ <code>Promise.<Array.<Array.<string>>></code>
|
|
@@ -5693,11 +5680,11 @@ helper for [preDeployTasks](#TransactionalSMS.preDeployTasks) that loads extract
|
|
|
5693
5680
|
|
|
5694
5681
|
<a name="TransactionalSMS.postRetrieveTasks"></a>
|
|
5695
5682
|
|
|
5696
|
-
### TransactionalSMS.postRetrieveTasks(metadata) ⇒ <code>TYPE.CodeExtractItem
|
|
5683
|
+
### TransactionalSMS.postRetrieveTasks(metadata) ⇒ <code>Promise.<TYPE.CodeExtractItem></code>
|
|
5697
5684
|
manages post retrieve steps
|
|
5698
5685
|
|
|
5699
5686
|
**Kind**: static method of [<code>TransactionalSMS</code>](#TransactionalSMS)
|
|
5700
|
-
**Returns**: <code>TYPE.CodeExtractItem
|
|
5687
|
+
**Returns**: <code>Promise.<TYPE.CodeExtractItem></code> - Array with one metadata object and one ssjs string
|
|
5701
5688
|
|
|
5702
5689
|
| Param | Type | Description |
|
|
5703
5690
|
| --- | --- | --- |
|
|
@@ -5705,11 +5692,11 @@ manages post retrieve steps
|
|
|
5705
5692
|
|
|
5706
5693
|
<a name="TransactionalSMS.prepExtractedCode"></a>
|
|
5707
5694
|
|
|
5708
|
-
### TransactionalSMS.prepExtractedCode(metadataScript) ⇒ <code>
|
|
5695
|
+
### TransactionalSMS.prepExtractedCode(metadataScript) ⇒ <code>Promise.<{fileExt:string, code:string}></code>
|
|
5709
5696
|
helper for [postRetrieveTasks](#TransactionalSMS.postRetrieveTasks) and [_buildForNested](#TransactionalSMS._buildForNested)
|
|
5710
5697
|
|
|
5711
5698
|
**Kind**: static method of [<code>TransactionalSMS</code>](#TransactionalSMS)
|
|
5712
|
-
**Returns**: <code>
|
|
5699
|
+
**Returns**: <code>Promise.<{fileExt:string, code:string}></code> - returns found extension and file content
|
|
5713
5700
|
|
|
5714
5701
|
| Param | Type | Description |
|
|
5715
5702
|
| --- | --- | --- |
|
|
@@ -6637,7 +6624,7 @@ File extends fs-extra. It adds logger and util methods for file handling
|
|
|
6637
6624
|
* [.normalizePath(denormalizedPath)](#File.normalizePath) ⇒ <code>string</code>
|
|
6638
6625
|
* [.writeJSONToFile(directory, filename, content)](#File.writeJSONToFile) ⇒ <code>Promise</code>
|
|
6639
6626
|
* [.writePrettyToFile(directory, filename, filetype, content, [templateVariables])](#File.writePrettyToFile) ⇒ <code>Promise.<boolean></code>
|
|
6640
|
-
* [.
|
|
6627
|
+
* [.beautify_beautyAmp(content, formatHTML)](#File.beautify_beautyAmp) ⇒ <code>Promise.<string></code>
|
|
6641
6628
|
* [._beautify_prettier(directory, filename, filetype, content)](#File._beautify_prettier) ⇒ <code>Promise.<string></code>
|
|
6642
6629
|
* [.writeToFile(directory, filename, filetype, content, [encoding])](#File.writeToFile) ⇒ <code>Promise.<boolean></code>
|
|
6643
6630
|
* [.readJSONFile(directory, filename, sync, cleanPath)](#File.readJSONFile) ⇒ <code>Promise.<object></code> \| <code>object</code> \| <code>void</code>
|
|
@@ -6739,17 +6726,18 @@ Saves beautified files in the local file system. Will create the parent director
|
|
|
6739
6726
|
| content | <code>string</code> | filecontent |
|
|
6740
6727
|
| [templateVariables] | <code>TYPE.TemplateMap</code> | templating variables to be replaced in the metadata |
|
|
6741
6728
|
|
|
6742
|
-
<a name="File.
|
|
6729
|
+
<a name="File.beautify_beautyAmp"></a>
|
|
6743
6730
|
|
|
6744
|
-
### File
|
|
6731
|
+
### File.beautify\_beautyAmp(content, formatHTML) ⇒ <code>Promise.<string></code>
|
|
6745
6732
|
helper for [writePrettyToFile](#File.writePrettyToFile), applying beautyAmp onto given stringified content
|
|
6746
6733
|
|
|
6747
6734
|
**Kind**: static method of [<code>File</code>](#File)
|
|
6748
|
-
**Returns**: <code>string
|
|
6735
|
+
**Returns**: <code>Promise.<string></code> - original string on error; formatted string on success
|
|
6749
6736
|
|
|
6750
6737
|
| Param | Type | Description |
|
|
6751
6738
|
| --- | --- | --- |
|
|
6752
6739
|
| content | <code>string</code> | filecontent |
|
|
6740
|
+
| formatHTML | <code>boolean</code> | should we format HTML or not via prettier included in beautyAmp |
|
|
6753
6741
|
|
|
6754
6742
|
<a name="File._beautify_prettier"></a>
|
|
6755
6743
|
|
package/lib/Retriever.js
CHANGED
|
@@ -66,8 +66,9 @@ class Retriever {
|
|
|
66
66
|
const subTypeArr = deployOrder[type];
|
|
67
67
|
// if types were added by getMetadataHierachy() for caching, make sure the key-list is set to [null] for them which will retrieve all
|
|
68
68
|
// if we have a subtype, we need to find the correct key-list for it
|
|
69
|
-
typeKeyMap[type]
|
|
70
|
-
|
|
69
|
+
typeKeyMap[type] ||= typeKeyMap[
|
|
70
|
+
Object.keys(typeKeyMap).find((k) => k.startsWith(type + '-'))
|
|
71
|
+
] || [null];
|
|
71
72
|
|
|
72
73
|
// add client to metadata process class instead of passing every time
|
|
73
74
|
MetadataTypeInfo[type].client = auth.getSDK(this.buObject);
|
package/lib/cli.js
CHANGED
|
@@ -617,13 +617,13 @@ function csvToArray(csv) {
|
|
|
617
617
|
return !csv
|
|
618
618
|
? null
|
|
619
619
|
: csv.includes(',')
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
620
|
+
? csv
|
|
621
|
+
.split(',')
|
|
622
|
+
.map((item) =>
|
|
623
|
+
// allow whitespace in comma-separated lists
|
|
624
|
+
item.trim()
|
|
625
|
+
)
|
|
626
|
+
// make sure trailing commas are ignored
|
|
627
|
+
.filter(Boolean)
|
|
628
|
+
: [csv.trim()].filter(Boolean);
|
|
629
629
|
}
|
|
@@ -945,8 +945,8 @@ class Automation extends MetadataType {
|
|
|
945
945
|
item.type = scheduleHelper
|
|
946
946
|
? 'scheduled'
|
|
947
947
|
: item.fileTrigger
|
|
948
|
-
|
|
949
|
-
|
|
948
|
+
? 'triggered'
|
|
949
|
+
: undefined;
|
|
950
950
|
|
|
951
951
|
// el.schedule.timezoneName
|
|
952
952
|
if (item.type === 'scheduled') {
|
|
@@ -1203,10 +1203,10 @@ class Automation extends MetadataType {
|
|
|
1203
1203
|
const patternType = recurHelper['BYMONTH']
|
|
1204
1204
|
? 'ByMonth'
|
|
1205
1205
|
: recurHelper['BYWEEK']
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1206
|
+
? 'ByWeek'
|
|
1207
|
+
: recurHelper['BYDAY']
|
|
1208
|
+
? 'ByDay'
|
|
1209
|
+
: 'Interval';
|
|
1210
1210
|
schedule.Recurrence[keyStem + 'lyRecurrencePatternType'] = patternType;
|
|
1211
1211
|
schedule.Recurrence['@_xsi:type'] = keyStem + 'lyRecurrence';
|
|
1212
1212
|
schedule.RecurrenceType = keyStem + 'ly';
|
|
@@ -1387,8 +1387,8 @@ class Automation extends MetadataType {
|
|
|
1387
1387
|
ical.COUNT
|
|
1388
1388
|
? ` for ${ical.COUNT} times`
|
|
1389
1389
|
: ical.UNTIL
|
|
1390
|
-
|
|
1391
|
-
|
|
1390
|
+
? ' until end date'
|
|
1391
|
+
: ''
|
|
1392
1392
|
}`;
|
|
1393
1393
|
output += '\n';
|
|
1394
1394
|
} else if (json.schedule) {
|
|
@@ -28,24 +28,14 @@ class DataExtension extends MetadataType {
|
|
|
28
28
|
*/
|
|
29
29
|
static async upsert(metadataMap) {
|
|
30
30
|
// get existing DE-fields for DE-keys in deployment package to properly handle add/update/delete of fields
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
},
|
|
40
|
-
operator: 'OR',
|
|
41
|
-
rightOperand: fieldOptions.filter,
|
|
42
|
-
}
|
|
43
|
-
: {
|
|
44
|
-
leftOperand: 'DataExtension.CustomerKey',
|
|
45
|
-
operator: 'equals',
|
|
46
|
-
rightOperand: key,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
31
|
+
// we need to use IN here because it would fail otherwise if we try to deploy too many DEs at the same time
|
|
32
|
+
const fieldOptions = {
|
|
33
|
+
filter: {
|
|
34
|
+
leftOperand: 'DataExtension.CustomerKey',
|
|
35
|
+
operator: 'IN',
|
|
36
|
+
rightOperand: Object.keys(metadataMap),
|
|
37
|
+
},
|
|
38
|
+
};
|
|
49
39
|
Util.logger.info(` - Caching dependent Metadata: dataExtensionField`);
|
|
50
40
|
await this.#attachFields(metadataMap, fieldOptions);
|
|
51
41
|
|
|
@@ -868,6 +858,7 @@ class DataExtension extends MetadataType {
|
|
|
868
858
|
static async #attachFields(metadata, fieldOptions, additionalFields) {
|
|
869
859
|
const fieldsObj = await this._retrieveFields(fieldOptions, additionalFields);
|
|
870
860
|
const fieldKeys = Object.keys(fieldsObj);
|
|
861
|
+
|
|
871
862
|
// add fields to corresponding DE
|
|
872
863
|
for (const key of fieldKeys) {
|
|
873
864
|
const field = fieldsObj[key];
|
|
@@ -96,8 +96,8 @@ class EmailSend extends MetadataType {
|
|
|
96
96
|
metadata.IsPlatformObject = false;
|
|
97
97
|
// folder
|
|
98
98
|
super.setFolderId(metadata);
|
|
99
|
-
// email
|
|
100
|
-
metadata.Email
|
|
99
|
+
// email; in case we still have Email.ID, keep it but warn
|
|
100
|
+
metadata.Email ||= {};
|
|
101
101
|
if (metadata.r__email_Name) {
|
|
102
102
|
// classic
|
|
103
103
|
metadata.Email.ID = cache.searchForField('email', metadata.r__email_Name, 'Name', 'ID');
|
|
@@ -131,6 +131,30 @@ class EmailSend extends MetadataType {
|
|
|
131
131
|
delete metadata.r__assetMessage_Key;
|
|
132
132
|
delete metadata.r__assetMessage_Name;
|
|
133
133
|
}
|
|
134
|
+
} else if (metadata.Email.ID) {
|
|
135
|
+
Util.logger.warn(
|
|
136
|
+
` - ${this.definition.type} ${metadata[this.definition.nameField]} (${
|
|
137
|
+
metadata[this.definition.keyField]
|
|
138
|
+
}): Email.ID was provided manually in your deployment file. We recommend using r__assetMessage_Key instead.`
|
|
139
|
+
);
|
|
140
|
+
try {
|
|
141
|
+
// content builder - test only
|
|
142
|
+
cache.searchForField(
|
|
143
|
+
'asset',
|
|
144
|
+
metadata.Email.ID,
|
|
145
|
+
'legacyData.legacyId',
|
|
146
|
+
'customerKey'
|
|
147
|
+
);
|
|
148
|
+
} catch {
|
|
149
|
+
try {
|
|
150
|
+
// classic - test only
|
|
151
|
+
cache.searchForField('email', metadata.Email.ID, 'ID', 'Name');
|
|
152
|
+
} catch {
|
|
153
|
+
throw new Error(
|
|
154
|
+
` ☇ skipping ${this.definition.type} ${metadata.Name} (${metadata.CustomerKey}): Could not find email with ID ${metadata.Email.ID} in Content Builder or Classic Emails.`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
134
158
|
}
|
|
135
159
|
// Target Audience DataExtension
|
|
136
160
|
// normalize first because this can be an array
|
|
@@ -189,15 +213,6 @@ class EmailSend extends MetadataType {
|
|
|
189
213
|
* @returns {TYPE.MetadataTypeItem} Array with one metadata object and one query string
|
|
190
214
|
*/
|
|
191
215
|
static postRetrieveTasks(metadata) {
|
|
192
|
-
return this.parseMetadata(metadata);
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* parses retrieved Metadata before saving
|
|
196
|
-
*
|
|
197
|
-
* @param {TYPE.MetadataTypeItem} metadata a single query activity definition
|
|
198
|
-
* @returns {TYPE.MetadataTypeItem} Array with one metadata object and one sql string
|
|
199
|
-
*/
|
|
200
|
-
static parseMetadata(metadata) {
|
|
201
216
|
// remove IsPlatformObject, always has to be 'false'
|
|
202
217
|
delete metadata.IsPlatformObject;
|
|
203
218
|
// folder
|
|
@@ -206,27 +221,32 @@ class EmailSend extends MetadataType {
|
|
|
206
221
|
// email
|
|
207
222
|
if (metadata.Email?.ID) {
|
|
208
223
|
try {
|
|
209
|
-
//
|
|
210
|
-
const
|
|
211
|
-
|
|
224
|
+
// content builder
|
|
225
|
+
const contentBuilderEmailName = cache.searchForField(
|
|
226
|
+
'asset',
|
|
227
|
+
metadata.Email.ID,
|
|
228
|
+
'legacyData.legacyId',
|
|
229
|
+
'name'
|
|
230
|
+
);
|
|
231
|
+
metadata.r__assetMessage_Name = contentBuilderEmailName;
|
|
232
|
+
const contentBuilderEmailKey = cache.searchForField(
|
|
233
|
+
'asset',
|
|
234
|
+
metadata.Email.ID,
|
|
235
|
+
'legacyData.legacyId',
|
|
236
|
+
'customerKey'
|
|
237
|
+
);
|
|
238
|
+
metadata.r__assetMessage_Key = contentBuilderEmailKey;
|
|
212
239
|
delete metadata.Email;
|
|
213
240
|
} catch {
|
|
214
241
|
try {
|
|
215
|
-
//
|
|
216
|
-
const
|
|
217
|
-
'
|
|
218
|
-
metadata.Email.ID,
|
|
219
|
-
'legacyData.legacyId',
|
|
220
|
-
'name'
|
|
221
|
-
);
|
|
222
|
-
metadata.r__assetMessage_Name = contentBuilderEmailName;
|
|
223
|
-
const contentBuilderEmailKey = cache.searchForField(
|
|
224
|
-
'asset',
|
|
242
|
+
// classic
|
|
243
|
+
const classicEmail = cache.searchForField(
|
|
244
|
+
'email',
|
|
225
245
|
metadata.Email.ID,
|
|
226
|
-
'
|
|
227
|
-
'
|
|
246
|
+
'ID',
|
|
247
|
+
'Name'
|
|
228
248
|
);
|
|
229
|
-
metadata.
|
|
249
|
+
metadata.r__email_Name = classicEmail;
|
|
230
250
|
delete metadata.Email;
|
|
231
251
|
} catch {
|
|
232
252
|
Util.logger.warn(
|
|
@@ -234,7 +254,7 @@ class EmailSend extends MetadataType {
|
|
|
234
254
|
metadata[this.definition.keyField]
|
|
235
255
|
}): Could not find email with ID ${
|
|
236
256
|
metadata.Email.ID
|
|
237
|
-
}
|
|
257
|
+
} Content Builder or Classic Emails.`
|
|
238
258
|
);
|
|
239
259
|
}
|
|
240
260
|
}
|
|
@@ -571,7 +571,7 @@ class Journey extends MetadataType {
|
|
|
571
571
|
'mobileKeyword',
|
|
572
572
|
activity.configurationArguments.nextKeywordId,
|
|
573
573
|
'id',
|
|
574
|
-
'
|
|
574
|
+
'c__codeKeyword'
|
|
575
575
|
);
|
|
576
576
|
delete activity.configurationArguments.nextKeywordId;
|
|
577
577
|
}
|
|
@@ -853,7 +853,7 @@ class Journey extends MetadataType {
|
|
|
853
853
|
activity.configurationArguments.nextKeywordId = cache.searchForField(
|
|
854
854
|
'mobileKeyword',
|
|
855
855
|
activity.configurationArguments.c__next_mobileKeyword,
|
|
856
|
-
'
|
|
856
|
+
'c__codeKeyword',
|
|
857
857
|
'id'
|
|
858
858
|
);
|
|
859
859
|
delete activity.configurationArguments.c__next_mobileKeyword;
|
|
@@ -4,7 +4,6 @@ import TYPE from '../../types/mcdev.d.js';
|
|
|
4
4
|
import TransactionalMessage from './TransactionalMessage.js';
|
|
5
5
|
import { Util } from '../util/util.js';
|
|
6
6
|
import File from '../util/file.js';
|
|
7
|
-
import beautifier from 'beauty-amp-core';
|
|
8
7
|
import cache from '../util/cache.js';
|
|
9
8
|
|
|
10
9
|
/**
|
|
@@ -52,16 +51,16 @@ class TransactionalSMS extends TransactionalMessage {
|
|
|
52
51
|
if (metadata.subscriptions?.shortCode) {
|
|
53
52
|
// we merely want to be able to show an error if it does not exist
|
|
54
53
|
cache.searchForField('mobileCode', metadata.subscriptions.shortCode, 'code', 'code');
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
54
|
+
// subscriptions: mobileKeyword
|
|
55
|
+
if (metadata.subscriptions?.keyword) {
|
|
56
|
+
// we merely want to be able to show an error if it does not exist
|
|
57
|
+
cache.searchForField(
|
|
58
|
+
'mobileKeyword',
|
|
59
|
+
metadata.subscriptions.shortCode + '.' + metadata.subscriptions.keyword,
|
|
60
|
+
'c__codeKeyword',
|
|
61
|
+
'id'
|
|
62
|
+
);
|
|
63
|
+
}
|
|
65
64
|
}
|
|
66
65
|
return metadata;
|
|
67
66
|
}
|
|
@@ -95,13 +94,13 @@ class TransactionalSMS extends TransactionalMessage {
|
|
|
95
94
|
* manages post retrieve steps
|
|
96
95
|
*
|
|
97
96
|
* @param {TYPE.MetadataTypeItem} metadata a single item
|
|
98
|
-
* @returns {TYPE.CodeExtractItem} Array with one metadata object and one ssjs string
|
|
97
|
+
* @returns {Promise.<TYPE.CodeExtractItem>} Array with one metadata object and one ssjs string
|
|
99
98
|
*/
|
|
100
|
-
static postRetrieveTasks(metadata) {
|
|
99
|
+
static async postRetrieveTasks(metadata) {
|
|
101
100
|
// extract message body
|
|
102
101
|
const codeArr = [];
|
|
103
102
|
// keep between tags
|
|
104
|
-
const { fileExt, code } = this.prepExtractedCode(metadata.content?.message);
|
|
103
|
+
const { fileExt, code } = await this.prepExtractedCode(metadata.content?.message);
|
|
105
104
|
delete metadata.content;
|
|
106
105
|
codeArr.push({
|
|
107
106
|
subFolder: null,
|
|
@@ -143,7 +142,7 @@ class TransactionalSMS extends TransactionalMessage {
|
|
|
143
142
|
cache.searchForField(
|
|
144
143
|
'mobileKeyword',
|
|
145
144
|
metadata.subscriptions.shortCode + '.' + metadata.subscriptions.keyword,
|
|
146
|
-
'
|
|
145
|
+
'c__codeKeyword',
|
|
147
146
|
'id'
|
|
148
147
|
);
|
|
149
148
|
} catch {
|
|
@@ -161,29 +160,10 @@ class TransactionalSMS extends TransactionalMessage {
|
|
|
161
160
|
* helper for {@link TransactionalSMS.postRetrieveTasks} and {@link TransactionalSMS._buildForNested}
|
|
162
161
|
*
|
|
163
162
|
* @param {string} metadataScript the code of the file
|
|
164
|
-
* @returns {{fileExt:string,code:string}} returns found extension and file content
|
|
163
|
+
* @returns {Promise.<{fileExt:string,code:string}>} returns found extension and file content
|
|
165
164
|
*/
|
|
166
|
-
static prepExtractedCode(metadataScript) {
|
|
167
|
-
|
|
168
|
-
const ampscript = {
|
|
169
|
-
capitalizeAndOrNot: true,
|
|
170
|
-
capitalizeIfFor: true,
|
|
171
|
-
capitalizeSet: true,
|
|
172
|
-
capitalizeVar: true,
|
|
173
|
-
maxParametersPerLine: 4,
|
|
174
|
-
};
|
|
175
|
-
// immutable at the moment:
|
|
176
|
-
const editor = {
|
|
177
|
-
insertSpaces: true,
|
|
178
|
-
tabSize: 4,
|
|
179
|
-
};
|
|
180
|
-
// logs trough console only for the moment.
|
|
181
|
-
const logs = {
|
|
182
|
-
loggerOn: false, // <= disable logging
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
beautifier.setup(ampscript, editor, logs);
|
|
186
|
-
const code = beautifier.beautify(metadataScript);
|
|
165
|
+
static async prepExtractedCode(metadataScript) {
|
|
166
|
+
const code = await File.beautify_beautyAmp(metadataScript, false);
|
|
187
167
|
const fileExt = 'amp';
|
|
188
168
|
|
|
189
169
|
return { fileExt, code };
|
|
@@ -266,7 +246,7 @@ class TransactionalSMS extends TransactionalMessage {
|
|
|
266
246
|
) {
|
|
267
247
|
// get code from filesystem
|
|
268
248
|
let code = await this._mergeCode(metadata, templateDir, templateName);
|
|
269
|
-
const file = this.prepExtractedCode(code, metadata.name);
|
|
249
|
+
const file = await this.prepExtractedCode(code, metadata.name);
|
|
270
250
|
const fileExt = file.fileExt;
|
|
271
251
|
code = file.code;
|
|
272
252
|
// apply templating
|
|
@@ -5,7 +5,7 @@ export default {
|
|
|
5
5
|
idField: 'id',
|
|
6
6
|
keyIsFixed: false, // custom field but mapped to normal fields
|
|
7
7
|
keyField: 'c__codeKeyword',
|
|
8
|
-
nameField: '
|
|
8
|
+
nameField: 'c__codeKeyword',
|
|
9
9
|
createdDateField: 'createdDate',
|
|
10
10
|
createdNameField: 'createdBy.name',
|
|
11
11
|
lastmodDateField: 'lastUpdated',
|
package/lib/util/file.js
CHANGED
|
@@ -6,7 +6,7 @@ import fs from 'fs-extra';
|
|
|
6
6
|
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import prettier from 'prettier';
|
|
9
|
-
import beautyAmp from 'beauty-amp-
|
|
9
|
+
import beautyAmp from 'beauty-amp-core2';
|
|
10
10
|
import { Util } from './util.js';
|
|
11
11
|
import updateNotifier from 'update-notifier';
|
|
12
12
|
|
|
@@ -171,7 +171,7 @@ const File = {
|
|
|
171
171
|
writePrettyToFile: async function (directory, filename, filetype, content, templateVariables) {
|
|
172
172
|
let formatted =
|
|
173
173
|
filetype === 'amp'
|
|
174
|
-
? this.
|
|
174
|
+
? await this.beautify_beautyAmp(content, false)
|
|
175
175
|
: await this._beautify_prettier(directory, filename, filetype, content);
|
|
176
176
|
if (templateVariables) {
|
|
177
177
|
formatted = Util.replaceByObject(formatted, templateVariables);
|
|
@@ -182,10 +182,10 @@ const File = {
|
|
|
182
182
|
* helper for {@link File.writePrettyToFile}, applying beautyAmp onto given stringified content
|
|
183
183
|
*
|
|
184
184
|
* @param {string} content filecontent
|
|
185
|
-
* @
|
|
185
|
+
* @param {boolean} formatHTML should we format HTML or not via prettier included in beautyAmp
|
|
186
|
+
* @returns {Promise.<string>} original string on error; formatted string on success
|
|
186
187
|
*/
|
|
187
|
-
|
|
188
|
-
// immutable at the moment:
|
|
188
|
+
beautify_beautyAmp: async function (content, formatHTML = true) {
|
|
189
189
|
const ampscript = {
|
|
190
190
|
capitalizeAndOrNot: true,
|
|
191
191
|
capitalizeIfFor: true,
|
|
@@ -193,7 +193,6 @@ const File = {
|
|
|
193
193
|
capitalizeVar: true,
|
|
194
194
|
maxParametersPerLine: 4,
|
|
195
195
|
};
|
|
196
|
-
// immutable at the moment:
|
|
197
196
|
const editor = {
|
|
198
197
|
insertSpaces: true,
|
|
199
198
|
tabSize: 4,
|
|
@@ -204,9 +203,10 @@ const File = {
|
|
|
204
203
|
};
|
|
205
204
|
try {
|
|
206
205
|
beautyAmp.setup(ampscript, editor, logs);
|
|
207
|
-
|
|
206
|
+
// Note: we need to trim the result as beautyAmp adds a leading new line; but we also want to ensure there is a single new line at the end to comply with standard linting rules
|
|
207
|
+
return (await beautyAmp.beautify(content, formatHTML)).trim() + '\n';
|
|
208
208
|
} catch (ex) {
|
|
209
|
-
Util.logger.debug('File.
|
|
209
|
+
Util.logger.debug('File.beautify_beautyAmp:: error | ' + ex.message);
|
|
210
210
|
return content;
|
|
211
211
|
}
|
|
212
212
|
},
|
|
@@ -229,7 +229,7 @@ const File = {
|
|
|
229
229
|
} else if (content.includes('%%[') || content.includes('%%=')) {
|
|
230
230
|
// in case we find AMPScript we need to abort beautifying as prettier
|
|
231
231
|
// will throw an error falsely assuming bad syntax
|
|
232
|
-
return this.
|
|
232
|
+
return await this.beautify_beautyAmp(content, true);
|
|
233
233
|
}
|
|
234
234
|
// load the right prettier config relative to our file
|
|
235
235
|
switch (filetype) {
|