Skip to content

Commit

Permalink
#789: generalize postCreateTasks for Legacy API endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
JoernBerkefeld committed Mar 30, 2023
1 parent 2ee7d3a commit fe779d8
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 34 deletions.
37 changes: 30 additions & 7 deletions docs/dist/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -3155,12 +3155,13 @@ Provides default functionality that can be overwritten by child metadata type cl
* [.deploy(metadata, deployDir, retrieveDir, [isRefresh])](#MetadataType.deploy) ⇒ <code>Promise.&lt;TYPE.MetadataTypeMap&gt;</code>
* [.postDeployTasks(upsertResults, originalMetadata, createdUpdated, [isRefresh])](#MetadataType.postDeployTasks) ⇒ <code>void</code>
* [.postCreateTasks(metadataEntry, apiResponse)](#MetadataType.postCreateTasks) ⇒ <code>void</code>
* [.postCreateTasks_legacyApi(metadataEntry, apiResponse)](#MetadataType.postCreateTasks_legacyApi) ⇒ <code>Promise.&lt;void&gt;</code>
* [.postRetrieveTasks(metadata, targetDir, [isTemplating])](#MetadataType.postRetrieveTasks) ⇒ <code>TYPE.MetadataTypeItem</code>
* [.setFolderPath(metadata)](#MetadataType.setFolderPath)
* [.setFolderId(metadata)](#MetadataType.setFolderId)
* [.retrieve(retrieveDir, [additionalFields], [subTypeArr], [key])](#MetadataType.retrieve) ⇒ <code>Promise.&lt;TYPE.MetadataTypeMapObj&gt;</code>
* [.retrieveChangelog([additionalFields], [subTypeArr])](#MetadataType.retrieveChangelog) ⇒ <code>Promise.&lt;TYPE.MetadataTypeMapObj&gt;</code>
* [.retrieveForCache([additionalFields], [subTypeArr])](#MetadataType.retrieveForCache) ⇒ <code>Promise.&lt;TYPE.MetadataTypeMapObj&gt;</code>
* [.retrieveForCache([additionalFields], [subTypeArr], [key])](#MetadataType.retrieveForCache) ⇒ <code>Promise.&lt;TYPE.MetadataTypeMapObj&gt;</code>
* [.retrieveAsTemplate(templateDir, name, templateVariables, [subType])](#MetadataType.retrieveAsTemplate) ⇒ <code>Promise.&lt;TYPE.MetadataTypeItemObj&gt;</code>
* [.buildTemplate(retrieveDir, templateDir, key, templateVariables)](#MetadataType.buildTemplate) ⇒ <code>Promise.&lt;TYPE.MetadataTypeItemObj&gt;</code>
* [.preDeployTasks(metadata, deployDir)](#MetadataType.preDeployTasks) ⇒ <code>Promise.&lt;TYPE.MetadataTypeItem&gt;</code>
Expand Down Expand Up @@ -3287,6 +3288,19 @@ helper for [createREST](createREST)
| metadataEntry | <code>TYPE.MetadataTypeItem</code> | a single metadata Entry |
| apiResponse | <code>object</code> | varies depending on the API call |

<a name="MetadataType.postCreateTasks_legacyApi"></a>

### MetadataType.postCreateTasks\_legacyApi(metadataEntry, apiResponse) ⇒ <code>Promise.&lt;void&gt;</code>
helper for [createREST](createREST) when legacy API endpoints as these do not return the created item but only their new id

**Kind**: static method of [<code>MetadataType</code>](#MetadataType)
**Returns**: <code>Promise.&lt;void&gt;</code> - -

| Param | Type | Description |
| --- | --- | --- |
| metadataEntry | <code>TYPE.MetadataTypeItem</code> | a single metadata Entry |
| apiResponse | <code>object</code> | varies depending on the API call |

<a name="MetadataType.postRetrieveTasks"></a>

### MetadataType.postRetrieveTasks(metadata, targetDir, [isTemplating]) ⇒ <code>TYPE.MetadataTypeItem</code>
Expand Down Expand Up @@ -3353,7 +3367,7 @@ Gets metadata from Marketing Cloud

<a name="MetadataType.retrieveForCache"></a>

### MetadataType.retrieveForCache([additionalFields], [subTypeArr]) ⇒ <code>Promise.&lt;TYPE.MetadataTypeMapObj&gt;</code>
### MetadataType.retrieveForCache([additionalFields], [subTypeArr], [key]) ⇒ <code>Promise.&lt;TYPE.MetadataTypeMapObj&gt;</code>
Gets metadata cache with limited fields and does not store value to disk

**Kind**: static method of [<code>MetadataType</code>](#MetadataType)
Expand All @@ -3363,6 +3377,7 @@ Gets metadata cache with limited fields and does not store value to disk
| --- | --- | --- |
| [additionalFields] | <code>Array.&lt;string&gt;</code> | Returns specified fields even if their retrieve definition is not set to true |
| [subTypeArr] | <code>Array.&lt;string&gt;</code> | optionally limit to a single subtype |
| [key] | <code>string</code> | customer key of single item to retrieve |

<a name="MetadataType.retrieveAsTemplate"></a>

Expand Down Expand Up @@ -4053,7 +4068,7 @@ MobileMessage MetadataType

* [MobileMessage](#MobileMessage)[<code>MetadataType</code>](#MetadataType)
* [.retrieve(retrieveDir, [_], [__], [key])](#MobileMessage.retrieve) ⇒ <code>Promise.&lt;TYPE.MetadataTypeMapObj&gt;</code> \| <code>void</code>
* [.retrieveForCache()](#MobileMessage.retrieveForCache) ⇒ <code>Promise.&lt;TYPE.MetadataTypeMapObj&gt;</code>
* [.retrieveForCache(_, __, [key])](#MobileMessage.retrieveForCache) ⇒ <code>Promise.&lt;TYPE.MetadataTypeMapObj&gt;</code>
* [.upgradeGetBulk()](#MobileMessage.upgradeGetBulk)
* [.getBulkForLegacyApi(url, [pageSize], [iteratorField])](#MobileMessage.getBulkForLegacyApi) ⇒ <code>Promise.&lt;object&gt;</code>
* [.update(metadata)](#MobileMessage.update) ⇒ <code>Promise</code>
Expand All @@ -4067,7 +4082,7 @@ MobileMessage MetadataType
* [.buildDefinitionForNested(templateDir, targetDir, metadata, templateVariables, templateName)](#MobileMessage.buildDefinitionForNested) ⇒ <code>Promise.&lt;Array.&lt;Array.&lt;string&gt;&gt;&gt;</code>
* [.buildTemplateForNested(templateDir, targetDir, metadata, templateVariables, templateName)](#MobileMessage.buildTemplateForNested) ⇒ <code>Promise.&lt;Array.&lt;Array.&lt;string&gt;&gt;&gt;</code>
* [._buildForNested(templateDir, targetDir, metadata, templateVariables, templateName, mode)](#MobileMessage._buildForNested) ⇒ <code>Promise.&lt;Array.&lt;Array.&lt;string&gt;&gt;&gt;</code>
* [.deleteByKey(key)](#MobileMessage.deleteByKey) ⇒ <code>Promise.&lt;boolean&gt;</code>
* [.deleteByKey(id)](#MobileMessage.deleteByKey) ⇒ <code>Promise.&lt;boolean&gt;</code>

<a name="MobileMessage.retrieve"></a>

Expand All @@ -4086,11 +4101,18 @@ Retrieves Metadata of Mobile Keywords

<a name="MobileMessage.retrieveForCache"></a>

### MobileMessage.retrieveForCache() ⇒ <code>Promise.&lt;TYPE.MetadataTypeMapObj&gt;</code>
### MobileMessage.retrieveForCache(_, __, [key]) ⇒ <code>Promise.&lt;TYPE.MetadataTypeMapObj&gt;</code>
Retrieves event definition metadata for caching

**Kind**: static method of [<code>MobileMessage</code>](#MobileMessage)
**Returns**: <code>Promise.&lt;TYPE.MetadataTypeMapObj&gt;</code> - Promise of metadata

| Param | Type | Description |
| --- | --- | --- |
| _ | <code>void</code> | parameter not used |
| __ | <code>void</code> | parameter not used |
| [key] | <code>string</code> | customer key of single item to retrieve |

<a name="MobileMessage.upgradeGetBulk"></a>

### MobileMessage.upgradeGetBulk()
Expand Down Expand Up @@ -4270,15 +4292,16 @@ handles extracted code if any are found for complex types

<a name="MobileMessage.deleteByKey"></a>

### MobileMessage.deleteByKey(key) ⇒ <code>Promise.&lt;boolean&gt;</code>
### MobileMessage.deleteByKey(id) ⇒ <code>Promise.&lt;boolean&gt;</code>
Delete a metadata item from the specified business unit
! the endpoint expects the ID and not a key but for mcdev in this case key==id

**Kind**: static method of [<code>MobileMessage</code>](#MobileMessage)
**Returns**: <code>Promise.&lt;boolean&gt;</code> - deletion success status

| Param | Type | Description |
| --- | --- | --- |
| key | <code>string</code> | Identifier of item |
| id | <code>string</code> | Identifier of item |

<a name="Query"></a>

Expand Down
38 changes: 36 additions & 2 deletions lib/metadataTypes/MetadataType.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,39 @@ class MetadataType {
*/
static postCreateTasks(metadataEntry, apiResponse) {}

/**
* helper for {@link createREST} when legacy API endpoints as these do not return the created item but only their new id
*
* @param {TYPE.MetadataTypeItem} metadataEntry a single metadata Entry
* @param {object} apiResponse varies depending on the API call
* @returns {Promise.<void>} -
*/
static async postCreateTasks_legacyApi(metadataEntry, apiResponse) {
if (!apiResponse?.[this.definition.idField]) {
return;
}
// re-retrieve created items because the API does not return any info for them except the new id (api key)
try {
const { metadata } = await this.retrieveForCache(
null,
null,
'id:' + apiResponse[this.definition.idField]
);
const item = Object.values(metadata)[0];
// ensure the "created item" cli log entry has the new auto-generated value
metadataEntry[this.definition.keyField] = item[this.definition.keyField];
// ensure postRetrieveTasks has the complete object in "apiResponse"
Object.assign(apiResponse, item);
// postRetrieveTasks will be run automatically on this via super.saveResult
} catch (ex) {
throw new Error(
`Could not get details for new ${this.definition.type} ${
apiResponse[this.definition.idField]
} from server (${ex.message})`
);
}
}

/**
* Gets executed after retreive of metadata type
*
Expand Down Expand Up @@ -235,10 +268,11 @@ class MetadataType {
*
* @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true
* @param {string[]} [subTypeArr] optionally limit to a single subtype
* @param {string} [key] customer key of single item to retrieve
* @returns {Promise.<TYPE.MetadataTypeMapObj>} metadata
*/
static async retrieveForCache(additionalFields, subTypeArr) {
return this.retrieve(null, additionalFields, subTypeArr);
static async retrieveForCache(additionalFields, subTypeArr, key) {
return this.retrieve(null, additionalFields, subTypeArr, key);
}
/**
* Gets metadata cache with limited fields and does not store value to disk
Expand Down
40 changes: 15 additions & 25 deletions lib/metadataTypes/MobileMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ class MobileMessage extends MetadataType {
*/
static retrieve(retrieveDir, _, __, key) {
this.upgradeGetBulk();
if (key && key.startsWith('id:')) {
// if key starts with id: remove it to be compatible with other legacy API types (MetadataType.postCreateTasks_legacyApi)
key = key.slice(3);
}
try {
return super.retrieveREST(
retrieveDir,
Expand All @@ -47,15 +51,13 @@ class MobileMessage extends MetadataType {
/**
* Retrieves event definition metadata for caching
*
* @param {void} _ parameter not used
* @param {void} __ parameter not used
* @param {string} [key] customer key of single item to retrieve
* @returns {Promise.<TYPE.MetadataTypeMapObj>} Promise of metadata
*/
static retrieveForCache() {
this.upgradeGetBulk();
return super.retrieveREST(
null,
'/legacy/v1/beta/mobile/message/' +
'?view=details&version=3&$sort=lastUpdated%20DESC&$where=isTest%20eq%200%20and%20status%20neq%20%27Archive%27'
);
static retrieveForCache(_, __, key) {
return this.retrieve(null, null, null, key);
}

/**
Expand Down Expand Up @@ -151,7 +153,7 @@ class MobileMessage extends MetadataType {
static update(metadata) {
return super.updateREST(
metadata,
'/legacy/v1/beta/mobile/message/' + metadata[this.definition.keyField],
'/legacy/v1/beta/mobile/message/' + metadata[this.definition.idField],
'post' // upsert API, post for insert and update!
);
}
Expand Down Expand Up @@ -404,20 +406,7 @@ class MobileMessage extends MetadataType {
* @returns {void}
*/
static async postCreateTasks(metadataEntry, apiResponse) {
if (!apiResponse?.id) {
return;
}
// re-retrieve created items because the API does not return any info for them except the new id (api key)
try {
const result = await this.retrieve(null, null, null, apiResponse.id);
metadataEntry[this.definition.keyField] = apiResponse.id;
Object.assign(apiResponse, result.metadata[apiResponse.id]);
// postRetrieveTasks will be run automatically on this via super.saveResult
} catch (ex) {
throw new Error(
`Could not get details for new ${this.definition.type} ${apiResponse.id} from server (${ex.message})`
);
}
await super.postCreateTasks_legacyApi(metadataEntry, apiResponse);
}
/**
* helper for {@link MetadataType.buildDefinition}
Expand Down Expand Up @@ -542,15 +531,16 @@ class MobileMessage extends MetadataType {
}
/**
* Delete a metadata item from the specified business unit
* ! the endpoint expects the ID and not a key but for mcdev in this case key==id
*
* @param {string} key Identifier of item
* @param {string} id Identifier of item
* @returns {Promise.<boolean>} deletion success status
*/
static deleteByKey(key) {
static deleteByKey(id) {
Util.logger.info(
' - Note: As long as the provided API key once existed, you will not see an error even if the mobileMessage is already deleted.'
);
return super.deleteByKeyREST('/legacy/v1/beta/mobile/message/' + key, key, false);
return super.deleteByKeyREST('/legacy/v1/beta/mobile/message/' + id, id, false);
}
}

Expand Down

0 comments on commit fe779d8

Please sign in to comment.