@aws-amplify/backend-notifications 0.0.0-test-20260708085627
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 +235 -0
- package/lib/campaign-association-asset/index.js +48413 -0
- package/lib/constants.d.ts +122 -0
- package/lib/constants.js +125 -0
- package/lib/construct.d.ts +283 -0
- package/lib/construct.js +824 -0
- package/lib/factory.d.ts +53 -0
- package/lib/factory.js +158 -0
- package/lib/handler-asset/index.js +530 -0
- package/lib/index.d.ts +7 -0
- package/lib/index.js +5 -0
- package/lib/lambda/campaign-association/handler.d.ts +29 -0
- package/lib/lambda/campaign-association/handler.js +80 -0
- package/lib/lambda/campaign-association/integration.d.ts +59 -0
- package/lib/lambda/campaign-association/integration.js +108 -0
- package/lib/lambda/campaign-association/onboarding.d.ts +25 -0
- package/lib/lambda/campaign-association/onboarding.js +74 -0
- package/lib/lambda/identify/device_resolver.d.ts +18 -0
- package/lib/lambda/identify/device_resolver.js +56 -0
- package/lib/lambda/identify/handler.d.ts +17 -0
- package/lib/lambda/identify/handler.js +124 -0
- package/lib/lambda/identify/mapping.d.ts +61 -0
- package/lib/lambda/identify/mapping.js +171 -0
- package/lib/lambda/identify/merge_resolver.d.ts +26 -0
- package/lib/lambda/identify/merge_resolver.js +36 -0
- package/lib/lambda/identify/principal.d.ts +68 -0
- package/lib/lambda/identify/principal.js +48 -0
- package/lib/lambda/identify/profile_resolver.d.ts +35 -0
- package/lib/lambda/identify/profile_resolver.js +65 -0
- package/lib/lambda/identify/types.d.ts +90 -0
- package/lib/lambda/identify/types.js +10 -0
- package/lib/lambda/identify/validation.d.ts +15 -0
- package/lib/lambda/identify/validation.js +99 -0
- package/lib/lambda/push/delivery.d.ts +49 -0
- package/lib/lambda/push/delivery.js +120 -0
- package/lib/lambda/push/device_lookup.d.ts +35 -0
- package/lib/lambda/push/device_lookup.js +88 -0
- package/lib/lambda/push/eum_client.d.ts +31 -0
- package/lib/lambda/push/eum_client.js +140 -0
- package/lib/lambda/push/event.d.ts +32 -0
- package/lib/lambda/push/event.js +122 -0
- package/lib/lambda/push/fixtures/real_journey_event.d.ts +19 -0
- package/lib/lambda/push/fixtures/real_journey_event.js +22 -0
- package/lib/lambda/push/handler.d.ts +15 -0
- package/lib/lambda/push/handler.js +86 -0
- package/lib/lambda/push/message_template.d.ts +72 -0
- package/lib/lambda/push/message_template.js +270 -0
- package/lib/lambda/push/payload.d.ts +25 -0
- package/lib/lambda/push/payload.js +53 -0
- package/lib/lambda/push/types.d.ts +153 -0
- package/lib/lambda/push/types.js +4 -0
- package/lib/lambda/shared/retry.d.ts +18 -0
- package/lib/lambda/shared/retry.js +45 -0
- package/lib/object_types.d.ts +63 -0
- package/lib/object_types.js +131 -0
- package/lib/push-handler-asset/index.js +75517 -0
- package/lib/types.d.ts +125 -0
- package/lib/types.js +2 -0
- package/package.json +49 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { SendMessagesCommand } from '@aws-sdk/client-pinpoint';
|
|
4
|
+
import { buildMessageConfiguration } from './payload.js';
|
|
5
|
+
/**
|
|
6
|
+
* Case-insensitive substrings of a Pinpoint per-address `StatusMessage` that
|
|
7
|
+
* indicate the DEVICE TOKEN itself is permanently invalid — the ONLY condition
|
|
8
|
+
* that justifies deleting the backing AmplifyDevice object (stale-token
|
|
9
|
+
* cleanup).
|
|
10
|
+
*
|
|
11
|
+
* - APNs: `BadDeviceToken`, `Unregistered`, `DeviceTokenNotForTopic`
|
|
12
|
+
* - FCM / GCM legacy HTTP API: `NotRegistered`, `InvalidRegistration`,
|
|
13
|
+
* `MismatchSenderId`
|
|
14
|
+
* - FCM HTTP v1 (current API): `UNREGISTERED` (matched by the APNs
|
|
15
|
+
* `Unregistered` entry), `SENDER_ID_MISMATCH`, and a malformed token's
|
|
16
|
+
* `INVALID_ARGUMENT` whose per-field message is "...not a valid FCM
|
|
17
|
+
* registration token"
|
|
18
|
+
*
|
|
19
|
+
* Everything else that yields a non-delivery — a channel that is not enabled on
|
|
20
|
+
* the EUM/Pinpoint application, missing channel credentials, `OPT_OUT`,
|
|
21
|
+
* `THROTTLED`, `TEMPORARY_FAILURE`, or a `PERMANENT_FAILURE` whose message does
|
|
22
|
+
* not match a token-invalidity signal — is treated as a transient / config
|
|
23
|
+
* problem and the token is KEPT. Deleting on those would wrongly wipe valid
|
|
24
|
+
* device registrations (e.g. when the app simply has no APNS/GCM channel yet).
|
|
25
|
+
*/
|
|
26
|
+
const INVALID_TOKEN_INDICATORS = [
|
|
27
|
+
// APNs
|
|
28
|
+
'BadDeviceToken',
|
|
29
|
+
'Unregistered',
|
|
30
|
+
'DeviceTokenNotForTopic',
|
|
31
|
+
// FCM / GCM legacy HTTP API
|
|
32
|
+
'NotRegistered',
|
|
33
|
+
'InvalidRegistration',
|
|
34
|
+
'MismatchSenderId',
|
|
35
|
+
// FCM HTTP v1 (current API). v1 reports token invalidity with different
|
|
36
|
+
// strings than the legacy API: `UNREGISTERED` (already matched
|
|
37
|
+
// case-insensitively by the APNs `Unregistered` entry), `SENDER_ID_MISMATCH`,
|
|
38
|
+
// and a malformed / non-FCM token as `INVALID_ARGUMENT` carrying the specific
|
|
39
|
+
// per-field message matched below. Match that exact token phrase rather than
|
|
40
|
+
// bare `INVALID_ARGUMENT` — the latter also covers non-token payload errors,
|
|
41
|
+
// so matching it broadly could wrongly delete a valid device on a
|
|
42
|
+
// malformed-message bug.
|
|
43
|
+
'SENDER_ID_MISMATCH',
|
|
44
|
+
'not a valid FCM registration token',
|
|
45
|
+
];
|
|
46
|
+
/**
|
|
47
|
+
* Decide whether a per-address delivery failure represents a permanently
|
|
48
|
+
* invalid TOKEN (safe to delete) versus a channel / app misconfiguration or
|
|
49
|
+
* transient error (keep the token).
|
|
50
|
+
*
|
|
51
|
+
* Conservative by design: returns `true` ONLY for a `PERMANENT_FAILURE` whose
|
|
52
|
+
* `StatusMessage` matches a known invalid-token indicator. The default for any
|
|
53
|
+
* ambiguous or unknown failure is `false` (keep the device).
|
|
54
|
+
*/
|
|
55
|
+
export const isInvalidTokenFailure = (status, statusMessage) => {
|
|
56
|
+
if (status !== 'PERMANENT_FAILURE') {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
const haystack = (statusMessage ?? '').toLowerCase();
|
|
60
|
+
return INVALID_TOKEN_INDICATORS.some((indicator) => haystack.includes(indicator.toLowerCase()));
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Deliver a single push to one device via AWS End User Messaging (Pinpoint
|
|
64
|
+
* `SendMessages`), addressing the message to the device token on its channel.
|
|
65
|
+
*
|
|
66
|
+
* Returns a structured per-device result classifying the Pinpoint
|
|
67
|
+
* `DeliveryStatus` into delivered / failed and flagging ONLY a genuinely
|
|
68
|
+
* invalid token as `stale` (via {@link isInvalidTokenFailure}) so the caller
|
|
69
|
+
* can delete its device object. A thrown call (e.g. the channel is not
|
|
70
|
+
* configured on the EUM app) is caught and reported as `status: 'ERROR'`
|
|
71
|
+
* (failed, NOT stale — the token itself may be fine).
|
|
72
|
+
*
|
|
73
|
+
* Emits greppable `[push] send.response` / `[push] classify` log lines carrying
|
|
74
|
+
* the request channel and the per-address response (DeliveryStatus /
|
|
75
|
+
* StatusCode / StatusMessage) plus the keep-vs-delete decision, so a failed
|
|
76
|
+
* send can be diagnosed as channel-not-enabled vs invalid-token from the logs.
|
|
77
|
+
* These carry NO device token, profile id, or message copy.
|
|
78
|
+
*/
|
|
79
|
+
export const deliverToDevice = async (pinpoint, applicationId, deviceToken, channelType, message) => {
|
|
80
|
+
try {
|
|
81
|
+
const messageConfiguration = buildMessageConfiguration(channelType, message);
|
|
82
|
+
const res = await pinpoint.send(new SendMessagesCommand({
|
|
83
|
+
ApplicationId: applicationId,
|
|
84
|
+
MessageRequest: {
|
|
85
|
+
Addresses: {
|
|
86
|
+
[deviceToken]: { ChannelType: channelType },
|
|
87
|
+
},
|
|
88
|
+
MessageConfiguration: messageConfiguration,
|
|
89
|
+
},
|
|
90
|
+
}));
|
|
91
|
+
const result = res.MessageResponse?.Result?.[deviceToken];
|
|
92
|
+
const status = result?.DeliveryStatus ?? 'UNKNOWN_FAILURE';
|
|
93
|
+
const statusCode = result?.StatusCode;
|
|
94
|
+
const statusMessage = result?.StatusMessage;
|
|
95
|
+
const stale = isInvalidTokenFailure(status, statusMessage);
|
|
96
|
+
console.log('[push] send.response', JSON.stringify({
|
|
97
|
+
channelType,
|
|
98
|
+
deliveryStatus: status,
|
|
99
|
+
statusCode,
|
|
100
|
+
statusMessage,
|
|
101
|
+
}));
|
|
102
|
+
console.log('[push] classify', JSON.stringify({
|
|
103
|
+
channelType,
|
|
104
|
+
deliveryStatus: status,
|
|
105
|
+
decision: stale ? 'STALE_DELETE' : 'KEEP',
|
|
106
|
+
reason: stale
|
|
107
|
+
? 'StatusMessage matched an invalid-token indicator'
|
|
108
|
+
: `not a token-invalidity signal (status=${status})`,
|
|
109
|
+
statusMessage,
|
|
110
|
+
}));
|
|
111
|
+
return {
|
|
112
|
+
deviceToken,
|
|
113
|
+
channelType,
|
|
114
|
+
status,
|
|
115
|
+
delivered: status === 'SUCCESSFUL',
|
|
116
|
+
stale,
|
|
117
|
+
statusCode,
|
|
118
|
+
statusMessage,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
const statusMessage = err instanceof Error ? err.message : 'unknown error';
|
|
123
|
+
console.log('[push] send.error', JSON.stringify({
|
|
124
|
+
channelType,
|
|
125
|
+
deliveryStatus: 'ERROR',
|
|
126
|
+
decision: 'KEEP',
|
|
127
|
+
reason: 'SendMessages threw (e.g. channel not configured) — token kept',
|
|
128
|
+
statusMessage,
|
|
129
|
+
}));
|
|
130
|
+
return {
|
|
131
|
+
deviceToken,
|
|
132
|
+
channelType,
|
|
133
|
+
status: 'ERROR',
|
|
134
|
+
delivered: false,
|
|
135
|
+
stale: false,
|
|
136
|
+
statusMessage,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXVtX2NsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYW1iZGEvcHVzaC9ldW1fY2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHFFQUFxRTtBQUNyRSxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFrQixtQkFBbUIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQy9FLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUd6RDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFDSCxNQUFNLHdCQUF3QixHQUFHO0lBQy9CLE9BQU87SUFDUCxnQkFBZ0I7SUFDaEIsY0FBYztJQUNkLHdCQUF3QjtJQUN4Qiw0QkFBNEI7SUFDNUIsZUFBZTtJQUNmLHFCQUFxQjtJQUNyQixrQkFBa0I7SUFDbEIsd0VBQXdFO0lBQ3hFLCtEQUErRDtJQUMvRCw4RUFBOEU7SUFDOUUsOEVBQThFO0lBQzlFLDZFQUE2RTtJQUM3RSw2RUFBNkU7SUFDN0Usa0VBQWtFO0lBQ2xFLHlCQUF5QjtJQUN6QixvQkFBb0I7SUFDcEIsb0NBQW9DO0NBQ3JDLENBQUM7QUFFRjs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUFHLENBQ25DLE1BQWMsRUFDZCxhQUFpQyxFQUN4QixFQUFFO0lBQ1gsSUFBSSxNQUFNLEtBQUssbUJBQW1CLEVBQUUsQ0FBQztRQUNuQyxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFDRCxNQUFNLFFBQVEsR0FBRyxDQUFDLGFBQWEsSUFBSSxFQUFFLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNyRCxPQUFPLHdCQUF3QixDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQ2pELFFBQVEsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQzNDLENBQUM7QUFDSixDQUFDLENBQUM7QUFFRjs7Ozs7Ozs7Ozs7Ozs7OztHQWdCRztBQUNILE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxLQUFLLEVBQ2xDLFFBQXdCLEVBQ3hCLGFBQXFCLEVBQ3JCLFdBQW1CLEVBQ25CLFdBQTRCLEVBQzVCLE9BQW9CLEVBQ1csRUFBRTtJQUNqQyxJQUFJLENBQUM7UUFDSCxNQUFNLG9CQUFvQixHQUFHLHlCQUF5QixDQUNwRCxXQUFXLEVBQ1gsT0FBTyxDQUNSLENBQUM7UUFFRixNQUFNLEdBQUcsR0FBRyxNQUFNLFFBQVEsQ0FBQyxJQUFJLENBQzdCLElBQUksbUJBQW1CLENBQUM7WUFDdEIsYUFBYSxFQUFFLGFBQWE7WUFDNUIsY0FBYyxFQUFFO2dCQUNkLFNBQVMsRUFBRTtvQkFDVCxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRTtpQkFDNUM7Z0JBQ0Qsb0JBQW9CLEVBQUUsb0JBQW9CO2FBQzNDO1NBQ0YsQ0FBQyxDQUNILENBQUM7UUFFRixNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsZUFBZSxFQUFFLE1BQU0sRUFBRSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQzFELE1BQU0sTUFBTSxHQUFHLE1BQU0sRUFBRSxjQUFjLElBQUksaUJBQWlCLENBQUM7UUFDM0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxFQUFFLFVBQVUsQ0FBQztRQUN0QyxNQUFNLGFBQWEsR0FBRyxNQUFNLEVBQUUsYUFBYSxDQUFDO1FBQzVDLE1BQU0sS0FBSyxHQUFHLHFCQUFxQixDQUFDLE1BQU0sRUFBRSxhQUFhLENBQUMsQ0FBQztRQUUzRCxPQUFPLENBQUMsR0FBRyxDQUNULHNCQUFzQixFQUN0QixJQUFJLENBQUMsU0FBUyxDQUFDO1lBQ2IsV0FBVztZQUNYLGNBQWMsRUFBRSxNQUFNO1lBQ3RCLFVBQVU7WUFDVixhQUFhO1NBQ2QsQ0FBQyxDQUNILENBQUM7UUFDRixPQUFPLENBQUMsR0FBRyxDQUNULGlCQUFpQixFQUNqQixJQUFJLENBQUMsU0FBUyxDQUFDO1lBQ2IsV0FBVztZQUNYLGNBQWMsRUFBRSxNQUFNO1lBQ3RCLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsTUFBTTtZQUN6QyxNQUFNLEVBQUUsS0FBSztnQkFDWCxDQUFDLENBQUMsa0RBQWtEO2dCQUNwRCxDQUFDLENBQUMseUNBQXlDLE1BQU0sR0FBRztZQUN0RCxhQUFhO1NBQ2QsQ0FBQyxDQUNILENBQUM7UUFFRixPQUFPO1lBQ0wsV0FBVztZQUNYLFdBQVc7WUFDWCxNQUFNO1lBQ04sU0FBUyxFQUFFLE1BQU0sS0FBSyxZQUFZO1lBQ2xDLEtBQUs7WUFDTCxVQUFVO1lBQ1YsYUFBYTtTQUNkLENBQUM7SUFDSixDQUFDO0lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNiLE1BQU0sYUFBYSxHQUFHLEdBQUcsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQztRQUMzRSxPQUFPLENBQUMsR0FBRyxDQUNULG1CQUFtQixFQUNuQixJQUFJLENBQUMsU0FBUyxDQUFDO1lBQ2IsV0FBVztZQUNYLGNBQWMsRUFBRSxPQUFPO1lBQ3ZCLFFBQVEsRUFBRSxNQUFNO1lBQ2hCLE1BQU0sRUFBRSwrREFBK0Q7WUFDdkUsYUFBYTtTQUNkLENBQUMsQ0FDSCxDQUFDO1FBQ0YsT0FBTztZQUNMLFdBQVc7WUFDWCxXQUFXO1lBQ1gsTUFBTSxFQUFFLE9BQU87WUFDZixTQUFTLEVBQUUsS0FBSztZQUNoQixLQUFLLEVBQUUsS0FBSztZQUNaLGFBQWE7U0FDZCxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgUGlucG9pbnRDbGllbnQsIFNlbmRNZXNzYWdlc0NvbW1hbmQgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtcGlucG9pbnQnO1xuaW1wb3J0IHsgYnVpbGRNZXNzYWdlQ29uZmlndXJhdGlvbiB9IGZyb20gJy4vcGF5bG9hZC5qcyc7XG5pbXBvcnQgeyBEZXZpY2VEZWxpdmVyeVJlc3VsdCwgUHVzaENoYW5uZWxUeXBlLCBQdXNoTWVzc2FnZSB9IGZyb20gJy4vdHlwZXMuanMnO1xuXG4vKipcbiAqIENhc2UtaW5zZW5zaXRpdmUgc3Vic3RyaW5ncyBvZiBhIFBpbnBvaW50IHBlci1hZGRyZXNzIGBTdGF0dXNNZXNzYWdlYCB0aGF0XG4gKiBpbmRpY2F0ZSB0aGUgREVWSUNFIFRPS0VOIGl0c2VsZiBpcyBwZXJtYW5lbnRseSBpbnZhbGlkIOKAlCB0aGUgT05MWSBjb25kaXRpb25cbiAqIHRoYXQganVzdGlmaWVzIGRlbGV0aW5nIHRoZSBiYWNraW5nIEFtcGxpZnlEZXZpY2Ugb2JqZWN0IChzdGFsZS10b2tlblxuICogY2xlYW51cCkuXG4gKlxuICogLSBBUE5zOiBgQmFkRGV2aWNlVG9rZW5gLCBgVW5yZWdpc3RlcmVkYCwgYERldmljZVRva2VuTm90Rm9yVG9waWNgXG4gKiAtIEZDTSAvIEdDTSBsZWdhY3kgSFRUUCBBUEk6IGBOb3RSZWdpc3RlcmVkYCwgYEludmFsaWRSZWdpc3RyYXRpb25gLFxuICogICBgTWlzbWF0Y2hTZW5kZXJJZGBcbiAqIC0gRkNNIEhUVFAgdjEgKGN1cnJlbnQgQVBJKTogYFVOUkVHSVNURVJFRGAgKG1hdGNoZWQgYnkgdGhlIEFQTnNcbiAqICAgYFVucmVnaXN0ZXJlZGAgZW50cnkpLCBgU0VOREVSX0lEX01JU01BVENIYCwgYW5kIGEgbWFsZm9ybWVkIHRva2VuJ3NcbiAqICAgYElOVkFMSURfQVJHVU1FTlRgIHdob3NlIHBlci1maWVsZCBtZXNzYWdlIGlzIFwiLi4ubm90IGEgdmFsaWQgRkNNXG4gKiAgIHJlZ2lzdHJhdGlvbiB0b2tlblwiXG4gKlxuICogRXZlcnl0aGluZyBlbHNlIHRoYXQgeWllbGRzIGEgbm9uLWRlbGl2ZXJ5IOKAlCBhIGNoYW5uZWwgdGhhdCBpcyBub3QgZW5hYmxlZCBvblxuICogdGhlIEVVTS9QaW5wb2ludCBhcHBsaWNhdGlvbiwgbWlzc2luZyBjaGFubmVsIGNyZWRlbnRpYWxzLCBgT1BUX09VVGAsXG4gKiBgVEhST1RUTEVEYCwgYFRFTVBPUkFSWV9GQUlMVVJFYCwgb3IgYSBgUEVSTUFORU5UX0ZBSUxVUkVgIHdob3NlIG1lc3NhZ2UgZG9lc1xuICogbm90IG1hdGNoIGEgdG9rZW4taW52YWxpZGl0eSBzaWduYWwg4oCUIGlzIHRyZWF0ZWQgYXMgYSB0cmFuc2llbnQgLyBjb25maWdcbiAqIHByb2JsZW0gYW5kIHRoZSB0b2tlbiBpcyBLRVBULiBEZWxldGluZyBvbiB0aG9zZSB3b3VsZCB3cm9uZ2x5IHdpcGUgdmFsaWRcbiAqIGRldmljZSByZWdpc3RyYXRpb25zIChlLmcuIHdoZW4gdGhlIGFwcCBzaW1wbHkgaGFzIG5vIEFQTlMvR0NNIGNoYW5uZWwgeWV0KS5cbiAqL1xuY29uc3QgSU5WQUxJRF9UT0tFTl9JTkRJQ0FUT1JTID0gW1xuICAvLyBBUE5zXG4gICdCYWREZXZpY2VUb2tlbicsXG4gICdVbnJlZ2lzdGVyZWQnLFxuICAnRGV2aWNlVG9rZW5Ob3RGb3JUb3BpYycsXG4gIC8vIEZDTSAvIEdDTSBsZWdhY3kgSFRUUCBBUElcbiAgJ05vdFJlZ2lzdGVyZWQnLFxuICAnSW52YWxpZFJlZ2lzdHJhdGlvbicsXG4gICdNaXNtYXRjaFNlbmRlcklkJyxcbiAgLy8gRkNNIEhUVFAgdjEgKGN1cnJlbnQgQVBJKS4gdjEgcmVwb3J0cyB0b2tlbiBpbnZhbGlkaXR5IHdpdGggZGlmZmVyZW50XG4gIC8vIHN0cmluZ3MgdGhhbiB0aGUgbGVnYWN5IEFQSTogYFVOUkVHSVNURVJFRGAgKGFscmVhZHkgbWF0Y2hlZFxuICAvLyBjYXNlLWluc2Vuc2l0aXZlbHkgYnkgdGhlIEFQTnMgYFVucmVnaXN0ZXJlZGAgZW50cnkpLCBgU0VOREVSX0lEX01JU01BVENIYCxcbiAgLy8gYW5kIGEgbWFsZm9ybWVkIC8gbm9uLUZDTSB0b2tlbiBhcyBgSU5WQUxJRF9BUkdVTUVOVGAgY2FycnlpbmcgdGhlIHNwZWNpZmljXG4gIC8vIHBlci1maWVsZCBtZXNzYWdlIG1hdGNoZWQgYmVsb3cuIE1hdGNoIHRoYXQgZXhhY3QgdG9rZW4gcGhyYXNlIHJhdGhlciB0aGFuXG4gIC8vIGJhcmUgYElOVkFMSURfQVJHVU1FTlRgIOKAlCB0aGUgbGF0dGVyIGFsc28gY292ZXJzIG5vbi10b2tlbiBwYXlsb2FkIGVycm9ycyxcbiAgLy8gc28gbWF0Y2hpbmcgaXQgYnJvYWRseSBjb3VsZCB3cm9uZ2x5IGRlbGV0ZSBhIHZhbGlkIGRldmljZSBvbiBhXG4gIC8vIG1hbGZvcm1lZC1tZXNzYWdlIGJ1Zy5cbiAgJ1NFTkRFUl9JRF9NSVNNQVRDSCcsXG4gICdub3QgYSB2YWxpZCBGQ00gcmVnaXN0cmF0aW9uIHRva2VuJyxcbl07XG5cbi8qKlxuICogRGVjaWRlIHdoZXRoZXIgYSBwZXItYWRkcmVzcyBkZWxpdmVyeSBmYWlsdXJlIHJlcHJlc2VudHMgYSBwZXJtYW5lbnRseVxuICogaW52YWxpZCBUT0tFTiAoc2FmZSB0byBkZWxldGUpIHZlcnN1cyBhIGNoYW5uZWwgLyBhcHAgbWlzY29uZmlndXJhdGlvbiBvclxuICogdHJhbnNpZW50IGVycm9yIChrZWVwIHRoZSB0b2tlbikuXG4gKlxuICogQ29uc2VydmF0aXZlIGJ5IGRlc2lnbjogcmV0dXJucyBgdHJ1ZWAgT05MWSBmb3IgYSBgUEVSTUFORU5UX0ZBSUxVUkVgIHdob3NlXG4gKiBgU3RhdHVzTWVzc2FnZWAgbWF0Y2hlcyBhIGtub3duIGludmFsaWQtdG9rZW4gaW5kaWNhdG9yLiBUaGUgZGVmYXVsdCBmb3IgYW55XG4gKiBhbWJpZ3VvdXMgb3IgdW5rbm93biBmYWlsdXJlIGlzIGBmYWxzZWAgKGtlZXAgdGhlIGRldmljZSkuXG4gKi9cbmV4cG9ydCBjb25zdCBpc0ludmFsaWRUb2tlbkZhaWx1cmUgPSAoXG4gIHN0YXR1czogc3RyaW5nLFxuICBzdGF0dXNNZXNzYWdlOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4pOiBib29sZWFuID0+IHtcbiAgaWYgKHN0YXR1cyAhPT0gJ1BFUk1BTkVOVF9GQUlMVVJFJykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBjb25zdCBoYXlzdGFjayA9IChzdGF0dXNNZXNzYWdlID8/ICcnKS50b0xvd2VyQ2FzZSgpO1xuICByZXR1cm4gSU5WQUxJRF9UT0tFTl9JTkRJQ0FUT1JTLnNvbWUoKGluZGljYXRvcikgPT5cbiAgICBoYXlzdGFjay5pbmNsdWRlcyhpbmRpY2F0b3IudG9Mb3dlckNhc2UoKSksXG4gICk7XG59O1xuXG4vKipcbiAqIERlbGl2ZXIgYSBzaW5nbGUgcHVzaCB0byBvbmUgZGV2aWNlIHZpYSBBV1MgRW5kIFVzZXIgTWVzc2FnaW5nIChQaW5wb2ludFxuICogYFNlbmRNZXNzYWdlc2ApLCBhZGRyZXNzaW5nIHRoZSBtZXNzYWdlIHRvIHRoZSBkZXZpY2UgdG9rZW4gb24gaXRzIGNoYW5uZWwuXG4gKlxuICogUmV0dXJucyBhIHN0cnVjdHVyZWQgcGVyLWRldmljZSByZXN1bHQgY2xhc3NpZnlpbmcgdGhlIFBpbnBvaW50XG4gKiBgRGVsaXZlcnlTdGF0dXNgIGludG8gZGVsaXZlcmVkIC8gZmFpbGVkIGFuZCBmbGFnZ2luZyBPTkxZIGEgZ2VudWluZWx5XG4gKiBpbnZhbGlkIHRva2VuIGFzIGBzdGFsZWAgKHZpYSB7QGxpbmsgaXNJbnZhbGlkVG9rZW5GYWlsdXJlfSkgc28gdGhlIGNhbGxlclxuICogY2FuIGRlbGV0ZSBpdHMgZGV2aWNlIG9iamVjdC4gQSB0aHJvd24gY2FsbCAoZS5nLiB0aGUgY2hhbm5lbCBpcyBub3RcbiAqIGNvbmZpZ3VyZWQgb24gdGhlIEVVTSBhcHApIGlzIGNhdWdodCBhbmQgcmVwb3J0ZWQgYXMgYHN0YXR1czogJ0VSUk9SJ2BcbiAqIChmYWlsZWQsIE5PVCBzdGFsZSDigJQgdGhlIHRva2VuIGl0c2VsZiBtYXkgYmUgZmluZSkuXG4gKlxuICogRW1pdHMgZ3JlcHBhYmxlIGBbcHVzaF0gc2VuZC5yZXNwb25zZWAgLyBgW3B1c2hdIGNsYXNzaWZ5YCBsb2cgbGluZXMgY2FycnlpbmdcbiAqIHRoZSByZXF1ZXN0IGNoYW5uZWwgYW5kIHRoZSBwZXItYWRkcmVzcyByZXNwb25zZSAoRGVsaXZlcnlTdGF0dXMgL1xuICogU3RhdHVzQ29kZSAvIFN0YXR1c01lc3NhZ2UpIHBsdXMgdGhlIGtlZXAtdnMtZGVsZXRlIGRlY2lzaW9uLCBzbyBhIGZhaWxlZFxuICogc2VuZCBjYW4gYmUgZGlhZ25vc2VkIGFzIGNoYW5uZWwtbm90LWVuYWJsZWQgdnMgaW52YWxpZC10b2tlbiBmcm9tIHRoZSBsb2dzLlxuICogVGhlc2UgY2FycnkgTk8gZGV2aWNlIHRva2VuLCBwcm9maWxlIGlkLCBvciBtZXNzYWdlIGNvcHkuXG4gKi9cbmV4cG9ydCBjb25zdCBkZWxpdmVyVG9EZXZpY2UgPSBhc3luYyAoXG4gIHBpbnBvaW50OiBQaW5wb2ludENsaWVudCxcbiAgYXBwbGljYXRpb25JZDogc3RyaW5nLFxuICBkZXZpY2VUb2tlbjogc3RyaW5nLFxuICBjaGFubmVsVHlwZTogUHVzaENoYW5uZWxUeXBlLFxuICBtZXNzYWdlOiBQdXNoTWVzc2FnZSxcbik6IFByb21pc2U8RGV2aWNlRGVsaXZlcnlSZXN1bHQ+ID0+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBtZXNzYWdlQ29uZmlndXJhdGlvbiA9IGJ1aWxkTWVzc2FnZUNvbmZpZ3VyYXRpb24oXG4gICAgICBjaGFubmVsVHlwZSxcbiAgICAgIG1lc3NhZ2UsXG4gICAgKTtcblxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHBpbnBvaW50LnNlbmQoXG4gICAgICBuZXcgU2VuZE1lc3NhZ2VzQ29tbWFuZCh7XG4gICAgICAgIEFwcGxpY2F0aW9uSWQ6IGFwcGxpY2F0aW9uSWQsXG4gICAgICAgIE1lc3NhZ2VSZXF1ZXN0OiB7XG4gICAgICAgICAgQWRkcmVzc2VzOiB7XG4gICAgICAgICAgICBbZGV2aWNlVG9rZW5dOiB7IENoYW5uZWxUeXBlOiBjaGFubmVsVHlwZSB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgTWVzc2FnZUNvbmZpZ3VyYXRpb246IG1lc3NhZ2VDb25maWd1cmF0aW9uLFxuICAgICAgICB9LFxuICAgICAgfSksXG4gICAgKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IHJlcy5NZXNzYWdlUmVzcG9uc2U/LlJlc3VsdD8uW2RldmljZVRva2VuXTtcbiAgICBjb25zdCBzdGF0dXMgPSByZXN1bHQ/LkRlbGl2ZXJ5U3RhdHVzID8/ICdVTktOT1dOX0ZBSUxVUkUnO1xuICAgIGNvbnN0IHN0YXR1c0NvZGUgPSByZXN1bHQ/LlN0YXR1c0NvZGU7XG4gICAgY29uc3Qgc3RhdHVzTWVzc2FnZSA9IHJlc3VsdD8uU3RhdHVzTWVzc2FnZTtcbiAgICBjb25zdCBzdGFsZSA9IGlzSW52YWxpZFRva2VuRmFpbHVyZShzdGF0dXMsIHN0YXR1c01lc3NhZ2UpO1xuXG4gICAgY29uc29sZS5sb2coXG4gICAgICAnW3B1c2hdIHNlbmQucmVzcG9uc2UnLFxuICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICBjaGFubmVsVHlwZSxcbiAgICAgICAgZGVsaXZlcnlTdGF0dXM6IHN0YXR1cyxcbiAgICAgICAgc3RhdHVzQ29kZSxcbiAgICAgICAgc3RhdHVzTWVzc2FnZSxcbiAgICAgIH0pLFxuICAgICk7XG4gICAgY29uc29sZS5sb2coXG4gICAgICAnW3B1c2hdIGNsYXNzaWZ5JyxcbiAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgY2hhbm5lbFR5cGUsXG4gICAgICAgIGRlbGl2ZXJ5U3RhdHVzOiBzdGF0dXMsXG4gICAgICAgIGRlY2lzaW9uOiBzdGFsZSA/ICdTVEFMRV9ERUxFVEUnIDogJ0tFRVAnLFxuICAgICAgICByZWFzb246IHN0YWxlXG4gICAgICAgICAgPyAnU3RhdHVzTWVzc2FnZSBtYXRjaGVkIGFuIGludmFsaWQtdG9rZW4gaW5kaWNhdG9yJ1xuICAgICAgICAgIDogYG5vdCBhIHRva2VuLWludmFsaWRpdHkgc2lnbmFsIChzdGF0dXM9JHtzdGF0dXN9KWAsXG4gICAgICAgIHN0YXR1c01lc3NhZ2UsXG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGRldmljZVRva2VuLFxuICAgICAgY2hhbm5lbFR5cGUsXG4gICAgICBzdGF0dXMsXG4gICAgICBkZWxpdmVyZWQ6IHN0YXR1cyA9PT0gJ1NVQ0NFU1NGVUwnLFxuICAgICAgc3RhbGUsXG4gICAgICBzdGF0dXNDb2RlLFxuICAgICAgc3RhdHVzTWVzc2FnZSxcbiAgICB9O1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBjb25zdCBzdGF0dXNNZXNzYWdlID0gZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6ICd1bmtub3duIGVycm9yJztcbiAgICBjb25zb2xlLmxvZyhcbiAgICAgICdbcHVzaF0gc2VuZC5lcnJvcicsXG4gICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIGNoYW5uZWxUeXBlLFxuICAgICAgICBkZWxpdmVyeVN0YXR1czogJ0VSUk9SJyxcbiAgICAgICAgZGVjaXNpb246ICdLRUVQJyxcbiAgICAgICAgcmVhc29uOiAnU2VuZE1lc3NhZ2VzIHRocmV3IChlLmcuIGNoYW5uZWwgbm90IGNvbmZpZ3VyZWQpIOKAlCB0b2tlbiBrZXB0JyxcbiAgICAgICAgc3RhdHVzTWVzc2FnZSxcbiAgICAgIH0pLFxuICAgICk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRldmljZVRva2VuLFxuICAgICAgY2hhbm5lbFR5cGUsXG4gICAgICBzdGF0dXM6ICdFUlJPUicsXG4gICAgICBkZWxpdmVyZWQ6IGZhbHNlLFxuICAgICAgc3RhbGU6IGZhbHNlLFxuICAgICAgc3RhdHVzTWVzc2FnZSxcbiAgICB9O1xuICB9XG59O1xuIl19
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ParsedPushEvent } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a raw Connect Journey Custom-action event into a flat list of profile
|
|
4
|
+
* targets plus the message to deliver.
|
|
5
|
+
*
|
|
6
|
+
* CANONICAL shape — the Amazon Connect Outbound Campaigns v2 journey
|
|
7
|
+
* invocation, confirmed verbatim from a live journey run (see
|
|
8
|
+
* `fixtures/real_journey_event.ts` for the source-log reference). This is the
|
|
9
|
+
* ONLY shape Connect sends, and the single primary parse path:
|
|
10
|
+
*
|
|
11
|
+
* {
|
|
12
|
+
* InvocationMetadata: { CampaignContext: { CampaignId, RunId, ActionId, CampaignName } },
|
|
13
|
+
* Items: { CustomerProfiles: [ { ProfileId, CustomerData, ... }, ... ] }
|
|
14
|
+
* }
|
|
15
|
+
*
|
|
16
|
+
* Shape specifics (all PascalCase on the envelope):
|
|
17
|
+
* - `Items` is an OBJECT `{ CustomerProfiles: [...] }`;
|
|
18
|
+
* - each entry carries a top-level `ProfileId` (used for device lookup);
|
|
19
|
+
* - each entry's `CustomerData` is a SERIALIZED JSON STRING with camelCase
|
|
20
|
+
* keys (`profileId`, `firstName`, `messageTitle`, `messageBody`,
|
|
21
|
+
* `attributes.*`) that is `JSON.parse`d.
|
|
22
|
+
*
|
|
23
|
+
* Minimal, documented defensive handling only: a `CustomerData` already given as
|
|
24
|
+
* a parsed object is tolerated (see {@link coerceCustomerData}); missing /
|
|
25
|
+
* malformed fields are skipped rather than aborting the batch. The real journey
|
|
26
|
+
* carries NO message copy, so {@link ParsedPushEvent.message} is always the safe
|
|
27
|
+
* {@link DEFAULT_PUSH_TITLE} / {@link DEFAULT_PUSH_BODY}; personalized copy comes
|
|
28
|
+
* from the Q Connect PUSH template rendered per profile downstream, and this
|
|
29
|
+
* default is used only as the per-channel fallback.
|
|
30
|
+
*/
|
|
31
|
+
export declare const parsePushEvent: (event: unknown) => ParsedPushEvent;
|
|
32
|
+
//# sourceMappingURL=event.d.ts.map
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { DEFAULT_PUSH_BODY, DEFAULT_PUSH_TITLE } from '../../constants.js';
|
|
4
|
+
/**
|
|
5
|
+
* Parse a raw Connect Journey Custom-action event into a flat list of profile
|
|
6
|
+
* targets plus the message to deliver.
|
|
7
|
+
*
|
|
8
|
+
* CANONICAL shape — the Amazon Connect Outbound Campaigns v2 journey
|
|
9
|
+
* invocation, confirmed verbatim from a live journey run (see
|
|
10
|
+
* `fixtures/real_journey_event.ts` for the source-log reference). This is the
|
|
11
|
+
* ONLY shape Connect sends, and the single primary parse path:
|
|
12
|
+
*
|
|
13
|
+
* {
|
|
14
|
+
* InvocationMetadata: { CampaignContext: { CampaignId, RunId, ActionId, CampaignName } },
|
|
15
|
+
* Items: { CustomerProfiles: [ { ProfileId, CustomerData, ... }, ... ] }
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* Shape specifics (all PascalCase on the envelope):
|
|
19
|
+
* - `Items` is an OBJECT `{ CustomerProfiles: [...] }`;
|
|
20
|
+
* - each entry carries a top-level `ProfileId` (used for device lookup);
|
|
21
|
+
* - each entry's `CustomerData` is a SERIALIZED JSON STRING with camelCase
|
|
22
|
+
* keys (`profileId`, `firstName`, `messageTitle`, `messageBody`,
|
|
23
|
+
* `attributes.*`) that is `JSON.parse`d.
|
|
24
|
+
*
|
|
25
|
+
* Minimal, documented defensive handling only: a `CustomerData` already given as
|
|
26
|
+
* a parsed object is tolerated (see {@link coerceCustomerData}); missing /
|
|
27
|
+
* malformed fields are skipped rather than aborting the batch. The real journey
|
|
28
|
+
* carries NO message copy, so {@link ParsedPushEvent.message} is always the safe
|
|
29
|
+
* {@link DEFAULT_PUSH_TITLE} / {@link DEFAULT_PUSH_BODY}; personalized copy comes
|
|
30
|
+
* from the Q Connect PUSH template rendered per profile downstream, and this
|
|
31
|
+
* default is used only as the per-channel fallback.
|
|
32
|
+
*/
|
|
33
|
+
export const parsePushEvent = (event) => {
|
|
34
|
+
const root = isRecord(event) ? event : {};
|
|
35
|
+
const { targets, parsePath } = extractTargets(root);
|
|
36
|
+
const campaign = extractCampaign(root);
|
|
37
|
+
return {
|
|
38
|
+
targets,
|
|
39
|
+
message: { title: DEFAULT_PUSH_TITLE, body: DEFAULT_PUSH_BODY },
|
|
40
|
+
parsePath,
|
|
41
|
+
...(campaign ? { campaign } : {}),
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
45
|
+
const asString = (v) => typeof v === 'string' && v.length > 0 ? v : undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Extract profile targets from the canonical `Items.CustomerProfiles[]` array.
|
|
48
|
+
* Each entry contributes its `ProfileId` + parsed `CustomerData`; entries
|
|
49
|
+
* without a usable `ProfileId` are skipped.
|
|
50
|
+
*/
|
|
51
|
+
const extractTargets = (root) => {
|
|
52
|
+
const targets = [];
|
|
53
|
+
const items = root.Items;
|
|
54
|
+
const customerProfiles = isRecord(items) ? items.CustomerProfiles : undefined;
|
|
55
|
+
if (Array.isArray(customerProfiles)) {
|
|
56
|
+
for (const entry of customerProfiles) {
|
|
57
|
+
if (!isRecord(entry)) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const profileId = asString(entry.ProfileId);
|
|
61
|
+
if (!profileId) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
targets.push({
|
|
65
|
+
profileId,
|
|
66
|
+
customerData: coerceCustomerData(entry.CustomerData),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return { targets, parsePath: targets.length > 0 ? 'canonical' : 'none' };
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Coerce a raw `CustomerData` value into a property bag.
|
|
74
|
+
*
|
|
75
|
+
* The real Connect journey delivers `CustomerData` as a SERIALIZED JSON STRING
|
|
76
|
+
* (camelCase keys), so a string is `JSON.parse`d. Minimal defensive tolerance:
|
|
77
|
+
* a value already given as a plain object is used as-is. Anything else — or a
|
|
78
|
+
* string that isn't valid JSON, or JSON that isn't an object — yields
|
|
79
|
+
* `undefined` so a malformed entry never aborts the batch.
|
|
80
|
+
*/
|
|
81
|
+
const coerceCustomerData = (raw) => {
|
|
82
|
+
if (typeof raw === 'string') {
|
|
83
|
+
const trimmed = raw.trim();
|
|
84
|
+
if (!trimmed) {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
const parsed = JSON.parse(trimmed);
|
|
89
|
+
return isRecord(parsed) ? parsed : undefined;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return isRecord(raw) ? raw : undefined;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Extract the Outbound Campaigns v2 journey context from
|
|
99
|
+
* `InvocationMetadata.CampaignContext`, when present. Returns `undefined` when
|
|
100
|
+
* the envelope carries no campaign metadata (e.g. direct-invoke test payloads)
|
|
101
|
+
* or when none of the expected fields resolve.
|
|
102
|
+
*/
|
|
103
|
+
const extractCampaign = (root) => {
|
|
104
|
+
const meta = root.InvocationMetadata;
|
|
105
|
+
if (!isRecord(meta)) {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
const ctx = meta.CampaignContext;
|
|
109
|
+
if (!isRecord(ctx)) {
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
const campaign = {
|
|
113
|
+
campaignId: asString(ctx.CampaignId),
|
|
114
|
+
campaignName: asString(ctx.CampaignName),
|
|
115
|
+
actionId: asString(ctx.ActionId),
|
|
116
|
+
runId: asString(ctx.RunId),
|
|
117
|
+
};
|
|
118
|
+
return Object.values(campaign).some((v) => v !== undefined)
|
|
119
|
+
? campaign
|
|
120
|
+
: undefined;
|
|
121
|
+
};
|
|
122
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGFtYmRhL3B1c2gvZXZlbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEscUVBQXFFO0FBQ3JFLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQVEzRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTRCRztBQUNILE1BQU0sQ0FBQyxNQUFNLGNBQWMsR0FBRyxDQUFDLEtBQWMsRUFBbUIsRUFBRTtJQUNoRSxNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQzFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLEdBQUcsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BELE1BQU0sUUFBUSxHQUFHLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN2QyxPQUFPO1FBQ0wsT0FBTztRQUNQLE9BQU8sRUFBRSxFQUFFLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxJQUFJLEVBQUUsaUJBQWlCLEVBQUU7UUFDL0QsU0FBUztRQUNULEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztLQUNsQyxDQUFDO0FBQ0osQ0FBQyxDQUFDO0FBRUYsTUFBTSxRQUFRLEdBQUcsQ0FBQyxDQUFVLEVBQWdDLEVBQUUsQ0FDNUQsT0FBTyxDQUFDLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRTNELE1BQU0sUUFBUSxHQUFHLENBQUMsQ0FBVSxFQUFzQixFQUFFLENBQ2xELE9BQU8sQ0FBQyxLQUFLLFFBQVEsSUFBSSxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFFeEQ7Ozs7R0FJRztBQUNILE1BQU0sY0FBYyxHQUFHLENBQ3JCLElBQTZCLEVBQ2dDLEVBQUU7SUFDL0QsTUFBTSxPQUFPLEdBQW9CLEVBQUUsQ0FBQztJQUVwQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3pCLE1BQU0sZ0JBQWdCLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztJQUM5RSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDO1FBQ3BDLEtBQUssTUFBTSxLQUFLLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztZQUNyQyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQ3JCLFNBQVM7WUFDWCxDQUFDO1lBQ0QsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUM1QyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ2YsU0FBUztZQUNYLENBQUM7WUFDRCxPQUFPLENBQUMsSUFBSSxDQUFDO2dCQUNYLFNBQVM7Z0JBQ1QsWUFBWSxFQUFFLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUM7YUFDckQsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztBQUMzRSxDQUFDLENBQUM7QUFFRjs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sa0JBQWtCLEdBQUcsQ0FDekIsR0FBWSxFQUN5QixFQUFFO0lBQ3ZDLElBQUksT0FBTyxHQUFHLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDNUIsTUFBTSxPQUFPLEdBQUcsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQzNCLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNiLE9BQU8sU0FBUyxDQUFDO1FBQ25CLENBQUM7UUFDRCxJQUFJLENBQUM7WUFDSCxNQUFNLE1BQU0sR0FBWSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzVDLE9BQU8sUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztRQUMvQyxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsT0FBTyxTQUFTLENBQUM7UUFDbkIsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDekMsQ0FBQyxDQUFDO0FBRUY7Ozs7O0dBS0c7QUFDSCxNQUFNLGVBQWUsR0FBRyxDQUN0QixJQUE2QixFQUNBLEVBQUU7SUFDL0IsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDO0lBQ3JDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUNwQixPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBQ0QsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQztJQUNqQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDbkIsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUNELE1BQU0sUUFBUSxHQUFvQjtRQUNoQyxVQUFVLEVBQUUsUUFBUSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUM7UUFDcEMsWUFBWSxFQUFFLFFBQVEsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDO1FBQ3hDLFFBQVEsRUFBRSxRQUFRLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQztRQUNoQyxLQUFLLEVBQUUsUUFBUSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUM7S0FDM0IsQ0FBQztJQUNGLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsS0FBSyxTQUFTLENBQUM7UUFDekQsQ0FBQyxDQUFDLFFBQVE7UUFDVixDQUFDLENBQUMsU0FBUyxDQUFDO0FBQ2hCLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgREVGQVVMVF9QVVNIX0JPRFksIERFRkFVTFRfUFVTSF9USVRMRSB9IGZyb20gJy4uLy4uL2NvbnN0YW50cy5qcyc7XG5pbXBvcnQge1xuICBDYW1wYWlnbkNvbnRleHQsXG4gIFBhcnNlZFB1c2hFdmVudCxcbiAgUHJvZmlsZVRhcmdldCxcbiAgUHVzaEV2ZW50UGFyc2VQYXRoLFxufSBmcm9tICcuL3R5cGVzLmpzJztcblxuLyoqXG4gKiBQYXJzZSBhIHJhdyBDb25uZWN0IEpvdXJuZXkgQ3VzdG9tLWFjdGlvbiBldmVudCBpbnRvIGEgZmxhdCBsaXN0IG9mIHByb2ZpbGVcbiAqIHRhcmdldHMgcGx1cyB0aGUgbWVzc2FnZSB0byBkZWxpdmVyLlxuICpcbiAqIENBTk9OSUNBTCBzaGFwZSDigJQgdGhlIEFtYXpvbiBDb25uZWN0IE91dGJvdW5kIENhbXBhaWducyB2MiBqb3VybmV5XG4gKiBpbnZvY2F0aW9uLCBjb25maXJtZWQgdmVyYmF0aW0gZnJvbSBhIGxpdmUgam91cm5leSBydW4gKHNlZVxuICogYGZpeHR1cmVzL3JlYWxfam91cm5leV9ldmVudC50c2AgZm9yIHRoZSBzb3VyY2UtbG9nIHJlZmVyZW5jZSkuIFRoaXMgaXMgdGhlXG4gKiBPTkxZIHNoYXBlIENvbm5lY3Qgc2VuZHMsIGFuZCB0aGUgc2luZ2xlIHByaW1hcnkgcGFyc2UgcGF0aDpcbiAqXG4gKiAgIHtcbiAqICAgICBJbnZvY2F0aW9uTWV0YWRhdGE6IHsgQ2FtcGFpZ25Db250ZXh0OiB7IENhbXBhaWduSWQsIFJ1bklkLCBBY3Rpb25JZCwgQ2FtcGFpZ25OYW1lIH0gfSxcbiAqICAgICBJdGVtczogeyBDdXN0b21lclByb2ZpbGVzOiBbIHsgUHJvZmlsZUlkLCBDdXN0b21lckRhdGEsIC4uLiB9LCAuLi4gXSB9XG4gKiAgIH1cbiAqXG4gKiBTaGFwZSBzcGVjaWZpY3MgKGFsbCBQYXNjYWxDYXNlIG9uIHRoZSBlbnZlbG9wZSk6XG4gKiAgIC0gYEl0ZW1zYCBpcyBhbiBPQkpFQ1QgYHsgQ3VzdG9tZXJQcm9maWxlczogWy4uLl0gfWA7XG4gKiAgIC0gZWFjaCBlbnRyeSBjYXJyaWVzIGEgdG9wLWxldmVsIGBQcm9maWxlSWRgICh1c2VkIGZvciBkZXZpY2UgbG9va3VwKTtcbiAqICAgLSBlYWNoIGVudHJ5J3MgYEN1c3RvbWVyRGF0YWAgaXMgYSBTRVJJQUxJWkVEIEpTT04gU1RSSU5HIHdpdGggY2FtZWxDYXNlXG4gKiAgICAga2V5cyAoYHByb2ZpbGVJZGAsIGBmaXJzdE5hbWVgLCBgbWVzc2FnZVRpdGxlYCwgYG1lc3NhZ2VCb2R5YCxcbiAqICAgICBgYXR0cmlidXRlcy4qYCkgdGhhdCBpcyBgSlNPTi5wYXJzZWBkLlxuICpcbiAqIE1pbmltYWwsIGRvY3VtZW50ZWQgZGVmZW5zaXZlIGhhbmRsaW5nIG9ubHk6IGEgYEN1c3RvbWVyRGF0YWAgYWxyZWFkeSBnaXZlbiBhc1xuICogYSBwYXJzZWQgb2JqZWN0IGlzIHRvbGVyYXRlZCAoc2VlIHtAbGluayBjb2VyY2VDdXN0b21lckRhdGF9KTsgbWlzc2luZyAvXG4gKiBtYWxmb3JtZWQgZmllbGRzIGFyZSBza2lwcGVkIHJhdGhlciB0aGFuIGFib3J0aW5nIHRoZSBiYXRjaC4gVGhlIHJlYWwgam91cm5leVxuICogY2FycmllcyBOTyBtZXNzYWdlIGNvcHksIHNvIHtAbGluayBQYXJzZWRQdXNoRXZlbnQubWVzc2FnZX0gaXMgYWx3YXlzIHRoZSBzYWZlXG4gKiB7QGxpbmsgREVGQVVMVF9QVVNIX1RJVExFfSAvIHtAbGluayBERUZBVUxUX1BVU0hfQk9EWX07IHBlcnNvbmFsaXplZCBjb3B5IGNvbWVzXG4gKiBmcm9tIHRoZSBRIENvbm5lY3QgUFVTSCB0ZW1wbGF0ZSByZW5kZXJlZCBwZXIgcHJvZmlsZSBkb3duc3RyZWFtLCBhbmQgdGhpc1xuICogZGVmYXVsdCBpcyB1c2VkIG9ubHkgYXMgdGhlIHBlci1jaGFubmVsIGZhbGxiYWNrLlxuICovXG5leHBvcnQgY29uc3QgcGFyc2VQdXNoRXZlbnQgPSAoZXZlbnQ6IHVua25vd24pOiBQYXJzZWRQdXNoRXZlbnQgPT4ge1xuICBjb25zdCByb290ID0gaXNSZWNvcmQoZXZlbnQpID8gZXZlbnQgOiB7fTtcbiAgY29uc3QgeyB0YXJnZXRzLCBwYXJzZVBhdGggfSA9IGV4dHJhY3RUYXJnZXRzKHJvb3QpO1xuICBjb25zdCBjYW1wYWlnbiA9IGV4dHJhY3RDYW1wYWlnbihyb290KTtcbiAgcmV0dXJuIHtcbiAgICB0YXJnZXRzLFxuICAgIG1lc3NhZ2U6IHsgdGl0bGU6IERFRkFVTFRfUFVTSF9USVRMRSwgYm9keTogREVGQVVMVF9QVVNIX0JPRFkgfSxcbiAgICBwYXJzZVBhdGgsXG4gICAgLi4uKGNhbXBhaWduID8geyBjYW1wYWlnbiB9IDoge30pLFxuICB9O1xufTtcblxuY29uc3QgaXNSZWNvcmQgPSAodjogdW5rbm93bik6IHYgaXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPT5cbiAgdHlwZW9mIHYgPT09ICdvYmplY3QnICYmIHYgIT09IG51bGwgJiYgIUFycmF5LmlzQXJyYXkodik7XG5cbmNvbnN0IGFzU3RyaW5nID0gKHY6IHVua25vd24pOiBzdHJpbmcgfCB1bmRlZmluZWQgPT5cbiAgdHlwZW9mIHYgPT09ICdzdHJpbmcnICYmIHYubGVuZ3RoID4gMCA/IHYgOiB1bmRlZmluZWQ7XG5cbi8qKlxuICogRXh0cmFjdCBwcm9maWxlIHRhcmdldHMgZnJvbSB0aGUgY2Fub25pY2FsIGBJdGVtcy5DdXN0b21lclByb2ZpbGVzW11gIGFycmF5LlxuICogRWFjaCBlbnRyeSBjb250cmlidXRlcyBpdHMgYFByb2ZpbGVJZGAgKyBwYXJzZWQgYEN1c3RvbWVyRGF0YWA7IGVudHJpZXNcbiAqIHdpdGhvdXQgYSB1c2FibGUgYFByb2ZpbGVJZGAgYXJlIHNraXBwZWQuXG4gKi9cbmNvbnN0IGV4dHJhY3RUYXJnZXRzID0gKFxuICByb290OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbik6IHsgdGFyZ2V0czogUHJvZmlsZVRhcmdldFtdOyBwYXJzZVBhdGg6IFB1c2hFdmVudFBhcnNlUGF0aCB9ID0+IHtcbiAgY29uc3QgdGFyZ2V0czogUHJvZmlsZVRhcmdldFtdID0gW107XG5cbiAgY29uc3QgaXRlbXMgPSByb290Lkl0ZW1zO1xuICBjb25zdCBjdXN0b21lclByb2ZpbGVzID0gaXNSZWNvcmQoaXRlbXMpID8gaXRlbXMuQ3VzdG9tZXJQcm9maWxlcyA6IHVuZGVmaW5lZDtcbiAgaWYgKEFycmF5LmlzQXJyYXkoY3VzdG9tZXJQcm9maWxlcykpIHtcbiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGN1c3RvbWVyUHJvZmlsZXMpIHtcbiAgICAgIGlmICghaXNSZWNvcmQoZW50cnkpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgcHJvZmlsZUlkID0gYXNTdHJpbmcoZW50cnkuUHJvZmlsZUlkKTtcbiAgICAgIGlmICghcHJvZmlsZUlkKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgdGFyZ2V0cy5wdXNoKHtcbiAgICAgICAgcHJvZmlsZUlkLFxuICAgICAgICBjdXN0b21lckRhdGE6IGNvZXJjZUN1c3RvbWVyRGF0YShlbnRyeS5DdXN0b21lckRhdGEpLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHsgdGFyZ2V0cywgcGFyc2VQYXRoOiB0YXJnZXRzLmxlbmd0aCA+IDAgPyAnY2Fub25pY2FsJyA6ICdub25lJyB9O1xufTtcblxuLyoqXG4gKiBDb2VyY2UgYSByYXcgYEN1c3RvbWVyRGF0YWAgdmFsdWUgaW50byBhIHByb3BlcnR5IGJhZy5cbiAqXG4gKiBUaGUgcmVhbCBDb25uZWN0IGpvdXJuZXkgZGVsaXZlcnMgYEN1c3RvbWVyRGF0YWAgYXMgYSBTRVJJQUxJWkVEIEpTT04gU1RSSU5HXG4gKiAoY2FtZWxDYXNlIGtleXMpLCBzbyBhIHN0cmluZyBpcyBgSlNPTi5wYXJzZWBkLiBNaW5pbWFsIGRlZmVuc2l2ZSB0b2xlcmFuY2U6XG4gKiBhIHZhbHVlIGFscmVhZHkgZ2l2ZW4gYXMgYSBwbGFpbiBvYmplY3QgaXMgdXNlZCBhcy1pcy4gQW55dGhpbmcgZWxzZSDigJQgb3IgYVxuICogc3RyaW5nIHRoYXQgaXNuJ3QgdmFsaWQgSlNPTiwgb3IgSlNPTiB0aGF0IGlzbid0IGFuIG9iamVjdCDigJQgeWllbGRzXG4gKiBgdW5kZWZpbmVkYCBzbyBhIG1hbGZvcm1lZCBlbnRyeSBuZXZlciBhYm9ydHMgdGhlIGJhdGNoLlxuICovXG5jb25zdCBjb2VyY2VDdXN0b21lckRhdGEgPSAoXG4gIHJhdzogdW5rbm93bixcbik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkID0+IHtcbiAgaWYgKHR5cGVvZiByYXcgPT09ICdzdHJpbmcnKSB7XG4gICAgY29uc3QgdHJpbW1lZCA9IHJhdy50cmltKCk7XG4gICAgaWYgKCF0cmltbWVkKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgY29uc3QgcGFyc2VkOiB1bmtub3duID0gSlNPTi5wYXJzZSh0cmltbWVkKTtcbiAgICAgIHJldHVybiBpc1JlY29yZChwYXJzZWQpID8gcGFyc2VkIDogdW5kZWZpbmVkO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGlzUmVjb3JkKHJhdykgPyByYXcgOiB1bmRlZmluZWQ7XG59O1xuXG4vKipcbiAqIEV4dHJhY3QgdGhlIE91dGJvdW5kIENhbXBhaWducyB2MiBqb3VybmV5IGNvbnRleHQgZnJvbVxuICogYEludm9jYXRpb25NZXRhZGF0YS5DYW1wYWlnbkNvbnRleHRgLCB3aGVuIHByZXNlbnQuIFJldHVybnMgYHVuZGVmaW5lZGAgd2hlblxuICogdGhlIGVudmVsb3BlIGNhcnJpZXMgbm8gY2FtcGFpZ24gbWV0YWRhdGEgKGUuZy4gZGlyZWN0LWludm9rZSB0ZXN0IHBheWxvYWRzKVxuICogb3Igd2hlbiBub25lIG9mIHRoZSBleHBlY3RlZCBmaWVsZHMgcmVzb2x2ZS5cbiAqL1xuY29uc3QgZXh0cmFjdENhbXBhaWduID0gKFxuICByb290OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbik6IENhbXBhaWduQ29udGV4dCB8IHVuZGVmaW5lZCA9PiB7XG4gIGNvbnN0IG1ldGEgPSByb290Lkludm9jYXRpb25NZXRhZGF0YTtcbiAgaWYgKCFpc1JlY29yZChtZXRhKSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgY29uc3QgY3R4ID0gbWV0YS5DYW1wYWlnbkNvbnRleHQ7XG4gIGlmICghaXNSZWNvcmQoY3R4KSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgY29uc3QgY2FtcGFpZ246IENhbXBhaWduQ29udGV4dCA9IHtcbiAgICBjYW1wYWlnbklkOiBhc1N0cmluZyhjdHguQ2FtcGFpZ25JZCksXG4gICAgY2FtcGFpZ25OYW1lOiBhc1N0cmluZyhjdHguQ2FtcGFpZ25OYW1lKSxcbiAgICBhY3Rpb25JZDogYXNTdHJpbmcoY3R4LkFjdGlvbklkKSxcbiAgICBydW5JZDogYXNTdHJpbmcoY3R4LlJ1bklkKSxcbiAgfTtcbiAgcmV0dXJuIE9iamVjdC52YWx1ZXMoY2FtcGFpZ24pLnNvbWUoKHYpID0+IHYgIT09IHVuZGVmaW5lZClcbiAgICA/IGNhbXBhaWduXG4gICAgOiB1bmRlZmluZWQ7XG59O1xuIl19
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VERBATIM real Amazon Connect Outbound Campaigns v2 journey invocation event.
|
|
3
|
+
*
|
|
4
|
+
* Captured byte-for-byte from the `[push] rawEvent` CloudWatch log line of a
|
|
5
|
+
* live journey run:
|
|
6
|
+
* - log group: /aws/lambda/amplify-connectidentifyus-notificationsPushHandler-N0RSPJyrq5gp
|
|
7
|
+
* - RequestId: 78da5698-8f31-4662-bf7b-d69502347fde
|
|
8
|
+
* - CampaignName: journey-2 (CampaignId a87c62f3-e312-4b6d-9a0a-5b0cc8ef852b)
|
|
9
|
+
*
|
|
10
|
+
* This is the AUTHORITATIVE fixture for the real journey envelope: `Items` is an
|
|
11
|
+
* OBJECT { CustomerProfiles: [...] }, each entry's `CustomerData` is a
|
|
12
|
+
* SERIALIZED JSON STRING with camelCase keys, `ProfileId` is top-level
|
|
13
|
+
* PascalCase, and there is an `IdempotencyToken`. Do not hand-edit — re-capture
|
|
14
|
+
* from CloudWatch if the real shape changes.
|
|
15
|
+
*/
|
|
16
|
+
export declare const REAL_JOURNEY_EVENT_RAW = "{\"InvocationMetadata\":{\"CampaignContext\":{\"CampaignId\":\"a87c62f3-e312-4b6d-9a0a-5b0cc8ef852b\",\"RunId\":\"a87c62f3-e312-4b6d-9a0a-5b0cc8ef852b#2026-07-03T10-04-00Z\",\"ActionId\":\"Push Notification\",\"CampaignName\":\"journey-2\"}},\"Items\":{\"CustomerProfiles\":[{\"ProfileId\":\"b1a19259aff1472fa4e4332b4f2ba441\",\"CustomerData\":\"{\\\"profileId\\\":\\\"b1a19259aff1472fa4e4332b4f2ba441\\\",\\\"attributes\\\":{\\\"cognitoSub\\\":\\\"push-e2e-sub-1783067414142\\\",\\\"deviceId\\\":\\\"dev-apns-1783067414142\\\"}}\",\"IdempotencyToken\":\"3709179dfad1fa981d2388a8c0fef99df26dd45b3c1725d097564239337c45e4\"},{\"ProfileId\":\"eb155c66aae14a10b775437c40a4e44d\",\"CustomerData\":\"{\\\"profileId\\\":\\\"eb155c66aae14a10b775437c40a4e44d\\\",\\\"firstName\\\":\\\"Manual\\\",\\\"lastName\\\":\\\"Tester\\\",\\\"emailAddress\\\":\\\"manual-test@example.com\\\",\\\"attributes\\\":{\\\"appUserId\\\":\\\"manual-test-user\\\",\\\"appVersion\\\":\\\"1.0.0\\\",\\\"cognitoSub\\\":\\\"74c824b8-9031-70bc-9e6c-e64660a34d32\\\",\\\"cognitoUserKey\\\":\\\"74c824b8-9031-70bc-9e6c-e64660a34d32\\\",\\\"deviceId\\\":\\\"manual-test-gcm-device\\\",\\\"hasAPNS\\\":\\\"true\\\",\\\"hasGCM\\\":\\\"true\\\",\\\"plan\\\":\\\"premium\\\",\\\"platform\\\":\\\"android\\\"}}\",\"IdempotencyToken\":\"2ec09dbd1477f39e1feeed32c9f6dc882a152d98d0096d2e36b5a9c900f05f00\"},{\"ProfileId\":\"980662c93bdd4527aeecbacc1aae296a\",\"CustomerData\":\"{\\\"profileId\\\":\\\"980662c93bdd4527aeecbacc1aae296a\\\",\\\"firstName\\\":\\\"Ada\\\",\\\"lastName\\\":\\\"Lovelace\\\",\\\"emailAddress\\\":\\\"ada@example.com\\\",\\\"address\\\":{\\\"city\\\":\\\"Seattle\\\",\\\"province\\\":\\\"WA\\\",\\\"country\\\":\\\"US\\\",\\\"postalCode\\\":\\\"98101\\\"},\\\"attributes\\\":{\\\"appUserId\\\":\\\"app-user-1\\\",\\\"appVersion\\\":\\\"1.2.3\\\",\\\"cognitoSub\\\":\\\"5498b4a8-30e1-7034-f334-15520531a361\\\",\\\"cognitoUserKey\\\":\\\"5498b4a8-30e1-7034-f334-15520531a361\\\",\\\"deviceId\\\":\\\"verify-device-0001\\\",\\\"hasAPNS\\\":\\\"true\\\",\\\"locale\\\":\\\"en_US\\\",\\\"plan\\\":\\\"premium\\\",\\\"platform\\\":\\\"ios\\\"}}\",\"IdempotencyToken\":\"64396f1aca4c1db9d2fb729102140a2e4250e4503659f1d047b9fca9987a7f38\"},{\"ProfileId\":\"594a41c0a6d84f46a56df716a3f62e7d\",\"CustomerData\":\"{\\\"profileId\\\":\\\"594a41c0a6d84f46a56df716a3f62e7d\\\",\\\"firstName\\\":\\\"Grace\\\",\\\"lastName\\\":\\\"Hopper\\\",\\\"emailAddress\\\":\\\"grace@example.com\\\",\\\"attributes\\\":{\\\"appUserId\\\":\\\"app-user-2\\\",\\\"cognitoSub\\\":\\\"b4780458-0061-70e3-a5a4-3b76098dc0bb\\\",\\\"cognitoUserKey\\\":\\\"b4780458-0061-70e3-a5a4-3b76098dc0bb\\\",\\\"deviceId\\\":\\\"verify-device-u2\\\",\\\"hasGCM\\\":\\\"true\\\",\\\"plan\\\":\\\"basic\\\"}}\",\"IdempotencyToken\":\"b7c8133e2ce51ed8aebb74ec65237f39090864df601fbac864fc8211e0564829\"}]}}";
|
|
17
|
+
/** The verbatim real journey event, parsed into a JS object. */
|
|
18
|
+
export declare const REAL_JOURNEY_EVENT: unknown;
|
|
19
|
+
//# sourceMappingURL=real_journey_event.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/* eslint-disable spellcheck/spell-checker -- verbatim captured Connect journey event (UUIDs, hashes, PII-shaped test data) */
|
|
2
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
/**
|
|
5
|
+
* VERBATIM real Amazon Connect Outbound Campaigns v2 journey invocation event.
|
|
6
|
+
*
|
|
7
|
+
* Captured byte-for-byte from the `[push] rawEvent` CloudWatch log line of a
|
|
8
|
+
* live journey run:
|
|
9
|
+
* - log group: /aws/lambda/amplify-connectidentifyus-notificationsPushHandler-N0RSPJyrq5gp
|
|
10
|
+
* - RequestId: 78da5698-8f31-4662-bf7b-d69502347fde
|
|
11
|
+
* - CampaignName: journey-2 (CampaignId a87c62f3-e312-4b6d-9a0a-5b0cc8ef852b)
|
|
12
|
+
*
|
|
13
|
+
* This is the AUTHORITATIVE fixture for the real journey envelope: `Items` is an
|
|
14
|
+
* OBJECT { CustomerProfiles: [...] }, each entry's `CustomerData` is a
|
|
15
|
+
* SERIALIZED JSON STRING with camelCase keys, `ProfileId` is top-level
|
|
16
|
+
* PascalCase, and there is an `IdempotencyToken`. Do not hand-edit — re-capture
|
|
17
|
+
* from CloudWatch if the real shape changes.
|
|
18
|
+
*/
|
|
19
|
+
export const REAL_JOURNEY_EVENT_RAW = '{"InvocationMetadata":{"CampaignContext":{"CampaignId":"a87c62f3-e312-4b6d-9a0a-5b0cc8ef852b","RunId":"a87c62f3-e312-4b6d-9a0a-5b0cc8ef852b#2026-07-03T10-04-00Z","ActionId":"Push Notification","CampaignName":"journey-2"}},"Items":{"CustomerProfiles":[{"ProfileId":"b1a19259aff1472fa4e4332b4f2ba441","CustomerData":"{\\"profileId\\":\\"b1a19259aff1472fa4e4332b4f2ba441\\",\\"attributes\\":{\\"cognitoSub\\":\\"push-e2e-sub-1783067414142\\",\\"deviceId\\":\\"dev-apns-1783067414142\\"}}","IdempotencyToken":"3709179dfad1fa981d2388a8c0fef99df26dd45b3c1725d097564239337c45e4"},{"ProfileId":"eb155c66aae14a10b775437c40a4e44d","CustomerData":"{\\"profileId\\":\\"eb155c66aae14a10b775437c40a4e44d\\",\\"firstName\\":\\"Manual\\",\\"lastName\\":\\"Tester\\",\\"emailAddress\\":\\"manual-test@example.com\\",\\"attributes\\":{\\"appUserId\\":\\"manual-test-user\\",\\"appVersion\\":\\"1.0.0\\",\\"cognitoSub\\":\\"74c824b8-9031-70bc-9e6c-e64660a34d32\\",\\"cognitoUserKey\\":\\"74c824b8-9031-70bc-9e6c-e64660a34d32\\",\\"deviceId\\":\\"manual-test-gcm-device\\",\\"hasAPNS\\":\\"true\\",\\"hasGCM\\":\\"true\\",\\"plan\\":\\"premium\\",\\"platform\\":\\"android\\"}}","IdempotencyToken":"2ec09dbd1477f39e1feeed32c9f6dc882a152d98d0096d2e36b5a9c900f05f00"},{"ProfileId":"980662c93bdd4527aeecbacc1aae296a","CustomerData":"{\\"profileId\\":\\"980662c93bdd4527aeecbacc1aae296a\\",\\"firstName\\":\\"Ada\\",\\"lastName\\":\\"Lovelace\\",\\"emailAddress\\":\\"ada@example.com\\",\\"address\\":{\\"city\\":\\"Seattle\\",\\"province\\":\\"WA\\",\\"country\\":\\"US\\",\\"postalCode\\":\\"98101\\"},\\"attributes\\":{\\"appUserId\\":\\"app-user-1\\",\\"appVersion\\":\\"1.2.3\\",\\"cognitoSub\\":\\"5498b4a8-30e1-7034-f334-15520531a361\\",\\"cognitoUserKey\\":\\"5498b4a8-30e1-7034-f334-15520531a361\\",\\"deviceId\\":\\"verify-device-0001\\",\\"hasAPNS\\":\\"true\\",\\"locale\\":\\"en_US\\",\\"plan\\":\\"premium\\",\\"platform\\":\\"ios\\"}}","IdempotencyToken":"64396f1aca4c1db9d2fb729102140a2e4250e4503659f1d047b9fca9987a7f38"},{"ProfileId":"594a41c0a6d84f46a56df716a3f62e7d","CustomerData":"{\\"profileId\\":\\"594a41c0a6d84f46a56df716a3f62e7d\\",\\"firstName\\":\\"Grace\\",\\"lastName\\":\\"Hopper\\",\\"emailAddress\\":\\"grace@example.com\\",\\"attributes\\":{\\"appUserId\\":\\"app-user-2\\",\\"cognitoSub\\":\\"b4780458-0061-70e3-a5a4-3b76098dc0bb\\",\\"cognitoUserKey\\":\\"b4780458-0061-70e3-a5a4-3b76098dc0bb\\",\\"deviceId\\":\\"verify-device-u2\\",\\"hasGCM\\":\\"true\\",\\"plan\\":\\"basic\\"}}","IdempotencyToken":"b7c8133e2ce51ed8aebb74ec65237f39090864df601fbac864fc8211e0564829"}]}}';
|
|
20
|
+
/** The verbatim real journey event, parsed into a JS object. */
|
|
21
|
+
export const REAL_JOURNEY_EVENT = JSON.parse(REAL_JOURNEY_EVENT_RAW);
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVhbF9qb3VybmV5X2V2ZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xhbWJkYS9wdXNoL2ZpeHR1cmVzL3JlYWxfam91cm5leV9ldmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSw4SEFBOEg7QUFDOUgscUVBQXFFO0FBQ3JFLHNDQUFzQztBQUV0Qzs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE1BQU0sQ0FBQyxNQUFNLHNCQUFzQixHQUNqQywyaEZBQTJoRixDQUFDO0FBRTloRixnRUFBZ0U7QUFDaEUsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQVksSUFBSSxDQUFDLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgc3BlbGxjaGVjay9zcGVsbC1jaGVja2VyIC0tIHZlcmJhdGltIGNhcHR1cmVkIENvbm5lY3Qgam91cm5leSBldmVudCAoVVVJRHMsIGhhc2hlcywgUElJLXNoYXBlZCB0ZXN0IGRhdGEpICovXG4vLyBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogVkVSQkFUSU0gcmVhbCBBbWF6b24gQ29ubmVjdCBPdXRib3VuZCBDYW1wYWlnbnMgdjIgam91cm5leSBpbnZvY2F0aW9uIGV2ZW50LlxuICpcbiAqIENhcHR1cmVkIGJ5dGUtZm9yLWJ5dGUgZnJvbSB0aGUgYFtwdXNoXSByYXdFdmVudGAgQ2xvdWRXYXRjaCBsb2cgbGluZSBvZiBhXG4gKiBsaXZlIGpvdXJuZXkgcnVuOlxuICogICAtIGxvZyBncm91cDogL2F3cy9sYW1iZGEvYW1wbGlmeS1jb25uZWN0aWRlbnRpZnl1cy1ub3RpZmljYXRpb25zUHVzaEhhbmRsZXItTjBSU1BKeXJxNWdwXG4gKiAgIC0gUmVxdWVzdElkOiAgNzhkYTU2OTgtOGYzMS00NjYyLWJmN2ItZDY5NTAyMzQ3ZmRlXG4gKiAgIC0gQ2FtcGFpZ25OYW1lOiBqb3VybmV5LTIgIChDYW1wYWlnbklkIGE4N2M2MmYzLWUzMTItNGI2ZC05YTBhLTViMGNjOGVmODUyYilcbiAqXG4gKiBUaGlzIGlzIHRoZSBBVVRIT1JJVEFUSVZFIGZpeHR1cmUgZm9yIHRoZSByZWFsIGpvdXJuZXkgZW52ZWxvcGU6IGBJdGVtc2AgaXMgYW5cbiAqIE9CSkVDVCB7IEN1c3RvbWVyUHJvZmlsZXM6IFsuLi5dIH0sIGVhY2ggZW50cnkncyBgQ3VzdG9tZXJEYXRhYCBpcyBhXG4gKiBTRVJJQUxJWkVEIEpTT04gU1RSSU5HIHdpdGggY2FtZWxDYXNlIGtleXMsIGBQcm9maWxlSWRgIGlzIHRvcC1sZXZlbFxuICogUGFzY2FsQ2FzZSwgYW5kIHRoZXJlIGlzIGFuIGBJZGVtcG90ZW5jeVRva2VuYC4gRG8gbm90IGhhbmQtZWRpdCDigJQgcmUtY2FwdHVyZVxuICogZnJvbSBDbG91ZFdhdGNoIGlmIHRoZSByZWFsIHNoYXBlIGNoYW5nZXMuXG4gKi9cbmV4cG9ydCBjb25zdCBSRUFMX0pPVVJORVlfRVZFTlRfUkFXID1cbiAgJ3tcIkludm9jYXRpb25NZXRhZGF0YVwiOntcIkNhbXBhaWduQ29udGV4dFwiOntcIkNhbXBhaWduSWRcIjpcImE4N2M2MmYzLWUzMTItNGI2ZC05YTBhLTViMGNjOGVmODUyYlwiLFwiUnVuSWRcIjpcImE4N2M2MmYzLWUzMTItNGI2ZC05YTBhLTViMGNjOGVmODUyYiMyMDI2LTA3LTAzVDEwLTA0LTAwWlwiLFwiQWN0aW9uSWRcIjpcIlB1c2ggTm90aWZpY2F0aW9uXCIsXCJDYW1wYWlnbk5hbWVcIjpcImpvdXJuZXktMlwifX0sXCJJdGVtc1wiOntcIkN1c3RvbWVyUHJvZmlsZXNcIjpbe1wiUHJvZmlsZUlkXCI6XCJiMWExOTI1OWFmZjE0NzJmYTRlNDMzMmI0ZjJiYTQ0MVwiLFwiQ3VzdG9tZXJEYXRhXCI6XCJ7XFxcXFwicHJvZmlsZUlkXFxcXFwiOlxcXFxcImIxYTE5MjU5YWZmMTQ3MmZhNGU0MzMyYjRmMmJhNDQxXFxcXFwiLFxcXFxcImF0dHJpYnV0ZXNcXFxcXCI6e1xcXFxcImNvZ25pdG9TdWJcXFxcXCI6XFxcXFwicHVzaC1lMmUtc3ViLTE3ODMwNjc0MTQxNDJcXFxcXCIsXFxcXFwiZGV2aWNlSWRcXFxcXCI6XFxcXFwiZGV2LWFwbnMtMTc4MzA2NzQxNDE0MlxcXFxcIn19XCIsXCJJZGVtcG90ZW5jeVRva2VuXCI6XCIzNzA5MTc5ZGZhZDFmYTk4MWQyMzg4YThjMGZlZjk5ZGYyNmRkNDViM2MxNzI1ZDA5NzU2NDIzOTMzN2M0NWU0XCJ9LHtcIlByb2ZpbGVJZFwiOlwiZWIxNTVjNjZhYWUxNGExMGI3NzU0MzdjNDBhNGU0NGRcIixcIkN1c3RvbWVyRGF0YVwiOlwie1xcXFxcInByb2ZpbGVJZFxcXFxcIjpcXFxcXCJlYjE1NWM2NmFhZTE0YTEwYjc3NTQzN2M0MGE0ZTQ0ZFxcXFxcIixcXFxcXCJmaXJzdE5hbWVcXFxcXCI6XFxcXFwiTWFudWFsXFxcXFwiLFxcXFxcImxhc3ROYW1lXFxcXFwiOlxcXFxcIlRlc3RlclxcXFxcIixcXFxcXCJlbWFpbEFkZHJlc3NcXFxcXCI6XFxcXFwibWFudWFsLXRlc3RAZXhhbXBsZS5jb21cXFxcXCIsXFxcXFwiYXR0cmlidXRlc1xcXFxcIjp7XFxcXFwiYXBwVXNlcklkXFxcXFwiOlxcXFxcIm1hbnVhbC10ZXN0LXVzZXJcXFxcXCIsXFxcXFwiYXBwVmVyc2lvblxcXFxcIjpcXFxcXCIxLjAuMFxcXFxcIixcXFxcXCJjb2duaXRvU3ViXFxcXFwiOlxcXFxcIjc0YzgyNGI4LTkwMzEtNzBiYy05ZTZjLWU2NDY2MGEzNGQzMlxcXFxcIixcXFxcXCJjb2duaXRvVXNlcktleVxcXFxcIjpcXFxcXCI3NGM4MjRiOC05MDMxLTcwYmMtOWU2Yy1lNjQ2NjBhMzRkMzJcXFxcXCIsXFxcXFwiZGV2aWNlSWRcXFxcXCI6XFxcXFwibWFudWFsLXRlc3QtZ2NtLWRldmljZVxcXFxcIixcXFxcXCJoYXNBUE5TXFxcXFwiOlxcXFxcInRydWVcXFxcXCIsXFxcXFwiaGFzR0NNXFxcXFwiOlxcXFxcInRydWVcXFxcXCIsXFxcXFwicGxhblxcXFxcIjpcXFxcXCJwcmVtaXVtXFxcXFwiLFxcXFxcInBsYXRmb3JtXFxcXFwiOlxcXFxcImFuZHJvaWRcXFxcXCJ9fVwiLFwiSWRlbXBvdGVuY3lUb2tlblwiOlwiMmVjMDlkYmQxNDc3ZjM5ZTFmZWVlZDMyYzlmNmRjODgyYTE1MmQ5OGQwMDk2ZDJlMzZiNWE5YzkwMGYwNWYwMFwifSx7XCJQcm9maWxlSWRcIjpcIjk4MDY2MmM5M2JkZDQ1MjdhZWVjYmFjYzFhYWUyOTZhXCIsXCJDdXN0b21lckRhdGFcIjpcIntcXFxcXCJwcm9maWxlSWRcXFxcXCI6XFxcXFwiOTgwNjYyYzkzYmRkNDUyN2FlZWNiYWNjMWFhZTI5NmFcXFxcXCIsXFxcXFwiZmlyc3ROYW1lXFxcXFwiOlxcXFxcIkFkYVxcXFxcIixcXFxcXCJsYXN0TmFtZVxcXFxcIjpcXFxcXCJMb3ZlbGFjZVxcXFxcIixcXFxcXCJlbWFpbEFkZHJlc3NcXFxcXCI6XFxcXFwiYWRhQGV4YW1wbGUuY29tXFxcXFwiLFxcXFxcImFkZHJlc3NcXFxcXCI6e1xcXFxcImNpdHlcXFxcXCI6XFxcXFwiU2VhdHRsZVxcXFxcIixcXFxcXCJwcm92aW5jZVxcXFxcIjpcXFxcXCJXQVxcXFxcIixcXFxcXCJjb3VudHJ5XFxcXFwiOlxcXFxcIlVTXFxcXFwiLFxcXFxcInBvc3RhbENvZGVcXFxcXCI6XFxcXFwiOTgxMDFcXFxcXCJ9LFxcXFxcImF0dHJpYnV0ZXNcXFxcXCI6e1xcXFxcImFwcFVzZXJJZFxcXFxcIjpcXFxcXCJhcHAtdXNlci0xXFxcXFwiLFxcXFxcImFwcFZlcnNpb25cXFxcXCI6XFxcXFwiMS4yLjNcXFxcXCIsXFxcXFwiY29nbml0b1N1YlxcXFxcIjpcXFxcXCI1NDk4YjRhOC0zMGUxLTcwMzQtZjMzNC0xNTUyMDUzMWEzNjFcXFxcXCIsXFxcXFwiY29nbml0b1VzZXJLZXlcXFxcXCI6XFxcXFwiNTQ5OGI0YTgtMzBlMS03MDM0LWYzMzQtMTU1MjA1MzFhMzYxXFxcXFwiLFxcXFxcImRldmljZUlkXFxcXFwiOlxcXFxcInZlcmlmeS1kZXZpY2UtMDAwMVxcXFxcIixcXFxcXCJoYXNBUE5TXFxcXFwiOlxcXFxcInRydWVcXFxcXCIsXFxcXFwibG9jYWxlXFxcXFwiOlxcXFxcImVuX1VTXFxcXFwiLFxcXFxcInBsYW5cXFxcXCI6XFxcXFwicHJlbWl1bVxcXFxcIixcXFxcXCJwbGF0Zm9ybVxcXFxcIjpcXFxcXCJpb3NcXFxcXCJ9fVwiLFwiSWRlbXBvdGVuY3lUb2tlblwiOlwiNjQzOTZmMWFjYTRjMWRiOWQyZmI3MjkxMDIxNDBhMmU0MjUwZTQ1MDM2NTlmMWQwNDdiOWZjYTk5ODdhN2YzOFwifSx7XCJQcm9maWxlSWRcIjpcIjU5NGE0MWMwYTZkODRmNDZhNTZkZjcxNmEzZjYyZTdkXCIsXCJDdXN0b21lckRhdGFcIjpcIntcXFxcXCJwcm9maWxlSWRcXFxcXCI6XFxcXFwiNTk0YTQxYzBhNmQ4NGY0NmE1NmRmNzE2YTNmNjJlN2RcXFxcXCIsXFxcXFwiZmlyc3ROYW1lXFxcXFwiOlxcXFxcIkdyYWNlXFxcXFwiLFxcXFxcImxhc3ROYW1lXFxcXFwiOlxcXFxcIkhvcHBlclxcXFxcIixcXFxcXCJlbWFpbEFkZHJlc3NcXFxcXCI6XFxcXFwiZ3JhY2VAZXhhbXBsZS5jb21cXFxcXCIsXFxcXFwiYXR0cmlidXRlc1xcXFxcIjp7XFxcXFwiYXBwVXNlcklkXFxcXFwiOlxcXFxcImFwcC11c2VyLTJcXFxcXCIsXFxcXFwiY29nbml0b1N1YlxcXFxcIjpcXFxcXCJiNDc4MDQ1OC0wMDYxLTcwZTMtYTVhNC0zYjc2MDk4ZGMwYmJcXFxcXCIsXFxcXFwiY29nbml0b1VzZXJLZXlcXFxcXCI6XFxcXFwiYjQ3ODA0NTgtMDA2MS03MGUzLWE1YTQtM2I3NjA5OGRjMGJiXFxcXFwiLFxcXFxcImRldmljZUlkXFxcXFwiOlxcXFxcInZlcmlmeS1kZXZpY2UtdTJcXFxcXCIsXFxcXFwiaGFzR0NNXFxcXFwiOlxcXFxcInRydWVcXFxcXCIsXFxcXFwicGxhblxcXFxcIjpcXFxcXCJiYXNpY1xcXFxcIn19XCIsXCJJZGVtcG90ZW5jeVRva2VuXCI6XCJiN2M4MTMzZTJjZTUxZWQ4YWViYjc0ZWM2NTIzN2YzOTA5MDg2NGRmNjAxZmJhYzg2NGZjODIxMWUwNTY0ODI5XCJ9XX19JztcblxuLyoqIFRoZSB2ZXJiYXRpbSByZWFsIGpvdXJuZXkgZXZlbnQsIHBhcnNlZCBpbnRvIGEgSlMgb2JqZWN0LiAqL1xuZXhwb3J0IGNvbnN0IFJFQUxfSk9VUk5FWV9FVkVOVDogdW5rbm93biA9IEpTT04ucGFyc2UoUkVBTF9KT1VSTkVZX0VWRU5UX1JBVyk7XG4iXX0=
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PushDeliveryResponse } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Push-delivery Lambda invoked by an Amazon Connect Journey Custom-action
|
|
4
|
+
* (Invoke Lambda) block. Amazon Connect has no native mobile-push channel, so
|
|
5
|
+
* this Lambda bridges the gap: it resolves each targeted profile's registered
|
|
6
|
+
* devices from Customer Profiles (ListProfileObjects on the AmplifyDevice
|
|
7
|
+
* object type) and delivers the message to each device via AWS End User
|
|
8
|
+
* Messaging (Pinpoint `SendMessages`), mapping the device's channel to a
|
|
9
|
+
* GCM (Android/FCM) or APNS (iOS) payload. Tokens permanently rejected by the
|
|
10
|
+
* push provider are cleaned up by deleting their AmplifyDevice object.
|
|
11
|
+
*
|
|
12
|
+
* Returns a per-profile delivered / failed / cleaned summary.
|
|
13
|
+
*/
|
|
14
|
+
export declare const handler: (event: unknown) => Promise<PushDeliveryResponse>;
|
|
15
|
+
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { CustomerProfilesClient } from '@aws-sdk/client-customer-profiles';
|
|
4
|
+
import { PinpointClient } from '@aws-sdk/client-pinpoint';
|
|
5
|
+
import { ConnectCampaignsV2Client } from '@aws-sdk/client-connectcampaignsv2';
|
|
6
|
+
import { ConnectClient } from '@aws-sdk/client-connect';
|
|
7
|
+
import { QConnectClient } from '@aws-sdk/client-qconnect';
|
|
8
|
+
import { ENV_DOMAIN_NAME, ENV_EUM_APPLICATION_ID } from '../../constants.js';
|
|
9
|
+
import { parsePushEvent } from './event.js';
|
|
10
|
+
import { deliverToTargets } from './delivery.js';
|
|
11
|
+
import { resolvePushTemplateContext, } from './message_template.js';
|
|
12
|
+
/**
|
|
13
|
+
* Module-level clients so warm invocations reuse the connection pool. Region is
|
|
14
|
+
* resolved from the standard AWS_REGION Lambda environment variable.
|
|
15
|
+
*
|
|
16
|
+
* `campaigns` / `connect` / `qconnect` back runtime message-template resolution:
|
|
17
|
+
* discovering the Q in Connect knowledge base from the journey's campaign and
|
|
18
|
+
* rendering the PUSH template whose name matches the Custom-action ActionId.
|
|
19
|
+
*/
|
|
20
|
+
const profiles = new CustomerProfilesClient({});
|
|
21
|
+
const pinpoint = new PinpointClient({});
|
|
22
|
+
const campaigns = new ConnectCampaignsV2Client({});
|
|
23
|
+
const connect = new ConnectClient({});
|
|
24
|
+
const qconnect = new QConnectClient({});
|
|
25
|
+
/**
|
|
26
|
+
* Push-delivery Lambda invoked by an Amazon Connect Journey Custom-action
|
|
27
|
+
* (Invoke Lambda) block. Amazon Connect has no native mobile-push channel, so
|
|
28
|
+
* this Lambda bridges the gap: it resolves each targeted profile's registered
|
|
29
|
+
* devices from Customer Profiles (ListProfileObjects on the AmplifyDevice
|
|
30
|
+
* object type) and delivers the message to each device via AWS End User
|
|
31
|
+
* Messaging (Pinpoint `SendMessages`), mapping the device's channel to a
|
|
32
|
+
* GCM (Android/FCM) or APNS (iOS) payload. Tokens permanently rejected by the
|
|
33
|
+
* push provider are cleaned up by deleting their AmplifyDevice object.
|
|
34
|
+
*
|
|
35
|
+
* Returns a per-profile delivered / failed / cleaned summary.
|
|
36
|
+
*/
|
|
37
|
+
export const handler = async (event) => {
|
|
38
|
+
const domainName = process.env[ENV_DOMAIN_NAME];
|
|
39
|
+
const applicationId = process.env[ENV_EUM_APPLICATION_ID];
|
|
40
|
+
if (!domainName || !applicationId) {
|
|
41
|
+
throw new Error(`Missing required env var(s): ${[
|
|
42
|
+
!domainName ? ENV_DOMAIN_NAME : undefined,
|
|
43
|
+
!applicationId ? ENV_EUM_APPLICATION_ID : undefined,
|
|
44
|
+
]
|
|
45
|
+
.filter(Boolean)
|
|
46
|
+
.join(', ')}`);
|
|
47
|
+
}
|
|
48
|
+
const parsed = parsePushEvent(event);
|
|
49
|
+
// Operational signals only: how the event was parsed, how many profiles it
|
|
50
|
+
// targeted, and the (non-personal) campaign / action identifiers. Profile ids
|
|
51
|
+
// and message copy are deliberately NOT logged.
|
|
52
|
+
console.log('[push] parsed', JSON.stringify({
|
|
53
|
+
parsePath: parsed.parsePath,
|
|
54
|
+
profileCount: parsed.targets.length,
|
|
55
|
+
campaign: parsed.campaign ?? null,
|
|
56
|
+
}));
|
|
57
|
+
if (parsed.targets.length === 0) {
|
|
58
|
+
console.warn('[push] no resolvable profile targets in event');
|
|
59
|
+
return {
|
|
60
|
+
profilesProcessed: 0,
|
|
61
|
+
totalDelivered: 0,
|
|
62
|
+
totalFailed: 0,
|
|
63
|
+
totalCleaned: 0,
|
|
64
|
+
results: [],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
// Resolve the Q in Connect PUSH message template ONCE per invocation (KB
|
|
68
|
+
// discovery + template lookup are per-journey, not per-profile). When the
|
|
69
|
+
// event carries campaign metadata, the template whose name == the
|
|
70
|
+
// Custom-action ActionId is used to render personalized per-platform copy;
|
|
71
|
+
// otherwise (or on any miss/failure) delivery falls back to the safe DEFAULT
|
|
72
|
+
// copy.
|
|
73
|
+
let templateContext;
|
|
74
|
+
if (parsed.campaign) {
|
|
75
|
+
templateContext = await resolvePushTemplateContext({ campaigns, connect, qconnect }, parsed.campaign);
|
|
76
|
+
}
|
|
77
|
+
const summary = await deliverToTargets({ profiles, pinpoint, domainName, applicationId, templateContext }, parsed);
|
|
78
|
+
console.log('[push] summary', JSON.stringify({
|
|
79
|
+
profilesProcessed: summary.profilesProcessed,
|
|
80
|
+
totalDelivered: summary.totalDelivered,
|
|
81
|
+
totalFailed: summary.totalFailed,
|
|
82
|
+
totalCleaned: summary.totalCleaned,
|
|
83
|
+
}));
|
|
84
|
+
return summary;
|
|
85
|
+
};
|
|
86
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYW1iZGEvcHVzaC9oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHFFQUFxRTtBQUNyRSxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDM0UsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzFELE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQzlFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFMUQsT0FBTyxFQUFFLGVBQWUsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDNUMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2pELE9BQU8sRUFFTCwwQkFBMEIsR0FDM0IsTUFBTSx1QkFBdUIsQ0FBQztBQUcvQjs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxRQUFRLEdBQUcsSUFBSSxzQkFBc0IsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUNoRCxNQUFNLFFBQVEsR0FBRyxJQUFJLGNBQWMsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUN4QyxNQUFNLFNBQVMsR0FBRyxJQUFJLHdCQUF3QixDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ25ELE1BQU0sT0FBTyxHQUFHLElBQUksYUFBYSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3RDLE1BQU0sUUFBUSxHQUFHLElBQUksY0FBYyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBRXhDOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sT0FBTyxHQUFHLEtBQUssRUFDMUIsS0FBYyxFQUNpQixFQUFFO0lBQ2pDLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDaEQsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO0lBQzFELElBQUksQ0FBQyxVQUFVLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUNsQyxNQUFNLElBQUksS0FBSyxDQUNiLGdDQUFnQztZQUM5QixDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxTQUFTO1lBQ3pDLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsU0FBUztTQUNwRDthQUNFLE1BQU0sQ0FBQyxPQUFPLENBQUM7YUFDZixJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FDaEIsQ0FBQztJQUNKLENBQUM7SUFFRCxNQUFNLE1BQU0sR0FBRyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDckMsMkVBQTJFO0lBQzNFLDhFQUE4RTtJQUM5RSxnREFBZ0Q7SUFDaEQsT0FBTyxDQUFDLEdBQUcsQ0FDVCxlQUFlLEVBQ2YsSUFBSSxDQUFDLFNBQVMsQ0FBQztRQUNiLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUztRQUMzQixZQUFZLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNO1FBQ25DLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUSxJQUFJLElBQUk7S0FDbEMsQ0FBQyxDQUNILENBQUM7SUFFRixJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ2hDLE9BQU8sQ0FBQyxJQUFJLENBQUMsK0NBQStDLENBQUMsQ0FBQztRQUM5RCxPQUFPO1lBQ0wsaUJBQWlCLEVBQUUsQ0FBQztZQUNwQixjQUFjLEVBQUUsQ0FBQztZQUNqQixXQUFXLEVBQUUsQ0FBQztZQUNkLFlBQVksRUFBRSxDQUFDO1lBQ2YsT0FBTyxFQUFFLEVBQUU7U0FDWixDQUFDO0lBQ0osQ0FBQztJQUVELHlFQUF5RTtJQUN6RSwwRUFBMEU7SUFDMUUsa0VBQWtFO0lBQ2xFLDJFQUEyRTtJQUMzRSw2RUFBNkU7SUFDN0UsUUFBUTtJQUNSLElBQUksZUFBZ0QsQ0FBQztJQUNyRCxJQUFJLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNwQixlQUFlLEdBQUcsTUFBTSwwQkFBMEIsQ0FDaEQsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxFQUNoQyxNQUFNLENBQUMsUUFBUSxDQUNoQixDQUFDO0lBQ0osQ0FBQztJQUVELE1BQU0sT0FBTyxHQUFHLE1BQU0sZ0JBQWdCLENBQ3BDLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsYUFBYSxFQUFFLGVBQWUsRUFBRSxFQUNsRSxNQUFNLENBQ1AsQ0FBQztJQUVGLE9BQU8sQ0FBQyxHQUFHLENBQ1QsZ0JBQWdCLEVBQ2hCLElBQUksQ0FBQyxTQUFTLENBQUM7UUFDYixpQkFBaUIsRUFBRSxPQUFPLENBQUMsaUJBQWlCO1FBQzVDLGNBQWMsRUFBRSxPQUFPLENBQUMsY0FBYztRQUN0QyxXQUFXLEVBQUUsT0FBTyxDQUFDLFdBQVc7UUFDaEMsWUFBWSxFQUFFLE9BQU8sQ0FBQyxZQUFZO0tBQ25DLENBQUMsQ0FDSCxDQUFDO0lBRUYsT0FBTyxPQUFPLENBQUM7QUFDakIsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBDdXN0b21lclByb2ZpbGVzQ2xpZW50IH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWN1c3RvbWVyLXByb2ZpbGVzJztcbmltcG9ydCB7IFBpbnBvaW50Q2xpZW50IH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXBpbnBvaW50JztcbmltcG9ydCB7IENvbm5lY3RDYW1wYWlnbnNWMkNsaWVudCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1jb25uZWN0Y2FtcGFpZ25zdjInO1xuaW1wb3J0IHsgQ29ubmVjdENsaWVudCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1jb25uZWN0JztcbmltcG9ydCB7IFFDb25uZWN0Q2xpZW50IH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXFjb25uZWN0JztcblxuaW1wb3J0IHsgRU5WX0RPTUFJTl9OQU1FLCBFTlZfRVVNX0FQUExJQ0FUSU9OX0lEIH0gZnJvbSAnLi4vLi4vY29uc3RhbnRzLmpzJztcbmltcG9ydCB7IHBhcnNlUHVzaEV2ZW50IH0gZnJvbSAnLi9ldmVudC5qcyc7XG5pbXBvcnQgeyBkZWxpdmVyVG9UYXJnZXRzIH0gZnJvbSAnLi9kZWxpdmVyeS5qcyc7XG5pbXBvcnQge1xuICBQdXNoVGVtcGxhdGVDb250ZXh0LFxuICByZXNvbHZlUHVzaFRlbXBsYXRlQ29udGV4dCxcbn0gZnJvbSAnLi9tZXNzYWdlX3RlbXBsYXRlLmpzJztcbmltcG9ydCB7IFB1c2hEZWxpdmVyeVJlc3BvbnNlIH0gZnJvbSAnLi90eXBlcy5qcyc7XG5cbi8qKlxuICogTW9kdWxlLWxldmVsIGNsaWVudHMgc28gd2FybSBpbnZvY2F0aW9ucyByZXVzZSB0aGUgY29ubmVjdGlvbiBwb29sLiBSZWdpb24gaXNcbiAqIHJlc29sdmVkIGZyb20gdGhlIHN0YW5kYXJkIEFXU19SRUdJT04gTGFtYmRhIGVudmlyb25tZW50IHZhcmlhYmxlLlxuICpcbiAqIGBjYW1wYWlnbnNgIC8gYGNvbm5lY3RgIC8gYHFjb25uZWN0YCBiYWNrIHJ1bnRpbWUgbWVzc2FnZS10ZW1wbGF0ZSByZXNvbHV0aW9uOlxuICogZGlzY292ZXJpbmcgdGhlIFEgaW4gQ29ubmVjdCBrbm93bGVkZ2UgYmFzZSBmcm9tIHRoZSBqb3VybmV5J3MgY2FtcGFpZ24gYW5kXG4gKiByZW5kZXJpbmcgdGhlIFBVU0ggdGVtcGxhdGUgd2hvc2UgbmFtZSBtYXRjaGVzIHRoZSBDdXN0b20tYWN0aW9uIEFjdGlvbklkLlxuICovXG5jb25zdCBwcm9maWxlcyA9IG5ldyBDdXN0b21lclByb2ZpbGVzQ2xpZW50KHt9KTtcbmNvbnN0IHBpbnBvaW50ID0gbmV3IFBpbnBvaW50Q2xpZW50KHt9KTtcbmNvbnN0IGNhbXBhaWducyA9IG5ldyBDb25uZWN0Q2FtcGFpZ25zVjJDbGllbnQoe30pO1xuY29uc3QgY29ubmVjdCA9IG5ldyBDb25uZWN0Q2xpZW50KHt9KTtcbmNvbnN0IHFjb25uZWN0ID0gbmV3IFFDb25uZWN0Q2xpZW50KHt9KTtcblxuLyoqXG4gKiBQdXNoLWRlbGl2ZXJ5IExhbWJkYSBpbnZva2VkIGJ5IGFuIEFtYXpvbiBDb25uZWN0IEpvdXJuZXkgQ3VzdG9tLWFjdGlvblxuICogKEludm9rZSBMYW1iZGEpIGJsb2NrLiBBbWF6b24gQ29ubmVjdCBoYXMgbm8gbmF0aXZlIG1vYmlsZS1wdXNoIGNoYW5uZWwsIHNvXG4gKiB0aGlzIExhbWJkYSBicmlkZ2VzIHRoZSBnYXA6IGl0IHJlc29sdmVzIGVhY2ggdGFyZ2V0ZWQgcHJvZmlsZSdzIHJlZ2lzdGVyZWRcbiAqIGRldmljZXMgZnJvbSBDdXN0b21lciBQcm9maWxlcyAoTGlzdFByb2ZpbGVPYmplY3RzIG9uIHRoZSBBbXBsaWZ5RGV2aWNlXG4gKiBvYmplY3QgdHlwZSkgYW5kIGRlbGl2ZXJzIHRoZSBtZXNzYWdlIHRvIGVhY2ggZGV2aWNlIHZpYSBBV1MgRW5kIFVzZXJcbiAqIE1lc3NhZ2luZyAoUGlucG9pbnQgYFNlbmRNZXNzYWdlc2ApLCBtYXBwaW5nIHRoZSBkZXZpY2UncyBjaGFubmVsIHRvIGFcbiAqIEdDTSAoQW5kcm9pZC9GQ00pIG9yIEFQTlMgKGlPUykgcGF5bG9hZC4gVG9rZW5zIHBlcm1hbmVudGx5IHJlamVjdGVkIGJ5IHRoZVxuICogcHVzaCBwcm92aWRlciBhcmUgY2xlYW5lZCB1cCBieSBkZWxldGluZyB0aGVpciBBbXBsaWZ5RGV2aWNlIG9iamVjdC5cbiAqXG4gKiBSZXR1cm5zIGEgcGVyLXByb2ZpbGUgZGVsaXZlcmVkIC8gZmFpbGVkIC8gY2xlYW5lZCBzdW1tYXJ5LlxuICovXG5leHBvcnQgY29uc3QgaGFuZGxlciA9IGFzeW5jIChcbiAgZXZlbnQ6IHVua25vd24sXG4pOiBQcm9taXNlPFB1c2hEZWxpdmVyeVJlc3BvbnNlPiA9PiB7XG4gIGNvbnN0IGRvbWFpbk5hbWUgPSBwcm9jZXNzLmVudltFTlZfRE9NQUlOX05BTUVdO1xuICBjb25zdCBhcHBsaWNhdGlvbklkID0gcHJvY2Vzcy5lbnZbRU5WX0VVTV9BUFBMSUNBVElPTl9JRF07XG4gIGlmICghZG9tYWluTmFtZSB8fCAhYXBwbGljYXRpb25JZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBNaXNzaW5nIHJlcXVpcmVkIGVudiB2YXIocyk6ICR7W1xuICAgICAgICAhZG9tYWluTmFtZSA/IEVOVl9ET01BSU5fTkFNRSA6IHVuZGVmaW5lZCxcbiAgICAgICAgIWFwcGxpY2F0aW9uSWQgPyBFTlZfRVVNX0FQUExJQ0FUSU9OX0lEIDogdW5kZWZpbmVkLFxuICAgICAgXVxuICAgICAgICAuZmlsdGVyKEJvb2xlYW4pXG4gICAgICAgIC5qb2luKCcsICcpfWAsXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IHBhcnNlZCA9IHBhcnNlUHVzaEV2ZW50KGV2ZW50KTtcbiAgLy8gT3BlcmF0aW9uYWwgc2lnbmFscyBvbmx5OiBob3cgdGhlIGV2ZW50IHdhcyBwYXJzZWQsIGhvdyBtYW55IHByb2ZpbGVzIGl0XG4gIC8vIHRhcmdldGVkLCBhbmQgdGhlIChub24tcGVyc29uYWwpIGNhbXBhaWduIC8gYWN0aW9uIGlkZW50aWZpZXJzLiBQcm9maWxlIGlkc1xuICAvLyBhbmQgbWVzc2FnZSBjb3B5IGFyZSBkZWxpYmVyYXRlbHkgTk9UIGxvZ2dlZC5cbiAgY29uc29sZS5sb2coXG4gICAgJ1twdXNoXSBwYXJzZWQnLFxuICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgIHBhcnNlUGF0aDogcGFyc2VkLnBhcnNlUGF0aCxcbiAgICAgIHByb2ZpbGVDb3VudDogcGFyc2VkLnRhcmdldHMubGVuZ3RoLFxuICAgICAgY2FtcGFpZ246IHBhcnNlZC5jYW1wYWlnbiA/PyBudWxsLFxuICAgIH0pLFxuICApO1xuXG4gIGlmIChwYXJzZWQudGFyZ2V0cy5sZW5ndGggPT09IDApIHtcbiAgICBjb25zb2xlLndhcm4oJ1twdXNoXSBubyByZXNvbHZhYmxlIHByb2ZpbGUgdGFyZ2V0cyBpbiBldmVudCcpO1xuICAgIHJldHVybiB7XG4gICAgICBwcm9maWxlc1Byb2Nlc3NlZDogMCxcbiAgICAgIHRvdGFsRGVsaXZlcmVkOiAwLFxuICAgICAgdG90YWxGYWlsZWQ6IDAsXG4gICAgICB0b3RhbENsZWFuZWQ6IDAsXG4gICAgICByZXN1bHRzOiBbXSxcbiAgICB9O1xuICB9XG5cbiAgLy8gUmVzb2x2ZSB0aGUgUSBpbiBDb25uZWN0IFBVU0ggbWVzc2FnZSB0ZW1wbGF0ZSBPTkNFIHBlciBpbnZvY2F0aW9uIChLQlxuICAvLyBkaXNjb3ZlcnkgKyB0ZW1wbGF0ZSBsb29rdXAgYXJlIHBlci1qb3VybmV5LCBub3QgcGVyLXByb2ZpbGUpLiBXaGVuIHRoZVxuICAvLyBldmVudCBjYXJyaWVzIGNhbXBhaWduIG1ldGFkYXRhLCB0aGUgdGVtcGxhdGUgd2hvc2UgbmFtZSA9PSB0aGVcbiAgLy8gQ3VzdG9tLWFjdGlvbiBBY3Rpb25JZCBpcyB1c2VkIHRvIHJlbmRlciBwZXJzb25hbGl6ZWQgcGVyLXBsYXRmb3JtIGNvcHk7XG4gIC8vIG90aGVyd2lzZSAob3Igb24gYW55IG1pc3MvZmFpbHVyZSkgZGVsaXZlcnkgZmFsbHMgYmFjayB0byB0aGUgc2FmZSBERUZBVUxUXG4gIC8vIGNvcHkuXG4gIGxldCB0ZW1wbGF0ZUNvbnRleHQ6IFB1c2hUZW1wbGF0ZUNvbnRleHQgfCB1bmRlZmluZWQ7XG4gIGlmIChwYXJzZWQuY2FtcGFpZ24pIHtcbiAgICB0ZW1wbGF0ZUNvbnRleHQgPSBhd2FpdCByZXNvbHZlUHVzaFRlbXBsYXRlQ29udGV4dChcbiAgICAgIHsgY2FtcGFpZ25zLCBjb25uZWN0LCBxY29ubmVjdCB9LFxuICAgICAgcGFyc2VkLmNhbXBhaWduLFxuICAgICk7XG4gIH1cblxuICBjb25zdCBzdW1tYXJ5ID0gYXdhaXQgZGVsaXZlclRvVGFyZ2V0cyhcbiAgICB7IHByb2ZpbGVzLCBwaW5wb2ludCwgZG9tYWluTmFtZSwgYXBwbGljYXRpb25JZCwgdGVtcGxhdGVDb250ZXh0IH0sXG4gICAgcGFyc2VkLFxuICApO1xuXG4gIGNvbnNvbGUubG9nKFxuICAgICdbcHVzaF0gc3VtbWFyeScsXG4gICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgcHJvZmlsZXNQcm9jZXNzZWQ6IHN1bW1hcnkucHJvZmlsZXNQcm9jZXNzZWQsXG4gICAgICB0b3RhbERlbGl2ZXJlZDogc3VtbWFyeS50b3RhbERlbGl2ZXJlZCxcbiAgICAgIHRvdGFsRmFpbGVkOiBzdW1tYXJ5LnRvdGFsRmFpbGVkLFxuICAgICAgdG90YWxDbGVhbmVkOiBzdW1tYXJ5LnRvdGFsQ2xlYW5lZCxcbiAgICB9KSxcbiAgKTtcblxuICByZXR1cm4gc3VtbWFyeTtcbn07XG4iXX0=
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { ConnectCampaignsV2Client } from '@aws-sdk/client-connectcampaignsv2';
|
|
2
|
+
import { ConnectClient } from '@aws-sdk/client-connect';
|
|
3
|
+
import { QConnectClient } from '@aws-sdk/client-qconnect';
|
|
4
|
+
import { CampaignContext, ProfileTarget, PushChannelType, PushMessage } from './types.js';
|
|
5
|
+
/** The AWS clients the template resolver needs. */
|
|
6
|
+
export type TemplateClients = {
|
|
7
|
+
campaigns: ConnectCampaignsV2Client;
|
|
8
|
+
connect: ConnectClient;
|
|
9
|
+
qconnect: QConnectClient;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* A resolved Q in Connect PUSH message template for one journey run: the
|
|
13
|
+
* knowledge base + the specific template id to render per profile. Produced by
|
|
14
|
+
* {@link resolvePushTemplateContext} and carried on the delivery deps so
|
|
15
|
+
* {@link renderProfileChannelMessages} can render personalized copy per profile.
|
|
16
|
+
*/
|
|
17
|
+
export type PushTemplateContext = {
|
|
18
|
+
qconnect: QConnectClient;
|
|
19
|
+
/** The discovered Q in Connect knowledge base id. */
|
|
20
|
+
knowledgeBaseId: string;
|
|
21
|
+
/** The PUSH message template id whose name matched the journey ActionId. */
|
|
22
|
+
messageTemplateId: string;
|
|
23
|
+
/** The template name (== the Custom-action block name / ActionId). */
|
|
24
|
+
templateName: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Discover the Q in Connect knowledge base backing a campaign's Connect
|
|
28
|
+
* instance, caching per container:
|
|
29
|
+
*
|
|
30
|
+
* CampaignId -> connectcampaignsv2 DescribeCampaign -> campaign.connectInstanceId
|
|
31
|
+
* -> connect ListIntegrationAssociations(Q_MESSAGE_TEMPLATES)
|
|
32
|
+
* -> IntegrationArn (arn:aws:wisdom:...:knowledge-base/<kbId>) -> kbId
|
|
33
|
+
*
|
|
34
|
+
* Returns `undefined` (never throws) when the instance id or the KB integration
|
|
35
|
+
* cannot be resolved — the caller then falls back to non-templated copy. If
|
|
36
|
+
* DescribeCampaign does not carry `connectInstanceId`, that is logged so the
|
|
37
|
+
* real shape can be inspected.
|
|
38
|
+
*/
|
|
39
|
+
export declare const discoverKnowledgeBaseId: (clients: Pick<TemplateClients, "campaigns" | "connect">, campaignId: string) => Promise<string | undefined>;
|
|
40
|
+
/**
|
|
41
|
+
* Resolve the PUSH message template for a journey run: discover the knowledge
|
|
42
|
+
* base from the campaign, find the PUSH template whose name == the ActionId,
|
|
43
|
+
* and confirm it has an ACTIVE version. Returns `undefined` (never throws) when
|
|
44
|
+
* anything is missing — no campaign metadata, no KB integration, no matching
|
|
45
|
+
* template — so the caller falls back to the non-templated per-profile copy.
|
|
46
|
+
*/
|
|
47
|
+
export declare const resolvePushTemplateContext: (clients: TemplateClients, campaign: CampaignContext) => Promise<PushTemplateContext | undefined>;
|
|
48
|
+
/**
|
|
49
|
+
* Flatten a profile's `CustomerData` into a flat `customAttributes` map for
|
|
50
|
+
* RenderMessageTemplate. Empirically only `{{Attributes.<flatKey>}}` variables
|
|
51
|
+
* interpolate (from `customAttributes`); the `{{Customer.*}}` namespace does not
|
|
52
|
+
* resolve here — so the profile's `firstName` and every `attributes.*` entry are
|
|
53
|
+
* passed as flat custom attributes (templates reference e.g.
|
|
54
|
+
* `{{Attributes.firstName}}`). Nested objects (`address`, `attributes`) are not
|
|
55
|
+
* added directly; `attributes` is merged one level deep. Non-string / empty
|
|
56
|
+
* values are dropped and values are capped at the render attribute-length limit.
|
|
57
|
+
*/
|
|
58
|
+
export declare const buildCustomAttributes: (customerData?: Record<string, unknown>) => Record<string, string>;
|
|
59
|
+
/**
|
|
60
|
+
* Render the resolved PUSH template for ONE profile and map the per-platform
|
|
61
|
+
* copy to push channels:
|
|
62
|
+
* - `push.apns` -> `APNS` (+ `APNS_SANDBOX`)
|
|
63
|
+
* - `push.fcm` -> `GCM`
|
|
64
|
+
*
|
|
65
|
+
* The profile's `CustomerData` is passed as flat `customAttributes` so
|
|
66
|
+
* `{{Attributes.<key>}}` variables personalize. Returns a partial per-channel
|
|
67
|
+
* map (only channels the template defines both a title and body for), or
|
|
68
|
+
* `undefined` (never throws) when there is no push content or the render fails —
|
|
69
|
+
* the caller then falls back to the non-templated copy for that profile.
|
|
70
|
+
*/
|
|
71
|
+
export declare const renderProfileChannelMessages: (ctx: PushTemplateContext, target: ProfileTarget) => Promise<Partial<Record<PushChannelType, PushMessage>> | undefined>;
|
|
72
|
+
//# sourceMappingURL=message_template.d.ts.map
|