mcdev 7.5.0 → 7.6.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/.github/ISSUE_TEMPLATE/bug.yml +1 -0
- package/@types/lib/index.d.ts +12 -8
- package/@types/lib/index.d.ts.map +1 -1
- package/@types/lib/metadataTypes/AttributeSet.d.ts.map +1 -1
- package/@types/lib/metadataTypes/DataExtension.d.ts +3 -1
- package/@types/lib/metadataTypes/DataExtension.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Event.d.ts +2 -2
- package/@types/lib/metadataTypes/Event.d.ts.map +1 -1
- package/@types/lib/metadataTypes/Journey.d.ts +16 -0
- package/@types/lib/metadataTypes/Journey.d.ts.map +1 -1
- package/@types/lib/metadataTypes/MetadataType.d.ts +4 -2
- package/@types/lib/metadataTypes/MetadataType.d.ts.map +1 -1
- package/@types/lib/metadataTypes/TransactionalEmail.d.ts +1 -0
- package/@types/lib/metadataTypes/TransactionalEmail.d.ts.map +1 -1
- package/@types/lib/metadataTypes/TriggeredSend.d.ts +0 -8
- package/@types/lib/metadataTypes/TriggeredSend.d.ts.map +1 -1
- package/@types/lib/metadataTypes/definitions/Journey.definition.d.ts +1 -0
- package/@types/lib/metadataTypes/definitions/TransactionalEmail.definition.d.ts +1 -0
- package/@types/lib/util/replaceContentBlockReference.d.ts.map +1 -1
- package/@types/lib/util/util.d.ts.map +1 -1
- package/@types/types/mcdev.d.d.ts +15 -7
- package/@types/types/mcdev.d.d.ts.map +1 -1
- package/lib/cli.js +13 -2
- package/lib/index.js +46 -42
- package/lib/metadataTypes/Event.js +4 -1
- package/lib/metadataTypes/Journey.js +456 -90
- package/lib/metadataTypes/MetadataType.js +8 -4
- package/lib/metadataTypes/TriggeredSend.js +21 -12
- package/lib/metadataTypes/definitions/Journey.definition.js +1 -0
- package/lib/metadataTypes/definitions/TransactionalEmail.definition.js +1 -0
- package/package.json +15 -15
- package/test/mockRoot/.mcdevrc.json +1 -1
- package/test/resources/9999999/interaction/v1/interactions/dsfdsafdsa-922c-4568-85a5-e5cc77efc3be/delete-response.txt +1 -0
- package/test/type.journey.test.js +6 -5
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import MetadataType from './MetadataType.js';
|
|
4
4
|
import TransactionalEmail from './TransactionalEmail.js';
|
|
5
|
+
import TriggeredSend from './TriggeredSend.js';
|
|
5
6
|
import Event from './Event.js';
|
|
6
7
|
import { Util } from '../util/util.js';
|
|
7
8
|
import cache from '../util/cache.js';
|
|
@@ -187,7 +188,8 @@ class Journey extends MetadataType {
|
|
|
187
188
|
[
|
|
188
189
|
'Interaction matching key not found.',
|
|
189
190
|
'Must provide a valid ID or Key parameter',
|
|
190
|
-
].includes(ex.message)
|
|
191
|
+
].includes(ex.message) ||
|
|
192
|
+
(key && ex.code === 'ERR_BAD_REQUEST')
|
|
191
193
|
) {
|
|
192
194
|
Util.logger.info(
|
|
193
195
|
`Downloaded: ${this.definition.type} (0)${Util.getKeysString(
|
|
@@ -209,22 +211,32 @@ class Journey extends MetadataType {
|
|
|
209
211
|
*/
|
|
210
212
|
static async deleteByKey(key) {
|
|
211
213
|
let version;
|
|
212
|
-
let
|
|
214
|
+
let id;
|
|
215
|
+
let cachedJourney;
|
|
213
216
|
|
|
214
217
|
if (key.startsWith('id:') || key.startsWith('%23')) {
|
|
215
218
|
// ! allow selecting journeys by ID because that's what users see in the URL
|
|
216
219
|
// if the key started with %23 assume an ID was copied from the URL but the user forgot to prefix it with id:
|
|
217
220
|
|
|
218
221
|
// remove id: or %23
|
|
219
|
-
|
|
220
|
-
if (
|
|
222
|
+
id = key.slice(3);
|
|
223
|
+
if (id.startsWith('%23')) {
|
|
221
224
|
// in the journey URL the Id is prefixed with an HTML-encoded "#" which could accidentally be copied by users
|
|
222
225
|
// despite the slicing above, this still needs testing here because users might have prefixed the ID with id: but did not know to remove the #23
|
|
223
|
-
|
|
226
|
+
id = id.slice(3);
|
|
224
227
|
}
|
|
225
|
-
if (
|
|
228
|
+
if (id.includes('/')) {
|
|
226
229
|
// in the journey URL the version is appended after the ID, separated by a forward-slash.
|
|
227
|
-
[
|
|
230
|
+
[id, version] = id.split('/');
|
|
231
|
+
}
|
|
232
|
+
try {
|
|
233
|
+
const response = await this.client.rest.get(
|
|
234
|
+
`/interaction/v1/interactions/${encodeURIComponent(id)}?extras=activities`
|
|
235
|
+
);
|
|
236
|
+
const results = this.parseResponseBody(response, key);
|
|
237
|
+
cachedJourney = results[key];
|
|
238
|
+
} catch {
|
|
239
|
+
// handle below
|
|
228
240
|
}
|
|
229
241
|
} else {
|
|
230
242
|
if (key.includes('/')) {
|
|
@@ -233,40 +245,75 @@ class Journey extends MetadataType {
|
|
|
233
245
|
}
|
|
234
246
|
|
|
235
247
|
// delete by key with specified version does not work, therefore we need to get the ID first
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const results = this.parseResponseBody(response, key);
|
|
240
|
-
singleKey = results[key].id;
|
|
241
|
-
if (version && version !== '*' && version > results[key].version) {
|
|
242
|
-
Util.logger.error(
|
|
243
|
-
`The chosen version (${version}) is higher than the latest known version (${results[key].version}). Please choose a lower version.`
|
|
248
|
+
try {
|
|
249
|
+
const response = await this.client.rest.get(
|
|
250
|
+
`/interaction/v1/interactions/key:${encodeURIComponent(key)}?extras=activities`
|
|
244
251
|
);
|
|
245
|
-
|
|
252
|
+
const results = this.parseResponseBody(response, key);
|
|
253
|
+
cachedJourney = results[key];
|
|
254
|
+
id = cachedJourney?.id;
|
|
255
|
+
} catch {
|
|
256
|
+
// handle below
|
|
246
257
|
}
|
|
247
|
-
Util.logger.debug(`Deleting interaction ${key} via its ID ${singleKey}`);
|
|
248
258
|
}
|
|
249
|
-
if (
|
|
250
|
-
if (!/^\d+$/.test(version)) {
|
|
251
|
-
Util.logger.error(
|
|
252
|
-
'Version is required for deleting interactions to avoid accidental deletion of the wrong item. Please append it at the end of the key or id, separated by forward-slash. Example for deleting version 4: ' +
|
|
253
|
-
key +
|
|
254
|
-
'/4'
|
|
255
|
-
);
|
|
256
|
-
return false;
|
|
257
|
-
}
|
|
259
|
+
if (!cachedJourney?.key) {
|
|
258
260
|
Util.logger.warn(
|
|
259
|
-
`
|
|
261
|
+
` ☇ skipping deletion of ${this.definition.type} ${key}: not found on server`
|
|
260
262
|
);
|
|
263
|
+
return false;
|
|
261
264
|
}
|
|
265
|
+
switch (cachedJourney.definitionType) {
|
|
266
|
+
case 'Multistep': {
|
|
267
|
+
if (version && version !== '*' && version > cachedJourney.version) {
|
|
268
|
+
Util.logger.error(
|
|
269
|
+
`The chosen version (${version}) is higher than the latest known version (${cachedJourney.version}). Please choose a lower version.`
|
|
270
|
+
);
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
if (version !== '*') {
|
|
274
|
+
if (!/^\d+$/.test(version)) {
|
|
275
|
+
Util.logger.error(
|
|
276
|
+
'Version is required for deleting interactions to avoid accidental deletion of the wrong item. Please append it at the end of the key or id, separated by forward-slash. Example for deleting version 4: ' +
|
|
277
|
+
key +
|
|
278
|
+
'/4'
|
|
279
|
+
);
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
Util.logger.warn(
|
|
283
|
+
`Deleting Journeys via this command breaks following retrieve-by-key/id requests until you've deployed/created a new draft version! You can get still get the latest available version of your journey by retrieving all interactions on this BU.`
|
|
284
|
+
);
|
|
285
|
+
}
|
|
262
286
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
287
|
+
return super.deleteByKeyREST(
|
|
288
|
+
'/interaction/v1/interactions/' +
|
|
289
|
+
id +
|
|
290
|
+
(version === '*' ? '' : `?versionNumber=${version}`),
|
|
291
|
+
key,
|
|
292
|
+
false
|
|
293
|
+
);
|
|
294
|
+
// break;
|
|
295
|
+
}
|
|
296
|
+
default: {
|
|
297
|
+
// Quicksend, Transactional dont have versions
|
|
298
|
+
const response = await super.deleteByKeyREST(
|
|
299
|
+
'/interaction/v1/interactions/' + id,
|
|
300
|
+
key,
|
|
301
|
+
false
|
|
302
|
+
);
|
|
303
|
+
if (response && cachedJourney.definitionType === 'Transactional') {
|
|
304
|
+
const msg = [];
|
|
305
|
+
if (cachedJourney.activities[0]?.configurationArguments?.triggeredSendKey) {
|
|
306
|
+
msg.push(
|
|
307
|
+
`transactionalEmail "${cachedJourney.activities[0].configurationArguments.triggeredSendKey}"`
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
if (msg.length) {
|
|
311
|
+
Util.logger.info(` - Remember to also delete linked ${msg.join(' and ')}`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return response;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
270
317
|
}
|
|
271
318
|
|
|
272
319
|
/**
|
|
@@ -1607,7 +1654,11 @@ class Journey extends MetadataType {
|
|
|
1607
1654
|
);
|
|
1608
1655
|
const cachedVersion = cache.getByKey(this.definition.type, normalizedKey);
|
|
1609
1656
|
if (cachedVersion) {
|
|
1610
|
-
if (
|
|
1657
|
+
if (
|
|
1658
|
+
cachedVersion.status === 'Draft' ||
|
|
1659
|
+
cachedVersion.definitionType !== 'Multistep'
|
|
1660
|
+
) {
|
|
1661
|
+
// we can update journeys either if there is a draft version or if the type is not multistep. transactional and quicksend journeys do not have versions.
|
|
1611
1662
|
// add version to ensure we update the correct one
|
|
1612
1663
|
metadataMap[metadataKey].version = cachedVersion.version;
|
|
1613
1664
|
// update modifiedDate field to bypass API-error "Another user recently modified this journey. Refresh to edit the latest version."
|
|
@@ -2335,41 +2386,115 @@ class Journey extends MetadataType {
|
|
|
2335
2386
|
let version;
|
|
2336
2387
|
const endpoint = '/interaction/v1/interactions/stop/';
|
|
2337
2388
|
const stoppedKeyArr = [];
|
|
2389
|
+
const pauseTransactionalKeyArr = [];
|
|
2338
2390
|
const apiLimit = pLimit(20);
|
|
2339
2391
|
const journeyCache = await this.retrieveForCache();
|
|
2340
2392
|
|
|
2393
|
+
const stoppableJourneyStatus = ['Paused', 'Published', 'Finishing'];
|
|
2394
|
+
|
|
2341
2395
|
await Promise.allSettled(
|
|
2342
2396
|
keyArr.map((key) =>
|
|
2343
2397
|
apiLimit(async () => {
|
|
2344
2398
|
[key, version] = key.split('/');
|
|
2345
2399
|
if (journeyCache.metadata[key]) {
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2400
|
+
switch (journeyCache.metadata[key].definitionType) {
|
|
2401
|
+
case 'Transactional': {
|
|
2402
|
+
// transactional send journeys cannot be "stopped" but only "paused"
|
|
2403
|
+
pauseTransactionalKeyArr.push(key);
|
|
2404
|
+
break;
|
|
2405
|
+
}
|
|
2406
|
+
case 'Multistep': {
|
|
2407
|
+
const toBeStoppedVersions = [];
|
|
2408
|
+
if (version === '*') {
|
|
2409
|
+
const responseAllVersions = await this.client.rest.getBulk(
|
|
2410
|
+
'/interaction/v1/interactions/?id=' +
|
|
2411
|
+
journeyCache.metadata[key].id +
|
|
2412
|
+
'&mostRecentVersionOnly=false',
|
|
2413
|
+
this.definition.restPageSize || 500
|
|
2414
|
+
);
|
|
2415
|
+
if (responseAllVersions?.items?.length) {
|
|
2416
|
+
// find all active versions
|
|
2417
|
+
const allActiveVersions = responseAllVersions.items
|
|
2418
|
+
.filter((item) =>
|
|
2419
|
+
stoppableJourneyStatus.includes(item.status)
|
|
2420
|
+
)
|
|
2421
|
+
.map((item) => item.version);
|
|
2422
|
+
if (allActiveVersions.length) {
|
|
2423
|
+
toBeStoppedVersions.push(...allActiveVersions);
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
if (!toBeStoppedVersions.length) {
|
|
2427
|
+
Util.logger.warn(
|
|
2428
|
+
` ☇ skipping stop of ${this.definition.type} ${key}: no active versions found`
|
|
2429
|
+
);
|
|
2430
|
+
}
|
|
2431
|
+
} else {
|
|
2432
|
+
if (!version) {
|
|
2433
|
+
version = journeyCache.metadata[key].version;
|
|
2434
|
+
Util.logger.info(
|
|
2435
|
+
Util.getGrayMsg(
|
|
2436
|
+
` - ${this.definition.type} ${key}: no version provided. Will try to stop latest version: Version ${version}. To stop all versions, append /* after the key.`
|
|
2437
|
+
)
|
|
2438
|
+
);
|
|
2439
|
+
if (
|
|
2440
|
+
!stoppableJourneyStatus.includes(
|
|
2441
|
+
journeyCache.metadata[key].status
|
|
2442
|
+
)
|
|
2443
|
+
) {
|
|
2444
|
+
Util.logger.warn(
|
|
2445
|
+
` ☇ skipping stop of ${this.definition.type} ${key}: version ${version} has status "${journeyCache.metadata[key].status}" which cannot be stopped. To stop all versions, append /* after the key.`
|
|
2446
|
+
);
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
toBeStoppedVersions.push(version);
|
|
2450
|
+
}
|
|
2451
|
+
const rateLimitActivities = pLimit(2);
|
|
2452
|
+
const stoppedVersions = (
|
|
2453
|
+
await Promise.all(
|
|
2454
|
+
toBeStoppedVersions.map((version) =>
|
|
2455
|
+
rateLimitActivities(async () => {
|
|
2456
|
+
try {
|
|
2457
|
+
await this.client.rest.post(
|
|
2458
|
+
endpoint +
|
|
2459
|
+
journeyCache.metadata[key].id +
|
|
2460
|
+
`?versionNumber=${version}`,
|
|
2461
|
+
{}
|
|
2462
|
+
);
|
|
2463
|
+
Util.logger.info(
|
|
2464
|
+
` - Stopped ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} - Version ${version}`
|
|
2465
|
+
);
|
|
2466
|
+
return version;
|
|
2467
|
+
} catch (ex) {
|
|
2468
|
+
Util.logger.error(
|
|
2469
|
+
` - Stopping ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} - Version ${version} failed: ${ex.message}`
|
|
2470
|
+
);
|
|
2471
|
+
return;
|
|
2472
|
+
}
|
|
2473
|
+
})
|
|
2474
|
+
)
|
|
2475
|
+
)
|
|
2476
|
+
).filter(Boolean);
|
|
2477
|
+
if (stoppedVersions.length === toBeStoppedVersions.length) {
|
|
2478
|
+
stoppedKeyArr.push(key);
|
|
2479
|
+
}
|
|
2480
|
+
|
|
2481
|
+
break;
|
|
2482
|
+
}
|
|
2483
|
+
default: {
|
|
2484
|
+
Util.logger.error(
|
|
2485
|
+
` - Stopping ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: Unsupported definitionType '${journeyCache.metadata[key].definitionType}'`
|
|
2486
|
+
);
|
|
2487
|
+
}
|
|
2368
2488
|
}
|
|
2489
|
+
} else {
|
|
2490
|
+
Util.logger.error(
|
|
2491
|
+
` ☇ skipping stop of ${this.definition.type} ${key}: not found on server`
|
|
2492
|
+
);
|
|
2369
2493
|
}
|
|
2370
2494
|
})
|
|
2371
2495
|
)
|
|
2372
2496
|
);
|
|
2497
|
+
stoppedKeyArr.push(...(await this.pause(pauseTransactionalKeyArr)));
|
|
2373
2498
|
|
|
2374
2499
|
return stoppedKeyArr;
|
|
2375
2500
|
}
|
|
@@ -2381,8 +2506,7 @@ class Journey extends MetadataType {
|
|
|
2381
2506
|
*/
|
|
2382
2507
|
static async pause(keyArr) {
|
|
2383
2508
|
let version;
|
|
2384
|
-
const
|
|
2385
|
-
const stoppedKeyArr = [];
|
|
2509
|
+
const pausedKeyArr = [];
|
|
2386
2510
|
const apiLimit = pLimit(20);
|
|
2387
2511
|
const journeyCache = await this.retrieveForCache();
|
|
2388
2512
|
|
|
@@ -2391,35 +2515,78 @@ class Journey extends MetadataType {
|
|
|
2391
2515
|
apiLimit(async () => {
|
|
2392
2516
|
[key, version] = key.split('/');
|
|
2393
2517
|
if (journeyCache.metadata[key]) {
|
|
2394
|
-
|
|
2395
|
-
try {
|
|
2396
|
-
await this.client.rest.post(
|
|
2397
|
-
endpoint +
|
|
2398
|
-
journeyCache.metadata[key].id +
|
|
2399
|
-
(version === '*'
|
|
2400
|
-
? '?allVersions=true'
|
|
2401
|
-
: `?versionNumber=${version}`),
|
|
2402
|
-
{}
|
|
2403
|
-
);
|
|
2404
|
-
Util.logger.info(` - Paused ${this.definition.type} ${key}/${version}`);
|
|
2405
|
-
stoppedKeyArr.push(key);
|
|
2406
|
-
} catch (ex) {
|
|
2518
|
+
if (journeyCache.metadata[key].status !== 'Published') {
|
|
2407
2519
|
Util.logger.error(
|
|
2408
|
-
` - Pausing ${this.definition.type} ${key} failed: ${
|
|
2520
|
+
` - Pausing ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: Cannot pause a journey in status ${journeyCache.metadata[key].status}`
|
|
2409
2521
|
);
|
|
2522
|
+
return;
|
|
2410
2523
|
}
|
|
2524
|
+
switch (journeyCache.metadata[key].definitionType) {
|
|
2525
|
+
case 'Transactional': {
|
|
2526
|
+
try {
|
|
2527
|
+
const response = await this.client.rest.post(
|
|
2528
|
+
'/interaction/v1/interactions/transactional/pause',
|
|
2529
|
+
{ definitionId: journeyCache.metadata[key].id }
|
|
2530
|
+
);
|
|
2531
|
+
if (response.errors?.length) {
|
|
2532
|
+
throw new Error(JSON.stringify(response));
|
|
2533
|
+
} else {
|
|
2534
|
+
Util.logger.info(
|
|
2535
|
+
` - 🛑 paused ${this.definition.type} ${key} / ${journeyCache.metadata[key].name}`
|
|
2536
|
+
);
|
|
2537
|
+
pausedKeyArr.push(key);
|
|
2538
|
+
}
|
|
2539
|
+
} catch (ex) {
|
|
2540
|
+
Util.logger.error(
|
|
2541
|
+
` - Pausing ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: ${ex.message}`
|
|
2542
|
+
);
|
|
2543
|
+
}
|
|
2544
|
+
break;
|
|
2545
|
+
}
|
|
2546
|
+
case 'Multistep': {
|
|
2547
|
+
version ||= journeyCache.metadata[key].version;
|
|
2548
|
+
try {
|
|
2549
|
+
await this.client.rest.post(
|
|
2550
|
+
'/interaction/v1/interactions/pause/' +
|
|
2551
|
+
journeyCache.metadata[key].id +
|
|
2552
|
+
(version === '*'
|
|
2553
|
+
? '?allVersions=true'
|
|
2554
|
+
: `?versionNumber=${version}`),
|
|
2555
|
+
{}
|
|
2556
|
+
);
|
|
2557
|
+
Util.logger.info(
|
|
2558
|
+
` -- 🛑 paused ${this.definition.type} ${key}/${version} / ${journeyCache.metadata[key].name}`
|
|
2559
|
+
);
|
|
2560
|
+
pausedKeyArr.push(key);
|
|
2561
|
+
} catch (ex) {
|
|
2562
|
+
Util.logger.error(
|
|
2563
|
+
` - Pausing ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: ${ex.message}`
|
|
2564
|
+
);
|
|
2565
|
+
}
|
|
2566
|
+
break;
|
|
2567
|
+
}
|
|
2568
|
+
default: {
|
|
2569
|
+
Util.logger.error(
|
|
2570
|
+
` - Pausing ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: Unsupported definitionType '${journeyCache.metadata[key].definitionType}'`
|
|
2571
|
+
);
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
} else {
|
|
2575
|
+
Util.logger.error(
|
|
2576
|
+
` ☇ skipping pause of ${this.definition.type} ${key}: not found on server`
|
|
2577
|
+
);
|
|
2411
2578
|
}
|
|
2412
2579
|
})
|
|
2413
2580
|
)
|
|
2414
2581
|
);
|
|
2415
2582
|
|
|
2416
|
-
return
|
|
2583
|
+
return pausedKeyArr;
|
|
2417
2584
|
}
|
|
2418
2585
|
/**
|
|
2419
2586
|
* resumes selected journey versions
|
|
2420
2587
|
*
|
|
2421
2588
|
* @param {string[]} keyArr customerkey of the metadata
|
|
2422
|
-
* @returns {Promise.<string[]>} Returns list of keys that were
|
|
2589
|
+
* @returns {Promise.<string[]>} Returns list of keys that were resumed
|
|
2423
2590
|
*/
|
|
2424
2591
|
static async execute(keyArr) {
|
|
2425
2592
|
let version;
|
|
@@ -2433,23 +2600,188 @@ class Journey extends MetadataType {
|
|
|
2433
2600
|
apiLimit(async () => {
|
|
2434
2601
|
[key, version] = key.split('/');
|
|
2435
2602
|
if (journeyCache.metadata[key]) {
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
endpoint +
|
|
2440
|
-
journeyCache.metadata[key].id +
|
|
2441
|
-
(version === '*'
|
|
2442
|
-
? '?allVersions=true'
|
|
2443
|
-
: `?versionNumber=${version}`),
|
|
2444
|
-
{}
|
|
2603
|
+
if (journeyCache.metadata[key].status !== 'Paused') {
|
|
2604
|
+
Util.logger.error(
|
|
2605
|
+
` - Resuming ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: Cannot pause a journey in status ${journeyCache.metadata[key].status}`
|
|
2445
2606
|
);
|
|
2446
|
-
|
|
2447
|
-
|
|
2607
|
+
return;
|
|
2608
|
+
}
|
|
2609
|
+
switch (journeyCache.metadata[key].definitionType) {
|
|
2610
|
+
case 'Transactional': {
|
|
2611
|
+
try {
|
|
2612
|
+
const response = await this.client.rest.post(
|
|
2613
|
+
'/interaction/v1/interactions/transactional/resume',
|
|
2614
|
+
{ definitionId: journeyCache.metadata[key].id }
|
|
2615
|
+
);
|
|
2616
|
+
if (response.errors?.length) {
|
|
2617
|
+
throw new Error(JSON.stringify(response));
|
|
2618
|
+
} else {
|
|
2619
|
+
Util.logger.info(
|
|
2620
|
+
` - ✅ resumed ${this.definition.type} ${key} / ${journeyCache.metadata[key].name}`
|
|
2621
|
+
);
|
|
2622
|
+
resumedKeyArr.push(key);
|
|
2623
|
+
}
|
|
2624
|
+
} catch (ex) {
|
|
2625
|
+
Util.logger.error(
|
|
2626
|
+
` - Resuming ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: ${ex.message}`
|
|
2627
|
+
);
|
|
2628
|
+
}
|
|
2629
|
+
break;
|
|
2630
|
+
}
|
|
2631
|
+
case 'Multistep': {
|
|
2632
|
+
version ||= journeyCache.metadata[key].version;
|
|
2633
|
+
try {
|
|
2634
|
+
await this.client.rest.post(
|
|
2635
|
+
endpoint +
|
|
2636
|
+
journeyCache.metadata[key].id +
|
|
2637
|
+
(version === '*'
|
|
2638
|
+
? '?allVersions=true'
|
|
2639
|
+
: `?versionNumber=${version}`),
|
|
2640
|
+
{}
|
|
2641
|
+
);
|
|
2642
|
+
Util.logger.info(
|
|
2643
|
+
` - ✅ resumed ${this.definition.type} ${key}/${version}`
|
|
2644
|
+
);
|
|
2645
|
+
resumedKeyArr.push(key);
|
|
2646
|
+
} catch (ex) {
|
|
2647
|
+
Util.logger.error(
|
|
2648
|
+
` - Resuming ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: ${ex.message}`
|
|
2649
|
+
);
|
|
2650
|
+
}
|
|
2651
|
+
break;
|
|
2652
|
+
}
|
|
2653
|
+
default: {
|
|
2654
|
+
Util.logger.error(
|
|
2655
|
+
` - Resuming ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: Unsupported definitionType '${journeyCache.metadata[key].definitionType}'`
|
|
2656
|
+
);
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
} else {
|
|
2660
|
+
Util.logger.error(
|
|
2661
|
+
` ☇ skipping resume of ${this.definition.type} ${key}: not found on server`
|
|
2662
|
+
);
|
|
2663
|
+
}
|
|
2664
|
+
})
|
|
2665
|
+
)
|
|
2666
|
+
);
|
|
2667
|
+
|
|
2668
|
+
return resumedKeyArr;
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2671
|
+
/**
|
|
2672
|
+
* TSD-specific refresh method that finds active TSDs and refreshes them
|
|
2673
|
+
*
|
|
2674
|
+
* @param {string[]} keyArr metadata keys
|
|
2675
|
+
* @param {boolean} [checkKey] whether to check if the key is valid
|
|
2676
|
+
* @returns {Promise.<string[]>} Returns list of keys that were refreshed
|
|
2677
|
+
*/
|
|
2678
|
+
static async refresh(keyArr, checkKey = true) {
|
|
2679
|
+
console.time('Time'); // eslint-disable-line no-console
|
|
2680
|
+
if (!keyArr) {
|
|
2681
|
+
Util.logger.error('No refresh-keys provided');
|
|
2682
|
+
return [];
|
|
2683
|
+
// keyArr = await this.getKeysForValidTSDs((await this.findRefreshableItems()).metadata);
|
|
2684
|
+
// checkKey = false;
|
|
2685
|
+
}
|
|
2686
|
+
let journeyCache;
|
|
2687
|
+
if (checkKey) {
|
|
2688
|
+
journeyCache = await this.retrieveForCache();
|
|
2689
|
+
}
|
|
2690
|
+
// then executes pause, publish, start on them.
|
|
2691
|
+
Util.logger.info(`Refreshing ${keyArr.length} ${this.definition.typeName}...`);
|
|
2692
|
+
Util.logger.debug(`Refreshing keys: ${keyArr.join(', ')}`);
|
|
2693
|
+
const refreshedKeyArr = [];
|
|
2694
|
+
const tsKeys = [];
|
|
2695
|
+
const rateLimit = pLimit(10);
|
|
2696
|
+
await Promise.all(
|
|
2697
|
+
keyArr.map((key) =>
|
|
2698
|
+
rateLimit(async () => {
|
|
2699
|
+
if (checkKey && !journeyCache.metadata[key]) {
|
|
2700
|
+
Util.logger.error(
|
|
2701
|
+
` ☇ skipping refresh of ${this.definition.type} ${key}: not found on server`
|
|
2702
|
+
);
|
|
2703
|
+
return;
|
|
2704
|
+
}
|
|
2705
|
+
switch (journeyCache.metadata[key].definitionType) {
|
|
2706
|
+
case 'Transactional': {
|
|
2707
|
+
if (checkKey && journeyCache.metadata[key]?.status !== 'Published') {
|
|
2708
|
+
Util.logger.error(
|
|
2709
|
+
` ☇ skipping refresh of ${this.definition.type} ${key}: Can only refresh journeys with status 'Published'. Found status: ${journeyCache.metadata[key]?.status}`
|
|
2710
|
+
);
|
|
2711
|
+
} else {
|
|
2712
|
+
const result = await this._refreshItem(key);
|
|
2713
|
+
if (result) {
|
|
2714
|
+
refreshedKeyArr.push(key);
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
break;
|
|
2718
|
+
}
|
|
2719
|
+
case 'Multistep': {
|
|
2720
|
+
// find all published & paused versions
|
|
2721
|
+
const responseAllVersions = await this.client.rest.getBulk(
|
|
2722
|
+
'/interaction/v1/interactions/?id=' +
|
|
2723
|
+
journeyCache.metadata[key].id +
|
|
2724
|
+
'&mostRecentVersionOnly=false',
|
|
2725
|
+
this.definition.restPageSize || 500
|
|
2448
2726
|
);
|
|
2449
|
-
|
|
2450
|
-
|
|
2727
|
+
if (responseAllVersions?.items?.length) {
|
|
2728
|
+
const allActiveVersions = responseAllVersions.items
|
|
2729
|
+
.filter(
|
|
2730
|
+
(item) =>
|
|
2731
|
+
item.status === 'Paused' || item.status === 'Published'
|
|
2732
|
+
)
|
|
2733
|
+
.map((item) => item.version);
|
|
2734
|
+
if (allActiveVersions.length) {
|
|
2735
|
+
Util.logger.info(
|
|
2736
|
+
Util.getGrayMsg(
|
|
2737
|
+
` - journey ${key} / ${journeyCache.metadata[key].name} Paused/Published version numbers: ` +
|
|
2738
|
+
allActiveVersions.join(', ')
|
|
2739
|
+
)
|
|
2740
|
+
);
|
|
2741
|
+
// get TS keys from email activities of paused/published versions
|
|
2742
|
+
const rateLimitActivities = pLimit(2);
|
|
2743
|
+
tsKeys.push(
|
|
2744
|
+
...(
|
|
2745
|
+
await Promise.all(
|
|
2746
|
+
allActiveVersions.map((version) =>
|
|
2747
|
+
rateLimitActivities(async () => {
|
|
2748
|
+
const journey = await this.client.rest.get(
|
|
2749
|
+
'/interaction/v1/interactions/' +
|
|
2750
|
+
journeyCache.metadata[key]?.id +
|
|
2751
|
+
'?extras=activities&versionNumber=' +
|
|
2752
|
+
version
|
|
2753
|
+
);
|
|
2754
|
+
// return all triggeredSends
|
|
2755
|
+
return journey.activities
|
|
2756
|
+
.filter(
|
|
2757
|
+
(activity) =>
|
|
2758
|
+
activity.type === 'EMAILV2' &&
|
|
2759
|
+
activity.configurationArguments
|
|
2760
|
+
?.triggeredSendKey
|
|
2761
|
+
)
|
|
2762
|
+
.map(
|
|
2763
|
+
(activity) =>
|
|
2764
|
+
activity.configurationArguments
|
|
2765
|
+
?.triggeredSendKey
|
|
2766
|
+
);
|
|
2767
|
+
})
|
|
2768
|
+
)
|
|
2769
|
+
)
|
|
2770
|
+
).flat()
|
|
2771
|
+
);
|
|
2772
|
+
|
|
2773
|
+
refreshedKeyArr.push(key);
|
|
2774
|
+
} else {
|
|
2775
|
+
Util.logger.error(
|
|
2776
|
+
` ☇ skipping refresh of ${this.definition.type} ${key}: no published/paused versions found`
|
|
2777
|
+
);
|
|
2778
|
+
}
|
|
2779
|
+
}
|
|
2780
|
+
break;
|
|
2781
|
+
}
|
|
2782
|
+
default: {
|
|
2451
2783
|
Util.logger.error(
|
|
2452
|
-
` -
|
|
2784
|
+
` - Refreshing ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: Unsupported definitionType '${journeyCache.metadata[key].definitionType}'`
|
|
2453
2785
|
);
|
|
2454
2786
|
}
|
|
2455
2787
|
}
|
|
@@ -2457,7 +2789,41 @@ class Journey extends MetadataType {
|
|
|
2457
2789
|
)
|
|
2458
2790
|
);
|
|
2459
2791
|
|
|
2460
|
-
|
|
2792
|
+
// refresh TriggeredSends
|
|
2793
|
+
TriggeredSend.buObject = this.buObject;
|
|
2794
|
+
TriggeredSend.client = this.client;
|
|
2795
|
+
TriggeredSend.properties = this.properties;
|
|
2796
|
+
// hard-refresh all triggeredSends even if the TS was paused (inactive) before
|
|
2797
|
+
await TriggeredSend.refresh(tsKeys, false);
|
|
2798
|
+
|
|
2799
|
+
Util.logger.info(
|
|
2800
|
+
`Refreshed ${refreshedKeyArr.length} of ${keyArr.length} ${this.definition.type}`
|
|
2801
|
+
);
|
|
2802
|
+
console.timeEnd('Time'); // eslint-disable-line no-console
|
|
2803
|
+
return refreshedKeyArr;
|
|
2804
|
+
}
|
|
2805
|
+
/**
|
|
2806
|
+
* helper for {@link Journey.refresh} that pauses, publishes and starts a triggered send
|
|
2807
|
+
*
|
|
2808
|
+
* @param {string} key external key of triggered send item
|
|
2809
|
+
* @returns {Promise.<boolean>} true if refresh was successful
|
|
2810
|
+
*/
|
|
2811
|
+
static async _refreshItem(key) {
|
|
2812
|
+
// pause
|
|
2813
|
+
const pausedKeys = await this.pause([key]);
|
|
2814
|
+
if (!pausedKeys?.length || pausedKeys[0] !== key) {
|
|
2815
|
+
Util.logger.error(` - failed to pause ${this.definition.typeName}: ${key}`);
|
|
2816
|
+
return false;
|
|
2817
|
+
}
|
|
2818
|
+
|
|
2819
|
+
// resume
|
|
2820
|
+
const resumedKeys = await this.execute([key]);
|
|
2821
|
+
if (!resumedKeys?.length || resumedKeys[0] !== key) {
|
|
2822
|
+
Util.logger.error(` - failed to resume ${this.definition.typeName}: ${key}`);
|
|
2823
|
+
return false;
|
|
2824
|
+
}
|
|
2825
|
+
|
|
2826
|
+
return true;
|
|
2461
2827
|
}
|
|
2462
2828
|
}
|
|
2463
2829
|
|